summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h2912
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/APValue.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/AST.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h108
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h1623
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h265
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTVector.h397
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Attr.h233
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h370
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h758
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CharUnits.h197
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h2708
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h72
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h1341
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h2315
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h223
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h185
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h151
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h1594
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h1972
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h567
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h192
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h82
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h3821
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h2892
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h859
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h276
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Mangle.h150
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h205
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h289
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ParentMap.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h112
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h206
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h1904
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h169
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h1410
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h125
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h231
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h347
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h166
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h571
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateName.h493
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Type.h4338
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h1629
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def41
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def125
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h53
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h186
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h114
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h610
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h123
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h319
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h786
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h343
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h393
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h307
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h244
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h102
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h59
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h170
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ABI.h126
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attr.td487
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def728
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h154
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def209
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def450
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h159
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h1031
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td89
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td113
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td82
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td114
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td279
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td260
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h212
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td317
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td463
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td3758
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileManager.h214
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h101
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h684
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h273
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Linkage.h68
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h484
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def106
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h342
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h398
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h886
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h130
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h162
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td141
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h553
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def460
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h70
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Version.h63
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Visibility.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td395
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Config/config.h.cmake17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Action.h228
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Arg.h123
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ArgList.h408
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td617
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Compilation.h145
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Driver.h359
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h94
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Job.h123
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/OptParser.td138
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/OptTable.h190
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Option.h322
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td797
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Phases.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Tool.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h198
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.def88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.h96
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Util.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h654
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def53
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h112
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h170
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h86
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h625
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h193
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def113
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def372
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h94
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h185
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h258
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h192
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h147
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h23
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h104
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h168
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def520
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def304
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h94
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h94
-rw-r--r--contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h174
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/Analyzer.h56
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/CallGraph.h146
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/Entity.h148
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h100
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/Handlers.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/Indexer.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/Program.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/STLExtras.h63
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h57
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h67
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h134
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h67
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h274
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Lexer.h466
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h191
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h256
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h130
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h273
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h106
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h140
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Pragma.h126
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h358
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h1053
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h174
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Token.h294
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h154
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/Parser.h1738
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h107
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h231
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h226
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Rewriters.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h79
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h320
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h79
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h854
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h1558
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h189
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Designator.h218
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h59
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h198
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h817
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Lookup.h671
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Overload.h672
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Ownership.h465
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h196
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Scope.h322
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h139
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h5172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Template.h423
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h134
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h994
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h1292
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTSerializationListener.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h609
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td38
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h486
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h500
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h109
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h93
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h220
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h201
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h59
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h324
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def48
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h103
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h546
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h106
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h469
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h550
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h793
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h165
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h1092
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h210
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h258
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h544
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h307
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h116
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h61
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h489
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h93
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h101
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h33
-rw-r--r--contrib/llvm/tools/clang/lib/AST/APValue.cpp142
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp6071
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp280
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp4321
-rw-r--r--contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXABI.h48
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp715
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp2265
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp1107
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp1396
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp953
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp940
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp625
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp604
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DumpXML.cpp1028
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp2831
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp893
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp591
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp3061
-rw-r--r--contrib/llvm/tools/clang/lib/AST/InheritViz.cpp163
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp2705
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Mangle.cpp135
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp1188
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp201
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ParentMap.cpp109
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp81
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp1908
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp674
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp680
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp155
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp1399
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp1016
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtViz.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp499
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateName.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp1643
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp265
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp1062
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp377
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp3407
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp180
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp476
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h72
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp392
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp668
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp240
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp290
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp221
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp317
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp610
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Builtins.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/ConvertUTF.c547
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp687
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp586
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp568
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp427
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp134
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp1394
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp433
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp2755
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h172
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp353
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp1421
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h198
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h28
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp2176
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp390
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp174
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h248
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp1416
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.h164
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp1475
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp1144
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h560
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp2038
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h263
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp963
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp341
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp1456
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.h55
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp2104
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp944
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp1478
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp784
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp1188
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp2655
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp923
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp2253
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp6288
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h236
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp1005
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h279
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp998
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp1313
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGTemporaries.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp484
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp3106
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h287
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGValue.h405
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp362
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp790
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h2187
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp2251
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h720
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp180
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h76
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp527
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h224
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/GlobalDecl.h127
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp1168
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp2861
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h117
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Action.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Arg.cpp121
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ArgList.cpp296
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp191
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp1433
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp731
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/InputInfo.h88
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/OptTable.cpp383
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Option.cpp284
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Phases.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tool.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp229
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp1643
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.h384
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp3909
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.h501
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp251
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp453
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp110
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp2099
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/BoostConAction.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp654
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp591
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp1674
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp183
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp184
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DiagChecker.cpp301
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp376
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp374
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp231
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp113
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp994
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp619
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/LangStandards.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp221
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp584
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp439
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp1033
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp513
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Warnings.cpp133
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp155
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/altivec.h11856
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avxintrin.h1156
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/emmintrin.h1362
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/float.h71
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/immintrin.h59
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/iso646.h43
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/limits.h117
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mm_malloc.h71
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mmintrin.h503
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/nmmintrin.h35
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pmmintrin.h121
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/smmintrin.h452
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdarg.h50
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdbool.h44
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stddef.h61
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdint.h654
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tgmath.h1358
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tmmintrin.h218
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/varargs.h26
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/wmmintrin.h67
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/x86intrin.h31
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xmmintrin.h967
-rw-r--r--contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp117
-rw-r--r--contrib/llvm/tools/clang/lib/Index/ASTVisitor.h143
-rw-r--r--contrib/llvm/tools/clang/lib/Index/Analyzer.cpp470
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CallGraph.cpp150
-rw-r--r--contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Index/Entity.cpp270
-rw-r--r--contrib/llvm/tools/clang/lib/Index/EntityImpl.h71
-rw-r--r--contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Index/Handlers.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Index/Indexer.cpp121
-rw-r--r--contrib/llvm/tools/clang/lib/Index/Program.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/Index/ProgramImpl.h56
-rw-r--r--contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp228
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp448
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp2489
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp1069
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp293
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroArgs.h119
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp112
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp1792
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp762
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp358
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp902
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp709
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp1031
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp183
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp494
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp231
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp562
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp388
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp3733
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp2328
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp1948
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp2027
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp387
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp2364
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp434
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.h107
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp1704
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp1124
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp1253
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp1272
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h118
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp469
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp159
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/FrontendActions.cpp116
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/HTMLPrint.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp580
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteMacros.cpp217
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp5928
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp808
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteTest.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp99
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp570
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp141
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp460
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp747
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp288
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp570
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp672
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp1594
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp386
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp1625
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp694
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp3179
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp6522
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp7985
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp3044
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp7624
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp2059
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp522
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp9669
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp3911
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp1210
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp4552
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp3379
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp1363
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp8984
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp1806
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp6223
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp3938
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp2263
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp3105
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp748
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp3038
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp276
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h7786
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h180
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h56
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp4935
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp1693
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp1941
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp3841
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp1254
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp1438
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/CMakeLists.txt3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp96
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp277
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp136
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp521
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h35
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt70
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp1053
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp358
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp284
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp140
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp517
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp87
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td197
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp167
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp137
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h29
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp363
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp80
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp205
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp3655
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp822
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h51
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp311
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp146
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Makefile24
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp731
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp238
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp80
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp203
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp356
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp184
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp152
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp95
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp210
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp470
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp102
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp87
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp94
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp282
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp228
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp138
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicConstraintManager.cpp338
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp604
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp288
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp1896
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp457
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp3519
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CMakeLists.txt41
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp322
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp80
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp848
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp234
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp392
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp204
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/GRState.cpp606
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp581
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Makefile17
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp988
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp99
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp280
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp472
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp441
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp1813
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp310
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp378
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp303
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h93
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp917
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp338
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp345
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp544
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h41
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt20
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/FrontendActions.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/Makefile19
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Makefile18
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/README.txt139
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1_main.cpp182
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp400
-rw-r--r--contrib/llvm/tools/clang/tools/driver/driver.cpp394
702 files changed, 446954 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
new file mode 100644
index 0000000..b3b49c7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -0,0 +1,2912 @@
+/*===-- clang-c/Index.h - Indexing Public C Interface -------------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header provides a public inferface to a Clang library for extracting *|
+|* high-level symbol information from source files without exposing the full *|
+|* Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_C_INDEX_H
+#define CLANG_C_INDEX_H
+
+#include <sys/stat.h>
+#include <time.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MSVC DLL import/export. */
+#ifdef _MSC_VER
+ #ifdef _CINDEX_LIB_
+ #define CINDEX_LINKAGE __declspec(dllexport)
+ #else
+ #define CINDEX_LINKAGE __declspec(dllimport)
+ #endif
+#else
+ #define CINDEX_LINKAGE
+#endif
+
+/** \defgroup CINDEX C Interface to Clang
+ *
+ * The C Interface to Clang provides a relatively small API that exposes
+ * facilities for parsing source code into an abstract syntax tree (AST),
+ * loading already-parsed ASTs, traversing the AST, associating
+ * physical source locations with elements within the AST, and other
+ * facilities that support Clang-based development tools.
+ *
+ * This C interface to Clang will never provide all of the information
+ * representation stored in Clang's C++ AST, nor should it: the intent is to
+ * maintain an API that is relatively stable from one release to the next,
+ * providing only the basic functionality needed to support development tools.
+ *
+ * To avoid namespace pollution, data types are prefixed with "CX" and
+ * functions are prefixed with "clang_".
+ *
+ * @{
+ */
+
+/**
+ * \brief An "index" that consists of a set of translation units that would
+ * typically be linked together into an executable or library.
+ */
+typedef void *CXIndex;
+
+/**
+ * \brief A single translation unit, which resides in an index.
+ */
+typedef struct CXTranslationUnitImpl *CXTranslationUnit;
+
+/**
+ * \brief Opaque pointer representing client data that will be passed through
+ * to various callbacks and visitors.
+ */
+typedef void *CXClientData;
+
+/**
+ * \brief Provides the contents of a file that has not yet been saved to disk.
+ *
+ * Each CXUnsavedFile instance provides the name of a file on the
+ * system along with the current contents of that file that have not
+ * yet been saved to disk.
+ */
+struct CXUnsavedFile {
+ /**
+ * \brief The file whose contents have not yet been saved.
+ *
+ * This file must already exist in the file system.
+ */
+ const char *Filename;
+
+ /**
+ * \brief A buffer containing the unsaved contents of this file.
+ */
+ const char *Contents;
+
+ /**
+ * \brief The length of the unsaved contents of this buffer.
+ */
+ unsigned long Length;
+};
+
+/**
+ * \brief Describes the availability of a particular entity, which indicates
+ * whether the use of this entity will result in a warning or error due to
+ * it being deprecated or unavailable.
+ */
+enum CXAvailabilityKind {
+ /**
+ * \brief The entity is available.
+ */
+ CXAvailability_Available,
+ /**
+ * \brief The entity is available, but has been deprecated (and its use is
+ * not recommended).
+ */
+ CXAvailability_Deprecated,
+ /**
+ * \brief The entity is not available; any use of it will be an error.
+ */
+ CXAvailability_NotAvailable
+};
+
+/**
+ * \defgroup CINDEX_STRING String manipulation routines
+ *
+ * @{
+ */
+
+/**
+ * \brief A character string.
+ *
+ * The \c CXString type is used to return strings from the interface when
+ * the ownership of that string might different from one call to the next.
+ * Use \c clang_getCString() to retrieve the string data and, once finished
+ * with the string data, call \c clang_disposeString() to free the string.
+ */
+typedef struct {
+ void *data;
+ unsigned private_flags;
+} CXString;
+
+/**
+ * \brief Retrieve the character data associated with the given string.
+ */
+CINDEX_LINKAGE const char *clang_getCString(CXString string);
+
+/**
+ * \brief Free the given string,
+ */
+CINDEX_LINKAGE void clang_disposeString(CXString string);
+
+/**
+ * @}
+ */
+
+/**
+ * \brief clang_createIndex() provides a shared context for creating
+ * translation units. It provides two options:
+ *
+ * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
+ * declarations (when loading any new translation units). A "local" declaration
+ * is one that belongs in the translation unit itself and not in a precompiled
+ * header that was used by the translation unit. If zero, all declarations
+ * will be enumerated.
+ *
+ * Here is an example:
+ *
+ * // excludeDeclsFromPCH = 1, displayDiagnostics=1
+ * Idx = clang_createIndex(1, 1);
+ *
+ * // IndexTest.pch was produced with the following command:
+ * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
+ * TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
+ *
+ * // This will load all the symbols from 'IndexTest.pch'
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
+ * clang_disposeTranslationUnit(TU);
+ *
+ * // This will load all the symbols from 'IndexTest.c', excluding symbols
+ * // from 'IndexTest.pch'.
+ * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
+ * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
+ * 0, 0);
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * TranslationUnitVisitor, 0);
+ * clang_disposeTranslationUnit(TU);
+ *
+ * This process of creating the 'pch', loading it separately, and using it (via
+ * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
+ * (which gives the indexer the same performance benefit as the compiler).
+ */
+CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+ int displayDiagnostics);
+
+/**
+ * \brief Destroy the given index.
+ *
+ * The index must not be destroyed until all of the translation units created
+ * within that index have been destroyed.
+ */
+CINDEX_LINKAGE void clang_disposeIndex(CXIndex index);
+
+/**
+ * \defgroup CINDEX_FILES File manipulation routines
+ *
+ * @{
+ */
+
+/**
+ * \brief A particular source file that is part of a translation unit.
+ */
+typedef void *CXFile;
+
+
+/**
+ * \brief Retrieve the complete file and path name of the given file.
+ */
+CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
+
+/**
+ * \brief Retrieve the last modification time of the given file.
+ */
+CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
+
+/**
+ * \brief Retrieve a file handle within the given translation unit.
+ *
+ * \param tu the translation unit
+ *
+ * \param file_name the name of the file.
+ *
+ * \returns the file handle for the named file in the translation unit \p tu,
+ * or a NULL file handle if the file was not a part of this translation unit.
+ */
+CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
+ const char *file_name);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_LOCATIONS Physical source locations
+ *
+ * Clang represents physical source locations in its abstract syntax tree in
+ * great detail, with file, line, and column information for the majority of
+ * the tokens parsed in the source code. These data types and functions are
+ * used to represent source location information, either for a particular
+ * point in the program or for a range of points in the program, and extract
+ * specific location information from those data types.
+ *
+ * @{
+ */
+
+/**
+ * \brief Identifies a specific source location within a translation
+ * unit.
+ *
+ * Use clang_getInstantiationLocation() or clang_getSpellingLocation()
+ * to map a source location to a particular file, line, and column.
+ */
+typedef struct {
+ void *ptr_data[2];
+ unsigned int_data;
+} CXSourceLocation;
+
+/**
+ * \brief Identifies a half-open character range in the source code.
+ *
+ * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+ * starting and end locations from a source range, respectively.
+ */
+typedef struct {
+ void *ptr_data[2];
+ unsigned begin_int_data;
+ unsigned end_int_data;
+} CXSourceRange;
+
+/**
+ * \brief Retrieve a NULL (invalid) source location.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
+
+/**
+ * \determine Determine whether two source locations, which must refer into
+ * the same translation unit, refer to exactly the same point in the source
+ * code.
+ *
+ * \returns non-zero if the source locations refer to the same location, zero
+ * if they refer to different locations.
+ */
+CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
+ CXSourceLocation loc2);
+
+/**
+ * \brief Retrieves the source location associated with a given file/line/column
+ * in a particular translation unit.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column);
+/**
+ * \brief Retrieves the source location associated with a given character offset
+ * in a particular translation unit.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
+ CXFile file,
+ unsigned offset);
+
+/**
+ * \brief Retrieve a NULL (invalid) source range.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getNullRange();
+
+/**
+ * \brief Retrieve a source range given the beginning and ending source
+ * locations.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
+ CXSourceLocation end);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro instantiation, retrieves the
+ * location of the macro instantiation.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro instantiation, return where the
+ * location was originally spelled in the source file.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+/**
+ * \brief Retrieve a source location representing the first character within a
+ * source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
+
+/**
+ * \brief Retrieve a source location representing the last character within a
+ * source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_DIAG Diagnostic reporting
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes the severity of a particular diagnostic.
+ */
+enum CXDiagnosticSeverity {
+ /**
+ * \brief A diagnostic that has been suppressed, e.g., by a command-line
+ * option.
+ */
+ CXDiagnostic_Ignored = 0,
+
+ /**
+ * \brief This diagnostic is a note that should be attached to the
+ * previous (non-note) diagnostic.
+ */
+ CXDiagnostic_Note = 1,
+
+ /**
+ * \brief This diagnostic indicates suspicious code that may not be
+ * wrong.
+ */
+ CXDiagnostic_Warning = 2,
+
+ /**
+ * \brief This diagnostic indicates that the code is ill-formed.
+ */
+ CXDiagnostic_Error = 3,
+
+ /**
+ * \brief This diagnostic indicates that the code is ill-formed such
+ * that future parser recovery is unlikely to produce useful
+ * results.
+ */
+ CXDiagnostic_Fatal = 4
+};
+
+/**
+ * \brief A single diagnostic, containing the diagnostic's severity,
+ * location, text, source ranges, and fix-it hints.
+ */
+typedef void *CXDiagnostic;
+
+/**
+ * \brief Determine the number of diagnostics produced for the given
+ * translation unit.
+ */
+CINDEX_LINKAGE unsigned clang_getNumDiagnostics(CXTranslationUnit Unit);
+
+/**
+ * \brief Retrieve a diagnostic associated with the given translation unit.
+ *
+ * \param Unit the translation unit to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit,
+ unsigned Index);
+
+/**
+ * \brief Destroy a diagnostic.
+ */
+CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic);
+
+/**
+ * \brief Options to control the display of diagnostics.
+ *
+ * The values in this enum are meant to be combined to customize the
+ * behavior of \c clang_displayDiagnostic().
+ */
+enum CXDiagnosticDisplayOptions {
+ /**
+ * \brief Display the source-location information where the
+ * diagnostic was located.
+ *
+ * When set, diagnostics will be prefixed by the file, line, and
+ * (optionally) column to which the diagnostic refers. For example,
+ *
+ * \code
+ * test.c:28: warning: extra tokens at end of #endif directive
+ * \endcode
+ *
+ * This option corresponds to the clang flag \c -fshow-source-location.
+ */
+ CXDiagnostic_DisplaySourceLocation = 0x01,
+
+ /**
+ * \brief If displaying the source-location information of the
+ * diagnostic, also include the column number.
+ *
+ * This option corresponds to the clang flag \c -fshow-column.
+ */
+ CXDiagnostic_DisplayColumn = 0x02,
+
+ /**
+ * \brief If displaying the source-location information of the
+ * diagnostic, also include information about source ranges in a
+ * machine-parsable format.
+ *
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-print-source-range-info.
+ */
+ CXDiagnostic_DisplaySourceRanges = 0x04,
+
+ /**
+ * \brief Display the option name associated with this diagnostic, if any.
+ *
+ * The option name displayed (e.g., -Wconversion) will be placed in brackets
+ * after the diagnostic text. This option corresponds to the clang flag
+ * \c -fdiagnostics-show-option.
+ */
+ CXDiagnostic_DisplayOption = 0x08,
+
+ /**
+ * \brief Display the category number associated with this diagnostic, if any.
+ *
+ * The category number is displayed within brackets after the diagnostic text.
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-show-category=id.
+ */
+ CXDiagnostic_DisplayCategoryId = 0x10,
+
+ /**
+ * \brief Display the category name associated with this diagnostic, if any.
+ *
+ * The category name is displayed within brackets after the diagnostic text.
+ * This option corresponds to the clang flag
+ * \c -fdiagnostics-show-category=name.
+ */
+ CXDiagnostic_DisplayCategoryName = 0x20
+};
+
+/**
+ * \brief Format the given diagnostic in a manner that is suitable for display.
+ *
+ * This routine will format the given diagnostic to a string, rendering
+ * the diagnostic according to the various options given. The
+ * \c clang_defaultDiagnosticDisplayOptions() function returns the set of
+ * options that most closely mimics the behavior of the clang compiler.
+ *
+ * \param Diagnostic The diagnostic to print.
+ *
+ * \param Options A set of options that control the diagnostic display,
+ * created by combining \c CXDiagnosticDisplayOptions values.
+ *
+ * \returns A new string containing for formatted diagnostic.
+ */
+CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
+ unsigned Options);
+
+/**
+ * \brief Retrieve the set of display options most similar to the
+ * default behavior of the clang compiler.
+ *
+ * \returns A set of display options suitable for use with \c
+ * clang_displayDiagnostic().
+ */
+CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
+
+/**
+ * \brief Determine the severity of the given diagnostic.
+ */
+CINDEX_LINKAGE enum CXDiagnosticSeverity
+clang_getDiagnosticSeverity(CXDiagnostic);
+
+/**
+ * \brief Retrieve the source location of the given diagnostic.
+ *
+ * This location is where Clang would print the caret ('^') when
+ * displaying the diagnostic on the command line.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
+
+/**
+ * \brief Retrieve the text of the given diagnostic.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
+
+/**
+ * \brief Retrieve the name of the command-line option that enabled this
+ * diagnostic.
+ *
+ * \param Diag The diagnostic to be queried.
+ *
+ * \param Disable If non-NULL, will be set to the option that disables this
+ * diagnostic (if any).
+ *
+ * \returns A string that contains the command-line option used to enable this
+ * warning, such as "-Wconversion" or "-pedantic".
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
+ CXString *Disable);
+
+/**
+ * \brief Retrieve the category number for this diagnostic.
+ *
+ * Diagnostics can be categorized into groups along with other, related
+ * diagnostics (e.g., diagnostics under the same warning flag). This routine
+ * retrieves the category number for the given diagnostic.
+ *
+ * \returns The number of the category that contains this diagnostic, or zero
+ * if this diagnostic is uncategorized.
+ */
+CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
+
+/**
+ * \brief Retrieve the name of a particular diagnostic category.
+ *
+ * \param Category A diagnostic category number, as returned by
+ * \c clang_getDiagnosticCategory().
+ *
+ * \returns The name of the given diagnostic category.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticCategoryName(unsigned Category);
+
+/**
+ * \brief Determine the number of source ranges associated with the given
+ * diagnostic.
+ */
+CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
+
+/**
+ * \brief Retrieve a source range associated with the diagnostic.
+ *
+ * A diagnostic's source ranges highlight important elements in the source
+ * code. On the command line, Clang displays source ranges by
+ * underlining them with '~' characters.
+ *
+ * \param Diagnostic the diagnostic whose range is being extracted.
+ *
+ * \param Range the zero-based index specifying which range to
+ *
+ * \returns the requested source range.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
+ unsigned Range);
+
+/**
+ * \brief Determine the number of fix-it hints associated with the
+ * given diagnostic.
+ */
+CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
+
+/**
+ * \brief Retrieve the replacement information for a given fix-it.
+ *
+ * Fix-its are described in terms of a source range whose contents
+ * should be replaced by a string. This approach generalizes over
+ * three kinds of operations: removal of source code (the range covers
+ * the code to be removed and the replacement string is empty),
+ * replacement of source code (the range covers the code to be
+ * replaced and the replacement string provides the new code), and
+ * insertion (both the start and end of the range point at the
+ * insertion location, and the replacement string provides the text to
+ * insert).
+ *
+ * \param Diagnostic The diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt The zero-based index of the fix-it.
+ *
+ * \param ReplacementRange The source range whose contents will be
+ * replaced with the returned replacement string. Note that source
+ * ranges are half-open ranges [a, b), so the source code should be
+ * replaced from a and up to (but not including) b.
+ *
+ * \returns A string containing text that should be replace the source
+ * code indicated by the \c ReplacementRange.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
+ unsigned FixIt,
+ CXSourceRange *ReplacementRange);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation
+ *
+ * The routines in this group provide the ability to create and destroy
+ * translation units from files, either by parsing the contents of the files or
+ * by reading in a serialized representation of a translation unit.
+ *
+ * @{
+ */
+
+/**
+ * \brief Get the original translation unit source file name.
+ */
+CINDEX_LINKAGE CXString
+clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+
+/**
+ * \brief Return the CXTranslationUnit for a given source file and the provided
+ * command line arguments one would pass to the compiler.
+ *
+ * Note: The 'source_filename' argument is optional. If the caller provides a
+ * NULL pointer, the name of the source file is expected to reside in the
+ * specified command line arguments.
+ *
+ * Note: When encountered in 'clang_command_line_args', the following options
+ * are ignored:
+ *
+ * '-c'
+ * '-emit-ast'
+ * '-fsyntax-only'
+ * '-o <output file>' (both '-o' and '<output file>' are ignored)
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param source_filename - The name of the source file to load, or NULL if the
+ * source file is included in \p clang_command_line_args.
+ *
+ * \param num_clang_command_line_args The number of command-line arguments in
+ * \p clang_command_line_args.
+ *
+ * \param clang_command_line_args The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed. Note that the following options are ignored: '-c',
+ * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for code completion, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
+ CXIndex CIdx,
+ const char *source_filename,
+ int num_clang_command_line_args,
+ const char * const *clang_command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files);
+
+/**
+ * \brief Create a translation unit from an AST file (-emit-ast).
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
+ const char *ast_filename);
+
+/**
+ * \brief Flags that control the creation of translation units.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * constructing the translation unit.
+ */
+enum CXTranslationUnit_Flags {
+ /**
+ * \brief Used to indicate that no special translation-unit options are
+ * needed.
+ */
+ CXTranslationUnit_None = 0x0,
+
+ /**
+ * \brief Used to indicate that the parser should construct a "detailed"
+ * preprocessing record, including all macro definitions and instantiations.
+ *
+ * Constructing a detailed preprocessing record requires more memory
+ * and time to parse, since the information contained in the record
+ * is usually not retained. However, it can be useful for
+ * applications that require more detailed information about the
+ * behavior of the preprocessor.
+ */
+ CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
+
+ /**
+ * \brief Used to indicate that the translation unit is incomplete.
+ *
+ * When a translation unit is considered "incomplete", semantic
+ * analysis that is typically performed at the end of the
+ * translation unit will be suppressed. For example, this suppresses
+ * the completion of tentative declarations in C and of
+ * instantiation of implicitly-instantiation function templates in
+ * C++. This option is typically used when parsing a header with the
+ * intent of producing a precompiled header.
+ */
+ CXTranslationUnit_Incomplete = 0x02,
+
+ /**
+ * \brief Used to indicate that the translation unit should be built with an
+ * implicit precompiled header for the preamble.
+ *
+ * An implicit precompiled header is used as an optimization when a
+ * particular translation unit is likely to be reparsed many times
+ * when the sources aren't changing that often. In this case, an
+ * implicit precompiled header will be built containing all of the
+ * initial includes at the top of the main file (what we refer to as
+ * the "preamble" of the file). In subsequent parses, if the
+ * preamble or the files in it have not changed, \c
+ * clang_reparseTranslationUnit() will re-use the implicit
+ * precompiled header to improve parsing performance.
+ */
+ CXTranslationUnit_PrecompiledPreamble = 0x04,
+
+ /**
+ * \brief Used to indicate that the translation unit should cache some
+ * code-completion results with each reparse of the source file.
+ *
+ * Caching of code-completion results is a performance optimization that
+ * introduces some overhead to reparsing but improves the performance of
+ * code-completion operations.
+ */
+ CXTranslationUnit_CacheCompletionResults = 0x08,
+ /**
+ * \brief Enable precompiled preambles in C++.
+ *
+ * Note: this is a *temporary* option that is available only while
+ * we are testing C++ precompiled preamble support.
+ */
+ CXTranslationUnit_CXXPrecompiledPreamble = 0x10,
+
+ /**
+ * \brief Enabled chained precompiled preambles in C++.
+ *
+ * Note: this is a *temporary* option that is available only while
+ * we are testing C++ precompiled preamble support.
+ */
+ CXTranslationUnit_CXXChainedPCH = 0x20
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for parsing a translation
+ * unit that is being edited.
+ *
+ * The set of flags returned provide options for \c clang_parseTranslationUnit()
+ * to indicate that the translation unit is likely to be reparsed many times,
+ * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
+ * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
+ * set contains an unspecified set of optimizations (e.g., the precompiled
+ * preamble) geared toward improving the performance of these routines. The
+ * set of optimizations enabled may change from one version to the next.
+ */
+CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
+
+/**
+ * \brief Parse the given source file and the translation unit corresponding
+ * to that file.
+ *
+ * This routine is the main entry point for the Clang C API, providing the
+ * ability to parse a source file into a translation unit that can then be
+ * queried by other functions in the API. This routine accepts a set of
+ * command-line arguments so that the compilation can be configured in the same
+ * way that the compiler is configured on the command line.
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param source_filename The name of the source file to load, or NULL if the
+ * source file is included in \p command_line_args.
+ *
+ * \param command_line_args The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed. Note that the following options are ignored: '-c',
+ * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
+ *
+ * \param num_command_line_args The number of command-line arguments in
+ * \p command_line_args.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is managed but not its compilation. This should be a bitwise OR of the
+ * CXTranslationUnit_XXX flags.
+ *
+ * \returns A new translation unit describing the parsed code and containing
+ * any diagnostics produced by the compiler. If there is a failure from which
+ * the compiler cannot recover, returns NULL.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options);
+
+/**
+ * \brief Flags that control how translation units are saved.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * saving the translation unit.
+ */
+enum CXSaveTranslationUnit_Flags {
+ /**
+ * \brief Used to indicate that no special saving options are needed.
+ */
+ CXSaveTranslationUnit_None = 0x0
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for saving a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_saveTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of options that save translation units with
+ * the most commonly-requested data.
+ */
+CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU);
+
+/**
+ * \brief Saves a translation unit into a serialized representation of
+ * that translation unit on disk.
+ *
+ * Any translation unit that was parsed without error can be saved
+ * into a file. The translation unit can then be deserialized into a
+ * new \c CXTranslationUnit with \c clang_createTranslationUnit() or,
+ * if it is an incomplete translation unit that corresponds to a
+ * header, used as a precompiled header when parsing other translation
+ * units.
+ *
+ * \param TU The translation unit to save.
+ *
+ * \param FileName The file to which the translation unit will be saved.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is saved. This should be a bitwise OR of the
+ * CXSaveTranslationUnit_XXX flags.
+ *
+ * \returns Zero if the translation unit was saved successfully, a
+ * non-zero value otherwise.
+ */
+CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
+ const char *FileName,
+ unsigned options);
+
+/**
+ * \brief Destroy the specified CXTranslationUnit object.
+ */
+CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
+
+/**
+ * \brief Flags that control the reparsing of translation units.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * reparsing the translation unit.
+ */
+enum CXReparse_Flags {
+ /**
+ * \brief Used to indicate that no special reparsing options are needed.
+ */
+ CXReparse_None = 0x0
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for reparsing a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_reparseTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of optimizations geared toward common uses
+ * of reparsing. The set of optimizations enabled may change from one version
+ * to the next.
+ */
+CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
+
+/**
+ * \brief Reparse the source files that produced this translation unit.
+ *
+ * This routine can be used to re-parse the source files that originally
+ * created the given translation unit, for example because those source files
+ * have changed (either on disk or as passed via \p unsaved_files). The
+ * source code will be reparsed with the same command-line options as it
+ * was originally parsed.
+ *
+ * Reparsing a translation unit invalidates all cursors and source locations
+ * that refer into that translation unit. This makes reparsing a translation
+ * unit semantically equivalent to destroying the translation unit and then
+ * creating a new translation unit with the same command-line arguments.
+ * However, it may be more efficient to reparse a translation
+ * unit using this routine.
+ *
+ * \param TU The translation unit whose contents will be re-parsed. The
+ * translation unit must originally have been built with
+ * \c clang_createTranslationUnitFromSourceFile().
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files The files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param options A bitset of options composed of the flags in CXReparse_Flags.
+ * The function \c clang_defaultReparseOptions() produces a default set of
+ * options recommended for most uses, based on the translation unit.
+ *
+ * \returns 0 if the sources could be reparsed. A non-zero value will be
+ * returned if reparsing was impossible, such that the translation unit is
+ * invalid. In such cases, the only valid call for \p TU is
+ * \c clang_disposeTranslationUnit(TU).
+ */
+CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options);
+
+/**
+ * @}
+ */
+
+/**
+ * \brief Describes the kind of entity that a cursor refers to.
+ */
+enum CXCursorKind {
+ /* Declarations */
+ /**
+ * \brief A declaration whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed declarations have the same operations as any other kind
+ * of declaration; one can extract their location information,
+ * spelling, find their definitions, etc. However, the specific kind
+ * of the declaration is not reported.
+ */
+ CXCursor_UnexposedDecl = 1,
+ /** \brief A C or C++ struct. */
+ CXCursor_StructDecl = 2,
+ /** \brief A C or C++ union. */
+ CXCursor_UnionDecl = 3,
+ /** \brief A C++ class. */
+ CXCursor_ClassDecl = 4,
+ /** \brief An enumeration. */
+ CXCursor_EnumDecl = 5,
+ /**
+ * \brief A field (in C) or non-static data member (in C++) in a
+ * struct, union, or C++ class.
+ */
+ CXCursor_FieldDecl = 6,
+ /** \brief An enumerator constant. */
+ CXCursor_EnumConstantDecl = 7,
+ /** \brief A function. */
+ CXCursor_FunctionDecl = 8,
+ /** \brief A variable. */
+ CXCursor_VarDecl = 9,
+ /** \brief A function or method parameter. */
+ CXCursor_ParmDecl = 10,
+ /** \brief An Objective-C @interface. */
+ CXCursor_ObjCInterfaceDecl = 11,
+ /** \brief An Objective-C @interface for a category. */
+ CXCursor_ObjCCategoryDecl = 12,
+ /** \brief An Objective-C @protocol declaration. */
+ CXCursor_ObjCProtocolDecl = 13,
+ /** \brief An Objective-C @property declaration. */
+ CXCursor_ObjCPropertyDecl = 14,
+ /** \brief An Objective-C instance variable. */
+ CXCursor_ObjCIvarDecl = 15,
+ /** \brief An Objective-C instance method. */
+ CXCursor_ObjCInstanceMethodDecl = 16,
+ /** \brief An Objective-C class method. */
+ CXCursor_ObjCClassMethodDecl = 17,
+ /** \brief An Objective-C @implementation. */
+ CXCursor_ObjCImplementationDecl = 18,
+ /** \brief An Objective-C @implementation for a category. */
+ CXCursor_ObjCCategoryImplDecl = 19,
+ /** \brief A typedef */
+ CXCursor_TypedefDecl = 20,
+ /** \brief A C++ class method. */
+ CXCursor_CXXMethod = 21,
+ /** \brief A C++ namespace. */
+ CXCursor_Namespace = 22,
+ /** \brief A linkage specification, e.g. 'extern "C"'. */
+ CXCursor_LinkageSpec = 23,
+ /** \brief A C++ constructor. */
+ CXCursor_Constructor = 24,
+ /** \brief A C++ destructor. */
+ CXCursor_Destructor = 25,
+ /** \brief A C++ conversion function. */
+ CXCursor_ConversionFunction = 26,
+ /** \brief A C++ template type parameter. */
+ CXCursor_TemplateTypeParameter = 27,
+ /** \brief A C++ non-type template parameter. */
+ CXCursor_NonTypeTemplateParameter = 28,
+ /** \brief A C++ template template parameter. */
+ CXCursor_TemplateTemplateParameter = 29,
+ /** \brief A C++ function template. */
+ CXCursor_FunctionTemplate = 30,
+ /** \brief A C++ class template. */
+ CXCursor_ClassTemplate = 31,
+ /** \brief A C++ class template partial specialization. */
+ CXCursor_ClassTemplatePartialSpecialization = 32,
+ /** \brief A C++ namespace alias declaration. */
+ CXCursor_NamespaceAlias = 33,
+ /** \brief A C++ using directive. */
+ CXCursor_UsingDirective = 34,
+ /** \brief A using declaration. */
+ CXCursor_UsingDeclaration = 35,
+ CXCursor_FirstDecl = CXCursor_UnexposedDecl,
+ CXCursor_LastDecl = CXCursor_UsingDeclaration,
+
+ /* References */
+ CXCursor_FirstRef = 40, /* Decl references */
+ CXCursor_ObjCSuperClassRef = 40,
+ CXCursor_ObjCProtocolRef = 41,
+ CXCursor_ObjCClassRef = 42,
+ /**
+ * \brief A reference to a type declaration.
+ *
+ * A type reference occurs anywhere where a type is named but not
+ * declared. For example, given:
+ *
+ * \code
+ * typedef unsigned size_type;
+ * size_type size;
+ * \endcode
+ *
+ * The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+ * while the type of the variable "size" is referenced. The cursor
+ * referenced by the type of size is the typedef for size_type.
+ */
+ CXCursor_TypeRef = 43,
+ CXCursor_CXXBaseSpecifier = 44,
+ /**
+ * \brief A reference to a class template, function template, template
+ * template parameter, or class template partial specialization.
+ */
+ CXCursor_TemplateRef = 45,
+ /**
+ * \brief A reference to a namespace or namespace alias.
+ */
+ CXCursor_NamespaceRef = 46,
+ /**
+ * \brief A reference to a member of a struct, union, or class that occurs in
+ * some non-expression context, e.g., a designated initializer.
+ */
+ CXCursor_MemberRef = 47,
+ /**
+ * \brief A reference to a labeled statement.
+ *
+ * This cursor kind is used to describe the jump to "start_over" in the
+ * goto statement in the following example:
+ *
+ * \code
+ * start_over:
+ * ++counter;
+ *
+ * goto start_over;
+ * \endcode
+ *
+ * A label reference cursor refers to a label statement.
+ */
+ CXCursor_LabelRef = 48,
+
+ /**
+ * \brief A reference to a set of overloaded functions or function templates
+ * that has not yet been resolved to a specific function or function template.
+ *
+ * An overloaded declaration reference cursor occurs in C++ templates where
+ * a dependent name refers to a function. For example:
+ *
+ * \code
+ * template<typename T> void swap(T&, T&);
+ *
+ * struct X { ... };
+ * void swap(X&, X&);
+ *
+ * template<typename T>
+ * void reverse(T* first, T* last) {
+ * while (first < last - 1) {
+ * swap(*first, *--last);
+ * ++first;
+ * }
+ * }
+ *
+ * struct Y { };
+ * void swap(Y&, Y&);
+ * \endcode
+ *
+ * Here, the identifier "swap" is associated with an overloaded declaration
+ * reference. In the template definition, "swap" refers to either of the two
+ * "swap" functions declared above, so both results will be available. At
+ * instantiation time, "swap" may also refer to other functions found via
+ * argument-dependent lookup (e.g., the "swap" function at the end of the
+ * example).
+ *
+ * The functions \c clang_getNumOverloadedDecls() and
+ * \c clang_getOverloadedDecl() can be used to retrieve the definitions
+ * referenced by this cursor.
+ */
+ CXCursor_OverloadedDeclRef = 49,
+
+ CXCursor_LastRef = CXCursor_OverloadedDeclRef,
+
+ /* Error conditions */
+ CXCursor_FirstInvalid = 70,
+ CXCursor_InvalidFile = 70,
+ CXCursor_NoDeclFound = 71,
+ CXCursor_NotImplemented = 72,
+ CXCursor_InvalidCode = 73,
+ CXCursor_LastInvalid = CXCursor_InvalidCode,
+
+ /* Expressions */
+ CXCursor_FirstExpr = 100,
+
+ /**
+ * \brief An expression whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed expressions have the same operations as any other kind
+ * of expression; one can extract their location information,
+ * spelling, children, etc. However, the specific kind of the
+ * expression is not reported.
+ */
+ CXCursor_UnexposedExpr = 100,
+
+ /**
+ * \brief An expression that refers to some value declaration, such
+ * as a function, varible, or enumerator.
+ */
+ CXCursor_DeclRefExpr = 101,
+
+ /**
+ * \brief An expression that refers to a member of a struct, union,
+ * class, Objective-C class, etc.
+ */
+ CXCursor_MemberRefExpr = 102,
+
+ /** \brief An expression that calls a function. */
+ CXCursor_CallExpr = 103,
+
+ /** \brief An expression that sends a message to an Objective-C
+ object or class. */
+ CXCursor_ObjCMessageExpr = 104,
+
+ /** \brief An expression that represents a block literal. */
+ CXCursor_BlockExpr = 105,
+
+ CXCursor_LastExpr = 105,
+
+ /* Statements */
+ CXCursor_FirstStmt = 200,
+ /**
+ * \brief A statement whose specific kind is not exposed via this
+ * interface.
+ *
+ * Unexposed statements have the same operations as any other kind of
+ * statement; one can extract their location information, spelling,
+ * children, etc. However, the specific kind of the statement is not
+ * reported.
+ */
+ CXCursor_UnexposedStmt = 200,
+
+ /** \brief A labelled statement in a function.
+ *
+ * This cursor kind is used to describe the "start_over:" label statement in
+ * the following example:
+ *
+ * \code
+ * start_over:
+ * ++counter;
+ * \endcode
+ *
+ */
+ CXCursor_LabelStmt = 201,
+
+ CXCursor_LastStmt = CXCursor_LabelStmt,
+
+ /**
+ * \brief Cursor that represents the translation unit itself.
+ *
+ * The translation unit cursor exists primarily to act as the root
+ * cursor for traversing the contents of a translation unit.
+ */
+ CXCursor_TranslationUnit = 300,
+
+ /* Attributes */
+ CXCursor_FirstAttr = 400,
+ /**
+ * \brief An attribute whose specific kind is not exposed via this
+ * interface.
+ */
+ CXCursor_UnexposedAttr = 400,
+
+ CXCursor_IBActionAttr = 401,
+ CXCursor_IBOutletAttr = 402,
+ CXCursor_IBOutletCollectionAttr = 403,
+ CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr,
+
+ /* Preprocessing */
+ CXCursor_PreprocessingDirective = 500,
+ CXCursor_MacroDefinition = 501,
+ CXCursor_MacroInstantiation = 502,
+ CXCursor_InclusionDirective = 503,
+ CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective,
+ CXCursor_LastPreprocessing = CXCursor_InclusionDirective
+};
+
+/**
+ * \brief A cursor representing some element in the abstract syntax tree for
+ * a translation unit.
+ *
+ * The cursor abstraction unifies the different kinds of entities in a
+ * program--declaration, statements, expressions, references to declarations,
+ * etc.--under a single "cursor" abstraction with a common set of operations.
+ * Common operation for a cursor include: getting the physical location in
+ * a source file where the cursor points, getting the name associated with a
+ * cursor, and retrieving cursors for any child nodes of a particular cursor.
+ *
+ * Cursors can be produced in two specific ways.
+ * clang_getTranslationUnitCursor() produces a cursor for a translation unit,
+ * from which one can use clang_visitChildren() to explore the rest of the
+ * translation unit. clang_getCursor() maps from a physical source location
+ * to the entity that resides at that location, allowing one to map from the
+ * source code into the AST.
+ */
+typedef struct {
+ enum CXCursorKind kind;
+ void *data[3];
+} CXCursor;
+
+/**
+ * \defgroup CINDEX_CURSOR_MANIP Cursor manipulations
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve the NULL cursor, which represents no entity.
+ */
+CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
+
+/**
+ * \brief Retrieve the cursor that represents the given translation unit.
+ *
+ * The translation unit cursor can be used to start traversing the
+ * various declarations within the given translation unit.
+ */
+CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
+
+/**
+ * \brief Determine whether two cursors are equivalent.
+ */
+CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
+
+/**
+ * \brief Compute a hash value for the given cursor.
+ */
+CINDEX_LINKAGE unsigned clang_hashCursor(CXCursor);
+
+/**
+ * \brief Retrieve the kind of the given cursor.
+ */
+CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
+
+/**
+ * \brief Determine whether the given cursor kind represents a declaration.
+ */
+CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents a simple
+ * reference.
+ *
+ * Note that other kinds of cursors (such as expressions) can also refer to
+ * other cursors. Use clang_getCursorReferenced() to determine whether a
+ * particular cursor refers to another entity.
+ */
+CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents an expression.
+ */
+CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents a statement.
+ */
+CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents an invalid
+ * cursor.
+ */
+CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
+
+/**
+ * \brief Determine whether the given cursor kind represents a translation
+ * unit.
+ */
+CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
+
+/***
+ * \brief Determine whether the given cursor represents a preprocessing
+ * element, such as a preprocessor directive or macro instantiation.
+ */
+CINDEX_LINKAGE unsigned clang_isPreprocessing(enum CXCursorKind);
+
+/***
+ * \brief Determine whether the given cursor represents a currently
+ * unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
+ */
+CINDEX_LINKAGE unsigned clang_isUnexposed(enum CXCursorKind);
+
+/**
+ * \brief Describe the linkage of the entity referred to by a cursor.
+ */
+enum CXLinkageKind {
+ /** \brief This value indicates that no linkage information is available
+ * for a provided CXCursor. */
+ CXLinkage_Invalid,
+ /**
+ * \brief This is the linkage for variables, parameters, and so on that
+ * have automatic storage. This covers normal (non-extern) local variables.
+ */
+ CXLinkage_NoLinkage,
+ /** \brief This is the linkage for static variables and static functions. */
+ CXLinkage_Internal,
+ /** \brief This is the linkage for entities with external linkage that live
+ * in C++ anonymous namespaces.*/
+ CXLinkage_UniqueExternal,
+ /** \brief This is the linkage for entities with true, external linkage. */
+ CXLinkage_External
+};
+
+/**
+ * \brief Determine the linkage of the entity referred to by a given cursor.
+ */
+CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
+
+/**
+ * \brief Determine the availability of the entity that this cursor refers to.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The availability of the cursor.
+ */
+CINDEX_LINKAGE enum CXAvailabilityKind
+clang_getCursorAvailability(CXCursor cursor);
+
+/**
+ * \brief Describe the "language" of the entity referred to by a cursor.
+ */
+CINDEX_LINKAGE enum CXLanguageKind {
+ CXLanguage_Invalid = 0,
+ CXLanguage_C,
+ CXLanguage_ObjC,
+ CXLanguage_CPlusPlus
+};
+
+/**
+ * \brief Determine the "language" of the entity referred to by a given cursor.
+ */
+CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
+
+
+/**
+ * \brief A fast container representing a set of CXCursors.
+ */
+typedef struct CXCursorSetImpl *CXCursorSet;
+
+/**
+ * \brief Creates an empty CXCursorSet.
+ */
+CINDEX_LINKAGE CXCursorSet clang_createCXCursorSet();
+
+/**
+ * \brief Disposes a CXCursorSet and releases its associated memory.
+ */
+CINDEX_LINKAGE void clang_disposeCXCursorSet(CXCursorSet cset);
+
+/**
+ * \brief Queries a CXCursorSet to see if it contains a specific CXCursor.
+ *
+ * \returns non-zero if the set contains the specified cursor.
+*/
+CINDEX_LINKAGE unsigned clang_CXCursorSet_contains(CXCursorSet cset,
+ CXCursor cursor);
+
+/**
+ * \brief Inserts a CXCursor into a CXCursorSet.
+ *
+ * \returns zero if the CXCursor was already in the set, and non-zero otherwise.
+*/
+CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset,
+ CXCursor cursor);
+
+/**
+ * \brief Determine the semantic parent of the given cursor.
+ *
+ * The semantic parent of a cursor is the cursor that semantically contains
+ * the given \p cursor. For many declarations, the lexical and semantic parents
+ * are equivalent (the lexical parent is returned by
+ * \c clang_getCursorLexicalParent()). They diverge when declarations or
+ * definitions are provided out-of-line. For example:
+ *
+ * \code
+ * class C {
+ * void f();
+ * };
+ *
+ * void C::f() { }
+ * \endcode
+ *
+ * In the out-of-line definition of \c C::f, the semantic parent is the
+ * the class \c C, of which this function is a member. The lexical parent is
+ * the place where the declaration actually occurs in the source code; in this
+ * case, the definition occurs in the translation unit. In general, the
+ * lexical parent for a given entity can change without affecting the semantics
+ * of the program, and the lexical parent of different declarations of the
+ * same entity may be different. Changing the semantic parent of a declaration,
+ * on the other hand, can have a major impact on semantics, and redeclarations
+ * of a particular entity should all have the same semantic context.
+ *
+ * In the example above, both declarations of \c C::f have \c C as their
+ * semantic context, while the lexical context of the first \c C::f is \c C
+ * and the lexical context of the second \c C::f is the translation unit.
+ *
+ * For global declarations, the semantic parent is the translation unit.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor);
+
+/**
+ * \brief Determine the lexical parent of the given cursor.
+ *
+ * The lexical parent of a cursor is the cursor in which the given \p cursor
+ * was actually written. For many declarations, the lexical and semantic parents
+ * are equivalent (the semantic parent is returned by
+ * \c clang_getCursorSemanticParent()). They diverge when declarations or
+ * definitions are provided out-of-line. For example:
+ *
+ * \code
+ * class C {
+ * void f();
+ * };
+ *
+ * void C::f() { }
+ * \endcode
+ *
+ * In the out-of-line definition of \c C::f, the semantic parent is the
+ * the class \c C, of which this function is a member. The lexical parent is
+ * the place where the declaration actually occurs in the source code; in this
+ * case, the definition occurs in the translation unit. In general, the
+ * lexical parent for a given entity can change without affecting the semantics
+ * of the program, and the lexical parent of different declarations of the
+ * same entity may be different. Changing the semantic parent of a declaration,
+ * on the other hand, can have a major impact on semantics, and redeclarations
+ * of a particular entity should all have the same semantic context.
+ *
+ * In the example above, both declarations of \c C::f have \c C as their
+ * semantic context, while the lexical context of the first \c C::f is \c C
+ * and the lexical context of the second \c C::f is the translation unit.
+ *
+ * For declarations written in the global scope, the lexical parent is
+ * the translation unit.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
+
+/**
+ * \brief Determine the set of methods that are overridden by the given
+ * method.
+ *
+ * In both Objective-C and C++, a method (aka virtual member function,
+ * in C++) can override a virtual method in a base class. For
+ * Objective-C, a method is said to override any method in the class's
+ * interface (if we're coming from an implementation), its protocols,
+ * or its categories, that has the same selector and is of the same
+ * kind (class or instance). If no such method exists, the search
+ * continues to the class's superclass, its protocols, and its
+ * categories, and so on.
+ *
+ * For C++, a virtual member function overrides any virtual member
+ * function with the same signature that occurs in its base
+ * classes. With multiple inheritance, a virtual member function can
+ * override several virtual member functions coming from different
+ * base classes.
+ *
+ * In all cases, this function determines the immediate overridden
+ * method, rather than all of the overridden methods. For example, if
+ * a method is originally declared in a class A, then overridden in B
+ * (which in inherits from A) and also in C (which inherited from B),
+ * then the only overridden method returned from this function when
+ * invoked on C's method will be B's method. The client may then
+ * invoke this function again, given the previously-found overridden
+ * methods, to map out the complete method-override set.
+ *
+ * \param cursor A cursor representing an Objective-C or C++
+ * method. This routine will compute the set of methods that this
+ * method overrides.
+ *
+ * \param overridden A pointer whose pointee will be replaced with a
+ * pointer to an array of cursors, representing the set of overridden
+ * methods. If there are no overridden methods, the pointee will be
+ * set to NULL. The pointee must be freed via a call to
+ * \c clang_disposeOverriddenCursors().
+ *
+ * \param num_overridden A pointer to the number of overridden
+ * functions, will be set to the number of overridden functions in the
+ * array pointed to by \p overridden.
+ */
+CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
+ CXCursor **overridden,
+ unsigned *num_overridden);
+
+/**
+ * \brief Free the set of overridden cursors returned by \c
+ * clang_getOverriddenCursors().
+ */
+CINDEX_LINKAGE void clang_disposeOverriddenCursors(CXCursor *overridden);
+
+/**
+ * \brief Retrieve the file that is included by the given inclusion directive
+ * cursor.
+ */
+CINDEX_LINKAGE CXFile clang_getIncludedFile(CXCursor cursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_SOURCE Mapping between cursors and source code
+ *
+ * Cursors represent a location within the Abstract Syntax Tree (AST). These
+ * routines help map between cursors and the physical locations where the
+ * described entities occur in the source code. The mapping is provided in
+ * both directions, so one can map from source code to the AST and back.
+ *
+ * @{
+ */
+
+/**
+ * \brief Map a source location to the cursor that describes the entity at that
+ * location in the source code.
+ *
+ * clang_getCursor() maps an arbitrary source location within a translation
+ * unit down to the most specific cursor that describes the entity at that
+ * location. For example, given an expression \c x + y, invoking
+ * clang_getCursor() with a source location pointing to "x" will return the
+ * cursor for "x"; similarly for "y". If the cursor points anywhere between
+ * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
+ * will return a cursor referring to the "+" expression.
+ *
+ * \returns a cursor representing the entity at the given source location, or
+ * a NULL cursor if no such entity can be found.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
+
+/**
+ * \brief Retrieve the physical location of the source constructor referenced
+ * by the given cursor.
+ *
+ * The location of a declaration is typically the location of the name of that
+ * declaration, where the name of that declaration would occur if it is
+ * unnamed, or some keyword that introduces that particular declaration.
+ * The location of a reference is where that reference occurs within the
+ * source code.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
+
+/**
+ * \brief Retrieve the physical extent of the source construct referenced by
+ * the given cursor.
+ *
+ * The extent of a cursor starts with the file/line/column pointing at the
+ * first character within the source construct that the cursor refers to and
+ * ends with the last character withinin that source construct. For a
+ * declaration, the extent covers the declaration itself. For a reference,
+ * the extent covers the location of the reference (e.g., where the referenced
+ * entity was actually used).
+ */
+CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_TYPES Type information for CXCursors
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes the kind of type
+ */
+enum CXTypeKind {
+ /**
+ * \brief Reprents an invalid type (e.g., where no type is available).
+ */
+ CXType_Invalid = 0,
+
+ /**
+ * \brief A type whose specific kind is not exposed via this
+ * interface.
+ */
+ CXType_Unexposed = 1,
+
+ /* Builtin types */
+ CXType_Void = 2,
+ CXType_Bool = 3,
+ CXType_Char_U = 4,
+ CXType_UChar = 5,
+ CXType_Char16 = 6,
+ CXType_Char32 = 7,
+ CXType_UShort = 8,
+ CXType_UInt = 9,
+ CXType_ULong = 10,
+ CXType_ULongLong = 11,
+ CXType_UInt128 = 12,
+ CXType_Char_S = 13,
+ CXType_SChar = 14,
+ CXType_WChar = 15,
+ CXType_Short = 16,
+ CXType_Int = 17,
+ CXType_Long = 18,
+ CXType_LongLong = 19,
+ CXType_Int128 = 20,
+ CXType_Float = 21,
+ CXType_Double = 22,
+ CXType_LongDouble = 23,
+ CXType_NullPtr = 24,
+ CXType_Overload = 25,
+ CXType_Dependent = 26,
+ CXType_ObjCId = 27,
+ CXType_ObjCClass = 28,
+ CXType_ObjCSel = 29,
+ CXType_FirstBuiltin = CXType_Void,
+ CXType_LastBuiltin = CXType_ObjCSel,
+
+ CXType_Complex = 100,
+ CXType_Pointer = 101,
+ CXType_BlockPointer = 102,
+ CXType_LValueReference = 103,
+ CXType_RValueReference = 104,
+ CXType_Record = 105,
+ CXType_Enum = 106,
+ CXType_Typedef = 107,
+ CXType_ObjCInterface = 108,
+ CXType_ObjCObjectPointer = 109,
+ CXType_FunctionNoProto = 110,
+ CXType_FunctionProto = 111
+};
+
+/**
+ * \brief The type of an element in the abstract syntax tree.
+ *
+ */
+typedef struct {
+ enum CXTypeKind kind;
+ void *data[2];
+} CXType;
+
+/**
+ * \brief Retrieve the type of a CXCursor (if any).
+ */
+CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
+
+/**
+ * \determine Determine whether two CXTypes represent the same type.
+ *
+ * \returns non-zero if the CXTypes represent the same type and
+ zero otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
+
+/**
+ * \brief Return the canonical type for a CXType.
+ *
+ * Clang's type system explicitly models typedefs and all the ways
+ * a specific type can be represented. The canonical type is the underlying
+ * type with all the "sugar" removed. For example, if 'T' is a typedef
+ * for 'int', the canonical type for 'T' would be 'int'.
+ */
+CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T);
+
+/**
+ * \determine Determine whether a CXType has the "const" qualifier set,
+ * without looking through typedefs that may have added "const" at a different level.
+ */
+CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T);
+
+/**
+ * \determine Determine whether a CXType has the "volatile" qualifier set,
+ * without looking through typedefs that may have added "volatile" at a different level.
+ */
+CINDEX_LINKAGE unsigned clang_isVolatileQualifiedType(CXType T);
+
+/**
+ * \determine Determine whether a CXType has the "restrict" qualifier set,
+ * without looking through typedefs that may have added "restrict" at a different level.
+ */
+CINDEX_LINKAGE unsigned clang_isRestrictQualifiedType(CXType T);
+
+/**
+ * \brief For pointer types, returns the type of the pointee.
+ *
+ */
+CINDEX_LINKAGE CXType clang_getPointeeType(CXType T);
+
+/**
+ * \brief Return the cursor for the declaration of the given type.
+ */
+CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T);
+
+/**
+ * Returns the Objective-C type encoding for the specified declaration.
+ */
+CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C);
+
+/**
+ * \brief Retrieve the spelling of a given CXTypeKind.
+ */
+CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K);
+
+/**
+ * \brief Retrieve the result type associated with a function type.
+ */
+CINDEX_LINKAGE CXType clang_getResultType(CXType T);
+
+/**
+ * \brief Retrieve the result type associated with a given cursor. This only
+ * returns a valid type of the cursor refers to a function or method.
+ */
+CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
+
+/**
+ * \brief Return 1 if the CXType is a POD (plain old data) type, and 0
+ * otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
+
+/**
+ * \brief Returns 1 if the base class specified by the cursor with kind
+ * CX_CXXBaseSpecifier is virtual.
+ */
+CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
+
+/**
+ * \brief Represents the C++ access control level to a base class for a
+ * cursor with kind CX_CXXBaseSpecifier.
+ */
+enum CX_CXXAccessSpecifier {
+ CX_CXXInvalidAccessSpecifier,
+ CX_CXXPublic,
+ CX_CXXProtected,
+ CX_CXXPrivate
+};
+
+/**
+ * \brief Returns the access control level for the C++ base specifier
+ * represented by a cursor with kind CX_CXXBaseSpecifier.
+ */
+CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
+
+/**
+ * \brief Determine the number of overloaded declarations referenced by a
+ * \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \returns The number of overloaded declarations referenced by \c cursor. If it
+ * is not a \c CXCursor_OverloadedDeclRef cursor, returns 0.
+ */
+CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor);
+
+/**
+ * \brief Retrieve a cursor for one of the overloaded declarations referenced
+ * by a \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \param index The zero-based index into the set of overloaded declarations in
+ * the cursor.
+ *
+ * \returns A cursor representing the declaration referenced by the given
+ * \c cursor at the specified \c index. If the cursor does not have an
+ * associated set of overloaded declarations, or if the index is out of bounds,
+ * returns \c clang_getNullCursor();
+ */
+CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
+ unsigned index);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_ATTRIBUTES Information for attributes
+ *
+ * @{
+ */
+
+
+/**
+ * \brief For cursors representing an iboutletcollection attribute,
+ * this function returns the collection element type.
+ *
+ */
+CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors
+ *
+ * These routines provide the ability to traverse the abstract syntax tree
+ * using cursors.
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes how the traversal of the children of a particular
+ * cursor should proceed after visiting a particular child cursor.
+ *
+ * A value of this enumeration type should be returned by each
+ * \c CXCursorVisitor to indicate how clang_visitChildren() proceed.
+ */
+enum CXChildVisitResult {
+ /**
+ * \brief Terminates the cursor traversal.
+ */
+ CXChildVisit_Break,
+ /**
+ * \brief Continues the cursor traversal with the next sibling of
+ * the cursor just visited, without visiting its children.
+ */
+ CXChildVisit_Continue,
+ /**
+ * \brief Recursively traverse the children of this cursor, using
+ * the same visitor and client data.
+ */
+ CXChildVisit_Recurse
+};
+
+/**
+ * \brief Visitor invoked for each cursor found by a traversal.
+ *
+ * This visitor function will be invoked for each cursor found by
+ * clang_visitCursorChildren(). Its first argument is the cursor being
+ * visited, its second argument is the parent visitor for that cursor,
+ * and its third argument is the client data provided to
+ * clang_visitCursorChildren().
+ *
+ * The visitor should return one of the \c CXChildVisitResult values
+ * to direct clang_visitCursorChildren().
+ */
+typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data);
+
+/**
+ * \brief Visit the children of a particular cursor.
+ *
+ * This function visits all the direct children of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited child. The traversal may be recursive, if the visitor returns
+ * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
+ * the visitor returns \c CXChildVisit_Break.
+ *
+ * \param parent the cursor whose child may be visited. All kinds of
+ * cursors can be visited, including invalid cursors (which, by
+ * definition, have no children).
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * child of \p parent.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXChildVisit_Break.
+ */
+CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
+ CXCursorVisitor visitor,
+ CXClientData client_data);
+#ifdef __has_feature
+# if __has_feature(blocks)
+/**
+ * \brief Visitor invoked for each cursor found by a traversal.
+ *
+ * This visitor block will be invoked for each cursor found by
+ * clang_visitChildrenWithBlock(). Its first argument is the cursor being
+ * visited, its second argument is the parent visitor for that cursor.
+ *
+ * The visitor should return one of the \c CXChildVisitResult values
+ * to direct clang_visitChildrenWithBlock().
+ */
+typedef enum CXChildVisitResult
+ (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent);
+
+/**
+ * Visits the children of a cursor using the specified block. Behaves
+ * identically to clang_visitChildren() in all other respects.
+ */
+unsigned clang_visitChildrenWithBlock(CXCursor parent,
+ CXCursorVisitorBlock block);
+# endif
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CURSOR_XREF Cross-referencing in the AST
+ *
+ * These routines provide the ability to determine references within and
+ * across translation units, by providing the names of the entities referenced
+ * by cursors, follow reference cursors to the declarations they reference,
+ * and associate declarations with their definitions.
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced
+ * by the given cursor.
+ *
+ * A Unified Symbol Resolution (USR) is a string that identifies a particular
+ * entity (function, class, variable, etc.) within a program. USRs can be
+ * compared across translation units to determine, e.g., when references in
+ * one translation refer to an entity defined in another translation unit.
+ */
+CINDEX_LINKAGE CXString clang_getCursorUSR(CXCursor);
+
+/**
+ * \brief Construct a USR for a specified Objective-C class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name);
+
+/**
+ * \brief Construct a USR for a specified Objective-C category.
+ */
+CINDEX_LINKAGE CXString
+ clang_constructUSR_ObjCCategory(const char *class_name,
+ const char *category_name);
+
+/**
+ * \brief Construct a USR for a specified Objective-C protocol.
+ */
+CINDEX_LINKAGE CXString
+ clang_constructUSR_ObjCProtocol(const char *protocol_name);
+
+
+/**
+ * \brief Construct a USR for a specified Objective-C instance variable and
+ * the USR for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCIvar(const char *name,
+ CXString classUSR);
+
+/**
+ * \brief Construct a USR for a specified Objective-C method and
+ * the USR for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCMethod(const char *name,
+ unsigned isInstanceMethod,
+ CXString classUSR);
+
+/**
+ * \brief Construct a USR for a specified Objective-C property and the USR
+ * for its containing class.
+ */
+CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property,
+ CXString classUSR);
+
+/**
+ * \brief Retrieve a name for the entity referenced by this cursor.
+ */
+CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
+
+/**
+ * \brief Retrieve the display name for the entity referenced by this cursor.
+ *
+ * The display name contains extra information that helps identify the cursor,
+ * such as the parameters of a function or template or the arguments of a
+ * class template specialization.
+ */
+CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor);
+
+/** \brief For a cursor that is a reference, retrieve a cursor representing the
+ * entity that it references.
+ *
+ * Reference cursors refer to other entities in the AST. For example, an
+ * Objective-C superclass reference cursor refers to an Objective-C class.
+ * This function produces the cursor for the Objective-C class from the
+ * cursor for the superclass reference. If the input cursor is a declaration or
+ * definition, it returns that declaration or definition unchanged.
+ * Otherwise, returns the NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
+
+/**
+ * \brief For a cursor that is either a reference to or a declaration
+ * of some entity, retrieve a cursor that describes the definition of
+ * that entity.
+ *
+ * Some entities can be declared multiple times within a translation
+ * unit, but only one of those declarations can also be a
+ * definition. For example, given:
+ *
+ * \code
+ * int f(int, int);
+ * int g(int x, int y) { return f(x, y); }
+ * int f(int a, int b) { return a + b; }
+ * int f(int, int);
+ * \endcode
+ *
+ * there are three declarations of the function "f", but only the
+ * second one is a definition. The clang_getCursorDefinition()
+ * function will take any cursor pointing to a declaration of "f"
+ * (the first or fourth lines of the example) or a cursor referenced
+ * that uses "f" (the call to "f' inside "g") and will return a
+ * declaration cursor pointing to the definition (the second "f"
+ * declaration).
+ *
+ * If given a cursor for which there is no corresponding definition,
+ * e.g., because there is no definition of that entity within this
+ * translation unit, returns a NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor);
+
+/**
+ * \brief Determine whether the declaration pointed to by this cursor
+ * is also a definition of that entity.
+ */
+CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
+
+/**
+ * \brief Retrieve the canonical cursor corresponding to the given cursor.
+ *
+ * In the C family of languages, many kinds of entities can be declared several
+ * times within a single translation unit. For example, a structure type can
+ * be forward-declared (possibly multiple times) and later defined:
+ *
+ * \code
+ * struct X;
+ * struct X;
+ * struct X {
+ * int member;
+ * };
+ * \endcode
+ *
+ * The declarations and the definition of \c X are represented by three
+ * different cursors, all of which are declarations of the same underlying
+ * entity. One of these cursor is considered the "canonical" cursor, which
+ * is effectively the representative for the underlying entity. One can
+ * determine if two cursors are declarations of the same underlying entity by
+ * comparing their canonical cursors.
+ *
+ * \returns The canonical cursor for the entity referred to by the given cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CPP C++ AST introspection
+ *
+ * The routines in this group provide access information in the ASTs specific
+ * to C++ language features.
+ *
+ * @{
+ */
+
+/**
+ * \brief Determine if a C++ member function or member function template is
+ * declared 'static'.
+ */
+CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a template, determine
+ * the cursor kind of the specializations would be generated by instantiating
+ * the template.
+ *
+ * This routine can be used to determine what flavor of function template,
+ * class template, or class template partial specialization is stored in the
+ * cursor. For example, it can describe whether a class template cursor is
+ * declared with "struct", "class" or "union".
+ *
+ * \param C The cursor to query. This cursor should represent a template
+ * declaration.
+ *
+ * \returns The cursor kind of the specializations that would be generated
+ * by instantiating the template \p C. If \p C is not a template, returns
+ * \c CXCursor_NoDeclFound.
+ */
+CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
+
+/**
+ * \brief Given a cursor that may represent a specialization or instantiation
+ * of a template, retrieve the cursor that represents the template that it
+ * specializes or from which it was instantiated.
+ *
+ * This routine determines the template involved both for explicit
+ * specializations of templates and for implicit instantiations of the template,
+ * both of which are referred to as "specializations". For a class template
+ * specialization (e.g., \c std::vector<bool>), this routine will return
+ * either the primary template (\c std::vector) or, if the specialization was
+ * instantiated from a class template partial specialization, the class template
+ * partial specialization. For a class template partial specialization and a
+ * function template specialization (including instantiations), this
+ * this routine will return the specialized template.
+ *
+ * For members of a class template (e.g., member functions, member classes, or
+ * static data members), returns the specialized or instantiated member.
+ * Although not strictly "templates" in the C++ language, members of class
+ * templates have the same notions of specializations and instantiations that
+ * templates do, so this routine treats them similarly.
+ *
+ * \param C A cursor that may be a specialization of a template or a member
+ * of a template.
+ *
+ * \returns If the given cursor is a specialization or instantiation of a
+ * template or a member thereof, the template or member that it specializes or
+ * from which it was instantiated. Otherwise, returns a NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_LEX Token extraction and manipulation
+ *
+ * The routines in this group provide access to the tokens within a
+ * translation unit, along with a semantic mapping of those tokens to
+ * their corresponding cursors.
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes a kind of token.
+ */
+typedef enum CXTokenKind {
+ /**
+ * \brief A token that contains some kind of punctuation.
+ */
+ CXToken_Punctuation,
+
+ /**
+ * \brief A language keyword.
+ */
+ CXToken_Keyword,
+
+ /**
+ * \brief An identifier (that is not a keyword).
+ */
+ CXToken_Identifier,
+
+ /**
+ * \brief A numeric, string, or character literal.
+ */
+ CXToken_Literal,
+
+ /**
+ * \brief A comment.
+ */
+ CXToken_Comment
+} CXTokenKind;
+
+/**
+ * \brief Describes a single preprocessing token.
+ */
+typedef struct {
+ unsigned int_data[4];
+ void *ptr_data;
+} CXToken;
+
+/**
+ * \brief Determine the kind of the given token.
+ */
+CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
+
+/**
+ * \brief Determine the spelling of the given token.
+ *
+ * The spelling of a token is the textual representation of that token, e.g.,
+ * the text of an identifier or keyword.
+ */
+CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
+
+/**
+ * \brief Retrieve the source location of the given token.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
+ CXToken);
+
+/**
+ * \brief Retrieve a source range that covers the given token.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
+
+/**
+ * \brief Tokenize the source code described by the given range into raw
+ * lexical tokens.
+ *
+ * \param TU the translation unit whose text is being tokenized.
+ *
+ * \param Range the source range in which text should be tokenized. All of the
+ * tokens produced by tokenization will fall within this source range,
+ *
+ * \param Tokens this pointer will be set to point to the array of tokens
+ * that occur within the given source range. The returned pointer must be
+ * freed with clang_disposeTokens() before the translation unit is destroyed.
+ *
+ * \param NumTokens will be set to the number of tokens in the \c *Tokens
+ * array.
+ *
+ */
+CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
+ CXToken **Tokens, unsigned *NumTokens);
+
+/**
+ * \brief Annotate the given set of tokens by providing cursors for each token
+ * that can be mapped to a specific entity within the abstract syntax tree.
+ *
+ * This token-annotation routine is equivalent to invoking
+ * clang_getCursor() for the source locations of each of the
+ * tokens. The cursors provided are filtered, so that only those
+ * cursors that have a direct correspondence to the token are
+ * accepted. For example, given a function call \c f(x),
+ * clang_getCursor() would provide the following cursors:
+ *
+ * * when the cursor is over the 'f', a DeclRefExpr cursor referring to 'f'.
+ * * when the cursor is over the '(' or the ')', a CallExpr referring to 'f'.
+ * * when the cursor is over the 'x', a DeclRefExpr cursor referring to 'x'.
+ *
+ * Only the first and last of these cursors will occur within the
+ * annotate, since the tokens "f" and "x' directly refer to a function
+ * and a variable, respectively, but the parentheses are just a small
+ * part of the full syntax of the function call expression, which is
+ * not provided as an annotation.
+ *
+ * \param TU the translation unit that owns the given tokens.
+ *
+ * \param Tokens the set of tokens to annotate.
+ *
+ * \param NumTokens the number of tokens in \p Tokens.
+ *
+ * \param Cursors an array of \p NumTokens cursors, whose contents will be
+ * replaced with the cursors corresponding to each token.
+ */
+CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors);
+
+/**
+ * \brief Free the given set of tokens.
+ */
+CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_DEBUG Debugging facilities
+ *
+ * These routines are used for testing and debugging, only, and should not
+ * be relied upon.
+ *
+ * @{
+ */
+
+/* for debug/testing */
+CINDEX_LINKAGE CXString clang_getCursorKindSpelling(enum CXCursorKind Kind);
+CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
+ const char **startBuf,
+ const char **endBuf,
+ unsigned *startLine,
+ unsigned *startColumn,
+ unsigned *endLine,
+ unsigned *endColumn);
+CINDEX_LINKAGE void clang_enableStackTraces(void);
+CINDEX_LINKAGE void clang_executeOnThread(void (*fn)(void*), void *user_data,
+ unsigned stack_size);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_CODE_COMPLET Code completion
+ *
+ * Code completion involves taking an (incomplete) source file, along with
+ * knowledge of where the user is actively editing that file, and suggesting
+ * syntactically- and semantically-valid constructs that the user might want to
+ * use at that particular point in the source code. These data structures and
+ * routines provide support for code completion.
+ *
+ * @{
+ */
+
+/**
+ * \brief A semantic string that describes a code-completion result.
+ *
+ * A semantic string that describes the formatting of a code-completion
+ * result as a single "template" of text that should be inserted into the
+ * source buffer when a particular code-completion result is selected.
+ * Each semantic string is made up of some number of "chunks", each of which
+ * contains some text along with a description of what that text means, e.g.,
+ * the name of the entity being referenced, whether the text chunk is part of
+ * the template, or whether it is a "placeholder" that the user should replace
+ * with actual code,of a specific kind. See \c CXCompletionChunkKind for a
+ * description of the different kinds of chunks.
+ */
+typedef void *CXCompletionString;
+
+/**
+ * \brief A single result of code completion.
+ */
+typedef struct {
+ /**
+ * \brief The kind of entity that this completion refers to.
+ *
+ * The cursor kind will be a macro, keyword, or a declaration (one of the
+ * *Decl cursor kinds), describing the entity that the completion is
+ * referring to.
+ *
+ * \todo In the future, we would like to provide a full cursor, to allow
+ * the client to extract additional information from declaration.
+ */
+ enum CXCursorKind CursorKind;
+
+ /**
+ * \brief The code-completion string that describes how to insert this
+ * code-completion result into the editing buffer.
+ */
+ CXCompletionString CompletionString;
+} CXCompletionResult;
+
+/**
+ * \brief Describes a single piece of text within a code-completion string.
+ *
+ * Each "chunk" within a code-completion string (\c CXCompletionString) is
+ * either a piece of text with a specific "kind" that describes how that text
+ * should be interpreted by the client or is another completion string.
+ */
+enum CXCompletionChunkKind {
+ /**
+ * \brief A code-completion string that describes "optional" text that
+ * could be a part of the template (but is not required).
+ *
+ * The Optional chunk is the only kind of chunk that has a code-completion
+ * string for its representation, which is accessible via
+ * \c clang_getCompletionChunkCompletionString(). The code-completion string
+ * describes an additional part of the template that is completely optional.
+ * For example, optional chunks can be used to describe the placeholders for
+ * arguments that match up with defaulted function parameters, e.g. given:
+ *
+ * \code
+ * void f(int x, float y = 3.14, double z = 2.71828);
+ * \endcode
+ *
+ * The code-completion string for this function would contain:
+ * - a TypedText chunk for "f".
+ * - a LeftParen chunk for "(".
+ * - a Placeholder chunk for "int x"
+ * - an Optional chunk containing the remaining defaulted arguments, e.g.,
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "float y"
+ * - an Optional chunk containing the last defaulted argument:
+ * - a Comma chunk for ","
+ * - a Placeholder chunk for "double z"
+ * - a RightParen chunk for ")"
+ *
+ * There are many ways to handle Optional chunks. Two simple approaches are:
+ * - Completely ignore optional chunks, in which case the template for the
+ * function "f" would only include the first parameter ("int x").
+ * - Fully expand all optional chunks, in which case the template for the
+ * function "f" would have all of the parameters.
+ */
+ CXCompletionChunk_Optional,
+ /**
+ * \brief Text that a user would be expected to type to get this
+ * code-completion result.
+ *
+ * There will be exactly one "typed text" chunk in a semantic string, which
+ * will typically provide the spelling of a keyword or the name of a
+ * declaration that could be used at the current code point. Clients are
+ * expected to filter the code-completion results based on the text in this
+ * chunk.
+ */
+ CXCompletionChunk_TypedText,
+ /**
+ * \brief Text that should be inserted as part of a code-completion result.
+ *
+ * A "text" chunk represents text that is part of the template to be
+ * inserted into user code should this particular code-completion result
+ * be selected.
+ */
+ CXCompletionChunk_Text,
+ /**
+ * \brief Placeholder text that should be replaced by the user.
+ *
+ * A "placeholder" chunk marks a place where the user should insert text
+ * into the code-completion template. For example, placeholders might mark
+ * the function parameters for a function declaration, to indicate that the
+ * user should provide arguments for each of those parameters. The actual
+ * text in a placeholder is a suggestion for the text to display before
+ * the user replaces the placeholder with real code.
+ */
+ CXCompletionChunk_Placeholder,
+ /**
+ * \brief Informative text that should be displayed but never inserted as
+ * part of the template.
+ *
+ * An "informative" chunk contains annotations that can be displayed to
+ * help the user decide whether a particular code-completion result is the
+ * right option, but which is not part of the actual template to be inserted
+ * by code completion.
+ */
+ CXCompletionChunk_Informative,
+ /**
+ * \brief Text that describes the current parameter when code-completion is
+ * referring to function call, message send, or template specialization.
+ *
+ * A "current parameter" chunk occurs when code-completion is providing
+ * information about a parameter corresponding to the argument at the
+ * code-completion point. For example, given a function
+ *
+ * \code
+ * int add(int x, int y);
+ * \endcode
+ *
+ * and the source code \c add(, where the code-completion point is after the
+ * "(", the code-completion string will contain a "current parameter" chunk
+ * for "int x", indicating that the current argument will initialize that
+ * parameter. After typing further, to \c add(17, (where the code-completion
+ * point is after the ","), the code-completion string will contain a
+ * "current paremeter" chunk to "int y".
+ */
+ CXCompletionChunk_CurrentParameter,
+ /**
+ * \brief A left parenthesis ('('), used to initiate a function call or
+ * signal the beginning of a function parameter list.
+ */
+ CXCompletionChunk_LeftParen,
+ /**
+ * \brief A right parenthesis (')'), used to finish a function call or
+ * signal the end of a function parameter list.
+ */
+ CXCompletionChunk_RightParen,
+ /**
+ * \brief A left bracket ('[').
+ */
+ CXCompletionChunk_LeftBracket,
+ /**
+ * \brief A right bracket (']').
+ */
+ CXCompletionChunk_RightBracket,
+ /**
+ * \brief A left brace ('{').
+ */
+ CXCompletionChunk_LeftBrace,
+ /**
+ * \brief A right brace ('}').
+ */
+ CXCompletionChunk_RightBrace,
+ /**
+ * \brief A left angle bracket ('<').
+ */
+ CXCompletionChunk_LeftAngle,
+ /**
+ * \brief A right angle bracket ('>').
+ */
+ CXCompletionChunk_RightAngle,
+ /**
+ * \brief A comma separator (',').
+ */
+ CXCompletionChunk_Comma,
+ /**
+ * \brief Text that specifies the result type of a given result.
+ *
+ * This special kind of informative chunk is not meant to be inserted into
+ * the text buffer. Rather, it is meant to illustrate the type that an
+ * expression using the given completion string would have.
+ */
+ CXCompletionChunk_ResultType,
+ /**
+ * \brief A colon (':').
+ */
+ CXCompletionChunk_Colon,
+ /**
+ * \brief A semicolon (';').
+ */
+ CXCompletionChunk_SemiColon,
+ /**
+ * \brief An '=' sign.
+ */
+ CXCompletionChunk_Equal,
+ /**
+ * Horizontal space (' ').
+ */
+ CXCompletionChunk_HorizontalSpace,
+ /**
+ * Vertical space ('\n'), after which it is generally a good idea to
+ * perform indentation.
+ */
+ CXCompletionChunk_VerticalSpace
+};
+
+/**
+ * \brief Determine the kind of a particular chunk within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the kind of the chunk at the index \c chunk_number.
+ */
+CINDEX_LINKAGE enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the text associated with a particular chunk within a
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the text associated with the chunk at index \c chunk_number.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the completion string associated with a particular chunk
+ * within a completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param chunk_number the 0-based index of the chunk in the completion string.
+ *
+ * \returns the completion string associated with the chunk at index
+ * \c chunk_number, or NULL if that chunk is not represented by a completion
+ * string.
+ */
+CINDEX_LINKAGE CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number);
+
+/**
+ * \brief Retrieve the number of chunks in the given code-completion string.
+ */
+CINDEX_LINKAGE unsigned
+clang_getNumCompletionChunks(CXCompletionString completion_string);
+
+/**
+ * \brief Determine the priority of this code completion.
+ *
+ * The priority of a code completion indicates how likely it is that this
+ * particular completion is the completion that the user will select. The
+ * priority is selected by various internal heuristics.
+ *
+ * \param completion_string The completion string to query.
+ *
+ * \returns The priority of this completion string. Smaller values indicate
+ * higher-priority (more likely) completions.
+ */
+CINDEX_LINKAGE unsigned
+clang_getCompletionPriority(CXCompletionString completion_string);
+
+/**
+ * \brief Determine the availability of the entity that this code-completion
+ * string refers to.
+ *
+ * \param completion_string The completion string to query.
+ *
+ * \returns The availability of the completion string.
+ */
+CINDEX_LINKAGE enum CXAvailabilityKind
+clang_getCompletionAvailability(CXCompletionString completion_string);
+
+/**
+ * \brief Contains the results of code-completion.
+ *
+ * This data structure contains the results of code completion, as
+ * produced by \c clang_codeCompleteAt(). Its contents must be freed by
+ * \c clang_disposeCodeCompleteResults.
+ */
+typedef struct {
+ /**
+ * \brief The code-completion results.
+ */
+ CXCompletionResult *Results;
+
+ /**
+ * \brief The number of code-completion results stored in the
+ * \c Results array.
+ */
+ unsigned NumResults;
+} CXCodeCompleteResults;
+
+/**
+ * \brief Flags that can be passed to \c clang_codeCompleteAt() to
+ * modify its behavior.
+ *
+ * The enumerators in this enumeration can be bitwise-OR'd together to
+ * provide multiple options to \c clang_codeCompleteAt().
+ */
+enum CXCodeComplete_Flags {
+ /**
+ * \brief Whether to include macros within the set of code
+ * completions returned.
+ */
+ CXCodeComplete_IncludeMacros = 0x01,
+
+ /**
+ * \brief Whether to include code patterns for language constructs
+ * within the set of code completions, e.g., for loops.
+ */
+ CXCodeComplete_IncludeCodePatterns = 0x02
+};
+
+/**
+ * \brief Returns a default set of code-completion options that can be
+ * passed to\c clang_codeCompleteAt().
+ */
+CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
+
+/**
+ * \brief Perform code completion at a given location in a translation unit.
+ *
+ * This function performs code completion at a particular file, line, and
+ * column within source code, providing results that suggest potential
+ * code snippets based on the context of the completion. The basic model
+ * for code completion is that Clang will parse a complete source file,
+ * performing syntax checking up to the location where code-completion has
+ * been requested. At that point, a special code-completion token is passed
+ * to the parser, which recognizes this token and determines, based on the
+ * current location in the C/Objective-C/C++ grammar and the state of
+ * semantic analysis, what completions to provide. These completions are
+ * returned via a new \c CXCodeCompleteResults structure.
+ *
+ * Code completion itself is meant to be triggered by the client when the
+ * user types punctuation characters or whitespace, at which point the
+ * code-completion location will coincide with the cursor. For example, if \c p
+ * is a pointer, code-completion might be triggered after the "-" and then
+ * after the ">" in \c p->. When the code-completion location is afer the ">",
+ * the completion results will provide, e.g., the members of the struct that
+ * "p" points to. The client is responsible for placing the cursor at the
+ * beginning of the token currently being typed, then filtering the results
+ * based on the contents of the token. For example, when code-completing for
+ * the expression \c p->get, the client should provide the location just after
+ * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the
+ * client can filter the results based on the current token text ("get"), only
+ * showing those results that start with "get". The intent of this interface
+ * is to separate the relatively high-latency acquisition of code-completion
+ * results from the filtering of results on a per-character basis, which must
+ * have a lower latency.
+ *
+ * \param TU The translation unit in which code-completion should
+ * occur. The source files for this translation unit need not be
+ * completely up-to-date (and the contents of those source files may
+ * be overridden via \p unsaved_files). Cursors referring into the
+ * translation unit may be invalidated by this invocation.
+ *
+ * \param complete_filename The name of the source file where code
+ * completion should be performed. This filename may be any file
+ * included in the translation unit.
+ *
+ * \param complete_line The line at which code-completion should occur.
+ *
+ * \param complete_column The column at which code-completion should occur.
+ * Note that the column should point just after the syntactic construct that
+ * initiated code completion, and not in the middle of a lexical token.
+ *
+ * \param unsaved_files the Tiles that have not yet been saved to disk
+ * but may be required for parsing or code completion, including the
+ * contents of those files. The contents and name of these files (as
+ * specified by CXUnsavedFile) are copied when necessary, so the
+ * client only needs to guarantee their validity until the call to
+ * this function returns.
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options Extra options that control the behavior of code
+ * completion, expressed as a bitwise OR of the enumerators of the
+ * CXCodeComplete_Flags enumeration. The
+ * \c clang_defaultCodeCompleteOptions() function returns a default set
+ * of code-completion options.
+ *
+ * \returns If successful, a new \c CXCodeCompleteResults structure
+ * containing code-completion results, which should eventually be
+ * freed with \c clang_disposeCodeCompleteResults(). If code
+ * completion fails, returns NULL.
+ */
+CINDEX_LINKAGE
+CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options);
+
+/**
+ * \brief Sort the code-completion results in case-insensitive alphabetical
+ * order.
+ *
+ * \param Results The set of results to sort.
+ * \param NumResults The number of results in \p Results.
+ */
+CINDEX_LINKAGE
+void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+ unsigned NumResults);
+
+/**
+ * \brief Free the given set of code-completion results.
+ */
+CINDEX_LINKAGE
+void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
+
+/**
+ * \brief Determine the number of diagnostics produced prior to the
+ * location where code completion was performed.
+ */
+CINDEX_LINKAGE
+unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
+
+/**
+ * \brief Retrieve a diagnostic associated with the given code completion.
+ *
+ * \param Result the code completion results to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+CINDEX_LINKAGE
+CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
+ unsigned Index);
+
+/**
+ * @}
+ */
+
+
+/**
+ * \defgroup CINDEX_MISC Miscellaneous utility functions
+ *
+ * @{
+ */
+
+/**
+ * \brief Return a version string, suitable for showing to a user, but not
+ * intended to be parsed (the format is not guaranteed to be stable).
+ */
+CINDEX_LINKAGE CXString clang_getClangVersion();
+
+ /**
+ * \brief Visitor invoked for each file in a translation unit
+ * (used with clang_getInclusions()).
+ *
+ * This visitor function will be invoked by clang_getInclusions() for each
+ * file included (either at the top-level or by #include directives) within
+ * a translation unit. The first argument is the file being included, and
+ * the second and third arguments provide the inclusion stack. The
+ * array is sorted in order of immediate inclusion. For example,
+ * the first element refers to the location that included 'included_file'.
+ */
+typedef void (*CXInclusionVisitor)(CXFile included_file,
+ CXSourceLocation* inclusion_stack,
+ unsigned include_len,
+ CXClientData client_data);
+
+/**
+ * \brief Visit the set of preprocessor inclusions in a translation unit.
+ * The visitor function is called with the provided data for every included
+ * file. This does not include headers included by the PCH file (unless one
+ * is inspecting the inclusions in the PCH file itself).
+ */
+CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu,
+ CXInclusionVisitor visitor,
+ CXClientData client_data);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/APValue.h b/contrib/llvm/tools/clang/include/clang/AST/APValue.h
new file mode 100644
index 0000000..5effa90
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h
@@ -0,0 +1,243 @@
+//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_APVALUE_H
+#define LLVM_CLANG_AST_APVALUE_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/APFloat.h"
+
+namespace clang {
+ class CharUnits;
+ class Expr;
+
+/// APValue - This class implements a discriminated union of [uninitialized]
+/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
+class APValue {
+ typedef llvm::APSInt APSInt;
+ typedef llvm::APFloat APFloat;
+public:
+ enum ValueKind {
+ Uninitialized,
+ Int,
+ Float,
+ ComplexInt,
+ ComplexFloat,
+ LValue,
+ Vector
+ };
+private:
+ ValueKind Kind;
+
+ struct ComplexAPSInt {
+ APSInt Real, Imag;
+ ComplexAPSInt() : Real(1), Imag(1) {}
+ };
+ struct ComplexAPFloat {
+ APFloat Real, Imag;
+ ComplexAPFloat() : Real(0.0), Imag(0.0) {}
+ };
+
+ struct Vec {
+ APValue *Elts;
+ unsigned NumElts;
+ Vec() : Elts(0), NumElts(0) {}
+ ~Vec() { delete[] Elts; }
+ };
+
+ enum {
+ MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
+ sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
+ };
+
+ union {
+ void *Aligner;
+ char Data[MaxSize];
+ };
+
+public:
+ APValue() : Kind(Uninitialized) {}
+ explicit APValue(const APSInt &I) : Kind(Uninitialized) {
+ MakeInt(); setInt(I);
+ }
+ explicit APValue(const APFloat &F) : Kind(Uninitialized) {
+ MakeFloat(); setFloat(F);
+ }
+ explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
+ MakeVector(); setVector(E, N);
+ }
+ APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
+ MakeComplexInt(); setComplexInt(R, I);
+ }
+ APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
+ MakeComplexFloat(); setComplexFloat(R, I);
+ }
+ APValue(const APValue &RHS) : Kind(Uninitialized) {
+ *this = RHS;
+ }
+ APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, O);
+ }
+ APValue(Expr* B);
+
+ ~APValue() {
+ MakeUninit();
+ }
+
+ ValueKind getKind() const { return Kind; }
+ bool isUninit() const { return Kind == Uninitialized; }
+ bool isInt() const { return Kind == Int; }
+ bool isFloat() const { return Kind == Float; }
+ bool isComplexInt() const { return Kind == ComplexInt; }
+ bool isComplexFloat() const { return Kind == ComplexFloat; }
+ bool isLValue() const { return Kind == LValue; }
+ bool isVector() const { return Kind == Vector; }
+
+ void print(llvm::raw_ostream &OS) const;
+ void dump() const;
+
+ APSInt &getInt() {
+ assert(isInt() && "Invalid accessor");
+ return *(APSInt*)(char*)Data;
+ }
+ const APSInt &getInt() const {
+ return const_cast<APValue*>(this)->getInt();
+ }
+
+ APFloat &getFloat() {
+ assert(isFloat() && "Invalid accessor");
+ return *(APFloat*)(char*)Data;
+ }
+ const APFloat &getFloat() const {
+ return const_cast<APValue*>(this)->getFloat();
+ }
+
+ APValue &getVectorElt(unsigned i) {
+ assert(isVector() && "Invalid accessor");
+ return ((Vec*)(char*)Data)->Elts[i];
+ }
+ const APValue &getVectorElt(unsigned i) const {
+ assert(isVector() && "Invalid accessor");
+ return ((const Vec*)(const char*)Data)->Elts[i];
+ }
+ unsigned getVectorLength() const {
+ assert(isVector() && "Invalid accessor");
+ return ((const Vec*)(const void *)Data)->NumElts;
+ }
+
+ APSInt &getComplexIntReal() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(char*)Data)->Real;
+ }
+ const APSInt &getComplexIntReal() const {
+ return const_cast<APValue*>(this)->getComplexIntReal();
+ }
+
+ APSInt &getComplexIntImag() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(char*)Data)->Imag;
+ }
+ const APSInt &getComplexIntImag() const {
+ return const_cast<APValue*>(this)->getComplexIntImag();
+ }
+
+ APFloat &getComplexFloatReal() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(char*)Data)->Real;
+ }
+ const APFloat &getComplexFloatReal() const {
+ return const_cast<APValue*>(this)->getComplexFloatReal();
+ }
+
+ APFloat &getComplexFloatImag() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(char*)Data)->Imag;
+ }
+ const APFloat &getComplexFloatImag() const {
+ return const_cast<APValue*>(this)->getComplexFloatImag();
+ }
+
+ Expr* getLValueBase() const;
+ CharUnits getLValueOffset() const;
+
+ void setInt(const APSInt &I) {
+ assert(isInt() && "Invalid accessor");
+ *(APSInt*)(char*)Data = I;
+ }
+ void setFloat(const APFloat &F) {
+ assert(isFloat() && "Invalid accessor");
+ *(APFloat*)(char*)Data = F;
+ }
+ void setVector(const APValue *E, unsigned N) {
+ assert(isVector() && "Invalid accessor");
+ ((Vec*)(char*)Data)->Elts = new APValue[N];
+ ((Vec*)(char*)Data)->NumElts = N;
+ for (unsigned i = 0; i != N; ++i)
+ ((Vec*)(char*)Data)->Elts[i] = E[i];
+ }
+ void setComplexInt(const APSInt &R, const APSInt &I) {
+ assert(R.getBitWidth() == I.getBitWidth() &&
+ "Invalid complex int (type mismatch).");
+ assert(isComplexInt() && "Invalid accessor");
+ ((ComplexAPSInt*)(char*)Data)->Real = R;
+ ((ComplexAPSInt*)(char*)Data)->Imag = I;
+ }
+ void setComplexFloat(const APFloat &R, const APFloat &I) {
+ assert(&R.getSemantics() == &I.getSemantics() &&
+ "Invalid complex float (type mismatch).");
+ assert(isComplexFloat() && "Invalid accessor");
+ ((ComplexAPFloat*)(char*)Data)->Real = R;
+ ((ComplexAPFloat*)(char*)Data)->Imag = I;
+ }
+ void setLValue(Expr *B, const CharUnits &O);
+
+ const APValue &operator=(const APValue &RHS);
+
+private:
+ void MakeUninit();
+ void MakeInt() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)Data) APSInt(1);
+ Kind = Int;
+ }
+ void MakeFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) APFloat(0.0);
+ Kind = Float;
+ }
+ void MakeVector() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) Vec();
+ Kind = Vector;
+ }
+ void MakeComplexInt() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) ComplexAPSInt();
+ Kind = ComplexInt;
+ }
+ void MakeComplexFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) ComplexAPFloat();
+ Kind = ComplexFloat;
+ }
+ void MakeLValue();
+};
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
+ V.print(OS);
+ return OS;
+}
+
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/AST.h b/contrib/llvm/tools/clang/include/clang/AST/AST.h
new file mode 100644
index 0000000..164c5fb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/AST.h
@@ -0,0 +1,28 @@
+//===--- AST.h - "Umbrella" header for AST library --------------*- 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 interface to the AST classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_AST_H
+#define LLVM_CLANG_AST_AST_H
+
+// This header exports all AST interfaces.
+#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/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/StmtVisitor.h"
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
new file mode 100644
index 0000000..08ee4ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
@@ -0,0 +1,108 @@
+//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- 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 ASTConsumer class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
+#define LLVM_CLANG_AST_ASTCONSUMER_H
+
+namespace clang {
+ class ASTContext;
+ class CXXRecordDecl;
+ class DeclGroupRef;
+ class HandleTagDeclDefinition;
+ class ASTMutationListener;
+ class ASTDeserializationListener; // layering violation because void* is ugly
+ class SemaConsumer; // layering violation required for safe SemaConsumer
+ class TagDecl;
+ class VarDecl;
+
+/// ASTConsumer - This is an abstract interface that should be implemented by
+/// clients that read ASTs. This abstraction layer allows the client to be
+/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
+class ASTConsumer {
+ /// \brief Whether this AST consumer also requires information about
+ /// semantic analysis.
+ bool SemaConsumer;
+
+ friend class SemaConsumer;
+
+public:
+ ASTConsumer() : SemaConsumer(false) { }
+
+ virtual ~ASTConsumer() {}
+
+ /// Initialize - This is called to initialize the consumer, providing the
+ /// ASTContext.
+ virtual void Initialize(ASTContext &Context) {}
+
+ /// HandleTopLevelDecl - Handle the specified top-level declaration. This is
+ /// called by the parser to process every top-level Decl*. Note that D can be
+ /// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
+ /// elements). Use Decl::getNextDeclarator() to walk the chain.
+ virtual void HandleTopLevelDecl(DeclGroupRef D);
+
+ /// HandleInterestingDecl - Handle the specified interesting declaration. This
+ /// is called by the AST reader when deserializing things that might interest
+ /// the consumer. The default implementation forwards to HandleTopLevelDecl.
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+
+ /// HandleTranslationUnit - This method is called when the ASTs for entire
+ /// translation unit have been parsed.
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {}
+
+ /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
+ /// (e.g. struct, union, enum, class) is completed. This allows the client to
+ /// hack on the type, which can occur at any point in the file (because these
+ /// can be defined in declspecs).
+ virtual void HandleTagDeclDefinition(TagDecl *D) {}
+
+ /// CompleteTentativeDefinition - Callback invoked at the end of a translation
+ /// unit to notify the consumer that the given tentative definition should be
+ /// completed.
+ ///
+ /// The variable declaration itself will be a tentative
+ /// definition. If it had an incomplete array type, its type will
+ /// have already been changed to an array of size 1. However, the
+ /// declaration remains a tentative definition and has not been
+ /// modified by the introduction of an implicit zero initializer.
+ virtual void CompleteTentativeDefinition(VarDecl *D) {}
+
+ /// \brief Callback involved at the end of a translation unit to
+ /// notify the consumer that a vtable for the given C++ class is
+ /// required.
+ ///
+ /// \param RD The class whose vtable was used.
+ ///
+ /// \param DefinitionRequired Whether a definition of this vtable is
+ /// required in this translation unit; otherwise, it is only needed if
+ /// it was actually used.
+ virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
+
+ /// \brief If the consumer is interested in entities getting modified after
+ /// their initial creation, it should return a pointer to
+ /// a GetASTMutationListener here.
+ virtual ASTMutationListener *GetASTMutationListener() { return 0; }
+
+ /// \brief If the consumer is interested in entities being deserialized from
+ /// AST files, it should return a pointer to a ASTDeserializationListener here
+ virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
+
+ /// PrintStats - If desired, print any statistics.
+ virtual void PrintStats() {}
+
+ // Support isa/cast/dyn_cast
+ static bool classof(const ASTConsumer *) { return true; }
+};
+
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
new file mode 100644
index 0000000..0e88713
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -0,0 +1,1623 @@
+//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- 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 ASTContext interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
+#define LLVM_CLANG_AST_ASTCONTEXT_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/UsuallyTinyPtrVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+ struct fltSemantics;
+ class raw_ostream;
+}
+
+namespace clang {
+ class FileManager;
+ class ASTRecordLayout;
+ class BlockExpr;
+ class CharUnits;
+ class Diagnostic;
+ class Expr;
+ class ExternalASTSource;
+ class ASTMutationListener;
+ class IdentifierTable;
+ class SelectorTable;
+ class SourceManager;
+ class TargetInfo;
+ class CXXABI;
+ // Decls
+ class DeclContext;
+ class CXXMethodDecl;
+ class CXXRecordDecl;
+ class Decl;
+ class FieldDecl;
+ class MangleContext;
+ class ObjCIvarDecl;
+ class ObjCIvarRefExpr;
+ class ObjCPropertyDecl;
+ class RecordDecl;
+ class StoredDeclsMap;
+ class TagDecl;
+ class TemplateTemplateParmDecl;
+ class TemplateTypeParmDecl;
+ class TranslationUnitDecl;
+ class TypeDecl;
+ class TypedefDecl;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class UnresolvedSetIterator;
+
+ namespace Builtin { class Context; }
+
+/// ASTContext - This class holds long-lived AST nodes (such as types and
+/// decls) that can be referred to throughout the semantic analysis of a file.
+class ASTContext {
+ ASTContext &this_() { return *this; }
+
+ mutable std::vector<Type*> Types;
+ mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
+ mutable llvm::FoldingSet<ComplexType> ComplexTypes;
+ mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
+ mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
+ mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
+ mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
+ mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
+ mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
+ mutable std::vector<VariableArrayType*> VariableArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
+ mutable llvm::FoldingSet<DependentSizedExtVectorType>
+ DependentSizedExtVectorTypes;
+ mutable llvm::FoldingSet<VectorType> VectorTypes;
+ mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
+ mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+ mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
+ mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
+ mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmType>
+ SubstTemplateTypeParmTypes;
+ mutable llvm::FoldingSet<SubstTemplateTypeParmPackType>
+ SubstTemplateTypeParmPackTypes;
+ mutable llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&>
+ TemplateSpecializationTypes;
+ mutable llvm::FoldingSet<ParenType> ParenTypes;
+ mutable llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
+ mutable llvm::FoldingSet<DependentNameType> DependentNameTypes;
+ mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
+ ASTContext&>
+ DependentTemplateSpecializationTypes;
+ llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
+ mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
+ mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ llvm::FoldingSet<AttributedType> AttributedTypes;
+
+ mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
+ mutable llvm::FoldingSet<SubstTemplateTemplateParmPackStorage>
+ SubstTemplateTemplateParmPacks;
+
+ /// \brief The set of nested name specifiers.
+ ///
+ /// This set is managed by the NestedNameSpecifier class.
+ mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
+ mutable NestedNameSpecifier *GlobalNestedNameSpecifier;
+ friend class NestedNameSpecifier;
+
+ /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
+ /// This is lazily created. This is intentionally not serialized.
+ mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>
+ ASTRecordLayouts;
+ mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>
+ ObjCLayouts;
+
+ /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions.
+ llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions;
+
+ /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+
+ /// \brief Mapping from __block VarDecls to their copy initialization expr.
+ llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
+
+ /// \brief Representation of a "canonical" template template parameter that
+ /// is used in canonical template names.
+ class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
+ TemplateTemplateParmDecl *Parm;
+
+ public:
+ CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm)
+ : Parm(Parm) { }
+
+ TemplateTemplateParmDecl *getParam() const { return Parm; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ TemplateTemplateParmDecl *Parm);
+ };
+ mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
+ CanonTemplateTemplateParms;
+
+ TemplateTemplateParmDecl *
+ getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const;
+
+ /// \brief Whether __[u]int128_t identifier is installed.
+ bool IsInt128Installed;
+
+ /// BuiltinVaListType - built-in va list type.
+ /// This is initially null and set by Sema::LazilyCreateBuiltin when
+ /// a builtin that takes a valist is encountered.
+ QualType BuiltinVaListType;
+
+ /// ObjCIdType - a pseudo built-in typedef type (set by Sema).
+ QualType ObjCIdTypedefType;
+
+ /// ObjCSelType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCSelTypedefType;
+
+ /// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCProtoType;
+ const RecordType *ProtoStructType;
+
+ /// ObjCClassType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCClassTypedefType;
+
+ QualType ObjCConstantStringType;
+ mutable RecordDecl *CFConstantStringTypeDecl;
+
+ mutable RecordDecl *NSConstantStringTypeDecl;
+
+ mutable RecordDecl *ObjCFastEnumerationStateTypeDecl;
+
+ /// \brief The type for the C FILE type.
+ TypeDecl *FILEDecl;
+
+ /// \brief The type for the C jmp_buf type.
+ TypeDecl *jmp_bufDecl;
+
+ /// \brief The type for the C sigjmp_buf type.
+ TypeDecl *sigjmp_bufDecl;
+
+ /// \brief Type for the Block descriptor for Blocks CodeGen.
+ mutable RecordDecl *BlockDescriptorType;
+
+ /// \brief Type for the Block descriptor for Blocks CodeGen.
+ mutable RecordDecl *BlockDescriptorExtendedType;
+
+ /// \brief Declaration for the CUDA cudaConfigureCall function.
+ FunctionDecl *cudaConfigureCallDecl;
+
+ TypeSourceInfo NullTypeSourceInfo;
+
+ /// \brief Keeps track of all declaration attributes.
+ ///
+ /// Since so few decls have attrs, we keep them in a hash map instead of
+ /// wasting space in the Decl class.
+ llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
+
+ /// \brief Keeps track of the static data member templates from which
+ /// static data members of class template specializations were instantiated.
+ ///
+ /// This data structure stores the mapping from instantiations of static
+ /// data members to the static data member representations within the
+ /// class template from which they were instantiated along with the kind
+ /// of instantiation or specialization (a TemplateSpecializationKind - 1).
+ ///
+ /// Given the following example:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// static T value;
+ /// };
+ ///
+ /// template<typename T>
+ /// T X<T>::value = T(17);
+ ///
+ /// int *x = &X<int>::value;
+ /// \endcode
+ ///
+ /// This mapping will contain an entry that maps from the VarDecl for
+ /// X<int>::value to the corresponding VarDecl for X<T>::value (within the
+ /// class template X) and will be marked TSK_ImplicitInstantiation.
+ llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
+ InstantiatedFromStaticDataMember;
+
+ /// \brief Keeps track of the declaration from which a UsingDecl was
+ /// created during instantiation. The source declaration is always
+ /// a UsingDecl, an UnresolvedUsingValueDecl, or an
+ /// UnresolvedUsingTypenameDecl.
+ ///
+ /// For example:
+ /// \code
+ /// template<typename T>
+ /// struct A {
+ /// void f();
+ /// };
+ ///
+ /// template<typename T>
+ /// struct B : A<T> {
+ /// using A<T>::f;
+ /// };
+ ///
+ /// template struct B<int>;
+ /// \endcode
+ ///
+ /// This mapping will contain an entry that maps from the UsingDecl in
+ /// B<int> to the UnresolvedUsingDecl in B<T>.
+ llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl;
+
+ llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>
+ InstantiatedFromUsingShadowDecl;
+
+ llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
+
+ /// \brief Mapping that stores the methods overridden by a given C++
+ /// member function.
+ ///
+ /// Since most C++ member functions aren't virtual and therefore
+ /// don't override anything, we store the overridden functions in
+ /// this map on the side rather than within the CXXMethodDecl structure.
+ typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector;
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
+
+ TranslationUnitDecl *TUDecl;
+
+ /// SourceMgr - The associated SourceManager object.
+ SourceManager &SourceMgr;
+
+ /// LangOpts - The language options used to create the AST associated with
+ /// this ASTContext object.
+ LangOptions LangOpts;
+
+ /// \brief The allocator used to create AST objects.
+ ///
+ /// AST objects are never destructed; rather, all memory associated with the
+ /// AST objects will be released when the ASTContext itself is destroyed.
+ mutable llvm::BumpPtrAllocator BumpAlloc;
+
+ /// \brief Allocator for partial diagnostics.
+ PartialDiagnostic::StorageAllocator DiagAllocator;
+
+ /// \brief The current C++ ABI.
+ llvm::OwningPtr<CXXABI> ABI;
+ CXXABI *createCXXABI(const TargetInfo &T);
+
+ friend class ASTDeclReader;
+
+public:
+ const TargetInfo &Target;
+ IdentifierTable &Idents;
+ SelectorTable &Selectors;
+ Builtin::Context &BuiltinInfo;
+ mutable DeclarationNameTable DeclarationNames;
+ llvm::OwningPtr<ExternalASTSource> ExternalSource;
+ ASTMutationListener *Listener;
+ clang::PrintingPolicy PrintingPolicy;
+
+ // Typedefs which may be provided defining the structure of Objective-C
+ // pseudo-builtins
+ QualType ObjCIdRedefinitionType;
+ QualType ObjCClassRedefinitionType;
+ QualType ObjCSelRedefinitionType;
+
+ SourceManager& getSourceManager() { return SourceMgr; }
+ const SourceManager& getSourceManager() const { return SourceMgr; }
+ void *Allocate(unsigned Size, unsigned Align = 8) const {
+ return BumpAlloc.Allocate(Size, Align);
+ }
+ void Deallocate(void *Ptr) const { }
+
+ PartialDiagnostic::StorageAllocator &getDiagAllocator() {
+ return DiagAllocator;
+ }
+
+ const LangOptions& getLangOptions() const { return LangOpts; }
+
+ Diagnostic &getDiagnostics() const;
+
+ FullSourceLoc getFullLoc(SourceLocation Loc) const {
+ return FullSourceLoc(Loc,SourceMgr);
+ }
+
+ /// \brief Retrieve the attributes for the given declaration.
+ AttrVec& getDeclAttrs(const Decl *D);
+
+ /// \brief Erase the attributes corresponding to the given declaration.
+ void eraseDeclAttrs(const Decl *D);
+
+ /// \brief If this variable is an instantiated static data member of a
+ /// class template specialization, returns the templated static data member
+ /// from which it was instantiated.
+ MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
+ const VarDecl *Var);
+
+ /// \brief Note that the static data member \p Inst is an instantiation of
+ /// the static data member template \p Tmpl of a class template.
+ void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
+ TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation = SourceLocation());
+
+ /// \brief If the given using decl is an instantiation of a
+ /// (possibly unresolved) using decl from a template instantiation,
+ /// return it.
+ NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
+
+ /// \brief Remember that the using decl \p Inst is an instantiation
+ /// of the using decl \p Pattern of a class template.
+ void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern);
+
+ void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+ UsingShadowDecl *Pattern);
+ UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst);
+
+ FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);
+
+ void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
+
+ // Access to the set of methods overridden by the given C++ method.
+ typedef CXXMethodVector::iterator overridden_cxx_method_iterator;
+ overridden_cxx_method_iterator
+ overridden_methods_begin(const CXXMethodDecl *Method) const;
+
+ overridden_cxx_method_iterator
+ overridden_methods_end(const CXXMethodDecl *Method) const;
+
+ unsigned overridden_methods_size(const CXXMethodDecl *Method) const;
+
+ /// \brief Note that the given C++ \p Method overrides the given \p
+ /// Overridden method.
+ void addOverriddenMethod(const CXXMethodDecl *Method,
+ const CXXMethodDecl *Overridden);
+
+ TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
+
+
+ // Builtin Types.
+ CanQualType VoidTy;
+ CanQualType BoolTy;
+ CanQualType CharTy;
+ CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
+ CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
+ CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
+ CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
+ CanQualType FloatTy, DoubleTy, LongDoubleTy;
+ CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
+ CanQualType VoidPtrTy, NullPtrTy;
+ CanQualType OverloadTy;
+ CanQualType DependentTy;
+ CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
+
+ ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
+ IdentifierTable &idents, SelectorTable &sels,
+ Builtin::Context &builtins,
+ unsigned size_reserve);
+
+ ~ASTContext();
+
+ /// \brief Attach an external AST source to the AST context.
+ ///
+ /// The external AST source provides the ability to load parts of
+ /// the abstract syntax tree as needed from some external storage,
+ /// e.g., a precompiled header.
+ void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source);
+
+ /// \brief Retrieve a pointer to the external AST source associated
+ /// with this AST context, if any.
+ ExternalASTSource *getExternalSource() const { return ExternalSource.get(); }
+
+ /// \brief Attach an AST mutation listener to the AST context.
+ ///
+ /// The AST mutation listener provides the ability to track modifications to
+ /// the abstract syntax tree entities committed after they were initially
+ /// created.
+ void setASTMutationListener(ASTMutationListener *Listener) {
+ this->Listener = Listener;
+ }
+
+ /// \brief Retrieve a pointer to the AST mutation listener associated
+ /// with this AST context, if any.
+ ASTMutationListener *getASTMutationListener() const { return Listener; }
+
+ void PrintStats() const;
+ const std::vector<Type*>& getTypes() const { return Types; }
+
+ //===--------------------------------------------------------------------===//
+ // Type Constructors
+ //===--------------------------------------------------------------------===//
+
+private:
+ /// getExtQualType - Return a type with extended qualifiers.
+ QualType getExtQualType(const Type *Base, Qualifiers Quals) const;
+
+ QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
+
+public:
+ /// getAddSpaceQualType - Return the uniqued reference to the type for an
+ /// address space qualified type with the specified type and address space.
+ /// The resulting type has a union of the qualifiers from T and the address
+ /// space. If T already has an address space specifier, it is silently
+ /// replaced.
+ QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const;
+
+ /// getObjCGCQualType - Returns the uniqued reference to the type for an
+ /// objc gc qualified type. The retulting type has a union of the qualifiers
+ /// from T and the gc attribute.
+ QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const;
+
+ /// getRestrictType - Returns the uniqued reference to the type for a
+ /// 'restrict' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'restrict'.
+ QualType getRestrictType(QualType T) const {
+ return T.withFastQualifiers(Qualifiers::Restrict);
+ }
+
+ /// getVolatileType - Returns the uniqued reference to the type for a
+ /// 'volatile' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'volatile'.
+ QualType getVolatileType(QualType T) const {
+ return T.withFastQualifiers(Qualifiers::Volatile);
+ }
+
+ /// getConstType - Returns the uniqued reference to the type for a
+ /// 'const' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'const'.
+ ///
+ /// It can be reasonably expected that this will always be
+ /// equivalent to calling T.withConst().
+ QualType getConstType(QualType T) const { return T.withConst(); }
+
+ /// adjustFunctionType - Change the ExtInfo on a function type.
+ const FunctionType *adjustFunctionType(const FunctionType *Fn,
+ FunctionType::ExtInfo EInfo);
+
+ /// getComplexType - Return the uniqued reference to the type for a complex
+ /// number with the specified element type.
+ QualType getComplexType(QualType T) const;
+ CanQualType getComplexType(CanQualType T) const {
+ return CanQualType::CreateUnsafe(getComplexType((QualType) T));
+ }
+
+ /// getPointerType - Return the uniqued reference to the type for a pointer to
+ /// the specified type.
+ QualType getPointerType(QualType T) const;
+ CanQualType getPointerType(CanQualType T) const {
+ return CanQualType::CreateUnsafe(getPointerType((QualType) T));
+ }
+
+ /// getBlockPointerType - Return the uniqued reference to the type for a block
+ /// of the specified type.
+ QualType getBlockPointerType(QualType T) const;
+
+ /// This gets the struct used to keep track of the descriptor for pointer to
+ /// blocks.
+ QualType getBlockDescriptorType() const;
+
+ // Set the type for a Block descriptor type.
+ void setBlockDescriptorType(QualType T);
+ /// Get the BlockDescriptorType type, or NULL if it hasn't yet been built.
+ QualType getRawBlockdescriptorType() {
+ if (BlockDescriptorType)
+ return getTagDeclType(BlockDescriptorType);
+ return QualType();
+ }
+
+ /// This gets the struct used to keep track of the extended descriptor for
+ /// pointer to blocks.
+ QualType getBlockDescriptorExtendedType() const;
+
+ // Set the type for a Block descriptor extended type.
+ void setBlockDescriptorExtendedType(QualType T);
+ /// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been
+ /// built.
+ QualType getRawBlockdescriptorExtendedType() const {
+ if (BlockDescriptorExtendedType)
+ return getTagDeclType(BlockDescriptorExtendedType);
+ return QualType();
+ }
+
+ void setcudaConfigureCallDecl(FunctionDecl *FD) {
+ cudaConfigureCallDecl = FD;
+ }
+ FunctionDecl *getcudaConfigureCallDecl() {
+ return cudaConfigureCallDecl;
+ }
+
+ /// This gets the struct used to keep track of pointer to blocks, complete
+ /// with captured variables.
+ QualType getBlockParmType(bool BlockHasCopyDispose,
+ llvm::SmallVectorImpl<const Expr *> &Layout) const;
+
+ /// This builds the struct used for __block variables.
+ QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
+
+ /// Returns true iff we need copy/dispose helpers for the given type.
+ bool BlockRequiresCopying(QualType Ty) const;
+
+ /// getLValueReferenceType - Return the uniqued reference to the type for an
+ /// lvalue reference to the specified type.
+ QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
+ const;
+
+ /// getRValueReferenceType - Return the uniqued reference to the type for an
+ /// rvalue reference to the specified type.
+ QualType getRValueReferenceType(QualType T) const;
+
+ /// getMemberPointerType - Return the uniqued reference to the type for a
+ /// member pointer to the specified type in the specified class. The class
+ /// is a Type because it could be a dependent name.
+ QualType getMemberPointerType(QualType T, const Type *Cls) const;
+
+ /// getVariableArrayType - Returns a non-unique reference to the type for a
+ /// variable array of the specified element type.
+ QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
+
+ /// getDependentSizedArrayType - Returns a non-unique reference to
+ /// the type for a dependently-sized array of the specified element
+ /// type. FIXME: We will need these to be uniqued, or at least
+ /// comparable, at some point.
+ QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals,
+ SourceRange Brackets) const;
+
+ /// getIncompleteArrayType - Returns a unique reference to the type for a
+ /// incomplete array of the specified element type.
+ QualType getIncompleteArrayType(QualType EltTy,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals) const;
+
+ /// getConstantArrayType - Return the unique reference to the type for a
+ /// constant array of the specified element type.
+ QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals) const;
+
+ /// getVariableArrayDecayedType - Returns a vla type where known sizes
+ /// are replaced with [*].
+ QualType getVariableArrayDecayedType(QualType Ty) const;
+
+ /// getVectorType - Return the unique reference to a vector type of
+ /// the specified element type and size. VectorType must be a built-in type.
+ QualType getVectorType(QualType VectorType, unsigned NumElts,
+ VectorType::VectorKind VecKind) const;
+
+ /// 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 getExtVectorType(QualType VectorType, unsigned NumElts) const;
+
+ /// getDependentSizedExtVectorType - Returns a non-unique reference to
+ /// the type for a dependently-sized vector of the specified element
+ /// type. FIXME: We will need these to be uniqued, or at least
+ /// comparable, at some point.
+ QualType getDependentSizedExtVectorType(QualType VectorType,
+ Expr *SizeExpr,
+ SourceLocation AttrLoc) const;
+
+ /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
+ ///
+ QualType getFunctionNoProtoType(QualType ResultTy,
+ const FunctionType::ExtInfo &Info) const;
+
+ QualType getFunctionNoProtoType(QualType ResultTy) const {
+ return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo());
+ }
+
+ /// getFunctionType - Return a normal function type with a typed
+ /// argument list.
+ QualType getFunctionType(QualType ResultTy,
+ const QualType *Args, unsigned NumArgs,
+ const FunctionProtoType::ExtProtoInfo &EPI) const;
+
+ /// getTypeDeclType - Return the unique reference to the type for
+ /// the specified type declaration.
+ QualType getTypeDeclType(const TypeDecl *Decl,
+ const TypeDecl *PrevDecl = 0) const {
+ assert(Decl && "Passed null for Decl param");
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (PrevDecl) {
+ assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl");
+ Decl->TypeForDecl = PrevDecl->TypeForDecl;
+ return QualType(PrevDecl->TypeForDecl, 0);
+ }
+
+ return getTypeDeclTypeSlow(Decl);
+ }
+
+ /// getTypedefType - Return the unique reference to the type for the
+ /// specified typename decl.
+ QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType())
+ const;
+
+ QualType getRecordType(const RecordDecl *Decl) const;
+
+ QualType getEnumType(const EnumDecl *Decl) const;
+
+ QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
+
+ QualType getAttributedType(AttributedType::Kind attrKind,
+ QualType modifiedType,
+ QualType equivalentType);
+
+ QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
+ QualType Replacement) const;
+ QualType getSubstTemplateTypeParmPackType(
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
+
+ QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ bool ParameterPack,
+ IdentifierInfo *Name = 0) const;
+
+ QualType getTemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ QualType Canon = QualType()) const;
+
+ QualType getCanonicalTemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs) const;
+
+ QualType getTemplateSpecializationType(TemplateName T,
+ const TemplateArgumentListInfo &Args,
+ QualType Canon = QualType()) const;
+
+ TypeSourceInfo *
+ getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
+ const TemplateArgumentListInfo &Args,
+ QualType Canon = QualType()) const;
+
+ QualType getParenType(QualType NamedType) const;
+
+ QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ QualType NamedType) const;
+ QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ QualType Canon = QualType()) const;
+
+ QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ const TemplateArgumentListInfo &Args) const;
+ QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args) const;
+
+ QualType getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions);
+
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const;
+
+ QualType getObjCObjectType(QualType Base,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) const;
+
+ /// getObjCObjectPointerType - Return a ObjCObjectPointerType type
+ /// for the given ObjCObjectType.
+ QualType getObjCObjectPointerType(QualType OIT) const;
+
+ /// getTypeOfType - GCC extension.
+ QualType getTypeOfExprType(Expr *e) const;
+ QualType getTypeOfType(QualType t) const;
+
+ /// getDecltypeType - C++0x decltype.
+ QualType getDecltypeType(Expr *e) const;
+
+ /// getAutoType - C++0x deduced auto type.
+ QualType getAutoType(QualType DeducedType) const;
+
+ /// getTagDeclType - Return the unique reference to the type for the
+ /// specified TagDecl (struct/union/class/enum) decl.
+ QualType getTagDeclType(const TagDecl *Decl) const;
+
+ /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
+ /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
+ CanQualType getSizeType() const;
+
+ /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this
+ /// returns a type compatible with the type defined in <stddef.h> as defined
+ /// by the target.
+ QualType getWCharType() const { return WCharTy; }
+
+ /// getSignedWCharType - Return the type of "signed wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getSignedWCharType() const;
+
+ /// getUnsignedWCharType - Return the type of "unsigned wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getUnsignedWCharType() const;
+
+ /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+ /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+ QualType getPointerDiffType() const;
+
+ // getCFConstantStringType - Return the C structure type used to represent
+ // constant CFStrings.
+ QualType getCFConstantStringType() const;
+
+ // getNSConstantStringType - Return the C structure type used to represent
+ // constant NSStrings.
+ QualType getNSConstantStringType() const;
+ /// Get the structure type used to representation NSStrings, or NULL
+ /// if it hasn't yet been built.
+ QualType getRawNSConstantStringType() const {
+ if (NSConstantStringTypeDecl)
+ return getTagDeclType(NSConstantStringTypeDecl);
+ return QualType();
+ }
+ void setNSConstantStringType(QualType T);
+
+
+ /// Get the structure type used to representation CFStrings, or NULL
+ /// if it hasn't yet been built.
+ QualType getRawCFConstantStringType() const {
+ if (CFConstantStringTypeDecl)
+ return getTagDeclType(CFConstantStringTypeDecl);
+ return QualType();
+ }
+ void setCFConstantStringType(QualType T);
+
+ // This setter/getter represents the ObjC type for an NSConstantString.
+ void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl);
+ QualType getObjCConstantStringInterface() const {
+ return ObjCConstantStringType;
+ }
+
+ //// This gets the struct used to keep track of fast enumerations.
+ QualType getObjCFastEnumerationStateType() const;
+
+ /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
+ /// been built.
+ QualType getRawObjCFastEnumerationStateType() const {
+ if (ObjCFastEnumerationStateTypeDecl)
+ return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
+ return QualType();
+ }
+
+ void setObjCFastEnumerationStateType(QualType T);
+
+ /// \brief Set the type for the C FILE type.
+ void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; }
+
+ /// \brief Retrieve the C FILE type.
+ QualType getFILEType() const {
+ if (FILEDecl)
+ return getTypeDeclType(FILEDecl);
+ return QualType();
+ }
+
+ /// \brief Set the type for the C jmp_buf type.
+ void setjmp_bufDecl(TypeDecl *jmp_bufDecl) {
+ this->jmp_bufDecl = jmp_bufDecl;
+ }
+
+ /// \brief Retrieve the C jmp_buf type.
+ QualType getjmp_bufType() const {
+ if (jmp_bufDecl)
+ return getTypeDeclType(jmp_bufDecl);
+ return QualType();
+ }
+
+ /// \brief Set the type for the C sigjmp_buf type.
+ void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) {
+ this->sigjmp_bufDecl = sigjmp_bufDecl;
+ }
+
+ /// \brief Retrieve the C sigjmp_buf type.
+ QualType getsigjmp_bufType() const {
+ if (sigjmp_bufDecl)
+ return getTypeDeclType(sigjmp_bufDecl);
+ return QualType();
+ }
+
+ /// \brief The result type of logical operations, '<', '>', '!=', etc.
+ QualType getLogicalOperationType() const {
+ return getLangOptions().CPlusPlus ? BoolTy : IntTy;
+ }
+
+ /// getObjCEncodingForType - Emit the ObjC type encoding for the
+ /// given type into \arg S. If \arg NameFields is specified then
+ /// record field names are also encoded.
+ void getObjCEncodingForType(QualType t, std::string &S,
+ const FieldDecl *Field=0) const;
+
+ void getLegacyIntegralTypeEncoding(QualType &t) const;
+
+ // Put the string version of type qualifiers into S.
+ void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
+ std::string &S) const;
+
+ /// getObjCEncodingForFunctionDecl - Returns the encoded type for this
+ //function. This is in the same format as Objective-C method encodings.
+ void getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
+
+ /// getObjCEncodingForMethodDecl - Return the encoded type for this method
+ /// declaration.
+ void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
+ const;
+
+ /// getObjCEncodingForBlock - Return the encoded type for this block
+ /// declaration.
+ std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
+
+ /// getObjCEncodingForPropertyDecl - Return the encoded type for
+ /// this method declaration. If non-NULL, Container must be either
+ /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
+ /// only be NULL when getting encodings for protocol properties.
+ void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container,
+ std::string &S) const;
+
+ bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+ ObjCProtocolDecl *rProto) const;
+
+ /// getObjCEncodingTypeSize returns size of type for objective-c encoding
+ /// purpose in characters.
+ CharUnits getObjCEncodingTypeSize(QualType t) const;
+
+ /// \brief Whether __[u]int128_t identifier is installed.
+ bool isInt128Installed() const { return IsInt128Installed; }
+ void setInt128Installed() { IsInt128Installed = true; }
+
+ /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
+ /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
+ QualType getObjCIdType() const { return ObjCIdTypedefType; }
+ void setObjCIdType(QualType T);
+
+ void setObjCSelType(QualType T);
+ QualType getObjCSelType() const { return ObjCSelTypedefType; }
+
+ void setObjCProtoType(QualType QT);
+ QualType getObjCProtoType() const { return ObjCProtoType; }
+
+ /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
+ /// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
+ /// struct.
+ QualType getObjCClassType() const { return ObjCClassTypedefType; }
+ void setObjCClassType(QualType T);
+
+ void setBuiltinVaListType(QualType T);
+ QualType getBuiltinVaListType() const { return BuiltinVaListType; }
+
+ /// getCVRQualifiedType - Returns a type with additional const,
+ /// volatile, or restrict qualifiers.
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) const {
+ return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(QualType T, Qualifiers Qs) const {
+ if (!Qs.hasNonFastQualifiers())
+ return T.withFastQualifiers(Qs.getFastQualifiers());
+ QualifierCollector Qc(Qs);
+ const Type *Ptr = Qc.strip(T);
+ return getExtQualType(Ptr, Qc);
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(const Type *T, Qualifiers Qs) const {
+ if (!Qs.hasNonFastQualifiers())
+ return QualType(T, Qs.getFastQualifiers());
+ return getExtQualType(T, Qs);
+ }
+
+ DeclarationNameInfo getNameForTemplate(TemplateName Name,
+ SourceLocation NameLoc) const;
+
+ TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) const;
+
+ TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ bool TemplateKeyword,
+ TemplateDecl *Template) const;
+
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name) const;
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator) const;
+ TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+ const TemplateArgument &ArgPack) const;
+
+ enum GetBuiltinTypeError {
+ GE_None, //< No error
+ GE_Missing_stdio, //< Missing a type from <stdio.h>
+ GE_Missing_setjmp //< Missing a type from <setjmp.h>
+ };
+
+ /// GetBuiltinType - Return the type for the specified builtin. If
+ /// IntegerConstantArgs is non-null, it is filled in with a bitmask of
+ /// arguments to the builtin that are required to be integer constant
+ /// expressions.
+ QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
+ unsigned *IntegerConstantArgs = 0) const;
+
+private:
+ CanQualType getFromTargetType(unsigned Type) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Predicates.
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
+ /// garbage collection attribute.
+ ///
+ Qualifiers::GC getObjCGCAttrKind(QualType Ty) const;
+
+ /// areCompatibleVectorTypes - Return true if the given vector types
+ /// are of the same unqualified type or if they are equivalent to the same
+ /// GCC vector type, ignoring whether they are target-specific (AltiVec or
+ /// Neon) types.
+ bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+
+ /// isObjCNSObjectType - Return true if this is an NSObject object with
+ /// its NSObject attribute set.
+ bool isObjCNSObjectType(QualType Ty) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Sizing and Analysis
+ //===--------------------------------------------------------------------===//
+
+ /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
+ /// scalar floating point type.
+ const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
+
+ /// getTypeInfo - Get the size and alignment of the specified complete type in
+ /// bits.
+ std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const;
+ std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const {
+ return getTypeInfo(T.getTypePtr());
+ }
+
+ /// getTypeSize - Return the size of the specified type, in bits. This method
+ /// does not work on incomplete types.
+ uint64_t getTypeSize(QualType T) const {
+ return getTypeInfo(T).first;
+ }
+ uint64_t getTypeSize(const Type *T) const {
+ return getTypeInfo(T).first;
+ }
+
+ /// getCharWidth - Return the size of the character type, in bits
+ uint64_t getCharWidth() const {
+ return getTypeSize(CharTy);
+ }
+
+ /// toCharUnitsFromBits - Convert a size in bits to a size in characters.
+ CharUnits toCharUnitsFromBits(int64_t BitSize) const;
+
+ /// toBits - Convert a size in characters to a size in bits.
+ int64_t toBits(CharUnits CharSize) const;
+
+ /// getTypeSizeInChars - Return the size of the specified type, in characters.
+ /// This method does not work on incomplete types.
+ CharUnits getTypeSizeInChars(QualType T) const;
+ CharUnits getTypeSizeInChars(const Type *T) const;
+
+ /// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
+ /// This method does not work on incomplete types.
+ unsigned getTypeAlign(QualType T) const {
+ return getTypeInfo(T).second;
+ }
+ unsigned getTypeAlign(const Type *T) const {
+ return getTypeInfo(T).second;
+ }
+
+ /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
+ /// characters. This method does not work on incomplete types.
+ CharUnits getTypeAlignInChars(QualType T) const;
+ CharUnits getTypeAlignInChars(const Type *T) const;
+
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
+
+ /// 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 getPreferredTypeAlign(const Type *T) const;
+
+ /// getDeclAlign - Return a conservative estimate of the alignment of
+ /// the specified decl. Note that bitfields do not have a valid alignment, so
+ /// 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 getDeclAlign(const Decl *D, bool RefAsPointee = false) const;
+
+ /// getASTRecordLayout - Get or compute information about the layout of the
+ /// specified record (struct/union/class), which indicates its size and field
+ /// position information.
+ const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
+
+ /// getASTObjCInterfaceLayout - Get or compute information about the
+ /// layout of the specified Objective-C interface.
+ const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D)
+ const;
+
+ void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS) const;
+
+ /// getASTObjCImplementationLayout - Get or compute information about
+ /// the layout of the specified Objective-C implementation. This may
+ /// differ from the interface if synthesized ivars are present.
+ const ASTRecordLayout &
+ getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const;
+
+ /// getKeyFunction - Get the key function for the given record decl, or NULL
+ /// if there isn't one. The key function is, according to the Itanium C++ ABI
+ /// section 5.2.3:
+ ///
+ /// ...the first non-pure virtual function that is not inline at the point
+ /// of class definition.
+ const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
+
+ bool isNearlyEmpty(const CXXRecordDecl *RD) const;
+
+ MangleContext *createMangleContext();
+
+ void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars)
+ const;
+
+ void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const;
+
+ unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
+ void CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
+
+ //===--------------------------------------------------------------------===//
+ // Type Operators
+ //===--------------------------------------------------------------------===//
+
+ /// 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 getCanonicalType(QualType T) const {
+ return CanQualType::CreateUnsafe(T.getCanonicalType());
+ }
+
+ const Type *getCanonicalType(const Type *T) const {
+ return T->getCanonicalTypeInternal().getTypePtr();
+ }
+
+ /// getCanonicalParamType - Return the canonical parameter type
+ /// corresponding to the specific potentially non-canonical one.
+ /// Qualifiers are stripped off, functions are turned into function
+ /// pointers, and arrays decay one level into pointers.
+ CanQualType getCanonicalParamType(QualType T) const;
+
+ /// \brief Determine whether the given types are equivalent.
+ bool hasSameType(QualType T1, QualType T2) {
+ return getCanonicalType(T1) == getCanonicalType(T2);
+ }
+
+ /// \brief Returns this type as a completely-unqualified array type,
+ /// capturing the qualifiers in Quals. This will remove the minimal amount of
+ /// sugaring from the types, similar to the behavior of
+ /// QualType::getUnqualifiedType().
+ ///
+ /// \param T is the qualified type, which may be an ArrayType
+ ///
+ /// \param Quals will receive the full set of qualifiers that were
+ /// applied to the array.
+ ///
+ /// \returns if this is an array type, the completely unqualified array type
+ /// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
+ QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
+
+ /// \brief Determine whether the given types are equivalent after
+ /// cvr-qualifiers have been removed.
+ bool hasSameUnqualifiedType(QualType T1, QualType T2) {
+ return getCanonicalType(T1).getTypePtr() ==
+ getCanonicalType(T2).getTypePtr();
+ }
+
+ bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
+
+ /// \brief Retrieves the "canonical" nested name specifier for a
+ /// given nested name specifier.
+ ///
+ /// The canonical nested name specifier is a nested name specifier
+ /// that uniquely identifies a type or namespace within the type
+ /// system. For example, given:
+ ///
+ /// \code
+ /// namespace N {
+ /// struct S {
+ /// template<typename T> struct X { typename T* type; };
+ /// };
+ /// }
+ ///
+ /// template<typename T> struct Y {
+ /// typename N::S::X<T>::type member;
+ /// };
+ /// \endcode
+ ///
+ /// Here, the nested-name-specifier for N::S::X<T>:: will be
+ /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined
+ /// by declarations in the type system and the canonical type for
+ /// the template type parameter 'T' is template-param-0-0.
+ NestedNameSpecifier *
+ getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const;
+
+ /// \brief Retrieves the default calling convention to use for
+ /// C++ instance methods.
+ CallingConv getDefaultMethodCallConv();
+
+ /// \brief Retrieves the canonical representation of the given
+ /// calling convention.
+ CallingConv getCanonicalCallConv(CallingConv CC) const {
+ if (CC == CC_C)
+ return CC_Default;
+ return CC;
+ }
+
+ /// \brief Determines whether two calling conventions name the same
+ /// calling convention.
+ bool isSameCallConv(CallingConv lcc, CallingConv rcc) {
+ return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
+ }
+
+ /// \brief Retrieves the "canonical" template name that refers to a
+ /// given template.
+ ///
+ /// The canonical template name is the simplest expression that can
+ /// be used to refer to a given template. For most templates, this
+ /// expression is just the template declaration itself. For example,
+ /// the template std::vector can be referred to via a variety of
+ /// names---std::vector, ::std::vector, vector (if vector is in
+ /// scope), etc.---but all of these names map down to the same
+ /// TemplateDecl, which is used to form the canonical template name.
+ ///
+ /// Dependent template names are more interesting. Here, the
+ /// template name could be something like T::template apply or
+ /// std::allocator<T>::template rebind, where the nested name
+ /// specifier itself is dependent. In this case, the canonical
+ /// template name uses the shortest form of the dependent
+ /// nested-name-specifier, which itself contains all canonical
+ /// types, values, and templates.
+ TemplateName getCanonicalTemplateName(TemplateName Name) const;
+
+ /// \brief Determine whether the given template names refer to the same
+ /// template.
+ bool hasSameTemplateName(TemplateName X, TemplateName Y);
+
+ /// \brief Retrieve the "canonical" template argument.
+ ///
+ /// The canonical template argument is the simplest template argument
+ /// (which may be a type, value, expression, or declaration) that
+ /// expresses the value of the argument.
+ TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
+ const;
+
+ /// Type Query functions. If the type is an instance of the specified class,
+ /// return the Type pointer for the underlying maximally pretty type. This
+ /// is a member of ASTContext because this may need to do some amount of
+ /// canonicalization, e.g. to move type qualifiers into the element type.
+ const ArrayType *getAsArrayType(QualType T) const;
+ const ConstantArrayType *getAsConstantArrayType(QualType T) const {
+ return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
+ }
+ const VariableArrayType *getAsVariableArrayType(QualType T) const {
+ return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
+ }
+ const IncompleteArrayType *getAsIncompleteArrayType(QualType T) const {
+ return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
+ }
+ const DependentSizedArrayType *getAsDependentSizedArrayType(QualType T)
+ const {
+ return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T));
+ }
+
+ /// getBaseElementType - Returns the innermost element type of an array type.
+ /// For example, will return "int" for int[m][n]
+ QualType getBaseElementType(const ArrayType *VAT) const;
+
+ /// getBaseElementType - Returns the innermost element type of a type
+ /// (which needn't actually be an array type).
+ QualType getBaseElementType(QualType QT) const;
+
+ /// getConstantArrayElementCount - Returns number of constant array elements.
+ uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
+
+ /// 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 getArrayDecayedType(QualType T) const;
+
+ /// getPromotedIntegerType - Returns the type that Promotable will
+ /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
+ /// integer type.
+ QualType getPromotedIntegerType(QualType PromotableType) const;
+
+ /// \brief Whether this is a promotable bitfield reference according
+ /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
+ ///
+ /// \returns the type this bit-field will promote to, or NULL if no
+ /// promotion occurs.
+ QualType isPromotableBitField(Expr *E) const;
+
+ /// 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 getIntegerTypeOrder(QualType LHS, QualType RHS) const;
+
+ /// getFloatingTypeOrder - Compare the rank of the two specified floating
+ /// 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 getFloatingTypeOrder(QualType LHS, QualType RHS) const;
+
+ /// getFloatingTypeOfSizeWithinDomain - Returns a real floating
+ /// point or a complex type (based on typeDomain/typeSize).
+ /// 'typeDomain' is a real floating point or complex type.
+ /// 'typeSize' is a real floating point or complex type.
+ QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
+ QualType typeDomain) const;
+
+private:
+ // Helper for integer ordering
+ unsigned getIntegerRank(const Type *T) const;
+
+public:
+
+ //===--------------------------------------------------------------------===//
+ // Type Compatibility Predicates
+ //===--------------------------------------------------------------------===//
+
+ /// Compatibility predicates used to check assignment expressions.
+ bool typesAreCompatible(QualType T1, QualType T2,
+ bool CompareUnqualified = false); // C99 6.2.7p1
+
+ bool typesAreBlockPointerCompatible(QualType, QualType);
+
+ bool isObjCIdType(QualType T) const {
+ return T == ObjCIdTypedefType;
+ }
+ bool isObjCClassType(QualType T) const {
+ return T == ObjCClassTypedefType;
+ }
+ bool isObjCSelType(QualType T) const {
+ return T == ObjCSelTypedefType;
+ }
+ bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS);
+ bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+ bool ForCompare);
+
+ bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
+
+ // Check the safety of assignment from LHS to RHS
+ bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+ bool canAssignObjCInterfaces(const ObjCObjectType *LHS,
+ const ObjCObjectType *RHS);
+ bool canAssignObjCInterfacesInBlockPointer(
+ const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+ bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
+ QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT);
+ bool canBindObjCObjectType(QualType To, QualType From);
+
+ // Functions for calculating composite types
+ QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeFunctionArgumentTypes(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeTransparentUnionType(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
+
+ QualType mergeObjCGCQualifiers(QualType, QualType);
+
+ void ResetObjCLayout(const ObjCContainerDecl *CD) {
+ ObjCLayouts[CD] = 0;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Integer Predicates
+ //===--------------------------------------------------------------------===//
+
+ // The width of an integer, as defined in C99 6.2.6.2. This is the number
+ // of bits in an integer type excluding any padding bits.
+ unsigned getIntWidth(QualType T) const;
+
+ // Per C99 6.2.5p6, for every signed integer type, there is a corresponding
+ // unsigned integer type. This method takes a signed type, and returns the
+ // corresponding unsigned integer type.
+ QualType getCorrespondingUnsignedType(QualType T);
+
+ //===--------------------------------------------------------------------===//
+ // Type Iterators.
+ //===--------------------------------------------------------------------===//
+
+ typedef std::vector<Type*>::iterator type_iterator;
+ typedef std::vector<Type*>::const_iterator const_type_iterator;
+
+ type_iterator types_begin() { return Types.begin(); }
+ type_iterator types_end() { return Types.end(); }
+ const_type_iterator types_begin() const { return Types.begin(); }
+ const_type_iterator types_end() const { return Types.end(); }
+
+ //===--------------------------------------------------------------------===//
+ // Integer Values
+ //===--------------------------------------------------------------------===//
+
+ /// MakeIntValue - Make an APSInt of the appropriate width and
+ /// signedness for the given \arg Value and integer \arg Type.
+ llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
+ llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType());
+ Res = Value;
+ return Res;
+ }
+
+ /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
+ /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+
+ /// \brief returns true if there is at lease one @implementation in TU.
+ bool AnyObjCImplementation() {
+ return !ObjCImpls.empty();
+ }
+
+ /// \brief Set the implementation of ObjCInterfaceDecl.
+ void setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+ ObjCImplementationDecl *ImplD);
+ /// \brief Set the implementation of ObjCCategoryDecl.
+ void setObjCImplementation(ObjCCategoryDecl *CatD,
+ ObjCCategoryImplDecl *ImplD);
+
+ /// \brief Set the copy inialization expression of a block var decl.
+ void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+ /// \brief Get the copy initialization expression of VarDecl,or NULL if
+ /// none exists.
+ Expr *getBlockVarCopyInits(const VarDecl*VD);
+
+ /// \brief Allocate an uninitialized TypeSourceInfo.
+ ///
+ /// The caller should initialize the memory held by TypeSourceInfo using
+ /// the TypeLoc wrappers.
+ ///
+ /// \param T the type that will be the basis for type source info. This type
+ /// should refer to how the declarator was written in source code, not to
+ /// what type semantic analysis resolved the declarator to.
+ ///
+ /// \param Size the size of the type info to create, or 0 if the size
+ /// should be calculated based on the type.
+ TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const;
+
+ /// \brief Allocate a TypeSourceInfo where all locations have been
+ /// initialized to a given location, which defaults to the empty
+ /// location.
+ TypeSourceInfo *
+ getTrivialTypeSourceInfo(QualType T,
+ SourceLocation Loc = SourceLocation()) const;
+
+ TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
+
+ /// \brief Add a deallocation callback that will be invoked when the
+ /// ASTContext is destroyed.
+ ///
+ /// \brief Callback A callback function that will be invoked on destruction.
+ ///
+ /// \brief Data Pointer data that will be provided to the callback function
+ /// when it is called.
+ void AddDeallocation(void (*Callback)(void*), void *Data);
+
+ GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD);
+ GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
+
+ /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
+ /// lazily, only when used; this is only relevant for function or file scoped
+ /// var definitions.
+ ///
+ /// \returns true if the function/var must be CodeGen'ed/deserialized even if
+ /// it is not used.
+ bool DeclMustBeEmitted(const Decl *D);
+
+ //===--------------------------------------------------------------------===//
+ // Statistics
+ //===--------------------------------------------------------------------===//
+
+ /// \brief The number of implicitly-declared default constructors.
+ static unsigned NumImplicitDefaultConstructors;
+
+ /// \brief The number of implicitly-declared default constructors for
+ /// which declarations were built.
+ static unsigned NumImplicitDefaultConstructorsDeclared;
+
+ /// \brief The number of implicitly-declared copy constructors.
+ static unsigned NumImplicitCopyConstructors;
+
+ /// \brief The number of implicitly-declared copy constructors for
+ /// which declarations were built.
+ static unsigned NumImplicitCopyConstructorsDeclared;
+
+ /// \brief The number of implicitly-declared copy assignment operators.
+ static unsigned NumImplicitCopyAssignmentOperators;
+
+ /// \brief The number of implicitly-declared copy assignment operators for
+ /// which declarations were built.
+ static unsigned NumImplicitCopyAssignmentOperatorsDeclared;
+
+ /// \brief The number of implicitly-declared destructors.
+ static unsigned NumImplicitDestructors;
+
+ /// \brief The number of implicitly-declared destructors for which
+ /// declarations were built.
+ static unsigned NumImplicitDestructorsDeclared;
+
+private:
+ ASTContext(const ASTContext&); // DO NOT IMPLEMENT
+ void operator=(const ASTContext&); // DO NOT IMPLEMENT
+
+ void InitBuiltinTypes();
+ void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
+
+ // Return the ObjC type encoding for a given type.
+ void getObjCEncodingForTypeImpl(QualType t, std::string &S,
+ bool ExpandPointedToStructures,
+ bool ExpandStructures,
+ const FieldDecl *Field,
+ bool OutermostType = false,
+ bool EncodingProperty = false) const;
+
+ const ASTRecordLayout &
+ getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl) const;
+
+private:
+ /// \brief A set of deallocations that should be performed when the
+ /// ASTContext is destroyed.
+ llvm::SmallVector<std::pair<void (*)(void*), void *>, 16> Deallocations;
+
+ // FIXME: This currently contains the set of StoredDeclMaps used
+ // by DeclContext objects. This probably should not be in ASTContext,
+ // but we include it here so that ASTContext can quickly deallocate them.
+ llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;
+
+ /// \brief A counter used to uniquely identify "blocks".
+ mutable unsigned int UniqueBlockByRefTypeID;
+ mutable unsigned int UniqueBlockParmTypeID;
+
+ friend class DeclContext;
+ friend class DeclarationNameTable;
+ void ReleaseDeclContextMaps();
+};
+
+/// @brief Utility function for constructing a nullary selector.
+static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(0, &II);
+}
+
+/// @brief Utility function for constructing an unary selector.
+static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(1, &II);
+}
+
+} // end namespace clang
+
+// operator new and delete aren't allowed inside namespaces.
+// The throw specifications are mandated by the standard.
+/// @brief Placement new for using the ASTContext's allocator.
+///
+/// This placement form of operator new uses the ASTContext's allocator for
+/// obtaining memory. It is a non-throwing new, which means that it returns
+/// null on error. (If that is what the allocator does. The current does, so if
+/// this ever changes, this operator will have to be changed, too.)
+/// Usage looks like this (assuming there's an ASTContext 'Context' in scope):
+/// @code
+/// // Default alignment (8)
+/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments);
+/// // Specific alignment
+/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments);
+/// @endcode
+/// Please note that you cannot use delete on the pointer; it must be
+/// deallocated using an explicit destructor call followed by
+/// @c Context.Deallocate(Ptr).
+///
+/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// @param C The ASTContext that provides the allocator.
+/// @param Alignment The alignment of the allocated memory (if the underlying
+/// allocator supports it).
+/// @return The allocated memory. Could be NULL.
+inline void *operator new(size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment) throw () {
+ return C.Allocate(Bytes, Alignment);
+}
+/// @brief Placement delete companion to the new above.
+///
+/// This operator is just a companion to the new above. There is no way of
+/// invoking it directly; see the new operator for more details. This operator
+/// is called implicitly by the compiler if a placement new expression using
+/// the ASTContext throws in the object constructor.
+inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
+ throw () {
+ C.Deallocate(Ptr);
+}
+
+/// This placement form of operator new[] uses the ASTContext's allocator for
+/// obtaining memory. It is a non-throwing new[], which means that it returns
+/// null on error.
+/// Usage looks like this (assuming there's an ASTContext 'Context' in scope):
+/// @code
+/// // Default alignment (8)
+/// char *data = new (Context) char[10];
+/// // Specific alignment
+/// char *data = new (Context, 4) char[10];
+/// @endcode
+/// Please note that you cannot use delete on the pointer; it must be
+/// deallocated using an explicit destructor call followed by
+/// @c Context.Deallocate(Ptr).
+///
+/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// @param C The ASTContext that provides the allocator.
+/// @param Alignment The alignment of the allocated memory (if the underlying
+/// allocator supports it).
+/// @return The allocated memory. Could be NULL.
+inline void *operator new[](size_t Bytes, const clang::ASTContext& C,
+ size_t Alignment = 8) throw () {
+ return C.Allocate(Bytes, Alignment);
+}
+
+/// @brief Placement delete[] companion to the new[] above.
+///
+/// This operator is just a companion to the new[] above. There is no way of
+/// invoking it directly; see the new[] operator for more details. This operator
+/// is called implicitly by the compiler if a placement new[] expression using
+/// the ASTContext throws in the object constructor.
+inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
+ throw () {
+ C.Deallocate(Ptr);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h
new file mode 100644
index 0000000..1ab53b3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h
@@ -0,0 +1,47 @@
+//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICAST_H
+#define LLVM_CLANG_DIAGNOSTICAST_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define ASTSTART
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_AST_DIAGNOSTICS
+ };
+ } // end namespace diag
+
+ /// \brief Diagnostic argument formatting function for diagnostics that
+ /// involve AST nodes.
+ ///
+ /// This function formats diagnostic arguments for various AST nodes,
+ /// including types, declaration names, nested name specifiers, and
+ /// declaration contexts, into strings that can be printed as part of
+ /// diagnostics. It is meant to be used as the argument to
+ /// \c Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext
+ /// pointer.
+ void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
+ intptr_t Val,
+ const char *Modifier,
+ unsigned ModLen,
+ const char *Argument,
+ unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie);
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
new file mode 100644
index 0000000..b659ce7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
@@ -0,0 +1,265 @@
+//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- 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 ASTImporter class which imports AST nodes from one
+// context into another context.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
+#define LLVM_CLANG_AST_ASTIMPORTER_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class ASTContext;
+ class Decl;
+ class DeclContext;
+ class Diagnostic;
+ class Expr;
+ class FileManager;
+ class IdentifierInfo;
+ class NestedNameSpecifier;
+ class Stmt;
+ class TypeSourceInfo;
+
+ /// \brief Imports selected nodes from one AST context into another context,
+ /// merging AST nodes where appropriate.
+ class ASTImporter {
+ public:
+ typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
+
+ private:
+ /// \brief The contexts we're importing to and from.
+ ASTContext &ToContext, &FromContext;
+
+ /// \brief The file managers we're importing to and from.
+ FileManager &ToFileManager, &FromFileManager;
+
+ /// \brief Whether to perform a minimal import.
+ bool Minimal;
+
+ /// \brief Mapping from the already-imported types in the "from" context
+ /// to the corresponding types in the "to" context.
+ llvm::DenseMap<const Type *, const Type *> ImportedTypes;
+
+ /// \brief Mapping from the already-imported declarations in the "from"
+ /// context to the corresponding declarations in the "to" context.
+ llvm::DenseMap<Decl *, Decl *> ImportedDecls;
+
+ /// \brief Mapping from the already-imported statements in the "from"
+ /// context to the corresponding statements in the "to" context.
+ llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
+
+ /// \brief Mapping from the already-imported FileIDs in the "from" source
+ /// manager to the corresponding FileIDs in the "to" source manager.
+ llvm::DenseMap<FileID, FileID> ImportedFileIDs;
+
+ /// \brief Imported, anonymous tag declarations that are missing their
+ /// corresponding typedefs.
+ llvm::SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
+
+ /// \brief Declaration (from, to) pairs that are known not to be equivalent
+ /// (which we have already complained about).
+ NonEquivalentDeclSet NonEquivalentDecls;
+
+ public:
+ /// \brief Create a new AST importer.
+ ///
+ /// \param ToContext The context we'll be importing into.
+ ///
+ /// \param ToFileManager The file manager we'll be importing into.
+ ///
+ /// \param FromContext The context we'll be importing from.
+ ///
+ /// \param FromFileManager The file manager we'll be importing into.
+ ///
+ /// \param MinimalImport If true, the importer will attempt to import
+ /// as little as it can, e.g., by importing declarations as forward
+ /// declarations that can be completed at a later point.
+ ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport);
+
+ virtual ~ASTImporter();
+
+ /// \brief Whether the importer will perform a minimal import, creating
+ /// to-be-completed forward declarations when possible.
+ bool isMinimalImport() const { return Minimal; }
+
+ /// \brief Import the given type from the "from" context into the "to"
+ /// context.
+ ///
+ /// \returns the equivalent type in the "to" context, or a NULL type if
+ /// an error occurred.
+ QualType Import(QualType FromT);
+
+ /// \brief Import the given type source information from the
+ /// "from" context into the "to" context.
+ ///
+ /// \returns the equivalent type source information in the "to"
+ /// context, or NULL if an error occurred.
+ TypeSourceInfo *Import(TypeSourceInfo *FromTSI);
+
+ /// \brief Import the given declaration from the "from" context into the
+ /// "to" context.
+ ///
+ /// \returns the equivalent declaration in the "to" context, or a NULL type
+ /// if an error occurred.
+ Decl *Import(Decl *FromD);
+
+ /// \brief Import the given declaration context from the "from"
+ /// AST context into the "to" AST context.
+ ///
+ /// \returns the equivalent declaration context in the "to"
+ /// context, or a NULL type if an error occurred.
+ DeclContext *ImportContext(DeclContext *FromDC);
+
+ /// \brief Import the given expression from the "from" context into the
+ /// "to" context.
+ ///
+ /// \returns the equivalent expression in the "to" context, or NULL if
+ /// an error occurred.
+ Expr *Import(Expr *FromE);
+
+ /// \brief Import the given statement from the "from" context into the
+ /// "to" context.
+ ///
+ /// \returns the equivalent statement in the "to" context, or NULL if
+ /// an error occurred.
+ Stmt *Import(Stmt *FromS);
+
+ /// \brief Import the given nested-name-specifier from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent nested-name-specifier in the "to"
+ /// context, or NULL if an error occurred.
+ NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
+
+ /// \brief Import the goven template name from the "from" context into the
+ /// "to" context.
+ TemplateName Import(TemplateName From);
+
+ /// \brief Import the given source location from the "from" context into
+ /// the "to" context.
+ ///
+ /// \returns the equivalent source location in the "to" context, or an
+ /// invalid source location if an error occurred.
+ SourceLocation Import(SourceLocation FromLoc);
+
+ /// \brief Import the given source range from the "from" context into
+ /// the "to" context.
+ ///
+ /// \returns the equivalent source range in the "to" context, or an
+ /// invalid source location if an error occurred.
+ SourceRange Import(SourceRange FromRange);
+
+ /// \brief Import the given declaration name from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent declaration name in the "to" context,
+ /// or an empty declaration name if an error occurred.
+ DeclarationName Import(DeclarationName FromName);
+
+ /// \brief Import the given identifier from the "from" context
+ /// into the "to" context.
+ ///
+ /// \returns the equivalent identifier in the "to" context.
+ IdentifierInfo *Import(const IdentifierInfo *FromId);
+
+ /// \brief Import the given Objective-C selector from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent selector in the "to" context.
+ Selector Import(Selector FromSel);
+
+ /// \brief Import the given file ID from the "from" context into the
+ /// "to" context.
+ ///
+ /// \returns the equivalent file ID in the source manager of the "to"
+ /// context.
+ FileID Import(FileID);
+
+ /// \brief Import the definition of the given declaration, including all of
+ /// the declarations it contains.
+ ///
+ /// This routine is intended to be used
+ void ImportDefinition(Decl *From);
+
+ /// \brief Cope with a name conflict when importing a declaration into the
+ /// given context.
+ ///
+ /// This routine is invoked whenever there is a name conflict while
+ /// importing a declaration. The returned name will become the name of the
+ /// imported declaration. By default, the returned name is the same as the
+ /// original name, leaving the conflict unresolve such that name lookup
+ /// for this name is likely to find an ambiguity later.
+ ///
+ /// Subclasses may override this routine to resolve the conflict, e.g., by
+ /// renaming the declaration being imported.
+ ///
+ /// \param Name the name of the declaration being imported, which conflicts
+ /// with other declarations.
+ ///
+ /// \param DC the declaration context (in the "to" AST context) in which
+ /// the name is being imported.
+ ///
+ /// \param IDNS the identifier namespace in which the name will be found.
+ ///
+ /// \param Decls the set of declarations with the same name as the
+ /// declaration being imported.
+ ///
+ /// \param NumDecls the number of conflicting declarations in \p Decls.
+ ///
+ /// \returns the name that the newly-imported declaration should have.
+ virtual DeclarationName HandleNameConflict(DeclarationName Name,
+ DeclContext *DC,
+ unsigned IDNS,
+ NamedDecl **Decls,
+ unsigned NumDecls);
+
+ /// \brief Retrieve the context that AST nodes are being imported into.
+ ASTContext &getToContext() const { return ToContext; }
+
+ /// \brief Retrieve the context that AST nodes are being imported from.
+ ASTContext &getFromContext() const { return FromContext; }
+
+ /// \brief Retrieve the file manager that AST nodes are being imported into.
+ FileManager &getToFileManager() const { return ToFileManager; }
+
+ /// \brief Retrieve the file manager that AST nodes are being imported from.
+ FileManager &getFromFileManager() const { return FromFileManager; }
+
+ /// \brief Report a diagnostic in the "to" context.
+ DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
+
+ /// \brief Report a diagnostic in the "from" context.
+ DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
+
+ /// \brief Return the set of declarations that we know are not equivalent.
+ NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
+
+ /// \brief Note that we have imported the "from" declaration by mapping it
+ /// to the (potentially-newly-created) "to" declaration.
+ ///
+ /// Subclasses can override this function to observe all of the \c From ->
+ /// \c To declaration mappings as they are imported.
+ virtual Decl *Imported(Decl *From, Decl *To);
+
+ /// \brief Determine whether the given types are structurally
+ /// equivalent.
+ bool IsStructurallyEquivalent(QualType From, QualType To);
+ };
+}
+
+#endif // LLVM_CLANG_AST_ASTIMPORTER_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
new file mode 100644
index 0000000..01e6180
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
@@ -0,0 +1,48 @@
+//===--- ASTMutationListener.h - AST Mutation Interface --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTMutationListener interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
+
+namespace clang {
+ class Decl;
+ class DeclContext;
+ class TagDecl;
+ class CXXRecordDecl;
+ class ClassTemplateDecl;
+ class ClassTemplateSpecializationDecl;
+
+/// \brief An abstract interface that should be implemented by listeners
+/// that want to be notified when an AST entity gets modified after its
+/// initial creation.
+class ASTMutationListener {
+public:
+ virtual ~ASTMutationListener();
+
+ /// \brief A new TagDecl definition was completed.
+ virtual void CompletedTagDefinition(const TagDecl *D) { }
+
+ /// \brief A new declaration with name has been added to a DeclContext.
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
+
+ /// \brief An implicit member was added after the definition was completed.
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
new file mode 100644
index 0000000..217dfad
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
@@ -0,0 +1,397 @@
+//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides ASTVector, a vector ADT whose contents are
+// allocated using the allocator associated with an ASTContext..
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
+// We can refactor this core logic into something common.
+
+#ifndef LLVM_CLANG_AST_VECTOR
+#define LLVM_CLANG_AST_VECTOR
+
+#include "llvm/Support/type_traits.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include <algorithm>
+#include <memory>
+#include <cstring>
+
+#ifdef _MSC_VER
+namespace std {
+#if _MSC_VER <= 1310
+ // Work around flawed VC++ implementation of std::uninitialized_copy. Define
+ // additional overloads so that elements with pointer types are recognized as
+ // scalars and not objects, causing bizarre type conversion errors.
+ template<class T1, class T2>
+ inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
+ _Scalar_ptr_iterator_tag _Cat;
+ return _Cat;
+ }
+
+ template<class T1, class T2>
+ inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
+ _Scalar_ptr_iterator_tag _Cat;
+ return _Cat;
+ }
+#else
+ // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
+ // is that the above hack won't work if it wasn't fixed.
+#endif
+}
+#endif
+
+namespace clang {
+
+template<typename T>
+class ASTVector {
+ T *Begin, *End, *Capacity;
+
+ void setEnd(T *P) { this->End = P; }
+
+public:
+ // Default ctor - Initialize to empty.
+ explicit ASTVector(ASTContext &C, unsigned N = 0)
+ : Begin(NULL), End(NULL), Capacity(NULL) {
+ reserve(C, N);
+ }
+
+ ~ASTVector() {
+ if (llvm::is_class<T>::value) {
+ // Destroy the constructed elements in the vector.
+ destroy_range(Begin, End);
+ }
+ }
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+
+ // forward iterator creation methods.
+ iterator begin() { return Begin; }
+ const_iterator begin() const { return Begin; }
+ iterator end() { return End; }
+ const_iterator end() const { return End; }
+
+ // reverse iterator creation methods.
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+ bool empty() const { return Begin == End; }
+ size_type size() const { return End-Begin; }
+
+ reference operator[](unsigned idx) {
+ assert(Begin + idx < End);
+ return Begin[idx];
+ }
+ const_reference operator[](unsigned idx) const {
+ assert(Begin + idx < End);
+ return Begin[idx];
+ }
+
+ reference front() {
+ return begin()[0];
+ }
+ const_reference front() const {
+ return begin()[0];
+ }
+
+ reference back() {
+ return end()[-1];
+ }
+ const_reference back() const {
+ return end()[-1];
+ }
+
+ void pop_back() {
+ --End;
+ End->~T();
+ }
+
+ T pop_back_val() {
+ T Result = back();
+ pop_back();
+ return Result;
+ }
+
+ void clear() {
+ if (llvm::is_class<T>::value) {
+ destroy_range(Begin, End);
+ }
+ End = Begin;
+ }
+
+ /// data - Return a pointer to the vector's buffer, even if empty().
+ pointer data() {
+ return pointer(Begin);
+ }
+
+ /// data - Return a pointer to the vector's buffer, even if empty().
+ const_pointer data() const {
+ return const_pointer(Begin);
+ }
+
+ void push_back(const_reference Elt, ASTContext &C) {
+ if (End < Capacity) {
+ Retry:
+ new (End) T(Elt);
+ ++End;
+ return;
+ }
+ grow(C);
+ goto Retry;
+ }
+
+ void reserve(ASTContext &C, unsigned N) {
+ if (unsigned(Capacity-Begin) < N)
+ grow(C, N);
+ }
+
+ /// capacity - Return the total number of elements in the currently allocated
+ /// buffer.
+ size_t capacity() const { return Capacity - Begin; }
+
+ /// append - Add the specified range to the end of the SmallVector.
+ ///
+ template<typename in_iter>
+ void append(ASTContext &C, in_iter in_start, in_iter in_end) {
+ size_type NumInputs = std::distance(in_start, in_end);
+
+ if (NumInputs == 0)
+ return;
+
+ // Grow allocated space if needed.
+ if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+ this->grow(C, this->size()+NumInputs);
+
+ // Copy the new elements over.
+ // TODO: NEED To compile time dispatch on whether in_iter is a random access
+ // iterator to use the fast uninitialized_copy.
+ std::uninitialized_copy(in_start, in_end, this->end());
+ this->setEnd(this->end() + NumInputs);
+ }
+
+ /// append - Add the specified range to the end of the SmallVector.
+ ///
+ void append(ASTContext &C, size_type NumInputs, const T &Elt) {
+ // Grow allocated space if needed.
+ if (NumInputs > size_type(this->capacity_ptr()-this->end()))
+ this->grow(C, this->size()+NumInputs);
+
+ // Copy the new elements over.
+ std::uninitialized_fill_n(this->end(), NumInputs, Elt);
+ this->setEnd(this->end() + NumInputs);
+ }
+
+ /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
+ /// starting with "Dest", constructing elements into it as needed.
+ template<typename It1, typename It2>
+ static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+ std::uninitialized_copy(I, E, Dest);
+ }
+
+ iterator insert(ASTContext &C, iterator I, const T &Elt) {
+ if (I == this->end()) { // Important special case for empty vector.
+ push_back(Elt);
+ return this->end()-1;
+ }
+
+ if (this->EndX < this->CapacityX) {
+ Retry:
+ new (this->end()) T(this->back());
+ this->setEnd(this->end()+1);
+ // Push everything else over.
+ std::copy_backward(I, this->end()-1, this->end());
+ *I = Elt;
+ return I;
+ }
+ size_t EltNo = I-this->begin();
+ this->grow(C);
+ I = this->begin()+EltNo;
+ goto Retry;
+ }
+
+ iterator insert(ASTContext &C, iterator I, size_type NumToInsert,
+ const T &Elt) {
+ if (I == this->end()) { // Important special case for empty vector.
+ append(C, NumToInsert, Elt);
+ return this->end()-1;
+ }
+
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ // Ensure there is enough space.
+ reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
+
+ // Uninvalidate the iterator.
+ I = this->begin()+InsertElt;
+
+ // If there are more elements between the insertion point and the end of the
+ // range than there are being inserted, we can use a simple approach to
+ // insertion. Since we already reserved space, we know that this won't
+ // reallocate the vector.
+ if (size_t(this->end()-I) >= NumToInsert) {
+ T *OldEnd = this->end();
+ append(C, this->end()-NumToInsert, this->end());
+
+ // Copy the existing elements that get replaced.
+ std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
+
+ std::fill_n(I, NumToInsert, Elt);
+ return I;
+ }
+
+ // Otherwise, we're inserting more elements than exist already, and we're
+ // not inserting at the end.
+
+ // Copy over the elements that we're about to overwrite.
+ T *OldEnd = this->end();
+ this->setEnd(this->end() + NumToInsert);
+ size_t NumOverwritten = OldEnd-I;
+ this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
+
+ // Replace the overwritten part.
+ std::fill_n(I, NumOverwritten, Elt);
+
+ // Insert the non-overwritten middle part.
+ std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
+ return I;
+ }
+
+ template<typename ItTy>
+ iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) {
+ if (I == this->end()) { // Important special case for empty vector.
+ append(C, From, To);
+ return this->end()-1;
+ }
+
+ size_t NumToInsert = std::distance(From, To);
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ // Ensure there is enough space.
+ reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
+
+ // Uninvalidate the iterator.
+ I = this->begin()+InsertElt;
+
+ // If there are more elements between the insertion point and the end of the
+ // range than there are being inserted, we can use a simple approach to
+ // insertion. Since we already reserved space, we know that this won't
+ // reallocate the vector.
+ if (size_t(this->end()-I) >= NumToInsert) {
+ T *OldEnd = this->end();
+ append(C, this->end()-NumToInsert, this->end());
+
+ // Copy the existing elements that get replaced.
+ std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
+
+ std::copy(From, To, I);
+ return I;
+ }
+
+ // Otherwise, we're inserting more elements than exist already, and we're
+ // not inserting at the end.
+
+ // Copy over the elements that we're about to overwrite.
+ T *OldEnd = this->end();
+ this->setEnd(this->end() + NumToInsert);
+ size_t NumOverwritten = OldEnd-I;
+ this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
+
+ // Replace the overwritten part.
+ for (; NumOverwritten > 0; --NumOverwritten) {
+ *I = *From;
+ ++I; ++From;
+ }
+
+ // Insert the non-overwritten middle part.
+ this->uninitialized_copy(From, To, OldEnd);
+ return I;
+ }
+
+ void resize(ASTContext &C, unsigned N, const T &NV) {
+ if (N < this->size()) {
+ this->destroy_range(this->begin()+N, this->end());
+ this->setEnd(this->begin()+N);
+ } else if (N > this->size()) {
+ if (this->capacity() < N)
+ this->grow(C, N);
+ construct_range(this->end(), this->begin()+N, NV);
+ this->setEnd(this->begin()+N);
+ }
+ }
+
+private:
+ /// grow - double the size of the allocated memory, guaranteeing space for at
+ /// least one more element or MinSize if specified.
+ void grow(ASTContext &C, size_type MinSize = 1);
+
+ void construct_range(T *S, T *E, const T &Elt) {
+ for (; S != E; ++S)
+ new (S) T(Elt);
+ }
+
+ void destroy_range(T *S, T *E) {
+ while (S != E) {
+ --E;
+ E->~T();
+ }
+ }
+
+protected:
+ iterator capacity_ptr() { return (iterator)this->Capacity; }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T>
+void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
+ size_t CurCapacity = Capacity-Begin;
+ size_t CurSize = size();
+ size_t NewCapacity = 2*CurCapacity;
+ if (NewCapacity < MinSize)
+ NewCapacity = MinSize;
+
+ // Allocate the memory from the ASTContext.
+ T *NewElts = new (C) T[NewCapacity];
+
+ // Copy the elements over.
+ if (llvm::is_class<T>::value) {
+ std::uninitialized_copy(Begin, End, NewElts);
+ // Destroy the original elements.
+ destroy_range(Begin, End);
+ }
+ else {
+ // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
+ memcpy(NewElts, Begin, CurSize * sizeof(T));
+ }
+
+ C.Deallocate(Begin);
+ Begin = NewElts;
+ End = NewElts+CurSize;
+ Capacity = Begin+NewCapacity;
+}
+
+} // end: clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
new file mode 100644
index 0000000..67968fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
@@ -0,0 +1,233 @@
+//===--- Attr.h - Classes for representing expressions ----------*- 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 Attr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ATTR_H
+#define LLVM_CLANG_AST_ATTR_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cassert>
+#include <cstring>
+#include <algorithm>
+using llvm::dyn_cast;
+
+namespace clang {
+ class ASTContext;
+ class IdentifierInfo;
+ class ObjCInterfaceDecl;
+ class Expr;
+ class QualType;
+ class FunctionDecl;
+ class TypeSourceInfo;
+}
+
+// Defined in ASTContext.h
+void *operator new(size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment = 16) throw ();
+// FIXME: Being forced to not have a default argument here due to redeclaration
+// rules on default arguments sucks
+void *operator new[](size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment) throw ();
+
+// It is good practice to pair new/delete operators. Also, MSVC gives many
+// warnings if a matching delete overload is not declared, even though the
+// throw() spec guarantees it will not be implicitly called.
+void operator delete(void *Ptr, const clang::ASTContext &C, size_t)
+ throw ();
+void operator delete[](void *Ptr, const clang::ASTContext &C, size_t)
+ throw ();
+
+namespace clang {
+
+/// Attr - This represents one attribute.
+class Attr {
+private:
+ SourceLocation Loc;
+ unsigned AttrKind : 16;
+
+protected:
+ bool Inherited : 1;
+
+ virtual ~Attr();
+
+ void* operator new(size_t bytes) throw() {
+ assert(0 && "Attrs cannot be allocated with regular 'new'.");
+ return 0;
+ }
+ void operator delete(void* data) throw() {
+ assert(0 && "Attrs cannot be released with regular 'delete'.");
+ }
+
+public:
+ // Forward so that the regular new and delete do not hide global ones.
+ void* operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 16) throw() {
+ return ::operator new(Bytes, C, Alignment);
+ }
+ void operator delete(void *Ptr, ASTContext &C,
+ size_t Alignment) throw() {
+ return ::operator delete(Ptr, C, Alignment);
+ }
+
+protected:
+ Attr(attr::Kind AK, SourceLocation L)
+ : Loc(L), AttrKind(AK), Inherited(false) {}
+
+public:
+
+ attr::Kind getKind() const {
+ return static_cast<attr::Kind>(AttrKind);
+ }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ bool isInherited() const { return Inherited; }
+
+ // Clone this attribute.
+ virtual Attr* clone(ASTContext &C) const = 0;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *) { return true; }
+};
+
+class InheritableAttr : public Attr {
+protected:
+ InheritableAttr(attr::Kind AK, SourceLocation L)
+ : Attr(AK, L) {}
+
+public:
+ void setInherited(bool I) { Inherited = I; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() <= attr::LAST_INHERITABLE;
+ }
+ static bool classof(const InheritableAttr *) { return true; }
+};
+
+#include "clang/AST/Attrs.inc"
+
+/// AttrVec - A vector of Attr, which is how they are stored on the AST.
+typedef llvm::SmallVector<Attr*, 2> AttrVec;
+typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
+
+/// DestroyAttrs - Destroy the contents of an AttrVec.
+inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
+}
+
+/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
+/// providing attributes that are of a specifc type.
+template <typename SpecificAttr>
+class specific_attr_iterator {
+ /// Current - The current, underlying iterator.
+ /// In order to ensure we don't dereference an invalid iterator unless
+ /// specifically requested, we don't necessarily advance this all the
+ /// way. Instead, we advance it when an operation is requested; if the
+ /// operation is acting on what should be a past-the-end iterator,
+ /// then we offer no guarantees, but this way we do not dererence a
+ /// past-the-end iterator when we move to a past-the-end position.
+ mutable AttrVec::const_iterator Current;
+
+ void AdvanceToNext() const {
+ while (!llvm::isa<SpecificAttr>(*Current))
+ ++Current;
+ }
+
+ void AdvanceToNext(AttrVec::const_iterator I) const {
+ while (Current != I && !llvm::isa<SpecificAttr>(*Current))
+ ++Current;
+ }
+
+public:
+ typedef SpecificAttr* value_type;
+ typedef SpecificAttr* reference;
+ typedef SpecificAttr* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ specific_attr_iterator() : Current() { }
+ explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
+
+ reference operator*() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
+ }
+ pointer operator->() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
+ }
+
+ specific_attr_iterator& operator++() {
+ ++Current;
+ return *this;
+ }
+ specific_attr_iterator operator++(int) {
+ specific_attr_iterator Tmp(*this);
+ ++(*this);
+ return Tmp;
+ }
+
+ friend bool operator==(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ if (Left.Current < Right.Current)
+ Left.AdvanceToNext(Right.Current);
+ else
+ Right.AdvanceToNext(Left.Current);
+ return Left.Current == Right.Current;
+ }
+ friend bool operator!=(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ return !(Left == Right);
+ }
+};
+
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.begin());
+}
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.end());
+}
+
+template <typename T>
+inline bool hasSpecificAttr(const AttrVec& vec) {
+ return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
+}
+template <typename T>
+inline T *getSpecificAttr(const AttrVec& vec) {
+ specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
+ if (i != specific_attr_end<T>(vec))
+ return *i;
+ else
+ return 0;
+}
+
+/// getMaxAlignment - Returns the highest alignment value found among
+/// AlignedAttrs in an AttrVec, or 0 if there are none.
+inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
+ unsigned Align = 0;
+ specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
+ for(; i != e; ++i)
+ Align = std::max(Align, i->getAlignment(Ctx));
+ return Align;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
new file mode 100644
index 0000000..2d30cb3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
@@ -0,0 +1,370 @@
+//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides routines that help analyzing C++ inheritance hierarchies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H
+#define LLVM_CLANG_AST_CXXINHERITANCE_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <list>
+#include <map>
+#include <cassert>
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class NamedDecl;
+
+/// \brief Represents an element in a path from a derived class to a
+/// base class.
+///
+/// Each step in the path references the link from a
+/// derived class to one of its direct base classes, along with a
+/// base "number" that identifies which base subobject of the
+/// original derived class we are referencing.
+struct CXXBasePathElement {
+ /// \brief The base specifier that states the link from a derived
+ /// class to a base class, which will be followed by this base
+ /// path element.
+ const CXXBaseSpecifier *Base;
+
+ /// \brief The record decl of the class that the base is a base of.
+ const CXXRecordDecl *Class;
+
+ /// \brief Identifies which base class subobject (of type
+ /// \c Base->getType()) this base path element refers to.
+ ///
+ /// This value is only valid if \c !Base->isVirtual(), because there
+ /// is no base numbering for the zero or one virtual bases of a
+ /// given type.
+ int SubobjectNumber;
+};
+
+/// \brief Represents a path from a specific derived class
+/// (which is not represented as part of the path) to a particular
+/// (direct or indirect) base class subobject.
+///
+/// Individual elements in the path are described by the \c CXXBasePathElement
+/// structure, which captures both the link from a derived class to one of its
+/// direct bases and identification describing which base class
+/// subobject is being used.
+class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
+public:
+ CXXBasePath() : Access(AS_public) {}
+
+ /// \brief The access along this inheritance path. This is only
+ /// calculated when recording paths. AS_none is a special value
+ /// used to indicate a path which permits no legal access.
+ AccessSpecifier Access;
+
+ /// \brief The set of declarations found inside this base class
+ /// subobject.
+ DeclContext::lookup_result Decls;
+
+ void clear() {
+ llvm::SmallVectorImpl<CXXBasePathElement>::clear();
+ Access = AS_public;
+ }
+};
+
+/// BasePaths - Represents the set of paths from a derived class to
+/// one of its (direct or indirect) bases. For example, given the
+/// following class hierachy:
+///
+/// @code
+/// class A { };
+/// class B : public A { };
+/// class C : public A { };
+/// class D : public B, public C{ };
+/// @endcode
+///
+/// There are two potential BasePaths to represent paths from D to a
+/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0)
+/// and another is (D,0)->(C,0)->(A,1). These two paths actually
+/// refer to two different base class subobjects of the same type,
+/// so the BasePaths object refers to an ambiguous path. On the
+/// other hand, consider the following class hierarchy:
+///
+/// @code
+/// class A { };
+/// class B : public virtual A { };
+/// class C : public virtual A { };
+/// class D : public B, public C{ };
+/// @endcode
+///
+/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0)
+/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them
+/// refer to the same base class subobject of type A (the virtual
+/// one), there is no ambiguity.
+class CXXBasePaths {
+ /// \brief The type from which this search originated.
+ CXXRecordDecl *Origin;
+
+ /// Paths - The actual set of paths that can be taken from the
+ /// derived class to the same base class.
+ std::list<CXXBasePath> Paths;
+
+ /// ClassSubobjects - Records the class subobjects for each class
+ /// type that we've seen. The first element in the pair says
+ /// whether we found a path to a virtual base for that class type,
+ /// while the element contains the number of non-virtual base
+ /// class subobjects for that class type. The key of the map is
+ /// the cv-unqualified canonical type of the base class subobject.
+ std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering>
+ ClassSubobjects;
+
+ /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
+ /// ambiguous paths while it is looking for a path from a derived
+ /// type to a base type.
+ bool FindAmbiguities;
+
+ /// RecordPaths - Whether Sema::IsDerivedFrom should record paths
+ /// while it is determining whether there are paths from a derived
+ /// type to a base type.
+ bool RecordPaths;
+
+ /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
+ /// if it finds a path that goes across a virtual base. The virtual class
+ /// is also recorded.
+ bool DetectVirtual;
+
+ /// ScratchPath - A BasePath that is used by Sema::lookupInBases
+ /// to help build the set of paths.
+ CXXBasePath ScratchPath;
+
+ /// DetectedVirtual - The base class that is virtual.
+ const RecordType *DetectedVirtual;
+
+ /// \brief Array of the declarations that have been found. This
+ /// array is constructed only if needed, e.g., to iterate over the
+ /// results within LookupResult.
+ NamedDecl **DeclsFound;
+ unsigned NumDeclsFound;
+
+ friend class CXXRecordDecl;
+
+ void ComputeDeclsFound();
+
+ bool lookupInBases(ASTContext &Context,
+ const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback *BaseMatches,
+ void *UserData);
+public:
+ typedef std::list<CXXBasePath>::iterator paths_iterator;
+ typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
+ typedef NamedDecl **decl_iterator;
+
+ /// BasePaths - Construct a new BasePaths structure to record the
+ /// paths for a derived-to-base search.
+ explicit CXXBasePaths(bool FindAmbiguities = true,
+ bool RecordPaths = true,
+ bool DetectVirtual = true)
+ : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
+ NumDeclsFound(0) { }
+
+ ~CXXBasePaths() { delete [] DeclsFound; }
+
+ paths_iterator begin() { return Paths.begin(); }
+ paths_iterator end() { return Paths.end(); }
+ const_paths_iterator begin() const { return Paths.begin(); }
+ const_paths_iterator end() const { return Paths.end(); }
+
+ CXXBasePath& front() { return Paths.front(); }
+ const CXXBasePath& front() const { return Paths.front(); }
+
+ decl_iterator found_decls_begin();
+ decl_iterator found_decls_end();
+
+ /// \brief Determine whether the path from the most-derived type to the
+ /// given base type is ambiguous (i.e., it refers to multiple subobjects of
+ /// the same base type).
+ bool isAmbiguous(CanQualType BaseType);
+
+ /// \brief Whether we are finding multiple paths to detect ambiguities.
+ bool isFindingAmbiguities() const { return FindAmbiguities; }
+
+ /// \brief Whether we are recording paths.
+ bool isRecordingPaths() const { return RecordPaths; }
+
+ /// \brief Specify whether we should be recording paths or not.
+ void setRecordingPaths(bool RP) { RecordPaths = RP; }
+
+ /// \brief Whether we are detecting virtual bases.
+ bool isDetectingVirtual() const { return DetectVirtual; }
+
+ /// \brief The virtual base discovered on the path (if we are merely
+ /// detecting virtuals).
+ const RecordType* getDetectedVirtual() const {
+ return DetectedVirtual;
+ }
+
+ /// \brief Retrieve the type from which this base-paths search
+ /// began
+ CXXRecordDecl *getOrigin() const { return Origin; }
+ void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
+
+ /// \brief Clear the base-paths results.
+ void clear();
+
+ /// \brief Swap this data structure's contents with another CXXBasePaths
+ /// object.
+ void swap(CXXBasePaths &Other);
+};
+
+/// \brief Uniquely identifies a virtual method within a class
+/// hierarchy by the method itself and a class subobject number.
+struct UniqueVirtualMethod {
+ UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { }
+
+ UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
+ const CXXRecordDecl *InVirtualSubobject)
+ : Method(Method), Subobject(Subobject),
+ InVirtualSubobject(InVirtualSubobject) { }
+
+ /// \brief The overriding virtual method.
+ CXXMethodDecl *Method;
+
+ /// \brief The subobject in which the overriding virtual method
+ /// resides.
+ unsigned Subobject;
+
+ /// \brief The virtual base class subobject of which this overridden
+ /// virtual method is a part. Note that this records the closest
+ /// derived virtual base class subobject.
+ const CXXRecordDecl *InVirtualSubobject;
+
+ friend bool operator==(const UniqueVirtualMethod &X,
+ const UniqueVirtualMethod &Y) {
+ return X.Method == Y.Method && X.Subobject == Y.Subobject &&
+ X.InVirtualSubobject == Y.InVirtualSubobject;
+ }
+
+ friend bool operator!=(const UniqueVirtualMethod &X,
+ const UniqueVirtualMethod &Y) {
+ return !(X == Y);
+ }
+};
+
+/// \brief The set of methods that override a given virtual method in
+/// each subobject where it occurs.
+///
+/// The first part of the pair is the subobject in which the
+/// overridden virtual function occurs, while the second part of the
+/// pair is the virtual method that overrides it (including the
+/// subobject in which that virtual function occurs).
+class OverridingMethods {
+ llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
+ Overrides;
+
+public:
+ // Iterate over the set of subobjects that have overriding methods.
+ typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
+ ::iterator iterator;
+ typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >
+ ::const_iterator const_iterator;
+ iterator begin() { return Overrides.begin(); }
+ const_iterator begin() const { return Overrides.begin(); }
+ iterator end() { return Overrides.end(); }
+ const_iterator end() const { return Overrides.end(); }
+ unsigned size() const { return Overrides.size(); }
+
+ // Iterate over the set of overriding virtual methods in a given
+ // subobject.
+ typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
+ overriding_iterator;
+ typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator
+ overriding_const_iterator;
+
+ // Add a new overriding method for a particular subobject.
+ void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
+
+ // Add all of the overriding methods from "other" into overrides for
+ // this method. Used when merging the overrides from multiple base
+ // class subobjects.
+ void add(const OverridingMethods &Other);
+
+ // Replace all overriding virtual methods in all subobjects with the
+ // given virtual method.
+ void replaceAll(UniqueVirtualMethod Overriding);
+};
+
+/// \brief A mapping from each virtual member function to its set of
+/// final overriders.
+///
+/// Within a class hierarchy for a given derived class, each virtual
+/// member function in that hierarchy has one or more "final
+/// overriders" (C++ [class.virtual]p2). A final overrider for a
+/// virtual function "f" is the virtual function that will actually be
+/// invoked when dispatching a call to "f" through the
+/// vtable. Well-formed classes have a single final overrider for each
+/// virtual function; in abstract classes, the final overrider for at
+/// least one virtual function is a pure virtual function. Due to
+/// multiple, virtual inheritance, it is possible for a class to have
+/// more than one final overrider. Athough this is an error (per C++
+/// [class.virtual]p2), it is not considered an error here: the final
+/// overrider map can represent multiple final overriders for a
+/// method, and it is up to the client to determine whether they are
+/// problem. For example, the following class \c D has two final
+/// overriders for the virtual function \c A::f(), one in \c C and one
+/// in \c D:
+///
+/// \code
+/// struct A { virtual void f(); };
+/// struct B : virtual A { virtual void f(); };
+/// struct C : virtual A { virtual void f(); };
+/// struct D : B, C { };
+/// \endcode
+///
+/// This data structure contaings a mapping from every virtual
+/// function *that does not override an existing virtual function* and
+/// in every subobject where that virtual function occurs to the set
+/// of virtual functions that override it. Thus, the same virtual
+/// function \c A::f can actually occur in multiple subobjects of type
+/// \c A due to multiple inheritance, and may be overriden by
+/// different virtual functions in each, as in the following example:
+///
+/// \code
+/// struct A { virtual void f(); };
+/// struct B : A { virtual void f(); };
+/// struct C : A { virtual void f(); };
+/// struct D : B, C { };
+/// \endcode
+///
+/// Unlike in the previous example, where the virtual functions \c
+/// B::f and \c C::f both overrode \c A::f in the same subobject of
+/// type \c A, in this example the two virtual functions both override
+/// \c A::f but in *different* subobjects of type A. This is
+/// represented by numbering the subobjects in which the overridden
+/// and the overriding virtual member functions are located. Subobject
+/// 0 represents the virtua base class subobject of that type, while
+/// subobject numbers greater than 0 refer to non-virtual base class
+/// subobjects of that type.
+class CXXFinalOverriderMap
+ : public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };
+
+/// \brief A set of all the primary bases for a class.
+class CXXIndirectPrimaryBaseSet
+ : public llvm::SmallSet<const CXXRecordDecl*, 32> { };
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
new file mode 100644
index 0000000..4d7fcfd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
@@ -0,0 +1,758 @@
+//===-- CanonicalType.h - C Language Family Type Representation -*- 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 CanQual class template, which provides access to
+// canonical types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
+#define LLVM_CLANG_AST_CANONICAL_TYPE_H
+
+#include "clang/AST/Type.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/type_traits.h"
+#include <iterator>
+
+namespace clang {
+
+template<typename T> class CanProxy;
+template<typename T> struct CanProxyAdaptor;
+
+//----------------------------------------------------------------------------//
+// Canonical, qualified type template
+//----------------------------------------------------------------------------//
+
+/// \brief Represents a canonical, potentially-qualified type.
+///
+/// The CanQual template is a lightweight smart pointer that provides access
+/// to the canonical representation of a type, where all typedefs and other
+/// syntactic sugar has been eliminated. A CanQualType may also have various
+/// qualifiers (const, volatile, restrict) attached to it.
+///
+/// The template type parameter @p T is one of the Type classes (PointerType,
+/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
+/// type (or some subclass of that type). The typedef @c CanQualType is just
+/// a shorthand for @c CanQual<Type>.
+///
+/// An instance of @c CanQual<T> can be implicitly converted to a
+/// @c CanQual<U> when T is derived from U, which essentially provides an
+/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
+/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
+/// be implicitly converted to a QualType, but the reverse operation requires
+/// a call to ASTContext::getCanonicalType().
+///
+///
+template<typename T = Type>
+class CanQual {
+ /// \brief The actual, canonical type.
+ QualType Stored;
+
+public:
+ /// \brief Constructs a NULL canonical type.
+ CanQual() : Stored() { }
+
+ /// \brief Converting constructor that permits implicit upcasting of
+ /// canonical type pointers.
+ template<typename U>
+ CanQual(const CanQual<U>& Other,
+ typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
+
+ /// \brief Retrieve the underlying type pointer, which refers to a
+ /// canonical type.
+ ///
+ /// The underlying pointer must not be NULL.
+ const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
+
+ /// \brief Retrieve the underlying type pointer, which refers to a
+ /// canonical type, or NULL.
+ ///
+ const T *getTypePtrOrNull() const {
+ return cast_or_null<T>(Stored.getTypePtrOrNull());
+ }
+
+ /// \brief Implicit conversion to a qualified type.
+ operator QualType() const { return Stored; }
+
+ /// \brief Implicit conversion to bool.
+ operator bool() const { return !isNull(); }
+
+ bool isNull() const {
+ return Stored.isNull();
+ }
+
+ SplitQualType split() const { return Stored.split(); }
+
+ /// \brief Retrieve a canonical type pointer with a different static type,
+ /// upcasting or downcasting as needed.
+ ///
+ /// The getAs() function is typically used to try to downcast to a
+ /// more specific (canonical) type in the type system. For example:
+ ///
+ /// @code
+ /// void f(CanQual<Type> T) {
+ /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
+ /// // look at Ptr's pointee type
+ /// }
+ /// }
+ /// @endcode
+ ///
+ /// \returns A proxy pointer to the same type, but with the specified
+ /// static type (@p U). If the dynamic type is not the specified static type
+ /// or a derived class thereof, a NULL canonical type.
+ template<typename U> CanProxy<U> getAs() const;
+
+ /// \brief Overloaded arrow operator that produces a canonical type
+ /// proxy.
+ CanProxy<T> operator->() const;
+
+ /// \brief Retrieve all qualifiers.
+ Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
+
+ /// \brief Retrieve the const/volatile/restrict qualifiers.
+ unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
+
+ /// \brief Determines whether this type has any qualifiers
+ bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
+
+ bool isConstQualified() const {
+ return Stored.isLocalConstQualified();
+ }
+ bool isVolatileQualified() const {
+ return Stored.isLocalVolatileQualified();
+ }
+ bool isRestrictQualified() const {
+ return Stored.isLocalRestrictQualified();
+ }
+
+ /// \brief Determines if this canonical type is furthermore
+ /// canonical as a parameter. The parameter-canonicalization
+ /// process decays arrays to pointers and drops top-level qualifiers.
+ bool isCanonicalAsParam() const {
+ return Stored.isCanonicalAsParam();
+ }
+
+ /// \brief Retrieve the unqualified form of this type.
+ CanQual<T> getUnqualifiedType() const;
+
+ /// \brief Retrieves a version of this type with const applied.
+ /// Note that this does not always yield a canonical type.
+ QualType withConst() const {
+ return Stored.withConst();
+ }
+
+ /// \brief Determines whether this canonical type is more qualified than
+ /// the @p Other canonical type.
+ bool isMoreQualifiedThan(CanQual<T> Other) const {
+ return Stored.isMoreQualifiedThan(Other.Stored);
+ }
+
+ /// \brief Determines whether this canonical type is at least as qualified as
+ /// the @p Other canonical type.
+ bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
+ return Stored.isAtLeastAsQualifiedAs(Other.Stored);
+ }
+
+ /// \brief If the canonical type is a reference type, returns the type that
+ /// it refers to; otherwise, returns the type itself.
+ CanQual<Type> getNonReferenceType() const;
+
+ /// \brief Retrieve the internal representation of this canonical type.
+ void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
+
+ /// \brief Construct a canonical type from its internal representation.
+ static CanQual<T> getFromOpaquePtr(void *Ptr);
+
+ /// \brief Builds a canonical type from a QualType.
+ ///
+ /// This routine is inherently unsafe, because it requires the user to
+ /// ensure that the given type is a canonical type with the correct
+ // (dynamic) type.
+ static CanQual<T> CreateUnsafe(QualType Other);
+
+ void dump() const { Stored.dump(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(getAsOpaquePtr());
+ }
+};
+
+template<typename T, typename U>
+inline bool operator==(CanQual<T> x, CanQual<U> y) {
+ return x.getAsOpaquePtr() == y.getAsOpaquePtr();
+}
+
+template<typename T, typename U>
+inline bool operator!=(CanQual<T> x, CanQual<U> y) {
+ return x.getAsOpaquePtr() != y.getAsOpaquePtr();
+}
+
+/// \brief Represents a canonical, potentially-qualified type.
+typedef CanQual<Type> CanQualType;
+
+inline CanQualType Type::getCanonicalTypeUnqualified() const {
+ return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ CanQualType T) {
+ DB << static_cast<QualType>(T);
+ return DB;
+}
+
+//----------------------------------------------------------------------------//
+// Internal proxy classes used by canonical types
+//----------------------------------------------------------------------------//
+
+#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
+CanQualType Accessor() const { \
+return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
+}
+
+#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
+Type Accessor() const { return this->getTypePtr()->Accessor(); }
+
+/// \brief Base class of all canonical proxy types, which is responsible for
+/// storing the underlying canonical type and providing basic conversions.
+template<typename T>
+class CanProxyBase {
+protected:
+ CanQual<T> Stored;
+
+public:
+ /// \brief Retrieve the pointer to the underlying Type
+ const T *getTypePtr() const { return Stored.getTypePtr(); }
+
+ /// \brief Implicit conversion to the underlying pointer.
+ ///
+ /// Also provides the ability to use canonical type proxies in a Boolean
+ // context,e.g.,
+ /// @code
+ /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
+ /// @endcode
+ operator const T*() const { return this->Stored.getTypePtrOrNull(); }
+
+ /// \brief Try to convert the given canonical type to a specific structural
+ /// type.
+ template<typename U> CanProxy<U> getAs() const {
+ return this->Stored.template getAs<U>();
+ }
+
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
+
+ // Type predicates
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
+
+ /// \brief Retrieve the proxy-adaptor type.
+ ///
+ /// This arrow operator is used when CanProxyAdaptor has been specialized
+ /// for the given type T. In that case, we reference members of the
+ /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
+ /// by the arrow operator in the primary CanProxyAdaptor template.
+ const CanProxyAdaptor<T> *operator->() const {
+ return static_cast<const CanProxyAdaptor<T> *>(this);
+ }
+};
+
+/// \brief Replacable canonical proxy adaptor class that provides the link
+/// between a canonical type and the accessors of the type.
+///
+/// The CanProxyAdaptor is a replaceable class template that is instantiated
+/// as part of each canonical proxy type. The primary template merely provides
+/// redirection to the underlying type (T), e.g., @c PointerType. One can
+/// provide specializations of this class template for each underlying type
+/// that provide accessors returning canonical types (@c CanQualType) rather
+/// than the more typical @c QualType, to propagate the notion of "canonical"
+/// through the system.
+template<typename T>
+struct CanProxyAdaptor : CanProxyBase<T> { };
+
+/// \brief Canonical proxy type returned when retrieving the members of a
+/// canonical type or as the result of the @c CanQual<T>::getAs member
+/// function.
+///
+/// The CanProxy type mainly exists as a proxy through which operator-> will
+/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
+/// type that provides canonical-type access to the fields of the type.
+template<typename T>
+class CanProxy : public CanProxyAdaptor<T> {
+public:
+ /// \brief Build a NULL proxy.
+ CanProxy() { }
+
+ /// \brief Build a proxy to the given canonical type.
+ CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
+
+ /// \brief Implicit conversion to the stored canonical type.
+ operator CanQual<T>() const { return this->Stored; }
+};
+
+} // end namespace clang
+
+namespace llvm {
+
+/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
+/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
+/// to return smart pointer (proxies?).
+template<typename T>
+struct simplify_type<const ::clang::CanQual<T> > {
+ typedef const T *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
+ return Val.getTypePtr();
+ }
+};
+template<typename T>
+struct simplify_type< ::clang::CanQual<T> >
+: public simplify_type<const ::clang::CanQual<T> > {};
+
+// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
+template<typename T>
+class PointerLikeTypeTraits<clang::CanQual<T> > {
+public:
+ static inline void *getAsVoidPointer(clang::CanQual<T> P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::CanQual<T> getFromVoidPointer(void *P) {
+ return clang::CanQual<T>::getFromOpaquePtr(P);
+ }
+ // qualifier information is encoded in the low bits.
+ enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm
+
+namespace clang {
+
+//----------------------------------------------------------------------------//
+// Canonical proxy adaptors for canonical type nodes.
+//----------------------------------------------------------------------------//
+
+/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
+/// into an iterator over CanQualTypes.
+template<typename InputIterator>
+class CanTypeIterator {
+ InputIterator Iter;
+
+public:
+ typedef CanQualType value_type;
+ typedef value_type reference;
+ typedef CanProxy<Type> pointer;
+ typedef typename std::iterator_traits<InputIterator>::difference_type
+ difference_type;
+ typedef typename std::iterator_traits<InputIterator>::iterator_category
+ iterator_category;
+
+ CanTypeIterator() : Iter() { }
+ explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
+
+ // Input iterator
+ reference operator*() const {
+ return CanQualType::CreateUnsafe(*Iter);
+ }
+
+ pointer operator->() const;
+
+ CanTypeIterator &operator++() {
+ ++Iter;
+ return *this;
+ }
+
+ CanTypeIterator operator++(int) {
+ CanTypeIterator Tmp(*this);
+ ++Iter;
+ return Tmp;
+ }
+
+ friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
+ return X.Iter == Y.Iter;
+ }
+ friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
+ return X.Iter != Y.Iter;
+ }
+
+ // Bidirectional iterator
+ CanTypeIterator &operator--() {
+ --Iter;
+ return *this;
+ }
+
+ CanTypeIterator operator--(int) {
+ CanTypeIterator Tmp(*this);
+ --Iter;
+ return Tmp;
+ }
+
+ // Random access iterator
+ reference operator[](difference_type n) const {
+ return CanQualType::CreateUnsafe(Iter[n]);
+ }
+
+ CanTypeIterator &operator+=(difference_type n) {
+ Iter += n;
+ return *this;
+ }
+
+ CanTypeIterator &operator-=(difference_type n) {
+ Iter -= n;
+ return *this;
+ }
+
+ friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
+ X += n;
+ return X;
+ }
+
+ friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
+ X += n;
+ return X;
+ }
+
+ friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
+ X -= n;
+ return X;
+ }
+
+ friend difference_type operator-(const CanTypeIterator &X,
+ const CanTypeIterator &Y) {
+ return X - Y;
+ }
+};
+
+template<>
+struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+};
+
+template<>
+struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<BlockPointerType>
+ : public CanProxyBase<BlockPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<LValueReferenceType>
+ : public CanProxyBase<LValueReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<RValueReferenceType>
+ : public CanProxyBase<RValueReferenceType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+};
+
+template<>
+struct CanProxyAdaptor<MemberPointerType>
+ : public CanProxyBase<MemberPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
+};
+
+template<>
+struct CanProxyAdaptor<ArrayType> : public CanProxyBase<ArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+};
+
+template<>
+struct CanProxyAdaptor<ConstantArrayType>
+ : public CanProxyBase<ConstantArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
+};
+
+template<>
+struct CanProxyAdaptor<IncompleteArrayType>
+ : public CanProxyBase<IncompleteArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+};
+
+template<>
+struct CanProxyAdaptor<VariableArrayType>
+ : public CanProxyBase<VariableArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
+ getSizeModifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
+};
+
+template<>
+struct CanProxyAdaptor<DependentSizedArrayType>
+ : public CanProxyBase<DependentSizedArrayType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc)
+};
+
+template<>
+struct CanProxyAdaptor<DependentSizedExtVectorType>
+ : public CanProxyBase<DependentSizedExtVectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
+};
+
+template<>
+struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
+};
+
+template<>
+struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionNoProtoType>
+ : public CanProxyBase<FunctionNoProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionProtoType>
+ : public CanProxyBase<FunctionProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
+ CanQualType getArgType(unsigned i) const {
+ return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
+ }
+
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
+
+ typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
+ arg_type_iterator;
+
+ arg_type_iterator arg_type_begin() const {
+ return arg_type_iterator(this->getTypePtr()->arg_type_begin());
+ }
+
+ arg_type_iterator arg_type_end() const {
+ return arg_type_iterator(this->getTypePtr()->arg_type_end());
+ }
+
+ // Note: canonical function types never have exception specifications
+};
+
+template<>
+struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+};
+
+template<>
+struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+};
+
+template<>
+struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+};
+
+template<>
+struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
+};
+
+template<>
+struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
+};
+
+template<>
+struct CanProxyAdaptor<TemplateTypeParmType>
+ : public CanProxyBase<TemplateTypeParmType> {
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName)
+};
+
+template<>
+struct CanProxyAdaptor<ObjCObjectType>
+ : public CanProxyBase<ObjCObjectType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
+ getInterface)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
+
+ typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
+};
+
+template<>
+struct CanProxyAdaptor<ObjCObjectPointerType>
+ : public CanProxyBase<ObjCObjectPointerType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
+ getInterfaceType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
+
+ typedef ObjCObjectPointerType::qual_iterator qual_iterator;
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
+};
+
+//----------------------------------------------------------------------------//
+// Method and function definitions
+//----------------------------------------------------------------------------//
+template<typename T>
+inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
+ return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
+}
+
+template<typename T>
+inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
+ if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
+ return RefType->getPointeeType();
+ else
+ return *this;
+}
+
+template<typename T>
+CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
+ CanQual<T> Result;
+ Result.Stored = QualType::getFromOpaquePtr(Ptr);
+ assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
+ Result.Stored.isCanonical()) && "Type is not canonical!");
+ return Result;
+}
+
+template<typename T>
+CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
+ assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
+ assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
+ "Dynamic type does not meet the static type's requires");
+ CanQual<T> Result;
+ Result.Stored = Other;
+ return Result;
+}
+
+template<typename T>
+template<typename U>
+CanProxy<U> CanQual<T>::getAs() const {
+ if (Stored.isNull())
+ return CanProxy<U>();
+
+ if (isa<U>(Stored.getTypePtr()))
+ return CanQual<U>::CreateUnsafe(Stored);
+
+ return CanProxy<U>();
+}
+
+template<typename T>
+CanProxy<T> CanQual<T>::operator->() const {
+ return CanProxy<T>(*this);
+}
+
+template<typename InputIterator>
+typename CanTypeIterator<InputIterator>::pointer
+CanTypeIterator<InputIterator>::operator->() const {
+ return CanProxy<Type>(*this);
+}
+
+}
+
+
+#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
new file mode 100644
index 0000000..cf909e8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
@@ -0,0 +1,197 @@
+//===--- CharUnits.h - Character units for sizes and offsets ----*- 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 CharUnits class
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CHARUNITS_H
+#define LLVM_CLANG_AST_CHARUNITS_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+
+namespace clang {
+
+ /// CharUnits - This is an opaque type for sizes expressed in character units.
+ /// Instances of this type represent a quantity as a multiple of the size
+ /// of the standard C type, char, on the target architecture. As an opaque
+ /// type, CharUnits protects you from accidentally combining operations on
+ /// quantities in bit units and character units.
+ ///
+ /// It should be noted that characters and bytes are distinct concepts. Bytes
+ /// refer to addressable units of data storage on the target machine, and
+ /// characters are members of a set of elements used for the organization,
+ /// control, or representation of data. According to C99, bytes are allowed
+ /// to exceed characters in size, although currently, clang only supports
+ /// architectures where the two are the same size.
+ ///
+ /// For portability, never assume that a target character is 8 bits wide. Use
+ /// CharUnit values whereever you calculate sizes, offsets, or alignments
+ /// in character units.
+ class CharUnits {
+ public:
+ typedef int64_t QuantityType;
+
+ private:
+ QuantityType Quantity;
+
+ explicit CharUnits(QuantityType C) : Quantity(C) {}
+
+ public:
+
+ /// CharUnits - A default constructor.
+ CharUnits() : Quantity(0) {}
+
+ /// Zero - Construct a CharUnits quantity of zero.
+ static CharUnits Zero() {
+ return CharUnits(0);
+ }
+
+ /// One - Construct a CharUnits quantity of one.
+ static CharUnits One() {
+ return CharUnits(1);
+ }
+
+ /// fromQuantity - Construct a CharUnits quantity from a raw integer type.
+ static CharUnits fromQuantity(QuantityType Quantity) {
+ return CharUnits(Quantity);
+ }
+
+ // Compound assignment.
+ CharUnits& operator+= (const CharUnits &Other) {
+ Quantity += Other.Quantity;
+ return *this;
+ }
+ CharUnits& operator-= (const CharUnits &Other) {
+ Quantity -= Other.Quantity;
+ return *this;
+ }
+
+ // Comparison operators.
+ bool operator== (const CharUnits &Other) const {
+ return Quantity == Other.Quantity;
+ }
+ bool operator!= (const CharUnits &Other) const {
+ return Quantity != Other.Quantity;
+ }
+
+ // Relational operators.
+ bool operator< (const CharUnits &Other) const {
+ return Quantity < Other.Quantity;
+ }
+ bool operator<= (const CharUnits &Other) const {
+ return Quantity <= Other.Quantity;
+ }
+ bool operator> (const CharUnits &Other) const {
+ return Quantity > Other.Quantity;
+ }
+ bool operator>= (const CharUnits &Other) const {
+ return Quantity >= Other.Quantity;
+ }
+
+ // Other predicates.
+
+ /// isZero - Test whether the quantity equals zero.
+ bool isZero() const { return Quantity == 0; }
+
+ /// isOne - Test whether the quantity equals one.
+ bool isOne() const { return Quantity == 1; }
+
+ /// isPositive - Test whether the quantity is greater than zero.
+ bool isPositive() const { return Quantity > 0; }
+
+ /// isNegative - Test whether the quantity is less than zero.
+ bool isNegative() const { return Quantity < 0; }
+
+ // Arithmetic operators.
+ CharUnits operator* (QuantityType N) const {
+ return CharUnits(Quantity * N);
+ }
+ CharUnits operator/ (QuantityType N) const {
+ return CharUnits(Quantity / N);
+ }
+ QuantityType operator/ (const CharUnits &Other) const {
+ return Quantity / Other.Quantity;
+ }
+ CharUnits operator% (QuantityType N) const {
+ return CharUnits(Quantity % N);
+ }
+ QuantityType operator% (const CharUnits &Other) const {
+ return Quantity % Other.Quantity;
+ }
+ CharUnits operator+ (const CharUnits &Other) const {
+ return CharUnits(Quantity + Other.Quantity);
+ }
+ CharUnits operator- (const CharUnits &Other) const {
+ return CharUnits(Quantity - Other.Quantity);
+ }
+ CharUnits operator- () const {
+ return CharUnits(-Quantity);
+ }
+
+
+ // Conversions.
+
+ /// getQuantity - Get the raw integer representation of this quantity.
+ QuantityType getQuantity() const { return Quantity; }
+
+ /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is
+ /// greater than or equal to this quantity and is a multiple of \arg
+ /// Align. Align must be non-zero.
+ CharUnits RoundUpToAlignment(const CharUnits &Align) {
+ return CharUnits(llvm::RoundUpToAlignment(Quantity,
+ Align.Quantity));
+ }
+
+
+ }; // class CharUnit
+} // namespace clang
+
+inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
+ const clang::CharUnits &CU) {
+ return CU * Scale;
+}
+
+namespace llvm {
+
+template<> struct DenseMapInfo<clang::CharUnits> {
+ static clang::CharUnits getEmptyKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static clang::CharUnits getTombstoneKey() {
+ clang::CharUnits::QuantityType Quantity =
+ DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
+
+ return clang::CharUnits::fromQuantity(Quantity);
+ }
+
+ static unsigned getHashValue(const clang::CharUnits &CU) {
+ clang::CharUnits::QuantityType Quantity = CU.getQuantity();
+ return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
+ }
+
+ static bool isEqual(const clang::CharUnits &LHS,
+ const clang::CharUnits &RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <> struct isPodLike<clang::CharUnits> {
+ static const bool value = true;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CLANG_AST_CHARUNITS_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
new file mode 100644
index 0000000..ee515da
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -0,0 +1,2708 @@
+//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Decl subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECL_H
+#define LLVM_CLANG_AST_DECL_H
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Redeclarable.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/Linkage.h"
+
+namespace clang {
+class CXXTemporary;
+class Expr;
+class FunctionTemplateDecl;
+class Stmt;
+class CompoundStmt;
+class StringLiteral;
+class NestedNameSpecifier;
+class TemplateParameterList;
+class TemplateArgumentList;
+class MemberSpecializationInfo;
+class FunctionTemplateSpecializationInfo;
+class DependentFunctionTemplateSpecializationInfo;
+class TypeLoc;
+class UnresolvedSetImpl;
+class LabelStmt;
+
+/// \brief A container of type source information.
+///
+/// A client can read the relevant info using TypeLoc wrappers, e.g:
+/// @code
+/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
+/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL))
+/// PL->getStarLoc().print(OS, SrcMgr);
+/// @endcode
+///
+class TypeSourceInfo {
+ QualType Ty;
+ // Contains a memory block after the class, used for type source information,
+ // allocated by ASTContext.
+ friend class ASTContext;
+ TypeSourceInfo(QualType ty) : Ty(ty) { }
+public:
+ /// \brief Return the type wrapped by this type source info.
+ QualType getType() const { return Ty; }
+
+ /// \brief Return the TypeLoc wrapper for the type source info.
+ TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
+};
+
+/// TranslationUnitDecl - The top declaration context.
+class TranslationUnitDecl : public Decl, public DeclContext {
+ ASTContext &Ctx;
+
+ /// The (most recently entered) anonymous namespace for this
+ /// translation unit, if one has been created.
+ NamespaceDecl *AnonymousNamespace;
+
+ explicit TranslationUnitDecl(ASTContext &ctx)
+ : Decl(TranslationUnit, 0, SourceLocation()),
+ DeclContext(TranslationUnit),
+ Ctx(ctx), AnonymousNamespace(0) {}
+public:
+ ASTContext &getASTContext() const { return Ctx; }
+
+ NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
+ void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
+
+ static TranslationUnitDecl *Create(ASTContext &C);
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TranslationUnitDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == TranslationUnit; }
+ static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
+ return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
+ }
+ static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// NamedDecl - This represents a decl with a name. Many decls have names such
+/// as ObjCMethodDecl, but not @class, etc.
+class NamedDecl : public Decl {
+ /// Name - The name of this declaration, which is typically a normal
+ /// identifier but may also be a special kind of name (C++
+ /// constructor, Objective-C selector, etc.)
+ DeclarationName Name;
+
+protected:
+ NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
+ : Decl(DK, DC, L), Name(N) { }
+
+public:
+ /// getIdentifier - Get the identifier that names this declaration,
+ /// if there is one. This will return NULL if this declaration has
+ /// no name (e.g., for an unnamed class) or if the name is a special
+ /// name (C++ constructor, Objective-C selector, etc.).
+ IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
+
+ /// getName - Get the name of identifier for this declaration as a StringRef.
+ /// This requires that the declaration have a name and that it be a simple
+ /// identifier.
+ llvm::StringRef getName() const {
+ assert(Name.isIdentifier() && "Name is not a simple identifier");
+ return getIdentifier() ? getIdentifier()->getName() : "";
+ }
+
+ /// getNameAsString - Get a human-readable name for the declaration, even if
+ /// it is one of the special kinds of names (C++ constructor, Objective-C
+ /// selector, etc). Creating this name requires expensive string
+ /// manipulation, so it should be called only when performance doesn't matter.
+ /// For simple declarations, getNameAsCString() should suffice.
+ //
+ // FIXME: This function should be renamed to indicate that it is not just an
+ // alternate form of getName(), and clients should move as appropriate.
+ //
+ // FIXME: Deprecated, move clients to getName().
+ std::string getNameAsString() const { return Name.getAsString(); }
+
+ void printName(llvm::raw_ostream &os) const { return Name.printName(os); }
+
+ /// getDeclName - Get the actual, stored name of the declaration,
+ /// which may be a special name.
+ DeclarationName getDeclName() const { return Name; }
+
+ /// \brief Set the name of this declaration.
+ void setDeclName(DeclarationName N) { Name = N; }
+
+ /// getQualifiedNameAsString - Returns human-readable qualified name for
+ /// declaration, like A::B::i, for i being member of namespace A::B.
+ /// If declaration is not member of context which can be named (record,
+ /// namespace), it will return same result as getNameAsString().
+ /// Creating this name is expensive, so it should be called only when
+ /// performance doesn't matter.
+ std::string getQualifiedNameAsString() const;
+ std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const;
+
+ /// getNameForDiagnostic - Appends a human-readable name for this
+ /// declaration into the given string.
+ ///
+ /// This is the method invoked by Sema when displaying a NamedDecl
+ /// in a diagnostic. It does not necessarily produce the same
+ /// result as getNameAsString(); for example, class template
+ /// specializations are printed with their template arguments.
+ ///
+ /// TODO: use an API that doesn't require so many temporary strings
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const {
+ if (Qualified)
+ S += getQualifiedNameAsString(Policy);
+ else
+ S += getNameAsString();
+ }
+
+ /// declarationReplaces - Determine whether this declaration, if
+ /// known to be well-formed within its context, will replace the
+ /// declaration OldD if introduced into scope. A declaration will
+ /// replace another declaration if, for example, it is a
+ /// redeclaration of the same variable or function, but not if it is
+ /// a declaration of a different kind (function vs. class) or an
+ /// overloaded function.
+ bool declarationReplaces(NamedDecl *OldD) const;
+
+ /// \brief Determine whether this declaration has linkage.
+ bool hasLinkage() const;
+
+ /// \brief Determine whether this declaration is a C++ class member.
+ bool isCXXClassMember() const {
+ const DeclContext *DC = getDeclContext();
+
+ // C++0x [class.mem]p1:
+ // The enumerators of an unscoped enumeration defined in
+ // the class are members of the class.
+ // FIXME: support C++0x scoped enumerations.
+ if (isa<EnumDecl>(DC))
+ DC = DC->getParent();
+
+ return DC->isRecord();
+ }
+
+ /// \brief Given that this declaration is a C++ class member,
+ /// determine whether it's an instance member of its class.
+ bool isCXXInstanceMember() const;
+
+ class LinkageInfo {
+ Linkage linkage_;
+ Visibility visibility_;
+ bool explicit_;
+
+ public:
+ LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
+ explicit_(false) {}
+ LinkageInfo(Linkage L, Visibility V, bool E)
+ : linkage_(L), visibility_(V), explicit_(E) {}
+
+ static LinkageInfo external() {
+ return LinkageInfo();
+ }
+ static LinkageInfo internal() {
+ return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo uniqueExternal() {
+ return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
+ }
+ static LinkageInfo none() {
+ return LinkageInfo(NoLinkage, DefaultVisibility, false);
+ }
+
+ Linkage linkage() const { return linkage_; }
+ Visibility visibility() const { return visibility_; }
+ bool visibilityExplicit() const { return explicit_; }
+
+ void setLinkage(Linkage L) { linkage_ = L; }
+ void setVisibility(Visibility V) { visibility_ = V; }
+ void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
+ void setVisibility(LinkageInfo Other) {
+ setVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void mergeLinkage(Linkage L) {
+ setLinkage(minLinkage(linkage(), L));
+ }
+ void mergeLinkage(LinkageInfo Other) {
+ setLinkage(minLinkage(linkage(), Other.linkage()));
+ }
+
+ void mergeVisibility(Visibility V) {
+ setVisibility(minVisibility(visibility(), V));
+ }
+ void mergeVisibility(Visibility V, bool E) {
+ setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
+ }
+ void mergeVisibility(LinkageInfo Other) {
+ mergeVisibility(Other.visibility(), Other.visibilityExplicit());
+ }
+
+ void merge(LinkageInfo Other) {
+ mergeLinkage(Other);
+ mergeVisibility(Other);
+ }
+ void merge(std::pair<Linkage,Visibility> LV) {
+ mergeLinkage(LV.first);
+ mergeVisibility(LV.second);
+ }
+
+ friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
+ L.merge(R);
+ return L;
+ }
+ };
+
+ /// \brief Determine what kind of linkage this entity has.
+ Linkage getLinkage() const;
+
+ /// \brief Determines the visibility of this entity.
+ Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); }
+
+ /// \brief Determines the linkage and visibility of this entity.
+ LinkageInfo getLinkageAndVisibility() const;
+
+ /// \brief Clear the linkage cache in response to a change
+ /// to the declaration.
+ void ClearLinkageCache();
+
+ /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
+ /// the underlying named decl.
+ NamedDecl *getUnderlyingDecl();
+ const NamedDecl *getUnderlyingDecl() const {
+ return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const NamedDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
+};
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const NamedDecl *ND) {
+ ND->getDeclName().printName(OS);
+ return OS;
+}
+
+/// LabelDecl - Represents the declaration of a label. Labels also have a
+/// corresponding LabelStmt, which indicates the position that the label was
+/// defined at. For normal labels, the location of the decl is the same as the
+/// location of the statement. For GNU local labels (__label__), the decl
+/// location is where the __label__ is.
+class LabelDecl : public NamedDecl {
+ LabelStmt *TheStmt;
+ LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S)
+ : NamedDecl(Label, DC, L, II), TheStmt(S) {}
+
+public:
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *II);
+
+ LabelStmt *getStmt() const { return TheStmt; }
+ void setStmt(LabelStmt *T) { TheStmt = T; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const LabelDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Label; }
+};
+
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public NamedDecl, public DeclContext {
+ bool IsInline : 1;
+
+ SourceLocation LBracLoc, RBracLoc;
+
+ // For extended namespace definitions:
+ //
+ // namespace A { int x; }
+ // namespace A { int y; }
+ //
+ // there will be one NamespaceDecl for each declaration.
+ // NextNamespace points to the next extended declaration.
+ // OrigNamespace points to the original namespace declaration.
+ // OrigNamespace of the first namespace decl points to its anonymous namespace
+ LazyDeclPtr NextNamespace;
+
+ /// \brief A pointer to either the original namespace definition for
+ /// this namespace (if the boolean value is false) or the anonymous
+ /// namespace that lives just inside this namespace (if the boolean
+ /// value is true).
+ ///
+ /// We can combine these two notions because the anonymous namespace
+ /// must only be stored in one of the namespace declarations (so all
+ /// of the namespace declarations can find it). We therefore choose
+ /// the original namespace declaration, since all of the namespace
+ /// declarations have a link directly to it; the original namespace
+ /// declaration itself only needs to know that it is the original
+ /// namespace declaration (which the boolean indicates).
+ llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace;
+
+ NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+ : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
+ IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { }
+
+public:
+ static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ /// \brief Returns true if this is an anonymous namespace declaration.
+ ///
+ /// For example:
+ /// \code
+ /// namespace {
+ /// ...
+ /// };
+ /// \endcode
+ /// q.v. C++ [namespace.unnamed]
+ bool isAnonymousNamespace() const {
+ return !getIdentifier();
+ }
+
+ /// \brief Returns true if this is an inline namespace declaration.
+ bool isInline() const {
+ return IsInline;
+ }
+
+ /// \brief Set whether this is an inline namespace declaration.
+ void setInline(bool Inline) {
+ IsInline = Inline;
+ }
+
+ /// \brief Return the next extended namespace declaration or null if there
+ /// is none.
+ NamespaceDecl *getNextNamespace();
+ const NamespaceDecl *getNextNamespace() const {
+ return const_cast<NamespaceDecl *>(this)->getNextNamespace();
+ }
+
+ /// \brief Set the next extended namespace declaration.
+ void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
+
+ /// \brief Get the original (first) namespace declaration.
+ NamespaceDecl *getOriginalNamespace() const {
+ if (OrigOrAnonNamespace.getInt())
+ return const_cast<NamespaceDecl *>(this);
+
+ return OrigOrAnonNamespace.getPointer();
+ }
+
+ /// \brief Return true if this declaration is an original (first) declaration
+ /// of the namespace. This is false for non-original (subsequent) namespace
+ /// declarations and anonymous namespaces.
+ bool isOriginalNamespace() const {
+ return getOriginalNamespace() == this;
+ }
+
+ /// \brief Set the original (first) namespace declaration.
+ void setOriginalNamespace(NamespaceDecl *ND) {
+ if (ND != this) {
+ OrigOrAnonNamespace.setPointer(ND);
+ OrigOrAnonNamespace.setInt(false);
+ }
+ }
+
+ NamespaceDecl *getAnonymousNamespace() const {
+ return getOriginalNamespace()->OrigOrAnonNamespace.getPointer();
+ }
+
+ void setAnonymousNamespace(NamespaceDecl *D) {
+ assert(!D || D->isAnonymousNamespace());
+ assert(!D || D->getParent() == this);
+ getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D);
+ }
+
+ virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); }
+ const NamespaceDecl *getCanonicalDecl() const {
+ return getOriginalNamespace();
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), RBracLoc);
+ }
+
+ SourceLocation getLBracLoc() const { return LBracLoc; }
+ SourceLocation getRBracLoc() const { return RBracLoc; }
+ void setLBracLoc(SourceLocation L) { LBracLoc = L; }
+ void setRBracLoc(SourceLocation R) { RBracLoc = R; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const NamespaceDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Namespace; }
+ static DeclContext *castToDeclContext(const NamespaceDecl *D) {
+ return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D));
+ }
+ static NamespaceDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// ValueDecl - Represent the declaration of a variable (in which case it is
+/// an lvalue) a function (in which case it is a function designator) or
+/// an enum constant.
+class ValueDecl : public NamedDecl {
+ QualType DeclType;
+
+protected:
+ ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T)
+ : NamedDecl(DK, DC, L, N), DeclType(T) {}
+public:
+ QualType getType() const { return DeclType; }
+ void setType(QualType newType) { DeclType = newType; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ValueDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
+};
+
+/// QualifierInfo - A struct with extended info about a syntactic
+/// name qualifier, to be used for the case of out-of-line declarations.
+struct QualifierInfo {
+ /// NNS - The syntactic name qualifier.
+ NestedNameSpecifier *NNS;
+ /// NNSRange - The source range for the qualifier.
+ SourceRange NNSRange;
+ /// NumTemplParamLists - The number of template parameter lists
+ /// that were matched against the template-ids occurring into the NNS.
+ unsigned NumTemplParamLists;
+ /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
+ /// containing pointers to the matched template parameter lists.
+ TemplateParameterList** TemplParamLists;
+
+ /// Default constructor.
+ QualifierInfo()
+ : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {}
+ /// setTemplateParameterListsInfo - Sets info about matched template
+ /// parameter lists.
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ unsigned NumTPLists,
+ TemplateParameterList **TPLists);
+
+private:
+ // Copy constructor and copy assignment are disabled.
+ QualifierInfo(const QualifierInfo&);
+ QualifierInfo& operator=(const QualifierInfo&);
+};
+
+/// \brief Represents a ValueDecl that came out of a declarator.
+/// Contains type source information through TypeSourceInfo.
+class DeclaratorDecl : public ValueDecl {
+ // A struct representing both a TInfo and a syntactic qualifier,
+ // to be used for the (uncommon) case of out-of-line declarations.
+ struct ExtInfo : public QualifierInfo {
+ TypeSourceInfo *TInfo;
+ };
+
+ llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
+
+ bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); }
+ ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); }
+ const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); }
+
+protected:
+ DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T, TypeSourceInfo *TInfo)
+ : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
+
+public:
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return hasExtInfo()
+ ? getExtInfo()->TInfo
+ : DeclInfo.get<TypeSourceInfo*>();
+ }
+ void setTypeSourceInfo(TypeSourceInfo *TI) {
+ if (hasExtInfo())
+ getExtInfo()->TInfo = TI;
+ else
+ DeclInfo = TI;
+ }
+
+ /// getInnerLocStart - Return SourceLocation representing start of source
+ /// range ignoring outer template declarations.
+ virtual SourceLocation getInnerLocStart() const { return getLocation(); }
+
+ /// getOuterLocStart - Return SourceLocation representing start of source
+ /// range taking into account any outer template declarations.
+ SourceLocation getOuterLocStart() const;
+ SourceRange getSourceRange() const {
+ return SourceRange(getOuterLocStart(), getLocation());
+ }
+
+ NestedNameSpecifier *getQualifier() const {
+ return hasExtInfo() ? getExtInfo()->NNS : 0;
+ }
+ SourceRange getQualifierRange() const {
+ return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+ }
+ void setQualifierInfo(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange);
+
+ unsigned getNumTemplateParameterLists() const {
+ return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+ }
+ TemplateParameterList *getTemplateParameterList(unsigned index) const {
+ assert(index < getNumTemplateParameterLists());
+ return getExtInfo()->TemplParamLists[index];
+ }
+ void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
+ TemplateParameterList **TPLists) {
+ getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+ }
+
+ SourceLocation getTypeSpecStartLoc() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const DeclaratorDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstDeclarator && K <= lastDeclarator;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Structure used to store a statement, the constant value to
+/// which it was evaluated (if any), and whether or not the statement
+/// is an integral constant expression (if known).
+struct EvaluatedStmt {
+ EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
+ CheckingICE(false), IsICE(false) { }
+
+ /// \brief Whether this statement was already evaluated.
+ bool WasEvaluated : 1;
+
+ /// \brief Whether this statement is being evaluated.
+ bool IsEvaluating : 1;
+
+ /// \brief Whether we already checked whether this statement was an
+ /// integral constant expression.
+ bool CheckedICE : 1;
+
+ /// \brief Whether we are checking whether this statement is an
+ /// integral constant expression.
+ bool CheckingICE : 1;
+
+ /// \brief Whether this statement is an integral constant
+ /// expression. Only valid if CheckedICE is true.
+ bool IsICE : 1;
+
+ Stmt *Value;
+ APValue Evaluated;
+};
+
+/// VarDecl - An instance of this class is created to represent a variable
+/// declaration or definition.
+class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
+public:
+ typedef clang::StorageClass StorageClass;
+
+ /// getStorageClassSpecifierString - Return the string used to
+ /// specify the storage class \arg SC.
+ ///
+ /// It is illegal to call this function with SC == None.
+ static const char *getStorageClassSpecifierString(StorageClass SC);
+
+protected:
+ /// \brief Placeholder type used in Init to denote an unparsed C++ default
+ /// argument.
+ struct UnparsedDefaultArgument;
+
+ /// \brief Placeholder type used in Init to denote an uninstantiated C++
+ /// default argument.
+ struct UninstantiatedDefaultArgument;
+
+ typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
+ UnparsedDefaultArgument *,
+ UninstantiatedDefaultArgument *> InitType;
+
+ /// \brief The initializer for this variable or, for a ParmVarDecl, the
+ /// C++ default argument.
+ mutable InitType Init;
+
+private:
+ // FIXME: This can be packed into the bitfields in Decl.
+ unsigned SClass : 3;
+ unsigned SClassAsWritten : 3;
+ bool ThreadSpecified : 1;
+ bool HasCXXDirectInit : 1;
+
+ /// \brief Whether this variable is the exception variable in a C++ catch
+ /// or an Objective-C @catch statement.
+ bool ExceptionVar : 1;
+
+ /// \brief Whether this local variable could be allocated in the return
+ /// slot of its function, enabling the named return value optimization (NRVO).
+ bool NRVOVariable : 1;
+
+ /// \brief Whether this variable has a deduced C++0x auto type for which we're
+ /// currently parsing the initializer.
+ bool ParsingAutoInit : 1;
+
+ friend class StmtIteratorBase;
+ friend class ASTDeclReader;
+
+protected:
+ VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo, StorageClass SC,
+ StorageClass SCAsWritten)
+ : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
+ ThreadSpecified(false), HasCXXDirectInit(false),
+ ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
+ SClass = SC;
+ SClassAsWritten = SCAsWritten;
+ }
+
+ typedef Redeclarable<VarDecl> redeclarable_base;
+ virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
+public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
+ static VarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo, StorageClass S,
+ StorageClass SCAsWritten);
+
+ virtual SourceLocation getInnerLocStart() const;
+ virtual SourceRange getSourceRange() const;
+
+ StorageClass getStorageClass() const { return (StorageClass)SClass; }
+ StorageClass getStorageClassAsWritten() const {
+ return (StorageClass) SClassAsWritten;
+ }
+ void setStorageClass(StorageClass SC);
+ void setStorageClassAsWritten(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ SClassAsWritten = SC;
+ }
+
+ void setThreadSpecified(bool T) { ThreadSpecified = T; }
+ bool isThreadSpecified() const {
+ return ThreadSpecified;
+ }
+
+ /// hasLocalStorage - Returns true if a variable with function scope
+ /// is a non-static local variable.
+ bool hasLocalStorage() const {
+ if (getStorageClass() == SC_None)
+ return !isFileVarDecl();
+
+ // Return true for: Auto, Register.
+ // Return false for: Extern, Static, PrivateExtern.
+
+ return getStorageClass() >= SC_Auto;
+ }
+
+ /// isStaticLocal - Returns true if a variable with function scope is a
+ /// static local variable.
+ bool isStaticLocal() const {
+ return getStorageClass() == SC_Static && !isFileVarDecl();
+ }
+
+ /// hasExternStorage - Returns true if a variable has extern or
+ /// __private_extern__ storage.
+ bool hasExternalStorage() const {
+ return getStorageClass() == SC_Extern ||
+ getStorageClass() == SC_PrivateExtern;
+ }
+
+ /// hasGlobalStorage - Returns true for all variables that do not
+ /// have local storage. This includs all global variables as well
+ /// as static variables declared within a function.
+ bool hasGlobalStorage() const { return !hasLocalStorage(); }
+
+ /// \brief Determines whether this variable is a variable with
+ /// external, C linkage.
+ bool isExternC() const;
+
+ /// isLocalVarDecl - Returns true for local variable declarations
+ /// other than parameters. Note that this includes static variables
+ /// inside of functions. It also includes variables inside blocks.
+ ///
+ /// void foo() { int x; static int y; extern int z; }
+ ///
+ bool isLocalVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ if (const DeclContext *DC = getDeclContext())
+ return DC->getRedeclContext()->isFunctionOrMethod();
+ return false;
+ }
+
+ /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
+ /// excludes variables declared in blocks.
+ bool isFunctionOrMethodVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
+ }
+
+ /// \brief Determines whether this is a static data member.
+ ///
+ /// This will only be true in C++, and applies to, e.g., the
+ /// variable 'x' in:
+ /// \code
+ /// struct S {
+ /// static int x;
+ /// };
+ /// \endcode
+ bool isStaticDataMember() const {
+ // If it wasn't static, it would be a FieldDecl.
+ return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
+ }
+
+ virtual VarDecl *getCanonicalDecl();
+ const VarDecl *getCanonicalDecl() const {
+ return const_cast<VarDecl*>(this)->getCanonicalDecl();
+ }
+
+ enum DefinitionKind {
+ DeclarationOnly, ///< This declaration is only a declaration.
+ TentativeDefinition, ///< This declaration is a tentative definition.
+ Definition ///< This declaration is definitely a definition.
+ };
+
+ /// \brief Check whether this declaration is a definition. If this could be
+ /// a tentative definition (in C), don't check whether there's an overriding
+ /// definition.
+ DefinitionKind isThisDeclarationADefinition() const;
+
+ /// \brief Check whether this variable is defined in this
+ /// translation unit.
+ DefinitionKind hasDefinition() const;
+
+ /// \brief Get the tentative definition that acts as the real definition in
+ /// a TU. Returns null if there is a proper definition available.
+ VarDecl *getActingDefinition();
+ const VarDecl *getActingDefinition() const {
+ return const_cast<VarDecl*>(this)->getActingDefinition();
+ }
+
+ /// \brief Determine whether this is a tentative definition of a
+ /// variable in C.
+ bool isTentativeDefinitionNow() const;
+
+ /// \brief Get the real (not just tentative) definition for this declaration.
+ VarDecl *getDefinition();
+ const VarDecl *getDefinition() const {
+ return const_cast<VarDecl*>(this)->getDefinition();
+ }
+
+ /// \brief Determine whether this is or was instantiated from an out-of-line
+ /// definition of a static data member.
+ virtual bool isOutOfLine() const;
+
+ /// \brief If this is a static data member, find its out-of-line definition.
+ VarDecl *getOutOfLineDefinition();
+
+ /// isFileVarDecl - Returns true for file scoped variable declaration.
+ bool isFileVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+
+ if (getDeclContext()->getRedeclContext()->isFileContext())
+ return true;
+
+ if (isStaticDataMember())
+ return true;
+
+ return false;
+ }
+
+ /// getAnyInitializer - Get the initializer for this variable, no matter which
+ /// declaration it is attached to.
+ const Expr *getAnyInitializer() const {
+ const VarDecl *D;
+ return getAnyInitializer(D);
+ }
+
+ /// getAnyInitializer - Get the initializer for this variable, no matter which
+ /// declaration it is attached to. Also get that declaration.
+ const Expr *getAnyInitializer(const VarDecl *&D) const;
+
+ bool hasInit() const {
+ return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
+ }
+ const Expr *getInit() const {
+ if (Init.isNull())
+ return 0;
+
+ const Stmt *S = Init.dyn_cast<Stmt *>();
+ if (!S) {
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ S = ES->Value;
+ }
+ return (const Expr*) S;
+ }
+ Expr *getInit() {
+ if (Init.isNull())
+ return 0;
+
+ Stmt *S = Init.dyn_cast<Stmt *>();
+ if (!S) {
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ S = ES->Value;
+ }
+
+ return (Expr*) S;
+ }
+
+ /// \brief Retrieve the address of the initializer expression.
+ Stmt **getInitAddress() {
+ if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
+ return &ES->Value;
+
+ // This union hack tip-toes around strict-aliasing rules.
+ union {
+ InitType *InitPtr;
+ Stmt **StmtPtr;
+ };
+
+ InitPtr = &Init;
+ return StmtPtr;
+ }
+
+ void setInit(Expr *I);
+
+ /// \brief Check whether we are in the process of parsing an initializer
+ /// needed to deduce the type of this variable.
+ bool isParsingAutoInit() const {
+ return ParsingAutoInit;
+ }
+
+ /// \brief Note whether we are currently parsing an initializer needed to
+ /// deduce the type of this variable.
+ void setParsingAutoInit(bool P) {
+ ParsingAutoInit = P;
+ }
+
+ EvaluatedStmt *EnsureEvaluatedStmt() const {
+ EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
+ if (!Eval) {
+ Stmt *S = Init.get<Stmt *>();
+ Eval = new (getASTContext()) EvaluatedStmt;
+ Eval->Value = S;
+ Init = Eval;
+ }
+ return Eval;
+ }
+
+ /// \brief Check whether we are in the process of checking whether the
+ /// initializer can be evaluated.
+ bool isEvaluatingValue() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->IsEvaluating;
+
+ return false;
+ }
+
+ /// \brief Note that we now are checking whether the initializer can be
+ /// evaluated.
+ void setEvaluatingValue() const {
+ EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+ Eval->IsEvaluating = true;
+ }
+
+ /// \brief Note that constant evaluation has computed the given
+ /// value for this variable's initializer.
+ void setEvaluatedValue(const APValue &Value) const {
+ EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+ Eval->IsEvaluating = false;
+ Eval->WasEvaluated = true;
+ Eval->Evaluated = Value;
+ }
+
+ /// \brief Return the already-evaluated value of this variable's
+ /// initializer, or NULL if the value is not yet known. Returns pointer
+ /// to untyped APValue if the value could not be evaluated.
+ APValue *getEvaluatedValue() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ if (Eval->WasEvaluated)
+ return &Eval->Evaluated;
+
+ return 0;
+ }
+
+ /// \brief Determines whether it is already known whether the
+ /// initializer is an integral constant expression or not.
+ bool isInitKnownICE() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->CheckedICE;
+
+ return false;
+ }
+
+ /// \brief Determines whether the initializer is an integral
+ /// constant expression.
+ ///
+ /// \pre isInitKnownICE()
+ bool isInitICE() const {
+ assert(isInitKnownICE() &&
+ "Check whether we already know that the initializer is an ICE");
+ return Init.get<EvaluatedStmt *>()->IsICE;
+ }
+
+ /// \brief Check whether we are in the process of checking the initializer
+ /// is an integral constant expression.
+ bool isCheckingICE() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->CheckingICE;
+
+ return false;
+ }
+
+ /// \brief Note that we now are checking whether the initializer is an
+ /// integral constant expression.
+ void setCheckingICE() const {
+ EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+ Eval->CheckingICE = true;
+ }
+
+ /// \brief Note that we now know whether the initializer is an
+ /// integral constant expression.
+ void setInitKnownICE(bool IsICE) const {
+ EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+ Eval->CheckingICE = false;
+ Eval->CheckedICE = true;
+ Eval->IsICE = IsICE;
+ }
+
+ void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; }
+
+ /// hasCXXDirectInitializer - If true, the initializer was a direct
+ /// initializer, e.g: "int x(1);". The Init expression will be the expression
+ /// inside the parens or a "ClassType(a,b,c)" class constructor expression for
+ /// class types. Clients can distinguish between "int x(1);" and "int x=1;"
+ /// by checking hasCXXDirectInitializer.
+ ///
+ bool hasCXXDirectInitializer() const {
+ return HasCXXDirectInit;
+ }
+
+ /// \brief Determine whether this variable is the exception variable in a
+ /// C++ catch statememt or an Objective-C @catch statement.
+ bool isExceptionVariable() const {
+ return ExceptionVar;
+ }
+ void setExceptionVariable(bool EV) { ExceptionVar = EV; }
+
+ /// \brief Determine whether this local variable can be used with the named
+ /// return value optimization (NRVO).
+ ///
+ /// The named return value optimization (NRVO) works by marking certain
+ /// non-volatile local variables of class type as NRVO objects. These
+ /// locals can be allocated within the return slot of their containing
+ /// function, in which case there is no need to copy the object to the
+ /// return slot when returning from the function. Within the function body,
+ /// each return that returns the NRVO object will have this variable as its
+ /// NRVO candidate.
+ bool isNRVOVariable() const { return NRVOVariable; }
+ void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; }
+
+ /// \brief If this variable is an instantiated static data member of a
+ /// class template specialization, returns the templated static data member
+ /// from which it was instantiated.
+ VarDecl *getInstantiatedFromStaticDataMember() const;
+
+ /// \brief If this variable is a static data member, determine what kind of
+ /// template specialization or instantiation this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief If this variable is an instantiation of a static data member of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
+ /// \brief For a static data member that was instantiated from a static
+ /// data member of a class template, set the template specialiation kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation = SourceLocation());
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const VarDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
+};
+
+class ImplicitParamDecl : public VarDecl {
+protected:
+ ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType Tw)
+ : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {
+ setImplicit();
+ }
+public:
+ static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T);
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const ImplicitParamDecl *D) { return true; }
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ImplicitParam; }
+};
+
+/// ParmVarDecl - Represent a parameter to a function.
+class ParmVarDecl : public VarDecl {
+ // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
+ /// FIXME: Also can be paced into the bitfields in Decl.
+ /// in, inout, etc.
+ unsigned objcDeclQualifier : 6;
+ bool HasInheritedDefaultArg : 1;
+
+protected:
+ ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten, Expr *DefArg)
+ : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten),
+ objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) {
+ setDefaultArg(DefArg);
+ }
+
+public:
+ static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten,
+ Expr *DefArg);
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return ObjCDeclQualifier(objcDeclQualifier);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QTVal) {
+ objcDeclQualifier = QTVal;
+ }
+
+ Expr *getDefaultArg();
+ const Expr *getDefaultArg() const {
+ return const_cast<ParmVarDecl *>(this)->getDefaultArg();
+ }
+
+ void setDefaultArg(Expr *defarg) {
+ Init = reinterpret_cast<Stmt *>(defarg);
+ }
+
+ unsigned getNumDefaultArgTemporaries() const;
+ CXXTemporary *getDefaultArgTemporary(unsigned i);
+ const CXXTemporary *getDefaultArgTemporary(unsigned i) const {
+ return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i);
+ }
+
+ /// \brief Retrieve the source range that covers the entire default
+ /// argument.
+ SourceRange getDefaultArgRange() const;
+ void setUninstantiatedDefaultArg(Expr *arg) {
+ Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
+ }
+ Expr *getUninstantiatedDefaultArg() {
+ return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ }
+ const Expr *getUninstantiatedDefaultArg() const {
+ return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ }
+
+ /// hasDefaultArg - Determines whether this parameter has a default argument,
+ /// either parsed or not.
+ bool hasDefaultArg() const {
+ return getInit() || hasUnparsedDefaultArg() ||
+ hasUninstantiatedDefaultArg();
+ }
+
+ /// hasUnparsedDefaultArg - Determines whether this parameter has a
+ /// default argument that has not yet been parsed. This will occur
+ /// during the processing of a C++ class whose member functions have
+ /// default arguments, e.g.,
+ /// @code
+ /// class X {
+ /// public:
+ /// void f(int x = 17); // x has an unparsed default argument now
+ /// }; // x has a regular default argument now
+ /// @endcode
+ bool hasUnparsedDefaultArg() const {
+ return Init.is<UnparsedDefaultArgument*>();
+ }
+
+ bool hasUninstantiatedDefaultArg() const {
+ return Init.is<UninstantiatedDefaultArgument*>();
+ }
+
+ /// setUnparsedDefaultArg - Specify that this parameter has an
+ /// unparsed default argument. The argument will be replaced with a
+ /// real default argument via setDefaultArg when the class
+ /// definition enclosing the function declaration that owns this
+ /// default argument is completed.
+ void setUnparsedDefaultArg() {
+ Init = (UnparsedDefaultArgument *)0;
+ }
+
+ bool hasInheritedDefaultArg() const {
+ return HasInheritedDefaultArg;
+ }
+
+ void setHasInheritedDefaultArg(bool I = true) {
+ HasInheritedDefaultArg = I;
+ }
+
+ QualType getOriginalType() const {
+ if (getTypeSourceInfo())
+ return getTypeSourceInfo()->getType();
+ return getType();
+ }
+
+ /// \brief Determine whether this parameter is actually a function
+ /// parameter pack.
+ bool isParameterPack() const;
+
+ /// setOwningFunction - Sets the function declaration that owns this
+ /// ParmVarDecl. Since ParmVarDecls are often created before the
+ /// FunctionDecls that own them, this routine is required to update
+ /// the DeclContext appropriately.
+ void setOwningFunction(DeclContext *FD) { setDeclContext(FD); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ParmVarDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ParmVar; }
+};
+
+/// FunctionDecl - An instance of this class is created to represent a
+/// function declaration or definition.
+///
+/// Since a given function can be declared several times in a program,
+/// there may be several FunctionDecls that correspond to that
+/// function. Only one of those FunctionDecls will be found when
+/// traversing the list of declarations in the context of the
+/// FunctionDecl (e.g., the translation unit); this FunctionDecl
+/// contains all of the information known about the function. Other,
+/// previous declarations of the function are available via the
+/// getPreviousDeclaration() chain.
+class FunctionDecl : public DeclaratorDecl, public DeclContext,
+ public Redeclarable<FunctionDecl> {
+public:
+ typedef clang::StorageClass StorageClass;
+
+ /// \brief The kind of templated function a FunctionDecl can be.
+ enum TemplatedKind {
+ TK_NonTemplate,
+ TK_FunctionTemplate,
+ TK_MemberSpecialization,
+ TK_FunctionTemplateSpecialization,
+ TK_DependentFunctionTemplateSpecialization
+ };
+
+private:
+ /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
+ /// parameters of this function. This is null if a prototype or if there are
+ /// no formals.
+ ParmVarDecl **ParamInfo;
+
+ LazyDeclStmtPtr Body;
+
+ // FIXME: This can be packed into the bitfields in Decl.
+ // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ unsigned SClass : 2;
+ unsigned SClassAsWritten : 2;
+ bool IsInline : 1;
+ bool IsInlineSpecified : 1;
+ bool IsVirtualAsWritten : 1;
+ bool IsPure : 1;
+ bool HasInheritedPrototype : 1;
+ bool HasWrittenPrototype : 1;
+ bool IsDeleted : 1;
+ bool IsTrivial : 1; // sunk from CXXMethodDecl
+ bool HasImplicitReturnZero : 1;
+
+ /// \brief End part of this FunctionDecl's source range.
+ ///
+ /// We could compute the full range in getSourceRange(). However, when we're
+ /// dealing with a function definition deserialized from a PCH/AST file,
+ /// we can only compute the full range once the function body has been
+ /// de-serialized, so it's far better to have the (sometimes-redundant)
+ /// EndRangeLoc.
+ SourceLocation EndRangeLoc;
+
+ /// \brief The template or declaration that this declaration
+ /// describes or was instantiated from, respectively.
+ ///
+ /// For non-templates, this value will be NULL. For function
+ /// declarations that describe a function template, this will be a
+ /// pointer to a FunctionTemplateDecl. For member functions
+ /// of class template specializations, this will be a MemberSpecializationInfo
+ /// pointer containing information about the specialization.
+ /// For function template specializations, this will be a
+ /// FunctionTemplateSpecializationInfo, which contains information about
+ /// the template being specialized and the template arguments involved in
+ /// that specialization.
+ llvm::PointerUnion4<FunctionTemplateDecl *,
+ MemberSpecializationInfo *,
+ FunctionTemplateSpecializationInfo *,
+ DependentFunctionTemplateSpecializationInfo *>
+ TemplateOrSpecialization;
+
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the DeclaratorDecl base class.
+ DeclarationNameLoc DNLoc;
+
+ /// \brief Specify that this function declaration is actually a function
+ /// template specialization.
+ ///
+ /// \param C the ASTContext.
+ ///
+ /// \param Template the function template that this function template
+ /// specialization specializes.
+ ///
+ /// \param TemplateArgs the template arguments that produced this
+ /// function template specialization from the template.
+ ///
+ /// \param InsertPos If non-NULL, the position in the function template
+ /// specialization set where the function template specialization data will
+ /// be inserted.
+ ///
+ /// \param TSK the kind of template specialization this is.
+ ///
+ /// \param TemplateArgsAsWritten location info of template arguments.
+ ///
+ /// \param PointOfInstantiation point at which the function template
+ /// specialization was first instantiated.
+ void setFunctionTemplateSpecialization(ASTContext &C,
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation);
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member function FD.
+ void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
+ TemplateSpecializationKind TSK);
+
+ void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams);
+
+protected:
+ FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified)
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
+ DeclContext(DK),
+ ParamInfo(0), Body(),
+ SClass(S), SClassAsWritten(SCAsWritten),
+ IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
+ IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
+ HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+ HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()),
+ TemplateOrSpecialization(),
+ DNLoc(NameInfo.getInfo()) {}
+
+ typedef Redeclarable<FunctionDecl> redeclarable_base;
+ virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
+public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ TypeSourceInfo *TInfo,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
+ bool isInlineSpecified = false,
+ bool hasWrittenPrototype = true) {
+ DeclarationNameInfo NameInfo(N, L);
+ return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
+ isInlineSpecified, hasWrittenPrototype);
+ }
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
+ bool isInlineSpecified = false,
+ bool hasWrittenPrototype = true);
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getOuterLocStart(), EndRangeLoc);
+ }
+ void setLocEnd(SourceLocation E) {
+ EndRangeLoc = E;
+ }
+
+ /// \brief Returns true if the function has a body (definition). The
+ /// function body might be in any of the (re-)declarations of this
+ /// function. The variant that accepts a FunctionDecl pointer will
+ /// set that function declaration to the actual declaration
+ /// containing the body (if there is one).
+ bool hasBody(const FunctionDecl *&Definition) const;
+
+ virtual bool hasBody() const {
+ const FunctionDecl* Definition;
+ return hasBody(Definition);
+ }
+
+ /// getBody - Retrieve the body (definition) of the function. The
+ /// function body might be in any of the (re-)declarations of this
+ /// function. The variant that accepts a FunctionDecl pointer will
+ /// set that function declaration to the actual declaration
+ /// containing the body (if there is one).
+ /// NOTE: For checking if there is a body, use hasBody() instead, to avoid
+ /// unnecessary AST de-serialization of the body.
+ Stmt *getBody(const FunctionDecl *&Definition) const;
+
+ virtual Stmt *getBody() const {
+ const FunctionDecl* Definition;
+ return getBody(Definition);
+ }
+
+ /// isThisDeclarationADefinition - Returns whether this specific
+ /// declaration of the function is also a definition. This does not
+ /// determine whether the function has been defined (e.g., in a
+ /// previous definition); for that information, use getBody.
+ /// FIXME: Should return true if function is deleted or defaulted. However,
+ /// CodeGenModule.cpp uses it, and I don't know if this would break it.
+ bool isThisDeclarationADefinition() const { return Body; }
+
+ void setBody(Stmt *B);
+ void setLazyBody(uint64_t Offset) { Body = Offset; }
+
+ /// Whether this function is variadic.
+ bool isVariadic() const;
+
+ /// Whether this function is marked as virtual explicitly.
+ bool isVirtualAsWritten() const { return IsVirtualAsWritten; }
+ void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; }
+
+ /// Whether this virtual function is pure, i.e. makes the containing class
+ /// abstract.
+ bool isPure() const { return IsPure; }
+ void setPure(bool P = true);
+
+ /// Whether this function is "trivial" in some specialized C++ senses.
+ /// Can only be true for default constructors, copy constructors,
+ /// copy assignment operators, and destructors. Not meaningful until
+ /// the class has been fully built by Sema.
+ bool isTrivial() const { return IsTrivial; }
+ void setTrivial(bool IT) { IsTrivial = IT; }
+
+ /// Whether falling off this function implicitly returns null/zero.
+ /// If a more specific implicit return value is required, front-ends
+ /// should synthesize the appropriate return statements.
+ bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
+ void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }
+
+ /// \brief Whether this function has a prototype, either because one
+ /// was explicitly written or because it was "inherited" by merging
+ /// a declaration without a prototype with a declaration that has a
+ /// prototype.
+ bool hasPrototype() const {
+ return HasWrittenPrototype || HasInheritedPrototype;
+ }
+
+ bool hasWrittenPrototype() const { return HasWrittenPrototype; }
+
+ /// \brief Whether this function inherited its prototype from a
+ /// previous declaration.
+ bool hasInheritedPrototype() const { return HasInheritedPrototype; }
+ void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
+
+ /// \brief Whether this function has been deleted.
+ ///
+ /// A function that is "deleted" (via the C++0x "= delete" syntax)
+ /// acts like a normal function, except that it cannot actually be
+ /// called or have its address taken. Deleted functions are
+ /// typically used in C++ overload resolution to attract arguments
+ /// whose type or lvalue/rvalue-ness would permit the use of a
+ /// different overload that would behave incorrectly. For example,
+ /// one might use deleted functions to ban implicit conversion from
+ /// a floating-point number to an Integer type:
+ ///
+ /// @code
+ /// struct Integer {
+ /// Integer(long); // construct from a long
+ /// Integer(double) = delete; // no construction from float or double
+ /// Integer(long double) = delete; // no construction from long double
+ /// };
+ /// @endcode
+ bool isDeleted() const { return IsDeleted; }
+ void setDeleted(bool D = true) { IsDeleted = D; }
+
+ /// \brief Determines whether this is a function "main", which is
+ /// the entry point into an executable program.
+ bool isMain() const;
+
+ /// \brief Determines whether this function is a function with
+ /// external, C linkage.
+ bool isExternC() const;
+
+ /// \brief Determines whether this is a global function.
+ bool isGlobal() const;
+
+ void setPreviousDeclaration(FunctionDecl * PrevDecl);
+
+ virtual const FunctionDecl *getCanonicalDecl() const;
+ virtual FunctionDecl *getCanonicalDecl();
+
+ unsigned getBuiltinID() const;
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return getNumParams(); }
+ typedef ParmVarDecl **param_iterator;
+ typedef ParmVarDecl * const *param_const_iterator;
+
+ param_iterator param_begin() { return ParamInfo; }
+ param_iterator param_end() { return ParamInfo+param_size(); }
+
+ param_const_iterator param_begin() const { return ParamInfo; }
+ param_const_iterator param_end() const { return ParamInfo+param_size(); }
+
+ /// getNumParams - Return the number of parameters this function must have
+ /// based on its FunctionType. This is the length of the ParamInfo array
+ /// after it has been created.
+ unsigned getNumParams() const;
+
+ const ParmVarDecl *getParamDecl(unsigned i) const {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ ParmVarDecl *getParamDecl(unsigned i) {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
+ setParams(getASTContext(), NewParamInfo, 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++).
+ unsigned getMinRequiredArguments() const;
+
+ QualType getResultType() const {
+ return getType()->getAs<FunctionType>()->getResultType();
+ }
+
+ /// \brief Determine the type of an expression that calls this function.
+ QualType getCallResultType() const {
+ return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
+ }
+
+ StorageClass getStorageClass() const { return StorageClass(SClass); }
+ void setStorageClass(StorageClass SC);
+
+ StorageClass getStorageClassAsWritten() const {
+ return StorageClass(SClassAsWritten);
+ }
+
+ /// \brief Determine whether the "inline" keyword was specified for this
+ /// function.
+ bool isInlineSpecified() const { return IsInlineSpecified; }
+
+ /// Set whether the "inline" keyword was specified for this function.
+ void setInlineSpecified(bool I) {
+ IsInlineSpecified = I;
+ IsInline = I;
+ }
+
+ /// Flag that this function is implicitly inline.
+ void setImplicitlyInline() {
+ IsInline = true;
+ }
+
+ /// \brief Determine whether this function should be inlined, because it is
+ /// either marked "inline" or is a member function of a C++ class that
+ /// was defined in the class body.
+ bool isInlined() const;
+
+ bool isInlineDefinitionExternallyVisible() const;
+
+ /// isOverloadedOperator - Whether this function declaration
+ /// represents an C++ overloaded operator, e.g., "operator+".
+ bool isOverloadedOperator() const {
+ return getOverloadedOperator() != OO_None;
+ }
+
+ OverloadedOperatorKind getOverloadedOperator() const;
+
+ const IdentifierInfo *getLiteralIdentifier() const;
+
+ /// \brief If this function is an instantiation of a member function
+ /// of a class template specialization, retrieves the function from
+ /// which it was instantiated.
+ ///
+ /// This routine will return non-NULL for (non-templated) member
+ /// functions of class templates and for instantiations of function
+ /// templates. For example, given:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// void f(T);
+ /// };
+ /// \endcode
+ ///
+ /// The declaration for X<int>::f is a (non-templated) FunctionDecl
+ /// whose parent is the class template specialization X<int>. For
+ /// this declaration, getInstantiatedFromFunction() will return
+ /// the FunctionDecl X<T>::A. When a complete definition of
+ /// X<int>::A is required, it will be instantiated from the
+ /// declaration returned by getInstantiatedFromMemberFunction().
+ FunctionDecl *getInstantiatedFromMemberFunction() const;
+
+ /// \brief What kind of templated function this is.
+ TemplatedKind getTemplatedKind() const;
+
+ /// \brief If this function is an instantiation of a member function of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member function FD.
+ void setInstantiationOfMemberFunction(FunctionDecl *FD,
+ TemplateSpecializationKind TSK) {
+ setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
+ }
+
+ /// \brief Retrieves the function template that is described by this
+ /// function declaration.
+ ///
+ /// Every function template is represented as a FunctionTemplateDecl
+ /// and a FunctionDecl (or something derived from FunctionDecl). The
+ /// former contains template properties (such as the template
+ /// parameter lists) while the latter contains the actual
+ /// description of the template's
+ /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the
+ /// FunctionDecl that describes the function template,
+ /// getDescribedFunctionTemplate() retrieves the
+ /// FunctionTemplateDecl from a FunctionDecl.
+ FunctionTemplateDecl *getDescribedFunctionTemplate() const {
+ return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>();
+ }
+
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
+ TemplateOrSpecialization = Template;
+ }
+
+ /// \brief Determine whether this function is a function template
+ /// specialization.
+ bool isFunctionTemplateSpecialization() const {
+ return getPrimaryTemplate() != 0;
+ }
+
+ /// \brief If this function is actually a function template specialization,
+ /// retrieve information about this function template specialization.
+ /// Otherwise, returns NULL.
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
+ return TemplateOrSpecialization.
+ dyn_cast<FunctionTemplateSpecializationInfo*>();
+ }
+
+ /// \brief Determines whether this function is a function template
+ /// specialization or a member of a class template specialization that can
+ /// be implicitly instantiated.
+ bool isImplicitlyInstantiable() const;
+
+ /// \brief Retrieve the function declaration from which this function could
+ /// be instantiated, if it is an instantiation (rather than a non-template
+ /// or a specialization, for example).
+ FunctionDecl *getTemplateInstantiationPattern() const;
+
+ /// \brief Retrieve the primary template that this function template
+ /// specialization either specializes or was instantiated from.
+ ///
+ /// If this function declaration is not a function template specialization,
+ /// returns NULL.
+ FunctionTemplateDecl *getPrimaryTemplate() const;
+
+ /// \brief Retrieve the template arguments used to produce this function
+ /// template specialization from the primary template.
+ ///
+ /// If this function declaration is not a function template specialization,
+ /// returns NULL.
+ const TemplateArgumentList *getTemplateSpecializationArgs() const;
+
+ /// \brief Retrieve the template argument list as written in the sources,
+ /// if any.
+ ///
+ /// If this function declaration is not a function template specialization
+ /// or if it had no explicit template argument list, returns NULL.
+ /// Note that it an explicit template argument list may be written empty,
+ /// e.g., template<> void foo<>(char* s);
+ const TemplateArgumentListInfo*
+ getTemplateSpecializationArgsAsWritten() const;
+
+ /// \brief Specify that this function declaration is actually a function
+ /// template specialization.
+ ///
+ /// \param Template the function template that this function template
+ /// specialization specializes.
+ ///
+ /// \param TemplateArgs the template arguments that produced this
+ /// function template specialization from the template.
+ ///
+ /// \param InsertPos If non-NULL, the position in the function template
+ /// specialization set where the function template specialization data will
+ /// be inserted.
+ ///
+ /// \param TSK the kind of template specialization this is.
+ ///
+ /// \param TemplateArgsAsWritten location info of template arguments.
+ ///
+ /// \param PointOfInstantiation point at which the function template
+ /// specialization was first instantiated.
+ void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten = 0,
+ SourceLocation PointOfInstantiation = SourceLocation()) {
+ setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
+ InsertPos, TSK, TemplateArgsAsWritten,
+ PointOfInstantiation);
+ }
+
+ /// \brief Specifies that this function declaration is actually a
+ /// dependent function template specialization.
+ void setDependentTemplateSpecialization(ASTContext &Context,
+ const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ DependentFunctionTemplateSpecializationInfo *
+ getDependentSpecializationInfo() const {
+ return TemplateOrSpecialization.
+ dyn_cast<DependentFunctionTemplateSpecializationInfo*>();
+ }
+
+ /// \brief Determine what kind of template instantiation this function
+ /// represents.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief Determine what kind of template instantiation this function
+ /// represents.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation = SourceLocation());
+
+ /// \brief Retrieve the (first) point of instantiation of a function template
+ /// specialization or a member of a class template specialization.
+ ///
+ /// \returns the first point of instantiation, if this function was
+ /// instantiated from a template; otherwie, returns an invalid source
+ /// location.
+ SourceLocation getPointOfInstantiation() const;
+
+ /// \brief Determine whether this is or was instantiated from an out-of-line
+ /// definition of a member function.
+ virtual bool isOutOfLine() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const FunctionDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstFunction && K <= lastFunction;
+ }
+ static DeclContext *castToDeclContext(const FunctionDecl *D) {
+ return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D));
+ }
+ static FunctionDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+
+/// FieldDecl - An instance of this class is created by Sema::ActOnField to
+/// represent a member of a struct/union/class.
+class FieldDecl : public DeclaratorDecl {
+ // FIXME: This can be packed into the bitfields in Decl.
+ bool Mutable : 1;
+ mutable unsigned CachedFieldIndex : 31;
+
+ Expr *BitWidth;
+protected:
+ FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ Expr *BW, bool Mutable)
+ : DeclaratorDecl(DK, DC, L, Id, T, TInfo),
+ Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
+ }
+
+public:
+ static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
+
+ /// getFieldIndex - Returns the index of this field within its record,
+ /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
+ unsigned getFieldIndex() const;
+
+ /// isMutable - Determines whether this field is mutable (C++ only).
+ bool isMutable() const { return Mutable; }
+
+ /// \brief Set whether this field is mutable (C++ only).
+ void setMutable(bool M) { Mutable = M; }
+
+ /// isBitfield - Determines whether this field is a bitfield.
+ bool isBitField() const { return BitWidth != NULL; }
+
+ /// @brief Determines whether this is an unnamed bitfield.
+ bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
+
+ /// isAnonymousStructOrUnion - Determines whether this field is a
+ /// representative for an anonymous struct or union. Such fields are
+ /// unnamed and are implicitly generated by the implementation to
+ /// store the data for the anonymous union or struct.
+ bool isAnonymousStructOrUnion() const;
+
+ Expr *getBitWidth() const { return BitWidth; }
+ void setBitWidth(Expr *BW) { BitWidth = BW; }
+
+ /// getParent - Returns the parent of this field declaration, which
+ /// is the struct in which this method is defined.
+ const RecordDecl *getParent() const {
+ return cast<RecordDecl>(getDeclContext());
+ }
+
+ RecordDecl *getParent() {
+ return cast<RecordDecl>(getDeclContext());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const FieldDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
+};
+
+/// EnumConstantDecl - An instance of this object exists for each enum constant
+/// that is defined. For example, in "enum X {a,b}", each of a/b are
+/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
+/// TagType for the X EnumDecl.
+class EnumConstantDecl : public ValueDecl {
+ Stmt *Init; // an integer constant expression
+ llvm::APSInt Val; // The value.
+protected:
+ EnumConstantDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *E,
+ const llvm::APSInt &V)
+ : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
+
+public:
+
+ static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *E,
+ const llvm::APSInt &V);
+
+ const Expr *getInitExpr() const { return (const Expr*) Init; }
+ Expr *getInitExpr() { return (Expr*) Init; }
+ const llvm::APSInt &getInitVal() const { return Val; }
+
+ void setInitExpr(Expr *E) { Init = (Stmt*) E; }
+ void setInitVal(const llvm::APSInt &V) { Val = V; }
+
+ SourceRange getSourceRange() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const EnumConstantDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == EnumConstant; }
+
+ friend class StmtIteratorBase;
+};
+
+/// IndirectFieldDecl - An instance of this class is created to represent a
+/// field injected from an anonymous union/struct into the parent scope.
+/// IndirectFieldDecl are always implicit.
+class IndirectFieldDecl : public ValueDecl {
+ NamedDecl **Chaining;
+ unsigned ChainingSize;
+
+ IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ NamedDecl **CH, unsigned CHS)
+ : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+
+public:
+ static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, NamedDecl **CH, unsigned CHS);
+
+ typedef NamedDecl * const *chain_iterator;
+ chain_iterator chain_begin() const { return Chaining; }
+ chain_iterator chain_end() const { return Chaining+ChainingSize; }
+
+ unsigned getChainingSize() const { return ChainingSize; }
+
+ FieldDecl *getAnonField() const {
+ assert(ChainingSize >= 2);
+ return cast<FieldDecl>(Chaining[ChainingSize - 1]);
+ }
+
+ VarDecl *getVarDecl() const {
+ assert(ChainingSize >= 2);
+ return dyn_cast<VarDecl>(*chain_begin());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const IndirectFieldDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == IndirectField; }
+ friend class ASTDeclReader;
+};
+
+/// TypeDecl - Represents a declaration of a type.
+///
+class TypeDecl : public NamedDecl {
+ /// TypeForDecl - This indicates the Type object that represents
+ /// this TypeDecl. It is a cache maintained by
+ /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
+ /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
+ mutable const Type *TypeForDecl;
+ friend class ASTContext;
+ friend class DeclContext;
+ friend class TagDecl;
+ friend class TemplateTypeParmDecl;
+ friend class TagType;
+
+protected:
+ TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {}
+
+public:
+ // Low-level accessor
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TypeDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstType && K <= lastType; }
+};
+
+
+class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
+ /// UnderlyingType - This is the type the typedef is set to.
+ TypeSourceInfo *TInfo;
+
+ TypedefDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, TypeSourceInfo *TInfo)
+ : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
+
+protected:
+ typedef Redeclarable<TypedefDecl> redeclarable_base;
+ virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
+public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
+ static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ TypeSourceInfo *TInfo);
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TInfo;
+ }
+
+ /// Retrieves the canonical declaration of this typedef.
+ TypedefDecl *getCanonicalDecl() {
+ return getFirstDeclaration();
+ }
+ const TypedefDecl *getCanonicalDecl() const {
+ return getFirstDeclaration();
+ }
+
+ QualType getUnderlyingType() const {
+ return TInfo->getType();
+ }
+ void setTypeSourceInfo(TypeSourceInfo *newType) {
+ TInfo = newType;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TypedefDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Typedef; }
+};
+
+class TypedefDecl;
+
+/// TagDecl - Represents the declaration of a struct/union/class/enum.
+class TagDecl
+ : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
+public:
+ // This is really ugly.
+ typedef TagTypeKind TagKind;
+
+private:
+ // FIXME: This can be packed into the bitfields in Decl.
+ /// TagDeclKind - The TagKind enum.
+ unsigned TagDeclKind : 2;
+
+ /// IsDefinition - True if this is a definition ("struct foo {};"), false if
+ /// it is a declaration ("struct foo;").
+ bool IsDefinition : 1;
+
+ /// IsBeingDefined - True if this is currently being defined.
+ bool IsBeingDefined : 1;
+
+ /// IsEmbeddedInDeclarator - True if this tag declaration is
+ /// "embedded" (i.e., defined or declared for the very first time)
+ /// in the syntax of a declarator.
+ bool IsEmbeddedInDeclarator : 1;
+
+protected:
+ // These are used by (and only defined for) EnumDecl.
+ unsigned NumPositiveBits : 8;
+ unsigned NumNegativeBits : 8;
+
+ /// IsScoped - True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++0x mode.
+ bool IsScoped : 1;
+ /// IsScopedUsingClassTag - If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ bool IsScopedUsingClassTag : 1;
+
+ /// IsFixed - True if this is an enumeration with fixed underlying type. Only
+ /// possible in C++0x mode.
+ bool IsFixed : 1;
+
+private:
+ SourceLocation TagKeywordLoc;
+ SourceLocation RBraceLoc;
+
+ // A struct representing syntactic qualifier info,
+ // to be used for the (uncommon) case of out-of-line declarations.
+ typedef QualifierInfo ExtInfo;
+
+ /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name
+ /// is qualified, it points to the qualifier info (nns and range);
+ /// otherwise, if the tag declaration is anonymous and it is part of
+ /// a typedef, it points to the TypedefDecl (used for mangling);
+ /// otherwise, it is a null (TypedefDecl) pointer.
+ llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier;
+
+ bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); }
+ ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); }
+ const ExtInfo *getExtInfo() const {
+ return TypedefDeclOrQualifier.get<ExtInfo*>();
+ }
+
+protected:
+ TagDecl(Kind DK, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ TagDecl *PrevDecl, SourceLocation TKL = SourceLocation())
+ : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL),
+ TypedefDeclOrQualifier((TypedefDecl*) 0) {
+ assert((DK != Enum || TK == TTK_Enum) &&
+ "EnumDecl not matched with TTK_Enum");
+ TagDeclKind = TK;
+ IsDefinition = false;
+ IsBeingDefined = false;
+ IsEmbeddedInDeclarator = false;
+ setPreviousDeclaration(PrevDecl);
+ }
+
+ typedef Redeclarable<TagDecl> redeclarable_base;
+ virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
+
+ /// @brief Completes the definition of this tag declaration.
+ ///
+ /// This is a helper function for derived classes.
+ void completeDefinition();
+
+public:
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ redecl_iterator redecls_begin() const {
+ return redeclarable_base::redecls_begin();
+ }
+ redecl_iterator redecls_end() const {
+ return redeclarable_base::redecls_end();
+ }
+
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+
+ SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; }
+ void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; }
+
+ /// getInnerLocStart - Return SourceLocation representing start of source
+ /// range ignoring outer template declarations.
+ virtual SourceLocation getInnerLocStart() const { return TagKeywordLoc; }
+
+ /// getOuterLocStart - Return SourceLocation representing start of source
+ /// range taking into account any outer template declarations.
+ SourceLocation getOuterLocStart() const;
+ virtual SourceRange getSourceRange() const;
+
+ virtual TagDecl* getCanonicalDecl();
+ const TagDecl* getCanonicalDecl() const {
+ return const_cast<TagDecl*>(this)->getCanonicalDecl();
+ }
+
+ /// isThisDeclarationADefinition() - Return true if this declaration
+ /// defines the type. Provided for consistency.
+ bool isThisDeclarationADefinition() const {
+ return isDefinition();
+ }
+
+ /// isDefinition - Return true if this decl has its body specified.
+ bool isDefinition() const {
+ return IsDefinition;
+ }
+
+ /// isBeingDefined - Return true if this decl is currently being defined.
+ bool isBeingDefined() const {
+ return IsBeingDefined;
+ }
+
+ bool isEmbeddedInDeclarator() const {
+ return IsEmbeddedInDeclarator;
+ }
+ void setEmbeddedInDeclarator(bool isInDeclarator) {
+ IsEmbeddedInDeclarator = isInDeclarator;
+ }
+
+ /// \brief Whether this declaration declares a type that is
+ /// dependent, i.e., a type that somehow depends on template
+ /// parameters.
+ bool isDependentType() const { return isDependentContext(); }
+
+ /// @brief Starts the definition of this tag declaration.
+ ///
+ /// This method should be invoked at the beginning of the definition
+ /// of this tag declaration. It will set the tag type into a state
+ /// where it is in the process of being defined.
+ void startDefinition();
+
+ /// getDefinition - Returns the TagDecl that actually defines this
+ /// struct/union/class/enum. When determining whether or not a
+ /// struct/union/class/enum is completely defined, one should use this method
+ /// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a
+ /// specific TagDecl is defining declaration, not whether or not the
+ /// struct/union/class/enum type is defined. This method returns NULL if
+ /// there is no TagDecl that defines the struct/union/class/enum.
+ TagDecl* getDefinition() const;
+
+ void setDefinition(bool V) { IsDefinition = V; }
+
+ const char *getKindName() const {
+ return TypeWithKeyword::getTagTypeKindName(getTagKind());
+ }
+
+ TagKind getTagKind() const {
+ return TagKind(TagDeclKind);
+ }
+
+ void setTagKind(TagKind TK) { TagDeclKind = TK; }
+
+ bool isStruct() const { return getTagKind() == TTK_Struct; }
+ bool isClass() const { return getTagKind() == TTK_Class; }
+ bool isUnion() const { return getTagKind() == TTK_Union; }
+ bool isEnum() const { return getTagKind() == TTK_Enum; }
+
+ TypedefDecl *getTypedefForAnonDecl() const {
+ return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
+ }
+
+ void setTypedefForAnonDecl(TypedefDecl *TDD);
+
+ NestedNameSpecifier *getQualifier() const {
+ return hasExtInfo() ? getExtInfo()->NNS : 0;
+ }
+ SourceRange getQualifierRange() const {
+ return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+ }
+ void setQualifierInfo(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange);
+
+ unsigned getNumTemplateParameterLists() const {
+ return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+ }
+ TemplateParameterList *getTemplateParameterList(unsigned i) const {
+ assert(i < getNumTemplateParameterLists());
+ return getExtInfo()->TemplParamLists[i];
+ }
+ void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
+ TemplateParameterList **TPLists) {
+ getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TagDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K >= firstTag && K <= lastTag; }
+
+ static DeclContext *castToDeclContext(const TagDecl *D) {
+ return static_cast<DeclContext *>(const_cast<TagDecl*>(D));
+ }
+ static TagDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
+/// enums.
+class EnumDecl : public TagDecl {
+ /// IntegerType - This represent the integer type that the enum corresponds
+ /// to for code generation purposes. Note that the enumerator constants may
+ /// have a different type than this does.
+ ///
+ /// If the underlying integer type was explicitly stated in the source
+ /// code, this is a TypeSourceInfo* for that type. Otherwise this type
+ /// was automatically deduced somehow, and this is a Type*.
+ ///
+ /// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in
+ /// some cases it won't.
+ ///
+ /// The underlying type of an enumeration never has any qualifiers, so
+ /// we can get away with just storing a raw Type*, and thus save an
+ /// extra pointer when TypeSourceInfo is needed.
+
+ llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;
+
+ /// PromotionType - The integer type that values of this type should
+ /// promote to. In C, enumerators are generally of an integer type
+ /// directly, but gcc-style large enumerators (and all enumerators
+ /// in C++) are of the enum type instead.
+ QualType PromotionType;
+
+ /// \brief If the enumeration was instantiated from an enumeration
+ /// within a class or function template, this pointer refers to the
+ /// enumeration declared within the template.
+ EnumDecl *InstantiatedFrom;
+
+ // The number of positive and negative bits required by the
+ // enumerators are stored in the SubclassBits field.
+ enum {
+ NumBitsWidth = 8,
+ NumBitsMask = (1 << NumBitsWidth) - 1
+ };
+
+ EnumDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL,
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed)
+ : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
+ assert(Scoped || !ScopedUsingClassTag);
+ IntegerType = (const Type*)0;
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
+ IsScoped = Scoped;
+ IsScopedUsingClassTag = ScopedUsingClassTag;
+ IsFixed = Fixed;
+ }
+public:
+ EnumDecl *getCanonicalDecl() {
+ return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ }
+ const EnumDecl *getCanonicalDecl() const {
+ return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ }
+
+ const EnumDecl *getPreviousDeclaration() const {
+ return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration());
+ }
+ EnumDecl *getPreviousDeclaration() {
+ return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration());
+ }
+
+ static EnumDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL, EnumDecl *PrevDecl,
+ bool IsScoped, bool IsScopedUsingClassTag,
+ bool IsFixed);
+ static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
+
+ /// completeDefinition - When created, the EnumDecl corresponds to a
+ /// forward-declared enum. This method is used to mark the
+ /// declaration as being defined; it's enumerators have already been
+ /// added (via DeclContext::addDecl). NewType is the new underlying
+ /// type of the enumeration type.
+ void completeDefinition(QualType NewType,
+ QualType PromotionType,
+ unsigned NumPositiveBits,
+ unsigned NumNegativeBits);
+
+ // enumerator_iterator - Iterates through the enumerators of this
+ // enumeration.
+ typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
+
+ enumerator_iterator enumerator_begin() const {
+ const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition());
+ if (!E)
+ E = this;
+ return enumerator_iterator(E->decls_begin());
+ }
+
+ enumerator_iterator enumerator_end() const {
+ const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition());
+ if (!E)
+ E = this;
+ return enumerator_iterator(E->decls_end());
+ }
+
+ /// getPromotionType - Return the integer type that enumerators
+ /// should promote to.
+ QualType getPromotionType() const { return PromotionType; }
+
+ /// \brief Set the promotion type.
+ void setPromotionType(QualType T) { PromotionType = T; }
+
+ /// getIntegerType - Return the integer type this enum decl corresponds to.
+ /// This returns a null qualtype for an enum forward definition.
+ QualType getIntegerType() const {
+ if (!IntegerType)
+ return QualType();
+ if (const Type* T = IntegerType.dyn_cast<const Type*>())
+ return QualType(T, 0);
+ return IntegerType.get<TypeSourceInfo*>()->getType();
+ }
+
+ /// \brief Set the underlying integer type.
+ void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }
+
+ /// \brief Set the underlying integer type source info.
+ void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; }
+
+ /// \brief Return the type source info for the underlying integer type,
+ /// if no type source info exists, return 0.
+ TypeSourceInfo* getIntegerTypeSourceInfo() const {
+ return IntegerType.dyn_cast<TypeSourceInfo*>();
+ }
+
+ /// \brief Returns the width in bits requred to store all the
+ /// non-negative enumerators of this enum.
+ unsigned getNumPositiveBits() const {
+ return NumPositiveBits;
+ }
+ void setNumPositiveBits(unsigned Num) {
+ NumPositiveBits = Num;
+ assert(NumPositiveBits == Num && "can't store this bitcount");
+ }
+
+ /// \brief Returns the width in bits requred to store all the
+ /// negative enumerators of this enum. These widths include
+ /// the rightmost leading 1; that is:
+ ///
+ /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS
+ /// ------------------------ ------- -----------------
+ /// -1 1111111 1
+ /// -10 1110110 5
+ /// -101 1001011 8
+ unsigned getNumNegativeBits() const {
+ return NumNegativeBits;
+ }
+ void setNumNegativeBits(unsigned Num) {
+ NumNegativeBits = Num;
+ }
+
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScoped() const {
+ return IsScoped;
+ }
+
+ /// \brief Returns true if this is a C++0x scoped enumeration.
+ bool isScopedUsingClassTag() const {
+ return IsScopedUsingClassTag;
+ }
+
+ /// \brief Returns true if this is a C++0x enumeration with fixed underlying
+ /// type.
+ bool isFixed() const {
+ return IsFixed;
+ }
+
+ /// \brief Returns true if this can be considered a complete type.
+ bool isComplete() const {
+ return isDefinition() || isFixed();
+ }
+
+ /// \brief Returns the enumeration (declared within the template)
+ /// from which this enumeration type was instantiated, or NULL if
+ /// this enumeration was not instantiated from any template.
+ EnumDecl *getInstantiatedFromMemberEnum() const {
+ return InstantiatedFrom;
+ }
+
+ void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const EnumDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Enum; }
+
+ friend class ASTDeclReader;
+};
+
+
+/// RecordDecl - Represents a struct/union/class. For example:
+/// struct X; // Forward declaration, no "body".
+/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
+/// This decl will be marked invalid if *any* members are invalid.
+///
+class RecordDecl : public TagDecl {
+ // FIXME: This can be packed into the bitfields in Decl.
+ /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
+ /// array member (e.g. int X[]) or if this union contains a struct that does.
+ /// If so, this cannot be contained in arrays or other structs as a member.
+ bool HasFlexibleArrayMember : 1;
+
+ /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct
+ /// or union.
+ bool AnonymousStructOrUnion : 1;
+
+ /// HasObjectMember - This is true if this struct has at least one member
+ /// containing an object.
+ bool HasObjectMember : 1;
+
+ /// \brief Whether the field declarations of this record have been loaded
+ /// from external storage. To avoid unnecessary deserialization of
+ /// methods/nested types we allow deserialization of just the fields
+ /// when needed.
+ mutable bool LoadedFieldsFromExternalStorage : 1;
+ friend class DeclContext;
+
+protected:
+ RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ RecordDecl *PrevDecl, SourceLocation TKL);
+
+public:
+ static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL = SourceLocation(),
+ RecordDecl* PrevDecl = 0);
+ static RecordDecl *Create(const ASTContext &C, EmptyShell Empty);
+
+ const RecordDecl *getPreviousDeclaration() const {
+ return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
+ }
+ RecordDecl *getPreviousDeclaration() {
+ return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
+ }
+
+ bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
+ void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
+
+ /// isAnonymousStructOrUnion - Whether this is an anonymous struct
+ /// or union. To be an anonymous struct or union, it must have been
+ /// declared without a name and there must be no objects of this
+ /// type declared, e.g.,
+ /// @code
+ /// union { int i; float f; };
+ /// @endcode
+ /// is an anonymous union but neither of the following are:
+ /// @code
+ /// union X { int i; float f; };
+ /// union { int i; float f; } obj;
+ /// @endcode
+ bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
+ void setAnonymousStructOrUnion(bool Anon) {
+ AnonymousStructOrUnion = Anon;
+ }
+
+ bool hasObjectMember() const { return HasObjectMember; }
+ void setHasObjectMember (bool val) { HasObjectMember = val; }
+
+ /// \brief Determines whether this declaration represents the
+ /// injected class name.
+ ///
+ /// The injected class name in C++ is the name of the class that
+ /// appears inside the class itself. For example:
+ ///
+ /// \code
+ /// struct C {
+ /// // C is implicitly declared here as a synonym for the class name.
+ /// };
+ ///
+ /// C::C c; // same as "C c;"
+ /// \endcode
+ bool isInjectedClassName() const;
+
+ /// getDefinition - Returns the RecordDecl that actually defines this
+ /// struct/union/class. When determining whether or not a struct/union/class
+ /// is completely defined, one should use this method as opposed to
+ /// 'isDefinition'. 'isDefinition' indicates whether or not a specific
+ /// RecordDecl is defining declaration, not whether or not the record
+ /// type is defined. This method returns NULL if there is no RecordDecl
+ /// that defines the struct/union/tag.
+ RecordDecl* getDefinition() const {
+ return cast_or_null<RecordDecl>(TagDecl::getDefinition());
+ }
+
+ // Iterator access to field members. The field iterator only visits
+ // the non-static data members of this class, ignoring any static
+ // data members, functions, constructors, destructors, etc.
+ typedef specific_decl_iterator<FieldDecl> field_iterator;
+
+ field_iterator field_begin() const;
+
+ field_iterator field_end() const {
+ return field_iterator(decl_iterator());
+ }
+
+ // field_empty - Whether there are any fields (non-static data
+ // members) in this record.
+ bool field_empty() const {
+ return field_begin() == field_end();
+ }
+
+ /// completeDefinition - Notes that the definition of this type is
+ /// now complete.
+ virtual void completeDefinition();
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const RecordDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstRecord && K <= lastRecord;
+ }
+
+private:
+ /// \brief Deserialize just the fields.
+ void LoadFieldsFromExternalStorage() const;
+};
+
+class FileScopeAsmDecl : public Decl {
+ StringLiteral *AsmString;
+ FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring)
+ : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {}
+public:
+ static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, StringLiteral *Str);
+
+ const StringLiteral *getAsmString() const { return AsmString; }
+ StringLiteral *getAsmString() { return AsmString; }
+ void setAsmString(StringLiteral *Asm) { AsmString = Asm; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const FileScopeAsmDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == FileScopeAsm; }
+};
+
+/// BlockDecl - This represents a block literal declaration, which is like an
+/// unnamed FunctionDecl. For example:
+/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
+///
+class BlockDecl : public Decl, public DeclContext {
+public:
+ /// A class which contains all the information about a particular
+ /// captured value.
+ class Capture {
+ enum {
+ flag_isByRef = 0x1,
+ flag_isNested = 0x2
+ };
+
+ /// The variable being captured.
+ llvm::PointerIntPair<VarDecl*, 2> VariableAndFlags;
+
+ /// The copy expression, expressed in terms of a DeclRef (or
+ /// BlockDeclRef) to the captured variable. Only required if the
+ /// variable has a C++ class type.
+ Expr *CopyExpr;
+
+ public:
+ Capture(VarDecl *variable, bool byRef, bool nested, Expr *copy)
+ : VariableAndFlags(variable,
+ (byRef ? flag_isByRef : 0) | (nested ? flag_isNested : 0)),
+ CopyExpr(copy) {}
+
+ /// The variable being captured.
+ VarDecl *getVariable() const { return VariableAndFlags.getPointer(); }
+
+ /// Whether this is a "by ref" capture, i.e. a capture of a __block
+ /// variable.
+ bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; }
+
+ /// Whether this is a nested capture, i.e. the variable captured
+ /// is not from outside the immediately enclosing function/block.
+ bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }
+
+ bool hasCopyExpr() const { return CopyExpr != 0; }
+ Expr *getCopyExpr() const { return CopyExpr; }
+ void setCopyExpr(Expr *e) { CopyExpr = e; }
+ };
+
+private:
+ // FIXME: This can be packed into the bitfields in Decl.
+ bool IsVariadic : 1;
+ bool CapturesCXXThis : 1;
+ /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
+ /// parameters of this function. This is null if a prototype or if there are
+ /// no formals.
+ ParmVarDecl **ParamInfo;
+ unsigned NumParams;
+
+ Stmt *Body;
+ TypeSourceInfo *SignatureAsWritten;
+
+ Capture *Captures;
+ unsigned NumCaptures;
+
+protected:
+ BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
+ : Decl(Block, DC, CaretLoc), DeclContext(Block),
+ IsVariadic(false), CapturesCXXThis(false),
+ ParamInfo(0), NumParams(0), Body(0),
+ SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
+
+public:
+ static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
+
+ SourceLocation getCaretLocation() const { return getLocation(); }
+
+ bool isVariadic() const { return IsVariadic; }
+ void setIsVariadic(bool value) { IsVariadic = value; }
+
+ CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; }
+ Stmt *getBody() const { return (Stmt*) Body; }
+ void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+
+ void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; }
+ TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; }
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return getNumParams(); }
+ typedef ParmVarDecl **param_iterator;
+ typedef ParmVarDecl * const *param_const_iterator;
+
+ bool param_empty() const { return NumParams == 0; }
+ param_iterator param_begin() { return ParamInfo; }
+ param_iterator param_end() { return ParamInfo+param_size(); }
+
+ param_const_iterator param_begin() const { return ParamInfo; }
+ param_const_iterator param_end() const { return ParamInfo+param_size(); }
+
+ unsigned getNumParams() const { return NumParams; }
+ const ParmVarDecl *getParamDecl(unsigned i) const {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ ParmVarDecl *getParamDecl(unsigned i) {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
+
+ /// hasCaptures - True if this block (or its nested blocks) captures
+ /// anything of local storage from its enclosing scopes.
+ bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }
+
+ /// getNumCaptures - Returns the number of captured variables.
+ /// Does not include an entry for 'this'.
+ unsigned getNumCaptures() const { return NumCaptures; }
+
+ typedef const Capture *capture_iterator;
+ typedef const Capture *capture_const_iterator;
+ capture_iterator capture_begin() { return Captures; }
+ capture_iterator capture_end() { return Captures + NumCaptures; }
+ capture_const_iterator capture_begin() const { return Captures; }
+ capture_const_iterator capture_end() const { return Captures + NumCaptures; }
+
+ bool capturesCXXThis() const { return CapturesCXXThis; }
+
+ void setCaptures(ASTContext &Context,
+ const Capture *begin,
+ const Capture *end,
+ bool capturesCXXThis);
+
+ virtual SourceRange getSourceRange() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const BlockDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Block; }
+ static DeclContext *castToDeclContext(const BlockDecl *D) {
+ return static_cast<DeclContext *>(const_cast<BlockDecl*>(D));
+ }
+ static BlockDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// Insertion operator for diagnostics. This allows sending NamedDecl's
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ NamedDecl* ND) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl);
+ return DB;
+}
+
+template<typename decl_type>
+void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) {
+ // Note: This routine is implemented here because we need both NamedDecl
+ // and Redeclarable to be defined.
+
+ decl_type *First;
+
+ if (PrevDecl) {
+ // Point to previous. Make sure that this is actually the most recent
+ // redeclaration, or we can build invalid chains. If the most recent
+ // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
+ RedeclLink = PreviousDeclLink(llvm::cast<decl_type>(
+ PrevDecl->getMostRecentDeclaration()));
+ First = PrevDecl->getFirstDeclaration();
+ assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ } else {
+ // Make this first.
+ First = static_cast<decl_type*>(this);
+ }
+
+ // First one will point to this one as latest.
+ First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this)))
+ ND->ClearLinkageCache();
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h b/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h
new file mode 100644
index 0000000..7ecd8f8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h
@@ -0,0 +1,72 @@
+//===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 DeclAccessPair class, which provides an
+// efficient representation of a pair of a NamedDecl* and an
+// AccessSpecifier. Generally the access specifier gives the
+// natural access of a declaration when named in a class, as
+// defined in C++ [class.access.base]p1.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H
+#define LLVM_CLANG_AST_DECLACCESSPAIR_H
+
+#include "clang/Basic/Specifiers.h"
+
+namespace clang {
+
+class NamedDecl;
+
+/// A POD class for pairing a NamedDecl* with an access specifier.
+/// Can be put into unions.
+class DeclAccessPair {
+ NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
+
+ enum { Mask = 0x3 };
+
+public:
+ static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
+ DeclAccessPair p;
+ p.set(D, AS);
+ return p;
+ }
+
+ NamedDecl *getDecl() const {
+ return (NamedDecl*) (~Mask & (uintptr_t) Ptr);
+ }
+ AccessSpecifier getAccess() const {
+ return AccessSpecifier(Mask & (uintptr_t) Ptr);
+ }
+
+ void setDecl(NamedDecl *D) {
+ set(D, getAccess());
+ }
+ void setAccess(AccessSpecifier AS) {
+ set(getDecl(), AS);
+ }
+ void set(NamedDecl *D, AccessSpecifier AS) {
+ Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) |
+ reinterpret_cast<uintptr_t>(D));
+ }
+
+ operator NamedDecl*() const { return getDecl(); }
+ NamedDecl *operator->() const { return getDecl(); }
+};
+}
+
+// Take a moment to tell SmallVector that DeclAccessPair is POD.
+namespace llvm {
+template<typename> struct isPodLike;
+template<> struct isPodLike<clang::DeclAccessPair> {
+ static const bool value = true;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
new file mode 100644
index 0000000..bf249ce
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -0,0 +1,1341 @@
+//===-- DeclBase.h - Base Classes for representing declarations -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Decl and DeclContext interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLBASE_H
+#define LLVM_CLANG_AST_DECLBASE_H
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+class DeclContext;
+class TranslationUnitDecl;
+class NamespaceDecl;
+class UsingDirectiveDecl;
+class NamedDecl;
+class FunctionDecl;
+class CXXRecordDecl;
+class EnumDecl;
+class ObjCMethodDecl;
+class ObjCContainerDecl;
+class ObjCInterfaceDecl;
+class ObjCCategoryDecl;
+class ObjCProtocolDecl;
+class ObjCImplementationDecl;
+class ObjCCategoryImplDecl;
+class ObjCImplDecl;
+class LinkageSpecDecl;
+class BlockDecl;
+class DeclarationName;
+class CompoundStmt;
+class StoredDeclsMap;
+class DependentDiagnostic;
+class ASTMutationListener;
+}
+
+namespace llvm {
+// DeclContext* is only 4-byte aligned on 32-bit systems.
+template<>
+ class PointerLikeTypeTraits<clang::DeclContext*> {
+ typedef clang::DeclContext* PT;
+public:
+ static inline void *getAsVoidPointer(PT P) { return P; }
+ static inline PT getFromVoidPointer(void *P) {
+ return static_cast<PT>(P);
+ }
+ enum { NumLowBitsAvailable = 2 };
+};
+}
+
+namespace clang {
+
+/// Decl - This represents one declaration (or definition), e.g. a variable,
+/// typedef, function, struct, etc.
+///
+class Decl {
+public:
+ /// \brief Lists the kind of concrete classes of Decl.
+ enum Kind {
+#define DECL(DERIVED, BASE) DERIVED,
+#define ABSTRACT_DECL(DECL)
+#define DECL_RANGE(BASE, START, END) \
+ first##BASE = START, last##BASE = END,
+#define LAST_DECL_RANGE(BASE, START, END) \
+ first##BASE = START, last##BASE = END
+#include "clang/AST/DeclNodes.inc"
+ };
+
+ /// \brief A placeholder type used to construct an empty shell of a
+ /// decl-derived type that will be filled in later (e.g., by some
+ /// deserialization method).
+ struct EmptyShell { };
+
+ /// IdentifierNamespace - The different namespaces in which
+ /// declarations may appear. According to C99 6.2.3, there are
+ /// four namespaces, labels, tags, members and ordinary
+ /// identifiers. C++ describes lookup completely differently:
+ /// certain lookups merely "ignore" certain kinds of declarations,
+ /// usually based on whether the declaration is of a type, etc.
+ ///
+ /// These are meant as bitmasks, so that searches in
+ /// C++ can look into the "tag" namespace during ordinary lookup.
+ ///
+ /// Decl currently provides 15 bits of IDNS bits.
+ enum IdentifierNamespace {
+ /// Labels, declared with 'x:' and referenced with 'goto x'.
+ IDNS_Label = 0x0001,
+
+ /// Tags, declared with 'struct foo;' and referenced with
+ /// 'struct foo'. All tags are also types. This is what
+ /// elaborated-type-specifiers look for in C.
+ IDNS_Tag = 0x0002,
+
+ /// Types, declared with 'struct foo', typedefs, etc.
+ /// This is what elaborated-type-specifiers look for in C++,
+ /// but note that it's ill-formed to find a non-tag.
+ IDNS_Type = 0x0004,
+
+ /// Members, declared with object declarations within tag
+ /// definitions. In C, these can only be found by "qualified"
+ /// lookup in member expressions. In C++, they're found by
+ /// normal lookup.
+ IDNS_Member = 0x0008,
+
+ /// Namespaces, declared with 'namespace foo {}'.
+ /// Lookup for nested-name-specifiers find these.
+ IDNS_Namespace = 0x0010,
+
+ /// Ordinary names. In C, everything that's not a label, tag,
+ /// or member ends up here.
+ IDNS_Ordinary = 0x0020,
+
+ /// Objective C @protocol.
+ IDNS_ObjCProtocol = 0x0040,
+
+ /// This declaration is a friend function. A friend function
+ /// declaration is always in this namespace but may also be in
+ /// IDNS_Ordinary if it was previously declared.
+ IDNS_OrdinaryFriend = 0x0080,
+
+ /// This declaration is a friend class. A friend class
+ /// declaration is always in this namespace but may also be in
+ /// IDNS_Tag|IDNS_Type if it was previously declared.
+ IDNS_TagFriend = 0x0100,
+
+ /// This declaration is a using declaration. A using declaration
+ /// *introduces* a number of other declarations into the current
+ /// scope, and those declarations use the IDNS of their targets,
+ /// but the actual using declarations go in this namespace.
+ IDNS_Using = 0x0200,
+
+ /// This declaration is a C++ operator declared in a non-class
+ /// context. All such operators are also in IDNS_Ordinary.
+ /// C++ lexical operator lookup looks for these.
+ IDNS_NonMemberOperator = 0x0400
+ };
+
+ /// ObjCDeclQualifier - Qualifier used on types in method declarations
+ /// for remote messaging. They are meant for the arguments though and
+ /// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
+ enum ObjCDeclQualifier {
+ OBJC_TQ_None = 0x0,
+ OBJC_TQ_In = 0x1,
+ OBJC_TQ_Inout = 0x2,
+ OBJC_TQ_Out = 0x4,
+ OBJC_TQ_Bycopy = 0x8,
+ OBJC_TQ_Byref = 0x10,
+ OBJC_TQ_Oneway = 0x20
+ };
+
+private:
+ /// NextDeclInContext - The next declaration within the same lexical
+ /// DeclContext. These pointers form the linked list that is
+ /// traversed via DeclContext's decls_begin()/decls_end().
+ Decl *NextDeclInContext;
+
+ friend class DeclContext;
+
+ struct MultipleDC {
+ DeclContext *SemanticDC;
+ DeclContext *LexicalDC;
+ };
+
+
+ /// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
+ /// For declarations that don't contain C++ scope specifiers, it contains
+ /// the DeclContext where the Decl was declared.
+ /// For declarations with C++ scope specifiers, it contains a MultipleDC*
+ /// with the context where it semantically belongs (SemanticDC) and the
+ /// context where it was lexically declared (LexicalDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
+
+ inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
+ inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
+ inline MultipleDC *getMultipleDC() const {
+ return DeclCtx.get<MultipleDC*>();
+ }
+ inline DeclContext *getSemanticDC() const {
+ return DeclCtx.get<DeclContext*>();
+ }
+
+ /// Loc - The location of this decl.
+ SourceLocation Loc;
+
+ /// DeclKind - This indicates which class this is.
+ unsigned DeclKind : 8;
+
+ /// InvalidDecl - This indicates a semantic error occurred.
+ unsigned InvalidDecl : 1;
+
+ /// HasAttrs - This indicates whether the decl has attributes or not.
+ unsigned HasAttrs : 1;
+
+ /// Implicit - Whether this declaration was implicitly generated by
+ /// the implementation rather than explicitly written by the user.
+ unsigned Implicit : 1;
+
+ /// \brief Whether this declaration was "used", meaning that a definition is
+ /// required.
+ unsigned Used : 1;
+
+protected:
+ /// Access - Used by C++ decls for the access specifier.
+ // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
+ unsigned Access : 2;
+ friend class CXXClassMemberWrapper;
+
+ /// PCHLevel - the "level" of AST file from which this declaration was built.
+ unsigned PCHLevel : 2;
+
+ /// ChangedAfterLoad - if this declaration has changed since being loaded
+ unsigned ChangedAfterLoad : 1;
+
+ /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
+ unsigned IdentifierNamespace : 12;
+
+ /// \brief Whether the \c CachedLinkage field is active.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned HasCachedLinkage : 1;
+
+ /// \brief If \c HasCachedLinkage, the linkage of this declaration.
+ ///
+ /// This field is only valid for NamedDecls subclasses.
+ mutable unsigned CachedLinkage : 2;
+
+
+private:
+ void CheckAccessDeclContext() const;
+
+protected:
+
+ Decl(Kind DK, DeclContext *DC, SourceLocation L)
+ : NextDeclInContext(0), DeclCtx(DC),
+ Loc(L), DeclKind(DK), InvalidDecl(0),
+ HasAttrs(false), Implicit(false), Used(false),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
+ if (Decl::CollectingStats()) add(DK);
+ }
+
+ Decl(Kind DK, EmptyShell Empty)
+ : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
+ HasAttrs(false), Implicit(false), Used(false),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ HasCachedLinkage(0)
+ {
+ if (Decl::CollectingStats()) add(DK);
+ }
+
+ virtual ~Decl();
+
+public:
+
+ /// \brief Source range that this declaration covers.
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), getLocation());
+ }
+ SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
+ SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ Kind getKind() const { return static_cast<Kind>(DeclKind); }
+ const char *getDeclKindName() const;
+
+ Decl *getNextDeclInContext() { return NextDeclInContext; }
+ const Decl *getNextDeclInContext() const { return NextDeclInContext; }
+
+ DeclContext *getDeclContext() {
+ if (isInSemaDC())
+ return getSemanticDC();
+ return getMultipleDC()->SemanticDC;
+ }
+ const DeclContext *getDeclContext() const {
+ return const_cast<Decl*>(this)->getDeclContext();
+ }
+
+ TranslationUnitDecl *getTranslationUnitDecl();
+ const TranslationUnitDecl *getTranslationUnitDecl() const {
+ return const_cast<Decl*>(this)->getTranslationUnitDecl();
+ }
+
+ bool isInAnonymousNamespace() const;
+
+ ASTContext &getASTContext() const;
+
+ void setAccess(AccessSpecifier AS) {
+ Access = AS;
+#ifndef NDEBUG
+ CheckAccessDeclContext();
+#endif
+ }
+
+ AccessSpecifier getAccess() const {
+#ifndef NDEBUG
+ CheckAccessDeclContext();
+#endif
+ return AccessSpecifier(Access);
+ }
+
+ bool hasAttrs() const { return HasAttrs; }
+ void setAttrs(const AttrVec& Attrs);
+ AttrVec &getAttrs() {
+ return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
+ }
+ const AttrVec &getAttrs() const;
+ void swapAttrs(Decl *D);
+ void dropAttrs();
+
+ void addAttr(Attr *A) {
+ if (hasAttrs())
+ getAttrs().push_back(A);
+ else
+ setAttrs(AttrVec(1, A));
+ }
+
+ typedef AttrVec::const_iterator attr_iterator;
+
+ // FIXME: Do not rely on iterators having comparable singular values.
+ // Note that this should error out if they do not.
+ attr_iterator attr_begin() const {
+ return hasAttrs() ? getAttrs().begin() : 0;
+ }
+ attr_iterator attr_end() const {
+ return hasAttrs() ? getAttrs().end() : 0;
+ }
+
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_begin() const {
+ return specific_attr_iterator<T>(attr_begin());
+ }
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_end() const {
+ return specific_attr_iterator<T>(attr_end());
+ }
+
+ template<typename T> T *getAttr() const {
+ return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
+ }
+ template<typename T> bool hasAttr() const {
+ return hasAttrs() && hasSpecificAttr<T>(getAttrs());
+ }
+
+ /// getMaxAlignment - return the maximum alignment specified by attributes
+ /// on this decl, 0 if there are none.
+ unsigned getMaxAlignment() const {
+ return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
+ }
+
+ /// setInvalidDecl - Indicates the Decl had a semantic error. This
+ /// allows for graceful error recovery.
+ void setInvalidDecl(bool Invalid = true);
+ bool isInvalidDecl() const { return (bool) InvalidDecl; }
+
+ /// isImplicit - Indicates whether the declaration was implicitly
+ /// generated by the implementation. If false, this declaration
+ /// was written explicitly in the source code.
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I = true) { Implicit = I; }
+
+ /// \brief Whether this declaration was used, meaning that a definition
+ /// is required.
+ ///
+ /// \param CheckUsedAttr When true, also consider the "used" attribute
+ /// (in addition to the "used" bit set by \c setUsed()) when determining
+ /// whether the function is used.
+ bool isUsed(bool CheckUsedAttr = true) const;
+
+ void setUsed(bool U = true) { Used = U; }
+
+ /// \brief Retrieve the level of precompiled header from which this
+ /// declaration was generated.
+ ///
+ /// The PCH level of a declaration describes where the declaration originated
+ /// from. A PCH level of 0 indicates that the declaration was parsed from
+ /// source. A PCH level of 1 indicates that the declaration was loaded from
+ /// a top-level AST file. A PCH level 2 indicates that the declaration was
+ /// loaded from a PCH file the AST file depends on, and so on.
+ unsigned getPCHLevel() const { return PCHLevel; }
+
+ /// \brief The maximum PCH level that any declaration may have.
+ static const unsigned MaxPCHLevel = 3;
+
+ /// \brief Set the PCH level of this declaration.
+ void setPCHLevel(unsigned Level) {
+ assert(Level <= MaxPCHLevel && "PCH level exceeds the maximum");
+ PCHLevel = Level;
+ }
+
+ /// \brief Query whether this declaration was changed in a significant way
+ /// since being loaded from an AST file.
+ ///
+ /// In an epic violation of layering, what is "significant" is entirely
+ /// up to the serialization system, but implemented in AST and Sema.
+ bool isChangedSinceDeserialization() const { return ChangedAfterLoad; }
+
+ /// \brief Mark this declaration as having changed since deserialization, or
+ /// reset the flag.
+ void setChangedSinceDeserialization(bool Changed) {
+ ChangedAfterLoad = Changed;
+ }
+
+ unsigned getIdentifierNamespace() const {
+ return IdentifierNamespace;
+ }
+ bool isInIdentifierNamespace(unsigned NS) const {
+ return getIdentifierNamespace() & NS;
+ }
+ static unsigned getIdentifierNamespaceForKind(Kind DK);
+
+ bool hasTagIdentifierNamespace() const {
+ return isTagIdentifierNamespace(getIdentifierNamespace());
+ }
+ static bool isTagIdentifierNamespace(unsigned NS) {
+ // TagDecls have Tag and Type set and may also have TagFriend.
+ return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type);
+ }
+
+ /// getLexicalDeclContext - The declaration context where this Decl was
+ /// lexically declared (LexicalDC). May be different from
+ /// getDeclContext() (SemanticDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ DeclContext *getLexicalDeclContext() {
+ if (isInSemaDC())
+ return getSemanticDC();
+ return getMultipleDC()->LexicalDC;
+ }
+ const DeclContext *getLexicalDeclContext() const {
+ return const_cast<Decl*>(this)->getLexicalDeclContext();
+ }
+
+ virtual bool isOutOfLine() const {
+ return getLexicalDeclContext() != getDeclContext();
+ }
+
+ /// setDeclContext - Set both the semantic and lexical DeclContext
+ /// to DC.
+ void setDeclContext(DeclContext *DC);
+
+ void setLexicalDeclContext(DeclContext *DC);
+
+ /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+ /// scoped decl is defined outside the current function or method. This is
+ /// roughly global variables and functions, but also handles enums (which
+ /// could be defined inside or outside a function etc).
+ bool isDefinedOutsideFunctionOrMethod() const;
+
+ /// \brief Retrieves the "canonical" declaration of the given declaration.
+ virtual Decl *getCanonicalDecl() { return this; }
+ const Decl *getCanonicalDecl() const {
+ return const_cast<Decl*>(this)->getCanonicalDecl();
+ }
+
+ /// \brief Whether this particular Decl is a canonical one.
+ bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
+
+protected:
+ /// \brief Returns the next redeclaration or itself if this is the only decl.
+ ///
+ /// Decl subclasses that can be redeclared should override this method so that
+ /// Decl::redecl_iterator can iterate over them.
+ virtual Decl *getNextRedeclaration() { return this; }
+
+public:
+ /// \brief Iterates through all the redeclarations of the same decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ Decl *Current;
+ Decl *Starter;
+
+ public:
+ typedef Decl* value_type;
+ typedef Decl* reference;
+ typedef Decl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ Decl *Next = Current->getNextRedeclaration();
+ assert(Next && "Should return next redeclaration or itself, never null!");
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same decl.
+ /// It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<Decl*>(this));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+ /// getBody - If this Decl represents a declaration for a body of code,
+ /// such as a function or method definition, this method returns the
+ /// top-level Stmt* of that body. Otherwise this method returns null.
+ virtual Stmt* getBody() const { return 0; }
+
+ /// \brief Returns true if this Decl represents a declaration for a body of
+ /// code, such as a function or method definition.
+ virtual bool hasBody() const { return getBody() != 0; }
+
+ /// getBodyRBrace - Gets the right brace of the body, if a body exists.
+ /// This works whether the body is a CompoundStmt or a CXXTryStmt.
+ SourceLocation getBodyRBrace() const;
+
+ // global temp stats (until we have a per-module visitor)
+ static void add(Kind k);
+ static bool CollectingStats(bool Enable = false);
+ static void PrintStats();
+
+ /// isTemplateParameter - Determines whether this declaration is a
+ /// template parameter.
+ bool isTemplateParameter() const;
+
+ /// isTemplateParameter - Determines whether this declaration is a
+ /// template parameter pack.
+ bool isTemplateParameterPack() const;
+
+ /// \brief Whether this declaration is a parameter pack.
+ bool isParameterPack() const;
+
+ /// \brief Whether this declaration is a function or function template.
+ bool isFunctionOrFunctionTemplate() const;
+
+ /// \brief Changes the namespace of this declaration to reflect that it's
+ /// the object of a friend declaration.
+ ///
+ /// These declarations appear in the lexical context of the friending
+ /// class, but in the semantic context of the actual entity. This property
+ /// applies only to a specific decl object; other redeclarations of the
+ /// same entity may not (and probably don't) share this property.
+ void setObjectOfFriendDecl(bool PreviouslyDeclared) {
+ unsigned OldNS = IdentifierNamespace;
+ assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
+ IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ "namespace includes neither ordinary nor tag");
+ assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
+ IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
+ "namespace includes other than ordinary or tag");
+
+ IdentifierNamespace = 0;
+ if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
+ IdentifierNamespace |= IDNS_TagFriend;
+ if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+ }
+
+ if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
+ IdentifierNamespace |= IDNS_OrdinaryFriend;
+ if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
+ }
+ }
+
+ enum FriendObjectKind {
+ FOK_None, // not a friend object
+ FOK_Declared, // a friend of a previously-declared entity
+ FOK_Undeclared // a friend of a previously-undeclared entity
+ };
+
+ /// \brief Determines whether this declaration is the object of a
+ /// friend declaration and, if so, what kind.
+ ///
+ /// There is currently no direct way to find the associated FriendDecl.
+ FriendObjectKind getFriendObjectKind() const {
+ unsigned mask
+ = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend));
+ if (!mask) return FOK_None;
+ return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ?
+ FOK_Declared : FOK_Undeclared);
+ }
+
+ /// Specifies that this declaration is a C++ overloaded non-member.
+ void setNonMemberOperator() {
+ assert(getKind() == Function || getKind() == FunctionTemplate);
+ assert((IdentifierNamespace & IDNS_Ordinary) &&
+ "visible non-member operators should be in ordinary namespace");
+ IdentifierNamespace |= IDNS_NonMemberOperator;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *) { return true; }
+ static bool classofKind(Kind K) { return true; }
+ static DeclContext *castToDeclContext(const Decl *);
+ static Decl *castFromDeclContext(const DeclContext *);
+
+ void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
+ void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation = 0) const;
+ static void printGroup(Decl** Begin, unsigned NumDecls,
+ llvm::raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation = 0);
+ void dump() const;
+ void dumpXML() const;
+ void dumpXML(llvm::raw_ostream &OS) const;
+
+private:
+ const Attr *getAttrsImpl() const;
+
+protected:
+ ASTMutationListener *getASTMutationListener() const;
+};
+
+/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
+/// doing something to a specific decl.
+class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
+ const Decl *TheDecl;
+ SourceLocation Loc;
+ SourceManager &SM;
+ const char *Message;
+public:
+ PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L,
+ SourceManager &sm, const char *Msg)
+ : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+class DeclContextLookupResult
+ : public std::pair<NamedDecl**,NamedDecl**> {
+public:
+ DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
+ : std::pair<NamedDecl**,NamedDecl**>(I, E) {}
+ DeclContextLookupResult()
+ : std::pair<NamedDecl**,NamedDecl**>() {}
+
+ using std::pair<NamedDecl**,NamedDecl**>::operator=;
+};
+
+class DeclContextLookupConstResult
+ : public std::pair<NamedDecl*const*, NamedDecl*const*> {
+public:
+ DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
+ DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
+ DeclContextLookupConstResult()
+ : std::pair<NamedDecl*const*, NamedDecl*const*>() {}
+
+ using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
+};
+
+/// DeclContext - This is used only as base class of specific decl types that
+/// can act as declaration contexts. These decls are (only the top classes
+/// that directly derive from DeclContext are mentioned, not their subclasses):
+///
+/// TranslationUnitDecl
+/// NamespaceDecl
+/// FunctionDecl
+/// TagDecl
+/// ObjCMethodDecl
+/// ObjCContainerDecl
+/// LinkageSpecDecl
+/// BlockDecl
+///
+class DeclContext {
+ /// DeclKind - This indicates which class this is.
+ unsigned DeclKind : 8;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are lexically
+ /// part of this context.
+ mutable unsigned ExternalLexicalStorage : 1;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable unsigned ExternalVisibleStorage : 1;
+
+ /// \brief Pointer to the data structure used to lookup declarations
+ /// within this context (or a DependentStoredDeclsMap if this is a
+ /// dependent context).
+ mutable StoredDeclsMap *LookupPtr;
+
+protected:
+ /// FirstDecl - The first declaration stored within this declaration
+ /// context.
+ mutable Decl *FirstDecl;
+
+ /// LastDecl - The last declaration stored within this declaration
+ /// context. FIXME: We could probably cache this value somewhere
+ /// outside of the DeclContext, to reduce the size of DeclContext by
+ /// another pointer.
+ mutable Decl *LastDecl;
+
+ friend class ExternalASTSource;
+
+ /// \brief Build up a chain of declarations.
+ ///
+ /// \returns the first/last pair of declarations.
+ static std::pair<Decl *, Decl *>
+ BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &Decls);
+
+ DeclContext(Decl::Kind K)
+ : DeclKind(K), ExternalLexicalStorage(false),
+ ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
+ LastDecl(0) { }
+
+public:
+ ~DeclContext();
+
+ Decl::Kind getDeclKind() const {
+ return static_cast<Decl::Kind>(DeclKind);
+ }
+ const char *getDeclKindName() const;
+
+ /// getParent - Returns the containing DeclContext.
+ DeclContext *getParent() {
+ return cast<Decl>(this)->getDeclContext();
+ }
+ const DeclContext *getParent() const {
+ return const_cast<DeclContext*>(this)->getParent();
+ }
+
+ /// getLexicalParent - Returns the containing lexical DeclContext. May be
+ /// different from getParent, e.g.:
+ ///
+ /// namespace A {
+ /// struct S;
+ /// }
+ /// struct A::S {}; // getParent() == namespace 'A'
+ /// // getLexicalParent() == translation unit
+ ///
+ DeclContext *getLexicalParent() {
+ return cast<Decl>(this)->getLexicalDeclContext();
+ }
+ const DeclContext *getLexicalParent() const {
+ return const_cast<DeclContext*>(this)->getLexicalParent();
+ }
+
+ DeclContext *getLookupParent();
+
+ const DeclContext *getLookupParent() const {
+ return const_cast<DeclContext*>(this)->getLookupParent();
+ }
+
+ ASTContext &getParentASTContext() const {
+ return cast<Decl>(this)->getASTContext();
+ }
+
+ bool isFunctionOrMethod() const {
+ switch (DeclKind) {
+ case Decl::Block:
+ case Decl::ObjCMethod:
+ return true;
+ default:
+ return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
+ }
+ }
+
+ bool isFileContext() const {
+ return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
+ }
+
+ bool isTranslationUnit() const {
+ return DeclKind == Decl::TranslationUnit;
+ }
+
+ bool isRecord() const {
+ return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
+ }
+
+ bool isNamespace() const {
+ return DeclKind == Decl::Namespace;
+ }
+
+ bool isInlineNamespace() const;
+
+ /// \brief Determines whether this context is dependent on a
+ /// template parameter.
+ bool isDependentContext() const;
+
+ /// isTransparentContext - Determines whether this context is a
+ /// "transparent" context, meaning that the members declared in this
+ /// context are semantically declared in the nearest enclosing
+ /// non-transparent (opaque) context but are lexically declared in
+ /// this context. For example, consider the enumerators of an
+ /// enumeration type:
+ /// @code
+ /// enum E {
+ /// Val1
+ /// };
+ /// @endcode
+ /// Here, E is a transparent context, so its enumerator (Val1) will
+ /// appear (semantically) that it is in the same context of E.
+ /// Examples of transparent contexts include: enumerations (except for
+ /// C++0x scoped enums), and C++ linkage specifications.
+ bool isTransparentContext() const;
+
+ /// \brief Determines whether this context is, or is nested within,
+ /// a C++ extern "C" linkage spec.
+ bool isExternCContext() const;
+
+ /// \brief Determine whether this declaration context is equivalent
+ /// to the declaration context DC.
+ bool Equals(const DeclContext *DC) const {
+ return DC && this->getPrimaryContext() == DC->getPrimaryContext();
+ }
+
+ /// \brief Determine whether this declaration context encloses the
+ /// declaration context DC.
+ bool Encloses(const DeclContext *DC) const;
+
+ /// getPrimaryContext - There may be many different
+ /// declarations of the same entity (including forward declarations
+ /// of classes, multiple definitions of namespaces, etc.), each with
+ /// a different set of declarations. This routine returns the
+ /// "primary" DeclContext structure, which will contain the
+ /// information needed to perform name lookup into this context.
+ DeclContext *getPrimaryContext();
+ const DeclContext *getPrimaryContext() const {
+ return const_cast<DeclContext*>(this)->getPrimaryContext();
+ }
+
+ /// getRedeclContext - Retrieve the context in which an entity conflicts with
+ /// other entities of the same name, or where it is a redeclaration if the
+ /// two entities are compatible. This skips through transparent contexts.
+ DeclContext *getRedeclContext();
+ const DeclContext *getRedeclContext() const {
+ return const_cast<DeclContext *>(this)->getRedeclContext();
+ }
+
+ /// \brief Retrieve the nearest enclosing namespace context.
+ DeclContext *getEnclosingNamespaceContext();
+ const DeclContext *getEnclosingNamespaceContext() const {
+ return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
+ }
+
+ /// \brief Test if this context is part of the enclosing namespace set of
+ /// the context NS, as defined in C++0x [namespace.def]p9. If either context
+ /// isn't a namespace, this is equivalent to Equals().
+ ///
+ /// The enclosing namespace set of a namespace is the namespace and, if it is
+ /// inline, its enclosing namespace, recursively.
+ bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
+
+ /// getNextContext - If this is a DeclContext that may have other
+ /// DeclContexts that are semantically connected but syntactically
+ /// different, such as C++ namespaces, this routine retrieves the
+ /// next DeclContext in the link. Iteration through the chain of
+ /// DeclContexts should begin at the primary DeclContext and
+ /// continue until this function returns NULL. For example, given:
+ /// @code
+ /// namespace N {
+ /// int x;
+ /// }
+ /// namespace N {
+ /// int y;
+ /// }
+ /// @endcode
+ /// The first occurrence of namespace N will be the primary
+ /// DeclContext. Its getNextContext will return the second
+ /// occurrence of namespace N.
+ DeclContext *getNextContext();
+
+ /// decl_iterator - Iterates through the declarations stored
+ /// within this context.
+ class decl_iterator {
+ /// Current - The current declaration.
+ Decl *Current;
+
+ public:
+ typedef Decl* value_type;
+ typedef Decl* reference;
+ typedef Decl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ decl_iterator() : Current(0) { }
+ explicit decl_iterator(Decl *C) : Current(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ decl_iterator& operator++() {
+ Current = Current->getNextDeclInContext();
+ return *this;
+ }
+
+ decl_iterator operator++(int) {
+ decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(decl_iterator x, decl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(decl_iterator x, decl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// decls_begin/decls_end - Iterate over the declarations stored in
+ /// this context.
+ decl_iterator decls_begin() const;
+ decl_iterator decls_end() const;
+ bool decls_empty() const;
+
+ /// noload_decls_begin/end - Iterate over the declarations stored in this
+ /// context that are currently loaded; don't attempt to retrieve anything
+ /// from an external source.
+ decl_iterator noload_decls_begin() const;
+ decl_iterator noload_decls_end() const;
+
+ /// specific_decl_iterator - Iterates over a subrange of
+ /// declarations stored in a DeclContext, providing only those that
+ /// are of type SpecificDecl (or a class derived from it). This
+ /// iterator is used, for example, to provide iteration over just
+ /// the fields within a RecordDecl (with SpecificDecl = FieldDecl).
+ template<typename SpecificDecl>
+ class specific_decl_iterator {
+ /// Current - The current, underlying declaration iterator, which
+ /// will either be NULL or will point to a declaration of
+ /// type SpecificDecl.
+ DeclContext::decl_iterator Current;
+
+ /// SkipToNextDecl - Advances the current position up to the next
+ /// declaration of type SpecificDecl that also meets the criteria
+ /// required by Acceptable.
+ void SkipToNextDecl() {
+ while (*Current && !isa<SpecificDecl>(*Current))
+ ++Current;
+ }
+
+ public:
+ typedef SpecificDecl* value_type;
+ typedef SpecificDecl* reference;
+ typedef SpecificDecl* pointer;
+ typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+ difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ specific_decl_iterator() : Current() { }
+
+ /// specific_decl_iterator - Construct a new iterator over a
+ /// subset of the declarations the range [C,
+ /// end-of-declarations). If A is non-NULL, it is a pointer to a
+ /// member function of SpecificDecl that should return true for
+ /// all of the SpecificDecl instances that will be in the subset
+ /// of iterators. For example, if you want Objective-C instance
+ /// methods, SpecificDecl will be ObjCMethodDecl and A will be
+ /// &ObjCMethodDecl::isInstanceMethod.
+ explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
+ SkipToNextDecl();
+ }
+
+ reference operator*() const { return cast<SpecificDecl>(*Current); }
+ pointer operator->() const { return cast<SpecificDecl>(*Current); }
+
+ specific_decl_iterator& operator++() {
+ ++Current;
+ SkipToNextDecl();
+ return *this;
+ }
+
+ specific_decl_iterator operator++(int) {
+ specific_decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool
+ operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+ return x.Current == y.Current;
+ }
+
+ friend bool
+ operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Iterates over a filtered subrange of declarations stored
+ /// in a DeclContext.
+ ///
+ /// This iterator visits only those declarations that are of type
+ /// SpecificDecl (or a class derived from it) and that meet some
+ /// additional run-time criteria. This iterator is used, for
+ /// example, to provide access to the instance methods within an
+ /// Objective-C interface (with SpecificDecl = ObjCMethodDecl and
+ /// Acceptable = ObjCMethodDecl::isInstanceMethod).
+ template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const>
+ class filtered_decl_iterator {
+ /// Current - The current, underlying declaration iterator, which
+ /// will either be NULL or will point to a declaration of
+ /// type SpecificDecl.
+ DeclContext::decl_iterator Current;
+
+ /// SkipToNextDecl - Advances the current position up to the next
+ /// declaration of type SpecificDecl that also meets the criteria
+ /// required by Acceptable.
+ void SkipToNextDecl() {
+ while (*Current &&
+ (!isa<SpecificDecl>(*Current) ||
+ (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
+ ++Current;
+ }
+
+ public:
+ typedef SpecificDecl* value_type;
+ typedef SpecificDecl* reference;
+ typedef SpecificDecl* pointer;
+ typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+ difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ filtered_decl_iterator() : Current() { }
+
+ /// specific_decl_iterator - Construct a new iterator over a
+ /// subset of the declarations the range [C,
+ /// end-of-declarations). If A is non-NULL, it is a pointer to a
+ /// member function of SpecificDecl that should return true for
+ /// all of the SpecificDecl instances that will be in the subset
+ /// of iterators. For example, if you want Objective-C instance
+ /// methods, SpecificDecl will be ObjCMethodDecl and A will be
+ /// &ObjCMethodDecl::isInstanceMethod.
+ explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
+ SkipToNextDecl();
+ }
+
+ reference operator*() const { return cast<SpecificDecl>(*Current); }
+ pointer operator->() const { return cast<SpecificDecl>(*Current); }
+
+ filtered_decl_iterator& operator++() {
+ ++Current;
+ SkipToNextDecl();
+ return *this;
+ }
+
+ filtered_decl_iterator operator++(int) {
+ filtered_decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool
+ operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
+ return x.Current == y.Current;
+ }
+
+ friend bool
+ operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// @brief Add the declaration D into this context.
+ ///
+ /// This routine should be invoked when the declaration D has first
+ /// been declared, to place D into the context where it was
+ /// (lexically) defined. Every declaration must be added to one
+ /// (and only one!) context, where it can be visited via
+ /// [decls_begin(), decls_end()). Once a declaration has been added
+ /// to its lexical context, the corresponding DeclContext owns the
+ /// declaration.
+ ///
+ /// If D is also a NamedDecl, it will be made visible within its
+ /// semantic context via makeDeclVisibleInContext.
+ void addDecl(Decl *D);
+
+ /// @brief Add the declaration D to this context without modifying
+ /// any lookup tables.
+ ///
+ /// This is useful for some operations in dependent contexts where
+ /// the semantic context might not be dependent; this basically
+ /// only happens with friends.
+ void addHiddenDecl(Decl *D);
+
+ /// @brief Removes a declaration from this context.
+ void removeDecl(Decl *D);
+
+ /// lookup_iterator - An iterator that provides access to the results
+ /// of looking up a name within this context.
+ typedef NamedDecl **lookup_iterator;
+
+ /// lookup_const_iterator - An iterator that provides non-mutable
+ /// access to the results of lookup up a name within this context.
+ typedef NamedDecl * const * lookup_const_iterator;
+
+ typedef DeclContextLookupResult lookup_result;
+ typedef DeclContextLookupConstResult lookup_const_result;
+
+ /// lookup - Find the declarations (if any) with the given Name in
+ /// this context. Returns a range of iterators that contains all of
+ /// the declarations with this name, with object, function, member,
+ /// and enumerator names preceding any tag name. Note that this
+ /// routine will not look into parent contexts.
+ lookup_result lookup(DeclarationName Name);
+ lookup_const_result lookup(DeclarationName Name) const;
+
+ /// @brief Makes a declaration visible within this context.
+ ///
+ /// This routine makes the declaration D visible to name lookup
+ /// within this context and, if this is a transparent context,
+ /// within its parent contexts up to the first enclosing
+ /// non-transparent context. Making a declaration visible within a
+ /// context does not transfer ownership of a declaration, and a
+ /// declaration can be visible in many contexts that aren't its
+ /// lexical context.
+ ///
+ /// If D is a redeclaration of an existing declaration that is
+ /// visible from this context, as determined by
+ /// NamedDecl::declarationReplaces, the previous declaration will be
+ /// replaced with D.
+ ///
+ /// @param Recoverable true if it's okay to not add this decl to
+ /// the lookup tables because it can be easily recovered by walking
+ /// the declaration chains.
+ void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
+
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table.
+ void MaterializeVisibleDeclsFromExternalStorage();
+
+ /// udir_iterator - Iterates through the using-directives stored
+ /// within this context.
+ typedef UsingDirectiveDecl * const * udir_iterator;
+
+ typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
+
+ udir_iterator_range getUsingDirectives() const;
+
+ udir_iterator using_directives_begin() const {
+ return getUsingDirectives().first;
+ }
+
+ udir_iterator using_directives_end() const {
+ return getUsingDirectives().second;
+ }
+
+ // These are all defined in DependentDiagnostic.h.
+ class ddiag_iterator;
+ inline ddiag_iterator ddiag_begin() const;
+ inline ddiag_iterator ddiag_end() const;
+
+ // Low-level accessors
+
+ /// \brief Retrieve the internal representation of the lookup structure.
+ StoredDeclsMap* getLookupPtr() const { return LookupPtr; }
+
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are lexically in this context.
+ bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations lexically in this context.
+ void setHasExternalLexicalStorage(bool ES = true) {
+ ExternalLexicalStorage = ES;
+ }
+
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are visible in this context.
+ bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations visible in this context.
+ void setHasExternalVisibleStorage(bool ES = true) {
+ ExternalVisibleStorage = ES;
+ }
+
+ static bool classof(const Decl *D);
+ static bool classof(const DeclContext *D) { return true; }
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) \
+ static bool classof(const NAME##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.inc"
+
+ void dumpDeclContext() const;
+
+private:
+ void LoadLexicalDeclsFromExternalStorage() const;
+
+ friend class DependentDiagnostic;
+ StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
+
+ void buildLookup(DeclContext *DCtx);
+ void makeDeclVisibleInContextImpl(NamedDecl *D);
+};
+
+inline bool Decl::isTemplateParameter() const {
+ return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm ||
+ getKind() == TemplateTemplateParm;
+}
+
+// Specialization selected when ToTy is not a known subclass of DeclContext.
+template <class ToTy,
+ bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
+struct cast_convert_decl_context {
+ static const ToTy *doit(const DeclContext *Val) {
+ return static_cast<const ToTy*>(Decl::castFromDeclContext(Val));
+ }
+
+ static ToTy *doit(DeclContext *Val) {
+ return static_cast<ToTy*>(Decl::castFromDeclContext(Val));
+ }
+};
+
+// Specialization selected when ToTy is a known subclass of DeclContext.
+template <class ToTy>
+struct cast_convert_decl_context<ToTy, true> {
+ static const ToTy *doit(const DeclContext *Val) {
+ return static_cast<const ToTy*>(Val);
+ }
+
+ static ToTy *doit(DeclContext *Val) {
+ return static_cast<ToTy*>(Val);
+ }
+};
+
+
+} // end clang.
+
+namespace llvm {
+
+/// isa<T>(DeclContext*)
+template<class ToTy>
+struct isa_impl_wrap<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {
+ static bool doit(const ::clang::DeclContext &Val) {
+ return ToTy::classofKind(Val.getDeclKind());
+ }
+};
+template<class ToTy>
+struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
+ : public isa_impl_wrap<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {};
+
+/// cast<T>(DeclContext*)
+template<class ToTy>
+struct cast_convert_val<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {
+ static const ToTy &doit(const ::clang::DeclContext &Val) {
+ return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
+ }
+};
+template<class ToTy>
+struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> {
+ static ToTy &doit(::clang::DeclContext &Val) {
+ return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
+ }
+};
+template<class ToTy>
+struct cast_convert_val<ToTy,
+ const ::clang::DeclContext*, const ::clang::DeclContext*> {
+ static const ToTy *doit(const ::clang::DeclContext *Val) {
+ return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
+ }
+};
+template<class ToTy>
+struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> {
+ static ToTy *doit(::clang::DeclContext *Val) {
+ return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
+ }
+};
+
+/// Implement cast_convert_val for Decl -> DeclContext conversions.
+template<class FromTy>
+struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> {
+ static ::clang::DeclContext &doit(const FromTy &Val) {
+ return *FromTy::castToDeclContext(&Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> {
+ static ::clang::DeclContext *doit(const FromTy *Val) {
+ return FromTy::castToDeclContext(Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
+ static const ::clang::DeclContext &doit(const FromTy &Val) {
+ return *FromTy::castToDeclContext(&Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
+ static const ::clang::DeclContext *doit(const FromTy *Val) {
+ return FromTy::castToDeclContext(Val);
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
new file mode 100644
index 0000000..d11ee8f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -0,0 +1,2315 @@
+//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C++ Decl subclasses, other than those for
+// templates (in DeclTemplate.h) and friends (in DeclFriend.h).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLCXX_H
+#define LLVM_CLANG_AST_DECLCXX_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+class ClassTemplateDecl;
+class ClassTemplateSpecializationDecl;
+class CXXBasePath;
+class CXXBasePaths;
+class CXXConstructorDecl;
+class CXXConversionDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class CXXMemberLookupCriteria;
+class CXXFinalOverriderMap;
+class CXXIndirectPrimaryBaseSet;
+class FriendDecl;
+
+/// \brief Represents any kind of function declaration, whether it is a
+/// concrete function or a function template.
+class AnyFunctionDecl {
+ NamedDecl *Function;
+
+ AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
+
+public:
+ AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
+ AnyFunctionDecl(FunctionTemplateDecl *FTD);
+
+ /// \brief Implicily converts any function or function template into a
+ /// named declaration.
+ operator NamedDecl *() const { return Function; }
+
+ /// \brief Retrieve the underlying function or function template.
+ NamedDecl *get() const { return Function; }
+
+ static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
+ return AnyFunctionDecl(ND);
+ }
+};
+
+} // end namespace clang
+
+namespace llvm {
+ /// Implement simplify_type for AnyFunctionDecl, so that we can dyn_cast from
+ /// AnyFunctionDecl to any function or function template declaration.
+ template<> struct simplify_type<const ::clang::AnyFunctionDecl> {
+ typedef ::clang::NamedDecl* SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::AnyFunctionDecl &Val) {
+ return Val;
+ }
+ };
+ template<> struct simplify_type< ::clang::AnyFunctionDecl>
+ : public simplify_type<const ::clang::AnyFunctionDecl> {};
+
+ // Provide PointerLikeTypeTraits for non-cvr pointers.
+ template<>
+ class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
+ public:
+ static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
+ return F.get();
+ }
+ static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
+ return ::clang::AnyFunctionDecl::getFromNamedDecl(
+ static_cast< ::clang::NamedDecl*>(P));
+ }
+
+ enum { NumLowBitsAvailable = 2 };
+ };
+
+} // end namespace llvm
+
+namespace clang {
+
+/// AccessSpecDecl - An access specifier followed by colon ':'.
+///
+/// An objects of this class represents sugar for the syntactic occurrence
+/// of an access specifier followed by a colon in the list of member
+/// specifiers of a C++ class definition.
+///
+/// Note that they do not represent other uses of access specifiers,
+/// such as those occurring in a list of base specifiers.
+/// Also note that this class has nothing to do with so-called
+/// "access declarations" (C++98 11.3 [class.access.dcl]).
+class AccessSpecDecl : public Decl {
+ /// ColonLoc - The location of the ':'.
+ SourceLocation ColonLoc;
+
+ AccessSpecDecl(AccessSpecifier AS, DeclContext *DC,
+ SourceLocation ASLoc, SourceLocation ColonLoc)
+ : Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) {
+ setAccess(AS);
+ }
+ AccessSpecDecl(EmptyShell Empty)
+ : Decl(AccessSpec, Empty) { }
+public:
+ /// getAccessSpecifierLoc - The location of the access specifier.
+ SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
+ /// setAccessSpecifierLoc - Sets the location of the access specifier.
+ void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); }
+
+ /// getColonLoc - The location of the colon following the access specifier.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ /// setColonLoc - Sets the location of the colon.
+ void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getAccessSpecifierLoc(), getColonLoc());
+ }
+
+ static AccessSpecDecl *Create(ASTContext &C, AccessSpecifier AS,
+ DeclContext *DC, SourceLocation ASLoc,
+ SourceLocation ColonLoc) {
+ return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
+ }
+ static AccessSpecDecl *Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) AccessSpecDecl(Empty);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const AccessSpecDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == AccessSpec; }
+};
+
+
+/// CXXBaseSpecifier - A base class of a C++ class.
+///
+/// Each CXXBaseSpecifier represents a single, direct base class (or
+/// struct) of a C++ class (or struct). It specifies the type of that
+/// base class, whether it is a virtual or non-virtual base, and what
+/// level of access (public, protected, private) is used for the
+/// derivation. For example:
+///
+/// @code
+/// class A { };
+/// class B { };
+/// class C : public virtual A, protected B { };
+/// @endcode
+///
+/// In this code, C will have two CXXBaseSpecifiers, one for "public
+/// virtual A" and the other for "protected B".
+class CXXBaseSpecifier {
+ /// Range - The source code range that covers the full base
+ /// specifier, including the "virtual" (if present) and access
+ /// specifier (if present).
+ SourceRange Range;
+
+ /// \brief The source location of the ellipsis, if this is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
+ /// Virtual - Whether this is a virtual base class or not.
+ bool Virtual : 1;
+
+ /// BaseOfClass - Whether this is the base of a class (true) or of a
+ /// struct (false). This determines the mapping from the access
+ /// specifier as written in the source code to the access specifier
+ /// used for semantic analysis.
+ bool BaseOfClass : 1;
+
+ /// Access - Access specifier as written in the source code (which
+ /// may be AS_none). The actual type of data stored here is an
+ /// AccessSpecifier, but we use "unsigned" here to work around a
+ /// VC++ bug.
+ unsigned Access : 2;
+
+ /// InheritConstructors - Whether the class contains a using declaration
+ /// to inherit the named class's constructors.
+ bool InheritConstructors : 1;
+
+ /// BaseTypeInfo - The type of the base class. This will be a class or struct
+ /// (or a typedef of such). The source code range does not include the
+ /// "virtual" or access specifier.
+ TypeSourceInfo *BaseTypeInfo;
+
+public:
+ CXXBaseSpecifier() { }
+
+ CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
+ TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
+ : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
+ Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { }
+
+ /// getSourceRange - Retrieves the source range that contains the
+ /// entire base specifier.
+ SourceRange getSourceRange() const { return Range; }
+
+ /// isVirtual - Determines whether the base class is a virtual base
+ /// class (or not).
+ bool isVirtual() const { return Virtual; }
+
+ /// \brief Determine whether this base class is a base of a class declared
+ /// with the 'class' keyword (vs. one declared with the 'struct' keyword).
+ bool isBaseOfClass() const { return BaseOfClass; }
+
+ /// \brief Determine whether this base specifier is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+ /// \brief Determine whether this base class's constructors get inherited.
+ bool getInheritConstructors() const { return InheritConstructors; }
+
+ /// \brief Set that this base class's constructors should be inherited.
+ void setInheritConstructors(bool Inherit = true) {
+ InheritConstructors = Inherit;
+ }
+
+ /// \brief For a pack expansion, determine the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
+ /// getAccessSpecifier - Returns the access specifier for this base
+ /// specifier. This is the actual base specifier as used for
+ /// semantic analysis, so the result can never be AS_none. To
+ /// retrieve the access specifier as written in the source code, use
+ /// getAccessSpecifierAsWritten().
+ AccessSpecifier getAccessSpecifier() const {
+ if ((AccessSpecifier)Access == AS_none)
+ return BaseOfClass? AS_private : AS_public;
+ else
+ return (AccessSpecifier)Access;
+ }
+
+ /// getAccessSpecifierAsWritten - Retrieves the access specifier as
+ /// written in the source code (which may mean that no access
+ /// specifier was explicitly written). Use getAccessSpecifier() to
+ /// retrieve the access specifier for use in semantic analysis.
+ AccessSpecifier getAccessSpecifierAsWritten() const {
+ return (AccessSpecifier)Access;
+ }
+
+ /// getType - Retrieves the type of the base class. This type will
+ /// always be an unqualified class type.
+ QualType getType() const { return BaseTypeInfo->getType(); }
+
+ /// getTypeLoc - Retrieves the type and source location of the base class.
+ TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
+};
+
+/// CXXRecordDecl - Represents a C++ struct/union/class.
+/// FIXME: This class will disappear once we've properly taught RecordDecl
+/// to deal with C++-specific things.
+class CXXRecordDecl : public RecordDecl {
+
+ friend void TagDecl::startDefinition();
+
+ struct DefinitionData {
+ DefinitionData(CXXRecordDecl *D);
+
+ /// UserDeclaredConstructor - True when this class has a
+ /// user-declared constructor.
+ bool UserDeclaredConstructor : 1;
+
+ /// UserDeclaredCopyConstructor - True when this class has a
+ /// user-declared copy constructor.
+ bool UserDeclaredCopyConstructor : 1;
+
+ /// UserDeclaredCopyAssignment - True when this class has a
+ /// user-declared copy assignment operator.
+ bool UserDeclaredCopyAssignment : 1;
+
+ /// UserDeclaredDestructor - True when this class has a
+ /// user-declared destructor.
+ bool UserDeclaredDestructor : 1;
+
+ /// Aggregate - True when this class is an aggregate.
+ bool Aggregate : 1;
+
+ /// PlainOldData - True when this class is a POD-type.
+ bool PlainOldData : 1;
+
+ /// Empty - true when this class is empty for traits purposes,
+ /// i.e. has no data members other than 0-width bit-fields, has no
+ /// virtual function/base, and doesn't inherit from a non-empty
+ /// class. Doesn't take union-ness into account.
+ bool Empty : 1;
+
+ /// Polymorphic - True when this class is polymorphic, i.e. has at
+ /// least one virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
+ /// Abstract - True when this class is abstract, i.e. has at least
+ /// one pure virtual function, (that can come from a base class).
+ bool Abstract : 1;
+
+ /// HasTrivialConstructor - True when this class has a trivial constructor.
+ ///
+ /// C++ [class.ctor]p5. A constructor is trivial if it is an
+ /// implicitly-declared default constructor and if:
+ /// * its class has no virtual functions and no virtual base classes, and
+ /// * all the direct base classes of its class have trivial constructors, and
+ /// * for all the nonstatic data members of its class that are of class type
+ /// (or array thereof), each such class has a trivial constructor.
+ bool HasTrivialConstructor : 1;
+
+ /// HasTrivialCopyConstructor - True when this class has a trivial copy
+ /// constructor.
+ ///
+ /// C++ [class.copy]p6. A copy constructor for class X is trivial
+ /// if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy constructor, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy constructor;
+ /// otherwise the copy constructor is non-trivial.
+ bool HasTrivialCopyConstructor : 1;
+
+ /// HasTrivialCopyAssignment - True when this class has a trivial copy
+ /// assignment operator.
+ ///
+ /// C++ [class.copy]p11. A copy assignment operator for class X is
+ /// trivial if it is implicitly declared and if
+ /// * class X has no virtual functions and no virtual base classes, and
+ /// * each direct base class of X has a trivial copy assignment operator, and
+ /// * for all the nonstatic data members of X that are of class type (or
+ /// array thereof), each such class type has a trivial copy assignment
+ /// operator;
+ /// otherwise the copy assignment operator is non-trivial.
+ bool HasTrivialCopyAssignment : 1;
+
+ /// HasTrivialDestructor - True when this class has a trivial destructor.
+ ///
+ /// C++ [class.dtor]p3. A destructor is trivial if it is an
+ /// implicitly-declared destructor and if:
+ /// * all of the direct base classes of its class have trivial destructors
+ /// and
+ /// * for all of the non-static data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial destructor.
+ bool HasTrivialDestructor : 1;
+
+ /// ComputedVisibleConversions - True when visible conversion functions are
+ /// already computed and are available.
+ bool ComputedVisibleConversions : 1;
+
+ /// \brief Whether we have already declared the default constructor or
+ /// do not need to have one declared.
+ bool DeclaredDefaultConstructor : 1;
+
+ /// \brief Whether we have already declared the copy constructor.
+ bool DeclaredCopyConstructor : 1;
+
+ /// \brief Whether we have already declared the copy-assignment operator.
+ bool DeclaredCopyAssignment : 1;
+
+ /// \brief Whether we have already declared a destructor within the class.
+ bool DeclaredDestructor : 1;
+
+ /// NumBases - The number of base class specifiers in Bases.
+ unsigned NumBases;
+
+ /// NumVBases - The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ LazyCXXBaseSpecifiersPtr Bases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ LazyCXXBaseSpecifiersPtr VBases;
+
+ /// Conversions - Overload set containing the conversion functions
+ /// of this C++ class (but not its inherited conversion
+ /// functions). Each of the entries in this overload set is a
+ /// CXXConversionDecl.
+ UnresolvedSet<4> Conversions;
+
+ /// VisibleConversions - Overload set containing the conversion
+ /// functions of this C++ class and all those inherited conversion
+ /// functions that are visible in this class. Each of the entries
+ /// in this overload set is a CXXConversionDecl or a
+ /// FunctionTemplateDecl.
+ UnresolvedSet<4> VisibleConversions;
+
+ /// Definition - The declaration which defines this record.
+ CXXRecordDecl *Definition;
+
+ /// FirstFriend - The first friend declaration in this class, or
+ /// null if there aren't any. This is actually currently stored
+ /// in reverse order.
+ FriendDecl *FirstFriend;
+
+ /// \brief Retrieve the set of direct base classes.
+ CXXBaseSpecifier *getBases() const {
+ return Bases.get(Definition->getASTContext().getExternalSource());
+ }
+
+ /// \brief Retrieve the set of virtual base classes.
+ CXXBaseSpecifier *getVBases() const {
+ return VBases.get(Definition->getASTContext().getExternalSource());
+ }
+ } *DefinitionData;
+
+ struct DefinitionData &data() {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
+
+ const struct DefinitionData &data() const {
+ assert(DefinitionData && "queried property of class with no definition");
+ return *DefinitionData;
+ }
+
+ /// \brief The template or declaration that this declaration
+ /// describes or was instantiated from, respectively.
+ ///
+ /// For non-templates, this value will be NULL. For record
+ /// declarations that describe a class template, this will be a
+ /// pointer to a ClassTemplateDecl. For member
+ /// classes of class template specializations, this will be the
+ /// MemberSpecializationInfo referring to the member class that was
+ /// instantiated or specialized.
+ llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>
+ TemplateOrInstantiation;
+
+ friend class DeclContext;
+
+ /// \brief Notify the class that member has been added.
+ ///
+ /// This routine helps maintain information about the class based on which
+ /// members have been added. It will be invoked by DeclContext::addDecl()
+ /// whenever a member is added to this record.
+ void addedMember(Decl *D);
+
+ void markedVirtualFunctionPure();
+ friend void FunctionDecl::setPure(bool);
+
+protected:
+ CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL = SourceLocation());
+
+public:
+ /// base_class_iterator - Iterator that traverses the base classes
+ /// of a class.
+ typedef CXXBaseSpecifier* base_class_iterator;
+
+ /// base_class_const_iterator - Iterator that traverses the base
+ /// classes of a class.
+ typedef const CXXBaseSpecifier* base_class_const_iterator;
+
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_iterator>
+ reverse_base_class_iterator;
+
+ /// reverse_base_class_iterator = Iterator that traverses the base classes
+ /// of a class in reverse order.
+ typedef std::reverse_iterator<base_class_const_iterator>
+ reverse_base_class_const_iterator;
+
+ virtual CXXRecordDecl *getCanonicalDecl() {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+ virtual const CXXRecordDecl *getCanonicalDecl() const {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+
+ const CXXRecordDecl *getPreviousDeclaration() const {
+ return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration());
+ }
+ CXXRecordDecl *getPreviousDeclaration() {
+ return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration());
+ }
+
+ CXXRecordDecl *getDefinition() const {
+ if (!DefinitionData) return 0;
+ return data().Definition;
+ }
+
+ bool hasDefinition() const { return DefinitionData != 0; }
+
+ static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL = SourceLocation(),
+ CXXRecordDecl* PrevDecl=0,
+ bool DelayTypeCreation = false);
+ static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty);
+
+ bool isDynamicClass() const {
+ return data().Polymorphic || data().NumVBases != 0;
+ }
+
+ /// setBases - Sets the base classes of this struct or class.
+ void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
+
+ /// getNumBases - Retrieves the number of base classes of this
+ /// class.
+ unsigned getNumBases() const { return data().NumBases; }
+
+ base_class_iterator bases_begin() { return data().getBases(); }
+ base_class_const_iterator bases_begin() const { return data().getBases(); }
+ base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
+ base_class_const_iterator bases_end() const {
+ return bases_begin() + data().NumBases;
+ }
+ reverse_base_class_iterator bases_rbegin() {
+ return reverse_base_class_iterator(bases_end());
+ }
+ reverse_base_class_const_iterator bases_rbegin() const {
+ return reverse_base_class_const_iterator(bases_end());
+ }
+ reverse_base_class_iterator bases_rend() {
+ return reverse_base_class_iterator(bases_begin());
+ }
+ reverse_base_class_const_iterator bases_rend() const {
+ return reverse_base_class_const_iterator(bases_begin());
+ }
+
+ /// getNumVBases - Retrieves the number of virtual base classes of this
+ /// class.
+ unsigned getNumVBases() const { return data().NumVBases; }
+
+ base_class_iterator vbases_begin() { return data().getVBases(); }
+ base_class_const_iterator vbases_begin() const { return data().getVBases(); }
+ base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
+ base_class_const_iterator vbases_end() const {
+ return vbases_begin() + data().NumVBases;
+ }
+ reverse_base_class_iterator vbases_rbegin() {
+ return reverse_base_class_iterator(vbases_end());
+ }
+ reverse_base_class_const_iterator vbases_rbegin() const {
+ return reverse_base_class_const_iterator(vbases_end());
+ }
+ reverse_base_class_iterator vbases_rend() {
+ return reverse_base_class_iterator(vbases_begin());
+ }
+ reverse_base_class_const_iterator vbases_rend() const {
+ return reverse_base_class_const_iterator(vbases_begin());
+ }
+
+ /// \brief Determine whether this class has any dependent base classes.
+ bool hasAnyDependentBases() const;
+
+ /// Iterator access to method members. The method iterator visits
+ /// all method members of the class, including non-instance methods,
+ /// special methods, etc.
+ typedef specific_decl_iterator<CXXMethodDecl> method_iterator;
+
+ /// method_begin - Method begin iterator. Iterates in the order the methods
+ /// were declared.
+ method_iterator method_begin() const {
+ return method_iterator(decls_begin());
+ }
+ /// method_end - Method end iterator.
+ method_iterator method_end() const {
+ return method_iterator(decls_end());
+ }
+
+ /// Iterator access to constructor members.
+ typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator;
+
+ ctor_iterator ctor_begin() const {
+ return ctor_iterator(decls_begin());
+ }
+ ctor_iterator ctor_end() const {
+ return ctor_iterator(decls_end());
+ }
+
+ /// An iterator over friend declarations. All of these are defined
+ /// in DeclFriend.h.
+ class friend_iterator;
+ friend_iterator friend_begin() const;
+ friend_iterator friend_end() const;
+ void pushFriendDecl(FriendDecl *FD);
+
+ /// Determines whether this record has any friends.
+ bool hasFriends() const {
+ return data().FirstFriend != 0;
+ }
+
+ /// \brief Determine whether this class has had its default constructor
+ /// declared implicitly or does not need one declared implicitly.
+ ///
+ /// This value is used for lazy creation of default constructors.
+ bool hasDeclaredDefaultConstructor() const {
+ return data().DeclaredDefaultConstructor;
+ }
+
+ /// hasConstCopyConstructor - Determines whether this class has a
+ /// copy constructor that accepts a const-qualified argument.
+ bool hasConstCopyConstructor(const ASTContext &Context) const;
+
+ /// getCopyConstructor - Returns the copy constructor for this class
+ CXXConstructorDecl *getCopyConstructor(const ASTContext &Context,
+ unsigned TypeQuals) const;
+
+ /// \brief Retrieve the copy-assignment operator for this class, if available.
+ ///
+ /// This routine attempts to find the copy-assignment operator for this
+ /// class, using a simplistic form of overload resolution.
+ ///
+ /// \param ArgIsConst Whether the argument to the copy-assignment operator
+ /// is const-qualified.
+ ///
+ /// \returns The copy-assignment operator that can be invoked, or NULL if
+ /// a unique copy-assignment operator could not be found.
+ CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const;
+
+ /// hasUserDeclaredConstructor - Whether this class has any
+ /// user-declared constructors. When true, a default constructor
+ /// will not be implicitly declared.
+ bool hasUserDeclaredConstructor() const {
+ return data().UserDeclaredConstructor;
+ }
+
+ /// hasUserDeclaredCopyConstructor - Whether this class has a
+ /// user-declared copy constructor. When false, a copy constructor
+ /// will be implicitly declared.
+ bool hasUserDeclaredCopyConstructor() const {
+ return data().UserDeclaredCopyConstructor;
+ }
+
+ /// \brief Determine whether this class has had its copy constructor
+ /// declared, either via the user or via an implicit declaration.
+ ///
+ /// This value is used for lazy creation of copy constructors.
+ bool hasDeclaredCopyConstructor() const {
+ return data().DeclaredCopyConstructor;
+ }
+
+ /// hasUserDeclaredCopyAssignment - Whether this class has a
+ /// user-declared copy assignment operator. When false, a copy
+ /// assigment operator will be implicitly declared.
+ bool hasUserDeclaredCopyAssignment() const {
+ return data().UserDeclaredCopyAssignment;
+ }
+
+ /// \brief Determine whether this class has had its copy assignment operator
+ /// declared, either via the user or via an implicit declaration.
+ ///
+ /// This value is used for lazy creation of copy assignment operators.
+ bool hasDeclaredCopyAssignment() const {
+ return data().DeclaredCopyAssignment;
+ }
+
+ /// hasUserDeclaredDestructor - Whether this class has a
+ /// user-declared destructor. When false, a destructor will be
+ /// implicitly declared.
+ bool hasUserDeclaredDestructor() const {
+ return data().UserDeclaredDestructor;
+ }
+
+ /// \brief Determine whether this class has had its destructor declared,
+ /// either via the user or via an implicit declaration.
+ ///
+ /// This value is used for lazy creation of destructors.
+ bool hasDeclaredDestructor() const { return data().DeclaredDestructor; }
+
+ /// getConversions - Retrieve the overload set containing all of the
+ /// conversion functions in this class.
+ UnresolvedSetImpl *getConversionFunctions() {
+ return &data().Conversions;
+ }
+ const UnresolvedSetImpl *getConversionFunctions() const {
+ return &data().Conversions;
+ }
+
+ typedef UnresolvedSetImpl::iterator conversion_iterator;
+ conversion_iterator conversion_begin() const {
+ return getConversionFunctions()->begin();
+ }
+ conversion_iterator conversion_end() const {
+ return getConversionFunctions()->end();
+ }
+
+ /// Removes a conversion function from this class. The conversion
+ /// function must currently be a member of this class. Furthermore,
+ /// this class must currently be in the process of being defined.
+ void removeConversion(const NamedDecl *Old);
+
+ /// getVisibleConversionFunctions - get all conversion functions visible
+ /// in current class; including conversion function templates.
+ const UnresolvedSetImpl *getVisibleConversionFunctions();
+
+ /// isAggregate - Whether this class is an aggregate (C++
+ /// [dcl.init.aggr]), which is a class with no user-declared
+ /// constructors, no private or protected non-static data members,
+ /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
+ bool isAggregate() const { return data().Aggregate; }
+
+ /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
+ /// that is an aggregate that has no non-static non-POD data members, no
+ /// reference data members, no user-defined copy assignment operator and no
+ /// user-defined destructor.
+ bool isPOD() const { return data().PlainOldData; }
+
+ /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
+ /// means it has a virtual function, virtual base, data member (other than
+ /// 0-width bit-field) or inherits from a non-empty class. Does NOT include
+ /// a check for union-ness.
+ bool isEmpty() const { return data().Empty; }
+
+ /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
+ /// which means that the class contains or inherits a virtual function.
+ bool isPolymorphic() const { return data().Polymorphic; }
+
+ /// isAbstract - Whether this class is abstract (C++ [class.abstract]),
+ /// which means that the class contains or inherits a pure virtual function.
+ bool isAbstract() const { return data().Abstract; }
+
+ // hasTrivialConstructor - Whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
+
+ // hasTrivialCopyConstructor - Whether this class has a trivial copy
+ // constructor (C++ [class.copy]p6)
+ bool hasTrivialCopyConstructor() const {
+ return data().HasTrivialCopyConstructor;
+ }
+
+ // hasTrivialCopyAssignment - Whether this class has a trivial copy
+ // assignment operator (C++ [class.copy]p11)
+ bool hasTrivialCopyAssignment() const {
+ return data().HasTrivialCopyAssignment;
+ }
+
+ // hasTrivialDestructor - Whether this class has a trivial destructor
+ // (C++ [class.dtor]p3)
+ bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
+
+ /// \brief If this record is an instantiation of a member class,
+ /// retrieves the member class from which it was instantiated.
+ ///
+ /// This routine will return non-NULL for (non-templated) member
+ /// classes of class templates. For example, given:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// struct A { };
+ /// };
+ /// \endcode
+ ///
+ /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl
+ /// whose parent is the class template specialization X<int>. For
+ /// this declaration, getInstantiatedFromMemberClass() will return
+ /// the CXXRecordDecl X<T>::A. When a complete definition of
+ /// X<int>::A is required, it will be instantiated from the
+ /// declaration returned by getInstantiatedFromMemberClass().
+ CXXRecordDecl *getInstantiatedFromMemberClass() const;
+
+ /// \brief If this class is an instantiation of a member class of a
+ /// class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member class RD.
+ void setInstantiationOfMemberClass(CXXRecordDecl *RD,
+ TemplateSpecializationKind TSK);
+
+ /// \brief Retrieves the class template that is described by this
+ /// class declaration.
+ ///
+ /// Every class template is represented as a ClassTemplateDecl and a
+ /// CXXRecordDecl. The former contains template properties (such as
+ /// the template parameter lists) while the latter contains the
+ /// actual description of the template's
+ /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the
+ /// CXXRecordDecl that from a ClassTemplateDecl, while
+ /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
+ /// a CXXRecordDecl.
+ ClassTemplateDecl *getDescribedClassTemplate() const {
+ return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
+ }
+
+ void setDescribedClassTemplate(ClassTemplateDecl *Template) {
+ TemplateOrInstantiation = Template;
+ }
+
+ /// \brief Determine whether this particular class is a specialization or
+ /// instantiation of a class template or member class of a class template,
+ /// and how it was instantiated or specialized.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief Set the kind of specialization or template instantiation this is.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
+
+ /// getDestructor - Returns the destructor decl for this class.
+ CXXDestructorDecl *getDestructor() const;
+
+ /// isLocalClass - If the class is a local class [class.local], returns
+ /// the enclosing function declaration.
+ const FunctionDecl *isLocalClass() const {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext()))
+ return RD->isLocalClass();
+
+ return dyn_cast<FunctionDecl>(getDeclContext());
+ }
+
+ /// \brief Determine whether this class is derived from the class \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ bool isDerivedFrom(const CXXRecordDecl *Base) const;
+
+ /// \brief Determine whether this class is derived from the type \p Base.
+ ///
+ /// This routine only determines whether this class is derived from \p Base,
+ /// but does not account for factors that may make a Derived -> Base class
+ /// ill-formed, such as private/protected inheritance or multiple, ambiguous
+ /// base class subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \param Paths will contain the paths taken from the current class to the
+ /// given \p Base class.
+ ///
+ /// \returns true if this class is derived from Base, false otherwise.
+ ///
+ /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
+ /// tangling input and output in \p Paths
+ bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+
+ /// \brief Determine whether this class is virtually derived from
+ /// the class \p Base.
+ ///
+ /// This routine only determines whether this class is virtually
+ /// derived from \p Base, but does not account for factors that may
+ /// make a Derived -> Base class ill-formed, such as
+ /// private/protected inheritance or multiple, ambiguous base class
+ /// subobjects.
+ ///
+ /// \param Base the base class we are searching for.
+ ///
+ /// \returns true if this class is virtually derived from Base,
+ /// false otherwise.
+ bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const;
+
+ /// \brief Determine whether this class is provably not derived from
+ /// the type \p Base.
+ bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const;
+
+ /// \brief Function type used by forallBases() as a callback.
+ ///
+ /// \param Base the definition of the base class
+ ///
+ /// \returns true if this base matched the search criteria
+ typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
+ void *UserData);
+
+ /// \brief Determines if the given callback holds for all the direct
+ /// or indirect base classes of this type.
+ ///
+ /// The class itself does not count as a base class. This routine
+ /// returns false if the class has non-computable base classes.
+ ///
+ /// \param AllowShortCircuit if false, forces the callback to be called
+ /// for every base class, even if a dependent or non-matching base was
+ /// found.
+ bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
+ bool AllowShortCircuit = true) const;
+
+ /// \brief Function type used by lookupInBases() to determine whether a
+ /// specific base class subobject matches the lookup criteria.
+ ///
+ /// \param Specifier the base-class specifier that describes the inheritance
+ /// from the base class we are trying to match.
+ ///
+ /// \param Path the current path, from the most-derived class down to the
+ /// base named by the \p Specifier.
+ ///
+ /// \param UserData a single pointer to user-specified data, provided to
+ /// lookupInBases().
+ ///
+ /// \returns true if this base matched the search criteria, false otherwise.
+ typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
+
+ /// \brief Look for entities within the base classes of this C++ class,
+ /// transitively searching all base class subobjects.
+ ///
+ /// This routine uses the callback function \p BaseMatches to find base
+ /// classes meeting some search criteria, walking all base class subobjects
+ /// and populating the given \p Paths structure with the paths through the
+ /// inheritance hierarchy that resulted in a match. On a successful search,
+ /// the \p Paths structure can be queried to retrieve the matching paths and
+ /// to determine if there were any ambiguities.
+ ///
+ /// \param BaseMatches callback function used to determine whether a given
+ /// base matches the user-defined search criteria.
+ ///
+ /// \param UserData user data pointer that will be provided to \p BaseMatches.
+ ///
+ /// \param Paths used to record the paths from this class to its base class
+ /// subobjects that match the search criteria.
+ ///
+ /// \returns true if there exists any path from this class to a base class
+ /// subobject that matches the search criteria.
+ bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ CXXBasePaths &Paths) const;
+
+ /// \brief Base-class lookup callback that determines whether the given
+ /// base class specifier refers to a specific class declaration.
+ ///
+ /// This callback can be used with \c lookupInBases() to determine whether
+ /// a given derived class has is a base class subobject of a particular type.
+ /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// base class that we are searching for.
+ static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *BaseRecord);
+
+ /// \brief Base-class lookup callback that determines whether the
+ /// given base class specifier refers to a specific class
+ /// declaration and describes virtual derivation.
+ ///
+ /// This callback can be used with \c lookupInBases() to determine
+ /// whether a given derived class has is a virtual base class
+ /// subobject of a particular type. The user data pointer should
+ /// refer to the canonical CXXRecordDecl of the base class that we
+ /// are searching for.
+ static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *BaseRecord);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a tag with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find tag members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindTagMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find members
+ /// of the given name within a C++ class hierarchy. The user data pointer
+ /// is an opaque \c DeclarationName pointer.
+ static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, void *Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
+ /// a member with the given name that can be used in a nested-name-specifier.
+ ///
+ /// This callback can be used with \c lookupInBases() to find membes of
+ /// the given name within a C++ class hierarchy that can occur within
+ /// nested-name-specifiers.
+ static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData);
+
+ /// \brief Retrieve the final overriders for each virtual member
+ /// function in the class hierarchy where this class is the
+ /// most-derived class in the class hierarchy.
+ void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const;
+
+ /// \brief Get the indirect primary bases for this class.
+ void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const;
+
+ /// viewInheritance - Renders and displays an inheritance diagram
+ /// for this C++ class and all of its base classes (transitively) using
+ /// GraphViz.
+ void viewInheritance(ASTContext& Context) const;
+
+ /// MergeAccess - Calculates the access of a decl that is reached
+ /// along a path.
+ static AccessSpecifier MergeAccess(AccessSpecifier PathAccess,
+ AccessSpecifier DeclAccess) {
+ assert(DeclAccess != AS_none);
+ if (DeclAccess == AS_private) return AS_none;
+ return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
+ }
+
+ /// \brief Indicates that the definition of this class is now complete.
+ virtual void completeDefinition();
+
+ /// \brief Indicates that the definition of this class is now complete,
+ /// and provides a final overrider map to help determine
+ ///
+ /// \param FinalOverriders The final overrider map for this class, which can
+ /// be provided as an optimization for abstract-class checking. If NULL,
+ /// final overriders will be computed if they are needed to complete the
+ /// definition.
+ void completeDefinition(CXXFinalOverriderMap *FinalOverriders);
+
+ /// \brief Determine whether this class may end up being abstract, even though
+ /// it is not yet known to be abstract.
+ ///
+ /// \returns true if this class is not known to be abstract but has any
+ /// base classes that are abstract. In this case, \c completeDefinition()
+ /// will need to compute final overriders to determine whether the class is
+ /// actually abstract.
+ bool mayBeAbstract() const;
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstCXXRecord && K <= lastCXXRecord;
+ }
+ static bool classof(const CXXRecordDecl *D) { return true; }
+ static bool classof(const ClassTemplateSpecializationDecl *D) {
+ return true;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// CXXMethodDecl - Represents a static or instance method of a
+/// struct/union/class.
+class CXXMethodDecl : public FunctionDecl {
+protected:
+ CXXMethodDecl(Kind DK, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic, StorageClass SCAsWritten, bool isInline)
+ : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None),
+ SCAsWritten, isInline) {}
+
+public:
+ static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic = false,
+ StorageClass SCAsWritten = SC_None,
+ bool isInline = false);
+
+ bool isStatic() const { return getStorageClass() == SC_Static; }
+ bool isInstance() const { return !isStatic(); }
+
+ bool isVirtual() const {
+ CXXMethodDecl *CD =
+ cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
+
+ if (CD->isVirtualAsWritten())
+ return true;
+
+ return (CD->begin_overridden_methods() != CD->end_overridden_methods());
+ }
+
+ /// \brief Determine whether this is a usual deallocation function
+ /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded
+ /// delete or delete[] operator with a particular signature.
+ bool isUsualDeallocationFunction() const;
+
+ /// \brief Determine whether this is a copy-assignment operator, regardless
+ /// of whether it was declared implicitly or explicitly.
+ bool isCopyAssignmentOperator() const;
+
+ const CXXMethodDecl *getCanonicalDecl() const {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ CXXMethodDecl *getCanonicalDecl() {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+
+ ///
+ void addOverriddenMethod(const CXXMethodDecl *MD);
+
+ typedef const CXXMethodDecl ** method_iterator;
+
+ method_iterator begin_overridden_methods() const;
+ method_iterator end_overridden_methods() const;
+ unsigned size_overridden_methods() const;
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ const CXXRecordDecl *getParent() const {
+ return cast<CXXRecordDecl>(FunctionDecl::getParent());
+ }
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ CXXRecordDecl *getParent() {
+ return const_cast<CXXRecordDecl *>(
+ cast<CXXRecordDecl>(FunctionDecl::getParent()));
+ }
+
+ /// getThisType - Returns the type of 'this' pointer.
+ /// Should only be called for instance methods.
+ QualType getThisType(ASTContext &C) const;
+
+ unsigned getTypeQualifiers() const {
+ return getType()->getAs<FunctionProtoType>()->getTypeQuals();
+ }
+
+ /// \brief Retrieve the ref-qualifier associated with this method.
+ ///
+ /// In the following example, \c f() has an lvalue ref-qualifier, \c g()
+ /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier.
+ /// \code
+ /// struct X {
+ /// void f() &;
+ /// void g() &&;
+ /// void h();
+ /// };
+ RefQualifierKind getRefQualifier() const {
+ return getType()->getAs<FunctionProtoType>()->getRefQualifier();
+ }
+
+ bool hasInlineBody() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXMethodDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstCXXMethod && K <= lastCXXMethod;
+ }
+};
+
+/// CXXCtorInitializer - Represents a C++ base or member
+/// initializer, which is part of a constructor initializer that
+/// initializes one non-static member variable or one base class. For
+/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
+/// initializers:
+///
+/// @code
+/// class A { };
+/// class B : public A {
+/// float f;
+/// public:
+/// B(A& a) : A(a), f(3.14159) { }
+/// };
+/// @endcode
+class CXXCtorInitializer {
+ /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal
+ /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being
+ /// initialized.
+ llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *>
+ Initializee;
+
+ /// \brief The source location for the field name or, for a base initializer
+ /// pack expansion, the location of the ellipsis.
+ SourceLocation MemberOrEllipsisLocation;
+
+ /// \brief The argument used to initialize the base or member, which may
+ /// end up constructing an object (when multiple arguments are involved).
+ Stmt *Init;
+
+ /// LParenLoc - Location of the left paren of the ctor-initializer.
+ SourceLocation LParenLoc;
+
+ /// RParenLoc - Location of the right paren of the ctor-initializer.
+ SourceLocation RParenLoc;
+
+ /// IsVirtual - If the initializer is a base initializer, this keeps track
+ /// of whether the base is virtual or not.
+ bool IsVirtual : 1;
+
+ /// IsWritten - Whether or not the initializer is explicitly written
+ /// in the sources.
+ bool IsWritten : 1;
+
+ /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this
+ /// number keeps track of the textual order of this initializer in the
+ /// original sources, counting from 0; otherwise, if IsWritten is false,
+ /// it stores the number of array index variables stored after this
+ /// object in memory.
+ unsigned SourceOrderOrNumArrayIndices : 14;
+
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+
+public:
+ /// CXXCtorInitializer - Creates a new base-class initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
+ SourceLocation L, Expr *Init, SourceLocation R,
+ SourceLocation EllipsisLoc);
+
+ /// CXXCtorInitializer - Creates a new member initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ explicit
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ /// \brief Creates a new member initializer that optionally contains
+ /// array indices used to describe an elementwise initialization.
+ static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L,
+ Expr *Init, SourceLocation R,
+ VarDecl **Indices, unsigned NumIndices);
+
+ /// isBaseInitializer - Returns true when this initializer is
+ /// initializing a base class.
+ bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>(); }
+
+ /// isMemberInitializer - Returns true when this initializer is
+ /// initializing a non-static data member.
+ bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); }
+
+ bool isAnyMemberInitializer() const {
+ return isMemberInitializer() || isIndirectMemberInitializer();
+ }
+
+ bool isIndirectMemberInitializer() const {
+ return Initializee.is<IndirectFieldDecl*>();
+ }
+
+ /// \brief Determine whether this initializer is a pack expansion.
+ bool isPackExpansion() const {
+ return isBaseInitializer() && MemberOrEllipsisLocation.isValid();
+ }
+
+ // \brief For a pack expansion, returns the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ assert(isPackExpansion() && "Initializer is not a pack expansion");
+ return MemberOrEllipsisLocation;
+ }
+
+ /// If this is a base class initializer, returns the type of the
+ /// base class with location information. Otherwise, returns an NULL
+ /// type location.
+ TypeLoc getBaseClassLoc() const;
+
+ /// If this is a base class initializer, returns the type of the base class.
+ /// Otherwise, returns NULL.
+ const Type *getBaseClass() const;
+
+ /// Returns whether the base is virtual or not.
+ bool isBaseVirtual() const {
+ assert(isBaseInitializer() && "Must call this on base initializer!");
+
+ return IsVirtual;
+ }
+
+ /// \brief Returns the declarator information for a base class initializer.
+ TypeSourceInfo *getBaseClassInfo() const {
+ return Initializee.dyn_cast<TypeSourceInfo *>();
+ }
+
+ /// getMember - If this is a member initializer, returns the
+ /// declaration of the non-static data member being
+ /// initialized. Otherwise, returns NULL.
+ FieldDecl *getMember() const {
+ if (isMemberInitializer())
+ return Initializee.get<FieldDecl*>();
+ else
+ return 0;
+ }
+ FieldDecl *getAnyMember() const {
+ if (isMemberInitializer())
+ return Initializee.get<FieldDecl*>();
+ else if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>()->getAnonField();
+ else
+ return 0;
+ }
+
+ IndirectFieldDecl *getIndirectMember() const {
+ if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>();
+ else
+ return 0;
+ }
+
+ SourceLocation getMemberLocation() const {
+ return MemberOrEllipsisLocation;
+ }
+
+ /// \brief Determine the source location of the initializer.
+ SourceLocation getSourceLocation() const;
+
+ /// \brief Determine the source range covering the entire initializer.
+ SourceRange getSourceRange() const;
+
+ /// isWritten - Returns true if this initializer is explicitly written
+ /// in the source code.
+ bool isWritten() const { return IsWritten; }
+
+ /// \brief Return the source position of the initializer, counting from 0.
+ /// If the initializer was implicit, -1 is returned.
+ int getSourceOrder() const {
+ return IsWritten ? static_cast<int>(SourceOrderOrNumArrayIndices) : -1;
+ }
+
+ /// \brief Set the source order of this initializer. This method can only
+ /// be called once for each initializer; it cannot be called on an
+ /// initializer having a positive number of (implicit) array indices.
+ void setSourceOrder(int pos) {
+ assert(!IsWritten &&
+ "calling twice setSourceOrder() on the same initializer");
+ assert(SourceOrderOrNumArrayIndices == 0 &&
+ "setSourceOrder() used when there are implicit array indices");
+ assert(pos >= 0 &&
+ "setSourceOrder() used to make an initializer implicit");
+ IsWritten = true;
+ SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos);
+ }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// \brief Determine the number of implicit array indices used while
+ /// described an array member initialization.
+ unsigned getNumArrayIndices() const {
+ return IsWritten ? 0 : SourceOrderOrNumArrayIndices;
+ }
+
+ /// \brief Retrieve a particular array index variable used to
+ /// describe an array member initialization.
+ VarDecl *getArrayIndex(unsigned I) {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ return reinterpret_cast<VarDecl **>(this + 1)[I];
+ }
+ const VarDecl *getArrayIndex(unsigned I) const {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ return reinterpret_cast<const VarDecl * const *>(this + 1)[I];
+ }
+ void setArrayIndex(unsigned I, VarDecl *Index) {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
+ }
+
+ Expr *getInit() const { return static_cast<Expr *>(Init); }
+};
+
+/// CXXConstructorDecl - Represents a C++ constructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// explicit X(int); // represented by a CXXConstructorDecl.
+/// };
+/// @endcode
+class CXXConstructorDecl : public CXXMethodDecl {
+ /// IsExplicitSpecified - Whether this constructor declaration has the
+ /// 'explicit' keyword specified.
+ bool IsExplicitSpecified : 1;
+
+ /// ImplicitlyDefined - Whether this constructor was implicitly
+ /// defined by the compiler. When false, the constructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a constructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ /// Support for base and member initializers.
+ /// CtorInitializers - The arguments used to initialize the base
+ /// or member.
+ CXXCtorInitializer **CtorInitializers;
+ unsigned NumCtorInitializers;
+
+ CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline,
+ bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
+ IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
+ CtorInitializers(0), NumCtorInitializers(0) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit,
+ bool isInline, bool isImplicitlyDeclared);
+
+ /// isExplicitSpecified - Whether this constructor declaration has the
+ /// 'explicit' keyword specified.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// isExplicit - Whether this constructor was marked "explicit" or not.
+ bool isExplicit() const {
+ return cast<CXXConstructorDecl>(getFirstDeclaration())
+ ->isExplicitSpecified();
+ }
+
+ /// isImplicitlyDefined - Whether this constructor was implicitly
+ /// defined. If false, then this constructor was defined by the
+ /// user. This operation can only be invoked if the constructor has
+ /// already been defined.
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the "
+ "constructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this constructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the constructor "
+ "has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ /// init_iterator - Iterates through the member/base initializer list.
+ typedef CXXCtorInitializer **init_iterator;
+
+ /// init_const_iterator - Iterates through the memberbase initializer list.
+ typedef CXXCtorInitializer * const * init_const_iterator;
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() { return CtorInitializers; }
+ /// begin() - Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const { return CtorInitializers; }
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return CtorInitializers + NumCtorInitializers;
+ }
+ /// end() - Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return CtorInitializers + NumCtorInitializers;
+ }
+
+ typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
+ typedef std::reverse_iterator<init_const_iterator> init_const_reverse_iterator;
+
+ init_reverse_iterator init_rbegin() {
+ return init_reverse_iterator(init_end());
+ }
+ init_const_reverse_iterator init_rbegin() const {
+ return init_const_reverse_iterator(init_end());
+ }
+
+ init_reverse_iterator init_rend() {
+ return init_reverse_iterator(init_begin());
+ }
+ init_const_reverse_iterator init_rend() const {
+ return init_const_reverse_iterator(init_begin());
+ }
+
+ /// getNumArgs - Determine the number of arguments used to
+ /// initialize the member or base.
+ unsigned getNumCtorInitializers() const {
+ return NumCtorInitializers;
+ }
+
+ void setNumCtorInitializers(unsigned numCtorInitializers) {
+ NumCtorInitializers = numCtorInitializers;
+ }
+
+ void setCtorInitializers(CXXCtorInitializer ** initializers) {
+ CtorInitializers = initializers;
+ }
+ /// isDefaultConstructor - Whether this constructor is a default
+ /// constructor (C++ [class.ctor]p5), which can be used to
+ /// default-initialize a class of this type.
+ bool isDefaultConstructor() const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class. @p TypeQuals will be set to the qualifiers on the
+ /// argument type. For example, @p TypeQuals would be set to @c
+ /// QualType::Const for the following copy constructor:
+ ///
+ /// @code
+ /// class X {
+ /// public:
+ /// X(const X&);
+ /// };
+ /// @endcode
+ bool isCopyConstructor(unsigned &TypeQuals) const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class.
+ bool isCopyConstructor() const {
+ unsigned TypeQuals = 0;
+ return isCopyConstructor(TypeQuals);
+ }
+
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ ///
+ /// \param TypeQuals If this constructor is a move constructor, will be set
+ /// to the type qualifiers on the referent of the first parameter's type.
+ bool isMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this constructor is a move constructor
+ /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ bool isMoveConstructor() const;
+
+ /// \brief Determine whether this is a copy or move constructor.
+ ///
+ /// \param TypeQuals Will be set to the type qualifiers on the reference
+ /// parameter, if in fact this is a copy or move constructor.
+ bool isCopyOrMoveConstructor(unsigned &TypeQuals) const;
+
+ /// \brief Determine whether this a copy or move constructor.
+ bool isCopyOrMoveConstructor() const {
+ unsigned Quals;
+ return isCopyOrMoveConstructor(Quals);
+ }
+
+ /// isConvertingConstructor - Whether this constructor is a
+ /// converting constructor (C++ [class.conv.ctor]), which can be
+ /// used for user-defined conversions.
+ bool isConvertingConstructor(bool AllowExplicit) const;
+
+ /// \brief Determine whether this is a member template specialization that
+ /// would copy the object to itself. Such constructors are never used to copy
+ /// an object.
+ bool isSpecializationCopyingObject() const;
+
+ /// \brief Get the constructor that this inheriting constructor is based on.
+ const CXXConstructorDecl *getInheritedConstructor() const;
+
+ /// \brief Set the constructor that this inheriting constructor is based on.
+ void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXConstructorDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXConstructor; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// CXXDestructorDecl - Represents a C++ destructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// ~X(); // represented by a CXXDestructorDecl.
+/// };
+/// @endcode
+class CXXDestructorDecl : public CXXMethodDecl {
+ /// ImplicitlyDefined - Whether this destructor was implicitly
+ /// defined by the compiler. When false, the destructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a destructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ FunctionDecl *OperatorDelete;
+
+ CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
+ ImplicitlyDefined(false), OperatorDelete(0) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
+ static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo* TInfo,
+ bool isInline,
+ bool isImplicitlyDeclared);
+
+ /// isImplicitlyDefined - Whether this destructor was implicitly
+ /// defined. If false, then this destructor was defined by the
+ /// user. This operation can only be invoked if the destructor has
+ /// already been defined.
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the destructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this destructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the destructor has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
+ const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXDestructorDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXDestructor; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// CXXConversionDecl - Represents a C++ conversion function within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// operator bool();
+/// };
+/// @endcode
+class CXXConversionDecl : public CXXMethodDecl {
+ /// IsExplicitSpecified - Whether this conversion function declaration is
+ /// marked "explicit", meaning that it can only be applied when the user
+ /// explicitly wrote a cast. This is a C++0x feature.
+ bool IsExplicitSpecified : 1;
+
+ CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicitSpecified)
+ : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
+ IsExplicitSpecified(isExplicitSpecified) { }
+
+public:
+ static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
+ static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit);
+
+ /// IsExplicitSpecified - Whether this conversion function declaration is
+ /// marked "explicit", meaning that it can only be applied when the user
+ /// explicitly wrote a cast. This is a C++0x feature.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// isExplicit - Whether this is an explicit conversion operator
+ /// (C++0x only). Explicit conversion operators are only considered
+ /// when the user has explicitly written a cast.
+ bool isExplicit() const {
+ return cast<CXXConversionDecl>(getFirstDeclaration())
+ ->isExplicitSpecified();
+ }
+
+ /// getConversionType - Returns the type that this conversion
+ /// function is converting to.
+ QualType getConversionType() const {
+ return getType()->getAs<FunctionType>()->getResultType();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const CXXConversionDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == CXXConversion; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// LinkageSpecDecl - This represents a linkage specification. For example:
+/// extern "C" void foo();
+///
+class LinkageSpecDecl : public Decl, public DeclContext {
+public:
+ /// LanguageIDs - Used to represent the language in a linkage
+ /// specification. The values are part of the serialization abi for
+ /// ASTs and cannot be changed without altering that abi. To help
+ /// ensure a stable abi for this, we choose the DW_LANG_ encodings
+ /// from the dwarf standard.
+ enum LanguageIDs {
+ lang_c = /* DW_LANG_C */ 0x0002,
+ lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004
+ };
+private:
+ /// Language - The language for this linkage specification.
+ LanguageIDs Language;
+
+ /// HadBraces - Whether this linkage specification had curly braces or not.
+ bool HadBraces : 1;
+
+ LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
+ bool Braces)
+ : Decl(LinkageSpec, DC, L),
+ DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
+
+public:
+ static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, LanguageIDs Lang,
+ bool Braces);
+
+ /// \brief Return the language specified by this linkage specification.
+ LanguageIDs getLanguage() const { return Language; }
+
+ /// \brief Set the language specified by this linkage specification.
+ void setLanguage(LanguageIDs L) { Language = L; }
+
+ /// \brief Determines whether this linkage specification had braces in
+ /// its syntactic form.
+ bool hasBraces() const { return HadBraces; }
+
+ /// \brief Set whether this linkage specification has braces in its
+ /// syntactic form.
+ void setHasBraces(bool B) { HadBraces = B; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const LinkageSpecDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == LinkageSpec; }
+ static DeclContext *castToDeclContext(const LinkageSpecDecl *D) {
+ return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D));
+ }
+ static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// UsingDirectiveDecl - Represents C++ using-directive. For example:
+///
+/// using namespace std;
+///
+// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide
+// artificial name, for all using-directives in order to store
+// them in DeclContext effectively.
+class UsingDirectiveDecl : public NamedDecl {
+ /// \brief The location of the "using" keyword.
+ SourceLocation UsingLoc;
+
+ /// SourceLocation - Location of 'namespace' token.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// NominatedNamespace - Namespace nominated by using-directive.
+ NamedDecl *NominatedNamespace;
+
+ /// Enclosing context containing both using-directive and nominated
+ /// namespace.
+ DeclContext *CommonAncestor;
+
+ /// getUsingDirectiveName - Returns special DeclarationName used by
+ /// using-directives. This is only used by DeclContext for storing
+ /// UsingDirectiveDecls in its lookup structure.
+ static DeclarationName getName() {
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor)
+ : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
+ NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), NominatedNamespace(Nominated),
+ CommonAncestor(CommonAncestor) {
+ }
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
+ const NamedDecl *getNominatedNamespaceAsWritten() const {
+ return NominatedNamespace;
+ }
+
+ /// getNominatedNamespace - Returns namespace nominated by using-directive.
+ NamespaceDecl *getNominatedNamespace();
+
+ const NamespaceDecl *getNominatedNamespace() const {
+ return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
+ }
+
+ /// \brief Returns the common ancestor context of this using-directive and
+ /// its nominated namespace.
+ DeclContext *getCommonAncestor() { return CommonAncestor; }
+ const DeclContext *getCommonAncestor() const { return CommonAncestor; }
+
+ /// \brief Return the location of the "using" keyword.
+ SourceLocation getUsingLoc() const { return UsingLoc; }
+
+ // FIXME: Could omit 'Key' in name.
+ /// getNamespaceKeyLocation - Returns location of namespace keyword.
+ SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
+
+ /// getIdentLocation - Returns location of identifier.
+ SourceLocation getIdentLocation() const { return getLocation(); }
+
+ static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceLocation NamespaceLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLoc, getLocation());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingDirectiveDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == UsingDirective; }
+
+ // Friend for getUsingDirectiveName.
+ friend class DeclContext;
+
+ friend class ASTDeclReader;
+};
+
+/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
+///
+/// @code
+/// namespace Foo = Bar;
+/// @endcode
+class NamespaceAliasDecl : public NamedDecl {
+ /// \brief The location of the "namespace" keyword.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc.
+ SourceLocation IdentLoc;
+
+ /// Namespace - The Decl that this alias points to. Can either be a
+ /// NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *Namespace;
+
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc, NamedDecl *Namespace)
+ : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
+ NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
+
+ friend class ASTDeclReader;
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifiers the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Set the source range of the nested-name-specifier that qualifies
+ /// the namespace name.
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Set the nested-name-specifier that qualifies the name of the
+ /// namespace.
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// \brief Retrieve the namespace declaration aliased by this directive.
+ NamespaceDecl *getNamespace() {
+ if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
+ return AD->getNamespace();
+
+ return cast<NamespaceDecl>(Namespace);
+ }
+
+ const NamespaceDecl *getNamespace() const {
+ return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
+ }
+
+ /// Returns the location of the alias name, i.e. 'foo' in
+ /// "namespace foo = ns::bar;".
+ SourceLocation getAliasLoc() const { return getLocation(); }
+
+ /// Returns the location of the 'namespace' keyword.
+ SourceLocation getNamespaceLoc() const { return NamespaceLoc; }
+
+ /// Returns the location of the identifier in the named namespace.
+ SourceLocation getTargetNameLoc() const { return IdentLoc; }
+
+ /// \brief Retrieve the namespace that this alias refers to, which
+ /// may either be a NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *getAliasedNamespace() const { return Namespace; }
+
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace);
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(NamespaceLoc, IdentLoc);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const NamespaceAliasDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == NamespaceAlias; }
+};
+
+/// UsingShadowDecl - Represents a shadow declaration introduced into
+/// a scope by a (resolved) using declaration. For example,
+///
+/// namespace A {
+/// void foo();
+/// }
+/// namespace B {
+/// using A::foo(); // <- a UsingDecl
+/// // Also creates a UsingShadowDecl for A::foo in B
+/// }
+///
+class UsingShadowDecl : public NamedDecl {
+ /// The referenced declaration.
+ NamedDecl *Underlying;
+
+ /// \brief The using declaration which introduced this decl or the next using
+ /// shadow declaration contained in the aforementioned using declaration.
+ NamedDecl *UsingOrNextShadow;
+ friend class UsingDecl;
+
+ UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target)
+ : NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
+ Underlying(Target),
+ UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
+ if (Target) {
+ setDeclName(Target->getDeclName());
+ IdentifierNamespace = Target->getIdentifierNamespace();
+ }
+ setImplicit();
+ }
+
+public:
+ static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target) {
+ return new (C) UsingShadowDecl(DC, Loc, Using, Target);
+ }
+
+ /// \brief Gets the underlying declaration which has been brought into the
+ /// local scope.
+ NamedDecl *getTargetDecl() const { return Underlying; }
+
+ /// \brief Sets the underlying declaration which has been brought into the
+ /// local scope.
+ void setTargetDecl(NamedDecl* ND) {
+ assert(ND && "Target decl is null!");
+ Underlying = ND;
+ IdentifierNamespace = ND->getIdentifierNamespace();
+ }
+
+ /// \brief Gets the using declaration to which this declaration is tied.
+ UsingDecl *getUsingDecl() const;
+
+ /// \brief The next using shadow declaration contained in the shadow decl
+ /// chain of the using declaration which introduced this decl.
+ UsingShadowDecl *getNextUsingShadowDecl() const {
+ return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingShadowDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// UsingDecl - Represents a C++ using-declaration. For example:
+/// using someNameSpace::someIdentifier;
+class UsingDecl : public NamedDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange NestedNameRange;
+
+ /// \brief The source location of the "using" location itself.
+ SourceLocation UsingLocation;
+
+ /// \brief Target nested name specifier.
+ NestedNameSpecifier* TargetNestedName;
+
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
+ /// \brief The first shadow declaration of the shadow decl chain associated
+ /// with this using declaration.
+ UsingShadowDecl *FirstUsingShadow;
+
+ // \brief Has 'typename' keyword.
+ bool IsTypeName;
+
+ UsingDecl(DeclContext *DC, SourceRange NNR,
+ SourceLocation UL, NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
+ : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
+ NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
+ }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getNestedNameRange() const { return NestedNameRange; }
+
+ /// \brief Set the source range of the nested-name-specifier.
+ void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
+
+ // FIXME: Naming is inconsistent with other get*Loc functions.
+ /// \brief Returns the source location of the "using" keyword.
+ SourceLocation getUsingLocation() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLocation(SourceLocation L) { UsingLocation = L; }
+
+ /// \brief Get the target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameDecl() const {
+ return TargetNestedName;
+ }
+
+ /// \brief Set the target nested name declaration.
+ void setTargetNestedNameDecl(NestedNameSpecifier *NNS) {
+ TargetNestedName = NNS;
+ }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ /// \brief Return true if the using declaration has 'typename'.
+ bool isTypeName() const { return IsTypeName; }
+
+ /// \brief Sets whether the using declaration has 'typename'.
+ void setTypeName(bool TN) { IsTypeName = TN; }
+
+ /// \brief Iterates through the using shadow declarations assosiated with
+ /// this using declaration.
+ class shadow_iterator {
+ /// \brief The current using shadow declaration.
+ UsingShadowDecl *Current;
+
+ public:
+ typedef UsingShadowDecl* value_type;
+ typedef UsingShadowDecl* reference;
+ typedef UsingShadowDecl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ shadow_iterator() : Current(0) { }
+ explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ shadow_iterator& operator++() {
+ Current = Current->getNextUsingShadowDecl();
+ return *this;
+ }
+
+ shadow_iterator operator++(int) {
+ shadow_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(shadow_iterator x, shadow_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(shadow_iterator x, shadow_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ shadow_iterator shadow_begin() const {
+ return shadow_iterator(FirstUsingShadow);
+ }
+ shadow_iterator shadow_end() const { return shadow_iterator(); }
+
+ /// \brief Return the number of shadowed declarations associated with this
+ /// using declaration.
+ unsigned shadow_size() const {
+ return std::distance(shadow_begin(), shadow_end());
+ }
+
+ void addShadowDecl(UsingShadowDecl *S);
+ void removeShadowDecl(UsingShadowDecl *S);
+
+ static UsingDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceRange NNR, SourceLocation UsingL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UsingDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Using; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// UnresolvedUsingValueDecl - Represents a dependent using
+/// declaration which was not marked with 'typename'. Unlike
+/// non-dependent using declarations, these *only* bring through
+/// non-types; otherwise they would break two-phase lookup.
+///
+/// template <class T> class A : public Base<T> {
+/// using Base<T>::foo;
+/// };
+class UnresolvedUsingValueDecl : public ValueDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
+ UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
+ SourceLocation UsingLoc, SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ const DeclarationNameInfo &NameInfo)
+ : ValueDecl(UnresolvedUsingValue, DC,
+ NameInfo.getLoc(), NameInfo.getName(), Ty),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
+ { }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+ /// \brief Set the source range coverting the nested-name-specifier preceding
+ /// the namespace name.
+ void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
+
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() const {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Set the nested name declaration.
+ void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
+ TargetNestedNameSpecifier = NNS;
+ }
+
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ static UnresolvedUsingValueDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ const DeclarationNameInfo &NameInfo);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// UnresolvedUsingTypenameDecl - Represents a dependent using
+/// declaration which was marked with 'typename'.
+///
+/// template <class T> class A : public Base<T> {
+/// using typename Base<T>::foo;
+/// };
+///
+/// The type associated with a unresolved using typename decl is
+/// currently always a typename type.
+class UnresolvedUsingTypenameDecl : public TypeDecl {
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange TargetNestedNameRange;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ /// \brief The source location of the 'typename' keyword
+ SourceLocation TypenameLocation;
+
+ NestedNameSpecifier *TargetNestedNameSpecifier;
+
+ UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+ : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
+ { }
+
+ friend class ASTDeclReader;
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ return TargetNestedNameSpecifier;
+ }
+
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Returns the source location of the 'typename' keyword.
+ SourceLocation getTypenameLoc() const { return TypenameLocation; }
+
+ static UnresolvedUsingTypenameDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getLocation());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
+};
+
+/// StaticAssertDecl - Represents a C++0x static_assert declaration.
+class StaticAssertDecl : public Decl {
+ Expr *AssertExpr;
+ StringLiteral *Message;
+
+ StaticAssertDecl(DeclContext *DC, SourceLocation L,
+ Expr *assertexpr, StringLiteral *message)
+ : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
+
+public:
+ static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, Expr *AssertExpr,
+ StringLiteral *Message);
+
+ Expr *getAssertExpr() { return AssertExpr; }
+ const Expr *getAssertExpr() const { return AssertExpr; }
+
+ StringLiteral *getMessage() { return Message; }
+ const StringLiteral *getMessage() const { return Message; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(StaticAssertDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == StaticAssert; }
+
+ friend class ASTDeclReader;
+};
+
+/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
+/// into a diagnostic with <<.
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ AccessSpecifier AS);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
new file mode 100644
index 0000000..97da6ca
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
@@ -0,0 +1,223 @@
+//===-- DeclContextInternals.h - DeclContext Representation -----*- 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 data structures used in the implementation
+// of DeclContext.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
+#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+
+namespace clang {
+
+class DependentDiagnostic;
+
+/// StoredDeclsList - This is an array of decls optimized a common case of only
+/// containing one entry.
+struct StoredDeclsList {
+
+ /// DeclsTy - When in vector form, this is what the Data pointer points to.
+ typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
+
+ /// \brief The stored data, which will be either a pointer to a NamedDecl,
+ /// or a pointer to a vector.
+ llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
+
+public:
+ StoredDeclsList() {}
+
+ StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
+ }
+
+ ~StoredDeclsList() {
+ // If this is a vector-form, free the vector.
+ if (DeclsTy *Vector = getAsVector())
+ delete Vector;
+ }
+
+ StoredDeclsList &operator=(const StoredDeclsList &RHS) {
+ if (DeclsTy *Vector = getAsVector())
+ delete Vector;
+ Data = RHS.Data;
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
+ return *this;
+ }
+
+ bool isNull() const { return Data.isNull(); }
+
+ NamedDecl *getAsDecl() const {
+ return Data.dyn_cast<NamedDecl *>();
+ }
+
+ DeclsTy *getAsVector() const {
+ return Data.dyn_cast<DeclsTy *>();
+ }
+
+ void setOnlyValue(NamedDecl *ND) {
+ assert(!getAsVector() && "Not inline");
+ Data = ND;
+ // Make sure that Data is a plain NamedDecl* so we can use its address
+ // at getLookupResult.
+ assert(*(NamedDecl **)&Data == ND &&
+ "PointerUnion mangles the NamedDecl pointer!");
+ }
+
+ void remove(NamedDecl *D) {
+ assert(!isNull() && "removing from empty list");
+ if (NamedDecl *Singleton = getAsDecl()) {
+ assert(Singleton == D && "list is different singleton");
+ (void)Singleton;
+ Data = (NamedDecl *)0;
+ return;
+ }
+
+ DeclsTy &Vec = *getAsVector();
+ DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
+ assert(I != Vec.end() && "list does not contain decl");
+ Vec.erase(I);
+
+ assert(std::find(Vec.begin(), Vec.end(), D)
+ == Vec.end() && "list still contains decl");
+ }
+
+ /// getLookupResult - Return an array of all the decls that this list
+ /// represents.
+ DeclContext::lookup_result getLookupResult() {
+ if (isNull())
+ return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
+ DeclContext::lookup_iterator(0));
+
+ // If we have a single NamedDecl, return it.
+ if (getAsDecl()) {
+ assert(!isNull() && "Empty list isn't allowed");
+
+ // Data is a raw pointer to a NamedDecl*, return it.
+ void *Ptr = &Data;
+ return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
+ }
+
+ assert(getAsVector() && "Must have a vector at this point");
+ DeclsTy &Vector = *getAsVector();
+
+ // Otherwise, we have a range result.
+ return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
+ }
+
+ /// HandleRedeclaration - If this is a redeclaration of an existing decl,
+ /// replace the old one with D and return true. Otherwise return false.
+ bool HandleRedeclaration(NamedDecl *D) {
+ // Most decls only have one entry in their list, special case it.
+ if (NamedDecl *OldD = getAsDecl()) {
+ if (!D->declarationReplaces(OldD))
+ return false;
+ setOnlyValue(D);
+ return true;
+ }
+
+ // Determine if this declaration is actually a redeclaration.
+ DeclsTy &Vec = *getAsVector();
+ for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
+ OD != ODEnd; ++OD) {
+ NamedDecl *OldD = *OD;
+ if (D->declarationReplaces(OldD)) {
+ *OD = D;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// AddSubsequentDecl - This is called on the second and later decl when it is
+ /// not a redeclaration to merge it into the appropriate place in our list.
+ ///
+ void AddSubsequentDecl(NamedDecl *D) {
+ // If this is the second decl added to the list, convert this to vector
+ // form.
+ if (NamedDecl *OldD = getAsDecl()) {
+ DeclsTy *VT = new DeclsTy();
+ VT->push_back(OldD);
+ Data = VT;
+ }
+
+ DeclsTy &Vec = *getAsVector();
+
+ // Using directives end up in a special entry which contains only
+ // other using directives, so all this logic is wasted for them.
+ // But avoiding the logic wastes time in the far-more-common case
+ // that we're *not* adding a new using directive.
+
+ // Tag declarations always go at the end of the list so that an
+ // iterator which points at the first tag will start a span of
+ // decls that only contains tags.
+ if (D->hasTagIdentifierNamespace())
+ Vec.push_back(D);
+
+ // Resolved using declarations go at the front of the list so that
+ // they won't show up in other lookup results. Unresolved using
+ // declarations (which are always in IDNS_Using | IDNS_Ordinary)
+ // follow that so that the using declarations will be contiguous.
+ else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
+ DeclsTy::iterator I = Vec.begin();
+ if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
+ while (I != Vec.end() &&
+ (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
+ ++I;
+ }
+ Vec.insert(I, D);
+
+ // All other declarations go at the end of the list, but before any
+ // tag declarations. But we can be clever about tag declarations
+ // because there can only ever be one in a scope.
+ } else if (Vec.back()->hasTagIdentifierNamespace()) {
+ NamedDecl *TagD = Vec.back();
+ Vec.back() = D;
+ Vec.push_back(TagD);
+ } else
+ Vec.push_back(D);
+ }
+};
+
+class StoredDeclsMap
+ : public llvm::DenseMap<DeclarationName, StoredDeclsList> {
+
+public:
+ static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
+
+private:
+ friend class ASTContext; // walks the chain deleting these
+ friend class DeclContext;
+ llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
+};
+
+class DependentStoredDeclsMap : public StoredDeclsMap {
+public:
+ DependentStoredDeclsMap() : FirstDiagnostic(0) {}
+
+private:
+ friend class DependentDiagnostic;
+ friend class DeclContext; // iterates over diagnostics
+
+ DependentDiagnostic *FirstDiagnostic;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
new file mode 100644
index 0000000..20d6da1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
@@ -0,0 +1,185 @@
+//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the section of the AST representing C++ friend
+// declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLFRIEND_H
+#define LLVM_CLANG_AST_DECLFRIEND_H
+
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+
+/// FriendDecl - Represents the declaration of a friend entity,
+/// which can be a function, a type, or a templated function or type.
+// For example:
+///
+/// @code
+/// template <typename T> class A {
+/// friend int foo(T);
+/// friend class B;
+/// friend T; // only in C++0x
+/// template <typename U> friend class C;
+/// template <typename U> friend A& operator+=(A&, const U&) { ... }
+/// };
+/// @endcode
+///
+/// The semantic context of a friend decl is its declaring class.
+class FriendDecl : public Decl {
+public:
+ typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
+
+private:
+ // The declaration that's a friend of this class.
+ FriendUnion Friend;
+
+ // A pointer to the next friend in the sequence.
+ LazyDeclPtr NextFriend;
+
+ // Location of the 'friend' specifier.
+ SourceLocation FriendLoc;
+
+ /// True if this 'friend' declaration is unsupported. Eventually we
+ /// will support every possible friend declaration, but for now we
+ /// silently ignore some and set this flag to authorize all access.
+ bool UnsupportedFriend;
+
+ friend class CXXRecordDecl::friend_iterator;
+ friend class CXXRecordDecl;
+
+ FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
+ SourceLocation FriendL)
+ : Decl(Decl::Friend, DC, L),
+ Friend(Friend),
+ NextFriend(),
+ FriendLoc(FriendL),
+ UnsupportedFriend(false) {
+ }
+
+ explicit FriendDecl(EmptyShell Empty)
+ : Decl(Decl::Friend, Empty), NextFriend() { }
+
+ FriendDecl *getNextFriend() {
+ return cast_or_null<FriendDecl>(
+ NextFriend.get(getASTContext().getExternalSource()));
+ }
+
+public:
+ static FriendDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, FriendUnion Friend_,
+ SourceLocation FriendL);
+ static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
+
+ /// If this friend declaration names an (untemplated but possibly
+ /// dependent) type, return the type; otherwise return null. This
+ /// is used for elaborated-type-specifiers and, in C++0x, for
+ /// arbitrary friend type declarations.
+ TypeSourceInfo *getFriendType() const {
+ return Friend.dyn_cast<TypeSourceInfo*>();
+ }
+
+ /// If this friend declaration doesn't name a type, return the inner
+ /// declaration.
+ NamedDecl *getFriendDecl() const {
+ return Friend.dyn_cast<NamedDecl*>();
+ }
+
+ /// Retrieves the location of the 'friend' keyword.
+ SourceLocation getFriendLoc() const {
+ return FriendLoc;
+ }
+
+ /// Determines if this friend kind is unsupported.
+ bool isUnsupportedFriend() const {
+ return UnsupportedFriend;
+ }
+ void setUnsupportedFriend(bool Unsupported) {
+ UnsupportedFriend = Unsupported;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const FriendDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == Decl::Friend; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// An iterator over the friend declarations of a class.
+class CXXRecordDecl::friend_iterator {
+ FriendDecl *Ptr;
+
+ friend class CXXRecordDecl;
+ explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
+public:
+ friend_iterator() {}
+
+ typedef FriendDecl *value_type;
+ typedef FriendDecl *reference;
+ typedef FriendDecl *pointer;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ reference operator*() const { return Ptr; }
+
+ friend_iterator &operator++() {
+ assert(Ptr && "attempt to increment past end of friend list");
+ Ptr = Ptr->getNextFriend();
+ return *this;
+ }
+
+ friend_iterator operator++(int) {
+ friend_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ bool operator==(const friend_iterator &Other) const {
+ return Ptr == Other.Ptr;
+ }
+
+ bool operator!=(const friend_iterator &Other) const {
+ return Ptr != Other.Ptr;
+ }
+
+ friend_iterator &operator+=(difference_type N) {
+ assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
+ while (N--)
+ ++*this;
+ return *this;
+ }
+
+ friend_iterator operator+(difference_type N) const {
+ friend_iterator tmp = *this;
+ tmp += N;
+ return tmp;
+ }
+};
+
+inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
+ return friend_iterator(data().FirstFriend);
+}
+
+inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
+ return friend_iterator(0);
+}
+
+inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
+ assert(FD->NextFriend == 0 && "friend already has next friend?");
+ FD->NextFriend = data().FirstFriend;
+ data().FirstFriend = FD;
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
new file mode 100644
index 0000000..cb9e168
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -0,0 +1,151 @@
+//===--- DeclGroup.h - Classes for representing groups of Decls -*- 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 DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLGROUP_H
+#define LLVM_CLANG_AST_DECLGROUP_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclGroup;
+class DeclGroupIterator;
+
+class DeclGroup {
+ // FIXME: Include a TypeSpecifier object.
+ unsigned NumDecls;
+
+private:
+ DeclGroup() : NumDecls(0) {}
+ DeclGroup(unsigned numdecls, Decl** decls);
+
+public:
+ static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
+
+ unsigned size() const { return NumDecls; }
+
+ Decl*& operator[](unsigned i) {
+ assert (i < NumDecls && "Out-of-bounds access.");
+ return *((Decl**) (this+1));
+ }
+
+ Decl* const& operator[](unsigned i) const {
+ assert (i < NumDecls && "Out-of-bounds access.");
+ return *((Decl* const*) (this+1));
+ }
+};
+
+class DeclGroupRef {
+ // Note this is not a PointerIntPair because we need the address of the
+ // non-group case to be valid as a Decl** for iteration.
+ enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
+ Decl* D;
+
+ Kind getKind() const {
+ return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
+ }
+
+public:
+ DeclGroupRef() : D(0) {}
+
+ explicit DeclGroupRef(Decl* d) : D(d) {}
+ explicit DeclGroupRef(DeclGroup* dg)
+ : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
+
+ static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ if (NumDecls == 0)
+ return DeclGroupRef();
+ if (NumDecls == 1)
+ return DeclGroupRef(Decls[0]);
+ return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
+ }
+
+ typedef Decl** iterator;
+ typedef Decl* const * const_iterator;
+
+ bool isNull() const { return D == 0; }
+ bool isSingleDecl() const { return getKind() == SingleDeclKind; }
+ bool isDeclGroup() const { return getKind() == DeclGroupKind; }
+
+ Decl *getSingleDecl() {
+ assert(isSingleDecl() && "Isn't a declgroup");
+ return D;
+ }
+ const Decl *getSingleDecl() const {
+ return const_cast<DeclGroupRef*>(this)->getSingleDecl();
+ }
+
+ DeclGroup &getDeclGroup() {
+ assert(isDeclGroup() && "Isn't a declgroup");
+ return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
+ }
+ const DeclGroup &getDeclGroup() const {
+ return const_cast<DeclGroupRef*>(this)->getDeclGroup();
+ }
+
+ iterator begin() {
+ if (isSingleDecl())
+ return D ? &D : 0;
+ return &getDeclGroup()[0];
+ }
+
+ iterator end() {
+ if (isSingleDecl())
+ return D ? &D+1 : 0;
+ DeclGroup &G = getDeclGroup();
+ return &G[0] + G.size();
+ }
+
+ const_iterator begin() const {
+ if (isSingleDecl())
+ return D ? &D : 0;
+ return &getDeclGroup()[0];
+ }
+
+ const_iterator end() const {
+ if (isSingleDecl())
+ return D ? &D+1 : 0;
+ const DeclGroup &G = getDeclGroup();
+ return &G[0] + G.size();
+ }
+
+ void *getAsOpaquePtr() const { return D; }
+ static DeclGroupRef getFromOpaquePtr(void *Ptr) {
+ DeclGroupRef X;
+ X.D = static_cast<Decl*>(Ptr);
+ return X;
+ }
+};
+
+} // end clang namespace
+
+namespace llvm {
+ // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
+ template <typename T>
+ class PointerLikeTypeTraits;
+ template <>
+ class PointerLikeTypeTraits<clang::DeclGroupRef> {
+ public:
+ static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
+ return clang::DeclGroupRef::getFromOpaquePtr(P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+}
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
new file mode 100644
index 0000000..b3ca474
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
@@ -0,0 +1,1594 @@
+//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeclObjC interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLOBJC_H
+#define LLVM_CLANG_AST_DECLOBJC_H
+
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+class Expr;
+class Stmt;
+class FunctionDecl;
+class RecordDecl;
+class ObjCIvarDecl;
+class ObjCMethodDecl;
+class ObjCProtocolDecl;
+class ObjCCategoryDecl;
+class ObjCPropertyDecl;
+class ObjCPropertyImplDecl;
+class CXXCtorInitializer;
+
+class ObjCListBase {
+ void operator=(const ObjCListBase &); // DO NOT IMPLEMENT
+ ObjCListBase(const ObjCListBase&); // DO NOT IMPLEMENT
+protected:
+ /// List is an array of pointers to objects that are not owned by this object.
+ void **List;
+ unsigned NumElts;
+
+public:
+ ObjCListBase() : List(0), NumElts(0) {}
+ unsigned size() const { return NumElts; }
+ bool empty() const { return NumElts == 0; }
+
+protected:
+ void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
+};
+
+
+/// ObjCList - This is a simple template class used to hold various lists of
+/// decls etc, which is heavily used by the ObjC front-end. This only use case
+/// this supports is setting the list all at once and then reading elements out
+/// of it.
+template <typename T>
+class ObjCList : public ObjCListBase {
+public:
+ void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
+ ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
+ }
+
+ typedef T* const * iterator;
+ iterator begin() const { return (iterator)List; }
+ iterator end() const { return (iterator)List+NumElts; }
+
+ T* operator[](unsigned Idx) const {
+ assert(Idx < NumElts && "Invalid access");
+ return (T*)List[Idx];
+ }
+};
+
+/// \brief A list of Objective-C protocols, along with the source
+/// locations at which they were referenced.
+class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
+ SourceLocation *Locations;
+
+ using ObjCList<ObjCProtocolDecl>::set;
+
+public:
+ ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { }
+
+ typedef const SourceLocation *loc_iterator;
+ loc_iterator loc_begin() const { return Locations; }
+ loc_iterator loc_end() const { return Locations + size(); }
+
+ void set(ObjCProtocolDecl* const* InList, unsigned Elts,
+ const SourceLocation *Locs, ASTContext &Ctx);
+};
+
+
+/// ObjCMethodDecl - Represents an instance or class method declaration.
+/// ObjC methods can be declared within 4 contexts: class interfaces,
+/// categories, protocols, and class implementations. While C++ member
+/// functions leverage C syntax, Objective-C method syntax is modeled after
+/// Smalltalk (using colons to specify argument types/expressions).
+/// Here are some brief examples:
+///
+/// Setter/getter instance methods:
+/// - (void)setMenu:(NSMenu *)menu;
+/// - (NSMenu *)menu;
+///
+/// Instance method that takes 2 NSView arguments:
+/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
+///
+/// Getter class method:
+/// + (NSMenu *)defaultMenu;
+///
+/// A selector represents a unique name for a method. The selector names for
+/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
+///
+class ObjCMethodDecl : public NamedDecl, public DeclContext {
+public:
+ enum ImplementationControl { None, Required, Optional };
+private:
+ /// Bitfields must be first fields in this class so they pack with those
+ /// declared in class Decl.
+ /// instance (true) or class (false) method.
+ bool IsInstance : 1;
+ bool IsVariadic : 1;
+
+ // Synthesized declaration method for a property setter/getter
+ bool IsSynthesized : 1;
+
+ // Method has a definition.
+ bool IsDefined : 1;
+
+ // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
+ /// @required/@optional
+ unsigned DeclImplementation : 2;
+
+ // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
+ /// in, inout, etc.
+ unsigned objcDeclQualifier : 6;
+
+ // Number of args separated by ':' in a method declaration.
+ unsigned NumSelectorArgs;
+
+ // Result type of this method.
+ QualType MethodDeclType;
+
+ // Type source information for the result type.
+ TypeSourceInfo *ResultTInfo;
+
+ /// ParamInfo - List of pointers to VarDecls for the formal parameters of this
+ /// Method.
+ ObjCList<ParmVarDecl> ParamInfo;
+
+ /// List of attributes for this method declaration.
+ SourceLocation EndLoc; // the location of the ';' or '}'.
+
+ // The following are only used for method definitions, null otherwise.
+ // FIXME: space savings opportunity, consider a sub-class.
+ Stmt *Body;
+
+ /// SelfDecl - Decl for the implicit self parameter. This is lazily
+ /// constructed by createImplicitParams.
+ ImplicitParamDecl *SelfDecl;
+ /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
+ /// constructed by createImplicitParams.
+ ImplicitParamDecl *CmdDecl;
+
+ ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T,
+ TypeSourceInfo *ResultTInfo,
+ DeclContext *contextDecl,
+ bool isInstance = true,
+ bool isVariadic = false,
+ bool isSynthesized = false,
+ bool isDefined = false,
+ ImplementationControl impControl = None,
+ unsigned numSelectorArgs = 0)
+ : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
+ DeclContext(ObjCMethod),
+ IsInstance(isInstance), IsVariadic(isVariadic),
+ IsSynthesized(isSynthesized),
+ IsDefined(isDefined),
+ DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
+ NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
+ ResultTInfo(ResultTInfo),
+ EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
+
+ /// \brief A definition will return its interface declaration.
+ /// An interface declaration will return its definition.
+ /// Otherwise it will return itself.
+ virtual ObjCMethodDecl *getNextRedeclaration();
+
+public:
+ static ObjCMethodDecl *Create(ASTContext &C,
+ SourceLocation beginLoc,
+ SourceLocation endLoc, Selector SelInfo,
+ QualType T,
+ TypeSourceInfo *ResultTInfo,
+ DeclContext *contextDecl,
+ bool isInstance = true,
+ bool isVariadic = false,
+ bool isSynthesized = false,
+ bool isDefined = false,
+ ImplementationControl impControl = None,
+ unsigned numSelectorArgs = 0);
+
+ virtual ObjCMethodDecl *getCanonicalDecl();
+ const ObjCMethodDecl *getCanonicalDecl() const {
+ return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
+ }
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return ObjCDeclQualifier(objcDeclQualifier);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
+
+ unsigned getNumSelectorArgs() const { return NumSelectorArgs; }
+ void setNumSelectorArgs(unsigned numSelectorArgs) {
+ NumSelectorArgs = numSelectorArgs;
+ }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); }
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setEndLoc(SourceLocation Loc) { EndLoc = Loc; }
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), EndLoc);
+ }
+
+ ObjCInterfaceDecl *getClassInterface();
+ const ObjCInterfaceDecl *getClassInterface() const {
+ return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
+ }
+
+ Selector getSelector() const { return getDeclName().getObjCSelector(); }
+
+ QualType getResultType() const { return MethodDeclType; }
+ void setResultType(QualType T) { MethodDeclType = T; }
+
+ /// \brief Determine the type of an expression that sends a message to this
+ /// function.
+ QualType getSendResultType() const {
+ return getResultType().getNonLValueExprType(getASTContext());
+ }
+
+ TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; }
+ void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return ParamInfo.size(); }
+ typedef ObjCList<ParmVarDecl>::iterator param_iterator;
+ param_iterator param_begin() const { return ParamInfo.begin(); }
+ param_iterator param_end() const { return ParamInfo.end(); }
+ // This method returns and of the parameters which are part of the selector
+ // name mangling requirements.
+ param_iterator sel_param_end() const {
+ return ParamInfo.begin() + NumSelectorArgs;
+ }
+
+ void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num,
+ unsigned numSelectorArgs) {
+ ParamInfo.set(List, Num, C);
+ NumSelectorArgs = numSelectorArgs;
+ }
+
+ // Iterator access to parameter types.
+ typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
+ typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator;
+
+ arg_type_iterator arg_type_begin() const {
+ return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
+ }
+ arg_type_iterator arg_type_end() const {
+ return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
+ }
+
+ /// createImplicitParams - Used to lazily create the self and cmd
+ /// implict parameters. This must be called prior to using getSelfDecl()
+ /// or getCmdDecl(). The call is ignored if the implicit paramters
+ /// have already been created.
+ void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
+
+ ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
+ void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
+ ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
+ void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
+
+ bool isInstanceMethod() const { return IsInstance; }
+ void setInstanceMethod(bool isInst) { IsInstance = isInst; }
+ bool isVariadic() const { return IsVariadic; }
+ void setVariadic(bool isVar) { IsVariadic = isVar; }
+
+ bool isClassMethod() const { return !IsInstance; }
+
+ bool isSynthesized() const { return IsSynthesized; }
+ void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
+
+ bool isDefined() const { return IsDefined; }
+ void setDefined(bool isDefined) { IsDefined = isDefined; }
+
+ // Related to protocols declared in @protocol
+ void setDeclImplementation(ImplementationControl ic) {
+ DeclImplementation = ic;
+ }
+ ImplementationControl getImplementationControl() const {
+ return ImplementationControl(DeclImplementation);
+ }
+
+ virtual Stmt *getBody() const {
+ return (Stmt*) Body;
+ }
+ CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; }
+ void setBody(Stmt *B) { Body = B; }
+
+ /// \brief Returns whether this specific method is a definition.
+ bool isThisDeclarationADefinition() const { return Body; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCMethodDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCMethod; }
+ static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
+ }
+ static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCContainerDecl - Represents a container for method declarations.
+/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
+/// ObjCProtocolDecl, and ObjCImplDecl.
+///
+class ObjCContainerDecl : public NamedDecl, public DeclContext {
+ // These two locations in the range mark the end of the method container.
+ // The first points to the '@' token, and the second to the 'end' token.
+ SourceRange AtEnd;
+public:
+
+ ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
+
+ // Iterator access to properties.
+ typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
+ prop_iterator prop_begin() const {
+ return prop_iterator(decls_begin());
+ }
+ prop_iterator prop_end() const {
+ return prop_iterator(decls_end());
+ }
+
+ // Iterator access to instance/class methods.
+ typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
+ method_iterator meth_begin() const {
+ return method_iterator(decls_begin());
+ }
+ method_iterator meth_end() const {
+ return method_iterator(decls_end());
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isInstanceMethod>
+ instmeth_iterator;
+ instmeth_iterator instmeth_begin() const {
+ return instmeth_iterator(decls_begin());
+ }
+ instmeth_iterator instmeth_end() const {
+ return instmeth_iterator(decls_end());
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isClassMethod>
+ classmeth_iterator;
+ classmeth_iterator classmeth_begin() const {
+ return classmeth_iterator(decls_begin());
+ }
+ classmeth_iterator classmeth_end() const {
+ return classmeth_iterator(decls_end());
+ }
+
+ // Get the local instance/class method declared in this interface.
+ ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *getInstanceMethod(Selector Sel) const {
+ return getMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *getClassMethod(Selector Sel) const {
+ return getMethod(Sel, false/*isInstance*/);
+ }
+ ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
+
+ ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
+
+ // Marks the end of the container.
+ SourceRange getAtEndRange() const {
+ return AtEnd;
+ }
+ void setAtEndRange(SourceRange atEnd) {
+ AtEnd = atEnd;
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), getAtEndRange().getEnd());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCContainerDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstObjCContainer &&
+ K <= lastObjCContainer;
+ }
+
+ static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
+ }
+ static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example:
+///
+/// // MostPrimitive declares no super class (not particularly useful).
+/// @interface MostPrimitive
+/// // no instance variables or methods.
+/// @end
+///
+/// // NSResponder inherits from NSObject & implements NSCoding (a protocol).
+/// @interface NSResponder : NSObject <NSCoding>
+/// { // instance variables are represented by ObjCIvarDecl.
+/// id nextResponder; // nextResponder instance variable.
+/// }
+/// - (NSResponder *)nextResponder; // return a pointer to NSResponder.
+/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
+/// @end // to an NSEvent.
+///
+/// Unlike C/C++, forward class declarations are accomplished with @class.
+/// Unlike C/C++, @class allows for a list of classes to be forward declared.
+/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
+/// typically inherit from NSObject (an exception is NSProxy).
+///
+class ObjCInterfaceDecl : public ObjCContainerDecl {
+ /// TypeForDecl - This indicates the Type object that represents this
+ /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
+ mutable const Type *TypeForDecl;
+ friend class ASTContext;
+
+ /// Class's super class.
+ ObjCInterfaceDecl *SuperClass;
+
+ /// Protocols referenced in the @interface declaration
+ ObjCProtocolList ReferencedProtocols;
+
+ /// Protocols reference in both the @interface and class extensions.
+ ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
+
+ /// \brief List of categories and class extensions defined for this class.
+ ///
+ /// Categories are stored as a linked list in the AST, since the categories
+ /// and class extensions come long after the initial interface declaration,
+ /// and we avoid dynamically-resized arrays in the AST whereever possible.
+ ObjCCategoryDecl *CategoryList;
+
+ /// IvarList - List of all ivars defined by this class; including class
+ /// extensions and implementation. This list is built lazily.
+ ObjCIvarDecl *IvarList;
+
+ bool ForwardDecl:1; // declared with @class.
+ bool InternalInterface:1; // true - no @interface for @implementation
+
+ /// \brief Indicates that the contents of this Objective-C class will be
+ /// completed by the external AST source when required.
+ mutable bool ExternallyCompleted : 1;
+
+ SourceLocation ClassLoc; // location of the class identifier.
+ SourceLocation SuperClassLoc; // location of the super class identifier.
+ SourceLocation EndLoc; // marks the '>', '}', or identifier.
+
+ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
+ SourceLocation CLoc, bool FD, bool isInternal);
+
+ void LoadExternalDefinition() const;
+public:
+ static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc,
+ IdentifierInfo *Id,
+ SourceLocation ClassLoc = SourceLocation(),
+ bool ForwardDecl = false,
+ bool isInternal = false);
+
+ /// \brief Indicate that this Objective-C class is complete, but that
+ /// the external AST source will be responsible for filling in its contents
+ /// when a complete class is required.
+ void setExternallyCompleted();
+
+ const ObjCProtocolList &getReferencedProtocols() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return ReferencedProtocols;
+ }
+
+ ObjCImplementationDecl *getImplementation() const;
+ void setImplementation(ObjCImplementationDecl *ImplD);
+
+ ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
+
+ // Get the local instance/class method declared in a category.
+ ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
+ ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
+ ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
+ return isInstance ? getInstanceMethod(Sel)
+ : getClassMethod(Sel);
+ }
+
+ typedef ObjCProtocolList::iterator protocol_iterator;
+
+ protocol_iterator protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return ReferencedProtocols.end();
+ }
+
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+
+ protocol_loc_iterator protocol_loc_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return ReferencedProtocols.loc_begin();
+ }
+
+ protocol_loc_iterator protocol_loc_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return ReferencedProtocols.loc_end();
+ }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+
+ all_protocol_iterator all_referenced_protocol_begin() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return AllReferencedProtocols.empty() ? protocol_begin()
+ : AllReferencedProtocols.begin();
+ }
+ all_protocol_iterator all_referenced_protocol_end() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return AllReferencedProtocols.empty() ? protocol_end()
+ : AllReferencedProtocols.end();
+ }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+
+ ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
+ ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+
+ unsigned ivar_size() const {
+ return std::distance(ivar_begin(), ivar_end());
+ }
+
+ bool ivar_empty() const { return ivar_begin() == ivar_end(); }
+
+ ObjCIvarDecl *all_declared_ivar_begin();
+ void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
+ }
+
+ /// mergeClassExtensionProtocolList - Merge class extension's protocol list
+ /// into the protocol list for this class.
+ void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
+ unsigned Num,
+ ASTContext &C);
+
+ bool isForwardDecl() const { return ForwardDecl; }
+ void setForwardDecl(bool val) { ForwardDecl = val; }
+
+ ObjCInterfaceDecl *getSuperClass() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return SuperClass;
+ }
+
+ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ ObjCCategoryDecl* getCategoryList() const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return CategoryList;
+ }
+
+ void setCategoryList(ObjCCategoryDecl *category) {
+ CategoryList = category;
+ }
+
+ ObjCCategoryDecl* getFirstClassExtension() const;
+
+ ObjCPropertyDecl
+ *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
+
+ /// isSuperClassOf - Return true if this class is the specified class or is a
+ /// super class of the specified interface class.
+ bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
+ // If RHS is derived from LHS it is OK; else it is not OK.
+ while (I != NULL) {
+ if (this == I)
+ return true;
+ I = I->getSuperClass();
+ }
+ return false;
+ }
+
+ ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
+ ObjCInterfaceDecl *&ClassDeclared);
+ ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
+ ObjCInterfaceDecl *ClassDeclared;
+ return lookupInstanceVariable(IVarName, ClassDeclared);
+ }
+
+ // Lookup a method. First, we search locally. If a method isn't
+ // found, we search referenced protocols and class categories.
+ ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
+ return lookupMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
+ }
+ ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
+
+ // Lookup a method in the classes implementation hierarchy.
+ ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true);
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); } // '@'interface
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; }
+
+ void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; }
+ SourceLocation getClassLoc() const { return ClassLoc; }
+ void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
+ SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
+
+ /// isImplicitInterfaceDecl - check that this is an implicitly declared
+ /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
+ /// declaration without an @interface declaration.
+ bool isImplicitInterfaceDecl() const { return InternalInterface; }
+ void setImplicitInterfaceDecl(bool val) { InternalInterface = val; }
+
+ /// ClassImplementsProtocol - Checks that 'lProto' protocol
+ /// has been implemented in IDecl class, its super class or categories (if
+ /// lookupCategory is true).
+ bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+ bool lookupCategory,
+ bool RHSIsQualifiedID = false);
+
+ // Low-level accessor
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCInterfaceDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCInterface; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
+/// instance variables are identical to C. The only exception is Objective-C
+/// supports C++ style access control. For example:
+///
+/// @interface IvarExample : NSObject
+/// {
+/// id defaultToProtected;
+/// @public:
+/// id canBePublic; // same as C++.
+/// @protected:
+/// id canBeProtected; // same as C++.
+/// @package:
+/// id canBePackage; // framework visibility (not available in C++).
+/// }
+///
+class ObjCIvarDecl : public FieldDecl {
+public:
+ enum AccessControl {
+ None, Private, Protected, Public, Package
+ };
+
+private:
+ ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
+ bool synthesized)
+ : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
+ NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
+
+public:
+ static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
+ SourceLocation L, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ AccessControl ac, Expr *BW = NULL,
+ bool synthesized=false);
+
+ /// \brief Return the class interface that this ivar is logically contained
+ /// in; this is either the interface where the ivar was declared, or the
+ /// interface the ivar is conceptually a part of in the case of synthesized
+ /// ivars.
+ const ObjCInterfaceDecl *getContainingInterface() const;
+
+ ObjCIvarDecl *getNextIvar() { return NextIvar; }
+ void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
+
+ void setAccessControl(AccessControl ac) { DeclAccess = ac; }
+
+ AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
+
+ AccessControl getCanonicalAccessControl() const {
+ return DeclAccess == None ? Protected : AccessControl(DeclAccess);
+ }
+
+ void setSynthesize(bool synth) { Synthesized = synth; }
+ bool getSynthesize() const { return Synthesized; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCIvarDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCIvar; }
+private:
+ /// NextIvar - Next Ivar in the list of ivars declared in class; class's
+ /// extensions and class's implementation
+ ObjCIvarDecl *NextIvar;
+
+ // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
+ unsigned DeclAccess : 3;
+ unsigned Synthesized : 1;
+};
+
+
+/// ObjCAtDefsFieldDecl - Represents a field declaration created by an
+/// @defs(...).
+class ObjCAtDefsFieldDecl : public FieldDecl {
+private:
+ ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *BW)
+ : FieldDecl(ObjCAtDefsField, DC, L, Id, T,
+ /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
+ BW, /*Mutable=*/false) {}
+
+public:
+ static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ Expr *BW);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
+};
+
+/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
+/// declare a pure abstract type (i.e no instance variables are permitted).
+/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
+/// feature with nice semantics and lousy syntax:-). Here is an example:
+///
+/// @protocol NSDraggingInfo <refproto1, refproto2>
+/// - (NSWindow *)draggingDestinationWindow;
+/// - (NSImage *)draggedImage;
+/// @end
+///
+/// This says that NSDraggingInfo requires two methods and requires everything
+/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
+/// well.
+///
+/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
+/// @end
+///
+/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
+/// protocols are in distinct namespaces. For example, Cocoa defines both
+/// an NSObject protocol and class (which isn't allowed in Java). As a result,
+/// protocols are referenced using angle brackets as follows:
+///
+/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
+///
+class ObjCProtocolDecl : public ObjCContainerDecl {
+ /// Referenced protocols
+ ObjCProtocolList ReferencedProtocols;
+
+ bool isForwardProtoDecl; // declared with @protocol.
+
+ SourceLocation EndLoc; // marks the '>' or identifier.
+
+ ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+ : ObjCContainerDecl(ObjCProtocol, DC, L, Id),
+ isForwardProtoDecl(true) {
+ }
+
+public:
+ static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ const ObjCProtocolList &getReferencedProtocols() const {
+ return ReferencedProtocols;
+ }
+ typedef ObjCProtocolList::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
+ }
+
+ ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
+
+ // Lookup a method. First, we search locally. If a method isn't
+ // found, we search referenced protocols and class categories.
+ ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
+ return lookupMethod(Sel, true/*isInstance*/);
+ }
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
+ }
+
+ bool isForwardDecl() const { return isForwardProtoDecl; }
+ void setForwardDecl(bool val) { isForwardProtoDecl = val; }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCProtocolDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCProtocol; }
+};
+
+/// ObjCClassDecl - Specifies a list of forward class declarations. For example:
+///
+/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
+///
+class ObjCClassDecl : public Decl {
+public:
+ class ObjCClassRef {
+ ObjCInterfaceDecl *ID;
+ SourceLocation L;
+ public:
+ ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {}
+ SourceLocation getLocation() const { return L; }
+ ObjCInterfaceDecl *getInterface() const { return ID; }
+ };
+private:
+ ObjCClassRef *ForwardDecls;
+ unsigned NumDecls;
+
+ ObjCClassDecl(DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
+ unsigned nElts, ASTContext &C);
+public:
+ static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *const *Elts = 0,
+ const SourceLocation *Locs = 0,
+ unsigned nElts = 0);
+
+ virtual SourceRange getSourceRange() const;
+
+ typedef const ObjCClassRef* iterator;
+ iterator begin() const { return ForwardDecls; }
+ iterator end() const { return ForwardDecls + NumDecls; }
+ unsigned size() const { return NumDecls; }
+
+ /// setClassList - Set the list of forward classes.
+ void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
+ const SourceLocation *Locs, unsigned Num);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCClassDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCClass; }
+};
+
+/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations.
+/// For example:
+///
+/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
+///
+class ObjCForwardProtocolDecl : public Decl {
+ ObjCProtocolList ReferencedProtocols;
+
+ ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
+ ObjCProtocolDecl *const *Elts, unsigned nElts,
+ const SourceLocation *Locs, ASTContext &C);
+
+public:
+ static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCProtocolDecl *const *Elts,
+ unsigned Num,
+ const SourceLocation *Locs);
+
+ static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L) {
+ return Create(C, DC, L, 0, 0, 0);
+ }
+
+ typedef ObjCProtocolList::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
+
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ /// setProtocolList - Set the list of forward protocols.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
+ }
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCForwardProtocolDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCForwardProtocol; }
+};
+
+/// ObjCCategoryDecl - Represents a category declaration. A category allows
+/// you to add methods to an existing class (without subclassing or modifying
+/// the original class interface or implementation:-). Categories don't allow
+/// you to add instance data. The following example adds "myMethod" to all
+/// NSView's within a process:
+///
+/// @interface NSView (MyViewMethods)
+/// - myMethod;
+/// @end
+///
+/// Categories also allow you to split the implementation of a class across
+/// several files (a feature more naturally supported in C++).
+///
+/// Categories were originally inspired by dynamic languages such as Common
+/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
+/// don't support this level of dynamism, which is both powerful and dangerous.
+///
+class ObjCCategoryDecl : public ObjCContainerDecl {
+ /// Interface belonging to this category
+ ObjCInterfaceDecl *ClassInterface;
+
+ /// referenced protocols in this category.
+ ObjCProtocolList ReferencedProtocols;
+
+ /// Next category belonging to this class.
+ /// FIXME: this should not be a singly-linked list. Move storage elsewhere.
+ ObjCCategoryDecl *NextClassCategory;
+
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
+ /// \brief The location of the '@' in '@interface'
+ SourceLocation AtLoc;
+
+ /// \brief The location of the category name in this declaration.
+ SourceLocation CategoryNameLoc;
+
+ ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
+ SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id)
+ : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
+ ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
+ AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
+ }
+public:
+
+ static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id);
+
+ ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
+ const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
+
+ ObjCCategoryImplDecl *getImplementation() const;
+ void setImplementation(ObjCCategoryImplDecl *ImplD);
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ ReferencedProtocols.set(List, Num, Locs, C);
+ }
+
+ const ObjCProtocolList &getReferencedProtocols() const {
+ return ReferencedProtocols;
+ }
+
+ typedef ObjCProtocolList::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ protocol_loc_iterator protocol_loc_begin() const {
+ return ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ return ReferencedProtocols.loc_end();
+ }
+
+ ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
+ void setNextClassCategory(ObjCCategoryDecl *Cat) {
+ NextClassCategory = Cat;
+ }
+ void insertNextClassCategory() {
+ NextClassCategory = ClassInterface->getCategoryList();
+ ClassInterface->setCategoryList(this);
+ ClassInterface->setChangedSinceDeserialization(true);
+ }
+
+ bool IsClassExtension() const { return getIdentifier() == 0; }
+ const ObjCCategoryDecl *getNextClassExtension() const;
+
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ ivar_iterator ivar_begin() const {
+ return ivar_iterator(decls_begin());
+ }
+ ivar_iterator ivar_end() const {
+ return ivar_iterator(decls_end());
+ }
+ unsigned ivar_size() const {
+ return std::distance(ivar_begin(), ivar_end());
+ }
+ bool ivar_empty() const {
+ return ivar_begin() == ivar_end();
+ }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation At) { AtLoc = At; }
+
+ SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
+ void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getAtEndRange().getEnd());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCCategoryDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCCategory; }
+};
+
+class ObjCImplDecl : public ObjCContainerDecl {
+ /// Class interface for this class/category implementation
+ ObjCInterfaceDecl *ClassInterface;
+
+protected:
+ ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *classInterface)
+ : ObjCContainerDecl(DK, DC, L,
+ classInterface? classInterface->getIdentifier() : 0),
+ ClassInterface(classInterface) {}
+
+public:
+ const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
+ void setClassInterface(ObjCInterfaceDecl *IFace);
+
+ void addInstanceMethod(ObjCMethodDecl *method) {
+ // FIXME: Context should be set correctly before we get here.
+ method->setLexicalDeclContext(this);
+ addDecl(method);
+ }
+ void addClassMethod(ObjCMethodDecl *method) {
+ // FIXME: Context should be set correctly before we get here.
+ method->setLexicalDeclContext(this);
+ addDecl(method);
+ }
+
+ void addPropertyImplementation(ObjCPropertyImplDecl *property);
+
+ ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const;
+ ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const;
+
+ // Iterator access to properties.
+ typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
+ propimpl_iterator propimpl_begin() const {
+ return propimpl_iterator(decls_begin());
+ }
+ propimpl_iterator propimpl_end() const {
+ return propimpl_iterator(decls_end());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCImplDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstObjCImpl && K <= lastObjCImpl;
+ }
+};
+
+/// ObjCCategoryImplDecl - An object of this class encapsulates a category
+/// @implementation declaration. If a category class has declaration of a
+/// property, its implementation must be specified in the category's
+/// @implementation declaration. Example:
+/// @interface I @end
+/// @interface I(CATEGORY)
+/// @property int p1, d1;
+/// @end
+/// @implementation I(CATEGORY)
+/// @dynamic p1,d1;
+/// @end
+///
+/// ObjCCategoryImplDecl
+class ObjCCategoryImplDecl : public ObjCImplDecl {
+ // Category name
+ IdentifierInfo *Id;
+
+ ObjCCategoryImplDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface)
+ : ObjCImplDecl(ObjCCategoryImpl, DC, L, classInterface), Id(Id) {}
+public:
+ static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface);
+
+ /// getIdentifier - Get the identifier that names the category
+ /// interface associated with this implementation.
+ /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
+ /// to mean something different. For example:
+ /// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the class interface name, whereas
+ /// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
+ /// returns the category name.
+ IdentifierInfo *getIdentifier() const {
+ return Id;
+ }
+ void setIdentifier(IdentifierInfo *II) { Id = II; }
+
+ ObjCCategoryDecl *getCategoryDecl() const;
+
+ /// getName - Get the name of identifier for the class interface associated
+ /// with this implementation as a StringRef.
+ //
+ // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
+ // something different.
+ llvm::StringRef getName() const {
+ return Id ? Id->getNameStart() : "";
+ }
+
+ /// getNameAsCString - Get the name of identifier for the class
+ /// interface associated with this implementation as a C string
+ /// (const char*).
+ //
+ // FIXME: Deprecated, move clients to getName().
+ const char *getNameAsCString() const {
+ return Id ? Id->getNameStart() : "";
+ }
+
+ /// @brief Get the name of the class associated with this interface.
+ //
+ // FIXME: Deprecated, move clients to getName().
+ std::string getNameAsString() const {
+ return getName();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCCategoryImplDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const ObjCCategoryImplDecl *CID);
+
+/// ObjCImplementationDecl - Represents a class definition - this is where
+/// method definitions are specified. For example:
+///
+/// @code
+/// @implementation MyClass
+/// - (void)myMethod { /* do something */ }
+/// @end
+/// @endcode
+///
+/// Typically, instance variables are specified in the class interface,
+/// *not* in the implementation. Nevertheless (for legacy reasons), we
+/// allow instance variables to be specified in the implementation. When
+/// specified, they need to be *identical* to the interface.
+///
+class ObjCImplementationDecl : public ObjCImplDecl {
+ /// Implementation Class's super class.
+ ObjCInterfaceDecl *SuperClass;
+ /// Support for ivar initialization.
+ /// IvarInitializers - The arguments used to initialize the ivars
+ CXXCtorInitializer **IvarInitializers;
+ unsigned NumIvarInitializers;
+
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
+ ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl)
+ : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
+ SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
+ HasSynthBitfield(false) {}
+public:
+ static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl);
+
+ /// init_iterator - Iterates through the ivar initializer list.
+ typedef CXXCtorInitializer **init_iterator;
+
+ /// init_const_iterator - Iterates through the ivar initializer list.
+ typedef CXXCtorInitializer * const * init_const_iterator;
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() { return IvarInitializers; }
+ /// begin() - Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const { return IvarInitializers; }
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return IvarInitializers + NumIvarInitializers;
+ }
+ /// end() - Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return IvarInitializers + NumIvarInitializers;
+ }
+ /// getNumArgs - Number of ivars which must be initialized.
+ unsigned getNumIvarInitializers() const {
+ return NumIvarInitializers;
+ }
+
+ void setNumIvarInitializers(unsigned numNumIvarInitializers) {
+ NumIvarInitializers = numNumIvarInitializers;
+ }
+
+ void setIvarInitializers(ASTContext &C,
+ CXXCtorInitializer ** initializers,
+ unsigned numInitializers);
+
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
+
+ /// getIdentifier - Get the identifier that names the class
+ /// interface associated with this implementation.
+ IdentifierInfo *getIdentifier() const {
+ return getClassInterface()->getIdentifier();
+ }
+
+ /// getName - Get the name of identifier for the class interface associated
+ /// with this implementation as a StringRef.
+ //
+ // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
+ // something different.
+ llvm::StringRef getName() const {
+ assert(getIdentifier() && "Name is not a simple identifier");
+ return getIdentifier()->getName();
+ }
+
+ /// getNameAsCString - Get the name of identifier for the class
+ /// interface associated with this implementation as a C string
+ /// (const char*).
+ //
+ // FIXME: Move to StringRef API.
+ const char *getNameAsCString() const {
+ return getName().data();
+ }
+
+ /// @brief Get the name of the class associated with this interface.
+ //
+ // FIXME: Move to StringRef API.
+ std::string getNameAsString() const {
+ return getName();
+ }
+
+ const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
+
+ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ ivar_iterator ivar_begin() const {
+ return ivar_iterator(decls_begin());
+ }
+ ivar_iterator ivar_end() const {
+ return ivar_iterator(decls_end());
+ }
+ unsigned ivar_size() const {
+ return std::distance(ivar_begin(), ivar_end());
+ }
+ bool ivar_empty() const {
+ return ivar_begin() == ivar_end();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCImplementationDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCImplementation; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const ObjCImplementationDecl *ID);
+
+/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
+/// declared as @compatibility_alias alias class.
+class ObjCCompatibleAliasDecl : public NamedDecl {
+ /// Class that this is an alias of.
+ ObjCInterfaceDecl *AliasedClass;
+
+ ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl* aliasedClass)
+ : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
+public:
+ static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl* aliasedClass);
+
+ const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
+ ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
+ void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
+
+};
+
+/// ObjCPropertyDecl - Represents one property declaration in an interface.
+/// For example:
+/// @property (assign, readwrite) int MyProperty;
+///
+class ObjCPropertyDecl : public NamedDecl {
+public:
+ enum PropertyAttributeKind {
+ OBJC_PR_noattr = 0x00,
+ OBJC_PR_readonly = 0x01,
+ OBJC_PR_getter = 0x02,
+ OBJC_PR_assign = 0x04,
+ OBJC_PR_readwrite = 0x08,
+ OBJC_PR_retain = 0x10,
+ OBJC_PR_copy = 0x20,
+ OBJC_PR_nonatomic = 0x40,
+ OBJC_PR_setter = 0x80,
+ OBJC_PR_atomic = 0x100
+ };
+
+ enum SetterKind { Assign, Retain, Copy };
+ enum PropertyControl { None, Required, Optional };
+private:
+ SourceLocation AtLoc; // location of @property
+ TypeSourceInfo *DeclType;
+ unsigned PropertyAttributes : 9;
+ unsigned PropertyAttributesAsWritten : 9;
+ // @required/@optional
+ unsigned PropertyImplementation : 2;
+
+ Selector GetterName; // getter name of NULL if no getter
+ Selector SetterName; // setter name of NULL if no setter
+
+ ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
+ ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
+ ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
+
+ ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ SourceLocation AtLocation, TypeSourceInfo *T)
+ : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T),
+ PropertyAttributes(OBJC_PR_noattr),
+ PropertyAttributesAsWritten(OBJC_PR_noattr),
+ PropertyImplementation(None),
+ GetterName(Selector()),
+ SetterName(Selector()),
+ GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
+public:
+ static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id, SourceLocation AtLocation,
+ TypeSourceInfo *T,
+ PropertyControl propControl = None);
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+
+ TypeSourceInfo *getTypeSourceInfo() const { return DeclType; }
+ QualType getType() const { return DeclType->getType(); }
+ void setType(TypeSourceInfo *T) { DeclType = T; }
+
+ PropertyAttributeKind getPropertyAttributes() const {
+ return PropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(PropertyAttributeKind PRVal) {
+ PropertyAttributes |= PRVal;
+ }
+
+ PropertyAttributeKind getPropertyAttributesAsWritten() const {
+ return PropertyAttributeKind(PropertyAttributesAsWritten);
+ }
+
+ void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
+ PropertyAttributesAsWritten = PRVal;
+ }
+
+ void makeitReadWriteAttribute(void) {
+ PropertyAttributes &= ~OBJC_PR_readonly;
+ PropertyAttributes |= OBJC_PR_readwrite;
+ }
+
+ // Helper methods for accessing attributes.
+
+ /// isReadOnly - Return true iff the property has a setter.
+ bool isReadOnly() const {
+ return (PropertyAttributes & OBJC_PR_readonly);
+ }
+
+ /// getSetterKind - Return the method used for doing assignment in
+ /// the property setter. This is only valid if the property has been
+ /// defined to have a setter.
+ SetterKind getSetterKind() const {
+ if (PropertyAttributes & OBJC_PR_retain)
+ return Retain;
+ if (PropertyAttributes & OBJC_PR_copy)
+ return Copy;
+ return Assign;
+ }
+
+ Selector getGetterName() const { return GetterName; }
+ void setGetterName(Selector Sel) { GetterName = Sel; }
+
+ Selector getSetterName() const { return SetterName; }
+ void setSetterName(Selector Sel) { SetterName = Sel; }
+
+ ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
+ void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
+
+ ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
+ void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
+
+ // Related to @optional/@required declared in @protocol
+ void setPropertyImplementation(PropertyControl pc) {
+ PropertyImplementation = pc;
+ }
+ PropertyControl getPropertyImplementation() const {
+ return PropertyControl(PropertyImplementation);
+ }
+
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
+ PropertyIvarDecl = Ivar;
+ }
+ ObjCIvarDecl *getPropertyIvarDecl() const {
+ return PropertyIvarDecl;
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, getLocation());
+ }
+
+ /// Lookup a property by name in the specified DeclContext.
+ static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
+ IdentifierInfo *propertyID);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCPropertyDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ObjCProperty; }
+};
+
+/// ObjCPropertyImplDecl - Represents implementation declaration of a property
+/// in a class or category implementation block. For example:
+/// @synthesize prop1 = ivar1;
+///
+class ObjCPropertyImplDecl : public Decl {
+public:
+ enum Kind {
+ Synthesize,
+ Dynamic
+ };
+private:
+ SourceLocation AtLoc; // location of @synthesize or @dynamic
+
+ /// \brief For @synthesize, the location of the ivar, if it was written in
+ /// the source code.
+ ///
+ /// \code
+ /// @synthesize int a = b
+ /// \endcode
+ SourceLocation IvarLoc;
+
+ /// Property declaration being implemented
+ ObjCPropertyDecl *PropertyDecl;
+
+ /// Null for @dynamic. Required for @synthesize.
+ ObjCIvarDecl *PropertyIvarDecl;
+
+ /// Null for @dynamic. Non-null if property must be copy-constructed in getter
+ Expr *GetterCXXConstructor;
+
+ /// Null for @dynamic. Non-null if property has assignment operator to call
+ /// in Setter synthesis.
+ Expr *SetterCXXAssignment;
+
+ ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc)
+ : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
+ IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
+ GetterCXXConstructor(0), SetterCXXAssignment(0) {
+ assert (PK == Dynamic || PropertyIvarDecl);
+ }
+
+public:
+ static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc);
+
+ virtual SourceRange getSourceRange() const;
+
+ SourceLocation getLocStart() const { return AtLoc; }
+ void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
+
+ ObjCPropertyDecl *getPropertyDecl() const {
+ return PropertyDecl;
+ }
+ void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; }
+
+ Kind getPropertyImplementation() const {
+ return PropertyIvarDecl ? Synthesize : Dynamic;
+ }
+
+ ObjCIvarDecl *getPropertyIvarDecl() const {
+ return PropertyIvarDecl;
+ }
+ SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; }
+
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar,
+ SourceLocation IvarLoc) {
+ PropertyIvarDecl = Ivar;
+ this->IvarLoc = IvarLoc;
+ }
+
+ Expr *getGetterCXXConstructor() const {
+ return GetterCXXConstructor;
+ }
+ void setGetterCXXConstructor(Expr *getterCXXConstructor) {
+ GetterCXXConstructor = getterCXXConstructor;
+ }
+
+ Expr *getSetterCXXAssignment() const {
+ return SetterCXXAssignment;
+ }
+ void setSetterCXXAssignment(Expr *setterCXXAssignment) {
+ SetterCXXAssignment = setterCXXAssignment;
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ObjCPropertyImplDecl *D) { return true; }
+ static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
+
+ friend class ASTDeclReader;
+};
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
new file mode 100644
index 0000000..176c6ba
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -0,0 +1,1972 @@
+//===-- DeclTemplate.h - Classes for representing C++ templates -*- 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 C++ template declaration subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
+#define LLVM_CLANG_AST_DECLTEMPLATE_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/TemplateBase.h"
+#include "llvm/ADT/PointerUnion.h"
+#include <limits>
+
+namespace clang {
+
+class TemplateParameterList;
+class TemplateDecl;
+class RedeclarableTemplateDecl;
+class FunctionTemplateDecl;
+class ClassTemplateDecl;
+class ClassTemplatePartialSpecializationDecl;
+class TemplateTypeParmDecl;
+class NonTypeTemplateParmDecl;
+class TemplateTemplateParmDecl;
+
+/// \brief Stores a template parameter of any kind.
+typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
+ TemplateTemplateParmDecl*> TemplateParameter;
+
+/// TemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes.
+class TemplateParameterList {
+ /// The location of the 'template' keyword.
+ SourceLocation TemplateLoc;
+
+ /// The locations of the '<' and '>' angle brackets.
+ SourceLocation LAngleLoc, RAngleLoc;
+
+ /// The number of template parameters in this template
+ /// parameter list.
+ unsigned NumParams;
+
+ TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ NamedDecl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+public:
+ static TemplateParameterList *Create(const ASTContext &C,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ NamedDecl **Params,
+ unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+ /// iterator - Iterates through the template parameters in this list.
+ typedef NamedDecl** iterator;
+
+ /// const_iterator - Iterates through the template parameters in this list.
+ typedef NamedDecl* const* const_iterator;
+
+ iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
+ const_iterator begin() const {
+ return reinterpret_cast<NamedDecl * const *>(this + 1);
+ }
+ iterator end() { return begin() + NumParams; }
+ const_iterator end() const { return begin() + NumParams; }
+
+ unsigned size() const { return NumParams; }
+
+ NamedDecl* getParam(unsigned Idx) {
+ assert(Idx < size() && "Template parameter index out-of-range");
+ return begin()[Idx];
+ }
+
+ const NamedDecl* getParam(unsigned Idx) const {
+ assert(Idx < size() && "Template parameter index out-of-range");
+ return begin()[Idx];
+ }
+
+ /// \brief Returns the minimum number of arguments needed to form a
+ /// template specialization. This may be fewer than the number of
+ /// template parameters, if some of the parameters have default
+ /// arguments or if there is a parameter pack.
+ unsigned getMinRequiredArguments() const;
+
+ /// \brief Get the depth of this template parameter list in the set of
+ /// template parameter lists.
+ ///
+ /// The first template parameter list in a declaration will have depth 0,
+ /// the second template parameter list will have depth 1, etc.
+ unsigned getDepth() const;
+
+ SourceLocation getTemplateLoc() const { return TemplateLoc; }
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TemplateLoc, RAngleLoc);
+ }
+};
+
+/// \brief A template argument list.
+class TemplateArgumentList {
+ /// \brief The template argument list.
+ ///
+ /// The integer value will be non-zero to indicate that this
+ /// template argument list does own the pointer.
+ llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
+
+ /// \brief The number of template arguments in this template
+ /// argument list.
+ unsigned NumArguments;
+
+ TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL
+ void operator=(const TemplateArgumentList &Other); // DO NOT IMPL
+
+ TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
+ bool Owned)
+ : Arguments(Args, Owned), NumArguments(NumArgs) { }
+
+public:
+ /// \brief Type used to indicate that the template argument list itself is a
+ /// stack object. It does not own its template arguments.
+ enum OnStackType { OnStack };
+
+ /// \brief Create a new template argument list that copies the given set of
+ /// template arguments.
+ static TemplateArgumentList *CreateCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Construct a new, temporary template argument list on the stack.
+ ///
+ /// The template argument list does not own the template arguments
+ /// provided.
+ explicit TemplateArgumentList(OnStackType,
+ const TemplateArgument *Args, unsigned NumArgs)
+ : Arguments(Args, false), NumArguments(NumArgs) { }
+
+ /// \brief Produces a shallow copy of the given template argument list.
+ ///
+ /// This operation 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.
+ explicit TemplateArgumentList(const TemplateArgumentList *Other)
+ : Arguments(Other->data(), false), NumArguments(Other->size()) { }
+
+ /// \brief Retrieve the template argument at a given index.
+ const TemplateArgument &get(unsigned Idx) const {
+ assert(Idx < NumArguments && "Invalid template argument index");
+ return data()[Idx];
+ }
+
+ /// \brief Retrieve the template argument at a given index.
+ const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+
+ /// \brief Retrieve the number of template arguments in this
+ /// template argument list.
+ unsigned size() const { return NumArguments; }
+
+ /// \brief Retrieve a pointer to the template argument list.
+ const TemplateArgument *data() const {
+ return Arguments.getPointer();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Templates
+//===----------------------------------------------------------------------===//
+
+/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
+/// class, function, etc.). The TemplateDecl class stores the list of template
+/// parameters and a reference to the templated scoped declaration: the
+/// underlying AST node.
+class TemplateDecl : public NamedDecl {
+protected:
+ // This is probably never used.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { }
+
+ // Construct a template decl with the given name and parameters.
+ // Used when there is not templated element (tt-params, alias?).
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params) { }
+
+ // Construct a template decl with name, parameters, and templated element.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
+ TemplateParams(Params) { }
+public:
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the underlying, templated declaration.
+ NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TemplateDecl *D) { return true; }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstTemplate && K <= lastTemplate;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TemplateParams->getTemplateLoc(),
+ TemplatedDecl->getSourceRange().getEnd());
+ }
+
+protected:
+ NamedDecl *TemplatedDecl;
+ TemplateParameterList* TemplateParams;
+
+public:
+ /// \brief Initialize the underlying templated declaration and
+ /// template parameters.
+ void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
+ assert(TemplatedDecl == 0 && "TemplatedDecl already set!");
+ assert(TemplateParams == 0 && "TemplateParams already set!");
+ TemplatedDecl = templatedDecl;
+ TemplateParams = templateParams;
+ }
+};
+
+/// \brief Provides information about a function template specialization,
+/// which is a FunctionDecl that has been explicitly specialization or
+/// instantiated from a function template.
+class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
+ FunctionTemplateSpecializationInfo(FunctionDecl *FD,
+ FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI)
+ : Function(FD),
+ Template(Template, TSK - 1),
+ TemplateArguments(TemplateArgs),
+ TemplateArgumentsAsWritten(TemplateArgsAsWritten),
+ PointOfInstantiation(POI) { }
+
+public:
+ static FunctionTemplateSpecializationInfo *
+ Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentList *TemplateArgs,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation POI) {
+ return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
+ TemplateArgs,
+ TemplateArgsAsWritten,
+ POI);
+ }
+
+ /// \brief The function template specialization that this structure
+ /// describes.
+ FunctionDecl *Function;
+
+ /// \brief The function template from which this function template
+ /// specialization was generated.
+ ///
+ /// The two bits are contain the top 4 values of TemplateSpecializationKind.
+ llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
+
+ /// \brief The template arguments used to produce the function template
+ /// specialization from the function template.
+ const TemplateArgumentList *TemplateArguments;
+
+ /// \brief The template arguments as written in the sources, if provided.
+ const TemplateArgumentListInfo *TemplateArgumentsAsWritten;
+
+ /// \brief The point at which this function template specialization was
+ /// first instantiated.
+ SourceLocation PointOfInstantiation;
+
+ /// \brief Retrieve the template from which this function was specialized.
+ FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
+
+ /// \brief Determine what kind of template specialization this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const {
+ return (TemplateSpecializationKind)(Template.getInt() + 1);
+ }
+
+ /// \brief Set the template specialization kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode TSK_Undeclared for a function template specialization");
+ Template.setInt(TSK - 1);
+ }
+
+ /// \brief Retrieve the first point of instantiation of this function
+ /// template specialization.
+ ///
+ /// The point of instantiation may be an invalid source location if this
+ /// function has yet to be instantiated.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ /// \brief Set the (first) point of instantiation of this function template
+ /// specialization.
+ void setPointOfInstantiation(SourceLocation POI) {
+ PointOfInstantiation = POI;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, TemplateArguments->data(),
+ TemplateArguments->size(),
+ Function->getASTContext());
+ }
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, ASTContext &Context) {
+ ID.AddInteger(NumTemplateArgs);
+ for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ TemplateArgs[Arg].Profile(ID, Context);
+ }
+};
+
+/// \brief Provides information a specialization of a member of a class
+/// template, which may be a member function, static data member, or
+/// member class.
+class MemberSpecializationInfo {
+ // The member declaration from which this member was instantiated, and the
+ // manner in which the instantiation occurred (in the lower two bits).
+ llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
+
+ // The point at which this member was first instantiated.
+ SourceLocation PointOfInstantiation;
+
+public:
+ explicit
+ MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK,
+ SourceLocation POI = SourceLocation())
+ : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode undeclared template specializations for members");
+ }
+
+ /// \brief Retrieve the member declaration from which this member was
+ /// instantiated.
+ NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); }
+
+ /// \brief Determine what kind of template specialization this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const {
+ return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1);
+ }
+
+ /// \brief Set the template specialization kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+ assert(TSK != TSK_Undeclared &&
+ "Cannot encode undeclared template specializations for members");
+ MemberAndTSK.setInt(TSK - 1);
+ }
+
+ /// \brief Retrieve the first point of instantiation of this member.
+ /// If the point of instantiation is an invalid location, then this member
+ /// has not yet been instantiated.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ /// \brief Set the first point of instantiation.
+ void setPointOfInstantiation(SourceLocation POI) {
+ PointOfInstantiation = POI;
+ }
+};
+
+/// \brief Provides information about a dependent function-template
+/// specialization declaration. Since explicit function template
+/// specialization and instantiation declarations can only appear in
+/// namespace scope, and you can only specialize a member of a
+/// fully-specialized class, the only way to get one of these is in
+/// a friend declaration like the following:
+///
+/// template <class T> void foo(T);
+/// template <class T> class A {
+/// friend void foo<>(T);
+/// };
+class DependentFunctionTemplateSpecializationInfo {
+ union {
+ // Force sizeof to be a multiple of sizeof(void*) so that the
+ // trailing data is aligned.
+ void *Aligner;
+
+ struct {
+ /// The number of potential template candidates.
+ unsigned NumTemplates;
+
+ /// The number of template arguments.
+ unsigned NumArgs;
+ } d;
+ };
+
+ /// The locations of the left and right angle brackets.
+ SourceRange AngleLocs;
+
+ FunctionTemplateDecl * const *getTemplates() const {
+ return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
+ }
+
+public:
+ DependentFunctionTemplateSpecializationInfo(
+ const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ /// \brief Returns the number of function templates that this might
+ /// be a specialization of.
+ unsigned getNumTemplates() const {
+ return d.NumTemplates;
+ }
+
+ /// \brief Returns the i'th template candidate.
+ FunctionTemplateDecl *getTemplate(unsigned I) const {
+ assert(I < getNumTemplates() && "template index out of range");
+ return getTemplates()[I];
+ }
+
+ /// \brief Returns the explicit template arguments that were given.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc*>(
+ &getTemplates()[getNumTemplates()]);
+ }
+
+ /// \brief Returns the number of explicit template arguments that were given.
+ unsigned getNumTemplateArgs() const {
+ return d.NumArgs;
+ }
+
+ /// \brief Returns the nth template argument.
+ const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
+ assert(I < getNumTemplateArgs() && "template arg index out of range");
+ return getTemplateArgs()[I];
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return AngleLocs.getBegin();
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return AngleLocs.getEnd();
+ }
+};
+
+/// Declaration of a redeclarable template.
+class RedeclarableTemplateDecl : public TemplateDecl {
+
+ RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
+ return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
+ }
+
+ RedeclarableTemplateDecl *getCanonicalDeclImpl();
+
+ void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
+
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
+ return getCommonPtr()->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
+ getCommonPtr()->InstantiatedFromMember.setPointer(TD);
+ }
+
+protected:
+ template <typename EntryType> struct SpecEntryTraits {
+ typedef EntryType DeclType;
+
+ static DeclType *getMostRecentDeclaration(EntryType *D) {
+ return D->getMostRecentDeclaration();
+ }
+ };
+
+ template <typename EntryType,
+ typename _SETraits = SpecEntryTraits<EntryType>,
+ typename _DeclType = typename _SETraits::DeclType>
+ class SpecIterator : public std::iterator<std::forward_iterator_tag,
+ _DeclType*, ptrdiff_t,
+ _DeclType*, _DeclType*> {
+ typedef _SETraits SETraits;
+ typedef _DeclType DeclType;
+
+ typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
+
+ SetIteratorType SetIter;
+
+ public:
+ SpecIterator() : SetIter() {}
+ SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
+
+ DeclType *operator*() const {
+ return SETraits::getMostRecentDeclaration(&*SetIter);
+ }
+ DeclType *operator->() const { return **this; }
+
+ SpecIterator &operator++() { ++SetIter; return *this; }
+ SpecIterator operator++(int) {
+ SpecIterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ bool operator==(SpecIterator Other) const {
+ return SetIter == Other.SetIter;
+ }
+ bool operator!=(SpecIterator Other) const {
+ return SetIter != Other.SetIter;
+ }
+ };
+
+ template <typename EntryType>
+ SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
+ bool isEnd) {
+ return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
+ }
+
+ template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
+ findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ struct CommonBase {
+ CommonBase() : InstantiatedFromMember(0, false) { }
+
+ /// \brief The template from which this was most
+ /// directly instantiated (or null).
+ ///
+ /// The boolean value indicates whether this template
+ /// was explicitly specialized.
+ llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
+ InstantiatedFromMember;
+
+ /// \brief The latest declaration of this template.
+ RedeclarableTemplateDecl *Latest;
+ };
+
+ /// \brief A pointer to the previous declaration (if this is a redeclaration)
+ /// or to the data that is common to all declarations of this template.
+ llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
+
+ /// \brief Retrieves the "common" pointer shared by all (re-)declarations of
+ /// the same template. Calling this routine may implicitly allocate memory
+ /// for the common pointer.
+ CommonBase *getCommonPtr();
+
+ virtual CommonBase *newCommon(ASTContext &C) = 0;
+
+ // Construct a template decl with name, parameters, and templated element.
+ RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : TemplateDecl(DK, DC, L, Name, Params, Decl),
+ CommonOrPrev((CommonBase*)0) { }
+
+public:
+ template <class decl_type> friend class RedeclarableTemplate;
+
+ RedeclarableTemplateDecl *getCanonicalDecl() {
+ return getCanonicalDeclImpl();
+ }
+
+ /// \brief Retrieve the previous declaration of this template, or
+ /// NULL if no such declaration exists.
+ RedeclarableTemplateDecl *getPreviousDeclaration() {
+ return getPreviousDeclarationImpl();
+ }
+
+ /// \brief Retrieve the previous declaration of this template, or
+ /// NULL if no such declaration exists.
+ const RedeclarableTemplateDecl *getPreviousDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
+ }
+
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ RedeclarableTemplateDecl *getFirstDeclaration() {
+ return getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ const RedeclarableTemplateDecl *getFirstDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
+ }
+
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ RedeclarableTemplateDecl *getMostRecentDeclaration() {
+ return getCommonPtr()->Latest;
+ }
+
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
+ }
+
+ /// \brief Determines whether this template was a specialization of a
+ /// member template.
+ ///
+ /// In the following example, the function template \c X<int>::f and the
+ /// member template \c X<int>::Inner are member specializations.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> void f(T, U);
+ /// template<typename U> struct Inner;
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// void X<int>::f(int, T);
+ /// template<> template<typename T>
+ /// struct X<int>::Inner { /* ... */ };
+ /// \endcode
+ bool isMemberSpecialization() {
+ return getCommonPtr()->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ getCommonPtr()->InstantiatedFromMember.setInt(true);
+ }
+
+ /// \brief Retrieve the previous declaration of this template, or
+ /// NULL if no such declaration exists.
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return getInstantiatedFromMemberTemplateImpl();
+ }
+
+ virtual RedeclarableTemplateDecl *getNextRedeclaration();
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+template <class decl_type>
+class RedeclarableTemplate {
+ RedeclarableTemplateDecl *thisDecl() {
+ return static_cast<decl_type*>(this);
+ }
+
+public:
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ decl_type *getPreviousDeclaration() {
+ return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const decl_type *getPreviousDeclaration() const {
+ return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
+ }
+
+ /// \brief Set the previous declaration of this function template.
+ void setPreviousDeclaration(decl_type *Prev) {
+ thisDecl()->setPreviousDeclarationImpl(Prev);
+ }
+
+ decl_type *getCanonicalDecl() {
+ return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
+ }
+
+ const decl_type *getCanonicalDecl() const {
+ return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the member template that this template was instantiated
+ /// from.
+ ///
+ /// This routine will return non-NULL for member templates of
+ /// class templates. For example, given:
+ ///
+ /// \code
+ /// template <typename T>
+ /// struct X {
+ /// template <typename U> void f();
+ /// template <typename U> struct A {};
+ /// };
+ /// \endcode
+ ///
+ /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
+ /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
+ /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
+ /// ClassTemplateDecl).
+ ///
+ /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
+ /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
+ /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
+ ///
+ /// \returns NULL if this is not an instantiation of a member template.
+ decl_type *getInstantiatedFromMemberTemplate() {
+ return static_cast<decl_type*>(
+ thisDecl()->getInstantiatedFromMemberTemplateImpl());
+ }
+
+ void setInstantiatedFromMemberTemplate(decl_type *TD) {
+ thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
+ }
+};
+
+template <> struct RedeclarableTemplateDecl::
+SpecEntryTraits<FunctionTemplateSpecializationInfo> {
+ typedef FunctionDecl DeclType;
+
+ static DeclType *
+ getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) {
+ return I->Function->getMostRecentDeclaration();
+ }
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<FunctionTemplateDecl> {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
+
+ /// \brief Data that is common to all of the declarations of a given
+ /// function template.
+ struct Common : CommonBase {
+ /// \brief The function template specializations for this function
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ };
+
+ FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon(ASTContext &C);
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+ friend class FunctionDecl;
+
+ /// \brief Retrieve the set of function template specializations of this
+ /// function template.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+ return getCommonPtr()->Specializations;
+ }
+
+public:
+ /// Get the underlying function declaration of the template.
+ FunctionDecl *getTemplatedDecl() const {
+ return static_cast<FunctionDecl*>(TemplatedDecl);
+ }
+
+ /// Returns whether this template declaration defines the primary
+ /// pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ FunctionDecl *findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos);
+
+ FunctionTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const FunctionTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ FunctionTemplateDecl *getPreviousDeclaration() {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const FunctionTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
+ }
+
+ typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ /// Create a template function node.
+ static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl);
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == FunctionTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Template Parameters
+//===----------------------------------------------------------------------===//
+
+/// The TemplateParmPosition class defines the position of a template parameter
+/// within a template parameter list. Because template parameter can be listed
+/// sequentially for out-of-line template members, each template parameter is
+/// given a Depth - the nesting of template parameter scopes - and a Position -
+/// the occurrence within the parameter list.
+/// This class is inheritedly privately by different kinds of template
+/// parameters and is not part of the Decl hierarchy. Just a facility.
+class TemplateParmPosition {
+protected:
+ // FIXME: This should probably never be called, but it's here as
+ TemplateParmPosition()
+ : Depth(0), Position(0)
+ { /* assert(0 && "Cannot create positionless template parameter"); */ }
+
+ TemplateParmPosition(unsigned D, unsigned P)
+ : Depth(D), Position(P)
+ { }
+
+ // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
+ // position? Maybe?
+ unsigned Depth;
+ unsigned Position;
+
+public:
+ /// Get the nesting depth of the template parameter.
+ unsigned getDepth() const { return Depth; }
+ void setDepth(unsigned D) { Depth = D; }
+
+ /// Get the position of the template parameter within its parameter list.
+ unsigned getPosition() const { return Position; }
+ void setPosition(unsigned P) { Position = P; }
+
+ /// Get the index of the template parameter within its parameter list.
+ unsigned getIndex() const { return Position; }
+};
+
+/// TemplateTypeParmDecl - Declaration of a template type parameter,
+/// e.g., "T" in
+/// @code
+/// template<typename T> class vector;
+/// @endcode
+class TemplateTypeParmDecl : public TypeDecl {
+ /// \brief Whether this template type parameter was declaration with
+ /// the 'typename' keyword. If false, it was declared with the
+ /// 'class' keyword.
+ bool Typename : 1;
+
+ /// \brief Whether this template type parameter inherited its
+ /// default argument.
+ bool InheritedDefault : 1;
+
+ /// \brief Whether this is a parameter pack.
+ bool ParameterPack : 1;
+
+ /// \brief The default template argument, if any.
+ TypeSourceInfo *DefaultArgument;
+
+ TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ bool Typename, QualType Type, bool ParameterPack)
+ : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
+ InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
+ TypeForDecl = Type.getTypePtrOrNull();
+ }
+
+public:
+ static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, bool Typename,
+ bool ParameterPack);
+ static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty);
+
+ /// \brief Whether this template type parameter was declared with
+ /// the 'typename' keyword. If not, it was declared with the 'class'
+ /// keyword.
+ bool wasDeclaredWithTypename() const { return Typename; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument != 0; }
+
+ /// \brief Retrieve the default argument, if any.
+ QualType getDefaultArgument() const { return DefaultArgument->getType(); }
+
+ /// \brief Retrieves the default argument's source information, if any.
+ TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
+
+ /// \brief Retrieves the location of the default argument declaration.
+ SourceLocation getDefaultArgumentLoc() const;
+
+ /// \brief Determines whether the default argument was inherited
+ /// from a previous declaration of this template.
+ bool defaultArgumentWasInherited() const { return InheritedDefault; }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) {
+ DefaultArgument = DefArg;
+ InheritedDefault = Inherited;
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgument = 0;
+ InheritedDefault = false;
+ }
+
+ /// \brief Set whether this template type parameter was declared with
+ /// the 'typename' or 'class' keyword.
+ void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
+
+ /// \brief Set whether this is a parameter pack.
+ void setParameterPack(bool isParamPack) { ParameterPack = isParamPack; }
+
+ /// \brief Retrieve the depth of the template parameter.
+ unsigned getDepth() const;
+
+ /// \brief Retrieve the index of the template parameter.
+ unsigned getIndex() const;
+
+ /// \brief Returns whether this is a parameter pack.
+ bool isParameterPack() const { return ParameterPack; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TemplateTypeParmDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == TemplateTypeParm; }
+};
+
+/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
+/// e.g., "Size" in
+/// @code
+/// template<int Size> class array { };
+/// @endcode
+class NonTypeTemplateParmDecl
+ : public DeclaratorDecl, protected TemplateParmPosition {
+ /// \brief The default template argument, if any, and whether or not
+ /// it was inherited.
+ llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
+
+ // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
+ // down here to save memory.
+
+ /// \brief Whether this non-type template parameter is a parameter pack.
+ bool ParameterPack;
+
+ /// \brief Whether this non-type template parameter is an "expanded"
+ /// parameter pack, meaning that its type is a pack expansion and we
+ /// already know the set of types that expansion expands to.
+ bool ExpandedParameterPack;
+
+ /// \brief The number of types in an expanded parameter pack.
+ unsigned NumExpandedTypes;
+
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ bool ParameterPack, TypeSourceInfo *TInfo)
+ : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
+ TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+ ParameterPack(ParameterPack), ExpandedParameterPack(false),
+ NumExpandedTypes(0)
+ { }
+
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes,
+ unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
+
+ friend class ASTDeclReader;
+
+public:
+ static NonTypeTemplateParmDecl *
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack,
+ TypeSourceInfo *TInfo);
+
+ static 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);
+
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::setDepth;
+ using TemplateParmPosition::getPosition;
+ using TemplateParmPosition::setPosition;
+ using TemplateParmPosition::getIndex;
+
+ SourceLocation getInnerLocStart() const;
+ SourceRange getSourceRange() const;
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const {
+ return DefaultArgumentAndInherited.getPointer() != 0;
+ }
+
+ /// \brief Retrieve the default argument, if any.
+ Expr *getDefaultArgument() const {
+ return DefaultArgumentAndInherited.getPointer();
+ }
+
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const;
+
+ /// \brief Determines whether the default argument was inherited
+ /// from a previous declaration of this template.
+ bool defaultArgumentWasInherited() const {
+ return DefaultArgumentAndInherited.getInt();
+ }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(Expr *DefArg, bool Inherited) {
+ DefaultArgumentAndInherited.setPointer(DefArg);
+ DefaultArgumentAndInherited.setInt(Inherited);
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgumentAndInherited.setPointer(0);
+ DefaultArgumentAndInherited.setInt(false);
+ }
+
+ /// \brief Whether this parameter is a non-type template parameter pack.
+ ///
+ /// If the parameter is a parameter pack, the type may be a
+ /// \c PackExpansionType. In the following example, the \c Dims parameter
+ /// is a parameter pack (whose type is 'unsigned').
+ ///
+ /// \code
+ /// template<typename T, unsigned ...Dims> struct multi_array;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
+ /// \brief Whether this parameter is a non-type template parameter pack
+ /// that has different types at different positions.
+ ///
+ /// A parameter pack is an expanded parameter pack when the original
+ /// parameter pack's type was itself a pack expansion, and that expansion
+ /// has already been expanded. For example, given:
+ ///
+ /// \code
+ /// template<typename ...Types>
+ /// struct X {
+ /// template<Types ...Values>
+ /// struct Y { /* ... */ };
+ /// };
+ /// \endcode
+ ///
+ /// The parameter pack \c Values has a \c PackExpansionType as its type,
+ /// which expands \c Types. When \c Types is supplied with template arguments
+ /// by instantiating \c X, the instantiation of \c Values becomes an
+ /// expanded parameter pack. For example, instantiating
+ /// \c X<int, unsigned int> results in \c Values being an expanded parameter
+ /// pack with expansion types \c int and \c unsigned int.
+ ///
+ /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions
+ /// return the expansion types.
+ bool isExpandedParameterPack() const { return ExpandedParameterPack; }
+
+ /// \brief Retrieves the number of expansion types in an expanded parameter pack.
+ unsigned getNumExpansionTypes() const {
+ assert(ExpandedParameterPack && "Not an expansion parameter pack");
+ return NumExpandedTypes;
+ }
+
+ /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// pack.
+ QualType getExpansionType(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
+ }
+
+ /// \brief Retrieve a particular expansion type source info within an
+ /// expanded parameter pack.
+ TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
+ assert(I < NumExpandedTypes && "Out-of-range expansion type index");
+ void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
+ return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
+};
+
+/// TemplateTemplateParmDecl - Declares a template template parameter,
+/// e.g., "T" in
+/// @code
+/// template <template <typename> class T> class container { };
+/// @endcode
+/// A template template parameter is a TemplateDecl because it defines the
+/// name of a template and the template parameters allowable for substitution.
+class TemplateTemplateParmDecl
+ : public TemplateDecl, protected TemplateParmPosition {
+
+ /// DefaultArgument - The default template argument, if any.
+ TemplateArgumentLoc DefaultArgument;
+ /// Whether or not the default argument was inherited.
+ bool DefaultArgumentWasInherited;
+
+ /// \brief Whether this parameter is a parameter pack.
+ bool ParameterPack;
+
+ TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+ unsigned D, unsigned P, bool ParameterPack,
+ IdentifierInfo *Id, TemplateParameterList *Params)
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), DefaultArgument(),
+ DefaultArgumentWasInherited(false), ParameterPack(ParameterPack)
+ { }
+
+public:
+ static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D,
+ unsigned P, bool ParameterPack,
+ IdentifierInfo *Id,
+ TemplateParameterList *Params);
+
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::getPosition;
+ using TemplateParmPosition::getIndex;
+
+ /// \brief Whether this template template parameter is a template
+ /// parameter pack.
+ ///
+ /// \code
+ /// template<template <class T> ...MetaFunctions> struct Apply;
+ /// \endcode
+ bool isParameterPack() const { return ParameterPack; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const {
+ return !DefaultArgument.getArgument().isNull();
+ }
+
+ /// \brief Retrieve the default argument, if any.
+ const TemplateArgumentLoc &getDefaultArgument() const {
+ return DefaultArgument;
+ }
+
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const;
+
+ /// \brief Determines whether the default argument was inherited
+ /// from a previous declaration of this template.
+ bool defaultArgumentWasInherited() const {
+ return DefaultArgumentWasInherited;
+ }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(const TemplateArgumentLoc &DefArg, bool Inherited) {
+ DefaultArgument = DefArg;
+ DefaultArgumentWasInherited = Inherited;
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgument = TemplateArgumentLoc();
+ DefaultArgumentWasInherited = false;
+ }
+
+ SourceRange getSourceRange() const {
+ SourceLocation End = getLocation();
+ if (hasDefaultArgument() && !defaultArgumentWasInherited())
+ End = getDefaultArgument().getSourceRange().getEnd();
+ return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a class template specialization, which refers to
+/// a class template with a given set of template arguments.
+///
+/// Class template specializations represent both explicit
+/// specialization of class templates, as in the example below, and
+/// implicit instantiations of class templates.
+///
+/// \code
+/// template<typename T> class array;
+///
+/// template<>
+/// class array<bool> { }; // class template specialization array<bool>
+/// \endcode
+class ClassTemplateSpecializationDecl
+ : public CXXRecordDecl, public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a class template
+ /// specialization that was instantiated from a class template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The class template partial specialization from which this
+ /// class template specialization was instantiated.
+ ClassTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the class template
+ /// partial specialization itself.
+ TemplateArgumentList *TemplateArgs;
+ };
+
+ /// \brief The template that this specialization specializes
+ llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
+ SpecializedTemplate;
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ struct ExplicitSpecializationInfo {
+ /// \brief The type-as-written.
+ TypeSourceInfo *TypeAsWritten;
+ /// \brief The location of the extern keyword.
+ SourceLocation ExternLoc;
+ /// \brief The location of the template keyword.
+ SourceLocation TemplateKeywordLoc;
+
+ ExplicitSpecializationInfo()
+ : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+ };
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ /// Does not apply to implicit specializations.
+ ExplicitSpecializationInfo *ExplicitInfo;
+
+ /// \brief The template arguments used to describe this specialization.
+ TemplateArgumentList *TemplateArgs;
+
+ /// \brief The point where this template was instantiated (if any)
+ SourceLocation PointOfInstantiation;
+
+ /// \brief The kind of specialization this declaration refers to.
+ /// Really a value of type TemplateSpecializationKind.
+ unsigned SpecializationKind : 3;
+
+protected:
+ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
+ DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl);
+
+ explicit ClassTemplateSpecializationDecl(Kind DK);
+
+public:
+ static ClassTemplateSpecializationDecl *
+ Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl);
+ static ClassTemplateSpecializationDecl *
+ Create(ASTContext &Context, EmptyShell Empty);
+
+ virtual void getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
+ ClassTemplateSpecializationDecl *getMostRecentDeclaration() {
+ CXXRecordDecl *Recent
+ = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration());
+ if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ // FIXME: Does injected class name need to be in the redeclarations chain?
+ assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration());
+ Recent = Recent->getPreviousDeclaration();
+ }
+ return cast<ClassTemplateSpecializationDecl>(Recent);
+ }
+
+ /// \brief Retrieve the template that this specialization specializes.
+ ClassTemplateDecl *getSpecializedTemplate() const;
+
+ /// \brief Retrieve the template arguments of the class template
+ /// specialization.
+ const TemplateArgumentList &getTemplateArgs() const {
+ return *TemplateArgs;
+ }
+
+ /// \brief Determine the kind of specialization that this
+ /// declaration represents.
+ TemplateSpecializationKind getSpecializationKind() const {
+ return static_cast<TemplateSpecializationKind>(SpecializationKind);
+ }
+
+ void setSpecializationKind(TemplateSpecializationKind TSK) {
+ SpecializationKind = TSK;
+ }
+
+ /// \brief Get the point of instantiation (if any), or null if none.
+ SourceLocation getPointOfInstantiation() const {
+ return PointOfInstantiation;
+ }
+
+ void setPointOfInstantiation(SourceLocation Loc) {
+ assert(Loc.isValid() && "point of instantiation must be valid!");
+ PointOfInstantiation = Loc;
+ }
+
+ /// \brief If this class template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// class template or class template partial specialization from which it
+ /// was instantiated.
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ return llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>();
+
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization;
+
+ return const_cast<ClassTemplateDecl*>(
+ SpecializedTemplate.get<ClassTemplateDecl*>());
+ }
+
+ /// \brief Retrieve the class template or class template partial
+ /// specialization which was specialized by this.
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ getSpecializedTemplateOrPartial() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization;
+
+ return const_cast<ClassTemplateDecl*>(
+ SpecializedTemplate.get<ClassTemplateDecl*>());
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate members of the class template or class template partial
+ /// specialization from which this class template specialization was
+ /// instantiated.
+ ///
+ /// \returns For a class template specialization instantiated from the primary
+ /// template, this function will return the same template arguments as
+ /// getTemplateArgs(). For a class template specialization instantiated from
+ /// a class template partial specialization, this function will return the
+ /// deduced template arguments for the class template partial specialization
+ /// itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this class template specialization is actually an
+ /// instantiation of the given class template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
+ TemplateArgumentList *TemplateArgs) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
+ "Already set to a class template partial specialization!");
+ SpecializedPartialSpecialization *PS
+ = new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
+ /// \brief Note that this class template specialization is an instantiation
+ /// of the given class template.
+ void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
+ "Previously set to a class template partial specialization!");
+ SpecializedTemplate = TemplDecl;
+ }
+
+ /// \brief Sets the type of this specialization as it was written by
+ /// the user. This will be a class template specialization type.
+ void setTypeAsWritten(TypeSourceInfo *T) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->TypeAsWritten = T;
+ }
+ /// \brief Gets the type of this specialization as it was written by
+ /// the user, if it was so written.
+ TypeSourceInfo *getTypeAsWritten() const {
+ return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+ }
+
+ /// \brief Gets the location of the extern keyword, if present.
+ SourceLocation getExternLoc() const {
+ return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+ }
+ /// \brief Sets the location of the extern keyword.
+ void setExternLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->ExternLoc = Loc;
+ }
+
+ /// \brief Sets the location of the template keyword.
+ void setTemplateKeywordLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->TemplateKeywordLoc = Loc;
+ }
+ /// \brief Gets the location of the template keyword, if present.
+ SourceLocation getTemplateKeywordLoc() const {
+ return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+ }
+
+ SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
+ }
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs, ASTContext &Context) {
+ ID.AddInteger(NumTemplateArgs);
+ for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ TemplateArgs[Arg].Profile(ID, Context);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstClassTemplateSpecialization &&
+ K <= lastClassTemplateSpecialization;
+ }
+
+ static bool classof(const ClassTemplateSpecializationDecl *) {
+ return true;
+ }
+
+ static bool classof(const ClassTemplatePartialSpecializationDecl *) {
+ return true;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class ClassTemplatePartialSpecializationDecl
+ : public ClassTemplateSpecializationDecl {
+ /// \brief The list of template parameters
+ TemplateParameterList* TemplateParams;
+
+ /// \brief The source info for the template arguments as written.
+ /// FIXME: redundant with TypeAsWritten?
+ TemplateArgumentLoc *ArgsAsWritten;
+ unsigned NumArgsAsWritten;
+
+ /// \brief Sequence number indicating when this class template partial
+ /// specialization was added to the set of partial specializations for
+ /// its owning class template.
+ unsigned SequenceNumber;
+
+ /// \brief The class template partial specialization from which this
+ /// class template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this class template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
+ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
+ DeclContext *DC, SourceLocation L,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ TemplateArgumentLoc *ArgInfos,
+ unsigned NumArgInfos,
+ ClassTemplatePartialSpecializationDecl *PrevDecl,
+ unsigned SequenceNumber)
+ : ClassTemplateSpecializationDecl(Context,
+ ClassTemplatePartialSpecialization,
+ TK, DC, L, SpecializedTemplate,
+ Args, NumArgs, PrevDecl),
+ TemplateParams(Params), ArgsAsWritten(ArgInfos),
+ NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
+ InstantiatedFromMember(0, false) { }
+
+ ClassTemplatePartialSpecializationDecl()
+ : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization),
+ TemplateParams(0), ArgsAsWritten(0),
+ NumArgsAsWritten(0), SequenceNumber(0),
+ InstantiatedFromMember(0, false) { }
+
+public:
+ static ClassTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const TemplateArgumentListInfo &ArgInfos,
+ QualType CanonInjectedType,
+ ClassTemplatePartialSpecializationDecl *PrevDecl,
+ unsigned SequenceNumber);
+
+ static ClassTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, EmptyShell Empty);
+
+ ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
+ return cast<ClassTemplatePartialSpecializationDecl>(
+ ClassTemplateSpecializationDecl::getMostRecentDeclaration());
+ }
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the template arguments as written.
+ TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// Get the number of template arguments as written.
+ unsigned getNumTemplateArgsAsWritten() const {
+ return NumArgsAsWritten;
+ }
+
+ /// \brief Get the sequence number for this class template partial
+ /// specialization.
+ unsigned getSequenceNumber() const { return SequenceNumber; }
+
+ /// \brief Retrieve the member class template partial specialization from
+ /// which this particular class template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*> { }; // #1
+ /// };
+ ///
+ /// Outer<float>::Inner<int*> ii;
+ /// \endcode
+ ///
+ /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
+ /// end up instantiating the partial specialization
+ /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
+ /// template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this class template partial specialization
+ /// template was a specialization of a member partial specialization.
+ ///
+ /// In the following example, the member template partial specialization
+ /// \c X<int>::Inner<T*> is a member specialization.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> struct Inner;
+ /// template<typename U> struct Inner<U*>;
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// struct X<int>::Inner<T*> { /* ... */ };
+ /// \endcode
+ bool isMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First
+ = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
+ /// Retrieves the injected specialization type for this partial
+ /// specialization. This is not the same as the type-decl-type for
+ /// this partial specialization, which is an InjectedClassNameType.
+ QualType getInjectedSpecializationType() const {
+ assert(getTypeForDecl() && "partial specialization has no type set!");
+ return cast<InjectedClassNameType>(getTypeForDecl())
+ ->getInjectedSpecializationType();
+ }
+
+ // FIXME: Add Profile support!
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == ClassTemplatePartialSpecialization;
+ }
+
+ static bool classof(const ClassTemplatePartialSpecializationDecl *) {
+ return true;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a class template.
+class ClassTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<ClassTemplateDecl> {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
+
+ /// \brief Data that is common to all of the declarations of a given
+ /// class template.
+ struct Common : CommonBase {
+ Common() : LazySpecializations() { }
+
+ /// \brief The class template specializations for this class
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
+
+ /// \brief The class template partial specializations for this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
+ PartialSpecializations;
+
+ /// \brief The injected-class-name type for this class template.
+ QualType InjectedClassNameType;
+
+ /// \brief If non-null, points to an array of specializations (including
+ /// partial specializations) known ownly by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations/
+ /// partial specializations that follow.
+ uint32_t *LazySpecializations;
+ };
+
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations();
+
+ /// \brief Retrieve the set of specializations of this class template.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations();
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ getPartialSpecializations();
+
+ ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon(ASTContext &C);
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// Get the underlying class declarations of the template.
+ CXXRecordDecl *getTemplatedDecl() const {
+ return static_cast<CXXRecordDecl *>(TemplatedDecl);
+ }
+
+ /// Returns whether this template declaration defines the primary
+ /// class pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ /// Create a class template node.
+ static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ ClassTemplateSpecializationDecl *
+ findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
+
+ ClassTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const ClassTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ ClassTemplateDecl *getPreviousDeclaration() {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ const ClassTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
+ }
+
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
+ void *InsertPos);
+
+ /// \brief Return the next partial specialization sequence number.
+ unsigned getNextPartialSpecSequenceNumber() {
+ return getPartialSpecializations().size();
+ }
+
+ /// \brief Retrieve the partial specializations as an ordered list.
+ void getPartialSpecializations(
+ llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
+
+ /// \brief Find a class template partial specialization with the given
+ /// type T.
+ ///
+ /// \param T a dependent type that names a specialization of this class
+ /// template.
+ ///
+ /// \returns the class template partial specialization that exactly matches
+ /// the type \p T, or NULL if no such partial specialization exists.
+ ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
+
+ /// \brief Find a class template partial specialization which was instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member class template partial specialization.
+ ///
+ /// \returns the class template partial specialization which was instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D);
+
+ /// \brief Retrieve the template specialization type of the
+ /// injected-class-name for this class template.
+ ///
+ /// The injected-class-name for a class template \c X is \c
+ /// X<template-args>, where \c template-args is formed from the
+ /// template arguments that correspond to the template parameters of
+ /// \c X. For example:
+ ///
+ /// \code
+ /// template<typename T, int N>
+ /// struct array {
+ /// typedef array this_type; // "array" is equivalent to "array<T, N>"
+ /// };
+ /// \endcode
+ QualType getInjectedClassNameSpecialization();
+
+ typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
+ partial_spec_iterator;
+
+ partial_spec_iterator partial_spec_begin() {
+ return makeSpecIterator(getPartialSpecializations(), false);
+ }
+
+ partial_spec_iterator partial_spec_end() {
+ return makeSpecIterator(getPartialSpecializations(), true);
+ }
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classofKind(Kind K) { return K == ClassTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a friend template. For example:
+///
+/// template <typename T> class A {
+/// friend class MyVector<T>; // not a friend template
+/// template <typename U> friend class B; // not a friend template
+/// template <typename U> friend class Foo<T>::Nested; // friend template
+/// };
+/// NOTE: This class is not currently in use. All of the above
+/// will yield a FriendDecl, not a FriendTemplateDecl.
+class FriendTemplateDecl : public Decl {
+public:
+ typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
+
+private:
+ // The number of template parameters; always non-zero.
+ unsigned NumParams;
+
+ // The parameter list.
+ TemplateParameterList **Params;
+
+ // The declaration that's a friend of this class.
+ FriendUnion Friend;
+
+ // Location of the 'friend' specifier.
+ SourceLocation FriendLoc;
+
+
+ FriendTemplateDecl(DeclContext *DC, SourceLocation Loc,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FriendLoc)
+ : Decl(Decl::FriendTemplate, DC, Loc),
+ NumParams(NParams),
+ Params(Params),
+ Friend(Friend),
+ FriendLoc(FriendLoc)
+ {}
+
+ FriendTemplateDecl(EmptyShell Empty)
+ : Decl(Decl::FriendTemplate, Empty),
+ NumParams(0),
+ Params(0)
+ {}
+
+public:
+ static FriendTemplateDecl *Create(ASTContext &Context,
+ DeclContext *DC, SourceLocation Loc,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FriendLoc);
+
+ static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty);
+
+ /// If this friend declaration names a templated type (or
+ /// a dependent member type of a templated type), return that
+ /// type; otherwise return null.
+ TypeSourceInfo *getFriendType() const {
+ return Friend.dyn_cast<TypeSourceInfo*>();
+ }
+
+ /// If this friend declaration names a templated function (or
+ /// a member function of a templated type), return that type;
+ /// otherwise return null.
+ NamedDecl *getFriendDecl() const {
+ return Friend.dyn_cast<NamedDecl*>();
+ }
+
+ /// Retrieves the location of the 'friend' keyword.
+ SourceLocation getFriendLoc() const {
+ return FriendLoc;
+ }
+
+ TemplateParameterList *getTemplateParameterList(unsigned i) const {
+ assert(i <= NumParams);
+ return Params[i];
+ }
+
+ unsigned getNumTemplateParameters() const {
+ return NumParams;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
+ static bool classof(const FriendTemplateDecl *D) { return true; }
+
+ friend class ASTDeclReader;
+};
+
+/// Implementation of inline functions that require the template declarations
+inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
+ : Function(FTD) { }
+
+} /* end of namespace clang */
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
new file mode 100644
index 0000000..aee1998
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
@@ -0,0 +1,54 @@
+//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- 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 DeclVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLVISITOR_H
+#define LLVM_CLANG_AST_DECLVISITOR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D))
+
+/// \brief A simple visitor class that helps create declaration visitors.
+template<typename ImplClass, typename RetTy=void>
+class DeclVisitor {
+public:
+ RetTy Visit(Decl *D) {
+ switch (D->getKind()) {
+ default: assert(false && "Decl that isn't part of DeclNodes.inc!");
+#define DECL(DERIVED, BASE) \
+ case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+#define DECL(DERIVED, BASE) \
+ RetTy Visit##DERIVED##Decl(DERIVED##Decl *D) { DISPATCH(BASE, BASE); }
+#include "clang/AST/DeclNodes.inc"
+
+ RetTy VisitDecl(Decl *D) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_DECLVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
new file mode 100644
index 0000000..e54719b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
@@ -0,0 +1,567 @@
+//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DeclarationName and DeclarationNameTable classes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
+#define LLVM_CLANG_AST_DECLARATIONNAME_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/Basic/PartialDiagnostic.h"
+
+namespace llvm {
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+ class CXXSpecialName;
+ class CXXOperatorIdName;
+ class CXXLiteralOperatorIdName;
+ class DeclarationNameExtra;
+ class IdentifierInfo;
+ class MultiKeywordSelector;
+ class UsingDirectiveDecl;
+ class TypeSourceInfo;
+
+/// DeclarationName - The name of a declaration. In the common case,
+/// this just stores an IdentifierInfo pointer to a normal
+/// name. However, it also provides encodings for Objective-C
+/// selectors (optimizing zero- and one-argument selectors, which make
+/// up 78% percent of all selectors in Cocoa.h) and special C++ names
+/// for constructors, destructors, and conversion functions.
+class DeclarationName {
+public:
+ /// NameKind - The kind of name this object contains.
+ enum NameKind {
+ Identifier,
+ ObjCZeroArgSelector,
+ ObjCOneArgSelector,
+ ObjCMultiArgSelector,
+ CXXConstructorName,
+ CXXDestructorName,
+ CXXConversionFunctionName,
+ CXXOperatorName,
+ CXXLiteralOperatorName,
+ CXXUsingDirective
+ };
+
+private:
+ /// StoredNameKind - The kind of name that is actually stored in the
+ /// upper bits of the Ptr field. This is only used internally.
+ enum StoredNameKind {
+ StoredIdentifier = 0,
+ StoredObjCZeroArgSelector,
+ StoredObjCOneArgSelector,
+ StoredDeclarationNameExtra,
+ PtrMask = 0x03
+ };
+
+ /// Ptr - The lowest two bits are used to express what kind of name
+ /// we're actually storing, using the values of NameKind. Depending
+ /// on the kind of name this is, the upper bits of Ptr may have one
+ /// of several different meanings:
+ ///
+ /// StoredIdentifier - The name is a normal identifier, and Ptr is
+ /// a normal IdentifierInfo pointer.
+ ///
+ /// StoredObjCZeroArgSelector - The name is an Objective-C
+ /// selector with zero arguments, and Ptr is an IdentifierInfo
+ /// pointer pointing to the selector name.
+ ///
+ /// StoredObjCOneArgSelector - The name is an Objective-C selector
+ /// with one argument, and Ptr is an IdentifierInfo pointer
+ /// pointing to the selector name.
+ ///
+ /// StoredDeclarationNameExtra - Ptr is actually a pointer to a
+ /// DeclarationNameExtra structure, whose first value will tell us
+ /// whether this is an Objective-C selector, C++ operator-id name,
+ /// or special C++ name.
+ uintptr_t Ptr;
+
+ /// getStoredNameKind - Return the kind of object that is stored in
+ /// Ptr.
+ StoredNameKind getStoredNameKind() const {
+ return static_cast<StoredNameKind>(Ptr & PtrMask);
+ }
+
+ /// getExtra - Get the "extra" information associated with this
+ /// multi-argument selector or C++ special name.
+ DeclarationNameExtra *getExtra() const {
+ assert(getStoredNameKind() == StoredDeclarationNameExtra &&
+ "Declaration name does not store an Extra structure");
+ return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
+ }
+
+ /// getAsCXXSpecialName - If the stored pointer is actually a
+ /// CXXSpecialName, returns a pointer to it. Otherwise, returns
+ /// a NULL pointer.
+ CXXSpecialName *getAsCXXSpecialName() const {
+ if (getNameKind() >= CXXConstructorName &&
+ getNameKind() <= CXXConversionFunctionName)
+ return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
+ return 0;
+ }
+
+ /// getAsCXXOperatorIdName
+ CXXOperatorIdName *getAsCXXOperatorIdName() const {
+ if (getNameKind() == CXXOperatorName)
+ return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+ return 0;
+ }
+
+ CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
+ if (getNameKind() == CXXLiteralOperatorName)
+ return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
+ return 0;
+ }
+
+ // Construct a declaration name from the name of a C++ constructor,
+ // destructor, or conversion function.
+ DeclarationName(CXXSpecialName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ // Construct a declaration name from the name of a C++ overloaded
+ // operator.
+ DeclarationName(CXXOperatorIdName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ DeclarationName(CXXLiteralOperatorIdName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ /// Construct a declaration name from a raw pointer.
+ DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
+
+ friend class DeclarationNameTable;
+ friend class NamedDecl;
+
+ /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
+ /// for this name as a void pointer.
+ void *getFETokenInfoAsVoid() const;
+
+public:
+ /// DeclarationName - Used to create an empty selector.
+ DeclarationName() : Ptr(0) { }
+
+ // Construct a declaration name from an IdentifierInfo *.
+ DeclarationName(const IdentifierInfo *II)
+ : Ptr(reinterpret_cast<uintptr_t>(II)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+ }
+
+ // Construct a declaration name from an Objective-C selector.
+ DeclarationName(Selector Sel);
+
+ /// getUsingDirectiveName - Return name for all using-directives.
+ static DeclarationName getUsingDirectiveName();
+
+ // operator bool() - Evaluates true when this declaration name is
+ // non-empty.
+ operator bool() const {
+ return ((Ptr & PtrMask) != 0) ||
+ (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+ }
+
+ /// Predicate functions for querying what type of name this is.
+ bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
+ bool isObjCZeroArgSelector() const {
+ return getStoredNameKind() == StoredObjCZeroArgSelector;
+ }
+ bool isObjCOneArgSelector() const {
+ return getStoredNameKind() == StoredObjCOneArgSelector;
+ }
+
+ /// getNameKind - Determine what kind of name this is.
+ NameKind getNameKind() const;
+
+ /// \brief Determines whether the name itself is dependent, e.g., because it
+ /// involves a C++ type that is itself dependent.
+ ///
+ /// Note that this does not capture all of the notions of "dependent name",
+ /// because an identifier can be a dependent name if it is used as the
+ /// callee in a call expression with dependent arguments.
+ bool isDependentName() const;
+
+ /// getNameAsString - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
+ /// printName - Print the human-readable name to a stream.
+ void printName(llvm::raw_ostream &OS) const;
+
+ /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
+ /// this declaration name, or NULL if this declaration name isn't a
+ /// simple identifier.
+ IdentifierInfo *getAsIdentifierInfo() const {
+ if (isIdentifier())
+ return reinterpret_cast<IdentifierInfo *>(Ptr);
+ return 0;
+ }
+
+ /// getAsOpaqueInteger - Get the representation of this declaration
+ /// name as an opaque integer.
+ uintptr_t getAsOpaqueInteger() const { return Ptr; }
+
+ /// getAsOpaquePtr - Get the representation of this declaration name as
+ /// an opaque pointer.
+ void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
+
+ static DeclarationName getFromOpaquePtr(void *P) {
+ DeclarationName N;
+ N.Ptr = reinterpret_cast<uintptr_t> (P);
+ return N;
+ }
+
+ static DeclarationName getFromOpaqueInteger(uintptr_t P) {
+ DeclarationName N;
+ N.Ptr = P;
+ return N;
+ }
+
+ /// getCXXNameType - If this name is one of the C++ names (of a
+ /// constructor, destructor, or conversion function), return the
+ /// type associated with that name.
+ QualType getCXXNameType() const;
+
+ /// getCXXOverloadedOperator - If this name is the name of an
+ /// overloadable operator in C++ (e.g., @c operator+), retrieve the
+ /// kind of overloaded operator.
+ OverloadedOperatorKind getCXXOverloadedOperator() const;
+
+ /// getCXXLiteralIdentifier - If this name is the name of a literal
+ /// operator, retrieve the identifier associated with it.
+ IdentifierInfo *getCXXLiteralIdentifier() const;
+
+ /// getObjCSelector - Get the Objective-C selector stored in this
+ /// declaration name.
+ Selector getObjCSelector() const;
+
+ /// getFETokenInfo/setFETokenInfo - The language front-end is
+ /// allowed to associate arbitrary metadata with some kinds of
+ /// declaration names, including normal identifiers and C++
+ /// constructors, destructors, and conversion functions.
+ template<typename T>
+ T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
+
+ void setFETokenInfo(void *T);
+
+ /// operator== - Determine whether the specified names are identical..
+ friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
+ return LHS.Ptr == RHS.Ptr;
+ }
+
+ /// operator!= - Determine whether the specified names are different.
+ friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
+ return LHS.Ptr != RHS.Ptr;
+ }
+
+ static DeclarationName getEmptyMarker() {
+ return DeclarationName(uintptr_t(-1));
+ }
+
+ static DeclarationName getTombstoneMarker() {
+ return DeclarationName(uintptr_t(-2));
+ }
+
+ static int compare(DeclarationName LHS, DeclarationName RHS);
+
+ void dump() const;
+};
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
+ return DeclarationName::compare(LHS, RHS) < 0;
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
+ return DeclarationName::compare(LHS, RHS) > 0;
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
+ return DeclarationName::compare(LHS, RHS) <= 0;
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
+ return DeclarationName::compare(LHS, RHS) >= 0;
+}
+
+/// DeclarationNameTable - Used to store and retrieve DeclarationName
+/// instances for the various kinds of declaration names, e.g., normal
+/// identifiers, C++ constructor names, etc. This class contains
+/// uniqued versions of each of the C++ special names, which can be
+/// retrieved using its member functions (e.g.,
+/// getCXXConstructorName).
+class DeclarationNameTable {
+ const ASTContext &Ctx;
+ void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
+ CXXOperatorIdName *CXXOperatorNames; // Operator names
+ void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
+
+ DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
+ DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
+
+public:
+ DeclarationNameTable(const ASTContext &C);
+ ~DeclarationNameTable();
+
+ /// getIdentifier - Create a declaration name that is a simple
+ /// identifier.
+ DeclarationName getIdentifier(const IdentifierInfo *ID) {
+ return DeclarationName(ID);
+ }
+
+ /// getCXXConstructorName - Returns the name of a C++ constructor
+ /// for the given Type.
+ DeclarationName getCXXConstructorName(CanQualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXConstructorName,
+ Ty.getUnqualifiedType());
+ }
+
+ /// getCXXDestructorName - Returns the name of a C++ destructor
+ /// for the given Type.
+ DeclarationName getCXXDestructorName(CanQualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXDestructorName,
+ Ty.getUnqualifiedType());
+ }
+
+ /// getCXXConversionFunctionName - Returns the name of a C++
+ /// conversion function for the given Type.
+ DeclarationName getCXXConversionFunctionName(CanQualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
+ }
+
+ /// getCXXSpecialName - Returns a declaration name for special kind
+ /// of C++ name, e.g., for a constructor, destructor, or conversion
+ /// function.
+ DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
+ CanQualType Ty);
+
+ /// getCXXOperatorName - Get the name of the overloadable C++
+ /// operator corresponding to Op.
+ DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
+
+ /// getCXXLiteralOperatorName - Get the name of the literal operator function
+ /// with II as the identifier.
+ DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
+};
+
+/// DeclarationNameLoc - Additional source/type location info
+/// for a declaration name. Needs a DeclarationName in order
+/// to be interpreted correctly.
+struct DeclarationNameLoc {
+ union {
+ // The source location for identifier stored elsewhere.
+ // struct {} Identifier;
+
+ // Type info for constructors, destructors and conversion functions.
+ // Locations (if any) for the tilde (destructor) or operator keyword
+ // (conversion) are stored elsewhere.
+ struct {
+ TypeSourceInfo* TInfo;
+ } NamedType;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned BeginOpNameLoc;
+ unsigned EndOpNameLoc;
+ } CXXOperatorName;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned OpNameLoc;
+ } CXXLiteralOperatorName;
+
+ // struct {} CXXUsingDirective;
+ // struct {} ObjCZeroArgSelector;
+ // struct {} ObjCOneArgSelector;
+ // struct {} ObjCMultiArgSelector;
+ };
+
+ DeclarationNameLoc(DeclarationName Name);
+ // FIXME: this should go away once all DNLocs are properly initialized.
+ DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
+}; // struct DeclarationNameLoc
+
+
+/// DeclarationNameInfo - A collector data type for bundling together
+/// a DeclarationName and the correspnding source/type location info.
+struct DeclarationNameInfo {
+private:
+ /// Name - The declaration name, also encoding name kind.
+ DeclarationName Name;
+ /// Loc - The main source location for the declaration name.
+ SourceLocation NameLoc;
+ /// Info - Further source/type location info for special kinds of names.
+ DeclarationNameLoc LocInfo;
+
+public:
+ // FIXME: remove it.
+ DeclarationNameInfo() {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
+ : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
+ DeclarationNameLoc LocInfo)
+ : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
+
+ /// getName - Returns the embedded declaration name.
+ DeclarationName getName() const { return Name; }
+ /// setName - Sets the embedded declaration name.
+ void setName(DeclarationName N) { Name = N; }
+
+ /// getLoc - Returns the main location of the declaration name.
+ SourceLocation getLoc() const { return NameLoc; }
+ /// setLoc - Sets the main location of the declaration name.
+ void setLoc(SourceLocation L) { NameLoc = L; }
+
+ const DeclarationNameLoc &getInfo() const { return LocInfo; }
+ DeclarationNameLoc &getInfo() { return LocInfo; }
+ void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
+
+ /// getNamedTypeInfo - Returns the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ TypeSourceInfo *getNamedTypeInfo() const {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ return LocInfo.NamedType.TInfo;
+ }
+ /// setNamedTypeInfo - Sets the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ void setNamedTypeInfo(TypeSourceInfo *TInfo) {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ LocInfo.NamedType.TInfo = TInfo;
+ }
+
+ /// getCXXOperatorNameRange - Gets the range of the operator name
+ /// (without the operator keyword). Assumes it is a (non-literal) operator.
+ SourceRange getCXXOperatorNameRange() const {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
+ );
+ }
+ /// setCXXOperatorNameRange - Sets the range of the operator name
+ /// (without the operator keyword). Assumes it is a C++ operator.
+ void setCXXOperatorNameRange(SourceRange R) {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
+ LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
+ }
+
+ /// getCXXLiteralOperatorNameLoc - Returns the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ SourceLocation getCXXLiteralOperatorNameLoc() const {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ return SourceLocation::
+ getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
+ }
+ /// setCXXLiteralOperatorNameLoc - Sets the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
+ }
+
+ /// \brief Determine whether this name contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
+ /// getAsString - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
+ /// printName - Print the human-readable name to a stream.
+ void printName(llvm::raw_ostream &OS) const;
+
+ /// getBeginLoc - Retrieve the location of the first token.
+ SourceLocation getBeginLoc() const { return NameLoc; }
+ /// getEndLoc - Retrieve the location of the last token.
+ SourceLocation getEndLoc() const;
+ /// getSourceRange - The range of the declaration name.
+ SourceRange getSourceRange() const {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+};
+
+/// Insertion operator for diagnostics. This allows sending DeclarationName's
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ DeclarationName N) {
+ DB.AddTaggedVal(N.getAsOpaqueInteger(),
+ Diagnostic::ak_declarationname);
+ return DB;
+}
+
+/// Insertion operator for partial diagnostics. This allows binding
+/// DeclarationName's into a partial diagnostic with <<.
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ DeclarationName N) {
+ PD.AddTaggedVal(N.getAsOpaqueInteger(),
+ Diagnostic::ak_declarationname);
+ return PD;
+}
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ DeclarationNameInfo DNInfo) {
+ DNInfo.printName(OS);
+ return OS;
+}
+
+} // end namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that DeclarationNames can be used as keys
+/// in DenseMap and DenseSets.
+template<>
+struct DenseMapInfo<clang::DeclarationName> {
+ static inline clang::DeclarationName getEmptyKey() {
+ return clang::DeclarationName::getEmptyMarker();
+ }
+
+ static inline clang::DeclarationName getTombstoneKey() {
+ return clang::DeclarationName::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::DeclarationName);
+
+ static inline bool
+ isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <>
+struct isPodLike<clang::DeclarationName> { static const bool value = true; };
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
new file mode 100644
index 0000000..2bbe502
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
@@ -0,0 +1,192 @@
+//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces for diagnostics which may or may
+// fire based on how a template is instantiated.
+//
+// At the moment, the only consumer of this interface is access
+// control.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
+#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
+
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+class ASTContext;
+class CXXRecordDecl;
+class NamedDecl;
+
+/// A dependently-generated diagnostic.
+class DependentDiagnostic {
+public:
+ enum AccessNonce { Access = 0 };
+
+ static DependentDiagnostic *Create(ASTContext &Context,
+ DeclContext *Parent,
+ AccessNonce _,
+ SourceLocation Loc,
+ bool IsMemberAccess,
+ AccessSpecifier AS,
+ NamedDecl *TargetDecl,
+ CXXRecordDecl *NamingClass,
+ QualType BaseObjectType,
+ const PartialDiagnostic &PDiag) {
+ DependentDiagnostic *DD = Create(Context, Parent, PDiag);
+ DD->AccessData.Loc = Loc.getRawEncoding();
+ DD->AccessData.IsMember = IsMemberAccess;
+ DD->AccessData.Access = AS;
+ DD->AccessData.TargetDecl = TargetDecl;
+ DD->AccessData.NamingClass = NamingClass;
+ DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
+ return DD;
+ }
+
+ unsigned getKind() const {
+ return Access;
+ }
+
+ bool isAccessToMember() const {
+ assert(getKind() == Access);
+ return AccessData.IsMember;
+ }
+
+ AccessSpecifier getAccess() const {
+ assert(getKind() == Access);
+ return AccessSpecifier(AccessData.Access);
+ }
+
+ SourceLocation getAccessLoc() const {
+ assert(getKind() == Access);
+ return SourceLocation::getFromRawEncoding(AccessData.Loc);
+ }
+
+ NamedDecl *getAccessTarget() const {
+ assert(getKind() == Access);
+ return AccessData.TargetDecl;
+ }
+
+ NamedDecl *getAccessNamingClass() const {
+ assert(getKind() == Access);
+ return AccessData.NamingClass;
+ }
+
+ QualType getAccessBaseObjectType() const {
+ assert(getKind() == Access);
+ return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
+ }
+
+ const PartialDiagnostic &getDiagnostic() const {
+ return Diag;
+ }
+
+private:
+ DependentDiagnostic(const PartialDiagnostic &PDiag,
+ PartialDiagnostic::Storage *Storage)
+ : Diag(PDiag, Storage) {}
+
+ static DependentDiagnostic *Create(ASTContext &Context,
+ DeclContext *Parent,
+ const PartialDiagnostic &PDiag);
+
+ friend class DependentStoredDeclsMap;
+ friend class DeclContext::ddiag_iterator;
+ DependentDiagnostic *NextDiagnostic;
+
+ PartialDiagnostic Diag;
+
+ union {
+ struct {
+ unsigned Loc;
+ unsigned Access : 2;
+ unsigned IsMember : 1;
+ NamedDecl *TargetDecl;
+ CXXRecordDecl *NamingClass;
+ void *BaseObjectType;
+ } AccessData;
+ };
+};
+
+///
+
+/// An iterator over the dependent diagnostics in a dependent context.
+class DeclContext::ddiag_iterator {
+public:
+ ddiag_iterator() : Ptr(0) {}
+ explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
+
+ typedef DependentDiagnostic *value_type;
+ typedef DependentDiagnostic *reference;
+ typedef DependentDiagnostic *pointer;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ reference operator*() const { return Ptr; }
+
+ ddiag_iterator &operator++() {
+ assert(Ptr && "attempt to increment past end of diag list");
+ Ptr = Ptr->NextDiagnostic;
+ return *this;
+ }
+
+ ddiag_iterator operator++(int) {
+ ddiag_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ bool operator==(ddiag_iterator Other) const {
+ return Ptr == Other.Ptr;
+ }
+
+ bool operator!=(ddiag_iterator Other) const {
+ return Ptr != Other.Ptr;
+ }
+
+ ddiag_iterator &operator+=(difference_type N) {
+ assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
+ while (N--)
+ ++*this;
+ return *this;
+ }
+
+ ddiag_iterator operator+(difference_type N) const {
+ ddiag_iterator tmp = *this;
+ tmp += N;
+ return tmp;
+ }
+
+private:
+ DependentDiagnostic *Ptr;
+};
+
+inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
+ assert(isDependentContext()
+ && "cannot iterate dependent diagnostics of non-dependent context");
+ const DependentStoredDeclsMap *Map
+ = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr);
+
+ if (!Map) return ddiag_iterator();
+ return ddiag_iterator(Map->FirstDiagnostic);
+}
+
+inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
+ return ddiag_iterator();
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
new file mode 100644
index 0000000..035f57c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
@@ -0,0 +1,82 @@
+//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- 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 EvaluatedExprVisitor class template, which visits
+// the potentially-evaluated subexpressions of a potentially-evaluated
+// expression.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+
+namespace clang {
+
+class ASTContext;
+
+/// \begin Given a potentially-evaluated expression, this visitor visits all
+/// of its potentially-evaluated subexpressions, recursively.
+template<typename ImplClass>
+class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
+ ASTContext &Context;
+
+public:
+ explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
+
+ // Expressions that have no potentially-evaluated subexpressions (but may have
+ // other sub-expressions).
+ void VisitDeclRefExpr(DeclRefExpr *E) { }
+ void VisitOffsetOfExpr(OffsetOfExpr *E) { }
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { }
+ void VisitBlockExpr(BlockExpr *E) { }
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
+ void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
+
+ void VisitMemberExpr(MemberExpr *E) {
+ // Only the base matters.
+ return this->Visit(E->getBase());
+ }
+
+ void VisitChooseExpr(ChooseExpr *E) {
+ // Only the selected subexpression matters; the other one is not evaluated.
+ return this->Visit(E->getChosenSubExpr(Context));
+ }
+
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ // Only the actual initializer matters; the designators are all constant
+ // expressions.
+ return this->Visit(E->getInit());
+ }
+
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ // typeid(expression) is potentially evaluated when the argument is
+ // a glvalue of polymorphic type. (C++ 5.2.8p2-3)
+ if (!E->isTypeOperand() && E->Classify(Context).isGLValue())
+ if (const RecordType *Record
+ = E->getExprOperand()->getType()->template getAs<RecordType>())
+ if (cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic())
+ return this->Visit(E->getExprOperand());
+ }
+
+ /// \brief The basis case walks all of the children of the statement or
+ /// expression, assuming they are all potentially evaluated.
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_range C = S->children(); C; ++C)
+ if (*C)
+ this->Visit(*C);
+ }
+};
+
+}
+
+#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
new file mode 100644
index 0000000..a17205c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -0,0 +1,3821 @@
+//===--- Expr.h - Classes for representing expressions ----------*- 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 Expr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPR_H
+#define LLVM_CLANG_AST_EXPR_H
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/ASTVector.h"
+#include "clang/AST/UsuallyTinyPtrVector.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cctype>
+#include <vector>
+
+namespace clang {
+ class ASTContext;
+ class APValue;
+ class Decl;
+ class IdentifierInfo;
+ class ParmVarDecl;
+ class NamedDecl;
+ class ValueDecl;
+ class BlockDecl;
+ class CXXBaseSpecifier;
+ class CXXOperatorCallExpr;
+ class CXXMemberCallExpr;
+ class ObjCPropertyRefExpr;
+ class TemplateArgumentLoc;
+ class TemplateArgumentListInfo;
+ class OpaqueValueExpr;
+
+/// \brief A simple array of base specifiers.
+typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+
+/// Expr - This represents one expression. Note that Expr's are subclasses of
+/// Stmt. This allows an expression to be transparently used any place a Stmt
+/// is required.
+///
+class Expr : public Stmt {
+ QualType TR;
+
+protected:
+ Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD, bool ContainsUnexpandedParameterPack) : Stmt(SC) {
+ ExprBits.TypeDependent = TD;
+ ExprBits.ValueDependent = VD;
+ ExprBits.ValueKind = VK;
+ ExprBits.ObjectKind = OK;
+ ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ setType(T);
+ }
+
+ /// \brief Construct an empty expression.
+ explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+
+public:
+ QualType getType() const { return TR; }
+ void setType(QualType t) {
+ // In C++, the type of an expression is always adjusted so that it
+ // will not have reference type an expression will never have
+ // reference type (C++ [expr]p6). Use
+ // QualType::getNonReferenceType() to retrieve the non-reference
+ // type. Additionally, inspect Expr::isLvalue to determine whether
+ // an expression that is adjusted in this manner should be
+ // considered an lvalue.
+ assert((t.isNull() || !t->isReferenceType()) &&
+ "Expressions can't have reference type");
+
+ TR = t;
+ }
+
+ /// isValueDependent - Determines whether this expression is
+ /// value-dependent (C++ [temp.dep.constexpr]). For example, the
+ /// array bound of "Chars" in the following example is
+ /// value-dependent.
+ /// @code
+ /// template<int Size, char (&Chars)[Size]> struct meta_string;
+ /// @endcode
+ bool isValueDependent() const { return ExprBits.ValueDependent; }
+
+ /// \brief Set whether this expression is value-dependent or not.
+ void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; }
+
+ /// isTypeDependent - Determines whether this expression is
+ /// type-dependent (C++ [temp.dep.expr]), which means that its type
+ /// could change from one template instantiation to the next. For
+ /// example, the expressions "x" and "x + y" are type-dependent in
+ /// the following code, but "y" is not type-dependent:
+ /// @code
+ /// template<typename T>
+ /// void add(T x, int y) {
+ /// x + y;
+ /// }
+ /// @endcode
+ bool isTypeDependent() const { return ExprBits.TypeDependent; }
+
+ /// \brief Set whether this expression is type-dependent or not.
+ void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; }
+
+ /// \brief Whether this expression contains an unexpanded parameter
+ /// pack (for C++0x variadic templates).
+ ///
+ /// Given the following function template:
+ ///
+ /// \code
+ /// template<typename F, typename ...Types>
+ /// void forward(const F &f, Types &&...args) {
+ /// f(static_cast<Types&&>(args)...);
+ /// }
+ /// \endcode
+ ///
+ /// The expressions \c args and \c static_cast<Types&&>(args) both
+ /// contain parameter packs.
+ bool containsUnexpandedParameterPack() const {
+ return ExprBits.ContainsUnexpandedParameterPack;
+ }
+
+ /// \brief Set the bit that describes whether this expression
+ /// contains an unexpanded parameter pack.
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ ExprBits.ContainsUnexpandedParameterPack = PP;
+ }
+
+ /// getExprLoc - Return the preferred location for the arrow when diagnosing
+ /// a problem with a generic expression.
+ SourceLocation getExprLoc() const;
+
+ /// isUnusedResultAWarning - Return true if this immediate expression should
+ /// be warned about if the result is unused. If so, fill in Loc and Ranges
+ /// with location to warn on and the source range[s] to report with the
+ /// warning.
+ bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
+ SourceRange &R2, ASTContext &Ctx) const;
+
+ /// isLValue - True if this expression is an "l-value" according to
+ /// the rules of the current language. C and C++ give somewhat
+ /// different rules for this concept, but in general, the result of
+ /// an l-value expression identifies a specific object whereas the
+ /// result of an r-value expression is a value detached from any
+ /// specific storage.
+ ///
+ /// C++0x divides the concept of "r-value" into pure r-values
+ /// ("pr-values") and so-called expiring values ("x-values"), which
+ /// identify specific objects that can be safely cannibalized for
+ /// their resources. This is an unfortunate abuse of terminology on
+ /// the part of the C++ committee. In Clang, when we say "r-value",
+ /// we generally mean a pr-value.
+ bool isLValue() const { return getValueKind() == VK_LValue; }
+ bool isRValue() const { return getValueKind() == VK_RValue; }
+ bool isXValue() const { return getValueKind() == VK_XValue; }
+ bool isGLValue() const { return getValueKind() != VK_RValue; }
+
+ enum LValueClassification {
+ LV_Valid,
+ LV_NotObjectType,
+ LV_IncompleteVoidType,
+ LV_DuplicateVectorComponents,
+ LV_InvalidExpression,
+ LV_MemberFunction,
+ LV_SubObjCPropertySetting,
+ LV_ClassTemporary
+ };
+ /// Reasons why an expression might not be an l-value.
+ LValueClassification ClassifyLValue(ASTContext &Ctx) const;
+
+ /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
+ /// does not have an incomplete type, does not have a const-qualified type,
+ /// and if it is a structure or union, does not have any member (including,
+ /// recursively, any member or element of all contained aggregates or unions)
+ /// with a const-qualified type.
+ ///
+ /// \param Loc [in] [out] - A source location which *may* be filled
+ /// in with the location of the expression making this a
+ /// non-modifiable lvalue, if specified.
+ enum isModifiableLvalueResult {
+ MLV_Valid,
+ MLV_NotObjectType,
+ MLV_IncompleteVoidType,
+ MLV_DuplicateVectorComponents,
+ MLV_InvalidExpression,
+ MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
+ MLV_IncompleteType,
+ MLV_ConstQualified,
+ MLV_ArrayType,
+ MLV_NotBlockQualified,
+ MLV_ReadonlyProperty,
+ MLV_NoSetterProperty,
+ MLV_MemberFunction,
+ MLV_SubObjCPropertySetting,
+ MLV_ClassTemporary
+ };
+ isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
+ SourceLocation *Loc = 0) const;
+
+ /// \brief The return type of classify(). Represents the C++0x expression
+ /// taxonomy.
+ class Classification {
+ public:
+ /// \brief The various classification results. Most of these mean prvalue.
+ enum Kinds {
+ CL_LValue,
+ CL_XValue,
+ CL_Function, // Functions cannot be lvalues in C.
+ CL_Void, // Void cannot be an lvalue in C.
+ CL_DuplicateVectorComponents, // A vector shuffle with dupes.
+ CL_MemberFunction, // An expression referring to a member function
+ CL_SubObjCPropertySetting,
+ CL_ClassTemporary, // A prvalue of class type
+ CL_PRValue // A prvalue for any other reason, of any other type
+ };
+ /// \brief The results of modification testing.
+ enum ModifiableType {
+ CM_Untested, // testModifiable was false.
+ CM_Modifiable,
+ CM_RValue, // Not modifiable because it's an rvalue
+ CM_Function, // Not modifiable because it's a function; C++ only
+ CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
+ CM_NotBlockQualified, // Not captured in the closure
+ CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
+ CM_ConstQualified,
+ CM_ArrayType,
+ CM_IncompleteType
+ };
+
+ private:
+ friend class Expr;
+
+ unsigned short Kind;
+ unsigned short Modifiable;
+
+ explicit Classification(Kinds k, ModifiableType m)
+ : Kind(k), Modifiable(m)
+ {}
+
+ public:
+ Classification() {}
+
+ Kinds getKind() const { return static_cast<Kinds>(Kind); }
+ ModifiableType getModifiable() const {
+ assert(Modifiable != CM_Untested && "Did not test for modifiability.");
+ return static_cast<ModifiableType>(Modifiable);
+ }
+ bool isLValue() const { return Kind == CL_LValue; }
+ bool isXValue() const { return Kind == CL_XValue; }
+ bool isGLValue() const { return Kind <= CL_XValue; }
+ bool isPRValue() const { return Kind >= CL_Function; }
+ bool isRValue() const { return Kind >= CL_XValue; }
+ bool isModifiable() const { return getModifiable() == CM_Modifiable; }
+
+ /// \brief Create a simple, modifiably lvalue
+ static Classification makeSimpleLValue() {
+ return Classification(CL_LValue, CM_Modifiable);
+ }
+
+ };
+ /// \brief Classify - Classify this expression according to the C++0x
+ /// expression taxonomy.
+ ///
+ /// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the
+ /// old lvalue vs rvalue. This function determines the type of expression this
+ /// is. There are three expression types:
+ /// - lvalues are classical lvalues as in C++03.
+ /// - prvalues are equivalent to rvalues in C++03.
+ /// - xvalues are expressions yielding unnamed rvalue references, e.g. a
+ /// function returning an rvalue reference.
+ /// lvalues and xvalues are collectively referred to as glvalues, while
+ /// prvalues and xvalues together form rvalues.
+ Classification Classify(ASTContext &Ctx) const {
+ return ClassifyImpl(Ctx, 0);
+ }
+
+ /// \brief ClassifyModifiable - Classify this expression according to the
+ /// C++0x expression taxonomy, and see if it is valid on the left side
+ /// of an assignment.
+ ///
+ /// This function extends classify in that it also tests whether the
+ /// expression is modifiable (C99 6.3.2.1p1).
+ /// \param Loc A source location that might be filled with a relevant location
+ /// if the expression is not modifiable.
+ Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{
+ return ClassifyImpl(Ctx, &Loc);
+ }
+
+ /// getValueKindForType - Given a formal return or parameter type,
+ /// give its value kind.
+ static ExprValueKind getValueKindForType(QualType T) {
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ return (isa<LValueReferenceType>(RT)
+ ? VK_LValue
+ : (RT->getPointeeType()->isFunctionType()
+ ? VK_LValue : VK_XValue));
+ return VK_RValue;
+ }
+
+ /// getValueKind - The value kind that this expression produces.
+ ExprValueKind getValueKind() const {
+ return static_cast<ExprValueKind>(ExprBits.ValueKind);
+ }
+
+ /// getObjectKind - The object kind that this expression produces.
+ /// Object kinds are meaningful only for expressions that yield an
+ /// l-value or x-value.
+ ExprObjectKind getObjectKind() const {
+ return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
+ }
+
+ bool isOrdinaryOrBitFieldObject() const {
+ ExprObjectKind OK = getObjectKind();
+ return (OK == OK_Ordinary || OK == OK_BitField);
+ }
+
+ /// setValueKind - Set the value kind produced by this expression.
+ void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
+
+ /// setObjectKind - Set the object kind produced by this expression.
+ void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }
+
+private:
+ Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
+
+public:
+
+ /// \brief If this expression refers to a bit-field, retrieve the
+ /// declaration of that bit-field.
+ FieldDecl *getBitField();
+
+ const FieldDecl *getBitField() const {
+ return const_cast<Expr*>(this)->getBitField();
+ }
+
+ /// \brief If this expression is an l-value for an Objective C
+ /// property, find the underlying property reference expression.
+ const ObjCPropertyRefExpr *getObjCProperty() const;
+
+ /// \brief Returns whether this expression refers to a vector element.
+ bool refersToVectorElement() const;
+
+ /// 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
+ /// C.
+ bool isKnownToHaveBooleanValue() const;
+
+ /// isIntegerConstantExpr - Return true if this expression is a valid integer
+ /// constant expression, and, if so, return its value in Result. If not a
+ /// valid i-c-e, return false and fill in Loc (if specified) with the location
+ /// of the invalid expression.
+ bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
+ SourceLocation *Loc = 0,
+ bool isEvaluated = true) const;
+ bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const {
+ llvm::APSInt X;
+ return isIntegerConstantExpr(X, Ctx, Loc);
+ }
+ /// isConstantInitializer - Returns true if this expression is a constant
+ /// initializer, which can be emitted at compile-time.
+ bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;
+
+ /// EvalResult is a struct with detailed info about an evaluated expression.
+ struct EvalResult {
+ /// Val - This is the value the expression can be folded to.
+ APValue Val;
+
+ /// HasSideEffects - Whether the evaluated expression has side effects.
+ /// For example, (f() && 0) can be folded, but it still has side effects.
+ bool HasSideEffects;
+
+ /// Diag - If the expression is unfoldable, then Diag contains a note
+ /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret
+ /// position for the error, and DiagExpr is the expression that caused
+ /// the error.
+ /// If the expression is foldable, but not an integer constant expression,
+ /// Diag contains a note diagnostic that describes why it isn't an integer
+ /// constant expression. If the expression *is* an integer constant
+ /// expression, then Diag will be zero.
+ unsigned Diag;
+ const Expr *DiagExpr;
+ SourceLocation DiagLoc;
+
+ EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {}
+
+ // isGlobalLValue - Return true if the evaluated lvalue expression
+ // is global.
+ bool isGlobalLValue() const;
+ // hasSideEffects - Return true if the evaluated expression has
+ // side effects.
+ bool hasSideEffects() const {
+ return HasSideEffects;
+ }
+ };
+
+ /// 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 Evaluate(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// EvaluateAsBooleanCondition - Return true if this is a constant
+ /// which we we can fold and convert to a boolean condition using
+ /// any crazy technique that we want to.
+ bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
+
+ /// isEvaluatable - Call Evaluate to see if this expression can be constant
+ /// folded, but discard the result.
+ bool isEvaluatable(const ASTContext &Ctx) const;
+
+ /// HasSideEffects - This routine returns true for all those expressions
+ /// which must be evaluated each time and must not be optimized away
+ /// or evaluated at compile time. Example is a function call, volatile
+ /// variable read.
+ bool HasSideEffects(const ASTContext &Ctx) const;
+
+ /// EvaluateAsInt - Call Evaluate and return the folded integer. This
+ /// must be called on an expression that constant folds to an integer.
+ llvm::APSInt EvaluateAsInt(const ASTContext &Ctx) const;
+
+ /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue
+ /// with link time known address.
+ bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue.
+ bool EvaluateAsAnyLValue(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// \brief Enumeration used to describe the kind of Null pointer constant
+ /// returned from \c isNullPointerConstant().
+ enum NullPointerConstantKind {
+ /// \brief Expression is not a Null pointer constant.
+ NPCK_NotNull = 0,
+
+ /// \brief Expression is a Null pointer constant built from a zero integer.
+ NPCK_ZeroInteger,
+
+ /// \brief Expression is a C++0X nullptr.
+ NPCK_CXX0X_nullptr,
+
+ /// \brief Expression is a GNU-style __null constant.
+ NPCK_GNUNull
+ };
+
+ /// \brief Enumeration used to describe how \c isNullPointerConstant()
+ /// should cope with value-dependent expressions.
+ enum NullPointerConstantValueDependence {
+ /// \brief Specifies that the expression should never be value-dependent.
+ NPC_NeverValueDependent = 0,
+
+ /// \brief Specifies that a value-dependent expression of integral or
+ /// dependent type should be considered a null pointer constant.
+ NPC_ValueDependentIsNull,
+
+ /// \brief Specifies that a value-dependent expression should be considered
+ /// to never be a null pointer constant.
+ NPC_ValueDependentIsNotNull
+ };
+
+ /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
+ /// a Null pointer constant. The return value can further distinguish the
+ /// kind of NULL pointer constant that was detected.
+ NullPointerConstantKind isNullPointerConstant(
+ ASTContext &Ctx,
+ NullPointerConstantValueDependence NPC) const;
+
+ /// isOBJCGCCandidate - Return true if this expression may be used in a read/
+ /// write barrier.
+ bool isOBJCGCCandidate(ASTContext &Ctx) const;
+
+ /// \brief Returns true if this expression is a bound member function.
+ bool isBoundMemberFunction(ASTContext &Ctx) const;
+
+ /// \brief Result type of CanThrow().
+ enum CanThrowResult {
+ CT_Cannot,
+ CT_Dependent,
+ CT_Can
+ };
+ /// \brief Test if this expression, if evaluated, might throw, according to
+ /// the rules of C++ [expr.unary.noexcept].
+ CanThrowResult CanThrow(ASTContext &C) const;
+
+ /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
+ /// its subexpression. If that subexpression is also a ParenExpr,
+ /// then this method recursively returns its subexpression, and so forth.
+ /// Otherwise, the method returns the current Expr.
+ Expr *IgnoreParens();
+
+ /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
+ /// or CastExprs, returning their operand.
+ Expr *IgnoreParenCasts();
+
+ /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any
+ /// ParenExpr or ImplicitCastExprs, returning their operand.
+ Expr *IgnoreParenImpCasts();
+
+ const Expr *IgnoreParenImpCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenImpCasts();
+ }
+
+ /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
+ /// CastExprs that represent lvalue casts, returning their operand.
+ Expr *IgnoreParenLValueCasts();
+
+ const Expr *IgnoreParenLValueCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
+ }
+
+ /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
+ /// value (including ptr->int casts of the same size). Strip off any
+ /// ParenExpr or CastExprs, returning their operand.
+ Expr *IgnoreParenNoopCasts(ASTContext &Ctx);
+
+ /// \brief Determine whether this expression is a default function argument.
+ ///
+ /// Default arguments are implicitly generated in the abstract syntax tree
+ /// by semantic analysis for function calls, object constructions, etc. in
+ /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes;
+ /// this routine also looks through any implicit casts to determine whether
+ /// the expression is a default argument.
+ bool isDefaultArgument() const;
+
+ /// \brief Determine whether the result of this expression is a
+ /// temporary object of the given class type.
+ bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
+
+ const Expr *IgnoreParens() const {
+ return const_cast<Expr*>(this)->IgnoreParens();
+ }
+ const Expr *IgnoreParenCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenCasts();
+ }
+ const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const {
+ return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
+ }
+
+ static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs);
+ static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstExprConstant &&
+ T->getStmtClass() <= lastExprConstant;
+ }
+ static bool classof(const Expr *) { return true; }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Primary Expressions.
+//===----------------------------------------------------------------------===//
+
+/// OpaqueValueExpr - An expression referring to an opaque object of a
+/// fixed type and value class. These don't correspond to concrete
+/// syntax; instead they're used to express operations (usually copy
+/// operations) on values whose source is generally obvious from
+/// context.
+class OpaqueValueExpr : public Expr {
+ friend class ASTStmtReader;
+ Expr *SourceExpr;
+ SourceLocation Loc;
+
+public:
+ OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
+ ExprObjectKind OK = OK_Ordinary)
+ : Expr(OpaqueValueExprClass, T, VK, OK,
+ T->isDependentType(), T->isDependentType(), false),
+ SourceExpr(0), Loc(Loc) {
+ }
+
+ /// Given an expression which invokes a copy constructor --- i.e. a
+ /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
+ /// find the OpaqueValueExpr that's the source of the construction.
+ static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
+
+ explicit OpaqueValueExpr(EmptyShell Empty)
+ : Expr(OpaqueValueExprClass, Empty) { }
+
+ /// \brief Retrieve the location of this expression.
+ SourceLocation getLocation() const { return Loc; }
+
+ SourceRange getSourceRange() const {
+ if (SourceExpr) return SourceExpr->getSourceRange();
+ return Loc;
+ }
+ SourceLocation getExprLoc() const {
+ if (SourceExpr) return SourceExpr->getExprLoc();
+ return Loc;
+ }
+
+ child_range children() { return child_range(); }
+
+ /// The source expression of an opaque value expression is the
+ /// expression which originally generated the value. This is
+ /// provided as a convenience for analyses that don't wish to
+ /// precisely model the execution behavior of the program.
+ ///
+ /// The source expression is typically set when building the
+ /// expression which binds the opaque value expression in the first
+ /// place.
+ Expr *getSourceExpr() const { return SourceExpr; }
+ void setSourceExpr(Expr *e) { SourceExpr = e; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpaqueValueExprClass;
+ }
+ static bool classof(const OpaqueValueExpr *) { return true; }
+};
+
+/// \brief Represents the qualifier that may precede a C++ name, e.g., the
+/// "std::" in "std::sort".
+struct NameQualifier {
+ /// \brief The nested name specifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The source range covered by the nested name specifier.
+ SourceRange Range;
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+struct ExplicitTemplateArgumentList {
+ /// \brief The source location of the left angle bracket ('<');
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>');
+ SourceLocation RAngleLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ /// The actual template arguments (if any) are stored after the
+ /// ExplicitTemplateArgumentList structure.
+ unsigned NumTemplateArgs;
+
+ /// \brief Retrieve the template arguments
+ TemplateArgumentLoc *getTemplateArgs() {
+ return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
+ }
+
+ /// \brief Retrieve the template arguments
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
+ }
+
+ void initializeFrom(const TemplateArgumentListInfo &List);
+ void initializeFrom(const TemplateArgumentListInfo &List,
+ bool &Dependent, bool &ContainsUnexpandedParameterPack);
+ void copyInto(TemplateArgumentListInfo &List) const;
+ static std::size_t sizeFor(unsigned NumTemplateArgs);
+ static std::size_t sizeFor(const TemplateArgumentListInfo &List);
+};
+
+/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
+/// enum, etc.
+class DeclRefExpr : public Expr {
+ enum {
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has a C++ nested-name-specifier.
+ HasQualifierFlag = 0x01,
+ // Flag on DecoratedD that specifies when this declaration reference
+ // expression has an explicit C++ template argument list.
+ HasExplicitTemplateArgumentListFlag = 0x02
+ };
+
+ // DecoratedD - The declaration that we are referencing, plus two bits to
+ // indicate whether (1) the declaration's name was explicitly qualified and
+ // (2) the declaration's name was followed by an explicit template
+ // argument list.
+ llvm::PointerIntPair<ValueDecl *, 2> DecoratedD;
+
+ // Loc - The location of the declaration name itself.
+ SourceLocation Loc;
+
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in DecoratedD.
+ DeclarationNameLoc DNLoc;
+
+ /// \brief Retrieve the qualifier that preceded the declaration name, if any.
+ NameQualifier *getNameQualifier() {
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return 0;
+
+ return reinterpret_cast<NameQualifier *> (this + 1);
+ }
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ const NameQualifier *getNameQualifier() const {
+ return const_cast<DeclRefExpr *>(this)->getNameQualifier();
+ }
+
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ ValueDecl *D, SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T, ExprValueKind VK);
+
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T, ExprValueKind VK);
+
+ /// \brief Construct an empty declaration reference expression.
+ explicit DeclRefExpr(EmptyShell Empty)
+ : Expr(DeclRefExprClass, Empty) { }
+
+ /// \brief Computes the type- and value-dependence flags for this
+ /// declaration reference expression.
+ void computeDependence();
+
+public:
+ DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) :
+ Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false),
+ DecoratedD(d, 0), Loc(l) {
+ computeDependence();
+ }
+
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ SourceLocation NameLoc,
+ QualType T, ExprValueKind VK,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
+
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, ExprValueKind VK,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
+
+ /// \brief Construct an empty declaration reference expression.
+ static DeclRefExpr *CreateEmpty(ASTContext &Context,
+ bool HasQualifier,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
+
+ ValueDecl *getDecl() { return DecoratedD.getPointer(); }
+ const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
+ void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
+ }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+ SourceRange getSourceRange() const;
+
+ /// \brief Determine whether this declaration reference was preceded by a
+ /// C++ nested-name-specifier, e.g., \c N::foo.
+ bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; }
+
+ /// \brief If the name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const {
+ if (!hasQualifier())
+ return SourceRange();
+
+ return getNameQualifier()->Range;
+ }
+
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ if (!hasQualifier())
+ return 0;
+
+ return getNameQualifier()->NNS;
+ }
+
+ bool hasExplicitTemplateArgs() const {
+ return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getNameQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!hasExplicitTemplateArgs())
+ return SourceLocation();
+
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!hasExplicitTemplateArgs())
+ return SourceLocation();
+
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclRefExprClass;
+ }
+ static bool classof(const DeclRefExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr : public Expr {
+public:
+ enum IdentType {
+ Func,
+ Function,
+ PrettyFunction,
+ /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
+ /// 'virtual' keyword is omitted for virtual member functions.
+ PrettyFunctionNoVirtual
+ };
+
+private:
+ SourceLocation Loc;
+ IdentType Type;
+public:
+ PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
+ : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
+ type->isDependentType(), type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(l), Type(IT) {}
+
+ /// \brief Construct an empty predefined expression.
+ explicit PredefinedExpr(EmptyShell Empty)
+ : Expr(PredefinedExprClass, Empty) { }
+
+ IdentType getIdentType() const { return Type; }
+ void setIdentType(IdentType IT) { Type = IT; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedExprClass;
+ }
+ static bool classof(const PredefinedExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
+/// leaking memory.
+///
+/// For large floats/integers, APFloat/APInt will allocate memory from the heap
+/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
+/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
+/// the APFloat/APInt values will never get freed. APNumericStorage uses
+/// ASTContext's allocator for memory allocation.
+class APNumericStorage {
+ unsigned BitWidth;
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+
+ bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
+
+ APNumericStorage(const APNumericStorage&); // do not implement
+ APNumericStorage& operator=(const APNumericStorage&); // do not implement
+
+protected:
+ APNumericStorage() : BitWidth(0), VAL(0) { }
+
+ llvm::APInt getIntValue() const {
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ if (NumWords > 1)
+ return llvm::APInt(BitWidth, NumWords, pVal);
+ else
+ return llvm::APInt(BitWidth, VAL);
+ }
+ void setIntValue(ASTContext &C, const llvm::APInt &Val);
+};
+
+class APIntStorage : public APNumericStorage {
+public:
+ llvm::APInt getValue() const { return getIntValue(); }
+ void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
+};
+
+class APFloatStorage : public APNumericStorage {
+public:
+ llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ setIntValue(C, Val.bitcastToAPInt());
+ }
+};
+
+class IntegerLiteral : public Expr {
+ APIntStorage Num;
+ SourceLocation Loc;
+
+ /// \brief Construct an empty integer literal.
+ explicit IntegerLiteral(EmptyShell Empty)
+ : Expr(IntegerLiteralClass, Empty) { }
+
+public:
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ IntegerLiteral(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l)
+ : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {
+ assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+ setValue(C, V);
+ }
+
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l);
+ static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
+
+ llvm::APInt getValue() const { return Num.getValue(); }
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ /// \brief Retrieve the location of the literal.
+ SourceLocation getLocation() const { return Loc; }
+
+ void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); }
+ void setLocation(SourceLocation Location) { Loc = Location; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IntegerLiteralClass;
+ }
+ static bool classof(const IntegerLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+class CharacterLiteral : public Expr {
+ unsigned Value;
+ SourceLocation Loc;
+ bool IsWide;
+public:
+ // type should be IntTy
+ CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
+ : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(value), Loc(l), IsWide(iswide) {
+ }
+
+ /// \brief Construct an empty character literal.
+ CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+
+ SourceLocation getLocation() const { return Loc; }
+ bool isWide() const { return IsWide; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ unsigned getValue() const { return Value; }
+
+ void setLocation(SourceLocation Location) { Loc = Location; }
+ void setWide(bool W) { IsWide = W; }
+ void setValue(unsigned Val) { Value = Val; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CharacterLiteralClass;
+ }
+ static bool classof(const CharacterLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+class FloatingLiteral : public Expr {
+ APFloatStorage Num;
+ bool IsExact : 1;
+ SourceLocation Loc;
+
+ FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
+ QualType Type, SourceLocation L)
+ : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
+ false),
+ IsExact(isexact), Loc(L) {
+ setValue(C, V);
+ }
+
+ /// \brief Construct an empty floating-point literal.
+ explicit FloatingLiteral(EmptyShell Empty)
+ : Expr(FloatingLiteralClass, Empty), IsExact(false) { }
+
+public:
+ static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L);
+ static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
+
+ llvm::APFloat getValue() const { return Num.getValue(); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ Num.setValue(C, Val);
+ }
+
+ bool isExact() const { return IsExact; }
+ void setExact(bool E) { IsExact = E; }
+
+ /// getValueAsApproximateDouble - This returns the value as an inaccurate
+ /// double. Note that this may cause loss of precision, but is useful for
+ /// debugging dumps, etc.
+ double getValueAsApproximateDouble() const;
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FloatingLiteralClass;
+ }
+ static bool classof(const FloatingLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ImaginaryLiteral - We support imaginary integer and floating point literals,
+/// like "1.0i". We represent these as a wrapper around FloatingLiteral and
+/// IntegerLiteral classes. Instances of this class always have a Complex type
+/// whose element type matches the subexpression.
+///
+class ImaginaryLiteral : public Expr {
+ Stmt *Val;
+public:
+ ImaginaryLiteral(Expr *val, QualType Ty)
+ : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Val(val) {}
+
+ /// \brief Build an empty imaginary literal.
+ explicit ImaginaryLiteral(EmptyShell Empty)
+ : Expr(ImaginaryLiteralClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ SourceRange getSourceRange() const { return Val->getSourceRange(); }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImaginaryLiteralClass;
+ }
+ static bool classof(const ImaginaryLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Val, &Val+1); }
+};
+
+/// StringLiteral - This represents a string literal expression, e.g. "foo"
+/// or L"bar" (wide strings). The actual string is returned by getStrData()
+/// is NOT null-terminated, and the length of the string is determined by
+/// calling getByteLength(). The C type for a string is always a
+/// ConstantArrayType. In C++, the char type is const qualified, in C it is
+/// not.
+///
+/// Note that strings in C can be formed by concatenation of multiple string
+/// literal pptokens in translation phase #6. This keeps track of the locations
+/// of each of these pieces.
+///
+/// Strings in C can also be truncated and extended by assigning into arrays,
+/// e.g. with constructs like:
+/// char X[2] = "foobar";
+/// In this case, getByteLength() will return 6, but the string literal will
+/// have type "char[2]".
+class StringLiteral : public Expr {
+ const char *StrData;
+ unsigned ByteLength;
+ bool IsWide;
+ unsigned NumConcatenated;
+ SourceLocation TokLocs[1];
+
+ StringLiteral(QualType Ty) :
+ Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false) {}
+
+public:
+ /// This is the "fully general" constructor that allows representation of
+ /// strings formed from multiple concatenated tokens.
+ static StringLiteral *Create(ASTContext &C, const char *StrData,
+ unsigned ByteLength, bool Wide, QualType Ty,
+ const SourceLocation *Loc, unsigned NumStrs);
+
+ /// Simple constructor for string literals made from one token.
+ static StringLiteral *Create(ASTContext &C, const char *StrData,
+ unsigned ByteLength,
+ bool Wide, QualType Ty, SourceLocation Loc) {
+ return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1);
+ }
+
+ /// \brief Construct an empty string literal.
+ static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
+
+ llvm::StringRef getString() const {
+ return llvm::StringRef(StrData, ByteLength);
+ }
+
+ unsigned getByteLength() const { return ByteLength; }
+
+ /// \brief Sets the string data to the given string data.
+ void setString(ASTContext &C, llvm::StringRef Str);
+
+ bool isWide() const { return IsWide; }
+ void setWide(bool W) { IsWide = W; }
+
+ bool containsNonAsciiOrNull() const {
+ llvm::StringRef Str = getString();
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ if (!isascii(Str[i]) || !Str[i])
+ return true;
+ return false;
+ }
+ /// getNumConcatenated - Get the number of string literal tokens that were
+ /// concatenated in translation phase #6 to form this string literal.
+ unsigned getNumConcatenated() const { return NumConcatenated; }
+
+ SourceLocation getStrTokenLoc(unsigned TokNum) const {
+ assert(TokNum < NumConcatenated && "Invalid tok number");
+ return TokLocs[TokNum];
+ }
+ void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
+ assert(TokNum < NumConcatenated && "Invalid tok number");
+ TokLocs[TokNum] = L;
+ }
+
+ /// 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 getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features,
+ const TargetInfo &Target) const;
+
+ typedef const SourceLocation *tokloc_iterator;
+ tokloc_iterator tokloc_begin() const { return TokLocs; }
+ tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StringLiteralClass;
+ }
+ static bool classof(const StringLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
+/// AST node is only formed if full location information is requested.
+class ParenExpr : public Expr {
+ SourceLocation L, R;
+ Stmt *Val;
+public:
+ ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
+ : Expr(ParenExprClass, val->getType(),
+ val->getValueKind(), val->getObjectKind(),
+ val->isTypeDependent(), val->isValueDependent(),
+ val->containsUnexpandedParameterPack()),
+ L(l), R(r), Val(val) {}
+
+ /// \brief Construct an empty parenthesized expression.
+ explicit ParenExpr(EmptyShell Empty)
+ : Expr(ParenExprClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ SourceRange getSourceRange() const { return SourceRange(L, R); }
+
+ /// \brief Get the location of the left parentheses '('.
+ SourceLocation getLParen() const { return L; }
+ void setLParen(SourceLocation Loc) { L = Loc; }
+
+ /// \brief Get the location of the right parentheses ')'.
+ SourceLocation getRParen() const { return R; }
+ void setRParen(SourceLocation Loc) { R = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenExprClass;
+ }
+ static bool classof(const ParenExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Val, &Val+1); }
+};
+
+
+/// UnaryOperator - This represents the unary-expression's (except sizeof and
+/// alignof), the postinc/postdec operators from postfix-expression, and various
+/// extensions.
+///
+/// Notes on various nodes:
+///
+/// Real/Imag - These return the real/imag part of a complex operand. If
+/// applied to a non-complex value, the former returns its operand and the
+/// later returns zero in the type of the operand.
+///
+class UnaryOperator : public Expr {
+public:
+ typedef UnaryOperatorKind Opcode;
+
+private:
+ unsigned Opc : 5;
+ SourceLocation Loc;
+ Stmt *Val;
+public:
+
+ UnaryOperator(Expr *input, Opcode opc, QualType type,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
+ : Expr(UnaryOperatorClass, type, VK, OK,
+ input->isTypeDependent() || type->isDependentType(),
+ input->isValueDependent(),
+ input->containsUnexpandedParameterPack()),
+ Opc(opc), Loc(l), Val(input) {}
+
+ /// \brief Build an empty unary operator.
+ explicit UnaryOperator(EmptyShell Empty)
+ : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
+
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
+ void setOpcode(Opcode O) { Opc = O; }
+
+ Expr *getSubExpr() const { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ /// getOperatorLoc - Return the location of the operator.
+ SourceLocation getOperatorLoc() const { return Loc; }
+ void setOperatorLoc(SourceLocation L) { Loc = L; }
+
+ /// isPostfix - Return true if this is a postfix operation, like x++.
+ static bool isPostfix(Opcode Op) {
+ return Op == UO_PostInc || Op == UO_PostDec;
+ }
+
+ /// isPrefix - Return true if this is a prefix operation, like --x.
+ static bool isPrefix(Opcode Op) {
+ return Op == UO_PreInc || Op == UO_PreDec;
+ }
+
+ bool isPrefix() const { return isPrefix(getOpcode()); }
+ bool isPostfix() const { return isPostfix(getOpcode()); }
+ bool isIncrementOp() const {
+ return Opc == UO_PreInc || Opc == UO_PostInc;
+ }
+ bool isIncrementDecrementOp() const {
+ return Opc <= UO_PreDec;
+ }
+ static bool isArithmeticOp(Opcode Op) {
+ return Op >= UO_Plus && Op <= UO_LNot;
+ }
+ bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
+
+ /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+ /// corresponds to, e.g. "sizeof" or "[pre]++"
+ static const char *getOpcodeStr(Opcode Op);
+
+ /// \brief Retrieve the unary opcode that corresponds to the given
+ /// overloaded operator.
+ static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);
+
+ /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// the given unary opcode.
+ static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
+
+ SourceRange getSourceRange() const {
+ if (isPostfix())
+ return SourceRange(Val->getLocStart(), Loc);
+ else
+ return SourceRange(Loc, Val->getLocEnd());
+ }
+ SourceLocation getExprLoc() const { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryOperatorClass;
+ }
+ static bool classof(const UnaryOperator *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Val, &Val+1); }
+};
+
+/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
+/// offsetof(record-type, member-designator). For example, given:
+/// @code
+/// struct S {
+/// float f;
+/// double d;
+/// };
+/// struct T {
+/// int i;
+/// struct S s[10];
+/// };
+/// @endcode
+/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
+
+class OffsetOfExpr : public Expr {
+public:
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ class OffsetOfNode {
+ public:
+ /// \brief The kind of offsetof node we have.
+ enum Kind {
+ /// \brief An index into an array.
+ Array = 0x00,
+ /// \brief A field.
+ Field = 0x01,
+ /// \brief A field in a dependent type, known only by its name.
+ Identifier = 0x02,
+ /// \brief An implicit indirection through a C++ base class, when the
+ /// field found is in a base class.
+ Base = 0x03
+ };
+
+ private:
+ enum { MaskBits = 2, Mask = 0x03 };
+
+ /// \brief The source range that covers this part of the designator.
+ SourceRange Range;
+
+ /// \brief The data describing the designator, which comes in three
+ /// different forms, depending on the lower two bits.
+ /// - An unsigned index into the array of Expr*'s stored after this node
+ /// in memory, for [constant-expression] designators.
+ /// - A FieldDecl*, for references to a known field.
+ /// - An IdentifierInfo*, for references to a field with a given name
+ /// when the class type is dependent.
+ /// - A CXXBaseSpecifier*, for references that look at a field in a
+ /// base class.
+ uintptr_t Data;
+
+ public:
+ /// \brief Create an offsetof node that refers to an array element.
+ OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
+ SourceLocation RBracketLoc)
+ : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
+
+ /// \brief Create an offsetof node that refers to a field.
+ OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
+ SourceLocation NameLoc)
+ : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
+
+ /// \brief Create an offsetof node that refers to an identifier.
+ OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
+ SourceLocation NameLoc)
+ : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { }
+
+ /// \brief Create an offsetof node that refers into a C++ base class.
+ explicit OffsetOfNode(const CXXBaseSpecifier *Base)
+ : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
+
+ /// \brief Determine what kind of offsetof node this is.
+ Kind getKind() const {
+ return static_cast<Kind>(Data & Mask);
+ }
+
+ /// \brief For an array element node, returns the index into the array
+ /// of expressions.
+ unsigned getArrayExprIndex() const {
+ assert(getKind() == Array);
+ return Data >> 2;
+ }
+
+ /// \brief For a field offsetof node, returns the field.
+ FieldDecl *getField() const {
+ assert(getKind() == Field);
+ return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief For a field or identifier offsetof node, returns the name of
+ /// the field.
+ IdentifierInfo *getFieldName() const;
+
+ /// \brief For a base class node, returns the base specifier.
+ CXXBaseSpecifier *getBase() const {
+ assert(getKind() == Base);
+ return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief Retrieve the source range that covers this offsetof node.
+ ///
+ /// For an array element node, the source range contains the locations of
+ /// the square brackets. For a field or identifier node, the source range
+ /// contains the location of the period (if there is one) and the
+ /// identifier.
+ SourceRange getRange() const { return Range; }
+ };
+
+private:
+
+ SourceLocation OperatorLoc, RParenLoc;
+ // Base type;
+ TypeSourceInfo *TSInfo;
+ // Number of sub-components (i.e. instances of OffsetOfNode).
+ unsigned NumComps;
+ // Number of sub-expressions (i.e. array subscript expressions).
+ unsigned NumExprs;
+
+ OffsetOfExpr(ASTContext &C, QualType type,
+ SourceLocation OperatorLoc, TypeSourceInfo *tsi,
+ OffsetOfNode* compsPtr, unsigned numComps,
+ Expr** exprsPtr, unsigned numExprs,
+ SourceLocation RParenLoc);
+
+ explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
+ : Expr(OffsetOfExprClass, EmptyShell()),
+ TSInfo(0), NumComps(numComps), NumExprs(numExprs) {}
+
+public:
+
+ static OffsetOfExpr *Create(ASTContext &C, QualType type,
+ SourceLocation OperatorLoc, TypeSourceInfo *tsi,
+ OffsetOfNode* compsPtr, unsigned numComps,
+ Expr** exprsPtr, unsigned numExprs,
+ SourceLocation RParenLoc);
+
+ static OffsetOfExpr *CreateEmpty(ASTContext &C,
+ unsigned NumComps, unsigned NumExprs);
+
+ /// getOperatorLoc - Return the location of the operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Return the location of the right parentheses.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation R) { RParenLoc = R; }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TSInfo;
+ }
+ void setTypeSourceInfo(TypeSourceInfo *tsi) {
+ TSInfo = tsi;
+ }
+
+ const OffsetOfNode &getComponent(unsigned Idx) {
+ assert(Idx < NumComps && "Subscript out of range");
+ return reinterpret_cast<OffsetOfNode *> (this + 1)[Idx];
+ }
+
+ void setComponent(unsigned Idx, OffsetOfNode ON) {
+ assert(Idx < NumComps && "Subscript out of range");
+ reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
+ }
+
+ unsigned getNumComponents() const {
+ return NumComps;
+ }
+
+ Expr* getIndexExpr(unsigned Idx) {
+ assert(Idx < NumExprs && "Subscript out of range");
+ return reinterpret_cast<Expr **>(
+ reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
+ }
+
+ void setIndexExpr(unsigned Idx, Expr* E) {
+ assert(Idx < NumComps && "Subscript out of range");
+ reinterpret_cast<Expr **>(
+ reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
+ }
+
+ unsigned getNumExpressions() const {
+ return NumExprs;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(OperatorLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OffsetOfExprClass;
+ }
+
+ static bool classof(const OffsetOfExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin =
+ reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
+ + NumComps);
+ return child_range(begin, begin + NumExprs);
+ }
+};
+
+/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
+/// types and expressions.
+class SizeOfAlignOfExpr : public Expr {
+ bool isSizeof : 1; // true if sizeof, false if alignof.
+ bool isType : 1; // true if operand is a type, false if an expression
+ union {
+ TypeSourceInfo *Ty;
+ Stmt *Ex;
+ } Argument;
+ SourceLocation OpLoc, RParenLoc;
+
+public:
+ SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ TInfo->getType()->isDependentType(),
+ TInfo->getType()->containsUnexpandedParameterPack()),
+ isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
+ Argument.Ty = TInfo;
+ }
+
+ SizeOfAlignOfExpr(bool issizeof, Expr *E,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ E->isTypeDependent(),
+ E->containsUnexpandedParameterPack()),
+ isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
+ Argument.Ex = E;
+ }
+
+ /// \brief Construct an empty sizeof/alignof expression.
+ explicit SizeOfAlignOfExpr(EmptyShell Empty)
+ : Expr(SizeOfAlignOfExprClass, Empty) { }
+
+ bool isSizeOf() const { return isSizeof; }
+ void setSizeof(bool S) { isSizeof = S; }
+
+ bool isArgumentType() const { return isType; }
+ QualType getArgumentType() const {
+ return getArgumentTypeInfo()->getType();
+ }
+ TypeSourceInfo *getArgumentTypeInfo() const {
+ assert(isArgumentType() && "calling getArgumentType() when arg is expr");
+ return Argument.Ty;
+ }
+ Expr *getArgumentExpr() {
+ assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
+ return static_cast<Expr*>(Argument.Ex);
+ }
+ const Expr *getArgumentExpr() const {
+ return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr();
+ }
+
+ void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
+ void setArgument(TypeSourceInfo *TInfo) {
+ Argument.Ty = TInfo;
+ isType = true;
+ }
+
+ /// Gets the argument type, or the type of the argument expression, whichever
+ /// is appropriate.
+ QualType getTypeOfArgument() const {
+ return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
+ }
+
+ SourceLocation getOperatorLoc() const { return OpLoc; }
+ void setOperatorLoc(SourceLocation L) { OpLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(OpLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfAlignOfExprClass;
+ }
+ static bool classof(const SizeOfAlignOfExpr *) { return true; }
+
+ // Iterators
+ child_range children();
+};
+
+//===----------------------------------------------------------------------===//
+// Postfix Operators.
+//===----------------------------------------------------------------------===//
+
+/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
+class ArraySubscriptExpr : public Expr {
+ enum { LHS, RHS, END_EXPR=2 };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation RBracketLoc;
+public:
+ ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation rbracketloc)
+ : Expr(ArraySubscriptExprClass, t, VK, OK,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ RBracketLoc(rbracketloc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Create an empty array subscript expression.
+ explicit ArraySubscriptExpr(EmptyShell Shell)
+ : Expr(ArraySubscriptExprClass, Shell) { }
+
+ /// An array access can be written A[4] or 4[A] (both are equivalent).
+ /// - getBase() and getIdx() always present the normalized view: A[4].
+ /// In this case getBase() returns "A" and getIdx() returns "4".
+ /// - getLHS() and getRHS() present the syntactic view. e.g. for
+ /// 4[A] getLHS() returns "4".
+ /// Note: Because vector element access is also written A[4] we must
+ /// predicate the format conversion in getBase and getIdx only on the
+ /// the type of the RHS, as it is possible for the LHS to be a vector of
+ /// integer type
+ Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); }
+ const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+
+ Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
+ const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ Expr *getBase() {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ }
+
+ const Expr *getBase() const {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ }
+
+ Expr *getIdx() {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ }
+
+ const Expr *getIdx() const {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getLHS()->getLocStart(), RBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySubscriptExprClass;
+ }
+ static bool classof(const ArraySubscriptExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+
+/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
+/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
+/// while its subclasses may represent alternative syntax that (semantically)
+/// results in a function call. For example, CXXOperatorCallExpr is
+/// a subclass for overloaded operator calls that use operator syntax, e.g.,
+/// "str1 + str2" to resolve to a function call.
+class CallExpr : public Expr {
+ enum { FN=0, PREARGS_START=1 };
+ Stmt **SubExprs;
+ unsigned NumArgs;
+ SourceLocation RParenLoc;
+
+protected:
+ // These versions of the constructor are for derived classes.
+ CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
+ Expr **args, unsigned numargs, QualType t, ExprValueKind VK,
+ SourceLocation rparenloc);
+ CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty);
+
+ Stmt *getPreArg(unsigned i) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ const Stmt *getPreArg(unsigned i) const {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ return SubExprs[PREARGS_START+i];
+ }
+ void setPreArg(unsigned i, Stmt *PreArg) {
+ assert(i < getNumPreArgs() && "Prearg access out of range!");
+ SubExprs[PREARGS_START+i] = PreArg;
+ }
+
+ unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
+
+public:
+ CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
+ ExprValueKind VK, SourceLocation rparenloc);
+
+ /// \brief Build an empty call expression.
+ CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
+
+ const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
+ Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
+ void setCallee(Expr *F) { SubExprs[FN] = F; }
+
+ Decl *getCalleeDecl();
+ const Decl *getCalleeDecl() const {
+ return const_cast<CallExpr*>(this)->getCalleeDecl();
+ }
+
+ /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
+ FunctionDecl *getDirectCallee();
+ const FunctionDecl *getDirectCallee() const {
+ return const_cast<CallExpr*>(this)->getDirectCallee();
+ }
+
+ /// getNumArgs - Return the number of actual arguments to this call.
+ ///
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief Retrieve the call arguments.
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
+ }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+ }
+
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
+ }
+
+ /// setNumArgs - This changes the number of arguments present in this call.
+ /// Any orphaned expressions are deleted by this, and any new operands are set
+ /// to null.
+ void setNumArgs(ASTContext& C, unsigned NumArgs);
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
+ arg_iterator arg_end() {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
+ const_arg_iterator arg_begin() const {
+ return SubExprs+PREARGS_START+getNumPreArgs();
+ }
+ const_arg_iterator arg_end() const {
+ return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
+ }
+
+ /// getNumCommas - Return the number of commas that must have been present in
+ /// this function call.
+ unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
+
+ /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
+ /// not, return 0.
+ unsigned isBuiltinCall(const ASTContext &Context) const;
+
+ /// getCallReturnType - Get the return type of the call expr. This is not
+ /// always the type of the expr itself, if the return type is a reference
+ /// type.
+ QualType getCallReturnType() const;
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCallee()->getLocStart(), RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstCallExprConstant &&
+ T->getStmtClass() <= lastCallExprConstant;
+ }
+ static bool classof(const CallExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
+ }
+};
+
+/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
+///
+class MemberExpr : public Expr {
+ /// Extra data stored in some member expressions.
+ struct MemberNameQualifier : public NameQualifier {
+ DeclAccessPair FoundDecl;
+ };
+
+ /// Base - the expression for the base pointer or structure references. In
+ /// X.F, this is "X".
+ Stmt *Base;
+
+ /// MemberDecl - This is the decl being referenced by the field/member name.
+ /// In X.F, this is the decl referenced by F.
+ ValueDecl *MemberDecl;
+
+ /// MemberLoc - This is the location of the member name.
+ SourceLocation MemberLoc;
+
+ /// MemberDNLoc - Provides source/type location info for the
+ /// declaration name embedded in MemberDecl.
+ DeclarationNameLoc MemberDNLoc;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ bool IsArrow : 1;
+
+ /// \brief True if this member expression used a nested-name-specifier to
+ /// refer to the member, e.g., "x->Base::f", or found its member via a using
+ /// declaration. When true, a MemberNameQualifier
+ /// structure is allocated immediately after the MemberExpr.
+ bool HasQualifierOrFoundDecl : 1;
+
+ /// \brief True if this member expression specified a template argument list
+ /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
+ /// structure (and its TemplateArguments) are allocated immediately after
+ /// the MemberExpr or, if the member expression also has a qualifier, after
+ /// the MemberNameQualifier structure.
+ bool HasExplicitTemplateArgumentList : 1;
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ MemberNameQualifier *getMemberQualifier() {
+ assert(HasQualifierOrFoundDecl);
+ return reinterpret_cast<MemberNameQualifier *> (this + 1);
+ }
+
+ /// \brief Retrieve the qualifier that preceded the member name, if any.
+ const MemberNameQualifier *getMemberQualifier() const {
+ return const_cast<MemberExpr *>(this)->getMemberQualifier();
+ }
+
+public:
+ MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
+ const DeclarationNameInfo &NameInfo, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
+ MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
+ assert(memberdecl->getDeclName() == NameInfo.getName());
+ }
+
+ // NOTE: this constructor should be used only when it is known that
+ // the member name can not provide additional syntactic info
+ // (i.e., source locations for C++ operator names or type source info
+ // for constructors, destructors and conversion oeprators).
+ MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
+ SourceLocation l, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK,
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
+ IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
+
+ static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
+ NestedNameSpecifier *qual, SourceRange qualrange,
+ ValueDecl *memberdecl, DeclAccessPair founddecl,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *targs,
+ QualType ty, ExprValueKind VK, ExprObjectKind OK);
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ /// \brief Retrieve the member declaration to which this expression refers.
+ ///
+ /// The returned declaration will either be a FieldDecl or (in C++)
+ /// a CXXMethodDecl.
+ ValueDecl *getMemberDecl() const { return MemberDecl; }
+ void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
+
+ /// \brief Retrieves the declaration found by lookup.
+ DeclAccessPair getFoundDecl() const {
+ if (!HasQualifierOrFoundDecl)
+ return DeclAccessPair::make(getMemberDecl(),
+ getMemberDecl()->getAccess());
+ return getMemberQualifier()->FoundDecl;
+ }
+
+ /// \brief Determines whether this member expression actually had
+ /// a C++ nested-name-specifier prior to the name of the member, e.g.,
+ /// x->Base::foo.
+ bool hasQualifier() const { return getQualifier() != 0; }
+
+ /// \brief If the member name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the member name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const {
+ if (!HasQualifierOrFoundDecl)
+ return SourceRange();
+
+ return getMemberQualifier()->Range;
+ }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const {
+ if (!HasQualifierOrFoundDecl)
+ return 0;
+
+ return getMemberQualifier()->NNS;
+ }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgs() const {
+ return HasExplicitTemplateArgumentList;
+ }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// follow the member template name. This must only be called on an
+ /// expression with explicit template arguments.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(HasExplicitTemplateArgumentList);
+ if (!HasQualifierOrFoundDecl)
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getMemberQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// followed the member template name. This must only be called on
+ /// an expression with explicit template arguments.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!HasExplicitTemplateArgumentList)
+ return 0;
+
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ if (!HasExplicitTemplateArgumentList)
+ return SourceLocation();
+
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ /// \brief Retrieve the member declaration name info.
+ DeclarationNameInfo getMemberNameInfo() const {
+ return DeclarationNameInfo(MemberDecl->getDeclName(),
+ MemberLoc, MemberDNLoc);
+ }
+
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// getMemberLoc - Return the location of the "member", in X->F, it is the
+ /// location of 'F'.
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+
+ SourceRange getSourceRange() const {
+ // If we have an implicit base (like a C++ implicit this),
+ // make sure not to return its location
+ SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
+ ? getRAngleLoc() : getMemberNameInfo().getEndLoc();
+
+ SourceLocation BaseLoc = getBase()->getLocStart();
+ if (BaseLoc.isInvalid())
+ return SourceRange(MemberLoc, EndLoc);
+ return SourceRange(BaseLoc, EndLoc);
+ }
+
+ SourceLocation getExprLoc() const { return MemberLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MemberExprClass;
+ }
+ static bool classof(const MemberExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+
+ friend class ASTReader;
+ friend class ASTStmtWriter;
+};
+
+/// CompoundLiteralExpr - [C99 6.5.2.5]
+///
+class CompoundLiteralExpr : public Expr {
+ /// LParenLoc - If non-null, this is the location of the left paren in a
+ /// compound literal like "(int){4}". This can be null if this is a
+ /// synthesized compound expression.
+ SourceLocation LParenLoc;
+
+ /// The type as written. This can be an incomplete array type, in
+ /// which case the actual expression type will be different.
+ TypeSourceInfo *TInfo;
+ Stmt *Init;
+ bool FileScope;
+public:
+ CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
+ QualType T, ExprValueKind VK, Expr *init, bool fileScope)
+ : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
+ tinfo->getType()->isDependentType(),
+ init->isValueDependent(),
+ init->containsUnexpandedParameterPack()),
+ LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {}
+
+ /// \brief Construct an empty compound literal.
+ explicit CompoundLiteralExpr(EmptyShell Empty)
+ : Expr(CompoundLiteralExprClass, Empty) { }
+
+ const Expr *getInitializer() const { return cast<Expr>(Init); }
+ Expr *getInitializer() { return cast<Expr>(Init); }
+ void setInitializer(Expr *E) { Init = E; }
+
+ bool isFileScope() const { return FileScope; }
+ void setFileScope(bool FS) { FileScope = FS; }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ TypeSourceInfo *getTypeSourceInfo() const { return TInfo; }
+ void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; }
+
+ SourceRange getSourceRange() const {
+ // FIXME: Init should never be null.
+ if (!Init)
+ return SourceRange();
+ if (LParenLoc.isInvalid())
+ return Init->getSourceRange();
+ return SourceRange(LParenLoc, Init->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundLiteralExprClass;
+ }
+ static bool classof(const CompoundLiteralExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Init, &Init+1); }
+};
+
+/// CastExpr - Base class for type casts, including both implicit
+/// casts (ImplicitCastExpr) and explicit casts that have some
+/// representation in the source code (ExplicitCastExpr's derived
+/// classes).
+class CastExpr : public Expr {
+public:
+ typedef clang::CastKind CastKind;
+
+private:
+ Stmt *Op;
+
+ void CheckCastConsistency() const {
+#ifndef NDEBUG
+ switch (getCastKind()) {
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_BaseToDerived:
+ case CK_BaseToDerivedMemberPointer:
+ assert(!path_empty() && "Cast kind should have a base path!");
+ break;
+
+ // These should not have an inheritance path.
+ case CK_BitCast:
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToMemberPointer:
+ case CK_NullToPointer:
+ case CK_ConstructorConversion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_ToVoid:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_ObjCObjectLValueCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+ // fallthrough to check for null base path
+
+ case CK_Dependent:
+ case CK_LValueToRValue:
+ case CK_GetObjCProperty:
+ case CK_NoOp:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_FloatingToBoolean:
+ case CK_MemberPointerToBoolean:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean:
+ case CK_LValueBitCast: // -> bool&
+ case CK_UserDefinedConversion: // operator bool()
+ assert(path_empty() && "Cast kind should not have a base path!");
+ break;
+ }
+#endif
+ }
+
+ const CXXBaseSpecifier * const *path_buffer() const {
+ return const_cast<CastExpr*>(this)->path_buffer();
+ }
+ CXXBaseSpecifier **path_buffer();
+
+protected:
+ CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ const CastKind kind, Expr *op, unsigned BasePathSize) :
+ Expr(SC, ty, VK, OK_Ordinary,
+ // Cast expressions are type-dependent if the type is
+ // dependent (C++ [temp.dep.expr]p3).
+ ty->isDependentType(),
+ // Cast expressions are value-dependent if the type is
+ // dependent or if the subexpression is value-dependent.
+ ty->isDependentType() || (op && op->isValueDependent()),
+ (ty->containsUnexpandedParameterPack() ||
+ op->containsUnexpandedParameterPack())),
+ Op(op) {
+ assert(kind != CK_Invalid && "creating cast with invalid cast kind");
+ CastExprBits.Kind = kind;
+ CastExprBits.BasePathSize = BasePathSize;
+ CheckCastConsistency();
+ }
+
+ /// \brief Construct an empty cast.
+ CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
+ : Expr(SC, Empty) {
+ CastExprBits.BasePathSize = BasePathSize;
+ }
+
+public:
+ CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
+ void setCastKind(CastKind K) { CastExprBits.Kind = K; }
+ const char *getCastKindName() const;
+
+ Expr *getSubExpr() { return cast<Expr>(Op); }
+ const Expr *getSubExpr() const { return cast<Expr>(Op); }
+ void setSubExpr(Expr *E) { Op = E; }
+
+ /// \brief Retrieve the cast subexpression as it was written in the source
+ /// code, looking through any implicit casts or other intermediate nodes
+ /// introduced by semantic analysis.
+ Expr *getSubExprAsWritten();
+ const Expr *getSubExprAsWritten() const {
+ return const_cast<CastExpr *>(this)->getSubExprAsWritten();
+ }
+
+ typedef CXXBaseSpecifier **path_iterator;
+ typedef const CXXBaseSpecifier * const *path_const_iterator;
+ bool path_empty() const { return CastExprBits.BasePathSize == 0; }
+ unsigned path_size() const { return CastExprBits.BasePathSize; }
+ path_iterator path_begin() { return path_buffer(); }
+ path_iterator path_end() { return path_buffer() + path_size(); }
+ path_const_iterator path_begin() const { return path_buffer(); }
+ path_const_iterator path_end() const { return path_buffer() + path_size(); }
+
+ void setCastPath(const CXXCastPath &Path);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstCastExprConstant &&
+ T->getStmtClass() <= lastCastExprConstant;
+ }
+ static bool classof(const CastExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Op, &Op+1); }
+};
+
+/// ImplicitCastExpr - Allows us to explicitly represent implicit type
+/// conversions, which have no direct representation in the original
+/// source code. For example: converting T[]->T*, void f()->void
+/// (*f)(), float->double, short->int, etc.
+///
+/// In C, implicit casts always produce rvalues. However, in C++, an
+/// implicit cast whose result is being bound to a reference will be
+/// an lvalue or xvalue. For example:
+///
+/// @code
+/// class Base { };
+/// class Derived : public Base { };
+/// Derived &&ref();
+/// void f(Derived d) {
+/// Base& b = d; // initializer is an ImplicitCastExpr
+/// // to an lvalue of type Base
+/// Base&& r = ref(); // initializer is an ImplicitCastExpr
+/// // to an xvalue of type Base
+/// }
+/// @endcode
+class ImplicitCastExpr : public CastExpr {
+private:
+ ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
+ unsigned BasePathLength, ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
+ }
+
+ /// \brief Construct an empty implicit cast.
+ explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
+ : CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
+
+public:
+ enum OnStack_t { OnStack };
+ ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
+ ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
+ }
+
+ static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind Cat);
+
+ static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
+
+ SourceRange getSourceRange() const {
+ return getSubExpr()->getSourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitCastExprClass;
+ }
+ static bool classof(const ImplicitCastExpr *) { return true; }
+};
+
+/// ExplicitCastExpr - An explicit cast written in the source
+/// code.
+///
+/// This class is effectively an abstract class, because it provides
+/// the basic representation of an explicitly-written cast without
+/// specifying which kind of cast (C cast, functional cast, static
+/// cast, etc.) was written; specific derived classes represent the
+/// particular style of cast and its location information.
+///
+/// Unlike implicit casts, explicit cast nodes have two different
+/// types: the type that was written into the source code, and the
+/// actual type of the expression as determined by semantic
+/// analysis. These types may differ slightly. For example, in C++ one
+/// can cast to a reference type, which indicates that the resulting
+/// expression will be an lvalue or xvalue. The reference type, however,
+/// will not be used as the type of the expression.
+class ExplicitCastExpr : public CastExpr {
+ /// TInfo - Source type info for the (written) type
+ /// this expression is casting to.
+ TypeSourceInfo *TInfo;
+
+protected:
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
+
+ /// \brief Construct an empty explicit cast.
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : CastExpr(SC, Shell, PathSize) { }
+
+public:
+ /// getTypeInfoAsWritten - Returns the type source info for the type
+ /// that this expression is casting to.
+ TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
+ void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }
+
+ /// getTypeAsWritten - Returns the type that this expression is
+ /// casting to, as written in the source code.
+ QualType getTypeAsWritten() const { return TInfo->getType(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstExplicitCastExprConstant &&
+ T->getStmtClass() <= lastExplicitCastExprConstant;
+ }
+ static bool classof(const ExplicitCastExpr *) { return true; }
+};
+
+/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
+/// cast in C++ (C++ [expr.cast]), which uses the syntax
+/// (Type)expr. For example: @c (int)f.
+class CStyleCastExpr : public ExplicitCastExpr {
+ SourceLocation LPLoc; // the location of the left paren
+ SourceLocation RPLoc; // the location of the right paren
+
+ CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation r)
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
+ writtenTy), LPLoc(l), RPLoc(r) {}
+
+ /// \brief Construct an empty C-style explicit cast.
+ explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+
+public:
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K,
+ Expr *Op, const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation R);
+
+ static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
+
+ SourceLocation getLParenLoc() const { return LPLoc; }
+ void setLParenLoc(SourceLocation L) { LPLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RPLoc; }
+ void setRParenLoc(SourceLocation L) { RPLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CStyleCastExprClass;
+ }
+ static bool classof(const CStyleCastExpr *) { return true; }
+};
+
+/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
+///
+/// This expression node kind describes a builtin binary operation,
+/// such as "x + y" for integer values "x" and "y". The operands will
+/// already have been converted to appropriate types (e.g., by
+/// performing promotions or conversions).
+///
+/// In C++, where operators may be overloaded, a different kind of
+/// expression node (CXXOperatorCallExpr) is used to express the
+/// invocation of an overloaded operator with operator syntax. Within
+/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is
+/// used to store an expression "x + y" depends on the subexpressions
+/// for x and y. If neither x or y is type-dependent, and the "+"
+/// operator resolves to a built-in operation, BinaryOperator will be
+/// used to express the computation (x and y may still be
+/// value-dependent). If either x or y is type-dependent, or if the
+/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will
+/// be used to express the computation.
+class BinaryOperator : public Expr {
+public:
+ typedef BinaryOperatorKind Opcode;
+
+private:
+ unsigned Opc : 6;
+ SourceLocation OpLoc;
+
+ enum { LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+public:
+
+ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc)
+ : Expr(BinaryOperatorClass, ResTy, VK, OK,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ Opc(opc), OpLoc(opLoc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ assert(!isCompoundAssignmentOp() &&
+ "Use ArithAssignBinaryOperator for compound assignments");
+ }
+
+ /// \brief Construct an empty binary operator.
+ explicit BinaryOperator(EmptyShell Empty)
+ : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
+
+ SourceLocation getOperatorLoc() const { return OpLoc; }
+ void setOperatorLoc(SourceLocation L) { OpLoc = L; }
+
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
+ void setOpcode(Opcode O) { Opc = O; }
+
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
+ }
+
+ /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+ /// corresponds to, e.g. "<<=".
+ static const char *getOpcodeStr(Opcode Op);
+
+ const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
+
+ /// \brief Retrieve the binary opcode that corresponds to the given
+ /// overloaded operator.
+ static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
+
+ /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// the given binary opcode.
+ static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
+
+ /// predicates to categorize the respective opcodes.
+ bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
+ bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
+ static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
+ bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
+ static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
+ bool isShiftOp() const { return isShiftOp(getOpcode()); }
+
+ static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
+ bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
+
+ static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
+ bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
+
+ static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
+ bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
+
+ static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
+ bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
+
+ static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
+ bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
+
+ static bool isAssignmentOp(Opcode Opc) {
+ return Opc >= BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }
+
+ static bool isCompoundAssignmentOp(Opcode Opc) {
+ return Opc > BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isCompoundAssignmentOp() const {
+ return isCompoundAssignmentOp(getOpcode());
+ }
+
+ static bool isShiftAssignOp(Opcode Opc) {
+ return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
+ }
+ bool isShiftAssignOp() const {
+ return isShiftAssignOp(getOpcode());
+ }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() >= firstBinaryOperatorConstant &&
+ S->getStmtClass() <= lastBinaryOperatorConstant;
+ }
+ static bool classof(const BinaryOperator *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
+protected:
+ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc, bool dead)
+ : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ Opc(opc), OpLoc(opLoc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ BinaryOperator(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty), Opc(BO_MulAssign) { }
+};
+
+/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
+/// track of the type the operation is performed in. Due to the semantics of
+/// these operators, the operands are promoted, the aritmetic performed, an
+/// implicit conversion back to the result type done, then the assignment takes
+/// place. This captures the intermediate type which the computation is done
+/// in.
+class CompoundAssignOperator : public BinaryOperator {
+ QualType ComputationLHSType;
+ QualType ComputationResultType;
+public:
+ CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
+ ExprValueKind VK, ExprObjectKind OK,
+ QualType CompLHSType, QualType CompResultType,
+ SourceLocation OpLoc)
+ : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true),
+ ComputationLHSType(CompLHSType),
+ ComputationResultType(CompResultType) {
+ assert(isCompoundAssignmentOp() &&
+ "Only should be used for compound assignments");
+ }
+
+ /// \brief Build an empty compound assignment operator expression.
+ explicit CompoundAssignOperator(EmptyShell Empty)
+ : BinaryOperator(CompoundAssignOperatorClass, Empty) { }
+
+ // The two computation types are the type the LHS is converted
+ // to for the computation and the type of the result; the two are
+ // distinct in a few cases (specifically, int+=ptr and ptr-=ptr).
+ QualType getComputationLHSType() const { return ComputationLHSType; }
+ void setComputationLHSType(QualType T) { ComputationLHSType = T; }
+
+ QualType getComputationResultType() const { return ComputationResultType; }
+ void setComputationResultType(QualType T) { ComputationResultType = T; }
+
+ static bool classof(const CompoundAssignOperator *) { return true; }
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == CompoundAssignOperatorClass;
+ }
+};
+
+/// AbstractConditionalOperator - An abstract base class for
+/// ConditionalOperator and BinaryConditionalOperator.
+class AbstractConditionalOperator : public Expr {
+ SourceLocation QuestionLoc, ColonLoc;
+ friend class ASTStmtReader;
+
+protected:
+ AbstractConditionalOperator(StmtClass SC, QualType T,
+ ExprValueKind VK, ExprObjectKind OK,
+ bool TD, bool VD,
+ bool ContainsUnexpandedParameterPack,
+ SourceLocation qloc,
+ SourceLocation cloc)
+ : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack),
+ QuestionLoc(qloc), ColonLoc(cloc) {}
+
+ AbstractConditionalOperator(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) { }
+
+public:
+ // getCond - Return the expression representing the condition for
+ // the ?: operator.
+ Expr *getCond() const;
+
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const;
+
+ // getFalseExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to false. This is
+ // the same as getRHS.
+ Expr *getFalseExpr() const;
+
+ SourceLocation getQuestionLoc() const { return QuestionLoc; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass ||
+ T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const AbstractConditionalOperator *) { return true; }
+};
+
+/// ConditionalOperator - The ?: ternary operator. The GNU "missing
+/// middle" extension is a BinaryConditionalOperator.
+class ConditionalOperator : public AbstractConditionalOperator {
+ enum { COND, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+
+ friend class ASTStmtReader;
+public:
+ ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
+ SourceLocation CLoc, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
+ // FIXME: the type of the conditional operator doesn't
+ // depend on the type of the conditional, but the standard
+ // seems to imply that it could. File a bug!
+ (lhs->isTypeDependent() || rhs->isTypeDependent()),
+ (cond->isValueDependent() || lhs->isValueDependent() ||
+ rhs->isValueDependent()),
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ QLoc, CLoc) {
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Build an empty conditional operator.
+ explicit ConditionalOperator(EmptyShell Empty)
+ : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
+
+ // getCond - Return the expression representing the condition for
+ // the ?: operator.
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+
+ // getTrueExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to true.
+ Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }
+
+ // getFalseExpr - Return the subexpression representing the value of
+ // the expression if the condition evaluates to false. This is
+ // the same as getRHS.
+ Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
+
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass;
+ }
+ static bool classof(const ConditionalOperator *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// BinaryConditionalOperator - The GNU extension to the conditional
+/// operator which allows the middle operand to be omitted.
+///
+/// This is a different expression kind on the assumption that almost
+/// every client ends up needing to know that these are different.
+class BinaryConditionalOperator : public AbstractConditionalOperator {
+ enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS };
+
+ /// - the common condition/left-hand-side expression, which will be
+ /// evaluated as the opaque value
+ /// - the condition, expressed in terms of the opaque value
+ /// - the left-hand-side, expressed in terms of the opaque value
+ /// - the right-hand-side
+ Stmt *SubExprs[NUM_SUBEXPRS];
+ OpaqueValueExpr *OpaqueValue;
+
+ friend class ASTStmtReader;
+public:
+ BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue,
+ Expr *cond, Expr *lhs, Expr *rhs,
+ SourceLocation qloc, SourceLocation cloc,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK,
+ (common->isTypeDependent() || rhs->isTypeDependent()),
+ (common->isValueDependent() || rhs->isValueDependent()),
+ (common->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ qloc, cloc),
+ OpaqueValue(opaqueValue) {
+ SubExprs[COMMON] = common;
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+
+ OpaqueValue->setSourceExpr(common);
+ }
+
+ /// \brief Build an empty conditional operator.
+ explicit BinaryConditionalOperator(EmptyShell Empty)
+ : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }
+
+ /// \brief getCommon - Return the common expression, written to the
+ /// left of the condition. The opaque value will be bound to the
+ /// result of this expression.
+ Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }
+
+ /// \brief getOpaqueValue - Return the opaque value placeholder.
+ OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
+
+ /// \brief getCond - Return the condition expression; this is defined
+ /// in terms of the opaque value.
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+
+ /// \brief getTrueExpr - Return the subexpression which will be
+ /// evaluated if the condition evaluates to true; this is defined
+ /// in terms of the opaque value.
+ Expr *getTrueExpr() const {
+ return cast<Expr>(SubExprs[LHS]);
+ }
+
+ /// \brief getFalseExpr - Return the subexpression which will be
+ /// evaluated if the condnition evaluates to false; this is
+ /// defined in terms of the opaque value.
+ Expr *getFalseExpr() const {
+ return cast<Expr>(SubExprs[RHS]);
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+ static bool classof(const BinaryConditionalOperator *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
+ }
+};
+
+inline Expr *AbstractConditionalOperator::getCond() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getCond();
+ return cast<BinaryConditionalOperator>(this)->getCond();
+}
+
+inline Expr *AbstractConditionalOperator::getTrueExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getTrueExpr();
+ return cast<BinaryConditionalOperator>(this)->getTrueExpr();
+}
+
+inline Expr *AbstractConditionalOperator::getFalseExpr() const {
+ if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
+ return co->getFalseExpr();
+ return cast<BinaryConditionalOperator>(this)->getFalseExpr();
+}
+
+/// AddrLabelExpr - The GNU address of label extension, representing &&label.
+class AddrLabelExpr : public Expr {
+ SourceLocation AmpAmpLoc, LabelLoc;
+ LabelDecl *Label;
+public:
+ AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
+ QualType t)
+ : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false),
+ AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
+
+ /// \brief Build an empty address of a label expression.
+ explicit AddrLabelExpr(EmptyShell Empty)
+ : Expr(AddrLabelExprClass, Empty) { }
+
+ SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
+ void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
+ SourceLocation getLabelLoc() const { return LabelLoc; }
+ void setLabelLoc(SourceLocation L) { LabelLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AmpAmpLoc, LabelLoc);
+ }
+
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *L) { Label = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AddrLabelExprClass;
+ }
+ static bool classof(const AddrLabelExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
+/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
+/// takes the value of the last subexpression.
+///
+/// A StmtExpr is always an r-value; values "returned" out of a
+/// StmtExpr will be copied.
+class StmtExpr : public Expr {
+ Stmt *SubStmt;
+ SourceLocation LParenLoc, RParenLoc;
+public:
+ // FIXME: Does type-dependence need to be computed differently?
+ StmtExpr(CompoundStmt *substmt, QualType T,
+ SourceLocation lp, SourceLocation rp) :
+ Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
+ T->isDependentType(), false, false),
+ SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
+
+ /// \brief Build an empty statement expression.
+ explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
+
+ CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); }
+ const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
+ void setSubStmt(CompoundStmt *S) { SubStmt = S; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LParenLoc, RParenLoc);
+ }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StmtExprClass;
+ }
+ static bool classof(const StmtExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+};
+
+
+/// ShuffleVectorExpr - clang-specific builtin-in function
+/// __builtin_shufflevector.
+/// This AST node represents a operator that does a constant
+/// shuffle, similar to LLVM's shufflevector instruction. It takes
+/// two vectors and a variable number of constant indices,
+/// and returns the appropriately shuffled vector.
+class ShuffleVectorExpr : public Expr {
+ SourceLocation BuiltinLoc, RParenLoc;
+
+ // SubExprs - the list of values passed to the __builtin_shufflevector
+ // function. The first two are vectors, and the rest are constant
+ // indices. The number of values in this list is always
+ // 2+the number of indices in the vector type.
+ Stmt **SubExprs;
+ unsigned NumExprs;
+
+public:
+ ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
+ QualType Type, SourceLocation BLoc,
+ SourceLocation RP);
+
+ /// \brief Build an empty vector-shuffle expression.
+ explicit ShuffleVectorExpr(EmptyShell Empty)
+ : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ShuffleVectorExprClass;
+ }
+ static bool classof(const ShuffleVectorExpr *) { return true; }
+
+ /// getNumSubExprs - Return the size of the SubExprs array. This includes the
+ /// constant expression, the actual arguments passed in, and the function
+ /// pointers.
+ unsigned getNumSubExprs() const { return NumExprs; }
+
+ /// \brief Retrieve the array of expressions.
+ Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
+
+ /// getExpr - Return the Expr at the specified index.
+ Expr *getExpr(unsigned Index) {
+ assert((Index < NumExprs) && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Index]);
+ }
+ const Expr *getExpr(unsigned Index) const {
+ assert((Index < NumExprs) && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Index]);
+ }
+
+ void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs);
+
+ unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) {
+ assert((N < NumExprs - 2) && "Shuffle idx out of range!");
+ return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue();
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
+ }
+};
+
+/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
+/// This AST node is similar to the conditional operator (?:) in C, with
+/// the following exceptions:
+/// - the test expression must be a integer constant expression.
+/// - the expression returned acts like the chosen subexpression in every
+/// visible way: the type is the same as that of the chosen subexpression,
+/// and all predicates (whether it's an l-value, whether it's an integer
+/// constant expression, etc.) return the same result as for the chosen
+/// sub-expression.
+class ChooseExpr : public Expr {
+ enum { COND, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation RP, bool TypeDependent, bool ValueDependent)
+ : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ BuiltinLoc(BLoc), RParenLoc(RP) {
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Build an empty __builtin_choose_expr.
+ explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }
+
+ /// isConditionTrue - Return whether the condition is true (i.e. not
+ /// equal to zero).
+ bool isConditionTrue(const ASTContext &C) const;
+
+ /// getChosenSubExpr - Return the subexpression chosen according to the
+ /// condition.
+ Expr *getChosenSubExpr(const ASTContext &C) const {
+ return isConditionTrue(C) ? getLHS() : getRHS();
+ }
+
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+ void setCond(Expr *E) { SubExprs[COND] = E; }
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ChooseExprClass;
+ }
+ static bool classof(const ChooseExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// GNUNullExpr - Implements the GNU __null extension, which is a name
+/// for a null pointer constant that has integral type (e.g., int or
+/// long) and is the same size and alignment as a pointer. The __null
+/// extension is typically only used by system headers, which define
+/// NULL as __null in C++ rather than using 0 (which is an integer
+/// that may not match the size of a pointer).
+class GNUNullExpr : public Expr {
+ /// TokenLoc - The location of the __null keyword.
+ SourceLocation TokenLoc;
+
+public:
+ GNUNullExpr(QualType Ty, SourceLocation Loc)
+ : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false),
+ TokenLoc(Loc) { }
+
+ /// \brief Build an empty GNU __null expression.
+ explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
+
+ /// getTokenLocation - The location of the __null token.
+ SourceLocation getTokenLocation() const { return TokenLoc; }
+ void setTokenLocation(SourceLocation L) { TokenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TokenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GNUNullExprClass;
+ }
+ static bool classof(const GNUNullExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// VAArgExpr, used for the builtin function __builtin_va_arg.
+class VAArgExpr : public Expr {
+ Stmt *Val;
+ TypeSourceInfo *TInfo;
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t)
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
+ t->isDependentType(), false,
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
+ Val(e), TInfo(TInfo),
+ BuiltinLoc(BLoc),
+ RParenLoc(RPLoc) { }
+
+ /// \brief Create an empty __builtin_va_arg expression.
+ explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == VAArgExprClass;
+ }
+ static bool classof(const VAArgExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Val, &Val+1); }
+};
+
+/// @brief Describes an C or C++ initializer list.
+///
+/// InitListExpr describes an initializer list, which can be used to
+/// initialize objects of different types, including
+/// struct/class/union types, arrays, and vectors. For example:
+///
+/// @code
+/// struct foo x = { 1, { 2, 3 } };
+/// @endcode
+///
+/// Prior to semantic analysis, an initializer list will represent the
+/// initializer list as written by the user, but will have the
+/// placeholder type "void". This initializer list is called the
+/// syntactic form of the initializer, and may contain C99 designated
+/// initializers (represented as DesignatedInitExprs), initializations
+/// of subobject members without explicit braces, and so on. Clients
+/// interested in the original syntax of the initializer list should
+/// use the syntactic form of the initializer list.
+///
+/// After semantic analysis, the initializer list will represent the
+/// semantic form of the initializer, where the initializations of all
+/// subobjects are made explicit with nested InitListExpr nodes and
+/// C99 designators have been eliminated by placing the designated
+/// initializations into the subobject they initialize. Additionally,
+/// any "holes" in the initialization, where no initializer has been
+/// specified for a particular subobject, will be replaced with
+/// implicitly-generated ImplicitValueInitExpr expressions that
+/// value-initialize the subobjects. Note, however, that the
+/// initializer lists may still have fewer initializers than there are
+/// elements to initialize within the object.
+///
+/// Given the semantic form of the initializer list, one can retrieve
+/// the original syntactic form of that initializer list (if it
+/// exists) using getSyntacticForm(). Since many initializer lists
+/// have the same syntactic and semantic forms, getSyntacticForm() may
+/// return NULL, indicating that the current initializer list also
+/// serves as its syntactic form.
+class InitListExpr : public Expr {
+ // FIXME: Eliminate this vector in favor of ASTContext allocation
+ typedef ASTVector<Stmt *> InitExprsTy;
+ InitExprsTy InitExprs;
+ SourceLocation LBraceLoc, RBraceLoc;
+
+ /// Contains the initializer list that describes the syntactic form
+ /// written in the source code.
+ InitListExpr *SyntacticForm;
+
+ /// If this initializer list initializes a union, specifies which
+ /// field within the union will be initialized.
+ FieldDecl *UnionFieldInit;
+
+ /// Whether this initializer list originally had a GNU array-range
+ /// designator in it. This is a temporary marker used by CodeGen.
+ bool HadArrayRangeDesignator;
+
+public:
+ InitListExpr(ASTContext &C, SourceLocation lbraceloc,
+ Expr **initexprs, unsigned numinits,
+ SourceLocation rbraceloc);
+
+ /// \brief Build an empty initializer list.
+ explicit InitListExpr(ASTContext &C, EmptyShell Empty)
+ : Expr(InitListExprClass, Empty), InitExprs(C) { }
+
+ unsigned getNumInits() const { return InitExprs.size(); }
+
+ /// \brief Retrieve the set of initializers.
+ Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+
+ const Expr *getInit(unsigned Init) const {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ return cast_or_null<Expr>(InitExprs[Init]);
+ }
+
+ Expr *getInit(unsigned Init) {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ return cast_or_null<Expr>(InitExprs[Init]);
+ }
+
+ void setInit(unsigned Init, Expr *expr) {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ InitExprs[Init] = expr;
+ }
+
+ /// \brief Reserve space for some number of initializers.
+ void reserveInits(ASTContext &C, unsigned NumInits);
+
+ /// @brief Specify the number of initializers
+ ///
+ /// If there are more than @p NumInits initializers, the remaining
+ /// initializers will be destroyed. If there are fewer than @p
+ /// NumInits initializers, NULL expressions will be added for the
+ /// unknown initializers.
+ void resizeInits(ASTContext &Context, unsigned NumInits);
+
+ /// @brief Updates the initializer at index @p Init with the new
+ /// expression @p expr, and returns the old expression at that
+ /// location.
+ ///
+ /// When @p Init is out of range for this initializer list, the
+ /// initializer list will be extended with NULL expressions to
+ /// accomodate the new entry.
+ Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr);
+
+ /// \brief If this initializes a union, specifies which field in the
+ /// union to initialize.
+ ///
+ /// Typically, this field is the first named field within the
+ /// union. However, a designated initializer can specify the
+ /// initialization of a different field within the union.
+ FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; }
+ void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; }
+
+ // Explicit InitListExpr's originate from source code (and have valid source
+ // locations). Implicit InitListExpr's are created by the semantic analyzer.
+ bool isExplicit() {
+ return LBraceLoc.isValid() && RBraceLoc.isValid();
+ }
+
+ SourceLocation getLBraceLoc() const { return LBraceLoc; }
+ void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
+
+ /// @brief Retrieve the initializer list that describes the
+ /// syntactic form of the initializer.
+ ///
+ ///
+ InitListExpr *getSyntacticForm() const { return SyntacticForm; }
+ void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; }
+
+ bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; }
+ void sawArrayRangeDesignator(bool ARD = true) {
+ HadArrayRangeDesignator = ARD;
+ }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == InitListExprClass;
+ }
+ static bool classof(const InitListExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (InitExprs.empty()) return child_range();
+ return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
+ }
+
+ typedef InitExprsTy::iterator iterator;
+ typedef InitExprsTy::const_iterator const_iterator;
+ typedef InitExprsTy::reverse_iterator reverse_iterator;
+ typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;
+
+ iterator begin() { return InitExprs.begin(); }
+ const_iterator begin() const { return InitExprs.begin(); }
+ iterator end() { return InitExprs.end(); }
+ const_iterator end() const { return InitExprs.end(); }
+ reverse_iterator rbegin() { return InitExprs.rbegin(); }
+ const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
+ reverse_iterator rend() { return InitExprs.rend(); }
+ const_reverse_iterator rend() const { return InitExprs.rend(); }
+};
+
+/// @brief Represents a C99 designated initializer expression.
+///
+/// A designated initializer expression (C99 6.7.8) contains one or
+/// more designators (which can be field designators, array
+/// designators, or GNU array-range designators) followed by an
+/// expression that initializes the field or element(s) that the
+/// designators refer to. For example, given:
+///
+/// @code
+/// struct point {
+/// double x;
+/// double y;
+/// };
+/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
+/// @endcode
+///
+/// The InitListExpr contains three DesignatedInitExprs, the first of
+/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
+/// designators, one array designator for @c [2] followed by one field
+/// designator for @c .y. The initalization expression will be 1.0.
+class DesignatedInitExpr : public Expr {
+public:
+ /// \brief Forward declaration of the Designator class.
+ class Designator;
+
+private:
+ /// The location of the '=' or ':' prior to the actual initializer
+ /// expression.
+ SourceLocation EqualOrColonLoc;
+
+ /// Whether this designated initializer used the GNU deprecated
+ /// syntax rather than the C99 '=' syntax.
+ bool GNUSyntax : 1;
+
+ /// The number of designators in this initializer expression.
+ unsigned NumDesignators : 15;
+
+ /// \brief The designators in this designated initialization
+ /// expression.
+ Designator *Designators;
+
+ /// The number of subexpressions of this initializer expression,
+ /// which contains both the initializer and any additional
+ /// expressions used by array and array-range designators.
+ unsigned NumSubExprs : 16;
+
+
+ DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators,
+ const Designator *Designators,
+ SourceLocation EqualOrColonLoc, bool GNUSyntax,
+ Expr **IndexExprs, unsigned NumIndexExprs,
+ Expr *Init);
+
+ explicit DesignatedInitExpr(unsigned NumSubExprs)
+ : Expr(DesignatedInitExprClass, EmptyShell()),
+ NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { }
+
+public:
+ /// A field designator, e.g., ".x".
+ struct FieldDesignator {
+ /// Refers to the field that is being initialized. The low bit
+ /// of this field determines whether this is actually a pointer
+ /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When
+ /// initially constructed, a field designator will store an
+ /// IdentifierInfo*. After semantic analysis has resolved that
+ /// name, the field designator will instead store a FieldDecl*.
+ uintptr_t NameOrField;
+
+ /// The location of the '.' in the designated initializer.
+ unsigned DotLoc;
+
+ /// The location of the field name in the designated initializer.
+ unsigned FieldLoc;
+ };
+
+ /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
+ struct ArrayOrRangeDesignator {
+ /// Location of the first index expression within the designated
+ /// initializer expression's list of subexpressions.
+ unsigned Index;
+ /// The location of the '[' starting the array range designator.
+ unsigned LBracketLoc;
+ /// The location of the ellipsis separating the start and end
+ /// indices. Only valid for GNU array-range designators.
+ unsigned EllipsisLoc;
+ /// The location of the ']' terminating the array range designator.
+ unsigned RBracketLoc;
+ };
+
+ /// @brief Represents a single C99 designator.
+ ///
+ /// @todo This class is infuriatingly similar to clang::Designator,
+ /// but minor differences (storing indices vs. storing pointers)
+ /// keep us from reusing it. Try harder, later, to rectify these
+ /// differences.
+ class Designator {
+ /// @brief The kind of designator this describes.
+ enum {
+ FieldDesignator,
+ ArrayDesignator,
+ ArrayRangeDesignator
+ } Kind;
+
+ union {
+ /// A field designator, e.g., ".x".
+ struct FieldDesignator Field;
+ /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
+ struct ArrayOrRangeDesignator ArrayOrRange;
+ };
+ friend class DesignatedInitExpr;
+
+ public:
+ Designator() {}
+
+ /// @brief Initializes a field designator.
+ Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
+ SourceLocation FieldLoc)
+ : Kind(FieldDesignator) {
+ Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
+ Field.DotLoc = DotLoc.getRawEncoding();
+ Field.FieldLoc = FieldLoc.getRawEncoding();
+ }
+
+ /// @brief Initializes an array designator.
+ Designator(unsigned Index, SourceLocation LBracketLoc,
+ SourceLocation RBracketLoc)
+ : Kind(ArrayDesignator) {
+ ArrayOrRange.Index = Index;
+ ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
+ ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding();
+ ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ /// @brief Initializes a GNU array-range designator.
+ Designator(unsigned Index, SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
+ : Kind(ArrayRangeDesignator) {
+ ArrayOrRange.Index = Index;
+ ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
+ ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ bool isFieldDesignator() const { return Kind == FieldDesignator; }
+ bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+ bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+ IdentifierInfo * getFieldName();
+
+ FieldDecl *getField() {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ if (Field.NameOrField & 0x01)
+ return 0;
+ else
+ return reinterpret_cast<FieldDecl *>(Field.NameOrField);
+ }
+
+ void setField(FieldDecl *FD) {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ Field.NameOrField = reinterpret_cast<uintptr_t>(FD);
+ }
+
+ SourceLocation getDotLoc() const {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ return SourceLocation::getFromRawEncoding(Field.DotLoc);
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ return SourceLocation::getFromRawEncoding(Field.FieldLoc);
+ }
+
+ SourceLocation getLBracketLoc() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == ArrayRangeDesignator &&
+ "Only valid on an array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc);
+ }
+
+ unsigned getFirstExprIndex() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return ArrayOrRange.Index;
+ }
+
+ SourceLocation getStartLocation() const {
+ if (Kind == FieldDesignator)
+ return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
+ else
+ return getLBracketLoc();
+ }
+ };
+
+ static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
+ unsigned NumDesignators,
+ Expr **IndexExprs, unsigned NumIndexExprs,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax, Expr *Init);
+
+ static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs);
+
+ /// @brief Returns the number of designators in this initializer.
+ unsigned size() const { return NumDesignators; }
+
+ // Iterator access to the designators.
+ typedef Designator* designators_iterator;
+ designators_iterator designators_begin() { return Designators; }
+ designators_iterator designators_end() {
+ return Designators + NumDesignators;
+ }
+
+ typedef std::reverse_iterator<designators_iterator>
+ reverse_designators_iterator;
+ reverse_designators_iterator designators_rbegin() {
+ return reverse_designators_iterator(designators_end());
+ }
+ reverse_designators_iterator designators_rend() {
+ return reverse_designators_iterator(designators_begin());
+ }
+
+ Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
+
+ void setDesignators(ASTContext &C, const Designator *Desigs,
+ unsigned NumDesigs);
+
+ Expr *getArrayIndex(const Designator& D);
+ Expr *getArrayRangeStart(const Designator& D);
+ Expr *getArrayRangeEnd(const Designator& D);
+
+ /// @brief Retrieve the location of the '=' that precedes the
+ /// initializer value itself, if present.
+ SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
+ void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
+
+ /// @brief Determines whether this designated initializer used the
+ /// deprecated GNU syntax for designated initializers.
+ bool usesGNUSyntax() const { return GNUSyntax; }
+ void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }
+
+ /// @brief Retrieve the initializer value.
+ Expr *getInit() const {
+ return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
+ }
+
+ void setInit(Expr *init) {
+ *child_begin() = init;
+ }
+
+ /// \brief Retrieve the total number of subexpressions in this
+ /// designated initializer expression, including the actual
+ /// initialized value and any expressions that occur within array
+ /// and array-range designators.
+ unsigned getNumSubExprs() const { return NumSubExprs; }
+
+ Expr *getSubExpr(unsigned Idx) {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx];
+ }
+
+ void setSubExpr(unsigned Idx, Expr *E) {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E;
+ }
+
+ /// \brief Replaces the designator at index @p Idx with the series
+ /// of designators in [First, Last).
+ void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
+ const Designator *Last);
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DesignatedInitExprClass;
+ }
+ static bool classof(const DesignatedInitExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
+ return child_range(begin, begin + NumSubExprs);
+ }
+};
+
+/// \brief Represents an implicitly-generated value initialization of
+/// an object of a given type.
+///
+/// Implicit value initializations occur within semantic initializer
+/// list expressions (InitListExpr) as placeholders for subobject
+/// initializations not explicitly specified by the user.
+///
+/// \see InitListExpr
+class ImplicitValueInitExpr : public Expr {
+public:
+ explicit ImplicitValueInitExpr(QualType ty)
+ : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, false, false) { }
+
+ /// \brief Construct an empty implicit value initialization.
+ explicit ImplicitValueInitExpr(EmptyShell Empty)
+ : Expr(ImplicitValueInitExprClass, Empty) { }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitValueInitExprClass;
+ }
+ static bool classof(const ImplicitValueInitExpr *) { return true; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange();
+ }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+
+class ParenListExpr : public Expr {
+ Stmt **Exprs;
+ unsigned NumExprs;
+ SourceLocation LParenLoc, RParenLoc;
+
+public:
+ ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
+ unsigned numexprs, SourceLocation rparenloc);
+
+ /// \brief Build an empty paren list.
+ explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
+
+ unsigned getNumExprs() const { return NumExprs; }
+
+ const Expr* getExpr(unsigned Init) const {
+ assert(Init < getNumExprs() && "Initializer access out of range!");
+ return cast_or_null<Expr>(Exprs[Init]);
+ }
+
+ Expr* getExpr(unsigned Init) {
+ assert(Init < getNumExprs() && "Initializer access out of range!");
+ return cast_or_null<Expr>(Exprs[Init]);
+ }
+
+ Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LParenLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenListExprClass;
+ }
+ static bool classof(const ParenListExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0]+NumExprs);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+
+//===----------------------------------------------------------------------===//
+// Clang Extensions
+//===----------------------------------------------------------------------===//
+
+
+/// ExtVectorElementExpr - This represents access to specific elements of a
+/// vector, and may occur on the left hand side or right hand side. For example
+/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector.
+///
+/// Note that the base may have either vector or pointer to vector type, just
+/// like a struct field reference.
+///
+class ExtVectorElementExpr : public Expr {
+ Stmt *Base;
+ IdentifierInfo *Accessor;
+ SourceLocation AccessorLoc;
+public:
+ ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
+ IdentifierInfo &accessor, SourceLocation loc)
+ : Expr(ExtVectorElementExprClass, ty, VK,
+ (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent),
+ base->isTypeDependent(), base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), Accessor(&accessor), AccessorLoc(loc) {}
+
+ /// \brief Build an empty vector element expression.
+ explicit ExtVectorElementExpr(EmptyShell Empty)
+ : Expr(ExtVectorElementExprClass, Empty) { }
+
+ const Expr *getBase() const { return cast<Expr>(Base); }
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *E) { Base = E; }
+
+ IdentifierInfo &getAccessor() const { return *Accessor; }
+ void setAccessor(IdentifierInfo *II) { Accessor = II; }
+
+ SourceLocation getAccessorLoc() const { return AccessorLoc; }
+ void setAccessorLoc(SourceLocation L) { AccessorLoc = L; }
+
+ /// getNumElements - Get the number of components being selected.
+ unsigned getNumElements() const;
+
+ /// containsDuplicateElements - Return true if any element access is
+ /// repeated.
+ bool containsDuplicateElements() const;
+
+ /// getEncodedElementAccess - Encode the elements accessed into an llvm
+ /// aggregate Constant of ConstantInt(s).
+ void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getBase()->getLocStart(), AccessorLoc);
+ }
+
+ /// isArrow - Return true if the base expression is a pointer to vector,
+ /// return false if the base expression is a vector.
+ bool isArrow() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExtVectorElementExprClass;
+ }
+ static bool classof(const ExtVectorElementExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+};
+
+
+/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
+/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
+class BlockExpr : public Expr {
+protected:
+ BlockDecl *TheBlock;
+public:
+ BlockExpr(BlockDecl *BD, QualType ty)
+ : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
+ ty->isDependentType(), false, false),
+ TheBlock(BD) {}
+
+ /// \brief Build an empty block expression.
+ explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
+
+ const BlockDecl *getBlockDecl() const { return TheBlock; }
+ BlockDecl *getBlockDecl() { return TheBlock; }
+ void setBlockDecl(BlockDecl *BD) { TheBlock = BD; }
+
+ // Convenience functions for probing the underlying BlockDecl.
+ SourceLocation getCaretLocation() const;
+ const Stmt *getBody() const;
+ Stmt *getBody();
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getCaretLocation(), getBody()->getLocEnd());
+ }
+
+ /// getFunctionType - Return the underlying function type for this block.
+ const FunctionType *getFunctionType() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockExprClass;
+ }
+ static bool classof(const BlockExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// BlockDeclRefExpr - A reference to a local variable declared in an
+/// enclosing scope.
+class BlockDeclRefExpr : public Expr {
+ VarDecl *D;
+ SourceLocation Loc;
+ bool IsByRef : 1;
+ bool ConstQualAdded : 1;
+public:
+ BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
+ SourceLocation l, bool ByRef, bool constAdded = false);
+
+ // \brief Build an empty reference to a declared variable in a
+ // block.
+ explicit BlockDeclRefExpr(EmptyShell Empty)
+ : Expr(BlockDeclRefExprClass, Empty) { }
+
+ VarDecl *getDecl() { return D; }
+ const VarDecl *getDecl() const { return D; }
+ void setDecl(VarDecl *VD) { D = VD; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ bool isByRef() const { return IsByRef; }
+ void setByRef(bool BR) { IsByRef = BR; }
+
+ bool isConstQualAdded() const { return ConstQualAdded; }
+ void setConstQualAdded(bool C) { ConstQualAdded = C; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockDeclRefExprClass;
+ }
+ static bool classof(const BlockDeclRefExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
new file mode 100644
index 0000000..85ce962
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -0,0 +1,2892 @@
+//===--- ExprCXX.h - Classes for representing expressions -------*- 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 Expr interface and subclasses for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPRCXX_H
+#define LLVM_CLANG_AST_EXPRCXX_H
+
+#include "clang/Basic/TypeTraits.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/AST/TemplateBase.h"
+
+namespace clang {
+
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXTemporary;
+class TemplateArgumentListInfo;
+
+//===--------------------------------------------------------------------===//
+// C++ Expressions.
+//===--------------------------------------------------------------------===//
+
+/// \brief A call to an overloaded operator written using operator
+/// syntax.
+///
+/// Represents a call to an overloaded operator written using operator
+/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a
+/// normal call, this AST node provides better information about the
+/// syntactic representation of the call.
+///
+/// In a C++ template, this expression node kind will be used whenever
+/// any of the arguments are type-dependent. In this case, the
+/// function itself will be a (possibly empty) set of functions and
+/// function templates that were found by name lookup at template
+/// definition time.
+class CXXOperatorCallExpr : public CallExpr {
+ /// \brief The overloaded operator.
+ OverloadedOperatorKind Operator;
+
+public:
+ CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
+ Expr **args, unsigned numargs, QualType t,
+ ExprValueKind VK, SourceLocation operatorloc)
+ : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK,
+ operatorloc),
+ Operator(Op) {}
+ explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
+ CallExpr(C, CXXOperatorCallExprClass, Empty) { }
+
+
+ /// getOperator - Returns the kind of overloaded operator that this
+ /// expression refers to.
+ OverloadedOperatorKind getOperator() const { return Operator; }
+ void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; }
+
+ /// getOperatorLoc - Returns the location of the operator symbol in
+ /// the expression. When @c getOperator()==OO_Call, this is the
+ /// location of the right parentheses; when @c
+ /// getOperator()==OO_Subscript, this is the location of the right
+ /// bracket.
+ SourceLocation getOperatorLoc() const { return getRParenLoc(); }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXOperatorCallExprClass;
+ }
+ static bool classof(const CXXOperatorCallExpr *) { return true; }
+};
+
+/// CXXMemberCallExpr - Represents a call to a member function that
+/// may be written either with member call syntax (e.g., "obj.func()"
+/// or "objptr->func()") or with normal function-call syntax
+/// ("func()") within a member function that ends up calling a member
+/// function. The callee in either case is a MemberExpr that contains
+/// both the object argument and the member function, while the
+/// arguments are the arguments within the parentheses (not including
+/// the object argument).
+class CXXMemberCallExpr : public CallExpr {
+public:
+ CXXMemberCallExpr(ASTContext &C, Expr *fn, Expr **args, unsigned numargs,
+ QualType t, ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, numargs, t, VK, RP) {}
+
+ CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, CXXMemberCallExprClass, Empty) { }
+
+ /// getImplicitObjectArgument - Retrieves the implicit object
+ /// argument for the member call. For example, in "x.f(5)", this
+ /// operation would return "x".
+ Expr *getImplicitObjectArgument();
+
+ /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of
+ /// the implicit object argument. Note that this is may not be the same
+ /// declaration as that of the class context of the CXXMethodDecl which this
+ /// function is calling.
+ /// FIXME: Returns 0 for member pointer call exprs.
+ CXXRecordDecl *getRecordDecl();
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXMemberCallExprClass;
+ }
+ static bool classof(const CXXMemberCallExpr *) { return true; }
+};
+
+/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function.
+class CUDAKernelCallExpr : public CallExpr {
+private:
+ enum { CONFIG, END_PREARG };
+
+public:
+ CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config,
+ Expr **args, unsigned numargs, QualType t,
+ ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, numargs, t, VK,
+ RP) {
+ setConfig(Config);
+ }
+
+ CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { }
+
+ const CallExpr *getConfig() const {
+ return cast_or_null<CallExpr>(getPreArg(CONFIG));
+ }
+ CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); }
+ void setConfig(CallExpr *E) { setPreArg(CONFIG, E); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CUDAKernelCallExprClass;
+ }
+ static bool classof(const CUDAKernelCallExpr *) { return true; }
+};
+
+/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
+/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
+/// const_cast.
+///
+/// This abstract class is inherited by all of the classes
+/// representing "named" casts, e.g., CXXStaticCastExpr,
+/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr.
+class CXXNamedCastExpr : public ExplicitCastExpr {
+private:
+ SourceLocation Loc; // the location of the casting op
+ SourceLocation RParenLoc; // the location of the right parenthesis
+
+protected:
+ CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
+ RParenLoc(RParenLoc) {}
+
+ explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(SC, Shell, PathSize) { }
+
+ friend class ASTStmtReader;
+
+public:
+ const char *getCastName() const;
+
+ /// \brief Retrieve the location of the cast operator keyword, e.g.,
+ /// "static_cast".
+ SourceLocation getOperatorLoc() const { return Loc; }
+
+ /// \brief Retrieve the location of the closing parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ switch (T->getStmtClass()) {
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const CXXNamedCastExpr *) { return true; }
+};
+
+/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]).
+///
+/// This expression node represents a C++ static cast, e.g.,
+/// @c static_cast<int>(1.0).
+class CXXStaticCastExpr : public CXXNamedCastExpr {
+ CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
+
+ explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+
+public:
+ static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
+ static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXStaticCastExprClass;
+ }
+ static bool classof(const CXXStaticCastExpr *) { return true; }
+};
+
+/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
+/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
+/// determine how to perform the type cast.
+///
+/// This expression node represents a dynamic cast, e.g.,
+/// @c dynamic_cast<Derived*>(BasePtr).
+class CXXDynamicCastExpr : public CXXNamedCastExpr {
+ CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
+ Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
+ writtenTy, l, RParenLoc) {}
+
+ explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc);
+
+ static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDynamicCastExprClass;
+ }
+ static bool classof(const CXXDynamicCastExpr *) { return true; }
+};
+
+/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
+/// [expr.reinterpret.cast]), which provides a differently-typed view
+/// of a value but performs no actual work at run time.
+///
+/// This expression node represents a reinterpret cast, e.g.,
+/// @c reinterpret_cast<int>(VoidPtr).
+class CXXReinterpretCastExpr : public CXXNamedCastExpr {
+ CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
+ Expr *op, unsigned pathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
+ pathSize, writtenTy, l, RParenLoc) {}
+
+ CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind Kind,
+ Expr *Op, const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
+ static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXReinterpretCastExprClass;
+ }
+ static bool classof(const CXXReinterpretCastExpr *) { return true; }
+};
+
+/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
+/// which can remove type qualifiers but does not change the underlying value.
+///
+/// This expression node represents a const cast, e.g.,
+/// @c const_cast<char*>(PtrToConstChar).
+class CXXConstCastExpr : public CXXNamedCastExpr {
+ CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
+ 0, writtenTy, l, RParenLoc) {}
+
+ explicit CXXConstCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+
+public:
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc);
+ static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstCastExprClass;
+ }
+ static bool classof(const CXXConstCastExpr *) { return true; }
+};
+
+/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
+///
+class CXXBoolLiteralExpr : public Expr {
+ bool Value;
+ SourceLocation Loc;
+public:
+ CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
+ Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Value(val), Loc(l) {}
+
+ explicit CXXBoolLiteralExpr(EmptyShell Empty)
+ : Expr(CXXBoolLiteralExprClass, Empty) { }
+
+ bool getValue() const { return Value; }
+ void setValue(bool V) { Value = V; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBoolLiteralExprClass;
+ }
+ static bool classof(const CXXBoolLiteralExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
+class CXXNullPtrLiteralExpr : public Expr {
+ SourceLocation Loc;
+public:
+ CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
+ Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false),
+ Loc(l) {}
+
+ explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
+ : Expr(CXXNullPtrLiteralExprClass, Empty) { }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNullPtrLiteralExprClass;
+ }
+ static bool classof(const CXXNullPtrLiteralExpr *) { return true; }
+
+ child_range children() { return child_range(); }
+};
+
+/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
+/// the type_info that corresponds to the supplied type, or the (possibly
+/// dynamic) type of the supplied expression.
+///
+/// This represents code like @c typeid(int) or @c typeid(*objPtr)
+class CXXTypeidExpr : public Expr {
+private:
+ llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
+ SourceRange Range;
+
+public:
+ CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ false,
+ // typeid is value-dependent if the type or expression are dependent
+ Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
+ : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ false,
+ // typeid is value-dependent if the type or expression are dependent
+ Operand->isTypeDependent() || Operand->isValueDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXTypeidExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXTypeidExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)0;
+ else
+ Operand = (TypeSourceInfo*)0;
+ }
+
+ bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
+
+ /// \brief Retrieves the type operand of this typeid() expression after
+ /// various required adjustments (removing reference types, cv-qualifiers).
+ QualType getTypeOperand() const;
+
+ /// \brief Retrieve source information for the type operand.
+ TypeSourceInfo *getTypeOperandSourceInfo() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ return Operand.get<TypeSourceInfo *>();
+ }
+
+ void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ Operand = TSI;
+ }
+
+ Expr *getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
+ return static_cast<Expr*>(Operand.get<Stmt *>());
+ }
+
+ void setExprOperand(Expr *E) {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
+ Operand = E;
+ }
+
+ SourceRange getSourceRange() const { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTypeidExprClass;
+ }
+ static bool classof(const CXXTypeidExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
+/// the _GUID that corresponds to the supplied type or expression.
+///
+/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
+class CXXUuidofExpr : public Expr {
+private:
+ llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
+ SourceRange Range;
+
+public:
+ CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->getType()->isDependentType(),
+ Operand->getType()->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
+ : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
+ false, Operand->isTypeDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXUuidofExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)0;
+ else
+ Operand = (TypeSourceInfo*)0;
+ }
+
+ bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
+
+ /// \brief Retrieves the type operand of this __uuidof() expression after
+ /// various required adjustments (removing reference types, cv-qualifiers).
+ QualType getTypeOperand() const;
+
+ /// \brief Retrieve source information for the type operand.
+ TypeSourceInfo *getTypeOperandSourceInfo() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ return Operand.get<TypeSourceInfo *>();
+ }
+
+ void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ Operand = TSI;
+ }
+
+ Expr *getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ return static_cast<Expr*>(Operand.get<Stmt *>());
+ }
+
+ void setExprOperand(Expr *E) {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
+ Operand = E;
+ }
+
+ SourceRange getSourceRange() const { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUuidofExprClass;
+ }
+ static bool classof(const CXXUuidofExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand()) return child_range();
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// CXXThisExpr - Represents the "this" expression in C++, which is a
+/// pointer to the object on which the current member function is
+/// executing (C++ [expr.prim]p3). Example:
+///
+/// @code
+/// class Foo {
+/// public:
+/// void bar();
+/// void test() { this->bar(); }
+/// };
+/// @endcode
+class CXXThisExpr : public Expr {
+ SourceLocation Loc;
+ bool Implicit : 1;
+
+public:
+ CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit)
+ : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary,
+ // 'this' is type-dependent if the class type of the enclosing
+ // member function is dependent (C++ [temp.dep.expr]p2)
+ Type->isDependentType(), Type->isDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(L), Implicit(isImplicit) { }
+
+ CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I) { Implicit = I; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThisExprClass;
+ }
+ static bool classof(const CXXThisExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
+/// 'throw' and 'throw' assignment-expression. When
+/// assignment-expression isn't present, Op will be null.
+///
+class CXXThrowExpr : public Expr {
+ Stmt *Op;
+ SourceLocation ThrowLoc;
+public:
+ // Ty is the void type which is used as the result type of the
+ // exepression. The l is the location of the throw keyword. expr
+ // can by null, if the optional expression to throw isn't present.
+ CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) :
+ Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ expr && expr->containsUnexpandedParameterPack()),
+ Op(expr), ThrowLoc(l) {}
+ CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
+
+ const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
+ Expr *getSubExpr() { return cast_or_null<Expr>(Op); }
+ void setSubExpr(Expr *E) { Op = E; }
+
+ SourceLocation getThrowLoc() const { return ThrowLoc; }
+ void setThrowLoc(SourceLocation L) { ThrowLoc = L; }
+
+ SourceRange getSourceRange() const {
+ if (getSubExpr() == 0)
+ return SourceRange(ThrowLoc, ThrowLoc);
+ return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThrowExprClass;
+ }
+ static bool classof(const CXXThrowExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Op, Op ? &Op+1 : &Op);
+ }
+};
+
+/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
+/// function call argument that was created from the corresponding
+/// parameter's default argument, when the call did not explicitly
+/// supply arguments for all of the parameters.
+class CXXDefaultArgExpr : public Expr {
+ /// \brief The parameter whose default is being used.
+ ///
+ /// When the bit is set, the subexpression is stored after the
+ /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's
+ /// actual default expression is the subexpression.
+ llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param;
+
+ /// \brief The location where the default argument expression was used.
+ SourceLocation Loc;
+
+ CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param)
+ : Expr(SC,
+ param->hasUnparsedDefaultArg()
+ ? param->getType().getNonReferenceType()
+ : param->getDefaultArg()->getType(),
+ param->getDefaultArg()->getValueKind(),
+ param->getDefaultArg()->getObjectKind(), false, false, false),
+ Param(param, false), Loc(Loc) { }
+
+ CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
+ Expr *SubExpr)
+ : Expr(SC, SubExpr->getType(),
+ SubExpr->getValueKind(), SubExpr->getObjectKind(),
+ false, false, false),
+ Param(param, true), Loc(Loc) {
+ *reinterpret_cast<Expr **>(this + 1) = SubExpr;
+ }
+
+public:
+ CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
+
+
+ // Param is the parameter whose default argument is used by this
+ // expression.
+ static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc,
+ ParmVarDecl *Param) {
+ return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
+ }
+
+ // Param is the parameter whose default argument is used by this
+ // expression, and SubExpr is the expression that will actually be used.
+ static CXXDefaultArgExpr *Create(ASTContext &C,
+ SourceLocation Loc,
+ ParmVarDecl *Param,
+ Expr *SubExpr);
+
+ // Retrieve the parameter that the argument was created from.
+ const ParmVarDecl *getParam() const { return Param.getPointer(); }
+ ParmVarDecl *getParam() { return Param.getPointer(); }
+
+ // Retrieve the actual argument to the function call.
+ const Expr *getExpr() const {
+ if (Param.getInt())
+ return *reinterpret_cast<Expr const * const*> (this + 1);
+ return getParam()->getDefaultArg();
+ }
+ Expr *getExpr() {
+ if (Param.getInt())
+ return *reinterpret_cast<Expr **> (this + 1);
+ return getParam()->getDefaultArg();
+ }
+
+ /// \brief Retrieve the location where this default argument was actually
+ /// used.
+ SourceLocation getUsedLocation() const { return Loc; }
+
+ SourceRange getSourceRange() const {
+ // Default argument expressions have no representation in the
+ // source, so they have an empty source range.
+ return SourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultArgExprClass;
+ }
+ static bool classof(const CXXDefaultArgExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// CXXTemporary - Represents a C++ temporary.
+class CXXTemporary {
+ /// Destructor - The destructor that needs to be called.
+ const CXXDestructorDecl *Destructor;
+
+ CXXTemporary(const CXXDestructorDecl *destructor)
+ : Destructor(destructor) { }
+
+public:
+ static CXXTemporary *Create(ASTContext &C,
+ const CXXDestructorDecl *Destructor);
+
+ const CXXDestructorDecl *getDestructor() const { return Destructor; }
+};
+
+/// \brief Represents binding an expression to a temporary.
+///
+/// This ensures the destructor is called for the temporary. It should only be
+/// needed for non-POD, non-trivially destructable class types. For example:
+///
+/// \code
+/// struct S {
+/// S() { } // User defined constructor makes S non-POD.
+/// ~S() { } // User defined destructor makes it non-trivial.
+/// };
+/// void test() {
+/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
+/// }
+/// \endcode
+class CXXBindTemporaryExpr : public Expr {
+ CXXTemporary *Temp;
+
+ Stmt *SubExpr;
+
+ CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr)
+ : Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
+ VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
+ SubExpr->isValueDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ Temp(temp), SubExpr(SubExpr) { }
+
+public:
+ CXXBindTemporaryExpr(EmptyShell Empty)
+ : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {}
+
+ static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp,
+ Expr* SubExpr);
+
+ CXXTemporary *getTemporary() { return Temp; }
+ const CXXTemporary *getTemporary() const { return Temp; }
+ void setTemporary(CXXTemporary *T) { Temp = T; }
+
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ SourceRange getSourceRange() const {
+ return SubExpr->getSourceRange();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBindTemporaryExprClass;
+ }
+ static bool classof(const CXXBindTemporaryExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
+};
+
+/// CXXConstructExpr - Represents a call to a C++ constructor.
+class CXXConstructExpr : public Expr {
+public:
+ enum ConstructionKind {
+ CK_Complete,
+ CK_NonVirtualBase,
+ CK_VirtualBase
+ };
+
+private:
+ CXXConstructorDecl *Constructor;
+
+ SourceLocation Loc;
+ SourceRange ParenRange;
+ bool Elidable : 1;
+ bool ZeroInitialization : 1;
+ unsigned ConstructKind : 2;
+ Stmt **Args;
+ unsigned NumArgs;
+
+protected:
+ CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *d, bool elidable,
+ Expr **args, unsigned numargs,
+ bool ZeroInitialization = false,
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
+
+ /// \brief Construct an empty C++ construction expression.
+ CXXConstructExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0),
+ ConstructKind(0), Args(0), NumArgs(0) { }
+
+public:
+ /// \brief Construct an empty C++ construction expression.
+ explicit CXXConstructExpr(EmptyShell Empty)
+ : Expr(CXXConstructExprClass, Empty), Constructor(0),
+ Elidable(0), ZeroInitialization(0),
+ ConstructKind(0), Args(0), NumArgs(0) { }
+
+ static CXXConstructExpr *Create(ASTContext &C, QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *D, bool Elidable,
+ Expr **Args, unsigned NumArgs,
+ bool ZeroInitialization = false,
+ ConstructionKind ConstructKind = CK_Complete,
+ SourceRange ParenRange = SourceRange());
+
+
+ CXXConstructorDecl* getConstructor() const { return Constructor; }
+ void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation Loc) { this->Loc = Loc; }
+
+ /// \brief Whether this construction is elidable.
+ bool isElidable() const { return Elidable; }
+ void setElidable(bool E) { Elidable = E; }
+
+ /// \brief Whether this construction first requires
+ /// zero-initialization before the initializer is called.
+ bool requiresZeroInitialization() const { return ZeroInitialization; }
+ void setRequiresZeroInitialization(bool ZeroInit) {
+ ZeroInitialization = ZeroInit;
+ }
+
+ /// \brief Determines whether this constructor is actually constructing
+ /// a base class (rather than a complete object).
+ ConstructionKind getConstructionKind() const {
+ return (ConstructionKind)ConstructKind;
+ }
+ void setConstructionKind(ConstructionKind CK) {
+ ConstructKind = CK;
+ }
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return Args; }
+ arg_iterator arg_end() { return Args + NumArgs; }
+ const_arg_iterator arg_begin() const { return Args; }
+ const_arg_iterator arg_end() const { return Args + NumArgs; }
+
+ Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); }
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(Args[Arg]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(Args[Arg]);
+ }
+
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ Args[Arg] = ArgExpr;
+ }
+
+ SourceRange getSourceRange() const;
+ SourceRange getParenRange() const { return ParenRange; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstructExprClass ||
+ T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+ static bool classof(const CXXConstructExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Args[0], &Args[0]+NumArgs);
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
+/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
+/// x = int(0.5);
+class CXXFunctionalCastExpr : public ExplicitCastExpr {
+ SourceLocation TyBeginLoc;
+ SourceLocation RParenLoc;
+
+ CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
+ TypeSourceInfo *writtenTy,
+ SourceLocation tyBeginLoc, CastKind kind,
+ Expr *castExpr, unsigned pathSize,
+ SourceLocation rParenLoc)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
+ castExpr, pathSize, writtenTy),
+ TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+
+ explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+
+public:
+ static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ TypeSourceInfo *Written,
+ SourceLocation TyBeginLoc,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ SourceLocation RPLoc);
+ static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
+
+ SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TyBeginLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFunctionalCastExprClass;
+ }
+ static bool classof(const CXXFunctionalCastExpr *) { return true; }
+};
+
+/// @brief Represents a C++ functional cast expression that builds a
+/// temporary object.
+///
+/// This expression type represents a C++ "functional" cast
+/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
+/// constructor to build a temporary object. With N == 1 arguments the
+/// functional cast expression will be represented by CXXFunctionalCastExpr.
+/// Example:
+/// @code
+/// struct X { X(int, float); }
+///
+/// X create_X() {
+/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
+/// };
+/// @endcode
+class CXXTemporaryObjectExpr : public CXXConstructExpr {
+ TypeSourceInfo *Type;
+
+public:
+ CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
+ TypeSourceInfo *Type,
+ Expr **Args,unsigned NumArgs,
+ SourceRange parenRange,
+ bool ZeroInitialization = false);
+ explicit CXXTemporaryObjectExpr(EmptyShell Empty)
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
+
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+ static bool classof(const CXXTemporaryObjectExpr *) { return true; }
+
+ friend class ASTStmtReader;
+};
+
+/// CXXScalarValueInitExpr - [C++ 5.2.3p2]
+/// Expression "T()" which creates a value-initialized rvalue of type
+/// T, which is a non-class type.
+///
+class CXXScalarValueInitExpr : public Expr {
+ SourceLocation RParenLoc;
+ TypeSourceInfo *TypeInfo;
+
+ friend class ASTStmtReader;
+
+public:
+ /// \brief Create an explicitly-written scalar-value initialization
+ /// expression.
+ CXXScalarValueInitExpr(QualType Type,
+ TypeSourceInfo *TypeInfo,
+ SourceLocation rParenLoc ) :
+ Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
+ false, false, false),
+ RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+
+ explicit CXXScalarValueInitExpr(EmptyShell Shell)
+ : Expr(CXXScalarValueInitExprClass, Shell) { }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TypeInfo;
+ }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXScalarValueInitExprClass;
+ }
+ static bool classof(const CXXScalarValueInitExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// CXXNewExpr - A new expression for memory allocation and constructor calls,
+/// e.g: "new CXXNewExpr(foo)".
+class CXXNewExpr : public Expr {
+ // Was the usage ::new, i.e. is the global new to be used?
+ bool GlobalNew : 1;
+ // Is there an initializer? If not, built-ins are uninitialized, else they're
+ // value-initialized.
+ bool Initializer : 1;
+ // Do we allocate an array? If so, the first SubExpr is the size expression.
+ bool Array : 1;
+ // If this is an array allocation, does the usual deallocation
+ // function for the allocated type want to know the allocated size?
+ bool UsualArrayDeleteWantsSize : 1;
+ // The number of placement new arguments.
+ unsigned NumPlacementArgs : 14;
+ // The number of constructor arguments. This may be 1 even for non-class
+ // types; use the pseudo copy constructor.
+ unsigned NumConstructorArgs : 14;
+ // Contains an optional array size expression, any number of optional
+ // placement arguments, and any number of optional constructor arguments,
+ // in that order.
+ Stmt **SubExprs;
+ // Points to the allocation function used.
+ FunctionDecl *OperatorNew;
+ // Points to the deallocation function used in case of error. May be null.
+ FunctionDecl *OperatorDelete;
+ // Points to the constructor used. Cannot be null if AllocType is a record;
+ // it would still point at the default constructor (even an implicit one).
+ // Must be null for all other types.
+ CXXConstructorDecl *Constructor;
+
+ /// \brief The allocated type-source information, as written in the source.
+ TypeSourceInfo *AllocatedTypeInfo;
+
+ /// \brief If the allocated type was expressed as a parenthesized type-id,
+ /// the source range covering the parenthesized type-id.
+ SourceRange TypeIdParens;
+
+ SourceLocation StartLoc;
+ SourceLocation EndLoc;
+ SourceLocation ConstructorLParen;
+ SourceLocation ConstructorRParen;
+
+ friend class ASTStmtReader;
+public:
+ CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
+ Expr **placementArgs, unsigned numPlaceArgs,
+ SourceRange TypeIdParens,
+ Expr *arraySize, CXXConstructorDecl *constructor, bool initializer,
+ Expr **constructorArgs, unsigned numConsArgs,
+ FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
+ QualType ty, TypeSourceInfo *AllocatedTypeInfo,
+ SourceLocation startLoc, SourceLocation endLoc,
+ SourceLocation constructorLParen,
+ SourceLocation constructorRParen);
+ explicit CXXNewExpr(EmptyShell Shell)
+ : Expr(CXXNewExprClass, Shell), SubExprs(0) { }
+
+ void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs,
+ unsigned numConsArgs);
+
+ QualType getAllocatedType() const {
+ assert(getType()->isPointerType());
+ return getType()->getAs<PointerType>()->getPointeeType();
+ }
+
+ TypeSourceInfo *getAllocatedTypeSourceInfo() const {
+ return AllocatedTypeInfo;
+ }
+
+ FunctionDecl *getOperatorNew() const { return OperatorNew; }
+ void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
+ FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+ void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
+ CXXConstructorDecl *getConstructor() const { return Constructor; }
+ void setConstructor(CXXConstructorDecl *D) { Constructor = D; }
+
+ bool isArray() const { return Array; }
+ Expr *getArraySize() {
+ return Array ? cast<Expr>(SubExprs[0]) : 0;
+ }
+ const Expr *getArraySize() const {
+ return Array ? cast<Expr>(SubExprs[0]) : 0;
+ }
+
+ unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ Expr **getPlacementArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array);
+ }
+
+ Expr *getPlacementArg(unsigned i) {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + i]);
+ }
+ const Expr *getPlacementArg(unsigned i) const {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + i]);
+ }
+
+ bool isParenTypeId() const { return TypeIdParens.isValid(); }
+ SourceRange getTypeIdParens() const { return TypeIdParens; }
+
+ bool isGlobalNew() const { return GlobalNew; }
+ bool hasInitializer() const { return Initializer; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
+
+ unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
+
+ Expr **getConstructorArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs);
+ }
+
+ Expr *getConstructorArg(unsigned i) {
+ assert(i < NumConstructorArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
+ }
+ const Expr *getConstructorArg(unsigned i) const {
+ assert(i < NumConstructorArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
+ }
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator placement_arg_begin() {
+ return SubExprs + Array;
+ }
+ arg_iterator placement_arg_end() {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ const_arg_iterator placement_arg_begin() const {
+ return SubExprs + Array;
+ }
+ const_arg_iterator placement_arg_end() const {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+
+ arg_iterator constructor_arg_begin() {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ arg_iterator constructor_arg_end() {
+ return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
+ }
+ const_arg_iterator constructor_arg_begin() const {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ const_arg_iterator constructor_arg_end() const {
+ return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
+ }
+
+ typedef Stmt **raw_arg_iterator;
+ raw_arg_iterator raw_arg_begin() { return SubExprs; }
+ raw_arg_iterator raw_arg_end() {
+ return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
+ }
+ const_arg_iterator raw_arg_begin() const { return SubExprs; }
+ const_arg_iterator raw_arg_end() const { return constructor_arg_end(); }
+
+ SourceLocation getStartLoc() const { return StartLoc; }
+ SourceLocation getEndLoc() const { return EndLoc; }
+
+ SourceLocation getConstructorLParen() const { return ConstructorLParen; }
+ SourceLocation getConstructorRParen() const { return ConstructorRParen; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLoc, EndLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNewExprClass;
+ }
+ static bool classof(const CXXNewExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0] + Array + getNumPlacementArgs()
+ + getNumConstructorArgs());
+ }
+};
+
+/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
+/// calls, e.g. "delete[] pArray".
+class CXXDeleteExpr : public Expr {
+ // Is this a forced global delete, i.e. "::delete"?
+ bool GlobalDelete : 1;
+ // Is this the array form of delete, i.e. "delete[]"?
+ bool ArrayForm : 1;
+ // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
+ // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
+ // will be true).
+ bool ArrayFormAsWritten : 1;
+ // Does the usual deallocation function for the element type require
+ // a size_t argument?
+ bool UsualArrayDeleteWantsSize : 1;
+ // Points to the operator delete overload that is used. Could be a member.
+ FunctionDecl *OperatorDelete;
+ // The pointer expression to be deleted.
+ Stmt *Argument;
+ // Location of the expression.
+ SourceLocation Loc;
+public:
+ CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
+ bool arrayFormAsWritten, bool usualArrayDeleteWantsSize,
+ FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
+ : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false,
+ arg->containsUnexpandedParameterPack()),
+ GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { }
+ explicit CXXDeleteExpr(EmptyShell Shell)
+ : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { }
+
+ bool isGlobalDelete() const { return GlobalDelete; }
+ bool isArrayForm() const { return ArrayForm; }
+ bool isArrayFormAsWritten() const { return ArrayFormAsWritten; }
+
+ /// Answers whether the usual array deallocation function for the
+ /// allocated type expects the size of the allocation as a
+ /// parameter. This can be true even if the actual deallocation
+ /// function that we're using doesn't want a size.
+ bool doesUsualArrayDeleteWantSize() const {
+ return UsualArrayDeleteWantsSize;
+ }
+
+ FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+
+ Expr *getArgument() { return cast<Expr>(Argument); }
+ const Expr *getArgument() const { return cast<Expr>(Argument); }
+
+ /// \brief Retrieve the type being destroyed. If the type being
+ /// destroyed is a dependent type which may or may not be a pointer,
+ /// return an invalid type.
+ QualType getDestroyedType() const;
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, Argument->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDeleteExprClass;
+ }
+ static bool classof(const CXXDeleteExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Argument, &Argument+1); }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief Structure used to store the type being destroyed by a
+/// pseudo-destructor expression.
+class PseudoDestructorTypeStorage {
+ /// \brief Either the type source information or the name of the type, if
+ /// it couldn't be resolved due to type-dependence.
+ llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
+
+ /// \brief The starting source location of the pseudo-destructor type.
+ SourceLocation Location;
+
+public:
+ PseudoDestructorTypeStorage() { }
+
+ PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
+ : Type(II), Location(Loc) { }
+
+ PseudoDestructorTypeStorage(TypeSourceInfo *Info);
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return Type.dyn_cast<TypeSourceInfo *>();
+ }
+
+ IdentifierInfo *getIdentifier() const {
+ return Type.dyn_cast<IdentifierInfo *>();
+ }
+
+ SourceLocation getLocation() const { return Location; }
+};
+
+/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
+///
+/// A pseudo-destructor is an expression that looks like a member access to a
+/// destructor of a scalar type, except that scalar types don't have
+/// destructors. For example:
+///
+/// \code
+/// typedef int T;
+/// void f(int *p) {
+/// p->T::~T();
+/// }
+/// \endcode
+///
+/// Pseudo-destructors typically occur when instantiating templates such as:
+///
+/// \code
+/// template<typename T>
+/// void destroy(T* ptr) {
+/// ptr->T::~T();
+/// }
+/// \endcode
+///
+/// for scalar types. A pseudo-destructor expression has no run-time semantics
+/// beyond evaluating the base expression.
+class CXXPseudoDestructorExpr : public Expr {
+ /// \brief The base expression (that is being destroyed).
+ Stmt *Base;
+
+ /// \brief Whether the operator was an arrow ('->'); otherwise, it was a
+ /// period ('.').
+ bool IsArrow : 1;
+
+ /// \brief The location of the '.' or '->' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The nested-name-specifier that follows the operator, if present.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The source range that covers the nested-name-specifier, if
+ /// present.
+ SourceRange QualifierRange;
+
+ /// \brief The type that precedes the '::' in a qualified pseudo-destructor
+ /// expression.
+ TypeSourceInfo *ScopeType;
+
+ /// \brief The location of the '::' in a qualified pseudo-destructor
+ /// expression.
+ SourceLocation ColonColonLoc;
+
+ /// \brief The location of the '~'.
+ SourceLocation TildeLoc;
+
+ /// \brief The type being destroyed, or its name if we were unable to
+ /// resolve the name.
+ PseudoDestructorTypeStorage DestroyedType;
+
+public:
+ CXXPseudoDestructorExpr(ASTContext &Context,
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType);
+
+ explicit CXXPseudoDestructorExpr(EmptyShell Shell)
+ : Expr(CXXPseudoDestructorExprClass, Shell),
+ Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { }
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ /// \brief Determines whether this member expression actually had
+ /// a C++ nested-name-specifier prior to the name of the member, e.g.,
+ /// x->Base::foo.
+ bool hasQualifier() const { return Qualifier != 0; }
+
+ /// \brief If the member name was qualified, retrieves the source range of
+ /// the nested-name-specifier that precedes the member name. Otherwise,
+ /// returns an empty source range.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// \brief Determine whether this pseudo-destructor expression was written
+ /// using an '->' (otherwise, it used a '.').
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '.' or '->' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieve the scope type in a qualified pseudo-destructor
+ /// expression.
+ ///
+ /// Pseudo-destructor expressions can have extra qualification within them
+ /// that is not part of the nested-name-specifier, e.g., \c p->T::~T().
+ /// Here, if the object type of the expression is (or may be) a scalar type,
+ /// \p T may also be a scalar type and, therefore, cannot be part of a
+ /// nested-name-specifier. It is stored as the "scope type" of the pseudo-
+ /// destructor expression.
+ TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
+ void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; }
+
+ /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
+ /// expression.
+ SourceLocation getColonColonLoc() const { return ColonColonLoc; }
+ void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; }
+
+ /// \brief Retrieve the location of the '~'.
+ SourceLocation getTildeLoc() const { return TildeLoc; }
+ void setTildeLoc(SourceLocation L) { TildeLoc = L; }
+
+ /// \brief Retrieve the source location information for the type
+ /// being destroyed.
+ ///
+ /// This type-source information is available for non-dependent
+ /// pseudo-destructor expressions and some dependent pseudo-destructor
+ /// expressions. Returns NULL if we only have the identifier for a
+ /// dependent pseudo-destructor expression.
+ TypeSourceInfo *getDestroyedTypeInfo() const {
+ return DestroyedType.getTypeSourceInfo();
+ }
+
+ /// \brief In a dependent pseudo-destructor expression for which we do not
+ /// have full type information on the destroyed type, provides the name
+ /// of the destroyed type.
+ IdentifierInfo *getDestroyedTypeIdentifier() const {
+ return DestroyedType.getIdentifier();
+ }
+
+ /// \brief Retrieve the type being destroyed.
+ QualType getDestroyedType() const;
+
+ /// \brief Retrieve the starting location of the type being destroyed.
+ SourceLocation getDestroyedTypeLoc() const {
+ return DestroyedType.getLocation();
+ }
+
+ /// \brief Set the name of destroyed type for a dependent pseudo-destructor
+ /// expression.
+ void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) {
+ DestroyedType = PseudoDestructorTypeStorage(II, Loc);
+ }
+
+ /// \brief Set the destroyed type.
+ void setDestroyedType(TypeSourceInfo *Info) {
+ DestroyedType = PseudoDestructorTypeStorage(Info);
+ }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXPseudoDestructorExprClass;
+ }
+ static bool classof(const CXXPseudoDestructorExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base + 1); }
+};
+
+/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_pod(int) == true
+/// __is_enum(std::string) == false
+class UnaryTypeTraitExpr : public Expr {
+ /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned.
+ unsigned UTT : 31;
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// The type being queried.
+ TypeSourceInfo *QueriedType;
+
+public:
+ UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt,
+ TypeSourceInfo *queried, bool value,
+ SourceLocation rparen, QualType ty)
+ : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, queried->getType()->isDependentType(),
+ queried->getType()->containsUnexpandedParameterPack()),
+ UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { }
+
+ explicit UnaryTypeTraitExpr(EmptyShell Empty)
+ : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false),
+ QueriedType() { }
+
+ SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+
+ UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); }
+
+ QualType getQueriedType() const { return QueriedType->getType(); }
+
+ TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryTypeTraitExprClass;
+ }
+ static bool classof(const UnaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+};
+
+/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_base_of(Base, Derived) == true
+class BinaryTypeTraitExpr : public Expr {
+ /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned.
+ unsigned BTT : 8;
+
+ /// The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// The lhs type being queried.
+ TypeSourceInfo *LhsType;
+
+ /// The rhs type being queried.
+ TypeSourceInfo *RhsType;
+
+public:
+ BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
+ TypeSourceInfo *lhsType, TypeSourceInfo *rhsType,
+ bool value, SourceLocation rparen, QualType ty)
+ : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false,
+ lhsType->getType()->isDependentType() ||
+ rhsType->getType()->isDependentType(),
+ (lhsType->getType()->containsUnexpandedParameterPack() ||
+ rhsType->getType()->containsUnexpandedParameterPack())),
+ BTT(btt), Value(value), Loc(loc), RParen(rparen),
+ LhsType(lhsType), RhsType(rhsType) { }
+
+
+ explicit BinaryTypeTraitExpr(EmptyShell Empty)
+ : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false),
+ LhsType(), RhsType() { }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Loc, RParen);
+ }
+
+ BinaryTypeTrait getTrait() const {
+ return static_cast<BinaryTypeTrait>(BTT);
+ }
+
+ QualType getLhsType() const { return LhsType->getType(); }
+ QualType getRhsType() const { return RhsType->getType(); }
+
+ TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; }
+ TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; }
+
+ bool getValue() const { assert(!isTypeDependent()); return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryTypeTraitExprClass;
+ }
+ static bool classof(const BinaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief A reference to an overloaded function set, either an
+/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
+class OverloadExpr : public Expr {
+ /// The results. These are undesugared, which is to say, they may
+ /// include UsingShadowDecls. Access is relative to the naming
+ /// class.
+ // FIXME: Allocate this data after the OverloadExpr subclass.
+ DeclAccessPair *Results;
+ unsigned NumResults;
+
+ /// The common name of these declarations.
+ DeclarationNameInfo NameInfo;
+
+ /// The scope specifier, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// The source range of the scope specifier.
+ SourceRange QualifierRange;
+
+protected:
+ /// True if the name was a template-id.
+ bool HasExplicitTemplateArgs;
+
+ OverloadExpr(StmtClass K, ASTContext &C,
+ NestedNameSpecifier *Qualifier, SourceRange QRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End,
+ bool KnownDependent = false,
+ bool KnownContainsUnexpandedParameterPack = false);
+
+ OverloadExpr(StmtClass K, EmptyShell Empty)
+ : Expr(K, Empty), Results(0), NumResults(0),
+ Qualifier(0), HasExplicitTemplateArgs(false) { }
+
+ void initializeResults(ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+
+public:
+ struct FindResult {
+ OverloadExpr *Expression;
+ bool IsAddressOfOperand;
+ bool HasFormOfMemberPointer;
+ };
+
+ /// Finds the overloaded expression in the given expression of
+ /// OverloadTy.
+ ///
+ /// \return the expression (which must be there) and true if it has
+ /// the particular form of a member pointer expression
+ static FindResult find(Expr *E) {
+ assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
+
+ FindResult Result;
+
+ E = E->IgnoreParens();
+ if (isa<UnaryOperator>(E)) {
+ assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
+ E = cast<UnaryOperator>(E)->getSubExpr();
+ OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens());
+
+ Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
+ Result.IsAddressOfOperand = true;
+ Result.Expression = Ovl;
+ } else {
+ Result.HasFormOfMemberPointer = false;
+ Result.IsAddressOfOperand = false;
+ Result.Expression = cast<OverloadExpr>(E);
+ }
+
+ return Result;
+ }
+
+ /// Gets the naming class of this lookup, if any.
+ CXXRecordDecl *getNamingClass() const;
+
+ typedef UnresolvedSetImpl::iterator decls_iterator;
+ decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); }
+ decls_iterator decls_end() const {
+ return UnresolvedSetIterator(Results + NumResults);
+ }
+
+ /// Gets the number of declarations in the unresolved set.
+ unsigned getNumDecls() const { return NumResults; }
+
+ /// Gets the full name info.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
+ /// Gets the name looked up.
+ DeclarationName getName() const { return NameInfo.getName(); }
+ void setName(DeclarationName N) { NameInfo.setName(N); }
+
+ /// Gets the location of the name.
+ SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
+ void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); }
+
+ /// Fetches the nested-name qualifier, if one was given.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// Fetches the range of the nested-name qualifier.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Determines whether this expression had an explicit
+ /// template argument list, e.g. f<int>.
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below
+
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedLookupExprClass ||
+ T->getStmtClass() == UnresolvedMemberExprClass;
+ }
+ static bool classof(const OverloadExpr *) { return true; }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief A reference to a name which we were able to look up during
+/// parsing but could not resolve to a specific declaration. This
+/// arises in several ways:
+/// * we might be waiting for argument-dependent lookup
+/// * the name might resolve to an overloaded function
+/// and eventually:
+/// * the lookup might have included a function template
+/// These never include UnresolvedUsingValueDecls, which are always
+/// class members and therefore appear only in
+/// UnresolvedMemberLookupExprs.
+class UnresolvedLookupExpr : public OverloadExpr {
+ /// True if these lookup results should be extended by
+ /// argument-dependent lookup if this is the operand of a function
+ /// call.
+ bool RequiresADL;
+
+ /// True if these lookup results are overloaded. This is pretty
+ /// trivially rederivable if we urgently need to kill this field.
+ bool Overloaded;
+
+ /// The naming class (C++ [class.access.base]p5) of the lookup, if
+ /// any. This can generally be recalculated from the context chain,
+ /// but that can be fairly expensive for unqualified lookups. If we
+ /// want to improve memory use here, this could go in a union
+ /// against the qualified-lookup bits.
+ CXXRecordDecl *NamingClass;
+
+ UnresolvedLookupExpr(ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifier *Qualifier, SourceRange QRange,
+ const DeclarationNameInfo &NameInfo,
+ bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End)
+ : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo,
+ TemplateArgs, Begin, End),
+ RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
+ {}
+
+ UnresolvedLookupExpr(EmptyShell Empty)
+ : OverloadExpr(UnresolvedLookupExprClass, Empty),
+ RequiresADL(false), Overloaded(false), NamingClass(0)
+ {}
+
+public:
+ static UnresolvedLookupExpr *Create(ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL, bool Overloaded,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier,
+ QualifierRange, NameInfo, ADL,
+ Overloaded, 0, Begin, End);
+ }
+
+ static UnresolvedLookupExpr *Create(ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL,
+ const TemplateArgumentListInfo &Args,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+
+ static UnresolvedLookupExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
+
+ /// True if this declaration should be extended by
+ /// argument-dependent lookup.
+ bool requiresADL() const { return RequiresADL; }
+ void setRequiresADL(bool V) { RequiresADL = V; }
+
+ /// True if this lookup is overloaded.
+ bool isOverloaded() const { return Overloaded; }
+ void setOverloaded(bool V) { Overloaded = V; }
+
+ /// Gets the 'naming class' (in the sense of C++0x
+ /// [class.access.base]p5) of the lookup. This is the scope
+ /// that was looked in to find these results.
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+ void setNamingClass(CXXRecordDecl *D) { NamingClass = D; }
+
+ // Note that, inconsistently with the explicit-template-argument AST
+ // nodes, users are *forbidden* from calling these methods on objects
+ // without explicit template arguments.
+
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
+ }
+
+ /// Gets a reference to the explicit template argument list.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ TemplateArgumentLoc const *getTemplateArgs() const {
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ unsigned getNumTemplateArgs() const {
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ SourceRange getSourceRange() const {
+ SourceRange Range(getNameInfo().getSourceRange());
+ if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
+ if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
+ return Range;
+ }
+
+ child_range children() { return child_range(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedLookupExprClass;
+ }
+ static bool classof(const UnresolvedLookupExpr *) { return true; }
+};
+
+/// \brief A qualified reference to a name whose declaration cannot
+/// yet be resolved.
+///
+/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that
+/// it expresses a reference to a declaration such as
+/// X<T>::value. The difference, however, is that an
+/// DependentScopeDeclRefExpr node is used only within C++ templates when
+/// the qualification (e.g., X<T>::) refers to a dependent type. In
+/// this case, X<T>::value cannot resolve to a declaration because the
+/// declaration will differ from on instantiation of X<T> to the
+/// next. Therefore, DependentScopeDeclRefExpr keeps track of the
+/// qualifier (X<T>::) and the name of the entity being referenced
+/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
+/// declaration can be found.
+class DependentScopeDeclRefExpr : public Expr {
+ /// The name of the entity we will be referencing.
+ DeclarationNameInfo NameInfo;
+
+ /// QualifierRange - The source range that covers the
+ /// nested-name-specifier.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that qualifies this unresolved
+ /// declaration name.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief Whether the name includes explicit template arguments.
+ bool HasExplicitTemplateArgs;
+
+ DependentScopeDeclRefExpr(QualType T,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args);
+
+public:
+ static DependentScopeDeclRefExpr *Create(ASTContext &C,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
+
+ static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
+
+ /// \brief Retrieve the name that this expression refers to.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
+ /// \brief Retrieve the name that this expression refers to.
+ DeclarationName getDeclName() const { return NameInfo.getName(); }
+ void setDeclName(DeclarationName N) { NameInfo.setName(N); }
+
+ /// \brief Retrieve the location of the name within the expression.
+ SourceLocation getLocation() const { return NameInfo.getLoc(); }
+ void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
+
+ /// \brief Retrieve the source range of the nested-name-specifier.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this
+ /// declaration.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// Determines whether this lookup had explicit template arguments.
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+
+ // Note that, inconsistently with the explicit-template-argument AST
+ // nodes, users are *forbidden* from calling these methods on objects
+ // without explicit template arguments.
+
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
+ }
+
+ /// Gets a reference to the explicit template argument list.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ TemplateArgumentLoc const *getTemplateArgs() const {
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ unsigned getNumTemplateArgs() const {
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ SourceRange getSourceRange() const {
+ SourceRange Range(QualifierRange.getBegin(), getLocation());
+ if (hasExplicitTemplateArgs())
+ Range.setEnd(getRAngleLoc());
+ return Range;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DependentScopeDeclRefExprClass;
+ }
+ static bool classof(const DependentScopeDeclRefExpr *) { return true; }
+
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// Represents an expression --- generally a full-expression --- which
+/// introduces cleanups to be run at the end of the sub-expression's
+/// evaluation. The most common source of expression-introduced
+/// cleanups is temporary objects in C++, but several other C++
+/// expressions can create cleanups.
+class ExprWithCleanups : public Expr {
+ Stmt *SubExpr;
+
+ CXXTemporary **Temps;
+ unsigned NumTemps;
+
+ ExprWithCleanups(ASTContext &C, Expr *SubExpr,
+ CXXTemporary **Temps, unsigned NumTemps);
+
+public:
+ ExprWithCleanups(EmptyShell Empty)
+ : Expr(ExprWithCleanupsClass, Empty),
+ SubExpr(0), Temps(0), NumTemps(0) {}
+
+ static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr,
+ CXXTemporary **Temps,
+ unsigned NumTemps);
+
+ unsigned getNumTemporaries() const { return NumTemps; }
+ void setNumTemporaries(ASTContext &C, unsigned N);
+
+ CXXTemporary *getTemporary(unsigned i) {
+ assert(i < NumTemps && "Index out of range");
+ return Temps[i];
+ }
+ const CXXTemporary *getTemporary(unsigned i) const {
+ return const_cast<ExprWithCleanups*>(this)->getTemporary(i);
+ }
+ void setTemporary(unsigned i, CXXTemporary *T) {
+ assert(i < NumTemps && "Index out of range");
+ Temps[i] = T;
+ }
+
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ SourceRange getSourceRange() const {
+ return SubExpr->getSourceRange();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExprWithCleanupsClass;
+ }
+ static bool classof(const ExprWithCleanups *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
+};
+
+/// \brief Describes an explicit type conversion that uses functional
+/// notion but could not be resolved because one or more arguments are
+/// type-dependent.
+///
+/// The explicit type conversions expressed by
+/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN),
+/// where \c T is some type and \c a1, a2, ..., aN are values, and
+/// either \C T is a dependent type or one or more of the \c a's is
+/// type-dependent. For example, this would occur in a template such
+/// as:
+///
+/// \code
+/// template<typename T, typename A1>
+/// inline T make_a(const A1& a1) {
+/// return T(a1);
+/// }
+/// \endcode
+///
+/// When the returned expression is instantiated, it may resolve to a
+/// constructor call, conversion function call, or some kind of type
+/// conversion.
+class CXXUnresolvedConstructExpr : public Expr {
+ /// \brief The type being constructed.
+ TypeSourceInfo *Type;
+
+ /// \brief The location of the left parentheses ('(').
+ SourceLocation LParenLoc;
+
+ /// \brief The location of the right parentheses (')').
+ SourceLocation RParenLoc;
+
+ /// \brief The number of arguments used to construct the type.
+ unsigned NumArgs;
+
+ CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
+ : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
+
+ friend class ASTStmtReader;
+
+public:
+ static CXXUnresolvedConstructExpr *Create(ASTContext &C,
+ TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C,
+ unsigned NumArgs);
+
+ /// \brief Retrieve the type that is being constructed, as specified
+ /// in the source code.
+ QualType getTypeAsWritten() const { return Type->getType(); }
+
+ /// \brief Retrieve the type source information for the type being
+ /// constructed.
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+
+ /// \brief Retrieve the location of the left parentheses ('(') that
+ /// precedes the argument list.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ /// \brief Retrieve the location of the right parentheses (')') that
+ /// follows the argument list.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ /// \brief Retrieve the number of arguments.
+ unsigned arg_size() const { return NumArgs; }
+
+ typedef Expr** arg_iterator;
+ arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
+ arg_iterator arg_end() { return arg_begin() + NumArgs; }
+
+ typedef const Expr* const * const_arg_iterator;
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<const Expr* const *>(this + 1);
+ }
+ const_arg_iterator arg_end() const {
+ return arg_begin() + NumArgs;
+ }
+
+ Expr *getArg(unsigned I) {
+ assert(I < NumArgs && "Argument index out-of-range");
+ return *(arg_begin() + I);
+ }
+
+ const Expr *getArg(unsigned I) const {
+ assert(I < NumArgs && "Argument index out-of-range");
+ return *(arg_begin() + I);
+ }
+
+ void setArg(unsigned I, Expr *E) {
+ assert(I < NumArgs && "Argument index out-of-range");
+ *(arg_begin() + I) = E;
+ }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUnresolvedConstructExprClass;
+ }
+ static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt**>(this+1);
+ return child_range(begin, begin + NumArgs);
+ }
+};
+
+/// \brief Represents a C++ member access expression where the actual
+/// member referenced could not be resolved because the base
+/// expression or the member name was dependent.
+///
+/// Like UnresolvedMemberExprs, these can be either implicit or
+/// explicit accesses. It is only possible to get one of these with
+/// an implicit access if a qualifier is provided.
+class CXXDependentScopeMemberExpr : public Expr {
+ /// \brief The expression for the base pointer or class reference,
+ /// e.g., the \c x in x.f. Can be null in implicit accesses.
+ Stmt *Base;
+
+ /// \brief The type of the base expression. Never null, even for
+ /// implicit accesses.
+ QualType BaseType;
+
+ /// \brief Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ bool IsArrow : 1;
+
+ /// \brief Whether this member expression has explicitly-specified template
+ /// arguments.
+ bool HasExplicitTemplateArgs : 1;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The nested-name-specifier that precedes the member name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The source range covering the nested name specifier.
+ SourceRange QualifierRange;
+
+ /// \brief In a qualified member access expression such as t->Base::f, this
+ /// member stores the resolves of name lookup in the context of the member
+ /// access expression, to be used at instantiation time.
+ ///
+ /// FIXME: This member, along with the Qualifier and QualifierRange, could
+ /// be stuck into a structure that is optionally allocated at the end of
+ /// the CXXDependentScopeMemberExpr, to save space in the common case.
+ NamedDecl *FirstQualifierFoundInScope;
+
+ /// \brief The member to which this member expression refers, which
+ /// can be name, overloaded operator, or destructor.
+ /// FIXME: could also be a template-id
+ DeclarationNameInfo MemberNameInfo;
+
+ CXXDependentScopeMemberExpr(ASTContext &C,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+public:
+ CXXDependentScopeMemberExpr(ASTContext &C,
+ Expr *Base, QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo);
+
+ static CXXDependentScopeMemberExpr *
+ Create(ASTContext &C,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ static CXXDependentScopeMemberExpr *
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
+
+ /// \brief True if this is an implicit access, i.e. one in which the
+ /// member being accessed was not written in the source. The source
+ /// location of the operator is invalid in this case.
+ bool isImplicitAccess() const { return Base == 0; }
+
+ /// \brief Retrieve the base object of this member expressions,
+ /// e.g., the \c x in \c x.m.
+ Expr *getBase() const {
+ assert(!isImplicitAccess());
+ return cast<Expr>(Base);
+ }
+ void setBase(Expr *E) { Base = E; }
+
+ QualType getBaseType() const { return BaseType; }
+ void setBaseType(QualType T) { BaseType = T; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+
+ /// \brief Retrieve the source range covering the nested-name-specifier
+ /// that qualifies the member name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+ void setQualifierRange(SourceRange R) { QualifierRange = R; }
+
+ /// \brief Retrieve the first part of the nested-name-specifier that was
+ /// found in the scope of the member access expression when the member access
+ /// was initially parsed.
+ ///
+ /// This function only returns a useful result when member access expression
+ /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
+ /// returned by this function describes what was found by unqualified name
+ /// lookup for the identifier "Base" within the scope of the member access
+ /// expression itself. At template instantiation time, this information is
+ /// combined with the results of name lookup into the type of the object
+ /// expression itself (the class type of x).
+ NamedDecl *getFirstQualifierFoundInScope() const {
+ return FirstQualifierFoundInScope;
+ }
+ void setFirstQualifierFoundInScope(NamedDecl *D) {
+ FirstQualifierFoundInScope = D;
+ }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ const DeclarationNameInfo &getMemberNameInfo() const {
+ return MemberNameInfo;
+ }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return MemberNameInfo.getName(); }
+ void setMember(DeclarationName N) { MemberNameInfo.setName(N); }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
+ void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgs() const {
+ return HasExplicitTemplateArgs;
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(HasExplicitTemplateArgs);
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<CXXDependentScopeMemberExpr *>(this)
+ ->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Initializes the template arguments using the given structure.
+ void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) {
+ getExplicitTemplateArgs().initializeFrom(List);
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following the
+ /// member name ('<'), if any.
+ SourceLocation getLAngleLoc() const {
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket following the
+ /// template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ SourceRange getSourceRange() const {
+ SourceRange Range;
+ if (!isImplicitAccess())
+ Range.setBegin(Base->getSourceRange().getBegin());
+ else if (getQualifier())
+ Range.setBegin(getQualifierRange().getBegin());
+ else
+ Range.setBegin(MemberNameInfo.getBeginLoc());
+
+ if (hasExplicitTemplateArgs())
+ Range.setEnd(getRAngleLoc());
+ else
+ Range.setEnd(MemberNameInfo.getEndLoc());
+ return Range;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDependentScopeMemberExprClass;
+ }
+ static bool classof(const CXXDependentScopeMemberExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief Represents a C++ member access expression for which lookup
+/// produced a set of overloaded functions.
+///
+/// The member access may be explicit or implicit:
+/// struct A {
+/// int a, b;
+/// int explicitAccess() { return this->a + this->A::b; }
+/// int implicitAccess() { return a + A::b; }
+/// };
+///
+/// In the final AST, an explicit access always becomes a MemberExpr.
+/// An implicit access may become either a MemberExpr or a
+/// DeclRefExpr, depending on whether the member is static.
+class UnresolvedMemberExpr : public OverloadExpr {
+ /// \brief Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ bool IsArrow : 1;
+
+ /// \brief Whether the lookup results contain an unresolved using
+ /// declaration.
+ bool HasUnresolvedUsing : 1;
+
+ /// \brief The expression for the base pointer or class reference,
+ /// e.g., the \c x in x.f. This can be null if this is an 'unbased'
+ /// member expression
+ Stmt *Base;
+
+ /// \brief The type of the base expression; never null.
+ QualType BaseType;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+
+ UnresolvedMemberExpr(EmptyShell Empty)
+ : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
+ HasUnresolvedUsing(false), Base(0) { }
+
+public:
+ static UnresolvedMemberExpr *
+ Create(ASTContext &C, bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+
+ static UnresolvedMemberExpr *
+ CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs);
+
+ /// \brief True if this is an implicit access, i.e. one in which the
+ /// member being accessed was not written in the source. The source
+ /// location of the operator is invalid in this case.
+ bool isImplicitAccess() const { return Base == 0; }
+
+ /// \brief Retrieve the base object of this member expressions,
+ /// e.g., the \c x in \c x.m.
+ Expr *getBase() {
+ assert(!isImplicitAccess());
+ return cast<Expr>(Base);
+ }
+ const Expr *getBase() const {
+ assert(!isImplicitAccess());
+ return cast<Expr>(Base);
+ }
+ void setBase(Expr *E) { Base = E; }
+
+ QualType getBaseType() const { return BaseType; }
+ void setBaseType(QualType T) { BaseType = T; }
+
+ /// \brief Determine whether the lookup results contain an unresolved using
+ /// declaration.
+ bool hasUnresolvedUsing() const { return HasUnresolvedUsing; }
+ void setHasUnresolvedUsing(bool V) { HasUnresolvedUsing = V; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieves the naming class of this lookup.
+ CXXRecordDecl *getNamingClass() const;
+
+ /// \brief Retrieve the full name info for the member that this expression
+ /// refers to.
+ const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMemberName() const { return getName(); }
+ void setMemberName(DeclarationName N) { setName(N); }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return getNameLoc(); }
+ void setMemberLoc(SourceLocation L) { setNameLoc(L); }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name, if any.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ assert(hasExplicitTemplateArgs());
+ return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
+ /// \brief Copies the template arguments into the given structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Retrieve the location of the left angle bracket following
+ /// the member name ('<').
+ SourceLocation getLAngleLoc() const {
+ return getExplicitTemplateArgs().LAngleLoc;
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return getExplicitTemplateArgs().getTemplateArgs();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as
+ /// part of this template-id.
+ unsigned getNumTemplateArgs() const {
+ return getExplicitTemplateArgs().NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket
+ /// following the template arguments ('>').
+ SourceLocation getRAngleLoc() const {
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ SourceRange getSourceRange() const {
+ SourceRange Range = getMemberNameInfo().getSourceRange();
+ if (!isImplicitAccess())
+ Range.setBegin(Base->getSourceRange().getBegin());
+ else if (getQualifier())
+ Range.setBegin(getQualifierRange().getBegin());
+
+ if (hasExplicitTemplateArgs())
+ Range.setEnd(getRAngleLoc());
+ return Range;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedMemberExprClass;
+ }
+ static bool classof(const UnresolvedMemberExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (isImplicitAccess()) return child_range();
+ return child_range(&Base, &Base + 1);
+ }
+};
+
+/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]).
+///
+/// The noexcept expression tests whether a given expression might throw. Its
+/// result is a boolean constant.
+class CXXNoexceptExpr : public Expr {
+ bool Value : 1;
+ Stmt *Operand;
+ SourceRange Range;
+
+ friend class ASTStmtReader;
+
+public:
+ CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
+ SourceLocation Keyword, SourceLocation RParen)
+ : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
+ /*TypeDependent*/false,
+ /*ValueDependent*/Val == CT_Dependent,
+ Operand->containsUnexpandedParameterPack()),
+ Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen)
+ { }
+
+ CXXNoexceptExpr(EmptyShell Empty)
+ : Expr(CXXNoexceptExprClass, Empty)
+ { }
+
+ Expr *getOperand() const { return static_cast<Expr*>(Operand); }
+
+ SourceRange getSourceRange() const { return Range; }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNoexceptExprClass;
+ }
+ static bool classof(const CXXNoexceptExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Operand, &Operand + 1); }
+};
+
+/// \brief Represents a C++0x pack expansion that produces a sequence of
+/// expressions.
+///
+/// A pack expansion expression contains a pattern (which itself is an
+/// expression) followed by an ellipsis. For example:
+///
+/// \code
+/// template<typename F, typename ...Types>
+/// void forward(F f, Types &&...args) {
+/// f(static_cast<Types&&>(args)...);
+/// }
+/// \endcode
+///
+/// Here, the argument to the function object \c f is a pack expansion whose
+/// pattern is \c static_cast<Types&&>(args). When the \c forward function
+/// template is instantiated, the pack expansion will instantiate to zero or
+/// or more function arguments to the function object \c f.
+class PackExpansionExpr : public Expr {
+ SourceLocation EllipsisLoc;
+
+ /// \brief The number of expansions that will be produced by this pack
+ /// expansion expression, if known.
+ ///
+ /// When zero, the number of expansions is not known. Otherwise, this value
+ /// is the number of expansions + 1.
+ unsigned NumExpansions;
+
+ Stmt *Pattern;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions)
+ : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
+ Pattern->getObjectKind(), /*TypeDependent=*/true,
+ /*ValueDependent=*/true, /*ContainsUnexpandedParameterPack=*/false),
+ EllipsisLoc(EllipsisLoc),
+ NumExpansions(NumExpansions? *NumExpansions + 1 : 0),
+ Pattern(Pattern) { }
+
+ PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the pattern of the pack expansion.
+ const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); }
+
+ /// \brief Retrieve the location of the ellipsis that describes this pack
+ /// expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// \brief Determine the number of expansions that will be produced when
+ /// this pack expansion is instantiated, if already known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(Pattern->getLocStart(), EllipsisLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PackExpansionExprClass;
+ }
+ static bool classof(const PackExpansionExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Pattern, &Pattern + 1);
+ }
+};
+
+inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
+ else
+ return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs();
+}
+
+/// \brief Represents an expression that computes the length of a parameter
+/// pack.
+///
+/// \code
+/// template<typename ...Types>
+/// struct count {
+/// static const unsigned value = sizeof...(Types);
+/// };
+/// \endcode
+class SizeOfPackExpr : public Expr {
+ /// \brief The location of the 'sizeof' keyword.
+ SourceLocation OperatorLoc;
+
+ /// \brief The location of the name of the parameter pack.
+ SourceLocation PackLoc;
+
+ /// \brief The location of the closing parenthesis.
+ SourceLocation RParenLoc;
+
+ /// \brief The length of the parameter pack, if known.
+ ///
+ /// When this expression is value-dependent, the length of the parameter pack
+ /// is unknown. When this expression is not value-dependent, the length is
+ /// known.
+ unsigned Length;
+
+ /// \brief The parameter pack itself.
+ NamedDecl *Pack;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ /// \brief Creates a value-dependent expression that computes the length of
+ /// the given parameter pack.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/true,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(0), Pack(Pack) { }
+
+ /// \brief Creates an expression that computes the length of
+ /// the given parameter pack, which is already known.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc,
+ unsigned Length)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(Length), Pack(Pack) { }
+
+ /// \brief Create an empty expression.
+ SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { }
+
+ /// \brief Determine the location of the 'sizeof' keyword.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Determine the location of the parameter pack.
+ SourceLocation getPackLoc() const { return PackLoc; }
+
+ /// \brief Determine the location of the right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// \brief Retrieve the parameter pack.
+ NamedDecl *getPack() const { return Pack; }
+
+ /// \brief Retrieve the length of the parameter pack.
+ ///
+ /// This routine may only be invoked when the expression is not
+ /// value-dependent.
+ unsigned getPackLength() const {
+ assert(!isValueDependent() &&
+ "Cannot get the length of a value-dependent pack size expression");
+ return Length;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(OperatorLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfPackExprClass;
+ }
+ static bool classof(const SizeOfPackExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// \brief Represents a reference to a non-type template parameter pack that
+/// has been substituted with a non-template argument pack.
+///
+/// When a pack expansion in the source code contains multiple parameter packs
+/// and those parameter packs correspond to different levels of template
+/// parameter lists, this node node is used to represent a non-type template
+/// parameter pack from an outer level, which has already had its argument pack
+/// substituted but that still lives within a pack expansion that itself
+/// could not be instantiated. When actually performing a substitution into
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the appropriate underlying
+/// expression at the current pack substitution index.
+class SubstNonTypeTemplateParmPackExpr : public Expr {
+ /// \brief The non-type template parameter pack itself.
+ NonTypeTemplateParmDecl *Param;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ /// \brief The location of the non-type template parameter pack reference.
+ SourceLocation NameLoc;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack);
+
+ SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+
+ /// \brief Retrieve the non-type template parameter pack being substituted.
+ NonTypeTemplateParmDecl *getParameterPack() const { return Param; }
+
+ /// \brief Retrieve the location of the parameter pack name.
+ SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+ /// \brief Retrieve the template argument pack containing the substituted
+ /// template arguments.
+ TemplateArgument getArgumentPack() const;
+
+ SourceRange getSourceRange() const { return NameLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
+ }
+ static bool classof(const SubstNonTypeTemplateParmPackExpr *) {
+ return true;
+ }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
new file mode 100644
index 0000000..285efb7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
@@ -0,0 +1,859 @@
+//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 ExprObjC interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPROBJC_H
+#define LLVM_CLANG_AST_EXPROBJC_H
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+ class IdentifierInfo;
+ class ASTContext;
+
+/// ObjCStringLiteral, used for Objective-C string literals
+/// i.e. @"foo".
+class ObjCStringLiteral : public Expr {
+ Stmt *String;
+ SourceLocation AtLoc;
+public:
+ ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
+ : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ String(SL), AtLoc(L) {}
+ explicit ObjCStringLiteral(EmptyShell Empty)
+ : Expr(ObjCStringLiteralClass, Empty) {}
+
+ StringLiteral *getString() { return cast<StringLiteral>(String); }
+ const StringLiteral *getString() const { return cast<StringLiteral>(String); }
+ void setString(StringLiteral *S) { String = S; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, String->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCStringLiteralClass;
+ }
+ static bool classof(const ObjCStringLiteral *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&String, &String+1); }
+};
+
+/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
+/// and behavior as StringLiteral except that the string initializer is obtained
+/// from ASTContext with the encoding type as an argument.
+class ObjCEncodeExpr : public Expr {
+ TypeSourceInfo *EncodedType;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->isDependentType(),
+ EncodedType->getType()->containsUnexpandedParameterPack()),
+ EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
+
+ explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
+
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ QualType getEncodedType() const { return EncodedType->getType(); }
+
+ TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
+ void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
+ EncodedType = EncType;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCEncodeExprClass;
+ }
+ static bool classof(const ObjCEncodeExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ObjCSelectorExpr used for @selector in Objective-C.
+class ObjCSelectorExpr : public Expr {
+ Selector SelName;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCSelectorExpr(QualType T, Selector selInfo,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ SelName(selInfo), AtLoc(at), RParenLoc(rp){}
+ explicit ObjCSelectorExpr(EmptyShell Empty)
+ : Expr(ObjCSelectorExprClass, Empty) {}
+
+ Selector getSelector() const { return SelName; }
+ void setSelector(Selector S) { SelName = S; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ /// getNumArgs - Return the number of actual arguments to this call.
+ unsigned getNumArgs() const { return SelName.getNumArgs(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSelectorExprClass;
+ }
+ static bool classof(const ObjCSelectorExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used
+/// as: @protocol(foo), as in:
+/// obj conformsToProtocol:@protocol(foo)]
+/// The return type is "Protocol*".
+class ObjCProtocolExpr : public Expr {
+ ObjCProtocolDecl *TheProtocol;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false),
+ TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {}
+ explicit ObjCProtocolExpr(EmptyShell Empty)
+ : Expr(ObjCProtocolExprClass, Empty) {}
+
+ ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
+ void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCProtocolExprClass;
+ }
+ static bool classof(const ObjCProtocolExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
+class ObjCIvarRefExpr : public Expr {
+ class ObjCIvarDecl *D;
+ SourceLocation Loc;
+ Stmt *Base;
+ bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
+ bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
+
+public:
+ ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
+ SourceLocation l, Expr *base,
+ bool arrow = false, bool freeIvar = false) :
+ Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {}
+
+ explicit ObjCIvarRefExpr(EmptyShell Empty)
+ : Expr(ObjCIvarRefExprClass, Empty) {}
+
+ ObjCIvarDecl *getDecl() { return D; }
+ const ObjCIvarDecl *getDecl() const { return D; }
+ void setDecl(ObjCIvarDecl *d) { D = d; }
+
+ const Expr *getBase() const { return cast<Expr>(Base); }
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr * base) { Base = base; }
+
+ bool isArrow() const { return IsArrow; }
+ bool isFreeIvar() const { return IsFreeIvar; }
+ void setIsArrow(bool A) { IsArrow = A; }
+ void setIsFreeIvar(bool A) { IsFreeIvar = A; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceRange getSourceRange() const {
+ return isFreeIvar() ? SourceRange(Loc)
+ : SourceRange(getBase()->getLocStart(), Loc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIvarRefExprClass;
+ }
+ static bool classof(const ObjCIvarRefExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+};
+
+/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
+/// property.
+///
+class ObjCPropertyRefExpr : public Expr {
+private:
+ /// If the bool is true, this is an implicit property reference; the
+ /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
+ /// if the bool is false, this is an explicit property reference;
+ /// the pointer is an ObjCPropertyDecl and Setter is always null.
+ llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
+ ObjCMethodDecl *Setter;
+
+ SourceLocation IdLoc;
+
+ /// \brief When the receiver in property access is 'super', this is
+ /// the location of the 'super' keyword. When it's an interface,
+ /// this is that interface.
+ SourceLocation ReceiverLoc;
+ llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
+
+public:
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, Expr *base)
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(), Receiver(base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, SourceLocation sl, QualType st)
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, false,
+ st->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), Setter(0),
+ IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc, Expr *Base)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
+ Base->isValueDependent(),
+ Base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation SuperLoc, QualType SuperTy)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc,
+ SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
+ PropertyOrGetter(Getter, true), Setter(Setter),
+ IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
+ }
+
+ explicit ObjCPropertyRefExpr(EmptyShell Empty)
+ : Expr(ObjCPropertyRefExprClass, Empty) {}
+
+ bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
+ bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
+
+ ObjCPropertyDecl *getExplicitProperty() const {
+ assert(!isImplicitProperty());
+ return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertyGetter() const {
+ assert(isImplicitProperty());
+ return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
+ }
+
+ ObjCMethodDecl *getImplicitPropertySetter() const {
+ assert(isImplicitProperty());
+ return Setter;
+ }
+
+ Selector getGetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertyGetter()->getSelector();
+ return getExplicitProperty()->getGetterName();
+ }
+
+ Selector getSetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertySetter()->getSelector();
+ return getExplicitProperty()->getSetterName();
+ }
+
+ const Expr *getBase() const {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
+ Expr *getBase() {
+ return cast<Expr>(Receiver.get<Stmt*>());
+ }
+
+ SourceLocation getLocation() const { return IdLoc; }
+
+ SourceLocation getReceiverLocation() const { return ReceiverLoc; }
+ QualType getSuperReceiverType() const {
+ return QualType(Receiver.get<const Type*>(), 0);
+ }
+ ObjCInterfaceDecl *getClassReceiver() const {
+ return Receiver.get<ObjCInterfaceDecl*>();
+ }
+ bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
+ bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
+ bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
+
+ SourceRange getSourceRange() const {
+ return SourceRange((isObjectReceiver() ? getBase()->getLocStart()
+ : getReceiverLocation()),
+ IdLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCPropertyRefExprClass;
+ }
+ static bool classof(const ObjCPropertyRefExpr *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (Receiver.is<Stmt*>()) {
+ Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
+ return child_range(begin, begin+1);
+ }
+ return child_range();
+ }
+
+private:
+ friend class ASTStmtReader;
+ void setExplicitProperty(ObjCPropertyDecl *D) {
+ PropertyOrGetter.setPointer(D);
+ PropertyOrGetter.setInt(false);
+ Setter = 0;
+ }
+ void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) {
+ PropertyOrGetter.setPointer(Getter);
+ PropertyOrGetter.setInt(true);
+ this->Setter = Setter;
+ }
+ void setBase(Expr *Base) { Receiver = Base; }
+ void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
+ void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
+
+ void setLocation(SourceLocation L) { IdLoc = L; }
+ void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
+};
+
+/// \brief An expression that sends a message to the given Objective-C
+/// object or class.
+///
+/// The following contains two message send expressions:
+///
+/// \code
+/// [[NSString alloc] initWithString:@"Hello"]
+/// \endcode
+///
+/// The innermost message send invokes the "alloc" class method on the
+/// NSString class, while the outermost message send invokes the
+/// "initWithString" instance method on the object returned from
+/// NSString's "alloc". In all, an Objective-C message send can take
+/// on four different (although related) forms:
+///
+/// 1. Send to an object instance.
+/// 2. Send to a class.
+/// 3. Send to the superclass instance of the current class.
+/// 4. Send to the superclass of the current class.
+///
+/// All four kinds of message sends are modeled by the ObjCMessageExpr
+/// class, and can be distinguished via \c getReceiverKind(). Example:
+///
+class ObjCMessageExpr : public Expr {
+ /// \brief The number of arguments in the message send, not
+ /// including the receiver.
+ unsigned NumArgs : 16;
+
+ /// \brief The kind of message send this is, which is one of the
+ /// ReceiverKind values.
+ ///
+ /// We pad this out to a byte to avoid excessive masking and shifting.
+ unsigned Kind : 8;
+
+ /// \brief Whether we have an actual method prototype in \c
+ /// SelectorOrMethod.
+ ///
+ /// When non-zero, we have a method declaration; otherwise, we just
+ /// have a selector.
+ unsigned HasMethod : 8;
+
+ /// \brief When the message expression is a send to 'super', this is
+ /// the location of the 'super' keyword.
+ SourceLocation SuperLoc;
+
+ /// \brief Stores either the selector that this message is sending
+ /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
+ /// referring to the method that we type-checked against.
+ uintptr_t SelectorOrMethod;
+
+ /// \brief Location of the selector.
+ SourceLocation SelectorLoc;
+
+ /// \brief The source locations of the open and close square
+ /// brackets ('[' and ']', respectively).
+ SourceLocation LBracLoc, RBracLoc;
+
+ ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
+ : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0),
+ HasMethod(0), SelectorOrMethod(0) { }
+
+ 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);
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ SourceLocation SelLoc,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc);
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation SelLoc,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc);
+
+ /// \brief Retrieve the pointer value of the message receiver.
+ void *getReceiverPointer() const {
+ return *const_cast<void **>(
+ reinterpret_cast<const void * const*>(this + 1));
+ }
+
+ /// \brief Set the pointer value of the message receiver.
+ void setReceiverPointer(void *Value) {
+ *reinterpret_cast<void **>(this + 1) = Value;
+ }
+
+public:
+ /// \brief The kind of receiver this message is sending to.
+ enum ReceiverKind {
+ /// \brief The receiver is a class.
+ Class = 0,
+ /// \brief The receiver is an object instance.
+ Instance,
+ /// \brief The receiver is a superclass.
+ SuperClass,
+ /// \brief The receiver is the instance of the superclass object.
+ SuperInstance
+ };
+
+ /// \brief Create a message send to super.
+ ///
+ /// \param Context The ASTContext in which this expression will be created.
+ ///
+ /// \param T The result type of this message.
+ ///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
+ /// \param LBrac The location of the open square bracket '['.
+ ///
+ /// \param SuperLoc The location of the "super" keyword.
+ ///
+ /// \param IsInstanceSuper Whether this is an instance "super"
+ /// message (otherwise, it's a class "super" message).
+ ///
+ /// \param Sel The selector used to determine which method gets called.
+ ///
+ /// \param Method The Objective-C method against which this message
+ /// send was type-checked. May be NULL.
+ ///
+ /// \param Args The message send arguments.
+ ///
+ /// \param NumArgs The number of arguments.
+ ///
+ /// \param RBracLoc The location of the closing square bracket ']'.
+ static 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);
+
+ /// \brief Create a class message send.
+ ///
+ /// \param Context The ASTContext in which this expression will be created.
+ ///
+ /// \param T The result type of this message.
+ ///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
+ /// \param LBrac The location of the open square bracket '['.
+ ///
+ /// \param Receiver The type of the receiver, including
+ /// source-location information.
+ ///
+ /// \param Sel The selector used to determine which method gets called.
+ ///
+ /// \param Method The Objective-C method against which this message
+ /// send was type-checked. May be NULL.
+ ///
+ /// \param Args The message send arguments.
+ ///
+ /// \param NumArgs The number of arguments.
+ ///
+ /// \param RBracLoc The location of the closing square bracket ']'.
+ static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ SourceLocation SelLoc,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc);
+
+ /// \brief Create an instance message send.
+ ///
+ /// \param Context The ASTContext in which this expression will be created.
+ ///
+ /// \param T The result type of this message.
+ ///
+ /// \param VK The value kind of this message. A message returning
+ /// a l-value or r-value reference will be an l-value or x-value,
+ /// respectively.
+ ///
+ /// \param LBrac The location of the open square bracket '['.
+ ///
+ /// \param Receiver The expression used to produce the object that
+ /// will receive this message.
+ ///
+ /// \param Sel The selector used to determine which method gets called.
+ ///
+ /// \param Method The Objective-C method against which this message
+ /// send was type-checked. May be NULL.
+ ///
+ /// \param Args The message send arguments.
+ ///
+ /// \param NumArgs The number of arguments.
+ ///
+ /// \param RBracLoc The location of the closing square bracket ']'.
+ static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation SelLoc,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc);
+
+ /// \brief Create an empty Objective-C message expression, to be
+ /// filled in by subsequent calls.
+ ///
+ /// \param Context The context in which the message send will be created.
+ ///
+ /// \param NumArgs The number of message arguments, not including
+ /// the receiver.
+ static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs);
+
+ /// \brief Determine the kind of receiver that this message is being
+ /// sent to.
+ ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
+
+ /// \brief Source range of the receiver.
+ SourceRange getReceiverRange() const;
+
+ /// \brief Determine whether this is an instance message to either a
+ /// computed object or to super.
+ bool isInstanceMessage() const {
+ return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
+ }
+
+ /// \brief Determine whether this is an class message to either a
+ /// specified class or to super.
+ bool isClassMessage() const {
+ return getReceiverKind() == Class || getReceiverKind() == SuperClass;
+ }
+
+ /// \brief Returns the receiver of an instance message.
+ ///
+ /// \brief Returns the object expression for an instance message, or
+ /// NULL for a message that is not an instance message.
+ Expr *getInstanceReceiver() {
+ if (getReceiverKind() == Instance)
+ return static_cast<Expr *>(getReceiverPointer());
+
+ return 0;
+ }
+ const Expr *getInstanceReceiver() const {
+ return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
+ }
+
+ /// \brief Turn this message send into an instance message that
+ /// computes the receiver object with the given expression.
+ void setInstanceReceiver(Expr *rec) {
+ Kind = Instance;
+ setReceiverPointer(rec);
+ }
+
+ /// \brief Returns the type of a class message send, or NULL if the
+ /// message is not a class message.
+ QualType getClassReceiver() const {
+ if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
+ return TSInfo->getType();
+
+ return QualType();
+ }
+
+ /// \brief Returns a type-source information of a class message
+ /// send, or NULL if the message is not a class message.
+ TypeSourceInfo *getClassReceiverTypeInfo() const {
+ if (getReceiverKind() == Class)
+ return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
+ return 0;
+ }
+
+ void setClassReceiver(TypeSourceInfo *TSInfo) {
+ Kind = Class;
+ setReceiverPointer(TSInfo);
+ }
+
+ /// \brief Retrieve the location of the 'super' keyword for a class
+ /// or instance message to 'super', otherwise an invalid source location.
+ SourceLocation getSuperLoc() const {
+ if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
+ return SuperLoc;
+
+ return SourceLocation();
+ }
+
+ /// \brief Retrieve the Objective-C interface to which this message
+ /// is being directed, if known.
+ ///
+ /// This routine cross-cuts all of the different kinds of message
+ /// sends to determine what the underlying (statically known) type
+ /// of the receiver will be; use \c getReceiverKind() to determine
+ /// whether the message is a class or an instance method, whether it
+ /// is a send to super or not, etc.
+ ///
+ /// \returns The Objective-C interface if known, otherwise NULL.
+ ObjCInterfaceDecl *getReceiverInterface() const;
+
+ /// \brief Retrieve the type referred to by 'super'.
+ ///
+ /// The returned type will either be an ObjCInterfaceType (for an
+ /// class message to super) or an ObjCObjectPointerType that refers
+ /// to a class (for an instance message to super);
+ QualType getSuperType() const {
+ if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
+ return QualType::getFromOpaquePtr(getReceiverPointer());
+
+ return QualType();
+ }
+
+ void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
+ Kind = IsInstanceSuper? SuperInstance : SuperClass;
+ SuperLoc = Loc;
+ setReceiverPointer(T.getAsOpaquePtr());
+ }
+
+ Selector getSelector() const;
+
+ void setSelector(Selector S) {
+ HasMethod = false;
+ SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
+ }
+
+ const ObjCMethodDecl *getMethodDecl() const {
+ if (HasMethod)
+ return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
+
+ return 0;
+ }
+
+ ObjCMethodDecl *getMethodDecl() {
+ if (HasMethod)
+ return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
+
+ return 0;
+ }
+
+ void setMethodDecl(ObjCMethodDecl *MD) {
+ HasMethod = true;
+ SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
+ }
+
+ /// \brief Return the number of actual arguments in this message,
+ /// not counting the receiver.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief Retrieve the arguments to this message, not including the
+ /// receiver.
+ Expr **getArgs() {
+ return reinterpret_cast<Expr **>(this + 1) + 1;
+ }
+ const Expr * const *getArgs() const {
+ return reinterpret_cast<const Expr * const *>(this + 1) + 1;
+ }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(getArgs()[Arg]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(getArgs()[Arg]);
+ }
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ getArgs()[Arg] = ArgExpr;
+ }
+
+ SourceLocation getLeftLoc() const { return LBracLoc; }
+ SourceLocation getRightLoc() const { return RBracLoc; }
+ SourceLocation getSelectorLoc() const { return SelectorLoc; }
+
+ void setSourceRange(SourceRange R) {
+ LBracLoc = R.getBegin();
+ RBracLoc = R.getEnd();
+ }
+ SourceRange getSourceRange() const {
+ return SourceRange(LBracLoc, RBracLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCMessageExprClass;
+ }
+ static bool classof(const ObjCMessageExpr *) { return true; }
+
+ // Iterators
+ child_range children();
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
+ arg_iterator arg_end() {
+ return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
+ }
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs());
+ }
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
+/// (similiar in spirit to MemberExpr).
+class ObjCIsaExpr : public Expr {
+ /// Base - the expression for the base object pointer.
+ Stmt *Base;
+
+ /// IsaMemberLoc - This is the location of the 'isa'.
+ SourceLocation IsaMemberLoc;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ bool IsArrow;
+public:
+ ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
+ : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
+
+ /// \brief Build an empty expression.
+ explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// getMemberLoc - Return the location of the "member", in X->F, it is the
+ /// location of 'F'.
+ SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
+ void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
+ }
+
+ SourceLocation getExprLoc() const { return IsaMemberLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIsaExprClass;
+ }
+ static bool classof(const ObjCIsaExpr *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
new file mode 100644
index 0000000..7b23766
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
@@ -0,0 +1,276 @@
+//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalASTSource interface, which enables
+// construction of AST nodes from some external source.x
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+
+#include "clang/AST/DeclBase.h"
+#include <cassert>
+#include <vector>
+
+namespace llvm {
+template <class T> class SmallVectorImpl;
+}
+
+namespace clang {
+
+class ASTConsumer;
+class CXXBaseSpecifier;
+class Decl;
+class DeclContext;
+class DeclContextLookupResult;
+class DeclarationName;
+class ExternalSemaSource; // layering violation required for downcasting
+class NamedDecl;
+class Selector;
+class Stmt;
+class TagDecl;
+
+/// \brief Abstract interface for external sources of AST nodes.
+///
+/// External AST sources provide AST nodes constructed from some
+/// external source, such as a precompiled header. External AST
+/// sources can resolve types and declarations from abstract IDs into
+/// actual type and declaration nodes, and read parts of declaration
+/// contexts.
+class ExternalASTSource {
+ /// \brief Whether this AST source also provides information for
+ /// semantic analysis.
+ bool SemaSource;
+
+ friend class ExternalSemaSource;
+
+public:
+ ExternalASTSource() : SemaSource(false) { }
+
+ virtual ~ExternalASTSource();
+
+ /// \brief RAII class for safely pairing a StartedDeserializing call
+ /// with FinishedDeserializing.
+ class Deserializing {
+ ExternalASTSource *Source;
+ public:
+ explicit Deserializing(ExternalASTSource *source) : Source(source) {
+ assert(Source);
+ Source->StartedDeserializing();
+ }
+ ~Deserializing() {
+ Source->FinishedDeserializing();
+ }
+ };
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ ///
+ /// This method only needs to be implemented if the AST source ever
+ /// passes back decl sets as VisibleDeclaration objects.
+ virtual Decl *GetExternalDecl(uint32_t ID) = 0;
+
+ /// \brief Resolve a selector ID into a selector.
+ ///
+ /// This operation only needs to be implemented if the AST source
+ /// returns non-zero for GetNumKnownSelectors().
+ virtual Selector GetExternalSelector(uint32_t ID) = 0;
+
+ /// \brief Returns the number of selectors known to the external AST
+ /// source.
+ virtual uint32_t GetNumExternalSelectors() = 0;
+
+ /// \brief Resolve the offset of a statement in the decl stream into
+ /// a statement.
+ ///
+ /// This operation is meant to be used via a LazyOffsetPtr. It only
+ /// needs to be implemented if the AST source uses methods like
+ /// FunctionDecl::setLazyBody when building decls.
+ virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
+
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0;
+
+ /// \brief Finds all declarations with the given name in the
+ /// given context.
+ ///
+ /// Generally the final step of this method is either to call
+ /// SetExternalVisibleDeclsForName or to recursively call lookup on
+ /// the DeclContext after calling SetExternalVisibleDecls.
+ virtual DeclContextLookupResult
+ FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) = 0;
+
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table of the DeclContext.
+ virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
+
+ /// \brief Finds all declarations lexically contained within the given
+ /// DeclContext, after applying an optional filter predicate.
+ ///
+ /// \param isKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for. If NULL, all declarations
+ /// are returned.
+ ///
+ /// \return true if an error occurred
+ virtual bool FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ llvm::SmallVectorImpl<Decl*> &Result) = 0;
+
+ /// \brief Finds all declarations lexically contained within the given
+ /// DeclContext.
+ ///
+ /// \return true if an error occurred
+ bool FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, 0, Result);
+ }
+
+ template <typename DeclTy>
+ bool FindExternalLexicalDeclsBy(const DeclContext *DC,
+ llvm::SmallVectorImpl<Decl*> &Result) {
+ return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
+ }
+
+ /// \brief Gives the external AST source an opportunity to complete
+ /// an incomplete type.
+ virtual void CompleteType(TagDecl *Tag) {}
+
+ /// \brief Gives the external AST source an opportunity to complete an
+ /// incomplete Objective-C class.
+ ///
+ /// This routine will only be invoked if the "externally completed" bit is
+ /// set on the ObjCInterfaceDecl via the function
+ /// \c ObjCInterfaceDecl::setExternallyCompleted().
+ virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+
+ /// \brief Notify ExternalASTSource that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void StartedDeserializing() { }
+
+ /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void FinishedDeserializing() { }
+
+ /// \brief Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
+
+ /// \brief Print any statistics that have been gathered regarding
+ /// the external AST source.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void PrintStats();
+
+protected:
+ static DeclContextLookupResult
+ SetExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls);
+
+ static DeclContextLookupResult
+ SetNoExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name);
+
+ void MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls);
+};
+
+/// \brief A lazy pointer to an AST node (of base type T) that resides
+/// within an external AST source.
+///
+/// The AST node is identified within the external AST source by a
+/// 63-bit offset, and can be retrieved via an operation on the
+/// external AST source itself.
+template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
+struct LazyOffsetPtr {
+ /// \brief Either a pointer to an AST node or the offset within the
+ /// external AST source where the AST node can be found.
+ ///
+ /// If the low bit is clear, a pointer to the AST node. If the low
+ /// bit is set, the upper 63 bits are the offset.
+ mutable uint64_t Ptr;
+
+public:
+ LazyOffsetPtr() : Ptr(0) { }
+
+ explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
+ explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
+ assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+ if (Offset == 0)
+ Ptr = 0;
+ }
+
+ LazyOffsetPtr &operator=(T *Ptr) {
+ this->Ptr = reinterpret_cast<uint64_t>(Ptr);
+ return *this;
+ }
+
+ LazyOffsetPtr &operator=(uint64_t Offset) {
+ assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+ if (Offset == 0)
+ Ptr = 0;
+ else
+ Ptr = (Offset << 1) | 0x01;
+
+ return *this;
+ }
+
+ /// \brief Whether this pointer is non-NULL.
+ ///
+ /// This operation does not require the AST node to be deserialized.
+ operator bool() const { return Ptr != 0; }
+
+ /// \brief Whether this pointer is currently stored as an offset.
+ bool isOffset() const { return Ptr & 0x01; }
+
+ /// \brief Retrieve the pointer to the AST node that this lazy pointer
+ ///
+ /// \param Source the external AST source.
+ ///
+ /// \returns a pointer to the AST node.
+ T* get(ExternalASTSource *Source) const {
+ if (isOffset()) {
+ assert(Source &&
+ "Cannot deserialize a lazy pointer without an AST source");
+ Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
+ }
+ return reinterpret_cast<T*>(Ptr);
+ }
+};
+
+/// \brief A lazy pointer to a statement.
+typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
+ LazyDeclStmtPtr;
+
+/// \brief A lazy pointer to a declaration.
+typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
+ LazyDeclPtr;
+
+/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>
+ LazyCXXBaseSpecifiersPtr;
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
new file mode 100644
index 0000000..7af7702
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
@@ -0,0 +1,150 @@
+//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the C++ name mangling interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MANGLE_H
+#define LLVM_CLANG_AST_MANGLE_H
+
+#include "clang/AST/Type.h"
+#include "clang/Basic/ABI.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+ class ASTContext;
+ class BlockDecl;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class FunctionDecl;
+ class NamedDecl;
+ class ObjCMethodDecl;
+ class VarDecl;
+ struct ThisAdjustment;
+ struct ThunkInfo;
+
+/// MangleBuffer - a convenient class for storing a name which is
+/// either the result of a mangling or is a constant string with
+/// external memory ownership.
+class MangleBuffer {
+public:
+ void setString(llvm::StringRef Ref) {
+ String = Ref;
+ }
+
+ llvm::SmallVectorImpl<char> &getBuffer() {
+ return Buffer;
+ }
+
+ llvm::StringRef getString() const {
+ if (!String.empty()) return String;
+ return Buffer.str();
+ }
+
+ operator llvm::StringRef() const {
+ return getString();
+ }
+
+private:
+ llvm::StringRef String;
+ llvm::SmallString<256> Buffer;
+};
+
+/// MangleContext - Context for tracking state which persists across multiple
+/// calls to the C++ name mangler.
+class MangleContext {
+ ASTContext &Context;
+ Diagnostic &Diags;
+
+ llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
+ llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
+
+public:
+ explicit MangleContext(ASTContext &Context,
+ Diagnostic &Diags)
+ : Context(Context), Diags(Diags) { }
+
+ virtual ~MangleContext() { }
+
+ ASTContext &getASTContext() const { return Context; }
+
+ Diagnostic &getDiags() const { return Diags; }
+
+ virtual void startNewFunction() { LocalBlockIds.clear(); }
+
+ unsigned getBlockId(const BlockDecl *BD, bool Local) {
+ llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
+ = Local? LocalBlockIds : GlobalBlockIds;
+ std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
+ Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
+ return Result.first->second;
+ }
+
+ /// @name Mangler Entry Points
+ /// @{
+
+ virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
+ virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &)=0;
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleReferenceTemporary(const VarDecl *D,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &) = 0;
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ llvm::raw_ostream &) = 0;
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ llvm::raw_ostream &) = 0;
+
+ void mangleGlobalBlock(const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
+ const BlockDecl *BD, llvm::raw_ostream &Out);
+ void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
+ llvm::raw_ostream &Out);
+ // Do the right thing.
+ void mangleBlock(const BlockDecl *BD, llvm::raw_ostream &Out);
+
+ void mangleObjCMethodName(const ObjCMethodDecl *MD,
+ llvm::raw_ostream &);
+
+ // This is pretty lame.
+ virtual void mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::raw_ostream &) {
+ assert(0 && "Target does not support mangling guard variables");
+ }
+ /// @}
+};
+
+MangleContext *createItaniumMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+MangleContext *createMicrosoftMangleContext(ASTContext &Context,
+ Diagnostic &Diags);
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
new file mode 100644
index 0000000..99cc1f2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -0,0 +1,205 @@
+//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NestedNameSpecifier class, which represents
+// a C++ nested-name-specifier.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
+#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class ASTContext;
+class NamespaceDecl;
+class IdentifierInfo;
+struct PrintingPolicy;
+class Type;
+class LangOptions;
+
+/// \brief Represents a C++ nested name specifier, such as
+/// "::std::vector<int>::".
+///
+/// C++ nested name specifiers are the prefixes to qualified
+/// namespaces. For example, "foo::" in "foo::x" is a nested name
+/// specifier. Nested name specifiers are made up of a sequence of
+/// specifiers, each of which can be a namespace, type, identifier
+/// (for dependent names), or the global specifier ('::', must be the
+/// first specifier).
+class NestedNameSpecifier : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that precedes this nested name
+ /// specifier.
+ ///
+ /// The pointer is the nested-name-specifier that precedes this
+ /// one. The integer stores one of the first four values of type
+ /// SpecifierKind.
+ llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
+
+ /// \brief The last component in the nested name specifier, which
+ /// can be an identifier, a declaration, or a type.
+ ///
+ /// When the pointer is NULL, this specifier represents the global
+ /// specifier '::'. Otherwise, the pointer is one of
+ /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
+ /// specifier as encoded within the prefix.
+ void* Specifier;
+
+public:
+ /// \brief The kind of specifier that completes this nested name
+ /// specifier.
+ enum SpecifierKind {
+ /// \brief An identifier, stored as an IdentifierInfo*.
+ Identifier = 0,
+ /// \brief A namespace, stored as a Namespace*.
+ Namespace = 1,
+ /// \brief A type, stored as a Type*.
+ TypeSpec = 2,
+ /// \brief A type that was preceded by the 'template' keyword,
+ /// stored as a Type*.
+ TypeSpecWithTemplate = 3,
+ /// \brief The global specifier '::'. There is no stored value.
+ Global = 4
+ };
+
+private:
+ /// \brief Builds the global specifier.
+ NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
+
+ /// \brief Copy constructor used internally to clone nested name
+ /// specifiers.
+ NestedNameSpecifier(const NestedNameSpecifier &Other)
+ : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
+ Specifier(Other.Specifier) {
+ }
+
+ NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
+
+ /// \brief Either find or insert the given nested name specifier
+ /// mockup in the given context.
+ static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
+ const NestedNameSpecifier &Mockup);
+
+public:
+ /// \brief Builds a specifier combining a prefix and an identifier.
+ ///
+ /// The prefix must be dependent, since nested name specifiers
+ /// referencing an identifier are only permitted when the identifier
+ /// cannot be resolved.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ IdentifierInfo *II);
+
+ /// \brief Builds a nested name specifier that names a namespace.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceDecl *NS);
+
+ /// \brief Builds a nested name specifier that names a type.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ bool Template, const Type *T);
+
+ /// \brief Builds a specifier that consists of just an identifier.
+ ///
+ /// The nested-name-specifier is assumed to be dependent, but has no
+ /// prefix because the prefix is implied by something outside of the
+ /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
+ /// type.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ IdentifierInfo *II);
+
+ /// \brief Returns the nested name specifier representing the global
+ /// scope.
+ static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
+
+ /// \brief Return the prefix of this nested name specifier.
+ ///
+ /// The prefix contains all of the parts of the nested name
+ /// specifier that preced this current specifier. For example, for a
+ /// nested name specifier that represents "foo::bar::", the current
+ /// specifier will contain "bar::" and the prefix will contain
+ /// "foo::".
+ NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
+
+ /// \brief Determine what kind of nested name specifier is stored.
+ SpecifierKind getKind() const {
+ if (Specifier == 0)
+ return Global;
+ return (SpecifierKind)Prefix.getInt();
+ }
+
+ /// \brief Retrieve the identifier stored in this nested name
+ /// specifier.
+ IdentifierInfo *getAsIdentifier() const {
+ if (Prefix.getInt() == Identifier)
+ return (IdentifierInfo *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Retrieve the namespace stored in this nested name
+ /// specifier.
+ NamespaceDecl *getAsNamespace() const {
+ if (Prefix.getInt() == Namespace)
+ return (NamespaceDecl *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Retrieve the type stored in this nested name specifier.
+ const Type *getAsType() const {
+ if (Prefix.getInt() == TypeSpec ||
+ Prefix.getInt() == TypeSpecWithTemplate)
+ return (const Type *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Whether this nested name specifier refers to a dependent
+ /// type or not.
+ bool isDependent() const;
+
+ /// \brief Whether this nested-name-specifier contains an unexpanded
+ /// parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Print this nested name specifier to the given output
+ /// stream.
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(Prefix.getOpaqueValue());
+ ID.AddPointer(Specifier);
+ }
+
+ /// \brief Dump the nested name specifier to standard output to aid
+ /// in debugging.
+ void dump(const LangOptions &LO);
+};
+
+/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ NestedNameSpecifier *NNS) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
+ Diagnostic::ak_nestednamespec);
+ return DB;
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
new file mode 100644
index 0000000..35c72c4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
@@ -0,0 +1,289 @@
+//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file enumerates the different kinds of operations that can be
+// performed by various expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
+#define LLVM_CLANG_AST_OPERATION_KINDS_H
+
+namespace clang {
+
+/// CastKind - The kind of operation required for a conversion.
+enum CastKind {
+ /// CK_Dependent - A conversion which cannot yet be analyzed because
+ /// either the expression or target type is dependent. These are
+ /// created only for explicit casts; dependent ASTs aren't required
+ /// to even approximately type-check.
+ /// (T*) malloc(sizeof(T))
+ /// reinterpret_cast<intptr_t>(A<T>::alloc());
+ CK_Dependent,
+
+ /// CK_BitCast - A conversion which causes a bit pattern of one type
+ /// to be reinterpreted as a bit pattern of another type. Generally
+ /// the operands must have equivalent size and unrelated types.
+ ///
+ /// The pointer conversion char* -> int* is a bitcast. Many other
+ /// pointer conversions which are "physically" bitcasts are given
+ /// special cast kinds.
+ ///
+ /// Vector coercions are bitcasts.
+ CK_BitCast,
+
+ /// CK_LValueBitCast - A conversion which reinterprets the address of
+ /// an l-value as an l-value of a different kind. Used for
+ /// reinterpret_casts of l-value expressions to reference types.
+ /// bool b; reinterpret_cast<char&>(b) = 'a';
+ CK_LValueBitCast,
+
+ /// CK_LValueToRValue - A conversion which causes the extraction of
+ /// an r-value from the operand gl-value. The result of an r-value
+ /// conversion is always unqualified.
+ CK_LValueToRValue,
+
+ /// CK_GetObjCProperty - A conversion which calls an Objective-C
+ /// property getter. The operand is an OK_ObjCProperty l-value; the
+ /// result will generally be an r-value, but could be an ordinary
+ /// gl-value if the property reference is to an implicit property
+ /// for a method that returns a reference type.
+ CK_GetObjCProperty,
+
+ /// CK_NoOp - A conversion which does not affect the type other than
+ /// (possibly) adding qualifiers.
+ /// int -> int
+ /// char** -> const char * const *
+ CK_NoOp,
+
+ /// CK_BaseToDerived - A conversion from a C++ class pointer/reference
+ /// to a derived class pointer/reference.
+ /// B *b = static_cast<B*>(a);
+ CK_BaseToDerived,
+
+ /// CK_DerivedToBase - A conversion from a C++ class pointer
+ /// to a base class pointer.
+ /// A *a = new B();
+ CK_DerivedToBase,
+
+ /// CK_UncheckedDerivedToBase - A conversion from a C++ class
+ /// pointer/reference to a base class that can assume that the
+ /// derived pointer is not null.
+ /// const A &a = B();
+ /// b->method_from_a();
+ CK_UncheckedDerivedToBase,
+
+ /// CK_Dynamic - A C++ dynamic_cast.
+ CK_Dynamic,
+
+ /// CK_ToUnion - The GCC cast-to-union extension.
+ /// int -> union { int x; float y; }
+ /// float -> union { int x; float y; }
+ CK_ToUnion,
+
+ /// CK_ArrayToPointerDecay - Array to pointer decay.
+ /// int[10] -> int*
+ /// char[5][6] -> char(*)[6]
+ CK_ArrayToPointerDecay,
+
+ /// CK_FunctionToPointerDecay - Function to pointer decay.
+ /// void(int) -> void(*)(int)
+ CK_FunctionToPointerDecay,
+
+ /// CK_NullToPointer - Null pointer constant to pointer, ObjC
+ /// pointer, or block pointer.
+ /// (void*) 0
+ /// void (^block)() = 0;
+ CK_NullToPointer,
+
+ /// CK_NullToMemberPointer - Null pointer constant to member pointer.
+ /// int A::*mptr = 0;
+ /// int (A::*fptr)(int) = nullptr;
+ CK_NullToMemberPointer,
+
+ /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
+ /// member pointer in derived class.
+ /// int B::*mptr = &A::member;
+ CK_BaseToDerivedMemberPointer,
+
+ /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
+ /// member pointer in base class.
+ /// int A::*mptr = static_cast<int A::*>(&B::member);
+ CK_DerivedToBaseMemberPointer,
+
+ /// CK_MemberPointerToBoolean - Member pointer to boolean. A check
+ /// against the null member pointer.
+ CK_MemberPointerToBoolean,
+
+ /// CK_UserDefinedConversion - Conversion using a user defined type
+ /// conversion function.
+ /// struct A { operator int(); }; int i = int(A());
+ CK_UserDefinedConversion,
+
+ /// CK_ConstructorConversion - Conversion by constructor.
+ /// struct A { A(int); }; A a = A(10);
+ CK_ConstructorConversion,
+
+ /// CK_IntegralToPointer - Integral to pointer. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (char*) 0x1001aab0
+ /// reinterpret_cast<int*>(0)
+ CK_IntegralToPointer,
+
+ /// CK_PointerToIntegral - Pointer to integral. A special kind of
+ /// reinterpreting conversion. Applies to normal, ObjC, and block
+ /// pointers.
+ /// (intptr_t) "help!"
+ CK_PointerToIntegral,
+
+ /// CK_PointerToBoolean - Pointer to boolean conversion. A check
+ /// against null. Applies to normal, ObjC, and block pointers.
+ CK_PointerToBoolean,
+
+ /// CK_ToVoid - Cast to void, discarding the computed value.
+ /// (void) malloc(2048)
+ CK_ToVoid,
+
+ /// CK_VectorSplat - A conversion from an arithmetic type to a
+ /// vector of that element type. Fills all elements ("splats") with
+ /// the source value.
+ /// __attribute__((ext_vector_type(4))) int v = 5;
+ CK_VectorSplat,
+
+ /// CK_IntegralCast - A cast between integral types (other than to
+ /// boolean). Variously a bitcast, a truncation, a sign-extension,
+ /// or a zero-extension.
+ /// long l = 5;
+ /// (unsigned) i
+ CK_IntegralCast,
+
+ /// CK_IntegralToBoolean - Integral to boolean. A check against zero.
+ /// (bool) i
+ CK_IntegralToBoolean,
+
+ /// CK_IntegralToFloating - Integral to floating point.
+ /// float f = i;
+ CK_IntegralToFloating,
+
+ /// CK_FloatingToIntegral - Floating point to integral. Rounds
+ /// towards zero, discarding any fractional component.
+ /// (int) f
+ CK_FloatingToIntegral,
+
+ /// CK_FloatingToBoolean - Floating point to boolean.
+ /// (bool) f
+ CK_FloatingToBoolean,
+
+ /// CK_FloatingCast - Casting between floating types of different size.
+ /// (double) f
+ /// (float) ld
+ CK_FloatingCast,
+
+ /// CK_AnyPointerToObjCPointerCast - Casting any other pointer kind
+ /// to an Objective-C pointer.
+ CK_AnyPointerToObjCPointerCast,
+
+ /// CK_AnyPointerToBlockPointerCast - Casting any other pointer kind
+ /// to a block pointer.
+ CK_AnyPointerToBlockPointerCast,
+
+ /// \brief Converting between two Objective-C object types, which
+ /// can occur when performing reference binding to an Objective-C
+ /// object.
+ CK_ObjCObjectLValueCast,
+
+ /// \brief A conversion of a floating point real to a floating point
+ /// complex of the original type. Injects the value as the real
+ /// component with a zero imaginary component.
+ /// float -> _Complex float
+ CK_FloatingRealToComplex,
+
+ /// \brief Converts a floating point complex to floating point real
+ /// of the source's element type. Just discards the imaginary
+ /// component.
+ /// _Complex long double -> long double
+ CK_FloatingComplexToReal,
+
+ /// \brief Converts a floating point complex to bool by comparing
+ /// against 0+0i.
+ CK_FloatingComplexToBoolean,
+
+ /// \brief Converts between different floating point complex types.
+ /// _Complex float -> _Complex double
+ CK_FloatingComplexCast,
+
+ /// \brief Converts from a floating complex to an integral complex.
+ /// _Complex float -> _Complex int
+ CK_FloatingComplexToIntegralComplex,
+
+ /// \brief Converts from an integral real to an integral complex
+ /// whose element type matches the source. Injects the value as
+ /// the real component with a zero imaginary component.
+ /// long -> _Complex long
+ CK_IntegralRealToComplex,
+
+ /// \brief Converts an integral complex to an integral real of the
+ /// source's element type by discarding the imaginary component.
+ /// _Complex short -> short
+ CK_IntegralComplexToReal,
+
+ /// \brief Converts an integral complex to bool by comparing against
+ /// 0+0i.
+ CK_IntegralComplexToBoolean,
+
+ /// \brief Converts between different integral complex types.
+ /// _Complex char -> _Complex long long
+ /// _Complex unsigned int -> _Complex signed int
+ CK_IntegralComplexCast,
+
+ /// \brief Converts from an integral complex to a floating complex.
+ /// _Complex unsigned -> _Complex float
+ CK_IntegralComplexToFloatingComplex
+};
+
+#define CK_Invalid ((CastKind) -1)
+
+enum BinaryOperatorKind {
+ // Operators listed in order of precedence.
+ // Note that additions to this should also update the StmtVisitor class.
+ BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
+ BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
+ BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
+ BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
+ BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
+ BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
+ BO_And, // [C99 6.5.10] Bitwise AND operator.
+ BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
+ BO_Or, // [C99 6.5.12] Bitwise OR operator.
+ BO_LAnd, // [C99 6.5.13] Logical AND operator.
+ BO_LOr, // [C99 6.5.14] Logical OR operator.
+ BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
+ BO_DivAssign, BO_RemAssign,
+ BO_AddAssign, BO_SubAssign,
+ BO_ShlAssign, BO_ShrAssign,
+ BO_AndAssign, BO_XorAssign,
+ BO_OrAssign,
+ BO_Comma // [C99 6.5.17] Comma operator.
+};
+
+enum UnaryOperatorKind {
+ // Note that additions to this should also update the StmtVisitor class.
+ UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
+ UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
+ UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
+ UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
+ UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
+ UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
+ UO_Extension // __extension__ marker.
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
new file mode 100644
index 0000000..9ea5a09
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
@@ -0,0 +1,60 @@
+//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- 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 ParentMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARENTMAP_H
+#define LLVM_CLANG_PARENTMAP_H
+
+namespace clang {
+class Stmt;
+class Expr;
+
+class ParentMap {
+ void* Impl;
+public:
+ ParentMap(Stmt* ASTRoot);
+ ~ParentMap();
+
+ /// \brief Adds and/or updates the parent/child-relations of the complete
+ /// stmt tree of S. All children of S including indirect descendants are
+ /// visited and updated or inserted but not the parents of S.
+ void addStmt(Stmt* S);
+
+ Stmt *getParent(Stmt*) const;
+ Stmt *getParentIgnoreParens(Stmt *) const;
+ Stmt *getParentIgnoreParenCasts(Stmt *) const;
+
+ const Stmt *getParent(const Stmt* S) const {
+ return getParent(const_cast<Stmt*>(S));
+ }
+
+ const Stmt *getParentIgnoreParens(const Stmt *S) const {
+ return getParentIgnoreParens(const_cast<Stmt*>(S));
+ }
+
+ const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
+ return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
+ }
+
+ bool hasParent(Stmt* S) const {
+ return getParent(S) != 0;
+ }
+
+ bool isConsumedExpr(Expr *E) const;
+
+ bool isConsumedExpr(const Expr *E) const {
+ return isConsumedExpr(const_cast<Expr*>(E));
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
new file mode 100644
index 0000000..a59c302
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
@@ -0,0 +1,112 @@
+//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- 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 PrinterHelper interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
+#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+
+#include "clang/Basic/LangOptions.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class Stmt;
+class TagDecl;
+class LangOptions;
+
+class PrinterHelper {
+public:
+ virtual ~PrinterHelper();
+ virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0;
+};
+
+/// \brief Describes how types, statements, expressions, and
+/// declarations should be printed.
+struct PrintingPolicy {
+ /// \brief Create a default printing policy for C.
+ PrintingPolicy(const LangOptions &LO)
+ : Indentation(2), LangOpts(LO), SuppressSpecifiers(false),
+ SuppressTag(false), SuppressScope(false),
+ Dump(false), ConstantArraySizeAsWritten(false),
+ AnonymousTagLocations(true) { }
+
+ /// \brief The number of spaces to use to indent each line.
+ unsigned Indentation : 8;
+
+ /// \brief What language we're printing.
+ const LangOptions LangOpts;
+
+ /// \brief Whether we should suppress printing of the actual specifiers for
+ /// the given type or declaration.
+ ///
+ /// This flag is only used when we are printing declarators beyond
+ /// the first declarator within a declaration group. For example, given:
+ ///
+ /// \code
+ /// const int *x, *y;
+ /// \endcode
+ ///
+ /// SuppressSpecifiers will be false when printing the
+ /// declaration for "x", so that we will print "int *x"; it will be
+ /// \c true when we print "y", so that we suppress printing the
+ /// "const int" type specifier and instead only print the "*y".
+ bool SuppressSpecifiers : 1;
+
+ /// \brief Whether type printing should skip printing the actual tag type.
+ ///
+ /// This is used when the caller needs to print a tag definition in front
+ /// of the type, as in constructs like the following:
+ ///
+ /// \code
+ /// typedef struct { int x, y; } Point;
+ /// \endcode
+ bool SuppressTag : 1;
+
+ /// \brief Suppresses printing of scope specifiers.
+ bool SuppressScope : 1;
+
+ /// \brief True when we are "dumping" rather than "pretty-printing",
+ /// where dumping involves printing the internal details of the AST
+ /// and pretty-printing involves printing something similar to
+ /// source code.
+ bool Dump : 1;
+
+ /// \brief Whether we should print the sizes of constant array expressions
+ /// as written in the sources.
+ ///
+ /// This flag is determines whether arrays types declared as
+ ///
+ /// \code
+ /// int a[4+10*10];
+ /// char a[] = "A string";
+ /// \endcode
+ ///
+ /// will be printed as written or as follows:
+ ///
+ /// \code
+ /// int a[104];
+ /// char a[9] = "A string";
+ /// \endcode
+ bool ConstantArraySizeAsWritten : 1;
+
+ /// \brief When printing an anonymous tag name, also print the location of
+ /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just
+ /// prints "<anonymous>" for the name.
+ bool AnonymousTagLocations : 1;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
new file mode 100644
index 0000000..d7bab80
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
@@ -0,0 +1,206 @@
+//===--- RecordLayout.h - Layout information for a struct/union -*- 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 RecordLayout interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
+#define LLVM_CLANG_AST_LAYOUTINFO_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+ class ASTContext;
+ class FieldDecl;
+ class RecordDecl;
+ class CXXRecordDecl;
+
+/// ASTRecordLayout -
+/// This class contains layout information for one RecordDecl,
+/// which is a struct/union/class. The decl represented must be a definition,
+/// not a forward declaration.
+/// This class is also used to contain layout information for one
+/// ObjCInterfaceDecl. FIXME - Find appropriate name.
+/// These objects are managed by ASTContext.
+class ASTRecordLayout {
+ /// Size - Size of record in characters.
+ CharUnits Size;
+
+ /// DataSize - Size of record in characters without tail padding.
+ CharUnits DataSize;
+
+ /// FieldOffsets - Array of field offsets in bits.
+ uint64_t *FieldOffsets;
+
+ // Alignment - Alignment of record in characters.
+ CharUnits Alignment;
+
+ // FieldCount - Number of fields.
+ unsigned FieldCount;
+
+ /// CXXRecordLayoutInfo - Contains C++ specific layout information.
+ struct CXXRecordLayoutInfo {
+ /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
+ /// the size of the object without virtual bases.
+ CharUnits NonVirtualSize;
+
+ /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
+ /// which is the alignment of the object without virtual bases.
+ CharUnits NonVirtualAlign;
+
+ /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
+ /// (either a base or a member). Will be zero if the class doesn't contain
+ /// any empty subobjects.
+ CharUnits SizeOfLargestEmptySubobject;
+
+ /// PrimaryBase - The primary base info for this record.
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
+
+ /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
+
+ /// BaseOffsets - Contains a map from base classes to their offset.
+ BaseOffsetsMapTy BaseOffsets;
+
+ /// VBaseOffsets - Contains a map from vbase classes to their offset.
+ BaseOffsetsMapTy VBaseOffsets;
+ };
+
+ /// CXXInfo - If the record layout is for a C++ record, this will have
+ /// C++ specific information about the record.
+ CXXRecordLayoutInfo *CXXInfo;
+
+ friend class ASTContext;
+
+ ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+ CharUnits datasize, const uint64_t *fieldoffsets,
+ unsigned fieldcount);
+
+ // Constructor for C++ records.
+ typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
+ ASTRecordLayout(const ASTContext &Ctx,
+ CharUnits size, CharUnits alignment, CharUnits datasize,
+ const uint64_t *fieldoffsets, unsigned fieldcount,
+ CharUnits nonvirtualsize, CharUnits nonvirtualalign,
+ CharUnits SizeOfLargestEmptySubobject,
+ const CXXRecordDecl *PrimaryBase,
+ bool IsPrimaryBaseVirtual,
+ const BaseOffsetsMapTy& BaseOffsets,
+ const BaseOffsetsMapTy& VBaseOffsets);
+
+ ~ASTRecordLayout() {}
+
+ void Destroy(ASTContext &Ctx);
+
+ ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
+ void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
+public:
+
+ /// getAlignment - Get the record alignment in characters.
+ CharUnits getAlignment() const { return Alignment; }
+
+ /// getSize - Get the record size in characters.
+ CharUnits getSize() const { return Size; }
+
+ /// getFieldCount - Get the number of fields in the layout.
+ unsigned getFieldCount() const { return FieldCount; }
+
+ /// getFieldOffset - Get the offset of the given field index, in
+ /// bits.
+ uint64_t getFieldOffset(unsigned FieldNo) const {
+ assert (FieldNo < FieldCount && "Invalid Field No");
+ return FieldOffsets[FieldNo];
+ }
+
+ /// getDataSize() - Get the record data size, which is the record size
+ /// without tail padding, in characters.
+ CharUnits getDataSize() const {
+ return DataSize;
+ }
+
+ /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
+ /// which is the size of the object without virtual bases.
+ CharUnits getNonVirtualSize() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->NonVirtualSize;
+ }
+
+ /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
+ /// which is the alignment of the object without virtual bases.
+ CharUnits getNonVirtualAlign() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->NonVirtualAlign;
+ }
+
+ /// getPrimaryBase - Get the primary base for this record.
+ const CXXRecordDecl *getPrimaryBase() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->PrimaryBase.getPointer();
+ }
+
+ /// isPrimaryBaseVirtual - Get whether the primary base for this record
+ /// is virtual or not.
+ bool isPrimaryBaseVirtual() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->PrimaryBase.getInt();
+ }
+
+ /// getBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+
+ return CXXInfo->BaseOffsets[Base];
+ }
+
+ /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
+ CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
+
+ return CXXInfo->VBaseOffsets[VBase];
+ }
+
+ /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
+
+ return getBaseClassOffset(Base).getQuantity() *
+ Base->getASTContext().getCharWidth();
+ }
+
+ /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given
+ /// base class.
+ uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
+
+ return getVBaseClassOffset(VBase).getQuantity() *
+ VBase->getASTContext().getCharWidth();
+ }
+
+ CharUnits getSizeOfLargestEmptySubobject() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->SizeOfLargestEmptySubobject;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
new file mode 100644
index 0000000..921b799
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -0,0 +1,1904 @@
+//===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- 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 RecursiveASTVisitor interface, which recursively
+// traverses the entire AST.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
+#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_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/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/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+
+// The following three macros are used for meta programming. The code
+// using them is responsible for defining macro OPERATOR().
+
+// All unary operators.
+#define UNARYOP_LIST() \
+ OPERATOR(PostInc) OPERATOR(PostDec) \
+ OPERATOR(PreInc) OPERATOR(PreDec) \
+ OPERATOR(AddrOf) OPERATOR(Deref) \
+ OPERATOR(Plus) OPERATOR(Minus) \
+ OPERATOR(Not) OPERATOR(LNot) \
+ OPERATOR(Real) OPERATOR(Imag) \
+ OPERATOR(Extension)
+
+// All binary operators (excluding compound assign operators).
+#define BINOP_LIST() \
+ OPERATOR(PtrMemD) OPERATOR(PtrMemI) \
+ OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \
+ OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \
+ OPERATOR(Shr) \
+ \
+ OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \
+ OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \
+ OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \
+ OPERATOR(LAnd) OPERATOR(LOr) \
+ \
+ OPERATOR(Assign) \
+ OPERATOR(Comma)
+
+// All compound assign operators.
+#define CAO_LIST() \
+ OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
+ OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
+
+namespace clang {
+
+// A helper macro to implement short-circuiting when recursing. It
+// invokes CALL_EXPR, which must be a method call, on the derived
+// object (s.t. a user of RecursiveASTVisitor can override the method
+// in CALL_EXPR).
+#define TRY_TO(CALL_EXPR) \
+ do { if (!getDerived().CALL_EXPR) return false; } while (0)
+
+/// \brief A class that does preorder depth-first traversal on the
+/// entire Clang AST and visits each node.
+///
+/// This class performs three distinct tasks:
+/// 1. traverse the AST (i.e. go to each node);
+/// 2. at a given node, walk up the class hierarchy, starting from
+/// the node's dynamic type, until the top-most class (e.g. Stmt,
+/// Decl, or Type) is reached.
+/// 3. given a (node, class) combination, where 'class' is some base
+/// class of the dynamic type of 'node', call a user-overridable
+/// function to actually visit the node.
+///
+/// These tasks are done by three groups of methods, respectively:
+/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point
+/// for traversing an AST rooted at x. This method simply
+/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
+/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and
+/// then recursively visits the child nodes of x.
+/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work
+/// similarly.
+/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit
+/// any child node of x. Instead, it first calls WalkUpFromBar(x)
+/// where Bar is the direct parent class of Foo (unless Foo has
+/// no parent), and then calls VisitFoo(x) (see the next list item).
+/// 3. VisitFoo(Foo *x) does task #3.
+///
+/// These three method groups are tiered (Traverse* > WalkUpFrom* >
+/// Visit*). A method (e.g. Traverse*) may call methods from the same
+/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
+/// It may not call methods from a higher tier.
+///
+/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
+/// is Foo's super class) before calling VisitFoo(), the result is
+/// that the Visit*() methods for a given node are called in the
+/// top-down order (e.g. for a node of type NamedDecl, the order will
+/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
+///
+/// This scheme guarantees that all Visit*() calls for the same AST
+/// node are grouped together. In other words, Visit*() methods for
+/// different nodes are never interleaved.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the Traverse*, WalkUpFrom*,
+/// and Visit* methods for declarations, types, statements,
+/// expressions, or other AST nodes where the visitor should customize
+/// behavior. Most users only need to override Visit*. Advanced
+/// users may override Traverse* and WalkUpFrom* to implement custom
+/// traversal strategies. Returning false from one of these overridden
+/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once. The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations. Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately. This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
+template<typename Derived>
+class RecursiveASTVisitor {
+public:
+ /// \brief Return a reference to the derived class.
+ Derived &getDerived() { return *static_cast<Derived*>(this); }
+
+ /// \brief Return whether this visitor should recurse into
+ /// template instantiations.
+ bool shouldVisitTemplateInstantiations() const { return false; }
+
+ /// \brief Return whether this visitor should recurse into the types of
+ /// TypeLocs.
+ bool shouldWalkTypesOfTypeLocs() const { return true; }
+
+ /// \brief Recursively visit a statement or expression, by
+ /// dispatching to Traverse*() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is NULL).
+ bool TraverseStmt(Stmt *S);
+
+ /// \brief Recursively visit a type, by dispatching to
+ /// Traverse*Type() based on the argument's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type).
+ bool TraverseType(QualType T);
+
+ /// \brief Recursively visit a type with location, by dispatching to
+ /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type location).
+ bool TraverseTypeLoc(TypeLoc TL);
+
+ /// \brief Recursively visit a declaration, by dispatching to
+ /// Traverse*Decl() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is NULL).
+ bool TraverseDecl(Decl *D);
+
+ /// \brief Recursively visit a C++ nested-name-specifier.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+ /// \brief Recursively visit a template name and dispatch to the
+ /// appropriate method.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseTemplateName(TemplateName Template);
+
+ /// \brief Recursively visit a template argument and dispatch to the
+ /// appropriate method for the argument type.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ // FIXME: migrate callers to TemplateArgumentLoc instead.
+ bool TraverseTemplateArgument(const TemplateArgument &Arg);
+
+ /// \brief Recursively visit a template argument location and dispatch to the
+ /// appropriate method for the argument type.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
+
+ /// \brief Recursively visit a set of template arguments.
+ /// This can be overridden by a subclass, but it's not expected that
+ /// will be needed -- this visitor always dispatches to another.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
+ bool TraverseTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Recursively visit a constructor initializer. This
+ /// automatically dispatches to another visitor for the initializer
+ /// expression, but not for the name of the initializer, so may
+ /// be overridden for clients that need access to the name.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+
+ // ---- Methods on Stmts ----
+
+ // Declare Traverse*() for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ bool Traverse##CLASS(CLASS *S);
+#include "clang/AST/StmtNodes.inc"
+ // The above header #undefs ABSTRACT_STMT and STMT upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
+ bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
+ bool VisitStmt(Stmt *S) { return true; }
+#define STMT(CLASS, PARENT) \
+ bool WalkUpFrom##CLASS(CLASS *S) { \
+ TRY_TO(WalkUpFrom##PARENT(S)); \
+ TRY_TO(Visit##CLASS(S)); \
+ return true; \
+ } \
+ bool Visit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
+ // operator methods. Unary operators are not classes in themselves
+ // (they're all opcodes in UnaryOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ bool TraverseUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
+ TRY_TO(TraverseStmt(S->getSubExpr())); \
+ return true; \
+ } \
+ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnaryOperator(S)); \
+ TRY_TO(VisitUnary##NAME(S)); \
+ return true; \
+ } \
+ bool VisitUnary##NAME(UnaryOperator *S) { return true; }
+
+ UNARYOP_LIST()
+#undef OPERATOR
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
+ // operator methods. Binary operators are not classes in themselves
+ // (they're all opcodes in BinaryOperator) but do have visitors.
+#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
+ bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFromBin##NAME(S)); \
+ TRY_TO(TraverseStmt(S->getLHS())); \
+ TRY_TO(TraverseStmt(S->getRHS())); \
+ return true; \
+ } \
+ bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
+ TRY_TO(VisitBin##NAME(S)); \
+ return true; \
+ } \
+ bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
+
+#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
+ BINOP_LIST()
+#undef OPERATOR
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
+ // assignment methods. Compound assignment operators are not
+ // classes in themselves (they're all opcodes in
+ // CompoundAssignOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
+
+ CAO_LIST()
+#undef OPERATOR
+#undef GENERAL_BINOP_FALLBACK
+
+ // ---- Methods on Types ----
+ // FIXME: revamp to take TypeLoc's rather than Types.
+
+ // Declare Traverse*() for all concrete Type classes.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) \
+ bool Traverse##CLASS##Type(CLASS##Type *T);
+#include "clang/AST/TypeNodes.def"
+ // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Type classes.
+ bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
+ bool VisitType(Type *T) { return true; }
+#define TYPE(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
+ TRY_TO(WalkUpFrom##BASE(T)); \
+ TRY_TO(Visit##CLASS##Type(T)); \
+ return true; \
+ } \
+ bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
+#include "clang/AST/TypeNodes.def"
+
+ // ---- Methods on TypeLocs ----
+ // FIXME: this currently just calls the matching Type methods
+
+ // Declare Traverse*() for all concrete Type classes.
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE) \
+ bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#include "clang/AST/TypeLocNodes.def"
+ // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
+ bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
+ bool VisitTypeLoc(TypeLoc TL) { return true; }
+
+ // QualifiedTypeLoc and UnqualTypeLoc are not declared in
+ // TypeNodes.def and thus need to be handled specially.
+ bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+ }
+ bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; }
+ bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
+ return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+ }
+ bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; }
+
+ // Note that BASE includes trailing 'Type' which CLASS doesn't.
+#define TYPE(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
+ TRY_TO(WalkUpFrom##BASE##Loc(TL)); \
+ TRY_TO(Visit##CLASS##TypeLoc(TL)); \
+ return true; \
+ } \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
+#include "clang/AST/TypeNodes.def"
+
+ // ---- Methods on Decls ----
+
+ // Declare Traverse*() for all concrete Decl classes.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#include "clang/AST/DeclNodes.inc"
+ // The above header #undefs ABSTRACT_DECL and DECL upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Decl classes.
+ bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
+ bool VisitDecl(Decl *D) { return true; }
+#define DECL(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
+ TRY_TO(WalkUpFrom##BASE(D)); \
+ TRY_TO(Visit##CLASS##Decl(D)); \
+ return true; \
+ } \
+ bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.inc"
+
+private:
+ // These are helper methods used by more than one Traverse* method.
+ bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
+ bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ unsigned Count);
+ bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
+ bool TraverseRecordHelper(RecordDecl *D);
+ bool TraverseCXXRecordHelper(CXXRecordDecl *D);
+ bool TraverseDeclaratorHelper(DeclaratorDecl *D);
+ bool TraverseDeclContextHelper(DeclContext *DC);
+ bool TraverseFunctionHelper(FunctionDecl *D);
+ bool TraverseVarHelper(VarDecl *D);
+};
+
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR))
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
+ if (!S)
+ return true;
+
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+ switch (BinOp->getOpcode()) {
+#define OPERATOR(NAME) \
+ case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S);
+
+ BINOP_LIST()
+#undef OPERATOR
+#undef BINOP_LIST
+
+#define OPERATOR(NAME) \
+ case BO_##NAME##Assign: \
+ DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
+
+ CAO_LIST()
+#undef OPERATOR
+#undef CAO_LIST
+ }
+ } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
+ switch (UnOp->getOpcode()) {
+#define OPERATOR(NAME) \
+ case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
+
+ UNARYOP_LIST()
+#undef OPERATOR
+#undef UNARYOP_LIST
+ }
+ }
+
+ // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass: break;
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS##Class: DISPATCH(CLASS, CLASS, S);
+#include "clang/AST/StmtNodes.inc"
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
+ if (T.isNull())
+ return true;
+
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) \
+ case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \
+ const_cast<Type*>(T.getTypePtr()));
+#include "clang/AST/TypeNodes.def"
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
+ if (TL.isNull())
+ return true;
+
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE) \
+ case TypeLoc::CLASS: \
+ return getDerived().Traverse##CLASS##TypeLoc(*cast<CLASS##TypeLoc>(&TL));
+#include "clang/AST/TypeLocNodes.def"
+ }
+
+ return true;
+}
+
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
+ if (!D)
+ return true;
+
+ // As a syntax visitor, we want to ignore declarations for
+ // implicitly-defined declarations (ones not typed explicitly by the
+ // user).
+ if (D->isImplicit())
+ return true;
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D);
+#include "clang/AST/DeclNodes.inc"
+ }
+
+ return true;
+}
+
+#undef DISPATCH
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
+ NestedNameSpecifier *NNS) {
+ if (!NNS)
+ return true;
+
+ if (NNS->getPrefix())
+ TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Global:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
+ const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ return true;
+
+ case TemplateArgument::Type:
+ return getDerived().TraverseType(Arg.getAsType());
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
+
+ case TemplateArgument::Expression:
+ return getDerived().TraverseStmt(Arg.getAsExpr());
+
+ case TemplateArgument::Pack:
+ return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
+ Arg.pack_size());
+ }
+
+ return true;
+}
+
+// FIXME: no template name location?
+// FIXME: no source locations for a template argument pack?
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
+ const TemplateArgumentLoc &ArgLoc) {
+ const TemplateArgument &Arg = ArgLoc.getArgument();
+
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ return true;
+
+ case TemplateArgument::Type: {
+ // FIXME: how can TSI ever be NULL?
+ if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
+ return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ else
+ return true;
+ }
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
+
+ case TemplateArgument::Expression:
+ return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
+
+ case TemplateArgument::Pack:
+ return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
+ Arg.pack_size());
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ TRY_TO(TraverseTemplateArgument(Args[I]));
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
+ CXXCtorInitializer *Init) {
+ // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()?
+ if (Init->isWritten())
+ TRY_TO(TraverseStmt(Init->getInit()));
+ return true;
+}
+
+
+// ----------------- Type traversal -----------------
+
+// This macro makes available a variable T, the passed-in type.
+#define DEF_TRAVERSE_TYPE(TYPE, CODE) \
+ template<typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##TYPE (TYPE *T) { \
+ TRY_TO(WalkUpFrom##TYPE (T)); \
+ { CODE; } \
+ return true; \
+ }
+
+DEF_TRAVERSE_TYPE(BuiltinType, { })
+
+DEF_TRAVERSE_TYPE(ComplexType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(PointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(BlockPointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(LValueReferenceType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(RValueReferenceType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(MemberPointerType, {
+ TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(ConstantArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(IncompleteArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(VariableArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(VectorType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(ExtVectorType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(FunctionNoProtoType, {
+ TRY_TO(TraverseType(T->getResultType()));
+ })
+
+DEF_TRAVERSE_TYPE(FunctionProtoType, {
+ TRY_TO(TraverseType(T->getResultType()));
+
+ for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
+ AEnd = T->arg_type_end();
+ A != AEnd; ++A) {
+ TRY_TO(TraverseType(*A));
+ }
+
+ for (FunctionProtoType::exception_iterator E = T->exception_begin(),
+ EEnd = T->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ })
+
+DEF_TRAVERSE_TYPE(UnresolvedUsingType, { })
+DEF_TRAVERSE_TYPE(TypedefType, { })
+
+DEF_TRAVERSE_TYPE(TypeOfExprType, {
+ TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(TypeOfType, {
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+ })
+
+DEF_TRAVERSE_TYPE(DecltypeType, {
+ TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(AutoType, {
+ TRY_TO(TraverseType(T->getDeducedType()));
+ })
+
+DEF_TRAVERSE_TYPE(RecordType, { })
+DEF_TRAVERSE_TYPE(EnumType, { })
+DEF_TRAVERSE_TYPE(TemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { })
+
+DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
+ TRY_TO(TraverseTemplateName(T->getTemplateName()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+ })
+
+DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
+
+DEF_TRAVERSE_TYPE(AttributedType, {
+ TRY_TO(TraverseType(T->getModifiedType()));
+ })
+
+DEF_TRAVERSE_TYPE(ParenType, {
+ TRY_TO(TraverseType(T->getInnerType()));
+ })
+
+DEF_TRAVERSE_TYPE(ElaboratedType, {
+ if (T->getQualifier()) {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ }
+ TRY_TO(TraverseType(T->getNamedType()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentNameType, {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+ })
+
+DEF_TRAVERSE_TYPE(PackExpansionType, {
+ TRY_TO(TraverseType(T->getPattern()));
+ })
+
+DEF_TRAVERSE_TYPE(ObjCInterfaceType, { })
+
+DEF_TRAVERSE_TYPE(ObjCObjectType, {
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (T->getBaseType().getTypePtr() != T)
+ TRY_TO(TraverseType(T->getBaseType()));
+ })
+
+DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+#undef DEF_TRAVERSE_TYPE
+
+// ----------------- TypeLoc traversal -----------------
+
+// This macro makes available a variable TL, the passed-in TypeLoc.
+// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
+// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
+// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
+// continue to work.
+#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
+ template<typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
+ if (getDerived().shouldWalkTypesOfTypeLocs()) \
+ TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \
+ TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
+ { CODE; } \
+ return true; \
+ }
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(
+ QualifiedTypeLoc TL) {
+ // Move this over to the 'main' typeloc tree. Note that this is a
+ // move -- we pretend that we were really looking at the unqualified
+ // typeloc all along -- rather than a recursion, so we don't follow
+ // the normal CRTP plan of going through
+ // getDerived().TraverseTypeLoc. If we did, we'd be traversing
+ // twice for the same type (once as a QualifiedTypeLoc version of
+ // the type, once as an UnqualifiedTypeLoc version of the type),
+ // which in effect means we'd call VisitTypeLoc twice with the
+ // 'same' type. This solves that problem, at the cost of never
+ // seeing the qualified version of the type (unless the client
+ // subclasses TraverseQualifiedTypeLoc themselves). It's not a
+ // perfect solution. A perfect solution probably requires making
+ // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a
+ // wrapper around Type* -- rather than being its own class in the
+ // type hierarchy.
+ return TraverseTypeLoc(TL.getUnqualifiedLoc());
+}
+
+DEF_TRAVERSE_TYPELOC(BuiltinType, { })
+
+// FIXME: ComplexTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ComplexType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(PointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(BlockPointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(LValueReferenceType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(RValueReferenceType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+// FIXME: location of base class?
+// We traverse this in the type case as well, but how is it not reached through
+// the pointee type?
+DEF_TRAVERSE_TYPELOC(MemberPointerType, {
+ TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
+ // This isn't available for ArrayType, but is for the ArrayTypeLoc.
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
+ return true;
+}
+
+DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(VariableArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+// FIXME: order? why not size expr first?
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
+ if (TL.getTypePtr()->getSizeExpr())
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+// FIXME: VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(VectorType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+// FIXME: size and attributes
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ExtVectorType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, {
+ TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+ })
+
+// FIXME: location of exception specifications (attributes?)
+DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
+ TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+
+ const FunctionProtoType *T = TL.getTypePtr();
+
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TRY_TO(TraverseDecl(TL.getArg(I)));
+ }
+
+ for (FunctionProtoType::exception_iterator E = T->exception_begin(),
+ EEnd = T->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { })
+DEF_TRAVERSE_TYPELOC(TypedefType, { })
+
+DEF_TRAVERSE_TYPELOC(TypeOfExprType, {
+ TRY_TO(TraverseStmt(TL.getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPELOC(TypeOfType, {
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+ })
+
+// FIXME: location of underlying expr
+DEF_TRAVERSE_TYPELOC(DecltypeType, {
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AutoType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(RecordType, { })
+DEF_TRAVERSE_TYPELOC(EnumType, { })
+DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { })
+
+// FIXME: use the loc for the template name?
+DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
+ TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { })
+
+DEF_TRAVERSE_TYPELOC(ParenType, {
+ TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AttributedType, {
+ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
+ })
+
+// FIXME: use the sourceloc on qualifier?
+DEF_TRAVERSE_TYPELOC(ElaboratedType, {
+ if (TL.getTypePtr()->getQualifier()) {
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+ }
+ TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
+ })
+
+// FIXME: use the sourceloc on qualifier?
+DEF_TRAVERSE_TYPELOC(DependentNameType, {
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+ })
+
+DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(PackExpansionType, {
+ TRY_TO(TraverseTypeLoc(TL.getPatternLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { })
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
+ TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+#undef DEF_TRAVERSE_TYPELOC
+
+// ----------------- Decl traversal -----------------
+//
+// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
+// the children that come from the DeclContext associated with it.
+// Therefore each Traverse* only needs to worry about children other
+// than those.
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
+ if (!DC)
+ return true;
+
+ for (DeclContext::decl_iterator Child = DC->decls_begin(),
+ ChildEnd = DC->decls_end();
+ Child != ChildEnd; ++Child) {
+ TRY_TO(TraverseDecl(*Child));
+ }
+
+ return true;
+}
+
+// This macro makes available a variable D, the passed-in decl.
+#define DEF_TRAVERSE_DECL(DECL, CODE) \
+template<typename Derived> \
+bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \
+ TRY_TO(WalkUpFrom##DECL (D)); \
+ { CODE; } \
+ TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
+ return true; \
+}
+
+DEF_TRAVERSE_DECL(AccessSpecDecl, { })
+
+DEF_TRAVERSE_DECL(BlockDecl, {
+ // We don't traverse nodes in param_begin()/param_end(), as they
+ // appear in decls_begin()/decls_end() and thus are handled by the
+ // DEF_TRAVERSE_DECL macro already.
+ TRY_TO(TraverseStmt(D->getBody()));
+ })
+
+DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
+ TRY_TO(TraverseStmt(D->getAsmString()));
+ })
+
+DEF_TRAVERSE_DECL(FriendDecl, {
+ // Friend is either decl or a type.
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
+ })
+
+DEF_TRAVERSE_DECL(FriendTemplateDecl, {
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
+ for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
+ TemplateParameterList *TPL = D->getTemplateParameterList(I);
+ for (TemplateParameterList::iterator ITPL = TPL->begin(),
+ ETPL = TPL->end();
+ ITPL != ETPL; ++ITPL) {
+ TRY_TO(TraverseDecl(*ITPL));
+ }
+ }
+ })
+
+DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
+
+DEF_TRAVERSE_DECL(ObjCClassDecl, {
+ // FIXME: implement this
+ })
+
+DEF_TRAVERSE_DECL(ObjCForwardProtocolDecl, {
+ // FIXME: implement this
+ })
+
+DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {
+ // FIXME: implement this
+ })
+
+DEF_TRAVERSE_DECL(StaticAssertDecl, {
+ TRY_TO(TraverseStmt(D->getAssertExpr()));
+ TRY_TO(TraverseStmt(D->getMessage()));
+ })
+
+DEF_TRAVERSE_DECL(TranslationUnitDecl, {
+ // Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
+
+DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
+ // We shouldn't traverse an aliased namespace, since it will be
+ // defined (and, therefore, traversed) somewhere else.
+ //
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+ })
+
+DEF_TRAVERSE_DECL(LabelDecl, {
+ // There is no code in a LabelDecl.
+})
+
+
+DEF_TRAVERSE_DECL(NamespaceDecl, {
+ // Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
+
+DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCImplementationDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCMethodDecl, {
+ // We don't traverse nodes in param_begin()/param_end(), as they
+ // appear in decls_begin()/decls_end() and thus are handled.
+ TRY_TO(TraverseStmt(D->getBody()));
+ })
+
+DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(UsingDecl, {
+ TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl()));
+ })
+
+DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
+ TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ })
+
+DEF_TRAVERSE_DECL(UsingShadowDecl, { })
+
+// A helper method for TemplateDecl's children.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
+ TemplateParameterList *TPL) {
+ if (TPL) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ return true;
+}
+
+// A helper method for traversing the implicit instantiations of a
+// class.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
+ ClassTemplateDecl* D, Decl *Pattern) {
+ assert(isa<ClassTemplateDecl>(Pattern) ||
+ isa<ClassTemplatePartialSpecializationDecl>(Pattern));
+
+ ClassTemplateDecl::spec_iterator end = D->spec_end();
+ for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ ClassTemplateSpecializationDecl* SD = *it;
+
+ switch (SD->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_ImplicitInstantiation: {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> U
+ = SD->getInstantiatedFrom();
+
+ bool ShouldVisit;
+ if (U.is<ClassTemplateDecl*>())
+ ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern);
+ else
+ ShouldVisit
+ = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
+
+ if (ShouldVisit)
+ TRY_TO(TraverseClassTemplateSpecializationDecl(SD));
+ break;
+ }
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+
+ // We don't need to do anything for an uninstantiated
+ // specialization.
+ case TSK_Undeclared:
+ break;
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplateDecl, {
+ CXXRecordDecl* TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // class templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // If this is the definition of the primary template, visit
+ // instantiations which were formed from this pattern.
+ if (D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D, D));
+ }
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
+ })
+
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+ FunctionTemplateDecl* D) {
+ FunctionTemplateDecl::spec_iterator end = D->spec_end();
+ for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ FunctionDecl* FD = *it;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_ImplicitInstantiation:
+ // We don't know what kind of FunctionDecl this is.
+ TRY_TO(TraverseDecl(FD));
+ break;
+
+ // No need to visit explicit instantiations, we'll find the node
+ // eventually.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_Undeclared: // Declaration of the template definition.
+ case TSK_ExplicitSpecialization:
+ break;
+ default:
+ assert(false && "Unknown specialization kind.");
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // function templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // Explicit function specializations will be traversed from the
+ // context of their declaration. There is therefore no need to
+ // traverse them for here.
+ //
+ // In addition, we only traverse the function instantiations when
+ // the function template is a function template definition.
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseFunctionInstantiations(D));
+ }
+ }
+ })
+
+DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
+ // D is the "T" in something like
+ // template <template <typename> class T> class container { };
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ if (D->hasDefaultArgument()) {
+ TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
+ }
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+ })
+
+DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
+ // D is the "T" in something like "template<typename T> class vector;"
+ if (D->getTypeForDecl())
+ TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+ if (D->hasDefaultArgument())
+ TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_DECL(TypedefDecl, {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the typedef, not something that was written in the
+ // source.
+ })
+
+DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
+ // A dependent using declaration which was marked with 'typename'.
+ // template<class T> class A : public B<T> { using typename B<T>::foo; };
+ TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type, not something that was written in the
+ // source.
+ })
+
+DEF_TRAVERSE_DECL(EnumDecl, {
+ if (D->getTypeForDecl())
+ TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+
+ TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ // The enumerators are already traversed by
+ // decls_begin()/decls_end().
+ })
+
+
+// Helper methods for RecordDecl and its children.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
+ RecordDecl *D) {
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type, not something that was written in the source.
+
+ TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
+ CXXRecordDecl *D) {
+ if (!TraverseRecordHelper(D))
+ return false;
+ if (D->hasDefinition()) {
+ for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+ E = D->bases_end();
+ I != E; ++I) {
+ TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
+ }
+ // We don't traverse the friends or the conversions, as they are
+ // already in decls_begin()/decls_end().
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(RecordDecl, {
+ TRY_TO(TraverseRecordHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(CXXRecordDecl, {
+ TRY_TO(TraverseCXXRecordHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
+ // For implicit instantiations ("set<int> x;"), we don't want to
+ // recurse at all, since the instatiated class isn't written in
+ // the source code anywhere. (Note the instatiated *type* --
+ // set<int> -- is written, and will still get a callback of
+ // TemplateSpecializationType). For explicit instantiations
+ // ("template set<int>;"), we do need a callback, since this
+ // is the only callback that's made for this instantiation.
+ // We use getTypeAsWritten() to distinguish.
+ if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the ClassTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro)
+ // which contains the instantiated members of the class.
+ return true;
+ })
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
+ const TemplateArgumentLoc *TAL, unsigned Count) {
+ for (unsigned I = 0; I < Count; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
+ // The partial specialization.
+ if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ // The args that remains unspecialized.
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten()));
+
+ // Don't need the ClassTemplatePartialSpecializationHelper, even
+ // though that's our parent class -- we already visit all the
+ // template args here.
+ TRY_TO(TraverseCXXRecordHelper(D));
+
+ // If we're visiting instantiations, visit the instantiations of
+ // this template now.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D));
+ })
+
+DEF_TRAVERSE_DECL(EnumConstantDecl, {
+ TRY_TO(TraverseStmt(D->getInitExpr()));
+ })
+
+DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
+ // Like UnresolvedUsingTypenameDecl, but without the 'typename':
+ // template <class T> Class A : public Base<T> { using Base<T>::foo; };
+ TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ })
+
+DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ if (D->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FieldDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ })
+
+DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ // FIXME: implement the rest.
+ })
+
+DEF_TRAVERSE_DECL(ObjCIvarDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ // FIXME: implement the rest.
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+
+ // If we're an explicit template specialization, iterate over the
+ // template args that were explicitly specified. If we were doing
+ // this in typing order, we'd do it between the return type and
+ // the function args, but both are handled by the FunctionTypeLoc
+ // above, so we have to choose one side. I've decided to do before.
+ if (const FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo()) {
+ if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
+ FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ // A specialization might not have explicit template arguments if it has
+ // a templated return type and concrete arguments.
+ if (const TemplateArgumentListInfo *TALI =
+ FTSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(),
+ TALI->size()));
+ }
+ }
+ }
+
+ // Visit the function type itself, which can be either
+ // FunctionNoProtoType or FunctionProtoType, or a typedef. This
+ // also covers the return type and the function parameters,
+ // including exception specifications.
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
+ // Constructor initializers.
+ for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(),
+ E = Ctor->init_end();
+ I != E; ++I) {
+ TRY_TO(TraverseConstructorInitializer(*I));
+ }
+ }
+
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseStmt(D->getBody())); // Function body.
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FunctionDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXMethodDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXConstructorDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+// CXXConversionDecl is the declaration of a type conversion operator.
+// It's not a cast expression.
+DEF_TRAVERSE_DECL(CXXConversionDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXDestructorDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ TRY_TO(TraverseStmt(D->getInit()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(VarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(ImplicitParamDecl, {
+ TRY_TO(TraverseVarHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
+ // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
+ TRY_TO(TraverseDeclaratorHelper(D));
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
+ })
+
+DEF_TRAVERSE_DECL(ParmVarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+
+ if (D->hasDefaultArg() &&
+ D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
+
+ if (D->hasDefaultArg() &&
+ !D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getDefaultArg()));
+ })
+
+#undef DEF_TRAVERSE_DECL
+
+// ----------------- Stmt traversal -----------------
+//
+// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+
+// This macro makes available a variable S, the passed-in stmt.
+#define DEF_TRAVERSE_STMT(STMT, CODE) \
+template<typename Derived> \
+bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
+ TRY_TO(WalkUpFrom##STMT(S)); \
+ { CODE; } \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ TRY_TO(TraverseStmt(*range)); \
+ } \
+ return true; \
+}
+
+DEF_TRAVERSE_STMT(AsmStmt, {
+ TRY_TO(TraverseStmt(S->getAsmString()));
+ for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
+ }
+ for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
+ }
+ for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->getClobber(I)));
+ }
+ // children() iterates over inputExpr and outputExpr.
+ })
+
+DEF_TRAVERSE_STMT(CXXCatchStmt, {
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
+ // children() iterates over the handler block.
+ })
+
+DEF_TRAVERSE_STMT(DeclStmt, {
+ for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ // Suppress the default iteration over children() by
+ // returning. Here's why: A DeclStmt looks like 'type var [=
+ // initializer]'. The decls above already traverse over the
+ // initializers, so we don't have to do it again (which
+ // children() would do).
+ return true;
+ })
+
+
+// These non-expr stmts (most of them), do not need any action except
+// iterating over the children.
+DEF_TRAVERSE_STMT(BreakStmt, { })
+DEF_TRAVERSE_STMT(CXXTryStmt, { })
+DEF_TRAVERSE_STMT(CaseStmt, { })
+DEF_TRAVERSE_STMT(CompoundStmt, { })
+DEF_TRAVERSE_STMT(ContinueStmt, { })
+DEF_TRAVERSE_STMT(DefaultStmt, { })
+DEF_TRAVERSE_STMT(DoStmt, { })
+DEF_TRAVERSE_STMT(ForStmt, { })
+DEF_TRAVERSE_STMT(GotoStmt, { })
+DEF_TRAVERSE_STMT(IfStmt, { })
+DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
+DEF_TRAVERSE_STMT(LabelStmt, { })
+DEF_TRAVERSE_STMT(NullStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
+DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
+DEF_TRAVERSE_STMT(ReturnStmt, { })
+DEF_TRAVERSE_STMT(SwitchStmt, { })
+DEF_TRAVERSE_STMT(WhileStmt, { })
+
+
+DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ }
+ })
+
+DEF_TRAVERSE_STMT(DeclRefExpr, {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ // FIXME: Should we be recursing on the qualifier?
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ })
+
+DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
+ // FIXME: Should we be recursing on these two things?
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ })
+
+DEF_TRAVERSE_STMT(MemberExpr, {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ // FIXME: Should we be recursing on the qualifier?
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ })
+
+DEF_TRAVERSE_STMT(ImplicitCastExpr, {
+ // We don't traverse the cast type, as it's not written in the
+ // source code.
+ })
+
+DEF_TRAVERSE_STMT(CStyleCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXConstCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default. We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
+ if (InitListExpr *Syn = S->getSyntacticForm())
+ S = Syn;
+ TRY_TO(WalkUpFromInitListExpr(S));
+ // All we need are the default actions. FIXME: use a helper function.
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ TRY_TO(TraverseStmt(*range));
+ }
+ return true;
+}
+
+DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
+ // This is called for code like 'return T()' where T is a built-in
+ // (i.e. non-class) type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXNewExpr, {
+ // The child-iterator will pick up the other arguments.
+ TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(OffsetOfExpr, {
+ // The child-iterator will pick up the expression representing
+ // the field.
+ // FIMXE: for code like offsetof(Foo, a.b.c), should we get
+ // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isArgumentType())
+ TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTypeidExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXUuidofExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
+ // This is called for code like 'return T()' where T is a class type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
+ // This is called for code like 'T()', where T is a template argument.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+// These expressions all might take explicit template arguments.
+// We traverse those if so. FIXME: implement these.
+DEF_TRAVERSE_STMT(CXXConstructExpr, { })
+DEF_TRAVERSE_STMT(CallExpr, { })
+DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
+
+// These exprs (most of them), do not need any action except iterating
+// over the children.
+DEF_TRAVERSE_STMT(AddrLabelExpr, { })
+DEF_TRAVERSE_STMT(ArraySubscriptExpr, { })
+DEF_TRAVERSE_STMT(BlockDeclRefExpr, { })
+DEF_TRAVERSE_STMT(BlockExpr, { })
+DEF_TRAVERSE_STMT(ChooseExpr, { })
+DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
+DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
+DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
+DEF_TRAVERSE_STMT(ExprWithCleanups, { })
+DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
+ TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
+ if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
+ TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(CXXThisExpr, { })
+DEF_TRAVERSE_STMT(CXXThrowExpr, { })
+DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
+DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
+DEF_TRAVERSE_STMT(GNUNullExpr, { })
+DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
+DEF_TRAVERSE_STMT(ObjCEncodeExpr, { })
+DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
+DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
+DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
+DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
+DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
+DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
+DEF_TRAVERSE_STMT(ParenExpr, { })
+DEF_TRAVERSE_STMT(ParenListExpr, { })
+DEF_TRAVERSE_STMT(PredefinedExpr, { })
+DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
+DEF_TRAVERSE_STMT(StmtExpr, { })
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
+DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
+DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { })
+
+// These operators (all of them) do not need any action except
+// iterating over the children.
+DEF_TRAVERSE_STMT(BinaryConditionalOperator, { })
+DEF_TRAVERSE_STMT(ConditionalOperator, { })
+DEF_TRAVERSE_STMT(UnaryOperator, { })
+DEF_TRAVERSE_STMT(BinaryOperator, { })
+DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
+DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
+DEF_TRAVERSE_STMT(PackExpansionExpr, { })
+DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
+
+// These literals (all of them) do not need any action.
+DEF_TRAVERSE_STMT(IntegerLiteral, { })
+DEF_TRAVERSE_STMT(CharacterLiteral, { })
+DEF_TRAVERSE_STMT(FloatingLiteral, { })
+DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
+DEF_TRAVERSE_STMT(StringLiteral, { })
+DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
+
+// FIXME: look at the following tricky-seeming exprs to see if we
+// need to recurse on anything. These are ones that have methods
+// returning decls or qualtypes or nestednamespecifier -- though I'm
+// not sure if they own them -- or just seemed very complicated, or
+// had lots of sub-types to explore.
+//
+// VisitOverloadExpr and its children: recurse on template args? etc?
+
+// FIXME: go through all the stmts and exprs again, and see which of them
+// create new types, and recurse on the types (TypeLocs?) of those.
+// Candidates:
+//
+// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
+// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html
+// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
+// Every class that has getQualifier.
+
+#undef DEF_TRAVERSE_STMT
+
+#undef TRY_TO
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
new file mode 100644
index 0000000..e87ca78
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
@@ -0,0 +1,169 @@
+//===-- Redeclarable.h - Base for Decls that can be redeclared -*- 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 Redeclarable interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_REDECLARABLE_H
+#define LLVM_CLANG_AST_REDECLARABLE_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Casting.h"
+#include <iterator>
+
+namespace clang {
+
+/// \brief Provides common interface for the Decls that can be redeclared.
+template<typename decl_type>
+class Redeclarable {
+
+protected:
+ // FIXME: PointerIntPair is a value class that should not be inherited from.
+ // This should change to using containment.
+ struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
+ DeclLink(decl_type *D, bool isLatest)
+ : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
+
+ typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type;
+
+ bool NextIsPrevious() const { return base_type::getInt() == false; }
+ bool NextIsLatest() const { return base_type::getInt() == true; }
+ decl_type *getNext() const { return base_type::getPointer(); }
+ };
+
+ struct PreviousDeclLink : public DeclLink {
+ PreviousDeclLink(decl_type *D) : DeclLink(D, false) { }
+ };
+
+ struct LatestDeclLink : public DeclLink {
+ LatestDeclLink(decl_type *D) : DeclLink(D, true) { }
+ };
+
+ /// \brief Points to the next redeclaration in the chain.
+ ///
+ /// If NextIsPrevious() is true, this is a link to the previous declaration
+ /// of this same Decl. If NextIsLatest() is true, this is the first
+ /// declaration and Link points to the latest declaration. For example:
+ ///
+ /// #1 int f(int x, int y = 1); // <pointer to #3, true>
+ /// #2 int f(int x = 0, int y); // <pointer to #1, false>
+ /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
+ ///
+ /// If there is only one declaration, it is <pointer to self, true>
+ DeclLink RedeclLink;
+
+public:
+ Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
+
+ /// \brief Return the previous declaration of this declaration or NULL if this
+ /// is the first declaration.
+ decl_type *getPreviousDeclaration() {
+ if (RedeclLink.NextIsPrevious())
+ return RedeclLink.getNext();
+ return 0;
+ }
+ const decl_type *getPreviousDeclaration() const {
+ return const_cast<decl_type *>(
+ static_cast<const decl_type*>(this))->getPreviousDeclaration();
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDeclaration() {
+ decl_type *D = static_cast<decl_type*>(this);
+ while (D->getPreviousDeclaration())
+ D = D->getPreviousDeclaration();
+ return D;
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDeclaration() const {
+ const decl_type *D = static_cast<const decl_type*>(this);
+ while (D->getPreviousDeclaration())
+ D = D->getPreviousDeclaration();
+ return D;
+ }
+
+ /// \brief Returns true if this is the first declaration.
+ bool isFirstDeclaration() const {
+ return RedeclLink.NextIsLatest();
+ }
+
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ decl_type *getMostRecentDeclaration() {
+ return getFirstDeclaration()->RedeclLink.getNext();
+ }
+
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ const decl_type *getMostRecentDeclaration() const {
+ return getFirstDeclaration()->RedeclLink.getNext();
+ }
+
+ /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
+ /// first and only declaration.
+ void setPreviousDeclaration(decl_type *PrevDecl);
+
+ /// \brief Iterates through all the redeclarations of the same decl.
+ class redecl_iterator {
+ /// Current - The current declaration.
+ decl_type *Current;
+ decl_type *Starter;
+
+ public:
+ typedef decl_type* value_type;
+ typedef decl_type* reference;
+ typedef decl_type* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(0) { }
+ explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Get either previous decl or latest decl.
+ decl_type *Next = Current->RedeclLink.getNext();
+ Current = (Next != Starter ? Next : 0);
+ return *this;
+ }
+
+ redecl_iterator operator++(int) {
+ redecl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(redecl_iterator x, redecl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(redecl_iterator x, redecl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Returns iterator for all the redeclarations of the same decl.
+ /// It will iterate at least once (when this decl is the only one).
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<decl_type*>(
+ static_cast<const decl_type*>(this)));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
new file mode 100644
index 0000000..7ede9ce
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -0,0 +1,1410 @@
+//===--- Stmt.h - Classes for representing statements -----------*- 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 Stmt interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_H
+#define LLVM_CLANG_AST_STMT_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/StmtIterator.h"
+#include "clang/AST/DeclGroup.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/ASTContext.h"
+#include <string>
+using llvm::dyn_cast_or_null;
+
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
+namespace clang {
+ class ASTContext;
+ class Expr;
+ class Decl;
+ class ParmVarDecl;
+ class QualType;
+ class IdentifierInfo;
+ class SourceManager;
+ class StringLiteral;
+ class SwitchStmt;
+
+ //===----------------------------------------------------------------------===//
+ // ExprIterator - Iterators for iterating over Stmt* arrays that contain
+ // only Expr*. This is needed because AST nodes use Stmt* arrays to store
+ // references to children (to be compatible with StmtIterator).
+ //===----------------------------------------------------------------------===//
+
+ class Stmt;
+ class Expr;
+
+ class ExprIterator {
+ Stmt** I;
+ public:
+ ExprIterator(Stmt** i) : I(i) {}
+ ExprIterator() : I(0) {}
+ ExprIterator& operator++() { ++I; return *this; }
+ ExprIterator operator-(size_t i) { return I-i; }
+ ExprIterator operator+(size_t i) { return I+i; }
+ Expr* operator[](size_t idx);
+ // FIXME: Verify that this will correctly return a signed distance.
+ signed operator-(const ExprIterator& R) const { return I - R.I; }
+ Expr* operator*() const;
+ Expr* operator->() const;
+ bool operator==(const ExprIterator& R) const { return I == R.I; }
+ bool operator!=(const ExprIterator& R) const { return I != R.I; }
+ bool operator>(const ExprIterator& R) const { return I > R.I; }
+ bool operator>=(const ExprIterator& R) const { return I >= R.I; }
+ };
+
+ class ConstExprIterator {
+ const Stmt * const *I;
+ public:
+ ConstExprIterator(const Stmt * const *i) : I(i) {}
+ ConstExprIterator() : I(0) {}
+ ConstExprIterator& operator++() { ++I; return *this; }
+ ConstExprIterator operator+(size_t i) const { return I+i; }
+ ConstExprIterator operator-(size_t i) const { return I-i; }
+ const Expr * operator[](size_t idx) const;
+ signed operator-(const ConstExprIterator& R) const { return I - R.I; }
+ const Expr * operator*() const;
+ const Expr * operator->() const;
+ bool operator==(const ConstExprIterator& R) const { return I == R.I; }
+ bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
+ bool operator>(const ConstExprIterator& R) const { return I > R.I; }
+ bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
+ };
+
+//===----------------------------------------------------------------------===//
+// AST classes for statements.
+//===----------------------------------------------------------------------===//
+
+/// Stmt - This represents one statement.
+///
+class Stmt {
+public:
+ enum StmtClass {
+ NoStmtClass = 0,
+#define STMT(CLASS, PARENT) CLASS##Class,
+#define STMT_RANGE(BASE, FIRST, LAST) \
+ first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class,
+#define LAST_STMT_RANGE(BASE, FIRST, LAST) \
+ first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class
+#define ABSTRACT_STMT(STMT)
+#include "clang/AST/StmtNodes.inc"
+ };
+
+ // Make vanilla 'new' and 'delete' illegal for Stmts.
+protected:
+ void* operator new(size_t bytes) throw() {
+ assert(0 && "Stmts cannot be allocated with regular 'new'.");
+ return 0;
+ }
+ void operator delete(void* data) throw() {
+ assert(0 && "Stmts cannot be released with regular 'delete'.");
+ }
+
+ class StmtBitfields {
+ friend class Stmt;
+
+ /// \brief The statement class.
+ unsigned sClass : 8;
+ };
+ enum { NumStmtBits = 8 };
+
+ class CompoundStmtBitfields {
+ friend class CompoundStmt;
+ unsigned : NumStmtBits;
+
+ unsigned NumStmts : 32 - NumStmtBits;
+ };
+
+ class ExprBitfields {
+ friend class Expr;
+ friend class DeclRefExpr; // computeDependence
+ friend class InitListExpr; // ctor
+ friend class DesignatedInitExpr; // ctor
+ friend class BlockDeclRefExpr; // ctor
+ friend class ASTStmtReader; // deserialization
+ friend class CXXNewExpr; // ctor
+ friend class DependentScopeDeclRefExpr; // ctor
+ friend class CXXConstructExpr; // ctor
+ friend class CallExpr; // ctor
+ friend class OffsetOfExpr; // ctor
+ friend class ObjCMessageExpr; // ctor
+ friend class ShuffleVectorExpr; // ctor
+ friend class ParenListExpr; // ctor
+ friend class CXXUnresolvedConstructExpr; // ctor
+ friend class CXXDependentScopeMemberExpr; // ctor
+ friend class OverloadExpr; // ctor
+ unsigned : NumStmtBits;
+
+ unsigned ValueKind : 2;
+ unsigned ObjectKind : 2;
+ unsigned TypeDependent : 1;
+ unsigned ValueDependent : 1;
+ unsigned ContainsUnexpandedParameterPack : 1;
+ };
+ enum { NumExprBits = 15 };
+
+ class CastExprBitfields {
+ friend class CastExpr;
+ unsigned : NumExprBits;
+
+ unsigned Kind : 6;
+ unsigned BasePathSize : 32 - 6 - NumExprBits;
+ };
+
+ class CallExprBitfields {
+ friend class CallExpr;
+ unsigned : NumExprBits;
+
+ unsigned NumPreArgs : 1;
+ };
+
+ union {
+ // FIXME: this is wasteful on 64-bit platforms.
+ void *Aligner;
+
+ StmtBitfields StmtBits;
+ CompoundStmtBitfields CompoundStmtBits;
+ ExprBitfields ExprBits;
+ CastExprBitfields CastExprBits;
+ CallExprBitfields CallExprBits;
+ };
+
+ friend class ASTStmtReader;
+
+public:
+ // Only allow allocation of Stmts using the allocator in ASTContext
+ // or by doing a placement new.
+ void* operator new(size_t bytes, ASTContext& C,
+ unsigned alignment = 8) throw() {
+ return ::operator new(bytes, C, alignment);
+ }
+
+ void* operator new(size_t bytes, ASTContext* C,
+ unsigned alignment = 8) throw() {
+ return ::operator new(bytes, *C, alignment);
+ }
+
+ void* operator new(size_t bytes, void* mem) throw() {
+ return mem;
+ }
+
+ void operator delete(void*, ASTContext&, unsigned) throw() { }
+ void operator delete(void*, ASTContext*, unsigned) throw() { }
+ void operator delete(void*, std::size_t) throw() { }
+ void operator delete(void*, void*) throw() { }
+
+public:
+ /// \brief A placeholder type used to construct an empty shell of a
+ /// type, that will be filled in later (e.g., by some
+ /// de-serialization).
+ struct EmptyShell { };
+
+protected:
+ /// \brief Construct an empty statement.
+ explicit Stmt(StmtClass SC, EmptyShell) {
+ StmtBits.sClass = SC;
+ if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
+ }
+
+public:
+ Stmt(StmtClass SC) {
+ StmtBits.sClass = SC;
+ if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
+ }
+
+ StmtClass getStmtClass() const {
+ return static_cast<StmtClass>(StmtBits.sClass);
+ }
+ const char *getStmtClassName() const;
+
+ /// SourceLocation tokens are not useful in isolation - they are low level
+ /// value objects created/interpreted by SourceManager. We assume AST
+ /// clients will have a pointer to the respective SourceManager.
+ SourceRange getSourceRange() const;
+
+ SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
+ SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
+
+ // global temp stats (until we have a per-module visitor)
+ static void addStmtClass(const StmtClass s);
+ static bool CollectingStats(bool Enable = false);
+ static void PrintStats();
+
+ /// dump - This does a local dump of the specified AST fragment. It dumps the
+ /// specified node and a few nodes underneath it, but not the whole subtree.
+ /// This is useful in a debugger.
+ void dump() const;
+ void dump(SourceManager &SM) const;
+ void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
+
+ /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+ void dumpAll() const;
+ void dumpAll(SourceManager &SM) const;
+
+ /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
+ /// back to its original source language syntax.
+ void dumpPretty(ASTContext& Context) const;
+ void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper,
+ const PrintingPolicy &Policy,
+ unsigned Indentation = 0) const {
+ printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
+ }
+ void printPretty(llvm::raw_ostream &OS, ASTContext &Context,
+ PrinterHelper *Helper,
+ const PrintingPolicy &Policy,
+ unsigned Indentation = 0) const;
+
+ /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
+ /// works on systems with GraphViz (Mac OS X) or dot+gv installed.
+ void viewAST() const;
+
+ // Implement isa<T> support.
+ static bool classof(const Stmt *) { return true; }
+
+ /// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
+ /// contain implicit control-flow in the order their subexpressions
+ /// are evaluated. This predicate returns true if this statement has
+ /// such implicit control-flow. Such statements are also specially handled
+ /// within CFGs.
+ bool hasImplicitControlFlow() const;
+
+ /// Child Iterators: All subclasses must implement 'children'
+ /// to permit easy iteration over the substatements/subexpessions of an
+ /// AST node. This permits easy iteration over all nodes in the AST.
+ typedef StmtIterator child_iterator;
+ typedef ConstStmtIterator const_child_iterator;
+
+ typedef StmtRange child_range;
+ typedef ConstStmtRange const_child_range;
+
+ child_range children();
+ const_child_range children() const {
+ return const_cast<Stmt*>(this)->children();
+ }
+
+ child_iterator child_begin() { return children().first; }
+ child_iterator child_end() { return children().second; }
+
+ const_child_iterator child_begin() const { return children().first; }
+ const_child_iterator child_end() const { return children().second; }
+
+ /// \brief Produce a unique representation of the given statement.
+ ///
+ /// \brief ID once the profiling operation is complete, will contain
+ /// the unique representation of the given statement.
+ ///
+ /// \brief Context the AST context in which the statement resides
+ ///
+ /// \brief Canonical whether the profile should be based on the canonical
+ /// representation of this statement (e.g., where non-type template
+ /// parameters are identified by index/level rather than their
+ /// declaration pointers) or the exact representation of the statement as
+ /// written in the source.
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ bool Canonical);
+};
+
+/// DeclStmt - Adaptor class for mixing declarations with statements and
+/// expressions. For example, CompoundStmt mixes statements, expressions
+/// and declarations (variables, types). Another example is ForStmt, where
+/// the first statement can be an expression or a declaration.
+///
+class DeclStmt : public Stmt {
+ DeclGroupRef DG;
+ SourceLocation StartLoc, EndLoc;
+
+public:
+ DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
+ SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
+ StartLoc(startLoc), EndLoc(endLoc) {}
+
+ /// \brief Build an empty declaration statement.
+ explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
+
+ /// isSingleDecl - This method returns true if this DeclStmt refers
+ /// to a single Decl.
+ bool isSingleDecl() const {
+ return DG.isSingleDecl();
+ }
+
+ const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
+ Decl *getSingleDecl() { return DG.getSingleDecl(); }
+
+ const DeclGroupRef getDeclGroup() const { return DG; }
+ DeclGroupRef getDeclGroup() { return DG; }
+ void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
+
+ SourceLocation getStartLoc() const { return StartLoc; }
+ void setStartLoc(SourceLocation L) { StartLoc = L; }
+ SourceLocation getEndLoc() const { return EndLoc; }
+ void setEndLoc(SourceLocation L) { EndLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLoc, EndLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclStmtClass;
+ }
+ static bool classof(const DeclStmt *) { return true; }
+
+ // Iterators over subexpressions.
+ child_range children() {
+ return child_range(child_iterator(DG.begin(), DG.end()),
+ child_iterator(DG.end(), DG.end()));
+ }
+
+ typedef DeclGroupRef::iterator decl_iterator;
+ typedef DeclGroupRef::const_iterator const_decl_iterator;
+
+ decl_iterator decl_begin() { return DG.begin(); }
+ decl_iterator decl_end() { return DG.end(); }
+ const_decl_iterator decl_begin() const { return DG.begin(); }
+ const_decl_iterator decl_end() const { return DG.end(); }
+};
+
+/// NullStmt - This is the null statement ";": C99 6.8.3p3.
+///
+class NullStmt : public Stmt {
+ SourceLocation SemiLoc;
+
+ /// \brief Whether the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ bool LeadingEmptyMacro;
+public:
+ NullStmt(SourceLocation L, bool LeadingEmptyMacro = false)
+ : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {}
+
+ /// \brief Build an empty null statement.
+ explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
+
+ SourceLocation getSemiLoc() const { return SemiLoc; }
+ void setSemiLoc(SourceLocation L) { SemiLoc = L; }
+
+ bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; }
+
+ SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == NullStmtClass;
+ }
+ static bool classof(const NullStmt *) { return true; }
+
+ child_range children() { return child_range(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// CompoundStmt - This represents a group of statements like { stmt stmt }.
+///
+class CompoundStmt : public Stmt {
+ Stmt** Body;
+ SourceLocation LBracLoc, RBracLoc;
+public:
+ CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts,
+ SourceLocation LB, SourceLocation RB)
+ : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
+ CompoundStmtBits.NumStmts = NumStmts;
+
+ if (NumStmts == 0) {
+ Body = 0;
+ return;
+ }
+
+ Body = new (C) Stmt*[NumStmts];
+ memcpy(Body, StmtStart, NumStmts * sizeof(*Body));
+ }
+
+ // \brief Build an empty compound statement.
+ explicit CompoundStmt(EmptyShell Empty)
+ : Stmt(CompoundStmtClass, Empty), Body(0) {
+ CompoundStmtBits.NumStmts = 0;
+ }
+
+ void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
+
+ bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
+ unsigned size() const { return CompoundStmtBits.NumStmts; }
+
+ typedef Stmt** body_iterator;
+ body_iterator body_begin() { return Body; }
+ body_iterator body_end() { return Body + size(); }
+ Stmt *body_back() { return !body_empty() ? Body[size()-1] : 0; }
+
+ void setLastStmt(Stmt *S) {
+ assert(!body_empty() && "setLastStmt");
+ Body[size()-1] = S;
+ }
+
+ typedef Stmt* const * const_body_iterator;
+ const_body_iterator body_begin() const { return Body; }
+ const_body_iterator body_end() const { return Body + size(); }
+ const Stmt *body_back() const { return !body_empty() ? Body[size()-1] : 0; }
+
+ typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
+ reverse_body_iterator body_rbegin() {
+ return reverse_body_iterator(body_end());
+ }
+ reverse_body_iterator body_rend() {
+ return reverse_body_iterator(body_begin());
+ }
+
+ typedef std::reverse_iterator<const_body_iterator>
+ const_reverse_body_iterator;
+
+ const_reverse_body_iterator body_rbegin() const {
+ return const_reverse_body_iterator(body_end());
+ }
+
+ const_reverse_body_iterator body_rend() const {
+ return const_reverse_body_iterator(body_begin());
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LBracLoc, RBracLoc);
+ }
+
+ SourceLocation getLBracLoc() const { return LBracLoc; }
+ void setLBracLoc(SourceLocation L) { LBracLoc = L; }
+ SourceLocation getRBracLoc() const { return RBracLoc; }
+ void setRBracLoc(SourceLocation L) { RBracLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundStmtClass;
+ }
+ static bool classof(const CompoundStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
+ }
+};
+
+// SwitchCase is the base class for CaseStmt and DefaultStmt,
+class SwitchCase : public Stmt {
+protected:
+ // A pointer to the following CaseStmt or DefaultStmt class,
+ // used by SwitchStmt.
+ SwitchCase *NextSwitchCase;
+
+ SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {}
+
+public:
+ const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
+
+ SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
+
+ void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
+
+ Stmt *getSubStmt();
+
+ SourceRange getSourceRange() const { return SourceRange(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass ||
+ T->getStmtClass() == DefaultStmtClass;
+ }
+ static bool classof(const SwitchCase *) { return true; }
+};
+
+class CaseStmt : public SwitchCase {
+ enum { SUBSTMT, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
+ // GNU "case 1 ... 4" extension
+ SourceLocation CaseLoc;
+ SourceLocation EllipsisLoc;
+ SourceLocation ColonLoc;
+public:
+ CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
+ SourceLocation ellipsisLoc, SourceLocation colonLoc)
+ : SwitchCase(CaseStmtClass) {
+ SubExprs[SUBSTMT] = 0;
+ SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
+ SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
+ CaseLoc = caseLoc;
+ EllipsisLoc = ellipsisLoc;
+ ColonLoc = colonLoc;
+ }
+
+ /// \brief Build an empty switch case statement.
+ explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { }
+
+ SourceLocation getCaseLoc() const { return CaseLoc; }
+ void setCaseLoc(SourceLocation L) { CaseLoc = L; }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
+ Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
+ Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+
+ const Expr *getLHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+ }
+ const Expr *getRHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+ }
+ const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
+
+ void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
+ void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
+ void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+
+
+ SourceRange getSourceRange() const {
+ // Handle deeply nested case statements with iteration instead of recursion.
+ const CaseStmt *CS = this;
+ while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
+ CS = CS2;
+
+ return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass;
+ }
+ static bool classof(const CaseStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
+};
+
+class DefaultStmt : public SwitchCase {
+ Stmt* SubStmt;
+ SourceLocation DefaultLoc;
+ SourceLocation ColonLoc;
+public:
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
+ SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
+ ColonLoc(CL) {}
+
+ /// \brief Build an empty default statement.
+ explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
+
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+ void setSubStmt(Stmt *S) { SubStmt = S; }
+
+ SourceLocation getDefaultLoc() const { return DefaultLoc; }
+ void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(DefaultLoc, SubStmt->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DefaultStmtClass;
+ }
+ static bool classof(const DefaultStmt *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+};
+
+
+/// LabelStmt - Represents a label, which has a substatement. For example:
+/// foo: return;
+///
+class LabelStmt : public Stmt {
+ LabelDecl *TheDecl;
+ Stmt *SubStmt;
+ SourceLocation IdentLoc;
+public:
+ LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
+ : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {
+ }
+
+ // \brief Build an empty label statement.
+ explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
+
+ SourceLocation getIdentLoc() const { return IdentLoc; }
+ LabelDecl *getDecl() const { return TheDecl; }
+ void setDecl(LabelDecl *D) { TheDecl = D; }
+ const char *getName() const;
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+ void setIdentLoc(SourceLocation L) { IdentLoc = L; }
+ void setSubStmt(Stmt *SS) { SubStmt = SS; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(IdentLoc, SubStmt->getLocEnd());
+ }
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == LabelStmtClass;
+ }
+ static bool classof(const LabelStmt *) { return true; }
+};
+
+
+/// IfStmt - This represents an if/then/else.
+///
+class IfStmt : public Stmt {
+ enum { VAR, COND, THEN, ELSE, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+
+ SourceLocation IfLoc;
+ SourceLocation ElseLoc;
+
+public:
+ IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
+ Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0);
+
+ /// \brief Build an empty if/then/else statement
+ explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
+
+ /// \brief Retrieve the variable declared in this "if" statement, if any.
+ ///
+ /// In the following example, "x" is the condition variable.
+ /// \code
+ /// if (int x = foo()) {
+ /// printf("x is %d", x);
+ /// }
+ /// \endcode
+ VarDecl *getConditionVariable() const;
+ void setConditionVariable(ASTContext &C, VarDecl *V);
+
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
+ const Stmt *getThen() const { return SubExprs[THEN]; }
+ void setThen(Stmt *S) { SubExprs[THEN] = S; }
+ const Stmt *getElse() const { return SubExprs[ELSE]; }
+ void setElse(Stmt *S) { SubExprs[ELSE] = S; }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ Stmt *getThen() { return SubExprs[THEN]; }
+ Stmt *getElse() { return SubExprs[ELSE]; }
+
+ SourceLocation getIfLoc() const { return IfLoc; }
+ void setIfLoc(SourceLocation L) { IfLoc = L; }
+ SourceLocation getElseLoc() const { return ElseLoc; }
+ void setElseLoc(SourceLocation L) { ElseLoc = L; }
+
+ SourceRange getSourceRange() const {
+ if (SubExprs[ELSE])
+ return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
+ else
+ return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
+ }
+
+ // Iterators over subexpressions. The iterators will include iterating
+ // over the initialization expression referenced by the condition variable.
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IfStmtClass;
+ }
+ static bool classof(const IfStmt *) { return true; }
+};
+
+/// SwitchStmt - This represents a 'switch' stmt.
+///
+class SwitchStmt : public Stmt {
+ enum { VAR, COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ // This points to a linked list of case and default statements.
+ SwitchCase *FirstCase;
+ SourceLocation SwitchLoc;
+
+ /// If the SwitchStmt is a switch on an enum value, this records whether
+ /// all the enum values were covered by CaseStmts. This value is meant to
+ /// be a hint for possible clients.
+ unsigned AllEnumCasesCovered : 1;
+
+public:
+ SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
+
+ /// \brief Build a empty switch statement.
+ explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
+
+ /// \brief Retrieve the variable declared in this "switch" statement, if any.
+ ///
+ /// In the following example, "x" is the condition variable.
+ /// \code
+ /// switch (int x = foo()) {
+ /// case 0: break;
+ /// // ...
+ /// }
+ /// \endcode
+ VarDecl *getConditionVariable() const;
+ void setConditionVariable(ASTContext &C, VarDecl *V);
+
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ const SwitchCase *getSwitchCaseList() const { return FirstCase; }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+ SwitchCase *getSwitchCaseList() { return FirstCase; }
+
+ /// \brief Set the case list for this switch statement.
+ ///
+ /// The caller is responsible for incrementing the retain counts on
+ /// all of the SwitchCase statements in this list.
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
+
+ SourceLocation getSwitchLoc() const { return SwitchLoc; }
+ void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
+
+ void setBody(Stmt *S, SourceLocation SL) {
+ SubExprs[BODY] = S;
+ SwitchLoc = SL;
+ }
+ void addSwitchCase(SwitchCase *SC) {
+ assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
+ SC->setNextSwitchCase(FirstCase);
+ FirstCase = SC;
+ }
+
+ /// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
+ /// switch over an enum value then all cases have been explicitly covered.
+ void setAllEnumCasesCovered() {
+ AllEnumCasesCovered = 1;
+ }
+
+ /// Returns true if the SwitchStmt is a switch of an enum value and all cases
+ /// have been explicitly covered.
+ bool isAllEnumCasesCovered() const {
+ return (bool) AllEnumCasesCovered;
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
+ }
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SwitchStmtClass;
+ }
+ static bool classof(const SwitchStmt *) { return true; }
+};
+
+
+/// WhileStmt - This represents a 'while' stmt.
+///
+class WhileStmt : public Stmt {
+ enum { VAR, COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation WhileLoc;
+public:
+ WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ SourceLocation WL);
+
+ /// \brief Build an empty while statement.
+ explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
+
+ /// \brief Retrieve the variable declared in this "while" statement, if any.
+ ///
+ /// In the following example, "x" is the condition variable.
+ /// \code
+ /// while (int x = random()) {
+ /// // ...
+ /// }
+ /// \endcode
+ VarDecl *getConditionVariable() const;
+ void setConditionVariable(ASTContext &C, VarDecl *V);
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getWhileLoc() const { return WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == WhileStmtClass;
+ }
+ static bool classof(const WhileStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// DoStmt - This represents a 'do/while' stmt.
+///
+class DoStmt : public Stmt {
+ enum { BODY, COND, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation DoLoc;
+ SourceLocation WhileLoc;
+ SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
+
+public:
+ DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL,
+ SourceLocation RP)
+ : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = body;
+ }
+
+ /// \brief Build an empty do-while statement.
+ explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getDoLoc() const { return DoLoc; }
+ void setDoLoc(SourceLocation L) { DoLoc = L; }
+ SourceLocation getWhileLoc() const { return WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(DoLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DoStmtClass;
+ }
+ static bool classof(const DoStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+
+/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of
+/// the init/cond/inc parts of the ForStmt will be null if they were not
+/// specified in the source.
+///
+class ForStmt : public Stmt {
+ enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
+ SourceLocation ForLoc;
+ SourceLocation LParenLoc, RParenLoc;
+
+public:
+ ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc,
+ Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP);
+
+ /// \brief Build an empty for statement.
+ explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
+
+ Stmt *getInit() { return SubExprs[INIT]; }
+
+ /// \brief Retrieve the variable declared in this "for" statement, if any.
+ ///
+ /// In the following example, "y" is the condition variable.
+ /// \code
+ /// for (int x = random(); int y = mangle(x); ++x) {
+ /// // ...
+ /// }
+ /// \endcode
+ VarDecl *getConditionVariable() const;
+ void setConditionVariable(ASTContext &C, VarDecl *V);
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+
+ const Stmt *getInit() const { return SubExprs[INIT]; }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+
+ void setInit(Stmt *S) { SubExprs[INIT] = S; }
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getForLoc() const { return ForLoc; }
+ void setForLoc(SourceLocation L) { ForLoc = L; }
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ForStmtClass;
+ }
+ static bool classof(const ForStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// GotoStmt - This represents a direct goto.
+///
+class GotoStmt : public Stmt {
+ LabelDecl *Label;
+ SourceLocation GotoLoc;
+ SourceLocation LabelLoc;
+public:
+ GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
+ : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
+
+ /// \brief Build an empty goto statement.
+ explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
+
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *D) { Label = D; }
+
+ SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getLabelLoc() const { return LabelLoc; }
+ void setLabelLoc(SourceLocation L) { LabelLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(GotoLoc, LabelLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GotoStmtClass;
+ }
+ static bool classof(const GotoStmt *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// IndirectGotoStmt - This represents an indirect goto.
+///
+class IndirectGotoStmt : public Stmt {
+ SourceLocation GotoLoc;
+ SourceLocation StarLoc;
+ Stmt *Target;
+public:
+ IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
+ Expr *target)
+ : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
+ Target((Stmt*)target) {}
+
+ /// \brief Build an empty indirect goto statement.
+ explicit IndirectGotoStmt(EmptyShell Empty)
+ : Stmt(IndirectGotoStmtClass, Empty) { }
+
+ void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setStarLoc(SourceLocation L) { StarLoc = L; }
+ SourceLocation getStarLoc() const { return StarLoc; }
+
+ Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
+ const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
+ void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
+
+ /// getConstantTarget - Returns the fixed target of this indirect
+ /// goto, if one exists.
+ LabelDecl *getConstantTarget();
+ const LabelDecl *getConstantTarget() const {
+ return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+ }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(GotoLoc, Target->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IndirectGotoStmtClass;
+ }
+ static bool classof(const IndirectGotoStmt *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(&Target, &Target+1); }
+};
+
+
+/// ContinueStmt - This represents a continue.
+///
+class ContinueStmt : public Stmt {
+ SourceLocation ContinueLoc;
+public:
+ ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
+
+ /// \brief Build an empty continue statement.
+ explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
+
+ SourceLocation getContinueLoc() const { return ContinueLoc; }
+ void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(ContinueLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ContinueStmtClass;
+ }
+ static bool classof(const ContinueStmt *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+/// BreakStmt - This represents a break.
+///
+class BreakStmt : public Stmt {
+ SourceLocation BreakLoc;
+public:
+ BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
+
+ /// \brief Build an empty break statement.
+ explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
+
+ SourceLocation getBreakLoc() const { return BreakLoc; }
+ void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+
+ SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BreakStmtClass;
+ }
+ static bool classof(const BreakStmt *) { return true; }
+
+ // Iterators
+ child_range children() { return child_range(); }
+};
+
+
+/// ReturnStmt - This represents a return, optionally of an expression:
+/// return;
+/// return 4;
+///
+/// Note that GCC allows return with no argument in a function declared to
+/// return a value, and it allows returning a value in functions declared to
+/// return void. We explicitly model this in the AST, which means you can't
+/// depend on the return type of the function and the presence of an argument.
+///
+class ReturnStmt : public Stmt {
+ Stmt *RetExpr;
+ SourceLocation RetLoc;
+ const VarDecl *NRVOCandidate;
+
+public:
+ ReturnStmt(SourceLocation RL)
+ : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { }
+
+ ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
+ : Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL),
+ NRVOCandidate(NRVOCandidate) {}
+
+ /// \brief Build an empty return expression.
+ explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
+
+ const Expr *getRetValue() const;
+ Expr *getRetValue();
+ void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); }
+
+ SourceLocation getReturnLoc() const { return RetLoc; }
+ void setReturnLoc(SourceLocation L) { RetLoc = L; }
+
+ /// \brief Retrieve the variable that might be used for the named return
+ /// value optimization.
+ ///
+ /// The optimization itself can only be performed if the variable is
+ /// also marked as an NRVO object.
+ const VarDecl *getNRVOCandidate() const { return NRVOCandidate; }
+ void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ReturnStmtClass;
+ }
+ static bool classof(const ReturnStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ return child_range();
+ }
+};
+
+/// AsmStmt - This represents a GNU inline-assembly statement extension.
+///
+class AsmStmt : public Stmt {
+ SourceLocation AsmLoc, RParenLoc;
+ StringLiteral *AsmStr;
+
+ bool IsSimple;
+ bool IsVolatile;
+ bool MSAsm;
+
+ unsigned NumOutputs;
+ unsigned NumInputs;
+ unsigned NumClobbers;
+
+ // FIXME: If we wanted to, we could allocate all of these in one big array.
+ IdentifierInfo **Names;
+ StringLiteral **Constraints;
+ Stmt **Exprs;
+ StringLiteral **Clobbers;
+
+public:
+ AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,
+ bool msasm, unsigned numoutputs, unsigned numinputs,
+ IdentifierInfo **names, StringLiteral **constraints,
+ Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
+ StringLiteral **clobbers, SourceLocation rparenloc);
+
+ /// \brief Build an empty inline-assembly statement.
+ explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty),
+ Names(0), Constraints(0), Exprs(0), Clobbers(0) { }
+
+ SourceLocation getAsmLoc() const { return AsmLoc; }
+ void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ bool isVolatile() const { return IsVolatile; }
+ void setVolatile(bool V) { IsVolatile = V; }
+ bool isSimple() const { return IsSimple; }
+ void setSimple(bool V) { IsSimple = V; }
+ bool isMSAsm() const { return MSAsm; }
+ void setMSAsm(bool V) { MSAsm = V; }
+
+ //===--- Asm String Analysis ---===//
+
+ const StringLiteral *getAsmString() const { return AsmStr; }
+ StringLiteral *getAsmString() { return AsmStr; }
+ void setAsmString(StringLiteral *E) { AsmStr = E; }
+
+ /// AsmStringPiece - this is part of a decomposed asm string specification
+ /// (for use with the AnalyzeAsmString function below). An asm string is
+ /// considered to be a concatenation of these parts.
+ class AsmStringPiece {
+ public:
+ enum Kind {
+ String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%".
+ Operand // Operand reference, with optional modifier %c4.
+ };
+ private:
+ Kind MyKind;
+ std::string Str;
+ unsigned OperandNo;
+ public:
+ AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
+ AsmStringPiece(unsigned OpNo, char Modifier)
+ : MyKind(Operand), Str(), OperandNo(OpNo) {
+ Str += Modifier;
+ }
+
+ bool isString() const { return MyKind == String; }
+ bool isOperand() const { return MyKind == Operand; }
+
+ const std::string &getString() const {
+ assert(isString());
+ return Str;
+ }
+
+ unsigned getOperandNo() const {
+ assert(isOperand());
+ return OperandNo;
+ }
+
+ /// getModifier - Get the modifier for this operand, if present. This
+ /// returns '\0' if there was no modifier.
+ char getModifier() const {
+ assert(isOperand());
+ return Str[0];
+ }
+ };
+
+ /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
+ /// it into pieces. If the asm string is erroneous, emit errors and return
+ /// true, otherwise return false. This handles canonicalization and
+ /// translation of strings from GCC syntax to LLVM IR syntax, and handles
+ //// flattening of named references like %[foo] to Operand AsmStringPiece's.
+ unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
+ ASTContext &C, unsigned &DiagOffs) const;
+
+
+ //===--- Output operands ---===//
+
+ unsigned getNumOutputs() const { return NumOutputs; }
+
+ IdentifierInfo *getOutputIdentifier(unsigned i) const {
+ return Names[i];
+ }
+
+ llvm::StringRef getOutputName(unsigned i) const {
+ if (IdentifierInfo *II = getOutputIdentifier(i))
+ return II->getName();
+
+ return llvm::StringRef();
+ }
+
+ /// getOutputConstraint - Return the constraint string for the specified
+ /// output operand. All output constraints are known to be non-empty (either
+ /// '=' or '+').
+ llvm::StringRef getOutputConstraint(unsigned i) const;
+
+ const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
+ return Constraints[i];
+ }
+ StringLiteral *getOutputConstraintLiteral(unsigned i) {
+ return Constraints[i];
+ }
+
+ Expr *getOutputExpr(unsigned i);
+
+ const Expr *getOutputExpr(unsigned i) const {
+ return const_cast<AsmStmt*>(this)->getOutputExpr(i);
+ }
+
+ /// isOutputPlusConstraint - Return true if the specified output constraint
+ /// is a "+" constraint (which is both an input and an output) or false if it
+ /// is an "=" constraint (just an output).
+ bool isOutputPlusConstraint(unsigned i) const {
+ return getOutputConstraint(i)[0] == '+';
+ }
+
+ /// getNumPlusOperands - Return the number of output operands that have a "+"
+ /// constraint.
+ unsigned getNumPlusOperands() const;
+
+ //===--- Input operands ---===//
+
+ unsigned getNumInputs() const { return NumInputs; }
+
+ IdentifierInfo *getInputIdentifier(unsigned i) const {
+ return Names[i + NumOutputs];
+ }
+
+ llvm::StringRef getInputName(unsigned i) const {
+ if (IdentifierInfo *II = getInputIdentifier(i))
+ return II->getName();
+
+ return llvm::StringRef();
+ }
+
+ /// getInputConstraint - Return the specified input constraint. Unlike output
+ /// constraints, these can be empty.
+ llvm::StringRef getInputConstraint(unsigned i) const;
+
+ const StringLiteral *getInputConstraintLiteral(unsigned i) const {
+ return Constraints[i + NumOutputs];
+ }
+ StringLiteral *getInputConstraintLiteral(unsigned i) {
+ return Constraints[i + NumOutputs];
+ }
+
+ Expr *getInputExpr(unsigned i);
+
+ const Expr *getInputExpr(unsigned i) const {
+ return const_cast<AsmStmt*>(this)->getInputExpr(i);
+ }
+
+ void setOutputsAndInputsAndClobbers(ASTContext &C,
+ IdentifierInfo **Names,
+ StringLiteral **Constraints,
+ Stmt **Exprs,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ StringLiteral **Clobbers,
+ unsigned NumClobbers);
+
+ //===--- Other ---===//
+
+ /// getNamedOperand - Given a symbolic operand reference like %[foo],
+ /// translate this into a numeric value needed to reference the same operand.
+ /// This returns -1 if the operand name is invalid.
+ int getNamedOperand(llvm::StringRef SymbolicName) const;
+
+ unsigned getNumClobbers() const { return NumClobbers; }
+ StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
+ const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AsmLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;}
+ static bool classof(const AsmStmt *) { return true; }
+
+ // Input expr iterators.
+
+ typedef ExprIterator inputs_iterator;
+ typedef ConstExprIterator const_inputs_iterator;
+
+ inputs_iterator begin_inputs() {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ inputs_iterator end_inputs() {
+ return &Exprs[0] + NumOutputs + NumInputs;
+ }
+
+ const_inputs_iterator begin_inputs() const {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ const_inputs_iterator end_inputs() const {
+ return &Exprs[0] + NumOutputs + NumInputs;
+ }
+
+ // Output expr iterators.
+
+ typedef ExprIterator outputs_iterator;
+ typedef ConstExprIterator const_outputs_iterator;
+
+ outputs_iterator begin_outputs() {
+ return &Exprs[0];
+ }
+ outputs_iterator end_outputs() {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ const_outputs_iterator begin_outputs() const {
+ return &Exprs[0];
+ }
+ const_outputs_iterator end_outputs() const {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
new file mode 100644
index 0000000..f08815f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
@@ -0,0 +1,125 @@
+//===--- StmtCXX.h - Classes for representing C++ statements ----*- 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 C++ statement AST node classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTCXX_H
+#define LLVM_CLANG_AST_STMTCXX_H
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+class VarDecl;
+
+/// CXXCatchStmt - This represents a C++ catch block.
+///
+class CXXCatchStmt : public Stmt {
+ SourceLocation CatchLoc;
+ /// The exception-declaration of the type.
+ VarDecl *ExceptionDecl;
+ /// The handler block.
+ Stmt *HandlerBlock;
+
+public:
+ CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
+ : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
+ HandlerBlock(handlerBlock) {}
+
+ CXXCatchStmt(EmptyShell Empty)
+ : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
+
+ SourceRange getSourceRange() const {
+ return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
+ }
+
+ SourceLocation getCatchLoc() const { return CatchLoc; }
+ VarDecl *getExceptionDecl() const { return ExceptionDecl; }
+ QualType getCaughtType() const;
+ Stmt *getHandlerBlock() const { return HandlerBlock; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXCatchStmtClass;
+ }
+ static bool classof(const CXXCatchStmt *) { return true; }
+
+ child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
+
+ friend class ASTStmtReader;
+};
+
+/// CXXTryStmt - A C++ try block, including all handlers.
+///
+class CXXTryStmt : public Stmt {
+ SourceLocation TryLoc;
+ unsigned NumHandlers;
+
+ CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers,
+ unsigned numHandlers);
+
+ CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
+ : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
+
+ Stmt const * const *getStmts() const {
+ return reinterpret_cast<Stmt const * const*>(this + 1);
+ }
+ Stmt **getStmts() {
+ return reinterpret_cast<Stmt **>(this + 1);
+ }
+
+public:
+ static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
+ Stmt *tryBlock, Stmt **handlers,
+ unsigned numHandlers);
+
+ static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(getTryLoc(), getEndLoc());
+ }
+
+ SourceLocation getTryLoc() const { return TryLoc; }
+ SourceLocation getEndLoc() const {
+ return getStmts()[NumHandlers]->getLocEnd();
+ }
+
+ CompoundStmt *getTryBlock() {
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
+ }
+ const CompoundStmt *getTryBlock() const {
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
+ }
+
+ unsigned getNumHandlers() const { return NumHandlers; }
+ CXXCatchStmt *getHandler(unsigned i) {
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
+ }
+ const CXXCatchStmt *getHandler(unsigned i) const {
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTryStmtClass;
+ }
+ static bool classof(const CXXTryStmt *) { return true; }
+
+ child_range children() {
+ return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
+ }
+
+ friend class ASTStmtReader;
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h
new file mode 100644
index 0000000..25d0152
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h
@@ -0,0 +1,83 @@
+//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a template specialization of llvm::GraphTraits to
+// treat ASTs (Stmt*) as graphs
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+
+namespace llvm {
+
+//template <typename T> struct GraphTraits;
+
+
+template <> struct GraphTraits<clang::Stmt*> {
+ typedef clang::Stmt NodeType;
+ typedef clang::Stmt::child_iterator ChildIteratorType;
+ typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
+
+ static NodeType* getEntryNode(clang::Stmt* S) { return S; }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ if (N) return N->child_begin();
+ else return ChildIteratorType();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ if (N) return N->child_end();
+ else return ChildIteratorType();
+ }
+
+ static nodes_iterator nodes_begin(clang::Stmt* S) {
+ return df_begin(S);
+ }
+
+ static nodes_iterator nodes_end(clang::Stmt* S) {
+ return df_end(S);
+ }
+};
+
+
+template <> struct GraphTraits<const clang::Stmt*> {
+ typedef const clang::Stmt NodeType;
+ typedef clang::Stmt::const_child_iterator ChildIteratorType;
+ typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
+
+ static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ if (N) return N->child_begin();
+ else return ChildIteratorType();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ if (N) return N->child_end();
+ else return ChildIteratorType();
+ }
+
+ static nodes_iterator nodes_begin(const clang::Stmt* S) {
+ return df_begin(S);
+ }
+
+ static nodes_iterator nodes_end(const clang::Stmt* S) {
+ return df_end(S);
+ }
+};
+
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
new file mode 100644
index 0000000..851c001
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
@@ -0,0 +1,231 @@
+//===--- StmtIterator.h - Iterators for Statements --------------*- 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 StmtIterator and ConstStmtIterator classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_ITR_H
+#define LLVM_CLANG_AST_STMT_ITR_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+namespace clang {
+
+class Stmt;
+class Decl;
+class VariableArrayType;
+
+class StmtIteratorBase {
+protected:
+ enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
+ Flags = 0x3 };
+
+ Stmt **stmt;
+ union { Decl *decl; Decl **DGI; };
+ uintptr_t RawVAPtr;
+ Decl **DGE;
+
+ bool inDecl() const {
+ return (RawVAPtr & Flags) == DeclMode;
+ }
+
+ bool inDeclGroup() const {
+ return (RawVAPtr & Flags) == DeclGroupMode;
+ }
+
+ bool inSizeOfTypeVA() const {
+ return (RawVAPtr & Flags) == SizeOfTypeVAMode;
+ }
+
+ bool inStmt() const {
+ return (RawVAPtr & Flags) == 0;
+ }
+
+ const VariableArrayType *getVAPtr() const {
+ return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
+ }
+
+ void setVAPtr(const VariableArrayType *P) {
+ assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
+ RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
+ }
+
+ void NextDecl(bool ImmediateAdvance = true);
+ bool HandleDecl(Decl* D);
+ void NextVA();
+
+ Stmt*& GetDeclExpr() const;
+
+ StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
+ StmtIteratorBase(Decl *d, Stmt **s);
+ StmtIteratorBase(const VariableArrayType *t);
+ StmtIteratorBase(Decl **dgi, Decl **dge);
+ StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
+};
+
+
+template <typename DERIVED, typename REFERENCE>
+class StmtIteratorImpl : public StmtIteratorBase,
+ public std::iterator<std::forward_iterator_tag,
+ REFERENCE, ptrdiff_t,
+ REFERENCE, REFERENCE> {
+protected:
+ StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
+public:
+ StmtIteratorImpl() {}
+ StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
+ StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
+ StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
+ StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
+
+ DERIVED& operator++() {
+ if (inDecl() || inDeclGroup()) {
+ if (getVAPtr()) NextVA();
+ else NextDecl();
+ }
+ else if (inSizeOfTypeVA())
+ NextVA();
+ else
+ ++stmt;
+
+ return static_cast<DERIVED&>(*this);
+ }
+
+ DERIVED operator++(int) {
+ DERIVED tmp = static_cast<DERIVED&>(*this);
+ operator++();
+ return tmp;
+ }
+
+ bool operator==(const DERIVED& RHS) const {
+ return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
+ }
+
+ bool operator!=(const DERIVED& RHS) const {
+ return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
+ }
+
+ REFERENCE operator*() const {
+ return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
+ }
+
+ REFERENCE operator->() const { return operator*(); }
+};
+
+struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
+ explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
+
+ StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
+
+ StmtIterator(Decl** dgi, Decl** dge)
+ : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
+
+ StmtIterator(const VariableArrayType *t)
+ : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
+
+ StmtIterator(Decl* D, Stmt **s = 0)
+ : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
+};
+
+struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
+ const Stmt*> {
+ explicit ConstStmtIterator() :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
+
+ ConstStmtIterator(const StmtIterator& RHS) :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
+};
+
+/// A range of statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (StmtRange range = stmt->children(); range; ++range)
+struct StmtRange : std::pair<StmtIterator,StmtIterator> {
+ StmtRange() {}
+ StmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<StmtIterator,StmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ Stmt *operator->() const { return first.operator->(); }
+ Stmt *&operator*() const { return first.operator*(); }
+
+ StmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ StmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ StmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const StmtIterator &begin(const StmtRange &range) {
+ return range.first;
+ }
+ friend const StmtIterator &end(const StmtRange &range) {
+ return range.second;
+ }
+};
+
+/// A range of const statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (ConstStmtRange range = stmt->children(); range; ++range)
+struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
+ ConstStmtRange() {}
+ ConstStmtRange(const ConstStmtIterator &begin,
+ const ConstStmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+ ConstStmtRange(const StmtRange &range)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
+ {}
+ ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ const Stmt *operator->() const { return first.operator->(); }
+ const Stmt *operator*() const { return first.operator*(); }
+
+ ConstStmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ ConstStmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ ConstStmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
+ return range.first;
+ }
+ friend const ConstStmtIterator &end(const ConstStmtRange &range) {
+ return range.second;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
new file mode 100644
index 0000000..1800a71
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
@@ -0,0 +1,347 @@
+//===--- StmtObjC.h - Classes for representing ObjC statements --*- 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 Objective-C statement AST node classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTOBJC_H
+#define LLVM_CLANG_AST_STMTOBJC_H
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+/// ObjCForCollectionStmt - This represents Objective-c's collection statement;
+/// represented as 'for (element 'in' collection-expression)' stmt.
+///
+class ObjCForCollectionStmt : public Stmt {
+ enum { ELEM, COLLECTION, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
+ SourceLocation ForLoc;
+ SourceLocation RParenLoc;
+public:
+ ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
+ SourceLocation FCL, SourceLocation RPL);
+ explicit ObjCForCollectionStmt(EmptyShell Empty) :
+ Stmt(ObjCForCollectionStmtClass, Empty) { }
+
+ Stmt *getElement() { return SubExprs[ELEM]; }
+ Expr *getCollection() {
+ return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+ }
+ Stmt *getBody() { return SubExprs[BODY]; }
+
+ const Stmt *getElement() const { return SubExprs[ELEM]; }
+ const Expr *getCollection() const {
+ return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+ }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+
+ void setElement(Stmt *S) { SubExprs[ELEM] = S; }
+ void setCollection(Expr *E) {
+ SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
+ }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getForLoc() const { return ForLoc; }
+ void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCForCollectionStmtClass;
+ }
+ static bool classof(const ObjCForCollectionStmt *) { return true; }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
+};
+
+/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
+class ObjCAtCatchStmt : public Stmt {
+private:
+ VarDecl *ExceptionDecl;
+ Stmt *Body;
+ SourceLocation AtCatchLoc, RParenLoc;
+
+public:
+ ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
+ VarDecl *catchVarDecl,
+ Stmt *atCatchStmt)
+ : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
+ Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }
+
+ explicit ObjCAtCatchStmt(EmptyShell Empty) :
+ Stmt(ObjCAtCatchStmtClass, Empty) { }
+
+ const Stmt *getCatchBody() const { return Body; }
+ Stmt *getCatchBody() { return Body; }
+ void setCatchBody(Stmt *S) { Body = S; }
+
+ const VarDecl *getCatchParamDecl() const {
+ return ExceptionDecl;
+ }
+ VarDecl *getCatchParamDecl() {
+ return ExceptionDecl;
+ }
+ void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; }
+
+ SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
+ void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtCatchLoc, Body->getLocEnd());
+ }
+
+ bool hasEllipsis() const { return getCatchParamDecl() == 0; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtCatchStmtClass;
+ }
+ static bool classof(const ObjCAtCatchStmt *) { return true; }
+
+ child_range children() { return child_range(&Body, &Body + 1); }
+};
+
+/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
+class ObjCAtFinallyStmt : public Stmt {
+ Stmt *AtFinallyStmt;
+ SourceLocation AtFinallyLoc;
+public:
+ ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
+ : Stmt(ObjCAtFinallyStmtClass),
+ AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
+
+ explicit ObjCAtFinallyStmt(EmptyShell Empty) :
+ Stmt(ObjCAtFinallyStmtClass, Empty) { }
+
+ const Stmt *getFinallyBody() const { return AtFinallyStmt; }
+ Stmt *getFinallyBody() { return AtFinallyStmt; }
+ void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
+ }
+
+ SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
+ void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtFinallyStmtClass;
+ }
+ static bool classof(const ObjCAtFinallyStmt *) { return true; }
+
+ child_range children() {
+ return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
+ }
+};
+
+/// ObjCAtTryStmt - This represent objective-c's over-all
+/// @try ... @catch ... @finally statement.
+class ObjCAtTryStmt : public Stmt {
+private:
+ // The location of the
+ SourceLocation AtTryLoc;
+
+ // The number of catch blocks in this statement.
+ unsigned NumCatchStmts : 16;
+
+ // Whether this statement has a @finally statement.
+ bool HasFinally : 1;
+
+ /// \brief Retrieve the statements that are stored after this @try statement.
+ ///
+ /// The order of the statements in memory follows the order in the source,
+ /// with the @try body first, followed by the @catch statements (if any) and,
+ /// finally, the @finally (if it exists).
+ Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); }
+ const Stmt* const *getStmts() const {
+ return reinterpret_cast<const Stmt * const*> (this + 1);
+ }
+
+ ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt);
+
+ explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts,
+ bool HasFinally)
+ : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts),
+ HasFinally(HasFinally) { }
+
+public:
+ static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc,
+ Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt);
+ static ObjCAtTryStmt *CreateEmpty(ASTContext &Context,
+ unsigned NumCatchStmts,
+ bool HasFinally);
+
+ /// \brief Retrieve the location of the @ in the @try.
+ SourceLocation getAtTryLoc() const { return AtTryLoc; }
+ void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
+
+ /// \brief Retrieve the @try body.
+ const Stmt *getTryBody() const { return getStmts()[0]; }
+ Stmt *getTryBody() { return getStmts()[0]; }
+ void setTryBody(Stmt *S) { getStmts()[0] = S; }
+
+ /// \brief Retrieve the number of @catch statements in this try-catch-finally
+ /// block.
+ unsigned getNumCatchStmts() const { return NumCatchStmts; }
+
+ /// \brief Retrieve a @catch statement.
+ const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
+ assert(I < NumCatchStmts && "Out-of-bounds @catch index");
+ return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
+ }
+
+ /// \brief Retrieve a @catch statement.
+ ObjCAtCatchStmt *getCatchStmt(unsigned I) {
+ assert(I < NumCatchStmts && "Out-of-bounds @catch index");
+ return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
+ }
+
+ /// \brief Set a particular catch statement.
+ void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
+ assert(I < NumCatchStmts && "Out-of-bounds @catch index");
+ getStmts()[I + 1] = S;
+ }
+
+ /// Retrieve the @finally statement, if any.
+ const ObjCAtFinallyStmt *getFinallyStmt() const {
+ if (!HasFinally)
+ return 0;
+
+ return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
+ }
+ ObjCAtFinallyStmt *getFinallyStmt() {
+ if (!HasFinally)
+ return 0;
+
+ return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
+ }
+ void setFinallyStmt(Stmt *S) {
+ assert(HasFinally && "@try does not have a @finally slot!");
+ getStmts()[1 + NumCatchStmts] = S;
+ }
+
+ SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtTryStmtClass;
+ }
+ static bool classof(const ObjCAtTryStmt *) { return true; }
+
+ child_range children() {
+ return child_range(getStmts(),
+ getStmts() + 1 + NumCatchStmts + HasFinally);
+ }
+};
+
+/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
+/// Example: @synchronized (sem) {
+/// do-something;
+/// }
+///
+class ObjCAtSynchronizedStmt : public Stmt {
+private:
+ enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
+ Stmt* SubStmts[END_EXPR];
+ SourceLocation AtSynchronizedLoc;
+
+public:
+ ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
+ Stmt *synchBody)
+ : Stmt(ObjCAtSynchronizedStmtClass) {
+ SubStmts[SYNC_EXPR] = synchExpr;
+ SubStmts[SYNC_BODY] = synchBody;
+ AtSynchronizedLoc = atSynchronizedLoc;
+ }
+ explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
+ Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
+
+ SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
+ void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
+
+ const CompoundStmt *getSynchBody() const {
+ return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
+ }
+ CompoundStmt *getSynchBody() {
+ return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
+ }
+ void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
+
+ const Expr *getSynchExpr() const {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+ }
+ Expr *getSynchExpr() {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+ }
+ void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
+ }
+ static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
+
+ child_range children() {
+ return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
+ }
+};
+
+/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
+class ObjCAtThrowStmt : public Stmt {
+ Stmt *Throw;
+ SourceLocation AtThrowLoc;
+public:
+ ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
+ : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
+ AtThrowLoc = atThrowLoc;
+ }
+ explicit ObjCAtThrowStmt(EmptyShell Empty) :
+ Stmt(ObjCAtThrowStmtClass, Empty) { }
+
+ const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
+ Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
+ void setThrowExpr(Stmt *S) { Throw = S; }
+
+ SourceLocation getThrowLoc() { return AtThrowLoc; }
+ void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
+
+ SourceRange getSourceRange() const {
+ if (Throw)
+ return SourceRange(AtThrowLoc, Throw->getLocEnd());
+ else
+ return SourceRange(AtThrowLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtThrowStmtClass;
+ }
+ static bool classof(const ObjCAtThrowStmt *) { return true; }
+
+ child_range children() { return child_range(&Throw, &Throw+1); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
new file mode 100644
index 0000000..b8c141d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
@@ -0,0 +1,166 @@
+//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- 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 StmtVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTVISITOR_H
+#define LLVM_CLANG_AST_STMTVISITOR_H
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S))
+
+/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
+/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
+template<typename ImplClass, typename RetTy=void>
+class StmtVisitor {
+public:
+ RetTy Visit(Stmt *S) {
+
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+ switch (BinOp->getOpcode()) {
+ default: assert(0 && "Unknown binary operator!");
+ case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
+ case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
+ case BO_Mul: DISPATCH(BinMul, BinaryOperator);
+ case BO_Div: DISPATCH(BinDiv, BinaryOperator);
+ case BO_Rem: DISPATCH(BinRem, BinaryOperator);
+ case BO_Add: DISPATCH(BinAdd, BinaryOperator);
+ case BO_Sub: DISPATCH(BinSub, BinaryOperator);
+ case BO_Shl: DISPATCH(BinShl, BinaryOperator);
+ case BO_Shr: DISPATCH(BinShr, BinaryOperator);
+
+ case BO_LT: DISPATCH(BinLT, BinaryOperator);
+ case BO_GT: DISPATCH(BinGT, BinaryOperator);
+ case BO_LE: DISPATCH(BinLE, BinaryOperator);
+ case BO_GE: DISPATCH(BinGE, BinaryOperator);
+ case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
+ case BO_NE: DISPATCH(BinNE, BinaryOperator);
+
+ case BO_And: DISPATCH(BinAnd, BinaryOperator);
+ case BO_Xor: DISPATCH(BinXor, BinaryOperator);
+ case BO_Or : DISPATCH(BinOr, BinaryOperator);
+ case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator);
+ case BO_LOr : DISPATCH(BinLOr, BinaryOperator);
+ case BO_Assign: DISPATCH(BinAssign, BinaryOperator);
+ case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator);
+ case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator);
+ case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator);
+ case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator);
+ case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator);
+ case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator);
+ case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator);
+ case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator);
+ case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator);
+ case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
+ case BO_Comma: DISPATCH(BinComma, BinaryOperator);
+ }
+ } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
+ switch (UnOp->getOpcode()) {
+ default: assert(0 && "Unknown unary operator!");
+ case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
+ case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
+ case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
+ case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
+ case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
+ case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator);
+ case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator);
+ case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator);
+ case UO_Not: DISPATCH(UnaryNot, UnaryOperator);
+ case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator);
+ case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
+ case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
+ case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
+ }
+ }
+
+ // Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
+ switch (S->getStmtClass()) {
+ default: assert(0 && "Unknown stmt kind!");
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
+#include "clang/AST/StmtNodes.inc"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit method, fall
+ // back on VisitExpr or whatever else is the superclass.
+#define STMT(CLASS, PARENT) \
+ RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); }
+#include "clang/AST/StmtNodes.inc"
+
+ // If the implementation doesn't implement binary operator methods, fall back
+ // on VisitBinaryOperator.
+#define BINOP_FALLBACK(NAME) \
+ RetTy VisitBin ## NAME(BinaryOperator *S) { \
+ DISPATCH(BinaryOperator, BinaryOperator); \
+ }
+ BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI)
+ BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem)
+ BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl)
+ BINOP_FALLBACK(Shr)
+
+ BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
+ BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
+ BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
+ BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr)
+
+ BINOP_FALLBACK(Assign)
+ BINOP_FALLBACK(Comma)
+#undef BINOP_FALLBACK
+
+ // If the implementation doesn't implement compound assignment operator
+ // methods, fall back on VisitCompoundAssignOperator.
+#define CAO_FALLBACK(NAME) \
+ RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \
+ DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
+ }
+ CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
+ CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign)
+ CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign)
+ CAO_FALLBACK(XorAssign)
+#undef CAO_FALLBACK
+
+ // If the implementation doesn't implement unary operator methods, fall back
+ // on VisitUnaryOperator.
+#define UNARYOP_FALLBACK(NAME) \
+ RetTy VisitUnary ## NAME(UnaryOperator *S) { \
+ DISPATCH(UnaryOperator, UnaryOperator); \
+ }
+ UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
+ UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
+ UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref)
+
+ UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
+ UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
+ UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
+ UNARYOP_FALLBACK(Extension)
+#undef UNARYOP_FALLBACK
+
+ // Base case, ignore it. :)
+ RetTy VisitStmt(Stmt *Node) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
new file mode 100644
index 0000000..a4e074e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
@@ -0,0 +1,571 @@
+//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides definitions which are common for all kinds of
+// template representation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
+#define LLVM_CLANG_AST_TEMPLATEBASE_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TemplateName.h"
+
+namespace llvm {
+ class FoldingSetNodeID;
+ class raw_ostream;
+}
+
+namespace clang {
+
+class Decl;
+class DiagnosticBuilder;
+class Expr;
+struct PrintingPolicy;
+class TypeSourceInfo;
+
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+public:
+ /// \brief The kind of template argument we're storing.
+ enum ArgKind {
+ /// \brief Represents an empty template argument, e.g., one that has not
+ /// been deduced.
+ Null = 0,
+ /// The template argument is a type. Its value is stored in the
+ /// TypeOrValue field.
+ Type,
+ /// The template argument is a declaration that was provided for a pointer
+ /// or reference non-type template parameter.
+ Declaration,
+ /// The template argument is an integral value stored in an llvm::APSInt
+ /// that was provided for an integral non-type template parameter.
+ Integral,
+ /// The template argument is a template name that was provided for a
+ /// template template parameter.
+ Template,
+ /// The template argument is a pack expansion of a template name that was
+ /// provided for a template template parameter.
+ TemplateExpansion,
+ /// The template argument is a value- or type-dependent expression
+ /// stored in an Expr*.
+ Expression,
+ /// The template argument is actually a parameter pack. Arguments are stored
+ /// in the Args struct.
+ Pack
+ };
+
+private:
+ /// \brief The kind of template argument we're storing.
+ unsigned Kind;
+
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ } Args;
+ struct {
+ void *Name;
+ unsigned NumExpansions;
+ } TemplateArg;
+ };
+
+ TemplateArgument(TemplateName, bool); // DO NOT USE
+
+public:
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() : Kind(Null), TypeOrValue(0) { }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(QualType T) : Kind(Type) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ }
+
+ /// \brief Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
+ TemplateArgument(Decl *D) : Kind(Declaration) {
+ // FIXME: Need to be sure we have the "canonical" declaration!
+ TypeOrValue = reinterpret_cast<uintptr_t>(D);
+ }
+
+ /// \brief Construct an integral constant template argument.
+ TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
+ new (Integer.Value) llvm::APSInt(Value);
+ Integer.Type = Type.getAsOpaquePtr();
+ }
+
+ /// \brief Construct a template argument that is a template.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ ///
+ /// \param Name The template name.
+ TemplateArgument(TemplateName Name) : Kind(Template)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ TemplateArg.NumExpansions = 0;
+ }
+
+ /// \brief Construct a template argument that is a template pack expansion.
+ ///
+ /// This form of template argument is generally used for template template
+ /// parameters. However, the template name could be a dependent template
+ /// name that ends up being instantiated to a function template whose address
+ /// is taken.
+ ///
+ /// \param Name The template name.
+ ///
+ /// \param NumExpansions The number of expansions that will be generated by
+ /// instantiating
+ TemplateArgument(TemplateName Name, llvm::Optional<unsigned> NumExpansions)
+ : Kind(TemplateExpansion)
+ {
+ TemplateArg.Name = Name.getAsVoidPointer();
+ if (NumExpansions)
+ TemplateArg.NumExpansions = *NumExpansions + 1;
+ else
+ TemplateArg.NumExpansions = 0;
+ }
+
+ /// \brief Construct a template argument that is an expression.
+ ///
+ /// This form of template argument only occurs in template argument
+ /// lists used for dependent types and for expression; it will not
+ /// occur in a non-dependent, canonical template argument list.
+ TemplateArgument(Expr *E) : Kind(Expression) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(E);
+ }
+
+ /// \brief Construct a template argument that is a template argument pack.
+ ///
+ /// We assume that storage for the template arguments provided
+ /// outlives the TemplateArgument itself.
+ TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
+ this->Args.Args = Args;
+ this->Args.NumArgs = NumArgs;
+ }
+
+ /// \brief Copy constructor for a template argument.
+ TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ // FIXME: Large integral values will get leaked. Do something
+ // similar to what we did with IntegerLiteral.
+ if (Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ TemplateArgument& operator=(const TemplateArgument& Other) {
+ using llvm::APSInt;
+
+ if (Kind == Other.Kind && Kind == Integral) {
+ // Copy integral values.
+ *this->getAsIntegral() = *Other.getAsIntegral();
+ Integer.Type = Other.Integer.Type;
+ return *this;
+ }
+
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+
+ Kind = Other.Kind;
+
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Other.Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = Other.Args.Args;
+ } else if (Kind == Template || Kind == TemplateExpansion) {
+ TemplateArg.Name = Other.TemplateArg.Name;
+ TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
+ } else {
+ TypeOrValue = Other.TypeOrValue;
+ }
+
+ return *this;
+ }
+
+ ~TemplateArgument() {
+ using llvm::APSInt;
+
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+ }
+
+ /// \brief Create a new template argument pack by copying the given set of
+ /// template arguments.
+ static TemplateArgument CreatePackCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return (ArgKind)Kind; }
+
+ /// \brief Determine whether this template argument has no value.
+ bool isNull() const { return Kind == Null; }
+
+ /// \brief Whether this template argument is dependent on a template
+ /// parameter.
+ bool isDependent() const;
+
+ /// \brief Whether this template argument contains an unexpanded
+ /// parameter pack.
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Determine whether this template argument is a pack expansion.
+ bool isPackExpansion() const;
+
+ /// \brief Retrieve the template argument as a type.
+ QualType getAsType() const {
+ if (Kind != Type)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+ }
+
+ /// \brief Retrieve the template argument as a declaration.
+ Decl *getAsDecl() const {
+ if (Kind != Declaration)
+ return 0;
+ return reinterpret_cast<Decl *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the template argument as a template name.
+ TemplateName getAsTemplate() const {
+ if (Kind != Template)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
+ }
+
+ /// \brief Retrieve the template argument as a template name; if the argument
+ /// is a pack expansion, return the pattern as a template name.
+ TemplateName getAsTemplateOrTemplatePattern() const {
+ if (Kind != Template && Kind != TemplateExpansion)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
+ }
+
+ /// \brief Retrieve the number of expansions that a template template argument
+ /// expansion will produce, if known.
+ llvm::Optional<unsigned> getNumTemplateExpansions() const;
+
+ /// \brief Retrieve the template argument as an integral value.
+ llvm::APSInt *getAsIntegral() {
+ if (Kind != Integral)
+ return 0;
+ return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+ }
+
+ const llvm::APSInt *getAsIntegral() const {
+ return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ if (Kind != Integral)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ void setIntegralType(QualType T) {
+ assert(Kind == Integral &&
+ "Cannot set the integral type of a non-integral template argument");
+ Integer.Type = T.getAsOpaquePtr();
+ }
+
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ if (Kind != Expression)
+ return 0;
+
+ return reinterpret_cast<Expr *>(TypeOrValue);
+ }
+
+ /// \brief Iterator that traverses the elements of a template argument pack.
+ typedef const TemplateArgument * pack_iterator;
+
+ /// \brief Iterator referencing the first argument of a template argument
+ /// pack.
+ pack_iterator pack_begin() const {
+ assert(Kind == Pack);
+ return Args.Args;
+ }
+
+ /// \brief Iterator referencing one past the last argument of a template
+ /// argument pack.
+ pack_iterator pack_end() const {
+ assert(Kind == Pack);
+ return Args.Args + Args.NumArgs;
+ }
+
+ /// \brief The number of template arguments in the given template argument
+ /// pack.
+ unsigned pack_size() const {
+ assert(Kind == Pack);
+ return Args.NumArgs;
+ }
+
+ /// Determines whether two template arguments are superficially the
+ /// same.
+ bool structurallyEquals(const TemplateArgument &Other) const;
+
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ TemplateArgument getPackExpansionPattern() const;
+
+ /// \brief Print this template argument to the given output stream.
+ void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
+
+ /// \brief Used to insert TemplateArguments into FoldingSets.
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
+};
+
+/// Location information for a TemplateArgument.
+struct TemplateArgumentLocInfo {
+private:
+ union {
+ Expr *Expression;
+ TypeSourceInfo *Declarator;
+ struct {
+ unsigned QualifierRange[2];
+ unsigned TemplateNameLoc;
+ unsigned EllipsisLoc;
+ } Template;
+ };
+
+public:
+ TemplateArgumentLocInfo();
+
+ TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
+
+ TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
+
+ TemplateArgumentLocInfo(SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
+ {
+ Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
+ Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
+ Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ }
+
+ TypeSourceInfo *getAsTypeSourceInfo() const {
+ return Declarator;
+ }
+
+ Expr *getAsExpr() const {
+ return Expression;
+ }
+
+ SourceRange getTemplateQualifierRange() const {
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
+ SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
+ }
+
+ SourceLocation getTemplateEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
+ }
+};
+
+/// Location wrapper for a TemplateArgument. TemplateArgument is to
+/// TemplateArgumentLoc as Type is to TypeLoc.
+class TemplateArgumentLoc {
+ TemplateArgument Argument;
+ TemplateArgumentLocInfo LocInfo;
+
+public:
+ TemplateArgumentLoc() {}
+
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ TemplateArgumentLocInfo Opaque)
+ : Argument(Argument), LocInfo(Opaque) {
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
+ : Argument(Argument), LocInfo(TInfo) {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
+ : Argument(Argument), LocInfo(E) {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ }
+
+ TemplateArgumentLoc(const TemplateArgument &Argument,
+ SourceRange QualifierRange,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc = SourceLocation())
+ : Argument(Argument),
+ LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ }
+
+ /// \brief - Fetches the primary location of the argument.
+ SourceLocation getLocation() const {
+ if (Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion)
+ return getTemplateNameLoc();
+
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief - Fetches the full source range of the argument.
+ SourceRange getSourceRange() const;
+
+ const TemplateArgument &getArgument() const {
+ return Argument;
+ }
+
+ TemplateArgumentLocInfo getLocInfo() const {
+ return LocInfo;
+ }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ assert(Argument.getKind() == TemplateArgument::Type);
+ return LocInfo.getAsTypeSourceInfo();
+ }
+
+ Expr *getSourceExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Expression);
+ return LocInfo.getAsExpr();
+ }
+
+ Expr *getSourceDeclExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Declaration);
+ return LocInfo.getAsExpr();
+ }
+
+ SourceRange getTemplateQualifierRange() const {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateQualifierRange();
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateNameLoc();
+ }
+
+ SourceLocation getTemplateEllipsisLoc() const {
+ assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateEllipsisLoc();
+ }
+
+ /// \brief When the template argument is a pack expansion, returns
+ /// the pattern of the pack expansion.
+ ///
+ /// \param Ellipsis Will be set to the location of the ellipsis.
+ ///
+ /// \param NumExpansions Will be set to the number of expansions that will
+ /// be generated from this pack expansion, if known a priori.
+ TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
+ ASTContext &Context) const;
+};
+
+/// A convenient class for passing around template argument
+/// information. Designed to be passed by reference.
+class TemplateArgumentListInfo {
+ llvm::SmallVector<TemplateArgumentLoc, 8> Arguments;
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+
+public:
+ TemplateArgumentListInfo() {}
+
+ TemplateArgumentListInfo(SourceLocation LAngleLoc,
+ SourceLocation RAngleLoc)
+ : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
+
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
+ void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
+
+ unsigned size() const { return Arguments.size(); }
+
+ const TemplateArgumentLoc *getArgumentArray() const {
+ return Arguments.data();
+ }
+
+ const TemplateArgumentLoc &operator[](unsigned I) const {
+ return Arguments[I];
+ }
+
+ void addArgument(const TemplateArgumentLoc &Loc) {
+ Arguments.push_back(Loc);
+ }
+};
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const TemplateArgument &Arg);
+
+inline TemplateSpecializationType::iterator
+ TemplateSpecializationType::end() const {
+ return getArgs() + getNumArgs();
+}
+
+inline DependentTemplateSpecializationType::iterator
+ DependentTemplateSpecializationType::end() const {
+ return getArgs() + getNumArgs();
+}
+
+inline const TemplateArgument &
+ TemplateSpecializationType::getArg(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Template argument out of range");
+ return getArgs()[Idx];
+}
+
+inline const TemplateArgument &
+ DependentTemplateSpecializationType::getArg(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Template argument out of range");
+ return getArgs()[Idx];
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
new file mode 100644
index 0000000..1721973
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
@@ -0,0 +1,493 @@
+//===--- TemplateName.h - C++ Template Name Representation-------*- 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 TemplateName interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
+#define LLVM_CLANG_AST_TEMPLATENAME_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "clang/Basic/OperatorKinds.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class ASTContext;
+class DependentTemplateName;
+class DiagnosticBuilder;
+class IdentifierInfo;
+class NestedNameSpecifier;
+class OverloadedTemplateStorage;
+struct PrintingPolicy;
+class QualifiedTemplateName;
+class NamedDecl;
+class SubstTemplateTemplateParmPackStorage;
+class TemplateArgument;
+class TemplateDecl;
+class TemplateTemplateParmDecl;
+
+/// \brief Implementation class used to describe either a set of overloaded
+/// template names or an already-substituted template template parameter pack.
+class UncommonTemplateNameStorage {
+protected:
+ union {
+ struct {
+ /// \brief If true, this is an OverloadedTemplateStorage instance;
+ /// otherwise, it's a SubstTemplateTemplateParmPackStorage instance.
+ unsigned IsOverloadedStorage : 1;
+
+ /// \brief The number of stored templates or template arguments,
+ /// depending on which subclass we have.
+ unsigned Size : 31;
+ } Bits;
+
+ void *PointerAlignment;
+ };
+
+ UncommonTemplateNameStorage(unsigned Size, bool OverloadedStorage) {
+ Bits.IsOverloadedStorage = OverloadedStorage;
+ Bits.Size = Size;
+ }
+
+public:
+ unsigned size() const { return Bits.Size; }
+
+ OverloadedTemplateStorage *getAsOverloadedStorage() {
+ return Bits.IsOverloadedStorage
+ ? reinterpret_cast<OverloadedTemplateStorage *>(this)
+ : 0;
+ }
+
+ SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
+ return Bits.IsOverloadedStorage
+ ? 0
+ : reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this) ;
+ }
+};
+
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
+ friend class ASTContext;
+
+ OverloadedTemplateStorage(unsigned Size)
+ : UncommonTemplateNameStorage(Size, true) { }
+
+ NamedDecl **getStorage() {
+ return reinterpret_cast<NamedDecl **>(this + 1);
+ }
+ NamedDecl * const *getStorage() const {
+ return reinterpret_cast<NamedDecl *const *>(this + 1);
+ }
+
+public:
+ typedef NamedDecl *const *iterator;
+
+ iterator begin() const { return getStorage(); }
+ iterator end() const { return getStorage() + size(); }
+};
+
+
+/// \brief A structure for storing an already-substituted template template
+/// parameter pack.
+///
+/// This kind of template names occurs when the parameter pack has been
+/// provided with a template template argument pack in a context where its
+/// enclosing pack expansion could not be fully expanded.
+class SubstTemplateTemplateParmPackStorage
+ : public UncommonTemplateNameStorage, public llvm::FoldingSetNode
+{
+ ASTContext &Context;
+ TemplateTemplateParmDecl *Parameter;
+ const TemplateArgument *Arguments;
+
+public:
+ SubstTemplateTemplateParmPackStorage(ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ unsigned Size,
+ const TemplateArgument *Arguments)
+ : UncommonTemplateNameStorage(Size, false), Context(Context),
+ Parameter(Parameter), Arguments(Arguments) { }
+
+ /// \brief Retrieve the template template parameter pack being substituted.
+ TemplateTemplateParmDecl *getParameterPack() const {
+ return Parameter;
+ }
+
+ /// \brief Retrieve the template template argument pack with which this
+ /// parameter was substituted.
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ const TemplateArgument &ArgPack);
+};
+
+/// \brief Represents a C++ template name within the type system.
+///
+/// A C++ template name refers to a template within the C++ type
+/// system. In most cases, a template name is simply a reference to a
+/// class template, e.g.
+///
+/// \code
+/// template<typename T> class X { };
+///
+/// X<int> xi;
+/// \endcode
+///
+/// Here, the 'X' in \c X<int> is a template name that refers to the
+/// declaration of the class template X, above. Template names can
+/// also refer to function templates, C++0x template aliases, etc.
+///
+/// Some template names are dependent. For example, consider:
+///
+/// \code
+/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
+/// typedef typename MetaFun::template apply<T1, T2>::type type;
+/// };
+/// \endcode
+///
+/// Here, "apply" is treated as a template name within the typename
+/// specifier in the typedef. "apply" is a nested template, and can
+/// only be understood in the context of
+class TemplateName {
+ typedef llvm::PointerUnion4<TemplateDecl *,
+ UncommonTemplateNameStorage *,
+ QualifiedTemplateName *,
+ DependentTemplateName *> StorageType;
+
+ StorageType Storage;
+
+ explicit TemplateName(void *Ptr) {
+ Storage = StorageType::getFromOpaqueValue(Ptr);
+ }
+
+public:
+ // \brief Kind of name that is actually stored.
+ enum NameKind {
+ /// \brief A single template declaration.
+ Template,
+ /// \brief A set of overloaded template declarations.
+ OverloadedTemplate,
+ /// \brief A qualified template name, where the qualification is kept
+ /// to describe the source code as written.
+ QualifiedTemplate,
+ /// \brief A dependent template name that has not been resolved to a
+ /// template (or set of templates).
+ DependentTemplate,
+ /// \brief A template template parameter pack that has been substituted for
+ /// a template template argument pack, but has not yet been expanded into
+ /// individual arguments.
+ SubstTemplateTemplateParmPack
+ };
+
+ TemplateName() : Storage() { }
+ explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
+ explicit TemplateName(OverloadedTemplateStorage *Storage)
+ : Storage(Storage) { }
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
+ : Storage(Storage) { }
+ explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
+ explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
+
+ /// \brief Determine whether this template name is NULL.
+ bool isNull() const { return Storage.isNull(); }
+
+ // \brief Get the kind of name that is actually stored.
+ NameKind getKind() const;
+
+ /// \brief Retrieve the underlying template declaration that
+ /// this template name refers to, if known.
+ ///
+ /// \returns The template declaration that this template name refers
+ /// to, if any. If the template name does not refer to a specific
+ /// declaration because it is a dependent name, or if it refers to a
+ /// set of function templates, returns NULL.
+ TemplateDecl *getAsTemplateDecl() const;
+
+ /// \brief Retrieve the underlying, overloaded function template
+ // declarations that this template name refers to, if known.
+ ///
+ /// \returns The set of overloaded function templates that this template
+ /// name refers to, if known. If the template name does not refer to a
+ /// specific set of function templates because it is a dependent name or
+ /// refers to a single template, returns NULL.
+ OverloadedTemplateStorage *getAsOverloadedTemplate() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsOverloadedStorage();
+
+ return 0;
+ }
+
+ /// \brief Retrieve the substituted template template parameter pack, if
+ /// known.
+ ///
+ /// \returns The storage for the substituted template template parameter pack,
+ /// if known. Otherwise, returns NULL.
+ SubstTemplateTemplateParmPackStorage *
+ getAsSubstTemplateTemplateParmPack() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsSubstTemplateTemplateParmPack();
+
+ return 0;
+ }
+
+ /// \brief Retrieve the underlying qualified template name
+ /// structure, if any.
+ QualifiedTemplateName *getAsQualifiedTemplateName() const {
+ return Storage.dyn_cast<QualifiedTemplateName *>();
+ }
+
+ /// \brief Retrieve the underlying dependent template name
+ /// structure, if any.
+ DependentTemplateName *getAsDependentTemplateName() const {
+ return Storage.dyn_cast<DependentTemplateName *>();
+ }
+
+ /// \brief Determines whether this is a dependent template name.
+ bool isDependent() const;
+
+ /// \brief Determines whether this template name contains an
+ /// unexpanded parameter pack (for C++0x variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Print the template name.
+ ///
+ /// \param OS the output stream to which the template name will be
+ /// printed.
+ ///
+ /// \param SuppressNNS if true, don't print the
+ /// nested-name-specifier that precedes the template name (if it has
+ /// one).
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
+ bool SuppressNNS = false) const;
+
+ /// \brief Debugging aid that dumps the template name to standard
+ /// error.
+ void dump() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddPointer(Storage.getOpaqueValue());
+ }
+
+ /// \brief Retrieve the template name as a void pointer.
+ void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
+
+ /// \brief Build a template name from a void pointer.
+ static TemplateName getFromVoidPointer(void *Ptr) {
+ return TemplateName(Ptr);
+ }
+};
+
+/// Insertion operator for diagnostics. This allows sending TemplateName's
+/// into a diagnostic with <<.
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ TemplateName N);
+
+/// \brief Represents a template name that was expressed as a
+/// qualified name.
+///
+/// This kind of template name refers to a template name that was
+/// preceded by a nested name specifier, e.g., \c std::vector. Here,
+/// the nested name specifier is "std::" and the template name is the
+/// declaration for "vector". The QualifiedTemplateName class is only
+/// used to provide "sugar" for template names that were expressed
+/// with a qualified name, and has no semantic meaning. In this
+/// manner, it is to TemplateName what ElaboratedType is to Type,
+/// providing extra syntactic sugar for downstream clients.
+class QualifiedTemplateName : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that qualifies the template name.
+ ///
+ /// The bit is used to indicate whether the "template" keyword was
+ /// present before the template name itself. Note that the
+ /// "template" keyword is always redundant in this case (otherwise,
+ /// the template name would be a dependent name and we would express
+ /// this name with DependentTemplateName).
+ llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
+
+ /// \brief The template declaration or set of overloaded function templates
+ /// that this qualified name refers to.
+ TemplateDecl *Template;
+
+ friend class ASTContext;
+
+ QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
+ TemplateDecl *Template)
+ : Qualifier(NNS, TemplateKeyword? 1 : 0),
+ Template(Template) { }
+
+public:
+ /// \brief Return the nested name specifier that qualifies this name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
+
+ /// \brief Whether the template name was prefixed by the "template"
+ /// keyword.
+ bool hasTemplateKeyword() const { return Qualifier.getInt(); }
+
+ /// \brief The template declaration that this qualified name refers
+ /// to.
+ TemplateDecl *getDecl() const { return Template; }
+
+ /// \brief The template declaration to which this qualified name
+ /// refers.
+ TemplateDecl *getTemplateDecl() const { return Template; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ bool TemplateKeyword, TemplateDecl *Template) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(TemplateKeyword);
+ ID.AddPointer(Template);
+ }
+};
+
+/// \brief Represents a dependent template name that cannot be
+/// resolved prior to template instantiation.
+///
+/// This kind of template name refers to a dependent template name,
+/// including its nested name specifier (if any). For example,
+/// DependentTemplateName can refer to "MetaFun::template apply",
+/// where "MetaFun::" is the nested name specifier and "apply" is the
+/// template name referenced. The "template" keyword is implied.
+class DependentTemplateName : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that qualifies the template
+ /// name.
+ ///
+ /// The bit stored in this qualifier describes whether the \c Name field
+ /// is interpreted as an IdentifierInfo pointer (when clear) or as an
+ /// overloaded operator kind (when set).
+ llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
+
+ /// \brief The dependent template name.
+ union {
+ /// \brief The identifier template name.
+ ///
+ /// Only valid when the bit on \c Qualifier is clear.
+ const IdentifierInfo *Identifier;
+
+ /// \brief The overloaded operator name.
+ ///
+ /// Only valid when the bit on \c Qualifier is set.
+ OverloadedOperatorKind Operator;
+ };
+
+ /// \brief The canonical template name to which this dependent
+ /// template name refers.
+ ///
+ /// The canonical template name for a dependent template name is
+ /// another dependent template name whose nested name specifier is
+ /// canonical.
+ TemplateName CanonicalTemplateName;
+
+ friend class ASTContext;
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Identifier)
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(this) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Identifier,
+ TemplateName Canon)
+ : Qualifier(Qualifier, false), Identifier(Identifier),
+ CanonicalTemplateName(Canon) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(this) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ TemplateName Canon)
+ : Qualifier(Qualifier, true), Operator(Operator),
+ CanonicalTemplateName(Canon) { }
+
+public:
+ /// \brief Return the nested name specifier that qualifies this name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
+
+ /// \brief Determine whether this template name refers to an identifier.
+ bool isIdentifier() const { return !Qualifier.getInt(); }
+
+ /// \brief Returns the identifier to which this template name refers.
+ const IdentifierInfo *getIdentifier() const {
+ assert(isIdentifier() && "Template name isn't an identifier?");
+ return Identifier;
+ }
+
+ /// \brief Determine whether this template name refers to an overloaded
+ /// operator.
+ bool isOverloadedOperator() const { return Qualifier.getInt(); }
+
+ /// \brief Return the overloaded operator to which this template name refers.
+ OverloadedOperatorKind getOperator() const {
+ assert(isOverloadedOperator() &&
+ "Template name isn't an overloaded operator?");
+ return Operator;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ if (isIdentifier())
+ Profile(ID, getQualifier(), getIdentifier());
+ else
+ Profile(ID, getQualifier(), getOperator());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Identifier) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(false);
+ ID.AddPointer(Identifier);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(true);
+ ID.AddInteger(Operator);
+ }
+};
+
+} // end namespace clang.
+
+namespace llvm {
+
+/// \brief The clang::TemplateName class is effectively a pointer.
+template<>
+class PointerLikeTypeTraits<clang::TemplateName> {
+public:
+ static inline void *getAsVoidPointer(clang::TemplateName TN) {
+ return TN.getAsVoidPointer();
+ }
+
+ static inline clang::TemplateName getFromVoidPointer(void *Ptr) {
+ return clang::TemplateName::getFromVoidPointer(Ptr);
+ }
+
+ // No bits are available!
+ enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h
new file mode 100644
index 0000000..9b177cc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h
@@ -0,0 +1,4338 @@
+//===--- Type.h - C Language Family Type Representation ---------*- 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 Type interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPE_H
+#define LLVM_CLANG_AST_TYPE_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Visibility.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateName.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/type_traits.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+namespace clang {
+ enum {
+ TypeAlignmentInBits = 4,
+ TypeAlignment = 1 << TypeAlignmentInBits
+ };
+ class Type;
+ class ExtQuals;
+ class QualType;
+}
+
+namespace llvm {
+ template <typename T>
+ class PointerLikeTypeTraits;
+ template<>
+ class PointerLikeTypeTraits< ::clang::Type*> {
+ public:
+ static inline void *getAsVoidPointer(::clang::Type *P) { return P; }
+ static inline ::clang::Type *getFromVoidPointer(void *P) {
+ return static_cast< ::clang::Type*>(P);
+ }
+ enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
+ };
+ template<>
+ class PointerLikeTypeTraits< ::clang::ExtQuals*> {
+ public:
+ static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; }
+ static inline ::clang::ExtQuals *getFromVoidPointer(void *P) {
+ return static_cast< ::clang::ExtQuals*>(P);
+ }
+ enum { NumLowBitsAvailable = clang::TypeAlignmentInBits };
+ };
+
+ template <>
+ struct isPodLike<clang::QualType> { static const bool value = true; };
+}
+
+namespace clang {
+ class ASTContext;
+ class TypedefDecl;
+ class TemplateDecl;
+ class TemplateTypeParmDecl;
+ class NonTypeTemplateParmDecl;
+ class TemplateTemplateParmDecl;
+ class TagDecl;
+ class RecordDecl;
+ class CXXRecordDecl;
+ class EnumDecl;
+ class FieldDecl;
+ class ObjCInterfaceDecl;
+ class ObjCProtocolDecl;
+ class ObjCMethodDecl;
+ class UnresolvedUsingTypenameDecl;
+ class Expr;
+ class Stmt;
+ class SourceLocation;
+ class StmtIteratorBase;
+ class TemplateArgument;
+ class TemplateArgumentLoc;
+ class TemplateArgumentListInfo;
+ class ElaboratedType;
+ class ExtQuals;
+ class ExtQualsTypeCommonBase;
+ struct PrintingPolicy;
+
+ template <typename> class CanQual;
+ typedef CanQual<Type> CanQualType;
+
+ // Provide forward declarations for all of the *Type classes
+#define TYPE(Class, Base) class Class##Type;
+#include "clang/AST/TypeNodes.def"
+
+/// Qualifiers - The collection of all-type qualifiers we support.
+/// Clang supports five independent qualifiers:
+/// * C99: const, volatile, and restrict
+/// * Embedded C (TR18037): address spaces
+/// * Objective C: the GC attributes (none, weak, or strong)
+class Qualifiers {
+public:
+ enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ Const = 0x1,
+ Restrict = 0x2,
+ Volatile = 0x4,
+ CVRMask = Const | Volatile | Restrict
+ };
+
+ enum GC {
+ GCNone = 0,
+ Weak,
+ Strong
+ };
+
+ enum {
+ /// The maximum supported address space number.
+ /// 24 bits should be enough for anyone.
+ MaxAddressSpace = 0xffffffu,
+
+ /// The width of the "fast" qualifier mask.
+ FastWidth = 3,
+
+ /// The fast qualifier mask.
+ FastMask = (1 << FastWidth) - 1
+ };
+
+ Qualifiers() : Mask(0) {}
+
+ static Qualifiers fromFastMask(unsigned Mask) {
+ Qualifiers Qs;
+ Qs.addFastQualifiers(Mask);
+ return Qs;
+ }
+
+ static Qualifiers fromCVRMask(unsigned CVR) {
+ Qualifiers Qs;
+ Qs.addCVRQualifiers(CVR);
+ return Qs;
+ }
+
+ // Deserialize qualifiers from an opaque representation.
+ static Qualifiers fromOpaqueValue(unsigned opaque) {
+ Qualifiers Qs;
+ Qs.Mask = opaque;
+ return Qs;
+ }
+
+ // Serialize these qualifiers into an opaque representation.
+ unsigned getAsOpaqueValue() const {
+ return Mask;
+ }
+
+ bool hasConst() const { return Mask & Const; }
+ void setConst(bool flag) {
+ Mask = (Mask & ~Const) | (flag ? Const : 0);
+ }
+ void removeConst() { Mask &= ~Const; }
+ void addConst() { Mask |= Const; }
+
+ bool hasVolatile() const { return Mask & Volatile; }
+ void setVolatile(bool flag) {
+ Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
+ }
+ void removeVolatile() { Mask &= ~Volatile; }
+ void addVolatile() { Mask |= Volatile; }
+
+ bool hasRestrict() const { return Mask & Restrict; }
+ void setRestrict(bool flag) {
+ Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
+ }
+ void removeRestrict() { Mask &= ~Restrict; }
+ void addRestrict() { Mask |= Restrict; }
+
+ bool hasCVRQualifiers() const { return getCVRQualifiers(); }
+ unsigned getCVRQualifiers() const { return Mask & CVRMask; }
+ void setCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask = (Mask & ~CVRMask) | mask;
+ }
+ void removeCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask &= ~mask;
+ }
+ void removeCVRQualifiers() {
+ removeCVRQualifiers(CVRMask);
+ }
+ void addCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask |= mask;
+ }
+
+ bool hasObjCGCAttr() const { return Mask & GCAttrMask; }
+ GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); }
+ void setObjCGCAttr(GC type) {
+ Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
+ }
+ void removeObjCGCAttr() { setObjCGCAttr(GCNone); }
+ void addObjCGCAttr(GC type) {
+ assert(type);
+ setObjCGCAttr(type);
+ }
+
+ bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
+ unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+ void setAddressSpace(unsigned space) {
+ assert(space <= MaxAddressSpace);
+ Mask = (Mask & ~AddressSpaceMask)
+ | (((uint32_t) space) << AddressSpaceShift);
+ }
+ void removeAddressSpace() { setAddressSpace(0); }
+ void addAddressSpace(unsigned space) {
+ assert(space);
+ setAddressSpace(space);
+ }
+
+ // Fast qualifiers are those that can be allocated directly
+ // on a QualType object.
+ bool hasFastQualifiers() const { return getFastQualifiers(); }
+ unsigned getFastQualifiers() const { return Mask & FastMask; }
+ void setFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask = (Mask & ~FastMask) | mask;
+ }
+ void removeFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask &= ~mask;
+ }
+ void removeFastQualifiers() {
+ removeFastQualifiers(FastMask);
+ }
+ void addFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask |= mask;
+ }
+
+ /// hasNonFastQualifiers - Return true if the set contains any
+ /// qualifiers which require an ExtQuals node to be allocated.
+ bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+ Qualifiers getNonFastQualifiers() const {
+ Qualifiers Quals = *this;
+ Quals.setFastQualifiers(0);
+ return Quals;
+ }
+
+ /// hasQualifiers - Return true if the set contains any qualifiers.
+ bool hasQualifiers() const { return Mask; }
+ bool empty() const { return !Mask; }
+
+ /// \brief Add the qualifiers from the given set to this set.
+ void addQualifiers(Qualifiers Q) {
+ // If the other set doesn't have any non-boolean qualifiers, just
+ // bit-or it in.
+ if (!(Q.Mask & ~CVRMask))
+ Mask |= Q.Mask;
+ else {
+ Mask |= (Q.Mask & CVRMask);
+ if (Q.hasAddressSpace())
+ addAddressSpace(Q.getAddressSpace());
+ if (Q.hasObjCGCAttr())
+ addObjCGCAttr(Q.getObjCGCAttr());
+ }
+ }
+
+ /// \brief Add the qualifiers from the given set to this set, given that
+ /// they don't conflict.
+ void addConsistentQualifiers(Qualifiers qs) {
+ assert(getAddressSpace() == qs.getAddressSpace() ||
+ !hasAddressSpace() || !qs.hasAddressSpace());
+ assert(getObjCGCAttr() == qs.getObjCGCAttr() ||
+ !hasObjCGCAttr() || !qs.hasObjCGCAttr());
+ Mask |= qs.Mask;
+ }
+
+ /// \brief Determines if these qualifiers compatibly include another set.
+ /// Generally this answers the question of whether an object with the other
+ /// qualifiers can be safely used as an object with these qualifiers.
+ bool compatiblyIncludes(Qualifiers other) const {
+ // Non-CVR qualifiers must match exactly. CVR qualifiers may subset.
+ return ((Mask & ~CVRMask) == (other.Mask & ~CVRMask)) &&
+ (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+ }
+
+ bool isSupersetOf(Qualifiers Other) const;
+
+ bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+ bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+
+ operator bool() const { return hasQualifiers(); }
+
+ Qualifiers &operator+=(Qualifiers R) {
+ addQualifiers(R);
+ return *this;
+ }
+
+ // Union two qualifier sets. If an enumerated qualifier appears
+ // in both sets, use the one from the right.
+ friend Qualifiers operator+(Qualifiers L, Qualifiers R) {
+ L += R;
+ return L;
+ }
+
+ Qualifiers &operator-=(Qualifiers R) {
+ Mask = Mask & ~(R.Mask);
+ return *this;
+ }
+
+ /// \brief Compute the difference between two qualifier sets.
+ friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
+ L -= R;
+ return L;
+ }
+
+ std::string getAsString() const;
+ std::string getAsString(const PrintingPolicy &Policy) const {
+ std::string Buffer;
+ getAsStringInternal(Buffer, Policy);
+ return Buffer;
+ }
+ void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Mask);
+ }
+
+private:
+
+ // bits: |0 1 2|3 .. 4|5 .. 31|
+ // |C R V|GCAttr|AddrSpace|
+ uint32_t Mask;
+
+ static const uint32_t GCAttrMask = 0x18;
+ static const uint32_t GCAttrShift = 3;
+ static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
+ static const uint32_t AddressSpaceShift = 5;
+};
+
+/// CallingConv - Specifies the calling convention that a function uses.
+enum CallingConv {
+ CC_Default,
+ CC_C, // __attribute__((cdecl))
+ CC_X86StdCall, // __attribute__((stdcall))
+ CC_X86FastCall, // __attribute__((fastcall))
+ CC_X86ThisCall, // __attribute__((thiscall))
+ CC_X86Pascal // __attribute__((pascal))
+};
+
+typedef std::pair<const Type*, Qualifiers> SplitQualType;
+
+/// QualType - For efficiency, we don't store CV-qualified types as nodes on
+/// their own: instead each reference to a type stores the qualifiers. This
+/// greatly reduces the number of nodes we need to allocate for types (for
+/// example we only need one for 'int', 'const int', 'volatile int',
+/// 'const volatile int', etc).
+///
+/// As an added efficiency bonus, instead of making this a pair, we
+/// just store the two bits we care about in the low bits of the
+/// pointer. To handle the packing/unpacking, we make QualType be a
+/// simple wrapper class that acts like a smart pointer. A third bit
+/// indicates whether there are extended qualifiers present, in which
+/// case the pointer points to a special structure.
+class QualType {
+ // Thankfully, these are efficiently composable.
+ llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
+ Qualifiers::FastWidth> Value;
+
+ const ExtQuals *getExtQualsUnsafe() const {
+ return Value.getPointer().get<const ExtQuals*>();
+ }
+
+ const Type *getTypePtrUnsafe() const {
+ return Value.getPointer().get<const Type*>();
+ }
+
+ const ExtQualsTypeCommonBase *getCommonPtr() const {
+ assert(!isNull() && "Cannot retrieve a NULL type pointer");
+ uintptr_t CommonPtrVal
+ = reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
+ CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
+ return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
+ }
+
+ friend class QualifierCollector;
+public:
+ QualType() {}
+
+ QualType(const Type *Ptr, unsigned Quals)
+ : Value(Ptr, Quals) {}
+ QualType(const ExtQuals *Ptr, unsigned Quals)
+ : Value(Ptr, Quals) {}
+
+ unsigned getLocalFastQualifiers() const { return Value.getInt(); }
+ void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
+
+ /// Retrieves a pointer to the underlying (unqualified) type.
+ /// This should really return a const Type, but it's not worth
+ /// changing all the users right now.
+ ///
+ /// This function requires that the type not be NULL. If the type might be
+ /// NULL, use the (slightly less efficient) \c getTypePtrOrNull().
+ const Type *getTypePtr() const;
+
+ const Type *getTypePtrOrNull() const;
+
+ /// Divides a QualType into its unqualified type and a set of local
+ /// qualifiers.
+ SplitQualType split() const;
+
+ void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
+ static QualType getFromOpaquePtr(const void *Ptr) {
+ QualType T;
+ T.Value.setFromOpaqueValue(const_cast<void*>(Ptr));
+ return T;
+ }
+
+ const Type &operator*() const {
+ return *getTypePtr();
+ }
+
+ const Type *operator->() const {
+ return getTypePtr();
+ }
+
+ bool isCanonical() const;
+ bool isCanonicalAsParam() const;
+
+ /// isNull - Return true if this QualType doesn't point to a type yet.
+ bool isNull() const {
+ return Value.getPointer().isNull();
+ }
+
+ /// \brief Determine whether this particular QualType instance has the
+ /// "const" qualifier set, without looking through typedefs that may have
+ /// added "const" at a different level.
+ bool isLocalConstQualified() const {
+ return (getLocalFastQualifiers() & Qualifiers::Const);
+ }
+
+ /// \brief Determine whether this type is const-qualified.
+ bool isConstQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has the
+ /// "restrict" qualifier set, without looking through typedefs that may have
+ /// added "restrict" at a different level.
+ bool isLocalRestrictQualified() const {
+ return (getLocalFastQualifiers() & Qualifiers::Restrict);
+ }
+
+ /// \brief Determine whether this type is restrict-qualified.
+ bool isRestrictQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has the
+ /// "volatile" qualifier set, without looking through typedefs that may have
+ /// added "volatile" at a different level.
+ bool isLocalVolatileQualified() const {
+ return (getLocalFastQualifiers() & Qualifiers::Volatile);
+ }
+
+ /// \brief Determine whether this type is volatile-qualified.
+ bool isVolatileQualified() const;
+
+ /// \brief Determine whether this particular QualType instance has any
+ /// qualifiers, without looking through any typedefs that might add
+ /// qualifiers at a different level.
+ bool hasLocalQualifiers() const {
+ return getLocalFastQualifiers() || hasLocalNonFastQualifiers();
+ }
+
+ /// \brief Determine whether this type has any qualifiers.
+ bool hasQualifiers() const;
+
+ /// \brief Determine whether this particular QualType instance has any
+ /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType
+ /// instance.
+ bool hasLocalNonFastQualifiers() const {
+ return Value.getPointer().is<const ExtQuals*>();
+ }
+
+ /// \brief Retrieve the set of qualifiers local to this particular QualType
+ /// instance, not including any qualifiers acquired through typedefs or
+ /// other sugar.
+ Qualifiers getLocalQualifiers() const;
+
+ /// \brief Retrieve the set of qualifiers applied to this type.
+ Qualifiers getQualifiers() const;
+
+ /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// local to this particular QualType instance, not including any qualifiers
+ /// acquired through typedefs or other sugar.
+ unsigned getLocalCVRQualifiers() const {
+ return getLocalFastQualifiers();
+ }
+
+ /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
+ /// applied to this type.
+ unsigned getCVRQualifiers() const;
+
+ bool isConstant(ASTContext& Ctx) const {
+ return QualType::isConstant(*this, Ctx);
+ }
+
+ // Don't promise in the API that anything besides 'const' can be
+ // easily added.
+
+ /// addConst - add the specified type qualifier to this QualType.
+ void addConst() {
+ addFastQualifiers(Qualifiers::Const);
+ }
+ QualType withConst() const {
+ return withFastQualifiers(Qualifiers::Const);
+ }
+
+ void addFastQualifiers(unsigned TQs) {
+ assert(!(TQs & ~Qualifiers::FastMask)
+ && "non-fast qualifier bits set in mask!");
+ Value.setInt(Value.getInt() | TQs);
+ }
+
+ void removeLocalConst();
+ void removeLocalVolatile();
+ void removeLocalRestrict();
+ void removeLocalCVRQualifiers(unsigned Mask);
+
+ void removeLocalFastQualifiers() { Value.setInt(0); }
+ void removeLocalFastQualifiers(unsigned Mask) {
+ assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
+ Value.setInt(Value.getInt() & ~Mask);
+ }
+
+ // Creates a type with the given qualifiers in addition to any
+ // qualifiers already on this type.
+ QualType withFastQualifiers(unsigned TQs) const {
+ QualType T = *this;
+ T.addFastQualifiers(TQs);
+ return T;
+ }
+
+ // Creates a type with exactly the given fast qualifiers, removing
+ // any existing fast qualifiers.
+ QualType withExactLocalFastQualifiers(unsigned TQs) const {
+ return withoutLocalFastQualifiers().withFastQualifiers(TQs);
+ }
+
+ // Removes fast qualifiers, but leaves any extended qualifiers in place.
+ QualType withoutLocalFastQualifiers() const {
+ QualType T = *this;
+ T.removeLocalFastQualifiers();
+ return T;
+ }
+
+ QualType getCanonicalType() const;
+
+ /// \brief Return this type with all of the instance-specific qualifiers
+ /// removed, but without removing any qualifiers that may have been applied
+ /// through typedefs.
+ QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); }
+
+ /// \brief Retrieve the unqualified variant of the given type,
+ /// removing as little sugar as possible.
+ ///
+ /// This routine looks through various kinds of sugar to find the
+ /// least-desugared type that is unqualified. For example, given:
+ ///
+ /// \code
+ /// typedef int Integer;
+ /// typedef const Integer CInteger;
+ /// typedef CInteger DifferenceType;
+ /// \endcode
+ ///
+ /// Executing \c getUnqualifiedType() on the type \c DifferenceType will
+ /// desugar until we hit the type \c Integer, which has no qualifiers on it.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline QualType getUnqualifiedType() const;
+
+ /// getSplitUnqualifiedType - Retrieve the unqualified variant of the
+ /// given type, removing as little sugar as possible.
+ ///
+ /// Like getUnqualifiedType(), but also returns the set of
+ /// qualifiers that were built up.
+ ///
+ /// The resulting type might still be qualified if it's an array
+ /// type. To strip qualifiers even from within an array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline SplitQualType getSplitUnqualifiedType() const;
+
+ bool isMoreQualifiedThan(QualType Other) const;
+ bool isAtLeastAsQualifiedAs(QualType Other) const;
+ QualType getNonReferenceType() const;
+
+ /// \brief Determine the type of a (typically non-lvalue) expression with the
+ /// specified result type.
+ ///
+ /// This routine should be used for expressions for which the return type is
+ /// explicitly specified (e.g., in a cast or call) and isn't necessarily
+ /// an lvalue. It removes a top-level reference (since there are no
+ /// expressions of reference type) and deletes top-level cvr-qualifiers
+ /// from non-class types (in C++) or all types (in C).
+ QualType getNonLValueExprType(ASTContext &Context) const;
+
+ /// getDesugaredType - Return the specified type with any "sugar" removed from
+ /// the type. This takes off typedefs, typeof's etc. If the outer level of
+ /// the type is already concrete, it returns it unmodified. This is similar
+ /// to getting the canonical type, but it doesn't remove *all* typedefs. For
+ /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
+ /// concrete.
+ ///
+ /// Qualifiers are left in place.
+ QualType getDesugaredType(const ASTContext &Context) const {
+ return getDesugaredType(*this, Context);
+ }
+
+ SplitQualType getSplitDesugaredType() const {
+ return getSplitDesugaredType(*this);
+ }
+
+ /// IgnoreParens - Returns the specified type after dropping any
+ /// outer-level parentheses.
+ QualType IgnoreParens() const {
+ if (isa<ParenType>(*this))
+ return QualType::IgnoreParens(*this);
+ return *this;
+ }
+
+ /// operator==/!= - Indicate whether the specified types and qualifiers are
+ /// identical.
+ friend bool operator==(const QualType &LHS, const QualType &RHS) {
+ return LHS.Value == RHS.Value;
+ }
+ friend bool operator!=(const QualType &LHS, const QualType &RHS) {
+ return LHS.Value != RHS.Value;
+ }
+ std::string getAsString() const {
+ return getAsString(split());
+ }
+ static std::string getAsString(SplitQualType split) {
+ return getAsString(split.first, split.second);
+ }
+ static std::string getAsString(const Type *ty, Qualifiers qs);
+
+ std::string getAsString(const PrintingPolicy &Policy) const {
+ std::string S;
+ getAsStringInternal(S, Policy);
+ return S;
+ }
+ void getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const {
+ return getAsStringInternal(split(), Str, Policy);
+ }
+ static void getAsStringInternal(SplitQualType split, std::string &out,
+ const PrintingPolicy &policy) {
+ return getAsStringInternal(split.first, split.second, out, policy);
+ }
+ static void getAsStringInternal(const Type *ty, Qualifiers qs,
+ std::string &out,
+ const PrintingPolicy &policy);
+
+ void dump(const char *s) const;
+ void dump() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(getAsOpaquePtr());
+ }
+
+ /// getAddressSpace - Return the address space of this type.
+ inline unsigned getAddressSpace() const;
+
+ /// GCAttrTypesAttr - Returns gc attribute of this type.
+ inline Qualifiers::GC getObjCGCAttr() const;
+
+ /// isObjCGCWeak true when Type is objc's weak.
+ bool isObjCGCWeak() const {
+ return getObjCGCAttr() == Qualifiers::Weak;
+ }
+
+ /// isObjCGCStrong true when Type is objc's strong.
+ bool isObjCGCStrong() const {
+ return getObjCGCAttr() == Qualifiers::Strong;
+ }
+
+ enum DestructionKind {
+ DK_none,
+ DK_cxx_destructor
+ };
+
+ /// isDestructedType - nonzero if objects of this type require
+ /// non-trivial work to clean up after. Non-zero because it's
+ /// conceivable that qualifiers (objc_gc(weak)?) could make
+ /// something require destruction.
+ DestructionKind isDestructedType() const {
+ return isDestructedTypeImpl(*this);
+ }
+
+private:
+ // These methods are implemented in a separate translation unit;
+ // "static"-ize them to avoid creating temporary QualTypes in the
+ // caller.
+ static bool isConstant(QualType T, ASTContext& Ctx);
+ static QualType getDesugaredType(QualType T, const ASTContext &Context);
+ static SplitQualType getSplitDesugaredType(QualType T);
+ static SplitQualType getSplitUnqualifiedTypeImpl(QualType type);
+ static QualType IgnoreParens(QualType T);
+ static DestructionKind isDestructedTypeImpl(QualType type);
+};
+
+} // end clang.
+
+namespace llvm {
+/// Implement simplify_type for QualType, so that we can dyn_cast from QualType
+/// to a specific Type class.
+template<> struct simplify_type<const ::clang::QualType> {
+ typedef const ::clang::Type *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::QualType &Val) {
+ return Val.getTypePtr();
+ }
+};
+template<> struct simplify_type< ::clang::QualType>
+ : public simplify_type<const ::clang::QualType> {};
+
+// Teach SmallPtrSet that QualType is "basically a pointer".
+template<>
+class PointerLikeTypeTraits<clang::QualType> {
+public:
+ static inline void *getAsVoidPointer(clang::QualType P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::QualType getFromVoidPointer(void *P) {
+ return clang::QualType::getFromOpaquePtr(P);
+ }
+ // Various qualifiers go in low bits.
+ enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm
+
+namespace clang {
+
+/// \brief Base class that is common to both the \c ExtQuals and \c Type
+/// classes, which allows \c QualType to access the common fields between the
+/// two.
+///
+class ExtQualsTypeCommonBase {
+ ExtQualsTypeCommonBase(const Type *baseType, QualType canon)
+ : BaseType(baseType), CanonicalType(canon) {}
+
+ /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
+ /// a self-referential pointer (for \c Type).
+ ///
+ /// This pointer allows an efficient mapping from a QualType to its
+ /// underlying type pointer.
+ const Type *const BaseType;
+
+ /// \brief The canonical type of this type. A QualType.
+ QualType CanonicalType;
+
+ friend class QualType;
+ friend class Type;
+ friend class ExtQuals;
+};
+
+/// ExtQuals - We can encode up to four bits in the low bits of a
+/// type pointer, but there are many more type qualifiers that we want
+/// to be able to apply to an arbitrary type. Therefore we have this
+/// struct, intended to be heap-allocated and used by QualType to
+/// store qualifiers.
+///
+/// The current design tags the 'const', 'restrict', and 'volatile' qualifiers
+/// in three low bits on the QualType pointer; a fourth bit records whether
+/// the pointer is an ExtQuals node. The extended qualifiers (address spaces,
+/// Objective-C GC attributes) are much more rare.
+class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
+ // NOTE: changing the fast qualifiers should be straightforward as
+ // long as you don't make 'const' non-fast.
+ // 1. Qualifiers:
+ // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
+ // Fast qualifiers must occupy the low-order bits.
+ // b) Update Qualifiers::FastWidth and FastMask.
+ // 2. QualType:
+ // a) Update is{Volatile,Restrict}Qualified(), defined inline.
+ // b) Update remove{Volatile,Restrict}, defined near the end of
+ // this header.
+ // 3. ASTContext:
+ // a) Update get{Volatile,Restrict}Type.
+
+ /// Quals - the immutable set of qualifiers applied by this
+ /// node; always contains extended qualifiers.
+ Qualifiers Quals;
+
+ ExtQuals *this_() { return this; }
+
+public:
+ ExtQuals(const Type *baseType, QualType canon, Qualifiers quals)
+ : ExtQualsTypeCommonBase(baseType,
+ canon.isNull() ? QualType(this_(), 0) : canon),
+ Quals(quals)
+ {
+ assert(Quals.hasNonFastQualifiers()
+ && "ExtQuals created with no fast qualifiers");
+ assert(!Quals.hasFastQualifiers()
+ && "ExtQuals created with fast qualifiers");
+ }
+
+ Qualifiers getQualifiers() const { return Quals; }
+
+ bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
+ Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
+
+ bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+ const Type *getBaseType() const { return BaseType; }
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, getBaseType(), Quals);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const Type *BaseType,
+ Qualifiers Quals) {
+ assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
+ ID.AddPointer(BaseType);
+ Quals.Profile(ID);
+ }
+};
+
+/// \brief The kind of C++0x ref-qualifier associated with a function type,
+/// which determines whether a member function's "this" object can be an
+/// lvalue, rvalue, or neither.
+enum RefQualifierKind {
+ /// \brief No ref-qualifier was provided.
+ RQ_None = 0,
+ /// \brief An lvalue ref-qualifier was provided (\c &).
+ RQ_LValue,
+ /// \brief An rvalue ref-qualifier was provided (\c &&).
+ RQ_RValue
+};
+
+/// Type - This is the base class of the type hierarchy. A central concept
+/// with types is that each type always has a canonical type. A canonical type
+/// is the type with any typedef names stripped out of it or the types it
+/// references. For example, consider:
+///
+/// typedef int foo;
+/// typedef foo* bar;
+/// 'int *' 'foo *' 'bar'
+///
+/// There will be a Type object created for 'int'. Since int is canonical, its
+/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a
+/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next
+/// there is a PointerType that represents 'int*', which, like 'int', is
+/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical
+/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type
+/// is also 'int*'.
+///
+/// Non-canonical types are useful for emitting diagnostics, without losing
+/// information about typedefs being used. Canonical types are useful for type
+/// comparisons (they allow by-pointer equality tests) and useful for reasoning
+/// about whether something has a particular form (e.g. is a function type),
+/// because they implicitly, recursively, strip all typedefs out of a type.
+///
+/// Types, once created, are immutable.
+///
+class Type : public ExtQualsTypeCommonBase {
+public:
+ enum TypeClass {
+#define TYPE(Class, Base) Class,
+#define LAST_TYPE(Class) TypeLast = Class,
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ TagFirst = Record, TagLast = Enum
+ };
+
+private:
+ Type(const Type&); // DO NOT IMPLEMENT.
+ void operator=(const Type&); // DO NOT IMPLEMENT.
+
+ /// Bitfields required by the Type class.
+ class TypeBitfields {
+ friend class Type;
+ template <class T> friend class TypePropertyCache;
+
+ /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
+ unsigned TC : 8;
+
+ /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ /// Note that this should stay at the end of the ivars for Type so that
+ /// subclasses can pack their bitfields into the same word.
+ unsigned Dependent : 1;
+
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ unsigned VariablyModified : 1;
+
+ /// \brief Whether this type contains an unexpanded parameter pack
+ /// (for C++0x variadic templates).
+ unsigned ContainsUnexpandedParameterPack : 1;
+
+ /// \brief Nonzero if the cache (i.e. the bitfields here starting
+ /// with 'Cache') is valid. If so, then this is a
+ /// LangOptions::VisibilityMode+1.
+ mutable unsigned CacheValidAndVisibility : 2;
+
+ /// \brief Linkage of this type.
+ mutable unsigned CachedLinkage : 2;
+
+ /// \brief Whether this type involves and local or unnamed types.
+ mutable unsigned CachedLocalOrUnnamed : 1;
+
+ /// \brief FromAST - Whether this type comes from an AST file.
+ mutable unsigned FromAST : 1;
+
+ bool isCacheValid() const {
+ return (CacheValidAndVisibility != 0);
+ }
+ Visibility getVisibility() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Visibility>(CacheValidAndVisibility-1);
+ }
+ Linkage getLinkage() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return static_cast<Linkage>(CachedLinkage);
+ }
+ bool hasLocalOrUnnamedType() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return CachedLocalOrUnnamed;
+ }
+ };
+ enum { NumTypeBits = 17 };
+
+protected:
+ // These classes allow subclasses to somewhat cleanly pack bitfields
+ // into Type.
+
+ class ArrayTypeBitfields {
+ friend class ArrayType;
+
+ unsigned : NumTypeBits;
+
+ /// IndexTypeQuals - CVR qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ unsigned IndexTypeQuals : 3;
+
+ /// SizeModifier - storage class qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ /// Actually an ArrayType::ArraySizeModifier.
+ unsigned SizeModifier : 3;
+ };
+
+ class BuiltinTypeBitfields {
+ friend class BuiltinType;
+
+ unsigned : NumTypeBits;
+
+ /// The kind (BuiltinType::Kind) of builtin type this is.
+ unsigned Kind : 8;
+ };
+
+ class FunctionTypeBitfields {
+ friend class FunctionType;
+
+ unsigned : NumTypeBits;
+
+ /// Extra information which affects how the function is called, like
+ /// regparm and the calling convention.
+ unsigned ExtInfo : 8;
+
+ /// Whether the function is variadic. Only used by FunctionProtoType.
+ unsigned Variadic : 1;
+
+ /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// other bitfields.
+ /// The qualifiers are part of FunctionProtoType because...
+ ///
+ /// C++ 8.3.5p4: The return type, the parameter type list and the
+ /// cv-qualifier-seq, [...], are part of the function type.
+ unsigned TypeQuals : 3;
+
+ /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+ ///
+ /// This is a value of type \c RefQualifierKind.
+ unsigned RefQualifier : 2;
+ };
+
+ class ObjCObjectTypeBitfields {
+ friend class ObjCObjectType;
+
+ unsigned : NumTypeBits;
+
+ /// NumProtocols - The number of protocols stored directly on this
+ /// object type.
+ unsigned NumProtocols : 32 - NumTypeBits;
+ };
+
+ class ReferenceTypeBitfields {
+ friend class ReferenceType;
+
+ unsigned : NumTypeBits;
+
+ /// True if the type was originally spelled with an lvalue sigil.
+ /// This is never true of rvalue references but can also be false
+ /// on lvalue references because of C++0x [dcl.typedef]p9,
+ /// as follows:
+ ///
+ /// typedef int &ref; // lvalue, spelled lvalue
+ /// typedef int &&rvref; // rvalue
+ /// ref &a; // lvalue, inner ref, spelled lvalue
+ /// ref &&a; // lvalue, inner ref
+ /// rvref &a; // lvalue, inner ref, spelled lvalue
+ /// rvref &&a; // rvalue, inner ref
+ unsigned SpelledAsLValue : 1;
+
+ /// True if the inner type is a reference type. This only happens
+ /// in non-canonical forms.
+ unsigned InnerRef : 1;
+ };
+
+ class TypeWithKeywordBitfields {
+ friend class TypeWithKeyword;
+
+ unsigned : NumTypeBits;
+
+ /// An ElaboratedTypeKeyword. 8 bits for efficient access.
+ unsigned Keyword : 8;
+ };
+
+ class VectorTypeBitfields {
+ friend class VectorType;
+
+ unsigned : NumTypeBits;
+
+ /// VecKind - The kind of vector, either a generic vector type or some
+ /// target-specific vector type such as for AltiVec or Neon.
+ unsigned VecKind : 3;
+
+ /// NumElements - The number of elements in the vector.
+ unsigned NumElements : 29 - NumTypeBits;
+ };
+
+ class AttributedTypeBitfields {
+ friend class AttributedType;
+
+ unsigned : NumTypeBits;
+
+ /// AttrKind - an AttributedType::Kind
+ unsigned AttrKind : 32 - NumTypeBits;
+ };
+
+ union {
+ TypeBitfields TypeBits;
+ ArrayTypeBitfields ArrayTypeBits;
+ AttributedTypeBitfields AttributedTypeBits;
+ BuiltinTypeBitfields BuiltinTypeBits;
+ FunctionTypeBitfields FunctionTypeBits;
+ ObjCObjectTypeBitfields ObjCObjectTypeBits;
+ ReferenceTypeBitfields ReferenceTypeBits;
+ TypeWithKeywordBitfields TypeWithKeywordBits;
+ VectorTypeBitfields VectorTypeBits;
+ };
+
+private:
+ /// \brief Set whether this type comes from an AST file.
+ void setFromAST(bool V = true) const {
+ TypeBits.FromAST = V;
+ }
+
+ template <class T> friend class TypePropertyCache;
+
+protected:
+ // silence VC++ warning C4355: 'this' : used in base member initializer list
+ Type *this_() { return this; }
+ Type(TypeClass tc, QualType canon, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : ExtQualsTypeCommonBase(this,
+ canon.isNull() ? QualType(this_(), 0) : canon) {
+ TypeBits.TC = tc;
+ TypeBits.Dependent = Dependent;
+ TypeBits.VariablyModified = VariablyModified;
+ TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ TypeBits.CacheValidAndVisibility = 0;
+ TypeBits.CachedLocalOrUnnamed = false;
+ TypeBits.CachedLinkage = NoLinkage;
+ TypeBits.FromAST = false;
+ }
+ friend class ASTContext;
+
+ void setDependent(bool D = true) { TypeBits.Dependent = D; }
+ void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; }
+ void setContainsUnexpandedParameterPack(bool PP = true) {
+ TypeBits.ContainsUnexpandedParameterPack = PP;
+ }
+
+public:
+ TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
+
+ /// \brief Whether this type comes from an AST file.
+ bool isFromAST() const { return TypeBits.FromAST; }
+
+ /// \brief Whether this type is or contains an unexpanded parameter
+ /// pack, used to support C++0x variadic templates.
+ ///
+ /// A type that contains a parameter pack shall be expanded by the
+ /// ellipsis operator at some point. For example, the typedef in the
+ /// following example contains an unexpanded parameter pack 'T':
+ ///
+ /// \code
+ /// template<typename ...T>
+ /// struct X {
+ /// typedef T* pointer_types; // ill-formed; T is a parameter pack.
+ /// };
+ /// \endcode
+ ///
+ /// Note that this routine does not specify which
+ bool containsUnexpandedParameterPack() const {
+ return TypeBits.ContainsUnexpandedParameterPack;
+ }
+
+ /// Determines if this type would be canonical if it had no further
+ /// qualification.
+ bool isCanonicalUnqualified() const {
+ return CanonicalType == QualType(this, 0);
+ }
+
+ /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
+ /// object types, function types, and incomplete types.
+
+ /// isIncompleteType - Return true if this is an incomplete type.
+ /// A type that can describe objects, but which lacks information needed to
+ /// determine its size (e.g. void, or a fwd declared struct). Clients of this
+ /// routine will need to determine if the size is actually required.
+ bool isIncompleteType() const;
+
+ /// isIncompleteOrObjectType - Return true if this is an incomplete or object
+ /// type, in other words, not a function type.
+ bool isIncompleteOrObjectType() const {
+ return !isFunctionType();
+ }
+
+ /// \brief Determine whether this type is an object type.
+ bool isObjectType() const {
+ // C++ [basic.types]p8:
+ // An object type is a (possibly cv-qualified) type that is not a
+ // function type, not a reference type, and not a void type.
+ return !isReferenceType() && !isFunctionType() && !isVoidType();
+ }
+
+ /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
+ bool isPODType() const;
+
+ /// isLiteralType - Return true if this is a literal type
+ /// (C++0x [basic.types]p10)
+ bool isLiteralType() const;
+
+ /// Helper methods to distinguish type categories. All type predicates
+ /// operate on the canonical type, ignoring typedefs and qualifiers.
+
+ /// isBuiltinType - returns true if the type is a builtin type.
+ bool isBuiltinType() const;
+
+ /// isSpecificBuiltinType - Test for a particular builtin type.
+ bool isSpecificBuiltinType(unsigned K) const;
+
+ /// isPlaceholderType - Test for a type which does not represent an
+ /// actual type-system type but is instead used as a placeholder for
+ /// various convenient purposes within Clang. All such types are
+ /// BuiltinTypes.
+ bool isPlaceholderType() const;
+
+ /// isIntegerType() does *not* include complex integers (a GCC extension).
+ /// isComplexIntegerType() can be used to test for complex integers.
+ bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
+ bool isEnumeralType() const;
+ bool isBooleanType() const;
+ bool isCharType() const;
+ bool isWideCharType() const;
+ bool isAnyCharacterType() const;
+ bool isIntegralType(ASTContext &Ctx) const;
+
+ /// \brief Determine whether this type is an integral or enumeration type.
+ bool isIntegralOrEnumerationType() const;
+ /// \brief Determine whether this type is an integral or unscoped enumeration
+ /// type.
+ bool isIntegralOrUnscopedEnumerationType() const;
+
+ /// Floating point categories.
+ bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
+ /// isComplexType() does *not* include complex integers (a GCC extension).
+ /// isComplexIntegerType() can be used to test for complex integers.
+ bool isComplexType() const; // C99 6.2.5p11 (complex)
+ bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
+ bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
+ bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
+ bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
+ bool isVoidType() const; // C99 6.2.5p19
+ bool isDerivedType() const; // C99 6.2.5p20
+ bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
+ bool isAggregateType() const;
+
+ // Type Predicates: Check to see if this type is structurally the specified
+ // type, ignoring typedefs and qualifiers.
+ bool isFunctionType() const;
+ bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); }
+ bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
+ bool isPointerType() const;
+ bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
+ bool isBlockPointerType() const;
+ bool isVoidPointerType() const;
+ bool isReferenceType() const;
+ bool isLValueReferenceType() const;
+ bool isRValueReferenceType() const;
+ bool isFunctionPointerType() const;
+ bool isMemberPointerType() const;
+ bool isMemberFunctionPointerType() const;
+ bool isMemberDataPointerType() const;
+ bool isArrayType() const;
+ bool isConstantArrayType() const;
+ bool isIncompleteArrayType() const;
+ bool isVariableArrayType() const;
+ bool isDependentSizedArrayType() const;
+ bool isRecordType() const;
+ bool isClassType() const;
+ bool isStructureType() const;
+ bool isStructureOrClassType() const;
+ bool isUnionType() const;
+ bool isComplexIntegerType() const; // GCC _Complex integer type.
+ bool isVectorType() const; // GCC vector type.
+ bool isExtVectorType() const; // Extended vector type.
+ bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object.
+ // FIXME: change this to 'raw' interface type, so we can used 'interface' type
+ // for the common case.
+ bool isObjCObjectType() const; // NSString or typeof(*(id)0)
+ bool isObjCQualifiedInterfaceType() const; // NSString<foo>
+ bool isObjCQualifiedIdType() const; // id<foo>
+ bool isObjCQualifiedClassType() const; // Class<foo>
+ bool isObjCObjectOrInterfaceType() const;
+ bool isObjCIdType() const; // id
+ bool isObjCClassType() const; // Class
+ bool isObjCSelType() const; // Class
+ bool isObjCBuiltinType() const; // 'id' or 'Class'
+ bool isTemplateTypeParmType() const; // C++ template type parameter
+ bool isNullPtrType() const; // C++0x nullptr_t
+
+ enum ScalarTypeKind {
+ STK_Pointer,
+ STK_MemberPointer,
+ STK_Bool,
+ STK_Integral,
+ STK_Floating,
+ STK_IntegralComplex,
+ STK_FloatingComplex
+ };
+ /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ ScalarTypeKind getScalarTypeKind() const;
+
+ /// isDependentType - Whether this type is a dependent type, meaning
+ /// that its definition somehow depends on a template parameter
+ /// (C++ [temp.dep.type]).
+ bool isDependentType() const { return TypeBits.Dependent; }
+
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ bool isVariablyModifiedType() const { return TypeBits.VariablyModified; }
+
+ /// \brief Whether this type involves a variable-length array type
+ /// with a definite size.
+ bool hasSizedVLAType() const;
+
+ /// \brief Whether this type is or contains a local or unnamed type.
+ bool hasUnnamedOrLocalType() const;
+
+ bool isOverloadableType() const;
+
+ /// \brief Determine wither this type is a C++ elaborated-type-specifier.
+ bool isElaboratedTypeSpecifier() const;
+
+ /// hasPointerRepresentation - Whether this type is represented
+ /// natively as a pointer; this includes pointers, references, block
+ /// pointers, and Objective-C interface, qualified id, and qualified
+ /// interface types, as well as nullptr_t.
+ bool hasPointerRepresentation() const;
+
+ /// hasObjCPointerRepresentation - Whether this type can represent
+ /// an objective pointer type for the purpose of GC'ability
+ bool hasObjCPointerRepresentation() const;
+
+ /// \brief Determine whether this type has an integer representation
+ /// of some sort, e.g., it is an integer type or a vector.
+ bool hasIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an signed integer representation
+ /// of some sort, e.g., it is an signed integer type or a vector.
+ bool hasSignedIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an unsigned integer representation
+ /// of some sort, e.g., it is an unsigned integer type or a vector.
+ bool hasUnsignedIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has a floating-point representation
+ /// of some sort, e.g., it is a floating-point type or a vector thereof.
+ bool hasFloatingRepresentation() const;
+
+ // Type Checking Functions: Check to see if this type is structurally the
+ // specified type, ignoring typedefs and qualifiers, and return a pointer to
+ // the best type we can.
+ const RecordType *getAsStructureType() const;
+ /// NOTE: getAs*ArrayType are methods on ASTContext.
+ const RecordType *getAsUnionType() const;
+ const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
+ // The following is a convenience method that returns an ObjCObjectPointerType
+ // for object declared using an interface.
+ const ObjCObjectPointerType *getAsObjCInterfacePointerType() const;
+ const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
+ const ObjCObjectType *getAsObjCQualifiedInterfaceType() const;
+ const CXXRecordDecl *getCXXRecordDeclForPointerType() const;
+
+ /// \brief Retrieves the CXXRecordDecl that this type refers to, either
+ /// because the type is a RecordType or because it is the injected-class-name
+ /// type of a class template or class template partial specialization.
+ CXXRecordDecl *getAsCXXRecordDecl() const;
+
+ /// \brief Get the AutoType whose type will be deduced for a variable with
+ /// an initializer of this type. This looks through declarators like pointer
+ /// types, but not through decltype or typedefs.
+ AutoType *getContainedAutoType() const;
+
+ /// Member-template getAs<specific type>'. Look through sugar for
+ /// an instance of <specific type>. This scheme will eventually
+ /// replace the specific getAsXXXX methods above.
+ ///
+ /// There are some specializations of this member template listed
+ /// immediately following this class.
+ template <typename T> const T *getAs() const;
+
+ /// A variant of getAs<> for array types which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *getAsArrayTypeUnsafe() const;
+
+ /// Member-template castAs<specific type>. Look through sugar for
+ /// the underlying instance of <specific type>.
+ ///
+ /// This method has the same relationship to getAs<T> as cast<T> has
+ /// to dyn_cast<T>; which is to say, the underlying type *must*
+ /// have the intended type, and this method will never return null.
+ template <typename T> const T *castAs() const;
+
+ /// A variant of castAs<> for array type which silently discards
+ /// qualifiers from the outermost type.
+ const ArrayType *castAsArrayTypeUnsafe() const;
+
+ /// getBaseElementTypeUnsafe - Get the base element type of this
+ /// type, potentially discarding type qualifiers. This method
+ /// should never be used when type qualifiers are meaningful.
+ const Type *getBaseElementTypeUnsafe() const;
+
+ /// getArrayElementTypeNoTypeQual - If this is an array type, return the
+ /// element type of the array, potentially with type qualifiers missing.
+ /// This method should never be used when type qualifiers are meaningful.
+ const Type *getArrayElementTypeNoTypeQual() const;
+
+ /// getPointeeType - If this is a pointer, ObjC object pointer, or block
+ /// pointer, this returns the respective pointee.
+ QualType getPointeeType() const;
+
+ /// getUnqualifiedDesugaredType() - Return the specified type with
+ /// any "sugar" removed from the type, removing any typedefs,
+ /// typeofs, etc., as well as any qualifiers.
+ const Type *getUnqualifiedDesugaredType() const;
+
+ /// More type predicates useful for type checking/promotion
+ bool isPromotableIntegerType() const; // C99 6.3.1.1p2
+
+ /// isSignedIntegerType - Return true if this is an integer type that is
+ /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
+ /// an enum decl which has a signed representation, or a vector of signed
+ /// integer element type.
+ bool isSignedIntegerType() const;
+
+ /// isUnsignedIntegerType - Return true if this is an integer type that is
+ /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
+ /// decl which has an unsigned representation, or a vector of unsigned integer
+ /// element type.
+ bool isUnsignedIntegerType() const;
+
+ /// isConstantSizeType - Return true if this is not a variable sized type,
+ /// according to the rules of C99 6.7.5p3. It is not legal to call this on
+ /// incomplete types.
+ bool isConstantSizeType() const;
+
+ /// isSpecifierType - Returns true if this type can be represented by some
+ /// set of type specifiers.
+ bool isSpecifierType() const;
+
+ /// \brief Determine the linkage of this type.
+ Linkage getLinkage() const;
+
+ /// \brief Determine the visibility of this type.
+ Visibility getVisibility() const;
+
+ /// \brief Determine the linkage and visibility of this type.
+ std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
+
+ /// \brief Note that the linkage is no longer known.
+ void ClearLinkageCache();
+
+ const char *getTypeClassName() const;
+
+ QualType getCanonicalTypeInternal() const {
+ return CanonicalType;
+ }
+ CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
+ void dump() const;
+ static bool classof(const Type *) { return true; }
+
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+template <> inline const TypedefType *Type::getAs() const {
+ return dyn_cast<TypedefType>(this);
+}
+
+// We can do canonical leaf types faster, because we don't have to
+// worry about preserving child type decoration.
+#define TYPE(Class, Base)
+#define LEAF_TYPE(Class) \
+template <> inline const Class##Type *Type::getAs() const { \
+ return dyn_cast<Class##Type>(CanonicalType); \
+} \
+template <> inline const Class##Type *Type::castAs() const { \
+ return cast<Class##Type>(CanonicalType); \
+}
+#include "clang/AST/TypeNodes.def"
+
+
+/// BuiltinType - This class is used for builtin types like 'int'. Builtin
+/// types are always canonical and have a literal name field.
+class BuiltinType : public Type {
+public:
+ enum Kind {
+ Void,
+
+ Bool, // This is bool and/or _Bool.
+ Char_U, // This is 'char' for targets where char is unsigned.
+ UChar, // This is explicitly qualified unsigned char.
+ WChar_U, // This is 'wchar_t' for C++, when unsigned.
+ Char16, // This is 'char16_t' for C++.
+ Char32, // This is 'char32_t' for C++.
+ UShort,
+ UInt,
+ ULong,
+ ULongLong,
+ UInt128, // __uint128_t
+
+ Char_S, // This is 'char' for targets where char is signed.
+ SChar, // This is explicitly qualified signed char.
+ WChar_S, // This is 'wchar_t' for C++, when signed.
+ Short,
+ Int,
+ Long,
+ LongLong,
+ Int128, // __int128_t
+
+ Float, Double, LongDouble,
+
+ NullPtr, // This is the type of C++0x 'nullptr'.
+
+ /// This represents the type of an expression whose type is
+ /// totally unknown, e.g. 'T::foo'. It is permitted for this to
+ /// appear in situations where the structure of the type is
+ /// theoretically deducible.
+ Dependent,
+
+ Overload, // This represents the type of an overloaded function declaration.
+
+ /// The primitive Objective C 'id' type. The type pointed to by the
+ /// user-visible 'id' type. Only ever shows up in an AST as the base
+ /// type of an ObjCObjectType.
+ ObjCId,
+
+ /// The primitive Objective C 'Class' type. The type pointed to by the
+ /// user-visible 'Class' type. Only ever shows up in an AST as the
+ /// base type of an ObjCObjectType.
+ ObjCClass,
+
+ ObjCSel // This represents the ObjC 'SEL' type.
+ };
+
+public:
+ BuiltinType(Kind K)
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*VariablyModified=*/false,
+ /*Unexpanded paramter pack=*/false) {
+ BuiltinTypeBits.Kind = K;
+ }
+
+ Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
+ const char *getName(const LangOptions &LO) const;
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ bool isInteger() const {
+ return getKind() >= Bool && getKind() <= Int128;
+ }
+
+ bool isSignedInteger() const {
+ return getKind() >= Char_S && getKind() <= Int128;
+ }
+
+ bool isUnsignedInteger() const {
+ return getKind() >= Bool && getKind() <= UInt128;
+ }
+
+ bool isFloatingPoint() const {
+ return getKind() >= Float && getKind() <= LongDouble;
+ }
+
+ /// Determines whether this type is a "forbidden" placeholder type,
+ /// i.e. a type which cannot appear in arbitrary positions in a
+ /// fully-formed expression.
+ bool isPlaceholderType() const {
+ return getKind() == Overload;
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
+ static bool classof(const BuiltinType *) { return true; }
+};
+
+/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
+/// types (_Complex float etc) as well as the GCC integer complex extensions.
+///
+class ComplexType : public Type, public llvm::FoldingSetNode {
+ QualType ElementType;
+ ComplexType(QualType Element, QualType CanonicalPtr) :
+ Type(Complex, CanonicalPtr, Element->isDependentType(),
+ Element->isVariablyModifiedType(),
+ Element->containsUnexpandedParameterPack()),
+ ElementType(Element) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getElementType() const { return ElementType; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) {
+ ID.AddPointer(Element.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
+ static bool classof(const ComplexType *) { return true; }
+};
+
+/// ParenType - Sugar for parentheses used when specifying types.
+///
+class ParenType : public Type, public llvm::FoldingSetNode {
+ QualType Inner;
+
+ ParenType(QualType InnerType, QualType CanonType) :
+ Type(Paren, CanonType, InnerType->isDependentType(),
+ InnerType->isVariablyModifiedType(),
+ InnerType->containsUnexpandedParameterPack()),
+ Inner(InnerType) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getInnerType() const { return Inner; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getInnerType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getInnerType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) {
+ Inner.Profile(ID);
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Paren; }
+ static bool classof(const ParenType *) { return true; }
+};
+
+/// PointerType - C99 6.7.5.1 - Pointer Declarators.
+///
+class PointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+
+ PointerType(QualType Pointee, QualType CanonicalPtr) :
+ Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getPointeeType() const { return PointeeType; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
+ static bool classof(const PointerType *) { return true; }
+};
+
+/// BlockPointerType - pointer to a block type.
+/// This type is to represent types syntactically represented as
+/// "void (^)(int)", etc. Pointee is required to always be a function type.
+///
+class BlockPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType; // Block is some kind of pointer type
+ BlockPointerType(QualType Pointee, QualType CanonicalCls) :
+ Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ // Get the pointee type. Pointee is required to always be a function type.
+ QualType getPointeeType() const { return PointeeType; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == BlockPointer;
+ }
+ static bool classof(const BlockPointerType *) { return true; }
+};
+
+/// ReferenceType - Base for LValueReferenceType and RValueReferenceType
+///
+class ReferenceType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+
+protected:
+ ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
+ bool SpelledAsLValue) :
+ Type(tc, CanonicalRef, Referencee->isDependentType(),
+ Referencee->isVariablyModifiedType(),
+ Referencee->containsUnexpandedParameterPack()),
+ PointeeType(Referencee)
+ {
+ ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue;
+ ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
+ }
+
+public:
+ bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
+ bool isInnerRef() const { return ReferenceTypeBits.InnerRef; }
+
+ QualType getPointeeTypeAsWritten() const { return PointeeType; }
+ QualType getPointeeType() const {
+ // FIXME: this might strip inner qualifiers; okay?
+ const ReferenceType *T = this;
+ while (T->isInnerRef())
+ T = T->PointeeType->castAs<ReferenceType>();
+ return T->PointeeType;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, PointeeType, isSpelledAsLValue());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Referencee,
+ bool SpelledAsLValue) {
+ ID.AddPointer(Referencee.getAsOpaquePtr());
+ ID.AddBoolean(SpelledAsLValue);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference ||
+ T->getTypeClass() == RValueReference;
+ }
+ static bool classof(const ReferenceType *) { return true; }
+};
+
+/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
+///
+class LValueReferenceType : public ReferenceType {
+ LValueReferenceType(QualType Referencee, QualType CanonicalRef,
+ bool SpelledAsLValue) :
+ ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue)
+ {}
+ friend class ASTContext; // ASTContext creates these
+public:
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference;
+ }
+ static bool classof(const LValueReferenceType *) { return true; }
+};
+
+/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference
+///
+class RValueReferenceType : public ReferenceType {
+ RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
+ ReferenceType(RValueReference, Referencee, CanonicalRef, false) {
+ }
+ friend class ASTContext; // ASTContext creates these
+public:
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == RValueReference;
+ }
+ static bool classof(const RValueReferenceType *) { return true; }
+};
+
+/// MemberPointerType - C++ 8.3.3 - Pointers to members
+///
+class MemberPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+ /// The class of which the pointee is a member. Must ultimately be a
+ /// RecordType, but could be a typedef or a template parameter too.
+ const Type *Class;
+
+ MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
+ Type(MemberPointer, CanonicalPtr,
+ Cls->isDependentType() || Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType(),
+ (Cls->containsUnexpandedParameterPack() ||
+ Pointee->containsUnexpandedParameterPack())),
+ PointeeType(Pointee), Class(Cls) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getPointeeType() const { return PointeeType; }
+
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// function type rather than a data-member type.
+ bool isMemberFunctionPointer() const {
+ return PointeeType->isFunctionProtoType();
+ }
+
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// data type rather than a function type.
+ bool isMemberDataPointer() const {
+ return !PointeeType->isFunctionProtoType();
+ }
+
+ const Type *getClass() const { return Class; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType(), getClass());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
+ const Type *Class) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ ID.AddPointer(Class);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == MemberPointer;
+ }
+ static bool classof(const MemberPointerType *) { return true; }
+};
+
+/// ArrayType - C99 6.7.5.2 - Array Declarators.
+///
+class ArrayType : public Type, public llvm::FoldingSetNode {
+public:
+ /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4])
+ /// an array with a static size (e.g. int X[static 4]), or an array
+ /// with a star size (e.g. int X[*]).
+ /// 'static' is only allowed on function parameters.
+ enum ArraySizeModifier {
+ Normal, Static, Star
+ };
+private:
+ /// ElementType - The element type of the array.
+ QualType ElementType;
+
+protected:
+ // C++ [temp.dep.type]p1:
+ // A type is dependent if it is...
+ // - an array type constructed from any dependent type or whose
+ // size is specified by a constant expression that is
+ // value-dependent,
+ ArrayType(TypeClass tc, QualType et, QualType can,
+ ArraySizeModifier sm, unsigned tq,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType()),
+ ContainsUnexpandedParameterPack),
+ ElementType(et) {
+ ArrayTypeBits.IndexTypeQuals = tq;
+ ArrayTypeBits.SizeModifier = sm;
+ }
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getElementType() const { return ElementType; }
+ ArraySizeModifier getSizeModifier() const {
+ return ArraySizeModifier(ArrayTypeBits.SizeModifier);
+ }
+ Qualifiers getIndexTypeQualifiers() const {
+ return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers());
+ }
+ unsigned getIndexTypeCVRQualifiers() const {
+ return ArrayTypeBits.IndexTypeQuals;
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ConstantArray ||
+ T->getTypeClass() == VariableArray ||
+ T->getTypeClass() == IncompleteArray ||
+ T->getTypeClass() == DependentSizedArray;
+ }
+ static bool classof(const ArrayType *) { return true; }
+};
+
+/// ConstantArrayType - This class represents the canonical version of
+/// C arrays with a specified constant size. For example, the canonical
+/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element
+/// type is 'int' and the size is 404.
+class ConstantArrayType : public ArrayType {
+ llvm::APInt Size; // Allows us to unique the type.
+
+ ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(ConstantArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
+ Size(size) {}
+protected:
+ ConstantArrayType(TypeClass tc, QualType et, QualType can,
+ const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
+ : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
+ Size(size) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ const llvm::APInt &getSize() const { return Size; }
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+
+ /// \brief Determine the number of bits required to address a member of
+ // an array with the given element type and number of elements.
+ static unsigned getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements);
+
+ /// \brief Determine the maximum number of active bits that an array's size
+ /// can require, which limits the maximum size of the array.
+ static unsigned getMaxSizeBits(ASTContext &Context);
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getSize(),
+ getSizeModifier(), getIndexTypeCVRQualifiers());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
+ const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
+ unsigned TypeQuals) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(ArraySize.getZExtValue());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ConstantArray;
+ }
+ static bool classof(const ConstantArrayType *) { return true; }
+};
+
+/// IncompleteArrayType - This class represents C arrays with an unspecified
+/// size. For example 'int A[]' has an IncompleteArrayType where the element
+/// type is 'int' and the size is unspecified.
+class IncompleteArrayType : public ArrayType {
+
+ IncompleteArrayType(QualType et, QualType can,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(IncompleteArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == IncompleteArray;
+ }
+ static bool classof(const IncompleteArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getSizeModifier(),
+ getIndexTypeCVRQualifiers());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
+ ArraySizeModifier SizeMod, unsigned TypeQuals) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ }
+};
+
+/// VariableArrayType - This class represents C arrays with a specified size
+/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'.
+/// Since the size expression is an arbitrary expression, we store it as such.
+///
+/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and
+/// should not be: two lexically equivalent variable array types could mean
+/// different things, for example, these variables do not have the same type
+/// dynamically:
+///
+/// void foo(int x) {
+/// int Y[x];
+/// ++x;
+/// int Z[x];
+/// }
+///
+class VariableArrayType : public ArrayType {
+ /// SizeExpr - An assignment expression. VLA's are only permitted within
+ /// a function block.
+ Stmt *SizeExpr;
+ /// Brackets - The left and right array brackets.
+ SourceRange Brackets;
+
+ VariableArrayType(QualType et, QualType can, Expr *e,
+ ArraySizeModifier sm, unsigned tq,
+ SourceRange brackets)
+ : ArrayType(VariableArray, et, can, sm, tq,
+ et->containsUnexpandedParameterPack()),
+ SizeExpr((Stmt*) e), Brackets(brackets) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ Expr *getSizeExpr() const {
+ // We use C-style casts instead of cast<> here because we do not wish
+ // to have a dependency of Type.h on Stmt.h/Expr.h.
+ return (Expr*) SizeExpr;
+ }
+ SourceRange getBracketsRange() const { return Brackets; }
+ SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
+ SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == VariableArray;
+ }
+ static bool classof(const VariableArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ assert(0 && "Cannnot unique VariableArrayTypes.");
+ }
+};
+
+/// DependentSizedArrayType - This type represents an array type in
+/// C++ whose size is a value-dependent expression. For example:
+///
+/// \code
+/// template<typename T, int Size>
+/// class array {
+/// T data[Size];
+/// };
+/// \endcode
+///
+/// For these types, we won't actually know what the array bound is
+/// until template instantiation occurs, at which point this will
+/// become either a ConstantArrayType or a VariableArrayType.
+class DependentSizedArrayType : public ArrayType {
+ const ASTContext &Context;
+
+ /// \brief An assignment expression that will instantiate to the
+ /// size of the array.
+ ///
+ /// The expression itself might be NULL, in which case the array
+ /// type will have its size deduced from an initializer.
+ Stmt *SizeExpr;
+
+ /// Brackets - The left and right array brackets.
+ SourceRange Brackets;
+
+ DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can,
+ Expr *e, ArraySizeModifier sm, unsigned tq,
+ SourceRange brackets);
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ Expr *getSizeExpr() const {
+ // We use C-style casts instead of cast<> here because we do not wish
+ // to have a dependency of Type.h on Stmt.h/Expr.h.
+ return (Expr*) SizeExpr;
+ }
+ SourceRange getBracketsRange() const { return Brackets; }
+ SourceLocation getLBracketLoc() const { return Brackets.getBegin(); }
+ SourceLocation getRBracketLoc() const { return Brackets.getEnd(); }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentSizedArray;
+ }
+ static bool classof(const DependentSizedArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getElementType(),
+ getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType ET, ArraySizeModifier SizeMod,
+ unsigned TypeQuals, Expr *E);
+};
+
+/// DependentSizedExtVectorType - This type represent an extended vector type
+/// where either the type or size is dependent. For example:
+/// @code
+/// template<typename T, int Size>
+/// class vector {
+/// typedef T __attribute__((ext_vector_type(Size))) type;
+/// }
+/// @endcode
+class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
+ const ASTContext &Context;
+ Expr *SizeExpr;
+ /// ElementType - The element type of the array.
+ QualType ElementType;
+ SourceLocation loc;
+
+ DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType,
+ QualType can, Expr *SizeExpr, SourceLocation loc);
+
+ friend class ASTContext;
+
+public:
+ Expr *getSizeExpr() const { return SizeExpr; }
+ QualType getElementType() const { return ElementType; }
+ SourceLocation getAttributeLoc() const { return loc; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentSizedExtVector;
+ }
+ static bool classof(const DependentSizedExtVectorType *) { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getElementType(), getSizeExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType ElementType, Expr *SizeExpr);
+};
+
+
+/// VectorType - GCC generic vector type. This type is created using
+/// __attribute__((vector_size(n)), where "n" specifies the vector size in
+/// bytes; or from an Altivec __vector or vector declaration.
+/// Since the constructor takes the number of vector elements, the
+/// client is responsible for converting the size into the number of elements.
+class VectorType : public Type, public llvm::FoldingSetNode {
+public:
+ enum VectorKind {
+ GenericVector, // not a target-specific vector type
+ AltiVecVector, // is AltiVec vector
+ AltiVecPixel, // is AltiVec 'vector Pixel'
+ AltiVecBool, // is AltiVec 'vector bool ...'
+ NeonVector, // is ARM Neon vector
+ NeonPolyVector // is ARM Neon polynomial vector
+ };
+protected:
+ /// ElementType - The element type of the vector.
+ QualType ElementType;
+
+ VectorType(QualType vecType, unsigned nElements, QualType canonType,
+ VectorKind vecKind);
+
+ VectorType(TypeClass tc, QualType vecType, unsigned nElements,
+ QualType canonType, VectorKind vecKind);
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getElementType() const { return ElementType; }
+ unsigned getNumElements() const { return VectorTypeBits.NumElements; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ VectorKind getVectorKind() const {
+ return VectorKind(VectorTypeBits.VecKind);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getNumElements(),
+ getTypeClass(), getVectorKind());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
+ unsigned NumElements, TypeClass TypeClass,
+ VectorKind VecKind) {
+ ID.AddPointer(ElementType.getAsOpaquePtr());
+ ID.AddInteger(NumElements);
+ ID.AddInteger(TypeClass);
+ ID.AddInteger(VecKind);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
+ }
+ static bool classof(const VectorType *) { return true; }
+};
+
+/// ExtVectorType - Extended vector type. This type is created using
+/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
+/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
+/// class enables syntactic extensions, like Vector Components for accessing
+/// points, colors, and textures (modeled after OpenGL Shading Language).
+class ExtVectorType : public VectorType {
+ ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
+ VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ static int getPointAccessorIdx(char c) {
+ switch (c) {
+ default: return -1;
+ case 'x': return 0;
+ case 'y': return 1;
+ case 'z': return 2;
+ case 'w': return 3;
+ }
+ }
+ static int getNumericAccessorIdx(char c) {
+ switch (c) {
+ default: return -1;
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'A':
+ case 'a': return 10;
+ case 'B':
+ case 'b': return 11;
+ case 'C':
+ case 'c': return 12;
+ case 'D':
+ case 'd': return 13;
+ case 'E':
+ case 'e': return 14;
+ case 'F':
+ case 'f': return 15;
+ }
+ }
+
+ static int getAccessorIdx(char c) {
+ if (int idx = getPointAccessorIdx(c)+1) return idx-1;
+ return getNumericAccessorIdx(c);
+ }
+
+ bool isAccessorWithinNumElements(char c) const {
+ if (int idx = getAccessorIdx(c)+1)
+ return unsigned(idx-1) < getNumElements();
+ return false;
+ }
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ExtVector;
+ }
+ static bool classof(const ExtVectorType *) { return true; }
+};
+
+/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base
+/// class of FunctionNoProtoType and FunctionProtoType.
+///
+class FunctionType : public Type {
+ // The type returned by the function.
+ QualType ResultType;
+
+ public:
+ /// ExtInfo - A class which abstracts out some details necessary for
+ /// making a call.
+ ///
+ /// It is not actually used directly for storing this information in
+ /// a FunctionType, although FunctionType does currently use the
+ /// same bit-pattern.
+ ///
+ // If you add a field (say Foo), other than the obvious places (both,
+ // constructors, compile failures), what you need to update is
+ // * Operator==
+ // * getFoo
+ // * withFoo
+ // * functionType. Add Foo, getFoo.
+ // * ASTContext::getFooType
+ // * ASTContext::mergeFunctionTypes
+ // * FunctionNoProtoType::Profile
+ // * FunctionProtoType::Profile
+ // * TypePrinter::PrintFunctionProto
+ // * AST read and write
+ // * Codegen
+ class ExtInfo {
+ // Feel free to rearrange or add bits, but if you go over 8,
+ // you'll need to adjust both the Bits field below and
+ // Type::FunctionTypeBitfields.
+
+ // | CC |noreturn|regparm
+ // |0 .. 2| 3 |4 .. 6
+ enum { CallConvMask = 0x7 };
+ enum { NoReturnMask = 0x8 };
+ enum { RegParmMask = ~(CallConvMask | NoReturnMask),
+ RegParmOffset = 4 };
+
+ unsigned char Bits;
+
+ ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {}
+
+ friend class FunctionType;
+
+ public:
+ // Constructor with no defaults. Use this when you know that you
+ // have all the elements (when reading an AST file for example).
+ ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) {
+ Bits = ((unsigned) cc) |
+ (noReturn ? NoReturnMask : 0) |
+ (regParm << RegParmOffset);
+ }
+
+ // Constructor with all defaults. Use when for example creating a
+ // function know to use defaults.
+ ExtInfo() : Bits(0) {}
+
+ bool getNoReturn() const { return Bits & NoReturnMask; }
+ unsigned getRegParm() const { return Bits >> RegParmOffset; }
+ CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
+
+ bool operator==(ExtInfo Other) const {
+ return Bits == Other.Bits;
+ }
+ bool operator!=(ExtInfo Other) const {
+ return Bits != Other.Bits;
+ }
+
+ // Note that we don't have setters. That is by design, use
+ // the following with methods instead of mutating these objects.
+
+ ExtInfo withNoReturn(bool noReturn) const {
+ if (noReturn)
+ return ExtInfo(Bits | NoReturnMask);
+ else
+ return ExtInfo(Bits & ~NoReturnMask);
+ }
+
+ ExtInfo withRegParm(unsigned RegParm) const {
+ return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset));
+ }
+
+ ExtInfo withCallingConv(CallingConv cc) const {
+ return ExtInfo((Bits & ~CallConvMask) | (unsigned) cc);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Bits);
+ }
+ };
+
+protected:
+ FunctionType(TypeClass tc, QualType res, bool variadic,
+ unsigned typeQuals, RefQualifierKind RefQualifier,
+ QualType Canonical, bool Dependent,
+ bool VariablyModified, bool ContainsUnexpandedParameterPack,
+ ExtInfo Info)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack),
+ ResultType(res) {
+ FunctionTypeBits.ExtInfo = Info.Bits;
+ FunctionTypeBits.Variadic = variadic;
+ FunctionTypeBits.TypeQuals = typeQuals;
+ FunctionTypeBits.RefQualifier = static_cast<unsigned>(RefQualifier);
+ }
+ bool isVariadic() const { return FunctionTypeBits.Variadic; }
+ unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
+
+ RefQualifierKind getRefQualifier() const {
+ return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
+ }
+
+public:
+
+ QualType getResultType() const { return ResultType; }
+
+ unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
+ bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
+ CallingConv getCallConv() const { return getExtInfo().getCC(); }
+ ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
+
+ /// \brief Determine the type of an expression that calls a function of
+ /// this type.
+ QualType getCallResultType(ASTContext &Context) const {
+ return getResultType().getNonLValueExprType(Context);
+ }
+
+ static llvm::StringRef getNameForCallConv(CallingConv CC);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionNoProto ||
+ T->getTypeClass() == FunctionProto;
+ }
+ static bool classof(const FunctionType *) { return true; }
+};
+
+/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
+/// no information available about its arguments.
+class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
+ FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
+ : FunctionType(FunctionNoProto, Result, false, 0, RQ_None, Canonical,
+ /*Dependent=*/false, Result->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false, Info) {}
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ // No additional state past what FunctionType provides.
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getResultType(), getExtInfo());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
+ ExtInfo Info) {
+ Info.Profile(ID);
+ ID.AddPointer(ResultType.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionNoProto;
+ }
+ static bool classof(const FunctionNoProtoType *) { return true; }
+};
+
+/// FunctionProtoType - Represents a prototype with argument type info, e.g.
+/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
+/// arguments, not as having a single void argument. Such a type can have an
+/// exception specification, but this specification is not part of the canonical
+/// type.
+class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
+public:
+ /// ExtProtoInfo - Extra information about a function prototype.
+ struct ExtProtoInfo {
+ ExtProtoInfo() :
+ Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false),
+ TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {}
+
+ FunctionType::ExtInfo ExtInfo;
+ bool Variadic;
+ bool HasExceptionSpec;
+ bool HasAnyExceptionSpec;
+ unsigned char TypeQuals;
+ RefQualifierKind RefQualifier;
+ unsigned NumExceptions;
+ const QualType *Exceptions;
+ };
+
+private:
+ /// \brief Determine whether there are any argument types that
+ /// contain an unexpanded parameter pack.
+ static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray,
+ unsigned numArgs) {
+ for (unsigned Idx = 0; Idx < numArgs; ++Idx)
+ if (ArgArray[Idx]->containsUnexpandedParameterPack())
+ return true;
+
+ return false;
+ }
+
+ FunctionProtoType(QualType result, const QualType *args, unsigned numArgs,
+ QualType canonical, const ExtProtoInfo &epi);
+
+ /// NumArgs - The number of arguments this function has, not counting '...'.
+ unsigned NumArgs : 20;
+
+ /// NumExceptions - The number of types in the exception spec, if any.
+ unsigned NumExceptions : 10;
+
+ /// HasExceptionSpec - Whether this function has an exception spec at all.
+ unsigned HasExceptionSpec : 1;
+
+ /// HasAnyExceptionSpec - Whether this function has a throw(...) spec.
+ unsigned HasAnyExceptionSpec : 1;
+
+ /// ArgInfo - There is an variable size array after the class in memory that
+ /// holds the argument types.
+
+ /// Exceptions - There is another variable size array after ArgInfo that
+ /// holds the exception types.
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ unsigned getNumArgs() const { return NumArgs; }
+ QualType getArgType(unsigned i) const {
+ assert(i < NumArgs && "Invalid argument number!");
+ return arg_type_begin()[i];
+ }
+
+ ExtProtoInfo getExtProtoInfo() const {
+ ExtProtoInfo EPI;
+ EPI.ExtInfo = getExtInfo();
+ EPI.Variadic = isVariadic();
+ EPI.HasExceptionSpec = hasExceptionSpec();
+ EPI.HasAnyExceptionSpec = hasAnyExceptionSpec();
+ EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
+ EPI.RefQualifier = getRefQualifier();
+ EPI.NumExceptions = NumExceptions;
+ EPI.Exceptions = exception_begin();
+ return EPI;
+ }
+
+ bool hasExceptionSpec() const { return HasExceptionSpec; }
+ bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; }
+ unsigned getNumExceptions() const { return NumExceptions; }
+ QualType getExceptionType(unsigned i) const {
+ assert(i < NumExceptions && "Invalid exception number!");
+ return exception_begin()[i];
+ }
+ bool hasEmptyExceptionSpec() const {
+ return hasExceptionSpec() && !hasAnyExceptionSpec() &&
+ getNumExceptions() == 0;
+ }
+
+ using FunctionType::isVariadic;
+
+ /// \brief Determines whether this function prototype contains a
+ /// parameter pack at the end.
+ ///
+ /// A function template whose last parameter is a parameter pack can be
+ /// called with an arbitrary number of arguments, much like a variadic
+ /// function. However,
+ bool isTemplateVariadic() const;
+
+ unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+
+
+ /// \brief Retrieve the ref-qualifier associated with this function type.
+ RefQualifierKind getRefQualifier() const {
+ return FunctionType::getRefQualifier();
+ }
+
+ typedef const QualType *arg_type_iterator;
+ arg_type_iterator arg_type_begin() const {
+ return reinterpret_cast<const QualType *>(this+1);
+ }
+ arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; }
+
+ typedef const QualType *exception_iterator;
+ exception_iterator exception_begin() const {
+ // exceptions begin where arguments end
+ return arg_type_end();
+ }
+ exception_iterator exception_end() const {
+ return exception_begin() + NumExceptions;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionProto;
+ }
+ static bool classof(const FunctionProtoType *) { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
+ arg_type_iterator ArgTys, unsigned NumArgs,
+ const ExtProtoInfo &EPI);
+};
+
+
+/// \brief Represents the dependent type named by a dependently-scoped
+/// typename using declaration, e.g.
+/// using typename Base<T>::foo;
+/// Template instantiation turns these into the underlying type.
+class UnresolvedUsingType : public Type {
+ UnresolvedUsingTypenameDecl *Decl;
+
+ UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
+ : Type(UnresolvedUsing, QualType(), true, false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ UnresolvedUsingTypenameDecl *getDecl() const { return Decl; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == UnresolvedUsing;
+ }
+ static bool classof(const UnresolvedUsingType *) { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ return Profile(ID, Decl);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ UnresolvedUsingTypenameDecl *D) {
+ ID.AddPointer(D);
+ }
+};
+
+
+class TypedefType : public Type {
+ TypedefDecl *Decl;
+protected:
+ TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
+ : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(const_cast<TypedefDecl*>(D)) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ TypedefDecl *getDecl() const { return Decl; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
+ static bool classof(const TypedefType *) { return true; }
+};
+
+/// TypeOfExprType (GCC extension).
+class TypeOfExprType : public Type {
+ Expr *TOExpr;
+
+protected:
+ TypeOfExprType(Expr *E, QualType can = QualType());
+ friend class ASTContext; // ASTContext creates these.
+public:
+ Expr *getUnderlyingExpr() const { return TOExpr; }
+
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const;
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
+ static bool classof(const TypeOfExprType *) { return true; }
+};
+
+/// \brief Internal representation of canonical, dependent
+/// typeof(expr) types.
+///
+/// This class is used internally by the ASTContext to manage
+/// canonical, dependent types, only. Clients will only see instances
+/// of this class via TypeOfExprType nodes.
+class DependentTypeOfExprType
+ : public TypeOfExprType, public llvm::FoldingSetNode {
+ const ASTContext &Context;
+
+public:
+ DependentTypeOfExprType(const ASTContext &Context, Expr *E)
+ : TypeOfExprType(E), Context(Context) { }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getUnderlyingExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ Expr *E);
+};
+
+/// TypeOfType (GCC extension).
+class TypeOfType : public Type {
+ QualType TOType;
+ TypeOfType(QualType T, QualType can)
+ : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(),
+ T->containsUnexpandedParameterPack()),
+ TOType(T) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+ QualType getUnderlyingType() const { return TOType; }
+
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getUnderlyingType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
+ static bool classof(const TypeOfType *) { return true; }
+};
+
+/// DecltypeType (C++0x)
+class DecltypeType : public Type {
+ Expr *E;
+
+ // FIXME: We could get rid of UnderlyingType if we wanted to: We would have to
+ // Move getDesugaredType to ASTContext so that it can call getDecltypeForExpr
+ // from it.
+ QualType UnderlyingType;
+
+protected:
+ DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType());
+ friend class ASTContext; // ASTContext creates these.
+public:
+ Expr *getUnderlyingExpr() const { return E; }
+ QualType getUnderlyingType() const { return UnderlyingType; }
+
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getUnderlyingType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return !isDependentType(); }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
+ static bool classof(const DecltypeType *) { return true; }
+};
+
+/// \brief Internal representation of canonical, dependent
+/// decltype(expr) types.
+///
+/// This class is used internally by the ASTContext to manage
+/// canonical, dependent types, only. Clients will only see instances
+/// of this class via DecltypeType nodes.
+class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
+ const ASTContext &Context;
+
+public:
+ DependentDecltypeType(const ASTContext &Context, Expr *E);
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getUnderlyingExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ Expr *E);
+};
+
+class TagType : public Type {
+ /// Stores the TagDecl associated with this type. The decl may point to any
+ /// TagDecl that declares the entity.
+ TagDecl * decl;
+
+protected:
+ TagType(TypeClass TC, const TagDecl *D, QualType can);
+
+public:
+ TagDecl *getDecl() const;
+
+ /// @brief Determines whether this type is in the process of being
+ /// defined.
+ bool isBeingDefined() const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
+ }
+ static bool classof(const TagType *) { return true; }
+ static bool classof(const RecordType *) { return true; }
+ static bool classof(const EnumType *) { return true; }
+};
+
+/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
+/// to detect TagType objects of structs/unions/classes.
+class RecordType : public TagType {
+protected:
+ explicit RecordType(const RecordDecl *D)
+ : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { }
+ explicit RecordType(TypeClass TC, RecordDecl *D)
+ : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ RecordDecl *getDecl() const {
+ return reinterpret_cast<RecordDecl*>(TagType::getDecl());
+ }
+
+ // FIXME: This predicate is a helper to QualType/Type. It needs to
+ // recursively check all fields for const-ness. If any field is declared
+ // const, it needs to return false.
+ bool hasConstFields() const { return false; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const TagType *T);
+ static bool classof(const Type *T) {
+ return isa<TagType>(T) && classof(cast<TagType>(T));
+ }
+ static bool classof(const RecordType *) { return true; }
+};
+
+/// EnumType - This is a helper class that allows the use of isa/cast/dyncast
+/// to detect TagType objects of enums.
+class EnumType : public TagType {
+ explicit EnumType(const EnumDecl *D)
+ : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ EnumDecl *getDecl() const {
+ return reinterpret_cast<EnumDecl*>(TagType::getDecl());
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const TagType *T);
+ static bool classof(const Type *T) {
+ return isa<TagType>(T) && classof(cast<TagType>(T));
+ }
+ static bool classof(const EnumType *) { return true; }
+};
+
+/// AttributedType - An attributed type is a type to which a type
+/// attribute has been applied. The "modified type" is the
+/// fully-sugared type to which the attributed type was applied;
+/// generally it is not canonically equivalent to the attributed type.
+/// The "equivalent type" is the minimally-desugared type which the
+/// type is canonically equivalent to.
+///
+/// For example, in the following attributed type:
+/// int32_t __attribute__((vector_size(16)))
+/// - the modified type is the TypedefType for int32_t
+/// - the equivalent type is VectorType(16, int32_t)
+/// - the canonical type is VectorType(16, int)
+class AttributedType : public Type, public llvm::FoldingSetNode {
+public:
+ // It is really silly to have yet another attribute-kind enum, but
+ // clang::attr::Kind doesn't currently cover the pure type attrs.
+ enum Kind {
+ // Expression operand.
+ attr_address_space,
+ attr_regparm,
+ attr_vector_size,
+ attr_neon_vector_type,
+ attr_neon_polyvector_type,
+
+ FirstExprOperandKind = attr_address_space,
+ LastExprOperandKind = attr_neon_polyvector_type,
+
+ // Enumerated operand (string or keyword).
+ attr_objc_gc,
+
+ FirstEnumOperandKind = attr_objc_gc,
+ LastEnumOperandKind = attr_objc_gc,
+
+ // No operand.
+ attr_noreturn,
+ attr_cdecl,
+ attr_fastcall,
+ attr_stdcall,
+ attr_thiscall,
+ attr_pascal
+ };
+
+private:
+ QualType ModifiedType;
+ QualType EquivalentType;
+
+ friend class ASTContext; // creates these
+
+ AttributedType(QualType canon, Kind attrKind,
+ QualType modified, QualType equivalent)
+ : Type(Attributed, canon, canon->isDependentType(),
+ canon->isVariablyModifiedType(),
+ canon->containsUnexpandedParameterPack()),
+ ModifiedType(modified), EquivalentType(equivalent) {
+ AttributedTypeBits.AttrKind = attrKind;
+ }
+
+public:
+ Kind getAttrKind() const {
+ return static_cast<Kind>(AttributedTypeBits.AttrKind);
+ }
+
+ QualType getModifiedType() const { return ModifiedType; }
+ QualType getEquivalentType() const { return EquivalentType; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getEquivalentType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
+ QualType modified, QualType equivalent) {
+ ID.AddInteger(attrKind);
+ ID.AddPointer(modified.getAsOpaquePtr());
+ ID.AddPointer(equivalent.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Attributed;
+ }
+ static bool classof(const AttributedType *T) { return true; }
+};
+
+class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ unsigned Depth : 15;
+ unsigned ParameterPack : 1;
+ unsigned Index : 16;
+ IdentifierInfo *Name;
+
+ TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
+ QualType Canon)
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(N) { }
+
+ TemplateTypeParmType(unsigned D, unsigned I, bool PP)
+ : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true,
+ /*VariablyModified=*/false, PP),
+ Depth(D), ParameterPack(PP), Index(I), Name(0) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ unsigned getDepth() const { return Depth; }
+ unsigned getIndex() const { return Index; }
+ bool isParameterPack() const { return ParameterPack; }
+ IdentifierInfo *getName() const { return Name; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Depth, Index, ParameterPack, Name);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth,
+ unsigned Index, bool ParameterPack,
+ IdentifierInfo *Name) {
+ ID.AddInteger(Depth);
+ ID.AddInteger(Index);
+ ID.AddBoolean(ParameterPack);
+ ID.AddPointer(Name);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == TemplateTypeParm;
+ }
+ static bool classof(const TemplateTypeParmType *T) { return true; }
+};
+
+/// \brief Represents the result of substituting a type for a template
+/// type parameter.
+///
+/// Within an instantiated template, all template type parameters have
+/// been replaced with these. They are used solely to record that a
+/// type was originally written as a template type parameter;
+/// therefore they are never canonical.
+class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ // The original type parameter.
+ const TemplateTypeParmType *Replaced;
+
+ SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
+ Replaced(Param) { }
+
+ friend class ASTContext;
+
+public:
+ IdentifierInfo *getName() const { return Replaced->getName(); }
+
+ /// Gets the template parameter that was substituted for.
+ const TemplateTypeParmType *getReplacedParameter() const {
+ return Replaced;
+ }
+
+ /// Gets the type that was substituted for the template
+ /// parameter.
+ QualType getReplacementType() const {
+ return getCanonicalTypeInternal();
+ }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getReplacementType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getReplacedParameter(), getReplacementType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ QualType Replacement) {
+ ID.AddPointer(Replaced);
+ ID.AddPointer(Replacement.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == SubstTemplateTypeParm;
+ }
+ static bool classof(const SubstTemplateTypeParmType *T) { return true; }
+};
+
+/// \brief Represents the result of substituting a set of types for a template
+/// type parameter pack.
+///
+/// When a pack expansion in the source code contains multiple parameter packs
+/// and those parameter packs correspond to different levels of template
+/// parameter lists, this type node is used to represent a template type
+/// parameter pack from an outer level, which has already had its argument pack
+/// substituted but that still lives within a pack expansion that itself
+/// could not be instantiated. When actually performing a substitution into
+/// that pack expansion (e.g., when all template parameters have corresponding
+/// arguments), this type will be replaced with the \c SubstTemplateTypeParmType
+/// at the current pack substitution index.
+class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode {
+ /// \brief The original type parameter.
+ const TemplateTypeParmType *Replaced;
+
+ /// \brief A pointer to the set of template arguments that this
+ /// parameter pack is instantiated with.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in \c Arguments.
+ unsigned NumArguments;
+
+ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+ QualType Canon,
+ const TemplateArgument &ArgPack);
+
+ friend class ASTContext;
+
+public:
+ IdentifierInfo *getName() const { return Replaced->getName(); }
+
+ /// Gets the template parameter that was substituted for.
+ const TemplateTypeParmType *getReplacedParameter() const {
+ return Replaced;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ TemplateArgument getArgumentPack() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == SubstTemplateTypeParmPack;
+ }
+ static bool classof(const SubstTemplateTypeParmPackType *T) { return true; }
+};
+
+/// \brief Represents a C++0x auto type.
+///
+/// These types are usually a placeholder for a deduced type. However, within
+/// templates and before the initializer is attached, there is no deduced type
+/// and an auto type is type-dependent and canonical.
+class AutoType : public Type, public llvm::FoldingSetNode {
+ AutoType(QualType DeducedType)
+ : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
+ /*Dependent=*/DeducedType.isNull(),
+ /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+ assert((DeducedType.isNull() || !DeducedType->isDependentType()) &&
+ "deduced a dependent type for auto");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ bool isSugared() const { return isDeduced(); }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ QualType getDeducedType() const {
+ return isDeduced() ? getCanonicalTypeInternal() : QualType();
+ }
+ bool isDeduced() const {
+ return !isDependentType();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDeducedType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Deduced) {
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Auto;
+ }
+ static bool classof(const AutoType *T) { return true; }
+};
+
+/// \brief Represents the type of a template specialization as written
+/// in the source code.
+///
+/// Template specialization types represent the syntactic form of a
+/// template-id that refers to a type, e.g., @c vector<int>. Some
+/// template specialization types are syntactic sugar, whose canonical
+/// type will point to some other type node that represents the
+/// instantiation or class template specialization. For example, a
+/// class template specialization type of @c vector<int> will refer to
+/// a tag type for the instantiation
+/// @c std::vector<int, std::allocator<int>>.
+///
+/// Other template specialization types, for which the template name
+/// is dependent, may be canonical types. These types are always
+/// dependent.
+class TemplateSpecializationType
+ : public Type, public llvm::FoldingSetNode {
+ /// \brief The name of the template being specialized.
+ TemplateName Template;
+
+ /// \brief - The number of template arguments named in this class
+ /// template specialization.
+ unsigned NumArgs;
+
+ TemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs, QualType Canon);
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Determine whether any of the given template arguments are
+ /// dependent.
+ static bool anyDependentTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs);
+
+ static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &);
+
+ /// \brief Print a template argument list, including the '<' and '>'
+ /// enclosing the template arguments.
+ static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy,
+ bool SkipBrackets = false);
+
+ static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
+ static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &,
+ const PrintingPolicy &Policy);
+
+ /// True if this template specialization type matches a current
+ /// instantiation in the context in which it is found.
+ bool isCurrentInstantiation() const {
+ return isa<InjectedClassNameType>(getCanonicalTypeInternal());
+ }
+
+ typedef const TemplateArgument * iterator;
+
+ iterator begin() const { return getArgs(); }
+ iterator end() const; // defined inline in TemplateBase.h
+
+ /// \brief Retrieve the name of the template that we are specializing.
+ TemplateName getTemplateName() const { return Template; }
+
+ /// \brief Retrieve the template arguments.
+ const TemplateArgument *getArgs() const {
+ return reinterpret_cast<const TemplateArgument *>(this + 1);
+ }
+
+ /// \brief Retrieve the number of template arguments.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief Retrieve a specific template argument as a type.
+ /// \precondition @c isArgType(Arg)
+ const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
+
+ bool isSugared() const {
+ return !isDependentType() || isCurrentInstantiation();
+ }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
+ Profile(ID, Template, getArgs(), NumArgs, Ctx);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const ASTContext &Context);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == TemplateSpecialization;
+ }
+ static bool classof(const TemplateSpecializationType *T) { return true; }
+};
+
+/// \brief The injected class name of a C++ class template or class
+/// template partial specialization. Used to record that a type was
+/// spelled with a bare identifier rather than as a template-id; the
+/// equivalent for non-templated classes is just RecordType.
+///
+/// Injected class name types are always dependent. Template
+/// instantiation turns these into RecordTypes.
+///
+/// Injected class name types are always canonical. This works
+/// because it is impossible to compare an injected class name type
+/// with the corresponding non-injected template type, for the same
+/// reason that it is impossible to directly compare template
+/// parameters from different dependent contexts: injected class name
+/// types can only occur within the scope of a particular templated
+/// declaration, and within that scope every template specialization
+/// will canonicalize to the injected class name (when appropriate
+/// according to the rules of the language).
+class InjectedClassNameType : public Type {
+ CXXRecordDecl *Decl;
+
+ /// The template specialization which this type represents.
+ /// For example, in
+ /// template <class T> class A { ... };
+ /// this is A<T>, whereas in
+ /// template <class X, class Y> class A<B<X,Y> > { ... };
+ /// this is A<B<X,Y> >.
+ ///
+ /// It is always unqualified, always a template specialization type,
+ /// and always dependent.
+ QualType InjectedType;
+
+ friend class ASTContext; // ASTContext creates these.
+ friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
+ // currently suitable for AST reading, too much
+ // interdependencies.
+ InjectedClassNameType(CXXRecordDecl *D, QualType TST)
+ : Type(InjectedClassName, QualType(), /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(D), InjectedType(TST) {
+ assert(isa<TemplateSpecializationType>(TST));
+ assert(!TST.hasQualifiers());
+ assert(TST->isDependentType());
+ }
+
+public:
+ QualType getInjectedSpecializationType() const { return InjectedType; }
+ const TemplateSpecializationType *getInjectedTST() const {
+ return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
+ }
+
+ CXXRecordDecl *getDecl() const;
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == InjectedClassName;
+ }
+ static bool classof(const InjectedClassNameType *T) { return true; }
+};
+
+/// \brief The kind of a tag type.
+enum TagTypeKind {
+ /// \brief The "struct" keyword.
+ TTK_Struct,
+ /// \brief The "union" keyword.
+ TTK_Union,
+ /// \brief The "class" keyword.
+ TTK_Class,
+ /// \brief The "enum" keyword.
+ TTK_Enum
+};
+
+/// \brief The elaboration keyword that precedes a qualified type name or
+/// introduces an elaborated-type-specifier.
+enum ElaboratedTypeKeyword {
+ /// \brief The "struct" keyword introduces the elaborated-type-specifier.
+ ETK_Struct,
+ /// \brief The "union" keyword introduces the elaborated-type-specifier.
+ ETK_Union,
+ /// \brief The "class" keyword introduces the elaborated-type-specifier.
+ ETK_Class,
+ /// \brief The "enum" keyword introduces the elaborated-type-specifier.
+ ETK_Enum,
+ /// \brief The "typename" keyword precedes the qualified type name, e.g.,
+ /// \c typename T::type.
+ ETK_Typename,
+ /// \brief No keyword precedes the qualified type name.
+ ETK_None
+};
+
+/// A helper class for Type nodes having an ElaboratedTypeKeyword.
+/// The keyword in stored in the free bits of the base class.
+/// Also provides a few static helpers for converting and printing
+/// elaborated type keyword and tag type kind enumerations.
+class TypeWithKeyword : public Type {
+protected:
+ TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc,
+ QualType Canonical, bool Dependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, Canonical, Dependent, VariablyModified,
+ ContainsUnexpandedParameterPack) {
+ TypeWithKeywordBits.Keyword = Keyword;
+ }
+
+public:
+ ElaboratedTypeKeyword getKeyword() const {
+ return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
+ }
+
+ /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST)
+ /// into an elaborated type keyword.
+ static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec);
+
+ /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
+ /// into a tag type kind. It is an error to provide a type specifier
+ /// which *isn't* a tag kind here.
+ static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec);
+
+ /// getKeywordForTagDeclKind - Converts a TagTypeKind into an
+ /// elaborated type keyword.
+ static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag);
+
+ /// getTagTypeKindForKeyword - Converts an elaborated type keyword into
+ // a TagTypeKind. It is an error to provide an elaborated type keyword
+ /// which *isn't* a tag kind here.
+ static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword);
+
+ static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword);
+
+ static const char *getKeywordName(ElaboratedTypeKeyword Keyword);
+
+ static const char *getTagTypeKindName(TagTypeKind Kind) {
+ return getKeywordName(getKeywordForTagTypeKind(Kind));
+ }
+
+ class CannotCastToThisType {};
+ static CannotCastToThisType classof(const Type *);
+};
+
+/// \brief Represents a type that was referred to using an elaborated type
+/// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type,
+/// or both.
+///
+/// This type is used to keep track of a type name as written in the
+/// source code, including tag keywords and any nested-name-specifiers.
+/// The type itself is always "sugar", used to express what was written
+/// in the source code but containing no additional semantic information.
+class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
+
+ /// \brief The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The type that this qualified name refers to.
+ QualType NamedType;
+
+ ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
+ QualType NamedType, QualType CanonType)
+ : TypeWithKeyword(Keyword, Elaborated, CanonType,
+ NamedType->isDependentType(),
+ NamedType->isVariablyModifiedType(),
+ NamedType->containsUnexpandedParameterPack()),
+ NNS(NNS), NamedType(NamedType) {
+ assert(!(Keyword == ETK_None && NNS == 0) &&
+ "ElaboratedType cannot have elaborated type keyword "
+ "and name qualifier both null.");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ ~ElaboratedType();
+
+ /// \brief Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// \brief Retrieve the type named by the qualified-id.
+ QualType getNamedType() const { return NamedType; }
+
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getNamedType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getKeyword(), NNS, NamedType);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, QualType NamedType) {
+ ID.AddInteger(Keyword);
+ ID.AddPointer(NNS);
+ NamedType.Profile(ID);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Elaborated;
+ }
+ static bool classof(const ElaboratedType *T) { return true; }
+};
+
+/// \brief Represents a qualified type name for which the type name is
+/// dependent.
+///
+/// DependentNameType represents a class of dependent types that involve a
+/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent)
+/// name of a type. The DependentNameType may start with a "typename" (for a
+/// typename-specifier), "class", "struct", "union", or "enum" (for a
+/// dependent elaborated-type-specifier), or nothing (in contexts where we
+/// know that we must be referring to a type, e.g., in a base class specifier).
+class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
+
+ /// \brief The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The type that this typename specifier refers to.
+ const IdentifierInfo *Name;
+
+ DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name, QualType CanonType)
+ : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
+ NNS(NNS), Name(Name) {
+ assert(NNS->isDependent() &&
+ "DependentNameType requires a dependent nested-name-specifier");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// \brief Retrieve the type named by the typename specifier as an
+ /// identifier.
+ ///
+ /// This routine will return a non-NULL identifier pointer when the
+ /// form of the original typename was terminated by an identifier,
+ /// e.g., "typename T::type".
+ const IdentifierInfo *getIdentifier() const {
+ return Name;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getKeyword(), NNS, Name);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, const IdentifierInfo *Name) {
+ ID.AddInteger(Keyword);
+ ID.AddPointer(NNS);
+ ID.AddPointer(Name);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentName;
+ }
+ static bool classof(const DependentNameType *T) { return true; }
+};
+
+/// DependentTemplateSpecializationType - Represents a template
+/// specialization type whose template cannot be resolved, e.g.
+/// A<T>::template B<T>
+class DependentTemplateSpecializationType :
+ public TypeWithKeyword, public llvm::FoldingSetNode {
+
+ /// \brief The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The identifier of the template.
+ const IdentifierInfo *Name;
+
+ /// \brief - The number of template arguments named in this class
+ /// template specialization.
+ unsigned NumArgs;
+
+ const TemplateArgument *getArgBuffer() const {
+ return reinterpret_cast<const TemplateArgument*>(this+1);
+ }
+ TemplateArgument *getArgBuffer() {
+ return reinterpret_cast<TemplateArgument*>(this+1);
+ }
+
+ DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args,
+ QualType Canon);
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+ const IdentifierInfo *getIdentifier() const { return Name; }
+
+ /// \brief Retrieve the template arguments.
+ const TemplateArgument *getArgs() const {
+ return getArgBuffer();
+ }
+
+ /// \brief Retrieve the number of template arguments.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
+
+ typedef const TemplateArgument * iterator;
+ iterator begin() const { return getArgs(); }
+ iterator end() const; // inline in TemplateBase.h
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
+ Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentTemplateSpecialization;
+ }
+ static bool classof(const DependentTemplateSpecializationType *T) {
+ return true;
+ }
+};
+
+/// \brief Represents a pack expansion of types.
+///
+/// Pack expansions are part of C++0x variadic templates. A pack
+/// expansion contains a pattern, which itself contains one or more
+/// "unexpanded" parameter packs. When instantiated, a pack expansion
+/// produces a series of types, each instantiated from the pattern of
+/// the expansion, where the Ith instantiation of the pattern uses the
+/// Ith arguments bound to each of the unexpanded parameter packs. The
+/// pack expansion is considered to "expand" these unexpanded
+/// parameter packs.
+///
+/// \code
+/// template<typename ...Types> struct tuple;
+///
+/// template<typename ...Types>
+/// struct tuple_of_references {
+/// typedef tuple<Types&...> type;
+/// };
+/// \endcode
+///
+/// Here, the pack expansion \c Types&... is represented via a
+/// PackExpansionType whose pattern is Types&.
+class PackExpansionType : public Type, public llvm::FoldingSetNode {
+ /// \brief The pattern of the pack expansion.
+ QualType Pattern;
+
+ /// \brief The number of expansions that this pack expansion will
+ /// generate when substituted (+1), or indicates that
+ ///
+ /// This field will only have a non-zero value when some of the parameter
+ /// packs that occur within the pattern have been substituted but others have
+ /// not.
+ unsigned NumExpansions;
+
+ PackExpansionType(QualType Pattern, QualType Canon,
+ llvm::Optional<unsigned> NumExpansions)
+ : Type(PackExpansion, Canon, /*Dependent=*/true,
+ /*VariableModified=*/Pattern->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Pattern(Pattern),
+ NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the pattern of this pack expansion, which is the
+ /// type that will be repeatedly instantiated when instantiating the
+ /// pack expansion itself.
+ QualType getPattern() const { return Pattern; }
+
+ /// \brief Retrieve the number of expansions that this pack expansion will
+ /// generate, if known.
+ llvm::Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPattern(), getNumExpansions());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
+ llvm::Optional<unsigned> NumExpansions) {
+ ID.AddPointer(Pattern.getAsOpaquePtr());
+ ID.AddBoolean(NumExpansions);
+ if (NumExpansions)
+ ID.AddInteger(*NumExpansions);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == PackExpansion;
+ }
+ static bool classof(const PackExpansionType *T) {
+ return true;
+ }
+};
+
+/// ObjCObjectType - Represents a class type in Objective C.
+/// Every Objective C type is a combination of a base type and a
+/// list of protocols.
+///
+/// Given the following declarations:
+/// @class C;
+/// @protocol P;
+///
+/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
+/// with base C and no protocols.
+///
+/// 'C<P>' is an ObjCObjectType with base C and protocol list [P].
+///
+/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose
+/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
+/// and no protocols.
+///
+/// 'id<P>' is an ObjCPointerType whose pointee is an ObjCObjecType
+/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
+/// this should get its own sugar class to better represent the source.
+class ObjCObjectType : public Type {
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the ObjCObjectPointerType node.
+ //
+ // These protocols are those written directly on the type. If
+ // protocol qualifiers ever become additive, the iterators will need
+ // to get kindof complicated.
+ //
+ // In the canonical object type, these are sorted alphabetically
+ // and uniqued.
+
+ /// Either a BuiltinType or an InterfaceType or sugar for either.
+ QualType BaseType;
+
+ ObjCProtocolDecl * const *getProtocolStorage() const {
+ return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
+ }
+
+ ObjCProtocolDecl **getProtocolStorage();
+
+protected:
+ ObjCObjectType(QualType Canonical, QualType Base,
+ ObjCProtocolDecl * const *Protocols, unsigned NumProtocols);
+
+ enum Nonce_ObjCInterface { Nonce_ObjCInterface };
+ ObjCObjectType(enum Nonce_ObjCInterface)
+ : Type(ObjCInterface, QualType(), false, false, false),
+ BaseType(QualType(this_(), 0)) {
+ ObjCObjectTypeBits.NumProtocols = 0;
+ }
+
+public:
+ /// getBaseType - Gets the base type of this object type. This is
+ /// always (possibly sugar for) one of:
+ /// - the 'id' builtin type (as opposed to the 'id' type visible to the
+ /// user, which is a typedef for an ObjCPointerType)
+ /// - the 'Class' builtin type (same caveat)
+ /// - an ObjCObjectType (currently always an ObjCInterfaceType)
+ QualType getBaseType() const { return BaseType; }
+
+ bool isObjCId() const {
+ return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId);
+ }
+ bool isObjCClass() const {
+ return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass);
+ }
+ bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); }
+ bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); }
+ bool isObjCUnqualifiedIdOrClass() const {
+ if (!qual_empty()) return false;
+ if (const BuiltinType *T = getBaseType()->getAs<BuiltinType>())
+ return T->getKind() == BuiltinType::ObjCId ||
+ T->getKind() == BuiltinType::ObjCClass;
+ return false;
+ }
+ bool isObjCQualifiedId() const { return !qual_empty() && isObjCId(); }
+ bool isObjCQualifiedClass() const { return !qual_empty() && isObjCClass(); }
+
+ /// Gets the interface declaration for this object type, if the base type
+ /// really is an interface.
+ ObjCInterfaceDecl *getInterface() const;
+
+ typedef ObjCProtocolDecl * const *qual_iterator;
+
+ qual_iterator qual_begin() const { return getProtocolStorage(); }
+ qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); }
+
+ bool qual_empty() const { return getNumProtocols() == 0; }
+
+ /// getNumProtocols - Return the number of qualifying protocols in this
+ /// interface type, or 0 if there are none.
+ unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
+
+ /// \brief Fetch a protocol by index.
+ ObjCProtocolDecl *getProtocol(unsigned I) const {
+ assert(I < getNumProtocols() && "Out-of-range protocol access");
+ return qual_begin()[I];
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCObject ||
+ T->getTypeClass() == ObjCInterface;
+ }
+ static bool classof(const ObjCObjectType *) { return true; }
+};
+
+/// ObjCObjectTypeImpl - A class providing a concrete implementation
+/// of ObjCObjectType, so as to not increase the footprint of
+/// ObjCInterfaceType. Code outside of ASTContext and the core type
+/// system should not reference this type.
+class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
+ // If anyone adds fields here, ObjCObjectType::getProtocolStorage()
+ // will need to be modified.
+
+ ObjCObjectTypeImpl(QualType Canonical, QualType Base,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols)
+ : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Base,
+ ObjCProtocolDecl *const *protocols,
+ unsigned NumProtocols);
+};
+
+inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
+ return reinterpret_cast<ObjCProtocolDecl**>(
+ static_cast<ObjCObjectTypeImpl*>(this) + 1);
+}
+
+/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
+/// object oriented design. They basically correspond to C++ classes. There
+/// are two kinds of interface types, normal interfaces like "NSString" and
+/// qualified interfaces, which are qualified with a protocol list like
+/// "NSString<NSCopyable, NSAmazing>".
+///
+/// ObjCInterfaceType guarantees the following properties when considered
+/// as a subtype of its superclass, ObjCObjectType:
+/// - There are no protocol qualifiers. To reinforce this, code which
+/// tries to invoke the protocol methods via an ObjCInterfaceType will
+/// fail to compile.
+/// - It is its own base type. That is, if T is an ObjCInterfaceType*,
+/// T->getBaseType() == QualType(T, 0).
+class ObjCInterfaceType : public ObjCObjectType {
+ ObjCInterfaceDecl *Decl;
+
+ ObjCInterfaceType(const ObjCInterfaceDecl *D)
+ : ObjCObjectType(Nonce_ObjCInterface),
+ Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ /// getDecl - Get the declaration of this interface.
+ ObjCInterfaceDecl *getDecl() const { return Decl; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCInterface;
+ }
+ static bool classof(const ObjCInterfaceType *) { return true; }
+
+ // Nonsense to "hide" certain members of ObjCObjectType within this
+ // class. People asking for protocols on an ObjCInterfaceType are
+ // not going to get what they want: ObjCInterfaceTypes are
+ // guaranteed to have no protocols.
+ enum {
+ qual_iterator,
+ qual_begin,
+ qual_end,
+ getNumProtocols,
+ getProtocol
+ };
+};
+
+inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
+ if (const ObjCInterfaceType *T =
+ getBaseType()->getAs<ObjCInterfaceType>())
+ return T->getDecl();
+ return 0;
+}
+
+/// ObjCObjectPointerType - Used to represent a pointer to an
+/// Objective C object. These are constructed from pointer
+/// declarators when the pointee type is an ObjCObjectType (or sugar
+/// for one). In addition, the 'id' and 'Class' types are typedefs
+/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>'
+/// are translated into these.
+///
+/// Pointers to pointers to Objective C objects are still PointerTypes;
+/// only the first level of pointer gets it own type implementation.
+class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+
+ ObjCObjectPointerType(QualType Canonical, QualType Pointee)
+ : Type(ObjCObjectPointer, Canonical, false, false, false),
+ PointeeType(Pointee) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ /// getPointeeType - Gets the type pointed to by this ObjC pointer.
+ /// The result will always be an ObjCObjectType or sugar thereof.
+ QualType getPointeeType() const { return PointeeType; }
+
+ /// getObjCObjectType - Gets the type pointed to by this ObjC
+ /// pointer. This method always returns non-null.
+ ///
+ /// This method is equivalent to getPointeeType() except that
+ /// it discards any typedefs (or other sugar) between this
+ /// type and the "outermost" object type. So for:
+ /// @class A; @protocol P; @protocol Q;
+ /// typedef A<P> AP;
+ /// typedef A A1;
+ /// typedef A1<P> A1P;
+ /// typedef A1P<Q> A1PQ;
+ /// For 'A*', getObjectType() will return 'A'.
+ /// For 'A<P>*', getObjectType() will return 'A<P>'.
+ /// For 'AP*', getObjectType() will return 'A<P>'.
+ /// For 'A1*', getObjectType() will return 'A'.
+ /// For 'A1<P>*', getObjectType() will return 'A1<P>'.
+ /// For 'A1P*', getObjectType() will return 'A1<P>'.
+ /// For 'A1PQ*', getObjectType() will return 'A1<Q>', because
+ /// adding protocols to a protocol-qualified base discards the
+ /// old qualifiers (for now). But if it didn't, getObjectType()
+ /// would return 'A1P<Q>' (and we'd have to make iterating over
+ /// qualifiers more complicated).
+ const ObjCObjectType *getObjectType() const {
+ return PointeeType->castAs<ObjCObjectType>();
+ }
+
+ /// getInterfaceType - If this pointer points to an Objective C
+ /// @interface type, gets the type for that interface. Any protocol
+ /// qualifiers on the interface are ignored.
+ ///
+ /// \return null if the base type for this pointer is 'id' or 'Class'
+ const ObjCInterfaceType *getInterfaceType() const {
+ return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>();
+ }
+
+ /// getInterfaceDecl - If this pointer points to an Objective @interface
+ /// type, gets the declaration for that interface.
+ ///
+ /// \return null if the base type for this pointer is 'id' or 'Class'
+ ObjCInterfaceDecl *getInterfaceDecl() const {
+ return getObjectType()->getInterface();
+ }
+
+ /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if
+ /// its object type is the primitive 'id' type with no protocols.
+ bool isObjCIdType() const {
+ return getObjectType()->isObjCUnqualifiedId();
+ }
+
+ /// isObjCClassType - True if this is equivalent to the 'Class' type,
+ /// i.e. if its object tive is the primitive 'Class' type with no protocols.
+ bool isObjCClassType() const {
+ return getObjectType()->isObjCUnqualifiedClass();
+ }
+
+ /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
+ /// non-empty set of protocols.
+ bool isObjCQualifiedIdType() const {
+ return getObjectType()->isObjCQualifiedId();
+ }
+
+ /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for
+ /// some non-empty set of protocols.
+ bool isObjCQualifiedClassType() const {
+ return getObjectType()->isObjCQualifiedClass();
+ }
+
+ /// An iterator over the qualifiers on the object type. Provided
+ /// for convenience. This will always iterate over the full set of
+ /// protocols on a type, not just those provided directly.
+ typedef ObjCObjectType::qual_iterator qual_iterator;
+
+ qual_iterator qual_begin() const {
+ return getObjectType()->qual_begin();
+ }
+ qual_iterator qual_end() const {
+ return getObjectType()->qual_end();
+ }
+ bool qual_empty() const { return getObjectType()->qual_empty(); }
+
+ /// getNumProtocols - Return the number of qualifying protocols on
+ /// the object type.
+ unsigned getNumProtocols() const {
+ return getObjectType()->getNumProtocols();
+ }
+
+ /// \brief Retrieve a qualifying protocol by index on the object
+ /// type.
+ ObjCProtocolDecl *getProtocol(unsigned I) const {
+ return getObjectType()->getProtocol(I);
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCObjectPointer;
+ }
+ static bool classof(const ObjCObjectPointerType *) { return true; }
+};
+
+/// A qualifier set is used to build a set of qualifiers.
+class QualifierCollector : public Qualifiers {
+public:
+ QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {}
+
+ /// Collect any qualifiers on the given type and return an
+ /// unqualified type. The qualifiers are assumed to be consistent
+ /// with those already in the type.
+ const Type *strip(QualType type) {
+ addFastQualifiers(type.getLocalFastQualifiers());
+ if (!type.hasLocalNonFastQualifiers())
+ return type.getTypePtrUnsafe();
+
+ const ExtQuals *extQuals = type.getExtQualsUnsafe();
+ addConsistentQualifiers(extQuals->getQualifiers());
+ return extQuals->getBaseType();
+ }
+
+ /// Apply the collected qualifiers to the given type.
+ QualType apply(const ASTContext &Context, QualType QT) const;
+
+ /// Apply the collected qualifiers to the given type.
+ QualType apply(const ASTContext &Context, const Type* T) const;
+};
+
+
+// Inline function definitions.
+
+inline const Type *QualType::getTypePtr() const {
+ return getCommonPtr()->BaseType;
+}
+
+inline const Type *QualType::getTypePtrOrNull() const {
+ return (isNull() ? 0 : getCommonPtr()->BaseType);
+}
+
+inline SplitQualType QualType::split() const {
+ if (!hasLocalNonFastQualifiers())
+ return SplitQualType(getTypePtrUnsafe(),
+ Qualifiers::fromFastMask(getLocalFastQualifiers()));
+
+ const ExtQuals *eq = getExtQualsUnsafe();
+ Qualifiers qs = eq->getQualifiers();
+ qs.addFastQualifiers(getLocalFastQualifiers());
+ return SplitQualType(eq->getBaseType(), qs);
+}
+
+inline Qualifiers QualType::getLocalQualifiers() const {
+ Qualifiers Quals;
+ if (hasLocalNonFastQualifiers())
+ Quals = getExtQualsUnsafe()->getQualifiers();
+ Quals.addFastQualifiers(getLocalFastQualifiers());
+ return Quals;
+}
+
+inline Qualifiers QualType::getQualifiers() const {
+ Qualifiers quals = getCommonPtr()->CanonicalType.getLocalQualifiers();
+ quals.addFastQualifiers(getLocalFastQualifiers());
+ return quals;
+}
+
+inline unsigned QualType::getCVRQualifiers() const {
+ unsigned cvr = getCommonPtr()->CanonicalType.getLocalCVRQualifiers();
+ cvr |= getLocalCVRQualifiers();
+ return cvr;
+}
+
+inline QualType QualType::getCanonicalType() const {
+ QualType canon = getCommonPtr()->CanonicalType;
+ return canon.withFastQualifiers(getLocalFastQualifiers());
+}
+
+inline bool QualType::isCanonical() const {
+ return getTypePtr()->isCanonicalUnqualified();
+}
+
+inline bool QualType::isCanonicalAsParam() const {
+ if (!isCanonical()) return false;
+ if (hasLocalQualifiers()) return false;
+
+ const Type *T = getTypePtr();
+ if (T->isVariablyModifiedType() && T->hasSizedVLAType())
+ return false;
+
+ return !isa<FunctionType>(T) && !isa<ArrayType>(T);
+}
+
+inline bool QualType::isConstQualified() const {
+ return isLocalConstQualified() ||
+ getCommonPtr()->CanonicalType.isLocalConstQualified();
+}
+
+inline bool QualType::isRestrictQualified() const {
+ return isLocalRestrictQualified() ||
+ getCommonPtr()->CanonicalType.isLocalRestrictQualified();
+}
+
+
+inline bool QualType::isVolatileQualified() const {
+ return isLocalVolatileQualified() ||
+ getCommonPtr()->CanonicalType.isLocalVolatileQualified();
+}
+
+inline bool QualType::hasQualifiers() const {
+ return hasLocalQualifiers() ||
+ getCommonPtr()->CanonicalType.hasLocalQualifiers();
+}
+
+inline QualType QualType::getUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return QualType(getTypePtr(), 0);
+
+ return QualType(getSplitUnqualifiedTypeImpl(*this).first, 0);
+}
+
+inline SplitQualType QualType::getSplitUnqualifiedType() const {
+ if (!getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers())
+ return split();
+
+ return getSplitUnqualifiedTypeImpl(*this);
+}
+
+inline void QualType::removeLocalConst() {
+ removeLocalFastQualifiers(Qualifiers::Const);
+}
+
+inline void QualType::removeLocalRestrict() {
+ removeLocalFastQualifiers(Qualifiers::Restrict);
+}
+
+inline void QualType::removeLocalVolatile() {
+ removeLocalFastQualifiers(Qualifiers::Volatile);
+}
+
+inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
+ assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits");
+ assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask);
+
+ // Fast path: we don't need to touch the slow qualifiers.
+ removeLocalFastQualifiers(Mask);
+}
+
+/// getAddressSpace - Return the address space of this type.
+inline unsigned QualType::getAddressSpace() const {
+ return getQualifiers().getAddressSpace();
+}
+
+/// getObjCGCAttr - Return the gc attribute of this type.
+inline Qualifiers::GC QualType::getObjCGCAttr() const {
+ return getQualifiers().getObjCGCAttr();
+}
+
+inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
+ if (const PointerType *PT = t.getAs<PointerType>()) {
+ if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>())
+ return FT->getExtInfo();
+ } else if (const FunctionType *FT = t.getAs<FunctionType>())
+ return FT->getExtInfo();
+
+ return FunctionType::ExtInfo();
+}
+
+inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) {
+ return getFunctionExtInfo(*t);
+}
+
+/// \brief Determine whether this set of qualifiers is a superset of the given
+/// set of qualifiers.
+inline bool Qualifiers::isSupersetOf(Qualifiers Other) const {
+ return Mask != Other.Mask && (Mask | Other.Mask) == Mask;
+}
+
+/// isMoreQualifiedThan - Determine whether this type is more
+/// qualified than the Other type. For example, "const volatile int"
+/// is more qualified than "const int", "volatile int", and
+/// "int". However, it is not more qualified than "const volatile
+/// int".
+inline bool QualType::isMoreQualifiedThan(QualType other) const {
+ Qualifiers myQuals = getQualifiers();
+ Qualifiers otherQuals = other.getQualifiers();
+ return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals));
+}
+
+/// isAtLeastAsQualifiedAs - Determine whether this type is at last
+/// as qualified as the Other type. For example, "const volatile
+/// int" is at least as qualified as "const int", "volatile int",
+/// "int", and "const volatile int".
+inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
+ return getQualifiers().compatiblyIncludes(other.getQualifiers());
+}
+
+/// getNonReferenceType - If Type is a reference type (e.g., const
+/// int&), returns the type that the reference refers to ("const
+/// int"). Otherwise, returns the type itself. This routine is used
+/// throughout Sema to implement C++ 5p6:
+///
+/// If an expression initially has the type "reference to T" (8.3.2,
+/// 8.5.3), the type is adjusted to "T" prior to any further
+/// analysis, the expression designates the object or function
+/// denoted by the reference, and the expression is an lvalue.
+inline QualType QualType::getNonReferenceType() const {
+ if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>())
+ return RefType->getPointeeType();
+ else
+ return *this;
+}
+
+inline bool Type::isFunctionType() const {
+ return isa<FunctionType>(CanonicalType);
+}
+inline bool Type::isPointerType() const {
+ return isa<PointerType>(CanonicalType);
+}
+inline bool Type::isAnyPointerType() const {
+ return isPointerType() || isObjCObjectPointerType();
+}
+inline bool Type::isBlockPointerType() const {
+ return isa<BlockPointerType>(CanonicalType);
+}
+inline bool Type::isReferenceType() const {
+ return isa<ReferenceType>(CanonicalType);
+}
+inline bool Type::isLValueReferenceType() const {
+ return isa<LValueReferenceType>(CanonicalType);
+}
+inline bool Type::isRValueReferenceType() const {
+ return isa<RValueReferenceType>(CanonicalType);
+}
+inline bool Type::isFunctionPointerType() const {
+ if (const PointerType *T = getAs<PointerType>())
+ return T->getPointeeType()->isFunctionType();
+ else
+ return false;
+}
+inline bool Type::isMemberPointerType() const {
+ return isa<MemberPointerType>(CanonicalType);
+}
+inline bool Type::isMemberFunctionPointerType() const {
+ if (const MemberPointerType* T = getAs<MemberPointerType>())
+ return T->isMemberFunctionPointer();
+ else
+ return false;
+}
+inline bool Type::isMemberDataPointerType() const {
+ if (const MemberPointerType* T = getAs<MemberPointerType>())
+ return T->isMemberDataPointer();
+ else
+ return false;
+}
+inline bool Type::isArrayType() const {
+ return isa<ArrayType>(CanonicalType);
+}
+inline bool Type::isConstantArrayType() const {
+ return isa<ConstantArrayType>(CanonicalType);
+}
+inline bool Type::isIncompleteArrayType() const {
+ return isa<IncompleteArrayType>(CanonicalType);
+}
+inline bool Type::isVariableArrayType() const {
+ return isa<VariableArrayType>(CanonicalType);
+}
+inline bool Type::isDependentSizedArrayType() const {
+ return isa<DependentSizedArrayType>(CanonicalType);
+}
+inline bool Type::isBuiltinType() const {
+ return isa<BuiltinType>(CanonicalType);
+}
+inline bool Type::isRecordType() const {
+ return isa<RecordType>(CanonicalType);
+}
+inline bool Type::isEnumeralType() const {
+ return isa<EnumType>(CanonicalType);
+}
+inline bool Type::isAnyComplexType() const {
+ return isa<ComplexType>(CanonicalType);
+}
+inline bool Type::isVectorType() const {
+ return isa<VectorType>(CanonicalType);
+}
+inline bool Type::isExtVectorType() const {
+ return isa<ExtVectorType>(CanonicalType);
+}
+inline bool Type::isObjCObjectPointerType() const {
+ return isa<ObjCObjectPointerType>(CanonicalType);
+}
+inline bool Type::isObjCObjectType() const {
+ return isa<ObjCObjectType>(CanonicalType);
+}
+inline bool Type::isObjCObjectOrInterfaceType() const {
+ return isa<ObjCInterfaceType>(CanonicalType) ||
+ isa<ObjCObjectType>(CanonicalType);
+}
+
+inline bool Type::isObjCQualifiedIdType() const {
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ return OPT->isObjCQualifiedIdType();
+ return false;
+}
+inline bool Type::isObjCQualifiedClassType() const {
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ return OPT->isObjCQualifiedClassType();
+ return false;
+}
+inline bool Type::isObjCIdType() const {
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ return OPT->isObjCIdType();
+ return false;
+}
+inline bool Type::isObjCClassType() const {
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ return OPT->isObjCClassType();
+ return false;
+}
+inline bool Type::isObjCSelType() const {
+ if (const PointerType *OPT = getAs<PointerType>())
+ return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel);
+ return false;
+}
+inline bool Type::isObjCBuiltinType() const {
+ return isObjCIdType() || isObjCClassType() || isObjCSelType();
+}
+inline bool Type::isTemplateTypeParmType() const {
+ return isa<TemplateTypeParmType>(CanonicalType);
+}
+
+inline bool Type::isSpecificBuiltinType(unsigned K) const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ if (BT->getKind() == (BuiltinType::Kind) K)
+ return true;
+ return false;
+}
+
+inline bool Type::isPlaceholderType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ return BT->isPlaceholderType();
+ return false;
+}
+
+/// \brief Determines whether this is a type for which one can define
+/// an overloaded operator.
+inline bool Type::isOverloadableType() const {
+ return isDependentType() || isRecordType() || isEnumeralType();
+}
+
+inline bool Type::hasPointerRepresentation() const {
+ return (isPointerType() || isReferenceType() || isBlockPointerType() ||
+ isObjCObjectPointerType() || isNullPtrType());
+}
+
+inline bool Type::hasObjCPointerRepresentation() const {
+ return isObjCObjectPointerType();
+}
+
+inline const Type *Type::getBaseElementTypeUnsafe() const {
+ const Type *type = this;
+ while (const ArrayType *arrayType = type->getAsArrayTypeUnsafe())
+ type = arrayType->getElementType().getTypePtr();
+ return type;
+}
+
+/// Insertion operator for diagnostics. This allows sending QualType's into a
+/// diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ QualType T) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
+ Diagnostic::ak_qualtype);
+ return DB;
+}
+
+/// Insertion operator for partial diagnostics. This allows sending QualType's
+/// into a diagnostic with <<.
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ QualType T) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
+ Diagnostic::ak_qualtype);
+ return PD;
+}
+
+// Helper class template that is used by Type::getAs to ensure that one does
+// not try to look through a qualified type to get to an array type.
+template<typename T,
+ bool isArrayType = (llvm::is_same<T, ArrayType>::value ||
+ llvm::is_base_of<ArrayType, T>::value)>
+struct ArrayType_cannot_be_used_with_getAs { };
+
+template<typename T>
+struct ArrayType_cannot_be_used_with_getAs<T, true>;
+
+/// Member-template getAs<specific type>'.
+template <typename T> const T *Type::getAs() const {
+ ArrayType_cannot_be_used_with_getAs<T> at;
+ (void)at;
+
+ // If this is directly a T type, return it.
+ if (const T *Ty = dyn_cast<T>(this))
+ return Ty;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<T>(CanonicalType))
+ return 0;
+
+ // If this is a typedef for the type, strip the typedef off without
+ // losing all typedef information.
+ return cast<T>(getUnqualifiedDesugaredType());
+}
+
+inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
+ // If this is directly an array type, return it.
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this))
+ return arr;
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<ArrayType>(CanonicalType))
+ return 0;
+
+ // If this is a typedef for the type, strip the typedef off without
+ // losing all typedef information.
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
+template <typename T> const T *Type::castAs() const {
+ ArrayType_cannot_be_used_with_getAs<T> at;
+ (void) at;
+
+ assert(isa<T>(CanonicalType));
+ if (const T *ty = dyn_cast<T>(this)) return ty;
+ return cast<T>(getUnqualifiedDesugaredType());
+}
+
+inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
+ assert(isa<ArrayType>(CanonicalType));
+ if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr;
+ return cast<ArrayType>(getUnqualifiedDesugaredType());
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
new file mode 100644
index 0000000..c7f5ee7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
@@ -0,0 +1,1629 @@
+//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- 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 TypeLoc interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPELOC_H
+#define LLVM_CLANG_AST_TYPELOC_H
+
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/Basic/Specifiers.h"
+
+namespace clang {
+ class ASTContext;
+ class ParmVarDecl;
+ class TypeSourceInfo;
+ class UnqualTypeLoc;
+
+// Predeclare all the type nodes.
+#define ABSTRACT_TYPELOC(Class, Base)
+#define TYPELOC(Class, Base) \
+ class Class##TypeLoc;
+#include "clang/AST/TypeLocNodes.def"
+
+/// \brief Base wrapper for a particular "section" of type source info.
+///
+/// A client should use the TypeLoc subclasses through cast/dyn_cast in order to
+/// get at the actual information.
+class TypeLoc {
+protected:
+ // The correctness of this relies on the property that, for Type *Ty,
+ // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty
+ const void *Ty;
+ void *Data;
+
+public:
+ /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum,
+ /// except it also defines a Qualified enum that corresponds to the
+ /// QualifiedLoc class.
+ enum TypeLocClass {
+#define ABSTRACT_TYPE(Class, Base)
+#define TYPE(Class, Base) \
+ Class = Type::Class,
+#include "clang/AST/TypeNodes.def"
+ Qualified
+ };
+
+ TypeLoc() : Ty(0), Data(0) { }
+ TypeLoc(QualType ty, void *opaqueData)
+ : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
+ TypeLoc(const Type *ty, void *opaqueData)
+ : Ty(ty), Data(opaqueData) { }
+
+ TypeLocClass getTypeLocClass() const {
+ if (getType().hasLocalQualifiers()) return Qualified;
+ return (TypeLocClass) getType()->getTypeClass();
+ }
+
+ bool isNull() const { return !Ty; }
+ operator bool() const { return Ty; }
+
+ /// \brief Returns the size of type source info data block for the given type.
+ static unsigned getFullDataSizeForType(QualType Ty);
+
+ /// \brief Get the type for which this source info wrapper provides
+ /// information.
+ QualType getType() const {
+ return QualType::getFromOpaquePtr(Ty);
+ }
+
+ const Type *getTypePtr() const {
+ return QualType::getFromOpaquePtr(Ty).getTypePtr();
+ }
+
+ /// \brief Get the pointer where source information is stored.
+ void *getOpaqueData() const {
+ return Data;
+ }
+
+ /// \brief Get the begin source location.
+ SourceLocation getBeginLoc() const;
+
+ /// \brief Get the end source location.
+ SourceLocation getEndLoc() const;
+
+ /// \brief Get the full source range.
+ SourceRange getSourceRange() const {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+
+ /// \brief Get the local source range.
+ SourceRange getLocalSourceRange() const {
+ return getLocalSourceRangeImpl(*this);
+ }
+
+ /// \brief Returns the size of the type source info data block.
+ unsigned getFullDataSize() const {
+ return getFullDataSizeForType(getType());
+ }
+
+ /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+ /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
+ TypeLoc getNextTypeLoc() const {
+ return getNextTypeLocImpl(*this);
+ }
+
+ /// \brief Skips past any qualifiers, if this is qualified.
+ UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header
+
+ TypeLoc IgnoreParens() const {
+ if (isa<ParenTypeLoc>(this))
+ return IgnoreParensImpl(*this);
+ return *this;
+ }
+
+ /// \brief Initializes this to state that every location in this
+ /// type is the given location.
+ ///
+ /// This method exists to provide a simple transition for code that
+ /// relies on location-less types.
+ void initialize(ASTContext &Context, SourceLocation Loc) const {
+ initializeImpl(Context, *this, Loc);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type.
+ void initializeFullCopy(TypeLoc Other) const {
+ assert(getType() == Other.getType());
+ size_t Size = getFullDataSize();
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ }
+
+ /// \brief Initializes this by copying its information from another
+ /// TypeLoc of the same type. The given size must be the full data
+ /// size.
+ void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+ assert(getType() == Other.getType());
+ assert(getFullDataSize() == Size);
+ memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ }
+
+ friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {
+ return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data;
+ }
+
+ friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) {
+ return !(LHS == RHS);
+ }
+
+ static bool classof(const TypeLoc *TL) { return true; }
+
+private:
+ static void initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc);
+ static TypeLoc getNextTypeLocImpl(TypeLoc TL);
+ static TypeLoc IgnoreParensImpl(TypeLoc TL);
+ static SourceRange getLocalSourceRangeImpl(TypeLoc TL);
+};
+
+/// \brief Return the TypeLoc for a type source info.
+inline TypeLoc TypeSourceInfo::getTypeLoc() const {
+ return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
+}
+
+/// \brief Wrapper of type source information for a type with
+/// no direct qualifiers.
+class UnqualTypeLoc : public TypeLoc {
+public:
+ UnqualTypeLoc() {}
+ UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {}
+
+ const Type *getTypePtr() const {
+ return reinterpret_cast<const Type*>(Ty);
+ }
+
+ TypeLocClass getTypeLocClass() const {
+ return (TypeLocClass) getTypePtr()->getTypeClass();
+ }
+
+ static bool classof(const TypeLoc *TL) {
+ return !TL->getType().hasLocalQualifiers();
+ }
+ static bool classof(const UnqualTypeLoc *TL) { return true; }
+};
+
+/// \brief Wrapper of type source information for a type with
+/// non-trivial direct qualifiers.
+///
+/// Currently, we intentionally do not provide source location for
+/// type qualifiers.
+class QualifiedTypeLoc : public TypeLoc {
+public:
+ SourceRange getLocalSourceRange() const {
+ return SourceRange();
+ }
+
+ UnqualTypeLoc getUnqualifiedLoc() const {
+ return UnqualTypeLoc(getTypePtr(), Data);
+ }
+
+ /// Initializes the local data of this type source info block to
+ /// provide no information.
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ // do nothing
+ }
+
+ TypeLoc getNextTypeLoc() const {
+ return getUnqualifiedLoc();
+ }
+
+ /// \brief Returns the size of the type source info data block that is
+ /// specific to this type.
+ unsigned getLocalDataSize() const {
+ // In fact, we don't currently preserve any location information
+ // for qualifiers.
+ return 0;
+ }
+
+ /// \brief Returns the size of the type source info data block.
+ unsigned getFullDataSize() const {
+ return getLocalDataSize() +
+ getFullDataSizeForType(getType().getLocalUnqualifiedType());
+ }
+
+ static bool classof(const TypeLoc *TL) {
+ return TL->getType().hasLocalQualifiers();
+ }
+ static bool classof(const QualifiedTypeLoc *TL) { return true; }
+};
+
+inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
+ if (isa<QualifiedTypeLoc>(this))
+ return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc();
+ return cast<UnqualTypeLoc>(*this);
+}
+
+/// A metaprogramming base class for TypeLoc classes which correspond
+/// to a particular Type subclass. It is accepted for a single
+/// TypeLoc class to correspond to multiple Type classes.
+///
+/// \param Base a class from which to derive
+/// \param Derived the class deriving from this one
+/// \param TypeClass the concrete Type subclass associated with this
+/// location type
+/// \param LocalData the structure type of local location data for
+/// this type
+///
+/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
+/// else the world will end.
+///
+/// TypeLocs with non-constant amounts of local data should override
+/// getExtraLocalDataSize(); getExtraLocalData() will then point to
+/// this extra memory.
+///
+/// TypeLocs with an inner type should define
+/// QualType getInnerType() const
+/// and getInnerTypeLoc() will then point to this inner type's
+/// location data.
+///
+/// A word about hierarchies: this template is not designed to be
+/// derived from multiple times in a hierarchy. It is also not
+/// designed to be used for classes where subtypes might provide
+/// different amounts of source information. It should be subclassed
+/// only at the deepest portion of the hierarchy where all children
+/// have identical source information; if that's an abstract type,
+/// then further descendents should inherit from
+/// InheritingConcreteTypeLoc instead.
+template <class Base, class Derived, class TypeClass, class LocalData>
+class ConcreteTypeLoc : public Base {
+
+ const Derived *asDerived() const {
+ return static_cast<const Derived*>(this);
+ }
+
+public:
+ unsigned getLocalDataSize() const {
+ return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
+ }
+ // Give a default implementation that's useful for leaf types.
+ unsigned getFullDataSize() const {
+ return asDerived()->getLocalDataSize() + getInnerTypeSize();
+ }
+
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
+ static bool classof(const TypeLoc *TL) {
+ return Derived::classofType(TL->getTypePtr());
+ }
+ static bool classof(const UnqualTypeLoc *TL) {
+ return Derived::classofType(TL->getTypePtr());
+ }
+ static bool classof(const Derived *TL) {
+ return true;
+ }
+
+ TypeLoc getNextTypeLoc() const {
+ return getNextTypeLoc(asDerived()->getInnerType());
+ }
+
+ const TypeClass *getTypePtr() const {
+ return cast<TypeClass>(Base::getTypePtr());
+ }
+
+protected:
+ unsigned getExtraLocalDataSize() const {
+ return 0;
+ }
+
+ LocalData *getLocalData() const {
+ return static_cast<LocalData*>(Base::Data);
+ }
+
+ /// Gets a pointer past the Info structure; useful for classes with
+ /// local data that can't be captured in the Info (e.g. because it's
+ /// of variable size).
+ void *getExtraLocalData() const {
+ return getLocalData() + 1;
+ }
+
+ void *getNonLocalData() const {
+ return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
+ }
+
+ struct HasNoInnerType {};
+ HasNoInnerType getInnerType() const { return HasNoInnerType(); }
+
+ TypeLoc getInnerTypeLoc() const {
+ return TypeLoc(asDerived()->getInnerType(), getNonLocalData());
+ }
+
+private:
+ unsigned getInnerTypeSize() const {
+ return getInnerTypeSize(asDerived()->getInnerType());
+ }
+
+ unsigned getInnerTypeSize(HasNoInnerType _) const {
+ return 0;
+ }
+
+ unsigned getInnerTypeSize(QualType _) const {
+ return getInnerTypeLoc().getFullDataSize();
+ }
+
+ TypeLoc getNextTypeLoc(HasNoInnerType _) const {
+ return TypeLoc();
+ }
+
+ TypeLoc getNextTypeLoc(QualType T) const {
+ return TypeLoc(T, getNonLocalData());
+ }
+};
+
+/// A metaprogramming class designed for concrete subtypes of abstract
+/// types where all subtypes share equivalently-structured source
+/// information. See the note on ConcreteTypeLoc.
+template <class Base, class Derived, class TypeClass>
+class InheritingConcreteTypeLoc : public Base {
+public:
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
+ static bool classof(const TypeLoc *TL) {
+ return Derived::classofType(TL->getTypePtr());
+ }
+ static bool classof(const UnqualTypeLoc *TL) {
+ return Derived::classofType(TL->getTypePtr());
+ }
+ static bool classof(const Derived *TL) {
+ return true;
+ }
+
+ const TypeClass *getTypePtr() const {
+ return cast<TypeClass>(Base::getTypePtr());
+ }
+};
+
+
+struct TypeSpecLocInfo {
+ SourceLocation NameLoc;
+};
+
+/// \brief A reasonable base class for TypeLocs that correspond to
+/// types that are written as a type-specifier.
+class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ TypeSpecTypeLoc,
+ Type,
+ TypeSpecLocInfo> {
+public:
+ enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
+
+ SourceLocation getNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+ void setNameLoc(SourceLocation Loc) {
+ this->getLocalData()->NameLoc = Loc;
+ }
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getNameLoc(), getNameLoc());
+ }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setNameLoc(Loc);
+ }
+
+ static bool classof(const TypeLoc *TL);
+ static bool classof(const TypeSpecTypeLoc *TL) { return true; }
+};
+
+
+struct BuiltinLocInfo {
+ SourceLocation BuiltinLoc;
+};
+
+/// \brief Wrapper for source info for builtin types.
+class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ BuiltinTypeLoc,
+ BuiltinType,
+ BuiltinLocInfo> {
+public:
+ enum { LocalDataSize = sizeof(BuiltinLocInfo) };
+
+ SourceLocation getBuiltinLoc() const {
+ return getLocalData()->BuiltinLoc;
+ }
+ void setBuiltinLoc(SourceLocation Loc) {
+ getLocalData()->BuiltinLoc = Loc;
+ }
+
+ SourceLocation getNameLoc() const { return getBuiltinLoc(); }
+
+ WrittenBuiltinSpecs& getWrittenBuiltinSpecs() {
+ return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
+ }
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData()));
+ }
+
+ bool needsExtraLocalData() const {
+ BuiltinType::Kind bk = getTypePtr()->getKind();
+ return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128)
+ || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble)
+ || bk == BuiltinType::UChar
+ || bk == BuiltinType::SChar;
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getBuiltinLoc(), getBuiltinLoc());
+ }
+
+ TypeSpecifierSign getWrittenSignSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign);
+ else
+ return TSS_unspecified;
+ }
+ bool hasWrittenSignSpec() const {
+ return getWrittenSignSpec() != TSS_unspecified;
+ }
+ void setWrittenSignSpec(TypeSpecifierSign written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Sign = written;
+ }
+
+ TypeSpecifierWidth getWrittenWidthSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width);
+ else
+ return TSW_unspecified;
+ }
+ bool hasWrittenWidthSpec() const {
+ return getWrittenWidthSpec() != TSW_unspecified;
+ }
+ void setWrittenWidthSpec(TypeSpecifierWidth written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Width = written;
+ }
+
+ TypeSpecifierType getWrittenTypeSpec() const;
+ bool hasWrittenTypeSpec() const {
+ return getWrittenTypeSpec() != TST_unspecified;
+ }
+ void setWrittenTypeSpec(TypeSpecifierType written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().Type = written;
+ }
+
+ bool hasModeAttr() const {
+ if (needsExtraLocalData())
+ return getWrittenBuiltinSpecs().ModeAttr;
+ else
+ return false;
+ }
+ void setModeAttr(bool written) {
+ if (needsExtraLocalData())
+ getWrittenBuiltinSpecs().ModeAttr = written;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setBuiltinLoc(Loc);
+ if (needsExtraLocalData()) {
+ WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs();
+ wbs.Sign = TSS_unspecified;
+ wbs.Width = TSW_unspecified;
+ wbs.Type = TST_unspecified;
+ wbs.ModeAttr = false;
+ }
+ }
+};
+
+
+/// \brief Wrapper for source info for typedefs.
+class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TypedefTypeLoc,
+ TypedefType> {
+public:
+ TypedefDecl *getTypedefDecl() const {
+ return getTypePtr()->getDecl();
+ }
+};
+
+/// \brief Wrapper for source info for injected class names of class
+/// templates.
+class InjectedClassNameTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ InjectedClassNameTypeLoc,
+ InjectedClassNameType> {
+};
+
+/// \brief Wrapper for source info for unresolved typename using decls.
+class UnresolvedUsingTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ UnresolvedUsingTypeLoc,
+ UnresolvedUsingType> {
+public:
+ UnresolvedUsingTypenameDecl *getDecl() const {
+ return getTypePtr()->getDecl();
+ }
+};
+
+/// \brief Wrapper for source info for tag types. Note that this only
+/// records source info for the name itself; a type written 'struct foo'
+/// should be represented as an ElaboratedTypeLoc. We currently
+/// only do that when C++ is enabled because of the expense of
+/// creating an ElaboratedType node for so many type references in C.
+class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TagTypeLoc,
+ TagType> {
+public:
+ TagDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \brief Wrapper for source info for record types.
+class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
+ RecordTypeLoc,
+ RecordType> {
+public:
+ RecordDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \brief Wrapper for source info for enum types.
+class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
+ EnumTypeLoc,
+ EnumType> {
+public:
+ EnumDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \brief Wrapper for template type parameters.
+class TemplateTypeParmTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ TemplateTypeParmTypeLoc,
+ TemplateTypeParmType> {
+};
+
+/// \brief Wrapper for substituted template type parameters.
+class SubstTemplateTypeParmTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ SubstTemplateTypeParmTypeLoc,
+ SubstTemplateTypeParmType> {
+};
+
+ /// \brief Wrapper for substituted template type parameters.
+class SubstTemplateTypeParmPackTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ SubstTemplateTypeParmPackTypeLoc,
+ SubstTemplateTypeParmPackType> {
+};
+
+struct AttributedLocInfo {
+ union {
+ Expr *ExprOperand;
+
+ /// A raw SourceLocation.
+ unsigned EnumOperandLoc;
+ };
+
+ SourceRange OperandParens;
+
+ SourceLocation AttrLoc;
+};
+
+/// \brief Type source information for an attributed type.
+class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ AttributedTypeLoc,
+ AttributedType,
+ AttributedLocInfo> {
+public:
+ AttributedType::Kind getAttrKind() const {
+ return getTypePtr()->getAttrKind();
+ }
+
+ bool hasAttrExprOperand() const {
+ return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
+ getAttrKind() <= AttributedType::LastExprOperandKind);
+ }
+
+ bool hasAttrEnumOperand() const {
+ return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
+ getAttrKind() <= AttributedType::LastEnumOperandKind);
+ }
+
+ bool hasAttrOperand() const {
+ return hasAttrExprOperand() || hasAttrEnumOperand();
+ }
+
+ /// The modified type, which is generally canonically different from
+ /// the attribute type.
+ /// int main(int, char**) __attribute__((noreturn))
+ /// ~~~ ~~~~~~~~~~~~~
+ TypeLoc getModifiedLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ /// The location of the attribute name, i.e.
+ /// __attribute__((regparm(1000)))
+ /// ^~~~~~~
+ SourceLocation getAttrNameLoc() const {
+ return getLocalData()->AttrLoc;
+ }
+ void setAttrNameLoc(SourceLocation loc) {
+ getLocalData()->AttrLoc = loc;
+ }
+
+ /// The attribute's expression operand, if it has one.
+ /// void *cur_thread __attribute__((address_space(21)))
+ /// ^~
+ Expr *getAttrExprOperand() const {
+ assert(hasAttrExprOperand());
+ return getLocalData()->ExprOperand;
+ }
+ void setAttrExprOperand(Expr *e) {
+ assert(hasAttrExprOperand());
+ getLocalData()->ExprOperand = e;
+ }
+
+ /// The location of the attribute's enumerated operand, if it has one.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^~~~
+ SourceLocation getAttrEnumOperandLoc() const {
+ assert(hasAttrEnumOperand());
+ return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
+ }
+ void setAttrEnumOperandLoc(SourceLocation loc) {
+ assert(hasAttrEnumOperand());
+ getLocalData()->EnumOperandLoc = loc.getRawEncoding();
+ }
+
+ /// The location of the parentheses around the operand, if there is
+ /// an operand.
+ /// void * __attribute__((objc_gc(weak)))
+ /// ^ ^
+ SourceRange getAttrOperandParensRange() const {
+ assert(hasAttrOperand());
+ return getLocalData()->OperandParens;
+ }
+ void setAttrOperandParensRange(SourceRange range) {
+ assert(hasAttrOperand());
+ getLocalData()->OperandParens = range;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ // Note that this does *not* include the range of the attribute
+ // enclosure, e.g.:
+ // __attribute__((foo(bar)))
+ // ^~~~~~~~~~~~~~~ ~~
+ // or
+ // [[foo(bar)]]
+ // ^~ ~~
+ // That enclosure doesn't necessarily belong to a single attribute
+ // anyway.
+ SourceRange range(getAttrNameLoc());
+ if (hasAttrOperand())
+ range.setEnd(getAttrOperandParensRange().getEnd());
+ return range;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation loc) {
+ setAttrNameLoc(loc);
+ if (hasAttrExprOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrExprOperand(0);
+ } else if (hasAttrEnumOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrEnumOperandLoc(loc);
+ }
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getModifiedType();
+ }
+};
+
+
+struct ObjCProtocolListLocInfo {
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+ bool HasBaseTypeAsWritten;
+};
+
+// A helper class for defining ObjC TypeLocs that can qualified with
+// protocols.
+//
+// TypeClass basically has to be either ObjCInterfaceType or
+// ObjCObjectPointerType.
+class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ ObjCObjectTypeLoc,
+ ObjCObjectType,
+ ObjCProtocolListLocInfo> {
+ // SourceLocations are stored after Info, one for each Protocol.
+ SourceLocation *getProtocolLocArray() const {
+ return (SourceLocation*) this->getExtraLocalData();
+ }
+
+public:
+ SourceLocation getLAngleLoc() const {
+ return this->getLocalData()->LAngleLoc;
+ }
+ void setLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return this->getLocalData()->RAngleLoc;
+ }
+ void setRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumProtocols() const {
+ return this->getTypePtr()->getNumProtocols();
+ }
+
+ SourceLocation getProtocolLoc(unsigned i) const {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ return getProtocolLocArray()[i];
+ }
+ void setProtocolLoc(unsigned i, SourceLocation Loc) {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ getProtocolLocArray()[i] = Loc;
+ }
+
+ ObjCProtocolDecl *getProtocol(unsigned i) const {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ return *(this->getTypePtr()->qual_begin() + i);
+ }
+
+ bool hasBaseTypeAsWritten() const {
+ return getLocalData()->HasBaseTypeAsWritten;
+ }
+
+ void setHasBaseTypeAsWritten(bool HasBaseType) {
+ getLocalData()->HasBaseTypeAsWritten = HasBaseType;
+ }
+
+ TypeLoc getBaseLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLAngleLoc(), getRAngleLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setHasBaseTypeAsWritten(true);
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+ setProtocolLoc(i, Loc);
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return this->getNumProtocols() * sizeof(SourceLocation);
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getBaseType();
+ }
+};
+
+
+struct ObjCInterfaceLocInfo {
+ SourceLocation NameLoc;
+};
+
+/// \brief Wrapper for source info for ObjC interfaces.
+class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc,
+ ObjCInterfaceTypeLoc,
+ ObjCInterfaceType,
+ ObjCInterfaceLocInfo> {
+public:
+ ObjCInterfaceDecl *getIFaceDecl() const {
+ return getTypePtr()->getDecl();
+ }
+
+ SourceLocation getNameLoc() const {
+ return getLocalData()->NameLoc;
+ }
+
+ void setNameLoc(SourceLocation Loc) {
+ getLocalData()->NameLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getNameLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setNameLoc(Loc);
+ }
+};
+
+struct ParenLocInfo {
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+};
+
+class ParenTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
+ ParenLocInfo> {
+public:
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+
+ TypeLoc getInnerLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getInnerType();
+ }
+};
+
+
+struct PointerLikeLocInfo {
+ SourceLocation StarLoc;
+};
+
+/// A base class for
+template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
+class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
+ TypeClass, LocalData> {
+public:
+ SourceLocation getSigilLoc() const {
+ return this->getLocalData()->StarLoc;
+ }
+ void setSigilLoc(SourceLocation Loc) {
+ this->getLocalData()->StarLoc = Loc;
+ }
+
+ TypeLoc getPointeeLoc() const {
+ return this->getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getSigilLoc(), getSigilLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getPointeeType();
+ }
+};
+
+
+/// \brief Wrapper for source info for pointers.
+class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
+ PointerType> {
+public:
+ SourceLocation getStarLoc() const {
+ return getSigilLoc();
+ }
+ void setStarLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+
+/// \brief Wrapper for source info for block pointers.
+class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
+ BlockPointerType> {
+public:
+ SourceLocation getCaretLoc() const {
+ return getSigilLoc();
+ }
+ void setCaretLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+
+/// \brief Wrapper for source info for member pointers.
+class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
+ MemberPointerType> {
+public:
+ SourceLocation getStarLoc() const {
+ return getSigilLoc();
+ }
+ void setStarLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+/// Wraps an ObjCPointerType with source location information.
+class ObjCObjectPointerTypeLoc :
+ public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
+ ObjCObjectPointerType> {
+public:
+ SourceLocation getStarLoc() const {
+ return getSigilLoc();
+ }
+
+ void setStarLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+
+class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
+ ReferenceType> {
+public:
+ QualType getInnerType() const {
+ return getTypePtr()->getPointeeTypeAsWritten();
+ }
+};
+
+class LValueReferenceTypeLoc :
+ public InheritingConcreteTypeLoc<ReferenceTypeLoc,
+ LValueReferenceTypeLoc,
+ LValueReferenceType> {
+public:
+ SourceLocation getAmpLoc() const {
+ return getSigilLoc();
+ }
+ void setAmpLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+class RValueReferenceTypeLoc :
+ public InheritingConcreteTypeLoc<ReferenceTypeLoc,
+ RValueReferenceTypeLoc,
+ RValueReferenceType> {
+public:
+ SourceLocation getAmpAmpLoc() const {
+ return getSigilLoc();
+ }
+ void setAmpAmpLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+};
+
+
+struct FunctionLocInfo {
+ SourceLocation LParenLoc, RParenLoc;
+ bool TrailingReturn;
+};
+
+/// \brief Wrapper for source info for functions.
+class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ FunctionTypeLoc,
+ FunctionType,
+ FunctionLocInfo> {
+public:
+ SourceLocation getLParenLoc() const {
+ return getLocalData()->LParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ getLocalData()->LParenLoc = Loc;
+ }
+
+ SourceLocation getRParenLoc() const {
+ return getLocalData()->RParenLoc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ getLocalData()->RParenLoc = Loc;
+ }
+
+ bool getTrailingReturn() const {
+ return getLocalData()->TrailingReturn;
+ }
+ void setTrailingReturn(bool Trailing) {
+ getLocalData()->TrailingReturn = Trailing;
+ }
+
+ // ParmVarDecls* are stored after Info, one for each argument.
+ ParmVarDecl **getParmArray() const {
+ return (ParmVarDecl**) getExtraLocalData();
+ }
+
+ unsigned getNumArgs() const {
+ if (isa<FunctionNoProtoType>(getTypePtr()))
+ return 0;
+ return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
+ }
+ ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
+ void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
+
+ TypeLoc getResultLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ setTrailingReturn(false);
+ for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
+ setArg(i, NULL);
+ }
+
+ /// \brief Returns the size of the type source info data block that is
+ /// specific to this type.
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(ParmVarDecl*);
+ }
+
+ QualType getInnerType() const { return getTypePtr()->getResultType(); }
+};
+
+class FunctionProtoTypeLoc :
+ public InheritingConcreteTypeLoc<FunctionTypeLoc,
+ FunctionProtoTypeLoc,
+ FunctionProtoType> {
+};
+
+class FunctionNoProtoTypeLoc :
+ public InheritingConcreteTypeLoc<FunctionTypeLoc,
+ FunctionNoProtoTypeLoc,
+ FunctionNoProtoType> {
+};
+
+
+struct ArrayLocInfo {
+ SourceLocation LBracketLoc, RBracketLoc;
+ Expr *Size;
+};
+
+/// \brief Wrapper for source info for arrays.
+class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ ArrayTypeLoc,
+ ArrayType,
+ ArrayLocInfo> {
+public:
+ SourceLocation getLBracketLoc() const {
+ return getLocalData()->LBracketLoc;
+ }
+ void setLBracketLoc(SourceLocation Loc) {
+ getLocalData()->LBracketLoc = Loc;
+ }
+
+ SourceLocation getRBracketLoc() const {
+ return getLocalData()->RBracketLoc;
+ }
+ void setRBracketLoc(SourceLocation Loc) {
+ getLocalData()->RBracketLoc = Loc;
+ }
+
+ SourceRange getBracketsRange() const {
+ return SourceRange(getLBracketLoc(), getRBracketLoc());
+ }
+
+ Expr *getSizeExpr() const {
+ return getLocalData()->Size;
+ }
+ void setSizeExpr(Expr *Size) {
+ getLocalData()->Size = Size;
+ }
+
+ TypeLoc getElementLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLBracketLoc(), getRBracketLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLBracketLoc(Loc);
+ setRBracketLoc(Loc);
+ setSizeExpr(NULL);
+ }
+
+ QualType getInnerType() const { return getTypePtr()->getElementType(); }
+};
+
+class ConstantArrayTypeLoc :
+ public InheritingConcreteTypeLoc<ArrayTypeLoc,
+ ConstantArrayTypeLoc,
+ ConstantArrayType> {
+};
+
+class IncompleteArrayTypeLoc :
+ public InheritingConcreteTypeLoc<ArrayTypeLoc,
+ IncompleteArrayTypeLoc,
+ IncompleteArrayType> {
+};
+
+class DependentSizedArrayTypeLoc :
+ public InheritingConcreteTypeLoc<ArrayTypeLoc,
+ DependentSizedArrayTypeLoc,
+ DependentSizedArrayType> {
+
+};
+
+class VariableArrayTypeLoc :
+ public InheritingConcreteTypeLoc<ArrayTypeLoc,
+ VariableArrayTypeLoc,
+ VariableArrayType> {
+};
+
+
+// Location information for a TemplateName. Rudimentary for now.
+struct TemplateNameLocInfo {
+ SourceLocation NameLoc;
+};
+
+struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+};
+
+class TemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ TemplateSpecializationTypeLoc,
+ TemplateSpecializationType,
+ TemplateSpecializationLocInfo> {
+public:
+ SourceLocation getLAngleLoc() const {
+ return getLocalData()->LAngleLoc;
+ }
+ void setLAngleLoc(SourceLocation Loc) {
+ getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return getLocalData()->RAngleLoc;
+ }
+ void setRAngleLoc(SourceLocation Loc) {
+ getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumArgs() const {
+ return getTypePtr()->getNumArgs();
+ }
+ void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
+ getArgInfos()[i] = AI;
+ }
+ TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
+ return getArgInfos()[i];
+ }
+
+ TemplateArgumentLoc getArgLoc(unsigned i) const {
+ return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ return getLocalData()->NameLoc;
+ }
+ void setTemplateNameLoc(SourceLocation Loc) {
+ getLocalData()->NameLoc = Loc;
+ }
+
+ /// \brief - Copy the location information from the given info.
+ void copy(TemplateSpecializationTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+
+ // We're potentially copying Expr references here. We don't
+ // bother retaining them because TypeSourceInfos live forever, so
+ // as long as the Expr was retained when originally written into
+ // the TypeLoc, we're okay.
+ memcpy(Data, Loc.Data, size);
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getTemplateNameLoc(), getRAngleLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ setTemplateNameLoc(Loc);
+ initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(),
+ getArgInfos(), Loc);
+ }
+
+ static void initializeArgLocs(ASTContext &Context, unsigned NumArgs,
+ const TemplateArgument *Args,
+ TemplateArgumentLocInfo *ArgInfos,
+ SourceLocation Loc);
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+private:
+ TemplateArgumentLocInfo *getArgInfos() const {
+ return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
+ }
+};
+
+//===----------------------------------------------------------------------===//
+//
+// All of these need proper implementations.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: size expression and attribute locations (or keyword if we
+// ever fully support altivec syntax).
+class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ VectorTypeLoc,
+ VectorType> {
+};
+
+// FIXME: size expression and attribute locations.
+class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
+ ExtVectorTypeLoc,
+ ExtVectorType> {
+};
+
+// FIXME: attribute locations.
+// For some reason, this isn't a subtype of VectorType.
+class DependentSizedExtVectorTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DependentSizedExtVectorTypeLoc,
+ DependentSizedExtVectorType> {
+};
+
+// FIXME: location of the '_Complex' keyword.
+class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ ComplexTypeLoc,
+ ComplexType> {
+};
+
+struct TypeofLocInfo {
+ SourceLocation TypeofLoc;
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+};
+
+struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
+};
+
+struct TypeOfTypeLocInfo : public TypeofLocInfo {
+ TypeSourceInfo* UnderlyingTInfo;
+};
+
+template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
+class TypeofLikeTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
+public:
+ SourceLocation getTypeofLoc() const {
+ return this->getLocalData()->TypeofLoc;
+ }
+ void setTypeofLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeofLoc = Loc;
+ }
+
+ SourceLocation getLParenLoc() const {
+ return this->getLocalData()->LParenLoc;
+ }
+ void setLParenLoc(SourceLocation Loc) {
+ this->getLocalData()->LParenLoc = Loc;
+ }
+
+ SourceLocation getRParenLoc() const {
+ return this->getLocalData()->RParenLoc;
+ }
+ void setRParenLoc(SourceLocation Loc) {
+ this->getLocalData()->RParenLoc = Loc;
+ }
+
+ SourceRange getParensRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+ void setParensRange(SourceRange range) {
+ setLParenLoc(range.getBegin());
+ setRParenLoc(range.getEnd());
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setTypeofLoc(Loc);
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+};
+
+class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
+ TypeOfExprType,
+ TypeOfExprTypeLocInfo> {
+public:
+ Expr* getUnderlyingExpr() const {
+ return getTypePtr()->getUnderlyingExpr();
+ }
+ // Reimplemented to account for GNU/C++ extension
+ // typeof unary-expression
+ // where there are no parentheses.
+ SourceRange getLocalSourceRange() const;
+};
+
+class TypeOfTypeLoc
+ : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
+public:
+ QualType getUnderlyingType() const {
+ return this->getTypePtr()->getUnderlyingType();
+ }
+ TypeSourceInfo* getUnderlyingTInfo() const {
+ return this->getLocalData()->UnderlyingTInfo;
+ }
+ void setUnderlyingTInfo(TypeSourceInfo* TI) const {
+ this->getLocalData()->UnderlyingTInfo = TI;
+ }
+};
+
+// FIXME: location of the 'decltype' and parens.
+class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DecltypeTypeLoc,
+ DecltypeType> {
+};
+
+class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ AutoTypeLoc,
+ AutoType> {
+};
+
+struct ElaboratedLocInfo {
+ SourceLocation KeywordLoc;
+ SourceRange QualifierRange;
+};
+
+class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ ElaboratedTypeLoc,
+ ElaboratedType,
+ ElaboratedLocInfo> {
+public:
+ SourceLocation getKeywordLoc() const {
+ return this->getLocalData()->KeywordLoc;
+ }
+ void setKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->KeywordLoc = Loc;
+ }
+
+ SourceRange getQualifierRange() const {
+ return this->getLocalData()->QualifierRange;
+ }
+ void setQualifierRange(SourceRange Range) {
+ this->getLocalData()->QualifierRange = Range;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (getKeywordLoc().isValid())
+ if (getQualifierRange().getEnd().isValid())
+ return SourceRange(getKeywordLoc(), getQualifierRange().getEnd());
+ else
+ return SourceRange(getKeywordLoc());
+ else
+ return getQualifierRange();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKeywordLoc(Loc);
+ setQualifierRange(SourceRange(Loc));
+ }
+
+ TypeLoc getNamedTypeLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getNamedType();
+ }
+
+ void copy(ElaboratedTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+};
+
+// This is exactly the structure of an ElaboratedTypeLoc whose inner
+// type is some sort of TypeDeclTypeLoc.
+struct DependentNameLocInfo : ElaboratedLocInfo {
+ SourceLocation NameLoc;
+};
+
+class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ DependentNameTypeLoc,
+ DependentNameType,
+ DependentNameLocInfo> {
+public:
+ SourceLocation getKeywordLoc() const {
+ return this->getLocalData()->KeywordLoc;
+ }
+ void setKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->KeywordLoc = Loc;
+ }
+
+ SourceRange getQualifierRange() const {
+ return this->getLocalData()->QualifierRange;
+ }
+ void setQualifierRange(SourceRange Range) {
+ this->getLocalData()->QualifierRange = Range;
+ }
+
+ SourceLocation getNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+ void setNameLoc(SourceLocation Loc) {
+ this->getLocalData()->NameLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (getKeywordLoc().isValid())
+ return SourceRange(getKeywordLoc(), getNameLoc());
+ else
+ return SourceRange(getQualifierRange().getBegin(), getNameLoc());
+ }
+
+ void copy(DependentNameTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKeywordLoc(Loc);
+ setQualifierRange(SourceRange(Loc));
+ setNameLoc(Loc);
+ }
+};
+
+// This is exactly the structure of an ElaboratedTypeLoc whose inner
+// type is some sort of TemplateSpecializationTypeLoc.
+struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+ // followed by a TemplateArgumentLocInfo[]
+};
+
+class DependentTemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ DependentTemplateSpecializationTypeLoc,
+ DependentTemplateSpecializationType,
+ DependentTemplateSpecializationLocInfo> {
+public:
+ SourceLocation getKeywordLoc() const {
+ return this->getLocalData()->KeywordLoc;
+ }
+ void setKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->KeywordLoc = Loc;
+ }
+
+ SourceRange getQualifierRange() const {
+ return this->getLocalData()->QualifierRange;
+ }
+ void setQualifierRange(SourceRange Range) {
+ this->getLocalData()->QualifierRange = Range;
+ }
+
+ SourceLocation getNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+ void setNameLoc(SourceLocation Loc) {
+ this->getLocalData()->NameLoc = Loc;
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return this->getLocalData()->LAngleLoc;
+ }
+ void setLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return this->getLocalData()->RAngleLoc;
+ }
+ void setRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumArgs() const {
+ return getTypePtr()->getNumArgs();
+ }
+
+ void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
+ getArgInfos()[i] = AI;
+ }
+ TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
+ return getArgInfos()[i];
+ }
+
+ TemplateArgumentLoc getArgLoc(unsigned i) const {
+ return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (getKeywordLoc().isValid())
+ return SourceRange(getKeywordLoc(), getRAngleLoc());
+ else
+ return SourceRange(getQualifierRange().getBegin(), getRAngleLoc());
+ }
+
+ void copy(DependentTemplateSpecializationTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKeywordLoc(Loc);
+ setQualifierRange(SourceRange(Loc));
+ setNameLoc(Loc);
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
+ getTypePtr()->getArgs(),
+ getArgInfos(), Loc);
+ }
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+private:
+ TemplateArgumentLocInfo *getArgInfos() const {
+ return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
+ }
+};
+
+
+struct PackExpansionTypeLocInfo {
+ SourceLocation EllipsisLoc;
+};
+
+class PackExpansionTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc,
+ PackExpansionType, PackExpansionTypeLocInfo> {
+public:
+ SourceLocation getEllipsisLoc() const {
+ return this->getLocalData()->EllipsisLoc;
+ }
+
+ void setEllipsisLoc(SourceLocation Loc) {
+ this->getLocalData()->EllipsisLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getEllipsisLoc(), getEllipsisLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setEllipsisLoc(Loc);
+ }
+
+ TypeLoc getPatternLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getPattern();
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def
new file mode 100644
index 0000000..4590e48
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLocNodes.def
@@ -0,0 +1,41 @@
+//===-- TypeLocNodes.def - Metadata about TypeLoc wrappers ------*- 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 TypeLoc info database. Each node is
+// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc")
+// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc
+// are associated
+//
+// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is
+// provided, there will be exactly one of these, Qualified.
+//
+// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass.
+//
+// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UNQUAL_TYPELOC
+# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base)
+#endif
+
+#ifndef ABSTRACT_TYPELOC
+# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base)
+#endif
+
+TYPELOC(Qualified, TypeLoc)
+#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc)
+#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc)
+#include "clang/AST/TypeNodes.def"
+
+#undef DECLARATOR_TYPELOC
+#undef TYPESPEC_TYPELOC
+#undef ABSTRACT_TYPELOC
+#undef UNQUAL_TYPELOC
+#undef TYPELOC
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h
new file mode 100644
index 0000000..50fc439
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLocVisitor.h
@@ -0,0 +1,62 @@
+//===--- TypeLocVisitor.h - Visitor for TypeLoc subclasses ------*- 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 TypeLocVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_TYPELOCVISITOR_H
+#define LLVM_CLANG_AST_TYPELOCVISITOR_H
+
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeVisitor.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+#define DISPATCH(CLASSNAME) \
+ return static_cast<ImplClass*>(this)-> \
+ Visit##CLASSNAME(cast<CLASSNAME>(TyLoc))
+
+template<typename ImplClass, typename RetTy=void>
+class TypeLocVisitor {
+public:
+ RetTy Visit(TypeLoc TyLoc) {
+ switch (TyLoc.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+ }
+ llvm_unreachable("unexpected type loc class!");
+ }
+
+ RetTy Visit(UnqualTypeLoc TyLoc) {
+ switch (TyLoc.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+ }
+ llvm_unreachable("unexpected type loc class!");
+ }
+
+#define TYPELOC(CLASS, PARENT) \
+ RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ DISPATCH(PARENT); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+
+ RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_TYPELOCVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
new file mode 100644
index 0000000..b2591cc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
@@ -0,0 +1,125 @@
+//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- 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 AST type info database. Each type node is
+// enumerated by providing its name (e.g., "Builtin" or "Enum") and
+// base class (e.g., "Type" or "TagType"). Depending on where in the
+// abstract syntax tree the type will show up, the enumeration uses
+// one of four different macros:
+//
+// TYPE(Class, Base) - A type that can show up anywhere in the AST,
+// and might be dependent, canonical, or non-canonical. All clients
+// will need to understand these types.
+//
+// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
+// the type hierarchy but has no concrete instances.
+//
+// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
+// anywhere in the AST but will never be a part of a canonical
+// type. Clients that only need to deal with canonical types
+// (ignoring, e.g., typedefs and other type alises used for
+// pretty-printing) can ignore these types.
+//
+// DEPENDENT_TYPE(Class, Base) - A type that will only show up
+// within a C++ template that has not been instantiated, e.g., a
+// type that is always dependent. Clients that do not need to deal
+// with uninstantiated C++ templates can ignore these types.
+//
+// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
+// is non-canonical unless it is dependent. Defaults to TYPE because
+// it is neither reliably dependent nor reliably non-canonical.
+//
+// There is a sixth macro, independent of the others. Most clients
+// will not need to use it.
+//
+// LEAF_TYPE(Class) - A type that never has inner types. Clients
+// which can operate on such types more efficiently may wish to do so.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ABSTRACT_TYPE
+# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+#ifndef NON_CANONICAL_TYPE
+# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+#ifndef DEPENDENT_TYPE
+# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
+# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+TYPE(Builtin, Type)
+TYPE(Complex, Type)
+TYPE(Pointer, Type)
+TYPE(BlockPointer, Type)
+ABSTRACT_TYPE(Reference, Type)
+TYPE(LValueReference, ReferenceType)
+TYPE(RValueReference, ReferenceType)
+TYPE(MemberPointer, Type)
+ABSTRACT_TYPE(Array, Type)
+TYPE(ConstantArray, ArrayType)
+TYPE(IncompleteArray, ArrayType)
+TYPE(VariableArray, ArrayType)
+DEPENDENT_TYPE(DependentSizedArray, ArrayType)
+DEPENDENT_TYPE(DependentSizedExtVector, Type)
+TYPE(Vector, Type)
+TYPE(ExtVector, VectorType)
+ABSTRACT_TYPE(Function, Type)
+TYPE(FunctionProto, FunctionType)
+TYPE(FunctionNoProto, FunctionType)
+DEPENDENT_TYPE(UnresolvedUsing, Type)
+NON_CANONICAL_TYPE(Paren, Type)
+NON_CANONICAL_TYPE(Typedef, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
+ABSTRACT_TYPE(Tag, Type)
+TYPE(Record, TagType)
+TYPE(Enum, TagType)
+NON_CANONICAL_TYPE(Elaborated, Type)
+NON_CANONICAL_TYPE(Attributed, Type)
+DEPENDENT_TYPE(TemplateTypeParm, Type)
+NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
+DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
+DEPENDENT_TYPE(InjectedClassName, Type)
+DEPENDENT_TYPE(DependentName, Type)
+DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
+DEPENDENT_TYPE(PackExpansion, Type)
+TYPE(ObjCObject, Type)
+TYPE(ObjCInterface, ObjCObjectType)
+TYPE(ObjCObjectPointer, Type)
+
+#ifdef LAST_TYPE
+LAST_TYPE(ObjCObjectPointer)
+#undef LAST_TYPE
+#endif
+
+// These types are always leaves in the type hierarchy.
+#ifdef LEAF_TYPE
+LEAF_TYPE(Enum)
+LEAF_TYPE(Builtin)
+LEAF_TYPE(Record)
+LEAF_TYPE(InjectedClassName)
+LEAF_TYPE(ObjCInterface)
+LEAF_TYPE(TemplateTypeParm)
+#undef LEAF_TYPE
+#endif
+
+#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
+#undef DEPENDENT_TYPE
+#undef NON_CANONICAL_TYPE
+#undef ABSTRACT_TYPE
+#undef TYPE
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
new file mode 100644
index 0000000..7cf0d5e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
@@ -0,0 +1,77 @@
+//===-------------- TypeOrdering.h - Total ordering for types -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a function objects and specializations that
+// allow QualType values to be sorted, used in std::maps, std::sets,
+// llvm::DenseMaps, and llvm::DenseSets.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TYPE_ORDERING_H
+#define LLVM_CLANG_TYPE_ORDERING_H
+
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+#include <functional>
+
+namespace clang {
+
+/// QualTypeOrdering - Function object that provides a total ordering
+/// on QualType values.
+struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
+ bool operator()(QualType T1, QualType T2) const {
+ return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
+ }
+};
+
+}
+
+namespace llvm {
+ template<class> struct DenseMapInfo;
+
+ template<> struct DenseMapInfo<clang::QualType> {
+ static inline clang::QualType getEmptyKey() { return clang::QualType(); }
+
+ static inline clang::QualType getTombstoneKey() {
+ using clang::QualType;
+ return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+ }
+
+ static unsigned getHashValue(clang::QualType Val) {
+ return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+ ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+ }
+
+ static bool isEqual(clang::QualType LHS, clang::QualType RHS) {
+ return LHS == RHS;
+ }
+ };
+
+ template<> struct DenseMapInfo<clang::CanQualType> {
+ static inline clang::CanQualType getEmptyKey() {
+ return clang::CanQualType();
+ }
+
+ static inline clang::CanQualType getTombstoneKey() {
+ using clang::CanQualType;
+ return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+ }
+
+ static unsigned getHashValue(clang::CanQualType Val) {
+ return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+ ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+ }
+
+ static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
+ return LHS == RHS;
+ }
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
new file mode 100644
index 0000000..c52926b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
@@ -0,0 +1,53 @@
+//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- 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 TypeVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPEVISITOR_H
+#define LLVM_CLANG_AST_TYPEVISITOR_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+#define DISPATCH(CLASS) \
+ return static_cast<ImplClass*>(this)-> \
+ Visit##CLASS(static_cast<const CLASS*>(T))
+
+template<typename ImplClass, typename RetTy=void>
+class TypeVisitor {
+public:
+ RetTy Visit(const Type *T) {
+ // Top switch stmt: dispatch to VisitFooType for each FooType.
+ switch (T->getTypeClass()) {
+ default: assert(0 && "Unknown type class!");
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit method, fall
+ // back on superclass.
+#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
+ DISPATCH(PARENT); \
+}
+#include "clang/AST/TypeNodes.def"
+
+ // Base case, ignore it. :)
+ RetTy VisitType(const Type*) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
new file mode 100644
index 0000000..a548b0b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
@@ -0,0 +1,186 @@
+//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the UnresolvedSet class, which is used to store
+// collections of declarations in the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H
+#define LLVM_CLANG_AST_UNRESOLVEDSET_H
+
+#include <iterator>
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/DeclAccessPair.h"
+
+namespace clang {
+
+/// The iterator over UnresolvedSets. Serves as both the const and
+/// non-const iterator.
+class UnresolvedSetIterator {
+private:
+ typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy;
+ typedef DeclsTy::iterator IteratorTy;
+
+ IteratorTy ir;
+
+ friend class UnresolvedSetImpl;
+ friend class OverloadExpr;
+ explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
+ explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
+ ir(const_cast<DeclsTy::iterator>(ir)) {}
+
+ IteratorTy getIterator() const { return ir; }
+
+public:
+ UnresolvedSetIterator() {}
+
+ typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
+ typedef NamedDecl *value_type;
+ typedef NamedDecl **pointer;
+ typedef NamedDecl *reference;
+ typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
+
+ NamedDecl *getDecl() const { return ir->getDecl(); }
+ AccessSpecifier getAccess() const { return ir->getAccess(); }
+ void setAccess(AccessSpecifier AS) { ir->setAccess(AS); }
+ DeclAccessPair getPair() const { return *ir; }
+
+ NamedDecl *operator*() const { return getDecl(); }
+
+ UnresolvedSetIterator &operator++() { ++ir; return *this; }
+ UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
+ UnresolvedSetIterator &operator--() { --ir; return *this; }
+ UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
+
+ UnresolvedSetIterator &operator+=(difference_type d) {
+ ir += d; return *this;
+ }
+ UnresolvedSetIterator operator+(difference_type d) const {
+ return UnresolvedSetIterator(ir + d);
+ }
+ UnresolvedSetIterator &operator-=(difference_type d) {
+ ir -= d; return *this;
+ }
+ UnresolvedSetIterator operator-(difference_type d) const {
+ return UnresolvedSetIterator(ir - d);
+ }
+ value_type operator[](difference_type d) const { return *(*this + d); }
+
+ difference_type operator-(const UnresolvedSetIterator &o) const {
+ return ir - o.ir;
+ }
+
+ bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
+ bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
+ bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
+ bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
+ bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
+ bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
+};
+
+/// UnresolvedSet - A set of unresolved declarations.
+class UnresolvedSetImpl {
+ typedef UnresolvedSetIterator::DeclsTy DeclsTy;
+
+ // Don't allow direct construction, and only permit subclassing by
+ // UnresolvedSet.
+private:
+ template <unsigned N> friend class UnresolvedSet;
+ UnresolvedSetImpl() {}
+ UnresolvedSetImpl(const UnresolvedSetImpl &) {}
+
+public:
+ // We don't currently support assignment through this iterator, so we might
+ // as well use the same implementation twice.
+ typedef UnresolvedSetIterator iterator;
+ typedef UnresolvedSetIterator const_iterator;
+
+ iterator begin() { return iterator(decls().begin()); }
+ iterator end() { return iterator(decls().end()); }
+
+ const_iterator begin() const { return const_iterator(decls().begin()); }
+ const_iterator end() const { return const_iterator(decls().end()); }
+
+ void addDecl(NamedDecl *D) {
+ addDecl(D, AS_none);
+ }
+
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ decls().push_back(DeclAccessPair::make(D, AS));
+ }
+
+ /// Replaces the given declaration with the new one, once.
+ ///
+ /// \return true if the set changed
+ bool replace(const NamedDecl* Old, NamedDecl *New) {
+ for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I)
+ if (I->getDecl() == Old)
+ return (I->setDecl(New), true);
+ return false;
+ }
+
+ /// Replaces the declaration at the given iterator with the new one,
+ /// preserving the original access bits.
+ void replace(iterator I, NamedDecl *New) {
+ I.ir->setDecl(New);
+ }
+
+ void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
+ I.ir->set(New, AS);
+ }
+
+ void erase(unsigned I) {
+ decls()[I] = decls().back();
+ decls().pop_back();
+ }
+
+ void erase(iterator I) {
+ *I.ir = decls().back();
+ decls().pop_back();
+ }
+
+ void setAccess(iterator I, AccessSpecifier AS) {
+ I.ir->setAccess(AS);
+ }
+
+ void clear() { decls().clear(); }
+ void set_size(unsigned N) { decls().set_size(N); }
+
+ bool empty() const { return decls().empty(); }
+ unsigned size() const { return decls().size(); }
+
+ void append(iterator I, iterator E) {
+ decls().append(I.ir, E.ir);
+ }
+
+ DeclAccessPair &operator[](unsigned I) { return decls()[I]; }
+ const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; }
+
+private:
+ // These work because the only permitted subclass is UnresolvedSetImpl
+
+ DeclsTy &decls() {
+ return *reinterpret_cast<DeclsTy*>(this);
+ }
+ const DeclsTy &decls() const {
+ return *reinterpret_cast<const DeclsTy*>(this);
+ }
+};
+
+/// A set of unresolved declarations
+template <unsigned InlineCapacity> class UnresolvedSet :
+ public UnresolvedSetImpl {
+ llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls;
+};
+
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h b/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h
new file mode 100644
index 0000000..534d4d4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/UsuallyTinyPtrVector.h
@@ -0,0 +1,114 @@
+//===-- UsuallyTinyPtrVector.h - Pointer vector 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 UsuallyTinyPtrVector class, which is a vector that
+// optimizes the case where there is only one element.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
+#define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
+
+#include <vector>
+
+namespace clang {
+
+/// \brief A vector class template that is optimized for storing a single
+/// pointer element.
+template<typename T>
+class UsuallyTinyPtrVector {
+ /// \brief Storage for the vector.
+ ///
+ /// When the low bit is zero, this is a T *. When the
+ /// low bit is one, this is a std::vector<T *> *.
+ mutable uintptr_t Storage;
+
+ typedef std::vector<T*> vector_type;
+
+public:
+ UsuallyTinyPtrVector() : Storage(0) { }
+ explicit UsuallyTinyPtrVector(T *Element)
+ : Storage(reinterpret_cast<uintptr_t>(Element)) { }
+
+ bool empty() const { return !Storage; }
+
+ typedef const T **iterator;
+ iterator begin() const;
+ iterator end() const;
+ size_t size() const;
+
+ void push_back(T *Method);
+ void Destroy();
+};
+
+template<typename T>
+typename UsuallyTinyPtrVector<T>::iterator
+UsuallyTinyPtrVector<T>::begin() const {
+ if ((Storage & 0x01) == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front();
+}
+
+template<typename T>
+typename UsuallyTinyPtrVector<T>::iterator
+UsuallyTinyPtrVector<T>::end() const {
+ if ((Storage & 0x01) == 0) {
+ if (Storage == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ return reinterpret_cast<iterator>(&Storage) + 1;
+ }
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front() + Vec->size();
+}
+
+template<typename T>
+size_t UsuallyTinyPtrVector<T>::size() const {
+ if ((Storage & 0x01) == 0)
+ return (Storage == 0) ? 0 : 1;
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return Vec->size();
+}
+
+template<typename T>
+void UsuallyTinyPtrVector<T>::push_back(T *Element) {
+ if (Storage == 0) {
+ // 0 -> 1 element.
+ Storage = reinterpret_cast<uintptr_t>(Element);
+ return;
+ }
+
+ vector_type *Vec;
+ if ((Storage & 0x01) == 0) {
+ // 1 -> 2 elements. Allocate a new vector and push the element into that
+ // vector.
+ Vec = new vector_type;
+ Vec->push_back(reinterpret_cast<T *>(Storage));
+ Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
+ } else
+ Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ // Add the new element to the vector.
+ Vec->push_back(Element);
+}
+
+template<typename T>
+void UsuallyTinyPtrVector<T>::Destroy() {
+ if (Storage & 0x01)
+ delete reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ Storage = 0;
+}
+
+}
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
new file mode 100644
index 0000000..069ead3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
@@ -0,0 +1,610 @@
+//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs for analyzing the format strings of printf, fscanf,
+// and friends.
+//
+// The structure of format strings for fprintf are described in C99 7.19.6.1.
+//
+// The structure of format strings for fscanf are described in C99 7.19.6.2.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FORMAT_H
+#define LLVM_CLANG_FORMAT_H
+
+#include "clang/AST/CanonicalType.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+/// Common components of both fprintf and fscanf format strings.
+namespace analyze_format_string {
+
+/// Class representing optional flags with location and representation
+/// information.
+class OptionalFlag {
+public:
+ OptionalFlag(const char *Representation)
+ : representation(Representation), flag(false) {}
+ bool isSet() { return flag; }
+ void set() { flag = true; }
+ void clear() { flag = false; }
+ void setPosition(const char *position) {
+ assert(position);
+ this->position = position;
+ }
+ const char *getPosition() const {
+ assert(position);
+ return position;
+ }
+ const char *toString() const { return representation; }
+
+ // Overloaded operators for bool like qualities
+ operator bool() const { return flag; }
+ OptionalFlag& operator=(const bool &rhs) {
+ flag = rhs;
+ return *this; // Return a reference to myself.
+ }
+private:
+ const char *representation;
+ const char *position;
+ bool flag;
+};
+
+/// Represents the length modifier in a format string in scanf/printf.
+class LengthModifier {
+public:
+ enum Kind {
+ None,
+ AsChar, // 'hh'
+ AsShort, // 'h'
+ AsLong, // 'l'
+ AsLongLong, // 'll', 'q' (BSD, deprecated)
+ AsIntMax, // 'j'
+ AsSizeT, // 'z'
+ AsPtrDiff, // 't'
+ AsLongDouble, // 'L'
+ AsWideChar = AsLong // for '%ls', only makes sense for printf
+ };
+
+ LengthModifier()
+ : Position(0), kind(None) {}
+ LengthModifier(const char *pos, Kind k)
+ : Position(pos), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ unsigned getLength() const {
+ switch (kind) {
+ default:
+ return 1;
+ case AsLongLong:
+ case AsChar:
+ return 2;
+ case None:
+ return 0;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+
+ const char *toString() const;
+
+private:
+ const char *Position;
+ Kind kind;
+};
+
+class ConversionSpecifier {
+public:
+ enum Kind {
+ InvalidSpecifier = 0,
+ // C99 conversion specifiers.
+ cArg,
+ dArg,
+ iArg,
+ IntArgBeg = cArg, IntArgEnd = iArg,
+
+ oArg,
+ uArg,
+ xArg,
+ XArg,
+ UIntArgBeg = oArg, UIntArgEnd = XArg,
+
+ fArg,
+ FArg,
+ eArg,
+ EArg,
+ gArg,
+ GArg,
+ aArg,
+ AArg,
+ DoubleArgBeg = fArg, DoubleArgEnd = AArg,
+
+ sArg,
+ pArg,
+ nArg,
+ PercentArg,
+ CArg,
+ SArg,
+
+ // ** Printf-specific **
+
+ // Objective-C specific specifiers.
+ ObjCObjArg, // '@'
+ ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+
+ // FreeBSD specific specifiers
+ bArg,
+ DArg,
+ rArg,
+
+ // GlibC specific specifiers.
+ PrintErrno, // 'm'
+
+ PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+
+ // ** Scanf-specific **
+ ScanListArg, // '['
+ ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
+ };
+
+ ConversionSpecifier(bool isPrintf)
+ : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
+
+ ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
+ : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ llvm::StringRef getCharacters() const {
+ return llvm::StringRef(getStart(), getLength());
+ }
+
+ bool consumesDataArgument() const {
+ switch (kind) {
+ case PrintErrno:
+ assert(IsPrintf);
+ case PercentArg:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+ unsigned getLength() const {
+ return EndScanList ? EndScanList - Position : 1;
+ }
+
+ const char *toString() const;
+
+ bool isPrintfKind() const { return IsPrintf; }
+
+protected:
+ bool IsPrintf;
+ const char *Position;
+ const char *EndScanList;
+ Kind kind;
+};
+
+class ArgTypeResult {
+public:
+ enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
+ CStrTy, WCStrTy, WIntTy };
+private:
+ const Kind K;
+ QualType T;
+ ArgTypeResult(bool) : K(InvalidTy) {}
+public:
+ ArgTypeResult(Kind k = UnknownTy) : K(k) {}
+ ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
+ ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
+
+ static ArgTypeResult Invalid() { return ArgTypeResult(true); }
+
+ bool isValid() const { return K != InvalidTy; }
+
+ const QualType *getSpecificType() const {
+ return K == SpecificTy ? &T : 0;
+ }
+
+ bool matchesType(ASTContext &C, QualType argTy) const;
+
+ bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
+
+ QualType getRepresentativeType(ASTContext &C) const;
+};
+
+class OptionalAmount {
+public:
+ enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
+
+ OptionalAmount(HowSpecified howSpecified,
+ unsigned amount,
+ const char *amountStart,
+ unsigned amountLength,
+ bool usesPositionalArg)
+ : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
+ UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
+
+ OptionalAmount(bool valid = true)
+ : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
+ UsesPositionalArg(0), UsesDotPrefix(0) {}
+
+ bool isInvalid() const {
+ return hs == Invalid;
+ }
+
+ HowSpecified getHowSpecified() const { return hs; }
+ void setHowSpecified(HowSpecified h) { hs = h; }
+
+ bool hasDataArgument() const { return hs == Arg; }
+
+ unsigned getArgIndex() const {
+ assert(hasDataArgument());
+ return amt;
+ }
+
+ unsigned getConstantAmount() const {
+ assert(hs == Constant);
+ return amt;
+ }
+
+ const char *getStart() const {
+ // We include the . character if it is given.
+ return start - UsesDotPrefix;
+ }
+
+ unsigned getConstantLength() const {
+ assert(hs == Constant);
+ return length + UsesDotPrefix;
+ }
+
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ void toString(llvm::raw_ostream &os) const;
+
+ bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
+ unsigned getPositionalArgIndex() const {
+ assert(hasDataArgument());
+ return amt + 1;
+ }
+
+ bool usesDotPrefix() const { return UsesDotPrefix; }
+ void setUsesDotPrefix() { UsesDotPrefix = true; }
+
+private:
+ const char *start;
+ unsigned length;
+ HowSpecified hs;
+ unsigned amt;
+ bool UsesPositionalArg : 1;
+ bool UsesDotPrefix;
+};
+
+
+class FormatSpecifier {
+protected:
+ LengthModifier LM;
+ OptionalAmount FieldWidth;
+ ConversionSpecifier CS;
+ /// Positional arguments, an IEEE extension:
+ /// IEEE Std 1003.1, 2004 Edition
+ /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
+ bool UsesPositionalArg;
+ unsigned argIndex;
+public:
+ FormatSpecifier(bool isPrintf)
+ : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
+
+ void setLengthModifier(LengthModifier lm) {
+ LM = lm;
+ }
+
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ void setArgIndex(unsigned i) {
+ argIndex = i;
+ }
+
+ unsigned getArgIndex() const {
+ return argIndex;
+ }
+
+ unsigned getPositionalArgIndex() const {
+ return argIndex + 1;
+ }
+
+ const LengthModifier &getLengthModifier() const {
+ return LM;
+ }
+
+ const OptionalAmount &getFieldWidth() const {
+ return FieldWidth;
+ }
+
+ void setFieldWidth(const OptionalAmount &Amt) {
+ FieldWidth = Amt;
+ }
+
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ bool hasValidLengthModifier() const;
+};
+
+} // end analyze_format_string namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fprintf format strings.
+
+namespace analyze_printf {
+
+class PrintfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ PrintfConversionSpecifier()
+ : ConversionSpecifier(true, 0, InvalidSpecifier) {}
+
+ PrintfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(true, pos, k) {}
+
+ bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
+ bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
+ bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
+ bool isDoubleArg() const { return kind >= DoubleArgBeg &&
+ kind <= DoubleArgBeg; }
+ unsigned getLength() const {
+ // Conversion specifiers currently only are represented by
+ // single characters, but we be flexible.
+ return 1;
+ }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::ArgTypeResult;
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
+ OptionalFlag IsLeftJustified; // '-'
+ OptionalFlag HasPlusPrefix; // '+'
+ OptionalFlag HasSpacePrefix; // ' '
+ OptionalFlag HasAlternativeForm; // '#'
+ OptionalFlag HasLeadingZeroes; // '0'
+ OptionalAmount Precision;
+public:
+ PrintfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ true),
+ HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
+ HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+
+ static PrintfSpecifier Parse(const char *beg, const char *end);
+
+ // Methods for incrementally constructing the PrintfSpecifier.
+ void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
+ CS = cs;
+ }
+ void setHasThousandsGrouping(const char *position) {
+ HasThousandsGrouping = true;
+ HasThousandsGrouping.setPosition(position);
+ }
+ void setIsLeftJustified(const char *position) {
+ IsLeftJustified = true;
+ IsLeftJustified.setPosition(position);
+ }
+ void setHasPlusPrefix(const char *position) {
+ HasPlusPrefix = true;
+ HasPlusPrefix.setPosition(position);
+ }
+ void setHasSpacePrefix(const char *position) {
+ HasSpacePrefix = true;
+ HasSpacePrefix.setPosition(position);
+ }
+ void setHasAlternativeForm(const char *position) {
+ HasAlternativeForm = true;
+ HasAlternativeForm.setPosition(position);
+ }
+ void setHasLeadingZeros(const char *position) {
+ HasLeadingZeroes = true;
+ HasLeadingZeroes.setPosition(position);
+ }
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ // Methods for querying the format specifier.
+
+ const PrintfConversionSpecifier &getConversionSpecifier() const {
+ return cast<PrintfConversionSpecifier>(CS);
+ }
+
+ void setPrecision(const OptionalAmount &Amt) {
+ Precision = Amt;
+ Precision.setUsesDotPrefix();
+ }
+
+ const OptionalAmount &getPrecision() const {
+ return Precision;
+ }
+
+ bool consumesDataArgument() const {
+ return getConversionSpecifier().consumesDataArgument();
+ }
+
+ /// \brief Returns the builtin type that a data argument
+ /// paired with this format specifier should have. This method
+ /// will return null if the format specifier does not have
+ /// a matching data argument or the matching argument matches
+ /// more than one type.
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ const OptionalFlag &hasThousandsGrouping() const {
+ return HasThousandsGrouping;
+ }
+ const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
+ const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
+ const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
+ const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
+ const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ /// Changes the specifier and length according to a QualType, retaining any
+ /// flags or options. Returns true on success, or false when a conversion
+ /// was not successful.
+ bool fixType(QualType QT);
+
+ void toString(llvm::raw_ostream &os) const;
+
+ // Validation methods - to check if any element results in undefined behavior
+ bool hasValidPlusPrefix() const;
+ bool hasValidAlternativeForm() const;
+ bool hasValidLeadingZeros() const;
+ bool hasValidSpacePrefix() const;
+ bool hasValidLeftJustified() const;
+ bool hasValidThousandsGroupingPrefix() const;
+
+ bool hasValidPrecision() const;
+ bool hasValidFieldWidth() const;
+};
+} // end analyze_printf namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fscanf format strings.
+
+namespace analyze_scanf {
+
+class ScanfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ ScanfConversionSpecifier()
+ : ConversionSpecifier(false, 0, InvalidSpecifier) {}
+
+ ScanfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(false, pos, k) {}
+
+ void setEndScanList(const char *pos) { EndScanList = pos; }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return !CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag SuppressAssignment; // '*'
+public:
+ ScanfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ false),
+ SuppressAssignment("*") {}
+
+ void setSuppressAssignment(const char *position) {
+ SuppressAssignment = true;
+ SuppressAssignment.setPosition(position);
+ }
+
+ const OptionalFlag &getSuppressAssignment() const {
+ return SuppressAssignment;
+ }
+
+ void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
+ CS = cs;
+ }
+
+ const ScanfConversionSpecifier &getConversionSpecifier() const {
+ return cast<ScanfConversionSpecifier>(CS);
+ }
+
+ bool consumesDataArgument() const {
+ return CS.consumesDataArgument() && !SuppressAssignment;
+ }
+
+ static ScanfSpecifier Parse(const char *beg, const char *end);
+};
+
+} // end analyze_scanf namespace
+
+//===----------------------------------------------------------------------===//
+// Parsing and processing of format strings (both fprintf and fscanf).
+
+namespace analyze_format_string {
+
+enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
+
+class FormatStringHandler {
+public:
+ FormatStringHandler() {}
+ virtual ~FormatStringHandler();
+
+ virtual void HandleNullChar(const char *nullCharacter) {}
+
+ virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
+ PositionContext p) {}
+
+ virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
+
+ virtual void HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen) {}
+
+ // Printf-specific handlers.
+
+ virtual bool HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ // Scanf-specific handlers.
+
+ virtual bool HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual void HandleIncompleteScanList(const char *start, const char *end) {}
+};
+
+bool ParsePrintfString(FormatStringHandler &H,
+ const char *beg, const char *end,
+ bool FormatExtensions);
+
+bool ParseScanfString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+} // end analyze_format_string namespace
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
new file mode 100644
index 0000000..fbbd261
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
@@ -0,0 +1,123 @@
+//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Live Variables analysis for source-level CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIVEVARIABLES_H
+#define LLVM_CLANG_LIVEVARIABLES_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+
+namespace clang {
+
+class Stmt;
+class DeclRefExpr;
+class SourceManager;
+class AnalysisContext;
+
+struct LiveVariables_ValueTypes {
+
+ struct ObserverTy;
+
+ // We keep dataflow state for declarations and block-level expressions;
+ typedef StmtDeclBitVector_Types::ValTy ValTy;
+
+ // We need to keep track of both declarations and CFGBlock-level expressions,
+ // (so that we don't explore such expressions twice). We also want
+ // to compute liveness information for block-level expressions, since these
+ // act as "temporary" values.
+
+ struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
+ ObserverTy* Observer;
+ ValTy AlwaysLive;
+ AnalysisContext *AC;
+ bool killAtAssign;
+
+ AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
+ };
+
+ //===-----------------------------------------------------===//
+ // ObserverTy - Observer for uninitialized values queries.
+ //===-----------------------------------------------------===//
+
+ struct ObserverTy {
+ virtual ~ObserverTy() {}
+
+ /// ObserveStmt - A callback invoked right before invoking the
+ /// liveness transfer function on the given statement.
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
+ const AnalysisDataTy& AD,
+ const ValTy& V) {}
+
+ virtual void ObserverKill(DeclRefExpr* DR) {}
+ };
+};
+
+class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
+ dataflow::backward_analysis_tag> {
+
+
+public:
+ typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
+
+ LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
+
+ /// IsLive - Return true if a variable is live at the end of a
+ /// specified block.
+ bool isLive(const CFGBlock* B, const VarDecl* D) const;
+
+ /// IsLive - Returns true if a variable is live at the beginning of the
+ /// the statement. This query only works if liveness information
+ /// has been recorded at the statement level (see runOnAllBlocks), and
+ /// only returns liveness information for block-level expressions.
+ bool isLive(const Stmt* S, const VarDecl* D) const;
+
+ /// IsLive - Returns true the block-level expression "value" is live
+ /// before the given block-level expression (see runOnAllBlocks).
+ bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
+
+ /// IsLive - Return true if a variable is live according to the
+ /// provided livness bitvector.
+ bool isLive(const ValTy& V, const VarDecl* D) const;
+
+ /// dumpLiveness - Print to stderr the liveness information encoded
+ /// by a specified bitvector.
+ void dumpLiveness(const ValTy& V, const SourceManager& M) const;
+
+ /// dumpBlockLiveness - Print to stderr the liveness information
+ /// associated with each basic block.
+ void dumpBlockLiveness(const SourceManager& M) const;
+
+ /// getNumDecls - Return the number of variables (declarations) that
+ /// whose liveness status is being tracked by the dataflow
+ /// analysis.
+ unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
+
+ /// IntializeValues - This routine can perform extra initialization, but
+ /// for LiveVariables this does nothing since all that logic is in
+ /// the constructor.
+ void InitializeValues(const CFG& cfg) {}
+
+ void runOnCFG(CFG& cfg);
+
+ /// runOnAllBlocks - Propagate the dataflow values once for each block,
+ /// starting from the current dataflow values. 'recordStmtValues' indicates
+ /// whether the method should store dataflow values per each individual
+ /// block-level expression.
+ void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
+ bool recordStmtValues=false);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
new file mode 100644
index 0000000..cb73850
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
@@ -0,0 +1,45 @@
+//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tracks the usage of variables in a Decl body to see if they are
+// never written to, implying that they constant. This is useful in static
+// analysis to see if a developer might have intended a variable to be const.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+class PseudoConstantAnalysis {
+public:
+ PseudoConstantAnalysis(const Stmt *DeclBody);
+ ~PseudoConstantAnalysis();
+
+ bool isPseudoConstant(const VarDecl *VD);
+ bool wasReferenced(const VarDecl *VD);
+
+private:
+ void RunAnalysis();
+ inline static const Decl *getDecl(const Expr *E);
+
+ // for storing the result of analyzed ValueDecls
+ void *NonConstantsImpl;
+ void *UsedVarsImpl;
+
+ const Stmt *DeclBody;
+ bool Analyzed;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
new file mode 100644
index 0000000..e0c84f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
@@ -0,0 +1,55 @@
+//===- ReachableCode.h -----------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A flow-sensitive, path-insensitive analysis of unreachable code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REACHABLECODE_H
+#define LLVM_CLANG_REACHABLECODE_H
+
+#include "clang/Basic/SourceLocation.h"
+
+//===----------------------------------------------------------------------===//
+// Forward declarations.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+ class BitVector;
+}
+
+namespace clang {
+ class AnalysisContext;
+ class CFGBlock;
+}
+
+//===----------------------------------------------------------------------===//
+// API.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace reachable_code {
+
+class Callback {
+public:
+ virtual ~Callback() {}
+ virtual void HandleUnreachable(SourceLocation L, SourceRange R1,
+ SourceRange R2) = 0;
+};
+
+/// ScanReachableFromBlock - Mark all blocks reachable from Start.
+/// Returns the total number of blocks that were marked reachable.
+unsigned ScanReachableFromBlock(const CFGBlock &Start,
+ llvm::BitVector &Reachable);
+
+void FindUnreachableCode(AnalysisContext &AC, Callback &CB);
+
+}} // end namespace clang::reachable_code
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
new file mode 100644
index 0000000..cd771ac
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -0,0 +1,77 @@
+//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Unintialized Values analysis,
+// a flow-sensitive analysis that detects when variable values are unintialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITVALS_H
+#define LLVM_CLANG_UNITVALS_H
+
+#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+
+namespace clang {
+
+ class BlockVarDecl;
+ class Expr;
+ class DeclRefExpr;
+ class VarDecl;
+
+/// UninitializedValues_ValueTypes - Utility class to wrap type declarations
+/// for dataflow values and dataflow analysis state for the
+/// Unitialized Values analysis.
+class UninitializedValues_ValueTypes {
+public:
+
+ struct ObserverTy;
+
+ struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
+ AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
+ virtual ~AnalysisDataTy() {}
+
+ ObserverTy* Observer;
+ bool FullUninitTaint;
+ };
+
+ typedef StmtDeclBitVector_Types::ValTy ValTy;
+
+ //===--------------------------------------------------------------------===//
+ // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
+ // value.
+ //===--------------------------------------------------------------------===//
+
+ struct ObserverTy {
+ virtual ~ObserverTy();
+ virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD,
+ DeclRefExpr* DR, VarDecl* VD) = 0;
+ };
+};
+
+/// UninitializedValues - Objects of this class encapsulate dataflow analysis
+/// information regarding what variable declarations in a function are
+/// potentially unintialized.
+class UninitializedValues :
+ public DataflowValues<UninitializedValues_ValueTypes> {
+public:
+ typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy;
+
+ UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); }
+
+ /// IntializeValues - Create initial dataflow values and meta data for
+ /// a given CFG. This is intended to be called by the dataflow solver.
+ void InitializeValues(const CFG& cfg);
+};
+
+
+void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
+ bool FullUninitTaint=false);
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h
new file mode 100644
index 0000000..c1fe040
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValuesV2.h
@@ -0,0 +1,40 @@
+//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- C++ -*-=
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs for invoking and reported uninitialized values
+// warnings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNINIT_VALS_H
+#define LLVM_CLANG_UNINIT_VALS_H
+
+namespace clang {
+
+class AnalysisContext;
+class CFG;
+class DeclContext;
+class Expr;
+class VarDecl;
+
+class UninitVariablesHandler {
+public:
+ UninitVariablesHandler() {}
+ virtual ~UninitVariablesHandler();
+
+ virtual void handleUseOfUninitVariable(const Expr *ex,
+ const VarDecl *vd) {}
+};
+
+void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
+ AnalysisContext &ac,
+ UninitVariablesHandler &handler);
+
+}
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
new file mode 100644
index 0000000..2ecbfdc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
@@ -0,0 +1,319 @@
+//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- 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 AnalysisContext, a class that manages the analysis context
+// data for path sensitive analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
+#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+
+class Decl;
+class Stmt;
+class CFG;
+class CFGBlock;
+class LiveVariables;
+class ParentMap;
+class PseudoConstantAnalysis;
+class ImplicitParamDecl;
+class LocationContextManager;
+class StackFrameContext;
+
+namespace idx { class TranslationUnit; }
+
+/// AnalysisContext contains the context data for the function or method under
+/// analysis.
+class AnalysisContext {
+ const Decl *D;
+
+ // TranslationUnit is NULL if we don't have multiple translation units.
+ idx::TranslationUnit *TU;
+
+ // AnalysisContext owns the following data.
+ CFG *cfg, *completeCFG;
+ bool builtCFG, builtCompleteCFG;
+ LiveVariables *liveness;
+ LiveVariables *relaxedLiveness;
+ ParentMap *PM;
+ PseudoConstantAnalysis *PCA;
+ llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+ llvm::BumpPtrAllocator A;
+ bool UseUnoptimizedCFG;
+ bool AddEHEdges;
+ bool AddImplicitDtors;
+ bool AddInitializers;
+public:
+ AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
+ bool useUnoptimizedCFG = false,
+ bool addehedges = false,
+ bool addImplicitDtors = false,
+ bool addInitializers = false)
+ : D(d), TU(tu), cfg(0), completeCFG(0),
+ builtCFG(false), builtCompleteCFG(false),
+ liveness(0), relaxedLiveness(0), PM(0), PCA(0),
+ ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
+ AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
+ AddInitializers(addInitializers) {}
+
+ ~AnalysisContext();
+
+ ASTContext &getASTContext() { return D->getASTContext(); }
+ const Decl *getDecl() const { return D; }
+
+ idx::TranslationUnit *getTranslationUnit() const { return TU; }
+
+ /// getAddEHEdges - Return true iff we are adding exceptional edges from
+ /// callExprs. If this is false, then try/catch statements and blocks
+ /// reachable from them can appear to be dead in the CFG, analysis passes must
+ /// cope with that.
+ bool getAddEHEdges() const { return AddEHEdges; }
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+ bool getAddImplicitDtors() const { return AddImplicitDtors; }
+ bool getAddInitializers() const { return AddInitializers; }
+
+ Stmt *getBody();
+ CFG *getCFG();
+
+ /// Return a version of the CFG without any edges pruned.
+ CFG *getUnoptimizedCFG();
+
+ void dumpCFG();
+
+ ParentMap &getParentMap();
+ PseudoConstantAnalysis *getPseudoConstantAnalysis();
+ LiveVariables *getLiveVariables();
+ LiveVariables *getRelaxedLiveVariables();
+
+ typedef const VarDecl * const * referenced_decls_iterator;
+
+ std::pair<referenced_decls_iterator, referenced_decls_iterator>
+ getReferencedBlockVars(const BlockDecl *BD);
+
+ /// Return the ImplicitParamDecl* associated with 'self' if this
+ /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
+ const ImplicitParamDecl *getSelfDecl() const;
+};
+
+class AnalysisContextManager {
+ typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
+ ContextMap Contexts;
+ bool UseUnoptimizedCFG;
+ bool AddImplicitDtors;
+ bool AddInitializers;
+public:
+ AnalysisContextManager(bool useUnoptimizedCFG = false,
+ bool addImplicitDtors = false, bool addInitializers = false)
+ : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
+ AddInitializers(addInitializers) {}
+
+ ~AnalysisContextManager();
+
+ AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+ bool getAddImplicitDtors() const { return AddImplicitDtors; }
+ bool getAddInitializers() const { return AddInitializers; }
+
+ // Discard all previously created AnalysisContexts.
+ void clear();
+};
+
+class LocationContext : public llvm::FoldingSetNode {
+public:
+ enum ContextKind { StackFrame, Scope, Block };
+
+private:
+ ContextKind Kind;
+
+ // AnalysisContext can't be const since some methods may modify its member.
+ AnalysisContext *Ctx;
+
+ const LocationContext *Parent;
+
+protected:
+ LocationContext(ContextKind k, AnalysisContext *ctx,
+ const LocationContext *parent)
+ : Kind(k), Ctx(ctx), Parent(parent) {}
+
+public:
+ virtual ~LocationContext();
+
+ ContextKind getKind() const { return Kind; }
+
+ AnalysisContext *getAnalysisContext() const { return Ctx; }
+
+ idx::TranslationUnit *getTranslationUnit() const {
+ return Ctx->getTranslationUnit();
+ }
+
+ const LocationContext *getParent() const { return Parent; }
+
+ bool isParentOf(const LocationContext *LC) const;
+
+ const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
+
+ CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
+
+ LiveVariables *getLiveVariables() const {
+ return getAnalysisContext()->getLiveVariables();
+ }
+
+ ParentMap &getParentMap() const {
+ return getAnalysisContext()->getParentMap();
+ }
+
+ const ImplicitParamDecl *getSelfDecl() const {
+ return Ctx->getSelfDecl();
+ }
+
+ const StackFrameContext *getCurrentStackFrame() const;
+ const StackFrameContext *
+ getStackFrameForDeclContext(const DeclContext *DC) const;
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
+
+ static bool classof(const LocationContext*) { return true; }
+
+public:
+ static void ProfileCommon(llvm::FoldingSetNodeID &ID,
+ ContextKind ck,
+ AnalysisContext *ctx,
+ const LocationContext *parent,
+ const void* data);
+};
+
+class StackFrameContext : public LocationContext {
+ // The callsite where this stack frame is established.
+ const Stmt *CallSite;
+
+ // The parent block of the callsite.
+ const CFGBlock *Block;
+
+ // The index of the callsite in the CFGBlock.
+ unsigned Index;
+
+ friend class LocationContextManager;
+ StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
+ const Stmt *s, const CFGBlock *blk,
+ unsigned idx)
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ Block(blk), Index(idx) {}
+
+public:
+ ~StackFrameContext() {}
+
+ const Stmt *getCallSite() const { return CallSite; }
+
+ const CFGBlock *getCallSiteBlock() const { return Block; }
+
+ unsigned getIndex() const { return Index; }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
+ const LocationContext *parent, const Stmt *s,
+ const CFGBlock *blk, unsigned idx) {
+ ProfileCommon(ID, StackFrame, ctx, parent, s);
+ ID.AddPointer(blk);
+ ID.AddInteger(idx);
+ }
+
+ static bool classof(const LocationContext* Ctx) {
+ return Ctx->getKind() == StackFrame;
+ }
+};
+
+class ScopeContext : public LocationContext {
+ const Stmt *Enter;
+
+ friend class LocationContextManager;
+ ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
+ const Stmt *s)
+ : LocationContext(Scope, ctx, parent), Enter(s) {}
+
+public:
+ ~ScopeContext() {}
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
+ const LocationContext *parent, const Stmt *s) {
+ ProfileCommon(ID, Scope, ctx, parent, s);
+ }
+
+ static bool classof(const LocationContext* Ctx) {
+ return Ctx->getKind() == Scope;
+ }
+};
+
+class BlockInvocationContext : public LocationContext {
+ // FIXME: Add back context-sensivity (we don't want libAnalysis to know
+ // about MemRegion).
+ const BlockDecl *BD;
+
+ friend class LocationContextManager;
+
+ BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
+ const BlockDecl *bd)
+ : LocationContext(Block, ctx, parent), BD(bd) {}
+
+public:
+ ~BlockInvocationContext() {}
+
+ const BlockDecl *getBlockDecl() const { return BD; }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
+ const LocationContext *parent, const BlockDecl *bd) {
+ ProfileCommon(ID, Block, ctx, parent, bd);
+ }
+
+ static bool classof(const LocationContext* Ctx) {
+ return Ctx->getKind() == Block;
+ }
+};
+
+class LocationContextManager {
+ llvm::FoldingSet<LocationContext> Contexts;
+public:
+ ~LocationContextManager();
+
+ const StackFrameContext *getStackFrame(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s,
+ const CFGBlock *blk, unsigned idx);
+
+ const ScopeContext *getScope(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s);
+
+ /// Discard all previously created LocationContext objects.
+ void clear();
+private:
+ template <typename LOC, typename DATA>
+ const LOC *getLocationContext(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const DATA *d);
+};
+
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h
new file mode 100644
index 0000000..295d0a2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H
+#define LLVM_CLANG_DIAGNOSTICANALYSIS_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define ANALYSISSTART
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_ANALYSIS_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
new file mode 100644
index 0000000..b337d74
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -0,0 +1,786 @@
+//===--- CFG.h - Classes for representing and building CFGs------*- 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 CFG and CFGBuilder classes for representing and
+// building Control-Flow Graphs (CFGs) from ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CFG_H
+#define LLVM_CLANG_CFG_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cassert>
+#include <iterator>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+ class Decl;
+ class Stmt;
+ class Expr;
+ class FieldDecl;
+ class VarDecl;
+ class CXXCtorInitializer;
+ class CXXBaseSpecifier;
+ class CXXBindTemporaryExpr;
+ class CFG;
+ class PrinterHelper;
+ class LangOptions;
+ class ASTContext;
+
+/// CFGElement - Represents a top-level expression in a basic block.
+class CFGElement {
+public:
+ enum Kind {
+ // main kind
+ Statement,
+ Initializer,
+ ImplicitDtor,
+ // dtor kind
+ AutomaticObjectDtor,
+ BaseDtor,
+ MemberDtor,
+ TemporaryDtor,
+ DTOR_BEGIN = AutomaticObjectDtor
+ };
+
+protected:
+ // The int bits are used to mark the main kind.
+ llvm::PointerIntPair<void *, 2> Data1;
+ // The int bits are used to mark the dtor kind.
+ llvm::PointerIntPair<void *, 2> Data2;
+
+ CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
+ CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2)
+ : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {}
+
+public:
+ CFGElement() {}
+
+ Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
+
+ Kind getDtorKind() const {
+ assert(getKind() == ImplicitDtor);
+ return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN);
+ }
+
+ bool isValid() const { return Data1.getPointer(); }
+
+ operator bool() const { return isValid(); }
+
+ template<class ElemTy> ElemTy getAs() const {
+ if (llvm::isa<ElemTy>(this))
+ return *static_cast<const ElemTy*>(this);
+ return ElemTy();
+ }
+
+ static bool classof(const CFGElement *E) { return true; }
+};
+
+class CFGStmt : public CFGElement {
+public:
+ CFGStmt() {}
+ CFGStmt(Stmt *S) : CFGElement(S, 0) {}
+
+ Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
+
+ operator Stmt*() const { return getStmt(); }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == Statement;
+ }
+};
+
+/// CFGInitializer - Represents C++ base or member initializer from
+/// constructor's initialization list.
+class CFGInitializer : public CFGElement {
+public:
+ CFGInitializer() {}
+ CFGInitializer(CXXCtorInitializer* I)
+ : CFGElement(I, Initializer) {}
+
+ CXXCtorInitializer* getInitializer() const {
+ return static_cast<CXXCtorInitializer*>(Data1.getPointer());
+ }
+ operator CXXCtorInitializer*() const { return getInitializer(); }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == Initializer;
+ }
+};
+
+/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
+/// by compiler on various occasions.
+class CFGImplicitDtor : public CFGElement {
+protected:
+ CFGImplicitDtor(unsigned K, void* P, void* S)
+ : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {}
+
+public:
+ CFGImplicitDtor() {}
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor;
+ }
+};
+
+/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
+/// for automatic object or temporary bound to const reference at the point
+/// of leaving its local scope.
+class CFGAutomaticObjDtor: public CFGImplicitDtor {
+public:
+ CFGAutomaticObjDtor() {}
+ CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
+ : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
+
+ VarDecl* getVarDecl() const {
+ return static_cast<VarDecl*>(Data1.getPointer());
+ }
+
+ // Get statement end of which triggered the destructor call.
+ Stmt* getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor &&
+ E->getDtorKind() == AutomaticObjectDtor;
+ }
+};
+
+/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
+/// base object in destructor.
+class CFGBaseDtor : public CFGImplicitDtor {
+public:
+ CFGBaseDtor() {}
+ CFGBaseDtor(const CXXBaseSpecifier *BS)
+ : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
+
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor;
+ }
+};
+
+/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
+/// member object in destructor.
+class CFGMemberDtor : public CFGImplicitDtor {
+public:
+ CFGMemberDtor() {}
+ CFGMemberDtor(FieldDecl *FD)
+ : CFGImplicitDtor(MemberDtor, FD, NULL) {}
+
+ FieldDecl *getFieldDecl() const {
+ return static_cast<FieldDecl*>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor;
+ }
+};
+
+/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
+/// at the end of full expression for temporary object.
+class CFGTemporaryDtor : public CFGImplicitDtor {
+public:
+ CFGTemporaryDtor() {}
+ CFGTemporaryDtor(CXXBindTemporaryExpr *E)
+ : CFGImplicitDtor(TemporaryDtor, E, NULL) {}
+
+ CXXBindTemporaryExpr *getBindTemporaryExpr() const {
+ return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer());
+ }
+
+ static bool classof(const CFGElement *E) {
+ return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor;
+ }
+};
+
+/// CFGTerminator - Represents CFGBlock terminator statement.
+///
+/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
+/// in control flow of destructors of temporaries. In this case terminator
+/// statement is the same statement that branches control flow in evaluation
+/// of matching full expression.
+class CFGTerminator {
+ llvm::PointerIntPair<Stmt *, 1> Data;
+public:
+ CFGTerminator() {}
+ CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
+ : Data(S, TemporaryDtorsBranch) {}
+
+ Stmt *getStmt() { return Data.getPointer(); }
+ const Stmt *getStmt() const { return Data.getPointer(); }
+
+ bool isTemporaryDtorsBranch() const { return Data.getInt(); }
+
+ operator Stmt *() { return getStmt(); }
+ operator const Stmt *() const { return getStmt(); }
+
+ Stmt *operator->() { return getStmt(); }
+ const Stmt *operator->() const { return getStmt(); }
+
+ Stmt &operator*() { return *getStmt(); }
+ const Stmt &operator*() const { return *getStmt(); }
+
+ operator bool() const { return getStmt(); }
+};
+
+/// CFGBlock - Represents a single basic block in a source-level CFG.
+/// It consists of:
+///
+/// (1) A set of statements/expressions (which may contain subexpressions).
+/// (2) A "terminator" statement (not in the set of statements).
+/// (3) A list of successors and predecessors.
+///
+/// Terminator: The terminator represents the type of control-flow that occurs
+/// at the end of the basic block. The terminator is a Stmt* referring to an
+/// AST node that has control-flow: if-statements, breaks, loops, etc.
+/// If the control-flow is conditional, the condition expression will appear
+/// within the set of statements in the block (usually the last statement).
+///
+/// Predecessors: the order in the set of predecessors is arbitrary.
+///
+/// Successors: the order in the set of successors is NOT arbitrary. We
+/// currently have the following orderings based on the terminator:
+///
+/// Terminator Successor Ordering
+/// -----------------------------------------------------
+/// if Then Block; Else Block
+/// ? operator LHS expression; RHS expression
+/// &&, || expression that uses result of && or ||, RHS
+///
+class CFGBlock {
+ class ElementList {
+ typedef BumpVector<CFGElement> ImplTy;
+ ImplTy Impl;
+ public:
+ ElementList(BumpVectorContext &C) : Impl(C, 4) {}
+
+ typedef std::reverse_iterator<ImplTy::iterator> iterator;
+ typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
+ typedef ImplTy::iterator reverse_iterator;
+ typedef ImplTy::const_iterator const_reverse_iterator;
+
+ void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
+ reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
+ BumpVectorContext& C) {
+ return Impl.insert(I, Cnt, E, C);
+ }
+
+ CFGElement front() const { return Impl.back(); }
+ CFGElement back() const { return Impl.front(); }
+
+ iterator begin() { return Impl.rbegin(); }
+ iterator end() { return Impl.rend(); }
+ const_iterator begin() const { return Impl.rbegin(); }
+ const_iterator end() const { return Impl.rend(); }
+ reverse_iterator rbegin() { return Impl.begin(); }
+ reverse_iterator rend() { return Impl.end(); }
+ const_reverse_iterator rbegin() const { return Impl.begin(); }
+ const_reverse_iterator rend() const { return Impl.end(); }
+
+ CFGElement operator[](size_t i) const {
+ assert(i < Impl.size());
+ return Impl[Impl.size() - 1 - i];
+ }
+
+ size_t size() const { return Impl.size(); }
+ bool empty() const { return Impl.empty(); }
+ };
+
+ /// Stmts - The set of statements in the basic block.
+ ElementList Elements;
+
+ /// Label - An (optional) label that prefixes the executable
+ /// statements in the block. When this variable is non-NULL, it is
+ /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
+ Stmt *Label;
+
+ /// Terminator - The terminator for a basic block that
+ /// indicates the type of control-flow that occurs between a block
+ /// and its successors.
+ CFGTerminator Terminator;
+
+ /// LoopTarget - Some blocks are used to represent the "loop edge" to
+ /// the start of a loop from within the loop body. This Stmt* will be
+ /// refer to the loop statement for such blocks (and be null otherwise).
+ const Stmt *LoopTarget;
+
+ /// BlockID - A numerical ID assigned to a CFGBlock during construction
+ /// of the CFG.
+ unsigned BlockID;
+
+ /// Predecessors/Successors - Keep track of the predecessor / successor
+ /// CFG blocks.
+ typedef BumpVector<CFGBlock*> AdjacentBlocks;
+ AdjacentBlocks Preds;
+ AdjacentBlocks Succs;
+
+public:
+ explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
+ : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
+ BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
+ ~CFGBlock() {}
+
+ // Statement iterators
+ typedef ElementList::iterator iterator;
+ typedef ElementList::const_iterator const_iterator;
+ typedef ElementList::reverse_iterator reverse_iterator;
+ typedef ElementList::const_reverse_iterator const_reverse_iterator;
+
+ CFGElement front() const { return Elements.front(); }
+ CFGElement back() const { return Elements.back(); }
+
+ iterator begin() { return Elements.begin(); }
+ iterator end() { return Elements.end(); }
+ const_iterator begin() const { return Elements.begin(); }
+ const_iterator end() const { return Elements.end(); }
+
+ reverse_iterator rbegin() { return Elements.rbegin(); }
+ reverse_iterator rend() { return Elements.rend(); }
+ const_reverse_iterator rbegin() const { return Elements.rbegin(); }
+ const_reverse_iterator rend() const { return Elements.rend(); }
+
+ unsigned size() const { return Elements.size(); }
+ bool empty() const { return Elements.empty(); }
+
+ CFGElement operator[](size_t i) const { return Elements[i]; }
+
+ // CFG iterators
+ typedef AdjacentBlocks::iterator pred_iterator;
+ typedef AdjacentBlocks::const_iterator const_pred_iterator;
+ typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
+ typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
+
+ typedef AdjacentBlocks::iterator succ_iterator;
+ typedef AdjacentBlocks::const_iterator const_succ_iterator;
+ typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
+ typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
+
+ pred_iterator pred_begin() { return Preds.begin(); }
+ pred_iterator pred_end() { return Preds.end(); }
+ const_pred_iterator pred_begin() const { return Preds.begin(); }
+ const_pred_iterator pred_end() const { return Preds.end(); }
+
+ pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
+ pred_reverse_iterator pred_rend() { return Preds.rend(); }
+ const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
+ const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
+
+ succ_iterator succ_begin() { return Succs.begin(); }
+ succ_iterator succ_end() { return Succs.end(); }
+ const_succ_iterator succ_begin() const { return Succs.begin(); }
+ const_succ_iterator succ_end() const { return Succs.end(); }
+
+ succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
+ succ_reverse_iterator succ_rend() { return Succs.rend(); }
+ const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
+ const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
+
+ unsigned succ_size() const { return Succs.size(); }
+ bool succ_empty() const { return Succs.empty(); }
+
+ unsigned pred_size() const { return Preds.size(); }
+ bool pred_empty() const { return Preds.empty(); }
+
+
+ class FilterOptions {
+ public:
+ FilterOptions() {
+ IgnoreDefaultsWithCoveredEnums = 0;
+ }
+
+ unsigned IgnoreDefaultsWithCoveredEnums : 1;
+ };
+
+ static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
+ const CFGBlock *Dst);
+
+ template <typename IMPL, bool IsPred>
+ class FilteredCFGBlockIterator {
+ private:
+ IMPL I, E;
+ const FilterOptions F;
+ const CFGBlock *From;
+ public:
+ explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
+ const CFGBlock *from,
+ const FilterOptions &f)
+ : I(i), E(e), F(f), From(from) {}
+
+ bool hasMore() const { return I != E; }
+
+ FilteredCFGBlockIterator &operator++() {
+ do { ++I; } while (hasMore() && Filter(*I));
+ return *this;
+ }
+
+ const CFGBlock *operator*() const { return *I; }
+ private:
+ bool Filter(const CFGBlock *To) {
+ return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
+ }
+ };
+
+ typedef FilteredCFGBlockIterator<const_pred_iterator, true>
+ filtered_pred_iterator;
+
+ typedef FilteredCFGBlockIterator<const_succ_iterator, false>
+ filtered_succ_iterator;
+
+ filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
+ return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
+ }
+
+ filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const {
+ return filtered_succ_iterator(succ_begin(), succ_end(), this, f);
+ }
+
+ // Manipulation of block contents
+
+ void setTerminator(Stmt* Statement) { Terminator = Statement; }
+ void setLabel(Stmt* Statement) { Label = Statement; }
+ void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
+
+ CFGTerminator getTerminator() { return Terminator; }
+ const CFGTerminator getTerminator() const { return Terminator; }
+
+ Stmt* getTerminatorCondition();
+
+ const Stmt* getTerminatorCondition() const {
+ return const_cast<CFGBlock*>(this)->getTerminatorCondition();
+ }
+
+ const Stmt *getLoopTarget() const { return LoopTarget; }
+
+ bool hasBinaryBranchTerminator() const;
+
+ Stmt* getLabel() { return Label; }
+ const Stmt* getLabel() const { return Label; }
+
+ unsigned getBlockID() const { return BlockID; }
+
+ void dump(const CFG *cfg, const LangOptions &LO) const;
+ void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
+ void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const;
+
+ void addSuccessor(CFGBlock* Block, BumpVectorContext &C) {
+ if (Block)
+ Block->Preds.push_back(this, C);
+ Succs.push_back(Block, C);
+ }
+
+ void appendStmt(Stmt* statement, BumpVectorContext &C) {
+ Elements.push_back(CFGStmt(statement), C);
+ }
+
+ void appendInitializer(CXXCtorInitializer *initializer,
+ BumpVectorContext& C) {
+ Elements.push_back(CFGInitializer(initializer), C);
+ }
+
+ void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
+ Elements.push_back(CFGBaseDtor(BS), C);
+ }
+
+ void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
+ Elements.push_back(CFGMemberDtor(FD), C);
+ }
+
+ void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) {
+ Elements.push_back(CFGTemporaryDtor(E), C);
+ }
+
+ // Destructors must be inserted in reversed order. So insertion is in two
+ // steps. First we prepare space for some number of elements, then we insert
+ // the elements beginning at the last position in prepared space.
+ iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
+ BumpVectorContext& C) {
+ return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C));
+ }
+ iterator insertAutomaticObjDtor(iterator I, VarDecl* VD, Stmt* S) {
+ *I = CFGAutomaticObjDtor(VD, S);
+ return ++I;
+ }
+};
+
+/// CFG - Represents a source-level, intra-procedural CFG that represents the
+/// control-flow of a Stmt. The Stmt can represent an entire function body,
+/// or a single expression. A CFG will always contain one empty block that
+/// represents the Exit point of the CFG. A CFG will also contain a designated
+/// Entry block. The CFG solely represents control-flow; it consists of
+/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
+/// was constructed from.
+class CFG {
+public:
+ //===--------------------------------------------------------------------===//
+ // CFG Construction & Manipulation.
+ //===--------------------------------------------------------------------===//
+
+ class BuildOptions {
+ public:
+ bool PruneTriviallyFalseEdges:1;
+ bool AddEHEdges:1;
+ bool AddInitializers:1;
+ bool AddImplicitDtors:1;
+
+ BuildOptions()
+ : PruneTriviallyFalseEdges(true)
+ , AddEHEdges(false)
+ , AddInitializers(false)
+ , AddImplicitDtors(false) {}
+ };
+
+ /// buildCFG - Builds a CFG from an AST. The responsibility to free the
+ /// constructed CFG belongs to the caller.
+ static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
+ BuildOptions BO = BuildOptions());
+
+ /// createBlock - Create a new block in the CFG. The CFG owns the block;
+ /// the caller should not directly free it.
+ CFGBlock* createBlock();
+
+ /// setEntry - Set the entry block of the CFG. This is typically used
+ /// only during CFG construction. Most CFG clients expect that the
+ /// entry block has no predecessors and contains no statements.
+ void setEntry(CFGBlock *B) { Entry = B; }
+
+ /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
+ /// This is typically used only during CFG construction.
+ void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
+
+ //===--------------------------------------------------------------------===//
+ // Block Iterators
+ //===--------------------------------------------------------------------===//
+
+ typedef BumpVector<CFGBlock*> CFGBlockListTy;
+ typedef CFGBlockListTy::iterator iterator;
+ typedef CFGBlockListTy::const_iterator const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ CFGBlock& front() { return *Blocks.front(); }
+ CFGBlock& back() { return *Blocks.back(); }
+
+ iterator begin() { return Blocks.begin(); }
+ iterator end() { return Blocks.end(); }
+ const_iterator begin() const { return Blocks.begin(); }
+ const_iterator end() const { return Blocks.end(); }
+
+ reverse_iterator rbegin() { return Blocks.rbegin(); }
+ reverse_iterator rend() { return Blocks.rend(); }
+ const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
+ const_reverse_iterator rend() const { return Blocks.rend(); }
+
+ CFGBlock& getEntry() { return *Entry; }
+ const CFGBlock& getEntry() const { return *Entry; }
+ CFGBlock& getExit() { return *Exit; }
+ const CFGBlock& getExit() const { return *Exit; }
+
+ CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; }
+ const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; }
+
+ //===--------------------------------------------------------------------===//
+ // Member templates useful for various batch operations over CFGs.
+ //===--------------------------------------------------------------------===//
+
+ template <typename CALLBACK>
+ void VisitBlockStmts(CALLBACK& O) const {
+ for (const_iterator I=begin(), E=end(); I != E; ++I)
+ for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
+ BI != BE; ++BI) {
+ if (CFGStmt S = BI->getAs<CFGStmt>())
+ O(S);
+ }
+ }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Introspection.
+ //===--------------------------------------------------------------------===//
+
+ struct BlkExprNumTy {
+ const signed Idx;
+ explicit BlkExprNumTy(signed idx) : Idx(idx) {}
+ explicit BlkExprNumTy() : Idx(-1) {}
+ operator bool() const { return Idx >= 0; }
+ operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
+ };
+
+ bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+ bool isBlkExpr(const Stmt *S) const {
+ return const_cast<CFG*>(this)->isBlkExpr(S);
+ }
+ BlkExprNumTy getBlkExprNum(const Stmt* S);
+ unsigned getNumBlkExprs();
+
+ /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
+ /// start at 0).
+ unsigned getNumBlockIDs() const { return NumBlockIDs; }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Debugging: Pretty-Printing and Visualization.
+ //===--------------------------------------------------------------------===//
+
+ void viewCFG(const LangOptions &LO) const;
+ void print(llvm::raw_ostream& OS, const LangOptions &LO) const;
+ void dump(const LangOptions &LO) const;
+
+ //===--------------------------------------------------------------------===//
+ // Internal: constructors and data.
+ //===--------------------------------------------------------------------===//
+
+ CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
+ BlkExprMap(NULL), Blocks(BlkBVC, 10) {}
+
+ ~CFG();
+
+ llvm::BumpPtrAllocator& getAllocator() {
+ return BlkBVC.getAllocator();
+ }
+
+ BumpVectorContext &getBumpVectorContext() {
+ return BlkBVC;
+ }
+
+private:
+ CFGBlock* Entry;
+ CFGBlock* Exit;
+ CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
+ // for indirect gotos
+ unsigned NumBlockIDs;
+
+ // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
+ // It represents a map from Expr* to integers to record the set of
+ // block-level expressions and their "statement number" in the CFG.
+ void* BlkExprMap;
+
+ BumpVectorContext BlkBVC;
+
+ CFGBlockListTy Blocks;
+
+};
+} // end namespace clang
+
+//===----------------------------------------------------------------------===//
+// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
+/// CFGTerminator to a specific Stmt class.
+template <> struct simplify_type<const ::clang::CFGTerminator> {
+ typedef const ::clang::Stmt *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
+ return Val.getStmt();
+ }
+};
+
+template <> struct simplify_type< ::clang::CFGTerminator> {
+ typedef ::clang::Stmt *SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
+ return const_cast<SimpleType>(Val.getStmt());
+ }
+};
+
+// Traits for: CFGBlock
+
+template <> struct GraphTraits< ::clang::CFGBlock* > {
+ typedef ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
+
+ static NodeType* getEntryNode(::clang::CFGBlock* BB)
+ { return BB; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->succ_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->succ_end(); }
+};
+
+template <> struct GraphTraits< const ::clang::CFGBlock* > {
+ typedef const ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
+
+ static NodeType* getEntryNode(const clang::CFGBlock* BB)
+ { return BB; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->succ_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->succ_end(); }
+};
+
+template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
+ typedef const ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
+
+ static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G)
+ { return G.Graph; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->pred_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->pred_end(); }
+};
+
+// Traits for: CFG
+
+template <> struct GraphTraits< ::clang::CFG* >
+ : public GraphTraits< ::clang::CFGBlock* > {
+
+ typedef ::clang::CFG::iterator nodes_iterator;
+
+ static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
+ static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); }
+ static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); }
+};
+
+template <> struct GraphTraits<const ::clang::CFG* >
+ : public GraphTraits<const ::clang::CFGBlock* > {
+
+ typedef ::clang::CFG::const_iterator nodes_iterator;
+
+ static NodeType *getEntryNode( const ::clang::CFG* F) {
+ return &F->getEntry();
+ }
+ static nodes_iterator nodes_begin( const ::clang::CFG* F) {
+ return F->begin();
+ }
+ static nodes_iterator nodes_end( const ::clang::CFG* F) {
+ return F->end();
+ }
+};
+
+template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
+ : public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
+
+ typedef ::clang::CFG::const_iterator nodes_iterator;
+
+ static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
+ static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();}
+ static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); }
+};
+} // end llvm namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h
new file mode 100644
index 0000000..6e8e140
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h
@@ -0,0 +1,52 @@
+//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CFGStmtMap class, which defines a mapping from
+// Stmt* to CFGBlock*
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CFGSTMTMAP_H
+#define LLVM_CLANG_CFGSTMTMAP_H
+
+#include "clang/Analysis/CFG.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+class ParentMap;
+class Stmt;
+
+class CFGStmtMap {
+ ParentMap *PM;
+ void *M;
+
+ CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
+
+public:
+ ~CFGStmtMap();
+
+ /// Returns a new CFGMap for the given CFG. It is the caller's
+ /// responsibility to 'delete' this object when done using it.
+ static CFGStmtMap *Build(CFG* C, ParentMap *PM);
+
+ /// Returns the CFGBlock the specified Stmt* appears in. For Stmt* that
+ /// are terminators, the CFGBlock is the block they appear as a terminator,
+ /// and not the block they appear as a block-level expression (e.g, '&&').
+ /// CaseStmts and LabelStmts map to the CFGBlock they label.
+ CFGBlock *getBlock(Stmt * S);
+
+ const CFGBlock *getBlock(const Stmt * S) const {
+ return const_cast<CFGStmtMap*>(this)->getBlock(const_cast<Stmt*>(S));
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
new file mode 100644
index 0000000..7e6e381
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -0,0 +1,40 @@
+//===- CocoaConventions.h - Special handling of Cocoa conventions -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
+#define LLVM_CLANG_ANALYSIS_DS_COCOA
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace ento {
+namespace cocoa {
+
+ enum NamingConvention { NoConvention, CreateRule, InitRule };
+
+ NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true);
+
+ static inline bool followsFundamentalRule(Selector S) {
+ return deriveNamingConvention(S) == CreateRule;
+ }
+
+ bool isRefType(QualType RetTy, llvm::StringRef Prefix,
+ llvm::StringRef Name = llvm::StringRef());
+
+ bool isCFObjectRef(QualType T);
+
+ bool isCocoaObjectRef(QualType T);
+
+}}}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h
new file mode 100644
index 0000000..d75d333
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -0,0 +1,343 @@
+//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- 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 skeleton code for implementing dataflow analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
+#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "functional" // STL
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+/// DataflowWorkListTy - Data structure representing the worklist used for
+/// dataflow algorithms.
+//===----------------------------------------------------------------------===//
+
+class DataflowWorkListTy {
+ llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet;
+ llvm::SmallVector<const CFGBlock *, 10> BlockQueue;
+public:
+ /// enqueue - Add a block to the worklist. Blocks already on the
+ /// worklist are not added a second time.
+ void enqueue(const CFGBlock* B) {
+ unsigned char &x = BlockSet[B];
+ if (x == 1)
+ return;
+ x = 1;
+ BlockQueue.push_back(B);
+ }
+
+ /// dequeue - Remove a block from the worklist.
+ const CFGBlock* dequeue() {
+ assert(!BlockQueue.empty());
+ const CFGBlock *B = BlockQueue.back();
+ BlockQueue.pop_back();
+ BlockSet[B] = 0;
+ return B;
+ }
+
+ /// isEmpty - Return true if the worklist is empty.
+ bool isEmpty() const { return BlockQueue.empty(); }
+};
+
+//===----------------------------------------------------------------------===//
+// BlockItrTraits - Traits classes that allow transparent iteration
+// over successors/predecessors of a block depending on the direction
+// of our dataflow analysis.
+//===----------------------------------------------------------------------===//
+
+namespace dataflow {
+template<typename Tag> struct ItrTraits {};
+
+template <> struct ItrTraits<forward_analysis_tag> {
+ typedef CFGBlock::const_pred_iterator PrevBItr;
+ typedef CFGBlock::const_succ_iterator NextBItr;
+ typedef CFGBlock::const_iterator StmtItr;
+
+ static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); }
+ static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); }
+
+ static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); }
+ static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); }
+
+ static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); }
+ static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); }
+
+ static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
+ return BlockEdge(Prev, B, 0);
+ }
+
+ static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
+ return BlockEdge(B, Next, 0);
+ }
+};
+
+template <> struct ItrTraits<backward_analysis_tag> {
+ typedef CFGBlock::const_succ_iterator PrevBItr;
+ typedef CFGBlock::const_pred_iterator NextBItr;
+ typedef CFGBlock::const_reverse_iterator StmtItr;
+
+ static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); }
+ static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); }
+
+ static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); }
+ static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); }
+
+ static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); }
+ static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); }
+
+ static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
+ return BlockEdge(B, Prev, 0);
+ }
+
+ static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
+ return BlockEdge(Next, B, 0);
+ }
+};
+} // end namespace dataflow
+
+//===----------------------------------------------------------------------===//
+/// DataflowSolverTy - Generic dataflow solver.
+//===----------------------------------------------------------------------===//
+
+template <typename _DFValuesTy, // Usually a subclass of DataflowValues
+ typename _TransferFuncsTy,
+ typename _MergeOperatorTy,
+ typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> >
+class DataflowSolver {
+
+ //===----------------------------------------------------===//
+ // Type declarations.
+ //===----------------------------------------------------===//
+
+public:
+ typedef _DFValuesTy DFValuesTy;
+ typedef _TransferFuncsTy TransferFuncsTy;
+ typedef _MergeOperatorTy MergeOperatorTy;
+
+ typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
+ typedef typename _DFValuesTy::ValTy ValTy;
+ typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
+ typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
+
+ typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits;
+ typedef typename ItrTraits::NextBItr NextBItr;
+ typedef typename ItrTraits::PrevBItr PrevBItr;
+ typedef typename ItrTraits::StmtItr StmtItr;
+
+ //===----------------------------------------------------===//
+ // External interface: constructing and running the solver.
+ //===----------------------------------------------------===//
+
+public:
+ DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
+ ~DataflowSolver() {}
+
+ /// runOnCFG - Computes dataflow values for all blocks in a CFG.
+ void runOnCFG(CFG& cfg, bool recordStmtValues = false) {
+ // Set initial dataflow values and boundary conditions.
+ D.InitializeValues(cfg);
+ // Solve the dataflow equations. This will populate D.EdgeDataMap
+ // with dataflow values.
+ SolveDataflowEquations(cfg, recordStmtValues);
+ }
+
+ /// runOnBlock - Computes dataflow values for a given block. This
+ /// should usually be invoked only after previously computing
+ /// dataflow values using runOnCFG, as runOnBlock is intended to
+ /// only be used for querying the dataflow values within a block
+ /// with and Observer object.
+ void runOnBlock(const CFGBlock* B, bool recordStmtValues) {
+ BlockDataMapTy& M = D.getBlockDataMap();
+ typename BlockDataMapTy::iterator I = M.find(B);
+
+ if (I != M.end()) {
+ TF.getVal().copyValues(I->second);
+ ProcessBlock(B, recordStmtValues, AnalysisDirTag());
+ }
+ }
+
+ void runOnBlock(const CFGBlock& B, bool recordStmtValues) {
+ runOnBlock(&B, recordStmtValues);
+ }
+ void runOnBlock(CFG::iterator& I, bool recordStmtValues) {
+ runOnBlock(*I, recordStmtValues);
+ }
+ void runOnBlock(CFG::const_iterator& I, bool recordStmtValues) {
+ runOnBlock(*I, recordStmtValues);
+ }
+
+ void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) {
+ for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+ runOnBlock(I, recordStmtValues);
+ }
+
+ //===----------------------------------------------------===//
+ // Internal solver logic.
+ //===----------------------------------------------------===//
+
+private:
+
+ /// SolveDataflowEquations - Perform the actual worklist algorithm
+ /// to compute dataflow values.
+ void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) {
+ EnqueueBlocksOnWorklist(cfg, AnalysisDirTag());
+
+ while (!WorkList.isEmpty()) {
+ const CFGBlock* B = WorkList.dequeue();
+ ProcessMerge(cfg, B);
+ ProcessBlock(B, recordStmtValues, AnalysisDirTag());
+ UpdateEdges(cfg, B, TF.getVal());
+ }
+ }
+
+ void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) {
+ // Enqueue all blocks to ensure the dataflow values are computed
+ // for every block. Not all blocks are guaranteed to reach the exit block.
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+ WorkList.enqueue(&**I);
+ }
+
+ void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) {
+ // Enqueue all blocks to ensure the dataflow values are computed
+ // for every block. Not all blocks are guaranteed to reach the exit block.
+ // Enqueue in reverse order since that will more likely match with
+ // the order they should ideally processed by the dataflow algorithm.
+ for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I)
+ WorkList.enqueue(&**I);
+ }
+
+ void ProcessMerge(CFG& cfg, const CFGBlock* B) {
+ ValTy& V = TF.getVal();
+ TF.SetTopValue(V);
+
+ // Merge dataflow values from all predecessors of this block.
+ MergeOperatorTy Merge;
+
+ EdgeDataMapTy& M = D.getEdgeDataMap();
+ bool firstMerge = true;
+ bool noEdges = true;
+ for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
+
+ CFGBlock *PrevBlk = *I;
+
+ if (!PrevBlk)
+ continue;
+
+ typename EdgeDataMapTy::iterator EI =
+ M.find(ItrTraits::PrevEdge(B, PrevBlk));
+
+ if (EI != M.end()) {
+ noEdges = false;
+ if (firstMerge) {
+ firstMerge = false;
+ V.copyValues(EI->second);
+ }
+ else
+ Merge(V, EI->second);
+ }
+ }
+
+ bool isInitialized = true;
+ typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B);
+ if(BI == D.getBlockDataMap().end()) {
+ isInitialized = false;
+ BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first;
+ }
+ // If no edges have been found, it means this is the first time the solver
+ // has been called on block B, we copy the initialization values (if any)
+ // as current value for V (which will be used as edge data)
+ if(noEdges && isInitialized)
+ Merge(V, BI->second);
+
+ // Set the data for the block.
+ BI->second.copyValues(V);
+ }
+
+ /// ProcessBlock - Process the transfer functions for a given block.
+ void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
+ dataflow::forward_analysis_tag) {
+
+ TF.setCurrentBlock(B);
+
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+ CFGElement El = *I;
+ if (CFGStmt S = El.getAs<CFGStmt>())
+ ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+ }
+
+ TF.VisitTerminator(const_cast<CFGBlock*>(B));
+ }
+
+ void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
+ dataflow::backward_analysis_tag) {
+
+ TF.setCurrentBlock(B);
+
+ TF.VisitTerminator(const_cast<CFGBlock*>(B));
+
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+ CFGElement El = *I;
+ if (CFGStmt S = El.getAs<CFGStmt>())
+ ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+ }
+ }
+
+ void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
+ if (record) D.getStmtDataMap()[S] = TF.getVal();
+ TF.BlockStmt_Visit(const_cast<Stmt*>(S));
+ }
+
+ void ProcessStmt(const Stmt* S, bool record, dataflow::backward_analysis_tag){
+ TF.BlockStmt_Visit(const_cast<Stmt*>(S));
+ if (record) D.getStmtDataMap()[S] = TF.getVal();
+ }
+
+ /// UpdateEdges - After processing the transfer functions for a
+ /// block, update the dataflow value associated with the block's
+ /// outgoing/incoming edges (depending on whether we do a
+ // forward/backward analysis respectively)
+ void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) {
+ for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
+ if (CFGBlock *NextBlk = *I)
+ UpdateEdgeValue(ItrTraits::NextEdge(B, NextBlk),V, NextBlk);
+ }
+
+ /// UpdateEdgeValue - Update the value associated with a given edge.
+ void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) {
+ EdgeDataMapTy& M = D.getEdgeDataMap();
+ typename EdgeDataMapTy::iterator I = M.find(E);
+
+ if (I == M.end()) { // First computed value for this edge?
+ M[E].copyValues(V);
+ WorkList.enqueue(TargetBlock);
+ }
+ else if (!_Equal()(V,I->second)) {
+ I->second.copyValues(V);
+ WorkList.enqueue(TargetBlock);
+ }
+ }
+
+private:
+ DFValuesTy& D;
+ DataflowWorkListTy WorkList;
+ TransferFuncsTy TF;
+};
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h
new file mode 100644
index 0000000..7aa15c5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h
@@ -0,0 +1,172 @@
+//===--- DataflowValues.h - Data structure for dataflow values --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a skeleton data structure for encapsulating the dataflow
+// values for a CFG. Typically this is subclassed to provide methods for
+// computing these values from a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
+#define LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
+
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "llvm/ADT/DenseMap.h"
+
+//===----------------------------------------------------------------------===//
+/// Dataflow Directional Tag Classes. These are used for tag dispatching
+/// within the dataflow solver/transfer functions to determine what direction
+/// a dataflow analysis flows.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace dataflow {
+ struct forward_analysis_tag {};
+ struct backward_analysis_tag {};
+} // end namespace dataflow
+
+//===----------------------------------------------------------------------===//
+/// DataflowValues. Container class to store dataflow values for a CFG.
+//===----------------------------------------------------------------------===//
+
+template <typename ValueTypes,
+ typename _AnalysisDirTag = dataflow::forward_analysis_tag >
+class DataflowValues {
+
+ //===--------------------------------------------------------------------===//
+ // Type declarations.
+ //===--------------------------------------------------------------------===//
+
+public:
+ typedef typename ValueTypes::ValTy ValTy;
+ typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
+ typedef _AnalysisDirTag AnalysisDirTag;
+ typedef llvm::DenseMap<ProgramPoint, ValTy> EdgeDataMapTy;
+ typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
+ typedef llvm::DenseMap<const Stmt*, ValTy> StmtDataMapTy;
+
+ //===--------------------------------------------------------------------===//
+ // Predicates.
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// isForwardAnalysis - Returns true if the dataflow values are computed
+ /// from a forward analysis.
+ bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
+
+ /// isBackwardAnalysis - Returns true if the dataflow values are computed
+ /// from a backward analysis.
+ bool isBackwardAnalysis() { return !isForwardAnalysis(); }
+
+private:
+ bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
+ bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }
+
+ //===--------------------------------------------------------------------===//
+ // Initialization and accessors methods.
+ //===--------------------------------------------------------------------===//
+
+public:
+ DataflowValues() : StmtDataMap(NULL) {}
+ ~DataflowValues() { delete StmtDataMap; }
+
+ /// InitializeValues - Invoked by the solver to initialize state needed for
+ /// dataflow analysis. This method is usually specialized by subclasses.
+ void InitializeValues(const CFG& cfg) {}
+
+
+ /// getEdgeData - Retrieves the dataflow values associated with a
+ /// CFG edge.
+ ValTy& getEdgeData(const BlockEdge& E) {
+ typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
+ assert (I != EdgeDataMap.end() && "No data associated with Edge.");
+ return I->second;
+ }
+
+ const ValTy& getEdgeData(const BlockEdge& E) const {
+ return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
+ }
+
+ /// getBlockData - Retrieves the dataflow values associated with a
+ /// specified CFGBlock. If the dataflow analysis is a forward analysis,
+ /// this data is associated with the END of the block. If the analysis
+ /// is a backwards analysis, it is associated with the ENTRY of the block.
+ ValTy& getBlockData(const CFGBlock* B) {
+ typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
+ assert (I != BlockDataMap.end() && "No data associated with block.");
+ return I->second;
+ }
+
+ const ValTy& getBlockData(const CFGBlock* B) const {
+ return const_cast<DataflowValues*>(this)->getBlockData(B);
+ }
+
+ /// getStmtData - Retrieves the dataflow values associated with a
+ /// specified Stmt. If the dataflow analysis is a forward analysis,
+ /// this data corresponds to the point immediately before a Stmt.
+ /// If the analysis is a backwards analysis, it is associated with
+ /// the point after a Stmt. This data is only computed for block-level
+ /// expressions, and only when requested when the analysis is executed.
+ ValTy& getStmtData(const Stmt* S) {
+ assert (StmtDataMap && "Dataflow values were not computed for statements.");
+ typename StmtDataMapTy::iterator I = StmtDataMap->find(S);
+ assert (I != StmtDataMap->end() && "No data associated with statement.");
+ return I->second;
+ }
+
+ const ValTy& getStmtData(const Stmt* S) const {
+ return const_cast<DataflowValues*>(this)->getStmtData(S);
+ }
+
+ /// getEdgeDataMap - Retrieves the internal map between CFG edges and
+ /// dataflow values. Usually used by a dataflow solver to compute
+ /// values for blocks.
+ EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
+ const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
+
+ /// getBlockDataMap - Retrieves the internal map between CFGBlocks and
+ /// dataflow values. If the dataflow analysis operates in the forward
+ /// direction, the values correspond to the dataflow values at the start
+ /// of the block. Otherwise, for a backward analysis, the values correpsond
+ /// to the dataflow values at the end of the block.
+ BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
+ const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
+
+ /// getStmtDataMap - Retrieves the internal map between Stmts and
+ /// dataflow values.
+ StmtDataMapTy& getStmtDataMap() {
+ if (!StmtDataMap) StmtDataMap = new StmtDataMapTy();
+ return *StmtDataMap;
+ }
+
+ const StmtDataMapTy& getStmtDataMap() const {
+ return const_cast<DataflowValues*>(this)->getStmtDataMap();
+ }
+
+ /// getAnalysisData - Retrieves the meta data associated with a
+ /// dataflow analysis for analyzing a particular CFG.
+ /// This is typically consumed by transfer function code (via the solver).
+ /// This can also be used by subclasses to interpret the dataflow values.
+ AnalysisDataTy& getAnalysisData() { return AnalysisData; }
+ const AnalysisDataTy& getAnalysisData() const { return AnalysisData; }
+
+ //===--------------------------------------------------------------------===//
+ // Internal data.
+ //===--------------------------------------------------------------------===//
+
+protected:
+ EdgeDataMapTy EdgeDataMap;
+ BlockDataMapTy BlockDataMap;
+ StmtDataMapTy* StmtDataMap;
+ AnalysisDataTy AnalysisData;
+};
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
new file mode 100644
index 0000000..54cfc3d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
@@ -0,0 +1,393 @@
+//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- 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 interface ProgramPoint, which identifies a
+// distinct location in a function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <utility>
+
+namespace clang {
+
+class LocationContext;
+class AnalysisContext;
+class FunctionDecl;
+
+class ProgramPoint {
+public:
+ enum Kind { BlockEdgeKind,
+ BlockEntranceKind,
+ BlockExitKind,
+ PreStmtKind,
+ PostStmtKind,
+ PreLoadKind,
+ PostLoadKind,
+ PreStoreKind,
+ PostStoreKind,
+ PostPurgeDeadSymbolsKind,
+ PostStmtCustomKind,
+ PostLValueKind,
+ PostInitializerKind,
+ CallEnterKind,
+ CallExitKind,
+ MinPostStmtKind = PostStmtKind,
+ MaxPostStmtKind = CallExitKind };
+
+private:
+ std::pair<const void *, const void *> Data;
+ Kind K;
+
+ // The LocationContext could be NULL to allow ProgramPoint to be used in
+ // context insensitive analysis.
+ const LocationContext *L;
+ const void *Tag;
+
+protected:
+ ProgramPoint(const void* P, Kind k, const LocationContext *l,
+ const void *tag = 0)
+ : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
+
+ ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
+ const void *tag = 0)
+ : Data(P1, P2), K(k), L(l), Tag(tag) {}
+
+protected:
+ const void* getData1() const { return Data.first; }
+ const void* getData2() const { return Data.second; }
+
+public:
+ Kind getKind() const { return K; }
+
+ const void *getTag() const { return Tag; }
+
+ const LocationContext *getLocationContext() const { return L; }
+
+ // For use with DenseMap. This hash is probably slow.
+ unsigned getHashValue() const {
+ llvm::FoldingSetNodeID ID;
+ Profile(ID);
+ return ID.ComputeHash();
+ }
+
+ static bool classof(const ProgramPoint*) { return true; }
+
+ bool operator==(const ProgramPoint & RHS) const {
+ return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
+ }
+
+ bool operator!=(const ProgramPoint& RHS) const {
+ return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) K);
+ ID.AddPointer(Data.first);
+ ID.AddPointer(Data.second);
+ ID.AddPointer(L);
+ ID.AddPointer(Tag);
+ }
+};
+
+class BlockEntrance : public ProgramPoint {
+public:
+ BlockEntrance(const CFGBlock* B, const LocationContext *L,
+ const void *tag = 0)
+ : ProgramPoint(B, BlockEntranceKind, L, tag) {}
+
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
+ }
+
+ const CFGElement getFirstElement() const {
+ const CFGBlock* B = getBlock();
+ return B->empty() ? CFGElement() : B->front();
+ }
+
+ /// Create a new BlockEntrance object that is the same as the original
+ /// except for using the specified tag value.
+ BlockEntrance withTag(const void *tag) {
+ return BlockEntrance(getBlock(), getLocationContext(), tag);
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockEntranceKind;
+ }
+};
+
+class BlockExit : public ProgramPoint {
+public:
+ BlockExit(const CFGBlock* B, const LocationContext *L)
+ : ProgramPoint(B, BlockExitKind, L) {}
+
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
+ }
+
+ const Stmt* getTerminator() const {
+ return getBlock()->getTerminator();
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockExitKind;
+ }
+};
+
+class StmtPoint : public ProgramPoint {
+public:
+ StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
+ const void *tag)
+ : ProgramPoint(S, p2, k, L, tag) {}
+
+ const Stmt *getStmt() const { return (const Stmt*) getData1(); }
+
+ template <typename T>
+ const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
+
+ static bool classof(const ProgramPoint* Location) {
+ unsigned k = Location->getKind();
+ return k >= PreStmtKind && k <= MaxPostStmtKind;
+ }
+};
+
+
+class PreStmt : public StmtPoint {
+public:
+ PreStmt(const Stmt *S, const LocationContext *L, const void *tag,
+ const Stmt *SubStmt = 0)
+ : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
+
+ const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PreStmtKind;
+ }
+};
+
+class PostStmt : public StmtPoint {
+protected:
+ PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
+ const void *tag =0)
+ : StmtPoint(S, data, k, L, tag) {}
+
+public:
+ explicit PostStmt(const Stmt* S, Kind k,
+ const LocationContext *L, const void *tag = 0)
+ : StmtPoint(S, NULL, k, L, tag) {}
+
+ explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
+ : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ unsigned k = Location->getKind();
+ return k >= MinPostStmtKind && k <= MaxPostStmtKind;
+ }
+};
+
+class PostStmtCustom : public PostStmt {
+public:
+ PostStmtCustom(const Stmt* S,
+ const std::pair<const void*, const void*>* TaggedData,\
+ const LocationContext *L)
+ : PostStmt(S, TaggedData, PostStmtCustomKind, L) {}
+
+ const std::pair<const void*, const void*>& getTaggedPair() const {
+ return
+ *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2());
+ }
+
+ const void* getTag() const { return getTaggedPair().first; }
+
+ const void* getTaggedData() const { return getTaggedPair().second; }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostStmtCustomKind;
+ }
+};
+
+
+class LocationCheck : public StmtPoint {
+protected:
+ LocationCheck(const Stmt *S, const LocationContext *L,
+ ProgramPoint::Kind K, const void *tag)
+ : StmtPoint(S, NULL, K, L, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ unsigned k = location->getKind();
+ return k == PreLoadKind || k == PreStoreKind;
+ }
+};
+
+class PreLoad : public LocationCheck {
+public:
+ PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreLoadKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreLoadKind;
+ }
+};
+
+class PreStore : public LocationCheck {
+public:
+ PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
+ : LocationCheck(S, L, PreStoreKind, tag) {}
+
+ static bool classof(const ProgramPoint *location) {
+ return location->getKind() == PreStoreKind;
+ }
+};
+
+class PostLoad : public PostStmt {
+public:
+ PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0)
+ : PostStmt(S, PostLoadKind, L, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostLoadKind;
+ }
+};
+
+class PostStore : public PostStmt {
+public:
+ PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0)
+ : PostStmt(S, PostStoreKind, L, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostStoreKind;
+ }
+};
+
+class PostLValue : public PostStmt {
+public:
+ PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0)
+ : PostStmt(S, PostLValueKind, L, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostLValueKind;
+ }
+};
+
+class PostPurgeDeadSymbols : public PostStmt {
+public:
+ PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
+ const void *tag = 0)
+ : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostPurgeDeadSymbolsKind;
+ }
+};
+
+class BlockEdge : public ProgramPoint {
+public:
+ BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
+ : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
+
+ const CFGBlock* getSrc() const {
+ return static_cast<const CFGBlock*>(getData1());
+ }
+
+ const CFGBlock* getDst() const {
+ return static_cast<const CFGBlock*>(getData2());
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockEdgeKind;
+ }
+};
+
+class PostInitializer : public ProgramPoint {
+public:
+ PostInitializer(const CXXCtorInitializer *I,
+ const LocationContext *L)
+ : ProgramPoint(I, PostInitializerKind, L) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == PostInitializerKind;
+ }
+};
+
+class CallEnter : public StmtPoint {
+public:
+ CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
+ const LocationContext *callerCtx)
+ : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
+
+ const Stmt *getCallExpr() const {
+ return static_cast<const Stmt *>(getData1());
+ }
+
+ const StackFrameContext *getCalleeContext() const {
+ return static_cast<const StackFrameContext *>(getData2());
+ }
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == CallEnterKind;
+ }
+};
+
+class CallExit : public StmtPoint {
+public:
+ // CallExit uses the callee's location context.
+ CallExit(const Stmt *S, const LocationContext *L)
+ : StmtPoint(S, 0, CallExitKind, L, 0) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == CallExitKind;
+ }
+};
+
+
+} // end namespace clang
+
+
+namespace llvm { // Traits specialization for DenseMap
+
+template <> struct DenseMapInfo<clang::ProgramPoint> {
+
+static inline clang::ProgramPoint getEmptyKey() {
+ uintptr_t x =
+ reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
+}
+
+static inline clang::ProgramPoint getTombstoneKey() {
+ uintptr_t x =
+ reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
+}
+
+static unsigned getHashValue(const clang::ProgramPoint& Loc) {
+ return Loc.getHashValue();
+}
+
+static bool isEqual(const clang::ProgramPoint& L,
+ const clang::ProgramPoint& R) {
+ return L == R;
+}
+
+};
+
+template <>
+struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h
new file mode 100644
index 0000000..27ecc66
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h
@@ -0,0 +1,307 @@
+// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*--
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides definition of dataflow types used by analyses such
+// as LiveVariables and UninitializedValues. The underlying dataflow values
+// are implemented as bitvectors, but the definitions in this file include
+// the necessary boilerplate to use with our dataflow framework.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STMTDECLBVDVAL_H
+#define LLVM_CLANG_STMTDECLBVDVAL_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+ class Stmt;
+ class ASTContext;
+
+struct DeclBitVector_Types {
+
+ class Idx {
+ unsigned I;
+ public:
+ explicit Idx(unsigned i) : I(i) {}
+ Idx() : I(~0U) {}
+
+ bool isValid() const {
+ return I != ~0U;
+ }
+ operator unsigned() const {
+ assert (isValid());
+ return I;
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // AnalysisDataTy - Whole-function meta data.
+ //===--------------------------------------------------------------------===//
+
+ class AnalysisDataTy {
+ public:
+ typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
+ typedef DMapTy::const_iterator decl_iterator;
+
+ protected:
+ DMapTy DMap;
+ unsigned NDecls;
+
+ public:
+
+ AnalysisDataTy() : NDecls(0) {}
+ virtual ~AnalysisDataTy() {}
+
+ bool isTracked(const NamedDecl* SD) { return DMap.find(SD) != DMap.end(); }
+
+ Idx getIdx(const NamedDecl* SD) const {
+ DMapTy::const_iterator I = DMap.find(SD);
+ return I == DMap.end() ? Idx() : Idx(I->second);
+ }
+
+ unsigned getNumDecls() const { return NDecls; }
+
+ void Register(const NamedDecl* SD) {
+ if (!isTracked(SD)) DMap[SD] = NDecls++;
+ }
+
+ decl_iterator begin_decl() const { return DMap.begin(); }
+ decl_iterator end_decl() const { return DMap.end(); }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // ValTy - Dataflow value.
+ //===--------------------------------------------------------------------===//
+
+ class ValTy {
+ llvm::BitVector DeclBV;
+ public:
+
+ void resetDeclValues(AnalysisDataTy& AD) {
+ DeclBV.resize(AD.getNumDecls());
+ DeclBV.reset();
+ }
+
+ void setDeclValues(AnalysisDataTy& AD) {
+ DeclBV.resize(AD.getNumDecls());
+ DeclBV.set();
+ }
+
+ void resetValues(AnalysisDataTy& AD) {
+ resetDeclValues(AD);
+ }
+
+ bool operator==(const ValTy& RHS) const {
+ assert (sizesEqual(RHS));
+ return DeclBV == RHS.DeclBV;
+ }
+
+ void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
+
+ llvm::BitVector::reference getBit(unsigned i) {
+ return DeclBV[i];
+ }
+
+ bool getBit(unsigned i) const {
+ return DeclBV[i];
+ }
+
+ llvm::BitVector::reference
+ operator()(const NamedDecl* ND, const AnalysisDataTy& AD) {
+ return getBit(AD.getIdx(ND));
+ }
+
+ bool operator()(const NamedDecl* ND, const AnalysisDataTy& AD) const {
+ return getBit(AD.getIdx(ND));
+ }
+
+ llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
+ const llvm::BitVector::reference getDeclBit(unsigned i) const {
+ return const_cast<llvm::BitVector&>(DeclBV)[i];
+ }
+
+ ValTy& operator|=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ DeclBV |= RHS.DeclBV;
+ return *this;
+ }
+
+ ValTy& operator&=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ DeclBV &= RHS.DeclBV;
+ return *this;
+ }
+
+ ValTy& OrDeclBits(const ValTy& RHS) {
+ return operator|=(RHS);
+ }
+
+ ValTy& AndDeclBits(const ValTy& RHS) {
+ return operator&=(RHS);
+ }
+
+ bool sizesEqual(const ValTy& RHS) const {
+ return DeclBV.size() == RHS.DeclBV.size();
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Some useful merge operations.
+ //===--------------------------------------------------------------------===//
+
+ struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
+ struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
+};
+
+
+struct StmtDeclBitVector_Types {
+
+ //===--------------------------------------------------------------------===//
+ // AnalysisDataTy - Whole-function meta data.
+ //===--------------------------------------------------------------------===//
+
+ class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
+ ASTContext* ctx;
+ CFG* cfg;
+ public:
+ AnalysisDataTy() : ctx(0), cfg(0) {}
+ virtual ~AnalysisDataTy() {}
+
+ void setContext(ASTContext& c) { ctx = &c; }
+ ASTContext& getContext() {
+ assert(ctx && "ASTContext should not be NULL.");
+ return *ctx;
+ }
+
+ void setCFG(CFG& c) { cfg = &c; }
+ CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
+
+ bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); }
+ using DeclBitVector_Types::AnalysisDataTy::isTracked;
+
+ unsigned getIdx(const Stmt* S) const {
+ CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
+ assert(I && "Stmtession not tracked for bitvector.");
+ return I;
+ }
+ using DeclBitVector_Types::AnalysisDataTy::getIdx;
+
+ unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // ValTy - Dataflow value.
+ //===--------------------------------------------------------------------===//
+
+ class ValTy : public DeclBitVector_Types::ValTy {
+ llvm::BitVector BlkExprBV;
+ typedef DeclBitVector_Types::ValTy ParentTy;
+
+ static inline ParentTy& ParentRef(ValTy& X) {
+ return static_cast<ParentTy&>(X);
+ }
+
+ static inline const ParentTy& ParentRef(const ValTy& X) {
+ return static_cast<const ParentTy&>(X);
+ }
+
+ public:
+
+ void resetBlkExprValues(AnalysisDataTy& AD) {
+ BlkExprBV.resize(AD.getNumBlkExprs());
+ BlkExprBV.reset();
+ }
+
+ void setBlkExprValues(AnalysisDataTy& AD) {
+ BlkExprBV.resize(AD.getNumBlkExprs());
+ BlkExprBV.set();
+ }
+
+ void resetValues(AnalysisDataTy& AD) {
+ resetDeclValues(AD);
+ resetBlkExprValues(AD);
+ }
+
+ void setValues(AnalysisDataTy& AD) {
+ setDeclValues(AD);
+ setBlkExprValues(AD);
+ }
+
+ bool operator==(const ValTy& RHS) const {
+ return ParentRef(*this) == ParentRef(RHS)
+ && BlkExprBV == RHS.BlkExprBV;
+ }
+
+ void copyValues(const ValTy& RHS) {
+ ParentRef(*this).copyValues(ParentRef(RHS));
+ BlkExprBV = RHS.BlkExprBV;
+ }
+
+ llvm::BitVector::reference
+ operator()(const Stmt* S, const AnalysisDataTy& AD) {
+ return BlkExprBV[AD.getIdx(S)];
+ }
+ const llvm::BitVector::reference
+ operator()(const Stmt* S, const AnalysisDataTy& AD) const {
+ return const_cast<ValTy&>(*this)(S,AD);
+ }
+
+ using DeclBitVector_Types::ValTy::operator();
+
+
+ llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; }
+ const llvm::BitVector::reference getStmtBit(unsigned i) const {
+ return const_cast<llvm::BitVector&>(BlkExprBV)[i];
+ }
+
+ ValTy& OrBlkExprBits(const ValTy& RHS) {
+ BlkExprBV |= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& AndBlkExprBits(const ValTy& RHS) {
+ BlkExprBV &= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& operator|=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ ParentRef(*this) |= ParentRef(RHS);
+ BlkExprBV |= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& operator&=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ ParentRef(*this) &= ParentRef(RHS);
+ BlkExprBV &= RHS.BlkExprBV;
+ return *this;
+ }
+
+ bool sizesEqual(const ValTy& RHS) const {
+ return ParentRef(*this).sizesEqual(ParentRef(RHS))
+ && BlkExprBV.size() == RHS.BlkExprBV.size();
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Some useful merge operations.
+ //===--------------------------------------------------------------------===//
+
+ struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
+ struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
+
+};
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
new file mode 100644
index 0000000..83532e6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
@@ -0,0 +1,244 @@
+//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides BumpVector, a vector-like ADT whose contents are
+// allocated from a BumpPtrAllocator.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: Most of this is copy-and-paste from SmallVector.h. We can
+// refactor this core logic into something common that is shared between
+// the two. The main thing that is different is the allocation strategy.
+
+#ifndef LLVM_CLANG_BUMP_VECTOR
+#define LLVM_CLANG_BUMP_VECTOR
+
+#include "llvm/Support/type_traits.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+#include <memory>
+
+namespace clang {
+
+class BumpVectorContext {
+ llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
+public:
+ /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator
+ /// and destroys it when the BumpVectorContext object is destroyed.
+ BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}
+
+ /// Construct a new BumpVectorContext that reuses an existing
+ /// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
+ /// BumpVectorContext object is destroyed.
+ BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}
+
+ ~BumpVectorContext() {
+ if (Alloc.getInt())
+ delete Alloc.getPointer();
+ }
+
+ llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); }
+};
+
+template<typename T>
+class BumpVector {
+ T *Begin, *End, *Capacity;
+public:
+ // Default ctor - Initialize to empty.
+ explicit BumpVector(BumpVectorContext &C, unsigned N)
+ : Begin(NULL), End(NULL), Capacity(NULL) {
+ reserve(C, N);
+ }
+
+ ~BumpVector() {
+ if (llvm::is_class<T>::value) {
+ // Destroy the constructed elements in the vector.
+ destroy_range(Begin, End);
+ }
+ }
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+
+ // forward iterator creation methods.
+ iterator begin() { return Begin; }
+ const_iterator begin() const { return Begin; }
+ iterator end() { return End; }
+ const_iterator end() const { return End; }
+
+ // reverse iterator creation methods.
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+ bool empty() const { return Begin == End; }
+ size_type size() const { return End-Begin; }
+
+ reference operator[](unsigned idx) {
+ assert(Begin + idx < End);
+ return Begin[idx];
+ }
+ const_reference operator[](unsigned idx) const {
+ assert(Begin + idx < End);
+ return Begin[idx];
+ }
+
+ reference front() {
+ return begin()[0];
+ }
+ const_reference front() const {
+ return begin()[0];
+ }
+
+ reference back() {
+ return end()[-1];
+ }
+ const_reference back() const {
+ return end()[-1];
+ }
+
+ void pop_back() {
+ --End;
+ End->~T();
+ }
+
+ T pop_back_val() {
+ T Result = back();
+ pop_back();
+ return Result;
+ }
+
+ void clear() {
+ if (llvm::is_class<T>::value) {
+ destroy_range(Begin, End);
+ }
+ End = Begin;
+ }
+
+ /// data - Return a pointer to the vector's buffer, even if empty().
+ pointer data() {
+ return pointer(Begin);
+ }
+
+ /// data - Return a pointer to the vector's buffer, even if empty().
+ const_pointer data() const {
+ return const_pointer(Begin);
+ }
+
+ void push_back(const_reference Elt, BumpVectorContext &C) {
+ if (End < Capacity) {
+ Retry:
+ new (End) T(Elt);
+ ++End;
+ return;
+ }
+ grow(C);
+ goto Retry;
+ }
+
+ /// insert - Insert some number of copies of element into a position. Return
+ /// iterator to position after last inserted copy.
+ iterator insert(iterator I, size_t Cnt, const_reference E,
+ BumpVectorContext &C) {
+ assert (I >= Begin && I <= End && "Iterator out of bounds.");
+ if (End + Cnt <= Capacity) {
+ Retry:
+ move_range_right(I, End, Cnt);
+ construct_range(I, I + Cnt, E);
+ End += Cnt;
+ return I + Cnt;
+ }
+ ptrdiff_t D = I - Begin;
+ grow(C, size() + Cnt);
+ I = Begin + D;
+ goto Retry;
+ }
+
+ void reserve(BumpVectorContext &C, unsigned N) {
+ if (unsigned(Capacity-Begin) < N)
+ grow(C, N);
+ }
+
+ /// capacity - Return the total number of elements in the currently allocated
+ /// buffer.
+ size_t capacity() const { return Capacity - Begin; }
+
+private:
+ /// grow - double the size of the allocated memory, guaranteeing space for at
+ /// least one more element or MinSize if specified.
+ void grow(BumpVectorContext &C, size_type MinSize = 1);
+
+ void construct_range(T *S, T *E, const T &Elt) {
+ for (; S != E; ++S)
+ new (S) T(Elt);
+ }
+
+ void destroy_range(T *S, T *E) {
+ while (S != E) {
+ --E;
+ E->~T();
+ }
+ }
+
+ void move_range_right(T *S, T *E, size_t D) {
+ for (T *I = E + D - 1, *IL = S + D - 1; I != IL; --I) {
+ --E;
+ new (I) T(*E);
+ E->~T();
+ }
+ }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T>
+void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
+ size_t CurCapacity = Capacity-Begin;
+ size_t CurSize = size();
+ size_t NewCapacity = 2*CurCapacity;
+ if (NewCapacity < MinSize)
+ NewCapacity = MinSize;
+
+ // Allocate the memory from the BumpPtrAllocator.
+ T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
+
+ // Copy the elements over.
+ if (llvm::is_class<T>::value) {
+ std::uninitialized_copy(Begin, End, NewElts);
+ // Destroy the original elements.
+ destroy_range(Begin, End);
+ }
+ else {
+ // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
+ memcpy(NewElts, Begin, CurSize * sizeof(T));
+ }
+
+ // For now, leak 'Begin'. We can add it back to a freelist in
+ // BumpVectorContext.
+ Begin = NewElts;
+ End = NewElts+CurSize;
+ Capacity = Begin+NewCapacity;
+}
+
+} // end: clang namespace
+#endif // end: LLVM_CLANG_BUMP_VECTOR
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h
new file mode 100644
index 0000000..f720639
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/SaveAndRestore.h
@@ -0,0 +1,47 @@
+//===-- SaveAndRestore.h - Utility -------------------------------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides utility classes that uses RAII to save and restore
+// values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_SAVERESTORE
+#define LLVM_CLANG_ANALYSIS_SAVERESTORE
+
+namespace clang {
+
+// SaveAndRestore - A utility class that uses RAII to save and restore
+// the value of a variable.
+template<typename T>
+struct SaveAndRestore {
+ SaveAndRestore(T& x) : X(x), old_value(x) {}
+ SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) {
+ X = new_value;
+ }
+ ~SaveAndRestore() { X = old_value; }
+ T get() { return old_value; }
+private:
+ T& X;
+ T old_value;
+};
+
+// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old
+// value of a variable is saved, and during the dstor the old value is
+// or'ed with the new value.
+struct SaveOr {
+ SaveOr(bool& x) : X(x), old_value(x) { x = false; }
+ ~SaveOr() { X |= old_value; }
+private:
+ bool& X;
+ const bool old_value;
+};
+
+}
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
new file mode 100644
index 0000000..95f4ace
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -0,0 +1,102 @@
+//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- C++ --*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the template class CFGRecStmtDeclVisitor, which extends
+// CFGRecStmtVisitor by implementing (typed) visitation of decls.
+//
+// FIXME: This may not be fully complete. We currently explore only subtypes
+// of ScopedDecl.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
+
+#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+
+#define DISPATCH_CASE(CLASS) \
+case Decl::CLASS: \
+static_cast<ImplClass*>(this)->Visit##CLASS##Decl( \
+ static_cast<CLASS##Decl*>(D)); \
+break;
+
+#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D) {}
+#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D)\
+ { static_cast<ImplClass*>(this)->VisitVarDecl(D); }
+
+
+namespace clang {
+template <typename ImplClass>
+class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
+public:
+
+ void VisitDeclRefExpr(DeclRefExpr* DR) {
+ static_cast<ImplClass*>(this)->VisitDecl(DR->getDecl());
+ }
+
+ void VisitDeclStmt(DeclStmt* DS) {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI) {
+ Decl* D = *DI;
+ static_cast<ImplClass*>(this)->VisitDecl(D);
+ // Visit the initializer.
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ if (Expr* I = VD->getInit())
+ static_cast<ImplClass*>(this)->Visit(I);
+ }
+ }
+
+ void VisitDecl(Decl* D) {
+ switch (D->getKind()) {
+ DISPATCH_CASE(Function)
+ DISPATCH_CASE(CXXMethod)
+ DISPATCH_CASE(Var)
+ DISPATCH_CASE(ParmVar) // FIXME: (same)
+ DISPATCH_CASE(ImplicitParam)
+ DISPATCH_CASE(EnumConstant)
+ DISPATCH_CASE(Typedef)
+ DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl?
+ DISPATCH_CASE(CXXRecord)
+ DISPATCH_CASE(Enum)
+ DISPATCH_CASE(UsingDirective)
+ DISPATCH_CASE(Using)
+ default:
+ assert(false && "Subtype of ScopedDecl not handled.");
+ }
+ }
+
+ DEFAULT_DISPATCH(Var)
+ DEFAULT_DISPATCH(Function)
+ DEFAULT_DISPATCH(CXXMethod)
+ DEFAULT_DISPATCH_VARDECL(ParmVar)
+ DEFAULT_DISPATCH(ImplicitParam)
+ DEFAULT_DISPATCH(EnumConstant)
+ DEFAULT_DISPATCH(Typedef)
+ DEFAULT_DISPATCH(Record)
+ DEFAULT_DISPATCH(Enum)
+ DEFAULT_DISPATCH(ObjCInterface)
+ DEFAULT_DISPATCH(ObjCClass)
+ DEFAULT_DISPATCH(ObjCMethod)
+ DEFAULT_DISPATCH(ObjCProtocol)
+ DEFAULT_DISPATCH(ObjCCategory)
+ DEFAULT_DISPATCH(UsingDirective)
+ DEFAULT_DISPATCH(Using)
+
+ void VisitCXXRecordDecl(CXXRecordDecl *D) {
+ static_cast<ImplClass*>(this)->VisitRecordDecl(D);
+ }
+};
+
+} // end namespace clang
+
+#undef DISPATCH_CASE
+#undef DEFAULT_DISPATCH
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
new file mode 100644
index 0000000..bb7cf0b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
@@ -0,0 +1,59 @@
+//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the template class CFGRecStmtVisitor, which extends
+// CFGStmtVisitor by implementing a default recursive visit of all statements.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
+
+#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
+
+namespace clang {
+template <typename ImplClass>
+class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
+public:
+
+ void VisitStmt(Stmt* S) {
+ static_cast< ImplClass* >(this)->VisitChildren(S);
+ }
+
+ void VisitCompoundStmt(CompoundStmt *S) {
+ // Do nothing. Everything in a CompoundStmt is inlined
+ // into the CFG.
+ }
+
+ void VisitConditionVariableInit(Stmt *S) {
+ assert(S == this->getCurrentBlkStmt());
+ VarDecl *CondVar = 0;
+ switch (S->getStmtClass()) {
+#define CONDVAR_CASE(CLASS) \
+case Stmt::CLASS ## Class:\
+CondVar = cast<CLASS>(S)->getConditionVariable();\
+break;
+ CONDVAR_CASE(IfStmt)
+ CONDVAR_CASE(ForStmt)
+ CONDVAR_CASE(SwitchStmt)
+ CONDVAR_CASE(WhileStmt)
+#undef CONDVAR_CASE
+ default:
+ assert(false && "Infeasible");
+ }
+ static_cast<ImplClass*>(this)->Visit(CondVar->getInit());
+ }
+
+ // Defining operator() allows the visitor to be used as a C++ style functor.
+ void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h
new file mode 100644
index 0000000..d197e69
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -0,0 +1,170 @@
+//===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- 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 CFGStmtVisitor interface, which extends
+// StmtVisitor. This interface is useful for visiting statements in a CFG
+// where some statements have implicit control-flow and thus should
+// be treated specially.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/CFG.h"
+
+namespace clang {
+
+#define DISPATCH_CASE(CLASS) \
+case Stmt::CLASS ## Class: return \
+static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
+
+#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
+{ return\
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\
+ cast<Expr>(S)); }
+
+template <typename ImplClass, typename RetTy=void>
+class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
+ Stmt* CurrentBlkStmt;
+
+ struct NullifyStmt {
+ Stmt*& S;
+
+ NullifyStmt(Stmt*& s) : S(s) {}
+ ~NullifyStmt() { S = NULL; }
+ };
+
+public:
+ CFGStmtVisitor() : CurrentBlkStmt(NULL) {}
+
+ Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; }
+
+ RetTy Visit(Stmt* S) {
+ if (S == CurrentBlkStmt ||
+ !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
+ return StmtVisitor<ImplClass,RetTy>::Visit(S);
+ else
+ return RetTy();
+ }
+
+ /// VisitConditionVariableInit - Handle the initialization of condition
+ /// variables at branches. Valid statements include IfStmt, ForStmt,
+ /// WhileStmt, and SwitchStmt.
+ RetTy VisitConditionVariableInit(Stmt *S) {
+ return RetTy();
+ }
+
+ /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
+ /// CFGBlocks. Root statements are the statements that appear explicitly in
+ /// the list of statements in a CFGBlock. For substatements, or when there
+ /// is no implementation provided for a BlockStmt_XXX method, we default
+ /// to using StmtVisitor's Visit method.
+ RetTy BlockStmt_Visit(Stmt* S) {
+ CurrentBlkStmt = S;
+ NullifyStmt cleanup(CurrentBlkStmt);
+
+ switch (S->getStmtClass()) {
+ case Stmt::IfStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::SwitchStmtClass:
+ return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S);
+
+ DISPATCH_CASE(StmtExpr)
+ DISPATCH_CASE(ConditionalOperator)
+ DISPATCH_CASE(BinaryConditionalOperator)
+ DISPATCH_CASE(ObjCForCollectionStmt)
+
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator* B = cast<BinaryOperator>(S);
+ if (B->isLogicalOp())
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
+ else if (B->getOpcode() == BO_Comma)
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
+ // Fall through.
+ }
+
+ default:
+ if (isa<Expr>(S))
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S));
+ else
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
+ }
+ }
+
+ DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
+ DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
+ DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator)
+
+ RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
+ }
+
+ RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
+ }
+
+ RetTy BlockStmt_VisitExpr(Expr* E) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
+ }
+
+ RetTy BlockStmt_VisitStmt(Stmt* S) {
+ return static_cast<ImplClass*>(this)->Visit(S);
+ }
+
+ RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
+ }
+
+ RetTy BlockStmt_VisitComma(BinaryOperator* B) {
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Utility methods. Not called by default (but subclasses may use them).
+ //===--------------------------------------------------------------------===//
+
+ /// VisitChildren: Call "Visit" on each child of S.
+ void VisitChildren(Stmt* S) {
+
+ switch (S->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::StmtExprClass: {
+ CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt();
+ if (CS->body_empty()) return;
+ static_cast<ImplClass*>(this)->Visit(CS->body_back());
+ return;
+ }
+
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator* B = cast<BinaryOperator>(S);
+ if (B->getOpcode() != BO_Comma) break;
+ static_cast<ImplClass*>(this)->Visit(B->getRHS());
+ return;
+ }
+ }
+
+ for (Stmt::child_range I = S->children(); I; ++I)
+ if (*I) static_cast<ImplClass*>(this)->Visit(*I);
+ }
+};
+
+#undef DEFAULT_BLOCKSTMT_VISIT
+#undef DISPATCH_CASE
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ABI.h b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
new file mode 100644
index 0000000..018f500
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
@@ -0,0 +1,126 @@
+//===----- ABI.h - ABI related declarations ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These enums/classes describe ABI related information about constructors,
+// destructors and thunks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_BASIC_ABI_H
+#define CLANG_BASIC_ABI_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+/// CXXCtorType - C++ constructor types
+enum CXXCtorType {
+ Ctor_Complete, // Complete object ctor
+ Ctor_Base, // Base object ctor
+ Ctor_CompleteAllocating // Complete object allocating ctor
+};
+
+/// CXXDtorType - C++ destructor types
+enum CXXDtorType {
+ Dtor_Deleting, // Deleting dtor
+ Dtor_Complete, // Complete object dtor
+ Dtor_Base // Base object dtor
+};
+
+/// ReturnAdjustment - A return adjustment.
+struct ReturnAdjustment {
+ /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// VBaseOffsetOffset - The offset (in bytes), relative to the address point
+ /// of the virtual base class offset.
+ int64_t VBaseOffsetOffset;
+
+ ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
+
+ bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
+
+ friend bool operator==(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset;
+ }
+
+ friend bool operator<(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VBaseOffsetOffset < RHS.VBaseOffsetOffset;
+ }
+};
+
+/// ThisAdjustment - A 'this' pointer adjustment.
+struct ThisAdjustment {
+ /// NonVirtual - The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// VCallOffsetOffset - The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
+
+ ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
+
+ bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
+
+ friend bool operator==(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VCallOffsetOffset == RHS.VCallOffsetOffset;
+ }
+
+ friend bool operator<(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VCallOffsetOffset < RHS.VCallOffsetOffset;
+ }
+};
+
+/// ThunkInfo - The 'this' pointer adjustment as well as an optional return
+/// adjustment for a thunk.
+struct ThunkInfo {
+ /// This - The 'this' pointer adjustment.
+ ThisAdjustment This;
+
+ /// Return - The return adjustment.
+ ReturnAdjustment Return;
+
+ ThunkInfo() { }
+
+ ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
+ : This(This), Return(Return) { }
+
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.This == RHS.This && LHS.Return == RHS.Return;
+ }
+
+ friend bool operator<(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ if (LHS.This < RHS.This)
+ return true;
+
+ return LHS.This == RHS.This && LHS.Return < RHS.Return;
+ }
+
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+};
+
+} // end namespace clang
+
+#endif // CLANG_BASIC_ABI_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
new file mode 100644
index 0000000..3e62d41
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
@@ -0,0 +1,487 @@
+////////////////////////////////////////////////////////////////////////////////
+// Note: This file is a work in progress. Please do not apply non-trivial
+// updates unless you have talked to Sean Hunt <rideau3@gmail.com> prior.
+// Merely adding a new attribute is a trivial update.
+////////////////////////////////////////////////////////////////////////////////
+
+// An attribute's subject is whatever it appertains to. In this file, it is
+// more accurately a list of things that an attribute can appertain to. All
+// Decls and Stmts are possibly AttrSubjects (even though the syntax may not
+// allow attributes on a given Decl or Stmt).
+class AttrSubject;
+
+include "clang/Basic/DeclNodes.td"
+include "clang/Basic/StmtNodes.td"
+
+// A subset-subject is an AttrSubject constrained to operate only on some subset
+// of that subject.
+//
+// The description is used in output messages to specify what the subject
+// represents. FIXME: Deal with translation issues.
+//
+// The code fragment is a boolean expression that will confirm that the subject
+// meets the requirements; the subject will have the name S, and will have the
+// type specified by the base. It should be a simple boolean expression.
+class SubsetSubject<AttrSubject base, string description, code check>
+ : AttrSubject {
+ AttrSubject Base = base;
+ string Description = description;
+ code CheckCode = check;
+}
+
+// This is the type of a variable which C++0x defines [[aligned()]] as being
+// a possible subject.
+def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
+ [{S->getStorageClass() != VarDecl::Register &&
+ S->getKind() != Decl::ImplicitParam &&
+ S->getKind() != Decl::ParmVar &&
+ S->getKind() != Decl::NonTypeTemplateParm}]>;
+def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
+ [{S->isVirtual()}]>;
+def NonBitField : SubsetSubject<Field, "non-bit field",
+ [{!S->isBitField()}]>;
+
+// A single argument to an attribute
+class Argument<string name> {
+ string Name = name;
+}
+
+class IdentifierArgument<string name> : Argument<name>;
+class IntArgument<string name> : Argument<name>;
+class StringArgument<string name> : Argument<name>;
+class ExprArgument<string name> : Argument<name>;
+class FunctionArgument<string name> : Argument<name>;
+class TypeArgument<string name> : Argument<name>;
+class UnsignedArgument<string name> : Argument<name>;
+class VariadicUnsignedArgument<string name> : Argument<name>;
+
+// This one's a doozy, so it gets its own special type
+// It can be an unsigned integer, or a type. Either can
+// be dependent.
+class AlignedArgument<string name> : Argument<name>;
+
+// An integer argument with a default value
+class DefaultIntArgument<string name, int default> : IntArgument<name> {
+ int Default = default;
+}
+
+// This argument is more complex, it includes the enumerator type name,
+// a list of strings to accept, and a list of enumerators to map them to.
+class EnumArgument<string name, string type, list<string> values,
+ list<string> enums> : Argument<name> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
+}
+
+class Attr {
+ // The various ways in which an attribute can be spelled in source
+ list<string> Spellings;
+ // The things to which an attribute can appertain
+ list<AttrSubject> Subjects;
+ // The arguments allowed on an attribute
+ list<Argument> Args = [];
+ // The namespaces in which the attribute appears in C++0x attributes.
+ // The attribute will not be permitted in C++0x attribute-specifiers if
+ // this is empty; the empty string can be used as a namespace.
+ list<string> Namespaces = [];
+ // Any additional text that should be included verbatim in the class.
+ code AdditionalMembers = [{}];
+}
+
+class InheritableAttr : Attr;
+
+//
+// Attributes begin here
+//
+
+def Alias : InheritableAttr {
+ let Spellings = ["alias"];
+ let Args = [StringArgument<"Aliasee">];
+}
+
+def Aligned : InheritableAttr {
+ let Spellings = ["align", "aligned"];
+ let Subjects = [NonBitField, NormalVar, Tag];
+ let Args = [AlignedArgument<"Alignment">];
+ let Namespaces = ["", "std"];
+}
+
+def AlignMac68k : InheritableAttr {
+ let Spellings = [];
+}
+
+def AlwaysInline : InheritableAttr {
+ let Spellings = ["always_inline"];
+}
+
+def AnalyzerNoReturn : InheritableAttr {
+ let Spellings = ["analyzer_noreturn"];
+}
+
+def Annotate : InheritableAttr {
+ let Spellings = ["annotate"];
+ let Args = [StringArgument<"Annotation">];
+}
+
+def AsmLabel : InheritableAttr {
+ let Spellings = [];
+ let Args = [StringArgument<"Label">];
+}
+
+def Blocks : InheritableAttr {
+ let Spellings = ["blocks"];
+ let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
+}
+
+def CarriesDependency : InheritableAttr {
+ let Spellings = ["carries_dependency"];
+ let Subjects = [ParmVar, Function];
+ let Namespaces = ["", "std"];
+}
+
+def CDecl : InheritableAttr {
+ let Spellings = ["cdecl", "__cdecl"];
+}
+
+def CFReturnsRetained : InheritableAttr {
+ let Spellings = ["cf_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def CFReturnsNotRetained : InheritableAttr {
+ let Spellings = ["cf_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def CFConsumed : InheritableAttr {
+ let Spellings = ["cf_consumed"];
+ let Subjects = [ParmVar];
+}
+
+def Cleanup : InheritableAttr {
+ let Spellings = ["cleanup"];
+ let Args = [FunctionArgument<"FunctionDecl">];
+}
+
+def Common : InheritableAttr {
+ let Spellings = ["common"];
+}
+
+def Const : InheritableAttr {
+ let Spellings = ["const"];
+}
+
+def Constructor : InheritableAttr {
+ let Spellings = ["constructor"];
+ let Args = [IntArgument<"Priority">];
+}
+
+def CUDAConstant : InheritableAttr {
+ let Spellings = ["constant"];
+}
+
+def CUDADevice : Attr {
+ let Spellings = ["device"];
+}
+
+def CUDAGlobal : InheritableAttr {
+ let Spellings = ["global"];
+}
+
+def CUDAHost : Attr {
+ let Spellings = ["host"];
+}
+
+def CUDALaunchBounds : InheritableAttr {
+ let Spellings = ["launch_bounds"];
+ let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
+}
+
+def CUDAShared : InheritableAttr {
+ let Spellings = ["shared"];
+}
+
+def OpenCLKernel : Attr {
+ let Spellings = ["opencl_kernel_function"];
+}
+
+def Deprecated : InheritableAttr {
+ let Spellings = ["deprecated"];
+ let Args = [StringArgument<"Message">];
+}
+
+def Destructor : InheritableAttr {
+ let Spellings = ["destructor"];
+ let Args = [IntArgument<"Priority">];
+}
+
+def DLLExport : InheritableAttr {
+ let Spellings = ["dllexport"];
+}
+
+def DLLImport : InheritableAttr {
+ let Spellings = ["dllimport"];
+}
+
+def Explicit : InheritableAttr {
+ let Spellings = [];
+}
+
+def FastCall : InheritableAttr {
+ let Spellings = ["fastcall", "__fastcall"];
+}
+
+def Final : InheritableAttr {
+ let Spellings = [];
+}
+
+def Format : InheritableAttr {
+ let Spellings = ["format"];
+ let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
+ IntArgument<"FirstArg">];
+}
+
+def FormatArg : InheritableAttr {
+ let Spellings = ["format_arg"];
+ let Args = [IntArgument<"FormatIdx">];
+}
+
+def GNUInline : InheritableAttr {
+ let Spellings = ["gnu_inline"];
+}
+
+def IBAction : InheritableAttr {
+ let Spellings = ["ibaction"];
+}
+
+def IBOutlet : InheritableAttr {
+ let Spellings = ["iboutlet"];
+}
+
+def IBOutletCollection : InheritableAttr {
+ let Spellings = ["iboutletcollection"];
+ let Args = [TypeArgument<"Interface">];
+}
+
+def Malloc : InheritableAttr {
+ let Spellings = ["malloc"];
+}
+
+def MaxFieldAlignment : InheritableAttr {
+ let Spellings = [];
+ let Args = [UnsignedArgument<"Alignment">];
+}
+
+def MayAlias : InheritableAttr {
+ let Spellings = ["may_alias"];
+}
+
+def MSP430Interrupt : InheritableAttr {
+ let Spellings = [];
+ let Args = [UnsignedArgument<"Number">];
+}
+
+def MBlazeInterruptHandler : InheritableAttr {
+ let Spellings = [];
+}
+
+def MBlazeSaveVolatiles : InheritableAttr {
+ let Spellings = [];
+}
+
+def Naked : InheritableAttr {
+ let Spellings = ["naked"];
+}
+
+def NoCommon : InheritableAttr {
+ let Spellings = ["nocommon"];
+}
+
+def NoDebug : InheritableAttr {
+ let Spellings = ["nodebug"];
+}
+
+def NoInline : InheritableAttr {
+ let Spellings = ["noinline"];
+}
+
+def NonNull : InheritableAttr {
+ let Spellings = ["nonnull"];
+ let Args = [VariadicUnsignedArgument<"Args">];
+ let AdditionalMembers =
+[{bool isNonNull(unsigned idx) const {
+ for (args_iterator i = args_begin(), e = args_end();
+ i != e; ++i)
+ if (*i == idx)
+ return true;
+ return false;
+ } }];
+}
+
+def NoReturn : InheritableAttr {
+ let Spellings = ["noreturn"];
+ // FIXME: Does GCC allow this on the function instead?
+ let Subjects = [Function];
+ let Namespaces = ["", "std"];
+}
+
+def NoInstrumentFunction : InheritableAttr {
+ let Spellings = ["no_instrument_function"];
+ let Subjects = [Function];
+}
+
+def NoThrow : InheritableAttr {
+ let Spellings = ["nothrow"];
+}
+
+def NSReturnsRetained : InheritableAttr {
+ let Spellings = ["ns_returns_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def NSReturnsNotRetained : InheritableAttr {
+ let Spellings = ["ns_returns_not_retained"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def NSReturnsAutoreleased : InheritableAttr {
+ let Spellings = ["ns_returns_autoreleased"];
+ let Subjects = [ObjCMethod, Function];
+}
+
+def NSConsumesSelf : InheritableAttr {
+ let Spellings = ["ns_consumes_self"];
+ let Subjects = [ObjCMethod];
+}
+
+def NSConsumed : InheritableAttr {
+ let Spellings = ["ns_consumed"];
+ let Subjects = [ParmVar];
+}
+
+def ObjCException : InheritableAttr {
+ let Spellings = ["objc_exception"];
+}
+
+def ObjCNSObject : InheritableAttr {
+ let Spellings = ["NSObject"];
+}
+
+def Overloadable : Attr {
+ let Spellings = ["overloadable"];
+}
+
+def Override : InheritableAttr {
+ let Spellings = [];
+}
+
+def Ownership : InheritableAttr {
+ let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
+ let Args = [EnumArgument<"OwnKind", "OwnershipKind",
+ ["ownership_holds", "ownership_returns", "ownership_takes"],
+ ["Holds", "Returns", "Takes"]>,
+ StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
+}
+
+def Packed : InheritableAttr {
+ let Spellings = ["packed"];
+}
+
+def Pure : InheritableAttr {
+ let Spellings = ["pure"];
+}
+
+def Regparm : InheritableAttr {
+ let Spellings = ["regparm"];
+ let Args = [UnsignedArgument<"NumParams">];
+}
+
+def ReqdWorkGroupSize : InheritableAttr {
+ let Spellings = ["reqd_work_group_size"];
+ let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
+}
+
+def InitPriority : InheritableAttr {
+ let Spellings = ["init_priority"];
+ let Args = [UnsignedArgument<"Priority">];
+}
+
+def Section : InheritableAttr {
+ let Spellings = ["section"];
+ let Args = [StringArgument<"Name">];
+}
+
+def Sentinel : InheritableAttr {
+ let Spellings = ["sentinel"];
+ let Args = [DefaultIntArgument<"Sentinel", 0>,
+ DefaultIntArgument<"NullPos", 0>];
+}
+
+def StdCall : InheritableAttr {
+ let Spellings = ["stdcall", "__stdcall"];
+}
+
+def ThisCall : InheritableAttr {
+ let Spellings = ["thiscall", "__thiscall"];
+}
+
+def Pascal : InheritableAttr {
+ let Spellings = ["pascal", "__pascal"];
+}
+
+def TransparentUnion : InheritableAttr {
+ let Spellings = ["transparent_union"];
+}
+
+def Unavailable : InheritableAttr {
+ let Spellings = ["unavailable"];
+ let Args = [StringArgument<"Message">];
+}
+
+def Unused : InheritableAttr {
+ let Spellings = ["unused"];
+}
+
+def Used : InheritableAttr {
+ let Spellings = ["used"];
+}
+
+def Uuid : InheritableAttr {
+ let Spellings = ["uuid"];
+ let Args = [StringArgument<"Guid">];
+ let Subjects = [CXXRecord];
+}
+
+def Visibility : InheritableAttr {
+ let Spellings = ["visibility"];
+ let Args = [EnumArgument<"Visibility", "VisibilityType",
+ ["default", "hidden", "internal", "protected"],
+ ["Default", "Hidden", "Hidden", "Protected"]>];
+}
+
+def VecReturn : InheritableAttr {
+ let Spellings = ["vecreturn"];
+ let Subjects = [CXXRecord];
+}
+
+def WarnUnusedResult : InheritableAttr {
+ let Spellings = ["warn_unused_result"];
+}
+
+def Weak : InheritableAttr {
+ let Spellings = ["weak"];
+}
+
+def WeakImport : InheritableAttr {
+ let Spellings = ["weak_import"];
+}
+
+def WeakRef : InheritableAttr {
+ let Spellings = ["weakref"];
+}
+
+def X86ForceAlignArgPointer : InheritableAttr {
+ let Spellings = [];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
new file mode 100644
index 0000000..65c4f98
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
@@ -0,0 +1,32 @@
+//===----- Attr.h - Enum values for C Attribute Kinds ----------*- 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 attr::Kind enum
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ATTRKINDS_H
+#define LLVM_CLANG_ATTRKINDS_H
+
+namespace clang {
+
+namespace attr {
+
+// Kind - This is a list of all the recognized kinds of attributes.
+enum Kind {
+#define ATTR(X) X,
+#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
+#include "clang/Basic/AttrList.inc"
+ NUM_ATTRS
+};
+
+} // end namespace attr
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
new file mode 100644
index 0000000..7d270ad
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -0,0 +1,728 @@
+//===--- Builtins.def - Builtin function info database ----------*- 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 standard builtin function database. Users of this file
+// must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: This should really be a .td file, but that requires modifying tblgen.
+// Perhaps tblgen should have plugins.
+
+// The first value provided to the macro specifies the function name of the
+// builtin, and results in a clang::builtin::BIXX enum value for XX.
+
+// The second value provided to the macro specifies the type of the function
+// (result value, then each argument) as follows:
+// v -> void
+// b -> boolean
+// c -> char
+// s -> short
+// i -> int
+// f -> float
+// d -> double
+// z -> size_t
+// F -> constant CFString
+// G -> id
+// H -> SEL
+// a -> __builtin_va_list
+// A -> "reference" to __builtin_va_list
+// V -> Vector, following num elements and a base type.
+// X -> _Complex, followed by the base type.
+// P -> FILE
+// J -> jmp_buf
+// SJ -> sigjmp_buf
+// . -> "...". This may only occur at the end of the function list.
+//
+// Types may be prefixed with the following modifiers:
+// L -> long (e.g. Li for 'long int')
+// LL -> long long
+// LLL -> __int128_t (e.g. LLLi)
+// S -> signed
+// U -> unsigned
+// I -> Required to constant fold to an integer constant expression.
+//
+// Types may be postfixed with the following modifiers:
+// * -> pointer (optionally followed by an address space number)
+// & -> reference (optionally followed by an address space number)
+// C -> const
+// D -> volatile
+
+// The third value provided to the macro specifies information about attributes
+// of the function. These must be kept in sync with the predicates in the
+// Builtin::Context class. Currently we have:
+// n -> nothrow
+// r -> noreturn
+// c -> const
+// F -> this is a libc/libm function with a '__builtin_' prefix added.
+// f -> this is a libc/libm function without the '__builtin_' prefix. It can
+// be followed by ':headername:' to state which header this function
+// comes from.
+// p:N: -> this is a printf-like function whose Nth argument is the format
+// string.
+// P:N: -> similar to the p:N: attribute, but the function is like vprintf
+// in that it accepts its arguments as a va_list rather than
+// through an ellipsis
+// s:N: -> this is a scanf-like function whose Nth argument is the format
+// string.
+// S:N: -> similar to the s:N: attribute, but the function is like vscanf
+// in that it accepts its arguments as a va_list rather than
+// through an ellipsis
+// e -> const, but only when -fmath-errno=0
+// FIXME: gcc has nonnull
+
+#if defined(BUILTIN) && !defined(LIBBUILTIN)
+# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// Standard libc/libm functions:
+BUILTIN(__builtin_atan2 , "ddd" , "Fnc")
+BUILTIN(__builtin_atan2f, "fff" , "Fnc")
+BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc")
+BUILTIN(__builtin_abs , "ii" , "ncF")
+BUILTIN(__builtin_copysign, "ddd", "ncF")
+BUILTIN(__builtin_copysignf, "fff", "ncF")
+BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
+BUILTIN(__builtin_fabs , "dd" , "ncF")
+BUILTIN(__builtin_fabsf, "ff" , "ncF")
+BUILTIN(__builtin_fabsl, "LdLd", "ncF")
+BUILTIN(__builtin_fmod , "ddd" , "Fnc")
+BUILTIN(__builtin_fmodf, "fff" , "Fnc")
+BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_frexp , "ddi*" , "Fnc")
+BUILTIN(__builtin_frexpf, "ffi*" , "Fnc")
+BUILTIN(__builtin_frexpl, "LdLdi*", "Fnc")
+BUILTIN(__builtin_huge_val, "d", "nc")
+BUILTIN(__builtin_huge_valf, "f", "nc")
+BUILTIN(__builtin_huge_vall, "Ld", "nc")
+BUILTIN(__builtin_inf , "d" , "nc")
+BUILTIN(__builtin_inff , "f" , "nc")
+BUILTIN(__builtin_infl , "Ld" , "nc")
+BUILTIN(__builtin_ldexp , "ddi" , "Fnc")
+BUILTIN(__builtin_ldexpf, "ffi" , "Fnc")
+BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc")
+BUILTIN(__builtin_modf , "ddd*" , "Fnc")
+BUILTIN(__builtin_modff, "fff*" , "Fnc")
+BUILTIN(__builtin_modfl, "LdLdLd*", "Fnc")
+BUILTIN(__builtin_nan, "dcC*" , "ncF")
+BUILTIN(__builtin_nanf, "fcC*" , "ncF")
+BUILTIN(__builtin_nanl, "LdcC*", "ncF")
+BUILTIN(__builtin_nans, "dcC*" , "ncF")
+BUILTIN(__builtin_nansf, "fcC*" , "ncF")
+BUILTIN(__builtin_nansl, "LdcC*", "ncF")
+BUILTIN(__builtin_powi , "ddi" , "Fnc")
+BUILTIN(__builtin_powif, "ffi" , "Fnc")
+BUILTIN(__builtin_powil, "LdLdi", "Fnc")
+BUILTIN(__builtin_pow , "ddd" , "Fnc")
+BUILTIN(__builtin_powf, "fff" , "Fnc")
+BUILTIN(__builtin_powl, "LdLdLd", "Fnc")
+
+// Standard unary libc/libm functions with double/float/long double variants:
+BUILTIN(__builtin_acos , "dd" , "Fnc")
+BUILTIN(__builtin_acosf, "ff" , "Fnc")
+BUILTIN(__builtin_acosl, "LdLd", "Fnc")
+BUILTIN(__builtin_acosh , "dd" , "Fnc")
+BUILTIN(__builtin_acoshf, "ff" , "Fnc")
+BUILTIN(__builtin_acoshl, "LdLd", "Fnc")
+BUILTIN(__builtin_asin , "dd" , "Fnc")
+BUILTIN(__builtin_asinf, "ff" , "Fnc")
+BUILTIN(__builtin_asinl, "LdLd", "Fnc")
+BUILTIN(__builtin_asinh , "dd" , "Fnc")
+BUILTIN(__builtin_asinhf, "ff" , "Fnc")
+BUILTIN(__builtin_asinhl, "LdLd", "Fnc")
+BUILTIN(__builtin_atan , "dd" , "Fnc")
+BUILTIN(__builtin_atanf, "ff" , "Fnc")
+BUILTIN(__builtin_atanl, "LdLd", "Fnc")
+BUILTIN(__builtin_atanh , "dd", "Fnc")
+BUILTIN(__builtin_atanhf, "ff", "Fnc")
+BUILTIN(__builtin_atanhl, "LdLd", "Fnc")
+BUILTIN(__builtin_cbrt , "dd", "Fnc")
+BUILTIN(__builtin_cbrtf, "ff", "Fnc")
+BUILTIN(__builtin_cbrtl, "LdLd", "Fnc")
+BUILTIN(__builtin_ceil , "dd" , "Fnc")
+BUILTIN(__builtin_ceilf, "ff" , "Fnc")
+BUILTIN(__builtin_ceill, "LdLd", "Fnc")
+BUILTIN(__builtin_cos , "dd" , "Fnc")
+BUILTIN(__builtin_cosf, "ff" , "Fnc")
+BUILTIN(__builtin_cosh , "dd" , "Fnc")
+BUILTIN(__builtin_coshf, "ff" , "Fnc")
+BUILTIN(__builtin_coshl, "LdLd", "Fnc")
+BUILTIN(__builtin_cosl, "LdLd", "Fnc")
+BUILTIN(__builtin_erf , "dd", "Fnc")
+BUILTIN(__builtin_erff, "ff", "Fnc")
+BUILTIN(__builtin_erfl, "LdLd", "Fnc")
+BUILTIN(__builtin_erfc , "dd", "Fnc")
+BUILTIN(__builtin_erfcf, "ff", "Fnc")
+BUILTIN(__builtin_erfcl, "LdLd", "Fnc")
+BUILTIN(__builtin_exp , "dd" , "Fnc")
+BUILTIN(__builtin_expf, "ff" , "Fnc")
+BUILTIN(__builtin_expl, "LdLd", "Fnc")
+BUILTIN(__builtin_exp2 , "dd" , "Fnc")
+BUILTIN(__builtin_exp2f, "ff" , "Fnc")
+BUILTIN(__builtin_exp2l, "LdLd", "Fnc")
+BUILTIN(__builtin_expm1 , "dd", "Fnc")
+BUILTIN(__builtin_expm1f, "ff", "Fnc")
+BUILTIN(__builtin_expm1l, "LdLd", "Fnc")
+BUILTIN(__builtin_fdim, "ddd", "Fnc")
+BUILTIN(__builtin_fdimf, "fff", "Fnc")
+BUILTIN(__builtin_fdiml, "LdLdLd", "Fnc")
+BUILTIN(__builtin_floor , "dd" , "Fnc")
+BUILTIN(__builtin_floorf, "ff" , "Fnc")
+BUILTIN(__builtin_floorl, "LdLd", "Fnc")
+BUILTIN(__builtin_fma, "dddd", "Fnc")
+BUILTIN(__builtin_fmaf, "ffff", "Fnc")
+BUILTIN(__builtin_fmal, "LdLdLdLd", "Fnc")
+BUILTIN(__builtin_fmax, "ddd", "Fnc")
+BUILTIN(__builtin_fmaxf, "fff", "Fnc")
+BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_fmin, "ddd", "Fnc")
+BUILTIN(__builtin_fminf, "fff", "Fnc")
+BUILTIN(__builtin_fminl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_hypot , "ddd" , "Fnc")
+BUILTIN(__builtin_hypotf, "fff" , "Fnc")
+BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_ilogb , "id", "Fnc")
+BUILTIN(__builtin_ilogbf, "if", "Fnc")
+BUILTIN(__builtin_ilogbl, "iLd", "Fnc")
+BUILTIN(__builtin_lgamma , "dd", "Fnc")
+BUILTIN(__builtin_lgammaf, "ff", "Fnc")
+BUILTIN(__builtin_lgammal, "LdLd", "Fnc")
+BUILTIN(__builtin_llrint, "LLid", "Fnc")
+BUILTIN(__builtin_llrintf, "LLif", "Fnc")
+BUILTIN(__builtin_llrintl, "LLiLd", "Fnc")
+BUILTIN(__builtin_llround , "LLid", "Fnc")
+BUILTIN(__builtin_llroundf, "LLif", "Fnc")
+BUILTIN(__builtin_llroundl, "LLiLd", "Fnc")
+BUILTIN(__builtin_log , "dd" , "Fnc")
+BUILTIN(__builtin_log10 , "dd" , "Fnc")
+BUILTIN(__builtin_log10f, "ff" , "Fnc")
+BUILTIN(__builtin_log10l, "LdLd", "Fnc")
+BUILTIN(__builtin_log1p , "dd" , "Fnc")
+BUILTIN(__builtin_log1pf, "ff" , "Fnc")
+BUILTIN(__builtin_log1pl, "LdLd", "Fnc")
+BUILTIN(__builtin_log2, "dd" , "Fnc")
+BUILTIN(__builtin_log2f, "ff" , "Fnc")
+BUILTIN(__builtin_log2l, "LdLd" , "Fnc")
+BUILTIN(__builtin_logb , "dd", "Fnc")
+BUILTIN(__builtin_logbf, "ff", "Fnc")
+BUILTIN(__builtin_logbl, "LdLd", "Fnc")
+BUILTIN(__builtin_logf, "ff" , "Fnc")
+BUILTIN(__builtin_logl, "LdLd", "Fnc")
+BUILTIN(__builtin_lrint , "Lid", "Fnc")
+BUILTIN(__builtin_lrintf, "Lif", "Fnc")
+BUILTIN(__builtin_lrintl, "LiLd", "Fnc")
+BUILTIN(__builtin_lround , "Lid", "Fnc")
+BUILTIN(__builtin_lroundf, "Lif", "Fnc")
+BUILTIN(__builtin_lroundl, "LiLd", "Fnc")
+BUILTIN(__builtin_nearbyint , "dd", "Fnc")
+BUILTIN(__builtin_nearbyintf, "ff", "Fnc")
+BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc")
+BUILTIN(__builtin_nextafter , "ddd", "Fnc")
+BUILTIN(__builtin_nextafterf, "fff", "Fnc")
+BUILTIN(__builtin_nextafterl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_nexttoward , "ddd", "Fnc")
+BUILTIN(__builtin_nexttowardf, "fff", "Fnc")
+BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_remainder , "ddd", "Fnc")
+BUILTIN(__builtin_remainderf, "fff", "Fnc")
+BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc")
+BUILTIN(__builtin_remquo , "dddi*", "Fnc")
+BUILTIN(__builtin_remquof, "fffi*", "Fnc")
+BUILTIN(__builtin_remquol, "LdLdLdi*", "Fnc")
+BUILTIN(__builtin_rint , "dd", "Fnc")
+BUILTIN(__builtin_rintf, "ff", "Fnc")
+BUILTIN(__builtin_rintl, "LdLd", "Fnc")
+BUILTIN(__builtin_round, "dd" , "Fnc")
+BUILTIN(__builtin_roundf, "ff" , "Fnc")
+BUILTIN(__builtin_roundl, "LdLd" , "Fnc")
+BUILTIN(__builtin_scalbln , "ddLi", "Fnc")
+BUILTIN(__builtin_scalblnf, "ffLi", "Fnc")
+BUILTIN(__builtin_scalblnl, "LdLdLi", "Fnc")
+BUILTIN(__builtin_scalbn , "ddi", "Fnc")
+BUILTIN(__builtin_scalbnf, "ffi", "Fnc")
+BUILTIN(__builtin_scalbnl, "LdLdi", "Fnc")
+BUILTIN(__builtin_sin , "dd" , "Fnc")
+BUILTIN(__builtin_sinf, "ff" , "Fnc")
+BUILTIN(__builtin_sinh , "dd" , "Fnc")
+BUILTIN(__builtin_sinhf, "ff" , "Fnc")
+BUILTIN(__builtin_sinhl, "LdLd", "Fnc")
+BUILTIN(__builtin_sinl, "LdLd", "Fnc")
+BUILTIN(__builtin_sqrt , "dd" , "Fnc")
+BUILTIN(__builtin_sqrtf, "ff" , "Fnc")
+BUILTIN(__builtin_sqrtl, "LdLd", "Fnc")
+BUILTIN(__builtin_tan , "dd" , "Fnc")
+BUILTIN(__builtin_tanf, "ff" , "Fnc")
+BUILTIN(__builtin_tanh , "dd" , "Fnc")
+BUILTIN(__builtin_tanhf, "ff" , "Fnc")
+BUILTIN(__builtin_tanhl, "LdLd", "Fnc")
+BUILTIN(__builtin_tanl, "LdLd", "Fnc")
+BUILTIN(__builtin_tgamma , "dd", "Fnc")
+BUILTIN(__builtin_tgammaf, "ff", "Fnc")
+BUILTIN(__builtin_tgammal, "LdLd", "Fnc")
+BUILTIN(__builtin_trunc , "dd", "Fnc")
+BUILTIN(__builtin_truncf, "ff", "Fnc")
+BUILTIN(__builtin_truncl, "LdLd", "Fnc")
+
+// C99 complex builtins
+BUILTIN(__builtin_cabs, "dXd", "Fnc")
+BUILTIN(__builtin_cabsf, "fXf", "Fnc")
+BUILTIN(__builtin_cabsl, "LdXLd", "Fnc")
+BUILTIN(__builtin_cacos, "XdXd", "Fnc")
+BUILTIN(__builtin_cacosf, "XfXf", "Fnc")
+BUILTIN(__builtin_cacosh, "XdXd", "Fnc")
+BUILTIN(__builtin_cacoshf, "XfXf", "Fnc")
+BUILTIN(__builtin_cacoshl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cacosl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_carg, "dXd", "Fnc")
+BUILTIN(__builtin_cargf, "fXf", "Fnc")
+BUILTIN(__builtin_cargl, "LdXLd", "Fnc")
+BUILTIN(__builtin_casin, "XdXd", "Fnc")
+BUILTIN(__builtin_casinf, "XfXf", "Fnc")
+BUILTIN(__builtin_casinh, "XdXd", "Fnc")
+BUILTIN(__builtin_casinhf, "XfXf", "Fnc")
+BUILTIN(__builtin_casinhl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_casinl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_catan, "XdXd", "Fnc")
+BUILTIN(__builtin_catanf, "XfXf", "Fnc")
+BUILTIN(__builtin_catanh, "XdXd", "Fnc")
+BUILTIN(__builtin_catanhf, "XfXf", "Fnc")
+BUILTIN(__builtin_catanhl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_catanl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_ccos, "XdXd", "Fnc")
+BUILTIN(__builtin_ccosf, "XfXf", "Fnc")
+BUILTIN(__builtin_ccosl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_ccosh, "XdXd", "Fnc")
+BUILTIN(__builtin_ccoshf, "XfXf", "Fnc")
+BUILTIN(__builtin_ccoshl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cexp, "XdXd", "Fnc")
+BUILTIN(__builtin_cexpf, "XfXf", "Fnc")
+BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cimag, "dXd", "Fnc")
+BUILTIN(__builtin_cimagf, "fXf", "Fnc")
+BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
+BUILTIN(__builtin_conj, "XdXd", "Fnc")
+BUILTIN(__builtin_conjf, "XfXf", "Fnc")
+BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_clog, "XdXd", "Fnc")
+BUILTIN(__builtin_clogf, "XfXf", "Fnc")
+BUILTIN(__builtin_clogl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cproj, "XdXd", "Fnc")
+BUILTIN(__builtin_cprojf, "XfXf", "Fnc")
+BUILTIN(__builtin_cprojl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_cpow, "XdXdXd", "Fnc")
+BUILTIN(__builtin_cpowf, "XfXfXf", "Fnc")
+BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fnc")
+BUILTIN(__builtin_creal, "dXd", "Fnc")
+BUILTIN(__builtin_crealf, "fXf", "Fnc")
+BUILTIN(__builtin_creall, "LdXLd", "Fnc")
+BUILTIN(__builtin_csin, "XdXd", "Fnc")
+BUILTIN(__builtin_csinf, "XfXf", "Fnc")
+BUILTIN(__builtin_csinl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_csinh, "XdXd", "Fnc")
+BUILTIN(__builtin_csinhf, "XfXf", "Fnc")
+BUILTIN(__builtin_csinhl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_csqrt, "XdXd", "Fnc")
+BUILTIN(__builtin_csqrtf, "XfXf", "Fnc")
+BUILTIN(__builtin_csqrtl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_ctan, "XdXd", "Fnc")
+BUILTIN(__builtin_ctanf, "XfXf", "Fnc")
+BUILTIN(__builtin_ctanl, "XLdXLd", "Fnc")
+BUILTIN(__builtin_ctanh, "XdXd", "Fnc")
+BUILTIN(__builtin_ctanhf, "XfXf", "Fnc")
+BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc")
+
+// FP Comparisons.
+BUILTIN(__builtin_isgreater , "i.", "nc")
+BUILTIN(__builtin_isgreaterequal, "i.", "nc")
+BUILTIN(__builtin_isless , "i.", "nc")
+BUILTIN(__builtin_islessequal , "i.", "nc")
+BUILTIN(__builtin_islessgreater , "i.", "nc")
+BUILTIN(__builtin_isunordered , "i.", "nc")
+
+// Unary FP classification
+BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
+BUILTIN(__builtin_isfinite, "i.", "nc")
+BUILTIN(__builtin_isinf, "i.", "nc")
+BUILTIN(__builtin_isinf_sign, "i.", "nc")
+BUILTIN(__builtin_isnan, "i.", "nc")
+BUILTIN(__builtin_isnormal, "i.", "nc")
+
+// FP signbit builtins
+BUILTIN(__builtin_signbit, "id", "nc")
+BUILTIN(__builtin_signbitf, "if", "nc")
+BUILTIN(__builtin_signbitl, "iLd", "nc")
+
+// Builtins for arithmetic.
+BUILTIN(__builtin_clz , "iUi" , "nc")
+BUILTIN(__builtin_clzl , "iULi" , "nc")
+BUILTIN(__builtin_clzll, "iULLi", "nc")
+// TODO: int clzimax(uintmax_t)
+BUILTIN(__builtin_ctz , "iUi" , "nc")
+BUILTIN(__builtin_ctzl , "iULi" , "nc")
+BUILTIN(__builtin_ctzll, "iULLi", "nc")
+// TODO: int ctzimax(uintmax_t)
+BUILTIN(__builtin_ffs , "iUi" , "nc")
+BUILTIN(__builtin_ffsl , "iULi" , "nc")
+BUILTIN(__builtin_ffsll, "iULLi", "nc")
+BUILTIN(__builtin_parity , "iUi" , "nc")
+BUILTIN(__builtin_parityl , "iULi" , "nc")
+BUILTIN(__builtin_parityll, "iULLi", "nc")
+BUILTIN(__builtin_popcount , "iUi" , "nc")
+BUILTIN(__builtin_popcountl , "iULi" , "nc")
+BUILTIN(__builtin_popcountll, "iULLi", "nc")
+
+// FIXME: These type signatures are not correct for targets with int != 32-bits
+// or with ULL != 64-bits.
+BUILTIN(__builtin_bswap32, "UiUi", "nc")
+BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
+
+// Random GCC builtins
+BUILTIN(__builtin_constant_p, "i.", "nc")
+BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin_va_start, "vA.", "n")
+BUILTIN(__builtin_va_end, "vA", "n")
+BUILTIN(__builtin_va_copy, "vAA", "n")
+BUILTIN(__builtin_stdarg_start, "vA.", "n")
+BUILTIN(__builtin_bcmp, "iv*v*z", "n")
+BUILTIN(__builtin_bcopy, "vv*v*z", "n")
+BUILTIN(__builtin_bzero, "vv*z", "nF")
+BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
+BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
+BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
+BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
+BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
+BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
+BUILTIN(__builtin_memset, "v*v*iz", "nF")
+BUILTIN(__builtin_printf, "icC*.", "Fp:0:")
+BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
+BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF")
+BUILTIN(__builtin_strcat, "c*c*cC*", "nF")
+BUILTIN(__builtin_strchr, "c*cC*i", "nF")
+BUILTIN(__builtin_strcmp, "icC*cC*", "nF")
+BUILTIN(__builtin_strcpy, "c*c*cC*", "nF")
+BUILTIN(__builtin_strcspn, "zcC*cC*", "nF")
+BUILTIN(__builtin_strdup, "c*cC*", "nF")
+BUILTIN(__builtin_strlen, "zcC*", "nF")
+BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF")
+BUILTIN(__builtin_strncat, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strncmp, "icC*cC*z", "nF")
+BUILTIN(__builtin_strncpy, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strndup, "c*cC*z", "nF")
+BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF")
+BUILTIN(__builtin_strrchr, "c*cC*i", "nF")
+BUILTIN(__builtin_strspn, "zcC*cC*", "nF")
+BUILTIN(__builtin_strstr, "c*cC*cC*", "nF")
+BUILTIN(__builtin_return_address, "v*IUi", "n")
+BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
+BUILTIN(__builtin_frame_address, "v*IUi", "n")
+BUILTIN(__builtin_flt_rounds, "i", "nc")
+BUILTIN(__builtin_setjmp, "iv**", "")
+BUILTIN(__builtin_longjmp, "vv**i", "r")
+BUILTIN(__builtin_unwind_init, "v", "")
+BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc")
+BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:")
+BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
+BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
+
+// GCC exception builtins
+BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t!
+BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
+BUILTIN(__builtin_dwarf_cfa, "v*", "n")
+BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
+BUILTIN(__builtin_dwarf_sp_column, "Ui", "n")
+BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t
+
+// GCC Object size checking builtins
+BUILTIN(__builtin_object_size, "zv*i", "n")
+BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___memset_chk, "v*v*izz", "nF")
+BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF")
+BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF")
+BUILTIN(__builtin___stpncpy_chk, "c*c*cC*zz", "nF")
+BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:")
+BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:")
+BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:")
+BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "FP:3:")
+BUILTIN(__builtin___fprintf_chk, "iP*icC*.", "Fp:2:")
+BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
+BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
+BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
+
+BUILTIN(__builtin_expect, "LiLiLi" , "nc")
+BUILTIN(__builtin_prefetch, "vvC*.", "nc")
+BUILTIN(__builtin_trap, "v", "nr")
+BUILTIN(__builtin_unreachable, "v", "nr")
+BUILTIN(__builtin_shufflevector, "v." , "nc")
+BUILTIN(__builtin_alloca, "v*z" , "n")
+
+// "Overloaded" Atomic operator builtins. These are overloaded to support data
+// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
+// non-suffixed version of these (which has a bogus type) and transforms them to
+// the right overloaded version in Sema (plus casts).
+
+// FIXME: These assume that char -> i8, short -> i16, int -> i32,
+// long long -> i64.
+
+BUILTIN(__sync_fetch_and_add, "v.", "")
+BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_sub, "v.", "")
+BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_or, "v.", "")
+BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_and, "v.", "")
+BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_xor, "v.", "")
+BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n")
+
+
+BUILTIN(__sync_add_and_fetch, "v.", "")
+BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_sub_and_fetch, "v.", "")
+BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_or_and_fetch, "v.", "")
+BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_and_and_fetch, "v.", "")
+BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_xor_and_fetch, "v.", "")
+BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_bool_compare_and_swap, "v.", "")
+BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
+BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n")
+BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "n")
+BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "n")
+BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "n")
+
+BUILTIN(__sync_val_compare_and_swap, "v.", "")
+BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "n")
+BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "n")
+BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "n")
+BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n")
+BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n")
+
+BUILTIN(__sync_lock_test_and_set, "v.", "")
+BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n")
+BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n")
+BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n")
+BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n")
+
+BUILTIN(__sync_lock_release, "v.", "")
+BUILTIN(__sync_lock_release_1, "vcD*.", "n")
+BUILTIN(__sync_lock_release_2, "vsD*.", "n")
+BUILTIN(__sync_lock_release_4, "viD*.", "n")
+BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
+BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
+
+
+
+// Non-overloaded atomic builtins.
+BUILTIN(__sync_synchronize, "v.", "n")
+// LLVM instruction builtin [Clang extension].
+BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
+// GCC does not support these, they are a Clang extension.
+BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n")
+BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n")
+
+// Random libc builtins.
+BUILTIN(__builtin_abort, "v", "Fnr")
+BUILTIN(__builtin_index, "c*cC*i", "Fn")
+BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
+
+// Microsoft builtins.
+BUILTIN(__assume, "vb", "n")
+BUILTIN(__noop, "v.", "n")
+
+// C99 library functions
+// C99 stdlib.h
+LIBBUILTIN(abort, "v", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES)
+// C99 string.h
+LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strxfrm, "zc*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memchr, "v*vC*iz", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strtok, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES)
+// C99 stdio.h
+LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h", ALL_LANGUAGES)
+// C99
+LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
+
+// Non-C library functions
+// FIXME: Non-C-standard stuff shouldn't be builtins in non-GNU mode!
+LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_LANGUAGES)
+// POSIX string.h
+LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES)
+// POSIX strings.h
+LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES)
+// POSIX unistd.h
+LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_LANGUAGES)
+// POSIX setjmp.h
+LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_LANGUAGES)
+// id objc_msgSend(id, SEL, ...)
+LIBBUILTIN(objc_msgSend, "GGH.", "f", "objc/message.h", OBJC_LANG)
+
+// long double objc_msgSend_fpret(id self, SEL op, ...)
+LIBBUILTIN(objc_msgSend_fpret, "LdGH.", "f", "objc/message.h", OBJC_LANG)
+// id objc_msgSend_stret (id, SEL, ...)
+LIBBUILTIN(objc_msgSend_stret, "GGH.", "f", "objc/message.h", OBJC_LANG)
+// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper, "Gv*H.", "f", "objc/message.h", OBJC_LANG)
+// void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper_stret, "vv*H.", "f", "objc/message.h", OBJC_LANG)
+// id objc_getClass(const char *name)
+LIBBUILTIN(objc_getClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG)
+// id objc_getMetaClass(const char *name)
+LIBBUILTIN(objc_getMetaClass, "GcC*", "f", "objc/runtime.h", OBJC_LANG)
+// void objc_enumerationMutation(id)
+LIBBUILTIN(objc_enumerationMutation, "vG", "f", "objc/runtime.h", OBJC_LANG)
+
+// id objc_read_weak(id *location)
+LIBBUILTIN(objc_read_weak, "GG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_weak(id value, id *location)
+LIBBUILTIN(objc_assign_weak, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_ivar(id value, id dest, ptrdiff_t offset)
+// FIXME. Darwin has ptrdiff_t typedef'ed to int.
+LIBBUILTIN(objc_assign_ivar, "GGGi", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_global(id val, id *dest)
+LIBBUILTIN(objc_assign_global, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+// id objc_assign_strongCast(id val, id *dest
+LIBBUILTIN(objc_assign_strongCast, "GGG*", "f", "/objc/objc-auto.h", OBJC_LANG)
+
+// id objc_exception_extract(void *localExceptionData)
+LIBBUILTIN(objc_exception_extract, "Gv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_try_enter(void *localExceptionData)
+LIBBUILTIN(objc_exception_try_enter, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_try_exit(void *localExceptionData)
+LIBBUILTIN(objc_exception_try_exit, "vv*", "f", "/objc/objc-exception.h", OBJC_LANG)
+// int objc_exception_match(Class exceptionClass, id exception)
+LIBBUILTIN(objc_exception_match, "iGG", "f", "/objc/objc-exception.h", OBJC_LANG)
+// void objc_exception_throw(id exception)
+LIBBUILTIN(objc_exception_throw, "vG", "f", "/objc/objc-exception.h", OBJC_LANG)
+
+// int objc_sync_enter(id obj)
+LIBBUILTIN(objc_sync_enter, "iG", "f", "/objc/objc-sync.h", OBJC_LANG)
+// int objc_sync_exit(id obj)
+LIBBUILTIN(objc_sync_exit, "iG", "f", "/objc/objc-sync.h", OBJC_LANG)
+
+BUILTIN(__builtin_objc_memmove_collectable, "v*v*vC*z", "nF")
+
+// Builtin math library functions
+LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES)
+
+// Blocks runtime Builtin math library functions
+LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
+LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
+// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
+
+#undef BUILTIN
+#undef LIBBUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
new file mode 100644
index 0000000..4df4c8f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -0,0 +1,154 @@
+//===--- Builtins.h - Builtin function header -------------------*- 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 enum values for all the target-independent builtin
+// functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_BUILTINS_H
+#define LLVM_CLANG_BASIC_BUILTINS_H
+
+#include <cstring>
+
+// VC++ defines 'alloca' as an object-like macro, which interferes with our
+// builtins.
+#undef alloca
+
+namespace llvm {
+ template <typename T> class SmallVectorImpl;
+}
+
+namespace clang {
+ class TargetInfo;
+ class IdentifierTable;
+ class ASTContext;
+ class QualType;
+ class LangOptions;
+
+ enum LanguageID {
+ C_LANG = 0x1, // builtin for c only.
+ CXX_LANG = 0x2, // builtin for cplusplus only.
+ OBJC_LANG = 0x4, // builtin for objective-c and objective-c++
+ ALL_LANGUAGES = (C_LANG|CXX_LANG|OBJC_LANG) //builtin is for all languages.
+ };
+
+namespace Builtin {
+enum ID {
+ NotBuiltin = 0, // This is not a builtin function.
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/Builtins.def"
+ FirstTSBuiltin
+};
+
+struct Info {
+ const char *Name, *Type, *Attributes, *HeaderName;
+ LanguageID builtin_lang;
+ bool Suppressed;
+
+ bool operator==(const Info &RHS) const {
+ return !strcmp(Name, RHS.Name) &&
+ !strcmp(Type, RHS.Type) &&
+ !strcmp(Attributes, RHS.Attributes);
+ }
+ bool operator!=(const Info &RHS) const { return !(*this == RHS); }
+};
+
+/// Builtin::Context - This holds information about target-independent and
+/// target-specific builtins, allowing easy queries by clients.
+class Context {
+ const Info *TSRecords;
+ unsigned NumTSRecords;
+public:
+ Context(const TargetInfo &Target);
+
+ /// InitializeBuiltins - Mark the identifiers for all the builtins with their
+ /// appropriate builtin ID # and mark any non-portable builtin identifiers as
+ /// such.
+ void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
+
+ /// \brief Popular the vector with the names of all of the builtins.
+ void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
+ bool NoBuiltins);
+
+ /// Builtin::GetName - Return the identifier name for the specified builtin,
+ /// e.g. "__builtin_abs".
+ const char *GetName(unsigned ID) const {
+ return GetRecord(ID).Name;
+ }
+
+ /// GetTypeString - Get the type descriptor string for the specified builtin.
+ const char *GetTypeString(unsigned ID) const {
+ return GetRecord(ID).Type;
+ }
+
+ /// isConst - Return true if this function has no side effects and doesn't
+ /// read memory.
+ bool isConst(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'c') != 0;
+ }
+
+ /// isNoThrow - Return true if we know this builtin never throws an exception.
+ bool isNoThrow(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'n') != 0;
+ }
+
+ /// isNoReturn - Return true if we know this builtin never returns.
+ bool isNoReturn(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'r') != 0;
+ }
+
+ /// isLibFunction - Return true if this is a builtin for a libc/libm function,
+ /// with a "__builtin_" prefix (e.g. __builtin_abs).
+ bool isLibFunction(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'F') != 0;
+ }
+
+ /// \brief Determines whether this builtin is a predefined libc/libm
+ /// function, such as "malloc", where we know the signature a
+ /// priori.
+ bool isPredefinedLibFunction(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'f') != 0;
+ }
+
+ /// \brief Completely forget that the given ID was ever considered a builtin,
+ /// e.g., because the user provided a conflicting signature.
+ void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
+
+ /// \brief If this is a library function that comes from a specific
+ /// header, retrieve that header name.
+ const char *getHeaderName(unsigned ID) const {
+ return GetRecord(ID).HeaderName;
+ }
+
+ /// \brief Determine whether this builtin is like printf in its
+ /// formatting rules and, if so, set the index to the format string
+ /// argument and whether this function as a va_list argument.
+ bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+
+ /// \brief Determine whether this builtin is like scanf in its
+ /// formatting rules and, if so, set the index to the format string
+ /// argument and whether this function as a va_list argument.
+ bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+
+ /// isConstWithoutErrno - Return true if this function has no side
+ /// effects and doesn't read memory, except for possibly errno. Such
+ /// functions can be const when the MathErrno lang option is
+ /// disabled.
+ bool isConstWithoutErrno(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'e') != 0;
+ }
+
+private:
+ const Info &GetRecord(unsigned ID) const;
+};
+
+}
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
new file mode 100644
index 0000000..080d17f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
@@ -0,0 +1,38 @@
+//===--- BuiltinsARM.def - ARM Builtin function database ----*- 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 ARM-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// In libgcc
+BUILTIN(__clear_cache, "v.", "")
+BUILTIN(__builtin_thread_pointer, "v*", "")
+
+// Saturating arithmetic
+BUILTIN(__builtin_arm_qadd, "iii", "nc")
+BUILTIN(__builtin_arm_qsub, "iii", "nc")
+BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
+BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
+
+// VFP
+BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc")
+BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc")
+BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
+BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
+
+// NEON
+#define GET_NEON_BUILTINS
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_BUILTINS
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
new file mode 100644
index 0000000..8a751e4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
@@ -0,0 +1,209 @@
+//===--- BuiltinsPPC.def - PowerPC Builtin function database ----*- 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 PowerPC-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
+// adding stuff on demand.
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// This is just a placeholder, the types and attributes are wrong.
+BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vaddubs, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vavgsh, "V8SsV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcfsx, "V4fV4ii", "")
+BUILTIN(__builtin_altivec_vcfux, "V4fV4ii", "")
+BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fi", "")
+BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fi", "")
+
+BUILTIN(__builtin_altivec_dss, "vUi", "")
+BUILTIN(__builtin_altivec_dssall, "v", "")
+BUILTIN(__builtin_altivec_dst, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dstt, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dstst, "vvC*iUi", "")
+BUILTIN(__builtin_altivec_dststt, "vvC*iUi", "")
+
+BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vrfim, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_lvx, "V4iivC*", "")
+BUILTIN(__builtin_altivec_lvxl, "V4iivC*", "")
+BUILTIN(__builtin_altivec_lvebx, "V16civC*", "")
+BUILTIN(__builtin_altivec_lvehx, "V8sivC*", "")
+BUILTIN(__builtin_altivec_lvewx, "V4iivC*", "")
+
+BUILTIN(__builtin_altivec_vlogefp, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_lvsl, "V16cUcvC*", "")
+BUILTIN(__builtin_altivec_lvsr, "V16cUcvC*", "")
+
+BUILTIN(__builtin_altivec_vmaddfp, "V4fV4fV4fV4f", "")
+BUILTIN(__builtin_altivec_vmhaddshs, "V8sV8sV8sV8s", "")
+BUILTIN(__builtin_altivec_vmhraddshs, "V8sV8sV8sV8s", "")
+
+BUILTIN(__builtin_altivec_vmsumubm, "V4UiV16UcV16UcV4Ui", "")
+BUILTIN(__builtin_altivec_vmsummbm, "V4SiV16ScV16UcV4Si", "")
+BUILTIN(__builtin_altivec_vmsumuhm, "V4UiV8UsV8UsV4Ui", "")
+BUILTIN(__builtin_altivec_vmsumshm, "V4SiV8SsV8SsV4Si", "")
+BUILTIN(__builtin_altivec_vmsumuhs, "V4UiV8UsV8UsV4Ui", "")
+BUILTIN(__builtin_altivec_vmsumshs, "V4SiV8SsV8SsV4Si", "")
+
+BUILTIN(__builtin_altivec_vmuleub, "V8UsV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vmulesb, "V8SsV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vmuleuh, "V4UiV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vmulesh, "V4SiV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "")
+
+BUILTIN(__builtin_altivec_vnmsubfp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vpkpx, "V8sV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vpkuhus, "V16UcV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vpkshss, "V16ScV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vpkuwus, "V8UsV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vpkswss, "V8SsV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vpkshus, "V16UcV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vpkswus, "V8UsV4SiV4Si", "")
+
+BUILTIN(__builtin_altivec_vperm_4si, "V4iV4iV4iV16Uc", "")
+
+BUILTIN(__builtin_altivec_stvx, "vV4iiv*", "")
+BUILTIN(__builtin_altivec_stvxl, "vV4iiv*", "")
+BUILTIN(__builtin_altivec_stvebx, "vV16civ*", "")
+BUILTIN(__builtin_altivec_stvehx, "vV8siv*", "")
+BUILTIN(__builtin_altivec_stvewx, "vV4iiv*", "")
+
+BUILTIN(__builtin_altivec_vcmpbfp, "V4iV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "")
+BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "")
+BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "")
+BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vmaxub, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "")
+
+BUILTIN(__builtin_altivec_mfvscr, "V8Us", "")
+
+BUILTIN(__builtin_altivec_vminsb, "V16ScV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vminub, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "")
+
+BUILTIN(__builtin_altivec_mtvscr, "vV4i", "")
+
+BUILTIN(__builtin_altivec_vrefp, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vrlb, "V16cV16cV16Uc", "")
+BUILTIN(__builtin_altivec_vrlh, "V8sV8sV8Us", "")
+BUILTIN(__builtin_altivec_vrlw, "V4iV4iV4Ui", "")
+
+BUILTIN(__builtin_altivec_vsel_4si, "V4iV4iV4iV4Ui", "")
+
+BUILTIN(__builtin_altivec_vsl, "V4iV4iV4i", "")
+BUILTIN(__builtin_altivec_vslo, "V4iV4iV4i", "")
+
+BUILTIN(__builtin_altivec_vsrab, "V16cV16cV16Uc", "")
+BUILTIN(__builtin_altivec_vsrah, "V8sV8sV8Us", "")
+BUILTIN(__builtin_altivec_vsraw, "V4iV4iV4Ui", "")
+
+BUILTIN(__builtin_altivec_vsr, "V4iV4iV4i", "")
+BUILTIN(__builtin_altivec_vsro, "V4iV4iV4i", "")
+
+BUILTIN(__builtin_altivec_vrfin, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vrsqrtefp, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vsubcuw, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_altivec_vsum4sbs, "V4SiV16ScV4Si", "")
+BUILTIN(__builtin_altivec_vsum4ubs, "V4UiV16UcV4Ui", "")
+BUILTIN(__builtin_altivec_vsum4shs, "V4SiV8SsV4Si", "")
+
+BUILTIN(__builtin_altivec_vsum2sws, "V4SiV4SiV4Si", "")
+
+BUILTIN(__builtin_altivec_vsumsws, "V4SiV4SiV4Si", "")
+
+BUILTIN(__builtin_altivec_vrfiz, "V4fV4f", "")
+
+BUILTIN(__builtin_altivec_vupkhsb, "V8sV16c", "")
+BUILTIN(__builtin_altivec_vupkhpx, "V4UiV8s", "")
+BUILTIN(__builtin_altivec_vupkhsh, "V4iV8s", "")
+
+BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "")
+BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "")
+BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "")
+
+BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "")
+BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "")
+BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "")
+BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "")
+
+// FIXME: Obviously incomplete.
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
new file mode 100644
index 0000000..da106da
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
@@ -0,0 +1,450 @@
+//===--- BuiltinsX86.def - X86 Builtin function database --------*- 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 X86-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// FIXME: In GCC, these builtins are defined depending on whether support for
+// MMX/SSE/etc is turned on. We should do this too.
+
+// FIXME: Ideally we would be able to pull this information from what
+// LLVM already knows about X86 builtins. We need to match the LLVM
+// definition anyway, since code generation will lower to the
+// intrinsic if one exists.
+
+// FIXME: Are these nothrow/const?
+
+// MMX
+//
+// FIXME: All MMX instructions will be generated via builtins. Any MMX vector
+// types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be
+// expanded by the back-end.
+BUILTIN(__builtin_ia32_emms, "v", "")
+BUILTIN(__builtin_ia32_femms, "v", "")
+BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
+BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
+BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
+BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
+BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "")
+BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
+BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
+BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
+BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "")
+BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
+BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
+BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
+BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
+
+// SSE intrinsics.
+BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comile, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comige, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fc", "")
+BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fc", "")
+BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
+BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
+BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpeqb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pcmpeqw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpeqd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pcmpgtb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pcmpgtw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpgtd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_packsswb128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_packssdw128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_packuswb128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "")
+BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "")
+BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
+BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
+BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
+BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
+BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
+BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
+BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
+BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
+BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
+BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
+BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
+BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
+BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
+BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
+BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
+BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
+BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
+BUILTIN(__builtin_ia32_sfence, "v", "")
+BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "")
+BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "")
+BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
+BUILTIN(__builtin_ia32_movmskpd, "iV2d", "")
+BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "")
+BUILTIN(__builtin_ia32_movnti, "vi*i", "")
+BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "")
+BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "")
+BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "")
+BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "")
+BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "")
+BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "")
+BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "")
+BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "")
+BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "")
+BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "")
+BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "")
+BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "")
+BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "")
+BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "")
+BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "")
+BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "")
+BUILTIN(__builtin_ia32_clflush, "vvC*", "")
+BUILTIN(__builtin_ia32_lfence, "v", "")
+BUILTIN(__builtin_ia32_mfence, "v", "")
+BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
+BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
+BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
+BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLiIi", "")
+BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLiIi", "")
+BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
+BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
+BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
+BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") // FIXME: Correct type?
+BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
+
+BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
+
+BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8si", "")
+BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "")
+BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "")
+BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "")
+BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "")
+BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "")
+BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "")
+BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "")
+BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "")
+BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
+BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "")
+BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_pcmpeqq, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16ci", "")
+
+// SSE 4.2
+BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cc", "")
+BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cc", "")
+BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16cic", "")
+BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16cic","")
+
+BUILTIN(__builtin_ia32_pcmpistria128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpistric128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpistrio128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpistris128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpistriz128, "iV16ciV16cic","")
+
+BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16cic","")
+BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16cic","")
+
+BUILTIN(__builtin_ia32_pcmpgtq, "V2LLiV2LLiV2LLi", "")
+
+BUILTIN(__builtin_ia32_crc32qi, "iic", "")
+BUILTIN(__builtin_ia32_crc32hi, "iis", "")
+BUILTIN(__builtin_ia32_crc32si, "iii", "")
+BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "")
+
+// AES
+BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "")
+
+// AVX
+BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
+BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
+BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "")
+BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
+BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
+BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "")
+BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "")
+BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
+BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
+BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
+BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
+BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "")
+BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "")
+BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "")
+BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "")
+BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "")
+BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "")
+BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
+BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "")
+BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "")
+BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
+BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
+BUILTIN(__builtin_ia32_vzeroall, "v", "")
+BUILTIN(__builtin_ia32_vzeroupper, "v", "")
+BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
+BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "")
+BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "")
+BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "")
+BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "")
+BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "")
+BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "")
+BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "")
+BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "")
+BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
+BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h
new file mode 100644
index 0000000..4da2ad75
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ConvertUTF.h
@@ -0,0 +1,159 @@
+/*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *==------------------------------------------------------------------------==*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum {
+ strictConversion = 0,
+ lenientConversion
+} ConversionFlags;
+
+/* This is for C++ and does no harm in C */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+#ifdef CLANG_NEEDS_THESE_ONE_DAY
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF8toUTF32 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+#endif
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
new file mode 100644
index 0000000..2ec7427
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
@@ -0,0 +1,73 @@
+class AttrSubject;
+
+class Decl<bit abstract = 0> : AttrSubject {
+ bit Abstract = abstract;
+}
+
+class DDecl<Decl base, bit abstract = 0> : Decl<abstract> {
+ Decl Base = base;
+}
+
+class DeclContext { }
+
+def TranslationUnit : Decl, DeclContext;
+def Named : Decl<1>;
+ def Namespace : DDecl<Named>, DeclContext;
+ def UsingDirective : DDecl<Named>;
+ def NamespaceAlias : DDecl<Named>;
+ def Label : DDecl<Named>;
+ def Type : DDecl<Named, 1>;
+ def Typedef : DDecl<Type>;
+ def UnresolvedUsingTypename : DDecl<Type>;
+ def Tag : DDecl<Type, 1>, DeclContext;
+ def Enum : DDecl<Tag>;
+ def Record : DDecl<Tag>;
+ def CXXRecord : DDecl<Record>;
+ def ClassTemplateSpecialization : DDecl<CXXRecord>;
+ def ClassTemplatePartialSpecialization
+ : DDecl<ClassTemplateSpecialization>;
+ def TemplateTypeParm : DDecl<Type>;
+ def Value : DDecl<Named, 1>;
+ def EnumConstant : DDecl<Value>;
+ def UnresolvedUsingValue : DDecl<Value>;
+ def IndirectField : DDecl<Value>;
+ def Declarator : DDecl<Value, 1>;
+ def Function : DDecl<Declarator>, DeclContext;
+ def CXXMethod : DDecl<Function>;
+ def CXXConstructor : DDecl<CXXMethod>;
+ def CXXDestructor : DDecl<CXXMethod>;
+ def CXXConversion : DDecl<CXXMethod>;
+ def Field : DDecl<Declarator>;
+ def ObjCIvar : DDecl<Field>;
+ def ObjCAtDefsField : DDecl<Field>;
+ def Var : DDecl<Declarator>;
+ def ImplicitParam : DDecl<Var>;
+ def ParmVar : DDecl<Var>;
+ def NonTypeTemplateParm : DDecl<Declarator>;
+ def Template : DDecl<Named, 1>;
+ def RedeclarableTemplate : DDecl<Template, 1>;
+ def FunctionTemplate : DDecl<RedeclarableTemplate>;
+ def ClassTemplate : DDecl<RedeclarableTemplate>;
+ def TemplateTemplateParm : DDecl<Template>;
+ def Using : DDecl<Named>;
+ def UsingShadow : DDecl<Named>;
+ def ObjCMethod : DDecl<Named>, DeclContext;
+ def ObjCContainer : DDecl<Named, 1>, DeclContext;
+ def ObjCCategory : DDecl<ObjCContainer>;
+ def ObjCProtocol : DDecl<ObjCContainer>;
+ def ObjCInterface : DDecl<ObjCContainer>;
+ def ObjCImpl : DDecl<ObjCContainer, 1>;
+ def ObjCCategoryImpl : DDecl<ObjCImpl>;
+ def ObjCImplementation : DDecl<ObjCImpl>;
+ def ObjCProperty : DDecl<Named>;
+ def ObjCCompatibleAlias : DDecl<Named>;
+def LinkageSpec : Decl, DeclContext;
+def ObjCPropertyImpl : Decl;
+def ObjCForwardProtocol : Decl;
+def ObjCClass : Decl;
+def FileScopeAsm : Decl;
+def AccessSpec : Decl;
+def Friend : Decl;
+def FriendTemplate : Decl;
+def StaticAssert : Decl;
+def Block : Decl, DeclContext;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
new file mode 100644
index 0000000..19e7c91
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -0,0 +1,1031 @@
+//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- 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 Diagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTIC_H
+#define LLVM_CLANG_DIAGNOSTIC_H
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/type_traits.h"
+
+#include <vector>
+#include <list>
+
+namespace clang {
+ class DiagnosticClient;
+ class DiagnosticBuilder;
+ class IdentifierInfo;
+ class DeclContext;
+ class LangOptions;
+ class Preprocessor;
+ class DiagnosticErrorTrap;
+
+/// \brief Annotates a diagnostic with some code that should be
+/// inserted, removed, or replaced to fix the problem.
+///
+/// This kind of hint should be used when we are certain that the
+/// introduction, removal, or modification of a particular (small!)
+/// amount of code will correct a compilation error. The compiler
+/// should also provide full recovery from such errors, such that
+/// suppressing the diagnostic output can still result in successful
+/// compilation.
+class FixItHint {
+public:
+ /// \brief Code that should be replaced to correct the error. Empty for an
+ /// insertion hint.
+ CharSourceRange RemoveRange;
+
+ /// \brief The actual code to insert at the insertion location, as a
+ /// string.
+ std::string CodeToInsert;
+
+ /// \brief Empty code modification hint, indicating that no code
+ /// modification is known.
+ FixItHint() : RemoveRange() { }
+
+ bool isNull() const {
+ return !RemoveRange.isValid();
+ }
+
+ /// \brief Create a code modification hint that inserts the given
+ /// code string at a specific location.
+ static FixItHint CreateInsertion(SourceLocation InsertionLoc,
+ llvm::StringRef Code) {
+ FixItHint Hint;
+ Hint.RemoveRange =
+ CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
+ Hint.CodeToInsert = Code;
+ return Hint;
+ }
+
+ /// \brief Create a code modification hint that removes the given
+ /// source range.
+ static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
+ FixItHint Hint;
+ Hint.RemoveRange = RemoveRange;
+ return Hint;
+ }
+ static FixItHint CreateRemoval(SourceRange RemoveRange) {
+ return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
+ }
+
+ /// \brief Create a code modification hint that replaces the given
+ /// source range with the given code string.
+ static FixItHint CreateReplacement(CharSourceRange RemoveRange,
+ llvm::StringRef Code) {
+ FixItHint Hint;
+ Hint.RemoveRange = RemoveRange;
+ Hint.CodeToInsert = Code;
+ return Hint;
+ }
+
+ static FixItHint CreateReplacement(SourceRange RemoveRange,
+ llvm::StringRef Code) {
+ return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
+ }
+};
+
+/// Diagnostic - This concrete class is used by the front-end to report
+/// problems and issues. It massages the diagnostics (e.g. handling things like
+/// "report warnings as errors" and passes them off to the DiagnosticClient for
+/// reporting to the user. Diagnostic is tied to one translation unit and
+/// one SourceManager.
+class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
+public:
+ /// Level - The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored = DiagnosticIDs::Ignored,
+ Note = DiagnosticIDs::Note,
+ Warning = DiagnosticIDs::Warning,
+ Error = DiagnosticIDs::Error,
+ Fatal = DiagnosticIDs::Fatal
+ };
+
+ /// ExtensionHandling - How do we handle otherwise-unmapped extension? This
+ /// is controlled by -pedantic and -pedantic-errors.
+ enum ExtensionHandling {
+ Ext_Ignore, Ext_Warn, Ext_Error
+ };
+
+ enum ArgumentKind {
+ ak_std_string, // std::string
+ ak_c_string, // const char *
+ ak_sint, // int
+ ak_uint, // unsigned
+ ak_identifierinfo, // IdentifierInfo
+ ak_qualtype, // QualType
+ ak_declarationname, // DeclarationName
+ ak_nameddecl, // NamedDecl *
+ ak_nestednamespec, // NestedNameSpecifier *
+ ak_declcontext // DeclContext *
+ };
+
+ /// Specifies which overload candidates to display when overload resolution
+ /// fails.
+ enum OverloadsShown {
+ Ovl_All, ///< Show all overloads.
+ Ovl_Best ///< Show just the "best" overload candidates.
+ };
+
+ /// ArgumentValue - This typedef represents on argument value, which is a
+ /// union discriminated by ArgumentKind, with a value.
+ typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
+
+private:
+ unsigned char AllExtensionsSilenced; // Used by __extension__
+ bool IgnoreAllWarnings; // Ignore all warnings: -w
+ bool WarningsAsErrors; // Treat warnings like errors:
+ bool ErrorsAsFatal; // Treat errors like fatal errors.
+ bool SuppressSystemWarnings; // Suppress warnings in system headers.
+ bool SuppressAllDiagnostics; // Suppress all diagnostics.
+ OverloadsShown ShowOverloads; // Which overload candidates to show.
+ unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit.
+ unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
+ // 0 -> no limit.
+ ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
+ DiagnosticClient *Client;
+ bool OwnsDiagClient;
+ SourceManager *SourceMgr;
+
+ /// \brief Mapping information for diagnostics. Mapping info is
+ /// packed into four bits per diagnostic. The low three bits are the mapping
+ /// (an instance of diag::Mapping), or zero if unset. The high bit is set
+ /// when the mapping was established as a user mapping. If the high bit is
+ /// clear, then the low bits are set to the default value, and should be
+ /// mapped with -pedantic, -Werror, etc.
+ ///
+ /// A new DiagState is created and kept around when diagnostic pragmas modify
+ /// the state so that we know what is the diagnostic state at any given
+ /// source location.
+ class DiagState {
+ llvm::DenseMap<unsigned, unsigned> DiagMap;
+
+ public:
+ typedef llvm::DenseMap<unsigned, unsigned>::const_iterator iterator;
+
+ void setMapping(diag::kind Diag, unsigned Map) { DiagMap[Diag] = Map; }
+
+ diag::Mapping getMapping(diag::kind Diag) const {
+ iterator I = DiagMap.find(Diag);
+ if (I != DiagMap.end())
+ return (diag::Mapping)I->second;
+ return diag::Mapping();
+ }
+
+ iterator begin() const { return DiagMap.begin(); }
+ iterator end() const { return DiagMap.end(); }
+ };
+
+ /// \brief Keeps and automatically disposes all DiagStates that we create.
+ std::list<DiagState> DiagStates;
+
+ /// \brief Represents a point in source where the diagnostic state was
+ /// modified because of a pragma. 'Loc' can be null if the point represents
+ /// the diagnostic state modifications done through the command-line.
+ struct DiagStatePoint {
+ DiagState *State;
+ FullSourceLoc Loc;
+ DiagStatePoint(DiagState *State, FullSourceLoc Loc)
+ : State(State), Loc(Loc) { }
+
+ bool operator<(const DiagStatePoint &RHS) const {
+ // If Loc is invalid it means it came from <command-line>, in which case
+ // we regard it as coming before any valid source location.
+ if (RHS.Loc.isInvalid())
+ return false;
+ if (Loc.isInvalid())
+ return true;
+ return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
+ }
+ };
+
+ /// \brief A vector of all DiagStatePoints representing changes in diagnostic
+ /// state due to diagnostic pragmas. The vector is always sorted according to
+ /// the SourceLocation of the DiagStatePoint.
+ typedef std::vector<DiagStatePoint> DiagStatePointsTy;
+ mutable DiagStatePointsTy DiagStatePoints;
+
+ /// \brief Keeps the DiagState that was active during each diagnostic 'push'
+ /// so we can get back at it when we 'pop'.
+ std::vector<DiagState *> DiagStateOnPushStack;
+
+ DiagState *GetCurDiagState() const {
+ assert(!DiagStatePoints.empty());
+ return DiagStatePoints.back().State;
+ }
+
+ void PushDiagStatePoint(DiagState *State, SourceLocation L) {
+ FullSourceLoc Loc(L, *SourceMgr);
+ // Make sure that DiagStatePoints is always sorted according to Loc.
+ assert((Loc.isValid() || DiagStatePoints.empty()) &&
+ "Adding invalid loc point after another point");
+ assert((Loc.isInvalid() || DiagStatePoints.empty() ||
+ DiagStatePoints.back().Loc.isInvalid() ||
+ DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
+ "Previous point loc comes after or is the same as new one");
+ DiagStatePoints.push_back(DiagStatePoint(State,
+ FullSourceLoc(Loc, *SourceMgr)));
+ }
+
+ /// \brief Finds the DiagStatePoint that contains the diagnostic state of
+ /// the given source location.
+ DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
+
+ /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
+ /// fatal error is emitted, and is sticky.
+ bool ErrorOccurred;
+ bool FatalErrorOccurred;
+
+ /// LastDiagLevel - This is the level of the last diagnostic emitted. This is
+ /// used to emit continuation diagnostics with the same level as the
+ /// diagnostic that they follow.
+ DiagnosticIDs::Level LastDiagLevel;
+
+ unsigned NumWarnings; // Number of warnings reported
+ unsigned NumErrors; // Number of errors reported
+ unsigned NumErrorsSuppressed; // Number of errors suppressed
+
+ /// ArgToStringFn - A function pointer that converts an opaque diagnostic
+ /// argument to a strings. This takes the modifiers and argument that was
+ /// present in the diagnostic.
+ ///
+ /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
+ /// arguments formatted for this diagnostic. Implementations of this function
+ /// can use this information to avoid redundancy across arguments.
+ ///
+ /// This is a hack to avoid a layering violation between libbasic and libsema.
+ typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
+ const char *Modifier, unsigned ModifierLen,
+ const char *Argument, unsigned ArgumentLen,
+ const ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie);
+ void *ArgToStringCookie;
+ ArgToStringFnTy ArgToStringFn;
+
+ /// \brief ID of the "delayed" diagnostic, which is a (typically
+ /// fatal) diagnostic that had to be delayed because it was found
+ /// while emitting another diagnostic.
+ unsigned DelayedDiagID;
+
+ /// \brief First string argument for the delayed diagnostic.
+ std::string DelayedDiagArg1;
+
+ /// \brief Second string argument for the delayed diagnostic.
+ std::string DelayedDiagArg2;
+
+public:
+ explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
+ DiagnosticClient *client = 0,
+ bool ShouldOwnClient = true);
+ ~Diagnostic();
+
+ const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
+ return Diags;
+ }
+
+ DiagnosticClient *getClient() { return Client; }
+ const DiagnosticClient *getClient() const { return Client; }
+
+ /// \brief Return the current diagnostic client along with ownership of that
+ /// client.
+ DiagnosticClient *takeClient() {
+ OwnsDiagClient = false;
+ return Client;
+ }
+
+ bool hasSourceManager() const { return SourceMgr != 0; }
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "SourceManager not set!");
+ return *SourceMgr;
+ }
+ void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic characterization methods, used by a client to customize how
+ // diagnostics are emitted.
+ //
+
+ /// pushMappings - Copies the current DiagMappings and pushes the new copy
+ /// onto the top of the stack.
+ void pushMappings(SourceLocation Loc);
+
+ /// popMappings - Pops the current DiagMappings off the top of the stack
+ /// causing the new top of the stack to be the active mappings. Returns
+ /// true if the pop happens, false if there is only one DiagMapping on the
+ /// stack.
+ bool popMappings(SourceLocation Loc);
+
+ /// \brief Set the diagnostic client associated with this diagnostic object.
+ ///
+ /// \param ShouldOwnClient true if the diagnostic object should take
+ /// ownership of \c client.
+ void setClient(DiagnosticClient *client, bool ShouldOwnClient = true);
+
+ /// setErrorLimit - Specify a limit for the number of errors we should
+ /// emit before giving up. Zero disables the limit.
+ void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
+
+ /// \brief Specify the maximum number of template instantiation
+ /// notes to emit along with a given diagnostic.
+ void setTemplateBacktraceLimit(unsigned Limit) {
+ TemplateBacktraceLimit = Limit;
+ }
+
+ /// \brief Retrieve the maximum number of template instantiation
+ /// nodes to emit along with a given diagnostic.
+ unsigned getTemplateBacktraceLimit() const {
+ return TemplateBacktraceLimit;
+ }
+
+ /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
+ /// ignored. If this and WarningsAsErrors are both set, then this one wins.
+ void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
+ bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
+
+ /// setWarningsAsErrors - When set to true, any warnings reported are issued
+ /// as errors.
+ void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
+ bool getWarningsAsErrors() const { return WarningsAsErrors; }
+
+ /// setErrorsAsFatal - When set to true, any error reported is made a
+ /// fatal error.
+ void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
+ bool getErrorsAsFatal() const { return ErrorsAsFatal; }
+
+ /// setSuppressSystemWarnings - When set to true mask warnings that
+ /// come from system headers.
+ void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
+ bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
+
+ /// \brief Suppress all diagnostics, to silence the front end when we
+ /// know that we don't want any more diagnostics to be passed along to the
+ /// client
+ void setSuppressAllDiagnostics(bool Val = true) {
+ SuppressAllDiagnostics = Val;
+ }
+ bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
+
+ /// \brief Specify which overload candidates to show when overload resolution
+ /// fails. By default, we show all candidates.
+ void setShowOverloads(OverloadsShown Val) {
+ ShowOverloads = Val;
+ }
+ OverloadsShown getShowOverloads() const { return ShowOverloads; }
+
+ /// \brief Pretend that the last diagnostic issued was ignored. This can
+ /// be used by clients who suppress diagnostics themselves.
+ void setLastDiagnosticIgnored() {
+ LastDiagLevel = DiagnosticIDs::Ignored;
+ }
+
+ /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
+ /// extension diagnostics are mapped onto ignore/warning/error. This
+ /// corresponds to the GCC -pedantic and -pedantic-errors option.
+ void setExtensionHandlingBehavior(ExtensionHandling H) {
+ ExtBehavior = H;
+ }
+
+ /// AllExtensionsSilenced - This is a counter bumped when an __extension__
+ /// block is encountered. When non-zero, all extension diagnostics are
+ /// entirely silenced, no matter how they are mapped.
+ void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
+ void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
+ bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
+
+ /// \brief This allows the client to specify that certain
+ /// warnings are ignored. Notes can never be mapped, errors can only be
+ /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
+ ///
+ /// \param Loc The source location that this change of diagnostic state should
+ /// take affect. It can be null if we are setting the latest state.
+ void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
+ SourceLocation Loc);
+
+ /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+ /// "unknown-pragmas" to have the specified mapping. This returns true and
+ /// ignores the request if "Group" was unknown, false otherwise.
+ ///
+ /// 'Loc' is the source location that this change of diagnostic state should
+ /// take affect. It can be null if we are setting the state from command-line.
+ bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
+ SourceLocation Loc = SourceLocation()) {
+ return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this);
+ }
+
+ bool hasErrorOccurred() const { return ErrorOccurred; }
+ bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
+
+ unsigned getNumWarnings() const { return NumWarnings; }
+
+ void setNumWarnings(unsigned NumWarnings) {
+ this->NumWarnings = NumWarnings;
+ }
+
+ /// getCustomDiagID - Return an ID for a diagnostic with the specified message
+ /// and level. If this is the first request for this diagnosic, it is
+ /// registered and created, otherwise the existing ID is returned.
+ unsigned getCustomDiagID(Level L, llvm::StringRef Message) {
+ return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
+ }
+
+ /// ConvertArgToString - This method converts a diagnostic argument (as an
+ /// intptr_t) into the string that represents it.
+ void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
+ const char *Modifier, unsigned ModLen,
+ const char *Argument, unsigned ArgLen,
+ const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output) const {
+ ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
+ PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
+ }
+
+ void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
+ ArgToStringFn = Fn;
+ ArgToStringCookie = Cookie;
+ }
+
+ /// \brief Reset the state of the diagnostic object to its initial
+ /// configuration.
+ void Reset();
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic classification and reporting interfaces.
+ //
+
+ /// \brief Based on the way the client configured the Diagnostic
+ /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticClient.
+ ///
+ /// \param Loc The source location we are interested in finding out the
+ /// diagnostic state. Can be null in order to query the latest state.
+ Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
+ return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
+ }
+
+ /// Report - Issue the message to the client. @c DiagID is a member of the
+ /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
+ /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
+ /// @c Pos represents the source location associated with the diagnostic,
+ /// which can be an invalid location if no position information is available.
+ inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
+ inline DiagnosticBuilder Report(unsigned DiagID);
+
+ /// \brief Determine whethere there is already a diagnostic in flight.
+ bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
+
+ /// \brief Set the "delayed" diagnostic that will be emitted once
+ /// the current diagnostic completes.
+ ///
+ /// If a diagnostic is already in-flight but the front end must
+ /// report a problem (e.g., with an inconsistent file system
+ /// state), this routine sets a "delayed" diagnostic that will be
+ /// emitted after the current diagnostic completes. This should
+ /// only be used for fatal errors detected at inconvenient
+ /// times. If emitting a delayed diagnostic causes a second delayed
+ /// diagnostic to be introduced, that second delayed diagnostic
+ /// will be ignored.
+ ///
+ /// \param DiagID The ID of the diagnostic being delayed.
+ ///
+ /// \param Arg1 A string argument that will be provided to the
+ /// diagnostic. A copy of this string will be stored in the
+ /// Diagnostic object itself.
+ ///
+ /// \param Arg2 A string argument that will be provided to the
+ /// diagnostic. A copy of this string will be stored in the
+ /// Diagnostic object itself.
+ void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "",
+ llvm::StringRef Arg2 = "");
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { CurDiagID = ~0U; }
+
+private:
+ /// \brief Report the delayed diagnostic.
+ void ReportDelayed();
+
+
+ /// getDiagnosticMappingInfo - Return the mapping info currently set for the
+ /// specified builtin diagnostic. This returns the high bit encoding, or zero
+ /// if the field is completely uninitialized.
+ diag::Mapping getDiagnosticMappingInfo(diag::kind Diag,
+ DiagState *State) const {
+ return State->getMapping(Diag);
+ }
+
+ void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
+ DiagState *State,
+ bool isUser, bool isPragma) const {
+ if (isUser) Map |= 8; // Set the high bit for user mappings.
+ if (isPragma) Map |= 0x10; // Set the bit for diagnostic pragma mappings.
+ State->setMapping((diag::kind)DiagId, Map);
+ }
+
+ // This is private state used by DiagnosticBuilder. We put it here instead of
+ // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
+ // object. This implementation choice means that we can only have one
+ // diagnostic "in flight" at a time, but this seems to be a reasonable
+ // tradeoff to keep these objects small. Assertions verify that only one
+ // diagnostic is in flight at a time.
+ friend class DiagnosticIDs;
+ friend class DiagnosticBuilder;
+ friend class DiagnosticInfo;
+ friend class PartialDiagnostic;
+ friend class DiagnosticErrorTrap;
+
+ /// CurDiagLoc - This is the location of the current diagnostic that is in
+ /// flight.
+ SourceLocation CurDiagLoc;
+
+ /// CurDiagID - This is the ID of the current diagnostic that is in flight.
+ /// This is set to ~0U when there is no diagnostic in flight.
+ unsigned CurDiagID;
+
+ enum {
+ /// MaxArguments - The maximum number of arguments we can hold. We currently
+ /// only support up to 10 arguments (%0-%9). A single diagnostic with more
+ /// than that almost certainly has to be simplified anyway.
+ MaxArguments = 10
+ };
+
+ /// NumDiagArgs - This contains the number of entries in Arguments.
+ signed char NumDiagArgs;
+ /// NumRanges - This is the number of ranges in the DiagRanges array.
+ unsigned char NumDiagRanges;
+ /// \brief The number of code modifications hints in the
+ /// FixItHints array.
+ unsigned char NumFixItHints;
+
+ /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
+ /// values, with one for each argument. This specifies whether the argument
+ /// is in DiagArgumentsStr or in DiagArguments.
+ unsigned char DiagArgumentsKind[MaxArguments];
+
+ /// DiagArgumentsStr - This holds the values of each string argument for the
+ /// current diagnostic. This value is only used when the corresponding
+ /// ArgumentKind is ak_std_string.
+ std::string DiagArgumentsStr[MaxArguments];
+
+ /// DiagArgumentsVal - The values for the various substitution positions. This
+ /// is used when the argument is not an std::string. The specific value is
+ /// mangled into an intptr_t and the intepretation depends on exactly what
+ /// sort of argument kind it is.
+ intptr_t DiagArgumentsVal[MaxArguments];
+
+ /// DiagRanges - The list of ranges added to this diagnostic. It currently
+ /// only support 10 ranges, could easily be extended if needed.
+ CharSourceRange DiagRanges[10];
+
+ enum { MaxFixItHints = 3 };
+
+ /// FixItHints - If valid, provides a hint with some code
+ /// to insert, remove, or modify at a particular position.
+ FixItHint FixItHints[MaxFixItHints];
+
+ /// ProcessDiag - This is the method used to report a diagnostic that is
+ /// finally fully formed.
+ ///
+ /// \returns true if the diagnostic was emitted, false if it was
+ /// suppressed.
+ bool ProcessDiag() {
+ return Diags->ProcessDiag(*this);
+ }
+
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// \brief RAII class that determines when any errors have occurred
+/// between the time the instance was created and the time it was
+/// queried.
+class DiagnosticErrorTrap {
+ Diagnostic &Diag;
+ unsigned PrevErrors;
+
+public:
+ explicit DiagnosticErrorTrap(Diagnostic &Diag)
+ : Diag(Diag), PrevErrors(Diag.NumErrors) {}
+
+ /// \brief Determine whether any errors have occurred since this
+ /// object instance was created.
+ bool hasErrorOccurred() const {
+ return Diag.NumErrors > PrevErrors;
+ }
+
+ // Set to initial state of "no errors occurred".
+ void reset() { PrevErrors = Diag.NumErrors; }
+};
+
+//===----------------------------------------------------------------------===//
+// DiagnosticBuilder
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticBuilder - This is a little helper class used to produce
+/// diagnostics. This is constructed by the Diagnostic::Report method, and
+/// allows insertion of extra information (arguments and source ranges) into the
+/// currently "in flight" diagnostic. When the temporary for the builder is
+/// destroyed, the diagnostic is issued.
+///
+/// Note that many of these will be created as temporary objects (many call
+/// sites), so we want them to be small and we never want their address taken.
+/// This ensures that compilers with somewhat reasonable optimizers will promote
+/// the common fields to registers, eliminating increments of the NumArgs field,
+/// for example.
+class DiagnosticBuilder {
+ mutable Diagnostic *DiagObj;
+ mutable unsigned NumArgs, NumRanges, NumFixItHints;
+
+ void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
+ friend class Diagnostic;
+ explicit DiagnosticBuilder(Diagnostic *diagObj)
+ : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
+
+ friend class PartialDiagnostic;
+
+protected:
+ void FlushCounts();
+
+public:
+ /// Copy constructor. When copied, this "takes" the diagnostic info from the
+ /// input and neuters it.
+ DiagnosticBuilder(const DiagnosticBuilder &D) {
+ DiagObj = D.DiagObj;
+ D.DiagObj = 0;
+ NumArgs = D.NumArgs;
+ NumRanges = D.NumRanges;
+ NumFixItHints = D.NumFixItHints;
+ }
+
+ /// \brief Simple enumeration value used to give a name to the
+ /// suppress-diagnostic constructor.
+ enum SuppressKind { Suppress };
+
+ /// \brief Create an empty DiagnosticBuilder object that represents
+ /// no actual diagnostic.
+ explicit DiagnosticBuilder(SuppressKind)
+ : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }
+
+ /// \brief Force the diagnostic builder to emit the diagnostic now.
+ ///
+ /// Once this function has been called, the DiagnosticBuilder object
+ /// should not be used again before it is destroyed.
+ ///
+ /// \returns true if a diagnostic was emitted, false if the
+ /// diagnostic was suppressed.
+ bool Emit();
+
+ /// Destructor - The dtor emits the diagnostic if it hasn't already
+ /// been emitted.
+ ~DiagnosticBuilder() { Emit(); }
+
+ /// isActive - Determine whether this diagnostic is still active.
+ bool isActive() const { return DiagObj != 0; }
+
+ /// \brief Retrieve the active diagnostic ID.
+ ///
+ /// \pre \c isActive()
+ unsigned getDiagID() const {
+ assert(isActive() && "Diagnostic is inactive");
+ return DiagObj->CurDiagID;
+ }
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { DiagObj = 0; }
+
+ /// Operator bool: conversion of DiagnosticBuilder to bool always returns
+ /// true. This allows is to be used in boolean error contexts like:
+ /// return Diag(...);
+ operator bool() const { return true; }
+
+ void AddString(llvm::StringRef S) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ if (DiagObj) {
+ DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
+ DiagObj->DiagArgumentsStr[NumArgs++] = S;
+ }
+ }
+
+ void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ if (DiagObj) {
+ DiagObj->DiagArgumentsKind[NumArgs] = Kind;
+ DiagObj->DiagArgumentsVal[NumArgs++] = V;
+ }
+ }
+
+ void AddSourceRange(const CharSourceRange &R) const {
+ assert(NumRanges <
+ sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
+ "Too many arguments to diagnostic!");
+ if (DiagObj)
+ DiagObj->DiagRanges[NumRanges++] = R;
+ }
+
+ void AddFixItHint(const FixItHint &Hint) const {
+ if (Hint.isNull())
+ return;
+
+ assert(NumFixItHints < Diagnostic::MaxFixItHints &&
+ "Too many fix-it hints!");
+ if (DiagObj)
+ DiagObj->FixItHints[NumFixItHints++] = Hint;
+ }
+};
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ llvm::StringRef S) {
+ DB.AddString(S);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const char *Str) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
+ Diagnostic::ak_c_string);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ unsigned I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_uint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const IdentifierInfo *II) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ Diagnostic::ak_identifierinfo);
+ return DB;
+}
+
+// Adds a DeclContext to the diagnostic. The enable_if template magic is here
+// so that we only match those arguments that are (statically) DeclContexts;
+// other arguments that derive from DeclContext (e.g., RecordDecls) will not
+// match.
+template<typename T>
+inline
+typename llvm::enable_if<llvm::is_same<T, DeclContext>,
+ const DiagnosticBuilder &>::type
+operator<<(const DiagnosticBuilder &DB, T *DC) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
+ Diagnostic::ak_declcontext);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const SourceRange &R) {
+ DB.AddSourceRange(CharSourceRange::getTokenRange(R));
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const CharSourceRange &R) {
+ DB.AddSourceRange(R);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const FixItHint &Hint) {
+ DB.AddFixItHint(Hint);
+ return DB;
+}
+
+/// Report - Issue the message to the client. DiagID is a member of the
+/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
+/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
+inline DiagnosticBuilder Diagnostic::Report(SourceLocation Loc,
+ unsigned DiagID){
+ assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ CurDiagLoc = Loc;
+ CurDiagID = DiagID;
+ return DiagnosticBuilder(this);
+}
+inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
+ return Report(SourceLocation(), DiagID);
+}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInfo
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticInfo - This is a little helper class (which is basically a smart
+/// pointer that forward info from Diagnostic) that allows clients to enquire
+/// about the currently in-flight diagnostic.
+class DiagnosticInfo {
+ const Diagnostic *DiagObj;
+public:
+ explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
+
+ const Diagnostic *getDiags() const { return DiagObj; }
+ unsigned getID() const { return DiagObj->CurDiagID; }
+ const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
+ bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
+ SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
+
+ unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
+
+ /// getArgKind - Return the kind of the specified index. Based on the kind
+ /// of argument, the accessors below can be used to get the value.
+ Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Argument index out of range!");
+ return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
+ }
+
+ /// getArgStdStr - Return the provided argument string specified by Idx.
+ const std::string &getArgStdStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsStr[Idx];
+ }
+
+ /// getArgCStr - Return the specified C string argument.
+ const char *getArgCStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
+ "invalid argument accessor!");
+ return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// getArgSInt - Return the specified signed integer argument.
+ int getArgSInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_sint &&
+ "invalid argument accessor!");
+ return (int)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// getArgUInt - Return the specified unsigned integer argument.
+ unsigned getArgUInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_uint &&
+ "invalid argument accessor!");
+ return (unsigned)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// getArgIdentifier - Return the specified IdentifierInfo argument.
+ const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
+ "invalid argument accessor!");
+ return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// getRawArg - Return the specified non-string argument in an opaque form.
+ intptr_t getRawArg(unsigned Idx) const {
+ assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsVal[Idx];
+ }
+
+
+ /// getNumRanges - Return the number of source ranges associated with this
+ /// diagnostic.
+ unsigned getNumRanges() const {
+ return DiagObj->NumDiagRanges;
+ }
+
+ const CharSourceRange &getRange(unsigned Idx) const {
+ assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
+ return DiagObj->DiagRanges[Idx];
+ }
+
+ unsigned getNumFixItHints() const {
+ return DiagObj->NumFixItHints;
+ }
+
+ const FixItHint &getFixItHint(unsigned Idx) const {
+ return DiagObj->FixItHints[Idx];
+ }
+
+ const FixItHint *getFixItHints() const {
+ return DiagObj->NumFixItHints?
+ &DiagObj->FixItHints[0] : 0;
+ }
+
+ /// FormatDiagnostic - Format this diagnostic into a string, substituting the
+ /// formal arguments into the %0 slots. The result is appended onto the Str
+ /// array.
+ void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
+
+ /// FormatDiagnostic - Format the given format-string into the
+ /// output buffer using the arguments stored in this diagnostic.
+ void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ llvm::SmallVectorImpl<char> &OutStr) const;
+};
+
+/**
+ * \brief Represents a diagnostic in a form that can be retained until its
+ * corresponding source manager is destroyed.
+ */
+class StoredDiagnostic {
+ unsigned ID;
+ Diagnostic::Level Level;
+ FullSourceLoc Loc;
+ std::string Message;
+ std::vector<CharSourceRange> Ranges;
+ std::vector<FixItHint> FixIts;
+
+public:
+ StoredDiagnostic();
+ StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info);
+ StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
+ llvm::StringRef Message);
+ ~StoredDiagnostic();
+
+ /// \brief Evaluates true when this object stores a diagnostic.
+ operator bool() const { return Message.size() > 0; }
+
+ unsigned getID() const { return ID; }
+ Diagnostic::Level getLevel() const { return Level; }
+ const FullSourceLoc &getLocation() const { return Loc; }
+ llvm::StringRef getMessage() const { return Message; }
+
+ void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
+
+ typedef std::vector<CharSourceRange>::const_iterator range_iterator;
+ range_iterator range_begin() const { return Ranges.begin(); }
+ range_iterator range_end() const { return Ranges.end(); }
+ unsigned range_size() const { return Ranges.size(); }
+
+ typedef std::vector<FixItHint>::const_iterator fixit_iterator;
+ fixit_iterator fixit_begin() const { return FixIts.begin(); }
+ fixit_iterator fixit_end() const { return FixIts.end(); }
+ unsigned fixit_size() const { return FixIts.size(); }
+};
+
+/// DiagnosticClient - This is an abstract interface implemented by clients of
+/// the front-end, which formats and prints fully processed diagnostics.
+class DiagnosticClient {
+protected:
+ unsigned NumWarnings; // Number of warnings reported
+ unsigned NumErrors; // Number of errors reported
+
+public:
+ DiagnosticClient() : NumWarnings(0), NumErrors(0) { }
+
+ unsigned getNumErrors() const { return NumErrors; }
+ unsigned getNumWarnings() const { return NumWarnings; }
+
+ virtual ~DiagnosticClient();
+
+ /// BeginSourceFile - Callback to inform the diagnostic client that processing
+ /// of a source file is beginning.
+ ///
+ /// Note that diagnostics may be emitted outside the processing of a source
+ /// file, for example during the parsing of command line options. However,
+ /// diagnostics with source range information are required to only be emitted
+ /// in between BeginSourceFile() and EndSourceFile().
+ ///
+ /// \arg LO - The language options for the source file being processed.
+ /// \arg PP - The preprocessor object being used for the source; this optional
+ /// and may not be present, for example when processing AST source files.
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = 0) {}
+
+ /// EndSourceFile - Callback to inform the diagnostic client that processing
+ /// of a source file has ended. The diagnostic client should assume that any
+ /// objects made available via \see BeginSourceFile() are inaccessible.
+ virtual void EndSourceFile() {}
+
+ /// IncludeInDiagnosticCounts - This method (whose default implementation
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticClient should be included in the number of diagnostics reported
+ /// by Diagnostic.
+ virtual bool IncludeInDiagnosticCounts() const;
+
+ /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ ///
+ /// Default implementation just keeps track of the total number of warnings
+ /// and errors.
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
new file mode 100644
index 0000000..be510ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
@@ -0,0 +1,89 @@
+//===--- Diagnostic.td - C Language Family Diagnostic Handling ------------===//
+//
+// 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 TableGen core definitions for the diagnostics
+// and diagnostic control.
+//
+//===----------------------------------------------------------------------===//
+
+// Define the diagnostic mappings.
+class DiagMapping;
+def MAP_IGNORE : DiagMapping;
+def MAP_WARNING : DiagMapping;
+def MAP_ERROR : DiagMapping;
+def MAP_FATAL : DiagMapping;
+
+// Define the diagnostic classes.
+class DiagClass;
+def CLASS_NOTE : DiagClass;
+def CLASS_WARNING : DiagClass;
+def CLASS_EXTENSION : DiagClass;
+def CLASS_ERROR : DiagClass;
+
+// Diagnostic Categories. These can be applied to groups or individual
+// diagnostics to specify a category.
+class DiagCategory<string Name> {
+ string CategoryName = Name;
+}
+
+// Diagnostic Groups.
+class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
+ string GroupName = Name;
+ list<DiagGroup> SubGroups = subgroups;
+ string CategoryName = "";
+}
+class InGroup<DiagGroup G> { DiagGroup Group = G; }
+//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
+
+
+// This defines all of the named diagnostic categories.
+include "DiagnosticCategories.td"
+
+// This defines all of the named diagnostic groups.
+include "DiagnosticGroups.td"
+
+
+// All diagnostics emitted by the compiler are an indirect subclass of this.
+class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
+ /// Component is specified by the file with a big let directive.
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ bit SFINAE = 1;
+ bit AccessControl = 0;
+ DiagMapping DefaultMapping = defaultmapping;
+ DiagGroup Group;
+ string CategoryName = "";
+}
+
+class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>;
+class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
+class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
+class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
+class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>;
+
+
+class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; }
+class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; }
+class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
+class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
+
+class NoSFINAE { bit SFINAE = 0; }
+class AccessControl { bit AccessControl = 1; }
+
+// Definitions for Diagnostics.
+include "DiagnosticASTKinds.td"
+include "DiagnosticAnalysisKinds.td"
+include "DiagnosticCommonKinds.td"
+include "DiagnosticDriverKinds.td"
+include "DiagnosticFrontendKinds.td"
+include "DiagnosticLexKinds.td"
+include "DiagnosticParseKinds.td"
+include "DiagnosticSemaKinds.td"
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
new file mode 100644
index 0000000..7d45bc5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -0,0 +1,113 @@
+//==--- DiagnosticASTKinds.td - libast diagnostics ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "AST" in {
+
+//def note_comma_in_ice : Note<
+// "C does not permit evaluated commas in an integer constant expression">;
+def note_expr_divide_by_zero : Note<"division by zero">;
+
+// inline asm related.
+let CategoryName = "Inline Assembly Issue" in {
+ def err_asm_invalid_escape : Error<
+ "invalid %% escape in inline assembly string">;
+ def err_asm_unknown_symbolic_operand_name : Error<
+ "unknown symbolic operand name in inline assembly string">;
+
+ def err_asm_unterminated_symbolic_operand_name : Error<
+ "unterminated symbolic operand name in inline assembly string">;
+ def err_asm_empty_symbolic_operand_name : Error<
+ "empty symbolic operand name in inline assembly string">;
+ def err_asm_invalid_operand_number : Error<
+ "invalid operand number in inline asm string">;
+}
+
+
+// Importing ASTs
+def err_odr_variable_type_inconsistent : Error<
+ "external variable %0 declared with incompatible types in different "
+ "translation units (%1 vs. %2)">;
+def err_odr_variable_multiple_def : Error<
+ "external variable %0 defined in multiple translation units">;
+def note_odr_value_here : Note<"declared here with type %0">;
+def note_odr_defined_here : Note<"also defined here">;
+def err_odr_function_type_inconsistent : Error<
+ "external function %0 declared with incompatible types in different "
+ "translation units (%1 vs. %2)">;
+def warn_odr_tag_type_inconsistent : Warning<
+ "type %0 has incompatible definitions in different translation units">;
+def note_odr_tag_kind_here: Note<
+ "%0 is a %select{struct|union|class|enum}1 here">;
+def note_odr_field : Note<"field %0 has type %1 here">;
+def note_odr_missing_field : Note<"no corresponding field here">;
+def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
+def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
+def note_odr_base : Note<"class has base type %0">;
+def note_odr_virtual_base : Note<
+ "%select{non-virtual|virtual}0 derivation here">;
+def note_odr_missing_base : Note<"no corresponding base class here">;
+def note_odr_number_of_bases : Note<
+ "class has %0 base %plural{1:class|:classes}0">;
+def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
+def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
+
+// Importing Objective-C ASTs
+def err_odr_ivar_type_inconsistent : Error<
+ "instance variable %0 declared with incompatible types in different "
+ "translation units (%1 vs. %2)">;
+def err_odr_objc_superclass_inconsistent : Error<
+ "class %0 has incompatible superclasses">;
+def note_odr_objc_superclass : Note<"inherits from superclass %0 here">;
+def note_odr_objc_missing_superclass : Note<"no corresponding superclass here">;
+def err_odr_objc_method_result_type_inconsistent : Error<
+ "%select{class|instance}0 method %1 has incompatible result types in "
+ "different translation units (%2 vs. %3)">;
+def err_odr_objc_method_num_params_inconsistent : Error<
+ "%select{class|instance}0 method %1 has a different number of parameters in "
+ "different translation units (%2 vs. %3)">;
+def err_odr_objc_method_param_type_inconsistent : Error<
+ "%select{class|instance}0 method %1 has a parameter with a different types "
+ "in different translation units (%2 vs. %3)">;
+def err_odr_objc_method_variadic_inconsistent : Error<
+ "%select{class|instance}0 method %1 is variadic in one translation unit "
+ "and not variadic in another">;
+def note_odr_objc_method_here : Note<
+ "%select{class|instance}0 method %1 also declared here">;
+def err_odr_objc_property_type_inconsistent : Error<
+ "property %0 declared with incompatible types in different "
+ "translation units (%1 vs. %2)">;
+def err_odr_objc_property_impl_kind_inconsistent : Error<
+ "property %0 is implemented with %select{@synthesize|@dynamic}1 in one "
+ "translation but %select{@dynamic|@synthesize}1 in another translation unit">;
+def note_odr_objc_property_impl_kind : Note<
+ "property %0 is implemented with %select{@synthesize|@dynamic}1 here">;
+def err_odr_objc_synthesize_ivar_inconsistent : Error<
+ "property %0 is synthesized to different ivars in different translation "
+ "units (%1 vs. %2)">;
+def note_odr_objc_synthesize_ivar_here : Note<
+ "property is synthesized to ivar %0 here">;
+
+// Importing C++ ASTs
+def err_odr_different_num_template_parameters : Error<
+ "template parameter lists have a different number of parameters (%0 vs %1)">;
+def note_odr_template_parameter_list : Note<
+ "template parameter list also declared here">;
+def err_odr_different_template_parameter_kind : Error<
+ "template parameter has different kinds in different translation units">;
+def note_odr_template_parameter_here : Note<
+ "template parameter declared here">;
+def err_odr_parameter_pack_non_pack : Error<
+ "parameter kind mismatch; parameter is %select{not a|a}0 parameter pack">;
+def note_odr_parameter_pack_non_pack : Note<
+ "%select{parameter|parameter pack}0 declared here">;
+def err_odr_non_type_parameter_type_inconsistent : Error<
+ "non-type template parameter declared with incompatible types in different "
+ "translation units (%0 vs. %1)">;
+def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td
new file mode 100644
index 0000000..46dc0e6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td
@@ -0,0 +1,15 @@
+//==--- DiagnosticAnalysisKinds.td - libanalysis diagnostics --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Analysis" in {
+
+// CHECK: use of uninitialized values
+def warn_uninit_val : Warning<"use of uninitialized variable">;
+
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td
new file mode 100644
index 0000000..a02fbdf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td
@@ -0,0 +1,10 @@
+//==--- DiagnosticCategories.td - Diagnostic Category Definitions ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
new file mode 100644
index 0000000..85c64c5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -0,0 +1,82 @@
+//==--- DiagnosticCommonKinds.td - common diagnostics ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Common Helpers
+//===----------------------------------------------------------------------===//
+
+let Component = "Common" in {
+
+// Basic.
+
+def fatal_too_many_errors
+ : Error<"too many errors emitted, stopping now">, DefaultFatal;
+
+def note_previous_definition : Note<"previous definition is here">;
+def note_previous_declaration : Note<"previous declaration is here">;
+def note_previous_implicit_declaration : Note<
+ "previous implicit declaration is here">;
+def note_previous_use : Note<"previous use is here">;
+def note_duplicate_case_prev : Note<"previous case defined here">;
+def note_forward_declaration : Note<"forward declaration of %0">;
+def note_type_being_defined : Note<
+ "definition of %0 is not complete until the closing '}'">;
+/// note_matching - this is used as a continuation of a previous diagnostic,
+/// e.g. to specify the '(' when we expected a ')'.
+def note_matching : Note<"to match this '%0'">;
+
+def note_using : Note<"using">;
+def note_also_found : Note<"also found">;
+
+// Parse && Lex
+def err_expected_colon : Error<"expected ':'">;
+def err_expected_colon_after_setter_name : Error<
+ "method name referenced in property setter attribute "
+ "must end with ':'">;
+
+// Parse && Sema
+def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
+ InGroup<MissingDeclarations>;
+def err_param_redefinition : Error<"redefinition of parameter %0">;
+def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
+def err_invalid_storage_class_in_func_decl : Error<
+ "invalid storage class specifier in function declarator">;
+def err_expected_namespace_name : Error<"expected namespace name">;
+def ext_variadic_templates : ExtWarn<
+ "variadic templates are a C++0x extension">, InGroup<CXX0x>;
+
+// Sema && Lex
+def ext_longlong : Extension<
+ "'long long' is an extension when C99 mode is not enabled">,
+ InGroup<LongLong>;
+def warn_integer_too_large : Warning<
+ "integer constant is too large for its type">;
+def warn_integer_too_large_for_signed : Warning<
+ "integer constant is so large that it is unsigned">;
+
+// Sema && AST
+def note_invalid_subexpr_in_ice : Note<
+ "subexpression not valid in an integer constant expression">;
+
+// Targets
+
+def err_target_unknown_triple : Error<
+ "unknown target triple '%0', please use -triple or -arch">;
+def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
+def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
+def err_target_unknown_cxxabi : Error<"unknown C++ ABI '%0'">;
+def err_target_invalid_feature : Error<"invalid target feature '%0'">;
+
+// Source manager
+def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
+def err_file_modified : Error<
+ "file '%0' modified since it was first processed">, DefaultFatal;
+def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
+ "encoding is not supported">, DefaultFatal;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
new file mode 100644
index 0000000..ef1c9e7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -0,0 +1,114 @@
+//==--- DiagnosticDriverKinds.td - libdriver diagnostics ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Driver" in {
+
+def err_drv_no_such_file : Error<"no such file or directory: '%0'">;
+def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
+def err_drv_unsupported_option_argument : Error<
+ "unsupported argument '%1' to option '%0'">;
+def err_drv_unknown_stdin_type : Error<
+ "-E or -x required when input is from standard input">;
+def err_drv_unknown_language : Error<"language not recognized: '%0'">;
+def err_drv_invalid_arch_name : Error<
+ "invalid arch name '%0'">;
+def err_drv_invalid_stdlib_name : Error<
+ "invalid library name in argument '%0'">;
+def err_drv_invalid_opt_with_multiple_archs : Error<
+ "option '%0' cannot be used with multiple -arch options">;
+def err_drv_invalid_output_with_multiple_archs : Error<
+ "cannot use '%0' output with multiple -arch options">;
+def err_drv_no_input_files : Error<"no input files">;
+def err_drv_use_of_Z_option : Error<
+ "unsupported use of internal gcc -Z option '%0'">;
+def err_drv_output_argument_with_multiple_files : Error<
+ "cannot specify -o when generating multiple output files">;
+def err_drv_unable_to_make_temp : Error<
+ "unable to make temporary file: %0">;
+def err_drv_unable_to_remove_file : Error<
+ "unable to remove file: %0">;
+def err_drv_command_failure : Error<
+ "unable to execute command: %0">;
+def err_drv_invalid_darwin_version : Error<
+ "invalid Darwin version number: %0">;
+def err_drv_missing_argument : Error<
+ "argument to '%0' is missing (expected %1 %plural{1:value|:values}1)">;
+def err_drv_invalid_Xarch_argument : Error<
+ "invalid Xarch argument: '%0'">;
+def err_drv_argument_only_allowed_with : Error<
+ "invalid argument '%0' only allowed with '%1'">;
+def err_drv_argument_not_allowed_with : Error<
+ "invalid argument '%0' not allowed with '%1'">;
+def err_drv_invalid_version_number : Error<
+ "invalid version number in '%0'">;
+def err_drv_no_linker_llvm_support : Error<
+ "'%0': unable to pass LLVM bit-code files to linker">;
+def err_drv_no_ast_support : Error<
+ "'%0': unable to use AST files with this tool">;
+def err_drv_clang_unsupported : Error<
+ "the clang compiler does not support '%0'">;
+def err_drv_clang_unsupported_per_platform : Error<
+ "the clang compiler does not support '%0' on this platform">;
+def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
+ "the clang compiler does not support '%0' for C++ on Darwin/i386">;
+def err_drv_command_failed : Error<
+ "%0 command failed with exit code %1 (use -v to see invocation)">;
+def err_drv_command_signalled : Error<
+ "%0 command failed due to signal %1 (use -v to see invocation)">;
+def err_drv_invalid_mfloat_abi : Error<
+ "invalid float ABI '%0'">;
+def err_drv_I_dash_not_supported : Error<
+ "'%0' not supported, please use -iquote instead">;
+def err_drv_unknown_argument : Error<"unknown argument: '%0'">;
+def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
+def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
+def err_drv_invalid_remap_file : Error<
+ "invalid option '%0' not of the form <from-file>;<to-file>">;
+def err_drv_invalid_gcc_output_type : Error<
+ "invalid output type '%0' for use with gcc tool">;
+def err_drv_cc_print_options_failure : Error<
+ "unable to open CC_PRINT_OPTIONS file: %0">;
+def err_drv_preamble_format : Error<
+ "incorrect format for -preamble-bytes=N,END">;
+
+def warn_c_kext : Warning<
+ "ignoring -fapple-kext which is valid for c++ and objective-c++ only">;
+def warn_drv_unsupported_option_argument : Warning<
+ "ignoring unsupported argument '%1' to option '%0'">;
+def warn_drv_input_file_unused : Warning<
+ "%0: '%1' input unused when '%2' is present">;
+def warn_drv_preprocessed_input_file_unused : Warning<
+ "%0: previously preprocessed input unused when '%1' is present">;
+def warn_drv_unused_argument : Warning<
+ "argument unused during compilation: '%0'">;
+def warn_drv_pipe_ignored_with_save_temps : Warning<
+ "-pipe ignored because -save-temps specified">;
+def warn_drv_not_using_clang_cpp : Warning<
+ "not using the clang preprocessor due to user override">;
+def warn_drv_not_using_clang_cxx : Warning<
+ "not using the clang compiler for C++ inputs">;
+def warn_drv_not_using_clang_arch : Warning<
+ "not using the clang compiler for the '%0' architecture">;
+def warn_drv_clang_unsupported : Warning<
+ "the clang compiler does not support '%0'">;
+def warn_drv_assuming_mfloat_abi_is : Warning<
+ "unknown platform, assuming -mfloat-abi=%0">;
+def warn_ignoring_ftabstop_value : Warning<
+ "ignoring invalid -ftabstop value '%0', using default value %1">;
+def warn_drv_conflicting_deployment_targets : Warning<
+ "conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">;
+def warn_drv_treating_input_as_cxx : Warning<
+ "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
+ InGroup<Deprecated>;
+def warn_drv_objc_gc_unsupported : Warning<
+ "Objective-C garbage collection is not supported on this platform, ignoring '%0'">;
+def warn_drv_pch_not_first_include : Warning<
+ "precompiled header '%0' was ignored because '%1' is not first '-include'">;
+
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
new file mode 100644
index 0000000..5f9f4a7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -0,0 +1,279 @@
+//==--- DiagnosticFrontendKinds.td - frontend diagnostics -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Frontend" in {
+
+def err_fe_error_opening : Error<"error opening '%0': %1">;
+def err_fe_error_reading : Error<"error reading '%0'">;
+def err_fe_error_reading_stdin : Error<"error reading stdin">;
+def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
+def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
+def err_fe_invalid_ast_action : Error<"invalid action for AST input">,
+ DefaultFatal;
+// Error generated by the backend.
+def err_fe_inline_asm : Error<"%0">, CatInlineAsm;
+def note_fe_inline_asm_here : Note<"instantiated into assembly here">;
+
+
+
+def err_fe_invalid_code_complete_file : Error<
+ "cannot locate code-completion file %0">, DefaultFatal;
+def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
+ DefaultFatal;
+def err_fe_stderr_binary : Error<"unable to change standard error to binary">,
+ DefaultFatal;
+def err_fe_dependency_file_requires_MT : Error<
+ "-dependency-file requires at least one -MT or -MQ option">;
+def err_fe_incompatible_options : Error<
+ "'%0' cannot be used with '%1'">, DefaultFatal;
+def err_fe_no_fixit_and_codegen : Error<
+ "FIX-ITs cannot be applied when generating code">;
+def err_fe_unable_to_find_fixit_file : Error<
+ "FIX-IT could not find file '%0'">;
+def err_fe_invalid_plugin_name : Error<
+ "unable to find plugin '%0'">;
+def err_fe_expected_compiler_job : Error<
+ "unable to handle compilation, expected exactly one compiler job in '%0'">;
+def err_fe_expected_clang_command : Error<
+ "expected a clang compiler command">;
+def err_fe_remap_missing_to_file : Error<
+ "could not remap file '%0' to the contents of file '%1'">, DefaultFatal;
+def err_fe_remap_missing_from_file : Error<
+ "could not remap from missing file '%0'">, DefaultFatal;
+def err_fe_unable_to_load_pch : Error<
+ "unable to load PCH file">;
+def err_fe_unable_to_load_plugin : Error<
+ "unable to load plugin '%0': '%1'">;
+def err_fe_unable_to_create_target : Error<
+ "unable to create target: '%0'">;
+def err_fe_unable_to_interface_with_target : Error<
+ "unable to interface with target machine">;
+def err_fe_unable_to_read_pch_file : Error<
+ "unable to read PCH file: '%0'">;
+def err_fe_not_a_pch_file : Error<
+ "input is not a PCH file: '%0'">;
+def err_fe_pch_malformed : Error<
+ "malformed or corrupted PCH file: '%0'">, DefaultFatal;
+def err_fe_pch_malformed_block : Error<
+ "malformed block record in PCH file: '%0'">, DefaultFatal;
+def err_fe_pch_error_at_end_block : Error<
+ "error at end of module block in PCH file: '%0'">, DefaultFatal;
+def err_fe_pch_file_modified : Error<
+ "file '%0' has been modified since the precompiled header was built">,
+ DefaultFatal;
+def err_fe_unable_to_open_output : Error<
+ "unable to open output file '%0': '%1'">;
+def err_fe_unable_to_rename_temp : Error<
+ "unable to rename temporary '%0' to output file '%1': '%2'">;
+def err_fe_unable_to_open_logfile : Error<
+ "unable to open logfile file '%0': '%1'">;
+def err_fe_pth_file_has_no_source_header : Error<
+ "PTH file '%0' does not designate an original source header file for -include-pth">;
+def warn_fe_macro_contains_embedded_newline : Warning<
+ "macro '%0' contains embedded newline, text after the newline is ignored.">;
+def warn_fe_cc_print_header_failure : Warning<
+ "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">;
+
+def err_verify_missing_start : Error<
+ "cannot find start ('{{') of expected %0">;
+def err_verify_missing_end : Error<
+ "cannot find end ('}}') of expected %0">;
+def err_verify_invalid_content : Error<
+ "invalid expected %0: %1">;
+def err_verify_inconsistent_diags : Error<
+ "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: "
+ "%2">;
+
+def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
+def note_fixit_in_macro : Note<
+ "FIX-IT unable to apply suggested code changes in a macro">;
+def note_fixit_failed : Note<
+ "FIX-IT unable to apply suggested code changes">;
+def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">;
+def note_fixit_main_file_unchanged : Note<
+ "main file unchanged">;
+def warn_fixit_no_changes : Note<
+ "FIX-IT detected errors it could not fix; no output will be generated">;
+
+def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal;
+
+// PCH reader
+def err_relocatable_without_isysroot : Error<
+ "must specify system root with -isysroot when building a relocatable "
+ "PCH file">;
+def warn_pch_target_triple : Error<
+ "PCH file was compiled for the target '%0' but the current translation "
+ "unit is being compiled for target '%1'">;
+def warn_pch_c99 : Error<
+ "C99 support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_cplusplus : Error<
+ "C++ support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_cplusplus0x : Error<
+ "C++0x support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_objective_c : Error<
+ "Objective-C support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_objective_c2 : Error<
+ "Objective-C 2.0 support was %select{disabled|enabled}0 in PCH file but "
+ "is currently %select{disabled|enabled}1">;
+def warn_pch_nonfragile_abi : Error<
+ "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C "
+ "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">;
+def warn_pch_nonfragile_abi2 : Error<
+ "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 "
+ "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 "
+ "Objective-C ABI is selected">;
+def warn_pch_apple_kext : Error<
+ "PCH file was compiled %select{with|without}0 support for Apple's kernel "
+ "extensions ABI but it is currently %select{disabled|enabled}1">;
+def warn_pch_objc_auto_properties : Error<
+ "PCH file was compiled %select{with|without}0 support for auto-synthesized "
+ "@properties but it is currently %select{disabled|enabled}1">;
+def warn_pch_no_constant_cfstrings : Error<
+ "Objctive-C NSstring generation support was %select{disabled|enabled}0 "
+ "in PCH file but currently %select{disabled|enabled}1">;
+def warn_pch_extensions : Error<
+ "extensions were %select{enabled|disabled}0 in PCH file but are "
+ "currently %select{enabled|disabled}1">;
+def warn_pch_gnu_extensions : Error<
+ "GNU extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_gnu_keywords : Error<
+ "GNU keywords were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_microsoft_extensions : Error<
+ "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_ms_bitfields : Error<
+ "Microsoft-compatible structure layout was %select{disabled|enabled}0 in "
+ "PCH file but is currently %select{disabled|enabled}1">;
+def warn_pch_heinous_extensions : Error<
+ "heinous extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_lax_vector_conversions : Error<
+ "lax vector conversions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_altivec : Error<
+ "AltiVec initializers were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_opencl : Error<
+ "OpenCL language extensions were %select{disabled|enabled}0 in PCH file "
+ "but are currently %select{disabled|enabled}1">;
+def warn_pch_cuda : Error<
+ "CUDA language extensions were %select{disabled|enabled}0 in PCH file "
+ "but are currently %select{disabled|enabled}1">;
+def warn_pch_elide_constructors : Error<
+ "Elidable copy constructors were %select{disabled|enabled}0 in PCH file "
+ "but are currently %select{disabled|enabled}1">;
+def warn_pch_exceptions : Error<
+ "exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_sjlj_exceptions : Error<
+ "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_objc_exceptions : Error<
+ "Objective-C exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_objc_runtime : Error<
+ "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
+ "%select{NeXT|GNU}1 runtime is selected">;
+def warn_pch_freestanding : Error<
+ "PCH file was compiled with a %select{hosted|freestanding}0 "
+ "implementation but a %select{hosted|freestanding}1 implementation "
+ "is selected">;
+def warn_pch_builtins : Error<
+ "PCH file was compiled with builtins %select{enabled|disabled}0 but "
+ "builtins are currently %select{enabled|disabled}1">;
+def warn_pch_thread_safe_statics : Error<
+ "PCH file was compiled %select{without|with}0 thread-safe statics but "
+ "thread-safe statics are currently %select{disabled|enabled}1">;
+def warn_pch_posix_threads : Error<
+ "PCH file was compiled %select{without|with}0 POSIX thread support but "
+ "POSIX threads are currently %select{disabled|enabled}1">;
+def warn_pch_stack_protector : Error<
+ "stack protector was %select{off|on|required}0 in PCH file but "
+ "is currently %select{off|on|required}1">;
+def warn_pch_blocks : Error<
+ "blocks were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_math_errno : Error<
+ "math functions %select{do not respect|respect}0 'errno' in PCH "
+ "file but they are currently set to %select{not respect|respect}1 "
+ "'errno'">;
+def warn_pch_optimize : Error<
+ "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_optimize_size : Error<
+ "the macro '__OPTIMIZE_SIZE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_static : Error<
+ "the PCH file was compiled %select{dynamic|static}0 but the "
+ "current translation unit is being compiled as %select{dynamic|static}1">;
+def warn_pch_pic_level : Error<
+ "PCH file was compiled with PIC level %0, but the current translation "
+ "unit will be compiled with PIC level %1">;
+def warn_pch_gnu_inline : Error<
+ "PCH file was compiled with %select{C99|GNU|}0 inline semantics but "
+ "%select{C99|GNU}1 inline semantics are currently selected">;
+def warn_pch_no_inline : Error<
+ "the macro '__NO_INLINE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_gc_mode : Error<
+ "the PCH file was built with %select{no||hybrid}0 garbage collection but "
+ "the current translation unit will compiled with %select{no||hybrid}1 "
+ "garbage collection">;
+def warn_pch_version_too_old : Error<
+ "PCH file uses an older PCH format that is no longer supported">;
+def warn_pch_version_too_new : Error<
+ "PCH file uses a newer PCH format that cannot be read">;
+def warn_pch_different_branch : Error<
+ "PCH file built from a different branch (%0) than the compiler (%1)">;
+def warn_cmdline_conflicting_macro_def : Error<
+ "definition of the macro '%0' conflicts with the definition used to "
+ "build the precompiled header">;
+def note_pch_macro_defined_as : Note<
+ "definition of macro '%0' in the precompiled header">;
+def warn_cmdline_missing_macro_defs : Warning<
+ "macro definitions used to build the precompiled header are missing">;
+def note_using_macro_def_from_pch : Note<
+ "using this macro definition from precompiled header">;
+def warn_macro_name_used_in_pch : Error<
+ "definition of macro %0 conflicts with an identifier used in the "
+ "precompiled header">;
+def warn_pch_compiler_options_mismatch : Error<
+ "compiler options used when building the precompiled header differ from "
+ "the options used when using the precompiled header">;
+def warn_pch_access_control : Error<
+ "C++ access control was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
+def warn_pch_char_signed : Error<
+ "char was %select{unsigned|signed}0 in the PCH file but "
+ "is currently %select{unsigned|signed}1">;
+def warn_pch_short_wchar : Error<
+ "-fshort-wchar was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
+def warn_pch_short_enums : Error<
+ "-fshort-enums was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
+
+def err_not_a_pch_file : Error<
+ "'%0' does not appear to be a precompiled header file">, DefaultFatal;
+def warn_unknown_warning_option : Warning<
+ "unknown warning option '%0'">,
+ InGroup<DiagGroup<"unknown-warning-option"> >;
+def warn_unknown_warning_specifier : Warning<
+ "unknown %0 warning specifier: '%1'">,
+ InGroup<DiagGroup<"unknown-warning-option"> >;
+
+def warn_unkwown_analyzer_checker : Warning<
+ "no analyzer checkers are associated with '%0'">;
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
new file mode 100644
index 0000000..d4377c9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -0,0 +1,260 @@
+//==--- DiagnosticGroups.td - Diagnostic Group Definitions ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+def ImplicitFunctionDeclare : DiagGroup<"implicit-function-declaration">;
+def ImplicitInt : DiagGroup<"implicit-int">;
+
+// Aggregation warning settings.
+def Implicit : DiagGroup<"implicit", [
+ ImplicitFunctionDeclare,
+ ImplicitInt
+]>;
+
+// Empty DiagGroups are recognized by clang but ignored.
+def : DiagGroup<"abi">;
+def : DiagGroup<"address">;
+def AddressOfTemporary : DiagGroup<"address-of-temporary">;
+def : DiagGroup<"aggregate-return">;
+def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
+def : DiagGroup<"attributes">;
+def : DiagGroup<"bad-function-cast">;
+def BoolConversions : DiagGroup<"bool-conversions">;
+def CXXCompat: DiagGroup<"c++-compat">;
+def CastAlign : DiagGroup<"cast-align">;
+def : DiagGroup<"cast-qual">;
+def : DiagGroup<"char-align">;
+def Comment : DiagGroup<"comment">;
+def : DiagGroup<"ctor-dtor-privacy">;
+def : DiagGroup<"declaration-after-statement">;
+def GNUDesignator : DiagGroup<"gnu-designator">;
+
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings">;
+def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
+ DiagCategory<"Deprecations">;
+
+def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
+
+def : DiagGroup<"disabled-optimization">;
+def : DiagGroup<"discard-qual">;
+def : DiagGroup<"div-by-zero">;
+def EmptyBody : DiagGroup<"empty-body">;
+def ExtraTokens : DiagGroup<"extra-tokens">;
+
+def FormatExtraArgs : DiagGroup<"format-extra-args">;
+def FormatZeroLength : DiagGroup<"format-zero-length">;
+
+def CXXHexFloats : DiagGroup<"c++-hex-floats">;
+
+def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
+def : DiagGroup<"effc++">;
+def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def GlobalConstructors : DiagGroup<"global-constructors">;
+def : DiagGroup<"idiomatic-parentheses">;
+def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
+def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
+def : DiagGroup<"import">;
+def : DiagGroup<"init-self">;
+def : DiagGroup<"inline">;
+def : DiagGroup<"int-to-pointer-cast">;
+def : DiagGroup<"invalid-pch">;
+def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
+def : DiagGroup<"main">;
+def MissingBraces : DiagGroup<"missing-braces">;
+def MissingDeclarations: DiagGroup<"missing-declarations">;
+def : DiagGroup<"missing-format-attribute">;
+def : DiagGroup<"missing-include-dirs">;
+def : DiagGroup<"missing-noreturn">;
+def MultiChar : DiagGroup<"multichar">;
+def : DiagGroup<"nested-externs">;
+def : DiagGroup<"newline-eof">;
+def LongLong : DiagGroup<"long-long">;
+def MismatchedTags : DiagGroup<"mismatched-tags">;
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def NullDereference : DiagGroup<"null-dereference">;
+def InitializerOverrides : DiagGroup<"initializer-overrides">;
+def NonNull : DiagGroup<"nonnull">;
+def : DiagGroup<"nonportable-cfstrings">;
+def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
+def : DiagGroup<"old-style-cast">;
+def : DiagGroup<"old-style-definition">;
+def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
+def : DiagGroup<"overflow">;
+def OverlengthStrings : DiagGroup<"overlength-strings">;
+def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def Packed : DiagGroup<"packed">;
+def Padded : DiagGroup<"padded">;
+def PointerArith : DiagGroup<"pointer-arith">;
+def PoundWarning : DiagGroup<"#warnings">,
+ DiagCategory<"#warning Directive">;
+def : DiagGroup<"pointer-to-int-cast">;
+def : DiagGroup<"redundant-decls">;
+def ReturnType : DiagGroup<"return-type">;
+def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">;
+def SelfAssignment : DiagGroup<"self-assign">;
+def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
+def : DiagGroup<"sequence-point">;
+def Shadow : DiagGroup<"shadow">;
+def : DiagGroup<"shorten-64-to-32">;
+def : DiagGroup<"sign-promo">;
+def SignCompare : DiagGroup<"sign-compare">;
+def : DiagGroup<"stack-protector">;
+def : DiagGroup<"switch-default">;
+def : DiagGroup<"synth">;
+def TautologicalCompare : DiagGroup<"tautological-compare">;
+
+// Preprocessor warnings.
+def : DiagGroup<"builtin-macro-redefined">;
+
+// Just silence warnings about -Wstrict-aliasing for now.
+def : DiagGroup<"strict-aliasing=0">;
+def : DiagGroup<"strict-aliasing=1">;
+def : DiagGroup<"strict-aliasing=2">;
+def : DiagGroup<"strict-aliasing">;
+
+// Just silence warnings about -Wstrict-overflow for now.
+def : DiagGroup<"strict-overflow=0">;
+def : DiagGroup<"strict-overflow=1">;
+def : DiagGroup<"strict-overflow=2">;
+def : DiagGroup<"strict-overflow=3">;
+def : DiagGroup<"strict-overflow=4">;
+def : DiagGroup<"strict-overflow=5">;
+def : DiagGroup<"strict-overflow">;
+
+def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
+def : DiagGroup<"strict-prototypes">;
+def StrictSelector : DiagGroup<"strict-selector-match">;
+def SwitchEnum : DiagGroup<"switch-enum">;
+def Switch : DiagGroup<"switch", [SwitchEnum]>;
+def Trigraphs : DiagGroup<"trigraphs">;
+
+def : DiagGroup<"type-limits">;
+def Uninitialized : DiagGroup<"uninitialized">;
+def UnknownPragmas : DiagGroup<"unknown-pragmas">;
+def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
+def UnusedArgument : DiagGroup<"unused-argument">;
+def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
+def UnusedFunction : DiagGroup<"unused-function">;
+def UnusedMemberFunction : DiagGroup<"unused-member-function">;
+def UnusedLabel : DiagGroup<"unused-label">;
+def UnusedParameter : DiagGroup<"unused-parameter">;
+def UnusedValue : DiagGroup<"unused-value">;
+def UnusedVariable : DiagGroup<"unused-variable">;
+def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
+def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
+def Reorder : DiagGroup<"reorder">;
+def UndeclaredSelector : DiagGroup<"undeclared-selector">;
+def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
+def CustomAtomic : DiagGroup<"custom-atomic-properties">;
+def AtomicProperties : DiagGroup<"atomic-properties",
+ [ImplicitAtomic, CustomAtomic]>;
+def Selector : DiagGroup<"selector">;
+def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
+def Protocol : DiagGroup<"protocol">;
+def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
+def : DiagGroup<"variadic-macros">;
+def VariadicMacros : DiagGroup<"variadic-macros">;
+def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
+def VLA : DiagGroup<"vla">;
+def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
+def : DiagGroup<"write-strings">;
+def CharSubscript : DiagGroup<"char-subscripts">;
+def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
+
+// Aggregation warning settings.
+
+// -Widiomatic-parentheses contains warnings about 'idiomatic'
+// missing parentheses; it is off by default.
+def Parentheses : DiagGroup<"parentheses",
+ [LogicalOpParentheses,
+ DiagGroup<"idiomatic-parentheses">]>;
+
+// -Wconversion has its own warnings, but we split a few out for
+// legacy reasons:
+// - some people want just 64-to-32 warnings
+// - conversion warnings with constant sources are on by default
+// - conversion warnings for literals are on by default
+// - bool-to-pointer conversion warnings are on by default
+def Conversion : DiagGroup<"conversion",
+ [DiagGroup<"shorten-64-to-32">,
+ DiagGroup<"constant-conversion">,
+ DiagGroup<"literal-conversion">,
+ BoolConversions]>,
+ DiagCategory<"Value Conversion Issue">;
+
+def Unused : DiagGroup<"unused",
+ [UnusedArgument, UnusedFunction, UnusedLabel,
+ // UnusedParameter, (matches GCC's behavior)
+ // UnusedMemberFunction, (clean-up llvm before enabling)
+ UnusedValue, UnusedVariable]>,
+ DiagCategory<"Unused Entity Issue">;
+
+// Format settings.
+def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>,
+ DiagCategory<"Format String Issue">;
+def FormatSecurity : DiagGroup<"format-security", [Format]>;
+def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
+def FormatY2K : DiagGroup<"format-y2k", [Format]>;
+def Format2 : DiagGroup<"format=2",
+ [FormatNonLiteral, FormatSecurity, FormatY2K]>;
+
+def Extra : DiagGroup<"extra", [
+ MissingFieldInitializers,
+ IgnoredQualifiers,
+ InitializerOverrides,
+ SemiBeforeMethodBody,
+ SignCompare,
+ UnusedParameter
+ ]>;
+
+def Most : DiagGroup<"most", [
+ CharSubscript,
+ Comment,
+ Format,
+ Implicit,
+ MismatchedTags,
+ MissingBraces,
+ MultiChar,
+ Reorder,
+ ReturnType,
+ SelfAssignment,
+ Switch,
+ Trigraphs,
+ Uninitialized,
+ UnknownPragmas,
+ Unused,
+ VectorConversions,
+ VolatileRegisterVar,
+ OverloadedVirtual
+ ]>;
+
+// -Wall is -Wmost -Wparentheses
+def : DiagGroup<"all", [Most, Parentheses]>;
+
+// Aliases.
+def : DiagGroup<"", [Extra]>; // -W = -Wextra
+def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens
+def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
+
+// A warning group for warnings that we want to have on by default in clang,
+// but which aren't on by default in GCC.
+def NonGCC : DiagGroup<"non-gcc",
+ [SignCompare, Conversion, LiteralRange]>;
+
+// A warning group for warnings about using C++0x features as extensions in
+// earlier C++ versions.
+def CXX0x : DiagGroup<"c++0x-extensions">;
+
+// A warning group for warnings about GCC extensions.
+def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>;
+
+// A warning group for warnings about Microsoft extensions.
+def Microsoft : DiagGroup<"microsoft">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
new file mode 100644
index 0000000..b463805
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -0,0 +1,212 @@
+//===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- 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 Diagnostic IDs-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
+#define LLVM_CLANG_DIAGNOSTICIDS_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class Diagnostic;
+ class SourceLocation;
+
+ // Import the diagnostic enums themselves.
+ namespace diag {
+ // Start position for diagnostics.
+ enum {
+ DIAG_START_DRIVER = 300,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
+ DIAG_START_LEX = DIAG_START_FRONTEND + 120,
+ DIAG_START_PARSE = DIAG_START_LEX + 300,
+ DIAG_START_AST = DIAG_START_PARSE + 300,
+ DIAG_START_SEMA = DIAG_START_AST + 100,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
+ DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
+ };
+
+ class CustomDiagInfo;
+
+ /// diag::kind - All of the diagnostics that can be emitted by the frontend.
+ typedef unsigned kind;
+
+ // Get typedefs for common diagnostics.
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+ NUM_BUILTIN_COMMON_DIAGNOSTICS
+#undef DIAG
+ };
+
+ /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
+ /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
+ /// (emit as an error). It allows clients to map errors to
+ /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
+ /// one).
+ enum Mapping {
+ // NOTE: 0 means "uncomputed".
+ MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
+ MAP_WARNING = 2, //< Map this diagnostic to a warning.
+ MAP_ERROR = 3, //< Map this diagnostic to an error.
+ MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
+
+ /// Map this diagnostic to "warning", but make it immune to -Werror. This
+ /// happens when you specify -Wno-error=foo.
+ MAP_WARNING_NO_WERROR = 5,
+ /// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
+ /// This happens for -Wno-fatal-errors=foo.
+ MAP_ERROR_NO_WFATAL = 6
+ };
+ }
+
+/// \brief Used for handling and querying diagnostic IDs. Can be used and shared
+/// by multiple Diagnostics for multiple translation units.
+class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
+public:
+ /// Level - The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored, Note, Warning, Error, Fatal
+ };
+
+private:
+ /// CustomDiagInfo - Information for uniquing and looking up custom diags.
+ diag::CustomDiagInfo *CustomDiagInfo;
+
+public:
+ DiagnosticIDs();
+ ~DiagnosticIDs();
+
+ /// getCustomDiagID - Return an ID for a diagnostic with the specified message
+ /// and level. If this is the first request for this diagnosic, it is
+ /// registered and created, otherwise the existing ID is returned.
+ unsigned getCustomDiagID(Level L, llvm::StringRef Message);
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic classification and reporting interfaces.
+ //
+
+ /// getDescription - Given a diagnostic ID, return a description of the
+ /// issue.
+ const char *getDescription(unsigned DiagID) const;
+
+ /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
+ /// level of the specified diagnostic ID is a Warning or Extension.
+ /// This only works on builtin diagnostics, not custom ones, and is not legal to
+ /// call on NOTEs.
+ static bool isBuiltinWarningOrExtension(unsigned DiagID);
+
+ /// \brief Determine whether the given built-in diagnostic ID is a
+ /// Note.
+ static bool isBuiltinNote(unsigned DiagID);
+
+ /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+ /// ID is for an extension of some sort.
+ ///
+ static bool isBuiltinExtensionDiag(unsigned DiagID) {
+ bool ignored;
+ return isBuiltinExtensionDiag(DiagID, ignored);
+ }
+
+ /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+ /// ID is for an extension of some sort. This also returns EnabledByDefault,
+ /// which is set to indicate whether the diagnostic is ignored by default (in
+ /// which case -pedantic enables it) or treated as a warning/error by default.
+ ///
+ static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
+
+
+ /// getWarningOptionForDiag - Return the lowest-level warning option that
+ /// enables the specified diagnostic. If there is no -Wfoo flag that controls
+ /// the diagnostic, this returns null.
+ static const char *getWarningOptionForDiag(unsigned DiagID);
+
+ /// getWarningOptionForDiag - Return the category number that a specified
+ /// DiagID belongs to, or 0 if no category.
+ static unsigned getCategoryNumberForDiag(unsigned DiagID);
+
+ /// getCategoryNameFromID - Given a category ID, return the name of the
+ /// category.
+ static const char *getCategoryNameFromID(unsigned CategoryID);
+
+ /// \brief Enumeration describing how the the emission of a diagnostic should
+ /// be treated when it occurs during C++ template argument deduction.
+ enum SFINAEResponse {
+ /// \brief The diagnostic should not be reported, but it should cause
+ /// template argument deduction to fail.
+ ///
+ /// The vast majority of errors that occur during template argument
+ /// deduction fall into this category.
+ SFINAE_SubstitutionFailure,
+
+ /// \brief The diagnostic should be suppressed entirely.
+ ///
+ /// Warnings generally fall into this category.
+ SFINAE_Suppress,
+
+ /// \brief The diagnostic should be reported.
+ ///
+ /// The diagnostic should be reported. Various fatal errors (e.g.,
+ /// template instantiation depth exceeded) fall into this category.
+ SFINAE_Report,
+
+ /// \brief The diagnostic is an access-control diagnostic, which will be
+ /// substitution failures in some contexts and reported in others.
+ SFINAE_AccessControl
+ };
+
+ /// \brief Determines whether the given built-in diagnostic ID is
+ /// for an error that is suppressed if it occurs during C++ template
+ /// argument deduction.
+ ///
+ /// When an error is suppressed due to SFINAE, the template argument
+ /// deduction fails but no diagnostic is emitted. Certain classes of
+ /// errors, such as those errors that involve C++ access control,
+ /// are not SFINAE errors.
+ static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
+
+private:
+ /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+ /// "unknown-pragmas" to have the specified mapping. This returns true and
+ /// ignores the request if "Group" was unknown, false otherwise.
+ bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
+ SourceLocation Loc, Diagnostic &Diag) const;
+
+ /// \brief Based on the way the client configured the Diagnostic
+ /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticClient.
+ ///
+ /// \param Loc The source location we are interested in finding out the
+ /// diagnostic state. Can be null in order to query the latest state.
+ DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ const Diagnostic &Diag) const;
+
+ /// getDiagnosticLevel - This is an internal implementation helper used when
+ /// DiagClass is already known.
+ DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
+ unsigned DiagClass,
+ SourceLocation Loc,
+ const Diagnostic &Diag) const;
+
+ /// ProcessDiag - This is the method used to report a diagnostic that is
+ /// finally fully formed.
+ ///
+ /// \returns true if the diagnostic was emitted, false if it was
+ /// suppressed.
+ bool ProcessDiag(Diagnostic &Diag) const;
+
+ friend class Diagnostic;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
new file mode 100644
index 0000000..6d1d9b6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -0,0 +1,317 @@
+//==--- DiagnosticLexKinds.td - liblex diagnostics ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Lexer Diagnostics
+//===----------------------------------------------------------------------===//
+
+let Component = "Lex", CategoryName = "Lexical or Preprocessor Issue" in {
+
+def null_in_string : Warning<"null character(s) preserved in string literal">;
+def null_in_char : Warning<"null character(s) preserved in character literal">;
+def null_in_file : Warning<"null character ignored">;
+def warn_nested_block_comment : Warning<"'/*' within block comment">,
+ InGroup<Comment>;
+def escaped_newline_block_comment_end : Warning<
+ "escaped newline between */ characters at block comment end">,
+ InGroup<Comment>;
+def backslash_newline_space : Warning<
+ "backslash and newline separated by space">;
+
+// Trigraphs.
+def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>;
+def trigraph_ignored_block_comment : Warning<
+ "ignored trigraph would end block comment">, InGroup<Trigraphs>;
+def trigraph_ends_block_comment : Warning<"trigraph ends block comment">,
+ InGroup<Trigraphs>;
+def trigraph_converted : Warning<"trigraph converted to '%0' character">,
+ InGroup<Trigraphs>;
+
+def ext_multi_line_bcpl_comment : Extension<"multi-line // comment">,
+ InGroup<Comment>;
+def ext_bcpl_comment : Extension<
+ "// comments are not allowed in this language">,
+ InGroup<Comment>;
+def ext_no_newline_eof : Extension<"no newline at end of file">;
+def ext_backslash_newline_eof : Extension<"backslash-newline at end of file">;
+def ext_dollar_in_identifier : Extension<"'$' in identifier">;
+def charize_microsoft_ext : Extension<"@# is a microsoft extension">;
+
+def ext_token_used : Extension<"extension used">;
+
+def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">;
+def warn_unterminated_char : ExtWarn<"missing terminating ' character">;
+def err_empty_character : Error<"empty character constant">;
+def err_unterminated_block_comment : Error<"unterminated /* comment">;
+def err_invalid_character_to_charify : Error<
+ "invalid argument to convert to character">;
+def err_unterminated___pragma : Error<"missing terminating ')' character">;
+
+def err_conflict_marker : Error<"version control conflict marker in file">;
+
+def ext_multichar_character_literal : ExtWarn<
+ "multi-character character constant">, InGroup<MultiChar>;
+def ext_four_char_character_literal : Extension<
+ "multi-character character constant">, InGroup<FourByteMultiChar>;
+
+
+// Literal
+def ext_nonstandard_escape : Extension<
+ "use of non-standard escape character '\\%0'">;
+def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">;
+def err_hex_escape_no_digits : Error<"\\x used with no following hex digits">;
+def err_ucn_escape_no_digits : Error<"\\u used with no following hex digits">;
+def err_ucn_escape_invalid : Error<"invalid universal character">;
+def err_ucn_escape_incomplete : Error<"incomplete universal character name">;
+def err_ucn_escape_too_big : Error<"universal character name is too long">;
+def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">;
+def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">;
+def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">;
+def err_invalid_suffix_integer_constant : Error<
+ "invalid suffix '%0' on integer constant">;
+def err_invalid_suffix_float_constant : Error<
+ "invalid suffix '%0' on floating constant">;
+def warn_extraneous_wide_char_constant : Warning<
+ "extraneous characters in wide character constant ignored">;
+def warn_char_constant_too_large : Warning<
+ "character constant too long for its type">;
+def err_exponent_has_no_digits : Error<"exponent has no digits">;
+def ext_imaginary_constant : Extension<"imaginary constants are an extension">;
+def err_hexconstant_requires_exponent : Error<
+ "hexadecimal floating constants require an exponent">;
+def ext_hexconstant_cplusplus : Extension<
+ "hexadecimal floating constants are a C99 feature that is incompatible with "
+ "C++0x">, InGroup<CXXHexFloats>;
+def ext_hexconstant_invalid : Extension<
+ "hexadecimal floating constants are a C99 feature">;
+def ext_binary_literal : Extension<
+ "binary integer literals are an extension">;
+def err_pascal_string_too_long : Error<"Pascal string is too long">;
+def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
+def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
+def ext_string_too_long : Extension<"string literal of length %0 exceeds "
+ "maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
+ "support">, InGroup<OverlengthStrings>;
+def warn_ucn_escape_too_large : ExtWarn<
+ "character unicode escape sequence too long for its type">;
+def warn_ucn_not_valid_in_c89 : ExtWarn<
+ "unicode escape sequences are only valid in C99 or C++">;
+
+//===----------------------------------------------------------------------===//
+// PTH Diagnostics
+//===----------------------------------------------------------------------===//
+def err_pth_cannot_read : Error<
+ "PTH file '%0' could not be read">;
+def err_invalid_pth_file : Error<
+ "invalid or corrupt PTH file '%0'">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Diagnostics
+//===----------------------------------------------------------------------===//
+def pp_hash_warning : Warning<"#warning%0">, InGroup<PoundWarning>;
+def pp_include_next_in_primary : Warning<
+ "#include_next in primary source file">;
+def pp_include_macros_out_of_predefines : Error<
+ "the #__include_macros directive is only for internal use by -imacros">;
+def pp_include_next_absolute_path : Warning<"#include_next with absolute path">;
+def ext_c99_whitespace_required_after_macro_name : ExtWarn<
+ "ISO C99 requires whitespace after the macro name">;
+def ext_missing_whitespace_after_macro_name : ExtWarn<
+ "whitespace required after macro name">;
+def warn_missing_whitespace_after_macro_name : Warning<
+ "whitespace recommended after macro name">;
+
+def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">;
+def pp_pragma_sysheader_in_main_file : Warning<
+ "#pragma system_header ignored in main file">;
+def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
+def pp_out_of_date_dependency : Warning<
+ "current file is older than dependency %0">;
+def pp_undef_builtin_macro : Warning<"undefining builtin macro">;
+def pp_redef_builtin_macro : Warning<"redefining builtin macro">,
+ InGroup<DiagGroup<"builtin-macro-redefined">>;
+def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore,
+ InGroup<DiagGroup<"unused-macros">>;
+def warn_pp_undef_identifier : Warning<
+ "%0 is not defined, evaluates to 0">,
+ InGroup<DiagGroup<"undef">>, DefaultIgnore;
+
+def pp_invalid_string_literal : Warning<
+ "invalid string literal, ignoring final '\\'">;
+def warn_pp_expr_overflow : Warning<
+ "integer overflow in preprocessor expression">;
+def warn_pp_convert_lhs_to_positive : Warning<
+ "left side of operator converted from negative value to unsigned: %0">;
+def warn_pp_convert_rhs_to_positive : Warning<
+ "right side of operator converted from negative value to unsigned: %0">;
+
+def ext_pp_import_directive : Extension<"#import is a language extension">;
+def ext_pp_ident_directive : Extension<"#ident is a language extension">;
+def ext_pp_include_next_directive : Extension<
+ "#include_next is a language extension">;
+def ext_pp_warning_directive : Extension<"#warning is a language extension">;
+
+def ext_pp_extra_tokens_at_eol : ExtWarn<
+ "extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
+
+def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
+def ext_pp_bad_vaargs_use : Extension<
+ "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
+def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
+def ext_variadic_macro : Extension<"variadic macros were introduced in C99">,
+ InGroup<VariadicMacros>;
+def ext_named_variadic_macro : Extension<
+ "named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
+def ext_embedded_directive : Extension<
+ "embedding a directive within macro arguments is not portable">;
+def ext_missing_varargs_arg : Extension<
+ "varargs argument missing, but tolerated as an extension">;
+def ext_empty_fnmacro_arg : Extension<
+ "empty macro arguments were standardized in C99">;
+
+def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
+def err_pp_hash_error : Error<"#error%0">;
+def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
+def err_pp_error_opening_file : Error<
+ "error opening file '%0': %1">, DefaultFatal;
+def err_pp_empty_filename : Error<"empty filename">;
+def err_pp_include_too_deep : Error<"#include nested too deeply">;
+def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;
+def err_pp_macro_not_identifier : Error<"macro names must be identifiers">;
+def err_pp_missing_macro_name : Error<"macro name missing">;
+def err_pp_missing_rparen_in_macro_def : Error<
+ "missing ')' in macro parameter list">;
+def err_pp_invalid_tok_in_arg_list : Error<
+ "invalid token in macro parameter list">;
+def err_pp_expected_ident_in_arg_list : Error<
+ "expected identifier in macro parameter list">;
+def err_pp_expected_comma_in_arg_list : Error<
+ "expected comma in macro parameter list">;
+def err_pp_duplicate_name_in_arg_list : Error<
+ "duplicate macro parameter name %0">;
+def err_pp_stringize_not_parameter : Error<
+ "'#' is not followed by a macro parameter">;
+def err_pp_malformed_ident : Error<"invalid #ident directive">;
+def err_pp_unterminated_conditional : Error<
+ "unterminated conditional directive">;
+def pp_err_else_after_else : Error<"#else after #else">;
+def pp_err_elif_after_else : Error<"#elif after #else">;
+def pp_err_else_without_if : Error<"#else without #if">;
+def pp_err_elif_without_if : Error<"#elif without #if">;
+def err_pp_endif_without_if : Error<"#endif without #if">;
+def err_pp_expected_value_in_expr : Error<"expected value in expression">;
+def err_pp_missing_val_before_operator : Error<"missing value before operator">;
+def err_pp_expected_rparen : Error<"expected ')' in preprocessor expression">;
+def err_pp_expected_eol : Error<
+ "expected end of line in preprocessor expression">;
+def err_pp_defined_requires_identifier : Error<
+ "operator 'defined' requires an identifier">;
+def err_pp_missing_lparen : Error<"missing '(' after '%0'">;
+def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
+def err_pp_colon_without_question : Error<"':' without preceding '?'">;
+def err_pp_division_by_zero : Error<
+ "division by zero in preprocessor expression">;
+def err_pp_remainder_by_zero : Error<
+ "remainder by zero in preprocessor expression">;
+def err_pp_expr_bad_token_binop : Error<
+ "token is not a valid binary operator in a preprocessor subexpression">;
+def err_pp_expr_bad_token_start_expr : Error<
+ "invalid token at start of a preprocessor expression">;
+def err_pp_invalid_poison : Error<"can only poison identifier tokens">;
+def err_pp_used_poisoned_id : Error<"attempt to use a poisoned identifier">;
+
+def err_feature_check_malformed : Error<
+ "builtin feature check macro requires a parenthesized identifier">;
+
+def err__Pragma_malformed : Error<
+ "_Pragma takes a parenthesized string literal">;
+def err_pragma_comment_malformed : Error<
+ "pragma comment requires parenthesized identifier and optional string">;
+def err_pragma_message_malformed : Error<
+ "pragma message requires parenthesized string">;
+def err_pragma_push_pop_macro_malformed : Error<
+ "pragma %0 requires a parenthesized string">;
+def warn_pragma_pop_macro_no_push : Warning<
+ "pragma pop_macro could not pop '%0', no matching push_macro">;
+def warn_pragma_message : Warning<"%0">;
+def warn_pragma_ignored : Warning<"unknown pragma ignored">,
+ InGroup<UnknownPragmas>, DefaultIgnore;
+def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
+ InGroup<UnknownPragmas>;
+def ext_on_off_switch_syntax :
+ ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">,
+ InGroup<UnknownPragmas>;
+def ext_pragma_syntax_eom :
+ ExtWarn<"expected end of macro in pragma">,
+ InGroup<UnknownPragmas>;
+def warn_stdc_fenv_access_not_supported :
+ Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid :
+ ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
+ " 'push', or 'pop'">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_cannot_pop :
+ ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid_option :
+ ExtWarn<"pragma diagnostic expected option name (e.g. \"-Wundef\")">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid_token :
+ ExtWarn<"unexpected token in pragma diagnostic">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_unknown_warning :
+ ExtWarn<"unknown warning group '%0', ignored">,
+ InGroup<UnknownPragmas>;
+// - #pragma __debug
+def warn_pragma_debug_unexpected_command : Warning<
+ "unexpected debug command '%0'">;
+
+def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
+def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
+def err_paste_at_start : Error<
+ "'##' cannot appear at start of macro expansion">;
+def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
+def ext_paste_comma : Extension<
+ "Use of comma pasting extension is non-portable">;
+def err_unterm_macro_invoc : Error<
+ "unterminated function-like macro invocation">;
+def err_too_many_args_in_macro_invoc : Error<
+ "too many arguments provided to function-like macro invocation">;
+def err_too_few_args_in_macro_invoc : Error<
+ "too few arguments provided to function-like macro invocation">;
+def err_pp_bad_paste : Error<
+ "pasting formed '%0', an invalid preprocessing token">;
+def err_pp_bad_paste_ms : Warning<
+ "pasting formed '%0', an invalid preprocessing token">, DefaultError,
+ InGroup<DiagGroup<"invalid-token-paste">>;
+def err_pp_operator_used_as_macro_name : Error<
+ "C++ operator '%0' cannot be used as a macro name">;
+def err_pp_illegal_floating_literal : Error<
+ "floating point literal in preprocessor expression">;
+def err_pp_line_requires_integer : Error<
+ "#line directive requires a positive integer argument">;
+def err_pp_line_invalid_filename : Error<
+ "invalid filename for #line directive">;
+def warn_pp_line_decimal : Warning<
+ "#line directive interprets number as decimal, not octal">;
+def err_pp_line_digit_sequence : Error<
+ "#line directive requires a simple digit sequence">;
+def err_pp_linemarker_requires_integer : Error<
+ "line marker directive requires a positive integer argument">;
+def err_pp_linemarker_invalid_filename : Error<
+ "invalid filename for line marker directive">;
+def err_pp_linemarker_invalid_flag : Error<
+ "invalid flag line marker directive">;
+def err_pp_linemarker_invalid_pop : Error<
+ "invalid line marker flag '2': cannot pop empty include stack">;
+def ext_pp_line_too_big : Extension<
+ "C requires #line number to be less than %0, allowed as extension">;
+
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
new file mode 100644
index 0000000..9d7ec9d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -0,0 +1,463 @@
+//==--- DiagnosticParseKinds.td - libparse diagnostics --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Parser Diagnostics
+//===----------------------------------------------------------------------===//
+
+let Component = "Parse" in {
+
+def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">,
+ CatInlineAsm;
+def warn_file_asm_volatile : Warning<
+ "meaningless 'volatile' on asm outside function">, CatInlineAsm;
+
+let CategoryName = "Parse Issue" in {
+
+def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
+def ext_top_level_semi : Extension<
+ "extra ';' outside of a function">;
+def ext_extra_struct_semi : Extension<
+ "extra ';' inside a %0">;
+def ext_extra_ivar_semi : Extension<
+ "extra ';' inside instance variable list">;
+
+def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
+def ext_plain_complex : ExtWarn<
+ "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
+def ext_integer_complex : Extension<
+ "complex integer types are an extension">;
+def ext_thread_before : Extension<"'__thread' before 'static'">;
+
+def ext_empty_struct_union : Extension<"empty %select{struct|union}0 "
+ "(accepted as an extension) has size 0 in C, size 1 in C++">,
+ InGroup<CXXCompat>;
+def error_empty_enum : Error<"use of empty enum">;
+def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
+def err_invalid_short_spec : Error<"'short %0' is invalid">;
+def err_invalid_long_spec : Error<"'long %0' is invalid">;
+def err_invalid_longlong_spec : Error<"'long long %0' is invalid">;
+def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
+def err_friend_storage_spec : Error<"'%0' is invalid in friend declarations">;
+
+def ext_ident_list_in_param : Extension<
+ "type-less parameter names in function declaration">;
+def ext_c99_variable_decl_in_for_loop : Extension<
+ "variable declaration in for loop is a C99-specific feature">;
+def ext_c99_compound_literal : Extension<
+ "compound literals are a C99-specific feature">;
+def ext_enumerator_list_comma : Extension<
+ "commas at the end of enumerator lists are a %select{C99|C++0x}0-specific "
+ "feature">;
+def err_enumerator_list_missing_comma : Error<
+ "missing ',' between enumerators">;
+
+def ext_gnu_indirect_goto : Extension<
+ "use of GNU indirect-goto extension">, InGroup<GNU>;
+def ext_gnu_address_of_label : Extension<
+ "use of GNU address-of-label extension">, InGroup<GNU>;
+def ext_gnu_local_label : Extension<
+ "use of GNU locally declared label extension">, InGroup<GNU>;
+def ext_gnu_statement_expr : Extension<
+ "use of GNU statement expression extension">, InGroup<GNU>;
+def ext_gnu_conditional_expr : Extension<
+ "use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>;
+def ext_gnu_empty_initializer : Extension<
+ "use of GNU empty initializer extension">, InGroup<GNU>;
+def ext_gnu_array_range : Extension<"use of GNU array range extension">,
+ InGroup<GNUDesignator>;
+def ext_gnu_missing_equal_designator : ExtWarn<
+ "use of GNU 'missing =' extension in designator">,
+ InGroup<GNUDesignator>;
+def err_expected_equal_designator : Error<"expected '=' or another designator">;
+def ext_gnu_old_style_field_designator : ExtWarn<
+ "use of GNU old-style field designator extension">,
+ InGroup<GNUDesignator>;
+def ext_gnu_case_range : Extension<"use of GNU case range extension">,
+ InGroup<GNU>;
+
+// Generic errors.
+def err_parse_error : Error<"parse error">;
+def err_expected_expression : Error<"expected expression">;
+def err_expected_type : Error<"expected a type">;
+def err_expected_external_declaration : Error<"expected external declaration">;
+def err_expected_ident : Error<"expected identifier">;
+def err_expected_ident_lparen : Error<"expected identifier or '('">;
+def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
+def err_expected_lbrace : Error<"expected '{'">;
+def err_expected_lparen : Error<"expected '('">;
+def err_expected_rparen : Error<"expected ')'">;
+def err_expected_lsquare : Error<"expected '['">;
+def err_expected_rsquare : Error<"expected ']'">;
+def err_expected_rbrace : Error<"expected '}'">;
+def err_expected_greater : Error<"expected '>'">;
+def err_expected_ggg : Error<"expected '>>>'">;
+def err_expected_semi_declaration : Error<
+ "expected ';' at end of declaration">;
+def err_expected_semi_decl_list : Error<
+ "expected ';' at end of declaration list">;
+def ext_expected_semi_decl_list : Extension<
+ "expected ';' at end of declaration list">;
+def err_expected_member_name_or_semi : Error<
+ "expected member name or ';' after declaration specifiers">;
+def err_function_declared_typedef : Error<
+ "function definition declared 'typedef'">;
+def err_iboutletcollection_builtintype : Error<
+ "type argument of iboutletcollection attribute cannot be a builtin type">;
+def err_expected_fn_body : Error<
+ "expected function body after function declarator">;
+def err_expected_method_body : Error<"expected method body">;
+def err_invalid_token_after_toplevel_declarator : Error<
+ "expected ';' after top level declarator">;
+def err_invalid_equalequal_after_declarator : Error<
+ "invalid '==' at end of declaration; did you mean '='?">;
+def err_expected_statement : Error<"expected statement">;
+def err_expected_lparen_after : Error<"expected '(' after '%0'">;
+def err_expected_lparen_after_id : Error<"expected '(' after %0">;
+def err_expected_less_after : Error<"expected '<' after '%0'">;
+def err_expected_comma : Error<"expected ','">;
+def err_expected_lbrace_in_compound_literal : Error<
+ "expected '{' in compound literal">;
+def err_expected_while : Error<"expected 'while' in do/while loop">;
+
+def err_expected_semi_after : Error<"expected ';' after %0">;
+def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
+def err_expected_semi_after_expr : Error<"expected ';' after expression">;
+def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
+
+def err_expected_semi_after_method_proto : Error<
+ "expected ';' after method prototype">;
+def err_expected_semi_after_namespace_name : Error<
+ "expected ';' after namespace name">;
+def err_unexpected_namespace_attributes_alias : Error<
+ "attributes can not be specified on namespace alias">;
+def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
+def err_namespace_nonnamespace_scope : Error<
+ "namespaces can only be defined in global or namespace scope">;
+def err_expected_semi_after_attribute_list : Error<
+ "expected ';' after attribute list">;
+def err_expected_semi_after_static_assert : Error<
+ "expected ';' after static_assert">;
+def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
+def err_expected_colon_after : Error<"expected ':' after %0">;
+def err_label_end_of_compound_statement : Error<
+ "label at end of compound statement: expected statement">;
+def err_address_of_label_outside_fn : Error<
+ "use of address-of-label extension outside of a function body">;
+def err_expected_string_literal : Error<"expected string literal">;
+def err_expected_asm_operand : Error<
+ "expected string literal or '[' for asm operand">, CatInlineAsm;
+def err_expected_selector_for_method : Error<
+ "expected selector for Objective-C method">;
+def err_expected_property_name : Error<"expected property name">;
+
+def err_unexpected_at : Error<"unexpected '@' in program">;
+
+def err_invalid_reference_qualifier_application : Error<
+ "'%0' qualifier may not be applied to a reference">;
+def err_illegal_decl_reference_to_reference : Error<
+ "%0 declared as a reference to a reference">;
+def ext_rvalue_reference : ExtWarn<
+ "rvalue references are a C++0x extension">, InGroup<CXX0x>;
+def ext_ref_qualifier : ExtWarn<
+ "reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
+def ext_inline_namespace : ExtWarn<
+ "inline namespaces are a C++0x feature">, InGroup<CXX0x>;
+def err_argument_required_after_attribute : Error<
+ "argument required after attribute">;
+def err_missing_param : Error<"expected parameter declarator">;
+def err_missing_comma_before_ellipsis : Error<
+ "C requires a comma prior to the ellipsis in a variadic function type">;
+def err_unexpected_typedef_ident : Error<
+ "unexpected type name %0: expected identifier">;
+def err_expected_class_name : Error<"expected class name">;
+def err_unspecified_vla_size_with_static : Error<
+ "'static' may not be used with an unspecified variable length array size">;
+
+// Declarations.
+def err_typename_requires_specqual : Error<
+ "type name requires a specifier or qualifier">;
+def err_typename_invalid_storageclass : Error<
+ "type name does not allow storage class to be specified">;
+def err_typename_invalid_functionspec : Error<
+ "type name does not allow function specifier to be specified">;
+def err_invalid_decl_spec_combination : Error<
+ "cannot combine with previous '%0' declaration specifier">;
+def err_invalid_vector_decl_spec_combination : Error<
+ "cannot combine with previous '%0' declaration specifier. "
+ "'__vector' must be first">;
+def err_invalid_pixel_decl_spec_combination : Error<
+ "'__pixel' must be preceded by '__vector'. "
+ "'%0' declaration specifier not allowed here">;
+def err_invalid_vector_decl_spec : Error<
+ "cannot use '%0' with '__vector'">;
+def err_invalid_vector_bool_decl_spec : Error<
+ "cannot use '%0' with '__vector bool'">;
+def warn_vector_long_decl_spec_combination : Warning<
+ "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
+def err_friend_invalid_in_context : Error<
+ "'friend' used outside of class">;
+def err_unknown_typename : Error<
+ "unknown type name %0">;
+def err_use_of_tag_name_without_tag : Error<
+ "must use '%1' tag to refer to type %0%select{| in this scope}2">;
+def err_templated_using_directive : Error<
+ "cannot template a using directive">;
+def err_templated_using_declaration : Error<
+ "cannot template a using declaration">;
+def err_expected_ident_in_using : Error<
+ "expected an identifier in using directive">;
+def err_unexected_colon_in_nested_name_spec : Error<
+ "unexpected ':' in nested name specifier">;
+def err_bool_redeclaration : Error<
+ "redeclaration of C++ built-in type 'bool'">;
+
+/// Objective-C parser diagnostics
+def err_expected_minus_or_plus : Error<
+ "method type specifier must start with '-' or '+'">;
+def err_objc_no_attributes_on_category : Error<
+ "attributes may not be specified on a category">;
+def err_objc_missing_end : Error<"missing @end">;
+def warn_objc_protocol_qualifier_missing_id : Warning<
+ "protocol qualifiers without 'id' is archaic">;
+def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">;
+def err_illegal_super_cast : Error<
+ "cannot cast 'super' (it isn't an expression)">;
+
+def err_objc_illegal_visibility_spec : Error<
+ "illegal visibility specification">;
+def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">;
+def err_objc_expected_equal_for_getter : Error<
+ "expected '=' for Objective-C getter">;
+def err_objc_expected_equal_for_setter : Error<
+ "expected '=' for Objective-C setter">;
+def err_objc_expected_selector_for_getter_setter : Error<
+ "expected selector for Objective-C %select{setter|getter}0">;
+def err_objc_property_requires_field_name : Error<
+ "property requires fields to be named">;
+def err_objc_property_bitfield : Error<"property name cannot be a bitfield">;
+def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
+def err_objc_properties_require_objc2 : Error<
+ "properties are an Objective-C 2 feature">;
+def err_objc_unexpected_attr : Error<
+ "prefix attribute must be followed by an interface or protocol">;
+def err_objc_directive_only_in_protocol : Error<
+ "directive may only be specified in protocols only">;
+def err_missing_catch_finally : Error<
+ "@try statement without a @catch and @finally clause">;
+def err_objc_concat_string : Error<"unexpected token after Objective-C string">;
+def err_missing_sel_definition : Error<"cannot find definition of 'SEL'">;
+def err_missing_id_definition : Error<"cannot find definition of 'id'">;
+def err_missing_proto_definition : Error<
+ "cannot find definition of 'Protocol'">;
+def err_missing_class_definition : Error<"cannot find definition of 'Class'">;
+def warn_expected_implementation : Warning<
+ "@end must appear in an @implementation context">;
+def error_property_ivar_decl : Error<
+ "property synthesize requires specification of an ivar">;
+def err_synthesized_property_name : Error<
+ "expected a property name in @synthesize">;
+def warn_semicolon_before_method_body : Warning<
+ "semicolon before method body is ignored">,
+ InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore;
+
+def err_expected_field_designator : Error<
+ "expected a field designator, such as '.field = 4'">;
+
+def err_declaration_does_not_declare_param : Error<
+ "declaration does not declare a parameter">;
+def err_no_matching_param : Error<"parameter named %0 is missing">;
+
+/// C++ parser diagnostics
+def err_expected_unqualified_id : Error<
+ "expected %select{identifier|unqualified-id}0">;
+def err_func_def_no_params : Error<
+ "function definition does not declare parameters">;
+def err_expected_lparen_after_type : Error<
+ "expected '(' for function-style cast or type construction">;
+def err_expected_equal_after_declarator : Error<
+ "expected '=' after declarator">;
+def warn_parens_disambiguated_as_function_decl : Warning<
+ "parentheses were disambiguated as a function declarator">;
+def err_expected_member_or_base_name : Error<
+ "expected class member or base class name">;
+def err_expected_lbrace_after_base_specifiers : Error<
+ "expected '{' after base class list">;
+def ext_ellipsis_exception_spec : Extension<
+ "exception specification of '...' is a Microsoft extension">;
+def err_expected_catch : Error<"expected catch">;
+def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
+def err_using_namespace_in_class : Error<
+ "'using namespace' is not allowed in classes">;
+def err_destructor_tilde_identifier : Error<
+ "expected a class name after '~' to name a destructor">;
+def err_destructor_template_id : Error<
+ "destructor name %0 does not refer to a template">;
+def err_default_arg_unparsed : Error<
+ "unexpected end of default argument expression">;
+
+// C++ derived classes
+def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
+
+// C++ operator overloading
+def err_operator_string_not_empty : Error<
+ "string literal after 'operator' must be '\"\"'">;
+
+// Classes.
+def err_anon_type_definition : Error<
+ "declaration of anonymous %0 must be a definition">;
+
+def err_cxx0x_attribute_forbids_arguments : Error<
+ "C++0x attribute '%0' cannot have an argument list">;
+def err_cxx0x_attribute_requires_arguments : Error<
+ "C++0x attribute '%0' must have an argument list">;
+def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+
+/// C++ Templates
+def err_expected_template : Error<"expected template">;
+def err_unknown_template_name : Error<
+ "unknown template name %0">;
+def err_expected_comma_greater : Error<
+ "expected ',' or '>' in template-parameter-list">;
+def err_expected_type_id_after : Error<"expected type-id after '%0'">;
+def err_expected_class_before : Error<"expected 'class' before '%0'">;
+def err_template_spec_syntax_non_template : Error<
+ "identifier followed by '<' indicates a class template specialization but "
+ "%0 %select{does not refer to a template|refers to a function "
+ "template|<unused>|refers to a template template parameter}1">;
+def err_id_after_template_in_nested_name_spec : Error<
+ "expected template name after 'template' keyword in nested name specifier">;
+def err_id_after_template_in_typename_spec : Error<
+ "expected template name after 'template' keyword in typename specifier">;
+def err_less_after_template_name_in_nested_name_spec : Error<
+ "expected '<' after 'template %0' in nested name specifier">;
+def err_two_right_angle_brackets_need_space : Error<
+ "a space is required between consecutive right angle brackets (use '> >')">;
+def warn_cxx0x_right_shift_in_template_arg : Warning<
+ "use of right-shift operator ('>>') in template argument will require "
+ "parentheses in C++0x">;
+def err_multiple_template_declarators : Error<
+ "%select{|a template declaration|an explicit template specialization|"
+ "an explicit template instantiation}0 can "
+ "only %select{|declare|declare|instantiate}0 a single entity">;
+def err_explicit_instantiation_with_definition : Error<
+ "explicit template instantiation cannot have a definition; if this "
+ "definition is meant to be an explicit specialization, add '<>' after the "
+ "'template' keyword">;
+def err_enum_template : Error<"enumeration cannot be a template">;
+
+def err_missing_dependent_template_keyword : Error<
+ "use 'template' keyword to treat '%0' as a dependent template name">;
+
+def warn_static_inline_explicit_inst_ignored : Warning<
+ "ignoring '%select{static|inline}0' keyword on explicit template "
+ "instantiation">;
+
+// Constructor template diagnostics.
+def err_out_of_line_constructor_template_id : Error<
+ "out-of-line constructor for %0 cannot have template arguments">;
+def err_out_of_line_template_id_names_constructor : Error<
+ "qualified reference to %0 is a constructor name rather than a "
+ "template name wherever a constructor can be declared">;
+def err_out_of_line_type_names_constructor : Error<
+ "qualified reference to %0 is a constructor name rather than a "
+ "type wherever a constructor can be declared">;
+
+def err_expected_qualified_after_typename : Error<
+ "expected a qualified name after 'typename'">;
+def err_expected_semi_after_tagdecl : Error<
+ "expected ';' after %0">;
+
+def err_typename_refers_to_non_type_template : Error<
+ "typename specifier refers to a non-template">;
+def err_expected_type_name_after_typename : Error<
+ "expected an identifier or template-id after '::'">;
+def err_explicit_spec_non_template : Error<
+ "explicit %select{specialization|instantiation}0 of non-template "
+ "%select{class|struct|union}1 %2">;
+
+def err_default_template_template_parameter_not_template : Error<
+ "default template argument for a template template parameter must be a class "
+ "template">;
+
+def err_ctor_init_missing_comma : Error<
+ "missing ',' between base or member initializers">;
+
+// C++ declarations
+def err_friend_decl_defines_class : Error<
+ "cannot define a type in a friend declaration">;
+
+def warn_deleted_function_accepted_as_extension: ExtWarn<
+ "deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
+
+// C++0x override control
+def ext_override_control_keyword : Extension<
+ "'%0' keyword accepted as a C++0x extension">, InGroup<CXX0x>;
+def ext_override_inline: Extension<
+ "'%0' keyword only allowed in declarations, allowed as an extension">;
+
+def err_duplicate_virt_specifier : Error<
+ "class member already marked '%0'">;
+def err_duplicate_class_virt_specifier : Error<
+ "class already marked '%0'">;
+
+def err_scoped_enum_missing_identifier : Error<
+ "scoped enumeration requires a name">;
+
+def err_expected_parameter_pack : Error<
+ "expected the name of a parameter pack">;
+def err_paren_sizeof_parameter_pack : Error<
+ "missing parentheses around the size of parameter pack %0">;
+def err_sizeof_parameter_pack : Error<
+ "expected parenthesized parameter pack name in 'sizeof...' expression">;
+
+// Language specific pragmas
+// - Generic warnings
+def warn_pragma_expected_lparen : Warning<
+ "missing '(' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_rparen : Warning<
+ "missing ')' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_identifier : Warning<
+ "expected identifier in '#pragma %0' - ignored">;
+def warn_pragma_extra_tokens_at_eol : Warning<
+ "extra tokens at end of '#pragma %0' - ignored">;
+// - #pragma options
+def warn_pragma_options_expected_align : Warning<
+ "expected 'align' following '#pragma options' - ignored">;
+def warn_pragma_align_expected_equal : Warning<
+ "expected '=' following '#pragma %select{align|options align}0' - ignored">;
+def warn_pragma_align_invalid_option : Warning<
+ "invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
+// - #pragma pack
+def warn_pragma_pack_invalid_action : Warning<
+ "unknown action for '#pragma pack' - ignored">;
+def warn_pragma_pack_invalid_constant : Warning<
+ "invalid constant for '#pragma pack', expected %0 - ignored">;
+def warn_pragma_pack_malformed : Warning<
+ "expected integer or identifier in '#pragma pack' - ignored">;
+// - #pragma unused
+def warn_pragma_unused_expected_var : Warning<
+ "expected '#pragma unused' argument to be a variable name">;
+def warn_pragma_unused_expected_punc : Warning<
+ "expected ')' or ',' in '#pragma unused'">;
+
+// OpenCL Section 6.8.g
+def err_not_opencl_storage_class_specifier : Error<
+ "OpenCL does not support the '%0' storage class specifier">;
+
+// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
+def warn_pragma_expected_colon : Warning<
+ "missing ':' after %0 - ignoring">;
+def warn_pragma_expected_enable_disable : Warning<
+ "expected 'enable' or 'disable' - ignoring">;
+def warn_pragma_unknown_extension : Warning<
+ "unknown OpenCL extension %0 - ignoring">;
+
+} // end of Parse Issue category.
+} // end of Parser diagnostics
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
new file mode 100644
index 0000000..2e7f274
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -0,0 +1,3758 @@
+//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Semantic Analysis
+//===----------------------------------------------------------------------===//
+
+let Component = "Sema" in {
+let CategoryName = "Semantic Issue" in {
+
+// Constant expressions
+def err_expr_not_ice : Error<
+ "expression is not an integer constant expression">;
+def ext_expr_not_ice : Extension<
+ "expression is not integer constant expression "
+ "(but is allowed as an extension)">;
+
+// Semantic analysis of constant literals.
+def ext_predef_outside_function : Warning<
+ "predefined identifier is only valid inside function">;
+def warn_float_overflow : Warning<
+ "magnitude of floating-point constant too large for type %0; maximum is %1">,
+ InGroup<LiteralRange>;
+def warn_float_underflow : Warning<
+ "magnitude of floating-point constant too small for type %0; minimum is %1">,
+ InGroup<LiteralRange>;
+
+// C99 variable-length arrays
+def ext_vla : Extension<
+ "variable length arrays are a C99 feature, accepted as an extension">,
+ InGroup<VLA>;
+def err_vla_non_pod : Error<"variable length array of non-POD element type %0">;
+def err_vla_in_sfinae : Error<
+ "variable length array cannot be formed during template argument deduction">;
+def err_array_star_in_function_definition : Error<
+ "variable length array must be bound in function definition">;
+def err_vla_decl_in_file_scope : Error<
+ "variable length array declaration not allowed at file scope">;
+def err_vla_decl_has_static_storage : Error<
+ "variable length array declaration can not have 'static' storage duration">;
+def err_vla_decl_has_extern_linkage : Error<
+ "variable length array declaration can not have 'extern' linkage">;
+
+// C99 variably modified types
+def err_variably_modified_template_arg : Error<
+ "variably modified type %0 cannot be used as a template argument">;
+def err_variably_modified_nontype_template_param : Error<
+ "non-type template parameter of variably modified type %0">;
+def err_variably_modified_new_type : Error<
+ "'new' cannot allocate object of variably modified type %0">;
+
+// C99 Designated Initializers
+def ext_designated_init : Extension<
+ "designated initializers are a C99 feature, accepted in C++ as an extension">;
+def err_array_designator_negative : Error<
+ "array designator value '%0' is negative">;
+def err_array_designator_empty_range : Error<
+ "array designator range [%0, %1] is empty">;
+def err_array_designator_non_array : Error<
+ "array designator cannot initialize non-array type %0">;
+def err_array_designator_too_large : Error<
+ "array designator index (%0) exceeds array bounds (%1)">;
+def err_field_designator_non_aggr : Error<
+ "field designator cannot initialize a "
+ "%select{non-struct, non-union|non-class}0 type %1">;
+def err_field_designator_unknown : Error<
+ "field designator %0 does not refer to any field in type %1">;
+def err_field_designator_nonfield : Error<
+ "field designator %0 does not refer to a non-static data member">;
+def note_field_designator_found : Note<"field designator refers here">;
+def err_designator_for_scalar_init : Error<
+ "designator in initializer for scalar type %0">;
+def warn_subobject_initializer_overrides : Warning<
+ "subobject initialization overrides initialization of other fields "
+ "within its enclosing subobject">, InGroup<InitializerOverrides>;
+def warn_initializer_overrides : Warning<
+ "initializer overrides prior initialization of this subobject">,
+ InGroup<InitializerOverrides>;
+def note_previous_initializer : Note<
+ "previous initialization %select{|with side effects }0is here"
+ "%select{| (side effects may not occur at run time)}0">;
+def err_designator_into_flexible_array_member : Error<
+ "designator into flexible array member subobject">;
+def note_flexible_array_member : Note<
+ "initialized flexible array member %0 is here">;
+def ext_flexible_array_init : Extension<
+ "flexible array initialization is a GNU extension">, InGroup<GNU>;
+
+// Declarations.
+def ext_anon_param_requires_type_specifier : Extension<
+ "type specifier required for unnamed parameter, defaults to int">;
+def err_bad_variable_name : Error<
+ "'%0' cannot be the name of a variable or data member">;
+def err_bad_parameter_name : Error<
+ "'%0' cannot be the name of a parameter">;
+def err_parameter_name_omitted : Error<"parameter name omitted">;
+def warn_unused_parameter : Warning<"unused parameter %0">,
+ InGroup<UnusedParameter>, DefaultIgnore;
+def warn_unused_variable : Warning<"unused variable %0">,
+ InGroup<UnusedVariable>, DefaultIgnore;
+def warn_unused_exception_param : Warning<"unused exception parameter %0">,
+ InGroup<UnusedExceptionParameter>, DefaultIgnore;
+def warn_decl_in_param_list : Warning<
+ "declaration of %0 will not be visible outside of this function">;
+def warn_unused_function : Warning<"unused function %0">,
+ InGroup<UnusedFunction>, DefaultIgnore;
+def warn_unused_member_function : Warning<"unused member function %0">,
+ InGroup<UnusedMemberFunction>, DefaultIgnore;
+def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">,
+ InGroup<UsedButMarkedUnused>, DefaultIgnore;
+
+def warn_parameter_size: Warning<
+ "%0 is a large (%1 bytes) pass-by-value argument; "
+ "pass it by reference instead ?">, InGroup<LargeByValueCopy>;
+def warn_return_value_size: Warning<
+ "return value of %0 is a large (%1 bytes) pass-by-value object; "
+ "pass it by reference instead ?">, InGroup<LargeByValueCopy>;
+
+def warn_implicit_function_decl : Warning<
+ "implicit declaration of function %0">,
+ InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
+def ext_implicit_function_decl : ExtWarn<
+ "implicit declaration of function %0 is invalid in C99">,
+ InGroup<ImplicitFunctionDeclare>;
+
+def err_ellipsis_first_arg : Error<
+ "ISO C requires a named argument before '...'">;
+def err_declarator_need_ident : Error<"declarator requires an identifier">;
+def err_bad_language : Error<"unknown linkage language">;
+def warn_use_out_of_scope_declaration : Warning<
+ "use of out-of-scope declaration of %0">;
+def err_inline_non_function : Error<
+ "'inline' can only appear on functions">;
+def warn_qual_return_type : Warning<
+ "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
+ InGroup<IgnoredQualifiers>, DefaultIgnore;
+
+def warn_decl_shadow :
+ Warning<"declaration shadows a %select{"
+ "local variable|"
+ "variable in %2|"
+ "static data member of %2|"
+ "field of %2}1">,
+ InGroup<Shadow>, DefaultIgnore;
+
+// C++ using declarations
+def err_using_requires_qualname : Error<
+ "using declaration requires a qualified name">;
+def err_using_typename_non_type : Error<
+ "'typename' keyword used on a non-type">;
+def err_using_dependent_value_is_type : Error<
+ "dependent using declaration resolved to type without 'typename'">;
+def err_using_decl_nested_name_specifier_is_not_class : Error<
+ "using declaration in class refers into '%0', which is not a class">;
+def err_using_decl_nested_name_specifier_is_current_class : Error<
+ "using declaration refers to its own class">;
+def err_using_decl_nested_name_specifier_is_not_base_class : Error<
+ "using declaration refers into '%0', which is not a base class of %1">;
+def err_using_decl_constructor_not_in_direct_base : Error<
+ "%0 is not a direct base of %1, can not inherit constructors">;
+def err_using_decl_constructor_conflict : Error<
+ "can not inherit constructor, already inherited constructor with "
+ "the same signature">;
+def note_using_decl_constructor_conflict_current_ctor : Note<
+ "conflicting constructor">;
+def note_using_decl_constructor_conflict_previous_ctor : Note<
+ "previous constructor">;
+def note_using_decl_constructor_conflict_previous_using : Note<
+ "previously inherited here">;
+def err_using_decl_can_not_refer_to_class_member : Error<
+ "using declaration can not refer to class member">;
+def err_using_decl_can_not_refer_to_namespace : Error<
+ "using declaration can not refer to namespace">;
+def err_using_decl_constructor : Error<
+ "using declaration can not refer to a constructor">;
+def err_using_decl_destructor : Error<
+ "using declaration can not refer to a destructor">;
+def err_using_decl_template_id : Error<
+ "using declaration can not refer to a template specialization">;
+def note_using_decl_target : Note<"target of using declaration">;
+def note_using_decl_conflict : Note<"conflicting declaration">;
+def err_using_decl_redeclaration : Error<"redeclaration of using decl">;
+def err_using_decl_conflict : Error<
+ "target of using declaration conflicts with declaration already in scope">;
+def err_using_decl_conflict_reverse : Error<
+ "declaration conflicts with target of using declaration already in scope">;
+def note_using_decl : Note<"%select{|previous }0using declaration">;
+
+def warn_access_decl_deprecated : Warning<
+ "access declarations are deprecated; use using declarations instead">,
+ InGroup<Deprecated>;
+
+def warn_global_constructor : Warning<
+ "declaration requires a global constructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+def warn_global_destructor : Warning<
+ "declaration requires a global destructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+
+def err_invalid_thread : Error<
+ "'__thread' is only allowed on variable declarations">;
+def err_thread_non_global : Error<
+ "'__thread' variables must have global storage">;
+def err_thread_unsupported : Error<
+ "thread-local storage is unsupported for the current target">;
+
+def warn_maybe_falloff_nonvoid_function : Warning<
+ "control may reach end of non-void function">,
+ InGroup<ReturnType>;
+def warn_falloff_nonvoid_function : Warning<
+ "control reaches end of non-void function">,
+ InGroup<ReturnType>;
+def err_maybe_falloff_nonvoid_block : Error<
+ "control may reach end of non-void block">;
+def err_falloff_nonvoid_block : Error<
+ "control reaches end of non-void block">;
+def warn_suggest_noreturn_function : Warning<
+ "function could be attribute 'noreturn'">,
+ InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
+def warn_suggest_noreturn_block : Warning<
+ "block could be attribute 'noreturn'">,
+ InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
+def warn_unreachable : Warning<"will never be executed">,
+ InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore;
+
+/// Built-in functions.
+def ext_implicit_lib_function_decl : ExtWarn<
+ "implicitly declaring C library function '%0' with type %1">;
+def note_please_include_header : Note<
+ "please include the header <%0> or explicitly provide a "
+ "declaration for '%1'">;
+def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
+def warn_implicit_decl_requires_stdio : Warning<
+ "declaration of built-in function '%0' requires inclusion of the header "
+ "<stdio.h>">;
+def warn_implicit_decl_requires_setjmp : Warning<
+ "declaration of built-in function '%0' requires inclusion of the header "
+ "<setjmp.h>">;
+def warn_redecl_library_builtin : Warning<
+ "incompatible redeclaration of library function %0">;
+def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_types_compatible_p_in_cplusplus : Error<
+ "__builtin_types_compatible_p is not valid in C++">;
+def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
+
+/// main()
+// static/inline main() are not errors in C, just in C++.
+def warn_unusual_main_decl : Warning<"'main' should not be declared "
+ "%select{static|inline|static or inline}0">;
+def err_unusual_main_decl : Error<"'main' is not allowed to be declared "
+ "%select{static|inline|static or inline}0">;
+def err_main_template_decl : Error<"'main' cannot be a template">;
+def err_main_returns_nonint : Error<"'main' must return 'int'">;
+def err_main_surplus_args : Error<"too many parameters (%0) for 'main': "
+ "must be 0, 2, or 3">;
+def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">;
+def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
+ "parameter of 'main' (%select{argument count|argument array|environment|"
+ "platform-specific data}0) must be of type %1">;
+
+/// parser diagnostics
+def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
+ InGroup<MissingDeclarations>;
+def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
+def err_statically_allocated_object : Error<
+ "interface type cannot be statically allocated">;
+def err_object_cannot_be_passed_returned_by_value : Error<
+ "interface type %1 cannot be %select{returned|passed}0 by value"
+ "; did you forget * in %1">;
+def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
+def warn_pragma_options_align_unsupported_option : Warning<
+ "unsupported alignment option in '#pragma options align'">;
+def warn_pragma_options_align_reset_failed : Warning<
+ "#pragma options align=reset failed: %0">;
+def err_pragma_options_align_mac68k_target_unsupported : Error<
+ "mac68k alignment pragma is not supported on this target">;
+def warn_pragma_pack_invalid_alignment : Warning<
+ "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">;
+// Follow the MSVC implementation.
+def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
+def warn_pragma_pack_pop_identifer_and_alignment : Warning<
+ "specifying both a name and alignment to 'pop' is undefined">;
+def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
+
+def warn_pragma_unused_undeclared_var : Warning<
+ "undeclared variable %0 used as an argument for '#pragma unused'">;
+def warn_pragma_unused_expected_var_arg : Warning<
+ "only variables can be arguments to '#pragma unused'">;
+def err_unsupported_pragma_weak : Error<
+ "using '#pragma weak' to refer to an undeclared identifier is not yet supported">;
+
+/// Objective-C parser diagnostics
+def err_duplicate_class_def : Error<
+ "duplicate interface definition for class %0">;
+def err_undef_superclass : Error<
+ "cannot find interface declaration for %0, superclass of %1">;
+def err_no_nsconstant_string_class : Error<
+ "cannot find interface declaration for %0">;
+def err_recursive_superclass : Error<
+ "trying to recursively use %0 as superclass of %1">;
+def warn_previous_alias_decl : Warning<"previously declared alias is ignored">;
+def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
+def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
+def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">;
+def err_protocol_has_circular_dependency : Error<
+ "protocol has circular dependency">;
+def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
+def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
+def warn_readonly_property : Warning<
+ "attribute 'readonly' of property %0 restricts attribute "
+ "'readwrite' of property inherited from %1">;
+
+def warn_property_attribute : Warning<
+ "property %0 '%1' attribute does not match the property inherited from %2">;
+def warn_property_types_are_incompatible : Warning<
+ "property type %0 is incompatible with type %1 inherited from %2">;
+def err_undef_interface : Error<"cannot find interface declaration for %0">;
+def err_class_extension_after_impl : Error<
+ "cannot declare class extension for %0 after class implementation">;
+def note_implementation_declared : Note<
+ "class implementation is declared here">;
+def warn_dup_category_def : Warning<
+ "duplicate definition of category %1 on interface %0">;
+def err_conflicting_super_class : Error<"conflicting super class name %0">;
+def err_dup_implementation_class : Error<"reimplementation of class %0">;
+def err_dup_implementation_category : Error<
+ "reimplementation of category %1 for class %0">;
+def err_conflicting_ivar_type : Error<
+ "instance variable %0 has conflicting type: %1 vs %2">;
+def err_duplicate_ivar_declaration : Error<
+ "instance variable is already declared">;
+def warn_on_superclass_use : Warning<
+ "class implementation may not have super class">;
+def err_conflicting_ivar_bitwidth : Error<
+ "instance variable %0 has conflicting bit-field width">;
+def err_conflicting_ivar_name : Error<
+ "conflicting instance variable names: %0 vs %1">;
+def err_inconsistant_ivar_count : Error<
+ "inconsistent number of instance variables specified">;
+def warn_incomplete_impl : Warning<"incomplete implementation">,
+ InGroup<DiagGroup<"incomplete-implementation">>;
+def note_undef_method_impl : Note<"method definition for %0 not found">;
+def note_required_for_protocol_at :
+ Note<"required for direct or indirect protocol %0">;
+
+def warn_conflicting_ret_types : Warning<
+ "conflicting return type in implementation of %0: %1 vs %2">;
+def warn_non_covariant_ret_types : Warning<
+ "conflicting return type in implementation of %0: %1 vs %2">,
+ InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
+
+def warn_conflicting_param_types : Warning<
+ "conflicting parameter types in implementation of %0: %1 vs %2">;
+def warn_non_contravariant_param_types : Warning<
+ "conflicting parameter types in implementation of %0: %1 vs %2">,
+ InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
+def warn_conflicting_variadic :Warning<
+ "conflicting variadic declaration of method and its implementation">;
+
+def warn_implements_nscopying : Warning<
+"default assign attribute on property %0 which implements "
+"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
+
+def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
+def warn_strict_multiple_method_decl : Warning<
+ "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
+def warn_accessor_property_type_mismatch : Warning<
+ "type of property %0 does not match type of accessor %1">;
+def note_declared_at : Note<"declared here">;
+def note_method_declared_at : Note<"method declared here">;
+def err_setter_type_void : Error<"type of setter must be void">;
+def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
+def warn_missing_atend : Warning<"'@end' is missing in implementation context">;
+def err_objc_var_decl_inclass :
+ Error<"cannot declare variable inside @interface or @protocol">;
+def error_missing_method_context : Error<
+ "missing context for method declaration">;
+def err_objc_property_attr_mutually_exclusive : Error<
+ "property attributes '%0' and '%1' are mutually exclusive">;
+def err_objc_property_requires_object : Error<
+ "property with '%0' attribute must be of object type">;
+def warn_objc_property_no_assignment_attribute : Warning<
+ "no 'assign', 'retain', or 'copy' attribute is specified - "
+ "'assign' is assumed">;
+def warn_objc_property_default_assign_on_object : Warning<
+ "default property attribute 'assign' not appropriate for non-gc object">;
+def warn_property_attr_mismatch : Warning<
+ "property attribute in continuation class does not match the primary class">;
+def warn_objc_property_copy_missing_on_block : Warning<
+ "'copy' attribute must be specified for the block property "
+ "when -fobjc-gc-only is specified">;
+def warn_atomic_property_rule : Warning<
+ "writable atomic property %0 cannot pair a synthesized setter/getter "
+ "with a user defined setter/getter">;
+def warn_default_atomic_custom_getter_setter : Warning<
+ "atomic by default property %0 has a user defined %select{getter|setter}1 "
+ "(property should be marked 'atomic' if this is intended)">,
+ InGroup<CustomAtomic>, DefaultIgnore;
+def err_use_continuation_class : Error<
+ "illegal redeclaration of property in continuation class %0"
+ " (attribute must be 'readwrite', while its primary must be 'readonly')">;
+def err_use_continuation_class_redeclaration_readwrite : Error<
+ "illegal redeclaration of 'readwrite' property in continuation class %0"
+ " (perhaps you intended this to be a 'readwrite' redeclaration of a "
+ "'readonly' public property?)">;
+def err_continuation_class : Error<"continuation class has no primary class">;
+def err_property_type : Error<"property cannot have array or function type %0">;
+def error_missing_property_context : Error<
+ "missing context for property implementation declaration">;
+def error_bad_property_decl : Error<
+ "property implementation must have its declaration in interface %0">;
+def error_category_property : Error<
+ "property declared in category %0 cannot be implemented in "
+ "class implementation">;
+def note_property_declare : Note<
+ "property declared here">;
+def error_synthesize_category_decl : Error<
+ "@synthesize not allowed in a category's implementation">;
+def error_reference_property : Error<
+ "property of reference type is not supported">;
+def error_missing_property_interface : Error<
+ "property implementation in a category with no category declaration">;
+def error_bad_category_property_decl : Error<
+ "property implementation must have its declaration in the category %0">;
+def error_bad_property_context : Error<
+ "property implementation must be in a class or category implementation">;
+def error_missing_property_ivar_decl : Error<
+ "synthesized property %0 must either be named the same as a compatible"
+ " ivar or must explicitly name an ivar">;
+
+def error_synthesized_ivar_yet_not_supported : Error<
+ "instance variable synthesis not yet supported"
+ " (need to declare %0 explicitly)">;
+
+def error_property_ivar_type : Error<
+ "type of property %0 (%1) does not match type of ivar %2 (%3)">;
+def error_ivar_in_superclass_use : Error<
+ "property %0 attempting to use ivar %1 declared in super class %2">;
+def error_weak_property : Error<
+ "existing ivar %1 for __weak property %0 must be __weak">;
+def error_strong_property : Error<
+ "property %0 must be declared __weak to match existing ivar %1 with __weak attribute">;
+def error_dynamic_property_ivar_decl : Error<
+ "dynamic property can not have ivar specification">;
+def error_duplicate_ivar_use : Error<
+ "synthesized properties %0 and %1 both claim ivar %2">;
+def error_property_implemented : Error<"property %0 is already implemented">;
+def warn_objc_property_attr_mutually_exclusive : Warning<
+ "property attributes '%0' and '%1' are mutually exclusive">,
+ InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
+def warn_undeclared_selector : Warning<
+ "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_implicit_atomic_property : Warning<
+ "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
+def warn_auto_implicit_atomic_property : Warning<
+ "property is assumed atomic when auto-synthesizing the property">,
+ InGroup<ImplicitAtomic>, DefaultIgnore;
+def warn_unimplemented_selector: Warning<
+ "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
+def warn_unimplemented_protocol_method : Warning<
+ "method in protocol not implemented">, InGroup<Protocol>;
+
+// C++ declarations
+def err_static_assert_expression_is_not_constant : Error<
+ "static_assert expression is not an integral constant expression">;
+def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
+
+def err_inline_namespace_mismatch : Error<
+ "%select{|non-}0inline namespace "
+ "cannot be reopened as %select{non-|}0inline">;
+
+def err_unexpected_friend : Error<
+ "friends can only be classes or functions">;
+def ext_enum_friend : ExtWarn<
+ "enumeration type %0 cannot be a friend">;
+def ext_nonclass_type_friend : ExtWarn<
+ "non-class type %0 cannot be a friend">;
+def err_friend_is_member : Error<
+ "friends cannot be members of the declaring class">;
+def ext_unelaborated_friend_type : ExtWarn<
+ "must specify '%select{struct|union|class|enum}0' to befriend %1">;
+def err_qualified_friend_not_found : Error<
+ "no function named %0 with type %1 was found in the specified scope">;
+def err_introducing_special_friend : Error<
+ "must use a qualified name when declaring a %select{constructor|"
+ "destructor|conversion operator}0 as a friend">;
+def err_tagless_friend_type_template : Error<
+ "friend type templates must use an elaborated type">;
+def err_no_matching_local_friend : Error<
+ "no matching function found in local scope">;
+def err_partial_specialization_friend : Error<
+ "partial specialization cannot be declared as a friend">;
+
+def err_abstract_type_in_decl : Error<
+ "%select{return|parameter|variable|field}0 type %1 is an abstract class">;
+def err_allocation_of_abstract_type : Error<
+ "allocating an object of abstract class type %0">;
+def err_throw_abstract_type : Error<
+ "cannot throw an object of abstract type %0">;
+def err_array_of_abstract_type : Error<"array of abstract class type %0">;
+
+def err_multiple_final_overriders : Error<
+ "virtual function %q0 has more than one final overrider in %1">;
+def note_final_overrider : Note<"final overrider of %q0 in %1">;
+
+def err_type_defined_in_type_specifier : Error<
+ "%0 can not be defined in a type specifier">;
+def err_type_defined_in_result_type : Error<
+ "%0 can not be defined in the result type of a function">;
+def err_type_defined_in_param_type : Error<
+ "%0 can not be defined in a parameter type">;
+
+def note_pure_virtual_function : Note<
+ "unimplemented pure virtual method %0 in %1">;
+
+def err_deleted_non_function : Error<
+ "only functions can have deleted definitions">;
+def err_deleted_decl_not_first : Error<
+ "deleted definition must be first declaration">;
+
+def warn_weak_vtable : Warning<
+ "%0 has no out-of-line virtual method definitions; its vtable will be "
+ "emitted in every translation unit">,
+ InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore;
+
+def ext_using_undefined_std : ExtWarn<
+ "using directive refers to implicitly-defined namespace 'std'">;
+
+// C++ exception specifications
+def err_exception_spec_in_typedef : Error<
+ "exception specifications are not allowed in typedefs">;
+def err_distant_exception_spec : Error<
+ "exception specifications are not allowed beyond a single level "
+ "of indirection">;
+def err_incomplete_in_exception_spec : Error<
+ "%select{|pointer to |reference to }0incomplete type %1 is not allowed "
+ "in exception specification">;
+def err_mismatched_exception_spec : Error<
+ "exception specification in declaration does not match previous declaration">;
+def err_override_exception_spec : Error<
+ "exception specification of overriding function is more lax than "
+ "base version">;
+def err_incompatible_exception_specs : Error<
+ "target exception specification is not superset of source">;
+def err_deep_exception_specs_differ : Error<
+ "exception specifications of %select{return|argument}0 types differ">;
+def warn_missing_exception_specification : Warning<
+ "%0 is missing exception specification '%1'">;
+
+// C++ access checking
+def err_class_redeclared_with_different_access : Error<
+ "%0 redeclared with '%1' access">;
+def err_access : Error<
+ "%1 is a %select{private|protected}0 member of %3">, AccessControl;
+def err_access_ctor : Error<
+ "calling a %select{private|protected}0 constructor of class %2">,
+ AccessControl;
+def ext_rvalue_to_reference_access_ctor : ExtWarn<
+ "C++98 requires an accessible copy constructor for class %2 when binding "
+ "a reference to a temporary; was %select{private|protected}0">,
+ AccessControl, InGroup<BindToTemporaryCopy>;
+def err_access_base : Error<
+ "%select{base class|inherited virtual base class}0 %1 has %select{private|"
+ "protected}3 %select{constructor|copy constructor|copy assignment operator|"
+ "destructor}2">, AccessControl;
+def err_access_field: Error<
+ "field of type %0 has %select{private|protected}2 %select{constructor|copy "
+ "constructor|copy assignment operator|destructor}1">, AccessControl;
+
+def err_access_ctor_field :
+ Error<"field of type %1 has %select{private|protected}2 constructor">,
+ AccessControl;
+def err_access_dtor : Error<
+ "calling a %select{private|protected}1 destructor of class %0">,
+ AccessControl;
+def err_access_dtor_base :
+ Error<"base class %0 has %select{private|protected}1 destructor">,
+ AccessControl;
+def err_access_dtor_vbase :
+ Error<"inherited virtual base class %0 has "
+ "%select{private|protected}1 destructor">,
+ AccessControl;
+def err_access_dtor_temp :
+ Error<"temporary of type %0 has %select{private|protected}1 destructor">,
+ AccessControl;
+def err_access_dtor_exception :
+ Error<"exception object of type %0 has %select{private|protected}1 "
+ "destructor">, AccessControl;
+def err_access_dtor_field :
+ Error<"field of type %1 has %select{private|protected}2 destructor">,
+ AccessControl;
+def err_access_dtor_var :
+ Error<"variable of type %1 has %select{private|protected}2 destructor">,
+ AccessControl;
+def err_access_assign_field :
+ Error<"field of type %1 has %select{private|protected}2 copy assignment"
+ " operator">,
+ AccessControl;
+def err_access_assign_base :
+ Error<"base class %0 has %select{private|protected}1 copy assignment"
+ " operator">,
+ AccessControl;
+def err_access_copy_field :
+ Error<"field of type %1 has %select{private|protected}2 copy constructor">,
+ AccessControl;
+def err_access_copy_base :
+ Error<"base class %0 has %select{private|protected}1 copy constructor">,
+ AccessControl;
+def err_access_dtor_ivar :
+ Error<"instance variable of type %0 has %select{private|protected}1 "
+ "destructor">,
+ AccessControl;
+def note_previous_access_declaration : Note<
+ "previously declared '%1' here">;
+def err_access_outside_class : Error<
+ "access to %select{private|protected}0 member outside any class context">,
+ AccessControl;
+def note_access_natural : Note<
+ "%select{|implicitly }1declared %select{private|protected}0 here">;
+def note_access_constrained_by_path : Note<
+ "constrained by %select{|implicitly }1%select{private|protected}0"
+ " inheritance here">;
+def note_access_protected_restricted : Note<
+ "object type %select{|%1 }0must derive from context type %2">;
+
+// C++ name lookup
+def err_incomplete_nested_name_spec : Error<
+ "incomplete type %0 named in nested name specifier">;
+def err_dependent_nested_name_spec : Error<
+ "nested name specifier for a declaration cannot depend on a template "
+ "parameter">;
+def err_nested_name_member_ref_lookup_ambiguous : Error<
+ "lookup of %0 in member access expression is ambiguous">;
+def ext_nested_name_member_ref_lookup_ambiguous : ExtWarn<
+ "lookup of %0 in member access expression is ambiguous; using member of %1">,
+ InGroup<AmbigMemberTemplate>;
+def note_ambig_member_ref_object_type : Note<
+ "lookup in the object type %0 refers here">;
+def note_ambig_member_ref_scope : Note<
+ "lookup from the current scope refers here">;
+def err_qualified_member_nonclass : Error<
+ "qualified member access refers to a member in %0">;
+def err_incomplete_member_access : Error<
+ "member access into incomplete type %0">;
+def err_incomplete_type : Error<
+ "incomplete type %0 where a complete type is required">;
+
+// C++ class members
+def err_storageclass_invalid_for_member : Error<
+ "storage class specified for a member declaration">;
+def err_mutable_function : Error<"'mutable' cannot be applied to functions">;
+def err_mutable_reference : Error<"'mutable' cannot be applied to references">;
+def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">;
+def err_mutable_nonmember : Error<
+ "'mutable' can only be applied to member variables">;
+def err_virtual_non_function : Error<
+ "'virtual' can only appear on non-static member functions">;
+def err_virtual_out_of_class : Error<
+ "'virtual' can only be specified inside the class definition">;
+def err_virtual_member_function_template : Error<
+ "'virtual' can not be specified on member function templates">;
+def err_static_overrides_virtual : Error<
+ "'static' member function %0 overrides a virtual function in a base class">;
+def err_explicit_non_function : Error<
+ "'explicit' can only appear on non-static member functions">;
+def err_explicit_out_of_class : Error<
+ "'explicit' can only be specified inside the class definition">;
+def err_explicit_non_ctor_or_conv_function : Error<
+ "'explicit' can only be applied to a constructor or conversion function">;
+def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
+def err_static_out_of_line : Error<
+ "'static' can only be specified inside the class definition">;
+def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">;
+def err_not_integral_type_bitfield : Error<
+ "bit-field %0 has non-integral type %1">;
+def err_not_integral_type_anon_bitfield : Error<
+ "anonymous bit-field has non-integral type %0">;
+def err_member_initialization : Error<
+ "fields can only be initialized in constructors">;
+def err_member_function_initialization : Error<
+ "initializer on function does not look like a pure-specifier">;
+def err_non_virtual_pure : Error<
+ "%0 is not virtual and cannot be declared pure">;
+def err_implicit_object_parameter_init : Error<
+ "cannot initialize object parameter of type %0 with an expression "
+ "of type %1">;
+def err_qualified_member_of_unrelated : Error<
+ "%q0 is not a member of class %1">;
+
+def note_field_decl : Note<"member is declared here">;
+def note_ivar_decl : Note<"ivar is declared here">;
+def note_bitfield_decl : Note<"bit-field is declared here">;
+def note_previous_decl : Note<"%0 declared here">;
+def note_member_synthesized_at : Note<
+ "implicit default %select{constructor|copy constructor|"
+ "copy assignment operator|destructor}0 for %1 first required here">;
+def err_missing_default_ctor : Error<
+ "%select{|implicit default }0constructor for %1 must explicitly initialize "
+ "the %select{base class|member}2 %3 which does not have a default "
+ "constructor">;
+def err_illegal_union_or_anon_struct_member : Error<
+ "%select{anonymous struct|union}0 member %1 has a non-trivial "
+ "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
+def note_nontrivial_has_virtual : Note<
+ "because type %0 has a virtual %select{member function|base class}1">;
+def note_nontrivial_has_nontrivial : Note<
+ "because type %0 has a %select{member|base class}1 with a non-trivial "
+ "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
+def note_nontrivial_user_defined : Note<
+ "because type %0 has a user-declared %select{constructor|copy constructor|"
+ "copy assignment operator|destructor}1">;
+def err_static_data_member_not_allowed_in_union_or_anon_struct : Error<
+ "static data member %0 not allowed in %select{anonymous struct|union}1">;
+def err_union_member_of_reference_type : Error<
+ "union member %0 has reference type %1">;
+
+def err_different_return_type_for_overriding_virtual_function : Error<
+ "virtual function %0 has a different return type (%1) than the "
+ "function it overrides (which has return type %2)">;
+def note_overridden_virtual_function : Note<
+ "overridden virtual function is here">;
+
+def err_covariant_return_inaccessible_base : Error<
+ "invalid covariant return for virtual function: %1 is a "
+ "%select{private|protected}2 base class of %0">, AccessControl;
+def err_covariant_return_ambiguous_derived_to_base_conv : Error<
+ "return type of virtual function %3 is not covariant with the return type of "
+ "the function it overrides (ambiguous conversion from derived class "
+ "%0 to base class %1:%2)">;
+def err_covariant_return_not_derived : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (%1 is not derived from %2)">;
+def err_covariant_return_incomplete : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (%1 is incomplete)">;
+def err_covariant_return_type_different_qualifications : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (%1 has different qualifiers than %2)">;
+def err_covariant_return_type_class_type_more_qualified : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (class type %1 is more qualified than class "
+ "type %2">;
+
+// C++ constructors
+def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">;
+def err_invalid_qualified_constructor : Error<
+ "'%0' qualifier is not allowed on a constructor">;
+def err_ref_qualifier_constructor : Error<
+ "ref-qualifier '%select{&&|&}0' is not allowed on a constructor">;
+
+def err_constructor_return_type : Error<
+ "constructor cannot have a return type">;
+def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
+def err_constructor_byvalue_arg : Error<
+ "copy constructor must pass its first argument by reference">;
+def warn_no_constructor_for_refconst : Warning<
+ "%select{struct|union|class|enum}0 %1 does not declare any constructor to "
+ "initialize its non-modifiable members">;
+def note_refconst_member_not_initialized : Note<
+ "%select{const|reference}0 member %1 will never be initialized">;
+def ext_ms_explicit_constructor_call : ExtWarn<
+ "explicit constructor calls are a Microsoft extension">, InGroup<Microsoft>;
+
+// C++ destructors
+def err_destructor_not_member : Error<
+ "destructor must be a non-static member function">;
+def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">;
+def err_invalid_qualified_destructor : Error<
+ "'%0' qualifier is not allowed on a destructor">;
+def err_ref_qualifier_destructor : Error<
+ "ref-qualifier '%select{&&|&}0' is not allowed on a destructor">;
+def err_destructor_return_type : Error<"destructor cannot have a return type">;
+def err_destructor_redeclared : Error<"destructor cannot be redeclared">;
+def err_destructor_with_params : Error<"destructor cannot have any parameters">;
+def err_destructor_variadic : Error<"destructor cannot be variadic">;
+def err_destructor_typedef_name : Error<
+ "destructor cannot be declared using a typedef %0 of the class name">;
+def err_destructor_name : Error<
+ "expected the class name after '~' to name the enclosing class">;
+def err_destructor_class_name : Error<
+ "expected the class name after '~' to name a destructor">;
+def err_ident_in_pseudo_dtor_not_a_type : Error<
+ "identifier %0 in pseudo-destructor expression does not name a type">;
+
+// C++ initialization
+def err_init_conversion_failed : Error<
+ "cannot initialize %select{a variable|a parameter|return object|an "
+ "exception object|a member subobject|an array element|a new value|a value|a "
+ "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of "
+ "type %3">;
+
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind "
+ "to lvalue of type %1">;
+def err_invalid_initialization : Error<
+"invalid initialization of reference of type %0 from expression of type %1">;
+def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
+ "due to multiple conversion functions">;
+def err_not_reference_to_const_init : Error<
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot be "
+ "initialized with a %select{value|temporary}2 of type %3">;
+def err_lvalue_reference_bind_to_temporary : Error<
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
+ "temporary of type %2">;
+def err_lvalue_reference_bind_to_unrelated : Error<
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
+ "value of unrelated type %2">;
+def err_reference_bind_drops_quals : Error<
+ "binding of reference to type %0 to a value of type %1 drops qualifiers">;
+def err_reference_bind_failed : Error<
+ "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
+ "%2">;
+def err_reference_bind_init_list : Error<
+ "reference to type %0 cannot bind to an initializer list">;
+def err_init_list_bad_dest_type : Error<
+ "%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
+ "list">;
+def err_member_function_call_bad_cvr : Error<"member function %0 not viable: "
+ "'this' argument has type %1, but function is not marked "
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
+ "volatile or restrict|const, volatile, or restrict}2">;
+
+def err_reference_init_drops_quals : Error<
+ "initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops "
+ "qualifiers">;
+def err_reference_bind_to_bitfield : Error<
+ "%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
+def err_reference_bind_to_vector_element : Error<
+ "%select{non-const|volatile}0 reference cannot bind to vector element">;
+def err_reference_var_requires_init : Error<
+ "declaration of reference variable %0 requires an initializer">;
+def err_const_var_requires_init : Error<
+ "declaration of const variable '%0' requires an initializer">;
+def err_reference_without_init : Error<
+ "reference to type %0 requires an initializer">;
+def err_reference_has_multiple_inits : Error<
+ "reference cannot be initialized with multiple values">;
+def err_init_non_aggr_init_list : Error<
+ "initialization of non-aggregate type %0 with an initializer list">;
+def err_init_reference_member_uninitialized : Error<
+ "reference member of type %0 uninitialized">;
+def note_uninit_reference_member : Note<
+ "uninitialized reference member is here">;
+def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
+ InGroup<Uninitialized>;
+def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">,
+ InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def note_uninit_var_def : Note<
+ "variable %0 is declared here">;
+def warn_uninit_var_captured_by_block : Warning<
+ "variable %0 is possibly uninitialized when captured by block">,
+ InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def note_var_fixit_add_initialization : Note<
+ "add initialization to silence this warning">;
+def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
+
+def err_temp_copy_no_viable : Error<
+ "no viable constructor %select{copying variable|copying parameter|"
+ "returning object|throwing object|copying member subobject|copying array "
+ "element|allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element}0 of type %1">;
+def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn<
+ "no viable constructor %select{copying variable|copying parameter|"
+ "returning object|throwing object|copying member subobject|copying array "
+ "element|allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element}0 of type %1; C++98 requires a copy "
+ "constructor when binding a reference to a temporary">,
+ InGroup<BindToTemporaryCopy>;
+def err_temp_copy_ambiguous : Error<
+ "ambiguous constructor call when %select{copying variable|copying "
+ "parameter|returning object|throwing object|copying member subobject|copying "
+ "array element|allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element}0 of type %1">;
+def err_temp_copy_deleted : Error<
+ "%select{copying variable|copying parameter|returning object|throwing "
+ "object|copying member subobject|copying array element|allocating object|"
+ "copying temporary|initializing base subobject|initializing vector element}0 "
+ "of type %1 invokes deleted constructor">;
+def err_temp_copy_incomplete : Error<
+ "copying a temporary object of incomplete type %0">;
+
+// C++0x decltype
+def err_cannot_determine_declared_type_of_overloaded_function : Error<
+ "cannot determine the type of an overloaded function">;
+
+// C++0x auto
+def err_auto_variable_cannot_appear_in_own_initializer : Error<
+ "variable %0 declared with 'auto' type cannot appear in its own initializer">;
+def err_illegal_decl_array_of_auto : Error<
+ "'%0' declared as array of %1">;
+def err_new_array_of_auto : Error<
+ "cannot allocate array of 'auto'">;
+def err_auto_not_allowed : Error<
+ "'auto' not allowed %select{in function prototype|in struct member"
+ "|in union member|in class member|in exception declaration"
+ "|in template parameter|in block literal|in template argument|here}0">;
+def err_auto_var_requires_init : Error<
+ "declaration of variable %0 with type %1 requires an initializer">;
+def err_auto_new_requires_ctor_arg : Error<
+ "new expression for type %0 requires a constructor argument">;
+def err_auto_var_init_multiple_expressions : Error<
+ "initializer for variable %0 with type %1 contains multiple expressions">;
+def err_auto_new_ctor_multiple_expressions : Error<
+ "new expression for type %0 contains multiple constructor arguments">;
+def err_auto_missing_trailing_return : Error<
+ "'auto' return without trailing return type">;
+def err_trailing_return_without_auto : Error<
+ "function with trailing return type must specify return type 'auto', not %0">;
+def err_auto_var_deduction_failure : Error<
+ "variable %0 with type %1 has incompatible initializer of type %2">;
+def err_auto_new_deduction_failure : Error<
+ "new expression for type %0 has incompatible constructor argument of type %1">;
+def err_auto_different_deductions : Error<
+ "'auto' deduced as %0 in declaration of %1 and deduced as %2 in declaration of %3">;
+
+// C++0x override control
+def override_keyword_only_allowed_on_virtual_member_functions : Error<
+ "only virtual member functions can be marked '%0'">;
+def err_function_marked_override_not_overriding : Error<
+ "%0 marked 'override' but does not override any member functions">;
+def err_class_marked_final_used_as_base : Error<
+ "base %0 is marked 'final'">;
+
+// C++0x attributes
+def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
+
+// C++0x [[final]]
+def err_final_function_overridden : Error<
+ "declaration of %0 overrides a 'final' function">;
+def err_final_base : Error<
+ "derivation from 'final' %0">;
+
+def err_function_overriding_without_override : Error<
+ "%0 overrides function%s1 without being marked 'override'">;
+
+// C++0x scoped enumerations
+def err_enum_invalid_underlying : Error<
+ "non-integral type %0 is an invalid underlying type">;
+def err_enumerator_too_large : Error<
+ "enumerator value is not representable in the underlying type %0">;
+def ext_enumerator_too_large : ExtWarn<
+ "enumerator value is not representable in the underlying type %0">,
+ InGroup<Microsoft>;
+def err_enumerator_wrapped : Error<
+ "enumerator value %0 is not representable in the underlying type %1">;
+def err_enum_redeclare_type_mismatch : Error<
+ "enumeration redeclared with different underlying type %0 (was %1)">;
+def err_enum_redeclare_fixed_mismatch : Error<
+ "enumeration previously declared with %select{non|}0fixed underlying type">;
+def err_enum_redeclare_scoped_mismatch : Error<
+ "enumeration previously declared as %select{un|}0scoped">;
+
+// C++0x delegating constructors
+def err_delegation_0x_only : Error<
+ "delegating constructors are permitted only in C++0x">;
+def err_delegation_unimplemented : Error<
+ "delegating constructors are not fully implemented">;
+
+// Objective-C++
+def err_objc_decls_may_only_appear_in_global_scope : Error<
+ "Objective-C declarations may only appear in global scope">;
+def err_nsobject_attribute : Error<
+ "__attribute ((NSObject)) is for pointer types only">;
+
+// Attributes
+def err_attribute_can_be_applied_only_to_symbol_declaration : Error<
+ "%0 attribute can be applied only to symbol declaration">;
+def err_attributes_are_not_compatible : Error<
+ "%0 and %1 attributes are not compatible">;
+def err_attribute_wrong_number_arguments : Error<
+ "attribute requires %0 argument(s)">;
+def err_iboutletcollection_type : Error<
+ "invalid type %0 as argument of iboutletcollection attribute">;
+def err_iboutletcollection_object_type : Error<
+ "%select{ivar|property}1 with iboutletcollection attribute must "
+ "have object type (invalid %0)">;
+def err_attribute_missing_parameter_name : Error<
+ "attribute requires unquoted parameter">;
+def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
+def err_attribute_bad_neon_vector_size : Error<
+ "Neon vector size must be 64 or 128 bits">;
+def err_attribute_argument_not_int : Error<
+ "'%0' attribute requires integer constant">;
+def err_attribute_argument_outof_range : Error<
+ "init_priority attribute requires integer constant between "
+ "101 and 65535 inclusive">;
+def err_init_priority_object_attr : Error<
+ "can only use 'init_priority' attribute on file-scope definitions "
+ "of objects of class type">;
+def err_attribute_argument_n_not_int : Error<
+ "'%0' attribute requires parameter %1 to be an integer constant">;
+def err_attribute_argument_n_not_string : Error<
+ "'%0' attribute requires parameter %1 to be a string">;
+def err_attribute_argument_out_of_bounds : Error<
+ "'%0' attribute parameter %1 is out of bounds">;
+def err_attribute_requires_objc_interface : Error<
+ "attribute may only be applied to an Objective-C interface">;
+def err_attribute_uuid_malformed_guid : Error<
+ "uuid attribute contains a malformed GUID">;
+def warn_nonnull_pointers_only : Warning<
+ "nonnull attribute only applies to pointer arguments">;
+def err_attribute_invalid_implicit_this_argument : Error<
+ "'%0' attribute is invalid for the implicit this argument">;
+def err_ownership_type : Error<
+ "%0 attribute only applies to %1 arguments">;
+def err_format_strftime_third_parameter : Error<
+ "strftime format attribute requires 3rd parameter to be 0">;
+def err_format_attribute_requires_variadic : Error<
+ "format attribute requires variadic function">;
+def err_format_attribute_not : Error<"format argument not %0">;
+def err_format_attribute_result_not : Error<"function does not return %0">;
+def err_format_attribute_implicit_this_format_string : Error<
+ "format attribute cannot specify the implicit this argument as the format "
+ "string">;
+def err_attribute_invalid_size : Error<
+ "vector size not an integral multiple of component size">;
+def err_attribute_zero_size : Error<"zero vector size">;
+def err_typecheck_vector_not_convertable : Error<
+ "can't convert between vector values of different size (%0 and %1)">;
+def err_typecheck_ext_vector_not_typedef : Error<
+ "ext_vector_type only applies to types, not variables">;
+def err_unsupported_vector_size : Error<
+ "unsupported type %0 for vector_size attribute, please use on typedef">;
+def err_ext_vector_component_exceeds_length : Error<
+ "vector component access exceeds type %0">;
+def err_ext_vector_component_name_illegal : Error<
+ "illegal vector component name '%0'">;
+def err_attribute_address_space_not_int : Error<
+ "address space attribute requires an integer constant">;
+def err_attribute_address_space_negative : Error<
+ "address space is negative">;
+def err_attribute_address_space_too_high : Error<
+ "address space is larger than the maximum supported (%0)">;
+def err_attribute_address_multiple_qualifiers : Error<
+ "multiple address spaces specified for type">;
+def err_as_qualified_auto_decl : Error<
+ "automatic variable qualified with an address space">;
+def err_arg_with_address_space : Error<
+ "parameter may not be qualified with an address space">;
+def err_attribute_not_string : Error<
+ "argument to %0 attribute was not a string literal">;
+def err_attribute_section_invalid_for_target : Error<
+ "argument to 'section' attribute is not valid for this target: %0">;
+def err_attribute_section_local_variable : Error<
+ "'section' attribute is not valid on local variables">;
+def err_attribute_aligned_not_power_of_two : Error<
+ "requested alignment is not a power of 2">;
+def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
+ "'%0' redeclared without %1 attribute: previous %1 ignored">;
+def warn_attribute_ignored : Warning<"%0 attribute ignored">;
+def warn_unknown_attribute_ignored : Warning<
+ "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_attribute_precede_definition : Warning<
+ "attribute declaration must precede definition">;
+def warn_attribute_void_function_method : Warning<
+ "attribute %0 cannot be applied to "
+ "%select{functions|Objective-C method}1 without return value">;
+def warn_attribute_weak_on_field : Warning<
+ "__weak attribute cannot be specified on a field declaration">;
+def warn_attribute_weak_on_local : Warning<
+ "__weak attribute cannot be specified on an automatic variable">;
+def warn_weak_identifier_undeclared : Warning<
+ "weak identifier %0 never declared">;
+def err_attribute_weak_static : Error<
+ "weak declaration cannot have internal linkage">;
+def warn_attribute_weak_import_invalid_on_definition : Warning<
+ "'weak_import' attribute cannot be specified on a definition">;
+def err_attribute_weakref_not_static : Error<
+ "weakref declaration must have internal linkage">;
+def err_attribute_weakref_not_global_context : Error<
+ "weakref declaration of '%0' must be in a global context">;
+def err_attribute_weakref_without_alias : Error<
+ "weakref declaration of '%0' must also have an alias attribute">;
+def err_alias_not_supported_on_darwin : Error <
+ "only weak aliases are supported on darwin">;
+def warn_attribute_wrong_decl_type : Warning<
+ "%0 attribute only applies to %select{functions|unions|"
+ "variables and functions|functions and methods|parameters|"
+ "parameters and methods|functions, methods and blocks|"
+ "classes and virtual methods|functions, methods, and parameters|"
+ "classes|virtual methods|class members|variables|methods|"
+ "variables, functions and labels}1">;
+def err_attribute_wrong_decl_type : Error<
+ "%0 attribute only applies to %select{functions|unions|"
+ "variables and functions|functions and methods|parameters|"
+ "parameters and methods|functions, methods and blocks|"
+ "classes and virtual methods|functions, methods, and parameters|"
+ "classes|virtual methods|class members|variables|methods}1">;
+def warn_function_attribute_wrong_type : Warning<
+ "%0 only applies to function types; type here is %1">;
+def warn_gnu_inline_attribute_requires_inline : Warning<
+ "'gnu_inline' attribute requires function to be marked 'inline',"
+ " attribute ignored">;
+def err_attribute_vecreturn_only_vector_member : Error<
+ "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">;
+def err_attribute_vecreturn_only_pod_record : Error<
+ "the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)">;
+def err_cconv_change : Error<
+ "function declared '%0' here was previously declared "
+ "%select{'%2'|without calling convention}1">;
+def err_cconv_knr : Error<
+ "function with no prototype cannot use %0 calling convention">;
+def err_cconv_varargs : Error<
+ "variadic function cannot use %0 calling convention">;
+def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
+ "attribute was previously declared "
+ "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
+
+def warn_impcast_vector_scalar : Warning<
+ "implicit conversion turns vector to scalar: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_complex_scalar : Warning<
+ "implicit conversion discards imaginary component: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_float_precision : Warning<
+ "implicit conversion loses floating-point precision: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_float_integer : Warning<
+ "implicit conversion turns floating-point number into integer: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_sign : Warning<
+ "implicit conversion changes signedness: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_sign_conditional : Warning<
+ "operand of ? changes signedness: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_precision : Warning<
+ "implicit conversion loses integer precision: %0 to %1">,
+ InGroup<DiagGroup<"conversion">>, DefaultIgnore;
+def warn_impcast_integer_64_32 : Warning<
+ "implicit conversion loses integer precision: %0 to %1">,
+ InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+def warn_impcast_integer_precision_constant : Warning<
+ "implicit conversion from %2 to %3 changes value from %0 to %1">,
+ InGroup<DiagGroup<"constant-conversion">>;
+def warn_impcast_bitfield_precision_constant : Warning<
+ "implicit truncation from %2 to bitfield changes value from %0 to %1">,
+ InGroup<DiagGroup<"constant-conversion">>;
+def warn_impcast_literal_float_to_integer : Warning<
+ "implicit conversion turns literal floating-point number into integer: "
+ "%0 to %1">,
+ InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore;
+
+def warn_cast_align : Warning<
+ "cast from %0 to %1 increases required alignment from %2 to %3">,
+ InGroup<CastAlign>, DefaultIgnore;
+
+def warn_attribute_ignored_for_field_of_type : Warning<
+ "%0 attribute ignored for field of type %1">;
+def warn_transparent_union_attribute_field_size_align : Warning<
+ "%select{alignment|size}0 of field %1 (%2 bits) does not match the "
+ "%select{alignment|size}0 of the first field in transparent union; "
+ "transparent_union attribute ignored">;
+def note_transparent_union_first_field_size_align : Note<
+ "%select{alignment|size}0 of first field is %1 bits">;
+def warn_transparent_union_attribute_not_definition : Warning<
+ "transparent_union attribute can only be applied to a union definition; "
+ "attribute ignored">;
+def warn_transparent_union_attribute_floating : Warning<
+ "first field of a transparent union cannot have %select{floating point|"
+ "vector}0 type %1; transparent_union attribute ignored">;
+def warn_transparent_union_attribute_zero_fields : Warning<
+ "transparent union definition must contain at least one field; "
+ "transparent_union attribute ignored">;
+def warn_attribute_type_not_supported : Warning<
+ "'%0' attribute argument not supported: %1">;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
+def err_unknown_machine_mode : Error<"unknown machine mode %0">;
+def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
+def err_mode_not_primitive : Error<
+ "mode attribute only supported for integer and floating-point types">;
+def err_mode_wrong_type : Error<
+ "type of machine mode does not match type of base type">;
+def err_attr_wrong_decl : Error<
+ "'%0' attribute invalid on this declaration, requires typedef or value">;
+def warn_attribute_nonnull_no_pointers : Warning<
+ "'nonnull' attribute applied to function with no pointer arguments">;
+def warn_attribute_malloc_pointer_only : Warning<
+ "'malloc' attribute only applies to functions returning a pointer type">;
+def warn_transparent_union_nonpointer : Warning<
+ "'transparent_union' attribute support incomplete; only supported for "
+ "pointer unions">;
+def warn_attribute_sentinel_named_arguments : Warning<
+ "'sentinel' attribute requires named arguments">;
+def warn_attribute_sentinel_not_variadic : Warning<
+ "'sentinel' attribute only supported for variadic %select{functions|blocks}0">;
+def err_attribute_sentinel_less_than_zero : Error<
+ "'sentinel' parameter 1 less than zero">;
+def err_attribute_sentinel_not_zero_or_one : Error<
+ "'sentinel' parameter 2 not 0 or 1">;
+def err_attribute_cleanup_arg_not_found : Error<
+ "'cleanup' argument %0 not found">;
+def err_attribute_cleanup_arg_not_function : Error<
+ "'cleanup' argument %0 is not a function">;
+def err_attribute_cleanup_func_must_take_one_arg : Error<
+ "'cleanup' function %0 must take 1 parameter">;
+def err_attribute_cleanup_func_arg_incompatible_type : Error<
+ "'cleanup' function %0 parameter has type %1 which is incompatible with "
+ "type %2">;
+def err_attribute_regparm_wrong_platform : Error<
+ "'regparm' is not valid on this platform">;
+def err_attribute_regparm_invalid_number : Error<
+ "'regparm' parameter must be between 0 and %0 inclusive">;
+
+
+// Clang-Specific Attributes
+def warn_attribute_iboutlet : Warning<
+ "%0 attribute can only be applied to instance variables or properties">;
+def warn_attribute_ibaction: Warning<
+ "ibaction attribute can only be applied to Objective-C instance methods">;
+def err_attribute_overloadable_not_function : Error<
+ "'overloadable' attribute can only be applied to a function">;
+def err_attribute_overloadable_missing : Error<
+ "%select{overloaded function|redeclaration of}0 %1 must have the "
+ "'overloadable' attribute">;
+def note_attribute_overloadable_prev_overload : Note<
+ "previous overload of function is here">;
+def err_attribute_overloadable_no_prototype : Error<
+ "'overloadable' function %0 must have a prototype">;
+def warn_ns_attribute_wrong_return_type : Warning<
+ "%0 attribute only applies to %select{functions|methods}1 that "
+ "return %select{an Objective-C object|a pointer}2">;
+def warn_ns_attribute_wrong_parameter_type : Warning<
+ "%0 attribute only applies to %select{Objective-C object|pointer}1 "
+ "parameters">;
+
+// Function Parameter Semantic Analysis.
+def err_param_with_void_type : Error<"argument may not have 'void' type">;
+def err_void_only_param : Error<
+ "'void' must be the first and only parameter if specified">;
+def err_void_param_qualified : Error<
+ "'void' as parameter must not have type qualifiers">;
+def err_ident_list_in_fn_declaration : Error<
+ "a parameter list without types is only allowed in a function definition">;
+def ext_param_not_declared : Extension<
+ "parameter %0 was not declared, defaulting to type 'int'">;
+def err_param_typedef_of_void : Error<
+ "empty parameter list defined with a typedef of 'void' not allowed in C++">;
+def err_param_default_argument : Error<
+ "C does not support default arguments">;
+def err_param_default_argument_redefinition : Error<
+ "redefinition of default argument">;
+def err_param_default_argument_missing : Error<
+ "missing default argument on parameter">;
+def err_param_default_argument_missing_name : Error<
+ "missing default argument on parameter %0">;
+def err_param_default_argument_references_param : Error<
+ "default argument references parameter %0">;
+def err_param_default_argument_references_local : Error<
+ "default argument references local variable %0 of enclosing function">;
+def err_param_default_argument_references_this : Error<
+ "default argument references 'this'">;
+def err_param_default_argument_nonfunc : Error<
+ "default arguments can only be specified for parameters in a function "
+ "declaration">;
+def err_param_default_argument_template_redecl : Error<
+ "default arguments cannot be added to a function template that has already "
+ "been declared">;
+def err_param_default_argument_member_template_redecl : Error<
+ "default arguments cannot be added to an out-of-line definition of a member "
+ "of a %select{class template|class template partial specialization|nested "
+ "class in a template}0">;
+def err_uninitialized_member_for_assign : Error<
+ "cannot define the implicit default assignment operator for %0, because "
+ "non-static %select{reference|const}1 member %2 can't use default "
+ "assignment operator">;
+def note_first_required_here : Note<
+ "synthesized method is first required here">;
+def err_uninitialized_member_in_ctor : Error<
+ "%select{|implicit default }0constructor for %1 must explicitly initialize "
+ "the %select{reference|const}2 member %3">;
+
+def err_use_of_default_argument_to_function_declared_later : Error<
+ "use of default argument to function %0 that is declared later in class %1">;
+def note_default_argument_declared_here : Note<
+ "default argument declared here">;
+
+def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
+ "promoted type %0 of K&R function parameter is not compatible with the "
+ "parameter type %1 declared in a previous prototype">;
+
+
+// C++ Overloading Semantic Analysis.
+def err_ovl_diff_return_type : Error<
+ "functions that differ only in their return type cannot be overloaded">;
+def err_ovl_static_nonstatic_member : Error<
+ "static and non-static member functions with the same parameter types "
+ "cannot be overloaded">;
+
+def err_ovl_no_viable_function_in_call : Error<
+ "no matching function for call to %0">;
+def err_ovl_no_viable_member_function_in_call : Error<
+ "no matching member function for call to %0">;
+def err_ovl_ambiguous_call : Error<
+ "call to %0 is ambiguous">;
+def err_ovl_deleted_call : Error<
+ "call to %select{unavailable|deleted}0 function %1">;
+def err_ovl_ambiguous_member_call : Error<
+ "call to member function %0 is ambiguous">;
+def err_ovl_deleted_member_call : Error<
+ "call to %select{unavailable|deleted}0 member function %1">;
+def note_ovl_too_many_candidates : Note<
+ "remaining %0 candidate%s0 omitted; "
+ "pass -fshow-overloads=all to show them">;
+def note_ovl_candidate : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "is the implicit default constructor|"
+ "is the implicit copy constructor|"
+ "is the implicit copy assignment operator|"
+ "is an inherited constructor}0%1">;
+
+def warn_init_pointer_from_false : Warning<
+ "initialization of pointer of type %0 from literal 'false'">,
+ InGroup<BoolConversions>;
+
+def note_ovl_candidate_inherited_constructor : Note<"inherited from here">;
+def note_ovl_candidate_bad_deduction : Note<
+ "candidate template ignored: failed template argument deduction">;
+def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
+ "couldn't infer template argument %0">;
+def note_ovl_candidate_inconsistent_deduction : Note<
+ "candidate template ignored: deduced conflicting %select{types|values|"
+ "templates}0 for parameter %1 (%2 vs. %3)">;
+def note_ovl_candidate_explicit_arg_mismatch_named : Note<
+ "candidate template ignored: invalid explicitly-specified argument "
+ "for template parameter %0">;
+def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
+ "candidate template ignored: invalid explicitly-specified argument "
+ "for %ordinal0 template parameter">;
+def note_ovl_candidate_instantiation_depth : Note<
+ "candidate template ignored: substitution exceeded maximum template "
+ "instantiation depth">;
+def note_ovl_candidate_underqualified : Note<
+ "candidate template ignored: can't deduce a type for %0 which would "
+ "make %2 equal %1">;
+def note_ovl_candidate_substitution_failure : Note<
+ "candidate template ignored: substitution failure %0">;
+
+// Note that we don't treat templates differently for this diagnostic.
+def note_ovl_candidate_arity : Note<"candidate "
+ "%select{function|function|constructor|function|function|constructor|"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0 %select{|template }1"
+ "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
+ "%plural{1:was|:were}4 provided">;
+
+def note_ovl_candidate_deleted : Note<
+ "candidate %select{function|function|constructor|"
+ "function |function |constructor ||||constructor (inherited)}0%1 "
+ "has been explicitly %select{made unavailable|deleted}2">;
+
+// Giving the index of the bad argument really clutters this message, and
+// it's relatively unimportant because 1) it's generally obvious which
+// argument(s) are of the given object type and 2) the fix is usually
+// to complete the type, which doesn't involve changes to the call line
+// anyway. If people complain, we can change it.
+def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 "
+ "not viable: cannot convert argument of incomplete type %2 to %3">;
+def note_ovl_candidate_bad_overload : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: no overload of %3 matching %2 for %ordinal4 argument">;
+def note_ovl_candidate_bad_conv : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: no known conversion from %2 to %3 for "
+ "%select{%ordinal5 argument|object argument}4">;
+def note_ovl_candidate_bad_addrspace : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
+ "%select{%ordinal6|'this'}5 argument (%2) is in "
+ "address space %3, but parameter must be in address space %4">;
+def note_ovl_candidate_bad_cvr_this : Note<"candidate "
+ "%select{|function|||function||||"
+ "function (the implicit copy assignment operator)|}0 not viable: "
+ "'this' argument has type %2, but method is not marked "
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
+ "volatile or restrict|const, volatile, or restrict}3">;
+def note_ovl_candidate_bad_cvr : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
+ "%ordinal4 argument (%2) would lose "
+ "%select{const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}3 qualifier"
+ "%select{||s||s|s|s}3">;
+def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: cannot %select{convert from|convert from|bind}2 "
+ "%select{base class pointer|superclass|base class object of type}2 %3 to "
+ "%select{derived class pointer|subclass|derived class reference}2 %4 for "
+ "%ordinal5 argument">;
+
+def note_ambiguous_type_conversion: Note<
+ "because of ambiguity in conversion of %0 to %1">;
+def note_ovl_builtin_binary_candidate : Note<
+ "built-in candidate %0">;
+def note_ovl_builtin_unary_candidate : Note<
+ "built-in candidate %0">;
+def err_ovl_no_viable_function_in_init : Error<
+ "no matching constructor for initialization of %0">;
+def err_ovl_no_conversion_in_cast : Error<
+ "cannot convert %1 to %2 without a conversion operator">;
+def err_ovl_no_viable_conversion_in_cast : Error<
+ "no matching conversion for %select{|static_cast|reinterpret_cast|"
+ "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
+def err_ovl_ambiguous_conversion_in_cast : Error<
+ "ambiguous conversion for %select{|static_cast|reinterpret_cast|"
+ "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
+def err_ovl_deleted_conversion_in_cast : Error<
+ "%select{|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 uses deleted function">;
+def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
+def err_ref_init_ambiguous : Error<
+ "reference initialization of type %0 with initializer of type %1 is ambiguous">;
+def err_ovl_deleted_init : Error<
+ "call to %select{unavailable|deleted}0 constructor of %1">;
+def err_ovl_ambiguous_oper_unary : Error<
+ "use of overloaded operator '%0' is ambiguous (operand type %1)">;
+def err_ovl_ambiguous_oper_binary : Error<
+ "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
+def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
+def err_ovl_deleted_oper : Error<
+ "overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
+def err_ovl_no_viable_subscript :
+ Error<"no viable overloaded operator[] for type %0">;
+def err_ovl_no_oper :
+ Error<"type %0 does not provide a %select{subscript|call}1 operator">;
+def err_ovl_unresolvable :
+ Error<"cannot resolve overloaded function from context">;
+
+
+def err_ovl_no_viable_object_call : Error<
+ "no matching function for call to object of type %0">;
+def err_ovl_ambiguous_object_call : Error<
+ "call to object of type %0 is ambiguous">;
+def err_ovl_deleted_object_call : Error<
+ "call to %select{unavailable|deleted}0 function call operator in type %1">;
+def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
+def err_member_call_without_object : Error<
+ "call to non-static member function without an object argument">;
+
+// C++ Address of Overloaded Function
+def err_addr_ovl_no_viable : Error<
+ "address of overloaded function %0 does not match required type %1">;
+def err_addr_ovl_ambiguous : Error<
+ "address of overloaded function %0 is ambiguous">;
+def err_addr_ovl_not_func_ptrref : Error<
+ "address of overloaded function %0 cannot be converted to type %1">;
+def err_addr_ovl_no_qualifier : Error<
+ "can't form member pointer of type %0 without '&' and class name">;
+
+// C++ Template Declarations
+def err_template_param_shadow : Error<
+ "declaration of %0 shadows template parameter">;
+def note_template_param_here : Note<"template parameter is declared here">;
+def warn_template_export_unsupported : Warning<
+ "exported templates are unsupported">;
+def err_template_outside_namespace_or_class_scope : Error<
+ "templates can only be declared in namespace or class scope">;
+def err_template_linkage : Error<"templates must have C++ linkage">;
+def err_template_typedef : Error<"a typedef cannot be a template">;
+def err_template_unnamed_class : Error<
+ "cannot declare a class template with no name">;
+def err_template_param_list_different_arity : Error<
+ "%select{too few|too many}0 template parameters in template "
+ "%select{|template parameter }1redeclaration">;
+def note_template_param_list_different_arity : Note<
+ "%select{too few|too many}0 template parameters in template template "
+ "argument">;
+def note_template_prev_declaration : Note<
+ "previous template %select{declaration|template parameter}0 is here">;
+def err_template_param_different_kind : Error<
+ "template parameter has a different kind in template "
+ "%select{|template parameter }0redeclaration">;
+def note_template_param_different_kind : Note<
+ "template parameter has a different kind in template argument">;
+
+def err_template_nontype_parm_different_type : Error<
+ "template non-type parameter has a different type %0 in template "
+ "%select{|template parameter }1redeclaration">;
+
+def note_template_nontype_parm_different_type : Note<
+ "template non-type parameter has a different type %0 in template argument">;
+def note_template_nontype_parm_prev_declaration : Note<
+ "previous non-type template parameter with type %0 is here">;
+def err_template_nontype_parm_bad_type : Error<
+ "a non-type template parameter cannot have type %0">;
+def err_template_param_default_arg_redefinition : Error<
+ "template parameter redefines default argument">;
+def note_template_param_prev_default_arg : Note<
+ "previous default template argument defined here">;
+def err_template_param_default_arg_missing : Error<
+ "template parameter missing a default argument">;
+def ext_template_parameter_default_in_function_template : ExtWarn<
+ "default template arguments for a function template are a C++0x extension">,
+ InGroup<CXX0x>;
+def err_template_parameter_default_template_member : Error<
+ "cannot add a default template argument to the definition of a member of a "
+ "class template">;
+def err_template_parameter_default_friend_template : Error<
+ "default template argument not permitted on a friend template">;
+def err_template_template_parm_no_parms : Error<
+ "template template parameter must have its own template parameters">;
+
+def err_template_variable : Error<"variable %0 declared as a template">;
+def err_template_variable_noparams : Error<
+ "extraneous 'template<>' in declaration of variable %0">;
+def err_template_tag_noparams : Error<
+ "extraneous 'template<>' in declaration of %0 %1">;
+def err_template_decl_ref : Error<
+ "cannot refer to class template %0 without a template argument list">;
+
+// C++ Template Argument Lists
+def err_template_missing_args : Error<
+ "use of class template %0 requires template arguments">;
+def err_template_arg_list_different_arity : Error<
+ "%select{too few|too many}0 template arguments for "
+ "%select{class template|function template|template template parameter"
+ "|template}1 %2">;
+def note_template_decl_here : Note<"template is declared here">;
+def note_member_of_template_here : Note<"member is declared here">;
+def err_template_arg_must_be_type : Error<
+ "template argument for template type parameter must be a type">;
+def err_template_arg_must_be_expr : Error<
+ "template argument for non-type template parameter must be an expression">;
+def err_template_arg_nontype_ambig : Error<
+ "template argument for non-type template parameter is treated as type %0">;
+def err_template_arg_must_be_template : Error<
+ "template argument for template template parameter must be a class template">;
+def ext_template_arg_local_type : ExtWarn<
+ "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
+def ext_template_arg_unnamed_type : ExtWarn<
+ "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
+def note_template_unnamed_type_here : Note<
+ "unnamed type used in template argument was declared here">;
+def err_template_arg_overload_type : Error<
+ "template argument is the type of an unresolved overloaded function">;
+def err_template_arg_not_class_template : Error<
+ "template argument does not refer to a class template or template "
+ "template parameter">;
+def note_template_arg_refers_here_func : Note<
+ "template argument refers to function template %0, here">;
+def err_template_arg_template_params_mismatch : Error<
+ "template template argument has different template parameters than its "
+ "corresponding template template parameter">;
+def err_template_arg_not_integral_or_enumeral : Error<
+ "non-type template argument of type %0 must have an integral or enumeration"
+ " type">;
+def err_template_arg_not_ice : Error<
+ "non-type template argument of type %0 is not an integral constant "
+ "expression">;
+def err_deduced_non_type_template_arg_type_mismatch : Error<
+ "deduced non-type template argument does not have the same type as the "
+ "its corresponding template parameter (%0 vs %1)">;
+def err_template_arg_not_convertible : Error<
+ "non-type template argument of type %0 cannot be converted to a value "
+ "of type %1">;
+def warn_template_arg_negative : Warning<
+ "non-type template argument with value '%0' converted to '%1' for unsigned "
+ "template parameter of type %2">, InGroup<Conversion>, DefaultIgnore;
+def warn_template_arg_too_large : Warning<
+ "non-type template argument value '%0' truncated to '%1' for "
+ "template parameter of type %2">, InGroup<Conversion>, DefaultIgnore;
+def err_template_arg_no_ref_bind : Error<
+ "non-type template parameter of reference type %0 cannot bind to template "
+ "argument of type %1">;
+def err_template_arg_ref_bind_ignores_quals : Error<
+ "reference binding of non-type template parameter of type %0 to template "
+ "argument of type %1 ignores qualifiers">;
+def err_template_arg_not_decl_ref : Error<
+ "non-type template argument does not refer to any declaration">;
+def err_template_arg_not_object_or_func_form : Error<
+ "non-type template argument does not directly refer to an object or "
+ "function">;
+def err_template_arg_not_address_of : Error<
+ "non-type template argument for template parameter of pointer type %0 must "
+ "have its address taken">;
+def err_template_arg_address_of_non_pointer : Error<
+ "address taken in non-type template argument for template parameter of "
+ "reference type %0">;
+def err_template_arg_reference_var : Error<
+ "non-type template argument of reference type %0 is not an object">;
+def err_template_arg_field : Error<
+ "non-type template argument refers to non-static data member %0">;
+def err_template_arg_method : Error<
+ "non-type template argument refers to non-static member function %0">;
+def err_template_arg_function_not_extern : Error<
+ "non-template argument refers to function %0 with internal linkage">;
+def err_template_arg_object_not_extern : Error<
+ "non-template argument refers to object %0 that does not have external "
+ "linkage">;
+def note_template_arg_internal_object : Note<
+ "non-template argument refers to %select{function|object}0 here">;
+def note_template_arg_refers_here : Note<"non-template argument refers here">;
+def err_template_arg_not_object_or_func : Error<
+ "non-type template argument does not refer to an object or function">;
+def err_template_arg_not_pointer_to_member_form : Error<
+ "non-type template argument is not a pointer to member constant">;
+def ext_template_arg_extra_parens : ExtWarn<
+ "address non-type template argument cannot be surrounded by parentheses">;
+def err_pointer_to_member_type : Error<
+ "invalid use of pointer to member type after %select{.*|->*}0">;
+def err_pointer_to_member_call_drops_quals : Error<
+ "call to pointer to member function of type %0 drops '%1' qualifier%s2">;
+def err_pointer_to_member_oper_value_classify: Error<
+ "pointer-to-member function type %0 can only be called on an "
+ "%select{rvalue|lvalue}1">;
+
+// C++ template specialization
+def err_template_spec_unknown_kind : Error<
+ "can only provide an explicit specialization for a class template, function "
+ "template, or a member function, static data member, or member class of a "
+ "class template">;
+def note_specialized_entity : Note<
+ "explicitly specialized declaration is here">;
+def err_template_spec_decl_function_scope : Error<
+ "explicit specialization of %0 in function scope">;
+def err_template_spec_decl_class_scope : Error<
+ "explicit specialization of %0 in class scope">;
+def err_template_spec_decl_friend : Error<
+ "cannot declare an explicit specialization in a friend">;
+def err_template_spec_decl_out_of_scope_global : Error<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in the global scope">;
+def ext_template_spec_decl_out_of_scope_global : ExtWarn<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in the global scope; accepted as a C++0x extension">,
+ InGroup<CXX0x>;
+def err_template_spec_decl_out_of_scope : Error<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in namespace %2">;
+def ext_template_spec_decl_out_of_scope : ExtWarn<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must "
+ "originally be declared in namespace %2; accepted as a C++0x extension">,
+ InGroup<CXX0x>;
+def err_template_spec_redecl_out_of_scope : Error<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 not in a "
+ "namespace enclosing %2">;
+def err_template_spec_redecl_global_scope : Error<
+ "%select{class template|class template partial|function template|member "
+ "function|static data member|member class}0 specialization of %1 must occur "
+ "at global scope">;
+def err_spec_member_not_instantiated : Error<
+ "specialization of member %q0 does not specialize an instantiated member">;
+def note_specialized_decl : Note<"attempt to specialize declaration here">;
+def err_specialization_after_instantiation : Error<
+ "explicit specialization of %0 after instantiation">;
+def note_instantiation_required_here : Note<
+ "%select{implicit|explicit}0 instantiation first required here">;
+def err_template_spec_friend : Error<
+ "template specialization declaration cannot be a friend">;
+def err_template_spec_default_arg : Error<
+ "default argument not permitted on an explicit "
+ "%select{instantiation|specialization}0 of function %1">;
+def err_not_class_template_specialization : Error<
+ "cannot specialize a %select{dependent template|template template "
+ "parameter}0">;
+
+// C++ class template specializations and out-of-line definitions
+def err_template_spec_needs_header : Error<
+ "template specialization requires 'template<>'">;
+def err_template_spec_needs_template_parameters : Error<
+ "template specialization or definition requires a template parameter list "
+ "corresponding to the nested type %0">;
+def err_template_param_list_matches_nontemplate : Error<
+ "template parameter list matching the non-templated nested type %0 should "
+ "be empty ('template<>')">;
+def err_template_spec_extra_headers : Error<
+ "extraneous template parameter list in template specialization or "
+ "out-of-line template definition">;
+def warn_template_spec_extra_headers : Warning<
+ "extraneous template parameter list in template specialization">;
+def note_explicit_template_spec_does_not_need_header : Note<
+ "'template<>' header not required for explicitly-specialized class %0 "
+ "declared here">;
+def err_template_qualified_declarator_no_match : Error<
+ "nested name specifier '%0' for declaration does not refer into a class, "
+ "class template or class template partial specialization">;
+
+// C++ Class Template Partial Specialization
+def err_default_arg_in_partial_spec : Error<
+ "default template argument in a class template partial specialization">;
+def err_dependent_non_type_arg_in_partial_spec : Error<
+ "non-type template argument depends on a template parameter of the "
+ "partial specialization">;
+def err_dependent_typed_non_type_arg_in_partial_spec : Error<
+ "non-type template argument specializes a template parameter with "
+ "dependent type %0">;
+def err_partial_spec_args_match_primary_template : Error<
+ "class template partial specialization does not specialize any template "
+ "argument; to %select{declare|define}0 the primary template, remove the "
+ "template argument list">;
+def warn_partial_specs_not_deducible : Warning<
+ "class template partial specialization contains "
+ "%select{a template parameter|template parameters}0 that can not be "
+ "deduced; this partial specialization will never be used">;
+def note_partial_spec_unused_parameter : Note<
+ "non-deducible template parameter %0">;
+def err_partial_spec_ordering_ambiguous : Error<
+ "ambiguous partial specializations of %0">;
+def note_partial_spec_match : Note<"partial specialization matches %0">;
+def err_partial_spec_redeclared : Error<
+ "class template partial specialization %0 cannot be redeclared">;
+def note_prev_partial_spec_here : Note<
+ "previous declaration of class template partial specialization %0 is here">;
+def err_partial_spec_fully_specialized : Error<
+ "partial specialization of %0 does not use any of its template parameters">;
+
+// C++ Function template specializations
+def err_function_template_spec_no_match : Error<
+ "no function template matches function template specialization %0">;
+def err_function_template_spec_ambiguous : Error<
+ "function template specialization %0 ambiguously refers to more than one "
+ "function template; explicitly specify%select{|additional }1 template "
+ "arguments to identify a particular function template">;
+def note_function_template_spec_matched : Note<
+ "function template matches specialization %0">;
+def err_function_template_partial_spec : Error<
+ "function template partial specialization is not allowed">;
+
+// C++ Template Instantiation
+def err_template_recursion_depth_exceeded : Error<
+ "recursive template instantiation exceeded maximum depth of %0">,
+ DefaultFatal, NoSFINAE;
+def note_template_recursion_depth : Note<
+ "use -ftemplate-depth-N to increase recursive template instantiation depth">;
+
+def err_template_instantiate_undefined : Error<
+ "%select{implicit|explicit}0 instantiation of undefined template %1">;
+def err_implicit_instantiate_member_undefined : Error<
+ "implicit instantiation of undefined member %0">;
+def note_template_class_instantiation_here : Note<
+ "in instantiation of template class %0 requested here">;
+def note_template_member_class_here : Note<
+ "in instantiation of member class %0 requested here">;
+def note_template_member_function_here : Note<
+ "in instantiation of member function %q0 requested here">;
+def note_function_template_spec_here : Note<
+ "in instantiation of function template specialization %q0 requested here">;
+def note_template_static_data_member_def_here : Note<
+ "in instantiation of static data member %q0 requested here">;
+
+def note_default_arg_instantiation_here : Note<
+ "in instantiation of default argument for '%0' required here">;
+def note_default_function_arg_instantiation_here : Note<
+ "in instantiation of default function argument expression "
+ "for '%0' required here">;
+def note_explicit_template_arg_substitution_here : Note<
+ "while substituting explicitly-specified template arguments into function "
+ "template %0 %1">;
+def note_function_template_deduction_instantiation_here : Note<
+ "while substituting deduced template arguments into function template %0 "
+ "%1">;
+def note_partial_spec_deduct_instantiation_here : Note<
+ "during template argument deduction for class template partial "
+ "specialization %0 %1">;
+def note_prior_template_arg_substitution : Note<
+ "while substituting prior template arguments into %select{non-type|template}0"
+ " template parameter%1 %2">;
+def note_template_default_arg_checking : Note<
+ "while checking a default template argument used here">;
+def note_instantiation_contexts_suppressed : Note<
+ "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
+ "see all)">;
+
+def err_field_instantiates_to_function : Error<
+ "data member instantiated with function type %0">;
+def err_variable_instantiates_to_function : Error<
+ "%select{variable|static data member}0 instantiated with function type %1">;
+def err_nested_name_spec_non_tag : Error<
+ "type %0 cannot be used prior to '::' because it has no members">;
+
+// C++ Explicit Instantiation
+def err_explicit_instantiation_duplicate : Error<
+ "duplicate explicit instantiation of %0">;
+def note_previous_explicit_instantiation : Note<
+ "previous explicit instantiation is here">;
+def ext_explicit_instantiation_after_specialization : Extension<
+ "explicit instantiation of %0 that occurs after an explicit "
+ "specialization will be ignored (C++0x extension)">,
+ InGroup<CXX0x>;
+def note_previous_template_specialization : Note<
+ "previous template specialization is here">;
+def err_explicit_instantiation_enum : Error<
+ "explicit instantiation of enumeration type %0">;
+def err_explicit_instantiation_nontemplate_type : Error<
+ "explicit instantiation of non-templated type %0">;
+def note_nontemplate_decl_here : Note<
+ "non-templated declaration is here">;
+def err_explicit_instantiation_in_class : Error<
+ "explicit instantiation of %0 in class scope">;
+def err_explicit_instantiation_out_of_scope : Error<
+ "explicit instantiation of %0 not in a namespace enclosing %1">;
+def err_explicit_instantiation_must_be_global : Error<
+ "explicit instantiation of %0 must occur at global scope">;
+def warn_explicit_instantiation_out_of_scope_0x : Warning<
+ "explicit instantiation of %0 not in a namespace enclosing %1">,
+ InGroup<DiagGroup<"-Wc++0x-compat"> >;
+def warn_explicit_instantiation_must_be_global_0x : Warning<
+ "explicit instantiation of %0 must occur at global scope">,
+ InGroup<DiagGroup<"-Wc++0x-compat"> >;
+
+def err_explicit_instantiation_requires_name : Error<
+ "explicit instantiation declaration requires a name">;
+def err_explicit_instantiation_of_typedef : Error<
+ "explicit instantiation of typedef %0">;
+def err_explicit_instantiation_not_known : Error<
+ "explicit instantiation of %0 does not refer to a function template, member "
+ "function, member class, or static data member">;
+def note_explicit_instantiation_here : Note<
+ "explicit instantiation refers here">;
+def err_explicit_instantiation_data_member_not_instantiated : Error<
+ "explicit instantiation refers to static data member %q0 that is not an "
+ "instantiation">;
+def err_explicit_instantiation_member_function_not_instantiated : Error<
+ "explicit instantiation refers to member function %q0 that is not an "
+ "instantiation">;
+def err_explicit_instantiation_ambiguous : Error<
+ "partial ordering for explicit instantiation of %0 is ambiguous">;
+def note_explicit_instantiation_candidate : Note<
+ "explicit instantiation candidate function template here %0">;
+def err_explicit_instantiation_inline : Error<
+ "explicit instantiation cannot be 'inline'">;
+def ext_explicit_instantiation_without_qualified_id : ExtWarn<
+ "qualifier in explicit instantiation of %q0 requires a template-id "
+ "(a typedef is not permitted)">;
+def err_explicit_instantiation_unqualified_wrong_namespace : Error<
+ "explicit instantiation of %q0 must occur in %1">;
+def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
+ "explicit instantiation of %q0 must occur in %1">,
+ InGroup<DiagGroup<"c++0x-compat"> >;
+def err_explicit_instantiation_undefined_member : Error<
+ "explicit instantiation of undefined %select{member class|member function|"
+ "static data member}0 %1 of class template %2">;
+def err_explicit_instantiation_undefined_func_template : Error<
+ "explicit instantiation of undefined function template %0">;
+def err_explicit_instantiation_declaration_after_definition : Error<
+ "explicit instantiation declaration (with 'extern') follows explicit "
+ "instantiation definition (without 'extern')">;
+def note_explicit_instantiation_definition_here : Note<
+ "explicit instantiation definition is here">;
+
+// C++ typename-specifiers
+def err_typename_nested_not_found : Error<"no type named %0 in %1">;
+def err_typename_nested_not_type : Error<
+ "typename specifier refers to non-type member %0 in %1">;
+def note_typename_refers_here : Note<
+ "referenced member %0 is declared here">;
+def err_typename_missing : Error<
+ "missing 'typename' prior to dependent type name '%0%1'">;
+def ext_typename_outside_of_template : ExtWarn<
+ "'typename' occurs outside of a template">, InGroup<CXX0x>;
+def err_typename_refers_to_using_value_decl : Error<
+ "typename specifier refers to a dependent using declaration for a value "
+ "%0 in %1">;
+def note_using_value_decl_missing_typename : Note<
+ "add 'typename' to treat this using declaration as a type">;
+
+def err_template_kw_refers_to_non_template : Error<
+ "%0 following the 'template' keyword does not refer to a template">;
+def err_template_kw_refers_to_function_template : Error<
+ "%0 following the 'template' keyword refers to a function template">;
+def err_template_kw_refers_to_class_template : Error<
+ "'%0%1' instantiated to a class template, not a function template">;
+def note_referenced_class_template : Error<
+ "class template declared here">;
+def err_template_kw_missing : Error<
+ "missing 'template' keyword prior to dependent template name '%0%1'">;
+def ext_template_outside_of_template : ExtWarn<
+ "'template' keyword outside of a template">, InGroup<CXX0x>;
+
+// C++0x Variadic Templates
+def err_template_param_pack_default_arg : Error<
+ "template parameter pack cannot have a default argument">;
+def err_template_param_pack_must_be_last_template_parameter : Error<
+ "template parameter pack must be the last template parameter">;
+
+def err_template_parameter_pack_non_pack : Error<
+ "%select{template type|non-type template|template template}0 parameter"
+ "%select{| pack}1 conflicts with previous %select{template type|"
+ "non-type template|template template}0 parameter%select{ pack|}1">;
+def note_template_parameter_pack_non_pack : Note<
+ "%select{template type|non-type template|template template}0 parameter"
+ "%select{| pack}1 does not match %select{template type|non-type template"
+ "|template template}0 parameter%select{ pack|}1 in template argument">;
+def note_template_parameter_pack_here : Note<
+ "previous %select{template type|non-type template|template template}0 "
+ "parameter%select{| pack}1 declared here">;
+
+def err_unexpanded_parameter_pack_0 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains an unexpanded parameter pack">;
+def err_unexpanded_parameter_pack_1 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter pack %1">;
+def err_unexpanded_parameter_pack_2 : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter packs %1 and %2">;
+def err_unexpanded_parameter_pack_3_or_more : Error<
+ "%select{expression|base type|declaration type|data member type|bit-field "
+ "size|static assertion|fixed underlying type|enumerator value|"
+ "using declaration|friend declaration|qualifier|initializer|default argument|"
+ "non-type template parameter type|exception type|partial specialization}0 "
+ "contains unexpanded parameter packs %1, %2, ...">;
+
+def err_pack_expansion_without_parameter_packs : Error<
+ "pack expansion does not contain any unexpanded parameter packs">;
+def err_pack_expansion_length_conflict : Error<
+ "pack expansion contains parameter packs %0 and %1 that have different "
+ "lengths (%2 vs. %3)">;
+def err_pack_expansion_length_conflict_multilevel : Error<
+ "pack expansion contains parameter pack %0 that has a different "
+ "length (%1 vs. %2) from outer parameter packs">;
+def err_pack_expansion_member_init : Error<
+ "pack expansion for initialization of member %0">;
+
+def err_function_parameter_pack_without_parameter_packs : Error<
+ "type %0 of function parameter pack does not contain any unexpanded "
+ "parameter packs">;
+def err_ellipsis_in_declarator_not_parameter : Error<
+ "only function and template parameters can be parameter packs">;
+
+def err_sizeof_pack_no_pack_name : Error<
+ "%0 does not refer to the name of a parameter pack">;
+
+def err_unexpected_typedef : Error<
+ "unexpected type name %0: expected expression">;
+def err_unexpected_namespace : Error<
+ "unexpected namespace name %0: expected expression">;
+def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
+def note_dependent_var_use : Note<"must qualify identifier to find this "
+ "declaration in dependent base class">;
+def err_undeclared_use : Error<"use of undeclared %0">;
+def warn_deprecated : Warning<"%0 is deprecated">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_fwdclass_message : Warning<
+ "%0 maybe deprecated because receiver type is unknown">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_def : Warning<
+ "Implementing deprecated %select{method|class|category}0">,
+ InGroup<DeprecatedImplementations>, DefaultIgnore;
+def err_unavailable : Error<"%0 is unavailable">;
+def err_unavailable_message : Error<"%0 is unavailable: %1">;
+def warn_unavailable_fwdclass_message : Warning<
+ "%0 maybe unavailable because receiver type is unknown">;
+def note_unavailable_here : Note<
+ "function has been explicitly marked %select{unavailable|deleted|deprecated}0 here">;
+def warn_not_enough_argument : Warning<
+ "not enough variable arguments in %0 declaration to fit a sentinel">;
+def warn_missing_sentinel : Warning <
+ "missing sentinel in %select{function call|method dispatch|block call}0">;
+def note_sentinel_here : Note<
+ "%select{function|method|block}0 has been explicitly marked sentinel here">;
+def warn_missing_prototype : Warning<
+ "no previous prototype for function %0">,
+ InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
+def err_redefinition : Error<"redefinition of %0">;
+def err_definition_of_implicitly_declared_member : Error<
+ "definition of implicitly declared %select{constructor|copy constructor|"
+ "copy assignment operator|destructor}1">;
+def err_redefinition_extern_inline : Error<
+ "redefinition of a 'extern inline' function %0 is not supported in "
+ "%select{C99 mode|C++}1">;
+
+// This should eventually be an error.
+def warn_undefined_internal : Warning<
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">;
+def note_used_here : Note<"used here">;
+
+def warn_redefinition_of_typedef : Warning<
+ "redefinition of typedef %0 is invalid in C">,
+ InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
+
+def err_inline_declaration_block_scope : Error<
+ "inline declaration of %0 not allowed in block scope">;
+def err_static_non_static : Error<
+ "static declaration of %0 follows non-static declaration">;
+def err_non_static_static : Error<
+ "non-static declaration of %0 follows static declaration">;
+def err_extern_non_extern : Error<
+ "extern declaration of %0 follows non-extern declaration">;
+def err_non_extern_extern : Error<
+ "non-extern declaration of %0 follows extern declaration">;
+def err_non_thread_thread : Error<
+ "non-thread-local declaration of %0 follows thread-local declaration">;
+def err_thread_non_thread : Error<
+ "thread-local declaration of %0 follows non-thread-local declaration">;
+def err_redefinition_different_type : Error<
+ "redefinition of %0 with a different type">;
+def err_redefinition_different_kind : Error<
+ "redefinition of %0 as different kind of symbol">;
+def err_redefinition_different_typedef : Error<
+ "typedef redefinition with different types (%0 vs %1)">;
+def err_tag_reference_non_tag : Error<
+ "elaborated type refers to %select{a non-tag type|a typedef|a template}0">;
+def err_tag_reference_conflict : Error<
+ "implicit declaration introduced by elaborated type conflicts with "
+ "%select{a declaration|a typedef|a template}0 of the same name">;
+def err_dependent_tag_decl : Error<
+ "%select{declaration|definition}0 of %select{struct|union|class|enum}1 "
+ "in a dependent scope">;
+def err_tag_definition_of_typedef : Error<
+ "definition of type %0 conflicts with typedef of the same name">;
+def err_conflicting_types : Error<"conflicting types for %0">;
+def err_nested_redefinition : Error<"nested redefinition of %0">;
+def err_use_with_wrong_tag : Error<
+ "use of %0 with tag type that does not match previous declaration">;
+def warn_struct_class_tag_mismatch : Warning<
+ "%select{struct|class}0 %select{|template}1 %2 was previously declared "
+ "as a %select{class|struct}0 %select{|template}1">,
+ InGroup<MismatchedTags>, DefaultIgnore;
+def ext_forward_ref_enum : Extension<
+ "ISO C forbids forward references to 'enum' types">;
+def err_forward_ref_enum : Error<
+ "ISO C++ forbids forward references to 'enum' types">;
+def ext_ms_forward_ref_enum : Extension<
+ "forward references to 'enum' types are a Microsoft extension">, InGroup<Microsoft>;
+def ext_forward_ref_enum_def : Extension<
+ "redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNU>;
+
+def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
+def err_duplicate_member : Error<"duplicate member %0">;
+def err_misplaced_ivar : Error<
+ "ivars may not be placed in %select{categories|class extension}0">;
+def ext_enum_value_not_int : Extension<
+ "ISO C restricts enumerator values to range of 'int' (%0 is too "
+ "%select{small|large}1)">;
+def warn_enum_too_large : Warning<
+ "enumeration values exceed range of largest integer">;
+def warn_enumerator_too_large : Warning<
+ "enumerator value %0 is not representable in the largest integer type">;
+
+def warn_illegal_constant_array_size : Extension<
+ "size of static array must be an integer constant expression">;
+def err_vm_decl_in_file_scope : Error<
+ "variably modified type declaration not allowed at file scope">;
+def err_vm_decl_has_extern_linkage : Error<
+ "variably modified type declaration can not have 'extern' linkage">;
+def err_typecheck_field_variable_size : Error<
+ "fields must have a constant size: 'variable length array in structure' "
+ "extension will never be supported">;
+def err_vm_func_decl : Error<
+ "function declaration cannot have variably modified type">;
+def err_array_too_large : Error<
+ "array is too large (%0 elements)">;
+
+// -Wpadded, -Wpacked
+def warn_padded_struct_field : Warning<
+ "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
+ "to align %5">, InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_anon_field : Warning<
+ "padding %select{struct|class}0 %1 with %2 %select{byte|bit}3%select{|s}4 "
+ "to align anonymous bit-field">, InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_size : Warning<
+ "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
+ "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
+def warn_unnecessary_packed : Warning<
+ "packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
+
+def err_typecheck_negative_array_size : Error<"array size is negative">;
+def warn_typecheck_function_qualifiers : Warning<
+ "qualifier on function type %0 has unspecified behavior">;
+def err_typecheck_invalid_restrict_not_pointer : Error<
+ "restrict requires a pointer or reference (%0 is invalid)">;
+def err_typecheck_invalid_restrict_not_pointer_noarg : Error<
+ "restrict requires a pointer or reference">;
+def err_typecheck_invalid_restrict_invalid_pointee : Error<
+ "pointer to function type %0 may not be 'restrict' qualified">;
+def ext_typecheck_zero_array_size : Extension<
+ "zero size arrays are an extension">;
+def err_typecheck_zero_array_size : Error<
+ "zero-length arrays are not permitted in C++">;
+def err_at_least_one_initializer_needed_to_size_array : Error<
+ "at least one initializer value required to size array">;
+def err_array_size_non_int : Error<"size of array has non-integer type %0">;
+def err_init_element_not_constant : Error<
+ "initializer element is not a compile-time constant">;
+def err_block_extern_cant_init : Error<
+ "'extern' variable cannot have an initializer">;
+def warn_extern_init : Warning<"'extern' variable has an initializer">;
+def err_variable_object_no_init : Error<
+ "variable-sized object may not be initialized">;
+def err_array_init_list_required : Error<
+ "initialization with '{...}' expected for array">;
+def err_excess_initializers : Error<
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+def warn_excess_initializers : ExtWarn<
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+def err_excess_initializers_in_char_array_initializer : Error<
+ "excess elements in char array initializer">;
+def warn_excess_initializers_in_char_array_initializer : ExtWarn<
+ "excess elements in char array initializer">;
+def warn_initializer_string_for_char_array_too_long : ExtWarn<
+ "initializer-string for char array is too long">;
+def warn_missing_field_initializers : Warning<
+ "missing field '%0' initializer">,
+ InGroup<MissingFieldInitializers>, DefaultIgnore;
+def warn_braces_around_scalar_init : Warning<
+ "braces around scalar initializer">;
+def warn_many_braces_around_scalar_init : ExtWarn<
+ "too many braces around scalar initializer">;
+def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
+def err_illegal_initializer : Error<
+ "illegal initializer (only variables can be initialized)">;
+def err_illegal_initializer_type : Error<"illegal initializer type %0">;
+def err_init_objc_class : Error<
+ "cannot initialize Objective-C class type %0">;
+def err_implicit_empty_initializer : Error<
+ "initializer for aggregate with no elements requires explicit braces">;
+def err_bitfield_has_negative_width : Error<
+ "bit-field %0 has negative width (%1)">;
+def err_anon_bitfield_has_negative_width : Error<
+ "anonymous bit-field has negative width (%0)">;
+def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">;
+def err_bitfield_width_exceeds_type_size : Error<
+ "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">;
+def err_anon_bitfield_width_exceeds_type_size : Error<
+ "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">;
+
+// Used by C++ which allows bit-fields that are wider than the type.
+def warn_bitfield_width_exceeds_type_size: Warning<
+ "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be "
+ "truncated to %2 bits">;
+def warn_anon_bitfield_width_exceeds_type_size : Warning<
+ "size of anonymous bit-field (%0 bits) exceeds size of its type; value will "
+ "be truncated to %1 bits">;
+
+def warn_missing_braces : Warning<
+ "suggest braces around initialization of subobject">,
+ InGroup<DiagGroup<"missing-braces">>, DefaultIgnore;
+
+def err_redefinition_of_label : Error<"redefinition of label %0">;
+def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def warn_unused_label : Warning<"unused label %0">,
+ InGroup<UnusedLabel>, DefaultIgnore;
+
+def err_goto_into_protected_scope : Error<"goto into protected scope">;
+def err_switch_into_protected_scope : Error<
+ "switch case is in protected scope">;
+def err_indirect_goto_without_addrlabel : Error<
+ "indirect goto in function with no address-of-label expressions">;
+def err_indirect_goto_in_protected_scope : Error<
+ "indirect goto might cross protected scopes">;
+def note_indirect_goto_target : Note<"possible target of indirect goto">;
+def note_protected_by_variable_init : Note<
+ "jump bypasses variable initialization">;
+def note_protected_by_cleanup : Note<
+ "jump bypasses initialization of variable with __attribute__((cleanup))">;
+def note_protected_by_vla_typedef : Note<
+ "jump bypasses initialization of VLA typedef">;
+def note_protected_by_vla : Note<
+ "jump bypasses initialization of variable length array">;
+def note_protected_by_objc_try : Note<
+ "jump bypasses initialization of @try block">;
+def note_protected_by_objc_catch : Note<
+ "jump bypasses initialization of @catch block">;
+def note_protected_by_objc_finally : Note<
+ "jump bypasses initialization of @finally block">;
+def note_protected_by_objc_synchronized : Note<
+ "jump bypasses initialization of @synchronized block">;
+def note_protected_by_cxx_try : Note<
+ "jump bypasses initialization of try block">;
+def note_protected_by_cxx_catch : Note<
+ "jump bypasses initialization of catch block">;
+def note_protected_by___block : Note<
+ "jump bypasses setup of __block variable">;
+
+def note_exits_cleanup : Note<
+ "jump exits scope of variable with __attribute__((cleanup))">;
+def note_exits_dtor : Note<
+ "jump exits scope of variable with non-trivial destructor">;
+def note_exits___block : Note<
+ "jump exits scope of __block variable">;
+def note_exits_objc_try : Note<
+ "jump exits @try block">;
+def note_exits_objc_catch : Note<
+ "jump exits @catch block">;
+def note_exits_objc_finally : Note<
+ "jump exits @finally block">;
+def note_exits_objc_synchronized : Note<
+ "jump exits @synchronized block">;
+def note_exits_cxx_try : Note<
+ "jump exits try block">;
+def note_exits_cxx_catch : Note<
+ "jump exits catch block">;
+
+def err_func_returning_array_function : Error<
+ "function cannot return %select{array|function}0 type %1">;
+def err_field_declared_as_function : Error<"field %0 declared as a function">;
+def err_field_incomplete : Error<"field has incomplete type %0">;
+def ext_variable_sized_type_in_struct : ExtWarn<
+ "field %0 with variable sized type %1 not at the end of a struct or class is"
+ " a GNU extension">, InGroup<GNU>;
+
+def err_flexible_array_empty_struct : Error<
+ "flexible array %0 not allowed in otherwise empty struct">;
+def err_flexible_array_has_nonpod_type : Error<
+ "flexible array member %0 of non-POD element type %1">;
+def ext_flexible_array_in_struct : Extension<
+ "%0 may not be nested in a struct due to flexible array member">;
+def ext_flexible_array_in_array : Extension<
+ "%0 may not be used as an array element due to flexible array member">;
+def err_flexible_array_init_nonempty : Error<
+ "non-empty initialization of flexible array member inside subobject">;
+def ext_flexible_array_empty_aggregate : Extension<
+ "flexible array member %0 in otherwise empty %select{struct|class}1 "
+ "is a Microsoft extension">, InGroup<Microsoft>;
+def ext_flexible_array_union : Extension<
+ "flexible array member %0 in a union is a Microsoft extension">,
+ InGroup<Microsoft>;
+
+def err_flexible_array_init_needs_braces : Error<
+ "flexible array requires brace-enclosed initializer">;
+def err_illegal_decl_array_of_functions : Error<
+ "'%0' declared as array of functions of type %1">;
+def err_illegal_decl_array_incomplete_type : Error<
+ "array has incomplete element type %0">;
+def err_illegal_message_expr_incomplete_type : Error<
+ "objective-c message has incomplete result type %0">;
+def err_illegal_decl_array_of_references : Error<
+ "'%0' declared as array of references of type %1">;
+def err_decl_negative_array_size : Error<
+ "'%0' declared as an array with a negative size">;
+def err_array_star_outside_prototype : Error<
+ "star modifier used outside of function prototype">;
+def err_illegal_decl_pointer_to_reference : Error<
+ "'%0' declared as a pointer to a reference of type %1">;
+def err_illegal_decl_mempointer_to_reference : Error<
+ "'%0' declared as a member pointer to a reference of type %1">;
+def err_illegal_decl_mempointer_to_void : Error<
+ "'%0' declared as a member pointer to void">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+ "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+ "member pointer refers into non-class type %0">;
+def err_reference_to_void : Error<"cannot form a reference to 'void'">;
+def err_qualified_block_pointer_type : Error<
+ "qualifier specification on block pointer type not allowed">;
+def err_nonfunction_block_type : Error<
+ "block pointer to non-function type is invalid">;
+def err_return_block_has_expr : Error<"void block should not return a value">;
+def err_block_return_missing_expr : Error<
+ "non-void block should return a value">;
+def err_block_with_return_type_requires_args : Error<
+ "block with explicit return type requires argument list">;
+def err_func_def_incomplete_result : Error<
+ "incomplete result type %0 in function definition">;
+
+// Expressions.
+def ext_sizeof_function_type : Extension<
+ "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>;
+def err_sizeof_alignof_overloaded_function_type : Error<
+ "invalid application of '%select{sizeof|__alignof}0' to an overloaded "
+ "function">;
+def ext_sizeof_void_type : Extension<
+ "invalid application of '%0' to a void type">, InGroup<PointerArith>;
+def err_sizeof_alignof_incomplete_type : Error<
+ "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">;
+def err_sizeof_alignof_bitfield : Error<
+ "invalid application of '%select{sizeof|__alignof}0' to bit-field">;
+def err_offsetof_incomplete_type : Error<
+ "offsetof of incomplete type %0">;
+def err_offsetof_record_type : Error<
+ "offsetof requires struct, union, or class type, %0 invalid">;
+def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
+def ext_offsetof_extended_field_designator : Extension<
+ "using extended field designator is an extension">;
+def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
+ InGroup<InvalidOffsetof>;
+def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
+
+def warn_floatingpoint_eq : Warning<
+ "comparing floating point with == or != is unsafe">,
+ InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
+
+def warn_division_by_zero : Warning<"division by zero is undefined">;
+def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
+def warn_shift_negative : Warning<"shift count is negative">;
+def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
+
+def warn_precedence_bitwise_rel : Warning<
+ "%0 has lower precedence than %1; %1 will be evaluated first">,
+ InGroup<Parentheses>;
+def note_precedence_bitwise_first : Note<
+ "place parentheses around the %0 expression to evaluate it first">;
+def note_precedence_bitwise_silence : Note<
+ "place parentheses around the %0 expression to silence this warning">;
+
+def warn_logical_instead_of_bitwise : Warning<
+ "use of logical %0 with constant operand; switch to bitwise %1 or "
+ "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
+
+def warn_logical_and_in_logical_or : Warning<
+ "'&&' within '||'">, InGroup<LogicalOpParentheses>;
+def note_logical_and_in_logical_or_silence : Note<
+ "place parentheses around the '&&' expression to silence this warning">;
+
+def warn_self_assignment : Warning<
+ "explicitly assigning a variable of type %0 to itself">,
+ InGroup<SelfAssignment>, DefaultIgnore;
+
+def err_sizeof_nonfragile_interface : Error<
+ "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
+ "non-fragile ABI">;
+def err_atdef_nonfragile_interface : Error<
+ "invalid application of @defs in non-fragile ABI">;
+def err_subscript_nonfragile_interface : Error<
+ "subscript requires size of interface %0, which is not constant in "
+ "non-fragile ABI">;
+
+def err_arithmetic_nonfragile_interface : Error<
+ "arithmetic on pointer to interface %0, which is not a constant size in "
+ "non-fragile ABI">;
+
+
+def ext_subscript_non_lvalue : Extension<
+ "ISO C90 does not allow subscripting non-lvalue array">;
+def err_typecheck_subscript_value : Error<
+ "subscripted value is not an array, pointer, or vector">;
+def err_typecheck_subscript_not_integer : Error<
+ "array subscript is not an integer">;
+def err_subscript_function_type : Error<
+ "subscript of pointer to function type %0">;
+def err_subscript_incomplete_type : Error<
+ "subscript of pointer to incomplete type %0">;
+def err_typecheck_member_reference_struct_union : Error<
+ "member reference base type %0 is not a structure or union">;
+def err_typecheck_member_reference_ivar : Error<
+ "%0 does not have a member named %1">;
+def err_typecheck_member_reference_arrow : Error<
+ "member reference type %0 is not a pointer">;
+def err_typecheck_member_reference_suggestion : Error<
+ "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">;
+def err_typecheck_member_reference_type : Error<
+ "cannot refer to type member %0 in %1 with '%select{.|->}2'">;
+def err_typecheck_member_reference_unknown : Error<
+ "cannot refer to member %0 in %1 with '%select{.|->}2'">;
+def err_member_reference_needs_call : Error<
+ "base of member reference is an overloaded function; perhaps you meant "
+ "to call %select{it|the 0-argument overload}0?">;
+def note_member_ref_possible_intended_overload : Note<
+ "possibly valid overload here">;
+def err_member_reference_needs_call_zero_arg : Error<
+ "base of member reference has function type %0; perhaps you meant to call "
+ "this function with '()'?">;
+def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
+ InGroup<CharSubscript>, DefaultIgnore;
+
+def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
+def err_no_member : Error<"no member named %0 in %1">;
+
+def err_member_redeclared : Error<"class member cannot be redeclared">;
+def err_member_name_of_class : Error<"member %0 has the same name as its class">;
+def err_member_def_undefined_record : Error<
+ "out-of-line definition of %0 from class %1 without definition">;
+def err_member_def_does_not_match : Error<
+ "out-of-line definition of %0 does not match any declaration in %1">;
+def err_member_def_does_not_match_ret_type : Error<
+ "out-of-line definition of %q0 differ from the declaration in the return type">;
+def err_nonstatic_member_out_of_line : Error<
+ "non-static data member defined out-of-line">;
+def err_nonstatic_flexible_variable : Error<
+ "non-static initialization of a variable with flexible array member">;
+def err_qualified_typedef_declarator : Error<
+ "typedef declarator cannot be qualified">;
+def err_qualified_param_declarator : Error<
+ "parameter declarator cannot be qualified">;
+def ext_out_of_line_declaration : ExtWarn<
+ "out-of-line declaration of a member must be a definition">,
+ InGroup<OutOfLineDeclaration>, DefaultError;
+def warn_member_extra_qualification : Warning<
+ "extra qualification on member %0">;
+def err_member_qualification : Error<
+ "non-friend class member %0 cannot have a qualified name">;
+def note_member_def_close_match : Note<"member declaration nearly matches">;
+def err_typecheck_ivar_variable_size : Error<
+ "instance variables must have a constant size">;
+def err_ivar_reference_type : Error<
+ "instance variables cannot be of reference type">;
+def err_typecheck_illegal_increment_decrement : Error<
+ "cannot %select{decrement|increment}1 value of type %0">;
+def err_typecheck_arithmetic_incomplete_type : Error<
+ "arithmetic on pointer to incomplete type %0">;
+def err_typecheck_pointer_arith_function_type : Error<
+ "arithmetic on pointer to function type %0">;
+def err_typecheck_pointer_arith_void_type : Error<
+ "arithmetic on pointer to void type">;
+def err_typecheck_decl_incomplete_type : Error<
+ "variable has incomplete type %0">;
+def ext_typecheck_decl_incomplete_type : ExtWarn<
+ "tentative definition of variable with internal linkage has incomplete non-array type %0">;
+def err_tentative_def_incomplete_type : Error<
+ "tentative definition has type %0 that is never completed">;
+def err_tentative_def_incomplete_type_arr : Error<
+ "tentative definition has array of type %0 that is never completed">;
+def warn_tentative_incomplete_array : Warning<
+ "tentative array definition assumed to have one element">;
+def err_typecheck_incomplete_array_needs_initializer : Error<
+ "definition of variable with array type needs an explicit size "
+ "or an initializer">;
+def err_array_init_not_init_list : Error<
+ "array initializer must be an initializer "
+ "list%select{| or string literal}0">;
+def warn_deprecated_string_literal_conversion : Warning<
+ "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
+def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
+def err_typecheck_sclass_fscope : Error<
+ "illegal storage class on file-scoped variable">;
+def err_unsupported_global_register : Error<
+ "global register variables are not supported">;
+def err_typecheck_sclass_func : Error<"illegal storage class on function">;
+def err_static_block_func : Error<
+ "function declared in block scope cannot have 'static' storage class">;
+def err_typecheck_address_of : Error<"address of %0 requested">;
+def ext_typecheck_addrof_void : Extension<
+ "ISO C forbids taking the address of an expression of type 'void'">;
+def err_unqualified_pointer_member_function : Error<
+ "must explicitly qualify name of member function when taking its address">;
+def err_invalid_form_pointer_member_function : Error<
+ "cannot create a non-constant pointer to member function">;
+def err_parens_pointer_member_function : Error<
+ "cannot parenthesize the name of a method when forming a member pointer">;
+def err_typecheck_invalid_lvalue_addrof : Error<
+ "address expression must be an lvalue or a function designator">;
+def ext_typecheck_addrof_class_temporary : ExtWarn<
+ "taking the address of a temporary object of type %0">,
+ InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
+def err_typecheck_addrof_class_temporary : Error<
+ "taking the address of a temporary object of type %0">;
+def err_typecheck_unary_expr : Error<
+ "invalid argument type %0 to unary expression">;
+def err_typecheck_indirection_requires_pointer : Error<
+ "indirection requires pointer operand (%0 invalid)">;
+def warn_indirection_through_null : Warning<
+ "indirection of non-volatile null pointer will be deleted, not trap">, InGroup<NullDereference>;
+def note_indirection_through_null : Note<
+ "consider using __builtin_trap() or qualifying pointer with 'volatile'">;
+
+def err_assignment_requires_nonfragile_object : Error<
+ "cannot assign to class object in non-fragile ABI (%0 invalid)">;
+def err_direct_interface_unsupported : Error<
+ "indirection to an interface is not supported (%0 invalid)">;
+def err_typecheck_invalid_operands : Error<
+ "invalid operands to binary expression (%0 and %1)">;
+def err_typecheck_sub_ptr_object : Error<
+ "subtraction of pointer %0 requires pointee to be a complete object type">;
+def err_typecheck_sub_ptr_compatible : Error<
+ "%0 and %1 are not pointers to compatible types">;
+def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn<
+ "ordered comparison between pointer and integer (%0 and %1)">;
+def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
+ "ordered comparison between pointer and zero (%0 and %1) is an extension">;
+def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
+ "ordered comparison of function pointers (%0 and %1)">;
+def ext_typecheck_comparison_of_fptr_to_void : Extension<
+ "equality comparison between function pointer and void pointer (%0 and %1)">;
+def err_typecheck_comparison_of_fptr_to_void : Error<
+ "equality comparison between function pointer and void pointer (%0 and %1)">;
+def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
+ "comparison between pointer and integer (%0 and %1)">;
+def err_typecheck_comparison_of_pointer_integer : Error<
+ "comparison between pointer and integer (%0 and %1)">;
+def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
+ "comparison of distinct pointer types (%0 and %1)">;
+def ext_typecheck_cond_incompatible_operands : ExtWarn<
+ "incompatible operand types (%0 and %1)">;
+def err_typecheck_comparison_of_distinct_pointers : Error<
+ "comparison of distinct pointer types (%0 and %1)">;
+def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn<
+ "comparison of distinct pointer types (%0 and %1) uses non-standard "
+ "composite pointer type %2">;
+def err_typecheck_vector_comparison : Error<
+ "comparison of vector types (%0 and %1) not supported yet">;
+def err_typecheck_assign_const : Error<"read-only variable is not assignable">;
+def err_stmtexpr_file_scope : Error<
+ "statement expression not allowed at file scope">;
+def warn_mixed_sign_comparison : Warning<
+ "comparison of integers of different signs: %0 and %1">,
+ InGroup<SignCompare>, DefaultIgnore;
+def warn_mixed_sign_conditional : Warning<
+ "operands of ? are integers of different signs: %0 and %1">,
+ InGroup<SignCompare>, DefaultIgnore;
+def warn_lunsigned_always_true_comparison : Warning<
+ "comparison of unsigned%select{| enum}2 expression %0 is always %1">,
+ InGroup<TautologicalCompare>;
+def warn_runsigned_always_true_comparison : Warning<
+ "comparison of %0 unsigned%select{| enum}2 expression is always %1">,
+ InGroup<TautologicalCompare>;
+def warn_comparison_of_mixed_enum_types : Warning<
+ "comparison of two values with different enumeration types (%0 and %1)">,
+ InGroup<DiagGroup<"enum-compare">>;
+
+def err_invalid_this_use : Error<
+ "invalid use of 'this' outside of a nonstatic member function">;
+def err_invalid_member_use_in_static_method : Error<
+ "invalid use of member %0 in static member function">;
+def err_invalid_qualified_function_type : Error<
+ "type qualifier is not allowed on this function">;
+def err_invalid_ref_qualifier_function_type : Error<
+ "ref-qualifier '%select{&&|&}0' is only allowed on non-static member functions,"
+ " member function pointers, and typedefs of function types">;
+def ext_qualified_function_type_template_arg : ExtWarn<
+ "template argument of '%0' qualified function type is a GNU extension">,
+ InGroup<GNU>;
+
+def err_invalid_qualified_function_pointer : Error<
+ "type qualifier is not allowed on this function %select{pointer|reference}0">;
+def err_invalid_qualified_typedef_function_type_use : Error<
+ "a qualified function type cannot be used to declare a "
+ "%select{static member|nonmember}0 function">;
+def err_invalid_ref_qualifier_typedef_function_type_use : Error<
+ "%select{static member|nonmember}0 function cannot have a ref-qualifier "
+ "'%select{&&|&}1'">;
+
+def err_ref_qualifier_overload : Error<
+ "cannot overload a member function %select{without a ref-qualifier|with "
+ "ref-qualifier '&'|with ref-qualifier '&&'}0 with a member function %select{"
+ "without a ref-qualifier|with ref-qualifier '&'|with ref-qualifier '&&'}1">;
+
+def err_invalid_non_static_member_use : Error<
+ "invalid use of nonstatic data member %0">;
+def err_invalid_incomplete_type_use : Error<
+ "invalid use of incomplete type %0">;
+def err_builtin_func_cast_more_than_one_arg : Error<
+ "function-style cast to a builtin type can only take one argument">;
+def err_builtin_direct_init_more_than_one_arg : Error<
+ "initializer of a builtin type can only take one argument">;
+def err_value_init_for_array_type : Error<
+ "array types cannot be value-initialized">;
+def warn_format_nonliteral_noargs : Warning<
+ "format string is not a string literal (potentially insecure)">,
+ InGroup<FormatSecurity>;
+def warn_format_nonliteral : Warning<
+ "format string is not a string literal">,
+ InGroup<FormatNonLiteral>, DefaultIgnore;
+
+def err_unexpected_interface : Error<
+ "unexpected interface name %0: expected expression">;
+def err_ref_non_value : Error<"%0 does not refer to a value">;
+def err_ref_vm_type : Error<
+ "cannot refer to declaration with a variably modified type inside block">;
+def err_ref_array_type : Error<
+ "cannot refer to declaration with an array type inside block">;
+def err_property_not_found : Error<
+ "property %0 not found on object of type %1">;
+def err_getter_not_found : Error<
+ "expected getter method not found on object of type %0">;
+def err_property_not_found_forward_class : Error<
+ "property %0 cannot be found in forward class object %1">;
+def err_property_not_as_forward_class : Error<
+ "property %0 refers to an incomplete Objective-C class %1 "
+ "(with no @interface available)">;
+def note_forward_class : Note<
+ "forward class is declared here">;
+def err_duplicate_property : Error<
+ "property has a previous declaration">;
+def ext_gnu_void_ptr : Extension<
+ "use of GNU void* extension">, InGroup<PointerArith>;
+def ext_gnu_ptr_func_arith : Extension<
+ "arithmetic on pointer to function type %0 is a GNU extension">,
+ InGroup<PointerArith>;
+def error_readonly_property_assignment : Error<
+ "assigning to property with 'readonly' attribute not allowed">;
+def ext_integer_increment_complex : Extension<
+ "ISO C does not support '++'/'--' on complex integer type %0">;
+def ext_integer_complement_complex : Extension<
+ "ISO C does not support '~' for complex conjugation of %0">;
+def error_nosetter_property_assignment : Error<
+ "setter method is needed to assign to object using property" " assignment syntax">;
+def error_no_subobject_property_setting : Error<
+ "expression is not assignable">;
+
+def ext_freestanding_complex : Extension<
+ "complex numbers are an extension in a freestanding C99 implementation">;
+
+// FIXME: Remove when we support imaginary.
+def err_imaginary_not_supported : Error<"imaginary types are not supported">;
+
+// Obj-c expressions
+def warn_root_inst_method_not_found : Warning<
+ "instance method %0 is being used on 'Class' which is not in the root class">;
+def warn_class_method_not_found : Warning<
+ "method %objcclass0 not found (return type defaults to 'id')">;
+def warn_inst_method_not_found : Warning<
+ "method %objcinstance0 not found (return type defaults to 'id')">;
+def error_no_super_class_message : Error<
+ "no @interface declaration found in class messaging of %0">;
+def error_root_class_cannot_use_super : Error<
+ "%0 cannot use 'super' because it is a root class">;
+def err_invalid_receiver_to_message : Error<
+ "invalid receiver to message expression">;
+def err_invalid_receiver_to_message_super : Error<
+ "'super' is only valid in a method body">;
+def err_invalid_receiver_class_message : Error<
+ "receiver type %0 is not an Objective-C class">;
+def err_missing_open_square_message_send : Error<
+ "missing '[' at start of message send expression">;
+def warn_bad_receiver_type : Warning<
+ "receiver type %0 is not 'id' or interface pointer, consider "
+ "casting it to 'id'">;
+def err_bad_receiver_type : Error<"bad receiver type %0">;
+def err_unknown_receiver_suggest : Error<
+ "unknown receiver %0; did you mean %1?">;
+def error_objc_throw_expects_object : Error<
+ "@throw requires an Objective-C object type (%0 invalid)">;
+def error_objc_synchronized_expects_object : Error<
+ "@synchronized requires an Objective-C object type (%0 invalid)">;
+def error_rethrow_used_outside_catch : Error<
+ "@throw (rethrow) used outside of a @catch block">;
+def err_attribute_multiple_objc_gc : Error<
+ "multiple garbage collection attributes specified for type">;
+def err_catch_param_not_objc_type : Error<
+ "@catch parameter is not a pointer to an interface type">;
+def err_illegal_qualifiers_on_catch_parm : Error<
+ "illegal qualifiers on @catch parameter">;
+def err_storage_spec_on_catch_parm : Error<
+ "@catch parameter cannot have storage specifier %select{|'typedef'|'extern'|"
+ "'static'|'auto'|'register'|'__private_extern__'|'mutable'}0">;
+def warn_register_objc_catch_parm : Warning<
+ "'register' storage specifier on @catch parameter will be ignored">;
+def err_qualified_objc_catch_parm : Error<
+ "@catch parameter declarator cannot be qualified">;
+def err_objc_pointer_cxx_catch_gnu : Error<
+ "can't catch Objective C exceptions in C++ in the GNU runtime">;
+def err_objc_pointer_cxx_catch_fragile : Error<
+ "can't catch Objective C exceptions in C++ in the non-unified "
+ "exception model">;
+def err_objc_object_catch : Error<
+ "can't catch an Objective C object by value">;
+
+def warn_setter_getter_impl_required : Warning<
+ "property %0 requires method %1 to be defined - "
+ "use @synthesize, @dynamic or provide a method implementation">;
+def warn_setter_getter_impl_required_in_category : Warning<
+ "property %0 requires method %1 to be defined - "
+ "use @dynamic or provide a method implementation in category">;
+def note_property_impl_required : Note<
+ "implementation is here">;
+def note_parameter_named_here : Note<
+ "passing argument to parameter %0 here">;
+def note_parameter_here : Note<
+ "passing argument to parameter here">;
+
+// C++ casts
+// These messages adhere to the TryCast pattern: %0 is an int specifying the
+// cast type, %1 is the source type, %2 is the destination type.
+def err_bad_reinterpret_cast_overload : Error<
+ "reinterpret_cast cannot resolve overloaded function %0 to type %1">;
+
+def err_bad_static_cast_overload : Error<
+ "address of overloaded function %0 cannot be static_cast to type %1">;
+
+def err_bad_cstyle_cast_overload : Error<
+ "address of overloaded function %0 cannot be cast to type %1">;
+
+
+def err_bad_cxx_cast_generic : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 is not allowed">;
+def err_bad_cxx_cast_rvalue : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from rvalue to reference type %2">;
+def err_bad_cxx_cast_const_away : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 casts away constness">;
+def err_bad_const_cast_dest : Error<
+ "%select{const_cast||||C-style cast|functional-style cast}0 to %2, "
+ "which is not a reference, pointer-to-object, or pointer-to-data-member">;
+def ext_cast_fn_obj : Extension<
+ "cast between pointer-to-function and pointer-to-object is an extension">;
+def err_bad_reinterpret_cast_small_int : Error<
+ "cast from pointer to smaller type %2 loses information">;
+def err_bad_cxx_cast_vector_to_scalar_different_size : Error<
+ "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
+ "to scalar %2 of different size">;
+def err_bad_cxx_cast_scalar_to_vector_different_size : Error<
+ "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 "
+ "to vector %2 of different size">;
+def err_bad_cxx_cast_vector_to_vector_different_size : Error<
+ "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
+ "to vector %2 of different size">;
+def err_bad_lvalue_to_rvalue_cast : Error<
+ "cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
+ "not compatible">;
+def err_bad_static_cast_pointer_nonpointer : Error<
+ "cannot cast from type %1 to pointer type %2">;
+def err_bad_static_cast_member_pointer_nonmp : Error<
+ "cannot cast from type %1 to member pointer type %2">;
+def err_bad_cxx_cast_member_pointer_size : Error<
+ "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
+ "type %1 to member pointer type %2 of different size">;
+def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
+
+// These messages don't adhere to the pattern.
+// FIXME: Display the path somehow better.
+def err_ambiguous_base_to_derived_cast : Error<
+ "ambiguous cast from base %0 to derived %1:%2">;
+def err_static_downcast_via_virtual : Error<
+ "cannot cast %0 to %1 via virtual base %2">;
+def err_downcast_from_inaccessible_base : Error<
+ "cannot cast %select{private|protected}2 base class %1 to %0">;
+def err_upcast_to_inaccessible_base : Error<
+ "cannot cast %0 to its %select{private|protected}2 base class %1">;
+def err_bad_dynamic_cast_not_ref_or_ptr : Error<
+ "%0 is not a reference or pointer">;
+def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">;
+def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">;
+def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">;
+def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
+
+// Other C++ expressions
+def err_need_header_before_typeid : Error<
+ "you need to include <typeinfo> before using the 'typeid' operator">;
+def err_need_header_before_ms_uuidof : Error<
+ "you need to include <guiddef.h> before using the '__uuidof' operator">;
+def err_uuidof_without_guid : Error<
+ "cannot call operator __uuidof on a type with no GUID">;
+def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
+def err_static_illegal_in_new : Error<
+ "the 'static' modifier for the array size is not legal in new expressions">;
+def err_array_new_needs_size : Error<
+ "array size must be specified in new expressions">;
+def err_bad_new_type : Error<
+ "cannot allocate %select{function|reference}1 type %0 with new">;
+def err_new_incomplete_type : Error<
+ "allocation of incomplete type %0">;
+def err_new_array_nonconst : Error<
+ "only the first dimension of an allocated array may have dynamic size">;
+def err_new_array_init_args : Error<
+ "array 'new' cannot have initialization arguments">;
+def ext_new_paren_array_nonconst : ExtWarn<
+ "when type is in parentheses, array cannot have dynamic size">;
+def err_placement_new_non_placement_delete : Error<
+ "'new' expression with placement arguments refers to non-placement "
+ "'operator delete'">;
+def err_array_size_not_integral : Error<
+ "array size expression must have integral or enumerated type, not %0">;
+def err_array_size_incomplete_type : Error<
+ "array size expression has incomplete class type %0">;
+def err_array_size_explicit_conversion : Error<
+ "array size expression of type %0 requires explicit conversion to type %1">;
+def note_array_size_conversion : Note<
+ "conversion to %select{integral|enumeration}0 type %1 declared here">;
+def err_array_size_ambiguous_conversion : Error<
+ "ambiguous conversion of array size expression of type %0 to an integral or "
+ "enumeration type">;
+def ext_array_size_conversion : Extension<
+ "implicit conversion from array size expression of type %0 to "
+ "%select{integral|enumeration}1 type %2 is a C++0x extension">,
+ InGroup<CXX0x>;
+
+def err_default_init_const : Error<
+ "default initialization of an object of const type %0"
+ "%select{| requires a user-provided default constructor}1">;
+def err_delete_operand : Error<"cannot delete expression of type %0">;
+def ext_delete_void_ptr_operand : ExtWarn<
+ "cannot delete expression with pointer-to-'void' type %0">;
+def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
+ "expression of type %0 to a pointer">;
+def warn_delete_incomplete : Warning<
+ "deleting pointer to incomplete type %0 may cause undefined behaviour">;
+def err_delete_incomplete_class_type : Warning<
+ "deleting incomplete class type %0; no conversions to pointer type">;
+def warn_delete_array_type : Warning<
+ "'delete' applied to a pointer-to-array type %0 treated as delete[]">;
+def err_no_suitable_delete_member_function_found : Error<
+ "no suitable member %0 in %1">;
+def err_ambiguous_suitable_delete_member_function_found : Error<
+ "multiple suitable %0 functions in %1">;
+def note_member_declared_here : Note<
+ "member %0 declared here">;
+def err_decrement_bool : Error<"cannot decrement expression of type bool">;
+def warn_increment_bool : Warning<
+ "incrementing expression of type bool is deprecated">, InGroup<Deprecated>;
+def ext_catch_incomplete_ptr : ExtWarn<
+ "ISO C++ forbids catching a pointer to incomplete type %0">;
+def ext_catch_incomplete_ref : ExtWarn<
+ "ISO C++ forbids catching a reference to incomplete type %0">;
+def err_catch_incomplete : Error<"cannot catch incomplete type %0">;
+def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">;
+def err_qualified_catch_declarator : Error<
+ "exception declarator cannot be qualified">;
+def err_early_catch_all : Error<"catch-all handler must come last">;
+def err_bad_memptr_rhs : Error<
+ "right hand operand to %0 has non pointer-to-member type %1">;
+def err_memptr_rhs_to_incomplete : Error<
+ "cannot dereference pointer into incomplete class type %0">;
+def err_bad_memptr_lhs : Error<
+ "left hand operand to %0 must be a %select{|pointer to }1class "
+ "compatible with the right hand operand, but is %2">;
+def warn_exception_caught_by_earlier_handler : Warning<
+ "exception of type %0 will be caught by earlier handler">;
+def note_previous_exception_handler : Note<"for type %0">;
+def err_exceptions_disabled : Error<
+ "cannot use '%0' with exceptions disabled">;
+def err_objc_exceptions_disabled : Error<
+ "cannot use '%0' with Objective-C exceptions disabled">;
+def warn_non_virtual_dtor : Warning<
+ "%0 has virtual functions but non-virtual destructor">,
+ InGroup<NonVirtualDtor>, DefaultIgnore;
+def warn_overloaded_virtual : Warning<
+ "%q0 hides overloaded virtual %select{function|functions}1">,
+ InGroup<OverloadedVirtual>, DefaultIgnore;
+def note_hidden_overloaded_virtual_declared_here : Note<
+ "hidden overloaded virtual function %q0 declared here">;
+
+def err_conditional_void_nonvoid : Error<
+ "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
+ "is of type %0">;
+def err_conditional_ambiguous : Error<
+ "conditional expression is ambiguous; %0 can be converted to %1 "
+ "and vice versa">;
+def err_conditional_ambiguous_ovl : Error<
+ "conditional expression is ambiguous; %0 and %1 can be converted to several "
+ "common types">;
+
+def err_throw_incomplete : Error<
+ "cannot throw object of incomplete type %0">;
+def err_throw_incomplete_ptr : Error<
+ "cannot throw pointer to object of incomplete type %0">;
+def err_return_in_constructor_handler : Error<
+ "return in the catch of a function try block of a constructor is illegal">;
+
+def err_operator_arrow_circular : Error<
+ "circular pointer delegation detected">;
+def err_pseudo_dtor_base_not_scalar : Error<
+ "object expression of non-scalar type %0 cannot be used in a "
+ "pseudo-destructor expression">;
+def err_pseudo_dtor_type_mismatch : Error<
+ "the type of object expression (%0) does not match the type being destroyed "
+ "(%1) in pseudo-destructor expression">;
+def err_pseudo_dtor_call_with_args : Error<
+ "call to pseudo-destructor cannot have any arguments">;
+def err_dtor_expr_without_call : Error<
+ "%select{destructor reference|pseudo-destructor expression}0 must be "
+ "called immediately with '()'">;
+def err_pseudo_dtor_destructor_non_type : Error<
+ "%0 does not refer to a type name in pseudo-destructor expression; expected "
+ "the name of type %1">;
+def err_pseudo_dtor_template : Error<
+ "specialization of template %0 does not refer to a scalar type in pseudo-"
+ "destructor expression">;
+def err_invalid_use_of_function_type : Error<
+ "a function type is not allowed here">;
+def err_invalid_use_of_array_type : Error<"an array type is not allowed here">;
+def err_type_defined_in_condition : Error<
+ "types may not be defined in conditions">;
+def err_typecheck_bool_condition : Error<
+ "value of type %0 is not contextually convertible to 'bool'">;
+def err_typecheck_ambiguous_condition : Error<
+ "conversion from %0 to %1 is ambiguous">;
+def err_typecheck_nonviable_condition : Error<
+ "no viable conversion from %0 to %1">;
+def err_typecheck_deleted_function : Error<
+ "conversion function from %0 to %1 invokes a deleted function">;
+
+def err_expected_class_or_namespace : Error<"expected a class or namespace">;
+def err_missing_qualified_for_redecl : Error<
+ "must qualify the name %0 to declare %q1 in this scope">;
+def err_invalid_declarator_scope : Error<
+ "definition or redeclaration of %0 not in a namespace enclosing %1">;
+def err_invalid_declarator_global_scope : Error<
+ "definition or redeclaration of %0 cannot name the global scope">;
+def err_invalid_declarator_in_function : Error<
+ "definition or redeclaration of %0 not allowed inside a function">;
+def err_not_tag_in_scope : Error<
+ "no %select{struct|union|class|enum}0 named %1 in %2">;
+
+def err_cannot_form_pointer_to_member_of_reference_type : Error<
+ "cannot form a pointer-to-member to member %0 of reference type %1">;
+def err_invalid_use_of_bound_member_func : Error<
+ "a bound member function may only be called">;
+def err_incomplete_object_call : Error<
+ "incomplete type in call to object of type %0">;
+def err_incomplete_pointer_to_member_return : Error<
+ "incomplete return type %0 of pointer-to-member constant">;
+
+def warn_condition_is_assignment : Warning<"using the result of an "
+ "assignment as a condition without parentheses">,
+ InGroup<Parentheses>;
+// Completely identical except off by default.
+def warn_condition_is_idiomatic_assignment : Warning<"using the result "
+ "of an assignment as a condition without parentheses">,
+ InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
+def note_condition_assign_to_comparison : Note<
+ "use '==' to turn this assignment into an equality comparison">;
+def note_condition_or_assign_to_comparison : Note<
+ "use '!=' to turn this compound assignment into an inequality comparison">;
+def note_condition_assign_silence : Note<
+ "place parentheses around the assignment to silence this warning">;
+
+def warn_equality_with_extra_parens : Warning<"equality comparison with "
+ "extraneous parentheses">, InGroup<Parentheses>;
+def note_equality_comparison_to_assign : Note<
+ "use '=' to turn this equality comparison into an assignment">;
+def note_equality_comparison_silence : Note<
+ "remove extraneous parentheses around the comparison to silence this warning">;
+
+def warn_synthesized_ivar_access : Warning<
+ "direct access of synthesized ivar by using property access %0">,
+ InGroup<NonfragileAbi2>, DefaultIgnore;
+def warn_ivar_variable_conflict : Warning<
+ "when default property synthesis is on, "
+ "%0 lookup will access property ivar instead of global variable">,
+ InGroup<NonfragileAbi2>;
+def note_global_declared_at : Note<"global variable declared here">;
+
+// assignment related diagnostics (also for argument passing, returning, etc).
+// In most of these diagnostics the %2 is a value from the
+// Sema::AssignmentAction enumeration
+def err_typecheck_convert_incompatible : Error<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from incompatible type|to parameter of incompatible type|"
+ "from a function with incompatible result type|to incompatible type|"
+ "with an expression of incompatible type|to parameter of incompatible type|"
+ "to incompatible type}2 %1">;
+def warn_incompatible_qualified_id : Warning<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from incompatible type|to parameter of incompatible type|"
+ "from a function with incompatible result type|to incompatible type|"
+ "with an expression of incompatible type|to parameter of incompatible type|"
+ "to incompatible type}2 %1">;
+def ext_typecheck_convert_pointer_int : ExtWarn<
+ "incompatible pointer to integer conversion "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">;
+def ext_typecheck_convert_int_pointer : ExtWarn<
+ "incompatible integer to pointer conversion "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">;
+def ext_typecheck_convert_pointer_void_func : Extension<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1 "
+ "converts between void pointer and function pointer">;
+def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1 "
+ "converts between pointers to integer types with different sign">,
+ InGroup<DiagGroup<"pointer-sign">>;
+def ext_typecheck_convert_incompatible_pointer : ExtWarn<
+ "incompatible pointer types "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">;
+def ext_typecheck_convert_discards_qualifiers : ExtWarn<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1 discards "
+ "qualifiers">;
+def ext_nested_pointer_qualifier_mismatch : ExtWarn<
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1 discards "
+ "qualifiers in nested pointer types">;
+def warn_incompatible_vectors : Warning<
+ "incompatible vector types "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">,
+ InGroup<VectorConversions>, DefaultIgnore;
+def err_int_to_block_pointer : Error<
+ "invalid block pointer conversion "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">;
+def err_typecheck_convert_incompatible_block_pointer : Error<
+ "incompatible block pointer types "
+ "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
+ " %0 "
+ "%select{from|to parameter of type|from a function with result type|to type|"
+ "with an expression of type|to parameter of type|to type}2 %1">;
+def err_typecheck_incompatible_address_space : Error<
+ "%select{assigning %1 to %0"
+ "|passing %0 to parameter of type %1"
+ "|returning %0 from a function with result type %1"
+ "|converting %0 to type %1"
+ "|initializing %0 with an expression of type %1"
+ "|sending %0 to parameter of type %1"
+ "|casting %0 to type %1}2"
+ " changes address space of pointer">;
+def err_typecheck_convert_ambiguous : Error<
+ "ambiguity in initializing value of type %0 with initializer of type %1">;
+def err_cannot_initialize_decl_noname : Error<
+ "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 "
+ "of type %2">;
+def err_cannot_initialize_decl : Error<
+ "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
+def err_typecheck_comparison_of_distinct_blocks : Error<
+ "comparison of distinct block types (%0 and %1)">;
+
+def err_typecheck_array_not_modifiable_lvalue : Error<
+ "array type %0 is not assignable">;
+def err_typecheck_non_object_not_modifiable_lvalue : Error<
+ "non-object type %0 is not assignable">;
+def err_typecheck_expression_not_modifiable_lvalue : Error<
+ "expression is not assignable">;
+def err_typecheck_incomplete_type_not_modifiable_lvalue : Error<
+ "incomplete type %0 is not assignable">;
+def err_typecheck_lvalue_casts_not_supported : Error<
+ "assignment to cast is illegal, lvalue casts are not supported">;
+
+def err_typecheck_duplicate_vector_components_not_mlvalue : Error<
+ "vector is not assignable (contains duplicate components)">;
+def err_block_decl_ref_not_modifiable_lvalue : Error<
+ "variable is not assignable (missing __block type specifier)">;
+def err_typecheck_call_not_function : Error<
+ "called object type %0 is not a function or function pointer">;
+def err_call_incomplete_return : Error<
+ "calling function with incomplete return type %0">;
+def err_call_function_incomplete_return : Error<
+ "calling %0 with incomplete return type %1">;
+def note_function_with_incomplete_return_type_declared_here : Note<
+ "%0 declared here">;
+def err_call_incomplete_argument : Error<
+ "argument type %0 is incomplete">;
+def err_typecheck_call_too_few_args : Error<
+ "too few arguments to %select{function|block|method}0 call, "
+ "expected %1, have %2">;
+def err_typecheck_call_too_few_args_at_least : Error<
+ "too few arguments to %select{function|block|method}0 call, "
+ "expected at least %1, have %2">;
+def err_typecheck_call_too_many_args : Error<
+ "too many arguments to %select{function|block|method}0 call, "
+ "expected %1, have %2">;
+def err_typecheck_call_too_many_args_at_most : Error<
+ "too many arguments to %select{function|block|method}0 call, "
+ "expected at most %1, have %2">;
+def warn_call_wrong_number_of_arguments : Warning<
+ "too %select{few|many}0 arguments in call to %1">;
+def err_atomic_builtin_must_be_pointer : Error<
+ "first argument to atomic builtin must be a pointer (%0 invalid)">;
+def err_atomic_builtin_must_be_pointer_intptr : Error<
+ "first argument to atomic builtin must be a pointer to integer or pointer"
+ " (%0 invalid)">;
+def err_atomic_builtin_pointer_size : Error<
+ "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
+ "type (%0 invalid)">;
+
+def err_deleted_function_use : Error<"attempt to use a deleted function">;
+
+def err_kern_type_not_void_return : Error<
+ "kernel function type %0 must have void return type">;
+def err_config_scalar_return : Error<
+ "CUDA special function 'cudaConfigureCall' must have scalar return type">;
+
+
+def err_cannot_pass_objc_interface_to_vararg : Error<
+ "cannot pass object with interface type %0 by-value through variadic "
+ "%select{function|block|method}1">;
+
+def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
+ "cannot pass object of non-POD type %0 through variadic "
+ "%select{function|block|method|constructor}1; call will abort at runtime">,
+ InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
+
+def err_typecheck_call_invalid_ordered_compare : Error<
+ "ordered compare requires two args of floating point type (%0 and %1)">;
+def err_typecheck_call_invalid_unary_fp : Error<
+ "floating point classification requires argument of floating point type "
+ "(passed in %0)">;
+def err_typecheck_cond_expect_scalar : Error<
+ "used type %0 where arithmetic or pointer type is required">;
+def ext_typecheck_cond_one_void : Extension<
+ "C99 forbids conditional expressions with only one void side">;
+def err_typecheck_cond_expect_scalar_or_vector : Error<
+ "used type %0 where arithmetic, pointer, or vector type is required">;
+def err_typecheck_cast_to_incomplete : Error<
+ "cast to incomplete type %0">;
+def ext_typecheck_cast_nonscalar : Extension<
+ "C99 forbids casting nonscalar type %0 to the same type">;
+def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
+def err_typecheck_cast_to_union_no_type : Error<
+ "cast to union type from type %0 not present in union">;
+def err_cast_pointer_from_non_pointer_int : Error<
+ "operand of type %0 cannot be cast to a pointer type">;
+def err_cast_pointer_to_non_pointer_int : Error<
+ "pointer cannot be cast to type %0">;
+def err_typecheck_expect_scalar_operand : Error<
+ "operand of type %0 where arithmetic or pointer type is required">;
+def err_typecheck_cond_incompatible_operands : Error<
+ "incompatible operand types (%0 and %1)">;
+def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
+ "incompatible operand types (%0 and %1) use non-standard composite pointer "
+ "type %2">;
+def err_cast_selector_expr : Error<
+ "cannot type cast @selector expression">;
+def warn_typecheck_cond_incompatible_pointers : ExtWarn<
+ "pointer type mismatch (%0 and %1)">;
+def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
+ "pointer/integer type mismatch in conditional expression (%0 and %1)">;
+def err_typecheck_choose_expr_requires_constant : Error<
+ "'__builtin_choose_expr' requires a constant expression">;
+def ext_typecheck_expression_not_constant_but_accepted : Extension<
+ "expression is not a constant, but is accepted as one by GNU extensions">,
+ InGroup<GNU>;
+def warn_unused_expr : Warning<"expression result unused">,
+ InGroup<UnusedValue>;
+def warn_unused_voidptr : Warning<
+ "expression result unused; should this cast be to 'void'?">,
+ InGroup<UnusedValue>;
+def warn_unused_property_expr : Warning<
+ "property access result unused - getters should not be used for side effects">,
+ InGroup<UnusedValue>;
+def warn_unused_call : Warning<
+ "ignoring return value of function declared with %0 attribute">,
+ InGroup<UnusedValue>;
+
+def err_incomplete_type_used_in_type_trait_expr : Error<
+ "incomplete type %0 used in type trait expression">;
+def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
+
+def err_typecheck_cond_incompatible_operands_null : Error<
+ "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
+} // End of general sema category.
+
+// inline asm.
+let CategoryName = "Inline Assembly Issue" in {
+ def err_asm_wide_character : Error<"wide string is invalid in 'asm'">;
+ def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">;
+ def err_asm_invalid_output_constraint : Error<
+ "invalid output constraint '%0' in asm">;
+ def err_asm_invalid_lvalue_in_input : Error<
+ "invalid lvalue in asm input for constraint '%0'">;
+ def err_asm_invalid_input_constraint : Error<
+ "invalid input constraint '%0' in asm">;
+ def err_asm_invalid_type_in_input : Error<
+ "invalid type %0 in asm input for constraint '%1'">;
+ def err_asm_tying_incompatible_types : Error<
+ "unsupported inline asm: input with type %0 matching output with type %1">;
+ def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
+ def warn_asm_label_on_auto_decl : Warning<
+ "ignored asm label '%0' on automatic variable">;
+ def err_invalid_asm_cast_lvalue : Error<
+ "invalid use of a cast in a inline asm context requiring an l-value: "
+ "remove the cast or build with -fheinous-gnu-extensions">;
+
+ def warn_invalid_asm_cast_lvalue : Warning<
+ "invalid use of a cast in a inline asm context requiring an l-value: "
+ "accepted due to -fheinous-gnu-extensions, but clang may remove support "
+ "for this in the future">;
+}
+
+let CategoryName = "Semantic Issue" in {
+
+def err_invalid_conversion_between_vectors : Error<
+ "invalid conversion between vector type %0 and %1 of different size">;
+def err_invalid_conversion_between_vector_and_integer : Error<
+ "invalid conversion between vector type %0 and integer type %1 "
+ "of different size">;
+
+def err_invalid_conversion_between_vector_and_scalar : Error<
+ "invalid conversion between vector type %0 and scalar type %1">;
+def err_overload_expr_requires_non_zero_constant : Error<
+ "overload requires a non-zero constant expression as first argument">;
+def err_overload_incorrect_fntype : Error<
+ "argument is not a function, or has wrong number of parameters">;
+
+// C++ member initializers.
+def err_only_constructors_take_base_inits : Error<
+ "only constructors take base initializers">;
+
+def err_multiple_mem_initialization : Error <
+ "multiple initializations given for non-static member %0">;
+def err_multiple_mem_union_initialization : Error <
+ "initializing multiple members of anonymous union">;
+def err_multiple_base_initialization : Error <
+ "multiple initializations given for base %0">;
+
+def err_mem_init_not_member_or_class : Error<
+ "member initializer %0 does not name a non-static data member or base "
+ "class">;
+
+def warn_initializer_out_of_order : Warning<
+ "%select{field|base class}0 %1 will be initialized after "
+ "%select{field|base}2 %3">,
+ InGroup<Reorder>, DefaultIgnore;
+
+def err_base_init_does_not_name_class : Error<
+ "constructor initializer %0 does not name a class">;
+def err_base_init_direct_and_virtual : Error<
+ "base class initializer %0 names both a direct base class and an "
+ "inherited virtual base class">;
+def err_not_direct_base_or_virtual : Error<
+ "type %0 is not a direct or virtual base of %1">;
+
+def err_in_class_initializer_non_const : Error<
+ "non-const static data member must be initialized out of line">;
+def err_in_class_initializer_bad_type : Error<
+ "static data member of type %0 must be initialized out of line">;
+def ext_in_class_initializer_float_type : ExtWarn<
+ "in-class initializer for static data member of type %0 "
+ "is a C++0x extension">, InGroup<CXX0x>;
+def err_in_class_initializer_non_constant : Error<
+ "in-class initializer is not a constant expression">;
+
+// C++ anonymous unions and GNU anonymous structs/unions
+def ext_anonymous_union : Extension<
+ "anonymous unions are a GNU extension in C">, InGroup<GNU>;
+def ext_anonymous_struct : Extension<
+ "anonymous structs are a GNU extension">, InGroup<GNU>;
+def err_anonymous_union_not_static : Error<
+ "anonymous unions at namespace or global scope must be declared 'static'">;
+def err_anonymous_union_with_storage_spec : Error<
+ "anonymous union at class scope must not have a storage specifier">;
+def err_anonymous_struct_not_member : Error<
+ "anonymous %select{structs|structs and classes}0 must be "
+ "%select{struct or union|class}0 members">;
+def err_anonymous_union_member_redecl : Error<
+ "member of anonymous union redeclares %0">;
+def err_anonymous_struct_member_redecl : Error<
+ "member of anonymous struct redeclares %0">;
+def err_anonymous_record_with_type : Error<
+ "types cannot be declared in an anonymous %select{struct|union}0">;
+def ext_anonymous_record_with_type : Extension<
+ "types declared in an anonymous %select{struct|union}0 are a Microsoft "
+ "extension">, InGroup<Microsoft>;
+def err_anonymous_record_with_function : Error<
+ "functions cannot be declared in an anonymous %select{struct|union}0">;
+def err_anonymous_record_with_static : Error<
+ "static members cannot be declared in an anonymous %select{struct|union}0">;
+def err_anonymous_record_bad_member : Error<
+ "anonymous %select{struct|union}0 can only contain non-static data members">;
+def err_anonymous_record_nonpublic_member : Error<
+ "anonymous %select{struct|union}0 cannot contain a "
+ "%select{private|protected}1 data member">;
+def ext_ms_anonymous_struct : ExtWarn<
+ "anonymous structs are a Microsoft extension">, InGroup<Microsoft>;
+
+// C++ local classes
+def err_reference_to_local_var_in_enclosing_function : Error<
+ "reference to local variable %0 declared in enclosed function %1">;
+def note_local_variable_declared_here : Note<
+ "%0 declared here">;
+def err_static_data_member_not_allowed_in_local_class : Error<
+ "static data member %0 not allowed in local class %1">;
+
+// C++ derived classes
+def err_base_clause_on_union : Error<"unions cannot have base classes">;
+def err_base_must_be_class : Error<"base specifier must name a class">;
+def err_union_as_base_class : Error<"unions cannot be base classes">;
+def err_incomplete_base_class : Error<"base class has incomplete type">;
+def err_duplicate_base_class : Error<
+ "base class %0 specified more than once as a direct base class">;
+// FIXME: better way to display derivation? Pass entire thing into diagclient?
+def err_ambiguous_derived_to_base_conv : Error<
+ "ambiguous conversion from derived class %0 to base class %1:%2">;
+def err_ambiguous_memptr_conv : Error<
+ "ambiguous conversion from pointer to member of %select{base|derived}0 "
+ "class %1 to pointer to member of %select{derived|base}0 class %2:%3">;
+
+def err_memptr_conv_via_virtual : Error<
+ "conversion from pointer to member of class %0 to pointer to member "
+ "of class %1 via virtual base %2 is not allowed">;
+
+// C++ access control
+def err_conv_to_inaccessible_base : Error<
+ "conversion from %0 to inaccessible base class %1">, AccessControl;
+def note_inheritance_specifier_here : Note<
+ "'%0' inheritance specifier here">;
+def note_inheritance_implicitly_private_here : Note<
+ "inheritance is implicitly 'private'">;
+
+// C++ member name lookup
+def err_ambiguous_member_multiple_subobjects : Error<
+ "non-static member %0 found in multiple base-class subobjects of type %1:%2">;
+def err_ambiguous_member_multiple_subobject_types : Error<
+ "member %0 found in multiple base classes of different types">;
+def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">;
+def err_ambiguous_reference : Error<"reference to %0 is ambiguous">;
+def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">;
+def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a "
+ "declaration in a different namespace">;
+def note_hidden_tag : Note<"type declaration hidden">;
+def note_hiding_object : Note<"declaration hides type">;
+
+// C++ operator overloading
+def err_operator_overload_needs_class_or_enum : Error<
+ "overloaded %0 must have at least one parameter of class "
+ "or enumeration type">;
+
+def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
+def err_operator_overload_static : Error<
+ "overloaded %0 cannot be a static member function">;
+def err_operator_overload_default_arg : Error<
+ "parameter of overloaded %0 cannot have a default argument">;
+def err_operator_overload_must_be : Error<
+ "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator "
+ "(has %1 parameter%s1)">;
+
+def err_operator_overload_must_be_member : Error<
+ "overloaded %0 must be a non-static member function">;
+def err_operator_overload_post_incdec_must_be_int : Error<
+ "parameter of overloaded post-%select{increment|decrement}1 operator must "
+ "have type 'int' (not %0)">;
+
+// C++ allocation and deallocation functions.
+def err_operator_new_delete_declared_in_namespace : Error<
+ "%0 cannot be declared inside a namespace">;
+def err_operator_new_delete_declared_static : Error<
+ "%0 cannot be declared static in global scope">;
+def err_operator_new_delete_invalid_result_type : Error<
+ "%0 must return type %1">;
+def err_operator_new_delete_dependent_result_type : Error<
+ "%0 cannot have a dependent return type; use %1 instead">;
+def err_operator_new_delete_too_few_parameters : Error<
+ "%0 must have at least one parameter.">;
+def err_operator_new_delete_template_too_few_parameters : Error<
+ "%0 template must have at least two parameters.">;
+
+def err_operator_new_dependent_param_type : Error<
+ "%0 cannot take a dependent type as first parameter; "
+ "use size_t (%1) instead">;
+def err_operator_new_param_type : Error<
+ "%0 takes type size_t (%1) as first parameter">;
+def err_operator_new_default_arg: Error<
+ "parameter of %0 cannot have a default argument">;
+def err_operator_delete_dependent_param_type : Error<
+ "%0 cannot take a dependent type as first parameter; use %1 instead">;
+def err_operator_delete_param_type : Error<
+ "first parameter of %0 must have type %1">;
+
+// C++ literal operators
+def err_literal_operator_outside_namespace : Error<
+ "literal operator %0 must be in a namespace or global scope">;
+// FIXME: This diagnostic sucks
+def err_literal_operator_params : Error<
+ "parameter declaration for literal operator %0 is not valid">;
+
+// C++ conversion functions
+def err_conv_function_not_member : Error<
+ "conversion function must be a non-static member function">;
+def err_conv_function_return_type : Error<
+ "conversion function cannot have a return type">;
+def err_conv_function_with_params : Error<
+ "conversion function cannot have any parameters">;
+def err_conv_function_variadic : Error<
+ "conversion function cannot be variadic">;
+def err_conv_function_to_array : Error<
+ "conversion function cannot convert to an array type">;
+def err_conv_function_to_function : Error<
+ "conversion function cannot convert to a function type">;
+def err_conv_function_with_complex_decl : Error<
+ "must use a typedef to declare a conversion to %0">;
+def err_conv_function_redeclared : Error<
+ "conversion function cannot be redeclared">;
+def warn_conv_to_self_not_used : Warning<
+ "conversion function converting %0 to itself will never be used">;
+def warn_conv_to_base_not_used : Warning<
+ "conversion function converting %0 to its base class %1 will never be used">;
+def warn_conv_to_void_not_used : Warning<
+ "conversion function converting %0 to %1 will never be used">;
+
+def warn_not_compound_assign : Warning<
+ "use of unary operator that may be intended as compound assignment (%0=)">;
+
+// C++0x explicit conversion operators
+def warn_explicit_conversion_functions : Warning<
+ "explicit conversion functions are a C++0x extension">, InGroup<CXX0x>;
+
+def warn_array_index_precedes_bounds : Warning<
+ "array index of '%0' indexes before the beginning of the array">,
+ InGroup<DiagGroup<"array-bounds">>;
+def warn_array_index_exceeds_bounds : Warning<
+ "array index of '%0' indexes past the end of an array (that contains %1 elements)">,
+ InGroup<DiagGroup<"array-bounds">>;
+def note_array_index_out_of_bounds : Note<
+ "array %0 declared here">;
+
+def warn_printf_write_back : Warning<
+ "use of '%%n' in format string discouraged (potentially insecure)">,
+ InGroup<FormatSecurity>;
+def warn_printf_insufficient_data_args : Warning<
+ "more '%%' conversions than data arguments">, InGroup<Format>;
+def warn_printf_data_arg_not_used : Warning<
+ "data argument not used by format string">, InGroup<FormatExtraArgs>;
+def warn_format_invalid_conversion : Warning<
+ "invalid conversion specifier '%0'">, InGroup<Format>;
+def warn_printf_incomplete_specifier : Warning<
+ "incomplete format specifier">, InGroup<Format>;
+def warn_missing_format_string : Warning<
+ "format string missing">, InGroup<Format>;
+def warn_scanf_nonzero_width : Warning<
+ "zero field width in scanf format string is unused">,
+ InGroup<Format>;
+def warn_printf_conversion_argument_type_mismatch : Warning<
+ "conversion specifies type %0 but the argument has type %1">,
+ InGroup<Format>;
+def warn_printf_positional_arg_exceeds_data_args : Warning <
+ "data argument position '%0' exceeds the number of data arguments (%1)">,
+ InGroup<Format>;
+def warn_format_zero_positional_specifier : Warning<
+ "position arguments in format strings start counting at 1 (not 0)">,
+ InGroup<Format>;
+def warn_format_invalid_positional_specifier : Warning<
+ "invalid position specified for %select{field width|field precision}0">,
+ InGroup<Format>;
+def warn_format_mix_positional_nonpositional_args : Warning<
+ "cannot mix positional and non-positional arguments in format string">,
+ InGroup<Format>;
+def warn_null_arg : Warning<
+ "null passed to a callee which requires a non-null argument">,
+ InGroup<NonNull>;
+def warn_empty_format_string : Warning<
+ "format string is empty">, InGroup<FormatZeroLength>;
+def warn_format_string_is_wide_literal : Warning<
+ "format string should not be a wide string">, InGroup<Format>;
+def warn_printf_format_string_contains_null_char : Warning<
+ "format string contains '\\0' within the string body">, InGroup<Format>;
+def warn_printf_asterisk_missing_arg : Warning<
+ "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">;
+def warn_printf_asterisk_wrong_type : Warning<
+ "field %select{width|precision}0 should have type %1, but argument has type %2">,
+ InGroup<Format>;
+def warn_printf_nonsensical_optional_amount: Warning<
+ "%select{field width|precision}0 used with '%1' conversion specifier, resulting in undefined behavior">,
+ InGroup<Format>;
+def warn_printf_nonsensical_flag: Warning<
+ "flag '%0' results in undefined behavior with '%1' conversion specifier">,
+ InGroup<Format>;
+def warn_format_nonsensical_length: Warning<
+ "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
+ InGroup<Format>;
+def warn_printf_ignored_flag: Warning<
+ "flag '%0' is ignored when flag '%1' is present">,
+ InGroup<Format>;
+def warn_scanf_scanlist_incomplete : Warning<
+ "no closing ']' for '%%[' in scanf format string">,
+ InGroup<Format>;
+
+// CHECK: returning address/reference of stack memory
+def warn_ret_stack_addr : Warning<
+ "address of stack memory associated with local variable %0 returned">;
+def warn_ret_stack_ref : Warning<
+ "reference to stack memory associated with local variable %0 returned">;
+def warn_ret_local_temp_addr : Warning<
+ "returning address of local temporary object">;
+def warn_ret_local_temp_ref : Warning<
+ "returning reference to local temporary object">;
+def warn_ret_addr_label : Warning<
+ "returning address of label, which is local">;
+def err_ret_local_block : Error<
+ "returning block that lives on the local stack">;
+def note_ref_var_local_bind : Note<
+ "binding reference variable %0 here">;
+
+
+// For non-floating point, expressions of the form x == x or x != x
+// should result in a warning, since these always evaluate to a constant.
+// Array comparisons have similar warnings
+def warn_comparison_always : Warning<
+ "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
+ InGroup<TautologicalCompare>;
+
+def warn_stringcompare : Warning<
+ "result of comparison against %select{a string literal|@encode}0 is "
+ "unspecified (use strncmp instead)">;
+
+
+
+// Blocks
+def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
+ " or pick a deployment target that supports them">;
+def err_expected_block_lbrace : Error<"expected '{' in block literal">;
+def err_return_in_block_expression : Error<
+ "return not allowed in block expression literal">;
+def err_block_returning_array_function : Error<
+ "block cannot return %select{array|function}0 type %1">;
+
+
+// CFString checking
+def err_cfstring_literal_not_string_constant : Error<
+ "CFString literal is not a string constant">;
+def warn_cfstring_literal_contains_nul_character : Warning<
+ "CFString literal contains NUL character">;
+def warn_cfstring_truncated : Warning<
+ "input conversion stopped due to an input byte that does not "
+ "belong to the input codeset UTF-8">;
+
+// Statements.
+def err_continue_not_in_loop : Error<
+ "'continue' statement not in loop statement">;
+def err_break_not_in_loop_or_switch : Error<
+ "'break' statement not in loop or switch statement">;
+def err_default_not_in_switch : Error<
+ "'default' statement not in switch statement">;
+def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
+def warn_bool_switch_condition : Warning<
+ "switch condition has boolean value">;
+def warn_case_value_overflow : Warning<
+ "overflow converting case value to switch condition type (%0 to %1)">,
+ InGroup<DiagGroup<"switch">>;
+def err_duplicate_case : Error<"duplicate case value '%0'">;
+def warn_case_empty_range : Warning<"empty case range specified">;
+def warn_missing_case_for_condition :
+ Warning<"no case matching constant switch condition '%0'">;
+def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case2 : Warning<
+ "enumeration values %0 and %1 not handled in switch">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case3 : Warning<
+ "enumeration values %0, %1, and %2 not handled in switch">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_cases : Warning<
+ "%0 enumeration values not handled in switch: %1, %2, %3...">,
+ InGroup<DiagGroup<"switch-enum"> >;
+
+def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
+ InGroup<DiagGroup<"switch-enum"> >;
+def err_typecheck_statement_requires_scalar : Error<
+ "statement requires expression of scalar type (%0 invalid)">;
+def err_typecheck_statement_requires_integer : Error<
+ "statement requires expression of integer type (%0 invalid)">;
+def err_multiple_default_labels_defined : Error<
+ "multiple default labels in one switch">;
+def err_switch_multiple_conversions : Error<
+ "multiple conversions from switch condition type %0 to an integral or "
+ "enumeration type">;
+def note_switch_conversion : Note<
+ "conversion to %select{integral|enumeration}0 type %1">;
+def err_switch_explicit_conversion : Error<
+ "switch condition type %0 requires explicit conversion to %1">;
+def err_switch_incomplete_class_type : Error<
+ "switch condition has incomplete class type %0">;
+def warn_empty_if_body : Warning<
+ "if statement has empty body">, InGroup<EmptyBody>;
+def err_va_start_used_in_non_variadic_function : Error<
+ "'va_start' used in function with fixed args">;
+def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
+ "second parameter of 'va_start' not last named argument">;
+def err_first_argument_to_va_arg_not_of_type_va_list : Error<
+ "first argument to 'va_arg' is of type %0 and not 'va_list'">;
+
+def warn_return_missing_expr : Warning<
+ "non-void %select{function|method}1 %0 should return a value">, DefaultError,
+ InGroup<ReturnType>;
+def ext_return_missing_expr : ExtWarn<
+ "non-void %select{function|method}1 %0 should return a value">, DefaultError,
+ InGroup<ReturnType>;
+def ext_return_has_expr : ExtWarn<
+ "void %select{function|method}1 %0 should not return a value">, DefaultError,
+ InGroup<ReturnType>;
+def ext_return_has_void_expr : Extension<
+ "void %select{function|method}1 %0 should not return void expression">;
+def warn_noreturn_function_has_return_expr : Warning<
+ "function %0 declared 'noreturn' should not return">,
+ InGroup<DiagGroup<"invalid-noreturn">>;
+def warn_falloff_noreturn_function : Warning<
+ "function declared 'noreturn' should not return">,
+ InGroup<DiagGroup<"invalid-noreturn">>;
+def err_noreturn_block_has_return_expr : Error<
+ "block declared 'noreturn' should not return">;
+def err_block_on_nonlocal : Error<
+ "__block attribute not allowed, only allowed on local variables">;
+def err_block_on_vm : Error<
+ "__block attribute not allowed on declaration with a variably modified type">;
+
+def err_shufflevector_non_vector : Error<
+ "first two arguments to __builtin_shufflevector must be vectors">;
+def err_shufflevector_incompatible_vector : Error<
+ "first two arguments to __builtin_shufflevector must have the same type">;
+def err_shufflevector_nonconstant_argument : Error<
+ "index for __builtin_shufflevector must be a constant integer">;
+def err_shufflevector_argument_too_large : Error<
+ "index for __builtin_shufflevector must be less than the total number "
+ "of vector elements">;
+
+def err_vector_incorrect_num_initializers : Error<
+ "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">;
+def err_altivec_empty_initializer : Error<"expected initializer">;
+
+def err_invalid_neon_type_code : Error<
+ "incompatible constant for this __builtin_neon function">;
+def err_argument_invalid_range : Error<
+ "argument should be a value from %0 to %1">;
+
+def err_builtin_longjmp_invalid_val : Error<
+ "argument to __builtin_longjmp must be a constant 1">;
+
+def err_constant_integer_arg_type : Error<
+ "argument to %0 must be a constant integer">;
+
+def ext_mixed_decls_code : Extension<
+ "ISO C90 forbids mixing declarations and code">,
+ InGroup<DiagGroup<"declaration-after-statement">>;
+
+def err_non_variable_decl_in_for : Error<
+ "declaration of non-local variable in 'for' loop">;
+def err_toomany_element_decls : Error<
+ "only one element declaration is allowed">;
+def err_selector_element_not_lvalue : Error<
+ "selector element is not a valid lvalue">;
+def err_selector_element_type : Error<
+ "selector element type %0 is not a valid object">;
+def err_collection_expr_type : Error<
+ "collection expression type %0 is not a valid object">;
+def warn_collection_expr_type : Warning<
+ "collection expression type %0 may not respond to %1">;
+
+def err_invalid_conversion_between_ext_vectors : Error<
+ "invalid conversion between ext-vector type %0 and %1">;
+
+// Type
+def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
+def warn_receiver_forward_class : Warning<
+ "receiver %0 is a forward class and corresponding @interface may not exist">;
+def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
+def ext_missing_declspec : ExtWarn<
+ "declaration specifier missing, defaulting to 'int'">;
+def ext_missing_type_specifier : ExtWarn<
+ "type specifier missing, defaults to 'int'">,
+ InGroup<ImplicitInt>;
+def err_decimal_unsupported : Error<
+ "GNU decimal type extension not supported">;
+def err_missing_type_specifier : Error<
+ "C++ requires a type specifier for all declarations">;
+def err_missing_param_declspec : Error<
+ "parameter requires a declaration specifier">;
+def err_objc_array_of_interfaces : Error<
+ "array of interface %0 is invalid (probably should be an array of pointers)">;
+def ext_c99_array_usage : Extension<
+ "use of C99-specific array features, accepted as an extension">;
+def err_c99_array_usage_cxx : Error<
+ "C99-specific array features are not permitted in C++">;
+def err_double_requires_fp64 : Error<
+ "use of type 'double' requires cl_khr_fp64 extension to be enabled">;
+
+def note_getter_unavailable : Note<
+ "or because setter is declared here, but no getter method %0 is found">;
+def err_invalid_protocol_qualifiers : Error<
+ "invalid protocol qualifiers on non-ObjC type">;
+def warn_ivar_use_hidden : Warning<
+ "local declaration of %0 hides instance variable">;
+def error_ivar_use_in_class_method : Error<
+ "instance variable %0 accessed in class method">;
+def error_private_ivar_access : Error<"instance variable %0 is private">,
+ AccessControl;
+def error_protected_ivar_access : Error<"instance variable %0 is protected">,
+ AccessControl;
+def warn_maynot_respond : Warning<"%0 may not respond to %1">;
+def warn_attribute_method_def : Warning<
+ "method attribute can only be specified on method declarations">;
+def ext_typecheck_base_super : Warning<
+ "method parameter type %0 does not match "
+ "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore;
+
+// Spell-checking diagnostics
+def err_unknown_typename_suggest : Error<
+ "unknown type name %0; did you mean %1?">;
+def err_unknown_nested_typename_suggest : Error<
+ "no type named %0 in %1; did you mean %2?">;
+def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
+def err_undeclared_use_suggest : Error<
+ "use of undeclared %0; did you mean %1?">;
+def err_undeclared_var_use_suggest : Error<
+ "use of undeclared identifier %0; did you mean %1?">;
+def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
+def err_no_member_template_suggest : Error<
+ "no template named %0 in %1; did you mean %2?">;
+def err_mem_init_not_member_or_class_suggest : Error<
+ "initializer %0 does not name a non-static data member or base "
+ "class; did you mean the %select{base class|member}1 %2?">;
+def err_field_designator_unknown_suggest : Error<
+ "field designator %0 does not refer to any field in type %1; did you mean "
+ "%2?">;
+def err_typecheck_member_reference_ivar_suggest : Error<
+ "%0 does not have a member named %1; did you mean %2?">;
+def err_property_not_found_suggest : Error<
+ "property %0 not found on object of type %1; did you mean %2?">;
+def err_undef_interface_suggest : Error<
+ "cannot find interface declaration for %0; did you mean %1?">;
+def warn_undef_interface_suggest : Warning<
+ "cannot find interface declaration for %0; did you mean %1?">;
+def err_undef_superclass_suggest : Error<
+ "cannot find interface declaration for %0, superclass of %1; did you mean "
+ "%2?">;
+def err_undeclared_protocol_suggest : Error<
+ "cannot find protocol declaration for %0; did you mean %1?">;
+def note_base_class_specified_here : Note<
+ "base class %0 specified here">;
+def err_using_directive_suggest : Error<
+ "no namespace named %0; did you mean %1?">;
+def err_using_directive_member_suggest : Error<
+ "no namespace named %0 in %1; did you mean %2?">;
+def note_namespace_defined_here : Note<"namespace %0 defined here">;
+def err_sizeof_pack_no_pack_name_suggest : Error<
+ "%0 does not refer to the name of a parameter pack; did you mean %1?">;
+def note_parameter_pack_here : Note<"parameter pack %0 declared here">;
+
+} // end of sema category
+} // end of sema component.
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
new file mode 100644
index 0000000..563157f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
@@ -0,0 +1,214 @@
+//===--- FileManager.h - File System Probing and Caching --------*- 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 FileManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FILEMANAGER_H
+#define LLVM_CLANG_FILEMANAGER_H
+
+#include "clang/Basic/FileSystemOptions.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Config/config.h" // for mode_t
+// FIXME: Enhance libsystem to support inode and other fields in stat.
+#include <sys/types.h>
+
+struct stat;
+
+namespace llvm {
+class MemoryBuffer;
+namespace sys { class Path; }
+}
+
+namespace clang {
+class FileManager;
+class FileSystemStatCache;
+
+/// DirectoryEntry - Cached information about one directory (either on
+/// the disk or in the virtual file system).
+///
+class DirectoryEntry {
+ const char *Name; // Name of the directory.
+ friend class FileManager;
+public:
+ DirectoryEntry() : Name(0) {}
+ const char *getName() const { return Name; }
+};
+
+/// FileEntry - Cached information about one file (either on the disk
+/// or in the virtual file system). If the 'FD' member is valid, then
+/// this FileEntry has an open file descriptor for the file.
+///
+class FileEntry {
+ const char *Name; // Name of the file.
+ off_t Size; // File size in bytes.
+ time_t ModTime; // Modification time of file.
+ const DirectoryEntry *Dir; // Directory file lives in.
+ unsigned UID; // A unique (small) ID for the file.
+ dev_t Device; // ID for the device containing the file.
+ ino_t Inode; // Inode number for the file.
+ mode_t FileMode; // The file mode as returned by 'stat'.
+
+ /// FD - The file descriptor for the file entry if it is opened and owned
+ /// by the FileEntry. If not, this is set to -1.
+ mutable int FD;
+ friend class FileManager;
+
+public:
+ FileEntry(dev_t device, ino_t inode, mode_t m)
+ : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {}
+ // Add a default constructor for use with llvm::StringMap
+ FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {}
+
+ FileEntry(const FileEntry &FE) {
+ memcpy(this, &FE, sizeof(FE));
+ assert(FD == -1 && "Cannot copy a file-owning FileEntry");
+ }
+
+ void operator=(const FileEntry &FE) {
+ memcpy(this, &FE, sizeof(FE));
+ assert(FD == -1 && "Cannot assign a file-owning FileEntry");
+ }
+
+ ~FileEntry();
+
+ const char *getName() const { return Name; }
+ off_t getSize() const { return Size; }
+ unsigned getUID() const { return UID; }
+ ino_t getInode() const { return Inode; }
+ dev_t getDevice() const { return Device; }
+ time_t getModificationTime() const { return ModTime; }
+ mode_t getFileMode() const { return FileMode; }
+
+ /// getDir - Return the directory the file lives in.
+ ///
+ const DirectoryEntry *getDir() const { return Dir; }
+
+ bool operator<(const FileEntry &RHS) const {
+ return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
+ }
+};
+
+/// FileManager - Implements support for file system lookup, file system
+/// caching, and directory search management. This also handles more advanced
+/// properties, such as uniquing files based on "inode", so that a file with two
+/// names (e.g. symlinked) will be treated as a single file.
+///
+class FileManager {
+ FileSystemOptions FileSystemOpts;
+
+ class UniqueDirContainer;
+ class UniqueFileContainer;
+
+ /// UniqueRealDirs/UniqueRealFiles - Cache for existing real directories/files.
+ ///
+ UniqueDirContainer &UniqueRealDirs;
+ UniqueFileContainer &UniqueRealFiles;
+
+ /// \brief The virtual directories that we have allocated. For each
+ /// virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
+ /// directories (foo/ and foo/bar/) here.
+ llvm::SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries;
+ /// \brief The virtual files that we have allocated.
+ llvm::SmallVector<FileEntry*, 4> VirtualFileEntries;
+
+ /// SeenDirEntries/SeenFileEntries - This is a cache that maps paths
+ /// to directory/file entries (either real or virtual) we have
+ /// looked up. The actual Entries for real directories/files are
+ /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
+ /// for virtual directories/files are owned by
+ /// VirtualDirectoryEntries/VirtualFileEntries above.
+ ///
+ llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
+ llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
+
+ /// NextFileUID - Each FileEntry we create is assigned a unique ID #.
+ ///
+ unsigned NextFileUID;
+
+ // Statistics.
+ unsigned NumDirLookups, NumFileLookups;
+ unsigned NumDirCacheMisses, NumFileCacheMisses;
+
+ // Caching.
+ llvm::OwningPtr<FileSystemStatCache> StatCache;
+
+ bool getStatValue(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor);
+
+ /// Add all ancestors of the given path (pointing to either a file
+ /// or a directory) as virtual directories.
+ void addAncestorsAsVirtualDirs(llvm::StringRef Path);
+
+public:
+ FileManager(const FileSystemOptions &FileSystemOpts);
+ ~FileManager();
+
+ /// \brief Installs the provided FileSystemStatCache object within
+ /// the FileManager.
+ ///
+ /// Ownership of this object is transferred to the FileManager.
+ ///
+ /// \param statCache the new stat cache to install. Ownership of this
+ /// object is transferred to the FileManager.
+ ///
+ /// \param AtBeginning whether this new stat cache must be installed at the
+ /// beginning of the chain of stat caches. Otherwise, it will be added to
+ /// the end of the chain.
+ void addStatCache(FileSystemStatCache *statCache, bool AtBeginning = false);
+
+ /// \brief Removes the specified FileSystemStatCache object from the manager.
+ void removeStatCache(FileSystemStatCache *statCache);
+
+ /// getDirectory - Lookup, cache, and verify the specified directory
+ /// (real or virtual). This returns NULL if the directory doesn't exist.
+ ///
+ const DirectoryEntry *getDirectory(llvm::StringRef DirName);
+
+ /// getFile - Lookup, cache, and verify the specified file (real or
+ /// virtual). This returns NULL if the file doesn't exist.
+ ///
+ const FileEntry *getFile(llvm::StringRef Filename);
+
+ /// \brief Retrieve a file entry for a "virtual" file that acts as
+ /// if there were a file with the given name on disk. The file
+ /// itself is not accessed.
+ const FileEntry *getVirtualFile(llvm::StringRef Filename, off_t Size,
+ time_t ModificationTime);
+
+ /// \brief Open the specified file as a MemoryBuffer, returning a new
+ /// MemoryBuffer if successful, otherwise returning null.
+ llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
+ std::string *ErrorStr = 0);
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr = 0);
+
+ /// \brief If path is not absolute and FileSystemOptions set the working
+ /// directory, the path is modified to be relative to the given
+ /// working directory.
+ static void FixupRelativePath(llvm::sys::Path &path,
+ const FileSystemOptions &FSOpts);
+
+
+ /// \brief Produce an array mapping from the unique IDs assigned to each
+ /// file to the corresponding FileEntry pointer.
+ void GetUniqueIDMapping(
+ llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
+
+ void PrintStats() const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
new file mode 100644
index 0000000..81e928d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
@@ -0,0 +1,31 @@
+//===--- FileSystemOptions.h - File System Options --------------*- 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 FileSystemOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+#define LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+
+#include <string>
+
+namespace clang {
+
+/// \brief Keeps track of options that affect how file operations are performed.
+class FileSystemOptions {
+public:
+ /// \brief If set, paths are resolved as if the working directory was
+ /// set to the value of WorkingDir.
+ std::string WorkingDir;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
new file mode 100644
index 0000000..77828b3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
@@ -0,0 +1,101 @@
+//===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- 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 FileSystemStatCache interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H
+#define LLVM_CLANG_FILESYSTEMSTATCACHE_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+namespace clang {
+
+/// \brief Abstract interface for introducing a FileManager cache for 'stat'
+/// system calls, which is used by precompiled and pretokenized headers to
+/// improve performance.
+class FileSystemStatCache {
+protected:
+ llvm::OwningPtr<FileSystemStatCache> NextStatCache;
+
+public:
+ virtual ~FileSystemStatCache() {}
+
+ enum LookupResult {
+ CacheExists, //< We know the file exists and its cached stat data.
+ CacheMissing //< We know that the file doesn't exist.
+ };
+
+ /// FileSystemStatCache::get - Get the 'stat' information for the specified
+ /// path, using the cache to accellerate it if possible. This returns true if
+ /// the path does not exist or false if it exists.
+ ///
+ /// If FileDescriptor is non-null, then this lookup should only return success
+ /// for files (not directories). If it is null this lookup should only return
+ /// success for directories (not files). On a successful file lookup, the
+ /// implementation can optionally fill in FileDescriptor with a valid
+ /// descriptor and the client guarantees that it will close it.
+ static bool get(const char *Path, struct stat &StatBuf, int *FileDescriptor,
+ FileSystemStatCache *Cache);
+
+
+ /// \brief Sets the next stat call cache in the chain of stat caches.
+ /// Takes ownership of the given stat cache.
+ void setNextStatCache(FileSystemStatCache *Cache) {
+ NextStatCache.reset(Cache);
+ }
+
+ /// \brief Retrieve the next stat call cache in the chain.
+ FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); }
+
+ /// \brief Retrieve the next stat call cache in the chain, transferring
+ /// ownership of this cache (and, transitively, all of the remaining caches)
+ /// to the caller.
+ FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
+
+protected:
+ virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) = 0;
+
+ LookupResult statChained(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ if (FileSystemStatCache *Next = getNextStatCache())
+ return Next->getStat(Path, StatBuf, FileDescriptor);
+
+ // If we hit the end of the list of stat caches to try, just compute and
+ // return it without a cache.
+ return get(Path, StatBuf, FileDescriptor, 0) ? CacheMissing : CacheExists;
+ }
+};
+
+/// \brief A stat "cache" that can be used by FileManager to keep
+/// track of the results of stat() calls that occur throughout the
+/// execution of the front end.
+class MemorizeStatCalls : public FileSystemStatCache {
+public:
+ /// \brief The set of stat() calls that have been seen.
+ llvm::StringMap<struct stat, llvm::BumpPtrAllocator> StatCalls;
+
+ typedef llvm::StringMap<struct stat, llvm::BumpPtrAllocator>::const_iterator
+ iterator;
+
+ iterator begin() const { return StatCalls.begin(); }
+ iterator end() const { return StatCalls.end(); }
+
+ virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
new file mode 100644
index 0000000..d576643
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -0,0 +1,684 @@
+//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IdentifierInfo, IdentifierTable, and Selector
+// interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <cctype>
+#include <string>
+
+namespace llvm {
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+ class LangOptions;
+ class IdentifierInfo;
+ class IdentifierTable;
+ class SourceLocation;
+ class MultiKeywordSelector; // private class used by Selector
+ class DeclarationName; // AST class that stores declaration names
+
+ /// IdentifierLocPair - A simple pair of identifier info and location.
+ typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
+
+
+/// IdentifierInfo - One of these records is kept for each identifier that
+/// is lexed. This contains information about whether the token was #define'd,
+/// is a language keyword, or if it is a front-end token of some sort (e.g. a
+/// variable or function name). The preprocessor keeps this information in a
+/// set, and all tok::identifier tokens have a pointer to one of these.
+class IdentifierInfo {
+ // Note: DON'T make TokenID a 'tok::TokenKind'; MSVC will treat it as a
+ // signed char and TokenKinds > 127 won't be handled correctly.
+ unsigned TokenID : 8; // Front-end token ID or tok::identifier.
+ // Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
+ // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
+ // are for builtins.
+ unsigned ObjCOrBuiltinID :11;
+ bool HasMacro : 1; // True if there is a #define for this.
+ bool IsExtension : 1; // True if identifier is a lang extension.
+ bool IsPoisoned : 1; // True if identifier is poisoned.
+ bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
+ bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
+ bool IsFromAST : 1; // True if identfier first appeared in an AST
+ // file and wasn't modified since.
+ bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
+ // called.
+ // 6 bits left in 32-bit word.
+ void *FETokenInfo; // Managed by the language front-end.
+ llvm::StringMapEntry<IdentifierInfo*> *Entry;
+
+ IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
+ void operator=(const IdentifierInfo&); // NONASSIGNABLE.
+
+ friend class IdentifierTable;
+
+public:
+ IdentifierInfo();
+
+
+ /// isStr - Return true if this is the identifier for the specified string.
+ /// This is intended to be used for string literals only: II->isStr("foo").
+ template <std::size_t StrLen>
+ bool isStr(const char (&Str)[StrLen]) const {
+ return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1);
+ }
+
+ /// getNameStart - Return the beginning of the actual string for this
+ /// identifier. The returned string is properly null terminated.
+ ///
+ const char *getNameStart() const {
+ if (Entry) return Entry->getKeyData();
+ // FIXME: This is gross. It would be best not to embed specific details
+ // of the PTH file format here.
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ typedef std::pair<IdentifierInfo, const char*> actualtype;
+ return ((const actualtype*) this)->second;
+ }
+
+ /// getLength - Efficiently return the length of this identifier info.
+ ///
+ unsigned getLength() const {
+ if (Entry) return Entry->getKeyLength();
+ // FIXME: This is gross. It would be best not to embed specific details
+ // of the PTH file format here.
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ typedef std::pair<IdentifierInfo, const char*> actualtype;
+ const char* p = ((const actualtype*) this)->second - 2;
+ return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1;
+ }
+
+ /// getName - Return the actual identifier string.
+ llvm::StringRef getName() const {
+ return llvm::StringRef(getNameStart(), getLength());
+ }
+
+ /// hasMacroDefinition - Return true if this identifier is #defined to some
+ /// other value.
+ bool hasMacroDefinition() const {
+ return HasMacro;
+ }
+ void setHasMacroDefinition(bool Val) {
+ if (HasMacro == Val) return;
+
+ HasMacro = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
+ }
+
+ /// getTokenID - If this is a source-language token (e.g. 'for'), this API
+ /// can be used to cause the lexer to map identifiers to source-language
+ /// tokens.
+ tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
+
+ /// \brief True if RevertTokenIDToIdentifier() was called.
+ bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
+
+ /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
+ /// compatibility.
+ ///
+ /// TokenID is normally read-only but there are 2 instances where we revert it
+ /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
+ /// using this method so we can inform serialization about it.
+ void RevertTokenIDToIdentifier() {
+ assert(TokenID != tok::identifier && "Already at tok::identifier");
+ TokenID = tok::identifier;
+ RevertedTokenID = true;
+ }
+
+ /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
+ /// For example, "define" will return tok::pp_define.
+ tok::PPKeywordKind getPPKeywordID() const;
+
+ /// getObjCKeywordID - Return the Objective-C keyword ID for the this
+ /// identifier. For example, 'class' will return tok::objc_class if ObjC is
+ /// enabled.
+ tok::ObjCKeywordKind getObjCKeywordID() const {
+ if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS)
+ return tok::ObjCKeywordKind(ObjCOrBuiltinID);
+ else
+ return tok::objc_not_keyword;
+ }
+ void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
+
+ /// getBuiltinID - Return a value indicating whether this is a builtin
+ /// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
+ /// 2+ are specific builtin functions.
+ unsigned getBuiltinID() const {
+ if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS)
+ return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS;
+ else
+ return 0;
+ }
+ void setBuiltinID(unsigned ID) {
+ ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS;
+ assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID
+ && "ID too large for field!");
+ }
+
+ unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; }
+ void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; }
+
+ /// get/setExtension - Initialize information about whether or not this
+ /// language token is an extension. This controls extension warnings, and is
+ /// only valid if a custom token ID is set.
+ bool isExtensionToken() const { return IsExtension; }
+ void setIsExtensionToken(bool Val) {
+ IsExtension = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the
+ /// Preprocessor will emit an error every time this token is used.
+ void setIsPoisoned(bool Value = true) {
+ IsPoisoned = Value;
+ if (Value)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
+ }
+
+ /// isPoisoned - Return true if this token has been poisoned.
+ bool isPoisoned() const { return IsPoisoned; }
+
+ /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
+ /// this identifier is a C++ alternate representation of an operator.
+ void setIsCPlusPlusOperatorKeyword(bool Val = true) {
+ IsCPPOperatorKeyword = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+ bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
+
+ /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
+ /// associate arbitrary metadata with this token.
+ template<typename T>
+ T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
+ void setFETokenInfo(void *T) { FETokenInfo = T; }
+
+ /// isHandleIdentifierCase - Return true if the Preprocessor::HandleIdentifier
+ /// must be called on a token of this identifier. If this returns false, we
+ /// know that HandleIdentifier will not affect the token.
+ bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
+
+ /// isFromAST - Return true if the identifier in its current state was loaded
+ /// from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
+private:
+ /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
+ /// several special (but rare) things to identifiers of various sorts. For
+ /// example, it changes the "for" keyword token from tok::identifier to
+ /// tok::for.
+ ///
+ /// This method is very tied to the definition of HandleIdentifier. Any
+ /// change to it should be reflected here.
+ void RecomputeNeedsHandleIdentifier() {
+ NeedsHandleIdentifier =
+ (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
+ isExtensionToken());
+ }
+};
+
+/// \brief An iterator that walks over all of the known identifiers
+/// in the lookup table.
+///
+/// Since this iterator uses an abstract interface via virtual
+/// functions, it uses an object-oriented interface rather than the
+/// more standard C++ STL iterator interface. In this OO-style
+/// iteration, the single function \c Next() provides dereference,
+/// advance, and end-of-sequence checking in a single
+/// operation. Subclasses of this iterator type will provide the
+/// actual functionality.
+class IdentifierIterator {
+private:
+ IdentifierIterator(const IdentifierIterator&); // Do not implement
+ IdentifierIterator &operator=(const IdentifierIterator&); // Do not implement
+
+protected:
+ IdentifierIterator() { }
+
+public:
+ virtual ~IdentifierIterator();
+
+ /// \brief Retrieve the next string in the identifier table and
+ /// advances the iterator for the following string.
+ ///
+ /// \returns The next string in the identifier table. If there is
+ /// no such string, returns an empty \c llvm::StringRef.
+ virtual llvm::StringRef Next() = 0;
+};
+
+/// IdentifierInfoLookup - An abstract class used by IdentifierTable that
+/// provides an interface for performing lookups from strings
+/// (const char *) to IdentiferInfo objects.
+class IdentifierInfoLookup {
+public:
+ virtual ~IdentifierInfoLookup();
+
+ /// get - Return the identifier token info for the specified named identifier.
+ /// Unlike the version in IdentifierTable, this returns a pointer instead
+ /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
+ /// be found.
+ virtual IdentifierInfo* get(llvm::StringRef Name) = 0;
+
+ /// \brief Retrieve an iterator into the set of all identifiers
+ /// known to this identifier lookup source.
+ ///
+ /// This routine provides access to all of the identifiers known to
+ /// the identifier lookup, allowing access to the contents of the
+ /// identifiers without introducing the overhead of constructing
+ /// IdentifierInfo objects for each.
+ ///
+ /// \returns A new iterator into the set of known identifiers. The
+ /// caller is responsible for deleting this iterator.
+ virtual IdentifierIterator *getIdentifiers() const;
+};
+
+/// \brief An abstract class used to resolve numerical identifier
+/// references (meaningful only to some external source) into
+/// IdentifierInfo pointers.
+class ExternalIdentifierLookup {
+public:
+ virtual ~ExternalIdentifierLookup();
+
+ /// \brief Return the identifier associated with the given ID number.
+ ///
+ /// The ID 0 is associated with the NULL identifier.
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
+};
+
+/// IdentifierTable - This table implements an efficient mapping from strings to
+/// IdentifierInfo nodes. It has no other purpose, but this is an
+/// extremely performance-critical piece of the code, as each occurrance of
+/// every identifier goes through here when lexed.
+class IdentifierTable {
+ // Shark shows that using MallocAllocator is *much* slower than using this
+ // BumpPtrAllocator!
+ typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy;
+ HashTableTy HashTable;
+
+ IdentifierInfoLookup* ExternalLookup;
+
+public:
+ /// IdentifierTable ctor - Create the identifier table, populating it with
+ /// info about the language keywords for the language specified by LangOpts.
+ IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup* externalLookup = 0);
+
+ /// \brief Set the external identifier lookup mechanism.
+ void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
+ ExternalLookup = IILookup;
+ }
+
+ /// \brief Retrieve the external identifier lookup object, if any.
+ IdentifierInfoLookup *getExternalIdentifierLookup() const {
+ return ExternalLookup;
+ }
+
+ llvm::BumpPtrAllocator& getAllocator() {
+ return HashTable.getAllocator();
+ }
+
+ /// get - Return the identifier token info for the specified named identifier.
+ ///
+ IdentifierInfo &get(llvm::StringRef Name) {
+ llvm::StringMapEntry<IdentifierInfo*> &Entry =
+ HashTable.GetOrCreateValue(Name);
+
+ IdentifierInfo *II = Entry.getValue();
+ if (II) return *II;
+
+ // No entry; if we have an external lookup, look there first.
+ if (ExternalLookup) {
+ II = ExternalLookup->get(Name);
+ if (II) {
+ // Cache in the StringMap for subsequent lookups.
+ Entry.setValue(II);
+ return *II;
+ }
+ }
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+
+ return *II;
+ }
+
+ IdentifierInfo &get(llvm::StringRef Name, tok::TokenKind TokenCode) {
+ IdentifierInfo &II = get(Name);
+ II.TokenID = TokenCode;
+ return II;
+ }
+
+ IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
+ return get(llvm::StringRef(NameStart, NameEnd-NameStart));
+ }
+
+ IdentifierInfo &get(const char *Name, size_t NameLen) {
+ return get(llvm::StringRef(Name, NameLen));
+ }
+
+ /// \brief Gets an IdentifierInfo for the given name without consulting
+ /// external sources.
+ ///
+ /// This is a version of get() meant for external sources that want to
+ /// introduce or modify an identifier. If they called get(), they would
+ /// likely end up in a recursion.
+ IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
+ llvm::StringMapEntry<IdentifierInfo*> &Entry =
+ HashTable.GetOrCreateValue(NameStart, NameEnd);
+
+ IdentifierInfo *II = Entry.getValue();
+ if (!II) {
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+ }
+
+ return *II;
+ }
+ IdentifierInfo &getOwn(llvm::StringRef Name) {
+ return getOwn(Name.begin(), Name.end());
+ }
+
+ typedef HashTableTy::const_iterator iterator;
+ typedef HashTableTy::const_iterator const_iterator;
+
+ iterator begin() const { return HashTable.begin(); }
+ iterator end() const { return HashTable.end(); }
+ unsigned size() const { return HashTable.size(); }
+
+ /// PrintStats - Print some statistics to stderr that indicate how well the
+ /// hashing is doing.
+ void PrintStats() const;
+
+ void AddKeywords(const LangOptions &LangOpts);
+};
+
+/// Selector - This smart pointer class efficiently represents Objective-C
+/// method names. This class will either point to an IdentifierInfo or a
+/// MultiKeywordSelector (which is private). This enables us to optimize
+/// selectors that take no arguments and selectors that take 1 argument, which
+/// accounts for 78% of all selectors in Cocoa.h.
+class Selector {
+ friend class DiagnosticInfo;
+
+ enum IdentifierInfoFlag {
+ // MultiKeywordSelector = 0.
+ ZeroArg = 0x1,
+ OneArg = 0x2,
+ ArgFlags = ZeroArg|OneArg
+ };
+ uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
+
+ Selector(IdentifierInfo *II, unsigned nArgs) {
+ InfoPtr = reinterpret_cast<uintptr_t>(II);
+ assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
+ assert(nArgs < 2 && "nArgs not equal to 0/1");
+ InfoPtr |= nArgs+1;
+ }
+ Selector(MultiKeywordSelector *SI) {
+ InfoPtr = reinterpret_cast<uintptr_t>(SI);
+ assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
+ }
+
+ IdentifierInfo *getAsIdentifierInfo() const {
+ if (getIdentifierInfoFlag())
+ return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
+ return 0;
+ }
+ unsigned getIdentifierInfoFlag() const {
+ return InfoPtr & ArgFlags;
+ }
+
+public:
+ friend class SelectorTable; // only the SelectorTable can create these
+ friend class DeclarationName; // and the AST's DeclarationName.
+
+ /// The default ctor should only be used when creating data structures that
+ /// will contain selectors.
+ Selector() : InfoPtr(0) {}
+ Selector(uintptr_t V) : InfoPtr(V) {}
+
+ /// operator==/!= - Indicate whether the specified selectors are identical.
+ bool operator==(Selector RHS) const {
+ return InfoPtr == RHS.InfoPtr;
+ }
+ bool operator!=(Selector RHS) const {
+ return InfoPtr != RHS.InfoPtr;
+ }
+ void *getAsOpaquePtr() const {
+ return reinterpret_cast<void*>(InfoPtr);
+ }
+
+ /// \brief Determine whether this is the empty selector.
+ bool isNull() const { return InfoPtr == 0; }
+
+ // Predicates to identify the selector type.
+ bool isKeywordSelector() const {
+ return getIdentifierInfoFlag() != ZeroArg;
+ }
+ bool isUnarySelector() const {
+ return getIdentifierInfoFlag() == ZeroArg;
+ }
+ unsigned getNumArgs() const;
+
+
+ /// \brief Retrieve the identifier at a given position in the selector.
+ ///
+ /// Note that the identifier pointer returned may be NULL. Clients that only
+ /// care about the text of the identifier string, and not the specific,
+ /// uniqued identifier pointer, should use \c getNameForSlot(), which returns
+ /// an empty string when the identifier pointer would be NULL.
+ ///
+ /// \param argIndex The index for which we want to retrieve the identifier.
+ /// This index shall be less than \c getNumArgs() unless this is a keyword
+ /// selector, in which case 0 is the only permissible value.
+ ///
+ /// \returns the uniqued identifier for this slot, or NULL if this slot has
+ /// no corresponding identifier.
+ IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
+
+ /// \brief Retrieve the name at a given position in the selector.
+ ///
+ /// \param argIndex The index for which we want to retrieve the name.
+ /// This index shall be less than \c getNumArgs() unless this is a keyword
+ /// selector, in which case 0 is the only permissible value.
+ ///
+ /// \returns the name for this slot, which may be the empty string if no
+ /// name was supplied.
+ llvm::StringRef getNameForSlot(unsigned argIndex) const;
+
+ /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return
+ /// it as an std::string.
+ std::string getAsString() const;
+
+ static Selector getEmptyMarker() {
+ return Selector(uintptr_t(-1));
+ }
+ static Selector getTombstoneMarker() {
+ return Selector(uintptr_t(-2));
+ }
+};
+
+/// SelectorTable - This table allows us to fully hide how we implement
+/// multi-keyword caching.
+class SelectorTable {
+ void *Impl; // Actually a SelectorTableImpl
+ SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
+ void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
+public:
+ SelectorTable();
+ ~SelectorTable();
+
+ /// getSelector - This can create any sort of selector. NumArgs indicates
+ /// whether this is a no argument selector "foo", a single argument selector
+ /// "foo:" or multi-argument "foo:bar:".
+ Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
+
+ Selector getUnarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 1);
+ }
+ Selector getNullarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 0);
+ }
+
+ /// constructSetterName - Return the setter name for the given
+ /// identifier, i.e. "set" + Name where the initial character of Name
+ /// has been capitalized.
+ static Selector constructSetterName(IdentifierTable &Idents,
+ SelectorTable &SelTable,
+ const IdentifierInfo *Name) {
+ llvm::SmallString<100> SelectorName;
+ SelectorName = "set";
+ SelectorName += Name->getName();
+ SelectorName[3] = toupper(SelectorName[3]);
+ IdentifierInfo *SetterName = &Idents.get(SelectorName);
+ return SelTable.getUnarySelector(SetterName);
+ }
+};
+
+/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
+/// CXXSpecialName, and CXXOperatorIdName classes, all of which are
+/// private classes that describe different kinds of names.
+class DeclarationNameExtra {
+public:
+ /// ExtraKind - The kind of "extra" information stored in the
+ /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of
+ /// how these enumerator values are used.
+ enum ExtraKind {
+ CXXConstructor = 0,
+ CXXDestructor,
+ CXXConversionFunction,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ CXXOperator##Name,
+#include "clang/Basic/OperatorKinds.def"
+ CXXLiteralOperator,
+ CXXUsingDirective,
+ NUM_EXTRA_KINDS
+ };
+
+ /// ExtraKindOrNumArgs - Either the kind of C++ special name or
+ /// operator-id (if the value is one of the CXX* enumerators of
+ /// ExtraKind), in which case the DeclarationNameExtra is also a
+ /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or
+ /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName,
+ /// it may be also name common to C++ using-directives (CXXUsingDirective),
+ /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
+ /// arguments in the Objective-C selector, in which case the
+ /// DeclarationNameExtra is also a MultiKeywordSelector.
+ unsigned ExtraKindOrNumArgs;
+};
+
+} // end namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
+/// DenseSets.
+template <>
+struct DenseMapInfo<clang::Selector> {
+ static inline clang::Selector getEmptyKey() {
+ return clang::Selector::getEmptyMarker();
+ }
+ static inline clang::Selector getTombstoneKey() {
+ return clang::Selector::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::Selector S);
+
+ static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <>
+struct isPodLike<clang::Selector> { static const bool value = true; };
+
+template<>
+class PointerLikeTypeTraits<clang::Selector> {
+public:
+ static inline const void *getAsVoidPointer(clang::Selector P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::Selector getFromVoidPointer(const void *P) {
+ return clang::Selector(reinterpret_cast<uintptr_t>(P));
+ }
+ enum { NumLowBitsAvailable = 0 };
+};
+
+// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
+// are not guaranteed to be 8-byte aligned.
+template<>
+class PointerLikeTypeTraits<clang::IdentifierInfo*> {
+public:
+ static inline void *getAsVoidPointer(clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline clang::IdentifierInfo *getFromVoidPointer(void *P) {
+ return static_cast<clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
+template<>
+class PointerLikeTypeTraits<const clang::IdentifierInfo*> {
+public:
+ static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
+ return static_cast<const clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
+} // end namespace llvm
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
new file mode 100644
index 0000000..b148943
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -0,0 +1,273 @@
+//===--- LangOptions.h - C Language Family Language Options -----*- 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 LangOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LANGOPTIONS_H
+#define LLVM_CLANG_LANGOPTIONS_H
+
+#include <string>
+#include "clang/Basic/Visibility.h"
+
+namespace clang {
+
+/// LangOptions - This class keeps track of the various options that can be
+/// enabled, which controls the dialect of C that is accepted.
+class LangOptions {
+public:
+ unsigned Trigraphs : 1; // Trigraphs in source files.
+ unsigned BCPLComment : 1; // BCPL-style '//' comments.
+ unsigned Bool : 1; // 'bool', 'true', 'false' keywords.
+ unsigned DollarIdents : 1; // '$' allowed in identifiers.
+ unsigned AsmPreprocessor : 1; // Preprocessor in asm mode.
+ unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc)
+ unsigned GNUKeywords : 1; // True if GNU-only keywords are allowed
+ unsigned ImplicitInt : 1; // C89 implicit 'int'.
+ unsigned Digraphs : 1; // C94, C99 and C++
+ unsigned HexFloats : 1; // C99 Hexadecimal float constants.
+ unsigned C99 : 1; // C99 Support
+ unsigned Microsoft : 1; // Microsoft extensions.
+ unsigned Borland : 1; // Borland extensions.
+ unsigned CPlusPlus : 1; // C++ Support
+ unsigned CPlusPlus0x : 1; // C++0x Support
+ unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
+
+ unsigned ObjC1 : 1; // Objective-C 1 support enabled.
+ unsigned ObjC2 : 1; // Objective-C 2 support enabled.
+ unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled
+ unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled
+ unsigned ObjCDefaultSynthProperties : 1; // Objective-C auto-synthesized properties.
+ unsigned AppleKext : 1; // Allow apple kext features.
+
+ unsigned PascalStrings : 1; // Allow Pascal strings
+ unsigned WritableStrings : 1; // Allow writable strings
+ unsigned ConstStrings : 1; // Add const qualifier to strings (-Wwrite-strings)
+ unsigned LaxVectorConversions : 1;
+ unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
+ unsigned Exceptions : 1; // Support exception handling.
+ unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
+ unsigned ObjCExceptions : 1; // Support Objective-C exceptions.
+ unsigned RTTI : 1; // Support RTTI information.
+
+ unsigned MSBitfields : 1; // MS-compatible structure layout
+ unsigned NeXTRuntime : 1; // Use NeXT runtime.
+ unsigned Freestanding : 1; // Freestanding implementation
+ unsigned FormatExtensions : 1; // FreeBSD format extensions (-fformat-extensions)
+ unsigned NoBuiltin : 1; // Do not use builtin functions (-fno-builtin)
+
+ unsigned ThreadsafeStatics : 1; // Whether static initializers are protected
+ // by locks.
+ unsigned POSIXThreads : 1; // Compiling with POSIX thread support
+ // (-pthread)
+ unsigned Blocks : 1; // block extension to C
+ unsigned EmitAllDecls : 1; // Emit all declarations, even if
+ // they are unused.
+ unsigned MathErrno : 1; // Math functions must respect errno
+ // (modulo the platform support).
+
+ unsigned HeinousExtensions : 1; // Extensions that we really don't like and
+ // may be ripped out at any time.
+
+ unsigned Optimize : 1; // Whether __OPTIMIZE__ should be defined.
+ unsigned OptimizeSize : 1; // Whether __OPTIMIZE_SIZE__ should be
+ // defined.
+ unsigned Static : 1; // Should __STATIC__ be defined (as
+ // opposed to __DYNAMIC__).
+ unsigned PICLevel : 2; // The value for __PIC__, if non-zero.
+
+ unsigned GNUInline : 1; // Should GNU inline semantics be
+ // used (instead of C99 semantics).
+ unsigned NoInline : 1; // Should __NO_INLINE__ be defined.
+
+ unsigned ObjCGCBitmapPrint : 1; // Enable printing of gc's bitmap layout
+ // for __weak/__strong ivars.
+
+ unsigned AccessControl : 1; // Whether C++ access control should
+ // be enabled.
+ unsigned CharIsSigned : 1; // Whether char is a signed or unsigned type
+ unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int.
+
+ unsigned ShortEnums : 1; // The enum type will be equivalent to the
+ // smallest integer type with enough room.
+
+ unsigned OpenCL : 1; // OpenCL C99 language extensions.
+ unsigned CUDA : 1; // CUDA C++ language extensions.
+
+ unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc))
+ // to the declaration of C++'s new
+ // operators
+ unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
+ // elided if possible.
+ unsigned CatchUndefined : 1; // Generate code to check for undefined ops.
+ unsigned DumpRecordLayouts : 1; /// Dump the layout of IRgen'd records.
+ unsigned DumpVTableLayouts : 1; /// Dump the layouts of emitted vtables.
+ unsigned NoConstantCFStrings : 1; // Do not do CF strings
+ unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have
+ // hidden visibility by default.
+
+ unsigned SpellChecking : 1; // Whether to perform spell-checking for error
+ // recovery.
+ unsigned SinglePrecisionConstants : 1; // Whether to treat double-precision
+ // floating point constants as
+ // single precision constants.
+ unsigned FastRelaxedMath : 1; // OpenCL fast relaxed math (on its own,
+ // defines __FAST_RELAXED_MATH__).
+ unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT
+ // FIXME: This is just a temporary option, for testing purposes.
+ unsigned NoBitFieldTypeAlign : 1;
+
+private:
+ // We declare multibit enums as unsigned because MSVC insists on making enums
+ // signed. Set/Query these values using accessors.
+ unsigned GC : 2; // Objective-C Garbage Collection modes.
+ unsigned SymbolVisibility : 3; // Symbol's visibility.
+ unsigned StackProtector : 2; // Whether stack protectors are on.
+ unsigned SignedOverflowBehavior : 2; // How to handle signed integer overflow.
+
+public:
+ unsigned InstantiationDepth; // Maximum template instantiation depth.
+ unsigned NumLargeByValueCopy; // Warn if parameter/return value is larger
+ // in bytes than this setting. 0 is no check.
+
+ // Version of Microsoft Visual C/C++ we are pretending to be. This is
+ // temporary until we support all MS extensions used in Windows SDK and stdlib
+ // headers. Sets _MSC_VER.
+ unsigned MSCVersion;
+
+ std::string ObjCConstantStringClass;
+
+ enum GCMode { NonGC, GCOnly, HybridGC };
+ enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
+
+ enum SignedOverflowBehaviorTy {
+ SOB_Undefined, // Default C standard behavior.
+ SOB_Defined, // -fwrapv
+ SOB_Trapping // -ftrapv
+ };
+ /// The name of the handler function to be called when -ftrapv is specified.
+ /// If none is specified, abort (GCC-compatible behaviour).
+ std::string OverflowHandler;
+
+ LangOptions() {
+ Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
+ GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0;
+ HexFloats = 0;
+ GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
+ AppleKext = 0;
+ ObjCDefaultSynthProperties = 0;
+ NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
+ C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
+ CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
+ Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
+ ObjCExceptions = 1;
+ MSBitfields = 0;
+ NeXTRuntime = 1;
+ RTTI = 1;
+ LaxVectorConversions = 1;
+ HeinousExtensions = 0;
+ AltiVec = OpenCL = CUDA = StackProtector = 0;
+
+ SymbolVisibility = (unsigned) DefaultVisibility;
+
+ ThreadsafeStatics = 1;
+ POSIXThreads = 0;
+ Blocks = 0;
+ EmitAllDecls = 0;
+ MathErrno = 1;
+ SignedOverflowBehavior = SOB_Undefined;
+
+ AssumeSaneOperatorNew = 1;
+ AccessControl = 1;
+ ElideConstructors = 1;
+
+ SignedOverflowBehavior = 0;
+ ObjCGCBitmapPrint = 0;
+
+ InstantiationDepth = 1024;
+
+ NumLargeByValueCopy = 0;
+ MSCVersion = 0;
+
+ Optimize = 0;
+ OptimizeSize = 0;
+
+ Static = 0;
+ PICLevel = 0;
+
+ GNUInline = 0;
+ NoInline = 0;
+
+ CharIsSigned = 1;
+ ShortWChar = 0;
+ ShortEnums = 0;
+ CatchUndefined = 0;
+ DumpRecordLayouts = 0;
+ DumpVTableLayouts = 0;
+ SpellChecking = 1;
+ SinglePrecisionConstants = 0;
+ FastRelaxedMath = 0;
+ DefaultFPContract = 0;
+ NoBitFieldTypeAlign = 0;
+ }
+
+ GCMode getGCMode() const { return (GCMode) GC; }
+ void setGCMode(GCMode m) { GC = (unsigned) m; }
+
+ StackProtectorMode getStackProtectorMode() const {
+ return static_cast<StackProtectorMode>(StackProtector);
+ }
+ void setStackProtectorMode(StackProtectorMode m) {
+ StackProtector = static_cast<unsigned>(m);
+ }
+
+ Visibility getVisibilityMode() const {
+ return (Visibility) SymbolVisibility;
+ }
+ void setVisibilityMode(Visibility v) { SymbolVisibility = (unsigned) v; }
+
+ SignedOverflowBehaviorTy getSignedOverflowBehavior() const {
+ return (SignedOverflowBehaviorTy)SignedOverflowBehavior;
+ }
+ void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) {
+ SignedOverflowBehavior = (unsigned)V;
+ }
+
+ bool areExceptionsEnabled() const {
+ return Exceptions;
+ }
+};
+
+/// Floating point control options
+class FPOptions {
+public:
+ unsigned fp_contract : 1;
+
+ FPOptions() : fp_contract(0) {}
+
+ FPOptions(const LangOptions &LangOpts) :
+ fp_contract(LangOpts.DefaultFPContract) {}
+};
+
+/// OpenCL volatile options
+class OpenCLOptions {
+public:
+#define OPENCLEXT(nm) unsigned nm : 1;
+#include "clang/Basic/OpenCLExtensions.def"
+
+ OpenCLOptions() {
+#define OPENCLEXT(nm) nm = 0;
+#include "clang/Basic/OpenCLExtensions.def"
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
new file mode 100644
index 0000000..01b6c79
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
@@ -0,0 +1,68 @@
+//===--- Linkage.h - Linkage enumeration and utilities ----------*- 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 Linkage enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_LINKAGE_H
+#define LLVM_CLANG_BASIC_LINKAGE_H
+
+namespace clang {
+
+/// \brief Describes the different kinds of linkage
+/// (C++ [basic.link], C99 6.2.2) that an entity may have.
+enum Linkage {
+ /// \brief No linkage, which means that the entity is unique and
+ /// can only be referred to from within its scope.
+ NoLinkage = 0,
+
+ /// \brief Internal linkage, which indicates that the entity can
+ /// be referred to from within the translation unit (but not other
+ /// translation units).
+ InternalLinkage,
+
+ /// \brief External linkage within a unique namespace. From the
+ /// langauge perspective, these entities have external
+ /// linkage. However, since they reside in an anonymous namespace,
+ /// their names are unique to this translation unit, which is
+ /// equivalent to having internal linkage from the code-generation
+ /// point of view.
+ UniqueExternalLinkage,
+
+ /// \brief External linkage, which indicates that the entity can
+ /// be referred to from other translation units.
+ ExternalLinkage
+};
+
+/// \brief A more specific kind of linkage. This is relevant to CodeGen and
+/// AST file reading.
+enum GVALinkage {
+ GVA_Internal,
+ GVA_C99Inline,
+ GVA_CXXInline,
+ GVA_StrongExternal,
+ GVA_TemplateInstantiation,
+ GVA_ExplicitTemplateInstantiation
+};
+
+/// \brief Determine whether the given linkage is semantically
+/// external.
+inline bool isExternalLinkage(Linkage L) {
+ return L == UniqueExternalLinkage || L == ExternalLinkage;
+}
+
+/// \brief Compute the minimum linkage given two linages.
+static inline Linkage minLinkage(Linkage L1, Linkage L2) {
+ return L1 < L2? L1 : L2;
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_LINKAGE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
new file mode 100644
index 0000000..3287b30
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
@@ -0,0 +1,46 @@
+//===--- MacroBuilder.h - CPP Macro building utility ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MacroBuilder utility class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H
+#define LLVM_CLANG_BASIC_MACROBUILDER_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+class MacroBuilder {
+ llvm::raw_ostream &Out;
+public:
+ MacroBuilder(llvm::raw_ostream &Output) : Out(Output) {}
+
+ /// Append a #define line for macro of the form "#define Name Value\n".
+ void defineMacro(const llvm::Twine &Name, const llvm::Twine &Value = "1") {
+ Out << "#define " << Name << ' ' << Value << '\n';
+ }
+
+ /// Append a #undef line for Name. Name should be of the form XXX
+ /// and we emit "#undef XXX".
+ void undefineMacro(const llvm::Twine &Name) {
+ Out << "#undef " << Name << '\n';
+ }
+
+ /// Directly append Str and a newline to the underlying buffer.
+ void append(const llvm::Twine &Str) {
+ Out << Str << '\n';
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h
new file mode 100644
index 0000000..267ecbc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OnDiskHashTable.h
@@ -0,0 +1,484 @@
+//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- 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 facilities for reading and writing on-disk hash
+// tables.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Host.h"
+#include <cassert>
+#include <cstdlib>
+
+namespace clang {
+
+namespace io {
+
+typedef uint32_t Offset;
+
+inline void Emit8(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+}
+
+inline void Emit16(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ assert((V >> 16) == 0);
+}
+
+inline void Emit24(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ assert((V >> 24) == 0);
+}
+
+inline void Emit32(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ Out << (unsigned char)(V >> 24);
+}
+
+inline void Emit64(llvm::raw_ostream& Out, uint64_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ Out << (unsigned char)(V >> 24);
+ Out << (unsigned char)(V >> 32);
+ Out << (unsigned char)(V >> 40);
+ Out << (unsigned char)(V >> 48);
+ Out << (unsigned char)(V >> 56);
+}
+
+inline void Pad(llvm::raw_ostream& Out, unsigned A) {
+ Offset off = (Offset) Out.tell();
+ uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off;
+ for (; n ; --n)
+ Emit8(Out, 0);
+}
+
+inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
+ uint16_t V = ((uint16_t)Data[0]) |
+ ((uint16_t)Data[1] << 8);
+ Data += 2;
+ return V;
+}
+
+inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) {
+ uint32_t V = ((uint32_t)Data[0]) |
+ ((uint32_t)Data[1] << 8) |
+ ((uint32_t)Data[2] << 16) |
+ ((uint32_t)Data[3] << 24);
+ Data += 4;
+ return V;
+}
+
+inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
+ uint64_t V = ((uint64_t)Data[0]) |
+ ((uint64_t)Data[1] << 8) |
+ ((uint64_t)Data[2] << 16) |
+ ((uint64_t)Data[3] << 24) |
+ ((uint64_t)Data[4] << 32) |
+ ((uint64_t)Data[5] << 40) |
+ ((uint64_t)Data[6] << 48) |
+ ((uint64_t)Data[7] << 56);
+ Data += 8;
+ return V;
+}
+
+inline uint32_t ReadLE32(const unsigned char *&Data) {
+ // Hosts that directly support little-endian 32-bit loads can just
+ // use them. Big-endian hosts need a bswap.
+ uint32_t V = *((uint32_t*)Data);
+ if (llvm::sys::isBigEndianHost())
+ V = llvm::ByteSwap_32(V);
+ Data += 4;
+ return V;
+}
+
+} // end namespace io
+
+template<typename Info>
+class OnDiskChainedHashTableGenerator {
+ unsigned NumBuckets;
+ unsigned NumEntries;
+ llvm::BumpPtrAllocator BA;
+
+ class Item {
+ public:
+ typename Info::key_type key;
+ typename Info::data_type data;
+ Item *next;
+ const uint32_t hash;
+
+ Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
+ Info &InfoObj)
+ : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
+ };
+
+ class Bucket {
+ public:
+ io::Offset off;
+ Item* head;
+ unsigned length;
+
+ Bucket() {}
+ };
+
+ Bucket* Buckets;
+
+private:
+ void insert(Bucket* b, size_t size, Item* E) {
+ unsigned idx = E->hash & (size - 1);
+ Bucket& B = b[idx];
+ E->next = B.head;
+ ++B.length;
+ B.head = E;
+ }
+
+ void resize(size_t newsize) {
+ Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket));
+ // Populate newBuckets with the old entries.
+ for (unsigned i = 0; i < NumBuckets; ++i)
+ for (Item* E = Buckets[i].head; E ; ) {
+ Item* N = E->next;
+ E->next = 0;
+ insert(newBuckets, newsize, E);
+ E = N;
+ }
+
+ free(Buckets);
+ NumBuckets = newsize;
+ Buckets = newBuckets;
+ }
+
+public:
+
+ void insert(typename Info::key_type_ref key,
+ typename Info::data_type_ref data) {
+ Info InfoObj;
+ insert(key, data, InfoObj);
+ }
+
+ void insert(typename Info::key_type_ref key,
+ typename Info::data_type_ref data, Info &InfoObj) {
+
+ ++NumEntries;
+ if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
+ insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
+ InfoObj));
+ }
+
+ io::Offset Emit(llvm::raw_ostream &out) {
+ Info InfoObj;
+ return Emit(out, InfoObj);
+ }
+
+ io::Offset Emit(llvm::raw_ostream &out, Info &InfoObj) {
+ using namespace clang::io;
+
+ // Emit the payload of the table.
+ for (unsigned i = 0; i < NumBuckets; ++i) {
+ Bucket& B = Buckets[i];
+ if (!B.head) continue;
+
+ // Store the offset for the data of this bucket.
+ B.off = out.tell();
+ assert(B.off && "Cannot write a bucket at offset 0. Please add padding.");
+
+ // Write out the number of items in the bucket.
+ Emit16(out, B.length);
+
+ // Write out the entries in the bucket.
+ for (Item *I = B.head; I ; I = I->next) {
+ Emit32(out, I->hash);
+ const std::pair<unsigned, unsigned>& Len =
+ InfoObj.EmitKeyDataLength(out, I->key, I->data);
+ InfoObj.EmitKey(out, I->key, Len.first);
+ InfoObj.EmitData(out, I->key, I->data, Len.second);
+ }
+ }
+
+ // Emit the hashtable itself.
+ Pad(out, 4);
+ io::Offset TableOff = out.tell();
+ Emit32(out, NumBuckets);
+ Emit32(out, NumEntries);
+ for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off);
+
+ return TableOff;
+ }
+
+ OnDiskChainedHashTableGenerator() {
+ NumEntries = 0;
+ NumBuckets = 64;
+ // Note that we do not need to run the constructors of the individual
+ // Bucket objects since 'calloc' returns bytes that are all 0.
+ Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket));
+ }
+
+ ~OnDiskChainedHashTableGenerator() {
+ std::free(Buckets);
+ }
+};
+
+template<typename Info>
+class OnDiskChainedHashTable {
+ const unsigned NumBuckets;
+ const unsigned NumEntries;
+ const unsigned char* const Buckets;
+ const unsigned char* const Base;
+ Info InfoObj;
+
+public:
+ typedef typename Info::internal_key_type internal_key_type;
+ typedef typename Info::external_key_type external_key_type;
+ typedef typename Info::data_type data_type;
+
+ OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries,
+ const unsigned char* buckets,
+ const unsigned char* base,
+ const Info &InfoObj = Info())
+ : NumBuckets(numBuckets), NumEntries(numEntries),
+ Buckets(buckets), Base(base), InfoObj(InfoObj) {
+ assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+ "'buckets' must have a 4-byte alignment");
+ }
+
+ unsigned getNumBuckets() const { return NumBuckets; }
+ unsigned getNumEntries() const { return NumEntries; }
+ const unsigned char* getBase() const { return Base; }
+ const unsigned char* getBuckets() const { return Buckets; }
+
+ bool isEmpty() const { return NumEntries == 0; }
+
+ class iterator {
+ internal_key_type key;
+ const unsigned char* const data;
+ const unsigned len;
+ Info *InfoObj;
+ public:
+ iterator() : data(0), len(0) {}
+ iterator(const internal_key_type k, const unsigned char* d, unsigned l,
+ Info *InfoObj)
+ : key(k), data(d), len(l), InfoObj(InfoObj) {}
+
+ data_type operator*() const { return InfoObj->ReadData(key, data, len); }
+ bool operator==(const iterator& X) const { return X.data == data; }
+ bool operator!=(const iterator& X) const { return X.data != data; }
+ };
+
+ iterator find(const external_key_type& eKey, Info *InfoPtr = 0) {
+ if (!InfoPtr)
+ InfoPtr = &InfoObj;
+
+ using namespace io;
+ const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
+ unsigned key_hash = InfoObj.ComputeHash(iKey);
+
+ // Each bucket is just a 32-bit offset into the hash table file.
+ unsigned idx = key_hash & (NumBuckets - 1);
+ const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx;
+
+ unsigned offset = ReadLE32(Bucket);
+ if (offset == 0) return iterator(); // Empty bucket.
+ const unsigned char* Items = Base + offset;
+
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ unsigned len = ReadUnalignedLE16(Items);
+
+ for (unsigned i = 0; i < len; ++i) {
+ // Read the hash.
+ uint32_t item_hash = ReadUnalignedLE32(Items);
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items);
+ unsigned item_len = L.first + L.second;
+
+ // Compare the hashes. If they are not the same, skip the entry entirely.
+ if (item_hash != key_hash) {
+ Items += item_len;
+ continue;
+ }
+
+ // Read the key.
+ const internal_key_type& X =
+ InfoPtr->ReadKey((const unsigned char* const) Items, L.first);
+
+ // If the key doesn't match just skip reading the value.
+ if (!InfoPtr->EqualKey(X, iKey)) {
+ Items += item_len;
+ continue;
+ }
+
+ // The key matches!
+ return iterator(X, Items + L.first, L.second, InfoPtr);
+ }
+
+ return iterator();
+ }
+
+ iterator end() const { return iterator(); }
+
+ /// \brief Iterates over all of the keys in the table.
+ class key_iterator {
+ const unsigned char* Ptr;
+ unsigned NumItemsInBucketLeft;
+ unsigned NumEntriesLeft;
+ Info *InfoObj;
+ public:
+ typedef external_key_type value_type;
+
+ key_iterator(const unsigned char* const Ptr, unsigned NumEntries,
+ Info *InfoObj)
+ : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
+ InfoObj(InfoObj) { }
+ key_iterator()
+ : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
+
+ friend bool operator==(const key_iterator &X, const key_iterator &Y) {
+ return X.NumEntriesLeft == Y.NumEntriesLeft;
+ }
+ friend bool operator!=(const key_iterator& X, const key_iterator &Y) {
+ return X.NumEntriesLeft != Y.NumEntriesLeft;
+ }
+
+ key_iterator& operator++() { // Preincrement
+ if (!NumItemsInBucketLeft) {
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
+ }
+ Ptr += 4; // Skip the hash.
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
+ Ptr += L.first + L.second;
+ assert(NumItemsInBucketLeft);
+ --NumItemsInBucketLeft;
+ assert(NumEntriesLeft);
+ --NumEntriesLeft;
+ return *this;
+ }
+ key_iterator operator++(int) { // Postincrement
+ key_iterator tmp = *this; ++*this; return tmp;
+ }
+
+ value_type operator*() const {
+ const unsigned char* LocalPtr = Ptr;
+ if (!NumItemsInBucketLeft)
+ LocalPtr += 2; // number of items in bucket
+ LocalPtr += 4; // Skip the hash.
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L
+ = Info::ReadKeyDataLength(LocalPtr);
+
+ // Read the key.
+ const internal_key_type& Key = InfoObj->ReadKey(LocalPtr, L.first);
+ return InfoObj->GetExternalKey(Key);
+ }
+ };
+
+ key_iterator key_begin() {
+ return key_iterator(Base + 4, getNumEntries(), &InfoObj);
+ }
+ key_iterator key_end() { return key_iterator(); }
+
+ /// \brief Iterates over all the entries in the table, returning
+ /// a key/data pair.
+ class item_iterator {
+ const unsigned char* Ptr;
+ unsigned NumItemsInBucketLeft;
+ unsigned NumEntriesLeft;
+ Info *InfoObj;
+ public:
+ typedef std::pair<external_key_type, data_type> value_type;
+
+ item_iterator(const unsigned char* const Ptr, unsigned NumEntries,
+ Info *InfoObj)
+ : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
+ InfoObj(InfoObj) { }
+ item_iterator()
+ : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
+
+ bool operator==(const item_iterator& X) const {
+ return X.NumEntriesLeft == NumEntriesLeft;
+ }
+ bool operator!=(const item_iterator& X) const {
+ return X.NumEntriesLeft != NumEntriesLeft;
+ }
+
+ item_iterator& operator++() { // Preincrement
+ if (!NumItemsInBucketLeft) {
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
+ }
+ Ptr += 4; // Skip the hash.
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
+ Ptr += L.first + L.second;
+ assert(NumItemsInBucketLeft);
+ --NumItemsInBucketLeft;
+ assert(NumEntriesLeft);
+ --NumEntriesLeft;
+ return *this;
+ }
+ item_iterator operator++(int) { // Postincrement
+ item_iterator tmp = *this; ++*this; return tmp;
+ }
+
+ value_type operator*() const {
+ const unsigned char* LocalPtr = Ptr;
+ if (!NumItemsInBucketLeft)
+ LocalPtr += 2; // number of items in bucket
+ LocalPtr += 4; // Skip the hash.
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr);
+
+ // Read the key.
+ const internal_key_type& Key =
+ InfoObj->ReadKey(LocalPtr, L.first);
+ return std::make_pair(InfoObj->GetExternalKey(Key),
+ InfoObj->ReadData(Key, LocalPtr + L.first, L.second));
+ }
+ };
+
+ item_iterator item_begin() {
+ return item_iterator(Base + 4, getNumEntries(), &InfoObj);
+ }
+ item_iterator item_end() { return item_iterator(); }
+
+ static OnDiskChainedHashTable* Create(const unsigned char* buckets,
+ const unsigned char* const base,
+ const Info &InfoObj = Info()) {
+ using namespace io;
+ assert(buckets > base);
+ assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+ "buckets should be 4-byte aligned.");
+
+ unsigned numBuckets = ReadLE32(buckets);
+ unsigned numEntries = ReadLE32(buckets);
+ return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets,
+ base, InfoObj);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
new file mode 100644
index 0000000..95cc1a9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
@@ -0,0 +1,28 @@
+//===--- OpenCLExtensions.def - OpenCL extension list -----------*- 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 list of supported OpenCL extensions.
+//
+//===----------------------------------------------------------------------===//
+
+OPENCLEXT(cl_khr_fp64)
+OPENCLEXT(cl_khr_int64_base_atomics)
+OPENCLEXT(cl_khr_int64_extended_atomics)
+OPENCLEXT(cl_khr_fp16)
+OPENCLEXT(cl_khr_gl_sharing)
+OPENCLEXT(cl_khr_gl_event)
+OPENCLEXT(cl_khr_d3d10_sharing)
+OPENCLEXT(cl_khr_global_int32_base_atomics)
+OPENCLEXT(cl_khr_global_int32_extended_atomics)
+OPENCLEXT(cl_khr_local_int32_base_atomics)
+OPENCLEXT(cl_khr_local_int32_extended_atomics)
+OPENCLEXT(cl_khr_byte_addressable_store)
+OPENCLEXT(cl_khr_3d_image_writes)
+
+#undef OPENCLEXT
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
new file mode 100644
index 0000000..d011e9d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
@@ -0,0 +1,106 @@
+//===--- OperatorKinds.def - C++ Overloaded Operator Database ---*- 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 OverloadedOperator database, which includes
+// all of the overloadable C++ operators.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file OperatorKinds.def
+///
+/// In this file, each of the overloadable C++ operators is enumerated
+/// with either the OVERLOADED_OPERATOR or OVERLOADED_OPERATOR_MULTI
+/// macro, each of which can be specified by the code including this
+/// file. OVERLOADED_OPERATOR is used for single-token operators
+/// (e.g., "+"), and has six arguments:
+///
+/// Name: The name of the token. OO_Name will be the name of the
+/// corresponding enumerator in OverloadedOperatorKind in
+/// OperatorKinds.h.
+///
+/// Spelling: A string that provides a canonical spelling for the
+/// operator, e.g., "operator+".
+///
+/// Token: The name of the token that specifies the operator, e.g.,
+/// "plus" for operator+ or "greatergreaterequal" for
+/// "operator>>=". With a "kw_" prefix, the token name can be used as
+/// an enumerator into the TokenKind enumeration.
+///
+/// Unary: True if the operator can be declared as a unary operator.
+///
+/// Binary: True if the operator can be declared as a binary
+/// operator. Note that some operators (e.g., "operator+" and
+/// "operator*") can be both unary and binary.
+///
+/// MemberOnly: True if this operator can only be declared as a
+/// non-static member function. False if the operator can be both a
+/// non-member function and a non-static member function.
+///
+/// OVERLOADED_OPERATOR_MULTI is used to enumerate the multi-token
+/// overloaded operator names, e.g., "operator delete []". The macro
+/// has all of the parameters of OVERLOADED_OPERATOR except Token,
+/// which is omitted.
+
+#ifndef OVERLOADED_OPERATOR
+# define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)
+#endif
+
+#ifndef OVERLOADED_OPERATOR_MULTI
+# define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) \
+ OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly)
+#endif
+
+OVERLOADED_OPERATOR_MULTI(New , "new" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Delete , "delete" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_New , "new[]" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_Delete , "delete[]" , true , true , false)
+OVERLOADED_OPERATOR(Plus , "+" , plus , true , true , false)
+OVERLOADED_OPERATOR(Minus , "-" , minus , true , true , false)
+OVERLOADED_OPERATOR(Star , "*" , star , true , true , false)
+OVERLOADED_OPERATOR(Slash , "/" , slash , false, true , false)
+OVERLOADED_OPERATOR(Percent , "%" , percent , false, true , false)
+OVERLOADED_OPERATOR(Caret , "^" , caret , false, true , false)
+OVERLOADED_OPERATOR(Amp , "&" , amp , true , true , false)
+OVERLOADED_OPERATOR(Pipe , "|" , pipe , false, true , false)
+OVERLOADED_OPERATOR(Tilde , "~" , tilde , true , false, false)
+OVERLOADED_OPERATOR(Exclaim , "!" , exclaim , true , false, false)
+OVERLOADED_OPERATOR(Equal , "=" , equal , false, true , true)
+OVERLOADED_OPERATOR(Less , "<" , less , false, true , false)
+OVERLOADED_OPERATOR(Greater , ">" , greater , false, true , false)
+OVERLOADED_OPERATOR(PlusEqual , "+=" , plusequal , false, true , false)
+OVERLOADED_OPERATOR(MinusEqual , "-=" , minusequal , false, true , false)
+OVERLOADED_OPERATOR(StarEqual , "*=" , starequal , false, true , false)
+OVERLOADED_OPERATOR(SlashEqual , "/=" , slashequal , false, true , false)
+OVERLOADED_OPERATOR(PercentEqual , "%=" , percentequal , false, true , false)
+OVERLOADED_OPERATOR(CaretEqual , "^=" , caretequal , false, true , false)
+OVERLOADED_OPERATOR(AmpEqual , "&=" , ampequal , false, true , false)
+OVERLOADED_OPERATOR(PipeEqual , "|=" , pipeequal , false, true , false)
+OVERLOADED_OPERATOR(LessLess , "<<" , lessless , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreater , ">>" , greatergreater , false, true , false)
+OVERLOADED_OPERATOR(LessLessEqual , "<<=" , lesslessequal , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreaterEqual , ">>=" , greatergreaterequal, false, true , false)
+OVERLOADED_OPERATOR(EqualEqual , "==" , equalequal , false, true , false)
+OVERLOADED_OPERATOR(ExclaimEqual , "!=" , exclaimequal , false, true , false)
+OVERLOADED_OPERATOR(LessEqual , "<=" , lessequal , false, true , false)
+OVERLOADED_OPERATOR(GreaterEqual , ">=" , greaterequal , false, true , false)
+OVERLOADED_OPERATOR(AmpAmp , "&&" , ampamp , false, true , false)
+OVERLOADED_OPERATOR(PipePipe , "||" , pipepipe , false, true , false)
+OVERLOADED_OPERATOR(PlusPlus , "++" , plusplus , true , true , false)
+OVERLOADED_OPERATOR(MinusMinus , "--" , minusminus , true , true , false)
+OVERLOADED_OPERATOR(Comma , "," , comma , false, true , false)
+OVERLOADED_OPERATOR(ArrowStar , "->*" , arrowstar , false, true , false)
+OVERLOADED_OPERATOR(Arrow , "->" , arrow , true , false, true)
+OVERLOADED_OPERATOR_MULTI(Call , "()" , true , true , true)
+OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, true , true)
+// ?: can *not* be overloaded, but we need the overload
+// resolution machinery for it.
+OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false)
+
+#undef OVERLOADED_OPERATOR_MULTI
+#undef OVERLOADED_OPERATOR
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
new file mode 100644
index 0000000..c0a9505
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
@@ -0,0 +1,35 @@
+//===--- OperatorKinds.h - C++ Overloaded Operators -------------*- 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 C++ overloaded operators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+#define LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+
+namespace clang {
+
+/// OverloadedOperatorKind - Enumeration specifying the different kinds of
+/// C++ overloaded operators.
+enum OverloadedOperatorKind {
+ OO_None, //< Not an overloaded operator
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ OO_##Name,
+#include "clang/Basic/OperatorKinds.def"
+ NUM_OVERLOADED_OPERATORS
+};
+
+/// \brief Retrieve the spelling of the given overloaded operator, without
+/// the preceding "operator" keyword.
+const char *getOperatorSpelling(OverloadedOperatorKind Operator);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
new file mode 100644
index 0000000..d00195b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -0,0 +1,342 @@
+//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a partial diagnostic that can be emitted anwyhere
+// in a DiagnosticBuilder stream.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H
+#define LLVM_CLANG_PARTIALDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace clang {
+
+class PartialDiagnostic {
+public:
+ struct Storage {
+ Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { }
+
+ enum {
+ /// MaxArguments - The maximum number of arguments we can hold. We
+ /// currently only support up to 10 arguments (%0-%9).
+ /// A single diagnostic with more than that almost certainly has to
+ /// be simplified anyway.
+ MaxArguments = 10
+ };
+
+ /// NumDiagArgs - This contains the number of entries in Arguments.
+ unsigned char NumDiagArgs;
+
+ /// NumDiagRanges - This is the number of ranges in the DiagRanges array.
+ unsigned char NumDiagRanges;
+
+ /// \brief The number of code modifications hints in the
+ /// FixItHints array.
+ unsigned char NumFixItHints;
+
+ /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
+ /// values, with one for each argument. This specifies whether the argument
+ /// is in DiagArgumentsStr or in DiagArguments.
+ unsigned char DiagArgumentsKind[MaxArguments];
+
+ /// DiagArgumentsVal - The values for the various substitution positions.
+ /// This is used when the argument is not an std::string. The specific value
+ /// is mangled into an intptr_t and the intepretation depends on exactly
+ /// what sort of argument kind it is.
+ intptr_t DiagArgumentsVal[MaxArguments];
+
+ /// \brief The values for the various substitution positions that have
+ /// string arguments.
+ std::string DiagArgumentsStr[MaxArguments];
+
+ /// DiagRanges - The list of ranges added to this diagnostic. It currently
+ /// only support 10 ranges, could easily be extended if needed.
+ CharSourceRange DiagRanges[10];
+
+ enum { MaxFixItHints = 3 };
+
+ /// FixItHints - If valid, provides a hint with some code
+ /// to insert, remove, or modify at a particular position.
+ FixItHint FixItHints[MaxFixItHints];
+ };
+
+ /// \brief An allocator for Storage objects, which uses a small cache to
+ /// objects, used to reduce malloc()/free() traffic for partial diagnostics.
+ class StorageAllocator {
+ static const unsigned NumCached = 4;
+ Storage Cached[NumCached];
+ Storage *FreeList[NumCached];
+ unsigned NumFreeListEntries;
+
+ public:
+ StorageAllocator();
+ ~StorageAllocator();
+
+ /// \brief Allocate new storage.
+ Storage *Allocate() {
+ if (NumFreeListEntries == 0)
+ return new Storage;
+
+ Storage *Result = FreeList[--NumFreeListEntries];
+ Result->NumDiagArgs = 0;
+ Result->NumDiagRanges = 0;
+ Result->NumFixItHints = 0;
+ return Result;
+ }
+
+ /// \brief Free the given storage object.
+ void Deallocate(Storage *S) {
+ if (S >= Cached && S <= Cached + NumCached) {
+ FreeList[NumFreeListEntries++] = S;
+ return;
+ }
+
+ delete S;
+ }
+ };
+
+private:
+ // NOTE: Sema assumes that PartialDiagnostic is location-invariant
+ // in the sense that its bits can be safely memcpy'ed and destructed
+ // in the new location.
+
+ /// DiagID - The diagnostic ID.
+ mutable unsigned DiagID;
+
+ /// DiagStorage - Storage for args and ranges.
+ mutable Storage *DiagStorage;
+
+ /// \brief Allocator used to allocate storage for this diagnostic.
+ StorageAllocator *Allocator;
+
+ /// \brief Retrieve storage for this particular diagnostic.
+ Storage *getStorage() const {
+ if (DiagStorage)
+ return DiagStorage;
+
+ if (Allocator)
+ DiagStorage = Allocator->Allocate();
+ else {
+ assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)));
+ DiagStorage = new Storage;
+ }
+ return DiagStorage;
+ }
+
+ void freeStorage() {
+ if (!DiagStorage)
+ return;
+
+ if (Allocator)
+ Allocator->Deallocate(DiagStorage);
+ else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
+ delete DiagStorage;
+ DiagStorage = 0;
+ }
+
+ void AddSourceRange(const CharSourceRange &R) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumDiagRanges <
+ llvm::array_lengthof(DiagStorage->DiagRanges) &&
+ "Too many arguments to diagnostic!");
+ DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
+ }
+
+ void AddFixItHint(const FixItHint &Hint) const {
+ if (Hint.isNull())
+ return;
+
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints &&
+ "Too many code modification hints!");
+ DiagStorage->FixItHints[DiagStorage->NumFixItHints++]
+ = Hint;
+ }
+
+public:
+ PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
+ : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { }
+
+ PartialDiagnostic(const PartialDiagnostic &Other)
+ : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator)
+ {
+ if (Other.DiagStorage) {
+ DiagStorage = getStorage();
+ *DiagStorage = *Other.DiagStorage;
+ }
+ }
+
+ PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)
+ : DiagID(Other.DiagID), DiagStorage(DiagStorage),
+ Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
+ {
+ if (Other.DiagStorage)
+ *this->DiagStorage = *Other.DiagStorage;
+ }
+
+ PartialDiagnostic(const DiagnosticInfo &Other, StorageAllocator &Allocator)
+ : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator)
+ {
+ // Copy arguments.
+ for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
+ if (Other.getArgKind(I) == Diagnostic::ak_std_string)
+ AddString(Other.getArgStdStr(I));
+ else
+ AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
+ }
+
+ // Copy source ranges.
+ for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
+ AddSourceRange(Other.getRange(I));
+
+ // Copy fix-its.
+ for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
+ AddFixItHint(Other.getFixItHint(I));
+ }
+
+ PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
+ DiagID = Other.DiagID;
+ if (Other.DiagStorage) {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ *DiagStorage = *Other.DiagStorage;
+ } else {
+ freeStorage();
+ }
+
+ return *this;
+ }
+
+ ~PartialDiagnostic() {
+ freeStorage();
+ }
+
+ unsigned getDiagID() const { return DiagID; }
+
+ void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind;
+ DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
+ }
+
+ void AddString(llvm::StringRef V) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs]
+ = Diagnostic::ak_std_string;
+ DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = V;
+ }
+
+ void Emit(const DiagnosticBuilder &DB) const {
+ if (!DiagStorage)
+ return;
+
+ // Add all arguments.
+ for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
+ if ((Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
+ == Diagnostic::ak_std_string)
+ DB.AddString(DiagStorage->DiagArgumentsStr[i]);
+ else
+ DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
+ (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
+ }
+
+ // Add all ranges.
+ for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
+ DB.AddSourceRange(DiagStorage->DiagRanges[i]);
+
+ // Add all fix-its.
+ for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i)
+ DB.AddFixItHint(DiagStorage->FixItHints[i]);
+ }
+
+ /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
+ /// and removing all of its arguments, ranges, and fix-it hints.
+ void Reset(unsigned DiagID = 0) {
+ this->DiagID = DiagID;
+ freeStorage();
+ }
+
+ bool hasStorage() const { return DiagStorage != 0; }
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ unsigned I) {
+ PD.AddTaggedVal(I, Diagnostic::ak_uint);
+ return PD;
+ }
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ int I) {
+ PD.AddTaggedVal(I, Diagnostic::ak_sint);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const char *S) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ llvm::StringRef S) {
+
+ PD.AddString(S);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const SourceRange &R) {
+ PD.AddSourceRange(CharSourceRange::getTokenRange(R));
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const CharSourceRange &R) {
+ PD.AddSourceRange(R);
+ return PD;
+ }
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const FixItHint &Hint) {
+ PD.AddFixItHint(Hint);
+ return PD;
+ }
+
+};
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const PartialDiagnostic &PD) {
+ PD.Emit(DB);
+ return DB;
+}
+
+/// \brief A partial diagnostic along with the source location where this
+/// diagnostic occurs.
+typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt;
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
new file mode 100644
index 0000000..5a5d551
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
@@ -0,0 +1,37 @@
+//===- clang/Basic/PrettyStackTrace.h - Pretty Crash Handling --*- 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 PrettyStackTraceEntry class, which is used to make
+// crashes give more contextual information about what the program was doing
+// when it crashed.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H
+#define CLANG_BASIC_PRETTYSTACKTRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+ /// PrettyStackTraceLoc - If a crash happens while one of these objects are
+ /// live, the message is printed out along with the specified source location.
+ class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry {
+ SourceManager &SM;
+ SourceLocation Loc;
+ const char *Message;
+ public:
+ PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg)
+ : SM(sm), Loc(L), Message(Msg) {}
+ virtual void print(llvm::raw_ostream &OS) const;
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
new file mode 100644
index 0000000..605c4bb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
@@ -0,0 +1,398 @@
+//===--- SourceLocation.h - Compact identifier for Source Files -*- 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 SourceLocation class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCELOCATION_H
+#define LLVM_CLANG_SOURCELOCATION_H
+
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <utility>
+#include <cassert>
+
+namespace llvm {
+ class MemoryBuffer;
+ class raw_ostream;
+ class StringRef;
+ template <typename T> struct DenseMapInfo;
+ template <typename T> struct isPodLike;
+}
+
+namespace clang {
+
+class SourceManager;
+
+/// FileID - This is an opaque identifier used by SourceManager which refers to
+/// a source file (MemoryBuffer) along with its #include path and #line data.
+///
+class FileID {
+ /// ID - Opaque identifier, 0 is "invalid".
+ unsigned ID;
+public:
+ FileID() : ID(0) {}
+
+ bool isInvalid() const { return ID == 0; }
+
+ bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
+ bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
+ bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
+ bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
+ bool operator>(const FileID &RHS) const { return RHS < *this; }
+ bool operator>=(const FileID &RHS) const { return RHS <= *this; }
+
+ static FileID getSentinel() { return get(~0U); }
+ unsigned getHashValue() const { return ID; }
+
+private:
+ friend class SourceManager;
+ static FileID get(unsigned V) {
+ FileID F;
+ F.ID = V;
+ return F;
+ }
+ unsigned getOpaqueValue() const { return ID; }
+};
+
+
+/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
+/// a full include stack, line and column number information for a position in
+/// an input translation unit.
+class SourceLocation {
+ unsigned ID;
+ friend class SourceManager;
+ enum {
+ MacroIDBit = 1U << 31
+ };
+public:
+
+ SourceLocation() : ID(0) {} // 0 is an invalid FileID.
+
+ bool isFileID() const { return (ID & MacroIDBit) == 0; }
+ bool isMacroID() const { return (ID & MacroIDBit) != 0; }
+
+ /// isValid - Return true if this is a valid SourceLocation object. Invalid
+ /// SourceLocations are often used when events have no corresponding location
+ /// in the source (e.g. a diagnostic is required for a command line option).
+ ///
+ bool isValid() const { return ID != 0; }
+ bool isInvalid() const { return ID == 0; }
+
+private:
+ /// getOffset - Return the index for SourceManager's SLocEntryTable table,
+ /// note that this is not an index *into* it though.
+ unsigned getOffset() const {
+ return ID & ~MacroIDBit;
+ }
+
+ static SourceLocation getFileLoc(unsigned ID) {
+ assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
+ SourceLocation L;
+ L.ID = ID;
+ return L;
+ }
+
+ static SourceLocation getMacroLoc(unsigned ID) {
+ assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
+ SourceLocation L;
+ L.ID = MacroIDBit | ID;
+ return L;
+ }
+public:
+
+ /// getFileLocWithOffset - Return a source location with the specified offset
+ /// from this file SourceLocation.
+ SourceLocation getFileLocWithOffset(int Offset) const {
+ assert(((getOffset()+Offset) & MacroIDBit) == 0 && "invalid location");
+ SourceLocation L;
+ L.ID = ID+Offset;
+ return L;
+ }
+
+ /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) 32-bit integer encoding for it. This should only be passed
+ /// to SourceLocation::getFromRawEncoding, it should not be inspected
+ /// directly.
+ unsigned getRawEncoding() const { return ID; }
+
+ /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
+ /// a real SourceLocation.
+ static SourceLocation getFromRawEncoding(unsigned Encoding) {
+ SourceLocation X;
+ X.ID = Encoding;
+ return X;
+ }
+
+ /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) pointer encoding for it. This should only be passed
+ /// to SourceLocation::getFromPtrEncoding, it should not be inspected
+ /// directly.
+ void* getPtrEncoding() const {
+ // Double cast to avoid a warning "cast to pointer from integer of different
+ // size".
+ return (void*)(uintptr_t)getRawEncoding();
+ }
+
+ /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object
+ /// into a real SourceLocation.
+ static SourceLocation getFromPtrEncoding(void *Encoding) {
+ return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
+ }
+
+ void print(llvm::raw_ostream &OS, const SourceManager &SM) const;
+ void dump(const SourceManager &SM) const;
+};
+
+inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.getRawEncoding() == RHS.getRawEncoding();
+}
+
+inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.getRawEncoding() < RHS.getRawEncoding();
+}
+
+/// SourceRange - a trival tuple used to represent a source range.
+class SourceRange {
+ SourceLocation B;
+ SourceLocation E;
+public:
+ SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
+ SourceRange(SourceLocation loc) : B(loc), E(loc) {}
+ SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
+
+ SourceLocation getBegin() const { return B; }
+ SourceLocation getEnd() const { return E; }
+
+ void setBegin(SourceLocation b) { B = b; }
+ void setEnd(SourceLocation e) { E = e; }
+
+ bool isValid() const { return B.isValid() && E.isValid(); }
+ bool isInvalid() const { return !isValid(); }
+
+ bool operator==(const SourceRange &X) const {
+ return B == X.B && E == X.E;
+ }
+
+ bool operator!=(const SourceRange &X) const {
+ return B != X.B || E != X.E;
+ }
+};
+
+/// CharSourceRange - This class represents a character granular source range.
+/// The underlying SourceRange can either specify the starting/ending character
+/// of the range, or it can specify the start or the range and the start of the
+/// last token of the range (a "token range"). In the token range case, the
+/// size of the last token must be measured to determine the actual end of the
+/// range.
+class CharSourceRange {
+ SourceRange Range;
+ bool IsTokenRange;
+public:
+ CharSourceRange() : IsTokenRange(false) {}
+ CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){}
+
+ static CharSourceRange getTokenRange(SourceRange R) {
+ CharSourceRange Result;
+ Result.Range = R;
+ Result.IsTokenRange = true;
+ return Result;
+ }
+
+ static CharSourceRange getCharRange(SourceRange R) {
+ CharSourceRange Result;
+ Result.Range = R;
+ Result.IsTokenRange = false;
+ return Result;
+ }
+
+ static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
+ return getTokenRange(SourceRange(B, E));
+ }
+ static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
+ return getCharRange(SourceRange(B, E));
+ }
+
+ /// isTokenRange - Return true if the end of this range specifies the start of
+ /// the last token. Return false if the end of this range specifies the last
+ /// character in the range.
+ bool isTokenRange() const { return IsTokenRange; }
+
+ SourceLocation getBegin() const { return Range.getBegin(); }
+ SourceLocation getEnd() const { return Range.getEnd(); }
+ const SourceRange &getAsRange() const { return Range; }
+
+ void setBegin(SourceLocation b) { Range.setBegin(b); }
+ void setEnd(SourceLocation e) { Range.setEnd(e); }
+
+ bool isValid() const { return Range.isValid(); }
+ bool isInvalid() const { return !isValid(); }
+};
+
+/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
+/// for argument passing to functions that expect both objects.
+class FullSourceLoc : public SourceLocation {
+ const SourceManager *SrcMgr;
+public:
+ /// Creates a FullSourceLoc where isValid() returns false.
+ explicit FullSourceLoc() : SrcMgr(0) {}
+
+ explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
+ : SourceLocation(Loc), SrcMgr(&SM) {}
+
+ const SourceManager &getManager() const {
+ assert(SrcMgr && "SourceManager is NULL.");
+ return *SrcMgr;
+ }
+
+ FileID getFileID() const;
+
+ FullSourceLoc getInstantiationLoc() const;
+ FullSourceLoc getSpellingLoc() const;
+
+ unsigned getInstantiationLineNumber(bool *Invalid = 0) const;
+ unsigned getInstantiationColumnNumber(bool *Invalid = 0) const;
+
+ unsigned getSpellingLineNumber(bool *Invalid = 0) const;
+ unsigned getSpellingColumnNumber(bool *Invalid = 0) const;
+
+ const char *getCharacterData(bool *Invalid = 0) const;
+
+ const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
+
+ /// getBufferData - Return a StringRef to the source buffer data for the
+ /// specified FileID.
+ llvm::StringRef getBufferData(bool *Invalid = 0) const;
+
+ /// getDecomposedLoc - Decompose the specified location into a raw FileID +
+ /// Offset pair. The first element is the FileID, the second is the
+ /// offset from the start of the buffer of the location.
+ std::pair<FileID, unsigned> getDecomposedLoc() const;
+
+ bool isInSystemHeader() const;
+
+ /// \brief Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if this source location comes before 'Loc', false otherwise.
+ bool isBeforeInTranslationUnitThan(SourceLocation Loc) const;
+
+ /// \brief Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if this source location comes before 'Loc', false otherwise.
+ bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const {
+ assert(Loc.isValid());
+ assert(SrcMgr == Loc.SrcMgr && "Loc comes from another SourceManager!");
+ return isBeforeInTranslationUnitThan((SourceLocation)Loc);
+ }
+
+ /// Prints information about this FullSourceLoc to stderr. Useful for
+ /// debugging.
+ void dump() const { SourceLocation::dump(*SrcMgr); }
+
+ friend inline bool
+ operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
+ return LHS.getRawEncoding() == RHS.getRawEncoding() &&
+ LHS.SrcMgr == RHS.SrcMgr;
+ }
+
+ friend inline bool
+ operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
+ return !(LHS == RHS);
+ }
+
+};
+
+/// PresumedLoc - This class represents an unpacked "presumed" location which
+/// can be presented to the user. A 'presumed' location can be modified by
+/// #line and GNU line marker directives and is always the instantiation point
+/// of a normal location.
+///
+/// You can get a PresumedLoc from a SourceLocation with SourceManager.
+class PresumedLoc {
+ const char *Filename;
+ unsigned Line, Col;
+ SourceLocation IncludeLoc;
+public:
+ PresumedLoc() : Filename(0) {}
+ PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
+ : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
+ }
+
+ /// isInvalid - Return true if this object is invalid or uninitialized. This
+ /// occurs when created with invalid source locations or when walking off
+ /// the top of a #include stack.
+ bool isInvalid() const { return Filename == 0; }
+ bool isValid() const { return Filename != 0; }
+
+ /// getFilename - Return the presumed filename of this location. This can be
+ /// affected by #line etc.
+ const char *getFilename() const { return Filename; }
+
+ /// getLine - Return the presumed line number of this location. This can be
+ /// affected by #line etc.
+ unsigned getLine() const { return Line; }
+
+ /// getColumn - Return the presumed column number of this location. This can
+ /// not be affected by #line, but is packaged here for convenience.
+ unsigned getColumn() const { return Col; }
+
+ /// getIncludeLoc - Return the presumed include location of this location.
+ /// This can be affected by GNU linemarker directives.
+ SourceLocation getIncludeLoc() const { return IncludeLoc; }
+};
+
+
+} // end namespace clang
+
+namespace llvm {
+ /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
+ /// DenseSets.
+ template <>
+ struct DenseMapInfo<clang::FileID> {
+ static inline clang::FileID getEmptyKey() {
+ return clang::FileID();
+ }
+ static inline clang::FileID getTombstoneKey() {
+ return clang::FileID::getSentinel();
+ }
+
+ static unsigned getHashValue(clang::FileID S) {
+ return S.getHashValue();
+ }
+
+ static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
+ return LHS == RHS;
+ }
+ };
+
+ template <>
+ struct isPodLike<clang::SourceLocation> { static const bool value = true; };
+ template <>
+ struct isPodLike<clang::FileID> { static const bool value = true; };
+
+ // Teach SmallPtrSet how to handle SourceLocation.
+ template<>
+ class PointerLikeTypeTraits<clang::SourceLocation> {
+ public:
+ static inline void *getAsVoidPointer(clang::SourceLocation L) {
+ return L.getPtrEncoding();
+ }
+ static inline clang::SourceLocation getFromVoidPointer(void *P) {
+ return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
new file mode 100644
index 0000000..c0fbd08
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -0,0 +1,886 @@
+//===--- SourceManager.h - Track and cache source files ---------*- 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 SourceManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCEMANAGER_H
+#define LLVM_CLANG_SOURCEMANAGER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+class MemoryBuffer;
+class StringRef;
+}
+
+namespace clang {
+
+class Diagnostic;
+class SourceManager;
+class FileManager;
+class FileEntry;
+class LineTableInfo;
+
+/// SrcMgr - Public enums and private classes that are part of the
+/// SourceManager implementation.
+///
+namespace SrcMgr {
+ /// CharacteristicKind - This is used to represent whether a file or directory
+ /// holds normal user code, system code, or system code which is implicitly
+ /// 'extern "C"' in C++ mode. Entire directories can be tagged with this
+ /// (this is maintained by DirectoryLookup and friends) as can specific
+ /// FileIDInfos when a #pragma system_header is seen or various other cases.
+ ///
+ enum CharacteristicKind {
+ C_User, C_System, C_ExternCSystem
+ };
+
+ /// ContentCache - One instance of this struct is kept for every file
+ /// loaded or used. This object owns the MemoryBuffer object.
+ class ContentCache {
+ enum CCFlags {
+ /// \brief Whether the buffer is invalid.
+ InvalidFlag = 0x01,
+ /// \brief Whether the buffer should not be freed on destruction.
+ DoNotFreeFlag = 0x02
+ };
+
+ /// Buffer - The actual buffer containing the characters from the input
+ /// file. This is owned by the ContentCache object.
+ /// The bits indicate indicates whether the buffer is invalid.
+ mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
+
+ public:
+ /// Reference to the file entry. This reference does not own
+ /// the FileEntry object. It is possible for this to be NULL if
+ /// the ContentCache encapsulates an imaginary text buffer.
+ const FileEntry *Entry;
+
+ /// SourceLineCache - A bump pointer allocated array of offsets for each
+ /// source line. This is lazily computed. This is owned by the
+ /// SourceManager BumpPointerAllocator object.
+ unsigned *SourceLineCache;
+
+ /// NumLines - The number of lines in this ContentCache. This is only valid
+ /// if SourceLineCache is non-null.
+ unsigned NumLines;
+
+ /// getBuffer - Returns the memory buffer for the associated content.
+ ///
+ /// \param Diag Object through which diagnostics will be emitted it the
+ /// buffer cannot be retrieved.
+ ///
+ /// \param Loc If specified, is the location that invalid file diagnostics
+ /// will be emitted at.
+ ///
+ /// \param Invalid If non-NULL, will be set \c true if an error occurred.
+ const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag,
+ const SourceManager &SM,
+ SourceLocation Loc = SourceLocation(),
+ bool *Invalid = 0) const;
+
+ /// getSize - Returns the size of the content encapsulated by this
+ /// ContentCache. This can be the size of the source file or the size of an
+ /// arbitrary scratch buffer. If the ContentCache encapsulates a source
+ /// file this size is retrieved from the file's FileEntry.
+ unsigned getSize() const;
+
+ /// getSizeBytesMapped - Returns the number of bytes actually mapped for
+ /// this ContentCache. This can be 0 if the MemBuffer was not actually
+ /// instantiated.
+ unsigned getSizeBytesMapped() const;
+
+ void setBuffer(const llvm::MemoryBuffer *B) {
+ assert(!Buffer.getPointer() && "MemoryBuffer already set.");
+ Buffer.setPointer(B);
+ Buffer.setInt(false);
+ }
+
+ /// \brief Get the underlying buffer, returning NULL if the buffer is not
+ /// yet available.
+ const llvm::MemoryBuffer *getRawBuffer() const {
+ return Buffer.getPointer();
+ }
+
+ /// \brief Replace the existing buffer (which will be deleted)
+ /// with the given buffer.
+ void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
+
+ /// \brief Determine whether the buffer itself is invalid.
+ bool isBufferInvalid() const {
+ return Buffer.getInt() & InvalidFlag;
+ }
+
+ /// \brief Determine whether the buffer should be freed.
+ bool shouldFreeBuffer() const {
+ return (Buffer.getInt() & DoNotFreeFlag) == 0;
+ }
+
+ ContentCache(const FileEntry *Ent = 0)
+ : Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
+
+ ~ContentCache();
+
+ /// The copy ctor does not allow copies where source object has either
+ /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
+ /// is not transfered, so this is a logical error.
+ ContentCache(const ContentCache &RHS)
+ : Buffer(0, false), SourceLineCache(0)
+ {
+ Entry = RHS.Entry;
+
+ assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0
+ && "Passed ContentCache object cannot own a buffer.");
+
+ NumLines = RHS.NumLines;
+ }
+
+ private:
+ // Disable assignments.
+ ContentCache &operator=(const ContentCache& RHS);
+ };
+
+ /// FileInfo - Information about a FileID, basically just the logical file
+ /// that it represents and include stack information.
+ ///
+ /// Each FileInfo has include stack information, indicating where it came
+ /// from. This information encodes the #include chain that a token was
+ /// instantiated from. The main include file has an invalid IncludeLoc.
+ ///
+ /// FileInfos contain a "ContentCache *", with the contents of the file.
+ ///
+ class FileInfo {
+ /// IncludeLoc - The location of the #include that brought in this file.
+ /// This is an invalid SLOC for the main file (top of the #include chain).
+ unsigned IncludeLoc; // Really a SourceLocation
+
+ /// Data - This contains the ContentCache* and the bits indicating the
+ /// characteristic of the file and whether it has #line info, all bitmangled
+ /// together.
+ uintptr_t Data;
+ public:
+ /// get - Return a FileInfo object.
+ static FileInfo get(SourceLocation IL, const ContentCache *Con,
+ CharacteristicKind FileCharacter) {
+ FileInfo X;
+ X.IncludeLoc = IL.getRawEncoding();
+ X.Data = (uintptr_t)Con;
+ assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned");
+ assert((unsigned)FileCharacter < 4 && "invalid file character");
+ X.Data |= (unsigned)FileCharacter;
+ return X;
+ }
+
+ SourceLocation getIncludeLoc() const {
+ return SourceLocation::getFromRawEncoding(IncludeLoc);
+ }
+ const ContentCache* getContentCache() const {
+ return reinterpret_cast<const ContentCache*>(Data & ~7UL);
+ }
+
+ /// getCharacteristic - Return whether this is a system header or not.
+ CharacteristicKind getFileCharacteristic() const {
+ return (CharacteristicKind)(Data & 3);
+ }
+
+ /// hasLineDirectives - Return true if this FileID has #line directives in
+ /// it.
+ bool hasLineDirectives() const { return (Data & 4) != 0; }
+
+ /// setHasLineDirectives - Set the flag that indicates that this FileID has
+ /// line table entries associated with it.
+ void setHasLineDirectives() {
+ Data |= 4;
+ }
+ };
+
+ /// InstantiationInfo - Each InstantiationInfo encodes the Instantiation
+ /// location - where the token was ultimately instantiated, and the
+ /// SpellingLoc - where the actual character data for the token came from.
+ class InstantiationInfo {
+ // Really these are all SourceLocations.
+
+ /// SpellingLoc - Where the spelling for the token can be found.
+ unsigned SpellingLoc;
+
+ /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these
+ /// indicate the start and end of the instantiation. In object-like macros,
+ /// these will be the same. In a function-like macro instantiation, the
+ /// start will be the identifier and the end will be the ')'.
+ unsigned InstantiationLocStart, InstantiationLocEnd;
+ public:
+ SourceLocation getSpellingLoc() const {
+ return SourceLocation::getFromRawEncoding(SpellingLoc);
+ }
+ SourceLocation getInstantiationLocStart() const {
+ return SourceLocation::getFromRawEncoding(InstantiationLocStart);
+ }
+ SourceLocation getInstantiationLocEnd() const {
+ return SourceLocation::getFromRawEncoding(InstantiationLocEnd);
+ }
+
+ std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const {
+ return std::make_pair(getInstantiationLocStart(),
+ getInstantiationLocEnd());
+ }
+
+ /// get - Return a InstantiationInfo for an expansion. IL specifies
+ /// the instantiation location (where the macro is expanded), and SL
+ /// specifies the spelling location (where the characters from the token
+ /// come from). IL and PL can both refer to normal File SLocs or
+ /// instantiation locations.
+ static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd,
+ SourceLocation SL) {
+ InstantiationInfo X;
+ X.SpellingLoc = SL.getRawEncoding();
+ X.InstantiationLocStart = ILStart.getRawEncoding();
+ X.InstantiationLocEnd = ILEnd.getRawEncoding();
+ return X;
+ }
+ };
+
+ /// SLocEntry - This is a discriminated union of FileInfo and
+ /// InstantiationInfo. SourceManager keeps an array of these objects, and
+ /// they are uniquely identified by the FileID datatype.
+ class SLocEntry {
+ unsigned Offset; // low bit is set for instantiation info.
+ union {
+ FileInfo File;
+ InstantiationInfo Instantiation;
+ };
+ public:
+ unsigned getOffset() const { return Offset >> 1; }
+
+ bool isInstantiation() const { return Offset & 1; }
+ bool isFile() const { return !isInstantiation(); }
+
+ const FileInfo &getFile() const {
+ assert(isFile() && "Not a file SLocEntry!");
+ return File;
+ }
+
+ const InstantiationInfo &getInstantiation() const {
+ assert(isInstantiation() && "Not an instantiation SLocEntry!");
+ return Instantiation;
+ }
+
+ static SLocEntry get(unsigned Offset, const FileInfo &FI) {
+ SLocEntry E;
+ E.Offset = Offset << 1;
+ E.File = FI;
+ return E;
+ }
+
+ static SLocEntry get(unsigned Offset, const InstantiationInfo &II) {
+ SLocEntry E;
+ E.Offset = (Offset << 1) | 1;
+ E.Instantiation = II;
+ return E;
+ }
+ };
+} // end SrcMgr namespace.
+
+/// \brief External source of source location entries.
+class ExternalSLocEntrySource {
+public:
+ virtual ~ExternalSLocEntrySource();
+
+ /// \brief Read the source location entry with index ID.
+ virtual void ReadSLocEntry(unsigned ID) = 0;
+};
+
+
+/// IsBeforeInTranslationUnitCache - This class holds the cache used by
+/// isBeforeInTranslationUnit. The cache structure is complex enough to be
+/// worth breaking out of SourceManager.
+class IsBeforeInTranslationUnitCache {
+ /// L/R QueryFID - These are the FID's of the cached query. If these match up
+ /// with a subsequent query, the result can be reused.
+ FileID LQueryFID, RQueryFID;
+
+ /// CommonFID - This is the file found in common between the two #include
+ /// traces. It is the nearest common ancestor of the #include tree.
+ FileID CommonFID;
+
+ /// L/R CommonOffset - This is the offset of the previous query in CommonFID.
+ /// Usually, this represents the location of the #include for QueryFID, but if
+ /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a
+ /// random token in the parent.
+ unsigned LCommonOffset, RCommonOffset;
+public:
+
+ /// isCacheValid - Return true if the currently cached values match up with
+ /// the specified LHS/RHS query. If not, we can't use the cache.
+ bool isCacheValid(FileID LHS, FileID RHS) const {
+ return LQueryFID == LHS && RQueryFID == RHS;
+ }
+
+ /// getCachedResult - If the cache is valid, compute the result given the
+ /// specified offsets in the LHS/RHS FID's.
+ bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
+ // If one of the query files is the common file, use the offset. Otherwise,
+ // use the #include loc in the common file.
+ if (LQueryFID != CommonFID) LOffset = LCommonOffset;
+ if (RQueryFID != CommonFID) ROffset = RCommonOffset;
+ return LOffset < ROffset;
+ }
+
+ // Set up a new query.
+ void setQueryFIDs(FileID LHS, FileID RHS) {
+ LQueryFID = LHS;
+ RQueryFID = RHS;
+ }
+
+ void setCommonLoc(FileID commonFID, unsigned lCommonOffset,
+ unsigned rCommonOffset) {
+ CommonFID = commonFID;
+ LCommonOffset = lCommonOffset;
+ RCommonOffset = rCommonOffset;
+ }
+
+};
+
+/// SourceManager - This file handles loading and caching of source files into
+/// memory. This object owns the MemoryBuffer objects for all of the loaded
+/// files and assigns unique FileID's for each unique #include chain.
+///
+/// The SourceManager can be queried for information about SourceLocation
+/// objects, turning them into either spelling or instantiation locations.
+/// Spelling locations represent where the bytes corresponding to a token came
+/// from and instantiation locations represent where the location is in the
+/// user's view. In the case of a macro expansion, for example, the spelling
+/// location indicates where the expanded token came from and the instantiation
+/// location specifies where it was expanded.
+class SourceManager {
+ /// \brief Diagnostic object.
+ Diagnostic &Diag;
+
+ FileManager &FileMgr;
+
+ mutable llvm::BumpPtrAllocator ContentCacheAlloc;
+
+ /// FileInfos - Memoized information about all of the files tracked by this
+ /// SourceManager. This set allows us to merge ContentCache entries based
+ /// on their FileEntry*. All ContentCache objects will thus have unique,
+ /// non-null, FileEntry pointers.
+ llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
+
+ /// MemBufferInfos - Information about various memory buffers that we have
+ /// read in. All FileEntry* within the stored ContentCache objects are NULL,
+ /// as they do not refer to a file.
+ std::vector<SrcMgr::ContentCache*> MemBufferInfos;
+
+ /// SLocEntryTable - This is an array of SLocEntry's that we have created.
+ /// FileID is an index into this vector. This array is sorted by the offset.
+ std::vector<SrcMgr::SLocEntry> SLocEntryTable;
+ /// NextOffset - This is the next available offset that a new SLocEntry can
+ /// start at. It is SLocEntryTable.back().getOffset()+size of back() entry.
+ unsigned NextOffset;
+
+ /// \brief If source location entries are being lazily loaded from
+ /// an external source, this vector indicates whether the Ith source
+ /// location entry has already been loaded from the external storage.
+ std::vector<bool> SLocEntryLoaded;
+
+ /// \brief An external source for source location entries.
+ ExternalSLocEntrySource *ExternalSLocEntries;
+
+ /// LastFileIDLookup - This is a one-entry cache to speed up getFileID.
+ /// LastFileIDLookup records the last FileID looked up or created, because it
+ /// is very common to look up many tokens from the same file.
+ mutable FileID LastFileIDLookup;
+
+ /// LineTable - This holds information for #line directives. It is referenced
+ /// by indices from SLocEntryTable.
+ LineTableInfo *LineTable;
+
+ /// LastLineNo - These ivars serve as a cache used in the getLineNumber
+ /// method which is used to speedup getLineNumber calls to nearby locations.
+ mutable FileID LastLineNoFileIDQuery;
+ mutable SrcMgr::ContentCache *LastLineNoContentCache;
+ mutable unsigned LastLineNoFilePos;
+ mutable unsigned LastLineNoResult;
+
+ /// MainFileID - The file ID for the main source file of the translation unit.
+ FileID MainFileID;
+
+ // Statistics for -print-stats.
+ mutable unsigned NumLinearScans, NumBinaryProbes;
+
+ // Cache results for the isBeforeInTranslationUnit method.
+ mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache;
+
+ // SourceManager doesn't support copy construction.
+ explicit SourceManager(const SourceManager&);
+ void operator=(const SourceManager&);
+public:
+ SourceManager(Diagnostic &Diag, FileManager &FileMgr);
+ ~SourceManager();
+
+ void clearIDTables();
+
+ Diagnostic &getDiagnostics() const { return Diag; }
+
+ FileManager &getFileManager() const { return FileMgr; }
+
+ //===--------------------------------------------------------------------===//
+ // MainFileID creation and querying methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getMainFileID - Returns the FileID of the main source file.
+ FileID getMainFileID() const { return MainFileID; }
+
+ /// createMainFileID - Create the FileID for the main source file.
+ FileID createMainFileID(const FileEntry *SourceFile) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
+ return MainFileID;
+ }
+
+ /// \brief Set the file ID for the precompiled preamble, which is also the
+ /// main file.
+ void SetPreambleFileID(FileID Preamble) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = Preamble;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Methods to create new FileID's and instantiations.
+ //===--------------------------------------------------------------------===//
+
+ /// createFileID - Create a new FileID that represents the specified file
+ /// being #included from the specified IncludePosition. This returns 0 on
+ /// error and translates NULL into standard input.
+ /// PreallocateID should be non-zero to specify which pre-allocated,
+ /// lazily computed source location is being filled in by this operation.
+ FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+ return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset);
+ }
+
+ /// createFileIDForMemBuffer - Create a new FileID that represents the
+ /// specified memory buffer. This does no caching of the buffer and takes
+ /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
+ FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0) {
+ return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
+ SrcMgr::C_User, PreallocatedID, Offset);
+ }
+
+ /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
+ /// that will represent the FileID for the main source. One example
+ /// of when this would be used is when the main source is read from STDIN.
+ FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = createFileIDForMemBuffer(Buffer);
+ return MainFileID;
+ }
+
+ /// createInstantiationLoc - Return a new SourceLocation that encodes the fact
+ /// that a token at Loc should actually be referenced from InstantiationLoc.
+ /// TokLength is the length of the token being instantiated.
+ SourceLocation createInstantiationLoc(SourceLocation Loc,
+ SourceLocation InstantiationLocStart,
+ SourceLocation InstantiationLocEnd,
+ unsigned TokLength,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0);
+
+ /// \brief Retrieve the memory buffer associated with the given file.
+ ///
+ /// \param Invalid If non-NULL, will be set \c true if an error
+ /// occurs while retrieving the memory buffer.
+ const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
+ bool *Invalid = 0);
+
+ /// \brief Override the contents of the given source file by providing an
+ /// already-allocated buffer.
+ ///
+ /// \param SourceFile the source file whose contents will be overriden.
+ ///
+ /// \param Buffer the memory buffer whose contents will be used as the
+ /// data in the given source file.
+ ///
+ /// \param DoNotFree If true, then the buffer will not be freed when the
+ /// source manager is destroyed.
+ void overrideFileContents(const FileEntry *SourceFile,
+ const llvm::MemoryBuffer *Buffer,
+ bool DoNotFree = false);
+
+ //===--------------------------------------------------------------------===//
+ // FileID manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getBuffer - Return the buffer for the specified FileID. If there is an
+ /// error opening this buffer the first time, this manufactures a temporary
+ /// buffer and returns a non-empty error string.
+ const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
+ bool *Invalid = 0) const {
+ return getSLocEntry(FID).getFile().getContentCache()
+ ->getBuffer(Diag, *this, Loc, Invalid);
+ }
+
+ const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const {
+ return getSLocEntry(FID).getFile().getContentCache()
+ ->getBuffer(Diag, *this, SourceLocation(), Invalid);
+ }
+
+ /// getFileEntryForID - Returns the FileEntry record for the provided FileID.
+ const FileEntry *getFileEntryForID(FileID FID) const {
+ return getSLocEntry(FID).getFile().getContentCache()->Entry;
+ }
+
+ /// getBufferData - Return a StringRef to the source buffer data for the
+ /// specified FileID.
+ ///
+ /// \param FID The file ID whose contents will be returned.
+ /// \param Invalid If non-NULL, will be set true if an error occurred.
+ llvm::StringRef getBufferData(FileID FID, bool *Invalid = 0) const;
+
+
+ //===--------------------------------------------------------------------===//
+ // SourceLocation manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getFileID - Return the FileID for a SourceLocation. This is a very
+ /// hot method that is used for all SourceManager queries that start with a
+ /// SourceLocation object. It is responsible for finding the entry in
+ /// SLocEntryTable which contains the specified location.
+ ///
+ FileID getFileID(SourceLocation SpellingLoc) const {
+ unsigned SLocOffset = SpellingLoc.getOffset();
+
+ // If our one-entry cache covers this offset, just return it.
+ if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
+ return LastFileIDLookup;
+
+ return getFileIDSlow(SLocOffset);
+ }
+
+ /// getLocForStartOfFile - Return the source location corresponding to the
+ /// first byte of the specified file.
+ SourceLocation getLocForStartOfFile(FileID FID) const {
+ assert(FID.ID < SLocEntryTable.size() && "FileID out of range");
+ assert(getSLocEntry(FID).isFile() && "FileID is not a file");
+ unsigned FileOffset = getSLocEntry(FID).getOffset();
+ return SourceLocation::getFileLoc(FileOffset);
+ }
+
+ /// getInstantiationLoc - Given a SourceLocation object, return the
+ /// instantiation location referenced by the ID.
+ SourceLocation getInstantiationLoc(SourceLocation Loc) const {
+ // Handle the non-mapped case inline, defer to out of line code to handle
+ // instantiations.
+ if (Loc.isFileID()) return Loc;
+ return getInstantiationLocSlowCase(Loc);
+ }
+
+ /// getImmediateInstantiationRange - Loc is required to be an instantiation
+ /// location. Return the start/end of the instantiation information.
+ std::pair<SourceLocation,SourceLocation>
+ getImmediateInstantiationRange(SourceLocation Loc) const;
+
+ /// getInstantiationRange - Given a SourceLocation object, return the
+ /// range of tokens covered by the instantiation in the ultimate file.
+ std::pair<SourceLocation,SourceLocation>
+ getInstantiationRange(SourceLocation Loc) const;
+
+
+ /// getSpellingLoc - Given a SourceLocation object, return the spelling
+ /// location referenced by the ID. This is the place where the characters
+ /// that make up the lexed token can be found.
+ SourceLocation getSpellingLoc(SourceLocation Loc) const {
+ // Handle the non-mapped case inline, defer to out of line code to handle
+ // instantiations.
+ if (Loc.isFileID()) return Loc;
+ return getSpellingLocSlowCase(Loc);
+ }
+
+ /// getImmediateSpellingLoc - Given a SourceLocation object, return the
+ /// spelling location referenced by the ID. This is the first level down
+ /// towards the place where the characters that make up the lexed token can be
+ /// found. This should not generally be used by clients.
+ SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
+
+ /// getDecomposedLoc - Decompose the specified location into a raw FileID +
+ /// Offset pair. The first element is the FileID, the second is the
+ /// offset from the start of the buffer of the location.
+ std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset());
+ }
+
+ /// getDecomposedInstantiationLoc - Decompose the specified location into a
+ /// raw FileID + Offset pair. If the location is an instantiation record,
+ /// walk through it until we find the final location instantiated.
+ std::pair<FileID, unsigned>
+ getDecomposedInstantiationLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+
+ return getDecomposedInstantiationLocSlowCase(E, Offset);
+ }
+
+ /// getDecomposedSpellingLoc - Decompose the specified location into a raw
+ /// FileID + Offset pair. If the location is an instantiation record, walk
+ /// through it until we find its spelling record.
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+ return getDecomposedSpellingLocSlowCase(E, Offset);
+ }
+
+ /// getFileOffset - This method returns the offset from the start
+ /// of the file that the specified SourceLocation represents. This is not very
+ /// meaningful for a macro ID.
+ unsigned getFileOffset(SourceLocation SpellingLoc) const {
+ return getDecomposedLoc(SpellingLoc).second;
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Queries about the code at a SourceLocation.
+ //===--------------------------------------------------------------------===//
+
+ /// getCharacterData - Return a pointer to the start of the specified location
+ /// in the appropriate spelling MemoryBuffer.
+ ///
+ /// \param Invalid If non-NULL, will be set \c true if an error occurs.
+ const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;
+
+ /// getColumnNumber - Return the column # for the specified file position.
+ /// This is significantly cheaper to compute than the line number. This
+ /// returns zero if the column number isn't known. This may only be called on
+ /// a file sloc, so you must choose a spelling or instantiation location
+ /// before calling this method.
+ unsigned getColumnNumber(FileID FID, unsigned FilePos,
+ bool *Invalid = 0) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc,
+ bool *Invalid = 0) const;
+ unsigned getInstantiationColumnNumber(SourceLocation Loc,
+ bool *Invalid = 0) const;
+
+
+ /// getLineNumber - Given a SourceLocation, return the spelling line number
+ /// for the position indicated. This requires building and caching a table of
+ /// line offsets for the MemoryBuffer, so this is not cheap: use only when
+ /// about to emit a diagnostic.
+ unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
+
+ unsigned getInstantiationLineNumber(SourceLocation Loc,
+ bool *Invalid = 0) const;
+ unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
+
+ /// Return the filename or buffer identifier of the buffer the location is in.
+ /// Note that this name does not respect #line directives. Use getPresumedLoc
+ /// for normal clients.
+ const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const;
+
+ /// getFileCharacteristic - return the file characteristic of the specified
+ /// source location, indicating whether this is a normal file, a system
+ /// header, or an "implicit extern C" system header.
+ ///
+ /// This state can be modified with flags on GNU linemarker directives like:
+ /// # 4 "foo.h" 3
+ /// which changes all source locations in the current file after that to be
+ /// considered to be from a system header.
+ SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
+
+ /// getPresumedLoc - This method returns the "presumed" location of a
+ /// SourceLocation specifies. A "presumed location" can be modified by #line
+ /// or GNU line marker directives. This provides a view on the data that a
+ /// user should see in diagnostics, for example.
+ ///
+ /// Note that a presumed location is always given as the instantiation point
+ /// of an instantiation location, not at the spelling location.
+ ///
+ /// \returns The presumed location of the specified SourceLocation. If the
+ /// presumed location cannot be calculate (e.g., because \p Loc is invalid
+ /// or the file containing \p Loc has changed on disk), returns an invalid
+ /// presumed location.
+ PresumedLoc getPresumedLoc(SourceLocation Loc) const;
+
+ /// isFromSameFile - Returns true if both SourceLocations correspond to
+ /// the same file.
+ bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
+ return getFileID(Loc1) == getFileID(Loc2);
+ }
+
+ /// isFromMainFile - Returns true if the file of provided SourceLocation is
+ /// the main file.
+ bool isFromMainFile(SourceLocation Loc) const {
+ return getFileID(Loc) == getMainFileID();
+ }
+
+ /// isInSystemHeader - Returns if a SourceLocation is in a system header.
+ bool isInSystemHeader(SourceLocation Loc) const {
+ return getFileCharacteristic(Loc) != SrcMgr::C_User;
+ }
+
+ /// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C"
+ /// system header.
+ bool isInExternCSystemHeader(SourceLocation Loc) const {
+ return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Line Table Manipulation Routines
+ //===--------------------------------------------------------------------===//
+
+ /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+ ///
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+
+ /// AddLineNote - Add a line note to the line table for the FileID and offset
+ /// specified by Loc. If FilenameID is -1, it is considered to be
+ /// unspecified.
+ void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
+ void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
+ bool IsFileEntry, bool IsFileExit,
+ bool IsSystemHeader, bool IsExternCHeader);
+
+ /// \brief Determine if the source manager has a line table.
+ bool hasLineTable() const { return LineTable != 0; }
+
+ /// \brief Retrieve the stored line table.
+ LineTableInfo &getLineTable();
+
+ //===--------------------------------------------------------------------===//
+ // Other miscellaneous methods.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Get the source location for the given file:line:col triplet.
+ ///
+ /// If the source file is included multiple times, the source location will
+ /// be based upon the first inclusion.
+ SourceLocation getLocation(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col);
+
+ /// \brief Determines the order of 2 source locations in the translation unit.
+ ///
+ /// \returns true if LHS source location comes before RHS, false otherwise.
+ bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
+
+ // Iterators over FileInfos.
+ typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
+ ::const_iterator fileinfo_iterator;
+ fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
+ fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
+ bool hasFileInfo(const FileEntry *File) const {
+ return FileInfos.find(File) != FileInfos.end();
+ }
+
+ /// PrintStats - Print statistics to stderr.
+ ///
+ void PrintStats() const;
+
+ unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
+
+ // FIXME: Exposing this is a little gross; what we want is a good way
+ // to iterate the entries that were not defined in an AST file (or
+ // any other external source).
+ unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }
+
+ const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const {
+ assert(ID < SLocEntryTable.size() && "Invalid id");
+ if (ExternalSLocEntries &&
+ ID < SLocEntryLoaded.size() &&
+ !SLocEntryLoaded[ID])
+ ExternalSLocEntries->ReadSLocEntry(ID);
+ return SLocEntryTable[ID];
+ }
+
+ const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
+ return getSLocEntry(FID.ID);
+ }
+
+ unsigned getNextOffset() const { return NextOffset; }
+
+ /// \brief Preallocate some number of source location entries, which
+ /// will be loaded as needed from the given external source.
+ void PreallocateSLocEntries(ExternalSLocEntrySource *Source,
+ unsigned NumSLocEntries,
+ unsigned NextOffset);
+
+ /// \brief Clear out any preallocated source location entries that
+ /// haven't already been loaded.
+ void ClearPreallocatedSLocEntries();
+
+private:
+ /// isOffsetInFileID - Return true if the specified FileID contains the
+ /// specified SourceLocation offset. This is a very hot method.
+ inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
+ // If the entry is after the offset, it can't contain it.
+ if (SLocOffset < Entry.getOffset()) return false;
+
+ // If this is the last entry than it does. Otherwise, the entry after it
+ // has to not include it.
+ if (FID.ID+1 == SLocEntryTable.size()) return true;
+
+ return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset();
+ }
+
+ /// createFileID - Create a new fileID for the specified ContentCache and
+ /// include position. This works regardless of whether the ContentCache
+ /// corresponds to a file or some other input source.
+ FileID createFileID(const SrcMgr::ContentCache* File,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind DirCharacter,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0);
+
+ const SrcMgr::ContentCache *
+ getOrCreateContentCache(const FileEntry *SourceFile);
+
+ /// createMemBufferContentCache - Create a new ContentCache for the specified
+ /// memory buffer.
+ const SrcMgr::ContentCache*
+ createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
+
+ FileID getFileIDSlow(unsigned SLocOffset) const;
+
+ SourceLocation getInstantiationLocSlowCase(SourceLocation Loc) const;
+ SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
+
+ std::pair<FileID, unsigned>
+ getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const;
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const;
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
new file mode 100644
index 0000000..258989c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
@@ -0,0 +1,130 @@
+//===--- SourceManagerInternals.h - SourceManager Internals -----*- 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 implementation details of the SourceManager
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
+#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringMap.h"
+#include <map>
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// Line Table Implementation
+//===----------------------------------------------------------------------===//
+
+struct LineEntry {
+ /// FileOffset - The offset in this file that the line entry occurs at.
+ unsigned FileOffset;
+
+ /// LineNo - The presumed line number of this line entry: #line 4.
+ unsigned LineNo;
+
+ /// FilenameID - The ID of the filename identified by this line entry:
+ /// #line 4 "foo.c". This is -1 if not specified.
+ int FilenameID;
+
+ /// Flags - Set the 0 if no flags, 1 if a system header,
+ SrcMgr::CharacteristicKind FileKind;
+
+ /// IncludeOffset - This is the offset of the virtual include stack location,
+ /// which is manipulated by GNU linemarker directives. If this is 0 then
+ /// there is no virtual #includer.
+ unsigned IncludeOffset;
+
+ static LineEntry get(unsigned Offs, unsigned Line, int Filename,
+ SrcMgr::CharacteristicKind FileKind,
+ unsigned IncludeOffset) {
+ LineEntry E;
+ E.FileOffset = Offs;
+ E.LineNo = Line;
+ E.FilenameID = Filename;
+ E.FileKind = FileKind;
+ E.IncludeOffset = IncludeOffset;
+ return E;
+ }
+};
+
+// needed for FindNearestLineEntry (upper_bound of LineEntry)
+inline bool operator<(const LineEntry &lhs, const LineEntry &rhs) {
+ // FIXME: should check the other field?
+ return lhs.FileOffset < rhs.FileOffset;
+}
+
+inline bool operator<(const LineEntry &E, unsigned Offset) {
+ return E.FileOffset < Offset;
+}
+
+inline bool operator<(unsigned Offset, const LineEntry &E) {
+ return Offset < E.FileOffset;
+}
+
+/// LineTableInfo - This class is used to hold and unique data used to
+/// represent #line information.
+class LineTableInfo {
+ /// FilenameIDs - This map is used to assign unique IDs to filenames in
+ /// #line directives. This allows us to unique the filenames that
+ /// frequently reoccur and reference them with indices. FilenameIDs holds
+ /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
+ /// to string.
+ llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
+ std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
+
+ /// LineEntries - This is a map from FileIDs to a list of line entries (sorted
+ /// by the offset they occur in the file.
+ std::map<unsigned, std::vector<LineEntry> > LineEntries;
+public:
+ LineTableInfo() {
+ }
+
+ void clear() {
+ FilenameIDs.clear();
+ FilenamesByID.clear();
+ LineEntries.clear();
+ }
+
+ ~LineTableInfo() {}
+
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+ const char *getFilename(unsigned ID) const {
+ assert(ID < FilenamesByID.size() && "Invalid FilenameID");
+ return FilenamesByID[ID]->getKeyData();
+ }
+ unsigned getNumFilenames() const { return FilenamesByID.size(); }
+
+ void AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID);
+ void AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID,
+ unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
+
+
+ /// FindNearestLineEntry - Find the line entry nearest to FID that is before
+ /// it. If there is no line entry before Offset in FID, return null.
+ const LineEntry *FindNearestLineEntry(unsigned FID, unsigned Offset);
+
+ // Low-level access
+ typedef std::map<unsigned, std::vector<LineEntry> >::iterator iterator;
+ iterator begin() { return LineEntries.begin(); }
+ iterator end() { return LineEntries.end(); }
+
+ /// \brief Add a new line entry that has already been encoded into
+ /// the internal representation of the line table.
+ void AddEntry(unsigned FID, const std::vector<LineEntry> &Entries);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
new file mode 100644
index 0000000..e6b6218
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
@@ -0,0 +1,162 @@
+//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various enumerations that describe declaration and
+// type specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
+#define LLVM_CLANG_BASIC_SPECIFIERS_H
+
+namespace clang {
+ /// \brief Specifies the width of a type, e.g., short, long, or long long.
+ enum TypeSpecifierWidth {
+ TSW_unspecified,
+ TSW_short,
+ TSW_long,
+ TSW_longlong
+ };
+
+ /// \brief Specifies the signedness of a type, e.g., signed or unsigned.
+ enum TypeSpecifierSign {
+ TSS_unspecified,
+ TSS_signed,
+ TSS_unsigned
+ };
+
+ /// \brief Specifies the kind of type.
+ enum TypeSpecifierType {
+ TST_unspecified,
+ TST_void,
+ TST_char,
+ TST_wchar, // C++ wchar_t
+ TST_char16, // C++0x char16_t
+ TST_char32, // C++0x char32_t
+ TST_int,
+ TST_float,
+ TST_double,
+ TST_bool, // _Bool
+ TST_decimal32, // _Decimal32
+ TST_decimal64, // _Decimal64
+ TST_decimal128, // _Decimal128
+ TST_enum,
+ TST_union,
+ TST_struct,
+ TST_class, // C++ class type
+ TST_typename, // Typedef, C++ class-name or enum name, etc.
+ TST_typeofType,
+ TST_typeofExpr,
+ TST_decltype, // C++0x decltype
+ TST_auto, // C++0x auto
+ TST_error // erroneous type
+ };
+
+ /// WrittenBuiltinSpecs - Structure that packs information about the
+ /// type specifiers that were written in a particular type specifier
+ /// sequence.
+ struct WrittenBuiltinSpecs {
+ /*DeclSpec::TST*/ unsigned Type : 5;
+ /*DeclSpec::TSS*/ unsigned Sign : 2;
+ /*DeclSpec::TSW*/ unsigned Width : 2;
+ bool ModeAttr : 1;
+ };
+
+ /// AccessSpecifier - A C++ access specifier (public, private,
+ /// protected), plus the special value "none" which means
+ /// different things in different contexts.
+ enum AccessSpecifier {
+ AS_public,
+ AS_protected,
+ AS_private,
+ AS_none
+ };
+
+ /// ExprValueKind - The categorization of expression values,
+ /// currently following the C++0x scheme.
+ enum ExprValueKind {
+ /// An r-value expression (a gr-value in the C++0x taxonomy)
+ /// produces a temporary value.
+ VK_RValue,
+
+ /// An l-value expression is a reference to an object with
+ /// independent storage.
+ VK_LValue,
+
+ /// An x-value expression is a reference to an object with
+ /// independent storage but which can be "moved", i.e.
+ /// efficiently cannibalized for its resources.
+ VK_XValue
+ };
+
+ /// A further classification of the kind of object referenced by an
+ /// l-value or x-value.
+ enum ExprObjectKind {
+ /// An ordinary object is located at an address in memory.
+ OK_Ordinary,
+
+ /// A bitfield object is a bitfield on a C or C++ record.
+ OK_BitField,
+
+ /// A vector component is an element or range of elements on a vector.
+ OK_VectorComponent,
+
+ /// An Objective C property is a logical field of an Objective-C
+ /// object which is read and written via Objective C method calls.
+ OK_ObjCProperty
+ };
+
+ // \brief Describes the kind of template specialization that a
+ // particular template specialization declaration represents.
+ enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation declaration request
+ /// (C++0x [temp.explicit]).
+ TSK_ExplicitInstantiationDeclaration,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation definition request
+ /// (C++ [temp.explicit]).
+ TSK_ExplicitInstantiationDefinition
+ };
+
+ /// \brief Storage classes.
+ enum StorageClass {
+ // These are legal on both functions and variables.
+ SC_None,
+ SC_Extern,
+ SC_Static,
+ SC_PrivateExtern,
+
+ // These are only legal on variables.
+ SC_Auto,
+ SC_Register
+ };
+
+ /// Checks whether the given storage class is legal for functions.
+ inline bool isLegalForFunction(StorageClass SC) {
+ return SC <= SC_PrivateExtern;
+ }
+
+ /// Checks whether the given storage class is legal for variables.
+ inline bool isLegalForVariable(StorageClass SC) {
+ return true;
+ }
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
new file mode 100644
index 0000000..be0d8ff
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
@@ -0,0 +1,141 @@
+class AttrSubject;
+
+class Stmt<bit abstract = 0> : AttrSubject {
+ bit Abstract = abstract;
+}
+
+class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> {
+ Stmt Base = base;
+}
+
+// Statements
+def NullStmt : Stmt;
+def CompoundStmt : Stmt;
+def LabelStmt : Stmt;
+def IfStmt : Stmt;
+def SwitchStmt : Stmt;
+def WhileStmt : Stmt;
+def DoStmt : Stmt;
+def ForStmt : Stmt;
+def GotoStmt : Stmt;
+def IndirectGotoStmt : Stmt;
+def ContinueStmt : Stmt;
+def BreakStmt : Stmt;
+def ReturnStmt : Stmt;
+def DeclStmt : Stmt;
+def SwitchCase : Stmt<1>;
+def CaseStmt : DStmt<SwitchCase>;
+def DefaultStmt : DStmt<SwitchCase>;
+
+// GNU Extensions
+def AsmStmt : Stmt;
+
+// Obj-C statements
+def ObjCAtTryStmt : Stmt;
+def ObjCAtCatchStmt : Stmt;
+def ObjCAtFinallyStmt : Stmt;
+def ObjCAtThrowStmt : Stmt;
+def ObjCAtSynchronizedStmt : Stmt;
+def ObjCForCollectionStmt : Stmt;
+
+// C++ statments
+def CXXCatchStmt : Stmt;
+def CXXTryStmt : Stmt;
+
+// Expressions
+def Expr : Stmt<1>;
+def PredefinedExpr : DStmt<Expr>;
+def DeclRefExpr : DStmt<Expr>;
+def IntegerLiteral : DStmt<Expr>;
+def FloatingLiteral : DStmt<Expr>;
+def ImaginaryLiteral : DStmt<Expr>;
+def StringLiteral : DStmt<Expr>;
+def CharacterLiteral : DStmt<Expr>;
+def ParenExpr : DStmt<Expr>;
+def UnaryOperator : DStmt<Expr>;
+def OffsetOfExpr : DStmt<Expr>;
+def SizeOfAlignOfExpr : DStmt<Expr>;
+def ArraySubscriptExpr : DStmt<Expr>;
+def CallExpr : DStmt<Expr>;
+def MemberExpr : DStmt<Expr>;
+def CastExpr : DStmt<Expr, 1>;
+def BinaryOperator : DStmt<Expr>;
+def CompoundAssignOperator : DStmt<BinaryOperator>;
+def AbstractConditionalOperator : DStmt<Expr, 1>;
+def ConditionalOperator : DStmt<AbstractConditionalOperator>;
+def BinaryConditionalOperator : DStmt<AbstractConditionalOperator>;
+def ImplicitCastExpr : DStmt<CastExpr>;
+def ExplicitCastExpr : DStmt<CastExpr, 1>;
+def CStyleCastExpr : DStmt<ExplicitCastExpr>;
+def CompoundLiteralExpr : DStmt<Expr>;
+def ExtVectorElementExpr : DStmt<Expr>;
+def InitListExpr : DStmt<Expr>;
+def DesignatedInitExpr : DStmt<Expr>;
+def ImplicitValueInitExpr : DStmt<Expr>;
+def ParenListExpr : DStmt<Expr>;
+def VAArgExpr : DStmt<Expr>;
+
+// GNU Extensions.
+def AddrLabelExpr : DStmt<Expr>;
+def StmtExpr : DStmt<Expr>;
+def ChooseExpr : DStmt<Expr>;
+def GNUNullExpr : DStmt<Expr>;
+
+// C++ Expressions.
+def CXXOperatorCallExpr : DStmt<CallExpr>;
+def CXXMemberCallExpr : DStmt<CallExpr>;
+def CXXNamedCastExpr : DStmt<ExplicitCastExpr, 1>;
+def CXXStaticCastExpr : DStmt<CXXNamedCastExpr>;
+def CXXDynamicCastExpr : DStmt<CXXNamedCastExpr>;
+def CXXReinterpretCastExpr : DStmt<CXXNamedCastExpr>;
+def CXXConstCastExpr : DStmt<CXXNamedCastExpr>;
+def CXXFunctionalCastExpr : DStmt<ExplicitCastExpr>;
+def CXXTypeidExpr : DStmt<Expr>;
+def CXXBoolLiteralExpr : DStmt<Expr>;
+def CXXNullPtrLiteralExpr : DStmt<Expr>;
+def CXXThisExpr : DStmt<Expr>;
+def CXXThrowExpr : DStmt<Expr>;
+def CXXDefaultArgExpr : DStmt<Expr>;
+def CXXScalarValueInitExpr : DStmt<Expr>;
+def CXXNewExpr : DStmt<Expr>;
+def CXXDeleteExpr : DStmt<Expr>;
+def CXXPseudoDestructorExpr : DStmt<Expr>;
+def UnaryTypeTraitExpr : DStmt<Expr>;
+def BinaryTypeTraitExpr : DStmt<Expr>;
+def DependentScopeDeclRefExpr : DStmt<Expr>;
+def CXXConstructExpr : DStmt<Expr>;
+def CXXBindTemporaryExpr : DStmt<Expr>;
+def ExprWithCleanups : DStmt<Expr>;
+def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
+def CXXUnresolvedConstructExpr : DStmt<Expr>;
+def CXXDependentScopeMemberExpr : DStmt<Expr>;
+def OverloadExpr : DStmt<Expr, 1>;
+def UnresolvedLookupExpr : DStmt<OverloadExpr>;
+def UnresolvedMemberExpr : DStmt<OverloadExpr>;
+def CXXNoexceptExpr : DStmt<Expr>;
+def PackExpansionExpr : DStmt<Expr>;
+def SizeOfPackExpr : DStmt<Expr>;
+def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
+
+// Obj-C Expressions.
+def ObjCStringLiteral : DStmt<Expr>;
+def ObjCEncodeExpr : DStmt<Expr>;
+def ObjCMessageExpr : DStmt<Expr>;
+def ObjCSelectorExpr : DStmt<Expr>;
+def ObjCProtocolExpr : DStmt<Expr>;
+def ObjCIvarRefExpr : DStmt<Expr>;
+def ObjCPropertyRefExpr : DStmt<Expr>;
+def ObjCIsaExpr : DStmt<Expr>;
+
+// CUDA Expressions.
+def CUDAKernelCallExpr : DStmt<CallExpr>;
+
+// Clang Extensions.
+def ShuffleVectorExpr : DStmt<Expr>;
+def BlockExpr : DStmt<Expr>;
+def BlockDeclRefExpr : DStmt<Expr>;
+def OpaqueValueExpr : DStmt<Expr>;
+
+// Microsoft Extensions.
+def CXXUuidofExpr : DStmt<Expr>;
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
new file mode 100644
index 0000000..f1edd1d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
@@ -0,0 +1,50 @@
+//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H
+#define LLVM_CLANG_BASIC_TARGET_BUILTINS_H
+
+#include "clang/Basic/Builtins.h"
+#undef PPC
+
+namespace clang {
+
+ /// ARM builtins
+ namespace ARM {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsARM.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// PPC builtins
+ namespace PPC {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsPPC.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// X86 builtins
+ namespace X86 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsX86.def"
+ LastTSBuiltin
+ };
+ }
+
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
new file mode 100644
index 0000000..b9087f2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
@@ -0,0 +1,553 @@
+//===--- TargetInfo.h - Expose information about the target -----*- 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 TargetInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
+#define LLVM_CLANG_BASIC_TARGETINFO_H
+
+// FIXME: Daniel isn't smart enough to use a prototype for this.
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <vector>
+#include <string>
+
+namespace llvm {
+struct fltSemantics;
+class StringRef;
+}
+
+namespace clang {
+class Diagnostic;
+class LangOptions;
+class MacroBuilder;
+class SourceLocation;
+class SourceManager;
+class TargetOptions;
+
+namespace Builtin { struct Info; }
+
+/// TargetCXXABI - The types of C++ ABIs for which we can generate code.
+enum TargetCXXABI {
+ /// The generic ("Itanium") C++ ABI, documented at:
+ /// http://www.codesourcery.com/public/cxx-abi/
+ CXXABI_Itanium,
+
+ /// The ARM C++ ABI, based largely on the Itanium ABI but with
+ /// significant differences.
+ /// http://infocenter.arm.com
+ /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+ CXXABI_ARM,
+
+ /// The Visual Studio ABI. Only scattered official documentation exists.
+ CXXABI_Microsoft
+};
+
+/// TargetInfo - This class exposes information about the current target.
+///
+class TargetInfo {
+ llvm::Triple Triple;
+protected:
+ // Target values set by the ctor of the actual target implementation. Default
+ // values are specified by the TargetInfo constructor.
+ bool TLSSupported;
+ bool NoAsmVariants; // True if {|} are normal characters.
+ unsigned char PointerWidth, PointerAlign;
+ unsigned char BoolWidth, BoolAlign;
+ unsigned char IntWidth, IntAlign;
+ unsigned char FloatWidth, FloatAlign;
+ unsigned char DoubleWidth, DoubleAlign;
+ unsigned char LongDoubleWidth, LongDoubleAlign;
+ unsigned char LargeArrayMinWidth, LargeArrayAlign;
+ unsigned char LongWidth, LongAlign;
+ unsigned char LongLongWidth, LongLongAlign;
+ const char *DescriptionString;
+ const char *UserLabelPrefix;
+ const char *MCountName;
+ const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
+ unsigned char RegParmMax, SSERegParmMax;
+ TargetCXXABI CXXABI;
+
+ unsigned HasAlignMac68kSupport : 1;
+ unsigned RealTypeUsesObjCFPRet : 3;
+
+ // TargetInfo Constructor. Default initializes all fields.
+ TargetInfo(const std::string &T);
+
+public:
+ /// CreateTargetInfo - Construct a target for the given options.
+ ///
+ /// \param Opts - The options to use to initialize the target. The target may
+ /// modify the options to canonicalize the target feature information to match
+ /// what the backend expects.
+ static TargetInfo* CreateTargetInfo(Diagnostic &Diags, TargetOptions &Opts);
+
+ virtual ~TargetInfo();
+
+ ///===---- Target Data Type Query Methods -------------------------------===//
+ enum IntType {
+ NoInt = 0,
+ SignedShort,
+ UnsignedShort,
+ SignedInt,
+ UnsignedInt,
+ SignedLong,
+ UnsignedLong,
+ SignedLongLong,
+ UnsignedLongLong
+ };
+
+ enum RealType {
+ Float = 0,
+ Double,
+ LongDouble
+ };
+
+protected:
+ IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
+ WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType;
+
+ /// Control whether the alignment of bit-field types is respected when laying
+ /// out structures. If true, then the alignment of the bit-field type will be
+ /// used to (a) impact the alignment of the containing structure, and (b)
+ /// ensure that the individual bit-field will not straddle an alignment
+ /// boundary.
+ unsigned UseBitFieldTypeAlignment : 1;
+
+public:
+ IntType getSizeType() const { return SizeType; }
+ IntType getIntMaxType() const { return IntMaxType; }
+ IntType getUIntMaxType() const { return UIntMaxType; }
+ IntType getPtrDiffType(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
+ }
+ IntType getIntPtrType() const { return IntPtrType; }
+ IntType getWCharType() const { return WCharType; }
+ IntType getWIntType() const { return WIntType; }
+ IntType getChar16Type() const { return Char16Type; }
+ IntType getChar32Type() const { return Char32Type; }
+ IntType getInt64Type() const { return Int64Type; }
+ IntType getSigAtomicType() const { return SigAtomicType; }
+
+
+ /// getTypeWidth - Return the width (in bits) of the specified integer type
+ /// enum. For example, SignedInt -> getIntWidth().
+ unsigned getTypeWidth(IntType T) const;
+
+ /// getTypeAlign - Return the alignment (in bits) of the specified integer
+ /// type enum. For example, SignedInt -> getIntAlign().
+ unsigned getTypeAlign(IntType T) const;
+
+ /// isTypeSigned - Return whether an integer types is signed. Returns true if
+ /// the type is signed; false otherwise.
+ static bool isTypeSigned(IntType T);
+
+ /// getPointerWidth - Return the width of pointers on this target, for the
+ /// specified address space.
+ uint64_t getPointerWidth(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
+ }
+ uint64_t getPointerAlign(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
+ }
+
+ /// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this
+ /// target, in bits.
+ unsigned getBoolWidth() const { return BoolWidth; }
+ unsigned getBoolAlign() const { return BoolAlign; }
+
+ unsigned getCharWidth() const { return 8; } // FIXME
+ unsigned getCharAlign() const { return 8; } // FIXME
+
+ /// getShortWidth/Align - Return the size of 'signed short' and
+ /// 'unsigned short' for this target, in bits.
+ unsigned getShortWidth() const { return 16; } // FIXME
+ unsigned getShortAlign() const { return 16; } // FIXME
+
+ /// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
+ /// this target, in bits.
+ unsigned getIntWidth() const { return IntWidth; }
+ unsigned getIntAlign() const { return IntAlign; }
+
+ /// getLongWidth/Align - Return the size of 'signed long' and 'unsigned long'
+ /// for this target, in bits.
+ unsigned getLongWidth() const { return LongWidth; }
+ unsigned getLongAlign() const { return LongAlign; }
+
+ /// getLongLongWidth/Align - Return the size of 'signed long long' and
+ /// 'unsigned long long' for this target, in bits.
+ unsigned getLongLongWidth() const { return LongLongWidth; }
+ unsigned getLongLongAlign() const { return LongLongAlign; }
+
+ /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
+ /// bits.
+ unsigned getWCharWidth() const { return getTypeWidth(WCharType); }
+ unsigned getWCharAlign() const { return getTypeAlign(WCharType); }
+
+ /// getChar16Width/Align - Return the size of 'char16_t' for this target, in
+ /// bits.
+ unsigned getChar16Width() const { return getTypeWidth(Char16Type); }
+ unsigned getChar16Align() const { return getTypeAlign(Char16Type); }
+
+ /// getChar32Width/Align - Return the size of 'char32_t' for this target, in
+ /// bits.
+ unsigned getChar32Width() const { return getTypeWidth(Char32Type); }
+ unsigned getChar32Align() const { return getTypeAlign(Char32Type); }
+
+ /// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
+ unsigned getFloatWidth() const { return FloatWidth; }
+ unsigned getFloatAlign() const { return FloatAlign; }
+ const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; }
+
+ /// getDoubleWidth/Align/Format - Return the size/align/format of 'double'.
+ unsigned getDoubleWidth() const { return DoubleWidth; }
+ unsigned getDoubleAlign() const { return DoubleAlign; }
+ const llvm::fltSemantics &getDoubleFormat() const { return *DoubleFormat; }
+
+ /// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long
+ /// double'.
+ unsigned getLongDoubleWidth() const { return LongDoubleWidth; }
+ unsigned getLongDoubleAlign() const { return LongDoubleAlign; }
+ const llvm::fltSemantics &getLongDoubleFormat() const {
+ return *LongDoubleFormat;
+ }
+
+ // getLargeArrayMinWidth/Align - Return the minimum array size that is
+ // 'large' and its alignment.
+ unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
+ unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
+
+ /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
+ /// target, in bits.
+ unsigned getIntMaxTWidth() const {
+ return getTypeWidth(IntMaxType);
+ }
+
+ /// getUserLabelPrefix - This returns the default value of the
+ /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by
+ /// default. On most platforms this is "_", but it is "" on some, and "." on
+ /// others.
+ const char *getUserLabelPrefix() const {
+ return UserLabelPrefix;
+ }
+
+ /// MCountName - This returns name of the mcount instrumentation function.
+ const char *getMCountName() const {
+ return MCountName;
+ }
+
+ bool useBitFieldTypeAlignment() const {
+ return UseBitFieldTypeAlignment;
+ }
+
+ /// hasAlignMac68kSupport - Check whether this target support '#pragma options
+ /// align=mac68k'.
+ bool hasAlignMac68kSupport() const {
+ return HasAlignMac68kSupport;
+ }
+
+ /// getTypeName - Return the user string for the specified integer type enum.
+ /// For example, SignedShort -> "short".
+ static const char *getTypeName(IntType T);
+
+ /// getTypeConstantSuffix - Return the constant suffix for the specified
+ /// integer type enum. For example, SignedLong -> "L".
+ static const char *getTypeConstantSuffix(IntType T);
+
+ /// \brief Check whether the given real type should use the "fpret" flavor of
+ /// Obj-C message passing on this target.
+ bool useObjCFPRetForRealType(RealType T) const {
+ return RealTypeUsesObjCFPRet & (1 << T);
+ }
+
+ ///===---- Other target property query methods --------------------------===//
+
+ /// getTargetDefines - Appends the target-specific #define values for this
+ /// target set to the specified buffer.
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const = 0;
+
+
+ /// getTargetBuiltins - Return information about target-specific builtins for
+ /// the current primary target, and info about which builtins are non-portable
+ /// across the current set of primary and secondary targets.
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const = 0;
+
+ /// getVAListDeclaration - Return the declaration to use for
+ /// __builtin_va_list, which is target-specific.
+ virtual const char *getVAListDeclaration() const = 0;
+
+ /// isValidGCCRegisterName - Returns whether the passed in string
+ /// is a valid register name according to GCC. This is used by Sema for
+ /// inline asm statements.
+ bool isValidGCCRegisterName(llvm::StringRef Name) const;
+
+ // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name.
+ // For example, on x86 it will return "ax" when "eax" is passed in.
+ llvm::StringRef getNormalizedGCCRegisterName(llvm::StringRef Name) const;
+
+ struct ConstraintInfo {
+ enum {
+ CI_None = 0x00,
+ CI_AllowsMemory = 0x01,
+ CI_AllowsRegister = 0x02,
+ CI_ReadWrite = 0x04, // "+r" output constraint (read and write).
+ CI_HasMatchingInput = 0x08 // This output operand has a matching input.
+ };
+ unsigned Flags;
+ int TiedOperand;
+
+ std::string ConstraintStr; // constraint: "=rm"
+ std::string Name; // Operand name: [foo] with no []'s.
+ public:
+ ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name)
+ : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
+ Name(Name.str()) {}
+
+ const std::string &getConstraintStr() const { return ConstraintStr; }
+ const std::string &getName() const { return Name; }
+ bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; }
+ bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
+ bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
+
+ /// hasMatchingInput - Return true if this output operand has a matching
+ /// (tied) input operand.
+ bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
+
+ /// hasTiedOperand() - Return true if this input operand is a matching
+ /// constraint that ties it to an output operand. If this returns true,
+ /// then getTiedOperand will indicate which output operand this is tied to.
+ bool hasTiedOperand() const { return TiedOperand != -1; }
+ unsigned getTiedOperand() const {
+ assert(hasTiedOperand() && "Has no tied operand!");
+ return (unsigned)TiedOperand;
+ }
+
+ void setIsReadWrite() { Flags |= CI_ReadWrite; }
+ void setAllowsMemory() { Flags |= CI_AllowsMemory; }
+ void setAllowsRegister() { Flags |= CI_AllowsRegister; }
+ void setHasMatchingInput() { Flags |= CI_HasMatchingInput; }
+
+ /// setTiedOperand - Indicate that this is an input operand that is tied to
+ /// the specified output operand. Copy over the various constraint
+ /// information from the output.
+ void setTiedOperand(unsigned N, ConstraintInfo &Output) {
+ Output.setHasMatchingInput();
+ Flags = Output.Flags;
+ TiedOperand = N;
+ // Don't copy Name or constraint string.
+ }
+ };
+
+ // validateOutputConstraint, validateInputConstraint - Checks that
+ // a constraint is valid and provides information about it.
+ // FIXME: These should return a real error instead of just true/false.
+ bool validateOutputConstraint(ConstraintInfo &Info) const;
+ bool validateInputConstraint(ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs,
+ ConstraintInfo &info) const;
+ bool resolveSymbolicName(const char *&Name,
+ ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs, unsigned &Index) const;
+
+ virtual std::string convertConstraint(const char Constraint) const {
+ // 'p' defaults to 'r', but can be overridden by targets.
+ if (Constraint == 'p')
+ return std::string("r");
+ return std::string(1, Constraint);
+ }
+
+ // Returns a string of target-specific clobbers, in LLVM format.
+ virtual const char *getClobbers() const = 0;
+
+
+ /// getTriple - Return the target triple of the primary target.
+ const llvm::Triple &getTriple() const {
+ return Triple;
+ }
+
+ const char *getTargetDescription() const {
+ return DescriptionString;
+ }
+
+ struct GCCRegAlias {
+ const char * const Aliases[5];
+ const char * const Register;
+ };
+
+ virtual bool useGlobalsForAutomaticVariables() const { return false; }
+
+ /// getCFStringSection - Return the section to use for CFString
+ /// literals, or 0 if no special section is used.
+ virtual const char *getCFStringSection() const {
+ return "__DATA,__cfstring";
+ }
+
+ /// getNSStringSection - Return the section to use for NSString
+ /// literals, or 0 if no special section is used.
+ virtual const char *getNSStringSection() const {
+ return "__OBJC,__cstring_object,regular,no_dead_strip";
+ }
+
+ /// getNSStringNonFragileABISection - Return the section to use for
+ /// NSString literals, or 0 if no special section is used (NonFragile ABI).
+ virtual const char *getNSStringNonFragileABISection() const {
+ return "__DATA, __objc_stringobj, regular, no_dead_strip";
+ }
+
+ /// isValidSectionSpecifier - This is an optional hook that targets can
+ /// implement to perform semantic checking on attribute((section("foo")))
+ /// specifiers. In this case, "foo" is passed in to be checked. If the
+ /// section specifier is invalid, the backend should return a non-empty string
+ /// that indicates the problem.
+ ///
+ /// This hook is a simple quality of implementation feature to catch errors
+ /// and give good diagnostics in cases when the assembler or code generator
+ /// would otherwise reject the section specifier.
+ ///
+ virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
+ return "";
+ }
+
+ /// setForcedLangOptions - Set forced language options.
+ /// Apply changes to the target information with respect to certain
+ /// language options which change the target configuration.
+ virtual void setForcedLangOptions(LangOptions &Opts);
+
+ /// getDefaultFeatures - Get the default set of target features for
+ /// the \args CPU; this should include all legal feature strings on
+ /// the target.
+ virtual void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const {
+ }
+
+ /// getABI - Get the ABI in use.
+ virtual const char *getABI() const {
+ return "";
+ }
+
+ /// getCXXABI - Get the C++ ABI in use.
+ virtual TargetCXXABI getCXXABI() const {
+ return CXXABI;
+ }
+
+ /// setCPU - Target the specific CPU.
+ ///
+ /// \return - False on error (invalid CPU name).
+ //
+ // FIXME: Remove this.
+ virtual bool setCPU(const std::string &Name) {
+ return true;
+ }
+
+ /// setABI - Use the specific ABI.
+ ///
+ /// \return - False on error (invalid ABI name).
+ virtual bool setABI(const std::string &Name) {
+ return false;
+ }
+
+ /// setCXXABI - Use this specific C++ ABI.
+ ///
+ /// \return - False on error (invalid C++ ABI name).
+ bool setCXXABI(const std::string &Name) {
+ static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
+ TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name)
+ .Case("arm", CXXABI_ARM)
+ .Case("itanium", CXXABI_Itanium)
+ .Case("microsoft", CXXABI_Microsoft)
+ .Default(Unknown);
+ if (ABI == Unknown) return false;
+ return setCXXABI(ABI);
+ }
+
+ /// setCXXABI - Set the C++ ABI to be used by this implementation.
+ ///
+ /// \return - False on error (ABI not valid on this target)
+ virtual bool setCXXABI(TargetCXXABI ABI) {
+ CXXABI = ABI;
+ return true;
+ }
+
+ /// setFeatureEnabled - Enable or disable a specific target feature,
+ /// the feature name must be valid.
+ ///
+ /// \return - False on error (invalid feature name).
+ virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const {
+ return false;
+ }
+
+ /// HandleTargetOptions - Perform initialization based on the user configured
+ /// set of features (e.g., +sse4). The list is guaranteed to have at most one
+ /// entry per feature.
+ ///
+ /// The target may modify the features list, to change which options are
+ /// passed onwards to the backend.
+ virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ }
+
+ // getRegParmMax - Returns maximal number of args passed in registers.
+ unsigned getRegParmMax() const {
+ return RegParmMax;
+ }
+
+ /// isTLSSupported - Whether the target supports thread-local storage.
+ bool isTLSSupported() const {
+ return TLSSupported;
+ }
+
+ /// hasNoAsmVariants - Return true if {|} are normal characters in the
+ /// asm string. If this returns false (the default), then {abc|xyz} is syntax
+ /// that says that when compiling for asm variant #0, "abc" should be
+ /// generated, but when compiling for asm variant #1, "xyz" should be
+ /// generated.
+ bool hasNoAsmVariants() const {
+ return NoAsmVariants;
+ }
+
+ /// getEHDataRegisterNumber - Return the register number that
+ /// __builtin_eh_return_regno would return with the specified argument.
+ virtual int getEHDataRegisterNumber(unsigned RegNo) const {
+ return -1;
+ }
+
+ /// getStaticInitSectionSpecifier - Return the section to use for C++ static
+ /// initialization functions.
+ virtual const char *getStaticInitSectionSpecifier() const {
+ return 0;
+ }
+protected:
+ virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
+ return PointerWidth;
+ }
+ virtual uint64_t getPointerAlignV(unsigned AddrSpace) const {
+ return PointerAlign;
+ }
+ virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const {
+ return PtrDiffType;
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const = 0;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const = 0;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const= 0;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
new file mode 100644
index 0000000..f3c206f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
@@ -0,0 +1,45 @@
+//===--- TargetOptions.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
+#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// TargetOptions - Options for controlling the target.
+class TargetOptions {
+public:
+ /// If given, the name of the target triple to compile for. If not given the
+ /// target will be selected to match the host.
+ std::string Triple;
+
+ /// If given, the name of the target CPU to generate code for.
+ std::string CPU;
+
+ /// If given, the name of the target ABI to use.
+ std::string ABI;
+
+ /// If given, the name of the target C++ ABI to use. If not given, defaults
+ /// to "itanium".
+ std::string CXXABI;
+
+ /// If given, the version string of the linker in use.
+ std::string LinkerVersion;
+
+ /// The list of target specific features to enable or disable -- this should
+ /// be a list of strings starting with by '+' or '-'.
+ std::vector<std::string> Features;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
new file mode 100644
index 0000000..c6ea05b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
@@ -0,0 +1,39 @@
+//===--- TemplateKinds.h - Enum values for C++ Template Kinds ---*- 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 TemplateNameKind enum.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TEMPLATEKINDS_H
+#define LLVM_CLANG_TEMPLATEKINDS_H
+
+namespace clang {
+
+/// \brief Specifies the kind of template name that an identifier refers to.
+enum TemplateNameKind {
+ /// The name does not refer to a template.
+ TNK_Non_template = 0,
+ /// The name refers to a function template or a set of overloaded
+ /// functions that includes at least one function template.
+ TNK_Function_template,
+ /// The name refers to a template whose specialization produces a
+ /// type. The template itself could be a class template, template
+ /// template parameter, or C++0x template alias.
+ TNK_Type_template,
+ /// The name refers to a dependent template name. Whether the
+ /// template name is assumed to refer to a type template or a
+ /// function template depends on the context in which the template
+ /// name occurs.
+ TNK_Dependent_template_name
+};
+
+}
+#endif
+
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
new file mode 100644
index 0000000..b84b04d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
@@ -0,0 +1,460 @@
+//===--- TokenKinds.def - C Family Token Kind Database ----------*- 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 TokenKind database. This includes normal tokens like
+// tok::ampamp (corresponding to the && token) as well as keywords for various
+// languages. Users of this file must optionally #define the TOK, KEYWORD,
+// ALIAS, or PPKEYWORD macros to make use of this file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TOK
+#define TOK(X)
+#endif
+#ifndef PUNCTUATOR
+#define PUNCTUATOR(X,Y) TOK(X)
+#endif
+#ifndef KEYWORD
+#define KEYWORD(X,Y) TOK(kw_ ## X)
+#endif
+#ifndef ALIAS
+#define ALIAS(X,Y,Z)
+#endif
+#ifndef PPKEYWORD
+#define PPKEYWORD(X)
+#endif
+#ifndef CXX_KEYWORD_OPERATOR
+#define CXX_KEYWORD_OPERATOR(X,Y)
+#endif
+#ifndef OBJC1_AT_KEYWORD
+#define OBJC1_AT_KEYWORD(X)
+#endif
+#ifndef OBJC2_AT_KEYWORD
+#define OBJC2_AT_KEYWORD(X)
+#endif
+#ifndef ANNOTATION
+#define ANNOTATION(X) TOK(annot_ ## X)
+#endif
+
+//===----------------------------------------------------------------------===//
+// Preprocessor keywords.
+//===----------------------------------------------------------------------===//
+
+// These have meaning after a '#' at the start of a line. These define enums in
+// the tok::pp_* namespace. Note that IdentifierInfo::getPPKeywordID must be
+// manually updated if something is added here.
+PPKEYWORD(not_keyword)
+
+// C99 6.10.1 - Conditional Inclusion.
+PPKEYWORD(if)
+PPKEYWORD(ifdef)
+PPKEYWORD(ifndef)
+PPKEYWORD(elif)
+PPKEYWORD(else)
+PPKEYWORD(endif)
+PPKEYWORD(defined)
+
+// C99 6.10.2 - Source File Inclusion.
+PPKEYWORD(include)
+PPKEYWORD(__include_macros)
+
+// C99 6.10.3 - Macro Replacement.
+PPKEYWORD(define)
+PPKEYWORD(undef)
+
+// C99 6.10.4 - Line Control.
+PPKEYWORD(line)
+
+// C99 6.10.5 - Error Directive.
+PPKEYWORD(error)
+
+// C99 6.10.6 - Pragma Directive.
+PPKEYWORD(pragma)
+
+// GNU Extensions.
+PPKEYWORD(import)
+PPKEYWORD(include_next)
+PPKEYWORD(warning)
+PPKEYWORD(ident)
+PPKEYWORD(sccs)
+PPKEYWORD(assert)
+PPKEYWORD(unassert)
+
+//===----------------------------------------------------------------------===//
+// Language keywords.
+//===----------------------------------------------------------------------===//
+
+// These define members of the tok::* namespace.
+
+TOK(unknown) // Not a token.
+TOK(eof) // End of file.
+TOK(eom) // End of macro (end of line inside a macro).
+TOK(code_completion) // Code completion marker
+TOK(cxx_defaultarg_end) // C++ default argument end marker
+
+// C99 6.4.9: Comments.
+TOK(comment) // Comment (only in -E -C[C] mode)
+
+// C99 6.4.2: Identifiers.
+TOK(identifier) // abcde123
+TOK(raw_identifier) // Used only in raw lexing mode.
+
+// C99 6.4.4.1: Integer Constants
+// C99 6.4.4.2: Floating Constants
+TOK(numeric_constant) // 0x123
+
+// C99 6.4.4: Character Constants
+TOK(char_constant) // 'a' L'b'
+
+// C99 6.4.5: String Literals.
+TOK(string_literal) // "foo"
+TOK(wide_string_literal) // L"foo"
+TOK(angle_string_literal)// <foo>
+
+// C99 6.4.6: Punctuators.
+PUNCTUATOR(l_square, "[")
+PUNCTUATOR(r_square, "]")
+PUNCTUATOR(l_paren, "(")
+PUNCTUATOR(r_paren, ")")
+PUNCTUATOR(l_brace, "{")
+PUNCTUATOR(r_brace, "}")
+PUNCTUATOR(period, ".")
+PUNCTUATOR(ellipsis, "...")
+PUNCTUATOR(amp, "&")
+PUNCTUATOR(ampamp, "&&")
+PUNCTUATOR(ampequal, "&=")
+PUNCTUATOR(star, "*")
+PUNCTUATOR(starequal, "*=")
+PUNCTUATOR(plus, "+")
+PUNCTUATOR(plusplus, "++")
+PUNCTUATOR(plusequal, "+=")
+PUNCTUATOR(minus, "-")
+PUNCTUATOR(arrow, "->")
+PUNCTUATOR(minusminus, "--")
+PUNCTUATOR(minusequal, "-=")
+PUNCTUATOR(tilde, "~")
+PUNCTUATOR(exclaim, "!")
+PUNCTUATOR(exclaimequal, "!=")
+PUNCTUATOR(slash, "/")
+PUNCTUATOR(slashequal, "/=")
+PUNCTUATOR(percent, "%")
+PUNCTUATOR(percentequal, "%=")
+PUNCTUATOR(less, "<")
+PUNCTUATOR(lessless, "<<")
+PUNCTUATOR(lessequal, "<=")
+PUNCTUATOR(lesslessequal, "<<=")
+PUNCTUATOR(greater, ">")
+PUNCTUATOR(greatergreater, ">>")
+PUNCTUATOR(greaterequal, ">=")
+PUNCTUATOR(greatergreaterequal, ">>=")
+PUNCTUATOR(caret, "^")
+PUNCTUATOR(caretequal, "^=")
+PUNCTUATOR(pipe, "|")
+PUNCTUATOR(pipepipe, "||")
+PUNCTUATOR(pipeequal, "|=")
+PUNCTUATOR(question, "?")
+PUNCTUATOR(colon, ":")
+PUNCTUATOR(semi, ";")
+PUNCTUATOR(equal, "=")
+PUNCTUATOR(equalequal, "==")
+PUNCTUATOR(comma, ",")
+PUNCTUATOR(hash, "#")
+PUNCTUATOR(hashhash, "##")
+PUNCTUATOR(hashat, "#@")
+
+// C++ Support
+PUNCTUATOR(periodstar, ".*")
+PUNCTUATOR(arrowstar, "->*")
+PUNCTUATOR(coloncolon, "::")
+
+// Objective C support.
+PUNCTUATOR(at, "@")
+
+// CUDA support.
+PUNCTUATOR(lesslessless, "<<<")
+PUNCTUATOR(greatergreatergreater, ">>>")
+
+// C99 6.4.1: Keywords. These turn into kw_* tokens.
+// Flags allowed:
+// KEYALL - This is a keyword in all variants of C and C++, or it
+// is a keyword in the implementation namespace that should
+// always be treated as a keyword
+// KEYC99 - This is a keyword introduced to C in C99
+// KEYCXX - This is a C++ keyword, or a C++-specific keyword in the
+// implementation namespace
+// KEYNOCXX - This is a keyword in every non-C++ dialect.
+// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
+// KEYGNU - This is a keyword if GNU extensions are enabled
+// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYOPENCL - This is a keyword in OpenCL
+// KEYALTIVEC - This is a keyword in AltiVec
+// KEYBORLAND - This is a keyword if Borland extensions are enabled
+//
+KEYWORD(auto , KEYALL)
+KEYWORD(break , KEYALL)
+KEYWORD(case , KEYALL)
+KEYWORD(char , KEYALL)
+KEYWORD(const , KEYALL)
+KEYWORD(continue , KEYALL)
+KEYWORD(default , KEYALL)
+KEYWORD(do , KEYALL)
+KEYWORD(double , KEYALL)
+KEYWORD(else , KEYALL)
+KEYWORD(enum , KEYALL)
+KEYWORD(extern , KEYALL)
+KEYWORD(float , KEYALL)
+KEYWORD(for , KEYALL)
+KEYWORD(goto , KEYALL)
+KEYWORD(if , KEYALL)
+KEYWORD(inline , KEYC99|KEYCXX|KEYGNU)
+KEYWORD(int , KEYALL)
+KEYWORD(long , KEYALL)
+KEYWORD(register , KEYALL)
+KEYWORD(restrict , KEYC99)
+KEYWORD(return , KEYALL)
+KEYWORD(short , KEYALL)
+KEYWORD(signed , KEYALL)
+KEYWORD(sizeof , KEYALL)
+KEYWORD(static , KEYALL)
+KEYWORD(struct , KEYALL)
+KEYWORD(switch , KEYALL)
+KEYWORD(typedef , KEYALL)
+KEYWORD(union , KEYALL)
+KEYWORD(unsigned , KEYALL)
+KEYWORD(void , KEYALL)
+KEYWORD(volatile , KEYALL)
+KEYWORD(while , KEYALL)
+KEYWORD(_Bool , KEYNOCXX)
+KEYWORD(_Complex , KEYALL)
+KEYWORD(_Imaginary , KEYALL)
+KEYWORD(__func__ , KEYALL)
+
+// C++ 2.11p1: Keywords.
+KEYWORD(asm , KEYCXX|KEYGNU)
+KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(catch , KEYCXX)
+KEYWORD(class , KEYCXX)
+KEYWORD(const_cast , KEYCXX)
+KEYWORD(delete , KEYCXX)
+KEYWORD(dynamic_cast , KEYCXX)
+KEYWORD(explicit , KEYCXX)
+KEYWORD(export , KEYCXX)
+KEYWORD(false , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(friend , KEYCXX)
+KEYWORD(mutable , KEYCXX)
+KEYWORD(namespace , KEYCXX)
+KEYWORD(new , KEYCXX)
+KEYWORD(operator , KEYCXX)
+KEYWORD(private , KEYCXX)
+KEYWORD(protected , KEYCXX)
+KEYWORD(public , KEYCXX)
+KEYWORD(reinterpret_cast , KEYCXX)
+KEYWORD(static_cast , KEYCXX)
+KEYWORD(template , KEYCXX)
+KEYWORD(this , KEYCXX)
+KEYWORD(throw , KEYCXX)
+KEYWORD(true , BOOLSUPPORT|KEYALTIVEC)
+KEYWORD(try , KEYCXX)
+KEYWORD(typename , KEYCXX)
+KEYWORD(typeid , KEYCXX)
+KEYWORD(using , KEYCXX)
+KEYWORD(virtual , KEYCXX)
+KEYWORD(wchar_t , KEYCXX)
+
+// C++ 2.5p2: Alternative Representations.
+CXX_KEYWORD_OPERATOR(and , ampamp)
+CXX_KEYWORD_OPERATOR(and_eq , ampequal)
+CXX_KEYWORD_OPERATOR(bitand , amp)
+CXX_KEYWORD_OPERATOR(bitor , pipe)
+CXX_KEYWORD_OPERATOR(compl , tilde)
+CXX_KEYWORD_OPERATOR(not , exclaim)
+CXX_KEYWORD_OPERATOR(not_eq , exclaimequal)
+CXX_KEYWORD_OPERATOR(or , pipepipe)
+CXX_KEYWORD_OPERATOR(or_eq , pipeequal)
+CXX_KEYWORD_OPERATOR(xor , caret)
+CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
+
+// C++0x keywords
+KEYWORD(alignof , KEYCXX0X)
+KEYWORD(char16_t , KEYCXX0X)
+KEYWORD(char32_t , KEYCXX0X)
+KEYWORD(constexpr , KEYCXX0X)
+KEYWORD(decltype , KEYCXX0X)
+KEYWORD(noexcept , KEYCXX0X)
+KEYWORD(nullptr , KEYCXX0X)
+KEYWORD(static_assert , KEYCXX0X)
+KEYWORD(thread_local , KEYCXX0X)
+
+// GNU Extensions (in impl-reserved namespace)
+KEYWORD(_Decimal32 , KEYALL)
+KEYWORD(_Decimal64 , KEYALL)
+KEYWORD(_Decimal128 , KEYALL)
+KEYWORD(__null , KEYCXX)
+KEYWORD(__alignof , KEYALL)
+KEYWORD(__attribute , KEYALL)
+KEYWORD(__builtin_choose_expr , KEYALL)
+KEYWORD(__builtin_offsetof , KEYALL)
+KEYWORD(__builtin_types_compatible_p, KEYALL)
+KEYWORD(__builtin_va_arg , KEYALL)
+KEYWORD(__extension__ , KEYALL)
+KEYWORD(__imag , KEYALL)
+KEYWORD(__label__ , KEYALL)
+KEYWORD(__real , KEYALL)
+KEYWORD(__thread , KEYALL)
+KEYWORD(__FUNCTION__ , KEYALL)
+KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
+
+// GNU Extensions (outside impl-reserved namespace)
+KEYWORD(typeof , KEYGNU)
+
+// GNU and MS Type Traits
+KEYWORD(__has_nothrow_assign , KEYCXX)
+KEYWORD(__has_nothrow_copy , KEYCXX)
+KEYWORD(__has_nothrow_constructor , KEYCXX)
+KEYWORD(__has_trivial_assign , KEYCXX)
+KEYWORD(__has_trivial_copy , KEYCXX)
+KEYWORD(__has_trivial_constructor , KEYCXX)
+KEYWORD(__has_trivial_destructor , KEYCXX)
+KEYWORD(__has_virtual_destructor , KEYCXX)
+KEYWORD(__is_abstract , KEYCXX)
+KEYWORD(__is_base_of , KEYCXX)
+KEYWORD(__is_class , KEYCXX)
+KEYWORD(__is_convertible_to , KEYCXX)
+KEYWORD(__is_empty , KEYCXX)
+KEYWORD(__is_enum , KEYCXX)
+KEYWORD(__is_pod , KEYCXX)
+KEYWORD(__is_polymorphic , KEYCXX)
+KEYWORD(__is_union , KEYCXX)
+// Tentative name - there's no implementation of std::is_literal_type yet.
+KEYWORD(__is_literal , KEYCXX)
+
+// Apple Extension.
+KEYWORD(__private_extern__ , KEYALL)
+
+// Microsoft Extension.
+KEYWORD(__declspec , KEYALL)
+KEYWORD(__cdecl , KEYALL)
+KEYWORD(__stdcall , KEYALL)
+KEYWORD(__fastcall , KEYALL)
+KEYWORD(__thiscall , KEYALL)
+KEYWORD(__forceinline , KEYALL)
+
+// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9])
+KEYWORD(__kernel , KEYOPENCL)
+ALIAS("kernel", __kernel , KEYOPENCL)
+
+// Borland Extensions.
+KEYWORD(__pascal , KEYALL)
+
+// Altivec Extension.
+KEYWORD(__vector , KEYALTIVEC)
+KEYWORD(__pixel , KEYALTIVEC)
+
+// Alternate spelling for various tokens. There are GCC extensions in all
+// languages, but should not be disabled in strict conformance mode.
+ALIAS("__attribute__", __attribute, KEYALL)
+ALIAS("__const" , const , KEYALL)
+ALIAS("__const__" , const , KEYALL)
+ALIAS("__alignof__" , __alignof , KEYALL)
+ALIAS("__asm" , asm , KEYALL)
+ALIAS("__asm__" , asm , KEYALL)
+ALIAS("__complex" , _Complex , KEYALL)
+ALIAS("__complex__" , _Complex , KEYALL)
+ALIAS("__imag__" , __imag , KEYALL)
+ALIAS("__inline" , inline , KEYALL)
+ALIAS("__inline__" , inline , KEYALL)
+ALIAS("__nullptr" , nullptr , KEYCXX)
+ALIAS("__real__" , __real , KEYALL)
+ALIAS("__restrict" , restrict , KEYALL)
+ALIAS("__restrict__" , restrict , KEYALL)
+ALIAS("__signed" , signed , KEYALL)
+ALIAS("__signed__" , signed , KEYALL)
+ALIAS("__typeof" , typeof , KEYALL)
+ALIAS("__typeof__" , typeof , KEYALL)
+ALIAS("__volatile" , volatile , KEYALL)
+ALIAS("__volatile__" , volatile , KEYALL)
+
+// Microsoft extensions which should be disabled in strict conformance mode
+KEYWORD(__ptr64 , KEYMS)
+KEYWORD(__w64 , KEYMS)
+KEYWORD(__uuidof , KEYMS | KEYBORLAND)
+ALIAS("_asm" , asm , KEYMS)
+ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
+ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
+ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
+ALIAS("_thiscall" , __thiscall , KEYMS)
+ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
+ALIAS("_inline" , inline , KEYMS)
+
+// Borland Extensions which should be disabled in strict conformance mode.
+ALIAS("_pascal" , __pascal , KEYBORLAND)
+
+// Clang Extensions.
+ALIAS("__char16_t" , char16_t , KEYCXX)
+ALIAS("__char32_t" , char32_t , KEYCXX)
+
+
+//===----------------------------------------------------------------------===//
+// Objective-C @-preceeded keywords.
+//===----------------------------------------------------------------------===//
+
+// These have meaning after an '@' in Objective-C mode. These define enums in
+// the tok::objc_* namespace.
+
+OBJC1_AT_KEYWORD(not_keyword)
+OBJC1_AT_KEYWORD(class)
+OBJC1_AT_KEYWORD(compatibility_alias)
+OBJC1_AT_KEYWORD(defs)
+OBJC1_AT_KEYWORD(encode)
+OBJC1_AT_KEYWORD(end)
+OBJC1_AT_KEYWORD(implementation)
+OBJC1_AT_KEYWORD(interface)
+OBJC1_AT_KEYWORD(private)
+OBJC1_AT_KEYWORD(protected)
+OBJC1_AT_KEYWORD(protocol)
+OBJC1_AT_KEYWORD(public)
+OBJC1_AT_KEYWORD(selector)
+OBJC1_AT_KEYWORD(throw)
+OBJC1_AT_KEYWORD(try)
+OBJC1_AT_KEYWORD(catch)
+OBJC1_AT_KEYWORD(finally)
+OBJC1_AT_KEYWORD(synchronized)
+
+OBJC2_AT_KEYWORD(property)
+OBJC2_AT_KEYWORD(package)
+OBJC2_AT_KEYWORD(required)
+OBJC2_AT_KEYWORD(optional)
+OBJC2_AT_KEYWORD(synthesize)
+OBJC2_AT_KEYWORD(dynamic)
+
+// TODO: What to do about context-sensitive keywords like:
+// bycopy/byref/in/inout/oneway/out?
+
+ANNOTATION(cxxscope) // annotation for a C++ scope spec, e.g. "::foo::bar::"
+ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
+ // qualified) typename, e.g. "foo::MyClass", or
+ // template-id that names a type ("std::vector<int>")
+ANNOTATION(template_id) // annotation for a C++ template-id that names a
+ // function template specialization (not a type),
+ // e.g., "std::swap<int>"
+
+// Annotation for #pragma unused(...)
+// For each argument inside the parentheses the pragma handler will produce
+// one 'pragma_unused' annotation token followed by the argument token.
+ANNOTATION(pragma_unused)
+
+#undef ANNOTATION
+#undef OBJC2_AT_KEYWORD
+#undef OBJC1_AT_KEYWORD
+#undef CXX_KEYWORD_OPERATOR
+#undef PPKEYWORD
+#undef ALIAS
+#undef KEYWORD
+#undef PUNCTUATOR
+#undef TOK
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
new file mode 100644
index 0000000..515390a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
@@ -0,0 +1,70 @@
+//===--- TokenKinds.h - Enum values for C Token Kinds -----------*- 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 TokenKind enum and support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENKINDS_H
+#define LLVM_CLANG_TOKENKINDS_H
+
+namespace clang {
+
+namespace tok {
+
+/// TokenKind - This provides a simple uniform namespace for tokens from all C
+/// languages.
+enum TokenKind {
+#define TOK(X) X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_TOKENS
+};
+
+/// PPKeywordKind - This provides a namespace for preprocessor keywords which
+/// start with a '#' at the beginning of the line.
+enum PPKeywordKind {
+#define PPKEYWORD(X) pp_##X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_PP_KEYWORDS
+};
+
+/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which
+/// start with an '@'.
+enum ObjCKeywordKind {
+#define OBJC1_AT_KEYWORD(X) objc_##X,
+#define OBJC2_AT_KEYWORD(X) objc_##X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_OBJC_KEYWORDS
+};
+
+/// OnOffSwitch - This defines the possible values of an on-off-switch
+/// (C99 6.10.6p2).
+enum OnOffSwitch {
+ OOS_ON, OOS_OFF, OOS_DEFAULT
+};
+
+/// \brief Determines the name of a token as used within the front end.
+///
+/// The name of a token will be an internal name (such as "l_square")
+/// and should not be used as part of diagnostic messages.
+const char *getTokenName(enum TokenKind Kind);
+
+/// \brief Determines the spelling of simple punctuation tokens like
+/// '!' or '%', and returns NULL for literal and annotation tokens.
+///
+/// This routine only retrieves the "simple" spelling of the token,
+/// and will not produce any alternative spellings (e.g., a
+/// digraph). For the actual spelling of a given Token, use
+/// Preprocessor::getSpelling().
+const char *getTokenSimpleSpelling(enum TokenKind Kind);
+
+} // end namespace tok
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
new file mode 100644
index 0000000..00c6e9e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
@@ -0,0 +1,47 @@
+//===--- TypeTraits.h - C++ Type Traits Support Enumerations ----*- 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 enumerations for the type traits support.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TYPETRAITS_H
+#define LLVM_CLANG_TYPETRAITS_H
+
+namespace clang {
+
+ /// UnaryTypeTrait - Names for the unary type traits.
+ enum UnaryTypeTrait {
+ UTT_HasNothrowAssign,
+ UTT_HasNothrowCopy,
+ UTT_HasNothrowConstructor,
+ UTT_HasTrivialAssign,
+ UTT_HasTrivialCopy,
+ UTT_HasTrivialConstructor,
+ UTT_HasTrivialDestructor,
+ UTT_HasVirtualDestructor,
+ UTT_IsAbstract,
+ UTT_IsClass,
+ UTT_IsEmpty,
+ UTT_IsEnum,
+ UTT_IsPOD,
+ UTT_IsPolymorphic,
+ UTT_IsUnion,
+ UTT_IsLiteral
+ };
+
+ /// BinaryTypeTrait - Names for the binary type traits.
+ enum BinaryTypeTrait {
+ BTT_IsBaseOf,
+ BTT_TypeCompatible,
+ BTT_IsConvertibleTo
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Version.h b/contrib/llvm/tools/clang/include/clang/Basic/Version.h
new file mode 100644
index 0000000..ede68ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h
@@ -0,0 +1,63 @@
+//===- Version.h - Clang Version Number -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines version macros and version-related utility functions
+// for Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_VERSION_H
+#define LLVM_CLANG_BASIC_VERSION_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include "clang/Basic/Version.inc"
+
+/// \brief Helper macro for CLANG_VERSION_STRING.
+#define CLANG_MAKE_VERSION_STRING2(X) #X
+
+#ifdef CLANG_VERSION_PATCHLEVEL
+/// \brief Helper macro for CLANG_VERSION_STRING.
+#define CLANG_MAKE_VERSION_STRING(X,Y,Z) CLANG_MAKE_VERSION_STRING2(X.Y.Z)
+
+/// \brief A string that describes the Clang version number, e.g.,
+/// "1.0".
+#define CLANG_VERSION_STRING \
+ CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR,CLANG_VERSION_PATCHLEVEL)
+#else
+/// \brief Helper macro for CLANG_VERSION_STRING.
+#define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y)
+
+/// \brief A string that describes the Clang version number, e.g.,
+/// "1.0".
+#define CLANG_VERSION_STRING \
+ CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR)
+#endif
+
+namespace clang {
+ /// \brief Retrieves the repository path (e.g., Subversion path) that
+ /// identifies the particular Clang branch, tag, or trunk from which this
+ /// Clang was built.
+ std::string getClangRepositoryPath();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// this Clang was built.
+ std::string getClangRevision();
+
+ /// \brief Retrieves the full repository version that is an amalgamation of
+ /// the information in getClangRepositoryPath() and getClangRevision().
+ std::string getClangFullRepositoryVersion();
+
+ /// \brief Retrieves a string representing the complete clang version,
+ /// which includes the clang version number, the repository version,
+ /// and the vendor tag.
+ std::string getClangFullVersion();
+}
+
+#endif // LLVM_CLANG_BASIC_VERSION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h b/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
new file mode 100644
index 0000000..90e288a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
@@ -0,0 +1,48 @@
+//===--- Visibility.h - Visibility enumeration and utilities ----*- 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 Visibility enumeration and various utility
+// functions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
+#define LLVM_CLANG_BASIC_VISIBILITY_H
+
+namespace clang {
+
+/// \link Describes the different kinds of visibility that a
+/// declaration may have. Visibility determines how a declaration
+/// interacts with the dynamic linker. It may also affect whether the
+/// symbol can be found by runtime symbol lookup APIs.
+///
+/// Visibility is not described in any language standard and
+/// (nonetheless) sometimes has odd behavior. Not all platforms
+/// support all visibility kinds.
+enum Visibility {
+ /// Objects with "hidden" visibility are not seen by the dynamic
+ /// linker.
+ HiddenVisibility,
+
+ /// Objects with "protected" visibility are seen by the dynamic
+ /// linker but always dynamically resolve to an object within this
+ /// shared object.
+ ProtectedVisibility,
+
+ /// Objects with "default" visibility are seen by the dynamic linker
+ /// and act like normal objects.
+ DefaultVisibility
+};
+
+inline Visibility minVisibility(Visibility L, Visibility R) {
+ return L < R ? L : R;
+}
+
+}
+
+#endif // LLVM_CLANG_BASIC_VISIBILITY_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
new file mode 100644
index 0000000..880a0da
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
@@ -0,0 +1,395 @@
+//===--- arm_neon.td - ARM NEON compiler interface ------------------------===//
+//
+// 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 TableGen definitions from which the ARM NEON header
+// file will be generated. See ARM document DUI0348B.
+//
+//===----------------------------------------------------------------------===//
+
+class Op;
+
+def OP_NONE : Op;
+def OP_ADD : Op;
+def OP_ADDL : Op;
+def OP_ADDW : Op;
+def OP_SUB : Op;
+def OP_SUBL : Op;
+def OP_SUBW : Op;
+def OP_MUL : Op;
+def OP_MULL : Op;
+def OP_MLA : Op;
+def OP_MLAL : Op;
+def OP_MLS : Op;
+def OP_MLSL : Op;
+def OP_MUL_N : Op;
+def OP_MULL_N: Op;
+def OP_MLA_N : Op;
+def OP_MLS_N : Op;
+def OP_MLAL_N : Op;
+def OP_MLSL_N : Op;
+def OP_MUL_LN: Op;
+def OP_MULL_LN : Op;
+def OP_MLA_LN: Op;
+def OP_MLS_LN: Op;
+def OP_MLAL_LN : Op;
+def OP_MLSL_LN : Op;
+def OP_QDMULL_LN : Op;
+def OP_QDMLAL_LN : Op;
+def OP_QDMLSL_LN : Op;
+def OP_QDMULH_LN : Op;
+def OP_QRDMULH_LN : Op;
+def OP_EQ : Op;
+def OP_GE : Op;
+def OP_LE : Op;
+def OP_GT : Op;
+def OP_LT : Op;
+def OP_NEG : Op;
+def OP_NOT : Op;
+def OP_AND : Op;
+def OP_OR : Op;
+def OP_XOR : Op;
+def OP_ANDN : Op;
+def OP_ORN : Op;
+def OP_CAST : Op;
+def OP_HI : Op;
+def OP_LO : Op;
+def OP_CONC : Op;
+def OP_DUP : Op;
+def OP_DUP_LN: Op;
+def OP_SEL : Op;
+def OP_REV64 : Op;
+def OP_REV32 : Op;
+def OP_REV16 : Op;
+def OP_REINT : Op;
+def OP_ABDL : Op;
+def OP_ABA : Op;
+def OP_ABAL : Op;
+
+class Inst <string n, string p, string t, Op o> {
+ string Name = n;
+ string Prototype = p;
+ string Types = t;
+ Op Operand = o;
+ bit isShift = 0;
+}
+
+// Used to generate Builtins.def:
+// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8")
+// IInst: Instruction with generic integer suffix (e.g., "i8")
+// WInst: Instruction with only bit size suffix (e.g., "8")
+class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
+
+// prototype: return (arg, arg, ...)
+// v: void
+// t: best-fit integer (int/poly args)
+// x: signed integer (int/float args)
+// u: unsigned integer (int/float args)
+// f: float (int args)
+// d: default
+// g: default, ignore 'Q' size modifier.
+// w: double width elements, same num elts
+// n: double width elements, half num elts
+// h: half width elements, double num elts
+// e: half width elements, double num elts, unsigned
+// i: constant int
+// l: constant uint64
+// s: scalar of element type
+// a: scalar of element type (splat to vector type)
+// k: default elt width, double num elts
+// #: array of default vectors
+// p: pointer type
+// c: const pointer type
+
+// sizes:
+// c: char
+// s: short
+// i: int
+// l: long
+// f: float
+// h: half-float
+
+// size modifiers:
+// U: unsigned
+// Q: 128b
+// P: polynomial
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.1 Addition
+def VADD : Inst<"vadd", "ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_ADD>;
+def VADDL : Inst<"vaddl", "wdd", "csiUcUsUi", OP_ADDL>;
+def VADDW : Inst<"vaddw", "wwd", "csiUcUsUi", OP_ADDW>;
+def VHADD : SInst<"vhadd", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VRHADD : SInst<"vrhadd", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VQADD : SInst<"vqadd", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VADDHN : IInst<"vaddhn", "hkk", "silUsUiUl">;
+def VRADDHN : IInst<"vraddhn", "hkk", "silUsUiUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.2 Multiplication
+def VMUL : Inst<"vmul", "ddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MUL>;
+def VMULP : SInst<"vmul", "ddd", "PcQPc">;
+def VMLA : Inst<"vmla", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLA>;
+def VMLAL : Inst<"vmlal", "wwdd", "csiUcUsUi", OP_MLAL>;
+def VMLS : Inst<"vmls", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
+def VMLSL : Inst<"vmlsl", "wwdd", "csiUcUsUi", OP_MLSL>;
+def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">;
+def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">;
+def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">;
+def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">;
+def VMULL : Inst<"vmull", "wdd", "csiUcUsUi", OP_MULL>;
+def VMULLP : SInst<"vmull", "wdd", "Pc">;
+def VQDMULL : SInst<"vqdmull", "wdd", "si">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.3 Subtraction
+def VSUB : Inst<"vsub", "ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_SUB>;
+def VSUBL : Inst<"vsubl", "wdd", "csiUcUsUi", OP_SUBL>;
+def VSUBW : Inst<"vsubw", "wwd", "csiUcUsUi", OP_SUBW>;
+def VQSUB : SInst<"vqsub", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VHSUB : SInst<"vhsub", "ddd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VSUBHN : IInst<"vsubhn", "hkk", "silUsUiUl">;
+def VRSUBHN : IInst<"vrsubhn", "hkk", "silUsUiUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.4 Comparison
+def VCEQ : Inst<"vceq", "udd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_EQ>;
+def VCGE : Inst<"vcge", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GE>;
+def VCLE : Inst<"vcle", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LE>;
+def VCGT : Inst<"vcgt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GT>;
+def VCLT : Inst<"vclt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LT>;
+def VCAGE : IInst<"vcage", "udd", "fQf">;
+def VCALE : IInst<"vcale", "udd", "fQf">;
+def VCAGT : IInst<"vcagt", "udd", "fQf">;
+def VCALT : IInst<"vcalt", "udd", "fQf">;
+def VTST : WInst<"vtst", "udd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.5 Absolute Difference
+def VABD : SInst<"vabd", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VABDL : Inst<"vabdl", "wdd", "csiUcUsUi", OP_ABDL>;
+def VABA : Inst<"vaba", "dddd", "csiUcUsUiQcQsQiQUcQUsQUi", OP_ABA>;
+def VABAL : Inst<"vabal", "wwdd", "csiUcUsUi", OP_ABAL>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.6 Max/Min
+def VMAX : SInst<"vmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VMIN : SInst<"vmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.7 Pairdise Addition
+def VPADD : IInst<"vpadd", "ddd", "csiUcUsUif">;
+def VPADDL : SInst<"vpaddl", "nd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VPADAL : SInst<"vpadal", "nnd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.8-9 Folding Max/Min
+def VPMAX : SInst<"vpmax", "ddd", "csiUcUsUif">;
+def VPMIN : SInst<"vpmin", "ddd", "csiUcUsUif">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.10 Reciprocal/Sqrt
+def VRECPS : IInst<"vrecps", "ddd", "fQf">;
+def VRSQRTS : IInst<"vrsqrts", "ddd", "fQf">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.11 Shifts by signed variable
+def VSHL : SInst<"vshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHL : SInst<"vqshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSHL : SInst<"vrshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQRSHL : SInst<"vqrshl", "ddx", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.12 Shifts by constant
+let isShift = 1 in {
+def VSHR_N : SInst<"vshr_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VSHL_N : IInst<"vshl_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSHR_N : SInst<"vrshr_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VSRA_N : SInst<"vsra_n", "dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VRSRA_N : SInst<"vrsra_n", "dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHL_N : SInst<"vqshl_n", "ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">;
+def VQSHLU_N : SInst<"vqshlu_n", "udi", "csilQcQsQiQl">;
+def VSHRN_N : IInst<"vshrn_n", "hki", "silUsUiUl">;
+def VQSHRUN_N : SInst<"vqshrun_n", "eki", "sil">;
+def VQRSHRUN_N : SInst<"vqrshrun_n", "eki", "sil">;
+def VQSHRN_N : SInst<"vqshrn_n", "hki", "silUsUiUl">;
+def VRSHRN_N : IInst<"vrshrn_n", "hki", "silUsUiUl">;
+def VQRSHRN_N : SInst<"vqrshrn_n", "hki", "silUsUiUl">;
+def VSHLL_N : SInst<"vshll_n", "wdi", "csiUcUsUi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.13 Shifts with insert
+def VSRI_N : WInst<"vsri_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
+def VSLI_N : WInst<"vsli_n", "dddi",
+ "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.14 Loads and stores of a single vector
+def VLD1 : WInst<"vld1", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1_LANE : WInst<"vld1_lane", "dcdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD1_DUP : WInst<"vld1_dup", "dc",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST1 : WInst<"vst1", "vpd",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST1_LANE : WInst<"vst1_lane", "vpdi",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.15 Loads and stores of an N-element structure
+def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VLD2_DUP : WInst<"vld2_dup", "2c", "UcUsUiUlcsilhfPcPs">;
+def VLD3_DUP : WInst<"vld3_dup", "3c", "UcUsUiUlcsilhfPcPs">;
+def VLD4_DUP : WInst<"vld4_dup", "4c", "UcUsUiUlcsilhfPcPs">;
+def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST2 : WInst<"vst2", "vp2", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST3 : WInst<"vst3", "vp3", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST4 : WInst<"vst4", "vp4", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">;
+def VST2_LANE : WInst<"vst2_lane", "vp2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST3_LANE : WInst<"vst3_lane", "vp3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+def VST4_LANE : WInst<"vst4_lane", "vp4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.16 Extract lanes from a vector
+def VGET_LANE : IInst<"vget_lane", "sdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.17 Set lanes within a vector
+def VSET_LANE : IInst<"vset_lane", "dsdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.18 Initialize a vector from bit pattern
+def VCREATE: Inst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.19 Set all lanes to same value
+def VDUP_N : Inst<"vdup_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VMOV_N : Inst<"vmov_n", "ds",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VDUP_LANE : Inst<"vdup_lane", "dgi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl",OP_DUP_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.20 Combining vectors
+def VCOMBINE : Inst<"vcombine", "kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.21 Splitting vectors
+def VGET_HIGH : Inst<"vget_high", "dk", "csilhfUcUsUiUlPcPs", OP_HI>;
+def VGET_LOW : Inst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.22 Converting vectors
+def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
+def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
+def VCVT_F16 : SInst<"vcvt_f16", "hk", "f">;
+def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
+def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
+def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
+def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "fd", "h">;
+def VCVT_N_F32 : SInst<"vcvt_n_f32", "fdi", "iUiQiQUi">;
+def VMOVN : IInst<"vmovn", "hk", "silUsUiUl">;
+def VMOVL : SInst<"vmovl", "wd", "csiUcUsUi">;
+def VQMOVN : SInst<"vqmovn", "hk", "silUsUiUl">;
+def VQMOVUN : SInst<"vqmovun", "ek", "sil">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.23-24 Table lookup, Extended table lookup
+def VTBL1 : WInst<"vtbl1", "ddt", "UccPc">;
+def VTBL2 : WInst<"vtbl2", "d2t", "UccPc">;
+def VTBL3 : WInst<"vtbl3", "d3t", "UccPc">;
+def VTBL4 : WInst<"vtbl4", "d4t", "UccPc">;
+def VTBX1 : WInst<"vtbx1", "dddt", "UccPc">;
+def VTBX2 : WInst<"vtbx2", "dd2t", "UccPc">;
+def VTBX3 : WInst<"vtbx3", "dd3t", "UccPc">;
+def VTBX4 : WInst<"vtbx4", "dd4t", "UccPc">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.25 Operations with a scalar value
+def VMLA_LANE : Inst<"vmla_lane", "dddgi", "siUsUifQsQiQUsQUiQf", OP_MLA_LN>;
+def VMLAL_LANE : Inst<"vmlal_lane", "wwddi", "siUsUi", OP_MLAL_LN>;
+def VQDMLAL_LANE : Inst<"vqdmlal_lane", "wwddi", "si", OP_QDMLAL_LN>;
+def VMLS_LANE : Inst<"vmls_lane", "dddgi", "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
+def VMLSL_LANE : Inst<"vmlsl_lane", "wwddi", "siUsUi", OP_MLSL_LN>;
+def VQDMLSL_LANE : Inst<"vqdmlsl_lane", "wwddi", "si", OP_QDMLSL_LN>;
+def VMUL_N : Inst<"vmul_n", "dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>;
+def VMUL_LANE : Inst<"vmul_lane", "ddgi", "sifUsUiQsQiQfQUsQUi", OP_MUL_LN>;
+def VMULL_N : Inst<"vmull_n", "wda", "siUsUi", OP_MULL_N>;
+def VMULL_LANE : Inst<"vmull_lane", "wddi", "siUsUi", OP_MULL_LN>;
+def VQDMULL_N : SInst<"vqdmull_n", "wda", "si">;
+def VQDMULL_LANE : Inst<"vqdmull_lane", "wddi", "si", OP_QDMULL_LN>;
+def VQDMULH_N : SInst<"vqdmulh_n", "dda", "siQsQi">;
+def VQDMULH_LANE : Inst<"vqdmulh_lane", "ddgi", "siQsQi", OP_QDMULH_LN>;
+def VQRDMULH_N : SInst<"vqrdmulh_n", "dda", "siQsQi">;
+def VQRDMULH_LANE : Inst<"vqrdmulh_lane", "ddgi", "siQsQi", OP_QRDMULH_LN>;
+def VMLA_N : Inst<"vmla_n", "ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
+def VMLAL_N : Inst<"vmlal_n", "wwda", "siUsUi", OP_MLAL_N>;
+def VQDMLAL_N : SInst<"vqdmlal_n", "wwda", "si">;
+def VMLS_N : Inst<"vmls_n", "ddds", "siUsUifQsQiQUsQUiQf", OP_MLS_N>;
+def VMLSL_N : Inst<"vmlsl_n", "wwda", "siUsUi", OP_MLSL_N>;
+def VQDMLSL_N : SInst<"vqdmlsl_n", "wwda", "si">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.26 Vector Extract
+def VEXT : WInst<"vext", "dddi",
+ "cUcPcsUsPsiUilUlfQcQUcQPcQsQUsQPsQiQUiQlQUlQf">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.27 Reverse vector elements (sdap endianness)
+def VREV64 : Inst<"vrev64", "dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf",
+ OP_REV64>;
+def VREV32 : Inst<"vrev32", "dd", "csUcUsPcPsQcQsQUcQUsQPcQPs", OP_REV32>;
+def VREV16 : Inst<"vrev16", "dd", "cUcPcQcQUcQPc", OP_REV16>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.28 Other single operand arithmetic
+def VABS : SInst<"vabs", "dd", "csifQcQsQiQf">;
+def VQABS : SInst<"vqabs", "dd", "csiQcQsQi">;
+def VNEG : Inst<"vneg", "dd", "csifQcQsQiQf", OP_NEG>;
+def VQNEG : SInst<"vqneg", "dd", "csiQcQsQi">;
+def VCLS : SInst<"vcls", "dd", "csiQcQsQi">;
+def VCLZ : IInst<"vclz", "dd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VCNT : WInst<"vcnt", "dd", "UccPcQUcQcQPc">;
+def VRECPE : SInst<"vrecpe", "dd", "fUiQfQUi">;
+def VRSQRTE : SInst<"vrsqrte", "dd", "fUiQfQUi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.29 Logical operations
+def VMVN : Inst<"vmvn", "dd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc", OP_NOT>;
+def VAND : Inst<"vand", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_AND>;
+def VORR : Inst<"vorr", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_OR>;
+def VEOR : Inst<"veor", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_XOR>;
+def VBIC : Inst<"vbic", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ANDN>;
+def VORN : Inst<"vorn", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ORN>;
+def VBSL : Inst<"vbsl", "dudd",
+ "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs", OP_SEL>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.30 Transposition operations
+def VTRN : WInst<"vtrn", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+def VZIP : WInst<"vzip", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+def VUZP : WInst<"vuzp", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.31 Vector reinterpret cast operations
+def VREINTERPRET
+ : Inst<"vreinterpret", "dd",
+ "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT>;
+
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
new file mode 100644
index 0000000..abcef81
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
@@ -0,0 +1,37 @@
+//===--- BackendUtil.h - LLVM Backend Utilities -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_BACKEND_UTIL_H
+#define LLVM_CLANG_CODEGEN_BACKEND_UTIL_H
+
+namespace llvm {
+ class Module;
+ class raw_ostream;
+}
+
+namespace clang {
+ class Diagnostic;
+ class CodeGenOptions;
+ class TargetOptions;
+
+ enum BackendAction {
+ Backend_EmitAssembly, ///< Emit native assembly files
+ Backend_EmitBC, ///< Emit LLVM bitcode files
+ Backend_EmitLL, ///< Emit human-readable LLVM assembly
+ Backend_EmitNothing, ///< Don't emit anything (benchmarking mode)
+ Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything
+ Backend_EmitObj ///< Emit native object files
+ };
+
+ void EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts,
+ const TargetOptions &TOpts, llvm::Module *M,
+ BackendAction Action, llvm::raw_ostream *OS);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
new file mode 100644
index 0000000..052c660
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
@@ -0,0 +1,91 @@
+//===--- CodeGenAction.h - LLVM Code Generation Frontend Action -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H
+#define LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace llvm {
+ class LLVMContext;
+ class Module;
+}
+
+namespace clang {
+class BackendConsumer;
+
+class CodeGenAction : public ASTFrontendAction {
+private:
+ unsigned Act;
+ llvm::OwningPtr<llvm::Module> TheModule;
+ llvm::LLVMContext *VMContext;
+ bool OwnsVMContext;
+
+protected:
+ /// Create a new code generation action. If the optional \arg _VMContext
+ /// parameter is supplied, the action uses it without taking ownership,
+ /// otherwise it creates a fresh LLVM context and takes ownership.
+ CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = 0);
+
+ virtual bool hasIRSupport() const;
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual void ExecuteAction();
+
+ virtual void EndSourceFileAction();
+
+public:
+ ~CodeGenAction();
+
+ /// takeModule - Take the generated LLVM module, for use after the action has
+ /// been run. The result may be null on failure.
+ llvm::Module *takeModule();
+
+ /// Take the LLVM context used by this action.
+ llvm::LLVMContext *takeLLVMContext();
+
+ BackendConsumer *BEConsumer;
+};
+
+class EmitAssemblyAction : public CodeGenAction {
+public:
+ EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+class EmitBCAction : public CodeGenAction {
+public:
+ EmitBCAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+class EmitLLVMAction : public CodeGenAction {
+public:
+ EmitLLVMAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+class EmitLLVMOnlyAction : public CodeGenAction {
+public:
+ EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+class EmitCodeGenOnlyAction : public CodeGenAction {
+public:
+ EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+class EmitObjAction : public CodeGenAction {
+public:
+ EmitObjAction(llvm::LLVMContext *_VMContext = 0);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
new file mode 100644
index 0000000..c45ad08
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
@@ -0,0 +1,45 @@
+//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- 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 ModuleBuilder interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H
+#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
+
+#include "clang/AST/ASTConsumer.h"
+#include <string>
+
+namespace llvm {
+ class LLVMContext;
+ class Module;
+}
+
+namespace clang {
+ class Diagnostic;
+ class LangOptions;
+ class CodeGenOptions;
+
+ class CodeGenerator : public ASTConsumer {
+ public:
+ virtual llvm::Module* GetModule() = 0;
+ virtual llvm::Module* ReleaseModule() = 0;
+ };
+
+ /// CreateLLVMCodeGen - Create a CodeGenerator instance.
+ /// It is the responsibility of the caller to call delete on
+ /// the allocated CodeGenerator instance.
+ CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
+ const std::string &ModuleName,
+ const CodeGenOptions &CGO,
+ llvm::LLVMContext& C);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Config/config.h.cmake b/contrib/llvm/tools/clang/include/clang/Config/config.h.cmake
new file mode 100644
index 0000000..5f13d2f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Config/config.h.cmake
@@ -0,0 +1,17 @@
+/* Relative directory for resource files */
+#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}"
+
+/* 32 bit multilib directory. */
+#define CXX_INCLUDE_32BIT_DIR "${CXX_INCLUDE_32BIT_DIR}"
+
+/* 64 bit multilib directory. */
+#define CXX_INCLUDE_64BIT_DIR "${CXX_INCLUDE_64BIT_DIR}"
+
+/* Arch the libstdc++ headers. */
+#define CXX_INCLUDE_ARCH "${CXX_INCLUDE_ARCH}"
+
+/* Directory with the libstdc++ headers. */
+#define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}"
+
+/* Directories clang will search for headers */
+#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
new file mode 100644
index 0000000..4b45c98
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
@@ -0,0 +1,228 @@
+//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ACTION_H_
+#define CLANG_DRIVER_ACTION_H_
+
+#include "llvm/ADT/SmallVector.h"
+
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+ class Arg;
+
+/// Action - Represent an abstract compilation step to perform.
+///
+/// An action represents an edge in the compilation graph; typically
+/// it is a job to transform an input using some tool.
+///
+/// The current driver is hard wired to expect actions which produce a
+/// single primary output, at least in terms of controlling the
+/// compilation. Actions can produce auxiliary files, but can only
+/// produce a single output to feed into subsequent actions.
+class Action {
+public:
+ typedef ActionList::size_type size_type;
+ typedef ActionList::iterator iterator;
+ typedef ActionList::const_iterator const_iterator;
+
+ enum ActionClass {
+ InputClass = 0,
+ BindArchClass,
+ PreprocessJobClass,
+ PrecompileJobClass,
+ AnalyzeJobClass,
+ CompileJobClass,
+ AssembleJobClass,
+ LinkJobClass,
+ LipoJobClass,
+ DsymutilJobClass,
+
+ JobClassFirst=PreprocessJobClass,
+ JobClassLast=DsymutilJobClass
+ };
+
+ static const char *getClassName(ActionClass AC);
+
+private:
+ ActionClass Kind;
+
+ /// The output type of this action.
+ types::ID Type;
+
+ ActionList Inputs;
+
+ unsigned OwnsInputs : 1;
+
+protected:
+ Action(ActionClass _Kind, types::ID _Type)
+ : Kind(_Kind), Type(_Type), OwnsInputs(true) {}
+ Action(ActionClass _Kind, Action *Input, types::ID _Type)
+ : Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1), OwnsInputs(true) {}
+ Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type)
+ : Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {}
+public:
+ virtual ~Action();
+
+ const char *getClassName() const { return Action::getClassName(getKind()); }
+
+ bool getOwnsInputs() { return OwnsInputs; }
+ void setOwnsInputs(bool Value) { OwnsInputs = Value; }
+
+ ActionClass getKind() const { return Kind; }
+ types::ID getType() const { return Type; }
+
+ ActionList &getInputs() { return Inputs; }
+ const ActionList &getInputs() const { return Inputs; }
+
+ size_type size() const { return Inputs.size(); }
+
+ iterator begin() { return Inputs.begin(); }
+ iterator end() { return Inputs.end(); }
+ const_iterator begin() const { return Inputs.begin(); }
+ const_iterator end() const { return Inputs.end(); }
+
+ static bool classof(const Action *) { return true; }
+};
+
+class InputAction : public Action {
+ const Arg &Input;
+public:
+ InputAction(const Arg &_Input, types::ID _Type);
+
+ const Arg &getInputArg() const { return Input; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == InputClass;
+ }
+ static bool classof(const InputAction *) { return true; }
+};
+
+class BindArchAction : public Action {
+ /// The architecture to bind, or 0 if the default architecture
+ /// should be bound.
+ const char *ArchName;
+
+public:
+ BindArchAction(Action *Input, const char *_ArchName);
+
+ const char *getArchName() const { return ArchName; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == BindArchClass;
+ }
+ static bool classof(const BindArchAction *) { return true; }
+};
+
+class JobAction : public Action {
+protected:
+ JobAction(ActionClass Kind, Action *Input, types::ID Type);
+ JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
+
+public:
+ static bool classof(const Action *A) {
+ return (A->getKind() >= JobClassFirst &&
+ A->getKind() <= JobClassLast);
+ }
+ static bool classof(const JobAction *) { return true; }
+};
+
+class PreprocessJobAction : public JobAction {
+public:
+ PreprocessJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PreprocessJobClass;
+ }
+ static bool classof(const PreprocessJobAction *) { return true; }
+};
+
+class PrecompileJobAction : public JobAction {
+public:
+ PrecompileJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PrecompileJobClass;
+ }
+ static bool classof(const PrecompileJobAction *) { return true; }
+};
+
+class AnalyzeJobAction : public JobAction {
+public:
+ AnalyzeJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AnalyzeJobClass;
+ }
+ static bool classof(const AnalyzeJobAction *) { return true; }
+};
+
+class CompileJobAction : public JobAction {
+public:
+ CompileJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == CompileJobClass;
+ }
+ static bool classof(const CompileJobAction *) { return true; }
+};
+
+class AssembleJobAction : public JobAction {
+public:
+ AssembleJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AssembleJobClass;
+ }
+ static bool classof(const AssembleJobAction *) { return true; }
+};
+
+class LinkJobAction : public JobAction {
+public:
+ LinkJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LinkJobClass;
+ }
+ static bool classof(const LinkJobAction *) { return true; }
+};
+
+class LipoJobAction : public JobAction {
+public:
+ LipoJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LipoJobClass;
+ }
+ static bool classof(const LipoJobAction *) { return true; }
+};
+
+class DsymutilJobAction : public JobAction {
+public:
+ DsymutilJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == DsymutilJobClass;
+ }
+ static bool classof(const DsymutilJobAction *) { return true; }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Arg.h b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h
new file mode 100644
index 0000000..a52789e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Arg.h
@@ -0,0 +1,123 @@
+//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ARG_H_
+#define CLANG_DRIVER_ARG_H_
+
+#include "Util.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Option;
+
+ /// Arg - A concrete instance of a particular driver option.
+ ///
+ /// The Arg class encodes just enough information to be able to
+ /// derive the argument values efficiently. In addition, Arg
+ /// instances have an intrusive double linked list which is used by
+ /// ArgList to provide efficient iteration over all instances of a
+ /// particular option.
+ class Arg {
+ Arg(const Arg &); // DO NOT IMPLEMENT
+ void operator=(const Arg &); // DO NOT IMPLEMENT
+
+ private:
+ /// The option this argument is an instance of.
+ const Option *Opt;
+
+ /// The argument this argument was derived from (during tool chain
+ /// argument translation), if any.
+ const Arg *BaseArg;
+
+ /// The index at which this argument appears in the containing
+ /// ArgList.
+ unsigned Index;
+
+ /// Was this argument used to effect compilation; used for generating
+ /// "argument unused" diagnostics.
+ mutable unsigned Claimed : 1;
+
+ /// Does this argument own its values.
+ mutable unsigned OwnsValues : 1;
+
+ /// The argument values, as C strings.
+ llvm::SmallVector<const char *, 2> Values;
+
+ public:
+ Arg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0);
+ Arg(const Option *Opt, unsigned Index,
+ const char *Value0, const Arg *BaseArg = 0);
+ Arg(const Option *Opt, unsigned Index,
+ const char *Value0, const char *Value1, const Arg *BaseArg = 0);
+ ~Arg();
+
+ const Option &getOption() const { return *Opt; }
+ unsigned getIndex() const { return Index; }
+
+ /// getBaseArg - Return the base argument which generated this
+ /// arg; this is either the argument itself or the argument it was
+ /// derived from during tool chain specific argument translation.
+ const Arg &getBaseArg() const {
+ return BaseArg ? *BaseArg : *this;
+ }
+ void setBaseArg(const Arg *_BaseArg) {
+ BaseArg = _BaseArg;
+ }
+
+ bool getOwnsValues() const { return OwnsValues; }
+ void setOwnsValues(bool Value) const { OwnsValues = Value; }
+
+ bool isClaimed() const { return getBaseArg().Claimed; }
+
+ /// claim - Set the Arg claimed bit.
+ void claim() const { getBaseArg().Claimed = true; }
+
+ unsigned getNumValues() const { return Values.size(); }
+ const char *getValue(const ArgList &Args, unsigned N=0) const {
+ return Values[N];
+ }
+
+ llvm::SmallVectorImpl<const char*> &getValues() {
+ return Values;
+ }
+
+ bool containsValue(llvm::StringRef Value) const {
+ for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+ if (Values[i] == Value)
+ return true;
+ return false;
+ }
+
+ /// render - Append the argument onto the given array as strings.
+ void render(const ArgList &Args, ArgStringList &Output) const;
+
+ /// renderAsInput - Append the argument, render as an input, onto
+ /// the given array as strings. The distinction is that some
+ /// options only render their values when rendered as a input
+ /// (e.g., Xlinker).
+ void renderAsInput(const ArgList &Args, ArgStringList &Output) const;
+
+ static bool classof(const Arg *) { return true; }
+
+ void dump() const;
+
+ /// getAsString - Return a formatted version of the argument and
+ /// its values, for debugging and diagnostics.
+ std::string getAsString(const ArgList &Args) const;
+ };
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h
new file mode 100644
index 0000000..0fcf821
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ArgList.h
@@ -0,0 +1,408 @@
+//===--- ArgList.h - Argument List Management ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ARGLIST_H_
+#define CLANG_DRIVER_ARGLIST_H_
+
+#include "clang/Driver/OptSpecifier.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <list>
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class Twine;
+}
+
+namespace clang {
+ class Diagnostic;
+
+namespace driver {
+ class Arg;
+ class ArgList;
+ class Option;
+
+ /// arg_iterator - Iterates through arguments stored inside an ArgList.
+ class arg_iterator {
+ /// The current argument.
+ llvm::SmallVectorImpl<Arg*>::const_iterator Current;
+
+ /// The argument list we are iterating over.
+ const ArgList &Args;
+
+ /// Optional filters on the arguments which will be match. Most clients
+ /// should never want to iterate over arguments without filters, so we won't
+ /// bother to factor this into two separate iterator implementations.
+ //
+ // FIXME: Make efficient; the idea is to provide efficient iteration over
+ // all arguments which match a particular id and then just provide an
+ // iterator combinator which takes multiple iterators which can be
+ // efficiently compared and returns them in order.
+ OptSpecifier Id0, Id1, Id2;
+
+ void SkipToNextArg();
+
+ public:
+ typedef Arg * const * value_type;
+ typedef Arg * const & reference;
+ typedef Arg * const * pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it,
+ const ArgList &_Args, OptSpecifier _Id0 = 0U,
+ OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
+ : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
+ SkipToNextArg();
+ }
+
+ operator const Arg*() { return *Current; }
+ reference operator*() const { return *Current; }
+ pointer operator->() const { return Current; }
+
+ arg_iterator &operator++() {
+ ++Current;
+ SkipToNextArg();
+ return *this;
+ }
+
+ arg_iterator operator++(int) {
+ arg_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
+ return LHS.Current == RHS.Current;
+ }
+ friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
+ return !(LHS == RHS);
+ }
+ };
+
+ /// ArgList - Ordered collection of driver arguments.
+ ///
+ /// The ArgList class manages a list of Arg instances as well as
+ /// auxiliary data and convenience methods to allow Tools to quickly
+ /// check for the presence of Arg instances for a particular Option
+ /// and to iterate over groups of arguments.
+ class ArgList {
+ private:
+ ArgList(const ArgList &); // DO NOT IMPLEMENT
+ void operator=(const ArgList &); // DO NOT IMPLEMENT
+
+ public:
+ typedef llvm::SmallVector<Arg*, 16> arglist_type;
+ typedef arglist_type::iterator iterator;
+ typedef arglist_type::const_iterator const_iterator;
+ typedef arglist_type::reverse_iterator reverse_iterator;
+ typedef arglist_type::const_reverse_iterator const_reverse_iterator;
+
+ private:
+ /// The internal list of arguments.
+ arglist_type Args;
+
+ protected:
+ ArgList();
+
+ public:
+ virtual ~ArgList();
+
+ /// @name Arg Access
+ /// @{
+
+ /// append - Append \arg A to the arg list.
+ void append(Arg *A);
+
+ arglist_type &getArgs() { return Args; }
+ const arglist_type &getArgs() const { return Args; }
+
+ unsigned size() const { return Args.size(); }
+
+ /// @}
+ /// @name Arg Iteration
+ /// @{
+
+ iterator begin() { return Args.begin(); }
+ iterator end() { return Args.end(); }
+
+ reverse_iterator rbegin() { return Args.rbegin(); }
+ reverse_iterator rend() { return Args.rend(); }
+
+ const_iterator begin() const { return Args.begin(); }
+ const_iterator end() const { return Args.end(); }
+
+ const_reverse_iterator rbegin() const { return Args.rbegin(); }
+ const_reverse_iterator rend() const { return Args.rend(); }
+
+ arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
+ OptSpecifier Id2 = 0U) const {
+ return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
+ }
+ arg_iterator filtered_end() const {
+ return arg_iterator(Args.end(), *this);
+ }
+
+ /// @}
+ /// @name Arg Access
+ /// @{
+
+ /// hasArg - Does the arg list contain any option matching \arg Id.
+ ///
+ /// \arg Claim Whether the argument should be claimed, if it exists.
+ bool hasArgNoClaim(OptSpecifier Id) const {
+ return getLastArgNoClaim(Id) != 0;
+ }
+ bool hasArg(OptSpecifier Id) const {
+ return getLastArg(Id) != 0;
+ }
+ bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
+ return getLastArg(Id0, Id1) != 0;
+ }
+ bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
+ return getLastArg(Id0, Id1, Id2) != 0;
+ }
+
+ /// getLastArg - Return the last argument matching \arg Id, or null.
+ ///
+ /// \arg Claim Whether the argument should be claimed, if it exists.
+ Arg *getLastArgNoClaim(OptSpecifier Id) const;
+ Arg *getLastArg(OptSpecifier Id) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
+ Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3) const;
+
+ /// getArgString - Return the input argument string at \arg Index.
+ virtual const char *getArgString(unsigned Index) const = 0;
+
+ /// getNumInputArgStrings - Return the number of original argument strings,
+ /// which are guaranteed to be the first strings in the argument string
+ /// list.
+ virtual unsigned getNumInputArgStrings() const = 0;
+
+ /// @}
+ /// @name Argument Lookup Utilities
+ /// @{
+
+ /// getLastArgValue - Return the value of the last argument, or a default.
+ llvm::StringRef getLastArgValue(OptSpecifier Id,
+ llvm::StringRef Default = "") const;
+
+ /// getLastArgValue - Return the value of the last argument as an integer,
+ /// or a default. Emits an error if the argument is given, but non-integral.
+ int getLastArgIntValue(OptSpecifier Id, int Default,
+ Diagnostic &Diags) const;
+
+ /// getAllArgValues - Get the values of all instances of the given argument
+ /// as strings.
+ std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
+
+ /// @}
+ /// @name Translation Utilities
+ /// @{
+
+ /// hasFlag - Given an option \arg Pos and its negative form \arg
+ /// Neg, return true if the option is present, false if the
+ /// negation is present, and \arg Default if neither option is
+ /// given. If both the option and its negation are present, the
+ /// last one wins.
+ bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const;
+
+ /// AddLastArg - Render only the last argument match \arg Id0, if
+ /// present.
+ void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
+
+ /// AddAllArgs - Render all arguments matching the given ids.
+ void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
+
+ /// AddAllArgValues - Render the argument values of all arguments
+ /// matching the given ids.
+ void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
+
+ /// AddAllArgsTranslated - Render all the arguments matching the
+ /// given ids, but forced to separate args and using the provided
+ /// name instead of the first option value.
+ ///
+ /// \param Joined - If true, render the argument as joined with
+ /// the option specifier.
+ void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
+ const char *Translation,
+ bool Joined = false) const;
+
+ /// ClaimAllArgs - Claim all arguments which match the given
+ /// option id.
+ void ClaimAllArgs(OptSpecifier Id0) const;
+
+ /// @}
+ /// @name Arg Synthesis
+ /// @{
+
+ /// MakeArgString - Construct a constant string pointer whose
+ /// lifetime will match that of the ArgList.
+ virtual const char *MakeArgString(llvm::StringRef Str) const = 0;
+ const char *MakeArgString(const char *Str) const {
+ return MakeArgString(llvm::StringRef(Str));
+ }
+ const char *MakeArgString(std::string Str) const {
+ return MakeArgString(llvm::StringRef(Str));
+ }
+ const char *MakeArgString(const llvm::Twine &Str) const;
+
+ /// \brief Create an arg string for (\arg LHS + \arg RHS), reusing the
+ /// string at \arg Index if possible.
+ const char *GetOrMakeJoinedArgString(unsigned Index, llvm::StringRef LHS,
+ llvm::StringRef RHS) const;
+
+ /// @}
+ };
+
+ class InputArgList : public ArgList {
+ private:
+ /// List of argument strings used by the contained Args.
+ ///
+ /// This is mutable since we treat the ArgList as being the list
+ /// of Args, and allow routines to add new strings (to have a
+ /// convenient place to store the memory) via MakeIndex.
+ mutable ArgStringList ArgStrings;
+
+ /// Strings for synthesized arguments.
+ ///
+ /// This is mutable since we treat the ArgList as being the list
+ /// of Args, and allow routines to add new strings (to have a
+ /// convenient place to store the memory) via MakeIndex.
+ mutable std::list<std::string> SynthesizedStrings;
+
+ /// The number of original input argument strings.
+ unsigned NumInputArgStrings;
+
+ public:
+ InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
+ ~InputArgList();
+
+ virtual const char *getArgString(unsigned Index) const {
+ return ArgStrings[Index];
+ }
+
+ virtual unsigned getNumInputArgStrings() const {
+ return NumInputArgStrings;
+ }
+
+ /// @name Arg Synthesis
+ /// @{
+
+ public:
+ /// MakeIndex - Get an index for the given string(s).
+ unsigned MakeIndex(llvm::StringRef String0) const;
+ unsigned MakeIndex(llvm::StringRef String0, llvm::StringRef String1) const;
+
+ virtual const char *MakeArgString(llvm::StringRef Str) const;
+
+ /// @}
+ };
+
+ /// DerivedArgList - An ordered collection of driver arguments,
+ /// whose storage may be in another argument list.
+ class DerivedArgList : public ArgList {
+ const InputArgList &BaseArgs;
+
+ /// The list of arguments we synthesized.
+ mutable arglist_type SynthesizedArgs;
+
+ public:
+ /// Construct a new derived arg list from \arg BaseArgs.
+ DerivedArgList(const InputArgList &BaseArgs);
+ ~DerivedArgList();
+
+ virtual const char *getArgString(unsigned Index) const {
+ return BaseArgs.getArgString(Index);
+ }
+
+ virtual unsigned getNumInputArgStrings() const {
+ return BaseArgs.getNumInputArgStrings();
+ }
+
+ const InputArgList &getBaseArgs() const {
+ return BaseArgs;
+ }
+
+ /// @name Arg Synthesis
+ /// @{
+
+ /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
+ /// (to be freed).
+ void AddSynthesizedArg(Arg *A) {
+ SynthesizedArgs.push_back(A);
+ }
+
+ virtual const char *MakeArgString(llvm::StringRef Str) const;
+
+ /// AddFlagArg - Construct a new FlagArg for the given option \arg Id and
+ /// append it to the argument list.
+ void AddFlagArg(const Arg *BaseArg, const Option *Opt) {
+ append(MakeFlagArg(BaseArg, Opt));
+ }
+
+ /// AddPositionalArg - Construct a new Positional arg for the given option
+ /// \arg Id, with the provided \arg Value and append it to the argument
+ /// list.
+ void AddPositionalArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) {
+ append(MakePositionalArg(BaseArg, Opt, Value));
+ }
+
+
+ /// AddSeparateArg - Construct a new Positional arg for the given option
+ /// \arg Id, with the provided \arg Value and append it to the argument
+ /// list.
+ void AddSeparateArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) {
+ append(MakeSeparateArg(BaseArg, Opt, Value));
+ }
+
+
+ /// AddJoinedArg - Construct a new Positional arg for the given option \arg
+ /// Id, with the provided \arg Value and append it to the argument list.
+ void AddJoinedArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) {
+ append(MakeJoinedArg(BaseArg, Opt, Value));
+ }
+
+
+ /// MakeFlagArg - Construct a new FlagArg for the given option
+ /// \arg Id.
+ Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const;
+
+ /// MakePositionalArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const;
+
+ /// MakeSeparateArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const;
+
+ /// MakeJoinedArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const;
+
+ /// @}
+ };
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h
new file mode 100644
index 0000000..0508213
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.h
@@ -0,0 +1,32 @@
+//===--- CC1AsOptions.h - Clang Assembler Options Table ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_CC1ASOPTIONS_H
+#define CLANG_DRIVER_CC1ASOPTIONS_H
+
+namespace clang {
+namespace driver {
+ class OptTable;
+
+namespace cc1asoptions {
+ enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/CC1AsOptions.inc"
+ LastOption
+#undef OPTION
+ };
+}
+
+ OptTable *createCC1AsOptTable();
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td
new file mode 100644
index 0000000..50472ff
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1AsOptions.td
@@ -0,0 +1,75 @@
+//===--- CC1AsOptions.td - Options for clang -cc1as -----------------------===//
+//
+// 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 options accepted by clang -cc1as.
+//
+//===----------------------------------------------------------------------===//
+
+// Include the common option parsing interfaces.
+include "OptParser.td"
+
+//===----------------------------------------------------------------------===//
+// Target Options
+//===----------------------------------------------------------------------===//
+
+def triple : Separate<"-triple">,
+ HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">;
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to include search path">;
+def n : Flag<"-n">,
+ HelpText<"Don't automatically start assembly file with a text section">;
+
+//===----------------------------------------------------------------------===//
+// Frontend Options
+//===----------------------------------------------------------------------===//
+
+def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
+
+def filetype : Separate<"-filetype">,
+ HelpText<"Specify the output file type ('asm', 'null', or 'obj')">;
+
+def help : Flag<"-help">,
+ HelpText<"Print this help text">;
+def _help : Flag<"--help">, Alias<help>;
+
+def version : Flag<"-version">,
+ HelpText<"Print the assembler version">;
+def _version : Flag<"--version">, Alias<version>;
+def v : Flag<"-v">, Alias<version>;
+
+// Generic forwarding to LLVM options. This should only be used for debugging
+// and experimental features.
+def mllvm : Separate<"-mllvm">,
+ HelpText<"Additional arguments to forward to LLVM's option processing">;
+
+//===----------------------------------------------------------------------===//
+// Transliterate Options
+//===----------------------------------------------------------------------===//
+
+def output_asm_variant : Separate<"-output-asm-variant">,
+ HelpText<"Select the asm variant index to use for output">;
+def show_encoding : Flag<"-show-encoding">,
+ HelpText<"Show instruction encoding information in transliterate mode">;
+def show_inst : Flag<"-show-inst">,
+ HelpText<"Show internal instruction representation in transliterate mode">;
+
+//===----------------------------------------------------------------------===//
+// Assemble Options
+//===----------------------------------------------------------------------===//
+
+def relax_all : Flag<"-relax-all">,
+ HelpText<"Relax all fixups (for performance testing)">;
+
+def no_exec_stack : Flag<"--noexecstack">,
+ HelpText<"Mark the file as not needing an executable stack">; \ No newline at end of file
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h
new file mode 100644
index 0000000..4a8bbe5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.h
@@ -0,0 +1,32 @@
+//===--- CC1Options.h - Clang CC1 Options Table -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_CC1OPTIONS_H
+#define CLANG_DRIVER_CC1OPTIONS_H
+
+namespace clang {
+namespace driver {
+ class OptTable;
+
+namespace cc1options {
+ enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/CC1Options.inc"
+ LastOption
+#undef OPTION
+ };
+}
+
+ OptTable *createCC1OptTable();
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
new file mode 100644
index 0000000..57107ba
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -0,0 +1,617 @@
+//===--- CC1Options.td - Options for clang -cc1 ---------------------------===//
+//
+// 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 options accepted by clang -cc1.
+//
+//===----------------------------------------------------------------------===//
+
+// Include the common option parsing interfaces.
+include "OptParser.td"
+
+//===----------------------------------------------------------------------===//
+// Target Options
+//===----------------------------------------------------------------------===//
+
+def cxx_abi : Separate<"-cxx-abi">,
+ HelpText<"Target a particular C++ ABI type">;
+def target_abi : Separate<"-target-abi">,
+ HelpText<"Target a particular ABI type">;
+def target_cpu : Separate<"-target-cpu">,
+ HelpText<"Target a specific cpu type">;
+def target_feature : Separate<"-target-feature">,
+ HelpText<"Target specific attributes">;
+def target_linker_version : Separate<"-target-linker-version">,
+ HelpText<"Target linker version">;
+def triple : Separate<"-triple">,
+ HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
+def triple_EQ : Joined<"-triple=">, Alias<triple>;
+
+//===----------------------------------------------------------------------===//
+// Analyzer Options
+//===----------------------------------------------------------------------===//
+
+def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">,
+ HelpText<"Generate unoptimized CFGs for all analyses">;
+def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">,
+ HelpText<"Add C++ implicit destructors to CFGs for all analyses">;
+def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">,
+ HelpText<"Add C++ initializers to CFGs for all analyses">;
+def analysis_WarnUninitVals : Flag<"-warn-uninit-values">,
+ HelpText<"Warn about uses of uninitialized variables">;
+def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
+ HelpText<"Run the [Core] Foundation reference count checker">;
+def analysis_AnalyzerStats : Flag<"-analyzer-stats">,
+ HelpText<"Emit warnings with analyzer statistics">;
+def analysis_WarnBufferOverflows : Flag<"-analyzer-check-buffer-overflows">,
+ HelpText<"Warn about buffer overflows">;
+
+def analyzer_store : Separate<"-analyzer-store">,
+ HelpText<"Source Code Analysis - Abstract Memory Store Models">;
+def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias<analyzer_store>;
+
+def analyzer_constraints : Separate<"-analyzer-constraints">,
+ HelpText<"Source Code Analysis - Symbolic Constraint Engines">;
+def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">,
+ Alias<analyzer_constraints>;
+
+def analyzer_output : Separate<"-analyzer-output">,
+ HelpText<"Source Code Analysis - Output Options">;
+def analyzer_output_EQ : Joined<"-analyzer-output=">,
+ Alias<analyzer_output>;
+
+def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">,
+ HelpText<"Force the static analyzer to analyze functions defined in header files">;
+def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">,
+ HelpText<"Analyze the definitions of blocks in addition to functions">;
+def analyzer_display_progress : Flag<"-analyzer-display-progress">,
+ HelpText<"Emit verbose output about the analyzer's progress">;
+def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
+ HelpText<"Use experimental path-sensitive checks">;
+def analyzer_experimental_internal_checks :
+ Flag<"-analyzer-experimental-internal-checks">,
+ HelpText<"Use new default path-sensitive checks currently in testing">;
+def analyze_function : Separate<"-analyze-function">,
+ HelpText<"Run analysis on specific function">;
+def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>;
+def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">,
+ HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
+def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">,
+ HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">;
+def analyzer_no_eagerly_trim_egraph : Flag<"-analyzer-no-eagerly-trim-egraph">,
+ HelpText<"Don't eagerly remove uninteresting ExplodedNodes from the ExplodedGraph">;
+def trim_egraph : Flag<"-trim-egraph">,
+ HelpText<"Only show error-related paths in the analysis graph">;
+def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">,
+ HelpText<"Display exploded graph using GraphViz">;
+def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
+ HelpText<"Display exploded graph using Ubigraph">;
+def analyzer_inline_call : Flag<"-analyzer-inline-call">,
+ HelpText<"Experimental transfer function inlining callees when its definition is available.">;
+def analyzer_max_nodes : Separate<"-analyzer-max-nodes">,
+ HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">;
+def analyzer_max_loop : Separate<"-analyzer-max-loop">,
+ HelpText<"The maximum number of times the analyzer will go through a loop">;
+
+def analyzer_checker : Separate<"-analyzer-checker">,
+ HelpText<"Choose analyzer checkers to enable">;
+def analyzer_checker_EQ : Joined<"-analyzer-checker=">,
+ Alias<analyzer_checker>;
+
+def analyzer_disable_checker : Separate<"-analyzer-disable-checker">,
+ HelpText<"Choose analyzer checkers to disable">;
+def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">,
+ Alias<analyzer_disable_checker>;
+
+//===----------------------------------------------------------------------===//
+// CodeGen Options
+//===----------------------------------------------------------------------===//
+
+def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
+ HelpText<"Don't run LLVM optimization passes">;
+def disable_llvm_verifier : Flag<"-disable-llvm-verifier">,
+ HelpText<"Don't run the LLVM IR verifier pass">;
+def disable_red_zone : Flag<"-disable-red-zone">,
+ HelpText<"Do not emit code that uses the red zone.">;
+def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
+ HelpText<"The string to embed in the Dwarf debug flags record.">;
+def g : Flag<"-g">, HelpText<"Generate source level debug information">;
+def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
+ HelpText<"Generate runtime checks for undefined behavior.">;
+def flimit_debug_info : Flag<"-flimit-debug-info">,
+ HelpText<"Limit debug information produced to reduce size of debug binary">;
+def fno_common : Flag<"-fno-common">,
+ HelpText<"Compile common globals like normal definitions">;
+def no_implicit_float : Flag<"-no-implicit-float">,
+ HelpText<"Don't generate implicit floating point instructions (x86-only)">;
+def finstrument_functions : Flag<"-finstrument-functions">,
+ HelpText<"Generate calls to instrument function entry and exit">;
+def fno_merge_all_constants : Flag<"-fno-merge-all-constants">,
+ HelpText<"Disallow merging of constants.">;
+def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">,
+ HelpText<"Do not emit code to make initialization of local statics thread safe">;
+def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">,
+ HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">;
+def ffunction_sections : Flag<"-ffunction-sections">,
+ HelpText<"Place each function in its own section (ELF Only)">;
+def fdata_sections : Flag<"-fdata-sections">,
+ HelpText<"Place each data in its own section (ELF Only)">;
+def funroll_loops : Flag<"-funroll-loops">,
+ HelpText<"Turn on loop unroller">;
+def relaxed_aliasing : Flag<"-relaxed-aliasing">,
+ HelpText<"Turn off Type Based Alias Analysis">;
+def masm_verbose : Flag<"-masm-verbose">,
+ HelpText<"Generate verbose assembly output">;
+def mcode_model : Separate<"-mcode-model">,
+ HelpText<"The code model to use">;
+def mdebug_pass : Separate<"-mdebug-pass">,
+ HelpText<"Enable additional debug output">;
+def mdisable_fp_elim : Flag<"-mdisable-fp-elim">,
+ HelpText<"Disable frame pointer elimination optimization">;
+def mfloat_abi : Separate<"-mfloat-abi">,
+ HelpText<"The float ABI to use">;
+def mlimit_float_precision : Separate<"-mlimit-float-precision">,
+ HelpText<"Limit float precision to the given value">;
+def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
+ HelpText<"Do not put zero initialized data in the BSS">;
+def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">,
+ HelpText<"Omit frame pointer setup for leaf functions.">;
+def msoft_float : Flag<"-msoft-float">,
+ HelpText<"Use software floating point">;
+def mregparm : Separate<"-mregparm">,
+ HelpText<"Limit the number of registers available for integer arguments">;
+def mrelax_all : Flag<"-mrelax-all">,
+ HelpText<"Relax all machine instructions">;
+def mrelocation_model : Separate<"-mrelocation-model">,
+ HelpText<"The relocation model to use">;
+def munwind_tables : Flag<"-munwind-tables">,
+ HelpText<"Generate unwinding tables for all functions">;
+def mconstructor_aliases : Flag<"-mconstructor-aliases">,
+ HelpText<"Emit complete constructors and destructors as aliases when possible">;
+def mms_bitfields : Flag<"-mms-bitfields">,
+ HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
+def O : Joined<"-O">, HelpText<"Optimization level">;
+def Os : Flag<"-Os">, HelpText<"Optimize for size">;
+def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">;
+
+//===----------------------------------------------------------------------===//
+// Dependency Output Options
+//===----------------------------------------------------------------------===//
+
+def dependency_file : Separate<"-dependency-file">,
+ HelpText<"Filename (or -) to write dependency output to">;
+def sys_header_deps : Flag<"-sys-header-deps">,
+ HelpText<"Include system headers in dependency output">;
+def header_include_file : Separate<"-header-include-file">,
+ HelpText<"Filename (or -) to write header include output to">;
+def H : Flag<"-H">,
+ HelpText<"Show header includes and nesting depth">;
+def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;
+def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
+def MP : Flag<"-MP">,
+ HelpText<"Create phony target for each dependency (other than main file)">;
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+def dump_build_information : Separate<"-dump-build-information">,
+ MetaVarName<"<filename>">,
+ HelpText<"output a dump of some build information to a file">;
+def fno_show_column : Flag<"-fno-show-column">,
+ HelpText<"Do not include column number on diagnostics">;
+def fno_show_source_location : Flag<"-fno-show-source-location">,
+ HelpText<"Do not include source location information with diagnostics">;
+def fshow_overloads_EQ : Joined<"-fshow-overloads=">,
+ HelpText<"Which overload candidates to show when overload resolution fails: "
+ "best|all; defaults to all">;
+def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
+ HelpText<"Do not include source line and caret with diagnostics">;
+def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
+ HelpText<"Do not include fixit information in diagnostics">;
+def w : Flag<"-w">, HelpText<"Suppress all warnings">;
+def pedantic : Flag<"-pedantic">;
+def pedantic_errors : Flag<"-pedantic-errors">;
+
+// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
+// driver has stripped off -Wa,foo etc. The driver has also translated -W to
+// -Wextra, so we don't need to worry about it.
+def W : Joined<"-W">;
+
+def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
+ HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">,
+ HelpText<"Print fix-its in machine parseable form">;
+def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
+ HelpText<"Print diagnostic name with mappable diagnostics">;
+def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
+ HelpText<"Print diagnostic category">;
+
+def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">,
+ HelpText<"Set the tab stop distance.">;
+def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">;
+def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of entries to print in a macro instantiation backtrace (0 = no limit).">;
+def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">;
+def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">,
+ HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
+ HelpText<"Use colors in diagnostics">;
+def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
+ HelpText<"Silence ObjC rewriting warnings">;
+def Wwrite_strings : Flag<"-Wwrite-strings">,
+ HelpText<"Remove const qualifier from string literals">;
+def verify : Flag<"-verify">,
+ HelpText<"Verify emitted diagnostics and warnings">;
+
+//===----------------------------------------------------------------------===//
+// Frontend Options
+//===----------------------------------------------------------------------===//
+
+// This isn't normally used, it is just here so we can parse a
+// CompilerInvocation out of a driver-derived argument vector.
+def cc1 : Flag<"-cc1">;
+
+def ast_merge : Separate<"-ast-merge">,
+ MetaVarName<"<ast file>">,
+ HelpText<"Merge the given AST file into the translation unit being compiled.">;
+def code_completion_at : Separate<"-code-completion-at">,
+ MetaVarName<"<file>:<line>:<column>">,
+ HelpText<"Dump code-completion information at a location">;
+def remap_file : Separate<"-remap-file">,
+ MetaVarName<"<from>;<to>">,
+ HelpText<"Replace the contents of the <from> file with the contents of the <to> file">;
+def code_completion_at_EQ : Joined<"-code-completion-at=">,
+ Alias<code_completion_at>;
+def code_completion_macros : Flag<"-code-completion-macros">,
+ HelpText<"Include macros in code-completion results">;
+def code_completion_patterns : Flag<"-code-completion-patterns">,
+ HelpText<"Include code patterns in code-completion results">;
+def no_code_completion_globals : Flag<"-no-code-completion-globals">,
+ HelpText<"Do not include global declarations in code-completion results.">;
+def disable_free : Flag<"-disable-free">,
+ HelpText<"Disable freeing of memory on exit">;
+def help : Flag<"-help">,
+ HelpText<"Print this help text">;
+def _help : Flag<"--help">, Alias<help>;
+def x : Separate<"-x">, HelpText<"Input language type">;
+def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
+def load : Separate<"-load">, MetaVarName<"<dsopath>">,
+ HelpText<"Load the named plugin (dynamic shared object)">;
+def plugin : Separate<"-plugin">, MetaVarName<"<name>">,
+ HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">;
+def plugin_arg : JoinedAndSeparate<"-plugin-arg-">,
+ MetaVarName<"<name> <arg>">,
+ HelpText<"Pass <arg> to plugin <name>">;
+def add_plugin : Separate<"-add-plugin">, MetaVarName<"<name>">,
+ HelpText<"Use the named plugin action in addition to the default action">;
+def resource_dir : Separate<"-resource-dir">,
+ HelpText<"The directory which holds the compiler resource files">;
+def version : Flag<"-version">,
+ HelpText<"Print the compiler version">;
+def _version : Flag<"--version">, Alias<version>;
+
+def Action_Group : OptionGroup<"<action group>">;
+let Group = Action_Group in {
+
+def Eonly : Flag<"-Eonly">,
+ HelpText<"Just run preprocessor, no output (for timings)">;
+def E : Flag<"-E">,
+ HelpText<"Run preprocessor, emit preprocessed file">;
+def dump_raw_tokens : Flag<"-dump-raw-tokens">,
+ HelpText<"Lex file in raw mode and dump raw tokens">;
+def analyze : Flag<"-analyze">,
+ HelpText<"Run static analysis engine">;
+def dump_tokens : Flag<"-dump-tokens">,
+ HelpText<"Run preprocessor, dump internal rep of tokens">;
+def init_only : Flag<"-init-only">,
+ HelpText<"Only execute frontend initialization">;
+def fsyntax_only : Flag<"-fsyntax-only">,
+ HelpText<"Run parser and perform semantic analysis">;
+def fixit : Flag<"-fixit">,
+ HelpText<"Apply fix-it advice to the input source">;
+def fixit_EQ : Joined<"-fixit=">,
+ HelpText<"Apply fix-it advice creating a file with the given suffix">;
+def print_preamble : Flag<"-print-preamble">,
+ HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit"
+ " precompiled headers.">;
+def emit_html : Flag<"-emit-html">,
+ HelpText<"Output input source as HTML">;
+def ast_print : Flag<"-ast-print">,
+ HelpText<"Build ASTs and then pretty-print them">;
+def ast_print_xml : Flag<"-ast-print-xml">,
+ HelpText<"Build ASTs and then print them in XML format">;
+def ast_dump : Flag<"-ast-dump">,
+ HelpText<"Build ASTs and then debug dump them">;
+def ast_dump_xml : Flag<"-ast-dump-xml">,
+ HelpText<"Build ASTs and then debug dump them in a verbose XML format">;
+def ast_view : Flag<"-ast-view">,
+ HelpText<"Build ASTs and view them with GraphViz">;
+def boostcon : Flag<"-boostcon">,
+ HelpText<"BoostCon workshop mode">;
+def print_decl_contexts : Flag<"-print-decl-contexts">,
+ HelpText<"Print DeclContexts and their Decls">;
+def emit_pth : Flag<"-emit-pth">,
+ HelpText<"Generate pre-tokenized header file">;
+def emit_pch : Flag<"-emit-pch">,
+ HelpText<"Generate pre-compiled header file">;
+def S : Flag<"-S">,
+ HelpText<"Emit native assembly code">;
+def emit_llvm : Flag<"-emit-llvm">,
+ HelpText<"Build ASTs then convert to LLVM, emit .ll file">;
+def emit_llvm_bc : Flag<"-emit-llvm-bc">,
+ HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
+def emit_llvm_only : Flag<"-emit-llvm-only">,
+ HelpText<"Build ASTs and convert to LLVM, discarding output">;
+def emit_codegen_only : Flag<"-emit-codegen-only">,
+ HelpText<"Generate machine code, but discard output">;
+def emit_obj : Flag<"-emit-obj">,
+ HelpText<"Emit native object files">;
+def rewrite_test : Flag<"-rewrite-test">,
+ HelpText<"Rewriter playground">;
+def rewrite_objc : Flag<"-rewrite-objc">,
+ HelpText<"Rewrite ObjC into C (code rewriter example)">;
+def rewrite_macros : Flag<"-rewrite-macros">,
+ HelpText<"Expand macros without full preprocessing">;
+
+def create_module : Flag<"-create-module">,
+ HelpText<"Create a module definition file">;
+}
+
+def import_module : Separate<"-import-module">,
+ HelpText<"Import a module definition file">;
+
+def working_directory : JoinedOrSeparate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
+def relocatable_pch : Flag<"-relocatable-pch">,
+ HelpText<"Whether to build a relocatable precompiled header">;
+def chained_pch : Flag<"-chained-pch">,
+ HelpText<"Whether to chain the new precompiled header to the old one.">;
+def print_stats : Flag<"-print-stats">,
+ HelpText<"Print performance metrics and statistics">;
+def ftime_report : Flag<"-ftime-report">,
+ HelpText<"Print the amount of time each phase of compilation takes">;
+def fdump_record_layouts : Flag<"-fdump-record-layouts">,
+ HelpText<"Dump record layout information">;
+def fix_what_you_can : Flag<"-fix-what-you-can">,
+ HelpText<"Apply fix-it advice even in the presence of unfixable errors">;
+
+// Generic forwarding to LLVM options. This should only be used for debugging
+// and experimental features.
+def mllvm : Separate<"-mllvm">,
+ HelpText<"Additional arguments to forward to LLVM's option processing">;
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+def fno_builtin : Flag<"-fno-builtin">,
+ HelpText<"Disable implicit builtin knowledge of functions">;
+def faltivec : Flag<"-faltivec">,
+ HelpText<"Enable AltiVec vector initializer syntax">;
+def fno_access_control : Flag<"-fno-access-control">,
+ HelpText<"Disable C++ access control">;
+def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
+ HelpText<"Don't assume that C++'s global operator new can't alias any pointer">;
+def fgnu_keywords : Flag<"-fgnu-keywords">,
+ HelpText<"Allow GNU-extension keywords regardless of language standard">;
+def fno_gnu_keywords : Flag<"-fno-gnu-keywords">,
+ HelpText<"Disallow GNU-extension keywords regardless of language standard">;
+def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
+ HelpText<"Allow '$' in identifiers">;
+def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
+ HelpText<"Disallow '$' in identifiers">;
+def femit_all_decls : Flag<"-femit-all-decls">,
+ HelpText<"Emit all declarations, even if unused">;
+def fblocks : Flag<"-fblocks">,
+ HelpText<"enable the 'blocks' language feature">;
+def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
+def fexceptions : Flag<"-fexceptions">,
+ HelpText<"Enable support for exception handling">;
+def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
+ HelpText<"Use SjLj style exceptions">;
+def fno_objc_exceptions : Flag<"-fno-objc-exceptions">,
+ HelpText<"Disable Objective-C exceptions">;
+def ffreestanding : Flag<"-ffreestanding">,
+ HelpText<"Assert that the compilation takes place in a freestanding environment">;
+def fformat_extensions : Flag<"-fformat-extensions">,
+ HelpText<"FreeBSD printf format extensions">;
+def fgnu_runtime : Flag<"-fgnu-runtime">,
+ HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
+def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">,
+ HelpText<"Generate weak vtables and RTTI with hidden visibility">;
+def std_EQ : Joined<"-std=">,
+ HelpText<"Language standard to compile for">;
+def fmath_errno : Flag<"-fmath-errno">,
+ HelpText<"Require math functions to indicate errors by setting errno">;
+def fms_extensions : Flag<"-fms-extensions">,
+ HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
+def fmsc_version : Joined<"-fmsc-version=">,
+ HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
+def fborland_extensions : Flag<"-fborland-extensions">,
+ HelpText<"Accept non-standard constructs supported by the Borland compiler">;
+def main_file_name : Separate<"-main-file-name">,
+ HelpText<"Main file name to use for debug info">;
+def fno_elide_constructors : Flag<"-fno-elide-constructors">,
+ HelpText<"Disable C++ copy constructor elision">;
+def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">,
+ HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">;
+def fno_operator_names : Flag<"-fno-operator-names">,
+ HelpText<"Do not treat C++ operator name keywords as synonyms for operators">;
+def fno_signed_char : Flag<"-fno-signed-char">,
+ HelpText<"Char is unsigned">;
+def fno_spell_checking : Flag<"-fno-spell-checking">,
+ HelpText<"Disable spell-checking">;
+def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">,
+ HelpText<"Don't use __cxa_atexit for calling destructors">;
+def fconstant_string_class : Separate<"-fconstant-string-class">,
+ MetaVarName<"<class name>">,
+ HelpText<"Specify the class to use for constant Objective-C string objects.">;
+def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">,
+ HelpText<"Enable creation of CodeFoundation-type constant strings">;
+def fobjc_gc : Flag<"-fobjc-gc">,
+ HelpText<"Enable Objective-C garbage collection">;
+def fobjc_gc_only : Flag<"-fobjc-gc-only">,
+ HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fapple_kext : Flag<"-fapple-kext">,
+ HelpText<"Use Apple's kernel extensions ABI">;
+def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">,
+ HelpText<"Objective-C dispatch method to use">;
+def fobjc_default_synthesize_properties : Flag<"-fobjc-default-synthesize-properties">,
+ HelpText<"enable the default synthesis of Objective-C properties">;
+def print_ivar_layout : Flag<"-print-ivar-layout">,
+ HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
+def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
+ HelpText<"enable objective-c's nonfragile abi">;
+def ftrapv : Flag<"-ftrapv">,
+ HelpText<"Trap on integer overflow">;
+def ftrapv_handler : Separate<"-ftrapv-handler">,
+ MetaVarName<"<function name>">,
+ HelpText<"Specify the function to be called on overflow.">;
+def fwrapv : Flag<"-fwrapv">,
+ HelpText<"Treat signed integer overflow as two's complement">;
+def pic_level : Separate<"-pic-level">,
+ HelpText<"Value for __PIC__">;
+def pthread : Flag<"-pthread">,
+ HelpText<"Support POSIX threads in generated code">;
+def fpascal_strings : Flag<"-fpascal-strings">,
+ HelpText<"Recognize and construct Pascal-style string literals">;
+def fno_rtti : Flag<"-fno-rtti">,
+ HelpText<"Disable generation of rtti information">;
+def fno_validate_pch : Flag<"-fno-validate-pch">,
+ HelpText<"Disable validation of precompiled headers">;
+def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">,
+ HelpText<"Dump declarations that are deserialized from PCH, for testing">;
+def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">,
+ HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">;
+def fshort_wchar : Flag<"-fshort-wchar">,
+ HelpText<"Force wchar_t to be a short unsigned int">;
+def fshort_enums : Flag<"-fshort-enums">,
+ HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
+def static_define : Flag<"-static-define">,
+ HelpText<"Should __STATIC__ be defined">;
+def stack_protector : Separate<"-stack-protector">,
+ HelpText<"Enable stack protectors">;
+def fvisibility : Separate<"-fvisibility">,
+ HelpText<"Default symbol visibility">;
+def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
+ HelpText<"Give inline C++ member functions default visibility by default">;
+def ftemplate_depth : Separate<"-ftemplate-depth">,
+ HelpText<"Maximum depth of recursive template instantiation">;
+def Wlarge_by_value_copy : Separate<"-Wlarge-by-value-copy">,
+ HelpText<"Warn if a function definition returns or accepts an object larger "
+ "in bytes that a given value">;
+def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">,
+ Alias<Wlarge_by_value_copy>;
+def trigraphs : Flag<"-trigraphs">,
+ HelpText<"Process trigraph sequences">;
+def fwritable_strings : Flag<"-fwritable-strings">,
+ HelpText<"Store string literals as writable data">;
+def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">,
+ HelpText<"Ignore bit-field types when aligning structures">;
+
+//===----------------------------------------------------------------------===//
+// Header Search Options
+//===----------------------------------------------------------------------===//
+
+def nostdinc : Flag<"-nostdinc">,
+ HelpText<"Disable standard #include directories">;
+def nostdincxx : Flag<"-nostdinc++">,
+ HelpText<"Disable standard #include directories for the C++ standard library">;
+def nobuiltininc : Flag<"-nobuiltininc">,
+ HelpText<"Disable builtin #include directories">;
+def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to framework include search path">;
+def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to include search path">;
+def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to AFTER include search path">;
+def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to QUOTE include search path">;
+def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to SYSTEM include search path">;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
+ HelpText<"Add directory to SYSTEM include search path, "
+ "absolute paths are relative to -isysroot">;
+def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
+ HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
+def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
+ HelpText<"Set directory to SYSTEM include search path with prefix">;
+def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
+ MetaVarName<"<dir>">,
+ HelpText<"Set directory to include search path with prefix">;
+def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
+ HelpText<"Set the system root directory (usually /)">;
+def cxx_system_include : Separate<"-cxx-system-include">,
+ HelpText<"Add a system #include directory for the C++ standard library">;
+def v : Flag<"-v">, HelpText<"Enable verbose output">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Options
+//===----------------------------------------------------------------------===//
+
+def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">,
+ HelpText<"Predefine the specified macro">;
+def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">,
+ HelpText<"Include file before parsing">;
+def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">,
+ HelpText<"Include macros from file before parsing">;
+def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
+ HelpText<"Include precompiled header file">;
+def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
+ HelpText<"Include file before parsing">;
+def preamble_bytes_EQ : Joined<"-preamble-bytes=">,
+ HelpText<"Assume that the precompiled header is a precompiled preamble "
+ "covering the first N bytes of the main file">;
+def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
+ HelpText<"Use specified token cache file">;
+def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
+ HelpText<"Undefine the specified macro">;
+def undef : Flag<"-undef">, MetaVarName<"<macro>">,
+ HelpText<"undef all system defines">;
+def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">,
+ HelpText<"include a detailed record of preprocessing actions">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessed Output Options
+//===----------------------------------------------------------------------===//
+
+def P : Flag<"-P">,
+ HelpText<"Disable linemarker output in -E mode">;
+def C : Flag<"-C">,
+ HelpText<"Enable comment output in -E mode">;
+def CC : Flag<"-CC">,
+ HelpText<"Enable comment output in -E mode, even from macro expansions">;
+def dM : Flag<"-dM">,
+ HelpText<"Print macro definitions in -E mode instead of normal output">;
+def dD : Flag<"-dD">,
+ HelpText<"Print macro definitions in -E mode in addition to normal output">;
+
+//===----------------------------------------------------------------------===//
+// OpenCL Options
+//===----------------------------------------------------------------------===//
+
+def cl_opt_disable : Flag<"-cl-opt-disable">,
+ HelpText<"OpenCL only. This option disables all optimizations. The default is optimizations are enabled.">;
+def cl_single_precision_constant : Flag<"-cl-single-precision-constant">,
+ HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">;
+def cl_finite_math_only : Flag<"-cl-finite-math-only">,
+ HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">;
+def cl_unsafe_math_optimizations : Flag<"-cl-unsafe-math-optimizations">,
+ HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">;
+def cl_fast_relaxed_math : Flag<"-cl-fast-relaxed-math">,
+ HelpText<"OpenCL only. Sets -cl-finite-math-only and -cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__">;
+def cl_mad_enable : Flag<"-cl-mad-enable">,
+ HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">;
+def cl_std_EQ : Joined<"-cl-std=">,
+ HelpText<"OpenCL language standard to compile for">;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
new file mode 100644
index 0000000..22d6b4e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
@@ -0,0 +1,145 @@
+//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_COMPILATION_H_
+#define CLANG_DRIVER_COMPILATION_H_
+
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+namespace driver {
+ class DerivedArgList;
+ class Driver;
+ class InputArgList;
+ class JobList;
+ class ToolChain;
+
+/// Compilation - A set of tasks to perform for a single driver
+/// invocation.
+class Compilation {
+ /// The driver we were created by.
+ const Driver &TheDriver;
+
+ /// The default tool chain.
+ const ToolChain &DefaultToolChain;
+
+ /// The original (untranslated) input argument list.
+ InputArgList *Args;
+
+ /// The driver translated arguments. Note that toolchains may perform their
+ /// own argument translation.
+ DerivedArgList *TranslatedArgs;
+
+ /// The list of actions.
+ ActionList Actions;
+
+ /// The root list of jobs.
+ JobList Jobs;
+
+ /// Cache of translated arguments for a particular tool chain and bound
+ /// architecture.
+ llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+ DerivedArgList*> TCArgs;
+
+ /// Temporary files which should be removed on exit.
+ ArgStringList TempFiles;
+
+ /// Result files which should be removed on failure.
+ ArgStringList ResultFiles;
+
+public:
+ Compilation(const Driver &D, const ToolChain &DefaultToolChain,
+ InputArgList *Args, DerivedArgList *TranslatedArgs);
+ ~Compilation();
+
+ const Driver &getDriver() const { return TheDriver; }
+
+ const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
+
+ const InputArgList &getInputArgs() const { return *Args; }
+
+ const DerivedArgList &getArgs() const { return *TranslatedArgs; }
+
+ ActionList &getActions() { return Actions; }
+ const ActionList &getActions() const { return Actions; }
+
+ JobList &getJobs() { return Jobs; }
+ const JobList &getJobs() const { return Jobs; }
+
+ void addCommand(Command *C) { Jobs.addJob(C); }
+
+ const ArgStringList &getTempFiles() const { return TempFiles; }
+
+ const ArgStringList &getResultFiles() const { return ResultFiles; }
+
+ /// getArgsForToolChain - Return the derived argument list for the
+ /// tool chain \arg TC (or the default tool chain, if TC is not
+ /// specified).
+ ///
+ /// \param BoundArch - The bound architecture name, or 0.
+ const DerivedArgList &getArgsForToolChain(const ToolChain *TC,
+ const char *BoundArch);
+
+ /// addTempFile - Add a file to remove on exit, and returns its
+ /// argument.
+ const char *addTempFile(const char *Name) {
+ TempFiles.push_back(Name);
+ return Name;
+ }
+
+ /// addResultFile - Add a file to remove on failure, and returns its
+ /// argument.
+ const char *addResultFile(const char *Name) {
+ ResultFiles.push_back(Name);
+ return Name;
+ }
+
+ /// CleanupFileList - Remove the files in the given list.
+ ///
+ /// \param IssueErrors - Report failures as errors.
+ /// \return Whether all files were removed successfully.
+ bool CleanupFileList(const ArgStringList &Files,
+ bool IssueErrors=false) const;
+
+ /// PrintJob - Print one job in -### format.
+ ///
+ /// \param OS - The stream to print on.
+ /// \param J - The job to print.
+ /// \param Terminator - A string to print at the end of the line.
+ /// \param Quote - Should separate arguments be quoted.
+ void PrintJob(llvm::raw_ostream &OS, const Job &J,
+ const char *Terminator, bool Quote) const;
+
+ /// ExecuteCommand - Execute an actual command.
+ ///
+ /// \param FailingCommand - For non-zero results, this will be set to the
+ /// Command which failed, if any.
+ /// \return The result code of the subprocess.
+ int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
+
+ /// ExecuteJob - Execute a single job.
+ ///
+ /// \param FailingCommand - For non-zero results, this will be set to the
+ /// Command which failed.
+ /// \return The accumulated result code of the job.
+ int ExecuteJob(const Job &J, const Command *&FailingCommand) const;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
new file mode 100644
index 0000000..03fa0ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
@@ -0,0 +1,359 @@
+//===--- Driver.h - Clang GCC Compatible Driver -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_DRIVER_H_
+#define CLANG_DRIVER_DRIVER_H_
+
+#include "clang/Basic/Diagnostic.h"
+
+#include "clang/Driver/Phases.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
+ // lands.
+#include <list>
+#include <set>
+#include <string>
+
+namespace llvm {
+ class raw_ostream;
+}
+namespace clang {
+namespace driver {
+ class Action;
+ class ArgList;
+ class Compilation;
+ class DerivedArgList;
+ class HostInfo;
+ class InputArgList;
+ class InputInfo;
+ class JobAction;
+ class OptTable;
+ class ToolChain;
+
+/// Driver - Encapsulate logic for constructing compilation processes
+/// from a set of gcc-driver-like command line arguments.
+class Driver {
+ OptTable *Opts;
+
+ Diagnostic &Diags;
+
+public:
+ // Diag - Forwarding function for diagnostics.
+ DiagnosticBuilder Diag(unsigned DiagID) const {
+ return Diags.Report(DiagID);
+ }
+
+ // FIXME: Privatize once interface is stable.
+public:
+ /// The name the driver was invoked as.
+ std::string Name;
+
+ /// The path the driver executable was in, as invoked from the
+ /// command line.
+ std::string Dir;
+
+ /// The original path to the clang executable.
+ std::string ClangExecutable;
+
+ /// The path to the installed clang directory, if any.
+ std::string InstalledDir;
+
+ /// The path to the compiler resource directory.
+ std::string ResourceDir;
+
+ /// A prefix directory used to emulated a limited subset of GCC's '-Bprefix'
+ /// functionality.
+ /// FIXME: This type of customization should be removed in favor of the
+ /// universal driver when it is ready.
+ typedef llvm::SmallVector<std::string, 4> prefix_list;
+ prefix_list PrefixDirs;
+
+ /// Default host triple.
+ std::string DefaultHostTriple;
+
+ /// Default name for linked images (e.g., "a.out").
+ std::string DefaultImageName;
+
+ /// Driver title to use with help.
+ std::string DriverTitle;
+
+ /// Host information for the platform the driver is running as. This
+ /// will generally be the actual host platform, but not always.
+ const HostInfo *Host;
+
+ /// Information about the host which can be overriden by the user.
+ std::string HostBits, HostMachine, HostSystem, HostRelease;
+
+ /// The file to log CC_PRINT_OPTIONS output to, if enabled.
+ const char *CCPrintOptionsFilename;
+
+ /// The file to log CC_PRINT_HEADERS output to, if enabled.
+ const char *CCPrintHeadersFilename;
+
+ /// Whether the driver should follow g++ like behavior.
+ unsigned CCCIsCXX : 1;
+
+ /// Echo commands while executing (in -v style).
+ unsigned CCCEcho : 1;
+
+ /// Only print tool bindings, don't build any jobs.
+ unsigned CCCPrintBindings : 1;
+
+ /// Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to
+ /// CCPrintOptionsFilename or to stderr.
+ unsigned CCPrintOptions : 1;
+
+ /// Set CC_PRINT_HEADERS mode, which causes the frontend to log header include
+ /// information to CCPrintHeadersFilename or to stderr.
+ unsigned CCPrintHeaders : 1;
+
+private:
+ /// Name to use when calling the generic gcc.
+ std::string CCCGenericGCCName;
+
+ /// Whether to check that input files exist when constructing compilation
+ /// jobs.
+ unsigned CheckInputsExist : 1;
+
+ /// Use the clang compiler where possible.
+ unsigned CCCUseClang : 1;
+
+ /// Use clang for handling C++ and Objective-C++ inputs.
+ unsigned CCCUseClangCXX : 1;
+
+ /// Use clang as a preprocessor (clang's preprocessor will still be
+ /// used where an integrated CPP would).
+ unsigned CCCUseClangCPP : 1;
+
+public:
+ /// Use lazy precompiled headers for PCH support.
+ unsigned CCCUsePCH : 1;
+
+private:
+ /// Only use clang for the given architectures (only used when
+ /// non-empty).
+ std::set<llvm::Triple::ArchType> CCCClangArchs;
+
+ /// Certain options suppress the 'no input files' warning.
+ bool SuppressMissingInputWarning : 1;
+
+ std::list<std::string> TempFiles;
+ std::list<std::string> ResultFiles;
+
+private:
+ /// TranslateInputArgs - Create a new derived argument list from the input
+ /// arguments, after applying the standard argument translations.
+ DerivedArgList *TranslateInputArgs(const InputArgList &Args) const;
+
+public:
+ Driver(llvm::StringRef _ClangExecutable,
+ llvm::StringRef _DefaultHostTriple,
+ llvm::StringRef _DefaultImageName,
+ bool IsProduction, bool CXXIsProduction,
+ Diagnostic &_Diags);
+ ~Driver();
+
+ /// @name Accessors
+ /// @{
+
+ /// Name to use when calling the generic gcc.
+ const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
+
+
+ const OptTable &getOpts() const { return *Opts; }
+
+ const Diagnostic &getDiags() const { return Diags; }
+
+ bool getCheckInputsExist() const { return CheckInputsExist; }
+
+ void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }
+
+ const std::string &getTitle() { return DriverTitle; }
+ void setTitle(std::string Value) { DriverTitle = Value; }
+
+ /// \brief Get the path to the main clang executable.
+ const char *getClangProgramPath() const {
+ return ClangExecutable.c_str();
+ }
+
+ /// \brief Get the path to where the clang executable was installed.
+ const char *getInstalledDir() const {
+ if (!InstalledDir.empty())
+ return InstalledDir.c_str();
+ return Dir.c_str();
+ }
+ void setInstalledDir(llvm::StringRef Value) {
+ InstalledDir = Value;
+ }
+
+ /// @}
+ /// @name Primary Functionality
+ /// @{
+
+ /// BuildCompilation - Construct a compilation object for a command
+ /// line argument vector.
+ ///
+ /// \return A compilation, or 0 if none was built for the given
+ /// argument vector. A null return value does not necessarily
+ /// indicate an error condition, the diagnostics should be queried
+ /// to determine if an error occurred.
+ Compilation *BuildCompilation(int argc, const char **argv);
+
+ /// @name Driver Steps
+ /// @{
+
+ /// ParseArgStrings - Parse the given list of strings into an
+ /// ArgList.
+ InputArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd);
+
+ /// BuildActions - Construct the list of actions to perform for the
+ /// given arguments, which are only done for a single architecture.
+ ///
+ /// \param TC - The default host tool chain.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
+
+ /// BuildUniversalActions - Construct the list of actions to perform
+ /// for the given arguments, which may require a universal build.
+ ///
+ /// \param TC - The default host tool chain.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildUniversalActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
+
+ /// BuildJobs - Bind actions to concrete tools and translate
+ /// arguments to form the list of jobs to run.
+ ///
+ /// \arg C - The compilation that is being built.
+ void BuildJobs(Compilation &C) const;
+
+ /// ExecuteCompilation - Execute the compilation according to the command line
+ /// arguments and return an appropriate exit code.
+ ///
+ /// This routine handles additional processing that must be done in addition
+ /// to just running the subprocesses, for example reporting errors, removing
+ /// temporary files, etc.
+ int ExecuteCompilation(const Compilation &C) const;
+
+ /// @}
+ /// @name Helper Methods
+ /// @{
+
+ /// PrintActions - Print the list of actions.
+ void PrintActions(const Compilation &C) const;
+
+ /// PrintHelp - Print the help text.
+ ///
+ /// \param ShowHidden - Show hidden options.
+ void PrintHelp(bool ShowHidden) const;
+
+ /// PrintOptions - Print the list of arguments.
+ void PrintOptions(const ArgList &Args) const;
+
+ /// PrintVersion - Print the driver version.
+ void PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const;
+
+ /// GetFilePath - Lookup \arg Name in the list of file search paths.
+ ///
+ /// \arg TC - The tool chain for additional information on
+ /// directories to search.
+ //
+ // FIXME: This should be in CompilationInfo.
+ std::string GetFilePath(const char *Name, const ToolChain &TC) const;
+
+ /// GetProgramPath - Lookup \arg Name in the list of program search
+ /// paths.
+ ///
+ /// \arg TC - The provided tool chain for additional information on
+ /// directories to search.
+ ///
+ /// \arg WantFile - False when searching for an executable file, otherwise
+ /// true. Defaults to false.
+ //
+ // FIXME: This should be in CompilationInfo.
+ std::string GetProgramPath(const char *Name, const ToolChain &TC,
+ bool WantFile = false) const;
+
+ /// HandleImmediateArgs - Handle any arguments which should be
+ /// treated before building actions or binding tools.
+ ///
+ /// \return Whether any compilation should be built for this
+ /// invocation.
+ bool HandleImmediateArgs(const Compilation &C);
+
+ /// ConstructAction - Construct the appropriate action to do for
+ /// \arg Phase on the \arg Input, taking in to account arguments
+ /// like -fsyntax-only or --analyze.
+ Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+ Action *Input) const;
+
+
+ /// BuildJobsForAction - Construct the jobs to perform for the
+ /// action \arg A.
+ void BuildJobsForAction(Compilation &C,
+ const Action *A,
+ const ToolChain *TC,
+ const char *BoundArch,
+ bool AtTopLevel,
+ const char *LinkingOutput,
+ InputInfo &Result) const;
+
+ /// GetNamedOutputPath - Return the name to use for the output of
+ /// the action \arg JA. The result is appended to the compilation's
+ /// list of temporary or result files, as appropriate.
+ ///
+ /// \param C - The compilation.
+ /// \param JA - The action of interest.
+ /// \param BaseInput - The original input file that this action was
+ /// triggered by.
+ /// \param AtTopLevel - Whether this is a "top-level" action.
+ const char *GetNamedOutputPath(Compilation &C,
+ const JobAction &JA,
+ const char *BaseInput,
+ bool AtTopLevel) const;
+
+ /// GetTemporaryPath - Return the pathname of a temporary file to
+ /// use as part of compilation; the file will have the given suffix.
+ ///
+ /// GCC goes to extra lengths here to be a bit more robust.
+ std::string GetTemporaryPath(const char *Suffix) const;
+
+ /// GetHostInfo - Construct a new host info object for the given
+ /// host triple.
+ const HostInfo *GetHostInfo(const char *HostTriple) const;
+
+ /// ShouldUseClangCompilar - Should the clang compiler be used to
+ /// handle this action.
+ bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
+ const llvm::Triple &ArchName) const;
+
+ /// @}
+
+ /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
+ /// return the grouped values as integers. Numbers which are not
+ /// provided are set to 0.
+ ///
+ /// \return True if the entire string was parsed (9.2), or all
+ /// groups were parsed (10.3.5extrastuff). HadExtra is true if all
+ /// groups were parsed but extra characters remain at the end.
+ static bool GetReleaseVersion(const char *Str, unsigned &Major,
+ unsigned &Minor, unsigned &Micro,
+ bool &HadExtra);
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h
new file mode 100644
index 0000000..0733c51
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticDriver.h - Diagnostics for libdriver ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVERDIAGNOSTIC_H
+#define LLVM_CLANG_DRIVERDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define DRIVERSTART
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_DRIVER_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h b/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h
new file mode 100644
index 0000000..7285a48
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/HostInfo.h
@@ -0,0 +1,94 @@
+//===--- HostInfo.h - Host specific information -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_HOSTINFO_H_
+#define CLANG_DRIVER_HOSTINFO_H_
+
+#include "llvm/ADT/Triple.h"
+#include <string>
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Driver;
+ class ToolChain;
+
+/// HostInfo - Config information about a particular host which may interact
+/// with driver behavior.
+///
+/// The host information is used for controlling the parts of the driver which
+/// interact with the platform the driver is ostensibly being run from. For
+/// testing purposes, the HostInfo used by the driver may differ from the actual
+/// host.
+class HostInfo {
+protected:
+ const Driver &TheDriver;
+ const llvm::Triple Triple;
+
+ HostInfo(const Driver &D, const llvm::Triple &_Triple);
+
+public:
+ virtual ~HostInfo();
+
+ const Driver &getDriver() const { return TheDriver; }
+
+ const llvm::Triple& getTriple() const { return Triple; }
+ std::string getArchName() const { return Triple.getArchName(); }
+ std::string getPlatformName() const { return Triple.getVendorName(); }
+ std::string getOSName() const { return Triple.getOSName(); }
+
+ /// useDriverDriver - Whether the driver should act as a driver driver for
+ /// this host and support -arch, -Xarch, etc.
+ virtual bool useDriverDriver() const = 0;
+
+ /// CreateToolChain - Construct the toolchain to use for this host (which the
+ /// host retains ownership of).
+ ///
+ /// \param Args - The argument list, which may be used to alter the default
+ /// toolchain, for example in the presence of -m32 or -m64.
+ ///
+ /// \param ArchName - The architecture to return a toolchain for, or 0 if
+ /// unspecified. This will only ever be non-zero for hosts which support a
+ /// driver driver.
+
+ // FIXME: Pin down exactly what the HostInfo is allowed to use Args
+ // for here. Currently this is for -m32 / -m64 defaulting.
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName=0) const = 0;
+};
+
+const HostInfo *createAuroraUXHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createDarwinHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createOpenBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createFreeBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createNetBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createMinixHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createDragonFlyHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createLinuxHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createTCEHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createWindowsHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
+const HostInfo *createMinGWHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
+const HostInfo *createUnknownHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
new file mode 100644
index 0000000..d2767d1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
@@ -0,0 +1,123 @@
+//===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_JOB_H_
+#define CLANG_DRIVER_JOB_H_
+
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+class Command;
+class Tool;
+
+class Job {
+public:
+ enum JobClass {
+ CommandClass,
+ JobListClass
+ };
+
+private:
+ JobClass Kind;
+
+protected:
+ Job(JobClass _Kind) : Kind(_Kind) {}
+public:
+ virtual ~Job();
+
+ JobClass getKind() const { return Kind; }
+
+ /// addCommand - Append a command to the current job, which must be
+ /// either a piped job or a job list.
+ void addCommand(Command *C);
+
+ static bool classof(const Job *) { return true; }
+};
+
+ /// Command - An executable path/name and argument vector to
+ /// execute.
+class Command : public Job {
+ /// Source - The action which caused the creation of this job.
+ const Action &Source;
+
+ /// Tool - The tool which caused the creation of this job.
+ const Tool &Creator;
+
+ /// The executable to run.
+ const char *Executable;
+
+ /// The list of program arguments (not including the implicit first
+ /// argument, which will be the executable).
+ ArgStringList Arguments;
+
+public:
+ Command(const Action &_Source, const Tool &_Creator, const char *_Executable,
+ const ArgStringList &_Arguments);
+
+ /// getSource - Return the Action which caused the creation of this job.
+ const Action &getSource() const { return Source; }
+
+ /// getCreator - Return the Tool which caused the creation of this job.
+ const Tool &getCreator() const { return Creator; }
+
+ const char *getExecutable() const { return Executable; }
+
+ const ArgStringList &getArguments() const { return Arguments; }
+
+ static bool classof(const Job *J) {
+ return J->getKind() == CommandClass;
+ }
+ static bool classof(const Command *) { return true; }
+};
+
+ /// JobList - A sequence of jobs to perform.
+class JobList : public Job {
+public:
+ typedef llvm::SmallVector<Job*, 4> list_type;
+ typedef list_type::size_type size_type;
+ typedef list_type::iterator iterator;
+ typedef list_type::const_iterator const_iterator;
+
+private:
+ list_type Jobs;
+
+public:
+ JobList();
+ virtual ~JobList();
+
+ /// Add a job to the list (taking ownership).
+ void addJob(Job *J) { Jobs.push_back(J); }
+
+ const list_type &getJobs() const { return Jobs; }
+
+ size_type size() const { return Jobs.size(); }
+ iterator begin() { return Jobs.begin(); }
+ const_iterator begin() const { return Jobs.begin(); }
+ iterator end() { return Jobs.end(); }
+ const_iterator end() const { return Jobs.end(); }
+
+ static bool classof(const Job *J) {
+ return J->getKind() == JobListClass;
+ }
+ static bool classof(const JobList *) { return true; }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td
new file mode 100644
index 0000000..04efd00
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/OptParser.td
@@ -0,0 +1,138 @@
+//===--- OptParser.td - Common Option Parsing Interfaces ------------------===//
+//
+// 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 common interfaces used by the option parsing TableGen
+// backend.
+//
+//===----------------------------------------------------------------------===//
+
+// Define the kinds of options.
+
+class OptionKind<string name, int predecence = 0, bit sentinel = 0> {
+ string Name = name;
+ // The kind precedence, kinds with lower precedence are matched first.
+ int Precedence = predecence;
+ // Indicate a sentinel option.
+ bit Sentinel = sentinel;
+}
+
+// An option group.
+def KIND_GROUP : OptionKind<"Group">;
+// The input option kind.
+def KIND_INPUT : OptionKind<"Input", 1, 1>;
+// The unknown option kind.
+def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>;
+// A flag with no values.
+def KIND_FLAG : OptionKind<"Flag">;
+// An option which prefixes its (single) value.
+def KIND_JOINED : OptionKind<"Joined", 1>;
+// An option which is followed by its value.
+def KIND_SEPARATE : OptionKind<"Separate">;
+// An option followed by its values, which are separated by commas.
+def KIND_COMMAJOINED : OptionKind<"CommaJoined">;
+// An option which is which takes multiple (separate) arguments.
+def KIND_MULTIARG : OptionKind<"MultiArg">;
+// An option which is either joined to its (non-empty) value, or followed by its
+// value.
+def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">;
+// An option which is both joined to its (first) value, and followed by its
+// (second) value.
+def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">;
+
+// Define the option flags.
+
+class OptionFlag {}
+
+// DriverOption - The option is a "driver" option, and should not be forwarded
+// to gcc.
+def DriverOption : OptionFlag;
+
+// LinkerInput - The option is a linker input.
+def LinkerInput : OptionFlag;
+
+// NoArgumentUnused - Don't report argument unused warnings for this option; this
+// is useful for options like -static or -dynamic which a user may always end up
+// passing, even if the platform defaults to (or only supports) that option.
+def NoArgumentUnused : OptionFlag;
+
+// RenderAsInput - The option should not render the name when rendered as an
+// input (i.e., the option is rendered as values).
+def RenderAsInput : OptionFlag;
+
+// RenderJoined - The option should be rendered joined, even if separate (only
+// sensible on single value separate options).
+def RenderJoined : OptionFlag;
+
+// RenderSeparate - The option should be rendered separately, even if joined
+// (only sensible on joined options).
+def RenderSeparate : OptionFlag;
+
+// Unsupported - The option is unsupported, and the driver will reject command
+// lines that use it.
+def Unsupported : OptionFlag;
+
+// HelpHidden - The option should not be displayed in --help, even if it has
+// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp
+// arguments to implement hidden help groups.
+def HelpHidden : OptionFlag;
+
+// NoForward - The option should not be implicitly forwarded to other tools.
+def NoForward : OptionFlag;
+
+// Define the option group class.
+
+class OptionGroup<string name> {
+ string EnumName = ?; // Uses the def name if undefined.
+ string Name = name;
+ string HelpText = ?;
+ OptionGroup Group = ?;
+}
+
+// Define the option class.
+
+class Option<string name, OptionKind kind> {
+ string EnumName = ?; // Uses the def name if undefined.
+ string Name = name;
+ OptionKind Kind = kind;
+ // Used by MultiArg option kind.
+ int NumArgs = 0;
+ string HelpText = ?;
+ string MetaVarName = ?;
+ list<OptionFlag> Flags = [];
+ OptionGroup Group = ?;
+ Option Alias = ?;
+}
+
+// Helpers for defining options.
+
+class Flag<string name> : Option<name, KIND_FLAG>;
+class Joined<string name> : Option<name, KIND_JOINED>;
+class Separate<string name> : Option<name, KIND_SEPARATE>;
+class CommaJoined<string name> : Option<name, KIND_COMMAJOINED>;
+class MultiArg<string name, int numargs> : Option<name, KIND_MULTIARG> {
+ int NumArgs = numargs;
+}
+class JoinedOrSeparate<string name> : Option<name, KIND_JOINED_OR_SEPARATE>;
+class JoinedAndSeparate<string name> : Option<name, KIND_JOINED_AND_SEPARATE>;
+
+// Mix-ins for adding optional attributes.
+
+class Alias<Option alias> { Option Alias = alias; }
+class EnumName<string name> { string EnumName = name; }
+class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
+class Group<OptionGroup group> { OptionGroup Group = group; }
+class HelpText<string text> { string HelpText = text; }
+class MetaVarName<string name> { string MetaVarName = name; }
+
+// Predefined options.
+
+// FIXME: Have generator validate that these appear in correct position (and
+// aren't duplicated).
+def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>;
+def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h b/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h
new file mode 100644
index 0000000..bb1cd17
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h
@@ -0,0 +1,39 @@
+//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTSPECIFIER_H
+#define CLANG_DRIVER_OPTSPECIFIER_H
+
+namespace clang {
+namespace driver {
+ class Option;
+
+ /// OptSpecifier - Wrapper class for abstracting references to option IDs.
+ class OptSpecifier {
+ unsigned ID;
+
+ private:
+ explicit OptSpecifier(bool); // DO NOT IMPLEMENT
+
+ public:
+ OptSpecifier() : ID(0) {}
+ /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
+ /*implicit*/ OptSpecifier(const Option *Opt);
+
+ bool isValid() const { return ID != 0; }
+
+ unsigned getID() const { return ID; }
+
+ bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }
+ bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); }
+ };
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h
new file mode 100644
index 0000000..3befe1d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/OptTable.h
@@ -0,0 +1,190 @@
+//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTTABLE_H
+#define CLANG_DRIVER_OPTTABLE_H
+
+#include "clang/Driver/OptSpecifier.h"
+#include <cassert>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+namespace driver {
+namespace options {
+ enum DriverFlag {
+ DriverOption = (1 << 0),
+ HelpHidden = (1 << 1),
+ LinkerInput = (1 << 2),
+ NoArgumentUnused = (1 << 3),
+ NoForward = (1 << 4),
+ RenderAsInput = (1 << 5),
+ RenderJoined = (1 << 6),
+ RenderSeparate = (1 << 7),
+ Unsupported = (1 << 8)
+ };
+}
+
+ class Arg;
+ class ArgList;
+ class InputArgList;
+ class Option;
+
+ /// OptTable - Provide access to the Option info table.
+ ///
+ /// The OptTable class provides a layer of indirection which allows Option
+ /// instance to be created lazily. In the common case, only a few options will
+ /// be needed at runtime; the OptTable class maintains enough information to
+ /// parse command lines without instantiating Options, while letting other
+ /// parts of the driver still use Option instances where convenient.
+ class OptTable {
+ public:
+ /// Info - Entry for a single option instance in the option data table.
+ struct Info {
+ const char *Name;
+ const char *HelpText;
+ const char *MetaVar;
+ unsigned char Kind;
+ unsigned short Flags;
+ unsigned char Param;
+ unsigned short GroupID;
+ unsigned short AliasID;
+ };
+
+ private:
+ /// The static option information table.
+ const Info *OptionInfos;
+ unsigned NumOptionInfos;
+
+ /// The lazily constructed options table, indexed by option::ID - 1.
+ mutable Option **Options;
+
+ /// Prebound input option instance.
+ const Option *TheInputOption;
+
+ /// Prebound unknown option instance.
+ const Option *TheUnknownOption;
+
+ /// The index of the first option which can be parsed (i.e., is not a
+ /// special option like 'input' or 'unknown', and is not an option group).
+ unsigned FirstSearchableIndex;
+
+ private:
+ const Info &getInfo(OptSpecifier Opt) const {
+ unsigned id = Opt.getID();
+ assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
+ return OptionInfos[id - 1];
+ }
+
+ Option *CreateOption(unsigned id) const;
+
+ protected:
+ OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
+ public:
+ ~OptTable();
+
+ /// getNumOptions - Return the total number of option classes.
+ unsigned getNumOptions() const { return NumOptionInfos; }
+
+ /// getOption - Get the given \arg id's Option instance, lazily creating it
+ /// if necessary.
+ ///
+ /// \return The option, or null for the INVALID option id.
+ const Option *getOption(OptSpecifier Opt) const {
+ unsigned id = Opt.getID();
+ if (id == 0)
+ return 0;
+
+ assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
+ Option *&Entry = Options[id - 1];
+ if (!Entry)
+ Entry = CreateOption(id);
+ return Entry;
+ }
+
+ /// getOptionName - Lookup the name of the given option.
+ const char *getOptionName(OptSpecifier id) const {
+ return getInfo(id).Name;
+ }
+
+ /// getOptionKind - Get the kind of the given option.
+ unsigned getOptionKind(OptSpecifier id) const {
+ return getInfo(id).Kind;
+ }
+
+ /// getOptionGroupID - Get the group id for the given option.
+ unsigned getOptionGroupID(OptSpecifier id) const {
+ return getInfo(id).GroupID;
+ }
+
+ /// isOptionHelpHidden - Should the help for the given option be hidden by
+ /// default.
+ bool isOptionHelpHidden(OptSpecifier id) const {
+ return getInfo(id).Flags & options::HelpHidden;
+ }
+
+ /// getOptionHelpText - Get the help text to use to describe this option.
+ const char *getOptionHelpText(OptSpecifier id) const {
+ return getInfo(id).HelpText;
+ }
+
+ /// getOptionMetaVar - Get the meta-variable name to use when describing
+ /// this options values in the help text.
+ const char *getOptionMetaVar(OptSpecifier id) const {
+ return getInfo(id).MetaVar;
+ }
+
+ /// ParseOneArg - Parse a single argument; returning the new argument and
+ /// updating Index.
+ ///
+ /// \param [in] [out] Index - The current parsing position in the argument
+ /// string list; on return this will be the index of the next argument
+ /// string to parse.
+ ///
+ /// \return - The parsed argument, or 0 if the argument is missing values
+ /// (in which case Index still points at the conceptual next argument string
+ /// to parse).
+ Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const;
+
+ /// ParseArgs - Parse an list of arguments into an InputArgList.
+ ///
+ /// The resulting InputArgList will reference the strings in [ArgBegin,
+ /// ArgEnd), and their lifetime should extend past that of the returned
+ /// InputArgList.
+ ///
+ /// The only error that can occur in this routine is if an argument is
+ /// missing values; in this case \arg MissingArgCount will be non-zero.
+ ///
+ /// \param ArgBegin - The beginning of the argument vector.
+ /// \param ArgEnd - The end of the argument vector.
+ /// \param MissingArgIndex - On error, the index of the option which could
+ /// not be parsed.
+ /// \param MissingArgCount - On error, the number of missing options.
+ /// \return - An InputArgList; on error this will contain all the options
+ /// which could be parsed.
+ InputArgList *ParseArgs(const char* const *ArgBegin,
+ const char* const *ArgEnd,
+ unsigned &MissingArgIndex,
+ unsigned &MissingArgCount) const;
+
+ /// PrintHelp - Render the help text for an option table.
+ ///
+ /// \param OS - The stream to write the help text to.
+ /// \param Name - The name to use in the usage line.
+ /// \param Title - The title to use in the usage line.
+ /// \param ShowHidden - Whether help-hidden arguments should be shown.
+ void PrintHelp(llvm::raw_ostream &OS, const char *Name,
+ const char *Title, bool ShowHidden = false) const;
+ };
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Option.h b/contrib/llvm/tools/clang/include/clang/Driver/Option.h
new file mode 100644
index 0000000..9625465
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Option.h
@@ -0,0 +1,322 @@
+//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTION_H_
+#define CLANG_DRIVER_OPTION_H_
+
+#include "clang/Driver/OptSpecifier.h"
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+ class Arg;
+ class ArgList;
+ class OptionGroup;
+
+ /// Option - Abstract representation for a single form of driver
+ /// argument.
+ ///
+ /// An Option class represents a form of option that the driver
+ /// takes, for example how many arguments the option has and how
+ /// they can be provided. Individual option instances store
+ /// additional information about what group the option is a member
+ /// of (if any), if the option is an alias, and a number of
+ /// flags. At runtime the driver parses the command line into
+ /// concrete Arg instances, each of which corresponds to a
+ /// particular Option instance.
+ class Option {
+ public:
+ enum OptionClass {
+ GroupClass = 0,
+ InputClass,
+ UnknownClass,
+ FlagClass,
+ JoinedClass,
+ SeparateClass,
+ CommaJoinedClass,
+ MultiArgClass,
+ JoinedOrSeparateClass,
+ JoinedAndSeparateClass
+ };
+
+ enum RenderStyleKind {
+ RenderCommaJoinedStyle,
+ RenderJoinedStyle,
+ RenderSeparateStyle,
+ RenderValuesStyle
+ };
+
+ private:
+ OptionClass Kind;
+
+ /// The option ID.
+ OptSpecifier ID;
+
+ /// The option name.
+ const char *Name;
+
+ /// Group this option is a member of, if any.
+ const OptionGroup *Group;
+
+ /// Option that this is an alias for, if any.
+ const Option *Alias;
+
+ /// Unsupported options will be rejected.
+ bool Unsupported : 1;
+
+ /// Treat this option like a linker input?
+ bool LinkerInput : 1;
+
+ /// When rendering as an input, don't render the option.
+
+ // FIXME: We should ditch the render/renderAsInput distinction.
+ bool NoOptAsInput : 1;
+
+ /// The style to using when rendering arguments parsed by this option.
+ unsigned RenderStyle : 2;
+
+ /// This option is only consumed by the driver.
+ bool DriverOption : 1;
+
+ /// This option should not report argument unused errors.
+ bool NoArgumentUnused : 1;
+
+ /// This option should not be implicitly forwarded.
+ bool NoForward : 1;
+
+ protected:
+ Option(OptionClass Kind, OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+ public:
+ virtual ~Option();
+
+ unsigned getID() const { return ID.getID(); }
+ OptionClass getKind() const { return Kind; }
+ const char *getName() const { return Name; }
+ const OptionGroup *getGroup() const { return Group; }
+ const Option *getAlias() const { return Alias; }
+
+ bool isUnsupported() const { return Unsupported; }
+ void setUnsupported(bool Value) { Unsupported = Value; }
+
+ bool isLinkerInput() const { return LinkerInput; }
+ void setLinkerInput(bool Value) { LinkerInput = Value; }
+
+ bool hasNoOptAsInput() const { return NoOptAsInput; }
+ void setNoOptAsInput(bool Value) { NoOptAsInput = Value; }
+
+ RenderStyleKind getRenderStyle() const {
+ return RenderStyleKind(RenderStyle);
+ }
+ void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; }
+
+ bool isDriverOption() const { return DriverOption; }
+ void setDriverOption(bool Value) { DriverOption = Value; }
+
+ bool hasNoArgumentUnused() const { return NoArgumentUnused; }
+ void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
+
+ bool hasNoForward() const { return NoForward; }
+ void setNoForward(bool Value) { NoForward = Value; }
+
+ bool hasForwardToGCC() const {
+ return !NoForward && !DriverOption && !LinkerInput;
+ }
+
+ /// getUnaliasedOption - Return the final option this option
+ /// aliases (itself, if the option has no alias).
+ const Option *getUnaliasedOption() const {
+ if (Alias) return Alias->getUnaliasedOption();
+ return this;
+ }
+
+ /// getRenderName - Return the name to use when rendering this
+ /// option.
+ const char *getRenderName() const {
+ return getUnaliasedOption()->getName();
+ }
+
+ /// matches - Predicate for whether this option is part of the
+ /// given option (which may be a group).
+ ///
+ /// Note that matches against options which are an alias should never be
+ /// done -- aliases do not participate in matching and so such a query will
+ /// always be false.
+ bool matches(OptSpecifier ID) const;
+
+ /// accept - Potentially accept the current argument, returning a
+ /// new Arg instance, or 0 if the option does not accept this
+ /// argument (or the argument is missing values).
+ ///
+ /// If the option accepts the current argument, accept() sets
+ /// Index to the position where argument parsing should resume
+ /// (even if the argument is missing values).
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0;
+
+ void dump() const;
+
+ static bool classof(const Option *) { return true; }
+ };
+
+ /// OptionGroup - A set of options which are can be handled uniformly
+ /// by the driver.
+ class OptionGroup : public Option {
+ public:
+ OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::GroupClass;
+ }
+ static bool classof(const OptionGroup *) { return true; }
+ };
+
+ // Dummy option classes.
+
+ /// InputOption - Dummy option class for representing driver inputs.
+ class InputOption : public Option {
+ public:
+ InputOption(OptSpecifier ID);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::InputClass;
+ }
+ static bool classof(const InputOption *) { return true; }
+ };
+
+ /// UnknownOption - Dummy option class for represent unknown arguments.
+ class UnknownOption : public Option {
+ public:
+ UnknownOption(OptSpecifier ID);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::UnknownClass;
+ }
+ static bool classof(const UnknownOption *) { return true; }
+ };
+
+ // Normal options.
+
+ class FlagOption : public Option {
+ public:
+ FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::FlagClass;
+ }
+ static bool classof(const FlagOption *) { return true; }
+ };
+
+ class JoinedOption : public Option {
+ public:
+ JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedClass;
+ }
+ static bool classof(const JoinedOption *) { return true; }
+ };
+
+ class SeparateOption : public Option {
+ public:
+ SeparateOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::SeparateClass;
+ }
+ static bool classof(const SeparateOption *) { return true; }
+ };
+
+ class CommaJoinedOption : public Option {
+ public:
+ CommaJoinedOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::CommaJoinedClass;
+ }
+ static bool classof(const CommaJoinedOption *) { return true; }
+ };
+
+ // FIXME: Fold MultiArgOption into SeparateOption?
+
+ /// MultiArgOption - An option which takes multiple arguments (these
+ /// are always separate arguments).
+ class MultiArgOption : public Option {
+ unsigned NumArgs;
+
+ public:
+ MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias, unsigned NumArgs);
+
+ unsigned getNumArgs() const { return NumArgs; }
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::MultiArgClass;
+ }
+ static bool classof(const MultiArgOption *) { return true; }
+ };
+
+ /// JoinedOrSeparateOption - An option which either literally
+ /// prefixes its (non-empty) value, or is follwed by a value.
+ class JoinedOrSeparateOption : public Option {
+ public:
+ JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedOrSeparateClass;
+ }
+ static bool classof(const JoinedOrSeparateOption *) { return true; }
+ };
+
+ /// JoinedAndSeparateOption - An option which literally prefixes its
+ /// value and is followed by another value.
+ class JoinedAndSeparateOption : public Option {
+ public:
+ JoinedAndSeparateOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedAndSeparateClass;
+ }
+ static bool classof(const JoinedAndSeparateOption *) { return true; }
+ };
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.h b/contrib/llvm/tools/clang/include/clang/Driver/Options.h
new file mode 100644
index 0000000..ac312cd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.h
@@ -0,0 +1,32 @@
+//===--- Options.h - Option info & table ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTIONS_H
+#define CLANG_DRIVER_OPTIONS_H
+
+namespace clang {
+namespace driver {
+ class OptTable;
+
+namespace options {
+ enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/Options.inc"
+ LastOption
+#undef OPTION
+ };
+}
+
+ OptTable *createDriverOptTable();
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
new file mode 100644
index 0000000..1a8a150
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -0,0 +1,797 @@
+//===--- DriverOptions.td - Options for clang -----------------------------===//
+//
+// 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 options accepted by clang.
+//
+//===----------------------------------------------------------------------===//
+
+// Include the common option parsing interfaces.
+include "OptParser.td"
+
+/////////
+// Groups
+
+// Meta-group which defines
+def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
+
+def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
+def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
+def T_Group : OptionGroup<"<T group>">;
+def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
+def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
+def X_Group : OptionGroup<"<X group>">;
+def a_Group : OptionGroup<"<a group>">;
+def d_Group : OptionGroup<"<d group>">;
+def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
+def g_Group : OptionGroup<"<g group>">;
+def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>;
+def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
+def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
+def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>;
+def u_Group : OptionGroup<"<u group>">;
+
+def pedantic_Group : OptionGroup<"<pedantic group>">,
+ Group<CompileOnly_Group>;
+def reserved_lib_Group : OptionGroup<"<reserved libs group>">;
+
+// Temporary groups for clang options which we know we don't support,
+// but don't want to verbosely warn the user about.
+def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">,
+ Group<f_Group>;
+def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
+ Group<m_Group>;
+
+/////////
+// Options
+
+// The internal option ID must be a valid C++ identifier and results in a
+// clang::driver::options::OPT_XX enum constant for XX.
+//
+// We want to unambiguously be able to refer to options from the driver source
+// code, for this reason the option name is mangled into an ID. This mangling
+// isn't guaranteed to have an inverse, but for practical purposes it does.
+//
+// The mangling scheme is to ignore the leading '-', and perform the following
+// substitutions:
+// _ => __
+// - => _
+// # => _HASH
+// , => _COMMA
+// = => _EQ
+// C++ => CXX
+// . => _
+
+// Developer Driver Options
+
+def ccc_Group : OptionGroup<"<clang internal options>">;
+def ccc_driver_Group : OptionGroup<"<clang driver internal options>">,
+ Group<ccc_Group>, HelpText<"DRIVER OPTIONS">;
+def ccc_debug_Group : OptionGroup<"<clang debug/development internal options>">,
+ Group<ccc_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
+
+class CCCDriverOpt : Group<ccc_driver_Group>, Flags<[DriverOption, HelpHidden]>;
+def ccc_cxx : Flag<"-ccc-cxx">, CCCDriverOpt,
+ HelpText<"Act as a C++ driver">;
+def ccc_echo : Flag<"-ccc-echo">, CCCDriverOpt,
+ HelpText<"Echo commands before running them">;
+def ccc_gcc_name : Separate<"-ccc-gcc-name">, CCCDriverOpt,
+ HelpText<"Name for native GCC compiler">,
+ MetaVarName<"<gcc-path>">;
+def ccc_clang_cxx : Flag<"-ccc-clang-cxx">, CCCDriverOpt,
+ HelpText<"Enable the clang compiler for C++">;
+def ccc_no_clang_cxx : Flag<"-ccc-no-clang-cxx">, CCCDriverOpt,
+ HelpText<"Disable the clang compiler for C++">;
+def ccc_no_clang : Flag<"-ccc-no-clang">, CCCDriverOpt,
+ HelpText<"Disable the clang compiler">;
+def ccc_no_clang_cpp : Flag<"-ccc-no-clang-cpp">, CCCDriverOpt,
+ HelpText<"Disable the clang preprocessor">;
+def ccc_clang_archs : Separate<"-ccc-clang-archs">, CCCDriverOpt,
+ HelpText<"Comma separate list of architectures to use the clang compiler for">,
+ MetaVarName<"<arch-list>">;
+def ccc_pch_is_pch : Flag<"-ccc-pch-is-pch">, CCCDriverOpt,
+ HelpText<"Use lazy PCH for precompiled headers">;
+def ccc_pch_is_pth : Flag<"-ccc-pch-is-pth">, CCCDriverOpt,
+ HelpText<"Use pretokenized headers for precompiled headers">;
+
+class CCCDebugOpt : Group<ccc_debug_Group>, Flags<[DriverOption, HelpHidden]>;
+def ccc_host_triple : Separate<"-ccc-host-triple">, CCCDebugOpt,
+ HelpText<"Simulate running on the given target">;
+def ccc_install_dir : Separate<"-ccc-install-dir">, CCCDebugOpt,
+ HelpText<"Simulate installation in the given directory">;
+def ccc_print_options : Flag<"-ccc-print-options">, CCCDebugOpt,
+ HelpText<"Dump parsed command line arguments">;
+def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt,
+ HelpText<"Dump list of actions to perform">;
+def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt,
+ HelpText<"Show bindings of tools to actions">;
+
+// Make sure all other -ccc- options are rejected.
+def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
+
+// Standard Options
+
+def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>,
+ HelpText<"Print the commands to run for this compilation">;
+def A : JoinedOrSeparate<"-A">;
+def B : JoinedOrSeparate<"-B">;
+def CC : Flag<"-CC">;
+def C : Flag<"-C">;
+def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>;
+def E : Flag<"-E">, Flags<[DriverOption]>,
+ HelpText<"Only run the preprocessor">;
+def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined]>;
+def H : Flag<"-H">;
+def I_ : Flag<"-I-">, Group<I_Group>;
+def I : JoinedOrSeparate<"-I">, Group<I_Group>;
+def L : JoinedOrSeparate<"-L">, Flags<[RenderJoined]>;
+def MD : Flag<"-MD">, Group<M_Group>;
+def MF : JoinedOrSeparate<"-MF">, Group<M_Group>;
+def MG : Flag<"-MG">, Group<M_Group>;
+def MMD : Flag<"-MMD">, Group<M_Group>;
+def MM : Flag<"-MM">, Group<M_Group>;
+def MP : Flag<"-MP">, Group<M_Group>;
+def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>;
+def MT : JoinedOrSeparate<"-MT">, Group<M_Group>;
+def Mach : Flag<"-Mach">;
+def M : Flag<"-M">, Group<M_Group>;
+def O0 : Joined<"-O0">, Group<O_Group>;
+def O4 : Joined<"-O4">, Group<O_Group>;
+def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>,
+ HelpText<"Treat source input files as Objective-C++ inputs">;
+def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>,
+ HelpText<"Treat source input files as Objective-C inputs">;
+def O : Joined<"-O">, Group<O_Group>;
+def P : Flag<"-P">;
+def Qn : Flag<"-Qn">;
+def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>,
+ HelpText<"Don't emit warning for unused driver arguments">;
+def Q : Flag<"-Q">;
+def R : Flag<"-R">;
+def S : Flag<"-S">, Flags<[DriverOption]>,
+ HelpText<"Only run preprocess and compilation steps">;
+def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>;
+def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>;
+def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>;
+def T : JoinedOrSeparate<"-T">, Group<T_Group>;
+def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>;
+def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>;
+def Wa_COMMA : CommaJoined<"-Wa,">,
+ HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
+ MetaVarName<"<arg>">;
+def Wall : Flag<"-Wall">, Group<W_Group>;
+def Wextra : Flag<"-Wextra">, Group<W_Group>;
+def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>,
+ HelpText<"Pass the comma separated arguments in <arg> to the linker">,
+ MetaVarName<"<arg>">;
+def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>;
+def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>;
+def Wp_COMMA : CommaJoined<"-Wp,">,
+ HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
+ MetaVarName<"<arg>">;
+def W_Joined : Joined<"-W">, Group<W_Group>;
+def Xanalyzer : Separate<"-Xanalyzer">,
+ HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">;
+def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>;
+def Xassembler : Separate<"-Xassembler">,
+ HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">;
+def Xclang : Separate<"-Xclang">,
+ HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">,
+ Flags<[NoForward]>;
+def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
+ HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">;
+def Xpreprocessor : Separate<"-Xpreprocessor">,
+ HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">;
+def X_Flag : Flag<"-X">;
+def X_Joined : Joined<"-X">;
+def Z_Flag : Flag<"-Z">;
+def Z_Joined : Joined<"-Z">;
+def all__load : Flag<"-all_load">;
+def allowable__client : Separate<"-allowable_client">;
+def ansi : Flag<"-ansi">, Group<a_Group>;
+def arch__errors__fatal : Flag<"-arch_errors_fatal">;
+def arch : Separate<"-arch">, Flags<[DriverOption]>;
+def arch__only : Separate<"-arch_only">;
+def a : Joined<"-a">, Group<a_Group>;
+def bind__at__load : Flag<"-bind_at_load">;
+def bundle__loader : Separate<"-bundle_loader">;
+def bundle : Flag<"-bundle">;
+def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>;
+def client__name : JoinedOrSeparate<"-client_name">;
+def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>;
+def compatibility__version : JoinedOrSeparate<"-compatibility_version">;
+def coverage : Flag<"-coverage">;
+def cpp_precomp : Flag<"-cpp-precomp">;
+def current__version : JoinedOrSeparate<"-current_version">;
+def c : Flag<"-c">, Flags<[DriverOption]>,
+ HelpText<"Only run preprocess, compile, and assemble steps">;
+def dA : Flag<"-dA">, Group<d_Group>;
+def dD : Flag<"-dD">, Group<d_Group>;
+def dM : Flag<"-dM">, Group<d_Group>;
+def dead__strip : Flag<"-dead_strip">;
+def dependency_file : Separate<"-dependency-file">;
+def dumpmachine : Flag<"-dumpmachine">;
+def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>;
+def dumpversion : Flag<"-dumpversion">;
+def dylib__file : Separate<"-dylib_file">;
+def dylinker__install__name : JoinedOrSeparate<"-dylinker_install_name">;
+def dylinker : Flag<"-dylinker">;
+def dynamiclib : Flag<"-dynamiclib">;
+def dynamic : Flag<"-dynamic">, Flags<[NoArgumentUnused]>;
+def d_Flag : Flag<"-d">, Group<d_Group>;
+def d_Joined : Joined<"-d">, Group<d_Group>;
+def emit_ast : Flag<"-emit-ast">,
+ HelpText<"Emit Clang AST files for source inputs">;
+def emit_llvm : Flag<"-emit-llvm">,
+ HelpText<"Use the LLVM representation for assembler and object files">;
+def exported__symbols__list : Separate<"-exported_symbols_list">;
+def e : JoinedOrSeparate<"-e">;
+def fPIC : Flag<"-fPIC">, Group<f_Group>;
+def fPIE : Flag<"-fPIE">, Group<f_Group>;
+def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>;
+def faccess_control : Flag<"-faccess-control">, Group<f_Group>;
+def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>;
+def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
+def fasm : Flag<"-fasm">, Group<f_Group>;
+
+def fasm_blocks : Flag<"-fasm-blocks">, Group<f_Group>;
+def fno_asm_blocks : Flag<"-fno-asm-blocks">, Group<f_Group>;
+
+def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>;
+def fastcp : Flag<"-fastcp">, Group<f_Group>;
+def fastf : Flag<"-fastf">, Group<f_Group>;
+def fast : Flag<"-fast">, Group<f_Group>;
+def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
+def fblocks : Flag<"-fblocks">, Group<f_Group>;
+def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
+def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>;
+def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
+def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>;
+def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>;
+def fcaret_diagnostics : Flag<"-fcaret-diagnostics">, Group<f_Group>;
+def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
+ Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">;
+def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>;
+def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>;
+def fcommon : Flag<"-fcommon">, Group<f_Group>;
+def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>;
+def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>;
+def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Group>;
+def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>;
+def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>;
+def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
+def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
+def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>;
+def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
+def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>;
+def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
+def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>;
+def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>;
+def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>;
+def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>;
+def fexceptions : Flag<"-fexceptions">, Group<f_Group>;
+def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>;
+def fhosted : Flag<"-fhosted">, Group<f_Group>;
+def ffast_math : Flag<"-ffast-math">, Group<clang_ignored_f_Group>;
+def ffinite_math_only : Flag<"-ffinite-math-only">, Group<clang_ignored_f_Group>;
+
+def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>;
+def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>;
+
+def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>;
+def fformat_extensions: Flag<"-fformat-extensions">;
+def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>;
+def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>;
+def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
+def filelist : Separate<"-filelist">, Flags<[LinkerInput]>;
+def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Group<f_Group>;
+def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>;
+def finline : Flag<"-finline">, Group<clang_ignored_f_Group>;
+def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>;
+def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>;
+def flat__namespace : Flag<"-flat_namespace">;
+def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>;
+def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>,
+ HelpText<"Limit debug information produced to reduce size of debug binary">;
+def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>;
+def flto : Flag<"-flto">, Group<f_Group>;
+def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">,
+ Group<f_Group>;
+def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>;
+def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>;
+def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>;
+def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>;
+def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>;
+def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>;
+def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
+def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
+def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>;
+def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>;
+def fno_asm : Flag<"-fno-asm">, Group<f_Group>;
+def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
+def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
+def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
+def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>;
+def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
+def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
+def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>;
+def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>;
+def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>;
+def fno_common : Flag<"-fno-common">, Group<f_Group>;
+def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>;
+def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>;
+def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>;
+def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>;
+def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>;
+def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>;
+def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>;
+def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<clang_ignored_f_Group>;
+def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>;
+def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>;
+def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>;
+def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>;
+def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>;
+def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>;
+def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>;
+def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>;
+def fno_objc_default_synthesize_properties
+ : Flag<"-fno-objc-default-synthesize-properties">, Group<f_Group>;
+def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>;
+def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>;
+def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>;
+def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>;
+def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>;
+def fno_short_enums : Flag<"-fno-short-enums">, Group<f_Group>;
+def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>;
+def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>;
+def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>;
+def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>;
+def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>;
+def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>;
+def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>;
+def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>;
+def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>;
+def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>;
+def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>;
+def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>;
+def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>;
+def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>;
+def fobjc_default_synthesize_properties :
+ Flag<"-fobjc-default-synthesize-properties">, Group<f_Group>;
+def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>;
+
+def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>;
+def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>;
+def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>;
+def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>;
+
+// Objective-C ABI options.
+def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
+def fobjc_nonfragile_abi_version_EQ : Joined<"-fobjc-nonfragile-abi-version=">, Group<f_Group>;
+def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>;
+def fno_objc_nonfragile_abi : Flag<"-fno-objc-nonfragile-abi">, Group<f_Group>;
+
+def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group<f_Group>;
+def fobjc : Flag<"-fobjc">, Group<f_Group>;
+def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>;
+def fopenmp : Flag<"-fopenmp">, Group<f_Group>;
+def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">;
+def force__flat__namespace : Flag<"-force_flat_namespace">;
+def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>;
+def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>;
+def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>;
+def fpic : Flag<"-fpic">, Group<f_Group>;
+def fpie : Flag<"-fpie">, Group<f_Group>;
+def fno_pie : Flag<"-fno-pie">, Group<f_Group>;
+def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>;
+def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>;
+def framework : Separate<"-framework">, Flags<[LinkerInput]>;
+def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>;
+def frtti : Flag<"-frtti">, Group<f_Group>;
+def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
+def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>;
+def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
+def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
+def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>;
+def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>;
+def fspell_checking : Flag<"-fspell-checking">, Group<f_Group>;
+def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
+def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>;
+def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>;
+def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>;
+def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>;
+def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
+def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>;
+def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>;
+def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
+def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
+ Group<f_Group>;
+def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">;
+def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">;
+def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>;
+def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
+def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
+def ftrapv : Flag<"-ftrapv">, Group<f_Group>;
+def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>;
+def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>;
+def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>;
+def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>;
+def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>;
+def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>;
+def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>;
+def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>;
+def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>;
+def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>;
+def fwrapv : Flag<"-fwrapv">, Group<f_Group>;
+def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>;
+def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>;
+def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>;
+def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>;
+def f : Joined<"-f">, Group<f_Group>;
+def g0 : Joined<"-g0">, Group<g_Group>;
+def g3 : Joined<"-g3">, Group<g_Group>;
+def gfull : Joined<"-gfull">, Group<g_Group>;
+def gstabs : Joined<"-gstabs">, Group<g_Group>;
+def gused : Joined<"-gused">, Group<g_Group>;
+def g_Flag : Flag<"-g">, Group<g_Group>;
+def g_Joined : Joined<"-g">, Group<g_Group>;
+def headerpad__max__install__names : Joined<"-headerpad_max_install_names">;
+def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>;
+def iframework : JoinedOrSeparate<"-iframework">, Group<clang_i_Group>;
+def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>;
+def image__base : Separate<"-image_base">;
+def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">;
+def include_pch : Separate<"-include-pch">, Group<clang_i_Group>;
+def init : Separate<"-init">;
+def install__name : Separate<"-install_name">;
+def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>;
+def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>;
+def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>;
+def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
+def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
+def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
+def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>;
+def i : Joined<"-i">, Group<i_Group>;
+def keep__private__externs : Flag<"-keep_private_externs">;
+def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>;
+def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>;
+def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>;
+def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>;
+def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>;
+def mabi_EQ : Joined<"-mabi=">, Group<m_Group>, Flags<[DriverOption]>;
+def march_EQ : Joined<"-march=">, Group<m_Group>, Flags<[DriverOption]>;
+def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>, Flags<[DriverOption]>;
+def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>;
+def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>;
+def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>;
+def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>;
+def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>;
+def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>;
+def mhard_float : Flag<"-mhard-float">, Group<m_Group>;
+def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>;
+def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>;
+def mkernel : Flag<"-mkernel">, Group<m_Group>;
+def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
+def mllvm : Separate<"-mllvm">;
+def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
+def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>;
+def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
+def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>;
+def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>;
+def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>;
+def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>;
+def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>;
+def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>;
+def mno_relax_all : Flag<"-mno-relax-all">, Group<m_Group>;
+def mno_soft_float : Flag<"-mno-soft-float">, Group<m_Group>;
+def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>;
+def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>;
+def mno_sse4a : Flag<"-mno-sse4a">, Group<m_x86_Features_Group>;
+def mno_sse4 : Flag<"-mno-sse4">, Group<m_x86_Features_Group>;
+def mno_sse4_1 : Flag<"-mno-sse4.1">, Group<m_x86_Features_Group>;
+def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>;
+def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>;
+def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>;
+def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>;
+def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>;
+
+def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>;
+def marm : Flag<"-marm">, Alias<mno_thumb>;
+
+def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>;
+def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_Group>;
+def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>;
+def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>;
+def mred_zone : Flag<"-mred-zone">, Group<m_Group>;
+def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>;
+def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>;
+def msoft_float : Flag<"-msoft-float">, Group<m_Group>;
+def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>;
+def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>;
+def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>;
+def msse4 : Flag<"-msse4">, Group<m_x86_Features_Group>;
+def msse4_1 : Flag<"-msse4.1">, Group<m_x86_Features_Group>;
+def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>;
+def msse : Flag<"-msse">, Group<m_x86_Features_Group>;
+def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>;
+def maes : Flag<"-maes">, Group<m_x86_Features_Group>;
+def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>;
+def mthumb : Flag<"-mthumb">, Group<m_Group>;
+def mtune_EQ : Joined<"-mtune=">, Group<m_Group>;
+def multi__module : Flag<"-multi_module">;
+def multiply__defined__unused : Separate<"-multiply_defined_unused">;
+def multiply__defined : Separate<"-multiply_defined">;
+def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>;
+def m_Separate : Separate<"-m">, Group<m_Group>;
+def m_Joined : Joined<"-m">, Group<m_Group>;
+def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>,
+ HelpText<"Use relative instead of canonical paths">;
+def no_cpp_precomp : Flag<"-no-cpp-precomp">;
+def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>;
+def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>;
+def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">;
+def nobuiltininc : Flag<"-nobuiltininc">;
+def nodefaultlibs : Flag<"-nodefaultlibs">;
+def nofixprebinding : Flag<"-nofixprebinding">;
+def nolibc : Flag<"-nolibc">;
+def nomultidefs : Flag<"-nomultidefs">;
+def noprebind : Flag<"-noprebind">;
+def noseglinkedit : Flag<"-noseglinkedit">;
+def nostartfiles : Flag<"-nostartfiles">;
+def nostdinc : Flag<"-nostdinc">;
+def nostdincxx : Flag<"-nostdinc++">;
+def nostdlib : Flag<"-nostdlib">;
+def object : Flag<"-object">;
+def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>,
+ HelpText<"Write output to <file>">, MetaVarName<"<file>">;
+def pagezero__size : JoinedOrSeparate<"-pagezero_size">;
+def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>;
+def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>;
+def pedantic : Flag<"-pedantic">, Group<pedantic_Group>;
+def pg : Flag<"-pg">;
+def pipe : Flag<"-pipe">,
+ HelpText<"Use pipes between commands, when possible">;
+def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">;
+def prebind : Flag<"-prebind">;
+def preload : Flag<"-preload">;
+def print_file_name_EQ : Joined<"-print-file-name=">,
+ HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">;
+def print_ivar_layout : Flag<"-print-ivar-layout">;
+def print_libgcc_file_name : Flag<"-print-libgcc-file-name">,
+ HelpText<"Print the library path for \"libgcc.a\"">;
+def print_multi_directory : Flag<"-print-multi-directory">;
+def print_multi_lib : Flag<"-print-multi-lib">;
+def print_multi_os_directory : Flag<"-print-multi-os-directory">;
+def print_prog_name_EQ : Joined<"-print-prog-name=">,
+ HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">;
+def print_search_dirs : Flag<"-print-search-dirs">,
+ HelpText<"Print the paths used for finding libraries and programs">;
+def private__bundle : Flag<"-private_bundle">;
+def pthreads : Flag<"-pthreads">;
+def pthread : Flag<"-pthread">;
+def p : Flag<"-p">;
+def pie : Flag<"-pie">;
+def read__only__relocs : Separate<"-read_only_relocs">;
+def remap : Flag<"-remap">;
+def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption]>,
+ HelpText<"Rewrite Objective-C source to C++">;
+def rdynamic : Flag<"-rdynamic">;
+def rpath : Separate<"-rpath">, Flags<[LinkerInput]>;
+def r : Flag<"-r">;
+def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>,
+ HelpText<"Save intermediate compilation results">;
+def sectalign : MultiArg<"-sectalign", 3>;
+def sectcreate : MultiArg<"-sectcreate", 3>;
+def sectobjectsymbols : MultiArg<"-sectobjectsymbols", 2>;
+def sectorder : MultiArg<"-sectorder", 3>;
+def seg1addr : JoinedOrSeparate<"-seg1addr">;
+def seg__addr__table__filename : Separate<"-seg_addr_table_filename">;
+def seg__addr__table : Separate<"-seg_addr_table">;
+def segaddr : MultiArg<"-segaddr", 2>;
+def segcreate : MultiArg<"-segcreate", 3>;
+def seglinkedit : Flag<"-seglinkedit">;
+def segprot : MultiArg<"-segprot", 3>;
+def segs__read__only__addr : Separate<"-segs_read_only_addr">;
+def segs__read__write__addr : Separate<"-segs_read_write_addr">;
+def segs__read__ : Joined<"-segs_read_">;
+def shared_libgcc : Flag<"-shared-libgcc">;
+def shared : Flag<"-shared">;
+def single__module : Flag<"-single_module">;
+def specs_EQ : Joined<"-specs=">;
+def specs : Separate<"-specs">, Flags<[Unsupported]>;
+def static_libgcc : Flag<"-static-libgcc">;
+def static : Flag<"-static">, Flags<[NoArgumentUnused]>;
+def std_default_EQ : Joined<"-std-default=">;
+def std_EQ : Joined<"-std=">;
+def stdlib_EQ : Joined<"-stdlib=">;
+def sub__library : JoinedOrSeparate<"-sub_library">;
+def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">;
+def s : Flag<"-s">;
+def time : Flag<"-time">,
+ HelpText<"Time individual commands">;
+def traditional_cpp : Flag<"-traditional-cpp">;
+def traditional : Flag<"-traditional">;
+def trigraphs : Flag<"-trigraphs">;
+def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">;
+def twolevel__namespace : Flag<"-twolevel_namespace">;
+def t : Flag<"-t">;
+def umbrella : Separate<"-umbrella">;
+def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>;
+def undef : Flag<"-undef">, Group<u_Group>;
+def unexported__symbols__list : Separate<"-unexported_symbols_list">;
+def u : JoinedOrSeparate<"-u">, Group<u_Group>;
+def use_gold_plugin : Flag<"-use-gold-plugin">;
+def v : Flag<"-v">,
+ HelpText<"Show commands to run and use verbose output">;
+def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>;
+def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>;
+def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>;
+def weak__reference__mismatches : Separate<"-weak_reference_mismatches">;
+def whatsloaded : Flag<"-whatsloaded">;
+def whyload : Flag<"-whyload">;
+def w : Flag<"-w">;
+def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>,
+ HelpText<"Treat subsequent input files as having type <language>">,
+ MetaVarName<"<language>">;
+def y : Joined<"-y">;
+
+def working_directory : Separate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
+// Double dash options, which are usually an alias for one of the previous
+// options.
+
+def _CLASSPATH_EQ : Joined<"--CLASSPATH=">, Alias<fclasspath_EQ>;
+def _CLASSPATH : Separate<"--CLASSPATH">, Alias<fclasspath_EQ>;
+def _all_warnings : Flag<"--all-warnings">, Alias<Wall>;
+def _analyze_auto : Flag<"--analyze-auto">, Flags<[DriverOption]>;
+def _analyzer_no_default_checks : Flag<"--analyzer-no-default-checks">, Flags<[DriverOption]>;
+def _analyzer_output : JoinedOrSeparate<"--analyzer-output">, Flags<[DriverOption]>;
+def _analyze : Flag<"--analyze">, Flags<[DriverOption]>,
+ HelpText<"Run the static analyzer">;
+def _ansi : Flag<"--ansi">, Alias<ansi>;
+def _assemble : Flag<"--assemble">, Alias<S>;
+def _assert_EQ : Joined<"--assert=">, Alias<A>;
+def _assert : Separate<"--assert">, Alias<A>;
+def _bootclasspath_EQ : Joined<"--bootclasspath=">, Alias<fbootclasspath_EQ>;
+def _bootclasspath : Separate<"--bootclasspath">, Alias<fbootclasspath_EQ>;
+def _classpath_EQ : Joined<"--classpath=">, Alias<fclasspath_EQ>;
+def _classpath : Separate<"--classpath">, Alias<fclasspath_EQ>;
+def _combine : Flag<"--combine">, Alias<combine>;
+def _comments_in_macros : Flag<"--comments-in-macros">, Alias<CC>;
+def _comments : Flag<"--comments">, Alias<C>;
+def _compile : Flag<"--compile">, Alias<c>;
+def _constant_cfstrings : Flag<"--constant-cfstrings">;
+def _coverage : Flag<"--coverage">, Alias<coverage>;
+def _debug_EQ : Joined<"--debug=">, Alias<g_Flag>;
+def _debug : Flag<"--debug">, Alias<g_Flag>;
+def _define_macro_EQ : Joined<"--define-macro=">, Alias<D>;
+def _define_macro : Separate<"--define-macro">, Alias<D>;
+def _dependencies : Flag<"--dependencies">, Alias<M>;
+def _encoding_EQ : Joined<"--encoding=">, Alias<fencoding_EQ>;
+def _encoding : Separate<"--encoding">, Alias<fencoding_EQ>;
+def _entry : Flag<"--entry">, Alias<e>;
+def _extdirs_EQ : Joined<"--extdirs=">, Alias<fextdirs_EQ>;
+def _extdirs : Separate<"--extdirs">, Alias<fextdirs_EQ>;
+def _extra_warnings : Flag<"--extra-warnings">, Alias<W_Joined>;
+def _for_linker_EQ : Joined<"--for-linker=">, Alias<Xlinker>;
+def _for_linker : Separate<"--for-linker">, Alias<Xlinker>;
+def _force_link_EQ : Joined<"--force-link=">, Alias<u>;
+def _force_link : Separate<"--force-link">, Alias<u>;
+def _help_hidden : Flag<"--help-hidden">;
+def _help : Flag<"--help">,
+ HelpText<"Display available options">;
+def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>;
+def _imacros : Separate<"--imacros">, Alias<imacros>;
+def _include_barrier : Flag<"--include-barrier">, Alias<I_>;
+def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias<idirafter>;
+def _include_directory_after : Separate<"--include-directory-after">, Alias<idirafter>;
+def _include_directory_EQ : Joined<"--include-directory=">, Alias<I>;
+def _include_directory : Separate<"--include-directory">, Alias<I>;
+def _include_prefix_EQ : Joined<"--include-prefix=">, Alias<iprefix>;
+def _include_prefix : Separate<"--include-prefix">, Alias<iprefix>;
+def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias<iwithprefix>;
+def _include_with_prefix_after : Separate<"--include-with-prefix-after">, Alias<iwithprefix>;
+def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias<iwithprefixbefore>;
+def _include_with_prefix_before : Separate<"--include-with-prefix-before">, Alias<iwithprefixbefore>;
+def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias<iwithprefix>;
+def _include_with_prefix : Separate<"--include-with-prefix">, Alias<iwithprefix>;
+def _include_EQ : Joined<"--include=">, Alias<include_>;
+def _include : Separate<"--include">, Alias<include_>;
+def _language_EQ : Joined<"--language=">, Alias<x>;
+def _language : Separate<"--language">, Alias<x>;
+def _library_directory_EQ : Joined<"--library-directory=">, Alias<L>;
+def _library_directory : Separate<"--library-directory">, Alias<L>;
+def _machine__EQ : Joined<"--machine-=">, Alias<m_Joined>;
+def _machine_ : Joined<"--machine-">, Alias<m_Joined>;
+def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>;
+def _machine : Separate<"--machine">, Alias<m_Joined>;
+def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>;
+def _no_line_commands : Flag<"--no-line-commands">, Alias<P>;
+def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>;
+def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>;
+def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>;
+def _no_warnings : Flag<"--no-warnings">, Alias<w>;
+def _optimize_EQ : Joined<"--optimize=">, Alias<O>;
+def _optimize : Flag<"--optimize">, Alias<O>;
+def _output_class_directory_EQ : Joined<"--output-class-directory=">, Alias<foutput_class_dir_EQ>;
+def _output_class_directory : Separate<"--output-class-directory">, Alias<foutput_class_dir_EQ>;
+def _output_EQ : Joined<"--output=">, Alias<o>;
+def _output : Separate<"--output">, Alias<o>;
+def _param : Separate<"--param">;
+def _param_EQ : Joined<"--param=">, Alias<_param>;
+def _pass_exit_codes : Flag<"--pass-exit-codes">, Alias<pass_exit_codes>;
+def _pedantic_errors : Flag<"--pedantic-errors">, Alias<pedantic_errors>;
+def _pedantic : Flag<"--pedantic">, Alias<pedantic>;
+def _pipe : Flag<"--pipe">, Alias<pipe>;
+def _prefix_EQ : Joined<"--prefix=">, Alias<B>;
+def _prefix : Separate<"--prefix">, Alias<B>;
+def _preprocess : Flag<"--preprocess">, Alias<E>;
+def _print_diagnostic_categories : Flag<"--print-diagnostic-categories">;
+def _print_file_name_EQ : Joined<"--print-file-name=">, Alias<print_file_name_EQ>;
+def _print_file_name : Separate<"--print-file-name">, Alias<print_file_name_EQ>;
+def _print_libgcc_file_name : Flag<"--print-libgcc-file-name">, Alias<print_libgcc_file_name>;
+def _print_missing_file_dependencies : Flag<"--print-missing-file-dependencies">, Alias<MG>;
+def _print_multi_directory : Flag<"--print-multi-directory">, Alias<print_multi_directory>;
+def _print_multi_lib : Flag<"--print-multi-lib">, Alias<print_multi_lib>;
+def _print_multi_os_directory : Flag<"--print-multi-os-directory">, Alias<print_multi_os_directory>;
+def _print_prog_name_EQ : Joined<"--print-prog-name=">, Alias<print_prog_name_EQ>;
+def _print_prog_name : Separate<"--print-prog-name">, Alias<print_prog_name_EQ>;
+def _print_search_dirs : Flag<"--print-search-dirs">, Alias<print_search_dirs>;
+def _profile_blocks : Flag<"--profile-blocks">, Alias<a>;
+def _profile : Flag<"--profile">, Alias<p>;
+def _relocatable_pch : Flag<"--relocatable-pch">,
+ HelpText<"Build a relocatable precompiled header">;
+def _resource_EQ : Joined<"--resource=">, Alias<fcompile_resource_EQ>;
+def _resource : Separate<"--resource">, Alias<fcompile_resource_EQ>;
+def _save_temps : Flag<"--save-temps">, Alias<save_temps>;
+def _shared : Flag<"--shared">, Alias<shared>;
+def _signed_char : Flag<"--signed-char">, Alias<fsigned_char>;
+def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>;
+def _specs : Separate<"--specs">, Alias<specs_EQ>;
+def _static : Flag<"--static">, Alias<static>;
+def _std_EQ : Joined<"--std=">, Alias<std_EQ>;
+def _std : Separate<"--std">, Alias<std_EQ>;
+def _stdlib_EQ : Joined<"--stdlib=">, Alias<std_EQ>;
+def _stdlib : Separate<"--stdlib">, Alias<std_EQ>;
+def _sysroot_EQ : Joined<"--sysroot=">;
+def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>;
+def _target_help : Flag<"--target-help">;
+def _trace_includes : Flag<"--trace-includes">, Alias<H>;
+def _traditional_cpp : Flag<"--traditional-cpp">, Alias<traditional_cpp>;
+def _traditional : Flag<"--traditional">, Alias<traditional>;
+def _trigraphs : Flag<"--trigraphs">, Alias<trigraphs>;
+def _undefine_macro_EQ : Joined<"--undefine-macro=">, Alias<U>;
+def _undefine_macro : Separate<"--undefine-macro">, Alias<U>;
+def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>;
+def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>;
+def _verbose : Flag<"--verbose">, Alias<v>;
+def _version : Flag<"--version">;
+def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>;
+def _warn_ : Joined<"--warn-">, Alias<W_Joined>;
+def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>;
+def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>;
+def _ : Joined<"--">, Flags<[Unsupported]>;
+
+// Special internal option to handle -Xlinker --no-demangle.
+def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">,
+ Flags<[Unsupported, NoArgumentUnused]>;
+
+// Special internal option to allow forwarding arbitrary arguments to linker.
+def Zlinker_input : Separate<"-Zlinker-input">,
+ Flags<[Unsupported, NoArgumentUnused]>;
+
+// Reserved library options.
+def Z_reserved_lib_stdcxx : Flag<"-Z-reserved-lib-stdc++">,
+ Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
+def Z_reserved_lib_cckext : Flag<"-Z-reserved-lib-cckext">,
+ Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Phases.h b/contrib/llvm/tools/clang/include/clang/Driver/Phases.h
new file mode 100644
index 0000000..a0c42ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Phases.h
@@ -0,0 +1,32 @@
+//===--- Phases.h - Transformations on Driver Types -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_PHASES_H_
+#define CLANG_DRIVER_PHASES_H_
+
+namespace clang {
+namespace driver {
+namespace phases {
+ /// ID - Ordered values for successive stages in the
+ /// compilation process which interact with user options.
+ enum ID {
+ Preprocess,
+ Precompile,
+ Compile,
+ Assemble,
+ Link
+ };
+
+ const char *getPhaseName(ID Id);
+
+} // end namespace phases
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Tool.h b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
new file mode 100644
index 0000000..c30fa4c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
@@ -0,0 +1,76 @@
+//===--- Tool.h - Compilation Tools -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TOOL_H_
+#define CLANG_DRIVER_TOOL_H_
+
+namespace llvm {
+ template<typename T, unsigned N> class SmallVector;
+}
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Compilation;
+ class InputInfo;
+ class Job;
+ class JobAction;
+ class ToolChain;
+
+ typedef llvm::SmallVector<InputInfo, 4> InputInfoList;
+
+/// Tool - Information on a specific compilation tool.
+class Tool {
+ /// The tool name (for debugging).
+ const char *Name;
+
+ /// The human readable name for the tool, for use in diagnostics.
+ const char *ShortName;
+
+ /// The tool chain this tool is a part of.
+ const ToolChain &TheToolChain;
+
+public:
+ Tool(const char *Name, const char *ShortName,
+ const ToolChain &TC);
+
+public:
+ virtual ~Tool();
+
+ const char *getName() const { return Name; }
+
+ const char *getShortName() const { return ShortName; }
+
+ const ToolChain &getToolChain() const { return TheToolChain; }
+
+ virtual bool hasIntegratedAssembler() const { return false; }
+ virtual bool hasIntegratedCPP() const = 0;
+
+ /// \brief Does this tool have "good" standardized diagnostics, or should the
+ /// driver add an additional "command failed" diagnostic on failures.
+ virtual bool hasGoodDiagnostics() const { return false; }
+
+ /// ConstructJob - Construct jobs to perform the action \arg JA,
+ /// writing to \arg Output and with \arg Inputs.
+ ///
+ /// \param TCArgs - The argument list for this toolchain, with any
+ /// tool chain specific translations applied.
+ /// \param LinkingOutput - If this output will eventually feed the
+ /// linker, then this is the final output name of the linked image.
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const = 0;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
new file mode 100644
index 0000000..f0012bd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
@@ -0,0 +1,198 @@
+//===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TOOLCHAIN_H_
+#define CLANG_DRIVER_TOOLCHAIN_H_
+
+#include "clang/Driver/Util.h"
+#include "clang/Driver/Types.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Path.h"
+#include <string>
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Compilation;
+ class DerivedArgList;
+ class Driver;
+ class HostInfo;
+ class InputArgList;
+ class JobAction;
+ class Tool;
+
+/// ToolChain - Access to tools for a single platform.
+class ToolChain {
+public:
+ typedef llvm::SmallVector<std::string, 4> path_list;
+
+ enum CXXStdlibType {
+ CST_Libcxx,
+ CST_Libstdcxx
+ };
+
+private:
+ const HostInfo &Host;
+ const llvm::Triple Triple;
+
+ /// The list of toolchain specific path prefixes to search for
+ /// files.
+ path_list FilePaths;
+
+ /// The list of toolchain specific path prefixes to search for
+ /// programs.
+ path_list ProgramPaths;
+
+protected:
+ ToolChain(const HostInfo &Host, const llvm::Triple &_Triple);
+
+public:
+ virtual ~ToolChain();
+
+ // Accessors
+
+ const Driver &getDriver() const;
+ const llvm::Triple &getTriple() const { return Triple; }
+
+ llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
+ llvm::StringRef getArchName() const { return Triple.getArchName(); }
+ llvm::StringRef getPlatform() const { return Triple.getVendorName(); }
+ llvm::StringRef getOS() const { return Triple.getOSName(); }
+
+ std::string getTripleString() const {
+ return Triple.getTriple();
+ }
+
+ path_list &getFilePaths() { return FilePaths; }
+ const path_list &getFilePaths() const { return FilePaths; }
+
+ path_list &getProgramPaths() { return ProgramPaths; }
+ const path_list &getProgramPaths() const { return ProgramPaths; }
+
+ // Tool access.
+
+ /// TranslateArgs - Create a new derived argument list for any argument
+ /// translations this ToolChain may wish to perform, or 0 if no tool chain
+ /// specific translations are needed.
+ ///
+ /// \param BoundArch - The bound architecture name, or 0.
+ virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ return 0;
+ }
+
+ /// SelectTool - Choose a tool to use to handle the action \arg JA.
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const = 0;
+
+ // Helper methods
+
+ std::string GetFilePath(const char *Name) const;
+ std::string GetProgramPath(const char *Name, bool WantFile = false) const;
+
+ // Platform defaults information
+
+ /// HasNativeLTOLinker - Check whether the linker and related tools have
+ /// native LLVM support.
+ virtual bool HasNativeLLVMSupport() const;
+
+ /// LookupTypeForExtension - Return the default language type to use for the
+ /// given extension.
+ virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
+ /// IsBlocksDefault - Does this tool chain enable -fblocks by default.
+ virtual bool IsBlocksDefault() const { return false; }
+
+ /// IsIntegratedAssemblerDefault - Does this tool chain enable -integrated-as
+ /// by default.
+ virtual bool IsIntegratedAssemblerDefault() const { return false; }
+
+ /// IsStrictAliasingDefault - Does this tool chain use -fstrict-aliasing by
+ /// default.
+ virtual bool IsStrictAliasingDefault() const { return true; }
+
+ /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable
+ /// -fobjc-default-synthesize-properties by default.
+ virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; }
+
+ /// IsObjCNonFragileABIDefault - Does this tool chain set
+ /// -fobjc-nonfragile-abi by default.
+ virtual bool IsObjCNonFragileABIDefault() const { return false; }
+
+ /// IsObjCLegacyDispatchDefault - Does this tool chain set
+ /// -fobjc-legacy-dispatch by default (this is only used with the non-fragile
+ /// ABI).
+ virtual bool IsObjCLegacyDispatchDefault() const { return false; }
+
+ /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the
+ /// mixed dispatch method be used?
+ virtual bool UseObjCMixedDispatch() const { return false; }
+
+ /// GetDefaultStackProtectorLevel - Get the default stack protector level for
+ /// this tool chain (0=off, 1=on, 2=all).
+ virtual unsigned GetDefaultStackProtectorLevel() const { return 0; }
+
+ /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
+ /// by default.
+ virtual bool IsUnwindTablesDefault() const = 0;
+
+ /// GetDefaultRelocationModel - Return the LLVM name of the default
+ /// relocation model for this tool chain.
+ virtual const char *GetDefaultRelocationModel() const = 0;
+
+ /// GetForcedPicModel - Return the LLVM name of the forced PIC model
+ /// for this tool chain, or 0 if this tool chain does not force a
+ /// particular PIC mode.
+ virtual const char *GetForcedPicModel() const = 0;
+
+ /// Does this tool chain support Objective-C garbage collection.
+ virtual bool SupportsObjCGC() const { return false; }
+
+ /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
+ /// compile unit information.
+ virtual bool UseDwarfDebugFlags() const { return false; }
+
+ /// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
+ virtual bool UseSjLjExceptions() const { return false; }
+
+ /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
+ /// command line arguments into account.
+ virtual std::string ComputeLLVMTriple(const ArgList &Args) const;
+
+ /// ComputeEffectiveClangTriple - Return the Clang triple to use for this
+ /// target, which may take into account the command line arguments. For
+ /// example, on Darwin the -mmacosx-version-min= command line argument (which
+ /// sets the deployment target) determines the version in the triple passed to
+ /// Clang.
+ virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
+ // GetCXXStdlibType - Determine the C++ standard library type to use with the
+ // given compilation arguments.
+ virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+
+ /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set
+ /// the include paths to use for the given C++ standard library type.
+ virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
+ /// for the given C++ standard library type.
+ virtual void AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// AddCCKextLibArgs - Add the system specific linker arguments to use
+ /// for kernel extensions (Darwin-specific).
+ virtual void AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.def b/contrib/llvm/tools/clang/include/clang/Driver/Types.def
new file mode 100644
index 0000000..f09a1dc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def
@@ -0,0 +1,88 @@
+//===--- Types.def - Driver Type info ---------------------------*- 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 driver type information. Users of this file
+// must define the TYPE macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE
+#error "Define TYPE prior to including this file!"
+#endif
+
+// TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS)
+
+// The first value is the type name as a string; for types which can
+// be user specified this should be the equivalent -x option.
+
+// The second value is the type id, which will result in a
+// clang::driver::types::TY_XX enum constant.
+
+// The third value is that id of the type for preprocessed inputs of
+// this type, or INVALID if this type is not preprocessed.
+
+// The fourth value is the suffix to use when creating temporary files
+// of this type, or null if unspecified.
+
+// The fifth value is a string containt option flags. Valid values:
+// a - The type should only be assembled.
+// p - The type should only be precompiled.
+// u - The type can be user specified (with -x).
+// A - The type's temporary suffix should be appended when generating
+// outputs of this type.
+
+
+// C family source language (with and without preprocessing).
+TYPE("cpp-output", PP_C, INVALID, "i", "u")
+TYPE("c", C, PP_C, 0, "u")
+TYPE("cl", CL, PP_C, 0, "u")
+TYPE("cuda", CUDA, PP_CXX, 0, "u")
+TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
+TYPE("objective-c", ObjC, PP_ObjC, 0, "u")
+TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
+TYPE("c++", CXX, PP_CXX, 0, "u")
+TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u")
+TYPE("objective-c++", ObjCXX, PP_ObjCXX, 0, "u")
+
+// C family input files to precompile.
+TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
+TYPE("c-header", CHeader, PP_CHeader, 0, "pu")
+TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
+TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, 0, "pu")
+TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
+TYPE("c++-header", CXXHeader, PP_CXXHeader, 0, "pu")
+TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
+TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu")
+
+// Other languages.
+TYPE("ada", Ada, INVALID, 0, "u")
+TYPE("assembler", PP_Asm, INVALID, "s", "au")
+TYPE("assembler-with-cpp", Asm, PP_Asm, 0, "au")
+TYPE("f95", PP_Fortran, INVALID, 0, "u")
+TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u")
+TYPE("java", Java, INVALID, 0, "u")
+
+// LLVM IR/LTO types. We define separate types for IR and LTO because LTO
+// outputs should use the standard suffixes.
+TYPE("ir", LLVM_IR, INVALID, "ll", "u")
+TYPE("ir", LLVM_BC, INVALID, "bc", "u")
+TYPE("lto-ir", LTO_IR, INVALID, "s", "")
+TYPE("lto-bc", LTO_BC, INVALID, "o", "")
+
+// Misc.
+TYPE("ast", AST, INVALID, "ast", "u")
+TYPE("plist", Plist, INVALID, "plist", "")
+TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "")
+TYPE("precompiled-header", PCH, INVALID, "gch", "A")
+TYPE("object", Object, INVALID, "o", "")
+TYPE("treelang", Treelang, INVALID, 0, "u")
+TYPE("image", Image, INVALID, "out", "")
+TYPE("dSYM", dSYM, INVALID, "dSYM", "A")
+TYPE("dependencies", Dependencies, INVALID, "d", "")
+TYPE("none", Nothing, INVALID, 0, "u")
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.h b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
new file mode 100644
index 0000000..9187529
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
@@ -0,0 +1,96 @@
+//===--- Types.h - Input & Temporary Driver Types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TYPES_H_
+#define CLANG_DRIVER_TYPES_H_
+
+#include "clang/Driver/Phases.h"
+
+namespace clang {
+namespace driver {
+namespace types {
+ enum ID {
+ TY_INVALID,
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) TY_##ID,
+#include "clang/Driver/Types.def"
+#undef TYPE
+ TY_LAST
+ };
+
+ /// getTypeName - Return the name of the type for \arg Id.
+ const char *getTypeName(ID Id);
+
+ /// getPreprocessedType - Get the ID of the type for this input when
+ /// it has been preprocessed, or INVALID if this input is not
+ /// preprocessed.
+ ID getPreprocessedType(ID Id);
+
+ /// getTypeTempSuffix - Return the suffix to use when creating a
+ /// temp file of this type, or null if unspecified.
+ const char *getTypeTempSuffix(ID Id);
+
+ /// onlyAssembleType - Should this type only be assembled.
+ bool onlyAssembleType(ID Id);
+
+ /// onlyPrecompileType - Should this type only be precompiled.
+ bool onlyPrecompileType(ID Id);
+
+ /// canTypeBeUserSpecified - Can this type be specified on the
+ /// command line (by the type name); this is used when forwarding
+ /// commands to gcc.
+ bool canTypeBeUserSpecified(ID Id);
+
+ /// appendSuffixForType - When generating outputs of this type,
+ /// should the suffix be appended (instead of replacing the existing
+ /// suffix).
+ bool appendSuffixForType(ID Id);
+
+ /// canLipoType - Is this type acceptable as the output of a
+ /// universal build (currently, just the Nothing, Image, and Object
+ /// types).
+ bool canLipoType(ID Id);
+
+ /// isAcceptedByClang - Can clang handle this input type.
+ bool isAcceptedByClang(ID Id);
+
+ /// isOnlyAcceptedByClang - Is clang the only compiler that can handle this
+ /// input type.
+ bool isOnlyAcceptedByClang(ID Id);
+
+ /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
+ bool isCXX(ID Id);
+
+ /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
+ bool isObjC(ID Id);
+
+ /// lookupTypeForExtension - Lookup the type to use for the file
+ /// extension \arg Ext.
+ ID lookupTypeForExtension(const char *Ext);
+
+ /// lookupTypeForTypSpecifier - Lookup the type to use for a user
+ /// specified type name.
+ ID lookupTypeForTypeSpecifier(const char *Name);
+
+ /// getNumCompilationPhases - Return the complete number of phases
+ /// to be done for this type.
+ unsigned getNumCompilationPhases(ID Id);
+
+ /// getCompilationPhase - Return the \args N th compilation phase to
+ /// be done for this type.
+ phases::ID getCompilationPhase(ID Id, unsigned N);
+
+ /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given
+ /// C type (used for clang++ emulation of g++ behaviour)
+ ID lookupCXXTypeForCType(ID Id);
+
+} // end namespace types
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Util.h b/contrib/llvm/tools/clang/include/clang/Driver/Util.h
new file mode 100644
index 0000000..52f268d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Util.h
@@ -0,0 +1,30 @@
+//===--- Util.h - Common Driver Utilities -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_UTIL_H_
+#define CLANG_DRIVER_UTIL_H_
+
+namespace llvm {
+ template<typename T, unsigned N> class SmallVector;
+}
+
+namespace clang {
+namespace driver {
+ class Action;
+
+ /// ArgStringList - Type used for constructing argv lists for subprocesses.
+ typedef llvm::SmallVector<const char*, 16> ArgStringList;
+
+ /// ActionList - Type used for lists of actions.
+ typedef llvm::SmallVector<Action*, 3> ActionList;
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
new file mode 100644
index 0000000..c45bd40
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
@@ -0,0 +1,64 @@
+//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DRIVER_ASTCONSUMERS_H
+#define DRIVER_ASTCONSUMERS_H
+
+#include <string>
+
+namespace llvm {
+ class raw_ostream;
+ namespace sys { class Path; }
+}
+namespace clang {
+
+class ASTConsumer;
+class CodeGenOptions;
+class Diagnostic;
+class FileManager;
+class LangOptions;
+class Preprocessor;
+class TargetOptions;
+
+// AST pretty-printer: prints out the AST in a format that is close to the
+// original C code. The output is intended to be in a format such that
+// clang could re-parse the output back into the same AST, but the
+// implementation is still incomplete.
+ASTConsumer *CreateASTPrinter(llvm::raw_ostream *OS);
+
+// AST XML-printer: prints out the AST in a XML format
+// The output is intended to be in a format such that
+// clang or any other tool could re-parse the output back into the same AST,
+// but the implementation is still incomplete.
+ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream *OS);
+
+// AST dumper: dumps the raw AST in human-readable form to stderr; this is
+// intended for debugging.
+ASTConsumer *CreateASTDumper();
+
+// AST XML-dumper: dumps out the AST to stderr in a very detailed XML
+// format; this is intended for particularly intense debugging.
+ASTConsumer *CreateASTDumperXML(llvm::raw_ostream &OS);
+
+// Graphical AST viewer: for each function definition, creates a graph of
+// the AST and displays it with the graph viewer "dotty". Also outputs
+// function declarations to stderr.
+ASTConsumer *CreateASTViewer();
+
+// DeclContext printer: prints out the DeclContext tree in human-readable form
+// to stderr; this is intended for debugging.
+ASTConsumer *CreateDeclContextPrinter();
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
new file mode 100644
index 0000000..e935633
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -0,0 +1,654 @@
+//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit utility class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
+#define LLVM_CLANG_FRONTEND_ASTUNIT_H
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang-c/Index.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Path.h"
+#include <map>
+#include <string>
+#include <vector>
+#include <cassert>
+#include <utility>
+#include <sys/types.h>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+class ASTContext;
+class CodeCompleteConsumer;
+class CompilerInvocation;
+class Decl;
+class Diagnostic;
+class FileEntry;
+class FileManager;
+class HeaderSearch;
+class Preprocessor;
+class SourceManager;
+class TargetInfo;
+
+using namespace idx;
+
+/// \brief Allocator for a cached set of global code completions.
+class GlobalCodeCompletionAllocator
+ : public CodeCompletionAllocator,
+ public llvm::RefCountedBase<GlobalCodeCompletionAllocator>
+{
+
+};
+
+/// \brief Utility class for loading a ASTContext from an AST file.
+///
+class ASTUnit {
+public:
+ typedef std::map<FileID, std::vector<PreprocessedEntity *> >
+ PreprocessedEntitiesByFileMap;
+
+private:
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
+ llvm::OwningPtr<FileManager> FileMgr;
+ llvm::OwningPtr<SourceManager> SourceMgr;
+ llvm::OwningPtr<HeaderSearch> HeaderInfo;
+ llvm::OwningPtr<TargetInfo> Target;
+ llvm::OwningPtr<Preprocessor> PP;
+ llvm::OwningPtr<ASTContext> Ctx;
+
+ FileSystemOptions FileSystemOpts;
+
+ /// \brief The AST consumer that received information about the translation
+ /// unit as it was parsed or loaded.
+ llvm::OwningPtr<ASTConsumer> Consumer;
+
+ /// \brief The semantic analysis object used to type-check the translation
+ /// unit.
+ llvm::OwningPtr<Sema> TheSema;
+
+ /// Optional owned invocation, just used to make the invocation used in
+ /// LoadFromCommandLine available.
+ llvm::OwningPtr<CompilerInvocation> Invocation;
+
+ /// \brief The set of target features.
+ ///
+ /// FIXME: each time we reparse, we need to restore the set of target
+ /// features from this vector, because TargetInfo::CreateTargetInfo()
+ /// mangles the target options in place. Yuck!
+ std::vector<std::string> TargetFeatures;
+
+ // OnlyLocalDecls - when true, walking this AST should only visit declarations
+ // that come from the AST itself, not from included precompiled headers.
+ // FIXME: This is temporary; eventually, CIndex will always do this.
+ bool OnlyLocalDecls;
+
+ /// \brief Whether to capture any diagnostics produced.
+ bool CaptureDiagnostics;
+
+ /// \brief Track whether the main file was loaded from an AST or not.
+ bool MainFileIsAST;
+
+ /// \brief Whether this AST represents a complete translation unit.
+ bool CompleteTranslationUnit;
+
+ /// \brief Whether we should time each operation.
+ bool WantTiming;
+
+ /// Track the top-level decls which appeared in an ASTUnit which was loaded
+ /// from a source file.
+ //
+ // FIXME: This is just an optimization hack to avoid deserializing large parts
+ // of a PCH file when using the Index library on an ASTUnit loaded from
+ // source. In the long term we should make the Index library use efficient and
+ // more scalable search mechanisms.
+ std::vector<Decl*> TopLevelDecls;
+
+ /// \brief The list of preprocessed entities which appeared when the ASTUnit
+ /// was loaded.
+ ///
+ /// FIXME: This is just an optimization hack to avoid deserializing large
+ /// parts of a PCH file while performing a walk or search. In the long term,
+ /// we should provide more scalable search mechanisms.
+ std::vector<PreprocessedEntity *> PreprocessedEntities;
+
+ /// The name of the original source file used to generate this ASTUnit.
+ std::string OriginalSourceFile;
+
+ // Critical optimization when using clang_getCursor().
+ ASTLocation LastLoc;
+
+ /// \brief The set of diagnostics produced when creating this
+ /// translation unit.
+ llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+
+ /// \brief The number of stored diagnostics that come from the driver
+ /// itself.
+ ///
+ /// Diagnostics that come from the driver are retained from one parse to
+ /// the next.
+ unsigned NumStoredDiagnosticsFromDriver;
+
+ /// \brief Temporary files that should be removed when the ASTUnit is
+ /// destroyed.
+ llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
+
+ /// \brief A mapping from file IDs to the set of preprocessed entities
+ /// stored in that file.
+ ///
+ /// FIXME: This is just an optimization hack to avoid searching through
+ /// many preprocessed entities during cursor traversal in the CIndex library.
+ /// Ideally, we would just be able to perform a binary search within the
+ /// list of preprocessed entities.
+ PreprocessedEntitiesByFileMap PreprocessedEntitiesByFile;
+
+ /// \brief Simple hack to allow us to assert that ASTUnit is not being
+ /// used concurrently, which is not supported.
+ ///
+ /// Clients should create instances of the ConcurrencyCheck class whenever
+ /// using the ASTUnit in a way that isn't intended to be concurrent, which is
+ /// just about any usage.
+ unsigned int ConcurrencyCheckValue;
+ static const unsigned int CheckLocked = 28573289;
+ static const unsigned int CheckUnlocked = 9803453;
+
+ /// \brief Counter that determines when we want to try building a
+ /// precompiled preamble.
+ ///
+ /// If zero, we will never build a precompiled preamble. Otherwise,
+ /// it's treated as a counter that decrements each time we reparse
+ /// without the benefit of a precompiled preamble. When it hits 1,
+ /// we'll attempt to rebuild the precompiled header. This way, if
+ /// building the precompiled preamble fails, we won't try again for
+ /// some number of calls.
+ unsigned PreambleRebuildCounter;
+
+ /// \brief The file in which the precompiled preamble is stored.
+ std::string PreambleFile;
+
+ /// \brief The contents of the preamble that has been precompiled to
+ /// \c PreambleFile.
+ std::vector<char> Preamble;
+
+ /// \brief Whether the preamble ends at the start of a new line.
+ ///
+ /// Used to inform the lexer as to whether it's starting at the beginning of
+ /// a line after skipping the preamble.
+ bool PreambleEndsAtStartOfLine;
+
+ /// \brief The size of the source buffer that we've reserved for the main
+ /// file within the precompiled preamble.
+ unsigned PreambleReservedSize;
+
+ /// \brief Keeps track of the files that were used when computing the
+ /// preamble, with both their buffer size and their modification time.
+ ///
+ /// If any of the files have changed from one compile to the next,
+ /// the preamble must be thrown away.
+ llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble;
+
+ /// \brief When non-NULL, this is the buffer used to store the contents of
+ /// the main file when it has been padded for use with the precompiled
+ /// preamble.
+ llvm::MemoryBuffer *SavedMainFileBuffer;
+
+ /// \brief When non-NULL, this is the buffer used to store the
+ /// contents of the preamble when it has been padded to build the
+ /// precompiled preamble.
+ llvm::MemoryBuffer *PreambleBuffer;
+
+ /// \brief The number of warnings that occurred while parsing the preamble.
+ ///
+ /// This value will be used to restore the state of the \c Diagnostic object
+ /// when re-using the precompiled preamble. Note that only the
+ /// number of warnings matters, since we will not save the preamble
+ /// when any errors are present.
+ unsigned NumWarningsInPreamble;
+
+ /// \brief The number of diagnostics that were stored when parsing
+ /// the precompiled preamble.
+ ///
+ /// This value is used to determine how many of the stored
+ /// diagnostics should be retained when reparsing in the presence of
+ /// a precompiled preamble.
+ unsigned NumStoredDiagnosticsInPreamble;
+
+ /// \brief A list of the serialization ID numbers for each of the top-level
+ /// declarations parsed within the precompiled preamble.
+ std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
+
+ /// \brief A list of the offsets into the precompiled preamble which
+ /// correspond to preprocessed entities.
+ std::vector<uint64_t> PreprocessedEntitiesInPreamble;
+
+ /// \brief Whether we should be caching code-completion results.
+ bool ShouldCacheCodeCompletionResults;
+
+ static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
+ const char **ArgBegin, const char **ArgEnd,
+ ASTUnit &AST, bool CaptureDiagnostics);
+
+public:
+ /// \brief A cached code-completion result, which may be introduced in one of
+ /// many different contexts.
+ struct CachedCodeCompletionResult {
+ /// \brief The code-completion string corresponding to this completion
+ /// result.
+ CodeCompletionString *Completion;
+
+ /// \brief A bitmask that indicates which code-completion contexts should
+ /// contain this completion result.
+ ///
+ /// The bits in the bitmask correspond to the values of
+ /// CodeCompleteContext::Kind. To map from a completion context kind to a
+ /// bit, subtract one from the completion context kind and shift 1 by that
+ /// number of bits. Many completions can occur in several different
+ /// contexts.
+ unsigned ShowInContexts;
+
+ /// \brief The priority given to this code-completion result.
+ unsigned Priority;
+
+ /// \brief The libclang cursor kind corresponding to this code-completion
+ /// result.
+ CXCursorKind Kind;
+
+ /// \brief The availability of this code-completion result.
+ CXAvailabilityKind Availability;
+
+ /// \brief The simplified type class for a non-macro completion result.
+ SimplifiedTypeClass TypeClass;
+
+ /// \brief The type of a non-macro completion result, stored as a unique
+ /// integer used by the string map of cached completion types.
+ ///
+ /// This value will be zero if the type is not known, or a unique value
+ /// determined by the formatted type string. Se \c CachedCompletionTypes
+ /// for more information.
+ unsigned Type;
+ };
+
+ /// \brief Retrieve the mapping from formatted type names to unique type
+ /// identifiers.
+ llvm::StringMap<unsigned> &getCachedCompletionTypes() {
+ return CachedCompletionTypes;
+ }
+
+ /// \brief Retrieve the allocator used to cache global code completions.
+ llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ getCachedCompletionAllocator() {
+ return CachedCompletionAllocator;
+ }
+
+private:
+ /// \brief Allocator used to store cached code completions.
+ llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ CachedCompletionAllocator;
+
+ /// \brief The set of cached code-completion results.
+ std::vector<CachedCodeCompletionResult> CachedCompletionResults;
+
+ /// \brief A mapping from the formatted type name to a unique number for that
+ /// type, which is used for type equality comparisons.
+ llvm::StringMap<unsigned> CachedCompletionTypes;
+
+ /// \brief A string hash of the top-level declaration and macro definition
+ /// names processed the last time that we reparsed the file.
+ ///
+ /// This hash value is used to determine when we need to refresh the
+ /// global code-completion cache.
+ unsigned CompletionCacheTopLevelHashValue;
+
+ /// \brief A string hash of the top-level declaration and macro definition
+ /// names processed the last time that we reparsed the precompiled preamble.
+ ///
+ /// This hash value is used to determine when we need to refresh the
+ /// global code-completion cache after a rebuild of the precompiled preamble.
+ unsigned PreambleTopLevelHashValue;
+
+ /// \brief The current hash value for the top-level declaration and macro
+ /// definition names
+ unsigned CurrentTopLevelHashValue;
+
+ /// \brief Bit used by CIndex to mark when a translation unit may be in an
+ /// inconsistent state, and is not safe to free.
+ unsigned UnsafeToFree : 1;
+
+ /// \brief Cache any "global" code-completion results, so that we can avoid
+ /// recomputing them with each completion.
+ void CacheCodeCompletionResults();
+
+ /// \brief Clear out and deallocate
+ void ClearCachedCompletionResults();
+
+ ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
+ ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
+
+ explicit ASTUnit(bool MainFileIsAST);
+
+ void CleanTemporaryFiles();
+ bool Parse(llvm::MemoryBuffer *OverrideMainBuffer);
+
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
+ ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines, bool &CreatedBuffer);
+
+ llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
+ bool AllowRebuild = true,
+ unsigned MaxLines = 0);
+ void RealizeTopLevelDeclsFromPreamble();
+ void RealizePreprocessedEntitiesFromPreamble();
+
+public:
+ class ConcurrencyCheck {
+ volatile ASTUnit &Self;
+
+ public:
+ explicit ConcurrencyCheck(ASTUnit &Self)
+ : Self(Self)
+ {
+ assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
+ "Concurrent access to ASTUnit!");
+ Self.ConcurrencyCheckValue = CheckLocked;
+ }
+
+ ~ConcurrencyCheck() {
+ Self.ConcurrencyCheckValue = CheckUnlocked;
+ }
+ };
+ friend class ConcurrencyCheck;
+
+ ~ASTUnit();
+
+ bool isMainFileAST() const { return MainFileIsAST; }
+
+ bool isUnsafeToFree() const { return UnsafeToFree; }
+ void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
+
+ const Diagnostic &getDiagnostics() const { return *Diagnostics; }
+ Diagnostic &getDiagnostics() { return *Diagnostics; }
+
+ const SourceManager &getSourceManager() const { return *SourceMgr; }
+ SourceManager &getSourceManager() { return *SourceMgr; }
+
+ const Preprocessor &getPreprocessor() const { return *PP.get(); }
+ Preprocessor &getPreprocessor() { return *PP.get(); }
+
+ const ASTContext &getASTContext() const { return *Ctx.get(); }
+ ASTContext &getASTContext() { return *Ctx.get(); }
+
+ bool hasSema() const { return TheSema; }
+ Sema &getSema() const {
+ assert(TheSema && "ASTUnit does not have a Sema object!");
+ return *TheSema;
+ }
+
+ const FileManager &getFileManager() const { return *FileMgr; }
+ FileManager &getFileManager() { return *FileMgr; }
+
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
+ const std::string &getOriginalSourceFileName();
+ const std::string &getASTFileName();
+
+ /// \brief Add a temporary file that the ASTUnit depends on.
+ ///
+ /// This file will be erased when the ASTUnit is destroyed.
+ void addTemporaryFile(const llvm::sys::Path &TempFile) {
+ TemporaryFiles.push_back(TempFile);
+ }
+
+ bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+
+ /// \brief Retrieve the maximum PCH level of declarations that a
+ /// traversal of the translation unit should consider.
+ unsigned getMaxPCHLevel() const;
+
+ void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
+ ASTLocation getLastASTLocation() const { return LastLoc; }
+
+
+ llvm::StringRef getMainFileName() const;
+
+ typedef std::vector<Decl *>::iterator top_level_iterator;
+
+ top_level_iterator top_level_begin() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.begin();
+ }
+
+ top_level_iterator top_level_end() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.end();
+ }
+
+ std::size_t top_level_size() const {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ return TopLevelDeclsInPreamble.size() + TopLevelDecls.size();
+ }
+
+ bool top_level_empty() const {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
+ }
+
+ /// \brief Add a new top-level declaration.
+ void addTopLevelDecl(Decl *D) {
+ TopLevelDecls.push_back(D);
+ }
+
+ /// \brief Add a new top-level declaration, identified by its ID in
+ /// the precompiled preamble.
+ void addTopLevelDeclFromPreamble(serialization::DeclID D) {
+ TopLevelDeclsInPreamble.push_back(D);
+ }
+
+ /// \brief Retrieve a reference to the current top-level name hash value.
+ ///
+ /// Note: This is used internally by the top-level tracking action
+ unsigned &getCurrentTopLevelHashValue() { return CurrentTopLevelHashValue; }
+
+ typedef std::vector<PreprocessedEntity *>::iterator pp_entity_iterator;
+
+ pp_entity_iterator pp_entity_begin();
+ pp_entity_iterator pp_entity_end();
+
+ /// \brief Add a new preprocessed entity that's stored at the given offset
+ /// in the precompiled preamble.
+ void addPreprocessedEntityFromPreamble(uint64_t Offset) {
+ PreprocessedEntitiesInPreamble.push_back(Offset);
+ }
+
+ /// \brief Retrieve the mapping from File IDs to the preprocessed entities
+ /// within that file.
+ PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() {
+ return PreprocessedEntitiesByFile;
+ }
+
+ // Retrieve the diagnostics associated with this AST
+ typedef const StoredDiagnostic *stored_diag_iterator;
+ stored_diag_iterator stored_diag_begin() const {
+ return StoredDiagnostics.begin();
+ }
+ stored_diag_iterator stored_diag_end() const {
+ return StoredDiagnostics.end();
+ }
+ unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
+
+ llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() {
+ return StoredDiagnostics;
+ }
+
+ typedef std::vector<CachedCodeCompletionResult>::iterator
+ cached_completion_iterator;
+
+ cached_completion_iterator cached_completion_begin() {
+ return CachedCompletionResults.begin();
+ }
+
+ cached_completion_iterator cached_completion_end() {
+ return CachedCompletionResults.end();
+ }
+
+ unsigned cached_completion_size() const {
+ return CachedCompletionResults.size();
+ }
+
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr = 0);
+
+ /// \brief Whether this AST represents a complete translation unit.
+ ///
+ /// If false, this AST is only a partial translation unit, e.g., one
+ /// that might still be used as a precompiled header or preamble.
+ bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
+
+ /// \brief A mapping from a file name to the memory buffer that stores the
+ /// remapped contents of that file.
+ typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
+
+ /// \brief Create a ASTUnit from an AST file.
+ ///
+ /// \param Filename - The AST file to load.
+ ///
+ /// \param Diags - The diagnostics engine to use for reporting errors; its
+ /// lifetime is expected to extend past that of the returned ASTUnit.
+ ///
+ /// \returns - The initialized ASTUnit or null if the AST failed to load.
+ static ASTUnit *LoadFromASTFile(const std::string &Filename,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ const FileSystemOptions &FileSystemOpts,
+ bool OnlyLocalDecls = false,
+ RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0,
+ bool CaptureDiagnostics = false);
+
+private:
+ /// \brief Helper function for \c LoadFromCompilerInvocation() and
+ /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
+ ///
+ /// \param PrecompilePreamble Whether to precompile the preamble of this
+ /// translation unit, to improve the performance of reparsing.
+ ///
+ /// \returns \c true if a catastrophic failure occurred (which means that the
+ /// \c ASTUnit itself is invalid), or \c false otherwise.
+ bool LoadFromCompilerInvocation(bool PrecompilePreamble);
+
+public:
+
+ /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
+ /// CompilerInvocation object.
+ ///
+ /// \param CI - The compiler invocation to use; it must have exactly one input
+ /// source file. The ASTUnit takes ownership of the CompilerInvocation object.
+ ///
+ /// \param Diags - The diagnostics engine to use for reporting errors; its
+ /// lifetime is expected to extend past that of the returned ASTUnit.
+ //
+ // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+ // shouldn't need to specify them at construction time.
+ static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ bool OnlyLocalDecls = false,
+ bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false);
+
+ /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
+ /// arguments, which must specify exactly one source file.
+ ///
+ /// \param ArgBegin - The beginning of the argument vector.
+ ///
+ /// \param ArgEnd - The end of the argument vector.
+ ///
+ /// \param Diags - The diagnostics engine to use for reporting errors; its
+ /// lifetime is expected to extend past that of the returned ASTUnit.
+ ///
+ /// \param ResourceFilesPath - The path to the compiler resource files.
+ //
+ // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
+ // shouldn't need to specify them at construction time.
+ static ASTUnit *LoadFromCommandLine(const char **ArgBegin,
+ const char **ArgEnd,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ llvm::StringRef ResourceFilesPath,
+ bool OnlyLocalDecls = false,
+ bool CaptureDiagnostics = false,
+ RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false,
+ bool CXXPrecompilePreamble = false,
+ bool CXXChainedPCH = false);
+
+ /// \brief Reparse the source files using the same command-line options that
+ /// were originally used to produce this translation unit.
+ ///
+ /// \returns True if a failure occurred that causes the ASTUnit not to
+ /// contain any translation-unit information, false otherwise.
+ bool Reparse(RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0);
+
+ /// \brief Perform code completion at the given file, line, and
+ /// column within this translation unit.
+ ///
+ /// \param File The file in which code completion will occur.
+ ///
+ /// \param Line The line at which code completion will occur.
+ ///
+ /// \param Column The column at which code completion will occur.
+ ///
+ /// \param IncludeMacros Whether to include macros in the code-completion
+ /// results.
+ ///
+ /// \param IncludeCodePatterns Whether to include code patterns (such as a
+ /// for loop) in the code-completion results.
+ ///
+ /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
+ /// OwnedBuffers parameters are all disgusting hacks. They will go away.
+ void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
+ RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
+ bool IncludeMacros, bool IncludeCodePatterns,
+ CodeCompleteConsumer &Consumer,
+ Diagnostic &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
+
+ /// \brief Save this translation unit to a file with the given name.
+ ///
+ /// \returns True if an error occurred, false otherwise.
+ bool Save(llvm::StringRef File);
+};
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def
new file mode 100644
index 0000000..75b52a8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Analyses.def
@@ -0,0 +1,53 @@
+//===-- Analyses.def - Metadata about Static Analyses -----------*- 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 set of static analyses used by AnalysisConsumer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ANALYSIS
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
+#endif
+
+ANALYSIS(WarnUninitVals, "warn-uninit-values",
+ "Warn about uses of uninitialized variables", Code)
+
+ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem",
+ "Run the [Core] Foundation reference count checker", Code)
+
+#ifndef ANALYSIS_STORE
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_STORE(BasicStore, "basic", "Use basic analyzer store", CreateBasicStoreManager)
+ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager)
+ANALYSIS_STORE(FlatStore, "flat", "Use flat analyzer store", CreateFlatStoreManager)
+
+#ifndef ANALYSIS_CONSTRAINTS
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_CONSTRAINTS(BasicConstraints, "basic", "Use basic constraint tracking", CreateBasicConstraintManager)
+ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
+
+#ifndef ANALYSIS_DIAGNOSTICS
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
+#endif
+
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticClient, false)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticClient, true)
+
+#undef ANALYSIS
+#undef ANALYSIS_STORE
+#undef ANALYSIS_CONSTRAINTS
+#undef ANALYSIS_DIAGNOSTICS
+#undef ANALYSIS_STORE
+
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
new file mode 100644
index 0000000..5806928
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
@@ -0,0 +1,112 @@
+//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains the structures necessary for a front-end to specify
+// various analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H
+#define LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTConsumer;
+class Diagnostic;
+class Preprocessor;
+class LangOptions;
+
+/// Analysis - Set of available source code analyses.
+enum Analyses {
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
+#include "clang/Frontend/Analyses.def"
+NumAnalyses
+};
+
+/// AnalysisStores - Set of available analysis store models.
+enum AnalysisStores {
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/Frontend/Analyses.def"
+NumStores
+};
+
+/// AnalysisConstraints - Set of available constraint models.
+enum AnalysisConstraints {
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/Frontend/Analyses.def"
+NumConstraints
+};
+
+/// AnalysisDiagClients - Set of available diagnostic clients for rendering
+/// analysis results.
+enum AnalysisDiagClients {
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
+#include "clang/Frontend/Analyses.def"
+NUM_ANALYSIS_DIAG_CLIENTS
+};
+
+class AnalyzerOptions {
+public:
+ std::vector<Analyses> AnalysisList;
+ /// \brief Pair of checker name and enable/disable.
+ std::vector<std::pair<std::string, bool> > CheckersControlList;
+ AnalysisStores AnalysisStoreOpt;
+ AnalysisConstraints AnalysisConstraintsOpt;
+ AnalysisDiagClients AnalysisDiagOpt;
+ std::string AnalyzeSpecificFunction;
+ unsigned MaxNodes;
+ unsigned MaxLoop;
+ unsigned AnalyzeAll : 1;
+ unsigned AnalyzerDisplayProgress : 1;
+ unsigned AnalyzeNestedBlocks : 1;
+ unsigned AnalyzerStats : 1;
+ unsigned EagerlyAssume : 1;
+ unsigned BufferOverflows : 1;
+ unsigned PurgeDead : 1;
+ unsigned TrimGraph : 1;
+ unsigned VisualizeEGDot : 1;
+ unsigned VisualizeEGUbi : 1;
+ unsigned EnableExperimentalChecks : 1;
+ unsigned EnableExperimentalInternalChecks : 1;
+ unsigned InlineCall : 1;
+ unsigned UnoptimizedCFG : 1;
+ unsigned CFGAddImplicitDtors : 1;
+ unsigned CFGAddInitializers : 1;
+ unsigned EagerlyTrimEGraph : 1;
+
+public:
+ AnalyzerOptions() {
+ AnalysisStoreOpt = BasicStoreModel;
+ AnalysisConstraintsOpt = RangeConstraintsModel;
+ AnalysisDiagOpt = PD_HTML;
+ AnalyzeAll = 0;
+ AnalyzerDisplayProgress = 0;
+ AnalyzeNestedBlocks = 0;
+ AnalyzerStats = 0;
+ EagerlyAssume = 0;
+ BufferOverflows = 0;
+ PurgeDead = 1;
+ TrimGraph = 0;
+ VisualizeEGDot = 0;
+ VisualizeEGUbi = 0;
+ EnableExperimentalChecks = 0;
+ EnableExperimentalInternalChecks = 0;
+ InlineCall = 0;
+ UnoptimizedCFG = 0;
+ CFGAddImplicitDtors = 0;
+ CFGAddInitializers = 0;
+ EagerlyTrimEGraph = 0;
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h
new file mode 100644
index 0000000..2d5e128
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticClient.h
@@ -0,0 +1,58 @@
+//===--- ChainedDiagnosticClient.h - Chain Diagnostic Clients ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H
+#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+class LangOptions;
+
+/// ChainedDiagnosticClient - Chain two diagnostic clients so that diagnostics
+/// go to the first client and then the second. The first diagnostic client
+/// should be the "primary" client, and will be used for computing whether the
+/// diagnostics should be included in counts.
+class ChainedDiagnosticClient : public DiagnosticClient {
+ llvm::OwningPtr<DiagnosticClient> Primary;
+ llvm::OwningPtr<DiagnosticClient> Secondary;
+
+public:
+ ChainedDiagnosticClient(DiagnosticClient *_Primary,
+ DiagnosticClient *_Secondary) {
+ Primary.reset(_Primary);
+ Secondary.reset(_Secondary);
+ }
+
+ virtual void BeginSourceFile(const LangOptions &LO,
+ const Preprocessor *PP) {
+ Primary->BeginSourceFile(LO, PP);
+ Secondary->BeginSourceFile(LO, PP);
+ }
+
+ virtual void EndSourceFile() {
+ Secondary->EndSourceFile();
+ Primary->EndSourceFile();
+ }
+
+ virtual bool IncludeInDiagnosticCounts() const {
+ return Primary->IncludeInDiagnosticCounts();
+ }
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ Primary->HandleDiagnostic(DiagLevel, Info);
+ Secondary->HandleDiagnostic(DiagLevel, Info);
+ }
+};
+
+} // end namspace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
new file mode 100644
index 0000000..ee85b655
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
@@ -0,0 +1,170 @@
+//===--- CodeGenOptions.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeGenOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H
+#define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H
+
+#include <string>
+
+namespace clang {
+
+/// CodeGenOptions - Track various options which control how the code
+/// is optimized and passed to the backend.
+class CodeGenOptions {
+public:
+ enum InliningMethod {
+ NoInlining, // Perform no inlining whatsoever.
+ NormalInlining, // Use the standard function inlining pass.
+ OnlyAlwaysInlining // Only run the always inlining pass.
+ };
+
+ enum ObjCDispatchMethodKind {
+ Legacy = 0,
+ NonLegacy = 1,
+ Mixed = 2
+ };
+
+ unsigned AsmVerbose : 1; /// -dA, -fverbose-asm.
+ unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors.
+ unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker
+ /// aliases to base ctors when possible.
+ unsigned DataSections : 1; /// Set when -fdata-sections is enabled
+ unsigned DebugInfo : 1; /// Should generate debug info (-g).
+ unsigned LimitDebugInfo : 1; /// Limit generated debug info to reduce size.
+ unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled.
+ unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in
+ /// getting .bc files that correspond to the
+ /// internal state before optimizations are
+ /// done.
+ unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
+ unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what
+ /// Decl* various IR entities came from. Only
+ /// useful when running CodeGen as a
+ /// subroutine.
+ unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled
+ unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for
+ /// template classes with hidden visibility
+ unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with
+ /// hidden visibility.
+ unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is
+ /// enabled.
+ unsigned InstrumentForProfiling : 1; /// Set when -pg is enabled
+ unsigned LessPreciseFPMAD : 1; /// Enable less precise MAD instructions to be
+ /// generated.
+ unsigned MergeAllConstants : 1; /// Merge identical constants.
+ unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
+ unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
+ unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf.
+ unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN.
+ unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
+ unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use.
+ unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is
+ /// enabled.
+ unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
+ unsigned OptimizeSize : 1; /// If -Os is specified.
+ unsigned RelaxAll : 1; /// Relax all machine code instructions.
+ unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled.
+ unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled.
+ unsigned SoftFloat : 1; /// -soft-float.
+ unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
+ unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization
+ /// selection.
+ unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
+ unsigned UnsafeFPMath : 1; /// Allow unsafe floating point optzns.
+ unsigned UnwindTables : 1; /// Emit unwind tables.
+ unsigned VerifyModule : 1; /// Control whether the module should be run
+ /// through the LLVM Verifier.
+
+ /// The code model to use (-mcmodel).
+ std::string CodeModel;
+
+ /// Enable additional debugging information.
+ std::string DebugPass;
+
+ /// The string to embed in the debug information for the compile unit, if
+ /// non-empty.
+ std::string DwarfDebugFlags;
+
+ /// The ABI to use for passing floating point arguments.
+ std::string FloatABI;
+
+ /// The float precision limit to use, if non-empty.
+ std::string LimitFloatPrecision;
+
+ /// The kind of inlining to perform.
+ InliningMethod Inlining;
+
+ /// The user provided name for the "main file", if non-empty. This is useful
+ /// in situations where the input file name does not match the original input
+ /// file, for example with -save-temps.
+ std::string MainFileName;
+
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
+
+ /// The user specified number of registers to be used for integral arguments,
+ /// or 0 if unspecified.
+ unsigned NumRegisterParameters;
+
+public:
+ CodeGenOptions() {
+ AsmVerbose = 0;
+ CXAAtExit = 1;
+ CXXCtorDtorAliases = 0;
+ DataSections = 0;
+ DebugInfo = 0;
+ LimitDebugInfo = 0;
+ DisableFPElim = 0;
+ DisableLLVMOpts = 0;
+ DisableRedZone = 0;
+ EmitDeclMetadata = 0;
+ FunctionSections = 0;
+ HiddenWeakTemplateVTables = 0;
+ HiddenWeakVTables = 0;
+ InstrumentFunctions = 0;
+ InstrumentForProfiling = 0;
+ LessPreciseFPMAD = 0;
+ MergeAllConstants = 1;
+ NoCommon = 0;
+ NoImplicitFloat = 0;
+ NoInfsFPMath = 0;
+ NoNaNsFPMath = 0;
+ NoZeroInitializedInBSS = 0;
+ NumRegisterParameters = 0;
+ ObjCDispatchMethod = Legacy;
+ OmitLeafFramePointer = 0;
+ OptimizationLevel = 0;
+ OptimizeSize = 0;
+ RelaxAll = 0;
+ RelaxedAliasing = 0;
+ SimplifyLibCalls = 1;
+ SoftFloat = 0;
+ TimePasses = 0;
+ UnitAtATime = 1;
+ UnrollLoops = 0;
+ UnsafeFPMath = 0;
+ UnwindTables = 0;
+ VerifyModule = 1;
+
+ Inlining = NoInlining;
+ RelocationModel = "pic";
+ }
+
+ ObjCDispatchMethodKind getObjCDispatchMethod() const {
+ return ObjCDispatchMethodKind(ObjCDispatchMethod);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
new file mode 100644
index 0000000..8911cfa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
@@ -0,0 +1,86 @@
+
+//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line parsing for source locations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
+#define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+/// \brief A source location that has been parsed on the command line.
+struct ParsedSourceLocation {
+ std::string FileName;
+ unsigned Line;
+ unsigned Column;
+
+public:
+ /// Construct a parsed source location from a string; the Filename is empty on
+ /// error.
+ static ParsedSourceLocation FromString(llvm::StringRef Str) {
+ ParsedSourceLocation PSL;
+ std::pair<llvm::StringRef, llvm::StringRef> ColSplit = Str.rsplit(':');
+ std::pair<llvm::StringRef, llvm::StringRef> LineSplit =
+ ColSplit.first.rsplit(':');
+
+ // If both tail splits were valid integers, return success.
+ if (!ColSplit.second.getAsInteger(10, PSL.Column) &&
+ !LineSplit.second.getAsInteger(10, PSL.Line)) {
+ PSL.FileName = LineSplit.first;
+
+ // On the command-line, stdin may be specified via "-". Inside the
+ // compiler, stdin is called "<stdin>".
+ if (PSL.FileName == "-")
+ PSL.FileName = "<stdin>";
+ }
+
+ return PSL;
+ }
+};
+
+}
+
+namespace llvm {
+ namespace cl {
+ /// \brief Command-line option parser that parses source locations.
+ ///
+ /// Source locations are of the form filename:line:column.
+ template<>
+ class parser<clang::ParsedSourceLocation>
+ : public basic_parser<clang::ParsedSourceLocation> {
+ public:
+ inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
+ clang::ParsedSourceLocation &Val);
+ };
+
+ bool
+ parser<clang::ParsedSourceLocation>::
+ parse(Option &O, StringRef ArgName, StringRef ArgValue,
+ clang::ParsedSourceLocation &Val) {
+ using namespace clang;
+
+ Val = ParsedSourceLocation::FromString(ArgValue);
+ if (Val.FileName.empty()) {
+ errs() << "error: "
+ << "source location must be of the form filename:line:column\n";
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
new file mode 100644
index 0000000..7ea79e5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -0,0 +1,625 @@
+//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
+#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cassert>
+#include <list>
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+class raw_fd_ostream;
+class Timer;
+}
+
+namespace clang {
+class ASTContext;
+class ASTConsumer;
+class CodeCompleteConsumer;
+class Diagnostic;
+class DiagnosticClient;
+class ExternalASTSource;
+class FileManager;
+class FrontendAction;
+class ASTReader;
+class Preprocessor;
+class Sema;
+class SourceManager;
+class TargetInfo;
+
+/// CompilerInstance - Helper class for managing a single instance of the Clang
+/// compiler.
+///
+/// The CompilerInstance serves two purposes:
+/// (1) It manages the various objects which are necessary to run the compiler,
+/// for example the preprocessor, the target information, and the AST
+/// context.
+/// (2) It provides utility routines for constructing and manipulating the
+/// common Clang objects.
+///
+/// The compiler instance generally owns the instance of all the objects that it
+/// manages. However, clients can still share objects by manually setting the
+/// object and retaking ownership prior to destroying the CompilerInstance.
+///
+/// The compiler instance is intended to simplify clients, but not to lock them
+/// in to the compiler instance for everything. When possible, utility functions
+/// come in two forms; a short form that reuses the CompilerInstance objects,
+/// and a long form that takes explicit instances of any required objects.
+class CompilerInstance {
+ /// The options used in this compiler instance.
+ llvm::OwningPtr<CompilerInvocation> Invocation;
+
+ /// The diagnostics engine instance.
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
+
+ /// The target being compiled for.
+ llvm::OwningPtr<TargetInfo> Target;
+
+ /// The file manager.
+ llvm::OwningPtr<FileManager> FileMgr;
+
+ /// The source manager.
+ llvm::OwningPtr<SourceManager> SourceMgr;
+
+ /// The preprocessor.
+ llvm::OwningPtr<Preprocessor> PP;
+
+ /// The AST context.
+ llvm::OwningPtr<ASTContext> Context;
+
+ /// The AST consumer.
+ llvm::OwningPtr<ASTConsumer> Consumer;
+
+ /// The code completion consumer.
+ llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+
+ /// \brief The semantic analysis object.
+ llvm::OwningPtr<Sema> TheSema;
+
+ /// The frontend timer
+ llvm::OwningPtr<llvm::Timer> FrontendTimer;
+
+ /// \brief Holds information about the output file.
+ ///
+ /// If TempFilename is not empty we must rename it to Filename at the end.
+ /// TempFilename may be empty and Filename non empty if creating the temporary
+ /// failed.
+ struct OutputFile {
+ std::string Filename;
+ std::string TempFilename;
+ llvm::raw_ostream *OS;
+
+ OutputFile(const std::string &filename, const std::string &tempFilename,
+ llvm::raw_ostream *os)
+ : Filename(filename), TempFilename(tempFilename), OS(os) { }
+ };
+
+ /// The list of active output files.
+ std::list<OutputFile> OutputFiles;
+
+ void operator=(const CompilerInstance &); // DO NOT IMPLEMENT
+ CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
+public:
+ CompilerInstance();
+ ~CompilerInstance();
+
+ /// @name High-Level Operations
+ /// {
+
+ /// ExecuteAction - Execute the provided action against the compiler's
+ /// CompilerInvocation object.
+ ///
+ /// This function makes the following assumptions:
+ ///
+ /// - The invocation options should be initialized. This function does not
+ /// handle the '-help' or '-version' options, clients should handle those
+ /// directly.
+ ///
+ /// - The diagnostics engine should have already been created by the client.
+ ///
+ /// - No other CompilerInstance state should have been initialized (this is
+ /// an unchecked error).
+ ///
+ /// - Clients should have initialized any LLVM target features that may be
+ /// required.
+ ///
+ /// - Clients should eventually call llvm_shutdown() upon the completion of
+ /// this routine to ensure that any managed objects are properly destroyed.
+ ///
+ /// Note that this routine may write output to 'stderr'.
+ ///
+ /// \param Act - The action to execute.
+ /// \return - True on success.
+ //
+ // FIXME: This function should take the stream to write any debugging /
+ // verbose output to as an argument.
+ //
+ // FIXME: Eliminate the llvm_shutdown requirement, that should either be part
+ // of the context or else not CompilerInstance specific.
+ bool ExecuteAction(FrontendAction &Act);
+
+ /// }
+ /// @name Compiler Invocation and Options
+ /// {
+
+ bool hasInvocation() const { return Invocation != 0; }
+
+ CompilerInvocation &getInvocation() {
+ assert(Invocation && "Compiler instance has no invocation!");
+ return *Invocation;
+ }
+
+ CompilerInvocation *takeInvocation() { return Invocation.take(); }
+
+ /// setInvocation - Replace the current invocation; the compiler instance
+ /// takes ownership of \arg Value.
+ void setInvocation(CompilerInvocation *Value);
+
+ /// }
+ /// @name Forwarding Methods
+ /// {
+
+ AnalyzerOptions &getAnalyzerOpts() {
+ return Invocation->getAnalyzerOpts();
+ }
+ const AnalyzerOptions &getAnalyzerOpts() const {
+ return Invocation->getAnalyzerOpts();
+ }
+
+ CodeGenOptions &getCodeGenOpts() {
+ return Invocation->getCodeGenOpts();
+ }
+ const CodeGenOptions &getCodeGenOpts() const {
+ return Invocation->getCodeGenOpts();
+ }
+
+ DependencyOutputOptions &getDependencyOutputOpts() {
+ return Invocation->getDependencyOutputOpts();
+ }
+ const DependencyOutputOptions &getDependencyOutputOpts() const {
+ return Invocation->getDependencyOutputOpts();
+ }
+
+ DiagnosticOptions &getDiagnosticOpts() {
+ return Invocation->getDiagnosticOpts();
+ }
+ const DiagnosticOptions &getDiagnosticOpts() const {
+ return Invocation->getDiagnosticOpts();
+ }
+
+ const FileSystemOptions &getFileSystemOpts() const {
+ return Invocation->getFileSystemOpts();
+ }
+
+ FrontendOptions &getFrontendOpts() {
+ return Invocation->getFrontendOpts();
+ }
+ const FrontendOptions &getFrontendOpts() const {
+ return Invocation->getFrontendOpts();
+ }
+
+ HeaderSearchOptions &getHeaderSearchOpts() {
+ return Invocation->getHeaderSearchOpts();
+ }
+ const HeaderSearchOptions &getHeaderSearchOpts() const {
+ return Invocation->getHeaderSearchOpts();
+ }
+
+ LangOptions &getLangOpts() {
+ return Invocation->getLangOpts();
+ }
+ const LangOptions &getLangOpts() const {
+ return Invocation->getLangOpts();
+ }
+
+ PreprocessorOptions &getPreprocessorOpts() {
+ return Invocation->getPreprocessorOpts();
+ }
+ const PreprocessorOptions &getPreprocessorOpts() const {
+ return Invocation->getPreprocessorOpts();
+ }
+
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() {
+ return Invocation->getPreprocessorOutputOpts();
+ }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
+ return Invocation->getPreprocessorOutputOpts();
+ }
+
+ TargetOptions &getTargetOpts() {
+ return Invocation->getTargetOpts();
+ }
+ const TargetOptions &getTargetOpts() const {
+ return Invocation->getTargetOpts();
+ }
+
+ /// }
+ /// @name Diagnostics Engine
+ /// {
+
+ bool hasDiagnostics() const { return Diagnostics != 0; }
+
+ Diagnostic &getDiagnostics() const {
+ assert(Diagnostics && "Compiler instance has no diagnostics!");
+ return *Diagnostics;
+ }
+
+ /// setDiagnostics - Replace the current diagnostics engine; the compiler
+ /// instance takes ownership of \arg Value.
+ void setDiagnostics(Diagnostic *Value);
+
+ DiagnosticClient &getDiagnosticClient() const {
+ assert(Diagnostics && Diagnostics->getClient() &&
+ "Compiler instance has no diagnostic client!");
+ return *Diagnostics->getClient();
+ }
+
+ /// }
+ /// @name Target Info
+ /// {
+
+ bool hasTarget() const { return Target != 0; }
+
+ TargetInfo &getTarget() const {
+ assert(Target && "Compiler instance has no target!");
+ return *Target;
+ }
+
+ /// takeTarget - Remove the current diagnostics engine and give ownership
+ /// to the caller.
+ TargetInfo *takeTarget() { return Target.take(); }
+
+ /// setTarget - Replace the current diagnostics engine; the compiler
+ /// instance takes ownership of \arg Value.
+ void setTarget(TargetInfo *Value);
+
+ /// }
+ /// @name File Manager
+ /// {
+
+ bool hasFileManager() const { return FileMgr != 0; }
+
+ FileManager &getFileManager() const {
+ assert(FileMgr && "Compiler instance has no file manager!");
+ return *FileMgr;
+ }
+
+ /// takeFileManager - Remove the current file manager and give ownership to
+ /// the caller.
+ FileManager *takeFileManager() { return FileMgr.take(); }
+
+ /// setFileManager - Replace the current file manager; the compiler instance
+ /// takes ownership of \arg Value.
+ void setFileManager(FileManager *Value);
+
+ /// }
+ /// @name Source Manager
+ /// {
+
+ bool hasSourceManager() const { return SourceMgr != 0; }
+
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "Compiler instance has no source manager!");
+ return *SourceMgr;
+ }
+
+ /// takeSourceManager - Remove the current source manager and give ownership
+ /// to the caller.
+ SourceManager *takeSourceManager() { return SourceMgr.take(); }
+
+ /// setSourceManager - Replace the current source manager; the compiler
+ /// instance takes ownership of \arg Value.
+ void setSourceManager(SourceManager *Value);
+
+ /// }
+ /// @name Preprocessor
+ /// {
+
+ bool hasPreprocessor() const { return PP != 0; }
+
+ Preprocessor &getPreprocessor() const {
+ assert(PP && "Compiler instance has no preprocessor!");
+ return *PP;
+ }
+
+ /// takePreprocessor - Remove the current preprocessor and give ownership to
+ /// the caller.
+ Preprocessor *takePreprocessor() { return PP.take(); }
+
+ /// setPreprocessor - Replace the current preprocessor; the compiler instance
+ /// takes ownership of \arg Value.
+ void setPreprocessor(Preprocessor *Value);
+
+ /// }
+ /// @name ASTContext
+ /// {
+
+ bool hasASTContext() const { return Context != 0; }
+
+ ASTContext &getASTContext() const {
+ assert(Context && "Compiler instance has no AST context!");
+ return *Context;
+ }
+
+ /// takeASTContext - Remove the current AST context and give ownership to the
+ /// caller.
+ ASTContext *takeASTContext() { return Context.take(); }
+
+ /// setASTContext - Replace the current AST context; the compiler instance
+ /// takes ownership of \arg Value.
+ void setASTContext(ASTContext *Value);
+
+ /// \brief Replace the current Sema; the compiler instance takes ownership
+ /// of S.
+ void setSema(Sema *S);
+
+ /// }
+ /// @name ASTConsumer
+ /// {
+
+ bool hasASTConsumer() const { return Consumer != 0; }
+
+ ASTConsumer &getASTConsumer() const {
+ assert(Consumer && "Compiler instance has no AST consumer!");
+ return *Consumer;
+ }
+
+ /// takeASTConsumer - Remove the current AST consumer and give ownership to
+ /// the caller.
+ ASTConsumer *takeASTConsumer() { return Consumer.take(); }
+
+ /// setASTConsumer - Replace the current AST consumer; the compiler instance
+ /// takes ownership of \arg Value.
+ void setASTConsumer(ASTConsumer *Value);
+
+ /// }
+ /// @name Semantic analysis
+ /// {
+ bool hasSema() const { return TheSema != 0; }
+
+ Sema &getSema() const {
+ assert(TheSema && "Compiler instance has no Sema object!");
+ return *TheSema;
+ }
+
+ Sema *takeSema() { return TheSema.take(); }
+
+ /// }
+ /// @name Code Completion
+ /// {
+
+ bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; }
+
+ CodeCompleteConsumer &getCodeCompletionConsumer() const {
+ assert(CompletionConsumer &&
+ "Compiler instance has no code completion consumer!");
+ return *CompletionConsumer;
+ }
+
+ /// takeCodeCompletionConsumer - Remove the current code completion consumer
+ /// and give ownership to the caller.
+ CodeCompleteConsumer *takeCodeCompletionConsumer() {
+ return CompletionConsumer.take();
+ }
+
+ /// setCodeCompletionConsumer - Replace the current code completion consumer;
+ /// the compiler instance takes ownership of \arg Value.
+ void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
+
+ /// }
+ /// @name Frontend timer
+ /// {
+
+ bool hasFrontendTimer() const { return FrontendTimer != 0; }
+
+ llvm::Timer &getFrontendTimer() const {
+ assert(FrontendTimer && "Compiler instance has no frontend timer!");
+ return *FrontendTimer;
+ }
+
+ /// }
+ /// @name Output Files
+ /// {
+
+ /// addOutputFile - Add an output file onto the list of tracked output files.
+ ///
+ /// \param OutFile - The output file info.
+ void addOutputFile(const OutputFile &OutFile);
+
+ /// clearOutputFiles - Clear the output file list, destroying the contained
+ /// output streams.
+ ///
+ /// \param EraseFiles - If true, attempt to erase the files from disk.
+ void clearOutputFiles(bool EraseFiles);
+
+ /// }
+ /// @name Construction Utility Methods
+ /// {
+
+ /// Create the diagnostics engine using the invocation's diagnostic options
+ /// and replace any existing one with it.
+ ///
+ /// Note that this routine also replaces the diagnostic client,
+ /// allocating one if one is not provided.
+ ///
+ /// \param Client If non-NULL, a diagnostic client that will be
+ /// attached to (and, then, owned by) the Diagnostic inside this AST
+ /// unit.
+ void createDiagnostics(int Argc, const char* const *Argv,
+ DiagnosticClient *Client = 0);
+
+ /// Create a Diagnostic object with a the TextDiagnosticPrinter.
+ ///
+ /// The \arg Argc and \arg Argv arguments are used only for logging purposes,
+ /// when the diagnostic options indicate that the compiler should output
+ /// logging information.
+ ///
+ /// If no diagnostic client is provided, this creates a
+ /// DiagnosticClient that is owned by the returned diagnostic
+ /// object, if using directly the caller is responsible for
+ /// releasing the returned Diagnostic's client eventually.
+ ///
+ /// \param Opts - The diagnostic options; note that the created text
+ /// diagnostic object contains a reference to these options and its lifetime
+ /// must extend past that of the diagnostic engine.
+ ///
+ /// \param Client If non-NULL, a diagnostic client that will be
+ /// attached to (and, then, owned by) the returned Diagnostic
+ /// object.
+ ///
+ /// \return The new object on success, or null on failure.
+ static llvm::IntrusiveRefCntPtr<Diagnostic>
+ createDiagnostics(const DiagnosticOptions &Opts, int Argc,
+ const char* const *Argv,
+ DiagnosticClient *Client = 0);
+
+ /// Create the file manager and replace any existing one with it.
+ void createFileManager();
+
+ /// Create the source manager and replace any existing one with it.
+ void createSourceManager(FileManager &FileMgr);
+
+ /// Create the preprocessor, using the invocation, file, and source managers,
+ /// and replace any existing one with it.
+ void createPreprocessor();
+
+ /// Create a Preprocessor object.
+ ///
+ /// Note that this also creates a new HeaderSearch object which will be owned
+ /// by the resulting Preprocessor.
+ ///
+ /// \return The new object on success, or null on failure.
+ static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &,
+ const PreprocessorOptions &,
+ const HeaderSearchOptions &,
+ const DependencyOutputOptions &,
+ const TargetInfo &,
+ const FrontendOptions &,
+ SourceManager &, FileManager &);
+
+ /// Create the AST context.
+ void createASTContext();
+
+ /// Create an external AST source to read a PCH file and attach it to the AST
+ /// context.
+ void createPCHExternalASTSource(llvm::StringRef Path,
+ bool DisablePCHValidation,
+ bool DisableStatCache,
+ void *DeserializationListener);
+
+ /// Create an external AST source to read a PCH file.
+ ///
+ /// \return - The new object on success, or null on failure.
+ static ExternalASTSource *
+ createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot,
+ bool DisablePCHValidation,
+ bool DisableStatCache,
+ Preprocessor &PP, ASTContext &Context,
+ void *DeserializationListener, bool Preamble);
+
+ /// Create a code completion consumer using the invocation; note that this
+ /// will cause the source manager to truncate the input source file at the
+ /// completion point.
+ void createCodeCompletionConsumer();
+
+ /// Create a code completion consumer to print code completion results, at
+ /// \arg Filename, \arg Line, and \arg Column, to the given output stream \arg
+ /// OS.
+ static CodeCompleteConsumer *
+ createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
+ unsigned Line, unsigned Column,
+ bool ShowMacros,
+ bool ShowCodePatterns, bool ShowGlobals,
+ llvm::raw_ostream &OS);
+
+ /// \brief Create the Sema object to be used for parsing.
+ void createSema(bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer);
+
+ /// Create the frontend timer and replace any existing one with it.
+ void createFrontendTimer();
+
+ /// Create the default output file (from the invocation's options) and add it
+ /// to the list of tracked output files.
+ ///
+ /// \return - Null on error.
+ llvm::raw_fd_ostream *
+ createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file and add it to the list of tracked output files,
+ /// optionally deriving the output path name.
+ ///
+ /// \return - Null on error.
+ llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath,
+ bool Binary = true, bool RemoveFileOnSignal = true,
+ llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file, optionally deriving the output path name.
+ ///
+ /// If \arg OutputPath is empty, then createOutputFile will derive an output
+ /// path location as \arg BaseInput, with any suffix removed, and \arg
+ /// Extension appended. If OutputPath is not stdout createOutputFile will
+ /// create a new temporary file that must be renamed to OutputPath in the end.
+ ///
+ /// \param OutputPath - If given, the path to the output file.
+ /// \param Error [out] - On failure, the error message.
+ /// \param BaseInput - If \arg OutputPath is empty, the input path name to use
+ /// for deriving the output path.
+ /// \param Extension - The extension to use for derived output names.
+ /// \param Binary - The mode to open the file in.
+ /// \param RemoveFileOnSignal - Whether the file should be registered with
+ /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for
+ /// multithreaded use, as the underlying signal mechanism is not reentrant
+ /// \param ResultPathName [out] - If given, the result path name will be
+ /// stored here on success.
+ /// \param TempPathName [out] - If given, the temporary file path name
+ /// will be stored here on success.
+ static llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath, std::string &Error,
+ bool Binary = true, bool RemoveFileOnSignal = true,
+ llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "",
+ std::string *ResultPathName = 0,
+ std::string *TempPathName = 0);
+
+ /// }
+ /// @name Initialization Utility Methods
+ /// {
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ bool InitializeSourceManager(llvm::StringRef InputFile);
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ static bool InitializeSourceManager(llvm::StringRef InputFile,
+ Diagnostic &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts);
+
+ /// }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
new file mode 100644
index 0000000..e0329db
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
@@ -0,0 +1,193 @@
+//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Frontend/AnalyzerOptions.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Frontend/LangStandard.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+ template<typename T> class SmallVectorImpl;
+}
+
+namespace clang {
+
+class Diagnostic;
+
+/// CompilerInvocation - Helper class for holding the data necessary to invoke
+/// the compiler.
+///
+/// This class is designed to represent an abstract "invocation" of the
+/// compiler, including data such as the include paths, the code generation
+/// options, the warning flags, and so on.
+class CompilerInvocation {
+ /// Options controlling the static analyzer.
+ AnalyzerOptions AnalyzerOpts;
+
+ /// Options controlling IRgen and the backend.
+ CodeGenOptions CodeGenOpts;
+
+ /// Options controlling dependency output.
+ DependencyOutputOptions DependencyOutputOpts;
+
+ /// Options controlling the diagnostic engine.
+ DiagnosticOptions DiagnosticOpts;
+
+ /// Options controlling file system operations.
+ FileSystemOptions FileSystemOpts;
+
+ /// Options controlling the frontend itself.
+ FrontendOptions FrontendOpts;
+
+ /// Options controlling the #include directive.
+ HeaderSearchOptions HeaderSearchOpts;
+
+ /// Options controlling the language variant.
+ LangOptions LangOpts;
+
+ /// Options controlling the preprocessor (aside from #include handling).
+ PreprocessorOptions PreprocessorOpts;
+
+ /// Options controlling preprocessed output.
+ PreprocessorOutputOptions PreprocessorOutputOpts;
+
+ /// Options controlling the target.
+ TargetOptions TargetOpts;
+
+public:
+ CompilerInvocation() {}
+
+ /// @name Utility Methods
+ /// @{
+
+ /// CreateFromArgs - Create a compiler invocation from a list of input
+ /// options.
+ ///
+ /// \param Res [out] - The resulting invocation.
+ /// \param ArgBegin - The first element in the argument vector.
+ /// \param ArgEnd - The last element in the argument vector.
+ /// \param Diags - The diagnostic engine to use for errors.
+ static void CreateFromArgs(CompilerInvocation &Res,
+ const char* const *ArgBegin,
+ const char* const *ArgEnd,
+ Diagnostic &Diags);
+
+ /// GetBuiltinIncludePath - Get the directory where the compiler headers
+ /// reside, relative to the compiler binary (found by the passed in
+ /// arguments).
+ ///
+ /// \param Argv0 - The program path (from argv[0]), for finding the builtin
+ /// compiler path.
+ /// \param MainAddr - The address of main (or some other function in the main
+ /// executable), for finding the builtin compiler path.
+ static std::string GetResourcesPath(const char *Argv0, void *MainAddr);
+
+ /// toArgs - Convert the CompilerInvocation to a list of strings suitable for
+ /// passing to CreateFromArgs.
+ void toArgs(std::vector<std::string> &Res);
+
+ /// setLangDefaults - Set language defaults for the given input language and
+ /// language standard in this CompilerInvocation.
+ ///
+ /// \param IK - The input language.
+ /// \param LangStd - The input language standard.
+ void setLangDefaults(InputKind IK,
+ LangStandard::Kind LangStd = LangStandard::lang_unspecified) {
+ setLangDefaults(LangOpts, IK, LangStd);
+ }
+
+ /// setLangDefaults - Set language defaults for the given input language and
+ /// language standard in the given LangOptions object.
+ ///
+ /// \param LangOpts - The LangOptions object to set up.
+ /// \param IK - The input language.
+ /// \param LangStd - The input language standard.
+ static void setLangDefaults(LangOptions &Opts, InputKind IK,
+ LangStandard::Kind LangStd = LangStandard::lang_unspecified);
+
+ /// @}
+ /// @name Option Subgroups
+ /// @{
+
+ AnalyzerOptions &getAnalyzerOpts() { return AnalyzerOpts; }
+ const AnalyzerOptions &getAnalyzerOpts() const {
+ return AnalyzerOpts;
+ }
+
+ CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
+ const CodeGenOptions &getCodeGenOpts() const {
+ return CodeGenOpts;
+ }
+
+ DependencyOutputOptions &getDependencyOutputOpts() {
+ return DependencyOutputOpts;
+ }
+ const DependencyOutputOptions &getDependencyOutputOpts() const {
+ return DependencyOutputOpts;
+ }
+
+ DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; }
+ const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; }
+
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const {
+ return FileSystemOpts;
+ }
+
+ HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; }
+ const HeaderSearchOptions &getHeaderSearchOpts() const {
+ return HeaderSearchOpts;
+ }
+
+ FrontendOptions &getFrontendOpts() { return FrontendOpts; }
+ const FrontendOptions &getFrontendOpts() const {
+ return FrontendOpts;
+ }
+
+ LangOptions &getLangOpts() { return LangOpts; }
+ const LangOptions &getLangOpts() const { return LangOpts; }
+
+ PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; }
+ const PreprocessorOptions &getPreprocessorOpts() const {
+ return PreprocessorOpts;
+ }
+
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() {
+ return PreprocessorOutputOpts;
+ }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
+ return PreprocessorOutputOpts;
+ }
+
+ TargetOptions &getTargetOpts() { return TargetOpts; }
+ const TargetOptions &getTargetOpts() const {
+ return TargetOpts;
+ }
+
+ /// @}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def
new file mode 100644
index 0000000..39ed5f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclContextXML.def
@@ -0,0 +1,113 @@
+//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- 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 XML context info database as written in the
+// <ReferenceSection>/<Contexts> sub-nodes of the XML document. Type nodes
+// are referred by "context" reference attributes throughout the document.
+// A context node never contains sub-nodes.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// context of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that context
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by "context" attributes to this value.
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type
+// nodes by a "type" attribute, if they create a type during declaration.
+// For instance 'struct S;' creates both a context 'S::' and a type 'S'.
+// Contexts and types always have different ids, however declarations and
+// contexts may share the same ids. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+NODE_XML(TranslationUnitDecl, "TranslationUnit")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(FunctionDecl, "Function")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType())
+END_NODE_XML
+
+NODE_XML(NamespaceDecl, "Namespace")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+END_NODE_XML
+
+NODE_XML(RecordDecl, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getTypeForDecl())
+END_NODE_XML
+
+NODE_XML(EnumDecl, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getTypeForDecl())
+END_NODE_XML
+
+NODE_XML(LinkageSpecDecl, "LinkageSpec")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
+ ENUM_XML(LinkageSpecDecl::lang_c, "C")
+ ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
+ END_ENUM_XML
+END_NODE_XML
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
new file mode 100644
index 0000000..1b158fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
@@ -0,0 +1,372 @@
+//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- 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 XML statement database structure as written in
+// <TranslationUnit> sub-nodes of the XML document.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by reference attributes to this value (currently used only for Label).
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
+// expression by a "type" attribute. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
+// a statement in the source file(s).
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ATTRIBUTE_FILE_LOCATION_XML
+# define ATTRIBUTE_FILE_LOCATION_XML \
+ ATTRIBUTE_XML(getFilename(), "file") \
+ ATTRIBUTE_XML(getLine(), "line") \
+ ATTRIBUTE_XML(getColumn(), "col") \
+ ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
+ ATTRIBUTE_OPT_XML(getLine(), "endline") \
+ ATTRIBUTE_OPT_XML(getColumn(), "endcol")
+#endif
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+//NODE_XML(TranslationUnitDecl, "TranslationUnit")
+// SUB_NODE_SEQUENCE_XML(Decl)
+//END_NODE_XML
+
+NODE_XML(Decl, "FIXME_Decl")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclKindName(), "unhandled_decl_name")
+END_NODE_XML
+
+NODE_XML(FunctionDecl, "Function")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
+ ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
+ ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
+ END_ENUM_XML
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
+ //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ ATTRIBUTE_OPT_XML(isMain(), "main")
+ ATTRIBUTE_OPT_XML(isExternC(), "externc")
+ ATTRIBUTE_OPT_XML(isGlobal(), "global")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ SUB_NODE_FN_BODY_XML
+END_NODE_XML
+
+NODE_XML(CXXMethodDecl, "CXXMethod")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
+ ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
+ ATTRIBUTE_OPT_XML(isStatic(), "static")
+ ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_OPT_XML(isPure(), "pure")
+ ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
+ ENUM_XML(AS_none, "")
+ ENUM_XML(AS_public, "public")
+ ENUM_XML(AS_protected, "protected")
+ ENUM_XML(AS_private, "private")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ SUB_NODE_FN_BODY_XML
+END_NODE_XML
+
+NODE_XML(CXXConstructorDecl, "CXXConstructor")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
+ ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
+ ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit")
+ ATTRIBUTE_OPT_XML(isDefaultConstructor(), "is_default_ctor")
+ ATTRIBUTE_OPT_XML(isCopyConstructor(), "is_copy_ctor")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
+ ATTRIBUTE_OPT_XML(isStatic(), "static")
+ ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
+ ENUM_XML(AS_none, "")
+ ENUM_XML(AS_public, "public")
+ ENUM_XML(AS_protected, "protected")
+ ENUM_XML(AS_private, "private")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ SUB_NODE_FN_BODY_XML
+END_NODE_XML
+
+NODE_XML(CXXDestructorDecl, "CXXDestructor")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
+ ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
+ ATTRIBUTE_OPT_XML(isStatic(), "static")
+ ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
+ ENUM_XML(AS_none, "")
+ ENUM_XML(AS_public, "public")
+ ENUM_XML(AS_protected, "protected")
+ ENUM_XML(AS_private, "private")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ SUB_NODE_FN_BODY_XML
+END_NODE_XML
+
+NODE_XML(CXXConversionDecl, "CXXConversion")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
+ ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
+ ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit")
+ ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
+ ATTRIBUTE_OPT_XML(isStatic(), "static")
+ ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
+ ENUM_XML(AS_none, "")
+ ENUM_XML(AS_public, "public")
+ ENUM_XML(AS_protected, "protected")
+ ENUM_XML(AS_private, "private")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ SUB_NODE_FN_BODY_XML
+END_NODE_XML
+
+NODE_XML(NamespaceDecl, "Namespace")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ SUB_NODE_SEQUENCE_XML(DeclContext)
+END_NODE_XML
+
+NODE_XML(UsingDirectiveDecl, "UsingDirective")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_XML(getNominatedNamespace(), "ref")
+END_NODE_XML
+
+NODE_XML(NamespaceAliasDecl, "NamespaceAlias")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_XML(getNamespace(), "ref")
+END_NODE_XML
+
+NODE_XML(RecordDecl, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
+ ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
+ SUB_NODE_SEQUENCE_XML(FieldDecl)
+END_NODE_XML
+
+NODE_XML(CXXRecordDecl, "CXXRecord")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
+ ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
+ SUB_NODE_SEQUENCE_XML(FieldDecl)
+END_NODE_XML
+
+NODE_XML(EnumDecl, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
+ ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling
+ SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition
+END_NODE_XML
+
+NODE_XML(EnumConstantDecl, "EnumConstant")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer
+ SUB_NODE_OPT_XML(Expr) // init expr of this constant
+END_NODE_XML
+
+NODE_XML(FieldDecl, "Field")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_OPT_XML(isMutable(), "mutable")
+ ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access")
+ ENUM_XML(AS_none, "")
+ ENUM_XML(AS_public, "public")
+ ENUM_XML(AS_protected, "protected")
+ ENUM_XML(AS_private, "private")
+ END_ENUM_XML
+ ATTRIBUTE_OPT_XML(isBitField(), "bitfield")
+ SUB_NODE_OPT_XML(Expr) // init expr of a bit field
+END_NODE_XML
+
+NODE_XML(TypedefDecl, "Typedef")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getUnderlyingType())
+END_NODE_XML
+
+NODE_XML(VarDecl, "Var")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Auto, "auto")
+ ENUM_XML(SC_Register, "register")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
+ END_ENUM_XML
+ SUB_NODE_OPT_XML(Expr) // init expr
+END_NODE_XML
+
+NODE_XML(ParmVarDecl, "ParmVar")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_OPT_XML(Expr) // default argument expression
+END_NODE_XML
+
+NODE_XML(LinkageSpecDecl, "LinkageSpec")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
+ ENUM_XML(LinkageSpecDecl::lang_c, "C")
+ ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
+ END_ENUM_XML
+ SUB_NODE_XML(DeclContext)
+END_NODE_XML
+
+NODE_XML(TemplateDecl, "Template")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+END_NODE_XML
+
+NODE_XML(TemplateTypeParmDecl, "TemplateTypeParm")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+END_NODE_XML
+
+NODE_XML(UsingShadowDecl, "UsingShadow")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getTargetDecl(), "target_decl")
+ ATTRIBUTE_XML(getUsingDecl(), "using_decl")
+END_NODE_XML
+
+NODE_XML(UsingDecl, "Using")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl")
+ ATTRIBUTE_XML(isTypeName(), "is_typename")
+END_NODE_XML
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
+#undef SUB_NODE_FN_BODY_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
new file mode 100644
index 0000000..35aa6c6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
@@ -0,0 +1,51 @@
+//===--- DependencyOutputOptions.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// DependencyOutputOptions - Options for controlling the compiler dependency
+/// file generation.
+class DependencyOutputOptions {
+public:
+ unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies.
+ unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
+ unsigned UsePhonyTargets : 1; ///< Include phony targets for each
+ /// dependency, which can avoid some 'make'
+ /// problems.
+
+ /// The file to write dependency output to.
+ std::string OutputFile;
+
+ /// The file to write header include output to. This is orthogonal to
+ /// ShowHeaderIncludes (-H) and will include headers mentioned in the
+ /// predefines buffer. If the output file is "-", output will be sent to
+ /// stderr.
+ std::string HeaderIncludeOutputFile;
+
+ /// A list of names to use as the targets in the dependency file; this list
+ /// must contain at least one entry.
+ std::vector<std::string> Targets;
+
+public:
+ DependencyOutputOptions() {
+ IncludeSystemHeaders = 0;
+ ShowHeaderIncludes = 0;
+ UsePhonyTargets = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h
new file mode 100644
index 0000000..f7f498b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticOptions.h
@@ -0,0 +1,94 @@
+//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
+
+#include "clang/Basic/Diagnostic.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// DiagnosticOptions - Options for controlling the compiler diagnostics
+/// engine.
+class DiagnosticOptions {
+public:
+ unsigned IgnoreWarnings : 1; /// -w
+ unsigned NoRewriteMacros : 1; /// -Wno-rewrite-macros
+ unsigned Pedantic : 1; /// -pedantic
+ unsigned PedanticErrors : 1; /// -pedantic-errors
+ unsigned ShowColumn : 1; /// Show column number on diagnostics.
+ unsigned ShowLocation : 1; /// Show source location information.
+ unsigned ShowCarets : 1; /// Show carets in diagnostics.
+ unsigned ShowFixits : 1; /// Show fixit information.
+ unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
+ unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its.
+ unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
+ /// diagnostics.
+ unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number,
+ /// 2 -> Full Name.
+ unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
+ unsigned ShowOverloads : 1; /// Overload candidates to show. Values from
+ /// Diagnostic::OverloadsShown
+ unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected
+ /// diagnostics, indicated by markers in the
+ /// input source file.
+
+ unsigned ErrorLimit; /// Limit # errors emitted.
+ unsigned MacroBacktraceLimit; /// Limit depth of macro instantiation
+ /// backtrace.
+ unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace.
+
+ /// The distance between tab stops.
+ unsigned TabStop;
+ enum { DefaultTabStop = 8, MaxTabStop = 100,
+ DefaultMacroBacktraceLimit = 6,
+ DefaultTemplateBacktraceLimit = 10 };
+
+ /// Column limit for formatting message diagnostics, or 0 if unused.
+ unsigned MessageLength;
+
+ /// If non-empty, a file to log extended build information to, for development
+ /// testing and analysis.
+ std::string DumpBuildInformation;
+
+ /// The list of -W... options used to alter the diagnostic mappings, with the
+ /// prefixes removed.
+ std::vector<std::string> Warnings;
+
+public:
+ DiagnosticOptions() {
+ IgnoreWarnings = 0;
+ TabStop = DefaultTabStop;
+ MessageLength = 0;
+ NoRewriteMacros = 0;
+ Pedantic = 0;
+ PedanticErrors = 0;
+ ShowCarets = 1;
+ ShowColors = 0;
+ ShowOverloads = Diagnostic::Ovl_All;
+ ShowColumn = 1;
+ ShowFixits = 1;
+ ShowLocation = 1;
+ ShowOptionNames = 0;
+ ShowCategories = 0;
+ ShowSourceRanges = 0;
+ ShowParseableFixits = 0;
+ VerifyDiagnostics = 0;
+ ErrorLimit = 0;
+ TemplateBacktraceLimit = DefaultTemplateBacktraceLimit;
+ MacroBacktraceLimit = DefaultMacroBacktraceLimit;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def
new file mode 100644
index 0000000..4c52bd8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.def
@@ -0,0 +1,75 @@
+//===-- DocumentXML.def - Metadata about Document XML nodes -----*- 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 XML root database structure as written in
+// an AST XML document.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a
+// string, which value uniquely identify the entity represented by that node.
+// Other nodes may refer by reference attributes to this value.
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+ROOT_NODE_XML("CLANG_XML")
+ ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed
+ SUB_NODE_XML("TranslationUnit")
+ SUB_NODE_XML("ReferenceSection")
+END_NODE_XML
+
+NODE_XML("TranslationUnit")
+ SUB_NODE_SEQUENCE_XML(Decl)
+END_NODE_XML
+
+NODE_XML("ReferenceSection")
+ SUB_NODE_XML("Types")
+ SUB_NODE_XML("Contexts")
+ SUB_NODE_XML("Files")
+END_NODE_XML
+
+NODE_XML("Types")
+ SUB_NODE_SEQUENCE_XML(Type)
+END_NODE_XML
+
+NODE_XML("Contexts")
+ SUB_NODE_SEQUENCE_XML(DeclContext)
+END_NODE_XML
+
+NODE_XML("Files")
+ SUB_NODE_SEQUENCE_XML("File")
+END_NODE_XML
+
+NODE_XML("File")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name
+END_NODE_XML
+
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h
new file mode 100644
index 0000000..602d846
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DocumentXML.h
@@ -0,0 +1,185 @@
+//===--- DocumentXML.h - XML document for ASTs ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+
+#include <string>
+#include <map>
+#include <stack>
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class DeclContext;
+class Decl;
+class NamedDecl;
+class FunctionDecl;
+class ASTContext;
+class LabelStmt;
+
+//---------------------------------------------------------
+namespace XML {
+ // id maps:
+ template<class T>
+ struct IdMap : llvm::DenseMap<T, unsigned> {};
+
+ template<>
+ struct IdMap<QualType> : std::map<QualType, unsigned, QualTypeOrdering> {};
+
+ template<>
+ struct IdMap<std::string> : std::map<std::string, unsigned> {};
+}
+
+//---------------------------------------------------------
+class DocumentXML {
+public:
+ DocumentXML(const std::string& rootName, llvm::raw_ostream& out);
+
+ void initialize(ASTContext &Context);
+ void PrintDecl(Decl *D);
+ void PrintStmt(const Stmt *S); // defined in StmtXML.cpp
+ void finalize();
+
+
+ DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this
+ DocumentXML& toParent(); // returns *this
+
+ void addAttribute(const char* pName, const QualType& pType);
+ void addAttribute(const char* pName, bool value);
+
+ template<class T>
+ void addAttribute(const char* pName, const T* value) {
+ addPtrAttribute(pName, value);
+ }
+
+ template<class T>
+ void addAttribute(const char* pName, T* value) {
+ addPtrAttribute(pName, value);
+ }
+
+ template<class T>
+ void addAttribute(const char* pName, const T& value);
+
+ template<class T>
+ void addAttributeOptional(const char* pName, const T& value);
+
+ void addSourceFileAttribute(const std::string& fileName);
+
+ PresumedLoc addLocation(const SourceLocation& Loc);
+ void addLocationRange(const SourceRange& R);
+
+ static std::string escapeString(const char* pStr, std::string::size_type len);
+
+private:
+ DocumentXML(const DocumentXML&); // not defined
+ DocumentXML& operator=(const DocumentXML&); // not defined
+
+ std::stack<std::string> NodeStack;
+ llvm::raw_ostream& Out;
+ ASTContext *Ctx;
+ bool HasCurrentNodeSubNodes;
+
+
+ XML::IdMap<QualType> Types;
+ XML::IdMap<const DeclContext*> Contexts;
+ XML::IdMap<const Type*> BasicTypes;
+ XML::IdMap<std::string> SourceFiles;
+ XML::IdMap<const NamedDecl*> Decls;
+ XML::IdMap<const LabelStmt*> Labels;
+
+ void addContextsRecursively(const DeclContext *DC);
+ void addTypeRecursively(const Type* pType);
+ void addTypeRecursively(const QualType& pType);
+
+ void Indent();
+
+ // forced pointer dispatch:
+ void addPtrAttribute(const char* pName, const Type* pType);
+ void addPtrAttribute(const char* pName, const NamedDecl* D);
+ void addPtrAttribute(const char* pName, const DeclContext* D);
+ void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation
+ void addPtrAttribute(const char* pName, const NestedNameSpecifier* N);
+ void addPtrAttribute(const char* pName, const LabelStmt* L);
+ void addPtrAttribute(const char* pName, const char* text);
+
+ // defined in TypeXML.cpp:
+ void addParentTypes(const Type* pType);
+ void writeTypeToXML(const Type* pType);
+ void writeTypeToXML(const QualType& pType);
+ class TypeAdder;
+ friend class TypeAdder;
+
+ // defined in DeclXML.cpp:
+ void writeDeclToXML(Decl *D);
+ class DeclPrinter;
+ friend class DeclPrinter;
+
+ // for addAttributeOptional:
+ static bool isDefault(unsigned value) { return value == 0; }
+ static bool isDefault(bool value) { return !value; }
+ static bool isDefault(Qualifiers::GC value) { return value == Qualifiers::GCNone; }
+ static bool isDefault(const std::string& value) { return value.empty(); }
+};
+
+//--------------------------------------------------------- inlines
+
+inline void DocumentXML::initialize(ASTContext &Context) {
+ Ctx = &Context;
+}
+
+//---------------------------------------------------------
+template<class T>
+inline void DocumentXML::addAttribute(const char* pName, const T& value) {
+ std::string repr;
+ {
+ llvm::raw_string_ostream buf(repr);
+ buf << value;
+ }
+
+ Out << ' ' << pName << "=\""
+ << DocumentXML::escapeString(repr.c_str(), repr.size())
+ << "\"";
+}
+
+//---------------------------------------------------------
+inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) {
+ Out << ' ' << pName << "=\""
+ << DocumentXML::escapeString(text, strlen(text))
+ << "\"";
+}
+
+//---------------------------------------------------------
+inline void DocumentXML::addAttribute(const char* pName, bool value) {
+ addPtrAttribute(pName, value ? "1" : "0");
+}
+
+//---------------------------------------------------------
+template<class T>
+inline void DocumentXML::addAttributeOptional(const char* pName,
+ const T& value) {
+ if (!isDefault(value)) {
+ addAttribute(pName, value);
+ }
+}
+
+//---------------------------------------------------------
+
+} //namespace clang
+
+#endif //LLVM_CLANG_DOCUMENTXML_H
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
new file mode 100644
index 0000000..ee0863a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
@@ -0,0 +1,258 @@
+//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+class ASTConsumer;
+class ASTMergeAction;
+class ASTUnit;
+class CompilerInstance;
+
+enum InputKind {
+ IK_None,
+ IK_Asm,
+ IK_C,
+ IK_CXX,
+ IK_ObjC,
+ IK_ObjCXX,
+ IK_PreprocessedC,
+ IK_PreprocessedCXX,
+ IK_PreprocessedObjC,
+ IK_PreprocessedObjCXX,
+ IK_OpenCL,
+ IK_CUDA,
+ IK_AST,
+ IK_LLVM_IR
+};
+
+
+/// FrontendAction - Abstract base class for actions which can be performed by
+/// the frontend.
+class FrontendAction {
+ std::string CurrentFile;
+ InputKind CurrentFileKind;
+ llvm::OwningPtr<ASTUnit> CurrentASTUnit;
+ CompilerInstance *Instance;
+ friend class ASTMergeAction;
+
+private:
+ ASTConsumer* CreateWrappedASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+protected:
+ /// @name Implementation Action Interface
+ /// @{
+
+ /// CreateASTConsumer - Create the AST consumer object for this action, if
+ /// supported.
+ ///
+ /// This routine is called as part of \see BeginSourceAction(), which will
+ /// fail if the AST consumer cannot be created. This will not be called if the
+ /// action has indicated that it only uses the preprocessor.
+ ///
+ /// \param CI - The current compiler instance, provided as a convenience, \see
+ /// getCompilerInstance().
+ ///
+ /// \param InFile - The current input file, provided as a convenience, \see
+ /// getCurrentFile().
+ ///
+ /// \return The new AST consumer, or 0 on failure.
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) = 0;
+
+ /// BeginSourceFileAction - Callback at the start of processing a single
+ /// input.
+ ///
+ /// \return True on success; on failure \see ExecutionAction() and
+ /// EndSourceFileAction() will not be called.
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ return true;
+ }
+
+ /// ExecuteAction - Callback to run the program action, using the initialized
+ /// compiler instance.
+ ///
+ /// This routine is guaranteed to only be called between \see
+ /// BeginSourceFileAction() and \see EndSourceFileAction().
+ virtual void ExecuteAction() = 0;
+
+ /// EndSourceFileAction - Callback at the end of processing a single input;
+ /// this is guaranteed to only be called following a successful call to
+ /// BeginSourceFileAction (and BeingSourceFile).
+ virtual void EndSourceFileAction() {}
+
+ /// @}
+
+public:
+ FrontendAction();
+ virtual ~FrontendAction();
+
+ /// @name Compiler Instance Access
+ /// @{
+
+ CompilerInstance &getCompilerInstance() const {
+ assert(Instance && "Compiler instance not registered!");
+ return *Instance;
+ }
+
+ void setCompilerInstance(CompilerInstance *Value) { Instance = Value; }
+
+ /// @}
+ /// @name Current File Information
+ /// @{
+
+ bool isCurrentFileAST() const {
+ assert(!CurrentFile.empty() && "No current file!");
+ return CurrentASTUnit != 0;
+ }
+
+ const std::string &getCurrentFile() const {
+ assert(!CurrentFile.empty() && "No current file!");
+ return CurrentFile;
+ }
+
+ InputKind getCurrentFileKind() const {
+ assert(!CurrentFile.empty() && "No current file!");
+ return CurrentFileKind;
+ }
+
+ ASTUnit &getCurrentASTUnit() const {
+ assert(CurrentASTUnit && "No current AST unit!");
+ return *CurrentASTUnit;
+ }
+
+ ASTUnit *takeCurrentASTUnit() {
+ return CurrentASTUnit.take();
+ }
+
+ void setCurrentFile(llvm::StringRef Value, InputKind Kind, ASTUnit *AST = 0);
+
+ /// @}
+ /// @name Supported Modes
+ /// @{
+
+ /// usesPreprocessorOnly - Does this action only use the preprocessor? If so
+ /// no AST context will be created and this action will be invalid with AST
+ /// file inputs.
+ virtual bool usesPreprocessorOnly() const = 0;
+
+ /// usesCompleteTranslationUnit - For AST based actions, should the
+ /// translation unit be completed?
+ virtual bool usesCompleteTranslationUnit() { return true; }
+
+ /// hasPCHSupport - Does this action support use with PCH?
+ virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); }
+
+ /// hasASTFileSupport - Does this action support use with AST files?
+ virtual bool hasASTFileSupport() const { return !usesPreprocessorOnly(); }
+
+ /// hasIRSupport - Does this action support use with IR files?
+ virtual bool hasIRSupport() const { return false; }
+
+ /// hasCodeCompletionSupport - Does this action support use with code
+ /// completion?
+ virtual bool hasCodeCompletionSupport() const { return false; }
+
+ /// @}
+ /// @name Public Action Interface
+ /// @{
+
+ /// BeginSourceFile - Prepare the action for processing the input file \arg
+ /// Filename; this is run after the options and frontend have been
+ /// initialized, but prior to executing any per-file processing.
+ ///
+ /// \param CI - The compiler instance this action is being run from. The
+ /// action may store and use this object up until the matching EndSourceFile
+ /// action.
+ ///
+ /// \param Filename - The input filename, which will be made available to
+ /// clients via \see getCurrentFile().
+ ///
+ /// \param InputKind - The type of input. Some input kinds are handled
+ /// specially, for example AST inputs, since the AST file itself contains
+ /// several objects which would normally be owned by the
+ /// CompilerInstance. When processing AST input files, these objects should
+ /// generally not be initialized in the CompilerInstance -- they will
+ /// automatically be shared with the AST file in between \see
+ /// BeginSourceFile() and \see EndSourceFile().
+ ///
+ /// \return True on success; the compilation of this file should be aborted
+ /// and neither Execute nor EndSourceFile should be called.
+ bool BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename,
+ InputKind Kind);
+
+ /// Execute - Set the source managers main input file, and run the action.
+ void Execute();
+
+ /// EndSourceFile - Perform any per-file post processing, deallocate per-file
+ /// objects, and run statistics and output file cleanup code.
+ void EndSourceFile();
+
+ /// @}
+};
+
+/// ASTFrontendAction - Abstract base class to use for AST consumer based
+/// frontend actions.
+class ASTFrontendAction : public FrontendAction {
+protected:
+ /// ExecuteAction - Implement the ExecuteAction interface by running Sema on
+ /// the already initialized AST consumer.
+ ///
+ /// This will also take care of instantiating a code completion consumer if
+ /// the user requested it and the action supports it.
+ virtual void ExecuteAction();
+
+public:
+ virtual bool usesPreprocessorOnly() const { return false; }
+};
+
+class PluginASTAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) = 0;
+
+public:
+ /// ParseArgs - Parse the given plugin command line arguments.
+ ///
+ /// \param CI - The compiler instance, for use in reporting diagnostics.
+ /// \return True if the parsing succeeded; otherwise the plugin will be
+ /// destroyed and no action run. The plugin is responsible for using the
+ /// CompilerInstance's Diagnostic object to report errors.
+ virtual bool ParseArgs(const CompilerInstance &CI,
+ const std::vector<std::string> &arg) = 0;
+};
+
+/// PreprocessorFrontendAction - Abstract base class to use for preprocessor
+/// based frontend actions.
+class PreprocessorFrontendAction : public FrontendAction {
+protected:
+ /// CreateASTConsumer - Provide a default implementation which returns aborts,
+ /// this method should never be called by FrontendAction clients.
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+public:
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
new file mode 100644
index 0000000..4df2e71
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
@@ -0,0 +1,192 @@
+//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H
+#define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// Custom Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class InitOnlyAction : public FrontendAction {
+ virtual void ExecuteAction();
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+public:
+ // Don't claim to only use the preprocessor, we want to follow the AST path,
+ // but do nothing.
+ virtual bool usesPreprocessorOnly() const { return false; }
+};
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class ASTPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTPrintXMLAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTDumpAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTDumpXMLAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class ASTViewAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class DeclContextPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class GeneratePCHAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual bool usesCompleteTranslationUnit() { return false; }
+
+ virtual bool hasASTFileSupport() const { return false; }
+
+public:
+ /// \brief Compute the AST consumer arguments that will be used to
+ /// create the PCHGenerator instance returned by CreateASTConsumer.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ static bool ComputeASTConsumerArguments(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ std::string &Sysroot,
+ std::string &OutputFile,
+ llvm::raw_ostream *&OS,
+ bool &Chaining);
+};
+
+class SyntaxOnlyAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+public:
+ virtual bool hasCodeCompletionSupport() const { return true; }
+};
+
+class BoostConAction : public SyntaxOnlyAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+/**
+ * \brief Frontend action adaptor that merges ASTs together.
+ *
+ * This action takes an existing AST file and "merges" it into the AST
+ * context, producing a merged context. This action is an action
+ * adaptor, which forwards most of its calls to another action that
+ * will consume the merged context.
+ */
+class ASTMergeAction : public FrontendAction {
+ /// \brief The action that the merge action adapts.
+ FrontendAction *AdaptedAction;
+
+ /// \brief The set of AST files to merge.
+ std::vector<std::string> ASTFiles;
+
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename);
+
+ virtual void ExecuteAction();
+ virtual void EndSourceFileAction();
+
+public:
+ ASTMergeAction(FrontendAction *AdaptedAction,
+ std::string *ASTFiles, unsigned NumASTFiles);
+ virtual ~ASTMergeAction();
+
+ virtual bool usesPreprocessorOnly() const;
+ virtual bool usesCompleteTranslationUnit();
+ virtual bool hasPCHSupport() const;
+ virtual bool hasASTFileSupport() const;
+ virtual bool hasCodeCompletionSupport() const;
+};
+
+class PrintPreambleAction : public FrontendAction {
+protected:
+ void ExecuteAction();
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, llvm::StringRef) {
+ return 0;
+ }
+
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+class DumpRawTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class DumpTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class GeneratePTHAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class PreprocessOnlyAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class PrintPreprocessedAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+
+ virtual bool hasPCHSupport() const { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h
new file mode 100644
index 0000000..2efbc81
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticFrontend.h - Diagnostics for frontend --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTENDDIAGNOSTIC_H
+#define LLVM_CLANG_FRONTENDDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define FRONTENDSTART
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_FRONTEND_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
new file mode 100644
index 0000000..19d39c3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -0,0 +1,147 @@
+//===--- FrontendOptions.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
+#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
+
+#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+ enum ActionKind {
+ ASTDump, ///< Parse ASTs and dump them.
+ ASTDumpXML, ///< Parse ASTs and dump them in XML.
+ ASTPrint, ///< Parse ASTs and print them.
+ ASTPrintXML, ///< Parse ASTs and print them in XML.
+ ASTView, ///< Parse ASTs and view them in Graphviz.
+ BoostCon, ///< BoostCon mode.
+ CreateModule, ///< Create module definition
+ DumpRawTokens, ///< Dump out raw tokens.
+ DumpTokens, ///< Dump out preprocessed tokens.
+ EmitAssembly, ///< Emit a .s file.
+ EmitBC, ///< Emit a .bc file.
+ EmitHTML, ///< Translate input source into HTML.
+ EmitLLVM, ///< Emit a .ll file.
+ EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything.
+ EmitCodeGenOnly, ///< Generate machine code, but don't emit anything.
+ EmitObj, ///< Emit a .o file.
+ FixIt, ///< Parse and apply any fixits to the source.
+ GeneratePCH, ///< Generate pre-compiled header.
+ GeneratePTH, ///< Generate pre-tokenized header.
+ InitOnly, ///< Only execute frontend initialization.
+ ParseSyntaxOnly, ///< Parse and perform semantic analysis.
+ PluginAction, ///< Run a plugin action, \see ActionName.
+ PrintDeclContext, ///< Print DeclContext and their Decls.
+ PrintPreamble, ///< Print the "preamble" of the input file
+ PrintPreprocessedInput, ///< -E mode.
+ RewriteMacros, ///< Expand macros but not #includes.
+ RewriteObjC, ///< ObjC->C Rewriter.
+ RewriteTest, ///< Rewriter playground
+ RunAnalysis, ///< Run one or more source code analyses.
+ RunPreprocessorOnly ///< Just lex, no output.
+ };
+}
+
+/// FrontendOptions - Options for controlling the behavior of the frontend.
+class FrontendOptions {
+public:
+ unsigned DisableFree : 1; ///< Disable memory freeing on exit.
+ unsigned RelocatablePCH : 1; ///< When generating PCH files,
+ /// instruct the AST writer to create
+ /// relocatable PCH files.
+ unsigned ChainedPCH : 1; ///< When generating PCH files,
+ /// instruct the AST writer to create
+ /// chained PCH files.
+ unsigned ShowHelp : 1; ///< Show the -help text.
+ unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
+ /// results.
+ unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code
+ /// completion results.
+ unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in
+ /// code completion results.
+ unsigned ShowStats : 1; ///< Show frontend performance
+ /// metrics and statistics.
+ unsigned ShowTimers : 1; ///< Show timers for individual
+ /// actions.
+ unsigned ShowVersion : 1; ///< Show the -version text.
+ unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
+ /// unfixable errors.
+
+ /// The input files and their types.
+ std::vector<std::pair<InputKind, std::string> > Inputs;
+
+ /// The output file, if any.
+ std::string OutputFile;
+
+ /// If given, the new suffix for fix-it rewritten files.
+ std::string FixItSuffix;
+
+ /// If given, enable code completion at the provided location.
+ ParsedSourceLocation CodeCompletionAt;
+
+ /// The frontend action to perform.
+ frontend::ActionKind ProgramAction;
+
+ /// The name of the action to run when using a plugin action.
+ std::string ActionName;
+
+ /// Args to pass to the plugin
+ std::vector<std::string> PluginArgs;
+
+ /// The list of plugin actions to run in addition to the normal action.
+ std::vector<std::string> AddPluginActions;
+
+ /// Args to pass to the additional plugins
+ std::vector<std::vector<std::string> > AddPluginArgs;
+
+ /// The list of plugins to load.
+ std::vector<std::string> Plugins;
+
+ /// \brief The list of AST files to merge.
+ std::vector<std::string> ASTMergeFiles;
+
+ /// \brief The list of modules to import.
+ std::vector<std::string> Modules;
+
+ /// \brief A list of arguments to forward to LLVM's option processing; this
+ /// should only be used for debugging and experimental features.
+ std::vector<std::string> LLVMArgs;
+
+public:
+ FrontendOptions() {
+ DisableFree = 0;
+ ProgramAction = frontend::ParseSyntaxOnly;
+ ActionName = "";
+ RelocatablePCH = 0;
+ ChainedPCH = 0;
+ ShowHelp = 0;
+ ShowMacrosInCodeCompletion = 0;
+ ShowCodePatternsInCodeCompletion = 0;
+ ShowGlobalSymbolsInCodeCompletion = 1;
+ ShowStats = 0;
+ ShowTimers = 0;
+ ShowVersion = 0;
+ }
+
+ /// getInputKindForExtension - Return the appropriate input kind for a file
+ /// extension. For example, "c" would return IK_C.
+ ///
+ /// \return The input kind for the extension, or IK_None if the extension is
+ /// not recognized.
+ static InputKind getInputKindForExtension(llvm::StringRef Extension);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
new file mode 100644
index 0000000..ec925ad
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
@@ -0,0 +1,23 @@
+//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
+#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+
+/// The frontend plugin registry.
+typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry;
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
new file mode 100644
index 0000000..cbb4a57
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
@@ -0,0 +1,104 @@
+//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H
+#define LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H
+
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+ /// IncludeDirGroup - Identifiers the group a include entry belongs to, which
+ /// represents its relative positive in the search list.
+ enum IncludeDirGroup {
+ Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`.
+ Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`)
+ System, ///< Like Angled, but marks system directories.
+ After ///< Like System, but searched after the system directories.
+ };
+}
+
+/// HeaderSearchOptions - Helper class for storing options related to the
+/// initialization of the HeaderSearch object.
+class HeaderSearchOptions {
+public:
+ struct Entry {
+ std::string Path;
+ frontend::IncludeDirGroup Group;
+ unsigned IsUserSupplied : 1;
+ unsigned IsFramework : 1;
+
+ /// IsSysRootRelative - This is true if an absolute path should be treated
+ /// relative to the sysroot, or false if it should always be the absolute
+ /// path.
+ unsigned IsSysRootRelative : 1;
+
+ Entry(llvm::StringRef path, frontend::IncludeDirGroup group,
+ bool isUserSupplied, bool isFramework, bool isSysRootRelative)
+ : Path(path), Group(group), IsUserSupplied(isUserSupplied),
+ IsFramework(isFramework), IsSysRootRelative(isSysRootRelative) {}
+ };
+
+ /// If non-empty, the directory to use as a "virtual system root" for include
+ /// paths.
+ std::string Sysroot;
+
+ /// User specified include entries.
+ std::vector<Entry> UserEntries;
+
+ /// If non-empty, the list of C++ standard include paths to use.
+ std::vector<std::string> CXXSystemIncludes;
+
+ /// A (system-path) delimited list of include paths to be added from the
+ /// environment following the user specified includes (but prior to builtin
+ /// and standard includes). This is parsed in the same manner as the CPATH
+ /// environment variable for gcc.
+ std::string EnvIncPath;
+
+ /// Per-language environmental include paths, see \see EnvIncPath.
+ std::string CEnvIncPath;
+ std::string ObjCEnvIncPath;
+ std::string CXXEnvIncPath;
+ std::string ObjCXXEnvIncPath;
+
+ /// The directory which holds the compiler resource files (builtin includes,
+ /// etc.).
+ std::string ResourceDir;
+
+ /// Include the compiler builtin includes.
+ unsigned UseBuiltinIncludes : 1;
+
+ /// Include the system standard include search directories.
+ unsigned UseStandardIncludes : 1;
+
+ /// Include the system standard C++ library include search directories.
+ unsigned UseStandardCXXIncludes : 1;
+
+ /// Whether header search information should be output as for -v.
+ unsigned Verbose : 1;
+
+public:
+ HeaderSearchOptions(llvm::StringRef _Sysroot = "/")
+ : Sysroot(_Sysroot), UseBuiltinIncludes(true),
+ UseStandardIncludes(true), UseStandardCXXIncludes(true),
+ Verbose(false) {}
+
+ /// AddPath - Add the \arg Path path to the specified \arg Group list.
+ void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group,
+ bool IsUserSupplied, bool IsFramework, bool IsSysRootRelative) {
+ UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework,
+ IsSysRootRelative));
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
new file mode 100644
index 0000000..441d34f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
@@ -0,0 +1,83 @@
+//===--- LangStandard.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_LANGSTANDARD_H
+#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+namespace frontend {
+
+enum LangFeatures {
+ BCPLComment = (1 << 0),
+ C99 = (1 << 1),
+ CPlusPlus = (1 << 2),
+ CPlusPlus0x = (1 << 3),
+ Digraphs = (1 << 4),
+ GNUMode = (1 << 5),
+ HexFloat = (1 << 6),
+ ImplicitInt = (1 << 7)
+};
+
+}
+
+/// LangStandard - Information about the properties of a particular language
+/// standard.
+struct LangStandard {
+ enum Kind {
+#define LANGSTANDARD(id, name, desc, features) \
+ lang_##id,
+#include "clang/Frontend/LangStandards.def"
+ lang_unspecified
+ };
+
+ const char *ShortName;
+ const char *Description;
+ unsigned Flags;
+
+public:
+ /// getName - Get the name of this standard.
+ const char *getName() const { return ShortName; }
+
+ /// getDescription - Get the description of this standard.
+ const char *getDescription() const { return Description; }
+
+ /// hasBCPLComments - Language supports '//' comments.
+ bool hasBCPLComments() const { return Flags & frontend::BCPLComment; }
+
+ /// isC99 - Language is a superset of C99.
+ bool isC99() const { return Flags & frontend::C99; }
+
+ /// isCPlusPlus - Language is a C++ variant.
+ bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
+
+ /// isCPlusPlus0x - Language is a C++0x variant.
+ bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; }
+
+ /// hasDigraphs - Language supports digraphs.
+ bool hasDigraphs() const { return Flags & frontend::Digraphs; }
+
+ /// isGNUMode - Language includes GNU extensions.
+ bool isGNUMode() const { return Flags & frontend::GNUMode; }
+
+ /// hasHexFloats - Language supports hexadecimal float constants.
+ bool hasHexFloats() const { return Flags & frontend::HexFloat; }
+
+ /// hasImplicitInt - Language allows variables to be typed as int implicitly.
+ bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; }
+
+ static const LangStandard &getLangStandardForKind(Kind K);
+ static const LangStandard *getLangStandardForName(llvm::StringRef Name);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
new file mode 100644
index 0000000..d4046b3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
@@ -0,0 +1,88 @@
+//===-- LangStandards.def - Language Standard Data --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LANGSTANDARD
+#error "LANGSTANDARD must be defined before including this file"
+#endif
+
+/// LANGSTANDARD(IDENT, NAME, DESC, FEATURES)
+///
+/// \param IDENT - The name of the standard as a C++ identifier.
+/// \param NAME - The name of the standard.
+/// \param DESC - A short description of the standard.
+/// \param FEATURES - The standard features as flags, these are enums from the
+/// clang::frontend namespace, which is assumed to be be available.
+
+// C89-ish modes.
+LANGSTANDARD(c89, "c89",
+ "ISO C 1990",
+ ImplicitInt)
+LANGSTANDARD(c90, "c90",
+ "ISO C 1990",
+ ImplicitInt)
+LANGSTANDARD(iso9899_1990, "iso9899:1990",
+ "ISO C 1990",
+ ImplicitInt)
+
+LANGSTANDARD(c94, "iso9899:199409",
+ "ISO C 1990 with amendment 1",
+ Digraphs | ImplicitInt)
+
+LANGSTANDARD(gnu89, "gnu89",
+ "ISO C 1990 with GNU extensions",
+ BCPLComment | Digraphs | GNUMode | ImplicitInt)
+
+// C99-ish modes
+LANGSTANDARD(c99, "c99",
+ "ISO C 1999",
+ BCPLComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(c9x, "c9x",
+ "ISO C 1999",
+ BCPLComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_1999,
+ "iso9899:1999", "ISO C 1999",
+ BCPLComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_199x,
+ "iso9899:199x", "ISO C 1999",
+ BCPLComment | C99 | Digraphs | HexFloat)
+
+LANGSTANDARD(gnu99, "gnu99",
+ "ISO C 1999 with GNU extensions",
+ BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs)
+LANGSTANDARD(gnu9x, "gnu9x",
+ "ISO C 1999 with GNU extensions",
+ BCPLComment | C99 | Digraphs | GNUMode | HexFloat)
+
+// C++ modes
+LANGSTANDARD(cxx98, "c++98",
+ "ISO C++ 1998 with amendments",
+ BCPLComment | CPlusPlus | Digraphs)
+LANGSTANDARD(gnucxx98, "gnu++98",
+ "ISO C++ 1998 with " "amendments and GNU extensions",
+ BCPLComment | CPlusPlus | Digraphs | GNUMode)
+
+LANGSTANDARD(cxx0x, "c++0x",
+ "Upcoming ISO C++ 200x with amendments",
+ BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs)
+LANGSTANDARD(gnucxx0x, "gnu++0x",
+ "Upcoming ISO C++ 200x with amendments and GNU extensions",
+ BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode)
+
+// OpenCL
+
+LANGSTANDARD(opencl, "cl",
+ "OpenCL 1.0",
+ BCPLComment | C99 | Digraphs | HexFloat)
+
+// CUDA
+LANGSTANDARD(cuda, "cuda",
+ "NVIDIA CUDA(tm)",
+ BCPLComment | CPlusPlus | Digraphs)
+
+#undef LANGSTANDARD
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
new file mode 100644
index 0000000..560178b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
@@ -0,0 +1,54 @@
+//===-- MultiplexConsumer.h - AST Consumer for PCH Generation ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MultiplexConsumer class, which can be used to
+// multiplex ASTConsumer and SemaConsumer messages to many consumers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <vector>
+
+namespace clang {
+
+class MultiplexASTMutationListener;
+class MultiplexASTDeserializationListener;
+
+// Has a list of ASTConsumers and calls each of them. Owns its children.
+class MultiplexConsumer : public SemaConsumer {
+public:
+ // Takes ownership of the pointers in C.
+ MultiplexConsumer(const std::vector<ASTConsumer*>& C);
+ ~MultiplexConsumer();
+
+ // ASTConsumer
+ virtual void Initialize(ASTContext &Context);
+ virtual void HandleTopLevelDecl(DeclGroupRef D);
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual void HandleTagDeclDefinition(TagDecl *D);
+ virtual void CompleteTentativeDefinition(VarDecl *D);
+ virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired);
+ virtual ASTMutationListener *GetASTMutationListener();
+ virtual ASTDeserializationListener *GetASTDeserializationListener();
+ virtual void PrintStats();
+
+ // SemaConsumer
+ virtual void InitializeSema(Sema &S);
+ virtual void ForgetSema();
+
+ static bool classof(const MultiplexConsumer *) { return true; }
+private:
+ std::vector<ASTConsumer*> Consumers; // Owns these.
+ llvm::OwningPtr<MultiplexASTMutationListener> MutationListener;
+ llvm::OwningPtr<MultiplexASTDeserializationListener> DeserializationListener;
+};
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h
new file mode 100644
index 0000000..0d52e53
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h
@@ -0,0 +1,168 @@
+//===--- PreprocessorOptionms.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
+#define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_
+
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <string>
+#include <utility>
+#include <vector>
+#include <set>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class Preprocessor;
+class LangOptions;
+
+/// PreprocessorOptions - This class is used for passing the various options
+/// used in preprocessor initialization to InitializePreprocessor().
+class PreprocessorOptions {
+public:
+ std::vector<std::pair<std::string, bool/*isUndef*/> > Macros;
+ std::vector<std::string> Includes;
+ std::vector<std::string> MacroIncludes;
+
+ unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler
+ /// and target specific predefines.
+
+ unsigned DetailedRecord : 1; /// Whether we should maintain a detailed
+ /// record of all macro definitions and
+ /// instantiations.
+
+ /// The implicit PCH included at the start of the translation unit, or empty.
+ std::string ImplicitPCHInclude;
+
+ /// \brief When true, disables most of the normal validation performed on
+ /// precompiled headers.
+ bool DisablePCHValidation;
+
+ /// \brief When true, disables the use of the stat cache within a
+ /// precompiled header or AST file.
+ bool DisableStatCache;
+
+ /// \brief Dump declarations that are deserialized from PCH, for testing.
+ bool DumpDeserializedPCHDecls;
+
+ /// \brief This is a set of names for decls that we do not want to be
+ /// deserialized, and we emit an error if they are; for testing purposes.
+ std::set<std::string> DeserializedPCHDeclsToErrorOn;
+
+ /// \brief If non-zero, the implicit PCH include is actually a precompiled
+ /// preamble that covers this number of bytes in the main source file.
+ ///
+ /// The boolean indicates whether the preamble ends at the start of a new
+ /// line.
+ std::pair<unsigned, bool> PrecompiledPreambleBytes;
+
+ /// The implicit PTH input included at the start of the translation unit, or
+ /// empty.
+ std::string ImplicitPTHInclude;
+
+ /// If given, a PTH cache file to use for speeding up header parsing.
+ std::string TokenCache;
+
+ /// \brief The set of file remappings, which take existing files on
+ /// the system (the first part of each pair) and gives them the
+ /// contents of other files on the system (the second part of each
+ /// pair).
+ std::vector<std::pair<std::string, std::string> > RemappedFiles;
+
+ /// \brief The set of file-to-buffer remappings, which take existing files
+ /// on the system (the first part of each pair) and gives them the contents
+ /// of the specified memory buffer (the second part of each pair).
+ std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
+ RemappedFileBuffers;
+
+ /// \brief Whether the compiler instance should retain (i.e., not free)
+ /// the buffers associated with remapped files.
+ ///
+ /// This flag defaults to false; it can be set true only through direct
+ /// manipulation of the compiler invocation object, in cases where the
+ /// compiler invocation and its buffers will be reused.
+ bool RetainRemappedFileBuffers;
+
+ typedef std::vector<std::pair<std::string, std::string> >::iterator
+ remapped_file_iterator;
+ typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ const_remapped_file_iterator;
+ remapped_file_iterator remapped_file_begin() {
+ return RemappedFiles.begin();
+ }
+ const_remapped_file_iterator remapped_file_begin() const {
+ return RemappedFiles.begin();
+ }
+ remapped_file_iterator remapped_file_end() {
+ return RemappedFiles.end();
+ }
+ const_remapped_file_iterator remapped_file_end() const {
+ return RemappedFiles.end();
+ }
+
+ typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+ iterator remapped_file_buffer_iterator;
+ typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+ const_iterator const_remapped_file_buffer_iterator;
+ remapped_file_buffer_iterator remapped_file_buffer_begin() {
+ return RemappedFileBuffers.begin();
+ }
+ const_remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ return RemappedFileBuffers.begin();
+ }
+ remapped_file_buffer_iterator remapped_file_buffer_end() {
+ return RemappedFileBuffers.end();
+ }
+ const_remapped_file_buffer_iterator remapped_file_buffer_end() const {
+ return RemappedFileBuffers.end();
+ }
+
+public:
+ PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+ DisablePCHValidation(false), DisableStatCache(false),
+ DumpDeserializedPCHDecls(false),
+ PrecompiledPreambleBytes(0, true),
+ RetainRemappedFileBuffers(false) { }
+
+ void addMacroDef(llvm::StringRef Name) {
+ Macros.push_back(std::make_pair(Name, false));
+ }
+ void addMacroUndef(llvm::StringRef Name) {
+ Macros.push_back(std::make_pair(Name, true));
+ }
+ void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
+ RemappedFiles.push_back(std::make_pair(From, To));
+ }
+
+ remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) {
+ return RemappedFiles.erase(Remapped);
+ }
+
+ void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
+ RemappedFileBuffers.push_back(std::make_pair(From, To));
+ }
+
+ remapped_file_buffer_iterator
+ eraseRemappedFile(remapped_file_buffer_iterator Remapped) {
+ return RemappedFileBuffers.erase(Remapped);
+ }
+
+ void clearRemappedFiles() {
+ RemappedFiles.clear();
+ RemappedFileBuffers.clear();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
new file mode 100644
index 0000000..1eda0d4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -0,0 +1,37 @@
+//===--- PreprocessorOutputOptions.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H
+#define LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H
+
+namespace clang {
+
+/// PreprocessorOutputOptions - Options for controlling the C preprocessor
+/// output (e.g., -E).
+class PreprocessorOutputOptions {
+public:
+ unsigned ShowCPP : 1; ///< Print normal preprocessed output.
+ unsigned ShowComments : 1; ///< Show comments.
+ unsigned ShowLineMarkers : 1; ///< Show #line markers.
+ unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ unsigned ShowMacros : 1; ///< Print macro definitions.
+
+public:
+ PreprocessorOutputOptions() {
+ ShowCPP = 1;
+ ShowComments = 0;
+ ShowLineMarkers = 1;
+ ShowMacroComments = 0;
+ ShowMacros = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def
new file mode 100644
index 0000000..8a859e6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/StmtXML.def
@@ -0,0 +1,520 @@
+//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- 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 XML statement database structure as written in
+// <TranslationUnit> sub-nodes of the XML document.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by reference attributes to this value (currently used only for Label).
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
+// expression by a "type" attribute. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
+// a statement in the source file(s).
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ATTRIBUTE_FILE_LOCATION_XML
+# define ATTRIBUTE_FILE_LOCATION_XML \
+ ATTRIBUTE_XML(getFilename(), "file") \
+ ATTRIBUTE_XML(getLine(), "line") \
+ ATTRIBUTE_XML(getColumn(), "col") \
+ ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
+ ATTRIBUTE_OPT_XML(getLine(), "endline") \
+ ATTRIBUTE_OPT_XML(getColumn(), "endcol")
+#endif
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+NODE_XML(Stmt, "Stmt_Unsupported") // fallback for unsupproted statements
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(NullStmt, "NullStmt")
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(CompoundStmt, "CompoundStmt")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(size(), "num_stmts")
+ SUB_NODE_SEQUENCE_XML(Stmt)
+END_NODE_XML
+
+NODE_XML(CaseStmt, "CaseStmt") // case expr: body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // body
+ SUB_NODE_XML(Expr) // expr
+ SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body;
+END_NODE_XML
+
+NODE_XML(DefaultStmt, "DefaultStmt") // default: body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(LabelStmt, "LabelStmt") // Label: body;
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getName(), "name") // string
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // stmt1
+ SUB_NODE_XML(Stmt) // stmt2
+END_NODE_XML
+
+NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(WhileStmt, "WhileStmt") // while (cond) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(DoStmt, "DoStmt") // do body while (cond);
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // init
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Expr) // inc
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(GotoStmt, "GotoStmt") // goto label;
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string
+ ATTRIBUTE_XML(getLabel(), "ref") // id string
+END_NODE_XML
+
+NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ContinueStmt, "ContinueStmt") // continue
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(BreakStmt, "BreakStmt") // break
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(ReturnStmt, "ReturnStmt") // return expr;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension
+ ATTRIBUTE_FILE_LOCATION_XML
+ // FIXME
+END_NODE_XML
+
+NODE_XML(DeclStmt, "DeclStmt") // a declaration statement
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_SEQUENCE_XML(Decl)
+END_NODE_XML
+
+// C++ statements
+NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 ..
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getNumHandlers(), "num_handlers")
+ SUB_NODE_XML(CompoundStmt)
+ SUB_NODE_SEQUENCE_XML(CXXCatchStmt)
+END_NODE_XML
+
+NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(VarDecl)
+ SUB_NODE_XML(Stmt)
+END_NODE_XML
+
+// Expressions
+NODE_XML(PredefinedExpr, "PredefinedExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getIdentType(), "kind")
+ ENUM_XML(PredefinedExpr::Func, "__func__")
+ ENUM_XML(PredefinedExpr::Function, "__FUNCTION__")
+ ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__")
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal
+ //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here?
+END_NODE_XML
+
+NODE_XML(IntegerLiteral, "IntegerLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // (signed) integer
+END_NODE_XML
+
+NODE_XML(CharacterLiteral, "CharacterLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // unsigned
+END_NODE_XML
+
+NODE_XML(FloatingLiteral, "FloatingLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ // FIXME: output float as written in source (no approximation or the like)
+ //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float
+END_NODE_XML
+
+NODE_XML(StringLiteral, "StringLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed
+ ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean
+END_NODE_XML
+
+NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
+ ENUM_XML(UO_PostInc, "postinc")
+ ENUM_XML(UO_PostDec, "postdec")
+ ENUM_XML(UO_PreInc, "preinc")
+ ENUM_XML(UO_PreDec, "predec")
+ ENUM_XML(UO_AddrOf, "addrof")
+ ENUM_XML(UO_Deref, "deref")
+ ENUM_XML(UO_Plus, "plus")
+ ENUM_XML(UO_Minus, "minus")
+ ENUM_XML(UO_Not, "not") // bitwise not
+ ENUM_XML(UO_LNot, "lnot") // boolean not
+ ENUM_XML(UO_Real, "__real")
+ ENUM_XML(UO_Imag, "__imag")
+ ENUM_XML(UO_Extension, "__extension__")
+ END_ENUM_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
+ ENUM_XML(BO_PtrMemD , "ptrmemd")
+ ENUM_XML(BO_PtrMemI , "ptrmemi")
+ ENUM_XML(BO_Mul , "mul")
+ ENUM_XML(BO_Div , "div")
+ ENUM_XML(BO_Rem , "rem")
+ ENUM_XML(BO_Add , "add")
+ ENUM_XML(BO_Sub , "sub")
+ ENUM_XML(BO_Shl , "shl")
+ ENUM_XML(BO_Shr , "shr")
+ ENUM_XML(BO_LT , "lt")
+ ENUM_XML(BO_GT , "gt")
+ ENUM_XML(BO_LE , "le")
+ ENUM_XML(BO_GE , "ge")
+ ENUM_XML(BO_EQ , "eq")
+ ENUM_XML(BO_NE , "ne")
+ ENUM_XML(BO_And , "and") // bitwise and
+ ENUM_XML(BO_Xor , "xor")
+ ENUM_XML(BO_Or , "or") // bitwise or
+ ENUM_XML(BO_LAnd , "land") // boolean and
+ ENUM_XML(BO_LOr , "lor") // boolean or
+ ENUM_XML(BO_Assign , "assign")
+ ENUM_XML(BO_MulAssign, "mulassign")
+ ENUM_XML(BO_DivAssign, "divassign")
+ ENUM_XML(BO_RemAssign, "remassign")
+ ENUM_XML(BO_AddAssign, "addassign")
+ ENUM_XML(BO_SubAssign, "subassign")
+ ENUM_XML(BO_ShlAssign, "shlassign")
+ ENUM_XML(BO_ShrAssign, "shrassign")
+ ENUM_XML(BO_AndAssign, "andassign")
+ ENUM_XML(BO_XorAssign, "xorassign")
+ ENUM_XML(BO_OrAssign , "orassign")
+ ENUM_XML(BO_Comma , "comma")
+ END_ENUM_XML
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+END_NODE_XML
+
+// FIXME: is there a special class needed or is BinaryOperator sufficient?
+//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator")
+
+NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+ SUB_NODE_XML(Expr) // expr3
+END_NODE_XML
+
+NODE_XML(OffsetOfExpr, "OffsetOfExpr") // offsetof(basetype, components)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getTypeSourceInfo()->getType())
+ ATTRIBUTE_XML(getNumComponents(), "num_components")
+ SUB_NODE_SEQUENCE_XML(OffsetOfExpr::OffsetOfNode)
+END_NODE_XML
+
+NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isSizeOf(), "is_sizeof")
+ ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type
+ ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert
+ SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
+END_NODE_XML
+
+NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2]
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+END_NODE_XML
+
+NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isArrow(), "is_deref")
+ ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F
+ ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ImplicitCastExpr, "ImplicitCastExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr)
+END_NODE_XML
+
+NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5]
+ SUB_NODE_XML(Expr) // init
+END_NODE_XML
+
+NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr")
+ SUB_NODE_XML(Expr) // base
+END_NODE_XML
+
+NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } };
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id
+ ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned
+ SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN
+END_NODE_XML
+
+NODE_XML(DesignatedInitExpr, "DesignatedInitExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+// GNU Extensions
+NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getLabel(), "ref") // id string
+ SUB_NODE_XML(LabelStmt) // expr
+END_NODE_XML
+
+NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(CompoundStmt)
+END_NODE_XML
+
+NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+ SUB_NODE_XML(Expr) // expr3
+END_NODE_XML
+
+NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+// C++ Expressions
+NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getStmtClass(), "kind")
+ ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast")
+ ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast")
+ ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast")
+ ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // boolean
+END_NODE_XML
+
+NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type
+ ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert
+ SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
+END_NODE_XML
+
+NODE_XML(CXXThisExpr, "CXXThisExpr") // this
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr);
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // NULL in case of "throw;"
+END_NODE_XML
+
+NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration)
+END_NODE_XML
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
new file mode 100644
index 0000000..380a1dd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -0,0 +1,52 @@
+//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_
+#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_
+
+#include "clang/Basic/Diagnostic.h"
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class SourceManager;
+
+class TextDiagnosticBuffer : public DiagnosticClient {
+public:
+ typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
+ typedef DiagList::iterator iterator;
+ typedef DiagList::const_iterator const_iterator;
+private:
+ DiagList Errors, Warnings, Notes;
+public:
+ const_iterator err_begin() const { return Errors.begin(); }
+ const_iterator err_end() const { return Errors.end(); }
+
+ const_iterator warn_begin() const { return Warnings.begin(); }
+ const_iterator warn_end() const { return Warnings.end(); }
+
+ const_iterator note_begin() const { return Notes.begin(); }
+ const_iterator note_end() const { return Notes.end(); }
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+
+ /// FlushDiagnostics - Flush the buffered diagnostics to an given
+ /// diagnostic engine.
+ void FlushDiagnostics(Diagnostic &Diags) const;
+};
+
+} // end namspace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
new file mode 100644
index 0000000..f530294
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -0,0 +1,80 @@
+//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which prints the diagnostics to
+// standard error.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_
+#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class DiagnosticOptions;
+class LangOptions;
+
+class TextDiagnosticPrinter : public DiagnosticClient {
+ llvm::raw_ostream &OS;
+ const LangOptions *LangOpts;
+ const DiagnosticOptions *DiagOpts;
+
+ SourceLocation LastWarningLoc;
+ FullSourceLoc LastLoc;
+ unsigned LastCaretDiagnosticWasNote : 1;
+ unsigned OwnsOutputStream : 1;
+
+ /// A string to prefix to error messages.
+ std::string Prefix;
+
+public:
+ TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags,
+ bool OwnsOutputStream = false);
+ virtual ~TextDiagnosticPrinter();
+
+ /// setPrefix - Set the diagnostic printer prefix string, which will be
+ /// printed at the start of any diagnostics. If empty, no prefix string is
+ /// used.
+ void setPrefix(std::string Value) { Prefix = Value; }
+
+ void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) {
+ LangOpts = &LO;
+ }
+
+ void EndSourceFile() {
+ LangOpts = 0;
+ }
+
+ void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
+
+ void HighlightRange(const CharSourceRange &R,
+ const SourceManager &SrcMgr,
+ unsigned LineNo, FileID FID,
+ std::string &CaretLine,
+ const std::string &SourceLine);
+
+ void EmitCaretDiagnostic(SourceLocation Loc,
+ CharSourceRange *Ranges, unsigned NumRanges,
+ const SourceManager &SM,
+ const FixItHint *Hints,
+ unsigned NumHints,
+ unsigned Columns,
+ unsigned OnMacroInst,
+ unsigned MacroSkipStart,
+ unsigned MacroSkipEnd);
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def
new file mode 100644
index 0000000..b78e70f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TypeXML.def
@@ -0,0 +1,304 @@
+//===-- TypeXML.def - Metadata about Type XML nodes ------------*- 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 XML type info database as written in the
+// <ReferenceSection>/<Types> sub-nodes of the XML document. Type nodes
+// are referred by "type" reference attributes throughout the document.
+// A type node never contains sub-nodes.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// type of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that type
+// node follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a
+// string, which value uniquely identify the type. Other nodes may refer
+// by "type" reference attributes to this value.
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type
+// nodes by a "type" attribute. FN is internally used by clang.
+//
+// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their
+// declaration contexts by a "context" attribute. FN is internally used by
+// clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+NODE_XML(Type, "FIXME_Type")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getTypeClassName(), "unhandled_type_name")
+END_NODE_XML
+
+NODE_XML(QualType, "CvQualifiedType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*'
+ ATTRIBUTE_OPT_XML(isLocalConstQualified(), "const") // boolean
+ ATTRIBUTE_OPT_XML(isLocalVolatileQualified(), "volatile") // boolean
+ ATTRIBUTE_OPT_XML(isLocalRestrictQualified(), "restrict") // boolean
+ ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC
+ ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned
+END_NODE_XML
+
+NODE_XML(BuiltinType, "FundamentalType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_ENUM_XML(getKind(), "kind")
+ ENUM_XML(BuiltinType::Void, "void")
+ ENUM_XML(BuiltinType::Bool, "bool")
+ ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform
+ ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform
+ ENUM_XML(BuiltinType::SChar, "signed char")
+ ENUM_XML(BuiltinType::Short, "short");
+ ENUM_XML(BuiltinType::Int, "int");
+ ENUM_XML(BuiltinType::Long, "long");
+ ENUM_XML(BuiltinType::LongLong, "long long");
+ ENUM_XML(BuiltinType::Int128, "__int128_t");
+ ENUM_XML(BuiltinType::UChar, "unsigned char");
+ ENUM_XML(BuiltinType::UShort, "unsigned short");
+ ENUM_XML(BuiltinType::UInt, "unsigned int");
+ ENUM_XML(BuiltinType::ULong, "unsigned long");
+ ENUM_XML(BuiltinType::ULongLong, "unsigned long long");
+ ENUM_XML(BuiltinType::UInt128, "__uint128_t");
+ ENUM_XML(BuiltinType::Float, "float");
+ ENUM_XML(BuiltinType::Double, "double");
+ ENUM_XML(BuiltinType::LongDouble, "long double");
+ ENUM_XML(BuiltinType::WChar_U, "wchar_t");
+ ENUM_XML(BuiltinType::WChar_S, "wchar_t");
+ ENUM_XML(BuiltinType::Char16, "char16_t");
+ ENUM_XML(BuiltinType::Char32, "char32_t");
+ ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'.
+ ENUM_XML(BuiltinType::Overload, "overloaded");
+ ENUM_XML(BuiltinType::Dependent, "dependent");
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(PointerType, "PointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(LValueReferenceType, "ReferenceType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(RValueReferenceType, "ReferenceType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(FunctionNoProtoType, "FunctionNoProtoType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(FunctionProtoType, "FunctionType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getResultType(), "result_type")
+ ATTRIBUTE_OPT_XML(isVariadic(), "variadic")
+ ATTRIBUTE_ENUM_XML(getCallConv(), "call_conv")
+ ENUM_XML(CC_Default, "")
+ ENUM_XML(CC_C, "C")
+ ENUM_XML(CC_X86StdCall, "X86StdCall")
+ ENUM_XML(CC_X86FastCall, "X86FastCall")
+ ENUM_XML(CC_X86ThisCall, "X86ThisCall")
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(TypedefType, "Typedef")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType())
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc)
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+END_NODE_XML
+
+NODE_XML(BlockPointerType, "BlockPointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type
+END_NODE_XML
+
+NODE_XML(MemberPointerType, "MemberPointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+ ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member
+END_NODE_XML
+
+NODE_XML(ConstantArrayType, "ArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getSize(), "size") // unsigned
+ ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier")
+ ENUM_XML(ArrayType::Normal, "")
+ ENUM_XML(ArrayType::Static, "static")
+ ENUM_XML(ArrayType::Star, "star")
+ END_ENUM_XML
+ ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier") // unsigned
+END_NODE_XML
+
+NODE_XML(IncompleteArrayType, "IncompleteArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+END_NODE_XML
+
+NODE_XML(VariableArrayType, "VariableArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ // note: the size expression is print at the point of declaration
+END_NODE_XML
+
+NODE_XML(DependentSizedArrayType, "DependentSizedArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ // FIXME: how to deal with size expression?
+END_NODE_XML
+
+NODE_XML(VectorType, "VectorType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getNumElements(), "size") // unsigned
+END_NODE_XML
+
+NODE_XML(ExtVectorType, "ExtVectorType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getNumElements(), "size") // unsigned
+END_NODE_XML
+
+NODE_XML(TypeOfExprType, "TypeOfExprType")
+ ID_ATTRIBUTE_XML
+ // note: the typeof expression is print at the point of use
+END_NODE_XML
+
+NODE_XML(TypeOfType, "TypeOfType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getUnderlyingType())
+END_NODE_XML
+
+
+NODE_XML(RecordType, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind")
+ ENUM_XML(TTK_Struct, "struct")
+ ENUM_XML(TTK_Union, "union")
+ ENUM_XML(TTK_Class, "class")
+ END_ENUM_XML
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(EnumType, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(TemplateTypeParmType, "TemplateTypeParmType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(TemplateSpecializationType, "TemplateSpecializationType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ElaboratedType, "ElaboratedType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_ENUM_XML(getKeyword(), "keyword")
+ ENUM_XML(ETK_None, "none")
+ ENUM_XML(ETK_Typename, "typename")
+ ENUM_XML(ETK_Struct, "struct")
+ ENUM_XML(ETK_Union, "union")
+ ENUM_XML(ETK_Class, "class")
+ ENUM_XML(ETK_Enum, "enum")
+ END_ENUM_XML
+ TYPE_ATTRIBUTE_XML(getNamedType())
+END_NODE_XML
+
+NODE_XML(InjectedClassNameType, "InjectedClassNameType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(DependentNameType, "DependentNameType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(DependentTemplateSpecializationType,
+ "DependentTemplateSpecializationType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ObjCInterfaceType, "ObjCInterfaceType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(SubstTemplateTypeParmType, "SubstTemplateTypeParm")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(DependentSizedExtVectorType, "DependentSizedExtVector")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(UnresolvedUsingType, "UnresolvedUsing")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(DecltypeType, "Decltype")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef CONTEXT_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
new file mode 100644
index 0000000..485161b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -0,0 +1,94 @@
+//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_UTILS_H
+#define LLVM_CLANG_FRONTEND_UTILS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+class Triple;
+}
+
+namespace clang {
+class ASTConsumer;
+class CompilerInstance;
+class Decl;
+class DependencyOutputOptions;
+class Diagnostic;
+class DiagnosticOptions;
+class HeaderSearch;
+class HeaderSearchOptions;
+class IdentifierTable;
+class LangOptions;
+class Preprocessor;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class SourceManager;
+class Stmt;
+class TargetInfo;
+class FrontendOptions;
+
+/// Normalize \arg File for use in a user defined #include directive (in the
+/// predefines buffer).
+std::string NormalizeDashIncludePath(llvm::StringRef File);
+
+/// Apply the header search options to get given HeaderSearch object.
+void ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &triple);
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file.
+void InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorOptions &PPOpts,
+ const HeaderSearchOptions &HSOpts,
+ const FrontendOptions &FEOpts);
+
+/// ProcessWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
+
+/// DoPrintPreprocessedInput - Implement -E mode.
+void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
+ const PreprocessorOutputOptions &Opts);
+
+/// CheckDiagnostics - Gather the expected diagnostics and check them.
+bool CheckDiagnostics(Preprocessor &PP);
+
+/// AttachDependencyFileGen - Create a dependency file generator, and attach
+/// it to the given preprocessor. This takes ownership of the output stream.
+void AttachDependencyFileGen(Preprocessor &PP,
+ const DependencyOutputOptions &Opts);
+
+/// AttachHeaderIncludeGen - Create a header include list generator, and attach
+/// it to the given preprocessor.
+///
+/// \param ShowAllHeaders - If true, show all header information instead of just
+/// headers following the predefines buffer. This is useful for making sure
+/// includes mentioned on the command line are also reported, but differs from
+/// the default behavior used by -H.
+/// \param OutputPath - If non-empty, a path to write the header include
+/// information to, instead of writing to stderr.
+void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
+ llvm::StringRef OutputPath = "");
+
+/// CacheTokens - Cache tokens for use with PCH. Note that this requires
+/// a seekable stream.
+void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h
new file mode 100644
index 0000000..793cedd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticsClient.h
@@ -0,0 +1,94 @@
+//===-- VerifyDiagnosticsClient.h - Verifying Diagnostic Client -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
+#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+class Diagnostic;
+class TextDiagnosticBuffer;
+
+/// VerifyDiagnosticsClient - Create a diagnostic client which will use markers
+/// in the input source to check that all the emitted diagnostics match those
+/// expected.
+///
+/// USING THE DIAGNOSTIC CHECKER:
+///
+/// Indicating that a line expects an error or a warning is simple. Put a
+/// comment on the line that has the diagnostic, use:
+///
+/// expected-{error,warning,note}
+///
+/// to tag if it's an expected error or warning, and place the expected text
+/// between {{ and }} markers. The full text doesn't have to be included, only
+/// enough to ensure that the correct diagnostic was emitted.
+///
+/// Here's an example:
+///
+/// int A = B; // expected-error {{use of undeclared identifier 'B'}}
+///
+/// You can place as many diagnostics on one line as you wish. To make the code
+/// more readable, you can use slash-newline to separate out the diagnostics.
+///
+/// The simple syntax above allows each specification to match exactly one
+/// error. You can use the extended syntax to customize this. The extended
+/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of
+/// "error", "warning" or "note", and <n> is a positive integer. This allows the
+/// diagnostic to appear as many times as specified. Example:
+///
+/// void f(); // expected-note 2 {{previous declaration is here}}
+///
+/// Regex matching mode may be selected by appending '-re' to type. Example:
+///
+/// expected-error-re
+///
+/// Examples matching error: "variable has incomplete type 'struct s'"
+///
+/// // expected-error {{variable has incomplete type 'struct s'}}
+/// // expected-error {{variable has incomplete type}}
+///
+/// // expected-error-re {{variable has has type 'struct .'}}
+/// // expected-error-re {{variable has has type 'struct .*'}}
+/// // expected-error-re {{variable has has type 'struct (.*)'}}
+/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
+///
+class VerifyDiagnosticsClient : public DiagnosticClient {
+public:
+ Diagnostic &Diags;
+ llvm::OwningPtr<DiagnosticClient> PrimaryClient;
+ llvm::OwningPtr<TextDiagnosticBuffer> Buffer;
+ Preprocessor *CurrentPreprocessor;
+
+private:
+ void CheckDiagnostics();
+
+public:
+ /// Create a new verifying diagnostic client, which will issue errors to \arg
+ /// PrimaryClient when a diagnostic does not match what is expected (as
+ /// indicated in the source file). The verifying diagnostic client takes
+ /// ownership of \arg PrimaryClient.
+ VerifyDiagnosticsClient(Diagnostic &Diags, DiagnosticClient *PrimaryClient);
+ ~VerifyDiagnosticsClient();
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP);
+
+ virtual void EndSourceFile();
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namspace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h b/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h
new file mode 100644
index 0000000..031ee7d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h
@@ -0,0 +1,30 @@
+//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions
+// which were split from Frontend to minimise Frontend's dependencies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H
+#define LLVM_CLANG_FRONTENDTOOL_UTILS_H
+
+namespace clang {
+
+class CompilerInstance;
+
+/// ExecuteCompilerInvocation - Execute the given actions described by the
+/// compiler invocation object in the given compiler instance.
+///
+/// \return - True on success.
+bool ExecuteCompilerInvocation(CompilerInstance *Clang);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h
new file mode 100644
index 0000000..fc18dae
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/ASTLocation.h
@@ -0,0 +1,174 @@
+//===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTLocation is Decl or a Stmt and its immediate Decl parent.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ASTLOCATION_H
+#define LLVM_CLANG_INDEX_ASTLOCATION_H
+
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+ class Decl;
+ class Stmt;
+ class NamedDecl;
+
+namespace idx {
+ class TranslationUnit;
+
+/// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's
+/// immutable.
+///
+/// ASTLocation is intended to be used as a "pointer" into the AST. It is either
+/// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid
+/// of context, its parent Decl provides all the additional missing information
+/// like the declaration context, ASTContext, etc.
+///
+class ASTLocation {
+public:
+ enum NodeKind {
+ N_Decl, N_NamedRef, N_Stmt, N_Type
+ };
+
+ struct NamedRef {
+ NamedDecl *ND;
+ SourceLocation Loc;
+
+ NamedRef() : ND(0) { }
+ NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { }
+ };
+
+private:
+ llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl;
+
+ union {
+ Decl *D;
+ Stmt *Stm;
+ struct {
+ NamedDecl *ND;
+ unsigned RawLoc;
+ } NDRef;
+ struct {
+ void *TyPtr;
+ void *Data;
+ } Ty;
+ };
+
+public:
+ ASTLocation() { }
+
+ explicit ASTLocation(const Decl *d)
+ : ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { }
+
+ ASTLocation(const Decl *parentDecl, const Stmt *stm)
+ : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt),
+ Stm(const_cast<Stmt*>(stm)) {
+ if (!stm) ParentDecl.setPointer(0);
+ }
+
+ ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc)
+ : ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) {
+ if (ndRef) {
+ NDRef.ND = ndRef;
+ NDRef.RawLoc = loc.getRawEncoding();
+ } else
+ ParentDecl.setPointer(0);
+ }
+
+ ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)
+ : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {
+ if (tyLoc) {
+ Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();
+ Ty.Data = tyLoc.getOpaqueData();
+ } else
+ ParentDecl.setPointer(0);
+ }
+
+ bool isValid() const { return ParentDecl.getPointer() != 0; }
+ bool isInvalid() const { return !isValid(); }
+
+ NodeKind getKind() const {
+ assert(isValid());
+ return (NodeKind)ParentDecl.getInt();
+ }
+
+ Decl *getParentDecl() const { return ParentDecl.getPointer(); }
+
+ Decl *AsDecl() const {
+ assert(getKind() == N_Decl);
+ return D;
+ }
+ Stmt *AsStmt() const {
+ assert(getKind() == N_Stmt);
+ return Stm;
+ }
+ NamedRef AsNamedRef() const {
+ assert(getKind() == N_NamedRef);
+ return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc));
+ }
+ TypeLoc AsTypeLoc() const {
+ assert(getKind() == N_Type);
+ return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);
+ }
+
+ Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; }
+ Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; }
+ NamedRef dyn_AsNamedRef() const {
+ return getKind() == N_Type ? AsNamedRef() : NamedRef();
+ }
+ TypeLoc dyn_AsTypeLoc() const {
+ return getKind() == N_Type ? AsTypeLoc() : TypeLoc();
+ }
+
+ bool isDecl() const { return isValid() && getKind() == N_Decl; }
+ bool isStmt() const { return isValid() && getKind() == N_Stmt; }
+ bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; }
+ bool isType() const { return isValid() && getKind() == N_Type; }
+
+ /// \brief Returns the declaration that this ASTLocation references.
+ ///
+ /// If this points to a Decl, that Decl is returned.
+ /// If this points to an Expr that references a Decl, that Decl is returned,
+ /// otherwise it returns NULL.
+ Decl *getReferencedDecl();
+ const Decl *getReferencedDecl() const {
+ return const_cast<ASTLocation*>(this)->getReferencedDecl();
+ }
+
+ SourceRange getSourceRange() const;
+
+ void print(llvm::raw_ostream &OS) const;
+};
+
+/// \brief Like ASTLocation but also contains the TranslationUnit that the
+/// ASTLocation originated from.
+class TULocation : public ASTLocation {
+ TranslationUnit *TU;
+
+public:
+ TULocation(TranslationUnit *tu, ASTLocation astLoc)
+ : ASTLocation(astLoc), TU(tu) {
+ assert(tu && "Passed null translation unit");
+ }
+
+ TranslationUnit *getTU() const { return TU; }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h b/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h
new file mode 100644
index 0000000..f6b5465
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/Analyzer.h
@@ -0,0 +1,56 @@
+//===--- Analyzer.h - Analysis for indexing information ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Analyzer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ANALYZER_H
+#define LLVM_CLANG_INDEX_ANALYZER_H
+
+namespace clang {
+ class Decl;
+ class ObjCMessageExpr;
+
+namespace idx {
+ class Program;
+ class IndexProvider;
+ class TULocationHandler;
+
+/// \brief Provides indexing information, like finding all references of an
+/// Entity across translation units.
+class Analyzer {
+ Program &Prog;
+ IndexProvider &Idxer;
+
+ Analyzer(const Analyzer&); // do not implement
+ Analyzer &operator=(const Analyzer &); // do not implement
+
+public:
+ explicit Analyzer(Program &prog, IndexProvider &idxer)
+ : Prog(prog), Idxer(idxer) { }
+
+ /// \brief Find all TULocations for declarations of the given Decl and pass
+ /// them to Handler.
+ void FindDeclarations(Decl *D, TULocationHandler &Handler);
+
+ /// \brief Find all TULocations for references of the given Decl and pass
+ /// them to Handler.
+ void FindReferences(Decl *D, TULocationHandler &Handler);
+
+ /// \brief Find methods that may respond to the given message and pass them
+ /// to Handler.
+ void FindObjCMethods(ObjCMessageExpr *MsgE, TULocationHandler &Handler);
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h
new file mode 100644
index 0000000..336bf47
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/CallGraph.h
@@ -0,0 +1,146 @@
+//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the CallGraph and CallGraphNode classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH
+#define LLVM_CLANG_ANALYSIS_CALLGRAPH
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Program.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/STLExtras.h"
+#include <vector>
+#include <map>
+
+namespace clang {
+
+class CallGraphNode {
+ idx::Entity F;
+ typedef std::pair<idx::ASTLocation, CallGraphNode*> CallRecord;
+ std::vector<CallRecord> CalledFunctions;
+
+public:
+ CallGraphNode(idx::Entity f) : F(f) {}
+
+ typedef std::vector<CallRecord>::iterator iterator;
+ typedef std::vector<CallRecord>::const_iterator const_iterator;
+
+ iterator begin() { return CalledFunctions.begin(); }
+ iterator end() { return CalledFunctions.end(); }
+ const_iterator begin() const { return CalledFunctions.begin(); }
+ const_iterator end() const { return CalledFunctions.end(); }
+
+ void addCallee(idx::ASTLocation L, CallGraphNode *Node) {
+ CalledFunctions.push_back(std::make_pair(L, Node));
+ }
+
+ bool hasCallee() const { return begin() != end(); }
+
+ std::string getName() const { return F.getPrintableName(); }
+
+ Decl *getDecl(ASTContext &Ctx) const { return F.getDecl(Ctx); }
+};
+
+class CallGraph {
+ /// Program manages all Entities.
+ idx::Program &Prog;
+
+ typedef std::map<idx::Entity, CallGraphNode *> FunctionMapTy;
+
+ /// FunctionMap owns all CallGraphNodes.
+ FunctionMapTy FunctionMap;
+
+ /// CallerCtx maps a caller to its ASTContext.
+ llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx;
+
+ /// Root node is the 'main' function or 0.
+ CallGraphNode *Root;
+
+ /// ExternalCallingNode has edges to all external functions.
+ CallGraphNode *ExternalCallingNode;
+
+public:
+ CallGraph(idx::Program &P);
+ ~CallGraph();
+
+ typedef FunctionMapTy::iterator iterator;
+ typedef FunctionMapTy::const_iterator const_iterator;
+
+ iterator begin() { return FunctionMap.begin(); }
+ iterator end() { return FunctionMap.end(); }
+ const_iterator begin() const { return FunctionMap.begin(); }
+ const_iterator end() const { return FunctionMap.end(); }
+
+ CallGraphNode *getRoot() { return Root; }
+
+ CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
+
+ void addTU(ASTContext &AST);
+
+ idx::Program &getProgram() { return Prog; }
+
+ CallGraphNode *getOrInsertFunction(idx::Entity F);
+
+ Decl *getDecl(CallGraphNode *Node);
+
+ void print(llvm::raw_ostream &os);
+ void dump();
+
+ void ViewCallGraph() const;
+};
+
+} // end clang namespace
+
+namespace llvm {
+
+template <> struct GraphTraits<clang::CallGraph> {
+ typedef clang::CallGraph GraphType;
+ typedef clang::CallGraphNode NodeType;
+
+ typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy;
+ typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun;
+
+ typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
+
+ static NodeType *getEntryNode(GraphType *CG) {
+ return CG->getExternalCallingNode();
+ }
+
+ static ChildIteratorType child_begin(NodeType *N) {
+ return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
+ }
+ static ChildIteratorType child_end(NodeType *N) {
+ return map_iterator(N->end(), CGNDerefFun(CGNDeref));
+ }
+
+ typedef std::pair<clang::idx::Entity, NodeType*> PairTy;
+ typedef std::pointer_to_unary_function<PairTy, NodeType*> DerefFun;
+
+ typedef mapped_iterator<GraphType::const_iterator, DerefFun> nodes_iterator;
+
+ static nodes_iterator nodes_begin(const GraphType &CG) {
+ return map_iterator(CG.begin(), DerefFun(CGDeref));
+ }
+ static nodes_iterator nodes_end(const GraphType &CG) {
+ return map_iterator(CG.end(), DerefFun(CGDeref));
+ }
+
+ static NodeType *CGNDeref(CGNPairTy P) { return P.second; }
+
+ static NodeType *CGDeref(PairTy P) { return P.second; }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h b/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h
new file mode 100644
index 0000000..73f2fe5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/DeclReferenceMap.h
@@ -0,0 +1,50 @@
+//===--- DeclReferenceMap.h - Map Decls to their references -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
+// reference them.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
+#define LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/Index/STLExtras.h"
+#include <map>
+
+namespace clang {
+ class ASTContext;
+ class NamedDecl;
+
+namespace idx {
+
+/// \brief Maps NamedDecls with the ASTLocations that reference them.
+///
+/// References are mapped and retrieved using the canonical decls.
+class DeclReferenceMap {
+public:
+ explicit DeclReferenceMap(ASTContext &Ctx);
+
+ typedef std::multimap<NamedDecl*, ASTLocation> MapTy;
+ typedef pair_value_iterator<MapTy::iterator> astlocation_iterator;
+
+ astlocation_iterator refs_begin(NamedDecl *D) const;
+ astlocation_iterator refs_end(NamedDecl *D) const;
+ bool refs_empty(NamedDecl *D) const;
+
+private:
+ mutable MapTy Map;
+};
+
+} // end idx namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/Entity.h b/contrib/llvm/tools/clang/include/clang/Index/Entity.h
new file mode 100644
index 0000000..9863963
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/Entity.h
@@ -0,0 +1,148 @@
+//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Entity is a ASTContext-independent way to refer to declarations that are
+// visible across translation units.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ENTITY_H
+#define LLVM_CLANG_INDEX_ENTITY_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+ class ASTContext;
+ class Decl;
+
+namespace idx {
+ class Program;
+ class EntityImpl;
+
+/// \brief A ASTContext-independent way to refer to declarations.
+///
+/// Entity is basically the link for declarations that are semantically the same
+/// in multiple ASTContexts. A client will convert a Decl into an Entity and
+/// later use that Entity to find the "same" Decl into another ASTContext.
+/// Declarations that are semantically the same and visible across translation
+/// units will be associated with the same Entity.
+///
+/// An Entity may also refer to declarations that cannot be visible across
+/// translation units, e.g. static functions with the same name in multiple
+/// translation units will be associated with different Entities.
+///
+/// Entities can be checked for equality but note that the same Program object
+/// should be used when getting Entities.
+///
+class Entity {
+ /// \brief Stores the Decl directly if it is not visible outside of its own
+ /// translation unit, otherwise it stores the associated EntityImpl.
+ llvm::PointerUnion<Decl *, EntityImpl *> Val;
+
+ explicit Entity(Decl *D);
+ explicit Entity(EntityImpl *impl) : Val(impl) { }
+ friend class EntityGetter;
+
+public:
+ Entity() { }
+
+ /// \brief Find the Decl that can be referred to by this entity.
+ Decl *getDecl(ASTContext &AST) const;
+
+ /// \brief If this Entity represents a declaration that is internal to its
+ /// translation unit, getInternalDecl() returns it.
+ Decl *getInternalDecl() const {
+ assert(isInternalToTU() && "This Entity is not internal!");
+ return Val.get<Decl *>();
+ }
+
+ /// \brief Get a printable name for debugging purpose.
+ std::string getPrintableName() const;
+
+ /// \brief Get an Entity associated with the given Decl.
+ /// \returns invalid Entity if an Entity cannot refer to this Decl.
+ static Entity get(Decl *D, Program &Prog);
+
+ /// \brief Get an Entity associated with a name in the global namespace.
+ static Entity get(llvm::StringRef Name, Program &Prog);
+
+ /// \brief true if the Entity is not visible outside the trasnlation unit.
+ bool isInternalToTU() const {
+ assert(isValid() && "This Entity is not valid!");
+ return Val.is<Decl *>();
+ }
+
+ bool isValid() const { return !Val.isNull(); }
+ bool isInvalid() const { return !isValid(); }
+
+ void *getAsOpaquePtr() const { return Val.getOpaqueValue(); }
+ static Entity getFromOpaquePtr(void *Ptr) {
+ Entity Ent;
+ Ent.Val = llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue(Ptr);
+ return Ent;
+ }
+
+ friend bool operator==(const Entity &LHS, const Entity &RHS) {
+ return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
+ }
+
+ // For use in a std::map.
+ friend bool operator < (const Entity &LHS, const Entity &RHS) {
+ return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
+ }
+
+ // For use in DenseMap/DenseSet.
+ static Entity getEmptyMarker() {
+ Entity Ent;
+ Ent.Val =
+ llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-1);
+ return Ent;
+ }
+ static Entity getTombstoneMarker() {
+ Entity Ent;
+ Ent.Val =
+ llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-2);
+ return Ent;
+ }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that Entities can be used as keys in DenseMap and
+/// DenseSets.
+template<>
+struct DenseMapInfo<clang::idx::Entity> {
+ static inline clang::idx::Entity getEmptyKey() {
+ return clang::idx::Entity::getEmptyMarker();
+ }
+
+ static inline clang::idx::Entity getTombstoneKey() {
+ return clang::idx::Entity::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::idx::Entity);
+
+ static inline bool
+ isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <>
+struct isPodLike<clang::idx::Entity> { static const bool value = true; };
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h b/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h
new file mode 100644
index 0000000..9cd83a8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/GlobalSelector.h
@@ -0,0 +1,100 @@
+//===--- GlobalSelector.h - Cross-translation-unit "token" for selectors --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GlobalSelector is a ASTContext-independent way to refer to selectors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_GLOBALSELECTOR_H
+#define LLVM_CLANG_INDEX_GLOBALSELECTOR_H
+
+#include "llvm/ADT/DenseMap.h"
+#include <string>
+
+namespace clang {
+ class ASTContext;
+ class Selector;
+
+namespace idx {
+ class Program;
+
+/// \brief A ASTContext-independent way to refer to selectors.
+class GlobalSelector {
+ void *Val;
+
+ explicit GlobalSelector(void *val) : Val(val) { }
+
+public:
+ GlobalSelector() : Val(0) { }
+
+ /// \brief Get the ASTContext-specific selector.
+ Selector getSelector(ASTContext &AST) const;
+
+ bool isValid() const { return Val != 0; }
+ bool isInvalid() const { return !isValid(); }
+
+ /// \brief Get a printable name for debugging purpose.
+ std::string getPrintableName() const;
+
+ /// \brief Get a GlobalSelector for the ASTContext-specific selector.
+ static GlobalSelector get(Selector Sel, Program &Prog);
+
+ void *getAsOpaquePtr() const { return Val; }
+
+ static GlobalSelector getFromOpaquePtr(void *Ptr) {
+ return GlobalSelector(Ptr);
+ }
+
+ friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) {
+ return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
+ }
+
+ // For use in a std::map.
+ friend bool operator< (const GlobalSelector &LHS, const GlobalSelector &RHS) {
+ return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
+ }
+
+ // For use in DenseMap/DenseSet.
+ static GlobalSelector getEmptyMarker() { return GlobalSelector((void*)-1); }
+ static GlobalSelector getTombstoneMarker() {
+ return GlobalSelector((void*)-2);
+ }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that GlobalSelectors can be used as keys in DenseMap
+/// and DenseSets.
+template<>
+struct DenseMapInfo<clang::idx::GlobalSelector> {
+ static inline clang::idx::GlobalSelector getEmptyKey() {
+ return clang::idx::GlobalSelector::getEmptyMarker();
+ }
+
+ static inline clang::idx::GlobalSelector getTombstoneKey() {
+ return clang::idx::GlobalSelector::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::idx::GlobalSelector);
+
+ static inline bool
+ isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) {
+ return LHS == RHS;
+ }
+};
+
+template <>
+struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/Handlers.h b/contrib/llvm/tools/clang/include/clang/Index/Handlers.h
new file mode 100644
index 0000000..655aef9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/Handlers.h
@@ -0,0 +1,81 @@
+//===--- Handlers.h - Interfaces for receiving information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract interfaces for receiving information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_HANDLERS_H
+#define LLVM_CLANG_INDEX_HANDLERS_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+namespace idx {
+ class Entity;
+ class TranslationUnit;
+ class TULocation;
+
+/// \brief Abstract interface for receiving Entities.
+class EntityHandler {
+public:
+ typedef Entity receiving_type;
+
+ virtual ~EntityHandler();
+ virtual void Handle(Entity Ent) = 0;
+};
+
+/// \brief Abstract interface for receiving TranslationUnits.
+class TranslationUnitHandler {
+public:
+ typedef TranslationUnit* receiving_type;
+
+ virtual ~TranslationUnitHandler();
+ virtual void Handle(TranslationUnit *TU) = 0;
+};
+
+/// \brief Abstract interface for receiving TULocations.
+class TULocationHandler {
+public:
+ typedef TULocation receiving_type;
+
+ virtual ~TULocationHandler();
+ virtual void Handle(TULocation TULoc) = 0;
+};
+
+/// \brief Helper for the Handler classes. Stores the objects into a vector.
+/// example:
+/// @code
+/// Storing<TranslationUnitHandler> TURes;
+/// IndexProvider.GetTranslationUnitsFor(Entity, TURes);
+/// for (Storing<TranslationUnitHandler>::iterator
+/// I = TURes.begin(), E = TURes.end(); I != E; ++I) { ....
+/// @endcode
+template <typename handler_type>
+class Storing : public handler_type {
+ typedef typename handler_type::receiving_type receiving_type;
+ typedef llvm::SmallVector<receiving_type, 8> StoreTy;
+ StoreTy Store;
+
+public:
+ virtual void Handle(receiving_type Obj) {
+ Store.push_back(Obj);
+ }
+
+ typedef typename StoreTy::const_iterator iterator;
+ iterator begin() const { return Store.begin(); }
+ iterator end() const { return Store.end(); }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h b/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h
new file mode 100644
index 0000000..187dd93
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/IndexProvider.h
@@ -0,0 +1,38 @@
+//===--- IndexProvider.h - Maps information to translation units -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Maps information to TranslationUnits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXPROVIDER_H
+#define LLVM_CLANG_INDEX_INDEXPROVIDER_H
+
+namespace clang {
+
+namespace idx {
+ class Entity;
+ class TranslationUnitHandler;
+ class GlobalSelector;
+
+/// \brief Maps information to TranslationUnits.
+class IndexProvider {
+public:
+ virtual ~IndexProvider();
+ virtual void GetTranslationUnitsFor(Entity Ent,
+ TranslationUnitHandler &Handler) = 0;
+ virtual void GetTranslationUnitsFor(GlobalSelector Sel,
+ TranslationUnitHandler &Handler) = 0;
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/Indexer.h b/contrib/llvm/tools/clang/include/clang/Index/Indexer.h
new file mode 100644
index 0000000..96c585d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/Indexer.h
@@ -0,0 +1,71 @@
+//===--- Indexer.h - IndexProvider implementation ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// IndexProvider implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_INDEXER_H
+#define LLVM_CLANG_INDEX_INDEXER_H
+
+#include "clang/Index/IndexProvider.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/GlobalSelector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include <map>
+
+namespace clang {
+ class ASTContext;
+ class FunctionDecl;
+
+namespace idx {
+ class Program;
+ class TranslationUnit;
+
+/// \brief Maps information to TranslationUnits.
+class Indexer : public IndexProvider {
+public:
+ typedef llvm::SmallPtrSet<TranslationUnit *, 4> TUSetTy;
+ typedef llvm::DenseMap<ASTContext *, TranslationUnit *> CtxTUMapTy;
+ typedef std::map<Entity, TUSetTy> MapTy;
+ typedef std::map<GlobalSelector, TUSetTy> SelMapTy;
+ typedef std::map<Entity, std::pair<FunctionDecl*,TranslationUnit*> > DefMapTy;
+
+ explicit Indexer(Program &prog) :
+ Prog(prog) { }
+
+ Program &getProgram() const { return Prog; }
+
+ /// \brief Find all Entities and map them to the given translation unit.
+ void IndexAST(TranslationUnit *TU);
+
+ virtual void GetTranslationUnitsFor(Entity Ent,
+ TranslationUnitHandler &Handler);
+ virtual void GetTranslationUnitsFor(GlobalSelector Sel,
+ TranslationUnitHandler &Handler);
+
+ std::pair<FunctionDecl*, TranslationUnit*> getDefinitionFor(Entity Ent);
+
+private:
+ Program &Prog;
+
+ MapTy Map;
+ // Map a function Entity to the its definition.
+ DefMapTy DefMap;
+
+ CtxTUMapTy CtxTUMap;
+ SelMapTy SelMap;
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/Program.h b/contrib/llvm/tools/clang/include/clang/Index/Program.h
new file mode 100644
index 0000000..8039192
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/Program.h
@@ -0,0 +1,45 @@
+//===--- Program.h - Cross-translation unit information ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the idx::Program interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_PROGRAM_H
+#define LLVM_CLANG_INDEX_PROGRAM_H
+
+namespace clang {
+ class ASTContext;
+
+namespace idx {
+ class EntityHandler;
+
+/// \brief Top level object that owns and maintains information
+/// that is common across translation units.
+class Program {
+ void *Impl;
+
+ Program(const Program&); // do not implement
+ Program &operator=(const Program &); // do not implement
+ friend class Entity;
+ friend class GlobalSelector;
+
+public:
+ Program();
+ ~Program();
+
+ /// \brief Traverses the AST and passes all the entities to the Handler.
+ void FindEntities(ASTContext &Ctx, EntityHandler &Handler);
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h b/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h
new file mode 100644
index 0000000..a3693c6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/STLExtras.h
@@ -0,0 +1,63 @@
+//===--- STLExtras.h - Helper STL related templates -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Helper templates for using with the STL.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_STLEXTRAS_H
+#define LLVM_CLANG_INDEX_STLEXTRAS_H
+
+namespace clang {
+
+namespace idx {
+
+/// \brief Wraps an iterator whose value_type is a pair, and provides
+/// pair's second object as the value.
+template <typename iter_type>
+class pair_value_iterator {
+ iter_type I;
+
+public:
+ typedef typename iter_type::value_type::second_type value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef typename iter_type::iterator_category iterator_category;
+ typedef typename iter_type::difference_type difference_type;
+
+ pair_value_iterator() { }
+ pair_value_iterator(iter_type i) : I(i) { }
+
+ reference operator*() const { return I->second; }
+ pointer operator->() const { return &I->second; }
+
+ pair_value_iterator& operator++() {
+ ++I;
+ return *this;
+ }
+
+ pair_value_iterator operator++(int) {
+ pair_value_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(pair_value_iterator L, pair_value_iterator R) {
+ return L.I == R.I;
+ }
+ friend bool operator!=(pair_value_iterator L, pair_value_iterator R) {
+ return L.I != R.I;
+ }
+};
+
+} // end idx namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h b/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h
new file mode 100644
index 0000000..be01702
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/SelectorMap.h
@@ -0,0 +1,57 @@
+//===--- SelectorMap.h - Maps selectors to methods and messages -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SelectorMap creates a mapping from selectors to ObjC method declarations
+// and ObjC message expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_SELECTORMAP_H
+#define LLVM_CLANG_INDEX_SELECTORMAP_H
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/Index/STLExtras.h"
+#include "clang/Basic/IdentifierTable.h"
+#include <map>
+
+namespace clang {
+ class ASTContext;
+ class ObjCMethodDecl;
+
+namespace idx {
+
+/// \brief Maps NamedDecls with the ASTLocations that reference them.
+///
+/// References are mapped and retrieved using the canonical decls.
+class SelectorMap {
+public:
+ explicit SelectorMap(ASTContext &Ctx);
+
+ typedef std::multimap<Selector, ObjCMethodDecl *> SelMethMapTy;
+ typedef std::multimap<Selector, ASTLocation> SelRefMapTy;
+
+ typedef pair_value_iterator<SelMethMapTy::iterator> method_iterator;
+ typedef pair_value_iterator<SelRefMapTy::iterator> astlocation_iterator;
+
+ method_iterator methods_begin(Selector Sel) const;
+ method_iterator methods_end(Selector Sel) const;
+
+ astlocation_iterator refs_begin(Selector Sel) const;
+ astlocation_iterator refs_end(Selector Sel) const;
+
+private:
+ mutable SelMethMapTy SelMethMap;
+ mutable SelRefMapTy SelRefMap;
+};
+
+} // end idx namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h b/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h
new file mode 100644
index 0000000..0099d63
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/TranslationUnit.h
@@ -0,0 +1,41 @@
+//===--- TranslationUnit.h - Interface for a translation unit ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract interface for a translation unit.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
+#define LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
+
+namespace clang {
+ class ASTContext;
+ class Diagnostic;
+ class Preprocessor;
+
+namespace idx {
+ class DeclReferenceMap;
+ class SelectorMap;
+
+/// \brief Abstract interface for a translation unit.
+class TranslationUnit {
+public:
+ virtual ~TranslationUnit();
+ virtual ASTContext &getASTContext() = 0;
+ virtual Preprocessor &getPreprocessor() = 0;
+ virtual Diagnostic &getDiagnostic() = 0;
+ virtual DeclReferenceMap &getDeclReferenceMap() = 0;
+ virtual SelectorMap &getSelectorMap() = 0;
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h b/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
new file mode 100644
index 0000000..d28a3aa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -0,0 +1,67 @@
+//===--- CodeCompletionHandler.h - Preprocessor code completion -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeCompletionHandler interface, which provides
+// code-completion callbacks for the preprocessor.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+
+namespace clang {
+
+class IdentifierInfo;
+class MacroInfo;
+
+/// \brief Callback handler that receives notifications when performing code
+/// completion within the preprocessor.
+class CodeCompletionHandler {
+public:
+ virtual ~CodeCompletionHandler();
+
+ /// \brief Callback invoked when performing code completion for a preprocessor
+ /// directive.
+ ///
+ /// This callback will be invoked when the preprocessor processes a '#' at the
+ /// start of a line, followed by the code-completion token.
+ ///
+ /// \param InConditional Whether we're inside a preprocessor conditional
+ /// already.
+ virtual void CodeCompleteDirective(bool InConditional) { }
+
+ /// \brief Callback invoked when performing code completion within a block of
+ /// code that was excluded due to preprocessor conditionals.
+ virtual void CodeCompleteInConditionalExclusion() { }
+
+ /// \brief Callback invoked when performing code completion in a context
+ /// where the name of a macro is expected.
+ ///
+ /// \param IsDefinition Whether this is the definition of a macro, e.g.,
+ /// in a #define.
+ virtual void CodeCompleteMacroName(bool IsDefinition) { }
+
+ /// \brief Callback invoked when performing code completion in a preprocessor
+ /// expression, such as the condition of an #if or #elif directive.
+ virtual void CodeCompletePreprocessorExpression() { }
+
+ /// \brief Callback invoked when performing code completion inside a
+ /// function-like macro argument.
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) { }
+
+ /// \brief Callback invoked when performing code completion in a part of the
+ /// file where we expect natural language, e.g., a comment, string, or
+ /// #error directive.
+ virtual void CodeCompleteNaturalLanguage() { }
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
new file mode 100644
index 0000000..64687a1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
@@ -0,0 +1,134 @@
+//===--- DirectoryLookup.h - Info for searching for headers -----*- 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 DirectoryLookup interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+#define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+
+#include "clang/Basic/SourceManager.h"
+
+namespace llvm {
+ class StringRef;
+}
+namespace clang {
+class HeaderMap;
+class DirectoryEntry;
+class FileEntry;
+class HeaderSearch;
+
+/// DirectoryLookup - This class represents one entry in the search list that
+/// specifies the search order for directories in #include directives. It
+/// represents either a directory, a framework, or a headermap.
+///
+class DirectoryLookup {
+public:
+ enum LookupType_t {
+ LT_NormalDir,
+ LT_Framework,
+ LT_HeaderMap
+ };
+private:
+ union { // This union is discriminated by isHeaderMap.
+ /// Dir - This is the actual directory that we're referring to for a normal
+ /// directory or a framework.
+ const DirectoryEntry *Dir;
+
+ /// Map - This is the HeaderMap if this is a headermap lookup.
+ ///
+ const HeaderMap *Map;
+ } u;
+
+ /// DirCharacteristic - The type of directory this is: this is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirCharacteristic : 2;
+
+ /// UserSupplied - True if this is a user-supplied directory.
+ ///
+ bool UserSupplied : 1;
+
+ /// LookupType - This indicates whether this DirectoryLookup object is a
+ /// normal directory, a framework, or a headermap.
+ unsigned LookupType : 2;
+public:
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'dir'.
+ DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT,
+ bool isUser, bool isFramework)
+ : DirCharacteristic(DT), UserSupplied(isUser),
+ LookupType(isFramework ? LT_Framework : LT_NormalDir) {
+ u.Dir = dir;
+ }
+
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'map'.
+ DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT,
+ bool isUser)
+ : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) {
+ u.Map = map;
+ }
+
+ /// getLookupType - Return the kind of directory lookup that this is: either a
+ /// normal directory, a framework path, or a HeaderMap.
+ LookupType_t getLookupType() const { return (LookupType_t)LookupType; }
+
+ /// getName - Return the directory or filename corresponding to this lookup
+ /// object.
+ const char *getName() const;
+
+ /// getDir - Return the directory that this entry refers to.
+ ///
+ const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; }
+
+ /// getFrameworkDir - Return the directory that this framework refers to.
+ ///
+ const DirectoryEntry *getFrameworkDir() const {
+ return isFramework() ? u.Dir : 0;
+ }
+
+ /// getHeaderMap - Return the directory that this entry refers to.
+ ///
+ const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; }
+
+ /// isNormalDir - Return true if this is a normal directory, not a header map.
+ bool isNormalDir() const { return getLookupType() == LT_NormalDir; }
+
+ /// isFramework - True if this is a framework directory.
+ ///
+ bool isFramework() const { return getLookupType() == LT_Framework; }
+
+ /// isHeaderMap - Return true if this is a header map, not a normal directory.
+ bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
+
+ /// DirCharacteristic - The type of directory this is, one of the DirType enum
+ /// values.
+ SrcMgr::CharacteristicKind getDirCharacteristic() const {
+ return (SrcMgr::CharacteristicKind)DirCharacteristic;
+ }
+
+ /// isUserSupplied - True if this is a user-supplied directory.
+ ///
+ bool isUserSupplied() const { return UserSupplied; }
+
+
+ /// LookupFile - Lookup the specified file in this search path, returning it
+ /// if it exists or returning null if not.
+ const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const;
+
+private:
+ const FileEntry *DoFrameworkLookup(llvm::StringRef Filename,
+ HeaderSearch &HS) const;
+
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
new file mode 100644
index 0000000..dbf7389
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
@@ -0,0 +1,37 @@
+//===- ExternalPreprocessorSource.h - Abstract Macro Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalPreprocessorSource interface, which enables
+// construction of macro definitions from some external source.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
+#define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
+
+namespace clang {
+
+/// \brief Abstract interface for external sources of preprocessor
+/// information.
+///
+/// This abstract class allows an external sources (such as the \c ASTReader)
+/// to provide additional macro definitions.
+class ExternalPreprocessorSource {
+public:
+ virtual ~ExternalPreprocessorSource();
+
+ /// \brief Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros() = 0;
+
+ /// \brief Read the definition for the given macro.
+ virtual void LoadMacroDefinition(IdentifierInfo *II) = 0;
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h
new file mode 100644
index 0000000..8a5c83e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h
@@ -0,0 +1,67 @@
+//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- 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 HeaderMap interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERMAP_H
+#define LLVM_CLANG_LEX_HEADERMAP_H
+
+namespace llvm {
+ class MemoryBuffer;
+ class StringRef;
+}
+namespace clang {
+ class FileEntry;
+ class FileManager;
+ struct HMapBucket;
+ struct HMapHeader;
+
+/// This class represents an Apple concept known as a 'header map'. To the
+/// #include file resolution process, it basically acts like a directory of
+/// symlinks to files. Its advantages are that it is dense and more efficient
+/// to create and process than a directory of symlinks.
+class HeaderMap {
+ HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT
+ void operator=(const HeaderMap&); // DO NOT IMPLEMENT
+
+ const llvm::MemoryBuffer *FileBuffer;
+ bool NeedsBSwap;
+
+ HeaderMap(const llvm::MemoryBuffer *File, bool BSwap)
+ : FileBuffer(File), NeedsBSwap(BSwap) {
+ }
+public:
+ ~HeaderMap();
+
+ /// HeaderMap::Create - This attempts to load the specified file as a header
+ /// map. If it doesn't look like a HeaderMap, it gives up and returns null.
+ static const HeaderMap *Create(const FileEntry *FE, FileManager &FM);
+
+ /// LookupFile - Check to see if the specified relative filename is located in
+ /// this HeaderMap. If so, open it and return its FileEntry.
+ const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const;
+
+ /// getFileName - Return the filename of the headermap.
+ const char *getFileName() const;
+
+ /// dump - Print the contents of this headermap to stderr.
+ void dump() const;
+
+private:
+ unsigned getEndianAdjustedWord(unsigned X) const;
+ const HMapHeader &getHeader() const;
+ HMapBucket getBucket(unsigned BucketNo) const;
+ const char *getString(unsigned StrTabIdx) const;
+};
+
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
new file mode 100644
index 0000000..30bd4f5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
@@ -0,0 +1,274 @@
+//===--- HeaderSearch.h - Resolve Header File Locations ---------*- 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 HeaderSearch interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
+#define LLVM_CLANG_LEX_HEADERSEARCH_H
+
+#include "clang/Lex/DirectoryLookup.h"
+#include "llvm/ADT/StringMap.h"
+#include <vector>
+
+namespace clang {
+
+class ExternalIdentifierLookup;
+class FileEntry;
+class FileManager;
+class IdentifierInfo;
+
+/// HeaderFileInfo - The preprocessor keeps track of this information for each
+/// file that is #included.
+struct HeaderFileInfo {
+ /// isImport - True if this is a #import'd or #pragma once file.
+ unsigned isImport : 1;
+
+ /// DirInfo - Keep track of whether this is a system header, and if so,
+ /// whether it is C++ clean or not. This can be set by the include paths or
+ /// by #pragma gcc system_header. This is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirInfo : 2;
+
+ /// \brief Whether this header file info was supplied by an external source.
+ unsigned External : 1;
+
+ /// \brief Whether this structure is considered to already have been
+ /// "resolved", meaning that it was loaded from the external source.
+ unsigned Resolved : 1;
+
+ /// NumIncludes - This is the number of times the file has been included
+ /// already.
+ unsigned short NumIncludes;
+
+ /// \brief The ID number of the controlling macro.
+ ///
+ /// This ID number will be non-zero when there is a controlling
+ /// macro whose IdentifierInfo may not yet have been loaded from
+ /// external storage.
+ unsigned ControllingMacroID;
+
+ /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
+ /// that protects the entire contents of the file, this is the identifier
+ /// for the macro that controls whether or not it has any effect.
+ ///
+ /// Note: Most clients should use getControllingMacro() to access
+ /// the controlling macro of this header, since
+ /// getControllingMacro() is able to load a controlling macro from
+ /// external storage.
+ const IdentifierInfo *ControllingMacro;
+
+ HeaderFileInfo()
+ : isImport(false), DirInfo(SrcMgr::C_User), External(false),
+ Resolved(false), NumIncludes(0), ControllingMacroID(0),
+ ControllingMacro(0) {}
+
+ /// \brief Retrieve the controlling macro for this header file, if
+ /// any.
+ const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External);
+
+ /// \brief Determine whether this is a non-default header file info, e.g.,
+ /// it corresponds to an actual header we've included or tried to include.
+ bool isNonDefault() const {
+ return isImport || NumIncludes || ControllingMacro || ControllingMacroID;
+ }
+};
+
+/// \brief An external source of header file information, which may supply
+/// information about header files already included.
+class ExternalHeaderFileInfoSource {
+public:
+ virtual ~ExternalHeaderFileInfoSource();
+
+ /// \brief Retrieve the header file information for the given file entry.
+ ///
+ /// \returns Header file information for the given file entry, with the
+ /// \c External bit set. If the file entry is not known, return a
+ /// default-constructed \c HeaderFileInfo.
+ virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
+};
+
+/// HeaderSearch - This class encapsulates the information needed to find the
+/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
+class HeaderSearch {
+ FileManager &FileMgr;
+ /// #include search path information. Requests for #include "x" search the
+ /// directory of the #including file first, then each directory in SearchDirs
+ /// consequtively. Requests for <x> search the current dir first, then each
+ /// directory in SearchDirs, starting at SystemDirIdx, consequtively. If
+ /// NoCurDirSearch is true, then the check for the file in the current
+ /// directory is supressed.
+ std::vector<DirectoryLookup> SearchDirs;
+ unsigned SystemDirIdx;
+ bool NoCurDirSearch;
+
+ /// FileInfo - This contains all of the preprocessor-specific data about files
+ /// that are included. The vector is indexed by the FileEntry's UID.
+ ///
+ std::vector<HeaderFileInfo> FileInfo;
+
+ /// LookupFileCache - This is keeps track of each lookup performed by
+ /// LookupFile. The first part of the value is the starting index in
+ /// SearchDirs that the cached search was performed from. If there is a hit
+ /// and this value doesn't match the current query, the cache has to be
+ /// ignored. The second value is the entry in SearchDirs that satisfied the
+ /// query.
+ llvm::StringMap<std::pair<unsigned, unsigned> > LookupFileCache;
+
+
+ /// FrameworkMap - This is a collection mapping a framework or subframework
+ /// name like "Carbon" to the Carbon.framework directory.
+ llvm::StringMap<const DirectoryEntry *> FrameworkMap;
+
+ /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
+ /// headermaps. This vector owns the headermap.
+ std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
+
+ /// \brief Entity used to resolve the identifier IDs of controlling
+ /// macros into IdentifierInfo pointers, as needed.
+ ExternalIdentifierLookup *ExternalLookup;
+
+ /// \brief Entity used to look up stored header file information.
+ ExternalHeaderFileInfoSource *ExternalSource;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumIncluded;
+ unsigned NumMultiIncludeFileOptzn;
+ unsigned NumFrameworkLookups, NumSubFrameworkLookups;
+
+ // HeaderSearch doesn't support default or copy construction.
+ explicit HeaderSearch();
+ explicit HeaderSearch(const HeaderSearch&);
+ void operator=(const HeaderSearch&);
+public:
+ HeaderSearch(FileManager &FM);
+ ~HeaderSearch();
+
+ FileManager &getFileMgr() const { return FileMgr; }
+
+ /// SetSearchPaths - Interface for setting the file search paths.
+ ///
+ void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
+ unsigned systemDirIdx, bool noCurDirSearch) {
+ SearchDirs = dirs;
+ SystemDirIdx = systemDirIdx;
+ NoCurDirSearch = noCurDirSearch;
+ //LookupFileCache.clear();
+ }
+
+ /// ClearFileInfo - Forget everything we know about headers so far.
+ void ClearFileInfo() {
+ FileInfo.clear();
+ }
+
+ void SetExternalLookup(ExternalIdentifierLookup *EIL) {
+ ExternalLookup = EIL;
+ }
+
+ ExternalIdentifierLookup *getExternalLookup() const {
+ return ExternalLookup;
+ }
+
+ /// \brief Set the external source of header information.
+ void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
+ ExternalSource = ES;
+ }
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// a <> reference. If successful, this returns 'UsedDir', the
+ /// DirectoryLookup member the file was found in, or null if not applicable.
+ /// If CurDir is non-null, the file was found in the specified directory
+ /// search location. This is used to implement #include_next. CurFileEnt, if
+ /// non-null, indicates where the #including file is, in case a relative
+ /// search is needed.
+ const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir,
+ const FileEntry *CurFileEnt);
+
+ /// LookupSubframeworkHeader - Look up a subframework for the specified
+ /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
+ /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
+ /// is a subframework within Carbon.framework. If so, return the FileEntry
+ /// for the designated file, otherwise return null.
+ const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename,
+ const FileEntry *RelativeFileEnt);
+
+ /// LookupFrameworkCache - Look up the specified framework name in our
+ /// framework cache, returning the DirectoryEntry it is in if we know,
+ /// otherwise, return null.
+ const DirectoryEntry *&LookupFrameworkCache(llvm::StringRef FWName) {
+ return FrameworkMap.GetOrCreateValue(FWName).getValue();
+ }
+
+ /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
+ /// #include, #include_next, or #import directive. Return false if #including
+ /// the file will have no effect or true if we should include it.
+ bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
+
+
+ /// getFileDirFlavor - Return whether the specified file is a normal header,
+ /// a system header, or a C++ friendly system header.
+ SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
+ return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
+ }
+
+ /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
+ /// due to #pragma once.
+ void MarkFileIncludeOnce(const FileEntry *File) {
+ getFileInfo(File).isImport = true;
+ }
+
+ /// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
+ /// due to #pragma GCC system_header.
+ void MarkFileSystemHeader(const FileEntry *File) {
+ getFileInfo(File).DirInfo = SrcMgr::C_System;
+ }
+
+ /// IncrementIncludeCount - Increment the count for the number of times the
+ /// specified FileEntry has been entered.
+ void IncrementIncludeCount(const FileEntry *File) {
+ ++getFileInfo(File).NumIncludes;
+ }
+
+ /// SetFileControllingMacro - Mark the specified file as having a controlling
+ /// macro. This is used by the multiple-include optimization to eliminate
+ /// no-op #includes.
+ void SetFileControllingMacro(const FileEntry *File,
+ const IdentifierInfo *ControllingMacro) {
+ getFileInfo(File).ControllingMacro = ControllingMacro;
+ }
+
+ /// CreateHeaderMap - This method returns a HeaderMap for the specified
+ /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+ const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+
+ void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
+
+ typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
+ header_file_iterator header_file_begin() const { return FileInfo.begin(); }
+ header_file_iterator header_file_end() const { return FileInfo.end(); }
+ unsigned header_file_size() const { return FileInfo.size(); }
+
+ // Used by ASTReader.
+ void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
+
+ void PrintStats();
+private:
+
+ /// getFileInfo - Return the HeaderFileInfo structure for the specified
+ /// FileEntry.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h
new file mode 100644
index 0000000..5fcb8eb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticLex.h - Diagnostics for liblex ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICLEX_H
+#define LLVM_CLANG_DIAGNOSTICLEX_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define LEXSTART
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_LEX_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
new file mode 100644
index 0000000..fc9a8de
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
@@ -0,0 +1,466 @@
+//===--- Lexer.h - C Language Family Lexer ----------------------*- 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 Lexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEXER_H
+#define LLVM_CLANG_LEXER_H
+
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+#include <vector>
+#include <cassert>
+
+namespace clang {
+class Diagnostic;
+class SourceManager;
+class Preprocessor;
+class DiagnosticBuilder;
+
+/// Lexer - This provides a simple interface that turns a text buffer into a
+/// stream of tokens. This provides no support for file reading or buffering,
+/// or buffering/seeking of tokens, only forward lexing is supported. It relies
+/// on the specified Preprocessor object to handle preprocessor directives, etc.
+class Lexer : public PreprocessorLexer {
+ //===--------------------------------------------------------------------===//
+ // Constant configuration values for this lexer.
+ const char *BufferStart; // Start of the buffer.
+ const char *BufferEnd; // End of the buffer.
+ SourceLocation FileLoc; // Location for start of file.
+ LangOptions Features; // Features enabled by this language (cache).
+ bool Is_PragmaLexer : 1; // True if lexer for _Pragma handling.
+ bool IsInConflictMarker : 1; // True if in a VCS conflict marker '<<<<<<<'
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //
+
+ /// ExtendedTokenMode - The lexer can optionally keep comments and whitespace
+ /// and return them as tokens. This is used for -C and -CC modes, and
+ /// whitespace preservation can be useful for some clients that want to lex
+ /// the file in raw mode and get every character from the file.
+ ///
+ /// When this is set to 2 it returns comments and whitespace. When set to 1
+ /// it returns comments, when it is set to 0 it returns normal tokens only.
+ unsigned char ExtendedTokenMode;
+
+ //===--------------------------------------------------------------------===//
+ // Context that changes as the file is lexed.
+ // NOTE: any state that mutates when in raw mode must have save/restore code
+ // in Lexer::isNextPPTokenLParen.
+
+ // BufferPtr - Current pointer into the buffer. This is the next character
+ // to be lexed.
+ const char *BufferPtr;
+
+ // IsAtStartOfLine - True if the next lexed token should get the "start of
+ // line" flag set on it.
+ bool IsAtStartOfLine;
+
+ Lexer(const Lexer&); // DO NOT IMPLEMENT
+ void operator=(const Lexer&); // DO NOT IMPLEMENT
+ friend class Preprocessor;
+
+ void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd);
+public:
+
+ /// Lexer constructor - Create a new lexer object for the specified buffer
+ /// with the specified preprocessor managing the lexing process. This lexer
+ /// assumes that the associated file buffer and Preprocessor objects will
+ /// outlive it, so it doesn't take ownership of either of them.
+ Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+ /// range will outlive it, so it doesn't take ownership of it.
+ Lexer(SourceLocation FileLoc, const LangOptions &Features,
+ const char *BufStart, const char *BufPtr, const char *BufEnd);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+ /// range will outlive it, so it doesn't take ownership of it.
+ Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer,
+ const SourceManager &SM, const LangOptions &Features);
+
+ /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
+ /// _Pragma expansion. This has a variety of magic semantics that this method
+ /// sets up. It returns a new'd Lexer that must be delete'd when done.
+ static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc,
+ SourceLocation InstantiationLocStart,
+ SourceLocation InstantiationLocEnd,
+ unsigned TokLen, Preprocessor &PP);
+
+
+ /// getFeatures - Return the language features currently enabled. NOTE: this
+ /// lexer modifies features as a file is parsed!
+ const LangOptions &getFeatures() const { return Features; }
+
+ /// getFileLoc - Return the File Location for the file we are lexing out of.
+ /// The physical location encodes the location where the characters come from,
+ /// the virtual location encodes where we should *claim* the characters came
+ /// from. Currently this is only used by _Pragma handling.
+ SourceLocation getFileLoc() const { return FileLoc; }
+
+ /// Lex - Return the next token in the file. If this is the end of file, it
+ /// return the tok::eof token. Return true if an error occurred and
+ /// compilation should terminate, false if normal. This implicitly involves
+ /// the preprocessor.
+ void Lex(Token &Result) {
+ // Start a new token.
+ Result.startToken();
+
+ // NOTE, any changes here should also change code after calls to
+ // Preprocessor::HandleDirective
+ if (IsAtStartOfLine) {
+ Result.setFlag(Token::StartOfLine);
+ IsAtStartOfLine = false;
+ }
+
+ // Get a token. Note that this may delete the current lexer if the end of
+ // file is reached.
+ LexTokenInternal(Result);
+ }
+
+ /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
+ bool isPragmaLexer() const { return Is_PragmaLexer; }
+
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) { Lex(Result); }
+
+ /// LexFromRawLexer - Lex a token from a designated raw lexer (one with no
+ /// associated preprocessor object. Return true if the 'next character to
+ /// read' pointer points at the end of the lexer buffer, false otherwise.
+ bool LexFromRawLexer(Token &Result) {
+ assert(LexingRawMode && "Not already in raw mode!");
+ Lex(Result);
+ // Note that lexing to the end of the buffer doesn't implicitly delete the
+ // lexer when in raw mode.
+ return BufferPtr == BufferEnd;
+ }
+
+ /// isKeepWhitespaceMode - Return true if the lexer should return tokens for
+ /// every character in the file, including whitespace and comments. This
+ /// should only be used in raw mode, as the preprocessor is not prepared to
+ /// deal with the excess tokens.
+ bool isKeepWhitespaceMode() const {
+ return ExtendedTokenMode > 1;
+ }
+
+ /// SetKeepWhitespaceMode - This method lets clients enable or disable
+ /// whitespace retention mode.
+ void SetKeepWhitespaceMode(bool Val) {
+ assert((!Val || LexingRawMode) &&
+ "Can only enable whitespace retention in raw mode");
+ ExtendedTokenMode = Val ? 2 : 0;
+ }
+
+ /// inKeepCommentMode - Return true if the lexer should return comments as
+ /// tokens.
+ bool inKeepCommentMode() const {
+ return ExtendedTokenMode > 0;
+ }
+
+ /// SetCommentRetentionMode - Change the comment retention mode of the lexer
+ /// to the specified mode. This is really only useful when lexing in raw
+ /// mode, because otherwise the lexer needs to manage this.
+ void SetCommentRetentionState(bool Mode) {
+ assert(!isKeepWhitespaceMode() &&
+ "Can't play with comment retention state when retaining whitespace");
+ ExtendedTokenMode = Mode ? 1 : 0;
+ }
+
+ const char *getBufferStart() const { return BufferStart; }
+
+ /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ std::string ReadToEndOfLine();
+
+
+ /// Diag - Forwarding function for diagnostics. This translate a source
+ /// position in the current buffer into a SourceLocation object for rendering.
+ DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const;
+
+ /// getSourceLocation - Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getSourceLocation(const char *Loc, unsigned TokLen = 1) const;
+
+ /// getSourceLocation - Return a source location for the next character in
+ /// the current file.
+ SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); }
+
+ /// \brief Return the current location in the buffer.
+ const char *getBufferLocation() const { return BufferPtr; }
+
+ /// Stringify - Convert the specified string into a C string by escaping '\'
+ /// and " characters. This does not add surrounding ""'s to the string.
+ /// If Charify is true, this escapes the ' character instead of ".
+ static std::string Stringify(const std::string &Str, bool Charify = false);
+
+ /// Stringify - Convert the specified string into a C string by escaping '\'
+ /// and " characters. This does not add surrounding ""'s to the string.
+ static void Stringify(llvm::SmallVectorImpl<char> &Str);
+
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// preallocated buffer, instead of as an std::string. The caller is required
+ /// to allocate enough space for the token, which is guaranteed to be at least
+ /// Tok.getLength() bytes long. The length of the actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ static unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features,
+ bool *Invalid = 0);
+
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ static std::string getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features,
+ bool *Invalid = 0);
+
+ /// MeasureTokenLength - Relex the token at the specified location and return
+ /// its length in bytes in the input file. If the token needs cleaning (e.g.
+ /// includes a trigraph or an escaped newline) then this count includes bytes
+ /// that are part of that.
+ static unsigned MeasureTokenLength(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// \brief Given a location any where in a source buffer, find the location
+ /// that corresponds to the beginning of the token in which the original
+ /// source location lands.
+ ///
+ /// \param Loc
+ static SourceLocation GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// AdvanceToTokenCharacter - If the current SourceLocation specifies a
+ /// location at the start of a token, return a new location that specifies a
+ /// character within the token. This handles trigraphs and escaped newlines.
+ static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Character,
+ const SourceManager &SM,
+ const LangOptions &Features);
+
+ /// \brief Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
+ const SourceManager &SM,
+ const LangOptions &Features);
+
+ /// \brief Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \param MaxLines If non-zero, restrict the length of the preamble
+ /// to fewer than this number of lines.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins along with a boolean value indicating whether
+ /// the preamble ends at the beginning of a new line.
+ static std::pair<unsigned, bool>
+ ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines = 0);
+
+ //===--------------------------------------------------------------------===//
+ // Internal implementation interfaces.
+private:
+
+ /// LexTokenInternal - Internal interface to lex a preprocessing token. Called
+ /// by Lex.
+ ///
+ void LexTokenInternal(Token &Result);
+
+ /// FormTokenWithChars - When we lex a token, we have identified a span
+ /// starting at BufferPtr, going to TokEnd that forms the token. This method
+ /// takes that range and assigns it to the token as its location and size. In
+ /// addition, since tokens cannot overlap, this also updates BufferPtr to be
+ /// TokEnd.
+ void FormTokenWithChars(Token &Result, const char *TokEnd,
+ tok::TokenKind Kind) {
+ unsigned TokLen = TokEnd-BufferPtr;
+ Result.setLength(TokLen);
+ Result.setLocation(getSourceLocation(BufferPtr, TokLen));
+ Result.setKind(Kind);
+ BufferPtr = TokEnd;
+ }
+
+ /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
+ /// tok::l_paren token, 0 if it is something else and 2 if there are no more
+ /// tokens in the buffer controlled by this lexer.
+ unsigned isNextPPTokenLParen();
+
+ //===--------------------------------------------------------------------===//
+ // Lexer character reading interfaces.
+public:
+
+ // This lexer is built on two interfaces for reading characters, both of which
+ // automatically provide phase 1/2 translation. getAndAdvanceChar is used
+ // when we know that we will be reading a character from the input buffer and
+ // that this character will be part of the result token. This occurs in (f.e.)
+ // string processing, because we know we need to read until we find the
+ // closing '"' character.
+ //
+ // The second interface is the combination of getCharAndSize with
+ // ConsumeChar. getCharAndSize reads a phase 1/2 translated character,
+ // returning it and its size. If the lexer decides that this character is
+ // part of the current token, it calls ConsumeChar on it. This two stage
+ // approach allows us to emit diagnostics for characters (e.g. warnings about
+ // trigraphs), knowing that they only are emitted if the character is
+ // consumed.
+
+ /// isObviouslySimpleCharacter - Return true if the specified character is
+ /// obviously the same in translation phase 1 and translation phase 3. This
+ /// can return false for characters that end up being the same, but it will
+ /// never return true for something that needs to be mapped.
+ static bool isObviouslySimpleCharacter(char C) {
+ return C != '?' && C != '\\';
+ }
+
+ /// getAndAdvanceChar - Read a single 'character' from the specified buffer,
+ /// advance over it, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getAndAdvanceChar(const char *&Ptr, Token &Tok) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) return *Ptr++;
+
+ unsigned Size = 0;
+ char C = getCharAndSizeSlow(Ptr, Size, &Tok);
+ Ptr += Size;
+ return C;
+ }
+
+private:
+ /// ConsumeChar - When a character (identified by getCharAndSize) is consumed
+ /// and added to a given token, check to see if there are diagnostics that
+ /// need to be emitted or flags that need to be set on the token. If so, do
+ /// it.
+ const char *ConsumeChar(const char *Ptr, unsigned Size, Token &Tok) {
+ // Normal case, we consumed exactly one token. Just return it.
+ if (Size == 1)
+ return Ptr+Size;
+
+ // Otherwise, re-lex the character with a current token, allowing
+ // diagnostics to be emitted and flags to be set.
+ Size = 0;
+ getCharAndSizeSlow(Ptr, Size, &Tok);
+ return Ptr+Size;
+ }
+
+ /// getCharAndSize - Peek a single 'character' from the specified buffer,
+ /// get its size, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getCharAndSize(const char *Ptr, unsigned &Size) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlow(Ptr, Size);
+ }
+
+ /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize
+ /// method.
+ char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0);
+public:
+
+ /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
+ /// emit a warning.
+ static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &Features) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlowNoWarn(Ptr, Size, Features);
+ }
+
+ /// getEscapedNewLineSize - Return the size of the specified escaped newline,
+ /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry
+ /// to this function.
+ static unsigned getEscapedNewLineSize(const char *P);
+
+ /// SkipEscapedNewLines - If P points to an escaped newline (or a series of
+ /// them), skip over them and return the first non-escaped-newline found,
+ /// otherwise return P.
+ static const char *SkipEscapedNewLines(const char *P);
+private:
+
+ /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
+ /// diagnostic.
+ static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &Features);
+
+ //===--------------------------------------------------------------------===//
+ // Other lexer functions.
+
+ void SkipBytes(unsigned Bytes, bool StartOfLine);
+
+ // Helper functions to lex the remainder of a token of the specific type.
+ void LexIdentifier (Token &Result, const char *CurPtr);
+ void LexNumericConstant (Token &Result, const char *CurPtr);
+ void LexStringLiteral (Token &Result, const char *CurPtr,bool Wide);
+ void LexAngledStringLiteral(Token &Result, const char *CurPtr);
+ void LexCharConstant (Token &Result, const char *CurPtr);
+ bool LexEndOfFile (Token &Result, const char *CurPtr);
+
+ bool SkipWhitespace (Token &Result, const char *CurPtr);
+ bool SkipBCPLComment (Token &Result, const char *CurPtr);
+ bool SkipBlockComment (Token &Result, const char *CurPtr);
+ bool SaveBCPLComment (Token &Result, const char *CurPtr);
+
+ bool IsStartOfConflictMarker(const char *CurPtr);
+ bool HandleEndOfConflictMarker(const char *CurPtr);
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
new file mode 100644
index 0000000..bf2c06b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
@@ -0,0 +1,191 @@
+//===--- LiteralSupport.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NumericLiteralParser, CharLiteralParser, and
+// StringLiteralParser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LITERALSUPPORT_H
+#define CLANG_LITERALSUPPORT_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/DataTypes.h"
+#include <cctype>
+#include <string>
+
+namespace clang {
+
+class Diagnostic;
+class Preprocessor;
+class Token;
+class SourceLocation;
+class TargetInfo;
+class SourceManager;
+class LangOptions;
+
+/// NumericLiteralParser - This performs strict semantic analysis of the content
+/// of a ppnumber, classifying it as either integer, floating, or erroneous,
+/// determines the radix of the value and can convert it to a useful value.
+class NumericLiteralParser {
+ Preprocessor &PP; // needed for diagnostics
+
+ const char *const ThisTokBegin;
+ const char *const ThisTokEnd;
+ const char *DigitsBegin, *SuffixBegin; // markers
+ const char *s; // cursor
+
+ unsigned radix;
+
+ bool saw_exponent, saw_period;
+
+public:
+ NumericLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP);
+ bool hadError;
+ bool isUnsigned;
+ bool isLong; // This is *not* set for long long.
+ bool isLongLong;
+ bool isFloat; // 1.0f
+ bool isImaginary; // 1.0i
+ bool isMicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
+
+ bool isIntegerLiteral() const {
+ return !saw_period && !saw_exponent;
+ }
+ bool isFloatingLiteral() const {
+ return saw_period || saw_exponent;
+ }
+ bool hasSuffix() const {
+ return SuffixBegin != ThisTokEnd;
+ }
+
+ unsigned getRadix() const { return radix; }
+
+ /// GetIntegerValue - Convert this numeric literal value to an APInt that
+ /// matches Val's input width. If there is an overflow (i.e., if the unsigned
+ /// value read is larger than the APInt's bits will hold), set Val to the low
+ /// bits of the result and return true. Otherwise, return false.
+ bool GetIntegerValue(llvm::APInt &Val);
+
+ /// GetFloatValue - Convert this numeric literal to a floating value, using
+ /// the specified APFloat fltSemantics (specifying float, double, etc).
+ /// The optional bool isExact (passed-by-reference) has its value
+ /// set to true if the returned APFloat can represent the number in the
+ /// literal exactly, and false otherwise.
+ llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);
+
+private:
+
+ void ParseNumberStartingWithZero(SourceLocation TokLoc);
+
+ /// SkipHexDigits - Read and skip over any hex digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipHexDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && isxdigit(*ptr))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipOctalDigits - Read and skip over any octal digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipOctalDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && ((*ptr >= '0') && (*ptr <= '7')))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipDigits - Read and skip over any digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && isdigit(*ptr))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipBinaryDigits - Read and skip over any binary digits, up to End.
+ /// Return a pointer to the first non-binary digit or End.
+ const char *SkipBinaryDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && (*ptr == '0' || *ptr == '1'))
+ ptr++;
+ return ptr;
+ }
+
+};
+
+/// CharLiteralParser - Perform interpretation and semantic analysis of a
+/// character literal.
+class CharLiteralParser {
+ uint64_t Value;
+ bool IsWide;
+ bool IsMultiChar;
+ bool HadError;
+public:
+ CharLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP);
+
+ bool hadError() const { return HadError; }
+ bool isWide() const { return IsWide; }
+ bool isMultiChar() const { return IsMultiChar; }
+ uint64_t getValue() const { return Value; }
+};
+
+/// StringLiteralParser - This decodes string escape characters and performs
+/// wide string analysis and Translation Phase #6 (concatenation of string
+/// literals) (C99 5.1.1.2p1).
+class StringLiteralParser {
+ const SourceManager &SM;
+ const LangOptions &Features;
+ const TargetInfo &Target;
+ Diagnostic *Diags;
+
+ unsigned MaxTokenLength;
+ unsigned SizeBound;
+ unsigned wchar_tByteWidth;
+ llvm::SmallString<512> ResultBuf;
+ char *ResultPtr; // cursor
+public:
+ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ Preprocessor &PP, bool Complain = true);
+ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ const SourceManager &sm, const LangOptions &features,
+ const TargetInfo &target, Diagnostic *diags = 0)
+ : SM(sm), Features(features), Target(target), Diags(diags) {
+ init(StringToks, NumStringToks);
+ }
+
+
+ bool hadError;
+ bool AnyWide;
+ bool Pascal;
+
+ const char *GetString() { return &ResultBuf[0]; }
+ unsigned GetStringLength() const { return ResultPtr-&ResultBuf[0]; }
+
+ unsigned GetNumStringChars() const {
+ if (AnyWide)
+ return GetStringLength() / wchar_tByteWidth;
+ return GetStringLength();
+ }
+ /// getOffsetOfStringByte - This function returns the offset of the
+ /// specified byte of the string data represented by Token. This handles
+ /// advancing over escape sequences in the string.
+ ///
+ /// If the Diagnostics pointer is non-null, then this will do semantic
+ /// checking of the string literal and emit errors and warnings.
+ unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const;
+
+private:
+ void init(const Token *StringToks, unsigned NumStringToks);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
new file mode 100644
index 0000000..717c300
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
@@ -0,0 +1,256 @@
+//===--- MacroInfo.h - Information about #defined identifiers ---*- 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 MacroInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_MACROINFO_H
+#define LLVM_CLANG_MACROINFO_H
+
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+#include <cassert>
+
+namespace clang {
+ class Preprocessor;
+
+/// MacroInfo - Each identifier that is #define'd has an instance of this class
+/// associated with it, used to implement macro expansion.
+class MacroInfo {
+ //===--------------------------------------------------------------------===//
+ // State set when the macro is defined.
+
+ /// Location - This is the place the macro is defined.
+ SourceLocation Location;
+ /// EndLocation - The location of the last token in the macro.
+ SourceLocation EndLocation;
+
+ /// Arguments - The list of arguments for a function-like macro. This can be
+ /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this
+ /// includes the __VA_ARGS__ identifier on the list.
+ IdentifierInfo **ArgumentList;
+ unsigned NumArguments;
+
+ /// ReplacementTokens - This is the list of tokens that the macro is defined
+ /// to.
+ llvm::SmallVector<Token, 8> ReplacementTokens;
+
+ /// IsFunctionLike - True if this macro is a function-like macro, false if it
+ /// is an object-like macro.
+ bool IsFunctionLike : 1;
+
+ /// IsC99Varargs - True if this macro is of the form "#define X(...)" or
+ /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the
+ /// contents of "..." in an invocation.
+ bool IsC99Varargs : 1;
+
+ /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The
+ /// "a" identifier in the replacement list will be replaced with all arguments
+ /// of the macro starting with the specified one.
+ bool IsGNUVarargs : 1;
+
+ /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if
+ /// it has not yet been redefined or undefined.
+ bool IsBuiltinMacro : 1;
+
+ /// IsFromAST - True if this macro was loaded from an AST file.
+ bool IsFromAST : 1;
+
+private:
+ //===--------------------------------------------------------------------===//
+ // State that changes as the macro is used.
+
+ /// IsDisabled - True if we have started an expansion of this macro already.
+ /// This disbles recursive expansion, which would be quite bad for things like
+ /// #define A A.
+ bool IsDisabled : 1;
+
+ /// IsUsed - True if this macro is either defined in the main file and has
+ /// been used, or if it is not defined in the main file. This is used to
+ /// emit -Wunused-macros diagnostics.
+ bool IsUsed : 1;
+
+ /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined
+ /// without emitting a warning.
+ bool IsAllowRedefinitionsWithoutWarning : 1;
+
+ /// \brief Must warn if the macro is unused at the end of translation unit.
+ bool IsWarnIfUnused : 1;
+
+ ~MacroInfo() {
+ assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
+ }
+
+public:
+ MacroInfo(SourceLocation DefLoc);
+ MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator);
+
+ /// FreeArgumentList - Free the argument list of the macro, restoring it to a
+ /// state where it can be reused for other devious purposes.
+ void FreeArgumentList() {
+ ArgumentList = 0;
+ NumArguments = 0;
+ }
+
+ /// Destroy - destroy this MacroInfo object.
+ void Destroy() {
+ FreeArgumentList();
+ this->~MacroInfo();
+ }
+
+ /// getDefinitionLoc - Return the location that the macro was defined at.
+ ///
+ SourceLocation getDefinitionLoc() const { return Location; }
+
+ /// setDefinitionEndLoc - Set the location of the last token in the macro.
+ ///
+ void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
+ /// getDefinitionEndLoc - Return the location of the last token in the macro.
+ ///
+ SourceLocation getDefinitionEndLoc() const { return EndLocation; }
+
+ /// isIdenticalTo - Return true if the specified macro definition is equal to
+ /// this macro in spelling, arguments, and whitespace. This is used to emit
+ /// duplicate definition warnings. This implements the rules in C99 6.10.3.
+ bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const;
+
+ /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag.
+ ///
+ void setIsBuiltinMacro(bool Val = true) {
+ IsBuiltinMacro = Val;
+ }
+
+ /// setIsUsed - Set the value of the IsUsed flag.
+ ///
+ void setIsUsed(bool Val) {
+ IsUsed = Val;
+ }
+
+ /// setIsAllowRedefinitionsWithoutWarning - Set the value of the
+ /// IsAllowRedefinitionsWithoutWarning flag.
+ void setIsAllowRedefinitionsWithoutWarning(bool Val) {
+ IsAllowRedefinitionsWithoutWarning = Val;
+ }
+
+ /// \brief Set the value of the IsWarnIfUnused flag.
+ void setIsWarnIfUnused(bool val) {
+ IsWarnIfUnused = val;
+ }
+
+ /// setArgumentList - Set the specified list of identifiers as the argument
+ /// list for this macro.
+ void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
+ llvm::BumpPtrAllocator &PPAllocator) {
+ assert(ArgumentList == 0 && NumArguments == 0 &&
+ "Argument list already set!");
+ if (NumArgs == 0) return;
+
+ NumArguments = NumArgs;
+ ArgumentList = PPAllocator.Allocate<IdentifierInfo*>(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ArgumentList[i] = List[i];
+ }
+
+ /// Arguments - The list of arguments for a function-like macro. This can be
+ /// empty, for, e.g. "#define X()".
+ typedef IdentifierInfo* const *arg_iterator;
+ bool arg_empty() const { return NumArguments == 0; }
+ arg_iterator arg_begin() const { return ArgumentList; }
+ arg_iterator arg_end() const { return ArgumentList+NumArguments; }
+ unsigned getNumArgs() const { return NumArguments; }
+
+ /// getArgumentNum - Return the argument number of the specified identifier,
+ /// or -1 if the identifier is not a formal argument identifier.
+ int getArgumentNum(IdentifierInfo *Arg) const {
+ for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I)
+ if (*I == Arg) return I-arg_begin();
+ return -1;
+ }
+
+ /// Function/Object-likeness. Keep track of whether this macro has formal
+ /// parameters.
+ void setIsFunctionLike() { IsFunctionLike = true; }
+ bool isFunctionLike() const { return IsFunctionLike; }
+ bool isObjectLike() const { return !IsFunctionLike; }
+
+ /// Varargs querying methods. This can only be set for function-like macros.
+ void setIsC99Varargs() { IsC99Varargs = true; }
+ void setIsGNUVarargs() { IsGNUVarargs = true; }
+ bool isC99Varargs() const { return IsC99Varargs; }
+ bool isGNUVarargs() const { return IsGNUVarargs; }
+ bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
+
+ /// isBuiltinMacro - Return true if this macro is a builtin macro, such as
+ /// __LINE__, which requires processing before expansion.
+ bool isBuiltinMacro() const { return IsBuiltinMacro; }
+
+ /// isFromAST - Return true if this macro was loaded from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ /// setIsFromAST - Set whether this macro was loaded from an AST file.
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
+ /// isUsed - Return false if this macro is defined in the main file and has
+ /// not yet been used.
+ bool isUsed() const { return IsUsed; }
+
+ /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be
+ /// redefined without warning.
+ bool isAllowRedefinitionsWithoutWarning() const {
+ return IsAllowRedefinitionsWithoutWarning;
+ }
+
+ /// \brief Return true if we should emit a warning if the macro is unused.
+ bool isWarnIfUnused() const {
+ return IsWarnIfUnused;
+ }
+
+ /// getNumTokens - Return the number of tokens that this macro expands to.
+ ///
+ unsigned getNumTokens() const {
+ return ReplacementTokens.size();
+ }
+
+ const Token &getReplacementToken(unsigned Tok) const {
+ assert(Tok < ReplacementTokens.size() && "Invalid token #");
+ return ReplacementTokens[Tok];
+ }
+
+ typedef llvm::SmallVector<Token, 8>::const_iterator tokens_iterator;
+ tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
+ tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
+ bool tokens_empty() const { return ReplacementTokens.empty(); }
+
+ /// AddTokenToBody - Add the specified token to the replacement text for the
+ /// macro.
+ void AddTokenToBody(const Token &Tok) {
+ ReplacementTokens.push_back(Tok);
+ }
+
+ /// isEnabled - Return true if this macro is enabled: in other words, that we
+ /// are not currently in an expansion of this macro.
+ bool isEnabled() const { return !IsDisabled; }
+
+ void EnableMacro() {
+ assert(IsDisabled && "Cannot enable an already-enabled macro!");
+ IsDisabled = false;
+ }
+
+ void DisableMacro() {
+ assert(!IsDisabled && "Cannot disable an already-disabled macro!");
+ IsDisabled = true;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
new file mode 100644
index 0000000..5d5d673
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
@@ -0,0 +1,130 @@
+//===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- 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 MultipleIncludeOpt interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
+#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
+
+namespace clang {
+class IdentifierInfo;
+
+/// MultipleIncludeOpt - This class implements the simple state machine that the
+/// Lexer class uses to detect files subject to the 'multiple-include'
+/// optimization. The public methods in this class are triggered by various
+/// events that occur when a file is lexed, and after the entire file is lexed,
+/// information about which macro (if any) controls the header is returned.
+class MultipleIncludeOpt {
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final #endif is parsed this is reset back
+ /// to false, that way any tokens before the first #ifdef or after the last
+ /// #endif can be easily detected.
+ bool ReadAnyTokens;
+
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final #endif is parsed this is reset back
+ /// to false, that way any tokens before the first #ifdef or after the last
+ /// #endif can be easily detected.
+ bool DidMacroExpansion;
+
+ /// TheMacro - The controlling macro for a file, if valid.
+ ///
+ const IdentifierInfo *TheMacro;
+public:
+ MultipleIncludeOpt() {
+ ReadAnyTokens = false;
+ DidMacroExpansion = false;
+ TheMacro = 0;
+ }
+
+ /// Invalidate - Permenantly mark this file as not being suitable for the
+ /// include-file optimization.
+ void Invalidate() {
+ // If we have read tokens but have no controlling macro, the state-machine
+ // below can never "accept".
+ ReadAnyTokens = true;
+ TheMacro = 0;
+ }
+
+ /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the
+ /// top of the file when reading preprocessor directives. Otherwise, reading
+ /// the "ifndef x" would count as reading tokens.
+ bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
+
+ // If a token is read, remember that we have seen a side-effect in this file.
+ void ReadToken() { ReadAnyTokens = true; }
+
+ /// ExpandedMacro - When a macro is expanded with this lexer as the current
+ /// buffer, this method is called to disable the MIOpt if needed.
+ void ExpandedMacro() { DidMacroExpansion = true; }
+
+ /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
+ /// "#if !defined" equivalent) without any preceding tokens, this method is
+ /// called.
+ ///
+ /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
+ /// ensures that this is only called if there are no tokens read before the
+ /// #ifndef. The caller is required to do this, because reading the #if line
+ /// obviously reads in in tokens.
+ void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
+ // If the macro is already set, this is after the top-level #endif.
+ if (TheMacro)
+ return Invalidate();
+
+ // If we have already expanded a macro by the end of the #ifndef line, then
+ // there is a macro expansion *in* the #ifndef line. This means that the
+ // condition could evaluate differently when subsequently #included. Reject
+ // this.
+ if (DidMacroExpansion)
+ return Invalidate();
+
+ // Remember that we're in the #if and that we have the macro.
+ ReadAnyTokens = true;
+ TheMacro = M;
+ }
+
+ /// EnterTopLevelConditional - This is invoked when a top level conditional
+ /// (except #ifndef) is found.
+ void EnterTopLevelConditional() {
+ /// If a conditional directive (except #ifndef) is found at the top level,
+ /// there is a chunk of the file not guarded by the controlling macro.
+ Invalidate();
+ }
+
+ /// ExitTopLevelConditional - This method is called when the lexer exits the
+ /// top-level conditional.
+ void ExitTopLevelConditional() {
+ // If we have a macro, that means the top of the file was ok. Set our state
+ // back to "not having read any tokens" so we can detect anything after the
+ // #endif.
+ if (!TheMacro) return Invalidate();
+
+ // At this point, we haven't "read any tokens" but we do have a controlling
+ // macro.
+ ReadAnyTokens = false;
+ }
+
+ /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
+ /// there is a controlling macro, return it.
+ const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
+ // If we haven't read any tokens after the #endif, return the controlling
+ // macro if it's valid (if it isn't, it will be null).
+ if (!ReadAnyTokens)
+ return TheMacro;
+ return 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
new file mode 100644
index 0000000..b2a80a6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
@@ -0,0 +1,273 @@
+//===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- 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 PPCallbacks interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
+#define LLVM_CLANG_LEX_PPCALLBACKS_H
+
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+ class SourceLocation;
+ class Token;
+ class IdentifierInfo;
+ class MacroInfo;
+
+/// PPCallbacks - This interface provides a way to observe the actions of the
+/// preprocessor as it does its thing. Clients can define their hooks here to
+/// implement preprocessor level tools.
+class PPCallbacks {
+public:
+ virtual ~PPCallbacks();
+
+ enum FileChangeReason {
+ EnterFile, ExitFile, SystemHeaderPragma, RenameFile
+ };
+
+ /// FileChanged - This callback is invoked whenever a source file is
+ /// entered or exited. The SourceLocation indicates the new location, and
+ /// EnteringFile indicates whether this is because we are entering a new
+ /// #include'd file (when true) or whether we're exiting one because we ran
+ /// off the end (when false).
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType) {
+ }
+
+ /// FileSkipped - This callback is invoked whenever a source file is
+ /// skipped as the result of header guard optimization. ParentFile
+ /// is the file that #includes the skipped file. FilenameTok is the
+ /// token in ParentFile that indicates the skipped file.
+ virtual void FileSkipped(const FileEntry &ParentFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+ }
+
+ /// \brief This callback is invoked whenever an inclusion directive of
+ /// any kind (\c #include, \c #import, etc.) has been processed, regardless
+ /// of whether the inclusion will actually result in an inclusion.
+ ///
+ /// \param HashLoc The location of the '#' that starts the inclusion
+ /// directive.
+ ///
+ /// \param IncludeTok The token that indicates the kind of inclusion
+ /// directive, e.g., 'include' or 'import'.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \param IsAngled Whether the file name was enclosed in angle brackets;
+ /// otherwise, it was enclosed in quotes.
+ ///
+ /// \param File The actual file that may be included by this inclusion
+ /// directive.
+ ///
+ /// \param EndLoc The location of the last token within the inclusion
+ /// directive.
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc) {
+ }
+
+ /// EndOfMainFile - This callback is invoked when the end of the main file is
+ /// reach, no subsequent callbacks will be made.
+ virtual void EndOfMainFile() {
+ }
+
+ /// Ident - This callback is invoked when a #ident or #sccs directive is read.
+ /// \param Loc The location of the directive.
+ /// \param str The text of the directive.
+ ///
+ virtual void Ident(SourceLocation Loc, const std::string &str) {
+ }
+
+ /// PragmaComment - This callback is invoked when a #pragma comment directive
+ /// is read.
+ ///
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str) {
+ }
+
+ /// PragmaMessage - This callback is invoked when a #pragma message directive
+ /// is read.
+ /// \param Loc The location of the message directive.
+ /// \param str The text of the message directive.
+ ///
+ virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
+ }
+
+ /// MacroExpands - This is called by
+ /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
+ /// found.
+ virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
+ }
+
+ /// MacroDefined - This hook is called whenever a macro definition is seen.
+ virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ }
+
+ /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ /// MI is released immediately following this callback.
+ virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ }
+
+ /// If -- This hook is called whenever an #if is seen.
+ /// \param Range The SourceRange of the expression being tested.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void If(SourceRange Range) {
+ }
+
+ /// Elif -- This hook is called whenever an #elif is seen.
+ /// \param Range The SourceRange of the expression being tested.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elif(SourceRange Range) {
+ }
+
+ /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ /// \param Loc The location of the token being tested.
+ /// \param II Information on the token being tested.
+ virtual void Ifdef(const Token &MacroNameTok) {
+ }
+
+ /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ /// \param Loc The location of the token being tested.
+ /// \param II Information on the token being tested.
+ virtual void Ifndef(const Token &MacroNameTok) {
+ }
+
+ /// Else -- This hook is called whenever an #else is seen.
+ virtual void Else() {
+ }
+
+ /// Endif -- This hook is called whenever an #endif is seen.
+ virtual void Endif() {
+ }
+};
+
+/// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
+class PPChainedCallbacks : public PPCallbacks {
+ PPCallbacks *First, *Second;
+
+public:
+ PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
+ : First(_First), Second(_Second) {}
+ ~PPChainedCallbacks() {
+ delete Second;
+ delete First;
+ }
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType) {
+ First->FileChanged(Loc, Reason, FileType);
+ Second->FileChanged(Loc, Reason, FileType);
+ }
+
+ virtual void FileSkipped(const FileEntry &ParentFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+ First->FileSkipped(ParentFile, FilenameTok, FileType);
+ Second->FileSkipped(ParentFile, FilenameTok, FileType);
+ }
+
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc) {
+ First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc);
+ Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc);
+ }
+
+ virtual void EndOfMainFile() {
+ First->EndOfMainFile();
+ Second->EndOfMainFile();
+ }
+
+ virtual void Ident(SourceLocation Loc, const std::string &str) {
+ First->Ident(Loc, str);
+ Second->Ident(Loc, str);
+ }
+
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str) {
+ First->PragmaComment(Loc, Kind, Str);
+ Second->PragmaComment(Loc, Kind, Str);
+ }
+
+ virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
+ First->PragmaMessage(Loc, Str);
+ Second->PragmaMessage(Loc, Str);
+ }
+
+ virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) {
+ First->MacroExpands(MacroNameTok, MI);
+ Second->MacroExpands(MacroNameTok, MI);
+ }
+
+ virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ First->MacroDefined(MacroNameTok, MI);
+ Second->MacroDefined(MacroNameTok, MI);
+ }
+
+ virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ First->MacroUndefined(MacroNameTok, MI);
+ Second->MacroUndefined(MacroNameTok, MI);
+ }
+
+ /// If -- This hook is called whenever an #if is seen.
+ virtual void If(SourceRange Range) {
+ First->If(Range);
+ Second->If(Range);
+ }
+
+ /// Elif -- This hook is called whenever an #if is seen.
+ virtual void Elif(SourceRange Range) {
+ First->Elif(Range);
+ Second->Elif(Range);
+ }
+
+ /// Ifdef -- This hook is called whenever an #ifdef is seen.
+ virtual void Ifdef(const Token &MacroNameTok) {
+ First->Ifdef(MacroNameTok);
+ Second->Ifdef(MacroNameTok);
+ }
+
+ /// Ifndef -- This hook is called whenever an #ifndef is seen.
+ virtual void Ifndef(const Token &MacroNameTok) {
+ First->Ifndef(MacroNameTok);
+ Second->Ifndef(MacroNameTok);
+ }
+
+ /// Else -- This hook is called whenever an #else is seen.
+ virtual void Else() {
+ First->Else();
+ Second->Else();
+ }
+
+ /// Endif -- This hook is called whenever an #endif is seen.
+ virtual void Endif() {
+ First->Endif();
+ Second->Endif();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
new file mode 100644
index 0000000..0b5a76c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
@@ -0,0 +1,106 @@
+//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- 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 PTHLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PTHLEXER_H
+#define LLVM_CLANG_PTHLEXER_H
+
+#include "clang/Lex/PreprocessorLexer.h"
+#include <vector>
+
+namespace clang {
+
+class PTHManager;
+class PTHSpellingSearch;
+
+class PTHLexer : public PreprocessorLexer {
+ SourceLocation FileStartLoc;
+
+ /// TokBuf - Buffer from PTH file containing raw token data.
+ const unsigned char* TokBuf;
+
+ /// CurPtr - Pointer into current offset of the token buffer where
+ /// the next token will be read.
+ const unsigned char* CurPtr;
+
+ /// LastHashTokPtr - Pointer into TokBuf of the last processed '#'
+ /// token that appears at the start of a line.
+ const unsigned char* LastHashTokPtr;
+
+ /// PPCond - Pointer to a side table in the PTH file that provides a
+ /// a consise summary of the preproccessor conditional block structure.
+ /// This is used to perform quick skipping of conditional blocks.
+ const unsigned char* PPCond;
+
+ /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry
+ /// to process when doing quick skipping of preprocessor blocks.
+ const unsigned char* CurPPCondPtr;
+
+ PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT
+ void operator=(const PTHLexer&); // DO NOT IMPLEMENT
+
+ /// ReadToken - Used by PTHLexer to read tokens TokBuf.
+ void ReadToken(Token& T);
+
+ bool LexEndOfFile(Token &Result);
+
+ /// PTHMgr - The PTHManager object that created this PTHLexer.
+ PTHManager& PTHMgr;
+
+ Token EofToken;
+
+protected:
+ friend class PTHManager;
+
+ /// Create a PTHLexer for the specified token stream.
+ PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D,
+ const unsigned char* ppcond, PTHManager &PM);
+public:
+
+ ~PTHLexer() {}
+
+ /// Lex - Return the next token.
+ void Lex(Token &Tok);
+
+ void getEOF(Token &Tok);
+
+ /// DiscardToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ void DiscardToEndOfLine();
+
+ /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
+ /// tok::l_paren token, 0 if it is something else and 2 if there are no more
+ /// tokens controlled by this lexer.
+ unsigned isNextPPTokenLParen() {
+ // isNextPPTokenLParen is not on the hot path, and all we care about is
+ // whether or not we are at a token with kind tok::eof or tok::l_paren.
+ // Just read the first byte from the current token pointer to determine
+ // its kind.
+ tok::TokenKind x = (tok::TokenKind)*CurPtr;
+ return x == tok::eof ? 2 : x == tok::l_paren;
+ }
+
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) { Lex(Result); }
+
+ /// getSourceLocation - Return a source location for the token in
+ /// the current file.
+ SourceLocation getSourceLocation();
+
+ /// SkipBlock - Used by Preprocessor to skip the current conditional block.
+ bool SkipBlock();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
new file mode 100644
index 0000000..094b7ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
@@ -0,0 +1,140 @@
+//===--- PTHManager.h - Manager object for PTH processing -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PTHManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PTHMANAGER_H
+#define LLVM_CLANG_PTHMANAGER_H
+
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+#include <string>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class FileEntry;
+class PTHLexer;
+class Diagnostic;
+class FileSystemStatCache;
+
+class PTHManager : public IdentifierInfoLookup {
+ friend class PTHLexer;
+
+ /// The memory mapped PTH file.
+ const llvm::MemoryBuffer* Buf;
+
+ /// Alloc - Allocator used for IdentifierInfo objects.
+ llvm::BumpPtrAllocator Alloc;
+
+ /// IdMap - A lazily generated cache mapping from persistent identifiers to
+ /// IdentifierInfo*.
+ IdentifierInfo** PerIDCache;
+
+ /// FileLookup - Abstract data structure used for mapping between files
+ /// and token data in the PTH file.
+ void* FileLookup;
+
+ /// IdDataTable - Array representing the mapping from persistent IDs to the
+ /// data offset within the PTH file containing the information to
+ /// reconsitute an IdentifierInfo.
+ const unsigned char* const IdDataTable;
+
+ /// SortedIdTable - Abstract data structure mapping from strings to
+ /// persistent IDs. This is used by get().
+ void* StringIdLookup;
+
+ /// NumIds - The number of identifiers in the PTH file.
+ const unsigned NumIds;
+
+ /// PP - The Preprocessor object that will use this PTHManager to create
+ /// PTHLexer objects.
+ Preprocessor* PP;
+
+ /// SpellingBase - The base offset within the PTH memory buffer that
+ /// contains the cached spellings for literals.
+ const unsigned char* const SpellingBase;
+
+ /// OriginalSourceFile - A null-terminated C-string that specifies the name
+ /// if the file (if any) that was to used to generate the PTH cache.
+ const char* OriginalSourceFile;
+
+ /// This constructor is intended to only be called by the static 'Create'
+ /// method.
+ PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
+ const unsigned char* idDataTable, IdentifierInfo** perIDCache,
+ void* stringIdLookup, unsigned numIds,
+ const unsigned char* spellingBase, const char *originalSourceFile);
+
+ // Do not implement.
+ PTHManager();
+ void operator=(const PTHManager&);
+
+ /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached
+ /// spelling for a token.
+ unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer);
+
+ /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the
+ /// PTH file.
+ inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) {
+ // Check if the IdentifierInfo has already been resolved.
+ if (IdentifierInfo* II = PerIDCache[PersistentID])
+ return II;
+ return LazilyCreateIdentifierInfo(PersistentID);
+ }
+ IdentifierInfo* LazilyCreateIdentifierInfo(unsigned PersistentID);
+
+public:
+ // The current PTH version.
+ enum { Version = 9 };
+
+ ~PTHManager();
+
+ /// getOriginalSourceFile - Return the full path to the original header
+ /// file name that was used to generate the PTH cache.
+ const char* getOriginalSourceFile() const {
+ return OriginalSourceFile;
+ }
+
+ /// get - Return the identifier token info for the specified named identifier.
+ /// Unlike the version in IdentifierTable, this returns a pointer instead
+ /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
+ /// be found.
+ IdentifierInfo *get(llvm::StringRef Name);
+
+ /// Create - This method creates PTHManager objects. The 'file' argument
+ /// is the name of the PTH file. This method returns NULL upon failure.
+ static PTHManager *Create(const std::string& file, Diagnostic &Diags);
+
+ void setPreprocessor(Preprocessor *pp) { PP = pp; }
+
+ /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the
+ /// specified file. This method returns NULL if no cached tokens exist.
+ /// It is the responsibility of the caller to 'delete' the returned object.
+ PTHLexer *CreateLexer(FileID FID);
+
+ /// createStatCache - Returns a FileSystemStatCache object for use with
+ /// FileManager objects. These objects use the PTH data to speed up
+ /// calls to stat by memoizing their results from when the PTH file
+ /// was generated.
+ FileSystemStatCache *createStatCache();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
new file mode 100644
index 0000000..8bd2236
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
@@ -0,0 +1,126 @@
+//===--- Pragma.h - Pragma registration and handling ------------*- 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 PragmaHandler and PragmaTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PRAGMA_H
+#define LLVM_CLANG_PRAGMA_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <vector>
+
+namespace clang {
+ class Preprocessor;
+ class Token;
+ class IdentifierInfo;
+ class PragmaNamespace;
+
+ /**
+ * \brief Describes how the pragma was introduced, e.g., with #pragma,
+ * _Pragma, or __pragma.
+ */
+ enum PragmaIntroducerKind {
+ /**
+ * \brief The pragma was introduced via #pragma.
+ */
+ PIK_HashPragma,
+
+ /**
+ * \brief The pragma was introduced via the C99 _Pragma(string-literal).
+ */
+ PIK__Pragma,
+
+ /**
+ * \brief The pragma was introduced via the Microsoft
+ * __pragma(token-string).
+ */
+ PIK___pragma
+ };
+
+/// PragmaHandler - Instances of this interface defined to handle the various
+/// pragmas that the language front-end uses. Each handler optionally has a
+/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
+/// that identifier is found. If a handler does not match any of the declared
+/// pragmas the handler with a null identifier is invoked, if it exists.
+///
+/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
+/// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other
+/// pragmas.
+class PragmaHandler {
+ std::string Name;
+public:
+ explicit PragmaHandler(llvm::StringRef name) : Name(name) {}
+ PragmaHandler() {}
+ virtual ~PragmaHandler();
+
+ llvm::StringRef getName() const { return Name; }
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) = 0;
+
+ /// getIfNamespace - If this is a namespace, return it. This is equivalent to
+ /// using a dynamic_cast, but doesn't require RTTI.
+ virtual PragmaNamespace *getIfNamespace() { return 0; }
+};
+
+/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
+/// used to ignore particular pragmas.
+class EmptyPragmaHandler : public PragmaHandler {
+public:
+ EmptyPragmaHandler();
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
+/// allowing hierarchical pragmas to be defined. Common examples of namespaces
+/// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may
+/// be (potentially recursively) defined.
+class PragmaNamespace : public PragmaHandler {
+ /// Handlers - This is a map of the handlers in this namespace with their name
+ /// as key.
+ ///
+ llvm::StringMap<PragmaHandler*> Handlers;
+public:
+ explicit PragmaNamespace(llvm::StringRef Name) : PragmaHandler(Name) {}
+ virtual ~PragmaNamespace();
+
+ /// FindHandler - Check to see if there is already a handler for the
+ /// specified name. If not, return the handler for the null name if it
+ /// exists, otherwise return null. If IgnoreNull is true (the default) then
+ /// the null handler isn't returned on failure to match.
+ PragmaHandler *FindHandler(llvm::StringRef Name,
+ bool IgnoreNull = true) const;
+
+ /// AddPragma - Add a pragma to this namespace.
+ ///
+ void AddPragma(PragmaHandler *Handler);
+
+ /// RemovePragmaHandler - Remove the given handler from the
+ /// namespace.
+ void RemovePragmaHandler(PragmaHandler *Handler);
+
+ bool IsEmpty() {
+ return Handlers.empty();
+ }
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+
+ virtual PragmaNamespace *getIfNamespace() { return this; }
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
new file mode 100644
index 0000000..afd7ae1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
@@ -0,0 +1,358 @@
+//===--- PreprocessingRecord.h - Record of Preprocessing --------*- 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 PreprocessingRecord class, which maintains a record
+// of what occurred during preprocessing.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace clang {
+ class IdentifierInfo;
+ class PreprocessingRecord;
+}
+
+/// \brief Allocates memory within a Clang preprocessing record.
+void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
+ unsigned alignment = 8) throw();
+
+/// \brief Frees memory allocated in a Clang preprocessing record.
+void operator delete(void* ptr, clang::PreprocessingRecord& PR,
+ unsigned) throw();
+
+namespace clang {
+ class MacroDefinition;
+ class FileEntry;
+
+ /// \brief Base class that describes a preprocessed entity, which may be a
+ /// preprocessor directive or macro instantiation.
+ class PreprocessedEntity {
+ public:
+ /// \brief The kind of preprocessed entity an object describes.
+ enum EntityKind {
+ /// \brief A macro instantiation.
+ MacroInstantiationKind,
+
+ /// \brief A preprocessing directive whose kind is not specified.
+ ///
+ /// This kind will be used for any preprocessing directive that does not
+ /// have a more specific kind within the \c DirectiveKind enumeration.
+ PreprocessingDirectiveKind,
+
+ /// \brief A macro definition.
+ MacroDefinitionKind,
+
+ /// \brief An inclusion directive, such as \c #include, \c
+ /// #import, or \c #include_next.
+ InclusionDirectiveKind,
+
+ FirstPreprocessingDirective = PreprocessingDirectiveKind,
+ LastPreprocessingDirective = InclusionDirectiveKind
+ };
+
+ private:
+ /// \brief The kind of preprocessed entity that this object describes.
+ EntityKind Kind;
+
+ /// \brief The source range that covers this preprocessed entity.
+ SourceRange Range;
+
+ protected:
+ PreprocessedEntity(EntityKind Kind, SourceRange Range)
+ : Kind(Kind), Range(Range) { }
+
+ public:
+ /// \brief Retrieve the kind of preprocessed entity stored in this object.
+ EntityKind getKind() const { return Kind; }
+
+ /// \brief Retrieve the source range that covers this entire preprocessed
+ /// entity.
+ SourceRange getSourceRange() const { return Range; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *) { return true; }
+
+ // Only allow allocation of preprocessed entities using the allocator
+ // in PreprocessingRecord or by doing a placement new.
+ void* operator new(size_t bytes, PreprocessingRecord& PR,
+ unsigned alignment = 8) throw() {
+ return ::operator new(bytes, PR, alignment);
+ }
+
+ void* operator new(size_t bytes, void* mem) throw() {
+ return mem;
+ }
+
+ void operator delete(void* ptr, PreprocessingRecord& PR,
+ unsigned alignment) throw() {
+ return ::operator delete(ptr, PR, alignment);
+ }
+
+ void operator delete(void*, std::size_t) throw() { }
+ void operator delete(void*, void*) throw() { }
+
+ private:
+ // Make vanilla 'new' and 'delete' illegal for preprocessed entities.
+ void* operator new(size_t bytes) throw();
+ void operator delete(void* data) throw();
+ };
+
+ /// \brief Records the location of a macro instantiation.
+ class MacroInstantiation : public PreprocessedEntity {
+ /// \brief The name of the macro being instantiation.
+ IdentifierInfo *Name;
+
+ /// \brief The definition of this macro.
+ MacroDefinition *Definition;
+
+ public:
+ MacroInstantiation(IdentifierInfo *Name, SourceRange Range,
+ MacroDefinition *Definition)
+ : PreprocessedEntity(MacroInstantiationKind, Range), Name(Name),
+ Definition(Definition) { }
+
+ /// \brief The name of the macro being instantiated.
+ IdentifierInfo *getName() const { return Name; }
+
+ /// \brief The definition of the macro being instantiated.
+ MacroDefinition *getDefinition() const { return Definition; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroInstantiationKind;
+ }
+ static bool classof(const MacroInstantiation *) { return true; }
+
+ };
+
+ /// \brief Records the presence of a preprocessor directive.
+ class PreprocessingDirective : public PreprocessedEntity {
+ public:
+ PreprocessingDirective(EntityKind Kind, SourceRange Range)
+ : PreprocessedEntity(Kind, Range) { }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PD) {
+ return PD->getKind() >= FirstPreprocessingDirective &&
+ PD->getKind() <= LastPreprocessingDirective;
+ }
+ static bool classof(const PreprocessingDirective *) { return true; }
+ };
+
+ /// \brief Record the location of a macro definition.
+ class MacroDefinition : public PreprocessingDirective {
+ /// \brief The name of the macro being defined.
+ const IdentifierInfo *Name;
+
+ /// \brief The location of the macro name in the macro definition.
+ SourceLocation Location;
+
+ public:
+ explicit MacroDefinition(const IdentifierInfo *Name, SourceLocation Location,
+ SourceRange Range)
+ : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name),
+ Location(Location) { }
+
+ /// \brief Retrieve the name of the macro being defined.
+ const IdentifierInfo *getName() const { return Name; }
+
+ /// \brief Retrieve the location of the macro name in the definition.
+ SourceLocation getLocation() const { return Location; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroDefinitionKind;
+ }
+ static bool classof(const MacroDefinition *) { return true; }
+ };
+
+ /// \brief Record the location of an inclusion directive, such as an
+ /// \c #include or \c #import statement.
+ class InclusionDirective : public PreprocessingDirective {
+ public:
+ /// \brief The kind of inclusion directives known to the
+ /// preprocessor.
+ enum InclusionKind {
+ /// \brief An \c #include directive.
+ Include,
+ /// \brief An Objective-C \c #import directive.
+ Import,
+ /// \brief A GNU \c #include_next directive.
+ IncludeNext,
+ /// \brief A Clang \c #__include_macros directive.
+ IncludeMacros
+ };
+
+ private:
+ /// \brief The name of the file that was included, as written in
+ /// the source.
+ llvm::StringRef FileName;
+
+ /// \brief Whether the file name was in quotation marks; otherwise, it was
+ /// in angle brackets.
+ unsigned InQuotes : 1;
+
+ /// \brief The kind of inclusion directive we have.
+ ///
+ /// This is a value of type InclusionKind.
+ unsigned Kind : 2;
+
+ /// \brief The file that was included.
+ const FileEntry *File;
+
+ public:
+ InclusionDirective(PreprocessingRecord &PPRec,
+ InclusionKind Kind, llvm::StringRef FileName,
+ bool InQuotes, const FileEntry *File, SourceRange Range);
+
+ /// \brief Determine what kind of inclusion directive this is.
+ InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }
+
+ /// \brief Retrieve the included file name as it was written in the source.
+ llvm::StringRef getFileName() const { return FileName; }
+
+ /// \brief Determine whether the included file name was written in quotes;
+ /// otherwise, it was written in angle brackets.
+ bool wasInQuotes() const { return InQuotes; }
+
+ /// \brief Retrieve the file entry for the actual file that was included
+ /// by this directive.
+ const FileEntry *getFile() const { return File; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == InclusionDirectiveKind;
+ }
+ static bool classof(const InclusionDirective *) { return true; }
+ };
+
+ /// \brief An abstract class that should be subclassed by any external source
+ /// of preprocessing record entries.
+ class ExternalPreprocessingRecordSource {
+ public:
+ virtual ~ExternalPreprocessingRecordSource();
+
+ /// \brief Read any preallocated preprocessed entities from the external
+ /// source.
+ virtual void ReadPreprocessedEntities() = 0;
+
+ /// \brief Read the preprocessed entity at the given offset.
+ virtual PreprocessedEntity *
+ ReadPreprocessedEntityAtOffset(uint64_t Offset) = 0;
+ };
+
+ /// \brief A record of the steps taken while preprocessing a source file,
+ /// including the various preprocessing directives processed, macros
+ /// instantiated, etc.
+ class PreprocessingRecord : public PPCallbacks {
+ /// \brief Allocator used to store preprocessing objects.
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// \brief The set of preprocessed entities in this record, in order they
+ /// were seen.
+ std::vector<PreprocessedEntity *> PreprocessedEntities;
+
+ /// \brief Mapping from MacroInfo structures to their definitions.
+ llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions;
+
+ /// \brief External source of preprocessed entities.
+ ExternalPreprocessingRecordSource *ExternalSource;
+
+ /// \brief The number of preallocated entities (that are known to the
+ /// external source).
+ unsigned NumPreallocatedEntities;
+
+ /// \brief Whether we have already loaded all of the preallocated entities.
+ mutable bool LoadedPreallocatedEntities;
+
+ void MaybeLoadPreallocatedEntities() const ;
+
+ public:
+ PreprocessingRecord();
+
+ /// \brief Allocate memory in the preprocessing record.
+ void *Allocate(unsigned Size, unsigned Align = 8) {
+ return BumpAlloc.Allocate(Size, Align);
+ }
+
+ /// \brief Deallocate memory in the preprocessing record.
+ void Deallocate(void *Ptr) { }
+
+ // Iteration over the preprocessed entities.
+ typedef std::vector<PreprocessedEntity *>::iterator iterator;
+ typedef std::vector<PreprocessedEntity *>::const_iterator const_iterator;
+ iterator begin(bool OnlyLocalEntities = false);
+ iterator end(bool OnlyLocalEntities = false);
+ const_iterator begin(bool OnlyLocalEntities = false) const;
+ const_iterator end(bool OnlyLocalEntities = false) const;
+
+ /// \brief Add a new preprocessed entity to this record.
+ void addPreprocessedEntity(PreprocessedEntity *Entity);
+
+ /// \brief Set the external source for preprocessed entities.
+ void SetExternalSource(ExternalPreprocessingRecordSource &Source,
+ unsigned NumPreallocatedEntities);
+
+ /// \brief Retrieve the external source for preprocessed entities.
+ ExternalPreprocessingRecordSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ unsigned getNumPreallocatedEntities() const {
+ return NumPreallocatedEntities;
+ }
+
+ /// \brief Set the preallocated entry at the given index to the given
+ /// preprocessed entity.
+ void SetPreallocatedEntity(unsigned Index, PreprocessedEntity *Entity);
+
+ /// \brief Register a new macro definition.
+ void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *MD);
+
+ /// \brief Retrieve the preprocessed entity at the given index.
+ PreprocessedEntity *getPreprocessedEntity(unsigned Index) {
+ assert(Index < PreprocessedEntities.size() &&
+ "Out-of-bounds preprocessed entity");
+ return PreprocessedEntities[Index];
+ }
+
+ /// \brief Retrieve the macro definition that corresponds to the given
+ /// \c MacroInfo.
+ MacroDefinition *findMacroDefinition(const MacroInfo *MI);
+
+ virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
+ virtual void MacroDefined(const Token &Id, const MacroInfo *MI);
+ virtual void MacroUndefined(const Token &Id, const MacroInfo *MI);
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ SourceLocation EndLoc);
+ };
+} // end namespace clang
+
+inline void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
+ unsigned alignment) throw() {
+ return PR.Allocate(bytes, alignment);
+}
+
+inline void operator delete(void* ptr, clang::PreprocessingRecord& PR,
+ unsigned) throw() {
+ PR.Deallocate(ptr);
+}
+
+#endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
new file mode 100644
index 0000000..018f7e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -0,0 +1,1053 @@
+//===--- Preprocessor.h - C Language Family Preprocessor --------*- 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 Preprocessor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
+#define LLVM_CLANG_LEX_PREPROCESSOR_H
+
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/TokenLexer.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace clang {
+
+class SourceManager;
+class ExternalPreprocessorSource;
+class FileManager;
+class FileEntry;
+class HeaderSearch;
+class PragmaNamespace;
+class PragmaHandler;
+class CommentHandler;
+class ScratchBuffer;
+class TargetInfo;
+class PPCallbacks;
+class CodeCompletionHandler;
+class DirectoryLookup;
+class PreprocessingRecord;
+
+/// Preprocessor - This object engages in a tight little dance with the lexer to
+/// efficiently preprocess tokens. Lexers know only about tokens within a
+/// single source file, and don't know anything about preprocessor-level issues
+/// like the #include stack, token expansion, etc.
+///
+class Preprocessor {
+ Diagnostic *Diags;
+ LangOptions Features;
+ const TargetInfo &Target;
+ FileManager &FileMgr;
+ SourceManager &SourceMgr;
+ ScratchBuffer *ScratchBuf;
+ HeaderSearch &HeaderInfo;
+
+ /// \brief External source of macros.
+ ExternalPreprocessorSource *ExternalSource;
+
+ /// PTH - An optional PTHManager object used for getting tokens from
+ /// a token cache rather than lexing the original source file.
+ llvm::OwningPtr<PTHManager> PTH;
+
+ /// BP - A BumpPtrAllocator object used to quickly allocate and release
+ /// objects internal to the Preprocessor.
+ llvm::BumpPtrAllocator BP;
+
+ /// Identifiers for builtin macros and other builtins.
+ IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__
+ IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
+ IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
+ IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
+ IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
+ IdentifierInfo *Ident__COUNTER__; // __COUNTER__
+ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
+ IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
+ IdentifierInfo *Ident__has_feature; // __has_feature
+ IdentifierInfo *Ident__has_builtin; // __has_builtin
+ IdentifierInfo *Ident__has_attribute; // __has_attribute
+ IdentifierInfo *Ident__has_include; // __has_include
+ IdentifierInfo *Ident__has_include_next; // __has_include_next
+
+ SourceLocation DATELoc, TIMELoc;
+ unsigned CounterValue; // Next __COUNTER__ value.
+
+ enum {
+ /// MaxIncludeStackDepth - Maximum depth of #includes.
+ MaxAllowedIncludeStackDepth = 200
+ };
+
+ // State that is set before the preprocessor begins.
+ bool KeepComments : 1;
+ bool KeepMacroComments : 1;
+
+ // State that changes while the preprocessor runs:
+ bool InMacroArgs : 1; // True if parsing fn macro invocation args.
+
+ /// Whether the preprocessor owns the header search object.
+ bool OwnsHeaderSearch : 1;
+
+ /// DisableMacroExpansion - True if macro expansion is disabled.
+ bool DisableMacroExpansion : 1;
+
+ /// \brief Whether we have already loaded macros from the external source.
+ mutable bool ReadMacrosFromExternalSource : 1;
+
+ /// Identifiers - This is mapping/lookup information for all identifiers in
+ /// the program, including program keywords.
+ mutable IdentifierTable Identifiers;
+
+ /// Selectors - This table contains all the selectors in the program. Unlike
+ /// IdentifierTable above, this table *isn't* populated by the preprocessor.
+ /// It is declared/instantiated here because it's role/lifetime is
+ /// conceptually similar the IdentifierTable. In addition, the current control
+ /// flow (in clang::ParseAST()), make it convenient to put here.
+ /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
+ /// the lifetime of the preprocessor.
+ SelectorTable Selectors;
+
+ /// BuiltinInfo - Information about builtins.
+ Builtin::Context BuiltinInfo;
+
+ /// PragmaHandlers - This tracks all of the pragmas that the client registered
+ /// with this preprocessor.
+ PragmaNamespace *PragmaHandlers;
+
+ /// \brief Tracks all of the comment handlers that the client registered
+ /// with this preprocessor.
+ std::vector<CommentHandler *> CommentHandlers;
+
+ /// \brief The code-completion handler.
+ CodeCompletionHandler *CodeComplete;
+
+ /// \brief The file that we're performing code-completion for, if any.
+ const FileEntry *CodeCompletionFile;
+
+ /// \brief The number of bytes that we will initially skip when entering the
+ /// main file, which is used when loading a precompiled preamble, along
+ /// with a flag that indicates whether skipping this number of bytes will
+ /// place the lexer at the start of a line.
+ std::pair<unsigned, bool> SkipMainFilePreamble;
+
+ /// CurLexer - This is the current top of the stack that we're lexing from if
+ /// not expanding a macro and we are lexing directly from source code.
+ /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ llvm::OwningPtr<Lexer> CurLexer;
+
+ /// CurPTHLexer - This is the current top of stack that we're lexing from if
+ /// not expanding from a macro and we are lexing from a PTH cache.
+ /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ llvm::OwningPtr<PTHLexer> CurPTHLexer;
+
+ /// CurPPLexer - This is the current top of the stack what we're lexing from
+ /// if not expanding a macro. This is an alias for either CurLexer or
+ /// CurPTHLexer.
+ PreprocessorLexer *CurPPLexer;
+
+ /// CurLookup - The DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
+ /// implement #include_next and find directory-specific properties.
+ const DirectoryLookup *CurDirLookup;
+
+ /// CurTokenLexer - This is the current macro we are expanding, if we are
+ /// expanding a macro. One of CurLexer and CurTokenLexer must be null.
+ llvm::OwningPtr<TokenLexer> CurTokenLexer;
+
+ /// IncludeMacroStack - This keeps track of the stack of files currently
+ /// #included, and macros currently being expanded from, not counting
+ /// CurLexer/CurTokenLexer.
+ struct IncludeStackInfo {
+ Lexer *TheLexer;
+ PTHLexer *ThePTHLexer;
+ PreprocessorLexer *ThePPLexer;
+ TokenLexer *TheTokenLexer;
+ const DirectoryLookup *TheDirLookup;
+
+ IncludeStackInfo(Lexer *L, PTHLexer* P, PreprocessorLexer* PPL,
+ TokenLexer* TL, const DirectoryLookup *D)
+ : TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL),
+ TheDirLookup(D) {}
+ };
+ std::vector<IncludeStackInfo> IncludeMacroStack;
+
+ /// Callbacks - These are actions invoked when some preprocessor activity is
+ /// encountered (e.g. a file is #included, etc).
+ PPCallbacks *Callbacks;
+
+ /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping
+ /// to the actual definition of the macro.
+ llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
+
+ /// \brief Macros that we want to warn because they are not used at the end
+ /// of the translation unit; we store just their SourceLocations instead
+ /// something like MacroInfo*. The benefit of this is that when we are
+ /// deserializing from PCH, we don't need to deserialize identifier & macros
+ /// just so that we can report that they are unused, we just warn using
+ /// the SourceLocations of this set (that will be filled by the ASTReader).
+ /// We are using SmallPtrSet instead of a vector for faster removal.
+ typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy;
+ WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
+
+ /// MacroArgCache - This is a "freelist" of MacroArg objects that can be
+ /// reused for quick allocation.
+ MacroArgs *MacroArgCache;
+ friend class MacroArgs;
+
+ /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma
+ /// push_macro directive, we keep a MacroInfo stack used to restore
+ /// previous macro value.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
+ unsigned NumIf, NumElse, NumEndif;
+ unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
+ unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
+ unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
+ unsigned NumSkipped;
+
+ /// Predefines - This string is the predefined macros that preprocessor
+ /// should use from the command line etc.
+ std::string Predefines;
+
+ /// TokenLexerCache - Cache macro expanders to reduce malloc traffic.
+ enum { TokenLexerCacheSize = 8 };
+ unsigned NumCachedTokenLexers;
+ TokenLexer *TokenLexerCache[TokenLexerCacheSize];
+
+ /// \brief A record of the macro definitions and instantiations that
+ /// occurred during preprocessing.
+ ///
+ /// This is an optional side structure that can be enabled with
+ /// \c createPreprocessingRecord() prior to preprocessing.
+ PreprocessingRecord *Record;
+
+private: // Cached tokens state.
+ typedef llvm::SmallVector<Token, 1> CachedTokensTy;
+
+ /// CachedTokens - Cached tokens are stored here when we do backtracking or
+ /// lookahead. They are "lexed" by the CachingLex() method.
+ CachedTokensTy CachedTokens;
+
+ /// CachedLexPos - The position of the cached token that CachingLex() should
+ /// "lex" next. If it points beyond the CachedTokens vector, it means that
+ /// a normal Lex() should be invoked.
+ CachedTokensTy::size_type CachedLexPos;
+
+ /// BacktrackPositions - Stack of backtrack positions, allowing nested
+ /// backtracks. The EnableBacktrackAtThisPos() method pushes a position to
+ /// indicate where CachedLexPos should be set when the BackTrack() method is
+ /// invoked (at which point the last position is popped).
+ std::vector<CachedTokensTy::size_type> BacktrackPositions;
+
+ struct MacroInfoChain {
+ MacroInfo MI;
+ MacroInfoChain *Next;
+ MacroInfoChain *Prev;
+ };
+
+ /// MacroInfos are managed as a chain for easy disposal. This is the head
+ /// of that list.
+ MacroInfoChain *MIChainHead;
+
+ /// MICache - A "freelist" of MacroInfo objects that can be reused for quick
+ /// allocation.
+ MacroInfoChain *MICache;
+
+ MacroInfo *getInfoForMacro(IdentifierInfo *II) const;
+
+public:
+ Preprocessor(Diagnostic &diags, const LangOptions &opts,
+ const TargetInfo &target,
+ SourceManager &SM, HeaderSearch &Headers,
+ IdentifierInfoLookup *IILookup = 0,
+ bool OwnsHeaderSearch = false);
+
+ ~Preprocessor();
+
+ Diagnostic &getDiagnostics() const { return *Diags; }
+ void setDiagnostics(Diagnostic &D) { Diags = &D; }
+
+ const LangOptions &getLangOptions() const { return Features; }
+ const TargetInfo &getTargetInfo() const { return Target; }
+ FileManager &getFileManager() const { return FileMgr; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
+
+ IdentifierTable &getIdentifierTable() { return Identifiers; }
+ SelectorTable &getSelectorTable() { return Selectors; }
+ Builtin::Context &getBuiltinInfo() { return BuiltinInfo; }
+ llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }
+
+ void setPTHManager(PTHManager* pm);
+
+ PTHManager *getPTHManager() { return PTH.get(); }
+
+ void setExternalSource(ExternalPreprocessorSource *Source) {
+ ExternalSource = Source;
+ }
+
+ ExternalPreprocessorSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ /// SetCommentRetentionState - Control whether or not the preprocessor retains
+ /// comments in output.
+ void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
+ this->KeepComments = KeepComments | KeepMacroComments;
+ this->KeepMacroComments = KeepMacroComments;
+ }
+
+ bool getCommentRetentionState() const { return KeepComments; }
+
+ /// isCurrentLexer - Return true if we are lexing directly from the specified
+ /// lexer.
+ bool isCurrentLexer(const PreprocessorLexer *L) const {
+ return CurPPLexer == L;
+ }
+
+ /// getCurrentLexer - Return the current lexer being lexed from. Note
+ /// that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
+
+ /// getCurrentFileLexer - Return the current file lexer being lexed from.
+ /// Note that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentFileLexer() const;
+
+ /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks.
+ /// Note that this class takes ownership of any PPCallbacks object given to
+ /// it.
+ PPCallbacks *getPPCallbacks() const { return Callbacks; }
+ void addPPCallbacks(PPCallbacks *C) {
+ if (Callbacks)
+ C = new PPChainedCallbacks(C, Callbacks);
+ Callbacks = C;
+ }
+
+ /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to
+ /// or null if it isn't #define'd.
+ MacroInfo *getMacroInfo(IdentifierInfo *II) const {
+ if (!II->hasMacroDefinition())
+ return 0;
+
+ return getInfoForMacro(II);
+ }
+
+ /// setMacroInfo - Specify a macro for this identifier.
+ ///
+ void setMacroInfo(IdentifierInfo *II, MacroInfo *MI);
+
+ /// macro_iterator/macro_begin/macro_end - This allows you to walk the current
+ /// state of the macro table. This visits every currently-defined macro.
+ typedef llvm::DenseMap<IdentifierInfo*,
+ MacroInfo*>::const_iterator macro_iterator;
+ macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
+ macro_iterator macro_end(bool IncludeExternalMacros = true) const;
+
+ const std::string &getPredefines() const { return Predefines; }
+ /// setPredefines - Set the predefines for this Preprocessor. These
+ /// predefines are automatically injected when parsing the main file.
+ void setPredefines(const char *P) { Predefines = P; }
+ void setPredefines(const std::string &P) { Predefines = P; }
+
+ /// getIdentifierInfo - Return information about the specified preprocessor
+ /// identifier token. The version of this method that takes two character
+ /// pointers is preferred unless the identifier is already available as a
+ /// string (this avoids allocation and copying of memory to construct an
+ /// std::string).
+ IdentifierInfo *getIdentifierInfo(llvm::StringRef Name) const {
+ return &Identifiers.get(Name);
+ }
+
+ /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
+ /// If 'Namespace' is non-null, then it is a token required to exist on the
+ /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
+ void AddPragmaHandler(llvm::StringRef Namespace, PragmaHandler *Handler);
+ void AddPragmaHandler(PragmaHandler *Handler) {
+ AddPragmaHandler(llvm::StringRef(), Handler);
+ }
+
+ /// RemovePragmaHandler - Remove the specific pragma handler from
+ /// the preprocessor. If \arg Namespace is non-null, then it should
+ /// be the namespace that \arg Handler was added to. It is an error
+ /// to remove a handler that has not been registered.
+ void RemovePragmaHandler(llvm::StringRef Namespace, PragmaHandler *Handler);
+ void RemovePragmaHandler(PragmaHandler *Handler) {
+ RemovePragmaHandler(llvm::StringRef(), Handler);
+ }
+
+ /// \brief Add the specified comment handler to the preprocessor.
+ void AddCommentHandler(CommentHandler *Handler);
+
+ /// \brief Remove the specified comment handler.
+ ///
+ /// It is an error to remove a handler that has not been registered.
+ void RemoveCommentHandler(CommentHandler *Handler);
+
+ /// \brief Set the code completion handler to the given object.
+ void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
+ CodeComplete = &Handler;
+ }
+
+ /// \brief Retrieve the current code-completion handler.
+ CodeCompletionHandler *getCodeCompletionHandler() const {
+ return CodeComplete;
+ }
+
+ /// \brief Clear out the code completion handler.
+ void clearCodeCompletionHandler() {
+ CodeComplete = 0;
+ }
+
+ /// \brief Hook used by the lexer to invoke the "natural language" code
+ /// completion point.
+ void CodeCompleteNaturalLanguage();
+
+ /// \brief Retrieve the preprocessing record, or NULL if there is no
+ /// preprocessing record.
+ PreprocessingRecord *getPreprocessingRecord() const { return Record; }
+
+ /// \brief Create a new preprocessing record, which will keep track of
+ /// all macro expansions, macro definitions, etc.
+ void createPreprocessingRecord();
+
+ /// EnterMainSourceFile - Enter the specified FileID as the main source file,
+ /// which implicitly adds the builtin defines etc.
+ void EnterMainSourceFile();
+
+ /// EndSourceFile - Inform the preprocessor callbacks that processing is
+ /// complete.
+ void EndSourceFile();
+
+ /// EnterSourceFile - Add a source file to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer. Emit an error
+ /// and don't enter the file on error.
+ void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
+ SourceLocation Loc);
+
+ /// EnterMacro - Add a Macro to the top of the include stack and start lexing
+ /// tokens from it instead of the current buffer. Args specifies the
+ /// tokens input to a function-like macro.
+ ///
+ /// ILEnd specifies the location of the ')' for a function-like macro or the
+ /// identifier for an object-like macro.
+ void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args);
+
+ /// EnterTokenStream - Add a "macro" context to the top of the include stack,
+ /// which will cause the lexer to start returning the specified tokens.
+ ///
+ /// If DisableMacroExpansion is true, tokens lexed from the token stream will
+ /// not be subject to further macro expansion. Otherwise, these tokens will
+ /// be re-macro-expanded when/if expansion is enabled.
+ ///
+ /// If OwnsTokens is false, this method assumes that the specified stream of
+ /// tokens has a permanent owner somewhere, so they do not need to be copied.
+ /// If it is true, it assumes the array of tokens is allocated with new[] and
+ /// must be freed.
+ ///
+ void EnterTokenStream(const Token *Toks, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens);
+
+ /// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
+ /// lexer stack. This should only be used in situations where the current
+ /// state of the top-of-stack lexer is known.
+ void RemoveTopOfLexerStack();
+
+ /// EnableBacktrackAtThisPos - From the point that this method is called, and
+ /// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+ /// keeps track of the lexed tokens so that a subsequent Backtrack() call will
+ /// make the Preprocessor re-lex the same tokens.
+ ///
+ /// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
+ /// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
+ /// be combined with the EnableBacktrackAtThisPos calls in reverse order.
+ ///
+ /// NOTE: *DO NOT* forget to call either CommitBacktrackedTokens or Backtrack
+ /// at some point after EnableBacktrackAtThisPos. If you don't, caching of
+ /// tokens will continue indefinitely.
+ ///
+ void EnableBacktrackAtThisPos();
+
+ /// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
+ void CommitBacktrackedTokens();
+
+ /// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
+ /// EnableBacktrackAtThisPos() was previously called.
+ void Backtrack();
+
+ /// isBacktrackEnabled - True if EnableBacktrackAtThisPos() was called and
+ /// caching of tokens is on.
+ bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
+
+ /// Lex - To lex a token from the preprocessor, just pull a token from the
+ /// current lexer or macro object.
+ void Lex(Token &Result) {
+ if (CurLexer)
+ CurLexer->Lex(Result);
+ else if (CurPTHLexer)
+ CurPTHLexer->Lex(Result);
+ else if (CurTokenLexer)
+ CurTokenLexer->Lex(Result);
+ else
+ CachingLex(Result);
+ }
+
+ /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get
+ /// something not a comment. This is useful in -E -C mode where comments
+ /// would foul up preprocessor directive handling.
+ void LexNonComment(Token &Result) {
+ do
+ Lex(Result);
+ while (Result.getKind() == tok::comment);
+ }
+
+ /// LexUnexpandedToken - This is just like Lex, but this disables macro
+ /// expansion of identifier tokens.
+ void LexUnexpandedToken(Token &Result) {
+ // Disable macro expansion.
+ bool OldVal = DisableMacroExpansion;
+ DisableMacroExpansion = true;
+ // Lex the token.
+ Lex(Result);
+
+ // Reenable it.
+ DisableMacroExpansion = OldVal;
+ }
+
+ /// LookAhead - This peeks ahead N tokens and returns that token without
+ /// consuming any tokens. LookAhead(0) returns the next token that would be
+ /// returned by Lex(), LookAhead(1) returns the token after it, etc. This
+ /// returns normal tokens after phase 5. As such, it is equivalent to using
+ /// 'Lex', not 'LexUnexpandedToken'.
+ const Token &LookAhead(unsigned N) {
+ if (CachedLexPos + N < CachedTokens.size())
+ return CachedTokens[CachedLexPos+N];
+ else
+ return PeekAhead(N+1);
+ }
+
+ /// RevertCachedTokens - When backtracking is enabled and tokens are cached,
+ /// this allows to revert a specific number of tokens.
+ /// Note that the number of tokens being reverted should be up to the last
+ /// backtrack position, not more.
+ void RevertCachedTokens(unsigned N) {
+ assert(isBacktrackEnabled() &&
+ "Should only be called when tokens are cached for backtracking");
+ assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back())
+ && "Should revert tokens up to the last backtrack position, not more");
+ assert(signed(CachedLexPos) - signed(N) >= 0 &&
+ "Corrupted backtrack positions ?");
+ CachedLexPos -= N;
+ }
+
+ /// EnterToken - Enters a token in the token stream to be lexed next. If
+ /// BackTrack() is called afterwards, the token will remain at the insertion
+ /// point.
+ void EnterToken(const Token &Tok) {
+ EnterCachingLexMode();
+ CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Tok);
+ }
+
+ /// AnnotateCachedTokens - We notify the Preprocessor that if it is caching
+ /// tokens (because backtrack is enabled) it should replace the most recent
+ /// cached tokens with the given annotation token. This function has no effect
+ /// if backtracking is not enabled.
+ ///
+ /// Note that the use of this function is just for optimization; so that the
+ /// cached tokens doesn't get re-parsed and re-resolved after a backtrack is
+ /// invoked.
+ void AnnotateCachedTokens(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ AnnotatePreviousCachedTokens(Tok);
+ }
+
+ /// \brief Replace the last token with an annotation token.
+ ///
+ /// Like AnnotateCachedTokens(), this routine replaces an
+ /// already-parsed (and resolved) token with an annotation
+ /// token. However, this routine only replaces the last token with
+ /// the annotation token; it does not affect any other cached
+ /// tokens. This function has no effect if backtracking is not
+ /// enabled.
+ void ReplaceLastTokenWithAnnotation(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ CachedTokens[CachedLexPos-1] = Tok;
+ }
+
+ /// \brief Specify the point at which code-completion will be performed.
+ ///
+ /// \param File the file in which code completion should occur. If
+ /// this file is included multiple times, code-completion will
+ /// perform completion the first time it is included. If NULL, this
+ /// function clears out the code-completion point.
+ ///
+ /// \param Line the line at which code completion should occur
+ /// (1-based).
+ ///
+ /// \param Column the column at which code completion should occur
+ /// (1-based).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SetCodeCompletionPoint(const FileEntry *File,
+ unsigned Line, unsigned Column);
+
+ /// \brief Determine if this source location refers into the file
+ /// for which we are performing code completion.
+ bool isCodeCompletionFile(SourceLocation FileLoc) const;
+
+ /// \brief Determine if we are performing code completion.
+ bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; }
+
+ /// \brief Instruct the preprocessor to skip part of the main
+ /// the main source file.
+ ///
+ /// \brief Bytes The number of bytes in the preamble to skip.
+ ///
+ /// \brief StartOfLine Whether skipping these bytes puts the lexer at the
+ /// start of a line.
+ void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) {
+ SkipMainFilePreamble.first = Bytes;
+ SkipMainFilePreamble.second = StartOfLine;
+ }
+
+ /// Diag - Forwarding function for diagnostics. This emits a diagnostic at
+ /// the specified Token's location, translating the token's start
+ /// position in the current buffer into a SourcePosition object for rendering.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags->Report(Loc, DiagID);
+ }
+
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) {
+ return Diags->Report(Tok.getLocation(), DiagID);
+ }
+
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ ///
+ /// \param Invalid If non-NULL, will be set \c true if an error occurs.
+ std::string getSpelling(const Token &Tok, bool *Invalid = 0) const {
+ return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid);
+ }
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// preallocated buffer, instead of as an std::string. The caller is required
+ /// to allocate enough space for the token, which is guaranteed to be at least
+ /// Tok.getLength() bytes long. The length of the actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ bool *Invalid = 0) const {
+ return Lexer::getSpelling(Tok, Buffer, SourceMgr, Features, Invalid);
+ }
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// SmallVector. Note that the returned StringRef may not point to the
+ /// supplied buffer if a copy can be avoided.
+ llvm::StringRef getSpelling(const Token &Tok,
+ llvm::SmallVectorImpl<char> &Buffer,
+ bool *Invalid = 0) const;
+
+ /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
+ /// with length 1, return the character.
+ char getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
+ bool *Invalid = 0) const {
+ assert(Tok.is(tok::numeric_constant) &&
+ Tok.getLength() == 1 && "Called on unsupported token");
+ assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1");
+
+ // If the token is carrying a literal data pointer, just use it.
+ if (const char *D = Tok.getLiteralData())
+ return *D;
+
+ // Otherwise, fall back on getCharacterData, which is slower, but always
+ // works.
+ return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid);
+ }
+
+ /// CreateString - Plop the specified string into a scratch buffer and set the
+ /// specified token's location and length to it. If specified, the source
+ /// location provides a location of the instantiation point of the token.
+ void CreateString(const char *Buf, unsigned Len,
+ Token &Tok, SourceLocation SourceLoc = SourceLocation());
+
+ /// \brief Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) {
+ return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features);
+ }
+
+ /// DumpToken - Print the token to stderr, used for debugging.
+ ///
+ void DumpToken(const Token &Tok, bool DumpFlags = false) const;
+ void DumpLocation(SourceLocation Loc) const;
+ void DumpMacro(const MacroInfo &MI) const;
+
+ /// AdvanceToTokenCharacter - Given a location that specifies the start of a
+ /// token, return a new location that specifies a character within the token.
+ SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Char) const {
+ return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, Features);
+ }
+
+ /// IncrementPasteCounter - Increment the counters for the number of token
+ /// paste operations performed. If fast was specified, this is a 'fast paste'
+ /// case we handled.
+ ///
+ void IncrementPasteCounter(bool isFast) {
+ if (isFast)
+ ++NumFastTokenPaste;
+ else
+ ++NumTokenPaste;
+ }
+
+ void PrintStats();
+
+ /// HandleMicrosoftCommentPaste - When the macro expander pastes together a
+ /// comment (/##/) in microsoft mode, this method handles updating the current
+ /// state, returning the token on the next source line.
+ void HandleMicrosoftCommentPaste(Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor callback methods. These are invoked by a lexer as various
+ // directives and events are found.
+
+ /// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
+ /// identifier information for the token and install it into the token,
+ /// updating the token kind accordingly.
+ IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const;
+
+ /// HandleIdentifier - This callback is invoked when the lexer reads an
+ /// identifier and has filled in the tokens IdentifierInfo member. This
+ /// callback potentially macro expands it or turns it into a named token (like
+ /// 'for').
+ void HandleIdentifier(Token &Identifier);
+
+
+ /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
+ /// the current file. This either returns the EOF token and returns true, or
+ /// pops a level off the include stack and returns false, at which point the
+ /// client should call lex again.
+ bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
+
+ /// HandleEndOfTokenLexer - This callback is invoked when the current
+ /// TokenLexer hits the end of its token stream.
+ bool HandleEndOfTokenLexer(Token &Result);
+
+ /// HandleDirective - This callback is invoked when the lexer sees a # token
+ /// at the start of a line. This consumes the directive, modifies the
+ /// lexer/preprocessor state, and advances the lexer(s) so that the next token
+ /// read is the correct one.
+ void HandleDirective(Token &Result);
+
+ /// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If
+ /// not, emit a diagnostic and consume up until the eom. If EnableMacros is
+ /// true, then we consider macros that expand to zero tokens as being ok.
+ void CheckEndOfDirective(const char *Directive, bool EnableMacros = false);
+
+ /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
+ /// current line until the tok::eom token is found.
+ void DiscardUntilEndOfDirective();
+
+ /// SawDateOrTime - This returns true if the preprocessor has seen a use of
+ /// __DATE__ or __TIME__ in the file so far.
+ bool SawDateOrTime() const {
+ return DATELoc != SourceLocation() || TIMELoc != SourceLocation();
+ }
+ unsigned getCounterValue() const { return CounterValue; }
+ void setCounterValue(unsigned V) { CounterValue = V; }
+
+ /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
+ /// SourceLocation.
+ MacroInfo *AllocateMacroInfo(SourceLocation L);
+
+ /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI.
+ MacroInfo *CloneMacroInfo(const MacroInfo &MI);
+
+ /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+ /// checked and spelled filename, e.g. as an operand of #include. This returns
+ /// true if the input filename was in <>'s or false if it were in ""'s. The
+ /// caller is expected to provide a buffer that is large enough to hold the
+ /// spelling of the filename, but is also expected to handle the case when
+ /// this method decides to use a different buffer.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,llvm::StringRef &Filename);
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// for system #include's or not (i.e. using <> instead of "").
+ const FileEntry *LookupFile(llvm::StringRef Filename,
+ bool isAngled, const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir);
+
+ /// GetCurLookup - The DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
+ /// implement #include_next and find directory-specific properties.
+ const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
+
+ /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+ /// #include.
+ bool isInPrimaryFile() const;
+
+ /// ConcatenateIncludeName - Handle cases where the #include name is expanded
+ /// from a macro as multiple tokens, which need to be glued together. This
+ /// occurs for code like:
+ /// #define FOO <a/b.h>
+ /// #include FOO
+ /// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
+ ///
+ /// This code concatenates and consumes tokens up to the '>' token. It
+ /// returns false if the > was found, otherwise it returns true if it finds
+ /// and consumes the EOM marker.
+ bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer,
+ SourceLocation &End);
+
+ /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// followed by EOM. Return true if the token is not a valid on-off-switch.
+ bool LexOnOffSwitch(tok::OnOffSwitch &OOS);
+
+private:
+
+ void PushIncludeMacroStack() {
+ IncludeMacroStack.push_back(IncludeStackInfo(CurLexer.take(),
+ CurPTHLexer.take(),
+ CurPPLexer,
+ CurTokenLexer.take(),
+ CurDirLookup));
+ CurPPLexer = 0;
+ }
+
+ void PopIncludeMacroStack() {
+ CurLexer.reset(IncludeMacroStack.back().TheLexer);
+ CurPTHLexer.reset(IncludeMacroStack.back().ThePTHLexer);
+ CurPPLexer = IncludeMacroStack.back().ThePPLexer;
+ CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
+ CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ IncludeMacroStack.pop_back();
+ }
+
+ /// AllocateMacroInfo - Allocate a new MacroInfo object.
+ MacroInfo *AllocateMacroInfo();
+
+ /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
+ /// be reused for allocating new MacroInfo objects.
+ void ReleaseMacroInfo(MacroInfo* MI);
+
+ /// ReadMacroName - Lex and validate a macro name, which occurs after a
+ /// #define or #undef. This emits a diagnostic, sets the token kind to eom,
+ /// and discards the rest of the macro line if the macro name is invalid.
+ void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0);
+
+ /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro
+ /// definition has just been read. Lex the rest of the arguments and the
+ /// closing ), updating MI with what we learn. Return true if an error occurs
+ /// parsing the arg list.
+ bool ReadMacroDefinitionArgList(MacroInfo *MI);
+
+ /// SkipExcludedConditionalBlock - We just read a #if or related directive and
+ /// decided that the subsequent tokens are in the #if'd out portion of the
+ /// file. Lex the rest of the file, until we see an #endif. If
+ /// FoundNonSkipPortion is true, then we have already emitted code for part of
+ /// this #if directive, so #else/#elif blocks should never be entered. If
+ /// FoundElse is false, then #else directives are ok, if not, then we have
+ /// already seen one so a #else directive is a duplicate. When this returns,
+ /// the caller can lex the first valid token.
+ void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse);
+
+ /// PTHSkipExcludedConditionalBlock - A fast PTH version of
+ /// SkipExcludedConditionalBlock.
+ void PTHSkipExcludedConditionalBlock();
+
+ /// EvaluateDirectiveExpression - Evaluate an integer constant expression that
+ /// may occur after a #if or #elif directive and return it as a bool. If the
+ /// expression is equivalent to "!defined(X)" return X in IfNDefMacro.
+ bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
+
+ /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
+ /// #pragma GCC poison/system_header/dependency and #pragma once.
+ void RegisterBuiltinPragmas();
+
+ /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
+ /// identifier table.
+ void RegisterBuiltinMacros();
+
+ /// HandleMacroExpandedIdentifier - If an identifier token is read that is to
+ /// be expanded as a macro, handle it and return the next token as 'Tok'. If
+ /// the macro should not be expanded return true, otherwise return false.
+ bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI);
+
+ /// isNextPPTokenLParen - Determine whether the next preprocessor token to be
+ /// lexed is a '('. If so, consume the token and return true, if not, this
+ /// method should have no observable side-effect on the lexed tokens.
+ bool isNextPPTokenLParen();
+
+ /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is
+ /// invoked to read all of the formal arguments specified for the macro
+ /// invocation. This returns null on error.
+ MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI,
+ SourceLocation &InstantiationEnd);
+
+ /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
+ /// as a builtin macro, handle it and return the next token as 'Tok'.
+ void ExpandBuiltinMacro(Token &Tok);
+
+ /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+ /// return the first token after the directive. The _Pragma token has just
+ /// been read into 'Tok'.
+ void Handle_Pragma(Token &Tok);
+
+ /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
+ /// is not enclosed within a string literal.
+ void HandleMicrosoft__pragma(Token &Tok);
+
+ void Handle_Pragma(unsigned Introducer, const std::string &StrVal,
+ SourceLocation PragmaLoc, SourceLocation RParenLoc);
+
+ /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
+
+ /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and
+ /// start getting tokens from it using the PTH cache.
+ void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
+
+ /// IsFileLexer - Returns true if we are lexing from a file and not a
+ /// pragma or a macro.
+ static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
+ return L ? !L->isPragmaLexer() : P != 0;
+ }
+
+ static bool IsFileLexer(const IncludeStackInfo& I) {
+ return IsFileLexer(I.TheLexer, I.ThePPLexer);
+ }
+
+ bool IsFileLexer() const {
+ return IsFileLexer(CurLexer.get(), CurPPLexer);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Caching stuff.
+ void CachingLex(Token &Result);
+ bool InCachingLexMode() const {
+ // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
+ // that we are past EOF, not that we are in CachingLex mode.
+ return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 &&
+ !IncludeMacroStack.empty();
+ }
+ void EnterCachingLexMode();
+ void ExitCachingLexMode() {
+ if (InCachingLexMode())
+ RemoveTopOfLexerStack();
+ }
+ const Token &PeekAhead(unsigned N);
+ void AnnotatePreviousCachedTokens(const Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ /// Handle*Directive - implement the various preprocessor directives. These
+ /// should side-effect the current preprocessor object so that the next call
+ /// to Lex() will return the appropriate token next.
+ void HandleLineDirective(Token &Tok);
+ void HandleDigitDirective(Token &Tok);
+ void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
+ void HandleIdentSCCSDirective(Token &Tok);
+
+ // File inclusion.
+ void HandleIncludeDirective(SourceLocation HashLoc,
+ Token &Tok,
+ const DirectoryLookup *LookupFrom = 0,
+ bool isImport = false);
+ void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
+
+ // Macro handling.
+ void HandleDefineDirective(Token &Tok);
+ void HandleUndefDirective(Token &Tok);
+
+ // Conditional Inclusion.
+ void HandleIfdefDirective(Token &Tok, bool isIfndef,
+ bool ReadAnyTokensBeforeDirective);
+ void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective);
+ void HandleEndifDirective(Token &Tok);
+ void HandleElseDirective(Token &Tok);
+ void HandleElifDirective(Token &Tok);
+
+ // Pragmas.
+ void HandlePragmaDirective(unsigned Introducer);
+public:
+ void HandlePragmaOnce(Token &OnceTok);
+ void HandlePragmaMark();
+ void HandlePragmaPoison(Token &PoisonTok);
+ void HandlePragmaSystemHeader(Token &SysHeaderTok);
+ void HandlePragmaDependency(Token &DependencyTok);
+ void HandlePragmaComment(Token &CommentTok);
+ void HandlePragmaMessage(Token &MessageTok);
+ void HandlePragmaPushMacro(Token &Tok);
+ void HandlePragmaPopMacro(Token &Tok);
+ IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
+
+ // Return true and store the first token only if any CommentHandler
+ // has inserted some tokens and getCommentRetentionState() is false.
+ bool HandleComment(Token &Token, SourceRange Comment);
+
+ /// \brief A macro is used, update information about macros that need unused
+ /// warnings.
+ void markMacroAsUsed(MacroInfo *MI);
+};
+
+/// \brief Abstract base class that describes a handler that will receive
+/// source ranges for each of the comments encountered in the source file.
+class CommentHandler {
+public:
+ virtual ~CommentHandler();
+
+ // The handler shall return true if it has pushed any tokens
+ // to be read using e.g. EnterToken or EnterTokenStream.
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
new file mode 100644
index 0000000..d833293
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
@@ -0,0 +1,174 @@
+//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- 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 PreprocessorLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PreprocessorLexer_H
+#define LLVM_CLANG_PreprocessorLexer_H
+
+#include "clang/Lex/MultipleIncludeOpt.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+
+namespace clang {
+
+class FileEntry;
+class Preprocessor;
+
+class PreprocessorLexer {
+protected:
+ Preprocessor *PP; // Preprocessor object controlling lexing.
+
+ /// The SourceManager FileID corresponding to the file being lexed.
+ const FileID FID;
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //===--------------------------------------------------------------------===//
+
+ /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns
+ /// '\n' into a tok::eom token.
+ bool ParsingPreprocessorDirective;
+
+ /// ParsingFilename - True after #include: this turns <xx> into a
+ /// tok::angle_string_literal token.
+ bool ParsingFilename;
+
+ /// LexingRawMode - True if in raw mode: This flag disables interpretation of
+ /// tokens and is a far faster mode to lex in than non-raw-mode. This flag:
+ /// 1. If EOF of the current lexer is found, the include stack isn't popped.
+ /// 2. Identifier information is not looked up for identifier tokens. As an
+ /// effect of this, implicit macro expansion is naturally disabled.
+ /// 3. "#" tokens at the start of a line are treated as normal tokens, not
+ /// implicitly transformed by the lexer.
+ /// 4. All diagnostic messages are disabled.
+ /// 5. No callbacks are made into the preprocessor.
+ ///
+ /// Note that in raw mode that the PP pointer may be null.
+ bool LexingRawMode;
+
+ /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file
+ /// idiom for the multiple-include optimization.
+ MultipleIncludeOpt MIOpt;
+
+ /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks
+ /// we are currently in.
+ llvm::SmallVector<PPConditionalInfo, 4> ConditionalStack;
+
+ PreprocessorLexer(const PreprocessorLexer&); // DO NOT IMPLEMENT
+ void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT
+ friend class Preprocessor;
+
+ PreprocessorLexer(Preprocessor *pp, FileID fid)
+ : PP(pp), FID(fid), ParsingPreprocessorDirective(false),
+ ParsingFilename(false), LexingRawMode(false) {}
+
+ PreprocessorLexer()
+ : PP(0),
+ ParsingPreprocessorDirective(false),
+ ParsingFilename(false),
+ LexingRawMode(false) {}
+
+ virtual ~PreprocessorLexer() {}
+
+ virtual void IndirectLex(Token& Result) = 0;
+
+ /// getSourceLocation - Return the source location for the next observable
+ /// location.
+ virtual SourceLocation getSourceLocation() = 0;
+
+ //===--------------------------------------------------------------------===//
+ // #if directive handling.
+
+ /// pushConditionalLevel - When we enter a #if directive, this keeps track of
+ /// what we are currently in for diagnostic emission (e.g. #if with missing
+ /// #endif).
+ void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
+ bool FoundNonSkip, bool FoundElse) {
+ PPConditionalInfo CI;
+ CI.IfLoc = DirectiveStart;
+ CI.WasSkipping = WasSkipping;
+ CI.FoundNonSkip = FoundNonSkip;
+ CI.FoundElse = FoundElse;
+ ConditionalStack.push_back(CI);
+ }
+ void pushConditionalLevel(const PPConditionalInfo &CI) {
+ ConditionalStack.push_back(CI);
+ }
+
+ /// popConditionalLevel - Remove an entry off the top of the conditional
+ /// stack, returning information about it. If the conditional stack is empty,
+ /// this returns true and does not fill in the arguments.
+ bool popConditionalLevel(PPConditionalInfo &CI) {
+ if (ConditionalStack.empty()) return true;
+ CI = ConditionalStack.back();
+ ConditionalStack.pop_back();
+ return false;
+ }
+
+ /// peekConditionalLevel - Return the top of the conditional stack. This
+ /// requires that there be a conditional active.
+ PPConditionalInfo &peekConditionalLevel() {
+ assert(!ConditionalStack.empty() && "No conditionals active!");
+ return ConditionalStack.back();
+ }
+
+ unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
+
+public:
+
+ //===--------------------------------------------------------------------===//
+ // Misc. lexing methods.
+
+ /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
+ /// (potentially) macro expand the filename. If the sequence parsed is not
+ /// lexically legal, emit a diagnostic and return a result EOM token.
+ void LexIncludeFilename(Token &Result);
+
+ /// setParsingPreprocessorDirective - Inform the lexer whether or not
+ /// we are currently lexing a preprocessor directive.
+ void setParsingPreprocessorDirective(bool f) {
+ ParsingPreprocessorDirective = f;
+ }
+
+ /// isLexingRawMode - Return true if this lexer is in raw mode or not.
+ bool isLexingRawMode() const { return LexingRawMode; }
+
+ /// getPP - Return the preprocessor object for this lexer.
+ Preprocessor *getPP() const { return PP; }
+
+ FileID getFileID() const {
+ assert(PP &&
+ "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
+ return FID;
+ }
+
+ /// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+ /// getFileID(), this only works for lexers with attached preprocessors.
+ const FileEntry *getFileEntry() const;
+
+ /// \brief Iterator that traverses the current stack of preprocessor
+ /// conditional directives (#if/#ifdef/#ifndef).
+ typedef llvm::SmallVectorImpl<PPConditionalInfo>::const_iterator
+ conditional_iterator;
+
+ conditional_iterator conditional_begin() const {
+ return ConditionalStack.begin();
+ }
+ conditional_iterator conditional_end() const {
+ return ConditionalStack.end();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h b/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h
new file mode 100644
index 0000000..f03515f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h
@@ -0,0 +1,45 @@
+//===--- ScratchBuffer.h - Scratch space for forming tokens -----*- 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 ScratchBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCRATCHBUFFER_H
+#define LLVM_CLANG_SCRATCHBUFFER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class SourceManager;
+
+/// ScratchBuffer - This class exposes a simple interface for the dynamic
+/// construction of tokens. This is used for builtin macros (e.g. __LINE__) as
+/// well as token pasting, etc.
+class ScratchBuffer {
+ SourceManager &SourceMgr;
+ char *CurBuffer;
+ SourceLocation BufferStartLoc;
+ unsigned BytesUsed;
+public:
+ ScratchBuffer(SourceManager &SM);
+
+ /// getToken - Splat the specified text into a temporary MemoryBuffer and
+ /// return a SourceLocation that refers to the token. This is just like the
+ /// previous method, but returns a location that indicates the physloc of the
+ /// token.
+ SourceLocation getToken(const char *Buf, unsigned Len, const char *&DestPtr);
+
+private:
+ void AllocScratchBuffer(unsigned RequestLen);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Token.h b/contrib/llvm/tools/clang/include/clang/Lex/Token.h
new file mode 100644
index 0000000..edcfcc10d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h
@@ -0,0 +1,294 @@
+//===--- Token.h - Token interface ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Token interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKEN_H
+#define LLVM_CLANG_TOKEN_H
+
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/OperatorKinds.h"
+#include <cstdlib>
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// Token - This structure provides full information about a lexed token.
+/// It is not intended to be space efficient, it is intended to return as much
+/// information as possible about each returned token. This is expected to be
+/// compressed into a smaller form if memory footprint is important.
+///
+/// The parser can create a special "annotation token" representing a stream of
+/// tokens that were parsed and semantically resolved, e.g.: "foo::MyClass<int>"
+/// can be represented by a single typename annotation token that carries
+/// information about the SourceRange of the tokens and the type object.
+class Token {
+ /// The location of the token.
+ SourceLocation Loc;
+
+ // Conceptually these next two fields could be in a union. However, this
+ // causes gcc 4.2 to pessimize LexTokenInternal, a very performance critical
+ // routine. Keeping as separate members with casts until a more beautiful fix
+ // presents itself.
+
+ /// UintData - This holds either the length of the token text, when
+ /// a normal token, or the end of the SourceRange when an annotation
+ /// token.
+ unsigned UintData;
+
+ /// PtrData - This is a union of four different pointer types, which depends
+ /// on what type of token this is:
+ /// Identifiers, keywords, etc:
+ /// This is an IdentifierInfo*, which contains the uniqued identifier
+ /// spelling.
+ /// Literals: isLiteral() returns true.
+ /// This is a pointer to the start of the token in a text buffer, which
+ /// may be dirty (have trigraphs / escaped newlines).
+ /// Annotations (resolved type names, C++ scopes, etc): isAnnotation().
+ /// This is a pointer to sema-specific data for the annotation token.
+ /// Other:
+ /// This is null.
+ void *PtrData;
+
+ /// Kind - The actual flavor of token this is.
+ ///
+ unsigned char Kind; // DON'T make Kind a 'tok::TokenKind';
+ // MSVC will treat it as a signed char and
+ // TokenKinds > 127 won't be handled correctly.
+
+ /// Flags - Bits we track about this token, members of the TokenFlags enum.
+ unsigned char Flags;
+public:
+
+ // Various flags set per token:
+ enum TokenFlags {
+ StartOfLine = 0x01, // At start of line or only after whitespace.
+ LeadingSpace = 0x02, // Whitespace exists before this token.
+ DisableExpand = 0x04, // This identifier may never be macro expanded.
+ NeedsCleaning = 0x08, // Contained an escaped newline or trigraph.
+ LeadingEmptyMacro = 0x10 // Empty macro exists before this token.
+ };
+
+ tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
+ void setKind(tok::TokenKind K) { Kind = K; }
+
+ /// is/isNot - Predicates to check if this token is a specific kind, as in
+ /// "if (Tok.is(tok::l_brace)) {...}".
+ bool is(tok::TokenKind K) const { return Kind == (unsigned) K; }
+ bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
+
+ /// isAnyIdentifier - Return true if this is a raw identifier (when lexing
+ /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode).
+ bool isAnyIdentifier() const {
+ return is(tok::identifier) || is(tok::raw_identifier);
+ }
+
+ /// isLiteral - Return true if this is a "literal", like a numeric
+ /// constant, string, etc.
+ bool isLiteral() const {
+ return is(tok::numeric_constant) || is(tok::char_constant) ||
+ is(tok::string_literal) || is(tok::wide_string_literal) ||
+ is(tok::angle_string_literal);
+ }
+
+ bool isAnnotation() const {
+#define ANNOTATION(NAME) \
+ if (is(tok::annot_##NAME)) \
+ return true;
+#include "clang/Basic/TokenKinds.def"
+ return false;
+ }
+
+ /// getLocation - Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getLocation() const { return Loc; }
+ unsigned getLength() const {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ return UintData;
+ }
+
+ void setLocation(SourceLocation L) { Loc = L; }
+ void setLength(unsigned Len) {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ UintData = Len;
+ }
+
+ SourceLocation getAnnotationEndLoc() const {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ return SourceLocation::getFromRawEncoding(UintData);
+ }
+ void setAnnotationEndLoc(SourceLocation L) {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ UintData = L.getRawEncoding();
+ }
+
+ SourceLocation getLastLoc() const {
+ return isAnnotation() ? getAnnotationEndLoc() : getLocation();
+ }
+
+ /// getAnnotationRange - SourceRange of the group of tokens that this
+ /// annotation token represents.
+ SourceRange getAnnotationRange() const {
+ return SourceRange(getLocation(), getAnnotationEndLoc());
+ }
+ void setAnnotationRange(SourceRange R) {
+ setLocation(R.getBegin());
+ setAnnotationEndLoc(R.getEnd());
+ }
+
+ const char *getName() const {
+ return tok::getTokenName( (tok::TokenKind) Kind);
+ }
+
+ /// startToken - Reset all flags to cleared.
+ ///
+ void startToken() {
+ Kind = tok::unknown;
+ Flags = 0;
+ PtrData = 0;
+ UintData = 0;
+ Loc = SourceLocation();
+ }
+
+ IdentifierInfo *getIdentifierInfo() const {
+ assert(isNot(tok::raw_identifier) &&
+ "getIdentifierInfo() on a tok::raw_identifier token!");
+ assert(!isAnnotation() &&
+ "getIdentifierInfo() on an annotation token!");
+ if (isLiteral()) return 0;
+ return (IdentifierInfo*) PtrData;
+ }
+ void setIdentifierInfo(IdentifierInfo *II) {
+ PtrData = (void*) II;
+ }
+
+ /// getRawIdentifierData - For a raw identifier token (i.e., an identifier
+ /// lexed in raw mode), returns a pointer to the start of it in the text
+ /// buffer if known, null otherwise.
+ const char *getRawIdentifierData() const {
+ assert(is(tok::raw_identifier));
+ return reinterpret_cast<const char*>(PtrData);
+ }
+ void setRawIdentifierData(const char *Ptr) {
+ assert(is(tok::raw_identifier));
+ PtrData = const_cast<char*>(Ptr);
+ }
+
+ /// getLiteralData - For a literal token (numeric constant, string, etc), this
+ /// returns a pointer to the start of it in the text buffer if known, null
+ /// otherwise.
+ const char *getLiteralData() const {
+ assert(isLiteral() && "Cannot get literal data of non-literal");
+ return reinterpret_cast<const char*>(PtrData);
+ }
+ void setLiteralData(const char *Ptr) {
+ assert(isLiteral() && "Cannot set literal data of non-literal");
+ PtrData = const_cast<char*>(Ptr);
+ }
+
+ void *getAnnotationValue() const {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ return PtrData;
+ }
+ void setAnnotationValue(void *val) {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ PtrData = val;
+ }
+
+ /// setFlag - Set the specified flag.
+ void setFlag(TokenFlags Flag) {
+ Flags |= Flag;
+ }
+
+ /// clearFlag - Unset the specified flag.
+ void clearFlag(TokenFlags Flag) {
+ Flags &= ~Flag;
+ }
+
+ /// getFlags - Return the internal represtation of the flags.
+ /// Only intended for low-level operations such as writing tokens to
+ // disk.
+ unsigned getFlags() const {
+ return Flags;
+ }
+
+ /// setFlagValue - Set a flag to either true or false.
+ void setFlagValue(TokenFlags Flag, bool Val) {
+ if (Val)
+ setFlag(Flag);
+ else
+ clearFlag(Flag);
+ }
+
+ /// isAtStartOfLine - Return true if this token is at the start of a line.
+ ///
+ bool isAtStartOfLine() const { return (Flags & StartOfLine) ? true : false; }
+
+ /// hasLeadingSpace - Return true if this token has whitespace before it.
+ ///
+ bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; }
+
+ /// isExpandDisabled - Return true if this identifier token should never
+ /// be expanded in the future, due to C99 6.10.3.4p2.
+ bool isExpandDisabled() const {
+ return (Flags & DisableExpand) ? true : false;
+ }
+
+ /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
+ bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
+
+ /// getObjCKeywordID - Return the ObjC keyword kind.
+ tok::ObjCKeywordKind getObjCKeywordID() const;
+
+ /// needsCleaning - Return true if this token has trigraphs or escaped
+ /// newlines in it.
+ ///
+ bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
+
+ /// \brief Return true if this token has an empty macro before it.
+ ///
+ bool hasLeadingEmptyMacro() const {
+ return (Flags & LeadingEmptyMacro) ? true : false;
+ }
+
+};
+
+/// PPConditionalInfo - Information about the conditional stack (#if directives)
+/// currently active.
+struct PPConditionalInfo {
+ /// IfLoc - Location where the conditional started.
+ ///
+ SourceLocation IfLoc;
+
+ /// WasSkipping - True if this was contained in a skipping directive, e.g.
+ /// in a "#if 0" block.
+ bool WasSkipping;
+
+ /// FoundNonSkip - True if we have emitted tokens already, and now we're in
+ /// an #else block or something. Only useful in Skipping blocks.
+ bool FoundNonSkip;
+
+ /// FoundElse - True if we've seen a #else in this block. If so,
+ /// #elif/#else directives are not allowed.
+ bool FoundElse;
+};
+
+} // end namespace clang
+
+namespace llvm {
+ template <>
+ struct isPodLike<clang::Token> { static const bool value = true; };
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
new file mode 100644
index 0000000..094990a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
@@ -0,0 +1,75 @@
+//===--- TokenConcatenation.h - Token Concatenation Avoidance ---*- 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 TokenConcatenation class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LEX_TOKEN_CONCATENATION_H
+#define CLANG_LEX_TOKEN_CONCATENATION_H
+
+#include "clang/Basic/TokenKinds.h"
+
+namespace clang {
+ class Preprocessor;
+ class Token;
+
+ /// TokenConcatenation class, which answers the question of
+ /// "Is it safe to emit two tokens without a whitespace between them, or
+ /// would that cause implicit concatenation of the tokens?"
+ ///
+ /// For example, it emitting two identifiers "foo" and "bar" next to each
+ /// other would cause the lexer to produce one "foobar" token. Emitting "1"
+ /// and ")" next to each other is safe.
+ ///
+ class TokenConcatenation {
+ Preprocessor &PP;
+
+ enum AvoidConcatInfo {
+ /// By default, a token never needs to avoid concatenation. Most tokens
+ /// (e.g. ',', ')', etc) don't cause a problem when concatenated.
+ aci_never_avoid_concat = 0,
+
+ /// aci_custom_firstchar - AvoidConcat contains custom code to handle this
+ /// token's requirements, and it needs to know the first character of the
+ /// token.
+ aci_custom_firstchar = 1,
+
+ /// aci_custom - AvoidConcat contains custom code to handle this token's
+ /// requirements, but it doesn't need to know the first character of the
+ /// token.
+ aci_custom = 2,
+
+ /// aci_avoid_equal - Many tokens cannot be safely followed by an '='
+ /// character. For example, "<<" turns into "<<=" when followed by an =.
+ aci_avoid_equal = 4
+ };
+
+ /// TokenInfo - This array contains information for each token on what
+ /// action to take when avoiding concatenation of tokens in the AvoidConcat
+ /// method.
+ char TokenInfo[tok::NUM_TOKENS];
+ public:
+ TokenConcatenation(Preprocessor &PP);
+
+ bool AvoidConcat(const Token &PrevPrevTok,
+ const Token &PrevTok,
+ const Token &Tok) const;
+
+ private:
+ /// StartsWithL - Return true if the spelling of this token starts with 'L'.
+ bool StartsWithL(const Token &Tok) const;
+
+ /// IsIdentifierL - Return true if the spelling of this token is literally
+ /// 'L'.
+ bool IsIdentifierL(const Token &Tok) const;
+ };
+ } // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
new file mode 100644
index 0000000..3f13e9c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -0,0 +1,154 @@
+//===--- TokenLexer.h - Lex from a token buffer -----------------*- 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 TokenLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENLEXER_H
+#define LLVM_CLANG_TOKENLEXER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class Token;
+ class MacroArgs;
+
+/// TokenLexer - This implements a lexer that returns token from a macro body
+/// or token stream instead of lexing from a character buffer. This is used for
+/// macro expansion and _Pragma handling, for example.
+///
+class TokenLexer {
+ /// Macro - The macro we are expanding from. This is null if expanding a
+ /// token stream.
+ ///
+ MacroInfo *Macro;
+
+ /// ActualArgs - The actual arguments specified for a function-like macro, or
+ /// null. The TokenLexer owns the pointed-to object.
+ MacroArgs *ActualArgs;
+
+ /// PP - The current preprocessor object we are expanding for.
+ ///
+ Preprocessor &PP;
+
+ /// Tokens - This is the pointer to an array of tokens that the macro is
+ /// defined to, with arguments expanded for function-like macros. If this is
+ /// a token stream, these are the tokens we are returning. This points into
+ /// the macro definition we are lexing from, a scratch buffer allocated from
+ /// the preprocessor's bump pointer allocator, or some other buffer that we
+ /// may or may not own (depending on OwnsTokens).
+ const Token *Tokens;
+
+ /// NumTokens - This is the length of the Tokens array.
+ ///
+ unsigned NumTokens;
+
+ /// CurToken - This is the next token that Lex will return.
+ ///
+ unsigned CurToken;
+
+ /// InstantiateLocStart/End - The source location range where this macro was
+ /// instantiated.
+ SourceLocation InstantiateLocStart, InstantiateLocEnd;
+
+ /// Lexical information about the expansion point of the macro: the identifier
+ /// that the macro expanded from had these properties.
+ bool AtStartOfLine : 1;
+ bool HasLeadingSpace : 1;
+
+ /// OwnsTokens - This is true if this TokenLexer allocated the Tokens
+ /// array, and thus needs to free it when destroyed. For simple object-like
+ /// macros (for example) we just point into the token buffer of the macro
+ /// definition, we don't make a copy of it.
+ bool OwnsTokens : 1;
+
+ /// DisableMacroExpansion - This is true when tokens lexed from the TokenLexer
+ /// should not be subject to further macro expansion.
+ bool DisableMacroExpansion : 1;
+
+ TokenLexer(const TokenLexer&); // DO NOT IMPLEMENT
+ void operator=(const TokenLexer&); // DO NOT IMPLEMENT
+public:
+ /// Create a TokenLexer for the specified macro with the specified actual
+ /// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
+ /// ILEnd specifies the location of the ')' for a function-like macro or the
+ /// identifier for an object-like macro.
+ TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs,
+ Preprocessor &pp)
+ : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ Init(Tok, ILEnd, ActualArgs);
+ }
+
+ /// Init - Initialize this TokenLexer to expand from the specified macro
+ /// with the specified argument information. Note that this ctor takes
+ /// ownership of the ActualArgs pointer. ILEnd specifies the location of the
+ /// ')' for a function-like macro or the identifier for an object-like macro.
+ void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs);
+
+ /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is
+ /// specified, this takes ownership of the tokens and delete[]'s them when
+ /// the token lexer is empty.
+ TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion,
+ bool ownsTokens, Preprocessor &pp)
+ : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ Init(TokArray, NumToks, DisableExpansion, ownsTokens);
+ }
+
+ /// Init - Initialize this TokenLexer with the specified token stream.
+ /// This does not take ownership of the specified token vector.
+ ///
+ /// DisableExpansion is true when macro expansion of tokens lexed from this
+ /// stream should be disabled.
+ void Init(const Token *TokArray, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens);
+
+ ~TokenLexer() { destroy(); }
+
+ /// isNextTokenLParen - If the next token lexed will pop this macro off the
+ /// expansion stack, return 2. If the next unexpanded token is a '(', return
+ /// 1, otherwise return 0.
+ unsigned isNextTokenLParen() const;
+
+ /// Lex - Lex and return a token from this macro stream.
+ void Lex(Token &Tok);
+
+private:
+ void destroy();
+
+ /// isAtEnd - Return true if the next lex call will pop this macro off the
+ /// include stack.
+ bool isAtEnd() const {
+ return CurToken == NumTokens;
+ }
+
+ /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
+ /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
+ /// are is another ## after it, chomp it iteratively. Return the result as
+ /// Tok. If this returns true, the caller should immediately return the
+ /// token.
+ bool PasteTokens(Token &Tok);
+
+ /// Expand the arguments of a function-like macro so that we can quickly
+ /// return preexpanded tokens from Tokens.
+ void ExpandFunctionArguments();
+
+ /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
+ /// together to form a comment that comments out everything in the current
+ /// macro, other active macros, and anything left on the current physical
+ /// source line of the instantiated buffer. Handle this by returning the
+ /// first token on the next line.
+ void HandleMicrosoftCommentPaste(Token &Tok);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
new file mode 100644
index 0000000..0d37e21
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
@@ -0,0 +1,47 @@
+//===--- ParseAST.h - Define the ParseAST method ----------------*- 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 clang::ParseAST method.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSEAST_H
+#define LLVM_CLANG_PARSE_PARSEAST_H
+
+namespace clang {
+ class Preprocessor;
+ class ASTConsumer;
+ class ASTContext;
+ class CodeCompleteConsumer;
+ class Sema;
+
+ /// \brief Parse the entire file specified, notifying the ASTConsumer as
+ /// the file is parsed.
+ ///
+ /// This operation inserts the parsed decls into the translation
+ /// unit held by Ctx.
+ ///
+ /// \param CompleteTranslationUnit When true, the parsed file is
+ /// considered to be a complete translation unit, and any
+ /// end-of-translation-unit wrapup will be performed.
+ ///
+ /// \param CompletionConsumer If given, an object to consume code completion
+ /// results.
+ void ParseAST(Preprocessor &pp, ASTConsumer *C,
+ ASTContext &Ctx, bool PrintStats = false,
+ bool CompleteTranslationUnit = true,
+ CodeCompleteConsumer *CompletionConsumer = 0);
+
+ /// \brief Parse the main file known to the preprocessor, producing an
+ /// abstract syntax tree.
+ void ParseAST(Sema &S, bool PrintStats = false);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h
new file mode 100644
index 0000000..f640b37
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICPARSE_H
+#define LLVM_CLANG_DIAGNOSTICPARSE_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define PARSESTART
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_PARSE_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
new file mode 100644
index 0000000..7587920
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
@@ -0,0 +1,1738 @@
+//===--- Parser.h - C Language Parser ---------------------------*- 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 Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSER_H
+#define LLVM_CLANG_PARSE_PARSER_H
+
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <stack>
+#include <list>
+
+namespace clang {
+ class PragmaHandler;
+ class Scope;
+ class DeclGroupRef;
+ class DiagnosticBuilder;
+ class Parser;
+ class PragmaUnusedHandler;
+ class ColonProtectionRAIIObject;
+ class InMessageExpressionRAIIObject;
+
+/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
+/// an entry is printed for it.
+class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
+ const Parser &P;
+public:
+ PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+/// PrecedenceLevels - These are precedences for the binary/ternary
+/// operators in the C99 grammar. These have been named to relate
+/// with the C99 grammar productions. Low precedences numbers bind
+/// more weakly than high numbers.
+namespace prec {
+ enum Level {
+ Unknown = 0, // Not binary operator.
+ Comma = 1, // ,
+ Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
+ Conditional = 3, // ?
+ LogicalOr = 4, // ||
+ LogicalAnd = 5, // &&
+ InclusiveOr = 6, // |
+ ExclusiveOr = 7, // ^
+ And = 8, // &
+ Equality = 9, // ==, !=
+ Relational = 10, // >=, <=, >, <
+ Shift = 11, // <<, >>
+ Additive = 12, // -, +
+ Multiplicative = 13, // *, /, %
+ PointerToMember = 14 // .*, ->*
+ };
+}
+
+/// Parser - This implements a parser for the C family of languages. After
+/// parsing units of the grammar, productions are invoked to handle whatever has
+/// been read.
+///
+class Parser : public CodeCompletionHandler {
+ friend class PragmaUnusedHandler;
+ friend class ColonProtectionRAIIObject;
+ friend class InMessageExpressionRAIIObject;
+ friend class ParenBraceBracketBalancer;
+ PrettyStackTraceParserEntry CrashInfo;
+
+ Preprocessor &PP;
+
+ /// Tok - The current token we are peeking ahead. All parsing methods assume
+ /// that this is valid.
+ Token Tok;
+
+ // PrevTokLocation - The location of the token we previously
+ // consumed. This token is used for diagnostics where we expected to
+ // see a token following another token (e.g., the ';' at the end of
+ // a statement).
+ SourceLocation PrevTokLocation;
+
+ unsigned short ParenCount, BracketCount, BraceCount;
+
+ /// Actions - These are the callbacks we invoke as we parse various constructs
+ /// in the file.
+ Sema &Actions;
+
+ Diagnostic &Diags;
+
+ /// ScopeCache - Cache scopes to reduce malloc traffic.
+ enum { ScopeCacheSize = 16 };
+ unsigned NumCachedScopes;
+ Scope *ScopeCache[ScopeCacheSize];
+
+ /// Ident_super - IdentifierInfo for "super", to support fast
+ /// comparison.
+ IdentifierInfo *Ident_super;
+ /// Ident_vector and Ident_pixel - cached IdentifierInfo's for
+ /// "vector" and "pixel" fast comparison. Only present if
+ /// AltiVec enabled.
+ IdentifierInfo *Ident_vector;
+ IdentifierInfo *Ident_pixel;
+
+ /// C++0x contextual keywords.
+ mutable IdentifierInfo *Ident_final;
+ mutable IdentifierInfo *Ident_override;
+
+ llvm::OwningPtr<PragmaHandler> AlignHandler;
+ llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
+ llvm::OwningPtr<PragmaHandler> OptionsHandler;
+ llvm::OwningPtr<PragmaHandler> PackHandler;
+ llvm::OwningPtr<PragmaHandler> UnusedHandler;
+ llvm::OwningPtr<PragmaHandler> WeakHandler;
+ llvm::OwningPtr<PragmaHandler> FPContractHandler;
+ llvm::OwningPtr<PragmaHandler> OpenCLExtensionHandler;
+
+ /// Whether the '>' token acts as an operator or not. This will be
+ /// true except when we are parsing an expression within a C++
+ /// template argument list, where the '>' closes the template
+ /// argument list.
+ bool GreaterThanIsOperator;
+
+ /// ColonIsSacred - When this is false, we aggressively try to recover from
+ /// code like "foo : bar" as if it were a typo for "foo :: bar". This is not
+ /// safe in case statements and a few other things. This is managed by the
+ /// ColonProtectionRAIIObject RAII object.
+ bool ColonIsSacred;
+
+ /// \brief When true, we are directly inside an Ojective-C messsage
+ /// send expression.
+ ///
+ /// This is managed by the \c InMessageExpressionRAIIObject class, and
+ /// should not be set directly.
+ bool InMessageExpression;
+
+ /// The "depth" of the template parameters currently being parsed.
+ unsigned TemplateParameterDepth;
+
+ /// Factory object for creating AttributeList objects.
+ AttributeList::Factory AttrFactory;
+
+public:
+ Parser(Preprocessor &PP, Sema &Actions);
+ ~Parser();
+
+ const LangOptions &getLang() const { return PP.getLangOptions(); }
+ const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
+ Preprocessor &getPreprocessor() const { return PP; }
+ Sema &getActions() const { return Actions; }
+
+ const Token &getCurToken() const { return Tok; }
+ Scope *getCurScope() const { return Actions.getCurScope(); }
+
+ // Type forwarding. All of these are statically 'void*', but they may all be
+ // different actual classes based on the actions in place.
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXCtorInitializer MemInitTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+
+ typedef llvm::SmallVector<TemplateParameterList *, 4> TemplateParameterLists;
+
+ typedef clang::ExprResult ExprResult;
+ typedef clang::StmtResult StmtResult;
+ typedef clang::BaseResult BaseResult;
+ typedef clang::MemInitResult MemInitResult;
+ typedef clang::TypeResult TypeResult;
+
+ typedef Expr *ExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef Sema::FullExprArg FullExprArg;
+
+ /// Adorns a ExprResult with Actions to make it an ExprResult
+ ExprResult Owned(ExprResult res) {
+ return ExprResult(res);
+ }
+ /// Adorns a StmtResult with Actions to make it an StmtResult
+ StmtResult Owned(StmtResult res) {
+ return StmtResult(res);
+ }
+
+ ExprResult ExprError() { return ExprResult(true); }
+ StmtResult StmtError() { return StmtResult(true); }
+
+ ExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
+ StmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
+
+ ExprResult ExprEmpty() { return ExprResult(false); }
+
+ // Parsing methods.
+
+ /// ParseTranslationUnit - All in one method that initializes parses, and
+ /// shuts down the parser.
+ void ParseTranslationUnit();
+
+ /// Initialize - Warm up the parser.
+ ///
+ void Initialize();
+
+ /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
+ /// the EOF was encountered.
+ bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
+
+ DeclGroupPtrTy FinishPendingObjCActions();
+
+private:
+ //===--------------------------------------------------------------------===//
+ // Low-Level token peeking and consumption methods.
+ //
+
+ /// isTokenParen - Return true if the cur token is '(' or ')'.
+ bool isTokenParen() const {
+ return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren;
+ }
+ /// isTokenBracket - Return true if the cur token is '[' or ']'.
+ bool isTokenBracket() const {
+ return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square;
+ }
+ /// isTokenBrace - Return true if the cur token is '{' or '}'.
+ bool isTokenBrace() const {
+ return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace;
+ }
+
+ /// isTokenStringLiteral - True if this token is a string-literal.
+ ///
+ bool isTokenStringLiteral() const {
+ return Tok.getKind() == tok::string_literal ||
+ Tok.getKind() == tok::wide_string_literal;
+ }
+
+ /// \brief Returns true if the current token is a '=' or '==' and
+ /// false otherwise. If it's '==', we assume that it's a typo and we emit
+ /// DiagID and a fixit hint to turn '==' -> '='.
+ bool isTokenEqualOrMistypedEqualEqual(unsigned DiagID);
+
+ /// ConsumeToken - Consume the current 'peek token' and lex the next one.
+ /// This does not work with all kinds of tokens: strings and specific other
+ /// tokens must be consumed with custom methods below. This returns the
+ /// location of the consumed token.
+ SourceLocation ConsumeToken() {
+ assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
+ !isTokenBrace() &&
+ "Should consume special tokens with Consume*Token");
+ if (Tok.is(tok::code_completion)) {
+ CodeCompletionRecovery();
+ return ConsumeCodeCompletionToken();
+ }
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
+ /// current token type. This should only be used in cases where the type of
+ /// the token really isn't known, e.g. in error recovery.
+ SourceLocation ConsumeAnyToken() {
+ if (isTokenParen())
+ return ConsumeParen();
+ else if (isTokenBracket())
+ return ConsumeBracket();
+ else if (isTokenBrace())
+ return ConsumeBrace();
+ else if (isTokenStringLiteral())
+ return ConsumeStringToken();
+ else
+ return ConsumeToken();
+ }
+
+ /// ConsumeParen - This consume method keeps the paren count up-to-date.
+ ///
+ SourceLocation ConsumeParen() {
+ assert(isTokenParen() && "wrong consume method");
+ if (Tok.getKind() == tok::l_paren)
+ ++ParenCount;
+ else if (ParenCount)
+ --ParenCount; // Don't let unbalanced )'s drive the count negative.
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBracket - This consume method keeps the bracket count up-to-date.
+ ///
+ SourceLocation ConsumeBracket() {
+ assert(isTokenBracket() && "wrong consume method");
+ if (Tok.getKind() == tok::l_square)
+ ++BracketCount;
+ else if (BracketCount)
+ --BracketCount; // Don't let unbalanced ]'s drive the count negative.
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBrace - This consume method keeps the brace count up-to-date.
+ ///
+ SourceLocation ConsumeBrace() {
+ assert(isTokenBrace() && "wrong consume method");
+ if (Tok.getKind() == tok::l_brace)
+ ++BraceCount;
+ else if (BraceCount)
+ --BraceCount; // Don't let unbalanced }'s drive the count negative.
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeStringToken - Consume the current 'peek token', lexing a new one
+ /// and returning the token kind. This method is specific to strings, as it
+ /// handles string literal concatenation, as per C99 5.1.1.2, translation
+ /// phase #6.
+ SourceLocation ConsumeStringToken() {
+ assert(isTokenStringLiteral() &&
+ "Should only consume string literals with this method");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// \brief Consume the current code-completion token.
+ ///
+ /// This routine should be called to consume the code-completion token once
+ /// a code-completion action has already been invoked.
+ SourceLocation ConsumeCodeCompletionToken() {
+ assert(Tok.is(tok::code_completion));
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ ///\ brief When we are consuming a code-completion token within having
+ /// matched specific position in the grammar, provide code-completion results
+ /// based on context.
+ void CodeCompletionRecovery();
+
+ /// \brief Handle the annotation token produced for #pragma unused(...)
+ void HandlePragmaUnused();
+
+ /// GetLookAheadToken - This peeks ahead N tokens and returns that token
+ /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
+ /// returns the token after Tok, etc.
+ ///
+ /// Note that this differs from the Preprocessor's LookAhead method, because
+ /// the Parser always has one token lexed that the preprocessor doesn't.
+ ///
+ const Token &GetLookAheadToken(unsigned N) {
+ if (N == 0 || Tok.is(tok::eof)) return Tok;
+ return PP.LookAhead(N-1);
+ }
+
+ /// NextToken - This peeks ahead one token and returns it without
+ /// consuming it.
+ const Token &NextToken() {
+ return PP.LookAhead(0);
+ }
+
+ /// getTypeAnnotation - Read a parsed type out of an annotation token.
+ static ParsedType getTypeAnnotation(Token &Tok) {
+ return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
+ }
+
+ static void setTypeAnnotation(Token &Tok, ParsedType T) {
+ Tok.setAnnotationValue(T.getAsOpaquePtr());
+ }
+
+ /// TryAnnotateTypeOrScopeToken - If the current token position is on a
+ /// typename (possibly qualified in C++) or a C++ scope specifier not followed
+ /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
+ /// with a single annotation token representing the typename or C++ scope
+ /// respectively.
+ /// This simplifies handling of C++ scope specifiers and allows efficient
+ /// backtracking without the need to re-parse and resolve nested-names and
+ /// typenames.
+ /// It will mainly be called when we expect to treat identifiers as typenames
+ /// (if they are typenames). For example, in C we do not expect identifiers
+ /// inside expressions to be treated as typenames so it will not be called
+ /// for expressions in C.
+ ///
+ /// This returns true if the token was annotated.
+ bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false);
+
+ /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but
+ /// only annotates C++ scope specifiers. This returns true if there
+ /// was an unrecoverable error.
+ bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
+
+ /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens,
+ /// replacing them with the non-context-sensitive keywords. This returns
+ /// true if the token was replaced.
+ bool TryAltiVecToken(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid) {
+ if (!getLang().AltiVec ||
+ (Tok.getIdentifierInfo() != Ident_vector &&
+ Tok.getIdentifierInfo() != Ident_pixel))
+ return false;
+
+ return TryAltiVecTokenOutOfLine(DS, Loc, PrevSpec, DiagID, isInvalid);
+ }
+
+ /// TryAltiVecVectorToken - Check for context-sensitive AltiVec vector
+ /// identifier token, replacing it with the non-context-sensitive __vector.
+ /// This returns true if the token was replaced.
+ bool TryAltiVecVectorToken() {
+ if (!getLang().AltiVec ||
+ Tok.getIdentifierInfo() != Ident_vector) return false;
+ return TryAltiVecVectorTokenOutOfLine();
+ }
+
+ bool TryAltiVecVectorTokenOutOfLine();
+ bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid);
+
+ /// TentativeParsingAction - An object that is used as a kind of "tentative
+ /// parsing transaction". It gets instantiated to mark the token position and
+ /// after the token consumption is done, Commit() or Revert() is called to
+ /// either "commit the consumed tokens" or revert to the previously marked
+ /// token position. Example:
+ ///
+ /// TentativeParsingAction TPA(*this);
+ /// ConsumeToken();
+ /// ....
+ /// TPA.Revert();
+ ///
+ class TentativeParsingAction {
+ Parser &P;
+ Token PrevTok;
+ bool isActive;
+
+ public:
+ explicit TentativeParsingAction(Parser& p) : P(p) {
+ PrevTok = P.Tok;
+ P.PP.EnableBacktrackAtThisPos();
+ isActive = true;
+ }
+ void Commit() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.CommitBacktrackedTokens();
+ isActive = false;
+ }
+ void Revert() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.Backtrack();
+ P.Tok = PrevTok;
+ isActive = false;
+ }
+ ~TentativeParsingAction() {
+ assert(!isActive && "Forgot to call Commit or Revert!");
+ }
+ };
+
+
+ /// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
+ /// this helper function matches and consumes the specified RHS token if
+ /// present. If not present, it emits the specified diagnostic indicating
+ /// that the parser failed to match the RHS of the token at LHSLoc. LHSName
+ /// should be the name of the unmatched LHS token. This returns the location
+ /// of the consumed token.
+ SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok,
+ SourceLocation LHSLoc);
+
+ /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+ /// input. If so, it is consumed and false is returned.
+ ///
+ /// If the input is malformed, this emits the specified diagnostic. Next, if
+ /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
+ /// returned.
+ bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag,
+ const char *DiagMsg = "",
+ tok::TokenKind SkipToTok = tok::unknown);
+
+ /// \brief The parser expects a semicolon and, if present, will consume it.
+ ///
+ /// If the next token is not a semicolon, this emits the specified diagnostic,
+ /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior
+ /// to the semicolon, consumes that extra token.
+ bool ExpectAndConsumeSemi(unsigned DiagID);
+
+ //===--------------------------------------------------------------------===//
+ // Scope manipulation
+
+ /// ParseScope - Introduces a new scope for parsing. The kind of
+ /// scope is determined by ScopeFlags. Objects of this type should
+ /// be created on the stack to coincide with the position where the
+ /// parser enters the new scope, and this object's constructor will
+ /// create that new scope. Similarly, once the object is destroyed
+ /// the parser will exit the scope.
+ class ParseScope {
+ Parser *Self;
+ ParseScope(const ParseScope&); // do not implement
+ ParseScope& operator=(const ParseScope&); // do not implement
+
+ public:
+ // ParseScope - Construct a new object to manage a scope in the
+ // parser Self where the new Scope is created with the flags
+ // ScopeFlags, but only when ManageScope is true (the default). If
+ // ManageScope is false, this object does nothing.
+ ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true)
+ : Self(Self) {
+ if (ManageScope)
+ Self->EnterScope(ScopeFlags);
+ else
+ this->Self = 0;
+ }
+
+ // Exit - Exit the scope associated with this object now, rather
+ // than waiting until the object is destroyed.
+ void Exit() {
+ if (Self) {
+ Self->ExitScope();
+ Self = 0;
+ }
+ }
+
+ ~ParseScope() {
+ Exit();
+ }
+ };
+
+ /// EnterScope - Start a new scope.
+ void EnterScope(unsigned ScopeFlags);
+
+ /// ExitScope - Pop a scope off the scope stack.
+ void ExitScope();
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic Emission and Error recovery.
+
+public:
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
+
+private:
+ void SuggestParentheses(SourceLocation Loc, unsigned DK,
+ SourceRange ParenRange);
+
+ /// SkipUntil - Read tokens until we get to the specified token, then consume
+ /// it (unless DontConsume is true). Because we cannot guarantee that the
+ /// token will ever occur, this skips to the next token, or to some likely
+ /// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
+ /// character.
+ ///
+ /// If SkipUntil finds the specified token, it returns true, otherwise it
+ /// returns false.
+ bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
+ return SkipUntil(&T, 1, StopAtSemi, DontConsume, StopAtCodeCompletion);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
+ tok::TokenKind TokArray[] = {T1, T2};
+ return SkipUntil(TokArray, 2, StopAtSemi, DontConsume,StopAtCodeCompletion);
+ }
+ bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
+ bool StopAtSemi = true, bool DontConsume = false,
+ bool StopAtCodeCompletion = false);
+
+ //===--------------------------------------------------------------------===//
+ // Lexing and parsing of C++ inline methods.
+
+ struct ParsingClass;
+
+ /// [class.mem]p1: "... the class is regarded as complete within
+ /// - function bodies
+ /// - default arguments
+ /// - exception-specifications (TODO: C++0x)
+ /// - and brace-or-equal-initializers (TODO: C++0x)
+ /// for non-static data members (including such things in nested classes)."
+ /// LateParsedDeclarations build the tree of those elements so they can
+ /// be parsed after parsing the top-level class.
+ class LateParsedDeclaration {
+ public:
+ virtual ~LateParsedDeclaration();
+
+ virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMethodDefs();
+ };
+
+ /// Inner node of the LateParsedDeclaration tree that parses
+ /// all its members recursively.
+ class LateParsedClass : public LateParsedDeclaration {
+ public:
+ LateParsedClass(Parser *P, ParsingClass *C);
+ virtual ~LateParsedClass();
+
+ virtual void ParseLexedMethodDeclarations();
+ virtual void ParseLexedMethodDefs();
+
+ private:
+ Parser *Self;
+ ParsingClass *Class;
+ };
+
+ /// Contains the lexed tokens of a member function definition
+ /// which needs to be parsed at the end of the class declaration
+ /// after parsing all other member declarations.
+ struct LexedMethod : public LateParsedDeclaration {
+ Parser *Self;
+ Decl *D;
+ CachedTokens Toks;
+
+ /// \brief Whether this member function had an associated template
+ /// scope. When true, D is a template declaration.
+ /// othewise, it is a member function declaration.
+ bool TemplateScope;
+
+ explicit LexedMethod(Parser* P, Decl *MD)
+ : Self(P), D(MD), TemplateScope(false) {}
+
+ virtual void ParseLexedMethodDefs();
+ };
+
+ /// LateParsedDefaultArgument - Keeps track of a parameter that may
+ /// have a default argument that cannot be parsed yet because it
+ /// occurs within a member function declaration inside the class
+ /// (C++ [class.mem]p2).
+ struct LateParsedDefaultArgument {
+ explicit LateParsedDefaultArgument(Decl *P,
+ CachedTokens *Toks = 0)
+ : Param(P), Toks(Toks) { }
+
+ /// Param - The parameter declaration for this parameter.
+ Decl *Param;
+
+ /// Toks - The sequence of tokens that comprises the default
+ /// argument expression, not including the '=' or the terminating
+ /// ')' or ','. This will be NULL for parameters that have no
+ /// default argument.
+ CachedTokens *Toks;
+ };
+
+ /// LateParsedMethodDeclaration - A method declaration inside a class that
+ /// contains at least one entity whose parsing needs to be delayed
+ /// until the class itself is completely-defined, such as a default
+ /// argument (C++ [class.mem]p2).
+ struct LateParsedMethodDeclaration : public LateParsedDeclaration {
+ explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
+ : Self(P), Method(M), TemplateScope(false) { }
+
+ virtual void ParseLexedMethodDeclarations();
+
+ Parser* Self;
+
+ /// Method - The method declaration.
+ Decl *Method;
+
+ /// \brief Whether this member function had an associated template
+ /// scope. When true, D is a template declaration.
+ /// othewise, it is a member function declaration.
+ bool TemplateScope;
+
+ /// DefaultArgs - Contains the parameters of the function and
+ /// their default arguments. At least one of the parameters will
+ /// have a default argument, but all of the parameters of the
+ /// method will be stored so that they can be reintroduced into
+ /// scope at the appropriate times.
+ llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
+ };
+
+ /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
+ /// C++ class, its method declarations that contain parts that won't be
+ /// parsed until after the definiton is completed (C++ [class.mem]p2),
+ /// the method declarations and possibly attached inline definitions
+ /// will be stored here with the tokens that will be parsed to create those entities.
+ typedef llvm::SmallVector<LateParsedDeclaration*, 2> LateParsedDeclarationsContainer;
+
+ /// \brief Representation of a class that has been parsed, including
+ /// any member function declarations or definitions that need to be
+ /// parsed after the corresponding top-level class is complete.
+ struct ParsingClass {
+ ParsingClass(Decl *TagOrTemplate, bool TopLevelClass)
+ : TopLevelClass(TopLevelClass), TemplateScope(false),
+ TagOrTemplate(TagOrTemplate) { }
+
+ /// \brief Whether this is a "top-level" class, meaning that it is
+ /// not nested within another class.
+ bool TopLevelClass : 1;
+
+ /// \brief Whether this class had an associated template
+ /// scope. When true, TagOrTemplate is a template declaration;
+ /// othewise, it is a tag declaration.
+ bool TemplateScope : 1;
+
+ /// \brief The class or class template whose definition we are parsing.
+ Decl *TagOrTemplate;
+
+ /// LateParsedDeclarations - Method declarations, inline definitions and
+ /// nested classes that contain pieces whose parsing will be delayed until
+ /// the top-level class is fully defined.
+ LateParsedDeclarationsContainer LateParsedDeclarations;
+ };
+
+ /// \brief The stack of classes that is currently being
+ /// parsed. Nested and local classes will be pushed onto this stack
+ /// when they are parsed, and removed afterward.
+ std::stack<ParsingClass *> ClassStack;
+
+ ParsingClass &getCurrentClass() {
+ assert(!ClassStack.empty() && "No lexed method stacks!");
+ return *ClassStack.top();
+ }
+
+ /// \brief RAII object used to inform the actions that we're
+ /// currently parsing a declaration. This is active when parsing a
+ /// variable's initializer, but not when parsing the body of a
+ /// class or function definition.
+ class ParsingDeclRAIIObject {
+ Sema &Actions;
+ Sema::ParsingDeclState State;
+ bool Popped;
+
+ public:
+ ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
+ push();
+ }
+
+ ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
+ : Actions(P.Actions) {
+ if (Other) steal(*Other);
+ else push();
+ }
+
+ /// Creates a RAII object which steals the state from a different
+ /// object instead of pushing.
+ ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
+ : Actions(Other.Actions) {
+ steal(Other);
+ }
+
+ ~ParsingDeclRAIIObject() {
+ abort();
+ }
+
+ /// Resets the RAII object for a new declaration.
+ void reset() {
+ abort();
+ push();
+ }
+
+ /// Signals that the context was completed without an appropriate
+ /// declaration being parsed.
+ void abort() {
+ pop(0);
+ }
+
+ void complete(Decl *D) {
+ assert(!Popped && "ParsingDeclaration has already been popped!");
+ pop(D);
+ }
+
+ private:
+ void steal(ParsingDeclRAIIObject &Other) {
+ State = Other.State;
+ Popped = Other.Popped;
+ Other.Popped = true;
+ }
+
+ void push() {
+ State = Actions.PushParsingDeclaration();
+ Popped = false;
+ }
+
+ void pop(Decl *D) {
+ if (!Popped) {
+ Actions.PopParsingDeclaration(State, D);
+ Popped = true;
+ }
+ }
+ };
+
+ /// A class for parsing a DeclSpec.
+ class ParsingDeclSpec : public DeclSpec {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {}
+ ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {}
+ ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+ : ParsingRAII(P, RAII) {}
+
+ void complete(Decl *D) {
+ ParsingRAII.complete(D);
+ }
+
+ void abort() {
+ ParsingRAII.abort();
+ }
+ };
+
+ /// A class for parsing a declarator.
+ class ParsingDeclarator : public Declarator {
+ ParsingDeclRAIIObject ParsingRAII;
+
+ public:
+ ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+ : Declarator(DS, C), ParsingRAII(P) {
+ }
+
+ const ParsingDeclSpec &getDeclSpec() const {
+ return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+ }
+
+ ParsingDeclSpec &getMutableDeclSpec() const {
+ return const_cast<ParsingDeclSpec&>(getDeclSpec());
+ }
+
+ void clear() {
+ Declarator::clear();
+ ParsingRAII.reset();
+ }
+
+ void complete(Decl *D) {
+ ParsingRAII.complete(D);
+ }
+ };
+
+ /// \brief RAII object used to
+ class ParsingClassDefinition {
+ Parser &P;
+ bool Popped;
+ Sema::ParsingClassState State;
+
+ public:
+ ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass)
+ : P(P), Popped(false),
+ State(P.PushParsingClass(TagOrTemplate, TopLevelClass)) {
+ }
+
+ /// \brief Pop this class of the stack.
+ void Pop() {
+ assert(!Popped && "Nested class has already been popped");
+ Popped = true;
+ P.PopParsingClass(State);
+ }
+
+ ~ParsingClassDefinition() {
+ if (!Popped)
+ P.PopParsingClass(State);
+ }
+ };
+
+ /// \brief Contains information about any template-specific
+ /// information that has been parsed prior to parsing declaration
+ /// specifiers.
+ struct ParsedTemplateInfo {
+ ParsedTemplateInfo()
+ : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
+
+ ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
+ bool isSpecialization,
+ bool lastParameterListWasEmpty = false)
+ : Kind(isSpecialization? ExplicitSpecialization : Template),
+ TemplateParams(TemplateParams),
+ LastParameterListWasEmpty(lastParameterListWasEmpty) { }
+
+ explicit ParsedTemplateInfo(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc)
+ : Kind(ExplicitInstantiation), TemplateParams(0),
+ ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+ LastParameterListWasEmpty(false){ }
+
+ /// \brief The kind of template we are parsing.
+ enum {
+ /// \brief We are not parsing a template at all.
+ NonTemplate = 0,
+ /// \brief We are parsing a template declaration.
+ Template,
+ /// \brief We are parsing an explicit specialization.
+ ExplicitSpecialization,
+ /// \brief We are parsing an explicit instantiation.
+ ExplicitInstantiation
+ } Kind;
+
+ /// \brief The template parameter lists, for template declarations
+ /// and explicit specializations.
+ TemplateParameterLists *TemplateParams;
+
+ /// \brief The location of the 'extern' keyword, if any, for an explicit
+ /// instantiation
+ SourceLocation ExternLoc;
+
+ /// \brief The location of the 'template' keyword, for an explicit
+ /// instantiation.
+ SourceLocation TemplateLoc;
+
+ /// \brief Whether the last template parameter list was empty.
+ bool LastParameterListWasEmpty;
+
+ SourceRange getSourceRange() const;
+ };
+
+ Sema::ParsingClassState
+ PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
+ void DeallocateParsedClasses(ParsingClass *Class);
+ void PopParsingClass(Sema::ParsingClassState);
+
+ Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers& VS);
+ void ParseLexedMethodDeclarations(ParsingClass &Class);
+ void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
+ void ParseLexedMethodDefs(ParsingClass &Class);
+ void ParseLexedMethodDef(LexedMethod &LM);
+ bool ConsumeAndStoreUntil(tok::TokenKind T1,
+ CachedTokens &Toks,
+ bool StopAtSemi = true,
+ bool ConsumeFinalToken = true) {
+ return ConsumeAndStoreUntil(T1, T1, Toks, StopAtSemi, ConsumeFinalToken);
+ }
+ bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+ CachedTokens &Toks,
+ bool StopAtSemi = true,
+ bool ConsumeFinalToken = true);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.9: External Definitions.
+ struct ParsedAttributesWithRange : ParsedAttributes {
+ SourceRange Range;
+ };
+
+ DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = 0);
+ bool isDeclarationAfterDeclarator() const;
+ bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
+ AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
+ AccessSpecifier AS = AS_none);
+
+ Decl *ParseFunctionDefinition(ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+ void ParseKNRParamDeclarations(Declarator &D);
+ // EndLoc, if non-NULL, is filled with the location of the last token of
+ // the simple-asm.
+ ExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
+ ExprResult ParseAsmStringLiteral();
+
+ // Objective-C External Declarations
+ Decl *ParseObjCAtDirectives();
+ Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ ParsedAttributes &prefixAttrs);
+ void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
+ tok::ObjCKeywordKind visibility,
+ SourceLocation atLoc);
+ bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &P,
+ llvm::SmallVectorImpl<SourceLocation> &PLocs,
+ bool WarnOnDeclarations,
+ SourceLocation &LAngleLoc,
+ SourceLocation &EndProtoLoc);
+ bool ParseObjCProtocolQualifiers(DeclSpec &DS);
+ void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
+ tok::ObjCKeywordKind contextKey);
+ Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ ParsedAttributes &prefixAttrs);
+
+ Decl *ObjCImpDecl;
+ llvm::SmallVector<Decl *, 4> PendingObjCImpDecl;
+
+ Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtEndDeclaration(SourceRange atEnd);
+ Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
+ Decl *ParseObjCPropertyDynamic(SourceLocation atLoc);
+
+ IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation);
+ // Definitions for Objective-c context sensitive keywords recognition.
+ enum ObjCTypeQual {
+ objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref,
+ objc_NumQuals
+ };
+ IdentifierInfo *ObjCTypeQuals[objc_NumQuals];
+
+ bool isTokIdentifier_in() const;
+
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter);
+ void ParseObjCMethodRequirement();
+ Decl *ParseObjCMethodPrototype(Decl *classOrCat,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
+ Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ Decl *classDecl,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl);
+
+ Decl *ParseObjCMethodDefinition();
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.5: Expressions.
+
+ ExprResult ParseExpression();
+ ExprResult ParseConstantExpression();
+ // Expr that doesn't include commas.
+ ExprResult ParseAssignmentExpression();
+
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+
+ ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+
+ ExprResult ParseRHSOfBinaryExpression(ExprResult LHS,
+ prec::Level MinPrec);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ bool &NotCastExpr,
+ ParsedType TypeOfCast);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand = false,
+ ParsedType TypeOfCast = ParsedType());
+
+ /// Returns true if the next token would start a postfix-expression
+ /// suffix.
+ bool isPostfixExpressionSuffixStart() {
+ tok::TokenKind K = Tok.getKind();
+ return (K == tok::l_square || K == tok::l_paren ||
+ K == tok::period || K == tok::arrow ||
+ K == tok::plusplus || K == tok::minusminus);
+ }
+
+ ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
+ ExprResult ParseSizeofAlignofExpression();
+ ExprResult ParseBuiltinPrimaryExpression();
+
+ ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+ bool &isCastExpr,
+ ParsedType &CastTy,
+ SourceRange &CastRange);
+
+ typedef llvm::SmallVector<Expr*, 20> ExprListTy;
+ typedef llvm::SmallVector<SourceLocation, 20> CommaLocsTy;
+
+ /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+ bool ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
+ llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S,
+ Expr *Data,
+ Expr **Args,
+ unsigned NumArgs) = 0,
+ Expr *Data = 0);
+
+ /// ParenParseOption - Control what ParseParenExpression will parse.
+ enum ParenParseOption {
+ SimpleExpr, // Only parse '(' expression ')'
+ CompoundStmt, // Also allow '(' compound-statement ')'
+ CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
+ CastExpr // Also allow '(' type-name ')' <anything>
+ };
+ ExprResult ParseParenExpression(ParenParseOption &ExprType,
+ bool stopIfCastExpr,
+ ParsedType TypeOfCast,
+ ParsedType &CastTy,
+ SourceLocation &RParenLoc);
+
+ ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+ ParsedType &CastTy,
+ SourceLocation LParenLoc,
+ SourceLocation &RParenLoc);
+
+ ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ ExprResult ParseStringLiteralExpression();
+
+ //===--------------------------------------------------------------------===//
+ // C++ Expressions
+ ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+
+ bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ bool *MayBePseudoDestructor = 0);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Casts
+ ExprResult ParseCXXCasts();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Type Identification
+ ExprResult ParseCXXTypeid();
+
+ //===--------------------------------------------------------------------===//
+ // C++ : Microsoft __uuidof Expression
+ ExprResult ParseCXXUuidof();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.4: C++ Pseudo-Destructor Expressions
+ ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ ParsedType ObjectType);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9.3.2: C++ 'this' pointer
+ ExprResult ParseCXXThis();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 15: C++ Throw Expression
+ ExprResult ParseThrowExpression();
+ // EndLoc is filled with the location of the last token of the specification.
+ bool ParseExceptionSpecification(SourceLocation &EndLoc,
+ llvm::SmallVectorImpl<ParsedType> &Exns,
+ llvm::SmallVectorImpl<SourceRange> &Ranges,
+ bool &hasAnyExceptionSpec);
+
+ //===--------------------------------------------------------------------===//
+ // C++0x 8: Function declaration trailing-return-type
+ TypeResult ParseTrailingReturnType();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 2.13.5: C++ Boolean Literals
+ ExprResult ParseCXXBoolLiteral();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.3: Explicit type conversion (functional notation)
+ ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+
+ bool isCXXSimpleTypeSpecifier() const;
+
+ /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
+ /// This should only be called when the current token is known to be part of
+ /// simple-type-specifier.
+ void ParseCXXSimpleTypeSpecifier(DeclSpec &DS);
+
+ bool ParseCXXTypeSpecifierSeq(DeclSpec &DS);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.3.4 and 5.3.5: C++ new and delete
+ bool ParseExpressionListOrTypeId(llvm::SmallVectorImpl<Expr*> &Exprs,
+ Declarator &D);
+ void ParseDirectNewDeclarator(Declarator &D);
+ ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
+ ExprResult ParseCXXDeleteExpression(bool UseGlobal,
+ SourceLocation Start);
+
+ //===--------------------------------------------------------------------===//
+ // C++ if/switch/while condition expression.
+ bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult,
+ SourceLocation Loc, bool ConvertToBoolean);
+
+ //===--------------------------------------------------------------------===//
+ // C++ types
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7.8: Initialization.
+
+ /// ParseInitializer
+ /// initializer: [C99 6.7.8]
+ /// assignment-expression
+ /// '{' ...
+ ExprResult ParseInitializer() {
+ if (Tok.isNot(tok::l_brace))
+ return ParseAssignmentExpression();
+ return ParseBraceInitializer();
+ }
+ ExprResult ParseBraceInitializer();
+ ExprResult ParseInitializerWithPotentialDesignator();
+
+ //===--------------------------------------------------------------------===//
+ // clang Expressions
+
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Expressions
+ ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ bool isSimpleObjCMessageExpression();
+ ExprResult ParseObjCMessageExpression();
+ ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
+ SourceLocation SuperLoc,
+ ParsedType ReceiverType,
+ ExprArg ReceiverExpr);
+ ExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ SourceLocation LBracloc, SourceLocation SuperLoc,
+ ParsedType ReceiverType, ExprArg ReceiverExpr);
+ bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.8: Statements and Blocks.
+
+ StmtResult ParseStatement() {
+ StmtVector Stmts(Actions);
+ return ParseStatementOrDeclaration(Stmts, true);
+ }
+ StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
+ bool OnlyStatement = false);
+ StmtResult ParseLabeledStatement(ParsedAttributes &Attr);
+ StmtResult ParseCaseStatement(ParsedAttributes &Attr);
+ StmtResult ParseDefaultStatement(ParsedAttributes &Attr);
+ StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
+ bool isStmtExpr = false);
+ StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
+ SourceLocation Loc,
+ bool ConvertToBoolean);
+ StmtResult ParseIfStatement(ParsedAttributes &Attr);
+ StmtResult ParseSwitchStatement(ParsedAttributes &Attr);
+ StmtResult ParseWhileStatement(ParsedAttributes &Attr);
+ StmtResult ParseDoStatement(ParsedAttributes &Attr);
+ StmtResult ParseForStatement(ParsedAttributes &Attr);
+ StmtResult ParseGotoStatement(ParsedAttributes &Attr);
+ StmtResult ParseContinueStatement(ParsedAttributes &Attr);
+ StmtResult ParseBreakStatement(ParsedAttributes &Attr);
+ StmtResult ParseReturnStatement(ParsedAttributes &Attr);
+ StmtResult ParseAsmStatement(bool &msAsm);
+ StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
+ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
+ llvm::SmallVectorImpl<ExprTy *> &Constraints,
+ llvm::SmallVectorImpl<ExprTy *> &Exprs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 6: Statements and Blocks
+
+ StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);
+ StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
+ StmtResult ParseCXXCatchBlock();
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Statements
+
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7: Declarations.
+
+ /// A context for parsing declaration specifiers. TODO: flesh this
+ /// out, there are other significant restrictions on specifiers than
+ /// would be best implemented in the parser.
+ enum DeclSpecContext {
+ DSC_normal, // normal context
+ DSC_class, // class context, enables 'friend'
+ DSC_top_level // top-level/namespace declaration context
+ };
+
+ DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts,
+ unsigned Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs);
+ DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
+ unsigned Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs,
+ bool RequireSemi);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd = 0);
+ Decl *ParseDeclarationAfterDeclarator(Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+ Decl *ParseFunctionStatementBody(Decl *Decl);
+ Decl *ParseFunctionTryBlock(Decl *Decl);
+
+ /// \brief When in code-completion, skip parsing of the function/method body
+ /// unless the body contains the code-completion point.
+ ///
+ /// \returns true if the function body was skipped.
+ bool trySkippingFunctionBodyForCodeCompletion();
+
+ bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS);
+ DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context);
+ void ParseDeclarationSpecifiers(DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DSC_normal);
+ bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ bool SuppressDeclarations = false);
+
+ void ParseSpecifierQualifierList(DeclSpec &DS);
+
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter);
+
+ void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none);
+ void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
+ void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+ Decl *TagDecl);
+
+ struct FieldCallback {
+ virtual Decl *invoke(FieldDeclarator &Field) = 0;
+ virtual ~FieldCallback() {}
+
+ private:
+ virtual void _anchor();
+ };
+ struct ObjCPropertyCallback;
+
+ void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
+
+ bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
+ bool isTypeSpecifierQualifier();
+ bool isTypeQualifier() const;
+
+ /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
+ /// is definitely a type-specifier. Return false if it isn't part of a type
+ /// specifier or if we're not sure.
+ bool isKnownToBeTypeSpecifier(const Token &Tok) const;
+
+ /// isDeclarationStatement - Disambiguates between a declaration or an
+ /// expression statement, when parsing function bodies.
+ /// Returns true for declaration, false for expression.
+ bool isDeclarationStatement() {
+ if (getLang().CPlusPlus)
+ return isCXXDeclarationStatement();
+ return isDeclarationSpecifier(true);
+ }
+
+ /// isSimpleDeclaration - Disambiguates between a declaration or an
+ /// expression, mainly used for the C 'clause-1' or the C++
+ // 'for-init-statement' part of a 'for' statement.
+ /// Returns true for declaration, false for expression.
+ bool isSimpleDeclaration() {
+ if (getLang().CPlusPlus)
+ return isCXXSimpleDeclaration();
+ return isDeclarationSpecifier(true);
+ }
+
+ /// \brief Determine whether we are currently at the start of an Objective-C
+ /// class message that appears to be missing the open bracket '['.
+ bool isStartOfObjCClassMessageMissingOpenBracket();
+
+ /// \brief Starting with a scope specifier, identifier, or
+ /// template-id that refers to the current class, determine whether
+ /// this is a constructor declarator.
+ bool isConstructorDeclarator();
+
+ /// \brief Specifies the context in which type-id/expression
+ /// disambiguation will occur.
+ enum TentativeCXXTypeIdContext {
+ TypeIdInParens,
+ TypeIdAsTemplateArgument
+ };
+
+
+ /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
+ /// whether the parens contain an expression or a type-id.
+ /// Returns true for a type-id and false for an expression.
+ bool isTypeIdInParens(bool &isAmbiguous) {
+ if (getLang().CPlusPlus)
+ return isCXXTypeId(TypeIdInParens, isAmbiguous);
+ isAmbiguous = false;
+ return isTypeSpecifierQualifier();
+ }
+ bool isTypeIdInParens() {
+ bool isAmbiguous;
+ return isTypeIdInParens(isAmbiguous);
+ }
+
+ /// isCXXDeclarationStatement - C++-specialized function that disambiguates
+ /// between a declaration or an expression statement, when parsing function
+ /// bodies. Returns true for declaration, false for expression.
+ bool isCXXDeclarationStatement();
+
+ /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+ /// between a simple-declaration or an expression-statement.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ /// Returns false if the statement is disambiguated as expression.
+ bool isCXXSimpleDeclaration();
+
+ /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+ /// a constructor-style initializer, when parsing declaration statements.
+ /// Returns true for function declarator and false for constructor-style
+ /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to
+ /// indicate that the parens were disambiguated as function declarator.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ bool isCXXFunctionDeclarator(bool warnIfAmbiguous);
+
+ /// isCXXConditionDeclaration - Disambiguates between a declaration or an
+ /// expression for a condition of a if/switch/while/for statement.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ bool isCXXConditionDeclaration();
+
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous);
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context) {
+ bool isAmbiguous;
+ return isCXXTypeId(Context, isAmbiguous);
+ }
+
+ /// TPResult - Used as the result value for functions whose purpose is to
+ /// disambiguate C++ constructs by "tentatively parsing" them.
+ /// This is a class instead of a simple enum because the implicit enum-to-bool
+ /// conversions may cause subtle bugs.
+ class TPResult {
+ enum Result {
+ TPR_true,
+ TPR_false,
+ TPR_ambiguous,
+ TPR_error
+ };
+ Result Res;
+ TPResult(Result result) : Res(result) {}
+ public:
+ static TPResult True() { return TPR_true; }
+ static TPResult False() { return TPR_false; }
+ static TPResult Ambiguous() { return TPR_ambiguous; }
+ static TPResult Error() { return TPR_error; }
+
+ bool operator==(const TPResult &RHS) const { return Res == RHS.Res; }
+ bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; }
+ };
+
+ /// \brief Based only on the given token kind, determine whether we know that
+ /// we're at the start of an expression or a type-specifier-seq (which may
+ /// be an expression, in C++).
+ ///
+ /// This routine does not attempt to resolve any of the trick cases, e.g.,
+ /// those involving lookup of identifiers.
+ ///
+ /// \returns \c TPR_true if this token starts an expression, \c TPR_false if
+ /// this token starts a type-specifier-seq, or \c TPR_ambiguous if it cannot
+ /// tell.
+ TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind);
+
+ /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a
+ /// declaration specifier, TPResult::False() if it is not,
+ /// TPResult::Ambiguous() if it could be either a decl-specifier or a
+ /// function-style cast, and TPResult::Error() if a parsing error was
+ /// encountered.
+ /// Doesn't consume tokens.
+ TPResult isCXXDeclarationSpecifier();
+
+ // "Tentative parsing" functions, used for disambiguation. If a parsing error
+ // is encountered they will return TPResult::Error().
+ // Returning TPResult::True()/False() indicates that the ambiguity was
+ // resolved and tentative parsing may stop. TPResult::Ambiguous() indicates
+ // that more tentative parsing is necessary for disambiguation.
+ // They all consume tokens, so backtracking should be used after calling them.
+
+ TPResult TryParseDeclarationSpecifier();
+ TPResult TryParseSimpleDeclaration();
+ TPResult TryParseTypeofSpecifier();
+ TPResult TryParseProtocolQualifiers();
+ TPResult TryParseInitDeclaratorList();
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
+ TPResult TryParseParameterDeclarationClause();
+ TPResult TryParseFunctionDeclarator();
+ TPResult TryParseBracketDeclarator();
+
+ TypeResult ParseTypeName(SourceRange *Range = 0,
+ Declarator::TheContext Context
+ = Declarator::TypeNameContext);
+ void ParseBlockId();
+
+ void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
+ if (!attrs.Range.isValid()) return;
+ DiagnoseProhibitedAttributes(attrs);
+ }
+ void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
+
+ void MaybeParseGNUAttributes(Declarator &D) {
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributes attrs;
+ SourceLocation endLoc;
+ ParseGNUAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs, endLoc);
+ }
+ void ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+
+ void MaybeParseCXX0XAttributes(Declarator &D) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrs;
+ SourceLocation endLoc;
+ ParseCXX0XAttributes(attrs, &endLoc);
+ D.addAttributes(attrs.getList(), endLoc);
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ ParsedAttributesWithRange attrsWithRange;
+ ParseCXX0XAttributes(attrsWithRange, endLoc);
+ attrs.append(attrsWithRange.getList());
+ }
+ }
+ void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ ParseCXX0XAttributes(attrs, endLoc);
+ }
+ void ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *EndLoc = 0);
+
+ void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0) {
+ if (getLang().Microsoft && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(attrs, endLoc);
+ }
+ void ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = 0);
+ void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
+ void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLAttributes(ParsedAttributes &attrs);
+
+ void ParseTypeofSpecifier(DeclSpec &DS);
+ void ParseDecltypeSpecifier(DeclSpec &DS);
+
+ ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
+
+ VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const;
+ void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS);
+
+ ClassVirtSpecifiers::Specifier isCXX0XClassVirtSpecifier() const;
+ void ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS);
+
+ /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
+ /// enter a new C++ declarator scope and exit it when the function is
+ /// finished.
+ class DeclaratorScopeObj {
+ Parser &P;
+ CXXScopeSpec &SS;
+ bool EnteredScope;
+ bool CreatedScope;
+ public:
+ DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss)
+ : P(p), SS(ss), EnteredScope(false), CreatedScope(false) {}
+
+ void EnterDeclaratorScope() {
+ assert(!EnteredScope && "Already entered the scope!");
+ assert(SS.isSet() && "C++ scope was not set!");
+
+ CreatedScope = true;
+ P.EnterScope(0); // Not a decl scope.
+
+ if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.getCurScope(), SS))
+ EnteredScope = true;
+ }
+
+ ~DeclaratorScopeObj() {
+ if (EnteredScope) {
+ assert(SS.isSet() && "C++ scope was cleared ?");
+ P.Actions.ActOnCXXExitDeclaratorScope(P.getCurScope(), SS);
+ }
+ if (CreatedScope)
+ P.ExitScope();
+ }
+ };
+
+ /// ParseDeclarator - Parse and verify a newly-initialized declarator.
+ void ParseDeclarator(Declarator &D);
+ /// A function that parses a variant of direct-declarator.
+ typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
+ void ParseDeclaratorInternal(Declarator &D,
+ DirectDeclParseFunction DirectDeclParser);
+
+ void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
+ bool CXX0XAttributesAllowed = true);
+ void ParseDirectDeclarator(Declarator &D);
+ void ParseParenDeclarator(Declarator &D);
+ void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
+ ParsedAttributes &attrs,
+ bool RequiresArg = false);
+ void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
+ IdentifierInfo *FirstIdent,
+ SourceLocation FirstIdentLoc,
+ Declarator &D);
+ void ParseBracketDeclarator(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 7: Declarations [dcl.dcl]
+
+ bool isCXX0XAttributeSpecifier(bool FullLookahead = false,
+ tok::TokenKind *After = 0);
+
+ Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
+ Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
+ Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs);
+ Decl *ParseUsingDirective(unsigned Context,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs);
+ Decl *ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9: classes [class] and C structs/unions.
+ TypeResult ParseClassName(SourceLocation &EndLocation,
+ CXXScopeSpec *SS = 0);
+ void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
+ DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none,
+ bool SuppressDeclarations = false);
+ void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
+ Decl *TagDecl);
+ void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = 0);
+ void ParseConstructorInitializer(Decl *ConstructorDecl);
+ MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
+ void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
+ Decl *ThisDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 10: Derived classes [class.derived]
+ void ParseBaseClause(Decl *ClassDecl);
+ BaseResult ParseBaseSpecifier(Decl *ClassDecl);
+ AccessSpecifier getAccessSpecifierIfPresent() const;
+
+ bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Id,
+ bool AssumeTemplateId,
+ SourceLocation TemplateKWLoc);
+ bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Result);
+ bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ ParsedType ObjectType,
+ UnqualifiedId &Result);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 14: Templates [temp]
+
+ // C++ 14.1: Template Parameters [temp.param]
+ Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS);
+ Decl *ParseSingleDeclarationAfterTemplate(
+ unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS=AS_none);
+ bool ParseTemplateParameters(unsigned Depth,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc);
+ bool ParseTemplateParameterList(unsigned Depth,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams);
+ bool isStartOfTemplateTypeParameter();
+ Decl *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ // C++ 14.3: Template arguments [temp.arg]
+ typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
+
+ bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ const CXXScopeSpec *SS,
+ bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ SourceLocation &RAngleLoc);
+
+ bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+ const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
+ SourceLocation TemplateKWLoc = SourceLocation(),
+ bool AllowTypeAnnotation = true);
+ void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
+ bool IsTemplateArgumentList(unsigned Skip = 0);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
+ ParsedTemplateArgument ParseTemplateArgument();
+ Decl *ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
+ ExprResult ParseUnaryTypeTrait();
+ ExprResult ParseBinaryTypeTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor code-completion pass-through
+ virtual void CodeCompleteDirective(bool InConditional);
+ virtual void CodeCompleteInConditionalExclusion();
+ virtual void CodeCompleteMacroName(bool IsDefinition);
+ virtual void CodeCompletePreprocessorExpression();
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex);
+ virtual void CodeCompleteNaturalLanguage();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h
new file mode 100644
index 0000000..b7f6427
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/ASTConsumers.h
@@ -0,0 +1,45 @@
+//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REWRITE_ASTCONSUMERS_H
+#define REWRITE_ASTCONSUMERS_H
+
+#include <string>
+
+namespace llvm {
+ class raw_ostream;
+}
+namespace clang {
+
+class ASTConsumer;
+class Diagnostic;
+class LangOptions;
+class Preprocessor;
+
+// ObjC rewriter: attempts to rewrite ObjC constructs into pure C code.
+// This is considered experimental, and only works with Apple's ObjC runtime.
+ASTConsumer *CreateObjCRewriter(const std::string &InFile,
+ llvm::raw_ostream *OS,
+ Diagnostic &Diags,
+ const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning);
+
+/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to
+/// HTML with syntax highlighting suitable for viewing in a web-browser.
+ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP,
+ bool SyntaxHighlight = true,
+ bool HighlightMacros = true);
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h b/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h
new file mode 100644
index 0000000..f32906a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/DeltaTree.h
@@ -0,0 +1,48 @@
+//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- 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 DeltaTree class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_REWRITE_DELTATREE_H
+#define CLANG_REWRITE_DELTATREE_H
+
+namespace clang {
+
+ /// DeltaTree - a multiway search tree (BTree) structure with some fancy
+ /// features. B-Trees are generally more memory and cache efficient than
+ /// binary trees, because they store multiple keys/values in each node. This
+ /// implements a key/value mapping from index to delta, and allows fast lookup
+ /// on index. However, an added (important) bonus is that it can also
+ /// efficiently tell us the full accumulated delta for a specific file offset
+ /// as well, without traversing the whole tree.
+ class DeltaTree {
+ void *Root; // "DeltaTreeNode *"
+ void operator=(const DeltaTree&); // DO NOT IMPLEMENT
+ public:
+ DeltaTree();
+
+ // Note: Currently we only support copying when the RHS is empty.
+ DeltaTree(const DeltaTree &RHS);
+ ~DeltaTree();
+
+ /// getDeltaAt - Return the accumulated delta at the specified file offset.
+ /// This includes all insertions or delections that occurred *before* the
+ /// specified file index.
+ int getDeltaAt(unsigned FileIndex) const;
+
+ /// AddDelta - When a change is made that shifts around the text buffer,
+ /// this method is used to record that info. It inserts a delta of 'Delta'
+ /// into the current DeltaTree at offset FileIndex.
+ void AddDelta(unsigned FileIndex, int Delta);
+ };
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h
new file mode 100644
index 0000000..26a0d72
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/FixItRewriter.h
@@ -0,0 +1,107 @@
+//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a diagnostic client adaptor that performs rewrites as
+// suggested by code modification hints attached to diagnostics. It
+// then forwards any diagnostics to the adapted diagnostic client.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H
+#define LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm { class raw_ostream; }
+
+namespace clang {
+
+class SourceManager;
+class FileEntry;
+
+class FixItOptions {
+public:
+ virtual ~FixItOptions();
+
+ /// \brief This file is about to be rewritten. Return the name of the file
+ /// that is okay to write to.
+ virtual std::string RewriteFilename(const std::string &Filename) = 0;
+
+ /// \brief Whether to abort fixing a file when not all errors could be fixed.
+ bool FixWhatYouCan;
+};
+
+class FixItRewriter : public DiagnosticClient {
+ /// \brief The diagnostics machinery.
+ Diagnostic &Diags;
+
+ /// \brief The rewriter used to perform the various code
+ /// modifications.
+ Rewriter Rewrite;
+
+ /// \brief The diagnostic client that performs the actual formatting
+ /// of error messages.
+ DiagnosticClient *Client;
+
+ /// \brief Turn an input path into an output path. NULL implies overwriting
+ /// the original.
+ FixItOptions *FixItOpts;
+
+ /// \brief The number of rewriter failures.
+ unsigned NumFailures;
+
+public:
+ typedef Rewriter::buffer_iterator iterator;
+
+ /// \brief Initialize a new fix-it rewriter.
+ FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
+ const LangOptions &LangOpts, FixItOptions *FixItOpts);
+
+ /// \brief Destroy the fix-it rewriter.
+ ~FixItRewriter();
+
+ /// \brief Check whether there are modifications for a given file.
+ bool IsModified(FileID ID) const {
+ return Rewrite.getRewriteBufferFor(ID) != NULL;
+ }
+
+ // Iteration over files with changes.
+ iterator buffer_begin() { return Rewrite.buffer_begin(); }
+ iterator buffer_end() { return Rewrite.buffer_end(); }
+
+ /// \brief Write a single modified source file.
+ ///
+ /// \returns true if there was an error, false otherwise.
+ bool WriteFixedFile(FileID ID, llvm::raw_ostream &OS);
+
+ /// \brief Write the modified source files.
+ ///
+ /// \returns true if there was an error, false otherwise.
+ bool WriteFixedFiles();
+
+ /// IncludeInDiagnosticCounts - This method (whose default implementation
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticClient should be included in the number of diagnostics
+ /// reported by Diagnostic.
+ virtual bool IncludeInDiagnosticCounts() const;
+
+ /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+
+ /// \brief Emit a diagnostic via the adapted diagnostic client.
+ void Diag(SourceLocation Loc, unsigned DiagID);
+};
+
+}
+
+#endif // LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h
new file mode 100644
index 0000000..2b5f88c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/FrontendActions.h
@@ -0,0 +1,69 @@
+//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITE_FRONTENDACTIONS_H
+#define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+class FixItRewriter;
+class FixItOptions;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class HTMLPrintAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class FixItAction : public ASTFrontendAction {
+protected:
+ llvm::OwningPtr<FixItRewriter> Rewriter;
+ llvm::OwningPtr<FixItOptions> FixItOpts;
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename);
+
+ virtual void EndSourceFileAction();
+
+ virtual bool hasASTFileSupport() const { return false; }
+
+public:
+ FixItAction();
+ ~FixItAction();
+};
+
+class RewriteObjCAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+class RewriteMacrosAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+class RewriteTestAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h b/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h
new file mode 100644
index 0000000..88caf85
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/HTMLRewrite.h
@@ -0,0 +1,81 @@
+//==- HTMLRewrite.h - Translate source code into prettified HTML ---*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of functions used for translating source code
+// into beautified HTML.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_HTMLREWRITER_H
+#define LLVM_CLANG_HTMLREWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include <string>
+
+namespace clang {
+
+class Rewriter;
+class RewriteBuffer;
+class Preprocessor;
+
+namespace html {
+
+ /// HighlightRange - Highlight a range in the source code with the specified
+ /// start/end tags. B/E must be in the same file. This ensures that
+ /// start/end tags are placed at the start/end of each line if the range is
+ /// multiline.
+ void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
+ const char *StartTag, const char *EndTag);
+
+ /// HighlightRange - Highlight a range in the source code with the specified
+ /// start/end tags. The Start/end of the range must be in the same file.
+ /// This ensures that start/end tags are placed at the start/end of each line
+ /// if the range is multiline.
+ inline void HighlightRange(Rewriter &R, SourceRange Range,
+ const char *StartTag, const char *EndTag) {
+ HighlightRange(R, Range.getBegin(), Range.getEnd(), StartTag, EndTag);
+ }
+
+ /// HighlightRange - This is the same as the above method, but takes
+ /// decomposed file locations.
+ void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E,
+ const char *BufferStart,
+ const char *StartTag, const char *EndTag);
+
+ /// EscapeText - HTMLize a specified file so that special characters are
+ /// are translated so that they are not interpreted as HTML tags.
+ void EscapeText(Rewriter& R, FileID FID,
+ bool EscapeSpaces = false, bool ReplaceTabs = false);
+
+ /// EscapeText - HTMLized the provided string so that special characters
+ /// in 's' are not interpreted as HTML tags. Unlike the version of
+ /// EscapeText that rewrites a file, this version by default replaces tabs
+ /// with spaces.
+ std::string EscapeText(const std::string& s,
+ bool EscapeSpaces = false, bool ReplaceTabs = false);
+
+ void AddLineNumbers(Rewriter& R, FileID FID);
+
+ void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
+ const char *title = NULL);
+
+ /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
+ /// information about keywords, comments, etc.
+ void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP);
+
+ /// HighlightMacros - This uses the macro table state from the end of the
+ /// file, to reexpand macros and insert (into the HTML) information about the
+ /// macro expansions. This won't be perfectly perfect, but it will be
+ /// reasonably close.
+ void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP);
+
+} // end html namespace
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h b/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h
new file mode 100644
index 0000000..cb3f8a8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/RewriteRope.h
@@ -0,0 +1,231 @@
+//===--- RewriteRope.h - Rope specialized for rewriter ----------*- 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 RewriteRope class, which is a powerful string class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITEROPE_H
+#define LLVM_CLANG_REWRITEROPE_H
+
+#include <cstring>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+namespace clang {
+ //===--------------------------------------------------------------------===//
+ // RopeRefCountString Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopeRefCountString - This struct is allocated with 'new char[]' from the
+ /// heap, and represents a reference counted chunk of string data. When its
+ /// ref count drops to zero, it is delete[]'d. This is primarily managed
+ /// through the RopePiece class below.
+ struct RopeRefCountString {
+ unsigned RefCount;
+ char Data[1]; // Variable sized.
+
+ void addRef() {
+ if (this) ++RefCount;
+ }
+
+ void dropRef() {
+ if (this && --RefCount == 0)
+ delete [] (char*)this;
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePiece Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopePiece - This class represents a view into a RopeRefCountString object.
+ /// This allows references to string data to be efficiently chopped up and
+ /// moved around without having to push around the string data itself.
+ ///
+ /// For example, we could have a 1M RopePiece and want to insert something
+ /// into the middle of it. To do this, we split it into two RopePiece objects
+ /// that both refer to the same underlying RopeRefCountString (just with
+ /// different offsets) which is a nice constant time operation.
+ struct RopePiece {
+ RopeRefCountString *StrData;
+ unsigned StartOffs;
+ unsigned EndOffs;
+
+ RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {}
+
+ RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
+ : StrData(Str), StartOffs(Start), EndOffs(End) {
+ StrData->addRef();
+ }
+ RopePiece(const RopePiece &RP)
+ : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
+ StrData->addRef();
+ }
+
+ ~RopePiece() {
+ StrData->dropRef();
+ }
+
+ void operator=(const RopePiece &RHS) {
+ if (StrData != RHS.StrData) {
+ StrData->dropRef();
+ StrData = RHS.StrData;
+ StrData->addRef();
+ }
+ StartOffs = RHS.StartOffs;
+ EndOffs = RHS.EndOffs;
+ }
+
+ const char &operator[](unsigned Offset) const {
+ return StrData->Data[Offset+StartOffs];
+ }
+ char &operator[](unsigned Offset) {
+ return StrData->Data[Offset+StartOffs];
+ }
+
+ unsigned size() const { return EndOffs-StartOffs; }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePieceBTreeIterator Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopePieceBTreeIterator - This class provides read-only forward iteration
+ /// over bytes that are in a RopePieceBTree. This first iterates over bytes
+ /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf,
+ /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree.
+ class RopePieceBTreeIterator :
+ public std::iterator<std::forward_iterator_tag, const char, ptrdiff_t> {
+ /// CurNode - The current B+Tree node that we are inspecting.
+ const void /*RopePieceBTreeLeaf*/ *CurNode;
+ /// CurPiece - The current RopePiece in the B+Tree node that we're
+ /// inspecting.
+ const RopePiece *CurPiece;
+ /// CurChar - The current byte in the RopePiece we are pointing to.
+ unsigned CurChar;
+ public:
+ // begin iterator.
+ RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N);
+ // end iterator
+ RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {}
+
+ char operator*() const {
+ return (*CurPiece)[CurChar];
+ }
+
+ bool operator==(const RopePieceBTreeIterator &RHS) const {
+ return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar;
+ }
+ bool operator!=(const RopePieceBTreeIterator &RHS) const {
+ return !operator==(RHS);
+ }
+
+ RopePieceBTreeIterator& operator++() { // Preincrement
+ if (CurChar+1 < CurPiece->size())
+ ++CurChar;
+ else
+ MoveToNextPiece();
+ return *this;
+ }
+ inline RopePieceBTreeIterator operator++(int) { // Postincrement
+ RopePieceBTreeIterator tmp = *this; ++*this; return tmp;
+ }
+ private:
+ void MoveToNextPiece();
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePieceBTree Class
+ //===--------------------------------------------------------------------===//
+
+ class RopePieceBTree {
+ void /*RopePieceBTreeNode*/ *Root;
+ void operator=(const RopePieceBTree &); // DO NOT IMPLEMENT
+ public:
+ RopePieceBTree();
+ RopePieceBTree(const RopePieceBTree &RHS);
+ ~RopePieceBTree();
+
+ typedef RopePieceBTreeIterator iterator;
+ iterator begin() const { return iterator(Root); }
+ iterator end() const { return iterator(); }
+ unsigned size() const;
+ unsigned empty() const { return size() == 0; }
+
+ void clear();
+
+ void insert(unsigned Offset, const RopePiece &R);
+
+ void erase(unsigned Offset, unsigned NumBytes);
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RewriteRope Class
+ //===--------------------------------------------------------------------===//
+
+/// RewriteRope - A powerful string class. This class supports extremely
+/// efficient insertions and deletions into the middle of it, even for
+/// ridiculously long strings.
+class RewriteRope {
+ RopePieceBTree Chunks;
+
+ /// We allocate space for string data out of a buffer of size AllocChunkSize.
+ /// This keeps track of how much space is left.
+ RopeRefCountString *AllocBuffer;
+ unsigned AllocOffs;
+ enum { AllocChunkSize = 4080 };
+
+public:
+ RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {}
+ RewriteRope(const RewriteRope &RHS)
+ : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) {
+ }
+
+ ~RewriteRope() {
+ // If we had an allocation buffer, drop our reference to it.
+ AllocBuffer->dropRef();
+ }
+
+ typedef RopePieceBTree::iterator iterator;
+ typedef RopePieceBTree::iterator const_iterator;
+ iterator begin() const { return Chunks.begin(); }
+ iterator end() const { return Chunks.end(); }
+ unsigned size() const { return Chunks.size(); }
+
+ void clear() {
+ Chunks.clear();
+ }
+
+ void assign(const char *Start, const char *End) {
+ clear();
+ if (Start != End)
+ Chunks.insert(0, MakeRopeString(Start, End));
+ }
+
+ void insert(unsigned Offset, const char *Start, const char *End) {
+ assert(Offset <= size() && "Invalid position to insert!");
+ if (Start == End) return;
+ Chunks.insert(Offset, MakeRopeString(Start, End));
+ }
+
+ void erase(unsigned Offset, unsigned NumBytes) {
+ assert(Offset+NumBytes <= size() && "Invalid region to erase!");
+ if (NumBytes == 0) return;
+ Chunks.erase(Offset, NumBytes);
+ }
+
+private:
+ RopePiece MakeRopeString(const char *Start, const char *End);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h
new file mode 100644
index 0000000..b3d4035
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriter.h
@@ -0,0 +1,226 @@
+//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Rewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITER_H
+#define LLVM_CLANG_REWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Rewrite/DeltaTree.h"
+#include "clang/Rewrite/RewriteRope.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstring>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm { class raw_ostream; }
+
+namespace clang {
+ class LangOptions;
+ class Rewriter;
+ class SourceManager;
+ class Stmt;
+
+/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
+/// input with modifications get a new RewriteBuffer associated with them. The
+/// RewriteBuffer captures the modified text itself as well as information used
+/// to map between SourceLocation's in the original input and offsets in the
+/// RewriteBuffer. For example, if text is inserted into the buffer, any
+/// locations after the insertion point have to be mapped.
+class RewriteBuffer {
+ friend class Rewriter;
+ /// Deltas - Keep track of all the deltas in the source code due to insertions
+ /// and deletions.
+ DeltaTree Deltas;
+
+ /// Buffer - This is the actual buffer itself. Note that using a vector or
+ /// string is a horribly inefficient way to do this, we should use a rope
+ /// instead.
+ typedef RewriteRope BufferTy;
+ BufferTy Buffer;
+public:
+ typedef BufferTy::const_iterator iterator;
+ iterator begin() const { return Buffer.begin(); }
+ iterator end() const { return Buffer.end(); }
+ unsigned size() const { return Buffer.size(); }
+
+ llvm::raw_ostream &write(llvm::raw_ostream &) const;
+
+ /// RemoveText - Remove the specified text.
+ void RemoveText(unsigned OrigOffset, unsigned Size);
+
+ /// InsertText - Insert some text at the specified point, where the offset in
+ /// the buffer is specified relative to the original SourceBuffer. The
+ /// text is inserted after the specified location.
+ ///
+ void InsertText(unsigned OrigOffset, llvm::StringRef Str,
+ bool InsertAfter = true);
+
+
+ /// InsertTextBefore - Insert some text before the specified point, where the
+ /// offset in the buffer is specified relative to the original
+ /// SourceBuffer. The text is inserted before the specified location. This is
+ /// method is the same as InsertText with "InsertAfter == false".
+ void InsertTextBefore(unsigned OrigOffset, llvm::StringRef Str) {
+ InsertText(OrigOffset, Str, false);
+ }
+
+ /// InsertTextAfter - Insert some text at the specified point, where the
+ /// offset in the buffer is specified relative to the original SourceBuffer.
+ /// The text is inserted after the specified location.
+ void InsertTextAfter(unsigned OrigOffset, llvm::StringRef Str) {
+ InsertText(OrigOffset, Str);
+ }
+
+ /// ReplaceText - This method replaces a range of characters in the input
+ /// buffer with a new string. This is effectively a combined "remove/insert"
+ /// operation.
+ void ReplaceText(unsigned OrigOffset, unsigned OrigLength,
+ llvm::StringRef NewStr);
+
+private: // Methods only usable by Rewriter.
+
+ /// Initialize - Start this rewrite buffer out with a copy of the unmodified
+ /// input buffer.
+ void Initialize(const char *BufStart, const char *BufEnd) {
+ Buffer.assign(BufStart, BufEnd);
+ }
+
+ /// getMappedOffset - Given an offset into the original SourceBuffer that this
+ /// RewriteBuffer is based on, map it into the offset space of the
+ /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a
+ /// position where text is inserted, the location returned will be after any
+ /// inserted text at the position.
+ unsigned getMappedOffset(unsigned OrigOffset,
+ bool AfterInserts = false) const{
+ return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset;
+ }
+
+ /// AddInsertDelta - When an insertion is made at a position, this
+ /// method is used to record that information.
+ void AddInsertDelta(unsigned OrigOffset, int Change) {
+ return Deltas.AddDelta(2*OrigOffset, Change);
+ }
+
+ /// AddReplaceDelta - When a replacement/deletion is made at a position, this
+ /// method is used to record that information.
+ void AddReplaceDelta(unsigned OrigOffset, int Change) {
+ return Deltas.AddDelta(2*OrigOffset+1, Change);
+ }
+};
+
+
+/// Rewriter - This is the main interface to the rewrite buffers. Its primary
+/// job is to dispatch high-level requests to the low-level RewriteBuffers that
+/// are involved.
+class Rewriter {
+ SourceManager *SourceMgr;
+ const LangOptions *LangOpts;
+ std::map<FileID, RewriteBuffer> RewriteBuffers;
+public:
+ typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
+
+ explicit Rewriter(SourceManager &SM, const LangOptions &LO)
+ : SourceMgr(&SM), LangOpts(&LO) {}
+ explicit Rewriter() : SourceMgr(0), LangOpts(0) {}
+
+ void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
+ SourceMgr = &SM;
+ LangOpts = &LO;
+ }
+ SourceManager &getSourceMgr() { return *SourceMgr; }
+ const LangOptions &getLangOpts() { return *LangOpts; }
+
+ /// isRewritable - Return true if this location is a raw file location, which
+ /// is rewritable. Locations from macros, etc are not rewritable.
+ static bool isRewritable(SourceLocation Loc) {
+ return Loc.isFileID();
+ }
+
+ /// getRangeSize - Return the size in bytes of the specified range if they
+ /// are in the same file. If not, this returns -1.
+ int getRangeSize(SourceRange Range) const;
+ int getRangeSize(const CharSourceRange &Range) const;
+
+ /// getRewrittenText - Return the rewritten form of the text in the specified
+ /// range. If the start or end of the range was unrewritable or if they are
+ /// in different buffers, this returns an empty string.
+ ///
+ /// Note that this method is not particularly efficient.
+ ///
+ std::string getRewrittenText(SourceRange Range) const;
+
+ /// InsertText - Insert the specified string at the specified location in the
+ /// original buffer. This method returns true (and does nothing) if the input
+ /// location was not rewritable, false otherwise.
+ bool InsertText(SourceLocation Loc, llvm::StringRef Str,
+ bool InsertAfter = true);
+
+ /// InsertTextAfter - Insert the specified string at the specified location in
+ /// the original buffer. This method returns true (and does nothing) if
+ /// the input location was not rewritable, false otherwise. Text is
+ /// inserted after any other text that has been previously inserted
+ /// at the some point (the default behavior for InsertText).
+ bool InsertTextAfter(SourceLocation Loc, llvm::StringRef Str) {
+ return InsertText(Loc, Str);
+ }
+
+ /// InsertText - Insert the specified string at the specified location in the
+ /// original buffer. This method returns true (and does nothing) if the input
+ /// location was not rewritable, false otherwise. Text is
+ /// inserted before any other text that has been previously inserted
+ /// at the some point.
+ bool InsertTextBefore(SourceLocation Loc, llvm::StringRef Str) {
+ return InsertText(Loc, Str, false);
+ }
+
+ /// RemoveText - Remove the specified text region.
+ bool RemoveText(SourceLocation Start, unsigned Length);
+
+ /// ReplaceText - This method replaces a range of characters in the input
+ /// buffer with a new string. This is effectively a combined "remove/insert"
+ /// operation.
+ bool ReplaceText(SourceLocation Start, unsigned OrigLength,
+ llvm::StringRef NewStr);
+
+ /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
+ /// printer to generate the replacement code. This returns true if the input
+ /// could not be rewritten, or false if successful.
+ bool ReplaceStmt(Stmt *From, Stmt *To);
+
+ /// getEditBuffer - This is like getRewriteBufferFor, but always returns a
+ /// buffer, and allows you to write on it directly. This is useful if you
+ /// want efficient low-level access to apis for scribbling on one specific
+ /// FileID's buffer.
+ RewriteBuffer &getEditBuffer(FileID FID);
+
+ /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
+ /// If no modification has been made to it, return null.
+ const RewriteBuffer *getRewriteBufferFor(FileID FID) const {
+ std::map<FileID, RewriteBuffer>::const_iterator I =
+ RewriteBuffers.find(FID);
+ return I == RewriteBuffers.end() ? 0 : &I->second;
+ }
+
+ // Iterators over rewrite buffers.
+ buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
+ buffer_iterator buffer_end() { return RewriteBuffers.end(); }
+
+private:
+ unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriters.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriters.h
new file mode 100644
index 0000000..669cf8c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Rewriters.h
@@ -0,0 +1,31 @@
+//===--- Rewriters.h - Rewriter implementations -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITE_REWRITERS_H
+#define LLVM_CLANG_REWRITE_REWRITERS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+class Preprocessor;
+
+/// RewriteMacrosInInput - Implement -rewrite-macros mode.
+void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS);
+
+/// DoRewriteTest - A simple test for the TokenRewriter class.
+void DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS);
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h
new file mode 100644
index 0000000..62ea12a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/TokenRewriter.h
@@ -0,0 +1,79 @@
+//===--- TokenRewriter.h - Token-based Rewriter -----------------*- 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 TokenRewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENREWRITER_H
+#define LLVM_CLANG_TOKENREWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <list>
+#include <map>
+
+namespace clang {
+ class Token;
+ class LangOptions;
+ class ScratchBuffer;
+
+ class TokenRewriter {
+ /// TokenList - This is the list of raw tokens that make up this file. Each
+ /// of these tokens has a unique SourceLocation, which is a FileID.
+ std::list<Token> TokenList;
+
+ /// TokenRefTy - This is the type used to refer to a token in the TokenList.
+ typedef std::list<Token>::iterator TokenRefTy;
+
+ /// TokenAtLoc - This map indicates which token exists at a specific
+ /// SourceLocation. Since each token has a unique SourceLocation, this is a
+ /// one to one map. The token can return its own location directly, to map
+ /// backwards.
+ std::map<SourceLocation, TokenRefTy> TokenAtLoc;
+
+ /// ScratchBuf - This is the buffer that we create scratch tokens from.
+ ///
+ llvm::OwningPtr<ScratchBuffer> ScratchBuf;
+
+ TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT
+ void operator=(const TokenRewriter&); // DO NOT IMPLEMENT.
+ public:
+ /// TokenRewriter - This creates a TokenRewriter for the file with the
+ /// specified FileID.
+ TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO);
+ ~TokenRewriter();
+
+ typedef std::list<Token>::const_iterator token_iterator;
+ token_iterator token_begin() const { return TokenList.begin(); }
+ token_iterator token_end() const { return TokenList.end(); }
+
+
+ token_iterator AddTokenBefore(token_iterator I, const char *Val);
+ token_iterator AddTokenAfter(token_iterator I, const char *Val) {
+ assert(I != token_end() && "Cannot insert after token_end()!");
+ return AddTokenBefore(++I, Val);
+ }
+
+ private:
+ /// RemapIterator - Convert from token_iterator (a const iterator) to
+ /// TokenRefTy (a non-const iterator).
+ TokenRefTy RemapIterator(token_iterator I);
+
+ /// AddToken - Add the specified token into the Rewriter before the other
+ /// position.
+ TokenRefTy AddToken(const Token &T, TokenRefTy Where);
+ };
+
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
new file mode 100644
index 0000000..0a6656e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -0,0 +1,64 @@
+//=- AnalysisBasedWarnings.h - Sema warnings based on libAnalysis -*- 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 AnalysisBasedWarnings, a worker object used by Sema
+// that issues warnings based on dataflow-analysis.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H
+#define LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class BlockExpr;
+class Decl;
+class FunctionDecl;
+class ObjCMethodDecl;
+class QualType;
+class Sema;
+
+namespace sema {
+
+class AnalysisBasedWarnings {
+public:
+ class Policy {
+ friend class AnalysisBasedWarnings;
+ // The warnings to run.
+ unsigned enableCheckFallThrough : 1;
+ unsigned enableCheckUnreachable : 1;
+ public:
+ Policy();
+ void disableCheckFallThrough() { enableCheckFallThrough = 0; }
+ };
+
+private:
+ Sema &S;
+ Policy DefaultPolicy;
+
+ enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
+ llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
+
+ void IssueWarnings(Policy P, const Decl *D, QualType BlockTy);
+
+public:
+ AnalysisBasedWarnings(Sema &s);
+
+ Policy getDefaultPolicy() { return DefaultPolicy; }
+
+ void IssueWarnings(Policy P, const BlockExpr *E);
+ void IssueWarnings(Policy P, const FunctionDecl *D);
+ void IssueWarnings(Policy P, const ObjCMethodDecl *D);
+};
+
+}} // end namespace clang::sema
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
new file mode 100644
index 0000000..45ee579
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
@@ -0,0 +1,320 @@
+//===--- AttributeList.h - Parsed attribute sets ----------------*- 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 AttributeList class, which is used to collect
+// parsed attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_ATTRLIST_H
+#define LLVM_CLANG_SEMA_ATTRLIST_H
+
+#include "llvm/Support/Allocator.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cassert>
+
+namespace clang {
+ class IdentifierInfo;
+ class Expr;
+
+/// AttributeList - Represents GCC's __attribute__ declaration. There are
+/// 4 forms of this construct...they are:
+///
+/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
+/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
+/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
+/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
+///
+class AttributeList {
+public:
+ class Factory;
+private:
+ IdentifierInfo *AttrName;
+ SourceLocation AttrLoc;
+ IdentifierInfo *ScopeName;
+ SourceLocation ScopeLoc;
+ IdentifierInfo *ParmName;
+ SourceLocation ParmLoc;
+ Expr **Args;
+ unsigned NumArgs;
+ AttributeList *Next;
+ bool DeclspecAttribute, CXX0XAttribute;
+
+ /// True if already diagnosed as invalid.
+ mutable bool Invalid;
+
+ AttributeList(const AttributeList &); // DO NOT IMPLEMENT
+ void operator=(const AttributeList &); // DO NOT IMPLEMENT
+ void operator delete(void *); // DO NOT IMPLEMENT
+ ~AttributeList(); // DO NOT IMPLEMENT
+ AttributeList(llvm::BumpPtrAllocator &Alloc,
+ IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ IdentifierInfo *ParmName, SourceLocation ParmLoc,
+ Expr **args, unsigned numargs,
+ bool declspec, bool cxx0x);
+public:
+ class Factory {
+ llvm::BumpPtrAllocator Alloc;
+ public:
+ Factory() {}
+ ~Factory() {}
+ AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ IdentifierInfo *ParmName, SourceLocation ParmLoc,
+ Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) {
+ AttributeList *Mem = Alloc.Allocate<AttributeList>();
+ new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
+ ParmName, ParmLoc, args, numargs,
+ declspec, cxx0x);
+ return Mem;
+ }
+ };
+
+ enum Kind { // Please keep this list alphabetized.
+ AT_IBAction, // Clang-specific.
+ AT_IBOutlet, // Clang-specific.
+ AT_IBOutletCollection, // Clang-specific.
+ AT_address_space,
+ AT_alias,
+ AT_aligned,
+ AT_always_inline,
+ AT_analyzer_noreturn,
+ AT_annotate,
+ AT_base_check,
+ AT_blocks,
+ AT_carries_dependency,
+ AT_cdecl,
+ AT_cleanup,
+ AT_common,
+ AT_const,
+ AT_constant,
+ AT_constructor,
+ AT_deprecated,
+ AT_destructor,
+ AT_device,
+ AT_dllexport,
+ AT_dllimport,
+ AT_ext_vector_type,
+ AT_fastcall,
+ AT_format,
+ AT_format_arg,
+ AT_global,
+ AT_gnu_inline,
+ AT_host,
+ AT_launch_bounds,
+ AT_malloc,
+ AT_may_alias,
+ AT_mode,
+ AT_neon_polyvector_type, // Clang-specific.
+ AT_neon_vector_type, // Clang-specific.
+ AT_naked,
+ AT_nodebug,
+ AT_noinline,
+ AT_no_instrument_function,
+ AT_nocommon,
+ AT_nonnull,
+ AT_noreturn,
+ AT_nothrow,
+ AT_nsobject,
+ AT_objc_exception,
+ AT_cf_returns_not_retained, // Clang-specific.
+ AT_cf_returns_retained, // Clang-specific.
+ AT_ns_returns_not_retained, // Clang-specific.
+ AT_ns_returns_retained, // Clang-specific.
+ AT_ns_returns_autoreleased, // Clang-specific.
+ AT_cf_consumed, // Clang-specific.
+ AT_ns_consumed, // Clang-specific.
+ AT_ns_consumes_self, // Clang-specific.
+ AT_objc_gc,
+ AT_opencl_kernel_function, // OpenCL-specific.
+ AT_overloadable, // Clang-specific.
+ AT_ownership_holds, // Clang-specific.
+ AT_ownership_returns, // Clang-specific.
+ AT_ownership_takes, // Clang-specific.
+ AT_packed,
+ AT_pascal,
+ AT_pure,
+ AT_regparm,
+ AT_section,
+ AT_sentinel,
+ AT_shared,
+ AT_stdcall,
+ AT_thiscall,
+ AT_transparent_union,
+ AT_unavailable,
+ AT_unused,
+ AT_used,
+ AT_uuid,
+ AT_vecreturn, // PS3 PPU-specific.
+ AT_vector_size,
+ AT_visibility,
+ AT_warn_unused_result,
+ AT_weak,
+ AT_weakref,
+ AT_weak_import,
+ AT_reqd_wg_size,
+ AT_init_priority,
+ IgnoredAttribute,
+ UnknownAttribute
+ };
+
+ IdentifierInfo *getName() const { return AttrName; }
+ SourceLocation getLoc() const { return AttrLoc; }
+
+ bool hasScope() const { return ScopeName; }
+ IdentifierInfo *getScopeName() const { return ScopeName; }
+ SourceLocation getScopeLoc() const { return ScopeLoc; }
+
+ IdentifierInfo *getParameterName() const { return ParmName; }
+ SourceLocation getParameterLoc() const { return ParmLoc; }
+
+ bool isDeclspecAttribute() const { return DeclspecAttribute; }
+ bool isCXX0XAttribute() const { return CXX0XAttribute; }
+
+ bool isInvalid() const { return Invalid; }
+ void setInvalid(bool b = true) const { Invalid = b; }
+
+ Kind getKind() const { return getKind(getName()); }
+ static Kind getKind(const IdentifierInfo *Name);
+
+ AttributeList *getNext() const { return Next; }
+ void setNext(AttributeList *N) { Next = N; }
+
+ /// getNumArgs - Return the number of actual arguments to this attribute.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return Args[Arg];
+ }
+
+ class arg_iterator {
+ Expr** X;
+ unsigned Idx;
+ public:
+ arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {}
+
+ arg_iterator& operator++() {
+ ++Idx;
+ return *this;
+ }
+
+ bool operator==(const arg_iterator& I) const {
+ assert (X == I.X &&
+ "compared arg_iterators are for different argument lists");
+ return Idx == I.Idx;
+ }
+
+ bool operator!=(const arg_iterator& I) const {
+ return !operator==(I);
+ }
+
+ Expr* operator*() const {
+ return X[Idx];
+ }
+
+ unsigned getArgNum() const {
+ return Idx+1;
+ }
+ };
+
+ arg_iterator arg_begin() const {
+ return arg_iterator(Args, 0);
+ }
+
+ arg_iterator arg_end() const {
+ return arg_iterator(Args, NumArgs);
+ }
+};
+
+/// addAttributeLists - Add two AttributeLists together
+/// The right-hand list is appended to the left-hand list, if any
+/// A pointer to the joined list is returned.
+/// Note: the lists are not left unmodified.
+inline AttributeList *addAttributeLists(AttributeList *Left,
+ AttributeList *Right) {
+ if (!Left)
+ return Right;
+
+ AttributeList *next = Left, *prev;
+ do {
+ prev = next;
+ next = next->getNext();
+ } while (next);
+ prev->setNext(Right);
+ return Left;
+}
+
+/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
+/// Stores, in addition to the list proper, whether or not an actual list was
+/// (as opposed to an empty list, which may be ill-formed in some places) and
+/// the source range of the list.
+struct CXX0XAttributeList {
+ AttributeList *AttrList;
+ SourceRange Range;
+ bool HasAttr;
+ CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
+ : AttrList(attrList), Range(range), HasAttr (hasAttr) {
+ }
+ CXX0XAttributeList ()
+ : AttrList(0), Range(), HasAttr(false) {
+ }
+};
+
+/// ParsedAttributes - A collection of parsed attributes. Currently
+/// we don't differentiate between the various attribute syntaxes,
+/// which is basically silly.
+///
+/// Right now this is a very lightweight container, but the expectation
+/// is that this will become significantly more serious.
+class ParsedAttributes {
+public:
+ ParsedAttributes() : list(0) {}
+
+ bool empty() const { return list == 0; }
+
+ void add(AttributeList *newAttr) {
+ assert(newAttr);
+ assert(newAttr->getNext() == 0);
+ newAttr->setNext(list);
+ list = newAttr;
+ }
+
+ void append(AttributeList *newList) {
+ if (!newList) return;
+
+ AttributeList *lastInNewList = newList;
+ while (AttributeList *next = lastInNewList->getNext())
+ lastInNewList = next;
+
+ lastInNewList->setNext(list);
+ list = newList;
+ }
+
+ void set(AttributeList *newList) {
+ list = newList;
+ }
+
+ void clear() { list = 0; }
+ AttributeList *getList() const { return list; }
+
+ /// Returns a reference to the attribute list. Try not to introduce
+ /// dependencies on this method, it may not be long-lived.
+ AttributeList *&getListRef() { return list; }
+
+private:
+ AttributeList *list;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h b/contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h
new file mode 100644
index 0000000..63c6ee3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h
@@ -0,0 +1,79 @@
+//===- CXXFieldCollector.h - Utility class for C++ class semantic analysis ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides CXXFieldCollector that is used during parsing & semantic
+// analysis of C++ classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+#define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class FieldDecl;
+
+/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
+/// C++ classes.
+class CXXFieldCollector {
+ /// Fields - Contains all FieldDecls collected during parsing of a C++
+ /// class. When a nested class is entered, its fields are appended to the
+ /// fields of its parent class, when it is exited its fields are removed.
+ llvm::SmallVector<FieldDecl*, 32> Fields;
+
+ /// FieldCount - Each entry represents the number of fields collected during
+ /// the parsing of a C++ class. When a nested class is entered, a new field
+ /// count is pushed, when it is exited, the field count is popped.
+ llvm::SmallVector<size_t, 4> FieldCount;
+
+ // Example:
+ //
+ // class C {
+ // int x,y;
+ // class NC {
+ // int q;
+ // // At this point, Fields contains [x,y,q] decls and FieldCount contains
+ // // [2,1].
+ // };
+ // int z;
+ // // At this point, Fields contains [x,y,z] decls and FieldCount contains
+ // // [3].
+ // };
+
+public:
+ /// StartClass - Called by Sema::ActOnStartCXXClassDef.
+ void StartClass() { FieldCount.push_back(0); }
+
+ /// Add - Called by Sema::ActOnCXXMemberDeclarator.
+ void Add(FieldDecl *D) {
+ Fields.push_back(D);
+ ++FieldCount.back();
+ }
+
+ /// getCurNumField - The number of fields added to the currently parsed class.
+ size_t getCurNumFields() const {
+ assert(!FieldCount.empty() && "no currently-parsed class");
+ return FieldCount.back();
+ }
+
+ /// getCurFields - Pointer to array of fields added to the currently parsed
+ /// class.
+ FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+
+ /// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
+ void FinishClass() {
+ Fields.resize(Fields.size() - getCurNumFields());
+ FieldCount.pop_back();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
new file mode 100644
index 0000000..882440b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -0,0 +1,854 @@
+//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeCompleteConsumer class.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "clang-c/Index.h"
+#include <string>
+
+namespace llvm {
+ class raw_ostream;
+ class Twine;
+}
+
+namespace clang {
+
+class Decl;
+
+/// \brief Default priority values for code-completion results based
+/// on their kind.
+enum {
+ /// \brief Priority for the next initialization in a constructor initializer
+ /// list.
+ CCP_NextInitializer = 7,
+ /// \brief Priority for an enumeration constant inside a switch whose
+ /// condition is of the enumeration type.
+ CCP_EnumInCase = 7,
+ /// \brief Priority for a send-to-super completion.
+ CCP_SuperCompletion = 20,
+ /// \brief Priority for a declaration that is in the local scope.
+ CCP_LocalDeclaration = 34,
+ /// \brief Priority for a member declaration found from the current
+ /// method or member function.
+ CCP_MemberDeclaration = 35,
+ /// \brief Priority for a language keyword (that isn't any of the other
+ /// categories).
+ CCP_Keyword = 40,
+ /// \brief Priority for a code pattern.
+ CCP_CodePattern = 40,
+ /// \brief Priority for a non-type declaration.
+ CCP_Declaration = 50,
+ /// \brief Priority for a type.
+ CCP_Type = CCP_Declaration,
+ /// \brief Priority for a constant value (e.g., enumerator).
+ CCP_Constant = 65,
+ /// \brief Priority for a preprocessor macro.
+ CCP_Macro = 70,
+ /// \brief Priority for a nested-name-specifier.
+ CCP_NestedNameSpecifier = 75,
+ /// \brief Priority for a result that isn't likely to be what the user wants,
+ /// but is included for completeness.
+ CCP_Unlikely = 80,
+
+ /// \brief Priority for the Objective-C "_cmd" implicit parameter.
+ CCP_ObjC_cmd = CCP_Unlikely
+};
+
+/// \brief Priority value deltas that are added to code-completion results
+/// based on the context of the result.
+enum {
+ /// \brief The result is in a base class.
+ CCD_InBaseClass = 2,
+ /// \brief The result is a C++ non-static member function whose qualifiers
+ /// exactly match the object type on which the member function can be called.
+ CCD_ObjectQualifierMatch = -1,
+ /// \brief The selector of the given message exactly matches the selector
+ /// of the current method, which might imply that some kind of delegation
+ /// is occurring.
+ CCD_SelectorMatch = -3,
+
+ /// \brief Adjustment to the "bool" type in Objective-C, where the typedef
+ /// "BOOL" is preferred.
+ CCD_bool_in_ObjC = 1,
+
+ /// \brief Adjustment for KVC code pattern priorities when it doesn't look
+ /// like the
+ CCD_ProbablyNotObjCCollection = 15
+};
+
+/// \brief Priority value factors by which we will divide or multiply the
+/// priority of a code-completion result.
+enum {
+ /// \brief Divide by this factor when a code-completion result's type exactly
+ /// matches the type we expect.
+ CCF_ExactTypeMatch = 4,
+ /// \brief Divide by this factor when a code-completion result's type is
+ /// similar to the type we expect (e.g., both arithmetic types, both
+ /// Objective-C object pointer types).
+ CCF_SimilarTypeMatch = 2
+};
+
+/// \brief A simplified classification of types used when determining
+/// "similar" types for code completion.
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// \brief Determine the simplified type class of the given canonical type.
+SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
+
+/// \brief Determine the type that this declaration will have if it is used
+/// as a type or in an expression.
+QualType getDeclUsageType(ASTContext &C, NamedDecl *ND);
+
+/// \brief Determine the priority to be given to a macro code completion result
+/// with the given name.
+///
+/// \param MacroName The name of the macro.
+///
+/// \param LangOpts Options describing the current language dialect.
+///
+/// \param PreferredTypeIsPointer Whether the preferred type for the context
+/// of this macro is a pointer type.
+unsigned getMacroUsagePriority(llvm::StringRef MacroName,
+ const LangOptions &LangOpts,
+ bool PreferredTypeIsPointer = false);
+
+/// \brief Determine the libclang cursor kind associated with the given
+/// declaration.
+CXCursorKind getCursorKindForDecl(Decl *D);
+
+class FunctionDecl;
+class FunctionType;
+class FunctionTemplateDecl;
+class IdentifierInfo;
+class NamedDecl;
+class NestedNameSpecifier;
+class Sema;
+
+/// \brief The context in which code completion occurred, so that the
+/// code-completion consumer can process the results accordingly.
+class CodeCompletionContext {
+public:
+ enum Kind {
+ /// \brief An unspecified code-completion context.
+ CCC_Other,
+ /// \brief An unspecified code-completion context where we should also add
+ /// macro completions.
+ CCC_OtherWithMacros,
+ /// \brief Code completion occurred within a "top-level" completion context,
+ /// e.g., at namespace or global scope.
+ CCC_TopLevel,
+ /// \brief Code completion occurred within an Objective-C interface,
+ /// protocol, or category interface.
+ CCC_ObjCInterface,
+ /// \brief Code completion occurred within an Objective-C implementation
+ /// or category implementation.
+ CCC_ObjCImplementation,
+ /// \brief Code completion occurred within the instance variable list of
+ /// an Objective-C interface, implementation, or category implementation.
+ CCC_ObjCIvarList,
+ /// \brief Code completion occurred within a class, struct, or union.
+ CCC_ClassStructUnion,
+ /// \brief Code completion occurred where a statement (or declaration) is
+ /// expected in a function, method, or block.
+ CCC_Statement,
+ /// \brief Code completion occurred where an expression is expected.
+ CCC_Expression,
+ /// \brief Code completion occurred where an Objective-C message receiver
+ /// is expected.
+ CCC_ObjCMessageReceiver,
+ /// \brief Code completion occurred on the right-hand side of a member
+ /// access expression.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_MemberAccess,
+ /// \brief Code completion occurred after the "enum" keyword, to indicate
+ /// an enumeration name.
+ CCC_EnumTag,
+ /// \brief Code completion occurred after the "union" keyword, to indicate
+ /// a union name.
+ CCC_UnionTag,
+ /// \brief Code completion occurred after the "struct" or "class" keyword,
+ /// to indicate a struct or class name.
+ CCC_ClassOrStructTag,
+ /// \brief Code completion occurred where a protocol name is expected.
+ CCC_ObjCProtocolName,
+ /// \brief Code completion occurred where a namespace or namespace alias
+ /// is expected.
+ CCC_Namespace,
+ /// \brief Code completion occurred where a type name is expected.
+ CCC_Type,
+ /// \brief Code completion occurred where a new name is expected.
+ CCC_Name,
+ /// \brief Code completion occurred where a new name is expected and a
+ /// qualified name is permissible.
+ CCC_PotentiallyQualifiedName,
+ /// \brief Code completion occurred where an macro is being defined.
+ CCC_MacroName,
+ /// \brief Code completion occurred where a macro name is expected
+ /// (without any arguments, in the case of a function-like macro).
+ CCC_MacroNameUse,
+ /// \brief Code completion occurred within a preprocessor expression.
+ CCC_PreprocessorExpression,
+ /// \brief Code completion occurred where a preprocessor directive is
+ /// expected.
+ CCC_PreprocessorDirective,
+ /// \brief Code completion occurred in a context where natural language is
+ /// expected, e.g., a comment or string literal.
+ ///
+ /// This context usually implies that no completions should be added,
+ /// unless they come from an appropriate natural-language dictionary.
+ CCC_NaturalLanguage,
+ /// \brief Code completion for a selector, as in an @selector expression.
+ CCC_SelectorName,
+ /// \brief Code completion within a type-qualifier list.
+ CCC_TypeQualifiers,
+ /// \brief Code completion in a parenthesized expression, which means that
+ /// we may also have types here in C and Objective-C (as well as in C++).
+ CCC_ParenthesizedExpression,
+ /// \brief An unknown context, in which we are recovering from a parsing
+ /// error and don't know which completions we should give.
+ CCC_Recovery
+ };
+
+private:
+ enum Kind Kind;
+
+ /// \brief The type that would prefer to see at this point (e.g., the type
+ /// of an initializer or function parameter).
+ QualType PreferredType;
+
+ /// \brief The type of the base object in a member access expression.
+ QualType BaseType;
+
+public:
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind) { }
+
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) {
+ if (Kind == CCC_MemberAccess)
+ BaseType = T;
+ else
+ PreferredType = T;
+ }
+
+ /// \brief Retrieve the kind of code-completion context.
+ enum Kind getKind() const { return Kind; }
+
+ /// \brief Retrieve the type that this expression would prefer to have, e.g.,
+ /// if the expression is a variable initializer or a function argument, the
+ /// type of the corresponding variable or function parameter.
+ QualType getPreferredType() const { return PreferredType; }
+
+ /// \brief Retrieve the type of the base object in a member-access
+ /// expression.
+ QualType getBaseType() const { return BaseType; }
+
+ /// \brief Determines whether we want C++ constructors as results within this
+ /// context.
+ bool wantConstructorResults() const;
+};
+
+
+/// \brief A "string" used to describe how code completion can
+/// be performed for an entity.
+///
+/// A code completion string typically shows how a particular entity can be
+/// used. For example, the code completion string for a function would show
+/// the syntax to call it, including the parentheses, placeholders for the
+/// arguments, etc.
+class CodeCompletionString {
+public:
+ /// \brief The different kinds of "chunks" that can occur within a code
+ /// completion string.
+ enum ChunkKind {
+ /// \brief The piece of text that the user is expected to type to
+ /// match the code-completion string, typically a keyword or the name of a
+ /// declarator or macro.
+ CK_TypedText,
+ /// \brief A piece of text that should be placed in the buffer, e.g.,
+ /// parentheses or a comma in a function call.
+ CK_Text,
+ /// \brief A code completion string that is entirely optional. For example,
+ /// an optional code completion string that describes the default arguments
+ /// in a function call.
+ CK_Optional,
+ /// \brief A string that acts as a placeholder for, e.g., a function
+ /// call argument.
+ CK_Placeholder,
+ /// \brief A piece of text that describes something about the result but
+ /// should not be inserted into the buffer.
+ CK_Informative,
+ /// \brief A piece of text that describes the type of an entity or, for
+ /// functions and methods, the return type.
+ CK_ResultType,
+ /// \brief A piece of text that describes the parameter that corresponds
+ /// to the code-completion location within a function call, message send,
+ /// macro invocation, etc.
+ CK_CurrentParameter,
+ /// \brief A left parenthesis ('(').
+ CK_LeftParen,
+ /// \brief A right parenthesis (')').
+ CK_RightParen,
+ /// \brief A left bracket ('[').
+ CK_LeftBracket,
+ /// \brief A right bracket (']').
+ CK_RightBracket,
+ /// \brief A left brace ('{').
+ CK_LeftBrace,
+ /// \brief A right brace ('}').
+ CK_RightBrace,
+ /// \brief A left angle bracket ('<').
+ CK_LeftAngle,
+ /// \brief A right angle bracket ('>').
+ CK_RightAngle,
+ /// \brief A comma separator (',').
+ CK_Comma,
+ /// \brief A colon (':').
+ CK_Colon,
+ /// \brief A semicolon (';').
+ CK_SemiColon,
+ /// \brief An '=' sign.
+ CK_Equal,
+ /// \brief Horizontal whitespace (' ').
+ CK_HorizontalSpace,
+ /// \brief Verticle whitespace ('\n' or '\r\n', depending on the
+ /// platform).
+ CK_VerticalSpace
+ };
+
+ /// \brief One piece of the code completion string.
+ struct Chunk {
+ /// \brief The kind of data stored in this piece of the code completion
+ /// string.
+ ChunkKind Kind;
+
+ union {
+ /// \brief The text string associated with a CK_Text, CK_Placeholder,
+ /// CK_Informative, or CK_Comma chunk.
+ /// The string is owned by the chunk and will be deallocated
+ /// (with delete[]) when the chunk is destroyed.
+ const char *Text;
+
+ /// \brief The code completion string associated with a CK_Optional chunk.
+ /// The optional code completion string is owned by the chunk, and will
+ /// be deallocated (with delete) when the chunk is destroyed.
+ CodeCompletionString *Optional;
+ };
+
+ Chunk() : Kind(CK_Text), Text(0) { }
+
+ Chunk(ChunkKind Kind, const char *Text = "");
+
+ /// \brief Create a new text chunk.
+ static Chunk CreateText(const char *Text);
+
+ /// \brief Create a new optional chunk.
+ static Chunk CreateOptional(CodeCompletionString *Optional);
+
+ /// \brief Create a new placeholder chunk.
+ static Chunk CreatePlaceholder(const char *Placeholder);
+
+ /// \brief Create a new informative chunk.
+ static Chunk CreateInformative(const char *Informative);
+
+ /// \brief Create a new result type chunk.
+ static Chunk CreateResultType(const char *ResultType);
+
+ /// \brief Create a new current-parameter chunk.
+ static Chunk CreateCurrentParameter(const char *CurrentParameter);
+ };
+
+private:
+ /// \brief The number of chunks stored in this string.
+ unsigned NumChunks;
+
+ /// \brief The priority of this code-completion string.
+ unsigned Priority : 30;
+
+ /// \brief The availability of this code-completion result.
+ unsigned Availability : 2;
+
+ CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
+ CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
+
+ CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
+ unsigned Priority, CXAvailabilityKind Availability);
+ ~CodeCompletionString() { }
+
+ friend class CodeCompletionBuilder;
+ friend class CodeCompletionResult;
+
+public:
+ typedef const Chunk *iterator;
+ iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); }
+ iterator end() const { return begin() + NumChunks; }
+ bool empty() const { return NumChunks == 0; }
+ unsigned size() const { return NumChunks; }
+
+ const Chunk &operator[](unsigned I) const {
+ assert(I < size() && "Chunk index out-of-range");
+ return begin()[I];
+ }
+
+ /// \brief Returns the text in the TypedText chunk.
+ const char *getTypedText() const;
+
+ /// \brief Retrieve the priority of this code completion result.
+ unsigned getPriority() const { return Priority; }
+
+ /// \brief Reteirve the availability of this code completion result.
+ unsigned getAvailability() const { return Availability; }
+
+ /// \brief Retrieve a string representation of the code completion string,
+ /// which is mainly useful for debugging.
+ std::string getAsString() const;
+};
+
+/// \brief An allocator used specifically for the purpose of code completion.
+class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
+public:
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(llvm::StringRef String);
+
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(llvm::Twine String);
+
+ // \brief Copy the given string into this allocator.
+ const char *CopyString(const char *String) {
+ return CopyString(llvm::StringRef(String));
+ }
+
+ /// \brief Copy the given string into this allocator.
+ const char *CopyString(const std::string &String) {
+ return CopyString(llvm::StringRef(String));
+ }
+};
+
+/// \brief A builder class used to construct new code-completion strings.
+class CodeCompletionBuilder {
+public:
+ typedef CodeCompletionString::Chunk Chunk;
+
+private:
+ CodeCompletionAllocator &Allocator;
+ unsigned Priority;
+ CXAvailabilityKind Availability;
+
+ /// \brief The chunks stored in this string.
+ llvm::SmallVector<Chunk, 4> Chunks;
+
+public:
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator)
+ : Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){
+ }
+
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ unsigned Priority, CXAvailabilityKind Availability)
+ : Allocator(Allocator), Priority(Priority), Availability(Availability) { }
+
+ /// \brief Retrieve the allocator into which the code completion
+ /// strings should be allocated.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ /// \brief Take the resulting completion string.
+ ///
+ /// This operation can only be performed once.
+ CodeCompletionString *TakeString();
+
+ /// \brief Add a new typed-text chunk.
+ void AddTypedTextChunk(const char *Text) {
+ Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
+ }
+
+ /// \brief Add a new text chunk.
+ void AddTextChunk(const char *Text) {
+ Chunks.push_back(Chunk::CreateText(Text));
+ }
+
+ /// \brief Add a new optional chunk.
+ void AddOptionalChunk(CodeCompletionString *Optional) {
+ Chunks.push_back(Chunk::CreateOptional(Optional));
+ }
+
+ /// \brief Add a new placeholder chunk.
+ void AddPlaceholderChunk(const char *Placeholder) {
+ Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
+ }
+
+ /// \brief Add a new informative chunk.
+ void AddInformativeChunk(const char *Text) {
+ Chunks.push_back(Chunk::CreateInformative(Text));
+ }
+
+ /// \brief Add a new result-type chunk.
+ void AddResultTypeChunk(const char *ResultType) {
+ Chunks.push_back(Chunk::CreateResultType(ResultType));
+ }
+
+ /// \brief Add a new current-parameter chunk.
+ void AddCurrentParameterChunk(const char *CurrentParameter) {
+ Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
+ }
+
+ /// \brief Add a new chunk.
+ void AddChunk(Chunk C) { Chunks.push_back(C); }
+};
+
+/// \brief Captures a result of code completion.
+class CodeCompletionResult {
+public:
+ /// \brief Describes the kind of result generated.
+ enum ResultKind {
+ RK_Declaration = 0, //< Refers to a declaration
+ RK_Keyword, //< Refers to a keyword or symbol.
+ RK_Macro, //< Refers to a macro
+ RK_Pattern //< Refers to a precomputed pattern.
+ };
+
+ /// \brief The kind of result stored here.
+ ResultKind Kind;
+
+ union {
+ /// \brief When Kind == RK_Declaration, the declaration we are referring
+ /// to.
+ NamedDecl *Declaration;
+
+ /// \brief When Kind == RK_Keyword, the string representing the keyword
+ /// or symbol's spelling.
+ const char *Keyword;
+
+ /// \brief When Kind == RK_Pattern, the code-completion string that
+ /// describes the completion text to insert.
+ CodeCompletionString *Pattern;
+
+ /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ IdentifierInfo *Macro;
+ };
+
+ /// \brief The priority of this particular code-completion result.
+ unsigned Priority;
+
+ /// \brief The cursor kind that describes this result.
+ CXCursorKind CursorKind;
+
+ /// \brief The availability of this result.
+ CXAvailabilityKind Availability;
+
+ /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter;
+
+ /// \brief Whether this result is hidden by another name.
+ bool Hidden : 1;
+
+ /// \brief Whether this result was found via lookup into a base class.
+ bool QualifierIsInformative : 1;
+
+ /// \brief Whether this declaration is the beginning of a
+ /// nested-name-specifier and, therefore, should be followed by '::'.
+ bool StartsNestedNameSpecifier : 1;
+
+ /// \brief Whether all parameters (of a function, Objective-C
+ /// method, etc.) should be considered "informative".
+ bool AllParametersAreInformative : 1;
+
+ /// \brief Whether we're completing a declaration of the given entity,
+ /// rather than a use of that entity.
+ bool DeclaringEntity : 1;
+
+ /// \brief If the result should have a nested-name-specifier, this is it.
+ /// When \c QualifierIsInformative, the nested-name-specifier is
+ /// informative rather than required.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief Build a result that refers to a declaration.
+ CodeCompletionResult(NamedDecl *Declaration,
+ NestedNameSpecifier *Qualifier = 0,
+ bool QualifierIsInformative = false)
+ : Kind(RK_Declaration), Declaration(Declaration),
+ Priority(getPriorityFromDecl(Declaration)),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(Qualifier) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Build a result that refers to a keyword or symbol.
+ CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
+ : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
+ Availability(CXAvailability_Available),
+ StartParameter(0), Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Build a result that refers to a macro.
+ CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
+ : Kind(RK_Macro), Macro(Macro), Priority(Priority),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Build a result that refers to a pattern.
+ CodeCompletionResult(CodeCompletionString *Pattern,
+ unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available)
+ : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
+ CursorKind(CursorKind), Availability(Availability), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0)
+ {
+ }
+
+ /// \brief Retrieve the declaration stored in this result.
+ NamedDecl *getDeclaration() const {
+ assert(Kind == RK_Declaration && "Not a declaration result");
+ return Declaration;
+ }
+
+ /// \brief Retrieve the keyword stored in this result.
+ const char *getKeyword() const {
+ assert(Kind == RK_Keyword && "Not a keyword result");
+ return Keyword;
+ }
+
+ /// \brief Create a new code-completion string that describes how to insert
+ /// this result into a program.
+ ///
+ /// \param S The semantic analysis that created the result.
+ ///
+ /// \param Allocator The allocator that will be used to allocate the
+ /// string itself.
+ CodeCompletionString *CreateCodeCompletionString(Sema &S,
+ CodeCompletionAllocator &Allocator);
+
+ /// \brief Determine a base priority for the given declaration.
+ static unsigned getPriorityFromDecl(NamedDecl *ND);
+
+private:
+ void computeCursorKindAndAvailability();
+};
+
+bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);
+
+inline bool operator>(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return Y < X;
+}
+
+inline bool operator<=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(Y < X);
+}
+
+inline bool operator>=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(X < Y);
+}
+
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const CodeCompletionString &CCS);
+
+/// \brief Abstract interface for a consumer of code-completion
+/// information.
+class CodeCompleteConsumer {
+protected:
+ /// \brief Whether to include macros in the code-completion results.
+ bool IncludeMacros;
+
+ /// \brief Whether to include code patterns (such as for loops) within
+ /// the completion results.
+ bool IncludeCodePatterns;
+
+ /// \brief Whether to include global (top-level) declarations and names in
+ /// the completion results.
+ bool IncludeGlobals;
+
+ /// \brief Whether the output format for the code-completion consumer is
+ /// binary.
+ bool OutputIsBinary;
+
+public:
+ class OverloadCandidate {
+ public:
+ /// \brief Describes the type of overload candidate.
+ enum CandidateKind {
+ /// \brief The candidate is a function declaration.
+ CK_Function,
+ /// \brief The candidate is a function template.
+ CK_FunctionTemplate,
+ /// \brief The "candidate" is actually a variable, expression, or block
+ /// for which we only have a function prototype.
+ CK_FunctionType
+ };
+
+ private:
+ /// \brief The kind of overload candidate.
+ CandidateKind Kind;
+
+ union {
+ /// \brief The function overload candidate, available when
+ /// Kind == CK_Function.
+ FunctionDecl *Function;
+
+ /// \brief The function template overload candidate, available when
+ /// Kind == CK_FunctionTemplate.
+ FunctionTemplateDecl *FunctionTemplate;
+
+ /// \brief The function type that describes the entity being called,
+ /// when Kind == CK_FunctionType.
+ const FunctionType *Type;
+ };
+
+ public:
+ OverloadCandidate(FunctionDecl *Function)
+ : Kind(CK_Function), Function(Function) { }
+
+ OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
+ : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { }
+
+ OverloadCandidate(const FunctionType *Type)
+ : Kind(CK_FunctionType), Type(Type) { }
+
+ /// \brief Determine the kind of overload candidate.
+ CandidateKind getKind() const { return Kind; }
+
+ /// \brief Retrieve the function overload candidate or the templated
+ /// function declaration for a function template.
+ FunctionDecl *getFunction() const;
+
+ /// \brief Retrieve the function template overload candidate.
+ FunctionTemplateDecl *getFunctionTemplate() const {
+ assert(getKind() == CK_FunctionTemplate && "Not a function template");
+ return FunctionTemplate;
+ }
+
+ /// \brief Retrieve the function type of the entity, regardless of how the
+ /// function is stored.
+ const FunctionType *getFunctionType() const;
+
+ /// \brief Create a new code-completion string that describes the function
+ /// signature of this overload candidate.
+ CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
+ Sema &S,
+ CodeCompletionAllocator &Allocator) const;
+ };
+
+ CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
+ IncludeGlobals(true), OutputIsBinary(false) { }
+
+ CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals, bool OutputIsBinary)
+ : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns),
+ IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { }
+
+ /// \brief Whether the code-completion consumer wants to see macros.
+ bool includeMacros() const { return IncludeMacros; }
+
+ /// \brief Whether the code-completion consumer wants to see code patterns.
+ bool includeCodePatterns() const { return IncludeCodePatterns; }
+
+ /// \brief Whether to include global (top-level) declaration results.
+ bool includeGlobals() const { return IncludeGlobals; }
+
+ /// \brief Determine whether the output of this consumer is binary.
+ bool isOutputBinary() const { return OutputIsBinary; }
+
+ /// \brief Deregisters and destroys this code-completion consumer.
+ virtual ~CodeCompleteConsumer();
+
+ /// \name Code-completion callbacks
+ //@{
+ /// \brief Process the finalized code-completion results.
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) { }
+
+ /// \param S the semantic-analyzer object for which code-completion is being
+ /// done.
+ ///
+ /// \param CurrentArg the index of the current argument.
+ ///
+ /// \param Candidates an array of overload candidates.
+ ///
+ /// \param NumCandidates the number of overload candidates
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) { }
+ //@}
+
+ /// \brief Retrieve the allocator that will be used to allocate
+ /// code completion strings.
+ virtual CodeCompletionAllocator &getAllocator() = 0;
+};
+
+/// \brief A simple code-completion consumer that prints the results it
+/// receives in a simple format.
+class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
+ /// \brief The raw output stream.
+ llvm::raw_ostream &OS;
+
+ CodeCompletionAllocator Allocator;
+
+public:
+ /// \brief Create a new printing code-completion consumer that prints its
+ /// results to the given raw output stream.
+ PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals,
+ llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ false), OS(OS) {}
+
+ /// \brief Prints the finalized code-completion results.
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults);
+
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates);
+
+ virtual CodeCompletionAllocator &getAllocator() { return Allocator; }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
new file mode 100644
index 0000000..9c4bb64
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -0,0 +1,1558 @@
+//===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the classes used to store parsed information about
+// declaration-specifiers and declarators.
+//
+// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+// ------------------------- - -- ---------------------------
+// declaration-specifiers \ | /
+// declarators
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
+#define LLVM_CLANG_SEMA_DECLSPEC_H
+
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Lex/Token.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+ class LangOptions;
+ class Diagnostic;
+ class IdentifierInfo;
+ class NestedNameSpecifier;
+ class Preprocessor;
+ class Declarator;
+ struct TemplateIdAnnotation;
+
+/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
+/// specifier. These can be in 3 states:
+/// 1) Not present, identified by isEmpty()
+/// 2) Present, identified by isNotEmpty()
+/// 2.a) Valid, idenified by isValid()
+/// 2.b) Invalid, identified by isInvalid().
+///
+/// isSet() is deprecated because it mostly corresponded to "valid" but was
+/// often used as if it meant "present".
+///
+/// The actual scope is described by getScopeRep().
+class CXXScopeSpec {
+ SourceRange Range;
+ NestedNameSpecifier *ScopeRep;
+
+public:
+ CXXScopeSpec() : Range(), ScopeRep() { }
+
+ const SourceRange &getRange() const { return Range; }
+ void setRange(const SourceRange &R) { Range = R; }
+ void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
+ void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+
+ NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
+ void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
+
+ /// No scope specifier.
+ bool isEmpty() const { return !Range.isValid(); }
+ /// A scope specifier is present, but may be valid or invalid.
+ bool isNotEmpty() const { return !isEmpty(); }
+
+ /// An error occured during parsing of the scope specifier.
+ bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
+ /// A scope specifier is present, and it refers to a real scope.
+ bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
+
+ /// Deprecated. Some call sites intend isNotEmpty() while others intend
+ /// isValid().
+ bool isSet() const { return ScopeRep != 0; }
+
+ void clear() {
+ Range = SourceRange();
+ ScopeRep = 0;
+ }
+};
+
+/// DeclSpec - This class captures information about "declaration specifiers",
+/// which encompasses storage-class-specifiers, type-specifiers,
+/// type-qualifiers, and function-specifiers.
+class DeclSpec {
+public:
+ // storage-class-specifier
+ // Note: The order of these enumerators is important for diagnostics.
+ enum SCS {
+ SCS_unspecified = 0,
+ SCS_typedef,
+ SCS_extern,
+ SCS_static,
+ SCS_auto,
+ SCS_register,
+ SCS_private_extern,
+ SCS_mutable
+ };
+
+ // Import type specifier width enumeration and constants.
+ typedef TypeSpecifierWidth TSW;
+ static const TSW TSW_unspecified = clang::TSW_unspecified;
+ static const TSW TSW_short = clang::TSW_short;
+ static const TSW TSW_long = clang::TSW_long;
+ static const TSW TSW_longlong = clang::TSW_longlong;
+
+ enum TSC {
+ TSC_unspecified,
+ TSC_imaginary,
+ TSC_complex
+ };
+
+ // Import type specifier sign enumeration and constants.
+ typedef TypeSpecifierSign TSS;
+ static const TSS TSS_unspecified = clang::TSS_unspecified;
+ static const TSS TSS_signed = clang::TSS_signed;
+ static const TSS TSS_unsigned = clang::TSS_unsigned;
+
+ // Import type specifier type enumeration and constants.
+ typedef TypeSpecifierType TST;
+ static const TST TST_unspecified = clang::TST_unspecified;
+ static const TST TST_void = clang::TST_void;
+ static const TST TST_char = clang::TST_char;
+ static const TST TST_wchar = clang::TST_wchar;
+ static const TST TST_char16 = clang::TST_char16;
+ static const TST TST_char32 = clang::TST_char32;
+ static const TST TST_int = clang::TST_int;
+ static const TST TST_float = clang::TST_float;
+ static const TST TST_double = clang::TST_double;
+ static const TST TST_bool = clang::TST_bool;
+ static const TST TST_decimal32 = clang::TST_decimal32;
+ static const TST TST_decimal64 = clang::TST_decimal64;
+ static const TST TST_decimal128 = clang::TST_decimal128;
+ static const TST TST_enum = clang::TST_enum;
+ static const TST TST_union = clang::TST_union;
+ static const TST TST_struct = clang::TST_struct;
+ static const TST TST_class = clang::TST_class;
+ static const TST TST_typename = clang::TST_typename;
+ static const TST TST_typeofType = clang::TST_typeofType;
+ static const TST TST_typeofExpr = clang::TST_typeofExpr;
+ static const TST TST_decltype = clang::TST_decltype;
+ static const TST TST_auto = clang::TST_auto;
+ static const TST TST_error = clang::TST_error;
+
+ // type-qualifiers
+ enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ.
+ TQ_unspecified = 0,
+ TQ_const = 1,
+ TQ_restrict = 2,
+ TQ_volatile = 4
+ };
+
+ /// ParsedSpecifiers - Flags to query which specifiers were applied. This is
+ /// returned by getParsedSpecifiers.
+ enum ParsedSpecifiers {
+ PQ_None = 0,
+ PQ_StorageClassSpecifier = 1,
+ PQ_TypeSpecifier = 2,
+ PQ_TypeQualifier = 4,
+ PQ_FunctionSpecifier = 8
+ };
+
+private:
+
+ // storage-class-specifier
+ /*SCS*/unsigned StorageClassSpec : 3;
+ unsigned SCS_thread_specified : 1;
+ unsigned SCS_extern_in_linkage_spec : 1;
+
+ // type-specifier
+ /*TSW*/unsigned TypeSpecWidth : 2;
+ /*TSC*/unsigned TypeSpecComplex : 2;
+ /*TSS*/unsigned TypeSpecSign : 2;
+ /*TST*/unsigned TypeSpecType : 5;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
+
+ // type-qualifiers
+ unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
+
+ // function-specifier
+ unsigned FS_inline_specified : 1;
+ unsigned FS_virtual_specified : 1;
+ unsigned FS_explicit_specified : 1;
+
+ // friend-specifier
+ unsigned Friend_specified : 1;
+
+ // constexpr-specifier
+ unsigned Constexpr_specified : 1;
+
+ /*SCS*/unsigned StorageClassSpecAsWritten : 3;
+
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ };
+
+ // attributes.
+ ParsedAttributes Attrs;
+
+ // Scope specifier for the type spec, if applicable.
+ CXXScopeSpec TypeScope;
+
+ // List of protocol qualifiers for objective-c classes. Used for
+ // protocol-qualified interfaces "NString<foo>" and protocol-qualified id
+ // "id<foo>".
+ Decl * const *ProtocolQualifiers;
+ unsigned NumProtocolQualifiers;
+ SourceLocation ProtocolLAngleLoc;
+ SourceLocation *ProtocolLocs;
+
+ // SourceLocation info. These are null if the item wasn't specified or if
+ // the setting was synthesized.
+ SourceRange Range;
+
+ SourceLocation StorageClassSpecLoc, SCS_threadLoc;
+ SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
+ SourceRange TypeofParensRange;
+ SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
+ SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
+ SourceLocation FriendLoc, ConstexprLoc;
+
+ WrittenBuiltinSpecs writtenBS;
+ void SaveWrittenBuiltinSpecs();
+ void SaveStorageSpecifierAsWritten();
+
+ static bool isTypeRep(TST T) {
+ return (T == TST_typename || T == TST_typeofType);
+ }
+ static bool isExprRep(TST T) {
+ return (T == TST_typeofExpr || T == TST_decltype);
+ }
+ static bool isDeclRep(TST T) {
+ return (T == TST_enum || T == TST_struct ||
+ T == TST_union || T == TST_class);
+ }
+
+ DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
+ void operator=(const DeclSpec&); // DO NOT IMPLEMENT
+public:
+
+ DeclSpec()
+ : StorageClassSpec(SCS_unspecified),
+ SCS_thread_specified(false),
+ SCS_extern_in_linkage_spec(false),
+ TypeSpecWidth(TSW_unspecified),
+ TypeSpecComplex(TSC_unspecified),
+ TypeSpecSign(TSS_unspecified),
+ TypeSpecType(TST_unspecified),
+ TypeAltiVecVector(false),
+ TypeAltiVecPixel(false),
+ TypeAltiVecBool(false),
+ TypeSpecOwned(false),
+ TypeQualifiers(TSS_unspecified),
+ FS_inline_specified(false),
+ FS_virtual_specified(false),
+ FS_explicit_specified(false),
+ Friend_specified(false),
+ Constexpr_specified(false),
+ StorageClassSpecAsWritten(SCS_unspecified),
+ ProtocolQualifiers(0),
+ NumProtocolQualifiers(0),
+ ProtocolLocs(0),
+ writtenBS() {
+ }
+ ~DeclSpec() {
+ delete [] ProtocolQualifiers;
+ delete [] ProtocolLocs;
+ }
+ // storage-class-specifier
+ SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
+ bool isThreadSpecified() const { return SCS_thread_specified; }
+ bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
+ void setExternInLinkageSpec(bool Value) {
+ SCS_extern_in_linkage_spec = Value;
+ }
+
+ SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
+ SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
+
+ void ClearStorageClassSpecs() {
+ StorageClassSpec = DeclSpec::SCS_unspecified;
+ SCS_thread_specified = false;
+ SCS_extern_in_linkage_spec = false;
+ StorageClassSpecLoc = SourceLocation();
+ SCS_threadLoc = SourceLocation();
+ }
+
+ // type-specifier
+ TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
+ TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
+ TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; }
+ TST getTypeSpecType() const { return (TST)TypeSpecType; }
+ bool isTypeAltiVecVector() const { return TypeAltiVecVector; }
+ bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
+ bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
+ bool isTypeSpecOwned() const { return TypeSpecOwned; }
+ ParsedType getRepAsType() const {
+ assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
+ return TypeRep;
+ }
+ Decl *getRepAsDecl() const {
+ assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
+ return DeclRep;
+ }
+ Expr *getRepAsExpr() const {
+ assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
+ return ExprRep;
+ }
+ CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
+ const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
+
+ const SourceRange &getSourceRange() const { return Range; }
+ SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
+ SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
+ SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
+ SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
+ SourceLocation getAltiVecLoc() const { return AltiVecLoc; }
+
+ SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+ void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
+
+ /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
+ /// or "union".
+ static const char *getSpecifierName(DeclSpec::TST T);
+ static const char *getSpecifierName(DeclSpec::TQ Q);
+ static const char *getSpecifierName(DeclSpec::TSS S);
+ static const char *getSpecifierName(DeclSpec::TSC C);
+ static const char *getSpecifierName(DeclSpec::TSW W);
+ static const char *getSpecifierName(DeclSpec::SCS S);
+
+ // type-qualifiers
+
+ /// getTypeQualifiers - Return a set of TQs.
+ unsigned getTypeQualifiers() const { return TypeQualifiers; }
+ SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
+ SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
+ SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
+
+ // function-specifier
+ bool isInlineSpecified() const { return FS_inline_specified; }
+ SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
+
+ bool isVirtualSpecified() const { return FS_virtual_specified; }
+ SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
+
+ bool isExplicitSpecified() const { return FS_explicit_specified; }
+ SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; }
+
+ void ClearFunctionSpecs() {
+ FS_inline_specified = false;
+ FS_inlineLoc = SourceLocation();
+ FS_virtual_specified = false;
+ FS_virtualLoc = SourceLocation();
+ FS_explicit_specified = false;
+ FS_explicitLoc = SourceLocation();
+ }
+
+ /// hasTypeSpecifier - Return true if any type-specifier has been found.
+ bool hasTypeSpecifier() const {
+ return getTypeSpecType() != DeclSpec::TST_unspecified ||
+ getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
+ getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
+ getTypeSpecSign() != DeclSpec::TSS_unspecified;
+ }
+
+ /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+ /// DeclSpec includes.
+ ///
+ unsigned getParsedSpecifiers() const;
+
+ SCS getStorageClassSpecAsWritten() const {
+ return (SCS)StorageClassSpecAsWritten;
+ }
+
+ /// isEmpty - Return true if this declaration specifier is completely empty:
+ /// no tokens were parsed in the production of it.
+ bool isEmpty() const {
+ return getParsedSpecifiers() == DeclSpec::PQ_None;
+ }
+
+ void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); }
+ void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); }
+
+ /// These methods set the specified attribute of the DeclSpec and
+ /// return false if there was no error. If an error occurs (for
+ /// example, if we tried to set "auto" on a spec with "extern"
+ /// already set), they return true and set PrevSpec and DiagID
+ /// such that
+ /// Diag(Loc, DiagID) << PrevSpec;
+ /// will yield a useful result.
+ ///
+ /// TODO: use a more general approach that still allows these
+ /// diagnostics to be ignored when desired.
+ bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const LangOptions &Lang);
+ bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Expr *Rep);
+ bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeSpecError();
+ void UpdateDeclRep(Decl *Rep) {
+ assert(isDeclRep((TST) TypeSpecType));
+ DeclRep = Rep;
+ }
+ void UpdateTypeRep(ParsedType Rep) {
+ assert(isTypeRep((TST) TypeSpecType));
+ TypeRep = Rep;
+ }
+ void UpdateExprRep(Expr *Rep) {
+ assert(isExprRep((TST) TypeSpecType));
+ ExprRep = Rep;
+ }
+
+ bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const LangOptions &Lang);
+
+ bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool isFriendSpecified() const { return Friend_specified; }
+ SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+
+ bool isConstexprSpecified() const { return Constexpr_specified; }
+ SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
+
+ /// AddAttributes - contatenates two attribute lists.
+ /// The GCC attribute syntax allows for the following:
+ ///
+ /// short __attribute__(( unused, deprecated ))
+ /// int __attribute__(( may_alias, aligned(16) )) var;
+ ///
+ /// This declares 4 attributes using 2 lists. The following syntax is
+ /// also allowed and equivalent to the previous declaration.
+ ///
+ /// short __attribute__((unused)) __attribute__((deprecated))
+ /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
+ ///
+ void addAttributes(AttributeList *AL) {
+ Attrs.append(AL);
+ }
+ void aetAttributes(AttributeList *AL) {
+ Attrs.set(AL);
+ }
+
+ bool hasAttributes() const { return !Attrs.empty(); }
+
+ ParsedAttributes &getAttributes() { return Attrs; }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+
+ /// TakeAttributes - Return the current attribute list and remove them from
+ /// the DeclSpec so that it doesn't own them.
+ ParsedAttributes takeAttributes() {
+ ParsedAttributes saved = Attrs;
+ Attrs.clear();
+ return saved;
+ }
+
+ void takeAttributesFrom(ParsedAttributes &attrs) {
+ Attrs.append(attrs.getList());
+ attrs.clear();
+ }
+
+ typedef Decl * const *ProtocolQualifierListTy;
+ ProtocolQualifierListTy getProtocolQualifiers() const {
+ return ProtocolQualifiers;
+ }
+ SourceLocation *getProtocolLocs() const { return ProtocolLocs; }
+ unsigned getNumProtocolQualifiers() const {
+ return NumProtocolQualifiers;
+ }
+ SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; }
+ void setProtocolQualifiers(Decl * const *Protos, unsigned NP,
+ SourceLocation *ProtoLocs,
+ SourceLocation LAngleLoc);
+
+ /// Finish - This does final analysis of the declspec, issuing diagnostics for
+ /// things like "_Imaginary" (lacking an FP type). After calling this method,
+ /// DeclSpec is guaranteed self-consistent, even if an error occurred.
+ void Finish(Diagnostic &D, Preprocessor &PP);
+
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return writtenBS;
+ }
+
+ /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
+ /// without a Declarator. Only tag declspecs can stand alone.
+ bool isMissingDeclaratorOk();
+};
+
+/// ObjCDeclSpec - This class captures information about
+/// "declaration specifiers" specific to objective-c
+class ObjCDeclSpec {
+public:
+ /// ObjCDeclQualifier - Qualifier used on types in method declarations
+ enum ObjCDeclQualifier {
+ DQ_None = 0x0,
+ DQ_In = 0x1,
+ DQ_Inout = 0x2,
+ DQ_Out = 0x4,
+ DQ_Bycopy = 0x8,
+ DQ_Byref = 0x10,
+ DQ_Oneway = 0x20
+ };
+
+ /// PropertyAttributeKind - list of property attributes.
+ enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0,
+ DQ_PR_readonly = 0x01,
+ DQ_PR_getter = 0x02,
+ DQ_PR_assign = 0x04,
+ DQ_PR_readwrite = 0x08,
+ DQ_PR_retain = 0x10,
+ DQ_PR_copy = 0x20,
+ DQ_PR_nonatomic = 0x40,
+ DQ_PR_setter = 0x80,
+ DQ_PR_atomic = 0x100
+ };
+
+
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
+ GetterName(0), SetterName(0) { }
+ ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
+ }
+
+ ObjCPropertyAttributeKind getPropertyAttributes() const {
+ return ObjCPropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
+ PropertyAttributes =
+ (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
+ }
+
+ const IdentifierInfo *getGetterName() const { return GetterName; }
+ IdentifierInfo *getGetterName() { return GetterName; }
+ void setGetterName(IdentifierInfo *name) { GetterName = name; }
+
+ const IdentifierInfo *getSetterName() const { return SetterName; }
+ IdentifierInfo *getSetterName() { return SetterName; }
+ void setSetterName(IdentifierInfo *name) { SetterName = name; }
+private:
+ // FIXME: These two are unrelated and mutially exclusive. So perhaps
+ // we can put them in a union to reflect their mutual exclusiveness
+ // (space saving is negligible).
+ ObjCDeclQualifier objcDeclQualifier : 6;
+
+ // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
+ unsigned PropertyAttributes : 9;
+ IdentifierInfo *GetterName; // getter name of NULL if no getter
+ IdentifierInfo *SetterName; // setter name of NULL if no setter
+};
+
+/// \brief Represents a C++ unqualified-id that has been parsed.
+class UnqualifiedId {
+private:
+ const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT
+
+public:
+ /// \brief Describes the kind of unqualified-id parsed.
+ enum IdKind {
+ /// \brief An identifier.
+ IK_Identifier,
+ /// \brief An overloaded operator name, e.g., operator+.
+ IK_OperatorFunctionId,
+ /// \brief A conversion function name, e.g., operator int.
+ IK_ConversionFunctionId,
+ /// \brief A user-defined literal name, e.g., operator "" _i.
+ IK_LiteralOperatorId,
+ /// \brief A constructor name.
+ IK_ConstructorName,
+ /// \brief A constructor named via a template-id.
+ IK_ConstructorTemplateId,
+ /// \brief A destructor name.
+ IK_DestructorName,
+ /// \brief A template-id, e.g., f<int>.
+ IK_TemplateId
+ } Kind;
+
+ /// \brief Anonymous union that holds extra data associated with the
+ /// parsed unqualified-id.
+ union {
+ /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind
+ /// == IK_UserLiteralId, the identifier suffix.
+ IdentifierInfo *Identifier;
+
+ /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
+ /// that we parsed.
+ struct {
+ /// \brief The kind of overloaded operator.
+ OverloadedOperatorKind Operator;
+
+ /// \brief The source locations of the individual tokens that name
+ /// the operator, e.g., the "new", "[", and "]" tokens in
+ /// operator new [].
+ ///
+ /// Different operators have different numbers of tokens in their name,
+ /// up to three. Any remaining source locations in this array will be
+ /// set to an invalid value for operators with fewer than three tokens.
+ unsigned SymbolLocations[3];
+ } OperatorFunctionId;
+
+ /// \brief When Kind == IK_ConversionFunctionId, the type that the
+ /// conversion function names.
+ UnionParsedType ConversionFunctionId;
+
+ /// \brief When Kind == IK_ConstructorName, the class-name of the type
+ /// whose constructor is being referenced.
+ UnionParsedType ConstructorName;
+
+ /// \brief When Kind == IK_DestructorName, the type referred to by the
+ /// class-name.
+ UnionParsedType DestructorName;
+
+ /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
+ /// the template-id annotation that contains the template name and
+ /// template arguments.
+ TemplateIdAnnotation *TemplateId;
+ };
+
+ /// \brief The location of the first token that describes this unqualified-id,
+ /// which will be the location of the identifier, "operator" keyword,
+ /// tilde (for a destructor), or the template name of a template-id.
+ SourceLocation StartLocation;
+
+ /// \brief The location of the last token that describes this unqualified-id.
+ SourceLocation EndLocation;
+
+ UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
+
+ /// \brief Do not use this copy constructor. It is temporary, and only
+ /// exists because we are holding FieldDeclarators in a SmallVector when we
+ /// don't actually need them.
+ ///
+ /// FIXME: Kill this copy constructor.
+ UnqualifiedId(const UnqualifiedId &Other)
+ : Kind(IK_Identifier), Identifier(Other.Identifier),
+ StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) {
+ assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
+ }
+
+ /// \brief Destroy this unqualified-id.
+ ~UnqualifiedId() { clear(); }
+
+ /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ /// state.
+ void clear();
+
+ /// \brief Determine whether this unqualified-id refers to a valid name.
+ bool isValid() const { return StartLocation.isValid(); }
+
+ /// \brief Determine whether this unqualified-id refers to an invalid name.
+ bool isInvalid() const { return !isValid(); }
+
+ /// \brief Determine what kind of name we have.
+ IdKind getKind() const { return Kind; }
+
+ /// \brief Specify that this unqualified-id was parsed as an identifier.
+ ///
+ /// \param Id the parsed identifier.
+ /// \param IdLoc the location of the parsed identifier.
+ void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
+ Kind = IK_Identifier;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = EndLocation = IdLoc;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as an
+ /// operator-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Op the overloaded operator.
+ ///
+ /// \param SymbolLocations the locations of the individual operator symbols
+ /// in the operator.
+ void setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]);
+
+ /// \brief Specify that this unqualified-id was parsed as a
+ /// conversion-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Ty the type to which this conversion function is converting.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConversionFunctionId(SourceLocation OperatorLoc,
+ ParsedType Ty,
+ SourceLocation EndLoc) {
+ Kind = IK_ConversionFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = EndLoc;
+ ConversionFunctionId = Ty;
+ }
+
+ /// \brief Specific that this unqualified-id was parsed as a
+ /// literal-operator-id.
+ ///
+ /// \param Id the parsed identifier.
+ ///
+ /// \param OpLoc the location of the 'operator' keyword.
+ ///
+ /// \param IdLoc the location of the identifier.
+ void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
+ SourceLocation IdLoc) {
+ Kind = IK_LiteralOperatorId;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = OpLoc;
+ EndLocation = IdLoc;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a constructor name.
+ ///
+ /// \param ClassType the class type referred to by the constructor name.
+ ///
+ /// \param ClassNameLoc the location of the class name.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConstructorName(ParsedType ClassType,
+ SourceLocation ClassNameLoc,
+ SourceLocation EndLoc) {
+ Kind = IK_ConstructorName;
+ StartLocation = ClassNameLoc;
+ EndLocation = EndLoc;
+ ConstructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a
+ /// template-id that names a constructor.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setConstructorTemplateId(TemplateIdAnnotation *TemplateId);
+
+ /// \brief Specify that this unqualified-id was parsed as a destructor name.
+ ///
+ /// \param TildeLoc the location of the '~' that introduces the destructor
+ /// name.
+ ///
+ /// \param ClassType the name of the class referred to by the destructor name.
+ void setDestructorName(SourceLocation TildeLoc,
+ ParsedType ClassType,
+ SourceLocation EndLoc) {
+ Kind = IK_DestructorName;
+ StartLocation = TildeLoc;
+ EndLocation = EndLoc;
+ DestructorName = ClassType;
+ }
+
+ /// \brief Specify that this unqualified-id was parsed as a template-id.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setTemplateId(TemplateIdAnnotation *TemplateId);
+
+ /// \brief Return the source range that covers this unqualified-id.
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLocation, EndLocation);
+ }
+};
+
+/// CachedTokens - A set of tokens that has been cached for later
+/// parsing.
+typedef llvm::SmallVector<Token, 4> CachedTokens;
+
+/// DeclaratorChunk - One instance of this struct is used for each type in a
+/// declarator that is parsed.
+///
+/// This is intended to be a small value object.
+struct DeclaratorChunk {
+ enum {
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
+ } Kind;
+
+ /// Loc - The place where this type was defined.
+ SourceLocation Loc;
+ /// EndLoc - If valid, the place where this chunck ends.
+ SourceLocation EndLoc;
+
+ struct TypeInfoCommon {
+ AttributeList *AttrList;
+ };
+
+ struct PointerTypeInfo : TypeInfoCommon {
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+ void destroy() {
+ }
+ };
+
+ struct ReferenceTypeInfo : TypeInfoCommon {
+ /// The type qualifier: restrict. [GNU] C++ extension
+ bool HasRestrict : 1;
+ /// True if this is an lvalue reference, false if it's an rvalue reference.
+ bool LValueRef : 1;
+ void destroy() {
+ }
+ };
+
+ struct ArrayTypeInfo : TypeInfoCommon {
+ /// The type qualifiers for the array: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+
+ /// True if this dimension included the 'static' keyword.
+ bool hasStatic : 1;
+
+ /// True if this dimension was [*]. In this case, NumElts is null.
+ bool isStar : 1;
+
+ /// This is the size of the array, or null if [] or [*] was specified.
+ /// Since the parser is multi-purpose, and we don't want to impose a root
+ /// expression class on all clients, NumElts is untyped.
+ Expr *NumElts;
+
+ void destroy() {}
+ };
+
+ /// ParamInfo - An array of paraminfo objects is allocated whenever a function
+ /// declarator is parsed. There are two interesting styles of arguments here:
+ /// K&R-style identifier lists and parameter type lists. K&R-style identifier
+ /// lists will have information about the identifier, but no type information.
+ /// Parameter type lists will have type info (if the actions module provides
+ /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
+ struct ParamInfo {
+ IdentifierInfo *Ident;
+ SourceLocation IdentLoc;
+ Decl *Param;
+
+ /// DefaultArgTokens - When the parameter's default argument
+ /// cannot be parsed immediately (because it occurs within the
+ /// declaration of a member function), it will be stored here as a
+ /// sequence of tokens to be parsed once the class definition is
+ /// complete. Non-NULL indicates that there is a default argument.
+ CachedTokens *DefaultArgTokens;
+
+ ParamInfo() {}
+ ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
+ Decl *param,
+ CachedTokens *DefArgTokens = 0)
+ : Ident(ident), IdentLoc(iloc), Param(param),
+ DefaultArgTokens(DefArgTokens) {}
+ };
+
+ struct TypeAndRange {
+ ParsedType Ty;
+ SourceRange Range;
+ };
+
+ struct FunctionTypeInfo : TypeInfoCommon {
+ /// hasPrototype - This is true if the function had at least one typed
+ /// argument. If the function is () or (a,b,c), then it has no prototype,
+ /// and is treated as a K&R-style function.
+ unsigned hasPrototype : 1;
+
+ /// isVariadic - If this function has a prototype, and if that
+ /// proto ends with ',...)', this is true. When true, EllipsisLoc
+ /// contains the location of the ellipsis.
+ unsigned isVariadic : 1;
+
+ /// \brief Whether the ref-qualifier (if any) is an lvalue reference.
+ /// Otherwise, it's an rvalue reference.
+ unsigned RefQualifierIsLValueRef : 1;
+
+ /// The type qualifiers: const/volatile/restrict.
+ /// The qualifier bitmask values are the same as in QualType.
+ unsigned TypeQuals : 3;
+
+ /// hasExceptionSpec - True if the function has an exception specification.
+ unsigned hasExceptionSpec : 1;
+
+ /// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
+ unsigned hasAnyExceptionSpec : 1;
+
+ /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
+ unsigned DeleteArgInfo : 1;
+
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ unsigned EllipsisLoc;
+
+ /// NumArgs - This is the number of formal arguments provided for the
+ /// declarator.
+ unsigned NumArgs;
+
+ /// NumExceptions - This is the number of types in the exception-decl, if
+ /// the function has one.
+ unsigned NumExceptions;
+
+ /// \brief The location of the ref-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no ref-qualifier.
+ unsigned RefQualifierLoc;
+
+ /// ThrowLoc - When hasExceptionSpec is true, the location of the throw
+ /// keyword introducing the spec.
+ unsigned ThrowLoc;
+
+ /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
+ /// describe the arguments for this function declarator. This is null if
+ /// there are no arguments specified.
+ ParamInfo *ArgInfo;
+
+ /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange
+ /// objects that contain the types in the function's exception
+ /// specification and their locations.
+ TypeAndRange *Exceptions;
+
+ /// TrailingReturnType - If this isn't null, it's the trailing return type
+ /// specified. This is actually a ParsedType, but stored as void* to
+ /// allow union storage.
+ void *TrailingReturnType;
+
+ /// freeArgs - reset the argument list to having zero arguments. This is
+ /// used in various places for error recovery.
+ void freeArgs() {
+ if (DeleteArgInfo) {
+ delete[] ArgInfo;
+ DeleteArgInfo = false;
+ }
+ NumArgs = 0;
+ }
+
+ void destroy() {
+ if (DeleteArgInfo)
+ delete[] ArgInfo;
+ delete[] Exceptions;
+ }
+
+ /// isKNRPrototype - Return true if this is a K&R style identifier list,
+ /// like "void foo(a,b,c)". In a function definition, this will be followed
+ /// by the argument type definitions.
+ bool isKNRPrototype() const {
+ return !hasPrototype && NumArgs != 0;
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(EllipsisLoc);
+ }
+ SourceLocation getThrowLoc() const {
+ return SourceLocation::getFromRawEncoding(ThrowLoc);
+ }
+
+ /// \brief Retrieve the location of the ref-qualifier, if any.
+ SourceLocation getRefQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(RefQualifierLoc);
+ }
+
+ /// \brief Determine whether this function declaration contains a
+ /// ref-qualifier.
+ bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
+ };
+
+ struct BlockPointerTypeInfo : TypeInfoCommon {
+ /// For now, sema will catch these as invalid.
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+
+ void destroy() {
+ }
+ };
+
+ struct MemberPointerTypeInfo : TypeInfoCommon {
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+ // CXXScopeSpec has a constructor, so it can't be a direct member.
+ // So we need some pointer-aligned storage and a bit of trickery.
+ union {
+ void *Aligner;
+ char Mem[sizeof(CXXScopeSpec)];
+ } ScopeMem;
+ CXXScopeSpec &Scope() {
+ return *reinterpret_cast<CXXScopeSpec*>(ScopeMem.Mem);
+ }
+ const CXXScopeSpec &Scope() const {
+ return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem);
+ }
+ void destroy() {
+ Scope().~CXXScopeSpec();
+ }
+ };
+
+ union {
+ TypeInfoCommon Common;
+ PointerTypeInfo Ptr;
+ ReferenceTypeInfo Ref;
+ ArrayTypeInfo Arr;
+ FunctionTypeInfo Fun;
+ BlockPointerTypeInfo Cls;
+ MemberPointerTypeInfo Mem;
+ };
+
+ void destroy() {
+ switch (Kind) {
+ default: assert(0 && "Unknown decl type!");
+ case DeclaratorChunk::Function: return Fun.destroy();
+ case DeclaratorChunk::Pointer: return Ptr.destroy();
+ case DeclaratorChunk::BlockPointer: return Cls.destroy();
+ case DeclaratorChunk::Reference: return Ref.destroy();
+ case DeclaratorChunk::Array: return Arr.destroy();
+ case DeclaratorChunk::MemberPointer: return Mem.destroy();
+ case DeclaratorChunk::Paren: return;
+ }
+ }
+
+ /// getAttrs - If there are attributes applied to this declaratorchunk, return
+ /// them.
+ const AttributeList *getAttrs() const {
+ return Common.AttrList;
+ }
+
+ AttributeList *&getAttrListRef() {
+ return Common.AttrList;
+ }
+
+ /// getPointer - Return a DeclaratorChunk for a pointer.
+ ///
+ static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ const ParsedAttributes &attrs) {
+ DeclaratorChunk I;
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.AttrList = attrs.getList();
+ return I;
+ }
+
+ /// getReference - Return a DeclaratorChunk for a reference.
+ ///
+ static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
+ const ParsedAttributes &attrs,
+ bool lvalue) {
+ DeclaratorChunk I;
+ I.Kind = Reference;
+ I.Loc = Loc;
+ I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
+ I.Ref.LValueRef = lvalue;
+ I.Ref.AttrList = attrs.getList();
+ return I;
+ }
+
+ /// getArray - Return a DeclaratorChunk for an array.
+ ///
+ static DeclaratorChunk getArray(unsigned TypeQuals,
+ const ParsedAttributes &attrs,
+ bool isStatic, bool isStar, Expr *NumElts,
+ SourceLocation LBLoc, SourceLocation RBLoc) {
+ DeclaratorChunk I;
+ I.Kind = Array;
+ I.Loc = LBLoc;
+ I.EndLoc = RBLoc;
+ I.Arr.AttrList = attrs.getList();
+ I.Arr.TypeQuals = TypeQuals;
+ I.Arr.hasStatic = isStatic;
+ I.Arr.isStar = isStar;
+ I.Arr.NumElts = NumElts;
+ return I;
+ }
+
+ /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+ /// "TheDeclarator" is the declarator that this will be added to.
+ static DeclaratorChunk getFunction(const ParsedAttributes &attrs,
+ bool hasProto, bool isVariadic,
+ SourceLocation EllipsisLoc,
+ ParamInfo *ArgInfo, unsigned NumArgs,
+ unsigned TypeQuals,
+ bool RefQualifierIsLvalueRef,
+ SourceLocation RefQualifierLoc,
+ bool hasExceptionSpec,
+ SourceLocation ThrowLoc,
+ bool hasAnyExceptionSpec,
+ ParsedType *Exceptions,
+ SourceRange *ExceptionRanges,
+ unsigned NumExceptions,
+ SourceLocation LPLoc, SourceLocation RPLoc,
+ Declarator &TheDeclarator,
+ ParsedType TrailingReturnType = ParsedType());
+
+ /// getBlockPointer - Return a DeclaratorChunk for a block.
+ ///
+ static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc,
+ const ParsedAttributes &attrs) {
+ DeclaratorChunk I;
+ I.Kind = BlockPointer;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ I.Cls.AttrList = attrs.getList();
+ return I;
+ }
+
+ static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
+ unsigned TypeQuals,
+ SourceLocation Loc,
+ const ParsedAttributes &attrs) {
+ DeclaratorChunk I;
+ I.Kind = MemberPointer;
+ I.Loc = Loc;
+ I.Mem.TypeQuals = TypeQuals;
+ I.Mem.AttrList = attrs.getList();
+ new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
+ return I;
+ }
+
+ /// getParen - Return a DeclaratorChunk for a paren.
+ ///
+ static DeclaratorChunk getParen(SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ DeclaratorChunk I;
+ I.Kind = Paren;
+ I.Loc = LParenLoc;
+ I.EndLoc = RParenLoc;
+ I.Common.AttrList = 0;
+ return I;
+ }
+
+};
+
+/// Declarator - Information about one declarator, including the parsed type
+/// information and the identifier. When the declarator is fully formed, this
+/// is turned into the appropriate Decl object.
+///
+/// Declarators come in two types: normal declarators and abstract declarators.
+/// Abstract declarators are used when parsing types, and don't have an
+/// identifier. Normal declarators do have ID's.
+///
+/// Instances of this class should be a transient object that lives on the
+/// stack, not objects that are allocated in large quantities on the heap.
+class Declarator {
+public:
+ enum TheContext {
+ FileContext, // File scope declaration.
+ PrototypeContext, // Within a function prototype.
+ KNRTypeListContext, // K&R type definition list for formals.
+ TypeNameContext, // Abstract declarator for types.
+ MemberContext, // Struct/Union field.
+ BlockContext, // Declaration within a block in a function.
+ ForContext, // Declaration within first part of a for loop.
+ ConditionContext, // Condition declaration in a C++ if/switch/while/for.
+ TemplateParamContext,// Within a template parameter list.
+ CXXCatchContext, // C++ catch exception-declaration
+ BlockLiteralContext, // Block literal declarator.
+ TemplateTypeArgContext // Template type argument.
+ };
+
+private:
+ const DeclSpec &DS;
+ CXXScopeSpec SS;
+ UnqualifiedId Name;
+ SourceRange Range;
+
+ /// Context - Where we are parsing this declarator.
+ ///
+ TheContext Context;
+
+ /// DeclTypeInfo - This holds each type that the declarator includes as it is
+ /// parsed. This is pushed from the identifier out, which means that element
+ /// #0 will be the most closely bound to the identifier, and
+ /// DeclTypeInfo.back() will be the least closely bound.
+ llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
+
+ /// InvalidType - Set by Sema::GetTypeForDeclarator().
+ bool InvalidType : 1;
+
+ /// GroupingParens - Set by Parser::ParseParenDeclarator().
+ bool GroupingParens : 1;
+
+ /// AttrList - Attributes.
+ AttributeList *AttrList;
+
+ /// AsmLabel - The asm label, if specified.
+ Expr *AsmLabel;
+
+ /// InlineParams - This is a local array used for the first function decl
+ /// chunk to avoid going to the heap for the common case when we have one
+ /// function chunk in the declarator.
+ DeclaratorChunk::ParamInfo InlineParams[16];
+ bool InlineParamsUsed;
+
+ /// Extension - true if the declaration is preceded by __extension__.
+ bool Extension : 1;
+
+ /// \brief If provided, the source location of the ellipsis used to describe
+ /// this declarator as a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ friend struct DeclaratorChunk;
+
+public:
+ Declarator(const DeclSpec &ds, TheContext C)
+ : DS(ds), Range(ds.getSourceRange()), Context(C),
+ InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
+ GroupingParens(false), AttrList(0), AsmLabel(0),
+ InlineParamsUsed(false), Extension(false) {
+ }
+
+ ~Declarator() {
+ clear();
+ }
+
+ /// getDeclSpec - Return the declaration-specifier that this declarator was
+ /// declared with.
+ const DeclSpec &getDeclSpec() const { return DS; }
+
+ /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This
+ /// should be used with extreme care: declspecs can often be shared between
+ /// multiple declarators, so mutating the DeclSpec affects all of the
+ /// Declarators. This should only be done when the declspec is known to not
+ /// be shared or when in error recovery etc.
+ DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); }
+
+ /// getCXXScopeSpec - Return the C++ scope specifier (global scope or
+ /// nested-name-specifier) that is part of the declarator-id.
+ const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
+ CXXScopeSpec &getCXXScopeSpec() { return SS; }
+
+ /// \brief Retrieve the name specified by this declarator.
+ UnqualifiedId &getName() { return Name; }
+
+ TheContext getContext() const { return Context; }
+
+ /// getSourceRange - Get the source range that spans this declarator.
+ const SourceRange &getSourceRange() const { return Range; }
+
+ void SetSourceRange(SourceRange R) { Range = R; }
+ /// SetRangeBegin - Set the start of the source range to Loc, unless it's
+ /// invalid.
+ void SetRangeBegin(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setBegin(Loc);
+ }
+ /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid.
+ void SetRangeEnd(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setEnd(Loc);
+ }
+ /// ExtendWithDeclSpec - Extend the declarator source range to include the
+ /// given declspec, unless its location is invalid. Adopts the range start if
+ /// the current range start is invalid.
+ void ExtendWithDeclSpec(const DeclSpec &DS) {
+ const SourceRange &SR = DS.getSourceRange();
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(SR.getBegin());
+ if (!SR.getEnd().isInvalid())
+ Range.setEnd(SR.getEnd());
+ }
+
+ /// clear - Reset the contents of this Declarator.
+ void clear() {
+ SS.clear();
+ Name.clear();
+ Range = DS.getSourceRange();
+
+ for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
+ DeclTypeInfo[i].destroy();
+ DeclTypeInfo.clear();
+ AttrList = 0;
+ AsmLabel = 0;
+ InlineParamsUsed = false;
+ }
+
+ /// mayOmitIdentifier - Return true if the identifier is either optional or
+ /// not allowed. This is true for typenames, prototypes, and template
+ /// parameter lists.
+ bool mayOmitIdentifier() const {
+ return Context == TypeNameContext || Context == PrototypeContext ||
+ Context == TemplateParamContext || Context == CXXCatchContext ||
+ Context == BlockLiteralContext || Context == TemplateTypeArgContext;
+ }
+
+ /// mayHaveIdentifier - Return true if the identifier is either optional or
+ /// required. This is true for normal declarators and prototypes, but not
+ /// typenames.
+ bool mayHaveIdentifier() const {
+ return Context != TypeNameContext && Context != BlockLiteralContext &&
+ Context != TemplateTypeArgContext;
+ }
+
+ /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
+ /// followed by a C++ direct initializer, e.g. "int x(1);".
+ bool mayBeFollowedByCXXDirectInit() const {
+ return !hasGroupingParens() &&
+ (Context == FileContext ||
+ Context == BlockContext ||
+ Context == ForContext);
+ }
+
+ /// isPastIdentifier - Return true if we have parsed beyond the point where
+ /// the
+ bool isPastIdentifier() const { return Name.isValid(); }
+
+ /// hasName - Whether this declarator has a name, which might be an
+ /// identifier (accessible via getIdentifier()) or some kind of
+ /// special C++ name (constructor, destructor, etc.).
+ bool hasName() const {
+ return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
+ }
+
+ IdentifierInfo *getIdentifier() const {
+ if (Name.getKind() == UnqualifiedId::IK_Identifier)
+ return Name.Identifier;
+
+ return 0;
+ }
+ SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
+
+ /// \brief Set the name of this declarator to be the given identifier.
+ void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+ Name.setIdentifier(Id, IdLoc);
+ }
+
+ /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+ /// EndLoc, which should be the last token of the chunk.
+ void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// AddInnermostTypeInfo - Add a new innermost chunk to this declarator.
+ void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
+ DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
+ }
+
+ /// getNumTypeObjects() - Return the number of types applied to this
+ /// declarator.
+ unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
+
+ /// Return the specified TypeInfo from this declarator. TypeInfo #0 is
+ /// closest to the identifier.
+ const DeclaratorChunk &getTypeObject(unsigned i) const {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+ DeclaratorChunk &getTypeObject(unsigned i) {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+
+ void DropFirstTypeObject()
+ {
+ assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
+ DeclTypeInfo.front().destroy();
+ DeclTypeInfo.erase(DeclTypeInfo.begin());
+ }
+
+ /// isFunctionDeclarator - This method returns true if the declarator
+ /// is a function declarator (looking through parentheses).
+ /// If true is returned, then the reference type parameter idx is
+ /// assigned with the index of the declaration chunk.
+ bool isFunctionDeclarator(unsigned& idx) const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ switch (DeclTypeInfo[i].Kind) {
+ case DeclaratorChunk::Function:
+ idx = i;
+ return true;
+ case DeclaratorChunk::Paren:
+ continue;
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ return false;
+ }
+ llvm_unreachable("Invalid type chunk");
+ return false;
+ }
+ return false;
+ }
+
+ /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
+ /// this method returns true if the identifier is a function declarator
+ /// (looking through parentheses).
+ bool isFunctionDeclarator() const {
+ unsigned index;
+ return isFunctionDeclarator(index);
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() {
+ assert(isFunctionDeclarator() && "Not a function declarator!");
+ unsigned index = 0;
+ isFunctionDeclarator(index);
+ return DeclTypeInfo[index].Fun;
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const {
+ return const_cast<Declarator*>(this)->getFunctionTypeInfo();
+ }
+
+ /// AddAttributes - simply adds the attribute list to the Declarator.
+ /// These examples both add 3 attributes to "var":
+ /// short int var __attribute__((aligned(16),common,deprecated));
+ /// short int x, __attribute__((aligned(16)) var
+ /// __attribute__((common,deprecated));
+ ///
+ /// Also extends the range of the declarator.
+ void addAttributes(AttributeList *alist, SourceLocation LastLoc) {
+ AttrList = addAttributeLists(AttrList, alist);
+
+ if (!LastLoc.isInvalid())
+ SetRangeEnd(LastLoc);
+ }
+
+ void addAttributes(const ParsedAttributes &attrs) {
+ addAttributes(attrs.getList(), SourceLocation());
+ }
+
+ const AttributeList *getAttributes() const { return AttrList; }
+ AttributeList *getAttributes() { return AttrList; }
+
+ AttributeList *&getAttrListRef() { return AttrList; }
+
+ /// hasAttributes - do we contain any attributes?
+ bool hasAttributes() const {
+ if (getAttributes() || getDeclSpec().hasAttributes()) return true;
+ for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i)
+ if (getTypeObject(i).getAttrs())
+ return true;
+ return false;
+ }
+
+ void setAsmLabel(Expr *E) { AsmLabel = E; }
+ Expr *getAsmLabel() const { return AsmLabel; }
+
+ void setExtension(bool Val = true) { Extension = Val; }
+ bool getExtension() const { return Extension; }
+
+ void setInvalidType(bool Val = true) { InvalidType = Val; }
+ bool isInvalidType() const {
+ return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
+ }
+
+ void setGroupingParens(bool flag) { GroupingParens = flag; }
+ bool hasGroupingParens() const { return GroupingParens; }
+
+ bool hasEllipsis() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
+};
+
+/// FieldDeclarator - This little struct is used to capture information about
+/// structure field declarators, which is basically just a bitfield size.
+struct FieldDeclarator {
+ Declarator D;
+ Expr *BitfieldSize;
+ explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
+ BitfieldSize = 0;
+ }
+};
+
+/// VirtSpecifiers - Represents a C++0x virt-specifier-seq.
+class VirtSpecifiers {
+public:
+ enum Specifier {
+ VS_None = 0,
+ VS_Override = 1,
+ VS_Final = 2,
+ VS_New = 4
+ };
+
+ VirtSpecifiers() : Specifiers(0) { }
+
+ bool SetSpecifier(Specifier VS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isOverrideSpecified() const { return Specifiers & VS_Override; }
+ SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
+
+ bool isFinalSpecified() const { return Specifiers & VS_Final; }
+ SourceLocation getFinalLoc() const { return VS_finalLoc; }
+
+ bool isNewSpecified() const { return Specifiers & VS_New; }
+ SourceLocation getNewLoc() const { return VS_newLoc; }
+
+ void clear() { Specifiers = 0; }
+
+ static const char *getSpecifierName(Specifier VS);
+
+private:
+ unsigned Specifiers;
+
+ SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc;
+};
+
+/// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq.
+class ClassVirtSpecifiers {
+public:
+ enum Specifier {
+ CVS_None = 0,
+ CVS_Final = 1,
+ CVS_Explicit = 2
+ };
+
+ ClassVirtSpecifiers() : Specifiers(0) { }
+
+ bool SetSpecifier(Specifier CVS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isFinalSpecified() const { return Specifiers & CVS_Final; }
+ SourceLocation getFinalLoc() const { return CVS_finalLoc; }
+
+ bool isExplicitSpecified() const { return Specifiers & CVS_Explicit; }
+ SourceLocation getExplicitLoc() const { return CVS_explicitLoc; }
+
+ static const char *getSpecifierName(Specifier CVS);
+
+private:
+ unsigned Specifiers;
+
+ SourceLocation CVS_finalLoc, CVS_explicitLoc;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
new file mode 100644
index 0000000..6e808de
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,189 @@
+//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DelayedDiagnostic class, which is used to
+// record diagnostics that are being conditionally produced during
+// declarator parsing. Certain kinds of diagnostics --- notably
+// deprecation and access control --- are suppressed based on
+// semantic properties of the parsed declaration that aren't known
+// until it is fully parsed.
+//
+// This file also defines AccessedEntity.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+namespace sema {
+
+/// A declaration being accessed, together with information about how
+/// it was accessed.
+class AccessedEntity {
+public:
+ /// A member declaration found through lookup. The target is the
+ /// member.
+ enum MemberNonce { Member };
+
+ /// A hierarchy (base-to-derived or derived-to-base) conversion.
+ /// The target is the base class.
+ enum BaseNonce { Base };
+
+ bool isMemberAccess() const { return IsMember; }
+
+ AccessedEntity(ASTContext &Context,
+ MemberNonce _,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl,
+ QualType BaseObjectType)
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) {
+ }
+
+ AccessedEntity(ASTContext &Context,
+ BaseNonce _,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access)
+ : Access(Access), IsMember(false),
+ Target(BaseClass),
+ NamingClass(DerivedClass),
+ Diag(0, Context.getDiagAllocator()) {
+ }
+
+ bool isQuiet() const { return Diag.getDiagID() == 0; }
+
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // These apply to member decls...
+ NamedDecl *getTargetDecl() const { return Target; }
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+ // ...and these apply to hierarchy conversions.
+ CXXRecordDecl *getBaseClass() const {
+ assert(!IsMember); return cast<CXXRecordDecl>(Target);
+ }
+ CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+ /// Retrieves the base object type, important when accessing
+ /// an instance member.
+ QualType getBaseObjectType() const { return BaseObjectType; }
+
+ /// Sets a diagnostic to be performed. The diagnostic is given
+ /// four (additional) arguments:
+ /// %0 - 0 if the entity was private, 1 if protected
+ /// %1 - the DeclarationName of the entity
+ /// %2 - the TypeDecl type of the naming class
+ /// %3 - the TypeDecl type of the declaring class
+ void setDiag(const PartialDiagnostic &PDiag) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ Diag = PDiag;
+ }
+ PartialDiagnostic &setDiag(unsigned DiagID) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ assert(DiagID && "creating null diagnostic");
+ Diag.Reset(DiagID);
+ return Diag;
+ }
+ const PartialDiagnostic &getDiag() const {
+ return Diag;
+ }
+
+private:
+ unsigned Access : 2;
+ unsigned IsMember : 1;
+ NamedDecl *Target;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+ PartialDiagnostic Diag;
+};
+
+/// A diagnostic message which has been conditionally emitted pending
+/// the complete parsing of the current declaration.
+class DelayedDiagnostic {
+public:
+ enum DDKind { Deprecation, Access };
+
+ unsigned char Kind; // actually a DDKind
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ void destroy() {
+ switch (Kind) {
+ case Access: getAccessData().~AccessedEntity(); break;
+ case Deprecation: break;
+ }
+ }
+
+ static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
+ const NamedDecl *D,
+ llvm::StringRef Msg) {
+ DelayedDiagnostic DD;
+ DD.Kind = Deprecation;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.DeprecationData.Decl = D;
+ DD.DeprecationData.Message = Msg.data();
+ DD.DeprecationData.MessageLen = Msg.size();
+ return DD;
+ }
+
+ static DelayedDiagnostic makeAccess(SourceLocation Loc,
+ const AccessedEntity &Entity) {
+ DelayedDiagnostic DD;
+ DD.Kind = Access;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ new (&DD.getAccessData()) AccessedEntity(Entity);
+ return DD;
+ }
+
+ AccessedEntity &getAccessData() {
+ assert(Kind == Access && "Not an access diagnostic.");
+ return *reinterpret_cast<AccessedEntity*>(AccessData);
+ }
+ const AccessedEntity &getAccessData() const {
+ assert(Kind == Access && "Not an access diagnostic.");
+ return *reinterpret_cast<const AccessedEntity*>(AccessData);
+ }
+
+ const NamedDecl *getDeprecationDecl() const {
+ assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ return DeprecationData.Decl;
+ }
+
+ llvm::StringRef getDeprecationMessage() const {
+ assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ return llvm::StringRef(DeprecationData.Message,
+ DeprecationData.MessageLen);
+ }
+
+private:
+ union {
+ /// Deprecation.
+ struct {
+ const NamedDecl *Decl;
+ const char *Message;
+ size_t MessageLen;
+ } DeprecationData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Designator.h b/contrib/llvm/tools/clang/include/clang/Sema/Designator.h
new file mode 100644
index 0000000..6fe7ab2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Designator.h
@@ -0,0 +1,218 @@
+//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used to represent designators (a la
+// C99 designated initializers) during parsing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
+#define LLVM_CLANG_SEMA_DESIGNATOR_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class Expr;
+class IdentifierInfo;
+class Sema;
+
+/// Designator - A designator in a C99 designated initializer.
+///
+/// This class is a discriminated union which holds the various
+/// different sorts of designators possible. A Designation is an array of
+/// these. An example of a designator are things like this:
+/// [8] .field [47] // C99 designation: 3 designators
+/// [8 ... 47] field: // GNU extensions: 2 designators
+/// These occur in initializers, e.g.:
+/// int a[10] = {2, 4, [8]=9, 10};
+///
+class Designator {
+public:
+ enum DesignatorKind {
+ FieldDesignator, ArrayDesignator, ArrayRangeDesignator
+ };
+private:
+ DesignatorKind Kind;
+
+ struct FieldDesignatorInfo {
+ const IdentifierInfo *II;
+ unsigned DotLoc;
+ unsigned NameLoc;
+ };
+ struct ArrayDesignatorInfo {
+ Expr *Index;
+ unsigned LBracketLoc;
+ mutable unsigned RBracketLoc;
+ };
+ struct ArrayRangeDesignatorInfo {
+ Expr *Start, *End;
+ unsigned LBracketLoc, EllipsisLoc;
+ mutable unsigned RBracketLoc;
+ };
+
+ union {
+ FieldDesignatorInfo FieldInfo;
+ ArrayDesignatorInfo ArrayInfo;
+ ArrayRangeDesignatorInfo ArrayRangeInfo;
+ };
+
+public:
+
+ DesignatorKind getKind() const { return Kind; }
+ bool isFieldDesignator() const { return Kind == FieldDesignator; }
+ bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+ bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+ const IdentifierInfo *getField() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return FieldInfo.II;
+ }
+
+ SourceLocation getDotLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc);
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
+ }
+
+ Expr *getArrayIndex() const {
+ assert(isArrayDesignator() && "Invalid accessor");
+ return ArrayInfo.Index;
+ }
+
+ Expr *getArrayRangeStart() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.Start;
+ }
+ Expr *getArrayRangeEnd() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.End;
+ }
+
+ SourceLocation getLBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc);
+ }
+
+ static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
+ SourceLocation NameLoc) {
+ Designator D;
+ D.Kind = FieldDesignator;
+ D.FieldInfo.II = II;
+ D.FieldInfo.DotLoc = DotLoc.getRawEncoding();
+ D.FieldInfo.NameLoc = NameLoc.getRawEncoding();
+ return D;
+ }
+
+ static Designator getArray(Expr *Index,
+ SourceLocation LBracketLoc) {
+ Designator D;
+ D.Kind = ArrayDesignator;
+ D.ArrayInfo.Index = Index;
+ D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ static Designator getArrayRange(Expr *Start,
+ Expr *End,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc) {
+ Designator D;
+ D.Kind = ArrayRangeDesignator;
+ D.ArrayRangeInfo.Start = Start;
+ D.ArrayRangeInfo.End = End;
+ D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ D.ArrayRangeInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ void setRBracketLoc(SourceLocation RBracketLoc) const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ else
+ ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents
+ /// them from being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in
+ /// this designator.
+ void FreeExprs(Sema &Actions) {}
+};
+
+
+/// Designation - Represent a full designation, which is a sequence of
+/// designators. This class is mostly a helper for InitListDesignations.
+class Designation {
+ /// InitIndex - The index of the initializer expression this is for. For
+ /// example, if the initializer were "{ A, .foo=B, C }" a Designation would
+ /// exist with InitIndex=1, because element #1 has a designation.
+ unsigned InitIndex;
+
+ /// Designators - The actual designators for this initializer.
+ llvm::SmallVector<Designator, 2> Designators;
+
+ Designation(unsigned Idx) : InitIndex(Idx) {}
+public:
+ Designation() : InitIndex(4000) {}
+
+ /// AddDesignator - Add a designator to the end of this list.
+ void AddDesignator(Designator D) {
+ Designators.push_back(D);
+ }
+
+ bool empty() const { return Designators.empty(); }
+
+ unsigned getNumDesignators() const { return Designators.size(); }
+ const Designator &getDesignator(unsigned Idx) const {
+ assert(Idx < Designators.size());
+ return Designators[Idx];
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents them from
+ /// being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in this
+ /// designation.
+ void FreeExprs(Sema &Actions) {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
new file mode 100644
index 0000000..6d7bc63
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -0,0 +1,59 @@
+//===--- ExternalSemaSource.h - External Sema Interface ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalSemaSource interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
+#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
+
+#include "clang/AST/ExternalASTSource.h"
+#include <utility>
+
+namespace clang {
+
+struct ObjCMethodList;
+class Sema;
+
+/// \brief An abstract interface that should be implemented by
+/// external AST sources that also provide information for semantic
+/// analysis.
+class ExternalSemaSource : public ExternalASTSource {
+public:
+ ExternalSemaSource() {
+ ExternalASTSource::SemaSource = true;
+ }
+
+ ~ExternalSemaSource();
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ /// \brief Inform the semantic consumer that Sema is no longer available.
+ virtual void ForgetSema() {}
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ ///
+ /// \returns a pair of Objective-C methods lists containing the
+ /// instance and factory methods, respectively, with this selector.
+ virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ExternalASTSource *Source) {
+ return Source->SemaSource;
+ }
+ static bool classof(const ExternalSemaSource *) { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
new file mode 100644
index 0000000..7e9d338
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
@@ -0,0 +1,198 @@
+//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclContext;
+class DeclarationName;
+class NamedDecl;
+class Scope;
+
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes. It manages the shadowing chains of declaration names and
+/// implements efficent decl lookup based on a declaration name.
+class IdentifierResolver {
+
+ /// IdDeclInfo - Keeps track of information about decls associated
+ /// to a particular declaration name. IdDeclInfos are lazily
+ /// constructed and assigned to a declaration name the first time a
+ /// decl with that declaration name is shadowed in some scope.
+ class IdDeclInfo {
+ public:
+ typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
+
+ inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
+ inline DeclsTy::iterator decls_end() { return Decls.end(); }
+
+ void AddDecl(NamedDecl *D) { Decls.push_back(D); }
+
+ /// RemoveDecl - Remove the decl from the scope chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Replaces the Old declaration with the New declaration. If the
+ /// replacement is successful, returns true. If the old
+ /// declaration was not found, returns false.
+ bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+ private:
+ DeclsTy Decls;
+ };
+
+public:
+
+ /// iterator - Iterate over the decls of a specified declaration name.
+ /// It will walk or not the parent declaration contexts depending on how
+ /// it was instantiated.
+ class iterator {
+ public:
+ typedef NamedDecl * value_type;
+ typedef NamedDecl * reference;
+ typedef NamedDecl * pointer;
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ /// Ptr - There are 3 forms that 'Ptr' represents:
+ /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
+ /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
+ /// same declaration context. (Ptr & 0x3 == 0x1)
+ /// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent
+ /// declaration contexts too. (Ptr & 0x3 == 0x3)
+ uintptr_t Ptr;
+ typedef IdDeclInfo::DeclsTy::iterator BaseIter;
+
+ /// A single NamedDecl. (Ptr & 0x1 == 0)
+ iterator(NamedDecl *D) {
+ Ptr = reinterpret_cast<uintptr_t>(D);
+ assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
+ }
+ /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
+ /// contexts depending on 'LookInParentCtx'.
+ iterator(BaseIter I) {
+ Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
+ }
+
+ bool isIterator() const { return (Ptr & 0x1); }
+
+ BaseIter getIterator() const {
+ assert(isIterator() && "Ptr not an iterator!");
+ return reinterpret_cast<BaseIter>(Ptr & ~0x3);
+ }
+
+ friend class IdentifierResolver;
+
+ void incrementSlowCase();
+ public:
+ iterator() : Ptr(0) {}
+
+ NamedDecl *operator*() const {
+ if (isIterator())
+ return *getIterator();
+ else
+ return reinterpret_cast<NamedDecl*>(Ptr);
+ }
+
+ bool operator==(const iterator &RHS) const {
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const iterator &RHS) const {
+ return Ptr != RHS.Ptr;
+ }
+
+ // Preincrement.
+ iterator& operator++() {
+ if (!isIterator()) // common case.
+ Ptr = 0;
+ else
+ incrementSlowCase();
+ return *this;
+ }
+
+ uintptr_t getAsOpaqueValue() const { return Ptr; }
+
+ static iterator getFromOpaqueValue(uintptr_t P) {
+ iterator Result;
+ Result.Ptr = P;
+ return Result;
+ }
+ };
+
+ /// begin - Returns an iterator for decls with the name 'Name'.
+ static iterator begin(DeclarationName Name);
+
+ /// end - Returns an iterator that has 'finished'.
+ static iterator end() {
+ return iterator();
+ }
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context,
+ Scope *S = 0) const;
+
+ /// AddDecl - Link the decl to its shadowed decl chain.
+ void AddDecl(NamedDecl *D);
+
+ /// RemoveDecl - Unlink the decl from its shadowed decl chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Replace the decl Old with the new declaration New on its
+ /// identifier chain. Returns true if the old declaration was found
+ /// (and, therefore, replaced).
+ bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+
+ /// \brief Link the declaration into the chain of declarations for
+ /// the given identifier.
+ ///
+ /// This is a lower-level routine used by the AST reader to link a
+ /// declaration into a specific IdentifierInfo before the
+ /// declaration actually has a name.
+ void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D);
+
+ explicit IdentifierResolver(const LangOptions &LangOpt);
+ ~IdentifierResolver();
+
+private:
+ const LangOptions &LangOpt;
+
+ class IdDeclInfoMap;
+ IdDeclInfoMap *IdDeclInfos;
+
+ /// FETokenInfo contains a Decl pointer if lower bit == 0.
+ static inline bool isDeclPtr(void *Ptr) {
+ return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+ }
+
+ /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+ static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+ assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+ && "Ptr not a IdDeclInfo* !");
+ return reinterpret_cast<IdDeclInfo*>(
+ reinterpret_cast<uintptr_t>(Ptr) & ~0x1
+ );
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
new file mode 100644
index 0000000..c191565
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -0,0 +1,817 @@
+//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides supporting data types for initialization of objects.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H
+#define LLVM_CLANG_SEMA_INITIALIZATION_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Overload.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class DeclaratorInfo;
+class FieldDecl;
+class FunctionDecl;
+class ParmVarDecl;
+class Sema;
+class TypeLoc;
+class VarDecl;
+
+/// \brief Describes an entity that is being initialized.
+class InitializedEntity {
+public:
+ /// \brief Specifies the kind of entity being initialized.
+ enum EntityKind {
+ /// \brief The entity being initialized is a variable.
+ EK_Variable,
+ /// \brief The entity being initialized is a function parameter.
+ EK_Parameter,
+ /// \brief The entity being initialized is the result of a function call.
+ EK_Result,
+ /// \brief The entity being initialized is an exception object that
+ /// is being thrown.
+ EK_Exception,
+ /// \brief The entity being initialized is a non-static data member
+ /// subobject.
+ EK_Member,
+ /// \brief The entity being initialized is an element of an array.
+ EK_ArrayElement,
+ /// \brief The entity being initialized is an object (or array of
+ /// objects) allocated via new.
+ EK_New,
+ /// \brief The entity being initialized is a temporary object.
+ EK_Temporary,
+ /// \brief The entity being initialized is a base member subobject.
+ EK_Base,
+ /// \brief The entity being initialized is an element of a vector.
+ /// or vector.
+ EK_VectorElement,
+ /// \brief The entity being initialized is a field of block descriptor for
+ /// the copied-in c++ object.
+ EK_BlockElement
+ };
+
+private:
+ /// \brief The kind of entity being initialized.
+ EntityKind Kind;
+
+ /// \brief If non-NULL, the parent entity in which this
+ /// initialization occurs.
+ const InitializedEntity *Parent;
+
+ /// \brief The type of the object or reference being initialized.
+ QualType Type;
+
+ union {
+ /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member,
+ /// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
+ DeclaratorDecl *VariableOrMember;
+
+ /// \brief When Kind == EK_Temporary, the type source information for
+ /// the temporary.
+ TypeSourceInfo *TypeInfo;
+
+ struct {
+ /// \brief When Kind == EK_Result, EK_Exception, or EK_New, the
+ /// location of the 'return', 'throw', or 'new' keyword,
+ /// respectively. When Kind == EK_Temporary, the location where
+ /// the temporary is being created.
+ unsigned Location;
+
+ /// \brief Whether the
+ bool NRVO;
+ } LocAndNRVO;
+
+ /// \brief When Kind == EK_Base, the base specifier that provides the
+ /// base class. The lower bit specifies whether the base is an inherited
+ /// virtual base.
+ uintptr_t Base;
+
+ /// \brief When Kind == EK_ArrayElement or EK_VectorElement, the
+ /// index of the array or vector element being initialized.
+ unsigned Index;
+ };
+
+ InitializedEntity() { }
+
+ /// \brief Create the initialization entity for a variable.
+ InitializedEntity(VarDecl *Var)
+ : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+ VariableOrMember(Var) { }
+
+ /// \brief Create the initialization entity for a parameter.
+ InitializedEntity(ParmVarDecl *Parm)
+ : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
+ VariableOrMember(Parm) { }
+
+ /// \brief Create the initialization entity for the result of a
+ /// function, throwing an object, performing an explicit cast, or
+ /// initializing a parameter for which there is no declaration.
+ InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
+ bool NRVO = false)
+ : Kind(Kind), Parent(0), Type(Type)
+ {
+ LocAndNRVO.Location = Loc.getRawEncoding();
+ LocAndNRVO.NRVO = NRVO;
+ }
+
+ /// \brief Create the initialization entity for a member subobject.
+ InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ VariableOrMember(Member) { }
+
+ /// \brief Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent);
+
+public:
+ /// \brief Create the initialization entity for a variable.
+ static InitializedEntity InitializeVariable(VarDecl *Var) {
+ return InitializedEntity(Var);
+ }
+
+ /// \brief Create the initialization entity for a parameter.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ ParmVarDecl *Parm) {
+ InitializedEntity Res(Parm);
+ Res.Type = Context.getVariableArrayDecayedType(Res.Type);
+ return Res;
+ }
+
+ /// \brief Create the initialization entity for a parameter that is
+ /// only known by its type.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ QualType Type) {
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type = Context.getVariableArrayDecayedType(Type);
+ Entity.Parent = 0;
+ Entity.VariableOrMember = 0;
+ return Entity;
+ }
+
+ /// \brief Create the initialization entity for the result of a function.
+ static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
+ }
+
+ static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
+ }
+
+ /// \brief Create the initialization entity for an exception object.
+ static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO);
+ }
+
+ /// \brief Create the initialization entity for an object allocated via new.
+ static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
+ return InitializedEntity(EK_New, NewLoc, Type);
+ }
+
+ /// \brief Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(QualType Type) {
+ return InitializedEntity(EK_Temporary, SourceLocation(), Type);
+ }
+
+ /// \brief Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
+ InitializedEntity Result(EK_Temporary, SourceLocation(),
+ TypeInfo->getType());
+ Result.TypeInfo = TypeInfo;
+ return Result;
+ }
+
+ /// \brief Create the initialization entity for a base class subobject.
+ static InitializedEntity InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase);
+
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity InitializeMember(FieldDecl *Member,
+ const InitializedEntity *Parent = 0) {
+ return InitializedEntity(Member, Parent);
+ }
+
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity InitializeMember(IndirectFieldDecl *Member,
+ const InitializedEntity *Parent = 0) {
+ return InitializedEntity(Member->getAnonField(), Parent);
+ }
+
+ /// \brief Create the initialization entity for an array element.
+ static InitializedEntity InitializeElement(ASTContext &Context,
+ unsigned Index,
+ const InitializedEntity &Parent) {
+ return InitializedEntity(Context, Index, Parent);
+ }
+
+ /// \brief Determine the kind of initialization.
+ EntityKind getKind() const { return Kind; }
+
+ /// \brief Retrieve the parent of the entity being initialized, when
+ /// the initialization itself is occuring within the context of a
+ /// larger initialization.
+ const InitializedEntity *getParent() const { return Parent; }
+
+ /// \brief Retrieve type being initialized.
+ QualType getType() const { return Type; }
+
+ /// \brief Retrieve complete type-source information for the object being
+ /// constructed, if known.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ if (Kind == EK_Temporary)
+ return TypeInfo;
+
+ return 0;
+ }
+
+ /// \brief Retrieve the name of the entity being initialized.
+ DeclarationName getName() const;
+
+ /// \brief Retrieve the variable, parameter, or field being
+ /// initialized.
+ DeclaratorDecl *getDecl() const;
+
+ /// \brief Determine whether this initialization allows the named return
+ /// value optimization, which also applies to thrown objects.
+ bool allowsNRVO() const;
+
+ /// \brief Retrieve the base specifier.
+ CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return reinterpret_cast<CXXBaseSpecifier *>(Base & ~0x1);
+ }
+
+ /// \brief Return whether the base is an inherited virtual base.
+ bool isInheritedVirtualBase() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base & 0x1;
+ }
+
+ /// \brief Determine the location of the 'return' keyword when initializing
+ /// the result of a function call.
+ SourceLocation getReturnLoc() const {
+ assert(getKind() == EK_Result && "No 'return' location!");
+ return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
+ }
+
+ /// \brief Determine the location of the 'throw' keyword when initializing
+ /// an exception object.
+ SourceLocation getThrowLoc() const {
+ assert(getKind() == EK_Exception && "No 'throw' location!");
+ return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
+ }
+
+ /// \brief If this is already the initializer for an array or vector
+ /// element, sets the element index.
+ void setElementIndex(unsigned Index) {
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement);
+ this->Index = Index;
+ }
+};
+
+/// \brief Describes the kind of initialization being performed, along with
+/// location information for tokens related to the initialization (equal sign,
+/// parentheses).
+class InitializationKind {
+public:
+ /// \brief The kind of initialization being performed.
+ enum InitKind {
+ IK_Direct, ///< Direct initialization
+ IK_Copy, ///< Copy initialization
+ IK_Default, ///< Default initialization
+ IK_Value ///< Value initialization
+ };
+
+private:
+ /// \brief The kind of initialization that we're storing.
+ enum StoredInitKind {
+ SIK_Direct = IK_Direct, ///< Direct initialization
+ SIK_Copy = IK_Copy, ///< Copy initialization
+ SIK_Default = IK_Default, ///< Default initialization
+ SIK_Value = IK_Value, ///< Value initialization
+ SIK_ImplicitValue, ///< Implicit value initialization
+ SIK_DirectCast, ///< Direct initialization due to a cast
+ /// \brief Direct initialization due to a C-style or functional cast.
+ SIK_DirectCStyleOrFunctionalCast
+ };
+
+ /// \brief The kind of initialization being performed.
+ StoredInitKind Kind;
+
+ /// \brief The source locations involved in the initialization.
+ SourceLocation Locations[3];
+
+ InitializationKind(StoredInitKind Kind, SourceLocation Loc1,
+ SourceLocation Loc2, SourceLocation Loc3)
+ : Kind(Kind)
+ {
+ Locations[0] = Loc1;
+ Locations[1] = Loc2;
+ Locations[2] = Loc3;
+ }
+
+public:
+ /// \brief Create a direct initialization.
+ static InitializationKind CreateDirect(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Create a direct initialization due to a cast.
+ static InitializationKind CreateCast(SourceRange TypeRange,
+ bool IsCStyleCast) {
+ return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast
+ : SIK_DirectCast,
+ TypeRange.getBegin(), TypeRange.getBegin(),
+ TypeRange.getEnd());
+ }
+
+ /// \brief Create a copy initialization.
+ static InitializationKind CreateCopy(SourceLocation InitLoc,
+ SourceLocation EqualLoc) {
+ return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc);
+ }
+
+ /// \brief Create a default initialization.
+ static InitializationKind CreateDefault(SourceLocation InitLoc) {
+ return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc);
+ }
+
+ /// \brief Create a value initialization.
+ static InitializationKind CreateValue(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool isImplicit = false) {
+ return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Determine the initialization kind.
+ InitKind getKind() const {
+ if (Kind > SIK_ImplicitValue)
+ return IK_Direct;
+ if (Kind == SIK_ImplicitValue)
+ return IK_Value;
+
+ return (InitKind)Kind;
+ }
+
+ /// \brief Determine whether this initialization is an explicit cast.
+ bool isExplicitCast() const {
+ return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Kind == SIK_DirectCStyleOrFunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is an implicit
+ /// value-initialization, e.g., as occurs during aggregate
+ /// initialization.
+ bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; }
+
+ /// \brief Retrieve the location at which initialization is occurring.
+ SourceLocation getLocation() const { return Locations[0]; }
+
+ /// \brief Retrieve the source range that covers the initialization.
+ SourceRange getRange() const {
+ return SourceRange(Locations[0], Locations[2]);
+ }
+
+ /// \brief Retrieve the location of the equal sign for copy initialization
+ /// (if present).
+ SourceLocation getEqualLoc() const {
+ assert(Kind == SIK_Copy && "Only copy initialization has an '='");
+ return Locations[1];
+ }
+
+ bool isCopyInit() const { return Kind == SIK_Copy; }
+
+ /// \brief Retrieve the source range containing the locations of the open
+ /// and closing parentheses for value and direct initializations.
+ SourceRange getParenRange() const {
+ assert((getKind() == IK_Direct || Kind == SIK_Value) &&
+ "Only direct- and value-initialization have parentheses");
+ return SourceRange(Locations[1], Locations[2]);
+ }
+};
+
+/// \brief Describes the sequence of initializations required to initialize
+/// a given object or reference with a set of arguments.
+class InitializationSequence {
+public:
+ /// \brief Describes the kind of initialization sequence computed.
+ ///
+ /// FIXME: Much of this information is in the initialization steps... why is
+ /// it duplicated here?
+ enum SequenceKind {
+ /// \brief A failed initialization sequence. The failure kind tells what
+ /// happened.
+ FailedSequence = 0,
+
+ /// \brief A dependent initialization, which could not be
+ /// type-checked due to the presence of dependent types or
+ /// dependently-type expressions.
+ DependentSequence,
+
+ /// \brief A user-defined conversion sequence.
+ UserDefinedConversion,
+
+ /// \brief A constructor call.
+ ConstructorInitialization,
+
+ /// \brief A reference binding.
+ ReferenceBinding,
+
+ /// \brief List initialization
+ ListInitialization,
+
+ /// \brief Zero-initialization.
+ ZeroInitialization,
+
+ /// \brief No initialization required.
+ NoInitialization,
+
+ /// \brief Standard conversion sequence.
+ StandardConversion,
+
+ /// \brief C conversion sequence.
+ CAssignment,
+
+ /// \brief String initialization
+ StringInit
+ };
+
+ /// \brief Describes the kind of a particular step in an initialization
+ /// sequence.
+ enum StepKind {
+ /// \brief Resolve the address of an overloaded function to a specific
+ /// function declaration.
+ SK_ResolveAddressOfOverloadedFunction,
+ /// \brief Perform a derived-to-base cast, producing an rvalue.
+ SK_CastDerivedToBaseRValue,
+ /// \brief Perform a derived-to-base cast, producing an xvalue.
+ SK_CastDerivedToBaseXValue,
+ /// \brief Perform a derived-to-base cast, producing an lvalue.
+ SK_CastDerivedToBaseLValue,
+ /// \brief Reference binding to an lvalue.
+ SK_BindReference,
+ /// \brief Reference binding to a temporary.
+ SK_BindReferenceToTemporary,
+ /// \brief An optional copy of a temporary object to another
+ /// temporary object, which is permitted (but not required) by
+ /// C++98/03 but not C++0x.
+ SK_ExtraneousCopyToTemporary,
+ /// \brief Perform a user-defined conversion, either via a conversion
+ /// function or via a constructor.
+ SK_UserConversion,
+ /// \brief Perform a qualification conversion, producing an rvalue.
+ SK_QualificationConversionRValue,
+ /// \brief Perform a qualification conversion, producing an xvalue.
+ SK_QualificationConversionXValue,
+ /// \brief Perform a qualification conversion, producing an lvalue.
+ SK_QualificationConversionLValue,
+ /// \brief Perform an implicit conversion sequence.
+ SK_ConversionSequence,
+ /// \brief Perform list-initialization
+ SK_ListInitialization,
+ /// \brief Perform initialization via a constructor.
+ SK_ConstructorInitialization,
+ /// \brief Zero-initialize the object
+ SK_ZeroInitialization,
+ /// \brief C assignment
+ SK_CAssignment,
+ /// \brief Initialization by string
+ SK_StringInit,
+ /// \brief An initialization that "converts" an Objective-C object
+ /// (not a point to an object) to another Objective-C object type.
+ SK_ObjCObjectConversion
+ };
+
+ /// \brief A single step in the initialization sequence.
+ class Step {
+ public:
+ /// \brief The kind of conversion or initialization step we are taking.
+ StepKind Kind;
+
+ // \brief The type that results from this initialization.
+ QualType Type;
+
+ union {
+ /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// SK_UserConversion, the function that the expression should be
+ /// resolved to or the conversion function to call, respectively.
+ ///
+ /// Always a FunctionDecl.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ struct {
+ FunctionDecl *Function;
+ DeclAccessPair FoundDecl;
+ } Function;
+
+ /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+ /// sequence
+ ImplicitConversionSequence *ICS;
+ };
+
+ void Destroy();
+ };
+
+private:
+ /// \brief The kind of initialization sequence computed.
+ enum SequenceKind SequenceKind;
+
+ /// \brief Steps taken by this initialization.
+ llvm::SmallVector<Step, 4> Steps;
+
+public:
+ /// \brief Describes why initialization failed.
+ enum FailureKind {
+ /// \brief Too many initializers provided for a reference.
+ FK_TooManyInitsForReference,
+ /// \brief Array must be initialized with an initializer list.
+ FK_ArrayNeedsInitList,
+ /// \brief Array must be initialized with an initializer list or a
+ /// string literal.
+ FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Cannot resolve the address of an overloaded function.
+ FK_AddressOfOverloadFailed,
+ /// \brief Overloading due to reference initialization failed.
+ FK_ReferenceInitOverloadFailed,
+ /// \brief Non-const lvalue reference binding to a temporary.
+ FK_NonConstLValueReferenceBindingToTemporary,
+ /// \brief Non-const lvalue reference binding to an lvalue of unrelated
+ /// type.
+ FK_NonConstLValueReferenceBindingToUnrelated,
+ /// \brief Rvalue reference binding to an lvalue.
+ FK_RValueReferenceBindingToLValue,
+ /// \brief Reference binding drops qualifiers.
+ FK_ReferenceInitDropsQualifiers,
+ /// \brief Reference binding failed.
+ FK_ReferenceInitFailed,
+ /// \brief Implicit conversion failed.
+ FK_ConversionFailed,
+ /// \brief Too many initializers for scalar
+ FK_TooManyInitsForScalar,
+ /// \brief Reference initialization from an initializer list
+ FK_ReferenceBindingToInitList,
+ /// \brief Initialization of some unused destination type with an
+ /// initializer list.
+ FK_InitListBadDestinationType,
+ /// \brief Overloading for a user-defined conversion failed.
+ FK_UserConversionOverloadFailed,
+ /// \brief Overloaded for initialization by constructor failed.
+ FK_ConstructorOverloadFailed,
+ /// \brief Default-initialization of a 'const' object.
+ FK_DefaultInitOfConst,
+ /// \brief Initialization of an incomplete type.
+ FK_Incomplete
+ };
+
+private:
+ /// \brief The reason why initialization failued.
+ FailureKind Failure;
+
+ /// \brief The failed result of overload resolution.
+ OverloadingResult FailedOverloadResult;
+
+ /// \brief The candidate set created when initialization failed.
+ OverloadCandidateSet FailedCandidateSet;
+
+ /// \brief Prints a follow-up note that highlights the location of
+ /// the initialized entity, if it's remote.
+ void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity);
+
+public:
+ /// \brief Try to perform initialization of the given entity, creating a
+ /// record of the steps required to perform the initialization.
+ ///
+ /// The generated initialization sequence will either contain enough
+ /// information to diagnose
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization.
+ ///
+ /// \param NumArgs the number of arguments provided for initialization.
+ InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args,
+ unsigned NumArgs);
+
+ ~InitializationSequence();
+
+ /// \brief Perform the actual initialization of the given entity based on
+ /// the computed initialization sequence.
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization, ownership of
+ /// which is transfered into the routine.
+ ///
+ /// \param ResultType if non-NULL, will be set to the type of the
+ /// initialized object, which is the type of the declaration in most
+ /// cases. However, when the initialized object is a variable of
+ /// incomplete array type and the initializer is an initializer
+ /// list, this type will be set to the completed array type.
+ ///
+ /// \returns an expression that performs the actual object initialization, if
+ /// the initialization is well-formed. Otherwise, emits diagnostics
+ /// and returns an invalid expression.
+ ExprResult Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType = 0);
+
+ /// \brief Diagnose an potentially-invalid initialization sequence.
+ ///
+ /// \returns true if the initialization sequence was ill-formed,
+ /// false otherwise.
+ bool Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs);
+
+ /// \brief Determine the kind of initialization sequence computed.
+ enum SequenceKind getKind() const { return SequenceKind; }
+
+ /// \brief Set the kind of sequence computed.
+ void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
+
+ /// \brief Determine whether the initialization sequence is valid.
+ operator bool() const { return SequenceKind != FailedSequence; }
+
+ typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator;
+ step_iterator step_begin() const { return Steps.begin(); }
+ step_iterator step_end() const { return Steps.end(); }
+
+ /// \brief Determine whether this initialization is a direct reference
+ /// binding (C++ [dcl.init.ref]).
+ bool isDirectReferenceBinding() const;
+
+ /// \brief Determine whether this initialization failed due to an ambiguity.
+ bool isAmbiguous() const;
+
+ /// \brief Determine whether this initialization is direct call to a
+ /// constructor.
+ bool isConstructorInitialization() const;
+
+ /// \brief Add a new step in the initialization that resolves the address
+ /// of an overloaded function to a specific function declaration.
+ ///
+ /// \param Function the function to which the overloaded function reference
+ /// resolves.
+ void AddAddressOverloadResolutionStep(FunctionDecl *Function,
+ DeclAccessPair Found);
+
+ /// \brief Add a new step in the initialization that performs a derived-to-
+ /// base cast.
+ ///
+ /// \param BaseType the base type to which we will be casting.
+ ///
+ /// \param IsLValue true if the result of this cast will be treated as
+ /// an lvalue.
+ void AddDerivedToBaseCastStep(QualType BaseType,
+ ExprValueKind Category);
+
+ /// \brief Add a new step binding a reference to an object.
+ ///
+ /// \param BindingTemporary True if we are binding a reference to a temporary
+ /// object (thereby extending its lifetime); false if we are binding to an
+ /// lvalue or an lvalue treated as an rvalue.
+ ///
+ /// \param UnnecessaryCopy True if we should check for a copy
+ /// constructor for a completely unnecessary but
+ void AddReferenceBindingStep(QualType T, bool BindingTemporary);
+
+ /// \brief Add a new step that makes an extraneous copy of the input
+ /// to a temporary of the same class type.
+ ///
+ /// This extraneous copy only occurs during reference binding in
+ /// C++98/03, where we are permitted (but not required) to introduce
+ /// an extra copy. At a bare minimum, we must check that we could
+ /// call the copy constructor, and produce a diagnostic if the copy
+ /// constructor is inaccessible or no copy constructor matches.
+ //
+ /// \param T The type of the temporary being created.
+ void AddExtraneousCopyToTemporary(QualType T);
+
+ /// \brief Add a new step invoking a conversion function, which is either
+ /// a constructor or a conversion function.
+ void AddUserConversionStep(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ QualType T);
+
+ /// \brief Add a new step that performs a qualification conversion to the
+ /// given type.
+ void AddQualificationConversionStep(QualType Ty,
+ ExprValueKind Category);
+
+ /// \brief Add a new step that applies an implicit conversion sequence.
+ void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+ QualType T);
+
+ /// \brief Add a list-initialiation step
+ void AddListInitializationStep(QualType T);
+
+ /// \brief Add a constructor-initialization step.
+ void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
+ QualType T);
+
+ /// \brief Add a zero-initialization step.
+ void AddZeroInitializationStep(QualType T);
+
+ /// \brief Add a C assignment step.
+ //
+ // FIXME: It isn't clear whether this should ever be needed;
+ // ideally, we would handle everything needed in C in the common
+ // path. However, that isn't the case yet.
+ void AddCAssignmentStep(QualType T);
+
+ /// \brief Add a string init step.
+ void AddStringInitStep(QualType T);
+
+ /// \brief Add an Objective-C object conversion step, which is
+ /// always a no-op.
+ void AddObjCObjectConversionStep(QualType T);
+
+ /// \brief Note that this initialization sequence failed.
+ void SetFailed(FailureKind Failure) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ }
+
+ /// \brief Note that this initialization sequence failed due to failed
+ /// overload resolution.
+ void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
+
+ /// \brief Retrieve a reference to the candidate set when overload
+ /// resolution fails.
+ OverloadCandidateSet &getFailedCandidateSet() {
+ return FailedCandidateSet;
+ }
+
+ /// brief Get the overloading result, for when the initialization
+ /// sequence failed due to a bad overload.
+ OverloadingResult getFailedOverloadResult() const {
+ return FailedOverloadResult;
+ }
+
+ /// \brief Determine why initialization failed.
+ FailureKind getFailureKind() const {
+ assert(getKind() == FailedSequence && "Not an initialization failure!");
+ return Failure;
+ }
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(llvm::raw_ostream &OS) const;
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// standard error, for debugging purposes.
+ void dump() const;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_INITIALIZATION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
new file mode 100644
index 0000000..aa58d14
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
@@ -0,0 +1,671 @@
+//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LookupResult class, which is integral to
+// Sema's name-lookup subsystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LOOKUP_H
+#define LLVM_CLANG_SEMA_LOOKUP_H
+
+#include "clang/Sema/Sema.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+
+/// @brief Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+class LookupResult {
+public:
+ enum LookupResultKind {
+ /// @brief No entity found met the criteria.
+ NotFound = 0,
+
+ /// @brief No entity found met the criteria within the current
+ /// instantiation,, but there were dependent base classes of the
+ /// current instantiation that could not be searched.
+ NotFoundInCurrentInstantiation,
+
+ /// @brief Name lookup found a single declaration that met the
+ /// criteria. getFoundDecl() will return this declaration.
+ Found,
+
+ /// @brief Name lookup found a set of overloaded functions that
+ /// met the criteria.
+ FoundOverloaded,
+
+ /// @brief Name lookup found an unresolvable value declaration
+ /// and cannot yet complete. This only happens in C++ dependent
+ /// contexts with dependent using declarations.
+ FoundUnresolvedValue,
+
+ /// @brief Name lookup results in an ambiguity; use
+ /// getAmbiguityKind to figure out what kind of ambiguity
+ /// we have.
+ Ambiguous
+ };
+
+ enum AmbiguityKind {
+ /// Name lookup results in an ambiguity because multiple
+ /// entities that meet the lookup criteria were found in
+ /// subobjects of different types. For example:
+ /// @code
+ /// struct A { void f(int); }
+ /// struct B { void f(double); }
+ /// struct C : A, B { };
+ /// void test(C c) {
+ /// c.f(0); // error: A::f and B::f come from subobjects of different
+ /// // types. overload resolution is not performed.
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjectTypes,
+
+ /// Name lookup results in an ambiguity because multiple
+ /// nonstatic entities that meet the lookup criteria were found
+ /// in different subobjects of the same type. For example:
+ /// @code
+ /// struct A { int x; };
+ /// struct B : A { };
+ /// struct C : A { };
+ /// struct D : B, C { };
+ /// int test(D d) {
+ /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjects,
+
+ /// Name lookup results in an ambiguity because multiple definitions
+ /// of entity that meet the lookup criteria were found in different
+ /// declaration contexts.
+ /// @code
+ /// namespace A {
+ /// int i;
+ /// namespace B { int i; }
+ /// int test() {
+ /// using namespace B;
+ /// return i; // error 'i' is found in namespace A and A::B
+ /// }
+ /// }
+ /// @endcode
+ AmbiguousReference,
+
+ /// Name lookup results in an ambiguity because an entity with a
+ /// tag name was hidden by an entity with an ordinary name from
+ /// a different context.
+ /// @code
+ /// namespace A { struct Foo {}; }
+ /// namespace B { void Foo(); }
+ /// namespace C {
+ /// using namespace A;
+ /// using namespace B;
+ /// }
+ /// void test() {
+ /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+ /// // different namespace
+ /// }
+ /// @endcode
+ AmbiguousTagHiding
+ };
+
+ /// A little identifier for flagging temporary lookup results.
+ enum TemporaryToken {
+ Temporary
+ };
+
+ typedef UnresolvedSetImpl::iterator iterator;
+
+ LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
+ Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(SemaRef),
+ NameInfo(NameInfo),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {
+ configure();
+ }
+
+ // TODO: consider whether this constructor should be restricted to take
+ // as input a const IndentifierInfo* (instead of Name),
+ // forcing other cases towards the constructor taking a DNInfo.
+ LookupResult(Sema &SemaRef, DeclarationName Name,
+ SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(SemaRef),
+ NameInfo(Name, NameLoc),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {
+ configure();
+ }
+
+ /// Creates a temporary lookup result, initializing its core data
+ /// using the information from another result. Diagnostics are always
+ /// disabled.
+ LookupResult(TemporaryToken _, const LookupResult &Other)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(Other.SemaRef),
+ NameInfo(Other.NameInfo),
+ LookupKind(Other.LookupKind),
+ IDNS(Other.IDNS),
+ Redecl(Other.Redecl),
+ HideTags(Other.HideTags),
+ Diagnose(false)
+ {}
+
+ ~LookupResult() {
+ if (Diagnose) diagnose();
+ if (Paths) deletePaths(Paths);
+ }
+
+ /// Gets the name info to look up.
+ const DeclarationNameInfo &getLookupNameInfo() const {
+ return NameInfo;
+ }
+
+ /// \brief Sets the name info to look up.
+ void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
+ this->NameInfo = NameInfo;
+ }
+
+ /// Gets the name to look up.
+ DeclarationName getLookupName() const {
+ return NameInfo.getName();
+ }
+
+ /// \brief Sets the name to look up.
+ void setLookupName(DeclarationName Name) {
+ NameInfo.setName(Name);
+ }
+
+ /// Gets the kind of lookup to perform.
+ Sema::LookupNameKind getLookupKind() const {
+ return LookupKind;
+ }
+
+ /// True if this lookup is just looking for an existing declaration.
+ bool isForRedeclaration() const {
+ return Redecl;
+ }
+
+ /// Sets whether tag declarations should be hidden by non-tag
+ /// declarations during resolution. The default is true.
+ void setHideTags(bool Hide) {
+ HideTags = Hide;
+ }
+
+ bool isAmbiguous() const {
+ return getResultKind() == Ambiguous;
+ }
+
+ /// Determines if this names a single result which is not an
+ /// unresolved value using decl. If so, it is safe to call
+ /// getFoundDecl().
+ bool isSingleResult() const {
+ return getResultKind() == Found;
+ }
+
+ /// Determines if the results are overloaded.
+ bool isOverloadedResult() const {
+ return getResultKind() == FoundOverloaded;
+ }
+
+ bool isUnresolvableResult() const {
+ return getResultKind() == FoundUnresolvedValue;
+ }
+
+ LookupResultKind getResultKind() const {
+ sanity();
+ return ResultKind;
+ }
+
+ AmbiguityKind getAmbiguityKind() const {
+ assert(isAmbiguous());
+ return Ambiguity;
+ }
+
+ const UnresolvedSetImpl &asUnresolvedSet() const {
+ return Decls;
+ }
+
+ iterator begin() const { return iterator(Decls.begin()); }
+ iterator end() const { return iterator(Decls.end()); }
+
+ /// \brief Return true if no decls were found
+ bool empty() const { return Decls.empty(); }
+
+ /// \brief Return the base paths structure that's associated with
+ /// these results, or null if none is.
+ CXXBasePaths *getBasePaths() const {
+ return Paths;
+ }
+
+ /// \brief Tests whether the given declaration is acceptable.
+ bool isAcceptableDecl(NamedDecl *D) const {
+ return D->isInIdentifierNamespace(IDNS);
+ }
+
+ /// \brief Returns the identifier namespace mask for this lookup.
+ unsigned getIdentifierNamespace() const {
+ return IDNS;
+ }
+
+ /// \brief Returns whether these results arose from performing a
+ /// lookup into a class.
+ bool isClassLookup() const {
+ return NamingClass != 0;
+ }
+
+ /// \brief Returns the 'naming class' for this lookup, i.e. the
+ /// class which was looked into to find these results.
+ ///
+ /// C++0x [class.access.base]p5:
+ /// The access to a member is affected by the class in which the
+ /// member is named. This naming class is the class in which the
+ /// member name was looked up and found. [Note: this class can be
+ /// explicit, e.g., when a qualified-id is used, or implicit,
+ /// e.g., when a class member access operator (5.2.5) is used
+ /// (including cases where an implicit "this->" is added). If both
+ /// a class member access operator and a qualified-id are used to
+ /// name the member (as in p->T::m), the class naming the member
+ /// is the class named by the nested-name-specifier of the
+ /// qualified-id (that is, T). -- end note ]
+ ///
+ /// This is set by the lookup routines when they find results in a class.
+ CXXRecordDecl *getNamingClass() const {
+ return NamingClass;
+ }
+
+ /// \brief Sets the 'naming class' for this lookup.
+ void setNamingClass(CXXRecordDecl *Record) {
+ NamingClass = Record;
+ }
+
+ /// \brief Returns the base object type associated with this lookup;
+ /// important for [class.protected]. Most lookups do not have an
+ /// associated base object.
+ QualType getBaseObjectType() const {
+ return BaseObjectType;
+ }
+
+ /// \brief Sets the base object type for this lookup.
+ void setBaseObjectType(QualType T) {
+ BaseObjectType = T;
+ }
+
+ /// \brief Add a declaration to these results with its natural access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D) {
+ addDecl(D, D->getAccess());
+ }
+
+ /// \brief Add a declaration to these results with the given access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ Decls.addDecl(D, AS);
+ ResultKind = Found;
+ }
+
+ /// \brief Add all the declarations from another set of lookup
+ /// results.
+ void addAllDecls(const LookupResult &Other) {
+ Decls.append(Other.Decls.begin(), Other.Decls.end());
+ ResultKind = Found;
+ }
+
+ /// \brief Determine whether no result was found because we could not
+ /// search into dependent base classes of the current instantiation.
+ bool wasNotFoundInCurrentInstantiation() const {
+ return ResultKind == NotFoundInCurrentInstantiation;
+ }
+
+ /// \brief Note that while no result was found in the current instantiation,
+ /// there were dependent base classes that could not be searched.
+ void setNotFoundInCurrentInstantiation() {
+ assert(ResultKind == NotFound && Decls.empty());
+ ResultKind = NotFoundInCurrentInstantiation;
+ }
+
+ /// \brief Resolves the result kind of the lookup, possibly hiding
+ /// decls.
+ ///
+ /// This should be called in any environment where lookup might
+ /// generate multiple lookup results.
+ void resolveKind();
+
+ /// \brief Re-resolves the result kind of the lookup after a set of
+ /// removals has been performed.
+ void resolveKindAfterFilter() {
+ if (Decls.empty()) {
+ if (ResultKind != NotFoundInCurrentInstantiation)
+ ResultKind = NotFound;
+
+ if (Paths) {
+ deletePaths(Paths);
+ Paths = 0;
+ }
+ } else {
+ AmbiguityKind SavedAK = Ambiguity;
+ ResultKind = Found;
+ resolveKind();
+
+ // If we didn't make the lookup unambiguous, restore the old
+ // ambiguity kind.
+ if (ResultKind == Ambiguous) {
+ Ambiguity = SavedAK;
+ } else if (Paths) {
+ deletePaths(Paths);
+ Paths = 0;
+ }
+ }
+ }
+
+ template <class DeclClass>
+ DeclClass *getAsSingle() const {
+ if (getResultKind() != Found) return 0;
+ return dyn_cast<DeclClass>(getFoundDecl());
+ }
+
+ /// \brief Fetch the unique decl found by this lookup. Asserts
+ /// that one was found.
+ ///
+ /// This is intended for users who have examined the result kind
+ /// and are certain that there is only one result.
+ NamedDecl *getFoundDecl() const {
+ assert(getResultKind() == Found
+ && "getFoundDecl called on non-unique result");
+ return (*begin())->getUnderlyingDecl();
+ }
+
+ /// Fetches a representative decl. Useful for lazy diagnostics.
+ NamedDecl *getRepresentativeDecl() const {
+ assert(!Decls.empty() && "cannot get representative of empty set");
+ return *begin();
+ }
+
+ /// \brief Asks if the result is a single tag decl.
+ bool isSingleTagDecl() const {
+ return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
+ }
+
+ /// \brief Make these results show that the name was found in
+ /// base classes of different types.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// distinct base classes of the same type.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+
+ /// \brief Make these results show that the name was found in
+ /// different contexts and a tag decl was hidden by an ordinary
+ /// decl in a different context.
+ void setAmbiguousQualifiedTagHiding() {
+ setAmbiguous(AmbiguousTagHiding);
+ }
+
+ /// \brief Clears out any current state.
+ void clear() {
+ ResultKind = NotFound;
+ Decls.clear();
+ if (Paths) deletePaths(Paths);
+ Paths = NULL;
+ }
+
+ /// \brief Clears out any current state and re-initializes for a
+ /// different kind of lookup.
+ void clear(Sema::LookupNameKind Kind) {
+ clear();
+ LookupKind = Kind;
+ configure();
+ }
+
+ /// \brief Change this lookup's redeclaration kind.
+ void setRedeclarationKind(Sema::RedeclarationKind RK) {
+ Redecl = RK;
+ configure();
+ }
+
+ void print(llvm::raw_ostream &);
+
+ /// Suppress the diagnostics that would normally fire because of this
+ /// lookup. This happens during (e.g.) redeclaration lookups.
+ void suppressDiagnostics() {
+ Diagnose = false;
+ }
+
+ /// Determines whether this lookup is suppressing diagnostics.
+ bool isSuppressingDiagnostics() const {
+ return !Diagnose;
+ }
+
+ /// Sets a 'context' source range.
+ void setContextRange(SourceRange SR) {
+ NameContextRange = SR;
+ }
+
+ /// Gets the source range of the context of this name; for C++
+ /// qualified lookups, this is the source range of the scope
+ /// specifier.
+ SourceRange getContextRange() const {
+ return NameContextRange;
+ }
+
+ /// Gets the location of the identifier. This isn't always defined:
+ /// sometimes we're doing lookups on synthesized names.
+ SourceLocation getNameLoc() const {
+ return NameInfo.getLoc();
+ }
+
+ /// \brief Get the Sema object that this lookup result is searching
+ /// with.
+ Sema &getSema() const { return SemaRef; }
+
+ /// A class for iterating through a result set and possibly
+ /// filtering out results. The results returned are possibly
+ /// sugared.
+ class Filter {
+ LookupResult &Results;
+ LookupResult::iterator I;
+ bool Changed;
+ bool CalledDone;
+
+ friend class LookupResult;
+ Filter(LookupResult &Results)
+ : Results(Results), I(Results.begin()), Changed(false), CalledDone(false)
+ {}
+
+ public:
+ ~Filter() {
+ assert(CalledDone &&
+ "LookupResult::Filter destroyed without done() call");
+ }
+
+ bool hasNext() const {
+ return I != Results.end();
+ }
+
+ NamedDecl *next() {
+ assert(I != Results.end() && "next() called on empty filter");
+ return *I++;
+ }
+
+ /// Erase the last element returned from this iterator.
+ void erase() {
+ Results.Decls.erase(--I);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one, preserving the
+ /// access bits.
+ void replace(NamedDecl *D) {
+ Results.Decls.replace(I-1, D);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one.
+ void replace(NamedDecl *D, AccessSpecifier AS) {
+ Results.Decls.replace(I-1, D, AS);
+ Changed = true;
+ }
+
+ void done() {
+ assert(!CalledDone && "done() called twice");
+ CalledDone = true;
+
+ if (Changed)
+ Results.resolveKindAfterFilter();
+ }
+ };
+
+ /// Create a filter for this result set.
+ Filter makeFilter() {
+ return Filter(*this);
+ }
+
+private:
+ void diagnose() {
+ if (isAmbiguous())
+ SemaRef.DiagnoseAmbiguousLookup(*this);
+ else if (isClassLookup() && SemaRef.getLangOptions().AccessControl)
+ SemaRef.CheckLookupAccess(*this);
+ }
+
+ void setAmbiguous(AmbiguityKind AK) {
+ ResultKind = Ambiguous;
+ Ambiguity = AK;
+ }
+
+ void addDeclsFromBasePaths(const CXXBasePaths &P);
+ void configure();
+
+ // Sanity checks.
+ void sanity() const;
+
+ bool sanityCheckUnresolved() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (isa<UnresolvedUsingValueDecl>(*I))
+ return true;
+ return false;
+ }
+
+ static void deletePaths(CXXBasePaths *);
+
+ // Results.
+ LookupResultKind ResultKind;
+ AmbiguityKind Ambiguity; // ill-defined unless ambiguous
+ UnresolvedSet<8> Decls;
+ CXXBasePaths *Paths;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+
+ // Parameters.
+ Sema &SemaRef;
+ DeclarationNameInfo NameInfo;
+ SourceRange NameContextRange;
+ Sema::LookupNameKind LookupKind;
+ unsigned IDNS; // set by configure()
+
+ bool Redecl;
+
+ /// \brief True if tag declarations should be hidden if non-tags
+ /// are present
+ bool HideTags;
+
+ bool Diagnose;
+};
+
+ /// \brief Consumes visible declarations found when searching for
+ /// all visible names within a given scope or context.
+ ///
+ /// This abstract class is meant to be subclassed by clients of \c
+ /// Sema::LookupVisibleDecls(), each of which should override the \c
+ /// FoundDecl() function to process declarations as they are found.
+ class VisibleDeclConsumer {
+ public:
+ /// \brief Destroys the visible declaration consumer.
+ virtual ~VisibleDeclConsumer();
+
+ /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// declaration visible from the current scope or context.
+ ///
+ /// \param ND the declaration found.
+ ///
+ /// \param Hiding a declaration that hides the declaration \p ND,
+ /// or NULL if no such declaration exists.
+ ///
+ /// \param InBaseClass whether this declaration was found in base
+ /// class of the context we searched.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
+ bool InBaseClass) = 0;
+ };
+
+/// \brief A class for storing results from argument-dependent lookup.
+class ADLResult {
+private:
+ /// A map from canonical decls to the 'most recent' decl.
+ llvm::DenseMap<NamedDecl*, NamedDecl*> Decls;
+
+public:
+ /// Adds a new ADL candidate to this map.
+ void insert(NamedDecl *D);
+
+ /// Removes any data associated with a given decl.
+ void erase(NamedDecl *D) {
+ Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
+ }
+
+ class iterator {
+ typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator;
+ inner_iterator iter;
+
+ friend class ADLResult;
+ iterator(const inner_iterator &iter) : iter(iter) {}
+ public:
+ iterator() {}
+
+ iterator &operator++() { ++iter; return *this; }
+ iterator operator++(int) { return iterator(iter++); }
+
+ NamedDecl *operator*() const { return iter->second; }
+
+ bool operator==(const iterator &other) const { return iter == other.iter; }
+ bool operator!=(const iterator &other) const { return iter != other.iter; }
+ };
+
+ iterator begin() { return iterator(Decls.begin()); }
+ iterator end() { return iterator(Decls.end()); }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
new file mode 100644
index 0000000..225c137
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,38 @@
+//===--- ObjCMethodList.h - A singly linked list of methods -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCMethodList, a singly-linked list of methods.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+#define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+
+namespace clang {
+
+class ObjCMethodDecl;
+
+/// ObjCMethodList - a linked list of methods with different signatures.
+struct ObjCMethodList {
+ ObjCMethodDecl *Method;
+ ObjCMethodList *Next;
+
+ ObjCMethodList() {
+ Method = 0;
+ Next = 0;
+ }
+ ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
+ Method = M;
+ Next = C;
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
new file mode 100644
index 0000000..3ce3513
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
@@ -0,0 +1,672 @@
+//===--- Overload.h - C++ Overloading ---------------------------*- 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 data structures and types used in C++
+// overload resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OVERLOAD_H
+#define LLVM_CLANG_SEMA_OVERLOAD_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class ASTContext;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class FunctionDecl;
+ class Sema;
+
+ /// OverloadingResult - Capture the result of performing overload
+ /// resolution.
+ enum OverloadingResult {
+ OR_Success, ///< Overload resolution succeeded.
+ OR_No_Viable_Function, ///< No viable function found.
+ OR_Ambiguous, ///< Ambiguous candidates found.
+ OR_Deleted ///< Succeeded, but refers to a deleted function.
+ };
+
+ enum OverloadCandidateDisplayKind {
+ /// Requests that all candidates be shown. Viable candidates will
+ /// be printed first.
+ OCD_AllCandidates,
+
+ /// Requests that only viable candidates be shown.
+ OCD_ViableCandidates
+ };
+
+ /// ImplicitConversionKind - The kind of implicit conversion used to
+ /// convert an argument to a parameter's type. The enumerator values
+ /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
+ /// better conversion kinds have smaller values.
+ enum ImplicitConversionKind {
+ ICK_Identity = 0, ///< Identity conversion (no conversion)
+ ICK_Lvalue_To_Rvalue, ///< Lvalue-to-rvalue conversion (C++ 4.1)
+ ICK_Array_To_Pointer, ///< Array-to-pointer conversion (C++ 4.2)
+ ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3)
+ ICK_NoReturn_Adjustment, ///< Removal of noreturn from a type (Clang)
+ ICK_Qualification, ///< Qualification conversions (C++ 4.4)
+ ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5)
+ ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6)
+ ICK_Complex_Promotion, ///< Complex promotions (Clang extension)
+ ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7)
+ ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8)
+ ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6)
+ ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9)
+ ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10)
+ ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11)
+ ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12)
+ ICK_Compatible_Conversion, ///< Conversions between compatible types in C99
+ ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics])
+ ICK_Vector_Conversion, ///< Vector conversions
+ ICK_Vector_Splat, ///< A vector splat from an arithmetic type
+ ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
+ ICK_Block_Pointer_Conversion, ///< Block Pointer conversions
+ ICK_Num_Conversion_Kinds ///< The number of conversion kinds
+ };
+
+ /// ImplicitConversionCategory - The category of an implicit
+ /// conversion kind. The enumerator values match with Table 9 of
+ /// (C++ 13.3.3.1.1) and are listed such that better conversion
+ /// categories have smaller values.
+ enum ImplicitConversionCategory {
+ ICC_Identity = 0, ///< Identity
+ ICC_Lvalue_Transformation, ///< Lvalue transformation
+ ICC_Qualification_Adjustment, ///< Qualification adjustment
+ ICC_Promotion, ///< Promotion
+ ICC_Conversion ///< Conversion
+ };
+
+ ImplicitConversionCategory
+ GetConversionCategory(ImplicitConversionKind Kind);
+
+ /// ImplicitConversionRank - The rank of an implicit conversion
+ /// kind. The enumerator values match with Table 9 of (C++
+ /// 13.3.3.1.1) and are listed such that better conversion ranks
+ /// have smaller values.
+ enum ImplicitConversionRank {
+ ICR_Exact_Match = 0, ///< Exact Match
+ ICR_Promotion, ///< Promotion
+ ICR_Conversion, ///< Conversion
+ ICR_Complex_Real_Conversion ///< Complex <-> Real conversion
+ };
+
+ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
+
+ /// StandardConversionSequence - represents a standard conversion
+ /// sequence (C++ 13.3.3.1.1). A standard conversion sequence
+ /// contains between zero and three conversions. If a particular
+ /// conversion is not needed, it will be set to the identity conversion
+ /// (ICK_Identity). Note that the three conversions are
+ /// specified as separate members (rather than in an array) so that
+ /// we can keep the size of a standard conversion sequence to a
+ /// single word.
+ class StandardConversionSequence {
+ public:
+ /// First -- The first conversion can be an lvalue-to-rvalue
+ /// conversion, array-to-pointer conversion, or
+ /// function-to-pointer conversion.
+ ImplicitConversionKind First : 8;
+
+ /// Second - The second conversion can be an integral promotion,
+ /// floating point promotion, integral conversion, floating point
+ /// conversion, floating-integral conversion, pointer conversion,
+ /// pointer-to-member conversion, or boolean conversion.
+ ImplicitConversionKind Second : 8;
+
+ /// Third - The third conversion can be a qualification conversion.
+ ImplicitConversionKind Third : 8;
+
+ /// \brief Whether this is the deprecated conversion of a
+ /// string literal to a pointer to non-const character data
+ /// (C++ 4.2p2).
+ unsigned DeprecatedStringLiteralToCharPtr : 1;
+
+ /// IncompatibleObjC - Whether this is an Objective-C conversion
+ /// that we should warn about (if we actually use it).
+ unsigned IncompatibleObjC : 1;
+
+ /// ReferenceBinding - True when this is a reference binding
+ /// (C++ [over.ics.ref]).
+ unsigned ReferenceBinding : 1;
+
+ /// DirectBinding - True when this is a reference binding that is a
+ /// direct binding (C++ [dcl.init.ref]).
+ unsigned DirectBinding : 1;
+
+ /// \brief Whether this is an lvalue reference binding (otherwise, it's
+ /// an rvalue reference binding).
+ unsigned IsLvalueReference : 1;
+
+ /// \brief Whether we're binding to a function lvalue.
+ unsigned BindsToFunctionLvalue : 1;
+
+ /// \brief Whether we're binding to an rvalue.
+ unsigned BindsToRvalue : 1;
+
+ /// \brief Whether this binds an implicit object argument to a
+ /// non-static member function without a ref-qualifier.
+ unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1;
+
+ /// FromType - The type that this conversion is converting
+ /// from. This is an opaque pointer that can be translated into a
+ /// QualType.
+ void *FromTypePtr;
+
+ /// ToType - The types that this conversion is converting to in
+ /// each step. This is an opaque pointer that can be translated
+ /// into a QualType.
+ void *ToTypePtrs[3];
+
+ /// CopyConstructor - The copy constructor that is used to perform
+ /// this conversion, when the conversion is actually just the
+ /// initialization of an object via copy constructor. Such
+ /// conversions are either identity conversions or derived-to-base
+ /// conversions.
+ CXXConstructorDecl *CopyConstructor;
+
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(unsigned Idx, QualType T) {
+ assert(Idx < 3 && "To type index is out of range");
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ }
+ void setAllToTypes(QualType T) {
+ ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[1] = ToTypePtrs[0];
+ ToTypePtrs[2] = ToTypePtrs[0];
+ }
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType(unsigned Idx) const {
+ assert(Idx < 3 && "To type index is out of range");
+ return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
+ }
+
+ void setAsIdentityConversion();
+
+ bool isIdentityConversion() const {
+ return First == ICK_Identity && Second == ICK_Identity &&
+ Third == ICK_Identity;
+ }
+
+ ImplicitConversionRank getRank() const;
+ bool isPointerConversionToBool() const;
+ bool isPointerConversionToVoidPointer(ASTContext& Context) const;
+ void DebugPrint() const;
+ };
+
+ /// UserDefinedConversionSequence - Represents a user-defined
+ /// conversion sequence (C++ 13.3.3.1.2).
+ struct UserDefinedConversionSequence {
+ /// Before - Represents the standard conversion that occurs before
+ /// the actual user-defined conversion. (C++ 13.3.3.1.2p1):
+ ///
+ /// If the user-defined conversion is specified by a constructor
+ /// (12.3.1), the initial standard conversion sequence converts
+ /// the source type to the type required by the argument of the
+ /// constructor. If the user-defined conversion is specified by
+ /// a conversion function (12.3.2), the initial standard
+ /// conversion sequence converts the source type to the implicit
+ /// object parameter of the conversion function.
+ StandardConversionSequence Before;
+
+ /// EllipsisConversion - When this is true, it means user-defined
+ /// conversion sequence starts with a ... (elipsis) conversion, instead of
+ /// a standard conversion. In this case, 'Before' field must be ignored.
+ // FIXME. I much rather put this as the first field. But there seems to be
+ // a gcc code gen. bug which causes a crash in a test. Putting it here seems
+ // to work around the crash.
+ bool EllipsisConversion : 1;
+
+ /// After - Represents the standard conversion that occurs after
+ /// the actual user-defined conversion.
+ StandardConversionSequence After;
+
+ /// ConversionFunction - The function that will perform the
+ /// user-defined conversion.
+ FunctionDecl* ConversionFunction;
+
+ /// \brief The declaration that we found via name lookup, which might be
+ /// the same as \c ConversionFunction or it might be a using declaration
+ /// that refers to \c ConversionFunction.
+ NamedDecl *FoundConversionFunction;
+
+ void DebugPrint() const;
+ };
+
+ /// Represents an ambiguous user-defined conversion sequence.
+ struct AmbiguousConversionSequence {
+ typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet;
+
+ void *FromTypePtr;
+ void *ToTypePtr;
+ char Buffer[sizeof(ConversionSet)];
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType() const {
+ return QualType::getFromOpaquePtr(ToTypePtr);
+ }
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+ ConversionSet &conversions() {
+ return *reinterpret_cast<ConversionSet*>(Buffer);
+ }
+
+ const ConversionSet &conversions() const {
+ return *reinterpret_cast<const ConversionSet*>(Buffer);
+ }
+
+ void addConversion(FunctionDecl *D) {
+ conversions().push_back(D);
+ }
+
+ typedef ConversionSet::iterator iterator;
+ iterator begin() { return conversions().begin(); }
+ iterator end() { return conversions().end(); }
+
+ typedef ConversionSet::const_iterator const_iterator;
+ const_iterator begin() const { return conversions().begin(); }
+ const_iterator end() const { return conversions().end(); }
+
+ void construct();
+ void destruct();
+ void copyFrom(const AmbiguousConversionSequence &);
+ };
+
+ /// BadConversionSequence - Records information about an invalid
+ /// conversion sequence.
+ struct BadConversionSequence {
+ enum FailureKind {
+ no_conversion,
+ unrelated_class,
+ suppressed_user,
+ bad_qualifiers,
+ lvalue_ref_to_rvalue,
+ rvalue_ref_to_lvalue
+ };
+
+ // This can be null, e.g. for implicit object arguments.
+ Expr *FromExpr;
+
+ FailureKind Kind;
+
+ private:
+ // The type we're converting from (an opaque QualType).
+ void *FromTy;
+
+ // The type we're converting to (an opaque QualType).
+ void *ToTy;
+
+ public:
+ void init(FailureKind K, Expr *From, QualType To) {
+ init(K, From->getType(), To);
+ FromExpr = From;
+ }
+ void init(FailureKind K, QualType From, QualType To) {
+ Kind = K;
+ FromExpr = 0;
+ setFromType(From);
+ setToType(To);
+ }
+
+ QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); }
+ QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); }
+
+ void setFromExpr(Expr *E) {
+ FromExpr = E;
+ setFromType(E->getType());
+ }
+ void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
+ };
+
+ /// ImplicitConversionSequence - Represents an implicit conversion
+ /// sequence, which may be a standard conversion sequence
+ /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
+ /// or an ellipsis conversion sequence (C++ 13.3.3.1.3).
+ class ImplicitConversionSequence {
+ public:
+ /// Kind - The kind of implicit conversion sequence. BadConversion
+ /// specifies that there is no conversion from the source type to
+ /// the target type. AmbiguousConversion represents the unique
+ /// ambiguous conversion (C++0x [over.best.ics]p10).
+ enum Kind {
+ StandardConversion = 0,
+ UserDefinedConversion,
+ AmbiguousConversion,
+ EllipsisConversion,
+ BadConversion
+ };
+
+ private:
+ enum {
+ Uninitialized = BadConversion + 1
+ };
+
+ /// ConversionKind - The kind of implicit conversion sequence.
+ unsigned ConversionKind;
+
+ void setKind(Kind K) {
+ destruct();
+ ConversionKind = K;
+ }
+
+ void destruct() {
+ if (ConversionKind == AmbiguousConversion) Ambiguous.destruct();
+ }
+
+ public:
+ union {
+ /// When ConversionKind == StandardConversion, provides the
+ /// details of the standard conversion sequence.
+ StandardConversionSequence Standard;
+
+ /// When ConversionKind == UserDefinedConversion, provides the
+ /// details of the user-defined conversion sequence.
+ UserDefinedConversionSequence UserDefined;
+
+ /// When ConversionKind == AmbiguousConversion, provides the
+ /// details of the ambiguous conversion.
+ AmbiguousConversionSequence Ambiguous;
+
+ /// When ConversionKind == BadConversion, provides the details
+ /// of the bad conversion.
+ BadConversionSequence Bad;
+ };
+
+ ImplicitConversionSequence() : ConversionKind(Uninitialized) {}
+ ~ImplicitConversionSequence() {
+ destruct();
+ }
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind)
+ {
+ switch (ConversionKind) {
+ case Uninitialized: break;
+ case StandardConversion: Standard = Other.Standard; break;
+ case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+ case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+ case EllipsisConversion: break;
+ case BadConversion: Bad = Other.Bad; break;
+ }
+ }
+
+ ImplicitConversionSequence &
+ operator=(const ImplicitConversionSequence &Other) {
+ destruct();
+ new (this) ImplicitConversionSequence(Other);
+ return *this;
+ }
+
+ Kind getKind() const {
+ assert(isInitialized() && "querying uninitialized conversion");
+ return Kind(ConversionKind);
+ }
+
+ /// \brief Return a ranking of the implicit conversion sequence
+ /// kind, where smaller ranks represent better conversion
+ /// sequences.
+ ///
+ /// In particular, this routine gives user-defined conversion
+ /// sequences and ambiguous conversion sequences the same rank,
+ /// per C++ [over.best.ics]p10.
+ unsigned getKindRank() const {
+ switch (getKind()) {
+ case StandardConversion:
+ return 0;
+
+ case UserDefinedConversion:
+ case AmbiguousConversion:
+ return 1;
+
+ case EllipsisConversion:
+ return 2;
+
+ case BadConversion:
+ return 3;
+ }
+
+ return 3;
+ }
+
+ bool isBad() const { return getKind() == BadConversion; }
+ bool isStandard() const { return getKind() == StandardConversion; }
+ bool isEllipsis() const { return getKind() == EllipsisConversion; }
+ bool isAmbiguous() const { return getKind() == AmbiguousConversion; }
+ bool isUserDefined() const { return getKind() == UserDefinedConversion; }
+
+ /// Determines whether this conversion sequence has been
+ /// initialized. Most operations should never need to query
+ /// uninitialized conversions and should assert as above.
+ bool isInitialized() const { return ConversionKind != Uninitialized; }
+
+ /// Sets this sequence as a bad conversion for an explicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ Expr *FromExpr, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromExpr, ToType);
+ }
+
+ /// Sets this sequence as a bad conversion for an implicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ QualType FromType, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromType, ToType);
+ }
+
+ void setStandard() { setKind(StandardConversion); }
+ void setEllipsis() { setKind(EllipsisConversion); }
+ void setUserDefined() { setKind(UserDefinedConversion); }
+ void setAmbiguous() {
+ if (ConversionKind == AmbiguousConversion) return;
+ ConversionKind = AmbiguousConversion;
+ Ambiguous.construct();
+ }
+
+ // The result of a comparison between implicit conversion
+ // sequences. Use Sema::CompareImplicitConversionSequences to
+ // actually perform the comparison.
+ enum CompareKind {
+ Better = -1,
+ Indistinguishable = 0,
+ Worse = 1
+ };
+
+ void DiagnoseAmbiguousConversion(Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const;
+
+ void DebugPrint() const;
+ };
+
+ enum OverloadFailureKind {
+ ovl_fail_too_many_arguments,
+ ovl_fail_too_few_arguments,
+ ovl_fail_bad_conversion,
+ ovl_fail_bad_deduction,
+
+ /// This conversion candidate was not considered because it
+ /// duplicates the work of a trivial or derived-to-base
+ /// conversion.
+ ovl_fail_trivial_conversion,
+
+ /// This conversion candidate is not viable because its result
+ /// type is not implicitly convertible to the desired type.
+ ovl_fail_bad_final_conversion,
+
+ /// This conversion function template specialization candidate is not
+ /// viable because the final conversion was not an exact match.
+ ovl_fail_final_conversion_not_exact
+ };
+
+ /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
+ struct OverloadCandidate {
+ /// Function - The actual function that this candidate
+ /// represents. When NULL, this is a built-in candidate
+ /// (C++ [over.oper]) or a surrogate for a conversion to a
+ /// function pointer or reference (C++ [over.call.object]).
+ FunctionDecl *Function;
+
+ /// FoundDecl - The original declaration that was looked up /
+ /// invented / otherwise found, together with its access.
+ /// Might be a UsingShadowDecl or a FunctionTemplateDecl.
+ DeclAccessPair FoundDecl;
+
+ // BuiltinTypes - Provides the return and parameter types of a
+ // built-in overload candidate. Only valid when Function is NULL.
+ struct {
+ QualType ResultTy;
+ QualType ParamTypes[3];
+ } BuiltinTypes;
+
+ /// Surrogate - The conversion function for which this candidate
+ /// is a surrogate, but only if IsSurrogate is true.
+ CXXConversionDecl *Surrogate;
+
+ /// Conversions - The conversion sequences used to convert the
+ /// function arguments to the function parameters.
+ llvm::SmallVector<ImplicitConversionSequence, 4> Conversions;
+
+ /// Viable - True to indicate that this overload candidate is viable.
+ bool Viable;
+
+ /// IsSurrogate - True to indicate that this candidate is a
+ /// surrogate for a conversion to a function pointer or reference
+ /// (C++ [over.call.object]).
+ bool IsSurrogate;
+
+ /// IgnoreObjectArgument - True to indicate that the first
+ /// argument's conversion, which for this function represents the
+ /// implicit object argument, should be ignored. This will be true
+ /// when the candidate is a static member function (where the
+ /// implicit object argument is just a placeholder) or a
+ /// non-static member function when the call doesn't have an
+ /// object argument.
+ bool IgnoreObjectArgument;
+
+ /// FailureKind - The reason why this candidate is not viable.
+ /// Actually an OverloadFailureKind.
+ unsigned char FailureKind;
+
+ /// \brief The number of call arguments that were explicitly provided,
+ /// to be used while performing partial ordering of function templates.
+ unsigned ExplicitCallArguments;
+
+ /// A structure used to record information about a failed
+ /// template argument deduction.
+ struct DeductionFailureInfo {
+ // A Sema::TemplateDeductionResult.
+ unsigned Result;
+
+ /// \brief Opaque pointer containing additional data about
+ /// this deduction failure.
+ void *Data;
+
+ /// \brief Retrieve the template parameter this deduction failure
+ /// refers to, if any.
+ TemplateParameter getTemplateParameter();
+
+ /// \brief Retrieve the template argument list associated with this
+ /// deduction failure, if any.
+ TemplateArgumentList *getTemplateArgumentList();
+
+ /// \brief Return the first template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getFirstArg();
+
+ /// \brief Return the second template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getSecondArg();
+
+ /// \brief Free any memory associated with this deduction failure.
+ void Destroy();
+ };
+
+ union {
+ DeductionFailureInfo DeductionFailure;
+
+ /// FinalConversion - For a conversion function (where Function is
+ /// a CXXConversionDecl), the standard conversion that occurs
+ /// after the call to the overload candidate to convert the result
+ /// of calling the conversion function to the required type.
+ StandardConversionSequence FinalConversion;
+ };
+
+ /// hasAmbiguousConversion - Returns whether this overload
+ /// candidate requires an ambiguous conversion or not.
+ bool hasAmbiguousConversion() const {
+ for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator
+ I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+ if (!I->isInitialized()) return false;
+ if (I->isAmbiguous()) return true;
+ }
+ return false;
+ }
+ };
+
+ /// OverloadCandidateSet - A set of overload candidates, used in C++
+ /// overload resolution (C++ 13.3).
+ class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
+ typedef llvm::SmallVector<OverloadCandidate, 16> inherited;
+ llvm::SmallPtrSet<Decl *, 16> Functions;
+
+ SourceLocation Loc;
+
+ OverloadCandidateSet(const OverloadCandidateSet &);
+ OverloadCandidateSet &operator=(const OverloadCandidateSet &);
+
+ public:
+ OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Determine when this overload candidate will be new to the
+ /// overload set.
+ bool isNewCandidate(Decl *F) {
+ return Functions.insert(F->getCanonicalDecl());
+ }
+
+ /// \brief Clear out all of the candidates.
+ void clear();
+
+ ~OverloadCandidateSet() { clear(); }
+
+ /// Find the best viable function on this overload set, if it exists.
+ OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
+ OverloadCandidateSet::iterator& Best,
+ bool UserDefinedConversion = false);
+
+ void NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ Expr **Args, unsigned NumArgs,
+ const char *Opc = 0,
+ SourceLocation Loc = SourceLocation());
+ };
+
+ bool isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate& Cand1,
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc,
+ bool UserDefinedConversion = false);
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
new file mode 100644
index 0000000..5f2f0eb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
@@ -0,0 +1,465 @@
+//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
+#define LLVM_CLANG_SEMA_OWNERSHIP_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class Attr;
+ class CXXCtorInitializer;
+ class CXXBaseSpecifier;
+ class Decl;
+ class DeclGroupRef;
+ class Expr;
+ class NestedNameSpecifier;
+ class QualType;
+ class Sema;
+ class Stmt;
+ class TemplateName;
+ class TemplateParameterList;
+
+ /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
+ /// Parser doesn't know about but that Sema or another client does. The UID
+ /// template argument is used to make sure that "Decl" pointers are not
+ /// compatible with "Type" pointers for example.
+ template <class PtrTy>
+ class OpaquePtr {
+ void *Ptr;
+ explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
+
+ typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
+
+ public:
+ OpaquePtr() : Ptr(0) {}
+
+ static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
+
+ template <typename T> T* getAs() const {
+ return get();
+ }
+
+ template <typename T> T getAsVal() const {
+ return get();
+ }
+
+ PtrTy get() const {
+ return Traits::getFromVoidPointer(Ptr);
+ }
+
+ void set(PtrTy P) {
+ Ptr = Traits::getAsVoidPointer(P);
+ }
+
+ operator bool() const { return Ptr != 0; }
+
+ void *getAsOpaquePtr() const { return Ptr; }
+ static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
+ };
+
+ /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
+ /// in a union.
+ template <class T> struct UnionOpaquePtr {
+ void *Ptr;
+
+ static UnionOpaquePtr make(OpaquePtr<T> P) {
+ UnionOpaquePtr OP = { P.getAsOpaquePtr() };
+ return OP;
+ }
+
+ OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
+ operator OpaquePtr<T>() const { return get(); }
+
+ UnionOpaquePtr &operator=(OpaquePtr<T> P) {
+ Ptr = P.getAsOpaquePtr();
+ return *this;
+ }
+ };
+}
+
+namespace llvm {
+ template <class T>
+ class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
+ public:
+ static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
+ // FIXME: Doesn't work? return P.getAs< void >();
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
+ return clang::OpaquePtr<T>::getFromOpaquePtr(P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+
+ template <class T>
+ struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; };
+}
+
+
+
+// -------------------------- About Move Emulation -------------------------- //
+// The smart pointer classes in this file attempt to emulate move semantics
+// as they appear in C++0x with rvalue references. Since C++03 doesn't have
+// rvalue references, some tricks are needed to get similar results.
+// Move semantics in C++0x have the following properties:
+// 1) "Moving" means transferring the value of an object to another object,
+// similar to copying, but without caring what happens to the old object.
+// In particular, this means that the new object can steal the old object's
+// resources instead of creating a copy.
+// 2) Since moving can modify the source object, it must either be explicitly
+// requested by the user, or the modifications must be unnoticeable.
+// 3) As such, C++0x moving is only allowed in three contexts:
+// * By explicitly using std::move() to request it.
+// * From a temporary object, since that object cannot be accessed
+// afterwards anyway, thus making the state unobservable.
+// * On function return, since the object is not observable afterwards.
+//
+// To sum up: moving from a named object should only be possible with an
+// explicit std::move(), or on function return. Moving from a temporary should
+// be implicitly done. Moving from a const object is forbidden.
+//
+// The emulation is not perfect, and has the following shortcomings:
+// * move() is not in namespace std.
+// * move() is required on function return.
+// * There are difficulties with implicit conversions.
+// * Microsoft's compiler must be given the /Za switch to successfully compile.
+//
+// -------------------------- Implementation -------------------------------- //
+// The move emulation relies on the peculiar reference binding semantics of
+// C++03: as a rule, a non-const reference may not bind to a temporary object,
+// except for the implicit object parameter in a member function call, which
+// can refer to a temporary even when not being const.
+// The moveable object has five important functions to facilitate moving:
+// * A private, unimplemented constructor taking a non-const reference to its
+// own class. This constructor serves a two-fold purpose.
+// - It prevents the creation of a copy constructor that takes a const
+// reference. Temporaries would be able to bind to the argument of such a
+// constructor, and that would be bad.
+// - Named objects will bind to the non-const reference, but since it's
+// private, this will fail to compile. This prevents implicit moving from
+// named objects.
+// There's also a copy assignment operator for the same purpose.
+// * An implicit, non-const conversion operator to a special mover type. This
+// type represents the rvalue reference of C++0x. Being a non-const member,
+// its implicit this parameter can bind to temporaries.
+// * A constructor that takes an object of this mover type. This constructor
+// performs the actual move operation. There is an equivalent assignment
+// operator.
+// There is also a free move() function that takes a non-const reference to
+// an object and returns a temporary. Internally, this function uses explicit
+// constructor calls to move the value from the referenced object to the return
+// value.
+//
+// There are now three possible scenarios of use.
+// * Copying from a const object. Constructor overload resolution will find the
+// non-const copy constructor, and the move constructor. The first is not
+// viable because the const object cannot be bound to the non-const reference.
+// The second fails because the conversion to the mover object is non-const.
+// Moving from a const object fails as intended.
+// * Copying from a named object. Constructor overload resolution will select
+// the non-const copy constructor, but fail as intended, because this
+// constructor is private.
+// * Copying from a temporary. Constructor overload resolution cannot select
+// the non-const copy constructor, because the temporary cannot be bound to
+// the non-const reference. It thus selects the move constructor. The
+// temporary can be bound to the implicit this parameter of the conversion
+// operator, because of the special binding rule. Construction succeeds.
+// Note that the Microsoft compiler, as an extension, allows binding
+// temporaries against non-const references. The compiler thus selects the
+// non-const copy constructor and fails, because the constructor is private.
+// Passing /Za (disable extensions) disables this behaviour.
+// The free move() function is used to move from a named object.
+//
+// Note that when passing an object of a different type (the classes below
+// have OwningResult and OwningPtr, which should be mixable), you get a problem.
+// Argument passing and function return use copy initialization rules. The
+// effect of this is that, when the source object is not already of the target
+// type, the compiler will first seek a way to convert the source object to the
+// target type, and only then attempt to copy the resulting object. This means
+// that when passing an OwningResult where an OwningPtr is expected, the
+// compiler will first seek a conversion from OwningResult to OwningPtr, then
+// copy the OwningPtr. The resulting conversion sequence is:
+// OwningResult object -> ResultMover -> OwningResult argument to
+// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
+// This conversion sequence is too complex to be allowed. Thus the special
+// move_* functions, which help the compiler out with some explicit
+// conversions.
+
+namespace clang {
+ // Basic
+ class DiagnosticBuilder;
+
+ // Determines whether the low bit of the result pointer for the
+ // given UID is always zero. If so, ActionResult will use that bit
+ // for it's "invalid" flag.
+ template<class Ptr>
+ struct IsResultPtrLowBitFree {
+ static const bool value = false;
+ };
+
+ /// ActionResult - This structure is used while parsing/acting on
+ /// expressions, stmts, etc. It encapsulates both the object returned by
+ /// the action, plus a sense of whether or not it is valid.
+ /// When CompressInvalid is true, the "invalid" flag will be
+ /// stored in the low bit of the Val pointer.
+ template<class PtrTy,
+ bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
+ class ActionResult {
+ PtrTy Val;
+ bool Invalid;
+
+ public:
+ ActionResult(bool Invalid = false)
+ : Val(PtrTy()), Invalid(Invalid) {}
+ ActionResult(PtrTy val) : Val(val), Invalid(false) {}
+ ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return Invalid; }
+ bool isUsable() const { return !Invalid && Val; }
+
+ PtrTy get() const { return Val; }
+ PtrTy release() const { return Val; }
+ PtrTy take() const { return Val; }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) { Val = V; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ Val = RHS;
+ Invalid = false;
+ return *this;
+ }
+ };
+
+ // This ActionResult partial specialization places the "invalid"
+ // flag into the low bit of the pointer.
+ template<typename PtrTy>
+ class ActionResult<PtrTy, true> {
+ // A pointer whose low bit is 1 if this result is invalid, 0
+ // otherwise.
+ uintptr_t PtrWithInvalid;
+ typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
+ public:
+ ActionResult(bool Invalid = false)
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
+
+ ActionResult(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return PtrWithInvalid & 0x01; }
+ bool isUsable() const { return PtrWithInvalid > 0x01; }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+ PtrTy take() const { return get(); }
+ PtrTy release() const { return get(); }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ void *VP = PtrTraits::getAsVoidPointer(RHS);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ return *this;
+ }
+ };
+
+ /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
+ /// the individual pointers, not the array holding them.
+ template <typename PtrTy> class ASTMultiPtr;
+
+ template <class PtrTy>
+ class ASTMultiPtr {
+ PtrTy *Nodes;
+ unsigned Count;
+
+ public:
+ // Normal copying implicitly defined
+ ASTMultiPtr() : Nodes(0), Count(0) {}
+ explicit ASTMultiPtr(Sema &) : Nodes(0), Count(0) {}
+ ASTMultiPtr(Sema &, PtrTy *nodes, unsigned count)
+ : Nodes(nodes), Count(count) {}
+ // Fake mover in Parse/AstGuard.h needs this:
+ ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {}
+
+ /// Access to the raw pointers.
+ PtrTy *get() const { return Nodes; }
+
+ /// Access to the count.
+ unsigned size() const { return Count; }
+
+ PtrTy *release() {
+ return Nodes;
+ }
+ };
+
+ class ParsedTemplateArgument;
+
+ class ASTTemplateArgsPtr {
+ ParsedTemplateArgument *Args;
+ mutable unsigned Count;
+
+ public:
+ ASTTemplateArgsPtr(Sema &actions, ParsedTemplateArgument *args,
+ unsigned count) :
+ Args(args), Count(count) { }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
+ Args(Other.Args), Count(Other.Count) {
+ }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
+ Args = Other.Args;
+ Count = Other.Count;
+ return *this;
+ }
+
+ ParsedTemplateArgument *getArgs() const { return Args; }
+ unsigned size() const { return Count; }
+
+ void reset(ParsedTemplateArgument *args, unsigned count) {
+ Args = args;
+ Count = count;
+ }
+
+ const ParsedTemplateArgument &operator[](unsigned Arg) const;
+
+ ParsedTemplateArgument *release() const {
+ return Args;
+ }
+ };
+
+ /// \brief A small vector that owns a set of AST nodes.
+ template <class PtrTy, unsigned N = 8>
+ class ASTOwningVector : public llvm::SmallVector<PtrTy, N> {
+ ASTOwningVector(ASTOwningVector &); // do not implement
+ ASTOwningVector &operator=(ASTOwningVector &); // do not implement
+
+ public:
+ explicit ASTOwningVector(Sema &Actions)
+ { }
+
+ PtrTy *take() {
+ return &this->front();
+ }
+
+ template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); }
+ };
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef ASTOwningVector<Stmt*, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef ASTOwningVector<Expr*, 12> ExprVector;
+
+ template <class T, unsigned N> inline
+ ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) {
+ return ASTMultiPtr<T>(vec.take(), vec.size());
+ }
+
+ // These versions are hopefully no-ops.
+ template <class T, bool C>
+ inline ActionResult<T,C> move(ActionResult<T,C> &ptr) {
+ return ptr;
+ }
+
+ template <class T> inline
+ ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) {
+ return ptr;
+ }
+
+ // We can re-use the low bit of expression, statement, base, and
+ // member-initializer pointers for the "invalid" flag of
+ // ActionResult.
+ template<> struct IsResultPtrLowBitFree<Expr*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<Stmt*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
+ static const bool value = true;
+ };
+
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ typedef OpaquePtr<QualType> ParsedType;
+ typedef UnionOpaquePtr<QualType> UnionParsedType;
+
+ typedef ActionResult<Expr*> ExprResult;
+ typedef ActionResult<Stmt*> StmtResult;
+ typedef ActionResult<ParsedType> TypeResult;
+ typedef ActionResult<CXXBaseSpecifier*> BaseResult;
+ typedef ActionResult<CXXCtorInitializer*> MemInitResult;
+
+ typedef ActionResult<Decl*> DeclResult;
+ typedef OpaquePtr<TemplateName> ParsedTemplateTy;
+
+ inline Expr *move(Expr *E) { return E; }
+ inline Stmt *move(Stmt *S) { return S; }
+
+ typedef ASTMultiPtr<Expr*> MultiExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg;
+
+ inline ExprResult ExprError() { return ExprResult(true); }
+ inline StmtResult StmtError() { return StmtResult(true); }
+
+ inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
+ inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
+
+ inline ExprResult ExprEmpty() { return ExprResult(false); }
+ inline StmtResult StmtEmpty() { return StmtResult(false); }
+
+ inline Expr *AssertSuccess(ExprResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+
+ inline Stmt *AssertSuccess(StmtResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
new file mode 100644
index 0000000..5aa6f47
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
@@ -0,0 +1,196 @@
+//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides data structures that store the parsed representation of
+// templates.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
+#include <cassert>
+
+namespace clang {
+ /// \brief Represents the parsed form of a C++ template argument.
+ class ParsedTemplateArgument {
+ public:
+ /// \brief Describes the kind of template argument that was parsed.
+ enum KindType {
+ /// \brief A template type parameter, stored as a type.
+ Type,
+ /// \brief A non-type template parameter, stored as an expression.
+ NonType,
+ /// \brief A template template argument, stored as a template name.
+ Template
+ };
+
+ /// \brief Build an empty template argument.
+ ///
+ /// This template argument is invalid.
+ ParsedTemplateArgument() : Kind(Type), Arg(0) { }
+
+ /// \brief Create a template type argument or non-type template argument.
+ ///
+ /// \param Arg the template type argument or non-type template argument.
+ /// \param Loc the location of the type.
+ ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
+ : Kind(Kind), Arg(Arg), Loc(Loc) { }
+
+ /// \brief Create a template template argument.
+ ///
+ /// \param SS the C++ scope specifier that precedes the template name, if
+ /// any.
+ ///
+ /// \param Template the template to which this template template
+ /// argument refers.
+ ///
+ /// \param TemplateLoc the location of the template name.
+ ParsedTemplateArgument(const CXXScopeSpec &SS,
+ ParsedTemplateTy Template,
+ SourceLocation TemplateLoc)
+ : Kind(ParsedTemplateArgument::Template),
+ Arg(Template.getAsOpaquePtr()),
+ Loc(TemplateLoc), SS(SS), EllipsisLoc() { }
+
+ /// \brief Determine whether the given template argument is invalid.
+ bool isInvalid() const { return Arg == 0; }
+
+ /// \brief Determine what kind of template argument we have.
+ KindType getKind() const { return Kind; }
+
+ /// \brief Retrieve the template type argument's type.
+ ParsedType getAsType() const {
+ assert(Kind == Type && "Not a template type argument");
+ return ParsedType::getFromOpaquePtr(Arg);
+ }
+
+ /// \brief Retrieve the non-type template argument's expression.
+ Expr *getAsExpr() const {
+ assert(Kind == NonType && "Not a non-type template argument");
+ return static_cast<Expr*>(Arg);
+ }
+
+ /// \brief Retrieve the template template argument's template name.
+ ParsedTemplateTy getAsTemplate() const {
+ assert(Kind == Template && "Not a template template argument");
+ return ParsedTemplateTy::getFromOpaquePtr(Arg);
+ }
+
+ /// \brief Retrieve the location of the template argument.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Retrieve the nested-name-specifier that precedes the template
+ /// name in a template template argument.
+ const CXXScopeSpec &getScopeSpec() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have a scope specifier");
+ return SS;
+ }
+
+ /// \brief Retrieve the location of the ellipsis that makes a template
+ /// template argument into a pack expansion.
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have an ellipsis");
+ return EllipsisLoc;
+ }
+
+ /// \brief Retrieve a pack expansion of the given template template
+ /// argument.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const;
+
+ private:
+ KindType Kind;
+
+ /// \brief The actual template argument representation, which may be
+ /// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an
+ /// expression), or an ActionBase::TemplateTy (for a template).
+ void *Arg;
+
+ /// \brief the location of the template argument.
+ SourceLocation Loc;
+
+ /// \brief The nested-name-specifier that can accompany a template template
+ /// argument.
+ CXXScopeSpec SS;
+
+ /// \brief The ellipsis location that can accompany a template template
+ /// argument (turning it into a template template argument expansion).
+ SourceLocation EllipsisLoc;
+ };
+
+ /// \brief Information about a template-id annotation
+ /// token.
+ ///
+ /// A template-id annotation token contains the template declaration,
+ /// template arguments, whether those template arguments were types,
+ /// expressions, or template names, and the source locations for important
+ /// tokens. All of the information about template arguments is allocated
+ /// directly after this structure.
+ struct TemplateIdAnnotation {
+ /// TemplateNameLoc - The location of the template name within the
+ /// source.
+ SourceLocation TemplateNameLoc;
+
+ /// FIXME: Temporarily stores the name of a specialization
+ IdentifierInfo *Name;
+
+ /// FIXME: Temporarily stores the overloaded operator kind.
+ OverloadedOperatorKind Operator;
+
+ /// The declaration of the template corresponding to the
+ /// template-name.
+ ParsedTemplateTy Template;
+
+ /// The kind of template that Template refers to.
+ TemplateNameKind Kind;
+
+ /// The location of the '<' before the template argument
+ /// list.
+ SourceLocation LAngleLoc;
+
+ /// The location of the '>' after the template argument
+ /// list.
+ SourceLocation RAngleLoc;
+
+ /// NumArgs - The number of template arguments.
+ unsigned NumArgs;
+
+ /// \brief Retrieves a pointer to the template arguments
+ ParsedTemplateArgument *getTemplateArgs() {
+ return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
+ }
+
+ static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
+ TemplateIdAnnotation *TemplateId
+ = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
+ sizeof(ParsedTemplateArgument) * NumArgs);
+ TemplateId->NumArgs = NumArgs;
+ return TemplateId;
+ }
+
+ void Destroy() { free(this); }
+ };
+
+ /// Retrieves the range of the given template parameter lists.
+ SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
+ unsigned NumParams);
+
+ inline const ParsedTemplateArgument &
+ ASTTemplateArgsPtr::operator[](unsigned Arg) const {
+ return Args[Arg];
+ }
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h
new file mode 100644
index 0000000..b78a1c0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h
@@ -0,0 +1,46 @@
+//===- PrettyDeclStackTrace.h - Stack trace for decl processing -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an llvm::PrettyStackTraceEntry object for showing
+// that a particular declaration was being processed when a crash
+// occurred.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+#define LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+class Decl;
+class Sema;
+class SourceManager;
+
+/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while
+/// parsing something related to a declaration, include that
+/// declaration in the stack trace.
+class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry {
+ Sema &S;
+ Decl *TheDecl;
+ SourceLocation Loc;
+ const char *Message;
+
+public:
+ PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, const char *Msg)
+ : S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Scope.h b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
new file mode 100644
index 0000000..d7fda35
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
@@ -0,0 +1,322 @@
+//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Scope interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPE_H
+#define LLVM_CLANG_SEMA_SCOPE_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+class Decl;
+class UsingDirectiveDecl;
+
+/// Scope - A scope is a transient data structure that is used while parsing the
+/// program. It assists with resolving identifiers to the appropriate
+/// declaration.
+///
+class Scope {
+public:
+ /// ScopeFlags - These are bitfields that are or'd together when creating a
+ /// scope, which defines the sorts of things the scope contains.
+ enum ScopeFlags {
+ /// FnScope - This indicates that the scope corresponds to a function, which
+ /// means that labels are set here.
+ FnScope = 0x01,
+
+ /// BreakScope - This is a while,do,switch,for, etc that can have break
+ /// stmts embedded into it.
+ BreakScope = 0x02,
+
+ /// ContinueScope - This is a while,do,for, which can have continue
+ /// stmt embedded into it.
+ ContinueScope = 0x04,
+
+ /// DeclScope - This is a scope that can contain a declaration. Some scopes
+ /// just contain loop constructs but don't contain decls.
+ DeclScope = 0x08,
+
+ /// ControlScope - The controlling scope in a if/switch/while/for statement.
+ ControlScope = 0x10,
+
+ /// ClassScope - The scope of a struct/union/class definition.
+ ClassScope = 0x20,
+
+ /// BlockScope - This is a scope that corresponds to a block/closure object.
+ /// Blocks serve as top-level scopes for some objects like labels, they
+ /// also prevent things like break and continue. BlockScopes always have
+ /// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well.
+ BlockScope = 0x40,
+
+ /// TemplateParamScope - This is a scope that corresponds to the
+ /// template parameters of a C++ template. Template parameter
+ /// scope starts at the 'template' keyword and ends when the
+ /// template declaration ends.
+ TemplateParamScope = 0x80,
+
+ /// FunctionPrototypeScope - This is a scope that corresponds to the
+ /// parameters within a function prototype.
+ FunctionPrototypeScope = 0x100,
+
+ /// AtCatchScope - This is a scope that corresponds to the Objective-C
+ /// @catch statement.
+ AtCatchScope = 0x200,
+
+ /// ObjCMethodScope - This scope corresponds to an Objective-C method body.
+ /// It always has FnScope and DeclScope set as well.
+ ObjCMethodScope = 0x400
+ };
+private:
+ /// The parent scope for this scope. This is null for the translation-unit
+ /// scope.
+ Scope *AnyParent;
+
+ /// Depth - This is the depth of this scope. The translation-unit scope has
+ /// depth 0.
+ unsigned short Depth;
+
+ /// Flags - This contains a set of ScopeFlags, which indicates how the scope
+ /// interrelates with other control flow statements.
+ unsigned short Flags;
+
+ /// FnParent - If this scope has a parent scope that is a function body, this
+ /// pointer is non-null and points to it. This is used for label processing.
+ Scope *FnParent;
+
+ /// BreakParent/ContinueParent - This is a direct link to the immediately
+ /// preceeding BreakParent/ContinueParent if this scope is not one, or null if
+ /// there is no containing break/continue scope.
+ Scope *BreakParent, *ContinueParent;
+
+ /// ControlParent - This is a direct link to the immediately
+ /// preceeding ControlParent if this scope is not one, or null if
+ /// there is no containing control scope.
+ Scope *ControlParent;
+
+ /// BlockParent - This is a direct link to the immediately containing
+ /// BlockScope if this scope is not one, or null if there is none.
+ Scope *BlockParent;
+
+ /// TemplateParamParent - This is a direct link to the
+ /// immediately containing template parameter scope. In the
+ /// case of nested templates, template parameter scopes can have
+ /// other template parameter scopes as parents.
+ Scope *TemplateParamParent;
+
+ /// DeclsInScope - This keeps track of all declarations in this scope. When
+ /// the declaration is added to the scope, it is set as the current
+ /// declaration for the identifier in the IdentifierTable. When the scope is
+ /// popped, these declarations are removed from the IdentifierTable's notion
+ /// of current declaration. It is up to the current Action implementation to
+ /// implement these semantics.
+ typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy;
+ DeclSetTy DeclsInScope;
+
+ /// Entity - The entity with which this scope is associated. For
+ /// example, the entity of a class scope is the class itself, the
+ /// entity of a function scope is a function, etc. This field is
+ /// maintained by the Action implementation.
+ void *Entity;
+
+ typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
+ UsingDirectivesTy UsingDirectives;
+
+ /// \brief Used to determine if errors occurred in this scope.
+ DiagnosticErrorTrap ErrorTrap;
+
+public:
+ Scope(Scope *Parent, unsigned ScopeFlags, Diagnostic &Diag)
+ : ErrorTrap(Diag) {
+ Init(Parent, ScopeFlags);
+ }
+
+ /// getFlags - Return the flags for this scope.
+ ///
+ unsigned getFlags() const { return Flags; }
+ void setFlags(unsigned F) { Flags = F; }
+
+ /// isBlockScope - Return true if this scope correspond to a closure.
+ bool isBlockScope() const { return Flags & BlockScope; }
+
+ /// getParent - Return the scope that this is nested in.
+ ///
+ const Scope *getParent() const { return AnyParent; }
+ Scope *getParent() { return AnyParent; }
+
+ /// getFnParent - Return the closest scope that is a function body.
+ ///
+ const Scope *getFnParent() const { return FnParent; }
+ Scope *getFnParent() { return FnParent; }
+
+ /// getContinueParent - Return the closest scope that a continue statement
+ /// would be affected by. If the closest scope is a closure scope, we know
+ /// that there is no loop *inside* the closure.
+ Scope *getContinueParent() {
+ if (ContinueParent && !ContinueParent->isBlockScope())
+ return ContinueParent;
+ return 0;
+ }
+
+ const Scope *getContinueParent() const {
+ return const_cast<Scope*>(this)->getContinueParent();
+ }
+
+ /// getBreakParent - Return the closest scope that a break statement
+ /// would be affected by. If the closest scope is a block scope, we know
+ /// that there is no loop *inside* the block.
+ Scope *getBreakParent() {
+ if (BreakParent && !BreakParent->isBlockScope())
+ return BreakParent;
+ return 0;
+ }
+ const Scope *getBreakParent() const {
+ return const_cast<Scope*>(this)->getBreakParent();
+ }
+
+ Scope *getControlParent() { return ControlParent; }
+ const Scope *getControlParent() const { return ControlParent; }
+
+ Scope *getBlockParent() { return BlockParent; }
+ const Scope *getBlockParent() const { return BlockParent; }
+
+ Scope *getTemplateParamParent() { return TemplateParamParent; }
+ const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+
+ typedef DeclSetTy::iterator decl_iterator;
+ decl_iterator decl_begin() const { return DeclsInScope.begin(); }
+ decl_iterator decl_end() const { return DeclsInScope.end(); }
+ bool decl_empty() const { return DeclsInScope.empty(); }
+
+ void AddDecl(Decl *D) {
+ DeclsInScope.insert(D);
+ }
+
+ void RemoveDecl(Decl *D) {
+ DeclsInScope.erase(D);
+ }
+
+ /// isDeclScope - Return true if this is the scope that the specified decl is
+ /// declared in.
+ bool isDeclScope(Decl *D) {
+ return DeclsInScope.count(D) != 0;
+ }
+
+ void* getEntity() const { return Entity; }
+ void setEntity(void *E) { Entity = E; }
+
+ bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); }
+
+ /// isClassScope - Return true if this scope is a class/struct/union scope.
+ bool isClassScope() const {
+ return (getFlags() & Scope::ClassScope);
+ }
+
+ /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline
+ /// method scope or is inside one.
+ bool isInCXXInlineMethodScope() const {
+ if (const Scope *FnS = getFnParent()) {
+ assert(FnS->getParent() && "TUScope not created?");
+ return FnS->getParent()->isClassScope();
+ }
+ return false;
+ }
+
+ /// isInObjcMethodScope - Return true if this scope is, or is contained in, an
+ /// Objective-C method body. Note that this method is not constant time.
+ bool isInObjcMethodScope() const {
+ for (const Scope *S = this; S; S = S->getParent()) {
+ // If this scope is an objc method scope, then we succeed.
+ if (S->getFlags() & ObjCMethodScope)
+ return true;
+ }
+ return false;
+ }
+
+ /// isTemplateParamScope - Return true if this scope is a C++
+ /// template parameter scope.
+ bool isTemplateParamScope() const {
+ return getFlags() & Scope::TemplateParamScope;
+ }
+
+ /// isFunctionPrototypeScope - Return true if this scope is a
+ /// function prototype scope.
+ bool isFunctionPrototypeScope() const {
+ return getFlags() & Scope::FunctionPrototypeScope;
+ }
+
+ /// isAtCatchScope - Return true if this scope is @catch.
+ bool isAtCatchScope() const {
+ return getFlags() & Scope::AtCatchScope;
+ }
+
+ typedef UsingDirectivesTy::iterator udir_iterator;
+ typedef UsingDirectivesTy::const_iterator const_udir_iterator;
+
+ void PushUsingDirective(UsingDirectiveDecl *UDir) {
+ UsingDirectives.push_back(UDir);
+ }
+
+ udir_iterator using_directives_begin() {
+ return UsingDirectives.begin();
+ }
+
+ udir_iterator using_directives_end() {
+ return UsingDirectives.end();
+ }
+
+ const_udir_iterator using_directives_begin() const {
+ return UsingDirectives.begin();
+ }
+
+ const_udir_iterator using_directives_end() const {
+ return UsingDirectives.end();
+ }
+
+ /// Init - This is used by the parser to implement scope caching.
+ ///
+ void Init(Scope *Parent, unsigned ScopeFlags) {
+ AnyParent = Parent;
+ Depth = AnyParent ? AnyParent->Depth+1 : 0;
+ Flags = ScopeFlags;
+
+ if (AnyParent) {
+ FnParent = AnyParent->FnParent;
+ BreakParent = AnyParent->BreakParent;
+ ContinueParent = AnyParent->ContinueParent;
+ ControlParent = AnyParent->ControlParent;
+ BlockParent = AnyParent->BlockParent;
+ TemplateParamParent = AnyParent->TemplateParamParent;
+ } else {
+ FnParent = BreakParent = ContinueParent = BlockParent = 0;
+ ControlParent = 0;
+ TemplateParamParent = 0;
+ }
+
+ // If this scope is a function or contains breaks/continues, remember it.
+ if (Flags & FnScope) FnParent = this;
+ if (Flags & BreakScope) BreakParent = this;
+ if (Flags & ContinueScope) ContinueParent = this;
+ if (Flags & ControlScope) ControlParent = this;
+ if (Flags & BlockScope) BlockParent = this;
+ if (Flags & TemplateParamScope) TemplateParamParent = this;
+ DeclsInScope.clear();
+ UsingDirectives.clear();
+ Entity = 0;
+ ErrorTrap.reset();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
new file mode 100644
index 0000000..b0bb955
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,139 @@
+//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines FunctionScopeInfo and BlockScopeInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
+#define LLVM_CLANG_SEMA_SCOPE_INFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+
+class BlockDecl;
+class IdentifierInfo;
+class LabelDecl;
+class ReturnStmt;
+class Scope;
+class SwitchStmt;
+
+namespace sema {
+
+/// \brief Retains information about a function, method, or block that is
+/// currently being parsed.
+class FunctionScopeInfo {
+public:
+
+ /// \brief Whether this scope information structure defined information for
+ /// a block.
+ bool IsBlockInfo;
+
+ /// \brief Whether this function contains a VLA, @try, try, C++
+ /// initializer, or anything else that can't be jumped past.
+ bool HasBranchProtectedScope;
+
+ /// \brief Whether this function contains any switches or direct gotos.
+ bool HasBranchIntoScope;
+
+ /// \brief Whether this function contains any indirect gotos.
+ bool HasIndirectGoto;
+
+ /// \brief Used to determine if errors occurred in this function or block.
+ DiagnosticErrorTrap ErrorTrap;
+
+ /// SwitchStack - This is the current set of active switch statements in the
+ /// block.
+ llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+
+ /// \brief The list of return statements that occur within the function or
+ /// block, if there is any chance of applying the named return value
+ /// optimization.
+ llvm::SmallVector<ReturnStmt*, 4> Returns;
+
+ void setHasBranchIntoScope() {
+ HasBranchIntoScope = true;
+ }
+
+ void setHasBranchProtectedScope() {
+ HasBranchProtectedScope = true;
+ }
+
+ void setHasIndirectGoto() {
+ HasIndirectGoto = true;
+ }
+
+ bool NeedsScopeChecking() const {
+ return HasIndirectGoto ||
+ (HasBranchProtectedScope && HasBranchIntoScope);
+ }
+
+ FunctionScopeInfo(Diagnostic &Diag)
+ : IsBlockInfo(false),
+ HasBranchProtectedScope(false),
+ HasBranchIntoScope(false),
+ HasIndirectGoto(false),
+ ErrorTrap(Diag) { }
+
+ virtual ~FunctionScopeInfo();
+
+ /// \brief Clear out the information in this function scope, making it
+ /// suitable for reuse.
+ void Clear();
+
+ static bool classof(const FunctionScopeInfo *FSI) { return true; }
+};
+
+/// \brief Retains information about a block that is currently being parsed.
+class BlockScopeInfo : public FunctionScopeInfo {
+public:
+ BlockDecl *TheDecl;
+
+ /// TheScope - This is the scope for the block itself, which contains
+ /// arguments etc.
+ Scope *TheScope;
+
+ /// ReturnType - The return type of the block, or null if the block
+ /// signature didn't provide an explicit return type.
+ QualType ReturnType;
+
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
+ /// CaptureMap - A map of captured variables to (index+1) into Captures.
+ llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
+
+ /// Captures - The captured variables.
+ llvm::SmallVector<BlockDecl::Capture, 4> Captures;
+
+ /// CapturesCXXThis - Whether this block captures 'this'.
+ bool CapturesCXXThis;
+
+ BlockScopeInfo(Diagnostic &Diag, Scope *BlockScope, BlockDecl *Block)
+ : FunctionScopeInfo(Diag), TheDecl(Block), TheScope(BlockScope),
+ CapturesCXXThis(false)
+ {
+ IsBlockInfo = true;
+ }
+
+ virtual ~BlockScopeInfo();
+
+ static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
+ static bool classof(const BlockScopeInfo *BSI) { return true; }
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
new file mode 100644
index 0000000..91d6914
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -0,0 +1,5172 @@
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- 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 Sema class, which performs semantic analysis and
+// builds ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_H
+#define LLVM_CLANG_SEMA_SEMA_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <deque>
+#include <string>
+
+namespace llvm {
+ class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
+}
+
+namespace clang {
+ class ADLResult;
+ class ASTConsumer;
+ class ASTContext;
+ class ArrayType;
+ class AttributeList;
+ class BlockDecl;
+ class CXXBasePath;
+ class CXXBasePaths;
+ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class CXXDestructorDecl;
+ class CXXFieldCollector;
+ class CXXMemberCallExpr;
+ class CXXMethodDecl;
+ class CXXScopeSpec;
+ class CXXTemporary;
+ class CXXTryStmt;
+ class CallExpr;
+ class ClassTemplateDecl;
+ class ClassTemplatePartialSpecializationDecl;
+ class ClassTemplateSpecializationDecl;
+ class CodeCompleteConsumer;
+ class CodeCompletionAllocator;
+ class CodeCompletionResult;
+ class Decl;
+ class DeclAccessPair;
+ class DeclContext;
+ class DeclRefExpr;
+ class DeclaratorDecl;
+ class DeducedTemplateArgument;
+ class DependentDiagnostic;
+ class DesignatedInitExpr;
+ class Designation;
+ class EnumConstantDecl;
+ class Expr;
+ class ExtVectorType;
+ class ExternalSemaSource;
+ class FormatAttr;
+ class FriendDecl;
+ class FunctionDecl;
+ class FunctionProtoType;
+ class FunctionTemplateDecl;
+ class ImplicitConversionSequence;
+ class InitListExpr;
+ class InitializationKind;
+ class InitializationSequence;
+ class InitializedEntity;
+ class IntegerLiteral;
+ class LabelStmt;
+ class LangOptions;
+ class LocalInstantiationScope;
+ class LookupResult;
+ class MacroInfo;
+ class MultiLevelTemplateArgumentList;
+ class NamedDecl;
+ class NonNullAttr;
+ class ObjCCategoryDecl;
+ class ObjCCategoryImplDecl;
+ class ObjCCompatibleAliasDecl;
+ class ObjCContainerDecl;
+ class ObjCImplDecl;
+ class ObjCImplementationDecl;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
+ template <class T> class ObjCList;
+ class ObjCMethodDecl;
+ class ObjCPropertyDecl;
+ class ObjCProtocolDecl;
+ class OverloadCandidateSet;
+ class ParenListExpr;
+ class ParmVarDecl;
+ class Preprocessor;
+ class PseudoDestructorTypeStorage;
+ class QualType;
+ class StandardConversionSequence;
+ class Stmt;
+ class StringLiteral;
+ class SwitchStmt;
+ class TargetAttributesSema;
+ class TemplateArgument;
+ class TemplateArgumentList;
+ class TemplateArgumentLoc;
+ class TemplateDecl;
+ class TemplateParameterList;
+ class TemplatePartialOrderingContext;
+ class TemplateTemplateParmDecl;
+ class Token;
+ class TypedefDecl;
+ class TypeLoc;
+ class UnqualifiedId;
+ class UnresolvedLookupExpr;
+ class UnresolvedMemberExpr;
+ class UnresolvedSetImpl;
+ class UnresolvedSetIterator;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class ValueDecl;
+ class VarDecl;
+ class VisibilityAttr;
+ class VisibleDeclConsumer;
+ class IndirectFieldDecl;
+
+namespace sema {
+ class AccessedEntity;
+ class BlockScopeInfo;
+ class DelayedDiagnostic;
+ class FunctionScopeInfo;
+ class TemplateDeductionInfo;
+}
+
+/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
+/// parsing.
+///
+/// LocInfoType is a "transient" type, only needed for passing to/from Parser
+/// and Sema, when we want to preserve type source info for a parsed type.
+/// It will not participate in the type system semantics in any way.
+class LocInfoType : public Type {
+ enum {
+ // The last number that can fit in Type's TC.
+ // Avoids conflict with an existing Type class.
+ LocInfo = Type::TypeLast + 1
+ };
+
+ TypeSourceInfo *DeclInfo;
+
+ LocInfoType(QualType ty, TypeSourceInfo *TInfo)
+ : Type((TypeClass)LocInfo, ty, ty->isDependentType(),
+ ty->isVariablyModifiedType(),
+ ty->containsUnexpandedParameterPack()),
+ DeclInfo(TInfo) {
+ assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
+ }
+ friend class Sema;
+
+public:
+ QualType getType() const { return getCanonicalTypeInternal(); }
+ TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
+
+ void getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == (TypeClass)LocInfo;
+ }
+ static bool classof(const LocInfoType *) { return true; }
+};
+
+// FIXME: No way to easily map from TemplateTypeParmTypes to
+// TemplateTypeParmDecls, so we have this horrible PointerUnion.
+typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
+ SourceLocation> UnexpandedParameterPack;
+
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema {
+ Sema(const Sema&); // DO NOT IMPLEMENT
+ void operator=(const Sema&); // DO NOT IMPLEMENT
+ mutable const TargetAttributesSema* TheTargetAttributesSema;
+public:
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
+ typedef Attr AttrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXCtorInitializer MemInitTy;
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+
+ OpenCLOptions OpenCLFeatures;
+ FPOptions FPFeatures;
+
+ const LangOptions &LangOpts;
+ Preprocessor &PP;
+ ASTContext &Context;
+ ASTConsumer &Consumer;
+ Diagnostic &Diags;
+ SourceManager &SourceMgr;
+
+ /// \brief Source of additional semantic information.
+ ExternalSemaSource *ExternalSource;
+
+ /// \brief Code-completion consumer.
+ CodeCompleteConsumer *CodeCompleter;
+
+ /// CurContext - This is the current declaration context of parsing.
+ DeclContext *CurContext;
+
+ /// VAListTagName - The declaration name corresponding to __va_list_tag.
+ /// This is used as part of a hack to omit that class from ADL results.
+ DeclarationName VAListTagName;
+
+ /// PackContext - Manages the stack for #pragma pack. An alignment
+ /// of 0 indicates default alignment.
+ void *PackContext; // Really a "PragmaPackStack*"
+
+ /// VisContext - Manages the stack for #pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
+
+ /// \brief Stack containing information about each of the nested
+ /// function, block, and method scopes that are currently active.
+ ///
+ /// This array is never empty. Clients should ignore the first
+ /// element, which is used to cache a single FunctionScopeInfo
+ /// that's used to parse every top-level function.
+ llvm::SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+
+ /// ExprTemporaries - This is the stack of temporaries that are created by
+ /// the current full expression.
+ llvm::SmallVector<CXXTemporary*, 8> ExprTemporaries;
+
+ /// ExtVectorDecls - This is a list all the extended vector types. This allows
+ /// us to associate a raw vector type with one of the ext_vector type names.
+ /// This is only necessary for issuing pretty diagnostics.
+ llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls;
+
+ /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+ llvm::OwningPtr<CXXFieldCollector> FieldCollector;
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+
+ /// PureVirtualClassDiagSet - a set of class declarations which we have
+ /// emitted a list of pure virtual functions. Used to prevent emitting the
+ /// same list more than once.
+ llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+
+ /// \brief A mapping from external names to the most recent
+ /// locally-scoped external declaration with that name.
+ ///
+ /// This map contains external declarations introduced in local
+ /// scoped, e.g.,
+ ///
+ /// \code
+ /// void f() {
+ /// void foo(int, int);
+ /// }
+ /// \endcode
+ ///
+ /// Here, the name "foo" will be associated with the declaration on
+ /// "foo" within f. This name is not visible outside of
+ /// "f". However, we still find it in two cases:
+ ///
+ /// - If we are declaring another external with the name "foo", we
+ /// can find "foo" as a previous declaration, so that the types
+ /// of this external declaration can be checked for
+ /// compatibility.
+ ///
+ /// - If we would implicitly declare "foo" (e.g., due to a call to
+ /// "foo" in C when no prototype or definition is visible), then
+ /// we find this declaration of "foo" and complain that it is
+ /// not visible.
+ llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls;
+
+ /// \brief All the tentative definitions encountered in the TU.
+ llvm::SmallVector<VarDecl *, 2> TentativeDefinitions;
+
+ /// \brief The set of file scoped decls seen so far that have not been used
+ /// and must warn if not used. Only contains the first declaration.
+ llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls;
+
+ class DelayedDiagnostics;
+
+ class ParsingDeclState {
+ unsigned SavedStackSize;
+ friend class Sema::DelayedDiagnostics;
+ };
+
+ class ProcessingContextState {
+ unsigned SavedParsingDepth;
+ unsigned SavedActiveStackBase;
+ friend class Sema::DelayedDiagnostics;
+ };
+
+ /// A class which encapsulates the logic for delaying diagnostics
+ /// during parsing and other processing.
+ class DelayedDiagnostics {
+ /// \brief The stack of diagnostics that were delayed due to being
+ /// produced during the parsing of a declaration.
+ sema::DelayedDiagnostic *Stack;
+
+ /// \brief The number of objects on the delayed-diagnostics stack.
+ unsigned StackSize;
+
+ /// \brief The current capacity of the delayed-diagnostics stack.
+ unsigned StackCapacity;
+
+ /// \brief The index of the first "active" delayed diagnostic in
+ /// the stack. When parsing class definitions, we ignore active
+ /// delayed diagnostics from the surrounding context.
+ unsigned ActiveStackBase;
+
+ /// \brief The depth of the declarations we're currently parsing.
+ /// This gets saved and reset whenever we enter a class definition.
+ unsigned ParsingDepth;
+
+ public:
+ DelayedDiagnostics() : Stack(0), StackSize(0), StackCapacity(0),
+ ActiveStackBase(0), ParsingDepth(0) {}
+
+ ~DelayedDiagnostics() {
+ delete[] reinterpret_cast<char*>(Stack);
+ }
+
+ /// Adds a delayed diagnostic.
+ void add(const sema::DelayedDiagnostic &diag);
+
+ /// Determines whether diagnostics should be delayed.
+ bool shouldDelayDiagnostics() { return ParsingDepth > 0; }
+
+ /// Observe that we've started parsing a declaration. Access and
+ /// deprecation diagnostics will be delayed; when the declaration
+ /// is completed, all active delayed diagnostics will be evaluated
+ /// in its context, and then active diagnostics stack will be
+ /// popped down to the saved depth.
+ ParsingDeclState pushParsingDecl() {
+ ParsingDepth++;
+
+ ParsingDeclState state;
+ state.SavedStackSize = StackSize;
+ return state;
+ }
+
+ /// Observe that we're completed parsing a declaration.
+ static void popParsingDecl(Sema &S, ParsingDeclState state, Decl *decl);
+
+ /// Observe that we've started processing a different context, the
+ /// contents of which are semantically separate from the
+ /// declarations it may lexically appear in. This sets aside the
+ /// current stack of active diagnostics and starts afresh.
+ ProcessingContextState pushContext() {
+ assert(StackSize >= ActiveStackBase);
+
+ ProcessingContextState state;
+ state.SavedParsingDepth = ParsingDepth;
+ state.SavedActiveStackBase = ActiveStackBase;
+
+ ActiveStackBase = StackSize;
+ ParsingDepth = 0;
+
+ return state;
+ }
+
+ /// Observe that we've stopped processing a context. This
+ /// restores the previous stack of active diagnostics.
+ void popContext(ProcessingContextState state) {
+ assert(ActiveStackBase == StackSize);
+ assert(ParsingDepth == 0);
+ ActiveStackBase = state.SavedActiveStackBase;
+ ParsingDepth = state.SavedParsingDepth;
+ }
+ } DelayedDiagnostics;
+
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+ ProcessingContextState SavedContextState;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush)
+ : S(S), SavedContext(S.CurContext),
+ SavedContextState(S.DelayedDiagnostics.pushContext())
+ {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ S.DelayedDiagnostics.popContext(SavedContextState);
+ SavedContext = 0;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
+ /// WeakUndeclaredIdentifiers - Identifiers contained in
+ /// #pragma weak before declared. rare. may alias another
+ /// identifier, declared or undeclared
+ class WeakInfo {
+ IdentifierInfo *alias; // alias (optional)
+ SourceLocation loc; // for diagnostics
+ bool used; // identifier later declared?
+ public:
+ WeakInfo()
+ : alias(0), loc(SourceLocation()), used(false) {}
+ WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
+ : alias(Alias), loc(Loc), used(false) {}
+ inline IdentifierInfo * getAlias() const { return alias; }
+ inline SourceLocation getLocation() const { return loc; }
+ void setUsed(bool Used=true) { used = Used; }
+ inline bool getUsed() { return used; }
+ bool operator==(WeakInfo RHS) const {
+ return alias == RHS.getAlias() && loc == RHS.getLocation();
+ }
+ bool operator!=(WeakInfo RHS) const { return !(*this == RHS); }
+ };
+ llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
+
+ /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
+ /// #pragma weak during processing of other Decls.
+ /// I couldn't figure out a clean way to generate these in-line, so
+ /// we store them here and handle separately -- which is a hack.
+ /// It would be best to refactor this.
+ llvm::SmallVector<Decl*,2> WeakTopLevelDecl;
+
+ IdentifierResolver IdResolver;
+
+ /// Translation Unit Scope - useful to Objective-C actions that need
+ /// to lookup file scope declarations in the "ordinary" C decl namespace.
+ /// For example, user-defined classes, built-in "id" type, etc.
+ Scope *TUScope;
+
+ /// \brief The C++ "std" namespace, where the standard library resides.
+ LazyDeclPtr StdNamespace;
+
+ /// \brief The C++ "std::bad_alloc" class, which is defined by the C++
+ /// standard library.
+ LazyDeclPtr StdBadAlloc;
+
+ /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>.
+ RecordDecl *CXXTypeInfoDecl;
+
+ /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files.
+ RecordDecl *MSVCGuidDecl;
+
+ /// A flag to remember whether the implicit forms of operator new and delete
+ /// have been declared.
+ bool GlobalNewDeleteDeclared;
+
+ /// \brief The set of declarations that have been referenced within
+ /// a potentially evaluated expression.
+ typedef llvm::SmallVector<std::pair<SourceLocation, Decl *>, 10>
+ PotentiallyReferencedDecls;
+
+ /// \brief A set of diagnostics that may be emitted.
+ typedef llvm::SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
+ PotentiallyEmittedDiagnostics;
+
+ /// \brief Describes how the expressions currently being parsed are
+ /// evaluated at run-time, if at all.
+ enum ExpressionEvaluationContext {
+ /// \brief The current expression and its subexpressions occur within an
+ /// unevaluated operand (C++0x [expr]p8), such as a constant expression
+ /// or the subexpression of \c sizeof, where the type or the value of the
+ /// expression may be significant but no code will be generated to evaluate
+ /// the value of the expression at run time.
+ Unevaluated,
+
+ /// \brief The current expression is potentially evaluated at run time,
+ /// which means that code may be generated to evaluate the value of the
+ /// expression at run time.
+ PotentiallyEvaluated,
+
+ /// \brief The current expression may be potentially evaluated or it may
+ /// be unevaluated, but it is impossible to tell from the lexical context.
+ /// This evaluation context is used primary for the operand of the C++
+ /// \c typeid expression, whose argument is potentially evaluated only when
+ /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
+ PotentiallyPotentiallyEvaluated,
+
+ /// \brief The current expression is potentially evaluated, but any
+ /// declarations referenced inside that expression are only used if
+ /// in fact the current expression is used.
+ ///
+ /// This value is used when parsing default function arguments, for which
+ /// we would like to provide diagnostics (e.g., passing non-POD arguments
+ /// through varargs) but do not want to mark declarations as "referenced"
+ /// until the default argument is used.
+ PotentiallyEvaluatedIfUsed
+ };
+
+ /// \brief Data structure used to record current or nested
+ /// expression evaluation contexts.
+ struct ExpressionEvaluationContextRecord {
+ /// \brief The expression evaluation context.
+ ExpressionEvaluationContext Context;
+
+ /// \brief The number of temporaries that were active when we
+ /// entered this expression evaluation context.
+ unsigned NumTemporaries;
+
+ /// \brief The set of declarations referenced within a
+ /// potentially potentially-evaluated context.
+ ///
+ /// When leaving a potentially potentially-evaluated context, each
+ /// of these elements will be as referenced if the corresponding
+ /// potentially potentially evaluated expression is potentially
+ /// evaluated.
+ PotentiallyReferencedDecls *PotentiallyReferenced;
+
+ /// \brief The set of diagnostics to emit should this potentially
+ /// potentially-evaluated context become evaluated.
+ PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
+
+ ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+ unsigned NumTemporaries)
+ : Context(Context), NumTemporaries(NumTemporaries),
+ PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
+
+ void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
+ if (!PotentiallyReferenced)
+ PotentiallyReferenced = new PotentiallyReferencedDecls;
+ PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
+ }
+
+ void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+ if (!PotentiallyDiagnosed)
+ PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics;
+ PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD));
+ }
+
+ void Destroy() {
+ delete PotentiallyReferenced;
+ delete PotentiallyDiagnosed;
+ PotentiallyReferenced = 0;
+ PotentiallyDiagnosed = 0;
+ }
+ };
+
+ /// A stack of expression evaluation contexts.
+ llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+
+ /// \brief Whether the code handled by Sema should be considered a
+ /// complete translation unit or not.
+ ///
+ /// When true (which is generally the case), Sema will perform
+ /// end-of-translation-unit semantic tasks (such as creating
+ /// initializers for tentative definitions in C) once parsing has
+ /// completed. This flag will be false when building PCH files,
+ /// since a PCH file is by definition not a complete translation
+ /// unit.
+ bool CompleteTranslationUnit;
+
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// \brief The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
+
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::SmallVector<ParmVarDecl *, 1> >
+ UnparsedDefaultArgInstantiationsMap;
+
+ /// \brief A mapping from parameters with unparsed default arguments to the
+ /// set of instantiations of each parameter.
+ ///
+ /// This mapping is a temporary data structure used when parsing
+ /// nested class templates or nested classes of class templates,
+ /// where we might end up instantiating an inner class before the
+ /// default arguments of its methods have been parsed.
+ UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
+
+ // Contains the locations of the beginning of unparsed default
+ // argument locations.
+ llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
+
+ /// UndefinedInternals - all the used, undefined objects with
+ /// internal linkage in this translation unit.
+ llvm::DenseMap<NamedDecl*, SourceLocation> UndefinedInternals;
+
+ typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
+ typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
+
+ /// Method Pool - allows efficient lookup when typechecking messages to "id".
+ /// We need to maintain a list, since selectors can have differing signatures
+ /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
+ /// of selectors are "overloaded").
+ GlobalMethodPool MethodPool;
+
+ /// Method selectors used in a @selector expression. Used for implementation
+ /// of -Wselector.
+ llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
+
+ GlobalMethodPool::iterator ReadMethodPool(Selector Sel);
+
+ /// Private Helper predicate to check for 'self'.
+ bool isSelfExpr(Expr *RExpr);
+public:
+ Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+ bool CompleteTranslationUnit = true,
+ CodeCompleteConsumer *CompletionConsumer = 0);
+ ~Sema();
+
+ /// \brief Perform initialization that occurs after the parser has been
+ /// initialized but before it parses anything.
+ void Initialize();
+
+ const LangOptions &getLangOptions() const { return LangOpts; }
+ OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+ FPOptions &getFPOptions() { return FPFeatures; }
+
+ Diagnostic &getDiagnostics() const { return Diags; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ const TargetAttributesSema &getTargetAttributesSema() const;
+ Preprocessor &getPreprocessor() const { return PP; }
+ ASTContext &getASTContext() const { return Context; }
+ ASTConsumer &getASTConsumer() const { return Consumer; }
+
+ /// \brief Helper class that creates diagnostics with optional
+ /// template instantiation stacks.
+ ///
+ /// This class provides a wrapper around the basic DiagnosticBuilder
+ /// class that emits diagnostics. SemaDiagnosticBuilder is
+ /// responsible for emitting the diagnostic (as DiagnosticBuilder
+ /// does) and, if the diagnostic comes from inside a template
+ /// instantiation, printing the template instantiation stack as
+ /// well.
+ class SemaDiagnosticBuilder : public DiagnosticBuilder {
+ Sema &SemaRef;
+ unsigned DiagID;
+
+ public:
+ SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
+ : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
+
+ explicit SemaDiagnosticBuilder(Sema &SemaRef)
+ : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { }
+
+ ~SemaDiagnosticBuilder();
+ };
+
+ /// \brief Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ /// \brief Emit a partial diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
+
+ /// \brief Build a partial diagnostic.
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+
+ ExprResult Owned(Expr* E) { return E; }
+ ExprResult Owned(ExprResult R) { return R; }
+ StmtResult Owned(Stmt* S) { return S; }
+
+ void ActOnEndOfTranslationUnit();
+
+ Scope *getScopeForContext(DeclContext *Ctx);
+
+ void PushFunctionScope();
+ void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+ void PopFunctionOrBlockScope();
+
+ sema::FunctionScopeInfo *getCurFunction() const {
+ return FunctionScopes.back();
+ }
+
+ bool hasAnyErrorsInThisFunction() const;
+
+ /// \brief Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
+
+ /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
+ llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+ //===--------------------------------------------------------------------===//
+ // Type Analysis / Processing: SemaType.cpp.
+ //
+
+ QualType adjustParameterType(QualType T);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) {
+ return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR));
+ }
+ QualType BuildPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildReferenceType(QualType T, bool LValueRef,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+ Expr *ArraySize, unsigned Quals,
+ SourceRange Brackets, DeclarationName Entity);
+ QualType BuildExtVectorType(QualType T, Expr *ArraySize,
+ SourceLocation AttrLoc);
+ QualType BuildFunctionType(QualType T,
+ QualType *ParamTypes, unsigned NumParamTypes,
+ bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
+ SourceLocation Loc, DeclarationName Entity,
+ FunctionType::ExtInfo Info);
+ QualType BuildMemberPointerType(QualType T, QualType Class,
+ SourceLocation Loc,
+ DeclarationName Entity);
+ QualType BuildBlockPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildParenType(QualType T);
+
+ TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
+ TagDecl **OwnedDecl = 0,
+ bool AllowAutoInTypeName = false);
+ TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+ TypeSourceInfo *ReturnTypeInfo);
+ /// \brief Package the given type and TSI into a ParsedType.
+ ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
+ DeclarationNameInfo GetNameForDeclarator(Declarator &D);
+ DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
+ static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
+ bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
+ bool CheckDistantExceptionSpec(QualType T);
+ bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
+ bool CheckEquivalentExceptionSpec(
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc);
+ bool CheckEquivalentExceptionSpec(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification = 0,
+ bool *MissingEmptyExceptionSpecification = 0);
+ bool CheckExceptionSpecSubset(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Superset, SourceLocation SuperLoc,
+ const FunctionProtoType *Subset, SourceLocation SubLoc);
+ bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Target, SourceLocation TargetLoc,
+ const FunctionProtoType *Source, SourceLocation SourceLoc);
+
+ TypeResult ActOnTypeName(Scope *S, Declarator &D);
+
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD,
+ std::pair<SourceLocation, PartialDiagnostic> Note);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID);
+
+ QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+ const CXXScopeSpec &SS, QualType T);
+
+ QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+ QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
+
+ //===--------------------------------------------------------------------===//
+ // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+ //
+
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr);
+
+ void DiagnoseUseOfUnimplementedSelectors();
+
+ ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS = 0,
+ bool isClassName = false,
+ bool HasTrailingDot = false,
+ ParsedType ObjectType = ParsedType());
+ TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
+ bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ CXXScopeSpec *SS,
+ ParsedType &SuggestedType);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ Decl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool IsFunctionDefinition);
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+ const LookupResult &Previous,
+ Scope *S);
+ void DiagnoseFunctionSpecifiers(Declarator& D);
+ void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
+ void CheckShadow(Scope *S, VarDecl *D);
+ void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
+ NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous, bool &Redeclaration);
+ NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &Redeclaration);
+ void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
+ bool &Redeclaration);
+ void CheckCompleteVariableDeclaration(VarDecl *var);
+ NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition,
+ bool &Redeclaration);
+ bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+ void CheckFunctionDeclaration(Scope *S,
+ FunctionDecl *NewFD, LookupResult &Previous,
+ bool IsExplicitSpecialization,
+ bool &Redeclaration);
+ void CheckMain(FunctionDecl *FD);
+ Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
+ ParmVarDecl *CheckParameter(DeclContext *DC,
+ TypeSourceInfo *TSInfo, QualType T,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ StorageClass SC,
+ StorageClass SCAsWritten);
+ void ActOnParamDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ Expr *defarg);
+ void ActOnParamUnparsedDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ SourceLocation ArgLoc);
+ void ActOnParamDefaultArgumentError(Decl *param);
+ bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+ SourceLocation EqualLoc);
+
+ void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit,
+ bool TypeMayContainAuto);
+ void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
+ void ActOnInitializerError(Decl *Dcl);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ Decl **Group,
+ unsigned NumDecls);
+ void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
+ void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
+
+ /// \brief Diagnose any unused parameters in the given sequence of
+ /// ParmVarDecl pointers.
+ void DiagnoseUnusedParameters(ParmVarDecl * const *Begin,
+ ParmVarDecl * const *End);
+
+ /// \brief Diagnose whether the size of parameters or return value of a
+ /// function or obj-c method definition is pass-by-value and larger than a
+ /// specified threshold.
+ void DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Begin,
+ ParmVarDecl * const *End,
+ QualType ReturnTy,
+ NamedDecl *D);
+
+ void DiagnoseInvalidJumps(Stmt *Body);
+ Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr);
+
+ /// Scope actions.
+ void ActOnPopScope(SourceLocation Loc, Scope *S);
+ void ActOnTranslationUnitScope(Scope *S);
+
+ /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+ /// no declarator (e.g. "struct foo;") is parsed.
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS);
+
+ StmtResult ActOnVlaStmt(const DeclSpec &DS);
+
+ Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record);
+
+ Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+ RecordDecl *Record);
+
+ bool isAcceptableTagRedeclaration(const TagDecl *Previous,
+ TagTypeKind NewTag,
+ SourceLocation NewTagLoc,
+ const IdentifierInfo &Name);
+
+ enum TagUseKind {
+ TUK_Reference, // Reference to a tag: 'struct foo *X;'
+ TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
+ TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
+ TUK_Friend // Friend declaration: 'friend struct foo;'
+ };
+
+ Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
+
+ Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+ unsigned TagSpec, SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TempParamLists);
+
+ TypeResult ActOnDependentTag(Scope *S,
+ unsigned TagSpec,
+ TagUseKind TUK,
+ const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation TagLoc,
+ SourceLocation NameLoc);
+
+ void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ llvm::SmallVectorImpl<Decl *> &Decls);
+ Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth);
+
+ FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ AccessSpecifier AS);
+
+ FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
+ TypeSourceInfo *TInfo,
+ RecordDecl *Record, SourceLocation Loc,
+ bool Mutable, Expr *BitfieldWidth,
+ SourceLocation TSSL,
+ AccessSpecifier AS, NamedDecl *PrevDecl,
+ Declarator *D = 0);
+
+ enum CXXSpecialMember {
+ CXXInvalid = -1,
+ CXXConstructor = 0,
+ CXXCopyConstructor = 1,
+ CXXCopyAssignment = 2,
+ CXXDestructor = 3
+ };
+ bool CheckNontrivialField(FieldDecl *FD);
+ void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
+ CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
+ void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls);
+ Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl,
+ Declarator &D, Expr *BitfieldWidth,
+ tok::ObjCKeywordKind visibility);
+
+ // This is used for both record definitions and ObjC interface declarations.
+ void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl,
+ Decl **Fields, unsigned NumFields,
+ SourceLocation LBrac, SourceLocation RBrac,
+ AttributeList *AttrList);
+
+ /// ActOnTagStartDefinition - Invoked when we have entered the
+ /// scope of a tag's definition (e.g., for an enumeration, class,
+ /// struct, or union).
+ void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
+
+ /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
+ /// C++ record definition's base-specifiers clause and are starting its
+ /// member declarations.
+ void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
+ ClassVirtSpecifiers &CVS,
+ SourceLocation LBraceLoc);
+
+ /// ActOnTagFinishDefinition - Invoked once we have finished parsing
+ /// the definition of a tag (enumeration, class, struct, or union).
+ void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
+ SourceLocation RBraceLoc);
+
+ /// ActOnTagDefinitionError - Invoked when there was an unrecoverable
+ /// error parsing the definition of a tag.
+ void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
+
+ EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ Expr *val);
+
+ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ AttributeList *Attrs,
+ SourceLocation EqualLoc, Expr *Val);
+ void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc, Decl *EnumDecl,
+ Decl **Elements, unsigned NumElements,
+ Scope *S, AttributeList *Attr);
+
+ DeclContext *getContainingDC(DeclContext *DC);
+
+ /// Set the current declaration context until it gets popped.
+ void PushDeclContext(Scope *S, DeclContext *DC);
+ void PopDeclContext();
+
+ /// EnterDeclaratorContext - Used when we must lookup names in the context
+ /// of a declarator's nested name specifier.
+ void EnterDeclaratorContext(Scope *S, DeclContext *DC);
+ void ExitDeclaratorContext(Scope *S);
+
+ DeclContext *getFunctionLevelDeclContext();
+
+ /// getCurFunctionDecl - If inside of a function body, this returns a pointer
+ /// to the function decl for the function being parsed. If we're currently
+ /// in a 'block', this returns the containing context.
+ FunctionDecl *getCurFunctionDecl();
+
+ /// getCurMethodDecl - If inside of a method body, this returns a pointer to
+ /// the method decl for the method being parsed. If we're currently
+ /// in a 'block', this returns the containing context.
+ ObjCMethodDecl *getCurMethodDecl();
+
+ /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
+ /// or C function we're in, otherwise return null. If we're currently
+ /// in a 'block', this returns the containing context.
+ NamedDecl *getCurFunctionOrMethodDecl();
+
+ /// Add this decl to the scope shadowed decl chains.
+ void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0);
+
+ /// Finds the scope corresponding to the given decl context, if it
+ /// happens to be an enclosing scope. Otherwise return NULL.
+ static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC);
+
+ /// Subroutines of ActOnDeclarator().
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ TypeSourceInfo *TInfo);
+ void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
+ bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
+ bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+ void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
+ void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
+ bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
+
+ // AssignmentAction - This is used by all the assignment diagnostic functions
+ // to represent what is actually causing the operation
+ enum AssignmentAction {
+ AA_Assigning,
+ AA_Passing,
+ AA_Returning,
+ AA_Converting,
+ AA_Initializing,
+ AA_Sending,
+ AA_Casting
+ };
+
+ /// C++ Overloading.
+ enum OverloadKind {
+ /// This is a legitimate overload: the existing declarations are
+ /// functions or function templates with different signatures.
+ Ovl_Overload,
+
+ /// This is not an overload because the signature exactly matches
+ /// an existing declaration.
+ Ovl_Match,
+
+ /// This is not an overload because the lookup results contain a
+ /// non-function.
+ Ovl_NonFunction
+ };
+ OverloadKind CheckOverload(Scope *S,
+ FunctionDecl *New,
+ const LookupResult &OldDecls,
+ NamedDecl *&OldDecl,
+ bool IsForUsingDecl);
+ bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl);
+
+ bool TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *From,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle);
+
+ bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
+ bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+ bool IsComplexPromotion(QualType FromType, QualType ToType);
+ bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ bool InOverloadResolution,
+ QualType& ConvertedType, bool &IncompatibleObjC);
+ bool isObjCPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType, bool &IncompatibleObjC);
+ bool IsBlockPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType);
+ bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType);
+
+ bool CheckPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath& BasePath,
+ bool IgnoreBaseAccess);
+ bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ bool InOverloadResolution,
+ QualType &ConvertedType);
+ bool CheckMemberPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
+ bool IgnoreBaseAccess);
+ bool IsQualificationConversion(QualType FromType, QualType ToType,
+ bool CStyle);
+ bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
+
+
+ ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *Value);
+
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init);
+ bool PerformObjectArgumentInitialization(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ bool PerformContextuallyConvertToBool(Expr *&From);
+ bool PerformContextuallyConvertToObjCId(Expr *&From);
+
+ ExprResult
+ ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
+ const PartialDiagnostic &NotIntDiag,
+ const PartialDiagnostic &IncompleteDiag,
+ const PartialDiagnostic &ExplicitConvDiag,
+ const PartialDiagnostic &ExplicitConvNote,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &AmbigNote,
+ const PartialDiagnostic &ConvDiag);
+
+ bool PerformObjectMemberConversion(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member);
+
+ // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+ // TODO: make this is a typesafe union.
+ typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet;
+ typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
+
+ void AddOverloadCandidate(NamedDecl *Function,
+ DeclAccessPair FoundDecl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet);
+
+ void AddOverloadCandidate(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddMethodCandidate(DeclAccessPair FoundDecl,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversion = false);
+ void AddMethodCandidate(CXXMethodDecl *Method,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false);
+ void AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet);
+ void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet);
+ void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const FunctionProtoType *Proto,
+ Expr *Object, Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ SourceRange OpRange = SourceRange());
+ void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool IsAssignmentOperator = false,
+ unsigned NumContextualBoolArguments = 0);
+ void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet);
+ void AddArgumentDependentLookupCandidates(DeclarationName Name,
+ bool Operator,
+ Expr **Args, unsigned NumArgs,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool PartialOverloading = false);
+
+ // Emit as a 'note' the specific overload candidate
+ void NoteOverloadCandidate(FunctionDecl *Fn);
+
+ // Emit as a series of 'note's all template and non-templates
+ // identified by the expression Expr
+ void NoteAllOverloadCandidates(Expr* E);
+
+ // [PossiblyAFunctionType] --> [Return]
+ // NonFunctionType --> NonFunctionType
+ // R (A) --> R(A)
+ // R (*)(A) --> R (A)
+ // R (&)(A) --> R (A)
+ // R (S::*)(A) --> R (A)
+ QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
+
+ FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+ bool Complain,
+ DeclAccessPair &Found);
+
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From,
+ bool Complain = false,
+ DeclAccessPair* Found = 0);
+
+ Expr *FixOverloadedFunctionReference(Expr *E,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+
+ void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading = false);
+
+ ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig);
+
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input);
+
+ ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS);
+
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ Expr *Base,Expr *Idx);
+
+ ExprResult
+ BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
+ SourceLocation LParenLoc, Expr **Args,
+ unsigned NumArgs, SourceLocation RParenLoc);
+ ExprResult
+ BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc);
+
+ /// CheckCallReturnType - Checks that a call expression's return type is
+ /// complete. Returns true on failure. The location passed in is the location
+ /// that best represents the call.
+ bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+ CallExpr *CE, FunctionDecl *FD);
+
+ /// Helpers for dealing with blocks and functions.
+ bool CheckParmsForFunctionDef(ParmVarDecl **Param, ParmVarDecl **ParamEnd,
+ bool CheckParameterNames);
+ void CheckCXXDefaultArguments(FunctionDecl *FD);
+ void CheckExtraCXXDefaultArguments(Declarator &D);
+ Scope *getNonFieldDeclScope(Scope *S);
+
+ /// \name Name lookup
+ ///
+ /// These routines provide name lookup that is used during semantic
+ /// analysis to resolve the various kinds of names (identifiers,
+ /// overloaded operator names, constructor names, etc.) into zero or
+ /// more declarations within a particular scope. The major entry
+ /// points are LookupName, which performs unqualified name lookup,
+ /// and LookupQualifiedName, which performs qualified name lookup.
+ ///
+ /// All name lookup is performed based on some specific criteria,
+ /// which specify what names will be visible to name lookup and how
+ /// far name lookup should work. These criteria are important both
+ /// for capturing language semantics (certain lookups will ignore
+ /// certain names, for example) and for performance, since name
+ /// lookup is often a bottleneck in the compilation of C++. Name
+ /// lookup criteria is specified via the LookupCriteria enumeration.
+ ///
+ /// The results of name lookup can vary based on the kind of name
+ /// lookup performed, the current language, and the translation
+ /// unit. In C, for example, name lookup will either return nothing
+ /// (no entity found) or a single declaration. In C++, name lookup
+ /// can additionally refer to a set of overloaded functions or
+ /// result in an ambiguity. All of the possible results of name
+ /// lookup are captured by the LookupResult class, which provides
+ /// the ability to distinguish among them.
+ //@{
+
+ /// @brief Describes the kind of name lookup to perform.
+ enum LookupNameKind {
+ /// Ordinary name lookup, which finds ordinary names (functions,
+ /// variables, typedefs, etc.) in C and most kinds of names
+ /// (functions, variables, members, types, etc.) in C++.
+ LookupOrdinaryName = 0,
+ /// Tag name lookup, which finds the names of enums, classes,
+ /// structs, and unions.
+ LookupTagName,
+ /// Label name lookup.
+ LookupLabel,
+ /// Member name lookup, which finds the names of
+ /// class/struct/union members.
+ LookupMemberName,
+ /// Look up of an operator name (e.g., operator+) for use with
+ /// operator overloading. This lookup is similar to ordinary name
+ /// lookup, but will ignore any declarations that are class members.
+ LookupOperatorName,
+ /// Look up of a name that precedes the '::' scope resolution
+ /// operator in C++. This lookup completely ignores operator, object,
+ /// function, and enumerator names (C++ [basic.lookup.qual]p1).
+ LookupNestedNameSpecifierName,
+ /// Look up a namespace name within a C++ using directive or
+ /// namespace alias definition, ignoring non-namespace names (C++
+ /// [basic.lookup.udir]p1).
+ LookupNamespaceName,
+ /// Look up all declarations in a scope with the given name,
+ /// including resolved using declarations. This is appropriate
+ /// for checking redeclarations for a using declaration.
+ LookupUsingDeclName,
+ /// Look up an ordinary name that is going to be redeclared as a
+ /// name with linkage. This lookup ignores any declarations that
+ /// are outside of the current scope unless they have linkage. See
+ /// C99 6.2.2p4-5 and C++ [basic.link]p6.
+ LookupRedeclarationWithLinkage,
+ /// Look up the name of an Objective-C protocol.
+ LookupObjCProtocolName,
+ /// \brief Look up any declaration with any name.
+ LookupAnyName
+ };
+
+ /// \brief Specifies whether (or how) name lookup is being performed for a
+ /// redeclaration (vs. a reference).
+ enum RedeclarationKind {
+ /// \brief The lookup is a reference to this name that is not for the
+ /// purpose of redeclaring the name.
+ NotForRedeclaration = 0,
+ /// \brief The lookup results will be used for redeclaration of a name,
+ /// if an entity by that name already exists.
+ ForRedeclaration
+ };
+
+private:
+ bool CppLookupName(LookupResult &R, Scope *S);
+
+public:
+ /// \brief Look up a name, looking for a single declaration. Return
+ /// null if the results were absent, ambiguous, or overloaded.
+ ///
+ /// It is preferable to use the elaborated form and explicitly handle
+ /// ambiguity and overloaded.
+ NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
+ SourceLocation Loc,
+ LookupNameKind NameKind,
+ RedeclarationKind Redecl
+ = NotForRedeclaration);
+ bool LookupName(LookupResult &R, Scope *S,
+ bool AllowBuiltinCreation = false);
+ bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+ bool InUnqualifiedLookup = false);
+ bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ bool AllowBuiltinCreation = false,
+ bool EnteringContext = false);
+ ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc);
+
+ void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+ QualType T1, QualType T2,
+ UnresolvedSetImpl &Functions);
+
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
+ bool isLocalLabel = false);
+
+ DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+ CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+
+ void ArgumentDependentLookup(DeclarationName Name, bool Operator,
+ Expr **Args, unsigned NumArgs,
+ ADLResult &Functions);
+
+ void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+ void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+
+ /// \brief The context in which typo-correction occurs.
+ ///
+ /// The typo-correction context affects which keywords (if any) are
+ /// considered when trying to correct for typos.
+ enum CorrectTypoContext {
+ /// \brief An unknown context, where any keyword might be valid.
+ CTC_Unknown,
+ /// \brief A context where no keywords are used (e.g. we expect an actual
+ /// name).
+ CTC_NoKeywords,
+ /// \brief A context where we're correcting a type name.
+ CTC_Type,
+ /// \brief An expression context.
+ CTC_Expression,
+ /// \brief A type cast, or anything else that can be followed by a '<'.
+ CTC_CXXCasts,
+ /// \brief A member lookup context.
+ CTC_MemberLookup,
+ /// \brief An Objective-C ivar lookup context (e.g., self->ivar).
+ CTC_ObjCIvarLookup,
+ /// \brief An Objective-C property lookup context (e.g., self.prop).
+ CTC_ObjCPropertyLookup,
+ /// \brief The receiver of an Objective-C message send within an
+ /// Objective-C method where 'super' is a valid keyword.
+ CTC_ObjCMessageReceiver
+ };
+
+ DeclarationName CorrectTypo(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ DeclContext *MemberContext = 0,
+ bool EnteringContext = false,
+ CorrectTypoContext CTC = CTC_Unknown,
+ const ObjCObjectPointerType *OPT = 0);
+
+ void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
+
+ bool DiagnoseAmbiguousLookup(LookupResult &Result);
+ //@}
+
+ ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection = false);
+ NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ Scope *S, bool ForRedeclaration,
+ SourceLocation Loc);
+ NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+ Scope *S);
+ void AddKnownFunctionAttributes(FunctionDecl *FD);
+
+ // More parsing and symbol table subroutines.
+
+ // Decl attributes - this routine is the top level dispatcher.
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
+ bool NonInheritable = true, bool Inheritable = true);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
+ bool NonInheritable = true, bool Inheritable = true);
+
+ bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
+ bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);
+ bool CheckNoReturnAttr(const AttributeList &attr);
+
+ void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+ bool &IncompleteImpl, unsigned DiagID);
+ void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
+ ObjCMethodDecl *IntfMethod);
+
+ bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
+ ObjCInterfaceDecl *IDecl);
+
+ typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
+
+ /// CheckProtocolMethodDefs - This routine checks unimplemented
+ /// methods declared in protocol, and those referenced by it.
+ /// \param IDecl - Used for checking for methods which may have been
+ /// inherited.
+ void CheckProtocolMethodDefs(SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
+ bool& IncompleteImpl,
+ const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
+ ObjCContainerDecl *CDecl);
+
+ /// CheckImplementationIvars - This routine checks if the instance variables
+ /// listed in the implelementation match those listed in the interface.
+ void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+ ObjCIvarDecl **Fields, unsigned nIvars,
+ SourceLocation Loc);
+
+ /// \brief Determine whether we can synthesize a provisional ivar for the
+ /// given name.
+ ObjCPropertyDecl *canSynthesizeProvisionalIvar(IdentifierInfo *II);
+
+ /// \brief Determine whether we can synthesize a provisional ivar for the
+ /// given property.
+ bool canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property);
+
+ /// ImplMethodsVsClassMethods - This is main routine to warn if any method
+ /// remains unimplemented in the class or category @implementation.
+ void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl,
+ bool IncompleteImpl = false);
+
+ /// DiagnoseUnimplementedProperties - This routine warns on those properties
+ /// which must be implemented by this implementation.
+ void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ const SelectorSet &InsMap);
+
+ /// DefaultSynthesizeProperties - This routine default synthesizes all
+ /// properties which must be synthesized in class's @implementation.
+ void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCInterfaceDecl *IDecl);
+
+ /// CollectImmediateProperties - This routine collects all properties in
+ /// the class and its conforming protocols; but not those it its super class.
+ void CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
+
+
+ /// LookupPropertyDecl - Looks up a property in the current class and all
+ /// its protocols.
+ ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+ IdentifierInfo *II);
+
+ /// Called by ActOnProperty to handle @property declarations in
+ //// class extensions.
+ Decl *HandlePropertyInClassExtension(Scope *S,
+ ObjCCategoryDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ bool *isOverridingProperty,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind);
+
+ /// Called by ActOnProperty and HandlePropertyInClassExtension to
+ /// handle creating the ObjcPropertyDecl for a category or @interface.
+ ObjCPropertyDecl *CreatePropertyDecl(Scope *S,
+ ObjCContainerDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = 0);
+
+ /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
+ /// warning) when atomic property has one but not the other user-declared
+ /// setter or getter.
+ void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl);
+
+ void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+
+ /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+ /// true, or false, accordingly.
+ bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+ const ObjCMethodDecl *PrevMethod,
+ bool matchBasedOnSizeAndAlignment = false,
+ bool matchBasedOnStrictEqulity = false);
+
+ /// MatchAllMethodDeclarations - Check methods declaraed in interface or
+ /// or protocol against those declared in their implementations.
+ void MatchAllMethodDeclarations(const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
+ SelectorSet &InsMapSeen,
+ SelectorSet &ClsMapSeen,
+ ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl,
+ bool &IncompleteImpl,
+ bool ImmediateClass);
+
+private:
+ /// AddMethodToGlobalPool - Add an instance or factory method to the global
+ /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+ void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+
+ /// LookupMethodInGlobalPool - Returns the instance or factory method and
+ /// optionally warns if there are multiple signatures.
+ ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass,
+ bool warn, bool instance);
+
+public:
+ /// AddInstanceMethodToGlobalPool - All instance methods in a translation
+ /// unit are added to a global pool. This allows us to efficiently associate
+ /// a selector with a method declaraation for purposes of typechecking
+ /// messages sent to "id" (where the class of the object is unknown).
+ void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/true);
+ }
+
+ /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ }
+
+ /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/true);
+ }
+
+ /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/false);
+ }
+
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+
+ /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+ /// initialization.
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ //===--------------------------------------------------------------------===//
+ // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+ class FullExprArg {
+ public:
+ FullExprArg(Sema &actions) : E(0) { }
+
+ // FIXME: The const_cast here is ugly. RValue references would make this
+ // much nicer (or we could duplicate a bunch of the move semantics
+ // emulation code from Ownership.h).
+ FullExprArg(const FullExprArg& Other) : E(Other.E) {}
+
+ ExprResult release() {
+ return move(E);
+ }
+
+ Expr *get() const { return E; }
+
+ Expr *operator->() {
+ return E;
+ }
+
+ private:
+ // FIXME: No need to make the entire Sema class a friend when it's just
+ // Sema::MakeFullExpr that needs access to the constructor below.
+ friend class Sema;
+
+ explicit FullExprArg(Expr *expr) : E(expr) {}
+
+ Expr *E;
+ };
+
+ FullExprArg MakeFullExpr(Expr *Arg) {
+ return FullExprArg(ActOnFinishFullExpr(Arg).release());
+ }
+
+ StmtResult ActOnExprStmt(FullExprArg Expr);
+
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+ bool LeadingEmptyMacro = false);
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ MultiStmtArg Elts,
+ bool isStmtExpr);
+ StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+ StmtResult ActOnForEachLValueExpr(Expr *E);
+ StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+ SourceLocation DotDotDotLoc, Expr *RHSVal,
+ SourceLocation ColonLoc);
+ void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
+
+ StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+ SourceLocation ColonLoc, Stmt *SubStmt);
+
+ StmtResult ActOnIfStmt(SourceLocation IfLoc,
+ FullExprArg CondVal, Decl *CondVar,
+ Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
+ StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+ Expr *Cond,
+ Decl *CondVar);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body);
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+ FullExprArg Cond,
+ Decl *CondVar, Stmt *Body);
+ StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+ SourceLocation WhileLoc,
+ SourceLocation CondLParen, Expr *Cond,
+ SourceLocation CondRParen);
+
+ StmtResult ActOnForStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, FullExprArg Second,
+ Decl *SecondVar,
+ FullExprArg Third,
+ SourceLocation RParenLoc,
+ Stmt *Body);
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, Expr *Second,
+ SourceLocation RParenLoc, Stmt *Body);
+
+ StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+ SourceLocation LabelLoc,
+ LabelDecl *TheDecl);
+ StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+ SourceLocation StarLoc,
+ Expr *DestExp);
+ StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
+ StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope);
+
+ const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
+ bool AllowFunctionParameters);
+
+ StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+
+ StmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple, bool IsVolatile,
+ unsigned NumOutputs, unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ Expr *AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm = false);
+
+
+ VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ bool Invalid = false);
+
+ Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+
+ StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+ Decl *Parm, Stmt *Body);
+
+ StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+
+ StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg Catch, Stmt *Finally);
+
+ StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw);
+ StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+ Scope *CurScope);
+ StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *SynchExpr,
+ Stmt *SynchBody);
+
+ VarDecl *BuildExceptionDeclaration(Scope *S,
+ TypeSourceInfo *TInfo,
+ IdentifierInfo *Name,
+ SourceLocation Loc);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ MultiStmtArg Handlers);
+ void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+
+ bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+
+ /// \brief If it's a file scoped decl that must warn if not used, keep track
+ /// of it.
+ void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+
+ /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+ /// whose result is unused, warn.
+ void DiagnoseUnusedExprResult(const Stmt *S);
+ void DiagnoseUnusedDecl(const NamedDecl *ND);
+
+ ParsingDeclState PushParsingDeclaration() {
+ return DelayedDiagnostics.pushParsingDecl();
+ }
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
+ DelayedDiagnostics::popParsingDecl(*this, state, decl);
+ }
+
+ typedef ProcessingContextState ParsingClassState;
+ ParsingClassState PushParsingClass() {
+ return DelayedDiagnostics.pushContext();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ DelayedDiagnostics.popContext(state);
+ }
+
+ void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
+ SourceLocation Loc, bool UnknownObjCClass=false);
+
+ void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks: SemaExpr.cpp.
+
+ bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool UnknownObjCClass=false);
+ bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
+ ObjCMethodDecl *Getter,
+ SourceLocation Loc);
+ void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+ Expr **Args, unsigned NumArgs);
+
+ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+
+ void PopExpressionEvaluationContext();
+
+ void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+ void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
+ void MarkDeclarationsReferencedInExpr(Expr *E);
+ bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+
+ // Primary Expressions.
+ SourceRange getExprRange(Expr *E) const;
+
+ ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name,
+ bool HasTrailingLParen, bool IsAddressOfOperand);
+
+ bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectTypoContext CTC = CTC_Unknown);
+
+ ExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
+
+ ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS = 0);
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS = 0);
+ ExprResult
+ BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ Expr *baseObjectExpr = 0,
+ SourceLocation opLoc = SourceLocation());
+ ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs);
+ ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool IsDefiniteInstance);
+ bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
+ const LookupResult &R,
+ bool HasTrailingLParen);
+
+ ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo);
+ ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool ADL);
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *D);
+
+ ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+ ExprResult ActOnNumericConstant(const Token &);
+ ExprResult ActOnCharacterConstant(const Token &);
+ ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *Val);
+ ExprResult ActOnParenOrParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val,
+ ParsedType TypeOfCast = ParsedType());
+
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
+
+ // Binary/Unary Operators. 'Tok' is the token for the operator.
+ ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
+ Expr *InputArg);
+ ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc, Expr *input);
+ ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input);
+
+ ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
+ SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult
+ ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+ void *TyOrEx, const SourceRange &ArgRange);
+
+ ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc);
+
+ bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
+ SourceRange R, bool isSizeof);
+ ExprResult ActOnSizeofParameterPackExpr(Scope *S,
+ SourceLocation OpLoc,
+ IdentifierInfo &Name,
+ SourceLocation NameLoc,
+ SourceLocation RParenLoc);
+ ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input);
+
+ ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool SuppressQualifierCheck = false);
+
+ ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+ bool &IsArrow, SourceLocation OpLoc,
+ CXXScopeSpec &SS,
+ Decl *ObjCImpDecl,
+ bool HasTemplateArgs);
+
+ bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+ const CXXScopeSpec &SS,
+ const LookupResult &R);
+
+ ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl,
+ bool HasTrailingLParen);
+
+ void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
+ bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+ /// This provides the location of the left/right parens and a list of comma
+ /// locations.
+ ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+ MultiExprArg Args, SourceLocation RParenLoc,
+ Expr *ExecConfig = 0);
+ ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig = 0);
+
+ ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg ExecConfig, SourceLocation GGGLoc);
+
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ ParsedType Ty, SourceLocation RParenLoc,
+ Expr *Op);
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
+
+ bool TypeIsVectorType(ParsedType Ty) {
+ return GetTypeFromParser(Ty)->isVectorType();
+ }
+
+ ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+ ExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
+
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
+
+ ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *InitExpr);
+
+ ExprResult ActOnInitList(SourceLocation LParenLoc,
+ MultiExprArg InitList,
+ SourceLocation RParenLoc);
+
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init);
+
+ ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind, Expr *LHS, Expr *RHS);
+ ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
+ ExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
+ BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
+
+ /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
+ /// in the case of a the GNU conditional expr extension.
+ ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ Expr *Cond, Expr *LHS, Expr *RHS);
+
+ /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *LD);
+
+ ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc); // "({..})"
+
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ struct OffsetOfComponent {
+ SourceLocation LocStart, LocEnd;
+ bool isBrackets; // true if [expr], false if .ident
+ union {
+ IdentifierInfo *IdentInfo;
+ ExprTy *E;
+ } U;
+ };
+
+ /// __builtin_offsetof(type, a.b[123][456].c)
+ ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
+ ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType Arg1,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
+
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *cond, Expr *expr1,
+ Expr *expr2, SourceLocation RPLoc);
+
+ // __builtin_va_arg(expr, type)
+ ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+ Expr *expr, ParsedType type,
+ SourceLocation RPLoc);
+ ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *expr, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc);
+
+ // __null
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
+ //===------------------------- "Block" Extension ------------------------===//
+
+ /// ActOnBlockStart - This callback is invoked when a block literal is
+ /// started.
+ void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+
+ /// ActOnBlockArguments - This callback allows processing of block arguments.
+ /// If there are no arguments, this is still invoked.
+ void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+
+ /// ActOnBlockError - If there is an error parsing a block, this callback
+ /// is invoked to pop the information about the block from the action impl.
+ void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+
+ /// ActOnBlockStmtExpr - This is called when the body of a block statement
+ /// literal was successfully completed. ^(int x){...}
+ ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope);
+
+ //===---------------------------- C++ Features --------------------------===//
+
+ // Act on C++ namespaces
+ Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ SourceLocation LBrace,
+ AttributeList *AttrList);
+ void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ CXXRecordDecl *getStdBadAlloc() const;
+
+ Decl *ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
+
+ void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident);
+
+ void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+ bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+ const LookupResult &PreviousDecls);
+ UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+ NamedDecl *Target);
+
+ bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+ bool isTypeName,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ const LookupResult &Previous);
+ bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc);
+
+ NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ AttributeList *AttrList,
+ bool IsInstantiation,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
+
+ bool CheckInheritedConstructorUsingDecl(UsingDecl *UD);
+
+ Decl *ActOnUsingDeclaration(Scope *CurScope,
+ AccessSpecifier AS,
+ bool HasUsingKeyword,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
+
+ /// AddCXXDirectInitializerToDecl - This action is called immediately after
+ /// ActOnDeclarator, when a C++ direct initializer is present.
+ /// e.g: "int x(1);"
+ void AddCXXDirectInitializerToDecl(Decl *Dcl,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc,
+ bool TypeMayContainAuto);
+
+ /// InitializeVarWithConstructor - Creates an CXXConstructExpr
+ /// and sets it as the initializer for the the passed in VarDecl.
+ bool InitializeVarWithConstructor(VarDecl *VD,
+ CXXConstructorDecl *Constructor,
+ MultiExprArg Exprs);
+
+ /// BuildCXXConstructExpr - Creates a complete call to a constructor,
+ /// including handling of its default argument expressions.
+ ///
+ /// \param ConstructKind - a CXXConstructExpr::ConstructionKind
+ ExprResult
+ BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor, MultiExprArg Exprs,
+ bool RequiresZeroInit, unsigned ConstructKind,
+ SourceRange ParenRange);
+
+ // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
+ // the constructor can be elidable?
+ ExprResult
+ BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor, bool Elidable,
+ MultiExprArg Exprs, bool RequiresZeroInit,
+ unsigned ConstructKind,
+ SourceRange ParenRange);
+
+ /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+ /// the default expr if needed.
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD,
+ ParmVarDecl *Param);
+
+ /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+ /// constructed variable.
+ void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+
+ /// \brief Declare the implicit default constructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// default constructor will be added.
+ ///
+ /// \returns The implicitly-declared default constructor.
+ CXXConstructorDecl *DeclareImplicitDefaultConstructor(
+ CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitDefaultConstructor - Checks for feasibility of
+ /// defining this constructor as the default constructor.
+ void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
+
+ /// \brief Declare the implicit destructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// destructor will be added.
+ ///
+ /// \returns The implicitly-declared destructor.
+ CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitDestructor - Checks for feasibility of
+ /// defining this destructor as the default destructor.
+ void DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor);
+
+ /// \brief Declare all inherited constructors for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the inherited
+ /// constructors will be added.
+ void DeclareInheritedConstructors(CXXRecordDecl *ClassDecl);
+
+ /// \brief Declare the implicit copy constructor for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy constructor will be added.
+ ///
+ /// \returns The implicitly-declared copy constructor.
+ CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitCopyConstructor - Checks for feasibility of
+ /// defining this constructor as the copy constructor.
+ void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor,
+ unsigned TypeQuals);
+
+ /// \brief Declare the implicit copy assignment operator for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy-assignment operator will be added.
+ ///
+ /// \returns The implicitly-declared copy assignment operator.
+ CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
+
+ /// \brief Defined an implicitly-declared copy assignment operator.
+ void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// \brief Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
+ /// MaybeBindToTemporary - If the passed in expression has a record type with
+ /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
+ /// it simply returns the passed in expression.
+ ExprResult MaybeBindToTemporary(Expr *E);
+
+ bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ ASTOwningVector<Expr*> &ConvertedArgs);
+
+ ParsedType getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc,
+ ParsedType Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc,
+ Expr *E,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ Expr *E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
+
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXTypeid - Parse typeid( something ).
+ ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXUuidof - Parse __uuidof( something ).
+ ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
+
+
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// tryCaptureCXXThis - Try to capture a 'this' pointer. Returns a
+ /// pointer to an instance method whose 'this' pointer is
+ /// capturable, or null if this is not possible.
+ CXXMethodDecl *tryCaptureCXXThis();
+
+ /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+
+ //// ActOnCXXThrow - Parse throw expressions.
+ ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr);
+ bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E);
+
+ /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+ /// Can be interpreted either as function-style casting ("int(x)")
+ /// or class type construction ("ClassType(x,y,z)")
+ /// or creation of a value-initialized type ("int()").
+ ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc);
+
+ /// ActOnCXXNew - Parsed a C++ 'new' expression.
+ ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens, Declarator &D,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen);
+ ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocType,
+ TypeSourceInfo *AllocTypeInfo,
+ Expr *ArraySize,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen,
+ bool TypeMayContainAuto = true);
+
+ bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R);
+ bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType, bool IsArray,
+ Expr **PlaceArgs, unsigned NumPlaceArgs,
+ FunctionDecl *&OperatorNew,
+ FunctionDecl *&OperatorDelete);
+ bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, Expr** Args,
+ unsigned NumArgs, DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator);
+ void DeclareGlobalNewDelete();
+ void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
+ QualType Argument,
+ bool addMallocAttr = false);
+
+ bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name, FunctionDecl* &Operator);
+
+ /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+ ExprResult ActOnCXXDelete(SourceLocation StartLoc,
+ bool UseGlobal, bool ArrayForm,
+ Expr *Operand);
+
+ DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
+ ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+ SourceLocation StmtLoc,
+ bool ConvertToBoolean);
+
+ ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+ Expr *Operand, SourceLocation RParen);
+ ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+ SourceLocation RParen);
+
+ /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ ParsedType Ty,
+ SourceLocation RParen);
+
+ ExprResult BuildUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *T,
+ SourceLocation RParen);
+
+ /// ActOnBinaryTypeTrait - Parsed one of the bianry type trait support
+ /// pseudo-functions.
+ ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ ParsedType RhsTy,
+ SourceLocation RParen);
+
+ ExprResult BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *LhsT,
+ TypeSourceInfo *RhsT,
+ SourceLocation RParen);
+
+ ExprResult ActOnStartCXXMemberReference(Scope *S,
+ Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor);
+
+ ExprResult DiagnoseDtorReference(SourceLocation NameLoc, Expr *MemExpr);
+
+ ExprResult BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType,
+ bool HasTrailingLParen);
+
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen);
+
+ /// MaybeCreateExprWithCleanups - If the current full-expression
+ /// requires any cleanups, surround it with a ExprWithCleanups node.
+ /// Otherwise, just returns the passed-in expression.
+ Expr *MaybeCreateExprWithCleanups(Expr *SubExpr);
+ Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
+ ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
+
+ ExprResult ActOnFinishFullExpr(Expr *Expr);
+ StmtResult ActOnFinishFullStmt(Stmt *Stmt);
+
+ // Marks SS invalid if it represents an incomplete type.
+ bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
+
+ DeclContext *computeDeclContext(QualType T);
+ DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+ bool EnteringContext = false);
+ bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+ bool isUnknownSpecialization(const CXXScopeSpec &SS);
+
+ /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+ /// global scope ('::').
+ NestedNameSpecifier *
+ ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
+
+ bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+
+ bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType);
+
+ NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *ScopeLookupResult,
+ bool EnteringContext,
+ bool ErrorRecoveryLookup);
+
+ NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+ /// nested-name-specifier that involves a template-id, e.g.,
+ /// "foo::bar<int, float>::", and now we need to build a scope
+ /// specifier. \p SS is empty or the previously parsed nested-name
+ /// part ("foo::"), \p Type is the already-parsed class template
+ /// specialization (or other template-id that names a type), \p
+ /// TypeRange is the source range where the type is located, and \p
+ /// CCLoc is the location of the trailing '::'.
+ CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ ParsedType Type,
+ SourceRange TypeRange,
+ SourceLocation CCLoc);
+
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+ /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+ /// After this method is called, according to [C++ 3.4.3p3], names should be
+ /// looked up in the declarator-id's scope, until the declarator is parsed and
+ /// ActOnCXXExitDeclaratorScope is called.
+ /// The 'SS' should be a non-empty valid CXXScopeSpec.
+ bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
+
+ /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+ /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+ /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+ /// Used to indicate that names should revert to being looked up in the
+ /// defining scope.
+ void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+ /// initializer for the declaration 'Dcl'.
+ /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+ /// static data member of class X, names should be looked up in the scope of
+ /// class X.
+ void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl);
+
+ /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+ /// initializer for the declaration 'Dcl'.
+ void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ Expr **Strings,
+ unsigned NumStrings);
+
+ Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc);
+
+ // ParseObjCSelectorExpression - Build selector expression for @selector
+ ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ // ParseObjCProtocolExpression - Build protocol expression for @protocol
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Declarations
+ //
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ llvm::StringRef Lang,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C++ Classes
+ //
+ bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0);
+
+ Decl *ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc);
+
+ Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Expr *BitfieldWidth, const VirtSpecifiers &VS,
+ Expr *Init, bool IsDefinition,
+ bool Deleted = false);
+
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args,
+ unsigned NumArgs, SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ MemInitResult BuildBaseInitializer(QualType BaseType,
+ TypeSourceInfo *BaseTInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ SourceLocation LParenLoc,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ bool SetCtorInitializers(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer **Initializers,
+ unsigned NumInitializers, bool AnyErrors);
+
+ void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+
+
+ /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+ /// mark all the non-trivial destructors of its members and bases as
+ /// referenced.
+ void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+ CXXRecordDecl *Record);
+
+ /// \brief The list of classes whose vtables have been used within
+ /// this translation unit, and the source locations at which the
+ /// first use occurred.
+ typedef std::pair<CXXRecordDecl*, SourceLocation> VTableUse;
+
+ /// \brief The list of vtables that are required but have not yet been
+ /// materialized.
+ llvm::SmallVector<VTableUse, 16> VTableUses;
+
+ /// \brief The set of classes whose vtables have been used within
+ /// this translation unit, and a bit that will be true if the vtable is
+ /// required to be emitted (otherwise, it should be emitted only if needed
+ /// by code generation).
+ llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed;
+
+ /// \brief A list of all of the dynamic classes in this translation
+ /// unit.
+ llvm::SmallVector<CXXRecordDecl *, 16> DynamicClasses;
+
+ /// \brief Note that the vtable for the given class was used at the
+ /// given location.
+ void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired = false);
+
+ /// MarkVirtualMembersReferenced - Will mark all members of the given
+ /// CXXRecordDecl referenced.
+ void MarkVirtualMembersReferenced(SourceLocation Loc,
+ const CXXRecordDecl *RD);
+
+ /// \brief Define all of the vtables that have been used in this
+ /// translation unit and reference any virtual members used by those
+ /// vtables.
+ ///
+ /// \returns true if any work was done, false otherwise.
+ bool DefineUsedVTables();
+
+ void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+
+ void ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors);
+
+ void CheckCompletedCXXClass(CXXRecordDecl *Record);
+ void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ Decl *TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac,
+ AttributeList *AttrList);
+
+ void ActOnReenterTemplateScope(Scope *S, Decl *Template);
+ void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
+ void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+
+ Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr);
+
+ FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc,
+ TypeSourceInfo *TSInfo);
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams);
+ Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
+ MultiTemplateParamsArg TemplateParams);
+
+ QualType CheckConstructorDeclarator(Declarator &D, QualType R,
+ StorageClass& SC);
+ void CheckConstructor(CXXConstructorDecl *Constructor);
+ QualType CheckDestructorDeclarator(Declarator &D, QualType R,
+ StorageClass& SC);
+ bool CheckDestructor(CXXDestructorDecl *Destructor);
+ void CheckConversionDeclarator(Declarator &D, QualType &R,
+ StorageClass& SC);
+ Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Derived Classes
+ //
+
+ /// ActOnBaseSpecifier - Parsed a base specifier
+ CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc);
+
+ BaseResult ActOnBaseSpecifier(Decl *classdecl,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
+
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+ unsigned NumBases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, unsigned NumBases);
+
+ bool IsDerivedFrom(QualType Derived, QualType Base);
+ bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
+
+ // FIXME: I don't like this name.
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+
+ bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath);
+
+ bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ SourceLocation Loc, SourceRange Range,
+ CXXCastPath *BasePath = 0,
+ bool IgnoreAccess = false);
+ bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ unsigned InaccessibleBaseID,
+ unsigned AmbigiousBaseConvID,
+ SourceLocation Loc, SourceRange Range,
+ DeclarationName Name,
+ CXXCastPath *BasePath);
+
+ std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+
+ /// CheckOverridingFunctionReturnType - Checks whether the return types are
+ /// covariant, according to C++ [class.virtual]p5.
+ bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+ /// spec is a subset of base spec.
+ bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+
+ /// CheckOverrideControl - Check C++0x override control semantics.
+ void CheckOverrideControl(const Decl *D);
+
+ /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
+ /// overrides a virtual member function marked 'final', according to
+ /// C++0x [class.virtual]p3.
+ bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+
+ //===--------------------------------------------------------------------===//
+ // C++ Access Control
+ //
+
+ enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent,
+ AR_delayed
+ };
+
+ bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+ NamedDecl *PrevMemberDecl,
+ AccessSpecifier LexicalAS);
+
+ AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
+ SourceRange PlacementRange,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp = false);
+ AccessResult CheckDestructorAccess(SourceLocation Loc,
+ CXXDestructorDecl *Dtor,
+ const PartialDiagnostic &PDiag);
+ AccessResult CheckDirectMemberAccess(SourceLocation Loc,
+ NamedDecl *D,
+ const PartialDiagnostic &PDiag);
+ AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
+ Expr *ObjectExpr,
+ Expr *ArgExpr,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair FoundDecl);
+ AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
+ QualType Base, QualType Derived,
+ const CXXBasePath &Path,
+ unsigned DiagID,
+ bool ForceCheck = false,
+ bool ForceUnprivileged = false);
+ void CheckLookupAccess(const LookupResult &R);
+
+ void HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void PerformDependentDiagnostics(const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ /// A flag to suppress access checking.
+ bool SuppressAccessChecking;
+
+ /// \brief When true, access checking violations are treated as SFINAE
+ /// failures rather than hard errors.
+ bool AccessCheckingSFINAE;
+
+ void ActOnStartSuppressingAccessChecks();
+ void ActOnStopSuppressingAccessChecks();
+
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType,
+ AbstractArrayType
+ };
+
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD);
+ void DiagnoseAbstractType(const CXXRecordDecl *RD);
+
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+ AbstractDiagSelID SelID = AbstractNone);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Overloaded Operators [C++ 13.5]
+ //
+
+ bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
+ bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Templates [C++ 14]
+ //
+ void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
+ QualType ObjectType, bool EnteringContext,
+ bool &MemberOfUnknownSpecialization);
+
+ TemplateNameKind isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization);
+
+ bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
+
+ bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+
+ Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg);
+
+ QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+ Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ Expr *DefaultArg);
+ Decl *ActOnTemplateTemplateParameter(Scope *S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
+ SourceLocation EllipsisLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedTemplateArgument DefaultArg);
+
+ TemplateParamsTy *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ Decl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+ /// \brief The context in which we are checking a template parameter
+ /// list.
+ enum TemplateParamListContext {
+ TPC_ClassTemplate,
+ TPC_FunctionTemplate,
+ TPC_ClassTemplateMember,
+ TPC_FriendFunctionTemplate,
+ TPC_FriendFunctionTemplateDefinition
+ };
+
+ bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+ TemplateParameterList *OldParams,
+ TemplateParamListContext TPC);
+ TemplateParameterList *
+ MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+ const CXXScopeSpec &SS,
+ TemplateParameterList **ParamLists,
+ unsigned NumParamLists,
+ bool IsFriend,
+ bool &IsExplicitSpecialization,
+ bool &Invalid);
+
+ DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ TemplateParameterList *TemplateParams,
+ AccessSpecifier AS);
+
+ void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+ TemplateArgumentListInfo &Out);
+
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ TypeResult
+ ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc);
+
+ TypeResult ActOnTagTemplateIdType(CXXScopeSpec &SS,
+ TypeResult Type,
+ TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc);
+
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo &TemplateArgs);
+ ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ TemplateNameKind ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template);
+
+ DeclResult
+ ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists);
+
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPtOfInstantiation,
+ bool &SuppressNew);
+
+ bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ LookupResult &Previous);
+
+ bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous);
+ bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+
+ DeclResult
+ ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr);
+
+ DeclResult
+ ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ AttributeList *Attr);
+
+ DeclResult ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D);
+
+ TemplateArgumentLoc
+ SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ Decl *Param,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
+
+ /// \brief Specifies the context in which a particular template
+ /// argument is being checked.
+ enum CheckTemplateArgumentKind {
+ /// \brief The template argument was specified in the code or was
+ /// instantiated with some deduced template arguments.
+ CTAK_Specified,
+
+ /// \brief The template argument was deduced via template argument
+ /// deduction.
+ CTAK_Deduced,
+
+ /// \brief The template argument was deduced from an array bound
+ /// via template argument deduction.
+ CTAK_DeducedFromArrayBound
+ };
+
+ bool CheckTemplateArgument(NamedDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ NamedDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ unsigned ArgumentPackIndex,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+
+ bool CheckTemplateArgumentList(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs,
+ bool PartialTemplateArgs,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
+
+ bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted);
+
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ TypeSourceInfo *Arg);
+ bool CheckTemplateArgumentPointerToMember(Expr *Arg,
+ TemplateArgument &Converted);
+ bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *&Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ const TemplateArgumentLoc &Arg);
+
+ ExprResult
+ BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+ QualType ParamType,
+ SourceLocation Loc);
+ ExprResult
+ BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc);
+
+ /// \brief Enumeration describing how template parameter lists are compared
+ /// for equality.
+ enum TemplateParameterListEqualKind {
+ /// \brief We are matching the template parameter lists of two templates
+ /// that might be redeclarations.
+ ///
+ /// \code
+ /// template<typename T> struct X;
+ /// template<typename T> struct X;
+ /// \endcode
+ TPL_TemplateMatch,
+
+ /// \brief We are matching the template parameter lists of two template
+ /// template parameters as part of matching the template parameter lists
+ /// of two templates that might be redeclarations.
+ ///
+ /// \code
+ /// template<template<int I> class TT> struct X;
+ /// template<template<int Value> class Other> struct X;
+ /// \endcode
+ TPL_TemplateTemplateParmMatch,
+
+ /// \brief We are matching the template parameter lists of a template
+ /// template argument against the template parameter lists of a template
+ /// template parameter.
+ ///
+ /// \code
+ /// template<template<int Value> class Metafun> struct X;
+ /// template<int Value> struct integer_c;
+ /// X<integer_c> xic;
+ /// \endcode
+ TPL_TemplateTemplateArgumentMatch
+ };
+
+ bool TemplateParameterListsAreEqual(TemplateParameterList *New,
+ TemplateParameterList *Old,
+ bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc
+ = SourceLocation());
+
+ bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier, e.g., "typename T::type".
+ ///
+ /// \param S The scope in which this typename type occurs.
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param II the identifier we're retrieving (e.g., 'type' in the example).
+ /// \param IdLoc the location of the identifier.
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc);
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier that ends in a template-id, e.g.,
+ /// "typename MetaFun::template apply<T1, T2>".
+ ///
+ /// \param S The scope in which this typename type occurs.
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param TemplateLoc the location of the 'template' keyword, if any.
+ /// \param Ty the type that the typename specifier refers to.
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ ParsedType Ty);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo &II,
+ SourceLocation KeywordLoc,
+ SourceRange NNSRange,
+ SourceLocation IILoc);
+
+ TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+ SourceLocation Loc,
+ DeclarationName Name);
+ bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+
+ ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgumentList &Args);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Variadic Templates (C++0x [temp.variadic])
+ //===--------------------------------------------------------------------===//
+
+ /// \brief The context in which an unexpanded parameter pack is
+ /// being diagnosed.
+ ///
+ /// Note that the values of this enumeration line up with the first
+ /// argument to the \c err_unexpanded_parameter_pack diagnostic.
+ enum UnexpandedParameterPackContext {
+ /// \brief An arbitrary expression.
+ UPPC_Expression = 0,
+
+ /// \brief The base type of a class type.
+ UPPC_BaseType,
+
+ /// \brief The type of an arbitrary declaration.
+ UPPC_DeclarationType,
+
+ /// \brief The type of a data member.
+ UPPC_DataMemberType,
+
+ /// \brief The size of a bit-field.
+ UPPC_BitFieldWidth,
+
+ /// \brief The expression in a static assertion.
+ UPPC_StaticAssertExpression,
+
+ /// \brief The fixed underlying type of an enumeration.
+ UPPC_FixedUnderlyingType,
+
+ /// \brief The enumerator value.
+ UPPC_EnumeratorValue,
+
+ /// \brief A using declaration.
+ UPPC_UsingDeclaration,
+
+ /// \brief A friend declaration.
+ UPPC_FriendDeclaration,
+
+ /// \brief A declaration qualifier.
+ UPPC_DeclarationQualifier,
+
+ /// \brief An initializer.
+ UPPC_Initializer,
+
+ /// \brief A default argument.
+ UPPC_DefaultArgument,
+
+ /// \brief The type of a non-type template parameter.
+ UPPC_NonTypeTemplateParameterType,
+
+ /// \brief The type of an exception.
+ UPPC_ExceptionType,
+
+ /// \brief Partial specialization.
+ UPPC_PartialSpecialization
+ };
+
+ /// \brief If the given type contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param Loc The source location where a diagnostc should be emitted.
+ ///
+ /// \param T The type that is being checked for unexpanded parameter
+ /// packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given expression contains an unexpanded parameter
+ /// pack, diagnose the error.
+ ///
+ /// \param E The expression that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(Expr *E,
+ UnexpandedParameterPackContext UPPC = UPPC_Expression);
+
+ /// \brief If the given nested-name-specifier contains an unexpanded
+ /// parameter pack, diagnose the error.
+ ///
+ /// \param SS The nested-name-specifier that is being checked for
+ /// unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given name contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param NameInfo The name (with source location information) that
+ /// is being checked for unexpanded parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given template name contains an unexpanded parameter pack,
+ /// diagnose the error.
+ ///
+ /// \param Loc The location of the template name.
+ ///
+ /// \param Template The template name that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+ TemplateName Template,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief If the given template argument contains an unexpanded parameter
+ /// pack, diagnose the error.
+ ///
+ /// \param Arg The template argument that is being checked for unexpanded
+ /// parameter packs.
+ ///
+ /// \returns true if an error ocurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
+ UnexpandedParameterPackContext UPPC);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// template argument.
+ ///
+ /// \param Arg The template argument that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TemplateArgument Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// template argument.
+ ///
+ /// \param Arg The template argument that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// type.
+ ///
+ /// \param T The type that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(QualType T,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// type.
+ ///
+ /// \param TL The type that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Invoked when parsing a template argument followed by an
+ /// ellipsis, which creates a pack expansion.
+ ///
+ /// \param Arg The template argument preceding the ellipsis, which
+ /// may already be invalid.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+ SourceLocation EllipsisLoc);
+
+ /// \brief Invoked when parsing a type followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Type The type preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Pattern The expression preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
+
+ /// \brief Invoked when parsing an expression followed by an ellipsis, which
+ /// creates a pack expansion.
+ ///
+ /// \param Pattern The expression preceding the ellipsis, which will become
+ /// the pattern of the pack expansion.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Determine whether we could expand a pack expansion with the
+ /// given set of parameter packs into separate arguments by repeatedly
+ /// transforming the pattern.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis that identifies the
+ /// pack expansion.
+ ///
+ /// \param PatternRange The source range that covers the entire pattern of
+ /// the pack expansion.
+ ///
+ /// \param Unexpanded The set of unexpanded parameter packs within the
+ /// pattern.
+ ///
+ /// \param NumUnexpanded The number of unexpanded parameter packs in
+ /// \p Unexpanded.
+ ///
+ /// \param ShouldExpand Will be set to \c true if the transformer should
+ /// expand the corresponding pack expansions into separate arguments. When
+ /// set, \c NumExpansions must also be set.
+ ///
+ /// \param RetainExpansion Whether the caller should add an unexpanded
+ /// pack expansion after all of the expanded arguments. This is used
+ /// when extending explicitly-specified template argument packs per
+ /// C++0x [temp.arg.explicit]p9.
+ ///
+ /// \param NumExpansions The number of separate arguments that will be in
+ /// the expanded form of the corresponding pack expansion. This is both an
+ /// input and an output parameter, which can be set by the caller if the
+ /// number of expansions is known a priori (e.g., due to a prior substitution)
+ /// and will be set by the callee when the number of expansions is known.
+ /// The callee must set this value when \c ShouldExpand is \c true; it may
+ /// set this value in other cases.
+ ///
+ /// \returns true if an error occurred (e.g., because the parameter packs
+ /// are to be instantiated with arguments of different lengths), false
+ /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
+ /// must be set.
+ bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ llvm::Optional<unsigned> &NumExpansions);
+
+ /// \brief Determine the number of arguments in the given pack expansion
+ /// type.
+ ///
+ /// This routine already assumes that the pack expansion type can be
+ /// expanded and that the number of arguments in the expansion is
+ /// consistent across all of the unexpanded parameter packs in its pattern.
+ unsigned getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// \brief Determine whether the given declarator contains any unexpanded
+ /// parameter packs.
+ ///
+ /// This routine is used by the parser to disambiguate function declarators
+ /// with an ellipsis prior to the ')', e.g.,
+ ///
+ /// \code
+ /// void f(T...);
+ /// \endcode
+ ///
+ /// To determine whether we have an (unnamed) function parameter pack or
+ /// a variadic function.
+ ///
+ /// \returns true if the declarator contains any unexpanded parameter packs,
+ /// false otherwise.
+ bool containsUnexpandedParameterPacks(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Argument Deduction (C++ [temp.deduct])
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Describes the result of template argument deduction.
+ ///
+ /// The TemplateDeductionResult enumeration describes the result of
+ /// template argument deduction, as returned from
+ /// DeduceTemplateArguments(). The separate TemplateDeductionInfo
+ /// structure provides additional information about the results of
+ /// template argument deduction, e.g., the deduced template argument
+ /// list (if successful) or the specific template parameters or
+ /// deduced arguments that were involved in the failure.
+ enum TemplateDeductionResult {
+ /// \brief Template argument deduction was successful.
+ TDK_Success = 0,
+ /// \brief Template argument deduction exceeded the maximum template
+ /// instantiation depth (which has already been diagnosed).
+ TDK_InstantiationDepth,
+ /// \brief Template argument deduction did not deduce a value
+ /// for every template parameter.
+ TDK_Incomplete,
+ /// \brief Template argument deduction produced inconsistent
+ /// deduced values for the given template parameter.
+ TDK_Inconsistent,
+ /// \brief Template argument deduction failed due to inconsistent
+ /// cv-qualifiers on a template parameter type that would
+ /// otherwise be deduced, e.g., we tried to deduce T in "const T"
+ /// but were given a non-const "X".
+ TDK_Underqualified,
+ /// \brief Substitution of the deduced template argument values
+ /// resulted in an error.
+ TDK_SubstitutionFailure,
+ /// \brief Substitution of the deduced template argument values
+ /// into a non-deduced context produced a type or value that
+ /// produces a type that does not match the original template
+ /// arguments provided.
+ TDK_NonDeducedMismatch,
+ /// \brief When performing template argument deduction for a function
+ /// template, there were too many call arguments.
+ TDK_TooManyArguments,
+ /// \brief When performing template argument deduction for a function
+ /// template, there were too few call arguments.
+ TDK_TooFewArguments,
+ /// \brief The explicitly-specified template arguments were not valid
+ /// template arguments for the given template.
+ TDK_InvalidExplicitArguments,
+ /// \brief The arguments included an overloaded function name that could
+ /// not be resolved to a suitable function.
+ TDK_FailedOverloadResolution
+ };
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result);
+
+ FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments);
+ UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
+ UnresolvedSetIterator SEnd,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain = true);
+
+ ClassTemplatePartialSpecializationDecl *
+ getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
+
+ void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used);
+ void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Instantiation
+ //
+
+ MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost = 0,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = 0);
+
+ /// \brief A template instantiation that is currently in progress.
+ struct ActiveTemplateInstantiation {
+ /// \brief The kind of template instantiation we are performing
+ enum InstantiationKind {
+ /// We are instantiating a template declaration. The entity is
+ /// the declaration we're instantiating (e.g., a CXXRecordDecl).
+ TemplateInstantiation,
+
+ /// We are instantiating a default argument for a template
+ /// parameter. The Entity is the template, and
+ /// TemplateArgs/NumTemplateArguments provides the template
+ /// arguments as specified.
+ /// FIXME: Use a TemplateArgumentList
+ DefaultTemplateArgumentInstantiation,
+
+ /// We are instantiating a default argument for a function.
+ /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+ /// provides the template arguments as specified.
+ DefaultFunctionArgumentInstantiation,
+
+ /// We are substituting explicit template arguments provided for
+ /// a function template. The entity is a FunctionTemplateDecl.
+ ExplicitTemplateArgumentSubstitution,
+
+ /// We are substituting template argument determined as part of
+ /// template argument deduction for either a class template
+ /// partial specialization or a function template. The
+ /// Entity is either a ClassTemplatePartialSpecializationDecl or
+ /// a FunctionTemplateDecl.
+ DeducedTemplateArgumentSubstitution,
+
+ /// We are substituting prior template arguments into a new
+ /// template parameter. The template parameter itself is either a
+ /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+ PriorTemplateArgumentSubstitution,
+
+ /// We are checking the validity of a default template argument that
+ /// has been used when naming a template-id.
+ DefaultTemplateArgumentChecking
+ } Kind;
+
+ /// \brief The point of instantiation within the source code.
+ SourceLocation PointOfInstantiation;
+
+ /// \brief The template (or partial specialization) in which we are
+ /// performing the instantiation, for substitutions of prior template
+ /// arguments.
+ NamedDecl *Template;
+
+ /// \brief The entity that is being instantiated.
+ uintptr_t Entity;
+
+ /// \brief The list of template arguments we are substituting, if they
+ /// are not part of the entity.
+ const TemplateArgument *TemplateArgs;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
+ /// \brief The template deduction info object associated with the
+ /// substitution or checking of explicit or deduced template arguments.
+ sema::TemplateDeductionInfo *DeductionInfo;
+
+ /// \brief The source range that covers the construct that cause
+ /// the instantiation, e.g., the template-id that causes a class
+ /// template instantiation.
+ SourceRange InstantiationRange;
+
+ ActiveTemplateInstantiation()
+ : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
+ NumTemplateArgs(0), DeductionInfo(0) {}
+
+ /// \brief Determines whether this template is an actual instantiation
+ /// that should be counted toward the maximum instantiation depth.
+ bool isInstantiationRecord() const;
+
+ friend bool operator==(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ if (X.Kind != Y.Kind)
+ return false;
+
+ if (X.Entity != Y.Entity)
+ return false;
+
+ switch (X.Kind) {
+ case TemplateInstantiation:
+ return true;
+
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ if (X.Template != Y.Template)
+ return false;
+
+ // Fall through
+
+ case DefaultTemplateArgumentInstantiation:
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case DefaultFunctionArgumentInstantiation:
+ return X.TemplateArgs == Y.TemplateArgs;
+
+ }
+
+ return true;
+ }
+
+ friend bool operator!=(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ return !(X == Y);
+ }
+ };
+
+ /// \brief List of active template instantiations.
+ ///
+ /// This vector is treated as a stack. As one template instantiation
+ /// requires another template instantiation, additional
+ /// instantiations are pushed onto the stack up to a
+ /// user-configurable limit LangOptions::InstantiationDepth.
+ llvm::SmallVector<ActiveTemplateInstantiation, 16>
+ ActiveTemplateInstantiations;
+
+ /// \brief Whether we are in a SFINAE context that is not associated with
+ /// template instantiation.
+ ///
+ /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
+ /// of a template instantiation or template argument deduction.
+ bool InNonInstantiationSFINAEContext;
+
+ /// \brief The number of ActiveTemplateInstantiation entries in
+ /// \c ActiveTemplateInstantiations that are not actual instantiations and,
+ /// therefore, should not be counted as part of the instantiation depth.
+ unsigned NonInstantiationEntries;
+
+ /// \brief The last template from which a template instantiation
+ /// error or warning was produced.
+ ///
+ /// This value is used to suppress printing of redundant template
+ /// instantiation backtraces when there are multiple errors in the
+ /// same instantiation. FIXME: Does this belong in Sema? It's tough
+ /// to implement it anywhere else.
+ ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+
+ /// \brief The current index into pack expansion arguments that will be
+ /// used for substitution of parameter packs.
+ ///
+ /// The pack expansion index will be -1 to indicate that parameter packs
+ /// should be instantiated as themselves. Otherwise, the index specifies
+ /// which argument within the parameter pack will be used for substitution.
+ int ArgumentPackSubstitutionIndex;
+
+ /// \brief RAII object used to change the argument pack substitution index
+ /// within a \c Sema object.
+ ///
+ /// See \c ArgumentPackSubstitutionIndex for more information.
+ class ArgumentPackSubstitutionIndexRAII {
+ Sema &Self;
+ int OldSubstitutionIndex;
+
+ public:
+ ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+ }
+
+ ~ArgumentPackSubstitutionIndexRAII() {
+ Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+ }
+ };
+
+ friend class ArgumentPackSubstitutionRAII;
+
+ /// \brief The stack of calls expression undergoing template instantiation.
+ ///
+ /// The top of this stack is used by a fixit instantiating unresolved
+ /// function calls to fix the AST to match the textual change it prints.
+ llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
+
+ /// \brief For each declaration that involved template argument deduction, the
+ /// set of diagnostics that were suppressed during that template argument
+ /// deduction.
+ ///
+ /// FIXME: Serialize this structure to the AST file.
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >
+ SuppressedDiagnostics;
+
+ /// \brief A stack object to be created when performing template
+ /// instantiation.
+ ///
+ /// Construction of an object of type \c InstantiatingTemplate
+ /// pushes the current instantiation onto the stack of active
+ /// instantiations. If the size of this stack exceeds the maximum
+ /// number of recursive template instantiations, construction
+ /// produces an error and evaluates true.
+ ///
+ /// Destruction of this object will pop the named instantiation off
+ /// the stack.
+ struct InstantiatingTemplate {
+ /// \brief Note that we are instantiating a class template,
+ /// function template, or a member thereof.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ Decl *Entity,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating as part of template
+ /// argument deduction for a class template partial
+ /// specialization.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ClassTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ParmVarDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are substituting prior template arguments into a
+ /// non-type or template template parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+ /// \brief Note that we are checking the default template argument
+ /// against the template parameter for a given template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange);
+
+
+ /// \brief Note that we have finished instantiating this template.
+ void Clear();
+
+ ~InstantiatingTemplate() { Clear(); }
+
+ /// \brief Determines whether we have exceeded the maximum
+ /// recursive template instantiations.
+ operator bool() const { return Invalid; }
+
+ private:
+ Sema &SemaRef;
+ bool Invalid;
+ bool SavedInNonInstantiationSFINAEContext;
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
+
+ InstantiatingTemplate&
+ operator=(const InstantiatingTemplate&); // not implemented
+ };
+
+ void PrintInstantiationStack();
+
+ /// \brief Determines whether we are currently in a context where
+ /// template argument substitution failures are not considered
+ /// errors.
+ ///
+ /// \returns An empty \c llvm::Optional if we're not in a SFINAE context.
+ /// Otherwise, contains a pointer that, if non-NULL, contains the nearest
+ /// template-deduction context object, which can be used to capture
+ /// diagnostics that will be suppressed.
+ llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
+
+ /// \brief RAII class used to determine whether SFINAE has
+ /// trapped any errors that occur during template argument
+ /// deduction.`
+ class SFINAETrap {
+ Sema &SemaRef;
+ unsigned PrevSFINAEErrors;
+ bool PrevInNonInstantiationSFINAEContext;
+ bool PrevAccessCheckingSFINAE;
+
+ public:
+ explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
+ : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
+ PrevInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext),
+ PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE)
+ {
+ if (!SemaRef.isSFINAEContext())
+ SemaRef.InNonInstantiationSFINAEContext = true;
+ SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE;
+ }
+
+ ~SFINAETrap() {
+ SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
+ SemaRef.InNonInstantiationSFINAEContext
+ = PrevInNonInstantiationSFINAEContext;
+ SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
+ }
+
+ /// \brief Determine whether any SFINAE errors have been trapped.
+ bool hasErrorOccurred() const {
+ return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+ }
+ };
+
+ /// \brief The current instantiation scope used to store local
+ /// variables.
+ LocalInstantiationScope *CurrentInstantiationScope;
+
+ /// \brief The number of typos corrected by CorrectTypo.
+ unsigned TyposCorrected;
+
+ typedef llvm::DenseMap<IdentifierInfo *, std::pair<llvm::StringRef, bool> >
+ UnqualifiedTyposCorrectedMap;
+
+ /// \brief A cache containing the results of typo correction for unqualified
+ /// name lookup.
+ ///
+ /// The string is the string that we corrected to (which may be empty, if
+ /// there was no correction), while the boolean will be true when the
+ /// string represents a keyword.
+ UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected;
+
+ /// \brief Worker object for performing CFG-based warnings.
+ sema::AnalysisBasedWarnings AnalysisWarnings;
+
+ /// \brief An entity for which implicit template instantiation is required.
+ ///
+ /// The source location associated with the declaration is the first place in
+ /// the source code where the declaration was "used". It is not necessarily
+ /// the point of instantiation (which will be either before or after the
+ /// namespace-scope declaration that triggered this implicit instantiation),
+ /// However, it is the location that diagnostics should generally refer to,
+ /// because users will need to know what code triggered the instantiation.
+ typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// but have not yet been performed.
+ std::deque<PendingImplicitInstantiation> PendingInstantiations;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// and must be performed within the current local scope.
+ ///
+ /// This queue is only used for member functions of local classes in
+ /// templates, which must be instantiated in the same scope as their
+ /// enclosing function, so that they can reference function-local
+ /// types, static variables, enumerators, etc.
+ std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+
+ void PerformPendingInstantiations(bool LocalOnly = false);
+
+ TypeSourceInfo *SubstType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ QualType SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ TypeSourceInfo *SubstType(TypeLoc TL,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity);
+ ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::Optional<unsigned> NumExpansions);
+ bool SubstParmTypes(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ llvm::SmallVectorImpl<ParmVarDecl *> *OutParams = 0);
+ ExprResult SubstExpr(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// \brief Substitute the given template arguments into a list of
+ /// expressions, expanding pack expansions if required.
+ ///
+ /// \param Exprs The list of expressions to substitute into.
+ ///
+ /// \param NumExprs The number of expressions in \p Exprs.
+ ///
+ /// \param IsCall Whether this is some form of call, in which case
+ /// default arguments will be dropped.
+ ///
+ /// \param TemplateArgs The set of template arguments to substitute.
+ ///
+ /// \param Outputs Will receive all of the substituted arguments.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<Expr *> &Outputs);
+
+ StmtResult SubstStmt(Stmt *S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ Decl *SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ bool
+ SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ bool
+ InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ Decl *Pattern, Decl *Inst);
+
+ bool
+ InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ void InstantiateClassMembers(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
+
+ void InstantiateClassTemplateSpecializationMembers(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK);
+
+ NestedNameSpecifier *
+ SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ DeclarationNameInfo
+ SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateName
+ SubstTemplateName(TemplateName Name, SourceLocation Loc,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ TemplateArgumentListInfo &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function,
+ bool Recursive = false,
+ bool DefinitionRequired = false);
+ void InstantiateStaticDataMemberDefinition(
+ SourceLocation PointOfInstantiation,
+ VarDecl *Var,
+ bool Recursive = false,
+ bool DefinitionRequired = false);
+
+ void InstantiateMemInitializers(CXXConstructorDecl *New,
+ const CXXConstructorDecl *Tmpl,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ // Objective-C declarations.
+ Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ Decl *ActOnCompatiblityAlias(
+ SourceLocation AtCompatibilityAliasLoc,
+ IdentifierInfo *AliasName, SourceLocation AliasLocation,
+ IdentifierInfo *ClassName, SourceLocation ClassLocation);
+
+ void CheckForwardProtocolDeclarationForCircularDependency(
+ IdentifierInfo *PName,
+ SourceLocation &PLoc, SourceLocation PrevLoc,
+ const ObjCList<ObjCProtocolDecl> &PList);
+
+ Decl *ActOnStartProtocolInterface(
+ SourceLocation AtProtoInterfaceLoc,
+ IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
+ Decl * const *ProtoRefNames, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CategoryName,
+ SourceLocation CategoryLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc);
+
+ Decl *ActOnStartClassImplementation(
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc);
+
+ Decl *ActOnStartCategoryImplementation(SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc);
+
+ Decl *ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts);
+
+ Decl *ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ const IdentifierLocPair *IdentList,
+ unsigned NumElts,
+ AttributeList *attrList);
+
+ void FindProtocolDeclaration(bool WarnOnDeclarations,
+ const IdentifierLocPair *ProtocolId,
+ unsigned NumProtocols,
+ llvm::SmallVectorImpl<Decl *> &Protocols);
+
+ /// Ensure attributes are consistent with type.
+ /// \param [in, out] Attributes The attributes to check; they will
+ /// be modified to be consistent with \arg PropertyTy.
+ void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
+ SourceLocation Loc,
+ unsigned &Attributes);
+
+ /// Process the specified property declaration and create decls for the
+ /// setters and getters as needed.
+ /// \param property The property declaration being processed
+ /// \param DC The semantic container for the property
+ /// \param redeclaredProperty Declaration for property if redeclared
+ /// in class extension.
+ /// \param lexicalDC Container for redeclaredProperty.
+ void ProcessPropertyDecl(ObjCPropertyDecl *property,
+ ObjCContainerDecl *DC,
+ ObjCPropertyDecl *redeclaredProperty = 0,
+ ObjCContainerDecl *lexicalDC = 0);
+
+ void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+ ObjCPropertyDecl *SuperProperty,
+ const IdentifierInfo *Name);
+ void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl);
+
+ void CompareMethodParamsInBaseAndSuper(Decl *IDecl,
+ ObjCMethodDecl *MethodDecl,
+ bool IsInstance);
+
+ void CompareProperties(Decl *CDecl, Decl *MergeProtocols);
+
+ void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID);
+
+ void MatchOneProtocolPropertiesInClass(Decl *CDecl,
+ ObjCProtocolDecl *PDecl);
+
+ void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl,
+ Decl **allMethods = 0, unsigned allNum = 0,
+ Decl **allProperties = 0, unsigned pNum = 0,
+ DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+
+ Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD, ObjCDeclSpec &ODS,
+ Selector GetterSel, Selector SetterSel,
+ Decl *ClassCategory,
+ bool *OverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = 0);
+
+ Decl *ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool ImplKind,Decl *ClassImplDecl,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar,
+ SourceLocation PropertyIvarLoc);
+
+ struct ObjCArgInfo {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ // The Type is null if no type was specified, and the DeclSpec is invalid
+ // in this case.
+ ParsedType Type;
+ ObjCDeclSpec DeclSpec;
+
+ /// ArgAttrs - Attribute list for this argument.
+ AttributeList *ArgAttrs;
+ };
+
+ Decl *ActOnMethodDeclaration(
+ Scope *S,
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType,
+ Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ Selector Sel,
+ // optional arguments. The number of types/arguments is obtained
+ // from the Sel.getNumArgs().
+ ObjCArgInfo *ArgInfo,
+ DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
+ AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind,
+ bool isVariadic = false);
+
+ // Helper method for ActOnClassMethod/ActOnInstanceMethod.
+ // Will search "local" class/category implementations for a method decl.
+ // Will also search in class's root looking for instance method.
+ // Returns 0 if no method is found.
+ ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel,
+ ObjCInterfaceDecl *CDecl);
+ ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
+ ObjCInterfaceDecl *ClassDecl);
+
+ ExprResult
+ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc, QualType SuperType,
+ bool Super);
+
+ ExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
+
+ ObjCMethodDecl *tryCaptureObjCSelf();
+
+ /// \brief Describes the kind of message expression indicated by a message
+ /// send that starts with an identifier.
+ enum ObjCMessageKind {
+ /// \brief The message is sent to 'super'.
+ ObjCSuperMessage,
+ /// \brief The message is an instance message.
+ ObjCInstanceMessage,
+ /// \brief The message is a class message, and the identifier is a type
+ /// name.
+ ObjCClassMessage
+ };
+
+ ObjCMessageKind getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType);
+
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+
+ enum PragmaOptionsAlignKind {
+ POAK_Native, // #pragma options align=native
+ POAK_Natural, // #pragma options align=natural
+ POAK_Packed, // #pragma options align=packed
+ POAK_Power, // #pragma options align=power
+ POAK_Mac68k, // #pragma options align=mac68k
+ POAK_Reset // #pragma options align=reset
+ };
+
+ /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align.
+ void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+ SourceLocation PragmaLoc,
+ SourceLocation KindLoc);
+
+ enum PragmaPackKind {
+ PPK_Default, // #pragma pack([n])
+ PPK_Show, // #pragma pack(show), only supported by MSVC.
+ PPK_Push, // #pragma pack(push, [identifier], [n])
+ PPK_Pop // #pragma pack(pop, [identifier], [n])
+ };
+
+ /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+ void ActOnPragmaPack(PragmaPackKind Kind,
+ IdentifierInfo *Name,
+ Expr *Alignment,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
+ void ActOnPragmaUnused(const Token &Identifier,
+ Scope *curScope,
+ SourceLocation PragmaLoc);
+
+ /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
+ void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
+
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
+
+ /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
+ void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc);
+
+ /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
+ void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
+ IdentifierInfo* AliasName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc,
+ SourceLocation AliasNameLoc);
+
+ /// ActOnPragmaFPContract - Called on well formed
+ /// #pragma {STDC,OPENCL} FP_CONTRACT
+ void ActOnPragmaFPContract(tok::OnOffSwitch OOS);
+
+ /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+ /// a the record decl, to handle '#pragma pack' and '#pragma options align'.
+ void AddAlignmentAttributesForRecord(RecordDecl *RD);
+
+ /// FreePackedContext - Deallocate and null out PackContext.
+ void FreePackedContext();
+
+ /// PushNamespaceVisibilityAttr - Note that we've entered a
+ /// namespace with a visibility attribute.
+ void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr);
+
+ /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
+ /// add an appropriate visibility attribute.
+ void AddPushedVisibilityAttribute(Decl *RD);
+
+ /// PopPragmaVisibility - Pop the top element of the visibility stack; used
+ /// for '#pragma GCC visibility' and visibility attributes on namespaces.
+ void PopPragmaVisibility();
+
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
+
+ /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T);
+
+ /// CastCategory - Get the correct forwarded implicit cast result category
+ /// from the inner expression.
+ ExprValueKind CastCategory(Expr *E);
+
+ /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
+ /// cast. If there is already an implicit cast, merge into the existing one.
+ /// If isLvalue, the result of the cast is an lvalue.
+ void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK,
+ ExprValueKind VK = VK_RValue,
+ const CXXCastPath *BasePath = 0);
+
+ /// IgnoredValueConversions - Given that an expression's result is
+ /// syntactically ignored, perform any conversions that are
+ /// required.
+ void IgnoredValueConversions(Expr *&expr);
+
+ // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+ // functions and arrays to their respective pointers (C99 6.3.2.1).
+ Expr *UsualUnaryConversions(Expr *&expr);
+
+ // DefaultFunctionArrayConversion - converts functions and arrays
+ // to their respective pointers (C99 6.3.2.1).
+ void DefaultFunctionArrayConversion(Expr *&expr);
+
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ void DefaultFunctionArrayLvalueConversion(Expr *&expr);
+
+ // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
+ // the operand. This is DefaultFunctionArrayLvalueConversion,
+ // except that it assumes the operand isn't of function or array
+ // type.
+ void DefaultLvalueConversion(Expr *&expr);
+
+ // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+ // do not have a prototype. Integer promotions are performed on each
+ // argument, and arguments that have type float are promoted to double.
+ void DefaultArgumentPromotion(Expr *&Expr);
+
+ // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+ enum VariadicCallType {
+ VariadicFunction,
+ VariadicBlock,
+ VariadicMethod,
+ VariadicConstructor,
+ VariadicDoesNotApply
+ };
+
+ /// GatherArgumentsForCall - Collector argument expressions for various
+ /// form of call prototypes.
+ bool GatherArgumentsForCall(SourceLocation CallLoc,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ unsigned FirstProtoArg,
+ Expr **Args, unsigned NumArgs,
+ llvm::SmallVector<Expr *, 8> &AllArgs,
+ VariadicCallType CallType = VariadicDoesNotApply);
+
+ // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+ // will warn if the resulting type is not a POD type.
+ bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
+ FunctionDecl *FDecl);
+
+ // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
+ // operands and then handles various conversions that are common to binary
+ // operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+ // routine returns the first non-arithmetic type found. The client is
+ // responsible for emitting appropriate error diagnostics.
+ QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
+ bool isCompAssign = false);
+
+ /// AssignConvertType - All of the 'assignment' semantic checks return this
+ /// enum to indicate whether the assignment was allowed. These checks are
+ /// done for simple assignments, as well as initialization, return from
+ /// function, argument passing, etc. The query is phrased in terms of a
+ /// source and destination type.
+ enum AssignConvertType {
+ /// Compatible - the types are compatible according to the standard.
+ Compatible,
+
+ /// PointerToInt - The assignment converts a pointer to an int, which we
+ /// accept as an extension.
+ PointerToInt,
+
+ /// IntToPointer - The assignment converts an int to a pointer, which we
+ /// accept as an extension.
+ IntToPointer,
+
+ /// FunctionVoidPointer - The assignment is between a function pointer and
+ /// void*, which the standard doesn't allow, but we accept as an extension.
+ FunctionVoidPointer,
+
+ /// IncompatiblePointer - The assignment is between two pointers types that
+ /// are not compatible, but we accept them as an extension.
+ IncompatiblePointer,
+
+ /// IncompatiblePointer - The assignment is between two pointers types which
+ /// point to integers which have a different sign, but are otherwise identical.
+ /// This is a subset of the above, but broken out because it's by far the most
+ /// common case of incompatible pointers.
+ IncompatiblePointerSign,
+
+ /// CompatiblePointerDiscardsQualifiers - The assignment discards
+ /// c/v/r qualifiers, which we accept as an extension.
+ CompatiblePointerDiscardsQualifiers,
+
+ /// IncompatiblePointerDiscardsQualifiers - The assignment
+ /// discards qualifiers that we don't permit to be discarded,
+ /// like address spaces.
+ IncompatiblePointerDiscardsQualifiers,
+
+ /// IncompatibleNestedPointerQualifiers - The assignment is between two
+ /// nested pointer types, and the qualifiers other than the first two
+ /// levels differ e.g. char ** -> const char **, but we accept them as an
+ /// extension.
+ IncompatibleNestedPointerQualifiers,
+
+ /// IncompatibleVectors - The assignment is between two vector types that
+ /// have the same size, which we accept as an extension.
+ IncompatibleVectors,
+
+ /// IntToBlockPointer - The assignment converts an int to a block
+ /// pointer. We disallow this.
+ IntToBlockPointer,
+
+ /// IncompatibleBlockPointer - The assignment is between two block
+ /// pointers types that are not compatible.
+ IncompatibleBlockPointer,
+
+ /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+ /// id type and something else (that is incompatible with it). For example,
+ /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+ IncompatibleObjCQualifiedId,
+
+ /// Incompatible - We reject this conversion outright, it is invalid to
+ /// represent it in the AST.
+ Incompatible
+ };
+
+ /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
+ /// assignment conversion type specified by ConvTy. This returns true if the
+ /// conversion was invalid or false if the conversion was accepted.
+ bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
+ SourceLocation Loc,
+ QualType DstType, QualType SrcType,
+ Expr *SrcExpr, AssignmentAction Action,
+ bool *Complained = 0);
+
+ /// CheckAssignmentConstraints - Perform type checking for assignment,
+ /// argument passing, variable initialization, and function return values.
+ /// C99 6.5.16.
+ AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
+ QualType lhs, QualType rhs);
+
+ /// Check assignment constraints and prepare for a conversion of the
+ /// RHS to the LHS type.
+ AssignConvertType CheckAssignmentConstraints(QualType lhs, Expr *&rhs,
+ CastKind &Kind);
+
+ // CheckSingleAssignmentConstraints - Currently used by
+ // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
+ // this routine performs the default function/array converions.
+ AssignConvertType CheckSingleAssignmentConstraints(QualType lhs,
+ Expr *&rExpr);
+
+ // \brief If the lhs type is a transparent union, check whether we
+ // can initialize the transparent union with the given expression.
+ AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs,
+ Expr *&rExpr);
+
+ bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+
+ bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit = false);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit,
+ ImplicitConversionSequence& ICS);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ const ImplicitConversionSequence& ICS,
+ AssignmentAction Action,
+ bool CStyle = false);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ const StandardConversionSequence& SCS,
+ AssignmentAction Action,
+ bool CStyle);
+
+ /// the following "Check" methods will return a valid/converted QualType
+ /// or a null QualType (indicating an error diagnostic was issued).
+
+ /// type checking binary operators (subroutines of CreateBuiltinBinOp).
+ QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+ QualType CheckPointerToMemberOperands( // C++ 5.5
+ Expr *&lex, Expr *&rex, ExprValueKind &VK,
+ SourceLocation OpLoc, bool isIndirect);
+ QualType CheckMultiplyDivideOperands( // C99 6.5.5
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign,
+ bool isDivide);
+ QualType CheckRemainderOperands( // C99 6.5.5
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckAdditionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+ QualType CheckSubtractionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
+ QualType CheckShiftOperands( // C99 6.5.7
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckCompareOperands( // C99 6.5.8/9
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
+ bool isRelational);
+ QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ QualType CheckLogicalOperands( // C99 6.5.[13,14]
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc);
+ // CheckAssignmentOperands is used for both simple and compound assignment.
+ // For simple assignment, pass both expressions and a null converted type.
+ // For compound assignment, pass both expressions and the converted type.
+ QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
+ Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType);
+
+ void ConvertPropertyForRValue(Expr *&E);
+ void ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType& LHSTy);
+
+ QualType CheckConditionalOperands( // C99 6.5.15
+ Expr *&cond, Expr *&lhs, Expr *&rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
+ QualType CXXCheckConditionalOperands( // C++ 5.16
+ Expr *&cond, Expr *&lhs, Expr *&rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
+ QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType = 0);
+
+ QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+ SourceLocation questionLoc);
+
+ bool DiagnoseConditionalForNull(Expr *LHS, Expr *RHS,
+ SourceLocation QuestionLoc);
+
+ /// type checking for vector binary operators.
+ QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+ QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
+ SourceLocation l, bool isRel);
+
+ /// type checking declaration initializers (C99 6.7.8)
+ bool CheckInitList(const InitializedEntity &Entity,
+ InitListExpr *&InitList, QualType &DeclType);
+ bool CheckForConstantInitializer(Expr *e, QualType t);
+
+ // type checking C++ declaration initializers (C++ [dcl.init]).
+
+ /// ReferenceCompareResult - Expresses the result of comparing two
+ /// types (cv1 T1 and cv2 T2) to determine their compatibility for the
+ /// purposes of initialization by reference (C++ [dcl.init.ref]p4).
+ enum ReferenceCompareResult {
+ /// Ref_Incompatible - The two types are incompatible, so direct
+ /// reference binding is not possible.
+ Ref_Incompatible = 0,
+ /// Ref_Related - The two types are reference-related, which means
+ /// that their unqualified forms (T1 and T2) are either the same
+ /// or T1 is a base class of T2.
+ Ref_Related,
+ /// Ref_Compatible_With_Added_Qualification - The two types are
+ /// reference-compatible with added qualification, meaning that
+ /// they are reference-compatible and the qualifiers on T1 (cv1)
+ /// are greater than the qualifiers on T2 (cv2).
+ Ref_Compatible_With_Added_Qualification,
+ /// Ref_Compatible - The two types are reference-compatible and
+ /// have equivalent qualifiers (cv1 == cv2).
+ Ref_Compatible
+ };
+
+ ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+ QualType T1, QualType T2,
+ bool &DerivedToBase,
+ bool &ObjCConversion);
+
+ /// CheckCastTypes - Check type constraints for casting between types under
+ /// C semantics, or forward to CXXCheckCStyleCast in C++.
+ bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
+ CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath,
+ bool FunctionalStyle = false);
+
+ // CheckVectorCast - check type constraints for vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size.
+ // returns true if the cast is invalid
+ bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+ CastKind &Kind);
+
+ // CheckExtVectorCast - check type constraints for extended vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size,
+ // or vectors and the element type of that vector.
+ // returns true if the cast is invalid
+ bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr,
+ CastKind &Kind);
+
+ /// CXXCheckCStyleCast - Check constraints of a C-style or function-style
+ /// cast under C++ semantics.
+ bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
+ Expr *&CastExpr, CastKind &Kind,
+ CXXCastPath &BasePath, bool FunctionalStyle);
+
+ /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
+ /// \param Method - May be null.
+ /// \param [out] ReturnType - The return type of the send.
+ /// \return true iff there were any incompatible types.
+ bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ SourceLocation lbrac, SourceLocation rbrac,
+ QualType &ReturnType, ExprValueKind &VK);
+
+ /// CheckBooleanCondition - Diagnose problems involving the use of
+ /// the given expression as a boolean condition (e.g. in an if
+ /// statement). Also performs the standard function and array
+ /// decays, possibly changing the input variable.
+ ///
+ /// \param Loc - A location associated with the condition, e.g. the
+ /// 'if' keyword.
+ /// \return true iff there were any errors
+ bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc);
+
+ ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+ Expr *SubExpr);
+
+ /// DiagnoseAssignmentAsCondition - Given that an expression is
+ /// being used as a boolean condition, warn if it's an assignment.
+ void DiagnoseAssignmentAsCondition(Expr *E);
+
+ /// \brief Redundant parentheses over an equality comparison can indicate
+ /// that the user intended an assignment used as condition.
+ void DiagnoseEqualityWithExtraParens(ParenExpr *parenE);
+
+ /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+ bool CheckCXXBooleanCondition(Expr *&CondExpr);
+
+ /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+ /// the specified width and sign. If an overflow occurs, detect it and emit
+ /// the specified diagnostic.
+ void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal,
+ unsigned NewWidth, bool NewSign,
+ SourceLocation Loc, unsigned DiagID);
+
+ /// Checks that the Objective-C declaration is declared in the global scope.
+ /// Emits an error and marks the declaration as invalid if it's not declared
+ /// in the global scope.
+ bool CheckObjCDeclScope(Decl *D);
+
+ /// VerifyIntegerConstantExpression - verifies that an expression is an ICE,
+ /// and reports the appropriate diagnostics. Returns false on success.
+ /// Can optionally return the value of the expression.
+ bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0);
+
+ /// VerifyBitField - verifies that a bit field expression is an ICE and has
+ /// the correct width, and that the field type is valid.
+ /// Returns false on success.
+ /// Can optionally return whether the bit-field is of width 0
+ bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, const Expr *BitWidth,
+ bool *ZeroWidth = 0);
+
+ /// \name Code completion
+ //@{
+ /// \brief Describes the context in which code completion occurs.
+ enum ParserCompletionContext {
+ /// \brief Code completion occurs at top-level or namespace context.
+ PCC_Namespace,
+ /// \brief Code completion occurs within a class, struct, or union.
+ PCC_Class,
+ /// \brief Code completion occurs within an Objective-C interface, protocol,
+ /// or category.
+ PCC_ObjCInterface,
+ /// \brief Code completion occurs within an Objective-C implementation or
+ /// category implementation
+ PCC_ObjCImplementation,
+ /// \brief Code completion occurs within the list of instance variables
+ /// in an Objective-C interface, protocol, category, or implementation.
+ PCC_ObjCInstanceVariableList,
+ /// \brief Code completion occurs following one or more template
+ /// headers.
+ PCC_Template,
+ /// \brief Code completion occurs following one or more template
+ /// headers within a class.
+ PCC_MemberTemplate,
+ /// \brief Code completion occurs within an expression.
+ PCC_Expression,
+ /// \brief Code completion occurs within a statement, which may
+ /// also be an expression or a declaration.
+ PCC_Statement,
+ /// \brief Code completion occurs at the beginning of the
+ /// initialization statement (or expression) in a for loop.
+ PCC_ForInit,
+ /// \brief Code completion occurs within the condition of an if,
+ /// while, switch, or for statement.
+ PCC_Condition,
+ /// \brief Code completion occurs within the body of a function on a
+ /// recovery path, where we do not have a specific handle on our position
+ /// in the grammar.
+ PCC_RecoveryInFunction,
+ /// \brief Code completion occurs where only a type is permitted.
+ PCC_Type,
+ /// \brief Code completion occurs in a parenthesized expression, which
+ /// might also be a type cast.
+ PCC_ParenthesizedExpression,
+ /// \brief Code completion occurs within a sequence of declaration
+ /// specifiers within a function, method, or block.
+ PCC_LocalDeclarationSpecifiers
+ };
+
+ void CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext);
+ void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
+
+ struct CodeCompleteExpressionData;
+ void CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data);
+ void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool IsArrow);
+ void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
+ void CodeCompleteTag(Scope *S, unsigned TagSpec);
+ void CodeCompleteTypeQualifiers(DeclSpec &DS);
+ void CodeCompleteCase(Scope *S);
+ void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs);
+ void CodeCompleteInitializer(Scope *S, Decl *D);
+ void CodeCompleteReturn(Scope *S);
+ void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
+
+ void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext);
+ void CodeCompleteUsing(Scope *S);
+ void CodeCompleteUsingDirective(Scope *S);
+ void CodeCompleteNamespaceDecl(Scope *S);
+ void CodeCompleteNamespaceAliasDecl(Scope *S);
+ void CodeCompleteOperatorName(Scope *S);
+ void CodeCompleteConstructorInitializer(Decl *Constructor,
+ CXXCtorInitializer** Initializers,
+ unsigned NumInitializers);
+
+ void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
+ bool InInterface);
+ void CodeCompleteObjCAtVisibility(Scope *S);
+ void CodeCompleteObjCAtStatement(Scope *S);
+ void CodeCompleteObjCAtExpression(Scope *S);
+ void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+ void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl);
+ void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl);
+ void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+ bool IsParameter);
+ void CodeCompleteObjCMessageReceiver(Scope *S);
+ void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper = false);
+ void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ ObjCInterfaceDecl *Super = 0);
+ void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols);
+ void CodeCompleteObjCProtocolDecl(Scope *S);
+ void CodeCompleteObjCInterfaceDecl(Scope *S);
+ void CodeCompleteObjCSuperclass(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationDecl(Scope *S);
+ void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl);
+ void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ Decl *ObjCImpDecl);
+ void CodeCompleteObjCMethodDecl(Scope *S,
+ bool IsInstanceMethod,
+ ParsedType ReturnType,
+ Decl *IDecl);
+ void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnType,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompletePreprocessorDirective(bool InConditional);
+ void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
+ void CodeCompletePreprocessorMacroName(bool IsDefinition);
+ void CodeCompletePreprocessorExpression();
+ void CodeCompletePreprocessorMacroArgument(Scope *S,
+ IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned Argument);
+ void CodeCompleteNaturalLanguage();
+ void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
+ llvm::SmallVectorImpl<CodeCompletionResult> &Results);
+ //@}
+
+ void PrintStats() const {}
+
+ //===--------------------------------------------------------------------===//
+ // Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
+private:
+ void CheckArrayAccess(const ArraySubscriptExpr *E);
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
+ bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
+
+ bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
+ bool CheckObjCString(Expr *Arg);
+
+ ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+
+public:
+ // Used by C++ template instantiation.
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+
+private:
+ bool SemaBuiltinPrefetch(CallExpr *TheCall);
+ bool SemaBuiltinObjectSize(CallExpr *TheCall);
+ bool SemaBuiltinLongjmp(CallExpr *TheCall);
+ ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
+ bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+ llvm::APSInt &Result);
+
+ bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+ bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg, bool isPrintf);
+
+ void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
+ const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
+ void CheckNonNullArguments(const NonNullAttr *NonNull,
+ const CallExpr *TheCall);
+
+ void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
+ void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc);
+ void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+
+ void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
+ Expr *Init);
+
+ /// \brief The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
+
+protected:
+ friend class Parser;
+ friend class InitializationSequence;
+
+ /// \brief Retrieve the parser's current scope.
+ Scope *getCurScope() const { return CurScope; }
+};
+
+/// \brief RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ Sema &Actions;
+
+public:
+ EnterExpressionEvaluationContext(Sema &Actions,
+ Sema::ExpressionEvaluationContext NewContext)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(NewContext);
+ }
+
+ ~EnterExpressionEvaluationContext() {
+ Actions.PopExpressionEvaluationContext();
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h
new file mode 100644
index 0000000..3689a6e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h
@@ -0,0 +1,48 @@
+//===--- SemaConsumer.h - Abstract interface for AST semantics --*- 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 SemaConsumer class, a subclass of
+// ASTConsumer that is used by AST clients that also require
+// additional semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_SEMACONSUMER_H
+#define LLVM_CLANG_SEMA_SEMACONSUMER_H
+
+#include "clang/AST/ASTConsumer.h"
+
+namespace clang {
+ class Sema;
+
+ /// \brief An abstract interface that should be implemented by
+ /// clients that read ASTs and then require further semantic
+ /// analysis of the entities in those ASTs.
+ class SemaConsumer : public ASTConsumer {
+ public:
+ SemaConsumer() {
+ ASTConsumer::SemaConsumer = true;
+ }
+
+ /// \brief Initialize the semantic consumer with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ /// \brief Inform the semantic consumer that Sema is no longer available.
+ virtual void ForgetSema() {}
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ASTConsumer *Consumer) {
+ return Consumer->SemaConsumer;
+ }
+ static bool classof(const SemaConsumer *) { return true; }
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h
new file mode 100644
index 0000000..ae5aa33
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticSema.h - Diagnostics for libsema -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICSEMA_H
+#define LLVM_CLANG_DIAGNOSTICSEMA_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
+#define SEMASTART
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_SEMA_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
new file mode 100644
index 0000000..64b83e3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,30 @@
+//===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides common API and #includes for the internal
+// implementation of Sema.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
+ return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
new file mode 100644
index 0000000..53f4a9d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
@@ -0,0 +1,423 @@
+//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file provides types used in the semantic analysis of C++ templates.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
+#define LLVM_CLANG_SEMA_TEMPLATE_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <utility>
+
+namespace clang {
+ /// \brief Data structure that captures multiple levels of template argument
+ /// lists for use in template instantiation.
+ ///
+ /// Multiple levels of template arguments occur when instantiating the
+ /// definitions of member templates. For example:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<T Value>
+ /// struct Y {
+ /// void f();
+ /// };
+ /// };
+ /// \endcode
+ ///
+ /// When instantiating X<int>::Y<17>::f, the multi-level template argument
+ /// list will contain a template argument list (int) at depth 0 and a
+ /// template argument list (17) at depth 1.
+ class MultiLevelTemplateArgumentList {
+ public:
+ typedef std::pair<const TemplateArgument *, unsigned> ArgList;
+
+ private:
+ /// \brief The template argument lists, stored from the innermost template
+ /// argument list (first) to the outermost template argument list (last).
+ llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
+
+ public:
+ /// \brief Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() { }
+
+ /// \brief Construct a single-level template argument list.
+ explicit
+ MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+ addOuterTemplateArguments(&TemplateArgs);
+ }
+
+ /// \brief Determine the number of levels in this template argument
+ /// list.
+ unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
+
+ /// \brief Retrieve the template argument at a given depth and index.
+ const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
+ assert(Depth < TemplateArgumentLists.size());
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
+ }
+
+ /// \brief Determine whether there is a non-NULL template argument at the
+ /// given depth and index.
+ ///
+ /// There must exist a template argument list at the given depth.
+ bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
+ assert(Depth < TemplateArgumentLists.size());
+
+ if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
+ return false;
+
+ return !(*this)(Depth, Index).isNull();
+ }
+
+ /// \brief Clear out a specific template argument.
+ void setArgument(unsigned Depth, unsigned Index,
+ TemplateArgument Arg) {
+ assert(Depth < TemplateArgumentLists.size());
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ const_cast<TemplateArgument&>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index])
+ = Arg;
+ }
+
+ /// \brief Add a new outermost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
+ TemplateArgumentLists.push_back(ArgList(TemplateArgs->data(),
+ TemplateArgs->size()));
+ }
+
+ /// \brief Add a new outmost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
+ }
+
+ /// \brief Retrieve the innermost template argument list.
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front();
+ }
+ };
+
+ /// \brief The context in which partial ordering of function templates occurs.
+ enum TPOC {
+ /// \brief Partial ordering of function templates for a function call.
+ TPOC_Call,
+ /// \brief Partial ordering of function templates for a call to a
+ /// conversion function.
+ TPOC_Conversion,
+ /// \brief Partial ordering of function templates in other contexts, e.g.,
+ /// taking the address of a function template or matching a function
+ /// template specialization to a function template.
+ TPOC_Other
+ };
+
+ // This is lame but unavoidable in a world without forward
+ // declarations of enums. The alternatives are to either pollute
+ // Sema.h (by including this file) or sacrifice type safety (by
+ // making Sema.h declare things as enums).
+ class TemplatePartialOrderingContext {
+ TPOC Value;
+ public:
+ TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
+ operator TPOC() const { return Value; }
+ };
+
+ /// \brief Captures a template argument whose value has been deduced
+ /// via c++ template argument deduction.
+ class DeducedTemplateArgument : public TemplateArgument {
+ /// \brief For a non-type template argument, whether the value was
+ /// deduced from an array bound.
+ bool DeducedFromArrayBound;
+
+ public:
+ DeducedTemplateArgument()
+ : TemplateArgument(), DeducedFromArrayBound(false) { }
+
+ DeducedTemplateArgument(const TemplateArgument &Arg,
+ bool DeducedFromArrayBound = false)
+ : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
+
+ /// \brief Construct an integral non-type template argument that
+ /// has been deduced, possibly from an array bound.
+ DeducedTemplateArgument(const llvm::APSInt &Value,
+ QualType ValueType,
+ bool DeducedFromArrayBound)
+ : TemplateArgument(Value, ValueType),
+ DeducedFromArrayBound(DeducedFromArrayBound) { }
+
+ /// \brief For a non-type template argument, determine whether the
+ /// template argument was deduced from an array bound.
+ bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
+
+ /// \brief Specify whether the given non-type template argument
+ /// was deduced from an array bound.
+ void setDeducedFromArrayBound(bool Deduced) {
+ DeducedFromArrayBound = Deduced;
+ }
+ };
+
+ /// \brief A stack-allocated class that identifies which local
+ /// variable declaration instantiations are present in this scope.
+ ///
+ /// A new instance of this class type will be created whenever we
+ /// instantiate a new function declaration, which will have its own
+ /// set of parameter declarations.
+ class LocalInstantiationScope {
+ public:
+ /// \brief A set of declarations.
+ typedef llvm::SmallVector<Decl *, 4> DeclArgumentPack;
+
+ private:
+ /// \brief Reference to the semantic analysis that is performing
+ /// this template instantiation.
+ Sema &SemaRef;
+
+ typedef llvm::DenseMap<const Decl *,
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> >
+ LocalDeclsMap;
+
+ /// \brief A mapping from local declarations that occur
+ /// within a template to their instantiations.
+ ///
+ /// This mapping is used during instantiation to keep track of,
+ /// e.g., function parameter and variable declarations. For example,
+ /// given:
+ ///
+ /// \code
+ /// template<typename T> T add(T x, T y) { return x + y; }
+ /// \endcode
+ ///
+ /// when we instantiate add<int>, we will introduce a mapping from
+ /// the ParmVarDecl for 'x' that occurs in the template to the
+ /// instantiated ParmVarDecl for 'x'.
+ ///
+ /// For a parameter pack, the local instantiation scope may contain a
+ /// set of instantiated parameters. This is stored as a DeclArgumentPack
+ /// pointer.
+ LocalDeclsMap LocalDecls;
+
+ /// \brief The set of argument packs we've allocated.
+ llvm::SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
+
+ /// \brief The outer scope, which contains local variable
+ /// definitions from some other instantiation (that may not be
+ /// relevant to this particular scope).
+ LocalInstantiationScope *Outer;
+
+ /// \brief Whether we have already exited this scope.
+ bool Exited;
+
+ /// \brief Whether to combine this scope with the outer scope, such that
+ /// lookup will search our outer scope.
+ bool CombineWithOuterScope;
+
+ /// \brief If non-NULL, the template parameter pack that has been
+ /// partially substituted per C++0x [temp.arg.explicit]p9.
+ NamedDecl *PartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack is non-null, the set of
+ /// explicitly-specified template arguments in that pack.
+ const TemplateArgument *ArgsInPartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack, the number of
+ /// explicitly-specified template arguments in
+ /// ArgsInPartiallySubstitutedPack.
+ unsigned NumArgsInPartiallySubstitutedPack;
+
+ // This class is non-copyable
+ LocalInstantiationScope(const LocalInstantiationScope &);
+ LocalInstantiationScope &operator=(const LocalInstantiationScope &);
+
+ public:
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope),
+ PartiallySubstitutedPack(0)
+ {
+ SemaRef.CurrentInstantiationScope = this;
+ }
+
+ ~LocalInstantiationScope() {
+ Exit();
+ }
+
+ const Sema &getSema() const { return SemaRef; }
+
+ /// \brief Exit this local instantiation scope early.
+ void Exit() {
+ if (Exited)
+ return;
+
+ for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
+ delete ArgumentPacks[I];
+
+ SemaRef.CurrentInstantiationScope = Outer;
+ Exited = true;
+ }
+
+ /// \brief Find the instantiation of the declaration D within the current
+ /// instantiation scope.
+ ///
+ /// \param D The declaration whose instantiation we are searching for.
+ ///
+ /// \returns A pointer to the declaration or argument pack of declarations
+ /// to which the declaration \c D is instantiataed, if found. Otherwise,
+ /// returns NULL.
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *
+ findInstantiationOf(const Decl *D);
+
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
+ void InstantiatedLocalPackArg(const Decl *D, Decl *Inst);
+ void MakeInstantiatedLocalArgPack(const Decl *D);
+
+ /// \brief Note that the given parameter pack has been partially substituted
+ /// via explicit specification of template arguments
+ /// (C++0x [temp.arg.explicit]p9).
+ ///
+ /// \param Pack The parameter pack, which will always be a template
+ /// parameter pack.
+ ///
+ /// \param ExplicitArgs The explicitly-specified template arguments provided
+ /// for this parameter pack.
+ ///
+ /// \param NumExplicitArgs The number of explicitly-specified template
+ /// arguments provided for this parameter pack.
+ void SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs);
+
+ /// \brief Retrieve the partially-substitued template parameter pack.
+ ///
+ /// If there is no partially-substituted parameter pack, returns NULL.
+ NamedDecl *getPartiallySubstitutedPack(
+ const TemplateArgument **ExplicitArgs = 0,
+ unsigned *NumExplicitArgs = 0) const;
+ };
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
+ Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+
+ /// \brief A list of out-of-line class template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing class's instantiation is complete.
+ llvm::SmallVector<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>, 4>
+ OutOfLinePartialSpecs;
+
+ public:
+ TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs)
+ : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
+ TemplateArgs(TemplateArgs) { }
+
+ // FIXME: Once we get closer to completion, replace these manually-written
+ // declarations with automatically-generated ones from
+ // clang/AST/DeclNodes.inc.
+ Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ Decl *VisitLabelDecl(LabelDecl *D);
+ Decl *VisitNamespaceDecl(NamespaceDecl *D);
+ Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ Decl *VisitTypedefDecl(TypedefDecl *D);
+ Decl *VisitVarDecl(VarDecl *D);
+ Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitFieldDecl(FieldDecl *D);
+ Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+ Decl *VisitEnumDecl(EnumDecl *D);
+ Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+ Decl *VisitFriendDecl(FriendDecl *D);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
+ ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
+ Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+ Decl *VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+ Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ // Base case. FIXME: Remove once we can instantiate everything.
+ Decl *VisitDecl(Decl *D) {
+ unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+ Diagnostic::Error,
+ "cannot instantiate %0 yet");
+ SemaRef.Diag(D->getLocation(), DiagID)
+ << D->getDeclKindName();
+
+ return 0;
+ }
+
+ typedef
+ llvm::SmallVectorImpl<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> >
+ ::iterator
+ delayed_partial_spec_iterator;
+
+ /// \brief Return an iterator to the beginning of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_begin() {
+ return OutOfLinePartialSpecs.begin();
+ }
+
+ /// \brief Return an iterator to the end of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_end() {
+ return OutOfLinePartialSpecs.end();
+ }
+
+ // Helper functions for instantiating methods.
+ TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+ llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+ bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+ bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *List);
+
+ bool SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl);
+ bool SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl);
+
+ ClassTemplatePartialSpecializationDecl *
+ InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
+ };
+}
+
+#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
new file mode 100644
index 0000000..7cc3571
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,134 @@
+//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file provides types used with Sema's template argument deduction
+// routines.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/AST/DeclTemplate.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class ASTContext;
+class TemplateArgumentList;
+
+namespace sema {
+
+/// \brief Provides information about an attempted template argument
+/// deduction, whose success or failure was described by a
+/// TemplateDeductionResult value.
+class TemplateDeductionInfo {
+ /// \brief The context in which the template arguments are stored.
+ ASTContext &Context;
+
+ /// \brief The deduced template argument list.
+ ///
+ TemplateArgumentList *Deduced;
+
+ /// \brief The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
+ /// \brief Warnings (and follow-on notes) that were suppressed due to
+ /// SFINAE while performing template argument deduction.
+ llvm::SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
+
+ // do not implement these
+ TemplateDeductionInfo(const TemplateDeductionInfo&);
+ TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
+
+public:
+ TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
+ : Context(Context), Deduced(0), Loc(Loc) { }
+
+ ~TemplateDeductionInfo() {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ }
+
+ /// \brief Returns the location at which template argument is
+ /// occuring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
+ /// \brief Take ownership of the deduced template argument list.
+ TemplateArgumentList *take() {
+ TemplateArgumentList *Result = Deduced;
+ Deduced = 0;
+ return Result;
+ }
+
+ /// \brief Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeduced) {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ Deduced = NewDeduced;
+ }
+
+ /// \brief Add a new diagnostic to the set of diagnostics
+ void addSuppressedDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
+ SuppressedDiagnostics.push_back(std::make_pair(Loc, PD));
+ }
+
+ /// \brief Iterator over the set of suppressed diagnostics.
+ typedef llvm::SmallVectorImpl<PartialDiagnosticAt>::const_iterator
+ diag_iterator;
+
+ /// \brief Returns an iterator at the beginning of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
+
+ /// \brief Returns an iterator at the end of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
+
+ /// \brief The template parameter to which a template argument
+ /// deduction failure refers.
+ ///
+ /// Depending on the result of template argument deduction, this
+ /// template parameter may have different meanings:
+ ///
+ /// TDK_Incomplete: this is the first template parameter whose
+ /// corresponding template argument was not deduced.
+ ///
+ /// TDK_Inconsistent: this is the template parameter for which
+ /// two different template argument values were deduced.
+ TemplateParameter Param;
+
+ /// \brief The first template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// Depending on the result of the template argument deduction,
+ /// this template argument may have different meanings:
+ ///
+ /// TDK_Inconsistent: this argument is the first value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_SubstitutionFailure: this argument is the template
+ /// argument we were instantiating when we encountered an error.
+ ///
+ /// TDK_NonDeducedMismatch: this is the template argument
+ /// provided in the source code.
+ TemplateArgument FirstArg;
+
+ /// \brief The second template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// FIXME: Finish documenting this.
+ TemplateArgument SecondArg;
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
new file mode 100644
index 0000000..68fd91d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
@@ -0,0 +1,994 @@
+//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines Bitcode enum values for Clang serialized AST files.
+//
+// The enum values defined in this file should be considered permanent. If
+// new features are added, they should have values added at the end of the
+// respective lists.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+
+#include "clang/AST/Type.h"
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+ namespace serialization {
+ /// \brief AST file major version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the AST file format changes in a way that makes it
+ /// incompatible with previous versions (such that a reader
+ /// designed for the previous version could not support reading
+ /// the new version), this number should be increased.
+ ///
+ /// Version 4 of AST files also requires that the version control branch and
+ /// revision match exactly, since there is no backward compatibility of
+ /// AST files at this time.
+ const unsigned VERSION_MAJOR = 4;
+
+ /// \brief AST file minor version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the AST format changes in a way that is still
+ /// compatible with previous versions (such that a reader designed
+ /// for the previous version could still support reading the new
+ /// version by ignoring new kinds of subblocks), this number
+ /// should be increased.
+ const unsigned VERSION_MINOR = 0;
+
+ /// \brief An ID number that refers to a declaration in an AST file.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery) and start at 2. 0 is reserved for NULL, and 1 is
+ /// reserved for the translation unit declaration.
+ typedef uint32_t DeclID;
+
+ /// \brief a Decl::Kind/DeclID pair.
+ typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
+
+ /// \brief An ID number that refers to a type in an AST file.
+ ///
+ /// The ID of a type is partitioned into two parts: the lower
+ /// three bits are used to store the const/volatile/restrict
+ /// qualifiers (as with QualType) and the upper bits provide a
+ /// type index. The type index values are partitioned into two
+ /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
+ /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
+ /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
+ /// other types that have serialized representations.
+ typedef uint32_t TypeID;
+
+ /// \brief A type index; the type ID with the qualifier bits removed.
+ class TypeIdx {
+ uint32_t Idx;
+ public:
+ TypeIdx() : Idx(0) { }
+ explicit TypeIdx(uint32_t index) : Idx(index) { }
+
+ uint32_t getIndex() const { return Idx; }
+ TypeID asTypeID(unsigned FastQuals) const {
+ return (Idx << Qualifiers::FastWidth) | FastQuals;
+ }
+ static TypeIdx fromTypeID(TypeID ID) {
+ return TypeIdx(ID >> Qualifiers::FastWidth);
+ }
+ };
+
+ /// A structure for putting "fast"-unqualified QualTypes into a
+ /// DenseMap. This uses the standard pointer hash function.
+ struct UnsafeQualTypeDenseMapInfo {
+ static inline bool isEqual(QualType A, QualType B) { return A == B; }
+ static inline QualType getEmptyKey() {
+ return QualType::getFromOpaquePtr((void*) 1);
+ }
+ static inline QualType getTombstoneKey() {
+ return QualType::getFromOpaquePtr((void*) 2);
+ }
+ static inline unsigned getHashValue(QualType T) {
+ assert(!T.getLocalFastQualifiers() &&
+ "hash invalid for types with fast quals");
+ uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+ }
+ };
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo>
+ TypeIdxMap;
+
+ /// \brief An ID number that refers to an identifier in an AST file.
+ typedef uint32_t IdentID;
+
+ /// \brief An ID number that refers to a macro in an AST file.
+ typedef uint32_t MacroID;
+
+ /// \brief An ID number that refers to an ObjC selctor in an AST file.
+ typedef uint32_t SelectorID;
+
+ /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
+ /// AST file.
+ typedef uint32_t CXXBaseSpecifiersID;
+
+ /// \brief Describes the various kinds of blocks that occur within
+ /// an AST file.
+ enum BlockIDs {
+ /// \brief The AST block, which acts as a container around the
+ /// full AST block.
+ AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+ /// \brief The block containing information about the source
+ /// manager.
+ SOURCE_MANAGER_BLOCK_ID,
+
+ /// \brief The block containing information about the
+ /// preprocessor.
+ PREPROCESSOR_BLOCK_ID,
+
+ /// \brief The block containing the definitions of all of the
+ /// types and decls used within the AST file.
+ DECLTYPES_BLOCK_ID,
+
+ /// \brief The block containing DECL_UPDATES records.
+ DECL_UPDATES_BLOCK_ID,
+
+ /// \brief The block containing the detailed preprocessing record.
+ PREPROCESSOR_DETAIL_BLOCK_ID
+ };
+
+ /// \brief Record types that occur within the AST block itself.
+ enum ASTRecordTypes {
+ /// \brief Record code for the offsets of each type.
+ ///
+ /// The TYPE_OFFSET constant describes the record that occurs
+ /// within the AST block. The record itself is an array of offsets that
+ /// point into the declarations and types block (identified by
+ /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
+ /// of a type. For a given type ID @c T, the lower three bits of
+ /// @c T are its qualifiers (const, volatile, restrict), as in
+ /// the QualType class. The upper bits, after being shifted and
+ /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+ /// TYPE_OFFSET block to determine the offset of that type's
+ /// corresponding record within the DECLTYPES_BLOCK_ID block.
+ TYPE_OFFSET = 1,
+
+ /// \brief Record code for the offsets of each decl.
+ ///
+ /// The DECL_OFFSET constant describes the record that occurs
+ /// within the block identified by DECL_OFFSETS_BLOCK_ID within
+ /// the AST block. The record itself is an array of offsets that
+ /// point into the declarations and types block (identified by
+ /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
+ /// record, after subtracting one to account for the use of
+ /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+ /// reserved for the translation unit declaration.
+ DECL_OFFSET = 2,
+
+ /// \brief Record code for the language options table.
+ ///
+ /// The record with this code contains the contents of the
+ /// LangOptions structure. We serialize the entire contents of
+ /// the structure, and let the reader decide which options are
+ /// actually important to check.
+ LANGUAGE_OPTIONS = 3,
+
+ /// \brief AST file metadata, including the AST file version number
+ /// and the target triple used to build the AST file.
+ METADATA = 4,
+
+ /// \brief Record code for the table of offsets of each
+ /// identifier ID.
+ ///
+ /// The offset table contains offsets into the blob stored in
+ /// the IDENTIFIER_TABLE record. Each offset points to the
+ /// NULL-terminated string that corresponds to that identifier.
+ IDENTIFIER_OFFSET = 5,
+
+ /// \brief Record code for the identifier table.
+ ///
+ /// The identifier table is a simple blob that contains
+ /// NULL-terminated strings for all of the identifiers
+ /// referenced by the AST file. The IDENTIFIER_OFFSET table
+ /// contains the mapping from identifier IDs to the characters
+ /// in this blob. Note that the starting offsets of all of the
+ /// identifiers are odd, so that, when the identifier offset
+ /// table is loaded in, we can use the low bit to distinguish
+ /// between offsets (for unresolved identifier IDs) and
+ /// IdentifierInfo pointers (for already-resolved identifier
+ /// IDs).
+ IDENTIFIER_TABLE = 6,
+
+ /// \brief Record code for the array of external definitions.
+ ///
+ /// The AST file contains a list of all of the unnamed external
+ /// definitions present within the parsed headers, stored as an
+ /// array of declaration IDs. These external definitions will be
+ /// reported to the AST consumer after the AST file has been
+ /// read, since their presence can affect the semantics of the
+ /// program (e.g., for code generation).
+ EXTERNAL_DEFINITIONS = 7,
+
+ /// \brief Record code for the set of non-builtin, special
+ /// types.
+ ///
+ /// This record contains the type IDs for the various type nodes
+ /// that are constructed during semantic analysis (e.g.,
+ /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
+ /// offsets into this record.
+ SPECIAL_TYPES = 8,
+
+ /// \brief Record code for the extra statistics we gather while
+ /// generating an AST file.
+ STATISTICS = 9,
+
+ /// \brief Record code for the array of tentative definitions.
+ TENTATIVE_DEFINITIONS = 10,
+
+ /// \brief Record code for the array of locally-scoped external
+ /// declarations.
+ LOCALLY_SCOPED_EXTERNAL_DECLS = 11,
+
+ /// \brief Record code for the table of offsets into the
+ /// Objective-C method pool.
+ SELECTOR_OFFSETS = 12,
+
+ /// \brief Record code for the Objective-C method pool,
+ METHOD_POOL = 13,
+
+ /// \brief The value of the next __COUNTER__ to dispense.
+ /// [PP_COUNTER_VALUE, Val]
+ PP_COUNTER_VALUE = 14,
+
+ /// \brief Record code for the table of offsets into the block
+ /// of source-location information.
+ SOURCE_LOCATION_OFFSETS = 15,
+
+ /// \brief Record code for the set of source location entries
+ /// that need to be preloaded by the AST reader.
+ ///
+ /// This set contains the source location entry for the
+ /// predefines buffer and for any file entries that need to be
+ /// preloaded.
+ SOURCE_LOCATION_PRELOADS = 16,
+
+ /// \brief Record code for the stat() cache.
+ STAT_CACHE = 17,
+
+ /// \brief Record code for the set of ext_vector type names.
+ EXT_VECTOR_DECLS = 18,
+
+ /// \brief Record code for the original file that was used to
+ /// generate the AST file.
+ ORIGINAL_FILE_NAME = 19,
+
+ /// Record #20 intentionally left blank.
+
+ /// \brief Record code for the version control branch and revision
+ /// information of the compiler used to build this AST file.
+ VERSION_CONTROL_BRANCH_REVISION = 21,
+
+ /// \brief Record code for the array of unused file scoped decls.
+ UNUSED_FILESCOPED_DECLS = 22,
+
+ /// \brief Record code for the table of offsets to macro definition
+ /// entries in the preprocessing record.
+ MACRO_DEFINITION_OFFSETS = 23,
+
+ /// \brief Record code for the array of VTable uses.
+ VTABLE_USES = 24,
+
+ /// \brief Record code for the array of dynamic classes.
+ DYNAMIC_CLASSES = 25,
+
+ /// \brief Record code for the chained AST metadata, including the
+ /// AST file version and the name of the PCH this depends on.
+ CHAINED_METADATA = 26,
+
+ /// \brief Record code for referenced selector pool.
+ REFERENCED_SELECTOR_POOL = 27,
+
+ /// \brief Record code for an update to the TU's lexically contained
+ /// declarations.
+ TU_UPDATE_LEXICAL = 28,
+
+ /// \brief Record code for an update to first decls pointing to the
+ /// latest redeclarations.
+ REDECLS_UPDATE_LATEST = 29,
+
+ /// \brief Record code for declarations that Sema keeps references of.
+ SEMA_DECL_REFS = 30,
+
+ /// \brief Record code for weak undeclared identifiers.
+ WEAK_UNDECLARED_IDENTIFIERS = 31,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 32,
+
+ /// \brief Record code for a decl replacement block.
+ ///
+ /// If a declaration is modified after having been deserialized, and then
+ /// written to a dependent AST file, its ID and offset must be added to
+ /// the replacement block.
+ DECL_REPLACEMENTS = 33,
+
+ /// \brief Record code for an update to a decl context's lookup table.
+ ///
+ /// In practice, this should only be used for the TU and namespaces.
+ UPDATE_VISIBLE = 34,
+
+ /// \brief Record for offsets of DECL_UPDATES records for declarations
+ /// that were modified after being deserialized and need updates.
+ DECL_UPDATE_OFFSETS = 35,
+
+ /// \brief Record of updates for a declaration that was modified after
+ /// being deserialized.
+ DECL_UPDATES = 36,
+
+ /// \brief Record code for the table of offsets to CXXBaseSpecifier
+ /// sets.
+ CXX_BASE_SPECIFIER_OFFSETS = 37,
+
+ /// \brief Record code for #pragma diagnostic mappings.
+ DIAG_PRAGMA_MAPPINGS = 38,
+
+ /// \brief Record code for special CUDA declarations.
+ CUDA_SPECIAL_DECL_REFS = 39,
+
+ /// \brief Record code for header search information.
+ HEADER_SEARCH_TABLE = 40,
+
+ /// \brief The directory that the PCH was originally created in.
+ ORIGINAL_PCH_DIR = 41,
+
+ /// \brief Record code for floating point #pragma options.
+ FP_PRAGMA_OPTIONS = 42,
+
+ /// \brief Record code for enabled OpenCL extensions.
+ OPENCL_EXTENSIONS = 43
+ };
+
+ /// \brief Record types used within a source manager block.
+ enum SourceManagerRecordTypes {
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// file.
+ SM_SLOC_FILE_ENTRY = 1,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// buffer.
+ SM_SLOC_BUFFER_ENTRY = 2,
+ /// \brief Describes a blob that contains the data for a buffer
+ /// entry. This kind of record always directly follows a
+ /// SM_SLOC_BUFFER_ENTRY record.
+ SM_SLOC_BUFFER_BLOB = 3,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// macro instantiation.
+ SM_SLOC_INSTANTIATION_ENTRY = 4,
+ /// \brief Describes the SourceManager's line table, with
+ /// information about #line directives.
+ SM_LINE_TABLE = 5
+ };
+
+ /// \brief Record types used within a preprocessor block.
+ enum PreprocessorRecordTypes {
+ // The macros in the PP section are a PP_MACRO_* instance followed by a
+ // list of PP_TOKEN instances for each token in the definition.
+
+ /// \brief An object-like macro definition.
+ /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
+ PP_MACRO_OBJECT_LIKE = 1,
+
+ /// \brief A function-like macro definition.
+ /// [PP_MACRO_FUNCTION_LIKE, <ObjectLikeStuff>, IsC99Varargs, IsGNUVarars,
+ /// NumArgs, ArgIdentInfoID* ]
+ PP_MACRO_FUNCTION_LIKE = 2,
+
+ /// \brief Describes one token.
+ /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
+ PP_TOKEN = 3
+ };
+
+ /// \brief Record types used within a preprocessor detail block.
+ enum PreprocessorDetailRecordTypes {
+ /// \brief Describes a macro instantiation within the preprocessing
+ /// record.
+ PPD_MACRO_INSTANTIATION = 0,
+
+ /// \brief Describes a macro definition within the preprocessing record.
+ PPD_MACRO_DEFINITION = 1,
+
+ /// \brief Describes an inclusion directive within the preprocessing
+ /// record.
+ PPD_INCLUSION_DIRECTIVE = 2
+ };
+
+ /// \defgroup ASTAST AST file AST constants
+ ///
+ /// The constants in this group describe various components of the
+ /// abstract syntax tree within an AST file.
+ ///
+ /// @{
+
+ /// \brief Predefined type IDs.
+ ///
+ /// These type IDs correspond to predefined types in the AST
+ /// context, such as built-in types (int) and special place-holder
+ /// types (the <overload> and <dependent> type markers). Such
+ /// types are never actually serialized, since they will be built
+ /// by the AST context when it is created.
+ enum PredefinedTypeIDs {
+ /// \brief The NULL type.
+ PREDEF_TYPE_NULL_ID = 0,
+ /// \brief The void type.
+ PREDEF_TYPE_VOID_ID = 1,
+ /// \brief The 'bool' or '_Bool' type.
+ PREDEF_TYPE_BOOL_ID = 2,
+ /// \brief The 'char' type, when it is unsigned.
+ PREDEF_TYPE_CHAR_U_ID = 3,
+ /// \brief The 'unsigned char' type.
+ PREDEF_TYPE_UCHAR_ID = 4,
+ /// \brief The 'unsigned short' type.
+ PREDEF_TYPE_USHORT_ID = 5,
+ /// \brief The 'unsigned int' type.
+ PREDEF_TYPE_UINT_ID = 6,
+ /// \brief The 'unsigned long' type.
+ PREDEF_TYPE_ULONG_ID = 7,
+ /// \brief The 'unsigned long long' type.
+ PREDEF_TYPE_ULONGLONG_ID = 8,
+ /// \brief The 'char' type, when it is signed.
+ PREDEF_TYPE_CHAR_S_ID = 9,
+ /// \brief The 'signed char' type.
+ PREDEF_TYPE_SCHAR_ID = 10,
+ /// \brief The C++ 'wchar_t' type.
+ PREDEF_TYPE_WCHAR_ID = 11,
+ /// \brief The (signed) 'short' type.
+ PREDEF_TYPE_SHORT_ID = 12,
+ /// \brief The (signed) 'int' type.
+ PREDEF_TYPE_INT_ID = 13,
+ /// \brief The (signed) 'long' type.
+ PREDEF_TYPE_LONG_ID = 14,
+ /// \brief The (signed) 'long long' type.
+ PREDEF_TYPE_LONGLONG_ID = 15,
+ /// \brief The 'float' type.
+ PREDEF_TYPE_FLOAT_ID = 16,
+ /// \brief The 'double' type.
+ PREDEF_TYPE_DOUBLE_ID = 17,
+ /// \brief The 'long double' type.
+ PREDEF_TYPE_LONGDOUBLE_ID = 18,
+ /// \brief The placeholder type for overloaded function sets.
+ PREDEF_TYPE_OVERLOAD_ID = 19,
+ /// \brief The placeholder type for dependent types.
+ PREDEF_TYPE_DEPENDENT_ID = 20,
+ /// \brief The '__uint128_t' type.
+ PREDEF_TYPE_UINT128_ID = 21,
+ /// \brief The '__int128_t' type.
+ PREDEF_TYPE_INT128_ID = 22,
+ /// \brief The type of 'nullptr'.
+ PREDEF_TYPE_NULLPTR_ID = 23,
+ /// \brief The C++ 'char16_t' type.
+ PREDEF_TYPE_CHAR16_ID = 24,
+ /// \brief The C++ 'char32_t' type.
+ PREDEF_TYPE_CHAR32_ID = 25,
+ /// \brief The ObjC 'id' type.
+ PREDEF_TYPE_OBJC_ID = 26,
+ /// \brief The ObjC 'Class' type.
+ PREDEF_TYPE_OBJC_CLASS = 27,
+ /// \brief The ObjC 'SEL' type.
+ PREDEF_TYPE_OBJC_SEL = 28
+ };
+
+ /// \brief The number of predefined type IDs that are reserved for
+ /// the PREDEF_TYPE_* constants.
+ ///
+ /// Type IDs for non-predefined types will start at
+ /// NUM_PREDEF_TYPE_IDs.
+ const unsigned NUM_PREDEF_TYPE_IDS = 100;
+
+ /// \brief Record codes for each kind of type.
+ ///
+ /// These constants describe the type records that can occur within a
+ /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
+ /// constant describes a record for a specific type class in the
+ /// AST.
+ enum TypeCode {
+ /// \brief An ExtQualType record.
+ TYPE_EXT_QUAL = 1,
+ /// \brief A ComplexType record.
+ TYPE_COMPLEX = 3,
+ /// \brief A PointerType record.
+ TYPE_POINTER = 4,
+ /// \brief A BlockPointerType record.
+ TYPE_BLOCK_POINTER = 5,
+ /// \brief An LValueReferenceType record.
+ TYPE_LVALUE_REFERENCE = 6,
+ /// \brief An RValueReferenceType record.
+ TYPE_RVALUE_REFERENCE = 7,
+ /// \brief A MemberPointerType record.
+ TYPE_MEMBER_POINTER = 8,
+ /// \brief A ConstantArrayType record.
+ TYPE_CONSTANT_ARRAY = 9,
+ /// \brief An IncompleteArrayType record.
+ TYPE_INCOMPLETE_ARRAY = 10,
+ /// \brief A VariableArrayType record.
+ TYPE_VARIABLE_ARRAY = 11,
+ /// \brief A VectorType record.
+ TYPE_VECTOR = 12,
+ /// \brief An ExtVectorType record.
+ TYPE_EXT_VECTOR = 13,
+ /// \brief A FunctionNoProtoType record.
+ TYPE_FUNCTION_NO_PROTO = 14,
+ /// \brief A FunctionProtoType record.
+ TYPE_FUNCTION_PROTO = 15,
+ /// \brief A TypedefType record.
+ TYPE_TYPEDEF = 16,
+ /// \brief A TypeOfExprType record.
+ TYPE_TYPEOF_EXPR = 17,
+ /// \brief A TypeOfType record.
+ TYPE_TYPEOF = 18,
+ /// \brief A RecordType record.
+ TYPE_RECORD = 19,
+ /// \brief An EnumType record.
+ TYPE_ENUM = 20,
+ /// \brief An ObjCInterfaceType record.
+ TYPE_OBJC_INTERFACE = 21,
+ /// \brief An ObjCObjectPointerType record.
+ TYPE_OBJC_OBJECT_POINTER = 22,
+ /// \brief a DecltypeType record.
+ TYPE_DECLTYPE = 23,
+ /// \brief An ElaboratedType record.
+ TYPE_ELABORATED = 24,
+ /// \brief A SubstTemplateTypeParmType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
+ /// \brief An UnresolvedUsingType record.
+ TYPE_UNRESOLVED_USING = 26,
+ /// \brief An InjectedClassNameType record.
+ TYPE_INJECTED_CLASS_NAME = 27,
+ /// \brief An ObjCObjectType record.
+ TYPE_OBJC_OBJECT = 28,
+ /// \brief An TemplateTypeParmType record.
+ TYPE_TEMPLATE_TYPE_PARM = 29,
+ /// \brief An TemplateSpecializationType record.
+ TYPE_TEMPLATE_SPECIALIZATION = 30,
+ /// \brief A DependentNameType record.
+ TYPE_DEPENDENT_NAME = 31,
+ /// \brief A DependentTemplateSpecializationType record.
+ TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
+ /// \brief A DependentSizedArrayType record.
+ TYPE_DEPENDENT_SIZED_ARRAY = 33,
+ /// \brief A ParenType record.
+ TYPE_PAREN = 34,
+ /// \brief A PackExpansionType record.
+ TYPE_PACK_EXPANSION = 35,
+ /// \brief An AttributedType record.
+ TYPE_ATTRIBUTED = 36,
+ /// \brief A SubstTemplateTypeParmPackType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
+ /// \brief A AutoType record.
+ TYPE_AUTO = 38
+ };
+
+ /// \brief The type IDs for special types constructed by semantic
+ /// analysis.
+ ///
+ /// The constants in this enumeration are indices into the
+ /// SPECIAL_TYPES record.
+ enum SpecialTypeIDs {
+ /// \brief __builtin_va_list
+ SPECIAL_TYPE_BUILTIN_VA_LIST = 0,
+ /// \brief Objective-C "id" type
+ SPECIAL_TYPE_OBJC_ID = 1,
+ /// \brief Objective-C selector type
+ SPECIAL_TYPE_OBJC_SELECTOR = 2,
+ /// \brief Objective-C Protocol type
+ SPECIAL_TYPE_OBJC_PROTOCOL = 3,
+ /// \brief Objective-C Class type
+ SPECIAL_TYPE_OBJC_CLASS = 4,
+ /// \brief CFConstantString type
+ SPECIAL_TYPE_CF_CONSTANT_STRING = 5,
+ /// \brief Objective-C fast enumeration state type
+ SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6,
+ /// \brief C FILE typedef type
+ SPECIAL_TYPE_FILE = 7,
+ /// \brief C jmp_buf typedef type
+ SPECIAL_TYPE_jmp_buf = 8,
+ /// \brief C sigjmp_buf typedef type
+ SPECIAL_TYPE_sigjmp_buf = 9,
+ /// \brief Objective-C "id" redefinition type
+ SPECIAL_TYPE_OBJC_ID_REDEFINITION = 10,
+ /// \brief Objective-C "Class" redefinition type
+ SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11,
+ /// \brief Block descriptor type for Blocks CodeGen
+ SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12,
+ /// \brief Block extedned descriptor type for Blocks CodeGen
+ SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13,
+ /// \brief Objective-C "SEL" redefinition type
+ SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14,
+ /// \brief NSConstantString type
+ SPECIAL_TYPE_NS_CONSTANT_STRING = 15,
+ /// \brief Whether __[u]int128_t identifier is installed.
+ SPECIAL_TYPE_INT128_INSTALLED = 16
+ };
+
+ /// \brief Record codes for each kind of declaration.
+ ///
+ /// These constants describe the declaration records that can occur within
+ /// a declarations block (identified by DECLS_BLOCK_ID). Each
+ /// constant describes a record for a specific declaration class
+ /// in the AST.
+ enum DeclCode {
+ /// \brief A TranslationUnitDecl record.
+ DECL_TRANSLATION_UNIT = 50,
+ /// \brief A TypedefDecl record.
+ DECL_TYPEDEF,
+ /// \brief An EnumDecl record.
+ DECL_ENUM,
+ /// \brief A RecordDecl record.
+ DECL_RECORD,
+ /// \brief An EnumConstantDecl record.
+ DECL_ENUM_CONSTANT,
+ /// \brief A FunctionDecl record.
+ DECL_FUNCTION,
+ /// \brief A ObjCMethodDecl record.
+ DECL_OBJC_METHOD,
+ /// \brief A ObjCInterfaceDecl record.
+ DECL_OBJC_INTERFACE,
+ /// \brief A ObjCProtocolDecl record.
+ DECL_OBJC_PROTOCOL,
+ /// \brief A ObjCIvarDecl record.
+ DECL_OBJC_IVAR,
+ /// \brief A ObjCAtDefsFieldDecl record.
+ DECL_OBJC_AT_DEFS_FIELD,
+ /// \brief A ObjCClassDecl record.
+ DECL_OBJC_CLASS,
+ /// \brief A ObjCForwardProtocolDecl record.
+ DECL_OBJC_FORWARD_PROTOCOL,
+ /// \brief A ObjCCategoryDecl record.
+ DECL_OBJC_CATEGORY,
+ /// \brief A ObjCCategoryImplDecl record.
+ DECL_OBJC_CATEGORY_IMPL,
+ /// \brief A ObjCImplementationDecl record.
+ DECL_OBJC_IMPLEMENTATION,
+ /// \brief A ObjCCompatibleAliasDecl record.
+ DECL_OBJC_COMPATIBLE_ALIAS,
+ /// \brief A ObjCPropertyDecl record.
+ DECL_OBJC_PROPERTY,
+ /// \brief A ObjCPropertyImplDecl record.
+ DECL_OBJC_PROPERTY_IMPL,
+ /// \brief A FieldDecl record.
+ DECL_FIELD,
+ /// \brief A VarDecl record.
+ DECL_VAR,
+ /// \brief An ImplicitParamDecl record.
+ DECL_IMPLICIT_PARAM,
+ /// \brief A ParmVarDecl record.
+ DECL_PARM_VAR,
+ /// \brief A FileScopeAsmDecl record.
+ DECL_FILE_SCOPE_ASM,
+ /// \brief A BlockDecl record.
+ DECL_BLOCK,
+ /// \brief A record that stores the set of declarations that are
+ /// lexically stored within a given DeclContext.
+ ///
+ /// The record itself is a blob that is an array of declaration IDs,
+ /// in the order in which those declarations were added to the
+ /// declaration context. This data is used when iterating over
+ /// the contents of a DeclContext, e.g., via
+ /// DeclContext::decls_begin()/DeclContext::decls_end().
+ DECL_CONTEXT_LEXICAL,
+ /// \brief A record that stores the set of declarations that are
+ /// visible from a given DeclContext.
+ ///
+ /// The record itself stores a set of mappings, each of which
+ /// associates a declaration name with one or more declaration
+ /// IDs. This data is used when performing qualified name lookup
+ /// into a DeclContext via DeclContext::lookup.
+ DECL_CONTEXT_VISIBLE,
+ /// \brief A LabelDecl record.
+ DECL_LABEL,
+ /// \brief A NamespaceDecl record.
+ DECL_NAMESPACE,
+ /// \brief A NamespaceAliasDecl record.
+ DECL_NAMESPACE_ALIAS,
+ /// \brief A UsingDecl record.
+ DECL_USING,
+ /// \brief A UsingShadowDecl record.
+ DECL_USING_SHADOW,
+ /// \brief A UsingDirecitveDecl record.
+ DECL_USING_DIRECTIVE,
+ /// \brief An UnresolvedUsingValueDecl record.
+ DECL_UNRESOLVED_USING_VALUE,
+ /// \brief An UnresolvedUsingTypenameDecl record.
+ DECL_UNRESOLVED_USING_TYPENAME,
+ /// \brief A LinkageSpecDecl record.
+ DECL_LINKAGE_SPEC,
+ /// \brief A CXXRecordDecl record.
+ DECL_CXX_RECORD,
+ /// \brief A CXXMethodDecl record.
+ DECL_CXX_METHOD,
+ /// \brief A CXXConstructorDecl record.
+ DECL_CXX_CONSTRUCTOR,
+ /// \brief A CXXDestructorDecl record.
+ DECL_CXX_DESTRUCTOR,
+ /// \brief A CXXConversionDecl record.
+ DECL_CXX_CONVERSION,
+ /// \brief An AccessSpecDecl record.
+ DECL_ACCESS_SPEC,
+
+ /// \brief A FriendDecl record.
+ DECL_FRIEND,
+ /// \brief A FriendTemplateDecl record.
+ DECL_FRIEND_TEMPLATE,
+ /// \brief A ClassTemplateDecl record.
+ DECL_CLASS_TEMPLATE,
+ /// \brief A ClassTemplateSpecializationDecl record.
+ DECL_CLASS_TEMPLATE_SPECIALIZATION,
+ /// \brief A ClassTemplatePartialSpecializationDecl record.
+ DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+ /// \brief A FunctionTemplateDecl record.
+ DECL_FUNCTION_TEMPLATE,
+ /// \brief A TemplateTypeParmDecl record.
+ DECL_TEMPLATE_TYPE_PARM,
+ /// \brief A NonTypeTemplateParmDecl record.
+ DECL_NON_TYPE_TEMPLATE_PARM,
+ /// \brief A TemplateTemplateParmDecl record.
+ DECL_TEMPLATE_TEMPLATE_PARM,
+ /// \brief A StaticAssertDecl record.
+ DECL_STATIC_ASSERT,
+ /// \brief A record containing CXXBaseSpecifiers.
+ DECL_CXX_BASE_SPECIFIERS,
+ /// \brief A IndirectFieldDecl record.
+ DECL_INDIRECTFIELD,
+ /// \brief A NonTypeTemplateParmDecl record that stores an expanded
+ /// non-type template parameter pack.
+ DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK
+ };
+
+ /// \brief Record codes for each kind of statement or expression.
+ ///
+ /// These constants describe the records that describe statements
+ /// or expressions. These records occur within type and declarations
+ /// block, so they begin with record values of 100. Each constant
+ /// describes a record for a specific statement or expression class in the
+ /// AST.
+ enum StmtCode {
+ /// \brief A marker record that indicates that we are at the end
+ /// of an expression.
+ STMT_STOP = 100,
+ /// \brief A NULL expression.
+ STMT_NULL_PTR,
+ /// \brief A NullStmt record.
+ STMT_NULL,
+ /// \brief A CompoundStmt record.
+ STMT_COMPOUND,
+ /// \brief A CaseStmt record.
+ STMT_CASE,
+ /// \brief A DefaultStmt record.
+ STMT_DEFAULT,
+ /// \brief A LabelStmt record.
+ STMT_LABEL,
+ /// \brief An IfStmt record.
+ STMT_IF,
+ /// \brief A SwitchStmt record.
+ STMT_SWITCH,
+ /// \brief A WhileStmt record.
+ STMT_WHILE,
+ /// \brief A DoStmt record.
+ STMT_DO,
+ /// \brief A ForStmt record.
+ STMT_FOR,
+ /// \brief A GotoStmt record.
+ STMT_GOTO,
+ /// \brief An IndirectGotoStmt record.
+ STMT_INDIRECT_GOTO,
+ /// \brief A ContinueStmt record.
+ STMT_CONTINUE,
+ /// \brief A BreakStmt record.
+ STMT_BREAK,
+ /// \brief A ReturnStmt record.
+ STMT_RETURN,
+ /// \brief A DeclStmt record.
+ STMT_DECL,
+ /// \brief An AsmStmt record.
+ STMT_ASM,
+ /// \brief A PredefinedExpr record.
+ EXPR_PREDEFINED,
+ /// \brief A DeclRefExpr record.
+ EXPR_DECL_REF,
+ /// \brief An IntegerLiteral record.
+ EXPR_INTEGER_LITERAL,
+ /// \brief A FloatingLiteral record.
+ EXPR_FLOATING_LITERAL,
+ /// \brief An ImaginaryLiteral record.
+ EXPR_IMAGINARY_LITERAL,
+ /// \brief A StringLiteral record.
+ EXPR_STRING_LITERAL,
+ /// \brief A CharacterLiteral record.
+ EXPR_CHARACTER_LITERAL,
+ /// \brief A ParenExpr record.
+ EXPR_PAREN,
+ /// \brief A ParenListExpr record.
+ EXPR_PAREN_LIST,
+ /// \brief A UnaryOperator record.
+ EXPR_UNARY_OPERATOR,
+ /// \brief An OffsetOfExpr record.
+ EXPR_OFFSETOF,
+ /// \brief A SizefAlignOfExpr record.
+ EXPR_SIZEOF_ALIGN_OF,
+ /// \brief An ArraySubscriptExpr record.
+ EXPR_ARRAY_SUBSCRIPT,
+ /// \brief A CallExpr record.
+ EXPR_CALL,
+ /// \brief A MemberExpr record.
+ EXPR_MEMBER,
+ /// \brief A BinaryOperator record.
+ EXPR_BINARY_OPERATOR,
+ /// \brief A CompoundAssignOperator record.
+ EXPR_COMPOUND_ASSIGN_OPERATOR,
+ /// \brief A ConditionOperator record.
+ EXPR_CONDITIONAL_OPERATOR,
+ /// \brief An ImplicitCastExpr record.
+ EXPR_IMPLICIT_CAST,
+ /// \brief A CStyleCastExpr record.
+ EXPR_CSTYLE_CAST,
+ /// \brief A CompoundLiteralExpr record.
+ EXPR_COMPOUND_LITERAL,
+ /// \brief An ExtVectorElementExpr record.
+ EXPR_EXT_VECTOR_ELEMENT,
+ /// \brief An InitListExpr record.
+ EXPR_INIT_LIST,
+ /// \brief A DesignatedInitExpr record.
+ EXPR_DESIGNATED_INIT,
+ /// \brief An ImplicitValueInitExpr record.
+ EXPR_IMPLICIT_VALUE_INIT,
+ /// \brief A VAArgExpr record.
+ EXPR_VA_ARG,
+ /// \brief An AddrLabelExpr record.
+ EXPR_ADDR_LABEL,
+ /// \brief A StmtExpr record.
+ EXPR_STMT,
+ /// \brief A ChooseExpr record.
+ EXPR_CHOOSE,
+ /// \brief A GNUNullExpr record.
+ EXPR_GNU_NULL,
+ /// \brief A ShuffleVectorExpr record.
+ EXPR_SHUFFLE_VECTOR,
+ /// \brief BlockExpr
+ EXPR_BLOCK,
+ /// \brief A BlockDeclRef record.
+ EXPR_BLOCK_DECL_REF,
+
+ // Objective-C
+
+ /// \brief An ObjCStringLiteral record.
+ EXPR_OBJC_STRING_LITERAL,
+ /// \brief An ObjCEncodeExpr record.
+ EXPR_OBJC_ENCODE,
+ /// \brief An ObjCSelectorExpr record.
+ EXPR_OBJC_SELECTOR_EXPR,
+ /// \brief An ObjCProtocolExpr record.
+ EXPR_OBJC_PROTOCOL_EXPR,
+ /// \brief An ObjCIvarRefExpr record.
+ EXPR_OBJC_IVAR_REF_EXPR,
+ /// \brief An ObjCPropertyRefExpr record.
+ EXPR_OBJC_PROPERTY_REF_EXPR,
+ /// \brief UNUSED
+ EXPR_OBJC_KVC_REF_EXPR,
+ /// \brief An ObjCMessageExpr record.
+ EXPR_OBJC_MESSAGE_EXPR,
+ /// \brief An ObjCIsa Expr record.
+ EXPR_OBJC_ISA,
+
+ /// \brief An ObjCForCollectionStmt record.
+ STMT_OBJC_FOR_COLLECTION,
+ /// \brief An ObjCAtCatchStmt record.
+ STMT_OBJC_CATCH,
+ /// \brief An ObjCAtFinallyStmt record.
+ STMT_OBJC_FINALLY,
+ /// \brief An ObjCAtTryStmt record.
+ STMT_OBJC_AT_TRY,
+ /// \brief An ObjCAtSynchronizedStmt record.
+ STMT_OBJC_AT_SYNCHRONIZED,
+ /// \brief An ObjCAtThrowStmt record.
+ STMT_OBJC_AT_THROW,
+
+ // C++
+
+ /// \brief A CXXCatchStmt record.
+ STMT_CXX_CATCH,
+ /// \brief A CXXTryStmt record.
+ STMT_CXX_TRY,
+
+ /// \brief A CXXOperatorCallExpr record.
+ EXPR_CXX_OPERATOR_CALL,
+ /// \brief A CXXMemberCallExpr record.
+ EXPR_CXX_MEMBER_CALL,
+ /// \brief A CXXConstructExpr record.
+ EXPR_CXX_CONSTRUCT,
+ /// \brief A CXXTemporaryObjectExpr record.
+ EXPR_CXX_TEMPORARY_OBJECT,
+ /// \brief A CXXStaticCastExpr record.
+ EXPR_CXX_STATIC_CAST,
+ /// \brief A CXXDynamicCastExpr record.
+ EXPR_CXX_DYNAMIC_CAST,
+ /// \brief A CXXReinterpretCastExpr record.
+ EXPR_CXX_REINTERPRET_CAST,
+ /// \brief A CXXConstCastExpr record.
+ EXPR_CXX_CONST_CAST,
+ /// \brief A CXXFunctionalCastExpr record.
+ EXPR_CXX_FUNCTIONAL_CAST,
+ /// \brief A CXXBoolLiteralExpr record.
+ EXPR_CXX_BOOL_LITERAL,
+ EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
+ EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
+ EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
+ EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
+ EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
+ EXPR_CXX_THIS, // CXXThisExpr
+ EXPR_CXX_THROW, // CXXThrowExpr
+ EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
+ EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
+
+ EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
+ EXPR_CXX_NEW, // CXXNewExpr
+ EXPR_CXX_DELETE, // CXXDeleteExpr
+ EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
+
+ EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
+
+ EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
+ EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
+ EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
+ EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
+ EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
+
+ EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
+ EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
+
+ EXPR_OPAQUE_VALUE, // OpaqueValueExpr
+ EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
+
+ EXPR_PACK_EXPANSION, // PackExpansionExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
+
+ // CUDA
+
+ EXPR_CUDA_KERNEL_CALL // CUDAKernelCallExpr
+ };
+
+ /// \brief The kinds of designators that can occur in a
+ /// DesignatedInitExpr.
+ enum DesignatorTypes {
+ /// \brief Field designator where only the field name is known.
+ DESIG_FIELD_NAME = 0,
+ /// \brief Field designator where the field has been resolved to
+ /// a declaration.
+ DESIG_FIELD_DECL = 1,
+ /// \brief Array designator.
+ DESIG_ARRAY = 2,
+ /// \brief GNU array range designator.
+ DESIG_ARRAY_RANGE = 3
+ };
+
+ /// @}
+ }
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
new file mode 100644
index 0000000..f8cdebe
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
@@ -0,0 +1,54 @@
+//===- ASTDeserializationListener.h - Decl/Type PCH Read Events -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTDeserializationListener class, which is notified
+// by the ASTReader whenever a type or declaration is deserialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+class Decl;
+class ASTReader;
+class QualType;
+class MacroDefinition;
+
+class ASTDeserializationListener {
+protected:
+ virtual ~ASTDeserializationListener();
+
+public:
+
+ /// \brief The ASTReader was initialized.
+ virtual void ReaderInitialized(ASTReader *Reader) { }
+
+ /// \brief An identifier was deserialized from the AST file.
+ virtual void IdentifierRead(serialization::IdentID ID,
+ IdentifierInfo *II) { }
+ /// \brief A type was deserialized from the AST file. The ID here has the
+ /// qualifier bits already removed, and T is guaranteed to be locally
+ /// unqualified.
+ virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { }
+ /// \brief A decl was deserialized from the AST file.
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) { }
+ /// \brief A selector was read from the AST file.
+ virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) { }
+ /// \brief A macro definition was read from the AST file.
+ virtual void MacroDefinitionRead(serialization::MacroID,
+ MacroDefinition *MD) { }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
new file mode 100644
index 0000000..9799b8d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -0,0 +1,1292 @@
+//===--- ASTReader.h - AST File Reader --------------------------*- 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 ASTReader class, which reads AST files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_AST_READER_H
+#define LLVM_CLANG_FRONTEND_AST_READER_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/DataTypes.h"
+#include <deque>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class AddrLabelExpr;
+class ASTConsumer;
+class ASTContext;
+class ASTIdentifierIterator;
+class Attr;
+class Decl;
+class DeclContext;
+class NestedNameSpecifier;
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class GotoStmt;
+class MacroDefinition;
+class NamedDecl;
+class OpaqueValueExpr;
+class Preprocessor;
+class Sema;
+class SwitchCase;
+class ASTDeserializationListener;
+class ASTReader;
+class ASTDeclReader;
+class ASTStmtReader;
+class ASTIdentifierLookupTrait;
+class TypeLocReader;
+struct HeaderFileInfo;
+
+struct PCHPredefinesBlock {
+ /// \brief The file ID for this predefines buffer in a PCH file.
+ FileID BufferID;
+
+ /// \brief This predefines buffer in a PCH file.
+ llvm::StringRef Data;
+};
+typedef llvm::SmallVector<PCHPredefinesBlock, 2> PCHPredefinesBlocks;
+
+/// \brief Abstract interface for callback invocations by the ASTReader.
+///
+/// While reading an AST file, the ASTReader will call the methods of the
+/// listener to pass on specific information. Some of the listener methods can
+/// return true to indicate to the ASTReader that the information (and
+/// consequently the AST file) is invalid.
+class ASTReaderListener {
+public:
+ virtual ~ASTReaderListener();
+
+ /// \brief Receives the language options.
+ ///
+ /// \returns true to indicate the options are invalid or false otherwise.
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ return false;
+ }
+
+ /// \brief Receives the target triple.
+ ///
+ /// \returns true to indicate the target triple is invalid or false otherwise.
+ virtual bool ReadTargetTriple(llvm::StringRef Triple) {
+ return false;
+ }
+
+ /// \brief Receives the contents of the predefines buffer.
+ ///
+ /// \param Buffers Information about the predefines buffers.
+ ///
+ /// \param OriginalFileName The original file name for the AST file, which
+ /// will appear as an entry in the predefines buffer.
+ ///
+ /// \param SuggestedPredefines If necessary, additional definitions are added
+ /// here.
+ ///
+ /// \returns true to indicate the predefines are invalid or false otherwise.
+ virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
+ llvm::StringRef OriginalFileName,
+ std::string &SuggestedPredefines) {
+ return false;
+ }
+
+ /// \brief Receives a HeaderFileInfo entry.
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {}
+
+ /// \brief Receives __COUNTER__ value.
+ virtual void ReadCounter(unsigned Value) {}
+};
+
+/// \brief ASTReaderListener implementation to validate the information of
+/// the PCH file against an initialized Preprocessor.
+class PCHValidator : public ASTReaderListener {
+ Preprocessor &PP;
+ ASTReader &Reader;
+
+ unsigned NumHeaderInfos;
+
+public:
+ PCHValidator(Preprocessor &PP, ASTReader &Reader)
+ : PP(PP), Reader(Reader), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
+ virtual bool ReadTargetTriple(llvm::StringRef Triple);
+ virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
+ llvm::StringRef OriginalFileName,
+ std::string &SuggestedPredefines);
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
+ virtual void ReadCounter(unsigned Value);
+
+private:
+ void Error(const char *Msg);
+};
+
+/// \brief Reads an AST files chain containing the contents of a translation
+/// unit.
+///
+/// The ASTReader class reads bitstreams (produced by the ASTWriter
+/// class) containing the serialized representation of a given
+/// abstract syntax tree and its supporting data structures. An
+/// instance of the ASTReader can be attached to an ASTContext object,
+/// which will provide access to the contents of the AST files.
+///
+/// The AST reader provides lazy de-serialization of declarations, as
+/// required when traversing the AST. Only those AST nodes that are
+/// actually required will be de-serialized.
+class ASTReader
+ : public ExternalPreprocessorSource,
+ public ExternalPreprocessingRecordSource,
+ public ExternalHeaderFileInfoSource,
+ public ExternalSemaSource,
+ public IdentifierInfoLookup,
+ public ExternalIdentifierLookup,
+ public ExternalSLocEntrySource
+{
+public:
+ enum ASTReadResult { Success, Failure, IgnorePCH };
+ /// \brief Types of AST files.
+ enum ASTFileType {
+ Module, ///< File is a module proper.
+ PCH, ///< File is a PCH file treated as such.
+ Preamble, ///< File is a PCH file treated as the preamble.
+ MainFile ///< File is a PCH file treated as the actual main file.
+ };
+ friend class PCHValidator;
+ friend class ASTDeclReader;
+ friend class ASTStmtReader;
+ friend class ASTIdentifierIterator;
+ friend class ASTIdentifierLookupTrait;
+ friend class TypeLocReader;
+private:
+ /// \brief The receiver of some callbacks invoked by ASTReader.
+ llvm::OwningPtr<ASTReaderListener> Listener;
+
+ /// \brief The receiver of deserialization events.
+ ASTDeserializationListener *DeserializationListener;
+
+ SourceManager &SourceMgr;
+ FileManager &FileMgr;
+ Diagnostic &Diags;
+
+ /// \brief The semantic analysis object that will be processing the
+ /// AST files and the translation unit that uses it.
+ Sema *SemaObj;
+
+ /// \brief The preprocessor that will be loading the source file.
+ Preprocessor *PP;
+
+ /// \brief The AST context into which we'll read the AST files.
+ ASTContext *Context;
+
+ /// \brief The AST consumer.
+ ASTConsumer *Consumer;
+
+ /// \brief Information that is needed for every module.
+ struct PerFileData {
+ PerFileData(ASTFileType Ty);
+ ~PerFileData();
+
+ // === General information ===
+
+ /// \brief The type of this AST file.
+ ASTFileType Type;
+
+ /// \brief The file name of the AST file.
+ std::string FileName;
+
+ /// \brief The memory buffer that stores the data associated with
+ /// this AST file.
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+
+ /// \brief The size of this file, in bits.
+ uint64_t SizeInBits;
+
+ /// \brief The bitstream reader from which we'll read the AST file.
+ llvm::BitstreamReader StreamFile;
+
+ /// \brief The main bitstream cursor for the main block.
+ llvm::BitstreamCursor Stream;
+
+ // === Source Locations ===
+
+ /// \brief Cursor used to read source location entries.
+ llvm::BitstreamCursor SLocEntryCursor;
+
+ /// \brief The number of source location entries in this AST file.
+ unsigned LocalNumSLocEntries;
+
+ /// \brief Offsets for all of the source location entries in the
+ /// AST file.
+ const uint32_t *SLocOffsets;
+
+ /// \brief The entire size of this module's source location offset range.
+ unsigned LocalSLocSize;
+
+ // === Identifiers ===
+
+ /// \brief The number of identifiers in this AST file.
+ unsigned LocalNumIdentifiers;
+
+ /// \brief Offsets into the identifier table data.
+ ///
+ /// This array is indexed by the identifier ID (-1), and provides
+ /// the offset into IdentifierTableData where the string data is
+ /// stored.
+ const uint32_t *IdentifierOffsets;
+
+ /// \brief Actual data for the on-disk hash table of identifiers.
+ ///
+ /// This pointer points into a memory buffer, where the on-disk hash
+ /// table for identifiers actually lives.
+ const char *IdentifierTableData;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// IdentifierHashTable.
+ void *IdentifierLookupTable;
+
+ // === Macros ===
+
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
+
+ /// \brief The offset of the start of the set of defined macros.
+ uint64_t MacroStartOffset;
+
+ // === Detailed PreprocessingRecord ===
+
+ /// \brief The cursor to the start of the (optional) detailed preprocessing
+ /// record block.
+ llvm::BitstreamCursor PreprocessorDetailCursor;
+
+ /// \brief The offset of the start of the preprocessor detail cursor.
+ uint64_t PreprocessorDetailStartOffset;
+
+ /// \brief The number of macro definitions in this file.
+ unsigned LocalNumMacroDefinitions;
+
+ /// \brief Offsets of all of the macro definitions in the preprocessing
+ /// record in the AST file.
+ const uint32_t *MacroDefinitionOffsets;
+
+ // === Header search information ===
+
+ /// \brief The number of local HeaderFileInfo structures.
+ unsigned LocalNumHeaderFileInfos;
+
+ /// \brief Actual data for the on-disk hash table of header file
+ /// information.
+ ///
+ /// This pointer points into a memory buffer, where the on-disk hash
+ /// table for header file information actually lives.
+ const char *HeaderFileInfoTableData;
+
+ /// \brief The on-disk hash table that contains information about each of
+ /// the header files.
+ void *HeaderFileInfoTable;
+
+ // === Selectors ===
+
+ /// \brief The number of selectors new to this file.
+ ///
+ /// This is the number of entries in SelectorOffsets.
+ unsigned LocalNumSelectors;
+
+ /// \brief Offsets into the selector lookup table's data array
+ /// where each selector resides.
+ const uint32_t *SelectorOffsets;
+
+ /// \brief A pointer to the character data that comprises the selector table
+ ///
+ /// The SelectorOffsets table refers into this memory.
+ const unsigned char *SelectorLookupTableData;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// ASTSelectorLookupTable.
+ ///
+ /// This hash table provides the IDs of all selectors, and the associated
+ /// instance and factory methods.
+ void *SelectorLookupTable;
+
+ /// \brief Method selectors used in a @selector expression. Used for
+ /// implementation of -Wselector.
+ llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData;
+
+ // === Declarations ===
+
+ /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+ /// has read all the abbreviations at the start of the block and is ready to
+ /// jump around with these in context.
+ llvm::BitstreamCursor DeclsCursor;
+
+ /// \brief The number of declarations in this AST file.
+ unsigned LocalNumDecls;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID (-1).
+ const uint32_t *DeclOffsets;
+
+ /// \brief A snapshot of the pending instantiations in the chain.
+ ///
+ /// This record tracks the instantiations that Sema has to perform at the
+ /// end of the TU. It consists of a pair of values for every pending
+ /// instantiation where the first value is the ID of the decl and the second
+ /// is the instantiation location.
+ llvm::SmallVector<uint64_t, 64> PendingInstantiations;
+
+ /// \brief The number of C++ base specifier sets in this AST file.
+ unsigned LocalNumCXXBaseSpecifiers;
+
+ /// \brief Offset of each C++ base specifier set within the bitstream,
+ /// indexed by the C++ base specifier set ID (-1).
+ const uint32_t *CXXBaseSpecifiersOffsets;
+
+ // === Types ===
+
+ /// \brief The number of types in this AST file.
+ unsigned LocalNumTypes;
+
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ const uint32_t *TypeOffsets;
+
+ // === Miscellaneous ===
+
+ /// \brief The AST stat cache installed for this file, if any.
+ ///
+ /// The dynamic type of this stat cache is always ASTStatCache
+ void *StatCache;
+
+ /// \brief The number of preallocated preprocessing entities in the
+ /// preprocessing record.
+ unsigned NumPreallocatedPreprocessingEntities;
+
+ /// \brief The next module in source order.
+ PerFileData *NextInSource;
+
+ /// \brief All the modules that loaded this one. Can contain NULL for
+ /// directly loaded modules.
+ llvm::SmallVector<PerFileData *, 1> Loaders;
+ };
+
+ /// \brief All loaded modules, indexed by name.
+ llvm::StringMap<PerFileData*> Modules;
+
+ /// \brief The first module in source order.
+ PerFileData *FirstInSource;
+
+ /// \brief The chain of AST files. The first entry is the one named by the
+ /// user, the last one is the one that doesn't depend on anything further.
+ /// That is, the entry I was created with -include-pch I+1.
+ llvm::SmallVector<PerFileData*, 2> Chain;
+
+ /// \brief SLocEntries that we're going to preload.
+ llvm::SmallVector<uint64_t, 64> PreloadSLocEntries;
+
+ /// \brief Types that have already been loaded from the chain.
+ ///
+ /// When the pointer at index I is non-NULL, the type with
+ /// ID = (I + 1) << FastQual::Width has already been loaded
+ std::vector<QualType> TypesLoaded;
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ serialization::TypeIdxMap TypeIdxs;
+
+ /// \brief Declarations that have already been loaded from the chain.
+ ///
+ /// When the pointer at index I is non-NULL, the declaration with ID
+ /// = I + 1 has already been loaded.
+ std::vector<Decl *> DeclsLoaded;
+
+ typedef std::pair<PerFileData *, uint64_t> FileOffset;
+ typedef llvm::SmallVector<FileOffset, 2> FileOffsetsTy;
+ typedef llvm::DenseMap<serialization::DeclID, FileOffsetsTy>
+ DeclUpdateOffsetsMap;
+ /// \brief Declarations that have modifications residing in a later file
+ /// in the chain.
+ DeclUpdateOffsetsMap DeclUpdateOffsets;
+
+ typedef llvm::DenseMap<serialization::DeclID,
+ std::pair<PerFileData *, uint64_t> >
+ DeclReplacementMap;
+ /// \brief Declarations that have been replaced in a later file in the chain.
+ DeclReplacementMap ReplacedDecls;
+
+ /// \brief Information about the contents of a DeclContext.
+ struct DeclContextInfo {
+ void *NameLookupTableData; // a ASTDeclContextNameLookupTable.
+ const serialization::KindDeclIDPair *LexicalDecls;
+ unsigned NumLexicalDecls;
+ };
+ // In a full chain, there could be multiple updates to every decl context,
+ // so this is a vector. However, typically a chain is only two elements long,
+ // with only one file containing updates, so there will be only one update
+ // per decl context.
+ typedef llvm::SmallVector<DeclContextInfo, 1> DeclContextInfos;
+ typedef llvm::DenseMap<const DeclContext *, DeclContextInfos>
+ DeclContextOffsetsMap;
+ // Updates for visible decls can occur for other contexts than just the
+ // TU, and when we read those update records, the actual context will not
+ // be available yet (unless it's the TU), so have this pending map using the
+ // ID as a key. It will be realized when the context is actually loaded.
+ typedef llvm::SmallVector<void *, 1> DeclContextVisibleUpdates;
+ typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
+ DeclContextVisibleUpdatesPending;
+
+ /// \brief Offsets of the lexical and visible declarations for each
+ /// DeclContext.
+ DeclContextOffsetsMap DeclContextOffsets;
+
+ /// \brief Updates to the visible declarations of declaration contexts that
+ /// haven't been loaded yet.
+ DeclContextVisibleUpdatesPending PendingVisibleUpdates;
+
+ typedef llvm::SmallVector<CXXRecordDecl *, 4> ForwardRefs;
+ typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs>
+ PendingForwardRefsMap;
+ /// \brief Forward references that have a definition but the definition decl
+ /// is still initializing. When the definition gets read it will update
+ /// the DefinitionData pointer of all pending references.
+ PendingForwardRefsMap PendingForwardRefs;
+
+ typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
+ FirstLatestDeclIDMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another AST file.
+ FirstLatestDeclIDMap FirstLatestDeclIDs;
+
+ /// \brief Read the records that describe the contents of declcontexts.
+ bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info);
+
+ /// \brief A vector containing identifiers that have already been
+ /// loaded.
+ ///
+ /// If the pointer at index I is non-NULL, then it refers to the
+ /// IdentifierInfo for the identifier with ID=I+1 that has already
+ /// been loaded.
+ std::vector<IdentifierInfo *> IdentifiersLoaded;
+
+ /// \brief A vector containing selectors that have already been loaded.
+ ///
+ /// This vector is indexed by the Selector ID (-1). NULL selector
+ /// entries indicate that the particular selector ID has not yet
+ /// been loaded.
+ llvm::SmallVector<Selector, 16> SelectorsLoaded;
+
+ /// \brief The macro definitions we have already loaded.
+ llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
+
+ /// \brief Mapping from identifiers that represent macros whose definitions
+ /// have not yet been deserialized to the global offset where the macro
+ /// record resides.
+ llvm::DenseMap<IdentifierInfo *, uint64_t> UnreadMacroRecordOffsets;
+
+ /// \name CodeGen-relevant special data
+ /// \brief Fields containing data that is relevant to CodeGen.
+ //@{
+
+ /// \brief The IDs of all declarations that fulfill the criteria of
+ /// "interesting" decls.
+ ///
+ /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the
+ /// chain. The referenced declarations are deserialized and passed to the
+ /// consumer eagerly.
+ llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+
+ /// \brief The IDs of all tentative definitions stored in the the chain.
+ ///
+ /// Sema keeps track of all tentative definitions in a TU because it has to
+ /// complete them and pass them on to CodeGen. Thus, tentative definitions in
+ /// the PCH chain must be eagerly deserialized.
+ llvm::SmallVector<uint64_t, 16> TentativeDefinitions;
+
+ /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are
+ /// used.
+ ///
+ /// CodeGen has to emit VTables for these records, so they have to be eagerly
+ /// deserialized.
+ llvm::SmallVector<uint64_t, 64> VTableUses;
+
+ //@}
+
+ /// \name Diagnostic-relevant special data
+ /// \brief Fields containing data that is used for generating diagnostics
+ //@{
+
+ /// \brief A snapshot of Sema's unused file-scoped variable tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
+
+ /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;
+
+ /// \brief The IDs of type aliases for ext_vectors that exist in the chain.
+ ///
+ /// Used by Sema for finding sugared names for ext_vectors in diagnostics.
+ llvm::SmallVector<uint64_t, 4> ExtVectorDecls;
+
+ //@}
+
+ /// \name Sema-relevant special data
+ /// \brief Fields containing data that is used for semantic analysis
+ //@{
+
+ /// \brief The IDs of all locally scoped external decls in the chain.
+ ///
+ /// Sema tracks these to validate that the types are consistent across all
+ /// local external declarations.
+ llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+
+ /// \brief The IDs of all dynamic class declarations in the chain.
+ ///
+ /// Sema tracks these because it checks for the key functions being defined
+ /// at the end of the TU, in which case it directs CodeGen to emit the VTable.
+ llvm::SmallVector<uint64_t, 16> DynamicClasses;
+
+ /// \brief The IDs of the declarations Sema stores directly.
+ ///
+ /// Sema tracks a few important decls, such as namespace std, directly.
+ llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
+
+ /// \brief The IDs of the types ASTContext stores directly.
+ ///
+ /// The AST context tracks a few important types, such as va_list, directly.
+ llvm::SmallVector<uint64_t, 16> SpecialTypes;
+
+ /// \brief The IDs of CUDA-specific declarations ASTContext stores directly.
+ ///
+ /// The AST context tracks a few important decls, currently cudaConfigureCall,
+ /// directly.
+ llvm::SmallVector<uint64_t, 2> CUDASpecialDeclRefs;
+
+ /// \brief The floating point pragma option settings.
+ llvm::SmallVector<uint64_t, 1> FPPragmaOptions;
+
+ /// \brief The OpenCL extension settings.
+ llvm::SmallVector<uint64_t, 1> OpenCLExtensions;
+
+ //@}
+
+ /// \brief Diagnostic IDs and their mappings that the user changed.
+ llvm::SmallVector<uint64_t, 8> PragmaDiagMappings;
+
+ /// \brief The original file name that was used to build the primary AST file,
+ /// which may have been modified for relocatable-pch support.
+ std::string OriginalFileName;
+
+ /// \brief The actual original file name that was used to build the primary
+ /// AST file.
+ std::string ActualOriginalFileName;
+
+ /// \brief The directory that the PCH was originally created in. Used to
+ /// allow resolving headers even after headers+PCH was moved to a new path.
+ std::string OriginalDir;
+
+ /// \brief The directory that the PCH we are reading is stored in.
+ std::string CurrentDir;
+
+ /// \brief Whether this precompiled header is a relocatable PCH file.
+ bool RelocatablePCH;
+
+ /// \brief The system include root to be used when loading the
+ /// precompiled header.
+ const char *isysroot;
+
+ /// \brief Whether to disable the normal validation performed on precompiled
+ /// headers when they are loaded.
+ bool DisableValidation;
+
+ /// \brief Whether to disable the use of stat caches in AST files.
+ bool DisableStatCache;
+
+ /// \brief Mapping from switch-case IDs in the chain to switch-case statements
+ ///
+ /// Statements usually don't have IDs, but switch cases need them, so that the
+ /// switch statement can refer to them.
+ std::map<unsigned, SwitchCase *> SwitchCaseStmts;
+
+ /// \brief Mapping from opaque value IDs to OpaqueValueExprs.
+ std::map<unsigned, OpaqueValueExpr*> OpaqueValueExprs;
+
+ /// \brief The number of stat() calls that hit/missed the stat
+ /// cache.
+ unsigned NumStatHits, NumStatMisses;
+
+ /// \brief The number of source location entries de-serialized from
+ /// the PCH file.
+ unsigned NumSLocEntriesRead;
+
+ /// \brief The number of source location entries in the chain.
+ unsigned TotalNumSLocEntries;
+
+ /// \brief The next offset for a SLocEntry after everything in this reader.
+ unsigned NextSLocOffset;
+
+ /// \brief The number of statements (and expressions) de-serialized
+ /// from the chain.
+ unsigned NumStatementsRead;
+
+ /// \brief The total number of statements (and expressions) stored
+ /// in the chain.
+ unsigned TotalNumStatements;
+
+ /// \brief The number of macros de-serialized from the chain.
+ unsigned NumMacrosRead;
+
+ /// \brief The total number of macros stored in the chain.
+ unsigned TotalNumMacros;
+
+ /// \brief The number of selectors that have been read.
+ unsigned NumSelectorsRead;
+
+ /// \brief The number of method pool entries that have been read.
+ unsigned NumMethodPoolEntriesRead;
+
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool and not found anything interesting.
+ unsigned NumMethodPoolMisses;
+
+ /// \brief The total number of method pool entries in the selector table.
+ unsigned TotalNumMethodPoolEntries;
+
+ /// Number of lexical decl contexts read/total.
+ unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts;
+
+ /// Number of visible decl contexts read/total.
+ unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts;
+
+ /// \brief Number of Decl/types that are currently deserializing.
+ unsigned NumCurrentElementsDeserializing;
+
+ /// \brief An IdentifierInfo that has been loaded but whose top-level
+ /// declarations of the same name have not (yet) been loaded.
+ struct PendingIdentifierInfo {
+ IdentifierInfo *II;
+ llvm::SmallVector<uint32_t, 4> DeclIDs;
+ };
+
+ /// \brief The set of identifiers that were read while the AST reader was
+ /// (recursively) loading declarations.
+ ///
+ /// The declarations on the identifier chain for these identifiers will be
+ /// loaded once the recursive loading has completed.
+ std::deque<PendingIdentifierInfo> PendingIdentifierInfos;
+
+ /// \brief Contains declarations and definitions that will be
+ /// "interesting" to the ASTConsumer, when we get that AST consumer.
+ ///
+ /// "Interesting" declarations are those that have data that may
+ /// need to be emitted, such as inline function definitions or
+ /// Objective-C protocols.
+ std::deque<Decl *> InterestingDecls;
+
+ /// \brief We delay loading of the previous declaration chain to avoid
+ /// deeply nested calls when there are many redeclarations.
+ std::deque<std::pair<Decl *, serialization::DeclID> > PendingPreviousDecls;
+
+ /// \brief Ready to load the previous declaration of the given Decl.
+ void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID);
+
+ /// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
+ llvm::SmallVector<Stmt *, 16> StmtStack;
+
+ /// \brief What kind of records we are reading.
+ enum ReadingKind {
+ Read_Decl, Read_Type, Read_Stmt
+ };
+
+ /// \brief What kind of records we are reading.
+ ReadingKind ReadingKind;
+
+ /// \brief RAII object to change the reading kind.
+ class ReadingKindTracker {
+ ASTReader &Reader;
+ enum ReadingKind PrevKind;
+
+ ReadingKindTracker(const ReadingKindTracker&); // do not implement
+ ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement
+
+ public:
+ ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
+ : Reader(reader), PrevKind(Reader.ReadingKind) {
+ Reader.ReadingKind = newKind;
+ }
+
+ ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
+ };
+
+ /// \brief All predefines buffers in the chain, to be treated as if
+ /// concatenated.
+ PCHPredefinesBlocks PCHPredefinesBuffers;
+
+ /// \brief Suggested contents of the predefines buffer, after this
+ /// PCH file has been processed.
+ ///
+ /// In most cases, this string will be empty, because the predefines
+ /// buffer computed to build the PCH file will be identical to the
+ /// predefines buffer computed from the command line. However, when
+ /// there are differences that the PCH reader can work around, this
+ /// predefines buffer may contain additional definitions.
+ std::string SuggestedPredefines;
+
+ /// \brief Reads a statement from the specified cursor.
+ Stmt *ReadStmtFromStream(PerFileData &F);
+
+ void MaybeAddSystemRootToFilename(std::string &Filename);
+
+ ASTReadResult ReadASTCore(llvm::StringRef FileName, ASTFileType Type);
+ ASTReadResult ReadASTBlock(PerFileData &F);
+ bool CheckPredefinesBuffers();
+ bool ParseLineTable(PerFileData &F, llvm::SmallVectorImpl<uint64_t> &Record);
+ ASTReadResult ReadSourceManagerBlock(PerFileData &F);
+ ASTReadResult ReadSLocEntryRecord(unsigned ID);
+ PerFileData *SLocCursorForID(unsigned ID);
+ SourceLocation getImportLocation(PerFileData *F);
+ bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
+
+ struct RecordLocation {
+ RecordLocation(PerFileData *M, uint64_t O)
+ : F(M), Offset(O) {}
+ PerFileData *F;
+ uint64_t Offset;
+ };
+
+ QualType ReadTypeRecord(unsigned Index);
+ RecordLocation TypeCursorForIndex(unsigned Index);
+ void LoadedDecl(unsigned Index, Decl *D);
+ Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
+ RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
+
+ void PassInterestingDeclsToConsumer();
+
+ /// \brief Produce an error diagnostic and return true.
+ ///
+ /// This routine should only be used for fatal errors that have to
+ /// do with non-routine failures (e.g., corrupted AST file).
+ void Error(const char *Msg);
+
+ ASTReader(const ASTReader&); // do not implement
+ ASTReader &operator=(const ASTReader &); // do not implement
+public:
+ typedef llvm::SmallVector<uint64_t, 64> RecordData;
+
+ /// \brief Load the AST file and validate its contents against the given
+ /// Preprocessor.
+ ///
+ /// \param PP the preprocessor associated with the context in which this
+ /// precompiled header will be loaded.
+ ///
+ /// \param Context the AST context that this precompiled header will be
+ /// loaded into.
+ ///
+ /// \param isysroot If non-NULL, the system include path specified by the
+ /// user. This is only used with relocatable PCH files. If non-NULL,
+ /// a relocatable PCH file will use the default path "/".
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ///
+ /// \param DisableStatCache If true, the AST reader will ignore the
+ /// stat cache in the AST files. This performance pessimization can
+ /// help when an AST file is being used in cases where the
+ /// underlying files in the file system may have changed, but
+ /// parsing should still continue.
+ ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
+ bool DisableValidation = false, bool DisableStatCache = false);
+
+ /// \brief Load the AST file without using any pre-initialized Preprocessor.
+ ///
+ /// The necessary information to initialize a Preprocessor later can be
+ /// obtained by setting a ASTReaderListener.
+ ///
+ /// \param SourceMgr the source manager into which the AST file will be loaded
+ ///
+ /// \param FileMgr the file manager into which the AST file will be loaded.
+ ///
+ /// \param Diags the diagnostics system to use for reporting errors and
+ /// warnings relevant to loading the AST file.
+ ///
+ /// \param isysroot If non-NULL, the system include path specified by the
+ /// user. This is only used with relocatable PCH files. If non-NULL,
+ /// a relocatable PCH file will use the default path "/".
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ///
+ /// \param DisableStatCache If true, the AST reader will ignore the
+ /// stat cache in the AST files. This performance pessimization can
+ /// help when an AST file is being used in cases where the
+ /// underlying files in the file system may have changed, but
+ /// parsing should still continue.
+ ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags, const char *isysroot = 0,
+ bool DisableValidation = false, bool DisableStatCache = false);
+ ~ASTReader();
+
+ /// \brief Load the precompiled header designated by the given file
+ /// name.
+ ASTReadResult ReadAST(const std::string &FileName, ASTFileType Type);
+
+ /// \brief Set the AST callbacks listener.
+ void setListener(ASTReaderListener *listener) {
+ Listener.reset(listener);
+ }
+
+ /// \brief Set the AST deserialization listener.
+ void setDeserializationListener(ASTDeserializationListener *Listener);
+
+ /// \brief Set the Preprocessor to use.
+ void setPreprocessor(Preprocessor &pp);
+
+ /// \brief Sets and initializes the given Context.
+ void InitializeContext(ASTContext &Context);
+
+ /// \brief Retrieve the name of the named (primary) AST file
+ const std::string &getFileName() const { return Chain[0]->FileName; }
+
+ /// \brief Retrieve the name of the original source file name
+ const std::string &getOriginalSourceFile() { return OriginalFileName; }
+
+ /// \brief Retrieve the name of the original source file name directly from
+ /// the AST file, without actually loading the AST file.
+ static std::string getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
+ Diagnostic &Diags);
+
+ /// \brief Returns the suggested contents of the predefines buffer,
+ /// which contains a (typically-empty) subset of the predefines
+ /// build prior to including the precompiled header.
+ const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
+
+ /// \brief Read preprocessed entities into the preprocessing record.
+ virtual void ReadPreprocessedEntities();
+
+ /// \brief Read the preprocessed entity at the given offset.
+ virtual PreprocessedEntity *ReadPreprocessedEntityAtOffset(uint64_t Offset);
+
+ /// \brief Read the header file information for the given file entry.
+ virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE);
+
+ void ReadPragmaDiagnosticMappings(Diagnostic &Diag);
+
+ /// \brief Returns the number of source locations found in the chain.
+ unsigned getTotalNumSLocs() const {
+ return TotalNumSLocEntries;
+ }
+
+ /// \brief Returns the next SLocEntry offset after the chain.
+ unsigned getNextSLocOffset() const {
+ return NextSLocOffset;
+ }
+
+ /// \brief Returns the number of identifiers found in the chain.
+ unsigned getTotalNumIdentifiers() const {
+ return static_cast<unsigned>(IdentifiersLoaded.size());
+ }
+
+ /// \brief Returns the number of types found in the chain.
+ unsigned getTotalNumTypes() const {
+ return static_cast<unsigned>(TypesLoaded.size());
+ }
+
+ /// \brief Returns the number of declarations found in the chain.
+ unsigned getTotalNumDecls() const {
+ return static_cast<unsigned>(DeclsLoaded.size());
+ }
+
+ /// \brief Returns the number of selectors found in the chain.
+ unsigned getTotalNumSelectors() const {
+ return static_cast<unsigned>(SelectorsLoaded.size());
+ }
+
+ /// \brief Returns the number of macro definitions found in the chain.
+ unsigned getTotalNumMacroDefinitions() const {
+ return static_cast<unsigned>(MacroDefinitionsLoaded.size());
+ }
+
+ /// \brief Returns the number of C++ base specifiers found in the chain.
+ unsigned getTotalNumCXXBaseSpecifiers() const;
+
+ /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// given TemplateArgument kind.
+ TemplateArgumentLocInfo
+ GetTemplateArgumentLocInfo(PerFileData &F, TemplateArgument::ArgKind Kind,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads a TemplateArgumentLoc.
+ TemplateArgumentLoc
+ ReadTemplateArgumentLoc(PerFileData &F,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads a declarator info from the given record.
+ TypeSourceInfo *GetTypeSourceInfo(PerFileData &F,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Resolve and return the translation unit declaration.
+ TranslationUnitDecl *GetTranslationUnitDecl();
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ QualType GetType(serialization::TypeID ID);
+
+ /// \brief Returns the type ID associated with the given type.
+ /// If the type didn't come from the AST file the ID that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeID GetTypeID(QualType T) const;
+
+ /// \brief Returns the type index associated with the given type.
+ /// If the type didn't come from the AST file the index that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeIdx GetTypeIdx(QualType T) const;
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ Decl *GetDecl(serialization::DeclID ID);
+ virtual Decl *GetExternalDecl(uint32_t ID);
+
+ /// \brief Resolve a CXXBaseSpecifiers ID into an offset into the chain
+ /// of loaded AST files.
+ uint64_t GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID);
+
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+
+ /// \brief Resolve the offset of a statement into a statement.
+ ///
+ /// This operation will read a new statement from the external
+ /// source each time it is called, and is meant to be used via a
+ /// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+ virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
+
+ /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+ /// specified cursor. Read the abbreviations that are at the top of the block
+ /// and then leave the cursor pointing into the block.
+ bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID);
+
+ /// \brief Finds all the visible declarations with a given name.
+ /// The current implementation of this method just loads the entire
+ /// lookup table as unmaterialized references.
+ virtual DeclContext::lookup_result
+ FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name);
+
+ virtual void MaterializeVisibleDecls(const DeclContext *DC);
+
+ /// \brief Read all of the declarations lexically stored in a
+ /// declaration context.
+ ///
+ /// \param DC The declaration context whose declarations will be
+ /// read.
+ ///
+ /// \param Decls Vector that will contain the declarations loaded
+ /// from the external source. The caller is responsible for merging
+ /// these declarations with any declarations already stored in the
+ /// declaration context.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ llvm::SmallVectorImpl<Decl*> &Decls);
+
+ /// \brief Notify ASTReader that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; }
+
+ /// \brief Notify ASTReader that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ virtual void FinishedDeserializing();
+
+ /// \brief Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ ///
+ /// This function will provide all of the external definitions to
+ /// the ASTConsumer.
+ virtual void StartTranslationUnit(ASTConsumer *Consumer);
+
+ /// \brief Print some statistics about AST usage.
+ virtual void PrintStats();
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S);
+
+ /// \brief Inform the semantic consumer that Sema is no longer available.
+ virtual void ForgetSema() { SemaObj = 0; }
+
+ /// \brief Retrieve the IdentifierInfo for the named identifier.
+ ///
+ /// This routine builds a new IdentifierInfo for the given identifier. If any
+ /// declarations with this name are visible from translation unit scope, their
+ /// declarations will be deserialized and introduced into the declaration
+ /// chain of the identifier.
+ virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd);
+ IdentifierInfo *get(llvm::StringRef Name) {
+ return get(Name.begin(), Name.end());
+ }
+
+ /// \brief Retrieve an iterator into the set of all identifiers
+ /// in all loaded AST files.
+ virtual IdentifierIterator *getIdentifiers() const;
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ ///
+ /// \returns a pair of Objective-C methods lists containing the
+ /// instance and factory methods, respectively, with this selector.
+ virtual std::pair<ObjCMethodList, ObjCMethodList>
+ ReadMethodPool(Selector Sel);
+
+ /// \brief Load a selector from disk, registering its ID if it exists.
+ void LoadSelector(Selector Sel);
+
+ void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
+ void SetGloballyVisibleDecls(IdentifierInfo *II,
+ const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
+ bool Nonrecursive = false);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(unsigned DiagID);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ IdentifierInfo *DecodeIdentifierInfo(unsigned Idx);
+
+ IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx) {
+ return DecodeIdentifierInfo(Record[Idx++]);
+ }
+
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) {
+ return DecodeIdentifierInfo(ID);
+ }
+
+ /// \brief Read the source location entry with index ID.
+ virtual void ReadSLocEntry(unsigned ID);
+
+ Selector DecodeSelector(unsigned Idx);
+
+ virtual Selector GetExternalSelector(uint32_t ID);
+ uint32_t GetNumExternalSelectors();
+
+ Selector GetSelector(const RecordData &Record, unsigned &Idx) {
+ return DecodeSelector(Record[Idx++]);
+ }
+
+ /// \brief Read a declaration name.
+ DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameLoc(PerFileData &F,
+ DeclarationNameLoc &DNLoc, DeclarationName Name,
+ const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameInfo(PerFileData &F, DeclarationNameInfo &NameInfo,
+ const RecordData &Record, unsigned &Idx);
+
+ void ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
+ const RecordData &Record, unsigned &Idx);
+
+ NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template name.
+ TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template argument.
+ TemplateArgument ReadTemplateArgument(PerFileData &F,
+ const RecordData &Record,unsigned &Idx);
+
+ /// \brief Read a template parameter list.
+ TemplateParameterList *ReadTemplateParameterList(PerFileData &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template argument array.
+ void
+ ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
+ PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a UnresolvedSet structure.
+ void ReadUnresolvedSet(UnresolvedSetImpl &Set,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a C++ base specifier.
+ CXXBaseSpecifier ReadCXXBaseSpecifier(PerFileData &F,
+ const RecordData &Record,unsigned &Idx);
+
+ /// \brief Read a CXXCtorInitializer array.
+ std::pair<CXXCtorInitializer **, unsigned>
+ ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a source location from raw form.
+ SourceLocation ReadSourceLocation(PerFileData &Module, unsigned Raw) {
+ (void)Module; // No remapping yet
+ return SourceLocation::getFromRawEncoding(Raw);
+ }
+
+ /// \brief Read a source location.
+ SourceLocation ReadSourceLocation(PerFileData &Module,
+ const RecordData &Record, unsigned& Idx) {
+ return ReadSourceLocation(Module, Record[Idx++]);
+ }
+
+ /// \brief Read a source range.
+ SourceRange ReadSourceRange(PerFileData &F,
+ const RecordData &Record, unsigned& Idx);
+
+ /// \brief Read an integral value
+ llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a signed integral value
+ llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a floating-point value
+ llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx);
+
+ // \brief Read a string
+ std::string ReadString(const RecordData &Record, unsigned &Idx);
+
+ CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads attributes from the current stream position.
+ void ReadAttributes(PerFileData &F, AttrVec &Attrs,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads a statement.
+ Stmt *ReadStmt(PerFileData &F);
+
+ /// \brief Reads an expression.
+ Expr *ReadExpr(PerFileData &F);
+
+ /// \brief Reads a sub-statement operand during statement reading.
+ Stmt *ReadSubStmt() {
+ assert(ReadingKind == Read_Stmt &&
+ "Should be called only during statement reading!");
+ // Subexpressions are stored from last to first, so the next Stmt we need
+ // is at the back of the stack.
+ assert(!StmtStack.empty() && "Read too many sub statements!");
+ return StmtStack.pop_back_val();
+ }
+
+ /// \brief Reads a sub-expression operand during statement reading.
+ Expr *ReadSubExpr();
+
+ /// \brief Reads the macro record located at the given offset.
+ PreprocessedEntity *ReadMacroRecord(PerFileData &F, uint64_t Offset);
+
+ /// \brief Reads the preprocessed entity located at the current stream
+ /// position.
+ PreprocessedEntity *LoadPreprocessedEntity(PerFileData &F);
+
+ /// \brief Note that the identifier is a macro whose record will be loaded
+ /// from the given AST file at the given (file-local) offset.
+ void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
+ uint64_t Offset);
+
+ /// \brief Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros();
+
+ /// \brief Read the macro definition for this identifier.
+ virtual void LoadMacroDefinition(IdentifierInfo *II);
+
+ /// \brief Read the macro definition corresponding to this iterator
+ /// into the unread macro record offsets table.
+ void LoadMacroDefinition(
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos);
+
+ /// \brief Retrieve the macro definition with the given ID.
+ MacroDefinition *getMacroDefinition(serialization::MacroID ID);
+
+ /// \brief Retrieve the AST context that this AST reader supplements.
+ ASTContext *getContext() { return Context; }
+
+ // \brief Contains declarations that were loaded before we have
+ // access to a Sema object.
+ llvm::SmallVector<NamedDecl *, 16> PreloadedDecls;
+
+ /// \brief Retrieve the semantic analysis object used to analyze the
+ /// translation unit in which the precompiled header is being
+ /// imported.
+ Sema *getSema() { return SemaObj; }
+
+ /// \brief Retrieve the identifier table associated with the
+ /// preprocessor.
+ IdentifierTable &getIdentifierTable();
+
+ /// \brief Record that the given ID maps to the given switch-case
+ /// statement.
+ void RecordSwitchCaseID(SwitchCase *SC, unsigned ID);
+
+ /// \brief Retrieve the switch-case statement with the given ID.
+ SwitchCase *getSwitchCaseWithID(unsigned ID);
+
+ void ClearSwitchCaseIDs();
+};
+
+/// \brief Helper class that saves the current stream position and
+/// then restores it when destroyed.
+struct SavedStreamPosition {
+ explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor)
+ : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { }
+
+ ~SavedStreamPosition() {
+ Cursor.JumpToBit(Offset);
+ }
+
+private:
+ llvm::BitstreamCursor &Cursor;
+ uint64_t Offset;
+};
+
+inline void PCHValidator::Error(const char *Msg) {
+ Reader.Error(Msg);
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTSerializationListener.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTSerializationListener.h
new file mode 100644
index 0000000..0c62e0b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTSerializationListener.h
@@ -0,0 +1,44 @@
+//===- ASTSerializationListener.h - Decl/Type PCH Write Events -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTSerializationListener class, which is notified
+// by the ASTWriter when an entity is serialized.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_AST_SERIALIZATION_LISTENER_H
+#define LLVM_CLANG_FRONTEND_AST_SERIALIZATION_LISTENER_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+class PreprocessedEntity;
+
+/// \brief Listener object that receives callbacks when certain kinds of
+/// entities are serialized.
+class ASTSerializationListener {
+public:
+ virtual ~ASTSerializationListener();
+
+ /// \brief Callback invoked whenever a preprocessed entity is serialized.
+ ///
+ /// This callback will only occur when the translation unit was created with
+ /// a detailed preprocessing record.
+ ///
+ /// \param Entity The entity that has been serialized.
+ ///
+ /// \param Offset The offset (in bits) of this entity in the resulting
+ /// AST file.
+ virtual void SerializedPreprocessedEntity(PreprocessedEntity *Entity,
+ uint64_t Offset) = 0;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
new file mode 100644
index 0000000..beb4936
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -0,0 +1,609 @@
+//===--- ASTWriter.h - AST File Writer --------------------------*- 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 ASTWriter class, which writes an AST file
+// containing a serialized representation of a translation unit.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H
+#define LLVM_CLANG_FRONTEND_AST_WRITER_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include <map>
+#include <queue>
+#include <vector>
+
+namespace llvm {
+ class APFloat;
+ class APInt;
+ class BitstreamWriter;
+}
+
+namespace clang {
+
+class ASTContext;
+class ASTSerializationListener;
+class NestedNameSpecifier;
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class FPOptions;
+class HeaderSearch;
+class MacroDefinition;
+class MemorizeStatCalls;
+class OpaqueValueExpr;
+class OpenCLOptions;
+class ASTReader;
+class PreprocessedEntity;
+class PreprocessingRecord;
+class Preprocessor;
+class Sema;
+class SourceManager;
+class SwitchCase;
+class TargetInfo;
+
+/// \brief Writes an AST file containing the contents of a translation unit.
+///
+/// The ASTWriter class produces a bitstream containing the serialized
+/// representation of a given abstract syntax tree and its supporting
+/// data structures. This bitstream can be de-serialized via an
+/// instance of the ASTReader class.
+class ASTWriter : public ASTDeserializationListener,
+ public ASTMutationListener {
+public:
+ typedef llvm::SmallVector<uint64_t, 64> RecordData;
+ typedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl;
+
+ friend class ASTDeclWriter;
+private:
+ /// \brief The bitstream writer used to emit this precompiled header.
+ llvm::BitstreamWriter &Stream;
+
+ /// \brief The reader of existing AST files, if we're chaining.
+ ASTReader *Chain;
+
+ /// \brief A listener object that receives notifications when certain
+ /// entities are serialized.
+ ASTSerializationListener *SerializationListener;
+
+ /// \brief Stores a declaration or a type to be written to the AST file.
+ class DeclOrType {
+ public:
+ DeclOrType(Decl *D) : Stored(D), IsType(false) { }
+ DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { }
+
+ bool isType() const { return IsType; }
+ bool isDecl() const { return !IsType; }
+
+ QualType getType() const {
+ assert(isType() && "Not a type!");
+ return QualType::getFromOpaquePtr(Stored);
+ }
+
+ Decl *getDecl() const {
+ assert(isDecl() && "Not a decl!");
+ return static_cast<Decl *>(Stored);
+ }
+
+ private:
+ void *Stored;
+ bool IsType;
+ };
+
+ /// \brief The declarations and types to emit.
+ std::queue<DeclOrType> DeclTypesToEmit;
+
+ /// \brief The first ID number we can use for our own declarations.
+ serialization::DeclID FirstDeclID;
+
+ /// \brief The decl ID that will be assigned to the next new decl.
+ serialization::DeclID NextDeclID;
+
+ /// \brief Map that provides the ID numbers of each declaration within
+ /// the output stream, as well as those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery) and start at 2. 1 is reserved for the translation
+ /// unit, while 0 is reserved for NULL.
+ llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs;
+
+ /// \brief Offset of each declaration in the bitstream, indexed by
+ /// the declaration's ID.
+ std::vector<uint32_t> DeclOffsets;
+
+ /// \brief The first ID number we can use for our own types.
+ serialization::TypeID FirstTypeID;
+
+ /// \brief The type ID that will be assigned to the next new type.
+ serialization::TypeID NextTypeID;
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ serialization::TypeIdxMap TypeIdxs;
+
+ /// \brief Offset of each type in the bitstream, indexed by
+ /// the type's ID.
+ std::vector<uint32_t> TypeOffsets;
+
+ /// \brief The first ID number we can use for our own identifiers.
+ serialization::IdentID FirstIdentID;
+
+ /// \brief The identifier ID that will be assigned to the next new identifier.
+ serialization::IdentID NextIdentID;
+
+ /// \brief Map that provides the ID numbers of each identifier in
+ /// the output stream.
+ ///
+ /// The ID numbers for identifiers are consecutive (in order of
+ /// discovery), starting at 1. An ID of zero refers to a NULL
+ /// IdentifierInfo.
+ llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
+
+ /// \brief Offsets of each of the identifier IDs into the identifier
+ /// table.
+ std::vector<uint32_t> IdentifierOffsets;
+
+ /// \brief The first ID number we can use for our own selectors.
+ serialization::SelectorID FirstSelectorID;
+
+ /// \brief The selector ID that will be assigned to the next new identifier.
+ serialization::SelectorID NextSelectorID;
+
+ /// \brief Map that provides the ID numbers of each Selector.
+ llvm::DenseMap<Selector, serialization::SelectorID> SelectorIDs;
+
+ /// \brief Offset of each selector within the method pool/selector
+ /// table, indexed by the Selector ID (-1).
+ std::vector<uint32_t> SelectorOffsets;
+
+ /// \brief Offsets of each of the macro identifiers into the
+ /// bitstream.
+ ///
+ /// For each identifier that is associated with a macro, this map
+ /// provides the offset into the bitstream where that macro is
+ /// defined.
+ llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
+
+ /// \brief The set of identifiers that had macro definitions at some point.
+ std::vector<const IdentifierInfo *> DeserializedMacroNames;
+
+ /// \brief The first ID number we can use for our own macro definitions.
+ serialization::MacroID FirstMacroID;
+
+ /// \brief The decl ID that will be assigned to the next new macro definition.
+ serialization::MacroID NextMacroID;
+
+ /// \brief Mapping from macro definitions (as they occur in the preprocessing
+ /// record) to the macro IDs.
+ llvm::DenseMap<const MacroDefinition *, serialization::MacroID>
+ MacroDefinitions;
+
+ /// \brief Mapping from the macro definition indices in \c MacroDefinitions
+ /// to the corresponding offsets within the preprocessor block.
+ std::vector<uint32_t> MacroDefinitionOffsets;
+
+ typedef llvm::SmallVector<uint64_t, 2> UpdateRecord;
+ typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap;
+ /// \brief Mapping from declarations that came from a chained PCH to the
+ /// record containing modifications to them.
+ DeclUpdateMap DeclUpdates;
+
+ typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another PCH.
+ FirstLatestDeclMap FirstLatestDecls;
+
+ /// \brief Declarations encountered that might be external
+ /// definitions.
+ ///
+ /// We keep track of external definitions (as well as tentative
+ /// definitions) as we are emitting declarations to the AST
+ /// file. The AST file contains a separate record for these external
+ /// definitions, which are provided to the AST consumer by the AST
+ /// reader. This is behavior is required to properly cope with,
+ /// e.g., tentative variable definitions that occur within
+ /// headers. The declarations themselves are stored as declaration
+ /// IDs, since they will be written out to an EXTERNAL_DEFINITIONS
+ /// record.
+ llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+
+ /// \brief DeclContexts that have received extensions since their serialized
+ /// form.
+ ///
+ /// For namespaces, when we're chaining and encountering a namespace, we check if
+ /// its primary namespace comes from the chain. If it does, we add the primary
+ /// to this set, so that we can write out lexical content updates for it.
+ llvm::SmallPtrSet<const DeclContext *, 16> UpdatedDeclContexts;
+
+ typedef llvm::SmallPtrSet<const Decl *, 16> DeclsToRewriteTy;
+ /// \brief Decls that will be replaced in the current dependent AST file.
+ DeclsToRewriteTy DeclsToRewrite;
+
+ /// \brief Decls that have been replaced in the current dependent AST file.
+ ///
+ /// When a decl changes fundamentally after being deserialized (this shouldn't
+ /// happen, but the ObjC AST nodes are designed this way), it will be
+ /// serialized again. In this case, it is registered here, so that the reader
+ /// knows to read the updated version.
+ llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16>
+ ReplacedDecls;
+
+ /// \brief Statements that we've encountered while serializing a
+ /// declaration or type.
+ llvm::SmallVector<Stmt *, 16> StmtsToEmit;
+
+ /// \brief Statements collection to use for ASTWriter::AddStmt().
+ /// It will point to StmtsToEmit unless it is overriden.
+ llvm::SmallVector<Stmt *, 16> *CollectedStmts;
+
+ /// \brief Mapping from SwitchCase statements to IDs.
+ std::map<SwitchCase *, unsigned> SwitchCaseIDs;
+
+ /// \brief Mapping from OpaqueValueExpr expressions to IDs.
+ llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues;
+
+ /// \brief The number of statements written to the AST file.
+ unsigned NumStatements;
+
+ /// \brief The number of macros written to the AST file.
+ unsigned NumMacros;
+
+ /// \brief The number of lexical declcontexts written to the AST
+ /// file.
+ unsigned NumLexicalDeclContexts;
+
+ /// \brief The number of visible declcontexts written to the AST
+ /// file.
+ unsigned NumVisibleDeclContexts;
+
+ /// \brief The offset of each CXXBaseSpecifier set within the AST.
+ llvm::SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets;
+
+ /// \brief The first ID number we can use for our own base specifiers.
+ serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID;
+
+ /// \brief The base specifiers ID that will be assigned to the next new
+ /// set of C++ base specifiers.
+ serialization::CXXBaseSpecifiersID NextCXXBaseSpecifiersID;
+
+ /// \brief A set of C++ base specifiers that is queued to be written into the
+ /// AST file.
+ struct QueuedCXXBaseSpecifiers {
+ QueuedCXXBaseSpecifiers() : ID(), Bases(), BasesEnd() { }
+
+ QueuedCXXBaseSpecifiers(serialization::CXXBaseSpecifiersID ID,
+ CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd)
+ : ID(ID), Bases(Bases), BasesEnd(BasesEnd) { }
+
+ serialization::CXXBaseSpecifiersID ID;
+ CXXBaseSpecifier const * Bases;
+ CXXBaseSpecifier const * BasesEnd;
+ };
+
+ /// \brief Queue of C++ base specifiers to be written to the AST file,
+ /// in the order they should be written.
+ llvm::SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite;
+
+ /// \brief Write the given subexpression to the bitstream.
+ void WriteSubStmt(Stmt *S);
+
+ void WriteBlockInfoBlock();
+ void WriteMetadata(ASTContext &Context, const char *isysroot,
+ const std::string &OutputFile);
+ void WriteLanguageOptions(const LangOptions &LangOpts);
+ void WriteStatCache(MemorizeStatCalls &StatCalls);
+ void WriteSourceManagerBlock(SourceManager &SourceMgr,
+ const Preprocessor &PP,
+ const char* isysroot);
+ void WritePreprocessor(const Preprocessor &PP);
+ void WriteHeaderSearch(HeaderSearch &HS, const char* isysroot);
+ void WritePreprocessorDetail(PreprocessingRecord &PPRec);
+ void WritePragmaDiagnosticMappings(const Diagnostic &Diag);
+ void WriteType(QualType T);
+ uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
+ uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
+ void WriteTypeDeclOffsets();
+ void WriteSelectors(Sema &SemaRef);
+ void WriteReferencedSelectorsPool(Sema &SemaRef);
+ void WriteIdentifierTable(Preprocessor &PP);
+ void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
+ void WriteDeclUpdatesBlocks();
+ void WriteDeclReplacementsBlock();
+ void WriteDeclContextVisibleUpdate(const DeclContext *DC);
+ void WriteFPPragmaOptions(const FPOptions &Opts);
+ void WriteOpenCLExtensions(Sema &SemaRef);
+
+ unsigned ParmVarDeclAbbrev;
+ unsigned DeclContextLexicalAbbrev;
+ unsigned DeclContextVisibleLookupAbbrev;
+ unsigned UpdateVisibleAbbrev;
+ void WriteDeclsBlockAbbrevs();
+ void WriteDecl(ASTContext &Context, Decl *D);
+
+ void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const char* isysroot, const std::string &OutputFile);
+ void WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const char* isysroot);
+
+public:
+ /// \brief Create a new precompiled header writer that outputs to
+ /// the given bitstream.
+ ASTWriter(llvm::BitstreamWriter &Stream);
+
+ /// \brief Set the listener that will receive notification of serialization
+ /// events.
+ void SetSerializationListener(ASTSerializationListener *Listener) {
+ SerializationListener = Listener;
+ }
+
+ /// \brief Write a precompiled header for the given semantic analysis.
+ ///
+ /// \param SemaRef a reference to the semantic analysis object that processed
+ /// the AST to be written into the precompiled header.
+ ///
+ /// \param StatCalls the object that cached all of the stat() calls made while
+ /// searching for source files and headers.
+ ///
+ /// \param isysroot if non-NULL, write a relocatable PCH file whose headers
+ /// are relative to the given system root.
+ ///
+ /// \param PPRec Record of the preprocessing actions that occurred while
+ /// preprocessing this file, e.g., macro instantiations
+ void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const std::string &OutputFile,
+ const char* isysroot);
+
+ /// \brief Emit a source location.
+ void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record);
+
+ /// \brief Emit a source range.
+ void AddSourceRange(SourceRange Range, RecordDataImpl &Record);
+
+ /// \brief Emit an integral value.
+ void AddAPInt(const llvm::APInt &Value, RecordDataImpl &Record);
+
+ /// \brief Emit a signed integral value.
+ void AddAPSInt(const llvm::APSInt &Value, RecordDataImpl &Record);
+
+ /// \brief Emit a floating-point value.
+ void AddAPFloat(const llvm::APFloat &Value, RecordDataImpl &Record);
+
+ /// \brief Emit a reference to an identifier.
+ void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record);
+
+ /// \brief Emit a Selector (which is a smart pointer reference).
+ void AddSelectorRef(Selector, RecordDataImpl &Record);
+
+ /// \brief Emit a CXXTemporary.
+ void AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record);
+
+ /// \brief Emit a set of C++ base specifiers to the record.
+ void AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd,
+ RecordDataImpl &Record);
+
+ /// \brief Get the unique number used to refer to the given selector.
+ serialization::SelectorID getSelectorRef(Selector Sel);
+
+ /// \brief Get the unique number used to refer to the given identifier.
+ serialization::IdentID getIdentifierRef(const IdentifierInfo *II);
+
+ /// \brief Retrieve the offset of the macro definition for the given
+ /// identifier.
+ ///
+ /// The identifier must refer to a macro.
+ uint64_t getMacroOffset(const IdentifierInfo *II) {
+ assert(MacroOffsets.find(II) != MacroOffsets.end() &&
+ "Identifier does not name a macro");
+ return MacroOffsets[II];
+ }
+
+ /// \brief Retrieve the ID number corresponding to the given macro
+ /// definition.
+ serialization::MacroID getMacroDefinitionID(MacroDefinition *MD);
+
+ /// \brief Emit a reference to a type.
+ void AddTypeRef(QualType T, RecordDataImpl &Record);
+
+ /// \brief Force a type to be emitted and get its ID.
+ serialization::TypeID GetOrCreateTypeID(QualType T);
+
+ /// \brief Determine the type ID of an already-emitted type.
+ serialization::TypeID getTypeID(QualType T) const;
+
+ /// \brief Force a type to be emitted and get its index.
+ serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
+
+ /// \brief Determine the type index of an already-emitted type.
+ serialization::TypeIdx getTypeIdx(QualType T) const;
+
+ /// \brief Emits a reference to a declarator info.
+ void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record);
+
+ /// \brief Emits a template argument location info.
+ void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const TemplateArgumentLocInfo &Arg,
+ RecordDataImpl &Record);
+
+ /// \brief Emits a template argument location.
+ void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordDataImpl &Record);
+
+ /// \brief Emit a reference to a declaration.
+ void AddDeclRef(const Decl *D, RecordDataImpl &Record);
+
+
+ /// \brief Force a declaration to be emitted and get its ID.
+ serialization::DeclID GetDeclRef(const Decl *D);
+
+ /// \brief Determine the declaration ID of an already-emitted
+ /// declaration.
+ serialization::DeclID getDeclID(const Decl *D);
+
+ /// \brief Emit a declaration name.
+ void AddDeclarationName(DeclarationName Name, RecordDataImpl &Record);
+ void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
+ DeclarationName Name, RecordDataImpl &Record);
+ void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ RecordDataImpl &Record);
+
+ void AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record);
+
+ /// \brief Emit a nested name specifier.
+ void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record);
+
+ /// \brief Emit a template name.
+ void AddTemplateName(TemplateName Name, RecordDataImpl &Record);
+
+ /// \brief Emit a template argument.
+ void AddTemplateArgument(const TemplateArgument &Arg, RecordDataImpl &Record);
+
+ /// \brief Emit a template parameter list.
+ void AddTemplateParameterList(const TemplateParameterList *TemplateParams,
+ RecordDataImpl &Record);
+
+ /// \brief Emit a template argument list.
+ void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
+ RecordDataImpl &Record);
+
+ /// \brief Emit a UnresolvedSet structure.
+ void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record);
+
+ /// \brief Emit a C++ base specifier.
+ void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordDataImpl &Record);
+
+ /// \brief Emit a CXXCtorInitializer array.
+ void AddCXXCtorInitializers(
+ const CXXCtorInitializer * const *CtorInitializers,
+ unsigned NumCtorInitializers,
+ RecordDataImpl &Record);
+
+ void AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record);
+
+ /// \brief Add a string to the given record.
+ void AddString(llvm::StringRef Str, RecordDataImpl &Record);
+
+ /// \brief Mark a declaration context as needing an update.
+ void AddUpdatedDeclContext(const DeclContext *DC) {
+ UpdatedDeclContexts.insert(DC);
+ }
+
+ void RewriteDecl(const Decl *D) {
+ DeclsToRewrite.insert(D);
+ // Reset the flag, so that we don't add this decl multiple times.
+ const_cast<Decl *>(D)->setChangedSinceDeserialization(false);
+ }
+
+ /// \brief Note that the identifier II occurs at the given offset
+ /// within the identifier table.
+ void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset);
+
+ /// \brief Note that the selector Sel occurs at the given offset
+ /// within the method pool/selector table.
+ void SetSelectorOffset(Selector Sel, uint32_t Offset);
+
+ /// \brief Add the given statement or expression to the queue of
+ /// statements to emit.
+ ///
+ /// This routine should be used when emitting types and declarations
+ /// that have expressions as part of their formulation. Once the
+ /// type or declaration has been written, call FlushStmts() to write
+ /// the corresponding statements just after the type or
+ /// declaration.
+ void AddStmt(Stmt *S) {
+ CollectedStmts->push_back(S);
+ }
+
+ /// \brief Flush all of the statements and expressions that have
+ /// been added to the queue via AddStmt().
+ void FlushStmts();
+
+ /// \brief Flush all of the C++ base specifier sets that have been added
+ /// via \c AddCXXBaseSpecifiersRef().
+ void FlushCXXBaseSpecifiers();
+
+ /// \brief Record an ID for the given switch-case statement.
+ unsigned RecordSwitchCaseID(SwitchCase *S);
+
+ /// \brief Retrieve the ID for the given switch-case statement.
+ unsigned getSwitchCaseID(SwitchCase *S);
+
+ void ClearSwitchCaseIDs();
+
+ /// \brief Retrieve the ID for the given opaque value expression.
+ unsigned getOpaqueValueID(OpaqueValueExpr *e);
+
+ unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
+
+ bool hasChain() const { return Chain; }
+
+ // ASTDeserializationListener implementation
+ void ReaderInitialized(ASTReader *Reader);
+ void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
+ void TypeRead(serialization::TypeIdx Idx, QualType T);
+ void DeclRead(serialization::DeclID ID, const Decl *D);
+ void SelectorRead(serialization::SelectorID ID, Selector Sel);
+ void MacroDefinitionRead(serialization::MacroID ID, MacroDefinition *MD);
+
+ // ASTMutationListener implementation.
+ virtual void CompletedTagDefinition(const TagDecl *D);
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D);
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D);
+};
+
+/// \brief AST and semantic-analysis consumer that generates a
+/// precompiled header from the parsed source code.
+class PCHGenerator : public SemaConsumer {
+ const Preprocessor &PP;
+ std::string OutputFile;
+ const char *isysroot;
+ llvm::raw_ostream *Out;
+ Sema *SemaPtr;
+ MemorizeStatCalls *StatCalls; // owned by the FileManager
+ std::vector<unsigned char> Buffer;
+ llvm::BitstreamWriter Stream;
+ ASTWriter Writer;
+ bool Chaining;
+
+protected:
+ ASTWriter &getWriter() { return Writer; }
+ const ASTWriter &getWriter() const { return Writer; }
+
+public:
+ PCHGenerator(const Preprocessor &PP, const std::string &OutputFile, bool Chaining,
+ const char *isysroot, llvm::raw_ostream *Out);
+ virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual ASTMutationListener *GetASTMutationListener();
+ virtual ASTSerializationListener *GetASTSerializationListener();
+ virtual ASTDeserializationListener *GetASTDeserializationListener();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
new file mode 100644
index 0000000..e452ccf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -0,0 +1,38 @@
+//===--- CheckerBase.td - Checker TableGen classes ------------------------===//
+//
+// 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 TableGen core definitions for checkers
+//
+//===----------------------------------------------------------------------===//
+
+class Package<string name> {
+ string PackageName = name;
+ bit Hidden = 0;
+ Package ParentPackage;
+}
+class InPackage<Package P> { Package ParentPackage = P; }
+
+class CheckerGroup<string name> {
+ string GroupName = name;
+}
+class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
+
+// All checkers are an indirect subclass of this.
+class Checker<string name = ""> {
+ string CheckerName = name;
+ string DescFile;
+ string HelpText;
+ bit Hidden = 0;
+ Package ParentPackage;
+ CheckerGroup Group;
+}
+
+class DescFile<string filename> { string DescFile = filename; }
+class HelpText<string text> { string HelpText = text; }
+class Hidden { bit Hidden = 1; }
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h
new file mode 100644
index 0000000..f9cce9c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/DereferenceChecker.h
@@ -0,0 +1,35 @@
+//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker and UndefDerefChecker, two builtin checks
+// in ExprEngine that check for null and undefined pointers at loads
+// and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_DEREFCHECKER
+#define LLVM_CLANG_GR_DEREFCHECKER
+
+#include <utility>
+
+namespace clang {
+
+namespace ento {
+
+class ExprEngine;
+class ExplodedNode;
+
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+GetImplicitNullDereferences(ExprEngine &Eng);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
new file mode 100644
index 0000000..42feb78
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
@@ -0,0 +1,51 @@
+//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to call a set of intra-procedural (local)
+// checkers that use flow/path-sensitive analyses to find bugs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_LOCALCHECKERS_H
+#define LLVM_CLANG_GR_LOCALCHECKERS_H
+
+namespace clang {
+
+class CFG;
+class Decl;
+class Diagnostic;
+class ASTContext;
+class LangOptions;
+class ParentMap;
+class LiveVariables;
+class ObjCImplementationDecl;
+class LangOptions;
+class TranslationUnitDecl;
+
+namespace ento {
+
+class PathDiagnosticClient;
+class TransferFuncs;
+class BugType;
+class BugReporter;
+class ExprEngine;
+
+TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts);
+
+void RegisterExperimentalChecks(ExprEngine &Eng);
+void RegisterExperimentalInternalChecks(ExprEngine &Eng);
+
+void RegisterCallInliner(ExprEngine &Eng);
+
+} // end GR namespace
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
new file mode 100644
index 0000000..1786fe6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -0,0 +1,486 @@
+//===--- BugReporter.h - Generate PathDiagnostics --------------*- 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 BugReporter, a utility class for generating
+// PathDiagnostics for analyses based on GRState.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_BUGREPORTER
+#define LLVM_CLANG_GR_BUGREPORTER
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include <list>
+
+namespace clang {
+
+class ASTContext;
+class Diagnostic;
+class Stmt;
+class ParentMap;
+
+namespace ento {
+
+class PathDiagnostic;
+class PathDiagnosticPiece;
+class PathDiagnosticClient;
+class ExplodedNode;
+class ExplodedGraph;
+class BugReporter;
+class BugReporterContext;
+class ExprEngine;
+class GRState;
+class BugType;
+
+//===----------------------------------------------------------------------===//
+// Interface for individual bug reports.
+//===----------------------------------------------------------------------===//
+
+class BugReporterVisitor : public llvm::FoldingSetNode {
+public:
+ virtual ~BugReporterVisitor();
+ virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
+ const ExplodedNode* PrevN,
+ BugReporterContext& BRC) = 0;
+
+ virtual bool isOwnedByReporterContext() { return true; }
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
+};
+
+// FIXME: Combine this with RangedBugReport and remove RangedBugReport.
+class BugReport : public BugReporterVisitor {
+protected:
+ BugType& BT;
+ std::string ShortDescription;
+ std::string Description;
+ const ExplodedNode *ErrorNode;
+ mutable SourceRange R;
+
+protected:
+ friend class BugReporter;
+ friend class BugReportEquivClass;
+
+ virtual void Profile(llvm::FoldingSetNodeID& hash) const {
+ hash.AddInteger(getLocation().getRawEncoding());
+ hash.AddString(Description);
+ }
+
+public:
+ class NodeResolver {
+ public:
+ virtual ~NodeResolver() {}
+ virtual const ExplodedNode*
+ getOriginalNode(const ExplodedNode* N) = 0;
+ };
+
+ BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *errornode)
+ : BT(bt), Description(desc), ErrorNode(errornode) {}
+
+ BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc,
+ const ExplodedNode *errornode)
+ : BT(bt), ShortDescription(shortDesc), Description(desc),
+ ErrorNode(errornode) {}
+
+ virtual ~BugReport();
+
+ virtual bool isOwnedByReporterContext() { return false; }
+
+ const BugType& getBugType() const { return BT; }
+ BugType& getBugType() { return BT; }
+
+ // FIXME: Perhaps this should be moved into a subclass?
+ const ExplodedNode* getErrorNode() const { return ErrorNode; }
+
+ // FIXME: Do we need this? Maybe getLocation() should return a ProgramPoint
+ // object.
+ // FIXME: If we do need it, we can probably just make it private to
+ // BugReporter.
+ const Stmt* getStmt() const;
+
+ const llvm::StringRef getDescription() const { return Description; }
+
+ const llvm::StringRef getShortDescription() const {
+ return ShortDescription.empty() ? Description : ShortDescription;
+ }
+
+ // FIXME: Is this needed?
+ virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
+ return std::make_pair((const char**)0,(const char**)0);
+ }
+
+ // FIXME: Perhaps move this into a subclass.
+ virtual PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* N);
+
+ /// getLocation - Return the "definitive" location of the reported bug.
+ /// While a bug can span an entire path, usually there is a specific
+ /// location that can be used to identify where the key issue occured.
+ /// This location is used by clients rendering diagnostics.
+ virtual SourceLocation getLocation() const;
+
+ typedef const SourceRange *ranges_iterator;
+
+ /// getRanges - Returns the source ranges associated with this bug.
+ virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const;
+
+ virtual PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
+ const ExplodedNode* PrevN,
+ BugReporterContext& BR);
+
+ virtual void registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode* N) {}
+};
+
+//===----------------------------------------------------------------------===//
+// BugTypes (collections of related reports).
+//===----------------------------------------------------------------------===//
+
+class BugReportEquivClass : public llvm::FoldingSetNode {
+ // List of *owned* BugReport objects.
+ std::list<BugReport*> Reports;
+
+ friend class BugReporter;
+ void AddReport(BugReport* R) { Reports.push_back(R); }
+public:
+ BugReportEquivClass(BugReport* R) { Reports.push_back(R); }
+ ~BugReportEquivClass();
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ assert(!Reports.empty());
+ (*Reports.begin())->Profile(ID);
+ }
+
+ class iterator {
+ std::list<BugReport*>::iterator impl;
+ public:
+ iterator(std::list<BugReport*>::iterator i) : impl(i) {}
+ iterator& operator++() { ++impl; return *this; }
+ bool operator==(const iterator& I) const { return I.impl == impl; }
+ bool operator!=(const iterator& I) const { return I.impl != impl; }
+ BugReport* operator*() const { return *impl; }
+ BugReport* operator->() const { return *impl; }
+ };
+
+ class const_iterator {
+ std::list<BugReport*>::const_iterator impl;
+ public:
+ const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {}
+ const_iterator& operator++() { ++impl; return *this; }
+ bool operator==(const const_iterator& I) const { return I.impl == impl; }
+ bool operator!=(const const_iterator& I) const { return I.impl != impl; }
+ const BugReport* operator*() const { return *impl; }
+ const BugReport* operator->() const { return *impl; }
+ };
+
+ iterator begin() { return iterator(Reports.begin()); }
+ iterator end() { return iterator(Reports.end()); }
+
+ const_iterator begin() const { return const_iterator(Reports.begin()); }
+ const_iterator end() const { return const_iterator(Reports.end()); }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Specialized subclasses of BugReport.
+//===----------------------------------------------------------------------===//
+
+// FIXME: Collapse this with the default BugReport class.
+class RangedBugReport : public BugReport {
+ llvm::SmallVector<SourceRange, 4> Ranges;
+public:
+ RangedBugReport(BugType& D, llvm::StringRef description,
+ ExplodedNode *errornode)
+ : BugReport(D, description, errornode) {}
+
+ RangedBugReport(BugType& D, llvm::StringRef shortDescription,
+ llvm::StringRef description, ExplodedNode *errornode)
+ : BugReport(D, shortDescription, description, errornode) {}
+
+ ~RangedBugReport();
+
+ // FIXME: Move this out of line.
+ void addRange(SourceRange R) {
+ assert(R.isValid());
+ Ranges.push_back(R);
+ }
+
+ virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const {
+ return std::make_pair(Ranges.begin(), Ranges.end());
+ }
+};
+
+class EnhancedBugReport : public RangedBugReport {
+public:
+ typedef void (*VisitorCreator)(BugReporterContext &BRcC, const void *data,
+ const ExplodedNode *N);
+
+private:
+ typedef std::vector<std::pair<VisitorCreator, const void*> > Creators;
+ Creators creators;
+
+public:
+ EnhancedBugReport(BugType& D, llvm::StringRef description,
+ ExplodedNode *errornode)
+ : RangedBugReport(D, description, errornode) {}
+
+ EnhancedBugReport(BugType& D, llvm::StringRef shortDescription,
+ llvm::StringRef description, ExplodedNode *errornode)
+ : RangedBugReport(D, shortDescription, description, errornode) {}
+
+ ~EnhancedBugReport() {}
+
+ void registerInitialVisitors(BugReporterContext& BRC, const ExplodedNode* N) {
+ for (Creators::iterator I = creators.begin(), E = creators.end(); I!=E; ++I)
+ I->first(BRC, I->second, N);
+ }
+
+ void addVisitorCreator(VisitorCreator creator, const void *data) {
+ creators.push_back(std::make_pair(creator, data));
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// BugReporter and friends.
+//===----------------------------------------------------------------------===//
+
+class BugReporterData {
+public:
+ virtual ~BugReporterData();
+ virtual Diagnostic& getDiagnostic() = 0;
+ virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
+ virtual ASTContext& getASTContext() = 0;
+ virtual SourceManager& getSourceManager() = 0;
+};
+
+class BugReporter {
+public:
+ enum Kind { BaseBRKind, GRBugReporterKind };
+
+private:
+ typedef llvm::ImmutableSet<BugType*> BugTypesTy;
+ BugTypesTy::Factory F;
+ BugTypesTy BugTypes;
+
+ const Kind kind;
+ BugReporterData& D;
+
+ void FlushReport(BugReportEquivClass& EQ);
+
+protected:
+ BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
+ D(d) {}
+
+public:
+ BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
+ D(d) {}
+ virtual ~BugReporter();
+
+ void FlushReports();
+
+ Kind getKind() const { return kind; }
+
+ Diagnostic& getDiagnostic() {
+ return D.getDiagnostic();
+ }
+
+ PathDiagnosticClient* getPathDiagnosticClient() {
+ return D.getPathDiagnosticClient();
+ }
+
+ typedef BugTypesTy::iterator iterator;
+ iterator begin() { return BugTypes.begin(); }
+ iterator end() { return BugTypes.end(); }
+
+ ASTContext& getContext() { return D.getASTContext(); }
+
+ SourceManager& getSourceManager() { return D.getSourceManager(); }
+
+ virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
+ llvm::SmallVectorImpl<BugReport *> &bugReports) {}
+
+ void Register(BugType *BT);
+
+ void EmitReport(BugReport *R);
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
+ SourceLocation Loc,
+ SourceRange* RangeBeg, unsigned NumRanges);
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
+ llvm::StringRef BugStr, SourceLocation Loc,
+ SourceRange* RangeBeg, unsigned NumRanges);
+
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
+ SourceLocation Loc) {
+ EmitBasicReport(BugName, BugStr, Loc, 0, 0);
+ }
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory,
+ llvm::StringRef BugStr, SourceLocation Loc) {
+ EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
+ }
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr,
+ SourceLocation Loc, SourceRange R) {
+ EmitBasicReport(BugName, BugStr, Loc, &R, 1);
+ }
+
+ void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef Category,
+ llvm::StringRef BugStr, SourceLocation Loc,
+ SourceRange R) {
+ EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
+ }
+
+ static bool classof(const BugReporter* R) { return true; }
+};
+
+// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
+class GRBugReporter : public BugReporter {
+ ExprEngine& Eng;
+ llvm::SmallSet<SymbolRef, 10> NotableSymbols;
+public:
+ GRBugReporter(BugReporterData& d, ExprEngine& eng)
+ : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+
+ virtual ~GRBugReporter();
+
+ /// getEngine - Return the analysis engine used to analyze a given
+ /// function or method.
+ ExprEngine &getEngine() { return Eng; }
+
+ /// getGraph - Get the exploded graph created by the analysis engine
+ /// for the analyzed method or function.
+ ExplodedGraph &getGraph();
+
+ /// getStateManager - Return the state manager used by the analysis
+ /// engine.
+ GRStateManager &getStateManager();
+
+ virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
+ llvm::SmallVectorImpl<BugReport*> &bugReports);
+
+ void addNotableSymbol(SymbolRef Sym) {
+ NotableSymbols.insert(Sym);
+ }
+
+ bool isNotable(SymbolRef Sym) const {
+ return (bool) NotableSymbols.count(Sym);
+ }
+
+ /// classof - Used by isa<>, cast<>, and dyn_cast<>.
+ static bool classof(const BugReporter* R) {
+ return R->getKind() == GRBugReporterKind;
+ }
+};
+
+class BugReporterContext {
+ GRBugReporter &BR;
+ // Not the most efficient data structure, but we use an ImmutableList for the
+ // Callbacks because it is safe to make additions to list during iteration.
+ llvm::ImmutableList<BugReporterVisitor*>::Factory F;
+ llvm::ImmutableList<BugReporterVisitor*> Callbacks;
+ llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
+public:
+ BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.getEmptyList()) {}
+ virtual ~BugReporterContext();
+
+ void addVisitor(BugReporterVisitor* visitor);
+
+ typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator;
+ visitor_iterator visitor_begin() { return Callbacks.begin(); }
+ visitor_iterator visitor_end() { return Callbacks.end(); }
+
+ GRBugReporter& getBugReporter() { return BR; }
+
+ ExplodedGraph &getGraph() { return BR.getGraph(); }
+
+ void addNotableSymbol(SymbolRef Sym) {
+ // FIXME: For now forward to GRBugReporter.
+ BR.addNotableSymbol(Sym);
+ }
+
+ bool isNotable(SymbolRef Sym) const {
+ // FIXME: For now forward to GRBugReporter.
+ return BR.isNotable(Sym);
+ }
+
+ GRStateManager& getStateManager() {
+ return BR.getStateManager();
+ }
+
+ SValBuilder& getSValBuilder() {
+ return getStateManager().getSValBuilder();
+ }
+
+ ASTContext& getASTContext() {
+ return BR.getContext();
+ }
+
+ SourceManager& getSourceManager() {
+ return BR.getSourceManager();
+ }
+
+ virtual BugReport::NodeResolver& getNodeResolver() = 0;
+};
+
+class DiagBugReport : public RangedBugReport {
+ std::list<std::string> Strs;
+ FullSourceLoc L;
+public:
+ DiagBugReport(BugType& D, llvm::StringRef desc, FullSourceLoc l) :
+ RangedBugReport(D, desc, 0), L(l) {}
+
+ virtual ~DiagBugReport() {}
+
+ // FIXME: Move out-of-line (virtual function).
+ SourceLocation getLocation() const { return L; }
+
+ void addString(llvm::StringRef s) { Strs.push_back(s); }
+
+ typedef std::list<std::string>::const_iterator str_iterator;
+ str_iterator str_begin() const { return Strs.begin(); }
+ str_iterator str_end() const { return Strs.end(); }
+};
+
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+namespace bugreporter {
+
+const Stmt *GetDerefExpr(const ExplodedNode *N);
+const Stmt *GetDenomExpr(const ExplodedNode *N);
+const Stmt *GetCalleeExpr(const ExplodedNode *N);
+const Stmt *GetRetValExpr(const ExplodedNode *N);
+
+void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt,
+ const ExplodedNode* N);
+
+void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
+ const ExplodedNode *N);
+
+void registerNilReceiverVisitor(BugReporterContext &BRC);
+
+void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
+ const ExplodedNode *N);
+
+} // end namespace clang::bugreporter
+
+//===----------------------------------------------------------------------===//
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
new file mode 100644
index 0000000..2793284
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -0,0 +1,76 @@
+//===--- BugType.h - Bug Information Desciption ----------------*- 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 BugType, a class representing a bug type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
+#define LLVM_CLANG_ANALYSIS_BUGTYPE
+
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <string>
+
+namespace clang {
+
+namespace ento {
+
+class ExplodedNode;
+class ExprEngine;
+
+class BugType {
+private:
+ const std::string Name;
+ const std::string Category;
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+ friend class BugReporter;
+ bool SuppressonSink;
+public:
+ BugType(llvm::StringRef name, llvm::StringRef cat)
+ : Name(name), Category(cat), SuppressonSink(false) {}
+ virtual ~BugType();
+
+ // FIXME: Should these be made strings as well?
+ llvm::StringRef getName() const { return Name; }
+ llvm::StringRef getCategory() const { return Category; }
+
+ /// isSuppressOnSink - Returns true if bug reports associated with this bug
+ /// type should be suppressed if the end node of the report is post-dominated
+ /// by a sink node.
+ bool isSuppressOnSink() const { return SuppressonSink; }
+ void setSuppressOnSink(bool x) { SuppressonSink = x; }
+
+ virtual void FlushReports(BugReporter& BR);
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
+ iterator begin() { return EQClasses.begin(); }
+ iterator end() { return EQClasses.end(); }
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
+ const_iterator begin() const { return EQClasses.begin(); }
+ const_iterator end() const { return EQClasses.end(); }
+};
+
+class BuiltinBug : public BugType {
+ const std::string desc;
+public:
+ BuiltinBug(const char *name, const char *description)
+ : BugType(name, "Logic error"), desc(description) {}
+
+ BuiltinBug(const char *name)
+ : BugType(name, "Logic error"), desc(name) {}
+
+ llvm::StringRef getDescription() const { return desc; }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
new file mode 100644
index 0000000..6d53c09
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -0,0 +1,500 @@
+//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- 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 PathDiagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H
+#define LLVM_CLANG_PATH_DIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <deque>
+#include <iterator>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class Decl;
+class SourceManager;
+class Stmt;
+
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+// High-level interface for handlers of path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnostic;
+
+class PathDiagnosticClient : public DiagnosticClient {
+public:
+ PathDiagnosticClient() {}
+
+ virtual ~PathDiagnosticClient() {}
+
+ virtual void
+ FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0;
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> &FilesMade) {
+ FlushDiagnostics(&FilesMade);
+ }
+
+ virtual llvm::StringRef getName() const = 0;
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+ virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
+
+ enum PathGenerationScheme { Minimal, Extensive };
+ virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
+ virtual bool supportsLogicalOpControlFlow() const { return false; }
+ virtual bool supportsAllBlockEdges() const { return false; }
+ virtual bool useVerboseDescription() const { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnosticRange : public SourceRange {
+public:
+ const bool isPoint;
+
+ PathDiagnosticRange(const SourceRange &R, bool isP = false)
+ : SourceRange(R), isPoint(isP) {}
+};
+
+class PathDiagnosticLocation {
+private:
+ enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
+ SourceRange R;
+ const Stmt *S;
+ const Decl *D;
+ const SourceManager *SM;
+public:
+ PathDiagnosticLocation()
+ : K(SingleLocK), S(0), D(0), SM(0) {}
+
+ PathDiagnosticLocation(FullSourceLoc L)
+ : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {}
+
+ PathDiagnosticLocation(const Stmt *s, const SourceManager &sm)
+ : K(StmtK), S(s), D(0), SM(&sm) {}
+
+ PathDiagnosticLocation(SourceRange r, const SourceManager &sm)
+ : K(RangeK), R(r), S(0), D(0), SM(&sm) {}
+
+ PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
+ : K(DeclK), S(0), D(d), SM(&sm) {}
+
+ bool operator==(const PathDiagnosticLocation &X) const {
+ return K == X.K && R == X.R && S == X.S && D == X.D;
+ }
+
+ bool operator!=(const PathDiagnosticLocation &X) const {
+ return K != X.K || R != X.R || S != X.S || D != X.D;;
+ }
+
+ PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) {
+ K = X.K;
+ R = X.R;
+ S = X.S;
+ D = X.D;
+ SM = X.SM;
+ return *this;
+ }
+
+ bool isValid() const {
+ return SM != 0;
+ }
+
+ const SourceManager& getSourceManager() const { assert(isValid());return *SM;}
+
+ FullSourceLoc asLocation() const;
+ PathDiagnosticRange asRange() const;
+ const Stmt *asStmt() const { assert(isValid()); return S; }
+ const Decl *asDecl() const { assert(isValid()); return D; }
+
+ bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
+
+ void invalidate() {
+ *this = PathDiagnosticLocation();
+ }
+
+ void flatten();
+
+ const SourceManager& getManager() const { assert(isValid()); return *SM; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+class PathDiagnosticLocationPair {
+private:
+ PathDiagnosticLocation Start, End;
+public:
+ PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
+ const PathDiagnosticLocation &end)
+ : Start(start), End(end) {}
+
+ const PathDiagnosticLocation &getStart() const { return Start; }
+ const PathDiagnosticLocation &getEnd() const { return End; }
+
+ void flatten() {
+ Start.flatten();
+ End.flatten();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Start.Profile(ID);
+ End.Profile(ID);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Path "pieces" for path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnosticPiece {
+public:
+ enum Kind { ControlFlow, Event, Macro };
+ enum DisplayHint { Above, Below };
+
+private:
+ const std::string str;
+ std::vector<FixItHint> FixItHints;
+ const Kind kind;
+ const DisplayHint Hint;
+ std::vector<SourceRange> ranges;
+
+ // Do not implement:
+ PathDiagnosticPiece();
+ PathDiagnosticPiece(const PathDiagnosticPiece &P);
+ PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P);
+
+protected:
+ PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below);
+
+ PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
+
+public:
+ virtual ~PathDiagnosticPiece();
+
+ const std::string& getString() const { return str; }
+
+ /// getDisplayHint - Return a hint indicating where the diagnostic should
+ /// be displayed by the PathDiagnosticClient.
+ DisplayHint getDisplayHint() const { return Hint; }
+
+ virtual PathDiagnosticLocation getLocation() const = 0;
+ virtual void flattenLocations() = 0;
+
+ Kind getKind() const { return kind; }
+
+ void addRange(SourceRange R) { ranges.push_back(R); }
+
+ void addRange(SourceLocation B, SourceLocation E) {
+ ranges.push_back(SourceRange(B,E));
+ }
+
+ void addFixItHint(const FixItHint& Hint) {
+ FixItHints.push_back(Hint);
+ }
+
+ typedef const SourceRange* range_iterator;
+
+ range_iterator ranges_begin() const {
+ return ranges.empty() ? NULL : &ranges[0];
+ }
+
+ range_iterator ranges_end() const {
+ return ranges_begin() + ranges.size();
+ }
+
+ typedef const FixItHint *fixit_iterator;
+
+ fixit_iterator fixit_begin() const {
+ return FixItHints.empty()? 0 : &FixItHints[0];
+ }
+
+ fixit_iterator fixit_end() const {
+ return FixItHints.empty()? 0
+ : &FixItHints[0] + FixItHints.size();
+ }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return true;
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
+private:
+ PathDiagnosticLocation Pos;
+public:
+ PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
+ llvm::StringRef s,
+ PathDiagnosticPiece::Kind k,
+ bool addPosRange = true)
+ : PathDiagnosticPiece(s, k), Pos(pos) {
+ assert(Pos.asLocation().isValid() &&
+ "PathDiagnosticSpotPiece's must have a valid location.");
+ if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
+ }
+
+ PathDiagnosticLocation getLocation() const { return Pos; }
+ virtual void flattenLocations() { Pos.flatten(); }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
+
+public:
+ PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
+ llvm::StringRef s, bool addPosRange = true)
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
+
+ ~PathDiagnosticEventPiece();
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == Event;
+ }
+};
+
+class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
+ std::vector<PathDiagnosticLocationPair> LPairs;
+public:
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos,
+ llvm::StringRef s)
+ : PathDiagnosticPiece(s, ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
+
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos)
+ : PathDiagnosticPiece(ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
+
+ ~PathDiagnosticControlFlowPiece();
+
+ PathDiagnosticLocation getStartLocation() const {
+ assert(!LPairs.empty() &&
+ "PathDiagnosticControlFlowPiece needs at least one location.");
+ return LPairs[0].getStart();
+ }
+
+ PathDiagnosticLocation getEndLocation() const {
+ assert(!LPairs.empty() &&
+ "PathDiagnosticControlFlowPiece needs at least one location.");
+ return LPairs[0].getEnd();
+ }
+
+ void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
+
+ virtual PathDiagnosticLocation getLocation() const {
+ return getStartLocation();
+ }
+
+ typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
+ iterator begin() { return LPairs.begin(); }
+ iterator end() { return LPairs.end(); }
+
+ virtual void flattenLocations() {
+ for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
+ }
+
+ typedef std::vector<PathDiagnosticLocationPair>::const_iterator
+ const_iterator;
+ const_iterator begin() const { return LPairs.begin(); }
+ const_iterator end() const { return LPairs.end(); }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == ControlFlow;
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
+ std::vector<PathDiagnosticPiece*> SubPieces;
+public:
+ PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
+
+ ~PathDiagnosticMacroPiece();
+
+ bool containsEvent() const;
+
+ void push_back(PathDiagnosticPiece* P) { SubPieces.push_back(P); }
+
+ typedef std::vector<PathDiagnosticPiece*>::iterator iterator;
+ iterator begin() { return SubPieces.begin(); }
+ iterator end() { return SubPieces.end(); }
+
+ virtual void flattenLocations() {
+ PathDiagnosticSpotPiece::flattenLocations();
+ for (iterator I=begin(), E=end(); I!=E; ++I) (*I)->flattenLocations();
+ }
+
+ typedef std::vector<PathDiagnosticPiece*>::const_iterator const_iterator;
+ const_iterator begin() const { return SubPieces.begin(); }
+ const_iterator end() const { return SubPieces.end(); }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == Macro;
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
+/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
+/// each which represent the pieces of the path.
+class PathDiagnostic : public llvm::FoldingSetNode {
+ std::deque<PathDiagnosticPiece*> path;
+ unsigned Size;
+ std::string BugType;
+ std::string Desc;
+ std::string Category;
+ std::deque<std::string> OtherDesc;
+
+public:
+ PathDiagnostic();
+
+ PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc,
+ llvm::StringRef category);
+
+ ~PathDiagnostic();
+
+ llvm::StringRef getDescription() const { return Desc; }
+ llvm::StringRef getBugType() const { return BugType; }
+ llvm::StringRef getCategory() const { return Category; }
+
+ typedef std::deque<std::string>::const_iterator meta_iterator;
+ meta_iterator meta_begin() const { return OtherDesc.begin(); }
+ meta_iterator meta_end() const { return OtherDesc.end(); }
+ void addMeta(llvm::StringRef s) { OtherDesc.push_back(s); }
+
+ PathDiagnosticLocation getLocation() const {
+ assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic.");
+ return rbegin()->getLocation();
+ }
+
+ void push_front(PathDiagnosticPiece* piece) {
+ assert(piece);
+ path.push_front(piece);
+ ++Size;
+ }
+
+ void push_back(PathDiagnosticPiece* piece) {
+ assert(piece);
+ path.push_back(piece);
+ ++Size;
+ }
+
+ PathDiagnosticPiece* back() {
+ return path.back();
+ }
+
+ const PathDiagnosticPiece* back() const {
+ return path.back();
+ }
+
+ unsigned size() const { return Size; }
+ bool empty() const { return Size == 0; }
+
+ void resetPath(bool deletePieces = true);
+
+ class iterator {
+ public:
+ typedef std::deque<PathDiagnosticPiece*>::iterator ImplTy;
+
+ typedef PathDiagnosticPiece value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ private:
+ ImplTy I;
+
+ public:
+ iterator(const ImplTy& i) : I(i) {}
+
+ bool operator==(const iterator& X) const { return I == X.I; }
+ bool operator!=(const iterator& X) const { return I != X.I; }
+
+ PathDiagnosticPiece& operator*() const { return **I; }
+ PathDiagnosticPiece* operator->() const { return *I; }
+
+ iterator& operator++() { ++I; return *this; }
+ iterator& operator--() { --I; return *this; }
+ };
+
+ class const_iterator {
+ public:
+ typedef std::deque<PathDiagnosticPiece*>::const_iterator ImplTy;
+
+ typedef const PathDiagnosticPiece value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ private:
+ ImplTy I;
+
+ public:
+ const_iterator(const ImplTy& i) : I(i) {}
+
+ bool operator==(const const_iterator& X) const { return I == X.I; }
+ bool operator!=(const const_iterator& X) const { return I != X.I; }
+
+ reference operator*() const { return **I; }
+ pointer operator->() const { return *I; }
+
+ const_iterator& operator++() { ++I; return *this; }
+ const_iterator& operator--() { --I; return *this; }
+ };
+
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // forward iterator creation methods.
+
+ iterator begin() { return path.begin(); }
+ iterator end() { return path.end(); }
+
+ const_iterator begin() const { return path.begin(); }
+ const_iterator end() const { return path.end(); }
+
+ // reverse iterator creation methods.
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+ void flattenLocations() {
+ for (iterator I = begin(), E = end(); I != E; ++I) I->flattenLocations();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+};
+
+} // end GR namespace
+
+} //end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
new file mode 100644
index 0000000..65c8b80
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -0,0 +1,109 @@
+//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Manager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+
+namespace clang {
+ class Decl;
+
+namespace ento {
+ class ExprEngine;
+ class AnalysisManager;
+ class BugReporter;
+
+class CheckerManager {
+public:
+ ~CheckerManager();
+
+ typedef void *CheckerRef;
+
+//===----------------------------------------------------------------------===//
+// registerChecker
+//===----------------------------------------------------------------------===//
+
+ /// \brief Used to register checkers.
+ template <typename CHECKER>
+ void registerChecker() {
+ CHECKER *checker = new CHECKER();
+ Checkers.push_back(std::pair<CheckerRef, Dtor>(checker, destruct<CHECKER>));
+ CHECKER::_register(checker, *this);
+ }
+
+ typedef void (*RegisterToEngFunc)(ExprEngine &Eng);
+ void addCheckerRegisterFunction(RegisterToEngFunc fn) {
+ Funcs.push_back(fn);
+ }
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers.
+//===----------------------------------------------------------------------===//
+
+ /// \brief Run checkers handling Decls.
+ void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR);
+
+ /// \brief Run checkers handling Decls containing a Stmt body.
+ void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions.
+//===----------------------------------------------------------------------===//
+
+ // Functions used by the registration mechanism, checkers should not touch
+ // these directly.
+
+ typedef void (*CheckDeclFunc)(CheckerRef checker, const Decl *D,
+ AnalysisManager& mgr, BugReporter &BR);
+ typedef bool (*HandlesDeclFunc)(const Decl *D);
+ void _registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
+ HandlesDeclFunc isForDeclFn);
+
+ void _registerForBody(CheckerRef checker, CheckDeclFunc checkfn);
+
+ void registerCheckersToEngine(ExprEngine &eng);
+
+private:
+ template <typename CHECKER>
+ static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
+
+ std::vector<RegisterToEngFunc> Funcs;
+
+ struct DeclCheckerInfo {
+ CheckerRef Checker;
+ CheckDeclFunc CheckFn;
+ HandlesDeclFunc IsForDeclFn;
+ };
+ std::vector<DeclCheckerInfo> DeclCheckers;
+
+ std::vector<std::pair<CheckerRef, CheckDeclFunc> > BodyCheckers;
+
+ typedef void (*Dtor)(void *);
+ std::vector<std::pair<CheckerRef, Dtor> > Checkers;
+
+ typedef llvm::SmallVector<std::pair<CheckerRef, CheckDeclFunc>, 4>
+ CachedDeclCheckers;
+ typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
+ CachedDeclCheckersMapTy CachedDeclCheckersMap;
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
new file mode 100644
index 0000000..414ad92
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
@@ -0,0 +1,54 @@
+//===--- CheckerProvider.h - Static Analyzer Checkers Provider --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Provider.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H
+#define LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+
+namespace ento {
+ class CheckerManager;
+
+class CheckerOptInfo {
+ const char *Name;
+ bool Enable;
+ bool Claimed;
+
+public:
+ CheckerOptInfo(const char *name, bool enable)
+ : Name(name), Enable(enable), Claimed(false) { }
+
+ const char *getName() const { return Name; }
+ bool isEnabled() const { return Enable; }
+ bool isDisabled() const { return !isEnabled(); }
+
+ bool isClaimed() const { return Claimed; }
+ bool isUnclaimed() const { return !isClaimed(); }
+ void claim() { Claimed = true; }
+};
+
+class CheckerProvider {
+public:
+ virtual ~CheckerProvider();
+ virtual void registerCheckers(CheckerManager &checkerMgr,
+ CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0;
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
new file mode 100644
index 0000000..8c96866
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
@@ -0,0 +1,93 @@
+//== CheckerV2.h - Registration mechanism for checkers -----------*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CheckerV2, used to create and register checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_CHECKERV2
+#define LLVM_CLANG_SA_CORE_CHECKERV2
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/Support/Casting.h"
+
+namespace clang {
+namespace ento {
+ class BugReporter;
+
+namespace check {
+
+struct _VoidCheck {
+ static void _register(void *checker, CheckerManager &mgr) { }
+};
+
+template <typename DECL>
+class ASTDecl {
+ template <typename CHECKER>
+ static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
+ }
+
+ static bool _handlesDecl(const Decl *D) {
+ return llvm::isa<DECL>(D);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDecl(checker, _checkDecl<CHECKER>, _handlesDecl);
+ }
+};
+
+class ASTCodeBody {
+ template <typename CHECKER>
+ static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBody(checker, _checkBody<CHECKER>);
+ }
+};
+
+} // end check namespace
+
+template <typename CHECK1, typename CHECK2=check::_VoidCheck,
+ typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
+ typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
+ typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
+ typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
+ typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
+class CheckerV2 {
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ CHECK1::_register(checker, mgr);
+ CHECK2::_register(checker, mgr);
+ CHECK3::_register(checker, mgr);
+ CHECK4::_register(checker, mgr);
+ CHECK5::_register(checker, mgr);
+ CHECK6::_register(checker, mgr);
+ CHECK7::_register(checker, mgr);
+ CHECK8::_register(checker, mgr);
+ CHECK9::_register(checker, mgr);
+ CHECK10::_register(checker, mgr);
+ CHECK11::_register(checker, mgr);
+ CHECK12::_register(checker, mgr);
+ }
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h
new file mode 100644
index 0000000..2713e31
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h
@@ -0,0 +1,42 @@
+//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- 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 interface to create different path diagostic clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H
+#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLiENTS_H
+
+#include <string>
+
+namespace clang {
+
+class Preprocessor;
+
+namespace ento {
+
+class PathDiagnosticClient;
+
+PathDiagnosticClient*
+createHTMLDiagnosticClient(const std::string& prefix, const Preprocessor &PP);
+
+PathDiagnosticClient*
+createPlistDiagnosticClient(const std::string& prefix, const Preprocessor &PP,
+ PathDiagnosticClient *SubPD = 0);
+
+PathDiagnosticClient*
+createTextPathDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
new file mode 100644
index 0000000..1ba038e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -0,0 +1,220 @@
+//== AnalysisManager.h - Path sensitive analysis data manager ------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AnalysisManager class that manages the data and policy
+// for path sensitive analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_ANALYSISMANAGER_H
+#define LLVM_CLANG_GR_ANALYSISMANAGER_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+
+namespace clang {
+
+namespace idx {
+ class Indexer;
+ class TranslationUnit;
+}
+
+namespace ento {
+ class CheckerManager;
+
+class AnalysisManager : public BugReporterData {
+ AnalysisContextManager AnaCtxMgr;
+ LocationContextManager LocCtxMgr;
+
+ ASTContext &Ctx;
+ Diagnostic &Diags;
+ const LangOptions &LangInfo;
+
+ llvm::OwningPtr<PathDiagnosticClient> PD;
+
+ // Configurable components creators.
+ StoreManagerCreator CreateStoreMgr;
+ ConstraintManagerCreator CreateConstraintMgr;
+
+ CheckerManager *CheckerMgr;
+
+ /// \brief Provide function definitions in other translation units. This is
+ /// NULL if we don't have multiple translation units. AnalysisManager does
+ /// not own the Indexer.
+ idx::Indexer *Idxer;
+
+ enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
+
+ // The maximum number of exploded nodes the analyzer will generate.
+ unsigned MaxNodes;
+
+ // The maximum number of times the analyzer visit a block.
+ unsigned MaxVisit;
+
+ bool VisualizeEGDot;
+ bool VisualizeEGUbi;
+ bool PurgeDead;
+
+ /// EargerlyAssume - A flag indicating how the engine should handle
+ // expressions such as: 'x = (y != 0)'. When this flag is true then
+ // the subexpression 'y != 0' will be eagerly assumed to be true or false,
+ // thus evaluating it to the integers 0 or 1 respectively. The upside
+ // is that this can increase analysis precision until we have a better way
+ // to lazily evaluate such logic. The downside is that it eagerly
+ // bifurcates paths.
+ bool EagerlyAssume;
+ bool TrimGraph;
+ bool InlineCall;
+ bool EagerlyTrimEGraph;
+
+public:
+ AnalysisManager(ASTContext &ctx, Diagnostic &diags,
+ const LangOptions &lang, PathDiagnosticClient *pd,
+ StoreManagerCreator storemgr,
+ ConstraintManagerCreator constraintmgr,
+ CheckerManager *checkerMgr,
+ idx::Indexer *idxer,
+ unsigned maxnodes, unsigned maxvisit,
+ bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
+ bool inlinecall, bool useUnoptimizedCFG,
+ bool addImplicitDtors, bool addInitializers,
+ bool eagerlyTrimEGraph)
+
+ : AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers),
+ Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ CheckerMgr(checkerMgr), Idxer(idxer),
+ AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit),
+ VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
+ EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall),
+ EagerlyTrimEGraph(eagerlyTrimEGraph) {}
+
+ ~AnalysisManager() { FlushDiagnostics(); }
+
+ void ClearContexts() {
+ LocCtxMgr.clear();
+ AnaCtxMgr.clear();
+ }
+
+ AnalysisContextManager& getAnalysisContextManager() {
+ return AnaCtxMgr;
+ }
+
+ StoreManagerCreator getStoreManagerCreator() {
+ return CreateStoreMgr;
+ }
+
+ ConstraintManagerCreator getConstraintManagerCreator() {
+ return CreateConstraintMgr;
+ }
+
+ CheckerManager *getCheckerManager() const { return CheckerMgr; }
+
+ idx::Indexer *getIndexer() const { return Idxer; }
+
+ virtual ASTContext &getASTContext() {
+ return Ctx;
+ }
+
+ virtual SourceManager &getSourceManager() {
+ return getASTContext().getSourceManager();
+ }
+
+ virtual Diagnostic &getDiagnostic() {
+ return Diags;
+ }
+
+ const LangOptions &getLangOptions() const {
+ return LangInfo;
+ }
+
+ virtual PathDiagnosticClient *getPathDiagnosticClient() {
+ return PD.get();
+ }
+
+ void FlushDiagnostics() {
+ if (PD.get())
+ PD->FlushDiagnostics();
+ }
+
+ unsigned getMaxNodes() const { return MaxNodes; }
+
+ unsigned getMaxVisit() const { return MaxVisit; }
+
+ bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
+
+ bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; }
+
+ bool shouldVisualize() const {
+ return VisualizeEGDot || VisualizeEGUbi;
+ }
+
+ bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; }
+
+ bool shouldTrimGraph() const { return TrimGraph; }
+
+ bool shouldPurgeDead() const { return PurgeDead; }
+
+ bool shouldEagerlyAssume() const { return EagerlyAssume; }
+
+ bool shouldInlineCall() const { return InlineCall; }
+
+ bool hasIndexer() const { return Idxer != 0; }
+
+ AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
+
+ CFG *getCFG(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getCFG();
+ }
+
+ LiveVariables *getLiveVariables(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getLiveVariables();
+ }
+
+ ParentMap &getParentMap(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getParentMap();
+ }
+
+ AnalysisContext *getAnalysisContext(const Decl *D) {
+ return AnaCtxMgr.getContext(D);
+ }
+
+ AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
+ return AnaCtxMgr.getContext(D, TU);
+ }
+
+ const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
+ LocationContext const *Parent,
+ const Stmt *S,
+ const CFGBlock *Blk, unsigned Idx) {
+ return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ }
+
+ // Get the top level stack frame.
+ const StackFrameContext *getStackFrame(Decl const *D,
+ idx::TranslationUnit *TU) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
+ }
+
+ // Get a stack frame with parent.
+ StackFrameContext const *getStackFrame(const Decl *D,
+ LocationContext const *Parent,
+ const Stmt *S,
+ const CFGBlock *Blk, unsigned Idx) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S,
+ Blk,Idx);
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
new file mode 100644
index 0000000..a4327e1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -0,0 +1,201 @@
+//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- 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 BasicValueFactory, a class that manages the lifetime
+// of APSInt objects and symbolic constraints used by ExprEngine
+// and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
+#define LLVM_CLANG_GR_BASICVALUEFACTORY_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ImmutableList.h"
+
+namespace clang {
+
+namespace ento {
+
+ class GRState;
+
+class CompoundValData : public llvm::FoldingSetNode {
+ QualType T;
+ llvm::ImmutableList<SVal> L;
+
+public:
+ CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
+ : T(t), L(l) {}
+
+ typedef llvm::ImmutableList<SVal>::iterator iterator;
+ iterator begin() const { return L.begin(); }
+ iterator end() const { return L.end(); }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
+ llvm::ImmutableList<SVal> L);
+
+ void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
+};
+
+class LazyCompoundValData : public llvm::FoldingSetNode {
+ const void *store;
+ const TypedRegion *region;
+public:
+ LazyCompoundValData(const void *st, const TypedRegion *r)
+ : store(st), region(r) {}
+
+ const void *getStore() const { return store; }
+ const TypedRegion *getRegion() const { return region; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const void *store,
+ const TypedRegion *region);
+
+ void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
+};
+
+class BasicValueFactory {
+ typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
+ APSIntSetTy;
+
+ ASTContext& Ctx;
+ llvm::BumpPtrAllocator& BPAlloc;
+
+ APSIntSetTy APSIntSet;
+ void* PersistentSVals;
+ void* PersistentSValPairs;
+
+ llvm::ImmutableList<SVal>::Factory SValListFactory;
+ llvm::FoldingSet<CompoundValData> CompoundValDataSet;
+ llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
+
+public:
+ BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
+ : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
+ SValListFactory(Alloc) {}
+
+ ~BasicValueFactory();
+
+ ASTContext& getContext() const { return Ctx; }
+
+ const llvm::APSInt& getValue(const llvm::APSInt& X);
+ const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
+ const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
+ const llvm::APSInt& getValue(uint64_t X, QualType T);
+
+ /// Convert - Create a new persistent APSInt with the same value as 'From'
+ /// but with the bitwidth and signedness of 'To'.
+ const llvm::APSInt &Convert(const llvm::APSInt& To,
+ const llvm::APSInt& From) {
+
+ if (To.isUnsigned() == From.isUnsigned() &&
+ To.getBitWidth() == From.getBitWidth())
+ return From;
+
+ return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned());
+ }
+
+ const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ unsigned bitwidth = Ctx.getTypeSize(T);
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
+
+ if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
+ return From;
+
+ return getValue(From.getSExtValue(), bitwidth, isUnsigned);
+ }
+
+ const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
+ QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
+ return getValue(X, T);
+ }
+
+ inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
+ return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned()));
+ }
+
+ inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
+ return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned()));
+ }
+
+ inline const llvm::APSInt& getMaxValue(QualType T) {
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
+ return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
+ }
+
+ inline const llvm::APSInt& getMinValue(QualType T) {
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
+ return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
+ }
+
+ inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
+ llvm::APSInt X = V;
+ ++X;
+ return getValue(X);
+ }
+
+ inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
+ llvm::APSInt X = V;
+ --X;
+ return getValue(X);
+ }
+
+ inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
+ return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
+ }
+
+ inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
+ return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
+ }
+
+ inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
+ return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
+ }
+
+ inline const llvm::APSInt& getTruthValue(bool b) {
+ return getTruthValue(b, Ctx.getLogicalOperationType());
+ }
+
+ const CompoundValData *getCompoundValData(QualType T,
+ llvm::ImmutableList<SVal> Vals);
+
+ const LazyCompoundValData *getLazyCompoundValData(const void *store,
+ const TypedRegion *region);
+
+ llvm::ImmutableList<SVal> getEmptySValList() {
+ return SValListFactory.getEmptyList();
+ }
+
+ llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
+ return SValListFactory.add(X, L);
+ }
+
+ const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt& V1,
+ const llvm::APSInt& V2);
+
+ const std::pair<SVal, uintptr_t>&
+ getPersistentSValWithData(const SVal& V, uintptr_t Data);
+
+ const std::pair<SVal, SVal>&
+ getPersistentSValPair(const SVal& V1, const SVal& V2);
+
+ const SVal* getPersistentSVal(SVal X);
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
new file mode 100644
index 0000000..7d0fdfb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
@@ -0,0 +1,59 @@
+//==- BlockCounter.h - ADT for counting block visits ---------------*- 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 BlockCounter, an abstract data type used to count
+// the number of times a given block has been visited along a path
+// analyzed by CoreEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_BLOCKCOUNTER
+#define LLVM_CLANG_GR_BLOCKCOUNTER
+
+namespace llvm {
+ class BumpPtrAllocator;
+}
+
+namespace clang {
+
+class StackFrameContext;
+
+namespace ento {
+
+class BlockCounter {
+ void* Data;
+
+ BlockCounter(void* D) : Data(D) {}
+
+public:
+ BlockCounter() : Data(0) {}
+
+ unsigned getNumVisited(const StackFrameContext *CallSite,
+ unsigned BlockID) const;
+
+ class Factory {
+ void* F;
+ public:
+ Factory(llvm::BumpPtrAllocator& Alloc);
+ ~Factory();
+
+ BlockCounter GetEmptyCounter();
+ BlockCounter IncrementCount(BlockCounter BC,
+ const StackFrameContext *CallSite,
+ unsigned BlockID);
+ };
+
+ friend class Factory;
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
new file mode 100644
index 0000000..22c2027
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
@@ -0,0 +1,324 @@
+//== Checker.h - Abstract interface for checkers -----------------*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines Checker and CheckerVisitor, classes used for creating
+// domain-specific checks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_CHECKER
+#define LLVM_CLANG_GR_CHECKER
+
+#include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+//===----------------------------------------------------------------------===//
+// Checker interface.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+
+namespace ento {
+
+class CheckerContext {
+ ExplodedNodeSet &Dst;
+ StmtNodeBuilder &B;
+ ExprEngine &Eng;
+ ExplodedNode *Pred;
+ SaveAndRestore<bool> OldSink;
+ const void *checkerTag;
+ SaveAndRestore<ProgramPoint::Kind> OldPointKind;
+ SaveOr OldHasGen;
+ const GRState *ST;
+ const Stmt *statement;
+ const unsigned size;
+public:
+ bool *respondsToCallback;
+public:
+ CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
+ ExprEngine &eng, ExplodedNode *pred,
+ const void *tag, ProgramPoint::Kind K,
+ bool *respondsToCB = 0,
+ const Stmt *stmt = 0, const GRState *st = 0)
+ : Dst(dst), B(builder), Eng(eng), Pred(pred),
+ OldSink(B.BuildSinks),
+ checkerTag(tag),
+ OldPointKind(B.PointKind, K),
+ OldHasGen(B.hasGeneratedNode),
+ ST(st), statement(stmt), size(Dst.size()),
+ respondsToCallback(respondsToCB) {}
+
+ ~CheckerContext();
+
+ ExprEngine &getEngine() {
+ return Eng;
+ }
+
+ AnalysisManager &getAnalysisManager() {
+ return Eng.getAnalysisManager();
+ }
+
+ ConstraintManager &getConstraintManager() {
+ return Eng.getConstraintManager();
+ }
+
+ StoreManager &getStoreManager() {
+ return Eng.getStoreManager();
+ }
+
+ ExplodedNodeSet &getNodeSet() { return Dst; }
+ StmtNodeBuilder &getNodeBuilder() { return B; }
+ ExplodedNode *&getPredecessor() { return Pred; }
+ const GRState *getState() { return ST ? ST : B.GetState(Pred); }
+
+ ASTContext &getASTContext() {
+ return Eng.getContext();
+ }
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
+
+ SourceManager &getSourceManager() {
+ return getBugReporter().getSourceManager();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return Eng.getSValBuilder();
+ }
+
+ ExplodedNode *generateNode(bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, getState(), false,
+ checkerTag);
+ if (N && autoTransition)
+ Dst.Add(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true, const void *tag = 0) {
+ assert(state);
+ ExplodedNode *N = generateNodeImpl(stmt, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+ bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
+ const void *tag = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
+ return generateNodeImpl(stmt, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ ExplodedNode *generateSink(const GRState *state = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ return generateNodeImpl(statement, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ void addTransition(ExplodedNode *node) {
+ Dst.Add(node);
+ }
+
+ void addTransition(const GRState *state, const void *tag = 0) {
+ assert(state);
+ // If the 'state' is not new, we need to check if the cached state 'ST'
+ // is new.
+ if (state != getState() || (ST && ST != B.GetState(Pred)))
+ // state is new or equals to ST.
+ generateNode(state, true, tag);
+ else
+ Dst.Add(Pred);
+ }
+
+ void EmitReport(BugReport *R) {
+ Eng.getBugReporter().EmitReport(R);
+ }
+
+ AnalysisContext *getCurrentAnalysisContext() const {
+ return Pred->getLocationContext()->getAnalysisContext();
+ }
+
+private:
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink, const void *tag) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ ExplodedNode *pred, bool markAsSink) {
+ ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+};
+
+class Checker {
+private:
+ friend class ExprEngine;
+
+ // FIXME: Remove the 'tag' option.
+ void GR_Visit(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const Stmt *S,
+ ExplodedNode *Pred, void *tag, bool isPrevisit,
+ bool& respondsToCallback) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, &respondsToCallback, S);
+ if (isPrevisit)
+ _PreVisit(C, S);
+ else
+ _PostVisit(C, S);
+ }
+
+ void GR_visitObjCMessage(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const ObjCMessage &msg,
+ ExplodedNode *Pred, void *tag, bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0, msg.getOriginExpr());
+ if (isPrevisit)
+ preVisitObjCMessage(C, msg);
+ else
+ postVisitObjCMessage(C, msg);
+ }
+
+ bool GR_evalNilReceiver(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const ObjCMessage &msg,
+ ExplodedNode *Pred, const GRState *state, void *tag) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
+ 0, msg.getOriginExpr(), state);
+ return evalNilReceiver(C, msg);
+ }
+
+ bool GR_evalCallExpr(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const CallExpr *CE,
+ ExplodedNode *Pred, void *tag) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
+ 0, CE);
+ return evalCallExpr(C, CE);
+ }
+
+ // FIXME: Remove the 'tag' option.
+ void GR_VisitBind(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder, ExprEngine &Eng,
+ const Stmt *StoreE, ExplodedNode *Pred, void *tag,
+ SVal location, SVal val,
+ bool isPrevisit) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isPrevisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0, StoreE);
+ assert(isPrevisit && "Only previsit supported for now.");
+ PreVisitBind(C, StoreE, location, val);
+ }
+
+ // FIXME: Remove the 'tag' option.
+ void GR_visitLocation(ExplodedNodeSet &Dst,
+ StmtNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const Stmt *S,
+ ExplodedNode *Pred, const GRState *state,
+ SVal location,
+ void *tag, bool isLoad) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ isLoad ? ProgramPoint::PreLoadKind :
+ ProgramPoint::PreStoreKind, 0, S, state);
+ visitLocation(C, S, location, isLoad);
+ }
+
+ void GR_evalDeadSymbols(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
+ ExprEngine &Eng, const Stmt *S, ExplodedNode *Pred,
+ SymbolReaper &SymReaper, void *tag) {
+ CheckerContext C(Dst, Builder, Eng, Pred, tag,
+ ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
+ evalDeadSymbols(C, SymReaper);
+ }
+
+public:
+ virtual ~Checker();
+ virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
+ virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
+ virtual void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
+ virtual void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
+ virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
+ bool isLoad) {}
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val) {}
+ virtual void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
+ virtual void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
+ ExprEngine &Eng) {}
+
+ virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
+
+ virtual void VisitBranchCondition(BranchNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const Stmt *Condition, void *tag) {}
+
+ virtual bool evalNilReceiver(CheckerContext &C, ObjCMessage msg) {
+ return false;
+ }
+
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ return false;
+ }
+
+ virtual const GRState *evalAssume(const GRState *state, SVal Cond,
+ bool Assumption, bool *respondsToCallback) {
+ *respondsToCallback = false;
+ return state;
+ }
+
+ virtual bool wantsRegionChangeUpdate(const GRState *state) { return false; }
+
+ virtual const GRState *EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool *respondsToCallback) {
+ *respondsToCallback = false;
+ return state;
+ }
+
+ virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
+ ExprEngine &Eng) {}
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
new file mode 100644
index 0000000..12547e0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -0,0 +1,43 @@
+//== CheckerHelpers.h - Helper functions for checkers ------------*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CheckerVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS
+#define LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+namespace ento {
+
+bool containsMacro(const Stmt *S);
+bool containsEnum(const Stmt *S);
+bool containsStaticLocal(const Stmt *S);
+bool containsBuiltinOffsetOf(const Stmt *S);
+template <class T> bool containsStmt(const Stmt *S) {
+ if (isa<T>(S))
+ return true;
+
+ for (Stmt::const_child_range I = S->children(); I; ++I)
+ if (const Stmt *child = *I)
+ if (containsStmt<T>(child))
+ return true;
+
+ return false;
+}
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def
new file mode 100644
index 0000000..9b3c263
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def
@@ -0,0 +1,48 @@
+//===-- CheckerVisitor.def - Metadata for CheckerVisitor ----------------*-===//
+//
+// 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 AST nodes accepted by the CheckerVisitor class.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef PREVISIT
+#define PREVISIT(NODE, FALLBACK)
+#endif
+
+#ifndef POSTVISIT
+#define POSTVISIT(NODE, FALLBACK)
+#endif
+
+PREVISIT(ArraySubscriptExpr, Stmt)
+PREVISIT(BinaryOperator, Stmt)
+PREVISIT(CallExpr, GenericCall)
+PREVISIT(CompoundAssignOperator, BinaryOperator)
+PREVISIT(CStyleCastExpr, CastExpr)
+PREVISIT(CXXConstCastExpr, CastExpr)
+PREVISIT(CXXDynamicCastExpr, CastExpr)
+PREVISIT(CXXFunctionalCastExpr, CastExpr)
+PREVISIT(CXXOperatorCallExpr, GenericCall)
+PREVISIT(CXXMemberCallExpr, GenericCall)
+PREVISIT(CXXReinterpretCastExpr, CastExpr)
+PREVISIT(CXXStaticCastExpr, CastExpr)
+PREVISIT(DeclStmt, Stmt)
+PREVISIT(ImplicitCastExpr, CastExpr)
+PREVISIT(ObjCAtSynchronizedStmt, Stmt)
+PREVISIT(ReturnStmt, Stmt)
+
+POSTVISIT(BlockExpr, Stmt)
+POSTVISIT(BinaryOperator, Stmt)
+POSTVISIT(CallExpr, GenericCall)
+POSTVISIT(CompoundAssignOperator, BinaryOperator)
+POSTVISIT(CXXOperatorCallExpr, GenericCall)
+POSTVISIT(CXXMemberCallExpr, GenericCall)
+POSTVISIT(ObjCIvarRefExpr, Stmt)
+
+#undef PREVISIT
+#undef POSTVISIT
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h
new file mode 100644
index 0000000..dc76c96
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h
@@ -0,0 +1,103 @@
+//== CheckerVisitor.h - Abstract visitor for checkers ------------*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CheckerVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_CHECKERVISITOR
+#define LLVM_CLANG_GR_CHECKERVISITOR
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+
+namespace clang {
+
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+// Checker visitor interface. Used by subclasses of Checker to specify their
+// own checker visitor logic.
+//===----------------------------------------------------------------------===//
+
+/// CheckerVisitor - This class implements a simple visitor for Stmt subclasses.
+/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
+template<typename ImplClass>
+class CheckerVisitor : public Checker {
+public:
+ virtual void _PreVisit(CheckerContext &C, const Stmt *S) {
+ PreVisit(C, S);
+ }
+
+ virtual void _PostVisit(CheckerContext &C, const Stmt *S) {
+ PostVisit(C, S);
+ }
+
+ void PreVisit(CheckerContext &C, const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default:
+ assert(false && "Unsupport statement.");
+ return;
+
+#define PREVISIT(NAME, FALLBACK) \
+case Stmt::NAME ## Class:\
+static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
+break;
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
+ }
+ }
+
+ void PostVisit(CheckerContext &C, const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default:
+ assert(false && "Unsupport statement.");
+ return;
+
+#define POSTVISIT(NAME, FALLBACK) \
+case Stmt::NAME ## Class:\
+static_cast<ImplClass*>(this)->\
+PostVisit ## NAME(C,static_cast<const NAME*>(S));\
+break;
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
+ }
+ }
+
+ void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE) {
+ static_cast<ImplClass*>(this)->PreVisitStmt(C, CE);
+ }
+ void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE) {
+ static_cast<ImplClass*>(this)->PostVisitStmt(C, CE);
+ }
+
+ void PreVisitStmt(CheckerContext &C, const Stmt *S) {
+ *C.respondsToCallback = false;
+ }
+
+ void PostVisitStmt(CheckerContext &C, const Stmt *S) {
+ *C.respondsToCallback = false;
+ }
+
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) {
+ static_cast<ImplClass*>(this)->PreVisitStmt(C, E);
+ }
+
+#define PREVISIT(NAME, FALLBACK) \
+void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\
+ static_cast<ImplClass*>(this)->PreVisit ## FALLBACK(C, S);\
+}
+#define POSTVISIT(NAME, FALLBACK) \
+void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\
+ static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\
+}
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def"
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
new file mode 100644
index 0000000..199b41a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -0,0 +1,76 @@
+//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the interface to manage constraints on symbolic values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
+#define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H
+
+// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+
+namespace llvm {
+class APSInt;
+}
+
+namespace clang {
+
+namespace ento {
+
+class GRState;
+class GRStateManager;
+class SubEngine;
+class SVal;
+
+class ConstraintManager {
+public:
+ virtual ~ConstraintManager();
+ virtual const GRState *assume(const GRState *state, DefinedSVal Cond,
+ bool Assumption) = 0;
+
+ std::pair<const GRState*, const GRState*> assumeDual(const GRState *state,
+ DefinedSVal Cond) {
+ return std::make_pair(assume(state, Cond, true),
+ assume(state, Cond, false));
+ }
+
+ virtual const llvm::APSInt* getSymVal(const GRState *state,
+ SymbolRef sym) const = 0;
+
+ virtual bool isEqual(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) const = 0;
+
+ virtual const GRState *removeDeadBindings(const GRState *state,
+ SymbolReaper& SymReaper) = 0;
+
+ virtual void print(const GRState *state, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) = 0;
+
+ virtual void EndPath(const GRState *state) {}
+
+ /// canReasonAbout - Not all ConstraintManagers can accurately reason about
+ /// all SVal values. This method returns true if the ConstraintManager can
+ /// reasonably handle a given SVal value. This is typically queried by
+ /// ExprEngine to determine if the value should be replaced with a
+ /// conjured symbolic value in order to recover some precision.
+ virtual bool canReasonAbout(SVal X) const = 0;
+};
+
+ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
+ SubEngine &subengine);
+ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
+ SubEngine &subengine);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
new file mode 100644
index 0000000..800e63a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -0,0 +1,546 @@
+//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic engine for intraprocedural, path-sensitive,
+// dataflow analysis via graph reachability.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_COREENGINE
+#define LLVM_CLANG_GR_COREENGINE
+
+#include "clang/AST/Expr.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+/// CoreEngine - Implements the core logic of the graph-reachability
+/// analysis. It traverses the CFG and generates the ExplodedGraph.
+/// Program "states" are treated as opaque void pointers.
+/// The template class CoreEngine (which subclasses CoreEngine)
+/// provides the matching component to the engine that knows the actual types
+/// for states. Note that this engine only dispatches to transfer functions
+/// at the statement and block-level. The analyses themselves must implement
+/// any transfer function logic and the sub-expression level (if any).
+class CoreEngine {
+ friend class StmtNodeBuilder;
+ friend class GenericNodeBuilderImpl;
+ friend class BranchNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+ friend class CallEnterNodeBuilder;
+ friend class CallExitNodeBuilder;
+
+public:
+ typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
+ BlocksAborted;
+private:
+
+ SubEngine& SubEng;
+
+ /// G - The simulation graph. Each node is a (location,state) pair.
+ llvm::OwningPtr<ExplodedGraph> G;
+
+ /// WList - A set of queued nodes that need to be processed by the
+ /// worklist algorithm. It is up to the implementation of WList to decide
+ /// the order that nodes are processed.
+ WorkList* WList;
+
+ /// BCounterFactory - A factory object for created BlockCounter objects.
+ /// These are used to record for key nodes in the ExplodedGraph the
+ /// number of times different CFGBlocks have been visited along a path.
+ BlockCounter::Factory BCounterFactory;
+
+ /// The locations where we stopped doing work because we visited a location
+ /// too many times.
+ BlocksAborted blocksAborted;
+
+ void generateNode(const ProgramPoint& Loc, const GRState* State,
+ ExplodedNode* Pred);
+
+ void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
+ void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
+ void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
+ void HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, ExplodedNode *Pred);
+
+ void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
+ ExplodedNode* Pred);
+ void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
+ unsigned Index, ExplodedNode *Pred);
+ void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
+
+private:
+ CoreEngine(const CoreEngine&); // Do not implement.
+ CoreEngine& operator=(const CoreEngine&);
+
+public:
+ /// Construct a CoreEngine object to analyze the provided CFG using
+ /// a DFS exploration of the exploded graph.
+ CoreEngine(SubEngine& subengine)
+ : SubEng(subengine), G(new ExplodedGraph()),
+ WList(WorkList::makeBFS()),
+ BCounterFactory(G->getAllocator()) {}
+
+ /// Construct a CoreEngine object to analyze the provided CFG and to
+ /// use the provided worklist object to execute the worklist algorithm.
+ /// The CoreEngine object assumes ownership of 'wlist'.
+ CoreEngine(WorkList* wlist, SubEngine& subengine)
+ : SubEng(subengine), G(new ExplodedGraph()), WList(wlist),
+ BCounterFactory(G->getAllocator()) {}
+
+ ~CoreEngine() {
+ delete WList;
+ }
+
+ /// getGraph - Returns the exploded graph.
+ ExplodedGraph& getGraph() { return *G.get(); }
+
+ /// takeGraph - Returns the exploded graph. Ownership of the graph is
+ /// transfered to the caller.
+ ExplodedGraph* takeGraph() { return G.take(); }
+
+ /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
+ /// steps. Returns true if there is still simulation state on the worklist.
+ bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
+ const GRState *InitState);
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst);
+
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return !blocksAborted.empty(); }
+ bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
+
+ WorkList *getWorkList() const { return WList; }
+
+ BlocksAborted::const_iterator blocks_aborted_begin() const {
+ return blocksAborted.begin();
+ }
+ BlocksAborted::const_iterator blocks_aborted_end() const {
+ return blocksAborted.end();
+ }
+};
+
+class StmtNodeBuilder {
+ CoreEngine& Eng;
+ const CFGBlock& B;
+ const unsigned Idx;
+ ExplodedNode* Pred;
+ GRStateManager& Mgr;
+
+public:
+ bool PurgingDeadSymbols;
+ bool BuildSinks;
+ bool hasGeneratedNode;
+ ProgramPoint::Kind PointKind;
+ const void *Tag;
+
+ const GRState* CleanedState;
+
+
+ typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy;
+ DeferredTy Deferred;
+
+ void GenerateAutoTransition(ExplodedNode* N);
+
+public:
+ StmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
+ CoreEngine* e, GRStateManager &mgr);
+
+ ~StmtNodeBuilder();
+
+ ExplodedNode* getPredecessor() const { return Pred; }
+
+ // FIXME: This should not be exposed.
+ WorkList *getWorkList() { return Eng.WList; }
+
+ void SetCleanedState(const GRState* St) {
+ CleanedState = St;
+ }
+
+ BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+
+ unsigned getCurrentBlockCount() const {
+ return getBlockCounter().getNumVisited(
+ Pred->getLocationContext()->getCurrentStackFrame(),
+ B.getBlockID());
+ }
+
+ ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) {
+ hasGeneratedNode = true;
+ return generateNodeInternal(PP, St, Pred);
+ }
+
+ ExplodedNode* generateNode(const Stmt *S, const GRState *St,
+ ExplodedNode *Pred, ProgramPoint::Kind K,
+ const void *tag = 0) {
+ hasGeneratedNode = true;
+
+ if (PurgingDeadSymbols)
+ K = ProgramPoint::PostPurgeDeadSymbolsKind;
+
+ return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag);
+ }
+
+ ExplodedNode* generateNode(const Stmt *S, const GRState *St,
+ ExplodedNode *Pred, const void *tag = 0) {
+ return generateNode(S, St, Pred, PointKind, tag);
+ }
+
+ ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State,
+ ExplodedNode* Pred) {
+ hasGeneratedNode = true;
+ return generateNodeInternal(PP, State, Pred);
+ }
+
+ ExplodedNode*
+ generateNodeInternal(const ProgramPoint &PP, const GRState* State,
+ ExplodedNode* Pred);
+
+ ExplodedNode*
+ generateNodeInternal(const Stmt* S, const GRState* State, ExplodedNode* Pred,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ const void *tag = 0);
+
+ /// getStmt - Return the current block-level expression associated with
+ /// this builder.
+ const Stmt* getStmt() const {
+ CFGStmt CS = B[Idx].getAs<CFGStmt>();
+ if (CS)
+ return CS.getStmt();
+ else
+ return 0;
+ }
+
+ /// getBlock - Return the CFGBlock associated with the block-level expression
+ /// of this builder.
+ const CFGBlock* getBlock() const { return &B; }
+
+ unsigned getIndex() const { return Idx; }
+
+ const GRState* GetState(ExplodedNode* Pred) const {
+ if (Pred == getPredecessor())
+ return CleanedState;
+ else
+ return Pred->getState();
+ }
+
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St) {
+ return MakeNode(Dst, S, Pred, St, PointKind);
+ }
+
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred,
+ const GRState* St, ProgramPoint::Kind K);
+
+ ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St) {
+ bool Tmp = BuildSinks;
+ BuildSinks = true;
+ ExplodedNode* N = MakeNode(Dst, S, Pred, St);
+ BuildSinks = Tmp;
+ return N;
+ }
+};
+
+class BranchNodeBuilder {
+ CoreEngine& Eng;
+ const CFGBlock* Src;
+ const CFGBlock* DstT;
+ const CFGBlock* DstF;
+ ExplodedNode* Pred;
+
+ typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy;
+ DeferredTy Deferred;
+
+ bool GeneratedTrue;
+ bool GeneratedFalse;
+ bool InFeasibleTrue;
+ bool InFeasibleFalse;
+
+public:
+ BranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
+ const CFGBlock* dstF, ExplodedNode* pred, CoreEngine* e)
+ : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
+ GeneratedTrue(false), GeneratedFalse(false),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
+
+ ~BranchNodeBuilder();
+
+ ExplodedNode* getPredecessor() const { return Pred; }
+
+ const ExplodedGraph& getGraph() const { return *Eng.G; }
+
+ BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+
+ ExplodedNode* generateNode(const GRState* State, bool branch);
+
+ const CFGBlock* getTargetBlock(bool branch) const {
+ return branch ? DstT : DstF;
+ }
+
+ void markInfeasible(bool branch) {
+ if (branch)
+ InFeasibleTrue = GeneratedTrue = true;
+ else
+ InFeasibleFalse = GeneratedFalse = true;
+ }
+
+ bool isFeasible(bool branch) {
+ return branch ? !InFeasibleTrue : !InFeasibleFalse;
+ }
+
+ const GRState* getState() const {
+ return getPredecessor()->getState();
+ }
+};
+
+class IndirectGotoNodeBuilder {
+ CoreEngine& Eng;
+ const CFGBlock* Src;
+ const CFGBlock& DispatchBlock;
+ const Expr* E;
+ ExplodedNode* Pred;
+
+public:
+ IndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* e, const CFGBlock* dispatch, CoreEngine* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+
+ class iterator {
+ CFGBlock::const_succ_iterator I;
+
+ friend class IndirectGotoNodeBuilder;
+ iterator(CFGBlock::const_succ_iterator i) : I(i) {}
+ public:
+
+ iterator& operator++() { ++I; return *this; }
+ bool operator!=(const iterator& X) const { return I != X.I; }
+
+ const LabelDecl *getLabel() const {
+ return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl();
+ }
+
+ const CFGBlock *getBlock() const {
+ return *I;
+ }
+ };
+
+ iterator begin() { return iterator(DispatchBlock.succ_begin()); }
+ iterator end() { return iterator(DispatchBlock.succ_end()); }
+
+ ExplodedNode* generateNode(const iterator& I, const GRState* State,
+ bool isSink = false);
+
+ const Expr* getTarget() const { return E; }
+
+ const GRState* getState() const { return Pred->State; }
+};
+
+class SwitchNodeBuilder {
+ CoreEngine& Eng;
+ const CFGBlock* Src;
+ const Expr* Condition;
+ ExplodedNode* Pred;
+
+public:
+ SwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* condition, CoreEngine* eng)
+ : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
+
+ class iterator {
+ CFGBlock::const_succ_reverse_iterator I;
+
+ friend class SwitchNodeBuilder;
+ iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
+
+ public:
+ iterator& operator++() { ++I; return *this; }
+ bool operator!=(const iterator &X) const { return I != X.I; }
+ bool operator==(const iterator &X) const { return I == X.I; }
+
+ const CaseStmt* getCase() const {
+ return llvm::cast<CaseStmt>((*I)->getLabel());
+ }
+
+ const CFGBlock* getBlock() const {
+ return *I;
+ }
+ };
+
+ iterator begin() { return iterator(Src->succ_rbegin()+1); }
+ iterator end() { return iterator(Src->succ_rend()); }
+
+ const SwitchStmt *getSwitch() const {
+ return llvm::cast<SwitchStmt>(Src->getTerminator());
+ }
+
+ ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State);
+
+ ExplodedNode* generateDefaultCaseNode(const GRState* State,
+ bool isSink = false);
+
+ const Expr* getCondition() const { return Condition; }
+
+ const GRState* getState() const { return Pred->State; }
+};
+
+class GenericNodeBuilderImpl {
+protected:
+ CoreEngine &engine;
+ ExplodedNode *pred;
+ ProgramPoint pp;
+ llvm::SmallVector<ExplodedNode*, 2> sinksGenerated;
+
+ ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred,
+ ProgramPoint programPoint, bool asSink);
+
+ GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
+ : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {}
+
+public:
+ bool hasGeneratedNode;
+
+ WorkList &getWorkList() { return *engine.WList; }
+
+ ExplodedNode* getPredecessor() const { return pred; }
+
+ BlockCounter getBlockCounter() const {
+ return engine.WList->getBlockCounter();
+ }
+
+ const llvm::SmallVectorImpl<ExplodedNode*> &sinks() const {
+ return sinksGenerated;
+ }
+};
+
+template <typename PP_T>
+class GenericNodeBuilder : public GenericNodeBuilderImpl {
+public:
+ GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p)
+ : GenericNodeBuilderImpl(eng, pr, p) {}
+
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+ const void *tag, bool asSink) {
+ return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag),
+ asSink);
+ }
+
+ const PP_T &getProgramPoint() const { return cast<PP_T>(pp); }
+};
+
+class EndOfFunctionNodeBuilder {
+ CoreEngine &Eng;
+ const CFGBlock& B;
+ ExplodedNode* Pred;
+
+public:
+ bool hasGeneratedNode;
+
+public:
+ EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e)
+ : Eng(*e), B(*b), Pred(N), hasGeneratedNode(false) {}
+
+ ~EndOfFunctionNodeBuilder();
+
+ WorkList &getWorkList() { return *Eng.WList; }
+
+ ExplodedNode* getPredecessor() const { return Pred; }
+
+ BlockCounter getBlockCounter() const {
+ return Eng.WList->getBlockCounter();
+ }
+
+ unsigned getCurrentBlockCount() const {
+ return getBlockCounter().getNumVisited(
+ Pred->getLocationContext()->getCurrentStackFrame(),
+ B.getBlockID());
+ }
+
+ ExplodedNode* generateNode(const GRState* State, const void *tag = 0,
+ ExplodedNode *P = 0);
+
+ void GenerateCallExitNode(const GRState *state);
+
+ const CFGBlock* getBlock() const { return &B; }
+
+ const GRState* getState() const {
+ return getPredecessor()->getState();
+ }
+};
+
+class CallEnterNodeBuilder {
+ CoreEngine &Eng;
+
+ const ExplodedNode *Pred;
+
+ // The call site. For implicit automatic object dtor, this is the trigger
+ // statement.
+ const Stmt *CE;
+
+ // The context of the callee.
+ const StackFrameContext *CalleeCtx;
+
+ // The parent block of the CallExpr.
+ const CFGBlock *Block;
+
+ // The CFGBlock index of the CallExpr.
+ unsigned Index;
+
+public:
+ CallEnterNodeBuilder(CoreEngine &eng, const ExplodedNode *pred,
+ const Stmt *s, const StackFrameContext *callee,
+ const CFGBlock *blk, unsigned idx)
+ : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
+
+ const GRState *getState() const { return Pred->getState(); }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+
+ const Stmt *getCallExpr() const { return CE; }
+
+ const StackFrameContext *getCalleeContext() const { return CalleeCtx; }
+
+ const CFGBlock *getBlock() const { return Block; }
+
+ unsigned getIndex() const { return Index; }
+
+ void generateNode(const GRState *state);
+};
+
+class CallExitNodeBuilder {
+ CoreEngine &Eng;
+ const ExplodedNode *Pred;
+
+public:
+ CallExitNodeBuilder(CoreEngine &eng, const ExplodedNode *pred)
+ : Eng(eng), Pred(pred) {}
+
+ const ExplodedNode *getPredecessor() const { return Pred; }
+
+ const GRState *getState() const { return Pred->getState(); }
+
+ void generateNode(const GRState *state);
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
new file mode 100644
index 0000000..732a40cb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -0,0 +1,106 @@
+//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the Environment and EnvironmentManager classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_ENVIRONMENT_H
+#define LLVM_CLANG_GR_ENVIRONMENT_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+
+class LiveVariables;
+
+namespace ento {
+
+class EnvironmentManager;
+class SValBuilder;
+
+/// Environment - An immutable map from Stmts to their current
+/// symbolic values (SVals).
+///
+class Environment {
+private:
+ friend class EnvironmentManager;
+
+ // Type definitions.
+ typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
+
+ // Data.
+ BindingsTy ExprBindings;
+
+ Environment(BindingsTy eb)
+ : ExprBindings(eb) {}
+
+ SVal lookupExpr(const Stmt* E) const;
+
+public:
+ typedef BindingsTy::iterator iterator;
+ iterator begin() const { return ExprBindings.begin(); }
+ iterator end() const { return ExprBindings.end(); }
+
+
+ /// GetSVal - Fetches the current binding of the expression in the
+ /// Environment.
+ SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder) const;
+
+ /// Profile - Profile the contents of an Environment object for use
+ /// in a FoldingSet.
+ static void Profile(llvm::FoldingSetNodeID& ID, const Environment* env) {
+ env->ExprBindings.Profile(ID);
+ }
+
+ /// Profile - Used to profile the contents of this object for inclusion
+ /// in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, this);
+ }
+
+ bool operator==(const Environment& RHS) const {
+ return ExprBindings == RHS.ExprBindings;
+ }
+};
+
+class EnvironmentManager {
+private:
+ typedef Environment::BindingsTy::Factory FactoryTy;
+ FactoryTy F;
+
+public:
+ EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
+ ~EnvironmentManager() {}
+
+ Environment getInitialEnvironment() {
+ return Environment(F.getEmptyMap());
+ }
+
+ /// Bind the value 'V' to the statement 'S'.
+ Environment bindExpr(Environment Env, const Stmt *S, SVal V,
+ bool Invalidate);
+
+ /// Bind the location 'location' and value 'V' to the statement 'S'. This
+ /// is used when simulating loads/stores.
+ Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
+ SVal V);
+
+ Environment removeDeadBindings(Environment Env,
+ SymbolReaper &SymReaper, const GRState *ST,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
new file mode 100644
index 0000000..e5d6876
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -0,0 +1,469 @@
+//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- 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 template classes ExplodedNode and ExplodedGraph,
+// which represent a path-sensitive, intra-procedural "exploded graph."
+// See "Precise interprocedural dataflow analysis via graph reachability"
+// by Reps, Horwitz, and Sagiv
+// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
+// exploded graph.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_EXPLODEDGRAPH
+#define LLVM_CLANG_GR_EXPLODEDGRAPH
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/Support/Casting.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+
+namespace clang {
+
+class CFG;
+
+namespace ento {
+
+class ExplodedGraph;
+
+//===----------------------------------------------------------------------===//
+// ExplodedGraph "implementation" classes. These classes are not typed to
+// contain a specific kind of state. Typed-specialized versions are defined
+// on top of these classes.
+//===----------------------------------------------------------------------===//
+
+// ExplodedNode is not constified all over the engine because we need to add
+// successors to it at any time after creating it.
+
+class ExplodedNode : public llvm::FoldingSetNode {
+ friend class ExplodedGraph;
+ friend class CoreEngine;
+ friend class StmtNodeBuilder;
+ friend class BranchNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+
+ class NodeGroup {
+ enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
+ uintptr_t P;
+
+ unsigned getKind() const {
+ return P & 0x1;
+ }
+
+ void* getPtr() const {
+ assert (!getFlag());
+ return reinterpret_cast<void*>(P & ~Mask);
+ }
+
+ ExplodedNode *getNode() const {
+ return reinterpret_cast<ExplodedNode*>(getPtr());
+ }
+
+ public:
+ NodeGroup() : P(0) {}
+
+ ExplodedNode **begin() const;
+
+ ExplodedNode **end() const;
+
+ unsigned size() const;
+
+ bool empty() const { return (P & ~Mask) == 0; }
+
+ void addNode(ExplodedNode* N, ExplodedGraph &G);
+
+ void replaceNode(ExplodedNode *node);
+
+ void setFlag() {
+ assert(P == 0);
+ P = AuxFlag;
+ }
+
+ bool getFlag() const {
+ return P & AuxFlag ? true : false;
+ }
+ };
+
+ /// Location - The program location (within a function body) associated
+ /// with this node.
+ const ProgramPoint Location;
+
+ /// State - The state associated with this node.
+ const GRState* State;
+
+ /// Preds - The predecessors of this node.
+ NodeGroup Preds;
+
+ /// Succs - The successors of this node.
+ NodeGroup Succs;
+
+public:
+
+ explicit ExplodedNode(const ProgramPoint& loc, const GRState* state)
+ : Location(loc), State(state) {
+ const_cast<GRState*>(State)->incrementReferenceCount();
+ }
+
+ ~ExplodedNode() {
+ const_cast<GRState*>(State)->decrementReferenceCount();
+ }
+
+ /// getLocation - Returns the edge associated with the given node.
+ ProgramPoint getLocation() const { return Location; }
+
+ const LocationContext *getLocationContext() const {
+ return getLocation().getLocationContext();
+ }
+
+ const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
+
+ CFG &getCFG() const { return *getLocationContext()->getCFG(); }
+
+ ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
+
+ LiveVariables &getLiveVariables() const {
+ return *getLocationContext()->getLiveVariables();
+ }
+
+ const GRState* getState() const { return State; }
+
+ template <typename T>
+ const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ProgramPoint& Loc, const GRState* state) {
+ ID.Add(Loc);
+ ID.AddPointer(state);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, getLocation(), getState());
+ }
+
+ /// addPredeccessor - Adds a predecessor to the current node, and
+ /// in tandem add this node as a successor of the other node.
+ void addPredecessor(ExplodedNode* V, ExplodedGraph &G);
+
+ unsigned succ_size() const { return Succs.size(); }
+ unsigned pred_size() const { return Preds.size(); }
+ bool succ_empty() const { return Succs.empty(); }
+ bool pred_empty() const { return Preds.empty(); }
+
+ bool isSink() const { return Succs.getFlag(); }
+ void markAsSink() { Succs.setFlag(); }
+
+ ExplodedNode* getFirstPred() {
+ return pred_empty() ? NULL : *(pred_begin());
+ }
+
+ const ExplodedNode* getFirstPred() const {
+ return const_cast<ExplodedNode*>(this)->getFirstPred();
+ }
+
+ // Iterators over successor and predecessor vertices.
+ typedef ExplodedNode** succ_iterator;
+ typedef const ExplodedNode* const * const_succ_iterator;
+ typedef ExplodedNode** pred_iterator;
+ typedef const ExplodedNode* const * const_pred_iterator;
+
+ pred_iterator pred_begin() { return Preds.begin(); }
+ pred_iterator pred_end() { return Preds.end(); }
+
+ const_pred_iterator pred_begin() const {
+ return const_cast<ExplodedNode*>(this)->pred_begin();
+ }
+ const_pred_iterator pred_end() const {
+ return const_cast<ExplodedNode*>(this)->pred_end();
+ }
+
+ succ_iterator succ_begin() { return Succs.begin(); }
+ succ_iterator succ_end() { return Succs.end(); }
+
+ const_succ_iterator succ_begin() const {
+ return const_cast<ExplodedNode*>(this)->succ_begin();
+ }
+ const_succ_iterator succ_end() const {
+ return const_cast<ExplodedNode*>(this)->succ_end();
+ }
+
+ // For debugging.
+
+public:
+
+ class Auditor {
+ public:
+ virtual ~Auditor();
+ virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst) = 0;
+ };
+
+ static void SetAuditor(Auditor* A);
+
+private:
+ void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
+ void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
+};
+
+// FIXME: Is this class necessary?
+class InterExplodedGraphMap {
+ llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
+ friend class ExplodedGraph;
+
+public:
+ ExplodedNode* getMappedNode(const ExplodedNode* N) const;
+
+ InterExplodedGraphMap() {}
+ virtual ~InterExplodedGraphMap() {}
+};
+
+class ExplodedGraph {
+protected:
+ friend class CoreEngine;
+
+ // Type definitions.
+ typedef llvm::SmallVector<ExplodedNode*,2> RootsTy;
+ typedef llvm::SmallVector<ExplodedNode*,10> EndNodesTy;
+
+ /// Roots - The roots of the simulation graph. Usually there will be only
+ /// one, but clients are free to establish multiple subgraphs within a single
+ /// SimulGraph. Moreover, these subgraphs can often merge when paths from
+ /// different roots reach the same state at the same program location.
+ RootsTy Roots;
+
+ /// EndNodes - The nodes in the simulation graph which have been
+ /// specially marked as the endpoint of an abstract simulation path.
+ EndNodesTy EndNodes;
+
+ /// Nodes - The nodes in the graph.
+ llvm::FoldingSet<ExplodedNode> Nodes;
+
+ /// BVC - Allocator and context for allocating nodes and their predecessor
+ /// and successor groups.
+ BumpVectorContext BVC;
+
+ /// NumNodes - The number of nodes in the graph.
+ unsigned NumNodes;
+
+ /// A list of recently allocated nodes that can potentially be recycled.
+ void *recentlyAllocatedNodes;
+
+ /// A list of nodes that can be reused.
+ void *freeNodes;
+
+ /// A flag that indicates whether nodes should be recycled.
+ bool reclaimNodes;
+
+public:
+ /// getNode - Retrieve the node associated with a (Location,State) pair,
+ /// where the 'Location' is a ProgramPoint in the CFG. If no node for
+ /// this pair exists, it is created. IsNew is set to true if
+ /// the node was freshly created.
+
+ ExplodedNode* getNode(const ProgramPoint& L, const GRState *State,
+ bool* IsNew = 0);
+
+ ExplodedGraph* MakeEmptyGraph() const {
+ return new ExplodedGraph();
+ }
+
+ /// addRoot - Add an untyped node to the set of roots.
+ ExplodedNode* addRoot(ExplodedNode* V) {
+ Roots.push_back(V);
+ return V;
+ }
+
+ /// addEndOfPath - Add an untyped node to the set of EOP nodes.
+ ExplodedNode* addEndOfPath(ExplodedNode* V) {
+ EndNodes.push_back(V);
+ return V;
+ }
+
+ ExplodedGraph()
+ : NumNodes(0), recentlyAllocatedNodes(0),
+ freeNodes(0), reclaimNodes(false) {}
+
+ ~ExplodedGraph();
+
+ unsigned num_roots() const { return Roots.size(); }
+ unsigned num_eops() const { return EndNodes.size(); }
+
+ bool empty() const { return NumNodes == 0; }
+ unsigned size() const { return NumNodes; }
+
+ // Iterators.
+ typedef ExplodedNode NodeTy;
+ typedef llvm::FoldingSet<ExplodedNode> AllNodesTy;
+ typedef NodeTy** roots_iterator;
+ typedef NodeTy* const * const_roots_iterator;
+ typedef NodeTy** eop_iterator;
+ typedef NodeTy* const * const_eop_iterator;
+ typedef AllNodesTy::iterator node_iterator;
+ typedef AllNodesTy::const_iterator const_node_iterator;
+
+ node_iterator nodes_begin() { return Nodes.begin(); }
+
+ node_iterator nodes_end() { return Nodes.end(); }
+
+ const_node_iterator nodes_begin() const { return Nodes.begin(); }
+
+ const_node_iterator nodes_end() const { return Nodes.end(); }
+
+ roots_iterator roots_begin() { return Roots.begin(); }
+
+ roots_iterator roots_end() { return Roots.end(); }
+
+ const_roots_iterator roots_begin() const { return Roots.begin(); }
+
+ const_roots_iterator roots_end() const { return Roots.end(); }
+
+ eop_iterator eop_begin() { return EndNodes.begin(); }
+
+ eop_iterator eop_end() { return EndNodes.end(); }
+
+ const_eop_iterator eop_begin() const { return EndNodes.begin(); }
+
+ const_eop_iterator eop_end() const { return EndNodes.end(); }
+
+ llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
+ BumpVectorContext &getNodeAllocator() { return BVC; }
+
+ typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
+
+ std::pair<ExplodedGraph*, InterExplodedGraphMap*>
+ Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
+ llvm::DenseMap<const void*, const void*> *InverseMap = 0) const;
+
+ ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg,
+ const ExplodedNode* const * NEnd,
+ InterExplodedGraphMap *M,
+ llvm::DenseMap<const void*, const void*> *InverseMap) const;
+
+ /// Enable tracking of recently allocated nodes for potential reclamation
+ /// when calling reclaimRecentlyAllocatedNodes().
+ void enableNodeReclamation() { reclaimNodes = true; }
+
+ /// Reclaim "uninteresting" nodes created since the last time this method
+ /// was called.
+ void reclaimRecentlyAllocatedNodes();
+};
+
+class ExplodedNodeSet {
+ typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
+ ImplTy Impl;
+
+public:
+ ExplodedNodeSet(ExplodedNode* N) {
+ assert (N && !static_cast<ExplodedNode*>(N)->isSink());
+ Impl.insert(N);
+ }
+
+ ExplodedNodeSet() {}
+
+ inline void Add(ExplodedNode* N) {
+ if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
+ }
+
+ ExplodedNodeSet& operator=(const ExplodedNodeSet &X) {
+ Impl = X.Impl;
+ return *this;
+ }
+
+ typedef ImplTy::iterator iterator;
+ typedef ImplTy::const_iterator const_iterator;
+
+ unsigned size() const { return Impl.size(); }
+ bool empty() const { return Impl.empty(); }
+
+ void clear() { Impl.clear(); }
+ void insert(const ExplodedNodeSet &S) {
+ if (empty())
+ Impl = S.Impl;
+ else
+ Impl.insert(S.begin(), S.end());
+ }
+
+ inline iterator begin() { return Impl.begin(); }
+ inline iterator end() { return Impl.end(); }
+
+ inline const_iterator begin() const { return Impl.begin(); }
+ inline const_iterator end() const { return Impl.end(); }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+// GraphTraits
+
+namespace llvm {
+ template<> struct GraphTraits<clang::ento::ExplodedNode*> {
+ typedef clang::ento::ExplodedNode NodeType;
+ typedef NodeType::succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeType*> nodes_iterator;
+
+ static inline NodeType* getEntryNode(NodeType* N) {
+ return N;
+ }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ return N->succ_begin();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ return N->succ_end();
+ }
+
+ static inline nodes_iterator nodes_begin(NodeType* N) {
+ return df_begin(N);
+ }
+
+ static inline nodes_iterator nodes_end(NodeType* N) {
+ return df_end(N);
+ }
+ };
+
+ template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
+ typedef const clang::ento::ExplodedNode NodeType;
+ typedef NodeType::const_succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeType*> nodes_iterator;
+
+ static inline NodeType* getEntryNode(NodeType* N) {
+ return N;
+ }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ return N->succ_begin();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ return N->succ_end();
+ }
+
+ static inline nodes_iterator nodes_begin(NodeType* N) {
+ return df_begin(N);
+ }
+
+ static inline nodes_iterator nodes_end(NodeType* N) {
+ return df_end(N);
+ }
+ };
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
new file mode 100644
index 0000000..767644a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -0,0 +1,550 @@
+//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a meta-engine for path-sensitive dataflow analysis that
+// is built on CoreEngine, but provides the boilerplate to execute transfer
+// functions and build the ExplodedGraph at the expression level.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_EXPRENGINE
+#define LLVM_CLANG_GR_EXPRENGINE
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
+
+namespace clang {
+
+class ObjCForCollectionStmt;
+
+namespace ento {
+
+class AnalysisManager;
+class Checker;
+
+class ExprEngine : public SubEngine {
+ AnalysisManager &AMgr;
+
+ CoreEngine Engine;
+
+ /// G - the simulation graph.
+ ExplodedGraph& G;
+
+ /// Builder - The current StmtNodeBuilder which is used when building the
+ /// nodes for a given statement.
+ StmtNodeBuilder* Builder;
+
+ /// StateMgr - Object that manages the data for all created states.
+ GRStateManager StateMgr;
+
+ /// SymMgr - Object that manages the symbol information.
+ SymbolManager& SymMgr;
+
+ /// svalBuilder - SValBuilder object that creates SVals from expressions.
+ SValBuilder &svalBuilder;
+
+ /// EntryNode - The immediate predecessor node.
+ ExplodedNode* EntryNode;
+
+ /// CleanedState - The state for EntryNode "cleaned" of all dead
+ /// variables and symbols (as determined by a liveness analysis).
+ const GRState* CleanedState;
+
+ /// currentStmt - The current block-level statement.
+ const Stmt* currentStmt;
+
+ // Obj-C Class Identifiers.
+ IdentifierInfo* NSExceptionII;
+
+ // Obj-C Selectors.
+ Selector* NSExceptionInstanceRaiseSelectors;
+ Selector RaiseSel;
+
+ enum CallbackKind {
+ PreVisitStmtCallback,
+ PostVisitStmtCallback,
+ processAssumeCallback,
+ EvalRegionChangesCallback
+ };
+
+ typedef uint32_t CallbackTag;
+
+ /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub'
+ /// argument can be used to differentiate callbacks that depend on another
+ /// value from a small set of possibilities, such as statement classes.
+ static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) {
+ assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits");
+ return K | (Sub << 8);
+ }
+
+ typedef llvm::DenseMap<void *, unsigned> CheckerMap;
+ typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
+ typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
+
+ /// A registration map from checker tag to the index into the
+ /// ordered checkers vector.
+ CheckerMap CheckerM;
+
+ /// An ordered vector of checkers that are called when evaluating
+ /// various expressions and statements.
+ CheckersOrdered Checkers;
+
+ /// A map used for caching the checkers that respond to the callback for
+ /// a particular callback tag.
+ CheckersOrderedCache COCache;
+
+ /// The BugReporter associated with this engine. It is important that
+ /// this object be placed at the very end of member variables so that its
+ /// destructor is called before the rest of the ExprEngine is destroyed.
+ GRBugReporter BR;
+
+ llvm::OwningPtr<TransferFuncs> TF;
+
+public:
+ ExprEngine(AnalysisManager &mgr, TransferFuncs *tf);
+
+ ~ExprEngine();
+
+ void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
+ Engine.ExecuteWorkList(L, Steps, 0);
+ }
+
+ /// Execute the work list with an initial state. Nodes that reaches the exit
+ /// of the function are added into the Dst set, which represent the exit
+ /// state of the function call.
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst) {
+ Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
+ }
+
+ /// getContext - Return the ASTContext associated with this analysis.
+ ASTContext& getContext() const { return AMgr.getASTContext(); }
+
+ virtual AnalysisManager &getAnalysisManager() { return AMgr; }
+
+ SValBuilder &getSValBuilder() { return svalBuilder; }
+
+ TransferFuncs& getTF() { return *TF; }
+
+ BugReporter& getBugReporter() { return BR; }
+
+ StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
+
+ // FIXME: Remove once TransferFuncs is no longer referenced.
+ void setTransferFunction(TransferFuncs* tf);
+
+ /// ViewGraph - Visualize the ExplodedGraph created by executing the
+ /// simulation.
+ void ViewGraph(bool trim = false);
+
+ void ViewGraph(ExplodedNode** Beg, ExplodedNode** End);
+
+ /// getInitialState - Return the initial state used for the root vertex
+ /// in the ExplodedGraph.
+ const GRState* getInitialState(const LocationContext *InitLoc);
+
+ ExplodedGraph& getGraph() { return G; }
+ const ExplodedGraph& getGraph() const { return G; }
+
+ template <typename CHECKER>
+ void registerCheck(CHECKER *check) {
+ unsigned entry = Checkers.size();
+ void *tag = CHECKER::getTag();
+ Checkers.push_back(std::make_pair(tag, check));
+ CheckerM[tag] = entry;
+ }
+
+ Checker *lookupChecker(void *tag) const;
+
+ template <typename CHECKER>
+ CHECKER *getChecker() const {
+ return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
+ }
+
+ /// processCFGElement - Called by CoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a CFG element.
+ void processCFGElement(const CFGElement E, StmtNodeBuilder& builder);
+
+ void ProcessStmt(const CFGStmt S, StmtNodeBuilder &builder);
+
+ void ProcessInitializer(const CFGInitializer I, StmtNodeBuilder &builder);
+
+ void ProcessImplicitDtor(const CFGImplicitDtor D, StmtNodeBuilder &builder);
+
+ void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
+ StmtNodeBuilder &builder);
+ void ProcessBaseDtor(const CFGBaseDtor D, StmtNodeBuilder &builder);
+ void ProcessMemberDtor(const CFGMemberDtor D, StmtNodeBuilder &builder);
+ void ProcessTemporaryDtor(const CFGTemporaryDtor D,
+ StmtNodeBuilder &builder);
+
+ /// Called by CoreEngine when processing the entrance of a CFGBlock.
+ virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+ GenericNodeBuilder<BlockEntrance> &nodeBuilder);
+
+ /// ProcessBranch - Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a branch condition.
+ void processBranch(const Stmt* Condition, const Stmt* Term,
+ BranchNodeBuilder& builder);
+
+ /// processIndirectGoto - Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ void processIndirectGoto(IndirectGotoNodeBuilder& builder);
+
+ /// ProcessSwitch - Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a switch statement.
+ void processSwitch(SwitchNodeBuilder& builder);
+
+ /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
+ void processEndOfFunction(EndOfFunctionNodeBuilder& builder);
+
+ /// Generate the entry node of the callee.
+ void processCallEnter(CallEnterNodeBuilder &builder);
+
+ /// Generate the first post callsite node.
+ void processCallExit(CallExitNodeBuilder &builder);
+
+ /// Called by CoreEngine when the analysis worklist has terminated.
+ void processEndWorklist(bool hasWorkRemaining);
+
+ /// evalAssume - Callback function invoked by the ConstraintManager when
+ /// making assumptions about state values.
+ const GRState *processAssume(const GRState *state, SVal cond,bool assumption);
+
+ /// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ bool wantsRegionChangeUpdate(const GRState* state);
+
+ /// processRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ const GRState* processRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End);
+
+ virtual GRStateManager& getStateManager() { return StateMgr; }
+
+ StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
+
+ ConstraintManager& getConstraintManager() {
+ return StateMgr.getConstraintManager();
+ }
+
+ // FIXME: Remove when we migrate over to just using SValBuilder.
+ BasicValueFactory& getBasicVals() {
+ return StateMgr.getBasicVals();
+ }
+ const BasicValueFactory& getBasicVals() const {
+ return StateMgr.getBasicVals();
+ }
+
+ // FIXME: Remove when we migrate over to just using ValueManager.
+ SymbolManager& getSymbolManager() { return SymMgr; }
+ const SymbolManager& getSymbolManager() const { return SymMgr; }
+
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return Engine.wasBlockAborted(); }
+ bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
+ bool hasWorkRemaining() const {
+ return wasBlockAborted() || Engine.getWorkList()->hasWork();
+ }
+
+ const CoreEngine &getCoreEngine() const { return Engine; }
+
+protected:
+ const GRState* GetState(ExplodedNode* N) {
+ return N == EntryNode ? CleanedState : N->getState();
+ }
+
+public:
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ const void *tag = 0);
+
+ /// CheckerVisit - Dispatcher for performing checker-specific logic
+ /// at specific statements.
+ void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ CallbackKind Kind);
+
+ void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, bool isPrevisit);
+
+ bool CheckerEvalCall(const CallExpr *CE,
+ ExplodedNodeSet &Dst,
+ ExplodedNode *Pred);
+
+ void CheckerEvalNilReceiver(const ObjCMessage &msg,
+ ExplodedNodeSet &Dst,
+ const GRState *state,
+ ExplodedNode *Pred);
+
+ void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location, SVal val,
+ bool isPrevisit);
+
+ /// Visit - Transfer function logic for all statements. Dispatches to
+ /// other functions that handle specific kinds of statements.
+ void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// VisitArraySubscriptExpr - Transfer function for array accesses.
+ void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* Ex,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitAsmStmt - Transfer function logic for inline asm.
+ void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ void VisitAsmStmtHelperOutputs(const AsmStmt* A,
+ AsmStmt::const_outputs_iterator I,
+ AsmStmt::const_outputs_iterator E,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ void VisitAsmStmtHelperInputs(const AsmStmt* A,
+ AsmStmt::const_inputs_iterator I,
+ AsmStmt::const_inputs_iterator E,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// VisitBlockExpr - Transfer function logic for BlockExprs.
+ void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// VisitBinaryOperator - Transfer function logic for binary operators.
+ void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+
+ /// VisitCall - Transfer function for function calls.
+ void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+ CallExpr::const_arg_iterator AI,
+ CallExpr::const_arg_iterator AE,
+ ExplodedNodeSet& Dst);
+
+ /// VisitCast - Transfer function logic for all casts (implicit and explicit).
+ void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
+ void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
+ void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// VisitDeclStmt - Transfer function logic for DeclStmts.
+ void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
+ void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ /// VisitCondInit - Transfer function for handling the initialization
+ /// of a condition variable in an IfStmt, SwitchStmt, etc.
+ void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred,
+ ExplodedNodeSet& Dst);
+
+ void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitLogicalExpr - Transfer function logic for '&&', '||'
+ void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitMemberExpr - Transfer function for member expressions.
+ void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// Transfer function logic for ObjCAtSynchronizedStmts.
+ void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ /// Transfer function logic for computing the lvalue of an Objective-C ivar.
+ void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitObjCForCollectionStmt - Transfer function logic for
+ /// ObjCForCollectionStmt.
+ void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
+
+ void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, SVal ElementV);
+
+ /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
+ void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+ void VisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Src,
+ ExplodedNodeSet& Dst);
+
+ /// VisitReturnStmt - Transfer function logic for return statements.
+ void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitOffsetOfExpr - Transfer function for offsetof.
+ void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
+ void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ /// VisitUnaryOperator - Transfer function logic for unary operators.
+ void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
+
+ void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
+ ExplodedNodeSet & Dst);
+
+ void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+ VisitCXXConstructExpr(expr, 0, Pred, Dst);
+ }
+
+ void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitCXXDestructor(const CXXDestructorDecl *DD,
+ const MemRegion *Dest, const Stmt *S,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitAggExpr(const Expr *E, const MemRegion *Dest, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// Create a C++ temporary object for an rvalue.
+ void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// Synthesize CXXThisRegion.
+ const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD,
+ const StackFrameContext *SFC);
+
+ const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl,
+ const StackFrameContext *frameCtx);
+
+ /// Evaluate arguments with a work list algorithm.
+ void evalArguments(ConstExprIterator AI, ConstExprIterator AE,
+ const FunctionProtoType *FnType,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ bool FstArgAsLValue = false);
+
+ /// Evaluate method call itself. Used for CXXMethodCallExpr and
+ /// CXXOperatorCallExpr.
+ void evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
+ const Expr *ThisExpr, ExplodedNode *Pred,
+ ExplodedNodeSet &Src, ExplodedNodeSet &Dst);
+
+ /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
+ /// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
+ /// with those assumptions.
+ void evalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
+ const Expr *Ex);
+
+ SVal evalMinus(SVal X) {
+ return X.isValid() ? svalBuilder.evalMinus(cast<NonLoc>(X)) : X;
+ }
+
+ SVal evalComplement(SVal X) {
+ return X.isValid() ? svalBuilder.evalComplement(cast<NonLoc>(X)) : X;
+ }
+
+public:
+
+ SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
+ NonLoc L, NonLoc R, QualType T) {
+ return svalBuilder.evalBinOpNN(state, op, L, R, T);
+ }
+
+ SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op,
+ NonLoc L, SVal R, QualType T) {
+ return R.isValid() ? svalBuilder.evalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
+ }
+
+ SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
+ SVal LHS, SVal RHS, QualType T) {
+ return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
+ }
+
+protected:
+ void evalObjCMessage(ExplodedNodeSet& Dst, const ObjCMessage &msg,
+ ExplodedNode* Pred, const GRState *state) {
+ assert (Builder && "StmtNodeBuilder must be defined.");
+ getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
+ }
+
+ const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
+ bool branchTaken);
+
+ /// evalBind - Handle the semantics of binding a value to a specific location.
+ /// This method is used by evalStore, VisitDeclStmt, and others.
+ void evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
+ const GRState* St, SVal location, SVal Val,
+ bool atDeclInit = false);
+
+public:
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ // FIXME: Comment on the meaning of the arguments, when 'St' may not
+ // be the same as Pred->state, and when 'location' may not be the
+ // same as state->getLValue(Ex).
+ /// Simulate a read of the result of Ex.
+ void evalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
+ const GRState* St, SVal location, const void *tag = 0,
+ QualType LoadTy = QualType());
+
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ void evalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
+ ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
+ const void *tag = 0);
+private:
+ void evalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
+ const GRState* St, SVal location, const void *tag,
+ QualType LoadTy);
+
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ void evalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
+ const GRState* St, SVal location,
+ const void *tag, bool isLoad);
+
+ bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h
new file mode 100644
index 0000000..18e39d9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h
@@ -0,0 +1,80 @@
+//===-- ExprEngineBuilders.h - "Builder" classes for ExprEngine ---*- 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 smart builder "references" which are used to marshal
+// builders between ExprEngine objects and their related components.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_EXPRENGINE_BUILDERS
+#define LLVM_CLANG_GR_EXPRENGINE_BUILDERS
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+namespace clang {
+
+namespace ento {
+
+class StmtNodeBuilderRef {
+ ExplodedNodeSet &Dst;
+ StmtNodeBuilder &B;
+ ExprEngine& Eng;
+ ExplodedNode* Pred;
+ const GRState* state;
+ const Stmt* stmt;
+ const unsigned OldSize;
+ const bool AutoCreateNode;
+ SaveAndRestore<bool> OldSink;
+ SaveOr OldHasGen;
+
+private:
+ friend class ExprEngine;
+
+ StmtNodeBuilderRef(); // do not implement
+ void operator=(const StmtNodeBuilderRef&); // do not implement
+
+ StmtNodeBuilderRef(ExplodedNodeSet &dst,
+ StmtNodeBuilder &builder,
+ ExprEngine& eng,
+ ExplodedNode* pred,
+ const GRState *st,
+ const Stmt* s, bool auto_create_node)
+ : Dst(dst), B(builder), Eng(eng), Pred(pred),
+ state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node),
+ OldSink(B.BuildSinks), OldHasGen(B.hasGeneratedNode) {}
+
+public:
+
+ ~StmtNodeBuilderRef() {
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+ if (!B.BuildSinks && Dst.size() == OldSize && !B.hasGeneratedNode) {
+ if (AutoCreateNode)
+ B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
+ else
+ Dst.Add(Pred);
+ }
+ }
+
+ const GRState *getState() { return state; }
+
+ GRStateManager& getStateManager() {
+ return Eng.getStateManager();
+ }
+
+ ExplodedNode* MakeNode(const GRState* state) {
+ return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
new file mode 100644
index 0000000..37694da
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
@@ -0,0 +1,793 @@
+//== GRState.h - Path-sensitive "State" for tracking values -----*- 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 SymbolRef, ExprBindKey, and GRState*.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_VALUESTATE_H
+#define LLVM_CLANG_GR_VALUESTATE_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+class APSInt;
+class BumpPtrAllocator;
+class raw_ostream;
+}
+
+namespace clang {
+class ASTContext;
+
+namespace ento {
+
+class GRStateManager;
+class Checker;
+
+typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
+ SubEngine&);
+typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
+
+//===----------------------------------------------------------------------===//
+// GRStateTrait - Traits used by the Generic Data Map of a GRState.
+//===----------------------------------------------------------------------===//
+
+template <typename T> struct GRStatePartialTrait;
+
+template <typename T> struct GRStateTrait {
+ typedef typename T::data_type data_type;
+ static inline void* GDMIndex() { return &T::TagInt; }
+ static inline void* MakeVoidPtr(data_type D) { return (void*) D; }
+ static inline data_type MakeData(void* const* P) {
+ return P ? (data_type) *P : (data_type) 0;
+ }
+};
+
+class GRStateManager;
+
+/// GRState - This class encapsulates:
+///
+/// 1. A mapping from expressions to values (Environment)
+/// 2. A mapping from locations to values (Store)
+/// 3. Constraints on symbolic values (GenericDataMap)
+///
+/// Together these represent the "abstract state" of a program.
+///
+/// GRState is intended to be used as a functional object; that is,
+/// once it is created and made "persistent" in a FoldingSet, its
+/// values will never change.
+class GRState : public llvm::FoldingSetNode {
+public:
+ typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
+ typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
+
+private:
+ void operator=(const GRState& R) const; // Do not implement.
+
+ friend class GRStateManager;
+ friend class ExplodedGraph;
+ friend class ExplodedNode;
+
+ GRStateManager *stateMgr;
+ Environment Env; // Maps a Stmt to its current SVal.
+ Store store; // Maps a location to its current value.
+ GenericDataMap GDM; // Custom data stored by a client of this class.
+ unsigned refCount;
+
+ /// makeWithStore - Return a GRState with the same values as the current
+ /// state with the exception of using the specified Store.
+ const GRState *makeWithStore(const StoreRef &store) const;
+
+ void setStore(const StoreRef &storeRef);
+
+public:
+
+ /// This ctor is used when creating the first GRState object.
+ GRState(GRStateManager *mgr, const Environment& env,
+ StoreRef st, GenericDataMap gdm);
+
+ /// Copy ctor - We must explicitly define this or else the "Next" ptr
+ /// in FoldingSetNode will also get copied.
+ GRState(const GRState& RHS);
+
+ ~GRState();
+
+ /// Return the GRStateManager associated with this state.
+ GRStateManager &getStateManager() const { return *stateMgr; }
+
+ /// Return true if this state is referenced by a persistent ExplodedNode.
+ bool referencedByExplodedNode() const { return refCount > 0; }
+
+ /// getEnvironment - Return the environment associated with this state.
+ /// The environment is the mapping from expressions to values.
+ const Environment& getEnvironment() const { return Env; }
+
+ /// Return the store associated with this state. The store
+ /// is a mapping from locations to values.
+ Store getStore() const { return store; }
+
+
+ /// getGDM - Return the generic data map associated with this state.
+ GenericDataMap getGDM() const { return GDM; }
+
+ void setGDM(GenericDataMap gdm) { GDM = gdm; }
+
+ /// Profile - Profile the contents of a GRState object for use in a
+ /// FoldingSet. Two GRState objects are considered equal if they
+ /// have the same Environment, Store, and GenericDataMap.
+ static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) {
+ V->Env.Profile(ID);
+ ID.AddPointer(V->store);
+ V->GDM.Profile(ID);
+ }
+
+ /// Profile - Used to profile the contents of this object for inclusion
+ /// in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, this);
+ }
+
+ BasicValueFactory &getBasicVals() const;
+ SymbolManager &getSymbolManager() const;
+
+ //==---------------------------------------------------------------------==//
+ // Constraints on values.
+ //==---------------------------------------------------------------------==//
+ //
+ // Each GRState records constraints on symbolic values. These constraints
+ // are managed using the ConstraintManager associated with a GRStateManager.
+ // As constraints gradually accrue on symbolic values, added constraints
+ // may conflict and indicate that a state is infeasible (as no real values
+ // could satisfy all the constraints). This is the principal mechanism
+ // for modeling path-sensitivity in ExprEngine/GRState.
+ //
+ // Various "assume" methods form the interface for adding constraints to
+ // symbolic values. A call to 'assume' indicates an assumption being placed
+ // on one or symbolic values. 'assume' methods take the following inputs:
+ //
+ // (1) A GRState object representing the current state.
+ //
+ // (2) The assumed constraint (which is specific to a given "assume" method).
+ //
+ // (3) A binary value "Assumption" that indicates whether the constraint is
+ // assumed to be true or false.
+ //
+ // The output of "assume*" is a new GRState object with the added constraints.
+ // If no new state is feasible, NULL is returned.
+ //
+
+ const GRState *assume(DefinedOrUnknownSVal cond, bool assumption) const;
+
+ /// This method assumes both "true" and "false" for 'cond', and
+ /// returns both corresponding states. It's shorthand for doing
+ /// 'assume' twice.
+ std::pair<const GRState*, const GRState*>
+ assume(DefinedOrUnknownSVal cond) const;
+
+ const GRState *assumeInBound(DefinedOrUnknownSVal idx,
+ DefinedOrUnknownSVal upperBound,
+ bool assumption) const;
+
+ //==---------------------------------------------------------------------==//
+ // Utility methods for getting regions.
+ //==---------------------------------------------------------------------==//
+
+ const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
+
+ //==---------------------------------------------------------------------==//
+ // Binding and retrieving values to/from the environment and symbolic store.
+ //==---------------------------------------------------------------------==//
+
+ /// BindCompoundLiteral - Return the state that has the bindings currently
+ /// in this state plus the bindings for the CompoundLiteral.
+ const GRState *bindCompoundLiteral(const CompoundLiteralExpr* CL,
+ const LocationContext *LC,
+ SVal V) const;
+
+ /// Create a new state by binding the value 'V' to the statement 'S' in the
+ /// state's environment.
+ const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
+
+ /// Create a new state by binding the value 'V' and location 'locaton' to the
+ /// statement 'S' in the state's environment.
+ const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
+ const;
+
+ const GRState *bindDecl(const VarRegion *VR, SVal V) const;
+
+ const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
+
+ const GRState *bindLoc(Loc location, SVal V) const;
+
+ const GRState *bindLoc(SVal location, SVal V) const;
+
+ const GRState *bindDefault(SVal loc, SVal V) const;
+
+ const GRState *unbindLoc(Loc LV) const;
+
+ /// invalidateRegion - Returns the state with bindings for the given region
+ /// cleared from the store. See invalidateRegions.
+ const GRState *invalidateRegion(const MemRegion *R,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS = NULL)
+ const {
+ return invalidateRegions(&R, &R+1, E, BlockCount, IS, false);
+ }
+
+ /// invalidateRegions - Returns the state with bindings for the given regions
+ /// cleared from the store. The regions are provided as a continuous array
+ /// from Begin to End. Optionally invalidates global regions as well.
+ const GRState *invalidateRegions(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const;
+
+ /// enterStackFrame - Returns the state for entry to the given stack frame,
+ /// preserving the current state.
+ const GRState *enterStackFrame(const StackFrameContext *frame) const;
+
+ /// Get the lvalue for a variable reference.
+ Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
+
+ /// Get the lvalue for a StringLiteral.
+ Loc getLValue(const StringLiteral *literal) const;
+
+ Loc getLValue(const CompoundLiteralExpr *literal,
+ const LocationContext *LC) const;
+
+ /// Get the lvalue for an ivar reference.
+ SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
+
+ /// Get the lvalue for a field reference.
+ SVal getLValue(const FieldDecl *decl, SVal Base) const;
+
+ /// Get the lvalue for an array index.
+ SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
+
+ const llvm::APSInt *getSymVal(SymbolRef sym) const;
+
+ /// Returns the SVal bound to the statement 'S' in the state's environment.
+ SVal getSVal(const Stmt* S) const;
+
+ SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
+
+ SVal getSVal(Loc LV, QualType T = QualType()) const;
+
+ /// Returns the "raw" SVal bound to LV before any value simplfication.
+ SVal getRawSVal(Loc LV, QualType T= QualType()) const;
+
+ SVal getSVal(const MemRegion* R) const;
+
+ SVal getSValAsScalarOrLoc(const MemRegion *R) const;
+
+ const llvm::APSInt *getSymVal(SymbolRef sym);
+
+ bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
+
+ bool scanReachableSymbols(const SVal *I, const SVal *E,
+ SymbolVisitor &visitor) const;
+
+ bool scanReachableSymbols(const MemRegion * const *I,
+ const MemRegion * const *E,
+ SymbolVisitor &visitor) const;
+
+ template <typename CB> CB scanReachableSymbols(SVal val) const;
+ template <typename CB> CB scanReachableSymbols(const SVal *beg,
+ const SVal *end) const;
+
+ template <typename CB> CB
+ scanReachableSymbols(const MemRegion * const *beg,
+ const MemRegion * const *end) const;
+
+ //==---------------------------------------------------------------------==//
+ // Accessing the Generic Data Map (GDM).
+ //==---------------------------------------------------------------------==//
+
+ void* const* FindGDM(void* K) const;
+
+ template<typename T>
+ const GRState *add(typename GRStateTrait<T>::key_type K) const;
+
+ template <typename T>
+ typename GRStateTrait<T>::data_type
+ get() const {
+ return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex()));
+ }
+
+ template<typename T>
+ typename GRStateTrait<T>::lookup_type
+ get(typename GRStateTrait<T>::key_type key) const {
+ void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
+ return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
+ }
+
+ template <typename T>
+ typename GRStateTrait<T>::context_type get_context() const;
+
+
+ template<typename T>
+ const GRState *remove(typename GRStateTrait<T>::key_type K) const;
+
+ template<typename T>
+ const GRState *remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) const;
+ template <typename T>
+ const GRState *remove() const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::data_type D) const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E) const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) const;
+
+ template<typename T>
+ bool contains(typename GRStateTrait<T>::key_type key) const {
+ void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
+ return GRStateTrait<T>::Contains(GRStateTrait<T>::MakeData(d), key);
+ }
+
+ // State pretty-printing.
+ class Printer {
+ public:
+ virtual ~Printer() {}
+ virtual void Print(llvm::raw_ostream& Out, const GRState* state,
+ const char* nl, const char* sep) = 0;
+ };
+
+ // Pretty-printing.
+ void print(llvm::raw_ostream& Out, CFG &C, const char *nl = "\n",
+ const char *sep = "") const;
+
+ void printStdErr(CFG &C) const;
+
+ void printDOT(llvm::raw_ostream& Out, CFG &C) const;
+
+private:
+ /// Increments the number of times this state is referenced by ExplodeNodes.
+ void incrementReferenceCount() { ++refCount; }
+
+ /// Decrement the number of times this state is referenced by ExplodeNodes.
+ void decrementReferenceCount() {
+ assert(refCount > 0);
+ --refCount;
+ }
+};
+
+class GRStateSet {
+ typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
+ ImplTy Impl;
+public:
+ GRStateSet() {}
+
+ inline void Add(const GRState* St) {
+ Impl.insert(St);
+ }
+
+ typedef ImplTy::const_iterator iterator;
+
+ inline unsigned size() const { return Impl.size(); }
+ inline bool empty() const { return Impl.empty(); }
+
+ inline iterator begin() const { return Impl.begin(); }
+ inline iterator end() const { return Impl.end(); }
+
+ class AutoPopulate {
+ GRStateSet& S;
+ unsigned StartSize;
+ const GRState* St;
+ public:
+ AutoPopulate(GRStateSet& s, const GRState* st)
+ : S(s), StartSize(S.size()), St(st) {}
+
+ ~AutoPopulate() {
+ if (StartSize == S.size())
+ S.Add(St);
+ }
+ };
+};
+
+//===----------------------------------------------------------------------===//
+// GRStateManager - Factory object for GRStates.
+//===----------------------------------------------------------------------===//
+
+class GRStateManager {
+ friend class GRState;
+ friend class ExprEngine; // FIXME: Remove.
+private:
+ /// Eng - The SubEngine that owns this state manager.
+ SubEngine *Eng; /* Can be null. */
+
+ EnvironmentManager EnvMgr;
+ llvm::OwningPtr<StoreManager> StoreMgr;
+ llvm::OwningPtr<ConstraintManager> ConstraintMgr;
+
+ GRState::GenericDataMap::Factory GDMFactory;
+
+ typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
+ GDMContextsTy GDMContexts;
+
+ /// Printers - A set of printer objects used for pretty-printing a GRState.
+ /// GRStateManager owns these objects.
+ std::vector<GRState::Printer*> Printers;
+
+ /// StateSet - FoldingSet containing all the states created for analyzing
+ /// a particular function. This is used to unique states.
+ llvm::FoldingSet<GRState> StateSet;
+
+ /// Object that manages the data for all created SVals.
+ llvm::OwningPtr<SValBuilder> svalBuilder;
+
+ /// A BumpPtrAllocator to allocate states.
+ llvm::BumpPtrAllocator &Alloc;
+
+ /// A vector of recently allocated GRStates that can potentially be
+ /// reused.
+ std::vector<GRState *> recentlyAllocatedStates;
+
+ /// A vector of GRStates that we can reuse.
+ std::vector<GRState *> freeStates;
+
+public:
+ GRStateManager(ASTContext& Ctx,
+ StoreManagerCreator CreateStoreManager,
+ ConstraintManagerCreator CreateConstraintManager,
+ llvm::BumpPtrAllocator& alloc,
+ SubEngine &subeng)
+ : Eng(&subeng),
+ EnvMgr(alloc),
+ GDMFactory(alloc),
+ svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
+ Alloc(alloc) {
+ StoreMgr.reset((*CreateStoreManager)(*this));
+ ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
+ }
+
+ GRStateManager(ASTContext& Ctx,
+ StoreManagerCreator CreateStoreManager,
+ ConstraintManager* ConstraintManagerPtr,
+ llvm::BumpPtrAllocator& alloc)
+ : Eng(0),
+ EnvMgr(alloc),
+ GDMFactory(alloc),
+ svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
+ Alloc(alloc) {
+ StoreMgr.reset((*CreateStoreManager)(*this));
+ ConstraintMgr.reset(ConstraintManagerPtr);
+ }
+
+ ~GRStateManager();
+
+ const GRState *getInitialState(const LocationContext *InitLoc);
+
+ ASTContext &getContext() { return svalBuilder->getContext(); }
+ const ASTContext &getContext() const { return svalBuilder->getContext(); }
+
+ BasicValueFactory &getBasicVals() {
+ return svalBuilder->getBasicValueFactory();
+ }
+ const BasicValueFactory& getBasicVals() const {
+ return svalBuilder->getBasicValueFactory();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return *svalBuilder;
+ }
+
+ SymbolManager &getSymbolManager() {
+ return svalBuilder->getSymbolManager();
+ }
+ const SymbolManager &getSymbolManager() const {
+ return svalBuilder->getSymbolManager();
+ }
+
+ llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
+
+ MemRegionManager& getRegionManager() {
+ return svalBuilder->getRegionManager();
+ }
+ const MemRegionManager& getRegionManager() const {
+ return svalBuilder->getRegionManager();
+ }
+
+ StoreManager& getStoreManager() { return *StoreMgr; }
+ ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
+ SubEngine* getOwningEngine() { return Eng; }
+
+ const GRState* removeDeadBindings(const GRState* St,
+ const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper);
+
+ /// Marshal a new state for the callee in another translation unit.
+ /// 'state' is owned by the caller's engine.
+ const GRState *MarshalState(const GRState *state, const StackFrameContext *L);
+
+public:
+
+ SVal ArrayToPointer(Loc Array) {
+ return StoreMgr->ArrayToPointer(Array);
+ }
+
+ // Methods that manipulate the GDM.
+ const GRState* addGDM(const GRState* St, void* Key, void* Data);
+ const GRState *removeGDM(const GRState *state, void *Key);
+
+ // Methods that query & manipulate the Store.
+
+ void iterBindings(const GRState* state, StoreManager::BindingsHandler& F) {
+ StoreMgr->iterBindings(state->getStore(), F);
+ }
+
+ const GRState* getPersistentState(GRState& Impl);
+
+ /// Periodically called by ExprEngine to recycle GRStates that were
+ /// created but never used for creating an ExplodedNode.
+ void recycleUnusedStates();
+
+ //==---------------------------------------------------------------------==//
+ // Generic Data Map methods.
+ //==---------------------------------------------------------------------==//
+ //
+ // GRStateManager and GRState support a "generic data map" that allows
+ // different clients of GRState objects to embed arbitrary data within a
+ // GRState object. The generic data map is essentially an immutable map
+ // from a "tag" (that acts as the "key" for a client) and opaque values.
+ // Tags/keys and values are simply void* values. The typical way that clients
+ // generate unique tags are by taking the address of a static variable.
+ // Clients are responsible for ensuring that data values referred to by a
+ // the data pointer are immutable (and thus are essentially purely functional
+ // data).
+ //
+ // The templated methods below use the GRStateTrait<T> class
+ // to resolve keys into the GDM and to return data values to clients.
+ //
+
+ // Trait based GDM dispatch.
+ template <typename T>
+ const GRState* set(const GRState* st, typename GRStateTrait<T>::data_type D) {
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(D));
+ }
+
+ template<typename T>
+ const GRState* set(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type V,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
+ }
+
+ template <typename T>
+ const GRState* add(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Add(st->get<T>(), K, C)));
+ }
+
+ template <typename T>
+ const GRState* remove(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
+ }
+
+ template <typename T>
+ const GRState *remove(const GRState *st) {
+ return removeGDM(st, GRStateTrait<T>::GDMIndex());
+ }
+
+ void* FindGDMContext(void* index,
+ void* (*CreateContext)(llvm::BumpPtrAllocator&),
+ void (*DeleteContext)(void*));
+
+ template <typename T>
+ typename GRStateTrait<T>::context_type get_context() {
+ void* p = FindGDMContext(GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::CreateContext,
+ GRStateTrait<T>::DeleteContext);
+
+ return GRStateTrait<T>::MakeContext(p);
+ }
+
+ const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) {
+ return ConstraintMgr->getSymVal(St, sym);
+ }
+
+ void EndPath(const GRState* St) {
+ ConstraintMgr->EndPath(St);
+ }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Out-of-line method definitions for GRState.
+//===----------------------------------------------------------------------===//
+
+inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) {
+ return getStateManager().getSymVal(this, sym);
+}
+
+inline const VarRegion* GRState::getRegion(const VarDecl *D,
+ const LocationContext *LC) const {
+ return getStateManager().getRegionManager().getVarRegion(D, LC);
+}
+
+inline const GRState *GRState::assume(DefinedOrUnknownSVal Cond,
+ bool Assumption) const {
+ if (Cond.isUnknown())
+ return this;
+
+ return getStateManager().ConstraintMgr->assume(this, cast<DefinedSVal>(Cond),
+ Assumption);
+}
+
+inline std::pair<const GRState*, const GRState*>
+GRState::assume(DefinedOrUnknownSVal Cond) const {
+ if (Cond.isUnknown())
+ return std::make_pair(this, this);
+
+ return getStateManager().ConstraintMgr->assumeDual(this,
+ cast<DefinedSVal>(Cond));
+}
+
+inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
+ return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
+}
+
+inline Loc GRState::getLValue(const VarDecl* VD,
+ const LocationContext *LC) const {
+ return getStateManager().StoreMgr->getLValueVar(VD, LC);
+}
+
+inline Loc GRState::getLValue(const StringLiteral *literal) const {
+ return getStateManager().StoreMgr->getLValueString(literal);
+}
+
+inline Loc GRState::getLValue(const CompoundLiteralExpr *literal,
+ const LocationContext *LC) const {
+ return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
+}
+
+inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
+ return getStateManager().StoreMgr->getLValueIvar(D, Base);
+}
+
+inline SVal GRState::getLValue(const FieldDecl* D, SVal Base) const {
+ return getStateManager().StoreMgr->getLValueField(D, Base);
+}
+
+inline SVal GRState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
+ if (NonLoc *N = dyn_cast<NonLoc>(&Idx))
+ return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
+ return UnknownVal();
+}
+
+inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
+ return getStateManager().getSymVal(this, sym);
+}
+
+inline SVal GRState::getSVal(const Stmt* Ex) const {
+ return Env.getSVal(Ex, *getStateManager().svalBuilder);
+}
+
+inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
+ if (const Expr *Ex = dyn_cast<Expr>(S)) {
+ QualType T = Ex->getType();
+ if (Loc::isLocType(T) || T->isIntegerType())
+ return getSVal(S);
+ }
+
+ return UnknownVal();
+}
+
+inline SVal GRState::getRawSVal(Loc LV, QualType T) const {
+ return getStateManager().StoreMgr->Retrieve(getStore(), LV, T);
+}
+
+inline SVal GRState::getSVal(const MemRegion* R) const {
+ return getStateManager().StoreMgr->Retrieve(getStore(), loc::MemRegionVal(R));
+}
+
+inline BasicValueFactory &GRState::getBasicVals() const {
+ return getStateManager().getBasicVals();
+}
+
+inline SymbolManager &GRState::getSymbolManager() const {
+ return getStateManager().getSymbolManager();
+}
+
+template<typename T>
+const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
+ return getStateManager().add<T>(this, K, get_context<T>());
+}
+
+template <typename T>
+typename GRStateTrait<T>::context_type GRState::get_context() const {
+ return getStateManager().get_context<T>();
+}
+
+template<typename T>
+const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const {
+ return getStateManager().remove<T>(this, K, get_context<T>());
+}
+
+template<typename T>
+const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) const {
+ return getStateManager().remove<T>(this, K, C);
+}
+
+template <typename T>
+const GRState *GRState::remove() const {
+ return getStateManager().remove<T>(this);
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
+ return getStateManager().set<T>(this, D);
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E) const {
+ return getStateManager().set<T>(this, K, E, get_context<T>());
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) const {
+ return getStateManager().set<T>(this, K, E, C);
+}
+
+template <typename CB>
+CB GRState::scanReachableSymbols(SVal val) const {
+ CB cb(this);
+ scanReachableSymbols(val, cb);
+ return cb;
+}
+
+template <typename CB>
+CB GRState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
+
+template <typename CB>
+CB GRState::scanReachableSymbols(const MemRegion * const *beg,
+ const MemRegion * const *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
new file mode 100644
index 0000000..411441f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
@@ -0,0 +1,165 @@
+//==- GRStateTrait.h - Partial implementations of GRStateTrait -----*- 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 partial implementations of template specializations of
+// the class GRStateTrait<>. GRStateTrait<> is used by GRState to implement
+// set/get methods for mapulating a GRState's generic data map.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_GR_GRSTATETRAIT_H
+#define LLVM_CLANG_GR_GRSTATETRAIT_H
+
+namespace llvm {
+ class BumpPtrAllocator;
+ template <typename K, typename D, typename I> class ImmutableMap;
+ template <typename K, typename I> class ImmutableSet;
+ template <typename T> class ImmutableList;
+ template <typename T> class ImmutableListImpl;
+}
+
+namespace clang {
+
+namespace ento {
+ template <typename T> struct GRStatePartialTrait;
+
+ // Partial-specialization for ImmutableMap.
+
+ template <typename Key, typename Data, typename Info>
+ struct GRStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
+ typedef llvm::ImmutableMap<Key,Data,Info> data_type;
+ typedef typename data_type::Factory& context_type;
+ typedef Key key_type;
+ typedef Data value_type;
+ typedef const value_type* lookup_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ }
+ static inline void* MakeVoidPtr(data_type B) {
+ return B.getRoot();
+ }
+ static lookup_type Lookup(data_type B, key_type K) {
+ return B.lookup(K);
+ }
+ static data_type Set(data_type B, key_type K, value_type E,context_type F){
+ return F.add(B, K, E);
+ }
+
+ static data_type Remove(data_type B, key_type K, context_type F) {
+ return F.remove(B, K);
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+
+
+ // Partial-specialization for ImmutableSet.
+
+ template <typename Key, typename Info>
+ struct GRStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
+ typedef llvm::ImmutableSet<Key,Info> data_type;
+ typedef typename data_type::Factory& context_type;
+ typedef Key key_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ }
+
+ static inline void* MakeVoidPtr(data_type B) {
+ return B.getRoot();
+ }
+
+ static data_type Add(data_type B, key_type K, context_type F) {
+ return F.add(B, K);
+ }
+
+ static data_type Remove(data_type B, key_type K, context_type F) {
+ return F.remove(B, K);
+ }
+
+ static bool Contains(data_type B, key_type K) {
+ return B.contains(K);
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+
+ // Partial-specialization for ImmutableList.
+
+ template <typename T>
+ struct GRStatePartialTrait< llvm::ImmutableList<T> > {
+ typedef llvm::ImmutableList<T> data_type;
+ typedef T key_type;
+ typedef typename data_type::Factory& context_type;
+
+ static data_type Add(data_type L, key_type K, context_type F) {
+ return F.add(K, L);
+ }
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
+ : data_type(0);
+ }
+
+ static inline void* MakeVoidPtr(data_type D) {
+ return (void*) D.getInternalPointer();
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+
+ // Partial specialization for bool.
+ template <> struct GRStatePartialTrait<bool> {
+ typedef bool data_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return (bool) (uintptr_t) p;
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
new file mode 100644
index 0000000..8d19b51
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -0,0 +1,1092 @@
+//== MemRegion.h - Abstract memory regions for static analysis --*- 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 MemRegion and its subclasses. MemRegion defines a
+// partially-typed abstraction of memory useful for path-sensitive dataflow
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_MEMREGION_H
+#define LLVM_CLANG_GR_MEMREGION_H
+
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <string>
+
+namespace llvm {
+class BumpPtrAllocator;
+class raw_ostream;
+}
+
+namespace clang {
+
+class LocationContext;
+class StackFrameContext;
+
+namespace ento {
+
+class MemRegionManager;
+class MemSpaceRegion;
+class SValBuilder;
+class VarRegion;
+class CodeTextRegion;
+
+/// Represent a region's offset within the top level base region.
+class RegionOffset {
+ /// The base region.
+ const MemRegion *R;
+
+ /// The bit offset within the base region. It shouldn't be negative.
+ int64_t Offset;
+
+public:
+ RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
+ RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
+
+ const MemRegion *getRegion() const { return R; }
+ int64_t getOffset() const { return Offset; }
+};
+
+//===----------------------------------------------------------------------===//
+// Base region classes.
+//===----------------------------------------------------------------------===//
+
+/// MemRegion - The root abstract class for all memory regions.
+class MemRegion : public llvm::FoldingSetNode {
+ friend class MemRegionManager;
+public:
+ enum Kind {
+ // Memory spaces.
+ GenericMemSpaceRegionKind,
+ StackLocalsSpaceRegionKind,
+ StackArgumentsSpaceRegionKind,
+ HeapSpaceRegionKind,
+ UnknownSpaceRegionKind,
+ NonStaticGlobalSpaceRegionKind,
+ StaticGlobalSpaceRegionKind,
+ BEG_GLOBAL_MEMSPACES = NonStaticGlobalSpaceRegionKind,
+ END_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
+ BEG_MEMSPACES = GenericMemSpaceRegionKind,
+ END_MEMSPACES = StaticGlobalSpaceRegionKind,
+ // Untyped regions.
+ SymbolicRegionKind,
+ AllocaRegionKind,
+ // Typed regions.
+ BEG_TYPED_REGIONS,
+ FunctionTextRegionKind = BEG_TYPED_REGIONS,
+ BlockTextRegionKind,
+ BlockDataRegionKind,
+ CompoundLiteralRegionKind,
+ CXXThisRegionKind,
+ StringRegionKind,
+ ElementRegionKind,
+ // Decl Regions.
+ BEG_DECL_REGIONS,
+ VarRegionKind = BEG_DECL_REGIONS,
+ FieldRegionKind,
+ ObjCIvarRegionKind,
+ END_DECL_REGIONS = ObjCIvarRegionKind,
+ CXXTempObjectRegionKind,
+ CXXBaseObjectRegionKind,
+ END_TYPED_REGIONS = CXXBaseObjectRegionKind
+ };
+
+private:
+ const Kind kind;
+
+protected:
+ MemRegion(Kind k) : kind(k) {}
+ virtual ~MemRegion();
+
+public:
+ ASTContext &getContext() const;
+
+ virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
+
+ virtual MemRegionManager* getMemRegionManager() const = 0;
+
+ std::string getString() const;
+
+ const MemSpaceRegion *getMemorySpace() const;
+
+ const MemRegion *getBaseRegion() const;
+
+ const MemRegion *StripCasts() const;
+
+ bool hasGlobalsOrParametersStorage() const;
+
+ bool hasStackStorage() const;
+
+ bool hasStackNonParametersStorage() const;
+
+ bool hasStackParametersStorage() const;
+
+ /// Compute the offset within the top level memory object.
+ RegionOffset getAsOffset() const;
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void dump() const;
+
+ Kind getKind() const { return kind; }
+
+ template<typename RegionTy> const RegionTy* getAs() const;
+
+ virtual bool isBoundable() const { return false; }
+
+ static bool classof(const MemRegion*) { return true; }
+};
+
+/// MemSpaceRegion - A memory region that represents and "memory space";
+/// for example, the set of global variables, the stack frame, etc.
+class MemSpaceRegion : public MemRegion {
+protected:
+ friend class MemRegionManager;
+
+ MemRegionManager *Mgr;
+
+ MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
+ : MemRegion(k), Mgr(mgr) {
+ assert(classof(this));
+ }
+
+ MemRegionManager* getMemRegionManager() const { return Mgr; }
+
+public:
+ bool isBoundable() const { return false; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
+ }
+};
+
+class GlobalsSpaceRegion : public MemSpaceRegion {
+protected:
+ GlobalsSpaceRegion(MemRegionManager *mgr, Kind k)
+ : MemSpaceRegion(mgr, k) {}
+public:
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
+ }
+};
+
+class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ friend class MemRegionManager;
+
+ const CodeTextRegion *CR;
+
+ StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
+ : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {}
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ const CodeTextRegion *getCodeRegion() const { return CR; }
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StaticGlobalSpaceRegionKind;
+ }
+};
+
+class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ friend class MemRegionManager;
+
+ NonStaticGlobalSpaceRegion(MemRegionManager *mgr)
+ : GlobalsSpaceRegion(mgr, NonStaticGlobalSpaceRegionKind) {}
+
+public:
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == NonStaticGlobalSpaceRegionKind;
+ }
+};
+
+class HeapSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+
+ HeapSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
+public:
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == HeapSpaceRegionKind;
+ }
+};
+
+class UnknownSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+ UnknownSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+public:
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == UnknownSpaceRegionKind;
+ }
+};
+
+class StackSpaceRegion : public MemSpaceRegion {
+private:
+ const StackFrameContext *SFC;
+
+protected:
+ StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
+ : MemSpaceRegion(mgr, k), SFC(sfc) {
+ assert(classof(this));
+ }
+
+public:
+ const StackFrameContext *getStackFrame() const { return SFC; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= StackLocalsSpaceRegionKind &&
+ k <= StackArgumentsSpaceRegionKind;
+ }
+};
+
+class StackLocalsSpaceRegion : public StackSpaceRegion {
+private:
+ friend class MemRegionManager;
+ StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
+public:
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StackLocalsSpaceRegionKind;
+ }
+};
+
+class StackArgumentsSpaceRegion : public StackSpaceRegion {
+private:
+ friend class MemRegionManager;
+ StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
+public:
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StackArgumentsSpaceRegionKind;
+ }
+};
+
+
+/// SubRegion - A region that subsets another larger region. Most regions
+/// are subclasses of SubRegion.
+class SubRegion : public MemRegion {
+protected:
+ const MemRegion* superRegion;
+ SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
+public:
+ const MemRegion* getSuperRegion() const {
+ return superRegion;
+ }
+
+ /// getExtent - Returns the size of the region in bytes.
+ virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
+ return UnknownVal();
+ }
+
+ MemRegionManager* getMemRegionManager() const;
+
+ bool isSubRegionOf(const MemRegion* R) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() > END_MEMSPACES;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// MemRegion subclasses.
+//===----------------------------------------------------------------------===//
+
+/// AllocaRegion - A region that represents an untyped blob of bytes created
+/// by a call to 'alloca'.
+class AllocaRegion : public SubRegion {
+ friend class MemRegionManager;
+protected:
+ unsigned Cnt; // Block counter. Used to distinguish different pieces of
+ // memory allocated by alloca at the same call site.
+ const Expr* Ex;
+
+ AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion *superRegion)
+ : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
+
+public:
+
+ const Expr* getExpr() const { return Ex; }
+
+ bool isBoundable() const { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex,
+ unsigned Cnt, const MemRegion *superRegion);
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == AllocaRegionKind;
+ }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public SubRegion {
+protected:
+ TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
+
+public:
+ virtual QualType getValueType() const = 0;
+
+ virtual QualType getLocationType() const {
+ // FIXME: We can possibly optimize this later to cache this value.
+ QualType T = getValueType();
+ ASTContext &ctx = getContext();
+ if (T->getAs<ObjCObjectType>())
+ return ctx.getObjCObjectPointerType(T);
+ return ctx.getPointerType(getValueType());
+ }
+
+ QualType getDesugaredValueType(ASTContext &Context) const {
+ QualType T = getValueType();
+ return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
+ }
+
+ QualType getDesugaredLocationType(ASTContext &Context) const {
+ return getLocationType().getDesugaredType(Context);
+ }
+
+ bool isBoundable() const { return true; }
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
+ }
+};
+
+
+class CodeTextRegion : public TypedRegion {
+protected:
+ CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
+public:
+ QualType getValueType() const {
+ assert(0 && "Do not get the object type of a CodeTextRegion.");
+ return QualType();
+ }
+
+ bool isBoundable() const { return false; }
+
+ static bool classof(const MemRegion* R) {
+ Kind k = R->getKind();
+ return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
+ }
+};
+
+/// FunctionTextRegion - A region that represents code texts of function.
+class FunctionTextRegion : public CodeTextRegion {
+ const FunctionDecl *FD;
+public:
+ FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
+ : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
+
+ QualType getLocationType() const {
+ return getContext().getPointerType(FD->getType());
+ }
+
+ const FunctionDecl *getDecl() const {
+ return FD;
+ }
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD,
+ const MemRegion*);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FunctionTextRegionKind;
+ }
+};
+
+
+/// BlockTextRegion - A region that represents code texts of blocks (closures).
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+class BlockTextRegion : public CodeTextRegion {
+ friend class MemRegionManager;
+
+ const BlockDecl *BD;
+ AnalysisContext *AC;
+ CanQualType locTy;
+
+ BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
+ AnalysisContext *ac, const MemRegion* sreg)
+ : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
+
+public:
+ QualType getLocationType() const {
+ return locTy;
+ }
+
+ const BlockDecl *getDecl() const {
+ return BD;
+ }
+
+ AnalysisContext *getAnalysisContext() const { return AC; }
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
+ CanQualType, const AnalysisContext*,
+ const MemRegion*);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockTextRegionKind;
+ }
+};
+
+/// BlockDataRegion - A region that represents a block instance.
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+class BlockDataRegion : public SubRegion {
+ friend class MemRegionManager;
+ const BlockTextRegion *BC;
+ const LocationContext *LC; // Can be null */
+ void *ReferencedVars;
+
+ BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
+ const MemRegion *sreg)
+ : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
+
+public:
+ const BlockTextRegion *getCodeRegion() const { return BC; }
+
+ const BlockDecl *getDecl() const { return BC->getDecl(); }
+
+ class referenced_vars_iterator {
+ const MemRegion * const *R;
+ public:
+ explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {}
+
+ operator const MemRegion * const *() const {
+ return R;
+ }
+
+ const VarRegion* operator*() const {
+ return cast<VarRegion>(*R);
+ }
+
+ bool operator==(const referenced_vars_iterator &I) const {
+ return I.R == R;
+ }
+ bool operator!=(const referenced_vars_iterator &I) const {
+ return I.R != R;
+ }
+ referenced_vars_iterator& operator++() {
+ ++R;
+ return *this;
+ }
+ };
+
+ referenced_vars_iterator referenced_vars_begin() const;
+ referenced_vars_iterator referenced_vars_end() const;
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
+ const LocationContext *, const MemRegion *);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockDataRegionKind;
+ }
+private:
+ void LazyInitializeReferencedVars();
+};
+
+/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
+/// clases, SymbolicRegion represents a region that serves as an alias for
+/// either a real region, a NULL pointer, etc. It essentially is used to
+/// map the concept of symbolic values into the domain of regions. Symbolic
+/// regions do not need to be typed.
+class SymbolicRegion : public SubRegion {
+protected:
+ const SymbolRef sym;
+
+public:
+ SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
+ : SubRegion(sreg, SymbolicRegionKind), sym(s) {}
+
+ SymbolRef getSymbol() const {
+ return sym;
+ }
+
+ bool isBoundable() const { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ SymbolRef sym,
+ const MemRegion* superRegion);
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == SymbolicRegionKind;
+ }
+};
+
+/// StringRegion - Region associated with a StringLiteral.
+class StringRegion : public TypedRegion {
+ friend class MemRegionManager;
+ const StringLiteral* Str;
+protected:
+
+ StringRegion(const StringLiteral* str, const MemRegion* sreg)
+ : TypedRegion(sreg, StringRegionKind), Str(str) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const StringLiteral* Str,
+ const MemRegion* superRegion);
+
+public:
+
+ const StringLiteral* getStringLiteral() const { return Str; }
+
+ QualType getValueType() const {
+ return Str->getType();
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
+ bool isBoundable() const { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == StringRegionKind;
+ }
+};
+
+/// CompoundLiteralRegion - A memory region representing a compound literal.
+/// Compound literals are essentially temporaries that are stack allocated
+/// or in the global constant pool.
+class CompoundLiteralRegion : public TypedRegion {
+private:
+ friend class MemRegionManager;
+ const CompoundLiteralExpr* CL;
+
+ CompoundLiteralRegion(const CompoundLiteralExpr* cl, const MemRegion* sReg)
+ : TypedRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const CompoundLiteralExpr* CL,
+ const MemRegion* superRegion);
+public:
+ QualType getValueType() const {
+ return CL->getType();
+ }
+
+ bool isBoundable() const { return !CL->isFileScope(); }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ const CompoundLiteralExpr* getLiteralExpr() const { return CL; }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CompoundLiteralRegionKind;
+ }
+};
+
+class DeclRegion : public TypedRegion {
+protected:
+ const Decl* D;
+
+ DeclRegion(const Decl* d, const MemRegion* sReg, Kind k)
+ : TypedRegion(sReg, k), D(d) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
+ const MemRegion* superRegion, Kind k);
+
+public:
+ const Decl* getDecl() const { return D; }
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
+ }
+};
+
+class VarRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ // Constructors and private methods.
+ VarRegion(const VarDecl* vd, const MemRegion* sReg)
+ : DeclRegion(vd, sReg, VarRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD,
+ const MemRegion *superRegion) {
+ DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+public:
+ const VarDecl *getDecl() const { return cast<VarDecl>(D); }
+
+ const StackFrameContext *getStackFrame() const;
+
+ QualType getValueType() const {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == VarRegionKind;
+ }
+};
+
+/// CXXThisRegion - Represents the region for the implicit 'this' parameter
+/// in a call to a C++ method. This region doesn't represent the object
+/// referred to by 'this', but rather 'this' itself.
+class CXXThisRegion : public TypedRegion {
+ friend class MemRegionManager;
+ CXXThisRegion(const PointerType *thisPointerTy,
+ const MemRegion *sReg)
+ : TypedRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sReg);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+public:
+ QualType getValueType() const {
+ return QualType(ThisPointerTy, 0);
+ }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CXXThisRegionKind;
+ }
+
+private:
+ const PointerType *ThisPointerTy;
+};
+
+class FieldRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ FieldRegion(const FieldDecl* fd, const MemRegion* sReg)
+ : DeclRegion(fd, sReg, FieldRegionKind) {}
+
+public:
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
+
+ QualType getValueType() const {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+ }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FieldRegionKind;
+ }
+};
+
+class ObjCIvarRegion : public DeclRegion {
+
+ friend class MemRegionManager;
+
+ ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg)
+ : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl* ivd,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
+ }
+
+public:
+ const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
+ QualType getValueType() const { return getDecl()->getType(); }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCIvarRegionKind;
+ }
+};
+//===----------------------------------------------------------------------===//
+// Auxillary data classes for use with MemRegions.
+//===----------------------------------------------------------------------===//
+
+class ElementRegion;
+
+class RegionRawOffset {
+private:
+ friend class ElementRegion;
+
+ const MemRegion *Region;
+ CharUnits Offset;
+
+ RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
+ : Region(reg), Offset(offset) {}
+
+public:
+ // FIXME: Eventually support symbolic offsets.
+ CharUnits getOffset() const { return Offset; }
+ const MemRegion *getRegion() const { return Region; }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+ void dump() const;
+};
+
+class ElementRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ QualType ElementType;
+ NonLoc Index;
+
+ ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
+ : TypedRegion(sReg, ElementRegionKind),
+ ElementType(elementType), Index(Idx) {
+ assert((!isa<nonloc::ConcreteInt>(&Idx) ||
+ cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
+ "The index must be signed");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
+ SVal Idx, const MemRegion* superRegion);
+
+public:
+
+ NonLoc getIndex() const { return Index; }
+
+ QualType getValueType() const {
+ return ElementType;
+ }
+
+ QualType getElementType() const {
+ return ElementType;
+ }
+ /// Compute the offset within the array. The array might also be a subobject.
+ RegionRawOffset getAsArrayOffset() const;
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ElementRegionKind;
+ }
+};
+
+// C++ temporary object associated with an expression.
+class CXXTempObjectRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ Expr const *Ex;
+
+ CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
+ : TypedRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ Expr const *E, const MemRegion *sReg);
+
+public:
+ QualType getValueType() const {
+ return Ex->getType();
+ }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CXXTempObjectRegionKind;
+ }
+};
+
+// CXXBaseObjectRegion represents a base object within a C++ object. It is
+// identified by the base class declaration and the region of its parent object.
+class CXXBaseObjectRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ const CXXRecordDecl *decl;
+
+ CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
+ : TypedRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const CXXRecordDecl *decl, const MemRegion *sReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return decl; }
+
+ QualType getValueType() const;
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXBaseObjectRegionKind;
+ }
+};
+
+template<typename RegionTy>
+const RegionTy* MemRegion::getAs() const {
+ if (const RegionTy* RT = dyn_cast<RegionTy>(this))
+ return RT;
+
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager - Factory object for creating regions.
+//===----------------------------------------------------------------------===//
+
+class MemRegionManager {
+ ASTContext &C;
+ llvm::BumpPtrAllocator& A;
+ llvm::FoldingSet<MemRegion> Regions;
+
+ NonStaticGlobalSpaceRegion *globals;
+
+ llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
+ StackLocalsSpaceRegions;
+ llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
+ StackArgumentsSpaceRegions;
+ llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
+ StaticsGlobalSpaceRegions;
+
+ HeapSpaceRegion *heap;
+ UnknownSpaceRegion *unknown;
+ MemSpaceRegion *code;
+
+public:
+ MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
+ : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {}
+
+ ~MemRegionManager();
+
+ ASTContext &getContext() { return C; }
+
+ llvm::BumpPtrAllocator &getAllocator() { return A; }
+
+ /// getStackLocalsRegion - Retrieve the memory region associated with the
+ /// specified stack frame.
+ const StackLocalsSpaceRegion *
+ getStackLocalsRegion(const StackFrameContext *STC);
+
+ /// getStackArgumentsRegion - Retrieve the memory region associated with
+ /// function/method arguments of the specified stack frame.
+ const StackArgumentsSpaceRegion *
+ getStackArgumentsRegion(const StackFrameContext *STC);
+
+ /// getGlobalsRegion - Retrieve the memory region associated with
+ /// global variables.
+ const GlobalsSpaceRegion *getGlobalsRegion(const CodeTextRegion *R = 0);
+
+ /// getHeapRegion - Retrieve the memory region associated with the
+ /// generic "heap".
+ const HeapSpaceRegion *getHeapRegion();
+
+ /// getUnknownRegion - Retrieve the memory region associated with unknown
+ /// memory space.
+ const MemSpaceRegion *getUnknownRegion();
+
+ const MemSpaceRegion *getCodeRegion();
+
+ /// getAllocaRegion - Retrieve a region associated with a call to alloca().
+ const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt,
+ const LocationContext *LC);
+
+ /// getCompoundLiteralRegion - Retrieve the region associated with a
+ /// given CompoundLiteral.
+ const CompoundLiteralRegion*
+ getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
+ const LocationContext *LC);
+
+ /// getCXXThisRegion - Retrieve the [artifical] region associated with the
+ /// parameter 'this'.
+ const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC);
+
+ /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+ const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
+
+ const StringRegion* getStringRegion(const StringLiteral* Str);
+
+ /// getVarRegion - Retrieve or create the memory region associated with
+ /// a specified VarDecl and LocationContext.
+ const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
+
+ /// getVarRegion - Retrieve or create the memory region associated with
+ /// a specified VarDecl and super region.
+ const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
+
+ /// getElementRegion - Retrieve the memory region associated with the
+ /// associated element type, index, and super region.
+ const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
+ const MemRegion *superRegion,
+ ASTContext &Ctx);
+
+ const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
+ const MemRegion *superRegion) {
+ return getElementRegion(ER->getElementType(), ER->getIndex(),
+ superRegion, ER->getContext());
+ }
+
+ /// getFieldRegion - Retrieve or create the memory region associated with
+ /// a specified FieldDecl. 'superRegion' corresponds to the containing
+ /// memory region (which typically represents the memory representing
+ /// a structure or class).
+ const FieldRegion *getFieldRegion(const FieldDecl* fd,
+ const MemRegion* superRegion);
+
+ const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
+ const MemRegion *superRegion) {
+ return getFieldRegion(FR->getDecl(), superRegion);
+ }
+
+ /// getObjCIvarRegion - Retrieve or create the memory region associated with
+ /// a specified Objective-c instance variable. 'superRegion' corresponds
+ /// to the containing region (which typically represents the Objective-C
+ /// object).
+ const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
+ const MemRegion* superRegion);
+
+ const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
+ LocationContext const *LC);
+
+ const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
+ const MemRegion *superRegion);
+
+ /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
+ /// super region.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
+ const MemRegion *superRegion) {
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+ }
+
+ const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
+ const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
+ CanQualType locTy,
+ AnalysisContext *AC);
+
+ /// getBlockDataRegion - Get the memory region associated with an instance
+ /// of a block. Unlike many other MemRegions, the LocationContext*
+ /// argument is allowed to be NULL for cases where we have no known
+ /// context.
+ const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
+ const LocationContext *lc = NULL);
+
+ bool isGlobalsRegion(const MemRegion* R) {
+ assert(R);
+ return R == globals;
+ }
+
+private:
+ template <typename RegionTy, typename A1>
+ RegionTy* getRegion(const A1 a1);
+
+ template <typename RegionTy, typename A1>
+ RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion);
+
+ template <typename RegionTy, typename A1, typename A2>
+ RegionTy* getRegion(const A1 a1, const A2 a2);
+
+ template <typename RegionTy, typename A1, typename A2>
+ RegionTy* getSubRegion(const A1 a1, const A2 a2,
+ const MemRegion* superRegion);
+
+ template <typename RegionTy, typename A1, typename A2, typename A3>
+ RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
+ const MemRegion* superRegion);
+
+ template <typename REG>
+ const REG* LazyAllocate(REG*& region);
+
+ template <typename REG, typename ARG>
+ const REG* LazyAllocate(REG*& region, ARG a);
+};
+
+//===----------------------------------------------------------------------===//
+// Out-of-line member definitions.
+//===----------------------------------------------------------------------===//
+
+inline ASTContext& MemRegion::getContext() const {
+ return getMemRegionManager()->getContext();
+}
+
+} // end GR namespace
+
+} // end clang namespace
+
+//===----------------------------------------------------------------------===//
+// Pretty-printing regions.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+static inline raw_ostream& operator<<(raw_ostream& os,
+ const clang::ento::MemRegion* R) {
+ R->dumpToStream(os);
+ return os;
+}
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
new file mode 100644
index 0000000..710fc6b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
@@ -0,0 +1,210 @@
+//===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- 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 ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/AST/ExprObjC.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Represents both explicit ObjC message expressions and implicit
+/// messages that are sent for handling properties in dot syntax.
+class ObjCMessage {
+ const Expr *MsgOrPropE;
+ const Expr *OriginE;
+ bool IsPropSetter;
+ SVal SetterArgV;
+
+protected:
+ ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
+ : MsgOrPropE(E), OriginE(origE),
+ IsPropSetter(isSetter), SetterArgV(setArgV) { }
+
+public:
+ ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
+
+ ObjCMessage(const ObjCMessageExpr *E)
+ : MsgOrPropE(E), OriginE(E) {
+ assert(E && "should not be initialized with null expression");
+ }
+
+ bool isValid() const { return MsgOrPropE != 0; }
+ bool isInvalid() const { return !isValid(); }
+
+ bool isMessageExpr() const {
+ return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
+ }
+
+ bool isPropertyGetter() const {
+ return isValid() &&
+ isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
+ }
+
+ bool isPropertySetter() const {
+ return isValid() &&
+ isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
+ }
+
+ const Expr *getOriginExpr() const { return OriginE; }
+
+ QualType getType(ASTContext &ctx) const;
+
+ QualType getResultType(ASTContext &ctx) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
+ return MD->getResultType();
+ return getType(ctx);
+ }
+
+ Selector getSelector() const;
+
+ const Expr *getInstanceReceiver() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getInstanceReceiver();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (propE->isObjectReceiver())
+ return propE->getBase();
+ return 0;
+ }
+
+ bool isInstanceMessage() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->isInstanceMessage();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ // FIXME: 'super' may be super class.
+ return propE->isObjectReceiver() || propE->isSuperReceiver();
+ }
+
+ const ObjCMethodDecl *getMethodDecl() const;
+
+ const ObjCInterfaceDecl *getReceiverInterface() const;
+
+ SourceLocation getSuperLoc() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getSuperLoc();
+ return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
+ }
+
+ SourceRange getSourceRange() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ return MsgOrPropE->getSourceRange();
+ }
+
+ unsigned getNumArgs() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getNumArgs();
+ return isPropertySetter() ? 1 : 0;
+ }
+
+ SVal getArgSVal(unsigned i, const GRState *state) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return state->getSVal(msgE->getArg(i));
+ assert(isPropertySetter());
+ return SetterArgV;
+ }
+
+ QualType getArgType(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getArg(i)->getType();
+ assert(isPropertySetter());
+ return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
+ }
+
+ const Expr *getArgExpr(unsigned i) const;
+
+ SourceRange getArgSourceRange(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const Expr *argE = getArgExpr(i))
+ return argE->getSourceRange();
+ return OriginE->getSourceRange();
+ }
+};
+
+class ObjCPropertyGetter : public ObjCMessage {
+public:
+ ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
+ : ObjCMessage(propE, originE, false, SVal()) {
+ assert(propE && originE &&
+ "should not be initialized with null expressions");
+ }
+};
+
+class ObjCPropertySetter : public ObjCMessage {
+public:
+ ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
+ SVal argV)
+ : ObjCMessage(propE, storeE, true, argV) {
+ assert(propE && storeE &&"should not be initialized with null expressions");
+ }
+};
+
+/// \brief Common wrapper for a call expression or an ObjC message, mainly to
+/// provide a common interface for handling their arguments.
+class CallOrObjCMessage {
+ const CallExpr *CallE;
+ ObjCMessage Msg;
+ const GRState *State;
+
+public:
+ CallOrObjCMessage(const CallExpr *callE, const GRState *state)
+ : CallE(callE), State(state) { }
+ CallOrObjCMessage(const ObjCMessage &msg, const GRState *state)
+ : CallE(0), Msg(msg), State(state) { }
+
+ QualType getResultType(ASTContext &ctx) const;
+
+ unsigned getNumArgs() const {
+ if (CallE) return CallE->getNumArgs();
+ return Msg.getNumArgs();
+ }
+
+ SVal getArgSVal(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return State->getSVal(CallE->getArg(i));
+ return Msg.getArgSVal(i, State);
+ }
+
+ SVal getArgSValAsScalarOrLoc(unsigned i) const;
+
+ const Expr *getArg(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return CallE->getArg(i);
+ return Msg.getArgExpr(i);
+ }
+
+ SourceRange getArgSourceRange(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return CallE->getArg(i)->getSourceRange();
+ return Msg.getArgSourceRange(i);
+ }
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
new file mode 100644
index 0000000..fc2b76e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -0,0 +1,258 @@
+// SValBuilder.h - Construction of SVals from evaluating expressions -*- 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 SValBuilder, a class that defines the interface for
+// "symbolical evaluators" which construct an SVal from an expression.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_SVALBUILDER
+#define LLVM_CLANG_GR_SVALBUILDER
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+
+namespace clang {
+
+namespace ento {
+
+class GRState;
+
+class SValBuilder {
+protected:
+ ASTContext &Context;
+
+ /// Manager of APSInt values.
+ BasicValueFactory BasicVals;
+
+ /// Manages the creation of symbols.
+ SymbolManager SymMgr;
+
+ /// Manages the creation of memory regions.
+ MemRegionManager MemMgr;
+
+ GRStateManager &StateMgr;
+
+ /// The scalar type to use for array indices.
+ const QualType ArrayIndexTy;
+
+ /// The width of the scalar type used for array indices.
+ const unsigned ArrayIndexWidth;
+
+public:
+ // FIXME: Make these protected again one RegionStoreManager correctly
+ // handles loads from differening bound value types.
+ virtual SVal evalCastNL(NonLoc val, QualType castTy) = 0;
+ virtual SVal evalCastL(Loc val, QualType castTy) = 0;
+
+public:
+ SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
+ GRStateManager &stateMgr)
+ : Context(context), BasicVals(context, alloc),
+ SymMgr(context, BasicVals, alloc),
+ MemMgr(context, alloc),
+ StateMgr(stateMgr),
+ ArrayIndexTy(context.IntTy),
+ ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
+
+ virtual ~SValBuilder() {}
+
+ SVal evalCast(SVal V, QualType castTy, QualType originalType);
+
+ virtual SVal evalMinus(NonLoc val) = 0;
+
+ virtual SVal evalComplement(NonLoc val) = 0;
+
+ virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode Op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode Op,
+ Loc lhs, Loc rhs, QualType resultTy) = 0;
+
+ virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode Op,
+ Loc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
+ /// (integer) value, that value is returned. Otherwise, returns NULL.
+ virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0;
+
+ SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
+ SVal L, SVal R, QualType T);
+
+ DefinedOrUnknownSVal evalEQ(const GRState *ST, DefinedOrUnknownSVal L,
+ DefinedOrUnknownSVal R);
+
+ ASTContext &getContext() { return Context; }
+ const ASTContext &getContext() const { return Context; }
+
+ GRStateManager &getStateManager() { return StateMgr; }
+
+ QualType getConditionType() const {
+ return getContext().IntTy;
+ }
+
+ QualType getArrayIndexType() const {
+ return ArrayIndexTy;
+ }
+
+ BasicValueFactory &getBasicValueFactory() { return BasicVals; }
+ const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
+
+ SymbolManager &getSymbolManager() { return SymMgr; }
+ const SymbolManager &getSymbolManager() const { return SymMgr; }
+
+ MemRegionManager &getRegionManager() { return MemMgr; }
+ const MemRegionManager &getRegionManager() const { return MemMgr; }
+
+ // Forwarding methods to SymbolManager.
+
+ const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+ unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return SymMgr.getConjuredSymbol(E, T, VisitCount, SymbolTag);
+ }
+
+ const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag);
+ }
+
+ /// makeZeroVal - Construct an SVal representing '0' for the specified type.
+ DefinedOrUnknownSVal makeZeroVal(QualType T);
+
+ /// getRegionValueSymbolVal - make a unique symbol for value of R.
+ DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R);
+
+ DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag,
+ const Expr *E, unsigned Count);
+ DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag,
+ const Expr *E, QualType T,
+ unsigned Count);
+
+ DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
+ const TypedRegion *R);
+
+ DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR,
+ const Expr *E, QualType T, unsigned Count);
+
+ DefinedSVal getFunctionPointer(const FunctionDecl *FD);
+
+ DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
+ const LocationContext *LC);
+
+ NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
+ return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
+ }
+
+ NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) {
+ return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R));
+ }
+
+ NonLoc makeZeroArrayIndex() {
+ return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
+ }
+
+ NonLoc makeArrayIndex(uint64_t idx) {
+ return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy));
+ }
+
+ SVal convertToArrayIndex(SVal V);
+
+ nonloc::ConcreteInt makeIntVal(const IntegerLiteral* I) {
+ return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(),
+ I->getType()->isUnsignedIntegerType()));
+ }
+
+ nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *E) {
+ return makeTruthVal(E->getValue());
+ }
+
+ nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) {
+ return nonloc::ConcreteInt(BasicVals.getValue(V));
+ }
+
+ loc::ConcreteInt makeIntLocVal(const llvm::APSInt &v) {
+ return loc::ConcreteInt(BasicVals.getValue(v));
+ }
+
+ NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned));
+ }
+
+ DefinedSVal makeIntVal(uint64_t X, QualType T) {
+ if (Loc::isLocType(T))
+ return loc::ConcreteInt(BasicVals.getValue(X, T));
+
+ return nonloc::ConcreteInt(BasicVals.getValue(X, T));
+ }
+
+ NonLoc makeIntVal(uint64_t X, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
+ }
+
+ NonLoc makeIntValWithPtrWidth(uint64_t X, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getIntWithPtrWidth(X, isUnsigned));
+ }
+
+ NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
+ }
+
+ NonLoc makeLocAsInteger(Loc V, unsigned Bits) {
+ return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits));
+ }
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType T);
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType T);
+
+ nonloc::ConcreteInt makeTruthVal(bool b, QualType T) {
+ return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
+ }
+
+ nonloc::ConcreteInt makeTruthVal(bool b) {
+ return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
+ }
+
+ Loc makeNull() {
+ return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
+ }
+
+ Loc makeLoc(SymbolRef Sym) {
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym));
+ }
+
+ Loc makeLoc(const MemRegion* R) {
+ return loc::MemRegionVal(R);
+ }
+
+ Loc makeLoc(const AddrLabelExpr *E) {
+ return loc::GotoLabel(E->getLabel());
+ }
+
+ Loc makeLoc(const llvm::APSInt& V) {
+ return loc::ConcreteInt(BasicVals.getValue(V));
+ }
+
+};
+
+SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
+ ASTContext &context,
+ GRStateManager &stateMgr);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
new file mode 100644
index 0000000..0d43079
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -0,0 +1,544 @@
+//== SVals.h - Abstract Values for Static Analysis ---------*- 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 SVal, Loc, and NonLoc, classes that represent
+// abstract r-values for use with path-sensitive value tracking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_RVALUE_H
+#define LLVM_CLANG_GR_RVALUE_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/ImmutableList.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+//==------------------------------------------------------------------------==//
+// Base SVal types.
+//==------------------------------------------------------------------------==//
+
+namespace clang {
+
+namespace ento {
+
+class CompoundValData;
+class LazyCompoundValData;
+class GRState;
+class BasicValueFactory;
+class MemRegion;
+class TypedRegion;
+class MemRegionManager;
+class GRStateManager;
+class SValBuilder;
+
+/// SVal - This represents a symbolic expression, which can be either
+/// an L-value or an R-value.
+///
+class SVal {
+public:
+ enum BaseKind {
+ // The enumerators must be representable using 2 bits.
+ UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
+ UnknownKind = 1, // for subclass UnknownVal (a void value)
+ LocKind = 2, // for subclass Loc (an L-value)
+ NonLocKind = 3 // for subclass NonLoc (an R-value that's not
+ // an L-value)
+ };
+ enum { BaseBits = 2, BaseMask = 0x3 };
+
+protected:
+ const void* Data;
+
+ /// The lowest 2 bits are a BaseKind (0 -- 3).
+ /// The higher bits are an unsigned "kind" value.
+ unsigned Kind;
+
+ explicit SVal(const void* d, bool isLoc, unsigned ValKind)
+ : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
+
+ explicit SVal(BaseKind k, const void* D = NULL)
+ : Data(D), Kind(k) {}
+
+public:
+ explicit SVal() : Data(0), Kind(0) {}
+ ~SVal() {}
+
+ /// BufferTy - A temporary buffer to hold a set of SVals.
+ typedef llvm::SmallVector<SVal,5> BufferTy;
+
+ inline unsigned getRawKind() const { return Kind; }
+ inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
+ inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+
+ // This method is required for using SVal in a FoldingSetNode. It
+ // extracts a unique signature for this SVal object.
+ inline void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) getRawKind());
+ ID.AddPointer(Data);
+ }
+
+ inline bool operator==(const SVal& R) const {
+ return getRawKind() == R.getRawKind() && Data == R.Data;
+ }
+
+ inline bool operator!=(const SVal& R) const {
+ return !(*this == R);
+ }
+
+ inline bool isUnknown() const {
+ return getRawKind() == UnknownKind;
+ }
+
+ inline bool isUndef() const {
+ return getRawKind() == UndefinedKind;
+ }
+
+ inline bool isUnknownOrUndef() const {
+ return getRawKind() <= UnknownKind;
+ }
+
+ inline bool isValid() const {
+ return getRawKind() > UnknownKind;
+ }
+
+ bool isConstant() const;
+
+ bool isConstant(int I) const;
+
+ bool isZeroConstant() const;
+
+ /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
+ bool hasConjuredSymbol() const;
+
+ /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
+ /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
+ /// Otherwise return 0.
+ const FunctionDecl* getAsFunctionDecl() const;
+
+ /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
+ /// wraps a symbol, return that SymbolRef. Otherwise return NULL.
+ SymbolRef getAsLocSymbol() const;
+
+ /// Get the symbol in the SVal or its base region.
+ SymbolRef getLocSymbolInBase() const;
+
+ /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
+ /// Otherwise return a SymbolRef where 'isValid()' returns false.
+ SymbolRef getAsSymbol() const;
+
+ /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+ /// return that expression. Otherwise return NULL.
+ const SymExpr *getAsSymbolicExpression() const;
+
+ const MemRegion *getAsRegion() const;
+
+ void dumpToStream(llvm::raw_ostream& OS) const;
+ void dump() const;
+
+ // Iterators.
+ class symbol_iterator {
+ llvm::SmallVector<const SymExpr*, 5> itr;
+ void expand();
+ public:
+ symbol_iterator() {}
+ symbol_iterator(const SymExpr* SE);
+
+ symbol_iterator& operator++();
+ SymbolRef operator*();
+
+ bool operator==(const symbol_iterator& X) const;
+ bool operator!=(const symbol_iterator& X) const;
+ };
+
+ symbol_iterator symbol_begin() const {
+ const SymExpr *SE = getAsSymbolicExpression();
+ if (SE)
+ return symbol_iterator(SE);
+ else
+ return symbol_iterator();
+ }
+
+ symbol_iterator symbol_end() const { return symbol_iterator(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal*) { return true; }
+};
+
+
+class UndefinedVal : public SVal {
+public:
+ UndefinedVal() : SVal(UndefinedKind) {}
+ UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == UndefinedKind;
+ }
+
+ const void* getData() const { return Data; }
+};
+
+class DefinedOrUnknownSVal : public SVal {
+private:
+ // Do not implement. We want calling these methods to be a compiler
+ // error since they are tautologically false.
+ bool isUndef() const;
+ bool isValid() const;
+
+protected:
+ explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind)
+ : SVal(d, isLoc, ValKind) {}
+
+ explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
+ : SVal(k, D) {}
+
+public:
+ // Implement isa<T> support.
+ static inline bool classof(const SVal *V) {
+ return !V->isUndef();
+ }
+};
+
+class UnknownVal : public DefinedOrUnknownSVal {
+public:
+ explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
+
+ static inline bool classof(const SVal *V) {
+ return V->getBaseKind() == UnknownKind;
+ }
+};
+
+class DefinedSVal : public DefinedOrUnknownSVal {
+private:
+ // Do not implement. We want calling these methods to be a compiler
+ // error since they are tautologically true/false.
+ bool isUnknown() const;
+ bool isUnknownOrUndef() const;
+ bool isValid() const;
+protected:
+ explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
+ : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
+public:
+ // Implement isa<T> support.
+ static inline bool classof(const SVal *V) {
+ return !V->isUnknownOrUndef();
+ }
+};
+
+class NonLoc : public DefinedSVal {
+protected:
+ explicit NonLoc(unsigned SubKind, const void* d)
+ : DefinedSVal(d, false, SubKind) {}
+
+public:
+ void dumpToStream(llvm::raw_ostream& Out) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind;
+ }
+};
+
+class Loc : public DefinedSVal {
+protected:
+ explicit Loc(unsigned SubKind, const void* D)
+ : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
+
+public:
+ void dumpToStream(llvm::raw_ostream& Out) const;
+
+ Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind;
+ }
+
+ static inline bool isLocType(QualType T) {
+ return T->isAnyPointerType() || T->isBlockPointerType() ||
+ T->isReferenceType();
+ }
+};
+
+//==------------------------------------------------------------------------==//
+// Subclasses of NonLoc.
+//==------------------------------------------------------------------------==//
+
+namespace nonloc {
+
+enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
+ LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
+
+class SymbolVal : public NonLoc {
+public:
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
+
+ SymbolRef getSymbol() const {
+ return (const SymbolData*) Data;
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == SymbolValKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == SymbolValKind;
+ }
+};
+
+class SymExprVal : public NonLoc {
+public:
+ explicit SymExprVal(const SymExpr *SE)
+ : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
+
+ const SymExpr *getSymbolicExpression() const {
+ return reinterpret_cast<const SymExpr*>(Data);
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == SymExprValKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == SymExprValKind;
+ }
+};
+
+class ConcreteInt : public NonLoc {
+public:
+ explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<const llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
+
+ ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
+
+class LocAsInteger : public NonLoc {
+ friend class ento::SValBuilder;
+
+ explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
+ NonLoc(LocAsIntegerKind, &data) {
+ assert (isa<Loc>(data.first));
+ }
+
+public:
+
+ Loc getLoc() const {
+ return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
+ }
+
+ const Loc& getPersistentLoc() const {
+ const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
+ return cast<Loc>(V);
+ }
+
+ unsigned getNumBits() const {
+ return ((std::pair<SVal, unsigned>*) Data)->second;
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == LocAsIntegerKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == LocAsIntegerKind;
+ }
+};
+
+class CompoundVal : public NonLoc {
+ friend class ento::SValBuilder;
+
+ explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
+
+public:
+ const CompoundValData* getValue() const {
+ return static_cast<const CompoundValData*>(Data);
+ }
+
+ typedef llvm::ImmutableList<SVal>::iterator iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ static bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
+ }
+
+ static bool classof(const NonLoc* V) {
+ return V->getSubKind() == CompoundValKind;
+ }
+};
+
+class LazyCompoundVal : public NonLoc {
+ friend class ento::SValBuilder;
+
+ explicit LazyCompoundVal(const LazyCompoundValData *D)
+ : NonLoc(LazyCompoundValKind, D) {}
+public:
+ const LazyCompoundValData *getCVData() const {
+ return static_cast<const LazyCompoundValData*>(Data);
+ }
+ const void *getStore() const;
+ const TypedRegion *getRegion() const;
+
+ static bool classof(const SVal *V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == LazyCompoundValKind;
+ }
+ static bool classof(const NonLoc *V) {
+ return V->getSubKind() == LazyCompoundValKind;
+ }
+};
+
+} // end namespace ento::nonloc
+
+//==------------------------------------------------------------------------==//
+// Subclasses of Loc.
+//==------------------------------------------------------------------------==//
+
+namespace loc {
+
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
+
+class GotoLabel : public Loc {
+public:
+ explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
+
+ const LabelDecl *getLabel() const {
+ return static_cast<const LabelDecl*>(Data);
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == GotoLabelKind;
+ }
+};
+
+
+class MemRegionVal : public Loc {
+public:
+ explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+
+ const MemRegion* getRegion() const {
+ return static_cast<const MemRegion*>(Data);
+ }
+
+ const MemRegion* stripCasts() const;
+
+ template <typename REGION>
+ const REGION* getRegionAs() const {
+ return llvm::dyn_cast<REGION>(getRegion());
+ }
+
+ inline bool operator==(const MemRegionVal& R) const {
+ return getRegion() == R.getRegion();
+ }
+
+ inline bool operator!=(const MemRegionVal& R) const {
+ return getRegion() != R.getRegion();
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == MemRegionKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == MemRegionKind;
+ }
+};
+
+class ConcreteInt : public Loc {
+public:
+ explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<const llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
+
+/// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
+/// "store" of an ObjC property for the dot syntax.
+class ObjCPropRef : public Loc {
+public:
+ explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
+ : Loc(ObjCPropRefKind, E) {}
+
+ const ObjCPropertyRefExpr *getPropRefExpr() const {
+ return static_cast<const ObjCPropertyRefExpr *>(Data);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == ObjCPropRefKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == ObjCPropRefKind;
+ }
+};
+
+} // end ento::loc namespace
+} // end GR namespace
+
+} // end clang namespace
+
+namespace llvm {
+static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
+ clang::ento::SVal V) {
+ V.dumpToStream(os);
+ return os;
+}
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
new file mode 100644
index 0000000..0251311
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -0,0 +1,307 @@
+//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the types Store and StoreManager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_STORE_H
+#define LLVM_CLANG_GR_STORE_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+
+namespace clang {
+
+class Stmt;
+class Expr;
+class ObjCIvarDecl;
+class StackFrameContext;
+
+namespace ento {
+
+/// Store - This opaque type encapsulates an immutable mapping from
+/// locations to values. At a high-level, it represents the symbolic
+/// memory model. Different subclasses of StoreManager may choose
+/// different types to represent the locations and values.
+typedef const void* Store;
+
+class GRState;
+class GRStateManager;
+class SubRegionMap;
+class StoreManager;
+
+class StoreRef {
+ Store store;
+ StoreManager &mgr;
+public:
+ StoreRef(Store, StoreManager &);
+ StoreRef(const StoreRef &);
+ StoreRef &operator=(StoreRef const &);
+
+ bool operator==(const StoreRef &x) const {
+ assert(&mgr == &x.mgr);
+ return x.store == store;
+ }
+ bool operator!=(const StoreRef &x) const { return !operator==(x); }
+
+ ~StoreRef();
+
+ Store getStore() const { return store; }
+};
+
+class StoreManager {
+protected:
+ SValBuilder &svalBuilder;
+ GRStateManager &StateMgr;
+
+ /// MRMgr - Manages region objects associated with this StoreManager.
+ MemRegionManager &MRMgr;
+ ASTContext &Ctx;
+
+ StoreManager(GRStateManager &stateMgr);
+
+public:
+ virtual ~StoreManager() {}
+
+ /// Return the value bound to specified location in a given state.
+ /// \param[in] state The analysis state.
+ /// \param[in] loc The symbolic memory location.
+ /// \param[in] T An optional type that provides a hint indicating the
+ /// expected type of the returned value. This is used if the value is
+ /// lazily computed.
+ /// \return The value bound to the location \c loc.
+ virtual SVal Retrieve(Store store, Loc loc, QualType T = QualType()) = 0;
+
+ /// Return a state with the specified value bound to the given location.
+ /// \param[in] state The analysis state.
+ /// \param[in] loc The symbolic memory location.
+ /// \param[in] val The value to bind to location \c loc.
+ /// \return A pointer to a GRState object that contains the same bindings as
+ /// \c state with the addition of having the value specified by \c val bound
+ /// to the location given for \c loc.
+ virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
+
+ virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V);
+ virtual StoreRef Remove(Store St, Loc L) = 0;
+
+ /// BindCompoundLiteral - Return the store that has the bindings currently
+ /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
+ /// for the compound literal and 'BegInit' and 'EndInit' represent an
+ /// array of initializer values.
+ virtual StoreRef BindCompoundLiteral(Store store,
+ const CompoundLiteralExpr* cl,
+ const LocationContext *LC, SVal v) = 0;
+
+ /// getInitialStore - Returns the initial "empty" store representing the
+ /// value bindings upon entry to an analyzed function.
+ virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
+
+ /// getRegionManager - Returns the internal RegionManager object that is
+ /// used to query and manipulate MemRegion objects.
+ MemRegionManager& getRegionManager() { return MRMgr; }
+
+ /// getSubRegionMap - Returns an opaque map object that clients can query
+ /// to get the subregions of a given MemRegion object. It is the
+ // caller's responsibility to 'delete' the returned map.
+ virtual SubRegionMap *getSubRegionMap(Store store) = 0;
+
+ virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
+ return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
+ }
+
+ virtual Loc getLValueString(const StringLiteral* S) {
+ return svalBuilder.makeLoc(MRMgr.getStringRegion(S));
+ }
+
+ Loc getLValueCompoundLiteral(const CompoundLiteralExpr* CL,
+ const LocationContext *LC) {
+ return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
+ }
+
+ virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) {
+ return getLValueFieldOrIvar(decl, base);
+ }
+
+ virtual SVal getLValueField(const FieldDecl* D, SVal Base) {
+ return getLValueFieldOrIvar(D, Base);
+ }
+
+ virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
+
+ // FIXME: This should soon be eliminated altogether; clients should deal with
+ // region extents directly.
+ virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
+ const MemRegion *region,
+ QualType EleTy) {
+ return UnknownVal();
+ }
+
+ /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
+ /// conversions between arrays and pointers.
+ virtual SVal ArrayToPointer(Loc Array) = 0;
+
+ /// Evaluates DerivedToBase casts.
+ virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) {
+ return UnknownVal();
+ }
+
+ class CastResult {
+ const GRState *state;
+ const MemRegion *region;
+ public:
+ const GRState *getState() const { return state; }
+ const MemRegion* getRegion() const { return region; }
+ CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){}
+ };
+
+ const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
+
+ /// castRegion - Used by ExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ const MemRegion *castRegion(const MemRegion *region, QualType CastToTy);
+
+ virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
+
+ virtual StoreRef BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
+
+ virtual StoreRef BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
+
+ /// If the StoreManager supports it, increment the reference count of
+ /// the specified Store object.
+ virtual void incrementReferenceCount(Store store) {}
+
+ /// If the StoreManager supports it, decrement the reference count of
+ /// the specified Store object. If the reference count hits 0, the memory
+ /// associated with the object is recycled.
+ virtual void decrementReferenceCount(Store store) {}
+
+ typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+ typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
+
+ /// invalidateRegions - Clears out the specified regions from the store,
+ /// marking their values as unknown. Depending on the store, this may also
+ /// invalidate additional regions that may have changed based on accessing
+ /// the given regions. Optionally, invalidates non-static globals as well.
+ /// \param[in] store The initial store
+ /// \param[in] Begin A pointer to the first region to invalidate.
+ /// \param[in] End A pointer just past the last region to invalidate.
+ /// \param[in] E The current statement being evaluated. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in] Count The current block count. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in,out] IS A set to fill with any symbols that are no longer
+ /// accessible. Pass \c NULL if this information will not be used.
+ /// \param[in] invalidateGlobals If \c true, any non-static global regions
+ /// are invalidated as well.
+ /// \param[in,out] Regions A vector to fill with any regions being
+ /// invalidated. This should include any regions explicitly invalidated
+ /// even if they do not currently have bindings. Pass \c NULL if this
+ /// information will not be used.
+ virtual StoreRef invalidateRegions(Store store,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) = 0;
+
+ /// enterStackFrame - Let the StoreManager to do something when execution
+ /// engine is about to execute into a callee.
+ virtual StoreRef enterStackFrame(const GRState *state,
+ const StackFrameContext *frame);
+
+ virtual void print(Store store, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) = 0;
+
+ class BindingsHandler {
+ public:
+ virtual ~BindingsHandler();
+ virtual bool HandleBinding(StoreManager& SMgr, Store store,
+ const MemRegion *region, SVal val) = 0;
+ };
+
+ /// iterBindings - Iterate over the bindings in the Store.
+ virtual void iterBindings(Store store, BindingsHandler& f) = 0;
+
+protected:
+ const MemRegion *MakeElementRegion(const MemRegion *baseRegion,
+ QualType pointeeTy, uint64_t index = 0);
+
+ /// CastRetrievedVal - Used by subclasses of StoreManager to implement
+ /// implicit casts that arise from loads from regions that are reinterpreted
+ /// as another region.
+ SVal CastRetrievedVal(SVal val, const TypedRegion *region, QualType castTy,
+ bool performTestOnly = true);
+
+private:
+ SVal getLValueFieldOrIvar(const Decl* decl, SVal base);
+};
+
+
+inline StoreRef::StoreRef(Store store, StoreManager & smgr)
+ : store(store), mgr(smgr) {
+ if (store)
+ mgr.incrementReferenceCount(store);
+}
+
+inline StoreRef::StoreRef(const StoreRef &sr)
+ : store(sr.store), mgr(sr.mgr)
+{
+ if (store)
+ mgr.incrementReferenceCount(store);
+}
+
+inline StoreRef::~StoreRef() {
+ if (store)
+ mgr.decrementReferenceCount(store);
+}
+
+inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
+ assert(&newStore.mgr == &mgr);
+ if (store != newStore.store) {
+ mgr.incrementReferenceCount(newStore.store);
+ mgr.decrementReferenceCount(store);
+ store = newStore.getStore();
+ }
+ return *this;
+}
+
+// FIXME: Do we still need this?
+/// SubRegionMap - An abstract interface that represents a queryable map
+/// between MemRegion objects and their subregions.
+class SubRegionMap {
+public:
+ virtual ~SubRegionMap() {}
+
+ class Visitor {
+ public:
+ virtual ~Visitor() {}
+ virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
+ };
+
+ virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
+};
+
+// FIXME: Do we need to pass GRStateManager anymore?
+StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
+StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
+StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
+StoreManager *CreateFlatStoreManager(GRStateManager &StMgr);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
new file mode 100644
index 0000000..3d6f9fa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -0,0 +1,116 @@
+//== SubEngine.h - Interface of the subengine of CoreEngine --------*- 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 interface of a subengine of the CoreEngine.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_GR_SUBENGINE_H
+#define LLVM_CLANG_GR_SUBENGINE_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+
+namespace clang {
+
+class CFGBlock;
+class CFGElement;
+class LocationContext;
+class Stmt;
+
+namespace ento {
+
+template <typename PP> class GenericNodeBuilder;
+class AnalysisManager;
+class ExplodedNodeSet;
+class ExplodedNode;
+class GRState;
+class GRStateManager;
+class BlockCounter;
+class StmtNodeBuilder;
+class BranchNodeBuilder;
+class IndirectGotoNodeBuilder;
+class SwitchNodeBuilder;
+class EndOfFunctionNodeBuilder;
+class CallEnterNodeBuilder;
+class CallExitNodeBuilder;
+class MemRegion;
+
+class SubEngine {
+public:
+ virtual ~SubEngine() {}
+
+ virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
+
+ virtual AnalysisManager &getAnalysisManager() = 0;
+
+ virtual GRStateManager &getStateManager() = 0;
+
+ /// Called by CoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a block-level statement.
+ virtual void processCFGElement(const CFGElement E, StmtNodeBuilder& builder)=0;
+
+ /// Called by CoreEngine when it starts processing a CFGBlock. The
+ /// SubEngine is expected to populate dstNodes with new nodes representing
+ /// updated analysis state, or generate no nodes at all if it doesn't.
+ virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+ GenericNodeBuilder<BlockEntrance> &nodeBuilder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a branch condition.
+ virtual void processBranch(const Stmt* Condition, const Stmt* Term,
+ BranchNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a switch statement.
+ virtual void processSwitch(SwitchNodeBuilder& builder) = 0;
+
+ /// Called by CoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
+ virtual void processEndOfFunction(EndOfFunctionNodeBuilder& builder) = 0;
+
+ // Generate the entry node of the callee.
+ virtual void processCallEnter(CallEnterNodeBuilder &builder) = 0;
+
+ // Generate the first post callsite node.
+ virtual void processCallExit(CallExitNodeBuilder &builder) = 0;
+
+ /// Called by ConstraintManager. Used to call checker-specific
+ /// logic for handling assumptions on symbolic values.
+ virtual const GRState* processAssume(const GRState *state,
+ SVal cond, bool assumption) = 0;
+
+ /// wantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ virtual bool wantsRegionChangeUpdate(const GRState* state) = 0;
+
+ /// processRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ virtual const GRState* processRegionChanges(const GRState* state,
+ const MemRegion* const *Begin,
+ const MemRegion* const *End) = 0;
+
+ inline const GRState* processRegionChange(const GRState* state,
+ const MemRegion* MR) {
+ return processRegionChanges(state, &MR, &MR+1);
+ }
+
+ /// Called by CoreEngine when the analysis worklist is either empty or the
+ // maximum number of analysis steps have been reached.
+ virtual void processEndWorklist(bool hasWorkRemaining) = 0;
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
new file mode 100644
index 0000000..ed87851
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
@@ -0,0 +1,61 @@
+//== SummaryManager.h - Generic handling of function summaries --*- 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 SummaryManager and related classes, which provides
+// a generic mechanism for managing function summaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_SUMMARY
+#define LLVM_CLANG_GR_SUMMARY
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+
+namespace ento {
+
+namespace summMgr {
+
+
+/* Key kinds:
+
+ - C functions
+ - C++ functions (name + parameter types)
+ - ObjC methods:
+ - Class, selector (class method)
+ - Class, selector (instance method)
+ - Category, selector (instance method)
+ - Protocol, selector (instance method)
+ - C++ methods
+ - Class, function name + parameter types + const
+ */
+
+class SummaryKey {
+
+};
+
+} // end namespace clang::summMgr
+
+class SummaryManagerImpl {
+
+};
+
+
+template <typename T>
+class SummaryManager : SummaryManagerImpl {
+
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
new file mode 100644
index 0000000..ad173bb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -0,0 +1,489 @@
+//== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
+// created for use by ExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_SYMMGR_H
+#define LLVM_CLANG_GR_SYMMGR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace llvm {
+class BumpPtrAllocator;
+class raw_ostream;
+}
+
+namespace clang {
+ class ASTContext;
+ class StackFrameContext;
+
+namespace ento {
+ class BasicValueFactory;
+ class MemRegion;
+ class SubRegion;
+ class TypedRegion;
+ class VarRegion;
+
+class SymExpr : public llvm::FoldingSetNode {
+public:
+ enum Kind { BEGIN_SYMBOLS,
+ RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+ MetadataKind,
+ END_SYMBOLS,
+ SymIntKind, SymSymKind };
+private:
+ Kind K;
+
+protected:
+ SymExpr(Kind k) : K(k) {}
+
+public:
+ virtual ~SymExpr() {}
+
+ Kind getKind() const { return K; }
+
+ void dump() const;
+
+ virtual void dumpToStream(llvm::raw_ostream &os) const = 0;
+
+ virtual QualType getType(ASTContext&) const = 0;
+ virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr*) { return true; }
+};
+
+typedef unsigned SymbolID;
+
+class SymbolData : public SymExpr {
+private:
+ const SymbolID Sym;
+
+protected:
+ SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
+
+public:
+ virtual ~SymbolData() {}
+
+ SymbolID getSymbolID() const { return Sym; }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ Kind k = SE->getKind();
+ return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
+ }
+};
+
+typedef const SymbolData* SymbolRef;
+
+// A symbol representing the value of a MemRegion.
+class SymbolRegionValue : public SymbolData {
+ const TypedRegion *R;
+
+public:
+ SymbolRegionValue(SymbolID sym, const TypedRegion *r)
+ : SymbolData(RegionValueKind, sym), R(r) {}
+
+ const TypedRegion* getRegion() const { return R; }
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) {
+ profile.AddInteger((unsigned) RegionValueKind);
+ profile.AddPointer(R);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R);
+ }
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ QualType getType(ASTContext&) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == RegionValueKind;
+ }
+};
+
+// A symbol representing the result of an expression.
+class SymbolConjured : public SymbolData {
+ const Stmt* S;
+ QualType T;
+ unsigned Count;
+ const void* SymbolTag;
+
+public:
+ SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
+ const void* symbolTag)
+ : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
+ SymbolTag(symbolTag) {}
+
+ const Stmt* getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void* getTag() const { return SymbolTag; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const Stmt* S,
+ QualType T, unsigned Count, const void* SymbolTag) {
+ profile.AddInteger((unsigned) ConjuredKind);
+ profile.AddPointer(S);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(SymbolTag);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, S, T, Count, SymbolTag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == ConjuredKind;
+ }
+};
+
+// A symbol representing the value of a MemRegion whose parent region has
+// symbolic value.
+class SymbolDerived : public SymbolData {
+ SymbolRef parentSymbol;
+ const TypedRegion *R;
+
+public:
+ SymbolDerived(SymbolID sym, SymbolRef parent, const TypedRegion *r)
+ : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
+
+ SymbolRef getParentSymbol() const { return parentSymbol; }
+ const TypedRegion *getRegion() const { return R; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
+ const TypedRegion *r) {
+ profile.AddInteger((unsigned) DerivedKind);
+ profile.AddPointer(r);
+ profile.AddPointer(parent);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, parentSymbol, R);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == DerivedKind;
+ }
+};
+
+/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
+/// Clients should not ask the SymbolManager for a region's extent. Always use
+/// SubRegion::getExtent instead -- the value returned may not be a symbol.
+class SymbolExtent : public SymbolData {
+ const SubRegion *R;
+
+public:
+ SymbolExtent(SymbolID sym, const SubRegion *r)
+ : SymbolData(ExtentKind, sym), R(r) {}
+
+ const SubRegion *getRegion() const { return R; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
+ profile.AddInteger((unsigned) ExtentKind);
+ profile.AddPointer(R);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == ExtentKind;
+ }
+};
+
+/// SymbolMetadata - Represents path-dependent metadata about a specific region.
+/// Metadata symbols remain live as long as they are marked as in use before
+/// dead-symbol sweeping AND their associated regions are still alive.
+/// Intended for use by checkers.
+class SymbolMetadata : public SymbolData {
+ const MemRegion* R;
+ const Stmt* S;
+ QualType T;
+ unsigned Count;
+ const void* Tag;
+public:
+ SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
+ unsigned count, const void* tag)
+ : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+
+ const MemRegion *getRegion() const { return R; }
+ const Stmt* getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void* getTag() const { return Tag; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
+ const Stmt *S, QualType T, unsigned Count,
+ const void *Tag) {
+ profile.AddInteger((unsigned) MetadataKind);
+ profile.AddPointer(R);
+ profile.AddPointer(S);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(Tag);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R, S, T, Count, Tag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == MetadataKind;
+ }
+};
+
+// SymIntExpr - Represents symbolic expression like 'x' + 3.
+class SymIntExpr : public SymExpr {
+ const SymExpr *LHS;
+ BinaryOperator::Opcode Op;
+ const llvm::APSInt& RHS;
+ QualType T;
+
+public:
+ SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t)
+ : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ const SymExpr *getLHS() const { return LHS; }
+ const llvm::APSInt &getRHS() const { return RHS; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const llvm::APSInt& rhs,
+ QualType t) {
+ ID.AddInteger((unsigned) SymIntKind);
+ ID.AddPointer(lhs);
+ ID.AddInteger(op);
+ ID.AddPointer(&rhs);
+ ID.Add(t);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) {
+ Profile(ID, LHS, Op, RHS, T);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymIntKind;
+ }
+};
+
+// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
+class SymSymExpr : public SymExpr {
+ const SymExpr *LHS;
+ BinaryOperator::Opcode Op;
+ const SymExpr *RHS;
+ QualType T;
+
+public:
+ SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType t)
+ : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+ const SymExpr *getLHS() const { return LHS; }
+ const SymExpr *getRHS() const { return RHS; }
+
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
+ ID.AddInteger((unsigned) SymSymKind);
+ ID.AddPointer(lhs);
+ ID.AddInteger(op);
+ ID.AddPointer(rhs);
+ ID.Add(t);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) {
+ Profile(ID, LHS, Op, RHS, T);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymSymKind;
+ }
+};
+
+class SymbolManager {
+ typedef llvm::FoldingSet<SymExpr> DataSetTy;
+ DataSetTy DataSet;
+ unsigned SymbolCounter;
+ llvm::BumpPtrAllocator& BPAlloc;
+ BasicValueFactory &BV;
+ ASTContext& Ctx;
+
+public:
+ SymbolManager(ASTContext& ctx, BasicValueFactory &bv,
+ llvm::BumpPtrAllocator& bpalloc)
+ : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
+
+ ~SymbolManager();
+
+ static bool canSymbolicate(QualType T);
+
+ /// Make a unique symbol for MemRegion R according to its kind.
+ const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R);
+
+ const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+ unsigned VisitCount,
+ const void* SymbolTag = 0);
+
+ const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
+ }
+
+ const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
+ const TypedRegion *R);
+
+ const SymbolExtent *getExtentSymbol(const SubRegion *R);
+
+ const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
+ QualType T, unsigned VisitCount,
+ const void* SymbolTag = 0);
+
+ const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t);
+
+ const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t) {
+ return getSymIntExpr(&lhs, op, rhs, t);
+ }
+
+ const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t);
+
+ QualType getType(const SymExpr *SE) const {
+ return SE->getType(Ctx);
+ }
+
+ ASTContext &getContext() { return Ctx; }
+ BasicValueFactory &getBasicVals() { return BV; }
+};
+
+class SymbolReaper {
+ typedef llvm::DenseSet<SymbolRef> SetTy;
+
+ SetTy TheLiving;
+ SetTy MetadataInUse;
+ SetTy TheDead;
+ const LocationContext *LCtx;
+ const Stmt *Loc;
+ SymbolManager& SymMgr;
+
+public:
+ SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr)
+ : LCtx(ctx), Loc(s), SymMgr(symmgr) {}
+
+ ~SymbolReaper() {}
+
+ const LocationContext *getLocationContext() const { return LCtx; }
+ const Stmt *getCurrentStatement() const { return Loc; }
+
+ bool isLive(SymbolRef sym);
+ bool isLive(const Stmt *ExprVal) const;
+ bool isLive(const VarRegion *VR) const;
+
+ // markLive - Unconditionally marks a symbol as live. This should never be
+ // used by checkers, only by the state infrastructure such as the store and
+ // environment. Checkers should instead use metadata symbols and markInUse.
+ void markLive(SymbolRef sym);
+
+ // markInUse - Marks a symbol as important to a checker. For metadata symbols,
+ // this will keep the symbol alive as long as its associated region is also
+ // live. For other symbols, this has no effect; checkers are not permitted
+ // to influence the life of other symbols. This should be used before any
+ // symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
+ void markInUse(SymbolRef sym);
+
+ // maybeDead - If a symbol is known to be live, marks the symbol as live.
+ // Otherwise, if the symbol cannot be proven live, it is marked as dead.
+ // Returns true if the symbol is dead, false if live.
+ bool maybeDead(SymbolRef sym);
+
+ typedef SetTy::const_iterator dead_iterator;
+ dead_iterator dead_begin() const { return TheDead.begin(); }
+ dead_iterator dead_end() const { return TheDead.end(); }
+
+ bool hasDeadSymbols() const {
+ return !TheDead.empty();
+ }
+
+ /// isDead - Returns whether or not a symbol has been confirmed dead. This
+ /// should only be called once all marking of dead symbols has completed.
+ /// (For checkers, this means only in the evalDeadSymbols callback.)
+ bool isDead(SymbolRef sym) const {
+ return TheDead.count(sym);
+ }
+};
+
+class SymbolVisitor {
+public:
+ // VisitSymbol - A visitor method invoked by
+ // GRStateManager::scanReachableSymbols. The method returns \c true if
+ // symbols should continue be scanned and \c false otherwise.
+ virtual bool VisitSymbol(SymbolRef sym) = 0;
+ virtual ~SymbolVisitor();
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+namespace llvm {
+static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
+ const clang::ento::SymExpr *SE) {
+ SE->dumpToStream(os);
+ return os;
+}
+} // end llvm namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
new file mode 100644
index 0000000..23ed2be
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h
@@ -0,0 +1,93 @@
+//== TransferFuncs.h - Path-Sens. Transfer Functions Interface ---*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines TransferFuncs, which provides a base-class that
+// defines an interface for transfer functions used by ExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_TRANSFERFUNCS
+#define LLVM_CLANG_GR_TRANSFERFUNCS
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include <vector>
+
+namespace clang {
+class ObjCMessageExpr;
+
+namespace ento {
+class ExplodedNode;
+class ExplodedNodeSet;
+class EndOfFunctionNodeBuilder;
+class ExprEngine;
+class StmtNodeBuilder;
+class StmtNodeBuilderRef;
+
+class TransferFuncs {
+public:
+ TransferFuncs() {}
+ virtual ~TransferFuncs() {}
+
+ virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
+ virtual void RegisterChecks(ExprEngine& Eng) {}
+
+
+ // Calls.
+
+ virtual void evalCall(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ const CallExpr* CE, SVal L,
+ ExplodedNode* Pred) {}
+
+ virtual void evalObjCMessage(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ObjCMessage msg,
+ ExplodedNode* Pred,
+ const GRState *state) {}
+
+ // Stores.
+
+ virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val) {}
+
+ // End-of-path and dead symbol notification.
+
+ virtual void evalEndPath(ExprEngine& Engine,
+ EndOfFunctionNodeBuilder& Builder) {}
+
+
+ virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ExplodedNode* Pred,
+ const GRState* state,
+ SymbolReaper& SymReaper) {}
+
+ // Return statements.
+ virtual void evalReturn(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ const ReturnStmt* S,
+ ExplodedNode* Pred) {}
+
+ // Assumptions.
+ virtual const GRState* evalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
+ return state;
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
new file mode 100644
index 0000000..6bc9fe5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -0,0 +1,101 @@
+//==- WorkList.h - Worklist class used by CoreEngine ---------------*- 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 WorkList, a pure virtual class that represents an opaque
+// worklist used by CoreEngine to explore the reachability state space.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_WORKLIST
+#define LLVM_CLANG_GR_WORKLIST
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include <cstddef>
+
+namespace clang {
+
+class CFGBlock;
+
+namespace ento {
+
+class ExplodedNode;
+class ExplodedNodeImpl;
+
+class WorkListUnit {
+ ExplodedNode* node;
+ BlockCounter counter;
+ const CFGBlock* block;
+ unsigned blockIdx; // This is the index of the next statement.
+
+public:
+ WorkListUnit(ExplodedNode* N, BlockCounter C,
+ const CFGBlock* B, unsigned idx)
+ : node(N),
+ counter(C),
+ block(B),
+ blockIdx(idx) {}
+
+ explicit WorkListUnit(ExplodedNode* N, BlockCounter C)
+ : node(N),
+ counter(C),
+ block(NULL),
+ blockIdx(0) {}
+
+ /// Returns the node associated with the worklist unit.
+ ExplodedNode *getNode() const { return node; }
+
+ /// Returns the block counter map associated with the worklist unit.
+ BlockCounter getBlockCounter() const { return counter; }
+
+ /// Returns the CFGblock associated with the worklist unit.
+ const CFGBlock *getBlock() const { return block; }
+
+ /// Return the index within the CFGBlock for the worklist unit.
+ unsigned getIndex() const { return blockIdx; }
+};
+
+class WorkList {
+ BlockCounter CurrentCounter;
+public:
+ virtual ~WorkList();
+ virtual bool hasWork() const = 0;
+
+ virtual void enqueue(const WorkListUnit& U) = 0;
+
+ void enqueue(ExplodedNode *N, const CFGBlock *B, unsigned idx) {
+ enqueue(WorkListUnit(N, CurrentCounter, B, idx));
+ }
+
+ void enqueue(ExplodedNode *N) {
+ enqueue(WorkListUnit(N, CurrentCounter));
+ }
+
+ virtual WorkListUnit dequeue() = 0;
+
+ void setBlockCounter(BlockCounter C) { CurrentCounter = C; }
+ BlockCounter getBlockCounter() const { return CurrentCounter; }
+
+ class Visitor {
+ public:
+ Visitor() {}
+ virtual ~Visitor();
+ virtual bool visit(const WorkListUnit &U) = 0;
+ };
+ virtual bool visitItemsInWorkList(Visitor &V) = 0;
+
+ static WorkList *makeDFS();
+ static WorkList *makeBFS();
+ static WorkList *makeBFSBlockDFSContents();
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
new file mode 100644
index 0000000..4c3e379
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -0,0 +1,26 @@
+//===-- CheckerRegistration.h - Checker Registration Function-------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_FRONTEND_CHECKERREGISTRATION_H
+#define LLVM_CLANG_SA_FRONTEND_CHECKERREGISTRATION_H
+
+namespace clang {
+ class AnalyzerOptions;
+ class Diagnostic;
+
+namespace ento {
+ class CheckerManager;
+
+CheckerManager *registerCheckers(const AnalyzerOptions &opts,Diagnostic &diags);
+
+} // end ento namespace
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
new file mode 100644
index 0000000..e3867a2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -0,0 +1,33 @@
+//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_FRONTENDACTIONS_H
+#define LLVM_CLANG_GR_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+namespace clang {
+
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class AnalysisAction : public ASTFrontendAction {
+protected:
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile);
+};
+
+} // end GR namespace
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
new file mode 100644
index 0000000..731d5e0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp
@@ -0,0 +1,142 @@
+//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the APValue class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/CharUnits.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+ struct LV {
+ Expr* Base;
+ CharUnits Offset;
+ };
+}
+
+APValue::APValue(Expr* B) : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, CharUnits::Zero());
+}
+
+const APValue &APValue::operator=(const APValue &RHS) {
+ if (Kind != RHS.Kind) {
+ MakeUninit();
+ if (RHS.isInt())
+ MakeInt();
+ else if (RHS.isFloat())
+ MakeFloat();
+ else if (RHS.isVector())
+ MakeVector();
+ else if (RHS.isComplexInt())
+ MakeComplexInt();
+ else if (RHS.isComplexFloat())
+ MakeComplexFloat();
+ else if (RHS.isLValue())
+ MakeLValue();
+ }
+ if (isInt())
+ setInt(RHS.getInt());
+ else if (isFloat())
+ setFloat(RHS.getFloat());
+ else if (isVector())
+ setVector(((const Vec *)(const char *)RHS.Data)->Elts,
+ RHS.getVectorLength());
+ else if (isComplexInt())
+ setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
+ else if (isComplexFloat())
+ setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
+ else if (isLValue())
+ setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
+ return *this;
+}
+
+void APValue::MakeUninit() {
+ if (Kind == Int)
+ ((APSInt*)(char*)Data)->~APSInt();
+ else if (Kind == Float)
+ ((APFloat*)(char*)Data)->~APFloat();
+ else if (Kind == Vector)
+ ((Vec*)(char*)Data)->~Vec();
+ else if (Kind == ComplexInt)
+ ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
+ else if (Kind == ComplexFloat)
+ ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
+ else if (Kind == LValue) {
+ ((LV*)(char*)Data)->~LV();
+ }
+ Kind = Uninitialized;
+}
+
+void APValue::dump() const {
+ print(llvm::errs());
+ llvm::errs() << '\n';
+}
+
+static double GetApproxValue(const llvm::APFloat &F) {
+ llvm::APFloat V = F;
+ bool ignored;
+ V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ &ignored);
+ return V.convertToDouble();
+}
+
+void APValue::print(llvm::raw_ostream &OS) const {
+ switch (getKind()) {
+ default: assert(0 && "Unknown APValue kind!");
+ case Uninitialized:
+ OS << "Uninitialized";
+ return;
+ case Int:
+ OS << "Int: " << getInt();
+ return;
+ case Float:
+ OS << "Float: " << GetApproxValue(getFloat());
+ return;
+ case Vector:
+ OS << "Vector: " << getVectorElt(0);
+ for (unsigned i = 1; i != getVectorLength(); ++i)
+ OS << ", " << getVectorElt(i);
+ return;
+ case ComplexInt:
+ OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
+ return;
+ case ComplexFloat:
+ OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
+ << ", " << GetApproxValue(getComplexFloatImag());
+ case LValue:
+ OS << "LValue: <todo>";
+ return;
+ }
+}
+
+Expr* APValue::getLValueBase() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Base;
+}
+
+CharUnits APValue::getLValueOffset() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Offset;
+}
+
+void APValue::setLValue(Expr *B, const CharUnits &O) {
+ assert(isLValue() && "Invalid accessor");
+ ((LV*)(char*)Data)->Base = B;
+ ((LV*)(char*)Data)->Offset = O;
+}
+
+void APValue::MakeLValue() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) LV();
+ Kind = LValue;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp
new file mode 100644
index 0000000..04a084a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp
@@ -0,0 +1,22 @@
+//===--- ASTConsumer.cpp - Abstract interface for reading ASTs --*- 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 ASTConsumer class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclGroup.h"
+using namespace clang;
+
+void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+
+void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
+ HandleTopLevelDecl(D);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
new file mode 100644
index 0000000..945dfb8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -0,0 +1,6071 @@
+//===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ASTContext interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#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"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "CXXABI.h"
+
+using namespace clang;
+
+unsigned ASTContext::NumImplicitDefaultConstructors;
+unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
+unsigned ASTContext::NumImplicitCopyConstructors;
+unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
+unsigned ASTContext::NumImplicitCopyAssignmentOperators;
+unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+unsigned ASTContext::NumImplicitDestructors;
+unsigned ASTContext::NumImplicitDestructorsDeclared;
+
+enum FloatingRank {
+ FloatRank, DoubleRank, LongDoubleRank
+};
+
+void
+ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateTemplateParmDecl *Parm) {
+ ID.AddInteger(Parm->getDepth());
+ ID.AddInteger(Parm->getPosition());
+ ID.AddBoolean(Parm->isParameterPack());
+
+ TemplateParameterList *Params = Parm->getTemplateParameters();
+ ID.AddInteger(Params->size());
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+ ID.AddInteger(0);
+ ID.AddBoolean(TTP->isParameterPack());
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ ID.AddInteger(1);
+ 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;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ ID.AddInteger(2);
+ Profile(ID, TTP);
+ }
+}
+
+TemplateTemplateParmDecl *
+ASTContext::getCanonicalTemplateTemplateParmDecl(
+ TemplateTemplateParmDecl *TTP) const {
+ // Check if we already have a canonical template template parameter.
+ llvm::FoldingSetNodeID ID;
+ CanonicalTemplateTemplateParm::Profile(ID, TTP);
+ void *InsertPos = 0;
+ CanonicalTemplateTemplateParm *Canonical
+ = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
+ if (Canonical)
+ return Canonical->getParam();
+
+ // Build a canonical template parameter list.
+ TemplateParameterList *Params = TTP->getTemplateParameters();
+ llvm::SmallVector<NamedDecl *, 4> CanonParams;
+ CanonParams.reserve(Params->size());
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P))
+ CanonParams.push_back(
+ TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(), TTP->getDepth(),
+ TTP->getIndex(), 0, false,
+ TTP->isParameterPack()));
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ QualType T = getCanonicalType(NTTP->getType());
+ TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T);
+ NonTypeTemplateParmDecl *Param;
+ if (NTTP->isExpandedParameterPack()) {
+ llvm::SmallVector<QualType, 2> ExpandedTypes;
+ llvm::SmallVector<TypeSourceInfo *, 2> 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<TemplateTemplateParmDecl>(*P)));
+ }
+
+ TemplateTemplateParmDecl *CanonTTP
+ = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(), TTP->getDepth(),
+ TTP->getPosition(),
+ TTP->isParameterPack(),
+ 0,
+ TemplateParameterList::Create(*this, SourceLocation(),
+ SourceLocation(),
+ CanonParams.data(),
+ CanonParams.size(),
+ SourceLocation()));
+
+ // Get the new insert position for the node we care about.
+ Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
+ assert(Canonical == 0 && "Shouldn't be in the map!");
+ (void)Canonical;
+
+ // Create the canonical template template parameter entry.
+ Canonical = new (*this) CanonicalTemplateTemplateParm(CanonTTP);
+ CanonTemplateTemplateParms.InsertNode(Canonical, InsertPos);
+ return CanonTTP;
+}
+
+CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
+ if (!LangOpts.CPlusPlus) return 0;
+
+ switch (T.getCXXABI()) {
+ case CXXABI_ARM:
+ return CreateARMCXXABI(*this);
+ case CXXABI_Itanium:
+ return CreateItaniumCXXABI(*this);
+ case CXXABI_Microsoft:
+ return CreateMicrosoftCXXABI(*this);
+ }
+ return 0;
+}
+
+ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
+ const TargetInfo &t,
+ IdentifierTable &idents, SelectorTable &sels,
+ Builtin::Context &builtins,
+ unsigned size_reserve) :
+ TemplateSpecializationTypes(this_()),
+ DependentTemplateSpecializationTypes(this_()),
+ GlobalNestedNameSpecifier(0), IsInt128Installed(false),
+ 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), Listener(0), PrintingPolicy(LOpts),
+ LastSDM(0, 0),
+ UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
+ ObjCIdRedefinitionType = QualType();
+ ObjCClassRedefinitionType = QualType();
+ ObjCSelRedefinitionType = QualType();
+ if (size_reserve > 0) Types.reserve(size_reserve);
+ TUDecl = TranslationUnitDecl::Create(*this);
+ InitBuiltinTypes();
+}
+
+ASTContext::~ASTContext() {
+ // Release the DenseMaps associated with DeclContext objects.
+ // FIXME: Is this the ideal solution?
+ ReleaseDeclContextMaps();
+
+ // Call all of the deallocation functions.
+ for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
+ Deallocations[I].first(Deallocations[I].second);
+
+ // Release all of the memory associated with overridden C++ methods.
+ for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator
+ OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end();
+ OM != OMEnd; ++OM)
+ OM->second.Destroy();
+
+ // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
+ // because they can contain DenseMaps.
+ for (llvm::DenseMap<const ObjCContainerDecl*,
+ const ASTRecordLayout*>::iterator
+ I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; )
+ // Increment in loop to prevent using deallocated memory.
+ if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ R->Destroy(*this);
+
+ for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
+ I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
+ // Increment in loop to prevent using deallocated memory.
+ if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ R->Destroy(*this);
+ }
+
+ for (llvm::DenseMap<const Decl*, AttrVec*>::iterator A = DeclAttrs.begin(),
+ AEnd = DeclAttrs.end();
+ A != AEnd; ++A)
+ A->second->~AttrVec();
+}
+
+void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
+ Deallocations.push_back(std::make_pair(Callback, Data));
+}
+
+void
+ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
+ ExternalSource.reset(Source.take());
+}
+
+void ASTContext::PrintStats() const {
+ fprintf(stderr, "*** AST Context Stats:\n");
+ fprintf(stderr, " %d types total.\n", (int)Types.size());
+
+ unsigned counts[] = {
+#define TYPE(Name, Parent) 0,
+#define ABSTRACT_TYPE(Name, Parent)
+#include "clang/AST/TypeNodes.def"
+ 0 // Extra
+ };
+
+ for (unsigned i = 0, e = Types.size(); i != e; ++i) {
+ Type *T = Types[i];
+ counts[(unsigned)T->getTypeClass()]++;
+ }
+
+ unsigned Idx = 0;
+ unsigned TotalBytes = 0;
+#define TYPE(Name, Parent) \
+ if (counts[Idx]) \
+ fprintf(stderr, " %d %s types\n", (int)counts[Idx], #Name); \
+ TotalBytes += counts[Idx] * sizeof(Name##Type); \
+ ++Idx;
+#define ABSTRACT_TYPE(Name, Parent)
+#include "clang/AST/TypeNodes.def"
+
+ fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
+
+ // Implicit special member functions.
+ fprintf(stderr, " %u/%u implicit default constructors created\n",
+ NumImplicitDefaultConstructorsDeclared,
+ NumImplicitDefaultConstructors);
+ fprintf(stderr, " %u/%u implicit copy constructors created\n",
+ NumImplicitCopyConstructorsDeclared,
+ NumImplicitCopyConstructors);
+ fprintf(stderr, " %u/%u implicit copy assignment operators created\n",
+ NumImplicitCopyAssignmentOperatorsDeclared,
+ NumImplicitCopyAssignmentOperators);
+ fprintf(stderr, " %u/%u implicit destructors created\n",
+ NumImplicitDestructorsDeclared, NumImplicitDestructors);
+
+ if (ExternalSource.get()) {
+ fprintf(stderr, "\n");
+ ExternalSource->PrintStats();
+ }
+
+ BumpAlloc.PrintStats();
+}
+
+
+void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
+ BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
+ R = CanQualType::CreateUnsafe(QualType(Ty, 0));
+ Types.push_back(Ty);
+}
+
+void ASTContext::InitBuiltinTypes() {
+ assert(VoidTy.isNull() && "Context reinitialized?");
+
+ // C99 6.2.5p19.
+ InitBuiltinType(VoidTy, BuiltinType::Void);
+
+ // C99 6.2.5p2.
+ InitBuiltinType(BoolTy, BuiltinType::Bool);
+ // C99 6.2.5p3.
+ if (LangOpts.CharIsSigned)
+ InitBuiltinType(CharTy, BuiltinType::Char_S);
+ else
+ InitBuiltinType(CharTy, BuiltinType::Char_U);
+ // C99 6.2.5p4.
+ InitBuiltinType(SignedCharTy, BuiltinType::SChar);
+ InitBuiltinType(ShortTy, BuiltinType::Short);
+ InitBuiltinType(IntTy, BuiltinType::Int);
+ InitBuiltinType(LongTy, BuiltinType::Long);
+ InitBuiltinType(LongLongTy, BuiltinType::LongLong);
+
+ // C99 6.2.5p6.
+ InitBuiltinType(UnsignedCharTy, BuiltinType::UChar);
+ InitBuiltinType(UnsignedShortTy, BuiltinType::UShort);
+ InitBuiltinType(UnsignedIntTy, BuiltinType::UInt);
+ InitBuiltinType(UnsignedLongTy, BuiltinType::ULong);
+ InitBuiltinType(UnsignedLongLongTy, BuiltinType::ULongLong);
+
+ // C99 6.2.5p10.
+ InitBuiltinType(FloatTy, BuiltinType::Float);
+ InitBuiltinType(DoubleTy, BuiltinType::Double);
+ InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble);
+
+ // GNU extension, 128-bit integers.
+ InitBuiltinType(Int128Ty, BuiltinType::Int128);
+ InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
+
+ 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++
+ InitBuiltinType(Char16Ty, BuiltinType::Char16);
+ else // C99
+ Char16Ty = getFromTargetType(Target.getChar16Type());
+
+ if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++
+ InitBuiltinType(Char32Ty, BuiltinType::Char32);
+ else // C99
+ Char32Ty = getFromTargetType(Target.getChar32Type());
+
+ // 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
+ // help diagnose failures to properly check for type-dependent
+ // expressions.
+ InitBuiltinType(DependentTy, BuiltinType::Dependent);
+
+ // Placeholder type for functions.
+ InitBuiltinType(OverloadTy, BuiltinType::Overload);
+
+ // C99 6.2.5p11.
+ FloatComplexTy = getComplexType(FloatTy);
+ DoubleComplexTy = getComplexType(DoubleTy);
+ LongDoubleComplexTy = getComplexType(LongDoubleTy);
+
+ BuiltinVaListType = QualType();
+
+ // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
+ ObjCIdTypedefType = QualType();
+ ObjCClassTypedefType = QualType();
+ ObjCSelTypedefType = QualType();
+
+ // Builtin types for 'id', 'Class', and 'SEL'.
+ InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
+ InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
+ InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
+
+ ObjCConstantStringType = QualType();
+
+ // void * type
+ VoidPtrTy = getPointerType(VoidTy);
+
+ // nullptr type (C++0x 2.14.7)
+ InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
+}
+
+Diagnostic &ASTContext::getDiagnostics() const {
+ return SourceMgr.getDiagnostics();
+}
+
+AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
+ AttrVec *&Result = DeclAttrs[D];
+ if (!Result) {
+ void *Mem = Allocate(sizeof(AttrVec));
+ Result = new (Mem) AttrVec;
+ }
+
+ return *Result;
+}
+
+/// \brief Erase the attributes corresponding to the given declaration.
+void ASTContext::eraseDeclAttrs(const Decl *D) {
+ llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
+ if (Pos != DeclAttrs.end()) {
+ Pos->second->~AttrVec();
+ DeclAttrs.erase(Pos);
+ }
+}
+
+
+MemberSpecializationInfo *
+ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
+ assert(Var->isStaticDataMember() && "Not a static data member");
+ llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
+ = InstantiatedFromStaticDataMember.find(Var);
+ if (Pos == InstantiatedFromStaticDataMember.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
+ TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
+ assert(Inst->isStaticDataMember() && "Not a static data member");
+ assert(Tmpl->isStaticDataMember() && "Not a static data member");
+ assert(!InstantiatedFromStaticDataMember[Inst] &&
+ "Already noted what static data member was instantiated from");
+ InstantiatedFromStaticDataMember[Inst]
+ = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation);
+}
+
+NamedDecl *
+ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
+ llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
+ = InstantiatedFromUsingDecl.find(UUD);
+ if (Pos == InstantiatedFromUsingDecl.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+ assert((isa<UsingDecl>(Pattern) ||
+ isa<UnresolvedUsingValueDecl>(Pattern) ||
+ isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
+ "pattern decl is not a using decl");
+ assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingDecl[Inst] = Pattern;
+}
+
+UsingShadowDecl *
+ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
+ llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
+ = InstantiatedFromUsingShadowDecl.find(Inst);
+ if (Pos == InstantiatedFromUsingShadowDecl.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+ UsingShadowDecl *Pattern) {
+ assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingShadowDecl[Inst] = Pattern;
+}
+
+FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
+ llvm::DenseMap<FieldDecl *, FieldDecl *>::iterator Pos
+ = InstantiatedFromUnnamedFieldDecl.find(Field);
+ if (Pos == InstantiatedFromUnnamedFieldDecl.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst,
+ FieldDecl *Tmpl) {
+ assert(!Inst->getDeclName() && "Instantiated field decl is not unnamed");
+ assert(!Tmpl->getDeclName() && "Template field decl is not unnamed");
+ assert(!InstantiatedFromUnnamedFieldDecl[Inst] &&
+ "Already noted what unnamed field was instantiated from");
+
+ InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl;
+}
+
+ASTContext::overridden_cxx_method_iterator
+ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.begin();
+}
+
+ASTContext::overridden_cxx_method_iterator
+ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.end();
+}
+
+unsigned
+ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.size();
+}
+
+void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
+ const CXXMethodDecl *Overridden) {
+ OverriddenMethods[Method].push_back(Overridden);
+}
+
+//===----------------------------------------------------------------------===//
+// Type Sizing and Analysis
+//===----------------------------------------------------------------------===//
+
+/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
+/// scalar floating point type.
+const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
+ const BuiltinType *BT = T->getAs<BuiltinType>();
+ assert(BT && "Not a floating point type!");
+ switch (BT->getKind()) {
+ default: assert(0 && "Not a floating point type!");
+ case BuiltinType::Float: return Target.getFloatFormat();
+ case BuiltinType::Double: return Target.getDoubleFormat();
+ case BuiltinType::LongDouble: return Target.getLongDoubleFormat();
+ }
+}
+
+/// getDeclAlign - Return a conservative estimate of the alignment of the
+/// specified decl. Note that bitfields do not have a valid alignment, so
+/// 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) const {
+ unsigned Align = Target.getCharWidth();
+
+ 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<FieldDecl>(D)) {
+ UseAlignAttrOnly = D->hasAttr<PackedAttr>() ||
+ cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
+ } else {
+ UseAlignAttrOnly = true;
+ }
+ }
+
+ // 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<ValueDecl>(D)) {
+ QualType T = VD->getType();
+ if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
+ if (RefAsPointee)
+ T = RT->getPointeeType();
+ else
+ 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();
+ const ArrayType *arrayType;
+ if (MinWidth && (arrayType = getAsArrayType(T))) {
+ if (isa<VariableArrayType>(arrayType))
+ Align = std::max(Align, Target.getLargeArrayAlign());
+ else if (isa<ConstantArrayType>(arrayType) &&
+ MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType)))
+ Align = std::max(Align, Target.getLargeArrayAlign());
+
+ // Walk through any array types while we're at it.
+ T = getBaseElementType(arrayType);
+ }
+ Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
+ }
+
+ // 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<FieldDecl>(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<unsigned>(lowBitOfOffset);
+ }
+
+ Align = std::min(Align, fieldAlign);
+ }
+ }
+
+ return toCharUnitsFromBits(Align);
+}
+
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoInChars(const Type *T) const {
+ std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
+ return std::make_pair(toCharUnitsFromBits(Info.first),
+ toCharUnitsFromBits(Info.second));
+}
+
+std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoInChars(QualType T) const {
+ return getTypeInfoInChars(T.getTypePtr());
+}
+
+/// getTypeSize - Return the size of the specified type, in bits. This method
+/// does not work on incomplete types.
+///
+/// FIXME: Pointers into different addr spaces could have different sizes and
+/// alignment requirements: getPointerInfo should take an AddrSpace, this
+/// should take a QualType, &c.
+std::pair<uint64_t, unsigned>
+ASTContext::getTypeInfo(const Type *T) const {
+ uint64_t Width=0;
+ unsigned Align=8;
+ switch (T->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Should not see dependent types");
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // GCC extension: alignof(function) = 32 bits
+ Width = 0;
+ Align = 32;
+ break;
+
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ Width = 0;
+ Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
+ break;
+
+ case Type::ConstantArray: {
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
+
+ std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
+ Width = EltInfo.first*CAT->getSize().getZExtValue();
+ Align = EltInfo.second;
+ break;
+ }
+ case Type::ExtVector:
+ case Type::Vector: {
+ const VectorType *VT = cast<VectorType>(T);
+ std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType());
+ Width = EltInfo.first*VT->getNumElements();
+ Align = Width;
+ // If the alignment is not a power of 2, round up to the next power of 2.
+ // This happens for non-power-of-2 length vectors.
+ if (Align & (Align-1)) {
+ Align = llvm::NextPowerOf2(Align);
+ Width = llvm::RoundUpToAlignment(Width, Align);
+ }
+ break;
+ }
+
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ default: assert(0 && "Unknown builtin type!");
+ case BuiltinType::Void:
+ // GCC extension: alignof(void) = 8 bits.
+ Width = 0;
+ Align = 8;
+ break;
+
+ case BuiltinType::Bool:
+ Width = Target.getBoolWidth();
+ Align = Target.getBoolAlign();
+ break;
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ Width = Target.getCharWidth();
+ Align = Target.getCharAlign();
+ break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ Width = Target.getWCharWidth();
+ Align = Target.getWCharAlign();
+ break;
+ case BuiltinType::Char16:
+ Width = Target.getChar16Width();
+ Align = Target.getChar16Align();
+ break;
+ case BuiltinType::Char32:
+ Width = Target.getChar32Width();
+ Align = Target.getChar32Align();
+ break;
+ case BuiltinType::UShort:
+ case BuiltinType::Short:
+ Width = Target.getShortWidth();
+ Align = Target.getShortAlign();
+ break;
+ case BuiltinType::UInt:
+ case BuiltinType::Int:
+ Width = Target.getIntWidth();
+ Align = Target.getIntAlign();
+ break;
+ case BuiltinType::ULong:
+ case BuiltinType::Long:
+ Width = Target.getLongWidth();
+ Align = Target.getLongAlign();
+ break;
+ case BuiltinType::ULongLong:
+ case BuiltinType::LongLong:
+ Width = Target.getLongLongWidth();
+ Align = Target.getLongLongAlign();
+ break;
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ Width = 128;
+ Align = 128; // int128_t is 128-bit aligned on all targets.
+ break;
+ case BuiltinType::Float:
+ Width = Target.getFloatWidth();
+ Align = Target.getFloatAlign();
+ break;
+ case BuiltinType::Double:
+ Width = Target.getDoubleWidth();
+ Align = Target.getDoubleAlign();
+ break;
+ case BuiltinType::LongDouble:
+ Width = Target.getLongDoubleWidth();
+ Align = Target.getLongDoubleAlign();
+ break;
+ case BuiltinType::NullPtr:
+ Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
+ Align = Target.getPointerAlign(0); // == sizeof(void*)
+ break;
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ Width = Target.getPointerWidth(0);
+ Align = Target.getPointerAlign(0);
+ break;
+ }
+ break;
+ case Type::ObjCObjectPointer:
+ Width = Target.getPointerWidth(0);
+ Align = Target.getPointerAlign(0);
+ break;
+ case Type::BlockPointer: {
+ unsigned AS = cast<BlockPointerType>(T)->getPointeeType().getAddressSpace();
+ Width = Target.getPointerWidth(AS);
+ Align = Target.getPointerAlign(AS);
+ break;
+ }
+ case Type::LValueReference:
+ case Type::RValueReference: {
+ // alignof and sizeof should never enter this code path here, so we go
+ // the pointer route.
+ unsigned AS = cast<ReferenceType>(T)->getPointeeType().getAddressSpace();
+ Width = Target.getPointerWidth(AS);
+ Align = Target.getPointerAlign(AS);
+ break;
+ }
+ case Type::Pointer: {
+ unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
+ Width = Target.getPointerWidth(AS);
+ Align = Target.getPointerAlign(AS);
+ break;
+ }
+ case Type::MemberPointer: {
+ const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ std::pair<uint64_t, unsigned> PtrDiffInfo =
+ getTypeInfo(getPointerDiffType());
+ Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT);
+ Align = PtrDiffInfo.second;
+ break;
+ }
+ case Type::Complex: {
+ // Complex types have the same alignment as their elements, but twice the
+ // size.
+ std::pair<uint64_t, unsigned> EltInfo =
+ getTypeInfo(cast<ComplexType>(T)->getElementType());
+ Width = EltInfo.first*2;
+ Align = EltInfo.second;
+ break;
+ }
+ case Type::ObjCObject:
+ return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
+ case Type::ObjCInterface: {
+ const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
+ const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
+ Width = toBits(Layout.getSize());
+ Align = toBits(Layout.getAlignment());
+ break;
+ }
+ case Type::Record:
+ case Type::Enum: {
+ const TagType *TT = cast<TagType>(T);
+
+ if (TT->getDecl()->isInvalidDecl()) {
+ Width = 1;
+ Align = 1;
+ break;
+ }
+
+ if (const EnumType *ET = dyn_cast<EnumType>(TT))
+ return getTypeInfo(ET->getDecl()->getIntegerType());
+
+ const RecordType *RT = cast<RecordType>(TT);
+ const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
+ Width = toBits(Layout.getSize());
+ Align = toBits(Layout.getAlignment());
+ break;
+ }
+
+ case Type::SubstTemplateTypeParm:
+ return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
+ getReplacementType().getTypePtr());
+
+ case Type::Auto: {
+ const AutoType *A = cast<AutoType>(T);
+ assert(A->isDeduced() && "Cannot request the size of a dependent type");
+ return getTypeInfo(cast<AutoType>(T)->getDeducedType().getTypePtr());
+ }
+
+ case Type::Paren:
+ return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
+
+ case Type::Typedef: {
+ const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
+ std::pair<uint64_t, unsigned> Info
+ = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ // 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;
+ }
+
+ case Type::TypeOfExpr:
+ return getTypeInfo(cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType()
+ .getTypePtr());
+
+ case Type::TypeOf:
+ return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr());
+
+ case Type::Decltype:
+ return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
+ .getTypePtr());
+
+ case Type::Elaborated:
+ return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
+
+ case Type::Attributed:
+ return getTypeInfo(
+ cast<AttributedType>(T)->getEquivalentType().getTypePtr());
+
+ case Type::TemplateSpecialization:
+ assert(getCanonicalType(T) != T &&
+ "Cannot request the size of a dependent type");
+ // FIXME: this is likely to be wrong once we support template
+ // aliases, since a template alias could refer to a typedef that
+ // has an __aligned__ attribute on it.
+ return getTypeInfo(getCanonicalType(T));
+ }
+
+ assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
+ 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) const {
+ return toCharUnitsFromBits(getTypeSize(T));
+}
+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) const {
+ return toCharUnitsFromBits(getTypeAlign(T));
+}
+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) const {
+ unsigned ABIAlign = getTypeAlign(T);
+
+ // Double and long long should be naturally aligned if possible.
+ if (const ComplexType* CT = T->getAs<ComplexType>())
+ T = CT->getElementType().getTypePtr();
+ if (T->isSpecificBuiltinType(BuiltinType::Double) ||
+ T->isSpecificBuiltinType(BuiltinType::LongLong))
+ return std::max(ABIAlign, (unsigned)getTypeSize(T));
+
+ return ABIAlign;
+}
+
+/// ShallowCollectObjCIvars -
+/// Collect all ivars, including those synthesized, in the current class.
+///
+void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const {
+ // FIXME. This need be removed but there are two many places which
+ // assume const-ness of ObjCInterfaceDecl
+ ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar())
+ Ivars.push_back(Iv);
+}
+
+/// DeepCollectObjCIvars -
+/// This routine first collects all declared, but not synthesized, ivars in
+/// super class and then collects all ivars, including those synthesized for
+/// current class. This routine is used for implementation of current class
+/// when all ivars, declared and synthesized are known.
+///
+void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
+ bool leafClass,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) const {
+ if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
+ DeepCollectObjCIvars(SuperClass, false, Ivars);
+ if (!leafClass) {
+ for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
+ E = OI->ivar_end(); I != E; ++I)
+ Ivars.push_back(*I);
+ }
+ else
+ ShallowCollectObjCIvars(OI, Ivars);
+}
+
+/// CollectInheritedProtocols - Collect all protocols in current class and
+/// those inherited by it.
+void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
+ if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ // We can use protocol_iterator here instead of
+ // all_referenced_protocol_iterator since we are walking all categories.
+ for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
+ PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.insert(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P) {
+ Protocols.insert(*P);
+ CollectInheritedProtocols(*P, Protocols);
+ }
+ }
+
+ // Categories of this Interface.
+ for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList();
+ CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
+ CollectInheritedProtocols(CDeclChain, Protocols);
+ if (ObjCInterfaceDecl *SD = OI->getSuperClass())
+ while (SD) {
+ CollectInheritedProtocols(SD, Protocols);
+ SD = SD->getSuperClass();
+ }
+ } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
+ PE = OC->protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.insert(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P)
+ CollectInheritedProtocols(*P, Protocols);
+ }
+ } else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
+ PE = OP->protocol_end(); P != PE; ++P) {
+ ObjCProtocolDecl *Proto = (*P);
+ Protocols.insert(Proto);
+ for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+ PE = Proto->protocol_end(); P != PE; ++P)
+ CollectInheritedProtocols(*P, Protocols);
+ }
+ }
+}
+
+unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
+ unsigned count = 0;
+ // Count ivars declared in class extension.
+ for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension())
+ count += CDecl->ivar_size();
+
+ // Count ivar defined in this class's implementation. This
+ // includes synthesized ivars.
+ if (ObjCImplementationDecl *ImplDecl = OI->getImplementation())
+ count += ImplDecl->ivar_size();
+
+ return count;
+}
+
+/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
+ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+ I = ObjCImpls.find(D);
+ if (I != ObjCImpls.end())
+ return cast<ObjCImplementationDecl>(I->second);
+ return 0;
+}
+/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
+ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
+ I = ObjCImpls.find(D);
+ if (I != ObjCImpls.end())
+ return cast<ObjCCategoryImplDecl>(I->second);
+ return 0;
+}
+
+/// \brief Set the implementation of ObjCInterfaceDecl.
+void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
+ ObjCImplementationDecl *ImplD) {
+ assert(IFaceD && ImplD && "Passed null params");
+ ObjCImpls[IFaceD] = ImplD;
+}
+/// \brief Set the implementation of ObjCCategoryDecl.
+void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
+ ObjCCategoryImplDecl *ImplD) {
+ assert(CatD && ImplD && "Passed null params");
+ 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<BlocksAttr>() &&
+ "getBlockVarCopyInits - not __block var");
+ llvm::DenseMap<const VarDecl*, Expr*>::iterator
+ I = BlockVarCopyInits.find(VD);
+ return (I != BlockVarCopyInits.end()) ? cast<Expr>(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<BlocksAttr>() &&
+ "setBlockVarCopyInits - not __block var");
+ BlockVarCopyInits[VD] = Init;
+}
+
+/// \brief Allocate an uninitialized TypeSourceInfo.
+///
+/// The caller should initialize the memory held by TypeSourceInfo using
+/// the TypeLoc wrappers.
+///
+/// \param T the type that will be the basis for type source info. This type
+/// 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) const {
+ if (!DataSize)
+ DataSize = TypeLoc::getFullDataSizeForType(T);
+ else
+ assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
+ "incorrect data size provided to CreateTypeSourceInfo!");
+
+ TypeSourceInfo *TInfo =
+ (TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8);
+ new (TInfo) TypeSourceInfo(T);
+ return TInfo;
+}
+
+TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
+ SourceLocation L) const {
+ TypeSourceInfo *DI = CreateTypeSourceInfo(T);
+ DI->getTypeLoc().initialize(const_cast<ASTContext &>(*this), L);
+ return DI;
+}
+
+const ASTRecordLayout &
+ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const {
+ return getObjCLayout(D, 0);
+}
+
+const ASTRecordLayout &
+ASTContext::getASTObjCImplementationLayout(
+ const ObjCImplementationDecl *D) const {
+ return getObjCLayout(D->getClassInterface(), D);
+}
+
+//===----------------------------------------------------------------------===//
+// Type creation/memoization methods
+//===----------------------------------------------------------------------===//
+
+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, baseType, quals);
+ void *insertPos = 0;
+ if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) {
+ assert(eq->getQualifiers() == quals);
+ return QualType(eq, fastQuals);
+ }
+
+ // 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);
+
+ // Re-find the insert position.
+ (void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos);
+ }
+
+ ExtQuals *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals);
+ ExtQualNodes.InsertNode(eq, insertPos);
+ return QualType(eq, fastQuals);
+}
+
+QualType
+ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const {
+ QualType CanT = getCanonicalType(T);
+ if (CanT.getAddressSpace() == AddressSpace)
+ return T;
+
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+
+ // If this type already has an address space specified, it cannot get
+ // another one.
+ assert(!Quals.hasAddressSpace() &&
+ "Type cannot be in multiple addr spaces!");
+ Quals.addAddressSpace(AddressSpace);
+
+ return getExtQualType(TypeNode, Quals);
+}
+
+QualType ASTContext::getObjCGCQualType(QualType T,
+ Qualifiers::GC GCAttr) const {
+ QualType CanT = getCanonicalType(T);
+ if (CanT.getObjCGCAttr() == GCAttr)
+ return T;
+
+ if (const PointerType *ptr = T->getAs<PointerType>()) {
+ QualType Pointee = ptr->getPointeeType();
+ if (Pointee->isAnyPointerType()) {
+ QualType ResultType = getObjCGCQualType(Pointee, GCAttr);
+ return getPointerType(ResultType);
+ }
+ }
+
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+
+ // If this type already has an ObjCGC specified, it cannot get
+ // another one.
+ assert(!Quals.hasObjCGCAttr() &&
+ "Type cannot have multiple ObjCGCs!");
+ Quals.addObjCGCAttr(GCAttr);
+
+ return getExtQualType(TypeNode, Quals);
+}
+
+const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
+ FunctionType::ExtInfo Info) {
+ if (T->getExtInfo() == Info)
+ return T;
+
+ QualType Result;
+ if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) {
+ Result = getFunctionNoProtoType(FNPT->getResultType(), Info);
+ } else {
+ const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.ExtInfo = Info;
+ Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
+ FPT->getNumArgs(), EPI);
+ }
+
+ return cast<FunctionType>(Result.getTypePtr());
+}
+
+/// getComplexType - Return the uniqued reference to the type for a complex
+/// number with the specified element type.
+QualType ASTContext::getComplexType(QualType T) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ ComplexType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(CT, 0);
+
+ // If the pointee type isn't canonical, this won't be a canonical type either,
+ // so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getComplexType(getCanonicalType(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!"); (void)NewIP;
+ }
+ ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical);
+ Types.push_back(New);
+ ComplexTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// getPointerType - Return the uniqued reference to the type for a pointer to
+/// the specified type.
+QualType ASTContext::getPointerType(QualType T) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ PointerType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(PT, 0);
+
+ // If the pointee type isn't canonical, this won't be a canonical type either,
+ // so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getPointerType(getCanonicalType(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!"); (void)NewIP;
+ }
+ PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical);
+ Types.push_back(New);
+ PointerTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// getBlockPointerType - Return the uniqued reference to the type for
+/// a pointer to the specified block.
+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.
+ llvm::FoldingSetNodeID ID;
+ BlockPointerType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (BlockPointerType *PT =
+ BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(PT, 0);
+
+ // If the block pointee type isn't canonical, this won't be a canonical
+ // type either so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getBlockPointerType(getCanonicalType(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!"); (void)NewIP;
+ }
+ BlockPointerType *New
+ = new (*this, TypeAlignment) BlockPointerType(T, Canonical);
+ Types.push_back(New);
+ BlockPointerTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// getLValueReferenceType - Return the uniqued reference to the type for an
+/// lvalue reference to the specified type.
+QualType
+ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ ReferenceType::Profile(ID, T, SpelledAsLValue);
+
+ void *InsertPos = 0;
+ if (LValueReferenceType *RT =
+ LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(RT, 0);
+
+ const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+
+ // If the referencee type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!SpelledAsLValue || InnerRef || !T.isCanonical()) {
+ QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
+ Canonical = getLValueReferenceType(getCanonicalType(PointeeType));
+
+ // 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!"); (void)NewIP;
+ }
+
+ LValueReferenceType *New
+ = new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
+ SpelledAsLValue);
+ Types.push_back(New);
+ LValueReferenceTypes.InsertNode(New, InsertPos);
+
+ return QualType(New, 0);
+}
+
+/// getRValueReferenceType - Return the uniqued reference to the type for an
+/// rvalue reference to the specified type.
+QualType ASTContext::getRValueReferenceType(QualType T) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ ReferenceType::Profile(ID, T, false);
+
+ void *InsertPos = 0;
+ if (RValueReferenceType *RT =
+ RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(RT, 0);
+
+ const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+
+ // If the referencee type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (InnerRef || !T.isCanonical()) {
+ QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
+ Canonical = getRValueReferenceType(getCanonicalType(PointeeType));
+
+ // 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!"); (void)NewIP;
+ }
+
+ RValueReferenceType *New
+ = new (*this, TypeAlignment) RValueReferenceType(T, Canonical);
+ Types.push_back(New);
+ RValueReferenceTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// 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) const {
+ // Unique pointers, to guarantee there is only one pointer of a particular
+ // structure.
+ llvm::FoldingSetNodeID ID;
+ MemberPointerType::Profile(ID, T, Cls);
+
+ void *InsertPos = 0;
+ if (MemberPointerType *PT =
+ MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(PT, 0);
+
+ // If the pointee or class type isn't canonical, this won't be a canonical
+ // type either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
+ Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(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!"); (void)NewIP;
+ }
+ MemberPointerType *New
+ = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical);
+ Types.push_back(New);
+ MemberPointerTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// getConstantArrayType - Return the unique reference to the type for an
+/// array of the specified element type.
+QualType ASTContext::getConstantArrayType(QualType EltTy,
+ const llvm::APInt &ArySizeIn,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals) const {
+ assert((EltTy->isDependentType() ||
+ EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
+ "Constant array of VLAs is illegal!");
+
+ // Convert the array size into a canonical width matching the pointer size for
+ // the target.
+ llvm::APInt ArySize(ArySizeIn);
+ ArySize =
+ ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
+
+ llvm::FoldingSetNodeID ID;
+ 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 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!"); (void)NewIP;
+ }
+
+ ConstantArrayType *New = new(*this,TypeAlignment)
+ 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<PointerType>(ty)->getPointeeType()));
+ break;
+
+ case Type::LValueReference: {
+ const LValueReferenceType *lv = cast<LValueReferenceType>(ty);
+ result = getLValueReferenceType(
+ getVariableArrayDecayedType(lv->getPointeeType()),
+ lv->isSpelledAsLValue());
+ break;
+ }
+
+ case Type::RValueReference: {
+ const RValueReferenceType *lv = cast<RValueReferenceType>(ty);
+ result = getRValueReferenceType(
+ getVariableArrayDecayedType(lv->getPointeeType()));
+ break;
+ }
+
+ case Type::ConstantArray: {
+ const ConstantArrayType *cat = cast<ConstantArrayType>(ty);
+ result = getConstantArrayType(
+ getVariableArrayDecayedType(cat->getElementType()),
+ cat->getSize(),
+ cat->getSizeModifier(),
+ cat->getIndexTypeCVRQualifiers());
+ break;
+ }
+
+ case Type::DependentSizedArray: {
+ const DependentSizedArrayType *dat = cast<DependentSizedArrayType>(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<IncompleteArrayType>(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<VariableArrayType>(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 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 Canon;
+
+ // 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, Canon, NumElts, ASM, IndexTypeQuals, Brackets);
+
+ VariableArrayTypes.push_back(New);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+/// getDependentSizedArrayType - Returns a non-unique reference to
+/// the type for a dependently-sized array of the specified element
+/// type.
+QualType ASTContext::getDependentSizedArrayType(QualType elementType,
+ Expr *numElements,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned elementTypeQuals,
+ SourceRange brackets) const {
+ assert((!numElements || numElements->isTypeDependent() ||
+ numElements->isValueDependent()) &&
+ "Size must be type- or value-dependent!");
+
+ // 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);
+ }
+
+ // Otherwise, we actually build a new type every time, but we
+ // also build a canonical type.
+
+ SplitQualType canonElementType = getCanonicalType(elementType).split();
+
+ 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 elementTypeQuals) const {
+ llvm::FoldingSetNodeID ID;
+ IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals);
+
+ 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. We also have to pull
+ // qualifiers off the element type.
+ QualType canon;
+
+ 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 *existing =
+ IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos);
+ assert(!existing && "Shouldn't be in the map!"); (void) existing;
+ }
+
+ IncompleteArrayType *newType = new (*this, TypeAlignment)
+ IncompleteArrayType(elementType, canon, ASM, elementTypeQuals);
+
+ 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::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, VecKind);
+
+ void *InsertPos = 0;
+ if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(VTP, 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 (!vecType.isCanonical()) {
+ 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!"); (void)NewIP;
+ }
+ VectorType *New = new (*this, TypeAlignment)
+ VectorType(vecType, NumElts, Canonical, VecKind);
+ VectorTypes.InsertNode(New, InsertPos);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+/// 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) 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::GenericVector);
+ void *InsertPos = 0;
+ if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(VTP, 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 (!vecType.isCanonical()) {
+ Canonical = getExtVectorType(getCanonicalType(vecType), 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!"); (void)NewIP;
+ }
+ ExtVectorType *New = new (*this, TypeAlignment)
+ ExtVectorType(vecType, NumElts, Canonical);
+ VectorTypes.InsertNode(New, InsertPos);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+QualType
+ASTContext::getDependentSizedExtVectorType(QualType vecType,
+ Expr *SizeExpr,
+ SourceLocation AttrLoc) const {
+ llvm::FoldingSetNodeID ID;
+ DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType),
+ SizeExpr);
+
+ void *InsertPos = 0;
+ DependentSizedExtVectorType *Canon
+ = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
+ DependentSizedExtVectorType *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)
+ DependentSizedExtVectorType(*this, vecType, QualType(Canon, 0),
+ SizeExpr, AttrLoc);
+ } else {
+ QualType CanonVecTy = getCanonicalType(vecType);
+ if (CanonVecTy == vecType) {
+ New = new (*this, TypeAlignment)
+ DependentSizedExtVectorType(*this, vecType, QualType(), SizeExpr,
+ AttrLoc);
+
+ DependentSizedExtVectorType *CanonCheck
+ = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CanonCheck && "Dependent-sized ext_vector canonical type broken");
+ (void)CanonCheck;
+ DependentSizedExtVectorTypes.InsertNode(New, InsertPos);
+ } else {
+ QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
+ SourceLocation());
+ New = new (*this, TypeAlignment)
+ DependentSizedExtVectorType(*this, vecType, Canon, SizeExpr, AttrLoc);
+ }
+ }
+
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
+/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
+///
+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.
+ llvm::FoldingSetNodeID ID;
+ FunctionNoProtoType::Profile(ID, ResultTy, Info);
+
+ void *InsertPos = 0;
+ if (FunctionNoProtoType *FT =
+ FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(FT, 0);
+
+ QualType Canonical;
+ if (!ResultTy.isCanonical() ||
+ getCanonicalCallConv(CallConv) != CallConv) {
+ Canonical =
+ getFunctionNoProtoType(getCanonicalType(ResultTy),
+ Info.withCallingConv(getCanonicalCallConv(CallConv)));
+
+ // 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!"); (void)NewIP;
+ }
+
+ FunctionNoProtoType *New = new (*this, TypeAlignment)
+ FunctionNoProtoType(ResultTy, Canonical, Info);
+ Types.push_back(New);
+ FunctionNoProtoTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
+/// 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,
+ 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, EPI);
+
+ void *InsertPos = 0;
+ if (FunctionProtoType *FTP =
+ FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(FTP, 0);
+
+ // Determine whether the type being created is already canonical or not.
+ 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;
+ if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) {
+ llvm::SmallVector<QualType, 16> CanonicalArgs;
+ CanonicalArgs.reserve(NumArgs);
+ 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,
+ 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!"); (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.
+ 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);
+}
+
+#ifndef NDEBUG
+static bool NeedsInjectedClassNameType(const RecordDecl *D) {
+ if (!isa<CXXRecordDecl>(D)) return false;
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ if (isa<ClassTemplatePartialSpecializationDecl>(RD))
+ return true;
+ if (RD->getDescribedClassTemplate() &&
+ !isa<ClassTemplateSpecializationDecl>(RD))
+ return true;
+ return false;
+}
+#endif
+
+/// getInjectedClassNameType - Return the unique reference to the
+/// injected class name type for the specified templated declaration.
+QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
+ QualType TST) const {
+ assert(NeedsInjectedClassNameType(Decl));
+ if (Decl->TypeForDecl) {
+ assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
+ } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) {
+ assert(PrevDecl->TypeForDecl && "previous declaration has no type");
+ Decl->TypeForDecl = PrevDecl->TypeForDecl;
+ assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
+ } else {
+ Type *newType =
+ new (*this, TypeAlignment) InjectedClassNameType(Decl, TST);
+ 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) const {
+ assert(Decl && "Passed null for Decl param");
+ assert(!Decl->TypeForDecl && "TypeForDecl present in slow case");
+
+ if (const TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl))
+ return getTypedefType(Typedef);
+
+ assert(!isa<TemplateTypeParmDecl>(Decl) &&
+ "Template type parameter types are always available.");
+
+ if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) {
+ assert(!Record->getPreviousDeclaration() &&
+ "struct/union has previous declaration");
+ assert(!NeedsInjectedClassNameType(Record));
+ return getRecordType(Record);
+ } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
+ assert(!Enum->getPreviousDeclaration() &&
+ "enum has previous declaration");
+ return getEnumType(Enum);
+ } else if (const UnresolvedUsingTypenameDecl *Using =
+ dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
+ Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using);
+ Decl->TypeForDecl = newType;
+ Types.push_back(newType);
+ } else
+ llvm_unreachable("TypeDecl without a type?");
+
+ 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) const {
+ if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
+
+ if (Canonical.isNull())
+ Canonical = getCanonicalType(Decl->getUnderlyingType());
+ TypedefType *newType = new(*this, TypeAlignment)
+ TypedefType(Type::Typedef, Decl, Canonical);
+ Decl->TypeForDecl = newType;
+ Types.push_back(newType);
+ return QualType(newType, 0);
+}
+
+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);
+
+ RecordType *newType = new (*this, TypeAlignment) RecordType(Decl);
+ Decl->TypeForDecl = newType;
+ Types.push_back(newType);
+ return QualType(newType, 0);
+}
+
+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);
+
+ 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) const {
+ assert(Replacement.isCanonical()
+ && "replacement types must always be canonical");
+
+ llvm::FoldingSetNodeID ID;
+ SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
+ void *InsertPos = 0;
+ SubstTemplateTypeParmType *SubstParm
+ = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!SubstParm) {
+ SubstParm = new (*this, TypeAlignment)
+ SubstTemplateTypeParmType(Parm, Replacement);
+ Types.push_back(SubstParm);
+ SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
+ }
+
+ 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<TemplateTypeParmType>(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) const {
+ llvm::FoldingSetNodeID ID;
+ TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name);
+ void *InsertPos = 0;
+ TemplateTypeParmType *TypeParm
+ = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (TypeParm)
+ return QualType(TypeParm, 0);
+
+ if (Name) {
+ QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
+ TypeParm = new (*this, TypeAlignment)
+ TemplateTypeParmType(Depth, Index, ParameterPack, Name, Canon);
+
+ TemplateTypeParmType *TypeCheck
+ = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!TypeCheck && "Template type parameter canonical type broken");
+ (void)TypeCheck;
+ } else
+ TypeParm = new (*this, TypeAlignment)
+ TemplateTypeParmType(Depth, Index, ParameterPack);
+
+ Types.push_back(TypeParm);
+ TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
+
+ return QualType(TypeParm, 0);
+}
+
+TypeSourceInfo *
+ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &Args,
+ QualType CanonType) const {
+ QualType TST = getTemplateSpecializationType(Name, Args, CanonType);
+
+ TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
+ TemplateSpecializationTypeLoc TL
+ = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TL.setTemplateNameLoc(NameLoc);
+ TL.setLAngleLoc(Args.getLAngleLoc());
+ TL.setRAngleLoc(Args.getRAngleLoc());
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i, Args[i].getLocInfo());
+ return DI;
+}
+
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+ const TemplateArgumentListInfo &Args,
+ QualType Canon) const {
+ unsigned NumArgs = Args.size();
+
+ llvm::SmallVector<TemplateArgument, 4> ArgVec;
+ ArgVec.reserve(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ArgVec.push_back(Args[i].getArgument());
+
+ return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs,
+ Canon);
+}
+
+QualType
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ QualType Canon) const {
+ if (!Canon.isNull())
+ Canon = getCanonicalType(Canon);
+ else
+ Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs);
+
+ // Allocate the (non-canonical) template specialization type, but don't
+ // try to unique it: these types typically have location information that
+ // we don't unique and don't want to lose.
+ void *Mem = Allocate((sizeof(TemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs),
+ TypeAlignment);
+ TemplateSpecializationType *Spec
+ = new (Mem) TemplateSpecializationType(Template,
+ Args, NumArgs,
+ Canon);
+
+ Types.push_back(Spec);
+ return QualType(Spec, 0);
+}
+
+QualType
+ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
+ const TemplateArgument *Args,
+ unsigned NumArgs) const {
+ // Build the canonical template specialization type.
+ TemplateName CanonTemplate = getCanonicalTemplateName(Template);
+ llvm::SmallVector<TemplateArgument, 4> CanonArgs;
+ CanonArgs.reserve(NumArgs);
+ for (unsigned I = 0; I != NumArgs; ++I)
+ CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
+
+ // Determine whether this canonical template specialization type already
+ // exists.
+ llvm::FoldingSetNodeID ID;
+ TemplateSpecializationType::Profile(ID, CanonTemplate,
+ CanonArgs.data(), NumArgs, *this);
+
+ void *InsertPos = 0;
+ TemplateSpecializationType *Spec
+ = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!Spec) {
+ // Allocate a new canonical template specialization type.
+ void *Mem = Allocate((sizeof(TemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs),
+ TypeAlignment);
+ Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
+ CanonArgs.data(), NumArgs,
+ QualType());
+ Types.push_back(Spec);
+ TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+ }
+
+ assert(Spec->isDependentType() &&
+ "Non-dependent template-id type must have a canonical type");
+ return QualType(Spec, 0);
+}
+
+QualType
+ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ QualType NamedType) const {
+ llvm::FoldingSetNodeID ID;
+ ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
+
+ void *InsertPos = 0;
+ ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ QualType Canon = NamedType;
+ if (!Canon.isCanonical()) {
+ Canon = getCanonicalType(NamedType);
+ ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CheckT && "Elaborated canonical type broken");
+ (void)CheckT;
+ }
+
+ T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
+ Types.push_back(T);
+ ElaboratedTypes.InsertNode(T, InsertPos);
+ 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) const {
+ assert(NNS->isDependent() && "nested-name-specifier must be dependent");
+
+ if (Canon.isNull()) {
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ ElaboratedTypeKeyword CanonKeyword = Keyword;
+ if (Keyword == ETK_None)
+ CanonKeyword = ETK_Typename;
+
+ if (CanonNNS != NNS || CanonKeyword != Keyword)
+ Canon = getDependentNameType(CanonKeyword, CanonNNS, Name);
+ }
+
+ llvm::FoldingSetNodeID ID;
+ DependentNameType::Profile(ID, Keyword, NNS, Name);
+
+ void *InsertPos = 0;
+ DependentNameType *T
+ = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
+ Types.push_back(T);
+ DependentNameTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
+QualType
+ASTContext::getDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ const TemplateArgumentListInfo &Args) const {
+ // TODO: avoid this copy
+ llvm::SmallVector<TemplateArgument, 16> ArgCopy;
+ for (unsigned I = 0, E = Args.size(); I != E; ++I)
+ ArgCopy.push_back(Args[I].getArgument());
+ return getDependentTemplateSpecializationType(Keyword, NNS, Name,
+ ArgCopy.size(),
+ ArgCopy.data());
+}
+
+QualType
+ASTContext::getDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args) const {
+ assert(NNS->isDependent() && "nested-name-specifier must be dependent");
+
+ llvm::FoldingSetNodeID ID;
+ DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
+ Name, NumArgs, Args);
+
+ void *InsertPos = 0;
+ DependentTemplateSpecializationType *T
+ = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+
+ ElaboratedTypeKeyword CanonKeyword = Keyword;
+ if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
+
+ bool AnyNonCanonArgs = false;
+ llvm::SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
+ if (!CanonArgs[I].structurallyEquals(Args[I]))
+ AnyNonCanonArgs = true;
+ }
+
+ QualType Canon;
+ if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
+ Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS,
+ Name, NumArgs,
+ CanonArgs.data());
+
+ // Find the insert position again.
+ DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs),
+ TypeAlignment);
+ T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
+ Name, NumArgs, Args, Canon);
+ Types.push_back(T);
+ DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
+QualType ASTContext::getPackExpansionType(QualType Pattern,
+ llvm::Optional<unsigned> 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,
+ const ObjCProtocolDecl *RHS) {
+ return LHS->getDeclName() < RHS->getDeclName();
+}
+
+static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) {
+ if (NumProtocols == 0) return true;
+
+ for (unsigned i = 1; i != NumProtocols; ++i)
+ if (!CmpProtocolNames(Protocols[i-1], Protocols[i]))
+ return false;
+ return true;
+}
+
+static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
+ unsigned &NumProtocols) {
+ ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
+
+ // Sort protocols, keyed by name.
+ std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
+
+ // Remove duplicates.
+ ProtocolsEnd = std::unique(Protocols, ProtocolsEnd);
+ NumProtocols = ProtocolsEnd-Protocols;
+}
+
+QualType ASTContext::getObjCObjectType(QualType BaseType,
+ ObjCProtocolDecl * const *Protocols,
+ 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<ObjCInterfaceType>(BaseType))
+ return BaseType;
+
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
+ void *InsertPos = 0;
+ if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // Build the canonical type, which has the canonical base type and
+ // a sorted-and-uniqued list of protocols.
+ QualType Canonical;
+ bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
+ if (!ProtocolsSorted || !BaseType.isCanonical()) {
+ if (!ProtocolsSorted) {
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
+ Protocols + NumProtocols);
+ unsigned UniqueCount = NumProtocols;
+
+ SortAndUniqueProtocols(&Sorted[0], UniqueCount);
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ &Sorted[0], UniqueCount);
+ } else {
+ Canonical = getObjCObjectType(getCanonicalType(BaseType),
+ Protocols, NumProtocols);
+ }
+
+ // Regenerate InsertPos.
+ ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ unsigned Size = sizeof(ObjCObjectTypeImpl);
+ Size += NumProtocols * sizeof(ObjCProtocolDecl *);
+ void *Mem = Allocate(Size, TypeAlignment);
+ ObjCObjectTypeImpl *T =
+ new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
+
+ Types.push_back(T);
+ ObjCObjectTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
+/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
+/// the given object type.
+QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const {
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectPointerType::Profile(ID, ObjectT);
+
+ void *InsertPos = 0;
+ if (ObjCObjectPointerType *QT =
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // Find the canonical object type.
+ QualType Canonical;
+ if (!ObjectT.isCanonical()) {
+ Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT));
+
+ // Regenerate InsertPos.
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ // No match.
+ void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment);
+ ObjCObjectPointerType *QType =
+ new (Mem) ObjCObjectPointerType(Canonical, ObjectT);
+
+ Types.push_back(QType);
+ ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
+ return QualType(QType, 0);
+}
+
+/// getObjCInterfaceType - Return the unique reference to the type for the
+/// specified ObjC interface decl. The list of protocols is optional.
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const {
+ if (Decl->TypeForDecl)
+ return QualType(Decl->TypeForDecl, 0);
+
+ // FIXME: redeclarations?
+ void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
+ ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
+ Decl->TypeForDecl = T;
+ Types.push_back(T);
+ return QualType(T, 0);
+}
+
+/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
+/// TypeOfExprType AST's (since expression's are never shared). For example,
+/// 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) const {
+ TypeOfExprType *toe;
+ if (tofExpr->isTypeDependent()) {
+ llvm::FoldingSetNodeID ID;
+ DependentTypeOfExprType::Profile(ID, *this, tofExpr);
+
+ void *InsertPos = 0;
+ DependentTypeOfExprType *Canon
+ = DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (Canon) {
+ // We already have a "canonical" version of an identical, dependent
+ // typeof(expr) type. Use that as our canonical type.
+ toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr,
+ QualType((TypeOfExprType*)Canon, 0));
+ }
+ else {
+ // Build a new, canonical typeof(expr) type.
+ Canon
+ = new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr);
+ DependentTypeOfExprTypes.InsertNode(Canon, InsertPos);
+ toe = Canon;
+ }
+ } else {
+ QualType Canonical = getCanonicalType(tofExpr->getType());
+ toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Canonical);
+ }
+ Types.push_back(toe);
+ return QualType(toe, 0);
+}
+
+/// getTypeOfType - Unlike many "get<Type>" functions, we don't unique
+/// TypeOfType AST's. The only motivation to unique these nodes would be
+/// 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) const {
+ QualType Canonical = getCanonicalType(tofType);
+ TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical);
+ Types.push_back(tot);
+ return QualType(tot, 0);
+}
+
+/// getDecltypeForExpr - Given an expr, will return the decltype for that
+/// expression, according to the rules in C++0x [dcl.type.simple]p4
+static QualType getDecltypeForExpr(const Expr *e, const ASTContext &Context) {
+ if (e->isTypeDependent())
+ return Context.DependentTy;
+
+ // If e is an id expression or a class member access, decltype(e) is defined
+ // as the type of the entity named by e.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(e)) {
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
+ return VD->getType();
+ }
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(e)) {
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
+ return FD->getType();
+ }
+ // If e is a function call or an invocation of an overloaded operator,
+ // (parentheses around e are ignored), decltype(e) is defined as the
+ // return type of that function.
+ if (const CallExpr *CE = dyn_cast<CallExpr>(e->IgnoreParens()))
+ return CE->getCallReturnType();
+
+ QualType T = e->getType();
+
+ // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is
+ // defined as T&, otherwise decltype(e) is defined as T.
+ if (e->isLValue())
+ T = Context.getLValueReferenceType(T);
+
+ return T;
+}
+
+/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique
+/// DecltypeType AST's. The only motivation to unique these nodes would be
+/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be
+/// an issue. This doesn't effect the type checker, since it operates
+/// on canonical type's (which are always unique).
+QualType ASTContext::getDecltypeType(Expr *e) const {
+ DecltypeType *dt;
+ if (e->isTypeDependent()) {
+ llvm::FoldingSetNodeID ID;
+ DependentDecltypeType::Profile(ID, *this, e);
+
+ void *InsertPos = 0;
+ DependentDecltypeType *Canon
+ = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (Canon) {
+ // We already have a "canonical" version of an equivalent, dependent
+ // decltype type. Use that as our canonical type.
+ dt = new (*this, TypeAlignment) DecltypeType(e, DependentTy,
+ QualType((DecltypeType*)Canon, 0));
+ }
+ else {
+ // Build a new, canonical typeof(expr) type.
+ Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
+ DependentDecltypeTypes.InsertNode(Canon, InsertPos);
+ dt = Canon;
+ }
+ } else {
+ QualType T = getDecltypeForExpr(e, *this);
+ dt = new (*this, TypeAlignment) DecltypeType(e, T, getCanonicalType(T));
+ }
+ Types.push_back(dt);
+ return QualType(dt, 0);
+}
+
+/// getAutoType - Unlike many "get<Type>" 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) const {
+ assert (Decl);
+ // FIXME: What is the design on getTagDeclType when it requires casting
+ // away const? mutable?
+ return getTypeDeclType(const_cast<TagDecl*>(Decl));
+}
+
+/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
+/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
+/// needs to agree with the definition in <stddef.h>.
+CanQualType ASTContext::getSizeType() const {
+ return getFromTargetType(Target.getSizeType());
+}
+
+/// getSignedWCharType - Return the type of "signed wchar_t".
+/// Used when in C++, as a GCC extension.
+QualType ASTContext::getSignedWCharType() const {
+ // FIXME: derive from "Target" ?
+ return WCharTy;
+}
+
+/// getUnsignedWCharType - Return the type of "unsigned wchar_t".
+/// Used when in C++, as a GCC extension.
+QualType ASTContext::getUnsignedWCharType() const {
+ // FIXME: derive from "Target" ?
+ return UnsignedIntTy;
+}
+
+/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+QualType ASTContext::getPointerDiffType() const {
+ return getFromTargetType(Target.getPtrDiffType(0));
+}
+
+//===----------------------------------------------------------------------===//
+// Type Operators
+//===----------------------------------------------------------------------===//
+
+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<ArrayType>(Ty)) {
+ Result = getArrayDecayedType(QualType(Ty,0));
+ } else if (isa<FunctionType>(Ty)) {
+ Result = getPointerType(QualType(Ty, 0));
+ } else {
+ Result = QualType(Ty, 0);
+ }
+
+ return CanQualType::CreateUnsafe(Result);
+}
+
+
+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<ArrayType>(splitType.first->getUnqualifiedDesugaredType());
+
+ // If we don't have an array, just use the results in splitType.
+ if (!AT) {
+ quals = splitType.second;
+ return QualType(splitType.first, 0);
+ }
+
+ // 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<ConstantArrayType>(AT)) {
+ return getConstantArrayType(unqualElementType, CAT->getSize(),
+ CAT->getSizeModifier(), 0);
+ }
+
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
+ return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0);
+ }
+
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) {
+ return getVariableArrayType(unqualElementType,
+ VAT->getSizeExpr(),
+ VAT->getSizeModifier(),
+ VAT->getIndexTypeCVRQualifiers(),
+ VAT->getBracketsRange());
+ }
+
+ const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT);
+ return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(),
+ DSAT->getSizeModifier(), 0,
+ SourceRange());
+}
+
+/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that
+/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
+/// they point to and return true. If T1 and T2 aren't pointer types
+/// or pointer-to-member types, or if they are not similar at this
+/// level, returns false and leaves T1 and T2 unchanged. Top-level
+/// qualifiers on T1 and T2 are ignored. This function will typically
+/// be called in a loop that successively "unwraps" pointer and
+/// pointer-to-member types to compare them at each level.
+bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
+ const PointerType *T1PtrType = T1->getAs<PointerType>(),
+ *T2PtrType = T2->getAs<PointerType>();
+ if (T1PtrType && T2PtrType) {
+ T1 = T1PtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+
+ const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+ *T2MPType = T2->getAs<MemberPointerType>();
+ if (T1MPType && T2MPType &&
+ hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+ QualType(T2MPType->getClass(), 0))) {
+ T1 = T1MPType->getPointeeType();
+ T2 = T2MPType->getPointeeType();
+ return true;
+ }
+
+ if (getLangOptions().ObjC1) {
+ const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
+ *T2OPType = T2->getAs<ObjCObjectPointerType>();
+ if (T1OPType && T2OPType) {
+ T1 = T1OPType->getPointeeType();
+ T2 = T2OPType->getPointeeType();
+ return true;
+ }
+ }
+
+ // FIXME: Block pointers, too?
+
+ return false;
+}
+
+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);
+
+ if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ DeclarationName DName;
+ if (DTN->isIdentifier()) {
+ DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
+ return DeclarationNameInfo(DName, NameLoc);
+ } else {
+ DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ // DNInfo work in progress: FIXME: source locations?
+ DeclarationNameLoc DNLoc;
+ DNLoc.CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ DNLoc.CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ return DeclarationNameInfo(DName, NameLoc, DNLoc);
+ }
+ }
+
+ OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
+ assert(Storage);
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
+}
+
+TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ Template = getCanonicalTemplateTemplateParmDecl(TTP);
+
+ // The canonical template name is the canonical template declaration.
+ return TemplateName(cast<TemplateDecl>(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();
+ assert(DTN && "Non-dependent template names must refer to template decls.");
+ return DTN->CanonicalTemplateName;
+}
+
+bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
+ X = getCanonicalTemplateName(X);
+ Y = getCanonicalTemplateName(Y);
+ return X.getAsVoidPointer() == Y.getAsVoidPointer();
+}
+
+TemplateArgument
+ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ return Arg;
+
+ case TemplateArgument::Expression:
+ return Arg;
+
+ case TemplateArgument::Declaration:
+ return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
+
+ 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()));
+
+ case TemplateArgument::Type:
+ return TemplateArgument(getCanonicalType(Arg.getAsType()));
+
+ case TemplateArgument::Pack: {
+ 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);
+
+ return TemplateArgument(CanonArgs, Arg.pack_size());
+ }
+ }
+
+ // Silence GCC warning
+ assert(false && "Unhandled template argument kind");
+ return TemplateArgument();
+}
+
+NestedNameSpecifier *
+ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
+ if (!NNS)
+ return 0;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ // Canonicalize the prefix but keep the identifier the same.
+ return NestedNameSpecifier::Create(*this,
+ getCanonicalNestedNameSpecifier(NNS->getPrefix()),
+ NNS->getAsIdentifier());
+
+ case NestedNameSpecifier::Namespace:
+ // A namespace is canonical; build a nested-name-specifier with
+ // this namespace and no prefix.
+ return NestedNameSpecifier::Create(*this, 0, NNS->getAsNamespace());
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
+
+ // 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<DependentNameType>()) {
+ NestedNameSpecifier *Prefix
+ = getCanonicalNestedNameSpecifier(DNT->getQualifier());
+ return NestedNameSpecifier::Create(*this, Prefix,
+ const_cast<IdentifierInfo *>(DNT->getIdentifier()));
+ }
+
+ // Do the same thing as above, but with dependent-named specializations.
+ if (const DependentTemplateSpecializationType *DTST
+ = T->getAs<DependentTemplateSpecializationType>()) {
+ NestedNameSpecifier *Prefix
+ = getCanonicalNestedNameSpecifier(DTST->getQualifier());
+ TemplateName Name
+ = getDependentTemplateName(Prefix, DTST->getIdentifier());
+ T = getTemplateSpecializationType(Name,
+ DTST->getArgs(), DTST->getNumArgs());
+ T = getCanonicalType(T);
+ }
+
+ return NestedNameSpecifier::Create(*this, 0, false,
+ const_cast<Type*>(T.getTypePtr()));
+ }
+
+ case NestedNameSpecifier::Global:
+ // The global specifier is canonical and unique.
+ return NNS;
+ }
+
+ // Required to silence a GCC warning
+ return 0;
+}
+
+
+const ArrayType *ASTContext::getAsArrayType(QualType T) const {
+ // Handle the non-qualified case efficiently.
+ if (!T.hasLocalQualifiers()) {
+ // Handle the common positive case fast.
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+ return AT;
+ }
+
+ // Handle the common negative case fast.
+ if (!isa<ArrayType>(T.getCanonicalType()))
+ return 0;
+
+ // Apply any qualifiers from the array type to the element type. This
+ // implements C99 6.7.3p8: "If the specification of an array type includes
+ // any type qualifiers, the element type is so qualified, not the array type."
+
+ // If we get here, we either have type qualifiers on the type, or we have
+ // 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.
+
+ SplitQualType split = T.getSplitDesugaredType();
+ Qualifiers qs = split.second;
+
+ // If we have a simple case, just return now.
+ const ArrayType *ATy = dyn_cast<ArrayType>(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.
+ QualType NewEltTy = getQualifiedType(ATy->getElementType(), qs);
+
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
+ return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
+ CAT->getSizeModifier(),
+ CAT->getIndexTypeCVRQualifiers()));
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
+ return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
+ IAT->getSizeModifier(),
+ IAT->getIndexTypeCVRQualifiers()));
+
+ if (const DependentSizedArrayType *DSAT
+ = dyn_cast<DependentSizedArrayType>(ATy))
+ return cast<ArrayType>(
+ getDependentSizedArrayType(NewEltTy,
+ DSAT->getSizeExpr(),
+ DSAT->getSizeModifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
+ DSAT->getBracketsRange()));
+
+ const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
+ return cast<ArrayType>(getVariableArrayType(NewEltTy,
+ 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) 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
+ // (C99 6.7.3p8).
+ const ArrayType *PrettyArrayType = getAsArrayType(Ty);
+ assert(PrettyArrayType && "Not an array type!");
+
+ QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
+
+ // int x[restrict 4] -> int *restrict
+ return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
+}
+
+QualType ASTContext::getBaseElementType(const ArrayType *array) const {
+ return getBaseElementType(array->getElementType());
+}
+
+QualType ASTContext::getBaseElementType(QualType type) const {
+ Qualifiers qs;
+ while (true) {
+ SplitQualType split = type.getSplitDesugaredType();
+ const ArrayType *array = split.first->getAsArrayTypeUnsafe();
+ if (!array) break;
+
+ type = array->getElementType();
+ qs.addConsistentQualifiers(split.second);
+ }
+
+ return getQualifiedType(type, qs);
+}
+
+/// getConstantArrayElementCount - Returns number of constant array elements.
+uint64_t
+ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const {
+ uint64_t ElementCount = 1;
+ do {
+ ElementCount *= CA->getSize().getZExtValue();
+ CA = dyn_cast<ConstantArrayType>(CA->getElementType());
+ } while (CA);
+ return ElementCount;
+}
+
+/// getFloatingRank - Return a relative rank for floating point types.
+/// This routine will assert if passed a built-in type that isn't a float.
+static FloatingRank getFloatingRank(QualType T) {
+ if (const ComplexType *CT = T->getAs<ComplexType>())
+ return getFloatingRank(CT->getElementType());
+
+ assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
+ switch (T->getAs<BuiltinType>()->getKind()) {
+ default: assert(0 && "getFloatingRank(): not a floating type");
+ case BuiltinType::Float: return FloatRank;
+ case BuiltinType::Double: return DoubleRank;
+ case BuiltinType::LongDouble: return LongDoubleRank;
+ }
+}
+
+/// getFloatingTypeOfSizeWithinDomain - Returns a real floating
+/// point or a complex type (based on typeDomain/typeSize).
+/// 'typeDomain' is a real floating point or complex type.
+/// 'typeSize' is a real floating point or complex type.
+QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
+ QualType Domain) const {
+ FloatingRank EltRank = getFloatingRank(Size);
+ if (Domain->isComplexType()) {
+ switch (EltRank) {
+ default: assert(0 && "getFloatingRank(): illegal value for rank");
+ case FloatRank: return FloatComplexTy;
+ case DoubleRank: return DoubleComplexTy;
+ case LongDoubleRank: return LongDoubleComplexTy;
+ }
+ }
+
+ assert(Domain->isRealFloatingType() && "Unknown domain!");
+ switch (EltRank) {
+ default: assert(0 && "getFloatingRank(): illegal value for rank");
+ case FloatRank: return FloatTy;
+ case DoubleRank: return DoubleTy;
+ case LongDoubleRank: return LongDoubleTy;
+ }
+}
+
+/// getFloatingTypeOrder - Compare the rank of the two specified floating
+/// 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) const {
+ FloatingRank LHSR = getFloatingRank(LHS);
+ FloatingRank RHSR = getFloatingRank(RHS);
+
+ if (LHSR == RHSR)
+ return 0;
+ if (LHSR > RHSR)
+ return 1;
+ return -1;
+}
+
+/// 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(const Type *T) const {
+ assert(T->isCanonicalUnqualified() && "T should be canonicalized");
+ if (const EnumType* ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getPromotionType().getTypePtr();
+
+ if (T->isSpecificBuiltinType(BuiltinType::WChar_S) ||
+ T->isSpecificBuiltinType(BuiltinType::WChar_U))
+ T = getFromTargetType(Target.getWCharType()).getTypePtr();
+
+ if (T->isSpecificBuiltinType(BuiltinType::Char16))
+ T = getFromTargetType(Target.getChar16Type()).getTypePtr();
+
+ if (T->isSpecificBuiltinType(BuiltinType::Char32))
+ T = getFromTargetType(Target.getChar32Type()).getTypePtr();
+
+ switch (cast<BuiltinType>(T)->getKind()) {
+ default: assert(0 && "getIntegerRank(): not a built-in integer");
+ case BuiltinType::Bool:
+ return 1 + (getIntWidth(BoolTy) << 3);
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ return 2 + (getIntWidth(CharTy) << 3);
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ return 3 + (getIntWidth(ShortTy) << 3);
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ return 4 + (getIntWidth(IntTy) << 3);
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ return 5 + (getIntWidth(LongTy) << 3);
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ return 6 + (getIntWidth(LongLongTy) << 3);
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ return 7 + (getIntWidth(Int128Ty) << 3);
+ }
+}
+
+/// \brief Whether this is a promotable bitfield reference according
+/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
+///
+/// \returns the type this bit-field will promote to, or NULL if no
+/// promotion occurs.
+QualType ASTContext::isPromotableBitField(Expr *E) const {
+ if (E->isTypeDependent() || E->isValueDependent())
+ return QualType();
+
+ FieldDecl *Field = E->getBitField();
+ if (!Field)
+ return QualType();
+
+ QualType FT = Field->getType();
+
+ llvm::APSInt BitWidthAP = Field->getBitWidth()->EvaluateAsInt(*this);
+ uint64_t BitWidth = BitWidthAP.getZExtValue();
+ uint64_t IntSize = getTypeSize(IntTy);
+ // GCC extension compatibility: if the bit-field size is less than or equal
+ // to the size of int, it gets promoted no matter what its type is.
+ // For instance, unsigned long bf : 4 gets promoted to signed int.
+ if (BitWidth < IntSize)
+ return IntTy;
+
+ if (BitWidth == IntSize)
+ return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy;
+
+ // Types bigger than int are not subject to promotions, and therefore act
+ // like the base type.
+ // FIXME: This doesn't quite match what gcc does, but what gcc does here
+ // is ridiculous.
+ return QualType();
+}
+
+/// 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) const {
+ assert(!Promotable.isNull());
+ assert(Promotable->isPromotableIntegerType());
+ if (const EnumType *ET = Promotable->getAs<EnumType>())
+ return ET->getDecl()->getPromotionType();
+ if (Promotable->isSignedIntegerType())
+ return IntTy;
+ uint64_t PromotableSize = getTypeSize(Promotable);
+ uint64_t IntSize = getTypeSize(IntTy);
+ assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize);
+ return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
+}
+
+/// 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) const {
+ const Type *LHSC = getCanonicalType(LHS).getTypePtr();
+ const Type *RHSC = getCanonicalType(RHS).getTypePtr();
+ if (LHSC == RHSC) return 0;
+
+ bool LHSUnsigned = LHSC->isUnsignedIntegerType();
+ bool RHSUnsigned = RHSC->isUnsignedIntegerType();
+
+ unsigned LHSRank = getIntegerRank(LHSC);
+ unsigned RHSRank = getIntegerRank(RHSC);
+
+ if (LHSUnsigned == RHSUnsigned) { // Both signed or both unsigned.
+ if (LHSRank == RHSRank) return 0;
+ return LHSRank > RHSRank ? 1 : -1;
+ }
+
+ // Otherwise, the LHS is signed and the RHS is unsigned or visa versa.
+ if (LHSUnsigned) {
+ // If the unsigned [LHS] type is larger, return it.
+ if (LHSRank >= RHSRank)
+ return 1;
+
+ // If the signed type can represent all values of the unsigned type, it
+ // wins. Because we are dealing with 2's complement and types that are
+ // powers of two larger than each other, this is always safe.
+ return -1;
+ }
+
+ // If the unsigned [RHS] type is larger, return it.
+ if (RHSRank >= LHSRank)
+ return -1;
+
+ // If the signed type can represent all values of the unsigned type, it
+ // wins. Because we are dealing with 2's complement and types that are
+ // powers of two larger than each other, this is always safe.
+ return 1;
+}
+
+static RecordDecl *
+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);
+ else
+ return RecordDecl::Create(Ctx, TK, DC, L, Id);
+}
+
+// getCFConstantStringType - Return the type used for constant CFStrings.
+QualType ASTContext::getCFConstantStringType() const {
+ if (!CFConstantStringTypeDecl) {
+ CFConstantStringTypeDecl =
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get("NSConstantString"));
+ CFConstantStringTypeDecl->startDefinition();
+
+ QualType FieldTypes[4];
+
+ // const int *isa;
+ FieldTypes[0] = getPointerType(IntTy.withConst());
+ // int flags;
+ FieldTypes[1] = IntTy;
+ // const char *str;
+ FieldTypes[2] = getPointerType(CharTy.withConst());
+ // long length;
+ FieldTypes[3] = LongTy;
+
+ // Create fields
+ for (unsigned i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ CFConstantStringTypeDecl->addDecl(Field);
+ }
+
+ CFConstantStringTypeDecl->completeDefinition();
+ }
+
+ return getTagDeclType(CFConstantStringTypeDecl);
+}
+
+void ASTContext::setCFConstantStringType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid CFConstantStringType");
+ CFConstantStringTypeDecl = Rec->getDecl();
+}
+
+// getNSConstantStringType - Return the type used for constant NSStrings.
+QualType ASTContext::getNSConstantStringType() const {
+ if (!NSConstantStringTypeDecl) {
+ NSConstantStringTypeDecl =
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get("__builtin_NSString"));
+ NSConstantStringTypeDecl->startDefinition();
+
+ QualType FieldTypes[3];
+
+ // const int *isa;
+ FieldTypes[0] = getPointerType(IntTy.withConst());
+ // const char *str;
+ FieldTypes[1] = getPointerType(CharTy.withConst());
+ // unsigned int length;
+ FieldTypes[2] = UnsignedIntTy;
+
+ // Create fields
+ for (unsigned i = 0; i < 3; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this, NSConstantStringTypeDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ NSConstantStringTypeDecl->addDecl(Field);
+ }
+
+ NSConstantStringTypeDecl->completeDefinition();
+ }
+
+ return getTagDeclType(NSConstantStringTypeDecl);
+}
+
+void ASTContext::setNSConstantStringType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid NSConstantStringType");
+ NSConstantStringTypeDecl = Rec->getDecl();
+}
+
+QualType ASTContext::getObjCFastEnumerationStateType() const {
+ if (!ObjCFastEnumerationStateTypeDecl) {
+ ObjCFastEnumerationStateTypeDecl =
+ CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get("__objcFastEnumerationState"));
+ ObjCFastEnumerationStateTypeDecl->startDefinition();
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ getPointerType(ObjCIdTypedefType),
+ getPointerType(UnsignedLongTy),
+ getConstantArrayType(UnsignedLongTy,
+ llvm::APInt(32, 5), ArrayType::Normal, 0)
+ };
+
+ for (size_t i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ ObjCFastEnumerationStateTypeDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ ObjCFastEnumerationStateTypeDecl->addDecl(Field);
+ }
+
+ ObjCFastEnumerationStateTypeDecl->completeDefinition();
+ }
+
+ return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
+}
+
+QualType ASTContext::getBlockDescriptorType() const {
+ if (BlockDescriptorType)
+ return getTagDeclType(BlockDescriptorType);
+
+ RecordDecl *T;
+ // FIXME: Needs the FlagAppleBlock bit.
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor"));
+ T->startDefinition();
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ UnsignedLongTy,
+ };
+
+ const char *FieldNames[] = {
+ "reserved",
+ "Size"
+ };
+
+ for (size_t i = 0; i < 2; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ T,
+ SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition();
+
+ BlockDescriptorType = T;
+
+ return getTagDeclType(BlockDescriptorType);
+}
+
+void ASTContext::setBlockDescriptorType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid BlockDescriptorType");
+ BlockDescriptorType = Rec->getDecl();
+}
+
+QualType ASTContext::getBlockDescriptorExtendedType() const {
+ if (BlockDescriptorExtendedType)
+ return getTagDeclType(BlockDescriptorExtendedType);
+
+ RecordDecl *T;
+ // FIXME: Needs the FlagAppleBlock bit.
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor_withcopydispose"));
+ T->startDefinition();
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ UnsignedLongTy,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy)
+ };
+
+ const char *FieldNames[] = {
+ "reserved",
+ "Size",
+ "CopyFuncPtr",
+ "DestroyFuncPtr"
+ };
+
+ for (size_t i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ T,
+ SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition();
+
+ BlockDescriptorExtendedType = T;
+
+ return getTagDeclType(BlockDescriptorExtendedType);
+}
+
+void ASTContext::setBlockDescriptorExtendedType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid BlockDescriptorType");
+ BlockDescriptorExtendedType = Rec->getDecl();
+}
+
+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<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ return RD->hasConstCopyConstructor(*this);
+
+ }
+ }
+ return false;
+}
+
+QualType
+ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
+ // type = struct __Block_byref_1_X {
+ // void *__isa;
+ // struct __Block_byref_1_X *__forwarding;
+ // unsigned int __flags;
+ // unsigned int __size;
+ // void *__copy_helper; // as needed
+ // void *__destroy_help // as needed
+ // int X;
+ // } *
+
+ bool HasCopyAndDispose = BlockRequiresCopying(Ty);
+
+ // FIXME: Move up
+ llvm::SmallString<36> Name;
+ llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
+ ++UniqueBlockByRefTypeID << '_' << DeclName;
+ RecordDecl *T;
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get(Name.str()));
+ T->startDefinition();
+ QualType Int32Ty = IntTy;
+ assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
+ QualType FieldTypes[] = {
+ getPointerType(VoidPtrTy),
+ getPointerType(getTagDeclType(T)),
+ Int32Ty,
+ Int32Ty,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy),
+ Ty
+ };
+
+ llvm::StringRef FieldNames[] = {
+ "__isa",
+ "__forwarding",
+ "__flags",
+ "__size",
+ "__copy_helper",
+ "__destroy_helper",
+ DeclName,
+ };
+
+ for (size_t i = 0; i < 7; ++i) {
+ if (!HasCopyAndDispose && i >=4 && i <= 5)
+ continue;
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition();
+
+ return getPointerType(getTagDeclType(T));
+}
+
+
+QualType ASTContext::getBlockParmType(
+ bool BlockHasCopyDispose,
+ llvm::SmallVectorImpl<const Expr *> &Layout) const {
+
+ // FIXME: Move up
+ llvm::SmallString<36> Name;
+ llvm::raw_svector_ostream(Name) << "__block_literal_"
+ << ++UniqueBlockParmTypeID;
+ RecordDecl *T;
+ T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
+ &Idents.get(Name.str()));
+ T->startDefinition();
+ QualType FieldTypes[] = {
+ getPointerType(VoidPtrTy),
+ IntTy,
+ IntTy,
+ getPointerType(VoidPtrTy),
+ (BlockHasCopyDispose ?
+ getPointerType(getBlockDescriptorExtendedType()) :
+ getPointerType(getBlockDescriptorType()))
+ };
+
+ const char *FieldNames[] = {
+ "__isa",
+ "__flags",
+ "__reserved",
+ "__FuncPtr",
+ "__descriptor"
+ };
+
+ for (size_t i = 0; i < 5; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*TInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ T->addDecl(Field);
+ }
+
+ for (unsigned i = 0; i < Layout.size(); ++i) {
+ const Expr *E = Layout[i];
+
+ QualType FieldType = E->getType();
+ IdentifierInfo *FieldName = 0;
+ if (isa<CXXThisExpr>(E)) {
+ FieldName = &Idents.get("this");
+ } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) {
+ const ValueDecl *D = BDRE->getDecl();
+ FieldName = D->getIdentifier();
+ if (BDRE->isByRef())
+ FieldType = BuildByRefType(D->getName(), FieldType);
+ } else {
+ // Padding.
+ assert(isa<ConstantArrayType>(FieldType) &&
+ isa<DeclRefExpr>(E) &&
+ !cast<DeclRefExpr>(E)->getDecl()->getDeclName() &&
+ "doesn't match characteristics of padding decl");
+ }
+
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ FieldName, FieldType, /*TInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ Field->setAccess(AS_public);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition();
+
+ return getPointerType(getTagDeclType(T));
+}
+
+void ASTContext::setObjCFastEnumerationStateType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid ObjCFAstEnumerationStateType");
+ ObjCFastEnumerationStateTypeDecl = Rec->getDecl();
+}
+
+// This returns true if a type has been typedefed to BOOL:
+// typedef <type> BOOL;
+static bool isTypeTypedefedAsBOOL(QualType T) {
+ if (const TypedefType *TT = dyn_cast<TypedefType>(T))
+ if (IdentifierInfo *II = TT->getDecl()->getIdentifier())
+ return II->isStr("BOOL");
+
+ return false;
+}
+
+/// getObjCEncodingTypeSize returns size of type for objective-c encoding
+/// purpose.
+CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
+ CharUnits sz = getTypeSizeInChars(type);
+
+ // Make all integer and enum types at least as large as an int
+ if (sz.isPositive() && type->isIntegralOrEnumerationType())
+ sz = std::max(sz, getTypeSizeInChars(IntTy));
+ // Treat arrays as pointers, since that's how they're passed in.
+ else if (type->isArrayType())
+ sz = getTypeSizeInChars(VoidPtrTy);
+ return sz;
+}
+
+static inline
+std::string charUnitsToString(const CharUnits &CU) {
+ return llvm::itostr(CU.getQuantity());
+}
+
+/// getObjCEncodingForBlock - Return the encoded type for this block
+/// declaration.
+std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
+ std::string S;
+
+ const BlockDecl *Decl = Expr->getBlockDecl();
+ QualType BlockTy =
+ Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
+ // Encode result type.
+ getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), S);
+ // Compute size of all parameters.
+ // Start with computing size of a pointer in number of bytes.
+ // FIXME: There might(should) be a better way of doing this computation!
+ SourceLocation Loc;
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
+ CharUnits ParmOffset = PtrSize;
+ for (BlockDecl::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() && "BlockExpr - Incomplete param type");
+ ParmOffset += sz;
+ }
+ // Size of the argument frame
+ S += charUnitsToString(ParmOffset);
+ // Block pointer and offset.
+ S += "@?0";
+ ParmOffset = PtrSize;
+
+ // Argument types.
+ ParmOffset = PtrSize;
+ for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E =
+ Decl->param_end(); PI != E; ++PI) {
+ ParmVarDecl *PVDecl = *PI;
+ QualType PType = PVDecl->getOriginalType();
+ if (const ArrayType *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ // Use array's original type only if it has known number of
+ // elements.
+ if (!isa<ConstantArrayType>(AT))
+ PType = PVDecl->getType();
+ } else if (PType->isFunctionType())
+ PType = PVDecl->getType();
+ getObjCEncodingForType(PType, S);
+ S += 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<ArrayType>(PType->getCanonicalTypeInternal())) {
+ // Use array's original type only if it has known number of
+ // elements.
+ if (!isa<ConstantArrayType>(AT))
+ PType = PVDecl->getType();
+ } else if (PType->isFunctionType())
+ PType = PVDecl->getType();
+ getObjCEncodingForType(PType, S);
+ S += charUnitsToString(ParmOffset);
+ ParmOffset += getObjCEncodingTypeSize(PType);
+ }
+}
+
+/// getObjCEncodingForMethodDecl - Return the encoded type for this method
+/// declaration.
+void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
+ std::string& S) const {
+ // FIXME: This is not very efficient.
+ // Encode type qualifer, 'in', 'inout', etc. for the return type.
+ getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S);
+ // Encode result type.
+ getObjCEncodingForType(Decl->getResultType(), S);
+ // Compute size of all parameters.
+ // Start with computing size of a pointer in number of bytes.
+ // FIXME: There might(should) be a better way of doing this computation!
+ SourceLocation Loc;
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
+ // The first two arguments (self and _cmd) are pointers; account for
+ // their size.
+ CharUnits ParmOffset = 2 * PtrSize;
+ for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ E = Decl->sel_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);
+ S += "@0:";
+ S += charUnitsToString(PtrSize);
+
+ // Argument types.
+ ParmOffset = 2 * PtrSize;
+ for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+ E = Decl->sel_param_end(); PI != E; ++PI) {
+ ParmVarDecl *PVDecl = *PI;
+ QualType PType = PVDecl->getOriginalType();
+ if (const ArrayType *AT =
+ dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+ // Use array's original type only if it has known number of
+ // elements.
+ if (!isa<ConstantArrayType>(AT))
+ PType = PVDecl->getType();
+ } else if (PType->isFunctionType())
+ PType = PVDecl->getType();
+ // Process argument qualifiers for user supplied arguments; such as,
+ // 'in', 'inout', etc.
+ getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S);
+ getObjCEncodingForType(PType, S);
+ S += charUnitsToString(ParmOffset);
+ ParmOffset += getObjCEncodingTypeSize(PType);
+ }
+}
+
+/// getObjCEncodingForPropertyDecl - Return the encoded type for this
+/// property declaration. If non-NULL, Container must be either an
+/// ObjCCategoryImplDecl or ObjCImplementationDecl; it should only be
+/// NULL when getting encodings for protocol properties.
+/// Property attributes are stored as a comma-delimited C string. The simple
+/// attributes readonly and bycopy are encoded as single characters. The
+/// parametrized attributes, getter=name, setter=name, and ivar=name, are
+/// encoded as single characters, followed by an identifier. Property types
+/// are also encoded as a parametrized attribute. The characters used to encode
+/// these attributes are defined by the following enumeration:
+/// @code
+/// enum PropertyAttributes {
+/// kPropertyReadOnly = 'R', // property is read-only.
+/// kPropertyBycopy = 'C', // property is a copy of the value last assigned
+/// kPropertyByref = '&', // property is a reference to the value last assigned
+/// kPropertyDynamic = 'D', // property is dynamic
+/// kPropertyGetter = 'G', // followed by getter selector name
+/// kPropertySetter = 'S', // followed by setter selector name
+/// kPropertyInstanceVariable = 'V' // followed by instance variable name
+/// kPropertyType = 't' // followed by old-style type encoding.
+/// kPropertyWeak = 'W' // 'weak' property
+/// kPropertyStrong = 'P' // property GC'able
+/// kPropertyNonAtomic = 'N' // property non-atomic
+/// };
+/// @endcode
+void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container,
+ std::string& S) const {
+ // Collect information from the property implementation decl(s).
+ bool Dynamic = false;
+ ObjCPropertyImplDecl *SynthesizePID = 0;
+
+ // FIXME: Duplicated code due to poor abstraction.
+ if (Container) {
+ if (const ObjCCategoryImplDecl *CID =
+ dyn_cast<ObjCCategoryImplDecl>(Container)) {
+ for (ObjCCategoryImplDecl::propimpl_iterator
+ i = CID->propimpl_begin(), e = CID->propimpl_end();
+ i != e; ++i) {
+ ObjCPropertyImplDecl *PID = *i;
+ if (PID->getPropertyDecl() == PD) {
+ if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) {
+ Dynamic = true;
+ } else {
+ SynthesizePID = PID;
+ }
+ }
+ }
+ } else {
+ const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
+ for (ObjCCategoryImplDecl::propimpl_iterator
+ i = OID->propimpl_begin(), e = OID->propimpl_end();
+ i != e; ++i) {
+ ObjCPropertyImplDecl *PID = *i;
+ if (PID->getPropertyDecl() == PD) {
+ if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) {
+ Dynamic = true;
+ } else {
+ SynthesizePID = PID;
+ }
+ }
+ }
+ }
+ }
+
+ // FIXME: This is not very efficient.
+ S = "T";
+
+ // Encode result type.
+ // GCC has some special rules regarding encoding of properties which
+ // closely resembles encoding of ivars.
+ getObjCEncodingForTypeImpl(PD->getType(), S, true, true, 0,
+ true /* outermost type */,
+ true /* encoding for property */);
+
+ if (PD->isReadOnly()) {
+ S += ",R";
+ } else {
+ switch (PD->getSetterKind()) {
+ case ObjCPropertyDecl::Assign: break;
+ case ObjCPropertyDecl::Copy: S += ",C"; break;
+ case ObjCPropertyDecl::Retain: S += ",&"; break;
+ }
+ }
+
+ // It really isn't clear at all what this means, since properties
+ // are "dynamic by default".
+ if (Dynamic)
+ S += ",D";
+
+ if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ S += ",N";
+
+ if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
+ S += ",G";
+ S += PD->getGetterName().getAsString();
+ }
+
+ if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
+ S += ",S";
+ S += PD->getSetterName().getAsString();
+ }
+
+ if (SynthesizePID) {
+ const ObjCIvarDecl *OID = SynthesizePID->getPropertyIvarDecl();
+ S += ",V";
+ S += OID->getNameAsString();
+ }
+
+ // FIXME: OBJCGC: weak & strong
+}
+
+/// getLegacyIntegralTypeEncoding -
+/// Another legacy compatibility encoding: 32-bit longs are encoded as
+/// 'l' or 'L' , but not always. For typedefs, we need to use
+/// 'i' or 'I' instead if encoding a struct field, or a pointer!
+///
+void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
+ if (isa<TypedefType>(PointeeTy.getTypePtr())) {
+ if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) {
+ if (BT->getKind() == BuiltinType::ULong && getIntWidth(PointeeTy) == 32)
+ PointeeTy = UnsignedIntTy;
+ else
+ if (BT->getKind() == BuiltinType::Long && getIntWidth(PointeeTy) == 32)
+ PointeeTy = IntTy;
+ }
+ }
+}
+
+void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
+ 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
+ // same type.
+ getObjCEncodingForTypeImpl(T, S, true, true, Field,
+ true /* outermost type */);
+}
+
+static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) {
+ switch (T->getAs<BuiltinType>()->getKind()) {
+ default: assert(0 && "Unhandled builtin type kind");
+ case BuiltinType::Void: return 'v';
+ case BuiltinType::Bool: return 'B';
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar: return 'C';
+ case BuiltinType::UShort: return 'S';
+ case BuiltinType::UInt: return 'I';
+ case BuiltinType::ULong:
+ 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_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Int: return 'i';
+ case BuiltinType::Long:
+ 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';
+ }
+}
+
+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");
+ 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,
+ // then the offset (in bits) of the first element, then the type of the
+ // bitfield, then the size in bits. For example, in this structure:
+ //
+ // struct
+ // {
+ // int integer;
+ // int flags:2;
+ // };
+ // On a 32-bit system, the encoding for flags would be b2 for the NeXT
+ // runtime, but b32i2 for the GNU runtime. The reason for this extra
+ // information is not especially sensible, but we're stuck with it for
+ // compatibility with GCC, although providing it breaks anything that
+ // actually uses runtime introspection and wants to work on both runtimes...
+ if (!Ctx->getLangOptions().NeXTRuntime) {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
+ // FIXME: This same linear search is also used in ExprConstant - it might
+ // be better if the FieldDecl stored its offset. We'd be increasing the
+ // size of the object slightly, but saving some time every time it is used.
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
+ break;
+ }
+ S += llvm::utostr(RL.getFieldOffset(i));
+ if (T->isEnumeralType())
+ S += 'i';
+ else
+ S += ObjCEncodingForPrimitiveKind(Ctx, T);
+ }
+ unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue();
+ S += llvm::utostr(N);
+}
+
+// FIXME: Use SmallString for accumulating string.
+void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
+ bool ExpandPointedToStructures,
+ bool ExpandStructures,
+ const FieldDecl *FD,
+ bool OutermostType,
+ bool EncodingProperty) const {
+ if (T->getAs<BuiltinType>()) {
+ if (FD && FD->isBitField())
+ return EncodeBitField(this, S, T, FD);
+ S += ObjCEncodingForPrimitiveKind(this, T);
+ return;
+ }
+
+ if (const ComplexType *CT = T->getAs<ComplexType>()) {
+ S += 'j';
+ getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false,
+ false);
+ return;
+ }
+
+ // encoding for pointer or r3eference types.
+ QualType PointeeTy;
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ if (PT->isObjCSelType()) {
+ S += ':';
+ return;
+ }
+ PointeeTy = PT->getPointeeType();
+ }
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ PointeeTy = RT->getPointeeType();
+ if (!PointeeTy.isNull()) {
+ bool isReadOnly = false;
+ // For historical/compatibility reasons, the read-only qualifier of the
+ // pointee gets emitted _before_ the '^'. The read-only qualifier of
+ // the pointer itself gets ignored, _unless_ we are looking at a typedef!
+ // Also, do not emit the 'r' for anything but the outermost type!
+ if (isa<TypedefType>(T.getTypePtr())) {
+ if (OutermostType && T.isConstQualified()) {
+ isReadOnly = true;
+ S += 'r';
+ }
+ } else if (OutermostType) {
+ QualType P = PointeeTy;
+ while (P->getAs<PointerType>())
+ P = P->getAs<PointerType>()->getPointeeType();
+ if (P.isConstQualified()) {
+ isReadOnly = true;
+ S += 'r';
+ }
+ }
+ if (isReadOnly) {
+ // Another legacy compatibility encoding. Some ObjC qualifier and type
+ // combinations need to be rearranged.
+ // Rewrite "in const" from "nr" to "rn"
+ if (llvm::StringRef(S).endswith("nr"))
+ S.replace(S.end()-2, S.end(), "rn");
+ }
+
+ if (PointeeTy->isCharType()) {
+ // char pointer types should be encoded as '*' unless it is a
+ // type that has been typedef'd to 'BOOL'.
+ if (!isTypeTypedefedAsBOOL(PointeeTy)) {
+ S += '*';
+ return;
+ }
+ } else if (const RecordType *RTy = PointeeTy->getAs<RecordType>()) {
+ // GCC binary compat: Need to convert "struct objc_class *" to "#".
+ if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) {
+ S += '#';
+ return;
+ }
+ // GCC binary compat: Need to convert "struct objc_object *" to "@".
+ if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_object")) {
+ S += '@';
+ return;
+ }
+ // fall through...
+ }
+ S += '^';
+ getLegacyIntegralTypeEncoding(PointeeTy);
+
+ getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures,
+ NULL);
+ return;
+ }
+
+ if (const ArrayType *AT =
+ // Ignore type qualifiers etc.
+ dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
+ if (isa<IncompleteArrayType>(AT)) {
+ // Incomplete arrays are encoded as a pointer to the array element.
+ S += '^';
+
+ getObjCEncodingForTypeImpl(AT->getElementType(), S,
+ false, ExpandStructures, FD);
+ } else {
+ S += '[';
+
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ S += llvm::utostr(CAT->getSize().getZExtValue());
+ else {
+ //Variable length arrays are encoded as a regular array with 0 elements.
+ assert(isa<VariableArrayType>(AT) && "Unknown array type!");
+ S += '0';
+ }
+
+ getObjCEncodingForTypeImpl(AT->getElementType(), S,
+ false, ExpandStructures, FD);
+ S += ']';
+ }
+ return;
+ }
+
+ if (T->getAs<FunctionType>()) {
+ S += '?';
+ return;
+ }
+
+ if (const RecordType *RTy = T->getAs<RecordType>()) {
+ RecordDecl *RDecl = RTy->getDecl();
+ S += RDecl->isUnion() ? '(' : '{';
+ // Anonymous structures print as '?'
+ if (const IdentifierInfo *II = RDecl->getIdentifier()) {
+ S += II->getName();
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.data(),
+ TemplateArgs.size(),
+ (*this).PrintingPolicy);
+
+ S += TemplateArgsStr;
+ }
+ } else {
+ S += '?';
+ }
+ if (ExpandStructures) {
+ S += '=';
+ for (RecordDecl::field_iterator Field = RDecl->field_begin(),
+ FieldEnd = RDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ if (FD) {
+ S += '"';
+ S += Field->getNameAsString();
+ S += '"';
+ }
+
+ // Special case bit-fields.
+ if (Field->isBitField()) {
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
+ (*Field));
+ } else {
+ QualType qt = Field->getType();
+ getLegacyIntegralTypeEncoding(qt);
+ getObjCEncodingForTypeImpl(qt, S, false, true,
+ FD);
+ }
+ }
+ }
+ S += RDecl->isUnion() ? ')' : '}';
+ return;
+ }
+
+ if (T->isEnumeralType()) {
+ if (FD && FD->isBitField())
+ EncodeBitField(this, S, T, FD);
+ else
+ S += 'i';
+ return;
+ }
+
+ if (T->isBlockPointerType()) {
+ S += "@?"; // Unlike a pointer-to-function, which is "^?".
+ return;
+ }
+
+ // Ignore protocol qualifiers when mangling at this level.
+ if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>())
+ T = OT->getBaseType();
+
+ if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
+ // @encode(class_name)
+ ObjCInterfaceDecl *OI = OIT->getDecl();
+ S += '{';
+ const IdentifierInfo *II = OI->getIdentifier();
+ S += II->getName();
+ S += '=';
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ DeepCollectObjCIvars(OI, true, Ivars);
+ for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
+ FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ if (Field->isBitField())
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
+ else
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
+ }
+ S += '}';
+ return;
+ }
+
+ if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) {
+ if (OPT->isObjCIdType()) {
+ S += '@';
+ return;
+ }
+
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ // FIXME: Consider if we need to output qualifiers for 'Class<p>'.
+ // Since this is a binary compatibility issue, need to consult with runtime
+ // folks. Fortunately, this is a *very* obsure construct.
+ S += '#';
+ return;
+ }
+
+ if (OPT->isObjCQualifiedIdType()) {
+ getObjCEncodingForTypeImpl(getObjCIdType(), S,
+ ExpandPointedToStructures,
+ ExpandStructures, FD);
+ if (FD || EncodingProperty) {
+ // Note that we do extended encoding of protocol qualifer list
+ // Only when doing ivar or property encoding.
+ S += '"';
+ for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I) {
+ S += '<';
+ S += (*I)->getNameAsString();
+ S += '>';
+ }
+ S += '"';
+ }
+ return;
+ }
+
+ QualType PointeeTy = OPT->getPointeeType();
+ if (!EncodingProperty &&
+ isa<TypedefType>(PointeeTy.getTypePtr())) {
+ // Another historical/compatibility reason.
+ // We encode the underlying type which comes out as
+ // {...};
+ S += '^';
+ getObjCEncodingForTypeImpl(PointeeTy, S,
+ false, ExpandPointedToStructures,
+ NULL);
+ return;
+ }
+
+ S += '@';
+ if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) {
+ S += '"';
+ S += OPT->getInterfaceDecl()->getIdentifier()->getName();
+ for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I) {
+ S += '<';
+ S += (*I)->getNameAsString();
+ S += '>';
+ }
+ S += '"';
+ }
+ return;
+ }
+
+ // gcc just blithely ignores member pointers.
+ // TODO: maybe there should be a mangling for these
+ if (T->getAs<MemberPointerType>())
+ 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!");
+}
+
+void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
+ std::string& S) const {
+ if (QT & Decl::OBJC_TQ_In)
+ S += 'n';
+ if (QT & Decl::OBJC_TQ_Inout)
+ S += 'N';
+ if (QT & Decl::OBJC_TQ_Out)
+ S += 'o';
+ if (QT & Decl::OBJC_TQ_Bycopy)
+ S += 'O';
+ if (QT & Decl::OBJC_TQ_Byref)
+ S += 'R';
+ if (QT & Decl::OBJC_TQ_Oneway)
+ S += 'V';
+}
+
+void ASTContext::setBuiltinVaListType(QualType T) {
+ assert(BuiltinVaListType.isNull() && "__builtin_va_list type already set!");
+
+ BuiltinVaListType = T;
+}
+
+void ASTContext::setObjCIdType(QualType T) {
+ ObjCIdTypedefType = T;
+}
+
+void ASTContext::setObjCSelType(QualType T) {
+ ObjCSelTypedefType = T;
+}
+
+void ASTContext::setObjCProtoType(QualType QT) {
+ ObjCProtoType = QT;
+}
+
+void ASTContext::setObjCClassType(QualType T) {
+ ObjCClassTypedefType = T;
+}
+
+void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
+ assert(ObjCConstantStringType.isNull() &&
+ "'NSConstantString' type already set!");
+
+ ObjCConstantStringType = getObjCInterfaceType(Decl);
+}
+
+/// \brief Retrieve the template name that corresponds to a non-empty
+/// lookup.
+TemplateName
+ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) const {
+ unsigned size = End - Begin;
+ assert(size > 1 && "set is not overloaded!");
+
+ void *memory = Allocate(sizeof(OverloadedTemplateStorage) +
+ size * sizeof(FunctionTemplateDecl*));
+ OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
+
+ NamedDecl **Storage = OT->getStorage();
+ for (UnresolvedSetIterator I = Begin; I != End; ++I) {
+ NamedDecl *D = *I;
+ assert(isa<FunctionTemplateDecl>(D) ||
+ (isa<UsingShadowDecl>(D) &&
+ isa<FunctionTemplateDecl>(D->getUnderlyingDecl())));
+ *Storage++ = D;
+ }
+
+ return TemplateName(OT);
+}
+
+/// \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) const {
+ // FIXME: Canonicalization?
+ llvm::FoldingSetNodeID ID;
+ QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
+
+ void *InsertPos = 0;
+ QualifiedTemplateName *QTN =
+ QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ if (!QTN) {
+ QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
+ QualifiedTemplateNames.InsertNode(QTN, InsertPos);
+ }
+
+ return TemplateName(QTN);
+}
+
+/// \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) const {
+ assert((!NNS || NNS->isDependent()) &&
+ "Nested name specifier must be dependent");
+
+ llvm::FoldingSetNodeID ID;
+ DependentTemplateName::Profile(ID, NNS, Name);
+
+ void *InsertPos = 0;
+ DependentTemplateName *QTN =
+ DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (QTN)
+ return TemplateName(QTN);
+
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ if (CanonNNS == NNS) {
+ QTN = new (*this,4) DependentTemplateName(NNS, Name);
+ } else {
+ TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
+ QTN = new (*this,4) DependentTemplateName(NNS, Name, Canon);
+ DependentTemplateName *CheckQTN =
+ DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CheckQTN && "Dependent type name canonicalization broken");
+ (void)CheckQTN;
+ }
+
+ DependentTemplateNames.InsertNode(QTN, InsertPos);
+ return TemplateName(QTN);
+}
+
+/// \brief Retrieve the template name that represents a dependent
+/// template name such as \c MetaFun::template operator+.
+TemplateName
+ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
+ OverloadedOperatorKind Operator) const {
+ assert((!NNS || NNS->isDependent()) &&
+ "Nested name specifier must be dependent");
+
+ llvm::FoldingSetNodeID ID;
+ DependentTemplateName::Profile(ID, NNS, Operator);
+
+ void *InsertPos = 0;
+ DependentTemplateName *QTN
+ = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (QTN)
+ return TemplateName(QTN);
+
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ if (CanonNNS == NNS) {
+ QTN = new (*this,4) DependentTemplateName(NNS, Operator);
+ } else {
+ TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
+ QTN = new (*this,4) DependentTemplateName(NNS, Operator, Canon);
+
+ DependentTemplateName *CheckQTN
+ = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!CheckQTN && "Dependent template name canonicalization broken");
+ (void)CheckQTN;
+ }
+
+ DependentTemplateNames.InsertNode(QTN, InsertPos);
+ return TemplateName(QTN);
+}
+
+TemplateName
+ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
+ const TemplateArgument &ArgPack) const {
+ ASTContext &Self = const_cast<ASTContext &>(*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.
+CanQualType ASTContext::getFromTargetType(unsigned Type) const {
+ switch (Type) {
+ case TargetInfo::NoInt: return CanQualType();
+ case TargetInfo::SignedShort: return ShortTy;
+ case TargetInfo::UnsignedShort: return UnsignedShortTy;
+ case TargetInfo::SignedInt: return IntTy;
+ case TargetInfo::UnsignedInt: return UnsignedIntTy;
+ case TargetInfo::SignedLong: return LongTy;
+ case TargetInfo::UnsignedLong: return UnsignedLongTy;
+ case TargetInfo::SignedLongLong: return LongLongTy;
+ case TargetInfo::UnsignedLongLong: return UnsignedLongLongTy;
+ }
+
+ assert(false && "Unhandled TargetInfo::IntType value");
+ return CanQualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Type Predicates.
+//===----------------------------------------------------------------------===//
+
+/// isObjCNSObjectType - Return true if this is an NSObject object using
+/// NSObject attribute on a c-style pointer type.
+/// FIXME - Make it work directly on types.
+/// FIXME: Move to Type.
+///
+bool ASTContext::isObjCNSObjectType(QualType Ty) const {
+ if (const TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
+ if (TypedefDecl *TD = TDT->getDecl())
+ if (TD->getAttr<ObjCNSObjectAttr>())
+ return true;
+ }
+ return false;
+}
+
+/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
+/// garbage collection attribute.
+///
+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<PointerType>()->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<ArrayType>(CT))
+ CT = AT->getElementType();
+ assert(CT->isAnyPointerType() || CT->isBlockPointerType());
+#endif
+ }
+ return GCAttrs;
+}
+
+//===----------------------------------------------------------------------===//
+// Type Compatibility Testing
+//===----------------------------------------------------------------------===//
+
+/// areCompatVectorTypes - Return true if the two specified vector types are
+/// compatible.
+static bool areCompatVectorTypes(const VectorType *LHS,
+ const VectorType *RHS) {
+ assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());
+ return LHS->getElementType() == RHS->getElementType() &&
+ LHS->getNumElements() == RHS->getNumElements();
+}
+
+bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
+ QualType SecondVec) {
+ assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
+ assert(SecondVec->isVectorType() && "SecondVec should be a vector type");
+
+ if (hasSameUnqualifiedType(FirstVec, SecondVec))
+ return true;
+
+ // Treat Neon vector types and most AltiVec vector types as if they are the
+ // equivalent GCC vector types.
+ const VectorType *First = FirstVec->getAs<VectorType>();
+ const VectorType *Second = SecondVec->getAs<VectorType>();
+ if (First->getNumElements() == Second->getNumElements() &&
+ hasSameType(First->getElementType(), Second->getElementType()) &&
+ First->getVectorKind() != VectorType::AltiVecPixel &&
+ First->getVectorKind() != VectorType::AltiVecBool &&
+ Second->getVectorKind() != VectorType::AltiVecPixel &&
+ Second->getVectorKind() != VectorType::AltiVecBool)
+ return true;
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
+//===----------------------------------------------------------------------===//
+
+/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
+/// inheritance hierarchy of 'rProto'.
+bool
+ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
+ ObjCProtocolDecl *rProto) const {
+ if (lProto == rProto)
+ return true;
+ for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
+ E = rProto->protocol_end(); PI != E; ++PI)
+ if (ProtocolCompatibleWithProtocol(lProto, *PI))
+ return true;
+ return false;
+}
+
+/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
+/// return true if lhs's protocols conform to rhs's protocol; false
+/// otherwise.
+bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
+ if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType())
+ return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false);
+ return false;
+}
+
+/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and
+/// Class<p1, ...>.
+bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
+ QualType rhs) {
+ const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
+
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ bool match = false;
+ ObjCProtocolDecl *lhsProto = *I;
+ for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+ E = rhsOPT->qual_end(); J != E; ++J) {
+ ObjCProtocolDecl *rhsProto = *J;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false;
+ }
+ return true;
+}
+
+/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
+/// ObjCQualifiedIDType.
+bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
+ bool compare) {
+ // Allow id<P..> and an 'id' or void* type in all cases.
+ if (lhs->isVoidPointerType() ||
+ lhs->isObjCIdType() || lhs->isObjCClassType())
+ return true;
+ else if (rhs->isVoidPointerType() ||
+ rhs->isObjCIdType() || rhs->isObjCClassType())
+ return true;
+
+ if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+
+ if (!rhsOPT) return false;
+
+ if (rhsOPT->qual_empty()) {
+ // If the RHS is a unqualified interface pointer "NSString*",
+ // make sure we check the class hierarchy.
+ if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ // when comparing an id<P> on lhs with a static type on rhs,
+ // see if static class implements all of id's protocols, directly or
+ // through its super class and categories.
+ if (!rhsID->ClassImplementsProtocol(*I, true))
+ return false;
+ }
+ }
+ // If there are no qualifiers and no interface, we have an 'id'.
+ return true;
+ }
+ // Both the right and left sides have qualifiers.
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ ObjCProtocolDecl *lhsProto = *I;
+ bool match = false;
+
+ // when comparing an id<P> on lhs with a static type on rhs,
+ // see if static class implements all of id's protocols, directly or
+ // through its super class and categories.
+ for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+ E = rhsOPT->qual_end(); J != E; ++J) {
+ ObjCProtocolDecl *rhsProto = *J;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+ (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
+ match = true;
+ break;
+ }
+ }
+ // If the RHS is a qualified interface pointer "NSString<P>*",
+ // make sure we check the class hierarchy.
+ if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ // when comparing an id<P> on lhs with a static type on rhs,
+ // see if static class implements all of id's protocols, directly or
+ // through its super class and categories.
+ if (rhsID->ClassImplementsProtocol(*I, true)) {
+ match = true;
+ break;
+ }
+ }
+ }
+ if (!match)
+ return false;
+ }
+
+ return true;
+ }
+
+ const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
+ assert(rhsQID && "One of the LHS/RHS should be id<x>");
+
+ if (const ObjCObjectPointerType *lhsOPT =
+ lhs->getAsObjCInterfacePointerType()) {
+ // 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<P> 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;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+ (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
+ match = true;
+ break;
+ }
+ }
+ 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<ObjCProtocolDecl *, 8> 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<ObjCProtocolDecl*,8>::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;
+}
+
+/// canAssignObjCInterfaces - Return true if the two interface types are
+/// compatible for assignment from RHS to LHS. This handles validation of any
+/// protocol qualifiers on the LHS or RHS.
+///
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT) {
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+
+ // If either type represents the built-in 'id' or 'Class' types, return true.
+ if (LHS->isObjCUnqualifiedIdOrClass() ||
+ RHS->isObjCUnqualifiedIdOrClass())
+ return true;
+
+ if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
+ return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0),
+ false);
+
+ if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
+ return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0));
+
+ // If we have 2 user-defined types, fall into that path.
+ if (LHS->getInterface() && RHS->getInterface())
+ return canAssignObjCInterfaces(LHS, RHS);
+
+ return false;
+}
+
+/// canAssignObjCInterfacesInBlockPointer - This routine is specifically written
+/// for providing type-safty for objective-c pointers used to pass/return
+/// arguments in block literals. When passed as arguments, passing 'A*' where
+/// 'id' is expected is not OK. Passing 'Sub *" where 'Super *" is expected is
+/// not OK. For the return type, the opposite is not OK.
+bool ASTContext::canAssignObjCInterfacesInBlockPointer(
+ const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT) {
+ if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
+ return true;
+
+ if (LHSOPT->isObjCBuiltinType()) {
+ return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
+ }
+
+ if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
+ return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0),
+ false);
+
+ const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+ const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+ if (LHS && RHS) { // We have 2 user-defined types.
+ if (LHS != RHS) {
+ if (LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
+ return false;
+ if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
+ return true;
+ }
+ else
+ return true;
+ }
+ return false;
+}
+
+/// getIntersectionOfProtocols - This routine finds the intersection of set
+/// of protocols inherited from two distinct objective-c pointer objects.
+/// It is used to build composite qualifier list of the composite type of
+/// the conditional expression involving two objective-c pointer objects.
+static
+void getIntersectionOfProtocols(ASTContext &Context,
+ const ObjCObjectPointerType *LHSOPT,
+ const ObjCObjectPointerType *RHSOPT,
+ llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
+
+ const ObjCObjectType* LHS = LHSOPT->getObjectType();
+ const ObjCObjectType* RHS = RHSOPT->getObjectType();
+ assert(LHS->getInterface() && "LHS must have an interface base");
+ assert(RHS->getInterface() && "RHS must have an interface base");
+
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
+ unsigned LHSNumProtocols = LHS->getNumProtocols();
+ if (LHSNumProtocols > 0)
+ InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
+ else {
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
+ Context.CollectInheritedProtocols(LHS->getInterface(),
+ LHSInheritedProtocols);
+ InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
+ LHSInheritedProtocols.end());
+ }
+
+ unsigned RHSNumProtocols = RHS->getNumProtocols();
+ if (RHSNumProtocols > 0) {
+ ObjCProtocolDecl **RHSProtocols =
+ const_cast<ObjCProtocolDecl **>(RHS->qual_begin());
+ for (unsigned i = 0; i < RHSNumProtocols; ++i)
+ if (InheritedProtocolSet.count(RHSProtocols[i]))
+ IntersectionOfProtocols.push_back(RHSProtocols[i]);
+ }
+ else {
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
+ Context.CollectInheritedProtocols(RHS->getInterface(),
+ RHSInheritedProtocols);
+ for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
+ RHSInheritedProtocols.begin(),
+ E = RHSInheritedProtocols.end(); I != E; ++I)
+ if (InheritedProtocolSet.count((*I)))
+ IntersectionOfProtocols.push_back((*I));
+ }
+}
+
+/// areCommonBaseCompatible - Returns common base class of the two classes if
+/// one found. Note that this is O'2 algorithm. But it will be called as the
+/// last type comparison in a ?-exp of ObjC pointer types before a
+/// warning is issued. So, its invokation is extremely rare.
+QualType ASTContext::areCommonBaseCompatible(
+ const ObjCObjectPointerType *Lptr,
+ const ObjCObjectPointerType *Rptr) {
+ const ObjCObjectType *LHS = Lptr->getObjectType();
+ const ObjCObjectType *RHS = Rptr->getObjectType();
+ const ObjCInterfaceDecl* LDecl = LHS->getInterface();
+ const ObjCInterfaceDecl* RDecl = RHS->getInterface();
+ if (!LDecl || !RDecl)
+ return QualType();
+
+ while ((LDecl = LDecl->getSuperClass())) {
+ LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
+ if (canAssignObjCInterfaces(LHS, RHS)) {
+ llvm::SmallVector<ObjCProtocolDecl *, 8> Protocols;
+ getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
+
+ QualType Result = QualType(LHS, 0);
+ if (!Protocols.empty())
+ Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
+ Result = getObjCObjectPointerType(Result);
+ return Result;
+ }
+ }
+
+ return QualType();
+}
+
+bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
+ const ObjCObjectType *RHS) {
+ assert(LHS->getInterface() && "LHS is not an interface type");
+ assert(RHS->getInterface() && "RHS is not an interface type");
+
+ // Verify that the base decls are compatible: the RHS must be a subclass of
+ // the LHS.
+ if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
+ return false;
+
+ // RHS must have a superset of the protocols in the LHS. If the LHS is not
+ // protocol qualified at all, then we are good.
+ if (LHS->getNumProtocols() == 0)
+ return true;
+
+ // Okay, we know the LHS has protocol qualifiers. If the RHS doesn't, then it
+ // isn't a superset.
+ if (RHS->getNumProtocols() == 0)
+ return true; // FIXME: should return false!
+
+ for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
+ LHSPE = LHS->qual_end();
+ LHSPI != LHSPE; LHSPI++) {
+ bool RHSImplementsProtocol = false;
+
+ // If the RHS doesn't implement the protocol on the left, the types
+ // are incompatible.
+ for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(),
+ RHSPE = RHS->qual_end();
+ RHSPI != RHSPE; RHSPI++) {
+ if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) {
+ RHSImplementsProtocol = true;
+ break;
+ }
+ }
+ // FIXME: For better diagnostics, consider passing back the protocol name.
+ if (!RHSImplementsProtocol)
+ return false;
+ }
+ // The RHS implements all protocols listed on the LHS.
+ return true;
+}
+
+bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
+ // get the "pointed to" types
+ const ObjCObjectPointerType *LHSOPT = LHS->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *RHSOPT = RHS->getAs<ObjCObjectPointerType>();
+
+ if (!LHSOPT || !RHSOPT)
+ return false;
+
+ return canAssignObjCInterfaces(LHSOPT, RHSOPT) ||
+ canAssignObjCInterfaces(RHSOPT, LHSOPT);
+}
+
+bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
+ return canAssignObjCInterfaces(
+ getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
+ getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
+}
+
+/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
+/// both shall have the identically qualified version of a compatible type.
+/// C99 6.2.7p1: Two types have compatible types if their types are the
+/// same. See 6.7.[2,3,5] for additional rules.
+bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
+ bool CompareUnqualified) {
+ if (getLangOptions().CPlusPlus)
+ return hasSameType(LHS, RHS);
+
+ return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
+}
+
+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<TransparentUnionAttr>()) {
+ 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) {
+ const FunctionType *lbase = lhs->getAs<FunctionType>();
+ const FunctionType *rbase = rhs->getAs<FunctionType>();
+ const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
+ const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase);
+ bool allLTypes = true;
+ bool allRTypes = true;
+
+ // Check return type
+ QualType retType;
+ 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);
+ if (retType.isNull()) return QualType();
+
+ if (Unqualified)
+ retType = retType.getUnqualifiedType();
+
+ CanQualType LRetType = getCanonicalType(lbase->getResultType());
+ CanQualType RRetType = getCanonicalType(rbase->getResultType());
+ if (Unqualified) {
+ LRetType = LRetType.getUnqualifiedType();
+ RRetType = RRetType.getUnqualifiedType();
+ }
+
+ if (getCanonicalType(retType) != LRetType)
+ allLTypes = false;
+ if (getCanonicalType(retType) != 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();
+
+ // 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())
+ allLTypes = false;
+ if (NoReturn != rbaseInfo.getNoReturn())
+ allRTypes = false;
+
+ FunctionType::ExtInfo einfo(NoReturn,
+ lbaseInfo.getRegParm(),
+ lbaseInfo.getCC());
+
+ if (lproto && rproto) { // two C99 style function prototypes
+ assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
+ "C++ shouldn't be here");
+ unsigned lproto_nargs = lproto->getNumArgs();
+ unsigned rproto_nargs = rproto->getNumArgs();
+
+ // Compatible functions must have the same number of arguments
+ if (lproto_nargs != rproto_nargs)
+ return QualType();
+
+ // Variadic and non-variadic functions aren't compatible
+ if (lproto->isVariadic() != rproto->isVariadic())
+ return QualType();
+
+ if (lproto->getTypeQuals() != rproto->getTypeQuals())
+ return QualType();
+
+ // Check argument compatibility
+ llvm::SmallVector<QualType, 10> types;
+ for (unsigned i = 0; i < lproto_nargs; i++) {
+ QualType largtype = lproto->getArgType(i).getUnqualifiedType();
+ QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
+ QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype,
+ OfBlockPointer,
+ Unqualified);
+ if (argtype.isNull()) return QualType();
+
+ if (Unqualified)
+ argtype = argtype.getUnqualifiedType();
+
+ types.push_back(argtype);
+ if (Unqualified) {
+ largtype = largtype.getUnqualifiedType();
+ rargtype = rargtype.getUnqualifiedType();
+ }
+
+ if (getCanonicalType(argtype) != getCanonicalType(largtype))
+ allLTypes = false;
+ if (getCanonicalType(argtype) != getCanonicalType(rargtype))
+ allRTypes = false;
+ }
+ if (allLTypes) return lhs;
+ if (allRTypes) return rhs;
+
+ FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo();
+ EPI.ExtInfo = einfo;
+ return getFunctionType(retType, types.begin(), types.size(), EPI);
+ }
+
+ if (lproto) allRTypes = false;
+ if (rproto) allLTypes = false;
+
+ const FunctionProtoType *proto = lproto ? lproto : rproto;
+ if (proto) {
+ assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
+ if (proto->isVariadic()) return QualType();
+ // Check that the types are compatible with the types that
+ // would result from default argument promotions (C99 6.7.5.3p15).
+ // The only types actually affected are promotable integer
+ // types and floats, which would be passed as a different
+ // type depending on whether the prototype is visible.
+ unsigned proto_nargs = proto->getNumArgs();
+ for (unsigned i = 0; i < proto_nargs; ++i) {
+ QualType argTy = proto->getArgType(i);
+
+ // Look at the promotion type of enum types, since that is the type used
+ // to pass enum values.
+ if (const EnumType *Enum = argTy->getAs<EnumType>())
+ argTy = Enum->getDecl()->getPromotionType();
+
+ if (argTy->isPromotableIntegerType() ||
+ getCanonicalType(argTy).getUnqualifiedType() == FloatTy)
+ return QualType();
+ }
+
+ 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(), EPI);
+ }
+
+ if (allLTypes) return lhs;
+ if (allRTypes) return rhs;
+ return getFunctionNoProtoType(retType, einfo);
+}
+
+QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
+ bool OfBlockPointer,
+ bool Unqualified) {
+ // C++ [expr]: If an expression initially has the type "reference to T", the
+ // type is adjusted to "T" prior to any further analysis, the expression
+ // designates the object or function denoted by the reference, and the
+ // expression is an lvalue unless the reference is an rvalue reference and
+ // the expression is a function call (possibly inside parentheses).
+ assert(!LHS->getAs<ReferenceType>() && "LHS is a reference type?");
+ assert(!RHS->getAs<ReferenceType>() && "RHS is a reference type?");
+
+ if (Unqualified) {
+ LHS = LHS.getUnqualifiedType();
+ RHS = RHS.getUnqualifiedType();
+ }
+
+ QualType LHSCan = getCanonicalType(LHS),
+ RHSCan = getCanonicalType(RHS);
+
+ // If two types are identical, they are compatible.
+ if (LHSCan == RHSCan)
+ return LHS;
+
+ // If the qualifiers are different, the types aren't compatible... mostly.
+ Qualifiers LQuals = LHSCan.getLocalQualifiers();
+ Qualifiers RQuals = RHSCan.getLocalQualifiers();
+ if (LQuals != RQuals) {
+ // If any of these qualifiers are different, we have a type
+ // mismatch.
+ if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+ LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ return QualType();
+
+ // Exactly one GC qualifier difference is allowed: __strong is
+ // okay if the other type has no GC qualifier but is an Objective
+ // C object pointer (i.e. implicitly strong by default). We fix
+ // this by pretending that the unqualified type was actually
+ // qualified __strong.
+ Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+ Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+ assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+ if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+ return QualType();
+
+ if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
+ }
+ if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
+ }
+ return QualType();
+ }
+
+ // Okay, qualifiers are equal.
+
+ Type::TypeClass LHSClass = LHSCan->getTypeClass();
+ Type::TypeClass RHSClass = RHSCan->getTypeClass();
+
+ // We want to consider the two function types to be the same for these
+ // comparisons, just force one to the other.
+ if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto;
+ if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto;
+
+ // Same as above for arrays
+ if (LHSClass == Type::VariableArray || LHSClass == Type::IncompleteArray)
+ LHSClass = Type::ConstantArray;
+ if (RHSClass == Type::VariableArray || RHSClass == Type::IncompleteArray)
+ RHSClass = Type::ConstantArray;
+
+ // ObjCInterfaces are just specialized ObjCObjects.
+ if (LHSClass == Type::ObjCInterface) LHSClass = Type::ObjCObject;
+ if (RHSClass == Type::ObjCInterface) RHSClass = Type::ObjCObject;
+
+ // Canonicalize ExtVector -> Vector.
+ if (LHSClass == Type::ExtVector) LHSClass = Type::Vector;
+ if (RHSClass == Type::ExtVector) RHSClass = Type::Vector;
+
+ // If the canonical type classes don't match.
+ if (LHSClass != RHSClass) {
+ // C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
+ // a signed integer type, or an unsigned integer type.
+ // Compatibility is based on the underlying type, not the promotion
+ // type.
+ if (const EnumType* ETy = LHS->getAs<EnumType>()) {
+ if (ETy->getDecl()->getIntegerType() == RHSCan.getUnqualifiedType())
+ return RHS;
+ }
+ if (const EnumType* ETy = RHS->getAs<EnumType>()) {
+ if (ETy->getDecl()->getIntegerType() == LHSCan.getUnqualifiedType())
+ return LHS;
+ }
+
+ return QualType();
+ }
+
+ // The canonical type classes match.
+ switch (LHSClass) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical and dependent types shouldn't get here");
+ return QualType();
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ assert(false && "C++ should never be in mergeTypes");
+ return QualType();
+
+ case Type::ObjCInterface:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::FunctionProto:
+ case Type::ExtVector:
+ assert(false && "Types are eliminated above");
+ return QualType();
+
+ case Type::Pointer:
+ {
+ // Merge two pointer types, while trying to preserve typedef info
+ QualType LHSPointee = LHS->getAs<PointerType>()->getPointeeType();
+ QualType RHSPointee = RHS->getAs<PointerType>()->getPointeeType();
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
+ return RHS;
+ return getPointerType(ResultType);
+ }
+ case Type::BlockPointer:
+ {
+ // Merge two block pointer types, while trying to preserve typedef info
+ QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
+ QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
+ return RHS;
+ return getBlockPointerType(ResultType);
+ }
+ case Type::ConstantArray:
+ {
+ const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
+ const ConstantArrayType* RCAT = getAsConstantArrayType(RHS);
+ if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize())
+ return QualType();
+
+ QualType LHSElem = getAsArrayType(LHS)->getElementType();
+ QualType RHSElem = getAsArrayType(RHS)->getElementType();
+ if (Unqualified) {
+ LHSElem = LHSElem.getUnqualifiedType();
+ RHSElem = RHSElem.getUnqualifiedType();
+ }
+
+ QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
+ return LHS;
+ if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
+ return RHS;
+ if (LCAT) return getConstantArrayType(ResultType, LCAT->getSize(),
+ ArrayType::ArraySizeModifier(), 0);
+ if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
+ ArrayType::ArraySizeModifier(), 0);
+ const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
+ const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
+ if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
+ return LHS;
+ if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
+ return RHS;
+ if (LVAT) {
+ // FIXME: This isn't correct! But tricky to implement because
+ // the array's size has to be the size of LHS, but the type
+ // has to be different.
+ return LHS;
+ }
+ if (RVAT) {
+ // FIXME: This isn't correct! But tricky to implement because
+ // the array's size has to be the size of RHS, but the type
+ // has to be different.
+ return RHS;
+ }
+ if (getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS;
+ if (getCanonicalType(RHSElem) == getCanonicalType(ResultType)) return RHS;
+ return getIncompleteArrayType(ResultType,
+ ArrayType::ArraySizeModifier(), 0);
+ }
+ case Type::FunctionNoProto:
+ return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
+ case Type::Record:
+ case Type::Enum:
+ return QualType();
+ case Type::Builtin:
+ // Only exactly equal builtin types are compatible, which is tested above.
+ return QualType();
+ case Type::Complex:
+ // Distinct complex types are incompatible.
+ return QualType();
+ case Type::Vector:
+ // FIXME: The merged type should be an ExtVector!
+ if (areCompatVectorTypes(LHSCan->getAs<VectorType>(),
+ RHSCan->getAs<VectorType>()))
+ return LHS;
+ return QualType();
+ case Type::ObjCObject: {
+ // Check if the types are assignment compatible.
+ // FIXME: This should be type compatibility, e.g. whether
+ // "LHS x; RHS x;" at global scope is legal.
+ const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>();
+ const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>();
+ if (canAssignObjCInterfaces(LHSIface, RHSIface))
+ return LHS;
+
+ return QualType();
+ }
+ case Type::ObjCObjectPointer: {
+ if (OfBlockPointer) {
+ if (canAssignObjCInterfacesInBlockPointer(
+ LHS->getAs<ObjCObjectPointerType>(),
+ RHS->getAs<ObjCObjectPointerType>()))
+ return LHS;
+ return QualType();
+ }
+ if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(),
+ RHS->getAs<ObjCObjectPointerType>()))
+ return LHS;
+
+ return QualType();
+ }
+ }
+
+ return QualType();
+}
+
+/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
+/// 'RHS' attributes and returns the merged version; including for function
+/// return types.
+QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
+ QualType LHSCan = getCanonicalType(LHS),
+ RHSCan = getCanonicalType(RHS);
+ // If two types are identical, they are compatible.
+ if (LHSCan == RHSCan)
+ return LHS;
+ if (RHSCan->isFunctionType()) {
+ if (!LHSCan->isFunctionType())
+ return QualType();
+ QualType OldReturnType =
+ cast<FunctionType>(RHSCan.getTypePtr())->getResultType();
+ QualType NewReturnType =
+ cast<FunctionType>(LHSCan.getTypePtr())->getResultType();
+ QualType ResReturnType =
+ mergeObjCGCQualifiers(NewReturnType, OldReturnType);
+ if (ResReturnType.isNull())
+ return QualType();
+ if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) {
+ // id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo();
+ // In either case, use OldReturnType to build the new function type.
+ const FunctionType *F = LHS->getAs<FunctionType>();
+ if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) {
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.ExtInfo = getFunctionExtInfo(LHS);
+ QualType ResultType
+ = getFunctionType(OldReturnType, FPT->arg_type_begin(),
+ FPT->getNumArgs(), EPI);
+ return ResultType;
+ }
+ }
+ return QualType();
+ }
+
+ // If the qualifiers are different, the types can still be merged.
+ Qualifiers LQuals = LHSCan.getLocalQualifiers();
+ Qualifiers RQuals = RHSCan.getLocalQualifiers();
+ if (LQuals != RQuals) {
+ // If any of these qualifiers are different, we have a type mismatch.
+ if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+ LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ return QualType();
+
+ // Exactly one GC qualifier difference is allowed: __strong is
+ // okay if the other type has no GC qualifier but is an Objective
+ // C object pointer (i.e. implicitly strong by default). We fix
+ // this by pretending that the unqualified type was actually
+ // qualified __strong.
+ Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+ Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+ assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+ if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+ return QualType();
+
+ if (GC_L == Qualifiers::Strong)
+ return LHS;
+ if (GC_R == Qualifiers::Strong)
+ return RHS;
+ return QualType();
+ }
+
+ if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
+ QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType ResQT = mergeObjCGCQualifiers(LHSBaseQT, RHSBaseQT);
+ if (ResQT == LHSBaseQT)
+ return LHS;
+ if (ResQT == RHSBaseQT)
+ return RHS;
+ }
+ return QualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Integer Predicates
+//===----------------------------------------------------------------------===//
+
+unsigned ASTContext::getIntWidth(QualType T) const {
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getIntegerType();
+ if (T->isBooleanType())
+ return 1;
+ // For builtin types, just use the standard type sizing method
+ return (unsigned)getTypeSize(T);
+}
+
+QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
+ assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
+
+ // Turn <4 x signed int> -> <4 x unsigned int>
+ if (const VectorType *VTy = T->getAs<VectorType>())
+ return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
+ VTy->getNumElements(), VTy->getVectorKind());
+
+ // For enums, we return the unsigned version of the base type.
+ if (const EnumType *ETy = T->getAs<EnumType>())
+ T = ETy->getDecl()->getIntegerType();
+
+ const BuiltinType *BTy = T->getAs<BuiltinType>();
+ assert(BTy && "Unexpected signed integer type");
+ switch (BTy->getKind()) {
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return UnsignedCharTy;
+ case BuiltinType::Short:
+ return UnsignedShortTy;
+ case BuiltinType::Int:
+ return UnsignedIntTy;
+ case BuiltinType::Long:
+ return UnsignedLongTy;
+ case BuiltinType::LongLong:
+ return UnsignedLongLongTy;
+ case BuiltinType::Int128:
+ return UnsignedInt128Ty;
+ default:
+ assert(0 && "Unexpected signed integer type");
+ return QualType();
+ }
+}
+
+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. 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 &RequiresICE,
+ bool AllowTypeModifiers) {
+ // Modifiers.
+ int HowLong = 0;
+ bool Signed = false, Unsigned = false;
+ 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!");
+ Signed = true;
+ break;
+ case 'U':
+ assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
+ assert(!Unsigned && "Can't use 'S' modifier multiple times!");
+ Unsigned = true;
+ break;
+ case 'L':
+ assert(HowLong <= 2 && "Can't have LLLL modifier");
+ ++HowLong;
+ break;
+ }
+ }
+
+ QualType Type;
+
+ // Read the base type.
+ switch (*Str++) {
+ default: assert(0 && "Unknown builtin type letter!");
+ case 'v':
+ assert(HowLong == 0 && !Signed && !Unsigned &&
+ "Bad modifiers used with 'v'!");
+ Type = Context.VoidTy;
+ break;
+ case 'f':
+ assert(HowLong == 0 && !Signed && !Unsigned &&
+ "Bad modifiers used with 'f'!");
+ Type = Context.FloatTy;
+ break;
+ case 'd':
+ assert(HowLong < 2 && !Signed && !Unsigned &&
+ "Bad modifiers used with 'd'!");
+ if (HowLong)
+ Type = Context.LongDoubleTy;
+ else
+ Type = Context.DoubleTy;
+ break;
+ case 's':
+ assert(HowLong == 0 && "Bad modifiers used with 's'!");
+ if (Unsigned)
+ Type = Context.UnsignedShortTy;
+ else
+ Type = Context.ShortTy;
+ break;
+ case 'i':
+ if (HowLong == 3)
+ Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
+ else if (HowLong == 2)
+ Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
+ else if (HowLong == 1)
+ Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
+ else
+ Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy;
+ break;
+ case 'c':
+ assert(HowLong == 0 && "Bad modifiers used with 'c'!");
+ if (Signed)
+ Type = Context.SignedCharTy;
+ else if (Unsigned)
+ Type = Context.UnsignedCharTy;
+ else
+ Type = Context.CharTy;
+ break;
+ case 'b': // boolean
+ assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
+ Type = Context.BoolTy;
+ break;
+ case 'z': // size_t.
+ assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
+ Type = Context.getSizeType();
+ break;
+ 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!");
+ break;
+ case 'A':
+ // This is a "reference" to a va_list; however, what exactly
+ // this means depends on how va_list is defined. There are two
+ // different kinds of va_list: ones passed by value, and ones
+ // passed by reference. An example of a by-value va_list is
+ // x86, where va_list is a char*. An example of by-ref va_list
+ // is x86-64, where va_list is a __va_list_tag[1]. For x86,
+ // we want this argument to be a char*&; for x86-64, we want
+ // it to be a __va_list_tag*.
+ Type = Context.getBuiltinVaListType();
+ assert(!Type.isNull() && "builtin va list type not initialized!");
+ if (Type->isArrayType())
+ Type = Context.getArrayDecayedType(Type);
+ 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,
+ 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::GenericVector);
+ break;
+ }
+ case 'X': {
+ QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
+ false);
+ assert(!RequiresICE && "Can't require complex ICE");
+ Type = Context.getComplexType(ElementType);
+ break;
+ }
+ case 'P':
+ Type = Context.getFILEType();
+ if (Type.isNull()) {
+ Error = ASTContext::GE_Missing_stdio;
+ return QualType();
+ }
+ break;
+ case 'J':
+ if (Signed)
+ Type = Context.getsigjmp_bufType();
+ else
+ Type = Context.getjmp_bufType();
+
+ if (Type.isNull()) {
+ Error = ASTContext::GE_Missing_setjmp;
+ return QualType();
+ }
+ break;
+ }
+
+ // 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;
+ }
+ }
+
+ 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,
+ unsigned *IntegerConstantArgs) const {
+ const char *TypeStr = BuiltinInfo.GetTypeString(Id);
+
+ llvm::SmallVector<QualType, 8> ArgTypes;
+
+ bool RequiresICE = false;
+ Error = GE_None;
+ 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, 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);
+
+ ArgTypes.push_back(Ty);
+ }
+
+ assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
+ "'.' should only occur at end of builtin type list!");
+
+ FunctionType::ExtInfo EI;
+ if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
+
+ bool Variadic = (TypeStr[0] == '.');
+
+ // We really shouldn't be making a no-proto type here, especially in C++.
+ if (ArgTypes.empty() && Variadic)
+ return getFunctionNoProtoType(ResType, EI);
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = EI;
+ EPI.Variadic = Variadic;
+
+ return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI);
+}
+
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
+ GVALinkage External = GVA_StrongExternal;
+
+ Linkage L = FD->getLinkage();
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = GVA_StrongExternal;
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
+ External = GVA_TemplateInstantiation;
+ break;
+ }
+ }
+
+ if (!FD->isInlined())
+ return External;
+
+ if (!getLangOptions().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
+ // GNU or C99 inline semantics. Determine whether this symbol should be
+ // externally visible.
+ if (FD->isInlineDefinitionExternallyVisible())
+ return External;
+
+ // C99 inline semantics, where the symbol is not externally visible.
+ return GVA_C99Inline;
+ }
+
+ // C++0x [temp.explicit]p9:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
+ if (FD->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return GVA_C99Inline;
+
+ return GVA_CXXInline;
+}
+
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ // If this is a static data member, compute the kind of template
+ // specialization. Otherwise, this variable is not part of a
+ // template.
+ TemplateSpecializationKind TSK = TSK_Undeclared;
+ if (VD->isStaticDataMember())
+ TSK = VD->getTemplateSpecializationKind();
+
+ Linkage L = VD->getLinkage();
+ if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ VD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (TSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return GVA_StrongExternal;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ llvm_unreachable("Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ImplicitInstantiation:
+ return GVA_TemplateInstantiation;
+ }
+ }
+
+ return GVA_StrongExternal;
+}
+
+bool ASTContext::DeclMustBeEmitted(const Decl *D) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!VD->isFileVarDecl())
+ return false;
+ } else if (!isa<FunctionDecl>(D))
+ return false;
+
+ // Weak references don't produce any output by themselves.
+ if (D->hasAttr<WeakRefAttr>())
+ return false;
+
+ // Aliases and used decls are required.
+ if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+ return true;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Forward declarations aren't required.
+ if (!FD->isThisDeclarationADefinition())
+ return false;
+
+ // Constructors and destructors are required.
+ if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+ return true;
+
+ // The key function for a class is required.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *RD = MD->getParent();
+ if (MD->isOutOfLine() && RD->isDynamicClass()) {
+ const CXXMethodDecl *KeyFunc = getKeyFunction(RD);
+ if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
+ return true;
+ }
+ }
+
+ GVALinkage Linkage = GetGVALinkageForFunction(FD);
+
+ // static, static inline, always_inline, and extern inline functions can
+ // always be deferred. Normal inline functions can be deferred in C99/C++.
+ // Implicit template instantiations can also be deferred in C++.
+ if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
+ Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+ return false;
+ return true;
+ }
+
+ const VarDecl *VD = cast<VarDecl>(D);
+ assert(VD->isFileVarDecl() && "Expected file scoped var");
+
+ if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
+ return false;
+
+ // Structs that have non-trivial constructors or destructors are required.
+
+ // FIXME: Handle references.
+ if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (RD->hasDefinition() &&
+ (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
+ return true;
+ }
+ }
+
+ GVALinkage L = GetGVALinkageForVariable(VD);
+ if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
+ if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this)))
+ return false;
+ }
+
+ return true;
+}
+
+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/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
new file mode 100644
index 0000000..5bf8a38
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
@@ -0,0 +1,280 @@
+//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a diagnostic formatting hook for AST elements.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTDiagnostic.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+// Returns a desugared version of the QualType, and marks ShouldAKA as true
+// whenever we remove significant sugar from the type.
+static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
+ QualifierCollector QC;
+
+ while (true) {
+ const Type *Ty = QC.strip(QT);
+
+ // Don't aka just because we saw an elaborated type...
+ if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
+ QT = ET->desugar();
+ continue;
+ }
+ // ... or a paren type ...
+ if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
+ QT = PT->desugar();
+ continue;
+ }
+ // ...or a substituted template type parameter ...
+ if (const SubstTemplateTypeParmType *ST =
+ dyn_cast<SubstTemplateTypeParmType>(Ty)) {
+ QT = ST->desugar();
+ continue;
+ }
+ // ... or an auto type.
+ if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
+ if (!AT->isSugared())
+ break;
+ QT = AT->desugar();
+ continue;
+ }
+
+ // Don't desugar template specializations.
+ if (isa<TemplateSpecializationType>(Ty))
+ break;
+
+ // Don't desugar magic Objective-C types.
+ if (QualType(Ty,0) == Context.getObjCIdType() ||
+ QualType(Ty,0) == Context.getObjCClassType() ||
+ QualType(Ty,0) == Context.getObjCSelType() ||
+ QualType(Ty,0) == Context.getObjCProtoType())
+ break;
+
+ // Don't desugar va_list.
+ if (QualType(Ty,0) == Context.getBuiltinVaListType())
+ break;
+
+ // Otherwise, do a single-step desugar.
+ QualType Underlying;
+ bool IsSugar = false;
+ switch (Ty->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Base)
+#define TYPE(Class, Base) \
+case Type::Class: { \
+const Class##Type *CTy = cast<Class##Type>(Ty); \
+if (CTy->isSugared()) { \
+IsSugar = true; \
+Underlying = CTy->desugar(); \
+} \
+break; \
+}
+#include "clang/AST/TypeNodes.def"
+ }
+
+ // If it wasn't sugared, we're done.
+ if (!IsSugar)
+ break;
+
+ // If the desugared type is a vector type, we don't want to expand
+ // it, it will turn into an attribute mess. People want their "vec4".
+ if (isa<VectorType>(Underlying))
+ break;
+
+ // Don't desugar through the primary typedef of an anonymous type.
+ if (const TagType *UTT = Underlying->getAs<TagType>())
+ if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
+ if (UTT->getDecl()->getTypedefForAnonDecl() == QTT->getDecl())
+ break;
+
+ // Record that we actually looked through an opaque type here.
+ ShouldAKA = true;
+ QT = Underlying;
+ }
+
+ // If we have a pointer-like type, desugar the pointee as well.
+ // FIXME: Handle other pointer-like types.
+ if (const PointerType *Ty = QT->getAs<PointerType>()) {
+ QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
+ ShouldAKA));
+ } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
+ QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
+ ShouldAKA));
+ } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
+ QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
+ ShouldAKA));
+ }
+
+ return QC.apply(Context, QT);
+}
+
+/// \brief Convert the given type to a string suitable for printing as part of
+/// a diagnostic.
+///
+/// There are three main criteria when determining whether we should have an
+/// a.k.a. clause when pretty-printing a type:
+///
+/// 1) Some types provide very minimal sugar that doesn't impede the
+/// user's understanding --- for example, elaborated type
+/// specifiers. If this is all the sugar we see, we don't want an
+/// a.k.a. clause.
+/// 2) Some types are technically sugared but are much more familiar
+/// when seen in their sugared form --- for example, va_list,
+/// vector types, and the magic Objective C types. We don't
+/// want to desugar these, even if we do produce an a.k.a. clause.
+/// 3) Some types may have already been desugared previously in this diagnostic.
+/// if this is the case, doing another "aka" would just be clutter.
+///
+/// \param Context the context in which the type was allocated
+/// \param Ty the type to print
+static std::string
+ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs) {
+ // FIXME: Playing with std::string is really slow.
+ std::string S = Ty.getAsString(Context.PrintingPolicy);
+
+ // Check to see if we already desugared this type in this
+ // diagnostic. If so, don't do it again.
+ bool Repeated = false;
+ for (unsigned i = 0; i != NumPrevArgs; ++i) {
+ // TODO: Handle ak_declcontext case.
+ if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
+ void *Ptr = (void*)PrevArgs[i].second;
+ QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
+ if (PrevTy == Ty) {
+ Repeated = true;
+ break;
+ }
+ }
+ }
+
+ // Consider producing an a.k.a. clause if removing all the direct
+ // sugar gives us something "significantly different".
+ if (!Repeated) {
+ bool ShouldAKA = false;
+ QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
+ if (ShouldAKA) {
+ S = "'" + S + "' (aka '";
+ S += DesugaredTy.getAsString(Context.PrintingPolicy);
+ S += "')";
+ return S;
+ }
+ }
+
+ S = "'" + S + "'";
+ return S;
+}
+
+void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
+ intptr_t Val,
+ const char *Modifier,
+ unsigned ModLen,
+ const char *Argument,
+ unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie) {
+ ASTContext &Context = *static_cast<ASTContext*>(Cookie);
+
+ std::string S;
+ bool NeedQuotes = true;
+
+ switch (Kind) {
+ default: assert(0 && "unknown ArgumentKind");
+ case Diagnostic::ak_qualtype: {
+ assert(ModLen == 0 && ArgLen == 0 &&
+ "Invalid modifier for QualType argument");
+
+ QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
+ S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
+ NeedQuotes = false;
+ break;
+ }
+ case Diagnostic::ak_declarationname: {
+ DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
+ S = N.getAsString();
+
+ if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
+ S = '+' + S;
+ else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12)
+ && ArgLen==0)
+ S = '-' + S;
+ else
+ assert(ModLen == 0 && ArgLen == 0 &&
+ "Invalid modifier for DeclarationName argument");
+ break;
+ }
+ case Diagnostic::ak_nameddecl: {
+ bool Qualified;
+ if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
+ Qualified = true;
+ else {
+ assert(ModLen == 0 && ArgLen == 0 &&
+ "Invalid modifier for NamedDecl* argument");
+ Qualified = false;
+ }
+ reinterpret_cast<NamedDecl*>(Val)->
+ getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
+ break;
+ }
+ case Diagnostic::ak_nestednamespec: {
+ llvm::raw_string_ostream OS(S);
+ reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
+ Context.PrintingPolicy);
+ NeedQuotes = false;
+ break;
+ }
+ case Diagnostic::ak_declcontext: {
+ DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
+ assert(DC && "Should never have a null declaration context");
+
+ if (DC->isTranslationUnit()) {
+ // FIXME: Get these strings from some localized place
+ if (Context.getLangOptions().CPlusPlus)
+ S = "the global namespace";
+ else
+ S = "the global scope";
+ } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
+ S = ConvertTypeToDiagnosticString(Context,
+ Context.getTypeDeclType(Type),
+ PrevArgs, NumPrevArgs);
+ } else {
+ // FIXME: Get these strings from some localized place
+ NamedDecl *ND = cast<NamedDecl>(DC);
+ if (isa<NamespaceDecl>(ND))
+ S += "namespace ";
+ else if (isa<ObjCMethodDecl>(ND))
+ S += "method ";
+ else if (isa<FunctionDecl>(ND))
+ S += "function ";
+
+ S += "'";
+ ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
+ S += "'";
+ }
+ NeedQuotes = false;
+ break;
+ }
+ }
+
+ if (NeedQuotes)
+ Output.push_back('\'');
+
+ Output.append(S.begin(), S.end());
+
+ if (NeedQuotes)
+ Output.push_back('\'');
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
new file mode 100644
index 0000000..65c0a3b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -0,0 +1,4321 @@
+//===--- ASTImporter.cpp - Importing ASTs from other Contexts ---*- 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 ASTImporter class which imports AST nodes from one
+// context into another context.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTImporter.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <deque>
+
+using namespace clang;
+
+namespace {
+ class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
+ public DeclVisitor<ASTNodeImporter, Decl *>,
+ public StmtVisitor<ASTNodeImporter, Stmt *> {
+ ASTImporter &Importer;
+
+ public:
+ explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { }
+
+ using TypeVisitor<ASTNodeImporter, QualType>::Visit;
+ using DeclVisitor<ASTNodeImporter, Decl *>::Visit;
+ using StmtVisitor<ASTNodeImporter, Stmt *>::Visit;
+
+ // Importing types
+ 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(const VectorType *T);
+ QualType VisitExtVectorType(const ExtVectorType *T);
+ QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T);
+ QualType VisitFunctionProtoType(const FunctionProtoType *T);
+ // FIXME: UnresolvedUsingType
+ QualType VisitTypedefType(const TypedefType *T);
+ QualType VisitTypeOfExprType(const TypeOfExprType *T);
+ // FIXME: DependentTypeOfExprType
+ QualType VisitTypeOfType(const TypeOfType *T);
+ QualType VisitDecltypeType(const DecltypeType *T);
+ QualType VisitAutoType(const AutoType *T);
+ // FIXME: DependentDecltypeType
+ QualType VisitRecordType(const RecordType *T);
+ QualType VisitEnumType(const EnumType *T);
+ // FIXME: TemplateTypeParmType
+ // FIXME: SubstTemplateTypeParmType
+ QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
+ QualType VisitElaboratedType(const ElaboratedType *T);
+ // FIXME: DependentNameType
+ // FIXME: DependentTemplateSpecializationType
+ QualType VisitObjCInterfaceType(const ObjCInterfaceType *T);
+ QualType VisitObjCObjectType(const ObjCObjectType *T);
+ QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+
+ // Importing declarations
+ bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
+ DeclContext *&LexicalDC, DeclarationName &Name,
+ SourceLocation &Loc);
+ void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To);
+ 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<TemplateArgument> &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);
+ Decl *VisitEnumDecl(EnumDecl *D);
+ Decl *VisitRecordDecl(RecordDecl *D);
+ Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+ Decl *VisitFunctionDecl(FunctionDecl *D);
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
+ Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ 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);
+ Decl *VisitParmVarDecl(ParmVarDecl *D);
+ Decl *VisitObjCMethodDecl(ObjCMethodDecl *D);
+ 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);
+
+ // Importing expressions
+ Expr *VisitExpr(Expr *E);
+ Expr *VisitDeclRefExpr(DeclRefExpr *E);
+ Expr *VisitIntegerLiteral(IntegerLiteral *E);
+ Expr *VisitCharacterLiteral(CharacterLiteral *E);
+ Expr *VisitParenExpr(ParenExpr *E);
+ Expr *VisitUnaryOperator(UnaryOperator *E);
+ Expr *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ Expr *VisitBinaryOperator(BinaryOperator *E);
+ Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
+ Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
+ Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+ };
+}
+
+//----------------------------------------------------------------------------
+// Structural Equivalence
+//----------------------------------------------------------------------------
+
+namespace {
+ struct StructuralEquivalenceContext {
+ /// \brief AST contexts for which we are checking structural equivalence.
+ ASTContext &C1, &C2;
+
+ /// \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.
+ llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
+
+ /// \brief Queue of declarations in the first context whose equivalence
+ /// with a declaration in the second context still needs to be verified.
+ std::deque<Decl *> DeclsToCheck;
+
+ /// \brief Declaration (from, to) pairs that are known not to be equivalent
+ /// (which we have already complained about).
+ llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls;
+
+ /// \brief Whether we're being strict about the spelling of types when
+ /// unifying two types.
+ bool StrictTypeSpelling;
+
+ StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
+ llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
+ bool StrictTypeSpelling = false)
+ : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
+ StrictTypeSpelling(StrictTypeSpelling) { }
+
+ /// \brief Determine whether the two declarations are structurally
+ /// equivalent.
+ bool IsStructurallyEquivalent(Decl *D1, Decl *D2);
+
+ /// \brief Determine whether the two types are structurally equivalent.
+ bool IsStructurallyEquivalent(QualType T1, QualType T2);
+
+ private:
+ /// \brief Finish checking all of the structural equivalences.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool Finish();
+
+ public:
+ DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
+ return C1.getDiagnostics().Report(Loc, DiagID);
+ }
+
+ DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
+ return C2.getDiagnostics().Report(Loc, DiagID);
+ }
+ };
+}
+
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ QualType T1, QualType T2);
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ Decl *D1, Decl *D2);
+
+/// \brief Determine if two APInts have the same value, after zero-extending
+/// one of them (if needed!) to ensure that the bit-widths match.
+static bool IsSameValue(const llvm::APInt &I1, const llvm::APInt &I2) {
+ if (I1.getBitWidth() == I2.getBitWidth())
+ return I1 == I2;
+
+ if (I1.getBitWidth() > I2.getBitWidth())
+ return I1 == I2.zext(I1.getBitWidth());
+
+ return I1.zext(I2.getBitWidth()) == I2;
+}
+
+/// \brief Determine if two APSInts have the same value, zero- or sign-extending
+/// as needed.
+static bool IsSameValue(const llvm::APSInt &I1, const llvm::APSInt &I2) {
+ if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
+ return I1 == I2;
+
+ // Check for a bit-width mismatch.
+ if (I1.getBitWidth() > I2.getBitWidth())
+ return IsSameValue(I1, I2.extend(I1.getBitWidth()));
+ else if (I2.getBitWidth() > I1.getBitWidth())
+ return IsSameValue(I1.extend(I2.getBitWidth()), I2);
+
+ // We have a signedness mismatch. Turn the signed value into an unsigned
+ // value.
+ if (I1.isSigned()) {
+ if (I1.isNegative())
+ return false;
+
+ return llvm::APSInt(I1, true) == I2;
+ }
+
+ if (I2.isNegative())
+ return false;
+
+ return I1 == llvm::APSInt(I2, true);
+}
+
+/// \brief Determine structural equivalence of two expressions.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ Expr *E1, Expr *E2) {
+ if (!E1 || !E2)
+ return E1 == E2;
+
+ // FIXME: Actually perform a structural comparison!
+ return true;
+}
+
+/// \brief Determine whether two identifiers are equivalent.
+static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
+ const IdentifierInfo *Name2) {
+ if (!Name1 || !Name2)
+ return Name1 == Name2;
+
+ return Name1->getName() == Name2->getName();
+}
+
+/// \brief Determine whether two nested-name-specifiers are equivalent.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ NestedNameSpecifier *NNS1,
+ NestedNameSpecifier *NNS2) {
+ // FIXME: Implement!
+ return true;
+}
+
+/// \brief Determine whether two template arguments are equivalent.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ const TemplateArgument &Arg1,
+ const TemplateArgument &Arg2) {
+ 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;
+}
+
+/// \brief Determine structural equivalence for the common part of array
+/// types.
+static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ const ArrayType *Array1,
+ const ArrayType *Array2) {
+ if (!IsStructurallyEquivalent(Context,
+ Array1->getElementType(),
+ Array2->getElementType()))
+ return false;
+ if (Array1->getSizeModifier() != Array2->getSizeModifier())
+ return false;
+ if (Array1->getIndexTypeQualifiers() != Array2->getIndexTypeQualifiers())
+ return false;
+
+ return true;
+}
+
+/// \brief Determine structural equivalence of two types.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ QualType T1, QualType T2) {
+ if (T1.isNull() || T2.isNull())
+ return T1.isNull() && T2.isNull();
+
+ if (!Context.StrictTypeSpelling) {
+ // We aren't being strict about token-to-token equivalence of types,
+ // so map down to the canonical type.
+ T1 = Context.C1.getCanonicalType(T1);
+ T2 = Context.C2.getCanonicalType(T2);
+ }
+
+ if (T1.getQualifiers() != T2.getQualifiers())
+ return false;
+
+ Type::TypeClass TC = T1->getTypeClass();
+
+ if (T1->getTypeClass() != T2->getTypeClass()) {
+ // Compare function types with prototypes vs. without prototypes as if
+ // both did not have prototypes.
+ if (T1->getTypeClass() == Type::FunctionProto &&
+ T2->getTypeClass() == Type::FunctionNoProto)
+ TC = Type::FunctionNoProto;
+ else if (T1->getTypeClass() == Type::FunctionNoProto &&
+ T2->getTypeClass() == Type::FunctionProto)
+ TC = Type::FunctionNoProto;
+ else
+ return false;
+ }
+
+ switch (TC) {
+ case Type::Builtin:
+ // FIXME: Deal with Char_S/Char_U.
+ if (cast<BuiltinType>(T1)->getKind() != cast<BuiltinType>(T2)->getKind())
+ return false;
+ break;
+
+ case Type::Complex:
+ if (!IsStructurallyEquivalent(Context,
+ cast<ComplexType>(T1)->getElementType(),
+ cast<ComplexType>(T2)->getElementType()))
+ return false;
+ break;
+
+ case Type::Pointer:
+ if (!IsStructurallyEquivalent(Context,
+ cast<PointerType>(T1)->getPointeeType(),
+ cast<PointerType>(T2)->getPointeeType()))
+ return false;
+ break;
+
+ case Type::BlockPointer:
+ if (!IsStructurallyEquivalent(Context,
+ cast<BlockPointerType>(T1)->getPointeeType(),
+ cast<BlockPointerType>(T2)->getPointeeType()))
+ return false;
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference: {
+ const ReferenceType *Ref1 = cast<ReferenceType>(T1);
+ const ReferenceType *Ref2 = cast<ReferenceType>(T2);
+ if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
+ return false;
+ if (Ref1->isInnerRef() != Ref2->isInnerRef())
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ Ref1->getPointeeTypeAsWritten(),
+ Ref2->getPointeeTypeAsWritten()))
+ return false;
+ break;
+ }
+
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtr1 = cast<MemberPointerType>(T1);
+ const MemberPointerType *MemPtr2 = cast<MemberPointerType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ MemPtr1->getPointeeType(),
+ MemPtr2->getPointeeType()))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ QualType(MemPtr1->getClass(), 0),
+ QualType(MemPtr2->getClass(), 0)))
+ return false;
+ break;
+ }
+
+ case Type::ConstantArray: {
+ const ConstantArrayType *Array1 = cast<ConstantArrayType>(T1);
+ const ConstantArrayType *Array2 = cast<ConstantArrayType>(T2);
+ if (!IsSameValue(Array1->getSize(), Array2->getSize()))
+ return false;
+
+ if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
+ return false;
+ break;
+ }
+
+ case Type::IncompleteArray:
+ if (!IsArrayStructurallyEquivalent(Context,
+ cast<ArrayType>(T1),
+ cast<ArrayType>(T2)))
+ return false;
+ break;
+
+ case Type::VariableArray: {
+ const VariableArrayType *Array1 = cast<VariableArrayType>(T1);
+ const VariableArrayType *Array2 = cast<VariableArrayType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Array1->getSizeExpr(), Array2->getSizeExpr()))
+ return false;
+
+ if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
+ return false;
+
+ break;
+ }
+
+ case Type::DependentSizedArray: {
+ const DependentSizedArrayType *Array1 = cast<DependentSizedArrayType>(T1);
+ const DependentSizedArrayType *Array2 = cast<DependentSizedArrayType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Array1->getSizeExpr(), Array2->getSizeExpr()))
+ return false;
+
+ if (!IsArrayStructurallyEquivalent(Context, Array1, Array2))
+ return false;
+
+ break;
+ }
+
+ case Type::DependentSizedExtVector: {
+ const DependentSizedExtVectorType *Vec1
+ = cast<DependentSizedExtVectorType>(T1);
+ const DependentSizedExtVectorType *Vec2
+ = cast<DependentSizedExtVectorType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Vec1->getSizeExpr(), Vec2->getSizeExpr()))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ Vec1->getElementType(),
+ Vec2->getElementType()))
+ return false;
+ break;
+ }
+
+ case Type::Vector:
+ case Type::ExtVector: {
+ const VectorType *Vec1 = cast<VectorType>(T1);
+ const VectorType *Vec2 = cast<VectorType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Vec1->getElementType(),
+ Vec2->getElementType()))
+ return false;
+ if (Vec1->getNumElements() != Vec2->getNumElements())
+ return false;
+ if (Vec1->getVectorKind() != Vec2->getVectorKind())
+ return false;
+ break;
+ }
+
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1);
+ const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2);
+ if (Proto1->getNumArgs() != Proto2->getNumArgs())
+ return false;
+ for (unsigned I = 0, N = Proto1->getNumArgs(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Proto1->getArgType(I),
+ Proto2->getArgType(I)))
+ return false;
+ }
+ if (Proto1->isVariadic() != Proto2->isVariadic())
+ return false;
+ if (Proto1->hasExceptionSpec() != Proto2->hasExceptionSpec())
+ return false;
+ if (Proto1->hasAnyExceptionSpec() != Proto2->hasAnyExceptionSpec())
+ return false;
+ if (Proto1->getNumExceptions() != Proto2->getNumExceptions())
+ return false;
+ for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Proto1->getExceptionType(I),
+ Proto2->getExceptionType(I)))
+ return false;
+ }
+ if (Proto1->getTypeQuals() != Proto2->getTypeQuals())
+ return false;
+
+ // Fall through to check the bits common with FunctionNoProtoType.
+ }
+
+ case Type::FunctionNoProto: {
+ const FunctionType *Function1 = cast<FunctionType>(T1);
+ const FunctionType *Function2 = cast<FunctionType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Function1->getResultType(),
+ Function2->getResultType()))
+ return false;
+ if (Function1->getExtInfo() != Function2->getExtInfo())
+ return false;
+ break;
+ }
+
+ case Type::UnresolvedUsing:
+ if (!IsStructurallyEquivalent(Context,
+ cast<UnresolvedUsingType>(T1)->getDecl(),
+ cast<UnresolvedUsingType>(T2)->getDecl()))
+ return false;
+
+ break;
+
+ case Type::Attributed:
+ if (!IsStructurallyEquivalent(Context,
+ cast<AttributedType>(T1)->getModifiedType(),
+ cast<AttributedType>(T2)->getModifiedType()))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ cast<AttributedType>(T1)->getEquivalentType(),
+ cast<AttributedType>(T2)->getEquivalentType()))
+ return false;
+ break;
+
+ case Type::Paren:
+ if (!IsStructurallyEquivalent(Context,
+ cast<ParenType>(T1)->getInnerType(),
+ cast<ParenType>(T2)->getInnerType()))
+ return false;
+ break;
+
+ case Type::Typedef:
+ if (!IsStructurallyEquivalent(Context,
+ cast<TypedefType>(T1)->getDecl(),
+ cast<TypedefType>(T2)->getDecl()))
+ return false;
+ break;
+
+ case Type::TypeOfExpr:
+ if (!IsStructurallyEquivalent(Context,
+ cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
+ cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
+ return false;
+ break;
+
+ case Type::TypeOf:
+ if (!IsStructurallyEquivalent(Context,
+ cast<TypeOfType>(T1)->getUnderlyingType(),
+ cast<TypeOfType>(T2)->getUnderlyingType()))
+ return false;
+ break;
+
+ case Type::Decltype:
+ if (!IsStructurallyEquivalent(Context,
+ cast<DecltypeType>(T1)->getUnderlyingExpr(),
+ cast<DecltypeType>(T2)->getUnderlyingExpr()))
+ return false;
+ break;
+
+ case Type::Auto:
+ if (!IsStructurallyEquivalent(Context,
+ cast<AutoType>(T1)->getDeducedType(),
+ cast<AutoType>(T2)->getDeducedType()))
+ return false;
+ break;
+
+ case Type::Record:
+ case Type::Enum:
+ if (!IsStructurallyEquivalent(Context,
+ cast<TagType>(T1)->getDecl(),
+ cast<TagType>(T2)->getDecl()))
+ return false;
+ break;
+
+ case Type::TemplateTypeParm: {
+ const TemplateTypeParmType *Parm1 = cast<TemplateTypeParmType>(T1);
+ const TemplateTypeParmType *Parm2 = cast<TemplateTypeParmType>(T2);
+ if (Parm1->getDepth() != Parm2->getDepth())
+ return false;
+ if (Parm1->getIndex() != Parm2->getIndex())
+ return false;
+ if (Parm1->isParameterPack() != Parm2->isParameterPack())
+ return false;
+
+ // Names of template type parameters are never significant.
+ break;
+ }
+
+ case Type::SubstTemplateTypeParm: {
+ const SubstTemplateTypeParmType *Subst1
+ = cast<SubstTemplateTypeParmType>(T1);
+ const SubstTemplateTypeParmType *Subst2
+ = cast<SubstTemplateTypeParmType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ QualType(Subst1->getReplacedParameter(), 0),
+ QualType(Subst2->getReplacedParameter(), 0)))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ Subst1->getReplacementType(),
+ Subst2->getReplacementType()))
+ return false;
+ break;
+ }
+
+ case Type::SubstTemplateTypeParmPack: {
+ const SubstTemplateTypeParmPackType *Subst1
+ = cast<SubstTemplateTypeParmPackType>(T1);
+ const SubstTemplateTypeParmPackType *Subst2
+ = cast<SubstTemplateTypeParmPackType>(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<TemplateSpecializationType>(T1);
+ const TemplateSpecializationType *Spec2
+ = cast<TemplateSpecializationType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getTemplateName(),
+ Spec2->getTemplateName()))
+ return false;
+ if (Spec1->getNumArgs() != Spec2->getNumArgs())
+ return false;
+ for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getArg(I), Spec2->getArg(I)))
+ return false;
+ }
+ break;
+ }
+
+ case Type::Elaborated: {
+ const ElaboratedType *Elab1 = cast<ElaboratedType>(T1);
+ const ElaboratedType *Elab2 = cast<ElaboratedType>(T2);
+ // CHECKME: what if a keyword is ETK_None or ETK_typename ?
+ if (Elab1->getKeyword() != Elab2->getKeyword())
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ Elab1->getQualifier(),
+ Elab2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Context,
+ Elab1->getNamedType(),
+ Elab2->getNamedType()))
+ return false;
+ break;
+ }
+
+ case Type::InjectedClassName: {
+ const InjectedClassNameType *Inj1 = cast<InjectedClassNameType>(T1);
+ const InjectedClassNameType *Inj2 = cast<InjectedClassNameType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Inj1->getInjectedSpecializationType(),
+ Inj2->getInjectedSpecializationType()))
+ return false;
+ break;
+ }
+
+ case Type::DependentName: {
+ const DependentNameType *Typename1 = cast<DependentNameType>(T1);
+ const DependentNameType *Typename2 = cast<DependentNameType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Typename1->getQualifier(),
+ Typename2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Typename1->getIdentifier(),
+ Typename2->getIdentifier()))
+ return false;
+
+ break;
+ }
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *Spec1 =
+ cast<DependentTemplateSpecializationType>(T1);
+ const DependentTemplateSpecializationType *Spec2 =
+ cast<DependentTemplateSpecializationType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getQualifier(),
+ Spec2->getQualifier()))
+ return false;
+ if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
+ Spec2->getIdentifier()))
+ return false;
+ if (Spec1->getNumArgs() != Spec2->getNumArgs())
+ return false;
+ for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Spec1->getArg(I), Spec2->getArg(I)))
+ return false;
+ }
+ break;
+ }
+
+ case Type::PackExpansion:
+ if (!IsStructurallyEquivalent(Context,
+ cast<PackExpansionType>(T1)->getPattern(),
+ cast<PackExpansionType>(T2)->getPattern()))
+ return false;
+ break;
+
+ case Type::ObjCInterface: {
+ const ObjCInterfaceType *Iface1 = cast<ObjCInterfaceType>(T1);
+ const ObjCInterfaceType *Iface2 = cast<ObjCInterfaceType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Iface1->getDecl(), Iface2->getDecl()))
+ return false;
+ break;
+ }
+
+ case Type::ObjCObject: {
+ const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1);
+ const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Obj1->getBaseType(),
+ Obj2->getBaseType()))
+ return false;
+ if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
+ return false;
+ for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Obj1->getProtocol(I),
+ Obj2->getProtocol(I)))
+ return false;
+ }
+ break;
+ }
+
+ case Type::ObjCObjectPointer: {
+ const ObjCObjectPointerType *Ptr1 = cast<ObjCObjectPointerType>(T1);
+ const ObjCObjectPointerType *Ptr2 = cast<ObjCObjectPointerType>(T2);
+ if (!IsStructurallyEquivalent(Context,
+ Ptr1->getPointeeType(),
+ Ptr2->getPointeeType()))
+ return false;
+ break;
+ }
+
+ } // end switch
+
+ return true;
+}
+
+/// \brief Determine structural equivalence of two records.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ RecordDecl *D1, RecordDecl *D2) {
+ if (D1->isUnion() != D2->isUnion()) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
+ << D1->getDeclName() << (unsigned)D1->getTagKind();
+ 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<ClassTemplateSpecializationDecl>(D1);
+ ClassTemplateSpecializationDecl *Spec2
+ = dyn_cast<ClassTemplateSpecializationDecl>(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();
+ D2 = D2->getDefinition();
+ if (!D1 || !D2)
+ return true;
+
+ if (CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
+ if (CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
+ if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
+ << D2CXX->getNumBases();
+ Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
+ << D1CXX->getNumBases();
+ return false;
+ }
+
+ // Check the base classes.
+ for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
+ BaseEnd1 = D1CXX->bases_end(),
+ Base2 = D2CXX->bases_begin();
+ Base1 != BaseEnd1;
+ ++Base1, ++Base2) {
+ if (!IsStructurallyEquivalent(Context,
+ Base1->getType(), Base2->getType())) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Base2->getSourceRange().getBegin(), diag::note_odr_base)
+ << Base2->getType()
+ << Base2->getSourceRange();
+ Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ << Base1->getType()
+ << Base1->getSourceRange();
+ return false;
+ }
+
+ // Check virtual vs. non-virtual inheritance mismatch.
+ if (Base1->isVirtual() != Base2->isVirtual()) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Base2->getSourceRange().getBegin(),
+ diag::note_odr_virtual_base)
+ << Base2->isVirtual() << Base2->getSourceRange();
+ Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ << Base1->isVirtual()
+ << Base1->getSourceRange();
+ return false;
+ }
+ }
+ } else if (D1CXX->getNumBases() > 0) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
+ Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ << Base1->getType()
+ << Base1->getSourceRange();
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
+ return false;
+ }
+ }
+
+ // Check the fields for consistency.
+ CXXRecordDecl::field_iterator Field2 = D2->field_begin(),
+ Field2End = D2->field_end();
+ for (CXXRecordDecl::field_iterator Field1 = D1->field_begin(),
+ Field1End = D1->field_end();
+ Field1 != Field1End;
+ ++Field1, ++Field2) {
+ if (Field2 == Field2End) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field)
+ << Field1->getDeclName() << Field1->getType();
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
+ return false;
+ }
+
+ if (!IsStructurallyEquivalent(Context,
+ Field1->getType(), Field2->getType())) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field)
+ << Field2->getDeclName() << Field2->getType();
+ Context.Diag1(Field1->getLocation(), diag::note_odr_field)
+ << Field1->getDeclName() << Field1->getType();
+ return false;
+ }
+
+ if (Field1->isBitField() != Field2->isBitField()) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ if (Field1->isBitField()) {
+ llvm::APSInt Bits;
+ Field1->getBitWidth()->isIntegerConstantExpr(Bits, Context.C1);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType()
+ << Bits.toString(10, false);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_not_bit_field)
+ << Field2->getDeclName();
+ } else {
+ llvm::APSInt Bits;
+ Field2->getBitWidth()->isIntegerConstantExpr(Bits, Context.C2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType()
+ << Bits.toString(10, false);
+ Context.Diag1(Field1->getLocation(),
+ diag::note_odr_not_bit_field)
+ << Field1->getDeclName();
+ }
+ return false;
+ }
+
+ if (Field1->isBitField()) {
+ // Make sure that the bit-fields are the same length.
+ llvm::APSInt Bits1, Bits2;
+ if (!Field1->getBitWidth()->isIntegerConstantExpr(Bits1, Context.C1))
+ return false;
+ if (!Field2->getBitWidth()->isIntegerConstantExpr(Bits2, Context.C2))
+ return false;
+
+ if (!IsSameValue(Bits1, Bits2)) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field)
+ << Field2->getDeclName() << Field2->getType()
+ << Bits2.toString(10, false);
+ Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field)
+ << Field1->getDeclName() << Field1->getType()
+ << Bits1.toString(10, false);
+ return false;
+ }
+ }
+ }
+
+ if (Field2 != Field2End) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(Field2->getLocation(), diag::note_odr_field)
+ << Field2->getDeclName() << Field2->getType();
+ Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Determine structural equivalence of two enums.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ EnumDecl *D1, EnumDecl *D2) {
+ EnumDecl::enumerator_iterator EC2 = D2->enumerator_begin(),
+ EC2End = D2->enumerator_end();
+ for (EnumDecl::enumerator_iterator EC1 = D1->enumerator_begin(),
+ EC1End = D1->enumerator_end();
+ EC1 != EC1End; ++EC1, ++EC2) {
+ if (EC2 == EC2End) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
+ << EC1->getDeclName()
+ << EC1->getInitVal().toString(10);
+ Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
+ return false;
+ }
+
+ llvm::APSInt Val1 = EC1->getInitVal();
+ llvm::APSInt Val2 = EC2->getInitVal();
+ if (!IsSameValue(Val1, Val2) ||
+ !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
+ << EC2->getDeclName()
+ << EC2->getInitVal().toString(10);
+ Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
+ << EC1->getDeclName()
+ << EC1->getInitVal().toString(10);
+ return false;
+ }
+ }
+
+ if (EC2 != EC2End) {
+ Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
+ << Context.C2.getTypeDeclType(D2);
+ Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
+ << EC2->getDeclName()
+ << EC2->getInitVal().toString(10);
+ Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
+ return false;
+ }
+
+ 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) {
+ // FIXME: Check for known structural equivalences via a callback of some sort.
+
+ // Check whether we already know that these two declarations are not
+ // structurally equivalent.
+ if (Context.NonEquivalentDecls.count(std::make_pair(D1->getCanonicalDecl(),
+ D2->getCanonicalDecl())))
+ return false;
+
+ // Determine whether we've already produced a tentative equivalence for D1.
+ Decl *&EquivToD1 = Context.TentativeEquivalences[D1->getCanonicalDecl()];
+ if (EquivToD1)
+ return EquivToD1 == D2->getCanonicalDecl();
+
+ // Produce a tentative equivalence D1 <-> D2, which will be checked later.
+ EquivToD1 = D2->getCanonicalDecl();
+ Context.DeclsToCheck.push_back(D1->getCanonicalDecl());
+ return true;
+}
+
+bool StructuralEquivalenceContext::IsStructurallyEquivalent(Decl *D1,
+ Decl *D2) {
+ if (!::IsStructurallyEquivalent(*this, D1, D2))
+ return false;
+
+ return !Finish();
+}
+
+bool StructuralEquivalenceContext::IsStructurallyEquivalent(QualType T1,
+ QualType T2) {
+ if (!::IsStructurallyEquivalent(*this, T1, T2))
+ return false;
+
+ return !Finish();
+}
+
+bool StructuralEquivalenceContext::Finish() {
+ while (!DeclsToCheck.empty()) {
+ // Check the next declaration.
+ Decl *D1 = DeclsToCheck.front();
+ DeclsToCheck.pop_front();
+
+ Decl *D2 = TentativeEquivalences[D1];
+ assert(D2 && "Unrecorded tentative equivalence?");
+
+ bool Equivalent = true;
+
+ // FIXME: Switch on all declaration kinds. For now, we're just going to
+ // check the obvious ones.
+ if (RecordDecl *Record1 = dyn_cast<RecordDecl>(D1)) {
+ if (RecordDecl *Record2 = dyn_cast<RecordDecl>(D2)) {
+ // Check for equivalent structure names.
+ IdentifierInfo *Name1 = Record1->getIdentifier();
+ if (!Name1 && Record1->getTypedefForAnonDecl())
+ Name1 = Record1->getTypedefForAnonDecl()->getIdentifier();
+ IdentifierInfo *Name2 = Record2->getIdentifier();
+ if (!Name2 && Record2->getTypedefForAnonDecl())
+ Name2 = Record2->getTypedefForAnonDecl()->getIdentifier();
+ if (!::IsStructurallyEquivalent(Name1, Name2) ||
+ !::IsStructurallyEquivalent(*this, Record1, Record2))
+ Equivalent = false;
+ } else {
+ // Record/non-record mismatch.
+ Equivalent = false;
+ }
+ } else if (EnumDecl *Enum1 = dyn_cast<EnumDecl>(D1)) {
+ if (EnumDecl *Enum2 = dyn_cast<EnumDecl>(D2)) {
+ // Check for equivalent enum names.
+ IdentifierInfo *Name1 = Enum1->getIdentifier();
+ if (!Name1 && Enum1->getTypedefForAnonDecl())
+ Name1 = Enum1->getTypedefForAnonDecl()->getIdentifier();
+ IdentifierInfo *Name2 = Enum2->getIdentifier();
+ if (!Name2 && Enum2->getTypedefForAnonDecl())
+ Name2 = Enum2->getTypedefForAnonDecl()->getIdentifier();
+ if (!::IsStructurallyEquivalent(Name1, Name2) ||
+ !::IsStructurallyEquivalent(*this, Enum1, Enum2))
+ Equivalent = false;
+ } else {
+ // Enum/non-enum mismatch
+ Equivalent = false;
+ }
+ } else if (TypedefDecl *Typedef1 = dyn_cast<TypedefDecl>(D1)) {
+ if (TypedefDecl *Typedef2 = dyn_cast<TypedefDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(),
+ Typedef2->getIdentifier()) ||
+ !::IsStructurallyEquivalent(*this,
+ Typedef1->getUnderlyingType(),
+ Typedef2->getUnderlyingType()))
+ Equivalent = false;
+ } else {
+ // Typedef/non-typedef mismatch.
+ Equivalent = false;
+ }
+ } else if (ClassTemplateDecl *ClassTemplate1
+ = dyn_cast<ClassTemplateDecl>(D1)) {
+ if (ClassTemplateDecl *ClassTemplate2 = dyn_cast<ClassTemplateDecl>(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<TemplateTypeParmDecl>(D1)) {
+ if (TemplateTypeParmDecl *TTP2 = dyn_cast<TemplateTypeParmDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, TTP1, TTP2))
+ Equivalent = false;
+ } else {
+ // Kind mismatch.
+ Equivalent = false;
+ }
+ } else if (NonTypeTemplateParmDecl *NTTP1
+ = dyn_cast<NonTypeTemplateParmDecl>(D1)) {
+ if (NonTypeTemplateParmDecl *NTTP2
+ = dyn_cast<NonTypeTemplateParmDecl>(D2)) {
+ if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2))
+ Equivalent = false;
+ } else {
+ // Kind mismatch.
+ Equivalent = false;
+ }
+ } else if (TemplateTemplateParmDecl *TTP1
+ = dyn_cast<TemplateTemplateParmDecl>(D1)) {
+ if (TemplateTemplateParmDecl *TTP2
+ = dyn_cast<TemplateTemplateParmDecl>(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).
+ NonEquivalentDecls.insert(std::make_pair(D1->getCanonicalDecl(),
+ D2->getCanonicalDecl()));
+ return true;
+ }
+ // FIXME: Check other declaration kinds!
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+// Import Types
+//----------------------------------------------------------------------------
+
+QualType ASTNodeImporter::VisitType(const Type *T) {
+ Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
+ << T->getTypeClassName();
+ return QualType();
+}
+
+QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
+ switch (T->getKind()) {
+ case BuiltinType::Void: return Importer.getToContext().VoidTy;
+ case BuiltinType::Bool: return Importer.getToContext().BoolTy;
+
+ case BuiltinType::Char_U:
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
+ // 'unsigned char' instead.
+ if (Importer.getToContext().getLangOptions().CharIsSigned)
+ return Importer.getToContext().UnsignedCharTy;
+
+ return Importer.getToContext().CharTy;
+
+ case BuiltinType::UChar: return Importer.getToContext().UnsignedCharTy;
+
+ case BuiltinType::Char16:
+ // FIXME: Make sure that the "to" context supports C++!
+ return Importer.getToContext().Char16Ty;
+
+ case BuiltinType::Char32:
+ // FIXME: Make sure that the "to" context supports C++!
+ return Importer.getToContext().Char32Ty;
+
+ case BuiltinType::UShort: return Importer.getToContext().UnsignedShortTy;
+ case BuiltinType::UInt: return Importer.getToContext().UnsignedIntTy;
+ case BuiltinType::ULong: return Importer.getToContext().UnsignedLongTy;
+ case BuiltinType::ULongLong:
+ return Importer.getToContext().UnsignedLongLongTy;
+ case BuiltinType::UInt128: return Importer.getToContext().UnsignedInt128Ty;
+
+ case BuiltinType::Char_S:
+ // The context we're importing from has an unsigned 'char'. If we're
+ // importing into a context with a signed 'char', translate to
+ // 'unsigned char' instead.
+ if (!Importer.getToContext().getLangOptions().CharIsSigned)
+ return Importer.getToContext().SignedCharTy;
+
+ return Importer.getToContext().CharTy;
+
+ case BuiltinType::SChar: return Importer.getToContext().SignedCharTy;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ // FIXME: If not in C++, shall we translate to the C equivalent of
+ // wchar_t?
+ return Importer.getToContext().WCharTy;
+
+ case BuiltinType::Short : return Importer.getToContext().ShortTy;
+ case BuiltinType::Int : return Importer.getToContext().IntTy;
+ case BuiltinType::Long : return Importer.getToContext().LongTy;
+ case BuiltinType::LongLong : return Importer.getToContext().LongLongTy;
+ case BuiltinType::Int128 : return Importer.getToContext().Int128Ty;
+ case BuiltinType::Float: return Importer.getToContext().FloatTy;
+ case BuiltinType::Double: return Importer.getToContext().DoubleTy;
+ case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy;
+
+ case BuiltinType::NullPtr:
+ // FIXME: Make sure that the "to" context supports C++0x!
+ return Importer.getToContext().NullPtrTy;
+
+ case BuiltinType::Overload: return Importer.getToContext().OverloadTy;
+ case BuiltinType::Dependent: return Importer.getToContext().DependentTy;
+
+ case BuiltinType::ObjCId:
+ // FIXME: Make sure that the "to" context supports Objective-C!
+ return Importer.getToContext().ObjCBuiltinIdTy;
+
+ case BuiltinType::ObjCClass:
+ return Importer.getToContext().ObjCBuiltinClassTy;
+
+ case BuiltinType::ObjCSel:
+ return Importer.getToContext().ObjCBuiltinSelTy;
+ }
+
+ return QualType();
+}
+
+QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getComplexType(ToElementType);
+}
+
+QualType ASTNodeImporter::VisitPointerType(const PointerType *T) {
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getPointerType(ToPointeeType);
+}
+
+QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
+ // FIXME: Check for blocks support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getBlockPointerType(ToPointeeType);
+}
+
+QualType
+ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
+ // FIXME: Check for C++ support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getLValueReferenceType(ToPointeeType);
+}
+
+QualType
+ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
+ // FIXME: Check for C++0x support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getRValueReferenceType(ToPointeeType);
+}
+
+QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
+ // FIXME: Check for C++ support in "to" context.
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ QualType ClassType = Importer.Import(QualType(T->getClass(), 0));
+ return Importer.getToContext().getMemberPointerType(ToPointeeType,
+ ClassType.getTypePtr());
+}
+
+QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getConstantArrayType(ToElementType,
+ T->getSize(),
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+}
+
+QualType
+ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getIncompleteArrayType(ToElementType,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+}
+
+QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ Expr *Size = Importer.Import(T->getSizeExpr());
+ if (!Size)
+ return QualType();
+
+ SourceRange Brackets = Importer.Import(T->getBracketsRange());
+ return Importer.getToContext().getVariableArrayType(ToElementType, Size,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(),
+ Brackets);
+}
+
+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->getVectorKind());
+}
+
+QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
+ QualType ToElementType = Importer.Import(T->getElementType());
+ if (ToElementType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getExtVectorType(ToElementType,
+ T->getNumElements());
+}
+
+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());
+ if (ToResultType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getFunctionNoProtoType(ToResultType,
+ T->getExtInfo());
+}
+
+QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ QualType ToResultType = Importer.Import(T->getResultType());
+ if (ToResultType.isNull())
+ return QualType();
+
+ // Import argument types
+ llvm::SmallVector<QualType, 4> ArgTypes;
+ for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
+ AEnd = T->arg_type_end();
+ A != AEnd; ++A) {
+ QualType ArgType = Importer.Import(*A);
+ if (ArgType.isNull())
+ return QualType();
+ ArgTypes.push_back(ArgType);
+ }
+
+ // Import exception types
+ llvm::SmallVector<QualType, 4> ExceptionTypes;
+ for (FunctionProtoType::exception_iterator E = T->exception_begin(),
+ EEnd = T->exception_end();
+ E != EEnd; ++E) {
+ QualType ExceptionType = Importer.Import(*E);
+ if (ExceptionType.isNull())
+ return QualType();
+ ExceptionTypes.push_back(ExceptionType);
+ }
+
+ FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo();
+ EPI.Exceptions = ExceptionTypes.data();
+
+ return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(),
+ ArgTypes.size(), EPI);
+}
+
+QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
+ TypedefDecl *ToDecl
+ = dyn_cast_or_null<TypedefDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
+
+ return Importer.getToContext().getTypeDeclType(ToDecl);
+}
+
+QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
+ Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
+ if (!ToExpr)
+ return QualType();
+
+ return Importer.getToContext().getTypeOfExprType(ToExpr);
+}
+
+QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
+ QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (ToUnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getTypeOfType(ToUnderlyingType);
+}
+
+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();
+
+ return Importer.getToContext().getDecltypeType(ToExpr);
+}
+
+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<RecordDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
+
+ return Importer.getToContext().getTagDeclType(ToDecl);
+}
+
+QualType ASTNodeImporter::VisitEnumType(const EnumType *T) {
+ EnumDecl *ToDecl
+ = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl()));
+ if (!ToDecl)
+ return QualType();
+
+ return Importer.getToContext().getTagDeclType(ToDecl);
+}
+
+QualType ASTNodeImporter::VisitTemplateSpecializationType(
+ const TemplateSpecializationType *T) {
+ TemplateName ToTemplate = Importer.Import(T->getTemplateName());
+ if (ToTemplate.isNull())
+ return QualType();
+
+ llvm::SmallVector<TemplateArgument, 2> 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()) {
+ ToQualifier = Importer.Import(T->getQualifier());
+ if (!ToQualifier)
+ return QualType();
+ }
+
+ QualType ToNamedType = Importer.Import(T->getNamedType());
+ if (ToNamedType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getElaboratedType(T->getKeyword(),
+ ToQualifier, ToNamedType);
+}
+
+QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ ObjCInterfaceDecl *Class
+ = dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
+ if (!Class)
+ return QualType();
+
+ return Importer.getToContext().getObjCInterfaceType(Class);
+}
+
+QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
+ QualType ToBaseType = Importer.Import(T->getBaseType());
+ if (ToBaseType.isNull())
+ return QualType();
+
+ llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ for (ObjCObjectType::qual_iterator P = T->qual_begin(),
+ PEnd = T->qual_end();
+ P != PEnd; ++P) {
+ ObjCProtocolDecl *Protocol
+ = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(*P));
+ if (!Protocol)
+ return QualType();
+ Protocols.push_back(Protocol);
+ }
+
+ return Importer.getToContext().getObjCObjectType(ToBaseType,
+ Protocols.data(),
+ Protocols.size());
+}
+
+QualType
+ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ QualType ToPointeeType = Importer.Import(T->getPointeeType());
+ if (ToPointeeType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getObjCObjectPointerType(ToPointeeType);
+}
+
+//----------------------------------------------------------------------------
+// Import Declarations
+//----------------------------------------------------------------------------
+bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
+ DeclContext *&LexicalDC,
+ DeclarationName &Name,
+ SourceLocation &Loc) {
+ // Import the context of this declaration.
+ DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return true;
+
+ LexicalDC = DC;
+ if (D->getDeclContext() != D->getLexicalDeclContext()) {
+ LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+ if (!LexicalDC)
+ return true;
+ }
+
+ // Import the name of this declaration.
+ Name = Importer.Import(D->getDeclName());
+ if (D->getDeclName() && !Name)
+ return true;
+
+ // Import the location of this declaration.
+ Loc = Importer.Import(D->getLocation());
+ return false;
+}
+
+void
+ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To) {
+ // NOTE: To.Name and To.Loc are already imported.
+ // We only have to import To.LocInfo.
+ switch (To.getName().getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return;
+
+ case DeclarationName::CXXOperatorName: {
+ SourceRange Range = From.getCXXOperatorNameRange();
+ To.setCXXOperatorNameRange(Importer.Import(Range));
+ return;
+ }
+ case DeclarationName::CXXLiteralOperatorName: {
+ SourceLocation Loc = From.getCXXLiteralOperatorNameLoc();
+ To.setCXXLiteralOperatorNameLoc(Importer.Import(Loc));
+ return;
+ }
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName: {
+ TypeSourceInfo *FromTInfo = From.getNamedTypeInfo();
+ To.setNamedTypeInfo(Importer.Import(FromTInfo));
+ return;
+ }
+ assert(0 && "Unknown name kind.");
+ }
+}
+
+void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, 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;
+ ++From)
+ 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<CXXRecordDecl>(To)) {
+ CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From);
+
+ llvm::SmallVector<CXXBaseSpecifier *, 4> 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<NamedDecl *, 4> 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<NamedDecl>(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<TemplateArgument, 2> 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<TemplateArgument> &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.getNonEquivalentDecls());
+ return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
+}
+
+bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
+ StructuralEquivalenceContext Ctx(Importer.getFromContext(),
+ Importer.getToContext(),
+ 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();
+ return 0;
+}
+
+Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
+ // Import the major distinguishing characteristics of this namespace.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ NamespaceDecl *MergeWithNamespace = 0;
+ if (!Name) {
+ // This is an anonymous namespace. Adopt an existing anonymous
+ // namespace if we can.
+ // FIXME: Not testable.
+ if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC))
+ MergeWithNamespace = TU->getAnonymousNamespace();
+ else
+ MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace();
+ } else {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace))
+ continue;
+
+ if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) {
+ MergeWithNamespace = FoundNS;
+ ConflictingDecls.clear();
+ break;
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ }
+ }
+
+ // Create the "to" namespace, if needed.
+ NamespaceDecl *ToNamespace = MergeWithNamespace;
+ if (!ToNamespace) {
+ ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo());
+ ToNamespace->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToNamespace);
+
+ // If this is an anonymous namespace, register it as the anonymous
+ // namespace within its context.
+ if (!Name) {
+ if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC))
+ TU->setAnonymousNamespace(ToNamespace);
+ else
+ cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
+ }
+ }
+ Importer.Imported(D, ToNamespace);
+
+ ImportDeclContext(D);
+
+ return ToNamespace;
+}
+
+Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
+ // Import the major distinguishing characteristics of this typedef.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // If this typedef is not in block scope, determine whether we've
+ // seen a typedef with the same name (that we can merge with) or any
+ // other entity by that name (which name lookup could conflict with).
+ if (!DC->isFunctionOrMethod()) {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+ if (TypedefDecl *FoundTypedef = dyn_cast<TypedefDecl>(*Lookup.first)) {
+ if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(),
+ FoundTypedef->getUnderlyingType()))
+ return Importer.Imported(D, FoundTypedef);
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (!Name)
+ return 0;
+ }
+ }
+
+ // Import the underlying type of this typedef;
+ QualType T = Importer.Import(D->getUnderlyingType());
+ if (T.isNull())
+ return 0;
+
+ // Create the new typedef node.
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ TypedefDecl *ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
+ Loc, Name.getAsIdentifierInfo(),
+ TInfo);
+ ToTypedef->setAccess(D->getAccess());
+ ToTypedef->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToTypedef);
+ LexicalDC->addDecl(ToTypedef);
+
+ return ToTypedef;
+}
+
+Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
+ // Import the major distinguishing characteristics of this enum.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // Figure out what enum name we're looking for.
+ unsigned IDNS = Decl::IDNS_Tag;
+ DeclarationName SearchName = Name;
+ if (!SearchName && D->getTypedefForAnonDecl()) {
+ SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName());
+ IDNS = Decl::IDNS_Ordinary;
+ } else if (Importer.getToContext().getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Ordinary;
+
+ // We may already have an enum of the same name; try to find and match it.
+ if (!DC->isFunctionOrMethod() && SearchName) {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+
+ Decl *Found = *Lookup.first;
+ if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Found)) {
+ if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
+ Found = Tag->getDecl();
+ }
+
+ if (EnumDecl *FoundEnum = dyn_cast<EnumDecl>(Found)) {
+ if (IsStructuralMatch(D, FoundEnum))
+ return Importer.Imported(D, FoundEnum);
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ }
+ }
+
+ // Create the enum declaration.
+ EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc,
+ 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());
+ SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+ D2->setQualifierInfo(NNS, NNSRange);
+ }
+ D2->setAccess(D->getAccess());
+ D2->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, D2);
+ LexicalDC->addDecl(D2);
+
+ // Import the integer type.
+ QualType ToIntegerType = Importer.Import(D->getIntegerType());
+ if (ToIntegerType.isNull())
+ return 0;
+ D2->setIntegerType(ToIntegerType);
+
+ // Import the definition
+ if (D->isDefinition()) {
+ QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(D));
+ if (T.isNull())
+ return 0;
+
+ QualType ToPromotionType = Importer.Import(D->getPromotionType());
+ if (ToPromotionType.isNull())
+ return 0;
+
+ D2->startDefinition();
+ ImportDeclContext(D);
+
+ // FIXME: we might need to merge the number of positive or negative bits
+ // if the enumerator lists don't match.
+ D2->completeDefinition(T, ToPromotionType,
+ D->getNumPositiveBits(),
+ D->getNumNegativeBits());
+ }
+
+ return D2;
+}
+
+Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *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);
+ }
+
+ // Import the major distinguishing characteristics of this record.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // Figure out what structure name we're looking for.
+ unsigned IDNS = Decl::IDNS_Tag;
+ DeclarationName SearchName = Name;
+ if (!SearchName && D->getTypedefForAnonDecl()) {
+ SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName());
+ IDNS = Decl::IDNS_Ordinary;
+ } else if (Importer.getToContext().getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Ordinary;
+
+ // We may already have a record of the same name; try to find and match it.
+ RecordDecl *AdoptDecl = 0;
+ if (!DC->isFunctionOrMethod() && SearchName) {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+
+ Decl *Found = *Lookup.first;
+ if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Found)) {
+ if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
+ Found = Tag->getDecl();
+ }
+
+ if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
+ if (RecordDecl *FoundDef = FoundRecord->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.
+ // FIXME: For C++, we should also merge methods here.
+ return Importer.Imported(D, FoundDef);
+ }
+ } else {
+ // We have a forward declaration of this type, so adopt that forward
+ // declaration rather than building a new one.
+ AdoptDecl = FoundRecord;
+ continue;
+ }
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ }
+ }
+
+ // Create the record declaration.
+ RecordDecl *D2 = AdoptDecl;
+ if (!D2) {
+ if (isa<CXXRecordDecl>(D)) {
+ CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
+ D->getTagKind(),
+ DC, Loc,
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getTagKeywordLoc()));
+ D2 = D2CXX;
+ D2->setAccess(D->getAccess());
+ } else {
+ D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
+ DC, Loc,
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getTagKeywordLoc()));
+ }
+ // Import the qualifier, if any.
+ if (D->getQualifier()) {
+ NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+ SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+ D2->setQualifierInfo(NNS, NNSRange);
+ }
+ D2->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(D2);
+ }
+
+ Importer.Imported(D, D2);
+
+ if (D->isDefinition() && ImportDefinition(D, D2))
+ return 0;
+
+ return D2;
+}
+
+Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ // Import the major distinguishing characteristics of this enumerator.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ // Determine whether there are any other declarations with the same name and
+ // in the same context.
+ if (!LexicalDC->isFunctionOrMethod()) {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (!Name)
+ return 0;
+ }
+ }
+
+ Expr *Init = Importer.Import(D->getInitExpr());
+ if (D->getInitExpr() && !Init)
+ return 0;
+
+ EnumConstantDecl *ToEnumerator
+ = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc,
+ Name.getAsIdentifierInfo(), T,
+ Init, D->getInitVal());
+ ToEnumerator->setAccess(D->getAccess());
+ ToEnumerator->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToEnumerator);
+ LexicalDC->addDecl(ToEnumerator);
+ return ToEnumerator;
+}
+
+Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
+ // Import the major distinguishing characteristics of this function.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // Try to find a function in our own ("to") context with the same name, same
+ // type, and in the same context as the function we're importing.
+ if (!LexicalDC->isFunctionOrMethod()) {
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+
+ if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(*Lookup.first)) {
+ if (isExternalLinkage(FoundFunction->getLinkage()) &&
+ isExternalLinkage(D->getLinkage())) {
+ if (Importer.IsStructurallyEquivalent(D->getType(),
+ FoundFunction->getType())) {
+ // FIXME: Actually try to merge the body and other attributes.
+ return Importer.Imported(D, FoundFunction);
+ }
+
+ // FIXME: Check for overloading more carefully, e.g., by boosting
+ // Sema::IsOverload out to the AST library.
+
+ // Function overloading is okay in C++.
+ if (Importer.getToContext().getLangOptions().CPlusPlus)
+ continue;
+
+ // Complain about inconsistent function types.
+ Importer.ToDiag(Loc, diag::err_odr_function_type_inconsistent)
+ << Name << D->getType() << FoundFunction->getType();
+ Importer.ToDiag(FoundFunction->getLocation(),
+ diag::note_odr_value_here)
+ << FoundFunction->getType();
+ }
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (!Name)
+ return 0;
+ }
+ }
+
+ DeclarationNameInfo NameInfo(Name, Loc);
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+
+ // Import the type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ // Import the function parameters.
+ llvm::SmallVector<ParmVarDecl *, 8> Parameters;
+ for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+ P != PEnd; ++P) {
+ ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*P));
+ if (!ToP)
+ return 0;
+
+ Parameters.push_back(ToP);
+ }
+
+ // Create the imported function.
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ FunctionDecl *ToFunction = 0;
+ if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
+ ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
+ cast<CXXRecordDecl>(DC),
+ NameInfo, T, TInfo,
+ FromConstructor->isExplicit(),
+ D->isInlineSpecified(),
+ D->isImplicit());
+ } else if (isa<CXXDestructorDecl>(D)) {
+ ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
+ cast<CXXRecordDecl>(DC),
+ NameInfo, T, TInfo,
+ D->isInlineSpecified(),
+ D->isImplicit());
+ } else if (CXXConversionDecl *FromConversion
+ = dyn_cast<CXXConversionDecl>(D)) {
+ ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
+ cast<CXXRecordDecl>(DC),
+ NameInfo, T, TInfo,
+ D->isInlineSpecified(),
+ FromConversion->isExplicit());
+ } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ ToFunction = CXXMethodDecl::Create(Importer.getToContext(),
+ cast<CXXRecordDecl>(DC),
+ NameInfo, T, TInfo,
+ Method->isStatic(),
+ Method->getStorageClassAsWritten(),
+ Method->isInlineSpecified());
+ } else {
+ ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
+ NameInfo, T, TInfo, D->getStorageClass(),
+ D->getStorageClassAsWritten(),
+ D->isInlineSpecified(),
+ D->hasWrittenPrototype());
+ }
+
+ // Import the qualifier, if any.
+ if (D->getQualifier()) {
+ NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+ SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+ ToFunction->setQualifierInfo(NNS, NNSRange);
+ }
+ ToFunction->setAccess(D->getAccess());
+ ToFunction->setLexicalDeclContext(LexicalDC);
+ ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
+ ToFunction->setTrivial(D->isTrivial());
+ ToFunction->setPure(D->isPure());
+ Importer.Imported(D, ToFunction);
+
+ // Set the parameters.
+ for (unsigned I = 0, N = Parameters.size(); I != N; ++I) {
+ Parameters[I]->setOwningFunction(ToFunction);
+ ToFunction->addDecl(Parameters[I]);
+ }
+ ToFunction->setParams(Parameters.data(), Parameters.size());
+
+ // FIXME: Other bits to merge?
+
+ // Add this function to the lexical context.
+ LexicalDC->addDecl(ToFunction);
+
+ return ToFunction;
+}
+
+Decl *ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ return VisitFunctionDecl(D);
+}
+
+Decl *ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+Decl *ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *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;
+
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ Expr *BitWidth = Importer.Import(D->getBitWidth());
+ if (!BitWidth && D->getBitWidth())
+ return 0;
+
+ FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
+ Loc, Name.getAsIdentifierInfo(),
+ T, TInfo, BitWidth, D->isMutable());
+ ToField->setAccess(D->getAccess());
+ ToField->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToField);
+ LexicalDC->addDecl(ToField);
+ 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<NamedDecl>(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;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // Determine whether we've already imported this ivar
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(*Lookup.first)) {
+ if (Importer.IsStructurallyEquivalent(D->getType(),
+ FoundIvar->getType())) {
+ Importer.Imported(D, FoundIvar);
+ return FoundIvar;
+ }
+
+ Importer.ToDiag(Loc, diag::err_odr_ivar_type_inconsistent)
+ << Name << D->getType() << FoundIvar->getType();
+ Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
+ << FoundIvar->getType();
+ return 0;
+ }
+ }
+
+ // Import the type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ Expr *BitWidth = Importer.Import(D->getBitWidth());
+ if (!BitWidth && D->getBitWidth())
+ return 0;
+
+ ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(),
+ cast<ObjCContainerDecl>(DC),
+ Loc, Name.getAsIdentifierInfo(),
+ T, TInfo, D->getAccessControl(),
+ BitWidth, D->getSynthesize());
+ ToIvar->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToIvar);
+ LexicalDC->addDecl(ToIvar);
+ return ToIvar;
+
+}
+
+Decl *ASTNodeImporter::VisitVarDecl(VarDecl *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;
+
+ // Try to find a variable in our own ("to") context with the same name and
+ // in the same context as the variable we're importing.
+ if (D->isFileVarDecl()) {
+ VarDecl *MergeWithVar = 0;
+ llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
+ continue;
+
+ if (VarDecl *FoundVar = dyn_cast<VarDecl>(*Lookup.first)) {
+ // We have found a variable that we may need to merge with. Check it.
+ if (isExternalLinkage(FoundVar->getLinkage()) &&
+ isExternalLinkage(D->getLinkage())) {
+ if (Importer.IsStructurallyEquivalent(D->getType(),
+ FoundVar->getType())) {
+ MergeWithVar = FoundVar;
+ break;
+ }
+
+ const ArrayType *FoundArray
+ = Importer.getToContext().getAsArrayType(FoundVar->getType());
+ const ArrayType *TArray
+ = Importer.getToContext().getAsArrayType(D->getType());
+ if (FoundArray && TArray) {
+ if (isa<IncompleteArrayType>(FoundArray) &&
+ isa<ConstantArrayType>(TArray)) {
+ // Import the type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ FoundVar->setType(T);
+ MergeWithVar = FoundVar;
+ break;
+ } else if (isa<IncompleteArrayType>(TArray) &&
+ isa<ConstantArrayType>(FoundArray)) {
+ MergeWithVar = FoundVar;
+ break;
+ }
+ }
+
+ Importer.ToDiag(Loc, diag::err_odr_variable_type_inconsistent)
+ << Name << D->getType() << FoundVar->getType();
+ Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here)
+ << FoundVar->getType();
+ }
+ }
+
+ ConflictingDecls.push_back(*Lookup.first);
+ }
+
+ if (MergeWithVar) {
+ // An equivalent variable with external linkage has been found. Link
+ // the two declarations, then merge them.
+ Importer.Imported(D, MergeWithVar);
+
+ if (VarDecl *DDef = D->getDefinition()) {
+ if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) {
+ Importer.ToDiag(ExistingDef->getLocation(),
+ diag::err_odr_variable_multiple_def)
+ << Name;
+ Importer.FromDiag(DDef->getLocation(), diag::note_odr_defined_here);
+ } else {
+ Expr *Init = Importer.Import(DDef->getInit());
+ MergeWithVar->setInit(Init);
+ }
+ }
+
+ return MergeWithVar;
+ }
+
+ if (!ConflictingDecls.empty()) {
+ Name = Importer.HandleNameConflict(Name, DC, IDNS,
+ ConflictingDecls.data(),
+ ConflictingDecls.size());
+ if (!Name)
+ return 0;
+ }
+ }
+
+ // Import the type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ // Create the imported variable.
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(), T, TInfo,
+ D->getStorageClass(),
+ D->getStorageClassAsWritten());
+ // Import the qualifier, if any.
+ if (D->getQualifier()) {
+ NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+ SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+ ToVar->setQualifierInfo(NNS, NNSRange);
+ }
+ ToVar->setAccess(D->getAccess());
+ ToVar->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToVar);
+ LexicalDC->addDecl(ToVar);
+
+ // Merge the initializer.
+ // FIXME: Can we really import any initializer? Alternatively, we could force
+ // ourselves to import every declaration of a variable and then only use
+ // getInit() here.
+ ToVar->setInit(Importer.Import(const_cast<Expr *>(D->getAnyInitializer())));
+
+ // FIXME: Other bits to merge?
+
+ return ToVar;
+}
+
+Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
+ // Parameters are created in the translation unit's context, then moved
+ // into the function declaration's context afterward.
+ DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
+
+ // 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 parameter's type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ // Create the imported parameter.
+ ImplicitParamDecl *ToParm
+ = ImplicitParamDecl::Create(Importer.getToContext(), DC,
+ Loc, Name.getAsIdentifierInfo(),
+ T);
+ return Importer.Imported(D, ToParm);
+}
+
+Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
+ // Parameters are created in the translation unit's context, then moved
+ // into the function declaration's context afterward.
+ DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();
+
+ // 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 parameter's type.
+ QualType T = Importer.Import(D->getType());
+ if (T.isNull())
+ return 0;
+
+ // Create the imported parameter.
+ TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC,
+ Loc, Name.getAsIdentifierInfo(),
+ T, TInfo, D->getStorageClass(),
+ D->getStorageClassAsWritten(),
+ /*FIXME: Default argument*/ 0);
+ ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
+ return Importer.Imported(D, ToParm);
+}
+
+Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ // Import the major distinguishing characteristics of a method.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(*Lookup.first)) {
+ if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
+ continue;
+
+ // Check return types.
+ if (!Importer.IsStructurallyEquivalent(D->getResultType(),
+ FoundMethod->getResultType())) {
+ Importer.ToDiag(Loc, diag::err_odr_objc_method_result_type_inconsistent)
+ << D->isInstanceMethod() << Name
+ << D->getResultType() << FoundMethod->getResultType();
+ Importer.ToDiag(FoundMethod->getLocation(),
+ diag::note_odr_objc_method_here)
+ << D->isInstanceMethod() << Name;
+ return 0;
+ }
+
+ // Check the number of parameters.
+ if (D->param_size() != FoundMethod->param_size()) {
+ Importer.ToDiag(Loc, diag::err_odr_objc_method_num_params_inconsistent)
+ << D->isInstanceMethod() << Name
+ << D->param_size() << FoundMethod->param_size();
+ Importer.ToDiag(FoundMethod->getLocation(),
+ diag::note_odr_objc_method_here)
+ << D->isInstanceMethod() << Name;
+ return 0;
+ }
+
+ // Check parameter types.
+ for (ObjCMethodDecl::param_iterator P = D->param_begin(),
+ PEnd = D->param_end(), FoundP = FoundMethod->param_begin();
+ P != PEnd; ++P, ++FoundP) {
+ if (!Importer.IsStructurallyEquivalent((*P)->getType(),
+ (*FoundP)->getType())) {
+ Importer.FromDiag((*P)->getLocation(),
+ diag::err_odr_objc_method_param_type_inconsistent)
+ << D->isInstanceMethod() << Name
+ << (*P)->getType() << (*FoundP)->getType();
+ Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here)
+ << (*FoundP)->getType();
+ return 0;
+ }
+ }
+
+ // Check variadic/non-variadic.
+ // Check the number of parameters.
+ if (D->isVariadic() != FoundMethod->isVariadic()) {
+ Importer.ToDiag(Loc, diag::err_odr_objc_method_variadic_inconsistent)
+ << D->isInstanceMethod() << Name;
+ Importer.ToDiag(FoundMethod->getLocation(),
+ diag::note_odr_objc_method_here)
+ << D->isInstanceMethod() << Name;
+ return 0;
+ }
+
+ // FIXME: Any other bits we need to merge?
+ return Importer.Imported(D, FoundMethod);
+ }
+ }
+
+ // Import the result type.
+ QualType ResultTy = Importer.Import(D->getResultType());
+ if (ResultTy.isNull())
+ return 0;
+
+ TypeSourceInfo *ResultTInfo = Importer.Import(D->getResultTypeSourceInfo());
+
+ ObjCMethodDecl *ToMethod
+ = ObjCMethodDecl::Create(Importer.getToContext(),
+ Loc,
+ Importer.Import(D->getLocEnd()),
+ Name.getObjCSelector(),
+ ResultTy, ResultTInfo, DC,
+ D->isInstanceMethod(),
+ D->isVariadic(),
+ D->isSynthesized(),
+ D->isDefined(),
+ D->getImplementationControl());
+
+ // FIXME: When we decide to merge method definitions, we'll need to
+ // deal with implicit parameters.
+
+ // Import the parameters
+ llvm::SmallVector<ParmVarDecl *, 5> ToParams;
+ for (ObjCMethodDecl::param_iterator FromP = D->param_begin(),
+ FromPEnd = D->param_end();
+ FromP != FromPEnd;
+ ++FromP) {
+ ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*FromP));
+ if (!ToP)
+ return 0;
+
+ ToParams.push_back(ToP);
+ }
+
+ // Set the parameters.
+ for (unsigned I = 0, N = ToParams.size(); I != N; ++I) {
+ ToParams[I]->setOwningFunction(ToMethod);
+ ToMethod->addDecl(ToParams[I]);
+ }
+ ToMethod->setMethodParams(Importer.getToContext(),
+ ToParams.data(), ToParams.size(),
+ ToParams.size());
+
+ ToMethod->setLexicalDeclContext(LexicalDC);
+ Importer.Imported(D, ToMethod);
+ LexicalDC->addDecl(ToMethod);
+ return ToMethod;
+}
+
+Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
+ // Import the major distinguishing characteristics of a category.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ ObjCInterfaceDecl *ToInterface
+ = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface()));
+ if (!ToInterface)
+ return 0;
+
+ // Determine if we've already encountered this category.
+ ObjCCategoryDecl *MergeWithCategory
+ = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
+ ObjCCategoryDecl *ToCategory = MergeWithCategory;
+ if (!ToCategory) {
+ ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getAtLoc()),
+ Loc,
+ Importer.Import(D->getCategoryNameLoc()),
+ Name.getAsIdentifierInfo());
+ ToCategory->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToCategory);
+ Importer.Imported(D, ToCategory);
+
+ // Link this category into its class's category list.
+ ToCategory->setClassInterface(ToInterface);
+ ToCategory->insertNextClassCategory();
+
+ // Import protocols
+ llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCCategoryDecl::protocol_loc_iterator FromProtoLoc
+ = D->protocol_loc_begin();
+ for (ObjCCategoryDecl::protocol_iterator FromProto = D->protocol_begin(),
+ FromProtoEnd = D->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return 0;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ ToCategory->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
+
+ } else {
+ Importer.Imported(D, ToCategory);
+ }
+
+ // Import all of the members of this category.
+ ImportDeclContext(D);
+
+ // If we have an implementation, import it as well.
+ if (D->getImplementation()) {
+ ObjCCategoryImplDecl *Impl
+ = cast_or_null<ObjCCategoryImplDecl>(
+ Importer.Import(D->getImplementation()));
+ if (!Impl)
+ return 0;
+
+ ToCategory->setImplementation(Impl);
+ }
+
+ return ToCategory;
+}
+
+Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+ // Import the major distinguishing characteristics of a protocol.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ ObjCProtocolDecl *MergeWithProtocol = 0;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
+ continue;
+
+ if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(*Lookup.first)))
+ break;
+ }
+
+ ObjCProtocolDecl *ToProto = MergeWithProtocol;
+ if (!ToProto || ToProto->isForwardDecl()) {
+ if (!ToProto) {
+ ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo());
+ ToProto->setForwardDecl(D->isForwardDecl());
+ ToProto->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToProto);
+ }
+ Importer.Imported(D, ToProto);
+
+ // Import protocols
+ llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCProtocolDecl::protocol_loc_iterator
+ FromProtoLoc = D->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(),
+ FromProtoEnd = D->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return 0;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ ToProto->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
+ } else {
+ Importer.Imported(D, ToProto);
+ }
+
+ // Import all of the members of this protocol.
+ ImportDeclContext(D);
+
+ return ToProto;
+}
+
+Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ // Import the major distinguishing characteristics of an @interface.
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ ObjCInterfaceDecl *MergeWithIface = 0;
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ continue;
+
+ if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(*Lookup.first)))
+ break;
+ }
+
+ ObjCInterfaceDecl *ToIface = MergeWithIface;
+ if (!ToIface || ToIface->isForwardDecl()) {
+ if (!ToIface) {
+ ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(),
+ DC, Loc,
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getClassLoc()),
+ D->isForwardDecl(),
+ D->isImplicitInterfaceDecl());
+ ToIface->setForwardDecl(D->isForwardDecl());
+ ToIface->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToIface);
+ }
+ Importer.Imported(D, ToIface);
+
+ if (D->getSuperClass()) {
+ ObjCInterfaceDecl *Super
+ = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
+ if (!Super)
+ return 0;
+
+ ToIface->setSuperClass(Super);
+ ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+ }
+
+ // Import protocols
+ llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCInterfaceDecl::protocol_loc_iterator
+ FromProtoLoc = D->protocol_loc_begin();
+
+ // FIXME: Should we be usng all_referenced_protocol_begin() here?
+ for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
+ FromProtoEnd = D->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return 0;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ ToIface->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
+
+ // Import @end range
+ ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
+ } else {
+ Importer.Imported(D, ToIface);
+
+ // Check for consistency of superclasses.
+ DeclarationName FromSuperName, ToSuperName;
+ if (D->getSuperClass())
+ FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
+ if (ToIface->getSuperClass())
+ ToSuperName = ToIface->getSuperClass()->getDeclName();
+ if (FromSuperName != ToSuperName) {
+ Importer.ToDiag(ToIface->getLocation(),
+ diag::err_odr_objc_superclass_inconsistent)
+ << ToIface->getDeclName();
+ if (ToIface->getSuperClass())
+ Importer.ToDiag(ToIface->getSuperClassLoc(),
+ diag::note_odr_objc_superclass)
+ << ToIface->getSuperClass()->getDeclName();
+ else
+ Importer.ToDiag(ToIface->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ if (D->getSuperClass())
+ Importer.FromDiag(D->getSuperClassLoc(),
+ diag::note_odr_objc_superclass)
+ << D->getSuperClass()->getDeclName();
+ else
+ Importer.FromDiag(D->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ return 0;
+ }
+ }
+
+ // Import categories. When the categories themselves are imported, they'll
+ // hook themselves into this interface.
+ for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
+ FromCat = FromCat->getNextClassCategory())
+ Importer.Import(FromCat);
+
+ // Import all of the members of this class.
+ ImportDeclContext(D);
+
+ // If we have an @implementation, import it as well.
+ if (D->getImplementation()) {
+ ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
+ Importer.Import(D->getImplementation()));
+ if (!Impl)
+ return 0;
+
+ ToIface->setImplementation(Impl);
+ }
+
+ return ToIface;
+}
+
+Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>(
+ 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<ObjCInterfaceDecl>(
+ Importer.Import(D->getClassInterface()));
+ if (!Iface)
+ return 0;
+
+ // Import the superclass, if any.
+ ObjCInterfaceDecl *Super = 0;
+ if (D->getSuperClass()) {
+ Super = cast_or_null<ObjCInterfaceDecl>(
+ 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;
+ DeclarationName Name;
+ SourceLocation Loc;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
+ return 0;
+
+ // Check whether we have already imported this property.
+ for (DeclContext::lookup_result Lookup = DC->lookup(Name);
+ Lookup.first != Lookup.second;
+ ++Lookup.first) {
+ if (ObjCPropertyDecl *FoundProp
+ = dyn_cast<ObjCPropertyDecl>(*Lookup.first)) {
+ // Check property types.
+ if (!Importer.IsStructurallyEquivalent(D->getType(),
+ FoundProp->getType())) {
+ Importer.ToDiag(Loc, diag::err_odr_objc_property_type_inconsistent)
+ << Name << D->getType() << FoundProp->getType();
+ Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here)
+ << FoundProp->getType();
+ return 0;
+ }
+
+ // FIXME: Check property attributes, getters, setters, etc.?
+
+ // Consider these properties to be equivalent.
+ Importer.Imported(D, FoundProp);
+ return FoundProp;
+ }
+ }
+
+ // Import the type.
+ TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());
+ if (!T)
+ return 0;
+
+ // Create the new property.
+ ObjCPropertyDecl *ToProperty
+ = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getAtLoc()),
+ T,
+ D->getPropertyImplementation());
+ Importer.Imported(D, ToProperty);
+ ToProperty->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToProperty);
+
+ ToProperty->setPropertyAttributes(D->getPropertyAttributes());
+ ToProperty->setPropertyAttributesAsWritten(
+ D->getPropertyAttributesAsWritten());
+ ToProperty->setGetterName(Importer.Import(D->getGetterName()));
+ ToProperty->setSetterName(Importer.Import(D->getSetterName()));
+ ToProperty->setGetterMethodDecl(
+ cast_or_null<ObjCMethodDecl>(Importer.Import(D->getGetterMethodDecl())));
+ ToProperty->setSetterMethodDecl(
+ cast_or_null<ObjCMethodDecl>(Importer.Import(D->getSetterMethodDecl())));
+ ToProperty->setPropertyIvarDecl(
+ cast_or_null<ObjCIvarDecl>(Importer.Import(D->getPropertyIvarDecl())));
+ return ToProperty;
+}
+
+Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>(
+ 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<ObjCImplDecl>(LexicalDC);
+ if (!InImpl)
+ return 0;
+
+ // Import the ivar (for an @synthesize).
+ ObjCIvarDecl *Ivar = 0;
+ if (D->getPropertyIvarDecl()) {
+ Ivar = cast_or_null<ObjCIvarDecl>(
+ 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.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return 0;
+
+ DeclContext *LexicalDC = DC;
+ if (D->getDeclContext() != D->getLexicalDeclContext()) {
+ LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+ if (!LexicalDC)
+ return 0;
+ }
+
+ // Import the location of this declaration.
+ SourceLocation Loc = Importer.Import(D->getLocation());
+
+ llvm::SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ llvm::SmallVector<SourceLocation, 4> Locations;
+ ObjCForwardProtocolDecl::protocol_loc_iterator FromProtoLoc
+ = D->protocol_loc_begin();
+ for (ObjCForwardProtocolDecl::protocol_iterator FromProto
+ = D->protocol_begin(), FromProtoEnd = D->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ continue;
+
+ Protocols.push_back(ToProto);
+ Locations.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ ObjCForwardProtocolDecl *ToForward
+ = ObjCForwardProtocolDecl::Create(Importer.getToContext(), DC, Loc,
+ Protocols.data(), Protocols.size(),
+ Locations.data());
+ ToForward->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToForward);
+ Importer.Imported(D, ToForward);
+ return ToForward;
+}
+
+Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) {
+ // Import the context of this declaration.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return 0;
+
+ DeclContext *LexicalDC = DC;
+ if (D->getDeclContext() != D->getLexicalDeclContext()) {
+ LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+ if (!LexicalDC)
+ return 0;
+ }
+
+ // Import the location of this declaration.
+ SourceLocation Loc = Importer.Import(D->getLocation());
+
+ llvm::SmallVector<ObjCInterfaceDecl *, 4> Interfaces;
+ llvm::SmallVector<SourceLocation, 4> Locations;
+ for (ObjCClassDecl::iterator From = D->begin(), FromEnd = D->end();
+ From != FromEnd; ++From) {
+ ObjCInterfaceDecl *ToIface
+ = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
+ if (!ToIface)
+ continue;
+
+ Interfaces.push_back(ToIface);
+ Locations.push_back(Importer.Import(From->getLocation()));
+ }
+
+ ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC,
+ Loc,
+ Interfaces.data(),
+ Locations.data(),
+ Interfaces.size());
+ ToClass->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToClass);
+ Importer.Imported(D, ToClass);
+ return ToClass;
+}
+
+Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ // For template arguments, we adopt the translation unit as our declaration
+ // context. This context will be fixed when the actual template declaration
+ // 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<CXXRecordDecl>(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<NamedDecl *, 4> 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<ClassTemplateDecl>(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<ClassTemplateDecl>(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<TemplateArgument, 2> 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
+//----------------------------------------------------------------------------
+
+Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// Import Expressions
+//----------------------------------------------------------------------------
+Expr *ASTNodeImporter::VisitExpr(Expr *E) {
+ Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
+ << E->getStmtClassName();
+ return 0;
+}
+
+Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = Importer.Import(E->getQualifier());
+ if (!E->getQualifier())
+ return 0;
+ }
+
+ ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
+ if (!ToD)
+ return 0;
+
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ return DeclRefExpr::Create(Importer.getToContext(), Qualifier,
+ Importer.Import(E->getQualifierRange()),
+ ToD,
+ Importer.Import(E->getLocation()),
+ T, E->getValueKind(),
+ /*FIXME:TemplateArgs=*/0);
+}
+
+Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ return IntegerLiteral::Create(Importer.getToContext(),
+ E->getValue(), T,
+ Importer.Import(E->getLocation()));
+}
+
+Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ return new (Importer.getToContext()) CharacterLiteral(E->getValue(),
+ E->isWide(), T,
+ Importer.Import(E->getLocation()));
+}
+
+Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return 0;
+
+ return new (Importer.getToContext())
+ ParenExpr(Importer.Import(E->getLParen()),
+ Importer.Import(E->getRParen()),
+ SubExpr);
+}
+
+Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return 0;
+
+ return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(),
+ T, E->getValueKind(),
+ E->getObjectKind(),
+ Importer.Import(E->getOperatorLoc()));
+}
+
+Expr *ASTNodeImporter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ QualType ResultType = Importer.Import(E->getType());
+
+ if (E->isArgumentType()) {
+ TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo());
+ if (!TInfo)
+ return 0;
+
+ return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(),
+ TInfo, ResultType,
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getRParenLoc()));
+ }
+
+ Expr *SubExpr = Importer.Import(E->getArgumentExpr());
+ if (!SubExpr)
+ return 0;
+
+ return new (Importer.getToContext()) SizeOfAlignOfExpr(E->isSizeOf(),
+ SubExpr, ResultType,
+ Importer.Import(E->getOperatorLoc()),
+ Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ Expr *LHS = Importer.Import(E->getLHS());
+ if (!LHS)
+ return 0;
+
+ Expr *RHS = Importer.Import(E->getRHS());
+ if (!RHS)
+ return 0;
+
+ return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(),
+ T, E->getValueKind(),
+ E->getObjectKind(),
+ Importer.Import(E->getOperatorLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ QualType CompLHSType = Importer.Import(E->getComputationLHSType());
+ if (CompLHSType.isNull())
+ return 0;
+
+ QualType CompResultType = Importer.Import(E->getComputationResultType());
+ if (CompResultType.isNull())
+ return 0;
+
+ Expr *LHS = Importer.Import(E->getLHS());
+ if (!LHS)
+ return 0;
+
+ Expr *RHS = Importer.Import(E->getRHS());
+ if (!RHS)
+ return 0;
+
+ return new (Importer.getToContext())
+ CompoundAssignOperator(LHS, RHS, E->getOpcode(),
+ T, E->getValueKind(),
+ E->getObjectKind(),
+ CompLHSType, CompResultType,
+ Importer.Import(E->getOperatorLoc()));
+}
+
+bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
+ if (E->path_empty()) return false;
+
+ // TODO: import cast paths
+ return true;
+}
+
+Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return 0;
+
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, E->getValueKind());
+}
+
+Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return 0;
+
+ TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten());
+ if (!TInfo && E->getTypeInfoAsWritten())
+ return 0;
+
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return CStyleCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(E->getLParenLoc()),
+ Importer.Import(E->getRParenLoc()));
+}
+
+ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ bool MinimalImport)
+ : ToContext(ToContext), FromContext(FromContext),
+ ToFileManager(ToFileManager), FromFileManager(FromFileManager),
+ Minimal(MinimalImport)
+{
+ ImportedDecls[FromContext.getTranslationUnitDecl()]
+ = ToContext.getTranslationUnitDecl();
+}
+
+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<const Type *, const Type *>::iterator Pos
+ = ImportedTypes.find(fromTy);
+ if (Pos != ImportedTypes.end())
+ return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers());
+
+ // Import the type
+ ASTNodeImporter Importer(*this);
+ QualType ToT = Importer.Visit(fromTy);
+ if (ToT.isNull())
+ return ToT;
+
+ // Record the imported type.
+ ImportedTypes[fromTy] = ToT.getTypePtr();
+
+ return ToContext.getQualifiedType(ToT, FromT.getLocalQualifiers());
+}
+
+TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
+ if (!FromTSI)
+ return FromTSI;
+
+ // FIXME: For now we just create a "trivial" type source info based
+ // on the type and a single location. Implement a real version of this.
+ QualType T = Import(FromTSI->getType());
+ if (T.isNull())
+ return 0;
+
+ return ToContext.getTrivialTypeSourceInfo(T,
+ FromTSI->getTypeLoc().getSourceRange().getBegin());
+}
+
+Decl *ASTImporter::Import(Decl *FromD) {
+ if (!FromD)
+ return 0;
+
+ // Check whether we've already imported this declaration.
+ llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
+ if (Pos != ImportedDecls.end())
+ return Pos->second;
+
+ // Import the type
+ ASTNodeImporter Importer(*this);
+ Decl *ToD = Importer.Visit(FromD);
+ if (!ToD)
+ return 0;
+
+ // Record the imported declaration.
+ ImportedDecls[FromD] = ToD;
+
+ if (TagDecl *FromTag = dyn_cast<TagDecl>(FromD)) {
+ // Keep track of anonymous tags that have an associated typedef.
+ if (FromTag->getTypedefForAnonDecl())
+ AnonTagsWithPendingTypedefs.push_back(FromTag);
+ } else if (TypedefDecl *FromTypedef = dyn_cast<TypedefDecl>(FromD)) {
+ // When we've finished transforming a typedef, see whether it was the
+ // typedef for an anonymous tag.
+ for (llvm::SmallVector<TagDecl *, 4>::iterator
+ FromTag = AnonTagsWithPendingTypedefs.begin(),
+ FromTagEnd = AnonTagsWithPendingTypedefs.end();
+ FromTag != FromTagEnd; ++FromTag) {
+ if ((*FromTag)->getTypedefForAnonDecl() == FromTypedef) {
+ if (TagDecl *ToTag = cast_or_null<TagDecl>(Import(*FromTag))) {
+ // We found the typedef for an anonymous tag; link them.
+ ToTag->setTypedefForAnonDecl(cast<TypedefDecl>(ToD));
+ AnonTagsWithPendingTypedefs.erase(FromTag);
+ break;
+ }
+ }
+ }
+ }
+
+ return ToD;
+}
+
+DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
+ if (!FromDC)
+ return FromDC;
+
+ return cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
+}
+
+Expr *ASTImporter::Import(Expr *FromE) {
+ if (!FromE)
+ return 0;
+
+ return cast_or_null<Expr>(Import(cast<Stmt>(FromE)));
+}
+
+Stmt *ASTImporter::Import(Stmt *FromS) {
+ if (!FromS)
+ return 0;
+
+ // Check whether we've already imported this declaration.
+ llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
+ if (Pos != ImportedStmts.end())
+ return Pos->second;
+
+ // Import the type
+ ASTNodeImporter Importer(*this);
+ Stmt *ToS = Importer.Visit(FromS);
+ if (!ToS)
+ return 0;
+
+ // Record the imported declaration.
+ ImportedStmts[FromS] = ToS;
+ return ToS;
+}
+
+NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
+ if (!FromNNS)
+ return 0;
+
+ // FIXME: Implement!
+ return 0;
+}
+
+TemplateName ASTImporter::Import(TemplateName From) {
+ switch (From.getKind()) {
+ case TemplateName::Template:
+ if (TemplateDecl *ToTemplate
+ = cast_or_null<TemplateDecl>(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<NamedDecl>(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<TemplateDecl>(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<TemplateTemplateParmDecl>(
+ 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();
+
+ SourceManager &FromSM = FromContext.getSourceManager();
+
+ // For now, map everything down to its spelling location, so that we
+ // don't have to import macro instantiations.
+ // FIXME: Import macro instantiations!
+ FromLoc = FromSM.getSpellingLoc(FromLoc);
+ std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
+ SourceManager &ToSM = ToContext.getSourceManager();
+ return ToSM.getLocForStartOfFile(Import(Decomposed.first))
+ .getFileLocWithOffset(Decomposed.second);
+}
+
+SourceRange ASTImporter::Import(SourceRange FromRange) {
+ return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd()));
+}
+
+FileID ASTImporter::Import(FileID FromID) {
+ llvm::DenseMap<FileID, FileID>::iterator Pos
+ = ImportedFileIDs.find(FromID);
+ if (Pos != ImportedFileIDs.end())
+ return Pos->second;
+
+ SourceManager &FromSM = FromContext.getSourceManager();
+ SourceManager &ToSM = ToContext.getSourceManager();
+ const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);
+ assert(FromSLoc.isFile() && "Cannot handle macro instantiations yet");
+
+ // Include location of this file.
+ SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
+
+ // Map the FileID for to the "to" source manager.
+ FileID ToID;
+ const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
+ if (Cache->Entry) {
+ // FIXME: We probably want to use getVirtualFile(), so we don't hit the
+ // disk again
+ // FIXME: We definitely want to re-use the existing MemoryBuffer, rather
+ // than mmap the files several times.
+ const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName());
+ ToID = ToSM.createFileID(Entry, ToIncludeLoc,
+ FromSLoc.getFile().getFileCharacteristic());
+ } else {
+ // FIXME: We want to re-use the existing MemoryBuffer!
+ const llvm::MemoryBuffer *
+ FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
+ llvm::MemoryBuffer *ToBuf
+ = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
+ FromBuf->getBufferIdentifier());
+ ToID = ToSM.createFileIDForMemBuffer(ToBuf);
+ }
+
+
+ ImportedFileIDs[FromID] = ToID;
+ return ToID;
+}
+
+void ASTImporter::ImportDefinition(Decl *From) {
+ Decl *To = Import(From);
+ if (!To)
+ return;
+
+ if (DeclContext *FromDC = cast<DeclContext>(From)) {
+ ASTNodeImporter Importer(*this);
+ Importer.ImportDeclContext(FromDC, true);
+ }
+}
+
+DeclarationName ASTImporter::Import(DeclarationName FromName) {
+ if (!FromName)
+ return DeclarationName();
+
+ switch (FromName.getNameKind()) {
+ case DeclarationName::Identifier:
+ return Import(FromName.getAsIdentifierInfo());
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return Import(FromName.getObjCSelector());
+
+ case DeclarationName::CXXConstructorName: {
+ QualType T = Import(FromName.getCXXNameType());
+ if (T.isNull())
+ return DeclarationName();
+
+ return ToContext.DeclarationNames.getCXXConstructorName(
+ ToContext.getCanonicalType(T));
+ }
+
+ case DeclarationName::CXXDestructorName: {
+ QualType T = Import(FromName.getCXXNameType());
+ if (T.isNull())
+ return DeclarationName();
+
+ return ToContext.DeclarationNames.getCXXDestructorName(
+ ToContext.getCanonicalType(T));
+ }
+
+ case DeclarationName::CXXConversionFunctionName: {
+ QualType T = Import(FromName.getCXXNameType());
+ if (T.isNull())
+ return DeclarationName();
+
+ return ToContext.DeclarationNames.getCXXConversionFunctionName(
+ ToContext.getCanonicalType(T));
+ }
+
+ case DeclarationName::CXXOperatorName:
+ return ToContext.DeclarationNames.getCXXOperatorName(
+ FromName.getCXXOverloadedOperator());
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return ToContext.DeclarationNames.getCXXLiteralOperatorName(
+ Import(FromName.getCXXLiteralIdentifier()));
+
+ case DeclarationName::CXXUsingDirective:
+ // FIXME: STATICS!
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ // Silence bogus GCC warning
+ return DeclarationName();
+}
+
+IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
+ if (!FromId)
+ return 0;
+
+ return &ToContext.Idents.get(FromId->getName());
+}
+
+Selector ASTImporter::Import(Selector FromSel) {
+ if (FromSel.isNull())
+ return Selector();
+
+ llvm::SmallVector<IdentifierInfo *, 4> Idents;
+ Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
+ for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I)
+ Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I)));
+ return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
+}
+
+DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name,
+ DeclContext *DC,
+ unsigned IDNS,
+ NamedDecl **Decls,
+ unsigned NumDecls) {
+ return Name;
+}
+
+DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
+ return ToContext.getDiagnostics().Report(Loc, DiagID);
+}
+
+DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
+ return FromContext.getDiagnostics().Report(Loc, DiagID);
+}
+
+Decl *ASTImporter::Imported(Decl *From, Decl *To) {
+ ImportedDecls[From] = To;
+ return To;
+}
+
+bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) {
+ llvm::DenseMap<const Type *, const Type *>::iterator Pos
+ = ImportedTypes.find(From.getTypePtr());
+ if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
+ return true;
+
+ StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls);
+ return Ctx.IsStructurallyEquivalent(From, To);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
new file mode 100644
index 0000000..3ca7d4d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp
@@ -0,0 +1,22 @@
+//===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains out-of-line virtual methods for Attr classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Expr.h"
+using namespace clang;
+
+Attr::~Attr() { }
+
+#include "clang/AST/AttrImpl.inc"
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
new file mode 100644
index 0000000..943c43e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
@@ -0,0 +1,48 @@
+//===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ AST support. Concrete
+// subclasses of this implement AST support for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CXXABI_H
+#define LLVM_CLANG_AST_CXXABI_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+class ASTContext;
+class MemberPointerType;
+
+/// Implements C++ ABI-specific semantic analysis functions.
+class CXXABI {
+public:
+ virtual ~CXXABI();
+
+ /// Returns the size of a member pointer in multiples of the target
+ /// pointer size.
+ virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0;
+
+ /// 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.
+CXXABI *CreateARMCXXABI(ASTContext &Ctx);
+CXXABI *CreateItaniumCXXABI(ASTContext &Ctx);
+CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
new file mode 100644
index 0000000..ca9ec18
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -0,0 +1,715 @@
+//===------ CXXInheritance.cpp - C++ Inheritance ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides routines that help analyzing C++ inheritance hierarchies.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/DeclCXX.h"
+#include <algorithm>
+#include <set>
+
+using namespace clang;
+
+/// \brief Computes the set of declarations referenced by these base
+/// paths.
+void CXXBasePaths::ComputeDeclsFound() {
+ assert(NumDeclsFound == 0 && !DeclsFound &&
+ "Already computed the set of declarations");
+
+ std::set<NamedDecl *> Decls;
+ for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end();
+ Path != PathEnd; ++Path)
+ Decls.insert(*Path->Decls.first);
+
+ NumDeclsFound = Decls.size();
+ DeclsFound = new NamedDecl * [NumDeclsFound];
+ std::copy(Decls.begin(), Decls.end(), DeclsFound);
+}
+
+CXXBasePaths::decl_iterator CXXBasePaths::found_decls_begin() {
+ if (NumDeclsFound == 0)
+ ComputeDeclsFound();
+ return DeclsFound;
+}
+
+CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() {
+ if (NumDeclsFound == 0)
+ ComputeDeclsFound();
+ return DeclsFound + NumDeclsFound;
+}
+
+/// isAmbiguous - Determines whether the set of paths provided is
+/// ambiguous, i.e., there are two or more paths that refer to
+/// different base class subobjects of the same type. BaseType must be
+/// an unqualified, canonical class type.
+bool CXXBasePaths::isAmbiguous(CanQualType BaseType) {
+ BaseType = BaseType.getUnqualifiedType();
+ std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
+ return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
+}
+
+/// clear - Clear out all prior path information.
+void CXXBasePaths::clear() {
+ Paths.clear();
+ ClassSubobjects.clear();
+ ScratchPath.clear();
+ DetectedVirtual = 0;
+}
+
+/// @brief Swaps the contents of this CXXBasePaths structure with the
+/// contents of Other.
+void CXXBasePaths::swap(CXXBasePaths &Other) {
+ std::swap(Origin, Other.Origin);
+ Paths.swap(Other.Paths);
+ ClassSubobjects.swap(Other.ClassSubobjects);
+ std::swap(FindAmbiguities, Other.FindAmbiguities);
+ std::swap(RecordPaths, Other.RecordPaths);
+ std::swap(DetectVirtual, Other.DetectVirtual);
+ std::swap(DetectedVirtual, Other.DetectedVirtual);
+}
+
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
+ CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
+ /*DetectVirtual=*/false);
+ return isDerivedFrom(Base, Paths);
+}
+
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
+ CXXBasePaths &Paths) const {
+ if (getCanonicalDecl() == Base->getCanonicalDecl())
+ return false;
+
+ Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
+ return lookupInBases(&FindBaseClass,
+ const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()),
+ Paths);
+}
+
+bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const {
+ if (!getNumVBases())
+ return false;
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
+ /*DetectVirtual=*/false);
+
+ if (getCanonicalDecl() == Base->getCanonicalDecl())
+ return false;
+
+ Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
+ return lookupInBases(&FindVirtualBaseClass, Base->getCanonicalDecl(), Paths);
+}
+
+static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) {
+ // OpaqueTarget is a CXXRecordDecl*.
+ return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget;
+}
+
+bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
+ return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl());
+}
+
+bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
+ void *OpaqueData,
+ bool AllowShortCircuit) const {
+ llvm::SmallVector<const CXXRecordDecl*, 8> Queue;
+
+ const CXXRecordDecl *Record = this;
+ bool AllMatches = true;
+ while (true) {
+ for (CXXRecordDecl::base_class_const_iterator
+ I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
+ const RecordType *Ty = I->getType()->getAs<RecordType>();
+ if (!Ty) {
+ if (AllowShortCircuit) return false;
+ AllMatches = false;
+ continue;
+ }
+
+ CXXRecordDecl *Base =
+ cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
+ if (!Base) {
+ if (AllowShortCircuit) return false;
+ AllMatches = false;
+ continue;
+ }
+
+ Queue.push_back(Base);
+ if (!BaseMatches(Base, OpaqueData)) {
+ if (AllowShortCircuit) return false;
+ AllMatches = false;
+ continue;
+ }
+ }
+
+ if (Queue.empty()) break;
+ Record = Queue.back(); // not actually a queue.
+ Queue.pop_back();
+ }
+
+ return AllMatches;
+}
+
+bool CXXBasePaths::lookupInBases(ASTContext &Context,
+ const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback *BaseMatches,
+ void *UserData) {
+ bool FoundPath = false;
+
+ // The access of the path down to this record.
+ AccessSpecifier AccessToHere = ScratchPath.Access;
+ bool IsFirstStep = ScratchPath.empty();
+
+ for (CXXRecordDecl::base_class_const_iterator BaseSpec = Record->bases_begin(),
+ BaseSpecEnd = Record->bases_end();
+ BaseSpec != BaseSpecEnd;
+ ++BaseSpec) {
+ // Find the record of the base class subobjects for this type.
+ QualType BaseType = Context.getCanonicalType(BaseSpec->getType())
+ .getUnqualifiedType();
+
+ // C++ [temp.dep]p3:
+ // In the definition of a class template or a member of a class template,
+ // if a base class of the class template depends on a template-parameter,
+ // the base class scope is not examined during unqualified name lookup
+ // either at the point of definition of the class template or member or
+ // during an instantiation of the class tem- plate or member.
+ if (BaseType->isDependentType())
+ continue;
+
+ // Determine whether we need to visit this base class at all,
+ // updating the count of subobjects appropriately.
+ std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
+ bool VisitBase = true;
+ bool SetVirtual = false;
+ if (BaseSpec->isVirtual()) {
+ VisitBase = !Subobjects.first;
+ Subobjects.first = true;
+ if (isDetectingVirtual() && DetectedVirtual == 0) {
+ // If this is the first virtual we find, remember it. If it turns out
+ // there is no base path here, we'll reset it later.
+ DetectedVirtual = BaseType->getAs<RecordType>();
+ SetVirtual = true;
+ }
+ } else
+ ++Subobjects.second;
+
+ if (isRecordingPaths()) {
+ // Add this base specifier to the current path.
+ CXXBasePathElement Element;
+ Element.Base = &*BaseSpec;
+ Element.Class = Record;
+ if (BaseSpec->isVirtual())
+ Element.SubobjectNumber = 0;
+ else
+ Element.SubobjectNumber = Subobjects.second;
+ ScratchPath.push_back(Element);
+
+ // Calculate the "top-down" access to this base class.
+ // The spec actually describes this bottom-up, but top-down is
+ // equivalent because the definition works out as follows:
+ // 1. Write down the access along each step in the inheritance
+ // chain, followed by the access of the decl itself.
+ // For example, in
+ // class A { public: int foo; };
+ // class B : protected A {};
+ // class C : public B {};
+ // class D : private C {};
+ // we would write:
+ // private public protected public
+ // 2. If 'private' appears anywhere except far-left, access is denied.
+ // 3. Otherwise, overall access is determined by the most restrictive
+ // access in the sequence.
+ if (IsFirstStep)
+ ScratchPath.Access = BaseSpec->getAccessSpecifier();
+ else
+ ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
+ BaseSpec->getAccessSpecifier());
+ }
+
+ // Track whether there's a path involving this specific base.
+ bool FoundPathThroughBase = false;
+
+ if (BaseMatches(BaseSpec, ScratchPath, UserData)) {
+ // We've found a path that terminates at this base.
+ FoundPath = FoundPathThroughBase = true;
+ if (isRecordingPaths()) {
+ // We have a path. Make a copy of it before moving on.
+ Paths.push_back(ScratchPath);
+ } else if (!isFindingAmbiguities()) {
+ // We found a path and we don't care about ambiguities;
+ // return immediately.
+ return FoundPath;
+ }
+ } else if (VisitBase) {
+ CXXRecordDecl *BaseRecord
+ = cast<CXXRecordDecl>(BaseSpec->getType()->getAs<RecordType>()
+ ->getDecl());
+ if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
+ // C++ [class.member.lookup]p2:
+ // A member name f in one sub-object B hides a member name f in
+ // a sub-object A if A is a base class sub-object of B. Any
+ // declarations that are so hidden are eliminated from
+ // consideration.
+
+ // There is a path to a base class that meets the criteria. If we're
+ // not collecting paths or finding ambiguities, we're done.
+ FoundPath = FoundPathThroughBase = true;
+ if (!isFindingAmbiguities())
+ return FoundPath;
+ }
+ }
+
+ // Pop this base specifier off the current path (if we're
+ // collecting paths).
+ if (isRecordingPaths()) {
+ ScratchPath.pop_back();
+ }
+
+ // If we set a virtual earlier, and this isn't a path, forget it again.
+ if (SetVirtual && !FoundPathThroughBase) {
+ DetectedVirtual = 0;
+ }
+ }
+
+ // Reset the scratch path access.
+ ScratchPath.Access = AccessToHere;
+
+ return FoundPath;
+}
+
+bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
+ void *UserData,
+ CXXBasePaths &Paths) const {
+ // If we didn't find anything, report that.
+ if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData))
+ return false;
+
+ // If we're not recording paths or we won't ever find ambiguities,
+ // we're done.
+ if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
+ return true;
+
+ // C++ [class.member.lookup]p6:
+ // When virtual base classes are used, a hidden declaration can be
+ // reached along a path through the sub-object lattice that does
+ // not pass through the hiding declaration. This is not an
+ // ambiguity. The identical use with nonvirtual base classes is an
+ // ambiguity; in that case there is no unique instance of the name
+ // that hides all the others.
+ //
+ // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
+ // way to make it any faster.
+ for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end();
+ P != PEnd; /* increment in loop */) {
+ bool Hidden = false;
+
+ for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end();
+ PE != PEEnd && !Hidden; ++PE) {
+ if (PE->Base->isVirtual()) {
+ CXXRecordDecl *VBase = 0;
+ if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>())
+ VBase = cast<CXXRecordDecl>(Record->getDecl());
+ if (!VBase)
+ break;
+
+ // The declaration(s) we found along this path were found in a
+ // subobject of a virtual base. Check whether this virtual
+ // base is a subobject of any other path; if so, then the
+ // declaration in this path are hidden by that patch.
+ for (CXXBasePaths::paths_iterator HidingP = Paths.begin(),
+ HidingPEnd = Paths.end();
+ HidingP != HidingPEnd;
+ ++HidingP) {
+ CXXRecordDecl *HidingClass = 0;
+ if (const RecordType *Record
+ = HidingP->back().Base->getType()->getAs<RecordType>())
+ HidingClass = cast<CXXRecordDecl>(Record->getDecl());
+ if (!HidingClass)
+ break;
+
+ if (HidingClass->isVirtuallyDerivedFrom(VBase)) {
+ Hidden = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (Hidden)
+ P = Paths.Paths.erase(P);
+ else
+ ++P;
+ }
+
+ return true;
+}
+
+bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *BaseRecord) {
+ assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
+ "User data for FindBaseClass is not canonical!");
+ return Specifier->getType()->getAs<RecordType>()->getDecl()
+ ->getCanonicalDecl() == BaseRecord;
+}
+
+bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *BaseRecord) {
+ assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
+ "User data for FindBaseClass is not canonical!");
+ return Specifier->isVirtual() &&
+ Specifier->getType()->getAs<RecordType>()->getDecl()
+ ->getCanonicalDecl() == BaseRecord;
+}
+
+bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+ for (Path.Decls = BaseRecord->lookup(N);
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag))
+ return true;
+ }
+
+ return false;
+}
+
+bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member;
+ DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+ for (Path.Decls = BaseRecord->lookup(N);
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS))
+ return true;
+ }
+
+ return false;
+}
+
+bool CXXRecordDecl::
+FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+ for (Path.Decls = BaseRecord->lookup(N);
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ // FIXME: Refactor the "is it a nested-name-specifier?" check
+ if (isa<TypedefDecl>(*Path.Decls.first) ||
+ (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag))
+ return true;
+ }
+
+ return false;
+}
+
+void OverridingMethods::add(unsigned OverriddenSubobject,
+ UniqueVirtualMethod Overriding) {
+ llvm::SmallVector<UniqueVirtualMethod, 4> &SubobjectOverrides
+ = Overrides[OverriddenSubobject];
+ if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(),
+ Overriding) == SubobjectOverrides.end())
+ SubobjectOverrides.push_back(Overriding);
+}
+
+void OverridingMethods::add(const OverridingMethods &Other) {
+ for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) {
+ for (overriding_const_iterator M = I->second.begin(),
+ MEnd = I->second.end();
+ M != MEnd;
+ ++M)
+ add(I->first, *M);
+ }
+}
+
+void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) {
+ for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) {
+ I->second.clear();
+ I->second.push_back(Overriding);
+ }
+}
+
+
+namespace {
+ class FinalOverriderCollector {
+ /// \brief The number of subobjects of a given class type that
+ /// occur within the class hierarchy.
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
+
+ /// \brief Overriders for each virtual base subobject.
+ llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
+
+ CXXFinalOverriderMap FinalOverriders;
+
+ public:
+ ~FinalOverriderCollector();
+
+ void Collect(const CXXRecordDecl *RD, bool VirtualBase,
+ const CXXRecordDecl *InVirtualSubobject,
+ CXXFinalOverriderMap &Overriders);
+ };
+}
+
+void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
+ bool VirtualBase,
+ const CXXRecordDecl *InVirtualSubobject,
+ CXXFinalOverriderMap &Overriders) {
+ unsigned SubobjectNumber = 0;
+ if (!VirtualBase)
+ SubobjectNumber
+ = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())];
+
+ for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
+ BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) {
+ if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
+ const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (!BaseDecl->isPolymorphic())
+ continue;
+
+ if (Overriders.empty() && !Base->isVirtual()) {
+ // There are no other overriders of virtual member functions,
+ // so let the base class fill in our overriders for us.
+ Collect(BaseDecl, false, InVirtualSubobject, Overriders);
+ continue;
+ }
+
+ // Collect all of the overridders from the base class subobject
+ // and merge them into the set of overridders for this class.
+ // For virtual base classes, populate or use the cached virtual
+ // overrides so that we do not walk the virtual base class (and
+ // its base classes) more than once.
+ CXXFinalOverriderMap ComputedBaseOverriders;
+ CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders;
+ if (Base->isVirtual()) {
+ CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl];
+ if (!MyVirtualOverriders) {
+ MyVirtualOverriders = new CXXFinalOverriderMap;
+ Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
+ }
+
+ BaseOverriders = MyVirtualOverriders;
+ } else
+ Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
+
+ // Merge the overriders from this base class into our own set of
+ // overriders.
+ for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
+ OMEnd = BaseOverriders->end();
+ OM != OMEnd;
+ ++OM) {
+ const CXXMethodDecl *CanonOM
+ = cast<CXXMethodDecl>(OM->first->getCanonicalDecl());
+ Overriders[CanonOM].add(OM->second);
+ }
+ }
+ }
+
+ for (CXXRecordDecl::method_iterator M = RD->method_begin(),
+ MEnd = RD->method_end();
+ M != MEnd;
+ ++M) {
+ // We only care about virtual methods.
+ if (!M->isVirtual())
+ continue;
+
+ CXXMethodDecl *CanonM = cast<CXXMethodDecl>(M->getCanonicalDecl());
+
+ if (CanonM->begin_overridden_methods()
+ == CanonM->end_overridden_methods()) {
+ // This is a new virtual function that does not override any
+ // other virtual function. Add it to the map of virtual
+ // functions for which we are tracking overridders.
+
+ // C++ [class.virtual]p2:
+ // For convenience we say that any virtual function overrides itself.
+ Overriders[CanonM].add(SubobjectNumber,
+ UniqueVirtualMethod(CanonM, SubobjectNumber,
+ InVirtualSubobject));
+ continue;
+ }
+
+ // This virtual method overrides other virtual methods, so it does
+ // not add any new slots into the set of overriders. Instead, we
+ // replace entries in the set of overriders with the new
+ // overrider. To do so, we dig down to the original virtual
+ // functions using data recursion and update all of the methods it
+ // overrides.
+ typedef std::pair<CXXMethodDecl::method_iterator,
+ CXXMethodDecl::method_iterator> OverriddenMethods;
+ llvm::SmallVector<OverriddenMethods, 4> Stack;
+ Stack.push_back(std::make_pair(CanonM->begin_overridden_methods(),
+ CanonM->end_overridden_methods()));
+ while (!Stack.empty()) {
+ OverriddenMethods OverMethods = Stack.back();
+ Stack.pop_back();
+
+ for (; OverMethods.first != OverMethods.second; ++OverMethods.first) {
+ const CXXMethodDecl *CanonOM
+ = cast<CXXMethodDecl>((*OverMethods.first)->getCanonicalDecl());
+
+ // C++ [class.virtual]p2:
+ // A virtual member function C::vf of a class object S is
+ // a final overrider unless the most derived class (1.8)
+ // of which S is a base class subobject (if any) declares
+ // or inherits another member function that overrides vf.
+ //
+ // Treating this object like the most derived class, we
+ // replace any overrides from base classes with this
+ // overriding virtual function.
+ Overriders[CanonOM].replaceAll(
+ UniqueVirtualMethod(CanonM, SubobjectNumber,
+ InVirtualSubobject));
+
+ if (CanonOM->begin_overridden_methods()
+ == CanonOM->end_overridden_methods())
+ continue;
+
+ // Continue recursion to the methods that this virtual method
+ // overrides.
+ Stack.push_back(std::make_pair(CanonOM->begin_overridden_methods(),
+ CanonOM->end_overridden_methods()));
+ }
+ }
+
+ // C++ [class.virtual]p2:
+ // For convenience we say that any virtual function overrides itself.
+ Overriders[CanonM].add(SubobjectNumber,
+ UniqueVirtualMethod(CanonM, SubobjectNumber,
+ InVirtualSubobject));
+ }
+}
+
+FinalOverriderCollector::~FinalOverriderCollector() {
+ for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
+ VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
+ VO != VOEnd;
+ ++VO)
+ delete VO->second;
+}
+
+void
+CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
+ FinalOverriderCollector Collector;
+ Collector.Collect(this, false, 0, FinalOverriders);
+
+ // Weed out any final overriders that come from virtual base class
+ // subobjects that were hidden by other subobjects along any path.
+ // This is the final-overrider variant of C++ [class.member.lookup]p10.
+ for (CXXFinalOverriderMap::iterator OM = FinalOverriders.begin(),
+ OMEnd = FinalOverriders.end();
+ OM != OMEnd;
+ ++OM) {
+ for (OverridingMethods::iterator SO = OM->second.begin(),
+ SOEnd = OM->second.end();
+ SO != SOEnd;
+ ++SO) {
+ llvm::SmallVector<UniqueVirtualMethod, 4> &Overriding = SO->second;
+ if (Overriding.size() < 2)
+ continue;
+
+ for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
+ Pos = Overriding.begin(), PosEnd = Overriding.end();
+ Pos != PosEnd;
+ /* increment in loop */) {
+ if (!Pos->InVirtualSubobject) {
+ ++Pos;
+ continue;
+ }
+
+ // We have an overriding method in a virtual base class
+ // subobject (or non-virtual base class subobject thereof);
+ // determine whether there exists an other overriding method
+ // in a base class subobject that hides the virtual base class
+ // subobject.
+ bool Hidden = false;
+ for (llvm::SmallVector<UniqueVirtualMethod, 4>::iterator
+ OP = Overriding.begin(), OPEnd = Overriding.end();
+ OP != OPEnd && !Hidden;
+ ++OP) {
+ if (Pos == OP)
+ continue;
+
+ if (OP->Method->getParent()->isVirtuallyDerivedFrom(
+ const_cast<CXXRecordDecl *>(Pos->InVirtualSubobject)))
+ Hidden = true;
+ }
+
+ if (Hidden) {
+ // The current overriding function is hidden by another
+ // overriding function; remove this one.
+ Pos = Overriding.erase(Pos);
+ PosEnd = Overriding.end();
+ } else {
+ ++Pos;
+ }
+ }
+ }
+ }
+}
+
+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<CXXRecordDecl>(I->getType()->getAs<RecordType>()->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<CXXRecordDecl>(I->getType()->getAs<RecordType>()->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/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
new file mode 100644
index 0000000..56db8c7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -0,0 +1,2265 @@
+//===--- Decl.cpp - Declaration AST Node Implementation -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Decl subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/Stmt.h"
+#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"
+#include "llvm/Support/ErrorHandling.h"
+
+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<VarDecl>(d))
+ return var->getMostRecentDeclaration()->getAttr<VisibilityAttr>();
+
+ // Use the most recent declaration of a function, and also handle
+ // function template specializations.
+ if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(d)) {
+ if (const VisibilityAttr *attr
+ = fn->getMostRecentDeclaration()->getAttr<VisibilityAttr>())
+ 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<VisibilityAttr>();
+
+ return 0;
+ }
+
+ // Otherwise, just check the declaration itself first.
+ if (const VisibilityAttr *attr = d->getAttr<VisibilityAttr>())
+ 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<ClassTemplateSpecializationDecl>(d))
+ return spec->getSpecializedTemplate()->getTemplatedDecl()
+ ->getAttr<VisibilityAttr>();
+
+ 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<Linkage,Visibility> LVPair;
+
+static LVPair merge(LVPair L, LVPair R) {
+ return LVPair(minLinkage(L.first, R.first),
+ minVisibility(L.second, R.second));
+}
+
+static LVPair merge(LVPair L, LinkageInfo R) {
+ return LVPair(minLinkage(L.first, R.linkage()),
+ minVisibility(L.second, R.visibility()));
+}
+
+namespace {
+/// Flags controlling the computation of linkage and visibility.
+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 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<NonTypeTemplateParmDecl>(*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()) {
+ LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
+ continue;
+ }
+ }
+
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(*P)) {
+ LV = merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters()));
+ }
+ }
+
+ 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 LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs,
+ LVFlags &F) {
+ LVPair LV(ExternalLinkage, DefaultVisibility);
+
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ switch (Args[I].getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Expression:
+ break;
+
+ case TemplateArgument::Type:
+ LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility());
+ break;
+
+ case TemplateArgument::Declaration:
+ // 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<NamedDecl>(D))
+ LV = merge(LV, getLVForDecl(ND, F));
+ }
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (TemplateDecl *Template
+ = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
+ LV = merge(LV, getLVForDecl(Template, F));
+ break;
+
+ case TemplateArgument::Pack:
+ LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
+ Args[I].pack_size(),
+ F));
+ break;
+ }
+ }
+
+ return LV;
+}
+
+static LVPair
+getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
+ LVFlags &F) {
+ return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
+}
+
+static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
+ assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
+ "Not a name having namespace scope");
+ ASTContext &Context = D->getASTContext();
+
+ // C++ [basic.link]p3:
+ // A name having namespace scope (3.3.6) has internal linkage if it
+ // is the name of
+ // - an object, reference, function or function template that is
+ // explicitly declared static; or,
+ // (This bullet corresponds to C99 6.2.2p3.)
+ if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ // Explicitly declared static.
+ if (Var->getStorageClass() == SC_Static)
+ return LinkageInfo::internal();
+
+ // - an object or reference that is explicitly declared const
+ // and neither explicitly declared extern nor previously
+ // declared to have external linkage; or
+ // (there is no equivalent in C99)
+ if (Context.getLangOptions().CPlusPlus &&
+ Var->getType().isConstant(Context) &&
+ Var->getStorageClass() != SC_Extern &&
+ Var->getStorageClass() != SC_PrivateExtern) {
+ bool FoundExtern = false;
+ for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
+ PrevVar && !FoundExtern;
+ PrevVar = PrevVar->getPreviousDeclaration())
+ if (isExternalLinkage(PrevVar->getLinkage()))
+ FoundExtern = true;
+
+ if (!FoundExtern)
+ return LinkageInfo::internal();
+ }
+ } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
+ // C++ [temp]p4:
+ // A non-member function template can have internal linkage; any
+ // other template name shall have external linkage.
+ const FunctionDecl *Function = 0;
+ if (const FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>(D))
+ Function = FunTmpl->getTemplatedDecl();
+ else
+ Function = cast<FunctionDecl>(D);
+
+ // Explicitly declared static.
+ if (Function->getStorageClass() == SC_Static)
+ return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
+ // - a data member of an anonymous union.
+ if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
+ 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<TranslationUnitDecl>(DC);
+ DC = DC->getParent()) {
+ if (!isa<NamespaceDecl>(DC)) continue;
+ if (const VisibilityAttr *VA =
+ cast<NamespaceDecl>(DC)->getAttr<VisibilityAttr>()) {
+ 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<VarDecl>(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
+ // identifier is visible, if the prior declaration specifies
+ // internal or external linkage, the linkage of the identifier
+ // at the later declaration is the same as the linkage
+ // specified at the prior declaration. If no prior declaration
+ // is visible, or if the prior declaration specifies no
+ // linkage, then the identifier has external linkage.
+ if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
+ LinkageInfo PrevLV = getLVForDecl(PrevVar, F);
+ if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
+ LV.mergeVisibility(PrevLV);
+ }
+ }
+
+ // - a function, unless it has internal linkage; or
+ } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(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.
+
+ if (Function->getStorageClass() == SC_PrivateExtern)
+ LV.setVisibility(HiddenVisibility, true);
+
+ // C99 6.2.2p5:
+ // If the declaration of an identifier for a function has no
+ // storage-class specifier, its linkage is determined exactly
+ // as if it were declared with the storage-class specifier
+ // extern.
+ if (!Context.getLangOptions().CPlusPlus &&
+ (Function->getStorageClass() == SC_Extern ||
+ Function->getStorageClass() == SC_PrivateExtern ||
+ Function->getStorageClass() == SC_None)) {
+ // C99 6.2.2p4:
+ // For an identifier declared with the storage-class specifier
+ // extern in a scope in which a prior declaration of that
+ // identifier is visible, if the prior declaration specifies
+ // internal or external linkage, the linkage of the identifier
+ // at the later declaration is the same as the linkage
+ // specified at the prior declaration. If no prior declaration
+ // is visible, or if the prior declaration specifies no
+ // linkage, then the identifier has external linkage.
+ if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
+ LinkageInfo PrevLV = getLVForDecl(PrevFunc, F);
+ if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
+ LV.mergeVisibility(PrevLV);
+ }
+ }
+
+ // 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()) {
+ LV.merge(getLVForDecl(SpecInfo->getTemplate(),
+ F.onlyTemplateVisibility()));
+ const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
+ LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ }
+
+ // - 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
+ } else if (const TagDecl *Tag = dyn_cast<TagDecl>(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<ClassTemplateSpecializationDecl>(Tag)) {
+ // From the template.
+ LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
+ F.onlyTemplateVisibility()));
+
+ // 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;
+ } else if (isa<EnumConstantDecl>(D)) {
+ LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(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);
+ } else if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+ LV.merge(getLVForTemplateParameterList(Template->getTemplateParameters()));
+
+ // - a namespace (7.3), unless it is declared within an unnamed
+ // namespace.
+ } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
+ return LV;
+
+ // By extension, we assign external linkage to Objective-C
+ // interfaces.
+ } else if (isa<ObjCInterfaceDecl>(D)) {
+ // fallout
+
+ // 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 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<CXXMethodDecl>(D) ||
+ isa<VarDecl>(D) ||
+ isa<FieldDecl>(D) ||
+ (isa<TagDecl>(D) &&
+ (D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
+ return LinkageInfo::none();
+
+ LinkageInfo LV;
+
+ // 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<RecordDecl>(D->getDeclContext()), ClassF));
+ if (!isExternalLinkage(LV.linkage()))
+ return LinkageInfo::none();
+
+ // If the class already has unique-external linkage, we can't improve.
+ if (LV.linkage() == UniqueExternalLinkage)
+ return LinkageInfo::uniqueExternal();
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ // 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()) {
+ 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<CXXRecordDecl>(D)) {
+ if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ // Merge template argument/parameter information for member
+ // class template specializations.
+ LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));
+ LV.merge(getLVForTemplateParameterList(
+ Spec->getSpecializedTemplate()->getTemplateParameters()));
+ }
+
+ // Static data members.
+ } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // Modify the variable's linkage by its type, but ignore the
+ // type's visibility unless it's a definition.
+ LVPair TypeLV = VD->getType()->getLinkageAndVisibility();
+ if (TypeLV.first != ExternalLinkage)
+ LV.mergeLinkage(UniqueExternalLinkage);
+ if (!LV.visibilityExplicit())
+ LV.mergeVisibility(TypeLV.second);
+ }
+
+ F.ConsiderGlobalVisibility &= !LV.visibilityExplicit();
+
+ // Apply -fvisibility if desired.
+ if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) {
+ LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode());
+ }
+
+ 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<NamedDecl>(child))
+ cast<NamedDecl>(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<CXXRecordDecl>(this))
+ clearLinkageForClass(record);
+
+ if (ClassTemplateDecl *temp =
+ dyn_cast<ClassTemplateDecl>(const_cast<NamedDecl*>(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<FunctionTemplateDecl>(const_cast<NamedDecl*>(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 (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::ObjCCompatibleAlias:
+ case Decl::ObjCForwardProtocol:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCMethod:
+ case Decl::ObjCProperty:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCProtocol:
+ return LinkageInfo::external();
+ }
+
+ // Handle linkage for namespace-scope names.
+ if (D->getDeclContext()->getRedeclContext()->isFileContext())
+ return getLVForNamespaceScopeDecl(D, Flags);
+
+ // C++ [basic.link]p5:
+ // In addition, a member function, static data member, a named
+ // class or enumeration of class scope, or an unnamed class or
+ // enumeration defined in a class-scope typedef declaration such
+ // 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 (D->getDeclContext()->isRecord())
+ return getLVForClassMember(D, Flags);
+
+ // C++ [basic.link]p6:
+ // The name of a function declared in block scope and the name of
+ // an object declared by a block scope extern declaration have
+ // linkage. If there is a visible declaration of an entity with
+ // linkage having the same name and type, ignoring entities
+ // declared outside the innermost enclosing namespace scope, the
+ // block scope declaration declares that same entity and receives
+ // the linkage of the previous declaration. If there is more than
+ // one such matching entity, the program is ill-formed. Otherwise,
+ // if no matching entity is found, the block scope entity receives
+ // external linkage.
+ if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ if (Function->isInAnonymousNamespace())
+ return LinkageInfo::uniqueExternal();
+
+ 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<VarDecl>(D))
+ if (Var->getStorageClass() == SC_Extern ||
+ Var->getStorageClass() == SC_PrivateExtern) {
+ if (Var->isInAnonymousNamespace())
+ 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 LV;
+ }
+ }
+
+ // C++ [basic.link]p6:
+ // Names not covered by these rules have no linkage.
+ return LinkageInfo::none();
+}
+
+std::string NamedDecl::getQualifiedNameAsString() const {
+ return getQualifiedNameAsString(getASTContext().getLangOptions());
+}
+
+std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
+ const DeclContext *Ctx = getDeclContext();
+
+ if (Ctx->isFunctionOrMethod())
+ return getNameAsString();
+
+ typedef llvm::SmallVector<const DeclContext *, 8> ContextsTy;
+ ContextsTy Contexts;
+
+ // Collect contexts.
+ while (Ctx && isa<NamedDecl>(Ctx)) {
+ Contexts.push_back(Ctx);
+ Ctx = Ctx->getParent();
+ };
+
+ std::string QualName;
+ llvm::raw_string_ostream OS(QualName);
+
+ for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend();
+ I != E; ++I) {
+ if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(*I)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.data(),
+ TemplateArgs.size(),
+ P);
+ OS << Spec->getName() << TemplateArgsStr;
+ } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) {
+ if (ND->isAnonymousNamespace())
+ OS << "<anonymous namespace>";
+ else
+ OS << ND;
+ } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) {
+ if (!RD->getIdentifier())
+ OS << "<anonymous " << RD->getKindName() << '>';
+ else
+ OS << RD;
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ const FunctionProtoType *FT = 0;
+ if (FD->hasWrittenPrototype())
+ FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
+
+ OS << FD << '(';
+ if (FT) {
+ unsigned NumParams = FD->getNumParams();
+ for (unsigned i = 0; i < NumParams; ++i) {
+ if (i)
+ OS << ", ";
+ std::string Param;
+ FD->getParamDecl(i)->getType().getAsStringInternal(Param, P);
+ OS << Param;
+ }
+
+ if (FT->isVariadic()) {
+ if (NumParams > 0)
+ OS << ", ";
+ OS << "...";
+ }
+ }
+ OS << ')';
+ } else {
+ OS << cast<NamedDecl>(*I);
+ }
+ OS << "::";
+ }
+
+ if (getDeclName())
+ OS << this;
+ else
+ OS << "<anonymous>";
+
+ return OS.str();
+}
+
+bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
+ assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
+
+ // UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
+ // We want to keep it, unless it nominates same namespace.
+ if (getKind() == Decl::UsingDirective) {
+ return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
+ }
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
+ // For function declarations, we keep track of redeclarations.
+ return FD->getPreviousDeclaration() == OldD;
+
+ // For function templates, the underlying function declarations are linked.
+ if (const FunctionTemplateDecl *FunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(this))
+ if (const FunctionTemplateDecl *OldFunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(OldD))
+ return FunctionTemplate->getTemplatedDecl()
+ ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl());
+
+ // For method declarations, we keep track of redeclarations.
+ if (isa<ObjCMethodDecl>(this))
+ return false;
+
+ if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
+ return true;
+
+ if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
+ return cast<UsingShadowDecl>(this)->getTargetDecl() ==
+ cast<UsingShadowDecl>(OldD)->getTargetDecl();
+
+ if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD))
+ return cast<UsingDecl>(this)->getTargetNestedNameDecl() ==
+ cast<UsingDecl>(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.
+ return this->getKind() == OldD->getKind();
+}
+
+bool NamedDecl::hasLinkage() const {
+ return getLinkage() != NoLinkage;
+}
+
+NamedDecl *NamedDecl::getUnderlyingDecl() {
+ NamedDecl *ND = this;
+ while (true) {
+ if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
+ ND = UD->getTargetDecl();
+ else if (ObjCCompatibleAliasDecl *AD
+ = dyn_cast<ObjCCompatibleAliasDecl>(ND))
+ return AD->getClassInterface();
+ else
+ return ND;
+ }
+}
+
+bool NamedDecl::isCXXInstanceMember() const {
+ assert(isCXXClassMember() &&
+ "checking whether non-member is instance member");
+
+ const NamedDecl *D = this;
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
+ return true;
+ if (isa<CXXMethodDecl>(D))
+ return cast<CXXMethodDecl>(D)->isInstance();
+ if (isa<FunctionTemplateDecl>(D))
+ return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D)
+ ->getTemplatedDecl())->isInstance();
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// DeclaratorDecl Implementation
+//===----------------------------------------------------------------------===//
+
+template <typename DeclT>
+static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
+ if (decl->getNumTemplateParameterLists() > 0)
+ return decl->getTemplateParameterList(0)->getTemplateLoc();
+ else
+ return decl->getInnerLocStart();
+}
+
+SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
+ TypeSourceInfo *TSI = getTypeSourceInfo();
+ if (TSI) return TSI->getTypeLoc().getBeginLoc();
+ return SourceLocation();
+}
+
+void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange) {
+ if (Qualifier) {
+ // Make sure the extended decl info is allocated.
+ if (!hasExtInfo()) {
+ // Save (non-extended) type source info pointer.
+ TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+ // Allocate external info struct.
+ DeclInfo = new (getASTContext()) ExtInfo;
+ // Restore savedTInfo into (extended) decl info.
+ getExtInfo()->TInfo = savedTInfo;
+ }
+ // Set qualifier info.
+ getExtInfo()->NNS = Qualifier;
+ getExtInfo()->NNSRange = QualifierRange;
+ }
+ else {
+ // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
+ assert(QualifierRange.isInvalid());
+ if (hasExtInfo()) {
+ // Save type source info pointer.
+ TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
+ // Deallocate the extended decl info.
+ getASTContext().Deallocate(getExtInfo());
+ // Restore savedTInfo into (non-extended) decl info.
+ DeclInfo = savedTInfo;
+ }
+ }
+}
+
+SourceLocation DeclaratorDecl::getOuterLocStart() const {
+ return getTemplateOrInnerLocStart(this);
+}
+
+void
+QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
+ unsigned NumTPLists,
+ TemplateParameterList **TPLists) {
+ assert((NumTPLists == 0 || TPLists != 0) &&
+ "Empty array of template parameters with positive size!");
+ assert((NumTPLists == 0 || NNS) &&
+ "Nonempty array of template parameters with no qualifier!");
+
+ // Free previous template parameters (if any).
+ if (NumTemplParamLists > 0) {
+ Context.Deallocate(TemplParamLists);
+ TemplParamLists = 0;
+ NumTemplParamLists = 0;
+ }
+ // Set info on matched template parameter lists (if any).
+ if (NumTPLists > 0) {
+ TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
+ NumTemplParamLists = NumTPLists;
+ for (unsigned i = NumTPLists; i-- > 0; )
+ TemplParamLists[i] = TPLists[i];
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// VarDecl Implementation
+//===----------------------------------------------------------------------===//
+
+const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
+ switch (SC) {
+ case SC_None: break;
+ case SC_Auto: return "auto"; break;
+ case SC_Extern: return "extern"; break;
+ case SC_PrivateExtern: return "__private_extern__"; break;
+ case SC_Register: return "register"; break;
+ case SC_Static: return "static"; break;
+ }
+
+ assert(0 && "Invalid storage class");
+ return 0;
+}
+
+VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten) {
+ 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())
+ Start = getLocation();
+ return Start;
+}
+
+SourceRange VarDecl::getSourceRange() const {
+ if (getInit())
+ return SourceRange(getOuterLocStart(), getInit()->getLocEnd());
+ return SourceRange(getOuterLocStart(), getLocation());
+}
+
+bool VarDecl::isExternC() const {
+ ASTContext &Context = getASTContext();
+ if (!Context.getLangOptions().CPlusPlus)
+ return (getDeclContext()->isTranslationUnit() &&
+ getStorageClass() != SC_Static) ||
+ (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
+
+ for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
+ DC = DC->getParent()) {
+ if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
+ if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
+ return getStorageClass() != SC_Static;
+
+ break;
+ }
+
+ if (DC->isFunctionOrMethod())
+ return false;
+ }
+
+ return false;
+}
+
+VarDecl *VarDecl::getCanonicalDecl() {
+ return getFirstDeclaration();
+}
+
+VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
+ // C++ [basic.def]p2:
+ // A declaration is a definition unless [...] it contains the 'extern'
+ // specifier or a linkage-specification and neither an initializer [...],
+ // it declares a static data member in a class declaration [...].
+ // C++ [temp.expl.spec]p15:
+ // An explicit specialization of a static data member of a template is a
+ // definition if the declaration includes an initializer; otherwise, it is
+ // a declaration.
+ if (isStaticDataMember()) {
+ if (isOutOfLine() && (hasInit() ||
+ getTemplateSpecializationKind() != TSK_ExplicitSpecialization))
+ return Definition;
+ else
+ return DeclarationOnly;
+ }
+ // C99 6.7p5:
+ // A definition of an identifier is a declaration for that identifier that
+ // [...] causes storage to be reserved for that object.
+ // Note: that applies for all non-file-scope objects.
+ // C99 6.9.2p1:
+ // If the declaration of an identifier for an object has file scope and an
+ // initializer, the declaration is an external definition for the identifier
+ if (hasInit())
+ return Definition;
+ // AST for 'extern "C" int foo;' is annotated with 'extern'.
+ if (hasExternalStorage())
+ return DeclarationOnly;
+
+ if (getStorageClassAsWritten() == SC_Extern ||
+ getStorageClassAsWritten() == SC_PrivateExtern) {
+ for (const VarDecl *PrevVar = getPreviousDeclaration();
+ PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
+ if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
+ return DeclarationOnly;
+ }
+ }
+ // C99 6.9.2p2:
+ // A declaration of an object that has file scope without an initializer,
+ // and without a storage class specifier or the scs 'static', constitutes
+ // a tentative definition.
+ // No such thing in C++.
+ if (!getASTContext().getLangOptions().CPlusPlus && isFileVarDecl())
+ return TentativeDefinition;
+
+ // What's left is (in C, block-scope) declarations without initializers or
+ // external storage. These are definitions.
+ return Definition;
+}
+
+VarDecl *VarDecl::getActingDefinition() {
+ DefinitionKind Kind = isThisDeclarationADefinition();
+ if (Kind != TentativeDefinition)
+ return 0;
+
+ VarDecl *LastTentative = 0;
+ VarDecl *First = getFirstDeclaration();
+ for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
+ I != E; ++I) {
+ Kind = (*I)->isThisDeclarationADefinition();
+ if (Kind == Definition)
+ return 0;
+ else if (Kind == TentativeDefinition)
+ LastTentative = *I;
+ }
+ return LastTentative;
+}
+
+bool VarDecl::isTentativeDefinitionNow() const {
+ DefinitionKind Kind = isThisDeclarationADefinition();
+ if (Kind != TentativeDefinition)
+ return false;
+
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if ((*I)->isThisDeclarationADefinition() == Definition)
+ return false;
+ }
+ return true;
+}
+
+VarDecl *VarDecl::getDefinition() {
+ VarDecl *First = getFirstDeclaration();
+ for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
+ I != E; ++I) {
+ if ((*I)->isThisDeclarationADefinition() == Definition)
+ return *I;
+ }
+ 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())
+ ++I;
+
+ if (I != E) {
+ D = *I;
+ return I->getInit();
+ }
+ return 0;
+}
+
+bool VarDecl::isOutOfLine() const {
+ if (Decl::isOutOfLine())
+ return true;
+
+ if (!isStaticDataMember())
+ return false;
+
+ // If this static data member was instantiated from a static data member of
+ // a class template, check whether that static data member was defined
+ // out-of-line.
+ if (VarDecl *VD = getInstantiatedFromStaticDataMember())
+ return VD->isOutOfLine();
+
+ return false;
+}
+
+VarDecl *VarDecl::getOutOfLineDefinition() {
+ if (!isStaticDataMember())
+ return 0;
+
+ for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
+ RD != RDEnd; ++RD) {
+ if (RD->getLexicalDeclContext()->isFileContext())
+ return *RD;
+ }
+
+ return 0;
+}
+
+void VarDecl::setInit(Expr *I) {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
+ Eval->~EvaluatedStmt();
+ getASTContext().Deallocate(Eval);
+ }
+
+ Init = I;
+}
+
+VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
+ if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
+ return cast<VarDecl>(MSI->getInstantiatedFrom());
+
+ return 0;
+}
+
+TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
+ if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
+ return MSI->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
+ return getASTContext().getInstantiatedFromStaticDataMember(this);
+}
+
+void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
+ MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
+ assert(MSI && "Not an instantiated static data member?");
+ MSI->setTemplateSpecializationKind(TSK);
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ MSI->getPointOfInstantiation().isInvalid())
+ MSI->setPointOfInstantiation(PointOfInstantiation);
+}
+
+//===----------------------------------------------------------------------===//
+// ParmVarDecl Implementation
+//===----------------------------------------------------------------------===//
+
+ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten,
+ Expr *DefArg) {
+ return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo,
+ S, SCAsWritten, DefArg);
+}
+
+Expr *ParmVarDecl::getDefaultArg() {
+ assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
+ assert(!hasUninstantiatedDefaultArg() &&
+ "Default argument is not yet instantiated!");
+
+ Expr *Arg = getInit();
+ if (ExprWithCleanups *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
+ return E->getSubExpr();
+
+ return Arg;
+}
+
+unsigned ParmVarDecl::getNumDefaultArgTemporaries() const {
+ if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(getInit()))
+ return E->getNumTemporaries();
+
+ return 0;
+}
+
+CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) {
+ assert(getNumDefaultArgTemporaries() &&
+ "Default arguments does not have any temporaries!");
+
+ ExprWithCleanups *E = cast<ExprWithCleanups>(getInit());
+ return E->getTemporary(i);
+}
+
+SourceRange ParmVarDecl::getDefaultArgRange() const {
+ if (const Expr *E = getInit())
+ return E->getSourceRange();
+
+ if (hasUninstantiatedDefaultArg())
+ return getUninstantiatedDefaultArg()->getSourceRange();
+
+ return SourceRange();
+}
+
+bool ParmVarDecl::isParameterPack() const {
+ return isa<PackExpansionType>(getType());
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void FunctionDecl::getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const {
+ NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
+ const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
+ if (TemplateArgs)
+ S += TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs->data(),
+ TemplateArgs->size(),
+ Policy);
+
+}
+
+bool FunctionDecl::isVariadic() const {
+ if (const FunctionProtoType *FT = getType()->getAs<FunctionProtoType>())
+ return FT->isVariadic();
+ return false;
+}
+
+bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->Body) {
+ Definition = *I;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if (I->Body) {
+ Definition = *I;
+ return I->Body.get(getASTContext().getExternalSource());
+ }
+ }
+
+ return 0;
+}
+
+void FunctionDecl::setBody(Stmt *B) {
+ Body = B;
+ if (B)
+ EndRangeLoc = B->getLocEnd();
+}
+
+void FunctionDecl::setPure(bool P) {
+ IsPure = P;
+ if (P)
+ if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
+ Parent->markedVirtualFunctionPure();
+}
+
+bool FunctionDecl::isMain() const {
+ ASTContext &Context = getASTContext();
+ return !Context.getLangOptions().Freestanding &&
+ getDeclContext()->getRedeclContext()->isTranslationUnit() &&
+ getIdentifier() && getIdentifier()->isStr("main");
+}
+
+bool FunctionDecl::isExternC() const {
+ ASTContext &Context = getASTContext();
+ // In C, any non-static, non-overloadable function has external
+ // linkage.
+ if (!Context.getLangOptions().CPlusPlus)
+ return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
+
+ for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
+ DC = DC->getParent()) {
+ if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
+ if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
+ return getStorageClass() != SC_Static &&
+ !getAttr<OverloadableAttr>();
+
+ break;
+ }
+
+ if (DC->isRecord())
+ break;
+ }
+
+ return isMain();
+}
+
+bool FunctionDecl::isGlobal() const {
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
+ return Method->isStatic();
+
+ if (getStorageClass() == SC_Static)
+ return false;
+
+ for (const DeclContext *DC = getDeclContext();
+ DC->isNamespace();
+ DC = DC->getParent()) {
+ if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
+ if (!Namespace->getDeclName())
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
+void
+FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
+ redeclarable_base::setPreviousDeclaration(PrevDecl);
+
+ if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
+ FunctionTemplateDecl *PrevFunTmpl
+ = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
+ assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
+ FunTmpl->setPreviousDeclaration(PrevFunTmpl);
+ }
+
+ if (PrevDecl->IsInline)
+ IsInline = true;
+}
+
+const FunctionDecl *FunctionDecl::getCanonicalDecl() const {
+ return getFirstDeclaration();
+}
+
+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.
+///
+/// The function corresponds to a built-in function if it is
+/// declared at translation scope or within an extern "C" block and
+/// its name matches with the name of a builtin. The returned value
+/// will be 0 for functions that do not correspond to a builtin, a
+/// value of type \c Builtin::ID if in the target-independent range
+/// \c [1,Builtin::First), or a target-specific builtin value.
+unsigned FunctionDecl::getBuiltinID() const {
+ ASTContext &Context = getASTContext();
+ if (!getIdentifier() || !getIdentifier()->getBuiltinID())
+ return 0;
+
+ unsigned BuiltinID = getIdentifier()->getBuiltinID();
+ if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return BuiltinID;
+
+ // This function has the name of a known C library
+ // function. Determine whether it actually refers to the C library
+ // function or whether it just has the same name.
+
+ // If this is a static function, it's not a builtin.
+ if (getStorageClass() == SC_Static)
+ return 0;
+
+ // If this function is at translation-unit scope and we're not in
+ // C++, it refers to the C library function.
+ if (!Context.getLangOptions().CPlusPlus &&
+ getDeclContext()->isTranslationUnit())
+ return BuiltinID;
+
+ // If the function is in an extern "C" linkage specification and is
+ // not marked "overloadable", it's the real function.
+ if (isa<LinkageSpecDecl>(getDeclContext()) &&
+ cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
+ == LinkageSpecDecl::lang_c &&
+ !getAttr<OverloadableAttr>())
+ return BuiltinID;
+
+ // Not a builtin
+ return 0;
+}
+
+
+/// getNumParams - Return the number of parameters this function must have
+/// 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<FunctionType>();
+ if (isa<FunctionNoProtoType>(FT))
+ return 0;
+ return cast<FunctionProtoType>(FT)->getNumArgs();
+
+}
+
+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 = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
+ ParamInfo = new (Mem) ParmVarDecl*[NumParams];
+ memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
+
+ // Update source range. The check below allows us to set EndRangeLoc before
+ // setting the parameters.
+ if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
+ EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
+ }
+}
+
+/// getMinRequiredArguments - Returns the minimum number of arguments
+/// needed to call this function. This may be fewer than the number of
+/// function parameters, if some of the parameters have default
+/// arguments (in C++) or the last parameter is a parameter pack.
+unsigned FunctionDecl::getMinRequiredArguments() const {
+ if (!getASTContext().getLangOptions().CPlusPlus)
+ 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 {
+ if (IsInline)
+ return true;
+
+ if (isa<CXXMethodDecl>(this)) {
+ if (!isOutOfLine() || getCanonicalDecl()->isInlineSpecified())
+ return true;
+ }
+
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ // Handle below.
+ break;
+ }
+
+ const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
+ bool HasPattern = false;
+ if (PatternDecl)
+ HasPattern = PatternDecl->hasBody(PatternDecl);
+
+ if (HasPattern && PatternDecl)
+ return PatternDecl->isInlined();
+
+ return false;
+}
+
+/// \brief For an inline function definition in C or C++, determine whether the
+/// definition will be externally visible.
+///
+/// Inline function definitions are always available for inlining optimizations.
+/// However, depending on the language dialect, declaration specifiers, and
+/// attributes, the definition of an inline function may or may not be
+/// "externally" visible to other translation units in the program.
+///
+/// In C99, inline definitions are not externally visible by default. However,
+/// if even one of the global-scope declarations is marked "extern inline", the
+/// inline definition becomes externally visible (C99 6.7.4p6).
+///
+/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
+/// definition, we use the GNU semantics for inline, which are nearly the
+/// opposite of C99 semantics. In particular, "inline" by itself will create
+/// an externally visible symbol, but "extern inline" will not create an
+/// externally visible symbol.
+bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
+ assert(isThisDeclarationADefinition() && "Must have the function definition");
+ assert(isInlined() && "Function must be inline");
+ ASTContext &Context = getASTContext();
+
+ if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
+ // 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->getStorageClassAsWritten() != SC_Extern)
+ return true;
+ }
+
+ return false;
+ }
+
+ // C99 6.7.4p6:
+ // [...] If all of the file scope declarations for a function in a
+ // translation unit include the inline function specifier without extern,
+ // then the definition in that translation unit is an inline definition.
+ for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
+ Redecl != RedeclEnd;
+ ++Redecl) {
+ // Only consider file-scope declarations in this test.
+ if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
+ continue;
+
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
+ return true; // Not an inline definition
+ }
+
+ // C99 6.7.4p6:
+ // An inline definition does not provide an external definition for the
+ // function, and does not forbid an external definition in another
+ // translation unit.
+ return false;
+}
+
+/// getOverloadedOperator - Which C++ overloaded operator this
+/// function represents, if any.
+OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
+ if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
+ return getDeclName().getCXXOverloadedOperator();
+ else
+ return OO_None;
+}
+
+/// getLiteralIdentifier - The literal suffix identifier this function
+/// represents, if any.
+const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
+ if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
+ return getDeclName().getCXXLiteralIdentifier();
+ else
+ return 0;
+}
+
+FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
+ if (TemplateOrSpecialization.isNull())
+ return TK_NonTemplate;
+ if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
+ return TK_FunctionTemplate;
+ if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
+ return TK_MemberSpecialization;
+ if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
+ return TK_FunctionTemplateSpecialization;
+ if (TemplateOrSpecialization.is
+ <DependentFunctionTemplateSpecializationInfo*>())
+ return TK_DependentFunctionTemplateSpecialization;
+
+ assert(false && "Did we miss a TemplateOrSpecialization type?");
+ return TK_NonTemplate;
+}
+
+FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
+ if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
+ return cast<FunctionDecl>(Info->getInstantiatedFrom());
+
+ return 0;
+}
+
+MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
+ return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+}
+
+void
+FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
+ FunctionDecl *FD,
+ TemplateSpecializationKind TSK) {
+ assert(TemplateOrSpecialization.isNull() &&
+ "Member function is already a specialization");
+ MemberSpecializationInfo *Info
+ = new (C) MemberSpecializationInfo(FD, TSK);
+ TemplateOrSpecialization = Info;
+}
+
+bool FunctionDecl::isImplicitlyInstantiable() const {
+ // If the function is invalid, it can't be implicitly instantiated.
+ if (isInvalidDecl())
+ return false;
+
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDefinition:
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ return true;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ // Handled below.
+ break;
+ }
+
+ // Find the actual template from which we will instantiate.
+ const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
+ bool HasPattern = false;
+ if (PatternDecl)
+ HasPattern = PatternDecl->hasBody(PatternDecl);
+
+ // C++0x [temp.explicit]p9:
+ // Except for inline functions, other explicit instantiation declarations
+ // have the effect of suppressing the implicit instantiation of the entity
+ // to which they refer.
+ if (!HasPattern || !PatternDecl)
+ return true;
+
+ return PatternDecl->isInlined();
+}
+
+FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
+ if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
+ while (Primary->getInstantiatedFromMemberTemplate()) {
+ // If we have hit a point where the user provided a specialization of
+ // this template, we're done looking.
+ if (Primary->isMemberSpecialization())
+ break;
+
+ Primary = Primary->getInstantiatedFromMemberTemplate();
+ }
+
+ return Primary->getTemplatedDecl();
+ }
+
+ return getInstantiatedFromMemberFunction();
+}
+
+FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
+ if (FunctionTemplateSpecializationInfo *Info
+ = TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
+ return Info->Template.getPointer();
+ }
+ return 0;
+}
+
+const TemplateArgumentList *
+FunctionDecl::getTemplateSpecializationArgs() const {
+ if (FunctionTemplateSpecializationInfo *Info
+ = TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
+ return Info->TemplateArguments;
+ }
+ return 0;
+}
+
+const TemplateArgumentListInfo *
+FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
+ if (FunctionTemplateSpecializationInfo *Info
+ = TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
+ return Info->TemplateArgumentsAsWritten;
+ }
+ return 0;
+}
+
+void
+FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation) {
+ assert(TSK != TSK_Undeclared &&
+ "Must specify the type of function template specialization");
+ FunctionTemplateSpecializationInfo *Info
+ = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
+ if (!Info)
+ Info = FunctionTemplateSpecializationInfo::Create(C, this, Template, TSK,
+ TemplateArgs,
+ TemplateArgsAsWritten,
+ PointOfInstantiation);
+ TemplateOrSpecialization = Info;
+
+ // Insert this function template specialization into the set of known
+ // function template specializations.
+ if (InsertPos)
+ Template->getSpecializations().InsertNode(Info, InsertPos);
+ else {
+ // Try to insert the new node. If there is an existing node, leave it, the
+ // set will contain the canonical decls while
+ // FunctionTemplateDecl::findSpecialization will return
+ // the most recent redeclarations.
+ FunctionTemplateSpecializationInfo *Existing
+ = Template->getSpecializations().GetOrInsertNode(Info);
+ (void)Existing;
+ assert((!Existing || Existing->Function->isCanonicalDecl()) &&
+ "Set is supposed to only contain canonical decls");
+ }
+}
+
+void
+FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
+ const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ assert(TemplateOrSpecialization.isNull());
+ size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo);
+ Size += Templates.size() * sizeof(FunctionTemplateDecl*);
+ Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc);
+ void *Buffer = Context.Allocate(Size);
+ DependentFunctionTemplateSpecializationInfo *Info =
+ new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates,
+ TemplateArgs);
+ TemplateOrSpecialization = Info;
+}
+
+DependentFunctionTemplateSpecializationInfo::
+DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
+ const TemplateArgumentListInfo &TArgs)
+ : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
+
+ d.NumTemplates = Ts.size();
+ d.NumArgs = TArgs.size();
+
+ FunctionTemplateDecl **TsArray =
+ const_cast<FunctionTemplateDecl**>(getTemplates());
+ for (unsigned I = 0, E = Ts.size(); I != E; ++I)
+ TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
+
+ TemplateArgumentLoc *ArgsArray =
+ const_cast<TemplateArgumentLoc*>(getTemplateArgs());
+ for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
+ new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
+}
+
+TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
+ // For a function template specialization, query the specialization
+ // information object.
+ FunctionTemplateSpecializationInfo *FTSInfo
+ = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
+ if (FTSInfo)
+ return FTSInfo->getTemplateSpecializationKind();
+
+ MemberSpecializationInfo *MSInfo
+ = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+ if (MSInfo)
+ return MSInfo->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+void
+FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
+ if (FunctionTemplateSpecializationInfo *FTSInfo
+ = TemplateOrSpecialization.dyn_cast<
+ FunctionTemplateSpecializationInfo*>()) {
+ FTSInfo->setTemplateSpecializationKind(TSK);
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ FTSInfo->getPointOfInstantiation().isInvalid())
+ FTSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else if (MemberSpecializationInfo *MSInfo
+ = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else
+ assert(false && "Function cannot have a template specialization kind");
+}
+
+SourceLocation FunctionDecl::getPointOfInstantiation() const {
+ if (FunctionTemplateSpecializationInfo *FTSInfo
+ = TemplateOrSpecialization.dyn_cast<
+ FunctionTemplateSpecializationInfo*>())
+ return FTSInfo->getPointOfInstantiation();
+ else if (MemberSpecializationInfo *MSInfo
+ = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+ return MSInfo->getPointOfInstantiation();
+
+ return SourceLocation();
+}
+
+bool FunctionDecl::isOutOfLine() const {
+ if (Decl::isOutOfLine())
+ return true;
+
+ // If this function was instantiated from a member function of a
+ // class template, check whether that member function was defined out-of-line.
+ if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
+ const FunctionDecl *Definition;
+ if (FD->hasBody(Definition))
+ return Definition->isOutOfLine();
+ }
+
+ // If this function was instantiated from a function template,
+ // check whether that function template was defined out-of-line.
+ if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
+ const FunctionDecl *Definition;
+ if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
+ return Definition->isOutOfLine();
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// FieldDecl Implementation
+//===----------------------------------------------------------------------===//
+
+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);
+}
+
+bool FieldDecl::isAnonymousStructOrUnion() const {
+ if (!isImplicit() || getDeclName())
+ return false;
+
+ if (const RecordType *Record = getType()->getAs<RecordType>())
+ return Record->getDecl()->isAnonymousStructOrUnion();
+
+ 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
+//===----------------------------------------------------------------------===//
+
+SourceLocation TagDecl::getOuterLocStart() const {
+ return getTemplateOrInnerLocStart(this);
+}
+
+SourceRange TagDecl::getSourceRange() const {
+ SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
+ return SourceRange(getOuterLocStart(), E);
+}
+
+TagDecl* TagDecl::getCanonicalDecl() {
+ return getFirstDeclaration();
+}
+
+void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {
+ TypedefDeclOrQualifier = TDD;
+ if (TypeForDecl)
+ const_cast<Type*>(TypeForDecl)->ClearLinkageCache();
+ ClearLinkageCache();
+}
+
+void TagDecl::startDefinition() {
+ IsBeingDefined = true;
+
+ if (isa<CXXRecordDecl>(this)) {
+ CXXRecordDecl *D = cast<CXXRecordDecl>(this);
+ struct CXXRecordDecl::DefinitionData *Data =
+ new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
+ cast<CXXRecordDecl>(*I)->DefinitionData = Data;
+ }
+}
+
+void TagDecl::completeDefinition() {
+ assert((!isa<CXXRecordDecl>(this) ||
+ cast<CXXRecordDecl>(this)->hasDefinition()) &&
+ "definition completed but not started");
+
+ IsDefinition = true;
+ IsBeingDefined = false;
+
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->CompletedTagDefinition(this);
+}
+
+TagDecl* TagDecl::getDefinition() const {
+ if (isDefinition())
+ return const_cast<TagDecl *>(this);
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this))
+ return CXXRD->getDefinition();
+
+ for (redecl_iterator R = redecls_begin(), REnd = redecls_end();
+ R != REnd; ++R)
+ if (R->isDefinition())
+ return *R;
+
+ return 0;
+}
+
+void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange) {
+ if (Qualifier) {
+ // Make sure the extended qualifier info is allocated.
+ if (!hasExtInfo())
+ TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
+ // Set qualifier info.
+ getExtInfo()->NNS = Qualifier;
+ getExtInfo()->NNSRange = QualifierRange;
+ }
+ else {
+ // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
+ assert(QualifierRange.isInvalid());
+ if (hasExtInfo()) {
+ getASTContext().Deallocate(getExtInfo());
+ TypedefDeclOrQualifier = (TypedefDecl*) 0;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// EnumDecl Implementation
+//===----------------------------------------------------------------------===//
+
+EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, SourceLocation 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(),
+ false, false, false);
+}
+
+void EnumDecl::completeDefinition(QualType NewType,
+ QualType NewPromotionType,
+ unsigned NumPositiveBits,
+ unsigned NumNegativeBits) {
+ assert(!isDefinition() && "Cannot redefine enums!");
+ if (!IntegerType)
+ IntegerType = NewType.getTypePtr();
+ PromotionType = NewPromotionType;
+ setNumPositiveBits(NumPositiveBits);
+ setNumNegativeBits(NumNegativeBits);
+ TagDecl::completeDefinition();
+}
+
+//===----------------------------------------------------------------------===//
+// RecordDecl Implementation
+//===----------------------------------------------------------------------===//
+
+RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, RecordDecl *PrevDecl,
+ SourceLocation TKL)
+ : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) {
+ HasFlexibleArrayMember = false;
+ AnonymousStructOrUnion = false;
+ HasObjectMember = false;
+ LoadedFieldsFromExternalStorage = false;
+ assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
+}
+
+RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ SourceLocation TKL, RecordDecl* PrevDecl) {
+
+ RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL);
+ C.getTypeDeclType(R, PrevDecl);
+ return R;
+}
+
+RecordDecl *RecordDecl::Create(const ASTContext &C, EmptyShell Empty) {
+ return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), 0, 0,
+ SourceLocation());
+}
+
+bool RecordDecl::isInjectedClassName() const {
+ return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
+ cast<RecordDecl>(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() {
+ assert(!isDefinition() && "Cannot redefine record!");
+ TagDecl::completeDefinition();
+}
+
+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);
+
+ llvm::SmallVector<Decl*, 64> Decls;
+ if (Source->FindExternalLexicalDeclsBy<FieldDecl>(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<FieldDecl>(Decls[i]));
+#endif
+
+ LoadedFieldsFromExternalStorage = true;
+
+ if (Decls.empty())
+ return;
+
+ llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
+}
+
+//===----------------------------------------------------------------------===//
+// BlockDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void BlockDecl::setParams(ParmVarDecl **NewParamInfo,
+ unsigned NParms) {
+ assert(ParamInfo == 0 && "Already has param info!");
+
+ // Zero params -> null pointer.
+ if (NParms) {
+ NumParams = NParms;
+ void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams);
+ ParamInfo = new (Mem) ParmVarDecl*[NumParams];
+ memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*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<Capture*>(buffer);
+}
+
+SourceRange BlockDecl::getSourceRange() const {
+ return SourceRange(getLocation(), Body? Body->getLocEnd() : getLocation());
+}
+
+//===----------------------------------------------------------------------===//
+// Other Decl Allocation/Deallocation Method Implementations
+//===----------------------------------------------------------------------===//
+
+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<NamespaceDecl>(
+ 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);
+}
+
+FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, StorageClass SCAsWritten,
+ bool isInlineSpecified,
+ bool hasWrittenPrototype) {
+ FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo,
+ S, SCAsWritten, isInlineSpecified);
+ New->HasWrittenPrototype = hasWrittenPrototype;
+ return New;
+}
+
+BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
+ return new (C) BlockDecl(DC, L);
+}
+
+EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
+ SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ Expr *E, const llvm::APSInt &V) {
+ 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)
+ End = Init->getLocEnd();
+ return SourceRange(getLocation(), End);
+}
+
+TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ TypeSourceInfo *TInfo) {
+ return new (C) TypedefDecl(DC, L, Id, TInfo);
+}
+
+FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ StringLiteral *Str) {
+ return new (C) FileScopeAsmDecl(DC, L, Str);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
new file mode 100644
index 0000000..be379d5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -0,0 +1,1107 @@
+//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Decl and DeclContext classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DependentDiagnostic.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/ASTContext.h"
+#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 <algorithm>
+#include <cstdio>
+#include <vector>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Statistics
+//===----------------------------------------------------------------------===//
+
+#define DECL(DERIVED, BASE) static int n##DERIVED##s = 0;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+
+static bool StatSwitch = false;
+
+const char *Decl::getDeclKindName() const {
+ switch (DeclKind) {
+ default: assert(0 && "Declaration not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case DERIVED: return #DERIVED;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+}
+
+void Decl::setInvalidDecl(bool Invalid) {
+ InvalidDecl = Invalid;
+ if (Invalid) {
+ // Defensive maneuver for ill-formed code: we're likely not to make it to
+ // a point where we set the access specifier, so default it to "public"
+ // to avoid triggering asserts elsewhere in the front end.
+ setAccess(AS_public);
+ }
+}
+
+const char *DeclContext::getDeclKindName() const {
+ switch (DeclKind) {
+ default: assert(0 && "Declaration context not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+}
+
+bool Decl::CollectingStats(bool Enable) {
+ if (Enable) StatSwitch = true;
+ return StatSwitch;
+}
+
+void Decl::PrintStats() {
+ fprintf(stderr, "*** Decl Stats:\n");
+
+ int totalDecls = 0;
+#define DECL(DERIVED, BASE) totalDecls += n##DERIVED##s;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ fprintf(stderr, " %d decls total.\n", totalDecls);
+
+ int totalBytes = 0;
+#define DECL(DERIVED, BASE) \
+ if (n##DERIVED##s > 0) { \
+ totalBytes += (int)(n##DERIVED##s * sizeof(DERIVED##Decl)); \
+ fprintf(stderr, " %d " #DERIVED " decls, %d each (%d bytes)\n", \
+ n##DERIVED##s, (int)sizeof(DERIVED##Decl), \
+ (int)(n##DERIVED##s * sizeof(DERIVED##Decl))); \
+ }
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+
+ fprintf(stderr, "Total bytes = %d\n", totalBytes);
+}
+
+void Decl::add(Kind k) {
+ switch (k) {
+ default: assert(0 && "Declaration not in DeclNodes.inc!");
+#define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break;
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+}
+
+bool Decl::isTemplateParameterPack() const {
+ if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(this))
+ return TTP->isParameterPack();
+ if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(this))
+ return NTTP->isParameterPack();
+ if (const TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(this))
+ return TTP->isParameterPack();
+ return false;
+}
+
+bool Decl::isParameterPack() const {
+ if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(this))
+ return Parm->isParameterPack();
+
+ return isTemplateParameterPack();
+}
+
+bool Decl::isFunctionOrFunctionTemplate() const {
+ if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
+ return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
+
+ return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
+}
+
+bool Decl::isDefinedOutsideFunctionOrMethod() const {
+ for (const DeclContext *DC = getDeclContext();
+ DC && !DC->isTranslationUnit();
+ DC = DC->getParent())
+ if (DC->isFunctionOrMethod())
+ return false;
+
+ return true;
+}
+
+
+//===----------------------------------------------------------------------===//
+// PrettyStackTraceDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
+ SourceLocation TheLoc = Loc;
+ if (TheLoc.isInvalid() && TheDecl)
+ TheLoc = TheDecl->getLocation();
+
+ if (TheLoc.isValid()) {
+ TheLoc.print(OS, SM);
+ OS << ": ";
+ }
+
+ OS << Message;
+
+ if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
+ OS << " '" << DN->getQualifiedNameAsString() << '\'';
+ OS << '\n';
+}
+
+//===----------------------------------------------------------------------===//
+// Decl Implementation
+//===----------------------------------------------------------------------===//
+
+// Out-of-line virtual method providing a home for Decl.
+Decl::~Decl() { }
+
+void Decl::setDeclContext(DeclContext *DC) {
+ if (isOutOfSemaDC())
+ delete getMultipleDC();
+
+ DeclCtx = DC;
+}
+
+void Decl::setLexicalDeclContext(DeclContext *DC) {
+ if (DC == getLexicalDeclContext())
+ return;
+
+ if (isInSemaDC()) {
+ MultipleDC *MDC = new (getASTContext()) MultipleDC();
+ MDC->SemanticDC = getDeclContext();
+ MDC->LexicalDC = DC;
+ DeclCtx = MDC;
+ } else {
+ getMultipleDC()->LexicalDC = DC;
+ }
+}
+
+bool Decl::isInAnonymousNamespace() const {
+ const DeclContext *DC = getDeclContext();
+ do {
+ if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
+ if (ND->isAnonymousNamespace())
+ return true;
+ } while ((DC = DC->getParent()));
+
+ return false;
+}
+
+TranslationUnitDecl *Decl::getTranslationUnitDecl() {
+ if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this))
+ return TUD;
+
+ DeclContext *DC = getDeclContext();
+ assert(DC && "This decl is not contained in a translation unit!");
+
+ while (!DC->isTranslationUnit()) {
+ DC = DC->getParent();
+ assert(DC && "This decl is not contained in a translation unit!");
+ }
+
+ return cast<TranslationUnitDecl>(DC);
+}
+
+ASTContext &Decl::getASTContext() const {
+ return getTranslationUnitDecl()->getASTContext();
+}
+
+ASTMutationListener *Decl::getASTMutationListener() const {
+ return getASTContext().getASTMutationListener();
+}
+
+bool Decl::isUsed(bool CheckUsedAttr) const {
+ if (Used)
+ return true;
+
+ // Check for used attribute.
+ if (CheckUsedAttr && hasAttr<UsedAttr>())
+ return true;
+
+ // Check redeclarations for used attribute.
+ for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+ if ((CheckUsedAttr && I->hasAttr<UsedAttr>()) || I->Used)
+ return true;
+ }
+
+ return false;
+}
+
+
+unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
+ switch (DeclKind) {
+ case Function:
+ case CXXMethod:
+ case CXXConstructor:
+ case CXXDestructor:
+ case CXXConversion:
+ case EnumConstant:
+ case Var:
+ case ImplicitParam:
+ case ParmVar:
+ case NonTypeTemplateParm:
+ case ObjCMethod:
+ case ObjCProperty:
+ return IDNS_Ordinary;
+ case Label:
+ return IDNS_Label;
+ case IndirectField:
+ return IDNS_Ordinary | IDNS_Member;
+
+ case ObjCCompatibleAlias:
+ case ObjCInterface:
+ return IDNS_Ordinary | IDNS_Type;
+
+ case Typedef:
+ case UnresolvedUsingTypename:
+ case TemplateTypeParm:
+ return IDNS_Ordinary | IDNS_Type;
+
+ case UsingShadow:
+ return 0; // we'll actually overwrite this later
+
+ case UnresolvedUsingValue:
+ return IDNS_Ordinary | IDNS_Using;
+
+ case Using:
+ return IDNS_Using;
+
+ case ObjCProtocol:
+ return IDNS_ObjCProtocol;
+
+ case Field:
+ case ObjCAtDefsField:
+ case ObjCIvar:
+ return IDNS_Member;
+
+ case Record:
+ case CXXRecord:
+ case Enum:
+ return IDNS_Tag | IDNS_Type;
+
+ case Namespace:
+ case NamespaceAlias:
+ return IDNS_Namespace;
+
+ case FunctionTemplate:
+ return IDNS_Ordinary;
+
+ case ClassTemplate:
+ case TemplateTemplateParm:
+ return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
+
+ // Never have names.
+ case Friend:
+ case FriendTemplate:
+ case AccessSpec:
+ case LinkageSpec:
+ case FileScopeAsm:
+ case StaticAssert:
+ case ObjCClass:
+ case ObjCPropertyImpl:
+ case ObjCForwardProtocol:
+ case Block:
+ case TranslationUnit:
+
+ case UsingDirective:
+ case ClassTemplateSpecialization:
+ case ClassTemplatePartialSpecialization:
+ case ObjCImplementation:
+ case ObjCCategory:
+ case ObjCCategoryImpl:
+ // Never looked up by name.
+ return 0;
+ }
+
+ return 0;
+}
+
+void Decl::setAttrs(const AttrVec &attrs) {
+ assert(!HasAttrs && "Decl already contains attrs.");
+
+ AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
+ assert(AttrBlank.empty() && "HasAttrs was wrong?");
+
+ AttrBlank = attrs;
+ HasAttrs = true;
+}
+
+void Decl::dropAttrs() {
+ if (!HasAttrs) return;
+
+ HasAttrs = false;
+ getASTContext().eraseDeclAttrs(this);
+}
+
+const AttrVec &Decl::getAttrs() const {
+ assert(HasAttrs && "No attrs to get!");
+ return getASTContext().getDeclAttrs(this);
+}
+
+void Decl::swapAttrs(Decl *RHS) {
+ bool HasLHSAttr = this->HasAttrs;
+ bool HasRHSAttr = RHS->HasAttrs;
+
+ // Usually, neither decl has attrs, nothing to do.
+ if (!HasLHSAttr && !HasRHSAttr) return;
+
+ // If 'this' has no attrs, swap the other way.
+ if (!HasLHSAttr)
+ return RHS->swapAttrs(this);
+
+ ASTContext &Context = getASTContext();
+
+ // Handle the case when both decls have attrs.
+ if (HasRHSAttr) {
+ std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
+ return;
+ }
+
+ // Otherwise, LHS has an attr and RHS doesn't.
+ Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
+ Context.eraseDeclAttrs(this);
+ this->HasAttrs = false;
+ RHS->HasAttrs = true;
+}
+
+Decl *Decl::castFromDeclContext (const DeclContext *D) {
+ Decl::Kind DK = D->getDeclKind();
+ switch(DK) {
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) \
+ case Decl::NAME: \
+ return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
+ default:
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (DK >= first##NAME && DK <= last##NAME) \
+ return static_cast<NAME##Decl*>(const_cast<DeclContext*>(D));
+#include "clang/AST/DeclNodes.inc"
+ assert(false && "a decl that inherits DeclContext isn't handled");
+ return 0;
+ }
+}
+
+DeclContext *Decl::castToDeclContext(const Decl *D) {
+ Decl::Kind DK = D->getKind();
+ switch(DK) {
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) \
+ case Decl::NAME: \
+ return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
+ default:
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (DK >= first##NAME && DK <= last##NAME) \
+ return static_cast<NAME##Decl*>(const_cast<Decl*>(D));
+#include "clang/AST/DeclNodes.inc"
+ assert(false && "a decl that inherits DeclContext isn't handled");
+ return 0;
+ }
+}
+
+SourceLocation Decl::getBodyRBrace() const {
+ // Special handling of FunctionDecl to avoid de-serializing the body from PCH.
+ // FunctionDecl stores EndRangeLoc for this purpose.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+ const FunctionDecl *Definition;
+ if (FD->hasBody(Definition))
+ return Definition->getSourceRange().getEnd();
+ return SourceLocation();
+ }
+
+ if (Stmt *Body = getBody())
+ return Body->getSourceRange().getEnd();
+
+ return SourceLocation();
+}
+
+void Decl::CheckAccessDeclContext() const {
+#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. 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<TranslationUnitDecl>(this) ||
+ isa<TemplateTypeParmDecl>(this) ||
+ isa<NonTypeTemplateParmDecl>(this) ||
+ !isa<CXXRecordDecl>(getDeclContext()) ||
+ isInvalidDecl() ||
+ isa<StaticAssertDecl>(this) ||
+ // FIXME: a ParmVarDecl can have ClassTemplateSpecialization
+ // as DeclContext (?).
+ isa<ParmVarDecl>(this) ||
+ // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
+ // AS_none as access specifier.
+ isa<CXXRecordDecl>(this))
+ return;
+
+ assert(Access != AS_none &&
+ "Access specifier is AS_none inside a record decl");
+#endif
+}
+
+
+//===----------------------------------------------------------------------===//
+// DeclContext Implementation
+//===----------------------------------------------------------------------===//
+
+bool DeclContext::classof(const Decl *D) {
+ switch (D->getKind()) {
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT(NAME) case Decl::NAME:
+#define DECL_CONTEXT_BASE(NAME)
+#include "clang/AST/DeclNodes.inc"
+ return true;
+ default:
+#define DECL(NAME, BASE)
+#define DECL_CONTEXT_BASE(NAME) \
+ if (D->getKind() >= Decl::first##NAME && \
+ D->getKind() <= Decl::last##NAME) \
+ return true;
+#include "clang/AST/DeclNodes.inc"
+ return false;
+ }
+}
+
+DeclContext::~DeclContext() { }
+
+/// \brief Find the parent context of this context that will be
+/// used for unqualified name lookup.
+///
+/// Generally, the parent lookup context is the semantic context. However, for
+/// a friend function the parent lookup context is the lexical context, which
+/// is the class in which the friend is declared.
+DeclContext *DeclContext::getLookupParent() {
+ // FIXME: Find a better way to identify friends
+ if (isa<FunctionDecl>(this))
+ if (getParent()->getRedeclContext()->isFileContext() &&
+ getLexicalParent()->getRedeclContext()->isRecord())
+ return getLexicalParent();
+
+ return getParent();
+}
+
+bool DeclContext::isInlineNamespace() const {
+ return isNamespace() &&
+ cast<NamespaceDecl>(this)->isInline();
+}
+
+bool DeclContext::isDependentContext() const {
+ if (isFileContext())
+ return false;
+
+ if (isa<ClassTemplatePartialSpecializationDecl>(this))
+ return true;
+
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
+ if (Record->getDescribedClassTemplate())
+ return true;
+
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
+ if (Function->getDescribedFunctionTemplate())
+ return true;
+
+ // Friend function declarations are dependent if their *lexical*
+ // context is dependent.
+ if (cast<Decl>(this)->getFriendObjectKind())
+ return getLexicalParent()->isDependentContext();
+ }
+
+ return getParent() && getParent()->isDependentContext();
+}
+
+bool DeclContext::isTransparentContext() const {
+ if (DeclKind == Decl::Enum)
+ return !cast<EnumDecl>(this)->isScoped();
+ else if (DeclKind == Decl::LinkageSpec)
+ return true;
+
+ return false;
+}
+
+bool DeclContext::isExternCContext() const {
+ const DeclContext *DC = this;
+ while (DC->DeclKind != Decl::TranslationUnit) {
+ if (DC->DeclKind == Decl::LinkageSpec)
+ return cast<LinkageSpecDecl>(DC)->getLanguage()
+ == LinkageSpecDecl::lang_c;
+ DC = DC->getParent();
+ }
+ return false;
+}
+
+bool DeclContext::Encloses(const DeclContext *DC) const {
+ if (getPrimaryContext() != this)
+ return getPrimaryContext()->Encloses(DC);
+
+ for (; DC; DC = DC->getParent())
+ if (DC->getPrimaryContext() == this)
+ return true;
+ return false;
+}
+
+DeclContext *DeclContext::getPrimaryContext() {
+ switch (DeclKind) {
+ case Decl::TranslationUnit:
+ case Decl::LinkageSpec:
+ case Decl::Block:
+ // There is only one DeclContext for these entities.
+ return this;
+
+ case Decl::Namespace:
+ // The original namespace is our primary context.
+ return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
+
+ case Decl::ObjCMethod:
+ return this;
+
+ case Decl::ObjCInterface:
+ case Decl::ObjCProtocol:
+ case Decl::ObjCCategory:
+ // FIXME: Can Objective-C interfaces be forward-declared?
+ return this;
+
+ case Decl::ObjCImplementation:
+ case Decl::ObjCCategoryImpl:
+ return this;
+
+ default:
+ if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) {
+ // If this is a tag type that has a definition or is currently
+ // being defined, that definition is our primary context.
+ TagDecl *Tag = cast<TagDecl>(this);
+ assert(isa<TagType>(Tag->TypeForDecl) ||
+ isa<InjectedClassNameType>(Tag->TypeForDecl));
+
+ if (TagDecl *Def = Tag->getDefinition())
+ return Def;
+
+ if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) {
+ const TagType *TagTy = cast<TagType>(Tag->TypeForDecl);
+ if (TagTy->isBeingDefined())
+ // FIXME: is it necessarily being defined in the decl
+ // that owns the type?
+ return TagTy->getDecl();
+ }
+
+ return Tag;
+ }
+
+ assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction &&
+ "Unknown DeclContext kind");
+ return this;
+ }
+}
+
+DeclContext *DeclContext::getNextContext() {
+ switch (DeclKind) {
+ case Decl::Namespace:
+ // Return the next namespace
+ return static_cast<NamespaceDecl*>(this)->getNextNamespace();
+
+ default:
+ return 0;
+ }
+}
+
+std::pair<Decl *, Decl *>
+DeclContext::BuildDeclChain(const llvm::SmallVectorImpl<Decl*> &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
+DeclContext::LoadLexicalDeclsFromExternalStorage() const {
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ assert(hasExternalLexicalStorage() && Source && "No external storage?");
+
+ // Notify that we have a DeclContext that is initializing.
+ ExternalASTSource::Deserializing ADeclContext(Source);
+
+ llvm::SmallVector<Decl*, 64> Decls;
+ if (Source->FindExternalLexicalDecls(this, Decls))
+ return;
+
+ // There is no longer any lexical storage in this context
+ ExternalLexicalStorage = false;
+
+ if (Decls.empty())
+ return;
+
+ // 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<RecordDecl>(this))
+ if (RD->LoadedFieldsFromExternalStorage) {
+ llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls);
+ return;
+ }
+
+ // Splice the newly-read declarations into the beginning of the list
+ // of declarations.
+ Decl *ExternalFirst, *ExternalLast;
+ llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls);
+ ExternalLast->NextDeclInContext = FirstDecl;
+ FirstDecl = ExternalFirst;
+ if (!LastDecl)
+ LastDecl = ExternalLast;
+}
+
+DeclContext::lookup_result
+ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name) {
+ ASTContext &Context = DC->getParentASTContext();
+ StoredDeclsMap *Map;
+ if (!(Map = DC->LookupPtr))
+ Map = DC->CreateStoredDeclsMap(Context);
+
+ StoredDeclsList &List = (*Map)[Name];
+ assert(List.isNull());
+ (void) List;
+
+ return DeclContext::lookup_result();
+}
+
+DeclContext::lookup_result
+ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ ASTContext &Context = DC->getParentASTContext();;
+
+ StoredDeclsMap *Map;
+ if (!(Map = DC->LookupPtr))
+ Map = DC->CreateStoredDeclsMap(Context);
+
+ StoredDeclsList &List = (*Map)[Name];
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ if (List.isNull())
+ List.setOnlyValue(Decls[I]);
+ else
+ List.AddSubsequentDecl(Decls[I]);
+ }
+
+ return List.getLookupResult();
+}
+
+void ExternalASTSource::MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ assert(DC->LookupPtr);
+ StoredDeclsMap &Map = *DC->LookupPtr;
+
+ // If there's an entry in the table the visible decls for this name have
+ // already been deserialized.
+ if (Map.find(Name) == Map.end()) {
+ StoredDeclsList &List = Map[Name];
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ if (List.isNull())
+ List.setOnlyValue(Decls[I]);
+ else
+ List.AddSubsequentDecl(Decls[I]);
+ }
+ }
+}
+
+DeclContext::decl_iterator DeclContext::noload_decls_begin() const {
+ return decl_iterator(FirstDecl);
+}
+
+DeclContext::decl_iterator DeclContext::noload_decls_end() const {
+ return decl_iterator();
+}
+
+DeclContext::decl_iterator DeclContext::decls_begin() const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage();
+
+ // FIXME: Check whether we need to load some declarations from
+ // external storage.
+ return decl_iterator(FirstDecl);
+}
+
+DeclContext::decl_iterator DeclContext::decls_end() const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage();
+
+ return decl_iterator();
+}
+
+bool DeclContext::decls_empty() const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage();
+
+ return !FirstDecl;
+}
+
+void DeclContext::removeDecl(Decl *D) {
+ assert(D->getLexicalDeclContext() == this &&
+ "decl being removed from non-lexical context");
+ assert((D->NextDeclInContext || D == LastDecl) &&
+ "decl is not in decls list");
+
+ // Remove D from the decl chain. This is O(n) but hopefully rare.
+ if (D == FirstDecl) {
+ if (D == LastDecl)
+ FirstDecl = LastDecl = 0;
+ else
+ FirstDecl = D->NextDeclInContext;
+ } else {
+ for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
+ assert(I && "decl not found in linked list");
+ if (I->NextDeclInContext == D) {
+ I->NextDeclInContext = D->NextDeclInContext;
+ if (D == LastDecl) LastDecl = I;
+ break;
+ }
+ }
+ }
+
+ // Mark that D is no longer in the decl chain.
+ D->NextDeclInContext = 0;
+
+ // Remove D from the lookup table if necessary.
+ if (isa<NamedDecl>(D)) {
+ NamedDecl *ND = cast<NamedDecl>(D);
+
+ StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
+ if (!Map) return;
+
+ StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
+ assert(Pos != Map->end() && "no lookup entry for decl");
+ Pos->second.remove(ND);
+ }
+}
+
+void DeclContext::addHiddenDecl(Decl *D) {
+ assert(D->getLexicalDeclContext() == this &&
+ "Decl inserted into wrong lexical context");
+ assert(!D->getNextDeclInContext() && D != LastDecl &&
+ "Decl already inserted into a DeclContext");
+
+ if (FirstDecl) {
+ LastDecl->NextDeclInContext = D;
+ LastDecl = 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<CXXRecordDecl>(this))
+ Record->addedMember(D);
+}
+
+void DeclContext::addDecl(Decl *D) {
+ addHiddenDecl(D);
+
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ ND->getDeclContext()->makeDeclVisibleInContext(ND);
+}
+
+/// buildLookup - Build the lookup data structure with all of the
+/// declarations in DCtx (and any other contexts linked to it or
+/// transparent contexts nested within it).
+void DeclContext::buildLookup(DeclContext *DCtx) {
+ for (; DCtx; DCtx = DCtx->getNextContext()) {
+ for (decl_iterator D = DCtx->decls_begin(),
+ DEnd = DCtx->decls_end();
+ D != DEnd; ++D) {
+ // Insert this declaration into the lookup structure, but only
+ // if it's semantically in its decl context. During non-lazy
+ // lookup building, this is implicitly enforced by addDecl.
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ if (D->getDeclContext() == DCtx)
+ makeDeclVisibleInContextImpl(ND);
+
+ // Insert any forward-declared Objective-C interfaces into the lookup
+ // data structure.
+ if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
+ for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
+ I != IEnd; ++I)
+ makeDeclVisibleInContextImpl(I->getInterface());
+
+ // If this declaration is itself a transparent declaration context or
+ // inline namespace, add its members (recursively).
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
+ buildLookup(InnerCtx->getPrimaryContext());
+ }
+ }
+}
+
+DeclContext::lookup_result
+DeclContext::lookup(DeclarationName Name) {
+ DeclContext *PrimaryContext = getPrimaryContext();
+ if (PrimaryContext != this)
+ return PrimaryContext->lookup(Name);
+
+ if (hasExternalVisibleStorage()) {
+ // Check to see if we've already cached the lookup results.
+ if (LookupPtr) {
+ StoredDeclsMap::iterator I = LookupPtr->find(Name);
+ if (I != LookupPtr->end())
+ return I->second.getLookupResult();
+ }
+
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ return Source->FindExternalVisibleDeclsByName(this, Name);
+ }
+
+ /// If there is no lookup data structure, build one now by walking
+ /// all of the linked DeclContexts (in declaration order!) and
+ /// inserting their values.
+ if (!LookupPtr) {
+ buildLookup(this);
+
+ if (!LookupPtr)
+ return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ }
+
+ StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
+ if (Pos == LookupPtr->end())
+ return lookup_result(lookup_iterator(0), lookup_iterator(0));
+ return Pos->second.getLookupResult();
+}
+
+DeclContext::lookup_const_result
+DeclContext::lookup(DeclarationName Name) const {
+ return const_cast<DeclContext*>(this)->lookup(Name);
+}
+
+DeclContext *DeclContext::getRedeclContext() {
+ DeclContext *Ctx = this;
+ // Skip through transparent contexts.
+ while (Ctx->isTransparentContext())
+ Ctx = Ctx->getParent();
+ return Ctx;
+}
+
+DeclContext *DeclContext::getEnclosingNamespaceContext() {
+ DeclContext *Ctx = this;
+ // Skip through non-namespace, non-translation-unit contexts.
+ while (!Ctx->isFileContext())
+ Ctx = Ctx->getParent();
+ return Ctx->getPrimaryContext();
+}
+
+bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
+ // For non-file contexts, this is equivalent to Equals.
+ if (!isFileContext())
+ return O->Equals(this);
+
+ do {
+ if (O->Equals(this))
+ return true;
+
+ const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(O);
+ if (!NS || !NS->isInline())
+ break;
+ O = NS->getParent();
+ } while (O);
+
+ return false;
+}
+
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
+ // FIXME: This feels like a hack. Should DeclarationName support
+ // template-ids, or is there a better way to keep specializations
+ // from being visible?
+ if (isa<ClassTemplateSpecializationDecl>(D))
+ return;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isFunctionTemplateSpecialization())
+ return;
+
+ DeclContext *PrimaryContext = getPrimaryContext();
+ if (PrimaryContext != this) {
+ PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
+ return;
+ }
+
+ // If we already have a lookup data structure, perform the insertion
+ // into it. If we haven't deserialized externally stored decls, deserialize
+ // them so we can add the decl. Otherwise, be lazy and don't build that
+ // structure until someone asks for it.
+ if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
+ makeDeclVisibleInContextImpl(D);
+
+ // If we are a transparent context or inline namespace, insert into our
+ // parent context, too. This operation is recursive.
+ if (isTransparentContext() || isInlineNamespace())
+ getParent()->makeDeclVisibleInContext(D, Recoverable);
+
+ Decl *DCAsDecl = cast<Decl>(this);
+ // Notify that a decl was made visible unless it's a Tag being defined.
+ if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
+ if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
+ L->AddedVisibleDecl(this, D);
+}
+
+void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
+ // Skip unnamed declarations.
+ if (!D->getDeclName())
+ return;
+
+ // FIXME: This feels like a hack. Should DeclarationName support
+ // template-ids, or is there a better way to keep specializations
+ // from being visible?
+ if (isa<ClassTemplateSpecializationDecl>(D))
+ return;
+
+ ASTContext *C = 0;
+ if (!LookupPtr) {
+ C = &getParentASTContext();
+ CreateStoredDeclsMap(*C);
+ }
+
+ // If there is an external AST source, load any declarations it knows about
+ // with this declaration's name.
+ // If the lookup table contains an entry about this name it means that we
+ // have already checked the external source.
+ if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+ if (hasExternalVisibleStorage() &&
+ LookupPtr->find(D->getDeclName()) == LookupPtr->end())
+ Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
+
+ // Insert this declaration into the map.
+ StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
+ if (DeclNameEntries.isNull()) {
+ DeclNameEntries.setOnlyValue(D);
+ return;
+ }
+
+ // If it is possible that this is a redeclaration, check to see if there is
+ // already a decl for which declarationReplaces returns true. If there is
+ // one, just replace it and return.
+ if (DeclNameEntries.HandleRedeclaration(D))
+ return;
+
+ // Put this declaration into the appropriate slot.
+ DeclNameEntries.AddSubsequentDecl(D);
+}
+
+void DeclContext::MaterializeVisibleDeclsFromExternalStorage() {
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ assert(hasExternalVisibleStorage() && Source && "No external storage?");
+
+ if (!LookupPtr)
+ CreateStoredDeclsMap(getParentASTContext());
+ Source->MaterializeVisibleDecls(this);
+}
+
+/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
+/// this context.
+DeclContext::udir_iterator_range
+DeclContext::getUsingDirectives() const {
+ lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
+ return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
+ reinterpret_cast<udir_iterator>(Result.second));
+}
+
+//===----------------------------------------------------------------------===//
+// Creation and Destruction of StoredDeclsMaps. //
+//===----------------------------------------------------------------------===//
+
+StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
+ assert(!LookupPtr && "context already has a decls map");
+ assert(getPrimaryContext() == this &&
+ "creating decls map on non-primary context");
+
+ StoredDeclsMap *M;
+ bool Dependent = isDependentContext();
+ if (Dependent)
+ M = new DependentStoredDeclsMap();
+ else
+ M = new StoredDeclsMap();
+ M->Previous = C.LastSDM;
+ C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
+ LookupPtr = M;
+ return M;
+}
+
+void ASTContext::ReleaseDeclContextMaps() {
+ // It's okay to delete DependentStoredDeclsMaps via a StoredDeclsMap
+ // pointer because the subclass doesn't add anything that needs to
+ // be deleted.
+ StoredDeclsMap::DestroyAll(LastSDM.getPointer(), LastSDM.getInt());
+}
+
+void StoredDeclsMap::DestroyAll(StoredDeclsMap *Map, bool Dependent) {
+ while (Map) {
+ // Advance the iteration before we invalidate memory.
+ llvm::PointerIntPair<StoredDeclsMap*,1> Next = Map->Previous;
+
+ if (Dependent)
+ delete static_cast<DependentStoredDeclsMap*>(Map);
+ else
+ delete Map;
+
+ Map = Next.getPointer();
+ Dependent = Next.getInt();
+ }
+}
+
+DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
+ DeclContext *Parent,
+ const PartialDiagnostic &PDiag) {
+ assert(Parent->isDependentContext()
+ && "cannot iterate dependent diagnostics of non-dependent context");
+ Parent = Parent->getPrimaryContext();
+ if (!Parent->LookupPtr)
+ Parent->CreateStoredDeclsMap(C);
+
+ DependentStoredDeclsMap *Map
+ = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr);
+
+ // Allocate the copy of the PartialDiagnostic via the ASTContext's
+ // BumpPtrAllocator, rather than the ASTContext itself.
+ PartialDiagnostic::Storage *DiagStorage = 0;
+ if (PDiag.hasStorage())
+ DiagStorage = new (C) PartialDiagnostic::Storage;
+
+ DependentDiagnostic *DD = new (C) DependentDiagnostic(PDiag, DiagStorage);
+
+ // TODO: Maybe we shouldn't reverse the order during insertion.
+ DD->NextDiagnostic = Map->FirstDiagnostic;
+ Map->FirstDiagnostic = DD;
+
+ return DD;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
new file mode 100644
index 0000000..fba73f5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -0,0 +1,1396 @@
+//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++ related Decl classes.
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Decl Allocation/Deallocation Method Implementations
+//===----------------------------------------------------------------------===//
+
+CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
+ : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+ UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
+ Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
+ Abstract(false), HasTrivialConstructor(true),
+ HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
+ HasTrivialDestructor(true), ComputedVisibleConversions(false),
+ DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
+ DeclaredCopyAssignment(false), DeclaredDestructor(false),
+ NumBases(0), NumVBases(0), Bases(), VBases(),
+ Definition(D), FirstFriend(0) {
+}
+
+CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl,
+ SourceLocation TKL)
+ : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL),
+ DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0),
+ TemplateOrInstantiation() { }
+
+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,
+ PrevDecl, TKL);
+
+ // FIXME: DelayTypeCreation seems like such a hack
+ if (!DelayTypeCreation)
+ C.getTypeDeclType(R, PrevDecl);
+ return R;
+}
+
+CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, EmptyShell Empty) {
+ return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0,
+ SourceLocation());
+}
+
+void
+CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
+ unsigned NumBases) {
+ ASTContext &C = getASTContext();
+
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with [...]
+ // no base classes [...].
+ data().Aggregate = false;
+
+ if (!data().Bases.isOffset() && data().NumBases > 0)
+ C.Deallocate(data().getBases());
+
+ // The set of seen virtual base types.
+ llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
+
+ // The virtual bases of this class.
+ llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases;
+
+ data().Bases = new(C) CXXBaseSpecifier [NumBases];
+ data().NumBases = NumBases;
+ for (unsigned i = 0; i < NumBases; ++i) {
+ data().getBases()[i] = *Bases[i];
+ // Keep track of inherited vbases for this base class.
+ const CXXBaseSpecifier *Base = Bases[i];
+ QualType BaseType = Base->getType();
+ // Skip dependent types; we can't do any checking on them now.
+ if (BaseType->isDependentType())
+ continue;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is [...] a class with [...] no base classes [...].
+ data().Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class...
+ data().PlainOldData = false;
+
+ // A class with a non-empty base class is not empty.
+ // FIXME: Standard ref?
+ if (!BaseClassDecl->isEmpty())
+ 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(),
+ E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) {
+ // Add this base if it's not already in the list.
+ if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType())))
+ VBases.push_back(VBase);
+ }
+
+ if (Base->isVirtual()) {
+ // 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())
+ return;
+
+ // Create base specifier for any direct or indirect virtual bases.
+ data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
+ data().NumVBases = VBases.size();
+ for (int I = 0, E = VBases.size(); I != E; ++I) {
+ TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo();
+
+ // Skip dependent types; we can't do any checking on them now.
+ if (VBaseTypeInfo->getType()->isDependentType())
+ continue;
+
+ CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(
+ VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl());
+
+ data().getVBases()[I] =
+ CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
+ VBaseClassDecl->getTagKind() == TTK_Class,
+ VBases[I]->getAccessSpecifier(), VBaseTypeInfo,
+ SourceLocation());
+ }
+}
+
+/// Callback function for CXXRecordDecl::forallBases that acknowledges
+/// that it saw a base class.
+static bool SawBase(const CXXRecordDecl *, void *) {
+ return true;
+}
+
+bool CXXRecordDecl::hasAnyDependentBases() const {
+ if (!isDependentContext())
+ return false;
+
+ return !forallBases(SawBase, 0);
+}
+
+bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const {
+ return getCopyConstructor(Context, Qualifiers::Const) != 0;
+}
+
+/// \brief Perform a simplistic form of overload resolution that only considers
+/// cv-qualifiers on a single parameter, and return the best overload candidate
+/// (if there is one).
+static CXXMethodDecl *
+GetBestOverloadCandidateSimple(
+ const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) {
+ if (Cands.empty())
+ return 0;
+ if (Cands.size() == 1)
+ return Cands[0].first;
+
+ unsigned Best = 0, N = Cands.size();
+ for (unsigned I = 1; I != N; ++I)
+ if (Cands[Best].second.isSupersetOf(Cands[I].second))
+ Best = I;
+
+ for (unsigned I = 1; I != N; ++I)
+ if (Cands[Best].second.isSupersetOf(Cands[I].second))
+ return 0;
+
+ return Cands[Best].first;
+}
+
+CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context,
+ unsigned TypeQuals) const{
+ QualType ClassType
+ = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType));
+ unsigned FoundTQs;
+ llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // C++ [class.copy]p2:
+ // A non-template constructor for class X is a copy constructor if [...]
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
+
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
+ if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) ||
+ (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const)))
+ Found.push_back(std::make_pair(
+ const_cast<CXXConstructorDecl *>(Constructor),
+ Qualifiers::fromCVRMask(FoundTQs)));
+ }
+ }
+
+ return cast_or_null<CXXConstructorDecl>(
+ GetBestOverloadCandidateSimple(Found));
+}
+
+CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
+ ASTContext &Context = getASTContext();
+ QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
+ DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+
+ llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found;
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) {
+ // C++ [class.copy]p9:
+ // A user-declared copy assignment operator is a non-static non-template
+ // member function of class X with exactly one parameter of type X, X&,
+ // const X&, volatile X& or const volatile X&.
+ const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
+ if (!Method || Method->isStatic() || Method->getPrimaryTemplate())
+ continue;
+
+ const FunctionProtoType *FnType
+ = Method->getType()->getAs<FunctionProtoType>();
+ assert(FnType && "Overloaded operator has no prototype.");
+ // Don't assert on this; an invalid decl might have been left in the AST.
+ if (FnType->getNumArgs() != 1 || FnType->isVariadic())
+ continue;
+
+ QualType ArgType = FnType->getArgType(0);
+ Qualifiers Quals;
+ if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) {
+ ArgType = Ref->getPointeeType();
+ // If we have a const argument and we have a reference to a non-const,
+ // this function does not match.
+ if (ArgIsConst && !ArgType.isConstQualified())
+ continue;
+
+ Quals = ArgType.getQualifiers();
+ } else {
+ // By-value copy-assignment operators are treated like const X&
+ // copy-assignment operators.
+ Quals = Qualifiers::fromCVRMask(Qualifiers::Const);
+ }
+
+ if (!Context.hasSameUnqualifiedType(ArgType, Class))
+ continue;
+
+ // Save this copy-assignment operator. It might be "the one".
+ Found.push_back(std::make_pair(const_cast<CXXMethodDecl *>(Method), Quals));
+ }
+
+ // Use a simplistic form of overload resolution to find the candidate.
+ return GetBestOverloadCandidateSimple(Found);
+}
+
+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;
+
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (FunTmpl)
+ D = FunTmpl->getTemplatedDecl();
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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<CXXConstructorDecl>(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;
+ }
+
+ if (isa<CXXDestructorDecl>(D)) {
+ data().DeclaredDestructor = true;
+ return;
+ }
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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;
+ }
+
+ // Any other implicit declarations are handled like normal declarations.
+ }
+
+ // Handle (user-declared) constructors.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(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++ [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;
+ }
+
+ // Handle (user-declared) destructors.
+ if (isa<CXXDestructorDecl>(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;
+ }
+
+ // Handle (user-declared) member functions.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Method->getOverloadedOperator() == OO_Equal) {
+ // We're interested specifically in copy assignment operators.
+ const FunctionProtoType *FnType
+ = Method->getType()->getAs<FunctionProtoType>();
+ 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<LValueReferenceType>())
+ ArgType = Ref->getPointeeType();
+
+ ArgType = ArgType.getUnqualifiedType();
+ QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
+ const_cast<CXXRecordDecl*>(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<CXXConversionDecl>(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 (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;
+ }
+
+ // Handle non-static data members.
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(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<RecordType>()) {
+ CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(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<UsingShadowDecl>(D))
+ if (Shadow->getDeclName().getNameKind()
+ == DeclarationName::CXXConversionFunctionName)
+ data().Conversions.addDecl(Shadow, Shadow->getAccess());
+}
+
+static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
+ QualType T;
+ if (isa<UsingShadowDecl>(Conv))
+ Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl();
+ if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
+ T = ConvTemp->getTemplatedDecl()->getResultType();
+ else
+ T = cast<CXXConversionDecl>(Conv)->getConversionType();
+ return Context.getCanonicalType(T);
+}
+
+/// Collect the visible conversions of a base class.
+///
+/// \param Base a base class of the class we're considering
+/// \param InVirtual whether this base class is a virtual base (or a base
+/// of a virtual base)
+/// \param Access the access along the inheritance path to this base
+/// \param ParentHiddenTypes the conversions provided by the inheritors
+/// of this base
+/// \param Output the set to which to add conversions from non-virtual bases
+/// \param VOutput the set to which to add conversions from virtual bases
+/// \param HiddenVBaseCs the set of conversions which were hidden in a
+/// virtual base along some inheritance path
+static void CollectVisibleConversions(ASTContext &Context,
+ CXXRecordDecl *Record,
+ bool InVirtual,
+ AccessSpecifier Access,
+ const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes,
+ UnresolvedSetImpl &Output,
+ UnresolvedSetImpl &VOutput,
+ llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) {
+ // The set of types which have conversions in this class or its
+ // subclasses. As an optimization, we don't copy the derived set
+ // unless it might change.
+ const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes;
+ llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer;
+
+ // Collect the direct conversions and figure out which conversions
+ // will be hidden in the subclasses.
+ UnresolvedSetImpl &Cs = *Record->getConversionFunctions();
+ if (!Cs.empty()) {
+ HiddenTypesBuffer = ParentHiddenTypes;
+ HiddenTypes = &HiddenTypesBuffer;
+
+ for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
+ bool Hidden =
+ !HiddenTypesBuffer.insert(GetConversionType(Context, I.getDecl()));
+
+ // If this conversion is hidden and we're in a virtual base,
+ // remember that it's hidden along some inheritance path.
+ if (Hidden && InVirtual)
+ HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()));
+
+ // If this conversion isn't hidden, add it to the appropriate output.
+ else if (!Hidden) {
+ AccessSpecifier IAccess
+ = CXXRecordDecl::MergeAccess(Access, I.getAccess());
+
+ if (InVirtual)
+ VOutput.addDecl(I.getDecl(), IAccess);
+ else
+ Output.addDecl(I.getDecl(), IAccess);
+ }
+ }
+ }
+
+ // Collect information recursively from any base classes.
+ for (CXXRecordDecl::base_class_iterator
+ I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
+ const RecordType *RT = I->getType()->getAs<RecordType>();
+ if (!RT) continue;
+
+ AccessSpecifier BaseAccess
+ = CXXRecordDecl::MergeAccess(Access, I->getAccessSpecifier());
+ bool BaseInVirtual = InVirtual || I->isVirtual();
+
+ CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
+ *HiddenTypes, Output, VOutput, HiddenVBaseCs);
+ }
+}
+
+/// Collect the visible conversions of a class.
+///
+/// This would be extremely straightforward if it weren't for virtual
+/// bases. It might be worth special-casing that, really.
+static void CollectVisibleConversions(ASTContext &Context,
+ CXXRecordDecl *Record,
+ UnresolvedSetImpl &Output) {
+ // The collection of all conversions in virtual bases that we've
+ // found. These will be added to the output as long as they don't
+ // appear in the hidden-conversions set.
+ UnresolvedSet<8> VBaseCs;
+
+ // The set of conversions in virtual bases that we've determined to
+ // be hidden.
+ llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs;
+
+ // The set of types hidden by classes derived from this one.
+ llvm::SmallPtrSet<CanQualType, 8> HiddenTypes;
+
+ // Go ahead and collect the direct conversions and add them to the
+ // hidden-types set.
+ UnresolvedSetImpl &Cs = *Record->getConversionFunctions();
+ Output.append(Cs.begin(), Cs.end());
+ for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I)
+ HiddenTypes.insert(GetConversionType(Context, I.getDecl()));
+
+ // Recursively collect conversions from base classes.
+ for (CXXRecordDecl::base_class_iterator
+ I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
+ const RecordType *RT = I->getType()->getAs<RecordType>();
+ if (!RT) continue;
+
+ CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()),
+ I->isVirtual(), I->getAccessSpecifier(),
+ HiddenTypes, Output, VBaseCs, HiddenVBaseCs);
+ }
+
+ // Add any unhidden conversions provided by virtual bases.
+ for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end();
+ I != E; ++I) {
+ if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())))
+ Output.addDecl(I.getDecl(), I.getAccess());
+ }
+}
+
+/// getVisibleConversionFunctions - get all conversion functions visible
+/// in current class; including conversion function templates.
+const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() {
+ // If root class, all conversions are visible.
+ if (bases_begin() == bases_end())
+ return &data().Conversions;
+ // If visible conversion list is already evaluated, return it.
+ if (data().ComputedVisibleConversions)
+ return &data().VisibleConversions;
+ CollectVisibleConversions(getASTContext(), this, data().VisibleConversions);
+ data().ComputedVisibleConversions = true;
+ return &data().VisibleConversions;
+}
+
+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
+ // declaration, e.g.:
+ // class A : B {
+ // using B::operator int;
+ // operator int();
+ // };
+ // This is uncommon by itself and even more uncommon in conjunction
+ // with sufficiently large numbers of directly-declared conversions
+ // that asymptotic behavior matters.
+
+ UnresolvedSetImpl &Convs = *getConversionFunctions();
+ for (unsigned I = 0, E = Convs.size(); I != E; ++I) {
+ if (Convs[I].getDecl() == ConvDecl) {
+ Convs.erase(I);
+ assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end()
+ && "conversion was found multiple times in unresolved set");
+ return;
+ }
+ }
+
+ llvm_unreachable("conversion not found in set!");
+}
+
+CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
+ return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
+
+ return 0;
+}
+
+MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
+ return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
+}
+
+void
+CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
+ TemplateSpecializationKind TSK) {
+ assert(TemplateOrInstantiation.isNull() &&
+ "Previous template or instantiation?");
+ assert(!isa<ClassTemplateSpecializationDecl>(this));
+ TemplateOrInstantiation
+ = new (getASTContext()) MemberSpecializationInfo(RD, TSK);
+}
+
+TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
+ if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(this))
+ return Spec->getSpecializationKind();
+
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
+ return MSInfo->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+void
+CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
+ Spec->setSpecializationKind(TSK);
+ return;
+ }
+
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ return;
+ }
+
+ assert(false && "Not a class template or member class specialization");
+}
+
+CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
+ ASTContext &Context = getASTContext();
+ QualType ClassType = Context.getTypeDeclType(this);
+
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(ClassType));
+
+ DeclContext::lookup_const_iterator I, E;
+ llvm::tie(I, E) = lookup(Name);
+ if (I == E)
+ return 0;
+
+ CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
+ assert(++I == E && "Found more than one destructor!");
+
+ 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<CXXRecordDecl>(B->getType()->getAs<RecordType>()->getDecl());
+ if (BaseDecl->isAbstract())
+ return true;
+ }
+
+ return false;
+}
+
+CXXMethodDecl *
+CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic, StorageClass SCAsWritten, bool isInline) {
+ return new (C) CXXMethodDecl(CXXMethod, RD, NameInfo, T, TInfo,
+ isStatic, SCAsWritten, isInline);
+}
+
+bool CXXMethodDecl::isUsualDeallocationFunction() const {
+ if (getOverloadedOperator() != OO_Delete &&
+ getOverloadedOperator() != OO_Array_Delete)
+ return false;
+
+ // C++ [basic.stc.dynamic.deallocation]p2:
+ // A template instance is never a usual deallocation function,
+ // regardless of its signature.
+ if (getPrimaryTemplate())
+ return false;
+
+ // C++ [basic.stc.dynamic.deallocation]p2:
+ // If a class T has a member deallocation function named operator delete
+ // with exactly one parameter, then that function is a usual (non-placement)
+ // deallocation function. [...]
+ if (getNumParams() == 1)
+ return true;
+
+ // C++ [basic.stc.dynamic.deallocation]p2:
+ // [...] If class T does not declare such an operator delete but does
+ // declare a member deallocation function named operator delete with
+ // exactly two parameters, the second of which has type std::size_t (18.1),
+ // then this function is a usual deallocation function.
+ ASTContext &Context = getASTContext();
+ if (getNumParams() != 2 ||
+ !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(),
+ Context.getSizeType()))
+ return false;
+
+ // This function is a usual deallocation function if there are no
+ // single-parameter deallocation functions of the same kind.
+ for (DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName());
+ R.first != R.second; ++R.first) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*R.first))
+ if (FD->getNumParams() == 1)
+ return false;
+ }
+
+ return true;
+}
+
+bool CXXMethodDecl::isCopyAssignmentOperator() const {
+ // C++0x [class.copy]p19:
+ // A user-declared copy assignment operator X::operator= is a non-static
+ // non-template member function of class X with exactly one parameter of
+ // type X, X&, const X&, volatile X& or const volatile X&.
+ if (/*operator=*/getOverloadedOperator() != OO_Equal ||
+ /*non-static*/ isStatic() ||
+ /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
+ /*exactly one parameter*/getNumParams() != 1)
+ return false;
+
+ QualType ParamType = getParamDecl(0)->getType();
+ if (const LValueReferenceType *Ref = ParamType->getAs<LValueReferenceType>())
+ ParamType = Ref->getPointeeType();
+
+ ASTContext &Context = getASTContext();
+ QualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
+ return Context.hasSameUnqualifiedType(ClassType, ParamType);
+}
+
+void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
+ assert(MD->isCanonicalDecl() && "Method is not canonical!");
+ assert(!MD->getParent()->isDependentContext() &&
+ "Can't add an overridden method to a class template!");
+
+ getASTContext().addOverriddenMethod(this, MD);
+}
+
+CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
+ return getASTContext().overridden_methods_begin(this);
+}
+
+CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
+ return getASTContext().overridden_methods_end(this);
+}
+
+unsigned CXXMethodDecl::size_overridden_methods() const {
+ return getASTContext().overridden_methods_size(this);
+}
+
+QualType CXXMethodDecl::getThisType(ASTContext &C) const {
+ // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
+ // If the member function is declared const, the type of this is const X*,
+ // if the member function is declared volatile, the type of this is
+ // volatile X*, and if the member function is declared const volatile,
+ // the type of this is const volatile X*.
+
+ assert(isInstance() && "No 'this' for static methods!");
+
+ QualType ClassTy = C.getTypeDeclType(getParent());
+ ClassTy = C.getQualifiedType(ClassTy,
+ Qualifiers::fromCVRMask(getTypeQualifiers()));
+ return C.getPointerType(ClassTy);
+}
+
+bool CXXMethodDecl::hasInlineBody() const {
+ // If this function is a template instantiation, look at the template from
+ // which it was instantiated.
+ const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
+ if (!CheckFn)
+ CheckFn = this;
+
+ const FunctionDecl *fn;
+ return CheckFn->hasBody(fn) && !fn->isOutOfLine();
+}
+
+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)
+{
+}
+
+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)
+{
+}
+
+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<VarDecl **> (this + 1);
+ memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
+}
+
+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<CXXCtorInitializer>());
+ return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
+ Indices, NumIndices);
+}
+
+TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
+ if (isBaseInitializer())
+ return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
+ else
+ return TypeLoc();
+}
+
+const Type *CXXCtorInitializer::getBaseClass() const {
+ if (isBaseInitializer())
+ return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr();
+ else
+ return 0;
+}
+
+SourceLocation CXXCtorInitializer::getSourceLocation() const {
+ if (isAnyMemberInitializer())
+ return getMemberLocation();
+
+ return getBaseClassLoc().getLocalSourceRange().getBegin();
+}
+
+SourceRange CXXCtorInitializer::getSourceRange() const {
+ return SourceRange(getSourceLocation(), getRParenLoc());
+}
+
+CXXConstructorDecl *
+CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) CXXConstructorDecl(0, DeclarationNameInfo(),
+ QualType(), 0, false, false, false);
+}
+
+CXXConstructorDecl *
+CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit,
+ bool isInline,
+ bool isImplicitlyDeclared) {
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConstructorName &&
+ "Name must refer to a constructor");
+ return new (C) CXXConstructorDecl(RD, NameInfo, T, TInfo, isExplicit,
+ isInline, isImplicitlyDeclared);
+}
+
+bool CXXConstructorDecl::isDefaultConstructor() const {
+ // C++ [class.ctor]p5:
+ // A default constructor for a class X is a constructor of class
+ // X that can be called without an argument.
+ return (getNumParams() == 0) ||
+ (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg());
+}
+
+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?
+ const ReferenceType *ParamRefType = Param->getType()->getAs<ReferenceType>();
+ if (!ParamRefType)
+ return false;
+
+ // Is it a reference to our class type?
+ ASTContext &Context = getASTContext();
+
+ CanQualType PointeeType
+ = Context.getCanonicalType(ParamRefType->getPointeeType());
+ CanQualType ClassTy
+ = Context.getCanonicalType(Context.getTagDeclType(getParent()));
+ if (PointeeType.getUnqualifiedType() != ClassTy)
+ return false;
+
+ // FIXME: other qualifiers?
+
+ // We have a copy or move constructor.
+ TypeQuals = PointeeType.getCVRQualifiers();
+ return true;
+}
+
+bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
+ // C++ [class.conv.ctor]p1:
+ // A constructor declared without the function-specifier explicit
+ // that can be called with a single parameter specifies a
+ // conversion from the type of its first parameter to the type of
+ // its class. Such a constructor is called a converting
+ // constructor.
+ if (isExplicit() && !AllowExplicit)
+ return false;
+
+ return (getNumParams() == 0 &&
+ getType()->getAs<FunctionProtoType>()->isVariadic()) ||
+ (getNumParams() == 1) ||
+ (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg());
+}
+
+bool CXXConstructorDecl::isSpecializationCopyingObject() const {
+ if ((getNumParams() < 1) ||
+ (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
+ (getPrimaryTemplate() == 0) ||
+ (getDescribedFunctionTemplate() != 0))
+ return false;
+
+ const ParmVarDecl *Param = getParamDecl(0);
+
+ ASTContext &Context = getASTContext();
+ CanQualType ParamType = Context.getCanonicalType(Param->getType());
+
+ // Is it the same as our our class type?
+ CanQualType ClassTy
+ = Context.getCanonicalType(Context.getTagDeclType(getParent()));
+ if (ParamType.getUnqualifiedType() != ClassTy)
+ return false;
+
+ 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<CXXConstructorDecl>(*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(), 0, false, false);
+}
+
+CXXDestructorDecl *
+CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ 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, TInfo, isInline,
+ isImplicitlyDeclared);
+}
+
+CXXConversionDecl *
+CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) CXXConversionDecl(0, DeclarationNameInfo(),
+ QualType(), 0, false, false);
+}
+
+CXXConversionDecl *
+CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit) {
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConversionFunctionName &&
+ "Name must refer to a conversion function");
+ return new (C) CXXConversionDecl(RD, NameInfo, T, TInfo,
+ isInline, isExplicit);
+}
+
+LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation L,
+ LanguageIDs Lang, bool Braces) {
+ return new (C) LinkageSpecDecl(DC, L, Lang, Braces);
+}
+
+UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ SourceLocation NamespaceLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Used,
+ DeclContext *CommonAncestor) {
+ if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
+ Used = NS->getOriginalNamespace();
+ return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange,
+ Qualifier, IdentLoc, Used, CommonAncestor);
+}
+
+NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
+ if (NamespaceAliasDecl *NA =
+ dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
+ return NA->getNamespace();
+ return cast_or_null<NamespaceDecl>(NominatedNamespace);
+}
+
+NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace) {
+ if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
+ Namespace = NS->getOriginalNamespace();
+ return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
+ Qualifier, IdentLoc, Namespace);
+}
+
+UsingDecl *UsingShadowDecl::getUsingDecl() const {
+ const UsingShadowDecl *Shadow = this;
+ while (const UsingShadowDecl *NextShadow =
+ dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
+ Shadow = NextShadow;
+ return cast<UsingDecl>(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<UsingShadowDecl>(S->UsingOrNextShadow);
+ S->UsingOrNextShadow = this;
+ return;
+ }
+
+ UsingShadowDecl *Prev = FirstUsingShadow;
+ while (Prev->UsingOrNextShadow != S)
+ Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow);
+ Prev->UsingOrNextShadow = S->UsingOrNextShadow;
+ S->UsingOrNextShadow = this;
+}
+
+UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceRange NNR, SourceLocation UL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg);
+}
+
+UnresolvedUsingValueDecl *
+UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ const DeclarationNameInfo &NameInfo) {
+ return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
+ TargetNNR, TargetNNS, NameInfo);
+}
+
+UnresolvedUsingTypenameDecl *
+UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ SourceRange TargetNNR,
+ NestedNameSpecifier *TargetNNS,
+ SourceLocation TargetNameLoc,
+ DeclarationName TargetName) {
+ return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc,
+ TargetNNR, TargetNNS,
+ TargetNameLoc,
+ TargetName.getAsIdentifierInfo());
+}
+
+StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, Expr *AssertExpr,
+ StringLiteral *Message) {
+ return new (C) StaticAssertDecl(DC, L, AssertExpr, Message);
+}
+
+static const char *getAccessName(AccessSpecifier AS) {
+ switch (AS) {
+ default:
+ case AS_none:
+ assert("Invalid access specifier!");
+ return 0;
+ case AS_public:
+ return "public";
+ case AS_private:
+ return "private";
+ case AS_protected:
+ return "protected";
+ }
+}
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ AccessSpecifier AS) {
+ return DB << getAccessName(AS);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
new file mode 100644
index 0000000..99bfe40
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
@@ -0,0 +1,45 @@
+//===--- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AST classes related to C++ friend
+// declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclTemplate.h"
+using namespace clang;
+
+FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ FriendUnion Friend,
+ SourceLocation FriendL) {
+#ifndef NDEBUG
+ if (Friend.is<NamedDecl*>()) {
+ NamedDecl *D = Friend.get<NamedDecl*>();
+ assert(isa<FunctionDecl>(D) ||
+ isa<CXXRecordDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) ||
+ isa<ClassTemplateDecl>(D));
+
+ // As a temporary hack, we permit template instantiation to point
+ // to the original declaration when instantiating members.
+ assert(D->getFriendObjectKind() ||
+ (cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
+ }
+#endif
+
+ FriendDecl *FD = new (C) FriendDecl(DC, L, Friend, FriendL);
+ cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
+ return FD;
+}
+
+FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) FriendDecl(Empty);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
new file mode 100644
index 0000000..036acc2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
@@ -0,0 +1,32 @@
+//===--- DeclGroup.cpp - Classes for representing groups of Decls -*- 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 DeclGroup and DeclGroupRef classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/Support/Allocator.h"
+using namespace clang;
+
+DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ assert(NumDecls > 1 && "Invalid DeclGroup");
+ unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+ void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
+ new (Mem) DeclGroup(NumDecls, Decls);
+ return static_cast<DeclGroup*>(Mem);
+}
+
+DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) {
+ assert(numdecls > 0);
+ assert(decls);
+ memcpy(this+1, decls, numdecls * sizeof(*decls));
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
new file mode 100644
index 0000000..45f5188
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -0,0 +1,953 @@
+//===--- DeclObjC.cpp - ObjC Declaration AST Node Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Objective-C related Decl classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// ObjCListBase
+//===----------------------------------------------------------------------===//
+
+void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
+ List = 0;
+ if (Elts == 0) return; // Setting to an empty list is a noop.
+
+
+ List = new (Ctx) void*[Elts];
+ NumElts = Elts;
+ memcpy(List, InList, sizeof(void*)*Elts);
+}
+
+void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
+ const SourceLocation *Locs, ASTContext &Ctx) {
+ if (Elts == 0)
+ return;
+
+ Locations = new (Ctx) SourceLocation[Elts];
+ memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
+ set(InList, Elts, Ctx);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCInterfaceDecl
+//===----------------------------------------------------------------------===//
+
+/// getIvarDecl - This method looks up an ivar in this ContextDecl.
+///
+ObjCIvarDecl *
+ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const {
+ lookup_const_iterator Ivar, IvarEnd;
+ for (llvm::tie(Ivar, IvarEnd) = lookup(Id); Ivar != IvarEnd; ++Ivar) {
+ if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar))
+ return ivar;
+ }
+ return 0;
+}
+
+// Get the local instance/class method declared in this interface.
+ObjCMethodDecl *
+ObjCContainerDecl::getMethod(Selector Sel, bool isInstance) const {
+ // Since instance & class methods can have the same name, the loop below
+ // ensures we get the correct method.
+ //
+ // @interface Whatever
+ // - (int) class_method;
+ // + (float) class_method;
+ // @end
+ //
+ lookup_const_iterator Meth, MethEnd;
+ for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) {
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+ if (MD && MD->isInstanceMethod() == isInstance)
+ return MD;
+ }
+ return 0;
+}
+
+ObjCPropertyDecl *
+ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
+ IdentifierInfo *propertyID) {
+
+ DeclContext::lookup_const_iterator I, E;
+ llvm::tie(I, E) = DC->lookup(propertyID);
+ for ( ; I != E; ++I)
+ if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I))
+ return PD;
+
+ return 0;
+}
+
+/// FindPropertyDeclaration - Finds declaration of the property given its name
+/// in 'PropertyId' and returns it. It returns 0, if not found.
+ObjCPropertyDecl *
+ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
+
+ if (ObjCPropertyDecl *PD =
+ ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
+ return PD;
+
+ switch (getKind()) {
+ default:
+ break;
+ case Decl::ObjCProtocol: {
+ const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this);
+ for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
+ E = PID->protocol_end(); I != E; ++I)
+ if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+ return P;
+ break;
+ }
+ case Decl::ObjCInterface: {
+ const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
+ // Look through categories.
+ for (ObjCCategoryDecl *Cat = OID->getCategoryList();
+ Cat; Cat = Cat->getNextClassCategory())
+ if (!Cat->IsClassExtension())
+ if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))
+ return P;
+
+ // Look through protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); I != E; ++I)
+ if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+ return P;
+
+ // Finally, check the super class.
+ if (const ObjCInterfaceDecl *superClass = OID->getSuperClass())
+ return superClass->FindPropertyDeclaration(PropertyId);
+ break;
+ }
+ case Decl::ObjCCategory: {
+ const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this);
+ // Look through protocols.
+ if (!OCD->IsClassExtension())
+ for (ObjCCategoryDecl::protocol_iterator
+ I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I)
+ if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+ return P;
+
+ break;
+ }
+ }
+ return 0;
+}
+
+/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
+/// with name 'PropertyId' in the primary class; including those in protocols
+/// (direct or indirect) used by the primary class.
+///
+ObjCPropertyDecl *
+ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
+ IdentifierInfo *PropertyId) const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ if (ObjCPropertyDecl *PD =
+ ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
+ return PD;
+
+ // Look through protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = all_referenced_protocol_begin(),
+ E = all_referenced_protocol_end(); I != E; ++I)
+ if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
+ return P;
+
+ return 0;
+}
+
+void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
+ ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
+ ASTContext &C)
+{
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
+ AllReferencedProtocols.set(ExtList, ExtNum, C);
+ return;
+ }
+
+ // Check for duplicate protocol in class's protocol list.
+ // This is O(n*m). But it is extremely rare and number of protocols in
+ // class or its extension are very few.
+ llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
+ for (unsigned i = 0; i < ExtNum; i++) {
+ bool protocolExists = false;
+ ObjCProtocolDecl *ProtoInExtension = ExtList[i];
+ for (all_protocol_iterator
+ p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
+ ObjCProtocolDecl *Proto = (*p);
+ if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
+ protocolExists = true;
+ break;
+ }
+ }
+ // Do we want to warn on a protocol in extension class which
+ // already exist in the class? Probably not.
+ if (!protocolExists)
+ ProtocolRefs.push_back(ProtoInExtension);
+ }
+
+ if (ProtocolRefs.empty())
+ return;
+
+ // Merge ProtocolRefs into class's protocol list;
+ for (all_protocol_iterator p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
+ ProtocolRefs.push_back(*p);
+ }
+
+ AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
+}
+
+/// getFirstClassExtension - Find first class extension of the given class.
+ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const {
+ for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl;
+ CDecl = CDecl->getNextClassCategory())
+ if (CDecl->IsClassExtension())
+ return CDecl;
+ return 0;
+}
+
+/// getNextClassCategory - Find next class extension in list of categories.
+const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const {
+ for (const ObjCCategoryDecl *CDecl = getNextClassCategory(); CDecl;
+ CDecl = CDecl->getNextClassCategory())
+ if (CDecl->IsClassExtension())
+ return CDecl;
+ return 0;
+}
+
+ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
+ ObjCInterfaceDecl *&clsDeclared) {
+ ObjCInterfaceDecl* ClassDecl = this;
+ while (ClassDecl != NULL) {
+ if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
+ clsDeclared = ClassDecl;
+ return I;
+ }
+ for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension();
+ CDecl; CDecl = CDecl->getNextClassExtension()) {
+ if (ObjCIvarDecl *I = CDecl->getIvarDecl(ID)) {
+ clsDeclared = ClassDecl;
+ return I;
+ }
+ }
+
+ ClassDecl = ClassDecl->getSuperClass();
+ }
+ return NULL;
+}
+
+/// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super
+/// class whose name is passed as argument. If it is not one of the super classes
+/// the it returns NULL.
+ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
+ const IdentifierInfo*ICName) {
+ ObjCInterfaceDecl* ClassDecl = this;
+ while (ClassDecl != NULL) {
+ if (ClassDecl->getIdentifier() == ICName)
+ return ClassDecl;
+ ClassDecl = ClassDecl->getSuperClass();
+ }
+ return NULL;
+}
+
+/// lookupMethod - This method returns an instance/class method by looking in
+/// the class, its categories, and its super classes (using a linear search).
+ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
+ bool isInstance) const {
+ const ObjCInterfaceDecl* ClassDecl = this;
+ ObjCMethodDecl *MethodDecl = 0;
+
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ while (ClassDecl != NULL) {
+ if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
+ return MethodDecl;
+
+ // Didn't find one yet - look through protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ ClassDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I)
+ if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+
+ // Didn't find one yet - now look through categories.
+ ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
+ while (CatDecl) {
+ if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
+ return MethodDecl;
+
+ // Didn't find one yet - look through protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I)
+ if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+ CatDecl = CatDecl->getNextClassCategory();
+ }
+ ClassDecl = ClassDecl->getSuperClass();
+ }
+ return NULL;
+}
+
+ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
+ const Selector &Sel,
+ bool Instance) {
+ ObjCMethodDecl *Method = 0;
+ if (ObjCImplementationDecl *ImpDecl = getImplementation())
+ Method = Instance ? ImpDecl->getInstanceMethod(Sel)
+ : ImpDecl->getClassMethod(Sel);
+
+ if (!Method && getSuperClass())
+ return getSuperClass()->lookupPrivateMethod(Sel, Instance);
+ return Method;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCMethodDecl
+//===----------------------------------------------------------------------===//
+
+ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
+ SourceLocation beginLoc,
+ SourceLocation endLoc,
+ Selector SelInfo, QualType T,
+ TypeSourceInfo *ResultTInfo,
+ DeclContext *contextDecl,
+ bool isInstance,
+ bool isVariadic,
+ bool isSynthesized,
+ bool isDefined,
+ ImplementationControl impControl,
+ unsigned numSelectorArgs) {
+ return new (C) ObjCMethodDecl(beginLoc, endLoc,
+ SelInfo, T, ResultTInfo, contextDecl,
+ isInstance,
+ isVariadic, isSynthesized, isDefined,
+ impControl,
+ numSelectorArgs);
+}
+
+/// \brief A definition will return its interface declaration.
+/// An interface declaration will return its definition.
+/// Otherwise it will return itself.
+ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
+ ASTContext &Ctx = getASTContext();
+ ObjCMethodDecl *Redecl = 0;
+ Decl *CtxD = cast<Decl>(getDeclContext());
+
+ if (ObjCInterfaceDecl *IFD = dyn_cast<ObjCInterfaceDecl>(CtxD)) {
+ if (ObjCImplementationDecl *ImplD = Ctx.getObjCImplementation(IFD))
+ Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
+
+ } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(CtxD)) {
+ if (ObjCCategoryImplDecl *ImplD = Ctx.getObjCImplementation(CD))
+ Redecl = ImplD->getMethod(getSelector(), isInstanceMethod());
+
+ } else if (ObjCImplementationDecl *ImplD =
+ dyn_cast<ObjCImplementationDecl>(CtxD)) {
+ if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
+ Redecl = IFD->getMethod(getSelector(), isInstanceMethod());
+
+ } else if (ObjCCategoryImplDecl *CImplD =
+ dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
+ if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
+ Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
+ }
+
+ return Redecl ? Redecl : this;
+}
+
+ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
+ Decl *CtxD = cast<Decl>(getDeclContext());
+
+ if (ObjCImplementationDecl *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
+ if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
+ if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
+ isInstanceMethod()))
+ return MD;
+
+ } else if (ObjCCategoryImplDecl *CImplD =
+ dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
+ if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
+ if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
+ isInstanceMethod()))
+ return MD;
+ }
+
+ return this;
+}
+
+void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
+ const ObjCInterfaceDecl *OID) {
+ QualType selfTy;
+ if (isInstanceMethod()) {
+ // There may be no interface context due to error in declaration
+ // of the interface (which has been reported). Recover gracefully.
+ if (OID) {
+ selfTy = Context.getObjCInterfaceType(OID);
+ selfTy = Context.getObjCObjectPointerType(selfTy);
+ } else {
+ selfTy = Context.getObjCIdType();
+ }
+ } else // we have a factory method.
+ selfTy = Context.getObjCClassType();
+
+ setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
+ &Context.Idents.get("self"), selfTy));
+
+ setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
+ &Context.Idents.get("_cmd"),
+ Context.getObjCSelType()));
+}
+
+ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
+ return ID;
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
+ return CD->getClassInterface();
+ if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext()))
+ return IMD->getClassInterface();
+
+ assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method");
+ assert(false && "unknown method context");
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCInterfaceDecl
+//===----------------------------------------------------------------------===//
+
+ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation atLoc,
+ IdentifierInfo *Id,
+ SourceLocation ClassLoc,
+ bool ForwardDecl, bool isInternal){
+ return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
+ isInternal);
+}
+
+ObjCInterfaceDecl::
+ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
+ SourceLocation CLoc, bool FD, bool isInternal)
+ : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
+ TypeForDecl(0), SuperClass(0),
+ CategoryList(0), IvarList(0),
+ 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<ObjCInterfaceDecl *>(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<ObjCInterfaceDecl*>(this));
+}
+
+void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
+ getASTContext().setObjCImplementation(this, ImplD);
+}
+
+/// all_declared_ivar_begin - return first ivar declared in this class,
+/// its extensions and its implementation. Lazily build the list on first
+/// access.
+ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
+ if (IvarList)
+ return IvarList;
+
+ ObjCIvarDecl *curIvar = 0;
+ if (!ivar_empty()) {
+ ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
+ IvarList = (*I); ++I;
+ for (curIvar = IvarList; I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+
+ for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension()) {
+ if (!CDecl->ivar_empty()) {
+ ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
+ E = CDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+
+ if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
+ if (!ImplDecl->ivar_empty()) {
+ ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
+ E = ImplDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+ return IvarList;
+}
+
+/// FindCategoryDeclaration - Finds category declaration in the list of
+/// categories for this class and returns it. Name of the category is passed
+/// in 'CategoryId'. If category not found, return 0;
+///
+ObjCCategoryDecl *
+ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
+ if (ExternallyCompleted)
+ LoadExternalDefinition();
+
+ for (ObjCCategoryDecl *Category = getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (Category->getIdentifier() == CategoryId)
+ return Category;
+ return 0;
+}
+
+ObjCMethodDecl *
+ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const {
+ for (ObjCCategoryDecl *Category = getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (ObjCCategoryImplDecl *Impl = Category->getImplementation())
+ if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel))
+ return MD;
+ return 0;
+}
+
+ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
+ for (ObjCCategoryDecl *Category = getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (ObjCCategoryImplDecl *Impl = Category->getImplementation())
+ if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel))
+ return MD;
+ return 0;
+}
+
+/// ClassImplementsProtocol - Checks that 'lProto' protocol
+/// has been implemented in IDecl class, its super class or categories (if
+/// lookupCategory is true).
+bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+ bool lookupCategory,
+ bool RHSIsQualifiedID) {
+ ObjCInterfaceDecl *IDecl = this;
+ // 1st, look up the class.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ IDecl->getReferencedProtocols();
+
+ for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
+ E = Protocols.end(); PI != E; ++PI) {
+ if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
+ return true;
+ // This is dubious and is added to be compatible with gcc. In gcc, it is
+ // also allowed assigning a protocol-qualified 'id' type to a LHS object
+ // when protocol in qualified LHS is in list of protocols in the rhs 'id'
+ // object. This IMO, should be a bug.
+ // FIXME: Treat this as an extension, and flag this as an error when GCC
+ // extensions are not enabled.
+ if (RHSIsQualifiedID &&
+ getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto))
+ return true;
+ }
+
+ // 2nd, look up the category.
+ if (lookupCategory)
+ for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
+ CDecl = CDecl->getNextClassCategory()) {
+ for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
+ E = CDecl->protocol_end(); PI != E; ++PI)
+ if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
+ return true;
+ }
+
+ // 3rd, look up the super class(s)
+ if (IDecl->getSuperClass())
+ return
+ IDecl->getSuperClass()->ClassImplementsProtocol(lProto, lookupCategory,
+ RHSIsQualifiedID);
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCIvarDecl
+//===----------------------------------------------------------------------===//
+
+ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo,
+ AccessControl ac, Expr *BW,
+ bool synthesized) {
+ if (DC) {
+ // Ivar's can only appear in interfaces, implementations (via synthesized
+ // properties), and class extensions (via direct declaration, or synthesized
+ // properties).
+ //
+ // FIXME: This should really be asserting this:
+ // (isa<ObjCCategoryDecl>(DC) &&
+ // cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
+ // but unfortunately we sometimes place ivars into non-class extension
+ // categories on error. This breaks an AST invariant, and should not be
+ // fixed.
+ assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
+ isa<ObjCCategoryDecl>(DC)) &&
+ "Invalid ivar decl context!");
+ // Once a new ivar is created in any of class/class-extension/implementation
+ // decl contexts, the previously built IvarList must be rebuilt.
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
+ if (!ID) {
+ if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) {
+ ID = IM->getClassInterface();
+ if (BW)
+ IM->setHasSynthBitfield(true);
+ }
+ else {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+ ID = CD->getClassInterface();
+ if (BW)
+ CD->setHasSynthBitfield(true);
+ }
+ }
+ ID->setIvarList(0);
+ }
+
+ return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized);
+}
+
+const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
+ const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());
+
+ switch (DC->getKind()) {
+ default:
+ case ObjCCategoryImpl:
+ case ObjCProtocol:
+ assert(0 && "invalid ivar container!");
+ return 0;
+
+ // Ivars can only appear in class extension categories.
+ case ObjCCategory: {
+ const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+ assert(CD->IsClassExtension() && "invalid container for ivar!");
+ return CD->getClassInterface();
+ }
+
+ case ObjCImplementation:
+ return cast<ObjCImplementationDecl>(DC)->getClassInterface();
+
+ case ObjCInterface:
+ return cast<ObjCInterfaceDecl>(DC);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCAtDefsFieldDecl
+//===----------------------------------------------------------------------===//
+
+ObjCAtDefsFieldDecl
+*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *BW) {
+ return new (C) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCProtocolDecl
+//===----------------------------------------------------------------------===//
+
+ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id) {
+ return new (C) ObjCProtocolDecl(DC, L, Id);
+}
+
+ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
+ ObjCProtocolDecl *PDecl = this;
+
+ if (Name == getIdentifier())
+ return PDecl;
+
+ for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
+ if ((PDecl = (*I)->lookupProtocolNamed(Name)))
+ return PDecl;
+
+ return NULL;
+}
+
+// lookupMethod - Lookup a instance/class method in the protocol and protocols
+// it inherited.
+ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
+ bool isInstance) const {
+ ObjCMethodDecl *MethodDecl = NULL;
+
+ if ((MethodDecl = getMethod(Sel, isInstance)))
+ return MethodDecl;
+
+ for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I)
+ if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCClassDecl
+//===----------------------------------------------------------------------===//
+
+ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *const *Elts,
+ const SourceLocation *Locs,
+ unsigned nElts,
+ ASTContext &C)
+ : Decl(ObjCClass, DC, L) {
+ setClassList(C, Elts, Locs, nElts);
+}
+
+void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
+ const SourceLocation *Locs, unsigned Num) {
+ ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num,
+ llvm::alignOf<ObjCClassRef>());
+ for (unsigned i = 0; i < Num; ++i)
+ new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]);
+
+ NumDecls = Num;
+}
+
+ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCInterfaceDecl *const *Elts,
+ const SourceLocation *Locs,
+ unsigned nElts) {
+ return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
+}
+
+SourceRange ObjCClassDecl::getSourceRange() const {
+ // FIXME: We should include the semicolon
+ assert(NumDecls);
+ return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation());
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCForwardProtocolDecl
+//===----------------------------------------------------------------------===//
+
+ObjCForwardProtocolDecl::
+ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
+ ObjCProtocolDecl *const *Elts, unsigned nElts,
+ const SourceLocation *Locs, ASTContext &C)
+: Decl(ObjCForwardProtocol, DC, L) {
+ ReferencedProtocols.set(Elts, nElts, Locs, C);
+}
+
+
+ObjCForwardProtocolDecl *
+ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCProtocolDecl *const *Elts,
+ unsigned NumElts,
+ const SourceLocation *Locs) {
+ return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCCategoryDecl
+//===----------------------------------------------------------------------===//
+
+ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id) {
+ return new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id);
+}
+
+ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
+ return getASTContext().getObjCImplementation(
+ const_cast<ObjCCategoryDecl*>(this));
+}
+
+void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
+ getASTContext().setObjCImplementation(this, ImplD);
+}
+
+
+//===----------------------------------------------------------------------===//
+// ObjCCategoryImplDecl
+//===----------------------------------------------------------------------===//
+
+ObjCCategoryImplDecl *
+ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,IdentifierInfo *Id,
+ ObjCInterfaceDecl *ClassInterface) {
+ return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface);
+}
+
+ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
+ // The class interface might be NULL if we are working with invalid code.
+ if (const ObjCInterfaceDecl *ID = getClassInterface())
+ return ID->FindCategoryDeclaration(getIdentifier());
+ return 0;
+}
+
+
+void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
+ // FIXME: The context should be correct before we get here.
+ property->setLexicalDeclContext(this);
+ addDecl(property);
+}
+
+void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) {
+ ASTContext &Ctx = getASTContext();
+
+ if (ObjCImplementationDecl *ImplD
+ = dyn_cast_or_null<ObjCImplementationDecl>(this)) {
+ if (IFace)
+ Ctx.setObjCImplementation(IFace, ImplD);
+
+ } else if (ObjCCategoryImplDecl *ImplD =
+ dyn_cast_or_null<ObjCCategoryImplDecl>(this)) {
+ if (ObjCCategoryDecl *CD = IFace->FindCategoryDeclaration(getIdentifier()))
+ Ctx.setObjCImplementation(CD, ImplD);
+ }
+
+ ClassInterface = IFace;
+}
+
+/// FindPropertyImplIvarDecl - This method lookup the ivar in the list of
+/// properties implemented in this category @implementation block and returns
+/// the implemented property that uses it.
+///
+ObjCPropertyImplDecl *ObjCImplDecl::
+FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const {
+ for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
+ ObjCPropertyImplDecl *PID = *i;
+ if (PID->getPropertyIvarDecl() &&
+ PID->getPropertyIvarDecl()->getIdentifier() == ivarId)
+ return PID;
+ }
+ return 0;
+}
+
+/// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl
+/// added to the list of those properties @synthesized/@dynamic in this
+/// category @implementation block.
+///
+ObjCPropertyImplDecl *ObjCImplDecl::
+FindPropertyImplDecl(IdentifierInfo *Id) const {
+ for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){
+ ObjCPropertyImplDecl *PID = *i;
+ if (PID->getPropertyDecl()->getIdentifier() == Id)
+ return PID;
+ }
+ return 0;
+}
+
+llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+ const ObjCCategoryImplDecl *CID) {
+ OS << CID->getName();
+ return OS;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCImplementationDecl
+//===----------------------------------------------------------------------===//
+
+ObjCImplementationDecl *
+ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCInterfaceDecl *ClassInterface,
+ ObjCInterfaceDecl *SuperDecl) {
+ return new (C) ObjCImplementationDecl(DC, L, ClassInterface, SuperDecl);
+}
+
+llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
+ const ObjCImplementationDecl *ID) {
+ OS << ID->getName();
+ return OS;
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCCompatibleAliasDecl
+//===----------------------------------------------------------------------===//
+
+ObjCCompatibleAliasDecl *
+ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id,
+ ObjCInterfaceDecl* AliasedClass) {
+ return new (C) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCPropertyDecl
+//===----------------------------------------------------------------------===//
+
+ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id,
+ SourceLocation AtLoc,
+ TypeSourceInfo *T,
+ PropertyControl propControl) {
+ return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T);
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCPropertyImplDecl
+//===----------------------------------------------------------------------===//
+
+ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation atLoc,
+ SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ 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/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
new file mode 100644
index 0000000..77b4257
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -0,0 +1,940 @@
+//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Decl::dump method, which pretty print the
+// AST back out to C/Objective-C/C++/Objective-C++ code.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+ class DeclPrinter : public DeclVisitor<DeclPrinter> {
+ llvm::raw_ostream &Out;
+ ASTContext &Context;
+ PrintingPolicy Policy;
+ unsigned Indentation;
+
+ llvm::raw_ostream& Indent() { return Indent(Indentation); }
+ llvm::raw_ostream& Indent(unsigned Indentation);
+ void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
+
+ void Print(AccessSpecifier AS);
+
+ public:
+ DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context,
+ const PrintingPolicy &Policy,
+ unsigned Indentation = 0)
+ : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { }
+
+ void VisitDeclContext(DeclContext *DC, bool Indent = true);
+
+ void VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ void VisitTypedefDecl(TypedefDecl *D);
+ void VisitEnumDecl(EnumDecl *D);
+ void VisitRecordDecl(RecordDecl *D);
+ void VisitEnumConstantDecl(EnumConstantDecl *D);
+ 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);
+ void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ void VisitCXXRecordDecl(CXXRecordDecl *D);
+ void VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ void VisitTemplateDecl(TemplateDecl *D);
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCClassDecl(ObjCClassDecl *D);
+ void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+ void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+ void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+ void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
+ void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingShadowDecl(UsingShadowDecl *D);
+ };
+}
+
+void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const {
+ print(Out, getASTContext().PrintingPolicy, Indentation);
+}
+
+void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation) const {
+ DeclPrinter Printer(Out, getASTContext(), Policy, Indentation);
+ Printer.Visit(const_cast<Decl*>(this));
+}
+
+static QualType GetBaseType(QualType T) {
+ // FIXME: This should be on the Type class!
+ QualType BaseType = T;
+ while (!BaseType->isSpecifierType()) {
+ if (isa<TypedefType>(BaseType))
+ break;
+ else if (const PointerType* PTy = BaseType->getAs<PointerType>())
+ BaseType = PTy->getPointeeType();
+ else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
+ BaseType = ATy->getElementType();
+ else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
+ BaseType = FTy->getResultType();
+ else if (const VectorType *VTy = BaseType->getAs<VectorType>())
+ BaseType = VTy->getElementType();
+ else
+ assert(0 && "Unknown declarator!");
+ }
+ return BaseType;
+}
+
+static QualType getDeclType(Decl* D) {
+ if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D))
+ return TDD->getUnderlyingType();
+ if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
+ return VD->getType();
+ return QualType();
+}
+
+void Decl::printGroup(Decl** Begin, unsigned NumDecls,
+ llvm::raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation) {
+ if (NumDecls == 1) {
+ (*Begin)->print(Out, Policy, Indentation);
+ return;
+ }
+
+ Decl** End = Begin + NumDecls;
+ TagDecl* TD = dyn_cast<TagDecl>(*Begin);
+ if (TD)
+ ++Begin;
+
+ PrintingPolicy SubPolicy(Policy);
+ if (TD && TD->isDefinition()) {
+ TD->print(Out, Policy, Indentation);
+ Out << " ";
+ SubPolicy.SuppressTag = true;
+ }
+
+ bool isFirst = true;
+ for ( ; Begin != End; ++Begin) {
+ if (isFirst) {
+ SubPolicy.SuppressSpecifiers = false;
+ isFirst = false;
+ } else {
+ if (!isFirst) Out << ", ";
+ SubPolicy.SuppressSpecifiers = true;
+ }
+
+ (*Begin)->print(Out, SubPolicy, Indentation);
+ }
+}
+
+void DeclContext::dumpDeclContext() const {
+ // Get the translation unit
+ const DeclContext *DC = this;
+ while (!DC->isTranslationUnit())
+ DC = DC->getParent();
+
+ ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
+ DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0);
+ Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
+}
+
+void Decl::dump() const {
+ print(llvm::errs());
+}
+
+llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
+ for (unsigned i = 0; i != Indentation; ++i)
+ Out << " ";
+ return Out;
+}
+
+void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
+ this->Indent();
+ Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
+ Out << ";\n";
+ Decls.clear();
+
+}
+
+void DeclPrinter::Print(AccessSpecifier AS) {
+ switch(AS) {
+ case AS_none: assert(0 && "No access specifier!"); break;
+ case AS_public: Out << "public"; break;
+ case AS_protected: Out << "protected"; break;
+ case AS_private: Out << "private"; break;
+ }
+}
+
+//----------------------------------------------------------------------------
+// Common C declarations
+//----------------------------------------------------------------------------
+
+void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
+ if (Indent)
+ Indentation += Policy.Indentation;
+
+ llvm::SmallVector<Decl*, 2> Decls;
+ for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
+ D != DEnd; ++D) {
+
+ // Don't print ObjCIvarDecls, as they are printed when visiting the
+ // containing ObjCInterfaceDecl.
+ if (isa<ObjCIvarDecl>(*D))
+ continue;
+
+ if (!Policy.Dump) {
+ // Skip over implicit declarations in pretty-printing mode.
+ if (D->isImplicit()) continue;
+ // FIXME: Ugly hack so we don't pretty-print the builtin declaration
+ // of __builtin_va_list or __[u]int128_t. There should be some other way
+ // to check that.
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
+ if (IdentifierInfo *II = ND->getIdentifier()) {
+ if (II->isStr("__builtin_va_list") ||
+ II->isStr("__int128_t") || II->isStr("__uint128_t"))
+ continue;
+ }
+ }
+ }
+
+ // The next bits of code handles stuff like "struct {int x;} a,b"; we're
+ // forced to merge the declarations because there's no other way to
+ // refer to the struct in question. This limited merging is safe without
+ // a bunch of other checks because it only merges declarations directly
+ // referring to the tag, not typedefs.
+ //
+ // Check whether the current declaration should be grouped with a previous
+ // unnamed struct.
+ QualType CurDeclType = getDeclType(*D);
+ if (!Decls.empty() && !CurDeclType.isNull()) {
+ QualType BaseType = GetBaseType(CurDeclType);
+ if (!BaseType.isNull() && isa<TagType>(BaseType) &&
+ cast<TagType>(BaseType)->getDecl() == Decls[0]) {
+ Decls.push_back(*D);
+ continue;
+ }
+ }
+
+ // If we have a merged group waiting to be handled, handle it now.
+ if (!Decls.empty())
+ ProcessDeclGroup(Decls);
+
+ // If the current declaration is an unnamed tag type, save it
+ // so we can merge it with the subsequent declaration(s) using it.
+ if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
+ Decls.push_back(*D);
+ continue;
+ }
+
+ if (isa<AccessSpecDecl>(*D)) {
+ Indentation -= Policy.Indentation;
+ this->Indent();
+ Print(D->getAccess());
+ Out << ":\n";
+ Indentation += Policy.Indentation;
+ continue;
+ }
+
+ this->Indent();
+ Visit(*D);
+
+ // FIXME: Need to be able to tell the DeclPrinter when
+ const char *Terminator = 0;
+ if (isa<FunctionDecl>(*D) &&
+ cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
+ Terminator = 0;
+ else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
+ Terminator = 0;
+ else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
+ isa<ObjCImplementationDecl>(*D) ||
+ isa<ObjCInterfaceDecl>(*D) ||
+ isa<ObjCProtocolDecl>(*D) ||
+ isa<ObjCCategoryImplDecl>(*D) ||
+ isa<ObjCCategoryDecl>(*D))
+ Terminator = 0;
+ else if (isa<EnumConstantDecl>(*D)) {
+ DeclContext::decl_iterator Next = D;
+ ++Next;
+ if (Next != DEnd)
+ Terminator = ",";
+ } else
+ Terminator = ";";
+
+ if (Terminator)
+ Out << Terminator;
+ Out << "\n";
+ }
+
+ if (!Decls.empty())
+ ProcessDeclGroup(Decls);
+
+ if (Indent)
+ Indentation -= Policy.Indentation;
+}
+
+void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ VisitDeclContext(D, false);
+}
+
+void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
+ std::string S = D->getNameAsString();
+ D->getUnderlyingType().getAsStringInternal(S, Policy);
+ if (!Policy.SuppressSpecifiers)
+ Out << "typedef ";
+ Out << S;
+}
+
+void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
+ 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) {
+ Out << D->getKindName();
+ if (D->getIdentifier())
+ Out << ' ' << D;
+
+ if (D->isDefinition()) {
+ Out << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+ }
+}
+
+void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ Out << D;
+ if (Expr *Init = D->getInitExpr()) {
+ Out << " = ";
+ Init->printPretty(Out, Context, 0, Policy, Indentation);
+ }
+}
+
+void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
+ if (!Policy.SuppressSpecifiers) {
+ switch (D->getStorageClass()) {
+ case SC_None: break;
+ case SC_Extern: Out << "extern "; break;
+ case SC_Static: Out << "static "; break;
+ case SC_PrivateExtern: Out << "__private_extern__ "; break;
+ case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
+ }
+
+ if (D->isInlineSpecified()) Out << "inline ";
+ if (D->isVirtualAsWritten()) Out << "virtual ";
+ }
+
+ PrintingPolicy SubPolicy(Policy);
+ SubPolicy.SuppressSpecifiers = false;
+ std::string Proto = D->getNameInfo().getAsString();
+
+ QualType Ty = D->getType();
+ while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
+ Proto = '(' + Proto + ')';
+ Ty = PT->getInnerType();
+ }
+
+ if (isa<FunctionType>(Ty)) {
+ const FunctionType *AFT = Ty->getAs<FunctionType>();
+ const FunctionProtoType *FT = 0;
+ if (D->hasWrittenPrototype())
+ FT = dyn_cast<FunctionProtoType>(AFT);
+
+ Proto += "(";
+ if (FT) {
+ llvm::raw_string_ostream POut(Proto);
+ DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation);
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ if (i) POut << ", ";
+ ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
+ }
+
+ if (FT->isVariadic()) {
+ if (D->getNumParams()) POut << ", ";
+ POut << "...";
+ }
+ } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) {
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ if (i)
+ Proto += ", ";
+ Proto += D->getParamDecl(i)->getNameAsString();
+ }
+ }
+
+ 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())
+ Proto += "...";
+ else
+ for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
+ if (I)
+ Proto += ", ";
+
+
+ std::string ExceptionType;
+ FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy);
+ Proto += ExceptionType;
+ }
+ Proto += ")";
+ }
+
+ if (D->hasAttr<NoReturnAttr>())
+ Proto += " __attribute((noreturn))";
+ if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
+ 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) {
+ CXXCtorInitializer * BMInitializer = (*B);
+ if (B != CDecl->init_begin())
+ Out << ", ";
+ if (BMInitializer->isAnyMemberInitializer()) {
+ FieldDecl *FD = BMInitializer->getAnyMember();
+ Out << FD;
+ } else {
+ Out << QualType(BMInitializer->getBaseClass(),
+ 0).getAsString(Policy);
+ }
+
+ Out << "(";
+ if (!BMInitializer->getInit()) {
+ // Nothing to print
+ } else {
+ Expr *Init = BMInitializer->getInit();
+ if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
+ Init = Tmp->getSubExpr();
+
+ Init = Init->IgnoreParens();
+
+ Expr *SimpleInit = 0;
+ Expr **Args = 0;
+ unsigned NumArgs = 0;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ } else if (CXXConstructExpr *Construct
+ = dyn_cast<CXXConstructExpr>(Init)) {
+ Args = Construct->getArgs();
+ NumArgs = Construct->getNumArgs();
+ } else
+ SimpleInit = Init;
+
+ if (SimpleInit)
+ SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
+ else {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ if (isa<CXXDefaultArgExpr>(Args[I]))
+ break;
+
+ if (I)
+ Out << ", ";
+ Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
+ }
+ }
+ }
+ Out << ")";
+ }
+ }
+ }
+ else
+ AFT->getResultType().getAsStringInternal(Proto, Policy);
+ } else {
+ Ty.getAsStringInternal(Proto, Policy);
+ }
+
+ Out << Proto;
+
+ if (D->isPure())
+ Out << " = 0";
+ else if (D->isDeleted())
+ Out << " = delete";
+ else if (D->isThisDeclarationADefinition()) {
+ if (!D->hasPrototype() && D->getNumParams()) {
+ // This is a K&R function definition, so we need to print the
+ // parameters.
+ Out << '\n';
+ DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation);
+ Indentation += Policy.Indentation;
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ Indent();
+ ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
+ Out << ";\n";
+ }
+ Indentation -= Policy.Indentation;
+ } else
+ Out << ' ';
+
+ D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation);
+ Out << '\n';
+ }
+}
+
+void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
+ if (!Policy.SuppressSpecifiers && D->isMutable())
+ Out << "mutable ";
+
+ std::string Name = D->getNameAsString();
+ D->getType().getAsStringInternal(Name, Policy);
+ Out << Name;
+
+ if (D->isBitField()) {
+ Out << " : ";
+ D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
+ }
+}
+
+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()) << " ";
+
+ if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
+ Out << "__thread ";
+
+ std::string Name = D->getNameAsString();
+ QualType T = D->getType();
+ if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
+ T = Parm->getOriginalType();
+ T.getAsStringInternal(Name, Policy);
+ Out << Name;
+ if (Expr *Init = D->getInit()) {
+ if (D->hasCXXDirectInitializer())
+ Out << "(";
+ else {
+ CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
+ if (!CCE || CCE->getConstructor()->isCopyConstructor())
+ Out << " = ";
+ }
+ Init->printPretty(Out, Context, 0, Policy, Indentation);
+ if (D->hasCXXDirectInitializer())
+ Out << ")";
+ }
+}
+
+void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
+ VisitVarDecl(D);
+}
+
+void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
+ Out << "__asm (";
+ D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation);
+ Out << ")";
+}
+
+//----------------------------------------------------------------------------
+// C++ declarations
+//----------------------------------------------------------------------------
+void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
+ Out << "namespace " << D << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+}
+
+void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ Out << "using namespace ";
+ if (D->getQualifier())
+ D->getQualifier()->print(Out, Policy);
+ Out << D->getNominatedNamespaceAsWritten();
+}
+
+void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ Out << "namespace " << D << " = ";
+ if (D->getQualifier())
+ D->getQualifier()->print(Out, Policy);
+ Out << D->getAliasedNamespace();
+}
+
+void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ Out << D->getKindName();
+ if (D->getIdentifier())
+ Out << ' ' << D;
+
+ if (D->isDefinition()) {
+ // Print the base classes
+ if (D->getNumBases()) {
+ Out << " : ";
+ for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
+ BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
+ if (Base != D->bases_begin())
+ Out << ", ";
+
+ if (Base->isVirtual())
+ Out << "virtual ";
+
+ AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
+ if (AS != AS_none)
+ Print(AS);
+ Out << " " << Base->getType().getAsString(Policy);
+ }
+ }
+
+ // Print the class definition
+ // FIXME: Doesn't print access specifiers, e.g., "public:"
+ Out << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+ }
+}
+
+void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ const char *l;
+ if (D->getLanguage() == LinkageSpecDecl::lang_c)
+ l = "C";
+ else {
+ assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
+ "unknown language in linkage specification");
+ l = "C++";
+ }
+
+ Out << "extern \"" << l << "\" ";
+ if (D->hasBraces()) {
+ Out << "{\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+ } else
+ Visit(*D->decls_begin());
+}
+
+void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
+ Out << "template <";
+
+ TemplateParameterList *Params = D->getTemplateParameters();
+ for (unsigned i = 0, e = Params->size(); i != e; ++i) {
+ if (i != 0)
+ Out << ", ";
+
+ const Decl *Param = Params->getParam(i);
+ if (const TemplateTypeParmDecl *TTP =
+ dyn_cast<TemplateTypeParmDecl>(Param)) {
+
+ QualType ParamType =
+ Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP));
+
+ if (TTP->wasDeclaredWithTypename())
+ Out << "typename ";
+ else
+ Out << "class ";
+
+ if (TTP->isParameterPack())
+ Out << "... ";
+
+ Out << ParamType.getAsString(Policy);
+
+ if (TTP->hasDefaultArgument()) {
+ Out << " = ";
+ Out << TTP->getDefaultArgument().getAsString(Policy);
+ };
+ } else if (const NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ Out << NTTP->getType().getAsString(Policy);
+
+ if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType()))
+ Out << "...";
+
+ if (IdentifierInfo *Name = NTTP->getIdentifier()) {
+ Out << ' ';
+ Out << Name->getName();
+ }
+
+ if (NTTP->hasDefaultArgument()) {
+ Out << " = ";
+ NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy,
+ Indentation);
+ }
+ }
+ }
+
+ Out << "> ";
+
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ Out << "class ";
+ if (TTP->isParameterPack())
+ Out << "...";
+ Out << D->getName();
+ } else {
+ Visit(D->getTemplatedDecl());
+ }
+}
+
+//----------------------------------------------------------------------------
+// Objective-C declarations
+//----------------------------------------------------------------------------
+
+void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
+ Out << "@class ";
+ for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
+ I != E; ++I) {
+ if (I != D->begin()) Out << ", ";
+ Out << I->getInterface();
+ }
+}
+
+void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
+ if (OMD->isInstanceMethod())
+ Out << "- ";
+ else
+ Out << "+ ";
+ if (!OMD->getResultType().isNull())
+ Out << '(' << OMD->getResultType().getAsString(Policy) << ")";
+
+ std::string name = OMD->getSelector().getAsString();
+ std::string::size_type pos, lastPos = 0;
+ for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+ E = OMD->param_end(); PI != E; ++PI) {
+ // FIXME: selector is missing here!
+ pos = name.find_first_of(":", lastPos);
+ Out << " " << name.substr(lastPos, pos - lastPos);
+ Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI;
+ lastPos = pos + 1;
+ }
+
+ if (OMD->param_begin() == OMD->param_end())
+ Out << " " << name;
+
+ if (OMD->isVariadic())
+ Out << ", ...";
+
+ if (OMD->getBody()) {
+ Out << ' ';
+ OMD->getBody()->printPretty(Out, Context, 0, Policy);
+ Out << '\n';
+ }
+}
+
+void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
+ std::string I = OID->getNameAsString();
+ ObjCInterfaceDecl *SID = OID->getSuperClass();
+
+ if (SID)
+ Out << "@implementation " << I << " : " << SID;
+ else
+ Out << "@implementation " << I;
+ Out << "\n";
+ VisitDeclContext(OID, false);
+ Out << "@end";
+}
+
+void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
+ std::string I = OID->getNameAsString();
+ ObjCInterfaceDecl *SID = OID->getSuperClass();
+
+ if (SID)
+ Out << "@interface " << I << " : " << SID;
+ else
+ Out << "@interface " << I;
+
+ // Protocols?
+ const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
+ if (!Protocols.empty()) {
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I)
+ Out << (I == Protocols.begin() ? '<' : ',') << *I;
+ }
+
+ if (!Protocols.empty())
+ Out << "> ";
+
+ if (OID->ivar_size() > 0) {
+ Out << "{\n";
+ Indentation += Policy.Indentation;
+ for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
+ E = OID->ivar_end(); I != E; ++I) {
+ Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n";
+ }
+ Indentation -= Policy.Indentation;
+ Out << "}\n";
+ }
+
+ VisitDeclContext(OID, false);
+ Out << "@end";
+ // FIXME: implement the rest...
+}
+
+void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ Out << "@protocol ";
+ for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end();
+ I != E; ++I) {
+ if (I != D->protocol_begin()) Out << ", ";
+ Out << *I;
+ }
+}
+
+void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ Out << "@protocol " << PID << '\n';
+ VisitDeclContext(PID, false);
+ Out << "@end";
+}
+
+void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
+ Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n";
+
+ VisitDeclContext(PID, false);
+ Out << "@end";
+ // FIXME: implement the rest...
+}
+
+void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
+ Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n";
+ VisitDeclContext(PID, false);
+ Out << "@end";
+
+ // FIXME: implement the rest...
+}
+
+void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
+ Out << "@compatibility_alias " << AID
+ << ' ' << AID->getClassInterface() << ";\n";
+}
+
+/// PrintObjCPropertyDecl - print a property declaration.
+///
+void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
+ if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
+ Out << "@required\n";
+ else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
+ Out << "@optional\n";
+
+ Out << "@property";
+ if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
+ bool first = true;
+ Out << " (";
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_readonly) {
+ Out << (first ? ' ' : ',') << "readonly";
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
+ Out << (first ? ' ' : ',') << "getter = "
+ << PDecl->getGetterName().getAsString();
+ first = false;
+ }
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
+ Out << (first ? ' ' : ',') << "setter = "
+ << PDecl->getSetterName().getAsString();
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
+ Out << (first ? ' ' : ',') << "assign";
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_readwrite) {
+ Out << (first ? ' ' : ',') << "readwrite";
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
+ Out << (first ? ' ' : ',') << "retain";
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
+ Out << (first ? ' ' : ',') << "copy";
+ first = false;
+ }
+
+ if (PDecl->getPropertyAttributes() &
+ ObjCPropertyDecl::OBJC_PR_nonatomic) {
+ Out << (first ? ' ' : ',') << "nonatomic";
+ first = false;
+ }
+ Out << " )";
+ }
+ Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl;
+}
+
+void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
+ if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
+ Out << "@synthesize ";
+ else
+ Out << "@dynamic ";
+ Out << PID->getPropertyDecl();
+ if (PID->getPropertyIvarDecl())
+ Out << '=' << PID->getPropertyIvarDecl();
+}
+
+void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
+ Out << "using ";
+ D->getTargetNestedNameDecl()->print(Out, Policy);
+ Out << D;
+}
+
+void
+DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ Out << "using typename ";
+ D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ Out << D->getDeclName();
+}
+
+void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ Out << "using ";
+ D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ Out << D->getDeclName();
+}
+
+void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ // ignore
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
new file mode 100644
index 0000000..a73deea
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -0,0 +1,625 @@
+//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++ related Decl classes for templates.
+//
+//===----------------------------------------------------------------------===//
+
+#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 <memory>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TemplateParameterList Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ NamedDecl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc)
+ : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
+ NumParams(NumParams) {
+ for (unsigned Idx = 0; Idx < NumParams; ++Idx)
+ begin()[Idx] = Params[Idx];
+}
+
+TemplateParameterList *
+TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc, NamedDecl **Params,
+ unsigned NumParams, SourceLocation RAngleLoc) {
+ unsigned Size = sizeof(TemplateParameterList)
+ + sizeof(NamedDecl *) * NumParams;
+ unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
+ void *Mem = C.Allocate(Size, Align);
+ return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
+ NumParams, RAngleLoc);
+}
+
+unsigned TemplateParameterList::getMinRequiredArguments() const {
+ unsigned NumRequiredArgs = 0;
+ for (iterator P = const_cast<TemplateParameterList *>(this)->begin(),
+ PEnd = const_cast<TemplateParameterList *>(this)->end();
+ P != PEnd; ++P) {
+ if ((*P)->isTemplateParameterPack()) {
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
+ if (NTTP->isExpandedParameterPack()) {
+ NumRequiredArgs += NTTP->getNumExpansionTypes();
+ continue;
+ }
+
+ break;
+ }
+
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+ if (TTP->hasDefaultArgument())
+ break;
+ } else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ if (NTTP->hasDefaultArgument())
+ break;
+ } else if (cast<TemplateTemplateParmDecl>(*P)->hasDefaultArgument())
+ break;
+
+ ++NumRequiredArgs;
+ }
+
+ return NumRequiredArgs;
+}
+
+unsigned TemplateParameterList::getDepth() const {
+ if (size() == 0)
+ return 0;
+
+ const NamedDecl *FirstParm = getParam(0);
+ if (const TemplateTypeParmDecl *TTP
+ = dyn_cast<TemplateTypeParmDecl>(FirstParm))
+ return TTP->getDepth();
+ else if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
+ return NTTP->getDepth();
+ else
+ return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
+}
+
+//===----------------------------------------------------------------------===//
+// RedeclarableTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
+ // Find the first declaration of this function template.
+ RedeclarableTemplateDecl *First = getCanonicalDecl();
+
+ if (First->CommonOrPrev.isNull()) {
+ CommonBase *CommonPtr = First->newCommon(getASTContext());
+ First->CommonOrPrev = CommonPtr;
+ CommonPtr->Latest = First;
+ }
+ return First->CommonOrPrev.get<CommonBase*>();
+}
+
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
+ RedeclarableTemplateDecl *Tmpl = this;
+ while (Tmpl->getPreviousDeclaration())
+ Tmpl = Tmpl->getPreviousDeclaration();
+ return Tmpl;
+}
+
+void RedeclarableTemplateDecl::setPreviousDeclarationImpl(
+ RedeclarableTemplateDecl *Prev) {
+ if (Prev) {
+ CommonBase *Common = Prev->getCommonPtr();
+ Prev = Common->Latest;
+ Common->Latest = this;
+ CommonOrPrev = Prev;
+ } else {
+ assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev");
+ }
+}
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
+ if (CommonOrPrev.is<RedeclarableTemplateDecl*>())
+ return CommonOrPrev.get<RedeclarableTemplateDecl*>();
+ CommonBase *Common = CommonOrPrev.get<CommonBase*>();
+ return Common ? Common->Latest : this;
+}
+
+template <class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+RedeclarableTemplateDecl::findSpecializationImpl(
+ llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos) {
+ typedef SpecEntryTraits<EntryType> SETraits;
+ llvm::FoldingSetNodeID ID;
+ EntryType::Profile(ID,Args,NumArgs, getASTContext());
+ EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
+ return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0;
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void FunctionTemplateDecl::DeallocateCommon(void *Ptr) {
+ static_cast<Common *>(Ptr)->~Common();
+}
+
+FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl) {
+ return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
+}
+
+RedeclarableTemplateDecl::CommonBase *
+FunctionTemplateDecl::newCommon(ASTContext &C) {
+ Common *CommonPtr = new (C) Common;
+ C.AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
+}
+
+FunctionDecl *
+FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
+}
+
+//===----------------------------------------------------------------------===//
+// ClassTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
+ static_cast<Common *>(Ptr)->~Common();
+}
+
+ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl) {
+ ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
+ New->setPreviousDeclaration(PrevDecl);
+ return New;
+}
+
+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<ClassTemplateSpecializationDecl> &
+ClassTemplateDecl::getSpecializations() {
+ LoadLazySpecializations();
+ return getCommonPtr()->Specializations;
+}
+
+llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ClassTemplateDecl::getPartialSpecializations() {
+ LoadLazySpecializations();
+ return getCommonPtr()->PartialSpecializations;
+}
+
+RedeclarableTemplateDecl::CommonBase *
+ClassTemplateDecl::newCommon(ASTContext &C) {
+ Common *CommonPtr = new (C) Common;
+ C.AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
+}
+
+ClassTemplateSpecializationDecl *
+ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ 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,
+ void *&InsertPos) {
+ return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
+ 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<ClassTemplatePartialSpecializationDecl *> &PS) {
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs
+ = getPartialSpecializations();
+ PS.clear();
+ PS.resize(PartialSpecs.size());
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
+ P != PEnd; ++P) {
+ assert(!PS[P->getSequenceNumber()]);
+ PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
+ }
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecialization(QualType T) {
+ ASTContext &Context = getASTContext();
+ typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ partial_spec_iterator;
+ for (partial_spec_iterator P = getPartialSpecializations().begin(),
+ PEnd = getPartialSpecializations().end();
+ P != PEnd; ++P) {
+ if (Context.hasSameType(P->getInjectedSpecializationType(), T))
+ return P->getMostRecentDeclaration();
+ }
+
+ return 0;
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D) {
+ Decl *DCanon = D->getCanonicalDecl();
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = getPartialSpecializations().begin(),
+ PEnd = getPartialSpecializations().end();
+ P != PEnd; ++P) {
+ if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+ return P->getMostRecentDeclaration();
+ }
+
+ return 0;
+}
+
+QualType
+ClassTemplateDecl::getInjectedClassNameSpecialization() {
+ Common *CommonPtr = getCommonPtr();
+ if (!CommonPtr->InjectedClassNameType.isNull())
+ return CommonPtr->InjectedClassNameType;
+
+ // 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<TemplateArgument, 16> TemplateArgs;
+ TemplateArgs.reserve(Params->size());
+ for (TemplateParameterList::iterator Param = Params->begin(),
+ ParamEnd = Params->end();
+ Param != ParamEnd; ++Param) {
+ TemplateArgument Arg;
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+ QualType ArgType = Context.getTypeDeclType(TTP);
+ if (TTP->isParameterPack())
+ ArgType = Context.getPackExpansionType(ArgType,
+ llvm::Optional<unsigned>());
+
+ Arg = TemplateArgument(ArgType);
+ } else if (NonTypeTemplateParmDecl *NTTP =
+ dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+ Expr *E = new (Context) DeclRefExpr(NTTP,
+ NTTP->getType().getNonLValueExprType(Context),
+ Expr::getValueKindForType(NTTP->getType()),
+ NTTP->getLocation());
+
+ if (NTTP->isParameterPack())
+ E = new (Context) PackExpansionExpr(Context.DependentTy, E,
+ NTTP->getLocation(),
+ llvm::Optional<unsigned>());
+ Arg = TemplateArgument(E);
+ } else {
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
+ if (TTP->isParameterPack())
+ Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>());
+ else
+ Arg = TemplateArgument(TemplateName(TTP));
+ }
+
+ if ((*Param)->isTemplateParameterPack())
+ Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1);
+
+ TemplateArgs.push_back(Arg);
+ }
+
+ CommonPtr->InjectedClassNameType
+ = Context.getTemplateSpecializationType(TemplateName(this),
+ &TemplateArgs[0],
+ TemplateArgs.size());
+ return CommonPtr->InjectedClassNameType;
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateTypeParm Allocation/Deallocation Method Implementations
+//===----------------------------------------------------------------------===//
+
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, bool Typename,
+ bool ParameterPack) {
+ QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
+ return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
+}
+
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) {
+ return new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, false,
+ QualType(), false);
+}
+
+SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
+ return DefaultArgument->getTypeLoc().getSourceRange().getBegin();
+}
+
+unsigned TemplateTypeParmDecl::getDepth() const {
+ return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
+}
+
+unsigned TemplateTypeParmDecl::getIndex() const {
+ return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
+}
+
+//===----------------------------------------------------------------------===//
+// 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<void **>(this + 1);
+ for (unsigned I = 0; I != NumExpandedTypes; ++I) {
+ TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr();
+ TypesAndInfos[2*I + 1] = ExpandedTInfos[I];
+ }
+ }
+}
+
+NonTypeTemplateParmDecl *
+NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, QualType T,
+ 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 {
+ return hasDefaultArgument()
+ ? getDefaultArgument()->getSourceRange().getBegin()
+ : SourceLocation();
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateTemplateParmDecl Method Implementations
+//===----------------------------------------------------------------------===//
+
+TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ bool ParameterPack, IdentifierInfo *Id,
+ TemplateParameterList *Params) {
+ return new (C) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
+ Params);
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateArgumentList Implementation
+//===----------------------------------------------------------------------===//
+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<TemplateArgument *>(
+ static_cast<TemplateArgumentList *>(Mem) + 1);
+ std::uninitialized_copy(Args, Args + NumArgs, StoredArgs);
+ return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true);
+}
+
+//===----------------------------------------------------------------------===//
+// ClassTemplateSpecializationDecl Implementation
+//===----------------------------------------------------------------------===//
+ClassTemplateSpecializationDecl::
+ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
+ DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl)
+ : CXXRecordDecl(DK, TK, DC, L,
+ SpecializedTemplate->getIdentifier(),
+ PrevDecl),
+ SpecializedTemplate(SpecializedTemplate),
+ ExplicitInfo(0),
+ TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)),
+ SpecializationKind(TSK_Undeclared) {
+}
+
+ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK)
+ : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), 0, 0),
+ ExplicitInfo(0),
+ SpecializationKind(TSK_Undeclared) {
+}
+
+ClassTemplateSpecializationDecl *
+ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
+ DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl) {
+ ClassTemplateSpecializationDecl *Result
+ = new (Context)ClassTemplateSpecializationDecl(Context,
+ ClassTemplateSpecialization,
+ TK, DC, L,
+ SpecializedTemplate,
+ Args, NumArgs,
+ PrevDecl);
+ Context.getTypeDeclType(Result, PrevDecl);
+ return Result;
+}
+
+ClassTemplateSpecializationDecl *
+ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) {
+ return
+ new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+}
+
+void
+ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S,
+ const PrintingPolicy &Policy,
+ bool Qualified) const {
+ NamedDecl::getNameForDiagnostic(S, Policy, Qualified);
+
+ const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+ S += TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.data(),
+ TemplateArgs.size(),
+ Policy);
+}
+
+ClassTemplateDecl *
+ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization->getSpecializedTemplate();
+ return SpecializedTemplate.get<ClassTemplateDecl*>();
+}
+
+//===----------------------------------------------------------------------===//
+// ClassTemplatePartialSpecializationDecl Implementation
+//===----------------------------------------------------------------------===//
+ClassTemplatePartialSpecializationDecl *
+ClassTemplatePartialSpecializationDecl::
+Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const TemplateArgumentListInfo &ArgInfos,
+ QualType CanonInjectedType,
+ ClassTemplatePartialSpecializationDecl *PrevDecl,
+ unsigned SequenceNumber) {
+ unsigned N = ArgInfos.size();
+ TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
+ for (unsigned I = 0; I != N; ++I)
+ ClonedArgs[I] = ArgInfos[I];
+
+ ClassTemplatePartialSpecializationDecl *Result
+ = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK,
+ DC, L, Params,
+ SpecializedTemplate,
+ Args, NumArgs,
+ ClonedArgs, N,
+ PrevDecl,
+ SequenceNumber);
+ Result->setSpecializationKind(TSK_ExplicitSpecialization);
+
+ Context.getInjectedClassNameType(Result, CanonInjectedType);
+ return Result;
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context,
+ EmptyShell Empty) {
+ return new (Context)ClassTemplatePartialSpecializationDecl();
+}
+
+//===----------------------------------------------------------------------===//
+// FriendTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
+ DeclContext *DC,
+ SourceLocation L,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FLoc) {
+ FriendTemplateDecl *Result
+ = new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc);
+ return Result;
+}
+
+FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
+ EmptyShell Empty) {
+ return new (Context) FriendTemplateDecl(Empty);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
new file mode 100644
index 0000000..cef54e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
@@ -0,0 +1,604 @@
+//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DeclarationName and DeclarationNameTable
+// classes.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace clang {
+/// CXXSpecialName - Records the type associated with one of the
+/// "special" kinds of declaration names in C++, e.g., constructors,
+/// destructors, and conversion functions.
+class CXXSpecialName
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
+public:
+ /// Type - The type associated with this declaration name.
+ QualType Type;
+
+ /// FETokenInfo - Extra information associated with this declaration
+ /// name that can be used by the front end.
+ void *FETokenInfo;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddInteger(ExtraKindOrNumArgs);
+ ID.AddPointer(Type.getAsOpaquePtr());
+ }
+};
+
+/// CXXOperatorIdName - Contains extra information for the name of an
+/// overloaded operator in C++, such as "operator+.
+class CXXOperatorIdName : public DeclarationNameExtra {
+public:
+ /// FETokenInfo - Extra information associated with this operator
+ /// name that can be used by the front end.
+ void *FETokenInfo;
+};
+
+/// CXXLiberalOperatorName - Contains the actual identifier that makes up the
+/// name.
+///
+/// This identifier is stored here rather than directly in DeclarationName so as
+/// to allow Objective-C selectors, which are about a million times more common,
+/// to consume minimal memory.
+class CXXLiteralOperatorIdName
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
+public:
+ IdentifierInfo *ID;
+
+ void Profile(llvm::FoldingSetNodeID &FSID) {
+ FSID.AddPointer(ID);
+ }
+};
+
+static int compareInt(unsigned A, unsigned B) {
+ return (A < B ? -1 : (A > B ? 1 : 0));
+}
+
+int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
+ if (LHS.getNameKind() != RHS.getNameKind())
+ return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);
+
+ switch (LHS.getNameKind()) {
+ case DeclarationName::Identifier: {
+ IdentifierInfo *LII = LHS.getAsIdentifierInfo();
+ IdentifierInfo *RII = RHS.getAsIdentifierInfo();
+ if (!LII) return RII ? -1 : 0;
+ if (!RII) return 1;
+
+ return LII->getName().compare(RII->getName());
+ }
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector: {
+ Selector LHSSelector = LHS.getObjCSelector();
+ Selector RHSSelector = RHS.getObjCSelector();
+ unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
+ for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
+ switch (LHSSelector.getNameForSlot(I).compare(
+ RHSSelector.getNameForSlot(I))) {
+ case -1: return true;
+ case 1: return false;
+ default: break;
+ }
+ }
+
+ return compareInt(LN, RN);
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
+ return -1;
+ if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
+ return 1;
+ return 0;
+
+ case DeclarationName::CXXOperatorName:
+ return compareInt(LHS.getCXXOverloadedOperator(),
+ RHS.getCXXOverloadedOperator());
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return LHS.getCXXLiteralIdentifier()->getName().compare(
+ RHS.getCXXLiteralIdentifier()->getName());
+
+ case DeclarationName::CXXUsingDirective:
+ return 0;
+ }
+
+ return 0;
+}
+
+} // end namespace clang
+
+DeclarationName::DeclarationName(Selector Sel) {
+ if (!Sel.getAsOpaquePtr()) {
+ Ptr = 0;
+ return;
+ }
+
+ switch (Sel.getNumArgs()) {
+ case 0:
+ Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+ Ptr |= StoredObjCZeroArgSelector;
+ break;
+
+ case 1:
+ Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+ Ptr |= StoredObjCOneArgSelector;
+ break;
+
+ default:
+ Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
+ Ptr |= StoredDeclarationNameExtra;
+ break;
+ }
+}
+
+DeclarationName::NameKind DeclarationName::getNameKind() const {
+ switch (getStoredNameKind()) {
+ case StoredIdentifier: return Identifier;
+ case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
+ case StoredObjCOneArgSelector: return ObjCOneArgSelector;
+
+ case StoredDeclarationNameExtra:
+ switch (getExtra()->ExtraKindOrNumArgs) {
+ case DeclarationNameExtra::CXXConstructor:
+ return CXXConstructorName;
+
+ case DeclarationNameExtra::CXXDestructor:
+ return CXXDestructorName;
+
+ case DeclarationNameExtra::CXXConversionFunction:
+ return CXXConversionFunctionName;
+
+ case DeclarationNameExtra::CXXLiteralOperator:
+ return CXXLiteralOperatorName;
+
+ case DeclarationNameExtra::CXXUsingDirective:
+ return CXXUsingDirective;
+
+ default:
+ // Check if we have one of the CXXOperator* enumeration values.
+ if (getExtra()->ExtraKindOrNumArgs <
+ DeclarationNameExtra::CXXUsingDirective)
+ return CXXOperatorName;
+
+ return ObjCMultiArgSelector;
+ }
+ break;
+ }
+
+ // Can't actually get here.
+ assert(0 && "This should be unreachable!");
+ return Identifier;
+}
+
+bool DeclarationName::isDependentName() const {
+ QualType T = getCXXNameType();
+ return !T.isNull() && T->isDependentType();
+}
+
+std::string DeclarationName::getAsString() const {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ printName(OS);
+ return OS.str();
+}
+
+void DeclarationName::printName(llvm::raw_ostream &OS) const {
+ switch (getNameKind()) {
+ case Identifier:
+ if (const IdentifierInfo *II = getAsIdentifierInfo())
+ OS << II->getName();
+ return;
+
+ case ObjCZeroArgSelector:
+ case ObjCOneArgSelector:
+ case ObjCMultiArgSelector:
+ OS << getObjCSelector().getAsString();
+ return;
+
+ case CXXConstructorName: {
+ QualType ClassType = getCXXNameType();
+ if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
+ OS << ClassRec->getDecl();
+ else
+ OS << ClassType.getAsString();
+ return;
+ }
+
+ case CXXDestructorName: {
+ OS << '~';
+ QualType Type = getCXXNameType();
+ if (const RecordType *Rec = Type->getAs<RecordType>())
+ OS << Rec->getDecl();
+ else
+ OS << Type.getAsString();
+ return;
+ }
+
+ case CXXOperatorName: {
+ static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+ 0,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ Spelling,
+#include "clang/Basic/OperatorKinds.def"
+ };
+ const char *OpName = OperatorNames[getCXXOverloadedOperator()];
+ assert(OpName && "not an overloaded operator");
+
+ OS << "operator";
+ if (OpName[0] >= 'a' && OpName[0] <= 'z')
+ OS << ' ';
+ OS << OpName;
+ return;
+ }
+
+ case CXXLiteralOperatorName:
+ OS << "operator \"\" " << getCXXLiteralIdentifier()->getName();
+ return;
+
+ case CXXConversionFunctionName: {
+ OS << "operator ";
+ QualType Type = getCXXNameType();
+ if (const RecordType *Rec = Type->getAs<RecordType>())
+ OS << Rec->getDecl();
+ else
+ OS << Type.getAsString();
+ return;
+ }
+ case CXXUsingDirective:
+ OS << "<using-directive>";
+ return;
+ }
+
+ assert(false && "Unexpected declaration name kind");
+}
+
+QualType DeclarationName::getCXXNameType() const {
+ if (CXXSpecialName *CXXName = getAsCXXSpecialName())
+ return CXXName->Type;
+ else
+ return QualType();
+}
+
+OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const {
+ if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) {
+ unsigned value
+ = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction;
+ return static_cast<OverloadedOperatorKind>(value);
+ } else {
+ return OO_None;
+ }
+}
+
+IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const {
+ if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName())
+ return CXXLit->ID;
+ else
+ return 0;
+}
+
+Selector DeclarationName::getObjCSelector() const {
+ switch (getNameKind()) {
+ case ObjCZeroArgSelector:
+ return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
+
+ case ObjCOneArgSelector:
+ return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
+
+ case ObjCMultiArgSelector:
+ return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
+
+ default:
+ break;
+ }
+
+ return Selector();
+}
+
+void *DeclarationName::getFETokenInfoAsVoid() const {
+ switch (getNameKind()) {
+ case Identifier:
+ return getAsIdentifierInfo()->getFETokenInfo<void>();
+
+ case CXXConstructorName:
+ case CXXDestructorName:
+ case CXXConversionFunctionName:
+ return getAsCXXSpecialName()->FETokenInfo;
+
+ case CXXOperatorName:
+ return getAsCXXOperatorIdName()->FETokenInfo;
+
+ case CXXLiteralOperatorName:
+ return getCXXLiteralIdentifier()->getFETokenInfo<void>();
+
+ default:
+ assert(false && "Declaration name has no FETokenInfo");
+ }
+ return 0;
+}
+
+void DeclarationName::setFETokenInfo(void *T) {
+ switch (getNameKind()) {
+ case Identifier:
+ getAsIdentifierInfo()->setFETokenInfo(T);
+ break;
+
+ case CXXConstructorName:
+ case CXXDestructorName:
+ case CXXConversionFunctionName:
+ getAsCXXSpecialName()->FETokenInfo = T;
+ break;
+
+ case CXXOperatorName:
+ getAsCXXOperatorIdName()->FETokenInfo = T;
+ break;
+
+ case CXXLiteralOperatorName:
+ getCXXLiteralIdentifier()->setFETokenInfo(T);
+ break;
+
+ default:
+ assert(false && "Declaration name has no FETokenInfo");
+ }
+}
+
+DeclarationName DeclarationName::getUsingDirectiveName() {
+ // Single instance of DeclarationNameExtra for using-directive
+ static const DeclarationNameExtra UDirExtra =
+ { DeclarationNameExtra::CXXUsingDirective };
+
+ uintptr_t Ptr = reinterpret_cast<uintptr_t>(&UDirExtra);
+ Ptr |= StoredDeclarationNameExtra;
+
+ return DeclarationName(Ptr);
+}
+
+void DeclarationName::dump() const {
+ printName(llvm::errs());
+ llvm::errs() << '\n';
+}
+
+DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) {
+ CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
+ CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
+
+ // Initialize the overloaded operator names.
+ CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
+ for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) {
+ CXXOperatorNames[Op].ExtraKindOrNumArgs
+ = Op + DeclarationNameExtra::CXXConversionFunction;
+ CXXOperatorNames[Op].FETokenInfo = 0;
+ }
+}
+
+DeclarationNameTable::~DeclarationNameTable() {
+ llvm::FoldingSet<CXXSpecialName> *SpecialNames =
+ static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
+ llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
+ = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
+ (CXXLiteralOperatorNames);
+
+ delete SpecialNames;
+ delete LiteralNames;
+}
+
+DeclarationName
+DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
+ CanQualType Ty) {
+ assert(Kind >= DeclarationName::CXXConstructorName &&
+ Kind <= DeclarationName::CXXConversionFunctionName &&
+ "Kind must be a C++ special name kind");
+ llvm::FoldingSet<CXXSpecialName> *SpecialNames
+ = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
+
+ DeclarationNameExtra::ExtraKind EKind;
+ switch (Kind) {
+ case DeclarationName::CXXConstructorName:
+ EKind = DeclarationNameExtra::CXXConstructor;
+ assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
+ break;
+ case DeclarationName::CXXDestructorName:
+ EKind = DeclarationNameExtra::CXXDestructor;
+ assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
+ break;
+ case DeclarationName::CXXConversionFunctionName:
+ EKind = DeclarationNameExtra::CXXConversionFunction;
+ break;
+ default:
+ return DeclarationName();
+ }
+
+ // Unique selector, to guarantee there is one per name.
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(EKind);
+ ID.AddPointer(Ty.getAsOpaquePtr());
+
+ void *InsertPos = 0;
+ if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName(Name);
+
+ CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName;
+ SpecialName->ExtraKindOrNumArgs = EKind;
+ SpecialName->Type = Ty;
+ SpecialName->FETokenInfo = 0;
+
+ SpecialNames->InsertNode(SpecialName, InsertPos);
+ return DeclarationName(SpecialName);
+}
+
+DeclarationName
+DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
+ return DeclarationName(&CXXOperatorNames[(unsigned)Op]);
+}
+
+DeclarationName
+DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
+ llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
+ = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
+ (CXXLiteralOperatorNames);
+
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(II);
+
+ void *InsertPos = 0;
+ if (CXXLiteralOperatorIdName *Name =
+ LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName (Name);
+
+ CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
+ LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
+ LiteralName->ID = II;
+
+ LiteralNames->InsertNode(LiteralName, InsertPos);
+ return DeclarationName(LiteralName);
+}
+
+unsigned
+llvm::DenseMapInfo<clang::DeclarationName>::
+getHashValue(clang::DeclarationName N) {
+ return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
+}
+
+DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ NamedType.TInfo = 0;
+ break;
+ case DeclarationName::CXXOperatorName:
+ CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ // FIXME: ?
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+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);
+ printName(OS);
+ return OS.str();
+}
+
+void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ Name.printName(OS);
+ return;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName)
+ OS << '~';
+ else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
+ OS << "operator ";
+ OS << TInfo->getType().getAsString();
+ }
+ else
+ Name.printName(OS);
+ return;
+ }
+ assert(false && "Unexpected declaration name kind");
+}
+
+SourceLocation DeclarationNameInfo::getEndLoc() const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ return NameLoc;
+
+ case DeclarationName::CXXOperatorName: {
+ unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXLiteralOperatorName: {
+ unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ return TInfo->getTypeLoc().getEndLoc();
+ else
+ return NameLoc;
+
+ // DNInfo work in progress: FIXME.
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return NameLoc;
+ }
+ assert(false && "Unexpected declaration name kind");
+ return SourceLocation();
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp
new file mode 100644
index 0000000..9d828fc
--- /dev/null
+++ b/contrib/llvm/tools/clang/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 <class Impl> struct XMLDeclVisitor {
+#define DISPATCH(NAME, CLASS) \
+ static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(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<Impl*>(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 <class Impl> struct XMLTypeVisitor {
+#define DISPATCH(NAME, CLASS) \
+ static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(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<Impl*>(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<XMLDumper>,
+ public XMLTypeVisitor<XMLDumper> {
+ llvm::raw_ostream &out;
+ ASTContext &Context;
+ llvm::SmallVector<Node, 16> 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 << "</" << Stack.back().Name << ">\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<XMLDumper>::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 <class T> 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<NamedDecl*>(*I);
+ push(isa<VarDecl>(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<Type*>(T.getTypePtr());
+ push(getTypeKindName(Ty));
+ XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(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<RecordType>())
+ 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<Decl*>(this));
+}
+
+#else /* ifndef NDEBUG */
+
+void Decl::dumpXML() const {}
+void Decl::dumpXML(llvm::raw_ostream &out) const {}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
new file mode 100644
index 0000000..391b26a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -0,0 +1,2831 @@
+//===--- Expr.cpp - Expression AST Node Implementation --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expr class and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#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 <algorithm>
+using namespace clang;
+
+/// 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
+/// C.
+bool Expr::isKnownToHaveBooleanValue() const {
+ // If this value has _Bool type, it is obvious 0/1.
+ if (getType()->isBooleanType()) return true;
+ // If this is a non-scalar-integer type, we don't care enough to try.
+ if (!getType()->isIntegralOrEnumerationType()) return false;
+
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(this))
+ return PE->getSubExpr()->isKnownToHaveBooleanValue();
+
+ if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(this)) {
+ switch (UO->getOpcode()) {
+ case UO_Plus:
+ case UO_Extension:
+ return UO->getSubExpr()->isKnownToHaveBooleanValue();
+ default:
+ return false;
+ }
+ }
+
+ // Only look through implicit casts. If the user writes
+ // '(int) (a && b)' treat it as an arbitrary int.
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(this))
+ return CE->getSubExpr()->isKnownToHaveBooleanValue();
+
+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
+ switch (BO->getOpcode()) {
+ default: return false;
+ case BO_LT: // Relational operators.
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ: // Equality operators.
+ case BO_NE:
+ case BO_LAnd: // AND operator.
+ case BO_LOr: // Logical OR operator.
+ return true;
+
+ case BO_And: // Bitwise AND operator.
+ case BO_Xor: // Bitwise XOR operator.
+ case BO_Or: // Bitwise OR operator.
+ // Handle things like (x==2)|(y==12).
+ return BO->getLHS()->isKnownToHaveBooleanValue() &&
+ BO->getRHS()->isKnownToHaveBooleanValue();
+
+ case BO_Comma:
+ case BO_Assign:
+ return BO->getRHS()->isKnownToHaveBooleanValue();
+ }
+ }
+
+ if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(this))
+ return CO->getTrueExpr()->isKnownToHaveBooleanValue() &&
+ CO->getFalseExpr()->isKnownToHaveBooleanValue();
+
+ 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 <class E, class T>
+ SourceLocation getExprLocImpl(const Expr *expr,
+ SourceLocation (T::*v)() const) {
+ return static_cast<const E*>(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 <class E>
+ SourceLocation getExprLocImpl(const Expr *expr,
+ SourceLocation (Expr::*v)() const) {
+ return static_cast<const E*>(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<type>(this, &type::getExprLoc);
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind");
+ return SourceLocation();
+}
+
+//===----------------------------------------------------------------------===//
+// Primary Expressions.
+//===----------------------------------------------------------------------===//
+
+void ExplicitTemplateArgumentList::initializeFrom(
+ const TemplateArgumentListInfo &Info) {
+ LAngleLoc = Info.getLAngleLoc();
+ RAngleLoc = Info.getRAngleLoc();
+ NumTemplateArgs = Info.size();
+
+ TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ 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);
+ Info.setRAngleLoc(RAngleLoc);
+ for (unsigned I = 0; I != NumTemplateArgs; ++I)
+ Info.addArgument(getTemplateArgs()[I]);
+}
+
+std::size_t ExplicitTemplateArgumentList::sizeFor(unsigned NumTemplateArgs) {
+ return sizeof(ExplicitTemplateArgumentList) +
+ sizeof(TemplateArgumentLoc) * NumTemplateArgs;
+}
+
+std::size_t ExplicitTemplateArgumentList::sizeFor(
+ const TemplateArgumentListInfo &Info) {
+ return sizeFor(Info.size());
+}
+
+/// \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;
+
+
+ // (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:
+
+ // (TD) - an identifier that was declared with dependent type
+ // (VD) - a name declared with a dependent type,
+ if (T->isDependentType()) {
+ TypeDependent = true;
+ ValueDependent = true;
+ return;
+ }
+
+ // (TD) - a conversion-function-id that specifies a dependent type
+ if (D->getDeclName().getNameKind()
+ == DeclarationName::CXXConversionFunctionName &&
+ D->getDeclName().getCXXNameType()->isDependentType()) {
+ TypeDependent = true;
+ ValueDependent = true;
+ return;
+ }
+ // (VD) - the name of a non-type template parameter,
+ if (isa<NonTypeTemplateParmDecl>(D)) {
+ ValueDependent = true;
+ return;
+ }
+
+ // (VD) - a constant with integral or enumeration type and is
+ // initialized with an expression that is value-dependent.
+ if (VarDecl *Var = dyn_cast<VarDecl>(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
+ if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
+ ValueDependent = true;
+ 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, ExprValueKind VK)
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false),
+ DecoratedD(D,
+ (Qualifier? HasQualifierFlag : 0) |
+ (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
+ Loc(NameLoc) {
+ if (Qualifier) {
+ NameQualifier *NQ = getNameQualifier();
+ NQ->NNS = Qualifier;
+ NQ->Range = QualifierRange;
+ }
+
+ if (TemplateArgs)
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
+
+ computeDependence();
+}
+
+DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T, ExprValueKind VK)
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false),
+ DecoratedD(D,
+ (Qualifier? HasQualifierFlag : 0) |
+ (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
+ Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
+ if (Qualifier) {
+ NameQualifier *NQ = getNameQualifier();
+ NQ->NNS = Qualifier;
+ NQ->Range = QualifierRange;
+ }
+
+ if (TemplateArgs)
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
+
+ computeDependence();
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ SourceLocation NameLoc,
+ QualType T,
+ ExprValueKind VK,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ return Create(Context, Qualifier, QualifierRange, D,
+ DeclarationNameInfo(D->getDeclName(), NameLoc),
+ T, VK, TemplateArgs);
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T,
+ ExprValueKind VK,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ std::size_t Size = sizeof(DeclRefExpr);
+ if (Qualifier != 0)
+ Size += sizeof(NameQualifier);
+
+ if (TemplateArgs)
+ Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+
+ void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo,
+ TemplateArgs, T, VK);
+}
+
+DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context,
+ bool HasQualifier,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs) {
+ std::size_t Size = sizeof(DeclRefExpr);
+ if (HasQualifier)
+ Size += sizeof(NameQualifier);
+
+ if (HasExplicitTemplateArgs)
+ Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ return new (Mem) DeclRefExpr(EmptyShell());
+}
+
+SourceRange DeclRefExpr::getSourceRange() const {
+ SourceRange R = getNameInfo().getSourceRange();
+ if (hasQualifier())
+ R.setBegin(getQualifierRange().getBegin());
+ if (hasExplicitTemplateArgs())
+ R.setEnd(getRAngleLoc());
+ return R;
+}
+
+// FIXME: Maybe this should use DeclPrinter with a special "print predefined
+// expr" policy instead.
+std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
+ ASTContext &Context = CurrentDecl->getASTContext();
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
+ if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
+ return FD->getNameAsString();
+
+ llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
+ Out << "virtual ";
+ if (MD->isStatic())
+ Out << "static ";
+ }
+
+ PrintingPolicy Policy(Context.getLangOptions());
+
+ std::string Proto = FD->getQualifiedNameAsString(Policy);
+
+ const FunctionType *AFT = FD->getType()->getAs<FunctionType>();
+ const FunctionProtoType *FT = 0;
+ if (FD->hasWrittenPrototype())
+ FT = dyn_cast<FunctionProtoType>(AFT);
+
+ Proto += "(";
+ if (FT) {
+ llvm::raw_string_ostream POut(Proto);
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+ if (i) POut << ", ";
+ std::string Param;
+ FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
+ POut << Param;
+ }
+
+ if (FT->isVariadic()) {
+ if (FD->getNumParams()) POut << ", ";
+ POut << "...";
+ }
+ }
+ Proto += ")";
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
+ if (ThisQuals.hasConst())
+ Proto += " const";
+ if (ThisQuals.hasVolatile())
+ Proto += " volatile";
+ }
+
+ if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
+ AFT->getResultType().getAsStringInternal(Proto, Policy);
+
+ Out << Proto;
+
+ Out.flush();
+ return Name.str().str();
+ }
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
+ llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ Out << (MD->isInstanceMethod() ? '-' : '+');
+ Out << '[';
+
+ // For incorrect code, there might not be an ObjCInterfaceDecl. Do
+ // a null check to avoid a crash.
+ if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
+ Out << ID;
+
+ if (const ObjCCategoryImplDecl *CID =
+ dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
+ Out << '(' << CID << ')';
+
+ Out << ' ';
+ Out << MD->getSelector().getAsString();
+ Out << ']';
+
+ Out.flush();
+ return Name.str().str();
+ }
+ if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
+ // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
+ return "top level";
+ }
+ return "";
+}
+
+void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) {
+ if (hasAllocation())
+ C.Deallocate(pVal);
+
+ BitWidth = Val.getBitWidth();
+ unsigned NumWords = Val.getNumWords();
+ const uint64_t* Words = Val.getRawData();
+ if (NumWords > 1) {
+ pVal = new (C) uint64_t[NumWords];
+ std::copy(Words, Words + NumWords, pVal);
+ } else if (NumWords == 1)
+ VAL = Words[0];
+ else
+ VAL = 0;
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l) {
+ return new (C) IntegerLiteral(C, V, type, l);
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) IntegerLiteral(Empty);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L) {
+ return new (C) FloatingLiteral(C, V, isexact, Type, L);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) FloatingLiteral(Empty);
+}
+
+/// getValueAsApproximateDouble - This returns the value as an inaccurate
+/// double. Note that this may cause loss of precision, but is useful for
+/// debugging dumps, etc.
+double FloatingLiteral::getValueAsApproximateDouble() const {
+ llvm::APFloat V = getValue();
+ bool ignored;
+ V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ &ignored);
+ return V.convertToDouble();
+}
+
+StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
+ unsigned ByteLength, bool Wide,
+ QualType Ty,
+ const SourceLocation *Loc,
+ unsigned NumStrs) {
+ // Allocate enough space for the StringLiteral plus an array of locations for
+ // any concatenated string tokens.
+ void *Mem = C.Allocate(sizeof(StringLiteral)+
+ sizeof(SourceLocation)*(NumStrs-1),
+ llvm::alignOf<StringLiteral>());
+ StringLiteral *SL = new (Mem) StringLiteral(Ty);
+
+ // OPTIMIZE: could allocate this appended to the StringLiteral.
+ char *AStrData = new (C, 1) char[ByteLength];
+ memcpy(AStrData, StrData, ByteLength);
+ SL->StrData = AStrData;
+ SL->ByteLength = ByteLength;
+ SL->IsWide = Wide;
+ SL->TokLocs[0] = Loc[0];
+ SL->NumConcatenated = NumStrs;
+
+ if (NumStrs != 1)
+ memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1));
+ return SL;
+}
+
+StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
+ void *Mem = C.Allocate(sizeof(StringLiteral)+
+ sizeof(SourceLocation)*(NumStrs-1),
+ llvm::alignOf<StringLiteral>());
+ StringLiteral *SL = new (Mem) StringLiteral(QualType());
+ SL->StrData = 0;
+ SL->ByteLength = 0;
+ SL->NumConcatenated = NumStrs;
+ return SL;
+}
+
+void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
+ char *AStrData = new (C, 1) char[Str.size()];
+ memcpy(AStrData, Str.data(), Str.size());
+ StrData = AStrData;
+ 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<FileID, unsigned> 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) {
+ switch (Op) {
+ default: assert(0 && "Unknown unary operator");
+ case UO_PostInc: return "++";
+ case UO_PostDec: return "--";
+ case UO_PreInc: return "++";
+ case UO_PreDec: return "--";
+ case UO_AddrOf: return "&";
+ case UO_Deref: return "*";
+ case UO_Plus: return "+";
+ case UO_Minus: return "-";
+ case UO_Not: return "~";
+ case UO_LNot: return "!";
+ case UO_Real: return "__real";
+ case UO_Imag: return "__imag";
+ case UO_Extension: return "__extension__";
+ }
+}
+
+UnaryOperatorKind
+UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
+ switch (OO) {
+ default: assert(false && "No unary operator for overloaded function");
+ case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc;
+ case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec;
+ case OO_Amp: return UO_AddrOf;
+ case OO_Star: return UO_Deref;
+ case OO_Plus: return UO_Plus;
+ case OO_Minus: return UO_Minus;
+ case OO_Tilde: return UO_Not;
+ case OO_Exclaim: return UO_LNot;
+ }
+}
+
+OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
+ switch (Opc) {
+ case UO_PostInc: case UO_PreInc: return OO_PlusPlus;
+ case UO_PostDec: case UO_PreDec: return OO_MinusMinus;
+ case UO_AddrOf: return OO_Amp;
+ case UO_Deref: return OO_Star;
+ case UO_Plus: return OO_Plus;
+ case UO_Minus: return OO_Minus;
+ case UO_Not: return OO_Tilde;
+ case UO_LNot: return OO_Exclaim;
+ default: return OO_None;
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Postfix Operators.
+//===----------------------------------------------------------------------===//
+
+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+PREARGS_START+NumPreArgs];
+ SubExprs[FN] = fn;
+ 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, ExprValueKind VK, SourceLocation rparenloc)
+ : Expr(CallExprClass, t, VK, OK_Ordinary,
+ fn->isTypeDependent(),
+ fn->isValueDependent(),
+ fn->containsUnexpandedParameterPack()),
+ NumArgs(numargs) {
+
+ SubExprs = new (C) Stmt*[numargs+PREARGS_START];
+ SubExprs[FN] = fn;
+ 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) {
+ // 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<BinaryOperator>(CEE)) {
+ if (BO->isPtrMemOp())
+ CEE = BO->getRHS()->IgnoreParenCasts();
+ } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
+ if (UO->getOpcode() == UO_Deref)
+ CEE = UO->getSubExpr()->IgnoreParenCasts();
+ }
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
+ return DRE->getDecl();
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
+ return ME->getMemberDecl();
+
+ return 0;
+}
+
+FunctionDecl *CallExpr::getDirectCallee() {
+ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
+}
+
+/// setNumArgs - This changes the number of arguments present in this call.
+/// Any orphaned expressions are deleted by this, and any new operands are set
+/// to null.
+void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
+ // No change, just return.
+ if (NumArgs == getNumArgs()) return;
+
+ // If shrinking # arguments, just delete the extras and forgot them.
+ if (NumArgs < getNumArgs()) {
+ this->NumArgs = NumArgs;
+ return;
+ }
+
+ // Otherwise, we are growing the # arguments. New an bigger argument array.
+ unsigned NumPreArgs = getNumPreArgs();
+ Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs];
+ // Copy over args.
+ for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i)
+ NewSubExprs[i] = SubExprs[i];
+ // Null out new args.
+ for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs;
+ i != NumArgs+PREARGS_START+NumPreArgs; ++i)
+ NewSubExprs[i] = 0;
+
+ if (SubExprs) C.Deallocate(SubExprs);
+ SubExprs = NewSubExprs;
+ this->NumArgs = NumArgs;
+}
+
+/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
+/// not, return 0.
+unsigned CallExpr::isBuiltinCall(const ASTContext &Context) const {
+ // 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.
+ const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
+ if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
+ return 0;
+
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
+ if (!DRE)
+ return 0;
+
+ const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (!FDecl)
+ return 0;
+
+ if (!FDecl->getIdentifier())
+ return 0;
+
+ return FDecl->getBuiltinID();
+}
+
+QualType CallExpr::getCallReturnType() const {
+ QualType CalleeType = getCallee()->getType();
+ if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
+ CalleeType = FnTypePtr->getPointeeType();
+ else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
+ CalleeType = BPT->getPointeeType();
+ else if (const MemberPointerType *MPT
+ = CalleeType->getAs<MemberPointerType>())
+ CalleeType = MPT->getPointeeType();
+
+ const FunctionType *FnType = CalleeType->getAs<FunctionType>();
+ return FnType->getResultType();
+}
+
+OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type,
+ SourceLocation OperatorLoc,
+ TypeSourceInfo *tsi,
+ OffsetOfNode* compsPtr, unsigned numComps,
+ Expr** exprsPtr, unsigned numExprs,
+ SourceLocation RParenLoc) {
+ void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
+ sizeof(OffsetOfNode) * numComps +
+ sizeof(Expr*) * numExprs);
+
+ return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, compsPtr, numComps,
+ exprsPtr, numExprs, RParenLoc);
+}
+
+OffsetOfExpr *OffsetOfExpr::CreateEmpty(ASTContext &C,
+ unsigned numComps, unsigned numExprs) {
+ void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
+ sizeof(OffsetOfNode) * numComps +
+ sizeof(Expr*) * numExprs);
+ return new (Mem) OffsetOfExpr(numComps, numExprs);
+}
+
+OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type,
+ SourceLocation OperatorLoc, TypeSourceInfo *tsi,
+ OffsetOfNode* compsPtr, unsigned numComps,
+ Expr** exprsPtr, unsigned numExprs,
+ SourceLocation RParenLoc)
+ : 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)
+{
+ for(unsigned i = 0; i < numComps; ++i) {
+ setComponent(i, compsPtr[i]);
+ }
+
+ 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]);
+ }
+}
+
+IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
+ assert(getKind() == Field || getKind() == Identifier);
+ if (getKind() == Field)
+ return getField()->getIdentifier();
+
+ return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask);
+}
+
+MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
+ NestedNameSpecifier *qual,
+ SourceRange qualrange,
+ ValueDecl *memberdecl,
+ DeclAccessPair founddecl,
+ DeclarationNameInfo nameinfo,
+ const TemplateArgumentListInfo *targs,
+ QualType ty,
+ ExprValueKind vk,
+ ExprObjectKind ok) {
+ std::size_t Size = sizeof(MemberExpr);
+
+ bool hasQualOrFound = (qual != 0 ||
+ founddecl.getDecl() != memberdecl ||
+ founddecl.getAccess() != memberdecl->getAccess());
+ if (hasQualOrFound)
+ Size += sizeof(MemberNameQualifier);
+
+ if (targs)
+ Size += ExplicitTemplateArgumentList::sizeFor(*targs);
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
+ MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
+ ty, vk, ok);
+
+ if (hasQualOrFound) {
+ if (qual && qual->isDependent()) {
+ E->setValueDependent(true);
+ E->setTypeDependent(true);
+ }
+ E->HasQualifierOrFoundDecl = true;
+
+ MemberNameQualifier *NQ = E->getMemberQualifier();
+ NQ->NNS = qual;
+ NQ->Range = qualrange;
+ NQ->FoundDecl = founddecl;
+ }
+
+ if (targs) {
+ E->HasExplicitTemplateArgumentList = true;
+ E->getExplicitTemplateArgs().initializeFrom(*targs);
+ }
+
+ return E;
+}
+
+const char *CastExpr::getCastKindName() const {
+ switch (getCastKind()) {
+ 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:
+ return "BaseToDerived";
+ case CK_DerivedToBase:
+ return "DerivedToBase";
+ case CK_UncheckedDerivedToBase:
+ return "UncheckedDerivedToBase";
+ case CK_Dynamic:
+ return "Dynamic";
+ case CK_ToUnion:
+ return "ToUnion";
+ case CK_ArrayToPointerDecay:
+ return "ArrayToPointerDecay";
+ case CK_FunctionToPointerDecay:
+ return "FunctionToPointerDecay";
+ case CK_NullToMemberPointer:
+ return "NullToMemberPointer";
+ case CK_NullToPointer:
+ return "NullToPointer";
+ case CK_BaseToDerivedMemberPointer:
+ return "BaseToDerivedMemberPointer";
+ case CK_DerivedToBaseMemberPointer:
+ return "DerivedToBaseMemberPointer";
+ case CK_UserDefinedConversion:
+ return "UserDefinedConversion";
+ case CK_ConstructorConversion:
+ return "ConstructorConversion";
+ case CK_IntegralToPointer:
+ 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:
+ return "AnyPointerToObjCPointerCast";
+ case CK_AnyPointerToBlockPointerCast:
+ 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";
+ }
+
+ llvm_unreachable("Unhandled cast kind!");
+ return 0;
+}
+
+Expr *CastExpr::getSubExprAsWritten() {
+ Expr *SubExpr = 0;
+ CastExpr *E = this;
+ do {
+ SubExpr = E->getSubExpr();
+
+ // Skip any temporary bindings; they're implicit.
+ if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
+ SubExpr = Binder->getSubExpr();
+
+ // Conversions by constructor and conversion functions have a
+ // subexpression describing the call; strip it off.
+ if (E->getCastKind() == CK_ConstructorConversion)
+ SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
+ else if (E->getCastKind() == CK_UserDefinedConversion)
+ SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
+
+ // If the subexpression we're left with is an implicit cast, look
+ // through that, too.
+ } while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
+
+ return SubExpr;
+}
+
+CXXBaseSpecifier **CastExpr::path_buffer() {
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ return 0;
+ }
+}
+
+void CastExpr::setCastPath(const CXXCastPath &Path) {
+ assert(Path.size() == path_size());
+ memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
+}
+
+ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind VK) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ ImplicitCastExpr *E =
+ new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+}
+
+
+CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T,
+ ExprValueKind VK, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CStyleCastExpr *E =
+ new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+}
+
+/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+/// corresponds to, e.g. "<<=".
+const char *BinaryOperator::getOpcodeStr(Opcode Op) {
+ switch (Op) {
+ case BO_PtrMemD: return ".*";
+ case BO_PtrMemI: return "->*";
+ case BO_Mul: return "*";
+ case BO_Div: return "/";
+ case BO_Rem: return "%";
+ case BO_Add: return "+";
+ case BO_Sub: return "-";
+ case BO_Shl: return "<<";
+ case BO_Shr: return ">>";
+ case BO_LT: return "<";
+ case BO_GT: return ">";
+ case BO_LE: return "<=";
+ case BO_GE: return ">=";
+ case BO_EQ: return "==";
+ case BO_NE: return "!=";
+ case BO_And: return "&";
+ case BO_Xor: return "^";
+ case BO_Or: return "|";
+ case BO_LAnd: return "&&";
+ case BO_LOr: return "||";
+ case BO_Assign: return "=";
+ case BO_MulAssign: return "*=";
+ case BO_DivAssign: return "/=";
+ case BO_RemAssign: return "%=";
+ case BO_AddAssign: return "+=";
+ case BO_SubAssign: return "-=";
+ case BO_ShlAssign: return "<<=";
+ case BO_ShrAssign: return ">>=";
+ case BO_AndAssign: return "&=";
+ case BO_XorAssign: return "^=";
+ case BO_OrAssign: return "|=";
+ case BO_Comma: return ",";
+ }
+
+ return "";
+}
+
+BinaryOperatorKind
+BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
+ switch (OO) {
+ default: assert(false && "Not an overloadable binary operator");
+ case OO_Plus: return BO_Add;
+ case OO_Minus: return BO_Sub;
+ case OO_Star: return BO_Mul;
+ case OO_Slash: return BO_Div;
+ case OO_Percent: return BO_Rem;
+ case OO_Caret: return BO_Xor;
+ case OO_Amp: return BO_And;
+ case OO_Pipe: return BO_Or;
+ case OO_Equal: return BO_Assign;
+ case OO_Less: return BO_LT;
+ case OO_Greater: return BO_GT;
+ case OO_PlusEqual: return BO_AddAssign;
+ case OO_MinusEqual: return BO_SubAssign;
+ case OO_StarEqual: return BO_MulAssign;
+ case OO_SlashEqual: return BO_DivAssign;
+ case OO_PercentEqual: return BO_RemAssign;
+ case OO_CaretEqual: return BO_XorAssign;
+ case OO_AmpEqual: return BO_AndAssign;
+ case OO_PipeEqual: return BO_OrAssign;
+ case OO_LessLess: return BO_Shl;
+ case OO_GreaterGreater: return BO_Shr;
+ case OO_LessLessEqual: return BO_ShlAssign;
+ case OO_GreaterGreaterEqual: return BO_ShrAssign;
+ case OO_EqualEqual: return BO_EQ;
+ case OO_ExclaimEqual: return BO_NE;
+ case OO_LessEqual: return BO_LE;
+ case OO_GreaterEqual: return BO_GE;
+ case OO_AmpAmp: return BO_LAnd;
+ case OO_PipePipe: return BO_LOr;
+ case OO_Comma: return BO_Comma;
+ case OO_ArrowStar: return BO_PtrMemI;
+ }
+}
+
+OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
+ static const OverloadedOperatorKind OverOps[] = {
+ /* .* Cannot be overloaded */OO_None, OO_ArrowStar,
+ OO_Star, OO_Slash, OO_Percent,
+ OO_Plus, OO_Minus,
+ OO_LessLess, OO_GreaterGreater,
+ OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
+ OO_EqualEqual, OO_ExclaimEqual,
+ OO_Amp,
+ OO_Caret,
+ OO_Pipe,
+ OO_AmpAmp,
+ OO_PipePipe,
+ OO_Equal, OO_StarEqual,
+ OO_SlashEqual, OO_PercentEqual,
+ OO_PlusEqual, OO_MinusEqual,
+ OO_LessLessEqual, OO_GreaterGreaterEqual,
+ OO_AmpEqual, OO_CaretEqual,
+ OO_PipeEqual,
+ OO_Comma
+ };
+ return OverOps[Opc];
+}
+
+InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
+ Expr **initExprs, unsigned numInits,
+ SourceLocation rbraceloc)
+ : 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())
+ ExprBits.TypeDependent = true;
+ if (initExprs[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (initExprs[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+ }
+
+ InitExprs.insert(C, InitExprs.end(), initExprs, initExprs+numInits);
+}
+
+void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) {
+ if (NumInits > InitExprs.size())
+ InitExprs.reserve(C, NumInits);
+}
+
+void InitListExpr::resizeInits(ASTContext &C, unsigned NumInits) {
+ InitExprs.resize(C, NumInits, 0);
+}
+
+Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) {
+ if (Init >= InitExprs.size()) {
+ InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, 0);
+ InitExprs.back() = expr;
+ return 0;
+ }
+
+ Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
+ InitExprs[Init] = 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 {
+ return getType()->getAs<BlockPointerType>()->
+ getPointeeType()->getAs<FunctionType>();
+}
+
+SourceLocation BlockExpr::getCaretLocation() const {
+ return TheBlock->getCaretLocation();
+}
+const Stmt *BlockExpr::getBody() const {
+ return TheBlock->getBody();
+}
+Stmt *BlockExpr::getBody() {
+ return TheBlock->getBody();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Generic Expression Routines
+//===----------------------------------------------------------------------===//
+
+/// isUnusedResultAWarning - Return true if this immediate expression should
+/// be warned about if the result is unused. If so, fill in Loc and Ranges
+/// with location to warn on and the source range[s] to report with the
+/// warning.
+bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
+ SourceRange &R2, ASTContext &Ctx) const {
+ // Don't warn if the expr is type dependent. The type could end up
+ // instantiating to void.
+ if (isTypeDependent())
+ return false;
+
+ switch (getStmtClass()) {
+ default:
+ if (getType()->isVoidType())
+ return false;
+ Loc = getExprLoc();
+ R1 = getSourceRange();
+ return true;
+ case ParenExprClass:
+ return cast<ParenExpr>(this)->getSubExpr()->
+ isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ case UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(this);
+
+ switch (UO->getOpcode()) {
+ default: break;
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec: // ++/--
+ return false; // Not a warning.
+ case UO_Deref:
+ // Dereferencing a volatile pointer is a side-effect.
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
+ return false;
+ break;
+ case UO_Real:
+ case UO_Imag:
+ // accessing a piece of a volatile complex is a side-effect.
+ if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
+ .isVolatileQualified())
+ return false;
+ break;
+ case UO_Extension:
+ return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ }
+ Loc = UO->getOperatorLoc();
+ R1 = UO->getSubExpr()->getSourceRange();
+ return true;
+ }
+ case BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(this);
+ switch (BO->getOpcode()) {
+ default:
+ break;
+ // Consider the RHS of comma for side effects. LHS was checked by
+ // Sema::CheckCommaOperands.
+ case BO_Comma:
+ // ((foo = <blah>), 0) is an idiom for hiding the result (and
+ // lvalue-ness) of an assignment written in a macro.
+ if (IntegerLiteral *IE =
+ dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens()))
+ if (IE->getValue() == 0)
+ return false;
+ return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ // Consider '||', '&&' to have side effects if the LHS or RHS does.
+ case BO_LAnd:
+ case BO_LOr:
+ if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
+ !BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
+ return false;
+ break;
+ }
+ if (BO->isAssignmentOp())
+ return false;
+ Loc = BO->getOperatorLoc();
+ R1 = BO->getLHS()->getSourceRange();
+ R2 = BO->getRHS()->getSourceRange();
+ return true;
+ }
+ case CompoundAssignOperatorClass:
+ case VAArgExprClass:
+ return false;
+
+ case ConditionalOperatorClass: {
+ // The condition must be evaluated, but if either the LHS or RHS is a
+ // warning, warn about them.
+ const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
+ if (Exp->getLHS() &&
+ Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
+ return true;
+ return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ }
+
+ case MemberExprClass:
+ // If the base pointer or element is to a volatile pointer/field, accessing
+ // it is a side effect.
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
+ return false;
+ Loc = cast<MemberExpr>(this)->getMemberLoc();
+ R1 = SourceRange(Loc, Loc);
+ R2 = cast<MemberExpr>(this)->getBase()->getSourceRange();
+ return true;
+
+ case ArraySubscriptExprClass:
+ // If the base pointer or element is to a volatile pointer/field, accessing
+ // it is a side effect.
+ if (Ctx.getCanonicalType(getType()).isVolatileQualified())
+ return false;
+ Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
+ R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
+ R2 = cast<ArraySubscriptExpr>(this)->getRHS()->getSourceRange();
+ return true;
+
+ case CallExprClass:
+ case CXXOperatorCallExprClass:
+ case CXXMemberCallExprClass: {
+ // If this is a direct call, get the callee.
+ const CallExpr *CE = cast<CallExpr>(this);
+ if (const Decl *FD = CE->getCalleeDecl()) {
+ // If the callee has attribute pure, const, or warn_unused_result, warn
+ // about it. void foo() { strlen("bar"); } should warn.
+ //
+ // Note: If new cases are added here, DiagnoseUnusedExprResult should be
+ // updated to match for QoI.
+ if (FD->getAttr<WarnUnusedResultAttr>() ||
+ FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
+ Loc = CE->getCallee()->getLocStart();
+ R1 = CE->getCallee()->getSourceRange();
+
+ if (unsigned NumArgs = CE->getNumArgs())
+ R2 = SourceRange(CE->getArg(0)->getLocStart(),
+ CE->getArg(NumArgs-1)->getLocEnd());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ case CXXTemporaryObjectExprClass:
+ case CXXConstructExprClass:
+ return false;
+
+ case ObjCMessageExprClass: {
+ const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
+ const ObjCMethodDecl *MD = ME->getMethodDecl();
+ if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
+ Loc = getExprLoc();
+ return true;
+ }
+ return false;
+ }
+
+ case ObjCPropertyRefExprClass:
+ Loc = getExprLoc();
+ R1 = getSourceRange();
+ return true;
+
+ case StmtExprClass: {
+ // Statement exprs don't logically have side effects themselves, but are
+ // sometimes used in macros in ways that give them a type that is unused.
+ // For example ({ blah; foo(); }) will end up with a type if foo has a type.
+ // however, if the result of the stmt expr is dead, we don't want to emit a
+ // warning.
+ const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
+ if (!CS->body_empty()) {
+ if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
+ return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ if (const LabelStmt *Label = dyn_cast<LabelStmt>(CS->body_back()))
+ if (const Expr *E = dyn_cast<Expr>(Label->getSubStmt()))
+ return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
+ }
+
+ if (getType()->isVoidType())
+ return false;
+ Loc = cast<StmtExpr>(this)->getLParenLoc();
+ R1 = getSourceRange();
+ return true;
+ }
+ case CStyleCastExprClass:
+ // If this is an explicit cast to void, allow it. People do this when they
+ // think they know what they're doing :).
+ if (getType()->isVoidType())
+ return false;
+ Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
+ R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
+ return true;
+ case CXXFunctionalCastExprClass: {
+ if (getType()->isVoidType())
+ return false;
+ const CastExpr *CE = cast<CastExpr>(this);
+
+ // If this is a cast to void or a constructor conversion, check the operand.
+ // Otherwise, the result of the cast is unused.
+ if (CE->getCastKind() == CK_ToVoid ||
+ CE->getCastKind() == CK_ConstructorConversion)
+ return (cast<CastExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+ Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
+ R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
+ return true;
+ }
+
+ case ImplicitCastExprClass:
+ // Check the operand, since implicit casts are inserted by Sema
+ return (cast<ImplicitCastExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+
+ case CXXDefaultArgExprClass:
+ return (cast<CXXDefaultArgExpr>(this)
+ ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+
+ case CXXNewExprClass:
+ // FIXME: In theory, there might be new expressions that don't have side
+ // effects (e.g. a placement new with an uninitialized POD).
+ case CXXDeleteExprClass:
+ return false;
+ case CXXBindTemporaryExprClass:
+ return (cast<CXXBindTemporaryExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+ case ExprWithCleanupsClass:
+ return (cast<ExprWithCleanups>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
+ }
+}
+
+/// isOBJCGCCandidate - Check if an expression is objc gc'able.
+/// returns true, if it is; false otherwise.
+bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
+ switch (getStmtClass()) {
+ default:
+ return false;
+ case ObjCIvarRefExprClass:
+ return true;
+ case Expr::UnaryOperatorClass:
+ return cast<UnaryOperator>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case ParenExprClass:
+ return cast<ParenExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case ImplicitCastExprClass:
+ return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case CStyleCastExprClass:
+ return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
+ case DeclRefExprClass: {
+ const Decl *D = cast<DeclRefExpr>(this)->getDecl();
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasGlobalStorage())
+ return true;
+ QualType T = VD->getType();
+ // dereferencing to a pointer is always a gc'able candidate,
+ // unless it is __weak.
+ return T->isPointerType() &&
+ (Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
+ }
+ return false;
+ }
+ case MemberExprClass: {
+ const MemberExpr *M = cast<MemberExpr>(this);
+ return M->getBase()->isOBJCGCCandidate(Ctx);
+ }
+ case ArraySubscriptExprClass:
+ return cast<ArraySubscriptExpr>(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<Expr*>(CE);
+ Expr::CanThrowResult R = Expr::CT_Cannot;
+ for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) {
+ R = MergeCanThrow(R, cast<Expr>(*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<ValueDecl>(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<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
+ return Expr::CT_Cannot;
+
+ QualType T = VD->getType();
+ const FunctionProtoType *FT;
+ if ((FT = T->getAs<FunctionProtoType>())) {
+ } else if (const PointerType *PT = T->getAs<PointerType>())
+ FT = PT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ FT = RT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
+ FT = MT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
+ FT = BT->getPointeeType()->getAs<FunctionProtoType>();
+
+ 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<RecordType>();
+ if (!RT)
+ return Expr::CT_Cannot;
+
+ if (!cast<CXXRecordDecl>(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<T>(v),
+ // where T is a reference type, that requires a run-time check
+ CanThrowResult CT = CanDynamicCastThrow(cast<CXXDynamicCastExpr>(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<CXXTypeidExpr>(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<CallExpr>(this)->getCalleeDecl());
+ if (CT == CT_Can)
+ return CT;
+ return MergeCanThrow(CT, CanSubExprsThrow(C, this));
+ }
+
+ case CXXConstructExprClass:
+ case CXXTemporaryObjectExprClass: {
+ CanThrowResult CT = CanCalleeThrow(
+ cast<CXXConstructExpr>(this)->getConstructor());
+ if (CT == CT_Can)
+ return CT;
+ return MergeCanThrow(CT, CanSubExprsThrow(C, this));
+ }
+
+ case CXXNewExprClass: {
+ CanThrowResult CT = MergeCanThrow(
+ CanCalleeThrow(cast<CXXNewExpr>(this)->getOperatorNew()),
+ CanCalleeThrow(cast<CXXNewExpr>(this)->getConstructor(),
+ /*NullThrows*/false));
+ if (CT == CT_Can)
+ return CT;
+ return MergeCanThrow(CT, CanSubExprsThrow(C, this));
+ }
+
+ case CXXDeleteExprClass: {
+ CanThrowResult CT = CanCalleeThrow(
+ cast<CXXDeleteExpr>(this)->getOperatorDelete());
+ if (CT == CT_Can)
+ return CT;
+ const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument();
+ // Unwrap exactly one implicit cast, which converts all pointers to void*.
+ if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = Cast->getSubExpr();
+ if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) {
+ if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
+ CanThrowResult CT2 = CanCalleeThrow(
+ cast<CXXRecordDecl>(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<CXXBindTemporaryExpr>(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<ChooseExpr>(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 (true) {
+ if (ParenExpr* P = dyn_cast<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
+ if (P->getOpcode() == UO_Extension) {
+ E = P->getSubExpr();
+ continue;
+ }
+ }
+ return E;
+ }
+}
+
+/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
+/// or CastExprs or ImplicitCastExprs, returning their operand.
+Expr *Expr::IgnoreParenCasts() {
+ Expr *E = this;
+ while (true) {
+ if (ParenExpr* P = dyn_cast<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (UnaryOperator* P = dyn_cast<UnaryOperator>(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<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ } else if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+ if (P->getCastKind() == CK_LValueToRValue) {
+ E = P->getSubExpr();
+ continue;
+ }
+ } else if (UnaryOperator* P = dyn_cast<UnaryOperator>(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<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
+ if (P->getOpcode() == UO_Extension) {
+ E = P->getSubExpr();
+ continue;
+ }
+ }
+ return E;
+ }
+}
+
+/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
+/// value (including ptr->int casts of the same size). Strip off any
+/// ParenExpr or CastExprs, returning their operand.
+Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
+ Expr *E = this;
+ while (true) {
+ if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+
+ if (CastExpr *P = dyn_cast<CastExpr>(E)) {
+ // We ignore integer <-> casts that are of the same width, ptr<->ptr and
+ // ptr<->int casts of the same width. We also ignore all identity casts.
+ Expr *SE = P->getSubExpr();
+
+ if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) {
+ E = SE;
+ continue;
+ }
+
+ if ((E->getType()->isPointerType() ||
+ E->getType()->isIntegralType(Ctx)) &&
+ (SE->getType()->isPointerType() ||
+ SE->getType()->isIntegralType(Ctx)) &&
+ Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) {
+ E = SE;
+ continue;
+ }
+ }
+
+ if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
+ if (P->getOpcode() == UO_Extension) {
+ E = P->getSubExpr();
+ continue;
+ }
+ }
+
+ return E;
+ }
+}
+
+bool Expr::isDefaultArgument() const {
+ const Expr *E = this;
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExprAsWritten();
+
+ return isa<CXXDefaultArgExpr>(E);
+}
+
+/// \brief Skip over any no-op casts and any temporary-binding
+/// expressions.
+static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CK_NoOp)
+ E = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = BE->getSubExpr();
+
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CK_NoOp)
+ E = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ return E->IgnoreParens();
+}
+
+/// 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;
+
+ const Expr *E = skipTemporaryBindingsNoOpCastsAndParens(this);
+
+ // 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<ObjCPropertyRefExpr>(E))
+ return false;
+ }
+
+ // Black-list a few cases which yield pr-values of class type that don't
+ // refer to temporaries of that type:
+
+ // - implicit derived-to-base conversions
+ if (isa<ImplicitCastExpr>(E)) {
+ switch (cast<ImplicitCastExpr>(E)->getCastKind()) {
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ return false;
+ default:
+ break;
+ }
+ }
+
+ // - member expressions (all)
+ if (isa<MemberExpr>(E))
+ return false;
+
+ // - opaque values (all)
+ if (isa<OpaqueValueExpr>(E))
+ return false;
+
+ return true;
+}
+
+/// hasAnyTypeDependentArguments - Determines if any of the expressions
+/// in Exprs is type-dependent.
+bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {
+ for (unsigned I = 0; I < NumExprs; ++I)
+ if (Exprs[I]->isTypeDependent())
+ return true;
+
+ return false;
+}
+
+/// hasAnyValueDependentArguments - Determines if any of the expressions
+/// in Exprs is value-dependent.
+bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
+ for (unsigned I = 0; I < NumExprs; ++I)
+ if (Exprs[I]->isValueDependent())
+ return true;
+
+ return false;
+}
+
+bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
+ // This function is attempting whether an expression is an initializer
+ // which can be evaluated at compile-time. isEvaluatable handles most
+ // of the cases, but it can't deal with some initializer-specific
+ // expressions, and it can't deal with aggregates; we deal with those here,
+ // and fall back to isEvaluatable for the other cases.
+
+ // If we ever capture reference-binding directly in the AST, we can
+ // kill the second parameter.
+
+ if (IsForRef) {
+ EvalResult Result;
+ return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects;
+ }
+
+ switch (getStmtClass()) {
+ default: break;
+ case StringLiteralClass:
+ case ObjCStringLiteralClass:
+ case ObjCEncodeExprClass:
+ return true;
+ case CXXTemporaryObjectExprClass:
+ case CXXConstructExprClass: {
+ const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
+
+ // Only if it's
+ // 1) an application of the trivial default constructor or
+ if (!CE->getConstructor()->isTrivial()) return false;
+ if (!CE->getNumArgs()) return true;
+
+ // 2) an elidable trivial copy construction of an operand which is
+ // itself a constant initializer. Note that we consider the
+ // operand on its own, *not* as a reference binding.
+ return CE->isElidable() &&
+ CE->getArg(0)->isConstantInitializer(Ctx, false);
+ }
+ case CompoundLiteralExprClass: {
+ // This handles gcc's extension that allows global initializers like
+ // "struct x {int x;} x = (struct x) {};".
+ // FIXME: This accepts other cases it shouldn't!
+ const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
+ return Exp->isConstantInitializer(Ctx, false);
+ }
+ case InitListExprClass: {
+ // FIXME: This doesn't deal with fields with reference types correctly.
+ // FIXME: This incorrectly allows pointers cast to integers to be assigned
+ // to bitfields.
+ const InitListExpr *Exp = cast<InitListExpr>(this);
+ unsigned numInits = Exp->getNumInits();
+ for (unsigned i = 0; i < numInits; i++) {
+ if (!Exp->getInit(i)->isConstantInitializer(Ctx, false))
+ return false;
+ }
+ return true;
+ }
+ case ImplicitValueInitExprClass:
+ return true;
+ case ParenExprClass:
+ return cast<ParenExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, IsForRef);
+ case ChooseExprClass:
+ return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)
+ ->isConstantInitializer(Ctx, IsForRef);
+ case UnaryOperatorClass: {
+ const UnaryOperator* Exp = cast<UnaryOperator>(this);
+ if (Exp->getOpcode() == UO_Extension)
+ return Exp->getSubExpr()->isConstantInitializer(Ctx, false);
+ break;
+ }
+ case BinaryOperatorClass: {
+ // Special case &&foo - &&bar. It would be nice to generalize this somehow
+ // but this handles the common case.
+ const BinaryOperator *Exp = cast<BinaryOperator>(this);
+ if (Exp->getOpcode() == BO_Sub &&
+ isa<AddrLabelExpr>(Exp->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
+ isa<AddrLabelExpr>(Exp->getRHS()->IgnoreParenNoopCasts(Ctx)))
+ return true;
+ break;
+ }
+ case CXXFunctionalCastExprClass:
+ case CXXStaticCastExprClass:
+ case ImplicitCastExprClass:
+ case CStyleCastExprClass:
+ // Handle casts with a destination that's a struct or union; this
+ // deals with both the gcc no-op struct cast extension and the
+ // cast-to-union extension.
+ if (getType()->isRecordType())
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
+
+ // Integer->integer casts can be handled here, which is important for
+ // things like (int)(&&x-&&y). Scary but true.
+ if (getType()->isIntegerType() &&
+ cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType())
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
+
+ break;
+ }
+ return isEvaluatable(Ctx);
+}
+
+/// 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:
+ assert(false && "Unexpected value dependent expression!");
+ // If the unthinkable happens, fall through to the safest alternative.
+
+ case NPC_ValueDependentIsNull:
+ if (isTypeDependent() || getType()->isIntegralType(Ctx))
+ return NPCK_ZeroInteger;
+ else
+ return NPCK_NotNull;
+
+ case NPC_ValueDependentIsNotNull:
+ return NPCK_NotNull;
+ }
+ }
+
+ // Strip off a cast to void*, if it exists. Except in C++.
+ if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) {
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // Check that it is a cast to void*.
+ if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
+ QualType Pointee = PT->getPointeeType();
+ if (!Pointee.hasQualifiers() &&
+ Pointee->isVoidType() && // to void*
+ CE->getSubExpr()->getType()->isIntegerType()) // from int.
+ return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
+ }
+ }
+ } else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(this)) {
+ // Ignore the ImplicitCastExpr type entirely.
+ return ICE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) {
+ // Accept ((void*)0) as a null pointer constant, as many other
+ // implementations do.
+ return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const CXXDefaultArgExpr *DefaultArg
+ = dyn_cast<CXXDefaultArgExpr>(this)) {
+ // See through default argument expressions
+ return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (isa<GNUNullExpr>(this)) {
+ // The GNU __null extension is always a null pointer constant.
+ return NPCK_GNUNull;
+ }
+
+ // C++0x nullptr_t is always a null pointer constant.
+ if (getType()->isNullPtrType())
+ return NPCK_CXX0X_nullptr;
+
+ if (const RecordType *UT = getType()->getAsUnionType())
+ if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(this)){
+ const Expr *InitExpr = CLE->getInitializer();
+ if (const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr))
+ return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC);
+ }
+ // This expression must be an integer type.
+ if (!getType()->isIntegerType() ||
+ (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType()))
+ return NPCK_NotNull;
+
+ // If we have an integer constant expression, we need to *evaluate* it and
+ // test for the value 0.
+ llvm::APSInt Result;
+ bool IsNull = isIntegerConstantExpr(Result, Ctx) && Result == 0;
+
+ 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<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma) {
+ E = BO->getRHS();
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ return cast<ObjCPropertyRefExpr>(E);
+}
+
+FieldDecl *Expr::getBitField() {
+ Expr *E = this->IgnoreParens();
+
+ while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CK_LValueToRValue ||
+ (ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp))
+ E = ICE->getSubExpr()->IgnoreParens();
+ else
+ break;
+ }
+
+ if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
+ if (Field->isBitField())
+ return Field;
+
+ if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E))
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
+ if (Field->isBitField())
+ return Field;
+
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E))
+ if (BinOp->isAssignmentOp() && BinOp->getLHS())
+ return BinOp->getLHS()->getBitField();
+
+ return 0;
+}
+
+bool Expr::refersToVectorElement() const {
+ const Expr *E = this->IgnoreParens();
+
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getValueKind() != VK_RValue &&
+ ICE->getCastKind() == CK_NoOp)
+ E = ICE->getSubExpr()->IgnoreParens();
+ else
+ break;
+ }
+
+ if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E))
+ return ASE->getBase()->getType()->isVectorType();
+
+ if (isa<ExtVectorElementExpr>(E))
+ return true;
+
+ return false;
+}
+
+/// isArrow - Return true if the base expression is a pointer to vector,
+/// return false if the base expression is a vector.
+bool ExtVectorElementExpr::isArrow() const {
+ return getBase()->getType()->isPointerType();
+}
+
+unsigned ExtVectorElementExpr::getNumElements() const {
+ if (const VectorType *VT = getType()->getAs<VectorType>())
+ return VT->getNumElements();
+ return 1;
+}
+
+/// containsDuplicateElements - Return true if any element access is repeated.
+bool ExtVectorElementExpr::containsDuplicateElements() const {
+ // FIXME: Refactor this code to an accessor on the AST node which returns the
+ // "type" of component access, and share with code below and in Sema.
+ llvm::StringRef Comp = Accessor->getName();
+
+ // Halving swizzles do not contain duplicate elements.
+ if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
+ return false;
+
+ // Advance past s-char prefix on hex swizzles.
+ if (Comp[0] == 's' || Comp[0] == 'S')
+ Comp = Comp.substr(1);
+
+ for (unsigned i = 0, e = Comp.size(); i != e; ++i)
+ if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)
+ return true;
+
+ return false;
+}
+
+/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
+void ExtVectorElementExpr::getEncodedElementAccess(
+ llvm::SmallVectorImpl<unsigned> &Elts) const {
+ llvm::StringRef Comp = Accessor->getName();
+ if (Comp[0] == 's' || Comp[0] == 'S')
+ Comp = Comp.substr(1);
+
+ bool isHi = Comp == "hi";
+ bool isLo = Comp == "lo";
+ bool isEven = Comp == "even";
+ bool isOdd = Comp == "odd";
+
+ for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
+ uint64_t Index;
+
+ if (isHi)
+ Index = e + i;
+ else if (isLo)
+ Index = i;
+ else if (isEven)
+ Index = 2 * i;
+ else if (isOdd)
+ Index = 2 * i + 1;
+ else
+ Index = ExtVectorType::getAccessorIdx(Comp[i]);
+
+ Elts.push_back(Index);
+ }
+}
+
+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, VK, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass),
+ HasMethod(Method != 0), SuperLoc(SuperLoc),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+{
+ setReceiverPointer(SuperType.getAsOpaquePtr());
+ if (NumArgs)
+ memcpy(getArgs(), Args, NumArgs * sizeof(Expr *));
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ SourceLocation SelLoc,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc)
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
+ T->isDependentType(), T->containsUnexpandedParameterPack()),
+ NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+{
+ setReceiverPointer(Receiver);
+ 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, VK, OK_Ordinary, Receiver->isTypeDependent(),
+ Receiver->isTypeDependent(),
+ Receiver->containsUnexpandedParameterPack()),
+ NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+{
+ setReceiverPointer(Receiver);
+ 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<ObjCMessageExpr>::Alignment);
+ 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<ObjCMessageExpr>::Alignment);
+ 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,
+ 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<ObjCMessageExpr>::Alignment);
+ return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc,
+ Method, Args, NumArgs, RBracLoc);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
+ unsigned NumArgs) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *);
+ void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::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<const ObjCMethodDecl *>(SelectorOrMethod)
+ ->getSelector();
+ return Selector(SelectorOrMethod);
+}
+
+ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+ switch (getReceiverKind()) {
+ case Instance:
+ if (const ObjCObjectPointerType *Ptr
+ = getInstanceReceiver()->getType()->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+ break;
+
+ case Class:
+ if (const ObjCObjectType *Ty
+ = getClassReceiver()->getAs<ObjCObjectType>())
+ return Ty->getInterface();
+ break;
+
+ case SuperInstance:
+ if (const ObjCObjectPointerType *Ptr
+ = getSuperType()->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+ break;
+
+ case SuperClass:
+ if (const ObjCObjectType *Iface
+ = getSuperType()->getAs<ObjCObjectType>())
+ return Iface->getInterface();
+ break;
+ }
+
+ return 0;
+}
+
+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);
+
+ SubExprs = new (C) Stmt* [NumExprs];
+ this->NumExprs = NumExprs;
+ memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
+}
+
+//===----------------------------------------------------------------------===//
+// DesignatedInitExpr
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ if (Field.NameOrField & 0x01)
+ return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01);
+ else
+ return getField()->getIdentifier();
+}
+
+DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
+ unsigned NumDesignators,
+ const Designator *Designators,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax,
+ Expr **IndexExprs,
+ unsigned NumIndexExprs,
+ Expr *Init)
+ : Expr(DesignatedInitExprClass, Ty,
+ 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_range Child = children();
+ *Child++ = Init;
+
+ // Copy the designators and their subexpressions, computing
+ // value-dependence along the way.
+ unsigned IndexIdx = 0;
+ for (unsigned I = 0; I != NumDesignators; ++I) {
+ this->Designators[I] = Designators[I];
+
+ if (this->Designators[I].isArrayDesignator()) {
+ // Compute type- and value-dependence.
+ Expr *Index = IndexExprs[IndexIdx];
+ 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++];
+ } else if (this->Designators[I].isArrayRangeDesignator()) {
+ // Compute type- and value-dependence.
+ Expr *Start = IndexExprs[IndexIdx];
+ Expr *End = IndexExprs[IndexIdx + 1];
+ 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++];
+ *Child++ = IndexExprs[IndexIdx++];
+ }
+ }
+
+ assert(IndexIdx == NumIndexExprs && "Wrong number of index expressions");
+}
+
+DesignatedInitExpr *
+DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
+ unsigned NumDesignators,
+ Expr **IndexExprs, unsigned NumIndexExprs,
+ SourceLocation ColonOrEqualLoc,
+ bool UsesColonSyntax, Expr *Init) {
+ void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
+ sizeof(Stmt *) * (NumIndexExprs + 1), 8);
+ return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
+ ColonOrEqualLoc, UsesColonSyntax,
+ IndexExprs, NumIndexExprs, Init);
+}
+
+DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
+ unsigned NumIndexExprs) {
+ void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
+ sizeof(Stmt *) * (NumIndexExprs + 1), 8);
+ return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
+}
+
+void DesignatedInitExpr::setDesignators(ASTContext &C,
+ const Designator *Desigs,
+ unsigned NumDesigs) {
+ Designators = new (C) Designator[NumDesigs];
+ NumDesignators = NumDesigs;
+ for (unsigned I = 0; I != NumDesigs; ++I)
+ Designators[I] = Desigs[I];
+}
+
+SourceRange DesignatedInitExpr::getSourceRange() const {
+ SourceLocation StartLoc;
+ Designator &First =
+ *const_cast<DesignatedInitExpr*>(this)->designators_begin();
+ if (First.isFieldDesignator()) {
+ if (GNUSyntax)
+ StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc);
+ else
+ StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc);
+ } else
+ StartLoc =
+ SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc);
+ return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
+}
+
+Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
+ assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+ return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+}
+
+Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
+ assert(D.Kind == Designator::ArrayRangeDesignator &&
+ "Requires array range designator");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+ return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+}
+
+Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
+ assert(D.Kind == Designator::ArrayRangeDesignator &&
+ "Requires array range designator");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+ return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
+}
+
+/// \brief Replaces the designator at index @p Idx with the series
+/// of designators in [First, Last).
+void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
+ const Designator *First,
+ const Designator *Last) {
+ unsigned NumNewDesignators = Last - First;
+ if (NumNewDesignators == 0) {
+ std::copy_backward(Designators + Idx + 1,
+ Designators + NumDesignators,
+ Designators + Idx);
+ --NumNewDesignators;
+ return;
+ } else if (NumNewDesignators == 1) {
+ Designators[Idx] = *First;
+ return;
+ }
+
+ Designator *NewDesignators
+ = new (C) Designator[NumDesignators - 1 + NumNewDesignators];
+ std::copy(Designators, Designators + Idx, NewDesignators);
+ std::copy(First, Last, NewDesignators + Idx);
+ std::copy(Designators + Idx + 1, Designators + NumDesignators,
+ NewDesignators + Idx + NumNewDesignators);
+ Designators = NewDesignators;
+ NumDesignators = NumDesignators - 1 + NumNewDesignators;
+}
+
+ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
+ Expr **exprs, unsigned nexprs,
+ SourceLocation 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) {
+ 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<ExprWithCleanups>(e))
+ e = ewc->getSubExpr();
+ e = cast<CXXConstructExpr>(e)->getArg(0);
+ while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
+ e = ice->getSubExpr();
+ return cast<OpaqueValueExpr>(e);
+}
+
+//===----------------------------------------------------------------------===//
+// ExprIterator.
+//===----------------------------------------------------------------------===//
+
+Expr* ExprIterator::operator[](size_t idx) { return cast<Expr>(I[idx]); }
+Expr* ExprIterator::operator*() const { return cast<Expr>(*I); }
+Expr* ExprIterator::operator->() const { return cast<Expr>(*I); }
+const Expr* ConstExprIterator::operator[](size_t idx) const {
+ return cast<Expr>(I[idx]);
+}
+const Expr* ConstExprIterator::operator*() const { return cast<Expr>(*I); }
+const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); }
+
+//===----------------------------------------------------------------------===//
+// Child Iterators for iterating over subexpressions/substatements
+//===----------------------------------------------------------------------===//
+
+// SizeOfAlignOfExpr
+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 (const VariableArrayType* T = dyn_cast<VariableArrayType>(
+ getArgumentType().getTypePtr()))
+ return child_range(child_iterator(T), child_iterator());
+ return child_range();
+ }
+ return child_range(&Argument.Ex, &Argument.Ex + 1);
+}
+
+// ObjCMessageExpr
+Stmt::child_range ObjCMessageExpr::children() {
+ Stmt **begin;
+ if (getReceiverKind() == Instance)
+ begin = reinterpret_cast<Stmt **>(this + 1);
+ else
+ begin = reinterpret_cast<Stmt **>(getArgs());
+ return child_range(begin,
+ reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
+}
+
+// Blocks
+BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
+ SourceLocation l, bool ByRef,
+ bool constAdded)
+ : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false,
+ 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;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
new file mode 100644
index 0000000..28ff9fb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -0,0 +1,893 @@
+//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Expr class declared in ExprCXX.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
+using namespace clang;
+
+
+//===----------------------------------------------------------------------===//
+// Child Iterators for iterating over subexpressions/substatements
+//===----------------------------------------------------------------------===//
+
+QualType CXXTypeidExpr::getTypeOperand() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ return Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType()
+ .getUnqualifiedType();
+}
+
+QualType CXXUuidofExpr::getTypeOperand() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ return Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType()
+ .getUnqualifiedType();
+}
+
+// CXXScalarValueInitExpr
+SourceRange CXXScalarValueInitExpr::getSourceRange() const {
+ SourceLocation Start = RParenLoc;
+ if (TypeInfo)
+ Start = TypeInfo->getTypeLoc().getBeginLoc();
+ return SourceRange(Start, RParenLoc);
+}
+
+// CXXNewExpr
+CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
+ Expr **placementArgs, unsigned numPlaceArgs,
+ SourceRange TypeIdParens, Expr *arraySize,
+ CXXConstructorDecl *constructor, bool initializer,
+ Expr **constructorArgs, unsigned numConsArgs,
+ 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),
+ AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens),
+ StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen),
+ ConstructorRParen(constructorRParen) {
+ AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs);
+ unsigned i = 0;
+ if (Array) {
+ if (arraySize->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ SubExprs[i++] = arraySize;
+ }
+
+ 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) {
+ if (constructorArgs[j]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ SubExprs[i++] = constructorArgs[j];
+ }
+}
+
+void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
+ unsigned numPlaceArgs, unsigned numConsArgs){
+ assert(SubExprs == 0 && "SubExprs already allocated");
+ Array = isArray;
+ NumPlacementArgs = numPlaceArgs;
+ NumConstructorArgs = numConsArgs;
+
+ unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs;
+ SubExprs = new (C) Stmt*[TotalSize];
+}
+
+
+// CXXDeleteExpr
+QualType CXXDeleteExpr::getDestroyedType() const {
+ const Expr *Arg = getArgument();
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(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();
+
+ if (ArgType->isDependentType() && !ArgType->isPointerType())
+ return QualType();
+
+ return ArgType->getAs<PointerType>()->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<Stmt *>(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();
+
+ return QualType();
+}
+
+SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
+ SourceLocation End = DestroyedType.getLocation();
+ if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+ End = TInfo->getTypeLoc().getLocalSourceRange().getEnd();
+ return SourceRange(Base->getLocStart(), End);
+}
+
+
+// UnresolvedLookupExpr
+UnresolvedLookupExpr *
+UnresolvedLookupExpr::Create(ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL,
+ const TemplateArgumentListInfo &Args,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
+{
+ void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
+ ExplicitTemplateArgumentList::sizeFor(Args));
+ return new (Mem) UnresolvedLookupExpr(C, NamingClass,
+ Qualifier, QualifierRange, NameInfo,
+ ADL, /*Overload*/ true, &Args,
+ Begin, End);
+}
+
+UnresolvedLookupExpr *
+UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs) {
+ std::size_t size = sizeof(UnresolvedLookupExpr);
+ if (HasExplicitTemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
+ UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
+ E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
+ return E;
+}
+
+OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
+ NestedNameSpecifier *Qualifier, SourceRange QRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin,
+ 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)
+{
+ 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<UnresolvedUsingValueDecl>(*I)) {
+ ExprBits.TypeDependent = true;
+ ExprBits.ValueDependent = true;
+ }
+ }
+
+ Results = static_cast<DeclAccessPair *>(
+ C.Allocate(sizeof(DeclAccessPair) * NumResults,
+ llvm::alignOf<DeclAccessPair>()));
+ memcpy(Results, &*Begin.getIterator(),
+ NumResults * sizeof(DeclAccessPair));
+ }
+
+ // 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 (isTypeDependent())
+ setType(C.DependentTy);
+}
+
+void OverloadExpr::initializeResults(ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ assert(Results == 0 && "Results already initialized!");
+ NumResults = End - Begin;
+ if (NumResults) {
+ Results = static_cast<DeclAccessPair *>(
+ C.Allocate(sizeof(DeclAccessPair) * NumResults,
+
+ llvm::alignOf<DeclAccessPair>()));
+ memcpy(Results, &*Begin.getIterator(),
+ NumResults * sizeof(DeclAccessPair));
+ }
+}
+
+CXXRecordDecl *OverloadExpr::getNamingClass() const {
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)->getNamingClass();
+ else
+ return cast<UnresolvedMemberExpr>(this)->getNamingClass();
+}
+
+// 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<ExplicitTemplateArgumentList*>(this+1)
+ ->initializeFrom(*Args, Dependent, ContainsUnexpandedParameterPack);
+ ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ }
+}
+
+DependentScopeDeclRefExpr *
+DependentScopeDeclRefExpr::Create(ASTContext &C,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args) {
+ std::size_t size = sizeof(DependentScopeDeclRefExpr);
+ if (Args)
+ 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 (HasExplicitTemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ void *Mem = C.Allocate(size);
+ DependentScopeDeclRefExpr *E
+ = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
+ DeclarationNameInfo(), 0);
+ E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
+ return E;
+}
+
+SourceRange CXXConstructExpr::getSourceRange() const {
+ if (ParenRange.isValid())
+ return SourceRange(Loc, ParenRange.getEnd());
+
+ 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 SourceRange(Loc, End);
+}
+
+SourceRange CXXOperatorCallExpr::getSourceRange() const {
+ OverloadedOperatorKind Kind = getOperator();
+ if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+ if (getNumArgs() == 1)
+ // Prefix operator
+ return SourceRange(getOperatorLoc(),
+ getArg(0)->getSourceRange().getEnd());
+ else
+ // Postfix operator
+ return SourceRange(getArg(0)->getSourceRange().getEnd(),
+ getOperatorLoc());
+ } else if (Kind == OO_Call) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+ } else if (Kind == OO_Subscript) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+ } else if (getNumArgs() == 1) {
+ return SourceRange(getOperatorLoc(), getArg(0)->getSourceRange().getEnd());
+ } else if (getNumArgs() == 2) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(),
+ getArg(1)->getSourceRange().getEnd());
+ } else {
+ return SourceRange();
+ }
+}
+
+Expr *CXXMemberCallExpr::getImplicitObjectArgument() {
+ if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
+ return MemExpr->getBase();
+
+ // FIXME: Will eventually need to cope with member pointers.
+ 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)
+ LocStart = getArg(0)->getLocStart();
+ return SourceRange(LocStart, getRParenLoc());
+}
+
+
+//===----------------------------------------------------------------------===//
+// Named casts
+//===----------------------------------------------------------------------===//
+
+/// getCastName - Get the name of the C++ cast being used, e.g.,
+/// "static_cast", "dynamic_cast", "reinterpret_cast", or
+/// "const_cast". The returned pointer must not be freed.
+const char *CXXNamedCastExpr::getCastName() const {
+ switch (getStmtClass()) {
+ case CXXStaticCastExprClass: return "static_cast";
+ case CXXDynamicCastExprClass: return "dynamic_cast";
+ case CXXReinterpretCastExprClass: return "reinterpret_cast";
+ case CXXConstCastExprClass: return "const_cast";
+ default: return "<invalid cast>";
+ }
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
+ ExprValueKind VK,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ 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, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
+ ExprValueKind VK,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ 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, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ 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, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L,
+ SourceLocation RParenLoc) {
+ return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
+ return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK,
+ TypeSourceInfo *Written, SourceLocation L,
+ CastKind K, Expr *Op, const CXXCastPath *BasePath,
+ SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXFunctionalCastExpr *E =
+ new (Buffer) CXXFunctionalCastExpr(T, VK, Written, L, K, Op, PathSize, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+
+CXXDefaultArgExpr *
+CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
+ ParmVarDecl *Param, Expr *SubExpr) {
+ void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *));
+ return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param,
+ SubExpr);
+}
+
+CXXTemporary *CXXTemporary::Create(ASTContext &C,
+ const CXXDestructorDecl *Destructor) {
+ return new (C) CXXTemporary(Destructor);
+}
+
+CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
+ CXXTemporary *Temp,
+ Expr* SubExpr) {
+ assert(SubExpr->getType()->isRecordType() &&
+ "Expression bound to a temporary must have record type!");
+
+ return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
+}
+
+CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
+ CXXConstructorDecl *Cons,
+ TypeSourceInfo *Type,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceRange parenRange,
+ bool ZeroInitialization)
+ : 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,
+ SourceLocation Loc,
+ CXXConstructorDecl *D, bool Elidable,
+ Expr **Args, unsigned NumArgs,
+ bool ZeroInitialization,
+ ConstructionKind ConstructKind,
+ SourceRange ParenRange) {
+ return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
+ Elidable, Args, NumArgs, ZeroInitialization,
+ ConstructKind, ParenRange);
+}
+
+CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *D, bool elidable,
+ Expr **args, unsigned numargs,
+ bool ZeroInitialization,
+ 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];
+ }
+ }
+}
+
+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);
+ for (unsigned i = 0; i != numtemps; ++i)
+ Temps[i] = temps[i];
+ }
+}
+
+void ExprWithCleanups::setNumTemporaries(ASTContext &C, unsigned N) {
+ assert(Temps == 0 && "Cannot resize with this");
+ NumTemps = N;
+ Temps = new (C) CXXTemporary*[NumTemps];
+}
+
+
+ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C,
+ Expr *SubExpr,
+ CXXTemporary **Temps,
+ unsigned NumTemps) {
+ return new (C) ExprWithCleanups(C, SubExpr, Temps, NumTemps);
+}
+
+CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc)
+ : 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<Stmt **>(this + 1);
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ if (Args[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ StoredArgs[I] = Args[I];
+ }
+}
+
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::Create(ASTContext &C,
+ TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
+ sizeof(Expr *) * NumArgs);
+ return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc,
+ Args, NumArgs, RParenLoc);
+}
+
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) {
+ Stmt::EmptyShell Empty;
+ void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
+ sizeof(Expr *) * NumArgs);
+ return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
+}
+
+SourceRange CXXUnresolvedConstructExpr::getSourceRange() const {
+ return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc);
+}
+
+CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
+ Expr *Base, QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs)
+ : 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) {
+ 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,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ if (!TemplateArgs)
+ return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType,
+ IsArrow, OperatorLoc,
+ Qualifier, QualifierRange,
+ FirstQualifierFoundInScope,
+ MemberNameInfo);
+
+ std::size_t size = sizeof(CXXDependentScopeMemberExpr);
+ if (TemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
+ IsArrow, OperatorLoc,
+ Qualifier, QualifierRange,
+ FirstQualifierFoundInScope,
+ MemberNameInfo, TemplateArgs);
+}
+
+CXXDependentScopeMemberExpr *
+CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
+ bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs) {
+ if (!HasExplicitTemplateArgs)
+ return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ 0, SourceLocation(), 0,
+ SourceRange(), 0,
+ DeclarationNameInfo());
+
+ std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
+ ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+ void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ CXXDependentScopeMemberExpr *E
+ = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
+ 0, SourceLocation(), 0,
+ SourceRange(), 0,
+ DeclarationNameInfo(), 0);
+ E->HasExplicitTemplateArgs = true;
+ return E;
+}
+
+UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C,
+ bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
+ : OverloadExpr(UnresolvedMemberExprClass, C,
+ Qualifier, QualifierRange, MemberNameInfo,
+ 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) {
+}
+
+UnresolvedMemberExpr *
+UnresolvedMemberExpr::Create(ASTContext &C,
+ bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ std::size_t size = sizeof(UnresolvedMemberExpr);
+ if (TemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
+ return new (Mem) UnresolvedMemberExpr(C,
+ HasUnresolvedUsing, Base, BaseType,
+ IsArrow, OperatorLoc, Qualifier, QualifierRange,
+ MemberNameInfo, TemplateArgs, Begin, End);
+}
+
+UnresolvedMemberExpr *
+UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+ unsigned NumTemplateArgs) {
+ std::size_t size = sizeof(UnresolvedMemberExpr);
+ if (HasExplicitTemplateArgs)
+ size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
+
+ void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
+ UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
+ E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
+ return E;
+}
+
+CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
+ // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.
+
+ // If there was a nested name specifier, it names the naming class.
+ // It can't be dependent: after all, we were actually able to do the
+ // lookup.
+ CXXRecordDecl *Record = 0;
+ if (getQualifier()) {
+ 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");
+ }
+ // Otherwise the naming class must have been the base class.
+ else {
+ QualType BaseType = getBaseType().getNonReferenceType();
+ if (isArrow()) {
+ const PointerType *PT = BaseType->getAs<PointerType>();
+ assert(PT && "base of arrow member access is not pointer");
+ BaseType = PT->getPointeeType();
+ }
+
+ Record = BaseType->getAsCXXRecordDecl();
+ assert(Record && "base of member expression does not name record");
+ }
+
+ return Record;
+}
+
+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) { }
+
+TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
+ return TemplateArgument(Arguments, NumArguments);
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
new file mode 100644
index 0000000..890898a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -0,0 +1,591 @@
+//===--- ExprClassification.cpp - Expression AST Node Implementation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Expr::classify.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+using namespace clang;
+
+typedef Expr::Classification Cl;
+
+static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E);
+static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D);
+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 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.");
+
+ Cl::Kinds kind = ClassifyInternal(Ctx, this);
+ // C99 6.3.2.1: An lvalue is an expression with an object type or an
+ // incomplete type other than void.
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // Thus, no functions.
+ if (TR->isFunctionType() || TR == Ctx.OverloadTy)
+ kind = Cl::CL_Function;
+ // No void either, but qualified void is OK because it is "other than void".
+ else if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
+ 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);
+ return Classification(kind, modifiable);
+}
+
+static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
+ // This function takes the first stab at classifying expressions.
+ const LangOptions &Lang = Ctx.getLangOptions();
+
+ 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:
+ // @encode is equivalent to its string
+ case Expr::ObjCEncodeExprClass:
+ // __func__ and friends are too.
+ case Expr::PredefinedExprClass:
+ // Property references are lvalues
+ case Expr::ObjCPropertyRefExprClass:
+ // 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.
+ // In C++, they're class temporaries.
+ case Expr::CompoundLiteralExprClass:
+ 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.
+
+ // C++ [expr.sub]p1: The result is an lvalue of type "T".
+ // However, subscripting vector types is more like member access.
+ case Expr::ArraySubscriptExprClass:
+ if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
+ return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
+ return Cl::CL_LValue;
+
+ // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
+ // function or variable and a prvalue otherwise.
+ case Expr::DeclRefExprClass:
+ return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl());
+ // We deal with names referenced from blocks the same way.
+ case Expr::BlockDeclRefExprClass:
+ return ClassifyDecl(Ctx, cast<BlockDeclRefExpr>(E)->getDecl());
+
+ // Member access is complex.
+ case Expr::MemberExprClass:
+ return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E));
+
+ case Expr::UnaryOperatorClass:
+ switch (cast<UnaryOperator>(E)->getOpcode()) {
+ // C++ [expr.unary.op]p1: The unary * operator performs indirection:
+ // [...] the result is an lvalue referring to the object or function
+ // to which the expression points.
+ case UO_Deref:
+ return Cl::CL_LValue;
+
+ // GNU extensions, simply look through them.
+ case UO_Extension:
+ return ClassifyInternal(Ctx, cast<UnaryOperator>(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<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ Cl::Kinds K = ClassifyInternal(Ctx, Op);
+ if (K != Cl::CL_LValue) return K;
+
+ if (isa<ObjCPropertyRefExpr>(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.
+ case UO_PreInc:
+ case UO_PreDec:
+ return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
+
+ default:
+ return Cl::CL_PRValue;
+ }
+
+ case Expr::OpaqueValueExprClass:
+ return ClassifyExprValueKind(Lang, E,
+ cast<OpaqueValueExpr>(E)->getValueKind());
+
+ // Implicit casts are lvalues if they're lvalue casts. Other than that, we
+ // only specifically record class temporaries.
+ case Expr::ImplicitCastExprClass:
+ return ClassifyExprValueKind(Lang, E,
+ cast<ImplicitCastExpr>(E)->getValueKind());
+
+ // C++ [expr.prim.general]p4: The presence of parentheses does not affect
+ // whether the expression is an lvalue.
+ case Expr::ParenExprClass:
+ return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr());
+
+ case Expr::BinaryOperatorClass:
+ case Expr::CompoundAssignOperatorClass:
+ // C doesn't have any binary expressions that are lvalues.
+ if (Lang.CPlusPlus)
+ return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E));
+ return Cl::CL_PRValue;
+
+ case Expr::CallExprClass:
+ case Expr::CXXOperatorCallExprClass:
+ case Expr::CXXMemberCallExprClass:
+ case Expr::CUDAKernelCallExprClass:
+ return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType());
+
+ // __builtin_choose_expr is equivalent to the chosen expression.
+ case Expr::ChooseExprClass:
+ return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr(Ctx));
+
+ // Extended vector element access is an lvalue unless there are duplicates
+ // in the shuffle expression.
+ case Expr::ExtVectorElementExprClass:
+ return cast<ExtVectorElementExpr>(E)->containsDuplicateElements() ?
+ Cl::CL_DuplicateVectorComponents : Cl::CL_LValue;
+
+ // Simply look at the actual default argument.
+ case Expr::CXXDefaultArgExprClass:
+ return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr());
+
+ // Same idea for temporary binding.
+ case Expr::CXXBindTemporaryExprClass:
+ return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr());
+
+ // And the cleanups guard.
+ case Expr::ExprWithCleanupsClass:
+ return ClassifyInternal(Ctx, cast<ExprWithCleanups>(E)->getSubExpr());
+
+ // Casts depend completely on the target type. All casts work the same.
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXDynamicCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass:
+ // Only in C++ can casts be interesting at all.
+ if (!Lang.CPlusPlus) return Cl::CL_PRValue;
+ return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
+
+ case Expr::BinaryConditionalOperatorClass: {
+ if (!Lang.CPlusPlus) return Cl::CL_PRValue;
+ const BinaryConditionalOperator *co = cast<BinaryConditionalOperator>(E);
+ return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
+ }
+
+ case Expr::ConditionalOperatorClass: {
+ // Once again, only C++ is interesting.
+ if (!Lang.CPlusPlus) return Cl::CL_PRValue;
+ const ConditionalOperator *co = cast<ConditionalOperator>(E);
+ return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
+ }
+
+ // ObjC message sends are effectively function calls, if the target function
+ // is known.
+ case Expr::ObjCMessageExprClass:
+ if (const ObjCMethodDecl *Method =
+ cast<ObjCMessageExpr>(E)->getMethodDecl()) {
+ return ClassifyUnnamed(Ctx, Method->getResultType());
+ }
+ return Cl::CL_PRValue;
+
+ // Some C++ expressions are always class temporaries.
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXTemporaryObjectExprClass:
+ return Cl::CL_ClassTemporary;
+
+ case Expr::VAArgExprClass:
+ return ClassifyUnnamed(Ctx, E->getType());
+
+ case Expr::DesignatedInitExprClass:
+ return ClassifyInternal(Ctx, cast<DesignatedInitExpr>(E)->getInit());
+
+ case Expr::StmtExprClass: {
+ const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt();
+ if (const Expr *LastExpr = dyn_cast_or_null<Expr>(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<PackExpansionExpr>(E)->getPattern());
+ }
+
+ llvm_unreachable("unhandled expression kind in classification");
+ return Cl::CL_LValue;
+}
+
+/// ClassifyDecl - Return the classification of an expression referencing the
+/// given declaration.
+static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
+ // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
+ // function, variable, or data member and a prvalue otherwise.
+ // In C, functions are not lvalues.
+ // In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
+ // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
+ // special-case this.
+
+ if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ return Cl::CL_MemberFunction;
+
+ bool islvalue;
+ if (const NonTypeTemplateParmDecl *NTTParm =
+ dyn_cast<NonTypeTemplateParmDecl>(D))
+ islvalue = NTTParm->getType()->isReferenceType();
+ else
+ islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
+ isa<IndirectFieldDecl>(D) ||
+ (Ctx.getLangOptions().CPlusPlus &&
+ (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)));
+
+ return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
+}
+
+/// ClassifyUnnamed - Return the classification of an expression yielding an
+/// unnamed value of the given type. This applies in particular to function
+/// calls and casts.
+static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
+ // In C, function calls are always rvalues.
+ if (!Ctx.getLangOptions().CPlusPlus) return Cl::CL_PRValue;
+
+ // C++ [expr.call]p10: A function call is an lvalue if the result type is an
+ // lvalue reference type or an rvalue reference to function type, an xvalue
+ // if the result type is an rvalue refernence to object type, and a prvalue
+ // otherwise.
+ if (T->isLValueReferenceType())
+ return Cl::CL_LValue;
+ const RValueReferenceType *RV = T->getAs<RValueReferenceType>();
+ if (!RV) // Could still be a class temporary, though.
+ return T->isRecordType() ? Cl::CL_ClassTemporary : Cl::CL_PRValue;
+
+ return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue;
+}
+
+static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
+ // Handle C first, it's easier.
+ if (!Ctx.getLangOptions().CPlusPlus) {
+ // C99 6.5.2.3p3
+ // For dot access, the expression is an lvalue if the first part is. For
+ // arrow access, it always is an lvalue.
+ if (E->isArrow())
+ return Cl::CL_LValue;
+ // ObjC property accesses are not lvalues, but get special treatment.
+ Expr *Base = E->getBase()->IgnoreParens();
+ if (isa<ObjCPropertyRefExpr>(Base))
+ return Cl::CL_SubObjCPropertySetting;
+ return ClassifyInternal(Ctx, Base);
+ }
+
+ NamedDecl *Member = E->getMemberDecl();
+ // C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2.
+ // C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then
+ // E1.E2 is an lvalue.
+ if (ValueDecl *Value = dyn_cast<ValueDecl>(Member))
+ if (Value->getType()->isReferenceType())
+ return Cl::CL_LValue;
+
+ // Otherwise, one of the following rules applies.
+ // -- If E2 is a static member [...] then E1.E2 is an lvalue.
+ if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
+ return Cl::CL_LValue;
+
+ // -- If E2 is a non-static data member [...]. If E1 is an lvalue, then
+ // E1.E2 is an lvalue; if E1 is an xvalue, then E1.E2 is an xvalue;
+ // otherwise, it is a prvalue.
+ if (isa<FieldDecl>(Member)) {
+ // *E1 is an lvalue
+ if (E->isArrow())
+ return Cl::CL_LValue;
+ Expr *Base = E->getBase()->IgnoreParenImpCasts();
+ if (isa<ObjCPropertyRefExpr>(Base))
+ return Cl::CL_SubObjCPropertySetting;
+ return ClassifyInternal(Ctx, E->getBase());
+ }
+
+ // -- If E2 is a [...] member function, [...]
+ // -- If it refers to a static member function [...], then E1.E2 is an
+ // lvalue; [...]
+ // -- Otherwise [...] E1.E2 is a prvalue.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member))
+ return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction;
+
+ // -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue.
+ // So is everything else we haven't handled yet.
+ return Cl::CL_PRValue;
+}
+
+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 (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, [...].
+ if (E->getOpcode() == BO_Comma)
+ return ClassifyInternal(Ctx, E->getRHS());
+
+ // C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand
+ // is a pointer to a data member is of the same value category as its first
+ // operand.
+ if (E->getOpcode() == BO_PtrMemD)
+ return E->getType()->isFunctionType() ? Cl::CL_MemberFunction :
+ ClassifyInternal(Ctx, E->getLHS());
+
+ // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
+ // second operand is a pointer to data member and a prvalue otherwise.
+ if (E->getOpcode() == BO_PtrMemI)
+ return E->getType()->isFunctionType() ?
+ Cl::CL_MemberFunction : Cl::CL_LValue;
+
+ // All other binary operations are prvalues.
+ return Cl::CL_PRValue;
+}
+
+static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True,
+ const Expr *False) {
+ assert(Ctx.getLangOptions().CPlusPlus &&
+ "This is only relevant for C++.");
+
+ // C++ [expr.cond]p2
+ // If either the second or the third operand has type (cv) void, [...]
+ // the result [...] is a prvalue.
+ if (True->getType()->isVoidType() || False->getType()->isVoidType())
+ return Cl::CL_PRValue;
+
+ // Note that at this point, we have already performed all conversions
+ // according to [expr.cond]p3.
+ // C++ [expr.cond]p4: If the second and third operands are glvalues of the
+ // same value category [...], the result is of that [...] value category.
+ // C++ [expr.cond]p5: Otherwise, the result is a prvalue.
+ Cl::Kinds LCl = ClassifyInternal(Ctx, True),
+ RCl = ClassifyInternal(Ctx, False);
+ return LCl == RCl ? LCl : Cl::CL_PRValue;
+}
+
+static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
+ Cl::Kinds Kind, SourceLocation &Loc) {
+ // As a general rule, we only care about lvalues. But there are some rvalues
+ // for which we want to generate special results.
+ 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 ExplicitCastExpr *CE =
+ dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
+ if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) {
+ Loc = CE->getExprLoc();
+ return Cl::CM_LValueCast;
+ }
+ }
+ }
+ if (Kind != Cl::CL_LValue)
+ return Cl::CM_RValue;
+
+ // This is the lvalue case.
+ // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
+ if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType())
+ return Cl::CM_Function;
+
+ // You cannot assign to a variable outside a block from within the block if
+ // it is not marked __block, e.g.
+ // void takeclosure(void (^C)(void));
+ // void func() { int x = 1; takeclosure(^{ x = 7; }); }
+ if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) {
+ if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
+ return Cl::CM_NotBlockQualified;
+ }
+
+ // Assignment to a property in ObjC is an implicit setter access. But a
+ // setter might not exist.
+ if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0)
+ return Cl::CM_NoSetterProperty;
+ }
+
+ CanQualType CT = Ctx.getCanonicalType(E->getType());
+ // Const stuff is obviously not modifiable.
+ if (CT.isConstQualified())
+ return Cl::CM_ConstQualified;
+ // Arrays are not modifiable, only their elements are.
+ if (CT->isArrayType())
+ return Cl::CM_ArrayType;
+ // Incomplete types are not modifiable.
+ if (CT->isIncompleteType())
+ return Cl::CM_IncompleteType;
+
+ // Records with any const fields (recursively) are not modifiable.
+ if (const RecordType *R = CT->getAs<RecordType>()) {
+ assert((E->getObjectKind() == OK_ObjCProperty ||
+ !Ctx.getLangOptions().CPlusPlus) &&
+ "C++ struct assignment should be resolved by the "
+ "copy assignment operator.");
+ if (R->hasConstFields())
+ return Cl::CM_ConstQualified;
+ }
+
+ return Cl::CM_Modifiable;
+}
+
+Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const {
+ Classification VC = Classify(Ctx);
+ switch (VC.getKind()) {
+ case Cl::CL_LValue: return LV_Valid;
+ case Cl::CL_XValue: return LV_InvalidExpression;
+ case Cl::CL_Function: return LV_NotObjectType;
+ case Cl::CL_Void: return LV_IncompleteVoidType;
+ case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents;
+ case Cl::CL_MemberFunction: return LV_MemberFunction;
+ case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
+ case Cl::CL_ClassTemporary: return LV_ClassTemporary;
+ case Cl::CL_PRValue: return LV_InvalidExpression;
+ }
+ llvm_unreachable("Unhandled kind");
+}
+
+Expr::isModifiableLvalueResult
+Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
+ SourceLocation dummy;
+ Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy);
+ switch (VC.getKind()) {
+ case Cl::CL_LValue: break;
+ case Cl::CL_XValue: return MLV_InvalidExpression;
+ case Cl::CL_Function: return MLV_NotObjectType;
+ case Cl::CL_Void: return MLV_IncompleteVoidType;
+ case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
+ case Cl::CL_MemberFunction: return MLV_MemberFunction;
+ case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
+ case Cl::CL_ClassTemporary: return MLV_ClassTemporary;
+ case Cl::CL_PRValue:
+ return VC.getModifiable() == Cl::CM_LValueCast ?
+ MLV_LValueCast : MLV_InvalidExpression;
+ }
+ assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
+ switch (VC.getModifiable()) {
+ case Cl::CM_Untested: llvm_unreachable("Did not test modifiability");
+ case Cl::CM_Modifiable: return MLV_Valid;
+ case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match");
+ case Cl::CM_Function: return MLV_NotObjectType;
+ case Cl::CM_LValueCast:
+ llvm_unreachable("CM_LValueCast and CL_LValue don't match");
+ case Cl::CM_NotBlockQualified: return MLV_NotBlockQualified;
+ case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
+ case Cl::CM_ConstQualified: return MLV_ConstQualified;
+ case Cl::CM_ArrayType: return MLV_ArrayType;
+ case Cl::CM_IncompleteType: return MLV_IncompleteType;
+ }
+ llvm_unreachable("Unhandled modifiable type");
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
new file mode 100644
index 0000000..656bb99
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -0,0 +1,3061 @@
+//===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expr constant evaluator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallString.h"
+#include <cstring>
+
+using namespace clang;
+using llvm::APSInt;
+using llvm::APFloat;
+
+/// EvalInfo - This is a private struct used by the evaluator to capture
+/// information about a subexpression as it is folded. It retains information
+/// about the AST context, but also maintains information about the folded
+/// expression.
+///
+/// If an expression could be evaluated, it is still possible it is not a C
+/// "integer constant expression" or constant expression. If not, this struct
+/// captures information about how and why not.
+///
+/// One bit of information passed *into* the request for constant folding
+/// indicates whether the subexpression is "evaluated" or not according to C
+/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
+/// evaluate the expression regardless of what the RHS is, but C only allows
+/// certain things in certain situations.
+struct EvalInfo {
+ const ASTContext &Ctx;
+
+ /// EvalResult - Contains information about the evaluation.
+ Expr::EvalResult &EvalResult;
+
+ llvm::DenseMap<const OpaqueValueExpr*, APValue> OpaqueValues;
+ const APValue *getOpaqueValue(const OpaqueValueExpr *e) {
+ llvm::DenseMap<const OpaqueValueExpr*, APValue>::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) {}
+};
+
+namespace {
+ struct ComplexValue {
+ private:
+ bool IsInt;
+
+ public:
+ APSInt IntReal, IntImag;
+ APFloat FloatReal, FloatImag;
+
+ ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {}
+
+ void makeComplexFloat() { IsInt = false; }
+ bool isComplexFloat() const { return !IsInt; }
+ APFloat &getComplexFloatReal() { return FloatReal; }
+ APFloat &getComplexFloatImag() { return FloatImag; }
+
+ void makeComplexInt() { IsInt = true; }
+ bool isComplexInt() const { return IsInt; }
+ APSInt &getComplexIntReal() { return IntReal; }
+ APSInt &getComplexIntImag() { return IntImag; }
+
+ 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 {
+ Expr *Base;
+ CharUnits Offset;
+
+ Expr *getLValueBase() { return Base; }
+ CharUnits getLValueOffset() { return Offset; }
+
+ 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);
+static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
+ EvalInfo &Info);
+static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
+static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info);
+
+//===----------------------------------------------------------------------===//
+// Misc utilities
+//===----------------------------------------------------------------------===//
+
+static bool IsGlobalLValue(const Expr* E) {
+ if (!E) return true;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (isa<FunctionDecl>(DRE->getDecl()))
+ return true;
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ return VD->hasGlobalStorage();
+ return false;
+ }
+
+ if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(E))
+ return CLE->isFileScope();
+
+ return true;
+}
+
+static bool EvalPointerValueAsBool(LValue& Value, bool& Result) {
+ const Expr* Base = Value.Base;
+
+ // A null base expression indicates a null pointer. These are always
+ // evaluatable, and they are false unless the offset is zero.
+ if (!Base) {
+ Result = !Value.Offset.isZero();
+ return true;
+ }
+
+ // Require the base expression to be a global l-value.
+ if (!IsGlobalLValue(Base)) return false;
+
+ // We have a non-null base expression. These are generally known to
+ // be true, but if it'a decl-ref to a weak symbol it can be null at
+ // runtime.
+ Result = true;
+
+ const DeclRefExpr* DeclRef = dyn_cast<DeclRefExpr>(Base);
+ if (!DeclRef)
+ return true;
+
+ // If it's a weak symbol, it isn't constant-evaluable.
+ const ValueDecl* Decl = DeclRef->getDecl();
+ if (Decl->hasAttr<WeakAttr>() ||
+ Decl->hasAttr<WeakRefAttr>() ||
+ Decl->hasAttr<WeakImportAttr>())
+ return false;
+
+ return true;
+}
+
+static bool HandleConversionToBool(const Expr* E, bool& Result,
+ EvalInfo &Info) {
+ if (E->getType()->isIntegralOrEnumerationType()) {
+ APSInt IntResult;
+ if (!EvaluateInteger(E, IntResult, Info))
+ return false;
+ Result = IntResult != 0;
+ return true;
+ } else if (E->getType()->isRealFloatingType()) {
+ APFloat FloatResult(0.0);
+ if (!EvaluateFloat(E, FloatResult, Info))
+ return false;
+ Result = !FloatResult.isZero();
+ return true;
+ } else if (E->getType()->hasPointerRepresentation()) {
+ LValue PointerResult;
+ if (!EvaluatePointer(E, PointerResult, Info))
+ return false;
+ return EvalPointerValueAsBool(PointerResult, Result);
+ } else if (E->getType()->isAnyComplexType()) {
+ ComplexValue ComplexResult;
+ if (!EvaluateComplex(E, ComplexResult, Info))
+ return false;
+ if (ComplexResult.isComplexFloat()) {
+ Result = !ComplexResult.getComplexFloatReal().isZero() ||
+ !ComplexResult.getComplexFloatImag().isZero();
+ } else {
+ Result = ComplexResult.getComplexIntReal().getBoolValue() ||
+ ComplexResult.getComplexIntImag().getBoolValue();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType,
+ APFloat &Value, const ASTContext &Ctx) {
+ unsigned DestWidth = Ctx.getIntWidth(DestType);
+ // Determine whether we are converting to unsigned or signed.
+ bool DestSigned = DestType->isSignedIntegerType();
+
+ // FIXME: Warning for overflow.
+ uint64_t Space[4];
+ bool ignored;
+ (void)Value.convertToInteger(Space, DestWidth, DestSigned,
+ llvm::APFloat::rmTowardZero, &ignored);
+ return APSInt(llvm::APInt(DestWidth, 4, Space), !DestSigned);
+}
+
+static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType,
+ APFloat &Value, const ASTContext &Ctx) {
+ bool ignored;
+ APFloat Result = Value;
+ Result.convert(Ctx.getFloatTypeSemantics(DestType),
+ APFloat::rmNearestTiesToEven, &ignored);
+ return Result;
+}
+
+static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType,
+ 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 = Result.extOrTrunc(DestWidth);
+ Result.setIsUnsigned(DestType->isUnsignedIntegerType());
+ return Result;
+}
+
+static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
+ APSInt &Value, const ASTContext &Ctx) {
+
+ APFloat Result(Ctx.getFloatTypeSemantics(DestType), 1);
+ Result.convertFromAPInt(Value, Value.isSigned(),
+ APFloat::rmNearestTiesToEven);
+ return Result;
+}
+
+namespace {
+class HasSideEffect
+ : public StmtVisitor<HasSideEffect, bool> {
+ EvalInfo &Info;
+public:
+
+ HasSideEffect(EvalInfo &info) : Info(info) {}
+
+ // Unhandled nodes conservatively default to having side effects.
+ bool VisitStmt(Stmt *S) {
+ return true;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return false;
+ }
+ // We don't want to evaluate BlockExprs multiple times, as they generate
+ // a ton of code.
+ bool VisitBlockExpr(BlockExpr *E) { return true; }
+ bool VisitPredefinedExpr(PredefinedExpr *E) { return false; }
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
+ { return Visit(E->getInitializer()); }
+ bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); }
+ bool VisitIntegerLiteral(IntegerLiteral *E) { return false; }
+ bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
+ bool VisitStringLiteral(StringLiteral *E) { return false; }
+ bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
+ bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
+ { return Visit(E->getLHS()) || Visit(E->getRHS()); }
+ bool VisitChooseExpr(ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitBinAssign(BinaryOperator *E) { return true; }
+ bool VisitCompoundAssignOperator(BinaryOperator *E) { return true; }
+ bool VisitBinaryOperator(BinaryOperator *E)
+ { return Visit(E->getLHS()) || Visit(E->getRHS()); }
+ bool VisitUnaryPreInc(UnaryOperator *E) { return true; }
+ bool VisitUnaryPostInc(UnaryOperator *E) { return true; }
+ bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
+ bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
+ bool VisitUnaryDeref(UnaryOperator *E) {
+ if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+ return true;
+ return Visit(E->getSubExpr());
+ }
+ bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+
+ // Has side effects if any element does.
+ bool VisitInitListExpr(InitListExpr *E) {
+ for (unsigned i = 0, e = E->getNumInits(); i != e; ++i)
+ 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
+
+//===----------------------------------------------------------------------===//
+// LValue Evaluation
+//===----------------------------------------------------------------------===//
+namespace {
+class LValueExprEvaluator
+ : public StmtVisitor<LValueExprEvaluator, bool> {
+ EvalInfo &Info;
+ LValue &Result;
+
+ bool Success(Expr *E) {
+ Result.Base = E;
+ Result.Offset = CharUnits::Zero();
+ return true;
+ }
+public:
+
+ LValueExprEvaluator(EvalInfo &info, LValue &Result) :
+ Info(info), Result(Result) {}
+
+ bool VisitStmt(Stmt *S) {
+ return false;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitDeclRefExpr(DeclRefExpr *E);
+ bool VisitPredefinedExpr(PredefinedExpr *E) { return Success(E); }
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ bool VisitMemberExpr(MemberExpr *E);
+ bool VisitStringLiteral(StringLiteral *E) { return Success(E); }
+ bool VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return Success(E); }
+ bool VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+ bool VisitUnaryDeref(UnaryOperator *E);
+ bool VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ bool VisitChooseExpr(const ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+
+ bool VisitCastExpr(CastExpr *E) {
+ switch (E->getCastKind()) {
+ default:
+ return false;
+
+ case CK_NoOp:
+ return Visit(E->getSubExpr());
+ }
+ }
+ // FIXME: Missing: __real__, __imag__
+};
+} // end anonymous namespace
+
+static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) {
+ return LValueExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
+ if (isa<FunctionDecl>(E->getDecl())) {
+ return Success(E);
+ } else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (!VD->getType()->isReferenceType())
+ return Success(E);
+ // Reference parameters can refer to anything even if they have an
+ // "initializer" in the form of a default argument.
+ if (isa<ParmVarDecl>(VD))
+ return false;
+ // FIXME: Check whether VD might be overridden!
+ if (const Expr *Init = VD->getAnyInitializer())
+ return Visit(const_cast<Expr *>(Init));
+ }
+
+ return false;
+}
+
+bool LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ return Success(E);
+}
+
+bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
+ QualType Ty;
+ if (E->isArrow()) {
+ if (!EvaluatePointer(E->getBase(), Result, Info))
+ return false;
+ Ty = E->getBase()->getType()->getAs<PointerType>()->getPointeeType();
+ } else {
+ if (!Visit(E->getBase()))
+ return false;
+ Ty = E->getBase()->getType();
+ }
+
+ RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
+
+ FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
+ if (!FD) // FIXME: deal with other kinds of member expressions
+ return false;
+
+ if (FD->getType()->isReferenceType())
+ return false;
+
+ // FIXME: This is linear time.
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == FD)
+ break;
+ }
+
+ Result.Offset += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i));
+ return true;
+}
+
+bool LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ if (!EvaluatePointer(E->getBase(), Result, Info))
+ return false;
+
+ APSInt Index;
+ if (!EvaluateInteger(E->getIdx(), Index, Info))
+ return false;
+
+ CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType());
+ Result.Offset += Index.getSExtValue() * ElementSize;
+ return true;
+}
+
+bool LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) {
+ return EvaluatePointer(E->getSubExpr(), Result, Info);
+}
+
+//===----------------------------------------------------------------------===//
+// Pointer Evaluation
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PointerExprEvaluator
+ : public StmtVisitor<PointerExprEvaluator, bool> {
+ EvalInfo &Info;
+ LValue &Result;
+
+ bool Success(Expr *E) {
+ Result.Base = E;
+ Result.Offset = CharUnits::Zero();
+ return true;
+ }
+public:
+
+ PointerExprEvaluator(EvalInfo &info, LValue &Result)
+ : Info(info), Result(Result) {}
+
+ bool VisitStmt(Stmt *S) {
+ return false;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ bool VisitCastExpr(CastExpr* E);
+ bool VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ bool VisitUnaryAddrOf(const UnaryOperator *E);
+ bool VisitObjCStringLiteral(ObjCStringLiteral *E)
+ { return Success(E); }
+ bool VisitAddrLabelExpr(AddrLabelExpr *E)
+ { return Success(E); }
+ bool VisitCallExpr(CallExpr *E);
+ bool VisitBlockExpr(BlockExpr *E) {
+ 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
+
+static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) {
+ assert(E->getType()->hasPointerRepresentation());
+ return PointerExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ if (E->getOpcode() != BO_Add &&
+ E->getOpcode() != BO_Sub)
+ return false;
+
+ const Expr *PExp = E->getLHS();
+ const Expr *IExp = E->getRHS();
+ if (IExp->getType()->isPointerType())
+ std::swap(PExp, IExp);
+
+ if (!EvaluatePointer(PExp, Result, Info))
+ return false;
+
+ llvm::APSInt Offset;
+ if (!EvaluateInteger(IExp, Offset, Info))
+ return false;
+ int64_t AdditionalOffset
+ = Offset.isSigned() ? Offset.getSExtValue()
+ : static_cast<int64_t>(Offset.getZExtValue());
+
+ // Compute the new offset in the appropriate width.
+
+ QualType PointeeType =
+ PExp->getType()->getAs<PointerType>()->getPointeeType();
+ CharUnits SizeOfPointee;
+
+ // Explicitly handle GNU void* and function pointer arithmetic extensions.
+ if (PointeeType->isVoidType() || PointeeType->isFunctionType())
+ SizeOfPointee = CharUnits::One();
+ else
+ SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
+
+ if (E->getOpcode() == BO_Add)
+ Result.Offset += AdditionalOffset * SizeOfPointee;
+ else
+ Result.Offset -= AdditionalOffset * SizeOfPointee;
+
+ return true;
+}
+
+bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
+ return EvaluateLValue(E->getSubExpr(), Result, Info);
+}
+
+
+bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
+ Expr* SubExpr = E->getSubExpr();
+
+ switch (E->getCastKind()) {
+ default:
+ break;
+
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_AnyPointerToObjCPointerCast:
+ 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<PointerType>()->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() = Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
+ Result.Base = 0;
+ Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue());
+ return true;
+ } else {
+ // Cast is of an lvalue, no need to change value.
+ Result.Base = Value.getLValueBase();
+ Result.Offset = Value.getLValueOffset();
+ return true;
+ }
+ }
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ return EvaluateLValue(SubExpr, Result, Info);
+ }
+
+ return false;
+}
+
+bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
+ if (E->isBuiltinCall(Info.Ctx) ==
+ Builtin::BI__builtin___CFStringMakeConstantString ||
+ E->isBuiltinCall(Info.Ctx) ==
+ Builtin::BI__builtin___NSStringMakeConstantString)
+ return Success(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))
+ return false;
+
+ Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
+ return Visit(EvalExpr);
+}
+
+//===----------------------------------------------------------------------===//
+// Vector Evaluation
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class VectorExprEvaluator
+ : public StmtVisitor<VectorExprEvaluator, APValue> {
+ EvalInfo &Info;
+ APValue GetZeroVector(QualType VecType);
+ public:
+
+ VectorExprEvaluator(EvalInfo &info) : Info(info) {}
+
+ APValue VisitStmt(Stmt *S) {
+ return APValue();
+ }
+
+ APValue VisitParenExpr(ParenExpr *E)
+ { return Visit(E->getSubExpr()); }
+ APValue VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ APValue VisitUnaryPlus(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ APValue VisitUnaryReal(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
+ { return GetZeroVector(E->getType()); }
+ APValue VisitCastExpr(const CastExpr* E);
+ APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
+ APValue VisitInitListExpr(const InitListExpr *E);
+ APValue VisitConditionalOperator(const ConditionalOperator *E);
+ APValue VisitChooseExpr(const ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ APValue VisitUnaryImag(const UnaryOperator *E);
+ // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
+ // binary comparisons, binary and/or/xor,
+ // shufflevector, ExtVectorElementExpr
+ // (Note that these require implementing conversions
+ // between vector types.)
+ };
+} // end anonymous namespace
+
+static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
+ if (!E->getType()->isVectorType())
+ return false;
+ Result = VectorExprEvaluator(Info).Visit(const_cast<Expr*>(E));
+ return !Result.isUninit();
+}
+
+APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
+ const VectorType *VTy = E->getType()->getAs<VectorType>();
+ QualType EltTy = VTy->getElementType();
+ unsigned NElts = VTy->getNumElements();
+ unsigned EltWidth = Info.Ctx.getTypeSize(EltTy);
+
+ const Expr* SE = E->getSubExpr();
+ QualType SETy = SE->getType();
+ APValue Result = APValue();
+
+ // Check for vector->vector bitcast and scalar->vector splat.
+ if (SETy->isVectorType()) {
+ return this->Visit(const_cast<Expr*>(SE));
+ } else if (SETy->isIntegerType()) {
+ APSInt IntResult;
+ if (!EvaluateInteger(SE, IntResult, Info))
+ return APValue();
+ Result = APValue(IntResult);
+ } else if (SETy->isRealFloatingType()) {
+ APFloat F(0.0);
+ if (!EvaluateFloat(SE, F, Info))
+ return APValue();
+ Result = APValue(F);
+ } else
+ return APValue();
+
+ // For casts of a scalar to ExtVector, convert the scalar to the element type
+ // and splat it to all elements.
+ if (E->getType()->isExtVectorType()) {
+ if (EltTy->isIntegerType() && Result.isInt())
+ Result = APValue(HandleIntToIntCast(EltTy, SETy, Result.getInt(),
+ Info.Ctx));
+ else if (EltTy->isIntegerType())
+ Result = APValue(HandleFloatToIntCast(EltTy, SETy, Result.getFloat(),
+ Info.Ctx));
+ else if (EltTy->isRealFloatingType() && Result.isInt())
+ Result = APValue(HandleIntToFloatCast(EltTy, SETy, Result.getInt(),
+ Info.Ctx));
+ else if (EltTy->isRealFloatingType())
+ Result = APValue(HandleFloatToFloatCast(EltTy, SETy, Result.getFloat(),
+ Info.Ctx));
+ else
+ return APValue();
+
+ // Splat and create vector APValue.
+ llvm::SmallVector<APValue, 4> Elts(NElts, Result);
+ return APValue(&Elts[0], Elts.size());
+ }
+
+ // For casts of a scalar to regular gcc-style vector type, bitcast the scalar
+ // to the vector. To construct the APValue vector initializer, bitcast the
+ // initializing value to an APInt, and shift out the bits pertaining to each
+ // element.
+ APSInt Init;
+ Init = Result.isInt() ? Result.getInt() : Result.getFloat().bitcastToAPInt();
+
+ llvm::SmallVector<APValue, 4> Elts;
+ for (unsigned i = 0; i != NElts; ++i) {
+ APSInt Tmp = Init.extOrTrunc(EltWidth);
+
+ if (EltTy->isIntegerType())
+ Elts.push_back(APValue(Tmp));
+ else if (EltTy->isRealFloatingType())
+ Elts.push_back(APValue(APFloat(Tmp)));
+ else
+ return APValue();
+
+ Init >>= EltWidth;
+ }
+ return APValue(&Elts[0], Elts.size());
+}
+
+APValue
+VectorExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+ return this->Visit(const_cast<Expr*>(E->getInitializer()));
+}
+
+APValue
+VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
+ const VectorType *VT = E->getType()->getAs<VectorType>();
+ unsigned NumInits = E->getNumInits();
+ unsigned NumElements = VT->getNumElements();
+
+ QualType EltTy = VT->getElementType();
+ llvm::SmallVector<APValue, 4> Elements;
+
+ // If a vector is initialized with a single element, that value
+ // becomes every element of the vector, not just the first.
+ // This is the behavior described in the IBM AltiVec documentation.
+ if (NumInits == 1) {
+ APValue InitValue;
+ if (EltTy->isIntegerType()) {
+ llvm::APSInt sInt(32);
+ if (!EvaluateInteger(E->getInit(0), sInt, Info))
+ return APValue();
+ InitValue = APValue(sInt);
+ } else {
+ llvm::APFloat f(0.0);
+ if (!EvaluateFloat(E->getInit(0), f, Info))
+ return APValue();
+ InitValue = APValue(f);
+ }
+ for (unsigned i = 0; i < NumElements; i++) {
+ Elements.push_back(InitValue);
+ }
+ } else {
+ for (unsigned i = 0; i < NumElements; i++) {
+ if (EltTy->isIntegerType()) {
+ llvm::APSInt sInt(32);
+ if (i < NumInits) {
+ if (!EvaluateInteger(E->getInit(i), sInt, Info))
+ return APValue();
+ } else {
+ sInt = Info.Ctx.MakeIntValue(0, EltTy);
+ }
+ Elements.push_back(APValue(sInt));
+ } else {
+ llvm::APFloat f(0.0);
+ if (i < NumInits) {
+ if (!EvaluateFloat(E->getInit(i), f, Info))
+ return APValue();
+ } else {
+ f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy));
+ }
+ Elements.push_back(APValue(f));
+ }
+ }
+ }
+ return APValue(&Elements[0], Elements.size());
+}
+
+APValue
+VectorExprEvaluator::GetZeroVector(QualType T) {
+ const VectorType *VT = T->getAs<VectorType>();
+ QualType EltTy = VT->getElementType();
+ APValue ZeroElement;
+ if (EltTy->isIntegerType())
+ ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy));
+ else
+ ZeroElement =
+ APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)));
+
+ llvm::SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement);
+ return APValue(&Elements[0], Elements.size());
+}
+
+APValue VectorExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) {
+ bool BoolResult;
+ if (!HandleConversionToBool(E->getCond(), BoolResult, Info))
+ return APValue();
+
+ Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr();
+
+ APValue Result;
+ if (EvaluateVector(EvalExpr, Result, Info))
+ return Result;
+ return APValue();
+}
+
+APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
+ if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+ return GetZeroVector(E->getType());
+}
+
+//===----------------------------------------------------------------------===//
+// Integer Evaluation
+//===----------------------------------------------------------------------===//
+
+namespace {
+class IntExprEvaluator
+ : public StmtVisitor<IntExprEvaluator, bool> {
+ EvalInfo &Info;
+ APValue &Result;
+public:
+ IntExprEvaluator(EvalInfo &info, APValue &result)
+ : Info(info), Result(result) {}
+
+ bool Success(const llvm::APSInt &SI, const Expr *E) {
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
+ assert(SI.isSigned() == E->getType()->isSignedIntegerType() &&
+ "Invalid evaluation result.");
+ assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+ "Invalid evaluation result.");
+ Result = APValue(SI);
+ return true;
+ }
+
+ bool Success(const llvm::APInt &I, const Expr *E) {
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
+ assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+ "Invalid evaluation result.");
+ Result = APValue(APSInt(I));
+ Result.getInt().setIsUnsigned(E->getType()->isUnsignedIntegerType());
+ return true;
+ }
+
+ bool Success(uint64_t Value, const Expr *E) {
+ assert(E->getType()->isIntegralOrEnumerationType() &&
+ "Invalid evaluation result.");
+ Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
+ return true;
+ }
+
+ bool Error(SourceLocation L, diag::kind D, const Expr *E) {
+ // Take the first error.
+ if (Info.EvalResult.Diag == 0) {
+ Info.EvalResult.DiagLoc = L;
+ Info.EvalResult.Diag = D;
+ Info.EvalResult.DiagExpr = E;
+ }
+ return false;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ bool VisitStmt(Stmt *) {
+ assert(0 && "This should be called on integers, stmts are not integers");
+ return false;
+ }
+
+ bool VisitExpr(Expr *E) {
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+
+ bool VisitIntegerLiteral(const IntegerLiteral *E) {
+ return Success(E->getValue(), E);
+ }
+ bool VisitCharacterLiteral(const CharacterLiteral *E) {
+ return Success(E->getValue(), 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);
+ bool VisitDeclRefExpr(const DeclRefExpr *E) {
+ return CheckReferencedDecl(E, E->getDecl());
+ }
+ bool VisitMemberExpr(const MemberExpr *E) {
+ if (CheckReferencedDecl(E, E->getMemberDecl())) {
+ // Conservatively assume a MemberExpr will have side-effects
+ Info.EvalResult.HasSideEffects = true;
+ return true;
+ }
+ return false;
+ }
+
+ bool VisitCallExpr(CallExpr *E);
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ 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);
+
+ bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
+ return Success(E->getValue(), E);
+ }
+
+ bool VisitGNUNullExpr(const GNUNullExpr *E) {
+ return Success(0, E);
+ }
+
+ bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
+ return Success(0, E);
+ }
+
+ bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
+ return Success(0, E);
+ }
+
+ bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
+ return Success(E->getValue(), E);
+ }
+
+ bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+ return Success(E->getValue(), E);
+ }
+
+ bool VisitChooseExpr(const ChooseExpr *E) {
+ return Visit(E->getChosenSubExpr(Info.Ctx));
+ }
+
+ 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);
+ static QualType GetObjectType(const Expr *E);
+ bool TryEvaluateBuiltinObjectSize(CallExpr *E);
+ // FIXME: Missing: array subscript of vector, member of vector
+};
+} // end anonymous namespace
+
+static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) {
+ assert(E->getType()->isIntegralOrEnumerationType());
+ return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
+ assert(E->getType()->isIntegralOrEnumerationType());
+
+ APValue Val;
+ if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt())
+ return false;
+ Result = Val.getInt();
+ return true;
+}
+
+bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
+ // Enums are integer constant exprs.
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+ return Success(ECD->getInitVal(), E);
+
+ // In C++, const, non-volatile integers initialized with ICEs are ICEs.
+ // In C, they can also be folded, although they are not ICEs.
+ if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers()
+ == Qualifiers::Const) {
+
+ if (isa<ParmVarDecl>(D))
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const Expr *Init = VD->getAnyInitializer()) {
+ if (APValue *V = VD->getEvaluatedValue()) {
+ if (V->isInt())
+ return Success(V->getInt(), E);
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+ }
+
+ if (VD->isEvaluatingValue())
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+ VD->setEvaluatingValue();
+
+ Expr::EvalResult EResult;
+ if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects &&
+ EResult.Val.isInt()) {
+ // Cache the evaluated value in the variable declaration.
+ Result = EResult.Val;
+ VD->setEvaluatedValue(Result);
+ return true;
+ }
+
+ VD->setEvaluatedValue(APValue());
+ }
+ }
+ }
+
+ // Otherwise, random variable references are not constants.
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+}
+
+/// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
+/// as GCC.
+static int EvaluateBuiltinClassifyType(const CallExpr *E) {
+ // The following enum mimics the values returned by GCC.
+ // FIXME: Does GCC differ between lvalue and rvalue references here?
+ enum gcc_type_class {
+ no_type_class = -1,
+ void_type_class, integer_type_class, char_type_class,
+ enumeral_type_class, boolean_type_class,
+ pointer_type_class, reference_type_class, offset_type_class,
+ real_type_class, complex_type_class,
+ function_type_class, method_type_class,
+ record_type_class, union_type_class,
+ array_type_class, string_type_class,
+ lang_type_class
+ };
+
+ // If no argument was supplied, default to "no_type_class". This isn't
+ // ideal, however it is what gcc does.
+ if (E->getNumArgs() == 0)
+ return no_type_class;
+
+ QualType ArgTy = E->getArg(0)->getType();
+ if (ArgTy->isVoidType())
+ return void_type_class;
+ else if (ArgTy->isEnumeralType())
+ return enumeral_type_class;
+ else if (ArgTy->isBooleanType())
+ return boolean_type_class;
+ else if (ArgTy->isCharType())
+ return string_type_class; // gcc doesn't appear to use char_type_class
+ else if (ArgTy->isIntegerType())
+ return integer_type_class;
+ else if (ArgTy->isPointerType())
+ return pointer_type_class;
+ else if (ArgTy->isReferenceType())
+ return reference_type_class;
+ else if (ArgTy->isRealType())
+ return real_type_class;
+ else if (ArgTy->isComplexType())
+ return complex_type_class;
+ else if (ArgTy->isFunctionType())
+ return function_type_class;
+ else if (ArgTy->isStructureOrClassType())
+ return record_type_class;
+ else if (ArgTy->isUnionType())
+ return union_type_class;
+ else if (ArgTy->isArrayType())
+ return array_type_class;
+ else if (ArgTy->isUnionType())
+ return union_type_class;
+ else // FIXME: offset_type_class, method_type_class, & lang_type_class?
+ assert(0 && "CallExpr::isBuiltinClassifyType(): unimplemented type");
+ return -1;
+}
+
+/// Retrieves the "underlying object type" of the given expression,
+/// as used by __builtin_object_size.
+QualType IntExprEvaluator::GetObjectType(const Expr *E) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ return VD->getType();
+ } else if (isa<CompoundLiteralExpr>(E)) {
+ return E->getType();
+ }
+
+ return QualType();
+}
+
+bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) {
+ // TODO: Perhaps we should let LLVM lower this?
+ LValue Base;
+ if (!EvaluatePointer(E->getArg(0), Base, Info))
+ return false;
+
+ // If we can prove the base is null, lower to zero now.
+ const Expr *LVBase = Base.getLValueBase();
+ if (!LVBase) return Success(0, E);
+
+ QualType T = GetObjectType(LVBase);
+ if (T.isNull() ||
+ T->isIncompleteType() ||
+ T->isFunctionType() ||
+ T->isVariablyModifiedType() ||
+ T->isDependentType())
+ return false;
+
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(T);
+ CharUnits Offset = Base.getLValueOffset();
+
+ if (!Offset.isNegative() && Offset <= Size)
+ Size -= Offset;
+ else
+ Size = CharUnits::Zero();
+ return Success(Size.getQuantity(), E);
+}
+
+bool IntExprEvaluator::VisitCallExpr(CallExpr *E) {
+ switch (E->isBuiltinCall(Info.Ctx)) {
+ default:
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+ case Builtin::BI__builtin_object_size: {
+ if (TryEvaluateBuiltinObjectSize(E))
+ return true;
+
+ // If evaluating the argument has side-effects we can't determine
+ // the size of the object and lower it to unknown now.
+ if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
+ if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
+ return Success(-1ULL, E);
+ return Success(0, E);
+ }
+
+ return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+ }
+
+ case Builtin::BI__builtin_classify_type:
+ return Success(EvaluateBuiltinClassifyType(E), E);
+
+ case Builtin::BI__builtin_constant_p:
+ // __builtin_constant_p always has one operand: it returns true if that
+ // operand can be folded, false otherwise.
+ return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E);
+
+ case Builtin::BI__builtin_eh_return_data_regno: {
+ int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue();
+ Operand = Info.Ctx.Target.getEHDataRegisterNumber(Operand);
+ return Success(Operand, 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<StringLiteral>(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);
+ }
+}
+
+bool IntExprEvaluator::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 (E->isLogicalOp()) {
+ // These need to be handled specially because the operands aren't
+ // necessarily integral
+ bool lhsResult, rhsResult;
+
+ if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) {
+ // We were able to evaluate the LHS, see if we can get away with not
+ // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
+ if (lhsResult == (E->getOpcode() == BO_LOr))
+ return Success(lhsResult, E);
+
+ if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
+ if (E->getOpcode() == BO_LOr)
+ return Success(lhsResult || rhsResult, E);
+ else
+ return Success(lhsResult && rhsResult, E);
+ }
+ } else {
+ if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
+ // We can't evaluate the LHS; however, sometimes the result
+ // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
+ if (rhsResult == (E->getOpcode() == BO_LOr) ||
+ !rhsResult == (E->getOpcode() == BO_LAnd)) {
+ // Since we weren't able to evaluate the left hand side, it
+ // must have had side effects.
+ Info.EvalResult.HasSideEffects = true;
+
+ return Success(rhsResult, E);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ QualType LHSTy = E->getLHS()->getType();
+ QualType RHSTy = E->getRHS()->getType();
+
+ if (LHSTy->isAnyComplexType()) {
+ assert(RHSTy->isAnyComplexType() && "Invalid comparison");
+ ComplexValue LHS, RHS;
+
+ if (!EvaluateComplex(E->getLHS(), LHS, Info))
+ return false;
+
+ if (!EvaluateComplex(E->getRHS(), RHS, Info))
+ return false;
+
+ if (LHS.isComplexFloat()) {
+ APFloat::cmpResult CR_r =
+ LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal());
+ APFloat::cmpResult CR_i =
+ LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag());
+
+ if (E->getOpcode() == BO_EQ)
+ return Success((CR_r == APFloat::cmpEqual &&
+ CR_i == APFloat::cmpEqual), E);
+ else {
+ assert(E->getOpcode() == BO_NE &&
+ "Invalid complex comparison.");
+ return Success(((CR_r == APFloat::cmpGreaterThan ||
+ CR_r == APFloat::cmpLessThan ||
+ CR_r == APFloat::cmpUnordered) ||
+ (CR_i == APFloat::cmpGreaterThan ||
+ CR_i == APFloat::cmpLessThan ||
+ CR_i == APFloat::cmpUnordered)), E);
+ }
+ } else {
+ if (E->getOpcode() == BO_EQ)
+ return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
+ LHS.getComplexIntImag() == RHS.getComplexIntImag()), E);
+ else {
+ assert(E->getOpcode() == BO_NE &&
+ "Invalid compex comparison.");
+ return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() ||
+ LHS.getComplexIntImag() != RHS.getComplexIntImag()), E);
+ }
+ }
+ }
+
+ if (LHSTy->isRealFloatingType() &&
+ RHSTy->isRealFloatingType()) {
+ APFloat RHS(0.0), LHS(0.0);
+
+ if (!EvaluateFloat(E->getRHS(), RHS, Info))
+ return false;
+
+ if (!EvaluateFloat(E->getLHS(), LHS, Info))
+ return false;
+
+ APFloat::cmpResult CR = LHS.compare(RHS);
+
+ switch (E->getOpcode()) {
+ default:
+ assert(0 && "Invalid binary operator!");
+ case BO_LT:
+ return Success(CR == APFloat::cmpLessThan, E);
+ case BO_GT:
+ return Success(CR == APFloat::cmpGreaterThan, E);
+ case BO_LE:
+ return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E);
+ case BO_GE:
+ return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual,
+ E);
+ case BO_EQ:
+ return Success(CR == APFloat::cmpEqual, E);
+ case BO_NE:
+ return Success(CR == APFloat::cmpGreaterThan
+ || CR == APFloat::cmpLessThan
+ || CR == APFloat::cmpUnordered, E);
+ }
+ }
+
+ if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
+ if (E->getOpcode() == BO_Sub || E->isEqualityOp()) {
+ LValue LHSValue;
+ if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
+ return false;
+
+ LValue RHSValue;
+ if (!EvaluatePointer(E->getRHS(), RHSValue, Info))
+ return false;
+
+ // Reject any bases from the normal codepath; we special-case comparisons
+ // to null.
+ if (LHSValue.getLValueBase()) {
+ if (!E->isEqualityOp())
+ return false;
+ if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero())
+ return false;
+ bool bres;
+ if (!EvalPointerValueAsBool(LHSValue, bres))
+ return false;
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
+ } else if (RHSValue.getLValueBase()) {
+ if (!E->isEqualityOp())
+ return false;
+ if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())
+ return false;
+ bool bres;
+ if (!EvalPointerValueAsBool(RHSValue, bres))
+ return false;
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
+ }
+
+ if (E->getOpcode() == BO_Sub) {
+ QualType Type = E->getLHS()->getType();
+ QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
+
+ CharUnits ElementSize = CharUnits::One();
+ if (!ElementType->isVoidType() && !ElementType->isFunctionType())
+ ElementSize = Info.Ctx.getTypeSizeInChars(ElementType);
+
+ CharUnits Diff = LHSValue.getLValueOffset() -
+ RHSValue.getLValueOffset();
+ return Success(Diff / ElementSize, E);
+ }
+ bool Result;
+ if (E->getOpcode() == BO_EQ) {
+ Result = LHSValue.getLValueOffset() == RHSValue.getLValueOffset();
+ } else {
+ Result = LHSValue.getLValueOffset() != RHSValue.getLValueOffset();
+ }
+ return Success(Result, E);
+ }
+ }
+ if (!LHSTy->isIntegralOrEnumerationType() ||
+ !RHSTy->isIntegralOrEnumerationType()) {
+ // We can't continue from here for non-integral types, and they
+ // could potentially confuse the following operations.
+ return false;
+ }
+
+ // The LHS of a constant expr is always evaluated and needed.
+ if (!Visit(E->getLHS()))
+ return false; // error in subexpression.
+
+ APValue RHSVal;
+ if (!EvaluateIntegerOrLValue(E->getRHS(), RHSVal, Info))
+ return false;
+
+ // Handle cases like (unsigned long)&a + 4.
+ if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
+ CharUnits Offset = Result.getLValueOffset();
+ CharUnits AdditionalOffset = CharUnits::fromQuantity(
+ RHSVal.getInt().getZExtValue());
+ if (E->getOpcode() == BO_Add)
+ Offset += AdditionalOffset;
+ else
+ Offset -= AdditionalOffset;
+ Result = APValue(Result.getLValueBase(), Offset);
+ return true;
+ }
+
+ // Handle cases like 4 + (unsigned long)&a
+ if (E->getOpcode() == BO_Add &&
+ RHSVal.isLValue() && Result.isInt()) {
+ CharUnits Offset = RHSVal.getLValueOffset();
+ Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
+ Result = APValue(RHSVal.getLValueBase(), Offset);
+ return true;
+ }
+
+ // All the following cases expect both operands to be an integer
+ if (!Result.isInt() || !RHSVal.isInt())
+ return false;
+
+ APSInt& RHS = RHSVal.getInt();
+
+ switch (E->getOpcode()) {
+ default:
+ return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
+ case BO_Mul: return Success(Result.getInt() * RHS, E);
+ case BO_Add: return Success(Result.getInt() + RHS, E);
+ case BO_Sub: return Success(Result.getInt() - RHS, E);
+ case BO_And: return Success(Result.getInt() & RHS, E);
+ case BO_Xor: return Success(Result.getInt() ^ RHS, E);
+ case BO_Or: return Success(Result.getInt() | RHS, E);
+ case BO_Div:
+ if (RHS == 0)
+ return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
+ return Success(Result.getInt() / RHS, E);
+ case BO_Rem:
+ if (RHS == 0)
+ return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
+ return Success(Result.getInt() % RHS, E);
+ case BO_Shl: {
+ // 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);
+ }
+
+ case BO_LT: return Success(Result.getInt() < RHS, E);
+ case BO_GT: return Success(Result.getInt() > RHS, E);
+ case BO_LE: return Success(Result.getInt() <= RHS, E);
+ case BO_GE: return Success(Result.getInt() >= RHS, E);
+ case BO_EQ: return Success(Result.getInt() == RHS, E);
+ case BO_NE: return Success(Result.getInt() != RHS, E);
+ }
+}
+
+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))
+ return false;
+
+ return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr());
+}
+
+CharUnits IntExprEvaluator::GetAlignOfType(QualType T) {
+ // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+ // the result is the size of the referenced type."
+ // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+ // result shall be the alignment of the referenced type."
+ if (const ReferenceType *Ref = T->getAs<ReferenceType>())
+ T = Ref->getPointeeType();
+
+ // __alignof is defined to return the preferred alignment.
+ return Info.Ctx.toCharUnitsFromBits(
+ Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
+}
+
+CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
+ E = E->IgnoreParens();
+
+ // alignof decl is always accepted, even if it doesn't make sense: we default
+ // to 1 in those cases.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return Info.Ctx.getDeclAlign(DRE->getDecl(),
+ /*RefAsPointee*/true);
+
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
+ /*RefAsPointee*/true);
+
+ return GetAlignOfType(E->getType());
+}
+
+
+/// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
+/// expression's type.
+bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
+ // Handle alignof separately.
+ if (!E->isSizeOf()) {
+ if (E->isArgumentType())
+ return Success(GetAlignOfType(E->getArgumentType()).getQuantity(), E);
+ else
+ return Success(GetAlignOfExpr(E->getArgumentExpr()).getQuantity(), E);
+ }
+
+ QualType SrcTy = E->getTypeOfArgument();
+ // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+ // the result is the size of the referenced type."
+ // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+ // result shall be the alignment of the referenced type."
+ if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>())
+ SrcTy = Ref->getPointeeType();
+
+ // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc
+ // extension.
+ if (SrcTy->isVoidType() || SrcTy->isFunctionType())
+ return Success(1, E);
+
+ // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
+ if (!SrcTy->isConstantSizeType())
+ return false;
+
+ // Get information about the size.
+ return Success(Info.Ctx.getTypeSizeInChars(SrcTy).getQuantity(), E);
+}
+
+bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) {
+ CharUnits Result;
+ unsigned n = E->getNumComponents();
+ OffsetOfExpr* OOE = const_cast<OffsetOfExpr*>(E);
+ if (n == 0)
+ return false;
+ QualType CurrentType = E->getTypeSourceInfo()->getType();
+ for (unsigned i = 0; i != n; ++i) {
+ OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i);
+ switch (ON.getKind()) {
+ case OffsetOfExpr::OffsetOfNode::Array: {
+ Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex());
+ APSInt IdxResult;
+ if (!EvaluateInteger(Idx, IdxResult, Info))
+ return false;
+ const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType);
+ if (!AT)
+ return false;
+ CurrentType = AT->getElementType();
+ CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType);
+ Result += IdxResult.getSExtValue() * ElementSize;
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Field: {
+ FieldDecl *MemberDecl = ON.getField();
+ const RecordType *RT = CurrentType->getAs<RecordType>();
+ if (!RT)
+ return false;
+ RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
+ unsigned i = MemberDecl->getFieldIndex();
+ assert(i < RL.getFieldCount() && "offsetof field in wrong type");
+ Result += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i));
+ CurrentType = MemberDecl->getType().getNonReferenceType();
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Identifier:
+ llvm_unreachable("dependent __builtin_offsetof");
+ return false;
+
+ case OffsetOfExpr::OffsetOfNode::Base: {
+ CXXBaseSpecifier *BaseSpec = ON.getBase();
+ if (BaseSpec->isVirtual())
+ return false;
+
+ // Find the layout of the class whose base we are looking into.
+ const RecordType *RT = CurrentType->getAs<RecordType>();
+ if (!RT)
+ return false;
+ RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD);
+
+ // Find the base class itself.
+ CurrentType = BaseSpec->getType();
+ const RecordType *BaseRT = CurrentType->getAs<RecordType>();
+ if (!BaseRT)
+ return false;
+
+ // Add the offset to the base.
+ Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
+ break;
+ }
+ }
+ }
+ return Success(Result.getQuantity(), E);
+}
+
+bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+ if (E->getOpcode() == UO_LNot) {
+ // LNot's operand isn't necessarily an integer, so we handle it specially.
+ bool bres;
+ if (!HandleConversionToBool(E->getSubExpr(), bres, Info))
+ return false;
+ return Success(!bres, E);
+ }
+
+ // Only handle integral operations...
+ if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType())
+ return false;
+
+ // Get the operand value into 'Result'.
+ if (!Visit(E->getSubExpr()))
+ return false;
+
+ switch (E->getOpcode()) {
+ default:
+ // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
+ // See C99 6.6p3.
+ return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
+ case UO_Extension:
+ // FIXME: Should extension allow i-c-e extension expressions in its scope?
+ // If so, we could clear the diagnostic ID.
+ return true;
+ case UO_Plus:
+ // The result is always just the subexpr.
+ return true;
+ case UO_Minus:
+ if (!Result.isInt()) return false;
+ return Success(-Result.getInt(), E);
+ case UO_Not:
+ if (!Result.isInt()) return false;
+ return Success(~Result.getInt(), E);
+ }
+}
+
+/// HandleCast - This is used to evaluate implicit or explicit casts where the
+/// result type is integer.
+bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
+ Expr *SubExpr = E->getSubExpr();
+ QualType DestType = E->getType();
+ QualType SrcType = SubExpr->getType();
+
+ if (DestType->isBooleanType()) {
+ bool BoolResult;
+ if (!HandleConversionToBool(SubExpr, BoolResult, Info))
+ return false;
+ return Success(BoolResult, E);
+ }
+
+ // Handle simple integer->integer casts.
+ if (SrcType->isIntegralOrEnumerationType()) {
+ if (!Visit(SubExpr))
+ return false;
+
+ if (!Result.isInt()) {
+ // Only allow casts of lvalues if they are lossless.
+ return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
+ }
+
+ return Success(HandleIntToIntCast(DestType, SrcType,
+ Result.getInt(), Info.Ctx), E);
+ }
+
+ // FIXME: Clean this up!
+ if (SrcType->isPointerType()) {
+ LValue LV;
+ if (!EvaluatePointer(SubExpr, LV, Info))
+ return false;
+
+ if (LV.getLValueBase()) {
+ // Only allow based lvalue casts if they are lossless.
+ if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType))
+ return false;
+
+ LV.moveInto(Result);
+ return true;
+ }
+
+ APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
+ SrcType);
+ return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
+ }
+
+ if (SrcType->isArrayType() || SrcType->isFunctionType()) {
+ // This handles double-conversion cases, where there's both
+ // an l-value promotion and an implicit conversion to int.
+ LValue LV;
+ if (!EvaluateLValue(SubExpr, LV, Info))
+ return false;
+
+ if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(Info.Ctx.VoidPtrTy))
+ return false;
+
+ LV.moveInto(Result);
+ return true;
+ }
+
+ if (SrcType->isAnyComplexType()) {
+ ComplexValue C;
+ if (!EvaluateComplex(SubExpr, C, Info))
+ return false;
+ if (C.isComplexFloat())
+ return Success(HandleFloatToIntCast(DestType, SrcType,
+ C.getComplexFloatReal(), Info.Ctx),
+ E);
+ else
+ return Success(HandleIntToIntCast(DestType, SrcType,
+ C.getComplexIntReal(), Info.Ctx), E);
+ }
+ // FIXME: Handle vectors
+
+ if (!SrcType->isRealFloatingType())
+ return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+
+ APFloat F(0.0);
+ if (!EvaluateFloat(SubExpr, F, Info))
+ return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+
+ return Success(HandleFloatToIntCast(DestType, SrcType, F, Info.Ctx), E);
+}
+
+bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue LV;
+ if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
+ return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+ return Success(LV.getComplexIntReal(), E);
+ }
+
+ return Visit(E->getSubExpr());
+}
+
+bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
+ if (E->getSubExpr()->getType()->isComplexIntegerType()) {
+ ComplexValue LV;
+ if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt())
+ return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E);
+ return Success(LV.getComplexIntImag(), E);
+ }
+
+ if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+ 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
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FloatExprEvaluator
+ : public StmtVisitor<FloatExprEvaluator, bool> {
+ EvalInfo &Info;
+ APFloat &Result;
+public:
+ FloatExprEvaluator(EvalInfo &info, APFloat &result)
+ : Info(info), Result(result) {}
+
+ bool VisitStmt(Stmt *S) {
+ return false;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+ bool VisitCallExpr(const CallExpr *E);
+
+ bool VisitUnaryOperator(const UnaryOperator *E);
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ bool VisitFloatingLiteral(const FloatingLiteral *E);
+ 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)); }
+ bool VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ 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
+};
+} // end anonymous namespace
+
+static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) {
+ assert(E->getType()->isRealFloatingType());
+ return FloatExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+static bool TryEvaluateBuiltinNaN(const ASTContext &Context,
+ QualType ResultTy,
+ const Expr *Arg,
+ bool SNaN,
+ llvm::APFloat &Result) {
+ const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
+ if (!S) return false;
+
+ const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy);
+
+ llvm::APInt fill;
+
+ // Treat empty strings as if they were zero.
+ if (S->getString().empty())
+ fill = llvm::APInt(32, 0);
+ else if (S->getString().getAsInteger(0, fill))
+ return false;
+
+ if (SNaN)
+ Result = llvm::APFloat::getSNaN(Sem, false, &fill);
+ else
+ Result = llvm::APFloat::getQNaN(Sem, false, &fill);
+ return true;
+}
+
+bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
+ switch (E->isBuiltinCall(Info.Ctx)) {
+ default: return false;
+ case Builtin::BI__builtin_huge_val:
+ case Builtin::BI__builtin_huge_valf:
+ case Builtin::BI__builtin_huge_vall:
+ case Builtin::BI__builtin_inf:
+ case Builtin::BI__builtin_inff:
+ case Builtin::BI__builtin_infl: {
+ const llvm::fltSemantics &Sem =
+ Info.Ctx.getFloatTypeSemantics(E->getType());
+ Result = llvm::APFloat::getInf(Sem);
+ return true;
+ }
+
+ case Builtin::BI__builtin_nans:
+ case Builtin::BI__builtin_nansf:
+ case Builtin::BI__builtin_nansl:
+ return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
+ true, Result);
+
+ case Builtin::BI__builtin_nan:
+ case Builtin::BI__builtin_nanf:
+ case Builtin::BI__builtin_nanl:
+ // If this is __builtin_nan() turn this into a nan, otherwise we
+ // can't constant fold it.
+ return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0),
+ false, Result);
+
+ case Builtin::BI__builtin_fabs:
+ case Builtin::BI__builtin_fabsf:
+ case Builtin::BI__builtin_fabsl:
+ if (!EvaluateFloat(E->getArg(0), Result, Info))
+ return false;
+
+ if (Result.isNegative())
+ Result.changeSign();
+ return true;
+
+ case Builtin::BI__builtin_copysign:
+ case Builtin::BI__builtin_copysignf:
+ case Builtin::BI__builtin_copysignl: {
+ APFloat RHS(0.);
+ if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info))
+ return false;
+ Result.copySign(RHS);
+ return true;
+ }
+ }
+}
+
+bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
+ const Decl *D = E->getDecl();
+ if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D)) return false;
+ const VarDecl *VD = cast<VarDecl>(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;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatReal;
+ return true;
+ }
+
+ return Visit(E->getSubExpr());
+}
+
+bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue CV;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatImag;
+ return true;
+ }
+
+ if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+ const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType());
+ Result = llvm::APFloat::getZero(Sem);
+ return true;
+}
+
+bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+ if (E->getOpcode() == UO_Deref)
+ return false;
+
+ if (!EvaluateFloat(E->getSubExpr(), Result, Info))
+ return false;
+
+ switch (E->getOpcode()) {
+ default: return false;
+ case UO_Plus:
+ return true;
+ case UO_Minus:
+ Result.changeSign();
+ return true;
+ }
+}
+
+bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ if (E->getOpcode() == BO_Comma) {
+ if (!EvaluateFloat(E->getRHS(), Result, Info))
+ return false;
+
+ // If we can't evaluate the LHS, it might have side effects;
+ // conservatively mark it.
+ if (!E->getLHS()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+
+ return true;
+ }
+
+ // 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);
+ if (!EvaluateFloat(E->getLHS(), Result, Info))
+ return false;
+ if (!EvaluateFloat(E->getRHS(), RHS, Info))
+ return false;
+
+ switch (E->getOpcode()) {
+ default: return false;
+ case BO_Mul:
+ Result.multiply(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BO_Add:
+ Result.add(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BO_Sub:
+ Result.subtract(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ case BO_Div:
+ Result.divide(RHS, APFloat::rmNearestTiesToEven);
+ return true;
+ }
+}
+
+bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) {
+ Result = E->getValue();
+ return true;
+}
+
+bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {
+ Expr* SubExpr = E->getSubExpr();
+
+ if (SubExpr->getType()->isIntegralOrEnumerationType()) {
+ APSInt IntResult;
+ if (!EvaluateInteger(SubExpr, IntResult, Info))
+ return false;
+ Result = HandleIntToFloatCast(E->getType(), SubExpr->getType(),
+ IntResult, Info.Ctx);
+ return true;
+ }
+ if (SubExpr->getType()->isRealFloatingType()) {
+ if (!Visit(SubExpr))
+ return false;
+ Result = HandleFloatToFloatCast(E->getType(), SubExpr->getType(),
+ Result, Info.Ctx);
+ return true;
+ }
+
+ if (E->getCastKind() == CK_FloatingComplexToReal) {
+ ComplexValue V;
+ if (!EvaluateComplex(SubExpr, V, Info))
+ return false;
+ Result = V.getComplexFloatReal();
+ return true;
+ }
+
+ return false;
+}
+
+bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
+ 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))
+ return false;
+
+ return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr());
+}
+
+//===----------------------------------------------------------------------===//
+// Complex Evaluation (for float and integer)
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ComplexExprEvaluator
+ : public StmtVisitor<ComplexExprEvaluator, bool> {
+ EvalInfo &Info;
+ ComplexValue &Result;
+
+public:
+ ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result)
+ : Info(info), Result(Result) {}
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ bool VisitStmt(Stmt *S) {
+ return false;
+ }
+
+ bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+
+ bool VisitImaginaryLiteral(ImaginaryLiteral *E);
+
+ 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()); }
+ 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
+
+static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
+ EvalInfo &Info) {
+ assert(E->getType()->isAnyComplexType());
+ return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ Expr* SubExpr = E->getSubExpr();
+
+ if (SubExpr->getType()->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ APFloat &Imag = Result.FloatImag;
+ if (!EvaluateFloat(SubExpr, Imag, Info))
+ return false;
+
+ Result.FloatReal = APFloat(Imag.getSemantics());
+ return true;
+ } else {
+ assert(SubExpr->getType()->isIntegerType() &&
+ "Unexpected imaginary literal.");
+
+ Result.makeComplexInt();
+ APSInt &Imag = Result.IntImag;
+ if (!EvaluateInteger(SubExpr, Imag, Info))
+ return false;
+
+ Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned());
+ return true;
+ }
+}
+
+bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) {
+
+ 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(E->getSubExpr(), Real, Info))
+ return false;
+
+ Result.makeComplexFloat();
+ Result.FloatImag = APFloat(Real.getSemantics());
+ return true;
+ }
+
+ case CK_FloatingComplexCast: {
+ if (!Visit(E->getSubExpr()))
+ return false;
+
+ QualType To = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType From
+ = E->getSubExpr()->getType()->getAs<ComplexType>()->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<ComplexType>()->getElementType();
+ QualType From
+ = E->getSubExpr()->getType()->getAs<ComplexType>()->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(E->getSubExpr(), Real, Info))
+ return false;
+
+ Result.makeComplexInt();
+ Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned());
+ return true;
+ }
+
+ case CK_IntegralComplexCast: {
+ if (!Visit(E->getSubExpr()))
+ return false;
+
+ QualType To = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType From
+ = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType();
+
+ 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<ComplexType>()->getElementType();
+ QualType From
+ = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType();
+ Result.makeComplexFloat();
+ Result.FloatReal = HandleIntToFloatCast(To, From, Result.IntReal, Info.Ctx);
+ Result.FloatImag = HandleIntToFloatCast(To, From, Result.IntImag, Info.Ctx);
+ return true;
+ }
+ }
+
+ 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;
+
+ ComplexValue RHS;
+ if (!EvaluateComplex(E->getRHS(), RHS, Info))
+ return false;
+
+ assert(Result.isComplexFloat() == RHS.isComplexFloat() &&
+ "Invalid operands to binary operator.");
+ switch (E->getOpcode()) {
+ default: return false;
+ case BO_Add:
+ if (Result.isComplexFloat()) {
+ Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
+ APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
+ } else {
+ Result.getComplexIntReal() += RHS.getComplexIntReal();
+ Result.getComplexIntImag() += RHS.getComplexIntImag();
+ }
+ break;
+ case BO_Sub:
+ if (Result.isComplexFloat()) {
+ Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
+ APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
+ } else {
+ Result.getComplexIntReal() -= RHS.getComplexIntReal();
+ Result.getComplexIntImag() -= RHS.getComplexIntImag();
+ }
+ break;
+ case BO_Mul:
+ 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 Tmp = LHS_r;
+ Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatReal() = Tmp;
+ Tmp = LHS_i;
+ Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven);
+
+ Tmp = LHS_r;
+ Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag() = Tmp;
+ Tmp = LHS_i;
+ Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven);
+ } else {
+ ComplexValue LHS = Result;
+ Result.getComplexIntReal() =
+ (LHS.getComplexIntReal() * RHS.getComplexIntReal() -
+ LHS.getComplexIntImag() * RHS.getComplexIntImag());
+ Result.getComplexIntImag() =
+ (LHS.getComplexIntReal() * RHS.getComplexIntImag() +
+ 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.
+//===----------------------------------------------------------------------===//
+
+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<Expr*>(E)))
+ return false;
+ if (Info.EvalResult.Val.isLValue() &&
+ !IsGlobalLValue(Info.EvalResult.Val.getLValueBase()))
+ return false;
+ } else if (E->getType()->hasPointerRepresentation()) {
+ LValue LV;
+ if (!EvaluatePointer(E, LV, Info))
+ return false;
+ if (!IsGlobalLValue(LV.Base))
+ return false;
+ LV.moveInto(Info.EvalResult.Val);
+ } else if (E->getType()->isRealFloatingType()) {
+ llvm::APFloat F(0.0);
+ if (!EvaluateFloat(E, F, Info))
+ return false;
+
+ Info.EvalResult.Val = APValue(F);
+ } else if (E->getType()->isAnyComplexType()) {
+ ComplexValue C;
+ if (!EvaluateComplex(E, C, Info))
+ return false;
+ C.moveInto(Info.EvalResult.Val);
+ } else
+ return false;
+
+ return true;
+}
+
+/// 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, const ASTContext &Ctx) const {
+ EvalInfo Info(Ctx, Result);
+
+ LValue LV;
+ if (EvaluateLValue(this, LV, Info) &&
+ !Result.HasSideEffects &&
+ IsGlobalLValue(LV.Base)) {
+ LV.moveInto(Result.Val);
+ return true;
+ }
+ return false;
+}
+
+bool Expr::EvaluateAsAnyLValue(EvalResult &Result,
+ const ASTContext &Ctx) const {
+ EvalInfo Info(Ctx, Result);
+
+ LValue LV;
+ if (EvaluateLValue(this, LV, Info)) {
+ LV.moveInto(Result.Val);
+ return true;
+ }
+ return false;
+}
+
+/// isEvaluatable - Call Evaluate to see if this expression can be constant
+/// folded, but discard the result.
+bool Expr::isEvaluatable(const ASTContext &Ctx) const {
+ EvalResult Result;
+ return Evaluate(Result, Ctx) && !Result.HasSideEffects;
+}
+
+bool Expr::HasSideEffects(const ASTContext &Ctx) const {
+ Expr::EvalResult Result;
+ EvalInfo Info(Ctx, Result);
+ return HasSideEffect(Info).Visit(const_cast<Expr*>(this));
+}
+
+APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const {
+ EvalResult EvalResult;
+ bool Result = Evaluate(EvalResult, Ctx);
+ (void)Result;
+ assert(Result && "Could not evaluate expression");
+ assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer");
+
+ return EvalResult.Val.getInt();
+}
+
+ bool Expr::EvalResult::isGlobalLValue() const {
+ assert(Val.isLValue());
+ return IsGlobalLValue(Val.getLValueBase());
+ }
+
+
+/// isIntegerConstantExpr - this recursive routine will test if an expression is
+/// an integer constant expression.
+
+/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero,
+/// comma, etc
+///
+/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof
+/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer
+/// cast+dereference.
+
+// CheckICE - This function does the fundamental ICE checking: the returned
+// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation.
+// Note that to reduce code duplication, this helper does no evaluation
+// itself; the caller checks whether the expression is evaluatable, and
+// in the rare cases where CheckICE actually cares about the evaluated
+// value, it calls into Evalute.
+//
+// Meanings of Val:
+// 0: This expression is an ICE if it can be evaluated by Evaluate.
+// 1: This expression is not an ICE, but if it isn't evaluated, it's
+// a legal subexpression for an ICE. This return value is used to handle
+// the comma operator in C99 mode.
+// 2: This expression is not an ICE, and is not a legal subexpression for one.
+
+namespace {
+
+struct ICEDiag {
+ unsigned Val;
+ SourceLocation Loc;
+
+ public:
+ ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {}
+ ICEDiag() : Val(0) {}
+};
+
+}
+
+static ICEDiag NoDiag() { return ICEDiag(); }
+
+static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
+ Expr::EvalResult EVResult;
+ if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects ||
+ !EVResult.Val.isInt()) {
+ return ICEDiag(2, E->getLocStart());
+ }
+ return NoDiag();
+}
+
+static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
+ assert(!E->isValueDependent() && "Should not see value dependent exprs!");
+ if (!E->getType()->isIntegralOrEnumerationType()) {
+ return ICEDiag(2, E->getLocStart());
+ }
+
+ switch (E->getStmtClass()) {
+#define ABSTRACT_STMT(Node)
+#define STMT(Node, Base) case Expr::Node##Class:
+#define EXPR(Node, Base)
+#include "clang/AST/StmtNodes.inc"
+ case Expr::PredefinedExprClass:
+ case Expr::FloatingLiteralClass:
+ case Expr::ImaginaryLiteralClass:
+ case Expr::StringLiteralClass:
+ case Expr::ArraySubscriptExprClass:
+ case Expr::MemberExprClass:
+ case Expr::CompoundAssignOperatorClass:
+ case Expr::CompoundLiteralExprClass:
+ case Expr::ExtVectorElementExprClass:
+ case Expr::InitListExprClass:
+ case Expr::DesignatedInitExprClass:
+ case Expr::ImplicitValueInitExprClass:
+ case Expr::ParenListExprClass:
+ case Expr::VAArgExprClass:
+ 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:
+ case Expr::CXXNewExprClass:
+ case Expr::CXXDeleteExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::UnresolvedLookupExprClass:
+ case Expr::DependentScopeDeclRefExprClass:
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXBindTemporaryExprClass:
+ case Expr::ExprWithCleanupsClass:
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXUnresolvedConstructExprClass:
+ case Expr::CXXDependentScopeMemberExprClass:
+ case Expr::UnresolvedMemberExprClass:
+ case Expr::ObjCStringLiteralClass:
+ case Expr::ObjCEncodeExprClass:
+ case Expr::ObjCMessageExprClass:
+ case Expr::ObjCSelectorExprClass:
+ case Expr::ObjCProtocolExprClass:
+ case Expr::ObjCIvarRefExprClass:
+ case Expr::ObjCPropertyRefExprClass:
+ 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();
+
+ case Expr::ParenExprClass:
+ return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
+ case Expr::IntegerLiteralClass:
+ case Expr::CharacterLiteralClass:
+ case Expr::CXXBoolLiteralExprClass:
+ case Expr::CXXScalarValueInitExprClass:
+ case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
+ case Expr::CXXNoexceptExprClass:
+ return NoDiag();
+ case Expr::CallExprClass:
+ case Expr::CXXOperatorCallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ if (CE->isBuiltinCall(Ctx))
+ return CheckEvalInICE(E, Ctx);
+ return ICEDiag(2, E->getLocStart());
+ }
+ case Expr::DeclRefExprClass:
+ if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
+ return NoDiag();
+ if (Ctx.getLangOptions().CPlusPlus &&
+ E->getType().getCVRQualifiers() == Qualifiers::Const) {
+ const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
+
+ // Parameter variables are never constants. Without this check,
+ // getAnyInitializer() can find a default argument, which leads
+ // to chaos.
+ if (isa<ParmVarDecl>(D))
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+
+ // C++ 7.1.5.1p2
+ // A variable of non-volatile const-qualified integral or enumeration
+ // type initialized by an ICE can be used in ICEs.
+ if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
+ Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers();
+ if (Quals.hasVolatile() || !Quals.hasConst())
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+
+ // Look for a declaration of this variable that has an initializer.
+ const VarDecl *ID = 0;
+ const Expr *Init = Dcl->getAnyInitializer(ID);
+ if (Init) {
+ if (ID->isInitKnownICE()) {
+ // We have already checked whether this subexpression is an
+ // integral constant expression.
+ if (ID->isInitICE())
+ return NoDiag();
+ else
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+ }
+
+ // It's an ICE whether or not the definition we found is
+ // out-of-line. See DR 721 and the discussion in Clang PR
+ // 6206 for details.
+
+ if (Dcl->isCheckingICE()) {
+ return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+ }
+
+ Dcl->setCheckingICE();
+ ICEDiag Result = CheckICE(Init, Ctx);
+ // Cache the result of the ICE test.
+ Dcl->setInitKnownICE(Result.Val == 0);
+ return Result;
+ }
+ }
+ }
+ return ICEDiag(2, E->getLocStart());
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *Exp = cast<UnaryOperator>(E);
+ switch (Exp->getOpcode()) {
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ case UO_AddrOf:
+ case UO_Deref:
+ return ICEDiag(2, E->getLocStart());
+ case UO_Extension:
+ case UO_LNot:
+ case UO_Plus:
+ case UO_Minus:
+ case UO_Not:
+ case UO_Real:
+ case UO_Imag:
+ return CheckICE(Exp->getSubExpr(), Ctx);
+ }
+
+ // OffsetOf falls through here.
+ }
+ case Expr::OffsetOfExprClass: {
+ // Note that per C99, offsetof must be an ICE. And AFAIK, using
+ // Evaluate matches the proposed gcc behavior for cases like
+ // "offsetof(struct s{int x[4];}, x[!.0])". This doesn't affect
+ // compliance: we should warn earlier for offsetof expressions with
+ // array subscripts that aren't ICEs, and if the array subscripts
+ // are ICEs, the value of the offsetof must be an integer constant.
+ return CheckEvalInICE(E, Ctx);
+ }
+ case Expr::SizeOfAlignOfExprClass: {
+ const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E);
+ if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType())
+ return ICEDiag(2, E->getLocStart());
+ return NoDiag();
+ }
+ case Expr::BinaryOperatorClass: {
+ const BinaryOperator *Exp = cast<BinaryOperator>(E);
+ switch (Exp->getOpcode()) {
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Assign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ return ICEDiag(2, E->getLocStart());
+
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_Comma: {
+ ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
+ ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
+ if (Exp->getOpcode() == BO_Div ||
+ Exp->getOpcode() == BO_Rem) {
+ // Evaluate gives an error for undefined Div/Rem, so make sure
+ // we don't evaluate one.
+ if (LHSResult.Val != 2 && RHSResult.Val != 2) {
+ llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx);
+ if (REval == 0)
+ return ICEDiag(1, E->getLocStart());
+ if (REval.isSigned() && REval.isAllOnesValue()) {
+ llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx);
+ if (LEval.isMinSignedValue())
+ return ICEDiag(1, E->getLocStart());
+ }
+ }
+ }
+ if (Exp->getOpcode() == BO_Comma) {
+ if (Ctx.getLangOptions().C99) {
+ // C99 6.6p3 introduces a strange edge case: comma can be in an ICE
+ // if it isn't evaluated.
+ if (LHSResult.Val == 0 && RHSResult.Val == 0)
+ return ICEDiag(1, E->getLocStart());
+ } else {
+ // In both C89 and C++, commas in ICEs are illegal.
+ return ICEDiag(2, E->getLocStart());
+ }
+ }
+ if (LHSResult.Val >= RHSResult.Val)
+ return LHSResult;
+ return RHSResult;
+ }
+ case BO_LAnd:
+ case BO_LOr: {
+ ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
+ ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
+ if (LHSResult.Val == 0 && RHSResult.Val == 1) {
+ // Rare case where the RHS has a comma "side-effect"; we need
+ // to actually check the condition to see whether the side
+ // with the comma is evaluated.
+ if ((Exp->getOpcode() == BO_LAnd) !=
+ (Exp->getLHS()->EvaluateAsInt(Ctx) == 0))
+ return RHSResult;
+ return NoDiag();
+ }
+
+ if (LHSResult.Val >= RHSResult.Val)
+ return LHSResult;
+ return RHSResult;
+ }
+ }
+ }
+ case Expr::ImplicitCastExprClass:
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass: {
+ const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
+ if (SubExpr->getType()->isIntegralOrEnumerationType())
+ return CheckICE(SubExpr, Ctx);
+ if (isa<FloatingLiteral>(SubExpr->IgnoreParens()))
+ return NoDiag();
+ return ICEDiag(2, E->getLocStart());
+ }
+ case Expr::BinaryConditionalOperatorClass: {
+ const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(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<ConditionalOperator>(E);
+ // If the condition (ignoring parens) is a __builtin_constant_p call,
+ // then only the true side is actually considered in an integer constant
+ // expression, and it is fully evaluated. This is an important GNU
+ // extension. See GCC PR38377 for discussion.
+ if (const CallExpr *CallCE
+ = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts()))
+ if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) {
+ Expr::EvalResult EVResult;
+ if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects ||
+ !EVResult.Val.isInt()) {
+ return ICEDiag(2, E->getLocStart());
+ }
+ return NoDiag();
+ }
+ ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
+ ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
+ ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
+ if (CondResult.Val == 2)
+ return CondResult;
+ if (TrueResult.Val == 2)
+ return TrueResult;
+ if (FalseResult.Val == 2)
+ return FalseResult;
+ if (CondResult.Val == 1)
+ return CondResult;
+ if (TrueResult.Val == 0 && FalseResult.Val == 0)
+ return NoDiag();
+ // Rare case where the diagnostics depend on which side is evaluated
+ // Note that if we get here, CondResult is 0, and at least one of
+ // TrueResult and FalseResult is non-zero.
+ if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) {
+ return FalseResult;
+ }
+ return TrueResult;
+ }
+ case Expr::CXXDefaultArgExprClass:
+ return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx);
+ case Expr::ChooseExprClass: {
+ return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx);
+ }
+ }
+
+ // Silence a GCC warning
+ return ICEDiag(2, E->getLocStart());
+}
+
+bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
+ SourceLocation *Loc, bool isEvaluated) const {
+ ICEDiag d = CheckICE(this, Ctx);
+ if (d.Val != 0) {
+ if (Loc) *Loc = d.Loc;
+ return false;
+ }
+ EvalResult EvalResult;
+ if (!Evaluate(EvalResult, Ctx))
+ llvm_unreachable("ICE cannot be evaluated!");
+ assert(!EvalResult.HasSideEffects && "ICE with side effects!");
+ assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
+ Result = EvalResult.Val.getInt();
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp
new file mode 100644
index 0000000..533a232
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp
@@ -0,0 +1,163 @@
+//===- InheritViz.cpp - Graphviz visualization for inheritance --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements CXXRecordDecl::viewInheritance, which
+// generates a GraphViz DOT file that depicts the class inheritance
+// diagram and then calls Graphviz/dot+gv on it.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#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 <map>
+
+using namespace llvm;
+
+namespace clang {
+
+/// InheritanceHierarchyWriter - Helper class that writes out a
+/// GraphViz file that diagrams the inheritance hierarchy starting at
+/// a given C++ class type. Note that we do not use LLVM's
+/// GraphWriter, because the interface does not permit us to properly
+/// differentiate between uses of types as virtual bases
+/// vs. non-virtual bases.
+class InheritanceHierarchyWriter {
+ ASTContext& Context;
+ llvm::raw_ostream &Out;
+ std::map<QualType, int, QualTypeOrdering> DirectBaseCount;
+ std::set<QualType, QualTypeOrdering> KnownVirtualBases;
+
+public:
+ InheritanceHierarchyWriter(ASTContext& Context, llvm::raw_ostream& Out)
+ : Context(Context), Out(Out) { }
+
+ void WriteGraph(QualType Type) {
+ Out << "digraph \"" << DOT::EscapeString(Type.getAsString()) << "\" {\n";
+ WriteNode(Type, false);
+ Out << "}\n";
+ }
+
+protected:
+ /// WriteNode - Write out the description of node in the inheritance
+ /// diagram, which may be a base class or it may be the root node.
+ void WriteNode(QualType Type, bool FromVirtual);
+
+ /// WriteNodeReference - Write out a reference to the given node,
+ /// using a unique identifier for each direct base and for the
+ /// (only) virtual base.
+ llvm::raw_ostream& WriteNodeReference(QualType Type, bool FromVirtual);
+};
+
+void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
+ QualType CanonType = Context.getCanonicalType(Type);
+
+ if (FromVirtual) {
+ if (KnownVirtualBases.find(CanonType) != KnownVirtualBases.end())
+ return;
+
+ // We haven't seen this virtual base before, so display it and
+ // its bases.
+ KnownVirtualBases.insert(CanonType);
+ }
+
+ // Declare the node itself.
+ Out << " ";
+ WriteNodeReference(Type, FromVirtual);
+
+ // Give the node a label based on the name of the class.
+ std::string TypeName = Type.getAsString();
+ Out << " [ shape=\"box\", label=\"" << DOT::EscapeString(TypeName);
+
+ // If the name of the class was a typedef or something different
+ // from the "real" class name, show the real class name in
+ // parentheses so we don't confuse ourselves.
+ if (TypeName != CanonType.getAsString()) {
+ Out << "\\n(" << CanonType.getAsString() << ")";
+ }
+
+ // Finished describing the node.
+ Out << " \"];\n";
+
+ // Display the base classes.
+ const CXXRecordDecl *Decl
+ = static_cast<const CXXRecordDecl *>(Type->getAs<RecordType>()->getDecl());
+ for (CXXRecordDecl::base_class_const_iterator Base = Decl->bases_begin();
+ Base != Decl->bases_end(); ++Base) {
+ QualType CanonBaseType = Context.getCanonicalType(Base->getType());
+
+ // If this is not virtual inheritance, bump the direct base
+ // count for the type.
+ if (!Base->isVirtual())
+ ++DirectBaseCount[CanonBaseType];
+
+ // Write out the node (if we need to).
+ WriteNode(Base->getType(), Base->isVirtual());
+
+ // Write out the edge.
+ Out << " ";
+ WriteNodeReference(Type, FromVirtual);
+ Out << " -> ";
+ WriteNodeReference(Base->getType(), Base->isVirtual());
+
+ // Write out edge attributes to show the kind of inheritance.
+ if (Base->isVirtual()) {
+ Out << " [ style=\"dashed\" ]";
+ }
+ Out << ";";
+ }
+}
+
+/// WriteNodeReference - Write out a reference to the given node,
+/// using a unique identifier for each direct base and for the
+/// (only) virtual base.
+llvm::raw_ostream&
+InheritanceHierarchyWriter::WriteNodeReference(QualType Type,
+ bool FromVirtual) {
+ QualType CanonType = Context.getCanonicalType(Type);
+
+ Out << "Class_" << CanonType.getAsOpaquePtr();
+ if (!FromVirtual)
+ Out << "_" << DirectBaseCount[CanonType];
+ return Out;
+}
+
+/// viewInheritance - Display the inheritance hierarchy of this C++
+/// class using GraphViz.
+void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
+ QualType Self = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
+ // 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 << "'... ";
+
+ llvm::raw_fd_ostream O(FileFD, true);
+ InheritanceHierarchyWriter Writer(Context, O);
+ Writer.WriteGraph(Self);
+
+ llvm::errs() << " done. \n";
+ O.close();
+
+ // Display the graph
+ DisplayGraph(sys::Path(Filename));
+}
+
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
new file mode 100644
index 0000000..bed02b4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -0,0 +1,73 @@
+//===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Itanium C++ ABI, which is
+// documented at:
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//
+// It also supports the closely-related ARM C++ ABI, documented at:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang;
+
+namespace {
+class ItaniumCXXABI : public CXXABI {
+protected:
+ ASTContext &Context;
+public:
+ ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ if (Pointee->isFunctionType()) return 2;
+ return 1;
+ }
+
+ 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 {
+public:
+ ARMCXXABI(ASTContext &Ctx) : ItaniumCXXABI(Ctx) { }
+};
+}
+
+CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
+ return new ItaniumCXXABI(Ctx);
+}
+
+CXXABI *clang::CreateARMCXXABI(ASTContext &Ctx) {
+ return new ARMCXXABI(Ctx);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
new file mode 100644
index 0000000..d66c374
--- /dev/null
+++ b/contrib/llvm/tools/clang/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 <cxxabi.h>
+#endif
+
+using namespace clang;
+
+namespace {
+
+static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
+ const DeclContext *DC = dyn_cast<DeclContext>(ND);
+ if (!DC)
+ DC = ND->getDeclContext();
+ while (!DC->isNamespace() && !DC->isTranslationUnit()) {
+ if (isa<FunctionDecl>(DC->getParent()))
+ return dyn_cast<CXXRecordDecl>(DC);
+ DC = DC->getParent();
+ }
+ return 0;
+}
+
+static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
+ assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
+ "Passed in decl is not a ctor or dtor!");
+
+ if (const TemplateDecl *TD = MD->getPrimaryTemplate()) {
+ MD = cast<CXXMethodDecl>(TD->getTemplatedDecl());
+
+ assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) &&
+ "Templated decl is not a ctor or dtor!");
+ }
+
+ return MD;
+}
+
+static const unsigned UnknownArity = ~0U;
+
+class ItaniumMangleContext : public MangleContext {
+ llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
+ unsigned Discriminator;
+ llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+
+public:
+ explicit ItaniumMangleContext(ASTContext &Context,
+ Diagnostic &Diags)
+ : MangleContext(Context, Diags) { }
+
+ uint64_t getAnonymousStructId(const TagDecl *TD) {
+ std::pair<llvm::DenseMap<const TagDecl *,
+ uint64_t>::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<uintptr_t, unsigned> 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<NamedDecl>(ND->getCanonicalDecl());
+
+ addSubstitution(reinterpret_cast<uintptr_t>(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<LinkageSpecDecl>(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<AsmLabelAttr>())
+ 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<FunctionDecl>(D);
+ if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(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<AsmLabelAttr>()) {
+ // 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;
+ }
+
+ // <mangled-name> ::= _Z <encoding>
+ // ::= <data name>
+ // ::= <special-name>
+ Out << Prefix;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ mangleFunctionEncoding(FD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ mangleName(VD);
+ else
+ mangleName(cast<FieldDecl>(D));
+}
+
+void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <encoding> ::= <function name> <bare-function-type>
+ 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<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
+ isa<CXXConversionDecl>(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<FunctionType>(Context.getASTContext()
+ .getCanonicalType(FD->getType()));
+
+ mangleBareFunctionType(FT, MangleReturnType);
+}
+
+static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
+ while (isa<LinkageSpecDecl>(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<NamespaceDecl>(DC));
+}
+
+static const TemplateDecl *
+isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
+ // Check if we have a function template.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(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<ClassTemplateSpecializationDecl>(ND)) {
+ TemplateArgs = &Spec->getTemplateArgs();
+ return Spec->getSpecializedTemplate();
+ }
+
+ return 0;
+}
+
+void CXXNameMangler::mangleName(const NamedDecl *ND) {
+ // <name> ::= <nested-name>
+ // ::= <unscoped-name>
+ // ::= <unscoped-template-name> <template-args>
+ // ::= <local-name>
+ //
+ 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<FunctionDecl>(DC) && ND->hasLinkage())
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = DC->getParent();
+ else if (GetLocalClassDecl(ND)) {
+ mangleLocalName(ND);
+ return;
+ }
+
+ while (isa<LinkageSpecDecl>(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<FunctionDecl>(DC) || isa<ObjCMethodDecl>(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) {
+ // <unscoped-name> ::= <unqualified-name>
+ // ::= St <unqualified-name> # ::std::
+ if (isStdNamespace(ND->getDeclContext()))
+ Out << "St";
+
+ mangleUnqualifiedName(ND);
+}
+
+void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+ if (mangleSubstitution(ND))
+ return;
+
+ // <template-template-param> ::= <template-param>
+ if (const TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ mangleTemplateParameter(TTP->getIndex());
+ return;
+ }
+
+ mangleUnscopedName(ND->getTemplatedDecl());
+ addSubstitution(ND);
+}
+
+void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+ 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) {
+ // <number> ::= [n] <non-negative decimal integer>
+ if (Number < 0) {
+ Out << 'n';
+ Number = -Number;
+ }
+
+ Out << Number;
+}
+
+void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
+ // <call-offset> ::= h <nv-offset> _
+ // ::= v <v-offset> _
+ // <nv-offset> ::= <offset number> # non-virtual base override
+ // <v-offset> ::= <offset number> _ <virtual offset number>
+ // # 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<TemplateSpecializationType>(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<RecordType>()) {
+ 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) {
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ 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<VarDecl>(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<NamespaceDecl>(ND)) {
+ if (NS->isAnonymousNamespace()) {
+ // This is how gcc mangles these names.
+ Out << "12_GLOBAL__N_1";
+ break;
+ }
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ // We must have an anonymous union or struct declaration.
+ const RecordDecl *RD =
+ cast<RecordDecl>(VD->getType()->getAs<RecordType>()->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<TagDecl>(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] $_<id>
+ // 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<CXXCtorType>(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<CXXDtorType>(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:
+ // <operator-name> ::= cv <type> # (cast)
+ Out << "cv";
+ mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType()));
+ break;
+
+ case DeclarationName::CXXOperatorName: {
+ unsigned Arity;
+ if (ND) {
+ Arity = cast<FunctionDecl>(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<CXXMethodDecl>(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) {
+ // <source-name> ::= <positive length number> <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() << II->getName();
+}
+
+void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
+ const DeclContext *DC,
+ bool NoFunction) {
+ // <nested-name>
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
+ // <template-args> E
+
+ Out << 'N';
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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) {
+ // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+
+ Out << 'N';
+
+ mangleTemplatePrefix(TD);
+ TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
+ mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
+
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
+ // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ // := Z <function encoding> E s [<discriminator>]
+ // <discriminator> := _ <non-negative number>
+ const DeclContext *DC = ND->getDeclContext();
+ Out << 'Z';
+
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
+ mangleObjCMethodName(MD);
+ } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
+ mangleFunctionEncoding(cast<FunctionDecl>(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<FunctionDecl>(DC));
+
+ Out << 'E';
+ mangleUnqualifiedName(ND);
+}
+
+void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
+ // <prefix> ::= <prefix> <unqualified-name>
+ // ::= <template-prefix> <template-args>
+ // ::= <template-param>
+ // ::= # empty
+ // ::= <substitution>
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+
+ if (DC->isTranslationUnit())
+ return;
+
+ if (const BlockDecl *Block = dyn_cast<BlockDecl>(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<NamedDecl>(DC)))
+ return;
+
+ // Check if we have a template.
+ const TemplateArgumentList *TemplateArgs = 0;
+ if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
+ mangleTemplatePrefix(TD);
+ TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
+ mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+ }
+ else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
+ return;
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+ mangleObjCMethodName(Method);
+ else {
+ manglePrefix(DC->getParent(), NoFunction);
+ mangleUnqualifiedName(cast<NamedDecl>(DC));
+ }
+
+ addSubstitution(cast<NamedDecl>(DC));
+}
+
+void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleTemplatePrefix(TD);
+
+ if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
+ mangleUnresolvedScope(Qualified->getQualifier());
+
+ if (OverloadedTemplateStorage *Overloaded
+ = Template.getAsOverloadedTemplate()) {
+ mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(),
+ UnknownArity);
+ return;
+ }
+
+ DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+ assert(Dependent && "Unknown template name kind?");
+ mangleUnresolvedScope(Dependent->getQualifier());
+ mangleUnscopedTemplateName(Template);
+}
+
+void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ // <template-template-param> ::= <template-param>
+ // <substitution>
+
+ if (mangleSubstitution(ND))
+ return;
+
+ // <template-template-param> ::= <template-param>
+ if (const TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ mangleTemplateParameter(TTP->getIndex());
+ return;
+ }
+
+ manglePrefix(ND->getDeclContext());
+ mangleUnqualifiedName(ND->getTemplatedDecl());
+ addSubstitution(ND);
+}
+
+/// Mangles a template name under the production <type>. Required for
+/// template template arguments.
+/// <type> ::= <class-enum-type>
+/// ::= <template-param>
+/// ::= <substitution>
+void CXXNameMangler::mangleType(TemplateName TN) {
+ if (mangleSubstitution(TN))
+ return;
+
+ TemplateDecl *TD = 0;
+
+ switch (TN.getKind()) {
+ case TemplateName::QualifiedTemplate:
+ TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();
+ goto HaveDecl;
+
+ case TemplateName::Template:
+ TD = TN.getAsTemplateDecl();
+ goto HaveDecl;
+
+ HaveDecl:
+ if (isa<TemplateTemplateParmDecl>(TD))
+ mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());
+ else
+ mangleName(TD);
+ break;
+
+ case TemplateName::OverloadedTemplate:
+ llvm_unreachable("can't mangle an overloaded template name as a <type>");
+ break;
+
+ case TemplateName::DependentTemplate: {
+ const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
+ assert(Dependent->isIdentifier());
+
+ // <class-enum-type> ::= <name>
+ // <name> ::= <nested-name>
+ mangleUnresolvedScope(Dependent->getQualifier());
+ mangleSourceName(Dependent->getIdentifier());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ SubstTemplateTemplateParmPackStorage *SubstPack
+ = TN.getAsSubstTemplateTemplateParmPack();
+ mangleTemplateParameter(SubstPack->getParameterPack()->getIndex());
+ break;
+ }
+ }
+
+ addSubstitution(TN);
+}
+
+void
+CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
+ switch (OO) {
+ // <operator-name> ::= nw # new
+ case OO_New: Out << "nw"; break;
+ // ::= na # new[]
+ case OO_Array_New: Out << "na"; break;
+ // ::= dl # delete
+ case OO_Delete: Out << "dl"; break;
+ // ::= da # delete[]
+ case OO_Array_Delete: Out << "da"; break;
+ // ::= ps # + (unary)
+ // ::= pl # + (binary or unknown)
+ case OO_Plus:
+ Out << (Arity == 1? "ps" : "pl"); break;
+ // ::= ng # - (unary)
+ // ::= mi # - (binary or unknown)
+ case OO_Minus:
+ Out << (Arity == 1? "ng" : "mi"); break;
+ // ::= ad # & (unary)
+ // ::= an # & (binary or unknown)
+ case OO_Amp:
+ Out << (Arity == 1? "ad" : "an"); break;
+ // ::= de # * (unary)
+ // ::= ml # * (binary or unknown)
+ case OO_Star:
+ // Use binary when unknown.
+ Out << (Arity == 1? "de" : "ml"); break;
+ // ::= co # ~
+ case OO_Tilde: Out << "co"; break;
+ // ::= dv # /
+ case OO_Slash: Out << "dv"; break;
+ // ::= rm # %
+ case OO_Percent: Out << "rm"; break;
+ // ::= or # |
+ case OO_Pipe: Out << "or"; break;
+ // ::= eo # ^
+ case OO_Caret: Out << "eo"; break;
+ // ::= aS # =
+ case OO_Equal: Out << "aS"; break;
+ // ::= pL # +=
+ case OO_PlusEqual: Out << "pL"; break;
+ // ::= mI # -=
+ case OO_MinusEqual: Out << "mI"; break;
+ // ::= mL # *=
+ case OO_StarEqual: Out << "mL"; break;
+ // ::= dV # /=
+ case OO_SlashEqual: Out << "dV"; break;
+ // ::= rM # %=
+ case OO_PercentEqual: Out << "rM"; break;
+ // ::= aN # &=
+ case OO_AmpEqual: Out << "aN"; break;
+ // ::= oR # |=
+ case OO_PipeEqual: Out << "oR"; break;
+ // ::= eO # ^=
+ case OO_CaretEqual: Out << "eO"; break;
+ // ::= ls # <<
+ case OO_LessLess: Out << "ls"; break;
+ // ::= rs # >>
+ case OO_GreaterGreater: Out << "rs"; break;
+ // ::= lS # <<=
+ case OO_LessLessEqual: Out << "lS"; break;
+ // ::= rS # >>=
+ case OO_GreaterGreaterEqual: Out << "rS"; break;
+ // ::= eq # ==
+ case OO_EqualEqual: Out << "eq"; break;
+ // ::= ne # !=
+ case OO_ExclaimEqual: Out << "ne"; break;
+ // ::= lt # <
+ case OO_Less: Out << "lt"; break;
+ // ::= gt # >
+ case OO_Greater: Out << "gt"; break;
+ // ::= le # <=
+ case OO_LessEqual: Out << "le"; break;
+ // ::= ge # >=
+ case OO_GreaterEqual: Out << "ge"; break;
+ // ::= nt # !
+ case OO_Exclaim: Out << "nt"; break;
+ // ::= aa # &&
+ case OO_AmpAmp: Out << "aa"; break;
+ // ::= oo # ||
+ case OO_PipePipe: Out << "oo"; break;
+ // ::= pp # ++
+ case OO_PlusPlus: Out << "pp"; break;
+ // ::= mm # --
+ case OO_MinusMinus: Out << "mm"; break;
+ // ::= cm # ,
+ case OO_Comma: Out << "cm"; break;
+ // ::= pm # ->*
+ case OO_ArrowStar: Out << "pm"; break;
+ // ::= pt # ->
+ case OO_Arrow: Out << "pt"; break;
+ // ::= cl # ()
+ case OO_Call: Out << "cl"; break;
+ // ::= ix # []
+ case OO_Subscript: Out << "ix"; break;
+
+ // ::= qu # ?
+ // The conditional operator can't be overloaded, but we still handle it when
+ // mangling expressions.
+ case OO_Conditional: Out << "qu"; break;
+
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ assert(false && "Not an overloaded operator");
+ break;
+ }
+}
+
+void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
+ // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ if (Quals.hasRestrict())
+ Out << 'r';
+ if (Quals.hasVolatile())
+ Out << 'V';
+ if (Quals.hasConst())
+ Out << 'K';
+
+ if (Quals.hasAddressSpace()) {
+ // Extension:
+ //
+ // <type> ::= U <address-space-number>
+ //
+ // where <address-space-number> is a source name consisting of 'AS'
+ // followed by the address space <number>.
+ llvm::SmallString<64> ASString;
+ ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace());
+ Out << 'U' << ASString.size() << ASString;
+ }
+
+ // FIXME: For now, just drop all extension qualifiers on the floor.
+}
+
+void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
+ // <ref-qualifier> ::= R # lvalue reference
+ // ::= O # rvalue-reference
+ // Proposal to Itanium C++ ABI list on 1/26/11
+ switch (RefQualifier) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ Out << 'R';
+ break;
+
+ case RQ_RValue:
+ Out << 'O';
+ break;
+ }
+}
+
+void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
+ Context.mangleObjCMethodName(MD, Out);
+}
+
+void CXXNameMangler::mangleType(QualType nonCanon) {
+ // Only operate on the canonical type!
+ QualType canon = nonCanon.getCanonicalType();
+
+ SplitQualType split = canon.split();
+ Qualifiers quals = split.second;
+ const Type *ty = split.first;
+
+ bool isSubstitutable = quals || !isa<BuiltinType>(ty);
+ if (isSubstitutable && mangleSubstitution(canon))
+ return;
+
+ // If we're mangling a qualified array type, push the qualifiers to
+ // the element type.
+ if (quals && isa<ArrayType>(ty)) {
+ ty = Context.getASTContext().getAsArrayType(canon);
+ quals = Qualifiers();
+
+ // Note that we don't update canon: we want to add the
+ // substitution at the canonical type.
+ }
+
+ if (quals) {
+ mangleQualifiers(quals);
+ // Recurse: even if the qualified type isn't yet substitutable,
+ // the unqualified type might be.
+ mangleType(QualType(ty, 0));
+ } else {
+ switch (ty->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
+ return;
+#define TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ mangleType(static_cast<const CLASS##Type*>(ty)); \
+ break;
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ // Add the substitution.
+ if (isSubstitutable)
+ addSubstitution(canon);
+}
+
+void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
+ if (!mangleStandardSubstitution(ND))
+ mangleName(ND);
+}
+
+void CXXNameMangler::mangleType(const BuiltinType *T) {
+ // <type> ::= <builtin-type>
+ // <builtin-type> ::= v # void
+ // ::= w # wchar_t
+ // ::= b # bool
+ // ::= c # char
+ // ::= a # signed char
+ // ::= h # unsigned char
+ // ::= s # short
+ // ::= t # unsigned short
+ // ::= i # int
+ // ::= j # unsigned int
+ // ::= l # long
+ // ::= m # unsigned long
+ // ::= x # long long, __int64
+ // ::= y # unsigned long long, __int64
+ // ::= n # __int128
+ // UNSUPPORTED: ::= o # unsigned __int128
+ // ::= f # float
+ // ::= d # double
+ // ::= e # long double, __float80
+ // UNSUPPORTED: ::= g # __float128
+ // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
+ // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
+ // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
+ // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= Di # char32_t
+ // ::= Ds # char16_t
+ // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
+ // ::= u <source-name> # vendor extended type
+ switch (T->getKind()) {
+ case BuiltinType::Void: Out << 'v'; break;
+ case BuiltinType::Bool: Out << 'b'; break;
+ case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
+ case BuiltinType::UChar: Out << 'h'; break;
+ case BuiltinType::UShort: Out << 't'; break;
+ case BuiltinType::UInt: Out << 'j'; break;
+ case BuiltinType::ULong: Out << 'm'; break;
+ case BuiltinType::ULongLong: Out << 'y'; break;
+ case BuiltinType::UInt128: Out << 'o'; break;
+ case BuiltinType::SChar: Out << 'a'; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: Out << 'w'; break;
+ case BuiltinType::Char16: Out << "Ds"; break;
+ case BuiltinType::Char32: Out << "Di"; break;
+ case BuiltinType::Short: Out << 's'; break;
+ case BuiltinType::Int: Out << 'i'; break;
+ case BuiltinType::Long: Out << 'l'; break;
+ case BuiltinType::LongLong: Out << 'x'; break;
+ case BuiltinType::Int128: Out << 'n'; break;
+ case BuiltinType::Float: Out << 'f'; break;
+ case BuiltinType::Double: Out << 'd'; break;
+ case BuiltinType::LongDouble: Out << 'e'; break;
+ case BuiltinType::NullPtr: Out << "Dn"; break;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ assert(false &&
+ "Overloaded and dependent types shouldn't get to name mangling");
+ break;
+ case BuiltinType::ObjCId: Out << "11objc_object"; break;
+ case BuiltinType::ObjCClass: Out << "10objc_class"; break;
+ case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
+ }
+}
+
+// <type> ::= <function-type>
+// <function-type> ::= F [Y] <bare-function-type> E
+void CXXNameMangler::mangleType(const FunctionProtoType *T) {
+ Out << 'F';
+ // FIXME: We don't have enough information in the AST to produce the 'Y'
+ // encoding for extern "C" function types.
+ mangleBareFunctionType(T, /*MangleReturnType=*/true);
+ Out << 'E';
+}
+void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
+ llvm_unreachable("Can't mangle K&R function prototypes");
+}
+void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
+ bool MangleReturnType) {
+ // We should never be mangling something without a prototype.
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
+ // <bare-function-type> ::= <signature type>+
+ if (MangleReturnType)
+ mangleType(Proto->getResultType());
+
+ if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ // <builtin-type> ::= v # void
+ Out << 'v';
+ return;
+ }
+
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleType(*Arg);
+
+ // <builtin-type> ::= z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'z';
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const EnumType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void CXXNameMangler::mangleType(const RecordType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void CXXNameMangler::mangleType(const TagType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <array-type>
+// <array-type> ::= A <positive dimension number> _ <element type>
+// ::= A [<dimension expression>] _ <element type>
+void CXXNameMangler::mangleType(const ConstantArrayType *T) {
+ Out << 'A' << T->getSize() << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const VariableArrayType *T) {
+ Out << 'A';
+ // decayed vla types (size 0) will just be skipped.
+ if (T->getSizeExpr())
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
+ Out << 'A';
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
+ Out << "A_";
+ mangleType(T->getElementType());
+}
+
+// <type> ::= <pointer-to-member-type>
+// <pointer-to-member-type> ::= M <class type> <member type>
+void CXXNameMangler::mangleType(const MemberPointerType *T) {
+ Out << 'M';
+ mangleType(QualType(T->getClass(), 0));
+ QualType PointeeType = T->getPointeeType();
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
+ mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals()));
+ mangleRefQualifier(FPT->getRefQualifier());
+ mangleType(FPT);
+
+ // Itanium C++ ABI 5.1.8:
+ //
+ // The type of a non-static member function is considered to be different,
+ // for the purposes of substitution, from the type of a namespace-scope or
+ // static member function whose type appears similar. The types of two
+ // non-static member functions are considered to be different, for the
+ // purposes of substitution, if the functions are members of different
+ // classes. In other words, for the purposes of substitution, the class of
+ // which the function is a member is considered part of the type of
+ // function.
+
+ // We increment the SeqID here to emulate adding an entry to the
+ // substitution table. We can't actually add it because we don't want this
+ // particular function type to be substituted.
+ ++SeqID;
+ } else
+ mangleType(PointeeType);
+}
+
+// <type> ::= <template-param>
+void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
+ mangleTemplateParameter(T->getIndex());
+}
+
+// <type> ::= <template-param>
+void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
+ mangleTemplateParameter(T->getReplacedParameter()->getIndex());
+}
+
+// <type> ::= P <type> # pointer-to
+void CXXNameMangler::mangleType(const PointerType *T) {
+ Out << 'P';
+ mangleType(T->getPointeeType());
+}
+void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
+ Out << 'P';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= R <type> # reference-to
+void CXXNameMangler::mangleType(const LValueReferenceType *T) {
+ Out << 'R';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= O <type> # rvalue reference-to (C++0x)
+void CXXNameMangler::mangleType(const RValueReferenceType *T) {
+ Out << 'O';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= C <type> # complex pair (C 2000)
+void CXXNameMangler::mangleType(const ComplexType *T) {
+ Out << 'C';
+ mangleType(T->getElementType());
+}
+
+// ARM's ABI for Neon vector types specifies that they should be mangled as
+// if they are structs (to match ARM's initial implementation). The
+// vector type must be one of the special types predefined by ARM.
+void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
+ QualType EltType = T->getElementType();
+ assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
+ const char *EltName = 0;
+ if (T->getVectorKind() == VectorType::NeonPolyVector) {
+ switch (cast<BuiltinType>(EltType)->getKind()) {
+ case BuiltinType::SChar: EltName = "poly8_t"; break;
+ case BuiltinType::Short: EltName = "poly16_t"; break;
+ default: llvm_unreachable("unexpected Neon polynomial vector element type");
+ }
+ } else {
+ switch (cast<BuiltinType>(EltType)->getKind()) {
+ case BuiltinType::SChar: EltName = "int8_t"; break;
+ case BuiltinType::UChar: EltName = "uint8_t"; break;
+ case BuiltinType::Short: EltName = "int16_t"; break;
+ case BuiltinType::UShort: EltName = "uint16_t"; break;
+ case BuiltinType::Int: EltName = "int32_t"; break;
+ case BuiltinType::UInt: EltName = "uint32_t"; break;
+ case BuiltinType::LongLong: EltName = "int64_t"; break;
+ case BuiltinType::ULongLong: EltName = "uint64_t"; break;
+ case BuiltinType::Float: EltName = "float32_t"; break;
+ default: llvm_unreachable("unexpected Neon vector element type");
+ }
+ }
+ const char *BaseName = 0;
+ unsigned BitSize = (T->getNumElements() *
+ getASTContext().getTypeSize(EltType));
+ if (BitSize == 64)
+ BaseName = "__simd64_";
+ else {
+ assert(BitSize == 128 && "Neon vector type not 64 or 128 bits");
+ BaseName = "__simd128_";
+ }
+ Out << strlen(BaseName) + strlen(EltName);
+ Out << BaseName << EltName;
+}
+
+// GNU extension: vector types
+// <type> ::= <vector-type>
+// <vector-type> ::= Dv <positive dimension number> _
+// <extended element type>
+// ::= Dv [<dimension expression>] _ <element type>
+// <extended element type> ::= <element type>
+// ::= p # AltiVec vector pixel
+void CXXNameMangler::mangleType(const VectorType *T) {
+ if ((T->getVectorKind() == VectorType::NeonVector ||
+ T->getVectorKind() == VectorType::NeonPolyVector)) {
+ mangleNeonVectorType(T);
+ return;
+ }
+ Out << "Dv" << T->getNumElements() << '_';
+ if (T->getVectorKind() == VectorType::AltiVecPixel)
+ Out << 'p';
+ else if (T->getVectorKind() == VectorType::AltiVecBool)
+ Out << 'b';
+ else
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const ExtVectorType *T) {
+ mangleType(static_cast<const VectorType*>(T));
+}
+void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
+ Out << "Dv";
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+
+void CXXNameMangler::mangleType(const PackExpansionType *T) {
+ // <type> ::= Dp <type> # pack expansion (C++0x)
+ Out << "Dp";
+ mangleType(T->getPattern());
+}
+
+void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
+ mangleSourceName(T->getDecl()->getIdentifier());
+}
+
+void CXXNameMangler::mangleType(const ObjCObjectType *T) {
+ // We don't allow overloading by different protocol qualification,
+ // so mangling them isn't necessary.
+ mangleType(T->getBaseType());
+}
+
+void CXXNameMangler::mangleType(const BlockPointerType *T) {
+ Out << "U13block_pointer";
+ mangleType(T->getPointeeType());
+}
+
+void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
+ // Mangle injected class name types as if the user had written the
+ // specialization out fully. It may not actually be possible to see
+ // this mangling, though.
+ mangleType(T->getInjectedSpecializationType());
+}
+
+void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
+ if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
+ mangleName(TD, T->getArgs(), T->getNumArgs());
+ } else {
+ if (mangleSubstitution(QualType(T, 0)))
+ return;
+
+ mangleTemplatePrefix(T->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(T->getTemplateName(), T->getArgs(), T->getNumArgs());
+ addSubstitution(QualType(T, 0));
+ }
+}
+
+void CXXNameMangler::mangleType(const DependentNameType *T) {
+ // Typename types are always nested
+ Out << 'N';
+ mangleUnresolvedScope(T->getQualifier());
+ mangleSourceName(T->getIdentifier());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
+ // Dependently-scoped template types are always nested
+ Out << 'N';
+
+ // TODO: avoid making this TemplateName.
+ TemplateName Prefix =
+ getASTContext().getDependentTemplateName(T->getQualifier(),
+ T->getIdentifier());
+ mangleTemplatePrefix(Prefix);
+
+ // 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(Prefix, T->getArgs(), T->getNumArgs());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const TypeOfType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const TypeOfExprType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const DecltypeType *T) {
+ Expr *E = T->getUnderlyingExpr();
+
+ // type ::= Dt <expression> E # decltype of an id-expression
+ // # or class member access
+ // ::= DT <expression> E # decltype of an expression
+
+ // This purports to be an exhaustive list of id-expressions and
+ // class member accesses. Note that we do not ignore parentheses;
+ // parentheses change the semantics of decltype for these
+ // expressions (and cause the mangler to use the other form).
+ if (isa<DeclRefExpr>(E) ||
+ isa<MemberExpr>(E) ||
+ isa<UnresolvedLookupExpr>(E) ||
+ isa<DependentScopeDeclRefExpr>(E) ||
+ isa<CXXDependentScopeMemberExpr>(E) ||
+ isa<UnresolvedMemberExpr>(E))
+ Out << "Dt";
+ else
+ Out << "DT";
+ mangleExpression(E);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const AutoType *T) {
+ QualType D = T->getDeducedType();
+ assert(!D.isNull() && "can't mangle undeduced auto type");
+ mangleType(D);
+}
+
+void CXXNameMangler::mangleIntegerLiteral(QualType T,
+ const llvm::APSInt &Value) {
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+ Out << 'L';
+
+ mangleType(T);
+ if (T->isBooleanType()) {
+ // Boolean values are encoded as 0/1.
+ Out << (Value.getBoolValue() ? '1' : '0');
+ } else {
+ mangleNumber(Value);
+ }
+ Out << 'E';
+
+}
+
+/// Mangles a member expression. Implicit accesses are not handled,
+/// but that should be okay, because you shouldn't be able to
+/// make an implicit access in a function template declaration.
+void CXXNameMangler::mangleMemberExpr(const Expr *Base,
+ bool IsArrow,
+ NestedNameSpecifier *Qualifier,
+ DeclarationName Member,
+ unsigned Arity) {
+ // gcc-4.4 uses 'dt' for dot expressions, which is reasonable.
+ // OTOH, gcc also mangles the name as an expression.
+ Out << (IsArrow ? "pt" : "dt");
+ mangleExpression(Base);
+ mangleUnresolvedName(Qualifier, Member, Arity);
+}
+
+void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
+ // <expression> ::= <unary operator-name> <expression>
+ // ::= <binary operator-name> <expression> <expression>
+ // ::= <trinary operator-name> <expression> <expression> <expression>
+ // ::= cl <expression>* E # call
+ // ::= cv <type> expression # conversion with one argument
+ // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
+ // ::= st <type> # sizeof (a type)
+ // ::= at <type> # alignof (a type)
+ // ::= <template-param>
+ // ::= <function-param>
+ // ::= sr <type> <unqualified-name> # dependent name
+ // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
+ // ::= sZ <template-param> # size of a parameter pack
+ // ::= sZ <function-param> # size of a function parameter pack
+ // ::= <expr-primary>
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+ // ::= L <type <value float> E # floating literal
+ // ::= L <mangled-name> E # external name
+ switch (E->getStmtClass()) {
+ case Expr::NoStmtClass:
+#define ABSTRACT_STMT(Type)
+#define EXPR(Type, Base)
+#define STMT(Type, Base) \
+ case Expr::Type##Class:
+#include "clang/AST/StmtNodes.inc"
+ // fallthrough
+
+ // These all can only appear in local or variable-initialization
+ // contexts and so should never appear in a mangling.
+ case Expr::AddrLabelExprClass:
+ case Expr::BlockDeclRefExprClass:
+ case Expr::CXXThisExprClass:
+ case Expr::DesignatedInitExprClass:
+ case Expr::ImplicitValueInitExprClass:
+ case Expr::InitListExprClass:
+ case Expr::ParenListExprClass:
+ case Expr::CXXScalarValueInitExprClass:
+ llvm_unreachable("unexpected statement kind");
+ break;
+
+ // FIXME: invent manglings for all these.
+ case Expr::BlockExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::ChooseExprClass:
+ case Expr::CompoundLiteralExprClass:
+ case Expr::ExtVectorElementExprClass:
+ case Expr::ObjCEncodeExprClass:
+ case Expr::ObjCIsaExprClass:
+ case Expr::ObjCIvarRefExprClass:
+ case Expr::ObjCMessageExprClass:
+ case Expr::ObjCPropertyRefExprClass:
+ case Expr::ObjCProtocolExprClass:
+ case Expr::ObjCSelectorExprClass:
+ case Expr::ObjCStringLiteralClass:
+ case Expr::OffsetOfExprClass:
+ case Expr::PredefinedExprClass:
+ case Expr::ShuffleVectorExprClass:
+ case Expr::StmtExprClass:
+ case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
+ case Expr::VAArgExprClass:
+ case Expr::CXXUuidofExprClass:
+ case Expr::CXXNoexceptExprClass:
+ case Expr::CUDAKernelCallExprClass: {
+ // As bad as this diagnostic is, it's better than crashing.
+ Diagnostic &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ "cannot yet mangle expression type %0");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+ break;
+ }
+
+ // Even gcc-4.5 doesn't mangle this.
+ case Expr::BinaryConditionalOperatorClass: {
+ Diagnostic &Diags = Context.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(Diagnostic::Error,
+ "?: operator with omitted middle operand cannot be mangled");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+ break;
+ }
+
+ // These are used for internal purposes and cannot be meaningfully mangled.
+ case Expr::OpaqueValueExprClass:
+ llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");
+
+ case Expr::CXXDefaultArgExprClass:
+ mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
+ break;
+
+ case Expr::CXXMemberCallExprClass: // fallthrough
+ case Expr::CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ Out << "cl";
+ mangleExpression(CE->getCallee(), CE->getNumArgs());
+ for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
+ mangleExpression(CE->getArg(I));
+ Out << 'E';
+ break;
+ }
+
+ case Expr::CXXNewExprClass: {
+ // Proposal from David Vandervoorde, 2010.06.30
+ const CXXNewExpr *New = cast<CXXNewExpr>(E);
+ if (New->isGlobalNew()) Out << "gs";
+ Out << (New->isArray() ? "na" : "nw");
+ for (CXXNewExpr::const_arg_iterator I = New->placement_arg_begin(),
+ E = New->placement_arg_end(); I != E; ++I)
+ mangleExpression(*I);
+ Out << '_';
+ mangleType(New->getAllocatedType());
+ if (New->hasInitializer()) {
+ Out << "pi";
+ for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(),
+ E = New->constructor_arg_end(); I != E; ++I)
+ mangleExpression(*I);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case Expr::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), ME->getMemberDecl()->getDeclName(),
+ Arity);
+ break;
+ }
+
+ case Expr::UnresolvedMemberExprClass: {
+ const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), ME->getMemberName(),
+ Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::CXXDependentScopeMemberExprClass: {
+ const CXXDependentScopeMemberExpr *ME
+ = cast<CXXDependentScopeMemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), ME->getMember(),
+ Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::UnresolvedLookupExprClass: {
+ // The ABI doesn't cover how to mangle overload sets, so we mangle
+ // using something as close as possible to the original lookup
+ // expression.
+ const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
+ if (ULE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ULE->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::CXXUnresolvedConstructExprClass: {
+ const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
+ unsigned N = CE->arg_size();
+
+ Out << "cv";
+ mangleType(CE->getType());
+ if (N != 1) Out << '_';
+ for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+ if (N != 1) Out << 'E';
+ break;
+ }
+
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXConstructExprClass: {
+ const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
+ unsigned N = CE->getNumArgs();
+
+ Out << "cv";
+ mangleType(CE->getType());
+ if (N != 1) Out << '_';
+ for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+ if (N != 1) Out << 'E';
+ break;
+ }
+
+ case Expr::SizeOfAlignOfExprClass: {
+ const SizeOfAlignOfExpr *SAE = cast<SizeOfAlignOfExpr>(E);
+ if (SAE->isSizeOf()) Out << 's';
+ else Out << 'a';
+ if (SAE->isArgumentType()) {
+ Out << 't';
+ mangleType(SAE->getArgumentType());
+ } else {
+ Out << 'z';
+ mangleExpression(SAE->getArgumentExpr());
+ }
+ break;
+ }
+
+ case Expr::CXXThrowExprClass: {
+ const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (TE->getSubExpr()) {
+ Out << "tw";
+ mangleExpression(TE->getSubExpr());
+ } else {
+ Out << "tr";
+ }
+ break;
+ }
+
+ case Expr::CXXTypeidExprClass: {
+ const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (TIE->isTypeOperand()) {
+ Out << "ti";
+ mangleType(TIE->getTypeOperand());
+ } else {
+ Out << "te";
+ mangleExpression(TIE->getExprOperand());
+ }
+ break;
+ }
+
+ case Expr::CXXDeleteExprClass: {
+ const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (DE->isGlobalDelete()) Out << "gs";
+ Out << (DE->isArrayForm() ? "da" : "dl");
+ mangleExpression(DE->getArgument());
+ break;
+ }
+
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(E);
+ mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
+ /*Arity=*/1);
+ mangleExpression(UO->getSubExpr());
+ break;
+ }
+
+ case Expr::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);
+
+ // Array subscript is treated as a syntactically wierd form of
+ // binary operator.
+ Out << "ix";
+ mangleExpression(AE->getLHS());
+ mangleExpression(AE->getRHS());
+ break;
+ }
+
+ case Expr::CompoundAssignOperatorClass: // fallthrough
+ case Expr::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(E);
+ mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
+ /*Arity=*/2);
+ mangleExpression(BO->getLHS());
+ mangleExpression(BO->getRHS());
+ break;
+ }
+
+ case Expr::ConditionalOperatorClass: {
+ const ConditionalOperator *CO = cast<ConditionalOperator>(E);
+ mangleOperatorName(OO_Conditional, /*Arity=*/3);
+ mangleExpression(CO->getCond());
+ mangleExpression(CO->getLHS(), Arity);
+ mangleExpression(CO->getRHS(), Arity);
+ break;
+ }
+
+ case Expr::ImplicitCastExprClass: {
+ mangleExpression(cast<ImplicitCastExpr>(E)->getSubExpr(), Arity);
+ break;
+ }
+
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXDynamicCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass:
+ case Expr::CXXFunctionalCastExprClass: {
+ const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
+ Out << "cv";
+ mangleType(ECE->getType());
+ mangleExpression(ECE->getSubExpr());
+ break;
+ }
+
+ case Expr::CXXOperatorCallExprClass: {
+ const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
+ unsigned NumArgs = CE->getNumArgs();
+ mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
+ // Mangle the arguments.
+ for (unsigned i = 0; i != NumArgs; ++i)
+ mangleExpression(CE->getArg(i));
+ break;
+ }
+
+ case Expr::ParenExprClass:
+ mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
+ break;
+
+ case Expr::DeclRefExprClass: {
+ const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
+
+ switch (D->getKind()) {
+ default:
+ // <expr-primary> ::= L <mangled-name> E # external name
+ Out << 'L';
+ mangle(D, "_Z");
+ Out << 'E';
+ break;
+
+ case Decl::EnumConstant: {
+ const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
+ mangleIntegerLiteral(ED->getType(), ED->getInitVal());
+ break;
+ }
+
+ case Decl::NonTypeTemplateParm: {
+ const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
+ mangleTemplateParameter(PD->getIndex());
+ break;
+ }
+
+ }
+
+ break;
+ }
+
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
+ mangleTemplateParameter(
+ cast<SubstNonTypeTemplateParmPackExpr>(E)->getParameterPack()->getIndex());
+ break;
+
+ case Expr::DependentScopeDeclRefExprClass: {
+ const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
+ NestedNameSpecifier *NNS = DRE->getQualifier();
+ const Type *QTy = NNS->getAsType();
+
+ // When we're dealing with a nested-name-specifier that has just a
+ // dependent identifier in it, mangle that as a typename. FIXME:
+ // It isn't clear that we ever actually want to have such a
+ // nested-name-specifier; why not just represent it as a typename type?
+ if (!QTy && NNS->getAsIdentifier() && NNS->getPrefix()) {
+ QTy = getASTContext().getDependentNameType(ETK_Typename,
+ NNS->getPrefix(),
+ NNS->getAsIdentifier())
+ .getTypePtr();
+ }
+ assert(QTy && "Qualifier was not type!");
+
+ // ::= sr <type> <unqualified-name> # dependent name
+ // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
+ Out << "sr";
+ mangleType(QualType(QTy, 0));
+ mangleUnqualifiedName(0, DRE->getDeclName(), Arity);
+ if (DRE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(DRE->getExplicitTemplateArgs());
+
+ break;
+ }
+
+ case Expr::CXXBindTemporaryExprClass:
+ mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
+ break;
+
+ case Expr::ExprWithCleanupsClass:
+ mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);
+ break;
+
+ case Expr::FloatingLiteralClass: {
+ const FloatingLiteral *FL = cast<FloatingLiteral>(E);
+ Out << 'L';
+ mangleType(FL->getType());
+ mangleFloat(FL->getValue());
+ Out << 'E';
+ break;
+ }
+
+ case Expr::CharacterLiteralClass:
+ Out << 'L';
+ mangleType(E->getType());
+ Out << cast<CharacterLiteral>(E)->getValue();
+ Out << 'E';
+ break;
+
+ case Expr::CXXBoolLiteralExprClass:
+ Out << "Lb";
+ Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
+ Out << 'E';
+ break;
+
+ case Expr::IntegerLiteralClass: {
+ llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
+ if (E->getType()->isSignedIntegerType())
+ Value.setIsSigned(true);
+ mangleIntegerLiteral(E->getType(), Value);
+ break;
+ }
+
+ case Expr::ImaginaryLiteralClass: {
+ const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);
+ // Mangle as if a complex literal.
+ // Proposal from David Vandevoorde, 2010.06.30.
+ Out << 'L';
+ mangleType(E->getType());
+ if (const FloatingLiteral *Imag =
+ dyn_cast<FloatingLiteral>(IE->getSubExpr())) {
+ // Mangle a floating-point zero of the appropriate type.
+ mangleFloat(llvm::APFloat(Imag->getValue().getSemantics()));
+ Out << '_';
+ mangleFloat(Imag->getValue());
+ } else {
+ Out << "0_";
+ llvm::APSInt Value(cast<IntegerLiteral>(IE->getSubExpr())->getValue());
+ if (IE->getSubExpr()->getType()->isSignedIntegerType())
+ Value.setIsSigned(true);
+ mangleNumber(Value);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case Expr::StringLiteralClass: {
+ // Revised proposal from David Vandervoorde, 2010.07.15.
+ Out << 'L';
+ assert(isa<ConstantArrayType>(E->getType()));
+ mangleType(E->getType());
+ Out << 'E';
+ break;
+ }
+
+ case Expr::GNUNullExprClass:
+ // FIXME: should this really be mangled the same as nullptr?
+ // fallthrough
+
+ case Expr::CXXNullPtrLiteralExprClass: {
+ // Proposal from David Vandervoorde, 2010.06.30, as
+ // modified by ABI list discussion.
+ Out << "LDnE";
+ break;
+ }
+
+ case Expr::PackExpansionExprClass:
+ Out << "sp";
+ mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
+ break;
+
+ case Expr::SizeOfPackExprClass: {
+ Out << "sZ";
+ const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();
+ if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
+ mangleTemplateParameter(TTP->getIndex());
+ else if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Pack))
+ mangleTemplateParameter(NTTP->getIndex());
+ else if (const TemplateTemplateParmDecl *TempTP
+ = dyn_cast<TemplateTemplateParmDecl>(Pack))
+ mangleTemplateParameter(TempTP->getIndex());
+ else {
+ // Note: proposed by Mike Herrick on 11/30/10
+ // <expression> ::= sZ <function-param> # size of function parameter pack
+ Diagnostic &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ "cannot mangle sizeof...(function parameter pack)");
+ Diags.Report(DiagID);
+ return;
+ }
+ }
+ }
+}
+
+void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
+ // <ctor-dtor-name> ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
+ //
+ switch (T) {
+ case Ctor_Complete:
+ Out << "C1";
+ break;
+ case Ctor_Base:
+ Out << "C2";
+ break;
+ case Ctor_CompleteAllocating:
+ Out << "C3";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+ // <ctor-dtor-name> ::= D0 # deleting destructor
+ // ::= D1 # complete object destructor
+ // ::= D2 # base object destructor
+ //
+ switch (T) {
+ case Dtor_Deleting:
+ Out << "D0";
+ break;
+ case Dtor_Complete:
+ Out << "D1";
+ break;
+ case Dtor_Base:
+ Out << "D2";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleTemplateArgs(
+ const ExplicitTemplateArgumentList &TemplateArgs) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned I = 0, E = TemplateArgs.NumTemplateArgs; I != E; ++I)
+ mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[I].getArgument());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs,
+ NumTemplateArgs);
+
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ mangleTemplateArg(0, TemplateArgs[i]);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
+ const TemplateArgumentList &AL) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0, e = AL.size(); i != e; ++i)
+ mangleTemplateArg(PL.getParam(i), AL[i]);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ mangleTemplateArg(PL.getParam(i), TemplateArgs[i]);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
+ const TemplateArgument &A) {
+ // <template-arg> ::= <type> # type or template
+ // ::= X <expression> E # expression
+ // ::= <expr-primary> # simple expressions
+ // ::= J <template-arg>* E # argument pack
+ // ::= sp <expression> # pack expansion of (C++0x)
+ switch (A.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Cannot mangle NULL template argument");
+
+ case TemplateArgument::Type:
+ mangleType(A.getAsType());
+ break;
+ case TemplateArgument::Template:
+ // This is mangled as <type>.
+ mangleType(A.getAsTemplate());
+ break;
+ case TemplateArgument::TemplateExpansion:
+ // <type> ::= Dp <type> # pack expansion (C++0x)
+ Out << "Dp";
+ mangleType(A.getAsTemplateOrTemplatePattern());
+ break;
+ case TemplateArgument::Expression:
+ Out << 'X';
+ mangleExpression(A.getAsExpr());
+ Out << 'E';
+ break;
+ case TemplateArgument::Integral:
+ mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral());
+ break;
+ case TemplateArgument::Declaration: {
+ assert(P && "Missing template parameter for declaration argument");
+ // <expr-primary> ::= L <mangled-name> E # external name
+
+ // Clang produces AST's where pointer-to-member-function expressions
+ // and pointer-to-function expressions are represented as a declaration not
+ // an expression. We compensate for it here to produce the correct mangling.
+ NamedDecl *D = cast<NamedDecl>(A.getAsDecl());
+ const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P);
+ bool compensateMangling = D->isCXXClassMember() &&
+ !Parameter->getType()->isReferenceType();
+ if (compensateMangling) {
+ Out << 'X';
+ mangleOperatorName(OO_Amp, 1);
+ }
+
+ Out << 'L';
+ // References to external entities use the mangled name; if the name would
+ // not normally be manged then mangle it as unqualified.
+ //
+ // FIXME: The ABI specifies that external names here should have _Z, but
+ // gcc leaves this off.
+ if (compensateMangling)
+ mangle(D, "_Z");
+ else
+ mangle(D, "Z");
+ Out << 'E';
+
+ if (compensateMangling)
+ Out << 'E';
+
+ break;
+ }
+
+ case TemplateArgument::Pack: {
+ // Note: proposal by Mike Herrick on 12/20/10
+ Out << 'J';
+ for (TemplateArgument::pack_iterator PA = A.pack_begin(),
+ PAEnd = A.pack_end();
+ PA != PAEnd; ++PA)
+ mangleTemplateArg(P, *PA);
+ Out << 'E';
+ }
+ }
+}
+
+void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
+ // <template-param> ::= T_ # first template parameter
+ // ::= T <parameter-2 non-negative number> _
+ if (Index == 0)
+ Out << "T_";
+ else
+ Out << 'T' << (Index - 1) << '_';
+}
+
+// <substitution> ::= S <seq-id> _
+// ::= S_
+bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
+ // Try one of the standard substitutions first.
+ if (mangleStandardSubstitution(ND))
+ return true;
+
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
+ return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
+}
+
+bool CXXNameMangler::mangleSubstitution(QualType T) {
+ if (!T.getCVRQualifiers()) {
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return mangleSubstitution(RT->getDecl());
+ }
+
+ uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+
+ return mangleSubstitution(TypePtr);
+}
+
+bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleSubstitution(TD);
+
+ Template = Context.getASTContext().getCanonicalTemplateName(Template);
+ return mangleSubstitution(
+ reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
+bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
+ llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);
+ if (I == Substitutions.end())
+ return false;
+
+ unsigned SeqID = I->second;
+ if (SeqID == 0)
+ Out << "S_";
+ else {
+ SeqID--;
+
+ // <seq-id> is encoded in base-36, using digits and upper case letters.
+ char Buffer[10];
+ char *BufferPtr = llvm::array_endof(Buffer);
+
+ if (SeqID == 0) *--BufferPtr = '0';
+
+ while (SeqID) {
+ assert(BufferPtr > Buffer && "Buffer overflow!");
+
+ char c = static_cast<char>(SeqID % 36);
+
+ *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
+ SeqID /= 36;
+ }
+
+ Out << 'S'
+ << llvm::StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
+ << '_';
+ }
+
+ return true;
+}
+
+static bool isCharType(QualType T) {
+ if (T.isNull())
+ return false;
+
+ return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ T->isSpecificBuiltinType(BuiltinType::Char_U);
+}
+
+/// isCharSpecialization - Returns whether a given type is a template
+/// specialization of a given name with a single argument of type char.
+static bool isCharSpecialization(QualType T, const char *Name) {
+ if (T.isNull())
+ return false;
+
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ const ClassTemplateSpecializationDecl *SD =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ if (!SD)
+ return false;
+
+ if (!isStdNamespace(SD->getDeclContext()))
+ return false;
+
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+ if (TemplateArgs.size() != 1)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ return SD->getIdentifier()->getName() == Name;
+}
+
+template <std::size_t StrLen>
+static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
+ const char (&Str)[StrLen]) {
+ if (!SD->getIdentifier()->isStr(Str))
+ return false;
+
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+ if (TemplateArgs.size() != 2)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
+ return false;
+
+ return true;
+}
+
+bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
+ // <substitution> ::= St # ::std::
+ if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
+ if (isStd(NS)) {
+ Out << "St";
+ return true;
+ }
+ }
+
+ if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
+ if (!isStdNamespace(TD->getDeclContext()))
+ return false;
+
+ // <substitution> ::= Sa # ::std::allocator
+ if (TD->getIdentifier()->isStr("allocator")) {
+ Out << "Sa";
+ return true;
+ }
+
+ // <<substitution> ::= Sb # ::std::basic_string
+ if (TD->getIdentifier()->isStr("basic_string")) {
+ Out << "Sb";
+ return true;
+ }
+ }
+
+ if (const ClassTemplateSpecializationDecl *SD =
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ if (!isStdNamespace(SD->getDeclContext()))
+ return false;
+
+ // <substitution> ::= Ss # ::std::basic_string<char,
+ // ::std::char_traits<char>,
+ // ::std::allocator<char> >
+ if (SD->getIdentifier()->isStr("basic_string")) {
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+
+ if (TemplateArgs.size() != 3)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
+ return false;
+
+ Out << "Ss";
+ return true;
+ }
+
+ // <substitution> ::= Si # ::std::basic_istream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_istream")) {
+ Out << "Si";
+ return true;
+ }
+
+ // <substitution> ::= So # ::std::basic_ostream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_ostream")) {
+ Out << "So";
+ return true;
+ }
+
+ // <substitution> ::= Sd # ::std::basic_iostream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_iostream")) {
+ Out << "Sd";
+ return true;
+ }
+ }
+ return false;
+}
+
+void CXXNameMangler::addSubstitution(QualType T) {
+ if (!T.getCVRQualifiers()) {
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ addSubstitution(RT->getDecl());
+ return;
+ }
+ }
+
+ uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ addSubstitution(TypePtr);
+}
+
+void CXXNameMangler::addSubstitution(TemplateName Template) {
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return addSubstitution(TD);
+
+ Template = Context.getASTContext().getCanonicalTemplateName(Template);
+ addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
+void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
+ assert(!Substitutions.count(Ptr) && "Substitution already exists!");
+ Substitutions[Ptr] = SeqID++;
+}
+
+//
+
+/// \brief Mangles the name of the declaration D and emits that name to the
+/// given output stream.
+///
+/// If the declaration D requires a mangled name, this routine will emit that
+/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
+/// and this routine will return false. In this case, the caller should just
+/// emit the identifier of the declaration (\c D->getIdentifier()) as its
+/// name.
+void ItaniumMangleContext::mangleName(const NamedDecl *D,
+ llvm::raw_ostream &Out) {
+ assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
+ "Invalid mangleName() call, argument is not a variable or function!");
+ assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
+ "Invalid mangleName() call on 'structor decl!");
+
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ getASTContext().getSourceManager(),
+ "Mangling declaration");
+
+ CXXNameMangler Mangler(*this, Out);
+ return Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ llvm::raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Type);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type,
+ llvm::raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Type);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // # first call-offset is 'this' adjustment
+ // # second call-offset is result adjustment
+
+ assert(!isa<CXXDestructorDecl>(MD) &&
+ "Use mangleCXXDtor for destructor decls!");
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZT";
+ if (!Thunk.Return.isEmpty())
+ Mangler.getStream() << 'c';
+
+ // Mangle the 'this' pointer adjustment.
+ Mangler.mangleCallOffset(Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset);
+
+ // Mangle the return pointer adjustment if there is one.
+ if (!Thunk.Return.isEmpty())
+ Mangler.mangleCallOffset(Thunk.Return.NonVirtual,
+ Thunk.Return.VBaseOffsetOffset);
+
+ Mangler.mangleFunctionEncoding(MD);
+}
+
+void
+ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ CXXNameMangler Mangler(*this, Out, DD, Type);
+ Mangler.getStream() << "_ZT";
+
+ // Mangle the 'this' pointer adjustment.
+ Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
+ ThisAdjustment.VCallOffsetOffset);
+
+ Mangler.mangleFunctionEncoding(DD);
+}
+
+/// mangleGuardVariable - Returns the mangled name for a guard variable
+/// for the passed in VarDecl.
+void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= GV <object name> # Guard variable for one-time
+ // # initialization
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZGV";
+ Mangler.mangleName(D);
+}
+
+void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,
+ llvm::raw_ostream &Out) {
+ // We match the GCC mangling here.
+ // <special-name> ::= GR <object name>
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZGR";
+ Mangler.mangleName(D);
+}
+
+void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= TV <type> # virtual table
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTV";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+}
+
+void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= TT <type> # VTT structure
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTT";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+}
+
+void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
+ int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= TC <type> <offset number> _ <base type>
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTC";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+ Mangler.getStream() << Offset;
+ Mangler.getStream() << '_';
+ Mangler.mangleNameOrStandardSubstitution(Type);
+}
+
+void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= TI <type> # typeinfo structure
+ assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTI";
+ Mangler.mangleType(Ty);
+}
+
+void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,
+ llvm::raw_ostream &Out) {
+ // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTS";
+ Mangler.mangleType(Ty);
+}
+
+MangleContext *clang::createItaniumMangleContext(ASTContext &Context,
+ Diagnostic &Diags) {
+ return new ItaniumMangleContext(Context, Diags);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
new file mode 100644
index 0000000..3a0b909
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
@@ -0,0 +1,135 @@
+//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements generic name mangling support for blocks and Objective-C.
+//
+//===----------------------------------------------------------------------===//
+#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 "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define MANGLE_CHECKER 0
+
+#if MANGLE_CHECKER
+#include <cxxabi.h>
+#endif
+
+using namespace clang;
+
+// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
+// much to be desired. Come up with a better mangling scheme.
+
+namespace {
+
+static void mangleFunctionBlock(MangleContext &Context,
+ llvm::StringRef Outer,
+ const BlockDecl *BD,
+ llvm::raw_ostream &Out) {
+ Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true);
+}
+
+static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) {
+#ifndef NDEBUG
+ const DeclContext *ExpectedDC = BD->getDeclContext();
+ while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC))
+ ExpectedDC = ExpectedDC->getParent();
+ assert(DC == ExpectedDC && "Given decl context did not match expected!");
+#endif
+}
+
+}
+
+void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
+ llvm::raw_ostream &Out) {
+ Out << "__block_global_" << getBlockId(BD, false);
+}
+
+void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
+ CXXCtorType CT, const BlockDecl *BD,
+ llvm::raw_ostream &ResStream) {
+ checkMangleDC(CD, BD);
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ mangleCXXCtor(CD, CT, Out);
+ Out.flush();
+ mangleFunctionBlock(*this, Buffer, BD, ResStream);
+}
+
+void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
+ CXXDtorType DT, const BlockDecl *BD,
+ llvm::raw_ostream &ResStream) {
+ checkMangleDC(DD, BD);
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ mangleCXXDtor(DD, DT, Out);
+ Out.flush();
+ mangleFunctionBlock(*this, Buffer, BD, ResStream);
+}
+
+void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
+ llvm::raw_ostream &Out) {
+ assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
+ checkMangleDC(DC, BD);
+
+ llvm::SmallString<64> Buffer;
+ llvm::raw_svector_ostream Stream(Buffer);
+ if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
+ mangleObjCMethodName(Method, Stream);
+ } else {
+ const NamedDecl *ND = cast<NamedDecl>(DC);
+ if (IdentifierInfo *II = ND->getIdentifier())
+ Stream << II->getName();
+ else {
+ // FIXME: We were doing a mangleUnqualifiedName() before, but that's
+ // a private member of a class that will soon itself be private to the
+ // Itanium C++ ABI object. What should we do now? Right now, I'm just
+ // calling the mangleName() method on the MangleContext; is there a
+ // better way?
+ mangleName(ND, Stream);
+ }
+ }
+ Stream.flush();
+ mangleFunctionBlock(*this, Buffer, BD, Out);
+}
+
+void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
+ llvm::raw_ostream &Out) {
+ llvm::SmallString<64> Name;
+ llvm::raw_svector_ostream OS(Name);
+
+ const ObjCContainerDecl *CD =
+ dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
+ assert (CD && "Missing container decl in GetNameForMethod");
+ OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName();
+ if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD))
+ OS << '(' << CID << ')';
+ OS << ' ' << MD->getSelector().getAsString() << ']';
+
+ Out << OS.str().size() << OS.str();
+}
+
+void MangleContext::mangleBlock(const BlockDecl *BD,
+ llvm::raw_ostream &Out) {
+ const DeclContext *DC = BD->getDeclContext();
+ while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
+ DC = DC->getParent();
+ if (DC->isFunctionOrMethod())
+ mangleBlock(DC, BD, Out);
+ else
+ mangleGlobalBlock(BD, Out);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
new file mode 100644
index 0000000..4de93bb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -0,0 +1,71 @@
+//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Microsoft Visual C++
+// ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang;
+
+namespace {
+class MicrosoftCXXABI : public CXXABI {
+ ASTContext &Context;
+public:
+ MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const;
+
+ CallingConv getDefaultMethodCallConv() const {
+ if (Context.Target.getTriple().getArch() == llvm::Triple::x86)
+ return CC_X86ThisCall;
+ else
+ return CC_C;
+ }
+
+ bool isNearlyEmpty(const CXXRecordDecl *RD) const {
+ // FIXME: Audit the corners
+ if (!RD->isDynamicClass())
+ return false;
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // In the Microsoft ABI, classes can have one or two vtable pointers.
+ CharUnits PointerSize =
+ Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0));
+ return Layout.getNonVirtualSize() == PointerSize ||
+ Layout.getNonVirtualSize() == PointerSize * 2;
+ }
+};
+}
+
+unsigned MicrosoftCXXABI::getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ if (RD->getNumVBases() > 0) {
+ if (Pointee->isFunctionType())
+ return 3;
+ else
+ return 2;
+ } else if (RD->getNumBases() > 1 && Pointee->isFunctionType())
+ return 2;
+ return 1;
+}
+
+CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
+ return new MicrosoftCXXABI(Ctx);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
new file mode 100644
index 0000000..4bf7f23
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -0,0 +1,1188 @@
+//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ name mangling targetting the Microsoft Visual C++ ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Mangle.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.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"
+
+using namespace clang;
+
+namespace {
+
+/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftCXXNameMangler {
+ MangleContext &Context;
+ llvm::raw_ostream &Out;
+
+ ASTContext &getASTContext() const { return Context.getASTContext(); }
+
+public:
+ MicrosoftCXXNameMangler(MangleContext &C, llvm::raw_ostream &Out_)
+ : Context(C), Out(Out_) { }
+
+ void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?");
+ void mangleName(const NamedDecl *ND);
+ void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleVariableEncoding(const VarDecl *VD);
+ void mangleNumber(int64_t Number);
+ void mangleType(QualType T);
+
+private:
+ void mangleUnqualifiedName(const NamedDecl *ND) {
+ mangleUnqualifiedName(ND, ND->getDeclName());
+ }
+ void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
+ void mangleSourceName(const IdentifierInfo *II);
+ void manglePostfix(const DeclContext *DC, bool NoFunction=false);
+ void mangleOperatorName(OverloadedOperatorKind OO);
+ void mangleQualifiers(Qualifiers Quals, bool IsMember);
+
+ 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(const FunctionType *T, const FunctionDecl *D,
+ bool IsStructor, bool IsInstMethod);
+ void mangleType(const ArrayType *T, bool IsGlobal);
+ void mangleExtraDimensions(QualType T);
+ void mangleFunctionClass(const FunctionDecl *FD);
+ void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
+ void mangleThrowSpecification(const FunctionProtoType *T);
+
+};
+
+/// MicrosoftMangleContext - Overrides the default MangleContext for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftMangleContext : public MangleContext {
+public:
+ MicrosoftMangleContext(ASTContext &Context,
+ Diagnostic &Diags) : MangleContext(Context, Diags) { }
+ virtual bool shouldMangleDeclName(const NamedDecl *D);
+ virtual void mangleName(const NamedDecl *D, llvm::raw_ostream &Out);
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &);
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ llvm::raw_ostream &);
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &);
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &);
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &);
+ virtual void mangleCXXRTTI(QualType T, llvm::raw_ostream &);
+ virtual void mangleCXXRTTIName(QualType T, llvm::raw_ostream &);
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ llvm::raw_ostream &);
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ llvm::raw_ostream &);
+ virtual void mangleReferenceTemporary(const clang::VarDecl *,
+ llvm::raw_ostream &);
+};
+
+}
+
+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<LinkageSpecDecl>(DC))
+ return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
+ }
+
+ return false;
+}
+
+bool MicrosoftMangleContext::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<AsmLabelAttr>())
+ 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<FunctionDecl>(D);
+ if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(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 internal linkage are not mangled.
+ if (!FD) {
+ const DeclContext *DC = D->getDeclContext();
+ if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
+ return false;
+ }
+
+ // C functions and "main" are not mangled.
+ if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
+ return false;
+
+ return true;
+}
+
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
+ llvm::StringRef Prefix) {
+ // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
+ // Therefore it's really important that we don't decorate the
+ // name with leading underscores or leading/trailing at signs. So, emit a
+ // asm marker at the start so we get the name right.
+ Out << '\01'; // LLVM IR Marker for __asm("foo")
+
+ // 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<AsmLabelAttr>()) {
+ // If we have an asm name, then we use it as the mangling.
+ Out << ALA->getLabel();
+ return;
+ }
+
+ // <mangled-name> ::= ? <name> <type-encoding>
+ Out << Prefix;
+ mangleName(D);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ mangleFunctionEncoding(FD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ mangleVariableEncoding(VD);
+ // TODO: Fields? Can MSVC even mangle them?
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <type-encoding> ::= <function-class> <function-type>
+
+ // Don't mangle in the type if this isn't a decl we should typically mangle.
+ if (!Context.shouldMangleDeclName(FD))
+ return;
+
+ // We should never ever see a FunctionNoProtoType at this point.
+ // We don't even know how to mangle their types anyway :).
+ const FunctionProtoType *FT = cast<FunctionProtoType>(FD->getType());
+
+ bool InStructor = false, InInstMethod = false;
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (MD) {
+ if (MD->isInstance())
+ InInstMethod = true;
+ if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ InStructor = true;
+ }
+
+ // First, the function class.
+ mangleFunctionClass(FD);
+
+ mangleType(FT, FD, InStructor, InInstMethod);
+}
+
+void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
+ // <type-encoding> ::= <storage-class> <variable-type>
+ // <storage-class> ::= 0 # private static member
+ // ::= 1 # protected static member
+ // ::= 2 # public static member
+ // ::= 3 # global
+ // ::= 4 # static local
+
+ // The first character in the encoding (after the name) is the storage class.
+ if (VD->isStaticDataMember()) {
+ // If it's a static member, it also encodes the access level.
+ switch (VD->getAccess()) {
+ default:
+ case AS_private: Out << '0'; break;
+ case AS_protected: Out << '1'; break;
+ case AS_public: Out << '2'; break;
+ }
+ }
+ else if (!VD->isStaticLocal())
+ Out << '3';
+ else
+ Out << '4';
+ // Now mangle the type.
+ // <variable-type> ::= <type> <cvr-qualifiers>
+ // ::= <type> A # pointers, references, arrays
+ // Pointers and references are odd. The type of 'int * const foo;' gets
+ // mangled as 'QAHA' instead of 'PAHB', for example.
+ QualType Ty = VD->getType();
+ if (Ty->isPointerType() || Ty->isReferenceType()) {
+ mangleType(Ty);
+ Out << 'A';
+ } else if (Ty->isArrayType()) {
+ // Global arrays are funny, too.
+ mangleType(cast<ArrayType>(Ty.getTypePtr()), true);
+ Out << 'A';
+ } else {
+ mangleType(Ty.getLocalUnqualifiedType());
+ mangleQualifiers(Ty.getLocalQualifiers(), false);
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
+ // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
+ const DeclContext *DC = ND->getDeclContext();
+
+ // Always start with the unqualified name.
+ mangleUnqualifiedName(ND);
+
+ // If this is an extern variable declared locally, the relevant DeclContext
+ // is that of the containing namespace, or the translation unit.
+ if (isa<FunctionDecl>(DC) && ND->hasLinkage())
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = DC->getParent();
+
+ manglePostfix(DC);
+
+ // Terminate the whole name with an '@'.
+ Out << '@';
+}
+
+void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
+ // <number> ::= [?] <decimal digit> # <= 9
+ // ::= [?] <hex digit>+ @ # > 9; A = 0, B = 1, etc...
+ if (Number < 0) {
+ Out << '?';
+ Number = -Number;
+ }
+ if (Number >= 1 && Number <= 10) {
+ Out << Number-1;
+ } else {
+ // We have to build up the encoding in reverse order, so it will come
+ // out right when we write it out.
+ char Encoding[16];
+ char *EndPtr = Encoding+sizeof(Encoding);
+ char *CurPtr = EndPtr;
+ while (Number) {
+ *--CurPtr = 'A' + (Number % 16);
+ Number /= 16;
+ }
+ Out.write(CurPtr, EndPtr-CurPtr);
+ Out << '@';
+ }
+}
+
+void
+MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+ DeclarationName Name) {
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier: {
+ if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ 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<NamespaceDecl>(ND)) {
+ if (NS->isAnonymousNamespace()) {
+ Out << "?A";
+ break;
+ }
+ }
+
+ // We must have an anonymous struct.
+ const TagDecl *TD = cast<TagDecl>(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;
+ }
+
+ // When VC encounters an anonymous type with no tag and no typedef,
+ // it literally emits '<unnamed-tag>'.
+ Out << "<unnamed-tag>";
+ break;
+ }
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ assert(false && "Can't mangle Objective-C selector names here!");
+ break;
+
+ case DeclarationName::CXXConstructorName:
+ assert(false && "Can't mangle constructors yet!");
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ assert(false && "Can't mangle destructors yet!");
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= ?B # (cast)
+ // The target type is encoded as the return type.
+ Out << "?B";
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ mangleOperatorName(Name.getCXXOverloadedOperator());
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
+ assert(false && "Don't know how to mangle literal operators yet!");
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ assert(false && "Can't mangle a using directive name!");
+ break;
+ }
+}
+
+void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
+ bool NoFunction) {
+ // <postfix> ::= <unqualified-name> [<postfix>]
+ // ::= <template-postfix> <template-args> [<postfix>]
+ // ::= <template-param>
+ // ::= <substitution> [<postfix>]
+
+ if (!DC) return;
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+
+ if (DC->isTranslationUnit())
+ return;
+
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
+ Context.mangleBlock(BD, Out);
+ Out << '@';
+ return manglePostfix(DC->getParent(), NoFunction);
+ }
+
+ if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
+ return;
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+ mangleObjCMethodName(Method);
+ else {
+ mangleUnqualifiedName(cast<NamedDecl>(DC));
+ manglePostfix(DC->getParent(), NoFunction);
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO) {
+ switch (OO) {
+ // ?0 # constructor
+ // ?1 # destructor
+ // <operator-name> ::= ?2 # new
+ case OO_New: Out << "?2"; break;
+ // <operator-name> ::= ?3 # delete
+ case OO_Delete: Out << "?3"; break;
+ // <operator-name> ::= ?4 # =
+ case OO_Equal: Out << "?4"; break;
+ // <operator-name> ::= ?5 # >>
+ case OO_GreaterGreater: Out << "?5"; break;
+ // <operator-name> ::= ?6 # <<
+ case OO_LessLess: Out << "?6"; break;
+ // <operator-name> ::= ?7 # !
+ case OO_Exclaim: Out << "?7"; break;
+ // <operator-name> ::= ?8 # ==
+ case OO_EqualEqual: Out << "?8"; break;
+ // <operator-name> ::= ?9 # !=
+ case OO_ExclaimEqual: Out << "?9"; break;
+ // <operator-name> ::= ?A # []
+ case OO_Subscript: Out << "?A"; break;
+ // ?B # conversion
+ // <operator-name> ::= ?C # ->
+ case OO_Arrow: Out << "?C"; break;
+ // <operator-name> ::= ?D # *
+ case OO_Star: Out << "?D"; break;
+ // <operator-name> ::= ?E # ++
+ case OO_PlusPlus: Out << "?E"; break;
+ // <operator-name> ::= ?F # --
+ case OO_MinusMinus: Out << "?F"; break;
+ // <operator-name> ::= ?G # -
+ case OO_Minus: Out << "?G"; break;
+ // <operator-name> ::= ?H # +
+ case OO_Plus: Out << "?H"; break;
+ // <operator-name> ::= ?I # &
+ case OO_Amp: Out << "?I"; break;
+ // <operator-name> ::= ?J # ->*
+ case OO_ArrowStar: Out << "?J"; break;
+ // <operator-name> ::= ?K # /
+ case OO_Slash: Out << "?K"; break;
+ // <operator-name> ::= ?L # %
+ case OO_Percent: Out << "?L"; break;
+ // <operator-name> ::= ?M # <
+ case OO_Less: Out << "?M"; break;
+ // <operator-name> ::= ?N # <=
+ case OO_LessEqual: Out << "?N"; break;
+ // <operator-name> ::= ?O # >
+ case OO_Greater: Out << "?O"; break;
+ // <operator-name> ::= ?P # >=
+ case OO_GreaterEqual: Out << "?P"; break;
+ // <operator-name> ::= ?Q # ,
+ case OO_Comma: Out << "?Q"; break;
+ // <operator-name> ::= ?R # ()
+ case OO_Call: Out << "?R"; break;
+ // <operator-name> ::= ?S # ~
+ case OO_Tilde: Out << "?S"; break;
+ // <operator-name> ::= ?T # ^
+ case OO_Caret: Out << "?T"; break;
+ // <operator-name> ::= ?U # |
+ case OO_Pipe: Out << "?U"; break;
+ // <operator-name> ::= ?V # &&
+ case OO_AmpAmp: Out << "?V"; break;
+ // <operator-name> ::= ?W # ||
+ case OO_PipePipe: Out << "?W"; break;
+ // <operator-name> ::= ?X # *=
+ case OO_StarEqual: Out << "?X"; break;
+ // <operator-name> ::= ?Y # +=
+ case OO_PlusEqual: Out << "?Y"; break;
+ // <operator-name> ::= ?Z # -=
+ case OO_MinusEqual: Out << "?Z"; break;
+ // <operator-name> ::= ?_0 # /=
+ case OO_SlashEqual: Out << "?_0"; break;
+ // <operator-name> ::= ?_1 # %=
+ case OO_PercentEqual: Out << "?_1"; break;
+ // <operator-name> ::= ?_2 # >>=
+ case OO_GreaterGreaterEqual: Out << "?_2"; break;
+ // <operator-name> ::= ?_3 # <<=
+ case OO_LessLessEqual: Out << "?_3"; break;
+ // <operator-name> ::= ?_4 # &=
+ case OO_AmpEqual: Out << "?_4"; break;
+ // <operator-name> ::= ?_5 # |=
+ case OO_PipeEqual: Out << "?_5"; break;
+ // <operator-name> ::= ?_6 # ^=
+ case OO_CaretEqual: Out << "?_6"; break;
+ // ?_7 # vftable
+ // ?_8 # vbtable
+ // ?_9 # vcall
+ // ?_A # typeof
+ // ?_B # local static guard
+ // ?_C # string
+ // ?_D # vbase destructor
+ // ?_E # vector deleting destructor
+ // ?_F # default constructor closure
+ // ?_G # scalar deleting destructor
+ // ?_H # vector constructor iterator
+ // ?_I # vector destructor iterator
+ // ?_J # vector vbase constructor iterator
+ // ?_K # virtual displacement map
+ // ?_L # eh vector constructor iterator
+ // ?_M # eh vector destructor iterator
+ // ?_N # eh vector vbase constructor iterator
+ // ?_O # copy constructor closure
+ // ?_P<name> # udt returning <name>
+ // ?_Q # <unknown>
+ // ?_R0 # RTTI Type Descriptor
+ // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)
+ // ?_R2 # RTTI Base Class Array
+ // ?_R3 # RTTI Class Hierarchy Descriptor
+ // ?_R4 # RTTI Complete Object Locator
+ // ?_S # local vftable
+ // ?_T # local vftable constructor closure
+ // <operator-name> ::= ?_U # new[]
+ case OO_Array_New: Out << "?_U"; break;
+ // <operator-name> ::= ?_V # delete[]
+ case OO_Array_Delete: Out << "?_V"; break;
+
+ case OO_Conditional:
+ assert(false && "Don't know how to mangle ?:");
+ break;
+
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ assert(false && "Not an overloaded operator");
+ break;
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+ // <source name> ::= <identifier> @
+ Out << II->getName() << '@';
+}
+
+void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
+ Context.mangleObjCMethodName(MD, Out);
+}
+
+void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
+ bool IsMember) {
+ // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
+ // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only);
+ // 'I' means __restrict (32/64-bit).
+ // Note that the MSVC __restrict keyword isn't the same as the C99 restrict
+ // keyword!
+ // <base-cvr-qualifiers> ::= A # near
+ // ::= B # near const
+ // ::= C # near volatile
+ // ::= D # near const volatile
+ // ::= E # far (16-bit)
+ // ::= F # far const (16-bit)
+ // ::= G # far volatile (16-bit)
+ // ::= H # far const volatile (16-bit)
+ // ::= I # huge (16-bit)
+ // ::= J # huge const (16-bit)
+ // ::= K # huge volatile (16-bit)
+ // ::= L # huge const volatile (16-bit)
+ // ::= M <basis> # based
+ // ::= N <basis> # based const
+ // ::= O <basis> # based volatile
+ // ::= P <basis> # based const volatile
+ // ::= Q # near member
+ // ::= R # near const member
+ // ::= S # near volatile member
+ // ::= T # near const volatile member
+ // ::= U # far member (16-bit)
+ // ::= V # far const member (16-bit)
+ // ::= W # far volatile member (16-bit)
+ // ::= X # far const volatile member (16-bit)
+ // ::= Y # huge member (16-bit)
+ // ::= Z # huge const member (16-bit)
+ // ::= 0 # huge volatile member (16-bit)
+ // ::= 1 # huge const volatile member (16-bit)
+ // ::= 2 <basis> # based member
+ // ::= 3 <basis> # based const member
+ // ::= 4 <basis> # based volatile member
+ // ::= 5 <basis> # based const volatile member
+ // ::= 6 # near function (pointers only)
+ // ::= 7 # far function (pointers only)
+ // ::= 8 # near method (pointers only)
+ // ::= 9 # far method (pointers only)
+ // ::= _A <basis> # based function (pointers only)
+ // ::= _B <basis> # based function (far?) (pointers only)
+ // ::= _C <basis> # based method (pointers only)
+ // ::= _D <basis> # based method (far?) (pointers only)
+ // ::= _E # block (Clang)
+ // <basis> ::= 0 # __based(void)
+ // ::= 1 # __based(segment)?
+ // ::= 2 <name> # __based(name)
+ // ::= 3 # ?
+ // ::= 4 # ?
+ // ::= 5 # not really based
+ if (!IsMember) {
+ if (!Quals.hasVolatile()) {
+ if (!Quals.hasConst())
+ Out << 'A';
+ else
+ Out << 'B';
+ } else {
+ if (!Quals.hasConst())
+ Out << 'C';
+ else
+ Out << 'D';
+ }
+ } else {
+ if (!Quals.hasVolatile()) {
+ if (!Quals.hasConst())
+ Out << 'Q';
+ else
+ Out << 'R';
+ } else {
+ if (!Quals.hasConst())
+ Out << 'S';
+ else
+ Out << 'T';
+ }
+ }
+
+ // FIXME: For now, just drop all extension qualifiers on the floor.
+}
+
+void MicrosoftCXXNameMangler::mangleType(QualType T) {
+ // Only operate on the canonical type!
+ T = getASTContext().getCanonicalType(T);
+
+ Qualifiers Quals = T.getLocalQualifiers();
+ if (Quals) {
+ // We have to mangle these now, while we still have enough information.
+ // <pointer-cvr-qualifiers> ::= P # pointer
+ // ::= Q # const pointer
+ // ::= R # volatile pointer
+ // ::= S # const volatile pointer
+ if (T->isAnyPointerType() || T->isMemberPointerType() ||
+ T->isBlockPointerType()) {
+ if (!Quals.hasVolatile())
+ Out << 'Q';
+ else {
+ if (!Quals.hasConst())
+ Out << 'R';
+ else
+ Out << 'S';
+ }
+ } else
+ // Just emit qualifiers like normal.
+ // NB: When we mangle a pointer/reference type, and the pointee
+ // type has no qualifiers, the lack of qualifier gets mangled
+ // in there.
+ mangleQualifiers(Quals, false);
+ } else if (T->isAnyPointerType() || T->isMemberPointerType() ||
+ T->isBlockPointerType()) {
+ Out << 'P';
+ }
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT) \
+case Type::CLASS: \
+llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
+return;
+#define TYPE(CLASS, PARENT) \
+case Type::CLASS: \
+mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \
+break;
+#include "clang/AST/TypeNodes.def"
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) {
+ // <type> ::= <builtin-type>
+ // <builtin-type> ::= X # void
+ // ::= C # signed char
+ // ::= D # char
+ // ::= E # unsigned char
+ // ::= F # short
+ // ::= G # unsigned short (or wchar_t if it's not a builtin)
+ // ::= H # int
+ // ::= I # unsigned int
+ // ::= J # long
+ // ::= K # unsigned long
+ // L # <none>
+ // ::= M # float
+ // ::= N # double
+ // ::= O # long double (__float80 is mangled differently)
+ // ::= _D # __int8 (yup, it's a distinct type in MSVC)
+ // ::= _E # unsigned __int8
+ // ::= _F # __int16
+ // ::= _G # unsigned __int16
+ // ::= _H # __int32
+ // ::= _I # unsigned __int32
+ // ::= _J # long long, __int64
+ // ::= _K # unsigned long long, __int64
+ // ::= _L # __int128
+ // ::= _M # unsigned __int128
+ // ::= _N # bool
+ // _O # <array in parameter>
+ // ::= _T # __float80 (Intel)
+ // ::= _W # wchar_t
+ // ::= _Z # __float80 (Digital Mars)
+ switch (T->getKind()) {
+ case BuiltinType::Void: Out << 'X'; break;
+ case BuiltinType::SChar: Out << 'C'; break;
+ case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;
+ case BuiltinType::UChar: Out << 'E'; break;
+ case BuiltinType::Short: Out << 'F'; break;
+ case BuiltinType::UShort: Out << 'G'; break;
+ case BuiltinType::Int: Out << 'H'; break;
+ case BuiltinType::UInt: Out << 'I'; break;
+ case BuiltinType::Long: Out << 'J'; break;
+ case BuiltinType::ULong: Out << 'K'; break;
+ case BuiltinType::Float: Out << 'M'; break;
+ case BuiltinType::Double: Out << 'N'; break;
+ // TODO: Determine size and mangle accordingly
+ case BuiltinType::LongDouble: Out << 'O'; break;
+ // TODO: __int8 and friends
+ case BuiltinType::LongLong: Out << "_J"; break;
+ case BuiltinType::ULongLong: Out << "_K"; break;
+ case BuiltinType::Int128: Out << "_L"; break;
+ case BuiltinType::UInt128: Out << "_M"; break;
+ case BuiltinType::Bool: Out << "_N"; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: Out << "_W"; break;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ assert(false &&
+ "Overloaded and dependent types shouldn't get to name mangling");
+ break;
+ case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;
+ case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;
+ case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;
+
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::NullPtr:
+ assert(false && "Don't know how to mangle this type");
+ break;
+ }
+}
+
+// <type> ::= <function-type>
+void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T) {
+ // Structors only appear in decls, so at this point we know it's not a
+ // structor type.
+ // I'll probably have mangleType(MemberPointerType) call the mangleType()
+ // method directly.
+ mangleType(T, NULL, false, false);
+}
+void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T) {
+ llvm_unreachable("Can't mangle K&R function prototypes");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
+ const FunctionDecl *D,
+ bool IsStructor,
+ bool IsInstMethod) {
+ // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
+ // <return-type> <argument-list> <throw-spec>
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
+ // If this is a C++ instance method, mangle the CVR qualifiers for the
+ // this pointer.
+ if (IsInstMethod)
+ mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
+
+ mangleCallingConvention(T, IsInstMethod);
+
+ // <return-type> ::= <type>
+ // ::= @ # structors (they have no declared return type)
+ if (IsStructor)
+ Out << '@';
+ else
+ mangleType(Proto->getResultType());
+
+ // <argument-list> ::= X # void
+ // ::= <type>+ @
+ // ::= <type>* Z # varargs
+ if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ Out << 'X';
+ } else {
+ if (D) {
+ // If we got a decl, use the "types-as-written" to make sure arrays
+ // get mangled right.
+ for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
+ ParmEnd = D->param_end();
+ Parm != ParmEnd; ++Parm)
+ mangleType((*Parm)->getTypeSourceInfo()->getType());
+ } else {
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleType(*Arg);
+ }
+ // <builtin-type> ::= Z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'Z';
+ else
+ Out << '@';
+ }
+
+ mangleThrowSpecification(Proto);
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
+ // <function-class> ::= A # private: near
+ // ::= B # private: far
+ // ::= C # private: static near
+ // ::= D # private: static far
+ // ::= E # private: virtual near
+ // ::= F # private: virtual far
+ // ::= G # private: thunk near
+ // ::= H # private: thunk far
+ // ::= I # protected: near
+ // ::= J # protected: far
+ // ::= K # protected: static near
+ // ::= L # protected: static far
+ // ::= M # protected: virtual near
+ // ::= N # protected: virtual far
+ // ::= O # protected: thunk near
+ // ::= P # protected: thunk far
+ // ::= Q # public: near
+ // ::= R # public: far
+ // ::= S # public: static near
+ // ::= T # public: static far
+ // ::= U # public: virtual near
+ // ::= V # public: virtual far
+ // ::= W # public: thunk near
+ // ::= X # public: thunk far
+ // ::= Y # global near
+ // ::= Z # global far
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ switch (MD->getAccess()) {
+ default:
+ case AS_private:
+ if (MD->isStatic())
+ Out << 'C';
+ else if (MD->isVirtual())
+ Out << 'E';
+ else
+ Out << 'A';
+ break;
+ case AS_protected:
+ if (MD->isStatic())
+ Out << 'K';
+ else if (MD->isVirtual())
+ Out << 'M';
+ else
+ Out << 'I';
+ break;
+ case AS_public:
+ if (MD->isStatic())
+ Out << 'S';
+ else if (MD->isVirtual())
+ Out << 'U';
+ else
+ Out << 'Q';
+ }
+ } else
+ Out << 'Y';
+}
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
+ bool IsInstMethod) {
+ // <calling-convention> ::= A # __cdecl
+ // ::= B # __export __cdecl
+ // ::= C # __pascal
+ // ::= D # __export __pascal
+ // ::= E # __thiscall
+ // ::= F # __export __thiscall
+ // ::= G # __stdcall
+ // ::= H # __export __stdcall
+ // ::= I # __fastcall
+ // ::= J # __export __fastcall
+ // The 'export' calling conventions are from a bygone era
+ // (*cough*Win16*cough*) when functions were declared for export with
+ // that keyword. (It didn't actually export them, it just made them so
+ // that they could be in a DLL and somebody from another module could call
+ // them.)
+ CallingConv CC = T->getCallConv();
+ if (CC == CC_Default)
+ CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C;
+ switch (CC) {
+ case CC_Default:
+ case CC_C: Out << 'A'; break;
+ case CC_X86Pascal: Out << 'C'; break;
+ case CC_X86ThisCall: Out << 'E'; break;
+ case CC_X86StdCall: Out << 'G'; break;
+ case CC_X86FastCall: Out << 'I'; break;
+ }
+}
+void MicrosoftCXXNameMangler::mangleThrowSpecification(
+ const FunctionProtoType *FT) {
+ // <throw-spec> ::= Z # throw(...) (default)
+ // ::= @ # throw() or __declspec/__attribute__((nothrow))
+ // ::= <type>+
+ // NOTE: Since the Microsoft compiler ignores throw specifications, they are
+ // all actually mangled as 'Z'. (They're ignored because their associated
+ // functionality isn't implemented, and probably never will be.)
+ Out << 'Z';
+}
+
+void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+ assert(false && "Don't know how to mangle UnresolvedUsingTypes yet!");
+}
+
+// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>
+// <union-type> ::= T <name>
+// <struct-type> ::= U <name>
+// <class-type> ::= V <name>
+// <enum-type> ::= W <size> <name>
+void MicrosoftCXXNameMangler::mangleType(const EnumType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void MicrosoftCXXNameMangler::mangleType(const RecordType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
+ switch (T->getDecl()->getTagKind()) {
+ case TTK_Union:
+ Out << 'T';
+ break;
+ case TTK_Struct:
+ Out << 'U';
+ break;
+ case TTK_Class:
+ Out << 'V';
+ break;
+ case TTK_Enum:
+ Out << 'W';
+ Out << getASTContext().getTypeSizeInChars(
+ cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();
+ break;
+ }
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <array-type>
+// <array-type> ::= P <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+// <element-type> # as global
+// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+// <element-type> # as param
+// It's supposed to be the other way around, but for some strange reason, it
+// isn't. Today this behavior is retained for the sole purpose of backwards
+// compatibility.
+void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
+ // This isn't a recursive mangling, so now we have to do it all in this
+ // one call.
+ if (IsGlobal)
+ Out << 'P';
+ else
+ Out << 'Q';
+ mangleExtraDimensions(T->getElementType());
+}
+void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T) {
+ mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T) {
+ mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T) {
+ mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T) {
+ mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
+ llvm::SmallVector<llvm::APInt, 3> Dimensions;
+ for (;;) {
+ if (ElementTy->isConstantArrayType()) {
+ const ConstantArrayType *CAT =
+ static_cast<const ConstantArrayType *>(ElementTy.getTypePtr());
+ Dimensions.push_back(CAT->getSize());
+ ElementTy = CAT->getElementType();
+ } else if (ElementTy->isVariableArrayType()) {
+ assert(false && "Don't know how to mangle VLAs!");
+ } else if (ElementTy->isDependentSizedArrayType()) {
+ // The dependent expression has to be folded into a constant (TODO).
+ assert(false && "Don't know how to mangle dependent-sized arrays!");
+ } else if (ElementTy->isIncompleteArrayType()) continue;
+ else break;
+ }
+ mangleQualifiers(ElementTy.getQualifiers(), false);
+ // If there are any additional dimensions, mangle them now.
+ if (Dimensions.size() > 0) {
+ Out << 'Y';
+ // <dimension-count> ::= <number> # number of extra dimensions
+ mangleNumber(Dimensions.size());
+ for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {
+ mangleNumber(Dimensions[Dim].getLimitedValue());
+ }
+ }
+ mangleType(ElementTy.getLocalUnqualifiedType());
+}
+
+// <type> ::= <pointer-to-member-type>
+// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
+// <class name> <type>
+void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T) {
+ QualType PointeeType = T->getPointeeType();
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
+ Out << '8';
+ mangleName(cast<RecordType>(T->getClass())->getDecl());
+ mangleType(FPT, NULL, false, true);
+ } else {
+ mangleQualifiers(PointeeType.getQualifiers(), true);
+ mangleName(cast<RecordType>(T->getClass())->getDecl());
+ mangleType(PointeeType.getLocalUnqualifiedType());
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T) {
+ assert(false && "Don't know how to mangle TemplateTypeParmTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(
+ const SubstTemplateTypeParmPackType *T) {
+ assert(false &&
+ "Don't know how to mangle SubstTemplateTypeParmPackTypes yet!");
+}
+
+// <type> ::= <pointer-type>
+// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const PointerType *T) {
+ QualType PointeeTy = T->getPointeeType();
+ if (PointeeTy->isArrayType()) {
+ // Pointers to arrays are mangled like arrays.
+ mangleExtraDimensions(T->getPointeeType());
+ } else if (PointeeTy->isFunctionType()) {
+ // Function pointers are special.
+ Out << '6';
+ mangleType(static_cast<const FunctionType *>(PointeeTy.getTypePtr()),
+ NULL, false, false);
+ } else {
+ if (!PointeeTy.hasQualifiers())
+ // Lack of qualifiers is mangled as 'A'.
+ Out << 'A';
+ mangleType(PointeeTy);
+ }
+}
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
+ // Object pointers never have qualifiers.
+ Out << 'A';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= <reference-type>
+// <reference-type> ::= A <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T) {
+ Out << 'A';
+ QualType PointeeTy = T->getPointeeType();
+ if (!PointeeTy.hasQualifiers())
+ // Lack of qualifiers is mangled as 'A'.
+ Out << 'A';
+ mangleType(PointeeTy);
+}
+
+void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T) {
+ assert(false && "Don't know how to mangle RValueReferenceTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ComplexType *T) {
+ assert(false && "Don't know how to mangle ComplexTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const VectorType *T) {
+ assert(false && "Don't know how to mangle VectorTypes yet!");
+}
+void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T) {
+ assert(false && "Don't know how to mangle ExtVectorTypes yet!");
+}
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
+ assert(false && "Don't know how to mangle DependentSizedExtVectorTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T) {
+ // ObjC interfaces have structs underlying them.
+ Out << 'U';
+ mangleName(T->getDecl());
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T) {
+ // We don't allow overloading by different protocol qualification,
+ // so mangling them isn't necessary.
+ mangleType(T->getBaseType());
+}
+
+void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T) {
+ Out << "_E";
+ mangleType(T->getPointeeType());
+}
+
+void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T) {
+ assert(false && "Don't know how to mangle InjectedClassNameTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T) {
+ assert(false && "Don't know how to mangle TemplateSpecializationTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T) {
+ assert(false && "Don't know how to mangle DependentNameTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(
+ const DependentTemplateSpecializationType *T) {
+ assert(false &&
+ "Don't know how to mangle DependentTemplateSpecializationTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T) {
+ assert(false && "Don't know how to mangle PackExpansionTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T) {
+ assert(false && "Don't know how to mangle TypeOfTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T) {
+ assert(false && "Don't know how to mangle TypeOfExprTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) {
+ assert(false && "Don't know how to mangle DecltypeTypes yet!");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const AutoType *T) {
+ assert(false && "Don't know how to mangle AutoTypes yet!");
+}
+
+void MicrosoftMangleContext::mangleName(const NamedDecl *D,
+ llvm::raw_ostream &Out) {
+ assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
+ "Invalid mangleName() call, argument is not a variable or function!");
+ assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
+ "Invalid mangleName() call on 'structor decl!");
+
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ getASTContext().getSourceManager(),
+ "Mangling declaration");
+
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ return Mangler.mangle(D);
+}
+void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle thunks!");
+}
+void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const ThisAdjustment &,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle destructor thunks!");
+}
+void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle virtual tables!");
+}
+void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
+ llvm::raw_ostream &) {
+ llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
+}
+void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
+ int64_t Offset,
+ const CXXRecordDecl *Type,
+ llvm::raw_ostream &) {
+ llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
+}
+void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle RTTI!");
+}
+void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle RTTI names!");
+}
+void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle constructors!");
+}
+void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle destructors!");
+}
+void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *,
+ llvm::raw_ostream &) {
+ assert(false && "Can't yet mangle reference temporaries!");
+}
+
+MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
+ Diagnostic &Diags) {
+ return new MicrosoftMangleContext(Context, Diags);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
new file mode 100644
index 0000000..650321d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -0,0 +1,201 @@
+//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NestedNameSpecifier class, which represents
+// a C++ nested-name-specifier.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+
+using namespace clang;
+
+NestedNameSpecifier *
+NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
+ const NestedNameSpecifier &Mockup) {
+ llvm::FoldingSetNodeID ID;
+ Mockup.Profile(ID);
+
+ void *InsertPos = 0;
+ NestedNameSpecifier *NNS
+ = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
+ if (!NNS) {
+ NNS = new (Context, 4) NestedNameSpecifier(Mockup);
+ Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
+ }
+
+ return NNS;
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix, IdentifierInfo *II) {
+ assert(II && "Identifier cannot be NULL");
+ assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
+
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(Prefix);
+ Mockup.Prefix.setInt(Identifier);
+ Mockup.Specifier = II;
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix, NamespaceDecl *NS) {
+ assert(NS && "Namespace cannot be NULL");
+ assert((!Prefix ||
+ (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+ "Broken nested name specifier");
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(Prefix);
+ Mockup.Prefix.setInt(Namespace);
+ Mockup.Specifier = NS;
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ bool Template, const Type *T) {
+ assert(T && "Type cannot be NULL");
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(Prefix);
+ Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec);
+ Mockup.Specifier = const_cast<Type*>(T);
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
+ assert(II && "Identifier cannot be NULL");
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(0);
+ Mockup.Prefix.setInt(Identifier);
+ Mockup.Specifier = II;
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
+ if (!Context.GlobalNestedNameSpecifier)
+ Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier();
+ return Context.GlobalNestedNameSpecifier;
+}
+
+/// \brief Whether this nested name specifier refers to a dependent
+/// type or not.
+bool NestedNameSpecifier::isDependent() const {
+ switch (getKind()) {
+ case Identifier:
+ // Identifier specifiers always represent dependent types
+ return true;
+
+ case Namespace:
+ case Global:
+ return false;
+
+ case TypeSpec:
+ case TypeSpecWithTemplate:
+ return getAsType()->isDependentType();
+ }
+
+ // Necessary to suppress a GCC warning.
+ return false;
+}
+
+bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
+ switch (getKind()) {
+ case Identifier:
+ return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
+
+ case Namespace:
+ case Global:
+ return false;
+
+ case TypeSpec:
+ case TypeSpecWithTemplate:
+ return getAsType()->containsUnexpandedParameterPack();
+ }
+
+ // Necessary to suppress a GCC warning.
+ return false;
+}
+
+/// \brief Print this nested name specifier to the given output
+/// stream.
+void
+NestedNameSpecifier::print(llvm::raw_ostream &OS,
+ const PrintingPolicy &Policy) const {
+ if (getPrefix())
+ getPrefix()->print(OS, Policy);
+
+ switch (getKind()) {
+ case Identifier:
+ OS << getAsIdentifier()->getName();
+ break;
+
+ case Namespace:
+ OS << getAsNamespace()->getIdentifier()->getName();
+ break;
+
+ case Global:
+ break;
+
+ case TypeSpecWithTemplate:
+ OS << "template ";
+ // Fall through to print the type.
+
+ case TypeSpec: {
+ std::string TypeStr;
+ const Type *T = getAsType();
+
+ PrintingPolicy InnerPolicy(Policy);
+ InnerPolicy.SuppressScope = true;
+
+ // Nested-name-specifiers are intended to contain minimally-qualified
+ // types. An actual ElaboratedType will not occur, since we'll store
+ // just the type that is referred to in the nested-name-specifier (e.g.,
+ // a TypedefType, TagType, etc.). However, when we are dealing with
+ // dependent template-id types (e.g., Outer<T>::template Inner<U>),
+ // the type requires its own nested-name-specifier for uniqueness, so we
+ // suppress that nested-name-specifier during printing.
+ assert(!isa<ElaboratedType>(T) &&
+ "Elaborated type in nested-name-specifier");
+ if (const TemplateSpecializationType *SpecType
+ = dyn_cast<TemplateSpecializationType>(T)) {
+ // Print the template name without its corresponding
+ // nested-name-specifier.
+ SpecType->getTemplateName().print(OS, InnerPolicy, true);
+
+ // Print the template argument list.
+ TypeStr = TemplateSpecializationType::PrintTemplateArgumentList(
+ SpecType->getArgs(),
+ SpecType->getNumArgs(),
+ InnerPolicy);
+ } else {
+ // Print the type normally
+ TypeStr = QualType(T, 0).getAsString(InnerPolicy);
+ }
+ OS << TypeStr;
+ break;
+ }
+ }
+
+ OS << "::";
+}
+
+void NestedNameSpecifier::dump(const LangOptions &LO) {
+ print(llvm::errs(), PrintingPolicy(LO));
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
new file mode 100644
index 0000000..eca351a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp
@@ -0,0 +1,109 @@
+//===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- 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 ParentMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "llvm/ADT/DenseMap.h"
+
+using namespace clang;
+
+typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
+
+static void BuildParentMap(MapTy& M, Stmt* S) {
+ for (Stmt::child_range I = S->children(); I; ++I)
+ if (*I) {
+ M[*I] = S;
+ BuildParentMap(M, *I);
+ }
+}
+
+ParentMap::ParentMap(Stmt* S) : Impl(0) {
+ if (S) {
+ MapTy *M = new MapTy();
+ BuildParentMap(*M, S);
+ Impl = M;
+ }
+}
+
+ParentMap::~ParentMap() {
+ delete (MapTy*) Impl;
+}
+
+void ParentMap::addStmt(Stmt* S) {
+ if (S) {
+ BuildParentMap(*(MapTy*) Impl, S);
+ }
+}
+
+Stmt* ParentMap::getParent(Stmt* S) const {
+ MapTy* M = (MapTy*) Impl;
+ MapTy::iterator I = M->find(S);
+ return I == M->end() ? 0 : I->second;
+}
+
+Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
+ do { S = getParent(S); } while (S && isa<ParenExpr>(S));
+ return S;
+}
+
+Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
+ do {
+ S = getParent(S);
+ }
+ while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
+
+ return S;
+}
+
+bool ParentMap::isConsumedExpr(Expr* E) const {
+ Stmt *P = getParent(E);
+ Stmt *DirectChild = E;
+
+ // Ignore parents that are parentheses or casts.
+ while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
+ DirectChild = P;
+ P = getParent(P);
+ }
+
+ if (!P)
+ return false;
+
+ switch (P->getStmtClass()) {
+ default:
+ return isa<Expr>(P);
+ case Stmt::DeclStmtClass:
+ return true;
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator *BE = cast<BinaryOperator>(P);
+ // If it is a comma, only the right side is consumed.
+ // If it isn't a comma, both sides are consumed.
+ return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
+ }
+ case Stmt::ForStmtClass:
+ return DirectChild == cast<ForStmt>(P)->getCond();
+ case Stmt::WhileStmtClass:
+ return DirectChild == cast<WhileStmt>(P)->getCond();
+ case Stmt::DoStmtClass:
+ return DirectChild == cast<DoStmt>(P)->getCond();
+ case Stmt::IfStmtClass:
+ return DirectChild == cast<IfStmt>(P)->getCond();
+ case Stmt::IndirectGotoStmtClass:
+ return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
+ case Stmt::SwitchStmtClass:
+ return DirectChild == cast<SwitchStmt>(P)->getCond();
+ case Stmt::ReturnStmtClass:
+ return true;
+ }
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
new file mode 100644
index 0000000..035c48f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp
@@ -0,0 +1,81 @@
+//===-- RecordLayout.cpp - Layout information for a struct/union -*- 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 RecordLayout interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+
+using namespace clang;
+
+void ASTRecordLayout::Destroy(ASTContext &Ctx) {
+ if (FieldOffsets)
+ Ctx.Deallocate(FieldOffsets);
+ if (CXXInfo) {
+ Ctx.Deallocate(CXXInfo);
+ CXXInfo->~CXXRecordLayoutInfo();
+ }
+ this->~ASTRecordLayout();
+ Ctx.Deallocate(this);
+}
+
+ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size,
+ CharUnits alignment, CharUnits datasize,
+ const uint64_t *fieldoffsets,
+ unsigned fieldcount)
+ : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
+ FieldCount(fieldcount), CXXInfo(0) {
+ if (FieldCount > 0) {
+ FieldOffsets = new (Ctx) uint64_t[FieldCount];
+ memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets));
+ }
+}
+
+// Constructor for C++ records.
+ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
+ CharUnits size, CharUnits alignment,
+ CharUnits datasize,
+ const uint64_t *fieldoffsets,
+ unsigned fieldcount,
+ CharUnits nonvirtualsize,
+ CharUnits nonvirtualalign,
+ CharUnits SizeOfLargestEmptySubobject,
+ const CXXRecordDecl *PrimaryBase,
+ bool IsPrimaryBaseVirtual,
+ const BaseOffsetsMapTy& BaseOffsets,
+ const BaseOffsetsMapTy& VBaseOffsets)
+ : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment),
+ FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo)
+{
+ if (FieldCount > 0) {
+ FieldOffsets = new (Ctx) uint64_t[FieldCount];
+ memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets));
+ }
+
+ CXXInfo->PrimaryBase.setPointer(PrimaryBase);
+ CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual);
+ CXXInfo->NonVirtualSize = nonvirtualsize;
+ CXXInfo->NonVirtualAlign = nonvirtualalign;
+ CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject;
+ CXXInfo->BaseOffsets = BaseOffsets;
+ CXXInfo->VBaseOffsets = VBaseOffsets;
+
+#ifndef NDEBUG
+ if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) {
+ if (isPrimaryBaseVirtual())
+ assert(getVBaseClassOffset(PrimaryBase).isZero() &&
+ "Primary virtual base must be at offset 0!");
+ else
+ assert(getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base must be at offset 0!");
+ }
+#endif
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
new file mode 100644
index 0000000..cf14eba
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -0,0 +1,1908 @@
+//=== RecordLayoutBuilder.cpp - Helper class for building record layouts ---==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/Support/Format.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/MathExtras.h"
+#include <map>
+
+using namespace clang;
+
+namespace {
+
+/// BaseSubobjectInfo - Represents a single base subobject in a complete class.
+/// For a class hierarchy like
+///
+/// class A { };
+/// class B : A { };
+/// class C : A, B { };
+///
+/// The BaseSubobjectInfo graph for C will have three BaseSubobjectInfo
+/// instances, one for B and two for A.
+///
+/// If a base is virtual, it will only have one BaseSubobjectInfo allocated.
+struct BaseSubobjectInfo {
+ /// Class - The class for this base info.
+ const CXXRecordDecl *Class;
+
+ /// IsVirtual - Whether the BaseInfo represents a virtual base or not.
+ bool IsVirtual;
+
+ /// Bases - Information about the base subobjects.
+ llvm::SmallVector<BaseSubobjectInfo*, 4> Bases;
+
+ /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
+ /// of this base info (if one exists).
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo;
+
+ // FIXME: Document.
+ const BaseSubobjectInfo *Derived;
+};
+
+/// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
+/// offsets while laying out a C++ class.
+class EmptySubobjectMap {
+ const ASTContext &Context;
+ uint64_t CharWidth;
+
+ /// Class - The class whose empty entries we're keeping track of.
+ const CXXRecordDecl *Class;
+
+ /// EmptyClassOffsets - A map from offsets to empty record decls.
+ typedef llvm::SmallVector<const CXXRecordDecl *, 1> ClassVectorTy;
+ typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
+ EmptyClassOffsetsMapTy EmptyClassOffsets;
+
+ /// MaxEmptyClassOffset - The highest offset known to contain an empty
+ /// base subobject.
+ CharUnits MaxEmptyClassOffset;
+
+ /// ComputeEmptySubobjectSizes - Compute the size of the largest base or
+ /// member subobject that is empty.
+ void ComputeEmptySubobjectSizes();
+
+ void AddSubobjectAtOffset(const CXXRecordDecl *RD, CharUnits Offset);
+
+ void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
+ CharUnits Offset, bool PlacingEmptyBase);
+
+ void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ CharUnits Offset);
+ void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset);
+
+ /// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty
+ /// subobjects beyond the given offset.
+ bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const {
+ return Offset <= MaxEmptyClassOffset;
+ }
+
+ CharUnits
+ getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
+ uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
+ assert(FieldOffset % CharWidth == 0 &&
+ "Field offset not at char boundary!");
+
+ return Context.toCharUnitsFromBits(FieldOffset);
+ }
+
+protected:
+ bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ CharUnits Offset) const;
+
+ bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
+ CharUnits Offset);
+
+ bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ CharUnits Offset) const;
+ bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ CharUnits Offset) const;
+
+public:
+ /// This holds the size of the largest empty subobject (either a base
+ /// or a member). Will be zero if the record being built doesn't contain
+ /// any empty classes.
+ CharUnits SizeOfLargestEmptySubobject;
+
+ EmptySubobjectMap(const ASTContext &Context, const CXXRecordDecl *Class)
+ : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) {
+ ComputeEmptySubobjectSizes();
+ }
+
+ /// CanPlaceBaseAtOffset - Return whether the given base class can be placed
+ /// at the given offset.
+ /// Returns false if placing the record will result in two components
+ /// (direct or indirect) of the same type having the same offset.
+ bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
+ CharUnits Offset);
+
+ /// CanPlaceFieldAtOffset - Return whether a field can be placed at the given
+ /// offset.
+ bool CanPlaceFieldAtOffset(const FieldDecl *FD, CharUnits Offset);
+};
+
+void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
+ // Check the bases.
+ for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
+ E = Class->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits EmptySize;
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
+ if (BaseDecl->isEmpty()) {
+ // If the class decl is empty, get its size.
+ EmptySize = Layout.getSize();
+ } else {
+ // Otherwise, we get the largest empty subobject for the decl.
+ EmptySize = Layout.getSizeOfLargestEmptySubobject();
+ }
+
+ if (EmptySize > SizeOfLargestEmptySubobject)
+ SizeOfLargestEmptySubobject = EmptySize;
+ }
+
+ // Check the fields.
+ for (CXXRecordDecl::field_iterator I = Class->field_begin(),
+ E = Class->field_end(); I != E; ++I) {
+ const FieldDecl *FD = *I;
+
+ const RecordType *RT =
+ Context.getBaseElementType(FD->getType())->getAs<RecordType>();
+
+ // We only care about record types.
+ if (!RT)
+ continue;
+
+ CharUnits EmptySize;
+ const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
+ if (MemberDecl->isEmpty()) {
+ // If the class decl is empty, get its size.
+ EmptySize = Layout.getSize();
+ } else {
+ // Otherwise, we get the largest empty subobject for the decl.
+ EmptySize = Layout.getSizeOfLargestEmptySubobject();
+ }
+
+ if (EmptySize > SizeOfLargestEmptySubobject)
+ SizeOfLargestEmptySubobject = EmptySize;
+ }
+}
+
+bool
+EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ CharUnits Offset) const {
+ // We only need to check empty bases.
+ if (!RD->isEmpty())
+ return true;
+
+ EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
+ if (I == EmptyClassOffsets.end())
+ return true;
+
+ const ClassVectorTy& Classes = I->second;
+ if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end())
+ return true;
+
+ // There is already an empty class of the same type at this offset.
+ return false;
+}
+
+void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
+ CharUnits Offset) {
+ // We only care about empty bases.
+ if (!RD->isEmpty())
+ return;
+
+ // If we have empty structures inside an union, we can assign both
+ // the same offset. Just avoid pushing them twice in the list.
+ ClassVectorTy& Classes = EmptyClassOffsets[Offset];
+ if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
+ return;
+
+ Classes.push_back(RD);
+
+ // Update the empty class offset.
+ if (Offset > MaxEmptyClassOffset)
+ MaxEmptyClassOffset = Offset;
+}
+
+bool
+EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
+ CharUnits Offset) {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
+
+ if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
+ return false;
+
+ // Traverse all non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
+ for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
+ BaseSubobjectInfo* Base = Info->Bases[I];
+ if (Base->IsVirtual)
+ continue;
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
+
+ if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
+ return false;
+ }
+
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
+
+ if (Info == PrimaryVirtualBaseInfo->Derived) {
+ if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
+ return false;
+ }
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+ if (FD->isBitField())
+ continue;
+
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
+ if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset))
+ return false;
+ }
+
+ return true;
+}
+
+void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
+ CharUnits Offset,
+ bool PlacingEmptyBase) {
+ if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
+ // We know that the only empty subobjects that can conflict with empty
+ // subobject of non-empty bases, are empty bases that can be placed at
+ // offset zero. Because of this, we only need to keep track of empty base
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ return;
+ }
+
+ AddSubobjectAtOffset(Info->Class, Offset);
+
+ // Traverse all non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
+ for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
+ BaseSubobjectInfo* Base = Info->Bases[I];
+ if (Base->IsVirtual)
+ continue;
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
+ UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
+ }
+
+ if (Info->PrimaryVirtualBaseInfo) {
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
+
+ if (Info == PrimaryVirtualBaseInfo->Derived)
+ UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
+ PlacingEmptyBase);
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
+ E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+ if (FD->isBitField())
+ continue;
+
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
+ UpdateEmptyFieldSubobjects(FD, FieldOffset);
+ }
+}
+
+bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
+ CharUnits Offset) {
+ // If we know this class doesn't have any empty subobjects we don't need to
+ // bother checking.
+ if (SizeOfLargestEmptySubobject.isZero())
+ return true;
+
+ if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
+ return false;
+
+ // We are able to place the base at this offset. Make sure to update the
+ // empty base subobject map.
+ UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
+ return true;
+}
+
+bool
+EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ CharUnits Offset) const {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
+
+ if (!CanPlaceSubobjectAtOffset(RD, Offset))
+ return false;
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Traverse all non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
+ if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
+ return false;
+ }
+
+ if (RD == Class) {
+ // This is the most derived class, traverse virtual bases as well.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *VBaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+ if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
+ return false;
+ }
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+ if (FD->isBitField())
+ continue;
+
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
+
+ if (!CanPlaceFieldSubobjectAtOffset(FD, FieldOffset))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ CharUnits Offset) const {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(Offset))
+ return true;
+
+ QualType T = FD->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
+ }
+
+ // If we have an array type we need to look at every element.
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
+ QualType ElemTy = Context.getBaseElementType(AT);
+ const RecordType *RT = ElemTy->getAs<RecordType>();
+ if (!RT)
+ return true;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ uint64_t NumElements = Context.getConstantArrayElementCount(AT);
+ CharUnits ElementOffset = Offset;
+ for (uint64_t I = 0; I != NumElements; ++I) {
+ // We don't have to keep looking past the maximum offset that's known to
+ // contain an empty class.
+ if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
+ return true;
+
+ if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
+ return false;
+
+ ElementOffset += Layout.getSize();
+ }
+ }
+
+ return true;
+}
+
+bool
+EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
+ CharUnits Offset) {
+ if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
+ return false;
+
+ // We are able to place the member variable at this offset.
+ // Make sure to update the empty base subobject map.
+ UpdateEmptyFieldSubobjects(FD, Offset);
+ return true;
+}
+
+void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ CharUnits Offset) {
+ // We know that the only empty subobjects that can conflict with empty
+ // field subobjects are subobjects of empty bases that can be placed at offset
+ // zero. Because of this, we only need to keep track of empty field
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ if (Offset >= SizeOfLargestEmptySubobject)
+ return;
+
+ AddSubobjectAtOffset(RD, Offset);
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Traverse all non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
+ UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
+ }
+
+ if (RD == Class) {
+ // This is the most derived class, traverse virtual bases as well.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *VBaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
+ UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
+ }
+ }
+
+ // Traverse all member variables.
+ unsigned FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ const FieldDecl *FD = *I;
+ if (FD->isBitField())
+ continue;
+
+ CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
+
+ UpdateEmptyFieldSubobjects(FD, FieldOffset);
+ }
+}
+
+void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
+ CharUnits Offset) {
+ QualType T = FD->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ UpdateEmptyFieldSubobjects(RD, RD, Offset);
+ return;
+ }
+
+ // If we have an array type we need to update every element.
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
+ QualType ElemTy = Context.getBaseElementType(AT);
+ const RecordType *RT = ElemTy->getAs<RecordType>();
+ if (!RT)
+ return;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ uint64_t NumElements = Context.getConstantArrayElementCount(AT);
+ CharUnits ElementOffset = Offset;
+
+ for (uint64_t I = 0; I != NumElements; ++I) {
+ // We know that the only empty subobjects that can conflict with empty
+ // field subobjects are subobjects of empty bases that can be placed at
+ // offset zero. Because of this, we only need to keep track of empty field
+ // subobjects with offsets less than the size of the largest empty
+ // subobject for our class.
+ if (ElementOffset >= SizeOfLargestEmptySubobject)
+ return;
+
+ UpdateEmptyFieldSubobjects(RD, RD, ElementOffset);
+ ElementOffset += Layout.getSize();
+ }
+ }
+}
+
+class RecordLayoutBuilder {
+protected:
+ // FIXME: Remove this and make the appropriate fields public.
+ friend class clang::ASTContext;
+
+ const ASTContext &Context;
+
+ EmptySubobjectMap *EmptySubobjects;
+
+ /// Size - The current size of the record layout.
+ uint64_t Size;
+
+ /// Alignment - The current alignment of the record layout.
+ CharUnits Alignment;
+
+ /// \brief The alignment if attribute packed is not used.
+ CharUnits UnpackedAlignment;
+
+ llvm::SmallVector<uint64_t, 16> FieldOffsets;
+
+ /// Packed - Whether the record is packed or not.
+ unsigned Packed : 1;
+
+ unsigned IsUnion : 1;
+
+ unsigned IsMac68kAlign : 1;
+
+ /// UnfilledBitsInLastByte - If the last field laid out was a bitfield,
+ /// this contains the number of bits in the last byte that can be used for
+ /// an adjacent bitfield if necessary.
+ unsigned char UnfilledBitsInLastByte;
+
+ /// MaxFieldAlignment - The maximum allowed field alignment. This is set by
+ /// #pragma pack.
+ CharUnits MaxFieldAlignment;
+
+ /// DataSize - The data size of the record being laid out.
+ uint64_t DataSize;
+
+ CharUnits NonVirtualSize;
+ CharUnits NonVirtualAlignment;
+
+ /// PrimaryBase - the primary base class (if one exists) of the class
+ /// we're laying out.
+ const CXXRecordDecl *PrimaryBase;
+
+ /// PrimaryBaseIsVirtual - Whether the primary base of the class we're laying
+ /// out is virtual.
+ bool PrimaryBaseIsVirtual;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
+
+ /// Bases - base classes and their offsets in the record.
+ BaseOffsetsMapTy Bases;
+
+ // VBases - virtual base classes and their offsets in the record.
+ BaseOffsetsMapTy VBases;
+
+ /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
+ /// primary base classes for some other direct or indirect base class.
+ CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
+
+ /// FirstNearlyEmptyVBase - The first nearly empty virtual base class in
+ /// inheritance graph order. Used for determining the primary base class.
+ const CXXRecordDecl *FirstNearlyEmptyVBase;
+
+ /// VisitedVirtualBases - A set of all the visited virtual bases, used to
+ /// avoid visiting virtual bases more than once.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
+
+ RecordLayoutBuilder(const ASTContext &Context, EmptySubobjectMap
+ *EmptySubobjects)
+ : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
+ Alignment(CharUnits::One()), UnpackedAlignment(Alignment),
+ Packed(false), IsUnion(false), IsMac68kAlign(false),
+ UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()),
+ DataSize(0), NonVirtualSize(CharUnits::Zero()),
+ NonVirtualAlignment(CharUnits::One()), PrimaryBase(0),
+ PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { }
+
+ void Layout(const RecordDecl *D);
+ void Layout(const CXXRecordDecl *D);
+ void Layout(const ObjCInterfaceDecl *D);
+
+ void LayoutFields(const RecordDecl *D);
+ void LayoutField(const FieldDecl *D);
+ void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
+ bool FieldPacked, const FieldDecl *D);
+ void LayoutBitField(const FieldDecl *D);
+
+ /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
+ llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
+ BaseSubobjectInfoMapTy;
+
+ /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases
+ /// of the class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy VirtualBaseInfo;
+
+ /// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the
+ /// class we're laying out to their base subobject info.
+ BaseSubobjectInfoMapTy NonVirtualBaseInfo;
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for the
+ /// bases of the given class.
+ void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
+
+ /// ComputeBaseSubobjectInfo - Compute the base subobject information for a
+ /// single class and all of its base classes.
+ BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived);
+
+ /// DeterminePrimaryBase - Determine the primary base of the given class.
+ void DeterminePrimaryBase(const CXXRecordDecl *RD);
+
+ void SelectPrimaryVBase(const CXXRecordDecl *RD);
+
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+
+ /// LayoutNonVirtualBases - Determines the primary base class (if any) and
+ /// lays it out. Will then proceed to lay out all non-virtual base clasess.
+ void LayoutNonVirtualBases(const CXXRecordDecl *RD);
+
+ /// LayoutNonVirtualBase - Lays out a single non-virtual base.
+ void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
+
+ void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
+ CharUnits Offset);
+
+ /// LayoutVirtualBases - Lays out all the virtual bases.
+ void LayoutVirtualBases(const CXXRecordDecl *RD,
+ const CXXRecordDecl *MostDerivedClass);
+
+ /// LayoutVirtualBase - Lays out a single virtual base.
+ void LayoutVirtualBase(const BaseSubobjectInfo *Base);
+
+ /// LayoutBase - Will lay out a base and return the offset where it was
+ /// placed, in chars.
+ CharUnits LayoutBase(const BaseSubobjectInfo *Base);
+
+ /// InitializeLayout - Initialize record layout for the given record decl.
+ void InitializeLayout(const Decl *D);
+
+ /// FinishLayout - Finalize record layout. Adjust record size based on the
+ /// alignment.
+ void FinishLayout(const NamedDecl *D);
+
+ void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment);
+ void UpdateAlignment(CharUnits NewAlignment) {
+ UpdateAlignment(NewAlignment, NewAlignment);
+ }
+
+ void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
+ uint64_t UnpackedOffset, unsigned UnpackedAlign,
+ bool isPacked, const FieldDecl *D);
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
+ void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
+public:
+ static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
+
+ virtual ~RecordLayoutBuilder() { }
+};
+} // end anonymous namespace
+
+void
+RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
+
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a nearly empty virtual base.
+ if (I->isVirtual() && Context.isNearlyEmpty(Base)) {
+ // If it's not an indirect primary base, then we've found our primary
+ // base.
+ if (!IndirectPrimaryBases.count(Base)) {
+ PrimaryBase = Base;
+ PrimaryBaseIsVirtual = true;
+ return;
+ }
+
+ // Is this the first nearly empty virtual base?
+ if (!FirstNearlyEmptyVBase)
+ FirstNearlyEmptyVBase = Base;
+ }
+
+ SelectPrimaryVBase(Base);
+ if (PrimaryBase)
+ return;
+ }
+}
+
+uint64_t
+RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ return Context.Target.getPointerWidth(0);
+}
+
+/// DeterminePrimaryBase - Determine the primary base of the given class.
+void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
+ // If the class isn't dynamic, it won't have a primary base.
+ if (!RD->isDynamicClass())
+ return;
+
+ // Compute all the primary virtual bases for all of our direct and
+ // indirect bases, and record all their primary virtual base classes.
+ RD->getIndirectPrimaryBases(IndirectPrimaryBases);
+
+ // If the record has a dynamic base class, attempt to choose a primary base
+ // class. It is the first (in direct base class order) non-virtual dynamic
+ // base class, if one exists.
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ // Ignore virtual bases.
+ if (i->isVirtual())
+ continue;
+
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isDynamicClass()) {
+ // We found it.
+ PrimaryBase = Base;
+ PrimaryBaseIsVirtual = false;
+ return;
+ }
+ }
+
+ // Otherwise, it is the first nearly empty virtual base that is not an
+ // indirect primary virtual base class, if one exists.
+ if (RD->getNumVBases() != 0) {
+ SelectPrimaryVBase(RD);
+ if (PrimaryBase)
+ return;
+ }
+
+ // Otherwise, it is the first nearly empty virtual base that is not an
+ // indirect primary virtual base class, if one exists.
+ if (FirstNearlyEmptyVBase) {
+ PrimaryBase = FirstNearlyEmptyVBase;
+ PrimaryBaseIsVirtual = true;
+ return;
+ }
+
+ // Otherwise there is no primary base class.
+ assert(!PrimaryBase && "Should not get here with a primary base!");
+
+ // Allocate the virtual table pointer at offset zero.
+ assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
+
+ // Update the size.
+ Size += GetVirtualPointersSize(RD);
+ DataSize = Size;
+
+ CharUnits UnpackedBaseAlign =
+ Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0));
+ CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
+
+ // The maximum field alignment overrides base align.
+ if (!MaxFieldAlignment.isZero()) {
+ BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
+ UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
+ }
+
+ // Update the alignment.
+ UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+}
+
+BaseSubobjectInfo *
+RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
+ bool IsVirtual,
+ BaseSubobjectInfo *Derived) {
+ BaseSubobjectInfo *Info;
+
+ if (IsVirtual) {
+ // Check if we already have info about this virtual base.
+ BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
+ if (InfoSlot) {
+ assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
+ return InfoSlot;
+ }
+
+ // We don't, create it.
+ InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ Info = InfoSlot;
+ } else {
+ Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
+ }
+
+ Info->Class = RD;
+ Info->IsVirtual = IsVirtual;
+ Info->Derived = 0;
+ Info->PrimaryVirtualBaseInfo = 0;
+
+ const CXXRecordDecl *PrimaryVirtualBase = 0;
+ BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0;
+
+ // Check if this base has a primary virtual base.
+ if (RD->getNumVBases()) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ if (Layout.isPrimaryBaseVirtual()) {
+ // This base does have a primary virtual base.
+ PrimaryVirtualBase = Layout.getPrimaryBase();
+ assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
+
+ // Now check if we have base subobject info about this primary base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+
+ if (PrimaryVirtualBaseInfo) {
+ if (PrimaryVirtualBaseInfo->Derived) {
+ // We did have info about this primary base, and it turns out that it
+ // has already been claimed as a primary virtual base for another
+ // base.
+ PrimaryVirtualBase = 0;
+ } else {
+ // We can claim this base as our primary base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+ }
+ }
+ }
+
+ // Now go through all direct bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
+ }
+
+ if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
+ // Traversing the bases must have created the base info for our primary
+ // virtual base.
+ PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
+ assert(PrimaryVirtualBaseInfo &&
+ "Did not create a primary virtual base!");
+
+ // Claim the primary virtual base as our primary virtual base.
+ Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
+ PrimaryVirtualBaseInfo->Derived = Info;
+ }
+
+ return Info;
+}
+
+void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ bool IsVirtual = I->isVirtual();
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Compute the base subobject info for this base.
+ BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0);
+
+ if (IsVirtual) {
+ // ComputeBaseInfo has already added this base for us.
+ assert(VirtualBaseInfo.count(BaseDecl) &&
+ "Did not add virtual base!");
+ } else {
+ // Add the base info to the map of non-virtual bases.
+ assert(!NonVirtualBaseInfo.count(BaseDecl) &&
+ "Non-virtual base already exists!");
+ NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
+ }
+ }
+}
+
+void
+RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
+ // Then, determine the primary base class.
+ DeterminePrimaryBase(RD);
+
+ // Compute base subobject info.
+ ComputeBaseSubobjectInfo(RD);
+
+ // If we have a primary base class, lay it out.
+ if (PrimaryBase) {
+ if (PrimaryBaseIsVirtual) {
+ // If the primary virtual base was a primary virtual base of some other
+ // base class we'll have to steal it.
+ BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
+ PrimaryBaseInfo->Derived = 0;
+
+ // We have a virtual primary base, insert it as an indirect primary base.
+ IndirectPrimaryBases.insert(PrimaryBase);
+
+ assert(!VisitedVirtualBases.count(PrimaryBase) &&
+ "vbase already visited!");
+ VisitedVirtualBases.insert(PrimaryBase);
+
+ LayoutVirtualBase(PrimaryBaseInfo);
+ } else {
+ BaseSubobjectInfo *PrimaryBaseInfo =
+ NonVirtualBaseInfo.lookup(PrimaryBase);
+ assert(PrimaryBaseInfo &&
+ "Did not find base info for non-virtual primary base!");
+
+ LayoutNonVirtualBase(PrimaryBaseInfo);
+ }
+ }
+
+ // Now lay out the non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+
+ // Ignore virtual bases.
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Skip the primary base.
+ if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
+ continue;
+
+ // Lay out the base.
+ BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);
+ assert(BaseInfo && "Did not find base info for non-virtual base!");
+
+ LayoutNonVirtualBase(BaseInfo);
+ }
+}
+
+void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) {
+ // Layout the base.
+ CharUnits Offset = LayoutBase(Base);
+
+ // Add its base class offset.
+ assert(!Bases.count(Base->Class) && "base offset already exists!");
+ Bases.insert(std::make_pair(Base->Class, Offset));
+
+ AddPrimaryVirtualBaseOffsets(Base, Offset);
+}
+
+void
+RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
+ CharUnits Offset) {
+ // This base isn't interesting, it has no virtual bases.
+ if (!Info->Class->getNumVBases())
+ return;
+
+ // First, check if we have a virtual primary base to add offsets for.
+ if (Info->PrimaryVirtualBaseInfo) {
+ assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
+ "Primary virtual base is not virtual!");
+ if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
+ // Add the offset.
+ assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
+ "primary vbase offset already exists!");
+ VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
+ Offset));
+
+ // Traverse the primary virtual base.
+ AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
+ }
+ }
+
+ // Now go through all direct non-virtual bases.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
+ for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) {
+ const BaseSubobjectInfo *Base = Info->Bases[I];
+ if (Base->IsVirtual)
+ continue;
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
+ AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
+ }
+}
+
+void
+RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
+ const CXXRecordDecl *MostDerivedClass) {
+ const CXXRecordDecl *PrimaryBase;
+ bool PrimaryBaseIsVirtual;
+
+ if (MostDerivedClass == RD) {
+ PrimaryBase = this->PrimaryBase;
+ PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
+ } else {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ PrimaryBase = Layout.getPrimaryBase();
+ PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
+ }
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ if (I->isVirtual()) {
+ if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
+ bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
+
+ // Only lay out the virtual base if it's not an indirect primary base.
+ if (!IndirectPrimaryBase) {
+ // Only visit virtual bases once.
+ if (!VisitedVirtualBases.insert(BaseDecl))
+ continue;
+
+ const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
+ assert(BaseInfo && "Did not find virtual base info!");
+ LayoutVirtualBase(BaseInfo);
+ }
+ }
+ }
+
+ if (!BaseDecl->getNumVBases()) {
+ // This base isn't interesting since it doesn't have any virtual bases.
+ continue;
+ }
+
+ LayoutVirtualBases(BaseDecl, MostDerivedClass);
+ }
+}
+
+void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) {
+ assert(!Base->Derived && "Trying to lay out a primary virtual base!");
+
+ // Layout the base.
+ CharUnits Offset = LayoutBase(Base);
+
+ // Add its base class offset.
+ assert(!VBases.count(Base->Class) && "vbase offset already exists!");
+ VBases.insert(std::make_pair(Base->Class, Offset));
+
+ AddPrimaryVirtualBaseOffsets(Base, Offset);
+}
+
+CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
+
+ // If we have an empty base class, try to place it at offset 0.
+ if (Base->Class->isEmpty() &&
+ EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
+ uint64_t RecordSizeInBits = Context.toBits(Layout.getSize());
+ Size = std::max(Size, RecordSizeInBits);
+
+ return CharUnits::Zero();
+ }
+
+ CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlign();
+ CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
+
+ // The maximum field alignment overrides base align.
+ if (!MaxFieldAlignment.isZero()) {
+ BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
+ UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
+ }
+
+ // Round up the current record size to the base's alignment boundary.
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(DataSize, Context.toBits(BaseAlign));
+
+ // Try to place the base.
+ while (!EmptySubobjects->CanPlaceBaseAtOffset(Base,
+ Context.toCharUnitsFromBits(Offset)))
+ Offset += Context.toBits(BaseAlign);
+
+ if (!Base->Class->isEmpty()) {
+ // Update the data size.
+ DataSize = Offset + Context.toBits(Layout.getNonVirtualSize());
+
+ Size = std::max(Size, DataSize);
+ } else
+ Size = std::max(Size, Offset + Context.toBits(Layout.getSize()));
+
+ // Remember max struct/class alignment.
+ UpdateAlignment(BaseAlign, UnpackedBaseAlign);
+
+ return Context.toCharUnitsFromBits(Offset);
+}
+
+void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ IsUnion = RD->isUnion();
+
+ Packed = D->hasAttr<PackedAttr>();
+
+ // mac68k alignment supersedes maximum field alignment and attribute aligned,
+ // and forces all structures to have 2-byte alignment. The IBM docs on it
+ // allude to additional (more complicated) semantics, especially with regard
+ // to bit-fields, but gcc appears not to follow that.
+ if (D->hasAttr<AlignMac68kAttr>()) {
+ IsMac68kAlign = true;
+ MaxFieldAlignment = CharUnits::fromQuantity(2);
+ Alignment = CharUnits::fromQuantity(2);
+ } else {
+ if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
+ MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());
+
+ if (unsigned MaxAlign = D->getMaxAlignment())
+ UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign));
+ }
+}
+
+void RecordLayoutBuilder::Layout(const RecordDecl *D) {
+ InitializeLayout(D);
+ LayoutFields(D);
+
+ // Finally, round the size of the total struct up to the alignment of the
+ // struct itself.
+ FinishLayout(D);
+}
+
+void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
+ InitializeLayout(RD);
+
+ // Lay out the vtable and the non-virtual bases.
+ LayoutNonVirtualBases(RD);
+
+ LayoutFields(RD);
+
+ NonVirtualSize = Context.toCharUnitsFromBits(Size);
+ NonVirtualAlignment = Alignment;
+
+ // Lay out the virtual bases and add the primary virtual base offsets.
+ LayoutVirtualBases(RD, RD);
+
+ VisitedVirtualBases.clear();
+
+ // Finally, round the size of the total struct up to the alignment of the
+ // struct itself.
+ FinishLayout(RD);
+
+#ifndef NDEBUG
+ // Check that we have base offsets for all bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ assert(Bases.count(BaseDecl) && "Did not find base offset!");
+ }
+
+ // And all virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ assert(VBases.count(BaseDecl) && "Did not find base offset!");
+ }
+#endif
+}
+
+void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
+ if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
+ const ASTRecordLayout &SL = Context.getASTObjCInterfaceLayout(SD);
+
+ UpdateAlignment(SL.getAlignment());
+
+ // We start laying out ivars not at the end of the superclass
+ // structure, but at the next byte following the last field.
+ Size = Context.toBits(SL.getDataSize());
+ DataSize = Size;
+ }
+
+ InitializeLayout(D);
+
+ // Layout each ivar sequentially.
+ llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+ Context.ShallowCollectObjCIvars(D, Ivars);
+ for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
+ LayoutField(Ivars[i]);
+
+ // Finally, round the size of the total struct up to the alignment of the
+ // struct itself.
+ FinishLayout(D);
+}
+
+void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
+ // Layout each field, for now, just sequentially, respecting alignment. In
+ // the future, this will need to be tweakable by targets.
+ for (RecordDecl::field_iterator Field = D->field_begin(),
+ FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
+ LayoutField(*Field);
+}
+
+void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
+ uint64_t TypeSize,
+ bool FieldPacked,
+ const FieldDecl *D) {
+ assert(Context.getLangOptions().CPlusPlus &&
+ "Can only have wide bit-fields in C++!");
+
+ // Itanium C++ ABI 2.4:
+ // If sizeof(T)*8 < n, let T' be the largest integral POD type with
+ // sizeof(T')*8 <= n.
+
+ QualType IntegralPODTypes[] = {
+ Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy,
+ Context.UnsignedLongTy, Context.UnsignedLongLongTy
+ };
+
+ QualType Type;
+ for (unsigned I = 0, E = llvm::array_lengthof(IntegralPODTypes);
+ I != E; ++I) {
+ uint64_t Size = Context.getTypeSize(IntegralPODTypes[I]);
+
+ if (Size > FieldSize)
+ break;
+
+ Type = IntegralPODTypes[I];
+ }
+ assert(!Type.isNull() && "Did not find a type!");
+
+ unsigned TypeAlign = Context.getTypeAlign(Type);
+
+ // We're not going to use any of the unfilled bits in the last byte.
+ UnfilledBitsInLastByte = 0;
+
+ uint64_t FieldOffset;
+ uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+
+ if (IsUnion) {
+ DataSize = std::max(DataSize, FieldSize);
+ FieldOffset = 0;
+ } else {
+ // The bitfield is allocated starting at the next offset aligned appropriately
+ // for T', with length n bits.
+ FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
+
+ uint64_t NewSizeInBits = FieldOffset + FieldSize;
+
+ DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
+ UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ }
+
+ // Place this field at the current location.
+ FieldOffsets.push_back(FieldOffset);
+
+ CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
+ TypeAlign, FieldPacked, D);
+
+ // Update the size.
+ Size = std::max(Size, DataSize);
+
+ // Remember max struct/class alignment.
+ UpdateAlignment(Context.toCharUnitsFromBits(TypeAlign));
+}
+
+void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
+ bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
+ uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
+ uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+
+ std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
+ uint64_t TypeSize = FieldInfo.first;
+ unsigned FieldAlign = FieldInfo.second;
+
+ if (FieldSize > TypeSize) {
+ LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
+ return;
+ }
+
+ // The align if the field is not packed. This is to check if the attribute
+ // was unnecessary (-Wpacked).
+ unsigned UnpackedFieldAlign = FieldAlign;
+ uint64_t UnpackedFieldOffset = FieldOffset;
+ if (!Context.Target.useBitFieldTypeAlignment())
+ UnpackedFieldAlign = 1;
+
+ if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
+ FieldAlign = 1;
+ FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
+ UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment());
+
+ // The maximum field alignment overrides the aligned attribute.
+ if (!MaxFieldAlignment.isZero()) {
+ unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment);
+ FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
+ UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
+ }
+
+ // Check if we need to add padding to give the field the correct alignment.
+ if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
+ FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
+
+ if (FieldSize == 0 ||
+ (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)
+ UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
+ UnpackedFieldAlign);
+
+ // Padding members don't affect overall alignment.
+ if (!D->getIdentifier())
+ FieldAlign = UnpackedFieldAlign = 1;
+
+ // Place this field at the current location.
+ FieldOffsets.push_back(FieldOffset);
+
+ CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
+ UnpackedFieldAlign, FieldPacked, D);
+
+ // Update DataSize to include the last byte containing (part of) the bitfield.
+ if (IsUnion) {
+ // FIXME: I think FieldSize should be TypeSize here.
+ DataSize = std::max(DataSize, FieldSize);
+ } else {
+ uint64_t NewSizeInBits = FieldOffset + FieldSize;
+
+ DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
+ UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ }
+
+ // Update the size.
+ Size = std::max(Size, DataSize);
+
+ // Remember max struct/class alignment.
+ UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
+ Context.toCharUnitsFromBits(UnpackedFieldAlign));
+}
+
+void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
+ if (D->isBitField()) {
+ LayoutBitField(D);
+ return;
+ }
+
+ uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+
+ // Reset the unfilled bits.
+ UnfilledBitsInLastByte = 0;
+
+ bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
+ CharUnits FieldOffset =
+ IsUnion ? CharUnits::Zero() : Context.toCharUnitsFromBits(DataSize);
+ CharUnits FieldSize;
+ CharUnits FieldAlign;
+
+ if (D->getType()->isIncompleteArrayType()) {
+ // This is a flexible array member; we can't directly
+ // query getTypeInfo about these, so we figure it out here.
+ // Flexible array members don't have any size, but they
+ // have to be aligned appropriately for their element type.
+ FieldSize = CharUnits::Zero();
+ const ArrayType* ATy = Context.getAsArrayType(D->getType());
+ FieldAlign = Context.getTypeAlignInChars(ATy->getElementType());
+ } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
+ unsigned AS = RT->getPointeeType().getAddressSpace();
+ FieldSize =
+ Context.toCharUnitsFromBits(Context.Target.getPointerWidth(AS));
+ FieldAlign =
+ Context.toCharUnitsFromBits(Context.Target.getPointerAlign(AS));
+ } else {
+ std::pair<CharUnits, CharUnits> FieldInfo =
+ Context.getTypeInfoInChars(D->getType());
+ FieldSize = FieldInfo.first;
+ FieldAlign = FieldInfo.second;
+
+ if (Context.getLangOptions().MSBitfields) {
+ // If MS bitfield layout is required, figure out what type is being
+ // laid out and align the field to the width of that type.
+
+ // Resolve all typedefs down to their base type and round up the field
+ // alignment if necessary.
+ QualType T = Context.getBaseElementType(D->getType());
+ if (const BuiltinType *BTy = T->getAs<BuiltinType>()) {
+ CharUnits TypeSize = Context.getTypeSizeInChars(BTy);
+ if (TypeSize > FieldAlign)
+ FieldAlign = TypeSize;
+ }
+ }
+ }
+
+ // The align if the field is not packed. This is to check if the attribute
+ // was unnecessary (-Wpacked).
+ CharUnits UnpackedFieldAlign = FieldAlign;
+ CharUnits UnpackedFieldOffset = FieldOffset;
+
+ if (FieldPacked)
+ FieldAlign = CharUnits::One();
+ CharUnits MaxAlignmentInChars =
+ Context.toCharUnitsFromBits(D->getMaxAlignment());
+ FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
+ UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
+
+ // The maximum field alignment overrides the aligned attribute.
+ if (!MaxFieldAlignment.isZero()) {
+ FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
+ UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
+ }
+
+ // Round up the current record size to the field's alignment boundary.
+ FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign);
+ UnpackedFieldOffset =
+ UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign);
+
+ if (!IsUnion && EmptySubobjects) {
+ // Check if we can place the field at this offset.
+ while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
+ // We couldn't place the field at the offset. Try again at a new offset.
+ FieldOffset += FieldAlign;
+ }
+ }
+
+ // Place this field at the current location.
+ FieldOffsets.push_back(Context.toBits(FieldOffset));
+
+ CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
+ Context.toBits(UnpackedFieldOffset),
+ Context.toBits(UnpackedFieldAlign), FieldPacked, D);
+
+ // Reserve space for this field.
+ uint64_t FieldSizeInBits = Context.toBits(FieldSize);
+ if (IsUnion)
+ Size = std::max(Size, FieldSizeInBits);
+ else
+ Size = Context.toBits(FieldOffset) + FieldSizeInBits;
+
+ // Update the data size.
+ DataSize = Size;
+
+ // Remember max struct/class alignment.
+ UpdateAlignment(FieldAlign, UnpackedFieldAlign);
+}
+
+void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
+ // In C++, records cannot be of size 0.
+ if (Context.getLangOptions().CPlusPlus && Size == 0) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ // Compatibility with gcc requires a class (pod or non-pod)
+ // which is not empty but of size 0; such as having fields of
+ // array of zero-length, remains of Size 0
+ if (RD->isEmpty())
+ Size = 8;
+ }
+ else
+ Size = 8;
+ }
+ // Finally, round the size of the record up to the alignment of the
+ // record itself.
+ uint64_t UnpaddedSize = Size - UnfilledBitsInLastByte;
+ uint64_t UnpackedSize =
+ llvm::RoundUpToAlignment(Size, Context.toBits(UnpackedAlignment));
+ Size = llvm::RoundUpToAlignment(Size, Context.toBits(Alignment));
+
+ unsigned CharBitNum = Context.Target.getCharWidth();
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+ // Warn if padding was introduced to the struct/class/union.
+ if (Size > UnpaddedSize) {
+ unsigned PadSize = Size - UnpaddedSize;
+ bool InBits = true;
+ if (PadSize % CharBitNum == 0) {
+ PadSize = PadSize / CharBitNum;
+ InBits = false;
+ }
+ Diag(RD->getLocation(), diag::warn_padded_struct_size)
+ << Context.getTypeDeclType(RD)
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+ }
+
+ // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
+ // bother since there won't be alignment issues.
+ if (Packed && UnpackedAlignment > CharUnits::One() && Size == UnpackedSize)
+ Diag(D->getLocation(), diag::warn_unnecessary_packed)
+ << Context.getTypeDeclType(RD);
+ }
+}
+
+void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
+ CharUnits UnpackedNewAlignment) {
+ // The alignment is not modified when using 'mac68k' alignment.
+ if (IsMac68kAlign)
+ return;
+
+ if (NewAlignment > Alignment) {
+ assert(llvm::isPowerOf2_32(NewAlignment.getQuantity() &&
+ "Alignment not a power of 2"));
+ Alignment = NewAlignment;
+ }
+
+ if (UnpackedNewAlignment > UnpackedAlignment) {
+ assert(llvm::isPowerOf2_32(UnpackedNewAlignment.getQuantity() &&
+ "Alignment not a power of 2"));
+ UnpackedAlignment = UnpackedNewAlignment;
+ }
+}
+
+void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
+ uint64_t UnpaddedOffset,
+ uint64_t UnpackedOffset,
+ unsigned UnpackedAlign,
+ bool isPacked,
+ const FieldDecl *D) {
+ // We let objc ivars without warning, objc interfaces generally are not used
+ // for padding tricks.
+ if (isa<ObjCIvarDecl>(D))
+ return;
+
+ unsigned CharBitNum = Context.Target.getCharWidth();
+
+ // Warn if padding was introduced to the struct/class.
+ if (!IsUnion && Offset > UnpaddedOffset) {
+ unsigned PadSize = Offset - UnpaddedOffset;
+ bool InBits = true;
+ if (PadSize % CharBitNum == 0) {
+ PadSize = PadSize / CharBitNum;
+ InBits = false;
+ }
+ if (D->getIdentifier())
+ Diag(D->getLocation(), diag::warn_padded_struct_field)
+ << (D->getParent()->isStruct() ? 0 : 1) // struct|class
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
+ << D->getIdentifier();
+ else
+ Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
+ << (D->getParent()->isStruct() ? 0 : 1) // struct|class
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+ }
+
+ // Warn if we packed it unnecessarily. If the alignment is 1 byte don't
+ // bother since there won't be alignment issues.
+ if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset)
+ Diag(D->getLocation(), diag::warn_unnecessary_packed)
+ << D->getIdentifier();
+}
+
+const CXXMethodDecl *
+RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
+ // If a class isn't polymorphic it doesn't have a key function.
+ if (!RD->isPolymorphic())
+ return 0;
+
+ // A class inside an anonymous namespace doesn't have a key function. (Or
+ // at least, there's no point to assigning a key function to such a class;
+ // this doesn't affect the ABI.)
+ if (RD->isInAnonymousNamespace())
+ return 0;
+
+ // Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6.
+ // Same behavior as GCC.
+ TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind();
+ if (TSK == TSK_ImplicitInstantiation ||
+ TSK == TSK_ExplicitInstantiationDefinition)
+ return 0;
+
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ if (MD->isPure())
+ continue;
+
+ // Ignore implicit member functions, they are always marked as inline, but
+ // they don't have a body until they're defined.
+ if (MD->isImplicit())
+ continue;
+
+ if (MD->isInlineSpecified())
+ continue;
+
+ if (MD->hasInlineBody())
+ continue;
+
+ // We found it.
+ return MD;
+ }
+
+ return 0;
+}
+
+DiagnosticBuilder
+RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
+ return Context.getDiagnostics().Report(Loc, DiagID);
+}
+
+namespace {
+ // This class implements layout specific to the Microsoft ABI.
+ class MSRecordLayoutBuilder : public RecordLayoutBuilder {
+ public:
+ MSRecordLayoutBuilder(const ASTContext& Ctx,
+ EmptySubobjectMap *EmptySubobjects) :
+ RecordLayoutBuilder(Ctx, EmptySubobjects) {}
+
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+ };
+}
+
+uint64_t
+MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ // We should reserve space for two pointers if the class has both
+ // virtual functions and virtual bases.
+ if (RD->isPolymorphic() && RD->getNumVBases() > 0)
+ return 2 * Context.Target.getPointerWidth(0);
+ return Context.Target.getPointerWidth(0);
+}
+
+/// getASTRecordLayout - Get or compute information about the layout of the
+/// specified record (struct/union/class), which indicates its size and field
+/// position information.
+const ASTRecordLayout &
+ASTContext::getASTRecordLayout(const RecordDecl *D) const {
+ D = D->getDefinition();
+ assert(D && "Cannot get layout of forward declarations!");
+
+ // Look up this layout, if already laid out, return what we have.
+ // Note that we can't save a reference to the entry because this function
+ // is recursive.
+ const ASTRecordLayout *Entry = ASTRecordLayouts[D];
+ if (Entry) return *Entry;
+
+ const ASTRecordLayout *NewEntry;
+
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ EmptySubobjectMap EmptySubobjects(*this, RD);
+
+ // When compiling for Microsoft, use the special MS builder.
+ llvm::OwningPtr<RecordLayoutBuilder> Builder;
+ switch (Target.getCXXABI()) {
+ default:
+ Builder.reset(new RecordLayoutBuilder(*this, &EmptySubobjects));
+ break;
+ case CXXABI_Microsoft:
+ Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects));
+ }
+ Builder->Layout(RD);
+
+ // FIXME: This is not always correct. See the part about bitfields at
+ // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
+ // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
+ bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
+
+ // FIXME: This should be done in FinalizeLayout.
+ uint64_t DataSize =
+ IsPODForThePurposeOfLayout ? Builder->Size : Builder->DataSize;
+ CharUnits NonVirtualSize =
+ IsPODForThePurposeOfLayout ?
+ toCharUnitsFromBits(DataSize) : Builder->NonVirtualSize;
+
+ CharUnits RecordSize = toCharUnitsFromBits(Builder->Size);
+ NewEntry =
+ new (*this) ASTRecordLayout(*this, RecordSize,
+ Builder->Alignment,
+ toCharUnitsFromBits(DataSize),
+ Builder->FieldOffsets.data(),
+ Builder->FieldOffsets.size(),
+ NonVirtualSize,
+ Builder->NonVirtualAlignment,
+ EmptySubobjects.SizeOfLargestEmptySubobject,
+ Builder->PrimaryBase,
+ Builder->PrimaryBaseIsVirtual,
+ Builder->Bases, Builder->VBases);
+ } else {
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ Builder.Layout(D);
+
+ CharUnits RecordSize = toCharUnitsFromBits(Builder.Size);
+
+ NewEntry =
+ new (*this) ASTRecordLayout(*this, RecordSize,
+ Builder.Alignment,
+ toCharUnitsFromBits(Builder.Size),
+ Builder.FieldOffsets.data(),
+ Builder.FieldOffsets.size());
+ }
+
+ ASTRecordLayouts[D] = NewEntry;
+
+ if (getLangOptions().DumpRecordLayouts) {
+ llvm::errs() << "\n*** Dumping AST Record Layout\n";
+ DumpRecordLayout(D, llvm::errs());
+ }
+
+ return *NewEntry;
+}
+
+const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
+ RD = cast<CXXRecordDecl>(RD->getDefinition());
+ assert(RD && "Cannot get key function for forward declarations!");
+
+ const CXXMethodDecl *&Entry = KeyFunctions[RD];
+ if (!Entry)
+ Entry = RecordLayoutBuilder::ComputeKeyFunction(RD);
+
+ return Entry;
+}
+
+/// getInterfaceLayoutImpl - Get or compute information about the
+/// layout of the given interface.
+///
+/// \param Impl - If given, also include the layout of the interface's
+/// implementation. This may differ by including synthesized ivars.
+const ASTRecordLayout &
+ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl) const {
+ assert(!D->isForwardDecl() && "Invalid interface decl!");
+
+ // Look up this layout, if already laid out, return what we have.
+ ObjCContainerDecl *Key =
+ Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D;
+ if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
+ return *Entry;
+
+ // Add in synthesized ivar count if laying out an implementation.
+ if (Impl) {
+ unsigned SynthCount = CountNonClassIvars(D);
+ // If there aren't any sythesized ivars then reuse the interface
+ // entry. Note we can't cache this because we simply free all
+ // entries later; however we shouldn't look up implementations
+ // frequently.
+ if (SynthCount == 0)
+ return getObjCLayout(D, 0);
+ }
+
+ RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+ Builder.Layout(D);
+
+ CharUnits RecordSize = toCharUnitsFromBits(Builder.Size);
+
+ const ASTRecordLayout *NewEntry =
+ new (*this) ASTRecordLayout(*this, RecordSize,
+ Builder.Alignment,
+ toCharUnitsFromBits(Builder.DataSize),
+ Builder.FieldOffsets.data(),
+ Builder.FieldOffsets.size());
+
+ ObjCLayouts[Key] = NewEntry;
+
+ return *NewEntry;
+}
+
+static void PrintOffset(llvm::raw_ostream &OS,
+ CharUnits Offset, unsigned IndentLevel) {
+ OS << llvm::format("%4d | ", Offset.getQuantity());
+ OS.indent(IndentLevel * 2);
+}
+
+static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
+ const CXXRecordDecl *RD, const ASTContext &C,
+ CharUnits Offset,
+ unsigned IndentLevel,
+ const char* Description,
+ bool IncludeVirtualBases) {
+ const ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
+
+ PrintOffset(OS, Offset, IndentLevel);
+ OS << C.getTypeDeclType(const_cast<CXXRecordDecl *>(RD)).getAsString();
+ if (Description)
+ OS << ' ' << Description;
+ if (RD->isEmpty())
+ OS << " (empty)";
+ OS << '\n';
+
+ IndentLevel++;
+
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ // Vtable pointer.
+ if (RD->isDynamicClass() && !PrimaryBase) {
+ PrintOffset(OS, Offset, IndentLevel);
+ OS << '(' << RD << " vtable pointer)\n";
+ }
+ // Dump (non-virtual) bases
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ assert(!I->getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+
+ DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel,
+ Base == PrimaryBase ? "(primary base)" : "(base)",
+ /*IncludeVirtualBases=*/false);
+ }
+
+ // Dump fields.
+ uint64_t FieldNo = 0;
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I, ++FieldNo) {
+ const FieldDecl *Field = *I;
+ CharUnits FieldOffset = Offset +
+ C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo));
+
+ if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
+ if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
+ Field->getName().data(),
+ /*IncludeVirtualBases=*/true);
+ continue;
+ }
+ }
+
+ PrintOffset(OS, FieldOffset, IndentLevel);
+ OS << Field->getType().getAsString() << ' ' << Field << '\n';
+ }
+
+ if (!IncludeVirtualBases)
+ return;
+
+ // Dump virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I) {
+ assert(I->isVirtual() && "Found non-virtual class!");
+ const CXXRecordDecl *VBase =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
+ DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
+ VBase == PrimaryBase ?
+ "(primary virtual base)" : "(virtual base)",
+ /*IncludeVirtualBases=*/false);
+ }
+
+ OS << " sizeof=" << Layout.getSize().getQuantity();
+ OS << ", dsize=" << Layout.getDataSize().getQuantity();
+ OS << ", align=" << Layout.getAlignment().getQuantity() << '\n';
+ OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
+ OS << ", nvalign=" << Layout.getNonVirtualAlign().getQuantity() << '\n';
+ OS << '\n';
+}
+
+void ASTContext::DumpRecordLayout(const RecordDecl *RD,
+ llvm::raw_ostream &OS) const {
+ const ASTRecordLayout &Info = getASTRecordLayout(RD);
+
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, 0,
+ /*IncludeVirtualBases=*/true);
+
+ OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n";
+ OS << "Record: ";
+ RD->dump();
+ OS << "\nLayout: ";
+ OS << "<ASTRecordLayout\n";
+ OS << " Size:" << toBits(Info.getSize()) << "\n";
+ OS << " DataSize:" << toBits(Info.getDataSize()) << "\n";
+ OS << " Alignment:" << toBits(Info.getAlignment()) << "\n";
+ OS << " FieldOffsets: [";
+ for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << Info.getFieldOffset(i);
+ }
+ OS << "]>\n";
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
new file mode 100644
index 0000000..7e73f02
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -0,0 +1,674 @@
+//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt class and statement subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Stmt.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include <cstdio>
+using namespace clang;
+
+static struct StmtClassNameTable {
+ const char *Name;
+ unsigned Counter;
+ unsigned Size;
+} StmtClassInfo[Stmt::lastStmtConstant+1];
+
+static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
+ static bool Initialized = false;
+ if (Initialized)
+ return StmtClassInfo[E];
+
+ // Intialize the table on the first use.
+ Initialized = true;
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
+ StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
+#include "clang/AST/StmtNodes.inc"
+
+ return StmtClassInfo[E];
+}
+
+const char *Stmt::getStmtClassName() const {
+ return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
+}
+
+void Stmt::PrintStats() {
+ // Ensure the table is primed.
+ getStmtInfoTableEntry(Stmt::NullStmtClass);
+
+ unsigned sum = 0;
+ fprintf(stderr, "*** Stmt/Expr Stats:\n");
+ for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
+ if (StmtClassInfo[i].Name == 0) continue;
+ sum += StmtClassInfo[i].Counter;
+ }
+ fprintf(stderr, " %d stmts/exprs total.\n", sum);
+ sum = 0;
+ for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
+ if (StmtClassInfo[i].Name == 0) continue;
+ if (StmtClassInfo[i].Counter == 0) continue;
+ fprintf(stderr, " %d %s, %d each (%d bytes)\n",
+ StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
+ StmtClassInfo[i].Size,
+ StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
+ sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
+ }
+ fprintf(stderr, "Total bytes = %d\n", sum);
+}
+
+void Stmt::addStmtClass(StmtClass s) {
+ ++getStmtInfoTableEntry(s).Counter;
+}
+
+static bool StatSwitch = false;
+
+bool Stmt::CollectingStats(bool Enable) {
+ if (Enable) StatSwitch = true;
+ return StatSwitch;
+}
+
+namespace {
+ struct good {};
+ struct bad {};
+
+ // These silly little functions have to be static inline to suppress
+ // unused warnings, and they have to be defined to suppress other
+ // warnings.
+ static inline good is_good(good) { return good(); }
+
+ typedef Stmt::child_range children_t();
+ template <class T> good implements_children(children_t T::*) {
+ return good();
+ }
+ static inline bad implements_children(children_t Stmt::*) {
+ return bad();
+ }
+
+ typedef SourceRange getSourceRange_t() const;
+ template <class T> good implements_getSourceRange(getSourceRange_t T::*) {
+ return good();
+ }
+ static inline bad implements_getSourceRange(getSourceRange_t Stmt::*) {
+ return bad();
+ }
+
+#define ASSERT_IMPLEMENTS_children(type) \
+ (void) sizeof(is_good(implements_children(&type::children)))
+#define ASSERT_IMPLEMENTS_getSourceRange(type) \
+ (void) sizeof(is_good(implements_getSourceRange(&type::getSourceRange)))
+}
+
+/// Check whether the various Stmt classes implement their member
+/// functions.
+static inline void check_implementations() {
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ ASSERT_IMPLEMENTS_children(type); \
+ ASSERT_IMPLEMENTS_getSourceRange(type);
+#include "clang/AST/StmtNodes.inc"
+}
+
+Stmt::child_range Stmt::children() {
+ switch (getStmtClass()) {
+ case Stmt::NoStmtClass: llvm_unreachable("statement without class");
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return static_cast<type*>(this)->children();
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind!");
+ return child_range();
+}
+
+SourceRange Stmt::getSourceRange() const {
+ switch (getStmtClass()) {
+ case Stmt::NoStmtClass: llvm_unreachable("statement without class");
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return static_cast<const type*>(this)->getSourceRange();
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind!");
+ return SourceRange();
+}
+
+void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
+ if (this->Body)
+ C.Deallocate(Body);
+ this->CompoundStmtBits.NumStmts = NumStmts;
+
+ Body = new (C) Stmt*[NumStmts];
+ memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
+}
+
+const char *LabelStmt::getName() const {
+ return getDecl()->getIdentifier()->getNameStart();
+}
+
+// This is defined here to avoid polluting Stmt.h with importing Expr.h
+SourceRange ReturnStmt::getSourceRange() const {
+ if (RetExpr)
+ return SourceRange(RetLoc, RetExpr->getLocEnd());
+ else
+ return SourceRange(RetLoc);
+}
+
+bool Stmt::hasImplicitControlFlow() const {
+ switch (StmtBits.sClass) {
+ default:
+ return false;
+
+ case CallExprClass:
+ case ConditionalOperatorClass:
+ case ChooseExprClass:
+ case StmtExprClass:
+ case DeclStmtClass:
+ return true;
+
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator* B = cast<BinaryOperator>(this);
+ if (B->isLogicalOp() || B->getOpcode() == BO_Comma)
+ return true;
+ else
+ return false;
+ }
+ }
+}
+
+Expr *AsmStmt::getOutputExpr(unsigned i) {
+ return cast<Expr>(Exprs[i]);
+}
+
+/// getOutputConstraint - Return the constraint string for the specified
+/// output operand. All output constraints are known to be non-empty (either
+/// '=' or '+').
+llvm::StringRef AsmStmt::getOutputConstraint(unsigned i) const {
+ return getOutputConstraintLiteral(i)->getString();
+}
+
+/// getNumPlusOperands - Return the number of output operands that have a "+"
+/// constraint.
+unsigned AsmStmt::getNumPlusOperands() const {
+ unsigned Res = 0;
+ for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
+ if (isOutputPlusConstraint(i))
+ ++Res;
+ return Res;
+}
+
+Expr *AsmStmt::getInputExpr(unsigned i) {
+ return cast<Expr>(Exprs[i + NumOutputs]);
+}
+
+/// getInputConstraint - Return the specified input constraint. Unlike output
+/// constraints, these can be empty.
+llvm::StringRef AsmStmt::getInputConstraint(unsigned i) const {
+ return getInputConstraintLiteral(i)->getString();
+}
+
+
+void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
+ IdentifierInfo **Names,
+ StringLiteral **Constraints,
+ Stmt **Exprs,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ StringLiteral **Clobbers,
+ unsigned NumClobbers) {
+ this->NumOutputs = NumOutputs;
+ this->NumInputs = NumInputs;
+ this->NumClobbers = NumClobbers;
+
+ unsigned NumExprs = NumOutputs + NumInputs;
+
+ C.Deallocate(this->Names);
+ this->Names = new (C) IdentifierInfo*[NumExprs];
+ std::copy(Names, Names + NumExprs, this->Names);
+
+ C.Deallocate(this->Exprs);
+ this->Exprs = new (C) Stmt*[NumExprs];
+ std::copy(Exprs, Exprs + NumExprs, this->Exprs);
+
+ C.Deallocate(this->Constraints);
+ this->Constraints = new (C) StringLiteral*[NumExprs];
+ std::copy(Constraints, Constraints + NumExprs, this->Constraints);
+
+ C.Deallocate(this->Clobbers);
+ this->Clobbers = new (C) StringLiteral*[NumClobbers];
+ std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
+}
+
+/// getNamedOperand - Given a symbolic operand reference like %[foo],
+/// translate this into a numeric value needed to reference the same operand.
+/// This returns -1 if the operand name is invalid.
+int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
+ unsigned NumPlusOperands = 0;
+
+ // Check if this is an output operand.
+ for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
+ if (getOutputName(i) == SymbolicName)
+ return i;
+ }
+
+ for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
+ if (getInputName(i) == SymbolicName)
+ return getNumOutputs() + NumPlusOperands + i;
+
+ // Not found.
+ return -1;
+}
+
+/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
+/// it into pieces. If the asm string is erroneous, emit errors and return
+/// true, otherwise return false.
+unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
+ ASTContext &C, unsigned &DiagOffs) const {
+ llvm::StringRef Str = getAsmString()->getString();
+ const char *StrStart = Str.begin();
+ const char *StrEnd = Str.end();
+ const char *CurPtr = StrStart;
+
+ // "Simple" inline asms have no constraints or operands, just convert the asm
+ // string to escape $'s.
+ if (isSimple()) {
+ std::string Result;
+ for (; CurPtr != StrEnd; ++CurPtr) {
+ switch (*CurPtr) {
+ case '$':
+ Result += "$$";
+ break;
+ default:
+ Result += *CurPtr;
+ break;
+ }
+ }
+ Pieces.push_back(AsmStringPiece(Result));
+ return 0;
+ }
+
+ // CurStringPiece - The current string that we are building up as we scan the
+ // asm string.
+ std::string CurStringPiece;
+
+ bool HasVariants = !C.Target.hasNoAsmVariants();
+
+ while (1) {
+ // Done with the string?
+ if (CurPtr == StrEnd) {
+ if (!CurStringPiece.empty())
+ Pieces.push_back(AsmStringPiece(CurStringPiece));
+ return 0;
+ }
+
+ char CurChar = *CurPtr++;
+ switch (CurChar) {
+ case '$': CurStringPiece += "$$"; continue;
+ case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
+ case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
+ case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
+ case '%':
+ break;
+ default:
+ CurStringPiece += CurChar;
+ continue;
+ }
+
+ // Escaped "%" character in asm string.
+ if (CurPtr == StrEnd) {
+ // % at end of string is invalid (no escape).
+ DiagOffs = CurPtr-StrStart-1;
+ return diag::err_asm_invalid_escape;
+ }
+
+ char EscapedChar = *CurPtr++;
+ if (EscapedChar == '%') { // %% -> %
+ // Escaped percentage sign.
+ CurStringPiece += '%';
+ continue;
+ }
+
+ if (EscapedChar == '=') { // %= -> Generate an unique ID.
+ CurStringPiece += "${:uid}";
+ continue;
+ }
+
+ // Otherwise, we have an operand. If we have accumulated a string so far,
+ // add it to the Pieces list.
+ if (!CurStringPiece.empty()) {
+ Pieces.push_back(AsmStringPiece(CurStringPiece));
+ CurStringPiece.clear();
+ }
+
+ // Handle %x4 and %x[foo] by capturing x as the modifier character.
+ char Modifier = '\0';
+ if (isalpha(EscapedChar)) {
+ Modifier = EscapedChar;
+ EscapedChar = *CurPtr++;
+ }
+
+ if (isdigit(EscapedChar)) {
+ // %n - Assembler operand n
+ unsigned N = 0;
+
+ --CurPtr;
+ while (CurPtr != StrEnd && isdigit(*CurPtr))
+ N = N*10 + ((*CurPtr++)-'0');
+
+ unsigned NumOperands =
+ getNumOutputs() + getNumPlusOperands() + getNumInputs();
+ if (N >= NumOperands) {
+ DiagOffs = CurPtr-StrStart-1;
+ return diag::err_asm_invalid_operand_number;
+ }
+
+ Pieces.push_back(AsmStringPiece(N, Modifier));
+ continue;
+ }
+
+ // Handle %[foo], a symbolic operand reference.
+ if (EscapedChar == '[') {
+ DiagOffs = CurPtr-StrStart-1;
+
+ // Find the ']'.
+ const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
+ if (NameEnd == 0)
+ return diag::err_asm_unterminated_symbolic_operand_name;
+ if (NameEnd == CurPtr)
+ return diag::err_asm_empty_symbolic_operand_name;
+
+ llvm::StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
+
+ int N = getNamedOperand(SymbolicName);
+ if (N == -1) {
+ // Verify that an operand with that name exists.
+ DiagOffs = CurPtr-StrStart;
+ return diag::err_asm_unknown_symbolic_operand_name;
+ }
+ Pieces.push_back(AsmStringPiece(N, Modifier));
+
+ CurPtr = NameEnd+1;
+ continue;
+ }
+
+ DiagOffs = CurPtr-StrStart-1;
+ return diag::err_asm_invalid_escape;
+ }
+}
+
+QualType CXXCatchStmt::getCaughtType() const {
+ if (ExceptionDecl)
+ return ExceptionDecl->getType();
+ return QualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Constructors
+//===----------------------------------------------------------------------===//
+
+AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
+ bool isvolatile, bool msasm,
+ unsigned numoutputs, unsigned numinputs,
+ IdentifierInfo **names, StringLiteral **constraints,
+ Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
+ StringLiteral **clobbers, SourceLocation rparenloc)
+ : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
+ , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
+ , NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) {
+
+ unsigned NumExprs = NumOutputs +NumInputs;
+
+ Names = new (C) IdentifierInfo*[NumExprs];
+ std::copy(names, names + NumExprs, Names);
+
+ Exprs = new (C) Stmt*[NumExprs];
+ std::copy(exprs, exprs + NumExprs, Exprs);
+
+ Constraints = new (C) StringLiteral*[NumExprs];
+ std::copy(constraints, constraints + NumExprs, Constraints);
+
+ Clobbers = new (C) StringLiteral*[NumClobbers];
+ std::copy(clobbers, clobbers + NumClobbers, Clobbers);
+}
+
+ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
+ Stmt *Body, SourceLocation FCL,
+ SourceLocation RPL)
+: Stmt(ObjCForCollectionStmtClass) {
+ SubExprs[ELEM] = Elem;
+ SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
+ SubExprs[BODY] = Body;
+ ForLoc = FCL;
+ RParenLoc = RPL;
+}
+
+ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt)
+ : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
+ NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0)
+{
+ Stmt **Stmts = getStmts();
+ Stmts[0] = atTryStmt;
+ for (unsigned I = 0; I != NumCatchStmts; ++I)
+ Stmts[I + 1] = CatchStmts[I];
+
+ if (HasFinally)
+ Stmts[NumCatchStmts + 1] = atFinallyStmt;
+}
+
+ObjCAtTryStmt *ObjCAtTryStmt::Create(ASTContext &Context,
+ SourceLocation atTryLoc,
+ Stmt *atTryStmt,
+ Stmt **CatchStmts,
+ unsigned NumCatchStmts,
+ Stmt *atFinallyStmt) {
+ unsigned Size = sizeof(ObjCAtTryStmt) +
+ (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *);
+ void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
+ atFinallyStmt);
+}
+
+ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context,
+ unsigned NumCatchStmts,
+ bool HasFinally) {
+ unsigned Size = sizeof(ObjCAtTryStmt) +
+ (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
+ void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
+}
+
+SourceRange ObjCAtTryStmt::getSourceRange() const {
+ SourceLocation EndLoc;
+ if (HasFinally)
+ EndLoc = getFinallyStmt()->getLocEnd();
+ else if (NumCatchStmts)
+ EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd();
+ else
+ EndLoc = getTryBody()->getLocEnd();
+
+ return SourceRange(AtTryLoc, EndLoc);
+}
+
+CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc,
+ Stmt *tryBlock, Stmt **handlers,
+ unsigned numHandlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((numHandlers + 1) * sizeof(Stmt));
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers);
+}
+
+CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((numHandlers + 1) * sizeof(Stmt));
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(Empty, numHandlers);
+}
+
+CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
+ Stmt **handlers, unsigned numHandlers)
+ : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) {
+ Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
+ Stmts[0] = tryBlock;
+ std::copy(handlers, handlers + NumHandlers, Stmts + 1);
+}
+
+IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
+ Stmt *then, SourceLocation EL, Stmt *elsev)
+ : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
+{
+ setConditionVariable(C, var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[THEN] = then;
+ SubExprs[ELSE] = elsev;
+}
+
+VarDecl *IfStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ V->getSourceRange().getEnd());
+}
+
+ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
+ Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
+ SourceLocation RP)
+ : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
+{
+ SubExprs[INIT] = Init;
+ setConditionVariable(C, condVar);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
+ SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
+ SubExprs[BODY] = Body;
+}
+
+VarDecl *ForStmt::getConditionVariable() const {
+ if (!SubExprs[CONDVAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[CONDVAR] = 0;
+ return;
+ }
+
+ SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ V->getSourceRange().getEnd());
+}
+
+SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
+ : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0)
+{
+ setConditionVariable(C, Var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = NULL;
+}
+
+VarDecl *SwitchStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ V->getSourceRange().getEnd());
+}
+
+Stmt *SwitchCase::getSubStmt() {
+ if (isa<CaseStmt>(this)) return cast<CaseStmt>(this)->getSubStmt();
+ return cast<DefaultStmt>(this)->getSubStmt();
+}
+
+WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ SourceLocation WL)
+: Stmt(WhileStmtClass)
+{
+ setConditionVariable(C, Var);
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = body;
+ WhileLoc = WL;
+}
+
+VarDecl *WhileStmt::getConditionVariable() const {
+ if (!SubExprs[VAR])
+ return 0;
+
+ DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
+ return cast<VarDecl>(DS->getSingleDecl());
+}
+
+void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
+ if (!V) {
+ SubExprs[VAR] = 0;
+ return;
+ }
+
+ SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
+ V->getSourceRange().getBegin(),
+ V->getSourceRange().getEnd());
+}
+
+// IndirectGotoStmt
+LabelDecl *IndirectGotoStmt::getConstantTarget() {
+ if (AddrLabelExpr *E =
+ dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
+ return E->getLabel();
+ return 0;
+}
+
+// ReturnStmt
+const Expr* ReturnStmt::getRetValue() const {
+ return cast_or_null<Expr>(RetExpr);
+}
+Expr* ReturnStmt::getRetValue() {
+ return cast_or_null<Expr>(RetExpr);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
new file mode 100644
index 0000000..846bd4c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
@@ -0,0 +1,680 @@
+//===--- StmtDumper.cpp - Dumping implementation for Stmt ASTs ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dump/Stmt::print methods, which dump out the
+// AST in a form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// StmtDumper Visitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class StmtDumper : public StmtVisitor<StmtDumper> {
+ SourceManager *SM;
+ llvm::raw_ostream &OS;
+ unsigned IndentLevel;
+
+ /// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
+ /// the first few levels of an AST. This keeps track of how many ast levels
+ /// are left.
+ unsigned MaxDepth;
+
+ /// LastLocFilename/LastLocLine - Keep track of the last location we print
+ /// out so that we can print out deltas from then on out.
+ const char *LastLocFilename;
+ unsigned LastLocLine;
+
+ public:
+ StmtDumper(SourceManager *sm, llvm::raw_ostream &os, unsigned maxDepth)
+ : SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
+ LastLocFilename = "";
+ LastLocLine = ~0U;
+ }
+
+ void DumpSubTree(Stmt *S) {
+ // Prune the recursion if not using dump all.
+ if (MaxDepth == 0) return;
+
+ ++IndentLevel;
+ if (S) {
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ VisitDeclStmt(DS);
+ else {
+ Visit(S);
+
+ // Print out children.
+ Stmt::child_range CI = S->children();
+ if (CI) {
+ while (CI) {
+ OS << '\n';
+ DumpSubTree(*CI++);
+ }
+ }
+ }
+ OS << ')';
+ } else {
+ Indent();
+ OS << "<<<NULL>>>";
+ }
+ --IndentLevel;
+ }
+
+ void DumpDeclarator(Decl *D);
+
+ void Indent() const {
+ for (int i = 0, e = IndentLevel; i < e; ++i)
+ OS << " ";
+ }
+
+ void DumpType(QualType T) {
+ SplitQualType T_split = T.split();
+ OS << "'" << QualType::getAsString(T_split) << "'";
+
+ if (!T.isNull()) {
+ // If the type is sugared, also dump a (shallow) desugared type.
+ SplitQualType D_split = T.getSplitDesugaredType();
+ if (T_split != D_split)
+ OS << ":'" << QualType::getAsString(D_split) << "'";
+ }
+ }
+ void DumpDeclRef(Decl *node);
+ void DumpStmt(const Stmt *Node) {
+ Indent();
+ OS << "(" << Node->getStmtClassName()
+ << " " << (void*)Node;
+ DumpSourceRange(Node);
+ }
+ void DumpValueKind(ExprValueKind K) {
+ switch (K) {
+ case VK_RValue: break;
+ case VK_LValue: OS << " lvalue"; break;
+ case VK_XValue: OS << " xvalue"; break;
+ }
+ }
+ void DumpObjectKind(ExprObjectKind K) {
+ switch (K) {
+ case OK_Ordinary: break;
+ case OK_BitField: OS << " bitfield"; break;
+ case OK_ObjCProperty: OS << " objcproperty"; break;
+ case OK_VectorComponent: OS << " vectorcomponent"; break;
+ }
+ }
+ void DumpExpr(const Expr *Node) {
+ DumpStmt(Node);
+ OS << ' ';
+ DumpType(Node->getType());
+ DumpValueKind(Node->getValueKind());
+ DumpObjectKind(Node->getObjectKind());
+ }
+ void DumpSourceRange(const Stmt *Node);
+ void DumpLocation(SourceLocation Loc);
+
+ // Stmts.
+ void VisitStmt(Stmt *Node);
+ void VisitDeclStmt(DeclStmt *Node);
+ void VisitLabelStmt(LabelStmt *Node);
+ void VisitGotoStmt(GotoStmt *Node);
+
+ // Exprs
+ void VisitExpr(Expr *Node);
+ void VisitCastExpr(CastExpr *Node);
+ void VisitDeclRefExpr(DeclRefExpr *Node);
+ void VisitPredefinedExpr(PredefinedExpr *Node);
+ void VisitCharacterLiteral(CharacterLiteral *Node);
+ void VisitIntegerLiteral(IntegerLiteral *Node);
+ void VisitFloatingLiteral(FloatingLiteral *Node);
+ void VisitStringLiteral(StringLiteral *Str);
+ void VisitUnaryOperator(UnaryOperator *Node);
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
+ void VisitMemberExpr(MemberExpr *Node);
+ void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
+ void VisitBinaryOperator(BinaryOperator *Node);
+ void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
+ void VisitAddrLabelExpr(AddrLabelExpr *Node);
+ void VisitBlockExpr(BlockExpr *Node);
+
+ // C++
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
+ void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
+ void VisitCXXThisExpr(CXXThisExpr *Node);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
+ void VisitCXXConstructExpr(CXXConstructExpr *Node);
+ void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node);
+ void VisitExprWithCleanups(ExprWithCleanups *Node);
+ void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node);
+ void DumpCXXTemporary(CXXTemporary *Temporary);
+
+ // ObjC
+ void VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node);
+ void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
+ void VisitObjCMessageExpr(ObjCMessageExpr* Node);
+ void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+ void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
+ };
+}
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::DumpLocation(SourceLocation Loc) {
+ SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
+
+ // The general format we print out is filename:line:col, but we drop pieces
+ // that haven't changed since the last loc printed.
+ PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
+
+ if (PLoc.isInvalid()) {
+ OS << "<invalid sloc>";
+ return;
+ }
+
+ if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
+ OS << PLoc.getFilename() << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ LastLocFilename = PLoc.getFilename();
+ LastLocLine = PLoc.getLine();
+ } else if (PLoc.getLine() != LastLocLine) {
+ OS << "line" << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ LastLocLine = PLoc.getLine();
+ } else {
+ OS << "col" << ':' << PLoc.getColumn();
+ }
+}
+
+void StmtDumper::DumpSourceRange(const Stmt *Node) {
+ // Can't translate locations if a SourceManager isn't available.
+ if (SM == 0) return;
+
+ // TODO: If the parent expression is available, we can print a delta vs its
+ // location.
+ SourceRange R = Node->getSourceRange();
+
+ OS << " <";
+ DumpLocation(R.getBegin());
+ if (R.getBegin() != R.getEnd()) {
+ OS << ", ";
+ DumpLocation(R.getEnd());
+ }
+ OS << ">";
+
+ // <t2.c:123:421[blah], t2.c:412:321>
+
+}
+
+
+//===----------------------------------------------------------------------===//
+// Stmt printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::VisitStmt(Stmt *Node) {
+ DumpStmt(Node);
+}
+
+void StmtDumper::DumpDeclarator(Decl *D) {
+ // FIXME: Need to complete/beautify this... this code simply shows the
+ // nodes are where they need to be.
+ if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
+ OS << "\"typedef " << localType->getUnderlyingType().getAsString()
+ << ' ' << localType << '"';
+ } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+ OS << "\"";
+ // Emit storage class for vardecls.
+ if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
+ if (V->getStorageClass() != SC_None)
+ OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
+ << " ";
+ }
+
+ std::string Name = VD->getNameAsString();
+ VD->getType().getAsStringInternal(Name,
+ PrintingPolicy(VD->getASTContext().getLangOptions()));
+ OS << Name;
+
+ // If this is a vardecl with an initializer, emit it.
+ if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
+ if (V->getInit()) {
+ OS << " =\n";
+ DumpSubTree(V->getInit());
+ }
+ }
+ OS << '"';
+ } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ // print a free standing tag decl (e.g. "struct x;").
+ const char *tagname;
+ if (const IdentifierInfo *II = TD->getIdentifier())
+ tagname = II->getNameStart();
+ else
+ tagname = "<anonymous>";
+ OS << '"' << TD->getKindName() << ' ' << tagname << ";\"";
+ // FIXME: print tag bodies.
+ } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) {
+ // print using-directive decl (e.g. "using namespace x;")
+ const char *ns;
+ if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
+ ns = II->getNameStart();
+ else
+ ns = "<anonymous>";
+ OS << '"' << UD->getDeclKindName() << ns << ";\"";
+ } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
+ // print using decl (e.g. "using std::string;")
+ const char *tn = UD->isTypeName() ? "typename " : "";
+ OS << '"' << UD->getDeclKindName() << tn;
+ UD->getTargetNestedNameDecl()->print(OS,
+ PrintingPolicy(UD->getASTContext().getLangOptions()));
+ OS << ";\"";
+ } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
+ OS << "label " << LD->getNameAsString();
+ } else {
+ assert(0 && "Unexpected decl");
+ }
+}
+
+void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
+ DumpStmt(Node);
+ OS << "\n";
+ for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
+ DI != DE; ++DI) {
+ Decl* D = *DI;
+ ++IndentLevel;
+ Indent();
+ OS << (void*) D << " ";
+ DumpDeclarator(D);
+ if (DI+1 != DE)
+ OS << "\n";
+ --IndentLevel;
+ }
+}
+
+void StmtDumper::VisitLabelStmt(LabelStmt *Node) {
+ DumpStmt(Node);
+ OS << " '" << Node->getName() << "'";
+}
+
+void StmtDumper::VisitGotoStmt(GotoStmt *Node) {
+ DumpStmt(Node);
+ OS << " '" << Node->getLabel()->getName()
+ << "':" << (void*)Node->getLabel();
+}
+
+//===----------------------------------------------------------------------===//
+// Expr printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::VisitExpr(Expr *Node) {
+ DumpExpr(Node);
+}
+
+static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
+ if (Node->path_empty())
+ return;
+
+ OS << " (";
+ bool First = true;
+ for (CastExpr::path_iterator
+ I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
+ const CXXBaseSpecifier *Base = *I;
+ if (!First)
+ OS << " -> ";
+
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isVirtual())
+ OS << "virtual ";
+ OS << RD->getName();
+ First = false;
+ }
+
+ OS << ')';
+}
+
+void StmtDumper::VisitCastExpr(CastExpr *Node) {
+ DumpExpr(Node);
+ OS << " <" << Node->getCastKindName();
+ DumpBasePath(OS, Node);
+ OS << ">";
+}
+
+void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
+ DumpExpr(Node);
+
+ OS << " ";
+ DumpDeclRef(Node->getDecl());
+}
+
+void StmtDumper::DumpDeclRef(Decl *d) {
+ OS << d->getDeclKindName() << ' ' << (void*) d;
+
+ if (NamedDecl *nd = dyn_cast<NamedDecl>(d)) {
+ OS << " '";
+ nd->getDeclName().printName(OS);
+ OS << "'";
+ }
+
+ if (ValueDecl *vd = dyn_cast<ValueDecl>(d)) {
+ OS << ' '; DumpType(vd->getType());
+ }
+}
+
+void StmtDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
+ DumpExpr(Node);
+ OS << " (";
+ if (!Node->requiresADL()) OS << "no ";
+ OS << "ADL) = '" << Node->getName() << '\'';
+
+ UnresolvedLookupExpr::decls_iterator
+ I = Node->decls_begin(), E = Node->decls_end();
+ if (I == E) OS << " empty";
+ for (; I != E; ++I)
+ OS << " " << (void*) *I;
+}
+
+void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ DumpExpr(Node);
+
+ OS << " " << Node->getDecl()->getDeclKindName()
+ << "Decl='" << Node->getDecl()
+ << "' " << (void*)Node->getDecl();
+ if (Node->isFreeIvar())
+ OS << " isFreeIvar";
+}
+
+void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
+ DumpExpr(Node);
+ switch (Node->getIdentType()) {
+ default: assert(0 && "unknown case");
+ case PredefinedExpr::Func: OS << " __func__"; break;
+ case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
+ case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
+ }
+}
+
+void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) {
+ DumpExpr(Node);
+ OS << Node->getValue();
+}
+
+void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) {
+ DumpExpr(Node);
+
+ bool isSigned = Node->getType()->isSignedIntegerType();
+ OS << " " << Node->getValue().toString(10, isSigned);
+}
+void StmtDumper::VisitFloatingLiteral(FloatingLiteral *Node) {
+ DumpExpr(Node);
+ OS << " " << Node->getValueAsApproximateDouble();
+}
+
+void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
+ DumpExpr(Str);
+ // FIXME: this doesn't print wstrings right.
+ OS << " ";
+ if (Str->isWide())
+ OS << "L";
+ OS << '"';
+ OS.write_escaped(Str->getString());
+ OS << '"';
+}
+
+void StmtDumper::VisitUnaryOperator(UnaryOperator *Node) {
+ DumpExpr(Node);
+ OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
+ << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+}
+void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << (Node->isSizeOf() ? "sizeof" : "alignof") << " ";
+ if (Node->isArgumentType())
+ DumpType(Node->getArgumentType());
+}
+
+void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << (Node->isArrow() ? "->" : ".")
+ << Node->getMemberDecl() << ' '
+ << (void*)Node->getMemberDecl();
+}
+void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << Node->getAccessor().getNameStart();
+}
+void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
+ DumpExpr(Node);
+ OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+}
+void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
+ DumpExpr(Node);
+ OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
+ << "' ComputeLHSTy=";
+ DumpType(Node->getComputationLHSType());
+ OS << " ComputeResultTy=";
+ DumpType(Node->getComputationResultType());
+}
+
+void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
+ DumpExpr(Node);
+
+ IndentLevel++;
+ BlockDecl *block = Node->getBlockDecl();
+ if (block->capturesCXXThis()) {
+ OS << '\n'; Indent(); OS << "(capture this)";
+ }
+ for (BlockDecl::capture_iterator
+ i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
+ OS << '\n';
+ Indent();
+ OS << "(capture ";
+ if (i->isByRef()) OS << "byref ";
+ if (i->isNested()) OS << "nested ";
+ DumpDeclRef(i->getVariable());
+ if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
+ OS << ")";
+ }
+ IndentLevel--;
+
+ DumpSubTree(block->getBody());
+}
+
+// GNU extensions.
+
+void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << Node->getLabel()->getName()
+ << " " << (void*)Node->getLabel();
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << Node->getCastName()
+ << "<" << Node->getTypeAsWritten().getAsString() << ">"
+ << " <" << Node->getCastKindName();
+ DumpBasePath(OS, Node);
+ OS << ">";
+}
+
+void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
+ DumpExpr(Node);
+ OS << " " << (Node->getValue() ? "true" : "false");
+}
+
+void StmtDumper::VisitCXXThisExpr(CXXThisExpr *Node) {
+ DumpExpr(Node);
+ OS << " this";
+}
+
+void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+ DumpExpr(Node);
+ OS << " functional cast to " << Node->getTypeAsWritten().getAsString();
+}
+
+void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
+ DumpExpr(Node);
+ CXXConstructorDecl *Ctor = Node->getConstructor();
+ DumpType(Ctor->getType());
+ if (Node->isElidable())
+ OS << " elidable";
+ if (Node->requiresZeroInitialization())
+ OS << " zeroing";
+}
+
+void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
+ DumpExpr(Node);
+ OS << " ";
+ DumpCXXTemporary(Node->getTemporary());
+}
+
+void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
+ DumpExpr(Node);
+ ++IndentLevel;
+ for (unsigned i = 0, e = Node->getNumTemporaries(); i != e; ++i) {
+ OS << "\n";
+ Indent();
+ DumpCXXTemporary(Node->getTemporary(i));
+ }
+ --IndentLevel;
+}
+
+void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
+ OS << "(CXXTemporary " << (void *)Temporary << ")";
+}
+
+//===----------------------------------------------------------------------===//
+// Obj-C Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
+ DumpExpr(Node);
+ OS << " selector=" << Node->getSelector().getAsString();
+ switch (Node->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ break;
+
+ case ObjCMessageExpr::Class:
+ OS << " class=";
+ DumpType(Node->getClassReceiver());
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ OS << " super (instance)";
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ OS << " super (class)";
+ break;
+ }
+}
+
+void StmtDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) {
+ DumpStmt(Node);
+ if (VarDecl *CatchParam = Node->getCatchParamDecl()) {
+ OS << " catch parm = ";
+ DumpDeclarator(CatchParam);
+ } else {
+ OS << " catch all";
+ }
+}
+
+void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
+ DumpExpr(Node);
+ OS << " ";
+ DumpType(Node->getEncodedType());
+}
+
+void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+ DumpExpr(Node);
+
+ OS << " " << Node->getSelector().getAsString();
+}
+
+void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+ DumpExpr(Node);
+
+ OS << ' ' << Node->getProtocol();
+}
+
+void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+ DumpExpr(Node);
+ if (Node->isImplicitProperty()) {
+ OS << " Kind=MethodRef Getter=\"";
+ if (Node->getImplicitPropertyGetter())
+ OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
+ else
+ OS << "(null)";
+
+ OS << "\" Setter=\"";
+ if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
+ OS << Setter->getSelector().getAsString();
+ else
+ OS << "(null)";
+ OS << "\"";
+ } else {
+ OS << " Kind=PropertyRef Property=\"" << Node->getExplicitProperty() << '"';
+ }
+
+ if (Node->isSuperReceiver())
+ OS << " super";
+}
+
+//===----------------------------------------------------------------------===//
+// Stmt method implementations
+//===----------------------------------------------------------------------===//
+
+/// dump - This does a local dump of the specified AST fragment. It dumps the
+/// specified node and a few nodes underneath it, but not the whole subtree.
+/// This is useful in a debugger.
+void Stmt::dump(SourceManager &SM) const {
+ dump(llvm::errs(), SM);
+}
+
+void Stmt::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+ StmtDumper P(&SM, OS, 4);
+ P.DumpSubTree(const_cast<Stmt*>(this));
+ OS << "\n";
+}
+
+/// dump - This does a local dump of the specified AST fragment. It dumps the
+/// specified node and a few nodes underneath it, but not the whole subtree.
+/// This is useful in a debugger.
+void Stmt::dump() const {
+ StmtDumper P(0, llvm::errs(), 4);
+ P.DumpSubTree(const_cast<Stmt*>(this));
+ llvm::errs() << "\n";
+}
+
+/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+void Stmt::dumpAll(SourceManager &SM) const {
+ StmtDumper P(&SM, llvm::errs(), ~0U);
+ P.DumpSubTree(const_cast<Stmt*>(this));
+ llvm::errs() << "\n";
+}
+
+/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+void Stmt::dumpAll() const {
+ StmtDumper P(0, llvm::errs(), ~0U);
+ P.DumpSubTree(const_cast<Stmt*>(this));
+ llvm::errs() << "\n";
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
new file mode 100644
index 0000000..9a7265a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
@@ -0,0 +1,155 @@
+//===--- StmtIterator.cpp - Iterators for Statements ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines internal methods for StmtIterator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtIterator.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
+static inline const VariableArrayType *FindVA(const Type* t) {
+ while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
+ if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
+ if (vat->getSizeExpr())
+ return vat;
+
+ t = vt->getElementType().getTypePtr();
+ }
+
+ return NULL;
+}
+
+void StmtIteratorBase::NextVA() {
+ assert (getVAPtr());
+
+ const VariableArrayType *p = getVAPtr();
+ p = FindVA(p->getElementType().getTypePtr());
+ setVAPtr(p);
+
+ if (p)
+ return;
+
+ if (inDecl()) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(decl))
+ if (VD->Init)
+ return;
+
+ NextDecl();
+ }
+ else if (inDeclGroup()) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(*DGI))
+ if (VD->Init)
+ return;
+
+ NextDecl();
+ }
+ else {
+ assert (inSizeOfTypeVA());
+ assert(!decl);
+ RawVAPtr = 0;
+ }
+}
+
+void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
+ assert (getVAPtr() == NULL);
+
+ if (inDecl()) {
+ assert(decl);
+
+ // FIXME: SIMPLIFY AWAY.
+ if (ImmediateAdvance)
+ decl = 0;
+ else if (HandleDecl(decl))
+ return;
+ }
+ else {
+ assert(inDeclGroup());
+
+ if (ImmediateAdvance)
+ ++DGI;
+
+ for ( ; DGI != DGE; ++DGI)
+ if (HandleDecl(*DGI))
+ return;
+ }
+
+ RawVAPtr = 0;
+}
+
+bool StmtIteratorBase::HandleDecl(Decl* D) {
+
+ if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
+ if (const VariableArrayType* VAPtr = FindVA(VD->getType().getTypePtr())) {
+ setVAPtr(VAPtr);
+ return true;
+ }
+
+ if (VD->getInit())
+ return true;
+ }
+ else if (TypedefDecl* TD = dyn_cast<TypedefDecl>(D)) {
+ if (const VariableArrayType* VAPtr =
+ FindVA(TD->getUnderlyingType().getTypePtr())) {
+ setVAPtr(VAPtr);
+ return true;
+ }
+ }
+ else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
+ if (ECD->getInitExpr())
+ return true;
+ }
+
+ return false;
+}
+
+StmtIteratorBase::StmtIteratorBase(Decl *d, Stmt **s)
+ : stmt(s), decl(d), RawVAPtr(d ? DeclMode : 0) {
+ if (decl)
+ NextDecl(false);
+}
+
+StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
+ : stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
+ NextDecl(false);
+}
+
+StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t)
+ : stmt(0), decl(0), RawVAPtr(SizeOfTypeVAMode) {
+ RawVAPtr |= reinterpret_cast<uintptr_t>(t);
+}
+
+Stmt*& StmtIteratorBase::GetDeclExpr() const {
+
+ if (const VariableArrayType* VAPtr = getVAPtr()) {
+ assert (VAPtr->SizeExpr);
+ return const_cast<Stmt*&>(VAPtr->SizeExpr);
+ }
+
+ assert (inDecl() || inDeclGroup());
+
+ if (inDeclGroup()) {
+ VarDecl* VD = cast<VarDecl>(*DGI);
+ return *VD->getInitAddress();
+ }
+
+ assert (inDecl());
+
+ if (VarDecl* VD = dyn_cast<VarDecl>(decl)) {
+ assert (VD->Init);
+ return *VD->getInitAddress();
+ }
+
+ EnumConstantDecl* ECD = cast<EnumConstantDecl>(decl);
+ return ECD->Init;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
new file mode 100644
index 0000000..1cdd220
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -0,0 +1,1399 @@
+//===--- StmtPrinter.cpp - Printing implementation for Stmt ASTs ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dumpPretty/Stmt::printPretty methods, which
+// pretty print the AST back out to C code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/Support/Format.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// StmtPrinter Visitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class StmtPrinter : public StmtVisitor<StmtPrinter> {
+ llvm::raw_ostream &OS;
+ ASTContext &Context;
+ unsigned IndentLevel;
+ clang::PrinterHelper* Helper;
+ PrintingPolicy Policy;
+
+ public:
+ StmtPrinter(llvm::raw_ostream &os, ASTContext &C, PrinterHelper* helper,
+ const PrintingPolicy &Policy,
+ unsigned Indentation = 0)
+ : OS(os), Context(C), IndentLevel(Indentation), Helper(helper),
+ Policy(Policy) {}
+
+ void PrintStmt(Stmt *S) {
+ PrintStmt(S, Policy.Indentation);
+ }
+
+ void PrintStmt(Stmt *S, int SubIndent) {
+ IndentLevel += SubIndent;
+ if (S && isa<Expr>(S)) {
+ // If this is an expr used in a stmt context, indent and newline it.
+ Indent();
+ Visit(S);
+ OS << ";\n";
+ } else if (S) {
+ Visit(S);
+ } else {
+ Indent() << "<<<NULL STATEMENT>>>\n";
+ }
+ IndentLevel -= SubIndent;
+ }
+
+ void PrintRawCompoundStmt(CompoundStmt *S);
+ void PrintRawDecl(Decl *D);
+ void PrintRawDeclStmt(DeclStmt *S);
+ void PrintRawIfStmt(IfStmt *If);
+ void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
+ void PrintCallArgs(CallExpr *E);
+
+ void PrintExpr(Expr *E) {
+ if (E)
+ Visit(E);
+ else
+ OS << "<null expr>";
+ }
+
+ llvm::raw_ostream &Indent(int Delta = 0) {
+ for (int i = 0, e = IndentLevel+Delta; i < e; ++i)
+ OS << " ";
+ return OS;
+ }
+
+ void Visit(Stmt* S) {
+ if (Helper && Helper->handledStmt(S,OS))
+ return;
+ else StmtVisitor<StmtPrinter>::Visit(S);
+ }
+
+ void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED {
+ Indent() << "<<unknown stmt type>>\n";
+ }
+ void VisitExpr(Expr *Node) LLVM_ATTRIBUTE_UNUSED {
+ OS << "<<unknown expr type>>";
+ }
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
+
+#define ABSTRACT_STMT(CLASS)
+#define STMT(CLASS, PARENT) \
+ void Visit##CLASS(CLASS *Node);
+#include "clang/AST/StmtNodes.inc"
+ };
+}
+
+//===----------------------------------------------------------------------===//
+// Stmt printing methods.
+//===----------------------------------------------------------------------===//
+
+/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
+/// with no newline after the }.
+void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
+ OS << "{\n";
+ for (CompoundStmt::body_iterator I = Node->body_begin(), E = Node->body_end();
+ I != E; ++I)
+ PrintStmt(*I);
+
+ Indent() << "}";
+}
+
+void StmtPrinter::PrintRawDecl(Decl *D) {
+ D->print(OS, Policy, IndentLevel);
+}
+
+void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
+ DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end();
+ llvm::SmallVector<Decl*, 2> Decls;
+ for ( ; Begin != End; ++Begin)
+ Decls.push_back(*Begin);
+
+ Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel);
+}
+
+void StmtPrinter::VisitNullStmt(NullStmt *Node) {
+ Indent() << ";\n";
+}
+
+void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
+ Indent();
+ PrintRawDeclStmt(Node);
+ OS << ";\n";
+}
+
+void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {
+ Indent();
+ PrintRawCompoundStmt(Node);
+ OS << "\n";
+}
+
+void StmtPrinter::VisitCaseStmt(CaseStmt *Node) {
+ Indent(-1) << "case ";
+ PrintExpr(Node->getLHS());
+ if (Node->getRHS()) {
+ OS << " ... ";
+ PrintExpr(Node->getRHS());
+ }
+ OS << ":\n";
+
+ PrintStmt(Node->getSubStmt(), 0);
+}
+
+void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) {
+ Indent(-1) << "default:\n";
+ PrintStmt(Node->getSubStmt(), 0);
+}
+
+void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
+ Indent(-1) << Node->getName() << ":\n";
+ PrintStmt(Node->getSubStmt(), 0);
+}
+
+void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
+ OS << "if (";
+ PrintExpr(If->getCond());
+ OS << ')';
+
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(If->getThen())) {
+ OS << ' ';
+ PrintRawCompoundStmt(CS);
+ OS << (If->getElse() ? ' ' : '\n');
+ } else {
+ OS << '\n';
+ PrintStmt(If->getThen());
+ if (If->getElse()) Indent();
+ }
+
+ if (Stmt *Else = If->getElse()) {
+ OS << "else";
+
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Else)) {
+ OS << ' ';
+ PrintRawCompoundStmt(CS);
+ OS << '\n';
+ } else if (IfStmt *ElseIf = dyn_cast<IfStmt>(Else)) {
+ OS << ' ';
+ PrintRawIfStmt(ElseIf);
+ } else {
+ OS << '\n';
+ PrintStmt(If->getElse());
+ }
+ }
+}
+
+void StmtPrinter::VisitIfStmt(IfStmt *If) {
+ Indent();
+ PrintRawIfStmt(If);
+}
+
+void StmtPrinter::VisitSwitchStmt(SwitchStmt *Node) {
+ Indent() << "switch (";
+ PrintExpr(Node->getCond());
+ OS << ")";
+
+ // Pretty print compoundstmt bodies (very common).
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ OS << " ";
+ PrintRawCompoundStmt(CS);
+ OS << "\n";
+ } else {
+ OS << "\n";
+ PrintStmt(Node->getBody());
+ }
+}
+
+void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
+ Indent() << "while (";
+ PrintExpr(Node->getCond());
+ OS << ")\n";
+ PrintStmt(Node->getBody());
+}
+
+void StmtPrinter::VisitDoStmt(DoStmt *Node) {
+ Indent() << "do ";
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ PrintRawCompoundStmt(CS);
+ OS << " ";
+ } else {
+ OS << "\n";
+ PrintStmt(Node->getBody());
+ Indent();
+ }
+
+ OS << "while (";
+ PrintExpr(Node->getCond());
+ OS << ");\n";
+}
+
+void StmtPrinter::VisitForStmt(ForStmt *Node) {
+ Indent() << "for (";
+ if (Node->getInit()) {
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getInit()))
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(cast<Expr>(Node->getInit()));
+ }
+ OS << ";";
+ if (Node->getCond()) {
+ OS << " ";
+ PrintExpr(Node->getCond());
+ }
+ OS << ";";
+ if (Node->getInc()) {
+ OS << " ";
+ PrintExpr(Node->getInc());
+ }
+ OS << ") ";
+
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ PrintRawCompoundStmt(CS);
+ OS << "\n";
+ } else {
+ OS << "\n";
+ PrintStmt(Node->getBody());
+ }
+}
+
+void StmtPrinter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *Node) {
+ Indent() << "for (";
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getElement()))
+ PrintRawDeclStmt(DS);
+ else
+ PrintExpr(cast<Expr>(Node->getElement()));
+ OS << " in ";
+ PrintExpr(Node->getCollection());
+ OS << ") ";
+
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+ PrintRawCompoundStmt(CS);
+ OS << "\n";
+ } else {
+ OS << "\n";
+ PrintStmt(Node->getBody());
+ }
+}
+
+void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
+ Indent() << "goto " << Node->getLabel()->getName() << ";\n";
+}
+
+void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
+ Indent() << "goto *";
+ PrintExpr(Node->getTarget());
+ OS << ";\n";
+}
+
+void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) {
+ Indent() << "continue;\n";
+}
+
+void StmtPrinter::VisitBreakStmt(BreakStmt *Node) {
+ Indent() << "break;\n";
+}
+
+
+void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) {
+ Indent() << "return";
+ if (Node->getRetValue()) {
+ OS << " ";
+ PrintExpr(Node->getRetValue());
+ }
+ OS << ";\n";
+}
+
+
+void StmtPrinter::VisitAsmStmt(AsmStmt *Node) {
+ Indent() << "asm ";
+
+ if (Node->isVolatile())
+ OS << "volatile ";
+
+ OS << "(";
+ VisitStringLiteral(Node->getAsmString());
+
+ // Outputs
+ if (Node->getNumOutputs() != 0 || Node->getNumInputs() != 0 ||
+ Node->getNumClobbers() != 0)
+ OS << " : ";
+
+ for (unsigned i = 0, e = Node->getNumOutputs(); i != e; ++i) {
+ if (i != 0)
+ OS << ", ";
+
+ if (!Node->getOutputName(i).empty()) {
+ OS << '[';
+ OS << Node->getOutputName(i);
+ OS << "] ";
+ }
+
+ VisitStringLiteral(Node->getOutputConstraintLiteral(i));
+ OS << " ";
+ Visit(Node->getOutputExpr(i));
+ }
+
+ // Inputs
+ if (Node->getNumInputs() != 0 || Node->getNumClobbers() != 0)
+ OS << " : ";
+
+ for (unsigned i = 0, e = Node->getNumInputs(); i != e; ++i) {
+ if (i != 0)
+ OS << ", ";
+
+ if (!Node->getInputName(i).empty()) {
+ OS << '[';
+ OS << Node->getInputName(i);
+ OS << "] ";
+ }
+
+ VisitStringLiteral(Node->getInputConstraintLiteral(i));
+ OS << " ";
+ Visit(Node->getInputExpr(i));
+ }
+
+ // Clobbers
+ if (Node->getNumClobbers() != 0)
+ OS << " : ";
+
+ for (unsigned i = 0, e = Node->getNumClobbers(); i != e; ++i) {
+ if (i != 0)
+ OS << ", ";
+
+ VisitStringLiteral(Node->getClobber(i));
+ }
+
+ OS << ");\n";
+}
+
+void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
+ Indent() << "@try";
+ if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) {
+ PrintRawCompoundStmt(TS);
+ OS << "\n";
+ }
+
+ for (unsigned I = 0, N = Node->getNumCatchStmts(); I != N; ++I) {
+ ObjCAtCatchStmt *catchStmt = Node->getCatchStmt(I);
+ Indent() << "@catch(";
+ if (catchStmt->getCatchParamDecl()) {
+ if (Decl *DS = catchStmt->getCatchParamDecl())
+ PrintRawDecl(DS);
+ }
+ OS << ")";
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) {
+ PrintRawCompoundStmt(CS);
+ OS << "\n";
+ }
+ }
+
+ if (ObjCAtFinallyStmt *FS = static_cast<ObjCAtFinallyStmt *>(
+ Node->getFinallyStmt())) {
+ Indent() << "@finally";
+ PrintRawCompoundStmt(dyn_cast<CompoundStmt>(FS->getFinallyBody()));
+ OS << "\n";
+ }
+}
+
+void StmtPrinter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Node) {
+}
+
+void StmtPrinter::VisitObjCAtCatchStmt (ObjCAtCatchStmt *Node) {
+ Indent() << "@catch (...) { /* todo */ } \n";
+}
+
+void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) {
+ Indent() << "@throw";
+ if (Node->getThrowExpr()) {
+ OS << " ";
+ PrintExpr(Node->getThrowExpr());
+ }
+ OS << ";\n";
+}
+
+void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
+ Indent() << "@synchronized (";
+ PrintExpr(Node->getSynchExpr());
+ OS << ")";
+ PrintRawCompoundStmt(Node->getSynchBody());
+ OS << "\n";
+}
+
+void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
+ OS << "catch (";
+ if (Decl *ExDecl = Node->getExceptionDecl())
+ PrintRawDecl(ExDecl);
+ else
+ OS << "...";
+ OS << ") ";
+ PrintRawCompoundStmt(cast<CompoundStmt>(Node->getHandlerBlock()));
+}
+
+void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
+ Indent();
+ PrintRawCXXCatchStmt(Node);
+ OS << "\n";
+}
+
+void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
+ Indent() << "try ";
+ PrintRawCompoundStmt(Node->getTryBlock());
+ for (unsigned i = 0, e = Node->getNumHandlers(); i < e; ++i) {
+ OS << " ";
+ PrintRawCXXCatchStmt(Node->getHandler(i));
+ }
+ OS << "\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Expr printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+ OS << Node->getNameInfo();
+ if (Node->hasExplicitTemplateArgs())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+}
+
+void StmtPrinter::VisitDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *Node) {
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+ OS << Node->getNameInfo();
+ if (Node->hasExplicitTemplateArgs())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+}
+
+void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
+ if (Node->getQualifier())
+ Node->getQualifier()->print(OS, Policy);
+ OS << Node->getNameInfo();
+ if (Node->hasExplicitTemplateArgs())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+}
+
+void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ if (Node->getBase()) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ }
+ OS << Node->getDecl();
+}
+
+void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+ if (Node->isSuperReceiver())
+ OS << "super.";
+ else if (Node->getBase()) {
+ PrintExpr(Node->getBase());
+ OS << ".";
+ }
+
+ if (Node->isImplicitProperty())
+ OS << Node->getImplicitPropertyGetter()->getSelector().getAsString();
+ else
+ OS << Node->getExplicitProperty()->getName();
+}
+
+void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
+ switch (Node->getIdentType()) {
+ default:
+ assert(0 && "unknown case");
+ case PredefinedExpr::Func:
+ OS << "__func__";
+ break;
+ case PredefinedExpr::Function:
+ OS << "__FUNCTION__";
+ break;
+ case PredefinedExpr::PrettyFunction:
+ OS << "__PRETTY_FUNCTION__";
+ break;
+ }
+}
+
+void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
+ unsigned value = Node->getValue();
+ if (Node->isWide())
+ OS << "L";
+ switch (value) {
+ case '\\':
+ OS << "'\\\\'";
+ break;
+ case '\'':
+ OS << "'\\''";
+ break;
+ case '\a':
+ // TODO: K&R: the meaning of '\\a' is different in traditional C
+ OS << "'\\a'";
+ break;
+ case '\b':
+ OS << "'\\b'";
+ break;
+ // Nonstandard escape sequence.
+ /*case '\e':
+ OS << "'\\e'";
+ break;*/
+ case '\f':
+ OS << "'\\f'";
+ break;
+ case '\n':
+ OS << "'\\n'";
+ break;
+ case '\r':
+ OS << "'\\r'";
+ break;
+ case '\t':
+ OS << "'\\t'";
+ break;
+ case '\v':
+ OS << "'\\v'";
+ break;
+ default:
+ if (value < 256 && isprint(value)) {
+ OS << "'" << (char)value << "'";
+ } else if (value < 256) {
+ OS << "'\\x" << llvm::format("%x", value) << "'";
+ } else {
+ // FIXME what to really do here?
+ OS << value;
+ }
+ }
+}
+
+void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
+ bool isSigned = Node->getType()->isSignedIntegerType();
+ OS << Node->getValue().toString(10, isSigned);
+
+ // Emit suffixes. Integer literals are always a builtin integer type.
+ switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
+ default: assert(0 && "Unexpected type for integer literal!");
+ case BuiltinType::Int: break; // no suffix.
+ case BuiltinType::UInt: OS << 'U'; break;
+ case BuiltinType::Long: OS << 'L'; break;
+ case BuiltinType::ULong: OS << "UL"; break;
+ case BuiltinType::LongLong: OS << "LL"; break;
+ case BuiltinType::ULongLong: OS << "ULL"; break;
+ }
+}
+void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
+ // FIXME: print value more precisely.
+ OS << Node->getValueAsApproximateDouble();
+}
+
+void StmtPrinter::VisitImaginaryLiteral(ImaginaryLiteral *Node) {
+ PrintExpr(Node->getSubExpr());
+ OS << "i";
+}
+
+void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
+ if (Str->isWide()) OS << 'L';
+ OS << '"';
+
+ // FIXME: this doesn't print wstrings right.
+ llvm::StringRef StrData = Str->getString();
+ for (llvm::StringRef::iterator I = StrData.begin(), E = StrData.end();
+ I != E; ++I) {
+ unsigned char Char = *I;
+
+ switch (Char) {
+ default:
+ if (isprint(Char))
+ OS << (char)Char;
+ else // Output anything hard as an octal escape.
+ OS << '\\'
+ << (char)('0'+ ((Char >> 6) & 7))
+ << (char)('0'+ ((Char >> 3) & 7))
+ << (char)('0'+ ((Char >> 0) & 7));
+ break;
+ // Handle some common non-printable cases to make dumps prettier.
+ case '\\': OS << "\\\\"; break;
+ case '"': OS << "\\\""; break;
+ case '\n': OS << "\\n"; break;
+ case '\t': OS << "\\t"; break;
+ case '\a': OS << "\\a"; break;
+ case '\b': OS << "\\b"; break;
+ }
+ }
+ OS << '"';
+}
+void StmtPrinter::VisitParenExpr(ParenExpr *Node) {
+ OS << "(";
+ PrintExpr(Node->getSubExpr());
+ OS << ")";
+}
+void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
+ if (!Node->isPostfix()) {
+ OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
+
+ // Print a space if this is an "identifier operator" like __real, or if
+ // it might be concatenated incorrectly like '+'.
+ switch (Node->getOpcode()) {
+ default: break;
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
+ OS << ' ';
+ break;
+ case UO_Plus:
+ case UO_Minus:
+ if (isa<UnaryOperator>(Node->getSubExpr()))
+ OS << ' ';
+ break;
+ }
+ }
+ PrintExpr(Node->getSubExpr());
+
+ if (Node->isPostfix())
+ OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
+}
+
+void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
+ OS << "__builtin_offsetof(";
+ OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", ";
+ bool PrintedSomething = false;
+ for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
+ OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i);
+ if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Array) {
+ // Array node
+ OS << "[";
+ PrintExpr(Node->getIndexExpr(ON.getArrayExprIndex()));
+ OS << "]";
+ PrintedSomething = true;
+ continue;
+ }
+
+ // Skip implicit base indirections.
+ if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Base)
+ continue;
+
+ // Field or identifier node.
+ IdentifierInfo *Id = ON.getFieldName();
+ if (!Id)
+ continue;
+
+ if (PrintedSomething)
+ OS << ".";
+ else
+ PrintedSomething = true;
+ OS << Id->getName();
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+ OS << (Node->isSizeOf() ? "sizeof" : "__alignof");
+ if (Node->isArgumentType())
+ OS << "(" << Node->getArgumentType().getAsString(Policy) << ")";
+ else {
+ OS << " ";
+ PrintExpr(Node->getArgumentExpr());
+ }
+}
+void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
+ PrintExpr(Node->getLHS());
+ OS << "[";
+ PrintExpr(Node->getRHS());
+ OS << "]";
+}
+
+void StmtPrinter::PrintCallArgs(CallExpr *Call) {
+ for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
+ if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
+ // Don't print any defaulted arguments
+ break;
+ }
+
+ if (i) OS << ", ";
+ PrintExpr(Call->getArg(i));
+ }
+}
+
+void StmtPrinter::VisitCallExpr(CallExpr *Call) {
+ PrintExpr(Call->getCallee());
+ OS << "(";
+ PrintCallArgs(Call);
+ OS << ")";
+}
+void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
+ // FIXME: Suppress printing implicit bases (like "this")
+ PrintExpr(Node->getBase());
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
+ if (FD->isAnonymousStructOrUnion())
+ return;
+ OS << (Node->isArrow() ? "->" : ".");
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+
+ OS << Node->getMemberNameInfo();
+
+ if (Node->hasExplicitTemplateArgs())
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+}
+void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->isa" : ".isa");
+}
+
+void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << ".";
+ OS << Node->getAccessor().getName();
+}
+void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
+ OS << "(" << Node->getType().getAsString(Policy) << ")";
+ PrintExpr(Node->getSubExpr());
+}
+void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
+ OS << "(" << Node->getType().getAsString(Policy) << ")";
+ PrintExpr(Node->getInitializer());
+}
+void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
+ // No need to print anything, simply forward to the sub expression.
+ PrintExpr(Node->getSubExpr());
+}
+void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
+ PrintExpr(Node->getLHS());
+ OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
+ PrintExpr(Node->getRHS());
+}
+void StmtPrinter::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
+ PrintExpr(Node->getLHS());
+ OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
+ PrintExpr(Node->getRHS());
+}
+void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
+ PrintExpr(Node->getCond());
+ OS << " ? ";
+ PrintExpr(Node->getLHS());
+ OS << " : ";
+ PrintExpr(Node->getRHS());
+}
+
+// GNU extensions.
+
+void
+StmtPrinter::VisitBinaryConditionalOperator(BinaryConditionalOperator *Node) {
+ PrintExpr(Node->getCommon());
+ OS << " ?: ";
+ PrintExpr(Node->getFalseExpr());
+}
+void StmtPrinter::VisitAddrLabelExpr(AddrLabelExpr *Node) {
+ OS << "&&" << Node->getLabel()->getName();
+}
+
+void StmtPrinter::VisitStmtExpr(StmtExpr *E) {
+ OS << "(";
+ PrintRawCompoundStmt(E->getSubStmt());
+ OS << ")";
+}
+
+void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
+ OS << "__builtin_choose_expr(";
+ PrintExpr(Node->getCond());
+ OS << ", ";
+ PrintExpr(Node->getLHS());
+ OS << ", ";
+ PrintExpr(Node->getRHS());
+ OS << ")";
+}
+
+void StmtPrinter::VisitGNUNullExpr(GNUNullExpr *) {
+ OS << "__null";
+}
+
+void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) {
+ OS << "__builtin_shufflevector(";
+ for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
+ if (i) OS << ", ";
+ PrintExpr(Node->getExpr(i));
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
+ if (Node->getSyntacticForm()) {
+ Visit(Node->getSyntacticForm());
+ return;
+ }
+
+ OS << "{ ";
+ for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
+ if (i) OS << ", ";
+ if (Node->getInit(i))
+ PrintExpr(Node->getInit(i));
+ else
+ OS << "0";
+ }
+ OS << " }";
+}
+
+void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
+ OS << "( ";
+ for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
+ if (i) OS << ", ";
+ PrintExpr(Node->getExpr(i));
+ }
+ OS << " )";
+}
+
+void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
+ for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(),
+ DEnd = Node->designators_end();
+ D != DEnd; ++D) {
+ if (D->isFieldDesignator()) {
+ if (D->getDotLoc().isInvalid())
+ OS << D->getFieldName()->getName() << ":";
+ else
+ OS << "." << D->getFieldName()->getName();
+ } else {
+ OS << "[";
+ if (D->isArrayDesignator()) {
+ PrintExpr(Node->getArrayIndex(*D));
+ } else {
+ PrintExpr(Node->getArrayRangeStart(*D));
+ OS << " ... ";
+ PrintExpr(Node->getArrayRangeEnd(*D));
+ }
+ OS << "]";
+ }
+ }
+
+ OS << " = ";
+ PrintExpr(Node->getInit());
+}
+
+void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
+ if (Policy.LangOpts.CPlusPlus)
+ OS << "/*implicit*/" << Node->getType().getAsString(Policy) << "()";
+ else {
+ OS << "/*implicit*/(" << Node->getType().getAsString(Policy) << ")";
+ if (Node->getType()->isRecordType())
+ OS << "{}";
+ else
+ OS << 0;
+ }
+}
+
+void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
+ OS << "__builtin_va_arg(";
+ PrintExpr(Node->getSubExpr());
+ OS << ", ";
+ OS << Node->getType().getAsString(Policy);
+ OS << ")";
+}
+
+// C++
+void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
+ const char *OpStrings[NUM_OVERLOADED_OPERATORS] = {
+ "",
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ Spelling,
+#include "clang/Basic/OperatorKinds.def"
+ };
+
+ OverloadedOperatorKind Kind = Node->getOperator();
+ if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+ if (Node->getNumArgs() == 1) {
+ OS << OpStrings[Kind] << ' ';
+ PrintExpr(Node->getArg(0));
+ } else {
+ PrintExpr(Node->getArg(0));
+ OS << ' ' << OpStrings[Kind];
+ }
+ } else if (Kind == OO_Call) {
+ PrintExpr(Node->getArg(0));
+ OS << '(';
+ for (unsigned ArgIdx = 1; ArgIdx < Node->getNumArgs(); ++ArgIdx) {
+ if (ArgIdx > 1)
+ OS << ", ";
+ if (!isa<CXXDefaultArgExpr>(Node->getArg(ArgIdx)))
+ PrintExpr(Node->getArg(ArgIdx));
+ }
+ OS << ')';
+ } else if (Kind == OO_Subscript) {
+ PrintExpr(Node->getArg(0));
+ OS << '[';
+ PrintExpr(Node->getArg(1));
+ OS << ']';
+ } else if (Node->getNumArgs() == 1) {
+ OS << OpStrings[Kind] << ' ';
+ PrintExpr(Node->getArg(0));
+ } else if (Node->getNumArgs() == 2) {
+ PrintExpr(Node->getArg(0));
+ OS << ' ' << OpStrings[Kind] << ' ';
+ PrintExpr(Node->getArg(1));
+ } else {
+ assert(false && "unknown overloaded operator");
+ }
+}
+
+void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
+ VisitCallExpr(cast<CallExpr>(Node));
+}
+
+void StmtPrinter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *Node) {
+ PrintExpr(Node->getCallee());
+ OS << "<<<";
+ PrintCallArgs(Node->getConfig());
+ OS << ">>>(";
+ PrintCallArgs(Node);
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+ OS << Node->getCastName() << '<';
+ OS << Node->getTypeAsWritten().getAsString(Policy) << ">(";
+ PrintExpr(Node->getSubExpr());
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXStaticCastExpr(CXXStaticCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
+ OS << "typeid(";
+ if (Node->isTypeOperand()) {
+ OS << Node->getTypeOperand().getAsString(Policy);
+ } else {
+ PrintExpr(Node->getExprOperand());
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) {
+ OS << "__uuidof(";
+ if (Node->isTypeOperand()) {
+ OS << Node->getTypeOperand().getAsString(Policy);
+ } else {
+ PrintExpr(Node->getExprOperand());
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
+ OS << (Node->getValue() ? "true" : "false");
+}
+
+void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
+ OS << "nullptr";
+}
+
+void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
+ OS << "this";
+}
+
+void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
+ if (Node->getSubExpr() == 0)
+ OS << "throw";
+ else {
+ OS << "throw ";
+ PrintExpr(Node->getSubExpr());
+ }
+}
+
+void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
+ // Nothing to print: we picked up the default argument
+}
+
+void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+ OS << Node->getType().getAsString(Policy);
+ OS << "(";
+ PrintExpr(Node->getSubExpr());
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
+ PrintExpr(Node->getSubExpr());
+}
+
+void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
+ OS << Node->getType().getAsString(Policy);
+ OS << "(";
+ for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
+ ArgEnd = Node->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ if (Arg != Node->arg_begin())
+ OS << ", ";
+ PrintExpr(*Arg);
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
+ if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
+ OS << TSInfo->getType().getAsString(Policy) << "()";
+ else
+ OS << Node->getType().getAsString(Policy) << "()";
+}
+
+void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
+ if (E->isGlobalNew())
+ OS << "::";
+ OS << "new ";
+ unsigned NumPlace = E->getNumPlacementArgs();
+ if (NumPlace > 0) {
+ OS << "(";
+ PrintExpr(E->getPlacementArg(0));
+ for (unsigned i = 1; i < NumPlace; ++i) {
+ OS << ", ";
+ PrintExpr(E->getPlacementArg(i));
+ }
+ OS << ") ";
+ }
+ if (E->isParenTypeId())
+ OS << "(";
+ std::string TypeS;
+ if (Expr *Size = E->getArraySize()) {
+ llvm::raw_string_ostream s(TypeS);
+ Size->printPretty(s, Context, Helper, Policy);
+ s.flush();
+ TypeS = "[" + TypeS + "]";
+ }
+ E->getAllocatedType().getAsStringInternal(TypeS, Policy);
+ OS << TypeS;
+ if (E->isParenTypeId())
+ OS << ")";
+
+ if (E->hasInitializer()) {
+ OS << "(";
+ unsigned NumCons = E->getNumConstructorArgs();
+ if (NumCons > 0) {
+ PrintExpr(E->getConstructorArg(0));
+ for (unsigned i = 1; i < NumCons; ++i) {
+ OS << ", ";
+ PrintExpr(E->getConstructorArg(i));
+ }
+ }
+ OS << ")";
+ }
+}
+
+void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ if (E->isGlobalDelete())
+ OS << "::";
+ OS << "delete ";
+ if (E->isArrayForm())
+ OS << "[] ";
+ PrintExpr(E->getArgument());
+}
+
+void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ PrintExpr(E->getBase());
+ if (E->isArrow())
+ OS << "->";
+ else
+ OS << '.';
+ if (E->getQualifier())
+ E->getQualifier()->print(OS, Policy);
+
+ std::string TypeS;
+ if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
+ OS << II->getName();
+ else
+ E->getDestroyedType().getAsStringInternal(TypeS, Policy);
+ OS << TypeS;
+}
+
+void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ if (isa<CXXDefaultArgExpr>(E->getArg(i))) {
+ // Don't print any defaulted arguments
+ break;
+ }
+
+ if (i) OS << ", ";
+ PrintExpr(E->getArg(i));
+ }
+}
+
+void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) {
+ // Just forward to the sub expression.
+ PrintExpr(E->getSubExpr());
+}
+
+void
+StmtPrinter::VisitCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *Node) {
+ OS << Node->getTypeAsWritten().getAsString(Policy);
+ OS << "(";
+ for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(),
+ ArgEnd = Node->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ if (Arg != Node->arg_begin())
+ OS << ", ";
+ PrintExpr(*Arg);
+ }
+ OS << ")";
+}
+
+void StmtPrinter::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *Node) {
+ if (!Node->isImplicitAccess()) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ }
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+ else if (Node->hasExplicitTemplateArgs())
+ // FIXME: Track use of "template" keyword explicitly?
+ OS << "template ";
+
+ OS << Node->getMemberNameInfo();
+
+ if (Node->hasExplicitTemplateArgs()) {
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+ }
+}
+
+void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
+ if (!Node->isImplicitAccess()) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ }
+ if (NestedNameSpecifier *Qualifier = Node->getQualifier())
+ Qualifier->print(OS, Policy);
+
+ // FIXME: this might originally have been written with 'template'
+
+ OS << Node->getMemberNameInfo();
+
+ if (Node->hasExplicitTemplateArgs()) {
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ Node->getTemplateArgs(),
+ Node->getNumTemplateArgs(),
+ Policy);
+ }
+}
+
+static const char *getTypeTraitName(UnaryTypeTrait UTT) {
+ switch (UTT) {
+ default: llvm_unreachable("Unknown unary type trait");
+ case UTT_HasNothrowAssign: return "__has_nothrow_assign";
+ case UTT_HasNothrowCopy: return "__has_nothrow_copy";
+ case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
+ case UTT_HasTrivialAssign: return "__has_trivial_assign";
+ case UTT_HasTrivialCopy: return "__has_trivial_copy";
+ case UTT_HasTrivialConstructor: return "__has_trivial_constructor";
+ case UTT_HasTrivialDestructor: return "__has_trivial_destructor";
+ case UTT_HasVirtualDestructor: return "__has_virtual_destructor";
+ case UTT_IsAbstract: return "__is_abstract";
+ case UTT_IsClass: return "__is_class";
+ case UTT_IsEmpty: return "__is_empty";
+ case UTT_IsEnum: return "__is_enum";
+ case UTT_IsPOD: return "__is_pod";
+ case UTT_IsPolymorphic: return "__is_polymorphic";
+ case UTT_IsUnion: return "__is_union";
+ }
+ return "";
+}
+
+static const char *getTypeTraitName(BinaryTypeTrait BTT) {
+ switch (BTT) {
+ case BTT_IsBaseOf: return "__is_base_of";
+ case BTT_TypeCompatible: return "__builtin_types_compatible_p";
+ case BTT_IsConvertibleTo: return "__is_convertible_to";
+ }
+ return "";
+}
+
+void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ OS << getTypeTraitName(E->getTrait()) << "("
+ << E->getQueriedType().getAsString(Policy) << ")";
+}
+
+void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ OS << getTypeTraitName(E->getTrait()) << "("
+ << E->getLhsType().getAsString(Policy) << ","
+ << E->getRhsType().getAsString(Policy) << ")";
+}
+
+void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ OS << "noexcept(";
+ PrintExpr(E->getOperand());
+ OS << ")";
+}
+
+void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) {
+ PrintExpr(E->getPattern());
+ OS << "...";
+}
+
+void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ OS << "sizeof...(" << E->getPack()->getNameAsString() << ")";
+}
+
+void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *Node) {
+ OS << Node->getParameterPack()->getNameAsString();
+}
+
+// Obj-C
+
+void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
+ OS << "@";
+ VisitStringLiteral(Node->getString());
+}
+
+void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
+ OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')';
+}
+
+void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+ OS << "@selector(" << Node->getSelector().getAsString() << ')';
+}
+
+void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+ OS << "@protocol(" << Node->getProtocol() << ')';
+}
+
+void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
+ OS << "[";
+ switch (Mess->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ PrintExpr(Mess->getInstanceReceiver());
+ break;
+
+ case ObjCMessageExpr::Class:
+ OS << Mess->getClassReceiver().getAsString(Policy);
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ case ObjCMessageExpr::SuperClass:
+ OS << "Super";
+ break;
+ }
+
+ OS << ' ';
+ Selector selector = Mess->getSelector();
+ if (selector.isUnarySelector()) {
+ OS << selector.getNameForSlot(0);
+ } else {
+ for (unsigned i = 0, e = Mess->getNumArgs(); i != e; ++i) {
+ if (i < selector.getNumArgs()) {
+ if (i > 0) OS << ' ';
+ if (selector.getIdentifierInfoForSlot(i))
+ OS << selector.getIdentifierInfoForSlot(i)->getName() << ':';
+ else
+ OS << ":";
+ }
+ else OS << ", "; // Handle variadic methods.
+
+ PrintExpr(Mess->getArg(i));
+ }
+ }
+ OS << "]";
+}
+
+
+void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
+ BlockDecl *BD = Node->getBlockDecl();
+ OS << "^";
+
+ const FunctionType *AFT = Node->getFunctionType();
+
+ if (isa<FunctionNoProtoType>(AFT)) {
+ OS << "()";
+ } else if (!BD->param_empty() || cast<FunctionProtoType>(AFT)->isVariadic()) {
+ OS << '(';
+ std::string ParamStr;
+ for (BlockDecl::param_iterator AI = BD->param_begin(),
+ E = BD->param_end(); AI != E; ++AI) {
+ if (AI != BD->param_begin()) OS << ", ";
+ ParamStr = (*AI)->getNameAsString();
+ (*AI)->getType().getAsStringInternal(ParamStr, Policy);
+ OS << ParamStr;
+ }
+
+ const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
+ if (FT->isVariadic()) {
+ if (!BD->param_empty()) OS << ", ";
+ OS << "...";
+ }
+ OS << ')';
+ }
+}
+
+void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) {
+ OS << Node->getDecl();
+}
+
+void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {}
+
+//===----------------------------------------------------------------------===//
+// Stmt method implementations
+//===----------------------------------------------------------------------===//
+
+void Stmt::dumpPretty(ASTContext& Context) const {
+ printPretty(llvm::errs(), Context, 0,
+ PrintingPolicy(Context.getLangOptions()));
+}
+
+void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
+ PrinterHelper* Helper,
+ const PrintingPolicy &Policy,
+ unsigned Indentation) const {
+ if (this == 0) {
+ OS << "<NULL>";
+ return;
+ }
+
+ if (Policy.Dump && &Context) {
+ dump(OS, Context.getSourceManager());
+ return;
+ }
+
+ StmtPrinter P(OS, Context, Helper, Policy, Indentation);
+ P.Visit(const_cast<Stmt*>(this));
+}
+
+//===----------------------------------------------------------------------===//
+// PrinterHelper
+//===----------------------------------------------------------------------===//
+
+// Implement virtual destructor.
+PrinterHelper::~PrinterHelper() {}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
new file mode 100644
index 0000000..b540011
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -0,0 +1,1016 @@
+//===---- StmtProfile.cpp - Profile implementation for Stmt ASTs ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::Profile method, which builds a unique bit
+// representation that identifies a statement/expression.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/FoldingSet.h"
+using namespace clang;
+
+namespace {
+ class StmtProfiler : public StmtVisitor<StmtProfiler> {
+ llvm::FoldingSetNodeID &ID;
+ const ASTContext &Context;
+ bool Canonical;
+
+ public:
+ StmtProfiler(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ bool Canonical)
+ : ID(ID), Context(Context), Canonical(Canonical) { }
+
+ void VisitStmt(Stmt *S);
+
+#define STMT(Node, Base) void Visit##Node(Node *S);
+#include "clang/AST/StmtNodes.inc"
+
+ /// \brief Visit a declaration that is referenced within an expression
+ /// or statement.
+ void VisitDecl(Decl *D);
+
+ /// \brief Visit a type that is referenced within an expression or
+ /// statement.
+ void VisitType(QualType T);
+
+ /// \brief Visit a name that occurs within an expression or statement.
+ void VisitName(DeclarationName Name);
+
+ /// \brief Visit a nested-name-specifier that occurs within an expression
+ /// or statement.
+ void VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+ /// \brief Visit a template name that occurs within an expression or
+ /// statement.
+ void VisitTemplateName(TemplateName Name);
+
+ /// \brief Visit template arguments that occur within an expression or
+ /// statement.
+ void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs);
+
+ /// \brief Visit a single template argument.
+ void VisitTemplateArgument(const TemplateArgument &Arg);
+ };
+}
+
+void StmtProfiler::VisitStmt(Stmt *S) {
+ ID.AddInteger(S->getStmtClass());
+ for (Stmt::child_range C = S->children(); C; ++C)
+ Visit(*C);
+}
+
+void StmtProfiler::VisitDeclStmt(DeclStmt *S) {
+ VisitStmt(S);
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D)
+ VisitDecl(*D);
+}
+
+void StmtProfiler::VisitNullStmt(NullStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitCompoundStmt(CompoundStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitSwitchCase(SwitchCase *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitCaseStmt(CaseStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitDefaultStmt(DefaultStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitLabelStmt(LabelStmt *S) {
+ VisitStmt(S);
+ VisitDecl(S->getDecl());
+}
+
+void StmtProfiler::VisitIfStmt(IfStmt *S) {
+ VisitStmt(S);
+ VisitDecl(S->getConditionVariable());
+}
+
+void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) {
+ VisitStmt(S);
+ VisitDecl(S->getConditionVariable());
+}
+
+void StmtProfiler::VisitWhileStmt(WhileStmt *S) {
+ VisitStmt(S);
+ VisitDecl(S->getConditionVariable());
+}
+
+void StmtProfiler::VisitDoStmt(DoStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitForStmt(ForStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitGotoStmt(GotoStmt *S) {
+ VisitStmt(S);
+ VisitDecl(S->getLabel());
+}
+
+void StmtProfiler::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitContinueStmt(ContinueStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitBreakStmt(BreakStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitReturnStmt(ReturnStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitAsmStmt(AsmStmt *S) {
+ VisitStmt(S);
+ ID.AddBoolean(S->isVolatile());
+ ID.AddBoolean(S->isSimple());
+ VisitStringLiteral(S->getAsmString());
+ ID.AddInteger(S->getNumOutputs());
+ for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
+ ID.AddString(S->getOutputName(I));
+ VisitStringLiteral(S->getOutputConstraintLiteral(I));
+ }
+ ID.AddInteger(S->getNumInputs());
+ for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
+ ID.AddString(S->getInputName(I));
+ VisitStringLiteral(S->getInputConstraintLiteral(I));
+ }
+ ID.AddInteger(S->getNumClobbers());
+ for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
+ VisitStringLiteral(S->getClobber(I));
+}
+
+void StmtProfiler::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ VisitStmt(S);
+ VisitType(S->getCaughtType());
+}
+
+void StmtProfiler::VisitCXXTryStmt(CXXTryStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ VisitStmt(S);
+ ID.AddBoolean(S->hasEllipsis());
+ if (S->getCatchParamDecl())
+ VisitType(S->getCatchParamDecl()->getType());
+}
+
+void StmtProfiler::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitExpr(Expr *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
+ VisitExpr(S);
+ if (!Canonical)
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitDecl(S->getDecl());
+ if (!Canonical)
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getIdentType());
+}
+
+void StmtProfiler::VisitIntegerLiteral(IntegerLiteral *S) {
+ VisitExpr(S);
+ S->getValue().Profile(ID);
+}
+
+void StmtProfiler::VisitCharacterLiteral(CharacterLiteral *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isWide());
+ ID.AddInteger(S->getValue());
+}
+
+void StmtProfiler::VisitFloatingLiteral(FloatingLiteral *S) {
+ VisitExpr(S);
+ S->getValue().Profile(ID);
+ ID.AddBoolean(S->isExact());
+}
+
+void StmtProfiler::VisitImaginaryLiteral(ImaginaryLiteral *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitStringLiteral(StringLiteral *S) {
+ VisitExpr(S);
+ ID.AddString(S->getString());
+ ID.AddBoolean(S->isWide());
+}
+
+void StmtProfiler::VisitParenExpr(ParenExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitParenListExpr(ParenListExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitUnaryOperator(UnaryOperator *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getOpcode());
+}
+
+void StmtProfiler::VisitOffsetOfExpr(OffsetOfExpr *S) {
+ VisitType(S->getTypeSourceInfo()->getType());
+ unsigned n = S->getNumComponents();
+ for (unsigned i = 0; i < n; ++i) {
+ const OffsetOfExpr::OffsetOfNode& ON = S->getComponent(i);
+ ID.AddInteger(ON.getKind());
+ switch (ON.getKind()) {
+ case OffsetOfExpr::OffsetOfNode::Array:
+ // Expressions handled below.
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Field:
+ VisitDecl(ON.getField());
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Identifier:
+ ID.AddPointer(ON.getFieldName());
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Base:
+ // These nodes are implicit, and therefore don't need profiling.
+ break;
+ }
+ }
+
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isSizeOf());
+ if (S->isArgumentType())
+ VisitType(S->getArgumentType());
+}
+
+void StmtProfiler::VisitArraySubscriptExpr(ArraySubscriptExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCallExpr(CallExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitMemberExpr(MemberExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getMemberDecl());
+ if (!Canonical)
+ VisitNestedNameSpecifier(S->getQualifier());
+ ID.AddBoolean(S->isArrow());
+}
+
+void StmtProfiler::VisitCompoundLiteralExpr(CompoundLiteralExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isFileScope());
+}
+
+void StmtProfiler::VisitCastExpr(CastExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitImplicitCastExpr(ImplicitCastExpr *S) {
+ VisitCastExpr(S);
+ ID.AddInteger(S->getValueKind());
+}
+
+void StmtProfiler::VisitExplicitCastExpr(ExplicitCastExpr *S) {
+ VisitCastExpr(S);
+ VisitType(S->getTypeAsWritten());
+}
+
+void StmtProfiler::VisitCStyleCastExpr(CStyleCastExpr *S) {
+ VisitExplicitCastExpr(S);
+}
+
+void StmtProfiler::VisitBinaryOperator(BinaryOperator *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getOpcode());
+}
+
+void StmtProfiler::VisitCompoundAssignOperator(CompoundAssignOperator *S) {
+ VisitBinaryOperator(S);
+}
+
+void StmtProfiler::VisitConditionalOperator(ConditionalOperator *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitBinaryConditionalOperator(BinaryConditionalOperator *S){
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitAddrLabelExpr(AddrLabelExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getLabel());
+}
+
+void StmtProfiler::VisitStmtExpr(StmtExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitShuffleVectorExpr(ShuffleVectorExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitChooseExpr(ChooseExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitGNUNullExpr(GNUNullExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitVAArgExpr(VAArgExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitInitListExpr(InitListExpr *S) {
+ if (S->getSyntacticForm()) {
+ VisitInitListExpr(S->getSyntacticForm());
+ return;
+ }
+
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitDesignatedInitExpr(DesignatedInitExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->usesGNUSyntax());
+ for (DesignatedInitExpr::designators_iterator D = S->designators_begin(),
+ DEnd = S->designators_end();
+ D != DEnd; ++D) {
+ if (D->isFieldDesignator()) {
+ ID.AddInteger(0);
+ VisitName(D->getFieldName());
+ continue;
+ }
+
+ if (D->isArrayDesignator()) {
+ ID.AddInteger(1);
+ } else {
+ assert(D->isArrayRangeDesignator());
+ ID.AddInteger(2);
+ }
+ ID.AddInteger(D->getFirstExprIndex());
+ }
+}
+
+void StmtProfiler::VisitImplicitValueInitExpr(ImplicitValueInitExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitExtVectorElementExpr(ExtVectorElementExpr *S) {
+ VisitExpr(S);
+ VisitName(&S->getAccessor());
+}
+
+void StmtProfiler::VisitBlockExpr(BlockExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getBlockDecl());
+}
+
+void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getDecl());
+ ID.AddBoolean(S->isByRef());
+ ID.AddBoolean(S->isConstQualAdded());
+}
+
+static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
+ UnaryOperatorKind &UnaryOp,
+ BinaryOperatorKind &BinaryOp) {
+ switch (S->getOperator()) {
+ case OO_None:
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ case OO_Arrow:
+ case OO_Call:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("Invalid operator call kind");
+ return Stmt::ArraySubscriptExprClass;
+
+ case OO_Plus:
+ if (S->getNumArgs() == 1) {
+ UnaryOp = UO_Plus;
+ return Stmt::UnaryOperatorClass;
+ }
+
+ BinaryOp = BO_Add;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Minus:
+ if (S->getNumArgs() == 1) {
+ UnaryOp = UO_Minus;
+ return Stmt::UnaryOperatorClass;
+ }
+
+ BinaryOp = BO_Sub;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Star:
+ if (S->getNumArgs() == 1) {
+ UnaryOp = UO_Minus;
+ return Stmt::UnaryOperatorClass;
+ }
+
+ BinaryOp = BO_Sub;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Slash:
+ BinaryOp = BO_Div;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Percent:
+ BinaryOp = BO_Rem;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Caret:
+ BinaryOp = BO_Xor;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Amp:
+ if (S->getNumArgs() == 1) {
+ UnaryOp = UO_AddrOf;
+ return Stmt::UnaryOperatorClass;
+ }
+
+ BinaryOp = BO_And;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Pipe:
+ BinaryOp = BO_Or;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Tilde:
+ UnaryOp = UO_Not;
+ return Stmt::UnaryOperatorClass;
+
+ case OO_Exclaim:
+ UnaryOp = UO_LNot;
+ return Stmt::UnaryOperatorClass;
+
+ case OO_Equal:
+ BinaryOp = BO_Assign;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Less:
+ BinaryOp = BO_LT;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Greater:
+ BinaryOp = BO_GT;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_PlusEqual:
+ BinaryOp = BO_AddAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_MinusEqual:
+ BinaryOp = BO_SubAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_StarEqual:
+ BinaryOp = BO_MulAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_SlashEqual:
+ BinaryOp = BO_DivAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_PercentEqual:
+ BinaryOp = BO_RemAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_CaretEqual:
+ BinaryOp = BO_XorAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_AmpEqual:
+ BinaryOp = BO_AndAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_PipeEqual:
+ BinaryOp = BO_OrAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_LessLess:
+ BinaryOp = BO_Shl;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_GreaterGreater:
+ BinaryOp = BO_Shr;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_LessLessEqual:
+ BinaryOp = BO_ShlAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_GreaterGreaterEqual:
+ BinaryOp = BO_ShrAssign;
+ return Stmt::CompoundAssignOperatorClass;
+
+ case OO_EqualEqual:
+ BinaryOp = BO_EQ;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_ExclaimEqual:
+ BinaryOp = BO_NE;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_LessEqual:
+ BinaryOp = BO_LE;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_GreaterEqual:
+ BinaryOp = BO_GE;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_AmpAmp:
+ BinaryOp = BO_LAnd;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_PipePipe:
+ BinaryOp = BO_LOr;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_PlusPlus:
+ UnaryOp = S->getNumArgs() == 1? UO_PreInc
+ : UO_PostInc;
+ return Stmt::UnaryOperatorClass;
+
+ case OO_MinusMinus:
+ UnaryOp = S->getNumArgs() == 1? UO_PreDec
+ : UO_PostDec;
+ return Stmt::UnaryOperatorClass;
+
+ case OO_Comma:
+ BinaryOp = BO_Comma;
+ return Stmt::BinaryOperatorClass;
+
+
+ case OO_ArrowStar:
+ BinaryOp = BO_PtrMemI;
+ return Stmt::BinaryOperatorClass;
+
+ case OO_Subscript:
+ return Stmt::ArraySubscriptExprClass;
+ }
+
+ llvm_unreachable("Invalid overloaded operator expression");
+}
+
+
+void StmtProfiler::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
+ if (S->isTypeDependent()) {
+ // Type-dependent operator calls are profiled like their underlying
+ // syntactic operator.
+ UnaryOperatorKind UnaryOp = UO_Extension;
+ BinaryOperatorKind BinaryOp = BO_Comma;
+ Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp);
+
+ ID.AddInteger(SC);
+ for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
+ Visit(S->getArg(I));
+ if (SC == Stmt::UnaryOperatorClass)
+ ID.AddInteger(UnaryOp);
+ else if (SC == Stmt::BinaryOperatorClass ||
+ SC == Stmt::CompoundAssignOperatorClass)
+ ID.AddInteger(BinaryOp);
+ else
+ assert(SC == Stmt::ArraySubscriptExprClass);
+
+ return;
+ }
+
+ VisitCallExpr(S);
+ ID.AddInteger(S->getOperator());
+}
+
+void StmtProfiler::VisitCXXMemberCallExpr(CXXMemberCallExpr *S) {
+ VisitCallExpr(S);
+}
+
+void StmtProfiler::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *S) {
+ VisitCallExpr(S);
+}
+
+void StmtProfiler::VisitCXXNamedCastExpr(CXXNamedCastExpr *S) {
+ VisitExplicitCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXStaticCastExpr(CXXStaticCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXConstCastExpr(CXXConstCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->getValue());
+}
+
+void StmtProfiler::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) {
+ VisitExpr(S);
+ if (S->isTypeOperand())
+ VisitType(S->getTypeOperand());
+}
+
+void StmtProfiler::VisitCXXUuidofExpr(CXXUuidofExpr *S) {
+ VisitExpr(S);
+ if (S->isTypeOperand())
+ VisitType(S->getTypeOperand());
+}
+
+void StmtProfiler::VisitCXXThisExpr(CXXThisExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCXXThrowExpr(CXXThrowExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getParam());
+}
+
+void StmtProfiler::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *S) {
+ VisitExpr(S);
+ VisitDecl(
+ const_cast<CXXDestructorDecl *>(S->getTemporary()->getDestructor()));
+}
+
+void StmtProfiler::VisitCXXConstructExpr(CXXConstructExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getConstructor());
+ ID.AddBoolean(S->isElidable());
+}
+
+void StmtProfiler::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *S) {
+ VisitExplicitCastExpr(S);
+}
+
+void StmtProfiler::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *S) {
+ VisitCXXConstructExpr(S);
+}
+
+void StmtProfiler::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isGlobalDelete());
+ ID.AddBoolean(S->isArrayForm());
+ VisitDecl(S->getOperatorDelete());
+}
+
+
+void StmtProfiler::VisitCXXNewExpr(CXXNewExpr *S) {
+ VisitExpr(S);
+ VisitType(S->getAllocatedType());
+ VisitDecl(S->getOperatorNew());
+ VisitDecl(S->getOperatorDelete());
+ VisitDecl(S->getConstructor());
+ ID.AddBoolean(S->isArray());
+ ID.AddInteger(S->getNumPlacementArgs());
+ ID.AddBoolean(S->isGlobalNew());
+ ID.AddBoolean(S->isParenTypeId());
+ ID.AddBoolean(S->hasInitializer());
+ ID.AddInteger(S->getNumConstructorArgs());
+}
+
+void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isArrow());
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitType(S->getDestroyedType());
+}
+
+void StmtProfiler::VisitOverloadExpr(OverloadExpr *S) {
+ VisitExpr(S);
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitName(S->getName());
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getExplicitTemplateArgs().NumTemplateArgs);
+}
+
+void
+StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+ VisitOverloadExpr(S);
+}
+
+void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getTrait());
+ VisitType(S->getQueriedType());
+}
+
+void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getTrait());
+ VisitType(S->getLhsType());
+ VisitType(S->getRhsType());
+}
+
+void
+StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
+ VisitExpr(S);
+ VisitName(S->getDeclName());
+ VisitNestedNameSpecifier(S->getQualifier());
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitExprWithCleanups(ExprWithCleanups *S) {
+ VisitExpr(S);
+}
+
+void
+StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) {
+ VisitExpr(S);
+ VisitType(S->getTypeAsWritten());
+}
+
+void
+StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
+ ID.AddBoolean(S->isImplicitAccess());
+ if (!S->isImplicitAccess()) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isArrow());
+ }
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitName(S->getMember());
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
+ ID.AddBoolean(S->isImplicitAccess());
+ if (!S->isImplicitAccess()) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isArrow());
+ }
+ VisitNestedNameSpecifier(S->getQualifier());
+ VisitName(S->getMemberName());
+ ID.AddBoolean(S->hasExplicitTemplateArgs());
+ if (S->hasExplicitTemplateArgs())
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+}
+
+void StmtProfiler::VisitCXXNoexceptExpr(CXXNoexceptExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitPackExpansionExpr(PackExpansionExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitSizeOfPackExpr(SizeOfPackExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getPack());
+}
+
+void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getParameterPack());
+ VisitTemplateArgument(S->getArgumentPack());
+}
+
+void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ VisitExpr(E);
+}
+
+void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitObjCEncodeExpr(ObjCEncodeExpr *S) {
+ VisitExpr(S);
+ VisitType(S->getEncodedType());
+}
+
+void StmtProfiler::VisitObjCSelectorExpr(ObjCSelectorExpr *S) {
+ VisitExpr(S);
+ VisitName(S->getSelector());
+}
+
+void StmtProfiler::VisitObjCProtocolExpr(ObjCProtocolExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getProtocol());
+}
+
+void StmtProfiler::VisitObjCIvarRefExpr(ObjCIvarRefExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getDecl());
+ ID.AddBoolean(S->isArrow());
+ ID.AddBoolean(S->isFreeIvar());
+}
+
+void StmtProfiler::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *S) {
+ VisitExpr(S);
+ if (S->isImplicitProperty()) {
+ VisitDecl(S->getImplicitPropertyGetter());
+ VisitDecl(S->getImplicitPropertySetter());
+ } else {
+ VisitDecl(S->getExplicitProperty());
+ }
+ if (S->isSuperReceiver()) {
+ ID.AddBoolean(S->isSuperReceiver());
+ VisitType(S->getSuperReceiverType());
+ }
+}
+
+void StmtProfiler::VisitObjCMessageExpr(ObjCMessageExpr *S) {
+ VisitExpr(S);
+ VisitName(S->getSelector());
+ VisitDecl(S->getMethodDecl());
+}
+
+void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) {
+ VisitExpr(S);
+ ID.AddBoolean(S->isArrow());
+}
+
+void StmtProfiler::VisitDecl(Decl *D) {
+ ID.AddInteger(D? D->getKind() : 0);
+
+ if (Canonical && D) {
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ ID.AddInteger(NTTP->getDepth());
+ ID.AddInteger(NTTP->getIndex());
+ ID.AddBoolean(NTTP->isParameterPack());
+ VisitType(NTTP->getType());
+ return;
+ }
+
+ if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
+ // The Itanium C++ ABI uses the type of a parameter when mangling
+ // expressions that involve function parameters, so we will use the
+ // parameter's type for establishing function parameter identity. That
+ // way, our definition of "equivalent" (per C++ [temp.over.link])
+ // matches the definition of "equivalent" used for name mangling.
+ VisitType(Parm->getType());
+ return;
+ }
+
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ ID.AddInteger(TTP->getDepth());
+ ID.AddInteger(TTP->getIndex());
+ ID.AddBoolean(TTP->isParameterPack());
+ return;
+ }
+ }
+
+ ID.AddPointer(D? D->getCanonicalDecl() : 0);
+}
+
+void StmtProfiler::VisitType(QualType T) {
+ if (Canonical)
+ T = Context.getCanonicalType(T);
+
+ ID.AddPointer(T.getAsOpaquePtr());
+}
+
+void StmtProfiler::VisitName(DeclarationName Name) {
+ ID.AddPointer(Name.getAsOpaquePtr());
+}
+
+void StmtProfiler::VisitNestedNameSpecifier(NestedNameSpecifier *NNS) {
+ if (Canonical)
+ NNS = Context.getCanonicalNestedNameSpecifier(NNS);
+ ID.AddPointer(NNS);
+}
+
+void StmtProfiler::VisitTemplateName(TemplateName Name) {
+ if (Canonical)
+ Name = Context.getCanonicalTemplateName(Name);
+
+ Name.Profile(ID);
+}
+
+void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs) {
+ ID.AddInteger(NumArgs);
+ for (unsigned I = 0; I != NumArgs; ++I)
+ VisitTemplateArgument(Args[I].getArgument());
+}
+
+void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
+ // Mostly repetitive with TemplateArgument::Profile!
+ ID.AddInteger(Arg.getKind());
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
+ break;
+
+ case TemplateArgument::Declaration:
+ VisitDecl(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::Integral:
+ Arg.getAsIntegral()->Profile(ID);
+ VisitType(Arg.getIntegralType());
+ break;
+
+ case TemplateArgument::Expression:
+ Visit(Arg.getAsExpr());
+ break;
+
+ case TemplateArgument::Pack:
+ const TemplateArgument *Pack = Arg.pack_begin();
+ for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i)
+ VisitTemplateArgument(Pack[i]);
+ break;
+ }
+}
+
+void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ bool Canonical) {
+ StmtProfiler Profiler(ID, Context, Canonical);
+ Profiler.Visit(this);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtViz.cpp b/contrib/llvm/tools/clang/lib/AST/StmtViz.cpp
new file mode 100644
index 0000000..8be287e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtViz.cpp
@@ -0,0 +1,62 @@
+//===--- StmtViz.cpp - Graphviz visualization for Stmt ASTs -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Stmt::viewAST, which generates a Graphviz DOT file
+// that depicts the AST and then calls Graphviz/dot+gv on it.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtGraphTraits.h"
+#include "clang/AST/Decl.h"
+#include "llvm/Support/GraphWriter.h"
+
+using namespace clang;
+
+void Stmt::viewAST() const {
+#ifndef NDEBUG
+ llvm::ViewGraph(this,"AST");
+#else
+ llvm::errs() << "Stmt::viewAST is only available in debug builds on "
+ << "systems with Graphviz or gv!\n";
+#endif
+}
+
+namespace llvm {
+template<>
+struct DOTGraphTraits<const Stmt*> : public DefaultDOTGraphTraits {
+ DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+
+ static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph) {
+
+#ifndef NDEBUG
+ std::string OutSStr;
+ llvm::raw_string_ostream Out(OutSStr);
+
+ if (Node)
+ Out << Node->getStmtClassName();
+ else
+ Out << "<NULL>";
+
+ std::string OutStr = Out.str();
+ if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
+
+ // Process string output to make it nicer...
+ for (unsigned i = 0; i != OutStr.length(); ++i)
+ if (OutStr[i] == '\n') { // Left justify
+ OutStr[i] = '\\';
+ OutStr.insert(OutStr.begin()+i+1, 'l');
+ }
+
+ return OutStr;
+#else
+ return "";
+#endif
+ }
+};
+} // end namespace llvm
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
new file mode 100644
index 0000000..5ab5f46
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -0,0 +1,499 @@
+//===--- TemplateBase.cpp - Common template AST class implementation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements common classes used throughout C++ template
+// representations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <algorithm>
+#include <cctype>
+#include <iomanip>
+#include <sstream>
+
+using namespace clang;
+
+/// \brief Print a template integral argument value.
+///
+/// \param TemplArg the TemplateArgument instance to print.
+///
+/// \param Out the raw_ostream instance to use for printing.
+static void printIntegral(const TemplateArgument &TemplArg,
+ llvm::raw_ostream &Out) {
+ const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
+ const llvm::APSInt *Val = TemplArg.getAsIntegral();
+
+ if (T->isBooleanType()) {
+ Out << (Val->getBoolValue() ? "true" : "false");
+ } else if (T->isCharType()) {
+ char Ch = Val->getSExtValue();
+ if (std::isprint(Ch)) {
+ Out << "'";
+ if (Ch == '\'' || Ch == '\\')
+ Out << '\\';
+ Out << Ch << "'";
+ } else {
+ std::ostringstream Str;
+ Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch;
+ Out << "'\\x" << Str.str() << "'";
+ }
+ } else {
+ Out << Val->toString(10);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateArgument Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ if (NumArgs == 0)
+ return TemplateArgument(0, 0);
+
+ TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
+ std::copy(Args, Args + NumArgs, Storage);
+ return TemplateArgument(Storage, NumArgs);
+}
+
+bool TemplateArgument::isDependent() const {
+ switch (getKind()) {
+ case Null:
+ assert(false && "Should not have a NULL template argument");
+ return false;
+
+ case Type:
+ return getAsType()->isDependentType();
+
+ case Template:
+ return getAsTemplate().isDependent();
+
+ case TemplateExpansion:
+ return true;
+
+ case Declaration:
+ if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+ return DC->isDependentContext();
+ return getAsDecl()->getDeclContext()->isDependentContext();
+
+ case Integral:
+ // Never dependent
+ return false;
+
+ case Expression:
+ return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
+
+ case Pack:
+ for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
+ if (P->isDependent())
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+bool TemplateArgument::isPackExpansion() const {
+ switch (getKind()) {
+ case Null:
+ case Declaration:
+ case Integral:
+ case Pack:
+ case Template:
+ return false;
+
+ case TemplateExpansion:
+ return true;
+
+ case Type:
+ return isa<PackExpansionType>(getAsType());
+
+ case Expression:
+ return isa<PackExpansionExpr>(getAsExpr());
+ }
+
+ return false;
+}
+
+bool TemplateArgument::containsUnexpandedParameterPack() const {
+ switch (getKind()) {
+ case Null:
+ case Declaration:
+ case Integral:
+ case TemplateExpansion:
+ break;
+
+ case Type:
+ if (getAsType()->containsUnexpandedParameterPack())
+ return true;
+ break;
+
+ case Template:
+ if (getAsTemplate().containsUnexpandedParameterPack())
+ return true;
+ break;
+
+ case Expression:
+ if (getAsExpr()->containsUnexpandedParameterPack())
+ return true;
+ break;
+
+ case Pack:
+ for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
+ if (P->containsUnexpandedParameterPack())
+ return true;
+
+ break;
+ }
+
+ return false;
+}
+
+llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
+ assert(Kind == TemplateExpansion);
+ if (TemplateArg.NumExpansions)
+ return TemplateArg.NumExpansions - 1;
+
+ return llvm::Optional<unsigned>();
+}
+
+void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context) const {
+ ID.AddInteger(Kind);
+ switch (Kind) {
+ case Null:
+ break;
+
+ case Type:
+ getAsType().Profile(ID);
+ break;
+
+ case Declaration:
+ ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
+ break;
+
+ case Template:
+ case TemplateExpansion: {
+ TemplateName Template = getAsTemplateOrTemplatePattern();
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(
+ Template.getAsTemplateDecl())) {
+ ID.AddBoolean(true);
+ ID.AddInteger(TTP->getDepth());
+ ID.AddInteger(TTP->getPosition());
+ ID.AddBoolean(TTP->isParameterPack());
+ } else {
+ ID.AddBoolean(false);
+ ID.AddPointer(Context.getCanonicalTemplateName(Template)
+ .getAsVoidPointer());
+ }
+ break;
+ }
+
+ case Integral:
+ getAsIntegral()->Profile(ID);
+ getIntegralType().Profile(ID);
+ break;
+
+ case Expression:
+ getAsExpr()->Profile(ID, Context, true);
+ break;
+
+ case Pack:
+ ID.AddInteger(Args.NumArgs);
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I].Profile(ID, Context);
+ }
+}
+
+bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
+ if (getKind() != Other.getKind()) return false;
+
+ switch (getKind()) {
+ case Null:
+ case Type:
+ case Declaration:
+ case Expression:
+ case Template:
+ case TemplateExpansion:
+ return TypeOrValue == Other.TypeOrValue;
+
+ case Integral:
+ return getIntegralType() == Other.getIntegralType() &&
+ *getAsIntegral() == *Other.getAsIntegral();
+
+ case Pack:
+ if (Args.NumArgs != Other.Args.NumArgs) return false;
+ for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
+ if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
+ return false;
+ return true;
+ }
+
+ // Suppress warnings.
+ return false;
+}
+
+TemplateArgument TemplateArgument::getPackExpansionPattern() const {
+ assert(isPackExpansion());
+
+ switch (getKind()) {
+ case Type:
+ return getAsType()->getAs<PackExpansionType>()->getPattern();
+
+ case Expression:
+ return cast<PackExpansionExpr>(getAsExpr())->getPattern();
+
+ case TemplateExpansion:
+ return TemplateArgument(getAsTemplateOrTemplatePattern());
+
+ case Declaration:
+ case Integral:
+ case Pack:
+ case Null:
+ case Template:
+ return TemplateArgument();
+ }
+
+ return TemplateArgument();
+}
+
+void TemplateArgument::print(const PrintingPolicy &Policy,
+ llvm::raw_ostream &Out) const {
+ switch (getKind()) {
+ case Null:
+ Out << "<no value>";
+ break;
+
+ case Type: {
+ std::string TypeStr;
+ getAsType().getAsStringInternal(TypeStr, Policy);
+ Out << TypeStr;
+ break;
+ }
+
+ case Declaration: {
+ bool Unnamed = true;
+ if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
+ if (ND->getDeclName()) {
+ Unnamed = false;
+ Out << ND->getNameAsString();
+ }
+ }
+
+ if (Unnamed) {
+ Out << "<anonymous>";
+ }
+ break;
+ }
+
+ case Template:
+ getAsTemplate().print(Out, Policy);
+ break;
+
+ case TemplateExpansion:
+ getAsTemplateOrTemplatePattern().print(Out, Policy);
+ Out << "...";
+ break;
+
+ case Integral: {
+ printIntegral(*this, Out);
+ break;
+ }
+
+ case Expression:
+ getAsExpr()->printPretty(Out, 0, Policy);
+ break;
+
+ case Pack:
+ Out << "<";
+ bool First = true;
+ for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
+ P != PEnd; ++P) {
+ if (First)
+ First = false;
+ else
+ Out << ", ";
+
+ P->print(Policy, Out);
+ }
+ Out << ">";
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateArgumentLoc Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
+ memset(this, 0, sizeof(TemplateArgumentLocInfo));
+}
+
+SourceRange TemplateArgumentLoc::getSourceRange() const {
+ switch (Argument.getKind()) {
+ case TemplateArgument::Expression:
+ return getSourceExpression()->getSourceRange();
+
+ case TemplateArgument::Declaration:
+ return getSourceDeclExpression()->getSourceRange();
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSI = getTypeSourceInfo())
+ return TSI->getTypeLoc().getSourceRange();
+ else
+ return SourceRange();
+
+ case TemplateArgument::Template:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateNameLoc());
+ return SourceRange(getTemplateNameLoc());
+
+ case TemplateArgument::TemplateExpansion:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateEllipsisLoc());
+ return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
+
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return SourceRange();
+ }
+
+ // Silence bonus gcc warning.
+ return SourceRange();
+}
+
+TemplateArgumentLoc
+TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
+ llvm::Optional<unsigned> &NumExpansions,
+ ASTContext &Context) const {
+ assert(Argument.isPackExpansion());
+
+ switch (Argument.getKind()) {
+ case TemplateArgument::Type: {
+ // FIXME: We shouldn't ever have to worry about missing
+ // type-source info!
+ TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
+ if (!ExpansionTSInfo)
+ ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
+ getArgument().getAsType(),
+ Ellipsis);
+ PackExpansionTypeLoc Expansion
+ = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
+ Ellipsis = Expansion.getEllipsisLoc();
+
+ TypeLoc Pattern = Expansion.getPatternLoc();
+ NumExpansions = Expansion.getTypePtr()->getNumExpansions();
+
+ // FIXME: This is horrible. We know where the source location data is for
+ // the pattern, and we have the pattern's type, but we are forced to copy
+ // them into an ASTContext because TypeSourceInfo bundles them together
+ // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
+ TypeSourceInfo *PatternTSInfo
+ = Context.CreateTypeSourceInfo(Pattern.getType(),
+ Pattern.getFullDataSize());
+ memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
+ Pattern.getOpaqueData(), Pattern.getFullDataSize());
+ return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
+ PatternTSInfo);
+ }
+
+ case TemplateArgument::Expression: {
+ PackExpansionExpr *Expansion
+ = cast<PackExpansionExpr>(Argument.getAsExpr());
+ Expr *Pattern = Expansion->getPattern();
+ Ellipsis = Expansion->getEllipsisLoc();
+ NumExpansions = Expansion->getNumExpansions();
+ return TemplateArgumentLoc(Pattern, Pattern);
+ }
+
+ case TemplateArgument::TemplateExpansion:
+ Ellipsis = getTemplateEllipsisLoc();
+ NumExpansions = Argument.getNumTemplateExpansions();
+ return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
+ getTemplateQualifierRange(),
+ getTemplateNameLoc());
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Template:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return TemplateArgumentLoc();
+ }
+
+ return TemplateArgumentLoc();
+}
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ // This is bad, but not as bad as crashing because of argument
+ // count mismatches.
+ return DB << "(null template argument)";
+
+ case TemplateArgument::Type:
+ return DB << Arg.getAsType();
+
+ case TemplateArgument::Declaration:
+ return DB << Arg.getAsDecl();
+
+ case TemplateArgument::Integral:
+ return DB << Arg.getAsIntegral()->toString(10);
+
+ case TemplateArgument::Template:
+ return DB << Arg.getAsTemplate();
+
+ case TemplateArgument::TemplateExpansion:
+ return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
+
+ case TemplateArgument::Expression: {
+ // This shouldn't actually ever happen, so it's okay that we're
+ // regurgitating an expression here.
+ // FIXME: We're guessing at LangOptions!
+ llvm::SmallString<32> Str;
+ llvm::raw_svector_ostream OS(Str);
+ LangOptions LangOpts;
+ LangOpts.CPlusPlus = true;
+ PrintingPolicy Policy(LangOpts);
+ Arg.getAsExpr()->printPretty(OS, 0, Policy);
+ return DB << OS.str();
+ }
+
+ case TemplateArgument::Pack: {
+ // FIXME: We're guessing at LangOptions!
+ llvm::SmallString<32> Str;
+ llvm::raw_svector_ostream OS(Str);
+ LangOptions LangOpts;
+ LangOpts.CPlusPlus = true;
+ PrintingPolicy Policy(LangOpts);
+ Arg.print(Policy, OS);
+ return DB << OS.str();
+ }
+ }
+
+ return DB;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
new file mode 100644
index 0000000..6b378a0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
@@ -0,0 +1,140 @@
+//===--- TemplateName.h - C++ Template Name Representation-------*- 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 TemplateName interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+using namespace llvm;
+
+TemplateArgument
+SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
+ return TemplateArgument(Arguments, size());
+}
+
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
+}
+
+void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
+ ASTContext &Context,
+ TemplateTemplateParmDecl *Parameter,
+ const TemplateArgument &ArgPack) {
+ ID.AddPointer(Parameter);
+ ArgPack.Profile(ID, Context);
+}
+
+TemplateName::NameKind TemplateName::getKind() const {
+ if (Storage.is<TemplateDecl *>())
+ return Template;
+ if (Storage.is<DependentTemplateName *>())
+ return DependentTemplate;
+ if (Storage.is<QualifiedTemplateName *>())
+ return QualifiedTemplate;
+
+ return getAsOverloadedTemplate()? OverloadedTemplate
+ : SubstTemplateTemplateParmPack;
+}
+
+TemplateDecl *TemplateName::getAsTemplateDecl() const {
+ if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+ return Template;
+
+ if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
+ return QTN->getTemplateDecl();
+
+ return 0;
+}
+
+bool TemplateName::isDependent() const {
+ if (TemplateDecl *Template = getAsTemplateDecl()) {
+ if (isa<TemplateTemplateParmDecl>(Template))
+ return true;
+ // FIXME: Hack, getDeclContext() can be null if Template is still
+ // initializing due to PCH reading, so we check it before using it.
+ // Should probably modify TemplateSpecializationType to allow constructing
+ // it without the isDependent() checking.
+ return Template->getDeclContext() &&
+ Template->getDeclContext()->isDependentContext();
+ }
+
+ assert(!getAsOverloadedTemplate() &&
+ "overloaded templates shouldn't survive to here");
+
+ return true;
+}
+
+bool TemplateName::containsUnexpandedParameterPack() const {
+ if (TemplateDecl *Template = getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template))
+ return TTP->isParameterPack();
+
+ return false;
+ }
+
+ if (DependentTemplateName *DTN = getAsDependentTemplateName())
+ return DTN->getQualifier() &&
+ DTN->getQualifier()->containsUnexpandedParameterPack();
+
+ return getAsSubstTemplateTemplateParmPack() != 0;
+}
+
+void
+TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
+ bool SuppressNNS) const {
+ if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+ OS << Template;
+ else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ if (!SuppressNNS)
+ QTN->getQualifier()->print(OS, Policy);
+ if (QTN->hasTemplateKeyword())
+ OS << "template ";
+ OS << QTN->getDecl();
+ } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
+ if (!SuppressNNS && DTN->getQualifier())
+ DTN->getQualifier()->print(OS, Policy);
+ OS << "template ";
+
+ if (DTN->isIdentifier())
+ OS << DTN->getIdentifier()->getName();
+ else
+ OS << "operator " << getOperatorSpelling(DTN->getOperator());
+ } else if (SubstTemplateTemplateParmPackStorage *SubstPack
+ = getAsSubstTemplateTemplateParmPack())
+ OS << SubstPack->getParameterPack()->getNameAsString();
+}
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+ TemplateName N) {
+ std::string NameStr;
+ raw_string_ostream OS(NameStr);
+ LangOptions LO;
+ LO.CPlusPlus = true;
+ LO.Bool = true;
+ N.print(OS, PrintingPolicy(LO));
+ OS.flush();
+ return DB << NameStr;
+}
+
+void TemplateName::dump() const {
+ LangOptions LO; // FIXME!
+ LO.CPlusPlus = true;
+ LO.Bool = true;
+ print(llvm::errs(), PrintingPolicy(LO));
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
new file mode 100644
index 0000000..b03314e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -0,0 +1,1643 @@
+//===--- Type.cpp - Type representation and manipulation ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements type-related functionality.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+using namespace clang;
+
+bool QualType::isConstant(QualType T, ASTContext &Ctx) {
+ if (T.isConstQualified())
+ return true;
+
+ if (const ArrayType *AT = Ctx.getAsArrayType(T))
+ return AT->getElementType().isConstant(Ctx);
+
+ return false;
+}
+
+unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements) {
+ llvm::APSInt SizeExtended(NumElements, true);
+ unsigned SizeTypeBits = Context.getTypeSize(Context.getSizeType());
+ SizeExtended = SizeExtended.extend(std::max(SizeTypeBits,
+ SizeExtended.getBitWidth()) * 2);
+
+ uint64_t ElementSize
+ = Context.getTypeSizeInChars(ElementType).getQuantity();
+ llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize));
+ TotalSize *= SizeExtended;
+
+ return TotalSize.getActiveBits();
+}
+
+unsigned ConstantArrayType::getMaxSizeBits(ASTContext &Context) {
+ unsigned Bits = Context.getTypeSize(Context.getSizeType());
+
+ // GCC appears to only allow 63 bits worth of address space when compiling
+ // for 64-bit, so we do the same.
+ if (Bits == 64)
+ --Bits;
+
+ return Bits;
+}
+
+DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
+ QualType et, QualType can,
+ Expr *e, ArraySizeModifier sm,
+ unsigned tq,
+ SourceRange brackets)
+ : ArrayType(DependentSizedArray, et, can, sm, tq,
+ (et->containsUnexpandedParameterPack() ||
+ (e && e->containsUnexpandedParameterPack()))),
+ Context(Context), SizeExpr((Stmt*) e), Brackets(brackets)
+{
+}
+
+void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ QualType ET,
+ ArraySizeModifier SizeMod,
+ unsigned TypeQuals,
+ Expr *E) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ E->Profile(ID, Context, true);
+}
+
+DependentSizedExtVectorType::DependentSizedExtVectorType(const
+ ASTContext &Context,
+ QualType ElementType,
+ QualType can,
+ Expr *SizeExpr,
+ SourceLocation loc)
+ : Type(DependentSizedExtVector, can, /*Dependent=*/true,
+ ElementType->isVariablyModifiedType(),
+ (ElementType->containsUnexpandedParameterPack() ||
+ (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
+ Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
+ loc(loc)
+{
+}
+
+void
+DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ QualType ElementType, Expr *SizeExpr) {
+ ID.AddPointer(ElementType.getAsOpaquePtr());
+ SizeExpr->Profile(ID, Context, true);
+}
+
+VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
+ VectorKind vecKind)
+ : Type(Vector, canonType, vecType->isDependentType(),
+ vecType->isVariablyModifiedType(),
+ vecType->containsUnexpandedParameterPack()),
+ ElementType(vecType)
+{
+ VectorTypeBits.VecKind = vecKind;
+ VectorTypeBits.NumElements = nElements;
+}
+
+VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
+ QualType canonType, VectorKind vecKind)
+ : Type(tc, canonType, vecType->isDependentType(),
+ vecType->isVariablyModifiedType(),
+ vecType->containsUnexpandedParameterPack()),
+ ElementType(vecType)
+{
+ VectorTypeBits.VecKind = vecKind;
+ VectorTypeBits.NumElements = nElements;
+}
+
+/// getArrayElementTypeNoTypeQual - If this is an array type, return the
+/// element type of the array, potentially with type qualifiers missing.
+/// This method should never be used when type qualifiers are meaningful.
+const Type *Type::getArrayElementTypeNoTypeQual() const {
+ // If this is directly an array type, return it.
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+ return ATy->getElementType().getTypePtr();
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<ArrayType>(CanonicalType))
+ return 0;
+
+ // If this is a typedef for an array type, strip the typedef off without
+ // losing all typedef information.
+ return cast<ArrayType>(getUnqualifiedDesugaredType())
+ ->getElementType().getTypePtr();
+}
+
+/// getDesugaredType - Return the specified type with any "sugar" removed from
+/// the type. This takes off typedefs, typeof's etc. If the outer level of
+/// the type is already concrete, it returns it unmodified. This is similar
+/// to getting the canonical type, but it doesn't remove *all* typedefs. For
+/// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
+/// concrete.
+QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) {
+ SplitQualType split = getSplitDesugaredType(T);
+ return Context.getQualifiedType(split.first, split.second);
+}
+
+SplitQualType QualType::getSplitDesugaredType(QualType T) {
+ QualifierCollector Qs;
+
+ QualType Cur = T;
+ while (true) {
+ const Type *CurTy = Qs.strip(Cur);
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return SplitQualType(Ty, Qs); \
+ Cur = Ty->desugar(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+}
+
+SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) {
+ SplitQualType split = type.split();
+
+ // All the qualifiers we've seen so far.
+ Qualifiers quals = split.second;
+
+ // The last type node we saw with any nodes inside it.
+ const Type *lastTypeWithQuals = split.first;
+
+ while (true) {
+ QualType next;
+
+ // Do a single-step desugar, aborting the loop if the type isn't
+ // sugared.
+ switch (split.first->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *ty = cast<Class##Type>(split.first); \
+ if (!ty->isSugared()) goto done; \
+ next = ty->desugar(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ // Otherwise, split the underlying type. If that yields qualifiers,
+ // update the information.
+ split = next.split();
+ if (!split.second.empty()) {
+ lastTypeWithQuals = split.first;
+ quals.addConsistentQualifiers(split.second);
+ }
+ }
+
+ done:
+ return SplitQualType(lastTypeWithQuals, quals);
+}
+
+QualType QualType::IgnoreParens(QualType T) {
+ // FIXME: this seems inherently un-qualifiers-safe.
+ while (const ParenType *PT = T->getAs<ParenType>())
+ T = PT->getInnerType();
+ return T;
+}
+
+/// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
+/// sugar off the given type. This should produce an object of the
+/// same dynamic type as the canonical type.
+const Type *Type::getUnqualifiedDesugaredType() const {
+ const Type *Cur = this;
+
+ while (true) {
+ switch (Cur->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Class: { \
+ const Class##Type *Ty = cast<Class##Type>(Cur); \
+ if (!Ty->isSugared()) return Cur; \
+ Cur = Ty->desugar().getTypePtr(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+}
+
+/// isVoidType - Helper method to determine if this is the 'void' type.
+bool Type::isVoidType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Void;
+ return false;
+}
+
+bool Type::isDerivedType() const {
+ switch (CanonicalType->getTypeClass()) {
+ case Pointer:
+ case VariableArray:
+ case ConstantArray:
+ case IncompleteArray:
+ case FunctionProto:
+ case FunctionNoProto:
+ case LValueReference:
+ case RValueReference:
+ case Record:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Type::isClassType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isClass();
+ return false;
+}
+bool Type::isStructureType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isStruct();
+ return false;
+}
+bool Type::isStructureOrClassType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isStruct() || RT->getDecl()->isClass();
+ return false;
+}
+bool Type::isVoidPointerType() const {
+ if (const PointerType *PT = getAs<PointerType>())
+ return PT->getPointeeType()->isVoidType();
+ return false;
+}
+
+bool Type::isUnionType() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return RT->getDecl()->isUnion();
+ return false;
+}
+
+bool Type::isComplexType() const {
+ if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ return CT->getElementType()->isFloatingType();
+ return false;
+}
+
+bool Type::isComplexIntegerType() const {
+ // Check for GCC complex integer extension.
+ return getAsComplexIntegerType();
+}
+
+const ComplexType *Type::getAsComplexIntegerType() const {
+ if (const ComplexType *Complex = getAs<ComplexType>())
+ if (Complex->getElementType()->isIntegerType())
+ return Complex;
+ return 0;
+}
+
+QualType Type::getPointeeType() const {
+ if (const PointerType *PT = getAs<PointerType>())
+ return PT->getPointeeType();
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
+ return OPT->getPointeeType();
+ if (const BlockPointerType *BPT = getAs<BlockPointerType>())
+ return BPT->getPointeeType();
+ if (const ReferenceType *RT = getAs<ReferenceType>())
+ return RT->getPointeeType();
+ return QualType();
+}
+
+const RecordType *Type::getAsStructureType() const {
+ // If this is directly a structure type, return it.
+ if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (RT->getDecl()->isStruct())
+ return RT;
+ }
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (!RT->getDecl()->isStruct())
+ return 0;
+
+ // If this is a typedef for a structure type, strip the typedef off without
+ // losing all typedef information.
+ return cast<RecordType>(getUnqualifiedDesugaredType());
+ }
+ return 0;
+}
+
+const RecordType *Type::getAsUnionType() const {
+ // If this is directly a union type, return it.
+ if (const RecordType *RT = dyn_cast<RecordType>(this)) {
+ if (RT->getDecl()->isUnion())
+ return RT;
+ }
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
+ if (!RT->getDecl()->isUnion())
+ return 0;
+
+ // If this is a typedef for a union type, strip the typedef off without
+ // losing all typedef information.
+ return cast<RecordType>(getUnqualifiedDesugaredType());
+ }
+
+ return 0;
+}
+
+ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols)
+ : Type(ObjCObject, Canonical, false, false, false),
+ BaseType(Base)
+{
+ ObjCObjectTypeBits.NumProtocols = NumProtocols;
+ assert(getNumProtocols() == NumProtocols &&
+ "bitfield overflow in protocol count");
+ if (NumProtocols)
+ memcpy(getProtocolStorage(), Protocols,
+ NumProtocols * sizeof(ObjCProtocolDecl*));
+}
+
+const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
+ // There is no sugar for ObjCObjectType's, just return the canonical
+ // type pointer if it is the right class. There is no typedef information to
+ // return and these cannot be Address-space qualified.
+ if (const ObjCObjectType *T = getAs<ObjCObjectType>())
+ if (T->getNumProtocols() && T->getInterface())
+ return T;
+ return 0;
+}
+
+bool Type::isObjCQualifiedInterfaceType() const {
+ return getAsObjCQualifiedInterfaceType() != 0;
+}
+
+const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
+ // There is no sugar for ObjCQualifiedIdType's, just return the canonical
+ // type pointer if it is the right class.
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (OPT->isObjCQualifiedIdType())
+ return OPT;
+ }
+ return 0;
+}
+
+const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const {
+ if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) {
+ if (OPT->getInterfaceType())
+ return OPT;
+ }
+ return 0;
+}
+
+const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const {
+ if (const PointerType *PT = getAs<PointerType>())
+ if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>())
+ return dyn_cast<CXXRecordDecl>(RT->getDecl());
+ return 0;
+}
+
+CXXRecordDecl *Type::getAsCXXRecordDecl() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return dyn_cast<CXXRecordDecl>(RT->getDecl());
+ else if (const InjectedClassNameType *Injected
+ = getAs<InjectedClassNameType>())
+ return Injected->getDecl();
+
+ return 0;
+}
+
+namespace {
+ class GetContainedAutoVisitor :
+ public TypeVisitor<GetContainedAutoVisitor, AutoType*> {
+ public:
+ using TypeVisitor<GetContainedAutoVisitor, AutoType*>::Visit;
+ AutoType *Visit(QualType T) {
+ if (T.isNull())
+ return 0;
+ return Visit(T.getTypePtr());
+ }
+
+ // The 'auto' type itself.
+ AutoType *VisitAutoType(const AutoType *AT) {
+ return const_cast<AutoType*>(AT);
+ }
+
+ // Only these types can contain the desired 'auto' type.
+ AutoType *VisitPointerType(const PointerType *T) {
+ return Visit(T->getPointeeType());
+ }
+ AutoType *VisitBlockPointerType(const BlockPointerType *T) {
+ return Visit(T->getPointeeType());
+ }
+ AutoType *VisitReferenceType(const ReferenceType *T) {
+ return Visit(T->getPointeeTypeAsWritten());
+ }
+ AutoType *VisitMemberPointerType(const MemberPointerType *T) {
+ return Visit(T->getPointeeType());
+ }
+ AutoType *VisitArrayType(const ArrayType *T) {
+ return Visit(T->getElementType());
+ }
+ AutoType *VisitDependentSizedExtVectorType(
+ const DependentSizedExtVectorType *T) {
+ return Visit(T->getElementType());
+ }
+ AutoType *VisitVectorType(const VectorType *T) {
+ return Visit(T->getElementType());
+ }
+ AutoType *VisitFunctionType(const FunctionType *T) {
+ return Visit(T->getResultType());
+ }
+ AutoType *VisitParenType(const ParenType *T) {
+ return Visit(T->getInnerType());
+ }
+ AutoType *VisitAttributedType(const AttributedType *T) {
+ return Visit(T->getModifiedType());
+ }
+ };
+}
+
+AutoType *Type::getContainedAutoType() const {
+ return GetContainedAutoVisitor().Visit(this);
+}
+
+bool Type::isIntegerType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::Int128;
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ // Incomplete enum types are not treated as integer types.
+ // FIXME: In C++, enum types are never integer types.
+ return ET->getDecl()->isComplete();
+ return false;
+}
+
+bool Type::hasIntegerRepresentation() const {
+ if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ return VT->getElementType()->isIntegerType();
+ else
+ return isIntegerType();
+}
+
+/// \brief Determine whether this type is an integral type.
+///
+/// This routine determines whether the given type is an integral type per
+/// C++ [basic.fundamental]p7. Although the C standard does not define the
+/// term "integral type", it has a similar term "integer type", and in C++
+/// the two terms are equivalent. However, C's "integer type" includes
+/// enumeration types, while C++'s "integer type" does not. The \c ASTContext
+/// parameter is used to determine whether we should be following the C or
+/// C++ rules when determining whether this type is an integral/integer type.
+///
+/// For cases where C permits "an integer type" and C++ permits "an integral
+/// type", use this routine.
+///
+/// For cases where C permits "an integer type" and C++ permits "an integral
+/// or enumeration type", use \c isIntegralOrEnumerationType() instead.
+///
+/// \param Ctx The context in which this type occurs.
+///
+/// \returns true if the type is considered an integral type, false otherwise.
+bool Type::isIntegralType(ASTContext &Ctx) const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::Int128;
+
+ if (!Ctx.getLangOptions().CPlusPlus)
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ return ET->getDecl()->isComplete(); // Complete enum types are integral in C.
+
+ return false;
+}
+
+bool Type::isIntegralOrEnumerationType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::Int128;
+
+ // Check for a complete enum type; incomplete enum types are not properly an
+ // enumeration type in the sense required here.
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ return ET->getDecl()->isComplete();
+
+ return false;
+}
+
+bool Type::isIntegralOrUnscopedEnumerationType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::Int128;
+
+ // Check for a complete enum type; incomplete enum types are not properly an
+ // enumeration type in the sense required here.
+ // C++0x: However, if the underlying type of the enum is fixed, it is
+ // considered complete.
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
+
+ return false;
+}
+
+
+bool Type::isBooleanType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Bool;
+ return false;
+}
+
+bool Type::isCharType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Char_U ||
+ BT->getKind() == BuiltinType::UChar ||
+ BT->getKind() == BuiltinType::Char_S ||
+ BT->getKind() == BuiltinType::SChar;
+ return false;
+}
+
+bool Type::isWideCharType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::WChar_S ||
+ BT->getKind() == BuiltinType::WChar_U;
+ return false;
+}
+
+/// \brief Determine whether this type is any of the built-in character
+/// types.
+bool Type::isAnyCharacterType() const {
+ const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
+ if (BT == 0) return false;
+ switch (BT->getKind()) {
+ default: return false;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ case BuiltinType::WChar_S:
+ return true;
+ }
+}
+
+/// isSignedIntegerType - Return true if this is an integer type that is
+/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
+/// an enum decl which has a signed representation
+bool Type::isSignedIntegerType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ return BT->getKind() >= BuiltinType::Char_S &&
+ BT->getKind() <= BuiltinType::Int128;
+ }
+
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ // Incomplete enum types are not treated as integer types.
+ // FIXME: In C++, enum types are never integer types.
+ if (ET->getDecl()->isComplete())
+ return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ }
+
+ return false;
+}
+
+bool Type::hasSignedIntegerRepresentation() const {
+ if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ return VT->getElementType()->isSignedIntegerType();
+ else
+ return isSignedIntegerType();
+}
+
+/// isUnsignedIntegerType - Return true if this is an integer type that is
+/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
+/// decl which has an unsigned representation
+bool Type::isUnsignedIntegerType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::UInt128;
+ }
+
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ // Incomplete enum types are not treated as integer types.
+ // FIXME: In C++, enum types are never integer types.
+ if (ET->getDecl()->isComplete())
+ return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ }
+
+ return false;
+}
+
+bool Type::hasUnsignedIntegerRepresentation() const {
+ if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ return VT->getElementType()->isUnsignedIntegerType();
+ else
+ return isUnsignedIntegerType();
+}
+
+bool Type::isFloatingType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Float &&
+ BT->getKind() <= BuiltinType::LongDouble;
+ if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
+ return CT->getElementType()->isFloatingType();
+ return false;
+}
+
+bool Type::hasFloatingRepresentation() const {
+ if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
+ return VT->getElementType()->isFloatingType();
+ else
+ return isFloatingType();
+}
+
+bool Type::isRealFloatingType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->isFloatingPoint();
+ return false;
+}
+
+bool Type::isRealType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::LongDouble;
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
+ return false;
+}
+
+bool Type::isArithmeticType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() >= BuiltinType::Bool &&
+ BT->getKind() <= BuiltinType::LongDouble;
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
+ // If a body isn't seen by the time we get here, return false.
+ //
+ // C++0x: Enumerations are not arithmetic types. For now, just return
+ // false for scoped enumerations since that will disable any
+ // unwanted implicit conversions.
+ return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete();
+ return isa<ComplexType>(CanonicalType);
+}
+
+bool Type::isScalarType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() > BuiltinType::Void &&
+ BT->getKind() <= BuiltinType::NullPtr;
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
+ // Enums are scalar types, but only if they are defined. Incomplete enums
+ // are not treated as scalar types.
+ return ET->getDecl()->isComplete();
+ return isa<PointerType>(CanonicalType) ||
+ isa<BlockPointerType>(CanonicalType) ||
+ isa<MemberPointerType>(CanonicalType) ||
+ isa<ComplexType>(CanonicalType) ||
+ isa<ObjCObjectPointerType>(CanonicalType);
+}
+
+Type::ScalarTypeKind Type::getScalarTypeKind() const {
+ assert(isScalarType());
+
+ const Type *T = CanonicalType.getTypePtr();
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
+ if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer;
+ if (BT->isInteger()) return STK_Integral;
+ if (BT->isFloatingPoint()) return STK_Floating;
+ llvm_unreachable("unknown scalar builtin type");
+ } else if (isa<PointerType>(T) ||
+ isa<BlockPointerType>(T) ||
+ isa<ObjCObjectPointerType>(T)) {
+ return STK_Pointer;
+ } else if (isa<MemberPointerType>(T)) {
+ return STK_MemberPointer;
+ } else if (isa<EnumType>(T)) {
+ assert(cast<EnumType>(T)->getDecl()->isComplete());
+ return STK_Integral;
+ } else if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+ if (CT->getElementType()->isRealFloatingType())
+ return STK_FloatingComplex;
+ return STK_IntegralComplex;
+ }
+
+ llvm_unreachable("unknown scalar type");
+ return STK_Pointer;
+}
+
+/// \brief Determines whether the type is a C++ aggregate type or C
+/// aggregate or union type.
+///
+/// An aggregate type is an array or a class type (struct, union, or
+/// class) that has no user-declared constructors, no private or
+/// protected non-static data members, no base classes, and no virtual
+/// functions (C++ [dcl.init.aggr]p1). The notion of an aggregate type
+/// subsumes the notion of C aggregates (C99 6.2.5p21) because it also
+/// includes union types.
+bool Type::isAggregateType() const {
+ if (const RecordType *Record = dyn_cast<RecordType>(CanonicalType)) {
+ if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(Record->getDecl()))
+ return ClassDecl->isAggregate();
+
+ return true;
+ }
+
+ return isa<ArrayType>(CanonicalType);
+}
+
+/// isConstantSizeType - Return true if this is not a variable sized type,
+/// according to the rules of C99 6.7.5p3. It is not legal to call this on
+/// incomplete types or dependent types.
+bool Type::isConstantSizeType() const {
+ assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
+ assert(!isDependentType() && "This doesn't make sense for dependent types");
+ // The VAT must have a size, as it is known to be complete.
+ return !isa<VariableArrayType>(CanonicalType);
+}
+
+/// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1)
+/// - a type that can describe objects, but which lacks information needed to
+/// determine its size.
+bool Type::isIncompleteType() const {
+ switch (CanonicalType->getTypeClass()) {
+ default: return false;
+ case Builtin:
+ // Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
+ // be completed.
+ return isVoidType();
+ case Enum:
+ // An enumeration with fixed underlying type is complete (C++0x 7.2p3).
+ if (cast<EnumType>(CanonicalType)->getDecl()->isFixed())
+ return false;
+ // Fall through.
+ case Record:
+ // A tagged type (struct/union/enum/class) is incomplete if the decl is a
+ // forward declaration, but not a full definition (C99 6.2.5p22).
+ return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
+ case ConstantArray:
+ // An array is incomplete if its element type is incomplete
+ // (C++ [dcl.array]p1).
+ // We don't handle variable arrays (they're not allowed in C++) or
+ // dependent-sized arrays (dependent types are never treated as incomplete).
+ return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType();
+ case IncompleteArray:
+ // An array of unknown size is an incomplete type (C99 6.2.5p22).
+ return true;
+ case ObjCObject:
+ return cast<ObjCObjectType>(CanonicalType)->getBaseType()
+ ->isIncompleteType();
+ case ObjCInterface:
+ // ObjC interfaces are incomplete if they are @class, not @interface.
+ return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl();
+ }
+}
+
+/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
+bool Type::isPODType() const {
+ // The compiler shouldn't query this for incomplete types, but the user might.
+ // We return false for that case. Except for incomplete arrays of PODs, which
+ // are PODs according to the standard.
+ if (isIncompleteArrayType() &&
+ cast<ArrayType>(CanonicalType)->getElementType()->isPODType())
+ return true;
+ if (isIncompleteType())
+ return false;
+
+ switch (CanonicalType->getTypeClass()) {
+ // Everything not explicitly mentioned is not POD.
+ default: return false;
+ case VariableArray:
+ case ConstantArray:
+ // IncompleteArray is handled above.
+ return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
+
+ case Builtin:
+ case Complex:
+ case Pointer:
+ case MemberPointer:
+ case Vector:
+ case ExtVector:
+ case ObjCObjectPointer:
+ case BlockPointer:
+ return true;
+
+ case Enum:
+ return true;
+
+ case Record:
+ if (CXXRecordDecl *ClassDecl
+ = dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
+ return ClassDecl->isPOD();
+
+ // C struct/union is POD.
+ return true;
+ }
+}
+
+bool Type::isLiteralType() const {
+ if (isIncompleteType())
+ return false;
+
+ // C++0x [basic.types]p10:
+ // A type is a literal type if it is:
+ switch (CanonicalType->getTypeClass()) {
+ // We're whitelisting
+ default: return false;
+
+ // -- a scalar type
+ case Builtin:
+ case Complex:
+ case Pointer:
+ case MemberPointer:
+ case Vector:
+ case ExtVector:
+ case ObjCObjectPointer:
+ case Enum:
+ return true;
+
+ // -- a class type with ...
+ case Record:
+ // FIXME: Do the tests
+ return false;
+
+ // -- an array of literal type
+ // Extension: variable arrays cannot be literal types, since they're
+ // runtime-sized.
+ case ConstantArray:
+ return cast<ArrayType>(CanonicalType)->getElementType()->isLiteralType();
+ }
+}
+
+bool Type::isPromotableIntegerType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ case BuiltinType::Bool:
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ return true;
+ default:
+ return false;
+ }
+
+ // Enumerated types are promotable to their compatible integer types
+ // (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2).
+ if (const EnumType *ET = getAs<EnumType>()){
+ if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull()
+ || ET->getDecl()->isScoped())
+ return false;
+
+ const BuiltinType *BT
+ = ET->getDecl()->getPromotionType()->getAs<BuiltinType>();
+ return BT->getKind() == BuiltinType::Int
+ || BT->getKind() == BuiltinType::UInt;
+ }
+
+ return false;
+}
+
+bool Type::isNullPtrType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ return BT->getKind() == BuiltinType::NullPtr;
+ return false;
+}
+
+bool Type::isSpecifierType() const {
+ // Note that this intentionally does not use the canonical type.
+ switch (getTypeClass()) {
+ case Builtin:
+ case Record:
+ case Enum:
+ case Typedef:
+ case Complex:
+ case TypeOfExpr:
+ case TypeOf:
+ case TemplateTypeParm:
+ case SubstTemplateTypeParm:
+ case TemplateSpecialization:
+ case Elaborated:
+ case DependentName:
+ case DependentTemplateSpecialization:
+ case ObjCInterface:
+ case ObjCObject:
+ case ObjCObjectPointer: // FIXME: object pointers aren't really specifiers
+ return true;
+ default:
+ return false;
+ }
+}
+
+ElaboratedTypeKeyword
+TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
+ switch (TypeSpec) {
+ default: return ETK_None;
+ case TST_typename: return ETK_Typename;
+ case TST_class: return ETK_Class;
+ case TST_struct: return ETK_Struct;
+ case TST_union: return ETK_Union;
+ case TST_enum: return ETK_Enum;
+ }
+}
+
+TagTypeKind
+TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) {
+ switch(TypeSpec) {
+ case TST_class: return TTK_Class;
+ case TST_struct: return TTK_Struct;
+ case TST_union: return TTK_Union;
+ case TST_enum: return TTK_Enum;
+ }
+
+ llvm_unreachable("Type specifier is not a tag type kind.");
+ return TTK_Union;
+}
+
+ElaboratedTypeKeyword
+TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) {
+ switch (Kind) {
+ case TTK_Class: return ETK_Class;
+ case TTK_Struct: return ETK_Struct;
+ case TTK_Union: return ETK_Union;
+ case TTK_Enum: return ETK_Enum;
+ }
+ llvm_unreachable("Unknown tag type kind.");
+}
+
+TagTypeKind
+TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) {
+ switch (Keyword) {
+ case ETK_Class: return TTK_Class;
+ case ETK_Struct: return TTK_Struct;
+ case ETK_Union: return TTK_Union;
+ case ETK_Enum: return TTK_Enum;
+ case ETK_None: // Fall through.
+ case ETK_Typename:
+ llvm_unreachable("Elaborated type keyword is not a tag type kind.");
+ }
+ llvm_unreachable("Unknown elaborated type keyword.");
+}
+
+bool
+TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) {
+ switch (Keyword) {
+ case ETK_None:
+ case ETK_Typename:
+ return false;
+ case ETK_Class:
+ case ETK_Struct:
+ case ETK_Union:
+ case ETK_Enum:
+ return true;
+ }
+ llvm_unreachable("Unknown elaborated type keyword.");
+}
+
+const char*
+TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
+ switch (Keyword) {
+ case ETK_None: return "";
+ case ETK_Typename: return "typename";
+ case ETK_Class: return "class";
+ case ETK_Struct: return "struct";
+ case ETK_Union: return "union";
+ case ETK_Enum: return "enum";
+ }
+
+ llvm_unreachable("Unknown elaborated type keyword.");
+ return "";
+}
+
+DependentTemplateSpecializationType::DependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, const IdentifierInfo *Name,
+ unsigned NumArgs, const TemplateArgument *Args,
+ QualType Canon)
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
+ NNS(NNS), Name(Name), NumArgs(NumArgs) {
+ assert(NNS && NNS->isDependent() &&
+ "DependentTemplateSpecializatonType requires dependent qualifier");
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ if (Args[I].containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
+ new (&getArgBuffer()[I]) TemplateArgument(Args[I]);
+ }
+}
+
+void
+DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Name,
+ unsigned NumArgs,
+ const TemplateArgument *Args) {
+ ID.AddInteger(Keyword);
+ ID.AddPointer(Qualifier);
+ ID.AddPointer(Name);
+ for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
+ Args[Idx].Profile(ID, Context);
+}
+
+bool Type::isElaboratedTypeSpecifier() const {
+ ElaboratedTypeKeyword Keyword;
+ if (const ElaboratedType *Elab = dyn_cast<ElaboratedType>(this))
+ Keyword = Elab->getKeyword();
+ else if (const DependentNameType *DepName = dyn_cast<DependentNameType>(this))
+ Keyword = DepName->getKeyword();
+ else if (const DependentTemplateSpecializationType *DepTST =
+ dyn_cast<DependentTemplateSpecializationType>(this))
+ Keyword = DepTST->getKeyword();
+ else
+ return false;
+
+ return TypeWithKeyword::KeywordIsTagTypeKind(Keyword);
+}
+
+const char *Type::getTypeClassName() const {
+ switch (TypeBits.TC) {
+#define ABSTRACT_TYPE(Derived, Base)
+#define TYPE(Derived, Base) case Derived: return #Derived;
+#include "clang/AST/TypeNodes.def"
+ }
+
+ llvm_unreachable("Invalid type class.");
+ return 0;
+}
+
+const char *BuiltinType::getName(const LangOptions &LO) const {
+ switch (getKind()) {
+ case Void: return "void";
+ case Bool: return LO.Bool ? "bool" : "_Bool";
+ case Char_S: return "char";
+ case Char_U: return "char";
+ case SChar: return "signed char";
+ case Short: return "short";
+ case Int: return "int";
+ case Long: return "long";
+ case LongLong: return "long long";
+ case Int128: return "__int128_t";
+ case UChar: return "unsigned char";
+ case UShort: return "unsigned short";
+ case UInt: return "unsigned int";
+ case ULong: return "unsigned long";
+ case ULongLong: return "unsigned long long";
+ case UInt128: return "__uint128_t";
+ case Float: return "float";
+ case Double: return "double";
+ case LongDouble: return "long double";
+ case WChar_S:
+ case WChar_U: return "wchar_t";
+ case Char16: return "char16_t";
+ case Char32: return "char32_t";
+ case NullPtr: return "nullptr_t";
+ case Overload: return "<overloaded function type>";
+ case Dependent: return "<dependent type>";
+ case ObjCId: return "id";
+ case ObjCClass: return "Class";
+ case ObjCSel: return "SEL";
+ }
+
+ llvm_unreachable("Invalid builtin type.");
+ return 0;
+}
+
+QualType QualType::getNonLValueExprType(ASTContext &Context) const {
+ if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>())
+ return RefType->getPointeeType();
+
+ // C++0x [basic.lval]:
+ // Class prvalues can have cv-qualified types; non-class prvalues always
+ // have cv-unqualified types.
+ //
+ // See also C99 6.3.2.1p2.
+ if (!Context.getLangOptions().CPlusPlus ||
+ (!getTypePtr()->isDependentType() && !getTypePtr()->isRecordType()))
+ return getUnqualifiedType();
+
+ return *this;
+}
+
+llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
+ switch (CC) {
+ case CC_Default:
+ llvm_unreachable("no name for default cc");
+ return "";
+
+ case CC_C: return "cdecl";
+ case CC_X86StdCall: return "stdcall";
+ case CC_X86FastCall: return "fastcall";
+ case CC_X86ThisCall: return "thiscall";
+ case CC_X86Pascal: return "pascal";
+ }
+
+ llvm_unreachable("Invalid calling convention.");
+ return "";
+}
+
+FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
+ unsigned numArgs, QualType canonical,
+ const ExtProtoInfo &epi)
+ : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals,
+ epi.RefQualifier, canonical,
+ result->isDependentType(),
+ result->isVariablyModifiedType(),
+ result->containsUnexpandedParameterPack(),
+ epi.ExtInfo),
+ NumArgs(numArgs), NumExceptions(epi.NumExceptions),
+ HasExceptionSpec(epi.HasExceptionSpec),
+ HasAnyExceptionSpec(epi.HasAnyExceptionSpec)
+{
+ // Fill in the trailing argument array.
+ QualType *argSlot = reinterpret_cast<QualType*>(this+1);
+ for (unsigned i = 0; i != numArgs; ++i) {
+ if (args[i]->isDependentType())
+ setDependent();
+
+ if (args[i]->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
+ argSlot[i] = args[i];
+ }
+
+ // Fill in the exception array.
+ QualType *exnSlot = argSlot + numArgs;
+ for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) {
+ if (epi.Exceptions[i]->isDependentType())
+ setDependent();
+
+ if (epi.Exceptions[i]->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
+ exnSlot[i] = epi.Exceptions[i];
+ }
+}
+
+bool FunctionProtoType::isTemplateVariadic() const {
+ for (unsigned ArgIdx = getNumArgs(); ArgIdx; --ArgIdx)
+ if (isa<PackExpansionType>(getArgType(ArgIdx - 1)))
+ return true;
+
+ return false;
+}
+
+void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
+ const QualType *ArgTys, unsigned NumArgs,
+ const ExtProtoInfo &epi) {
+ ID.AddPointer(Result.getAsOpaquePtr());
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddPointer(ArgTys[i].getAsOpaquePtr());
+ ID.AddBoolean(epi.Variadic);
+ ID.AddInteger(epi.TypeQuals);
+ ID.AddInteger(epi.RefQualifier);
+ if (epi.HasExceptionSpec) {
+ ID.AddBoolean(epi.HasAnyExceptionSpec);
+ for (unsigned i = 0; i != epi.NumExceptions; ++i)
+ ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
+ }
+ epi.ExtInfo.Profile(ID);
+}
+
+void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo());
+}
+
+QualType TypedefType::desugar() const {
+ return getDecl()->getUnderlyingType();
+}
+
+TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
+ : Type(TypeOfExpr, can, E->isTypeDependent(),
+ E->getType()->isVariablyModifiedType(),
+ E->containsUnexpandedParameterPack()),
+ TOExpr(E) {
+}
+
+QualType TypeOfExprType::desugar() const {
+ return getUnderlyingExpr()->getType();
+}
+
+void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context, Expr *E) {
+ E->Profile(ID, Context, true);
+}
+
+DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
+ : Type(Decltype, can, E->isTypeDependent(),
+ E->getType()->isVariablyModifiedType(),
+ E->containsUnexpandedParameterPack()),
+ E(E),
+ UnderlyingType(underlyingType) {
+}
+
+DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E)
+ : DecltypeType(E, Context.DependentTy), Context(Context) { }
+
+void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &Context, Expr *E) {
+ E->Profile(ID, Context, true);
+}
+
+TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
+ : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ decl(const_cast<TagDecl*>(D)) {}
+
+static TagDecl *getInterestingTagDecl(TagDecl *decl) {
+ for (TagDecl::redecl_iterator I = decl->redecls_begin(),
+ E = decl->redecls_end();
+ I != E; ++I) {
+ if (I->isDefinition() || I->isBeingDefined())
+ return *I;
+ }
+ // If there's no definition (not even in progress), return what we have.
+ return decl;
+}
+
+TagDecl *TagType::getDecl() const {
+ return getInterestingTagDecl(decl);
+}
+
+bool TagType::isBeingDefined() const {
+ return getDecl()->isBeingDefined();
+}
+
+CXXRecordDecl *InjectedClassNameType::getDecl() const {
+ return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
+}
+
+bool RecordType::classof(const TagType *TT) {
+ return isa<RecordDecl>(TT->getDecl());
+}
+
+bool EnumType::classof(const TagType *TT) {
+ return isa<EnumDecl>(TT->getDecl());
+}
+
+SubstTemplateTypeParmPackType::
+SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
+ QualType Canon,
+ const TemplateArgument &ArgPack)
+ : Type(SubstTemplateTypeParmPack, Canon, true, false, true), Replaced(Param),
+ Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size())
+{
+}
+
+TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
+ return TemplateArgument(Arguments, NumArguments);
+}
+
+void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getReplacedParameter(), getArgumentPack());
+}
+
+void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ const TemplateArgument &ArgPack) {
+ ID.AddPointer(Replaced);
+ ID.AddInteger(ArgPack.pack_size());
+ for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(),
+ PEnd = ArgPack.pack_end();
+ P != PEnd; ++P)
+ ID.AddPointer(P->getAsType().getAsOpaquePtr());
+}
+
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) {
+ return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size());
+}
+
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
+ for (unsigned i = 0; i != N; ++i)
+ if (Args[i].getArgument().isDependent())
+ return true;
+ return false;
+}
+
+bool TemplateSpecializationType::
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
+ for (unsigned i = 0; i != N; ++i)
+ if (Args[i].isDependent())
+ return true;
+ return false;
+}
+
+TemplateSpecializationType::
+TemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs, QualType Canon)
+ : Type(TemplateSpecialization,
+ Canon.isNull()? QualType(this, 0) : Canon,
+ T.isDependent(), false,
+ T.containsUnexpandedParameterPack()),
+ Template(T), NumArgs(NumArgs)
+{
+ assert((!Canon.isNull() ||
+ T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
+ "No canonical type for non-dependent class template specialization");
+
+ TemplateArgument *TemplateArgs
+ = reinterpret_cast<TemplateArgument *>(this + 1);
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ // Update dependent and variably-modified bits.
+ if (Args[Arg].isDependent())
+ setDependent();
+ if (Args[Arg].getKind() == TemplateArgument::Type &&
+ Args[Arg].getAsType()->isVariablyModifiedType())
+ setVariablyModified();
+ if (Args[Arg].containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
+ new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
+ }
+}
+
+void
+TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const ASTContext &Context) {
+ T.Profile(ID);
+ for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
+ Args[Idx].Profile(ID, Context);
+}
+
+QualType
+QualifierCollector::apply(const ASTContext &Context, QualType QT) const {
+ if (!hasNonFastQualifiers())
+ return QT.withFastQualifiers(getFastQualifiers());
+
+ return Context.getQualifiedType(QT, *this);
+}
+
+QualType
+QualifierCollector::apply(const ASTContext &Context, const Type *T) const {
+ if (!hasNonFastQualifiers())
+ return QualType(T, getFastQualifiers());
+
+ return Context.getQualifiedType(T, *this);
+}
+
+void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID,
+ QualType BaseType,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) {
+ ID.AddPointer(BaseType.getAsOpaquePtr());
+ for (unsigned i = 0; i != NumProtocols; i++)
+ ID.AddPointer(Protocols[i]);
+}
+
+void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
+}
+
+namespace {
+
+/// \brief The cached properties of a type.
+class CachedProperties {
+ char linkage;
+ char visibility;
+ bool local;
+
+public:
+ CachedProperties(Linkage linkage, Visibility visibility, bool local)
+ : linkage(linkage), visibility(visibility), local(local) {}
+
+ Linkage getLinkage() const { return (Linkage) linkage; }
+ Visibility getVisibility() const { return (Visibility) visibility; }
+ bool hasLocalOrUnnamedType() const { return local; }
+
+ friend CachedProperties merge(CachedProperties L, CachedProperties R) {
+ return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
+ minVisibility(L.getVisibility(), R.getVisibility()),
+ L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
+ }
+};
+}
+
+static CachedProperties computeCachedProperties(const Type *T);
+
+namespace clang {
+/// The type-property cache. This is templated so as to be
+/// instantiated at an internal type to prevent unnecessary symbol
+/// leakage.
+template <class Private> class TypePropertyCache {
+public:
+ static CachedProperties get(QualType T) {
+ return get(T.getTypePtr());
+ }
+
+ static CachedProperties get(const Type *T) {
+ ensure(T);
+ return CachedProperties(T->TypeBits.getLinkage(),
+ T->TypeBits.getVisibility(),
+ T->TypeBits.hasLocalOrUnnamedType());
+ }
+
+ static void ensure(const Type *T) {
+ // If the cache is valid, we're okay.
+ if (T->TypeBits.isCacheValid()) return;
+
+ // If this type is non-canonical, ask its canonical type for the
+ // relevant information.
+ if (!T->isCanonicalUnqualified()) {
+ const Type *CT = T->getCanonicalTypeInternal().getTypePtr();
+ ensure(CT);
+ T->TypeBits.CacheValidAndVisibility =
+ CT->TypeBits.CacheValidAndVisibility;
+ T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage;
+ T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed;
+ return;
+ }
+
+ // Compute the cached properties and then set the cache.
+ CachedProperties Result = computeCachedProperties(T);
+ T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
+ assert(T->TypeBits.isCacheValid() &&
+ T->TypeBits.getVisibility() == Result.getVisibility());
+ T->TypeBits.CachedLinkage = Result.getLinkage();
+ T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
+ }
+};
+}
+
+// Instantiate the friend template at a private class. In a
+// reasonable implementation, these symbols will be internal.
+// It is terrible that this is the best way to accomplish this.
+namespace { class Private {}; }
+typedef TypePropertyCache<Private> Cache;
+
+static CachedProperties computeCachedProperties(const Type *T) {
+ switch (T->getTypeClass()) {
+#define TYPE(Class,Base)
+#define NON_CANONICAL_TYPE(Class,Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("didn't expect a non-canonical type here");
+
+#define TYPE(Class,Base)
+#define DEPENDENT_TYPE(Class,Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ // Treat dependent types as external.
+ assert(T->isDependentType());
+ return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+
+ case Type::Builtin:
+ // C++ [basic.link]p8:
+ // A type is said to have linkage if and only if:
+ // - it is a fundamental type (3.9.1); or
+ return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+
+ case Type::Record:
+ case Type::Enum: {
+ const TagDecl *Tag = cast<TagType>(T)->getDecl();
+
+ // C++ [basic.link]p8:
+ // - it is a class or enumeration type that is named (or has a name
+ // for linkage purposes (7.1.3)) and the name has linkage; or
+ // - it is a specialization of a class template (14); or
+ NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility();
+ bool IsLocalOrUnnamed =
+ Tag->getDeclContext()->isFunctionOrMethod() ||
+ (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl());
+ return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed);
+ }
+
+ // C++ [basic.link]p8:
+ // - it is a compound type (3.9.2) other than a class or enumeration,
+ // compounded exclusively from types that have linkage; or
+ case Type::Complex:
+ return Cache::get(cast<ComplexType>(T)->getElementType());
+ case Type::Pointer:
+ return Cache::get(cast<PointerType>(T)->getPointeeType());
+ case Type::BlockPointer:
+ return Cache::get(cast<BlockPointerType>(T)->getPointeeType());
+ case Type::LValueReference:
+ case Type::RValueReference:
+ return Cache::get(cast<ReferenceType>(T)->getPointeeType());
+ case Type::MemberPointer: {
+ const MemberPointerType *MPT = cast<MemberPointerType>(T);
+ return merge(Cache::get(MPT->getClass()),
+ Cache::get(MPT->getPointeeType()));
+ }
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ return Cache::get(cast<ArrayType>(T)->getElementType());
+ case Type::Vector:
+ case Type::ExtVector:
+ return Cache::get(cast<VectorType>(T)->getElementType());
+ case Type::FunctionNoProto:
+ return Cache::get(cast<FunctionType>(T)->getResultType());
+ case Type::FunctionProto: {
+ const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ CachedProperties result = Cache::get(FPT->getResultType());
+ for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(),
+ ae = FPT->arg_type_end(); ai != ae; ++ai)
+ result = merge(result, Cache::get(*ai));
+ return result;
+ }
+ case Type::ObjCInterface: {
+ NamedDecl::LinkageInfo LV =
+ cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility();
+ return CachedProperties(LV.linkage(), LV.visibility(), false);
+ }
+ case Type::ObjCObject:
+ return Cache::get(cast<ObjCObjectType>(T)->getBaseType());
+ case Type::ObjCObjectPointer:
+ return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
+ }
+
+ llvm_unreachable("unhandled type class");
+
+ // C++ [basic.link]p8:
+ // Names not covered by these rules have no linkage.
+ return CachedProperties(NoLinkage, DefaultVisibility, false);
+}
+
+/// \brief Determine the linkage of this type.
+Linkage Type::getLinkage() const {
+ Cache::ensure(this);
+ return TypeBits.getLinkage();
+}
+
+/// \brief Determine the linkage of this type.
+Visibility Type::getVisibility() const {
+ Cache::ensure(this);
+ return TypeBits.getVisibility();
+}
+
+bool Type::hasUnnamedOrLocalType() const {
+ Cache::ensure(this);
+ return TypeBits.hasLocalOrUnnamedType();
+}
+
+std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const {
+ Cache::ensure(this);
+ return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility());
+}
+
+void Type::ClearLinkageCache() {
+ TypeBits.CacheValidAndVisibility = 0;
+ if (QualType(this, 0) != CanonicalType)
+ CanonicalType->TypeBits.CacheValidAndVisibility = 0;
+}
+
+bool Type::hasSizedVLAType() const {
+ if (!isVariablyModifiedType()) return false;
+
+ if (const PointerType *ptr = getAs<PointerType>())
+ return ptr->getPointeeType()->hasSizedVLAType();
+ if (const ReferenceType *ref = getAs<ReferenceType>())
+ return ref->getPointeeType()->hasSizedVLAType();
+ if (const ArrayType *arr = getAsArrayTypeUnsafe()) {
+ if (isa<VariableArrayType>(arr) &&
+ cast<VariableArrayType>(arr)->getSizeExpr())
+ return true;
+
+ return arr->getElementType()->hasSizedVLAType();
+ }
+
+ return false;
+}
+
+QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
+ /// Currently, the only destruction kind we recognize is C++ objects
+ /// with non-trivial destructors.
+ const CXXRecordDecl *record =
+ type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ if (record && !record->hasTrivialDestructor())
+ return DK_cxx_destructor;
+
+ return DK_none;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
new file mode 100644
index 0000000..14db7f8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -0,0 +1,265 @@
+//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- 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 TypeLoc subclasses implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TypeLoc Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalSourceRange(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
+ if (TL.isNull()) return SourceRange();
+ return TypeLocRanger().Visit(TL);
+}
+
+namespace {
+ class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getFullDataSize(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Returns the size of the type source info data block.
+unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
+ if (Ty.isNull()) return 0;
+ return TypeSizer().Visit(TypeLoc(Ty, 0));
+}
+
+namespace {
+ class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getNextTypeLoc(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
+TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
+ return NextLoc().Visit(TL);
+}
+
+/// \brief Initializes a type location, and all of its children
+/// recursively, as if the entire tree had been written in the
+/// given location.
+void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
+ SourceLocation Loc) {
+ while (true) {
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case CLASS: { \
+ CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
+ TLCasted.initializeLocal(Context, Loc); \
+ TL = TLCasted.getNextTypeLoc(); \
+ if (!TL) return; \
+ continue; \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+}
+
+SourceLocation TypeLoc::getBeginLoc() const {
+ TypeLoc Cur = *this;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ // FIXME: Currently QualifiedTypeLoc does not have a source range
+ // case Qualified:
+ case Elaborated:
+ break;
+ default:
+ TypeLoc Next = Cur.getNextTypeLoc();
+ if (Next.isNull()) break;
+ Cur = Next;
+ continue;
+ }
+ break;
+ }
+ return Cur.getLocalSourceRange().getBegin();
+}
+
+SourceLocation TypeLoc::getEndLoc() const {
+ TypeLoc Cur = *this;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ default:
+ break;
+ case Qualified:
+ case Elaborated:
+ Cur = Cur.getNextTypeLoc();
+ continue;
+ }
+ break;
+ }
+ return Cur.getLocalSourceRange().getEnd();
+}
+
+
+namespace {
+ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class. Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+ if (TL->getType().hasLocalQualifiers()) return false;
+ return TSTChecker().Visit(*TL);
+}
+
+// Reimplemented to account for GNU/C++ extension
+// typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
+ if (getRParenLoc().isValid())
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ else
+ return SourceRange(getTypeofLoc(),
+ getUnderlyingExpr()->getSourceRange().getEnd());
+}
+
+
+TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
+ else {
+ switch (getTypePtr()->getKind()) {
+ case BuiltinType::Void:
+ return TST_void;
+ case BuiltinType::Bool:
+ return TST_bool;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ return TST_char;
+ case BuiltinType::Char16:
+ return TST_char16;
+ case BuiltinType::Char32:
+ return TST_char32;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ return TST_wchar;
+
+ case BuiltinType::UChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::Int128:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ llvm_unreachable("Builtin type needs extra local data!");
+ // Fall through, if the impossible happens.
+
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return TST_unspecified;
+ }
+ }
+
+ return TST_unspecified;
+}
+
+TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
+ while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
+ TL = PTL->getInnerLoc();
+ return TL;
+}
+
+void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
+ unsigned NumArgs,
+ const TemplateArgument *Args,
+ TemplateArgumentLocInfo *ArgInfos,
+ SourceLocation Loc) {
+ for (unsigned i = 0, e = NumArgs; i != e; ++i) {
+ switch (Args[i].getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Expression:
+ // FIXME: Can we do better for declarations and integral values?
+ ArgInfos[i] = TemplateArgumentLocInfo();
+ break;
+
+ case TemplateArgument::Type:
+ ArgInfos[i] = TemplateArgumentLocInfo(
+ Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
+ Loc));
+ break;
+
+ case TemplateArgument::Template:
+ ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc,
+ SourceLocation());
+ break;
+
+ case TemplateArgument::TemplateExpansion:
+ ArgInfos[i] = TemplateArgumentLocInfo(SourceRange(Loc), Loc, Loc);
+ break;
+ }
+ }
+}
+
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
new file mode 100644
index 0000000..1390739
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -0,0 +1,1062 @@
+//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to print types from Clang's type system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+ class TypePrinter {
+ PrintingPolicy Policy;
+
+ public:
+ explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
+
+ void print(const Type *ty, Qualifiers qs, std::string &buffer);
+ void print(QualType T, std::string &S);
+ void AppendScope(DeclContext *DC, std::string &S);
+ void printTag(TagDecl *T, std::string &S);
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) \
+ void print##CLASS(const CLASS##Type *T, std::string &S);
+#include "clang/AST/TypeNodes.def"
+ };
+}
+
+static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
+ if (TypeQuals & Qualifiers::Const) {
+ if (!S.empty()) S += ' ';
+ S += "const";
+ }
+ if (TypeQuals & Qualifiers::Volatile) {
+ if (!S.empty()) S += ' ';
+ S += "volatile";
+ }
+ if (TypeQuals & Qualifiers::Restrict) {
+ if (!S.empty()) S += ' ';
+ S += "restrict";
+ }
+}
+
+void TypePrinter::print(QualType t, std::string &buffer) {
+ SplitQualType split = t.split();
+ print(split.first, split.second, buffer);
+}
+
+void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
+ if (!T) {
+ buffer += "NULL TYPE";
+ return;
+ }
+
+ if (Policy.SuppressSpecifiers && T->isSpecifierType())
+ return;
+
+ // Print qualifiers as appropriate.
+
+ // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
+ // so that we get "const int" instead of "int const", but we can't do this if
+ // the type is complex. For example if the type is "int*", we *must* print
+ // "int * const", printing "const int *" is different. Only do this when the
+ // type expands to a simple string.
+ bool CanPrefixQualifiers = false;
+
+ Type::TypeClass TC = T->getTypeClass();
+ if (const AutoType *AT = dyn_cast<AutoType>(T))
+ TC = AT->desugar()->getTypeClass();
+ if (const SubstTemplateTypeParmType *Subst
+ = dyn_cast<SubstTemplateTypeParmType>(T))
+ TC = Subst->getReplacementType()->getTypeClass();
+
+ switch (TC) {
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::UnresolvedUsing:
+ case Type::Typedef:
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::Record:
+ case Type::Enum:
+ case Type::Elaborated:
+ case Type::TemplateTypeParm:
+ case Type::SubstTemplateTypeParmPack:
+ case Type::TemplateSpecialization:
+ case Type::InjectedClassName:
+ case Type::DependentName:
+ case Type::DependentTemplateSpecialization:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ CanPrefixQualifiers = true;
+ break;
+
+ case Type::ObjCObjectPointer:
+ CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
+ T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
+ break;
+
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Paren:
+ case Type::Attributed:
+ case Type::PackExpansion:
+ case Type::SubstTemplateTypeParm:
+ case Type::Auto:
+ CanPrefixQualifiers = false;
+ break;
+ }
+
+ if (!CanPrefixQualifiers && !Quals.empty()) {
+ std::string qualsBuffer;
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+
+ if (!buffer.empty()) {
+ qualsBuffer += ' ';
+ qualsBuffer += buffer;
+ }
+ std::swap(buffer, qualsBuffer);
+ }
+
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) case Type::CLASS: \
+ print##CLASS(cast<CLASS##Type>(T), buffer); \
+ break;
+#include "clang/AST/TypeNodes.def"
+ }
+
+ // If we're adding the qualifiers as a prefix, do it now.
+ if (CanPrefixQualifiers && !Quals.empty()) {
+ std::string qualsBuffer;
+ Quals.getAsStringInternal(qualsBuffer, Policy);
+
+ if (!buffer.empty()) {
+ qualsBuffer += ' ';
+ qualsBuffer += buffer;
+ }
+ std::swap(buffer, qualsBuffer);
+ }
+}
+
+void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
+ if (S.empty()) {
+ S = T->getName(Policy.LangOpts);
+ } else {
+ // Prefix the basic type, e.g. 'int X'.
+ S = ' ' + S;
+ S = T->getName(Policy.LangOpts) + S;
+ }
+}
+
+void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
+ print(T->getElementType(), S);
+ S = "_Complex " + S;
+}
+
+void TypePrinter::printPointer(const PointerType *T, std::string &S) {
+ S = '*' + S;
+
+ // Handle things like 'int (*A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeType()))
+ S = '(' + S + ')';
+
+ print(T->getPointeeType(), S);
+}
+
+void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
+ S = '^' + S;
+ print(T->getPointeeType(), S);
+}
+
+void TypePrinter::printLValueReference(const LValueReferenceType *T,
+ std::string &S) {
+ S = '&' + S;
+
+ // Handle things like 'int (&A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ S = '(' + S + ')';
+
+ print(T->getPointeeTypeAsWritten(), S);
+}
+
+void TypePrinter::printRValueReference(const RValueReferenceType *T,
+ std::string &S) {
+ S = "&&" + S;
+
+ // Handle things like 'int (&&A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ S = '(' + S + ')';
+
+ print(T->getPointeeTypeAsWritten(), S);
+}
+
+void TypePrinter::printMemberPointer(const MemberPointerType *T,
+ std::string &S) {
+ std::string C;
+ print(QualType(T->getClass(), 0), C);
+ C += "::*";
+ S = C + S;
+
+ // Handle things like 'int (Cls::*A)[4];' correctly.
+ // FIXME: this should include vectors, but vectors use attributes I guess.
+ if (isa<ArrayType>(T->getPointeeType()))
+ S = '(' + S + ')';
+
+ print(T->getPointeeType(), S);
+}
+
+void TypePrinter::printConstantArray(const ConstantArrayType *T,
+ std::string &S) {
+ S += '[';
+ S += llvm::utostr(T->getSize().getZExtValue());
+ S += ']';
+
+ print(T->getElementType(), S);
+}
+
+void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
+ std::string &S) {
+ S += "[]";
+ print(T->getElementType(), S);
+}
+
+void TypePrinter::printVariableArray(const VariableArrayType *T,
+ std::string &S) {
+ S += '[';
+
+ if (T->getIndexTypeQualifiers().hasQualifiers()) {
+ AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
+ S += ' ';
+ }
+
+ if (T->getSizeModifier() == VariableArrayType::Static)
+ S += "static";
+ else if (T->getSizeModifier() == VariableArrayType::Star)
+ S += '*';
+
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ']';
+
+ print(T->getElementType(), S);
+}
+
+void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
+ std::string &S) {
+ S += '[';
+
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ']';
+
+ print(T->getElementType(), S);
+}
+
+void TypePrinter::printDependentSizedExtVector(
+ const DependentSizedExtVectorType *T,
+ std::string &S) {
+ print(T->getElementType(), S);
+
+ S += " __attribute__((ext_vector_type(";
+ if (T->getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ T->getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ")))";
+}
+
+void TypePrinter::printVector(const VectorType *T, std::string &S) {
+ switch (T->getVectorKind()) {
+ case VectorType::AltiVecPixel:
+ S = "__vector __pixel " + S;
+ break;
+ case VectorType::AltiVecBool:
+ print(T->getElementType(), S);
+ S = "__vector __bool " + S;
+ break;
+ case VectorType::AltiVecVector:
+ print(T->getElementType(), S);
+ S = "__vector " + S;
+ break;
+ case VectorType::NeonVector:
+ print(T->getElementType(), S);
+ S = ("__attribute__((neon_vector_type(" +
+ llvm::utostr_32(T->getNumElements()) + "))) " + S);
+ break;
+ case VectorType::NeonPolyVector:
+ print(T->getElementType(), S);
+ S = ("__attribute__((neon_polyvector_type(" +
+ llvm::utostr_32(T->getNumElements()) + "))) " + S);
+ break;
+ case VectorType::GenericVector: {
+ // FIXME: We prefer to print the size directly here, but have no way
+ // to get the size of the type.
+ print(T->getElementType(), S);
+ std::string V = "__attribute__((__vector_size__(";
+ V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
+ std::string ET;
+ print(T->getElementType(), ET);
+ V += " * sizeof(" + ET + ")))) ";
+ S = V + S;
+ break;
+ }
+ }
+}
+
+void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) {
+ S += " __attribute__((ext_vector_type(";
+ S += llvm::utostr_32(T->getNumElements());
+ S += ")))";
+ print(T->getElementType(), S);
+}
+
+void TypePrinter::printFunctionProto(const FunctionProtoType *T,
+ std::string &S) {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ if (!S.empty())
+ S = "(" + S + ")";
+
+ S += "(";
+ std::string Tmp;
+ PrintingPolicy ParamPolicy(Policy);
+ ParamPolicy.SuppressSpecifiers = false;
+ for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
+ if (i) S += ", ";
+ print(T->getArgType(i), Tmp);
+ S += Tmp;
+ Tmp.clear();
+ }
+
+ if (T->isVariadic()) {
+ if (T->getNumArgs())
+ S += ", ";
+ S += "...";
+ } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
+ // Do not emit int() if we have a proto, emit 'int(void)'.
+ S += "void";
+ }
+
+ S += ")";
+
+ FunctionType::ExtInfo Info = T->getExtInfo();
+ switch(Info.getCC()) {
+ case CC_Default:
+ default: break;
+ case CC_C:
+ S += " __attribute__((cdecl))";
+ break;
+ case CC_X86StdCall:
+ S += " __attribute__((stdcall))";
+ break;
+ case CC_X86FastCall:
+ S += " __attribute__((fastcall))";
+ break;
+ case CC_X86ThisCall:
+ S += " __attribute__((thiscall))";
+ break;
+ case CC_X86Pascal:
+ S += " __attribute__((pascal))";
+ break;
+ }
+ if (Info.getNoReturn())
+ S += " __attribute__((noreturn))";
+ if (Info.getRegParm())
+ S += " __attribute__((regparm (" +
+ llvm::utostr_32(Info.getRegParm()) + ")))";
+
+ AppendTypeQualList(S, T->getTypeQuals());
+
+ switch (T->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ S += " &";
+ break;
+
+ case RQ_RValue:
+ S += " &&";
+ break;
+ }
+
+ if (T->hasExceptionSpec()) {
+ S += " throw(";
+ if (T->hasAnyExceptionSpec())
+ S += "...";
+ else
+ for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
+ if (I)
+ S += ", ";
+
+ std::string ExceptionType;
+ print(T->getExceptionType(I), ExceptionType);
+ S += ExceptionType;
+ }
+ S += ")";
+ }
+
+ print(T->getResultType(), S);
+}
+
+void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
+ std::string &S) {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ if (!S.empty())
+ S = "(" + S + ")";
+
+ S += "()";
+ if (T->getNoReturnAttr())
+ S += " __attribute__((noreturn))";
+ print(T->getResultType(), S);
+}
+
+static void printTypeSpec(const NamedDecl *D, std::string &S) {
+ IdentifierInfo *II = D->getIdentifier();
+ if (S.empty())
+ S = II->getName().str();
+ else
+ S = II->getName().str() + ' ' + S;
+}
+
+void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
+ std::string &S) {
+ printTypeSpec(T->getDecl(), S);
+}
+
+void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
+ printTypeSpec(T->getDecl(), S);
+}
+
+void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
+ S = ' ' + S;
+ std::string Str;
+ llvm::raw_string_ostream s(Str);
+ T->getUnderlyingExpr()->printPretty(s, 0, Policy);
+ S = "typeof " + s.str() + S;
+}
+
+void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
+ S = ' ' + S;
+ std::string Tmp;
+ print(T->getUnderlyingType(), Tmp);
+ S = "typeof(" + Tmp + ")" + S;
+}
+
+void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
+ S = ' ' + S;
+ std::string Str;
+ llvm::raw_string_ostream s(Str);
+ T->getUnderlyingExpr()->printPretty(s, 0, Policy);
+ S = "decltype(" + s.str() + ")" + S;
+}
+
+void TypePrinter::printAuto(const AutoType *T, std::string &S) {
+ // If the type has been deduced, do not print 'auto'.
+ if (T->isDeduced()) {
+ print(T->getDeducedType(), S);
+ } else {
+ if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
+ S = ' ' + S;
+ S = "auto" + S;
+ }
+}
+
+/// Appends the given scope to the end of a string.
+void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
+ if (DC->isTranslationUnit()) return;
+ AppendScope(DC->getParent(), Buffer);
+
+ unsigned OldSize = Buffer.size();
+
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
+ if (NS->getIdentifier())
+ Buffer += NS->getNameAsString();
+ else
+ Buffer += "<anonymous>";
+ } else if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateArgs.data(),
+ TemplateArgs.size(),
+ Policy);
+ Buffer += Spec->getIdentifier()->getName();
+ Buffer += TemplateArgsStr;
+ } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
+ Buffer += Typedef->getIdentifier()->getName();
+ else if (Tag->getIdentifier())
+ Buffer += Tag->getIdentifier()->getName();
+ }
+
+ if (Buffer.size() != OldSize)
+ Buffer += "::";
+}
+
+void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
+ if (Policy.SuppressTag)
+ return;
+
+ std::string Buffer;
+ bool HasKindDecoration = false;
+
+ // We don't print tags unless this is an elaborated type.
+ // In C, we just assume every RecordType is an elaborated type.
+ if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
+ HasKindDecoration = true;
+ Buffer += D->getKindName();
+ Buffer += ' ';
+ }
+
+ // Compute the full nested-name-specifier for this type.
+ // In C, this will always be empty except when the type
+ // being printed is anonymous within other Record.
+ if (!Policy.SuppressScope)
+ AppendScope(D->getDeclContext(), Buffer);
+
+ if (const IdentifierInfo *II = D->getIdentifier())
+ Buffer += II->getNameStart();
+ else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
+ assert(Typedef->getIdentifier() && "Typedef without identifier?");
+ Buffer += Typedef->getIdentifier()->getNameStart();
+ } else {
+ // Make an unambiguous representation for anonymous types, e.g.
+ // <anonymous enum at /usr/include/string.h:120:9>
+ llvm::raw_string_ostream OS(Buffer);
+ OS << "<anonymous";
+
+ if (Policy.AnonymousTagLocations) {
+ // Suppress the redundant tag keyword if we just printed one.
+ // We don't have to worry about ElaboratedTypes here because you can't
+ // refer to an anonymous type with one.
+ if (!HasKindDecoration)
+ OS << " " << D->getKindName();
+
+ PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
+ D->getLocation());
+ if (PLoc.isValid()) {
+ OS << " at " << PLoc.getFilename()
+ << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ }
+ }
+
+ OS << '>';
+ }
+
+ // If this is a class template specialization, print the template
+ // arguments.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(TAW->getType());
+ Args = TST->getArgs();
+ NumArgs = TST->getNumArgs();
+ } else {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ Args = TemplateArgs.data();
+ NumArgs = TemplateArgs.size();
+ }
+ Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
+ NumArgs,
+ Policy);
+ }
+
+ if (!InnerString.empty()) {
+ Buffer += ' ';
+ Buffer += InnerString;
+ }
+
+ std::swap(Buffer, InnerString);
+}
+
+void TypePrinter::printRecord(const RecordType *T, std::string &S) {
+ printTag(T->getDecl(), S);
+}
+
+void TypePrinter::printEnum(const EnumType *T, std::string &S) {
+ printTag(T->getDecl(), S);
+}
+
+void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
+ std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
+ S = ' ' + S;
+
+ if (!T->getName())
+ S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
+ llvm::utostr_32(T->getIndex()) + S;
+ else
+ S = T->getName()->getName().str() + S;
+}
+
+void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
+ std::string &S) {
+ print(T->getReplacementType(), S);
+}
+
+void TypePrinter::printSubstTemplateTypeParmPack(
+ const SubstTemplateTypeParmPackType *T,
+ std::string &S) {
+ printTemplateTypeParm(T->getReplacedParameter(), S);
+}
+
+void TypePrinter::printTemplateSpecialization(
+ const TemplateSpecializationType *T,
+ std::string &S) {
+ std::string SpecString;
+
+ {
+ llvm::raw_string_ostream OS(SpecString);
+ T->getTemplateName().print(OS, Policy);
+ }
+
+ SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
+ T->getArgs(),
+ T->getNumArgs(),
+ Policy);
+ if (S.empty())
+ S.swap(SpecString);
+ else
+ S = SpecString + ' ' + S;
+}
+
+void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
+ std::string &S) {
+ printTemplateSpecialization(T->getInjectedTST(), S);
+}
+
+void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
+ std::string MyString;
+
+ {
+ llvm::raw_string_ostream OS(MyString);
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
+ NestedNameSpecifier* Qualifier = T->getQualifier();
+ if (Qualifier)
+ Qualifier->print(OS, Policy);
+ }
+
+ std::string TypeStr;
+ PrintingPolicy InnerPolicy(Policy);
+ InnerPolicy.SuppressScope = true;
+ TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
+
+ MyString += TypeStr;
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::printParen(const ParenType *T, std::string &S) {
+ if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
+ S = '(' + S + ')';
+ print(T->getInnerType(), S);
+}
+
+void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
+ std::string MyString;
+
+ {
+ llvm::raw_string_ostream OS(MyString);
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
+
+ T->getQualifier()->print(OS, Policy);
+
+ OS << T->getIdentifier()->getName();
+ }
+
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::printDependentTemplateSpecialization(
+ const DependentTemplateSpecializationType *T, std::string &S) {
+ std::string MyString;
+ {
+ llvm::raw_string_ostream OS(MyString);
+
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
+
+ T->getQualifier()->print(OS, Policy);
+ OS << T->getIdentifier()->getName();
+ OS << TemplateSpecializationType::PrintTemplateArgumentList(
+ T->getArgs(),
+ T->getNumArgs(),
+ Policy);
+ }
+
+ if (S.empty())
+ S.swap(MyString);
+ else
+ S = MyString + ' ' + S;
+}
+
+void TypePrinter::printPackExpansion(const PackExpansionType *T,
+ std::string &S) {
+ print(T->getPattern(), S);
+ S += "...";
+}
+
+void TypePrinter::printAttributed(const AttributedType *T,
+ std::string &S) {
+ print(T->getModifiedType(), S);
+
+ // TODO: not all attributes are GCC-style attributes.
+ S += "__attribute__((";
+ switch (T->getAttrKind()) {
+ case AttributedType::attr_address_space:
+ S += "address_space(";
+ S += T->getEquivalentType().getAddressSpace();
+ S += ")";
+ break;
+
+ case AttributedType::attr_vector_size: {
+ S += "__vector_size__(";
+ if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
+ S += vector->getNumElements();
+ S += " * sizeof(";
+
+ std::string tmp;
+ print(vector->getElementType(), tmp);
+ S += tmp;
+ S += ")";
+ }
+ S += ")";
+ break;
+ }
+
+ case AttributedType::attr_neon_vector_type:
+ case AttributedType::attr_neon_polyvector_type: {
+ if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
+ S += "neon_vector_type(";
+ else
+ S += "neon_polyvector_type(";
+ const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
+ S += llvm::utostr_32(vector->getNumElements());
+ S += ")";
+ break;
+ }
+
+ case AttributedType::attr_regparm: {
+ S += "regparm(";
+ QualType t = T->getEquivalentType();
+ while (!t->isFunctionType())
+ t = t->getPointeeType();
+ S += t->getAs<FunctionType>()->getRegParmType();
+ S += ")";
+ break;
+ }
+
+ case AttributedType::attr_objc_gc: {
+ S += "objc_gc(";
+
+ QualType tmp = T->getEquivalentType();
+ while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
+ QualType next = tmp->getPointeeType();
+ if (next == tmp) break;
+ tmp = next;
+ }
+
+ if (tmp.isObjCGCWeak())
+ S += "weak";
+ else
+ S += "strong";
+ S += ")";
+ break;
+ }
+
+ case AttributedType::attr_noreturn: S += "noreturn"; break;
+ case AttributedType::attr_cdecl: S += "cdecl"; break;
+ case AttributedType::attr_fastcall: S += "fastcall"; break;
+ case AttributedType::attr_stdcall: S += "stdcall"; break;
+ case AttributedType::attr_thiscall: S += "thiscall"; break;
+ case AttributedType::attr_pascal: S += "pascal"; break;
+ }
+ S += "))";
+}
+
+void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
+ std::string &S) {
+ if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ S = ' ' + S;
+
+ std::string ObjCQIString = T->getDecl()->getNameAsString();
+ S = ObjCQIString + S;
+}
+
+void TypePrinter::printObjCObject(const ObjCObjectType *T,
+ std::string &S) {
+ if (T->qual_empty())
+ return print(T->getBaseType(), S);
+
+ std::string tmp;
+ print(T->getBaseType(), tmp);
+ tmp += '<';
+ bool isFirst = true;
+ for (ObjCObjectType::qual_iterator
+ I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
+ if (isFirst)
+ isFirst = false;
+ else
+ tmp += ',';
+ tmp += (*I)->getNameAsString();
+ }
+ tmp += '>';
+
+ if (!S.empty()) {
+ tmp += ' ';
+ tmp += S;
+ }
+ std::swap(tmp, S);
+}
+
+void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
+ std::string &S) {
+ std::string ObjCQIString;
+
+ T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
+ Policy);
+ if (!ObjCQIString.empty())
+ ObjCQIString += ' ';
+
+ if (T->isObjCIdType() || T->isObjCQualifiedIdType())
+ ObjCQIString += "id";
+ else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
+ ObjCQIString += "Class";
+ else if (T->isObjCSelType())
+ ObjCQIString += "SEL";
+ else
+ ObjCQIString += T->getInterfaceDecl()->getNameAsString();
+
+ if (!T->qual_empty()) {
+ ObjCQIString += '<';
+ for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
+ E = T->qual_end();
+ I != E; ++I) {
+ ObjCQIString += (*I)->getNameAsString();
+ if (I+1 != E)
+ ObjCQIString += ',';
+ }
+ ObjCQIString += '>';
+ }
+
+ if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
+ ObjCQIString += " *"; // Don't forget the implicit pointer.
+ else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ S = ' ' + S;
+
+ S = ObjCQIString + S;
+}
+
+std::string TemplateSpecializationType::
+ PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
+ const PrintingPolicy &Policy) {
+ return PrintTemplateArgumentList(Args.getArgumentArray(),
+ Args.size(),
+ Policy);
+}
+
+std::string
+TemplateSpecializationType::PrintTemplateArgumentList(
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy,
+ bool SkipBrackets) {
+ std::string SpecString;
+ if (!SkipBrackets)
+ SpecString += '<';
+
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (SpecString.size() > !SkipBrackets)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ if (Args[Arg].getKind() == TemplateArgument::Pack) {
+ ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
+ Args[Arg].pack_size(),
+ Policy, true);
+ } else {
+ llvm::raw_string_ostream ArgOut(ArgString);
+ Args[Arg].print(Policy, ArgOut);
+ }
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ if (!SkipBrackets)
+ SpecString += '>';
+
+ return SpecString;
+}
+
+// Sadly, repeat all that with TemplateArgLoc.
+std::string TemplateSpecializationType::
+PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ const PrintingPolicy &Policy) {
+ std::string SpecString;
+ SpecString += '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (SpecString.size() > 1)
+ SpecString += ", ";
+
+ // Print the argument into a string.
+ std::string ArgString;
+ if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
+ ArgString = PrintTemplateArgumentList(
+ Args[Arg].getArgument().pack_begin(),
+ Args[Arg].getArgument().pack_size(),
+ Policy, true);
+ } else {
+ llvm::raw_string_ostream ArgOut(ArgString);
+ Args[Arg].getArgument().print(Policy, ArgOut);
+ }
+
+ // If this is the first argument and its string representation
+ // begins with the global scope specifier ('::foo'), add a space
+ // to avoid printing the diagraph '<:'.
+ if (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ SpecString += ' ';
+
+ SpecString += ArgString;
+ }
+
+ // If the last character of our string is '>', add another space to
+ // keep the two '>''s separate tokens. We don't *have* to do this in
+ // C++0x, but it's still good hygiene.
+ if (SpecString[SpecString.size() - 1] == '>')
+ SpecString += ' ';
+
+ SpecString += '>';
+
+ return SpecString;
+}
+
+void QualType::dump(const char *msg) const {
+ std::string R = "identifier";
+ LangOptions LO;
+ getAsStringInternal(R, PrintingPolicy(LO));
+ if (msg)
+ llvm::errs() << msg << ": ";
+ llvm::errs() << R << "\n";
+}
+void QualType::dump() const {
+ dump("");
+}
+
+void Type::dump() const {
+ QualType(this, 0).dump();
+}
+
+std::string Qualifiers::getAsString() const {
+ LangOptions LO;
+ return getAsString(PrintingPolicy(LO));
+}
+
+// Appends qualifiers to the given string, separated by spaces. Will
+// prefix a space if the string is non-empty. Will not append a final
+// space.
+void Qualifiers::getAsStringInternal(std::string &S,
+ const PrintingPolicy&) const {
+ AppendTypeQualList(S, getCVRQualifiers());
+ if (unsigned AddressSpace = getAddressSpace()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((address_space(";
+ S += llvm::utostr_32(AddressSpace);
+ S += ")))";
+ }
+ if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((objc_gc(";
+ if (GCAttrType == Qualifiers::Weak)
+ S += "weak";
+ else
+ S += "strong";
+ S += ")))";
+ }
+}
+
+std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
+ std::string buffer;
+ LangOptions options;
+ getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
+ return buffer;
+}
+
+void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
+ std::string &buffer,
+ const PrintingPolicy &policy) {
+ TypePrinter(policy).print(ty, qs, buffer);
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
new file mode 100644
index 0000000..5233d3b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
@@ -0,0 +1,377 @@
+//== AnalysisContext.cpp - Analysis context for Path Sens analysis -*- 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 AnalysisContext, a class that manages the analysis context
+// data for path sensitive analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+void AnalysisContextManager::clear() {
+ for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
+ delete I->second;
+ Contexts.clear();
+}
+
+Stmt *AnalysisContext::getBody() {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getBody();
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getBody();
+ else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ return BD->getBody();
+ else if (const FunctionTemplateDecl *FunTmpl
+ = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ return FunTmpl->getTemplatedDecl()->getBody();
+
+ llvm_unreachable("unknown code decl");
+}
+
+const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getSelfDecl();
+
+ return NULL;
+}
+
+CFG *AnalysisContext::getCFG() {
+ if (UseUnoptimizedCFG)
+ return getUnoptimizedCFG();
+
+ if (!builtCFG) {
+ CFG::BuildOptions B;
+ B.AddEHEdges = AddEHEdges;
+ B.AddImplicitDtors = AddImplicitDtors;
+ B.AddInitializers = AddInitializers;
+ cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), B);
+ // Even when the cfg is not successfully built, we don't
+ // want to try building it again.
+ builtCFG = true;
+ }
+ return cfg;
+}
+
+CFG *AnalysisContext::getUnoptimizedCFG() {
+ if (!builtCompleteCFG) {
+ CFG::BuildOptions B;
+ B.PruneTriviallyFalseEdges = false;
+ B.AddEHEdges = AddEHEdges;
+ B.AddImplicitDtors = AddImplicitDtors;
+ B.AddInitializers = AddInitializers;
+ completeCFG = CFG::buildCFG(D, getBody(), &D->getASTContext(), B);
+ // Even when the cfg is not successfully built, we don't
+ // want to try building it again.
+ builtCompleteCFG = true;
+ }
+ return completeCFG;
+}
+
+void AnalysisContext::dumpCFG() {
+ getCFG()->dump(getASTContext().getLangOptions());
+}
+
+ParentMap &AnalysisContext::getParentMap() {
+ if (!PM)
+ PM = new ParentMap(getBody());
+ return *PM;
+}
+
+PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() {
+ if (!PCA)
+ PCA = new PseudoConstantAnalysis(getBody());
+ return PCA;
+}
+
+LiveVariables *AnalysisContext::getLiveVariables() {
+ if (!liveness) {
+ CFG *c = getCFG();
+ if (!c)
+ return 0;
+
+ liveness = new LiveVariables(*this);
+ liveness->runOnCFG(*c);
+ liveness->runOnAllBlocks(*c, 0, true);
+ }
+
+ return liveness;
+}
+
+LiveVariables *AnalysisContext::getRelaxedLiveVariables() {
+ if (!relaxedLiveness) {
+ CFG *c = getCFG();
+ if (!c)
+ return 0;
+
+ relaxedLiveness = new LiveVariables(*this, false);
+ relaxedLiveness->runOnCFG(*c);
+ relaxedLiveness->runOnAllBlocks(*c, 0, true);
+ }
+
+ return relaxedLiveness;
+}
+
+AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
+ idx::TranslationUnit *TU) {
+ AnalysisContext *&AC = Contexts[D];
+ if (!AC)
+ AC = new AnalysisContext(D, TU, UseUnoptimizedCFG, false,
+ AddImplicitDtors, AddInitializers);
+
+ return AC;
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSet profiling.
+//===----------------------------------------------------------------------===//
+
+void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
+ ContextKind ck,
+ AnalysisContext *ctx,
+ const LocationContext *parent,
+ const void* data) {
+ ID.AddInteger(ck);
+ ID.AddPointer(ctx);
+ ID.AddPointer(parent);
+ ID.AddPointer(data);
+}
+
+void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
+}
+
+void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAnalysisContext(), getParent(), Enter);
+}
+
+void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getAnalysisContext(), getParent(), BD);
+}
+
+//===----------------------------------------------------------------------===//
+// LocationContext creation.
+//===----------------------------------------------------------------------===//
+
+template <typename LOC, typename DATA>
+const LOC*
+LocationContextManager::getLocationContext(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const DATA *d) {
+ llvm::FoldingSetNodeID ID;
+ LOC::Profile(ID, ctx, parent, d);
+ void *InsertPos;
+
+ LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
+
+ if (!L) {
+ L = new LOC(ctx, parent, d);
+ Contexts.InsertNode(L, InsertPos);
+ }
+ return L;
+}
+
+const StackFrameContext*
+LocationContextManager::getStackFrame(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s,
+ const CFGBlock *blk, unsigned idx) {
+ llvm::FoldingSetNodeID ID;
+ StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
+ void *InsertPos;
+ StackFrameContext *L =
+ cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
+ if (!L) {
+ L = new StackFrameContext(ctx, parent, s, blk, idx);
+ Contexts.InsertNode(L, InsertPos);
+ }
+ return L;
+}
+
+const ScopeContext *
+LocationContextManager::getScope(AnalysisContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s) {
+ return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
+}
+
+//===----------------------------------------------------------------------===//
+// LocationContext methods.
+//===----------------------------------------------------------------------===//
+
+const StackFrameContext *LocationContext::getCurrentStackFrame() const {
+ const LocationContext *LC = this;
+ while (LC) {
+ if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
+ return SFC;
+ LC = LC->getParent();
+ }
+ return NULL;
+}
+
+const StackFrameContext *
+LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
+ const LocationContext *LC = this;
+ while (LC) {
+ if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
+ if (cast<DeclContext>(SFC->getDecl()) == DC)
+ return SFC;
+ }
+ LC = LC->getParent();
+ }
+ return NULL;
+}
+
+bool LocationContext::isParentOf(const LocationContext *LC) const {
+ do {
+ const LocationContext *Parent = LC->getParent();
+ if (Parent == this)
+ return true;
+ else
+ LC = Parent;
+ } while (LC);
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Lazily generated map to query the external variables referenced by a Block.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
+ BumpVector<const VarDecl*> &BEVals;
+ BumpVectorContext &BC;
+ llvm::DenseMap<const VarDecl*, unsigned> Visited;
+ llvm::SmallSet<const DeclContext*, 4> IgnoredContexts;
+public:
+ FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
+ BumpVectorContext &bc)
+ : BEVals(bevals), BC(bc) {}
+
+ bool IsTrackedDecl(const VarDecl *VD) {
+ const DeclContext *DC = VD->getDeclContext();
+ return IgnoredContexts.count(DC) == 0;
+ }
+
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_range I = S->children(); I; ++I)
+ if (Stmt *child = *I)
+ Visit(child);
+ }
+
+ void VisitDeclRefExpr(const DeclRefExpr *DR) {
+ // Non-local variables are also directly modified.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (!VD->hasLocalStorage()) {
+ unsigned &flag = Visited[VD];
+ if (!flag) {
+ flag = 1;
+ BEVals.push_back(VD, BC);
+ }
+ }
+ }
+
+ void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ unsigned &flag = Visited[VD];
+ if (!flag) {
+ flag = 1;
+ if (IsTrackedDecl(VD))
+ BEVals.push_back(VD, BC);
+ }
+ }
+ }
+
+ void VisitBlockExpr(BlockExpr *BR) {
+ // Blocks containing blocks can transitively capture more variables.
+ IgnoredContexts.insert(BR->getBlockDecl());
+ Visit(BR->getBlockDecl()->getBody());
+ }
+};
+} // end anonymous namespace
+
+typedef BumpVector<const VarDecl*> DeclVec;
+
+static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
+ void *&Vec,
+ llvm::BumpPtrAllocator &A) {
+ if (Vec)
+ return (DeclVec*) Vec;
+
+ BumpVectorContext BC(A);
+ DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
+ new (BV) DeclVec(BC, 10);
+
+ // Find the referenced variables.
+ FindBlockDeclRefExprsVals F(*BV, BC);
+ F.Visit(BD->getBody());
+
+ Vec = BV;
+ return BV;
+}
+
+std::pair<AnalysisContext::referenced_decls_iterator,
+ AnalysisContext::referenced_decls_iterator>
+AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
+ if (!ReferencedBlockVars)
+ ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
+
+ DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
+ return std::make_pair(V->begin(), V->end());
+}
+
+//===----------------------------------------------------------------------===//
+// Cleanup.
+//===----------------------------------------------------------------------===//
+
+AnalysisContext::~AnalysisContext() {
+ delete cfg;
+ delete completeCFG;
+ delete liveness;
+ delete relaxedLiveness;
+ delete PM;
+ delete PCA;
+ delete ReferencedBlockVars;
+}
+
+AnalysisContextManager::~AnalysisContextManager() {
+ for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
+ delete I->second;
+}
+
+LocationContext::~LocationContext() {}
+
+LocationContextManager::~LocationContextManager() {
+ clear();
+}
+
+void LocationContextManager::clear() {
+ for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
+ E = Contexts.end(); I != E; ) {
+ LocationContext *LC = &*I;
+ ++I;
+ delete LC;
+ }
+
+ Contexts.clear();
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
new file mode 100644
index 0000000..a0ec5fe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -0,0 +1,3407 @@
+//===--- CFG.cpp - Classes for representing and building CFGs----*- 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 CFG and CFGBuilder classes for representing and
+// building Control-Flow Graphs (CFGs) from ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/Support/GraphWriter.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Format.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
+
+using namespace clang;
+
+namespace {
+
+static SourceLocation GetEndLoc(Decl* D) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ if (Expr* Ex = VD->getInit())
+ return Ex->getSourceRange().getEnd();
+ return D->getLocation();
+}
+
+/// The CFG builder uses a recursive algorithm to build the CFG. When
+/// we process an expression, sometimes we know that we must add the
+/// subexpressions as block-level expressions. For example:
+///
+/// exp1 || exp2
+///
+/// When processing the '||' expression, we know that exp1 and exp2
+/// need to be added as block-level expressions, even though they
+/// might not normally need to be. AddStmtChoice records this
+/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then
+/// the builder has an option not to add a subexpression as a
+/// block-level expression.
+///
+class AddStmtChoice {
+public:
+ enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
+
+ AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
+
+ bool alwaysAdd() const { return kind & AlwaysAdd; }
+
+ /// Return a copy of this object, except with the 'always-add' bit
+ /// set as specified.
+ AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {
+ return AddStmtChoice(alwaysAdd ? Kind(kind | AlwaysAdd) :
+ Kind(kind & ~AlwaysAdd));
+ }
+
+private:
+ Kind kind;
+};
+
+/// LocalScope - Node in tree of local scopes created for C++ implicit
+/// destructor calls generation. It contains list of automatic variables
+/// declared in the scope and link to position in previous scope this scope
+/// began in.
+///
+/// The process of creating local scopes is as follows:
+/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),
+/// - Before processing statements in scope (e.g. CompoundStmt) create
+/// LocalScope object using CFGBuilder::ScopePos as link to previous scope
+/// and set CFGBuilder::ScopePos to the end of new scope,
+/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points
+/// at this VarDecl,
+/// - For every normal (without jump) end of scope add to CFGBlock destructors
+/// for objects in the current scope,
+/// - For every jump add to CFGBlock destructors for objects
+/// between CFGBuilder::ScopePos and local scope position saved for jump
+/// target. Thanks to C++ restrictions on goto jumps we can be sure that
+/// jump target position will be on the path to root from CFGBuilder::ScopePos
+/// (adding any variable that doesn't need constructor to be called to
+/// LocalScope can break this assumption),
+///
+class LocalScope {
+public:
+ typedef BumpVector<VarDecl*> AutomaticVarsTy;
+
+ /// const_iterator - Iterates local scope backwards and jumps to previous
+ /// scope on reaching the beginning of currently iterated scope.
+ class const_iterator {
+ const LocalScope* Scope;
+
+ /// VarIter is guaranteed to be greater then 0 for every valid iterator.
+ /// Invalid iterator (with null Scope) has VarIter equal to 0.
+ unsigned VarIter;
+
+ public:
+ /// Create invalid iterator. Dereferencing invalid iterator is not allowed.
+ /// Incrementing invalid iterator is allowed and will result in invalid
+ /// iterator.
+ const_iterator()
+ : Scope(NULL), VarIter(0) {}
+
+ /// Create valid iterator. In case when S.Prev is an invalid iterator and
+ /// I is equal to 0, this will create invalid iterator.
+ const_iterator(const LocalScope& S, unsigned I)
+ : Scope(&S), VarIter(I) {
+ // Iterator to "end" of scope is not allowed. Handle it by going up
+ // in scopes tree possibly up to invalid iterator in the root.
+ if (VarIter == 0 && Scope)
+ *this = Scope->Prev;
+ }
+
+ VarDecl* const* operator->() const {
+ assert (Scope && "Dereferencing invalid iterator is not allowed");
+ assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+ return &Scope->Vars[VarIter - 1];
+ }
+ VarDecl* operator*() const {
+ return *this->operator->();
+ }
+
+ const_iterator& operator++() {
+ if (!Scope)
+ return *this;
+
+ assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+ --VarIter;
+ if (VarIter == 0)
+ *this = Scope->Prev;
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator P = *this;
+ ++*this;
+ return P;
+ }
+
+ bool operator==(const const_iterator& rhs) const {
+ return Scope == rhs.Scope && VarIter == rhs.VarIter;
+ }
+ bool operator!=(const const_iterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ operator bool() const {
+ return *this != const_iterator();
+ }
+
+ int distance(const_iterator L);
+ };
+
+ friend class const_iterator;
+
+private:
+ BumpVectorContext ctx;
+
+ /// Automatic variables in order of declaration.
+ AutomaticVarsTy Vars;
+ /// Iterator to variable in previous scope that was declared just before
+ /// begin of this scope.
+ const_iterator Prev;
+
+public:
+ /// Constructs empty scope linked to previous scope in specified place.
+ LocalScope(BumpVectorContext &ctx, const_iterator P)
+ : ctx(ctx), Vars(ctx, 4), Prev(P) {}
+
+ /// Begin of scope in direction of CFG building (backwards).
+ const_iterator begin() const { return const_iterator(*this, Vars.size()); }
+
+ void addVar(VarDecl* VD) {
+ Vars.push_back(VD, ctx);
+ }
+};
+
+/// distance - Calculates distance from this to L. L must be reachable from this
+/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.
+/// number of scopes between this and L.
+int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
+ int D = 0;
+ const_iterator F = *this;
+ while (F.Scope != L.Scope) {
+ assert (F != const_iterator()
+ && "L iterator is not reachable from F iterator.");
+ D += F.VarIter;
+ F = F.Scope->Prev;
+ }
+ D += F.VarIter - L.VarIter;
+ return D;
+}
+
+/// BlockScopePosPair - Structure for specifying position in CFG during its
+/// build process. It consists of CFGBlock that specifies position in CFG graph
+/// and LocalScope::const_iterator that specifies position in LocalScope graph.
+struct BlockScopePosPair {
+ BlockScopePosPair() : block(0) {}
+ BlockScopePosPair(CFGBlock* b, LocalScope::const_iterator scopePos)
+ : block(b), scopePosition(scopePos) {}
+
+ CFGBlock *block;
+ LocalScope::const_iterator scopePosition;
+};
+
+/// CFGBuilder - This class implements CFG construction from an AST.
+/// The builder is stateful: an instance of the builder should be used to only
+/// construct a single CFG.
+///
+/// Example usage:
+///
+/// CFGBuilder builder;
+/// CFG* cfg = builder.BuildAST(stmt1);
+///
+/// CFG construction is done via a recursive walk of an AST. We actually parse
+/// the AST in reverse order so that the successor of a basic block is
+/// constructed prior to its predecessor. This allows us to nicely capture
+/// implicit fall-throughs without extra basic blocks.
+///
+class CFGBuilder {
+ typedef BlockScopePosPair JumpTarget;
+ typedef BlockScopePosPair JumpSource;
+
+ ASTContext *Context;
+ llvm::OwningPtr<CFG> cfg;
+
+ CFGBlock* Block;
+ CFGBlock* Succ;
+ JumpTarget ContinueJumpTarget;
+ JumpTarget BreakJumpTarget;
+ CFGBlock* SwitchTerminatedBlock;
+ CFGBlock* DefaultCaseBlock;
+ CFGBlock* TryTerminatedBlock;
+
+ // Current position in local scope.
+ LocalScope::const_iterator ScopePos;
+
+ // LabelMap records the mapping from Label expressions to their jump targets.
+ typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
+ LabelMapTy LabelMap;
+
+ // A list of blocks that end with a "goto" that must be backpatched to their
+ // resolved targets upon completion of CFG construction.
+ typedef std::vector<JumpSource> BackpatchBlocksTy;
+ BackpatchBlocksTy BackpatchBlocks;
+
+ // A list of labels whose address has been taken (for indirect gotos).
+ typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
+ LabelSetTy AddressTakenLabels;
+
+ bool badCFG;
+ CFG::BuildOptions BuildOpts;
+
+public:
+ explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
+ Block(NULL), Succ(NULL),
+ SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
+ TryTerminatedBlock(NULL), badCFG(false) {}
+
+ // buildCFG - Used by external clients to construct the CFG.
+ CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C,
+ CFG::BuildOptions BO);
+
+private:
+ // Visitors to walk an AST and construct the CFG.
+ CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
+ CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
+ CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc);
+ CFGBlock *VisitBreakStmt(BreakStmt *B);
+ CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
+ CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
+ AddStmtChoice asc);
+ CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
+ CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
+ CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
+ AddStmtChoice asc);
+ CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
+ CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
+ AddStmtChoice asc);
+ CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
+ AddStmtChoice asc);
+ CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc);
+ CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
+ CFGBlock *VisitCaseStmt(CaseStmt *C);
+ CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
+ CFGBlock *VisitCompoundStmt(CompoundStmt *C);
+ CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,
+ AddStmtChoice asc);
+ CFGBlock *VisitContinueStmt(ContinueStmt *C);
+ CFGBlock *VisitDeclStmt(DeclStmt *DS);
+ CFGBlock *VisitDeclSubExpr(DeclStmt* DS);
+ CFGBlock *VisitDefaultStmt(DefaultStmt *D);
+ CFGBlock *VisitDoStmt(DoStmt *D);
+ CFGBlock *VisitForStmt(ForStmt *F);
+ CFGBlock *VisitGotoStmt(GotoStmt* G);
+ CFGBlock *VisitIfStmt(IfStmt *I);
+ CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
+ CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
+ CFGBlock *VisitLabelStmt(LabelStmt *L);
+ CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
+ CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
+ CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
+ CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
+ CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
+ CFGBlock *VisitReturnStmt(ReturnStmt* R);
+ CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc);
+ CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
+ CFGBlock *VisitSwitchStmt(SwitchStmt *S);
+ CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
+ CFGBlock *VisitWhileStmt(WhileStmt *W);
+
+ CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
+ CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
+ CFGBlock *VisitChildren(Stmt* S);
+
+ // Visitors to walk an AST and generate destructors of temporaries in
+ // full expression.
+ CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false);
+ CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E);
+ CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E);
+ CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E,
+ bool BindToTemporary);
+ CFGBlock *
+ VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E,
+ bool BindToTemporary);
+
+ // NYS == Not Yet Supported
+ CFGBlock* NYS() {
+ badCFG = true;
+ return Block;
+ }
+
+ void autoCreateBlock() { if (!Block) Block = createBlock(); }
+ CFGBlock *createBlock(bool add_successor = true);
+
+ CFGBlock *addStmt(Stmt *S) {
+ return Visit(S, AddStmtChoice::AlwaysAdd);
+ }
+ CFGBlock *addInitializer(CXXCtorInitializer *I);
+ void addAutomaticObjDtors(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt* S);
+ void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
+
+ // Local scopes creation.
+ LocalScope* createOrReuseLocalScope(LocalScope* Scope);
+
+ void addLocalScopeForStmt(Stmt* S);
+ LocalScope* addLocalScopeForDeclStmt(DeclStmt* DS, LocalScope* Scope = NULL);
+ LocalScope* addLocalScopeForVarDecl(VarDecl* VD, LocalScope* Scope = NULL);
+
+ void addLocalScopeAndDtors(Stmt* S);
+
+ // Interface to CFGBlock - adding CFGElements.
+ void appendStmt(CFGBlock *B, Stmt *S,
+ AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
+ B->appendStmt(S, cfg->getBumpVectorContext());
+ }
+ void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
+ B->appendInitializer(I, cfg->getBumpVectorContext());
+ }
+ void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
+ B->appendBaseDtor(BS, cfg->getBumpVectorContext());
+ }
+ void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
+ B->appendMemberDtor(FD, cfg->getBumpVectorContext());
+ }
+ void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
+ B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
+ }
+
+ void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I,
+ LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S);
+ void appendAutomaticObjDtors(CFGBlock* Blk, LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt* S);
+ void prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk,
+ LocalScope::const_iterator B, LocalScope::const_iterator E);
+
+ void addSuccessor(CFGBlock *B, CFGBlock *S) {
+ B->addSuccessor(S, cfg->getBumpVectorContext());
+ }
+
+ /// TryResult - a class representing a variant over the values
+ /// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool,
+ /// and is used by the CFGBuilder to decide if a branch condition
+ /// can be decided up front during CFG construction.
+ class TryResult {
+ int X;
+ public:
+ TryResult(bool b) : X(b ? 1 : 0) {}
+ TryResult() : X(-1) {}
+
+ bool isTrue() const { return X == 1; }
+ bool isFalse() const { return X == 0; }
+ bool isKnown() const { return X >= 0; }
+ void negate() {
+ assert(isKnown());
+ X ^= 0x1;
+ }
+ };
+
+ /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
+ /// if we can evaluate to a known value, otherwise return -1.
+ TryResult tryEvaluateBool(Expr *S) {
+ if (!BuildOpts.PruneTriviallyFalseEdges)
+ return TryResult();
+
+ Expr::EvalResult Result;
+ if (!S->isTypeDependent() && !S->isValueDependent() &&
+ S->Evaluate(Result, *Context) && Result.Val.isInt())
+ return Result.Val.getInt().getBoolValue();
+
+ return TryResult();
+ }
+};
+
+// FIXME: Add support for dependent-sized array types in C++?
+// Does it even make sense to build a CFG for an uninstantiated template?
+static const VariableArrayType *FindVA(const Type *t) {
+ while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
+ if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
+ if (vat->getSizeExpr())
+ return vat;
+
+ t = vt->getElementType().getTypePtr();
+ }
+
+ return 0;
+}
+
+/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an
+/// arbitrary statement. Examples include a single expression or a function
+/// body (compound statement). The ownership of the returned CFG is
+/// transferred to the caller. If CFG construction fails, this method returns
+/// NULL.
+CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
+ CFG::BuildOptions BO) {
+
+ Context = C;
+ assert(cfg.get());
+ if (!Statement)
+ return NULL;
+
+ BuildOpts = BO;
+
+ // Create an empty block that will serve as the exit block for the CFG. Since
+ // this is the first block added to the CFG, it will be implicitly registered
+ // as the exit block.
+ Succ = createBlock();
+ assert(Succ == &cfg->getExit());
+ Block = NULL; // the EXIT block is empty. Create all other blocks lazily.
+
+ if (BuildOpts.AddImplicitDtors)
+ if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
+ addImplicitDtorsForDestructor(DD);
+
+ // Visit the statements and create the CFG.
+ CFGBlock *B = addStmt(Statement);
+
+ if (badCFG)
+ return NULL;
+
+ // For C++ constructor add initializers to CFG.
+ if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
+ for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(),
+ E = CD->init_rend(); I != E; ++I) {
+ B = addInitializer(*I);
+ if (badCFG)
+ return NULL;
+ }
+ }
+
+ if (B)
+ Succ = B;
+
+ // Backpatch the gotos whose label -> block mappings we didn't know when we
+ // encountered them.
+ for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
+ E = BackpatchBlocks.end(); I != E; ++I ) {
+
+ CFGBlock* B = I->block;
+ GotoStmt* G = cast<GotoStmt>(B->getTerminator());
+ LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
+
+ // If there is no target for the goto, then we are looking at an
+ // incomplete AST. Handle this by not registering a successor.
+ if (LI == LabelMap.end()) continue;
+
+ JumpTarget JT = LI->second;
+ prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
+ JT.scopePosition);
+ addSuccessor(B, JT.block);
+ }
+
+ // Add successors to the Indirect Goto Dispatch block (if we have one).
+ if (CFGBlock* B = cfg->getIndirectGotoBlock())
+ for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
+ E = AddressTakenLabels.end(); I != E; ++I ) {
+
+ // Lookup the target block.
+ LabelMapTy::iterator LI = LabelMap.find(*I);
+
+ // If there is no target block that contains label, then we are looking
+ // at an incomplete AST. Handle this by not registering a successor.
+ if (LI == LabelMap.end()) continue;
+
+ addSuccessor(B, LI->second.block);
+ }
+
+ // Create an empty entry block that has no predecessors.
+ cfg->setEntry(createBlock());
+
+ return cfg.take();
+}
+
+/// createBlock - Used to lazily create blocks that are connected
+/// to the current (global) succcessor.
+CFGBlock* CFGBuilder::createBlock(bool add_successor) {
+ CFGBlock* B = cfg->createBlock();
+ if (add_successor && Succ)
+ addSuccessor(B, Succ);
+ return B;
+}
+
+/// addInitializer - Add C++ base or member initializer element to CFG.
+CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
+ if (!BuildOpts.AddInitializers)
+ return Block;
+
+ bool IsReference = false;
+ bool HasTemporaries = false;
+
+ // Destructors of temporaries in initialization expression should be called
+ // after initialization finishes.
+ Expr *Init = I->getInit();
+ if (Init) {
+ if (FieldDecl *FD = I->getAnyMember())
+ IsReference = FD->getType()->isReferenceType();
+ HasTemporaries = isa<ExprWithCleanups>(Init);
+
+ if (BuildOpts.AddImplicitDtors && HasTemporaries) {
+ // Generate destructors for temporaries in initialization expression.
+ VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
+ IsReference);
+ }
+ }
+
+ autoCreateBlock();
+ appendInitializer(Block, I);
+
+ if (Init) {
+ if (HasTemporaries) {
+ // For expression with temporaries go directly to subexpression to omit
+ // generating destructors for the second time.
+ return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
+ }
+ return Visit(Init);
+ }
+
+ return Block;
+}
+
+/// addAutomaticObjDtors - Add to current block automatic objects destructors
+/// for objects in range of local scope positions. Use S as trigger statement
+/// for destructors.
+void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
+ LocalScope::const_iterator E, Stmt* S) {
+ if (!BuildOpts.AddImplicitDtors)
+ return;
+
+ if (B == E)
+ return;
+
+ autoCreateBlock();
+ appendAutomaticObjDtors(Block, B, E, S);
+}
+
+/// addImplicitDtorsForDestructor - Add implicit destructors generated for
+/// base and member objects in destructor.
+void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
+ assert (BuildOpts.AddImplicitDtors
+ && "Can be called only when dtors should be added");
+ const CXXRecordDecl *RD = DD->getParent();
+
+ // At the end destroy virtual base objects.
+ for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(),
+ VE = RD->vbases_end(); VI != VE; ++VI) {
+ const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl();
+ if (!CD->hasTrivialDestructor()) {
+ autoCreateBlock();
+ appendBaseDtor(Block, VI);
+ }
+ }
+
+ // Before virtual bases destroy direct base objects.
+ for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
+ BE = RD->bases_end(); BI != BE; ++BI) {
+ if (!BI->isVirtual()) {
+ const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl();
+ if (!CD->hasTrivialDestructor()) {
+ autoCreateBlock();
+ appendBaseDtor(Block, BI);
+ }
+ }
+ }
+
+ // First destroy member objects.
+ for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
+ FE = RD->field_end(); FI != FE; ++FI) {
+ // Check for constant size array. Set type to array element type.
+ QualType QT = FI->getType();
+ if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
+ if (AT->getSize() == 0)
+ continue;
+ QT = AT->getElementType();
+ }
+
+ if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
+ if (!CD->hasTrivialDestructor()) {
+ autoCreateBlock();
+ appendMemberDtor(Block, *FI);
+ }
+ }
+}
+
+/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
+/// way return valid LocalScope object.
+LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
+ if (!Scope) {
+ llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
+ Scope = alloc.Allocate<LocalScope>();
+ BumpVectorContext ctx(alloc);
+ new (Scope) LocalScope(ctx, ScopePos);
+ }
+ return Scope;
+}
+
+/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
+/// that should create implicit scope (e.g. if/else substatements).
+void CFGBuilder::addLocalScopeForStmt(Stmt* S) {
+ if (!BuildOpts.AddImplicitDtors)
+ return;
+
+ LocalScope *Scope = 0;
+
+ // For compound statement we will be creating explicit scope.
+ if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
+ for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end()
+ ; BI != BE; ++BI) {
+ Stmt *SI = *BI;
+ if (LabelStmt *LS = dyn_cast<LabelStmt>(SI))
+ SI = LS->getSubStmt();
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
+ Scope = addLocalScopeForDeclStmt(DS, Scope);
+ }
+ return;
+ }
+
+ // For any other statement scope will be implicit and as such will be
+ // interesting only for DeclStmt.
+ if (LabelStmt *LS = dyn_cast<LabelStmt>(S))
+ S = LS->getSubStmt();
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(S))
+ addLocalScopeForDeclStmt(DS);
+}
+
+/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will
+/// reuse Scope if not NULL.
+LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt* DS,
+ LocalScope* Scope) {
+ if (!BuildOpts.AddImplicitDtors)
+ return Scope;
+
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end()
+ ; DI != DE; ++DI) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(*DI))
+ Scope = addLocalScopeForVarDecl(VD, Scope);
+ }
+ return Scope;
+}
+
+/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will
+/// create add scope for automatic objects and temporary objects bound to
+/// const reference. Will reuse Scope if not NULL.
+LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl* VD,
+ LocalScope* Scope) {
+ if (!BuildOpts.AddImplicitDtors)
+ return Scope;
+
+ // Check if variable is local.
+ switch (VD->getStorageClass()) {
+ case SC_None:
+ case SC_Auto:
+ case SC_Register:
+ break;
+ default: return Scope;
+ }
+
+ // Check for const references bound to temporary. Set type to pointee.
+ QualType QT = VD->getType();
+ if (const ReferenceType* RT = QT.getTypePtr()->getAs<ReferenceType>()) {
+ QT = RT->getPointeeType();
+ if (!QT.isConstQualified())
+ return Scope;
+ if (!VD->getInit() || !VD->getInit()->Classify(*Context).isRValue())
+ return Scope;
+ }
+
+ // Check for constant size array. Set type to array element type.
+ if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
+ if (AT->getSize() == 0)
+ return Scope;
+ QT = AT->getElementType();
+ }
+
+ // Check if type is a C++ class with non-trivial destructor.
+ if (const CXXRecordDecl* CD = QT->getAsCXXRecordDecl())
+ if (!CD->hasTrivialDestructor()) {
+ // Add the variable to scope
+ Scope = createOrReuseLocalScope(Scope);
+ Scope->addVar(VD);
+ ScopePos = Scope->begin();
+ }
+ return Scope;
+}
+
+/// addLocalScopeAndDtors - For given statement add local scope for it and
+/// add destructors that will cleanup the scope. Will reuse Scope if not NULL.
+void CFGBuilder::addLocalScopeAndDtors(Stmt* S) {
+ if (!BuildOpts.AddImplicitDtors)
+ return;
+
+ LocalScope::const_iterator scopeBeginPos = ScopePos;
+ addLocalScopeForStmt(S);
+ addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
+}
+
+/// insertAutomaticObjDtors - Insert destructor CFGElements for variables with
+/// automatic storage duration to CFGBlock's elements vector. Insertion will be
+/// performed in place specified with iterator.
+void CFGBuilder::insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I,
+ LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) {
+ BumpVectorContext& C = cfg->getBumpVectorContext();
+ I = Blk->beginAutomaticObjDtorsInsert(I, B.distance(E), C);
+ while (B != E)
+ I = Blk->insertAutomaticObjDtor(I, *B++, S);
+}
+
+/// appendAutomaticObjDtors - Append destructor CFGElements for variables with
+/// automatic storage duration to CFGBlock's elements vector. Elements will be
+/// appended to physical end of the vector which happens to be logical
+/// beginning.
+void CFGBuilder::appendAutomaticObjDtors(CFGBlock* Blk,
+ LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) {
+ insertAutomaticObjDtors(Blk, Blk->begin(), B, E, S);
+}
+
+/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for
+/// variables with automatic storage duration to CFGBlock's elements vector.
+/// Elements will be prepended to physical beginning of the vector which
+/// happens to be logical end. Use blocks terminator as statement that specifies
+/// destructors call site.
+void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk,
+ LocalScope::const_iterator B, LocalScope::const_iterator E) {
+ insertAutomaticObjDtors(Blk, Blk->end(), B, E, Blk->getTerminator());
+}
+
+/// Visit - Walk the subtree of a statement and add extra
+/// blocks for ternary operators, &&, and ||. We also process "," and
+/// DeclStmts (which may contain nested control-flow).
+CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
+tryAgain:
+ if (!S) {
+ badCFG = true;
+ return 0;
+ }
+ switch (S->getStmtClass()) {
+ default:
+ return VisitStmt(S, asc);
+
+ case Stmt::AddrLabelExprClass:
+ return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
+
+ case Stmt::BinaryConditionalOperatorClass:
+ return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
+
+ case Stmt::BinaryOperatorClass:
+ return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
+
+ case Stmt::BlockExprClass:
+ return VisitBlockExpr(cast<BlockExpr>(S), asc);
+
+ case Stmt::BreakStmtClass:
+ return VisitBreakStmt(cast<BreakStmt>(S));
+
+ case Stmt::CallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ return VisitCallExpr(cast<CallExpr>(S), asc);
+
+ case Stmt::CaseStmtClass:
+ return VisitCaseStmt(cast<CaseStmt>(S));
+
+ case Stmt::ChooseExprClass:
+ return VisitChooseExpr(cast<ChooseExpr>(S), asc);
+
+ case Stmt::CompoundStmtClass:
+ return VisitCompoundStmt(cast<CompoundStmt>(S));
+
+ case Stmt::ConditionalOperatorClass:
+ return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
+
+ case Stmt::ContinueStmtClass:
+ return VisitContinueStmt(cast<ContinueStmt>(S));
+
+ case Stmt::CXXCatchStmtClass:
+ return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
+
+ case Stmt::ExprWithCleanupsClass:
+ return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
+
+ case Stmt::CXXBindTemporaryExprClass:
+ return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
+
+ case Stmt::CXXConstructExprClass:
+ return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
+
+ case Stmt::CXXFunctionalCastExprClass:
+ return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
+
+ case Stmt::CXXTemporaryObjectExprClass:
+ return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
+
+ case Stmt::CXXMemberCallExprClass:
+ return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc);
+
+ case Stmt::CXXThrowExprClass:
+ return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
+
+ case Stmt::CXXTryStmtClass:
+ return VisitCXXTryStmt(cast<CXXTryStmt>(S));
+
+ case Stmt::DeclStmtClass:
+ return VisitDeclStmt(cast<DeclStmt>(S));
+
+ case Stmt::DefaultStmtClass:
+ return VisitDefaultStmt(cast<DefaultStmt>(S));
+
+ case Stmt::DoStmtClass:
+ return VisitDoStmt(cast<DoStmt>(S));
+
+ case Stmt::ForStmtClass:
+ return VisitForStmt(cast<ForStmt>(S));
+
+ case Stmt::GotoStmtClass:
+ return VisitGotoStmt(cast<GotoStmt>(S));
+
+ case Stmt::IfStmtClass:
+ return VisitIfStmt(cast<IfStmt>(S));
+
+ case Stmt::ImplicitCastExprClass:
+ return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
+
+ case Stmt::IndirectGotoStmtClass:
+ return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
+
+ case Stmt::LabelStmtClass:
+ return VisitLabelStmt(cast<LabelStmt>(S));
+
+ case Stmt::MemberExprClass:
+ return VisitMemberExpr(cast<MemberExpr>(S), asc);
+
+ case Stmt::ObjCAtCatchStmtClass:
+ return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
+
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
+
+ case Stmt::ObjCAtThrowStmtClass:
+ return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
+
+ case Stmt::ObjCAtTryStmtClass:
+ return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
+
+ case Stmt::ObjCForCollectionStmtClass:
+ return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
+
+ case Stmt::ParenExprClass:
+ S = cast<ParenExpr>(S)->getSubExpr();
+ goto tryAgain;
+
+ case Stmt::NullStmtClass:
+ return Block;
+
+ case Stmt::ReturnStmtClass:
+ return VisitReturnStmt(cast<ReturnStmt>(S));
+
+ case Stmt::SizeOfAlignOfExprClass:
+ return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc);
+
+ case Stmt::StmtExprClass:
+ return VisitStmtExpr(cast<StmtExpr>(S), asc);
+
+ case Stmt::SwitchStmtClass:
+ return VisitSwitchStmt(cast<SwitchStmt>(S));
+
+ case Stmt::UnaryOperatorClass:
+ return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
+
+ case Stmt::WhileStmtClass:
+ return VisitWhileStmt(cast<WhileStmt>(S));
+ }
+}
+
+CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, S, asc);
+ }
+
+ return VisitChildren(S);
+}
+
+/// VisitChildren - Visit the children of a Stmt.
+CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
+ CFGBlock *B = Block;
+ for (Stmt::child_range I = Terminator->children(); I; ++I) {
+ if (*I) B = Visit(*I);
+ }
+ return B;
+}
+
+CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
+ AddStmtChoice asc) {
+ AddressTakenLabels.insert(A->getLabel());
+
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, A, asc);
+ }
+
+ return Block;
+}
+
+CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U,
+ AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, U, asc);
+ }
+
+ return Visit(U->getSubExpr(), AddStmtChoice());
+}
+
+CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
+ AddStmtChoice asc) {
+ if (B->isLogicalOp()) { // && or ||
+ CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
+ appendStmt(ConfluenceBlock, B, asc);
+
+ if (badCFG)
+ return 0;
+
+ // create the block evaluating the LHS
+ CFGBlock* LHSBlock = createBlock(false);
+ LHSBlock->setTerminator(B);
+
+ // create the block evaluating the RHS
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock* RHSBlock = addStmt(B->getRHS());
+
+ if (RHSBlock) {
+ if (badCFG)
+ return 0;
+ } else {
+ // Create an empty block for cases where the RHS doesn't require
+ // any explicit statements in the CFG.
+ RHSBlock = createBlock();
+ }
+
+ // See if this is a known constant.
+ TryResult KnownVal = tryEvaluateBool(B->getLHS());
+ if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr))
+ KnownVal.negate();
+
+ // Now link the LHSBlock with RHSBlock.
+ if (B->getOpcode() == BO_LOr) {
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+ } else {
+ assert(B->getOpcode() == BO_LAnd);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+ }
+
+ // Generate the blocks for evaluating the LHS.
+ Block = LHSBlock;
+ return addStmt(B->getLHS());
+ }
+
+ if (B->getOpcode() == BO_Comma) { // ,
+ autoCreateBlock();
+ appendStmt(Block, B, asc);
+ addStmt(B->getRHS());
+ return addStmt(B->getLHS());
+ }
+
+ if (B->isAssignmentOp()) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, B, asc);
+ }
+ Visit(B->getLHS());
+ return Visit(B->getRHS());
+ }
+
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, B, asc);
+ }
+
+ CFGBlock *RBlock = Visit(B->getRHS());
+ CFGBlock *LBlock = Visit(B->getLHS());
+ // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
+ // containing a DoStmt, and the LHS doesn't create a new block, then we should
+ // return RBlock. Otherwise we'll incorrectly return NULL.
+ return (LBlock ? LBlock : RBlock);
+}
+
+CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, E, asc);
+ }
+ return Block;
+}
+
+CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
+ // "break" is a control-flow statement. Thus we stop processing the current
+ // block.
+ if (badCFG)
+ return 0;
+
+ // Now create a new block that ends with the break statement.
+ Block = createBlock(false);
+ Block->setTerminator(B);
+
+ // If there is no target for the break, then we are looking at an incomplete
+ // AST. This means that the CFG cannot be constructed.
+ if (BreakJumpTarget.block) {
+ addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
+ addSuccessor(Block, BreakJumpTarget.block);
+ } else
+ badCFG = true;
+
+
+ return Block;
+}
+
+static bool CanThrow(Expr *E) {
+ QualType Ty = E->getType();
+ if (Ty->isFunctionPointerType())
+ Ty = Ty->getAs<PointerType>()->getPointeeType();
+ else if (Ty->isBlockPointerType())
+ Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+
+ const FunctionType *FT = Ty->getAs<FunctionType>();
+ if (FT) {
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
+ if (Proto->hasEmptyExceptionSpec())
+ return false;
+ }
+ return true;
+}
+
+CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
+ // If this is a call to a no-return function, this stops the block here.
+ bool NoReturn = false;
+ if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) {
+ NoReturn = true;
+ }
+
+ bool AddEHEdge = false;
+
+ // Languages without exceptions are assumed to not throw.
+ if (Context->getLangOptions().areExceptionsEnabled()) {
+ if (BuildOpts.AddEHEdges)
+ AddEHEdge = true;
+ }
+
+ if (FunctionDecl *FD = C->getDirectCallee()) {
+ if (FD->hasAttr<NoReturnAttr>())
+ NoReturn = true;
+ if (FD->hasAttr<NoThrowAttr>())
+ AddEHEdge = false;
+ }
+
+ if (!CanThrow(C->getCallee()))
+ AddEHEdge = false;
+
+ if (!NoReturn && !AddEHEdge)
+ return VisitStmt(C, asc.withAlwaysAdd(true));
+
+ if (Block) {
+ Succ = Block;
+ if (badCFG)
+ return 0;
+ }
+
+ Block = createBlock(!NoReturn);
+ appendStmt(Block, C, asc);
+
+ if (NoReturn) {
+ // Wire this to the exit block directly.
+ addSuccessor(Block, &cfg->getExit());
+ }
+ if (AddEHEdge) {
+ // Add exceptional edges.
+ if (TryTerminatedBlock)
+ addSuccessor(Block, TryTerminatedBlock);
+ else
+ addSuccessor(Block, &cfg->getExit());
+ }
+
+ return VisitChildren(C);
+}
+
+CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
+ AddStmtChoice asc) {
+ CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
+ appendStmt(ConfluenceBlock, C, asc);
+ if (badCFG)
+ return 0;
+
+ AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock* LHSBlock = Visit(C->getLHS(), alwaysAdd);
+ if (badCFG)
+ return 0;
+
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock* RHSBlock = Visit(C->getRHS(), alwaysAdd);
+ if (badCFG)
+ return 0;
+
+ Block = createBlock(false);
+ // See if this is a known constant.
+ const TryResult& KnownVal = tryEvaluateBool(C->getCond());
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+ addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+ Block->setTerminator(C);
+ return addStmt(C->getCond());
+}
+
+
+CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
+ addLocalScopeAndDtors(C);
+ CFGBlock* LastBlock = Block;
+
+ for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
+ I != E; ++I ) {
+ // If we hit a segment of code just containing ';' (NullStmts), we can
+ // get a null block back. In such cases, just use the LastBlock
+ if (CFGBlock *newBlock = addStmt(*I))
+ LastBlock = newBlock;
+
+ if (badCFG)
+ return NULL;
+ }
+
+ return LastBlock;
+}
+
+CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
+ AddStmtChoice asc) {
+ const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);
+ const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL);
+
+ // Create the confluence block that will "merge" the results of the ternary
+ // expression.
+ CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
+ appendStmt(ConfluenceBlock, C, asc);
+ if (badCFG)
+ return 0;
+
+ AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
+
+ // Create a block for the LHS expression if there is an LHS expression. A
+ // GCC extension allows LHS to be NULL, causing the condition to be the
+ // value that is returned instead.
+ // e.g: x ?: y is shorthand for: x ? x : y;
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock* LHSBlock = 0;
+ const Expr *trueExpr = C->getTrueExpr();
+ if (trueExpr != opaqueValue) {
+ LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
+ if (badCFG)
+ return 0;
+ Block = NULL;
+ }
+
+ // Create the block for the RHS expression.
+ Succ = ConfluenceBlock;
+ CFGBlock* RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
+ if (badCFG)
+ return 0;
+
+ // Create the block that will contain the condition.
+ Block = createBlock(false);
+
+ // See if this is a known constant.
+ const TryResult& KnownVal = tryEvaluateBool(C->getCond());
+ if (LHSBlock)
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+ addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+ Block->setTerminator(C);
+ Expr *condExpr = C->getCond();
+
+ CFGBlock *result = 0;
+
+ // Run the condition expression if it's not trivially expressed in
+ // terms of the opaque value (or if there is no opaque value).
+ if (condExpr != opaqueValue) result = addStmt(condExpr);
+
+ // Before that, run the common subexpression if there was one.
+ // At least one of this or the above will be run.
+ if (opaqueValue) result = addStmt(BCO->getCommon());
+
+ return result;
+}
+
+CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
+ if (DS->isSingleDecl())
+ return VisitDeclSubExpr(DS);
+
+ CFGBlock *B = 0;
+
+ // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy.
+ typedef llvm::SmallVector<Decl*,10> BufTy;
+ BufTy Buf(DS->decl_begin(), DS->decl_end());
+
+ for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) {
+ // Get the alignment of the new DeclStmt, padding out to >=8 bytes.
+ unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
+ ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
+
+ // Allocate the DeclStmt using the BumpPtrAllocator. It will get
+ // automatically freed with the CFG.
+ DeclGroupRef DG(*I);
+ Decl *D = *I;
+ void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
+ DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
+
+ // Append the fake DeclStmt to block.
+ B = VisitDeclSubExpr(DSNew);
+ }
+
+ return B;
+}
+
+/// VisitDeclSubExpr - Utility method to add block-level expressions for
+/// DeclStmts and initializers in them.
+CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) {
+ assert(DS->isSingleDecl() && "Can handle single declarations only.");
+
+ VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+
+ if (!VD) {
+ autoCreateBlock();
+ appendStmt(Block, DS);
+ return Block;
+ }
+
+ bool IsReference = false;
+ bool HasTemporaries = false;
+
+ // Destructors of temporaries in initialization expression should be called
+ // after initialization finishes.
+ Expr *Init = VD->getInit();
+ if (Init) {
+ IsReference = VD->getType()->isReferenceType();
+ HasTemporaries = isa<ExprWithCleanups>(Init);
+
+ if (BuildOpts.AddImplicitDtors && HasTemporaries) {
+ // Generate destructors for temporaries in initialization expression.
+ VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
+ IsReference);
+ }
+ }
+
+ autoCreateBlock();
+ appendStmt(Block, DS);
+
+ if (Init) {
+ if (HasTemporaries)
+ // For expression with temporaries go directly to subexpression to omit
+ // generating destructors for the second time.
+ Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
+ else
+ Visit(Init);
+ }
+
+ // If the type of VD is a VLA, then we must process its size expressions.
+ for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());
+ VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
+ Block = addStmt(VA->getSizeExpr());
+
+ // Remove variable from local scope.
+ if (ScopePos && VD == *ScopePos)
+ ++ScopePos;
+
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
+ // We may see an if statement in the middle of a basic block, or it may be the
+ // first statement we are processing. In either case, we create a new basic
+ // block. First, we create the blocks for the then...else statements, and
+ // then we create the block containing the if statement. If we were in the
+ // middle of a block, we stop processing that block. That block is then the
+ // implicit successor for the "then" and "else" clauses.
+
+ // Save local scope position because in case of condition variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ // Create local scope for possible condition variable.
+ // Store scope position. Add implicit destructor.
+ if (VarDecl* VD = I->getConditionVariable()) {
+ LocalScope::const_iterator BeginScopePos = ScopePos;
+ addLocalScopeForVarDecl(VD);
+ addAutomaticObjDtors(ScopePos, BeginScopePos, I);
+ }
+
+ // The block we were proccessing is now finished. Make it the successor
+ // block.
+ if (Block) {
+ Succ = Block;
+ if (badCFG)
+ return 0;
+ }
+
+ // Process the false branch.
+ CFGBlock* ElseBlock = Succ;
+
+ if (Stmt* Else = I->getElse()) {
+ SaveAndRestore<CFGBlock*> sv(Succ);
+
+ // NULL out Block so that the recursive call to Visit will
+ // create a new basic block.
+ Block = NULL;
+
+ // If branch is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(Else))
+ addLocalScopeAndDtors(Else);
+
+ ElseBlock = addStmt(Else);
+
+ if (!ElseBlock) // Can occur when the Else body has all NullStmts.
+ ElseBlock = sv.get();
+ else if (Block) {
+ if (badCFG)
+ return 0;
+ }
+ }
+
+ // Process the true branch.
+ CFGBlock* ThenBlock;
+ {
+ Stmt* Then = I->getThen();
+ assert(Then);
+ SaveAndRestore<CFGBlock*> sv(Succ);
+ Block = NULL;
+
+ // If branch is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(Then))
+ addLocalScopeAndDtors(Then);
+
+ ThenBlock = addStmt(Then);
+
+ if (!ThenBlock) {
+ // We can reach here if the "then" body has all NullStmts.
+ // Create an empty block so we can distinguish between true and false
+ // branches in path-sensitive analyses.
+ ThenBlock = createBlock(false);
+ addSuccessor(ThenBlock, sv.get());
+ } else if (Block) {
+ if (badCFG)
+ return 0;
+ }
+ }
+
+ // Now create a new block containing the if statement.
+ Block = createBlock(false);
+
+ // Set the terminator of the new block to the If statement.
+ Block->setTerminator(I);
+
+ // See if this is a known constant.
+ const TryResult &KnownVal = tryEvaluateBool(I->getCond());
+
+ // Now add the successors.
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock);
+ addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock);
+
+ // Add the condition as the last statement in the new block. This may create
+ // new blocks as the condition may contain control-flow. Any newly created
+ // blocks will be pointed to be "Block".
+ Block = addStmt(I->getCond());
+
+ // Finally, if the IfStmt contains a condition variable, add both the IfStmt
+ // and the condition variable initialization to the CFG.
+ if (VarDecl *VD = I->getConditionVariable()) {
+ if (Expr *Init = VD->getInit()) {
+ autoCreateBlock();
+ appendStmt(Block, I, AddStmtChoice::AlwaysAdd);
+ addStmt(Init);
+ }
+ }
+
+ return Block;
+}
+
+
+CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
+ // If we were in the middle of a block we stop processing that block.
+ //
+ // NOTE: If a "return" appears in the middle of a block, this means that the
+ // code afterwards is DEAD (unreachable). We still keep a basic block
+ // for that code; a simple "mark-and-sweep" from the entry block will be
+ // able to report such dead blocks.
+
+ // Create the new block.
+ Block = createBlock(false);
+
+ // The Exit block is the only successor.
+ addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
+ addSuccessor(Block, &cfg->getExit());
+
+ // Add the return statement to the block. This may create new blocks if R
+ // contains control-flow (short-circuit operations).
+ return VisitStmt(R, AddStmtChoice::AlwaysAdd);
+}
+
+CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt *L) {
+ // Get the block of the labeled statement. Add it to our map.
+ addStmt(L->getSubStmt());
+ CFGBlock *LabelBlock = Block;
+
+ if (!LabelBlock) // This can happen when the body is empty, i.e.
+ LabelBlock = createBlock(); // scopes that only contains NullStmts.
+
+ assert(LabelMap.find(L->getDecl()) == LabelMap.end() &&
+ "label already in map");
+ LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
+
+ // Labels partition blocks, so this is the end of the basic block we were
+ // processing (L is the block's label). Because this is label (and we have
+ // already processed the substatement) there is no extra control-flow to worry
+ // about.
+ LabelBlock->setLabel(L);
+ if (badCFG)
+ return 0;
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary);
+ Block = NULL;
+
+ // This block is now the implicit successor of other blocks.
+ Succ = LabelBlock;
+
+ return LabelBlock;
+}
+
+CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
+ // Goto is a control-flow statement. Thus we stop processing the current
+ // block and create a new one.
+
+ Block = createBlock(false);
+ Block->setTerminator(G);
+
+ // If we already know the mapping to the label block add the successor now.
+ LabelMapTy::iterator I = LabelMap.find(G->getLabel());
+
+ if (I == LabelMap.end())
+ // We will need to backpatch this block later.
+ BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
+ else {
+ JumpTarget JT = I->second;
+ addAutomaticObjDtors(ScopePos, JT.scopePosition, G);
+ addSuccessor(Block, JT.block);
+ }
+
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
+ CFGBlock* LoopSuccessor = NULL;
+
+ // Save local scope position because in case of condition variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ // Create local scope for init statement and possible condition variable.
+ // Add destructor for init statement and condition variable.
+ // Store scope position for continue statement.
+ if (Stmt* Init = F->getInit())
+ addLocalScopeForStmt(Init);
+ LocalScope::const_iterator LoopBeginScopePos = ScopePos;
+
+ if (VarDecl* VD = F->getConditionVariable())
+ addLocalScopeForVarDecl(VD);
+ LocalScope::const_iterator ContinueScopePos = ScopePos;
+
+ addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
+
+ // "for" is a control-flow statement. Thus we stop processing the current
+ // block.
+ if (Block) {
+ if (badCFG)
+ return 0;
+ LoopSuccessor = Block;
+ } else
+ LoopSuccessor = Succ;
+
+ // Save the current value for the break targets.
+ // All breaks should go to the code following the loop.
+ SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
+ BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
+
+ // Because of short-circuit evaluation, the condition of the loop can span
+ // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
+ // evaluate the condition.
+ CFGBlock* ExitConditionBlock = createBlock(false);
+ CFGBlock* EntryConditionBlock = ExitConditionBlock;
+
+ // Set the terminator for the "exit" condition block.
+ ExitConditionBlock->setTerminator(F);
+
+ // Now add the actual condition to the condition block. Because the condition
+ // itself may contain control-flow, new blocks may be created.
+ if (Stmt* C = F->getCond()) {
+ Block = ExitConditionBlock;
+ EntryConditionBlock = addStmt(C);
+ if (badCFG)
+ return 0;
+ assert(Block == EntryConditionBlock ||
+ (Block == 0 && EntryConditionBlock == Succ));
+
+ // If this block contains a condition variable, add both the condition
+ // variable and initializer to the CFG.
+ if (VarDecl *VD = F->getConditionVariable()) {
+ if (Expr *Init = VD->getInit()) {
+ autoCreateBlock();
+ appendStmt(Block, F, AddStmtChoice::AlwaysAdd);
+ EntryConditionBlock = addStmt(Init);
+ assert(Block == EntryConditionBlock);
+ }
+ }
+
+ if (Block) {
+ if (badCFG)
+ return 0;
+ }
+ }
+
+ // The condition block is the implicit successor for the loop body as well as
+ // any code above the loop.
+ Succ = EntryConditionBlock;
+
+ // See if this is a known constant.
+ TryResult KnownVal(true);
+
+ if (F->getCond())
+ KnownVal = tryEvaluateBool(F->getCond());
+
+ // Now create the loop body.
+ {
+ assert(F->getBody());
+
+ // Save the current values for Block, Succ, and continue targets.
+ SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+ SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
+
+ // Create a new block to contain the (bottom) of the loop body.
+ Block = NULL;
+
+ // Loop body should end with destructor of Condition variable (if any).
+ addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
+
+ if (Stmt* I = F->getInc()) {
+ // Generate increment code in its own basic block. This is the target of
+ // continue statements.
+ Succ = addStmt(I);
+ } else {
+ // No increment code. Create a special, empty, block that is used as the
+ // target block for "looping back" to the start of the loop.
+ assert(Succ == EntryConditionBlock);
+ Succ = Block ? Block : createBlock();
+ }
+
+ // Finish up the increment (or empty) block if it hasn't been already.
+ if (Block) {
+ assert(Block == Succ);
+ if (badCFG)
+ return 0;
+ Block = 0;
+ }
+
+ ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
+
+ // The starting block for the loop increment is the block that should
+ // represent the 'loop target' for looping back to the start of the loop.
+ ContinueJumpTarget.block->setLoopTarget(F);
+
+ // If body is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(F->getBody()))
+ addLocalScopeAndDtors(F->getBody());
+
+ // Now populate the body block, and in the process create new blocks as we
+ // walk the body of the loop.
+ CFGBlock* BodyBlock = addStmt(F->getBody());
+
+ if (!BodyBlock)
+ BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);"
+ else if (badCFG)
+ return 0;
+
+ // This new body block is a successor to our "exit" condition block.
+ addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop. (the
+ // false branch).
+ addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+
+ // If the loop contains initialization, create a new block for those
+ // statements. This block can also contain statements that precede the loop.
+ if (Stmt* I = F->getInit()) {
+ Block = createBlock();
+ return addStmt(I);
+ }
+
+ // There is no loop initialization. We are thus basically a while loop.
+ // NULL out Block to force lazy block construction.
+ Block = NULL;
+ Succ = EntryConditionBlock;
+ return EntryConditionBlock;
+}
+
+CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, M, asc);
+ }
+ return Visit(M->getBase());
+}
+
+CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+ // Objective-C fast enumeration 'for' statements:
+ // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
+ //
+ // for ( Type newVariable in collection_expression ) { statements }
+ //
+ // becomes:
+ //
+ // prologue:
+ // 1. collection_expression
+ // T. jump to loop_entry
+ // loop_entry:
+ // 1. side-effects of element expression
+ // 1. ObjCForCollectionStmt [performs binding to newVariable]
+ // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]
+ // TB:
+ // statements
+ // T. jump to loop_entry
+ // FB:
+ // what comes after
+ //
+ // and
+ //
+ // Type existingItem;
+ // for ( existingItem in expression ) { statements }
+ //
+ // becomes:
+ //
+ // the same with newVariable replaced with existingItem; the binding works
+ // the same except that for one ObjCForCollectionStmt::getElement() returns
+ // a DeclStmt and the other returns a DeclRefExpr.
+ //
+
+ CFGBlock* LoopSuccessor = 0;
+
+ if (Block) {
+ if (badCFG)
+ return 0;
+ LoopSuccessor = Block;
+ Block = 0;
+ } else
+ LoopSuccessor = Succ;
+
+ // Build the condition blocks.
+ CFGBlock* ExitConditionBlock = createBlock(false);
+ CFGBlock* EntryConditionBlock = ExitConditionBlock;
+
+ // Set the terminator for the "exit" condition block.
+ ExitConditionBlock->setTerminator(S);
+
+ // The last statement in the block should be the ObjCForCollectionStmt, which
+ // performs the actual binding to 'element' and determines if there are any
+ // more items in the collection.
+ appendStmt(ExitConditionBlock, S);
+ Block = ExitConditionBlock;
+
+ // Walk the 'element' expression to see if there are any side-effects. We
+ // generate new blocks as necesary. We DON'T add the statement by default to
+ // the CFG unless it contains control-flow.
+ EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd);
+ if (Block) {
+ if (badCFG)
+ return 0;
+ Block = 0;
+ }
+
+ // The condition block is the implicit successor for the loop body as well as
+ // any code above the loop.
+ Succ = EntryConditionBlock;
+
+ // Now create the true branch.
+ {
+ // Save the current values for Succ, continue and break targets.
+ SaveAndRestore<CFGBlock*> save_Succ(Succ);
+ SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+ save_break(BreakJumpTarget);
+
+ BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
+ ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
+
+ CFGBlock* BodyBlock = addStmt(S->getBody());
+
+ if (!BodyBlock)
+ BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;"
+ else if (Block) {
+ if (badCFG)
+ return 0;
+ }
+
+ // This new body block is a successor to our "exit" condition block.
+ addSuccessor(ExitConditionBlock, BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ addSuccessor(ExitConditionBlock, LoopSuccessor);
+
+ // Now create a prologue block to contain the collection expression.
+ Block = createBlock();
+ return addStmt(S->getCollection());
+}
+
+CFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) {
+ // FIXME: Add locking 'primitives' to CFG for @synchronized.
+
+ // Inline the body.
+ CFGBlock *SyncBlock = addStmt(S->getSynchBody());
+
+ // The sync body starts its own basic block. This makes it a little easier
+ // for diagnostic clients.
+ if (SyncBlock) {
+ if (badCFG)
+ return 0;
+
+ Block = 0;
+ Succ = SyncBlock;
+ }
+
+ // Add the @synchronized to the CFG.
+ autoCreateBlock();
+ appendStmt(Block, S, AddStmtChoice::AlwaysAdd);
+
+ // Inline the sync expression.
+ return addStmt(S->getSynchExpr());
+}
+
+CFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) {
+ // FIXME
+ return NYS();
+}
+
+CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
+ CFGBlock* LoopSuccessor = NULL;
+
+ // Save local scope position because in case of condition variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ // Create local scope for possible condition variable.
+ // Store scope position for continue statement.
+ LocalScope::const_iterator LoopBeginScopePos = ScopePos;
+ if (VarDecl* VD = W->getConditionVariable()) {
+ addLocalScopeForVarDecl(VD);
+ addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
+ }
+
+ // "while" is a control-flow statement. Thus we stop processing the current
+ // block.
+ if (Block) {
+ if (badCFG)
+ return 0;
+ LoopSuccessor = Block;
+ } else
+ LoopSuccessor = Succ;
+
+ // Because of short-circuit evaluation, the condition of the loop can span
+ // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
+ // evaluate the condition.
+ CFGBlock* ExitConditionBlock = createBlock(false);
+ CFGBlock* EntryConditionBlock = ExitConditionBlock;
+
+ // Set the terminator for the "exit" condition block.
+ ExitConditionBlock->setTerminator(W);
+
+ // Now add the actual condition to the condition block. Because the condition
+ // itself may contain control-flow, new blocks may be created. Thus we update
+ // "Succ" after adding the condition.
+ if (Stmt* C = W->getCond()) {
+ Block = ExitConditionBlock;
+ EntryConditionBlock = addStmt(C);
+ // The condition might finish the current 'Block'.
+ Block = EntryConditionBlock;
+
+ // If this block contains a condition variable, add both the condition
+ // variable and initializer to the CFG.
+ if (VarDecl *VD = W->getConditionVariable()) {
+ if (Expr *Init = VD->getInit()) {
+ autoCreateBlock();
+ appendStmt(Block, W, AddStmtChoice::AlwaysAdd);
+ EntryConditionBlock = addStmt(Init);
+ assert(Block == EntryConditionBlock);
+ }
+ }
+
+ if (Block) {
+ if (badCFG)
+ return 0;
+ }
+ }
+
+ // The condition block is the implicit successor for the loop body as well as
+ // any code above the loop.
+ Succ = EntryConditionBlock;
+
+ // See if this is a known constant.
+ const TryResult& KnownVal = tryEvaluateBool(W->getCond());
+
+ // Process the loop body.
+ {
+ assert(W->getBody());
+
+ // Save the current values for Block, Succ, and continue and break targets
+ SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+ SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+ save_break(BreakJumpTarget);
+
+ // Create an empty block to represent the transition block for looping back
+ // to the head of the loop.
+ Block = 0;
+ assert(Succ == EntryConditionBlock);
+ Succ = createBlock();
+ Succ->setLoopTarget(W);
+ ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
+
+ // All breaks should go to the code following the loop.
+ BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
+
+ // NULL out Block to force lazy instantiation of blocks for the body.
+ Block = NULL;
+
+ // Loop body should end with destructor of Condition variable (if any).
+ addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
+
+ // If body is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(W->getBody()))
+ addLocalScopeAndDtors(W->getBody());
+
+ // Create the body. The returned block is the entry to the loop body.
+ CFGBlock* BodyBlock = addStmt(W->getBody());
+
+ if (!BodyBlock)
+ BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
+ else if (Block) {
+ if (badCFG)
+ return 0;
+ }
+
+ // Add the loop body entry as a successor to the condition.
+ addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop. (the
+ // false branch).
+ addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+
+ // There can be no more statements in the condition block since we loop back
+ // to this block. NULL out Block to force lazy creation of another block.
+ Block = NULL;
+
+ // Return the condition block, which is the dominating block for the loop.
+ Succ = EntryConditionBlock;
+ return EntryConditionBlock;
+}
+
+
+CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) {
+ // FIXME: For now we pretend that @catch and the code it contains does not
+ // exit.
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) {
+ // FIXME: This isn't complete. We basically treat @throw like a return
+ // statement.
+
+ // If we were in the middle of a block we stop processing that block.
+ if (badCFG)
+ return 0;
+
+ // Create the new block.
+ Block = createBlock(false);
+
+ // The Exit block is the only successor.
+ addSuccessor(Block, &cfg->getExit());
+
+ // Add the statement to the block. This may create new blocks if S contains
+ // control-flow (short-circuit operations).
+ return VisitStmt(S, AddStmtChoice::AlwaysAdd);
+}
+
+CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
+ // If we were in the middle of a block we stop processing that block.
+ if (badCFG)
+ return 0;
+
+ // Create the new block.
+ Block = createBlock(false);
+
+ if (TryTerminatedBlock)
+ // The current try statement is the only successor.
+ addSuccessor(Block, TryTerminatedBlock);
+ else
+ // otherwise the Exit block is the only successor.
+ addSuccessor(Block, &cfg->getExit());
+
+ // Add the statement to the block. This may create new blocks if S contains
+ // control-flow (short-circuit operations).
+ return VisitStmt(T, AddStmtChoice::AlwaysAdd);
+}
+
+CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
+ CFGBlock* LoopSuccessor = NULL;
+
+ // "do...while" is a control-flow statement. Thus we stop processing the
+ // current block.
+ if (Block) {
+ if (badCFG)
+ return 0;
+ LoopSuccessor = Block;
+ } else
+ LoopSuccessor = Succ;
+
+ // Because of short-circuit evaluation, the condition of the loop can span
+ // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
+ // evaluate the condition.
+ CFGBlock* ExitConditionBlock = createBlock(false);
+ CFGBlock* EntryConditionBlock = ExitConditionBlock;
+
+ // Set the terminator for the "exit" condition block.
+ ExitConditionBlock->setTerminator(D);
+
+ // Now add the actual condition to the condition block. Because the condition
+ // itself may contain control-flow, new blocks may be created.
+ if (Stmt* C = D->getCond()) {
+ Block = ExitConditionBlock;
+ EntryConditionBlock = addStmt(C);
+ if (Block) {
+ if (badCFG)
+ return 0;
+ }
+ }
+
+ // The condition block is the implicit successor for the loop body.
+ Succ = EntryConditionBlock;
+
+ // See if this is a known constant.
+ const TryResult &KnownVal = tryEvaluateBool(D->getCond());
+
+ // Process the loop body.
+ CFGBlock* BodyBlock = NULL;
+ {
+ assert(D->getBody());
+
+ // Save the current values for Block, Succ, and continue and break targets
+ SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+ SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+ save_break(BreakJumpTarget);
+
+ // All continues within this loop should go to the condition block
+ ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
+
+ // All breaks should go to the code following the loop.
+ BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
+
+ // NULL out Block to force lazy instantiation of blocks for the body.
+ Block = NULL;
+
+ // If body is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(D->getBody()))
+ addLocalScopeAndDtors(D->getBody());
+
+ // Create the body. The returned block is the entry to the loop body.
+ BodyBlock = addStmt(D->getBody());
+
+ if (!BodyBlock)
+ BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
+ else if (Block) {
+ if (badCFG)
+ return 0;
+ }
+
+ if (!KnownVal.isFalse()) {
+ // Add an intermediate block between the BodyBlock and the
+ // ExitConditionBlock to represent the "loop back" transition. Create an
+ // empty block to represent the transition block for looping back to the
+ // head of the loop.
+ // FIXME: Can we do this more efficiently without adding another block?
+ Block = NULL;
+ Succ = BodyBlock;
+ CFGBlock *LoopBackBlock = createBlock();
+ LoopBackBlock->setLoopTarget(D);
+
+ // Add the loop body entry as a successor to the condition.
+ addSuccessor(ExitConditionBlock, LoopBackBlock);
+ }
+ else
+ addSuccessor(ExitConditionBlock, NULL);
+ }
+
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+
+ // There can be no more statements in the body block(s) since we loop back to
+ // the body. NULL out Block to force lazy creation of another block.
+ Block = NULL;
+
+ // Return the loop body, which is the dominating block for the loop.
+ Succ = BodyBlock;
+ return BodyBlock;
+}
+
+CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
+ // "continue" is a control-flow statement. Thus we stop processing the
+ // current block.
+ if (badCFG)
+ return 0;
+
+ // Now create a new block that ends with the continue statement.
+ Block = createBlock(false);
+ Block->setTerminator(C);
+
+ // If there is no target for the continue, then we are looking at an
+ // incomplete AST. This means the CFG cannot be constructed.
+ if (ContinueJumpTarget.block) {
+ addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
+ addSuccessor(Block, ContinueJumpTarget.block);
+ } else
+ badCFG = true;
+
+ return Block;
+}
+
+CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
+ AddStmtChoice asc) {
+
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, E);
+ }
+
+ // VLA types have expressions that must be evaluated.
+ if (E->isArgumentType()) {
+ for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
+ VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
+ addStmt(VA->getSizeExpr());
+ }
+
+ return Block;
+}
+
+/// VisitStmtExpr - Utility method to handle (nested) statement
+/// expressions (a GCC extension).
+CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, SE);
+ }
+ return VisitCompoundStmt(SE->getSubStmt());
+}
+
+CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
+ // "switch" is a control-flow statement. Thus we stop processing the current
+ // block.
+ CFGBlock* SwitchSuccessor = NULL;
+
+ // Save local scope position because in case of condition variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ // Create local scope for possible condition variable.
+ // Store scope position. Add implicit destructor.
+ if (VarDecl* VD = Terminator->getConditionVariable()) {
+ LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
+ addLocalScopeForVarDecl(VD);
+ addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
+ }
+
+ if (Block) {
+ if (badCFG)
+ return 0;
+ SwitchSuccessor = Block;
+ } else SwitchSuccessor = Succ;
+
+ // Save the current "switch" context.
+ SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
+ save_default(DefaultCaseBlock);
+ SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
+
+ // Set the "default" case to be the block after the switch statement. If the
+ // switch statement contains a "default:", this value will be overwritten with
+ // the block for that code.
+ DefaultCaseBlock = SwitchSuccessor;
+
+ // Create a new block that will contain the switch statement.
+ SwitchTerminatedBlock = createBlock(false);
+
+ // Now process the switch body. The code after the switch is the implicit
+ // successor.
+ Succ = SwitchSuccessor;
+ BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
+
+ // When visiting the body, the case statements should automatically get linked
+ // up to the switch. We also don't keep a pointer to the body, since all
+ // control-flow from the switch goes to case/default statements.
+ assert(Terminator->getBody() && "switch must contain a non-NULL body");
+ Block = NULL;
+
+ // If body is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(Terminator->getBody()))
+ addLocalScopeAndDtors(Terminator->getBody());
+
+ addStmt(Terminator->getBody());
+ if (Block) {
+ if (badCFG)
+ return 0;
+ }
+
+ // If we have no "default:" case, the default transition is to the code
+ // following the switch body.
+ addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock);
+
+ // Add the terminator and condition in the switch block.
+ SwitchTerminatedBlock->setTerminator(Terminator);
+ assert(Terminator->getCond() && "switch condition must be non-NULL");
+ Block = SwitchTerminatedBlock;
+ Block = addStmt(Terminator->getCond());
+
+ // Finally, if the SwitchStmt contains a condition variable, add both the
+ // SwitchStmt and the condition variable initialization to the CFG.
+ if (VarDecl *VD = Terminator->getConditionVariable()) {
+ if (Expr *Init = VD->getInit()) {
+ autoCreateBlock();
+ appendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
+ addStmt(Init);
+ }
+ }
+
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
+ // CaseStmts are essentially labels, so they are the first statement in a
+ // block.
+ CFGBlock *TopBlock = 0, *LastBlock = 0;
+
+ if (Stmt *Sub = CS->getSubStmt()) {
+ // For deeply nested chains of CaseStmts, instead of doing a recursion
+ // (which can blow out the stack), manually unroll and create blocks
+ // along the way.
+ while (isa<CaseStmt>(Sub)) {
+ CFGBlock *currentBlock = createBlock(false);
+ currentBlock->setLabel(CS);
+
+ if (TopBlock)
+ addSuccessor(LastBlock, currentBlock);
+ else
+ TopBlock = currentBlock;
+
+ addSuccessor(SwitchTerminatedBlock, currentBlock);
+ LastBlock = currentBlock;
+
+ CS = cast<CaseStmt>(Sub);
+ Sub = CS->getSubStmt();
+ }
+
+ addStmt(Sub);
+ }
+
+ CFGBlock* CaseBlock = Block;
+ if (!CaseBlock)
+ CaseBlock = createBlock();
+
+ // Cases statements partition blocks, so this is the top of the basic block we
+ // were processing (the "case XXX:" is the label).
+ CaseBlock->setLabel(CS);
+
+ if (badCFG)
+ return 0;
+
+ // Add this block to the list of successors for the block with the switch
+ // statement.
+ assert(SwitchTerminatedBlock);
+ addSuccessor(SwitchTerminatedBlock, CaseBlock);
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary)
+ Block = NULL;
+
+ if (TopBlock) {
+ addSuccessor(LastBlock, CaseBlock);
+ Succ = TopBlock;
+ } else {
+ // This block is now the implicit successor of other blocks.
+ Succ = CaseBlock;
+ }
+
+ return Succ;
+}
+
+CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {
+ if (Terminator->getSubStmt())
+ addStmt(Terminator->getSubStmt());
+
+ DefaultCaseBlock = Block;
+
+ if (!DefaultCaseBlock)
+ DefaultCaseBlock = createBlock();
+
+ // Default statements partition blocks, so this is the top of the basic block
+ // we were processing (the "default:" is the label).
+ DefaultCaseBlock->setLabel(Terminator);
+
+ if (badCFG)
+ return 0;
+
+ // Unlike case statements, we don't add the default block to the successors
+ // for the switch statement immediately. This is done when we finish
+ // processing the switch statement. This allows for the default case
+ // (including a fall-through to the code after the switch statement) to always
+ // be the last successor of a switch-terminated block.
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary)
+ Block = NULL;
+
+ // This block is now the implicit successor of other blocks.
+ Succ = DefaultCaseBlock;
+
+ return DefaultCaseBlock;
+}
+
+CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
+ // "try"/"catch" is a control-flow statement. Thus we stop processing the
+ // current block.
+ CFGBlock* TrySuccessor = NULL;
+
+ if (Block) {
+ if (badCFG)
+ return 0;
+ TrySuccessor = Block;
+ } else TrySuccessor = Succ;
+
+ CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
+
+ // Create a new block that will contain the try statement.
+ CFGBlock *NewTryTerminatedBlock = createBlock(false);
+ // Add the terminator in the try block.
+ NewTryTerminatedBlock->setTerminator(Terminator);
+
+ bool HasCatchAll = false;
+ for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
+ // The code after the try is the implicit successor.
+ Succ = TrySuccessor;
+ CXXCatchStmt *CS = Terminator->getHandler(h);
+ if (CS->getExceptionDecl() == 0) {
+ HasCatchAll = true;
+ }
+ Block = NULL;
+ CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
+ if (CatchBlock == 0)
+ return 0;
+ // Add this block to the list of successors for the block with the try
+ // statement.
+ addSuccessor(NewTryTerminatedBlock, CatchBlock);
+ }
+ if (!HasCatchAll) {
+ if (PrevTryTerminatedBlock)
+ addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
+ else
+ addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
+ }
+
+ // The code after the try is the implicit successor.
+ Succ = TrySuccessor;
+
+ // Save the current "try" context.
+ SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock);
+ TryTerminatedBlock = NewTryTerminatedBlock;
+
+ assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
+ Block = NULL;
+ Block = addStmt(Terminator->getTryBlock());
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
+ // CXXCatchStmt are treated like labels, so they are the first statement in a
+ // block.
+
+ // Save local scope position because in case of exception variable ScopePos
+ // won't be restored when traversing AST.
+ SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
+
+ // Create local scope for possible exception variable.
+ // Store scope position. Add implicit destructor.
+ if (VarDecl* VD = CS->getExceptionDecl()) {
+ LocalScope::const_iterator BeginScopePos = ScopePos;
+ addLocalScopeForVarDecl(VD);
+ addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
+ }
+
+ if (CS->getHandlerBlock())
+ addStmt(CS->getHandlerBlock());
+
+ CFGBlock* CatchBlock = Block;
+ if (!CatchBlock)
+ CatchBlock = createBlock();
+
+ CatchBlock->setLabel(CS);
+
+ if (badCFG)
+ return 0;
+
+ // We set Block to NULL to allow lazy creation of a new block (if necessary)
+ Block = NULL;
+
+ return CatchBlock;
+}
+
+CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
+ AddStmtChoice asc) {
+ if (BuildOpts.AddImplicitDtors) {
+ // If adding implicit destructors visit the full expression for adding
+ // destructors of temporaries.
+ VisitForTemporaryDtors(E->getSubExpr());
+
+ // Full expression has to be added as CFGStmt so it will be sequenced
+ // before destructors of it's temporaries.
+ asc = asc.withAlwaysAdd(true);
+ }
+ return Visit(E->getSubExpr(), asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
+ AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, E, asc);
+
+ // We do not want to propagate the AlwaysAdd property.
+ asc = asc.withAlwaysAdd(false);
+ }
+ return Visit(E->getSubExpr(), asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
+ AddStmtChoice asc) {
+ autoCreateBlock();
+ if (!C->isElidable())
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
+
+ return VisitChildren(C);
+}
+
+CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
+ AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, E, asc);
+ // We do not want to propagate the AlwaysAdd property.
+ asc = asc.withAlwaysAdd(false);
+ }
+ return Visit(E->getSubExpr(), asc);
+}
+
+CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
+ AddStmtChoice asc) {
+ autoCreateBlock();
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
+ return VisitChildren(C);
+}
+
+CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
+ AddStmtChoice asc) {
+ autoCreateBlock();
+ appendStmt(Block, C, asc.withAlwaysAdd(true));
+ return VisitChildren(C);
+}
+
+CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
+ AddStmtChoice asc) {
+ if (asc.alwaysAdd()) {
+ autoCreateBlock();
+ appendStmt(Block, E, asc);
+ }
+ return Visit(E->getSubExpr(), AddStmtChoice());
+}
+
+CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
+ // Lazily create the indirect-goto dispatch block if there isn't one already.
+ CFGBlock* IBlock = cfg->getIndirectGotoBlock();
+
+ if (!IBlock) {
+ IBlock = createBlock(false);
+ cfg->setIndirectGotoBlock(IBlock);
+ }
+
+ // IndirectGoto is a control-flow statement. Thus we stop processing the
+ // current block and create a new one.
+ if (badCFG)
+ return 0;
+
+ Block = createBlock(false);
+ Block->setTerminator(I);
+ addSuccessor(Block, IBlock);
+ return addStmt(I->getTarget());
+}
+
+CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) {
+tryAgain:
+ if (!E) {
+ badCFG = true;
+ return NULL;
+ }
+ switch (E->getStmtClass()) {
+ default:
+ return VisitChildrenForTemporaryDtors(E);
+
+ case Stmt::BinaryOperatorClass:
+ return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E));
+
+ case Stmt::CXXBindTemporaryExprClass:
+ return VisitCXXBindTemporaryExprForTemporaryDtors(
+ cast<CXXBindTemporaryExpr>(E), BindToTemporary);
+
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ return VisitConditionalOperatorForTemporaryDtors(
+ cast<AbstractConditionalOperator>(E), BindToTemporary);
+
+ case Stmt::ImplicitCastExprClass:
+ // For implicit cast we want BindToTemporary to be passed further.
+ E = cast<CastExpr>(E)->getSubExpr();
+ goto tryAgain;
+
+ case Stmt::ParenExprClass:
+ E = cast<ParenExpr>(E)->getSubExpr();
+ goto tryAgain;
+ }
+}
+
+CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) {
+ // When visiting children for destructors we want to visit them in reverse
+ // order. Because there's no reverse iterator for children must to reverse
+ // them in helper vector.
+ typedef llvm::SmallVector<Stmt *, 4> ChildrenVect;
+ ChildrenVect ChildrenRev;
+ for (Stmt::child_range I = E->children(); I; ++I) {
+ if (*I) ChildrenRev.push_back(*I);
+ }
+
+ CFGBlock *B = Block;
+ for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(),
+ L = ChildrenRev.rend(); I != L; ++I) {
+ if (CFGBlock *R = VisitForTemporaryDtors(*I))
+ B = R;
+ }
+ return B;
+}
+
+CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) {
+ if (E->isLogicalOp()) {
+ // Destructors for temporaries in LHS expression should be called after
+ // those for RHS expression. Even if this will unnecessarily create a block,
+ // this block will be used at least by the full expression.
+ autoCreateBlock();
+ CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS());
+ if (badCFG)
+ return NULL;
+
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+
+ if (RHSBlock) {
+ if (badCFG)
+ return NULL;
+
+ // If RHS expression did produce destructors we need to connect created
+ // blocks to CFG in same manner as for binary operator itself.
+ CFGBlock *LHSBlock = createBlock(false);
+ LHSBlock->setTerminator(CFGTerminator(E, true));
+
+ // For binary operator LHS block is before RHS in list of predecessors
+ // of ConfluenceBlock.
+ std::reverse(ConfluenceBlock->pred_begin(),
+ ConfluenceBlock->pred_end());
+
+ // See if this is a known constant.
+ TryResult KnownVal = tryEvaluateBool(E->getLHS());
+ if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr))
+ KnownVal.negate();
+
+ // Link LHSBlock with RHSBlock exactly the same way as for binary operator
+ // itself.
+ if (E->getOpcode() == BO_LOr) {
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+ } else {
+ assert (E->getOpcode() == BO_LAnd);
+ addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+ addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+ }
+
+ Block = LHSBlock;
+ return LHSBlock;
+ }
+
+ Block = ConfluenceBlock;
+ return ConfluenceBlock;
+ }
+
+ if (E->isAssignmentOp()) {
+ // For assignment operator (=) LHS expression is visited
+ // before RHS expression. For destructors visit them in reverse order.
+ CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+ CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS());
+ return LHSBlock ? LHSBlock : RHSBlock;
+ }
+
+ // For any other binary operator RHS expression is visited before
+ // LHS expression (order of children). For destructors visit them in reverse
+ // order.
+ CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS());
+ CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+ return RHSBlock ? RHSBlock : LHSBlock;
+}
+
+CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
+ CXXBindTemporaryExpr *E, bool BindToTemporary) {
+ // First add destructors for temporaries in subexpression.
+ CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr());
+ if (!BindToTemporary) {
+ // If lifetime of temporary is not prolonged (by assigning to constant
+ // reference) add destructor for it.
+ autoCreateBlock();
+ appendTemporaryDtor(Block, E);
+ B = Block;
+ }
+ return B;
+}
+
+CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
+ AbstractConditionalOperator *E, bool BindToTemporary) {
+ // First add destructors for condition expression. Even if this will
+ // unnecessarily create a block, this block will be used at least by the full
+ // expression.
+ autoCreateBlock();
+ CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond());
+ if (badCFG)
+ return NULL;
+ if (BinaryConditionalOperator *BCO
+ = dyn_cast<BinaryConditionalOperator>(E)) {
+ ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon());
+ if (badCFG)
+ return NULL;
+ }
+
+ // Try to add block with destructors for LHS expression.
+ CFGBlock *LHSBlock = NULL;
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary);
+ if (badCFG)
+ return NULL;
+
+ // Try to add block with destructors for RHS expression;
+ Succ = ConfluenceBlock;
+ Block = NULL;
+ CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(),
+ BindToTemporary);
+ if (badCFG)
+ return NULL;
+
+ if (!RHSBlock && !LHSBlock) {
+ // If neither LHS nor RHS expression had temporaries to destroy don't create
+ // more blocks.
+ Block = ConfluenceBlock;
+ return Block;
+ }
+
+ Block = createBlock(false);
+ Block->setTerminator(CFGTerminator(E, true));
+
+ // See if this is a known constant.
+ const TryResult &KnownVal = tryEvaluateBool(E->getCond());
+
+ if (LHSBlock) {
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+ } else if (KnownVal.isFalse()) {
+ addSuccessor(Block, NULL);
+ } else {
+ addSuccessor(Block, ConfluenceBlock);
+ std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end());
+ }
+
+ if (!RHSBlock)
+ RHSBlock = ConfluenceBlock;
+ addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+
+ return Block;
+}
+
+} // end anonymous namespace
+
+/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has
+/// no successors or predecessors. If this is the first block created in the
+/// CFG, it is automatically set to be the Entry and Exit of the CFG.
+CFGBlock* CFG::createBlock() {
+ bool first_block = begin() == end();
+
+ // Create the block.
+ CFGBlock *Mem = getAllocator().Allocate<CFGBlock>();
+ new (Mem) CFGBlock(NumBlockIDs++, BlkBVC);
+ Blocks.push_back(Mem, BlkBVC);
+
+ // If this is the first block, set it as the Entry and Exit.
+ if (first_block)
+ Entry = Exit = &back();
+
+ // Return the block.
+ return &back();
+}
+
+/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
+/// CFG is returned to the caller.
+CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
+ BuildOptions BO) {
+ CFGBuilder Builder;
+ return Builder.buildCFG(D, Statement, C, BO);
+}
+
+//===----------------------------------------------------------------------===//
+// CFG: Queries for BlkExprs.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy;
+}
+
+static void FindSubExprAssignments(Stmt *S,
+ llvm::SmallPtrSet<Expr*,50>& Set) {
+ if (!S)
+ return;
+
+ for (Stmt::child_range I = S->children(); I; ++I) {
+ Stmt *child = *I;
+ if (!child)
+ continue;
+
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(child))
+ if (B->isAssignmentOp()) Set.insert(B);
+
+ FindSubExprAssignments(child, Set);
+ }
+}
+
+static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
+ BlkExprMapTy* M = new BlkExprMapTy();
+
+ // Look for assignments that are used as subexpressions. These are the only
+ // assignments that we want to *possibly* register as a block-level
+ // expression. Basically, if an assignment occurs both in a subexpression and
+ // at the block-level, it is a block-level expression.
+ llvm::SmallPtrSet<Expr*,50> SubExprAssignments;
+
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
+ for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI)
+ if (CFGStmt S = BI->getAs<CFGStmt>())
+ FindSubExprAssignments(S, SubExprAssignments);
+
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) {
+
+ // Iterate over the statements again on identify the Expr* and Stmt* at the
+ // block-level that are block-level expressions.
+
+ for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) {
+ CFGStmt CS = BI->getAs<CFGStmt>();
+ if (!CS.isValid())
+ continue;
+ if (Expr* Exp = dyn_cast<Expr>(CS.getStmt())) {
+
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) {
+ // Assignment expressions that are not nested within another
+ // expression are really "statements" whose value is never used by
+ // another expression.
+ if (B->isAssignmentOp() && !SubExprAssignments.count(Exp))
+ continue;
+ } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) {
+ // Special handling for statement expressions. The last statement in
+ // the statement expression is also a block-level expr.
+ const CompoundStmt* C = Terminator->getSubStmt();
+ if (!C->body_empty()) {
+ unsigned x = M->size();
+ (*M)[C->body_back()] = x;
+ }
+ }
+
+ unsigned x = M->size();
+ (*M)[Exp] = x;
+ }
+ }
+
+ // Look at terminators. The condition is a block-level expression.
+
+ Stmt* S = (*I)->getTerminatorCondition();
+
+ if (S && M->find(S) == M->end()) {
+ unsigned x = M->size();
+ (*M)[S] = x;
+ }
+ }
+
+ return M;
+}
+
+CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
+ assert(S != NULL);
+ if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); }
+
+ BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
+ BlkExprMapTy::iterator I = M->find(S);
+ return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second);
+}
+
+unsigned CFG::getNumBlkExprs() {
+ if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap))
+ return M->size();
+
+ // We assume callers interested in the number of BlkExprs will want
+ // the map constructed if it doesn't already exist.
+ BlkExprMap = (void*) PopulateBlkExprMap(*this);
+ return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size();
+}
+
+//===----------------------------------------------------------------------===//
+// Filtered walking of the CFG.
+//===----------------------------------------------------------------------===//
+
+bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
+ const CFGBlock *From, const CFGBlock *To) {
+
+ if (F.IgnoreDefaultsWithCoveredEnums) {
+ // If the 'To' has no label or is labeled but the label isn't a
+ // CaseStmt then filter this edge.
+ if (const SwitchStmt *S =
+ dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) {
+ if (S->isAllEnumCasesCovered()) {
+ const Stmt *L = To->getLabel();
+ if (!L || !isa<CaseStmt>(L))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Cleanup: CFG dstor.
+//===----------------------------------------------------------------------===//
+
+CFG::~CFG() {
+ delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap);
+}
+
+//===----------------------------------------------------------------------===//
+// CFG pretty printing
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class StmtPrinterHelper : public PrinterHelper {
+ typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
+ typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
+ StmtMapTy StmtMap;
+ DeclMapTy DeclMap;
+ signed currentBlock;
+ unsigned currentStmt;
+ const LangOptions &LangOpts;
+public:
+
+ StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
+ : currentBlock(0), currentStmt(0), LangOpts(LO) {
+ for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
+ unsigned j = 1;
+ for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
+ BI != BEnd; ++BI, ++j ) {
+ if (CFGStmt SE = BI->getAs<CFGStmt>()) {
+ std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
+ StmtMap[SE] = P;
+
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(SE.getStmt())) {
+ DeclMap[DS->getSingleDecl()] = P;
+
+ } else if (IfStmt* IS = dyn_cast<IfStmt>(SE.getStmt())) {
+ if (VarDecl* VD = IS->getConditionVariable())
+ DeclMap[VD] = P;
+
+ } else if (ForStmt* FS = dyn_cast<ForStmt>(SE.getStmt())) {
+ if (VarDecl* VD = FS->getConditionVariable())
+ DeclMap[VD] = P;
+
+ } else if (WhileStmt* WS = dyn_cast<WhileStmt>(SE.getStmt())) {
+ if (VarDecl* VD = WS->getConditionVariable())
+ DeclMap[VD] = P;
+
+ } else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(SE.getStmt())) {
+ if (VarDecl* VD = SS->getConditionVariable())
+ DeclMap[VD] = P;
+
+ } else if (CXXCatchStmt* CS = dyn_cast<CXXCatchStmt>(SE.getStmt())) {
+ if (VarDecl* VD = CS->getExceptionDecl())
+ DeclMap[VD] = P;
+ }
+ }
+ }
+ }
+ }
+
+ virtual ~StmtPrinterHelper() {}
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ void setBlockID(signed i) { currentBlock = i; }
+ void setStmtID(unsigned i) { currentStmt = i; }
+
+ virtual bool handledStmt(Stmt* S, llvm::raw_ostream& OS) {
+ StmtMapTy::iterator I = StmtMap.find(S);
+
+ if (I == StmtMap.end())
+ return false;
+
+ if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
+ && I->second.second == currentStmt) {
+ return false;
+ }
+
+ OS << "[B" << I->second.first << "." << I->second.second << "]";
+ return true;
+ }
+
+ bool handleDecl(Decl* D, llvm::raw_ostream& OS) {
+ DeclMapTy::iterator I = DeclMap.find(D);
+
+ if (I == DeclMap.end())
+ return false;
+
+ if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
+ && I->second.second == currentStmt) {
+ return false;
+ }
+
+ OS << "[B" << I->second.first << "." << I->second.second << "]";
+ return true;
+ }
+};
+} // end anonymous namespace
+
+
+namespace {
+class CFGBlockTerminatorPrint
+ : public StmtVisitor<CFGBlockTerminatorPrint,void> {
+
+ llvm::raw_ostream& OS;
+ StmtPrinterHelper* Helper;
+ PrintingPolicy Policy;
+public:
+ CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper,
+ const PrintingPolicy &Policy)
+ : OS(os), Helper(helper), Policy(Policy) {}
+
+ void VisitIfStmt(IfStmt* I) {
+ OS << "if ";
+ I->getCond()->printPretty(OS,Helper,Policy);
+ }
+
+ // Default case.
+ void VisitStmt(Stmt* Terminator) {
+ Terminator->printPretty(OS, Helper, Policy);
+ }
+
+ void VisitForStmt(ForStmt* F) {
+ OS << "for (" ;
+ if (F->getInit())
+ OS << "...";
+ OS << "; ";
+ if (Stmt* C = F->getCond())
+ C->printPretty(OS, Helper, Policy);
+ OS << "; ";
+ if (F->getInc())
+ OS << "...";
+ OS << ")";
+ }
+
+ void VisitWhileStmt(WhileStmt* W) {
+ OS << "while " ;
+ if (Stmt* C = W->getCond())
+ C->printPretty(OS, Helper, Policy);
+ }
+
+ void VisitDoStmt(DoStmt* D) {
+ OS << "do ... while ";
+ if (Stmt* C = D->getCond())
+ C->printPretty(OS, Helper, Policy);
+ }
+
+ void VisitSwitchStmt(SwitchStmt* Terminator) {
+ OS << "switch ";
+ Terminator->getCond()->printPretty(OS, Helper, Policy);
+ }
+
+ void VisitCXXTryStmt(CXXTryStmt* CS) {
+ OS << "try ...";
+ }
+
+ void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
+ C->getCond()->printPretty(OS, Helper, Policy);
+ OS << " ? ... : ...";
+ }
+
+ void VisitChooseExpr(ChooseExpr* C) {
+ OS << "__builtin_choose_expr( ";
+ C->getCond()->printPretty(OS, Helper, Policy);
+ OS << " )";
+ }
+
+ void VisitIndirectGotoStmt(IndirectGotoStmt* I) {
+ OS << "goto *";
+ I->getTarget()->printPretty(OS, Helper, Policy);
+ }
+
+ void VisitBinaryOperator(BinaryOperator* B) {
+ if (!B->isLogicalOp()) {
+ VisitExpr(B);
+ return;
+ }
+
+ B->getLHS()->printPretty(OS, Helper, Policy);
+
+ switch (B->getOpcode()) {
+ case BO_LOr:
+ OS << " || ...";
+ return;
+ case BO_LAnd:
+ OS << " && ...";
+ return;
+ default:
+ assert(false && "Invalid logical operator.");
+ }
+ }
+
+ void VisitExpr(Expr* E) {
+ E->printPretty(OS, Helper, Policy);
+ }
+};
+} // end anonymous namespace
+
+static void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
+ const CFGElement &E) {
+ if (CFGStmt CS = E.getAs<CFGStmt>()) {
+ Stmt *S = CS;
+
+ if (Helper) {
+
+ // special printing for statement-expressions.
+ if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
+ CompoundStmt* Sub = SE->getSubStmt();
+
+ if (Sub->children()) {
+ OS << "({ ... ; ";
+ Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
+ OS << " })\n";
+ return;
+ }
+ }
+ // special printing for comma expressions.
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (B->getOpcode() == BO_Comma) {
+ OS << "... , ";
+ Helper->handledStmt(B->getRHS(),OS);
+ OS << '\n';
+ return;
+ }
+ }
+ }
+ S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
+
+ if (isa<CXXOperatorCallExpr>(S)) {
+ OS << " (OperatorCall)";
+ } else if (isa<CXXBindTemporaryExpr>(S)) {
+ OS << " (BindTemporary)";
+ }
+
+ // Expressions need a newline.
+ if (isa<Expr>(S))
+ OS << '\n';
+
+ } else if (CFGInitializer IE = E.getAs<CFGInitializer>()) {
+ CXXCtorInitializer* I = IE;
+ if (I->isBaseInitializer())
+ OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
+ else OS << I->getAnyMember()->getName();
+
+ OS << "(";
+ if (Expr* IE = I->getInit())
+ IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
+ OS << ")";
+
+ if (I->isBaseInitializer())
+ OS << " (Base initializer)\n";
+ else OS << " (Member initializer)\n";
+
+ } else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){
+ VarDecl* VD = DE.getVarDecl();
+ Helper->handleDecl(VD, OS);
+
+ const Type* T = VD->getType().getTypePtr();
+ if (const ReferenceType* RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType().getTypePtr();
+ else if (const Type *ET = T->getArrayElementTypeNoTypeQual())
+ T = ET;
+
+ OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
+ OS << " (Implicit destructor)\n";
+
+ } else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) {
+ const CXXBaseSpecifier *BS = BE.getBaseSpecifier();
+ OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
+ OS << " (Base object destructor)\n";
+
+ } else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) {
+ FieldDecl *FD = ME.getFieldDecl();
+
+ const Type *T = FD->getType().getTypePtr();
+ if (const Type *ET = T->getArrayElementTypeNoTypeQual())
+ T = ET;
+
+ OS << "this->" << FD->getName();
+ OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
+ OS << " (Member object destructor)\n";
+
+ } else if (CFGTemporaryDtor TE = E.getAs<CFGTemporaryDtor>()) {
+ CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr();
+ OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()";
+ OS << " (Temporary object destructor)\n";
+ }
+}
+
+static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
+ const CFGBlock& B,
+ StmtPrinterHelper* Helper, bool print_edges) {
+
+ if (Helper) Helper->setBlockID(B.getBlockID());
+
+ // Print the header.
+ OS << "\n [ B" << B.getBlockID();
+
+ if (&B == &cfg->getEntry())
+ OS << " (ENTRY) ]\n";
+ else if (&B == &cfg->getExit())
+ OS << " (EXIT) ]\n";
+ else if (&B == cfg->getIndirectGotoBlock())
+ OS << " (INDIRECT GOTO DISPATCH) ]\n";
+ else
+ OS << " ]\n";
+
+ // Print the label of this block.
+ if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) {
+
+ if (print_edges)
+ OS << " ";
+
+ if (LabelStmt* L = dyn_cast<LabelStmt>(Label))
+ OS << L->getName();
+ else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
+ OS << "case ";
+ C->getLHS()->printPretty(OS, Helper,
+ PrintingPolicy(Helper->getLangOpts()));
+ if (C->getRHS()) {
+ OS << " ... ";
+ C->getRHS()->printPretty(OS, Helper,
+ PrintingPolicy(Helper->getLangOpts()));
+ }
+ } else if (isa<DefaultStmt>(Label))
+ OS << "default";
+ else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
+ OS << "catch (";
+ if (CS->getExceptionDecl())
+ CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()),
+ 0);
+ else
+ OS << "...";
+ OS << ")";
+
+ } else
+ assert(false && "Invalid label statement in CFGBlock.");
+
+ OS << ":\n";
+ }
+
+ // Iterate through the statements in the block and print them.
+ unsigned j = 1;
+
+ for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
+ I != E ; ++I, ++j ) {
+
+ // Print the statement # in the basic block and the statement itself.
+ if (print_edges)
+ OS << " ";
+
+ OS << llvm::format("%3d", j) << ": ";
+
+ if (Helper)
+ Helper->setStmtID(j);
+
+ print_elem(OS,Helper,*I);
+ }
+
+ // Print the terminator of this block.
+ if (B.getTerminator()) {
+ if (print_edges)
+ OS << " ";
+
+ OS << " T: ";
+
+ if (Helper) Helper->setBlockID(-1);
+
+ CFGBlockTerminatorPrint TPrinter(OS, Helper,
+ PrintingPolicy(Helper->getLangOpts()));
+ TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt()));
+ OS << '\n';
+ }
+
+ if (print_edges) {
+ // Print the predecessors of this block.
+ OS << " Predecessors (" << B.pred_size() << "):";
+ unsigned i = 0;
+
+ for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
+ I != E; ++I, ++i) {
+
+ if (i == 8 || (i-8) == 0)
+ OS << "\n ";
+
+ OS << " B" << (*I)->getBlockID();
+ }
+
+ OS << '\n';
+
+ // Print the successors of this block.
+ OS << " Successors (" << B.succ_size() << "):";
+ i = 0;
+
+ for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
+ I != E; ++I, ++i) {
+
+ if (i == 8 || (i-8) % 10 == 0)
+ OS << "\n ";
+
+ if (*I)
+ OS << " B" << (*I)->getBlockID();
+ else
+ OS << " NULL";
+ }
+
+ OS << '\n';
+ }
+}
+
+
+/// dump - A simple pretty printer of a CFG that outputs to stderr.
+void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); }
+
+/// print - A simple pretty printer of a CFG that outputs to an ostream.
+void CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const {
+ StmtPrinterHelper Helper(this, LO);
+
+ // Print the entry block.
+ print_block(OS, this, getEntry(), &Helper, true);
+
+ // Iterate through the CFGBlocks and print them one by one.
+ for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
+ // Skip the entry block, because we already printed it.
+ if (&(**I) == &getEntry() || &(**I) == &getExit())
+ continue;
+
+ print_block(OS, this, **I, &Helper, true);
+ }
+
+ // Print the exit block.
+ print_block(OS, this, getExit(), &Helper, true);
+ OS.flush();
+}
+
+/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
+void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const {
+ print(llvm::errs(), cfg, LO);
+}
+
+/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
+/// Generally this will only be called from CFG::print.
+void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg,
+ const LangOptions &LO) const {
+ StmtPrinterHelper Helper(cfg, LO);
+ print_block(OS, cfg, *this, &Helper, true);
+}
+
+/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
+void CFGBlock::printTerminator(llvm::raw_ostream &OS,
+ const LangOptions &LO) const {
+ CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
+ TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt()));
+}
+
+Stmt* CFGBlock::getTerminatorCondition() {
+ Stmt *Terminator = this->Terminator;
+ if (!Terminator)
+ return NULL;
+
+ Expr* E = NULL;
+
+ switch (Terminator->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::ForStmtClass:
+ E = cast<ForStmt>(Terminator)->getCond();
+ break;
+
+ case Stmt::WhileStmtClass:
+ E = cast<WhileStmt>(Terminator)->getCond();
+ break;
+
+ case Stmt::DoStmtClass:
+ E = cast<DoStmt>(Terminator)->getCond();
+ break;
+
+ case Stmt::IfStmtClass:
+ E = cast<IfStmt>(Terminator)->getCond();
+ break;
+
+ case Stmt::ChooseExprClass:
+ E = cast<ChooseExpr>(Terminator)->getCond();
+ break;
+
+ case Stmt::IndirectGotoStmtClass:
+ E = cast<IndirectGotoStmt>(Terminator)->getTarget();
+ break;
+
+ case Stmt::SwitchStmtClass:
+ E = cast<SwitchStmt>(Terminator)->getCond();
+ break;
+
+ case Stmt::BinaryConditionalOperatorClass:
+ E = cast<BinaryConditionalOperator>(Terminator)->getCond();
+ break;
+
+ case Stmt::ConditionalOperatorClass:
+ E = cast<ConditionalOperator>(Terminator)->getCond();
+ break;
+
+ case Stmt::BinaryOperatorClass: // '&&' and '||'
+ E = cast<BinaryOperator>(Terminator)->getLHS();
+ break;
+
+ case Stmt::ObjCForCollectionStmtClass:
+ return Terminator;
+ }
+
+ return E ? E->IgnoreParens() : NULL;
+}
+
+bool CFGBlock::hasBinaryBranchTerminator() const {
+ const Stmt *Terminator = this->Terminator;
+ if (!Terminator)
+ return false;
+
+ Expr* E = NULL;
+
+ switch (Terminator->getStmtClass()) {
+ default:
+ return false;
+
+ case Stmt::ForStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::IfStmtClass:
+ case Stmt::ChooseExprClass:
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryOperatorClass:
+ return true;
+ }
+
+ return E ? E->IgnoreParens() : NULL;
+}
+
+
+//===----------------------------------------------------------------------===//
+// CFG Graphviz Visualization
+//===----------------------------------------------------------------------===//
+
+
+#ifndef NDEBUG
+static StmtPrinterHelper* GraphHelper;
+#endif
+
+void CFG::viewCFG(const LangOptions &LO) const {
+#ifndef NDEBUG
+ StmtPrinterHelper H(this, LO);
+ GraphHelper = &H;
+ llvm::ViewGraph(this,"CFG");
+ GraphHelper = NULL;
+#endif
+}
+
+namespace llvm {
+template<>
+struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
+
+ DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+
+ static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
+
+#ifndef NDEBUG
+ std::string OutSStr;
+ llvm::raw_string_ostream Out(OutSStr);
+ print_block(Out,Graph, *Node, GraphHelper, false);
+ std::string& OutStr = Out.str();
+
+ if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
+
+ // Process string output to make it nicer...
+ for (unsigned i = 0; i != OutStr.length(); ++i)
+ if (OutStr[i] == '\n') { // Left justify
+ OutStr[i] = '\\';
+ OutStr.insert(OutStr.begin()+i+1, 'l');
+ }
+
+ return OutStr;
+#else
+ return "";
+#endif
+ }
+};
+} // end namespace llvm
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp
new file mode 100644
index 0000000..3a030f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFGStmtMap.cpp
@@ -0,0 +1,91 @@
+//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CFGStmtMap class, which defines a mapping from
+// Stmt* to CFGBlock*
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
+
+using namespace clang;
+
+typedef llvm::DenseMap<Stmt*,CFGBlock*> SMap;
+static SMap *AsMap(void *m) { return (SMap*) m; }
+
+CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
+
+CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
+ SMap *SM = AsMap(M);
+ Stmt *X = S;
+
+ // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
+ // is in the map.
+ while (X) {
+ SMap::iterator I = SM->find(X);
+ if (I != SM->end()) {
+ CFGBlock *B = I->second;
+ // Memoize this lookup.
+ if (X != S)
+ (*SM)[X] = B;
+ return B;
+ }
+
+ X = PM->getParentIgnoreParens(X);
+ }
+
+ return 0;
+}
+
+static void Accumulate(SMap &SM, CFGBlock *B) {
+ // First walk the block-level expressions.
+ for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
+ const CFGElement &CE = *I;
+ CFGStmt CS = CE.getAs<CFGStmt>();
+ if (!CS.isValid())
+ continue;
+
+ CFGBlock *&Entry = SM[CS];
+ // If 'Entry' is already initialized (e.g., a terminator was already),
+ // skip.
+ if (Entry)
+ continue;
+
+ Entry = B;
+
+ }
+
+ // Look at the label of the block.
+ if (Stmt *Label = B->getLabel())
+ SM[Label] = B;
+
+ // Finally, look at the terminator. If the terminator was already added
+ // because it is a block-level expression in another block, overwrite
+ // that mapping.
+ if (Stmt *Term = B->getTerminator())
+ SM[Term] = B;
+}
+
+CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
+ if (!C || !PM)
+ return 0;
+
+ SMap *SM = new SMap();
+
+ // Walk all blocks, accumulating the block-level expressions, labels,
+ // and terminators.
+ for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
+ Accumulate(*SM, *I);
+
+ return new CFGStmtMap(PM, SM);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
new file mode 100644
index 0000000..22b6c1a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/CocoaConventions.cpp
@@ -0,0 +1,180 @@
+//===- CocoaConventions.h - Special handling of Cocoa conventions -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+using namespace ento;
+
+using llvm::StringRef;
+
+// The "fundamental rule" for naming conventions of methods:
+// (url broken into two lines)
+// http://developer.apple.com/documentation/Cocoa/Conceptual/
+// MemoryMgmt/Tasks/MemoryManagementRules.html
+//
+// "You take ownership of an object if you create it using a method whose name
+// begins with "alloc" or "new" or contains "copy" (for example, alloc,
+// newObject, or mutableCopy), or if you send it a retain message. You are
+// responsible for relinquishing ownership of objects you own using release
+// or autorelease. Any other time you receive an object, you must
+// not release it."
+//
+
+static bool isWordEnd(char ch, char prev, char next) {
+ return ch == '\0'
+ || (islower(prev) && isupper(ch)) // xxxC
+ || (isupper(prev) && isupper(ch) && islower(next)) // XXCreate
+ || !isalpha(ch);
+}
+
+static const char* parseWord(const char* s) {
+ char ch = *s, prev = '\0';
+ assert(ch != '\0');
+ char next = *(s+1);
+ while (!isWordEnd(ch, prev, next)) {
+ prev = ch;
+ ch = next;
+ next = *((++s)+1);
+ }
+ return s;
+}
+
+cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S,
+ bool ignorePrefix) {
+ IdentifierInfo *II = S.getIdentifierInfoForSlot(0);
+
+ if (!II)
+ return NoConvention;
+
+ const char *s = II->getNameStart();
+
+ const char *orig = s;
+ // A method/function name may contain a prefix. We don't know it is there,
+ // however, until we encounter the first '_'.
+ while (*s != '\0') {
+ // Skip '_', numbers, ':', etc.
+ if (*s == '_' || !isalpha(*s)) {
+ ++s;
+ continue;
+ }
+ break;
+ }
+
+ if (!ignorePrefix && s != orig)
+ return NoConvention;
+
+ // Parse the first word, and look for specific keywords.
+ const char *wordEnd = parseWord(s);
+ assert(wordEnd > s);
+ unsigned len = wordEnd - s;
+
+ switch (len) {
+ default:
+ return NoConvention;
+ case 3:
+ // Methods starting with 'new' follow the create rule.
+ return (memcmp(s, "new", 3) == 0) ? CreateRule : NoConvention;
+ case 4:
+ // Methods starting with 'copy' follow the create rule.
+ if (memcmp(s, "copy", 4) == 0)
+ return CreateRule;
+ // Methods starting with 'init' follow the init rule.
+ if (memcmp(s, "init", 4) == 0)
+ return InitRule;
+ return NoConvention;
+ case 5:
+ return (memcmp(s, "alloc", 5) == 0) ? CreateRule : NoConvention;
+ case 7:
+ // Methods starting with 'mutableCopy' follow the create rule.
+ if (memcmp(s, "mutable", 7) == 0) {
+ // Look at the next word to see if it is "Copy".
+ s = wordEnd;
+ if (*s != '\0') {
+ wordEnd = parseWord(s);
+ len = wordEnd - s;
+ if (len == 4 && memcmp(s, "Copy", 4) == 0)
+ return CreateRule;
+ }
+ }
+ return NoConvention;
+ }
+}
+
+bool cocoa::isRefType(QualType RetTy, llvm::StringRef Prefix,
+ llvm::StringRef Name) {
+ // Recursively walk the typedef stack, allowing typedefs of reference types.
+ while (const TypedefType *TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
+ llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
+ if (TDName.startswith(Prefix) && TDName.endswith("Ref"))
+ return true;
+
+ RetTy = TD->getDecl()->getUnderlyingType();
+ }
+
+ if (Name.empty())
+ return false;
+
+ // Is the type void*?
+ const PointerType* PT = RetTy->getAs<PointerType>();
+ if (!(PT->getPointeeType().getUnqualifiedType()->isVoidType()))
+ return false;
+
+ // Does the name start with the prefix?
+ return Name.startswith(Prefix);
+}
+
+bool cocoa::isCFObjectRef(QualType T) {
+ return isRefType(T, "CF") || // Core Foundation.
+ isRefType(T, "CG") || // Core Graphics.
+ isRefType(T, "DADisk") || // Disk Arbitration API.
+ isRefType(T, "DADissenter") ||
+ isRefType(T, "DASessionRef");
+}
+
+
+bool cocoa::isCocoaObjectRef(QualType Ty) {
+ if (!Ty->isObjCObjectPointerType())
+ return false;
+
+ const ObjCObjectPointerType *PT = Ty->getAs<ObjCObjectPointerType>();
+
+ // Can be true for objects with the 'NSObject' attribute.
+ if (!PT)
+ return true;
+
+ // We assume that id<..>, id, Class, and Class<..> all represent tracked
+ // objects.
+ if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
+ PT->isObjCClassType() || PT->isObjCQualifiedClassType())
+ return true;
+
+ // Does the interface subclass NSObject?
+ // FIXME: We can memoize here if this gets too expensive.
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+
+ // Assume that anything declared with a forward declaration and no
+ // @interface subclasses NSObject.
+ if (ID->isForwardDecl())
+ return true;
+
+ for ( ; ID ; ID = ID->getSuperClass())
+ if (ID->getIdentifier()->getName() == "NSObject")
+ return true;
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
new file mode 100644
index 0000000..a6d6108
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/FormatString.cpp
@@ -0,0 +1,476 @@
+// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared details for processing format strings of printf and scanf
+// (and friends).
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatStringParsing.h"
+
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::FormatSpecifier;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::PositionContext;
+using clang::analyze_format_string::ConversionSpecifier;
+using namespace clang;
+
+// Key function to FormatStringHandler.
+FormatStringHandler::~FormatStringHandler() {}
+
+//===----------------------------------------------------------------------===//
+// Functions for parsing format strings components in both printf and
+// scanf format strings.
+//===----------------------------------------------------------------------===//
+
+OptionalAmount
+clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
+ const char *I = Beg;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ unsigned accumulator = 0;
+ bool hasDigits = false;
+
+ for ( ; I != E; ++I) {
+ char c = *I;
+ if (c >= '0' && c <= '9') {
+ hasDigits = true;
+ accumulator = (accumulator * 10) + (c - '0');
+ continue;
+ }
+
+ if (hasDigits)
+ return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
+ false);
+
+ break;
+ }
+
+ return OptionalAmount();
+}
+
+OptionalAmount
+clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
+ const char *E,
+ unsigned &argIndex) {
+ if (*Beg == '*') {
+ ++Beg;
+ return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
+ }
+
+ return ParseAmount(Beg, E);
+}
+
+OptionalAmount
+clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
+ const char *Start,
+ const char *&Beg,
+ const char *E,
+ PositionContext p) {
+ if (*Beg == '*') {
+ const char *I = Beg + 1;
+ const OptionalAmount &Amt = ParseAmount(I, E);
+
+ if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
+ H.HandleInvalidPosition(Beg, I - Beg, p);
+ return OptionalAmount(false);
+ }
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return OptionalAmount(false);
+ }
+
+ assert(Amt.getHowSpecified() == OptionalAmount::Constant);
+
+ if (*I == '$') {
+ // Handle positional arguments
+
+ // Special case: '*0$', since this is an easy mistake.
+ if (Amt.getConstantAmount() == 0) {
+ H.HandleZeroPosition(Beg, I - Beg + 1);
+ return OptionalAmount(false);
+ }
+
+ const char *Tmp = Beg;
+ Beg = ++I;
+
+ return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
+ Tmp, 0, true);
+ }
+
+ H.HandleInvalidPosition(Beg, I - Beg, p);
+ return OptionalAmount(false);
+ }
+
+ return ParseAmount(Beg, E);
+}
+
+
+bool
+clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
+ FormatSpecifier &CS,
+ const char *Start,
+ const char *&Beg, const char *E,
+ unsigned *argIndex) {
+ // FIXME: Support negative field widths.
+ if (argIndex) {
+ CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
+ }
+ else {
+ const OptionalAmount Amt =
+ ParsePositionAmount(H, Start, Beg, E,
+ analyze_format_string::FieldWidthPos);
+
+ if (Amt.isInvalid())
+ return true;
+ CS.setFieldWidth(Amt);
+ }
+ return false;
+}
+
+bool
+clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
+ FormatSpecifier &FS,
+ const char *Start,
+ const char *&Beg,
+ const char *E) {
+ const char *I = Beg;
+
+ const OptionalAmount &Amt = ParseAmount(I, E);
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
+ // Special case: '%0$', since this is an easy mistake.
+ if (Amt.getConstantAmount() == 0) {
+ H.HandleZeroPosition(Start, I - Start);
+ return true;
+ }
+
+ FS.setArgIndex(Amt.getConstantAmount() - 1);
+ FS.setUsesPositionalArg();
+ // Update the caller's pointer if we decided to consume
+ // these characters.
+ Beg = I;
+ return false;
+ }
+
+ return false;
+}
+
+bool
+clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
+ const char *&I,
+ const char *E) {
+ LengthModifier::Kind lmKind = LengthModifier::None;
+ const char *lmPosition = I;
+ switch (*I) {
+ default:
+ return false;
+ case 'h':
+ ++I;
+ lmKind = (I != E && *I == 'h') ?
+ ++I, LengthModifier::AsChar : LengthModifier::AsShort;
+ break;
+ case 'l':
+ ++I;
+ lmKind = (I != E && *I == 'l') ?
+ ++I, LengthModifier::AsLongLong : LengthModifier::AsLong;
+ break;
+ case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
+ case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
+ case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
+ case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
+ case 'q': lmKind = LengthModifier::AsLongLong; ++I; break;
+ }
+ LengthModifier lm(lmPosition, lmKind);
+ FS.setLengthModifier(lm);
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on ArgTypeResult.
+//===----------------------------------------------------------------------===//
+
+bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
+ switch (K) {
+ case InvalidTy:
+ assert(false && "ArgTypeResult must be valid");
+ return true;
+
+ case UnknownTy:
+ return true;
+
+ case SpecificTy: {
+ argTy = C.getCanonicalType(argTy).getUnqualifiedType();
+ if (T == argTy)
+ return true;
+ if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ default:
+ break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return T == C.UnsignedCharTy;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return T == C.SignedCharTy;
+ case BuiltinType::Short:
+ return T == C.UnsignedShortTy;
+ case BuiltinType::UShort:
+ return T == C.ShortTy;
+ case BuiltinType::Int:
+ return T == C.UnsignedIntTy;
+ case BuiltinType::UInt:
+ return T == C.IntTy;
+ case BuiltinType::Long:
+ return T == C.UnsignedLongTy;
+ case BuiltinType::ULong:
+ return T == C.LongTy;
+ case BuiltinType::LongLong:
+ return T == C.UnsignedLongLongTy;
+ case BuiltinType::ULongLong:
+ return T == C.LongLongTy;
+ }
+ return false;
+ }
+
+ case CStrTy: {
+ const PointerType *PT = argTy->getAs<PointerType>();
+ if (!PT)
+ return false;
+ QualType pointeeTy = PT->getPointeeType();
+ if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ case WCStrTy: {
+ const PointerType *PT = argTy->getAs<PointerType>();
+ if (!PT)
+ return false;
+ QualType pointeeTy =
+ C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
+ return pointeeTy == C.getWCharType();
+ }
+
+ case WIntTy: {
+ // Instead of doing a lookup for the definition of 'wint_t' (which
+ // is defined by the system headers) instead see if wchar_t and
+ // the argument type promote to the same type.
+ QualType PromoWChar =
+ C.getWCharType()->isPromotableIntegerType()
+ ? C.getPromotedIntegerType(C.getWCharType()) : C.getWCharType();
+ QualType PromoArg =
+ argTy->isPromotableIntegerType()
+ ? C.getPromotedIntegerType(argTy) : argTy;
+
+ PromoWChar = C.getCanonicalType(PromoWChar).getUnqualifiedType();
+ PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
+
+ return PromoWChar == PromoArg;
+ }
+
+ case CPointerTy:
+ return argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
+ argTy->isNullPtrType();
+
+ case ObjCPointerTy:
+ return argTy->getAs<ObjCObjectPointerType>() != NULL;
+ }
+
+ // FIXME: Should be unreachable, but Clang is currently emitting
+ // a warning.
+ return false;
+}
+
+QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
+ switch (K) {
+ case InvalidTy:
+ assert(false && "No representative type for Invalid ArgTypeResult");
+ // Fall-through.
+ case UnknownTy:
+ return QualType();
+ case SpecificTy:
+ return T;
+ case CStrTy:
+ return C.getPointerType(C.CharTy);
+ case WCStrTy:
+ return C.getPointerType(C.getWCharType());
+ case ObjCPointerTy:
+ return C.ObjCBuiltinIdTy;
+ case CPointerTy:
+ return C.VoidPtrTy;
+ case WIntTy: {
+ QualType WC = C.getWCharType();
+ return WC->isPromotableIntegerType() ? C.getPromotedIntegerType(WC) : WC;
+ }
+ }
+
+ // FIXME: Should be unreachable, but Clang is currently emitting
+ // a warning.
+ return QualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on OptionalAmount.
+//===----------------------------------------------------------------------===//
+
+ArgTypeResult
+analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
+ return Ctx.IntTy;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on LengthModifier.
+//===----------------------------------------------------------------------===//
+
+const char *
+analyze_format_string::LengthModifier::toString() const {
+ switch (kind) {
+ case AsChar:
+ return "hh";
+ case AsShort:
+ return "h";
+ case AsLong: // or AsWideChar
+ return "l";
+ case AsLongLong:
+ return "ll";
+ case AsIntMax:
+ return "j";
+ case AsSizeT:
+ return "z";
+ case AsPtrDiff:
+ return "t";
+ case AsLongDouble:
+ return "L";
+ case None:
+ return "";
+ }
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on OptionalAmount.
+//===----------------------------------------------------------------------===//
+
+void OptionalAmount::toString(llvm::raw_ostream &os) const {
+ switch (hs) {
+ case Invalid:
+ case NotSpecified:
+ return;
+ case Arg:
+ if (UsesDotPrefix)
+ os << ".";
+ if (usesPositionalArg())
+ os << "*" << getPositionalArgIndex() << "$";
+ else
+ os << "*";
+ break;
+ case Constant:
+ if (UsesDotPrefix)
+ os << ".";
+ os << amt;
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on ConversionSpecifier.
+//===----------------------------------------------------------------------===//
+
+bool FormatSpecifier::hasValidLengthModifier() const {
+ switch (LM.getKind()) {
+ case LengthModifier::None:
+ return true;
+
+ // Handle most integer flags
+ case LengthModifier::AsChar:
+ case LengthModifier::AsShort:
+ case LengthModifier::AsLongLong:
+ case LengthModifier::AsIntMax:
+ case LengthModifier::AsSizeT:
+ case LengthModifier::AsPtrDiff:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::nArg:
+ case ConversionSpecifier::rArg:
+ return true;
+ default:
+ return false;
+ }
+
+ // Handle 'l' flag
+ case LengthModifier::AsLong:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::nArg:
+ case ConversionSpecifier::cArg:
+ case ConversionSpecifier::sArg:
+ case ConversionSpecifier::rArg:
+ return true;
+ default:
+ return false;
+ }
+
+ case LengthModifier::AsLongDouble:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h b/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h
new file mode 100644
index 0000000..607e99c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/FormatStringParsing.h
@@ -0,0 +1,72 @@
+#ifndef LLVM_CLANG_FORMAT_PARSING_H
+#define LLVM_CLANG_FORMAT_PARSING_H
+
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+template <typename T>
+class UpdateOnReturn {
+ T &ValueToUpdate;
+ const T &ValueToCopy;
+public:
+ UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
+ : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
+
+ ~UpdateOnReturn() {
+ ValueToUpdate = ValueToCopy;
+ }
+};
+
+namespace analyze_format_string {
+
+OptionalAmount ParseAmount(const char *&Beg, const char *E);
+OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
+ unsigned &argIndex);
+
+OptionalAmount ParsePositionAmount(FormatStringHandler &H,
+ const char *Start, const char *&Beg,
+ const char *E, PositionContext p);
+
+bool ParseFieldWidth(FormatStringHandler &H,
+ FormatSpecifier &CS,
+ const char *Start, const char *&Beg, const char *E,
+ unsigned *argIndex);
+
+bool ParseArgPosition(FormatStringHandler &H,
+ FormatSpecifier &CS, const char *Start,
+ const char *&Beg, const char *E);
+
+/// Returns true if a LengthModifier was parsed and installed in the
+/// FormatSpecifier& argument, and false otherwise.
+bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E);
+
+template <typename T> class SpecifierResult {
+ T FS;
+ const char *Start;
+ bool Stop;
+public:
+ SpecifierResult(bool stop = false)
+ : Start(0), Stop(stop) {}
+ SpecifierResult(const char *start,
+ const T &fs)
+ : FS(fs), Start(start), Stop(false) {}
+
+ const char *getStart() const { return Start; }
+ bool shouldStop() const { return Stop; }
+ bool hasValue() const { return Start != 0; }
+ const T &getValue() const {
+ assert(hasValue());
+ return FS;
+ }
+ const T &getValue() { return FS; }
+};
+
+} // end analyze_format_string namespace
+} // end clang namespace
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
new file mode 100644
index 0000000..303dc0f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/LiveVariables.cpp
@@ -0,0 +1,392 @@
+//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs -*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Live Variables analysis for source-level CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "clang/Analysis/FlowSensitive/DataflowSolver.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Useful constants.
+//===----------------------------------------------------------------------===//
+
+static const bool Alive = true;
+static const bool Dead = false;
+
+//===----------------------------------------------------------------------===//
+// Dataflow initialization logic.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RegisterDecls
+ : public CFGRecStmtDeclVisitor<RegisterDecls> {
+
+ LiveVariables::AnalysisDataTy& AD;
+
+ typedef llvm::SmallVector<VarDecl*, 20> AlwaysLiveTy;
+ AlwaysLiveTy AlwaysLive;
+
+
+public:
+ RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+
+ ~RegisterDecls() {
+
+ AD.AlwaysLive.resetValues(AD);
+
+ for (AlwaysLiveTy::iterator I = AlwaysLive.begin(), E = AlwaysLive.end();
+ I != E; ++ I)
+ AD.AlwaysLive(*I, AD) = Alive;
+ }
+
+ void VisitImplicitParamDecl(ImplicitParamDecl* IPD) {
+ // Register the VarDecl for tracking.
+ AD.Register(IPD);
+ }
+
+ void VisitVarDecl(VarDecl* VD) {
+ // Register the VarDecl for tracking.
+ AD.Register(VD);
+
+ // Does the variable have global storage? If so, it is always live.
+ if (VD->hasGlobalStorage())
+ AlwaysLive.push_back(VD);
+ }
+
+ CFG& getCFG() { return AD.getCFG(); }
+};
+} // end anonymous namespace
+
+LiveVariables::LiveVariables(AnalysisContext &AC, bool killAtAssign) {
+ // Register all referenced VarDecls.
+ CFG &cfg = *AC.getCFG();
+ getAnalysisData().setCFG(cfg);
+ getAnalysisData().setContext(AC.getASTContext());
+ getAnalysisData().AC = &AC;
+ getAnalysisData().killAtAssign = killAtAssign;
+
+ RegisterDecls R(getAnalysisData());
+ cfg.VisitBlockStmts(R);
+
+ // Register all parameters even if they didn't occur in the function body.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(AC.getDecl()))
+ for (FunctionDecl::param_const_iterator PI = FD->param_begin(),
+ PE = FD->param_end(); PI != PE; ++PI)
+ getAnalysisData().Register(*PI);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class TransferFuncs : public CFGRecStmtVisitor<TransferFuncs>{
+ LiveVariables::AnalysisDataTy& AD;
+ LiveVariables::ValTy LiveState;
+ const CFGBlock *currentBlock;
+public:
+ TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad), currentBlock(0) {}
+
+ LiveVariables::ValTy& getVal() { return LiveState; }
+ CFG& getCFG() { return AD.getCFG(); }
+
+ void VisitDeclRefExpr(DeclRefExpr* DR);
+ void VisitBinaryOperator(BinaryOperator* B);
+ void VisitBlockExpr(BlockExpr *B);
+ void VisitAssign(BinaryOperator* B);
+ void VisitDeclStmt(DeclStmt* DS);
+ void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S);
+ void VisitUnaryOperator(UnaryOperator* U);
+ void Visit(Stmt *S);
+ void VisitTerminator(CFGBlock* B);
+
+ /// VisitConditionVariableInit - Handle the initialization of condition
+ /// variables at branches. Valid statements include IfStmt, ForStmt,
+ /// WhileStmt, and SwitchStmt.
+ void VisitConditionVariableInit(Stmt *S);
+
+ void SetTopValue(LiveVariables::ValTy& V) {
+ V = AD.AlwaysLive;
+ }
+
+ void setCurrentBlock(const CFGBlock *block) {
+ currentBlock = block;
+ }
+};
+
+void TransferFuncs::Visit(Stmt *S) {
+
+ if (S == getCurrentBlkStmt()) {
+
+ if (AD.Observer)
+ AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
+
+ if (getCFG().isBlkExpr(S))
+ LiveState(S, AD) = Dead;
+
+ StmtVisitor<TransferFuncs,void>::Visit(S);
+ }
+ else if (!getCFG().isBlkExpr(S)) {
+
+ if (AD.Observer)
+ AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
+
+ StmtVisitor<TransferFuncs,void>::Visit(S);
+
+ }
+ else {
+ // For block-level expressions, mark that they are live.
+ LiveState(S,AD) = Alive;
+ }
+}
+
+void TransferFuncs::VisitConditionVariableInit(Stmt *S) {
+ assert(!getCFG().isBlkExpr(S));
+ CFGRecStmtVisitor<TransferFuncs>::VisitConditionVariableInit(S);
+}
+
+void TransferFuncs::VisitTerminator(CFGBlock* B) {
+
+ const Stmt* E = B->getTerminatorCondition();
+
+ if (!E)
+ return;
+
+ assert (getCFG().isBlkExpr(E));
+ LiveState(E, AD) = Alive;
+}
+
+void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
+ if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
+ LiveState(V, AD) = Alive;
+}
+
+void TransferFuncs::VisitBlockExpr(BlockExpr *BE) {
+ AnalysisContext::referenced_decls_iterator I, E;
+ llvm::tie(I, E) = AD.AC->getReferencedBlockVars(BE->getBlockDecl());
+ for ( ; I != E ; ++I) {
+ DeclBitVector_Types::Idx i = AD.getIdx(*I);
+ if (i.isValid())
+ LiveState.getBit(i) = Alive;
+ }
+}
+
+void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
+ if (B->isAssignmentOp()) VisitAssign(B);
+ else VisitStmt(B);
+}
+
+void
+TransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+
+ // This is a block-level expression. Its value is 'dead' before this point.
+ LiveState(S, AD) = Dead;
+
+ // This represents a 'use' of the collection.
+ Visit(S->getCollection());
+
+ // This represents a 'kill' for the variable.
+ Stmt* Element = S->getElement();
+ DeclRefExpr* DR = 0;
+ VarDecl* VD = 0;
+
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(Element))
+ VD = cast<VarDecl>(DS->getSingleDecl());
+ else {
+ Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens();
+ if ((DR = dyn_cast<DeclRefExpr>(ElemExpr)))
+ VD = cast<VarDecl>(DR->getDecl());
+ else {
+ Visit(ElemExpr);
+ return;
+ }
+ }
+
+ if (VD) {
+ LiveState(VD, AD) = Dead;
+ if (AD.Observer && DR) { AD.Observer->ObserverKill(DR); }
+ }
+}
+
+
+void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
+ Expr *E = U->getSubExpr();
+
+ switch (U->getOpcode()) {
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ // Walk through the subexpressions, blasting through ParenExprs
+ // until we either find a DeclRefExpr or some non-DeclRefExpr
+ // expression.
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParens()))
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Treat the --/++ operator as a kill.
+ if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+ LiveState(VD, AD) = Alive;
+ return VisitDeclRefExpr(DR);
+ }
+
+ // Fall-through.
+
+ default:
+ return Visit(E);
+ }
+}
+
+void TransferFuncs::VisitAssign(BinaryOperator* B) {
+ Expr* LHS = B->getLHS();
+
+ // Assigning to a variable?
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParens())) {
+ // Assignments to references don't kill the ref's address
+ if (DR->getDecl()->getType()->isReferenceType()) {
+ VisitDeclRefExpr(DR);
+ } else {
+ if (AD.killAtAssign) {
+ // Update liveness inforamtion.
+ unsigned bit = AD.getIdx(DR->getDecl());
+ LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
+
+ if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+ }
+ // Handle things like +=, etc., which also generate "uses"
+ // of a variable. Do this just by visiting the subexpression.
+ if (B->getOpcode() != BO_Assign)
+ VisitDeclRefExpr(DR);
+ }
+ }
+ else // Not assigning to a variable. Process LHS as usual.
+ Visit(LHS);
+
+ Visit(B->getRHS());
+}
+
+void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
+ // Declarations effectively "kill" a variable since they cannot
+ // possibly be live before they are declared.
+ for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI)
+ if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) {
+ // Update liveness information by killing the VarDecl.
+ unsigned bit = AD.getIdx(VD);
+ LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
+
+ // The initializer is evaluated after the variable comes into scope, but
+ // before the DeclStmt (which binds the value to the variable).
+ // Since this is a reverse dataflow analysis, we must evaluate the
+ // transfer function for this expression after the DeclStmt. If the
+ // initializer references the variable (which is bad) then we extend
+ // its liveness.
+ if (Expr* Init = VD->getInit())
+ Visit(Init);
+
+ if (const VariableArrayType* VT =
+ AD.getContext().getAsVariableArrayType(VD->getType())) {
+ StmtIterator I(const_cast<VariableArrayType*>(VT));
+ StmtIterator E;
+ for (; I != E; ++I) Visit(*I);
+ }
+ }
+}
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Merge operator: if something is live on any successor block, it is live
+// in the current block (a set union).
+//===----------------------------------------------------------------------===//
+
+namespace {
+ typedef StmtDeclBitVector_Types::Union Merge;
+ typedef DataflowSolver<LiveVariables, TransferFuncs, Merge> Solver;
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// External interface to run Liveness analysis.
+//===----------------------------------------------------------------------===//
+
+void LiveVariables::runOnCFG(CFG& cfg) {
+ Solver S(*this);
+ S.runOnCFG(cfg);
+}
+
+void LiveVariables::runOnAllBlocks(const CFG& cfg,
+ LiveVariables::ObserverTy* Obs,
+ bool recordStmtValues) {
+ Solver S(*this);
+ SaveAndRestore<LiveVariables::ObserverTy*> SRObs(getAnalysisData().Observer,
+ Obs);
+ S.runOnAllBlocks(cfg, recordStmtValues);
+}
+
+//===----------------------------------------------------------------------===//
+// liveness queries
+//
+
+bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
+ DeclBitVector_Types::Idx i = getAnalysisData().getIdx(D);
+ return i.isValid() ? getBlockData(B).getBit(i) : false;
+}
+
+bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const {
+ DeclBitVector_Types::Idx i = getAnalysisData().getIdx(D);
+ return i.isValid() ? Live.getBit(i) : false;
+}
+
+bool LiveVariables::isLive(const Stmt* Loc, const Stmt* StmtVal) const {
+ return getStmtData(Loc)(StmtVal,getAnalysisData());
+}
+
+bool LiveVariables::isLive(const Stmt* Loc, const VarDecl* D) const {
+ return getStmtData(Loc)(D,getAnalysisData());
+}
+
+//===----------------------------------------------------------------------===//
+// printing liveness state for debugging
+//
+
+void LiveVariables::dumpLiveness(const ValTy& V, const SourceManager& SM) const {
+ const AnalysisDataTy& AD = getAnalysisData();
+
+ for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
+ E = AD.end_decl(); I!=E; ++I)
+ if (V.getDeclBit(I->second)) {
+ llvm::errs() << " " << I->first->getIdentifier()->getName() << " <";
+ I->first->getLocation().dump(SM);
+ llvm::errs() << ">\n";
+ }
+}
+
+void LiveVariables::dumpBlockLiveness(const SourceManager& M) const {
+ for (BlockDataMapTy::const_iterator I = getBlockDataMap().begin(),
+ E = getBlockDataMap().end(); I!=E; ++I) {
+ llvm::errs() << "\n[ B" << I->first->getBlockID()
+ << " (live variables at block exit) ]\n";
+ dumpLiveness(I->second,M);
+ }
+
+ llvm::errs() << "\n";
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
new file mode 100644
index 0000000..ef5c0fb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp
@@ -0,0 +1,668 @@
+//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handling of format string in printf and friends. The structure of format
+// strings for fprintf() are described in C99 7.19.6.1.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "FormatStringParsing.h"
+
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::ConversionSpecifier;
+using clang::analyze_printf::PrintfSpecifier;
+
+using namespace clang;
+
+typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
+ PrintfSpecifierResult;
+
+//===----------------------------------------------------------------------===//
+// Methods for parsing format strings.
+//===----------------------------------------------------------------------===//
+
+using analyze_format_string::ParseNonPositionAmount;
+
+static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
+ const char *Start, const char *&Beg, const char *E,
+ unsigned *argIndex) {
+ if (argIndex) {
+ FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
+ }
+ else {
+ const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
+ analyze_format_string::PrecisionPos);
+ if (Amt.isInvalid())
+ return true;
+ FS.setPrecision(Amt);
+ }
+ return false;
+}
+
+static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
+ const char *&Beg,
+ const char *E,
+ unsigned &argIndex,
+ bool FormatExtensions) {
+
+ using namespace clang::analyze_format_string;
+ using namespace clang::analyze_printf;
+
+ const char *I = Beg;
+ const char *Start = 0;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ // Look for a '%' character that indicates the start of a format specifier.
+ for ( ; I != E ; ++I) {
+ char c = *I;
+ if (c == '\0') {
+ // Detect spurious null characters, which are likely errors.
+ H.HandleNullChar(I);
+ return true;
+ }
+ if (c == '%') {
+ Start = I++; // Record the start of the format specifier.
+ break;
+ }
+ }
+
+ // No format specifier found?
+ if (!Start)
+ return false;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ PrintfSpecifier FS;
+ if (ParseArgPosition(H, FS, Start, I, E))
+ return true;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Look for flags (if any).
+ bool hasMore = true;
+ for ( ; I != E; ++I) {
+ switch (*I) {
+ default: hasMore = false; break;
+ case '\'':
+ // FIXME: POSIX specific. Always accept?
+ FS.setHasThousandsGrouping(I);
+ break;
+ case '-': FS.setIsLeftJustified(I); break;
+ case '+': FS.setHasPlusPrefix(I); break;
+ case ' ': FS.setHasSpacePrefix(I); break;
+ case '#': FS.setHasAlternativeForm(I); break;
+ case '0': FS.setHasLeadingZeros(I); break;
+ }
+ if (!hasMore)
+ break;
+ }
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Look for the field width (if any).
+ if (ParseFieldWidth(H, FS, Start, I, E,
+ FS.usesPositionalArg() ? 0 : &argIndex))
+ return true;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Look for the precision (if any).
+ if (*I == '.') {
+ ++I;
+ if (I == E) {
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ if (ParsePrecision(H, FS, Start, I, E,
+ FS.usesPositionalArg() ? 0 : &argIndex))
+ return true;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+
+ // Look for the length modifier.
+ if (ParseLengthModifier(FS, I, E) && I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ if (*I == '\0') {
+ // Detect spurious null characters, which are likely errors.
+ H.HandleNullChar(I);
+ return true;
+ }
+
+ // Finally, look for the conversion specifier.
+ const char *conversionPosition = I++;
+ ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
+ switch (*conversionPosition) {
+ default:
+ break;
+ // C99: 7.19.6.1 (section 8).
+ case '%': k = ConversionSpecifier::PercentArg; break;
+ case 'A': k = ConversionSpecifier::AArg; break;
+ case 'E': k = ConversionSpecifier::EArg; break;
+ case 'F': k = ConversionSpecifier::FArg; break;
+ case 'G': k = ConversionSpecifier::GArg; break;
+ case 'X': k = ConversionSpecifier::XArg; break;
+ case 'a': k = ConversionSpecifier::aArg; break;
+ case 'c': k = ConversionSpecifier::cArg; break;
+ case 'd': k = ConversionSpecifier::dArg; break;
+ case 'e': k = ConversionSpecifier::eArg; break;
+ case 'f': k = ConversionSpecifier::fArg; break;
+ case 'g': k = ConversionSpecifier::gArg; break;
+ case 'i': k = ConversionSpecifier::iArg; break;
+ case 'n': k = ConversionSpecifier::nArg; break;
+ case 'o': k = ConversionSpecifier::oArg; break;
+ case 'p': k = ConversionSpecifier::pArg; break;
+ case 's': k = ConversionSpecifier::sArg; break;
+ case 'u': k = ConversionSpecifier::uArg; break;
+ case 'x': k = ConversionSpecifier::xArg; break;
+ // POSIX specific.
+ case 'C': k = ConversionSpecifier::CArg; break;
+ case 'S': k = ConversionSpecifier::SArg; break;
+ // Objective-C.
+ case '@': k = ConversionSpecifier::ObjCObjArg; break;
+ // Glibc specific.
+ case 'm': k = ConversionSpecifier::PrintErrno; break;
+ // FreeBSD format extensions
+ case 'b': if (FormatExtensions) k = ConversionSpecifier::bArg; break; /* check for int and then char * */
+ case 'r': if (FormatExtensions) k = ConversionSpecifier::rArg; break;
+ case 'y': if (FormatExtensions) k = ConversionSpecifier::iArg; break;
+ case 'D': if (FormatExtensions) k = ConversionSpecifier::DArg; break; /* check for u_char * pointer and a char * string */
+ }
+ PrintfConversionSpecifier CS(conversionPosition, k);
+ FS.setConversionSpecifier(CS);
+ if (CS.consumesDataArgument() && !FS.usesPositionalArg())
+ FS.setArgIndex(argIndex++);
+ // FreeBSD extension
+ if (k == ConversionSpecifier::bArg || k == ConversionSpecifier::DArg)
+ argIndex++;
+
+ if (k == ConversionSpecifier::InvalidSpecifier) {
+ // Assume the conversion takes one argument.
+ return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
+ }
+ return PrintfSpecifierResult(Start, FS);
+}
+
+bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
+ const char *I,
+ const char *E,
+ bool FormatExtensions) {
+
+ unsigned argIndex = 0;
+
+ // Keep looking for a format specifier until we have exhausted the string.
+ while (I != E) {
+ const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
+ FormatExtensions);
+ // Did a fail-stop error of any kind occur when parsing the specifier?
+ // If so, don't do any more processing.
+ if (FSR.shouldStop())
+ return true;;
+ // Did we exhaust the string or encounter an error that
+ // we can recover from?
+ if (!FSR.hasValue())
+ continue;
+ // We have a format specifier. Pass it to the callback.
+ if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
+ I - FSR.getStart()))
+ return true;
+ }
+ assert(I == E && "Format string not exhausted");
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on ConversionSpecifier.
+//===----------------------------------------------------------------------===//
+const char *ConversionSpecifier::toString() const {
+ switch (kind) {
+ case dArg: return "d";
+ case iArg: return "i";
+ case oArg: return "o";
+ case uArg: return "u";
+ case xArg: return "x";
+ case XArg: return "X";
+ case fArg: return "f";
+ case FArg: return "F";
+ case eArg: return "e";
+ case EArg: return "E";
+ case gArg: return "g";
+ case GArg: return "G";
+ case aArg: return "a";
+ case AArg: return "A";
+ case cArg: return "c";
+ case sArg: return "s";
+ case pArg: return "p";
+ case nArg: return "n";
+ case PercentArg: return "%";
+ case ScanListArg: return "[";
+ case InvalidSpecifier: return NULL;
+
+ // MacOS X unicode extensions.
+ case CArg: return "C";
+ case SArg: return "S";
+
+ // Objective-C specific specifiers.
+ case ObjCObjArg: return "@";
+
+ // FreeBSD specific specifiers.
+ case bArg: return "b";
+ case DArg: return "D";
+ case rArg: return "r";
+
+ // GlibC specific specifiers.
+ case PrintErrno: return "m";
+ }
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on PrintfSpecifier.
+//===----------------------------------------------------------------------===//
+
+ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
+ const PrintfConversionSpecifier &CS = getConversionSpecifier();
+
+ if (!CS.consumesDataArgument())
+ return ArgTypeResult::Invalid();
+
+ if (CS.getKind() == ConversionSpecifier::cArg)
+ switch (LM.getKind()) {
+ case LengthModifier::None: return Ctx.IntTy;
+ case LengthModifier::AsLong: return ArgTypeResult::WIntTy;
+ default:
+ return ArgTypeResult::Invalid();
+ }
+
+ if (CS.isIntArg())
+ switch (LM.getKind()) {
+ case LengthModifier::AsLongDouble:
+ return ArgTypeResult::Invalid();
+ case LengthModifier::None: return Ctx.IntTy;
+ case LengthModifier::AsChar: return Ctx.SignedCharTy;
+ case LengthModifier::AsShort: return Ctx.ShortTy;
+ case LengthModifier::AsLong: return Ctx.LongTy;
+ case LengthModifier::AsLongLong: return Ctx.LongLongTy;
+ case LengthModifier::AsIntMax:
+ // FIXME: Return unknown for now.
+ return ArgTypeResult();
+ case LengthModifier::AsSizeT: return Ctx.getSizeType();
+ case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
+ }
+
+ if (CS.isUIntArg())
+ switch (LM.getKind()) {
+ case LengthModifier::AsLongDouble:
+ return ArgTypeResult::Invalid();
+ case LengthModifier::None: return Ctx.UnsignedIntTy;
+ case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
+ case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
+ case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
+ case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
+ case LengthModifier::AsIntMax:
+ // FIXME: Return unknown for now.
+ return ArgTypeResult();
+ case LengthModifier::AsSizeT:
+ // FIXME: How to get the corresponding unsigned
+ // version of size_t?
+ return ArgTypeResult();
+ case LengthModifier::AsPtrDiff:
+ // FIXME: How to get the corresponding unsigned
+ // version of ptrdiff_t?
+ return ArgTypeResult();
+ }
+
+ if (CS.isDoubleArg()) {
+ if (LM.getKind() == LengthModifier::AsLongDouble)
+ return Ctx.LongDoubleTy;
+ return Ctx.DoubleTy;
+ }
+
+ switch (CS.getKind()) {
+ case ConversionSpecifier::sArg:
+ return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
+ ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
+ case ConversionSpecifier::SArg:
+ // FIXME: This appears to be Mac OS X specific.
+ return ArgTypeResult::WCStrTy;
+ case ConversionSpecifier::CArg:
+ return Ctx.WCharTy;
+ case ConversionSpecifier::pArg:
+ return ArgTypeResult::CPointerTy;
+ default:
+ break;
+ }
+
+ // FIXME: Handle other cases.
+ return ArgTypeResult();
+}
+
+bool PrintfSpecifier::fixType(QualType QT) {
+ // Handle strings first (char *, wchar_t *)
+ if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
+ CS.setKind(ConversionSpecifier::sArg);
+
+ // Disable irrelevant flags
+ HasAlternativeForm = 0;
+ HasLeadingZeroes = 0;
+
+ // Set the long length modifier for wide characters
+ if (QT->getPointeeType()->isWideCharType())
+ LM.setKind(LengthModifier::AsWideChar);
+
+ return true;
+ }
+
+ // We can only work with builtin types.
+ if (!QT->isBuiltinType())
+ return false;
+
+ // Everything else should be a base type
+ const BuiltinType *BT = QT->getAs<BuiltinType>();
+
+ // Set length modifier
+ switch (BT->getKind()) {
+ default:
+ // The rest of the conversions are either optional or for non-builtin types
+ LM.setKind(LengthModifier::None);
+ break;
+
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ LM.setKind(LengthModifier::AsChar);
+ break;
+
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ LM.setKind(LengthModifier::AsShort);
+ break;
+
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ LM.setKind(LengthModifier::AsLong);
+ break;
+
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ LM.setKind(LengthModifier::AsLongLong);
+ break;
+
+ case BuiltinType::LongDouble:
+ LM.setKind(LengthModifier::AsLongDouble);
+ break;
+ }
+
+ // Set conversion specifier and disable any flags which do not apply to it.
+ // Let typedefs to char fall through to int, as %c is silly for uint8_t.
+ if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
+ CS.setKind(ConversionSpecifier::cArg);
+ LM.setKind(LengthModifier::None);
+ Precision.setHowSpecified(OptionalAmount::NotSpecified);
+ HasAlternativeForm = 0;
+ HasLeadingZeroes = 0;
+ HasPlusPrefix = 0;
+ }
+ // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
+ else if (QT->isRealFloatingType()) {
+ CS.setKind(ConversionSpecifier::fArg);
+ }
+ else if (QT->isPointerType()) {
+ CS.setKind(ConversionSpecifier::pArg);
+ Precision.setHowSpecified(OptionalAmount::NotSpecified);
+ HasAlternativeForm = 0;
+ HasLeadingZeroes = 0;
+ HasPlusPrefix = 0;
+ }
+ else if (QT->isSignedIntegerType()) {
+ CS.setKind(ConversionSpecifier::dArg);
+ HasAlternativeForm = 0;
+ }
+ else if (QT->isUnsignedIntegerType()) {
+ CS.setKind(ConversionSpecifier::uArg);
+ HasAlternativeForm = 0;
+ HasPlusPrefix = 0;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+void PrintfSpecifier::toString(llvm::raw_ostream &os) const {
+ // Whilst some features have no defined order, we are using the order
+ // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
+ os << "%";
+
+ // Positional args
+ if (usesPositionalArg()) {
+ os << getPositionalArgIndex() << "$";
+ }
+
+ // Conversion flags
+ if (IsLeftJustified) os << "-";
+ if (HasPlusPrefix) os << "+";
+ if (HasSpacePrefix) os << " ";
+ if (HasAlternativeForm) os << "#";
+ if (HasLeadingZeroes) os << "0";
+
+ // Minimum field width
+ FieldWidth.toString(os);
+ // Precision
+ Precision.toString(os);
+ // Length modifier
+ os << LM.toString();
+ // Conversion specifier
+ os << CS.toString();
+}
+
+bool PrintfSpecifier::hasValidPlusPrefix() const {
+ if (!HasPlusPrefix)
+ return true;
+
+ // The plus prefix only makes sense for signed conversions
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::rArg:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool PrintfSpecifier::hasValidAlternativeForm() const {
+ if (!HasAlternativeForm)
+ return true;
+
+ // Alternate form flag only valid with the oxXaAeEfFgG conversions
+ switch (CS.getKind()) {
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::rArg:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool PrintfSpecifier::hasValidLeadingZeros() const {
+ if (!HasLeadingZeroes)
+ return true;
+
+ // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool PrintfSpecifier::hasValidSpacePrefix() const {
+ if (!HasSpacePrefix)
+ return true;
+
+ // The space prefix only makes sense for signed conversions
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool PrintfSpecifier::hasValidLeftJustified() const {
+ if (!IsLeftJustified)
+ return true;
+
+ // The left justified flag is valid for all conversions except n
+ switch (CS.getKind()) {
+ case ConversionSpecifier::nArg:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
+ if (!HasThousandsGrouping)
+ return true;
+
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool PrintfSpecifier::hasValidPrecision() const {
+ if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
+ return true;
+
+ // Precision is only valid with the diouxXaAeEfFgGs conversions
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::sArg:
+ return true;
+
+ default:
+ return false;
+ }
+}
+bool PrintfSpecifier::hasValidFieldWidth() const {
+ if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
+ return true;
+
+ // The field width is valid for all conversions except n
+ switch (CS.getKind()) {
+ case ConversionSpecifier::nArg:
+ return false;
+
+ default:
+ return true;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp
new file mode 100644
index 0000000..ff96eb4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -0,0 +1,240 @@
+//== PseudoConstantAnalysis.cpp - Find Pseudoconstants in the AST-*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tracks the usage of variables in a Decl body to see if they are
+// never written to, implying that they constant. This is useful in static
+// analysis to see if a developer might have intended a variable to be const.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include <deque>
+
+using namespace clang;
+
+// The number of ValueDecls we want to keep track of by default (per-function)
+#define VARDECL_SET_SIZE 256
+typedef llvm::SmallPtrSet<const VarDecl*, VARDECL_SET_SIZE> VarDeclSet;
+
+PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) :
+ DeclBody(DeclBody), Analyzed(false) {
+ NonConstantsImpl = new VarDeclSet;
+ UsedVarsImpl = new VarDeclSet;
+}
+
+PseudoConstantAnalysis::~PseudoConstantAnalysis() {
+ delete (VarDeclSet*)NonConstantsImpl;
+ delete (VarDeclSet*)UsedVarsImpl;
+}
+
+// Returns true if the given ValueDecl is never written to in the given DeclBody
+bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) {
+ // Only local and static variables can be pseudoconstants
+ if (!VD->hasLocalStorage() && !VD->isStaticLocal())
+ return false;
+
+ if (!Analyzed) {
+ RunAnalysis();
+ Analyzed = true;
+ }
+
+ VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
+
+ return !NonConstants->count(VD);
+}
+
+// Returns true if the variable was used (self assignments don't count)
+bool PseudoConstantAnalysis::wasReferenced(const VarDecl *VD) {
+ if (!Analyzed) {
+ RunAnalysis();
+ Analyzed = true;
+ }
+
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
+
+ return UsedVars->count(VD);
+}
+
+// Returns a Decl from a (Block)DeclRefExpr (if any)
+const Decl *PseudoConstantAnalysis::getDecl(const Expr *E) {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+ return DR->getDecl();
+ else if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E))
+ return BDR->getDecl();
+ else
+ return 0;
+}
+
+void PseudoConstantAnalysis::RunAnalysis() {
+ std::deque<const Stmt *> WorkList;
+ VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
+
+ // Start with the top level statement of the function
+ WorkList.push_back(DeclBody);
+
+ while (!WorkList.empty()) {
+ const Stmt* Head = WorkList.front();
+ WorkList.pop_front();
+
+ if (const Expr *Ex = dyn_cast<Expr>(Head))
+ Head = Ex->IgnoreParenCasts();
+
+ switch (Head->getStmtClass()) {
+ // Case 1: Assignment operators modifying VarDecls
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(Head);
+ // Look for a Decl on the LHS
+ const Decl *LHSDecl = getDecl(BO->getLHS()->IgnoreParenCasts());
+ if (!LHSDecl)
+ break;
+
+ // We found a binary operator with a DeclRefExpr on the LHS. We now check
+ // for any of the assignment operators, implying that this Decl is being
+ // written to.
+ switch (BO->getOpcode()) {
+ // Self-assignments don't count as use of a variable
+ case BO_Assign: {
+ // Look for a DeclRef on the RHS
+ const Decl *RHSDecl = getDecl(BO->getRHS()->IgnoreParenCasts());
+
+ // If the Decls match, we have self-assignment
+ if (LHSDecl == RHSDecl)
+ // Do not visit the children
+ continue;
+
+ }
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign: {
+ const VarDecl *VD = dyn_cast<VarDecl>(LHSDecl);
+ // The DeclRefExpr is being assigned to - mark it as non-constant
+ if (VD)
+ NonConstants->insert(VD);
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ // Case 2: Pre/post increment/decrement and address of
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(Head);
+
+ // Look for a DeclRef in the subexpression
+ const Decl *D = getDecl(UO->getSubExpr()->IgnoreParenCasts());
+ if (!D)
+ break;
+
+ // We found a unary operator with a DeclRef as a subexpression. We now
+ // check for any of the increment/decrement operators, as well as
+ // addressOf.
+ switch (UO->getOpcode()) {
+ case UO_PostDec:
+ case UO_PostInc:
+ case UO_PreDec:
+ case UO_PreInc:
+ // The DeclRef is being changed - mark it as non-constant
+ case UO_AddrOf: {
+ // If we are taking the address of the DeclRefExpr, assume it is
+ // non-constant.
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (VD)
+ NonConstants->insert(VD);
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ // Case 3: Reference Declarations
+ case Stmt::DeclStmtClass: {
+ const DeclStmt *DS = cast<DeclStmt>(Head);
+ // Iterate over each decl and see if any of them contain reference decls
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(),
+ E = DS->decl_end(); I != E; ++I) {
+ // We only care about VarDecls
+ const VarDecl *VD = dyn_cast<VarDecl>(*I);
+ if (!VD)
+ continue;
+
+ // We found a VarDecl; make sure it is a reference type
+ if (!VD->getType().getTypePtr()->isReferenceType())
+ continue;
+
+ // Try to find a Decl in the initializer
+ const Decl *D = getDecl(VD->getInit()->IgnoreParenCasts());
+ if (!D)
+ break;
+
+ // If the reference is to another var, add the var to the non-constant
+ // list
+ if (const VarDecl *RefVD = dyn_cast<VarDecl>(D)) {
+ NonConstants->insert(RefVD);
+ continue;
+ }
+ }
+ break;
+ }
+
+ // Case 4: Block variable references
+ case Stmt::BlockDeclRefExprClass: {
+ const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(Head);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(BDR->getDecl())) {
+ // Add the Decl to the used list
+ UsedVars->insert(VD);
+ continue;
+ }
+ break;
+ }
+
+ // Case 5: Variable references
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Add the Decl to the used list
+ UsedVars->insert(VD);
+ continue;
+ }
+ break;
+ }
+
+ // Case 6: Block expressions
+ case Stmt::BlockExprClass: {
+ const BlockExpr *B = cast<BlockExpr>(Head);
+ // Add the body of the block to the list
+ WorkList.push_back(B->getBody());
+ continue;
+ }
+
+ default:
+ break;
+ } // switch (head->getStmtClass())
+
+ // Add all substatements to the worklist
+ for (Stmt::const_child_range I = Head->children(); I; ++I)
+ if (*I)
+ WorkList.push_back(*I);
+ } // while (!WorkList.empty())
+}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
new file mode 100644
index 0000000..7afa586
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/ReachableCode.cpp
@@ -0,0 +1,290 @@
+//=- ReachableCodePathInsensitive.cpp ---------------------------*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a flow-sensitive, path-insensitive analysis of
+// determining reachable blocks within a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+
+static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1,
+ SourceRange &R2) {
+ const Stmt *S = 0;
+ unsigned sn = 0;
+ R1 = R2 = SourceRange();
+
+ if (sn < b.size()) {
+ CFGStmt CS = b[sn].getAs<CFGStmt>();
+ if (!CS)
+ return SourceLocation();
+
+ S = CS.getStmt();
+ } else if (b.getTerminator())
+ S = b.getTerminator();
+ else
+ return SourceLocation();
+
+ if (const Expr *Ex = dyn_cast<Expr>(S))
+ S = Ex->IgnoreParenImpCasts();
+
+ switch (S->getStmtClass()) {
+ case Expr::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(S);
+ if (BO->getOpcode() == BO_Comma) {
+ if (sn+1 < b.size())
+ return b[sn+1].getAs<CFGStmt>().getStmt()->getLocStart();
+ const CFGBlock *n = &b;
+ while (1) {
+ if (n->getTerminator())
+ return n->getTerminator()->getLocStart();
+ if (n->succ_size() != 1)
+ return SourceLocation();
+ n = n[0].succ_begin()[0];
+ if (n->pred_size() != 1)
+ return SourceLocation();
+ if (!n->empty())
+ return n[0][0].getAs<CFGStmt>().getStmt()->getLocStart();
+ }
+ }
+ R1 = BO->getLHS()->getSourceRange();
+ R2 = BO->getRHS()->getSourceRange();
+ return BO->getOperatorLoc();
+ }
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(S);
+ R1 = UO->getSubExpr()->getSourceRange();
+ return UO->getOperatorLoc();
+ }
+ case Expr::CompoundAssignOperatorClass: {
+ const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
+ R1 = CAO->getLHS()->getSourceRange();
+ R2 = CAO->getRHS()->getSourceRange();
+ return CAO->getOperatorLoc();
+ }
+ case Expr::BinaryConditionalOperatorClass:
+ case Expr::ConditionalOperatorClass: {
+ const AbstractConditionalOperator *CO =
+ cast<AbstractConditionalOperator>(S);
+ return CO->getQuestionLoc();
+ }
+ case Expr::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(S);
+ R1 = ME->getSourceRange();
+ return ME->getMemberLoc();
+ }
+ case Expr::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
+ R1 = ASE->getLHS()->getSourceRange();
+ R2 = ASE->getRHS()->getSourceRange();
+ return ASE->getRBracketLoc();
+ }
+ case Expr::CStyleCastExprClass: {
+ const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
+ R1 = CSC->getSubExpr()->getSourceRange();
+ return CSC->getLParenLoc();
+ }
+ case Expr::CXXFunctionalCastExprClass: {
+ const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
+ R1 = CE->getSubExpr()->getSourceRange();
+ return CE->getTypeBeginLoc();
+ }
+ case Stmt::CXXTryStmtClass: {
+ return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
+ }
+ default: ;
+ }
+ R1 = S->getSourceRange();
+ return S->getLocStart();
+}
+
+static SourceLocation MarkLiveTop(const CFGBlock *Start,
+ llvm::BitVector &reachable,
+ SourceManager &SM) {
+
+ // Prep work worklist.
+ llvm::SmallVector<const CFGBlock*, 32> WL;
+ WL.push_back(Start);
+
+ SourceRange R1, R2;
+ SourceLocation top = GetUnreachableLoc(*Start, R1, R2);
+
+ bool FromMainFile = false;
+ bool FromSystemHeader = false;
+ bool TopValid = false;
+
+ if (top.isValid()) {
+ FromMainFile = SM.isFromMainFile(top);
+ FromSystemHeader = SM.isInSystemHeader(top);
+ TopValid = true;
+ }
+
+ // Solve
+ CFGBlock::FilterOptions FO;
+ FO.IgnoreDefaultsWithCoveredEnums = 1;
+
+ while (!WL.empty()) {
+ const CFGBlock *item = WL.back();
+ WL.pop_back();
+
+ SourceLocation c = GetUnreachableLoc(*item, R1, R2);
+ if (c.isValid()
+ && (!TopValid
+ || (SM.isFromMainFile(c) && !FromMainFile)
+ || (FromSystemHeader && !SM.isInSystemHeader(c))
+ || SM.isBeforeInTranslationUnit(c, top))) {
+ top = c;
+ FromMainFile = SM.isFromMainFile(top);
+ FromSystemHeader = SM.isInSystemHeader(top);
+ }
+
+ reachable.set(item->getBlockID());
+ for (CFGBlock::filtered_succ_iterator I =
+ item->filtered_succ_start_end(FO); I.hasMore(); ++I)
+ if (const CFGBlock *B = *I) {
+ unsigned blockID = B->getBlockID();
+ if (!reachable[blockID]) {
+ reachable.set(blockID);
+ WL.push_back(B);
+ }
+ }
+ }
+
+ return top;
+}
+
+static int LineCmp(const void *p1, const void *p2) {
+ SourceLocation *Line1 = (SourceLocation *)p1;
+ SourceLocation *Line2 = (SourceLocation *)p2;
+ return !(*Line1 < *Line2);
+}
+
+namespace {
+struct ErrLoc {
+ SourceLocation Loc;
+ SourceRange R1;
+ SourceRange R2;
+ ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2)
+ : Loc(l), R1(r1), R2(r2) { }
+};
+}
+namespace clang { namespace reachable_code {
+
+/// ScanReachableFromBlock - Mark all blocks reachable from Start.
+/// Returns the total number of blocks that were marked reachable.
+unsigned ScanReachableFromBlock(const CFGBlock &Start,
+ llvm::BitVector &Reachable) {
+ unsigned count = 0;
+ llvm::SmallVector<const CFGBlock*, 32> WL;
+
+ // Prep work queue
+ Reachable.set(Start.getBlockID());
+ ++count;
+ WL.push_back(&Start);
+
+ // Find the reachable blocks from 'Start'.
+ CFGBlock::FilterOptions FO;
+ FO.IgnoreDefaultsWithCoveredEnums = 1;
+
+ while (!WL.empty()) {
+ const CFGBlock *item = WL.back();
+ WL.pop_back();
+
+ // Look at the successors and mark then reachable.
+ for (CFGBlock::filtered_succ_iterator I= item->filtered_succ_start_end(FO);
+ I.hasMore(); ++I)
+ if (const CFGBlock *B = *I) {
+ unsigned blockID = B->getBlockID();
+ if (!Reachable[blockID]) {
+ Reachable.set(blockID);
+ ++count;
+ WL.push_back(B);
+ }
+ }
+ }
+ return count;
+}
+
+void FindUnreachableCode(AnalysisContext &AC, Callback &CB) {
+ CFG *cfg = AC.getCFG();
+ if (!cfg)
+ return;
+
+ // Scan for reachable blocks.
+ llvm::BitVector reachable(cfg->getNumBlockIDs());
+ unsigned numReachable = ScanReachableFromBlock(cfg->getEntry(), reachable);
+
+ // If there are no unreachable blocks, we're done.
+ if (numReachable == cfg->getNumBlockIDs())
+ return;
+
+ SourceRange R1, R2;
+
+ llvm::SmallVector<ErrLoc, 24> lines;
+ bool AddEHEdges = AC.getAddEHEdges();
+
+ // First, give warnings for blocks with no predecessors, as they
+ // can't be part of a loop.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!reachable[b.getBlockID()]) {
+ if (b.pred_empty()) {
+ if (!AddEHEdges
+ && dyn_cast_or_null<CXXTryStmt>(b.getTerminator().getStmt())) {
+ // When not adding EH edges from calls, catch clauses
+ // can otherwise seem dead. Avoid noting them as dead.
+ numReachable += ScanReachableFromBlock(b, reachable);
+ continue;
+ }
+ SourceLocation c = GetUnreachableLoc(b, R1, R2);
+ if (!c.isValid()) {
+ // Blocks without a location can't produce a warning, so don't mark
+ // reachable blocks from here as live.
+ reachable.set(b.getBlockID());
+ ++numReachable;
+ continue;
+ }
+ lines.push_back(ErrLoc(c, R1, R2));
+ // Avoid excessive errors by marking everything reachable from here
+ numReachable += ScanReachableFromBlock(b, reachable);
+ }
+ }
+ }
+
+ if (numReachable < cfg->getNumBlockIDs()) {
+ // And then give warnings for the tops of loops.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!reachable[b.getBlockID()])
+ // Avoid excessive errors by marking everything reachable from here
+ lines.push_back(ErrLoc(MarkLiveTop(&b, reachable,
+ AC.getASTContext().getSourceManager()),
+ SourceRange(), SourceRange()));
+ }
+ }
+
+ llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp);
+
+ for (llvm::SmallVectorImpl<ErrLoc>::iterator I=lines.begin(), E=lines.end();
+ I != E; ++I)
+ if (I->Loc.isValid())
+ CB.HandleUnreachable(I->Loc, I->R1, I->R2);
+}
+
+}} // end namespace clang::reachable_code
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
new file mode 100644
index 0000000..6a8673a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/ScanfFormatString.cpp
@@ -0,0 +1,221 @@
+//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handling of format string in scanf and friends. The structure of format
+// strings for fscanf() are described in C99 7.19.6.2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "FormatStringParsing.h"
+
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::ConversionSpecifier;
+using clang::analyze_scanf::ScanfConversionSpecifier;
+using clang::analyze_scanf::ScanfSpecifier;
+using clang::UpdateOnReturn;
+
+typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
+ ScanfSpecifierResult;
+
+static bool ParseScanList(FormatStringHandler &H,
+ ScanfConversionSpecifier &CS,
+ const char *&Beg, const char *E) {
+ const char *I = Beg;
+ const char *start = I - 1;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ // No more characters?
+ if (I == E) {
+ H.HandleIncompleteScanList(start, I);
+ return true;
+ }
+
+ // Special case: ']' is the first character.
+ if (*I == ']') {
+ if (++I == E) {
+ H.HandleIncompleteScanList(start, I - 1);
+ return true;
+ }
+ }
+
+ // Look for a ']' character which denotes the end of the scan list.
+ while (*I != ']') {
+ if (++I == E) {
+ H.HandleIncompleteScanList(start, I - 1);
+ return true;
+ }
+ }
+
+ CS.setEndScanList(I);
+ return false;
+}
+
+// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
+// We can possibly refactor.
+static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
+ const char *&Beg,
+ const char *E,
+ unsigned &argIndex) {
+
+ using namespace clang::analyze_scanf;
+ const char *I = Beg;
+ const char *Start = 0;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ // Look for a '%' character that indicates the start of a format specifier.
+ for ( ; I != E ; ++I) {
+ char c = *I;
+ if (c == '\0') {
+ // Detect spurious null characters, which are likely errors.
+ H.HandleNullChar(I);
+ return true;
+ }
+ if (c == '%') {
+ Start = I++; // Record the start of the format specifier.
+ break;
+ }
+ }
+
+ // No format specifier found?
+ if (!Start)
+ return false;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ ScanfSpecifier FS;
+ if (ParseArgPosition(H, FS, Start, I, E))
+ return true;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Look for '*' flag if it is present.
+ if (*I == '*') {
+ FS.setSuppressAssignment(I);
+ if (++I == E) {
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+
+ // Look for the field width (if any). Unlike printf, this is either
+ // a fixed integer or isn't present.
+ const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
+ if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
+ assert(Amt.getHowSpecified() == OptionalAmount::Constant);
+ FS.setFieldWidth(Amt);
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+
+ // Look for the length modifier.
+ if (ParseLengthModifier(FS, I, E) && I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Detect spurious null characters, which are likely errors.
+ if (*I == '\0') {
+ H.HandleNullChar(I);
+ return true;
+ }
+
+ // Finally, look for the conversion specifier.
+ const char *conversionPosition = I++;
+ ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
+ switch (*conversionPosition) {
+ default:
+ break;
+ case '%': k = ConversionSpecifier::PercentArg; break;
+ case 'A': k = ConversionSpecifier::AArg; break;
+ case 'E': k = ConversionSpecifier::EArg; break;
+ case 'F': k = ConversionSpecifier::FArg; break;
+ case 'G': k = ConversionSpecifier::GArg; break;
+ case 'X': k = ConversionSpecifier::XArg; break;
+ case 'a': k = ConversionSpecifier::aArg; break;
+ case 'd': k = ConversionSpecifier::dArg; break;
+ case 'e': k = ConversionSpecifier::eArg; break;
+ case 'f': k = ConversionSpecifier::fArg; break;
+ case 'g': k = ConversionSpecifier::gArg; break;
+ case 'i': k = ConversionSpecifier::iArg; break;
+ case 'n': k = ConversionSpecifier::nArg; break;
+ case 'c': k = ConversionSpecifier::cArg; break;
+ case 'C': k = ConversionSpecifier::CArg; break;
+ case 'S': k = ConversionSpecifier::SArg; break;
+ case '[': k = ConversionSpecifier::ScanListArg; break;
+ case 'u': k = ConversionSpecifier::uArg; break;
+ case 'x': k = ConversionSpecifier::xArg; break;
+ case 'o': k = ConversionSpecifier::oArg; break;
+ case 's': k = ConversionSpecifier::sArg; break;
+ case 'p': k = ConversionSpecifier::pArg; break;
+ }
+ ScanfConversionSpecifier CS(conversionPosition, k);
+ if (k == ScanfConversionSpecifier::ScanListArg) {
+ if (!ParseScanList(H, CS, I, E))
+ return true;
+ }
+ FS.setConversionSpecifier(CS);
+ if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
+ && !FS.usesPositionalArg())
+ FS.setArgIndex(argIndex++);
+
+ // FIXME: '%' and '*' doesn't make sense. Issue a warning.
+ // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
+
+ if (k == ScanfConversionSpecifier::InvalidSpecifier) {
+ // Assume the conversion takes one argument.
+ return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg);
+ }
+ return ScanfSpecifierResult(Start, FS);
+}
+
+bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
+ const char *I,
+ const char *E) {
+
+ unsigned argIndex = 0;
+
+ // Keep looking for a format specifier until we have exhausted the string.
+ while (I != E) {
+ const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex);
+ // Did a fail-stop error of any kind occur when parsing the specifier?
+ // If so, don't do any more processing.
+ if (FSR.shouldStop())
+ return true;;
+ // Did we exhaust the string or encounter an error that
+ // we can recover from?
+ if (!FSR.hasValue())
+ continue;
+ // We have a format specifier. Pass it to the callback.
+ if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
+ I - FSR.getStart())) {
+ return true;
+ }
+ }
+ assert(I == E && "Format string not exhausted");
+ return false;
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
new file mode 100644
index 0000000..c08cbed
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValues.cpp
@@ -0,0 +1,317 @@
+//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Uninitialized Values analysis for source-level CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/UninitializedValues.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/FlowSensitive/DataflowSolver.h"
+
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Dataflow initialization logic.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class RegisterDecls
+ : public CFGRecStmtDeclVisitor<RegisterDecls> {
+
+ UninitializedValues::AnalysisDataTy& AD;
+public:
+ RegisterDecls(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {}
+
+ void VisitVarDecl(VarDecl* VD) { AD.Register(VD); }
+ CFG& getCFG() { return AD.getCFG(); }
+};
+
+} // end anonymous namespace
+
+void UninitializedValues::InitializeValues(const CFG& cfg) {
+ RegisterDecls R(getAnalysisData());
+ cfg.VisitBlockStmts(R);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class TransferFuncs
+ : public CFGStmtVisitor<TransferFuncs,bool> {
+
+ UninitializedValues::ValTy V;
+ UninitializedValues::AnalysisDataTy& AD;
+public:
+ TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {}
+
+ UninitializedValues::ValTy& getVal() { return V; }
+ CFG& getCFG() { return AD.getCFG(); }
+
+ void SetTopValue(UninitializedValues::ValTy& X) {
+ X.setDeclValues(AD);
+ X.resetBlkExprValues(AD);
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr* DR);
+ bool VisitBinaryOperator(BinaryOperator* B);
+ bool VisitUnaryOperator(UnaryOperator* U);
+ bool VisitStmt(Stmt* S);
+ bool VisitCallExpr(CallExpr* C);
+ bool VisitDeclStmt(DeclStmt* D);
+ bool VisitAbstractConditionalOperator(AbstractConditionalOperator* C);
+ bool BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S);
+
+ bool Visit(Stmt *S);
+ bool BlockStmt_VisitExpr(Expr* E);
+
+ void VisitTerminator(CFGBlock* B) { }
+
+ void setCurrentBlock(const CFGBlock *block) {}
+};
+
+static const bool Initialized = false;
+static const bool Uninitialized = true;
+
+bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
+
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VD->isLocalVarDecl()) {
+
+ if (AD.Observer)
+ AD.Observer->ObserveDeclRefExpr(V, AD, DR, VD);
+
+ // Pseudo-hack to prevent cascade of warnings. If an accessed variable
+ // is uninitialized, then we are already going to flag a warning for
+ // this variable, which a "source" of uninitialized values.
+ // We can otherwise do a full "taint" of uninitialized values. The
+ // client has both options by toggling AD.FullUninitTaint.
+
+ if (AD.FullUninitTaint)
+ return V(VD,AD);
+ }
+
+ return Initialized;
+}
+
+static VarDecl* FindBlockVarDecl(Expr* E) {
+
+ // Blast through casts and parentheses to find any DeclRefExprs that
+ // refer to a block VarDecl.
+
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VD->isLocalVarDecl()) return VD;
+
+ return NULL;
+}
+
+bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
+
+ if (VarDecl* VD = FindBlockVarDecl(B->getLHS()))
+ if (B->isAssignmentOp()) {
+ if (B->getOpcode() == BO_Assign)
+ return V(VD,AD) = Visit(B->getRHS());
+ else // Handle +=, -=, *=, etc. We do want '&', not '&&'.
+ return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS());
+ }
+
+ return VisitStmt(B);
+}
+
+bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
+ for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) {
+ VarDecl *VD = dyn_cast<VarDecl>(*I);
+ if (VD && VD->isLocalVarDecl()) {
+ if (Stmt* I = VD->getInit()) {
+ // Visit the subexpression to check for uses of uninitialized values,
+ // even if we don't propagate that value.
+ bool isSubExprUninit = Visit(I);
+ V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized;
+ }
+ else {
+ // Special case for declarations of array types. For things like:
+ //
+ // char x[10];
+ //
+ // we should treat "x" as being initialized, because the variable
+ // "x" really refers to the memory block. Clearly x[1] is
+ // uninitialized, but expressions like "(char *) x" really do refer to
+ // an initialized value. This simple dataflow analysis does not reason
+ // about the contents of arrays, although it could be potentially
+ // extended to do so if the array were of constant size.
+ if (VD->getType()->isArrayType())
+ V(VD,AD) = Initialized;
+ else
+ V(VD,AD) = Uninitialized;
+ }
+ }
+ }
+ return Uninitialized; // Value is never consumed.
+}
+
+bool TransferFuncs::VisitCallExpr(CallExpr* C) {
+ VisitChildren(C);
+ return Initialized;
+}
+
+bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
+ switch (U->getOpcode()) {
+ case UO_AddrOf: {
+ VarDecl* VD = FindBlockVarDecl(U->getSubExpr());
+ if (VD && VD->isLocalVarDecl())
+ return V(VD,AD) = Initialized;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return Visit(U->getSubExpr());
+}
+
+bool
+TransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+ // This represents a use of the 'collection'
+ bool x = Visit(S->getCollection());
+
+ if (x == Uninitialized)
+ return Uninitialized;
+
+ // This represents an initialization of the 'element' value.
+ Stmt* Element = S->getElement();
+ VarDecl* VD = 0;
+
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(Element))
+ VD = cast<VarDecl>(DS->getSingleDecl());
+ else {
+ Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens();
+
+ // Initialize the value of the reference variable.
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(ElemExpr))
+ VD = cast<VarDecl>(DR->getDecl());
+ else
+ return Visit(ElemExpr);
+ }
+
+ V(VD,AD) = Initialized;
+ return Initialized;
+}
+
+
+bool TransferFuncs::
+VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
+ Visit(C->getCond());
+
+ bool rhsResult = Visit(C->getFalseExpr());
+ // Handle the GNU extension for missing LHS.
+ if (isa<ConditionalOperator>(C))
+ return Visit(C->getTrueExpr()) & rhsResult; // Yes: we want &, not &&.
+ else
+ return rhsResult;
+}
+
+bool TransferFuncs::VisitStmt(Stmt* S) {
+ bool x = Initialized;
+
+ // We don't stop at the first subexpression that is Uninitialized because
+ // evaluating some subexpressions may result in propogating "Uninitialized"
+ // or "Initialized" to variables referenced in the other subexpressions.
+ for (Stmt::child_range I = S->children(); I; ++I)
+ if (*I && Visit(*I) == Uninitialized) x = Uninitialized;
+
+ return x;
+}
+
+bool TransferFuncs::Visit(Stmt *S) {
+ if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD);
+ else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S);
+}
+
+bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
+ bool x = static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E);
+ if (AD.isTracked(E)) V(E,AD) = x;
+ return x;
+}
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Merge operator.
+//
+// In our transfer functions we take the approach that any
+// combination of uninitialized values, e.g.
+// Uninitialized + ___ = Uninitialized.
+//
+// Merges take the same approach, preferring soundness. At a confluence point,
+// if any predecessor has a variable marked uninitialized, the value is
+// uninitialized at the confluence point.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ typedef StmtDeclBitVector_Types::Union Merge;
+ typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
+}
+
+//===----------------------------------------------------------------------===//
+// Uninitialized values checker. Scan an AST and flag variable uses
+//===----------------------------------------------------------------------===//
+
+UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}
+
+namespace {
+class UninitializedValuesChecker
+ : public UninitializedValues::ObserverTy {
+
+ ASTContext &Ctx;
+ Diagnostic &Diags;
+ llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned;
+
+public:
+ UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
+ : Ctx(ctx), Diags(diags) {}
+
+ virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
+ UninitializedValues::AnalysisDataTy& AD,
+ DeclRefExpr* DR, VarDecl* VD) {
+
+ assert ( AD.isTracked(VD) && "Unknown VarDecl.");
+
+ if (V(VD,AD) == Uninitialized)
+ if (AlreadyWarned.insert(VD))
+ Diags.Report(Ctx.getFullLoc(DR->getSourceRange().getBegin()),
+ diag::warn_uninit_val);
+ }
+};
+} // end anonymous namespace
+
+namespace clang {
+void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags,
+ bool FullUninitTaint) {
+
+ // Compute the uninitialized values information.
+ UninitializedValues U(cfg);
+ U.getAnalysisData().FullUninitTaint = FullUninitTaint;
+ Solver S(U);
+ S.runOnCFG(cfg);
+
+ // Scan for DeclRefExprs that use uninitialized values.
+ UninitializedValuesChecker Observer(Ctx,Diags);
+ U.getAnalysisData().Observer = &Observer;
+ S.runOnAllBlocks(cfg);
+}
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp
new file mode 100644
index 0000000..75eccbf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/UninitializedValuesV2.cpp
@@ -0,0 +1,610 @@
+//==- UninitializedValuesV2.cpp - Find Uninitialized Values -----*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements uninitialized values analysis for source-level CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#include <utility>
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+using namespace clang;
+
+static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
+ return vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
+ vd->getType()->isScalarType() &&
+ vd->getDeclContext() == dc;
+}
+
+//------------------------------------------------------------------------====//
+// DeclToBit: a mapping from Decls we track to bitvector indices.
+//====------------------------------------------------------------------------//
+
+namespace {
+class DeclToBit {
+ llvm::DenseMap<const VarDecl *, unsigned> map;
+public:
+ DeclToBit() {}
+
+ /// Compute the actual mapping from declarations to bits.
+ void computeMap(const DeclContext &dc);
+
+ /// Return the number of declarations in the map.
+ unsigned size() const { return map.size(); }
+
+ /// Returns the bit vector index for a given declaration.
+ llvm::Optional<unsigned> getBitVectorIndex(const VarDecl *d);
+};
+}
+
+void DeclToBit::computeMap(const DeclContext &dc) {
+ unsigned count = 0;
+ DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()),
+ E(dc.decls_end());
+ for ( ; I != E; ++I) {
+ const VarDecl *vd = *I;
+ if (isTrackedVar(vd, &dc))
+ map[vd] = count++;
+ }
+}
+
+llvm::Optional<unsigned> DeclToBit::getBitVectorIndex(const VarDecl *d) {
+ llvm::DenseMap<const VarDecl *, unsigned>::iterator I = map.find(d);
+ if (I == map.end())
+ return llvm::Optional<unsigned>();
+ return I->second;
+}
+
+//------------------------------------------------------------------------====//
+// CFGBlockValues: dataflow values for CFG blocks.
+//====------------------------------------------------------------------------//
+
+typedef std::pair<llvm::BitVector *, llvm::BitVector *> BVPair;
+
+namespace {
+class CFGBlockValues {
+ const CFG &cfg;
+ BVPair *vals;
+ llvm::BitVector scratch;
+ DeclToBit declToBit;
+
+ llvm::BitVector &lazyCreate(llvm::BitVector *&bv);
+public:
+ CFGBlockValues(const CFG &cfg);
+ ~CFGBlockValues();
+
+ void computeSetOfDeclarations(const DeclContext &dc);
+ llvm::BitVector &getBitVector(const CFGBlock *block,
+ const CFGBlock *dstBlock);
+
+ BVPair &getBitVectors(const CFGBlock *block, bool shouldLazyCreate);
+
+ void mergeIntoScratch(llvm::BitVector const &source, bool isFirst);
+ bool updateBitVectorWithScratch(const CFGBlock *block);
+ bool updateBitVectors(const CFGBlock *block, const BVPair &newVals);
+
+ bool hasNoDeclarations() const {
+ return declToBit.size() == 0;
+ }
+
+ void resetScratch();
+ llvm::BitVector &getScratch() { return scratch; }
+
+ llvm::BitVector::reference operator[](const VarDecl *vd);
+};
+}
+
+CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {
+ unsigned n = cfg.getNumBlockIDs();
+ if (!n)
+ return;
+ vals = new std::pair<llvm::BitVector*, llvm::BitVector*>[n];
+ memset(vals, 0, sizeof(*vals) * n);
+}
+
+CFGBlockValues::~CFGBlockValues() {
+ unsigned n = cfg.getNumBlockIDs();
+ if (n == 0)
+ return;
+ for (unsigned i = 0; i < n; ++i) {
+ delete vals[i].first;
+ delete vals[i].second;
+ }
+ delete [] vals;
+}
+
+void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
+ declToBit.computeMap(dc);
+ scratch.resize(declToBit.size());
+}
+
+llvm::BitVector &CFGBlockValues::lazyCreate(llvm::BitVector *&bv) {
+ if (!bv)
+ bv = new llvm::BitVector(declToBit.size());
+ return *bv;
+}
+
+/// This function pattern matches for a '&&' or '||' that appears at
+/// the beginning of a CFGBlock that also (1) has a terminator and
+/// (2) has no other elements. If such an expression is found, it is returned.
+static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {
+ if (block->empty())
+ return 0;
+
+ CFGStmt cstmt = block->front().getAs<CFGStmt>();
+ BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt.getStmt());
+
+ if (!b || !b->isLogicalOp())
+ return 0;
+
+ if (block->pred_size() == 2 &&
+ ((block->succ_size() == 2 && block->getTerminatorCondition() == b) ||
+ block->size() == 1))
+ return b;
+
+ return 0;
+}
+
+llvm::BitVector &CFGBlockValues::getBitVector(const CFGBlock *block,
+ const CFGBlock *dstBlock) {
+ unsigned idx = block->getBlockID();
+ if (dstBlock && getLogicalOperatorInChain(block)) {
+ if (*block->succ_begin() == dstBlock)
+ return lazyCreate(vals[idx].first);
+ assert(*(block->succ_begin()+1) == dstBlock);
+ return lazyCreate(vals[idx].second);
+ }
+
+ assert(vals[idx].second == 0);
+ return lazyCreate(vals[idx].first);
+}
+
+BVPair &CFGBlockValues::getBitVectors(const clang::CFGBlock *block,
+ bool shouldLazyCreate) {
+ unsigned idx = block->getBlockID();
+ lazyCreate(vals[idx].first);
+ if (shouldLazyCreate)
+ lazyCreate(vals[idx].second);
+ return vals[idx];
+}
+
+void CFGBlockValues::mergeIntoScratch(llvm::BitVector const &source,
+ bool isFirst) {
+ if (isFirst)
+ scratch = source;
+ else
+ scratch |= source;
+}
+#if 0
+static void printVector(const CFGBlock *block, llvm::BitVector &bv,
+ unsigned num) {
+
+ llvm::errs() << block->getBlockID() << " :";
+ for (unsigned i = 0; i < bv.size(); ++i) {
+ llvm::errs() << ' ' << bv[i];
+ }
+ llvm::errs() << " : " << num << '\n';
+}
+#endif
+
+bool CFGBlockValues::updateBitVectorWithScratch(const CFGBlock *block) {
+ llvm::BitVector &dst = getBitVector(block, 0);
+ bool changed = (dst != scratch);
+ if (changed)
+ dst = scratch;
+#if 0
+ printVector(block, scratch, 0);
+#endif
+ return changed;
+}
+
+bool CFGBlockValues::updateBitVectors(const CFGBlock *block,
+ const BVPair &newVals) {
+ BVPair &vals = getBitVectors(block, true);
+ bool changed = *newVals.first != *vals.first ||
+ *newVals.second != *vals.second;
+ *vals.first = *newVals.first;
+ *vals.second = *newVals.second;
+#if 0
+ printVector(block, *vals.first, 1);
+ printVector(block, *vals.second, 2);
+#endif
+ return changed;
+}
+
+void CFGBlockValues::resetScratch() {
+ scratch.reset();
+}
+
+llvm::BitVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
+ const llvm::Optional<unsigned> &idx = declToBit.getBitVectorIndex(vd);
+ assert(idx.hasValue());
+ return scratch[idx.getValue()];
+}
+
+//------------------------------------------------------------------------====//
+// Worklist: worklist for dataflow analysis.
+//====------------------------------------------------------------------------//
+
+namespace {
+class DataflowWorklist {
+ llvm::SmallVector<const CFGBlock *, 20> worklist;
+ llvm::BitVector enqueuedBlocks;
+public:
+ DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {}
+
+ void enqueue(const CFGBlock *block);
+ void enqueueSuccessors(const CFGBlock *block);
+ const CFGBlock *dequeue();
+
+};
+}
+
+void DataflowWorklist::enqueue(const CFGBlock *block) {
+ if (!block)
+ return;
+ unsigned idx = block->getBlockID();
+ if (enqueuedBlocks[idx])
+ return;
+ worklist.push_back(block);
+ enqueuedBlocks[idx] = true;
+}
+
+void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
+ for (CFGBlock::const_succ_iterator I = block->succ_begin(),
+ E = block->succ_end(); I != E; ++I) {
+ enqueue(*I);
+ }
+}
+
+const CFGBlock *DataflowWorklist::dequeue() {
+ if (worklist.empty())
+ return 0;
+ const CFGBlock *b = worklist.back();
+ worklist.pop_back();
+ enqueuedBlocks[b->getBlockID()] = false;
+ return b;
+}
+
+//------------------------------------------------------------------------====//
+// Transfer function for uninitialized values analysis.
+//====------------------------------------------------------------------------//
+
+static const bool Initialized = false;
+static const bool Uninitialized = true;
+
+namespace {
+class FindVarResult {
+ const VarDecl *vd;
+ const DeclRefExpr *dr;
+public:
+ FindVarResult(VarDecl *vd, DeclRefExpr *dr) : vd(vd), dr(dr) {}
+
+ const DeclRefExpr *getDeclRefExpr() const { return dr; }
+ const VarDecl *getDecl() const { return vd; }
+};
+
+class TransferFunctions : public CFGRecStmtVisitor<TransferFunctions> {
+ CFGBlockValues &vals;
+ const CFG &cfg;
+ AnalysisContext &ac;
+ UninitVariablesHandler *handler;
+ const DeclRefExpr *currentDR;
+ const Expr *currentVoidCast;
+ const bool flagBlockUses;
+public:
+ TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
+ AnalysisContext &ac,
+ UninitVariablesHandler *handler,
+ bool flagBlockUses)
+ : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0),
+ currentVoidCast(0), flagBlockUses(flagBlockUses) {}
+
+ const CFG &getCFG() { return cfg; }
+ void reportUninit(const DeclRefExpr *ex, const VarDecl *vd);
+
+ void VisitBlockExpr(BlockExpr *be);
+ void VisitDeclStmt(DeclStmt *ds);
+ void VisitDeclRefExpr(DeclRefExpr *dr);
+ void VisitUnaryOperator(UnaryOperator *uo);
+ void VisitBinaryOperator(BinaryOperator *bo);
+ void VisitCastExpr(CastExpr *ce);
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se);
+ void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs);
+
+ bool isTrackedVar(const VarDecl *vd) {
+ return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl()));
+ }
+
+ FindVarResult findBlockVarDecl(Expr *ex);
+};
+}
+
+void TransferFunctions::reportUninit(const DeclRefExpr *ex,
+ const VarDecl *vd) {
+ if (handler) handler->handleUseOfUninitVariable(ex, vd);
+}
+
+FindVarResult TransferFunctions::findBlockVarDecl(Expr* ex) {
+ if (DeclRefExpr* dr = dyn_cast<DeclRefExpr>(ex->IgnoreParenCasts()))
+ if (VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
+ if (isTrackedVar(vd))
+ return FindVarResult(vd, dr);
+ return FindVarResult(0, 0);
+}
+
+void TransferFunctions::BlockStmt_VisitObjCForCollectionStmt(
+ ObjCForCollectionStmt *fs) {
+
+ Visit(fs->getCollection());
+
+ // This represents an initialization of the 'element' value.
+ Stmt *element = fs->getElement();
+ const VarDecl* vd = 0;
+
+ if (DeclStmt* ds = dyn_cast<DeclStmt>(element)) {
+ vd = cast<VarDecl>(ds->getSingleDecl());
+ if (!isTrackedVar(vd))
+ vd = 0;
+ }
+ else {
+ // Initialize the value of the reference variable.
+ const FindVarResult &res = findBlockVarDecl(cast<Expr>(element));
+ vd = res.getDecl();
+ if (!vd) {
+ Visit(element);
+ return;
+ }
+ }
+
+ if (vd)
+ vals[vd] = Initialized;
+}
+
+void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
+ if (!flagBlockUses || !handler)
+ return;
+ AnalysisContext::referenced_decls_iterator i, e;
+ llvm::tie(i, e) = ac.getReferencedBlockVars(be->getBlockDecl());
+ for ( ; i != e; ++i) {
+ const VarDecl *vd = *i;
+ if (vd->getAttr<BlocksAttr>() || !vd->hasLocalStorage() ||
+ !isTrackedVar(vd))
+ continue;
+ if (vals[vd] == Uninitialized)
+ handler->handleUseOfUninitVariable(be, vd);
+ }
+}
+
+void TransferFunctions::VisitDeclStmt(DeclStmt *ds) {
+ for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end();
+ DI != DE; ++DI) {
+ if (VarDecl *vd = dyn_cast<VarDecl>(*DI)) {
+ if (isTrackedVar(vd)) {
+ vals[vd] = Uninitialized;
+ if (Stmt *init = vd->getInit()) {
+ Visit(init);
+ vals[vd] = Initialized;
+ }
+ }
+ else if (Stmt *init = vd->getInit()) {
+ Visit(init);
+ }
+ }
+ }
+}
+
+void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
+ // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ // If a DeclRefExpr is not involved in a load, we are essentially computing
+ // its address, either for assignment to a reference or via the '&' operator.
+ // In such cases, treat the variable as being initialized, since this
+ // analysis isn't powerful enough to do alias tracking.
+ if (dr != currentDR)
+ if (const VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
+ if (isTrackedVar(vd))
+ vals[vd] = Initialized;
+}
+
+void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
+ if (bo->isAssignmentOp()) {
+ const FindVarResult &res = findBlockVarDecl(bo->getLHS());
+ if (const VarDecl* vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment"
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(bo->getRHS());
+ Visit(bo->getLHS());
+
+ llvm::BitVector::reference bit = vals[vd];
+ if (bit == Uninitialized) {
+ if (bo->getOpcode() != BO_Assign)
+ reportUninit(res.getDeclRefExpr(), vd);
+ bit = Initialized;
+ }
+ return;
+ }
+ }
+ Visit(bo->getRHS());
+ Visit(bo->getLHS());
+}
+
+void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) {
+ switch (uo->getOpcode()) {
+ case clang::UO_PostDec:
+ case clang::UO_PostInc:
+ case clang::UO_PreDec:
+ case clang::UO_PreInc: {
+ const FindVarResult &res = findBlockVarDecl(uo->getSubExpr());
+ if (const VarDecl *vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in a unary operator ++/--
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(uo->getSubExpr());
+
+ llvm::BitVector::reference bit = vals[vd];
+ if (bit == Uninitialized) {
+ reportUninit(res.getDeclRefExpr(), vd);
+ bit = Initialized;
+ }
+ return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ Visit(uo->getSubExpr());
+}
+
+void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
+ if (ce->getCastKind() == CK_LValueToRValue) {
+ const FindVarResult &res = findBlockVarDecl(ce->getSubExpr());
+ if (const VarDecl *vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ // Here we update 'currentDR' to be the one associated with this
+ // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we
+ // will know that we are not computing its lvalue for other purposes
+ // than to perform a load.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(ce->getSubExpr());
+ if (currentVoidCast != ce && vals[vd] == Uninitialized) {
+ reportUninit(res.getDeclRefExpr(), vd);
+ // Don't cascade warnings.
+ vals[vd] = Initialized;
+ }
+ return;
+ }
+ }
+ else if (CStyleCastExpr *cse = dyn_cast<CStyleCastExpr>(ce)) {
+ if (cse->getType()->isVoidType()) {
+ // e.g. (void) x;
+ SaveAndRestore<const Expr *>
+ lastVoidCast(currentVoidCast, cse->getSubExpr()->IgnoreParens());
+ Visit(cse->getSubExpr());
+ return;
+ }
+ }
+ Visit(ce->getSubExpr());
+}
+
+void TransferFunctions::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se) {
+ if (se->isSizeOf()) {
+ if (se->getType()->isConstantSizeType())
+ return;
+ // Handle VLAs.
+ Visit(se->getArgumentExpr());
+ }
+}
+
+//------------------------------------------------------------------------====//
+// High-level "driver" logic for uninitialized values analysis.
+//====------------------------------------------------------------------------//
+
+static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
+ AnalysisContext &ac, CFGBlockValues &vals,
+ UninitVariablesHandler *handler = 0,
+ bool flagBlockUses = false) {
+
+ if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
+ CFGBlock::const_pred_iterator itr = block->pred_begin();
+ BVPair vA = vals.getBitVectors(*itr, false);
+ ++itr;
+ BVPair vB = vals.getBitVectors(*itr, false);
+
+ BVPair valsAB;
+
+ if (b->getOpcode() == BO_LAnd) {
+ // Merge the 'F' bits from the first and second.
+ vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true);
+ vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false);
+ valsAB.first = vA.first;
+ valsAB.second = &vals.getScratch();
+ }
+ else {
+ // Merge the 'T' bits from the first and second.
+ assert(b->getOpcode() == BO_LOr);
+ vals.mergeIntoScratch(*vA.first, true);
+ vals.mergeIntoScratch(*vB.first, false);
+ valsAB.first = &vals.getScratch();
+ valsAB.second = vA.second ? vA.second : vA.first;
+ }
+ return vals.updateBitVectors(block, valsAB);
+ }
+
+ // Default behavior: merge in values of predecessor blocks.
+ vals.resetScratch();
+ bool isFirst = true;
+ for (CFGBlock::const_pred_iterator I = block->pred_begin(),
+ E = block->pred_end(); I != E; ++I) {
+ vals.mergeIntoScratch(vals.getBitVector(*I, block), isFirst);
+ isFirst = false;
+ }
+ // Apply the transfer function.
+ TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses);
+ for (CFGBlock::const_iterator I = block->begin(), E = block->end();
+ I != E; ++I) {
+ if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) {
+ tf.BlockStmt_Visit(cs->getStmt());
+ }
+ }
+ return vals.updateBitVectorWithScratch(block);
+}
+
+void clang::runUninitializedVariablesAnalysis(const DeclContext &dc,
+ const CFG &cfg,
+ AnalysisContext &ac,
+ UninitVariablesHandler &handler) {
+ CFGBlockValues vals(cfg);
+ vals.computeSetOfDeclarations(dc);
+ if (vals.hasNoDeclarations())
+ return;
+ DataflowWorklist worklist(cfg);
+ llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
+
+ worklist.enqueueSuccessors(&cfg.getEntry());
+
+ while (const CFGBlock *block = worklist.dequeue()) {
+ // Did the block change?
+ bool changed = runOnBlock(block, cfg, ac, vals);
+ if (changed || !previouslyVisited[block->getBlockID()])
+ worklist.enqueueSuccessors(block);
+ previouslyVisited[block->getBlockID()] = true;
+ }
+
+ // Run through the blocks one more time, and report uninitialized variabes.
+ for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
+ runOnBlock(*BI, cfg, ac, vals, &handler, /* flagBlockUses */ true);
+ }
+}
+
+UninitVariablesHandler::~UninitVariablesHandler() {}
+
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
new file mode 100644
index 0000000..845ae81
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -0,0 +1,123 @@
+//===--- Builtins.cpp - Builtin function implementation -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements various things for builtin functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/LangOptions.h"
+using namespace clang;
+
+static const Builtin::Info BuiltinInfo[] = {
+ { "not a builtin function", 0, 0, 0, ALL_LANGUAGES, false },
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\
+ BUILTIN_LANG, false },
+#include "clang/Basic/Builtins.def"
+};
+
+const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
+ if (ID < Builtin::FirstTSBuiltin)
+ return BuiltinInfo[ID];
+ assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
+ return TSRecords[ID - Builtin::FirstTSBuiltin];
+}
+
+Builtin::Context::Context(const TargetInfo &Target) {
+ // Get the target specific builtins from the target.
+ TSRecords = 0;
+ NumTSRecords = 0;
+ Target.getTargetBuiltins(TSRecords, NumTSRecords);
+}
+
+/// InitializeBuiltins - Mark the identifiers for all the builtins with their
+/// appropriate builtin ID # and mark any non-portable builtin identifiers as
+/// such.
+void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
+ const LangOptions& LangOpts) {
+ // Step #1: mark all target-independent builtins with their ID's.
+ for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
+ if (!BuiltinInfo[i].Suppressed &&
+ (!LangOpts.NoBuiltin || !strchr(BuiltinInfo[i].Attributes, 'f'))) {
+ if (LangOpts.ObjC1 ||
+ BuiltinInfo[i].builtin_lang != clang::OBJC_LANG)
+ Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
+ }
+
+ // Step #2: Register target-specific builtins.
+ for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
+ if (!TSRecords[i].Suppressed &&
+ (!LangOpts.NoBuiltin ||
+ (TSRecords[i].Attributes &&
+ !strchr(TSRecords[i].Attributes, 'f'))))
+ Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
+}
+
+void
+Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
+ bool NoBuiltins) {
+ // Final all target-independent names
+ for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
+ if (!BuiltinInfo[i].Suppressed &&
+ (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
+ Names.push_back(BuiltinInfo[i].Name);
+
+ // Find target-specific names.
+ for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
+ if (!TSRecords[i].Suppressed &&
+ (!NoBuiltins ||
+ (TSRecords[i].Attributes &&
+ !strchr(TSRecords[i].Attributes, 'f'))))
+ Names.push_back(TSRecords[i].Name);
+}
+
+void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) {
+ Table.get(GetRecord(ID).Name).setBuiltinID(0);
+}
+
+bool
+Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ const char *Printf = strpbrk(GetRecord(ID).Attributes, "pP");
+ if (!Printf)
+ return false;
+
+ HasVAListArg = (*Printf == 'P');
+
+ ++Printf;
+ assert(*Printf == ':' && "p or P specifier must have be followed by a ':'");
+ ++Printf;
+
+ assert(strchr(Printf, ':') && "printf specifier must end with a ':'");
+ FormatIdx = strtol(Printf, 0, 10);
+ return true;
+}
+
+// FIXME: Refactor with isPrintfLike.
+bool
+Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS");
+ if (!Scanf)
+ return false;
+
+ HasVAListArg = (*Scanf == 'S');
+
+ ++Scanf;
+ assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'");
+ ++Scanf;
+
+ assert(strchr(Scanf, ':') && "printf specifier must end with a ':'");
+ FormatIdx = strtol(Scanf, 0, 10);
+ return true;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Basic/ConvertUTF.c b/contrib/llvm/tools/clang/lib/Basic/ConvertUTF.c
new file mode 100644
index 0000000..124e386
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/ConvertUTF.c
@@ -0,0 +1,547 @@
+/*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *===------------------------------------------------------------------------=*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Sept 2001: fixed const & error conditions per
+ mods suggested by S. Parent & A. Lillich.
+ June 2002: Tim Dodd added detection and handling of incomplete
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
+ July 2003: slight mods to back out aggressive FFFE detection.
+ Jan 2004: updated switches in from-UTF8 conversions.
+ Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+ See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+
+#include "clang/Basic/ConvertUTF.h"
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+#define false 0
+#define true 1
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+#ifdef CLANG_NEEDS_THESE_ONE_DAY
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16* source = *sourceStart;
+ UTF32* target = *targetStart;
+ UTF32 ch, ch2;
+ while (source < sourceEnd) {
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+#ifdef CVTUTF_DEBUG
+if (result == sourceIllegal) {
+ fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
+ fflush(stderr);
+}
+#endif
+ return result;
+}
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF32 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8* source = *sourceStart;
+ UTF32* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up the source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static Boolean isLegalUTF8(const UTF8 *source, int length) {
+ UTF8 a;
+ const UTF8 *srcptr = source+length;
+ switch (length) {
+ default: return false;
+ /* Everything else falls through when "true"... */
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
+
+ case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4) return false;
+ return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
+ int length = trailingBytesForUTF8[*source]+1;
+ if (source+length > sourceEnd) {
+ return false;
+ }
+ return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead+1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
new file mode 100644
index 0000000..31e3331
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -0,0 +1,687 @@
+//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Diagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
+ const char *Modifier, unsigned ML,
+ const char *Argument, unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie) {
+ const char *Str = "<can't format argument>";
+ Output.append(Str, Str+strlen(Str));
+}
+
+
+Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags,
+ DiagnosticClient *client, bool ShouldOwnClient)
+ : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient),
+ SourceMgr(0) {
+ ArgToStringFn = DummyArgToStringFn;
+ ArgToStringCookie = 0;
+
+ AllExtensionsSilenced = 0;
+ IgnoreAllWarnings = false;
+ WarningsAsErrors = false;
+ ErrorsAsFatal = false;
+ SuppressSystemWarnings = false;
+ SuppressAllDiagnostics = false;
+ ShowOverloads = Ovl_All;
+ ExtBehavior = Ext_Ignore;
+
+ ErrorLimit = 0;
+ TemplateBacktraceLimit = 0;
+
+ // Create a DiagState and DiagStatePoint representing diagnostic changes
+ // through command-line.
+ DiagStates.push_back(DiagState());
+ PushDiagStatePoint(&DiagStates.back(), SourceLocation());
+
+ Reset();
+}
+
+Diagnostic::~Diagnostic() {
+ if (OwnsDiagClient)
+ delete Client;
+}
+
+void Diagnostic::setClient(DiagnosticClient *client, bool ShouldOwnClient) {
+ if (OwnsDiagClient && Client)
+ delete Client;
+
+ Client = client;
+ OwnsDiagClient = ShouldOwnClient;
+}
+
+void Diagnostic::pushMappings(SourceLocation Loc) {
+ DiagStateOnPushStack.push_back(GetCurDiagState());
+}
+
+bool Diagnostic::popMappings(SourceLocation Loc) {
+ if (DiagStateOnPushStack.empty())
+ return false;
+
+ if (DiagStateOnPushStack.back() != GetCurDiagState()) {
+ // State changed at some point between push/pop.
+ PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
+ }
+ DiagStateOnPushStack.pop_back();
+ return true;
+}
+
+void Diagnostic::Reset() {
+ ErrorOccurred = false;
+ FatalErrorOccurred = false;
+
+ NumWarnings = 0;
+ NumErrors = 0;
+ NumErrorsSuppressed = 0;
+ CurDiagID = ~0U;
+ // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes
+ // using a Diagnostic associated to a translation unit that follow
+ // diagnostics from a Diagnostic associated to anoter t.u. will not be
+ // displayed.
+ LastDiagLevel = (DiagnosticIDs::Level)-1;
+ DelayedDiagID = 0;
+}
+
+void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1,
+ llvm::StringRef Arg2) {
+ if (DelayedDiagID)
+ return;
+
+ DelayedDiagID = DiagID;
+ DelayedDiagArg1 = Arg1.str();
+ DelayedDiagArg2 = Arg2.str();
+}
+
+void Diagnostic::ReportDelayed() {
+ Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2;
+ DelayedDiagID = 0;
+ DelayedDiagArg1.clear();
+ DelayedDiagArg2.clear();
+}
+
+Diagnostic::DiagStatePointsTy::iterator
+Diagnostic::GetDiagStatePointForLoc(SourceLocation L) const {
+ assert(!DiagStatePoints.empty());
+ assert(DiagStatePoints.front().Loc.isInvalid() &&
+ "Should have created a DiagStatePoint for command-line");
+
+ FullSourceLoc Loc(L, *SourceMgr);
+ if (Loc.isInvalid())
+ return DiagStatePoints.end() - 1;
+
+ DiagStatePointsTy::iterator Pos = DiagStatePoints.end();
+ FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
+ if (LastStateChangePos.isValid() &&
+ Loc.isBeforeInTranslationUnitThan(LastStateChangePos))
+ Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(),
+ DiagStatePoint(0, Loc));
+ --Pos;
+ return Pos;
+}
+
+/// \brief This allows the client to specify that certain
+/// warnings are ignored. Notes can never be mapped, errors can only be
+/// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
+///
+/// \param The source location that this change of diagnostic state should
+/// take affect. It can be null if we are setting the latest state.
+void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
+ SourceLocation L) {
+ assert(Diag < diag::DIAG_UPPER_LIMIT &&
+ "Can only map builtin diagnostics");
+ assert((Diags->isBuiltinWarningOrExtension(Diag) ||
+ (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) &&
+ "Cannot map errors into warnings!");
+ assert(!DiagStatePoints.empty());
+
+ bool isPragma = L.isValid();
+ FullSourceLoc Loc(L, *SourceMgr);
+ FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
+
+ // Common case; setting all the diagnostics of a group in one place.
+ if (Loc.isInvalid() || Loc == LastStateChangePos) {
+ setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma);
+ return;
+ }
+
+ // Another common case; modifying diagnostic state in a source location
+ // after the previous one.
+ if ((Loc.isValid() && LastStateChangePos.isInvalid()) ||
+ LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) {
+ // A diagnostic pragma occured, create a new DiagState initialized with
+ // the current one and a new DiagStatePoint to record at which location
+ // the new state became active.
+ DiagStates.push_back(*GetCurDiagState());
+ PushDiagStatePoint(&DiagStates.back(), Loc);
+ setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma);
+ return;
+ }
+
+ // We allow setting the diagnostic state in random source order for
+ // completeness but it should not be actually happening in normal practice.
+
+ DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc);
+ assert(Pos != DiagStatePoints.end());
+
+ // Update all diagnostic states that are active after the given location.
+ for (DiagStatePointsTy::iterator
+ I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) {
+ setDiagnosticMappingInternal(Diag, Map, I->State, true, isPragma);
+ }
+
+ // If the location corresponds to an existing point, just update its state.
+ if (Pos->Loc == Loc) {
+ setDiagnosticMappingInternal(Diag, Map, Pos->State, true, isPragma);
+ return;
+ }
+
+ // Create a new state/point and fit it into the vector of DiagStatePoints
+ // so that the vector is always ordered according to location.
+ Pos->Loc.isBeforeInTranslationUnitThan(Loc);
+ DiagStates.push_back(*Pos->State);
+ DiagState *NewState = &DiagStates.back();
+ setDiagnosticMappingInternal(Diag, Map, NewState, true, isPragma);
+ DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState,
+ FullSourceLoc(Loc, *SourceMgr)));
+}
+
+void DiagnosticBuilder::FlushCounts() {
+ DiagObj->NumDiagArgs = NumArgs;
+ DiagObj->NumDiagRanges = NumRanges;
+ DiagObj->NumFixItHints = NumFixItHints;
+}
+
+bool DiagnosticBuilder::Emit() {
+ // If DiagObj is null, then its soul was stolen by the copy ctor
+ // or the user called Emit().
+ if (DiagObj == 0) return false;
+
+ // When emitting diagnostics, we set the final argument count into
+ // the Diagnostic object.
+ FlushCounts();
+
+ // Process the diagnostic, sending the accumulated information to the
+ // DiagnosticClient.
+ bool Emitted = DiagObj->ProcessDiag();
+
+ // Clear out the current diagnostic object.
+ unsigned DiagID = DiagObj->CurDiagID;
+ DiagObj->Clear();
+
+ // If there was a delayed diagnostic, emit it now.
+ if (DiagObj->DelayedDiagID && DiagObj->DelayedDiagID != DiagID)
+ DiagObj->ReportDelayed();
+
+ // This diagnostic is dead.
+ DiagObj = 0;
+
+ return Emitted;
+}
+
+
+DiagnosticClient::~DiagnosticClient() {}
+
+void DiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ if (!IncludeInDiagnosticCounts())
+ return;
+
+ if (DiagLevel == Diagnostic::Warning)
+ ++NumWarnings;
+ else if (DiagLevel >= Diagnostic::Error)
+ ++NumErrors;
+}
+
+/// ModifierIs - Return true if the specified modifier matches specified string.
+template <std::size_t StrLen>
+static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
+ const char (&Str)[StrLen]) {
+ return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
+}
+
+/// ScanForward - Scans forward, looking for the given character, skipping
+/// nested clauses and escaped characters.
+static const char *ScanFormat(const char *I, const char *E, char Target) {
+ unsigned Depth = 0;
+
+ for ( ; I != E; ++I) {
+ if (Depth == 0 && *I == Target) return I;
+ if (Depth != 0 && *I == '}') Depth--;
+
+ if (*I == '%') {
+ I++;
+ if (I == E) break;
+
+ // Escaped characters get implicitly skipped here.
+
+ // Format specifier.
+ if (!isdigit(*I) && !ispunct(*I)) {
+ for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ;
+ if (I == E) break;
+ if (*I == '{')
+ Depth++;
+ }
+ }
+ }
+ return E;
+}
+
+/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
+/// like this: %select{foo|bar|baz}2. This means that the integer argument
+/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
+/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
+/// This is very useful for certain classes of variant diagnostics.
+static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo,
+ const char *Argument, unsigned ArgumentLen,
+ llvm::SmallVectorImpl<char> &OutStr) {
+ const char *ArgumentEnd = Argument+ArgumentLen;
+
+ // Skip over 'ValNo' |'s.
+ while (ValNo) {
+ const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
+ assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
+ " larger than the number of options in the diagnostic string!");
+ Argument = NextVal+1; // Skip this string.
+ --ValNo;
+ }
+
+ // Get the end of the value. This is either the } or the |.
+ const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Recursively format the result of the select clause into the output string.
+ DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
+}
+
+/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
+/// letter 's' to the string if the value is not 1. This is used in cases like
+/// this: "you idiot, you have %4 parameter%s4!".
+static void HandleIntegerSModifier(unsigned ValNo,
+ llvm::SmallVectorImpl<char> &OutStr) {
+ if (ValNo != 1)
+ OutStr.push_back('s');
+}
+
+/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
+/// prints the ordinal form of the given integer, with 1 corresponding
+/// to the first ordinal. Currently this is hard-coded to use the
+/// English form.
+static void HandleOrdinalModifier(unsigned ValNo,
+ llvm::SmallVectorImpl<char> &OutStr) {
+ assert(ValNo != 0 && "ValNo must be strictly positive!");
+
+ llvm::raw_svector_ostream Out(OutStr);
+
+ // We could use text forms for the first N ordinals, but the numeric
+ // forms are actually nicer in diagnostics because they stand out.
+ Out << ValNo;
+
+ // It is critically important that we do this perfectly for
+ // user-written sequences with over 100 elements.
+ switch (ValNo % 100) {
+ case 11:
+ case 12:
+ case 13:
+ Out << "th"; return;
+ default:
+ switch (ValNo % 10) {
+ case 1: Out << "st"; return;
+ case 2: Out << "nd"; return;
+ case 3: Out << "rd"; return;
+ default: Out << "th"; return;
+ }
+ }
+}
+
+
+/// PluralNumber - Parse an unsigned integer and advance Start.
+static unsigned PluralNumber(const char *&Start, const char *End) {
+ // Programming 101: Parse a decimal number :-)
+ unsigned Val = 0;
+ while (Start != End && *Start >= '0' && *Start <= '9') {
+ Val *= 10;
+ Val += *Start - '0';
+ ++Start;
+ }
+ return Val;
+}
+
+/// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
+static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
+ if (*Start != '[') {
+ unsigned Ref = PluralNumber(Start, End);
+ return Ref == Val;
+ }
+
+ ++Start;
+ unsigned Low = PluralNumber(Start, End);
+ assert(*Start == ',' && "Bad plural expression syntax: expected ,");
+ ++Start;
+ unsigned High = PluralNumber(Start, End);
+ assert(*Start == ']' && "Bad plural expression syntax: expected )");
+ ++Start;
+ return Low <= Val && Val <= High;
+}
+
+/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
+static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
+ // Empty condition?
+ if (*Start == ':')
+ return true;
+
+ while (1) {
+ char C = *Start;
+ if (C == '%') {
+ // Modulo expression
+ ++Start;
+ unsigned Arg = PluralNumber(Start, End);
+ assert(*Start == '=' && "Bad plural expression syntax: expected =");
+ ++Start;
+ unsigned ValMod = ValNo % Arg;
+ if (TestPluralRange(ValMod, Start, End))
+ return true;
+ } else {
+ assert((C == '[' || (C >= '0' && C <= '9')) &&
+ "Bad plural expression syntax: unexpected character");
+ // Range expression
+ if (TestPluralRange(ValNo, Start, End))
+ return true;
+ }
+
+ // Scan for next or-expr part.
+ Start = std::find(Start, End, ',');
+ if (Start == End)
+ break;
+ ++Start;
+ }
+ return false;
+}
+
+/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
+/// for complex plural forms, or in languages where all plurals are complex.
+/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
+/// conditions that are tested in order, the form corresponding to the first
+/// that applies being emitted. The empty condition is always true, making the
+/// last form a default case.
+/// Conditions are simple boolean expressions, where n is the number argument.
+/// Here are the rules.
+/// condition := expression | empty
+/// empty := -> always true
+/// expression := numeric [',' expression] -> logical or
+/// numeric := range -> true if n in range
+/// | '%' number '=' range -> true if n % number in range
+/// range := number
+/// | '[' number ',' number ']' -> ranges are inclusive both ends
+///
+/// Here are some examples from the GNU gettext manual written in this form:
+/// English:
+/// {1:form0|:form1}
+/// Latvian:
+/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
+/// Gaeilge:
+/// {1:form0|2:form1|:form2}
+/// Romanian:
+/// {1:form0|0,%100=[1,19]:form1|:form2}
+/// Lithuanian:
+/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
+/// Russian (requires repeated form):
+/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
+/// Slovak
+/// {1:form0|[2,4]:form1|:form2}
+/// Polish (requires repeated form):
+/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
+static void HandlePluralModifier(const DiagnosticInfo &DInfo, unsigned ValNo,
+ const char *Argument, unsigned ArgumentLen,
+ llvm::SmallVectorImpl<char> &OutStr) {
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ while (1) {
+ assert(Argument < ArgumentEnd && "Plural expression didn't match.");
+ const char *ExprEnd = Argument;
+ while (*ExprEnd != ':') {
+ assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
+ ++ExprEnd;
+ }
+ if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
+ Argument = ExprEnd + 1;
+ ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
+
+ // Recursively format the result of the plural clause into the
+ // output string.
+ DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
+ return;
+ }
+ Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
+ }
+}
+
+
+/// FormatDiagnostic - Format this diagnostic into a string, substituting the
+/// formal arguments into the %0 slots. The result is appended onto the Str
+/// array.
+void DiagnosticInfo::
+FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
+ const char *DiagStr = getDiags()->getDiagnosticIDs()->getDescription(getID());
+ const char *DiagEnd = DiagStr+strlen(DiagStr);
+
+ FormatDiagnostic(DiagStr, DiagEnd, OutStr);
+}
+
+void DiagnosticInfo::
+FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ llvm::SmallVectorImpl<char> &OutStr) const {
+
+ /// FormattedArgs - Keep track of all of the arguments formatted by
+ /// ConvertArgToString and pass them into subsequent calls to
+ /// ConvertArgToString, allowing the implementation to avoid redundancies in
+ /// obvious cases.
+ llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs;
+
+ while (DiagStr != DiagEnd) {
+ if (DiagStr[0] != '%') {
+ // Append non-%0 substrings to Str if we have one.
+ const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
+ OutStr.append(DiagStr, StrEnd);
+ DiagStr = StrEnd;
+ continue;
+ } else if (ispunct(DiagStr[1])) {
+ OutStr.push_back(DiagStr[1]); // %% -> %.
+ DiagStr += 2;
+ continue;
+ }
+
+ // Skip the %.
+ ++DiagStr;
+
+ // This must be a placeholder for a diagnostic argument. The format for a
+ // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
+ // The digit is a number from 0-9 indicating which argument this comes from.
+ // The modifier is a string of digits from the set [-a-z]+, arguments is a
+ // brace enclosed string.
+ const char *Modifier = 0, *Argument = 0;
+ unsigned ModifierLen = 0, ArgumentLen = 0;
+
+ // Check to see if we have a modifier. If so eat it.
+ if (!isdigit(DiagStr[0])) {
+ Modifier = DiagStr;
+ while (DiagStr[0] == '-' ||
+ (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
+ ++DiagStr;
+ ModifierLen = DiagStr-Modifier;
+
+ // If we have an argument, get it next.
+ if (DiagStr[0] == '{') {
+ ++DiagStr; // Skip {.
+ Argument = DiagStr;
+
+ DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
+ assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
+ ArgumentLen = DiagStr-Argument;
+ ++DiagStr; // Skip }.
+ }
+ }
+
+ assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
+ unsigned ArgNo = *DiagStr++ - '0';
+
+ Diagnostic::ArgumentKind Kind = getArgKind(ArgNo);
+
+ switch (Kind) {
+ // ---- STRINGS ----
+ case Diagnostic::ak_std_string: {
+ const std::string &S = getArgStdStr(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+ OutStr.append(S.begin(), S.end());
+ break;
+ }
+ case Diagnostic::ak_c_string: {
+ const char *S = getArgCStr(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+
+ // Don't crash if get passed a null pointer by accident.
+ if (!S)
+ S = "(null)";
+
+ OutStr.append(S, S + strlen(S));
+ break;
+ }
+ // ---- INTEGERS ----
+ case Diagnostic::ak_sint: {
+ int Val = getArgSInt(ArgNo);
+
+ if (ModifierIs(Modifier, ModifierLen, "select")) {
+ HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "s")) {
+ HandleIntegerSModifier(Val, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
+ HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier((unsigned)Val, OutStr);
+ } else {
+ assert(ModifierLen == 0 && "Unknown integer modifier");
+ llvm::raw_svector_ostream(OutStr) << Val;
+ }
+ break;
+ }
+ case Diagnostic::ak_uint: {
+ unsigned Val = getArgUInt(ArgNo);
+
+ if (ModifierIs(Modifier, ModifierLen, "select")) {
+ HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "s")) {
+ HandleIntegerSModifier(Val, OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
+ HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
+ OutStr);
+ } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
+ HandleOrdinalModifier(Val, OutStr);
+ } else {
+ assert(ModifierLen == 0 && "Unknown integer modifier");
+ llvm::raw_svector_ostream(OutStr) << Val;
+ }
+ break;
+ }
+ // ---- NAMES and TYPES ----
+ case Diagnostic::ak_identifierinfo: {
+ const IdentifierInfo *II = getArgIdentifier(ArgNo);
+ assert(ModifierLen == 0 && "No modifiers for strings yet");
+
+ // Don't crash if get passed a null pointer by accident.
+ if (!II) {
+ const char *S = "(null)";
+ OutStr.append(S, S + strlen(S));
+ continue;
+ }
+
+ llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
+ break;
+ }
+ case Diagnostic::ak_qualtype:
+ case Diagnostic::ak_declarationname:
+ case Diagnostic::ak_nameddecl:
+ case Diagnostic::ak_nestednamespec:
+ case Diagnostic::ak_declcontext:
+ getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
+ Modifier, ModifierLen,
+ Argument, ArgumentLen,
+ FormattedArgs.data(), FormattedArgs.size(),
+ OutStr);
+ break;
+ }
+
+ // Remember this argument info for subsequent formatting operations. Turn
+ // std::strings into a null terminated string to make it be the same case as
+ // all the other ones.
+ if (Kind != Diagnostic::ak_std_string)
+ FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
+ else
+ FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string,
+ (intptr_t)getArgStdStr(ArgNo).c_str()));
+
+ }
+}
+
+StoredDiagnostic::StoredDiagnostic() { }
+
+StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
+ llvm::StringRef Message)
+ : ID(ID), Level(Level), Loc(), Message(Message) { }
+
+StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
+ const DiagnosticInfo &Info)
+ : ID(Info.getID()), Level(Level)
+{
+ assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
+ "Valid source location without setting a source manager for diagnostic");
+ if (Info.getLocation().isValid())
+ Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
+ llvm::SmallString<64> Message;
+ Info.FormatDiagnostic(Message);
+ this->Message.assign(Message.begin(), Message.end());
+
+ Ranges.reserve(Info.getNumRanges());
+ for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
+ Ranges.push_back(Info.getRange(I));
+
+ FixIts.reserve(Info.getNumFixItHints());
+ for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
+ FixIts.push_back(Info.getFixItHint(I));
+}
+
+StoredDiagnostic::~StoredDiagnostic() { }
+
+/// IncludeInDiagnosticCounts - This method (whose default implementation
+/// returns true) indicates whether the diagnostics handled by this
+/// DiagnosticClient should be included in the number of diagnostics
+/// reported by Diagnostic.
+bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }
+
+PartialDiagnostic::StorageAllocator::StorageAllocator() {
+ for (unsigned I = 0; I != NumCached; ++I)
+ FreeList[I] = Cached + I;
+ NumFreeListEntries = NumCached;
+}
+
+PartialDiagnostic::StorageAllocator::~StorageAllocator() {
+ assert(NumFreeListEntries == NumCached && "A partial is on the lamb");
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
new file mode 100644
index 0000000..8725e7f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -0,0 +1,586 @@
+//===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Diagnostic IDs-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Builtin Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+// Diagnostic classes.
+enum {
+ CLASS_NOTE = 0x01,
+ CLASS_WARNING = 0x02,
+ CLASS_EXTENSION = 0x03,
+ CLASS_ERROR = 0x04
+};
+
+struct StaticDiagInfoRec {
+ unsigned short DiagID;
+ unsigned Mapping : 3;
+ unsigned Class : 3;
+ unsigned SFINAE : 1;
+ unsigned AccessControl : 1;
+ unsigned Category : 5;
+
+ const char *Description;
+ const char *OptionGroup;
+
+ bool operator<(const StaticDiagInfoRec &RHS) const {
+ return DiagID < RHS.DiagID;
+ }
+};
+
+}
+
+static const StaticDiagInfoRec StaticDiagInfo[] = {
+#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) \
+ { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, DESC, GROUP },
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+ { 0, 0, 0, 0, 0, 0, 0, 0}
+};
+#undef DIAG
+
+/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
+/// or null if the ID is invalid.
+static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
+ unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
+
+ // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
+#ifndef NDEBUG
+ static bool IsFirst = true;
+ if (IsFirst) {
+ for (unsigned i = 1; i != NumDiagEntries; ++i) {
+ assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
+ "Diag ID conflict, the enums at the start of clang::diag (in "
+ "DiagnosticIDs.h) probably need to be increased");
+
+ assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
+ "Improperly sorted diag info");
+ }
+ IsFirst = false;
+ }
+#endif
+
+ // Search the diagnostic table with a binary search.
+ StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0 };
+
+ const StaticDiagInfoRec *Found =
+ std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
+ if (Found == StaticDiagInfo + NumDiagEntries ||
+ Found->DiagID != DiagID)
+ return 0;
+
+ return Found;
+}
+
+static unsigned GetDefaultDiagMapping(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Mapping;
+ return diag::MAP_FATAL;
+}
+
+/// getWarningOptionForDiag - Return the lowest-level warning option that
+/// enables the specified diagnostic. If there is no -Wfoo flag that controls
+/// the diagnostic, this returns null.
+const char *DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->OptionGroup;
+ return 0;
+}
+
+/// getWarningOptionForDiag - Return the category number that a specified
+/// DiagID belongs to, or 0 if no category.
+unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Category;
+ return 0;
+}
+
+/// getCategoryNameFromID - Given a category ID, return the name of the
+/// category, an empty string if CategoryID is zero, or null if CategoryID is
+/// invalid.
+const char *DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
+ // Second the table of options, sorted by name for fast binary lookup.
+ static const char *CategoryNameTable[] = {
+#define GET_CATEGORY_TABLE
+#define CATEGORY(X) X,
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_CATEGORY_TABLE
+ "<<END>>"
+ };
+ static const size_t CategoryNameTableSize =
+ sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
+
+ if (CategoryID >= CategoryNameTableSize) return 0;
+ return CategoryNameTable[CategoryID];
+}
+
+
+
+DiagnosticIDs::SFINAEResponse
+DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
+ if (Info->AccessControl)
+ return SFINAE_AccessControl;
+
+ if (!Info->SFINAE)
+ return SFINAE_Report;
+
+ if (Info->Class == CLASS_ERROR)
+ return SFINAE_SubstitutionFailure;
+
+ // Suppress notes, warnings, and extensions;
+ return SFINAE_Suppress;
+ }
+
+ return SFINAE_Report;
+}
+
+/// getDiagClass - Return the class field of the diagnostic.
+///
+static unsigned getBuiltinDiagClass(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Class;
+ return ~0U;
+}
+
+//===----------------------------------------------------------------------===//
+// Custom Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ namespace diag {
+ class CustomDiagInfo {
+ typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
+ std::vector<DiagDesc> DiagInfo;
+ std::map<DiagDesc, unsigned> DiagIDs;
+ public:
+
+ /// getDescription - Return the description of the specified custom
+ /// diagnostic.
+ const char *getDescription(unsigned DiagID) const {
+ assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnosic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
+ }
+
+ /// getLevel - Return the level of the specified custom diagnostic.
+ DiagnosticIDs::Level getLevel(unsigned DiagID) const {
+ assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnosic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
+ }
+
+ unsigned getOrCreateDiagID(DiagnosticIDs::Level L, llvm::StringRef Message,
+ DiagnosticIDs &Diags) {
+ DiagDesc D(L, Message);
+ // Check to see if it already exists.
+ std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+ if (I != DiagIDs.end() && I->first == D)
+ return I->second;
+
+ // If not, assign a new ID.
+ unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
+ DiagIDs.insert(std::make_pair(D, ID));
+ DiagInfo.push_back(D);
+ return ID;
+ }
+ };
+
+ } // end diag namespace
+} // end clang namespace
+
+
+//===----------------------------------------------------------------------===//
+// Common Diagnostic implementation
+//===----------------------------------------------------------------------===//
+
+DiagnosticIDs::DiagnosticIDs() {
+ CustomDiagInfo = 0;
+}
+
+DiagnosticIDs::~DiagnosticIDs() {
+ delete CustomDiagInfo;
+}
+
+/// getCustomDiagID - Return an ID for a diagnostic with the specified message
+/// and level. If this is the first request for this diagnosic, it is
+/// registered and created, otherwise the existing ID is returned.
+unsigned DiagnosticIDs::getCustomDiagID(Level L, llvm::StringRef Message) {
+ if (CustomDiagInfo == 0)
+ CustomDiagInfo = new diag::CustomDiagInfo();
+ return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
+}
+
+
+/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
+/// level of the specified diagnostic ID is a Warning or Extension.
+/// This only works on builtin diagnostics, not custom ones, and is not legal to
+/// call on NOTEs.
+bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) != CLASS_ERROR;
+}
+
+/// \brief Determine whether the given built-in diagnostic ID is a
+/// Note.
+bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) == CLASS_NOTE;
+}
+
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+/// ID is for an extension of some sort. This also returns EnabledByDefault,
+/// which is set to indicate whether the diagnostic is ignored by default (in
+/// which case -pedantic enables it) or treated as a warning/error by default.
+///
+bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
+ bool &EnabledByDefault) {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT ||
+ getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
+ return false;
+
+ EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
+ return true;
+}
+
+/// getDescription - Given a diagnostic ID, return a description of the
+/// issue.
+const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Description;
+ return CustomDiagInfo->getDescription(DiagID);
+}
+
+/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+DiagnosticIDs::Level
+DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ const Diagnostic &Diag) const {
+ // Handle custom diagnostics, which cannot be mapped.
+ if (DiagID >= diag::DIAG_UPPER_LIMIT)
+ return CustomDiagInfo->getLevel(DiagID);
+
+ unsigned DiagClass = getBuiltinDiagClass(DiagID);
+ assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
+ return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
+}
+
+/// \brief Based on the way the client configured the Diagnostic
+/// object, classify the specified diagnostic ID into a Level, consumable by
+/// the DiagnosticClient.
+///
+/// \param Loc The source location we are interested in finding out the
+/// diagnostic state. Can be null in order to query the latest state.
+DiagnosticIDs::Level
+DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
+ SourceLocation Loc,
+ const Diagnostic &Diag) const {
+ // Specific non-error diagnostics may be mapped to various levels from ignored
+ // to error. Errors can only be mapped to fatal.
+ DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
+
+ Diagnostic::DiagStatePointsTy::iterator
+ Pos = Diag.GetDiagStatePointForLoc(Loc);
+ Diagnostic::DiagState *State = Pos->State;
+
+ // Get the mapping information, if unset, compute it lazily.
+ unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID,
+ State);
+ if (MappingInfo == 0) {
+ MappingInfo = GetDefaultDiagMapping(DiagID);
+ Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false);
+ }
+
+ switch (MappingInfo & 7) {
+ default: assert(0 && "Unknown mapping!");
+ case diag::MAP_IGNORE:
+ // Ignore this, unless this is an extension diagnostic and we're mapping
+ // them onto warnings or errors.
+ if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
+ Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored
+ (MappingInfo & 8) != 0) // User explicitly mapped it.
+ return DiagnosticIDs::Ignored;
+ Result = DiagnosticIDs::Warning;
+ if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error;
+ if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
+ Result = DiagnosticIDs::Fatal;
+ break;
+ case diag::MAP_ERROR:
+ Result = DiagnosticIDs::Error;
+ if (Diag.ErrorsAsFatal)
+ Result = DiagnosticIDs::Fatal;
+ break;
+ case diag::MAP_FATAL:
+ Result = DiagnosticIDs::Fatal;
+ break;
+ case diag::MAP_WARNING:
+ // If warnings are globally mapped to ignore or error, do it.
+ if (Diag.IgnoreAllWarnings)
+ return DiagnosticIDs::Ignored;
+
+ Result = DiagnosticIDs::Warning;
+
+ // If this is an extension diagnostic and we're in -pedantic-error mode, and
+ // if the user didn't explicitly map it, upgrade to an error.
+ if (Diag.ExtBehavior == Diagnostic::Ext_Error &&
+ (MappingInfo & 8) == 0 &&
+ isBuiltinExtensionDiag(DiagID))
+ Result = DiagnosticIDs::Error;
+
+ if (Diag.WarningsAsErrors)
+ Result = DiagnosticIDs::Error;
+ if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
+ Result = DiagnosticIDs::Fatal;
+ break;
+
+ case diag::MAP_WARNING_NO_WERROR:
+ // Diagnostics specified with -Wno-error=foo should be set to warnings, but
+ // not be adjusted by -Werror or -pedantic-errors.
+ Result = DiagnosticIDs::Warning;
+
+ // If warnings are globally mapped to ignore or error, do it.
+ if (Diag.IgnoreAllWarnings)
+ return DiagnosticIDs::Ignored;
+
+ break;
+
+ case diag::MAP_ERROR_NO_WFATAL:
+ // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
+ // unaffected by -Wfatal-errors.
+ Result = DiagnosticIDs::Error;
+ break;
+ }
+
+ // Okay, we're about to return this as a "diagnostic to emit" one last check:
+ // if this is any sort of extension warning, and if we're in an __extension__
+ // block, silence it.
+ if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
+ return DiagnosticIDs::Ignored;
+
+ return Result;
+}
+
+struct WarningOption {
+ const char *Name;
+ const short *Members;
+ const short *SubGroups;
+};
+
+#define GET_DIAG_ARRAYS
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_ARRAYS
+
+// Second the table of options, sorted by name for fast binary lookup.
+static const WarningOption OptionTable[] = {
+#define GET_DIAG_TABLE
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_DIAG_TABLE
+};
+static const size_t OptionTableSize =
+sizeof(OptionTable) / sizeof(OptionTable[0]);
+
+static bool WarningOptionCompare(const WarningOption &LHS,
+ const WarningOption &RHS) {
+ return strcmp(LHS.Name, RHS.Name) < 0;
+}
+
+static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
+ SourceLocation Loc, Diagnostic &Diag) {
+ // Option exists, poke all the members of its diagnostic set.
+ if (const short *Member = Group->Members) {
+ for (; *Member != -1; ++Member)
+ Diag.setDiagnosticMapping(*Member, Mapping, Loc);
+ }
+
+ // Enable/disable all subgroups along with this one.
+ if (const short *SubGroups = Group->SubGroups) {
+ for (; *SubGroups != (short)-1; ++SubGroups)
+ MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag);
+ }
+}
+
+/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+/// "unknown-pragmas" to have the specified mapping. This returns true and
+/// ignores the request if "Group" was unknown, false otherwise.
+bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group,
+ diag::Mapping Map,
+ SourceLocation Loc,
+ Diagnostic &Diag) const {
+ assert((Loc.isValid() ||
+ Diag.DiagStatePoints.empty() ||
+ Diag.DiagStatePoints.back().Loc.isInvalid()) &&
+ "Loc should be invalid only when the mapping comes from command-line");
+ assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() ||
+ Diag.DiagStatePoints.back().Loc.isInvalid() ||
+ !Diag.SourceMgr->isBeforeInTranslationUnit(Loc,
+ Diag.DiagStatePoints.back().Loc)) &&
+ "Source location of new mapping is before the previous one!");
+
+ WarningOption Key = { Group, 0, 0 };
+ const WarningOption *Found =
+ std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
+ WarningOptionCompare);
+ if (Found == OptionTable + OptionTableSize ||
+ strcmp(Found->Name, Group) != 0)
+ return true; // Option not found.
+
+ MapGroupMembers(Found, Map, Loc, Diag);
+ return false;
+}
+
+/// ProcessDiag - This is the method used to report a diagnostic that is
+/// finally fully formed.
+bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
+ DiagnosticInfo Info(&Diag);
+
+ if (Diag.SuppressAllDiagnostics)
+ return false;
+
+ assert(Diag.getClient() && "DiagnosticClient not set!");
+
+ // Figure out the diagnostic level of this message.
+ DiagnosticIDs::Level DiagLevel;
+ unsigned DiagID = Info.getID();
+
+ // ShouldEmitInSystemHeader - True if this diagnostic should be produced even
+ // in a system header.
+ bool ShouldEmitInSystemHeader;
+
+ if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ // Handle custom diagnostics, which cannot be mapped.
+ DiagLevel = CustomDiagInfo->getLevel(DiagID);
+
+ // Custom diagnostics always are emitted in system headers.
+ ShouldEmitInSystemHeader = true;
+ } else {
+ // Get the class of the diagnostic. If this is a NOTE, map it onto whatever
+ // the diagnostic level was for the previous diagnostic so that it is
+ // filtered the same as the previous diagnostic.
+ unsigned DiagClass = getBuiltinDiagClass(DiagID);
+ if (DiagClass == CLASS_NOTE) {
+ DiagLevel = DiagnosticIDs::Note;
+ ShouldEmitInSystemHeader = false; // extra consideration is needed
+ } else {
+ // If this is not an error and we are in a system header, we ignore it.
+ // Check the original Diag ID here, because we also want to ignore
+ // extensions and warnings in -Werror and -pedantic-errors modes, which
+ // *map* warnings/extensions to errors.
+ ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
+
+ DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
+ Diag);
+ }
+ }
+
+ if (DiagLevel != DiagnosticIDs::Note) {
+ // Record that a fatal error occurred only when we see a second
+ // non-note diagnostic. This allows notes to be attached to the
+ // fatal error, but suppresses any diagnostics that follow those
+ // notes.
+ if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
+ Diag.FatalErrorOccurred = true;
+
+ Diag.LastDiagLevel = DiagLevel;
+ }
+
+ // If a fatal error has already been emitted, silence all subsequent
+ // diagnostics.
+ if (Diag.FatalErrorOccurred) {
+ if (DiagLevel >= DiagnosticIDs::Error &&
+ Diag.Client->IncludeInDiagnosticCounts()) {
+ ++Diag.NumErrors;
+ ++Diag.NumErrorsSuppressed;
+ }
+
+ return false;
+ }
+
+ // If the client doesn't care about this message, don't issue it. If this is
+ // a note and the last real diagnostic was ignored, ignore it too.
+ if (DiagLevel == DiagnosticIDs::Ignored ||
+ (DiagLevel == DiagnosticIDs::Note &&
+ Diag.LastDiagLevel == DiagnosticIDs::Ignored))
+ return false;
+
+ // If this diagnostic is in a system header and is not a clang error, suppress
+ // it.
+ if (Diag.SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
+ Info.getLocation().isValid() &&
+ Diag.getSourceManager().isInSystemHeader(
+ Diag.getSourceManager().getInstantiationLoc(Info.getLocation())) &&
+ (DiagLevel != DiagnosticIDs::Note ||
+ Diag.LastDiagLevel == DiagnosticIDs::Ignored)) {
+ Diag.LastDiagLevel = DiagnosticIDs::Ignored;
+ return false;
+ }
+
+ if (DiagLevel >= DiagnosticIDs::Error) {
+ if (Diag.Client->IncludeInDiagnosticCounts()) {
+ Diag.ErrorOccurred = true;
+ ++Diag.NumErrors;
+ }
+
+ // If we've emitted a lot of errors, emit a fatal error after it to stop a
+ // flood of bogus errors.
+ if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit &&
+ DiagLevel == DiagnosticIDs::Error)
+ Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
+ }
+
+ // If we have any Fix-Its, make sure that all of the Fix-Its point into
+ // source locations that aren't macro instantiations. If any point into
+ // macro instantiations, remove all of the Fix-Its.
+ for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) {
+ const FixItHint &FixIt = Diag.FixItHints[I];
+ if (FixIt.RemoveRange.isInvalid() ||
+ FixIt.RemoveRange.getBegin().isMacroID() ||
+ FixIt.RemoveRange.getEnd().isMacroID()) {
+ Diag.NumFixItHints = 0;
+ break;
+ }
+ }
+
+ // Finally, report it.
+ Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info);
+ if (Diag.Client->IncludeInDiagnosticCounts()) {
+ if (DiagLevel == DiagnosticIDs::Warning)
+ ++Diag.NumWarnings;
+ }
+
+ Diag.CurDiagID = ~0U;
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
new file mode 100644
index 0000000..342413d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -0,0 +1,568 @@
+//===--- FileManager.cpp - File System Probing and Caching ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the FileManager interface.
+//
+//===----------------------------------------------------------------------===//
+//
+// TODO: This should index all interesting directories with dirent calls.
+// getdirentries ?
+// opendir/readdir_r/closedir ?
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Config/config.h"
+#include <map>
+#include <set>
+#include <string>
+
+// FIXME: This is terrible, we need this for ::close.
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#include <sys/uio.h>
+#else
+#include <io.h>
+#endif
+using namespace clang;
+
+// FIXME: Enhance libsystem to support inode and other fields.
+#include <sys/stat.h>
+
+/// NON_EXISTENT_DIR - A special value distinct from null that is used to
+/// represent a dir name that doesn't exist on the disk.
+#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
+
+/// NON_EXISTENT_FILE - A special value distinct from null that is used to
+/// represent a filename that doesn't exist on the disk.
+#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
+
+
+FileEntry::~FileEntry() {
+ // If this FileEntry owns an open file descriptor that never got used, close
+ // it.
+ if (FD != -1) ::close(FD);
+}
+
+//===----------------------------------------------------------------------===//
+// Windows.
+//===----------------------------------------------------------------------===//
+
+#ifdef LLVM_ON_WIN32
+
+namespace {
+ static std::string GetFullPath(const char *relPath) {
+ char *absPathStrPtr = _fullpath(NULL, relPath, 0);
+ assert(absPathStrPtr && "_fullpath() returned NULL!");
+
+ std::string absPath(absPathStrPtr);
+
+ free(absPathStrPtr);
+ return absPath;
+ }
+}
+
+class FileManager::UniqueDirContainer {
+ /// UniqueDirs - Cache from full path to existing directories/files.
+ ///
+ llvm::StringMap<DirectoryEntry> UniqueDirs;
+
+public:
+ /// getDirectory - Return an existing DirectoryEntry with the given
+ /// name if there is already one; otherwise create and return a
+ /// default-constructed DirectoryEntry.
+ DirectoryEntry &getDirectory(const char *Name,
+ const struct stat & /*StatBuf*/) {
+ std::string FullPath(GetFullPath(Name));
+ return UniqueDirs.GetOrCreateValue(FullPath).getValue();
+ }
+
+ size_t size() const { return UniqueDirs.size(); }
+};
+
+class FileManager::UniqueFileContainer {
+ /// UniqueFiles - Cache from full path to existing directories/files.
+ ///
+ llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles;
+
+public:
+ /// getFile - Return an existing FileEntry with the given name if
+ /// there is already one; otherwise create and return a
+ /// default-constructed FileEntry.
+ FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) {
+ std::string FullPath(GetFullPath(Name));
+
+ // LowercaseString because Windows filesystem is case insensitive.
+ FullPath = llvm::LowercaseString(FullPath);
+ return UniqueFiles.GetOrCreateValue(FullPath).getValue();
+ }
+
+ size_t size() const { return UniqueFiles.size(); }
+};
+
+//===----------------------------------------------------------------------===//
+// Unix-like Systems.
+//===----------------------------------------------------------------------===//
+
+#else
+
+class FileManager::UniqueDirContainer {
+ /// UniqueDirs - Cache from ID's to existing directories/files.
+ std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
+
+public:
+ /// getDirectory - Return an existing DirectoryEntry with the given
+ /// ID's if there is already one; otherwise create and return a
+ /// default-constructed DirectoryEntry.
+ DirectoryEntry &getDirectory(const char * /*Name*/,
+ const struct stat &StatBuf) {
+ return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
+ }
+
+ size_t size() const { return UniqueDirs.size(); }
+};
+
+class FileManager::UniqueFileContainer {
+ /// UniqueFiles - Cache from ID's to existing directories/files.
+ std::set<FileEntry> UniqueFiles;
+
+public:
+ /// getFile - Return an existing FileEntry with the given ID's if
+ /// there is already one; otherwise create and return a
+ /// default-constructed FileEntry.
+ FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) {
+ return
+ const_cast<FileEntry&>(
+ *UniqueFiles.insert(FileEntry(StatBuf.st_dev,
+ StatBuf.st_ino,
+ StatBuf.st_mode)).first);
+ }
+
+ size_t size() const { return UniqueFiles.size(); }
+};
+
+#endif
+
+//===----------------------------------------------------------------------===//
+// Common logic.
+//===----------------------------------------------------------------------===//
+
+FileManager::FileManager(const FileSystemOptions &FSO)
+ : FileSystemOpts(FSO),
+ UniqueRealDirs(*new UniqueDirContainer()),
+ UniqueRealFiles(*new UniqueFileContainer()),
+ SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) {
+ NumDirLookups = NumFileLookups = 0;
+ NumDirCacheMisses = NumFileCacheMisses = 0;
+}
+
+FileManager::~FileManager() {
+ delete &UniqueRealDirs;
+ delete &UniqueRealFiles;
+ for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i)
+ delete VirtualFileEntries[i];
+ for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i)
+ delete VirtualDirectoryEntries[i];
+}
+
+void FileManager::addStatCache(FileSystemStatCache *statCache,
+ bool AtBeginning) {
+ assert(statCache && "No stat cache provided?");
+ if (AtBeginning || StatCache.get() == 0) {
+ statCache->setNextStatCache(StatCache.take());
+ StatCache.reset(statCache);
+ return;
+ }
+
+ FileSystemStatCache *LastCache = StatCache.get();
+ while (LastCache->getNextStatCache())
+ LastCache = LastCache->getNextStatCache();
+
+ LastCache->setNextStatCache(statCache);
+}
+
+void FileManager::removeStatCache(FileSystemStatCache *statCache) {
+ if (!statCache)
+ return;
+
+ if (StatCache.get() == statCache) {
+ // This is the first stat cache.
+ StatCache.reset(StatCache->takeNextStatCache());
+ return;
+ }
+
+ // Find the stat cache in the list.
+ FileSystemStatCache *PrevCache = StatCache.get();
+ while (PrevCache && PrevCache->getNextStatCache() != statCache)
+ PrevCache = PrevCache->getNextStatCache();
+
+ assert(PrevCache && "Stat cache not found for removal");
+ PrevCache->setNextStatCache(statCache->getNextStatCache());
+}
+
+/// \brief Retrieve the directory that the given file name resides in.
+/// Filename can point to either a real file or a virtual file.
+static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
+ llvm::StringRef Filename) {
+ if (Filename.empty())
+ return NULL;
+
+ if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
+ return NULL; // If Filename is a directory.
+
+ llvm::StringRef DirName = llvm::sys::path::parent_path(Filename);
+ // Use the current directory if file has no path component.
+ if (DirName.empty())
+ DirName = ".";
+
+ return FileMgr.getDirectory(DirName);
+}
+
+/// Add all ancestors of the given path (pointing to either a file or
+/// a directory) as virtual directories.
+void FileManager::addAncestorsAsVirtualDirs(llvm::StringRef Path) {
+ llvm::StringRef DirName = llvm::sys::path::parent_path(Path);
+ if (DirName.empty())
+ return;
+
+ llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
+ SeenDirEntries.GetOrCreateValue(DirName);
+
+ // When caching a virtual directory, we always cache its ancestors
+ // at the same time. Therefore, if DirName is already in the cache,
+ // we don't need to recurse as its ancestors must also already be in
+ // the cache.
+ if (NamedDirEnt.getValue())
+ return;
+
+ // Add the virtual directory to the cache.
+ DirectoryEntry *UDE = new DirectoryEntry;
+ UDE->Name = NamedDirEnt.getKeyData();
+ NamedDirEnt.setValue(UDE);
+ VirtualDirectoryEntries.push_back(UDE);
+
+ // Recursively add the other ancestors.
+ addAncestorsAsVirtualDirs(DirName);
+}
+
+/// getDirectory - Lookup, cache, and verify the specified directory
+/// (real or virtual). This returns NULL if the directory doesn't
+/// exist.
+///
+const DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) {
+ // stat doesn't like trailing separators (at least on Windows).
+ if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back()))
+ DirName = DirName.substr(0, DirName.size()-1);
+
+ ++NumDirLookups;
+ llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
+ SeenDirEntries.GetOrCreateValue(DirName);
+
+ // See if there was already an entry in the map. Note that the map
+ // contains both virtual and real directories.
+ if (NamedDirEnt.getValue())
+ return NamedDirEnt.getValue() == NON_EXISTENT_DIR
+ ? 0 : NamedDirEnt.getValue();
+
+ ++NumDirCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedDirEnt.setValue(NON_EXISTENT_DIR);
+
+ // Get the null-terminated directory name as stored as the key of the
+ // SeenDirEntries map.
+ const char *InterndDirName = NamedDirEnt.getKeyData();
+
+ // Check to see if the directory exists.
+ struct stat StatBuf;
+ if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) {
+ // There's no real directory at the given path.
+ return 0;
+ }
+
+ // It exists. See if we have already opened a directory with the
+ // same inode (this occurs on Unix-like systems when one dir is
+ // symlinked to another, for example) or the same path (on
+ // Windows).
+ DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf);
+
+ NamedDirEnt.setValue(&UDE);
+ if (!UDE.getName()) {
+ // We don't have this directory yet, add it. We use the string
+ // key from the SeenDirEntries map as the string.
+ UDE.Name = InterndDirName;
+ }
+
+ return &UDE;
+}
+
+/// getFile - Lookup, cache, and verify the specified file (real or
+/// virtual). This returns NULL if the file doesn't exist.
+///
+const FileEntry *FileManager::getFile(llvm::StringRef Filename) {
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
+ SeenFileEntries.GetOrCreateValue(Filename);
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.getValue())
+ return NamedFileEnt.getValue() == NON_EXISTENT_FILE
+ ? 0 : NamedFileEnt.getValue();
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.setValue(NON_EXISTENT_FILE);
+
+ // Get the null-terminated file name as stored as the key of the
+ // SeenFileEntries map.
+ const char *InterndFileName = NamedFileEnt.getKeyData();
+
+ // Look up the directory for the file. When looking up something like
+ // sys/foo.h we'll discover all of the search directories that have a 'sys'
+ // subdirectory. This will let us avoid having to waste time on known-to-fail
+ // searches when we go to find sys/bar.h, because all the search directories
+ // without a 'sys' subdir will get a cached failure result.
+ const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename);
+ if (DirInfo == 0) // Directory doesn't exist, file can't exist.
+ return 0;
+
+ // FIXME: Use the directory info to prune this, before doing the stat syscall.
+ // FIXME: This will reduce the # syscalls.
+
+ // Nope, there isn't. Check to see if the file exists.
+ int FileDescriptor = -1;
+ struct stat StatBuf;
+ if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) {
+ // There's no real file at the given path.
+ return 0;
+ }
+
+ // It exists. See if we have already opened a file with the same inode.
+ // This occurs when one dir is symlinked to another, for example.
+ FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf);
+
+ NamedFileEnt.setValue(&UFE);
+ if (UFE.getName()) { // Already have an entry with this inode, return it.
+ // If the stat process opened the file, close it to avoid a FD leak.
+ if (FileDescriptor != -1)
+ close(FileDescriptor);
+
+ return &UFE;
+ }
+
+ // Otherwise, we don't have this directory yet, add it.
+ // FIXME: Change the name to be a char* that points back to the
+ // 'SeenFileEntries' key.
+ UFE.Name = InterndFileName;
+ UFE.Size = StatBuf.st_size;
+ UFE.ModTime = StatBuf.st_mtime;
+ UFE.Dir = DirInfo;
+ UFE.UID = NextFileUID++;
+ UFE.FD = FileDescriptor;
+ return &UFE;
+}
+
+const FileEntry *
+FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
+ time_t ModificationTime) {
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
+ SeenFileEntries.GetOrCreateValue(Filename);
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE)
+ return NamedFileEnt.getValue();
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.setValue(NON_EXISTENT_FILE);
+
+ addAncestorsAsVirtualDirs(Filename);
+ FileEntry *UFE = 0;
+
+ // Now that all ancestors of Filename are in the cache, the
+ // following call is guaranteed to find the DirectoryEntry from the
+ // cache.
+ const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename);
+ assert(DirInfo &&
+ "The directory of a virtual file should already be in the cache.");
+
+ // Check to see if the file exists. If so, drop the virtual file
+ int FileDescriptor = -1;
+ struct stat StatBuf;
+ const char *InterndFileName = NamedFileEnt.getKeyData();
+ if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) {
+ // If the stat process opened the file, close it to avoid a FD leak.
+ if (FileDescriptor != -1)
+ close(FileDescriptor);
+
+ StatBuf.st_size = Size;
+ StatBuf.st_mtime = ModificationTime;
+ UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf);
+
+ NamedFileEnt.setValue(UFE);
+
+ // If we had already opened this file, close it now so we don't
+ // leak the descriptor. We're not going to use the file
+ // descriptor anyway, since this is a virtual file.
+ if (UFE->FD != -1) {
+ close(UFE->FD);
+ UFE->FD = -1;
+ }
+
+ // If we already have an entry with this inode, return it.
+ if (UFE->getName())
+ return UFE;
+ }
+
+ if (!UFE) {
+ UFE = new FileEntry();
+ VirtualFileEntries.push_back(UFE);
+ NamedFileEnt.setValue(UFE);
+ }
+
+ UFE->Name = InterndFileName;
+ UFE->Size = Size;
+ UFE->ModTime = ModificationTime;
+ UFE->Dir = DirInfo;
+ UFE->UID = NextFileUID++;
+ UFE->FD = -1;
+ return UFE;
+}
+
+void FileManager::FixupRelativePath(llvm::sys::Path &path,
+ const FileSystemOptions &FSOpts) {
+ if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(path.str()))
+ return;
+
+ llvm::SmallString<128> NewPath(FSOpts.WorkingDir);
+ llvm::sys::path::append(NewPath, path.str());
+ path = NewPath;
+}
+
+llvm::MemoryBuffer *FileManager::
+getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
+ llvm::OwningPtr<llvm::MemoryBuffer> Result;
+ llvm::error_code ec;
+ if (FileSystemOpts.WorkingDir.empty()) {
+ const char *Filename = Entry->getName();
+ // If the file is already open, use the open file descriptor.
+ if (Entry->FD != -1) {
+ ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
+ Entry->getSize());
+ if (ErrorStr)
+ *ErrorStr = ec.message();
+
+ close(Entry->FD);
+ Entry->FD = -1;
+ return Result.take();
+ }
+
+ // Otherwise, open the file.
+ ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize());
+ if (ec && ErrorStr)
+ *ErrorStr = ec.message();
+ return Result.take();
+ }
+
+ llvm::sys::Path FilePath(Entry->getName());
+ FixupRelativePath(FilePath, FileSystemOpts);
+ ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result, Entry->getSize());
+ if (ec && ErrorStr)
+ *ErrorStr = ec.message();
+ return Result.take();
+}
+
+llvm::MemoryBuffer *FileManager::
+getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) {
+ llvm::OwningPtr<llvm::MemoryBuffer> Result;
+ llvm::error_code ec;
+ if (FileSystemOpts.WorkingDir.empty()) {
+ ec = llvm::MemoryBuffer::getFile(Filename, Result);
+ if (ec && ErrorStr)
+ *ErrorStr = ec.message();
+ return Result.take();
+ }
+
+ llvm::sys::Path FilePath(Filename);
+ FixupRelativePath(FilePath, FileSystemOpts);
+ ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
+ if (ec && ErrorStr)
+ *ErrorStr = ec.message();
+ return Result.take();
+}
+
+/// getStatValue - Get the 'stat' information for the specified path,
+/// using the cache to accelerate it if possible. This returns true
+/// if the path points to a virtual file or does not exist, or returns
+/// false if it's an existent real file. If FileDescriptor is NULL,
+/// do directory look-up instead of file look-up.
+bool FileManager::getStatValue(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
+ // absolute!
+ if (FileSystemOpts.WorkingDir.empty())
+ return FileSystemStatCache::get(Path, StatBuf, FileDescriptor,
+ StatCache.get());
+
+ llvm::sys::Path FilePath(Path);
+ FixupRelativePath(FilePath, FileSystemOpts);
+
+ return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor,
+ StatCache.get());
+}
+
+void FileManager::GetUniqueIDMapping(
+ llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
+ UIDToFiles.clear();
+ UIDToFiles.resize(NextFileUID);
+
+ // Map file entries
+ for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
+ FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
+ FE != FEEnd; ++FE)
+ if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE)
+ UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
+
+ // Map virtual file entries
+ for (llvm::SmallVector<FileEntry*, 4>::const_iterator
+ VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end();
+ VFE != VFEEnd; ++VFE)
+ if (*VFE && *VFE != NON_EXISTENT_FILE)
+ UIDToFiles[(*VFE)->getUID()] = *VFE;
+}
+
+
+void FileManager::PrintStats() const {
+ llvm::errs() << "\n*** File Manager Stats:\n";
+ llvm::errs() << UniqueRealFiles.size() << " real files found, "
+ << UniqueRealDirs.size() << " real dirs found.\n";
+ llvm::errs() << VirtualFileEntries.size() << " virtual files found, "
+ << VirtualDirectoryEntries.size() << " virtual dirs found.\n";
+ llvm::errs() << NumDirLookups << " dir lookups, "
+ << NumDirCacheMisses << " dir cache misses.\n";
+ llvm::errs() << NumFileLookups << " file lookups, "
+ << NumFileCacheMisses << " file cache misses.\n";
+
+ //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
new file mode 100644
index 0000000..c8b07af
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/FileSystemStatCache.cpp
@@ -0,0 +1,120 @@
+//===--- FileSystemStatCache.cpp - Caching for 'stat' calls ---------------===//
+//
+// 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 FileSystemStatCache interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileSystemStatCache.h"
+#include "llvm/Support/Path.h"
+#include <fcntl.h>
+
+// FIXME: This is terrible, we need this for ::close.
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#include <sys/uio.h>
+#else
+#include <io.h>
+#endif
+using namespace clang;
+
+#if defined(_MSC_VER)
+#define S_ISDIR(s) ((_S_IFDIR & s) !=0)
+#endif
+
+/// FileSystemStatCache::get - Get the 'stat' information for the specified
+/// path, using the cache to accelerate it if possible. This returns true if
+/// the path does not exist or false if it exists.
+///
+/// If FileDescriptor is non-null, then this lookup should only return success
+/// for files (not directories). If it is null this lookup should only return
+/// success for directories (not files). On a successful file lookup, the
+/// implementation can optionally fill in FileDescriptor with a valid
+/// descriptor and the client guarantees that it will close it.
+bool FileSystemStatCache::get(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor, FileSystemStatCache *Cache) {
+ LookupResult R;
+ bool isForDir = FileDescriptor == 0;
+
+ // If we have a cache, use it to resolve the stat query.
+ if (Cache)
+ R = Cache->getStat(Path, StatBuf, FileDescriptor);
+ else if (isForDir) {
+ // If this is a directory and we have no cache, just go to the file system.
+ R = ::stat(Path, &StatBuf) != 0 ? CacheMissing : CacheExists;
+ } else {
+ // Otherwise, we have to go to the filesystem. We can always just use
+ // 'stat' here, but (for files) the client is asking whether the file exists
+ // because it wants to turn around and *open* it. It is more efficient to
+ // do "open+fstat" on success than it is to do "stat+open".
+ //
+ // Because of this, check to see if the file exists with 'open'. If the
+ // open succeeds, use fstat to get the stat info.
+ int OpenFlags = O_RDONLY;
+#ifdef O_BINARY
+ OpenFlags |= O_BINARY; // Open input file in binary mode on win32.
+#endif
+ *FileDescriptor = ::open(Path, OpenFlags);
+
+ if (*FileDescriptor == -1) {
+ // If the open fails, our "stat" fails.
+ R = CacheMissing;
+ } else {
+ // Otherwise, the open succeeded. Do an fstat to get the information
+ // about the file. We'll end up returning the open file descriptor to the
+ // client to do what they please with it.
+ if (::fstat(*FileDescriptor, &StatBuf) == 0)
+ R = CacheExists;
+ else {
+ // fstat rarely fails. If it does, claim the initial open didn't
+ // succeed.
+ R = CacheMissing;
+ ::close(*FileDescriptor);
+ *FileDescriptor = -1;
+ }
+ }
+ }
+
+ // If the path doesn't exist, return failure.
+ if (R == CacheMissing) return true;
+
+ // If the path exists, make sure that its "directoryness" matches the clients
+ // demands.
+ if (S_ISDIR(StatBuf.st_mode) != isForDir) {
+ // If not, close the file if opened.
+ if (FileDescriptor && *FileDescriptor != -1) {
+ ::close(*FileDescriptor);
+ *FileDescriptor = -1;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+MemorizeStatCalls::LookupResult
+MemorizeStatCalls::getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ LookupResult Result = statChained(Path, StatBuf, FileDescriptor);
+
+ // Do not cache failed stats, it is easy to construct common inconsistent
+ // situations if we do, and they are not important for PCH performance (which
+ // currently only needs the stats to construct the initial FileManager
+ // entries).
+ if (Result == CacheMissing)
+ return Result;
+
+ // Cache file 'stat' results and directories with absolutely paths.
+ if (!S_ISDIR(StatBuf.st_mode) || llvm::sys::path::is_absolute(Path))
+ StatCalls[Path] = StatBuf;
+
+ return Result;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
new file mode 100644
index 0000000..ef11d65
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -0,0 +1,427 @@
+//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierInfo, IdentifierVisitor, and
+// IdentifierTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdentifierInfo Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo::IdentifierInfo() {
+ TokenID = tok::identifier;
+ ObjCOrBuiltinID = 0;
+ HasMacro = false;
+ IsExtension = false;
+ IsPoisoned = false;
+ IsCPPOperatorKeyword = false;
+ NeedsHandleIdentifier = false;
+ IsFromAST = false;
+ RevertedTokenID = false;
+ FETokenInfo = 0;
+ Entry = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// IdentifierTable Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierIterator::~IdentifierIterator() { }
+
+IdentifierInfoLookup::~IdentifierInfoLookup() {}
+
+namespace {
+ /// \brief A simple identifier lookup iterator that represents an
+ /// empty sequence of identifiers.
+ class EmptyLookupIterator : public IdentifierIterator
+ {
+ public:
+ virtual llvm::StringRef Next() { return llvm::StringRef(); }
+ };
+}
+
+IdentifierIterator *IdentifierInfoLookup::getIdentifiers() const {
+ return new EmptyLookupIterator();
+}
+
+ExternalIdentifierLookup::~ExternalIdentifierLookup() {}
+
+IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup* externalLookup)
+ : HashTable(8192), // Start with space for 8K identifiers.
+ ExternalLookup(externalLookup) {
+
+ // Populate the identifier table with info about keywords for the current
+ // language.
+ AddKeywords(LangOpts);
+}
+
+//===----------------------------------------------------------------------===//
+// Language Keyword Implementation
+//===----------------------------------------------------------------------===//
+
+// Constants for TokenKinds.def
+namespace {
+ enum {
+ KEYALL = 1,
+ KEYC99 = 2,
+ KEYCXX = 4,
+ KEYCXX0X = 8,
+ KEYGNU = 16,
+ KEYMS = 32,
+ BOOLSUPPORT = 64,
+ KEYALTIVEC = 128,
+ KEYNOCXX = 256,
+ KEYBORLAND = 512,
+ KEYOPENCL = 1024
+ };
+}
+
+/// AddKeyword - This method is used to associate a token ID with specific
+/// identifiers because they are language keywords. This causes the lexer to
+/// automatically map matching identifiers to specialized token codes.
+///
+/// The C90/C99/CPP/CPP0x flags are set to 2 if the token should be
+/// enabled in the specified langauge, set to 1 if it is an extension
+/// in the specified language, and set to 0 if disabled in the
+/// specified language.
+static void AddKeyword(llvm::StringRef Keyword,
+ tok::TokenKind TokenCode, unsigned Flags,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ unsigned AddResult = 0;
+ if (Flags & KEYALL) AddResult = 2;
+ else if (LangOpts.CPlusPlus && (Flags & KEYCXX)) AddResult = 2;
+ else if (LangOpts.CPlusPlus0x && (Flags & KEYCXX0X)) AddResult = 2;
+ else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2;
+ else if (LangOpts.GNUKeywords && (Flags & KEYGNU)) AddResult = 1;
+ else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1;
+ else if (LangOpts.Borland && (Flags & KEYBORLAND)) AddResult = 1;
+ else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2;
+ else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2;
+ else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2;
+ else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2;
+
+ // Don't add this keyword if disabled in this language.
+ if (AddResult == 0) return;
+
+ IdentifierInfo &Info = Table.get(Keyword, TokenCode);
+ Info.setIsExtensionToken(AddResult == 1);
+}
+
+/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
+/// representations.
+static void AddCXXOperatorKeyword(llvm::StringRef Keyword,
+ tok::TokenKind TokenCode,
+ IdentifierTable &Table) {
+ IdentifierInfo &Info = Table.get(Keyword, TokenCode);
+ Info.setIsCPlusPlusOperatorKeyword();
+}
+
+/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
+/// "property".
+static void AddObjCKeyword(llvm::StringRef Name,
+ tok::ObjCKeywordKind ObjCID,
+ IdentifierTable &Table) {
+ Table.get(Name).setObjCKeywordID(ObjCID);
+}
+
+/// AddKeywords - Add all keywords to the symbol table.
+///
+void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
+ // Add keywords and tokens for the current language.
+#define KEYWORD(NAME, FLAGS) \
+ AddKeyword(llvm::StringRef(#NAME), tok::kw_ ## NAME, \
+ FLAGS, LangOpts, *this);
+#define ALIAS(NAME, TOK, FLAGS) \
+ AddKeyword(llvm::StringRef(NAME), tok::kw_ ## TOK, \
+ FLAGS, LangOpts, *this);
+#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
+ if (LangOpts.CXXOperatorNames) \
+ AddCXXOperatorKeyword(llvm::StringRef(#NAME), tok::ALIAS, *this);
+#define OBJC1_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC1) \
+ AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this);
+#define OBJC2_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC2) \
+ AddObjCKeyword(llvm::StringRef(#NAME), tok::objc_##NAME, *this);
+#include "clang/Basic/TokenKinds.def"
+}
+
+tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
+ // We use a perfect hash function here involving the length of the keyword,
+ // the first and third character. For preprocessor ID's there are no
+ // collisions (if there were, the switch below would complain about duplicate
+ // case values). Note that this depends on 'if' being null terminated.
+
+#define HASH(LEN, FIRST, THIRD) \
+ (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
+#define CASE(LEN, FIRST, THIRD, NAME) \
+ case HASH(LEN, FIRST, THIRD): \
+ return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
+
+ unsigned Len = getLength();
+ if (Len < 2) return tok::pp_not_keyword;
+ const char *Name = getNameStart();
+ switch (HASH(Len, Name[0], Name[2])) {
+ default: return tok::pp_not_keyword;
+ CASE( 2, 'i', '\0', if);
+ CASE( 4, 'e', 'i', elif);
+ CASE( 4, 'e', 's', else);
+ CASE( 4, 'l', 'n', line);
+ CASE( 4, 's', 'c', sccs);
+ CASE( 5, 'e', 'd', endif);
+ CASE( 5, 'e', 'r', error);
+ CASE( 5, 'i', 'e', ident);
+ CASE( 5, 'i', 'd', ifdef);
+ CASE( 5, 'u', 'd', undef);
+
+ CASE( 6, 'a', 's', assert);
+ CASE( 6, 'd', 'f', define);
+ CASE( 6, 'i', 'n', ifndef);
+ CASE( 6, 'i', 'p', import);
+ CASE( 6, 'p', 'a', pragma);
+
+ CASE( 7, 'd', 'f', defined);
+ CASE( 7, 'i', 'c', include);
+ CASE( 7, 'w', 'r', warning);
+
+ CASE( 8, 'u', 'a', unassert);
+ CASE(12, 'i', 'c', include_next);
+
+ CASE(16, '_', 'i', __include_macros);
+#undef CASE
+#undef HASH
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Stats Implementation
+//===----------------------------------------------------------------------===//
+
+/// PrintStats - Print statistics about how well the identifier table is doing
+/// at hashing identifiers.
+void IdentifierTable::PrintStats() const {
+ unsigned NumBuckets = HashTable.getNumBuckets();
+ unsigned NumIdentifiers = HashTable.getNumItems();
+ unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
+ unsigned AverageIdentifierSize = 0;
+ unsigned MaxIdentifierLength = 0;
+
+ // TODO: Figure out maximum times an identifier had to probe for -stats.
+ for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
+ I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
+ unsigned IdLen = I->getKeyLength();
+ AverageIdentifierSize += IdLen;
+ if (MaxIdentifierLength < IdLen)
+ MaxIdentifierLength = IdLen;
+ }
+
+ fprintf(stderr, "\n*** Identifier Table Stats:\n");
+ fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
+ fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
+ fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
+ NumIdentifiers/(double)NumBuckets);
+ fprintf(stderr, "Ave identifier length: %f\n",
+ (AverageIdentifierSize/(double)NumIdentifiers));
+ fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
+
+ // Compute statistics about the memory allocated for identifiers.
+ HashTable.getAllocator().PrintStats();
+}
+
+//===----------------------------------------------------------------------===//
+// SelectorTable Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
+ return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
+}
+
+namespace clang {
+/// MultiKeywordSelector - One of these variable length records is kept for each
+/// selector containing more than one keyword. We use a folding set
+/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
+/// this class is provided strictly through Selector.
+class MultiKeywordSelector
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
+ MultiKeywordSelector(unsigned nKeys) {
+ ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
+ }
+public:
+ // Constructor for keyword selectors.
+ MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ assert((nKeys > 1) && "not a multi-keyword selector");
+ ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
+
+ // Fill in the trailing keyword array.
+ IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
+ for (unsigned i = 0; i != nKeys; ++i)
+ KeyInfo[i] = IIV[i];
+ }
+
+ // getName - Derive the full selector name and return it.
+ std::string getName() const;
+
+ unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
+
+ typedef IdentifierInfo *const *keyword_iterator;
+ keyword_iterator keyword_begin() const {
+ return reinterpret_cast<keyword_iterator>(this+1);
+ }
+ keyword_iterator keyword_end() const {
+ return keyword_begin()+getNumArgs();
+ }
+ IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
+ assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
+ return keyword_begin()[i];
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ keyword_iterator ArgTys, unsigned NumArgs) {
+ ID.AddInteger(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddPointer(ArgTys[i]);
+ }
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, keyword_begin(), getNumArgs());
+ }
+};
+} // end namespace clang.
+
+unsigned Selector::getNumArgs() const {
+ unsigned IIF = getIdentifierInfoFlag();
+ if (IIF == ZeroArg)
+ return 0;
+ if (IIF == OneArg)
+ return 1;
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getNumArgs();
+}
+
+IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
+ if (getIdentifierInfoFlag()) {
+ assert(argIndex == 0 && "illegal keyword index");
+ return getAsIdentifierInfo();
+ }
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getIdentifierInfoForSlot(argIndex);
+}
+
+llvm::StringRef Selector::getNameForSlot(unsigned int argIndex) const {
+ IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
+ return II? II->getName() : llvm::StringRef();
+}
+
+std::string MultiKeywordSelector::getName() const {
+ llvm::SmallString<256> Str;
+ llvm::raw_svector_ostream OS(Str);
+ for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
+ if (*I)
+ OS << (*I)->getName();
+ OS << ':';
+ }
+
+ return OS.str();
+}
+
+std::string Selector::getAsString() const {
+ if (InfoPtr == 0)
+ return "<null selector>";
+
+ if (InfoPtr & ArgFlags) {
+ IdentifierInfo *II = getAsIdentifierInfo();
+
+ // If the number of arguments is 0 then II is guaranteed to not be null.
+ if (getNumArgs() == 0)
+ return II->getName();
+
+ if (!II)
+ return ":";
+
+ return II->getName().str() + ":";
+ }
+
+ // We have a multiple keyword selector (no embedded flags).
+ return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
+}
+
+
+namespace {
+ struct SelectorTableImpl {
+ llvm::FoldingSet<MultiKeywordSelector> Table;
+ llvm::BumpPtrAllocator Allocator;
+ };
+} // end anonymous namespace.
+
+static SelectorTableImpl &getSelectorTableImpl(void *P) {
+ return *static_cast<SelectorTableImpl*>(P);
+}
+
+
+Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ if (nKeys < 2)
+ return Selector(IIV[0], nKeys);
+
+ SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
+
+ // Unique selector, to guarantee there is one per name.
+ llvm::FoldingSetNodeID ID;
+ MultiKeywordSelector::Profile(ID, IIV, nKeys);
+
+ void *InsertPos = 0;
+ if (MultiKeywordSelector *SI =
+ SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
+ return Selector(SI);
+
+ // MultiKeywordSelector objects are not allocated with new because they have a
+ // variable size array (for parameter types) at the end of them.
+ unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
+ MultiKeywordSelector *SI =
+ (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
+ llvm::alignOf<MultiKeywordSelector>());
+ new (SI) MultiKeywordSelector(nKeys, IIV);
+ SelTabImpl.Table.InsertNode(SI, InsertPos);
+ return Selector(SI);
+}
+
+SelectorTable::SelectorTable() {
+ Impl = new SelectorTableImpl();
+}
+
+SelectorTable::~SelectorTable() {
+ delete &getSelectorTableImpl(Impl);
+}
+
+const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
+ switch (Operator) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ return 0;
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name: return Spelling;
+#include "clang/Basic/OperatorKinds.def"
+ }
+
+ return 0;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
new file mode 100644
index 0000000..5062d43
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceLocation.cpp
@@ -0,0 +1,134 @@
+//==--- SourceLocation.cpp - Compact identifier for Source Files -*- 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 accessor methods for the FullSourceLoc class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// PrettyStackTraceLoc
+//===----------------------------------------------------------------------===//
+
+void PrettyStackTraceLoc::print(llvm::raw_ostream &OS) const {
+ if (Loc.isValid()) {
+ Loc.print(OS, SM);
+ OS << ": ";
+ }
+ OS << Message << '\n';
+}
+
+//===----------------------------------------------------------------------===//
+// SourceLocation
+//===----------------------------------------------------------------------===//
+
+void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{
+ if (!isValid()) {
+ OS << "<invalid loc>";
+ return;
+ }
+
+ if (isFileID()) {
+ PresumedLoc PLoc = SM.getPresumedLoc(*this);
+
+ if (PLoc.isInvalid()) {
+ OS << "<invalid>";
+ return;
+ }
+ // The instantiation and spelling pos is identical for file locs.
+ OS << PLoc.getFilename() << ':' << PLoc.getLine()
+ << ':' << PLoc.getColumn();
+ return;
+ }
+
+ SM.getInstantiationLoc(*this).print(OS, SM);
+
+ OS << " <Spelling=";
+ SM.getSpellingLoc(*this).print(OS, SM);
+ OS << '>';
+}
+
+void SourceLocation::dump(const SourceManager &SM) const {
+ print(llvm::errs(), SM);
+}
+
+//===----------------------------------------------------------------------===//
+// FullSourceLoc
+//===----------------------------------------------------------------------===//
+
+FileID FullSourceLoc::getFileID() const {
+ assert(isValid());
+ return SrcMgr->getFileID(*this);
+}
+
+
+FullSourceLoc FullSourceLoc::getInstantiationLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getInstantiationLoc(*this), *SrcMgr);
+}
+
+FullSourceLoc FullSourceLoc::getSpellingLoc() const {
+ assert(isValid());
+ return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);
+}
+
+unsigned FullSourceLoc::getInstantiationLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getInstantiationLineNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getInstantiationColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getInstantiationColumnNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getSpellingLineNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getSpellingLineNumber(*this, Invalid);
+}
+
+unsigned FullSourceLoc::getSpellingColumnNumber(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getSpellingColumnNumber(*this, Invalid);
+}
+
+bool FullSourceLoc::isInSystemHeader() const {
+ assert(isValid());
+ return SrcMgr->isInSystemHeader(*this);
+}
+
+bool FullSourceLoc::isBeforeInTranslationUnitThan(SourceLocation Loc) const {
+ assert(isValid());
+ return SrcMgr->isBeforeInTranslationUnit(*this, Loc);
+}
+
+const char *FullSourceLoc::getCharacterData(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getCharacterData(*this, Invalid);
+}
+
+const llvm::MemoryBuffer* FullSourceLoc::getBuffer(bool *Invalid) const {
+ assert(isValid());
+ return SrcMgr->getBuffer(SrcMgr->getFileID(*this), Invalid);
+}
+
+llvm::StringRef FullSourceLoc::getBufferData(bool *Invalid) const {
+ return getBuffer(Invalid)->getBuffer();
+}
+
+std::pair<FileID, unsigned> FullSourceLoc::getDecomposedLoc() const {
+ return SrcMgr->getDecomposedLoc(*this);
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
new file mode 100644
index 0000000..044c88d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -0,0 +1,1394 @@
+//===--- SourceManager.cpp - Track and cache source files -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SourceManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <string>
+#include <cstring>
+#include <sys/stat.h>
+
+using namespace clang;
+using namespace SrcMgr;
+using llvm::MemoryBuffer;
+
+//===----------------------------------------------------------------------===//
+// SourceManager Helper Classes
+//===----------------------------------------------------------------------===//
+
+ContentCache::~ContentCache() {
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
+}
+
+/// getSizeBytesMapped - Returns the number of bytes actually mapped for
+/// this ContentCache. This can be 0 if the MemBuffer was not actually
+/// instantiated.
+unsigned ContentCache::getSizeBytesMapped() const {
+ return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
+}
+
+/// getSize - Returns the size of the content encapsulated by this ContentCache.
+/// This can be the size of the source file or the size of an arbitrary
+/// scratch buffer. If the ContentCache encapsulates a source file, that
+/// file is not lazily brought in from disk to satisfy this query.
+unsigned ContentCache::getSize() const {
+ return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
+ : (unsigned) Entry->getSize();
+}
+
+void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
+ bool DoNotFree) {
+ assert(B != Buffer.getPointer());
+
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
+ Buffer.setPointer(B);
+ Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
+}
+
+const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
+ const SourceManager &SM,
+ SourceLocation Loc,
+ bool *Invalid) const {
+ // Lazily create the Buffer for ContentCaches that wrap files. If we already
+ // computed it, jsut return what we have.
+ if (Buffer.getPointer() || Entry == 0) {
+ if (Invalid)
+ *Invalid = isBufferInvalid();
+
+ return Buffer.getPointer();
+ }
+
+ std::string ErrorStr;
+ Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry, &ErrorStr));
+
+ // If we were unable to open the file, then we are in an inconsistent
+ // situation where the content cache referenced a file which no longer
+ // exists. Most likely, we were using a stat cache with an invalid entry but
+ // the file could also have been removed during processing. Since we can't
+ // really deal with this situation, just create an empty buffer.
+ //
+ // FIXME: This is definitely not ideal, but our immediate clients can't
+ // currently handle returning a null entry here. Ideally we should detect
+ // that we are in an inconsistent situation and error out as quickly as
+ // possible.
+ if (!Buffer.getPointer()) {
+ const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
+ Buffer.setPointer(MemoryBuffer::getNewMemBuffer(Entry->getSize(),
+ "<invalid>"));
+ char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart());
+ for (unsigned i = 0, e = Entry->getSize(); i != e; ++i)
+ Ptr[i] = FillStr[i % FillStr.size()];
+
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
+ Entry->getName(), ErrorStr);
+ else
+ Diag.Report(Loc, diag::err_cannot_open_file)
+ << Entry->getName() << ErrorStr;
+
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+
+ if (Invalid) *Invalid = true;
+ return Buffer.getPointer();
+ }
+
+ // Check that the file's size is the same as in the file entry (which may
+ // have come from a stat cache).
+ if (getRawBuffer()->getBufferSize() != (size_t)Entry->getSize()) {
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_file_modified,
+ Entry->getName());
+ else
+ Diag.Report(Loc, diag::err_file_modified)
+ << Entry->getName();
+
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+ if (Invalid) *Invalid = true;
+ return Buffer.getPointer();
+ }
+
+ // If the buffer is valid, check to see if it has a UTF Byte Order Mark
+ // (BOM). We only support UTF-8 without a BOM right now. See
+ // http://en.wikipedia.org/wiki/Byte_order_mark for more information.
+ llvm::StringRef BufStr = Buffer.getPointer()->getBuffer();
+ const char *BOM = llvm::StringSwitch<const char *>(BufStr)
+ .StartsWith("\xEF\xBB\xBF", "UTF-8")
+ .StartsWith("\xFE\xFF", "UTF-16 (BE)")
+ .StartsWith("\xFF\xFE", "UTF-16 (LE)")
+ .StartsWith("\x00\x00\xFE\xFF", "UTF-32 (BE)")
+ .StartsWith("\xFF\xFE\x00\x00", "UTF-32 (LE)")
+ .StartsWith("\x2B\x2F\x76", "UTF-7")
+ .StartsWith("\xF7\x64\x4C", "UTF-1")
+ .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
+ .StartsWith("\x0E\xFE\xFF", "SDSU")
+ .StartsWith("\xFB\xEE\x28", "BOCU-1")
+ .StartsWith("\x84\x31\x95\x33", "GB-18030")
+ .Default(0);
+
+ if (BOM) {
+ Diag.Report(Loc, diag::err_unsupported_bom)
+ << BOM << Entry->getName();
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
+ }
+
+ if (Invalid)
+ *Invalid = isBufferInvalid();
+
+ return Buffer.getPointer();
+}
+
+unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
+ // Look up the filename in the string table, returning the pre-existing value
+ // if it exists.
+ llvm::StringMapEntry<unsigned> &Entry =
+ FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
+ if (Entry.getValue() != ~0U)
+ return Entry.getValue();
+
+ // Otherwise, assign this the next available ID.
+ Entry.setValue(FilenamesByID.size());
+ FilenamesByID.push_back(&Entry);
+ return FilenamesByID.size()-1;
+}
+
+/// AddLineNote - Add a line note to the line table that indicates that there
+/// is a #line at the specified FID/Offset location which changes the presumed
+/// location to LineNo/FilenameID.
+void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID) {
+ std::vector<LineEntry> &Entries = LineEntries[FID];
+
+ assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
+ "Adding line entries out of order!");
+
+ SrcMgr::CharacteristicKind Kind = SrcMgr::C_User;
+ unsigned IncludeOffset = 0;
+
+ if (!Entries.empty()) {
+ // If this is a '#line 4' after '#line 42 "foo.h"', make sure to remember
+ // that we are still in "foo.h".
+ if (FilenameID == -1)
+ FilenameID = Entries.back().FilenameID;
+
+ // If we are after a line marker that switched us to system header mode, or
+ // that set #include information, preserve it.
+ Kind = Entries.back().FileKind;
+ IncludeOffset = Entries.back().IncludeOffset;
+ }
+
+ Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, Kind,
+ IncludeOffset));
+}
+
+/// AddLineNote This is the same as the previous version of AddLineNote, but is
+/// used for GNU line markers. If EntryExit is 0, then this doesn't change the
+/// presumed #include stack. If it is 1, this is a file entry, if it is 2 then
+/// this is a file exit. FileKind specifies whether this is a system header or
+/// extern C system header.
+void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID,
+ unsigned EntryExit,
+ SrcMgr::CharacteristicKind FileKind) {
+ assert(FilenameID != -1 && "Unspecified filename should use other accessor");
+
+ std::vector<LineEntry> &Entries = LineEntries[FID];
+
+ assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
+ "Adding line entries out of order!");
+
+ unsigned IncludeOffset = 0;
+ if (EntryExit == 0) { // No #include stack change.
+ IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset;
+ } else if (EntryExit == 1) {
+ IncludeOffset = Offset-1;
+ } else if (EntryExit == 2) {
+ assert(!Entries.empty() && Entries.back().IncludeOffset &&
+ "PPDirectives should have caught case when popping empty include stack");
+
+ // Get the include loc of the last entries' include loc as our include loc.
+ IncludeOffset = 0;
+ if (const LineEntry *PrevEntry =
+ FindNearestLineEntry(FID, Entries.back().IncludeOffset))
+ IncludeOffset = PrevEntry->IncludeOffset;
+ }
+
+ Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,
+ IncludeOffset));
+}
+
+
+/// FindNearestLineEntry - Find the line entry nearest to FID that is before
+/// it. If there is no line entry before Offset in FID, return null.
+const LineEntry *LineTableInfo::FindNearestLineEntry(unsigned FID,
+ unsigned Offset) {
+ const std::vector<LineEntry> &Entries = LineEntries[FID];
+ assert(!Entries.empty() && "No #line entries for this FID after all!");
+
+ // It is very common for the query to be after the last #line, check this
+ // first.
+ if (Entries.back().FileOffset <= Offset)
+ return &Entries.back();
+
+ // Do a binary search to find the maximal element that is still before Offset.
+ std::vector<LineEntry>::const_iterator I =
+ std::upper_bound(Entries.begin(), Entries.end(), Offset);
+ if (I == Entries.begin()) return 0;
+ return &*--I;
+}
+
+/// \brief Add a new line entry that has already been encoded into
+/// the internal representation of the line table.
+void LineTableInfo::AddEntry(unsigned FID,
+ const std::vector<LineEntry> &Entries) {
+ LineEntries[FID] = Entries;
+}
+
+/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+///
+unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
+ if (LineTable == 0)
+ LineTable = new LineTableInfo();
+ return LineTable->getLineTableFilenameID(Ptr, Len);
+}
+
+
+/// AddLineNote - Add a line note to the line table for the FileID and offset
+/// specified by Loc. If FilenameID is -1, it is considered to be
+/// unspecified.
+void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
+ int FilenameID) {
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+
+ const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
+
+ // Remember that this file has #line directives now if it doesn't already.
+ const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
+
+ if (LineTable == 0)
+ LineTable = new LineTableInfo();
+ LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID);
+}
+
+/// AddLineNote - Add a GNU line marker to the line table.
+void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
+ int FilenameID, bool IsFileEntry,
+ bool IsFileExit, bool IsSystemHeader,
+ bool IsExternCHeader) {
+ // If there is no filename and no flags, this is treated just like a #line,
+ // which does not change the flags of the previous line marker.
+ if (FilenameID == -1) {
+ assert(!IsFileEntry && !IsFileExit && !IsSystemHeader && !IsExternCHeader &&
+ "Can't set flags without setting the filename!");
+ return AddLineNote(Loc, LineNo, FilenameID);
+ }
+
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+ const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
+
+ // Remember that this file has #line directives now if it doesn't already.
+ const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
+
+ if (LineTable == 0)
+ LineTable = new LineTableInfo();
+
+ SrcMgr::CharacteristicKind FileKind;
+ if (IsExternCHeader)
+ FileKind = SrcMgr::C_ExternCSystem;
+ else if (IsSystemHeader)
+ FileKind = SrcMgr::C_System;
+ else
+ FileKind = SrcMgr::C_User;
+
+ unsigned EntryExit = 0;
+ if (IsFileEntry)
+ EntryExit = 1;
+ else if (IsFileExit)
+ EntryExit = 2;
+
+ LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID,
+ EntryExit, FileKind);
+}
+
+LineTableInfo &SourceManager::getLineTable() {
+ if (LineTable == 0)
+ LineTable = new LineTableInfo();
+ return *LineTable;
+}
+
+//===----------------------------------------------------------------------===//
+// Private 'Create' methods.
+//===----------------------------------------------------------------------===//
+
+SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr)
+ : Diag(Diag), FileMgr(FileMgr),
+ ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
+ NumBinaryProbes(0) {
+ clearIDTables();
+ Diag.setSourceManager(this);
+}
+
+SourceManager::~SourceManager() {
+ delete LineTable;
+
+ // Delete FileEntry objects corresponding to content caches. Since the actual
+ // content cache objects are bump pointer allocated, we just have to run the
+ // dtors, but we call the deallocate method for completeness.
+ for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
+ MemBufferInfos[i]->~ContentCache();
+ ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
+ }
+ for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
+ I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
+ I->second->~ContentCache();
+ ContentCacheAlloc.Deallocate(I->second);
+ }
+}
+
+void SourceManager::clearIDTables() {
+ MainFileID = FileID();
+ SLocEntryTable.clear();
+ LastLineNoFileIDQuery = FileID();
+ LastLineNoContentCache = 0;
+ LastFileIDLookup = FileID();
+
+ if (LineTable)
+ LineTable->clear();
+
+ // Use up FileID #0 as an invalid instantiation.
+ NextOffset = 0;
+ createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
+}
+
+/// getOrCreateContentCache - Create or return a cached ContentCache for the
+/// specified file.
+const ContentCache *
+SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
+ assert(FileEnt && "Didn't specify a file entry to use?");
+
+ // Do we already have information about this file?
+ ContentCache *&Entry = FileInfos[FileEnt];
+ if (Entry) return Entry;
+
+ // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned
+ // so that FileInfo can use the low 3 bits of the pointer for its own
+ // nefarious purposes.
+ unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
+ EntryAlign = std::max(8U, EntryAlign);
+ Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
+ new (Entry) ContentCache(FileEnt);
+ return Entry;
+}
+
+
+/// createMemBufferContentCache - Create a new ContentCache for the specified
+/// memory buffer. This does no caching.
+const ContentCache*
+SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
+ // Add a new ContentCache to the MemBufferInfos list and return it. Make sure
+ // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of
+ // the pointer for its own nefarious purposes.
+ unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
+ EntryAlign = std::max(8U, EntryAlign);
+ ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
+ new (Entry) ContentCache();
+ MemBufferInfos.push_back(Entry);
+ Entry->setBuffer(Buffer);
+ return Entry;
+}
+
+void SourceManager::PreallocateSLocEntries(ExternalSLocEntrySource *Source,
+ unsigned NumSLocEntries,
+ unsigned NextOffset) {
+ ExternalSLocEntries = Source;
+ this->NextOffset = NextOffset;
+ unsigned CurPrealloc = SLocEntryLoaded.size();
+ // If we've ever preallocated, we must not count the dummy entry.
+ if (CurPrealloc) --CurPrealloc;
+ SLocEntryLoaded.resize(NumSLocEntries + 1);
+ SLocEntryLoaded[0] = true;
+ SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries - CurPrealloc);
+}
+
+void SourceManager::ClearPreallocatedSLocEntries() {
+ unsigned I = 0;
+ for (unsigned N = SLocEntryLoaded.size(); I != N; ++I)
+ if (!SLocEntryLoaded[I])
+ break;
+
+ // We've already loaded all preallocated source location entries.
+ if (I == SLocEntryLoaded.size())
+ return;
+
+ // Remove everything from location I onward.
+ SLocEntryTable.resize(I);
+ SLocEntryLoaded.clear();
+ ExternalSLocEntries = 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Methods to create new FileID's and instantiations.
+//===----------------------------------------------------------------------===//
+
+/// createFileID - Create a new FileID for the specified ContentCache and
+/// include position. This works regardless of whether the ContentCache
+/// corresponds to a file or some other input source.
+FileID SourceManager::createFileID(const ContentCache *File,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ unsigned PreallocatedID,
+ unsigned Offset) {
+ if (PreallocatedID) {
+ // If we're filling in a preallocated ID, just load in the file
+ // entry and return.
+ assert(PreallocatedID < SLocEntryLoaded.size() &&
+ "Preallocate ID out-of-range");
+ assert(!SLocEntryLoaded[PreallocatedID] &&
+ "Source location entry already loaded");
+ assert(Offset && "Preallocate source location cannot have zero offset");
+ SLocEntryTable[PreallocatedID]
+ = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
+ SLocEntryLoaded[PreallocatedID] = true;
+ FileID FID = FileID::get(PreallocatedID);
+ return FID;
+ }
+
+ SLocEntryTable.push_back(SLocEntry::get(NextOffset,
+ FileInfo::get(IncludePos, File,
+ FileCharacter)));
+ unsigned FileSize = File->getSize();
+ assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
+ NextOffset += FileSize+1;
+
+ // Set LastFileIDLookup to the newly created file. The next getFileID call is
+ // almost guaranteed to be from that file.
+ FileID FID = FileID::get(SLocEntryTable.size()-1);
+ return LastFileIDLookup = FID;
+}
+
+/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
+/// that a token from SpellingLoc should actually be referenced from
+/// InstantiationLoc.
+SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
+ SourceLocation ILocStart,
+ SourceLocation ILocEnd,
+ unsigned TokLength,
+ unsigned PreallocatedID,
+ unsigned Offset) {
+ InstantiationInfo II = InstantiationInfo::get(ILocStart,ILocEnd, SpellingLoc);
+ if (PreallocatedID) {
+ // If we're filling in a preallocated ID, just load in the
+ // instantiation entry and return.
+ assert(PreallocatedID < SLocEntryLoaded.size() &&
+ "Preallocate ID out-of-range");
+ assert(!SLocEntryLoaded[PreallocatedID] &&
+ "Source location entry already loaded");
+ assert(Offset && "Preallocate source location cannot have zero offset");
+ SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II);
+ SLocEntryLoaded[PreallocatedID] = true;
+ return SourceLocation::getMacroLoc(Offset);
+ }
+ SLocEntryTable.push_back(SLocEntry::get(NextOffset, II));
+ assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
+ NextOffset += TokLength+1;
+ return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
+}
+
+const llvm::MemoryBuffer *
+SourceManager::getMemoryBufferForFile(const FileEntry *File,
+ bool *Invalid) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+ return IR->getBuffer(Diag, *this, SourceLocation(), Invalid);
+}
+
+void SourceManager::overrideFileContents(const FileEntry *SourceFile,
+ const llvm::MemoryBuffer *Buffer,
+ bool DoNotFree) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
+}
+
+llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
+ bool MyInvalid = false;
+ const SLocEntry &SLoc = getSLocEntry(FID.ID);
+ if (!SLoc.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+ return "<<<<<INVALID SOURCE LOCATION>>>>>";
+ }
+
+ const llvm::MemoryBuffer *Buf
+ = SLoc.getFile().getContentCache()->getBuffer(Diag, *this, SourceLocation(),
+ &MyInvalid);
+ if (Invalid)
+ *Invalid = MyInvalid;
+
+ if (MyInvalid)
+ return "<<<<<INVALID SOURCE LOCATION>>>>>";
+
+ return Buf->getBuffer();
+}
+
+//===----------------------------------------------------------------------===//
+// SourceLocation manipulation methods.
+//===----------------------------------------------------------------------===//
+
+/// getFileIDSlow - Return the FileID for a SourceLocation. This is a very hot
+/// method that is used for all SourceManager queries that start with a
+/// SourceLocation object. It is responsible for finding the entry in
+/// SLocEntryTable which contains the specified location.
+///
+FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
+ assert(SLocOffset && "Invalid FileID");
+
+ // After the first and second level caches, I see two common sorts of
+ // behavior: 1) a lot of searched FileID's are "near" the cached file location
+ // or are "near" the cached instantiation location. 2) others are just
+ // completely random and may be a very long way away.
+ //
+ // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
+ // then we fall back to a less cache efficient, but more scalable, binary
+ // search to find the location.
+
+ // See if this is near the file point - worst case we start scanning from the
+ // most newly created FileID.
+ std::vector<SrcMgr::SLocEntry>::const_iterator I;
+
+ if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
+ // Neither loc prunes our search.
+ I = SLocEntryTable.end();
+ } else {
+ // Perhaps it is near the file point.
+ I = SLocEntryTable.begin()+LastFileIDLookup.ID;
+ }
+
+ // Find the FileID that contains this. "I" is an iterator that points to a
+ // FileID whose offset is known to be larger than SLocOffset.
+ unsigned NumProbes = 0;
+ while (1) {
+ --I;
+ if (ExternalSLocEntries)
+ getSLocEntry(FileID::get(I - SLocEntryTable.begin()));
+ if (I->getOffset() <= SLocOffset) {
+#if 0
+ printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
+ I-SLocEntryTable.begin(),
+ I->isInstantiation() ? "inst" : "file",
+ LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
+#endif
+ FileID Res = FileID::get(I-SLocEntryTable.begin());
+
+ // If this isn't an instantiation, remember it. We have good locality
+ // across FileID lookups.
+ if (!I->isInstantiation())
+ LastFileIDLookup = Res;
+ NumLinearScans += NumProbes+1;
+ return Res;
+ }
+ if (++NumProbes == 8)
+ break;
+ }
+
+ // Convert "I" back into an index. We know that it is an entry whose index is
+ // larger than the offset we are looking for.
+ unsigned GreaterIndex = I-SLocEntryTable.begin();
+ // LessIndex - This is the lower bound of the range that we're searching.
+ // We know that the offset corresponding to the FileID is is less than
+ // SLocOffset.
+ unsigned LessIndex = 0;
+ NumProbes = 0;
+ while (1) {
+ unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
+ unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex)).getOffset();
+
+ ++NumProbes;
+
+ // If the offset of the midpoint is too large, chop the high side of the
+ // range to the midpoint.
+ if (MidOffset > SLocOffset) {
+ GreaterIndex = MiddleIndex;
+ continue;
+ }
+
+ // If the middle index contains the value, succeed and return.
+ if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
+#if 0
+ printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
+ I-SLocEntryTable.begin(),
+ I->isInstantiation() ? "inst" : "file",
+ LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
+#endif
+ FileID Res = FileID::get(MiddleIndex);
+
+ // If this isn't an instantiation, remember it. We have good locality
+ // across FileID lookups.
+ if (!I->isInstantiation())
+ LastFileIDLookup = Res;
+ NumBinaryProbes += NumProbes;
+ return Res;
+ }
+
+ // Otherwise, move the low-side up to the middle index.
+ LessIndex = MiddleIndex;
+ }
+}
+
+SourceLocation SourceManager::
+getInstantiationLocSlowCase(SourceLocation Loc) const {
+ do {
+ // Note: If Loc indicates an offset into a token that came from a macro
+ // expansion (e.g. the 5th character of the token) we do not want to add
+ // this offset when going to the instantiation location. The instatiation
+ // location is the macro invocation, which the offset has nothing to do
+ // with. This is unlike when we get the spelling loc, because the offset
+ // directly correspond to the token whose spelling we're inspecting.
+ Loc = getSLocEntry(getFileID(Loc)).getInstantiation()
+ .getInstantiationLocStart();
+ } while (!Loc.isFileID());
+
+ return Loc;
+}
+
+SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
+ do {
+ std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
+ Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
+ Loc = Loc.getFileLocWithOffset(LocInfo.second);
+ } while (!Loc.isFileID());
+ return Loc;
+}
+
+
+std::pair<FileID, unsigned>
+SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const {
+ // If this is an instantiation record, walk through all the instantiation
+ // points.
+ FileID FID;
+ SourceLocation Loc;
+ do {
+ Loc = E->getInstantiation().getInstantiationLocStart();
+
+ FID = getFileID(Loc);
+ E = &getSLocEntry(FID);
+ Offset += Loc.getOffset()-E->getOffset();
+ } while (!Loc.isFileID());
+
+ return std::make_pair(FID, Offset);
+}
+
+std::pair<FileID, unsigned>
+SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const {
+ // If this is an instantiation record, walk through all the instantiation
+ // points.
+ FileID FID;
+ SourceLocation Loc;
+ do {
+ Loc = E->getInstantiation().getSpellingLoc();
+
+ FID = getFileID(Loc);
+ E = &getSLocEntry(FID);
+ Offset += Loc.getOffset()-E->getOffset();
+ } while (!Loc.isFileID());
+
+ return std::make_pair(FID, Offset);
+}
+
+/// getImmediateSpellingLoc - Given a SourceLocation object, return the
+/// spelling location referenced by the ID. This is the first level down
+/// towards the place where the characters that make up the lexed token can be
+/// found. This should not generally be used by clients.
+SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
+ if (Loc.isFileID()) return Loc;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
+ Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
+ return Loc.getFileLocWithOffset(LocInfo.second);
+}
+
+
+/// getImmediateInstantiationRange - Loc is required to be an instantiation
+/// location. Return the start/end of the instantiation information.
+std::pair<SourceLocation,SourceLocation>
+SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const {
+ assert(Loc.isMacroID() && "Not an instantiation loc!");
+ const InstantiationInfo &II = getSLocEntry(getFileID(Loc)).getInstantiation();
+ return II.getInstantiationLocRange();
+}
+
+/// getInstantiationRange - Given a SourceLocation object, return the
+/// range of tokens covered by the instantiation in the ultimate file.
+std::pair<SourceLocation,SourceLocation>
+SourceManager::getInstantiationRange(SourceLocation Loc) const {
+ if (Loc.isFileID()) return std::make_pair(Loc, Loc);
+
+ std::pair<SourceLocation,SourceLocation> Res =
+ getImmediateInstantiationRange(Loc);
+
+ // Fully resolve the start and end locations to their ultimate instantiation
+ // points.
+ while (!Res.first.isFileID())
+ Res.first = getImmediateInstantiationRange(Res.first).first;
+ while (!Res.second.isFileID())
+ Res.second = getImmediateInstantiationRange(Res.second).second;
+ return Res;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Queries about the code at a SourceLocation.
+//===----------------------------------------------------------------------===//
+
+/// getCharacterData - Return a pointer to the start of the specified location
+/// in the appropriate MemoryBuffer.
+const char *SourceManager::getCharacterData(SourceLocation SL,
+ bool *Invalid) const {
+ // Note that this is a hot function in the getSpelling() path, which is
+ // heavily used by -E mode.
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
+
+ // Note that calling 'getBuffer()' may lazily page in a source file.
+ bool CharDataInvalid = false;
+ const llvm::MemoryBuffer *Buffer
+ = getSLocEntry(LocInfo.first).getFile().getContentCache()
+ ->getBuffer(Diag, *this, SourceLocation(), &CharDataInvalid);
+ if (Invalid)
+ *Invalid = CharDataInvalid;
+ return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
+}
+
+
+/// getColumnNumber - Return the column # for the specified file position.
+/// this is significantly cheaper to compute than the line number.
+unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ bool MyInvalid = false;
+ const char *Buf = getBuffer(FID, &MyInvalid)->getBufferStart();
+ if (Invalid)
+ *Invalid = MyInvalid;
+
+ if (MyInvalid)
+ return 1;
+
+ unsigned LineStart = FilePos;
+ while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
+ --LineStart;
+ return FilePos-LineStart+1;
+}
+
+// isInvalid - Return the result of calling loc.isInvalid(), and
+// if Invalid is not null, set its value to same.
+static bool isInvalid(SourceLocation Loc, bool *Invalid) {
+ bool MyInvalid = Loc.isInvalid();
+ if (Invalid)
+ *Invalid = MyInvalid;
+ return MyInvalid;
+}
+
+unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
+}
+
+unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+ return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
+}
+
+static LLVM_ATTRIBUTE_NOINLINE void
+ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI,
+ llvm::BumpPtrAllocator &Alloc,
+ const SourceManager &SM, bool &Invalid);
+static void ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI,
+ llvm::BumpPtrAllocator &Alloc,
+ const SourceManager &SM, bool &Invalid) {
+ // Note that calling 'getBuffer()' may lazily page in the file.
+ const MemoryBuffer *Buffer = FI->getBuffer(Diag, SM, SourceLocation(),
+ &Invalid);
+ if (Invalid)
+ return;
+
+ // Find the file offsets of all of the *physical* source lines. This does
+ // not look at trigraphs, escaped newlines, or anything else tricky.
+ std::vector<unsigned> LineOffsets;
+
+ // Line #1 starts at char 0.
+ LineOffsets.push_back(0);
+
+ const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
+ const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
+ unsigned Offs = 0;
+ while (1) {
+ // Skip over the contents of the line.
+ // TODO: Vectorize this? This is very performance sensitive for programs
+ // with lots of diagnostics and in -E mode.
+ const unsigned char *NextBuf = (const unsigned char *)Buf;
+ while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
+ ++NextBuf;
+ Offs += NextBuf-Buf;
+ Buf = NextBuf;
+
+ if (Buf[0] == '\n' || Buf[0] == '\r') {
+ // If this is \n\r or \r\n, skip both characters.
+ if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
+ ++Offs, ++Buf;
+ ++Offs, ++Buf;
+ LineOffsets.push_back(Offs);
+ } else {
+ // Otherwise, this is a null. If end of file, exit.
+ if (Buf == End) break;
+ // Otherwise, skip the null.
+ ++Offs, ++Buf;
+ }
+ }
+
+ // Copy the offsets into the FileInfo structure.
+ FI->NumLines = LineOffsets.size();
+ FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
+ std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
+}
+
+/// getLineNumber - Given a SourceLocation, return the spelling line number
+/// for the position indicated. This requires building and caching a table of
+/// line offsets for the MemoryBuffer, so this is not cheap: use only when
+/// about to emit a diagnostic.
+unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
+ bool *Invalid) const {
+ ContentCache *Content;
+ if (LastLineNoFileIDQuery == FID)
+ Content = LastLineNoContentCache;
+ else
+ Content = const_cast<ContentCache*>(getSLocEntry(FID)
+ .getFile().getContentCache());
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (Content->SourceLineCache == 0) {
+ bool MyInvalid = false;
+ ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+ if (Invalid)
+ *Invalid = MyInvalid;
+ if (MyInvalid)
+ return 1;
+ } else if (Invalid)
+ *Invalid = false;
+
+ // Okay, we know we have a line number table. Do a binary search to find the
+ // line number that this character position lands on.
+ unsigned *SourceLineCache = Content->SourceLineCache;
+ unsigned *SourceLineCacheStart = SourceLineCache;
+ unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
+
+ unsigned QueriedFilePos = FilePos+1;
+
+ // FIXME: I would like to be convinced that this code is worth being as
+ // complicated as it is, binary search isn't that slow.
+ //
+ // If it is worth being optimized, then in my opinion it could be more
+ // performant, simpler, and more obviously correct by just "galloping" outward
+ // from the queried file position. In fact, this could be incorporated into a
+ // generic algorithm such as lower_bound_with_hint.
+ //
+ // If someone gives me a test case where this matters, and I will do it! - DWD
+
+ // If the previous query was to the same file, we know both the file pos from
+ // that query and the line number returned. This allows us to narrow the
+ // search space from the entire file to something near the match.
+ if (LastLineNoFileIDQuery == FID) {
+ if (QueriedFilePos >= LastLineNoFilePos) {
+ // FIXME: Potential overflow?
+ SourceLineCache = SourceLineCache+LastLineNoResult-1;
+
+ // The query is likely to be nearby the previous one. Here we check to
+ // see if it is within 5, 10 or 20 lines. It can be far away in cases
+ // where big comment blocks and vertical whitespace eat up lines but
+ // contribute no tokens.
+ if (SourceLineCache+5 < SourceLineCacheEnd) {
+ if (SourceLineCache[5] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+5;
+ else if (SourceLineCache+10 < SourceLineCacheEnd) {
+ if (SourceLineCache[10] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+10;
+ else if (SourceLineCache+20 < SourceLineCacheEnd) {
+ if (SourceLineCache[20] > QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCache+20;
+ }
+ }
+ }
+ } else {
+ if (LastLineNoResult < Content->NumLines)
+ SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
+ }
+ }
+
+ // If the spread is large, do a "radix" test as our initial guess, based on
+ // the assumption that lines average to approximately the same length.
+ // NOTE: This is currently disabled, as it does not appear to be profitable in
+ // initial measurements.
+ if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
+ unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
+
+ // Take a stab at guessing where it is.
+ unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
+
+ // Check for -10 and +10 lines.
+ unsigned LowerBound = std::max(int(ApproxPos-10), 0);
+ unsigned UpperBound = std::min(ApproxPos+10, FileLen);
+
+ // If the computed lower bound is less than the query location, move it in.
+ if (SourceLineCache < SourceLineCacheStart+LowerBound &&
+ SourceLineCacheStart[LowerBound] < QueriedFilePos)
+ SourceLineCache = SourceLineCacheStart+LowerBound;
+
+ // If the computed upper bound is greater than the query location, move it.
+ if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
+ SourceLineCacheStart[UpperBound] >= QueriedFilePos)
+ SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
+ }
+
+ unsigned *Pos
+ = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
+ unsigned LineNo = Pos-SourceLineCacheStart;
+
+ LastLineNoFileIDQuery = FID;
+ LastLineNoContentCache = Content;
+ LastLineNoFilePos = QueriedFilePos;
+ LastLineNoResult = LineNo;
+ return LineNo;
+}
+
+unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
+unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
+
+/// getFileCharacteristic - return the file characteristic of the specified
+/// source location, indicating whether this is a normal file, a system
+/// header, or an "implicit extern C" system header.
+///
+/// This state can be modified with flags on GNU linemarker directives like:
+/// # 4 "foo.h" 3
+/// which changes all source locations in the current file after that to be
+/// considered to be from a system header.
+SrcMgr::CharacteristicKind
+SourceManager::getFileCharacteristic(SourceLocation Loc) const {
+ assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!");
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+ const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
+
+ // If there are no #line directives in this file, just return the whole-file
+ // state.
+ if (!FI.hasLineDirectives())
+ return FI.getFileCharacteristic();
+
+ assert(LineTable && "Can't have linetable entries without a LineTable!");
+ // See if there is a #line directive before the location.
+ const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second);
+
+ // If this is before the first line marker, use the file characteristic.
+ if (!Entry)
+ return FI.getFileCharacteristic();
+
+ return Entry->FileKind;
+}
+
+/// Return the filename or buffer identifier of the buffer the location is in.
+/// Note that this name does not respect #line directives. Use getPresumedLoc
+/// for normal clients.
+const char *SourceManager::getBufferName(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return "<invalid loc>";
+
+ return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
+}
+
+
+/// getPresumedLoc - This method returns the "presumed" location of a
+/// SourceLocation specifies. A "presumed location" can be modified by #line
+/// or GNU line marker directives. This provides a view on the data that a
+/// user should see in diagnostics, for example.
+///
+/// Note that a presumed location is always given as the instantiation point
+/// of an instantiation location, not at the spelling location.
+PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
+ if (Loc.isInvalid()) return PresumedLoc();
+
+ // Presumed locations are always for instantiation points.
+ std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
+
+ const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
+ const SrcMgr::ContentCache *C = FI.getContentCache();
+
+ // To get the source name, first consult the FileEntry (if one exists)
+ // before the MemBuffer as this will avoid unnecessarily paging in the
+ // MemBuffer.
+ const char *Filename;
+ if (C->Entry)
+ Filename = C->Entry->getName();
+ else
+ Filename = C->getBuffer(Diag, *this)->getBufferIdentifier();
+ bool Invalid = false;
+ unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+ unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
+ if (Invalid)
+ return PresumedLoc();
+
+ SourceLocation IncludeLoc = FI.getIncludeLoc();
+
+ // If we have #line directives in this file, update and overwrite the physical
+ // location info if appropriate.
+ if (FI.hasLineDirectives()) {
+ assert(LineTable && "Can't have linetable entries without a LineTable!");
+ // See if there is a #line directive before this. If so, get it.
+ if (const LineEntry *Entry =
+ LineTable->FindNearestLineEntry(LocInfo.first.ID, LocInfo.second)) {
+ // If the LineEntry indicates a filename, use it.
+ if (Entry->FilenameID != -1)
+ Filename = LineTable->getFilename(Entry->FilenameID);
+
+ // Use the line number specified by the LineEntry. This line number may
+ // be multiple lines down from the line entry. Add the difference in
+ // physical line numbers from the query point and the line marker to the
+ // total.
+ unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
+ LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
+
+ // Note that column numbers are not molested by line markers.
+
+ // Handle virtual #include manipulation.
+ if (Entry->IncludeOffset) {
+ IncludeLoc = getLocForStartOfFile(LocInfo.first);
+ IncludeLoc = IncludeLoc.getFileLocWithOffset(Entry->IncludeOffset);
+ }
+ }
+ }
+
+ return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc);
+}
+
+//===----------------------------------------------------------------------===//
+// Other miscellaneous methods.
+//===----------------------------------------------------------------------===//
+
+/// \brief Retrieve the inode for the given file entry, if possible.
+///
+/// This routine involves a system call, and therefore should only be used
+/// in non-performance-critical code.
+static llvm::Optional<ino_t> getActualFileInode(const FileEntry *File) {
+ if (!File)
+ return llvm::Optional<ino_t>();
+
+ struct stat StatBuf;
+ if (::stat(File->getName(), &StatBuf))
+ return llvm::Optional<ino_t>();
+
+ return StatBuf.st_ino;
+}
+
+/// \brief Get the source location for the given file:line:col triplet.
+///
+/// If the source file is included multiple times, the source location will
+/// be based upon the first inclusion.
+SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col) {
+ assert(SourceFile && "Null source file!");
+ assert(Line && Col && "Line and column should start from 1!");
+
+ // Find the first file ID that corresponds to the given file.
+ FileID FirstFID;
+
+ // First, check the main file ID, since it is common to look for a
+ // location in the main file.
+ llvm::Optional<ino_t> SourceFileInode;
+ llvm::Optional<llvm::StringRef> SourceFileName;
+ if (!MainFileID.isInvalid()) {
+ const SLocEntry &MainSLoc = getSLocEntry(MainFileID);
+ if (MainSLoc.isFile()) {
+ const ContentCache *MainContentCache
+ = MainSLoc.getFile().getContentCache();
+ if (!MainContentCache) {
+ // Can't do anything
+ } else if (MainContentCache->Entry == SourceFile) {
+ FirstFID = MainFileID;
+ } else {
+ // Fall back: check whether we have the same base name and inode
+ // as the main file.
+ const FileEntry *MainFile = MainContentCache->Entry;
+ SourceFileName = llvm::sys::path::filename(SourceFile->getName());
+ if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) {
+ SourceFileInode = getActualFileInode(SourceFile);
+ if (SourceFileInode) {
+ if (llvm::Optional<ino_t> MainFileInode
+ = getActualFileInode(MainFile)) {
+ if (*SourceFileInode == *MainFileInode) {
+ FirstFID = MainFileID;
+ SourceFile = MainFile;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (FirstFID.isInvalid()) {
+ // The location we're looking for isn't in the main file; look
+ // through all of the source locations.
+ for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getSLocEntry(I);
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->Entry == SourceFile) {
+ FirstFID = FileID::get(I);
+ break;
+ }
+ }
+ }
+
+ // If we haven't found what we want yet, try again, but this time stat()
+ // each of the files in case the files have changed since we originally
+ // parsed the file.
+ if (FirstFID.isInvalid() &&
+ (SourceFileName ||
+ (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) &&
+ (SourceFileInode ||
+ (SourceFileInode = getActualFileInode(SourceFile)))) {
+ for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getSLocEntry(I);
+ if (SLoc.isFile()) {
+ const ContentCache *FileContentCache
+ = SLoc.getFile().getContentCache();
+ const FileEntry *Entry =FileContentCache? FileContentCache->Entry : 0;
+ if (Entry &&
+ *SourceFileName == llvm::sys::path::filename(Entry->getName())) {
+ if (llvm::Optional<ino_t> EntryInode = getActualFileInode(Entry)) {
+ if (*SourceFileInode == *EntryInode) {
+ FirstFID = FileID::get(I);
+ SourceFile = Entry;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (FirstFID.isInvalid())
+ return SourceLocation();
+
+ if (Line == 1 && Col == 1)
+ return getLocForStartOfFile(FirstFID);
+
+ ContentCache *Content
+ = const_cast<ContentCache *>(getOrCreateContentCache(SourceFile));
+ if (!Content)
+ return SourceLocation();
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (Content->SourceLineCache == 0) {
+ bool MyInvalid = false;
+ ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+ if (MyInvalid)
+ return SourceLocation();
+ }
+
+ if (Line > Content->NumLines) {
+ unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize();
+ if (Size > 0)
+ --Size;
+ return getLocForStartOfFile(FirstFID).getFileLocWithOffset(Size);
+ }
+
+ unsigned FilePos = Content->SourceLineCache[Line - 1];
+ const char *Buf = Content->getBuffer(Diag, *this)->getBufferStart() + FilePos;
+ unsigned BufLength = Content->getBuffer(Diag, *this)->getBufferEnd() - Buf;
+ unsigned i = 0;
+
+ // Check that the given column is valid.
+ while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
+ ++i;
+ if (i < Col-1)
+ return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + i);
+
+ return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + Col - 1);
+}
+
+/// Given a decomposed source location, move it up the include/instantiation
+/// stack to the parent source location. If this is possible, return the
+/// decomposed version of the parent in Loc and return false. If Loc is the
+/// top-level entry, return true and don't modify it.
+static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
+ const SourceManager &SM) {
+ SourceLocation UpperLoc;
+ const SrcMgr::SLocEntry &Entry = SM.getSLocEntry(Loc.first);
+ if (Entry.isInstantiation())
+ UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+
+ if (UpperLoc.isInvalid())
+ return true; // We reached the top.
+
+ Loc = SM.getDecomposedLoc(UpperLoc);
+ return false;
+}
+
+
+/// \brief Determines the order of 2 source locations in the translation unit.
+///
+/// \returns true if LHS source location comes before RHS, false otherwise.
+bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
+ SourceLocation RHS) const {
+ assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
+ if (LHS == RHS)
+ return false;
+
+ // If both locations are macro instantiations, the order of their offsets
+ // reflect the order that the tokens, pointed to by these locations, were
+ // instantiated (during parsing each token that is instantiated by a macro,
+ // expands the SLocEntries).
+ if (LHS.isMacroID() && RHS.isMacroID())
+ return LHS.getOffset() < RHS.getOffset();
+
+ std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
+ std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
+
+ // If the source locations are in the same file, just compare offsets.
+ if (LOffs.first == ROffs.first)
+ return LOffs.second < ROffs.second;
+
+ // If we are comparing a source location with multiple locations in the same
+ // file, we get a big win by caching the result.
+ if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
+ return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
+
+ // Okay, we missed in the cache, start updating the cache for this query.
+ IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first);
+
+ // "Traverse" the include/instantiation stacks of both locations and try to
+ // find a common "ancestor". FileIDs build a tree-like structure that
+ // reflects the #include hierarchy, and this algorithm needs to find the
+ // nearest common ancestor between the two locations. For example, if you
+ // have a.c that includes b.h and c.h, and are comparing a location in b.h to
+ // a location in c.h, we need to find that their nearest common ancestor is
+ // a.c, and compare the locations of the two #includes to find their relative
+ // ordering.
+ //
+ // SourceManager assigns FileIDs in order of parsing. This means that an
+ // includee always has a larger FileID than an includer. While you might
+ // think that we could just compare the FileID's here, that doesn't work to
+ // compare a point at the end of a.c with a point within c.h. Though c.h has
+ // a larger FileID, we have to compare the include point of c.h to the
+ // location in a.c.
+ //
+ // Despite not being able to directly compare FileID's, we can tell that a
+ // larger FileID is necessarily more deeply nested than a lower one and use
+ // this information to walk up the tree to the nearest common ancestor.
+ do {
+ // If LOffs is larger than ROffs, then LOffs must be more deeply nested than
+ // ROffs, walk up the #include chain.
+ if (LOffs.first.ID > ROffs.first.ID) {
+ if (MoveUpIncludeHierarchy(LOffs, *this))
+ break; // We reached the top.
+
+ } else {
+ // Otherwise, ROffs is larger than LOffs, so ROffs must be more deeply
+ // nested than LOffs, walk up the #include chain.
+ if (MoveUpIncludeHierarchy(ROffs, *this))
+ break; // We reached the top.
+ }
+ } while (LOffs.first != ROffs.first);
+
+ // If we exited because we found a nearest common ancestor, compare the
+ // locations within the common file and cache them.
+ if (LOffs.first == ROffs.first) {
+ IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
+ return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
+ }
+
+ // There is no common ancestor, most probably because one location is in the
+ // predefines buffer or an AST file.
+ // FIXME: We should rearrange the external interface so this simply never
+ // happens; it can't conceptually happen. Also see PR5662.
+ IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
+
+ // Zip both entries up to the top level record.
+ while (!MoveUpIncludeHierarchy(LOffs, *this)) /*empty*/;
+ while (!MoveUpIncludeHierarchy(ROffs, *this)) /*empty*/;
+
+ // If exactly one location is a memory buffer, assume it preceeds the other.
+
+ // Strip off macro instantation locations, going up to the top-level File
+ // SLocEntry.
+ bool LIsMB = getFileEntryForID(LOffs.first) == 0;
+ bool RIsMB = getFileEntryForID(ROffs.first) == 0;
+ if (LIsMB != RIsMB)
+ return LIsMB;
+
+ // Otherwise, just assume FileIDs were created in order.
+ return LOffs.first < ROffs.first;
+}
+
+/// PrintStats - Print statistics to stderr.
+///
+void SourceManager::PrintStats() const {
+ llvm::errs() << "\n*** Source Manager Stats:\n";
+ llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
+ << " mem buffers mapped.\n";
+ llvm::errs() << SLocEntryTable.size() << " SLocEntry's allocated, "
+ << NextOffset << "B of Sloc address space used.\n";
+
+ unsigned NumLineNumsComputed = 0;
+ unsigned NumFileBytesMapped = 0;
+ for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
+ NumLineNumsComputed += I->second->SourceLineCache != 0;
+ NumFileBytesMapped += I->second->getSizeBytesMapped();
+ }
+
+ llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
+ << NumLineNumsComputed << " files with line #'s computed.\n";
+ llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
+ << NumBinaryProbes << " binary.\n";
+}
+
+ExternalSLocEntrySource::~ExternalSLocEntrySource() { }
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
new file mode 100644
index 0000000..a9eeb8b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -0,0 +1,433 @@
+//===--- TargetInfo.cpp - Information about Target machine ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TargetInfo and TargetInfoImpl interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/STLExtras.h"
+#include <cctype>
+#include <cstdlib>
+using namespace clang;
+
+// TargetInfo Constructor.
+TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
+ // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
+ // SPARC. These should be overridden by concrete targets as needed.
+ TLSSupported = true;
+ NoAsmVariants = false;
+ PointerWidth = PointerAlign = 32;
+ BoolWidth = BoolAlign = 8;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongAlign = 32;
+ LongLongWidth = LongLongAlign = 64;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 64;
+ DoubleAlign = 64;
+ LongDoubleWidth = 64;
+ LongDoubleAlign = 64;
+ LargeArrayMinWidth = 0;
+ LargeArrayAlign = 0;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ IntPtrType = SignedLong;
+ WCharType = SignedInt;
+ WIntType = SignedInt;
+ Char16Type = UnsignedShort;
+ Char32Type = UnsignedInt;
+ Int64Type = SignedLongLong;
+ SigAtomicType = SignedInt;
+ UseBitFieldTypeAlignment = true;
+ FloatFormat = &llvm::APFloat::IEEEsingle;
+ DoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-n32";
+ UserLabelPrefix = "_";
+ MCountName = "mcount";
+ HasAlignMac68kSupport = false;
+
+ // Default to no types using fpret.
+ RealTypeUsesObjCFPRet = 0;
+
+ // Default to using the Itanium ABI.
+ CXXABI = CXXABI_Itanium;
+}
+
+// Out of line virtual dtor for TargetInfo.
+TargetInfo::~TargetInfo() {}
+
+/// getTypeName - Return the user string for the specified integer type enum.
+/// For example, SignedShort -> "short".
+const char *TargetInfo::getTypeName(IntType T) {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort: return "short";
+ case UnsignedShort: return "unsigned short";
+ case SignedInt: return "int";
+ case UnsignedInt: return "unsigned int";
+ case SignedLong: return "long int";
+ case UnsignedLong: return "long unsigned int";
+ case SignedLongLong: return "long long int";
+ case UnsignedLongLong: return "long long unsigned int";
+ }
+}
+
+/// getTypeConstantSuffix - Return the constant suffix for the specified
+/// integer type enum. For example, SignedLong -> "L".
+const char *TargetInfo::getTypeConstantSuffix(IntType T) {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case SignedInt: return "";
+ case SignedLong: return "L";
+ case SignedLongLong: return "LL";
+ case UnsignedShort:
+ case UnsignedInt: return "U";
+ case UnsignedLong: return "UL";
+ case UnsignedLongLong: return "ULL";
+ }
+}
+
+/// getTypeWidth - Return the width (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntWidth().
+unsigned TargetInfo::getTypeWidth(IntType T) const {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case UnsignedShort: return getShortWidth();
+ case SignedInt:
+ case UnsignedInt: return getIntWidth();
+ case SignedLong:
+ case UnsignedLong: return getLongWidth();
+ case SignedLongLong:
+ case UnsignedLongLong: return getLongLongWidth();
+ };
+}
+
+/// getTypeAlign - Return the alignment (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntAlign().
+unsigned TargetInfo::getTypeAlign(IntType T) const {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case UnsignedShort: return getShortAlign();
+ case SignedInt:
+ case UnsignedInt: return getIntAlign();
+ case SignedLong:
+ case UnsignedLong: return getLongAlign();
+ case SignedLongLong:
+ case UnsignedLongLong: return getLongLongAlign();
+ };
+}
+
+/// isTypeSigned - Return whether an integer types is signed. Returns true if
+/// the type is signed; false otherwise.
+bool TargetInfo::isTypeSigned(IntType T) {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case SignedInt:
+ case SignedLong:
+ case SignedLongLong:
+ return true;
+ case UnsignedShort:
+ case UnsignedInt:
+ case UnsignedLong:
+ case UnsignedLongLong:
+ return false;
+ };
+}
+
+/// setForcedLangOptions - Set forced language options.
+/// Apply changes to the target information with respect to certain
+/// language options which change the target configuration.
+void TargetInfo::setForcedLangOptions(LangOptions &Opts) {
+ if (Opts.NoBitFieldTypeAlign)
+ UseBitFieldTypeAlignment = false;
+ if (Opts.ShortWChar)
+ WCharType = UnsignedShort;
+}
+
+//===----------------------------------------------------------------------===//
+
+
+static llvm::StringRef removeGCCRegisterPrefix(llvm::StringRef Name) {
+ if (Name[0] == '%' || Name[0] == '#')
+ Name = Name.substr(1);
+
+ return Name;
+}
+
+/// isValidGCCRegisterName - Returns whether the passed in string
+/// is a valid register name according to GCC. This is used by Sema for
+/// inline asm statements.
+bool TargetInfo::isValidGCCRegisterName(llvm::StringRef Name) const {
+ if (Name.empty())
+ return false;
+
+ const char * const *Names;
+ unsigned NumNames;
+
+ // Get rid of any register prefix.
+ Name = removeGCCRegisterPrefix(Name);
+
+ if (Name == "memory" || Name == "cc")
+ return true;
+
+ getGCCRegNames(Names, NumNames);
+
+ // If we have a number it maps to an entry in the register name array.
+ if (isdigit(Name[0])) {
+ int n;
+ if (!Name.getAsInteger(0, n))
+ return n >= 0 && (unsigned)n < NumNames;
+ }
+
+ // Check register names.
+ for (unsigned i = 0; i < NumNames; i++) {
+ if (Name == Names[i])
+ return true;
+ }
+
+ // Now check aliases.
+ const GCCRegAlias *Aliases;
+ unsigned NumAliases;
+
+ getGCCRegAliases(Aliases, NumAliases);
+ for (unsigned i = 0; i < NumAliases; i++) {
+ for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
+ if (!Aliases[i].Aliases[j])
+ break;
+ if (Aliases[i].Aliases[j] == Name)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+llvm::StringRef
+TargetInfo::getNormalizedGCCRegisterName(llvm::StringRef Name) const {
+ assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
+
+ // Get rid of any register prefix.
+ Name = removeGCCRegisterPrefix(Name);
+
+ const char * const *Names;
+ unsigned NumNames;
+
+ getGCCRegNames(Names, NumNames);
+
+ // First, check if we have a number.
+ if (isdigit(Name[0])) {
+ int n;
+ if (!Name.getAsInteger(0, n)) {
+ assert(n >= 0 && (unsigned)n < NumNames &&
+ "Out of bounds register number!");
+ return Names[n];
+ }
+ }
+
+ // Now check aliases.
+ const GCCRegAlias *Aliases;
+ unsigned NumAliases;
+
+ getGCCRegAliases(Aliases, NumAliases);
+ for (unsigned i = 0; i < NumAliases; i++) {
+ for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
+ if (!Aliases[i].Aliases[j])
+ break;
+ if (Aliases[i].Aliases[j] == Name)
+ return Aliases[i].Register;
+ }
+ }
+
+ return Name;
+}
+
+bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
+ const char *Name = Info.getConstraintStr().c_str();
+ // An output constraint must start with '=' or '+'
+ if (*Name != '=' && *Name != '+')
+ return false;
+
+ if (*Name == '+')
+ Info.setIsReadWrite();
+
+ Name++;
+ while (*Name) {
+ switch (*Name) {
+ default:
+ if (!validateAsmConstraint(Name, Info)) {
+ // FIXME: We temporarily return false
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ return false;
+ }
+ case '&': // early clobber.
+ break;
+ case '%': // commutative.
+ // FIXME: Check that there is a another register after this one.
+ break;
+ case 'r': // general register.
+ Info.setAllowsRegister();
+ break;
+ case 'm': // memory operand.
+ case 'o': // offsetable memory operand.
+ case 'V': // non-offsetable memory operand.
+ case '<': // autodecrement memory operand.
+ case '>': // autoincrement memory operand.
+ Info.setAllowsMemory();
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ case 'X': // any operand.
+ Info.setAllowsRegister();
+ Info.setAllowsMemory();
+ break;
+ case ',': // multiple alternative constraint. Pass it.
+ // Handle additional optional '=' or '+' modifiers.
+ if (Name[1] == '=' || Name[1] == '+')
+ Name++;
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severely.
+ break; // Pass them.
+ }
+
+ Name++;
+ }
+
+ return true;
+}
+
+bool TargetInfo::resolveSymbolicName(const char *&Name,
+ ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs,
+ unsigned &Index) const {
+ assert(*Name == '[' && "Symbolic name did not start with '['");
+ Name++;
+ const char *Start = Name;
+ while (*Name && *Name != ']')
+ Name++;
+
+ if (!*Name) {
+ // Missing ']'
+ return false;
+ }
+
+ std::string SymbolicName(Start, Name - Start);
+
+ for (Index = 0; Index != NumOutputs; ++Index)
+ if (SymbolicName == OutputConstraints[Index].getName())
+ return true;
+
+ return false;
+}
+
+bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs,
+ ConstraintInfo &Info) const {
+ const char *Name = Info.ConstraintStr.c_str();
+
+ while (*Name) {
+ switch (*Name) {
+ default:
+ // Check if we have a matching constraint
+ if (*Name >= '0' && *Name <= '9') {
+ unsigned i = *Name - '0';
+
+ // Check if matching constraint is out of bounds.
+ if (i >= NumOutputs)
+ return false;
+
+ // A number must refer to an output only operand.
+ if (OutputConstraints[i].isReadWrite())
+ return false;
+
+ // If the constraint is already tied, it must be tied to the
+ // same operand referenced to by the number.
+ if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
+ return false;
+
+ // The constraint should have the same info as the respective
+ // output constraint.
+ Info.setTiedOperand(i, OutputConstraints[i]);
+ } else if (!validateAsmConstraint(Name, Info)) {
+ // FIXME: This error return is in place temporarily so we can
+ // add more constraints as we hit it. Eventually, an unknown
+ // constraint should just be treated as 'g'.
+ return false;
+ }
+ break;
+ case '[': {
+ unsigned Index = 0;
+ if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
+ return false;
+
+ // If the constraint is already tied, it must be tied to the
+ // same operand referenced to by the number.
+ if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
+ return false;
+
+ Info.setTiedOperand(Index, OutputConstraints[Index]);
+ break;
+ }
+ case '%': // commutative
+ // FIXME: Fail if % is used with the last operand.
+ break;
+ case 'i': // immediate integer.
+ case 'n': // immediate integer with a known value.
+ break;
+ case 'I': // Various constant constraints with target-specific meanings.
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ break;
+ case 'r': // general register.
+ Info.setAllowsRegister();
+ break;
+ case 'm': // memory operand.
+ case 'o': // offsettable memory operand.
+ case 'V': // non-offsettable memory operand.
+ case '<': // autodecrement memory operand.
+ case '>': // autoincrement memory operand.
+ Info.setAllowsMemory();
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ case 'X': // any operand.
+ Info.setAllowsRegister();
+ Info.setAllowsMemory();
+ break;
+ case 'E': // immediate floating point.
+ case 'F': // immediate floating point.
+ case 'p': // address operand.
+ break;
+ case ',': // multiple alternative constraint. Ignore comma.
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severly.
+ break; // Pass them.
+ }
+
+ Name++;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
new file mode 100644
index 0000000..a8198e4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -0,0 +1,2755 @@
+//===--- Targets.cpp - Implement -arch option and targets -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements construction of a TargetInfo object from a
+// target triple.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Type.h"
+#include <algorithm>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Common code shared among targets.
+//===----------------------------------------------------------------------===//
+
+/// DefineStd - Define a macro name and standard variants. For example if
+/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
+/// when in GNU mode.
+static void DefineStd(MacroBuilder &Builder, llvm::StringRef MacroName,
+ const LangOptions &Opts) {
+ assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
+
+ // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
+ // in the user's namespace.
+ if (Opts.GNUMode)
+ Builder.defineMacro(MacroName);
+
+ // Define __unix.
+ Builder.defineMacro("__" + MacroName);
+
+ // Define __unix__.
+ Builder.defineMacro("__" + MacroName + "__");
+}
+
+//===----------------------------------------------------------------------===//
+// Defines specific to certain operating systems.
+//===----------------------------------------------------------------------===//
+
+namespace {
+template<typename TgtInfo>
+class OSTargetInfo : public TgtInfo {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const=0;
+public:
+ OSTargetInfo(const std::string& triple) : TgtInfo(triple) {}
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ TgtInfo::getTargetDefines(Opts, Builder);
+ getOSDefines(Opts, TgtInfo::getTriple(), Builder);
+ }
+
+};
+} // end anonymous namespace
+
+
+static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
+ const llvm::Triple &Triple) {
+ Builder.defineMacro("__APPLE_CC__", "5621");
+ Builder.defineMacro("__APPLE__");
+ Builder.defineMacro("__MACH__");
+ Builder.defineMacro("OBJC_NEW_PROPERTIES");
+
+ // __weak is always defined, for use in blocks and with objc pointers.
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+
+ // Darwin defines __strong even in C mode (just to nothing).
+ if (!Opts.ObjC1 || Opts.getGCMode() == LangOptions::NonGC)
+ Builder.defineMacro("__strong", "");
+ else
+ Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
+
+ if (Opts.Static)
+ Builder.defineMacro("__STATIC__");
+ else
+ Builder.defineMacro("__DYNAMIC__");
+
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+
+ // Get the OS version number from the triple.
+ unsigned Maj, Min, Rev;
+
+ // If no version was given, default to to 10.4.0, for simplifying tests.
+ if (Triple.getOSName() == "darwin") {
+ Min = Rev = 0;
+ Maj = 8;
+ } else
+ Triple.getDarwinNumber(Maj, Min, Rev);
+
+ // Set the appropriate OS version define.
+ if (Triple.getEnvironmentName() == "iphoneos") {
+ assert(Maj < 10 && Min < 99 && Rev < 99 && "Invalid version!");
+ char Str[6];
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str);
+ } else {
+ // For historical reasons that make little sense, the version passed here is
+ // the "darwin" version, which drops the 10 and offsets by 4.
+ Rev = Min;
+ Min = Maj - 4;
+ Maj = 10;
+
+ assert(Triple.getEnvironmentName().empty() && "Invalid environment!");
+ assert(Maj < 99 && Min < 10 && Rev < 10 && "Invalid version!");
+ char Str[5];
+ Str[0] = '0' + (Maj / 10);
+ Str[1] = '0' + (Maj % 10);
+ Str[2] = '0' + Min;
+ Str[3] = '0' + Rev;
+ Str[4] = '\0';
+ Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
+ }
+}
+
+namespace {
+template<typename Target>
+class DarwinTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts, Triple);
+ }
+
+public:
+ DarwinTargetInfo(const std::string& triple) :
+ OSTargetInfo<Target>(triple) {
+ this->TLSSupported = llvm::Triple(triple).getDarwinMajorNumber() > 10;
+ }
+
+ virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
+ // Let MCSectionMachO validate this.
+ llvm::StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
+ TAA, StubSize);
+ }
+
+ virtual const char *getStaticInitSectionSpecifier() const {
+ // FIXME: We should return 0 when building kexts.
+ return "__TEXT,__StaticInit,regular,pure_instructions";
+ }
+
+};
+
+
+// DragonFlyBSD Target
+template<typename Target>
+class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // DragonFly defines; list based off of gcc output
+ Builder.defineMacro("__DragonFly__");
+ Builder.defineMacro("__DragonFly_cc_version", "100001");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ Builder.defineMacro("__tune_i386__");
+ DefineStd(Builder, "unix", Opts);
+ }
+public:
+ DragonFlyBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {}
+};
+
+// FreeBSD Target
+template<typename Target>
+class FreeBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // FreeBSD defines; list based off of gcc output
+
+ // FIXME: Move version number handling to llvm::Triple.
+ llvm::StringRef Release = Triple.getOSName().substr(strlen("freebsd"), 1);
+
+ Builder.defineMacro("__FreeBSD__", Release);
+ Builder.defineMacro("__FreeBSD_cc_version", Release + "00001");
+ Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ }
+public:
+ FreeBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+
+ llvm::Triple Triple(triple);
+ switch (Triple.getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ this->MCountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ this->MCountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ this->MCountName = "__mcount";
+ break;
+ }
+
+ }
+};
+
+// Minix Target
+template<typename Target>
+class MinixTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // Minix defines
+
+ Builder.defineMacro("__minix", "3");
+ Builder.defineMacro("_EM_WSIZE", "4");
+ Builder.defineMacro("_EM_PSIZE", "4");
+ Builder.defineMacro("_EM_SSIZE", "2");
+ Builder.defineMacro("_EM_LSIZE", "4");
+ Builder.defineMacro("_EM_FSIZE", "4");
+ Builder.defineMacro("_EM_DSIZE", "8");
+ DefineStd(Builder, "unix", Opts);
+ }
+public:
+ MinixTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
+// Linux target
+template<typename Target>
+class LinuxTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // Linux defines; list based off of gcc output
+ DefineStd(Builder, "unix", Opts);
+ DefineStd(Builder, "linux", Opts);
+ Builder.defineMacro("__gnu_linux__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+public:
+ LinuxTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ this->WIntType = TargetInfo::UnsignedInt;
+ }
+};
+
+// NetBSD Target
+template<typename Target>
+class NetBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // NetBSD defines; list based off of gcc output
+ Builder.defineMacro("__NetBSD__");
+ Builder.defineMacro("__unix__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_POSIX_THREADS");
+ }
+public:
+ NetBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
+// OpenBSD Target
+template<typename Target>
+class OpenBSDTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // OpenBSD defines; list based off of gcc output
+
+ Builder.defineMacro("__OpenBSD__");
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_POSIX_THREADS");
+ }
+public:
+ OpenBSDTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {}
+};
+
+// PSP Target
+template<typename Target>
+class PSPTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // PSP defines; list based on the output of the pspdev gcc toolchain.
+ Builder.defineMacro("PSP");
+ Builder.defineMacro("_PSP");
+ Builder.defineMacro("__psp__");
+ Builder.defineMacro("__ELF__");
+ }
+public:
+ PSPTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
+// PS3 PPU Target
+template<typename Target>
+class PS3PPUTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // PS3 PPU defines.
+ Builder.defineMacro("__PPC__");
+ Builder.defineMacro("__PPU__");
+ Builder.defineMacro("__CELLOS_LV2__");
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__LP32__");
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("__powerpc64__");
+ }
+public:
+ PS3PPUTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ this->LongWidth = this->LongAlign = this->PointerWidth = this->PointerAlign = 32;
+ this->IntMaxType = TargetInfo::SignedLongLong;
+ this->UIntMaxType = TargetInfo::UnsignedLongLong;
+ this->Int64Type = TargetInfo::SignedLongLong;
+ this->SizeType = TargetInfo::UnsignedInt;
+ this->DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32";
+ }
+};
+
+// FIXME: Need a real SPU target.
+// PS3 SPU Target
+template<typename Target>
+class PS3SPUTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ // PS3 PPU defines.
+ Builder.defineMacro("__SPU__");
+ Builder.defineMacro("__ELF__");
+ }
+public:
+ PS3SPUTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ }
+};
+
+// AuroraUX target
+template<typename Target>
+class AuroraUXTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
+ }
+public:
+ AuroraUXTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ this->WCharType = this->SignedLong;
+ // FIXME: WIntType should be SignedLong
+ }
+};
+
+// Solaris target
+template<typename Target>
+class SolarisTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sun", Opts);
+ DefineStd(Builder, "unix", Opts);
+ Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__svr4__");
+ Builder.defineMacro("__SVR4");
+ }
+public:
+ SolarisTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ this->WCharType = this->SignedLong;
+ // FIXME: WIntType should be SignedLong
+ }
+};
+
+// Windows target
+template<typename Target>
+class WindowsTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("_WIN32");
+ }
+ void getVisualStudioDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (Opts.CPlusPlus) {
+ if (Opts.RTTI)
+ Builder.defineMacro("_CPPRTTI");
+
+ if (Opts.Exceptions)
+ Builder.defineMacro("_CPPUNWIND");
+ }
+
+ if (!Opts.CharIsSigned)
+ Builder.defineMacro("_CHAR_UNSIGNED");
+
+ // FIXME: POSIXThreads isn't exactly the option this should be defined for,
+ // but it works for now.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_MT");
+
+ if (Opts.MSCVersion != 0)
+ Builder.defineMacro("_MSC_VER", llvm::Twine(Opts.MSCVersion));
+
+ if (Opts.Microsoft) {
+ Builder.defineMacro("_MSC_EXTENSIONS");
+
+ if (Opts.CPlusPlus0x) {
+ Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
+ Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
+ Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
+ }
+ }
+
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ }
+
+public:
+ WindowsTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {}
+};
+
+} // end anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// Specific target implementations.
+//===----------------------------------------------------------------------===//
+
+namespace {
+// PPC abstract base class
+class PPCTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+ static const char * const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+
+public:
+ PPCTargetInfo(const std::string& triple) : TargetInfo(triple) {}
+
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ Records = BuiltinInfo;
+ NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default: return false;
+ case 'O': // Zero
+ break;
+ case 'b': // Base register
+ case 'f': // Floating point register
+ Info.setAllowsRegister();
+ break;
+ // FIXME: The following are added to allow parsing.
+ // I just took a guess at what the actions should be.
+ // Also, is more specific checking needed? I.e. specific registers?
+ case 'd': // Floating point register (containing 64-bit value)
+ case 'v': // Altivec vector register
+ Info.setAllowsRegister();
+ break;
+ case 'w':
+ switch (Name[1]) {
+ case 'd':// VSX vector register to hold vector double data
+ case 'f':// VSX vector register to hold vector float data
+ case 's':// VSX vector register to hold scalar float data
+ case 'a':// Any VSX register
+ break;
+ default:
+ return false;
+ }
+ Info.setAllowsRegister();
+ Name++; // Skip over 'w'.
+ break;
+ case 'h': // `MQ', `CTR', or `LINK' register
+ case 'q': // `MQ' register
+ case 'c': // `CTR' register
+ case 'l': // `LINK' register
+ case 'x': // `CR' register (condition register) number 0
+ case 'y': // `CR' register (condition register)
+ case 'z': // `XER[CA]' carry bit (part of the XER register)
+ Info.setAllowsRegister();
+ break;
+ case 'I': // Signed 16-bit constant
+ case 'J': // Unsigned 16-bit constant shifted left 16 bits
+ // (use `L' instead for SImode constants)
+ case 'K': // Unsigned 16-bit constant
+ case 'L': // Signed 16-bit constant shifted left 16 bits
+ case 'M': // Constant larger than 31
+ case 'N': // Exact power of 2
+ case 'P': // Constant whose negation is a signed 16-bit constant
+ case 'G': // Floating point constant that can be loaded into a
+ // register with one instruction per word
+ case 'H': // Integer/Floating point constant that can be loaded
+ // into a register using three instructions
+ break;
+ case 'm': // Memory operand. Note that on PowerPC targets, m can
+ // include addresses that update the base register. It
+ // is therefore only safe to use `m' in an asm statement
+ // if that asm statement accesses the operand exactly once.
+ // The asm statement must also use `%U<opno>' as a
+ // placeholder for the "update" flag in the corresponding
+ // load or store instruction. For example:
+ // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
+ // is correct but:
+ // asm ("st %1,%0" : "=m" (mem) : "r" (val));
+ // is not. Use es rather than m if you don't want the base
+ // register to be updated.
+ case 'e':
+ if (Name[1] != 's')
+ return false;
+ // es: A "stable" memory operand; that is, one which does not
+ // include any automodification of the base register. Unlike
+ // `m', this constraint can be used in asm statements that
+ // might access the operand several times, or that might not
+ // access it at all.
+ Info.setAllowsMemory();
+ Name++; // Skip over 'e'.
+ break;
+ case 'Q': // Memory operand that is an offset from a register (it is
+ // usually better to use `m' or `es' in asm statements)
+ case 'Z': // Memory operand that is an indexed or indirect from a
+ // register (it is usually better to use `m' or `es' in
+ // asm statements)
+ Info.setAllowsMemory();
+ Info.setAllowsRegister();
+ break;
+ case 'R': // AIX TOC entry
+ case 'a': // Address operand that is an indexed or indirect from a
+ // register (`p' is preferable for asm statements)
+ case 'S': // Constant suitable as a 64-bit mask operand
+ case 'T': // Constant suitable as a 32-bit mask operand
+ case 'U': // System V Release 4 small data area reference
+ case 't': // AND masks that can be performed by two rldic{l, r}
+ // instructions
+ case 'W': // Vector constant that does not require memory
+ case 'j': // Vector constant that is all zeros.
+ break;
+ // End FIXME.
+ }
+ return true;
+ }
+ virtual const char *getClobbers() const {
+ return "";
+ }
+};
+
+const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+ ALL_LANGUAGES, false },
+#include "clang/Basic/BuiltinsPPC.def"
+};
+
+
+/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
+/// #defines that are not tied to a specific subtarget.
+void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__ppc__");
+ Builder.defineMacro("_ARCH_PPC");
+ Builder.defineMacro("__powerpc__");
+ Builder.defineMacro("__POWERPC__");
+ if (PointerWidth == 64) {
+ Builder.defineMacro("_ARCH_PPC64");
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ Builder.defineMacro("__powerpc64__");
+ Builder.defineMacro("__ppc64__");
+ } else {
+ Builder.defineMacro("__ppc__");
+ }
+
+ // Target properties.
+ Builder.defineMacro("_BIG_ENDIAN");
+ Builder.defineMacro("__BIG_ENDIAN__");
+
+ // Subtarget options.
+ Builder.defineMacro("__NATURAL_ALIGNMENT__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // FIXME: Should be controlled by command line option.
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+
+ if (Opts.AltiVec) {
+ Builder.defineMacro("__VEC__", "10206");
+ Builder.defineMacro("__ALTIVEC__");
+ }
+}
+
+
+const char * const PPCTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "mq", "lr", "ctr", "ap",
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+ "xer",
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+ "vrsave", "vscr",
+ "spe_acc", "spefscr",
+ "sfp"
+};
+
+void PPCTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
+ // While some of these aliases do map to different registers
+ // they still share the same register name.
+ { { "0" }, "r0" },
+ { { "1"}, "r1" },
+ { { "2" }, "r2" },
+ { { "3" }, "r3" },
+ { { "4" }, "r4" },
+ { { "5" }, "r5" },
+ { { "6" }, "r6" },
+ { { "7" }, "r7" },
+ { { "8" }, "r8" },
+ { { "9" }, "r9" },
+ { { "10" }, "r10" },
+ { { "11" }, "r11" },
+ { { "12" }, "r12" },
+ { { "13" }, "r13" },
+ { { "14" }, "r14" },
+ { { "15" }, "r15" },
+ { { "16" }, "r16" },
+ { { "17" }, "r17" },
+ { { "18" }, "r18" },
+ { { "19" }, "r19" },
+ { { "20" }, "r20" },
+ { { "21" }, "r21" },
+ { { "22" }, "r22" },
+ { { "23" }, "r23" },
+ { { "24" }, "r24" },
+ { { "25" }, "r25" },
+ { { "26" }, "r26" },
+ { { "27" }, "r27" },
+ { { "28" }, "r28" },
+ { { "29" }, "r29" },
+ { { "30" }, "r30" },
+ { { "31" }, "r31" },
+ { { "fr0" }, "f0" },
+ { { "fr1" }, "f1" },
+ { { "fr2" }, "f2" },
+ { { "fr3" }, "f3" },
+ { { "fr4" }, "f4" },
+ { { "fr5" }, "f5" },
+ { { "fr6" }, "f6" },
+ { { "fr7" }, "f7" },
+ { { "fr8" }, "f8" },
+ { { "fr9" }, "f9" },
+ { { "fr10" }, "f10" },
+ { { "fr11" }, "f11" },
+ { { "fr12" }, "f12" },
+ { { "fr13" }, "f13" },
+ { { "fr14" }, "f14" },
+ { { "fr15" }, "f15" },
+ { { "fr16" }, "f16" },
+ { { "fr17" }, "f17" },
+ { { "fr18" }, "f18" },
+ { { "fr19" }, "f19" },
+ { { "fr20" }, "f20" },
+ { { "fr21" }, "f21" },
+ { { "fr22" }, "f22" },
+ { { "fr23" }, "f23" },
+ { { "fr24" }, "f24" },
+ { { "fr25" }, "f25" },
+ { { "fr26" }, "f26" },
+ { { "fr27" }, "f27" },
+ { { "fr28" }, "f28" },
+ { { "fr29" }, "f29" },
+ { { "fr30" }, "f30" },
+ { { "fr31" }, "f31" },
+ { { "cc" }, "cr0" },
+};
+
+void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+} // end anonymous namespace.
+
+namespace {
+class PPC32TargetInfo : public PPCTargetInfo {
+public:
+ PPC32TargetInfo(const std::string &triple) : PPCTargetInfo(triple) {
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32";
+
+ if (getTriple().getOS() == llvm::Triple::FreeBSD)
+ SizeType = UnsignedInt;
+ }
+
+ virtual const char *getVAListDeclaration() const {
+ // This is the ELF definition, and is overridden by the Darwin sub-target
+ return "typedef struct __va_list_tag {"
+ " unsigned char gpr;"
+ " unsigned char fpr;"
+ " unsigned short reserved;"
+ " void* overflow_arg_area;"
+ " void* reg_save_area;"
+ "} __builtin_va_list[1];";
+ }
+};
+} // end anonymous namespace.
+
+namespace {
+class PPC64TargetInfo : public PPCTargetInfo {
+public:
+ PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ Int64Type = SignedLong;
+ DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64";
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+};
+} // end anonymous namespace.
+
+
+namespace {
+class DarwinPPC32TargetInfo :
+ public DarwinTargetInfo<PPC32TargetInfo> {
+public:
+ DarwinPPC32TargetInfo(const std::string& triple)
+ : DarwinTargetInfo<PPC32TargetInfo>(triple) {
+ HasAlignMac68kSupport = true;
+ BoolWidth = BoolAlign = 32; //XXX support -mone-byte-bool?
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+};
+
+class DarwinPPC64TargetInfo :
+ public DarwinTargetInfo<PPC64TargetInfo> {
+public:
+ DarwinPPC64TargetInfo(const std::string& triple)
+ : DarwinTargetInfo<PPC64TargetInfo>(triple) {
+ HasAlignMac68kSupport = true;
+ }
+};
+} // end anonymous namespace.
+
+namespace {
+// MBlaze abstract base class
+class MBlazeTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+
+public:
+ MBlazeTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ DescriptionString = "E-p:32:32:32-i8:8:8-i16:16:16";
+ }
+
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+ virtual const char *getTargetPrefix() const {
+ return "mblaze";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default: return false;
+ case 'O': // Zero
+ return true;
+ case 'b': // Base register
+ case 'f': // Floating point register
+ Info.setAllowsRegister();
+ return true;
+ }
+ }
+ virtual const char *getClobbers() const {
+ return "";
+ }
+};
+
+/// MBlazeTargetInfo::getTargetDefines - Return a set of the MBlaze-specific
+/// #defines that are not tied to a specific subtarget.
+void MBlazeTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__microblaze__");
+ Builder.defineMacro("_ARCH_MICROBLAZE");
+ Builder.defineMacro("__MICROBLAZE__");
+
+ // Target properties.
+ Builder.defineMacro("_BIG_ENDIAN");
+ Builder.defineMacro("__BIG_ENDIAN__");
+
+ // Subtarget options.
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+}
+
+
+const char * const MBlazeTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
+ "hi", "lo", "accum","rmsr", "$fcc1","$fcc2","$fcc3","$fcc4",
+ "$fcc5","$fcc6","$fcc7","$ap", "$rap", "$frp"
+};
+
+void MBlazeTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias MBlazeTargetInfo::GCCRegAliases[] = {
+ { {"f0"}, "r0" },
+ { {"f1"}, "r1" },
+ { {"f2"}, "r2" },
+ { {"f3"}, "r3" },
+ { {"f4"}, "r4" },
+ { {"f5"}, "r5" },
+ { {"f6"}, "r6" },
+ { {"f7"}, "r7" },
+ { {"f8"}, "r8" },
+ { {"f9"}, "r9" },
+ { {"f10"}, "r10" },
+ { {"f11"}, "r11" },
+ { {"f12"}, "r12" },
+ { {"f13"}, "r13" },
+ { {"f14"}, "r14" },
+ { {"f15"}, "r15" },
+ { {"f16"}, "r16" },
+ { {"f17"}, "r17" },
+ { {"f18"}, "r18" },
+ { {"f19"}, "r19" },
+ { {"f20"}, "r20" },
+ { {"f21"}, "r21" },
+ { {"f22"}, "r22" },
+ { {"f23"}, "r23" },
+ { {"f24"}, "r24" },
+ { {"f25"}, "r25" },
+ { {"f26"}, "r26" },
+ { {"f27"}, "r27" },
+ { {"f28"}, "r28" },
+ { {"f29"}, "r29" },
+ { {"f30"}, "r30" },
+ { {"f31"}, "r31" },
+};
+
+void MBlazeTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+} // end anonymous namespace.
+
+namespace {
+// Namespace for x86 abstract base class
+const Builtin::Info BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+ ALL_LANGUAGES, false },
+#include "clang/Basic/BuiltinsX86.def"
+};
+
+static const char* const GCCRegNames[] = {
+ "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+ "argp", "flags", "fspr", "dirflag", "frame",
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
+};
+
+const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+ { { "al", "ah", "eax", "rax" }, "ax" },
+ { { "bl", "bh", "ebx", "rbx" }, "bx" },
+ { { "cl", "ch", "ecx", "rcx" }, "cx" },
+ { { "dl", "dh", "edx", "rdx" }, "dx" },
+ { { "esi", "rsi" }, "si" },
+ { { "edi", "rdi" }, "di" },
+ { { "esp", "rsp" }, "sp" },
+ { { "ebp", "rbp" }, "bp" },
+};
+
+// X86 target abstract base class; x86-32 and x86-64 are very close, so
+// most of the implementation can be shared.
+class X86TargetInfo : public TargetInfo {
+ enum X86SSEEnum {
+ NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42
+ } SSELevel;
+ enum AMD3DNowEnum {
+ NoAMD3DNow, AMD3DNow, AMD3DNowAthlon
+ } AMD3DNowLevel;
+
+ bool HasAES;
+ bool HasAVX;
+
+public:
+ X86TargetInfo(const std::string& triple)
+ : TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow),
+ HasAES(false), HasAVX(false) {
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ Records = BuiltinInfo;
+ NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+ }
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const;
+ virtual std::string convertConstraint(const char Constraint) const;
+ virtual const char *getClobbers() const {
+ return "~{dirflag},~{fpsr},~{flags}";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+ virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const;
+ virtual void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const;
+ virtual void HandleTargetFeatures(std::vector<std::string> &Features);
+};
+
+void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const {
+ // FIXME: This should not be here.
+ Features["3dnow"] = false;
+ Features["3dnowa"] = false;
+ Features["mmx"] = false;
+ Features["sse"] = false;
+ Features["sse2"] = false;
+ Features["sse3"] = false;
+ Features["ssse3"] = false;
+ Features["sse41"] = false;
+ Features["sse42"] = false;
+ Features["aes"] = false;
+ Features["avx"] = false;
+
+ // LLVM does not currently recognize this.
+ // Features["sse4a"] = false;
+
+ // FIXME: This *really* should not be here.
+
+ // X86_64 always has SSE2.
+ if (PointerWidth == 64)
+ Features["sse2"] = Features["sse"] = Features["mmx"] = true;
+
+ if (CPU == "generic" || CPU == "i386" || CPU == "i486" || CPU == "i586" ||
+ CPU == "pentium" || CPU == "i686" || CPU == "pentiumpro")
+ ;
+ else if (CPU == "pentium-mmx" || CPU == "pentium2")
+ setFeatureEnabled(Features, "mmx", true);
+ else if (CPU == "pentium3")
+ setFeatureEnabled(Features, "sse", true);
+ else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64")
+ setFeatureEnabled(Features, "sse2", true);
+ else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona")
+ setFeatureEnabled(Features, "sse3", true);
+ else if (CPU == "core2")
+ setFeatureEnabled(Features, "ssse3", true);
+ else if (CPU == "penryn") {
+ setFeatureEnabled(Features, "sse4", true);
+ Features["sse42"] = false;
+ } else if (CPU == "atom")
+ setFeatureEnabled(Features, "sse3", true);
+ else if (CPU == "corei7") {
+ setFeatureEnabled(Features, "sse4", true);
+ setFeatureEnabled(Features, "aes", true);
+ }
+ else if (CPU == "k6" || CPU == "winchip-c6")
+ setFeatureEnabled(Features, "mmx", true);
+ else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
+ CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") {
+ setFeatureEnabled(Features, "mmx", true);
+ setFeatureEnabled(Features, "3dnow", true);
+ } else if (CPU == "athlon-4" || CPU == "athlon-xp" || CPU == "athlon-mp") {
+ setFeatureEnabled(Features, "sse", true);
+ setFeatureEnabled(Features, "3dnowa", true);
+ } else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" ||
+ CPU == "athlon-fx") {
+ setFeatureEnabled(Features, "sse2", true);
+ setFeatureEnabled(Features, "3dnowa", true);
+ } else if (CPU == "k8-sse3") {
+ setFeatureEnabled(Features, "sse3", true);
+ setFeatureEnabled(Features, "3dnowa", true);
+ } else if (CPU == "c3-2")
+ setFeatureEnabled(Features, "sse", true);
+}
+
+bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const {
+ // FIXME: This *really* should not be here. We need some way of translating
+ // options into llvm subtarget features.
+ if (!Features.count(Name) &&
+ (Name != "sse4" && Name != "sse4.2" && Name != "sse4.1"))
+ return false;
+
+ if (Enabled) {
+ if (Name == "mmx")
+ Features["mmx"] = true;
+ else if (Name == "sse")
+ Features["mmx"] = Features["sse"] = true;
+ else if (Name == "sse2")
+ Features["mmx"] = Features["sse"] = Features["sse2"] = true;
+ else if (Name == "sse3")
+ Features["mmx"] = Features["sse"] = Features["sse2"] =
+ Features["sse3"] = true;
+ else if (Name == "ssse3")
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["ssse3"] = true;
+ else if (Name == "sse4" || Name == "sse4.2")
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["ssse3"] = Features["sse41"] = Features["sse42"] = true;
+ else if (Name == "sse4.1")
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["ssse3"] = Features["sse41"] = true;
+ else if (Name == "3dnow")
+ Features["3dnowa"] = true;
+ else if (Name == "3dnowa")
+ Features["3dnow"] = Features["3dnowa"] = true;
+ else if (Name == "aes")
+ Features["aes"] = true;
+ else if (Name == "avx")
+ Features["avx"] = true;
+ } else {
+ if (Name == "mmx")
+ Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "sse")
+ Features["sse"] = Features["sse2"] = Features["sse3"] =
+ Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "sse2")
+ Features["sse2"] = Features["sse3"] = Features["ssse3"] =
+ Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "sse3")
+ Features["sse3"] = Features["ssse3"] = Features["sse41"] =
+ Features["sse42"] = false;
+ else if (Name == "ssse3")
+ Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "sse4")
+ Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "sse4.2")
+ Features["sse42"] = false;
+ else if (Name == "sse4.1")
+ Features["sse41"] = Features["sse42"] = false;
+ else if (Name == "3dnow")
+ Features["3dnow"] = Features["3dnowa"] = false;
+ else if (Name == "3dnowa")
+ Features["3dnowa"] = false;
+ else if (Name == "aes")
+ Features["aes"] = false;
+ else if (Name == "avx")
+ Features["avx"] = false;
+ }
+
+ return true;
+}
+
+/// HandleTargetOptions - Perform initialization based on the user
+/// configured set of features.
+void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
+ // Remember the maximum enabled sselevel.
+ for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
+ // Ignore disabled features.
+ if (Features[i][0] == '-')
+ continue;
+
+ if (Features[i].substr(1) == "aes") {
+ HasAES = true;
+ continue;
+ }
+
+ // FIXME: Not sure yet how to treat AVX in regard to SSE levels.
+ // For now let it be enabled together with other SSE levels.
+ if (Features[i].substr(1) == "avx") {
+ HasAVX = true;
+ continue;
+ }
+
+ assert(Features[i][0] == '+' && "Invalid target feature!");
+ X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1))
+ .Case("sse42", SSE42)
+ .Case("sse41", SSE41)
+ .Case("ssse3", SSSE3)
+ .Case("sse3", SSE3)
+ .Case("sse2", SSE2)
+ .Case("sse", SSE1)
+ .Case("mmx", MMX)
+ .Default(NoMMXSSE);
+ SSELevel = std::max(SSELevel, Level);
+
+ AMD3DNowEnum ThreeDNowLevel =
+ llvm::StringSwitch<AMD3DNowEnum>(Features[i].substr(1))
+ .Case("3dnowa", AMD3DNowAthlon)
+ .Case("3dnow", AMD3DNow)
+ .Default(NoAMD3DNow);
+
+ AMD3DNowLevel = std::max(AMD3DNowLevel, ThreeDNowLevel);
+ }
+}
+
+/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
+/// that are not tied to a specific subtarget.
+void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ if (PointerWidth == 64) {
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ Builder.defineMacro("__amd64__");
+ Builder.defineMacro("__amd64");
+ Builder.defineMacro("__x86_64");
+ Builder.defineMacro("__x86_64__");
+ } else {
+ DefineStd(Builder, "i386", Opts);
+ }
+
+ if (HasAES)
+ Builder.defineMacro("__AES__");
+
+ if (HasAVX)
+ Builder.defineMacro("__AVX__");
+
+ // Target properties.
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+
+ // Subtarget options.
+ Builder.defineMacro("__nocona");
+ Builder.defineMacro("__nocona__");
+ Builder.defineMacro("__tune_nocona__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
+ // functions in glibc header files that use FP Stack inline asm which the
+ // backend can't deal with (PR879).
+ Builder.defineMacro("__NO_MATH_INLINES");
+
+ // Each case falls through to the previous one here.
+ switch (SSELevel) {
+ case SSE42:
+ Builder.defineMacro("__SSE4_2__");
+ case SSE41:
+ Builder.defineMacro("__SSE4_1__");
+ case SSSE3:
+ Builder.defineMacro("__SSSE3__");
+ case SSE3:
+ Builder.defineMacro("__SSE3__");
+ case SSE2:
+ Builder.defineMacro("__SSE2__");
+ Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
+ case SSE1:
+ Builder.defineMacro("__SSE__");
+ Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
+ case MMX:
+ Builder.defineMacro("__MMX__");
+ case NoMMXSSE:
+ break;
+ }
+
+ if (Opts.Microsoft && PointerWidth == 32) {
+ switch (SSELevel) {
+ case SSE42:
+ case SSE41:
+ case SSSE3:
+ case SSE3:
+ case SSE2:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(2));
+ break;
+ case SSE1:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(1));
+ break;
+ default:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(0));
+ }
+ }
+
+ // Each case falls through to the previous one here.
+ switch (AMD3DNowLevel) {
+ case AMD3DNowAthlon:
+ Builder.defineMacro("__3dNOW_A__");
+ case AMD3DNow:
+ Builder.defineMacro("__3dNOW__");
+ case NoAMD3DNow:
+ break;
+ }
+}
+
+
+bool
+X86TargetInfo::validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default: return false;
+ case 'Y': // first letter of a pair:
+ switch (*(Name+1)) {
+ default: return false;
+ case '0': // First SSE register.
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // any MMX register, when inter-unit moves enabled.
+ break; // falls through to setAllowsRegister.
+ }
+ case 'a': // eax.
+ case 'b': // ebx.
+ case 'c': // ecx.
+ case 'd': // edx.
+ case 'S': // esi.
+ case 'D': // edi.
+ case 'A': // edx:eax.
+ case 'f': // any x87 floating point stack register.
+ case 't': // top of floating point stack.
+ case 'u': // second from top of floating point stack.
+ case 'q': // Any register accessible as [r]l: a, b, c, and d.
+ case 'y': // Any MMX register.
+ case 'x': // Any SSE register.
+ case 'Q': // Any register accessible as [r]h: a, b, c, and d.
+ case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
+ case 'l': // "Index" registers: any general register that can be used as an
+ // index in a base+index memory access.
+ Info.setAllowsRegister();
+ return true;
+ case 'C': // SSE floating point constant.
+ case 'G': // x87 floating point constant.
+ case 'e': // 32-bit signed integer constant for use with zero-extending
+ // x86_64 instructions.
+ case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+ // x86_64 instructions.
+ return true;
+ }
+ return false;
+}
+
+
+std::string
+X86TargetInfo::convertConstraint(const char Constraint) const {
+ switch (Constraint) {
+ case 'a': return std::string("{ax}");
+ case 'b': return std::string("{bx}");
+ case 'c': return std::string("{cx}");
+ case 'd': return std::string("{dx}");
+ case 'S': return std::string("{si}");
+ case 'D': return std::string("{di}");
+ case 'p': // address
+ return std::string("im");
+ case 't': // top of floating point stack.
+ return std::string("{st}");
+ case 'u': // second from top of floating point stack.
+ return std::string("{st(1)}"); // second from top of floating point stack.
+ default:
+ return std::string(1, Constraint);
+ }
+}
+} // end anonymous namespace
+
+namespace {
+// X86-32 generic target
+class X86_32TargetInfo : public X86TargetInfo {
+public:
+ X86_32TargetInfo(const std::string& triple) : X86TargetInfo(triple) {
+ DoubleAlign = LongLongAlign = 32;
+ LongDoubleWidth = 96;
+ LongDoubleAlign = 32;
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
+ "a0:0:64-f80:32:32-n8:16:32";
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ RegParmMax = 3;
+
+ // Use fpret for all types.
+ RealTypeUsesObjCFPRet = ((1 << TargetInfo::Float) |
+ (1 << TargetInfo::Double) |
+ (1 << TargetInfo::LongDouble));
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0) return 0;
+ if (RegNo == 1) return 2;
+ return -1;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> {
+public:
+ OpenBSDI386TargetInfo(const std::string& triple) :
+ OpenBSDTargetInfo<X86_32TargetInfo>(triple) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> {
+public:
+ DarwinI386TargetInfo(const std::string& triple) :
+ DarwinTargetInfo<X86_32TargetInfo>(triple) {
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
+ "a0:0:64-f80:128:128-n8:16:32";
+ HasAlignMac68kSupport = true;
+ }
+
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 Windows target
+class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> {
+public:
+ WindowsX86_32TargetInfo(const std::string& triple)
+ : WindowsTargetInfo<X86_32TargetInfo>(triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ DoubleAlign = LongLongAlign = 64;
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-"
+ "v128:128:128-a0:0:64-f80:32:32-n8:16:32";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<X86_32TargetInfo>::getTargetDefines(Opts, Builder);
+ }
+};
+} // end anonymous namespace
+
+namespace {
+
+// x86-32 Windows Visual Studio target
+class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
+public:
+ VisualStudioWindowsX86_32TargetInfo(const std::string& triple)
+ : WindowsX86_32TargetInfo(triple) {
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_32TargetInfo::getVisualStudioDefines(Opts, Builder);
+ // The value of the following reflects processor type.
+ // 300=386, 400=486, 500=Pentium, 600=Blend (default)
+ // We lost the original triple, so we use the default.
+ Builder.defineMacro("_M_IX86", "600");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 MinGW target
+class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
+public:
+ MinGWX86_32TargetInfo(const std::string& triple)
+ : WindowsX86_32TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
+ DefineStd(Builder, "WIN32", Opts);
+ DefineStd(Builder, "WINNT", Opts);
+ Builder.defineMacro("_X86_");
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW32__");
+ Builder.defineMacro("__declspec", "__declspec");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 Cygwin target
+class CygwinX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ CygwinX86_32TargetInfo(const std::string& triple)
+ : X86_32TargetInfo(triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ DoubleAlign = LongLongAlign = 64;
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a0:0:64-f80:32:32-n8:16:32";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-32 Haiku target
+class HaikuX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ HaikuX86_32TargetInfo(const std::string& triple)
+ : X86_32TargetInfo(triple) {
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ this->UserLabelPrefix = "";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__INTEL__");
+ Builder.defineMacro("__HAIKU__");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 generic target
+class X86_64TargetInfo : public X86TargetInfo {
+public:
+ X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) {
+ LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ Int64Type = SignedLong;
+ RegParmMax = 6;
+
+ DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64";
+
+ // Use fpret only for long double.
+ RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef struct __va_list_tag {"
+ " unsigned gp_offset;"
+ " unsigned fp_offset;"
+ " void* overflow_arg_area;"
+ " void* reg_save_area;"
+ "} __va_list_tag;"
+ "typedef __va_list_tag __builtin_va_list[1];";
+ }
+
+ int getEHDataRegisterNumber(unsigned RegNo) const {
+ if (RegNo == 0) return 0;
+ if (RegNo == 1) return 1;
+ return -1;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 Windows target
+class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> {
+public:
+ WindowsX86_64TargetInfo(const std::string& triple)
+ : WindowsTargetInfo<X86_64TargetInfo>(triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ LongWidth = LongAlign = 32;
+ DoubleAlign = LongLongAlign = 64;
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ Int64Type = SignedLongLong;
+ SizeType = UnsignedLongLong;
+ PtrDiffType = SignedLongLong;
+ IntPtrType = SignedLongLong;
+ this->UserLabelPrefix = "";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_WIN64");
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 Windows Visual Studio target
+class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
+public:
+ VisualStudioWindowsX86_64TargetInfo(const std::string& triple)
+ : WindowsX86_64TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder);
+ Builder.defineMacro("_M_X64");
+ Builder.defineMacro("_M_AMD64");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+// x86-64 MinGW target
+class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
+public:
+ MinGWX86_64TargetInfo(const std::string& triple)
+ : WindowsX86_64TargetInfo(triple) {
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ DefineStd(Builder, "WIN64", Opts);
+ Builder.defineMacro("__MSVCRT__");
+ Builder.defineMacro("__MINGW64__");
+ Builder.defineMacro("__declspec", "__declspec");
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
+public:
+ DarwinX86_64TargetInfo(const std::string& triple)
+ : DarwinTargetInfo<X86_64TargetInfo>(triple) {
+ Int64Type = SignedLongLong;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> {
+public:
+ OpenBSDX86_64TargetInfo(const std::string& triple)
+ : OpenBSDTargetInfo<X86_64TargetInfo>(triple) {
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ Int64Type = SignedLongLong;
+ }
+};
+} // end anonymous namespace
+
+namespace {
+class ARMTargetInfo : public TargetInfo {
+ // Possible FPU choices.
+ enum FPUMode {
+ NoFPU,
+ VFP2FPU,
+ VFP3FPU,
+ NeonFPU
+ };
+
+ static bool FPUModeIsVFP(FPUMode Mode) {
+ return Mode >= VFP2FPU && Mode <= NeonFPU;
+ }
+
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char * const GCCRegNames[];
+
+ std::string ABI, CPU;
+
+ unsigned FPU : 3;
+
+ unsigned IsThumb : 1;
+
+ // Initialized via features.
+ unsigned SoftFloat : 1;
+ unsigned SoftFloatABI : 1;
+
+ static const Builtin::Info BuiltinInfo[];
+
+public:
+ ARMTargetInfo(const std::string &TripleStr)
+ : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s")
+ {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+
+ // {} in inline assembly are neon specifiers, not assembly variant
+ // specifiers.
+ NoAsmVariants = true;
+
+ // FIXME: Should we just treat this as a feature?
+ IsThumb = getTriple().getArchName().startswith("thumb");
+ if (IsThumb) {
+ DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "v64:64:64-v128:128:128-a0:0:32-n32");
+ } else {
+ DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-"
+ "v64:64:64-v128:128:128-a0:0:64-n32");
+ }
+
+ // ARM targets default to using the ARM C++ ABI.
+ CXXABI = CXXABI_ARM;
+ }
+ virtual const char *getABI() const { return ABI.c_str(); }
+ virtual bool setABI(const std::string &Name) {
+ ABI = Name;
+
+ // The defaults (above) are for AAPCS, check if we need to change them.
+ //
+ // FIXME: We need support for -meabi... we could just mangle it into the
+ // name.
+ if (Name == "apcs-gnu") {
+ DoubleAlign = LongLongAlign = LongDoubleAlign = 32;
+ SizeType = UnsignedLong;
+
+ // Do not respect the alignment of bit-field types when laying out
+ // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
+ UseBitFieldTypeAlignment = false;
+
+ if (IsThumb) {
+ DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:32-f32:32:32-f64:32:32-"
+ "v64:64:64-v128:128:128-a0:0:32-n32");
+ } else {
+ DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:32:32-f32:32:32-f64:32:32-"
+ "v64:64:64-v128:128:128-a0:0:64-n32");
+ }
+
+ // FIXME: Override "preferred align" for double and long long.
+ } else if (Name == "aapcs") {
+ // FIXME: Enumerated types are variable width in straight AAPCS.
+ } else if (Name == "aapcs-linux") {
+ ;
+ } else
+ return false;
+
+ return true;
+ }
+
+ void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const {
+ // FIXME: This should not be here.
+ Features["vfp2"] = false;
+ Features["vfp3"] = false;
+ Features["neon"] = false;
+
+ if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore")
+ Features["vfp2"] = true;
+ else if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ Features["neon"] = true;
+ }
+
+ virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const {
+ if (Name == "soft-float" || Name == "soft-float-abi") {
+ Features[Name] = Enabled;
+ } else if (Name == "vfp2" || Name == "vfp3" || Name == "neon") {
+ // These effectively are a single option, reset them when any is enabled.
+ if (Enabled)
+ Features["vfp2"] = Features["vfp3"] = Features["neon"] = false;
+ Features[Name] = Enabled;
+ } else
+ return false;
+
+ return true;
+ }
+
+ virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ FPU = NoFPU;
+ SoftFloat = SoftFloatABI = false;
+ for (unsigned i = 0, e = Features.size(); i != e; ++i) {
+ if (Features[i] == "+soft-float")
+ SoftFloat = true;
+ else if (Features[i] == "+soft-float-abi")
+ SoftFloatABI = true;
+ else if (Features[i] == "+vfp2")
+ FPU = VFP2FPU;
+ else if (Features[i] == "+vfp3")
+ FPU = VFP3FPU;
+ else if (Features[i] == "+neon")
+ FPU = NeonFPU;
+ }
+
+ // Remove front-end specific options which the backend handles differently.
+ std::vector<std::string>::iterator it;
+ it = std::find(Features.begin(), Features.end(), "+soft-float");
+ if (it != Features.end())
+ Features.erase(it);
+ it = std::find(Features.begin(), Features.end(), "+soft-float-abi");
+ if (it != Features.end())
+ Features.erase(it);
+ }
+
+ static const char *getCPUDefineSuffix(llvm::StringRef Name) {
+ return llvm::StringSwitch<const char*>(Name)
+ .Cases("arm8", "arm810", "4")
+ .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "4")
+ .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "arm720t", "arm9", "4T")
+ .Cases("arm9tdmi", "arm920", "arm920t", "arm922t", "arm940t", "4T")
+ .Case("ep9312", "4T")
+ .Cases("arm10tdmi", "arm1020t", "5T")
+ .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "5TE")
+ .Case("arm926ej-s", "5TEJ")
+ .Cases("arm10e", "arm1020e", "arm1022e", "5TE")
+ .Cases("xscale", "iwmmxt", "5TE")
+ .Case("arm1136j-s", "6J")
+ .Cases("arm1176jz-s", "arm1176jzf-s", "6ZK")
+ .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K")
+ .Cases("arm1156t2-s", "arm1156t2f-s", "6T2")
+ .Cases("cortex-a8", "cortex-a9", "7A")
+ .Case("cortex-m3", "7M")
+ .Default(0);
+ }
+ virtual bool setCPU(const std::string &Name) {
+ if (!getCPUDefineSuffix(Name))
+ return false;
+
+ CPU = Name;
+ return true;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ // Target identification.
+ Builder.defineMacro("__arm");
+ Builder.defineMacro("__arm__");
+
+ // Target properties.
+ Builder.defineMacro("__ARMEL__");
+ Builder.defineMacro("__LITTLE_ENDIAN__");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ llvm::StringRef CPUArch = getCPUDefineSuffix(CPU);
+ Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
+
+ // Subtarget options.
+
+ // FIXME: It's more complicated than this and we don't really support
+ // interworking.
+ if ('5' <= CPUArch[0] && CPUArch[0] <= '7')
+ Builder.defineMacro("__THUMB_INTERWORK__");
+
+ if (ABI == "aapcs" || ABI == "aapcs-linux")
+ Builder.defineMacro("__ARM_EABI__");
+
+ if (SoftFloat)
+ Builder.defineMacro("__SOFTFP__");
+
+ if (CPU == "xscale")
+ Builder.defineMacro("__XSCALE__");
+
+ bool IsThumb2 = IsThumb && (CPUArch == "6T2" || CPUArch.startswith("7"));
+ if (IsThumb) {
+ Builder.defineMacro("__THUMBEL__");
+ Builder.defineMacro("__thumb__");
+ if (IsThumb2)
+ Builder.defineMacro("__thumb2__");
+ }
+
+ // Note, this is always on in gcc, even though it doesn't make sense.
+ Builder.defineMacro("__APCS_32__");
+
+ if (FPUModeIsVFP((FPUMode) FPU))
+ Builder.defineMacro("__VFP_FP__");
+
+ // This only gets set when Neon instructions are actually available, unlike
+ // the VFP define, hence the soft float and arch check. This is subtly
+ // different from gcc, we follow the intent which was that it should be set
+ // when Neon instructions are actually available.
+ if (FPU == NeonFPU && !SoftFloat && IsThumb2)
+ Builder.defineMacro("__ARM_NEON__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ Records = BuiltinInfo;
+ NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ // FIXME: Check if this is complete
+ switch (*Name) {
+ default:
+ case 'l': // r0-r7
+ case 'h': // r8-r15
+ case 'w': // VFP Floating point register single precision
+ case 'P': // VFP Floating point register double precision
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+ virtual const char *getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+ }
+};
+
+const char * const ARMTargetInfo::GCCRegNames[] = {
+ // Integer registers
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
+
+ // Float registers
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+ // Double registers
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+ // Quad registers
+ "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
+ "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
+};
+
+void ARMTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
+ { { "a1" }, "r0" },
+ { { "a2" }, "r1" },
+ { { "a3" }, "r2" },
+ { { "a4" }, "r3" },
+ { { "v1" }, "r4" },
+ { { "v2" }, "r5" },
+ { { "v3" }, "r6" },
+ { { "v4" }, "r7" },
+ { { "v5" }, "r8" },
+ { { "v6", "rfp" }, "r9" },
+ { { "sl" }, "r10" },
+ { { "fp" }, "r11" },
+ { { "ip" }, "r12" },
+ { { "r13" }, "sp" },
+ { { "r14" }, "lr" },
+ { { "r15" }, "pc" },
+ // The S, D and Q registers overlap, but aren't really aliases; we
+ // don't want to substitute one of these for a different-sized one.
+};
+
+void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+
+const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES, false },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+ ALL_LANGUAGES, false },
+#include "clang/Basic/BuiltinsARM.def"
+};
+} // end anonymous namespace.
+
+
+namespace {
+class DarwinARMTargetInfo :
+ public DarwinTargetInfo<ARMTargetInfo> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ getDarwinDefines(Builder, Opts, Triple);
+ }
+
+public:
+ DarwinARMTargetInfo(const std::string& triple)
+ : DarwinTargetInfo<ARMTargetInfo>(triple) {
+ HasAlignMac68kSupport = true;
+ }
+};
+} // end anonymous namespace.
+
+namespace {
+class SparcV8TargetInfo : public TargetInfo {
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char * const GCCRegNames[];
+ bool SoftFloat;
+public:
+ SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) {
+ // FIXME: Support Sparc quad-precision long double?
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32";
+ }
+ virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const {
+ if (Name == "soft-float")
+ Features[Name] = Enabled;
+ else
+ return false;
+
+ return true;
+ }
+ virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ SoftFloat = false;
+ for (unsigned i = 0, e = Features.size(); i != e; ++i)
+ if (Features[i] == "+soft-float")
+ SoftFloat = true;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "sparc", Opts);
+ Builder.defineMacro("__sparcv8");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+
+ if (SoftFloat)
+ Builder.defineMacro("SOFT_FLOAT", "1");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement!
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef void* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ // FIXME: Implement!
+ return false;
+ }
+ virtual const char *getClobbers() const {
+ // FIXME: Implement!
+ return "";
+ }
+};
+
+const char * const SparcV8TargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+
+void SparcV8TargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = {
+ { { "g0" }, "r0" },
+ { { "g1" }, "r1" },
+ { { "g2" }, "r2" },
+ { { "g3" }, "r3" },
+ { { "g4" }, "r4" },
+ { { "g5" }, "r5" },
+ { { "g6" }, "r6" },
+ { { "g7" }, "r7" },
+ { { "o0" }, "r8" },
+ { { "o1" }, "r9" },
+ { { "o2" }, "r10" },
+ { { "o3" }, "r11" },
+ { { "o4" }, "r12" },
+ { { "o5" }, "r13" },
+ { { "o6", "sp" }, "r14" },
+ { { "o7" }, "r15" },
+ { { "l0" }, "r16" },
+ { { "l1" }, "r17" },
+ { { "l2" }, "r18" },
+ { { "l3" }, "r19" },
+ { { "l4" }, "r20" },
+ { { "l5" }, "r21" },
+ { { "l6" }, "r22" },
+ { { "l7" }, "r23" },
+ { { "i0" }, "r24" },
+ { { "i1" }, "r25" },
+ { { "i2" }, "r26" },
+ { { "i3" }, "r27" },
+ { { "i4" }, "r28" },
+ { { "i5" }, "r29" },
+ { { "i6", "fp" }, "r30" },
+ { { "i7" }, "r31" },
+};
+
+void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+} // end anonymous namespace.
+
+namespace {
+class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> {
+public:
+ AuroraUXSparcV8TargetInfo(const std::string& triple) :
+ AuroraUXTargetInfo<SparcV8TargetInfo>(triple) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ }
+};
+class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
+public:
+ SolarisSparcV8TargetInfo(const std::string& triple) :
+ SolarisTargetInfo<SparcV8TargetInfo>(triple) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ }
+};
+} // end anonymous namespace.
+
+namespace {
+ class MSP430TargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ public:
+ MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ IntWidth = 16; IntAlign = 16;
+ LongWidth = 32; LongLongWidth = 64;
+ LongAlign = LongLongAlign = 16;
+ PointerWidth = 16; PointerAlign = 16;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ IntPtrType = SignedShort;
+ PtrDiffType = SignedInt;
+ SigAtomicType = SignedLong;
+ DescriptionString = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("MSP430");
+ Builder.defineMacro("__MSP430__");
+ // FIXME: defines for different 'flavours' of MCU
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ // No target constraints for now.
+ return false;
+ }
+ virtual const char *getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+ }
+ virtual const char *getVAListDeclaration() const {
+ // FIXME: implement
+ return "typedef char* __builtin_va_list;";
+ }
+ };
+
+ const char * const MSP430TargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+
+ void MSP430TargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+}
+
+
+namespace {
+ class SystemZTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ public:
+ SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16-n32:64";
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ // FIXME: implement
+ return true;
+ }
+ virtual const char *getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+ }
+ virtual const char *getVAListDeclaration() const {
+ // FIXME: implement
+ return "typedef char* __builtin_va_list;";
+ }
+ };
+
+ const char * const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+
+ void SystemZTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+}
+
+namespace {
+ class BlackfinTargetInfo : public TargetInfo {
+ static const char * const GCCRegNames[];
+ public:
+ BlackfinTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ DoubleAlign = 32;
+ LongLongAlign = 32;
+ LongDoubleAlign = 32;
+ DescriptionString = "e-p:32:32-i64:32-f64:32-n32";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "bfin", Opts);
+ DefineStd(Builder, "BFIN", Opts);
+ Builder.defineMacro("__ADSPBLACKFIN__");
+ // FIXME: This one is really dependent on -mcpu
+ Builder.defineMacro("__ADSPLPBLACKFIN__");
+ // FIXME: Add cpu-dependent defines and __SILICON_REVISION__
+ }
+
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ if (strchr("adzDWeABbvfcCtukxywZY", Name[0])) {
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+
+ virtual const char *getClobbers() const {
+ return "";
+ }
+
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+ };
+
+ const char * const BlackfinTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "p0", "p1", "p2", "p3", "p4", "p5", "sp", "fp",
+ "i0", "i1", "i2", "i3", "b0", "b1", "b2", "b3",
+ "l0", "l1", "l2", "l3", "m0", "m1", "m2", "m3",
+ "a0", "a1", "cc",
+ "rets", "reti", "retx", "retn", "rete", "astat", "seqstat", "usp",
+ "argp", "lt0", "lt1", "lc0", "lc1", "lb0", "lb1"
+ };
+
+ void BlackfinTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+}
+
+namespace {
+
+ // LLVM and Clang cannot be used directly to output native binaries for
+ // target, but is used to compile C code to llvm bitcode with correct
+ // type and alignment information.
+ //
+ // TCE uses the llvm bitcode as input and uses it for generating customized
+ // target processor and program binary. TCE co-design environment is
+ // publicly available in http://tce.cs.tut.fi
+
+ class TCETargetInfo : public TargetInfo{
+ public:
+ TCETargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = false;
+ IntWidth = 32;
+ LongWidth = LongLongWidth = 32;
+ PointerWidth = 32;
+ IntAlign = 32;
+ LongAlign = LongLongAlign = 32;
+ PointerAlign = 32;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ UIntMaxType = UnsignedLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 32;
+ DoubleAlign = 32;
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 32;
+ FloatFormat = &llvm::APFloat::IEEEsingle;
+ DoubleFormat = &llvm::APFloat::IEEEsingle;
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle;
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-a0:0:32-n32";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tce", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {}
+ virtual const char *getClobbers() const {
+ return "";
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef void* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {}
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const {
+ return true;
+ }
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {}
+ };
+}
+
+namespace {
+class MipsTargetInfo : public TargetInfo {
+ std::string ABI, CPU;
+ static const TargetInfo::GCCRegAlias GCCRegAliases[];
+ static const char * const GCCRegNames[];
+public:
+ MipsTargetInfo(const std::string& triple) : TargetInfo(triple), ABI("o32") {
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
+ }
+ virtual const char *getABI() const { return ABI.c_str(); }
+ virtual bool setABI(const std::string &Name) {
+
+ if ((Name == "o32") || (Name == "eabi")) {
+ ABI = Name;
+ return true;
+ } else
+ return false;
+ }
+ virtual bool setCPU(const std::string &Name) {
+ CPU = Name;
+ return true;
+ }
+ void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const {
+ Features[ABI] = true;
+ Features[CPU] = true;
+ }
+ virtual void getArchDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ if (ABI == "o32")
+ Builder.defineMacro("__mips_o32");
+ else if (ABI == "eabi")
+ Builder.defineMacro("__mips_eabi");
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "mips", Opts);
+ Builder.defineMacro("_mips");
+ DefineStd(Builder, "MIPSEB", Opts);
+ Builder.defineMacro("_MIPSEB");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+ getArchDefines(Opts, Builder);
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement!
+ }
+ virtual const char *getVAListDeclaration() const {
+ return "typedef void* __builtin_va_list;";
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ case 'r': // CPU registers.
+ case 'd': // Equivalent to "r" unless generating MIPS16 code.
+ case 'y': // Equivalent to "r", backwards compatibility only.
+ case 'f': // floating-point registers.
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
+ }
+
+ virtual const char *getClobbers() const {
+ // FIXME: Implement!
+ return "";
+ }
+};
+
+const char * const MipsTargetInfo::GCCRegNames[] = {
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31",
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
+ "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+ "$fcc5","$fcc6","$fcc7"
+};
+
+void MipsTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias MipsTargetInfo::GCCRegAliases[] = {
+ { { "at" }, "$1" },
+ { { "v0" }, "$2" },
+ { { "v1" }, "$3" },
+ { { "a0" }, "$4" },
+ { { "a1" }, "$5" },
+ { { "a2" }, "$6" },
+ { { "a3" }, "$7" },
+ { { "t0" }, "$8" },
+ { { "t1" }, "$9" },
+ { { "t2" }, "$10" },
+ { { "t3" }, "$11" },
+ { { "t4" }, "$12" },
+ { { "t5" }, "$13" },
+ { { "t6" }, "$14" },
+ { { "t7" }, "$15" },
+ { { "s0" }, "$16" },
+ { { "s1" }, "$17" },
+ { { "s2" }, "$18" },
+ { { "s3" }, "$19" },
+ { { "s4" }, "$20" },
+ { { "s5" }, "$21" },
+ { { "s6" }, "$22" },
+ { { "s7" }, "$23" },
+ { { "t8" }, "$24" },
+ { { "t9" }, "$25" },
+ { { "k0" }, "$26" },
+ { { "k1" }, "$27" },
+ { { "gp" }, "$28" },
+ { { "sp" }, "$29" },
+ { { "fp" }, "$30" },
+ { { "ra" }, "$31" }
+};
+
+void MipsTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ Aliases = GCCRegAliases;
+ NumAliases = llvm::array_lengthof(GCCRegAliases);
+}
+} // end anonymous namespace.
+
+namespace {
+class MipselTargetInfo : public MipsTargetInfo {
+public:
+ MipselTargetInfo(const std::string& triple) : MipsTargetInfo(triple) {
+ DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
+ "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const;
+};
+
+void MipselTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "mips", Opts);
+ Builder.defineMacro("_mips");
+ DefineStd(Builder, "MIPSEL", Opts);
+ Builder.defineMacro("_MIPSEL");
+ Builder.defineMacro("__REGISTER_PREFIX__", "");
+ getArchDefines(Opts, Builder);
+}
+} // end anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// Driver code
+//===----------------------------------------------------------------------===//
+
+static TargetInfo *AllocateTarget(const std::string &T) {
+ llvm::Triple Triple(T);
+ llvm::Triple::OSType os = Triple.getOS();
+
+ switch (Triple.getArch()) {
+ default:
+ return NULL;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<ARMTargetInfo>(T);
+ case llvm::Triple::Darwin:
+ return new DarwinARMTargetInfo(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<ARMTargetInfo>(T);
+ default:
+ return new ARMTargetInfo(T);
+ }
+
+ case llvm::Triple::bfin:
+ return new BlackfinTargetInfo(T);
+
+ case llvm::Triple::msp430:
+ return new MSP430TargetInfo(T);
+
+ case llvm::Triple::mips:
+ if (os == llvm::Triple::Psp)
+ return new PSPTargetInfo<MipsTargetInfo>(T);
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<MipsTargetInfo>(T);
+ return new MipsTargetInfo(T);
+
+ case llvm::Triple::mipsel:
+ if (os == llvm::Triple::Psp)
+ return new PSPTargetInfo<MipselTargetInfo>(T);
+ if (os == llvm::Triple::Linux)
+ return new LinuxTargetInfo<MipselTargetInfo>(T);
+ return new MipselTargetInfo(T);
+
+ case llvm::Triple::ppc:
+ if (os == llvm::Triple::Darwin)
+ return new DarwinPPC32TargetInfo(T);
+ else if (os == llvm::Triple::FreeBSD)
+ return new FreeBSDTargetInfo<PPC32TargetInfo>(T);
+ return new PPC32TargetInfo(T);
+
+ case llvm::Triple::ppc64:
+ if (os == llvm::Triple::Darwin)
+ return new DarwinPPC64TargetInfo(T);
+ else if (os == llvm::Triple::Lv2)
+ return new PS3PPUTargetInfo<PPC64TargetInfo>(T);
+ else if (os == llvm::Triple::FreeBSD)
+ return new FreeBSDTargetInfo<PPC64TargetInfo>(T);
+ return new PPC64TargetInfo(T);
+
+ case llvm::Triple::mblaze:
+ return new MBlazeTargetInfo(T);
+
+ case llvm::Triple::sparc:
+ if (os == llvm::Triple::AuroraUX)
+ return new AuroraUXSparcV8TargetInfo(T);
+ if (os == llvm::Triple::Solaris)
+ return new SolarisSparcV8TargetInfo(T);
+ return new SparcV8TargetInfo(T);
+
+ // FIXME: Need a real SPU target.
+ case llvm::Triple::cellspu:
+ return new PS3SPUTargetInfo<PPC64TargetInfo>(T);
+
+ case llvm::Triple::systemz:
+ return new SystemZTargetInfo(T);
+
+ case llvm::Triple::tce:
+ return new TCETargetInfo(T);
+
+ case llvm::Triple::x86:
+ switch (os) {
+ case llvm::Triple::AuroraUX:
+ return new AuroraUXTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::Darwin:
+ return new DarwinI386TargetInfo(T);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::DragonFly:
+ return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDI386TargetInfo(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::Minix:
+ return new MinixTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<X86_32TargetInfo>(T);
+ case llvm::Triple::Cygwin:
+ return new CygwinX86_32TargetInfo(T);
+ case llvm::Triple::MinGW32:
+ return new MinGWX86_32TargetInfo(T);
+ case llvm::Triple::Win32:
+ return new VisualStudioWindowsX86_32TargetInfo(T);
+ case llvm::Triple::Haiku:
+ return new HaikuX86_32TargetInfo(T);
+ default:
+ return new X86_32TargetInfo(T);
+ }
+
+ case llvm::Triple::x86_64:
+ switch (os) {
+ case llvm::Triple::AuroraUX:
+ return new AuroraUXTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::Darwin:
+ return new DarwinX86_64TargetInfo(T);
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::DragonFly:
+ return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDX86_64TargetInfo(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<X86_64TargetInfo>(T);
+ case llvm::Triple::MinGW32:
+ return new MinGWX86_64TargetInfo(T);
+ case llvm::Triple::Win32: // This is what Triple.h supports now.
+ if (Triple.getEnvironment() == llvm::Triple::MachO)
+ return new DarwinX86_64TargetInfo(T);
+ else
+ return new VisualStudioWindowsX86_64TargetInfo(T);
+ default:
+ return new X86_64TargetInfo(T);
+ }
+ }
+}
+
+/// CreateTargetInfo - Return the target info object for the specified target
+/// triple.
+TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags,
+ TargetOptions &Opts) {
+ llvm::Triple Triple(Opts.Triple);
+
+ // Construct the target
+ llvm::OwningPtr<TargetInfo> Target(AllocateTarget(Triple.str()));
+ if (!Target) {
+ Diags.Report(diag::err_target_unknown_triple) << Triple.str();
+ return 0;
+ }
+
+ // Set the target CPU if specified.
+ if (!Opts.CPU.empty() && !Target->setCPU(Opts.CPU)) {
+ Diags.Report(diag::err_target_unknown_cpu) << Opts.CPU;
+ return 0;
+ }
+
+ // Set the target ABI if specified.
+ if (!Opts.ABI.empty() && !Target->setABI(Opts.ABI)) {
+ Diags.Report(diag::err_target_unknown_abi) << Opts.ABI;
+ return 0;
+ }
+
+ // Set the target C++ ABI.
+ if (!Opts.CXXABI.empty() && !Target->setCXXABI(Opts.CXXABI)) {
+ Diags.Report(diag::err_target_unknown_cxxabi) << Opts.CXXABI;
+ return 0;
+ }
+
+ // Compute the default target features, we need the target to handle this
+ // because features may have dependencies on one another.
+ llvm::StringMap<bool> Features;
+ Target->getDefaultFeatures(Opts.CPU, Features);
+
+ // Apply the user specified deltas.
+ for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
+ ie = Opts.Features.end(); it != ie; ++it) {
+ const char *Name = it->c_str();
+
+ // Apply the feature via the target.
+ if ((Name[0] != '-' && Name[0] != '+') ||
+ !Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
+ Diags.Report(diag::err_target_invalid_feature) << Name;
+ return 0;
+ }
+ }
+
+ // Add the features to the compile options.
+ //
+ // FIXME: If we are completely confident that we have the right set, we only
+ // need to pass the minuses.
+ Opts.Features.clear();
+ for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
+ ie = Features.end(); it != ie; ++it)
+ Opts.Features.push_back(std::string(it->second ? "+" : "-") + it->first());
+ Target->HandleTargetFeatures(Opts.Features);
+
+ return Target.take();
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp
new file mode 100644
index 0000000..8cdc1e3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/TokenKinds.cpp
@@ -0,0 +1,39 @@
+//===--- TokenKinds.cpp - Token Kinds Support -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenKind enum and support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TokenKinds.h"
+
+#include <cassert>
+using namespace clang;
+
+static const char * const TokNames[] = {
+#define TOK(X) #X,
+#define KEYWORD(X,Y) #X,
+#include "clang/Basic/TokenKinds.def"
+ 0
+};
+
+const char *tok::getTokenName(enum TokenKind Kind) {
+ assert(Kind < tok::NUM_TOKENS);
+ return TokNames[Kind];
+}
+
+const char *tok::getTokenSimpleSpelling(enum TokenKind Kind) {
+ switch (Kind) {
+#define PUNCTUATOR(X,Y) case X: return Y;
+#include "clang/Basic/TokenKinds.def"
+ default: break;
+ }
+
+ return 0;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
new file mode 100644
index 0000000..3a82e5d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
@@ -0,0 +1,92 @@
+//===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several version-related utility functions for Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Config/config.h"
+#include <cstring>
+#include <cstdlib>
+
+using namespace std;
+
+namespace clang {
+
+std::string getClangRepositoryPath() {
+#ifdef SVN_REPOSITORY
+ llvm::StringRef URL(SVN_REPOSITORY);
+#else
+ llvm::StringRef URL("");
+#endif
+
+ // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
+ // pick up a tag in an SVN export, for example.
+ static llvm::StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
+ if (URL.empty()) {
+ URL = SVNRepository.slice(SVNRepository.find(':'),
+ SVNRepository.find("/lib/Basic"));
+ }
+
+ // Strip off version from a build from an integration branch.
+ URL = URL.slice(0, URL.find("/src/tools/clang"));
+
+ // Trim path prefix off, assuming path came from standard cfe path.
+ size_t Start = URL.find("cfe/");
+ if (Start != llvm::StringRef::npos)
+ URL = URL.substr(Start + 4);
+
+ return URL;
+}
+
+std::string getClangRevision() {
+#ifdef SVN_REVISION
+ return SVN_REVISION;
+#else
+ return "";
+#endif
+}
+
+std::string getClangFullRepositoryVersion() {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+ std::string Path = getClangRepositoryPath();
+ std::string Revision = getClangRevision();
+ if (!Path.empty())
+ OS << Path;
+ if (!Revision.empty()) {
+ if (!Path.empty())
+ OS << ' ';
+ OS << Revision;
+ }
+ return OS.str();
+}
+
+std::string getClangFullVersion() {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
+#endif
+ OS << "clang version " CLANG_VERSION_STRING " ("
+ << getClangFullRepositoryVersion() << ')';
+
+#ifdef CLANG_VENDOR_SUFFIX
+ OS << CLANG_VENDOR_SUFFIX;
+#elif defined(CLANG_VENDOR)
+ // If vendor supplied, include the base LLVM version as well.
+ OS << " (based on LLVM " << PACKAGE_VERSION << ")";
+#endif
+
+ return OS.str();
+}
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
new file mode 100644
index 0000000..ce10398
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
@@ -0,0 +1,172 @@
+//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_ABIINFO_H
+#define CLANG_CODEGEN_ABIINFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/Type.h"
+
+namespace llvm {
+ class Value;
+ class LLVMContext;
+ class TargetData;
+}
+
+namespace clang {
+ class ASTContext;
+
+ namespace CodeGen {
+ class CGFunctionInfo;
+ class CodeGenFunction;
+ class CodeGenTypes;
+ }
+
+ // FIXME: All of this stuff should be part of the target interface
+ // somehow. It is currently here because it is not clear how to factor
+ // the targets to support this, since the Targets currently live in a
+ // layer below types n'stuff.
+
+ /// ABIArgInfo - Helper class to encapsulate information about how a
+ /// specific C type should be passed to or returned from a function.
+ class ABIArgInfo {
+ public:
+ enum Kind {
+ /// Direct - Pass the argument directly using the normal converted LLVM
+ /// type, or by coercing to another specified type stored in
+ /// 'CoerceToType'). If an offset is specified (in UIntData), then the
+ /// argument passed is offset by some number of bytes in the memory
+ /// representation.
+ Direct,
+
+ /// Extend - Valid only for integer argument types. Same as 'direct'
+ /// but also emit a zero/sign extension attribute.
+ Extend,
+
+ /// Indirect - Pass the argument indirectly via a hidden pointer
+ /// with the specified alignment (0 indicates default alignment).
+ Indirect,
+
+ /// Ignore - Ignore the argument (treat as void). Useful for void and
+ /// empty structs.
+ Ignore,
+
+ /// Expand - Only valid for aggregate argument types. The structure should
+ /// be expanded into consecutive arguments for its constituent fields.
+ /// Currently expand is only allowed on structures whose fields
+ /// are all scalar types or are themselves expandable types.
+ Expand,
+
+ KindFirst=Direct, KindLast=Expand
+ };
+
+ private:
+ Kind TheKind;
+ llvm::PATypeHolder TypeData;
+ unsigned UIntData;
+ bool BoolData0;
+ bool BoolData1;
+
+ ABIArgInfo(Kind K, const llvm::Type *TD=0,
+ unsigned UI=0, bool B0 = false, bool B1 = false)
+ : TheKind(K), TypeData(TD), UIntData(UI), BoolData0(B0), BoolData1(B1) {}
+
+ public:
+ ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
+
+ static ABIArgInfo getDirect(const llvm::Type *T = 0, unsigned Offset = 0) {
+ return ABIArgInfo(Direct, T, Offset);
+ }
+ static ABIArgInfo getExtend(const llvm::Type *T = 0) {
+ return ABIArgInfo(Extend, T, 0);
+ }
+ static ABIArgInfo getIgnore() {
+ return ABIArgInfo(Ignore);
+ }
+ static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
+ , bool Realign = false) {
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign);
+ }
+ static ABIArgInfo getExpand() {
+ return ABIArgInfo(Expand);
+ }
+
+ Kind getKind() const { return TheKind; }
+ bool isDirect() const { return TheKind == Direct; }
+ bool isExtend() const { return TheKind == Extend; }
+ bool isIgnore() const { return TheKind == Ignore; }
+ bool isIndirect() const { return TheKind == Indirect; }
+ bool isExpand() const { return TheKind == Expand; }
+
+ bool canHaveCoerceToType() const {
+ return TheKind == Direct || TheKind == Extend;
+ }
+
+ // Direct/Extend accessors
+ unsigned getDirectOffset() const {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ return UIntData;
+ }
+ const llvm::Type *getCoerceToType() const {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ return TypeData;
+ }
+
+ void setCoerceToType(const llvm::Type *T) {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ TypeData = T;
+ }
+
+ // Indirect accessors
+ unsigned getIndirectAlign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return UIntData;
+ }
+
+ bool getIndirectByVal() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return BoolData0;
+ }
+
+ bool getIndirectRealign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return BoolData1;
+ }
+
+ void dump() const;
+ };
+
+ /// ABIInfo - Target specific hooks for defining how a type should be
+ /// passed or returned from functions.
+ class ABIInfo {
+ public:
+ CodeGen::CodeGenTypes &CGT;
+
+ ABIInfo(CodeGen::CodeGenTypes &cgt) : CGT(cgt) {}
+ virtual ~ABIInfo();
+
+ ASTContext &getContext() const;
+ llvm::LLVMContext &getVMContext() const;
+ const llvm::TargetData &getTargetData() const;
+
+ virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
+
+ /// EmitVAArg - Emit the target dependent code to load a value of
+ /// \arg Ty from the va_list pointed to by \arg VAListAddr.
+
+ // FIXME: This is a gaping layering violation if we wanted to drop
+ // the ABI information any lower than CodeGen. Of course, for
+ // VAArg handling it has to be at this level; there is no way to
+ // abstract this out.
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGen::CodeGenFunction &CGF) const = 0;
+ };
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
new file mode 100644
index 0000000..9897b1b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
@@ -0,0 +1,353 @@
+//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/StandardPasses.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLibraryInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+class EmitAssemblyHelper {
+ Diagnostic &Diags;
+ const CodeGenOptions &CodeGenOpts;
+ const TargetOptions &TargetOpts;
+ Module *TheModule;
+
+ Timer CodeGenerationTime;
+
+ mutable PassManager *CodeGenPasses;
+ mutable PassManager *PerModulePasses;
+ mutable FunctionPassManager *PerFunctionPasses;
+
+private:
+ PassManager *getCodeGenPasses() const {
+ if (!CodeGenPasses) {
+ CodeGenPasses = new PassManager();
+ CodeGenPasses->add(new TargetData(TheModule));
+ }
+ return CodeGenPasses;
+ }
+
+ PassManager *getPerModulePasses() const {
+ if (!PerModulePasses) {
+ PerModulePasses = new PassManager();
+ PerModulePasses->add(new TargetData(TheModule));
+ }
+ return PerModulePasses;
+ }
+
+ FunctionPassManager *getPerFunctionPasses() const {
+ if (!PerFunctionPasses) {
+ PerFunctionPasses = new FunctionPassManager(TheModule);
+ PerFunctionPasses->add(new TargetData(TheModule));
+ }
+ return PerFunctionPasses;
+ }
+
+ void CreatePasses();
+
+ /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
+ ///
+ /// \return True on success.
+ bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS);
+
+public:
+ EmitAssemblyHelper(Diagnostic &_Diags,
+ const CodeGenOptions &CGOpts, const TargetOptions &TOpts,
+ Module *M)
+ : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts),
+ TheModule(M), CodeGenerationTime("Code Generation Time"),
+ CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}
+
+ ~EmitAssemblyHelper() {
+ delete CodeGenPasses;
+ delete PerModulePasses;
+ delete PerFunctionPasses;
+ }
+
+ void EmitAssembly(BackendAction Action, raw_ostream *OS);
+};
+
+}
+
+void EmitAssemblyHelper::CreatePasses() {
+ unsigned OptLevel = CodeGenOpts.OptimizationLevel;
+ CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;
+
+ // Handle disabling of LLVM optimization, where we want to preserve the
+ // internal module before any optimization.
+ if (CodeGenOpts.DisableLLVMOpts) {
+ OptLevel = 0;
+ Inlining = CodeGenOpts.NoInlining;
+ }
+
+ FunctionPassManager *FPM = getPerFunctionPasses();
+
+ TargetLibraryInfo *TLI =
+ new TargetLibraryInfo(Triple(TheModule->getTargetTriple()));
+ if (!CodeGenOpts.SimplifyLibCalls)
+ TLI->disableAllFunctions();
+ FPM->add(TLI);
+
+ // In -O0 if checking is disabled, we don't even have per-function passes.
+ if (CodeGenOpts.VerifyModule)
+ FPM->add(createVerifierPass());
+
+ // Assume that standard function passes aren't run for -O0.
+ if (OptLevel > 0)
+ llvm::createStandardFunctionPasses(FPM, OptLevel);
+
+ llvm::Pass *InliningPass = 0;
+ switch (Inlining) {
+ case CodeGenOptions::NoInlining: break;
+ case CodeGenOptions::NormalInlining: {
+ // Set the inline threshold following llvm-gcc.
+ //
+ // FIXME: Derive these constants in a principled fashion.
+ unsigned Threshold = 225;
+ if (CodeGenOpts.OptimizeSize)
+ Threshold = 75;
+ else if (OptLevel > 2)
+ Threshold = 275;
+ InliningPass = createFunctionInliningPass(Threshold);
+ break;
+ }
+ case CodeGenOptions::OnlyAlwaysInlining:
+ InliningPass = createAlwaysInlinerPass(); // Respect always_inline
+ break;
+ }
+
+ PassManager *MPM = getPerModulePasses();
+
+ TLI = new TargetLibraryInfo(Triple(TheModule->getTargetTriple()));
+ if (!CodeGenOpts.SimplifyLibCalls)
+ TLI->disableAllFunctions();
+ MPM->add(TLI);
+
+ // For now we always create per module passes.
+ llvm::createStandardModulePasses(MPM, OptLevel,
+ CodeGenOpts.OptimizeSize,
+ CodeGenOpts.UnitAtATime,
+ CodeGenOpts.UnrollLoops,
+ CodeGenOpts.SimplifyLibCalls,
+ /*HaveExceptions=*/true,
+ InliningPass);
+}
+
+bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
+ formatted_raw_ostream &OS) {
+ // Create the TargetMachine for generating code.
+ std::string Error;
+ std::string Triple = TheModule->getTargetTriple();
+ const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
+ if (!TheTarget) {
+ Diags.Report(diag::err_fe_unable_to_create_target) << Error;
+ return false;
+ }
+
+ // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
+ // being gross, this is also totally broken if we ever care about
+ // concurrency.
+
+ // Set frame pointer elimination mode.
+ if (!CodeGenOpts.DisableFPElim) {
+ llvm::NoFramePointerElim = false;
+ llvm::NoFramePointerElimNonLeaf = false;
+ } else if (CodeGenOpts.OmitLeafFramePointer) {
+ llvm::NoFramePointerElim = false;
+ llvm::NoFramePointerElimNonLeaf = true;
+ } else {
+ llvm::NoFramePointerElim = true;
+ llvm::NoFramePointerElimNonLeaf = true;
+ }
+
+ // Set float ABI type.
+ if (CodeGenOpts.FloatABI == "soft")
+ llvm::FloatABIType = llvm::FloatABI::Soft;
+ else if (CodeGenOpts.FloatABI == "hard")
+ llvm::FloatABIType = llvm::FloatABI::Hard;
+ else {
+ assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
+ llvm::FloatABIType = llvm::FloatABI::Default;
+ }
+
+ llvm::LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD;
+ llvm::NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
+ llvm::NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
+ NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
+ llvm::UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
+ llvm::UseSoftFloat = CodeGenOpts.SoftFloat;
+ UnwindTablesMandatory = CodeGenOpts.UnwindTables;
+
+ TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);
+
+ TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections);
+ TargetMachine::setDataSections (CodeGenOpts.DataSections);
+
+ // FIXME: Parse this earlier.
+ if (CodeGenOpts.RelocationModel == "static") {
+ TargetMachine::setRelocationModel(llvm::Reloc::Static);
+ } else if (CodeGenOpts.RelocationModel == "pic") {
+ TargetMachine::setRelocationModel(llvm::Reloc::PIC_);
+ } else {
+ assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
+ "Invalid PIC model!");
+ TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC);
+ }
+ // FIXME: Parse this earlier.
+ if (CodeGenOpts.CodeModel == "small") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Small);
+ } else if (CodeGenOpts.CodeModel == "kernel") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Kernel);
+ } else if (CodeGenOpts.CodeModel == "medium") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Medium);
+ } else if (CodeGenOpts.CodeModel == "large") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Large);
+ } else {
+ assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
+ TargetMachine::setCodeModel(llvm::CodeModel::Default);
+ }
+
+ std::vector<const char *> BackendArgs;
+ BackendArgs.push_back("clang"); // Fake program name.
+ if (!CodeGenOpts.DebugPass.empty()) {
+ BackendArgs.push_back("-debug-pass");
+ BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
+ }
+ if (!CodeGenOpts.LimitFloatPrecision.empty()) {
+ BackendArgs.push_back("-limit-float-precision");
+ BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
+ }
+ if (llvm::TimePassesIsEnabled)
+ BackendArgs.push_back("-time-passes");
+ BackendArgs.push_back(0);
+ llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
+ const_cast<char **>(&BackendArgs[0]));
+
+ std::string FeaturesStr;
+ if (TargetOpts.CPU.size() || TargetOpts.Features.size()) {
+ SubtargetFeatures Features;
+ Features.setCPU(TargetOpts.CPU);
+ for (std::vector<std::string>::const_iterator
+ it = TargetOpts.Features.begin(),
+ ie = TargetOpts.Features.end(); it != ie; ++it)
+ Features.AddFeature(*it);
+ FeaturesStr = Features.getString();
+ }
+ TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr);
+
+ if (CodeGenOpts.RelaxAll)
+ TM->setMCRelaxAll(true);
+
+ // Create the code generator passes.
+ PassManager *PM = getCodeGenPasses();
+ CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+
+ switch (CodeGenOpts.OptimizationLevel) {
+ default: break;
+ case 0: OptLevel = CodeGenOpt::None; break;
+ case 3: OptLevel = CodeGenOpt::Aggressive; break;
+ }
+
+ // Normal mode, emit a .s or .o file by running the code generator. Note,
+ // this also adds codegenerator level optimization passes.
+ TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile;
+ if (Action == Backend_EmitObj)
+ CGFT = TargetMachine::CGFT_ObjectFile;
+ else if (Action == Backend_EmitMCNull)
+ CGFT = TargetMachine::CGFT_Null;
+ else
+ assert(Action == Backend_EmitAssembly && "Invalid action!");
+ if (TM->addPassesToEmitFile(*PM, OS, CGFT, OptLevel,
+ /*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
+ Diags.Report(diag::err_fe_unable_to_interface_with_target);
+ return false;
+ }
+
+ return true;
+}
+
+void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
+ TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0);
+ llvm::formatted_raw_ostream FormattedOS;
+
+ CreatePasses();
+ switch (Action) {
+ case Backend_EmitNothing:
+ break;
+
+ case Backend_EmitBC:
+ getPerModulePasses()->add(createBitcodeWriterPass(*OS));
+ break;
+
+ case Backend_EmitLL:
+ FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
+ getPerModulePasses()->add(createPrintModulePass(&FormattedOS));
+ break;
+
+ default:
+ FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
+ if (!AddEmitPasses(Action, FormattedOS))
+ return;
+ }
+
+ // Run passes. For now we do all passes at once, but eventually we
+ // would like to have the option of streaming code generation.
+
+ if (PerFunctionPasses) {
+ PrettyStackTraceString CrashInfo("Per-function optimization");
+
+ PerFunctionPasses->doInitialization();
+ for (Module::iterator I = TheModule->begin(),
+ E = TheModule->end(); I != E; ++I)
+ if (!I->isDeclaration())
+ PerFunctionPasses->run(*I);
+ PerFunctionPasses->doFinalization();
+ }
+
+ if (PerModulePasses) {
+ PrettyStackTraceString CrashInfo("Per-module optimization passes");
+ PerModulePasses->run(*TheModule);
+ }
+
+ if (CodeGenPasses) {
+ PrettyStackTraceString CrashInfo("Code generation");
+ CodeGenPasses->run(*TheModule);
+ }
+}
+
+void clang::EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts,
+ const TargetOptions &TOpts, Module *M,
+ BackendAction Action, raw_ostream *OS) {
+ EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, M);
+
+ AsmHelper.EmitAssembly(Action, OS);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
new file mode 100644
index 0000000..a35648d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -0,0 +1,1421 @@
+//===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
+#include "CGObjCRuntime.h"
+#include "CodeGenModule.h"
+#include "CGBlocks.h"
+#include "clang/AST/DeclObjC.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Target/TargetData.h"
+#include <algorithm>
+
+using namespace clang;
+using namespace CodeGen;
+
+CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N)
+ : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
+ HasCXXObject(false), StructureType(0), Block(blockExpr) {
+
+ // Skip asm prefix, if any.
+ if (Name && Name[0] == '\01')
+ ++Name;
+}
+
+/// Build the given block as a global block.
+static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo,
+ llvm::Constant *blockFn);
+
+/// Build the helper function to copy a block.
+static llvm::Constant *buildCopyHelper(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo);
+}
+
+/// Build the helper function to dipose of a block.
+static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo);
+}
+
+/// Build the block descriptor constant for a block.
+static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ ASTContext &C = CGM.getContext();
+
+ const llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy);
+ const llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
+
+ llvm::SmallVector<llvm::Constant*, 6> elements;
+
+ // reserved
+ elements.push_back(llvm::ConstantInt::get(ulong, 0));
+
+ // Size
+ // FIXME: What is the right way to say this doesn't fit? We should give
+ // a user diagnostic in that case. Better fix would be to change the
+ // API to size_t.
+ elements.push_back(llvm::ConstantInt::get(ulong,
+ blockInfo.BlockSize.getQuantity()));
+
+ // Optional copy/dispose helpers.
+ if (blockInfo.NeedsCopyDispose) {
+ // copy_func_helper_decl
+ elements.push_back(buildCopyHelper(CGM, blockInfo));
+
+ // destroy_func_decl
+ elements.push_back(buildDisposeHelper(CGM, blockInfo));
+ }
+
+ // Signature. Mandatory ObjC-style method descriptor @encode sequence.
+ std::string typeAtEncoding =
+ CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
+ elements.push_back(llvm::ConstantExpr::getBitCast(
+ CGM.GetAddrOfConstantCString(typeAtEncoding), i8p));
+
+ // GC layout.
+ if (C.getLangOptions().ObjC1)
+ elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
+ else
+ elements.push_back(llvm::Constant::getNullValue(i8p));
+
+ llvm::Constant *init =
+ llvm::ConstantStruct::get(CGM.getLLVMContext(), elements.data(),
+ elements.size(), false);
+
+ llvm::GlobalVariable *global =
+ new llvm::GlobalVariable(CGM.getModule(), init->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ init, "__block_descriptor_tmp");
+
+ return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
+}
+
+static BlockFlags computeBlockFlag(CodeGenModule &CGM,
+ const BlockExpr *BE,
+ BlockFlags flags) {
+ const FunctionType *ftype = BE->getFunctionType();
+
+ // This is a bit overboard.
+ CallArgList args;
+ const CGFunctionInfo &fnInfo =
+ CGM.getTypes().getFunctionInfo(ftype->getResultType(), args,
+ ftype->getExtInfo());
+
+ if (CGM.ReturnTypeUsesSRet(fnInfo))
+ flags |= BLOCK_USE_STRET;
+
+ return flags;
+}
+
+/*
+ Purely notional variadic template describing the layout of a block.
+
+ template <class _ResultType, class... _ParamTypes, class... _CaptureTypes>
+ struct Block_literal {
+ /// Initialized to one of:
+ /// extern void *_NSConcreteStackBlock[];
+ /// extern void *_NSConcreteGlobalBlock[];
+ ///
+ /// In theory, we could start one off malloc'ed by setting
+ /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using
+ /// this isa:
+ /// extern void *_NSConcreteMallocBlock[];
+ struct objc_class *isa;
+
+ /// These are the flags (with corresponding bit number) that the
+ /// compiler is actually supposed to know about.
+ /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
+ /// descriptor provides copy and dispose helper functions
+ /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
+ /// object with a nontrivial destructor or copy constructor
+ /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated
+ /// as global memory
+ /// 29. BLOCK_USE_STRET - indicates that the block function
+ /// uses stret, which objc_msgSend needs to know about
+ /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an
+ /// @encoded signature string
+ /// And we're not supposed to manipulate these:
+ /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved
+ /// to malloc'ed memory
+ /// 27. BLOCK_IS_GC - indicates that the block has been moved to
+ /// to GC-allocated memory
+ /// Additionally, the bottom 16 bits are a reference count which
+ /// should be zero on the stack.
+ int flags;
+
+ /// Reserved; should be zero-initialized.
+ int reserved;
+
+ /// Function pointer generated from block literal.
+ _ResultType (*invoke)(Block_literal *, _ParamTypes...);
+
+ /// Block description metadata generated from block literal.
+ struct Block_descriptor *block_descriptor;
+
+ /// Captured values follow.
+ _CapturesTypes captures...;
+ };
+ */
+
+/// The number of fields in a block header.
+const unsigned BlockHeaderSize = 5;
+
+namespace {
+ /// A chunk of data that we actually have to capture in the block.
+ struct BlockLayoutChunk {
+ CharUnits Alignment;
+ CharUnits Size;
+ const BlockDecl::Capture *Capture; // null for 'this'
+ const llvm::Type *Type;
+
+ BlockLayoutChunk(CharUnits align, CharUnits size,
+ const BlockDecl::Capture *capture,
+ const llvm::Type *type)
+ : Alignment(align), Size(size), Capture(capture), Type(type) {}
+
+ /// Tell the block info that this chunk has the given field index.
+ void setIndex(CGBlockInfo &info, unsigned index) {
+ if (!Capture)
+ info.CXXThisIndex = index;
+ else
+ info.Captures[Capture->getVariable()]
+ = CGBlockInfo::Capture::makeIndex(index);
+ }
+ };
+
+ /// Order by descending alignment.
+ bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {
+ return left.Alignment > right.Alignment;
+ }
+}
+
+/// Determines if the given record type has a mutable field.
+static bool hasMutableField(const CXXRecordDecl *record) {
+ for (CXXRecordDecl::field_iterator
+ i = record->field_begin(), e = record->field_end(); i != e; ++i)
+ if ((*i)->isMutable())
+ return true;
+
+ for (CXXRecordDecl::base_class_const_iterator
+ i = record->bases_begin(), e = record->bases_end(); i != e; ++i) {
+ const RecordType *record = i->getType()->castAs<RecordType>();
+ if (hasMutableField(cast<CXXRecordDecl>(record->getDecl())))
+ return true;
+ }
+
+ return false;
+}
+
+/// Determines if the given type is safe for constant capture in C++.
+static bool isSafeForCXXConstantCapture(QualType type) {
+ const RecordType *recordType =
+ type->getBaseElementTypeUnsafe()->getAs<RecordType>();
+
+ // Only records can be unsafe.
+ if (!recordType) return true;
+
+ const CXXRecordDecl *record = cast<CXXRecordDecl>(recordType->getDecl());
+
+ // Maintain semantics for classes with non-trivial dtors or copy ctors.
+ if (!record->hasTrivialDestructor()) return false;
+ if (!record->hasTrivialCopyConstructor()) return false;
+
+ // Otherwise, we just have to make sure there aren't any mutable
+ // fields that might have changed since initialization.
+ return !hasMutableField(record);
+}
+
+/// It is illegal to modify a const object after initialization.
+/// Therefore, if a const object has a constant initializer, we don't
+/// actually need to keep storage for it in the block; we'll just
+/// rematerialize it at the start of the block function. This is
+/// acceptable because we make no promises about address stability of
+/// captured variables.
+static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
+ const VarDecl *var) {
+ QualType type = var->getType();
+
+ // We can only do this if the variable is const.
+ if (!type.isConstQualified()) return 0;
+
+ // Furthermore, in C++ we have to worry about mutable fields:
+ // C++ [dcl.type.cv]p4:
+ // Except that any class member declared mutable can be
+ // modified, any attempt to modify a const object during its
+ // lifetime results in undefined behavior.
+ if (CGM.getLangOptions().CPlusPlus && !isSafeForCXXConstantCapture(type))
+ return 0;
+
+ // If the variable doesn't have any initializer (shouldn't this be
+ // invalid?), it's not clear what we should do. Maybe capture as
+ // zero?
+ const Expr *init = var->getInit();
+ if (!init) return 0;
+
+ return CGM.EmitConstantExpr(init, var->getType());
+}
+
+/// Get the low bit of a nonzero character count. This is the
+/// alignment of the nth byte if the 0th byte is universally aligned.
+static CharUnits getLowBit(CharUnits v) {
+ return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1));
+}
+
+static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
+ std::vector<const llvm::Type*> &elementTypes) {
+ ASTContext &C = CGM.getContext();
+
+ // The header is basically a 'struct { void *; int; int; void *; void *; }'.
+ CharUnits ptrSize, ptrAlign, intSize, intAlign;
+ llvm::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy);
+ llvm::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy);
+
+ // Are there crazy embedded platforms where this isn't true?
+ assert(intSize <= ptrSize && "layout assumptions horribly violated");
+
+ CharUnits headerSize = ptrSize;
+ if (2 * intSize < ptrAlign) headerSize += ptrSize;
+ else headerSize += 2 * intSize;
+ headerSize += 2 * ptrSize;
+
+ info.BlockAlign = ptrAlign;
+ info.BlockSize = headerSize;
+
+ assert(elementTypes.empty());
+ const llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
+ const llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy);
+ elementTypes.push_back(i8p);
+ elementTypes.push_back(intTy);
+ elementTypes.push_back(intTy);
+ elementTypes.push_back(i8p);
+ elementTypes.push_back(CGM.getBlockDescriptorType());
+
+ assert(elementTypes.size() == BlockHeaderSize);
+}
+
+/// Compute the layout of the given block. Attempts to lay the block
+/// out with minimal space requirements.
+static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
+ ASTContext &C = CGM.getContext();
+ const BlockDecl *block = info.getBlockDecl();
+
+ std::vector<const llvm::Type*> elementTypes;
+ initializeForBlockHeader(CGM, info, elementTypes);
+
+ if (!block->hasCaptures()) {
+ info.StructureType =
+ llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
+ info.CanBeGlobal = true;
+ return;
+ }
+
+ // Collect the layout chunks.
+ llvm::SmallVector<BlockLayoutChunk, 16> layout;
+ layout.reserve(block->capturesCXXThis() +
+ (block->capture_end() - block->capture_begin()));
+
+ CharUnits maxFieldAlign;
+
+ // First, 'this'.
+ if (block->capturesCXXThis()) {
+ const DeclContext *DC = block->getDeclContext();
+ for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext())
+ ;
+ QualType thisType = cast<CXXMethodDecl>(DC)->getThisType(C);
+
+ const llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
+ std::pair<CharUnits,CharUnits> tinfo
+ = CGM.getContext().getTypeInfoInChars(thisType);
+ maxFieldAlign = std::max(maxFieldAlign, tinfo.second);
+
+ layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 0, llvmType));
+ }
+
+ // Next, all the block captures.
+ for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
+ ce = block->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+
+ if (ci->isByRef()) {
+ // We have to copy/dispose of the __block reference.
+ info.NeedsCopyDispose = true;
+
+ // Just use void* instead of a pointer to the byref type.
+ QualType byRefPtrTy = C.VoidPtrTy;
+
+ const llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy);
+ std::pair<CharUnits,CharUnits> tinfo
+ = CGM.getContext().getTypeInfoInChars(byRefPtrTy);
+ maxFieldAlign = std::max(maxFieldAlign, tinfo.second);
+
+ layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
+ &*ci, llvmType));
+ continue;
+ }
+
+ // Otherwise, build a layout chunk with the size and alignment of
+ // the declaration.
+ if (llvm::Constant *constant = tryCaptureAsConstant(CGM, variable)) {
+ info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant);
+ continue;
+ }
+
+ // Block pointers require copy/dispose.
+ if (variable->getType()->isBlockPointerType()) {
+ info.NeedsCopyDispose = true;
+
+ // So do Objective-C pointers.
+ } else if (variable->getType()->isObjCObjectPointerType() ||
+ C.isObjCNSObjectType(variable->getType())) {
+ info.NeedsCopyDispose = true;
+
+ // So do types that require non-trivial copy construction.
+ } else if (ci->hasCopyExpr()) {
+ info.NeedsCopyDispose = true;
+ info.HasCXXObject = true;
+
+ // And so do types with destructors.
+ } else if (CGM.getLangOptions().CPlusPlus) {
+ if (const CXXRecordDecl *record =
+ variable->getType()->getAsCXXRecordDecl()) {
+ if (!record->hasTrivialDestructor()) {
+ info.HasCXXObject = true;
+ info.NeedsCopyDispose = true;
+ }
+ }
+ }
+
+ CharUnits size = C.getTypeSizeInChars(variable->getType());
+ CharUnits align = C.getDeclAlign(variable);
+ maxFieldAlign = std::max(maxFieldAlign, align);
+
+ const llvm::Type *llvmType =
+ CGM.getTypes().ConvertTypeForMem(variable->getType());
+
+ layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType));
+ }
+
+ // If that was everything, we're done here.
+ if (layout.empty()) {
+ info.StructureType =
+ llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
+ info.CanBeGlobal = true;
+ return;
+ }
+
+ // Sort the layout by alignment. We have to use a stable sort here
+ // to get reproducible results. There should probably be an
+ // llvm::array_pod_stable_sort.
+ std::stable_sort(layout.begin(), layout.end());
+
+ CharUnits &blockSize = info.BlockSize;
+ info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
+
+ // Assuming that the first byte in the header is maximally aligned,
+ // get the alignment of the first byte following the header.
+ CharUnits endAlign = getLowBit(blockSize);
+
+ // If the end of the header isn't satisfactorily aligned for the
+ // maximum thing, look for things that are okay with the header-end
+ // alignment, and keep appending them until we get something that's
+ // aligned right. This algorithm is only guaranteed optimal if
+ // that condition is satisfied at some point; otherwise we can get
+ // things like:
+ // header // next byte has alignment 4
+ // something_with_size_5; // next byte has alignment 1
+ // something_with_alignment_8;
+ // which has 7 bytes of padding, as opposed to the naive solution
+ // which might have less (?).
+ if (endAlign < maxFieldAlign) {
+ llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
+ li = layout.begin() + 1, le = layout.end();
+
+ // Look for something that the header end is already
+ // satisfactorily aligned for.
+ for (; li != le && endAlign < li->Alignment; ++li)
+ ;
+
+ // If we found something that's naturally aligned for the end of
+ // the header, keep adding things...
+ if (li != le) {
+ llvm::SmallVectorImpl<BlockLayoutChunk>::iterator first = li;
+ for (; li != le; ++li) {
+ assert(endAlign >= li->Alignment);
+
+ li->setIndex(info, elementTypes.size());
+ elementTypes.push_back(li->Type);
+ blockSize += li->Size;
+ endAlign = getLowBit(blockSize);
+
+ // ...until we get to the alignment of the maximum field.
+ if (endAlign >= maxFieldAlign)
+ break;
+ }
+
+ // Don't re-append everything we just appended.
+ layout.erase(first, li);
+ }
+ }
+
+ // At this point, we just have to add padding if the end align still
+ // isn't aligned right.
+ if (endAlign < maxFieldAlign) {
+ CharUnits padding = maxFieldAlign - endAlign;
+
+ elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
+ padding.getQuantity()));
+ blockSize += padding;
+
+ endAlign = getLowBit(blockSize);
+ assert(endAlign >= maxFieldAlign);
+ }
+
+ // Slam everything else on now. This works because they have
+ // strictly decreasing alignment and we expect that size is always a
+ // multiple of alignment.
+ for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
+ li = layout.begin(), le = layout.end(); li != le; ++li) {
+ assert(endAlign >= li->Alignment);
+ li->setIndex(info, elementTypes.size());
+ elementTypes.push_back(li->Type);
+ blockSize += li->Size;
+ endAlign = getLowBit(blockSize);
+ }
+
+ info.StructureType =
+ llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
+}
+
+/// Emit a block literal expression in the current function.
+llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
+ std::string Name = CurFn->getName();
+ CGBlockInfo blockInfo(blockExpr, Name.c_str());
+
+ // Compute information about the layout, etc., of this block.
+ computeBlockInfo(CGM, blockInfo);
+
+ // Using that metadata, generate the actual block function.
+ llvm::Constant *blockFn
+ = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo,
+ CurFuncDecl, LocalDeclMap);
+ blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
+
+ // If there is nothing to capture, we can emit this as a global block.
+ if (blockInfo.CanBeGlobal)
+ return buildGlobalBlock(CGM, blockInfo, blockFn);
+
+ // Otherwise, we have to emit this as a local block.
+
+ llvm::Constant *isa = CGM.getNSConcreteStackBlock();
+ isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy);
+
+ // Build the block descriptor.
+ llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
+
+ const llvm::Type *intTy = ConvertType(getContext().IntTy);
+
+ llvm::AllocaInst *blockAddr =
+ CreateTempAlloca(blockInfo.StructureType, "block");
+ blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity());
+
+ // Compute the initial on-stack block flags.
+ BlockFlags flags = BLOCK_HAS_SIGNATURE;
+ if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
+ if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ;
+ flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), flags);
+
+ // Initialize the block literal.
+ Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
+ Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()),
+ Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
+ Builder.CreateStore(llvm::ConstantInt::get(intTy, 0),
+ Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
+ Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
+ "block.invoke"));
+ Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4,
+ "block.descriptor"));
+
+ // Finally, capture all the values into the block.
+ const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+
+ // First, 'this'.
+ if (blockDecl->capturesCXXThis()) {
+ llvm::Value *addr = Builder.CreateStructGEP(blockAddr,
+ blockInfo.CXXThisIndex,
+ "block.captured-this.addr");
+ Builder.CreateStore(LoadCXXThis(), addr);
+ }
+
+ // Next, captured variables.
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+
+ // Ignore constant captures.
+ if (capture.isConstant()) continue;
+
+ QualType type = variable->getType();
+
+ // This will be a [[type]]*, except that a byref entry will just be
+ // an i8**.
+ llvm::Value *blockField =
+ Builder.CreateStructGEP(blockAddr, capture.getIndex(),
+ "block.captured");
+
+ // Compute the address of the thing we're going to move into the
+ // block literal.
+ llvm::Value *src;
+ if (ci->isNested()) {
+ // We need to use the capture from the enclosing block.
+ const CGBlockInfo::Capture &enclosingCapture =
+ BlockInfo->getCapture(variable);
+
+ // This is a [[type]]*, except that a byref entry wil just be an i8**.
+ src = Builder.CreateStructGEP(LoadBlockStruct(),
+ enclosingCapture.getIndex(),
+ "block.capture.addr");
+ } else {
+ // This is a [[type]]*.
+ src = LocalDeclMap[variable];
+ }
+
+ // For byrefs, we just write the pointer to the byref struct into
+ // the block field. There's no need to chase the forwarding
+ // pointer at this point, since we're building something that will
+ // live a shorter life than the stack byref anyway.
+ if (ci->isByRef()) {
+ // Get a void* that points to the byref struct.
+ if (ci->isNested())
+ src = Builder.CreateLoad(src, "byref.capture");
+ else
+ src = Builder.CreateBitCast(src, VoidPtrTy);
+
+ // Write that void* into the capture field.
+ Builder.CreateStore(src, blockField);
+
+ // If we have a copy constructor, evaluate that into the block field.
+ } else if (const Expr *copyExpr = ci->getCopyExpr()) {
+ EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
+
+ // If it's a reference variable, copy the reference into the block field.
+ } else if (type->isReferenceType()) {
+ Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField);
+
+ // Otherwise, fake up a POD copy into the block field.
+ } else {
+ // We use one of these or the other depending on whether the
+ // reference is nested.
+ DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue,
+ SourceLocation());
+ BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), type,
+ VK_LValue, SourceLocation(), /*byref*/ false);
+
+ Expr *declRef =
+ (ci->isNested() ? static_cast<Expr*>(&nested) : &notNested);
+
+ ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
+ declRef, VK_RValue);
+ EmitAnyExprToMem(&l2r, blockField, /*volatile*/ false, /*init*/ true);
+ }
+
+ // Push a destructor if necessary. The semantics for when this
+ // actually gets run are really obscure.
+ if (!ci->isByRef() && CGM.getLangOptions().CPlusPlus)
+ PushDestructorCleanup(type, blockField);
+ }
+
+ // Cast to the converted block-pointer type, which happens (somewhat
+ // unfortunately) to be a pointer to function type.
+ llvm::Value *result =
+ Builder.CreateBitCast(blockAddr,
+ ConvertType(blockInfo.getBlockExpr()->getType()));
+
+ return result;
+}
+
+
+const llvm::Type *CodeGenModule::getBlockDescriptorType() {
+ if (BlockDescriptorType)
+ return BlockDescriptorType;
+
+ const llvm::Type *UnsignedLongTy =
+ getTypes().ConvertType(getContext().UnsignedLongTy);
+
+ // struct __block_descriptor {
+ // unsigned long reserved;
+ // unsigned long block_size;
+ //
+ // // later, the following will be added
+ //
+ // struct {
+ // void (*copyHelper)();
+ // void (*copyHelper)();
+ // } helpers; // !!! optional
+ //
+ // const char *signature; // the block signature
+ // const char *layout; // reserved
+ // };
+ BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(),
+ UnsignedLongTy,
+ UnsignedLongTy,
+ NULL);
+
+ getModule().addTypeName("struct.__block_descriptor",
+ BlockDescriptorType);
+
+ // Now form a pointer to that.
+ BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType);
+ return BlockDescriptorType;
+}
+
+const llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
+ if (GenericBlockLiteralType)
+ return GenericBlockLiteralType;
+
+ const llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
+
+ // struct __block_literal_generic {
+ // void *__isa;
+ // int __flags;
+ // int __reserved;
+ // void (*__invoke)(void *);
+ // struct __block_descriptor *__descriptor;
+ // };
+ GenericBlockLiteralType = llvm::StructType::get(getLLVMContext(),
+ VoidPtrTy,
+ IntTy,
+ IntTy,
+ VoidPtrTy,
+ BlockDescPtrTy,
+ NULL);
+
+ getModule().addTypeName("struct.__block_literal_generic",
+ GenericBlockLiteralType);
+
+ return GenericBlockLiteralType;
+}
+
+
+RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
+ ReturnValueSlot ReturnValue) {
+ const BlockPointerType *BPT =
+ E->getCallee()->getType()->getAs<BlockPointerType>();
+
+ llvm::Value *Callee = EmitScalarExpr(E->getCallee());
+
+ // Get a pointer to the generic block literal.
+ const llvm::Type *BlockLiteralTy =
+ llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
+
+ // Bitcast the callee to a block literal.
+ llvm::Value *BlockLiteral =
+ Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
+
+ // Get the function pointer from the literal.
+ llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
+
+ BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy, "tmp");
+
+ // Add the block literal.
+ QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
+ CallArgList Args;
+ Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
+
+ QualType FnType = BPT->getPointeeType();
+
+ // And the rest of the arguments.
+ EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(),
+ E->arg_begin(), E->arg_end());
+
+ // Load the function.
+ llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp");
+
+ const FunctionType *FuncTy = FnType->getAs<FunctionType>();
+ QualType ResultType = FuncTy->getResultType();
+
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().getFunctionInfo(ResultType, Args,
+ FuncTy->getExtInfo());
+
+ // Cast the function pointer to the right type.
+ const llvm::Type *BlockFTy =
+ CGM.getTypes().GetFunctionType(FnInfo, false);
+
+ const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
+ Func = Builder.CreateBitCast(Func, BlockFTyPtr);
+
+ // And call the block.
+ return EmitCall(FnInfo, Func, ReturnValue, Args);
+}
+
+llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
+ bool isByRef) {
+ assert(BlockInfo && "evaluating block ref without block information?");
+ const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
+
+ // Handle constant captures.
+ if (capture.isConstant()) return LocalDeclMap[variable];
+
+ llvm::Value *addr =
+ Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
+ "block.capture.addr");
+
+ if (isByRef) {
+ // addr should be a void** right now. Load, then cast the result
+ // to byref*.
+
+ addr = Builder.CreateLoad(addr);
+ const llvm::PointerType *byrefPointerType
+ = llvm::PointerType::get(BuildByRefType(variable), 0);
+ addr = Builder.CreateBitCast(addr, byrefPointerType,
+ "byref.addr");
+
+ // Follow the forwarding pointer.
+ addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding");
+ addr = Builder.CreateLoad(addr, "byref.addr.forwarded");
+
+ // Cast back to byref* and GEP over to the actual object.
+ addr = Builder.CreateBitCast(addr, byrefPointerType);
+ addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable),
+ variable->getNameAsString());
+ }
+
+ if (variable->getType()->isReferenceType())
+ addr = Builder.CreateLoad(addr, "ref.tmp");
+
+ return addr;
+}
+
+llvm::Constant *
+CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
+ const char *name) {
+ CGBlockInfo blockInfo(blockExpr, name);
+
+ // Compute information about the layout, etc., of this block.
+ computeBlockInfo(*this, blockInfo);
+
+ // Using that metadata, generate the actual block function.
+ llvm::Constant *blockFn;
+ {
+ llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
+ blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
+ blockInfo,
+ 0, LocalDeclMap);
+ }
+ blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
+
+ return buildGlobalBlock(*this, blockInfo, blockFn);
+}
+
+static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo,
+ llvm::Constant *blockFn) {
+ assert(blockInfo.CanBeGlobal);
+
+ // Generate the constants for the block literal initializer.
+ llvm::Constant *fields[BlockHeaderSize];
+
+ // isa
+ fields[0] = CGM.getNSConcreteGlobalBlock();
+
+ // __flags
+ BlockFlags flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(),
+ BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE);
+ fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask());
+
+ // Reserved
+ fields[2] = llvm::Constant::getNullValue(CGM.IntTy);
+
+ // Function
+ fields[3] = blockFn;
+
+ // Descriptor
+ fields[4] = buildBlockDescriptor(CGM, blockInfo);
+
+ llvm::Constant *init =
+ llvm::ConstantStruct::get(CGM.getLLVMContext(), fields, BlockHeaderSize,
+ /*packed*/ false);
+
+ llvm::GlobalVariable *literal =
+ new llvm::GlobalVariable(CGM.getModule(),
+ init->getType(),
+ /*constant*/ true,
+ llvm::GlobalVariable::InternalLinkage,
+ init,
+ "__block_literal_global");
+ literal->setAlignment(blockInfo.BlockAlign.getQuantity());
+
+ // Return a constant of the appropriately-casted type.
+ const llvm::Type *requiredType =
+ CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
+ return llvm::ConstantExpr::getBitCast(literal, requiredType);
+}
+
+llvm::Function *
+CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
+ const CGBlockInfo &blockInfo,
+ const Decl *outerFnDecl,
+ const DeclMapTy &ldm) {
+ const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+
+ DebugInfo = CGM.getDebugInfo();
+ BlockInfo = &blockInfo;
+
+ // Arrange for local static and local extern declarations to appear
+ // to be local to this function as well, in case they're directly
+ // referenced in a block.
+ for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
+ const VarDecl *var = dyn_cast<VarDecl>(i->first);
+ if (var && !var->hasLocalStorage())
+ LocalDeclMap[var] = i->second;
+ }
+
+ // Begin building the function declaration.
+
+ // Build the argument list.
+ FunctionArgList args;
+
+ // The first argument is the block pointer. Just take it as a void*
+ // and cast it later.
+ QualType selfTy = getContext().VoidPtrTy;
+ IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
+
+ // FIXME: this leaks, and we only need it very temporarily.
+ ImplicitParamDecl *selfDecl =
+ ImplicitParamDecl::Create(getContext(),
+ const_cast<BlockDecl*>(blockDecl),
+ SourceLocation(), II, selfTy);
+ args.push_back(std::make_pair(selfDecl, selfTy));
+
+ // Now add the rest of the parameters.
+ for (BlockDecl::param_const_iterator i = blockDecl->param_begin(),
+ e = blockDecl->param_end(); i != e; ++i)
+ args.push_back(std::make_pair(*i, (*i)->getType()));
+
+ // Create the function declaration.
+ const FunctionProtoType *fnType =
+ cast<FunctionProtoType>(blockInfo.getBlockExpr()->getFunctionType());
+ const CGFunctionInfo &fnInfo =
+ CGM.getTypes().getFunctionInfo(fnType->getResultType(), args,
+ fnType->getExtInfo());
+ const llvm::FunctionType *fnLLVMType =
+ CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic());
+
+ MangleBuffer name;
+ CGM.getBlockMangledName(GD, name, blockDecl);
+ llvm::Function *fn =
+ llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage,
+ name.getString(), &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
+
+ // Begin generating the function.
+ StartFunction(blockDecl, fnType->getResultType(), fn, args,
+ blockInfo.getBlockExpr()->getBody()->getLocEnd());
+ CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl
+
+ // Okay. Undo some of what StartFunction did. We really don't need
+ // an alloca for the block address; in theory we could remove it,
+ // but that might do unpleasant things to debug info.
+ llvm::AllocaInst *blockAddrAlloca
+ = cast<llvm::AllocaInst>(LocalDeclMap[selfDecl]);
+ llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca);
+ BlockPointer = Builder.CreateBitCast(blockAddr,
+ blockInfo.StructureType->getPointerTo(),
+ "block");
+
+ // If we have a C++ 'this' reference, go ahead and force it into
+ // existence now.
+ if (blockDecl->capturesCXXThis()) {
+ llvm::Value *addr = Builder.CreateStructGEP(BlockPointer,
+ blockInfo.CXXThisIndex,
+ "block.captured-this");
+ CXXThisValue = Builder.CreateLoad(addr, "this");
+ }
+
+ // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap;
+ // appease it.
+ if (const ObjCMethodDecl *method
+ = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl)) {
+ const VarDecl *self = method->getSelfDecl();
+
+ // There might not be a capture for 'self', but if there is...
+ if (blockInfo.Captures.count(self)) {
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(self);
+ llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer,
+ capture.getIndex(),
+ "block.captured-self");
+ LocalDeclMap[self] = selfAddr;
+ }
+ }
+
+ // Also force all the constant captures.
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+ if (!capture.isConstant()) continue;
+
+ unsigned align = getContext().getDeclAlign(variable).getQuantity();
+
+ llvm::AllocaInst *alloca =
+ CreateMemTemp(variable->getType(), "block.captured-const");
+ alloca->setAlignment(align);
+
+ Builder.CreateStore(capture.getConstant(), alloca, align);
+
+ LocalDeclMap[variable] = alloca;
+ }
+
+ // Save a spot to insert the debug information for all the BlockDeclRefDecls.
+ llvm::BasicBlock *entry = Builder.GetInsertBlock();
+ llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
+ --entry_ptr;
+
+ EmitStmt(blockDecl->getBody());
+
+ // Remember where we were...
+ llvm::BasicBlock *resume = Builder.GetInsertBlock();
+
+ // Go back to the entry.
+ ++entry_ptr;
+ Builder.SetInsertPoint(entry, entry_ptr);
+
+ // Emit debug information for all the BlockDeclRefDecls.
+ // FIXME: also for 'this'
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ DI->setLocation(variable->getLocation());
+
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+ if (capture.isConstant()) {
+ DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable],
+ Builder);
+ continue;
+ }
+
+ DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca,
+ Builder, blockInfo);
+ }
+ }
+
+ // And resume where we left off.
+ if (resume == 0)
+ Builder.ClearInsertionPoint();
+ else
+ Builder.SetInsertPoint(resume);
+
+ FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
+
+ return fn;
+}
+
+/*
+ notes.push_back(HelperInfo());
+ HelperInfo &note = notes.back();
+ note.index = capture.getIndex();
+ note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type));
+ note.cxxbar_import = ci->getCopyExpr();
+
+ if (ci->isByRef()) {
+ note.flag = BLOCK_FIELD_IS_BYREF;
+ if (type.isObjCGCWeak())
+ note.flag |= BLOCK_FIELD_IS_WEAK;
+ } else if (type->isBlockPointerType()) {
+ note.flag = BLOCK_FIELD_IS_BLOCK;
+ } else {
+ note.flag = BLOCK_FIELD_IS_OBJECT;
+ }
+ */
+
+
+
+
+
+llvm::Constant *
+CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
+ ASTContext &C = getContext();
+
+ FunctionArgList args;
+ // FIXME: This leaks
+ ImplicitParamDecl *dstDecl =
+ ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy);
+ args.push_back(std::make_pair(dstDecl, dstDecl->getType()));
+ ImplicitParamDecl *srcDecl =
+ ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy);
+ args.push_back(std::make_pair(srcDecl, srcDecl->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+
+ // FIXME: it would be nice if these were mergeable with things with
+ // identical semantics.
+ const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ "__copy_helper_block_", &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__copy_helper_block_");
+
+ FunctionDecl *FD = FunctionDecl::Create(C,
+ C.getTranslationUnitDecl(),
+ SourceLocation(), II, C.VoidTy, 0,
+ SC_Static,
+ SC_None,
+ false,
+ true);
+ StartFunction(FD, C.VoidTy, Fn, args, SourceLocation());
+
+ const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
+
+ llvm::Value *src = GetAddrOfLocalVar(srcDecl);
+ src = Builder.CreateLoad(src);
+ src = Builder.CreateBitCast(src, structPtrTy, "block.source");
+
+ llvm::Value *dst = GetAddrOfLocalVar(dstDecl);
+ dst = Builder.CreateLoad(dst);
+ dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
+
+ const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ QualType type = variable->getType();
+
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+ if (capture.isConstant()) continue;
+
+ const Expr *copyExpr = ci->getCopyExpr();
+ unsigned flags = 0;
+
+ if (copyExpr) {
+ assert(!ci->isByRef());
+ // don't bother computing flags
+ } else if (ci->isByRef()) {
+ flags = BLOCK_FIELD_IS_BYREF;
+ if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK;
+ } else if (type->isBlockPointerType()) {
+ flags = BLOCK_FIELD_IS_BLOCK;
+ } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) {
+ flags = BLOCK_FIELD_IS_OBJECT;
+ }
+
+ if (!copyExpr && !flags) continue;
+
+ unsigned index = capture.getIndex();
+ llvm::Value *srcField = Builder.CreateStructGEP(src, index);
+ llvm::Value *dstField = Builder.CreateStructGEP(dst, index);
+
+ // If there's an explicit copy expression, we do that.
+ if (copyExpr) {
+ EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr);
+ } else {
+ llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
+ srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
+ llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy);
+ Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue,
+ llvm::ConstantInt::get(Int32Ty, flags));
+ }
+ }
+
+ FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+}
+
+llvm::Constant *
+CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
+ ASTContext &C = getContext();
+
+ FunctionArgList args;
+ // FIXME: This leaks
+ ImplicitParamDecl *srcDecl =
+ ImplicitParamDecl::Create(C, 0, SourceLocation(), 0, C.VoidPtrTy);
+ args.push_back(std::make_pair(srcDecl, srcDecl->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+
+ // FIXME: We'd like to put these into a mergable by content, with
+ // internal linkage.
+ const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ "__destroy_helper_block_", &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__destroy_helper_block_");
+
+ FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(),
+ SourceLocation(), II, C.VoidTy, 0,
+ SC_Static,
+ SC_None,
+ false, true);
+ StartFunction(FD, C.VoidTy, Fn, args, SourceLocation());
+
+ const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
+
+ llvm::Value *src = GetAddrOfLocalVar(srcDecl);
+ src = Builder.CreateLoad(src);
+ src = Builder.CreateBitCast(src, structPtrTy, "block");
+
+ const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+
+ CodeGenFunction::RunCleanupsScope cleanups(*this);
+
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ QualType type = variable->getType();
+
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+ if (capture.isConstant()) continue;
+
+ BlockFieldFlags flags;
+ const CXXDestructorDecl *dtor = 0;
+
+ if (ci->isByRef()) {
+ flags = BLOCK_FIELD_IS_BYREF;
+ if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK;
+ } else if (type->isBlockPointerType()) {
+ flags = BLOCK_FIELD_IS_BLOCK;
+ } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) {
+ flags = BLOCK_FIELD_IS_OBJECT;
+ } else if (C.getLangOptions().CPlusPlus) {
+ if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
+ if (!record->hasTrivialDestructor())
+ dtor = record->getDestructor();
+ }
+
+ if (!dtor && flags.empty()) continue;
+
+ unsigned index = capture.getIndex();
+ llvm::Value *srcField = Builder.CreateStructGEP(src, index);
+
+ // If there's an explicit copy expression, we do that.
+ if (dtor) {
+ PushDestructorCleanup(dtor, srcField);
+
+ // Otherwise we call _Block_object_dispose. It wouldn't be too
+ // hard to just emit this as a cleanup if we wanted to make sure
+ // that things were done in reverse.
+ } else {
+ llvm::Value *value = Builder.CreateLoad(srcField);
+ value = Builder.CreateBitCast(value, VoidPtrTy);
+ BuildBlockRelease(value, flags);
+ }
+ }
+
+ cleanups.ForceCleanup();
+
+ FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+}
+
+llvm::Constant *CodeGenFunction::
+GeneratebyrefCopyHelperFunction(const llvm::Type *T, BlockFieldFlags flags,
+ const VarDecl *variable) {
+ QualType R = getContext().VoidTy;
+
+ FunctionArgList Args;
+ // FIXME: This leaks
+ ImplicitParamDecl *Dst =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Dst, Dst->getType()));
+
+ // FIXME: This leaks
+ ImplicitParamDecl *Src =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Src, Src->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+
+ // FIXME: We'd like to put these into a mergable by content, with
+ // internal linkage.
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ "__Block_byref_object_copy_", &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__Block_byref_object_copy_");
+
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R, 0,
+ SC_Static,
+ SC_None,
+ false, true);
+ StartFunction(FD, R, Fn, Args, SourceLocation());
+
+ // dst->x
+ llvm::Value *V = GetAddrOfLocalVar(Dst);
+ V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
+ V = Builder.CreateLoad(V);
+ V = Builder.CreateStructGEP(V, 6, "x");
+ llvm::Value *DstObj = V;
+
+ // src->x
+ V = GetAddrOfLocalVar(Src);
+ V = Builder.CreateLoad(V);
+ V = Builder.CreateBitCast(V, T);
+ V = Builder.CreateStructGEP(V, 6, "x");
+
+ if (Expr *copyExpr = getContext().getBlockVarCopyInits(variable)) {
+ llvm::Value *SrcObj = V;
+ EmitSynthesizedCXXCopyCtor(DstObj, SrcObj, copyExpr);
+ } else {
+ DstObj = Builder.CreateBitCast(DstObj, VoidPtrTy);
+ V = Builder.CreateBitCast(V, VoidPtrPtrTy);
+ llvm::Value *SrcObj = Builder.CreateLoad(V);
+ flags |= BLOCK_BYREF_CALLER;
+ llvm::Value *N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask());
+ llvm::Value *F = CGM.getBlockObjectAssign();
+ Builder.CreateCall3(F, DstObj, SrcObj, N);
+ }
+
+ FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy);
+}
+
+llvm::Constant *
+CodeGenFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
+ BlockFieldFlags flags,
+ const VarDecl *variable) {
+ QualType R = getContext().VoidTy;
+
+ FunctionArgList Args;
+ // FIXME: This leaks
+ ImplicitParamDecl *Src =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+
+ Args.push_back(std::make_pair(Src, Src->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+
+ // FIXME: We'd like to put these into a mergable by content, with
+ // internal linkage.
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ "__Block_byref_object_dispose_",
+ &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__Block_byref_object_dispose_");
+
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R, 0,
+ SC_Static,
+ SC_None,
+ false, true);
+ StartFunction(FD, R, Fn, Args, SourceLocation());
+
+ llvm::Value *V = GetAddrOfLocalVar(Src);
+ V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
+ V = Builder.CreateLoad(V);
+ V = Builder.CreateStructGEP(V, 6, "x");
+
+ // If it's not any kind of special object, it must have a destructor
+ // or something.
+ if (!flags.isSpecialPointer()) {
+ EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
+ PushDestructorCleanup(variable->getType(), V);
+ PopCleanupBlocks(CleanupDepth);
+
+ // Otherwise, call _Block_object_dispose.
+ } else {
+ V = Builder.CreateBitCast(V, llvm::PointerType::get(Int8PtrTy, 0));
+ V = Builder.CreateLoad(V);
+
+ flags |= BLOCK_BYREF_CALLER;
+ BuildBlockRelease(V, flags);
+ }
+
+ FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy);
+}
+
+llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T,
+ BlockFieldFlags flags,
+ unsigned align,
+ const VarDecl *var) {
+ // All alignments below that of pointer alignment collapse down to just
+ // pointer alignment, as we always have at least that much alignment to begin
+ // with.
+ align /= unsigned(getTarget().getPointerAlign(0) / 8);
+
+ // As an optimization, we only generate a single function of each kind we
+ // might need. We need a different one for each alignment and for each
+ // setting of flags. We mix Align and flag to get the kind.
+ uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask();
+ llvm::Constant *&Entry = AssignCache[Kind];
+ if (!Entry)
+ Entry = CodeGenFunction(*this).
+ GeneratebyrefCopyHelperFunction(T, flags, var);
+ return Entry;
+}
+
+llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T,
+ BlockFieldFlags flags,
+ unsigned align,
+ const VarDecl *var) {
+ // All alignments below that of pointer alignment collpase down to just
+ // pointer alignment, as we always have at least that much alignment to begin
+ // with.
+ align /= unsigned(getTarget().getPointerAlign(0) / 8);
+
+ // As an optimization, we only generate a single function of each kind we
+ // might need. We need a different one for each alignment and for each
+ // setting of flags. We mix Align and flag to get the kind.
+ uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask();
+ llvm::Constant *&Entry = DestroyCache[Kind];
+ if (!Entry)
+ Entry = CodeGenFunction(*this).
+ GeneratebyrefDestroyHelperFunction(T, flags, var);
+ return Entry;
+}
+
+void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
+ llvm::Value *F = CGM.getBlockObjectDispose();
+ llvm::Value *N;
+ V = Builder.CreateBitCast(V, Int8PtrTy);
+ N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask());
+ Builder.CreateCall2(F, V, N);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
new file mode 100644
index 0000000..bee729d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
@@ -0,0 +1,198 @@
+//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal state used for llvm translation for block literals.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGBLOCKS_H
+#define CLANG_CODEGEN_CGBLOCKS_H
+
+#include "CodeGenTypes.h"
+#include "clang/AST/Type.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+
+#include "CGBuilder.h"
+#include "CGCall.h"
+#include "CGValue.h"
+
+namespace llvm {
+ class Module;
+ class Constant;
+ class Function;
+ class GlobalValue;
+ class TargetData;
+ class FunctionType;
+ class PointerType;
+ class Value;
+ class LLVMContext;
+}
+
+namespace clang {
+
+namespace CodeGen {
+
+class CodeGenModule;
+class CGBlockInfo;
+
+enum BlockFlag_t {
+ BLOCK_HAS_COPY_DISPOSE = (1 << 25),
+ BLOCK_HAS_CXX_OBJ = (1 << 26),
+ BLOCK_IS_GLOBAL = (1 << 28),
+ BLOCK_USE_STRET = (1 << 29),
+ BLOCK_HAS_SIGNATURE = (1 << 30)
+};
+class BlockFlags {
+ uint32_t flags;
+
+ BlockFlags(uint32_t flags) : flags(flags) {}
+public:
+ BlockFlags() : flags(0) {}
+ BlockFlags(BlockFlag_t flag) : flags(flag) {}
+
+ uint32_t getBitMask() const { return flags; }
+ bool empty() const { return flags == 0; }
+
+ friend BlockFlags operator|(BlockFlags l, BlockFlags r) {
+ return BlockFlags(l.flags | r.flags);
+ }
+ friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) {
+ l.flags |= r.flags;
+ return l;
+ }
+ friend bool operator&(BlockFlags l, BlockFlags r) {
+ return (l.flags & r.flags);
+ }
+};
+inline BlockFlags operator|(BlockFlag_t l, BlockFlag_t r) {
+ return BlockFlags(l) | BlockFlags(r);
+}
+
+enum BlockFieldFlag_t {
+ BLOCK_FIELD_IS_OBJECT = 0x03, /* id, NSObject, __attribute__((NSObject)),
+ block, ... */
+ BLOCK_FIELD_IS_BLOCK = 0x07, /* a block variable */
+
+ BLOCK_FIELD_IS_BYREF = 0x08, /* the on stack structure holding the __block
+ variable */
+ BLOCK_FIELD_IS_WEAK = 0x10, /* declared __weak, only used in byref copy
+ helpers */
+
+ BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
+ support routines */
+ BLOCK_BYREF_CURRENT_MAX = 256
+};
+
+class BlockFieldFlags {
+ uint32_t flags;
+
+ BlockFieldFlags(uint32_t flags) : flags(flags) {}
+public:
+ BlockFieldFlags() : flags(0) {}
+ BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {}
+
+ uint32_t getBitMask() const { return flags; }
+ bool empty() const { return flags == 0; }
+
+ /// Answers whether the flags indicate that this field is an object
+ /// or block pointer that requires _Block_object_assign/dispose.
+ bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; }
+
+ friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) {
+ return BlockFieldFlags(l.flags | r.flags);
+ }
+ friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) {
+ l.flags |= r.flags;
+ return l;
+ }
+ friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) {
+ return (l.flags & r.flags);
+ }
+};
+inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) {
+ return BlockFieldFlags(l) | BlockFieldFlags(r);
+}
+
+/// CGBlockInfo - Information to generate a block literal.
+class CGBlockInfo {
+public:
+ /// Name - The name of the block, kindof.
+ const char *Name;
+
+ /// The field index of 'this' within the block, if there is one.
+ unsigned CXXThisIndex;
+
+ class Capture {
+ uintptr_t Data;
+
+ public:
+ bool isIndex() const { return (Data & 1) != 0; }
+ bool isConstant() const { return !isIndex(); }
+ unsigned getIndex() const { assert(isIndex()); return Data >> 1; }
+ llvm::Value *getConstant() const {
+ assert(isConstant());
+ return reinterpret_cast<llvm::Value*>(Data);
+ }
+
+ static Capture makeIndex(unsigned index) {
+ Capture v;
+ v.Data = (index << 1) | 1;
+ return v;
+ }
+
+ static Capture makeConstant(llvm::Value *value) {
+ Capture v;
+ v.Data = reinterpret_cast<uintptr_t>(value);
+ return v;
+ }
+ };
+
+ /// The mapping of allocated indexes within the block.
+ llvm::DenseMap<const VarDecl*, Capture> Captures;
+
+ /// CanBeGlobal - True if the block can be global, i.e. it has
+ /// no non-constant captures.
+ bool CanBeGlobal : 1;
+
+ /// True if the block needs a custom copy or dispose function.
+ bool NeedsCopyDispose : 1;
+
+ /// HasCXXObject - True if the block's custom copy/dispose functions
+ /// need to be run even in GC mode.
+ bool HasCXXObject : 1;
+
+ const llvm::StructType *StructureType;
+ const BlockExpr *Block;
+ CharUnits BlockSize;
+ CharUnits BlockAlign;
+ llvm::SmallVector<const Expr*, 8> BlockLayout;
+
+ const Capture &getCapture(const VarDecl *var) const {
+ llvm::DenseMap<const VarDecl*, Capture>::const_iterator
+ it = Captures.find(var);
+ assert(it != Captures.end() && "no entry for variable!");
+ return it->second;
+ }
+
+ const BlockDecl *getBlockDecl() const { return Block->getBlockDecl(); }
+ const BlockExpr *getBlockExpr() const { return Block; }
+
+ CGBlockInfo(const BlockExpr *blockExpr, const char *Name);
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
new file mode 100644
index 0000000..8120217
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
@@ -0,0 +1,28 @@
+//===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGBUILDER_H
+#define CLANG_CODEGEN_CGBUILDER_H
+
+#include "llvm/Support/IRBuilder.h"
+
+namespace clang {
+namespace CodeGen {
+
+// Don't preserve names on values in an optimized build.
+#ifdef NDEBUG
+typedef llvm::IRBuilder<false> CGBuilderTy;
+#else
+typedef llvm::IRBuilder<> CGBuilderTy;
+#endif
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
new file mode 100644
index 0000000..5eeb605
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -0,0 +1,2176 @@
+//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Builtin calls as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetInfo.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGObjCRuntime.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+using namespace llvm;
+
+static void EmitMemoryBarrier(CodeGenFunction &CGF,
+ bool LoadLoad, bool LoadStore,
+ bool StoreLoad, bool StoreStore,
+ bool Device) {
+ Value *True = CGF.Builder.getTrue();
+ Value *False = CGF.Builder.getFalse();
+ Value *C[5] = { LoadLoad ? True : False,
+ LoadStore ? True : False,
+ StoreLoad ? True : False,
+ StoreStore ? True : False,
+ Device ? True : False };
+ CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::memory_barrier),
+ C, C + 5);
+}
+
+/// Emit the conversions required to turn the given value into an
+/// integer of the given size.
+static Value *EmitToInt(CodeGenFunction &CGF, llvm::Value *V,
+ QualType T, const llvm::IntegerType *IntType) {
+ V = CGF.EmitToMemory(V, T);
+
+ if (V->getType()->isPointerTy())
+ return CGF.Builder.CreatePtrToInt(V, IntType);
+
+ assert(V->getType() == IntType);
+ return V;
+}
+
+static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V,
+ QualType T, const llvm::Type *ResultType) {
+ V = CGF.EmitFromMemory(V, T);
+
+ if (ResultType->isPointerTy())
+ return CGF.Builder.CreateIntToPtr(V, ResultType);
+
+ assert(V->getType() == ResultType);
+ return V;
+}
+
+// The atomic builtins are also full memory barriers. This is a utility for
+// wrapping a call to the builtins with memory barriers.
+static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn,
+ Value **ArgBegin, Value **ArgEnd) {
+ // FIXME: We need a target hook for whether this applies to device memory or
+ // not.
+ bool Device = true;
+
+ // Create barriers both before and after the call.
+ EmitMemoryBarrier(CGF, true, true, true, true, Device);
+ Value *Result = CGF.Builder.CreateCall(Fn, ArgBegin, ArgEnd);
+ EmitMemoryBarrier(CGF, true, true, true, true, Device);
+ return Result;
+}
+
+/// Utility to insert an atomic instruction based on Instrinsic::ID
+/// and the expression node.
+static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
+ Intrinsic::ID Id, const CallExpr *E) {
+ QualType T = E->getType();
+ assert(E->getArg(0)->getType()->isPointerType());
+ assert(CGF.getContext().hasSameUnqualifiedType(T,
+ E->getArg(0)->getType()->getPointeeType()));
+ assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType()));
+
+ llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0));
+ unsigned AddrSpace =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+
+ const llvm::IntegerType *IntType =
+ llvm::IntegerType::get(CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(T));
+ const llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
+
+ const llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType };
+ llvm::Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes, 2);
+
+ llvm::Value *Args[2];
+ Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType);
+ Args[1] = CGF.EmitScalarExpr(E->getArg(1));
+ const llvm::Type *ValueType = Args[1]->getType();
+ Args[1] = EmitToInt(CGF, Args[1], T, IntType);
+
+ llvm::Value *Result = EmitCallWithBarrier(CGF, AtomF, Args, Args + 2);
+ Result = EmitFromInt(CGF, Result, T, ValueType);
+ return RValue::get(Result);
+}
+
+/// Utility to insert an atomic instruction based Instrinsic::ID and
+/// the expression node, where the return value is the result of the
+/// operation.
+static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
+ Intrinsic::ID Id, const CallExpr *E,
+ Instruction::BinaryOps Op) {
+ QualType T = E->getType();
+ assert(E->getArg(0)->getType()->isPointerType());
+ assert(CGF.getContext().hasSameUnqualifiedType(T,
+ E->getArg(0)->getType()->getPointeeType()));
+ assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType()));
+
+ llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0));
+ unsigned AddrSpace =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+
+ const llvm::IntegerType *IntType =
+ llvm::IntegerType::get(CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(T));
+ const llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
+
+ const llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType };
+ llvm::Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes, 2);
+
+ llvm::Value *Args[2];
+ Args[1] = CGF.EmitScalarExpr(E->getArg(1));
+ const llvm::Type *ValueType = Args[1]->getType();
+ Args[1] = EmitToInt(CGF, Args[1], T, IntType);
+ Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType);
+
+ llvm::Value *Result = EmitCallWithBarrier(CGF, AtomF, Args, Args + 2);
+ Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]);
+ Result = EmitFromInt(CGF, Result, T, ValueType);
+ return RValue::get(Result);
+}
+
+/// EmitFAbs - Emit a call to fabs/fabsf/fabsl, depending on the type of ValTy,
+/// which must be a scalar floating point type.
+static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) {
+ const BuiltinType *ValTyP = ValTy->getAs<BuiltinType>();
+ assert(ValTyP && "isn't scalar fp type!");
+
+ StringRef FnName;
+ switch (ValTyP->getKind()) {
+ default: assert(0 && "Isn't a scalar fp type!");
+ case BuiltinType::Float: FnName = "fabsf"; break;
+ case BuiltinType::Double: FnName = "fabs"; break;
+ case BuiltinType::LongDouble: FnName = "fabsl"; break;
+ }
+
+ // The prototype is something that takes and returns whatever V's type is.
+ std::vector<const llvm::Type*> Args;
+ Args.push_back(V->getType());
+ llvm::FunctionType *FT = llvm::FunctionType::get(V->getType(), Args, false);
+ llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FT, FnName);
+
+ return CGF.Builder.CreateCall(Fn, V, "abs");
+}
+
+RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
+ unsigned BuiltinID, const CallExpr *E) {
+ // See if we can constant fold this builtin. If so, don't emit it at all.
+ Expr::EvalResult Result;
+ if (E->Evaluate(Result, CGM.getContext())) {
+ if (Result.Val.isInt())
+ return RValue::get(llvm::ConstantInt::get(getLLVMContext(),
+ Result.Val.getInt()));
+ if (Result.Val.isFloat())
+ return RValue::get(llvm::ConstantFP::get(getLLVMContext(),
+ Result.Val.getFloat()));
+ }
+
+ switch (BuiltinID) {
+ default: break; // Handle intrinsics and libm functions below.
+ case Builtin::BI__builtin___CFStringMakeConstantString:
+ case Builtin::BI__builtin___NSStringMakeConstantString:
+ return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0));
+ case Builtin::BI__builtin_stdarg_start:
+ case Builtin::BI__builtin_va_start:
+ case Builtin::BI__builtin_va_end: {
+ Value *ArgValue = EmitVAListRef(E->getArg(0));
+ const llvm::Type *DestType = Int8PtrTy;
+ if (ArgValue->getType() != DestType)
+ ArgValue = Builder.CreateBitCast(ArgValue, DestType,
+ ArgValue->getName().data());
+
+ Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ?
+ Intrinsic::vaend : Intrinsic::vastart;
+ return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue));
+ }
+ case Builtin::BI__builtin_va_copy: {
+ Value *DstPtr = EmitVAListRef(E->getArg(0));
+ Value *SrcPtr = EmitVAListRef(E->getArg(1));
+
+ const llvm::Type *Type = Int8PtrTy;
+
+ DstPtr = Builder.CreateBitCast(DstPtr, Type);
+ SrcPtr = Builder.CreateBitCast(SrcPtr, Type);
+ return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy),
+ DstPtr, SrcPtr));
+ }
+ case Builtin::BI__builtin_abs: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ Value *NegOp = Builder.CreateNeg(ArgValue, "neg");
+ Value *CmpResult =
+ Builder.CreateICmpSGE(ArgValue,
+ llvm::Constant::getNullValue(ArgValue->getType()),
+ "abscond");
+ Value *Result =
+ Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs");
+
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_ctz:
+ case Builtin::BI__builtin_ctzl:
+ case Builtin::BI__builtin_ctzll: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_clz:
+ case Builtin::BI__builtin_clzl:
+ case Builtin::BI__builtin_clzll: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::ctlz, &ArgType, 1);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_ffs:
+ case Builtin::BI__builtin_ffsl:
+ case Builtin::BI__builtin_ffsll: {
+ // ffs(x) -> x ? cttz(x) + 1 : 0
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"),
+ llvm::ConstantInt::get(ArgType, 1), "tmp");
+ Value *Zero = llvm::Constant::getNullValue(ArgType);
+ Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero");
+ Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs");
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_parity:
+ case Builtin::BI__builtin_parityl:
+ case Builtin::BI__builtin_parityll: {
+ // parity(x) -> ctpop(x) & 1
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Tmp = Builder.CreateCall(F, ArgValue, "tmp");
+ Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1),
+ "tmp");
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_popcount:
+ case Builtin::BI__builtin_popcountl:
+ case Builtin::BI__builtin_popcountll: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_expect: {
+ // FIXME: pass expect through to LLVM
+ if (E->getArg(1)->HasSideEffects(getContext()))
+ (void)EmitScalarExpr(E->getArg(1));
+ return RValue::get(EmitScalarExpr(E->getArg(0)));
+ }
+ case Builtin::BI__builtin_bswap32:
+ case Builtin::BI__builtin_bswap64: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ const llvm::Type *ArgType = ArgValue->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1);
+ return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
+ }
+ case Builtin::BI__builtin_object_size: {
+ // We pass this builtin onto the optimizer so that it can
+ // figure out the object size in more complex cases.
+ const llvm::Type *ResType[] = {
+ ConvertType(E->getType())
+ };
+
+ // LLVM only supports 0 and 2, make sure that we pass along that
+ // as a boolean.
+ Value *Ty = EmitScalarExpr(E->getArg(1));
+ ConstantInt *CI = dyn_cast<ConstantInt>(Ty);
+ assert(CI);
+ uint64_t val = CI->getZExtValue();
+ CI = ConstantInt::get(Builder.getInt1Ty(), (val & 0x2) >> 1);
+
+ Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1);
+ return RValue::get(Builder.CreateCall2(F,
+ EmitScalarExpr(E->getArg(0)),
+ CI));
+ }
+ case Builtin::BI__builtin_prefetch: {
+ Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
+ // FIXME: Technically these constants should of type 'int', yes?
+ RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) :
+ llvm::ConstantInt::get(Int32Ty, 0);
+ Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) :
+ llvm::ConstantInt::get(Int32Ty, 3);
+ Value *F = CGM.getIntrinsic(Intrinsic::prefetch, 0, 0);
+ return RValue::get(Builder.CreateCall3(F, Address, RW, Locality));
+ }
+ case Builtin::BI__builtin_trap: {
+ Value *F = CGM.getIntrinsic(Intrinsic::trap, 0, 0);
+ return RValue::get(Builder.CreateCall(F));
+ }
+ case Builtin::BI__builtin_unreachable: {
+ if (CatchUndefined)
+ EmitBranch(getTrapBB());
+ else
+ Builder.CreateUnreachable();
+
+ // We do need to preserve an insertion point.
+ EmitBlock(createBasicBlock("unreachable.cont"));
+
+ return RValue::get(0);
+ }
+
+ case Builtin::BI__builtin_powi:
+ case Builtin::BI__builtin_powif:
+ case Builtin::BI__builtin_powil: {
+ Value *Base = EmitScalarExpr(E->getArg(0));
+ Value *Exponent = EmitScalarExpr(E->getArg(1));
+ const llvm::Type *ArgType = Base->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::powi, &ArgType, 1);
+ return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp"));
+ }
+
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered: {
+ // Ordered comparisons: we know the arguments to these are matching scalar
+ // floating point values.
+ Value *LHS = EmitScalarExpr(E->getArg(0));
+ Value *RHS = EmitScalarExpr(E->getArg(1));
+
+ switch (BuiltinID) {
+ default: assert(0 && "Unknown ordered comparison");
+ case Builtin::BI__builtin_isgreater:
+ LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp");
+ break;
+ case Builtin::BI__builtin_isgreaterequal:
+ LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp");
+ break;
+ case Builtin::BI__builtin_isless:
+ LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp");
+ break;
+ case Builtin::BI__builtin_islessequal:
+ LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp");
+ break;
+ case Builtin::BI__builtin_islessgreater:
+ LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp");
+ break;
+ case Builtin::BI__builtin_isunordered:
+ LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp");
+ break;
+ }
+ // ZExt bool to int type.
+ return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()),
+ "tmp"));
+ }
+ case Builtin::BI__builtin_isnan: {
+ Value *V = EmitScalarExpr(E->getArg(0));
+ V = Builder.CreateFCmpUNO(V, V, "cmp");
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp"));
+ }
+
+ case Builtin::BI__builtin_isinf: {
+ // isinf(x) --> fabs(x) == infinity
+ Value *V = EmitScalarExpr(E->getArg(0));
+ V = EmitFAbs(*this, V, E->getArg(0)->getType());
+
+ V = Builder.CreateFCmpOEQ(V, ConstantFP::getInfinity(V->getType()),"isinf");
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp"));
+ }
+
+ // TODO: BI__builtin_isinf_sign
+ // isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0
+
+ case Builtin::BI__builtin_isnormal: {
+ // isnormal(x) --> x == x && fabsf(x) < infinity && fabsf(x) >= float_min
+ Value *V = EmitScalarExpr(E->getArg(0));
+ Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq");
+
+ Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType());
+ Value *IsLessThanInf =
+ Builder.CreateFCmpULT(Abs, ConstantFP::getInfinity(V->getType()),"isinf");
+ APFloat Smallest = APFloat::getSmallestNormalized(
+ getContext().getFloatTypeSemantics(E->getArg(0)->getType()));
+ Value *IsNormal =
+ Builder.CreateFCmpUGE(Abs, ConstantFP::get(V->getContext(), Smallest),
+ "isnormal");
+ V = Builder.CreateAnd(Eq, IsLessThanInf, "and");
+ V = Builder.CreateAnd(V, IsNormal, "and");
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
+ }
+
+ case Builtin::BI__builtin_isfinite: {
+ // isfinite(x) --> x == x && fabs(x) != infinity; }
+ Value *V = EmitScalarExpr(E->getArg(0));
+ Value *Eq = Builder.CreateFCmpOEQ(V, V, "iseq");
+
+ Value *Abs = EmitFAbs(*this, V, E->getArg(0)->getType());
+ Value *IsNotInf =
+ Builder.CreateFCmpUNE(Abs, ConstantFP::getInfinity(V->getType()),"isinf");
+
+ V = Builder.CreateAnd(Eq, IsNotInf, "and");
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
+ }
+
+ case Builtin::BI__builtin_fpclassify: {
+ Value *V = EmitScalarExpr(E->getArg(5));
+ const llvm::Type *Ty = ConvertType(E->getArg(5)->getType());
+
+ // Create Result
+ BasicBlock *Begin = Builder.GetInsertBlock();
+ BasicBlock *End = createBasicBlock("fpclassify_end", this->CurFn);
+ Builder.SetInsertPoint(End);
+ PHINode *Result =
+ Builder.CreatePHI(ConvertType(E->getArg(0)->getType()),
+ "fpclassify_result");
+
+ // if (V==0) return FP_ZERO
+ Builder.SetInsertPoint(Begin);
+ Value *IsZero = Builder.CreateFCmpOEQ(V, Constant::getNullValue(Ty),
+ "iszero");
+ Value *ZeroLiteral = EmitScalarExpr(E->getArg(4));
+ BasicBlock *NotZero = createBasicBlock("fpclassify_not_zero", this->CurFn);
+ Builder.CreateCondBr(IsZero, End, NotZero);
+ Result->addIncoming(ZeroLiteral, Begin);
+
+ // if (V != V) return FP_NAN
+ Builder.SetInsertPoint(NotZero);
+ Value *IsNan = Builder.CreateFCmpUNO(V, V, "cmp");
+ Value *NanLiteral = EmitScalarExpr(E->getArg(0));
+ BasicBlock *NotNan = createBasicBlock("fpclassify_not_nan", this->CurFn);
+ Builder.CreateCondBr(IsNan, End, NotNan);
+ Result->addIncoming(NanLiteral, NotZero);
+
+ // if (fabs(V) == infinity) return FP_INFINITY
+ Builder.SetInsertPoint(NotNan);
+ Value *VAbs = EmitFAbs(*this, V, E->getArg(5)->getType());
+ Value *IsInf =
+ Builder.CreateFCmpOEQ(VAbs, ConstantFP::getInfinity(V->getType()),
+ "isinf");
+ Value *InfLiteral = EmitScalarExpr(E->getArg(1));
+ BasicBlock *NotInf = createBasicBlock("fpclassify_not_inf", this->CurFn);
+ Builder.CreateCondBr(IsInf, End, NotInf);
+ Result->addIncoming(InfLiteral, NotNan);
+
+ // if (fabs(V) >= MIN_NORMAL) return FP_NORMAL else FP_SUBNORMAL
+ Builder.SetInsertPoint(NotInf);
+ APFloat Smallest = APFloat::getSmallestNormalized(
+ getContext().getFloatTypeSemantics(E->getArg(5)->getType()));
+ Value *IsNormal =
+ Builder.CreateFCmpUGE(VAbs, ConstantFP::get(V->getContext(), Smallest),
+ "isnormal");
+ Value *NormalResult =
+ Builder.CreateSelect(IsNormal, EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)));
+ Builder.CreateBr(End);
+ Result->addIncoming(NormalResult, NotInf);
+
+ // return Result
+ Builder.SetInsertPoint(End);
+ return RValue::get(Result);
+ }
+
+ case Builtin::BIalloca:
+ case Builtin::BI__builtin_alloca: {
+ Value *Size = EmitScalarExpr(E->getArg(0));
+ return RValue::get(Builder.CreateAlloca(Builder.getInt8Ty(), Size, "tmp"));
+ }
+ case Builtin::BIbzero:
+ case Builtin::BI__builtin_bzero: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *SizeVal = EmitScalarExpr(E->getArg(1));
+ Builder.CreateMemSet(Address, Builder.getInt8(0), SizeVal, 1, false);
+ return RValue::get(Address);
+ }
+ case Builtin::BImemcpy:
+ case Builtin::BI__builtin_memcpy: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *SrcAddr = EmitScalarExpr(E->getArg(1));
+ Value *SizeVal = EmitScalarExpr(E->getArg(2));
+ Builder.CreateMemCpy(Address, SrcAddr, SizeVal, 1, false);
+ return RValue::get(Address);
+ }
+
+ case Builtin::BI__builtin_objc_memmove_collectable: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *SrcAddr = EmitScalarExpr(E->getArg(1));
+ Value *SizeVal = EmitScalarExpr(E->getArg(2));
+ CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this,
+ Address, SrcAddr, SizeVal);
+ return RValue::get(Address);
+ }
+
+ case Builtin::BImemmove:
+ case Builtin::BI__builtin_memmove: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *SrcAddr = EmitScalarExpr(E->getArg(1));
+ Value *SizeVal = EmitScalarExpr(E->getArg(2));
+ Builder.CreateMemMove(Address, SrcAddr, SizeVal, 1, false);
+ return RValue::get(Address);
+ }
+ case Builtin::BImemset:
+ case Builtin::BI__builtin_memset: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
+ Builder.getInt8Ty());
+ Value *SizeVal = EmitScalarExpr(E->getArg(2));
+ Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false);
+ return RValue::get(Address);
+ }
+ case Builtin::BI__builtin_dwarf_cfa: {
+ // The offset in bytes from the first argument to the CFA.
+ //
+ // Why on earth is this in the frontend? Is there any reason at
+ // all that the backend can't reasonably determine this while
+ // lowering llvm.eh.dwarf.cfa()?
+ //
+ // TODO: If there's a satisfactory reason, add a target hook for
+ // this instead of hard-coding 0, which is correct for most targets.
+ int32_t Offset = 0;
+
+ Value *F = CGM.getIntrinsic(Intrinsic::eh_dwarf_cfa, 0, 0);
+ return RValue::get(Builder.CreateCall(F,
+ llvm::ConstantInt::get(Int32Ty, Offset)));
+ }
+ case Builtin::BI__builtin_return_address: {
+ Value *Depth = EmitScalarExpr(E->getArg(0));
+ Depth = Builder.CreateIntCast(Depth, Int32Ty, false, "tmp");
+ Value *F = CGM.getIntrinsic(Intrinsic::returnaddress, 0, 0);
+ return RValue::get(Builder.CreateCall(F, Depth));
+ }
+ case Builtin::BI__builtin_frame_address: {
+ Value *Depth = EmitScalarExpr(E->getArg(0));
+ Depth = Builder.CreateIntCast(Depth, Int32Ty, false, "tmp");
+ Value *F = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0);
+ return RValue::get(Builder.CreateCall(F, Depth));
+ }
+ case Builtin::BI__builtin_extract_return_addr: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Result = getTargetHooks().decodeReturnAddress(*this, Address);
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_frob_return_addr: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Result = getTargetHooks().encodeReturnAddress(*this, Address);
+ return RValue::get(Result);
+ }
+ case Builtin::BI__builtin_dwarf_sp_column: {
+ const llvm::IntegerType *Ty
+ = cast<llvm::IntegerType>(ConvertType(E->getType()));
+ int Column = getTargetHooks().getDwarfEHStackPointer(CGM);
+ if (Column == -1) {
+ CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column");
+ return RValue::get(llvm::UndefValue::get(Ty));
+ }
+ return RValue::get(llvm::ConstantInt::get(Ty, Column, true));
+ }
+ case Builtin::BI__builtin_init_dwarf_reg_size_table: {
+ Value *Address = EmitScalarExpr(E->getArg(0));
+ if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address))
+ CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table");
+ return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
+ }
+ case Builtin::BI__builtin_eh_return: {
+ Value *Int = EmitScalarExpr(E->getArg(0));
+ Value *Ptr = EmitScalarExpr(E->getArg(1));
+
+ const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(Int->getType());
+ assert((IntTy->getBitWidth() == 32 || IntTy->getBitWidth() == 64) &&
+ "LLVM's __builtin_eh_return only supports 32- and 64-bit variants");
+ Value *F = CGM.getIntrinsic(IntTy->getBitWidth() == 32
+ ? Intrinsic::eh_return_i32
+ : Intrinsic::eh_return_i64,
+ 0, 0);
+ Builder.CreateCall2(F, Int, Ptr);
+ Builder.CreateUnreachable();
+
+ // We do need to preserve an insertion point.
+ EmitBlock(createBasicBlock("builtin_eh_return.cont"));
+
+ return RValue::get(0);
+ }
+ case Builtin::BI__builtin_unwind_init: {
+ Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init, 0, 0);
+ return RValue::get(Builder.CreateCall(F));
+ }
+ case Builtin::BI__builtin_extend_pointer: {
+ // Extends a pointer to the size of an _Unwind_Word, which is
+ // uint64_t on all platforms. Generally this gets poked into a
+ // register and eventually used as an address, so if the
+ // addressing registers are wider than pointers and the platform
+ // doesn't implicitly ignore high-order bits when doing
+ // addressing, we need to make sure we zext / sext based on
+ // the platform's expectations.
+ //
+ // See: http://gcc.gnu.org/ml/gcc-bugs/2002-02/msg00237.html
+
+ // Cast the pointer to intptr_t.
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ Value *Result = Builder.CreatePtrToInt(Ptr, IntPtrTy, "extend.cast");
+
+ // If that's 64 bits, we're done.
+ if (IntPtrTy->getBitWidth() == 64)
+ return RValue::get(Result);
+
+ // Otherwise, ask the codegen data what to do.
+ if (getTargetHooks().extendPointerWithSExt())
+ return RValue::get(Builder.CreateSExt(Result, Int64Ty, "extend.sext"));
+ else
+ return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext"));
+ }
+ case Builtin::BI__builtin_setjmp: {
+ // Buffer is a void**.
+ Value *Buf = EmitScalarExpr(E->getArg(0));
+
+ // Store the frame pointer to the setjmp buffer.
+ Value *FrameAddr =
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
+ ConstantInt::get(Int32Ty, 0));
+ Builder.CreateStore(FrameAddr, Buf);
+
+ // Store the stack pointer to the setjmp buffer.
+ Value *StackAddr =
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave));
+ Value *StackSaveSlot =
+ Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2));
+ Builder.CreateStore(StackAddr, StackSaveSlot);
+
+ // Call LLVM's EH setjmp, which is lightweight.
+ Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp);
+ Buf = Builder.CreateBitCast(Buf, Int8PtrTy);
+ return RValue::get(Builder.CreateCall(F, Buf));
+ }
+ case Builtin::BI__builtin_longjmp: {
+ Value *Buf = EmitScalarExpr(E->getArg(0));
+ Buf = Builder.CreateBitCast(Buf, Int8PtrTy);
+
+ // Call LLVM's EH longjmp, which is lightweight.
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp), Buf);
+
+ // longjmp doesn't return; mark this as unreachable.
+ Builder.CreateUnreachable();
+
+ // We do need to preserve an insertion point.
+ EmitBlock(createBasicBlock("longjmp.cont"));
+
+ return RValue::get(0);
+ }
+ case Builtin::BI__sync_fetch_and_add:
+ case Builtin::BI__sync_fetch_and_sub:
+ case Builtin::BI__sync_fetch_and_or:
+ case Builtin::BI__sync_fetch_and_and:
+ case Builtin::BI__sync_fetch_and_xor:
+ case Builtin::BI__sync_add_and_fetch:
+ case Builtin::BI__sync_sub_and_fetch:
+ case Builtin::BI__sync_and_and_fetch:
+ case Builtin::BI__sync_or_and_fetch:
+ case Builtin::BI__sync_xor_and_fetch:
+ case Builtin::BI__sync_val_compare_and_swap:
+ case Builtin::BI__sync_bool_compare_and_swap:
+ case Builtin::BI__sync_lock_test_and_set:
+ case Builtin::BI__sync_lock_release:
+ assert(0 && "Shouldn't make it through sema");
+ case Builtin::BI__sync_fetch_and_add_1:
+ case Builtin::BI__sync_fetch_and_add_2:
+ case Builtin::BI__sync_fetch_and_add_4:
+ case Builtin::BI__sync_fetch_and_add_8:
+ case Builtin::BI__sync_fetch_and_add_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_add, E);
+ case Builtin::BI__sync_fetch_and_sub_1:
+ case Builtin::BI__sync_fetch_and_sub_2:
+ case Builtin::BI__sync_fetch_and_sub_4:
+ case Builtin::BI__sync_fetch_and_sub_8:
+ case Builtin::BI__sync_fetch_and_sub_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_sub, E);
+ case Builtin::BI__sync_fetch_and_or_1:
+ case Builtin::BI__sync_fetch_and_or_2:
+ case Builtin::BI__sync_fetch_and_or_4:
+ case Builtin::BI__sync_fetch_and_or_8:
+ case Builtin::BI__sync_fetch_and_or_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_or, E);
+ case Builtin::BI__sync_fetch_and_and_1:
+ case Builtin::BI__sync_fetch_and_and_2:
+ case Builtin::BI__sync_fetch_and_and_4:
+ case Builtin::BI__sync_fetch_and_and_8:
+ case Builtin::BI__sync_fetch_and_and_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_and, E);
+ case Builtin::BI__sync_fetch_and_xor_1:
+ case Builtin::BI__sync_fetch_and_xor_2:
+ case Builtin::BI__sync_fetch_and_xor_4:
+ case Builtin::BI__sync_fetch_and_xor_8:
+ case Builtin::BI__sync_fetch_and_xor_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_xor, E);
+
+ // Clang extensions: not overloaded yet.
+ case Builtin::BI__sync_fetch_and_min:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E);
+ case Builtin::BI__sync_fetch_and_max:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_max, E);
+ case Builtin::BI__sync_fetch_and_umin:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umin, E);
+ case Builtin::BI__sync_fetch_and_umax:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umax, E);
+
+ case Builtin::BI__sync_add_and_fetch_1:
+ case Builtin::BI__sync_add_and_fetch_2:
+ case Builtin::BI__sync_add_and_fetch_4:
+ case Builtin::BI__sync_add_and_fetch_8:
+ case Builtin::BI__sync_add_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E,
+ llvm::Instruction::Add);
+ case Builtin::BI__sync_sub_and_fetch_1:
+ case Builtin::BI__sync_sub_and_fetch_2:
+ case Builtin::BI__sync_sub_and_fetch_4:
+ case Builtin::BI__sync_sub_and_fetch_8:
+ case Builtin::BI__sync_sub_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_sub, E,
+ llvm::Instruction::Sub);
+ case Builtin::BI__sync_and_and_fetch_1:
+ case Builtin::BI__sync_and_and_fetch_2:
+ case Builtin::BI__sync_and_and_fetch_4:
+ case Builtin::BI__sync_and_and_fetch_8:
+ case Builtin::BI__sync_and_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_and, E,
+ llvm::Instruction::And);
+ case Builtin::BI__sync_or_and_fetch_1:
+ case Builtin::BI__sync_or_and_fetch_2:
+ case Builtin::BI__sync_or_and_fetch_4:
+ case Builtin::BI__sync_or_and_fetch_8:
+ case Builtin::BI__sync_or_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_or, E,
+ llvm::Instruction::Or);
+ case Builtin::BI__sync_xor_and_fetch_1:
+ case Builtin::BI__sync_xor_and_fetch_2:
+ case Builtin::BI__sync_xor_and_fetch_4:
+ case Builtin::BI__sync_xor_and_fetch_8:
+ case Builtin::BI__sync_xor_and_fetch_16:
+ return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_xor, E,
+ llvm::Instruction::Xor);
+
+ case Builtin::BI__sync_val_compare_and_swap_1:
+ case Builtin::BI__sync_val_compare_and_swap_2:
+ case Builtin::BI__sync_val_compare_and_swap_4:
+ case Builtin::BI__sync_val_compare_and_swap_8:
+ case Builtin::BI__sync_val_compare_and_swap_16: {
+ QualType T = E->getType();
+ llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0));
+ unsigned AddrSpace =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+
+ const llvm::IntegerType *IntType =
+ llvm::IntegerType::get(getLLVMContext(),
+ getContext().getTypeSize(T));
+ const llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
+ const llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType };
+ Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap,
+ IntrinsicTypes, 2);
+
+ Value *Args[3];
+ Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType);
+ Args[1] = EmitScalarExpr(E->getArg(1));
+ const llvm::Type *ValueType = Args[1]->getType();
+ Args[1] = EmitToInt(*this, Args[1], T, IntType);
+ Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
+
+ Value *Result = EmitCallWithBarrier(*this, AtomF, Args, Args + 3);
+ Result = EmitFromInt(*this, Result, T, ValueType);
+ return RValue::get(Result);
+ }
+
+ case Builtin::BI__sync_bool_compare_and_swap_1:
+ case Builtin::BI__sync_bool_compare_and_swap_2:
+ case Builtin::BI__sync_bool_compare_and_swap_4:
+ case Builtin::BI__sync_bool_compare_and_swap_8:
+ case Builtin::BI__sync_bool_compare_and_swap_16: {
+ QualType T = E->getArg(1)->getType();
+ llvm::Value *DestPtr = EmitScalarExpr(E->getArg(0));
+ unsigned AddrSpace =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+
+ const llvm::IntegerType *IntType =
+ llvm::IntegerType::get(getLLVMContext(),
+ getContext().getTypeSize(T));
+ const llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace);
+ const llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType };
+ Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap,
+ IntrinsicTypes, 2);
+
+ Value *Args[3];
+ Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType);
+ Args[1] = EmitToInt(*this, EmitScalarExpr(E->getArg(1)), T, IntType);
+ Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType);
+
+ Value *OldVal = Args[1];
+ Value *PrevVal = EmitCallWithBarrier(*this, AtomF, Args, Args + 3);
+ Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
+ // zext bool to int.
+ Result = Builder.CreateZExt(Result, ConvertType(E->getType()));
+ return RValue::get(Result);
+ }
+
+ case Builtin::BI__sync_lock_test_and_set_1:
+ case Builtin::BI__sync_lock_test_and_set_2:
+ case Builtin::BI__sync_lock_test_and_set_4:
+ case Builtin::BI__sync_lock_test_and_set_8:
+ case Builtin::BI__sync_lock_test_and_set_16:
+ return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
+
+ case Builtin::BI__sync_lock_release_1:
+ case Builtin::BI__sync_lock_release_2:
+ case Builtin::BI__sync_lock_release_4:
+ case Builtin::BI__sync_lock_release_8:
+ case Builtin::BI__sync_lock_release_16: {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ const llvm::Type *ElTy =
+ cast<llvm::PointerType>(Ptr->getType())->getElementType();
+ llvm::StoreInst *Store =
+ Builder.CreateStore(llvm::Constant::getNullValue(ElTy), Ptr);
+ Store->setVolatile(true);
+ return RValue::get(0);
+ }
+
+ case Builtin::BI__sync_synchronize: {
+ // We assume like gcc appears to, that this only applies to cached memory.
+ EmitMemoryBarrier(*this, true, true, true, true, false);
+ return RValue::get(0);
+ }
+
+ case Builtin::BI__builtin_llvm_memory_barrier: {
+ Value *C[5] = {
+ EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)),
+ EmitScalarExpr(E->getArg(3)),
+ EmitScalarExpr(E->getArg(4))
+ };
+ Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5);
+ return RValue::get(0);
+ }
+
+ // Library functions with special handling.
+ case Builtin::BIsqrt:
+ case Builtin::BIsqrtf:
+ case Builtin::BIsqrtl: {
+ // TODO: there is currently no set of optimizer flags
+ // sufficient for us to rewrite sqrt to @llvm.sqrt.
+ // -fmath-errno=0 is not good enough; we need finiteness.
+ // We could probably precondition the call with an ult
+ // against 0, but is that worth the complexity?
+ break;
+ }
+
+ case Builtin::BIpow:
+ case Builtin::BIpowf:
+ case Builtin::BIpowl: {
+ // Rewrite sqrt to intrinsic if allowed.
+ if (!FD->hasAttr<ConstAttr>())
+ break;
+ Value *Base = EmitScalarExpr(E->getArg(0));
+ Value *Exponent = EmitScalarExpr(E->getArg(1));
+ const llvm::Type *ArgType = Base->getType();
+ Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1);
+ return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp"));
+ }
+
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl: {
+ LLVMContext &C = CGM.getLLVMContext();
+
+ Value *Arg = EmitScalarExpr(E->getArg(0));
+ const llvm::Type *ArgTy = Arg->getType();
+ if (ArgTy->isPPC_FP128Ty())
+ break; // FIXME: I'm not sure what the right implementation is here.
+ int ArgWidth = ArgTy->getPrimitiveSizeInBits();
+ const llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth);
+ Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy);
+ Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy);
+ Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp);
+ return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
+ }
+ }
+
+ // If this is an alias for a libm function (e.g. __builtin_sin) turn it into
+ // that function.
+ if (getContext().BuiltinInfo.isLibFunction(BuiltinID) ||
+ getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return EmitCall(E->getCallee()->getType(),
+ CGM.getBuiltinLibFunction(FD, BuiltinID),
+ ReturnValueSlot(),
+ E->arg_begin(), E->arg_end());
+
+ // See if we have a target specific intrinsic.
+ const char *Name = getContext().BuiltinInfo.GetName(BuiltinID);
+ Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
+ if (const char *Prefix =
+ llvm::Triple::getArchTypePrefix(Target.getTriple().getArch()))
+ IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name);
+
+ if (IntrinsicID != Intrinsic::not_intrinsic) {
+ SmallVector<Value*, 16> Args;
+
+ // Find out if any arguments are required to be integer constant
+ // expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ assert(Error == ASTContext::GE_None && "Should not codegen an error");
+
+ Function *F = CGM.getIntrinsic(IntrinsicID);
+ const llvm::FunctionType *FTy = F->getFunctionType();
+
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+ Value *ArgValue;
+ // If this is a normal argument, just emit it as a scalar.
+ if ((ICEArguments & (1 << i)) == 0) {
+ ArgValue = EmitScalarExpr(E->getArg(i));
+ } else {
+ // If this is required to be a constant, constant fold it so that we
+ // know that the generated intrinsic gets a ConstantInt.
+ llvm::APSInt Result;
+ bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result,getContext());
+ assert(IsConst && "Constant arg isn't actually constant?");
+ (void)IsConst;
+ ArgValue = llvm::ConstantInt::get(getLLVMContext(), Result);
+ }
+
+ // If the intrinsic arg type is different from the builtin arg type
+ // we need to do a bit cast.
+ const llvm::Type *PTy = FTy->getParamType(i);
+ if (PTy != ArgValue->getType()) {
+ assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
+ "Must be able to losslessly bit cast to param");
+ ArgValue = Builder.CreateBitCast(ArgValue, PTy);
+ }
+
+ Args.push_back(ArgValue);
+ }
+
+ Value *V = Builder.CreateCall(F, Args.data(), Args.data() + Args.size());
+ QualType BuiltinRetType = E->getType();
+
+ const llvm::Type *RetTy = llvm::Type::getVoidTy(getLLVMContext());
+ if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType);
+
+ if (RetTy != V->getType()) {
+ assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
+ "Must be able to losslessly bit cast result type");
+ V = Builder.CreateBitCast(V, RetTy);
+ }
+
+ return RValue::get(V);
+ }
+
+ // See if we have a target specific builtin that needs to be lowered.
+ if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E))
+ return RValue::get(V);
+
+ ErrorUnsupported(E, "builtin function");
+
+ // Unknown builtin, for now just dump it out and return undef.
+ if (hasAggregateLLVMType(E->getType()))
+ return RValue::getAggregate(CreateMemTemp(E->getType()));
+ return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
+}
+
+Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (Target.getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return EmitARMBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return EmitX86BuiltinExpr(BuiltinID, E);
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ return EmitPPCBuiltinExpr(BuiltinID, E);
+ default:
+ return 0;
+ }
+}
+
+static const llvm::VectorType *GetNeonType(LLVMContext &C, unsigned type,
+ bool q) {
+ switch (type) {
+ default: break;
+ case 0:
+ case 5: return llvm::VectorType::get(llvm::Type::getInt8Ty(C), 8 << (int)q);
+ case 6:
+ case 7:
+ case 1: return llvm::VectorType::get(llvm::Type::getInt16Ty(C),4 << (int)q);
+ case 2: return llvm::VectorType::get(llvm::Type::getInt32Ty(C),2 << (int)q);
+ case 3: return llvm::VectorType::get(llvm::Type::getInt64Ty(C),1 << (int)q);
+ case 4: return llvm::VectorType::get(llvm::Type::getFloatTy(C),2 << (int)q);
+ };
+ return 0;
+}
+
+Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) {
+ unsigned nElts = cast<llvm::VectorType>(V->getType())->getNumElements();
+ SmallVector<Constant*, 16> Indices(nElts, C);
+ Value* SV = llvm::ConstantVector::get(Indices);
+ return Builder.CreateShuffleVector(V, V, SV, "lane");
+}
+
+Value *CodeGenFunction::EmitNeonCall(Function *F, SmallVectorImpl<Value*> &Ops,
+ const char *name,
+ unsigned shift, bool rightshift) {
+ unsigned j = 0;
+ for (Function::const_arg_iterator ai = F->arg_begin(), ae = F->arg_end();
+ ai != ae; ++ai, ++j)
+ if (shift > 0 && shift == j)
+ Ops[j] = EmitNeonShiftVector(Ops[j], ai->getType(), rightshift);
+ else
+ Ops[j] = Builder.CreateBitCast(Ops[j], ai->getType(), name);
+
+ return Builder.CreateCall(F, Ops.begin(), Ops.end(), name);
+}
+
+Value *CodeGenFunction::EmitNeonShiftVector(Value *V, const llvm::Type *Ty,
+ bool neg) {
+ ConstantInt *CI = cast<ConstantInt>(V);
+ int SV = CI->getSExtValue();
+
+ const llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
+ llvm::Constant *C = ConstantInt::get(VTy->getElementType(), neg ? -SV : SV);
+ SmallVector<llvm::Constant*, 16> CV(VTy->getNumElements(), C);
+ return llvm::ConstantVector::get(CV);
+}
+
+/// GetPointeeAlignment - Given an expression with a pointer type, find the
+/// alignment of the type referenced by the pointer. Skip over implicit
+/// casts.
+static Value *GetPointeeAlignment(CodeGenFunction &CGF, const Expr *Addr) {
+ unsigned Align = 1;
+ // Check if the type is a pointer. The implicit cast operand might not be.
+ while (Addr->getType()->isPointerType()) {
+ QualType PtTy = Addr->getType()->getPointeeType();
+ unsigned NewA = CGF.getContext().getTypeAlignInChars(PtTy).getQuantity();
+ if (NewA > Align)
+ Align = NewA;
+
+ // If the address is an implicit cast, repeat with the cast operand.
+ if (const ImplicitCastExpr *CastAddr = dyn_cast<ImplicitCastExpr>(Addr)) {
+ Addr = CastAddr->getSubExpr();
+ continue;
+ }
+ break;
+ }
+ return llvm::ConstantInt::get(CGF.Int32Ty, Align);
+}
+
+Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ if (BuiltinID == ARM::BI__clear_cache) {
+ const FunctionDecl *FD = E->getDirectCallee();
+ Value *a = EmitScalarExpr(E->getArg(0));
+ Value *b = EmitScalarExpr(E->getArg(1));
+ const llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
+ const llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
+ llvm::StringRef Name = FD->getName();
+ return Builder.CreateCall2(CGM.CreateRuntimeFunction(FTy, Name),
+ a, b);
+ }
+
+ llvm::SmallVector<Value*, 4> Ops;
+ for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++)
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+
+ llvm::APSInt Result;
+ const Expr *Arg = E->getArg(E->getNumArgs()-1);
+ if (!Arg->isIntegerConstantExpr(Result, getContext()))
+ return 0;
+
+ if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f ||
+ BuiltinID == ARM::BI__builtin_arm_vcvtr_d) {
+ // Determine the overloaded type of this builtin.
+ const llvm::Type *Ty;
+ if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f)
+ Ty = llvm::Type::getFloatTy(getLLVMContext());
+ else
+ Ty = llvm::Type::getDoubleTy(getLLVMContext());
+
+ // Determine whether this is an unsigned conversion or not.
+ bool usgn = Result.getZExtValue() == 1;
+ unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr;
+
+ // Call the appropriate intrinsic.
+ Function *F = CGM.getIntrinsic(Int, &Ty, 1);
+ return Builder.CreateCall(F, Ops.begin(), Ops.end(), "vcvtr");
+ }
+
+ // Determine the type of this overloaded NEON intrinsic.
+ unsigned type = Result.getZExtValue();
+ bool usgn = type & 0x08;
+ bool quad = type & 0x10;
+ bool poly = (type & 0x7) == 5 || (type & 0x7) == 6;
+ (void)poly; // Only used in assert()s.
+ bool rightShift = false;
+
+ const llvm::VectorType *VTy = GetNeonType(getLLVMContext(), type & 0x7, quad);
+ const llvm::Type *Ty = VTy;
+ if (!Ty)
+ return 0;
+
+ unsigned Int;
+ switch (BuiltinID) {
+ default: return 0;
+ case ARM::BI__builtin_neon_vabd_v:
+ case ARM::BI__builtin_neon_vabdq_v:
+ Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vabd");
+ case ARM::BI__builtin_neon_vabs_v:
+ case ARM::BI__builtin_neon_vabsq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vabs, &Ty, 1),
+ Ops, "vabs");
+ case ARM::BI__builtin_neon_vaddhn_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vaddhn, &Ty, 1),
+ Ops, "vaddhn");
+ case ARM::BI__builtin_neon_vcale_v:
+ std::swap(Ops[0], Ops[1]);
+ case ARM::BI__builtin_neon_vcage_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacged);
+ return EmitNeonCall(F, Ops, "vcage");
+ }
+ case ARM::BI__builtin_neon_vcaleq_v:
+ std::swap(Ops[0], Ops[1]);
+ case ARM::BI__builtin_neon_vcageq_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgeq);
+ return EmitNeonCall(F, Ops, "vcage");
+ }
+ case ARM::BI__builtin_neon_vcalt_v:
+ std::swap(Ops[0], Ops[1]);
+ case ARM::BI__builtin_neon_vcagt_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtd);
+ return EmitNeonCall(F, Ops, "vcagt");
+ }
+ case ARM::BI__builtin_neon_vcaltq_v:
+ std::swap(Ops[0], Ops[1]);
+ case ARM::BI__builtin_neon_vcagtq_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vacgtq);
+ return EmitNeonCall(F, Ops, "vcagt");
+ }
+ case ARM::BI__builtin_neon_vcls_v:
+ case ARM::BI__builtin_neon_vclsq_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcls, &Ty, 1);
+ return EmitNeonCall(F, Ops, "vcls");
+ }
+ case ARM::BI__builtin_neon_vclz_v:
+ case ARM::BI__builtin_neon_vclzq_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vclz, &Ty, 1);
+ return EmitNeonCall(F, Ops, "vclz");
+ }
+ case ARM::BI__builtin_neon_vcnt_v:
+ case ARM::BI__builtin_neon_vcntq_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcnt, &Ty, 1);
+ return EmitNeonCall(F, Ops, "vcnt");
+ }
+ case ARM::BI__builtin_neon_vcvt_f16_v: {
+ assert((type & 0x7) == 7 && !quad && "unexpected vcvt_f16_v builtin");
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvtfp2hf);
+ return EmitNeonCall(F, Ops, "vcvt");
+ }
+ case ARM::BI__builtin_neon_vcvt_f32_f16: {
+ assert((type & 0x7) == 7 && !quad && "unexpected vcvt_f32_f16 builtin");
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vcvthf2fp);
+ return EmitNeonCall(F, Ops, "vcvt");
+ }
+ case ARM::BI__builtin_neon_vcvt_f32_v:
+ case ARM::BI__builtin_neon_vcvtq_f32_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ty = GetNeonType(getLLVMContext(), 4, quad);
+ return usgn ? Builder.CreateUIToFP(Ops[0], Ty, "vcvt")
+ : Builder.CreateSIToFP(Ops[0], Ty, "vcvt");
+ }
+ case ARM::BI__builtin_neon_vcvt_s32_v:
+ case ARM::BI__builtin_neon_vcvt_u32_v:
+ case ARM::BI__builtin_neon_vcvtq_s32_v:
+ case ARM::BI__builtin_neon_vcvtq_u32_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetNeonType(getLLVMContext(), 4, quad));
+ return usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
+ : Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
+ }
+ case ARM::BI__builtin_neon_vcvt_n_f32_v:
+ case ARM::BI__builtin_neon_vcvtq_n_f32_v: {
+ const llvm::Type *Tys[2] = { GetNeonType(getLLVMContext(), 4, quad), Ty };
+ Int = usgn ? Intrinsic::arm_neon_vcvtfxu2fp : Intrinsic::arm_neon_vcvtfxs2fp;
+ Function *F = CGM.getIntrinsic(Int, Tys, 2);
+ return EmitNeonCall(F, Ops, "vcvt_n");
+ }
+ case ARM::BI__builtin_neon_vcvt_n_s32_v:
+ case ARM::BI__builtin_neon_vcvt_n_u32_v:
+ case ARM::BI__builtin_neon_vcvtq_n_s32_v:
+ case ARM::BI__builtin_neon_vcvtq_n_u32_v: {
+ const llvm::Type *Tys[2] = { Ty, GetNeonType(getLLVMContext(), 4, quad) };
+ Int = usgn ? Intrinsic::arm_neon_vcvtfp2fxu : Intrinsic::arm_neon_vcvtfp2fxs;
+ Function *F = CGM.getIntrinsic(Int, Tys, 2);
+ return EmitNeonCall(F, Ops, "vcvt_n");
+ }
+ case ARM::BI__builtin_neon_vext_v:
+ case ARM::BI__builtin_neon_vextq_v: {
+ int CV = cast<ConstantInt>(Ops[2])->getSExtValue();
+ SmallVector<Constant*, 16> Indices;
+ for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
+ Indices.push_back(ConstantInt::get(Int32Ty, i+CV));
+
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Value *SV = llvm::ConstantVector::get(Indices);
+ return Builder.CreateShuffleVector(Ops[0], Ops[1], SV, "vext");
+ }
+ case ARM::BI__builtin_neon_vget_lane_i8:
+ case ARM::BI__builtin_neon_vget_lane_i16:
+ case ARM::BI__builtin_neon_vget_lane_i32:
+ case ARM::BI__builtin_neon_vget_lane_i64:
+ case ARM::BI__builtin_neon_vget_lane_f32:
+ case ARM::BI__builtin_neon_vgetq_lane_i8:
+ case ARM::BI__builtin_neon_vgetq_lane_i16:
+ case ARM::BI__builtin_neon_vgetq_lane_i32:
+ case ARM::BI__builtin_neon_vgetq_lane_i64:
+ case ARM::BI__builtin_neon_vgetq_lane_f32:
+ return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
+ "vget_lane");
+ case ARM::BI__builtin_neon_vhadd_v:
+ case ARM::BI__builtin_neon_vhaddq_v:
+ Int = usgn ? Intrinsic::arm_neon_vhaddu : Intrinsic::arm_neon_vhadds;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vhadd");
+ case ARM::BI__builtin_neon_vhsub_v:
+ case ARM::BI__builtin_neon_vhsubq_v:
+ Int = usgn ? Intrinsic::arm_neon_vhsubu : Intrinsic::arm_neon_vhsubs;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vhsub");
+ case ARM::BI__builtin_neon_vld1_v:
+ case ARM::BI__builtin_neon_vld1q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vld1, &Ty, 1),
+ Ops, "vld1");
+ case ARM::BI__builtin_neon_vld1_lane_v:
+ case ARM::BI__builtin_neon_vld1q_lane_v:
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ty = llvm::PointerType::getUnqual(VTy->getElementType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[0] = Builder.CreateLoad(Ops[0]);
+ return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vld1_lane");
+ case ARM::BI__builtin_neon_vld1_dup_v:
+ case ARM::BI__builtin_neon_vld1q_dup_v: {
+ Value *V = UndefValue::get(Ty);
+ Ty = llvm::PointerType::getUnqual(VTy->getElementType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[0] = Builder.CreateLoad(Ops[0]);
+ llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Ops[0] = Builder.CreateInsertElement(V, Ops[0], CI);
+ return EmitNeonSplat(Ops[0], CI);
+ }
+ case ARM::BI__builtin_neon_vld2_v:
+ case ARM::BI__builtin_neon_vld2q_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2, &Ty, 1);
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld2");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld3_v:
+ case ARM::BI__builtin_neon_vld3q_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld3, &Ty, 1);
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld3");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld4_v:
+ case ARM::BI__builtin_neon_vld4q_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld4, &Ty, 1);
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld4");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld2_lane_v:
+ case ARM::BI__builtin_neon_vld2q_lane_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2lane, &Ty, 1);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
+ Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld2_lane");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld3_lane_v:
+ case ARM::BI__builtin_neon_vld3q_lane_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld3lane, &Ty, 1);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
+ Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
+ Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld3_lane");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld4_lane_v:
+ case ARM::BI__builtin_neon_vld4q_lane_v: {
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld4lane, &Ty, 1);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
+ Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
+ Ops[5] = Builder.CreateBitCast(Ops[5], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
+ Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld3_lane");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vld2_dup_v:
+ case ARM::BI__builtin_neon_vld3_dup_v:
+ case ARM::BI__builtin_neon_vld4_dup_v: {
+ // Handle 64-bit elements as a special-case. There is no "dup" needed.
+ if (VTy->getElementType()->getPrimitiveSizeInBits() == 64) {
+ switch (BuiltinID) {
+ case ARM::BI__builtin_neon_vld2_dup_v:
+ Int = Intrinsic::arm_neon_vld2;
+ break;
+ case ARM::BI__builtin_neon_vld3_dup_v:
+ Int = Intrinsic::arm_neon_vld2;
+ break;
+ case ARM::BI__builtin_neon_vld4_dup_v:
+ Int = Intrinsic::arm_neon_vld2;
+ break;
+ default: assert(0 && "unknown vld_dup intrinsic?");
+ }
+ Function *F = CGM.getIntrinsic(Int, &Ty, 1);
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld_dup");
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ switch (BuiltinID) {
+ case ARM::BI__builtin_neon_vld2_dup_v:
+ Int = Intrinsic::arm_neon_vld2lane;
+ break;
+ case ARM::BI__builtin_neon_vld3_dup_v:
+ Int = Intrinsic::arm_neon_vld2lane;
+ break;
+ case ARM::BI__builtin_neon_vld4_dup_v:
+ Int = Intrinsic::arm_neon_vld2lane;
+ break;
+ default: assert(0 && "unknown vld_dup intrinsic?");
+ }
+ Function *F = CGM.getIntrinsic(Int, &Ty, 1);
+ const llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType());
+
+ SmallVector<Value*, 6> Args;
+ Args.push_back(Ops[1]);
+ Args.append(STy->getNumElements(), UndefValue::get(Ty));
+
+ llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
+ Args.push_back(CI);
+ Args.push_back(GetPointeeAlignment(*this, E->getArg(1)));
+
+ Ops[1] = Builder.CreateCall(F, Args.begin(), Args.end(), "vld_dup");
+ // splat lane 0 to all elts in each vector of the result.
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ Value *Val = Builder.CreateExtractValue(Ops[1], i);
+ Value *Elt = Builder.CreateBitCast(Val, Ty);
+ Elt = EmitNeonSplat(Elt, CI);
+ Elt = Builder.CreateBitCast(Elt, Val->getType());
+ Ops[1] = Builder.CreateInsertValue(Ops[1], Elt, i);
+ }
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case ARM::BI__builtin_neon_vmax_v:
+ case ARM::BI__builtin_neon_vmaxq_v:
+ Int = usgn ? Intrinsic::arm_neon_vmaxu : Intrinsic::arm_neon_vmaxs;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmax");
+ case ARM::BI__builtin_neon_vmin_v:
+ case ARM::BI__builtin_neon_vminq_v:
+ Int = usgn ? Intrinsic::arm_neon_vminu : Intrinsic::arm_neon_vmins;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmin");
+ case ARM::BI__builtin_neon_vmovl_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
+ if (usgn)
+ return Builder.CreateZExt(Ops[0], Ty, "vmovl");
+ return Builder.CreateSExt(Ops[0], Ty, "vmovl");
+ }
+ case ARM::BI__builtin_neon_vmovn_v: {
+ const llvm::Type *QTy = llvm::VectorType::getExtendedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], QTy);
+ return Builder.CreateTrunc(Ops[0], Ty, "vmovn");
+ }
+ case ARM::BI__builtin_neon_vmul_v:
+ case ARM::BI__builtin_neon_vmulq_v:
+ assert(poly && "vmul builtin only supported for polynomial types");
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmulp, &Ty, 1),
+ Ops, "vmul");
+ case ARM::BI__builtin_neon_vmull_v:
+ assert(poly && "vmull builtin only supported for polynomial types");
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmullp, &Ty, 1),
+ Ops, "vmull");
+ case ARM::BI__builtin_neon_vpadal_v:
+ case ARM::BI__builtin_neon_vpadalq_v: {
+ Int = usgn ? Intrinsic::arm_neon_vpadalu : Intrinsic::arm_neon_vpadals;
+ // The source operand type has twice as many elements of half the size.
+ unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+ const llvm::Type *EltTy =
+ llvm::IntegerType::get(getLLVMContext(), EltBits / 2);
+ const llvm::Type *NarrowTy =
+ llvm::VectorType::get(EltTy, VTy->getNumElements() * 2);
+ const llvm::Type *Tys[2] = { Ty, NarrowTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys, 2), Ops, "vpadal");
+ }
+ case ARM::BI__builtin_neon_vpadd_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vpadd, &Ty, 1),
+ Ops, "vpadd");
+ case ARM::BI__builtin_neon_vpaddl_v:
+ case ARM::BI__builtin_neon_vpaddlq_v: {
+ Int = usgn ? Intrinsic::arm_neon_vpaddlu : Intrinsic::arm_neon_vpaddls;
+ // The source operand type has twice as many elements of half the size.
+ unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+ const llvm::Type *EltTy = llvm::IntegerType::get(getLLVMContext(), EltBits / 2);
+ const llvm::Type *NarrowTy =
+ llvm::VectorType::get(EltTy, VTy->getNumElements() * 2);
+ const llvm::Type *Tys[2] = { Ty, NarrowTy };
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys, 2), Ops, "vpaddl");
+ }
+ case ARM::BI__builtin_neon_vpmax_v:
+ Int = usgn ? Intrinsic::arm_neon_vpmaxu : Intrinsic::arm_neon_vpmaxs;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vpmax");
+ case ARM::BI__builtin_neon_vpmin_v:
+ Int = usgn ? Intrinsic::arm_neon_vpminu : Intrinsic::arm_neon_vpmins;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vpmin");
+ case ARM::BI__builtin_neon_vqabs_v:
+ case ARM::BI__builtin_neon_vqabsq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqabs, &Ty, 1),
+ Ops, "vqabs");
+ case ARM::BI__builtin_neon_vqadd_v:
+ case ARM::BI__builtin_neon_vqaddq_v:
+ Int = usgn ? Intrinsic::arm_neon_vqaddu : Intrinsic::arm_neon_vqadds;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqadd");
+ case ARM::BI__builtin_neon_vqdmlal_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmlal, &Ty, 1),
+ Ops, "vqdmlal");
+ case ARM::BI__builtin_neon_vqdmlsl_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmlsl, &Ty, 1),
+ Ops, "vqdmlsl");
+ case ARM::BI__builtin_neon_vqdmulh_v:
+ case ARM::BI__builtin_neon_vqdmulhq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmulh, &Ty, 1),
+ Ops, "vqdmulh");
+ case ARM::BI__builtin_neon_vqdmull_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqdmull, &Ty, 1),
+ Ops, "vqdmull");
+ case ARM::BI__builtin_neon_vqmovn_v:
+ Int = usgn ? Intrinsic::arm_neon_vqmovnu : Intrinsic::arm_neon_vqmovns;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqmovn");
+ case ARM::BI__builtin_neon_vqmovun_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqmovnsu, &Ty, 1),
+ Ops, "vqdmull");
+ case ARM::BI__builtin_neon_vqneg_v:
+ case ARM::BI__builtin_neon_vqnegq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqneg, &Ty, 1),
+ Ops, "vqneg");
+ case ARM::BI__builtin_neon_vqrdmulh_v:
+ case ARM::BI__builtin_neon_vqrdmulhq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrdmulh, &Ty, 1),
+ Ops, "vqrdmulh");
+ case ARM::BI__builtin_neon_vqrshl_v:
+ case ARM::BI__builtin_neon_vqrshlq_v:
+ Int = usgn ? Intrinsic::arm_neon_vqrshiftu : Intrinsic::arm_neon_vqrshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqrshl");
+ case ARM::BI__builtin_neon_vqrshrn_n_v:
+ Int = usgn ? Intrinsic::arm_neon_vqrshiftnu : Intrinsic::arm_neon_vqrshiftns;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqrshrn_n",
+ 1, true);
+ case ARM::BI__builtin_neon_vqrshrun_n_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqrshiftnsu, &Ty, 1),
+ Ops, "vqrshrun_n", 1, true);
+ case ARM::BI__builtin_neon_vqshl_v:
+ case ARM::BI__builtin_neon_vqshlq_v:
+ Int = usgn ? Intrinsic::arm_neon_vqshiftu : Intrinsic::arm_neon_vqshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqshl");
+ case ARM::BI__builtin_neon_vqshl_n_v:
+ case ARM::BI__builtin_neon_vqshlq_n_v:
+ Int = usgn ? Intrinsic::arm_neon_vqshiftu : Intrinsic::arm_neon_vqshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqshl_n",
+ 1, false);
+ case ARM::BI__builtin_neon_vqshlu_n_v:
+ case ARM::BI__builtin_neon_vqshluq_n_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftsu, &Ty, 1),
+ Ops, "vqshlu", 1, false);
+ case ARM::BI__builtin_neon_vqshrn_n_v:
+ Int = usgn ? Intrinsic::arm_neon_vqshiftnu : Intrinsic::arm_neon_vqshiftns;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqshrn_n",
+ 1, true);
+ case ARM::BI__builtin_neon_vqshrun_n_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vqshiftnsu, &Ty, 1),
+ Ops, "vqshrun_n", 1, true);
+ case ARM::BI__builtin_neon_vqsub_v:
+ case ARM::BI__builtin_neon_vqsubq_v:
+ Int = usgn ? Intrinsic::arm_neon_vqsubu : Intrinsic::arm_neon_vqsubs;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vqsub");
+ case ARM::BI__builtin_neon_vraddhn_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vraddhn, &Ty, 1),
+ Ops, "vraddhn");
+ case ARM::BI__builtin_neon_vrecpe_v:
+ case ARM::BI__builtin_neon_vrecpeq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecpe, &Ty, 1),
+ Ops, "vrecpe");
+ case ARM::BI__builtin_neon_vrecps_v:
+ case ARM::BI__builtin_neon_vrecpsq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrecps, &Ty, 1),
+ Ops, "vrecps");
+ case ARM::BI__builtin_neon_vrhadd_v:
+ case ARM::BI__builtin_neon_vrhaddq_v:
+ Int = usgn ? Intrinsic::arm_neon_vrhaddu : Intrinsic::arm_neon_vrhadds;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vrhadd");
+ case ARM::BI__builtin_neon_vrshl_v:
+ case ARM::BI__builtin_neon_vrshlq_v:
+ Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vrshl");
+ case ARM::BI__builtin_neon_vrshrn_n_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrshiftn, &Ty, 1),
+ Ops, "vrshrn_n", 1, true);
+ case ARM::BI__builtin_neon_vrshr_n_v:
+ case ARM::BI__builtin_neon_vrshrq_n_v:
+ Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vrshr_n", 1, true);
+ case ARM::BI__builtin_neon_vrsqrte_v:
+ case ARM::BI__builtin_neon_vrsqrteq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsqrte, &Ty, 1),
+ Ops, "vrsqrte");
+ case ARM::BI__builtin_neon_vrsqrts_v:
+ case ARM::BI__builtin_neon_vrsqrtsq_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsqrts, &Ty, 1),
+ Ops, "vrsqrts");
+ case ARM::BI__builtin_neon_vrsra_n_v:
+ case ARM::BI__builtin_neon_vrsraq_n_v:
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[2] = EmitNeonShiftVector(Ops[2], Ty, true);
+ Int = usgn ? Intrinsic::arm_neon_vrshiftu : Intrinsic::arm_neon_vrshifts;
+ Ops[1] = Builder.CreateCall2(CGM.getIntrinsic(Int, &Ty, 1), Ops[1], Ops[2]);
+ return Builder.CreateAdd(Ops[0], Ops[1], "vrsra_n");
+ case ARM::BI__builtin_neon_vrsubhn_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vrsubhn, &Ty, 1),
+ Ops, "vrsubhn");
+ case ARM::BI__builtin_neon_vset_lane_i8:
+ case ARM::BI__builtin_neon_vset_lane_i16:
+ case ARM::BI__builtin_neon_vset_lane_i32:
+ case ARM::BI__builtin_neon_vset_lane_i64:
+ case ARM::BI__builtin_neon_vset_lane_f32:
+ case ARM::BI__builtin_neon_vsetq_lane_i8:
+ case ARM::BI__builtin_neon_vsetq_lane_i16:
+ case ARM::BI__builtin_neon_vsetq_lane_i32:
+ case ARM::BI__builtin_neon_vsetq_lane_i64:
+ case ARM::BI__builtin_neon_vsetq_lane_f32:
+ Ops.push_back(EmitScalarExpr(E->getArg(2)));
+ return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
+ case ARM::BI__builtin_neon_vshl_v:
+ case ARM::BI__builtin_neon_vshlq_v:
+ Int = usgn ? Intrinsic::arm_neon_vshiftu : Intrinsic::arm_neon_vshifts;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vshl");
+ case ARM::BI__builtin_neon_vshll_n_v:
+ Int = usgn ? Intrinsic::arm_neon_vshiftlu : Intrinsic::arm_neon_vshiftls;
+ return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vshll", 1);
+ case ARM::BI__builtin_neon_vshl_n_v:
+ case ARM::BI__builtin_neon_vshlq_n_v:
+ Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false);
+ return Builder.CreateShl(Builder.CreateBitCast(Ops[0],Ty), Ops[1], "vshl_n");
+ case ARM::BI__builtin_neon_vshrn_n_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftn, &Ty, 1),
+ Ops, "vshrn_n", 1, true);
+ case ARM::BI__builtin_neon_vshr_n_v:
+ case ARM::BI__builtin_neon_vshrq_n_v:
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false);
+ if (usgn)
+ return Builder.CreateLShr(Ops[0], Ops[1], "vshr_n");
+ else
+ return Builder.CreateAShr(Ops[0], Ops[1], "vshr_n");
+ case ARM::BI__builtin_neon_vsri_n_v:
+ case ARM::BI__builtin_neon_vsriq_n_v:
+ rightShift = true;
+ case ARM::BI__builtin_neon_vsli_n_v:
+ case ARM::BI__builtin_neon_vsliq_n_v:
+ Ops[2] = EmitNeonShiftVector(Ops[2], Ty, rightShift);
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vshiftins, &Ty, 1),
+ Ops, "vsli_n");
+ case ARM::BI__builtin_neon_vsra_n_v:
+ case ARM::BI__builtin_neon_vsraq_n_v:
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[2] = EmitNeonShiftVector(Ops[2], Ty, false);
+ if (usgn)
+ Ops[1] = Builder.CreateLShr(Ops[1], Ops[2], "vsra_n");
+ else
+ Ops[1] = Builder.CreateAShr(Ops[1], Ops[2], "vsra_n");
+ return Builder.CreateAdd(Ops[0], Ops[1]);
+ case ARM::BI__builtin_neon_vst1_v:
+ case ARM::BI__builtin_neon_vst1q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst1_lane_v:
+ case ARM::BI__builtin_neon_vst1q_lane_v:
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
+ Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
+ return Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty));
+ case ARM::BI__builtin_neon_vst2_v:
+ case ARM::BI__builtin_neon_vst2q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst2_lane_v:
+ case ARM::BI__builtin_neon_vst2q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2lane, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst3_v:
+ case ARM::BI__builtin_neon_vst3q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst3_lane_v:
+ case ARM::BI__builtin_neon_vst3q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3lane, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst4_v:
+ case ARM::BI__builtin_neon_vst4q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vst4_lane_v:
+ case ARM::BI__builtin_neon_vst4q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4lane, &Ty, 1),
+ Ops, "");
+ case ARM::BI__builtin_neon_vsubhn_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vsubhn, &Ty, 1),
+ Ops, "vsubhn");
+ case ARM::BI__builtin_neon_vtbl1_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1),
+ Ops, "vtbl1");
+ case ARM::BI__builtin_neon_vtbl2_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl2),
+ Ops, "vtbl2");
+ case ARM::BI__builtin_neon_vtbl3_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl3),
+ Ops, "vtbl3");
+ case ARM::BI__builtin_neon_vtbl4_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl4),
+ Ops, "vtbl4");
+ case ARM::BI__builtin_neon_vtbx1_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx1),
+ Ops, "vtbx1");
+ case ARM::BI__builtin_neon_vtbx2_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx2),
+ Ops, "vtbx2");
+ case ARM::BI__builtin_neon_vtbx3_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx3),
+ Ops, "vtbx3");
+ case ARM::BI__builtin_neon_vtbx4_v:
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbx4),
+ Ops, "vtbx4");
+ case ARM::BI__builtin_neon_vtst_v:
+ case ARM::BI__builtin_neon_vtstq_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]);
+ Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0],
+ ConstantAggregateZero::get(Ty));
+ return Builder.CreateSExt(Ops[0], Ty, "vtst");
+ }
+ case ARM::BI__builtin_neon_vtrn_v:
+ case ARM::BI__builtin_neon_vtrnq_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Value *SV = 0;
+
+ for (unsigned vi = 0; vi != 2; ++vi) {
+ SmallVector<Constant*, 16> Indices;
+ for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
+ Indices.push_back(ConstantInt::get(Int32Ty, i+vi));
+ Indices.push_back(ConstantInt::get(Int32Ty, i+e+vi));
+ }
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ SV = llvm::ConstantVector::get(Indices);
+ SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
+ SV = Builder.CreateStore(SV, Addr);
+ }
+ return SV;
+ }
+ case ARM::BI__builtin_neon_vuzp_v:
+ case ARM::BI__builtin_neon_vuzpq_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Value *SV = 0;
+
+ for (unsigned vi = 0; vi != 2; ++vi) {
+ SmallVector<Constant*, 16> Indices;
+ for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i)
+ Indices.push_back(ConstantInt::get(Int32Ty, 2*i+vi));
+
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ SV = llvm::ConstantVector::get(Indices);
+ SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
+ SV = Builder.CreateStore(SV, Addr);
+ }
+ return SV;
+ }
+ case ARM::BI__builtin_neon_vzip_v:
+ case ARM::BI__builtin_neon_vzipq_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
+ Value *SV = 0;
+
+ for (unsigned vi = 0; vi != 2; ++vi) {
+ SmallVector<Constant*, 16> Indices;
+ for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
+ Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
+ Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
+ }
+ Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
+ SV = llvm::ConstantVector::get(Indices);
+ SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
+ SV = Builder.CreateStore(SV, Addr);
+ }
+ return SV;
+ }
+ }
+}
+
+llvm::Value *CodeGenFunction::
+BuildVector(const llvm::SmallVectorImpl<llvm::Value*> &Ops) {
+ assert((Ops.size() & (Ops.size() - 1)) == 0 &&
+ "Not a power-of-two sized vector!");
+ bool AllConstants = true;
+ for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i)
+ AllConstants &= isa<Constant>(Ops[i]);
+
+ // If this is a constant vector, create a ConstantVector.
+ if (AllConstants) {
+ std::vector<llvm::Constant*> CstOps;
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i)
+ CstOps.push_back(cast<Constant>(Ops[i]));
+ return llvm::ConstantVector::get(CstOps);
+ }
+
+ // Otherwise, insertelement the values to build the vector.
+ Value *Result =
+ llvm::UndefValue::get(llvm::VectorType::get(Ops[0]->getType(), Ops.size()));
+
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i)
+ Result = Builder.CreateInsertElement(Result, Ops[i],
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), i));
+
+ return Result;
+}
+
+Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ llvm::SmallVector<Value*, 4> Ops;
+
+ // Find out if any arguments are required to be integer constant expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ assert(Error == ASTContext::GE_None && "Should not codegen an error");
+
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
+ // If this is a normal argument, just emit it as a scalar.
+ if ((ICEArguments & (1 << i)) == 0) {
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ continue;
+ }
+
+ // If this is required to be a constant, constant fold it so that we know
+ // that the generated intrinsic gets a ConstantInt.
+ llvm::APSInt Result;
+ bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext());
+ assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst;
+ Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result));
+ }
+
+ switch (BuiltinID) {
+ default: return 0;
+ case X86::BI__builtin_ia32_pslldi128:
+ case X86::BI__builtin_ia32_psllqi128:
+ case X86::BI__builtin_ia32_psllwi128:
+ case X86::BI__builtin_ia32_psradi128:
+ case X86::BI__builtin_ia32_psrawi128:
+ case X86::BI__builtin_ia32_psrldi128:
+ case X86::BI__builtin_ia32_psrlqi128:
+ case X86::BI__builtin_ia32_psrlwi128: {
+ Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty, "zext");
+ const llvm::Type *Ty = llvm::VectorType::get(Int64Ty, 2);
+ llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ Ops[1] = Builder.CreateInsertElement(llvm::UndefValue::get(Ty),
+ Ops[1], Zero, "insert");
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType(), "bitcast");
+ const char *name = 0;
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+
+ switch (BuiltinID) {
+ default: assert(0 && "Unsupported shift intrinsic!");
+ case X86::BI__builtin_ia32_pslldi128:
+ name = "pslldi";
+ ID = Intrinsic::x86_sse2_psll_d;
+ break;
+ case X86::BI__builtin_ia32_psllqi128:
+ name = "psllqi";
+ ID = Intrinsic::x86_sse2_psll_q;
+ break;
+ case X86::BI__builtin_ia32_psllwi128:
+ name = "psllwi";
+ ID = Intrinsic::x86_sse2_psll_w;
+ break;
+ case X86::BI__builtin_ia32_psradi128:
+ name = "psradi";
+ ID = Intrinsic::x86_sse2_psra_d;
+ break;
+ case X86::BI__builtin_ia32_psrawi128:
+ name = "psrawi";
+ ID = Intrinsic::x86_sse2_psra_w;
+ break;
+ case X86::BI__builtin_ia32_psrldi128:
+ name = "psrldi";
+ ID = Intrinsic::x86_sse2_psrl_d;
+ break;
+ case X86::BI__builtin_ia32_psrlqi128:
+ name = "psrlqi";
+ ID = Intrinsic::x86_sse2_psrl_q;
+ break;
+ case X86::BI__builtin_ia32_psrlwi128:
+ name = "psrlwi";
+ ID = Intrinsic::x86_sse2_psrl_w;
+ break;
+ }
+ llvm::Function *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name);
+ }
+ case X86::BI__builtin_ia32_vec_init_v8qi:
+ case X86::BI__builtin_ia32_vec_init_v4hi:
+ case X86::BI__builtin_ia32_vec_init_v2si:
+ return Builder.CreateBitCast(BuildVector(Ops),
+ llvm::Type::getX86_MMXTy(getLLVMContext()));
+ case X86::BI__builtin_ia32_vec_ext_v2si:
+ return Builder.CreateExtractElement(Ops[0],
+ llvm::ConstantInt::get(Ops[1]->getType(), 0));
+ case X86::BI__builtin_ia32_pslldi:
+ case X86::BI__builtin_ia32_psllqi:
+ case X86::BI__builtin_ia32_psllwi:
+ case X86::BI__builtin_ia32_psradi:
+ case X86::BI__builtin_ia32_psrawi:
+ case X86::BI__builtin_ia32_psrldi:
+ case X86::BI__builtin_ia32_psrlqi:
+ case X86::BI__builtin_ia32_psrlwi: {
+ Ops[1] = Builder.CreateZExt(Ops[1], Int64Ty, "zext");
+ const llvm::Type *Ty = llvm::VectorType::get(Int64Ty, 1);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty, "bitcast");
+ const char *name = 0;
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+
+ switch (BuiltinID) {
+ default: assert(0 && "Unsupported shift intrinsic!");
+ case X86::BI__builtin_ia32_pslldi:
+ name = "pslldi";
+ ID = Intrinsic::x86_mmx_psll_d;
+ break;
+ case X86::BI__builtin_ia32_psllqi:
+ name = "psllqi";
+ ID = Intrinsic::x86_mmx_psll_q;
+ break;
+ case X86::BI__builtin_ia32_psllwi:
+ name = "psllwi";
+ ID = Intrinsic::x86_mmx_psll_w;
+ break;
+ case X86::BI__builtin_ia32_psradi:
+ name = "psradi";
+ ID = Intrinsic::x86_mmx_psra_d;
+ break;
+ case X86::BI__builtin_ia32_psrawi:
+ name = "psrawi";
+ ID = Intrinsic::x86_mmx_psra_w;
+ break;
+ case X86::BI__builtin_ia32_psrldi:
+ name = "psrldi";
+ ID = Intrinsic::x86_mmx_psrl_d;
+ break;
+ case X86::BI__builtin_ia32_psrlqi:
+ name = "psrlqi";
+ ID = Intrinsic::x86_mmx_psrl_q;
+ break;
+ case X86::BI__builtin_ia32_psrlwi:
+ name = "psrlwi";
+ ID = Intrinsic::x86_mmx_psrl_w;
+ break;
+ }
+ llvm::Function *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name);
+ }
+ case X86::BI__builtin_ia32_cmpps: {
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpps");
+ }
+ case X86::BI__builtin_ia32_cmpss: {
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ss);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpss");
+ }
+ case X86::BI__builtin_ia32_ldmxcsr: {
+ const llvm::Type *PtrTy = Int8PtrTy;
+ Value *One = llvm::ConstantInt::get(Int32Ty, 1);
+ Value *Tmp = Builder.CreateAlloca(Int32Ty, One, "tmp");
+ Builder.CreateStore(Ops[0], Tmp);
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),
+ Builder.CreateBitCast(Tmp, PtrTy));
+ }
+ case X86::BI__builtin_ia32_stmxcsr: {
+ const llvm::Type *PtrTy = Int8PtrTy;
+ Value *One = llvm::ConstantInt::get(Int32Ty, 1);
+ Value *Tmp = Builder.CreateAlloca(Int32Ty, One, "tmp");
+ One = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),
+ Builder.CreateBitCast(Tmp, PtrTy));
+ return Builder.CreateLoad(Tmp, "stmxcsr");
+ }
+ case X86::BI__builtin_ia32_cmppd: {
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_pd);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmppd");
+ }
+ case X86::BI__builtin_ia32_cmpsd: {
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_sd);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpsd");
+ }
+ case X86::BI__builtin_ia32_storehps:
+ case X86::BI__builtin_ia32_storelps: {
+ llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty);
+ llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2);
+
+ // cast val v2i64
+ Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast");
+
+ // extract (0, 1)
+ unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1;
+ llvm::Value *Idx = llvm::ConstantInt::get(Int32Ty, Index);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract");
+
+ // cast pointer to i64 & store
+ Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
+ return Builder.CreateStore(Ops[1], Ops[0]);
+ }
+ case X86::BI__builtin_ia32_palignr: {
+ unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+
+ // If palignr is shifting the pair of input vectors less than 9 bytes,
+ // emit a shuffle instruction.
+ if (shiftVal <= 8) {
+ llvm::SmallVector<llvm::Constant*, 8> Indices;
+ for (unsigned i = 0; i != 8; ++i)
+ Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i));
+
+ Value* SV = llvm::ConstantVector::get(Indices);
+ return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
+ }
+
+ // If palignr is shifting the pair of input vectors more than 8 but less
+ // than 16 bytes, emit a logical right shift of the destination.
+ if (shiftVal < 16) {
+ // MMX has these as 1 x i64 vectors for some odd optimization reasons.
+ const llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 1);
+
+ Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Ops[1] = llvm::ConstantInt::get(VecTy, (shiftVal-8) * 8);
+
+ // create i32 constant
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_mmx_psrl_q);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + 2, "palignr");
+ }
+
+ // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
+ }
+ case X86::BI__builtin_ia32_palignr128: {
+ unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
+
+ // If palignr is shifting the pair of input vectors less than 17 bytes,
+ // emit a shuffle instruction.
+ if (shiftVal <= 16) {
+ llvm::SmallVector<llvm::Constant*, 16> Indices;
+ for (unsigned i = 0; i != 16; ++i)
+ Indices.push_back(llvm::ConstantInt::get(Int32Ty, shiftVal + i));
+
+ Value* SV = llvm::ConstantVector::get(Indices);
+ return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
+ }
+
+ // If palignr is shifting the pair of input vectors more than 16 but less
+ // than 32 bytes, emit a logical right shift of the destination.
+ if (shiftVal < 32) {
+ const llvm::Type *VecTy = llvm::VectorType::get(Int64Ty, 2);
+
+ Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
+ Ops[1] = llvm::ConstantInt::get(Int32Ty, (shiftVal-16) * 8);
+
+ // create i32 constant
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_psrl_dq);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + 2, "palignr");
+ }
+
+ // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
+ }
+ }
+}
+
+Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ llvm::SmallVector<Value*, 4> Ops;
+
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; i++)
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+
+ switch (BuiltinID) {
+ default: return 0;
+
+ // vec_ld, vec_lvsl, vec_lvsr
+ case PPC::BI__builtin_altivec_lvx:
+ case PPC::BI__builtin_altivec_lvxl:
+ case PPC::BI__builtin_altivec_lvebx:
+ case PPC::BI__builtin_altivec_lvehx:
+ case PPC::BI__builtin_altivec_lvewx:
+ case PPC::BI__builtin_altivec_lvsl:
+ case PPC::BI__builtin_altivec_lvsr:
+ {
+ Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
+
+ Ops[0] = Builder.CreateGEP(Ops[1], Ops[0], "tmp");
+ Ops.pop_back();
+
+ switch (BuiltinID) {
+ default: assert(0 && "Unsupported ld/lvsl/lvsr intrinsic!");
+ case PPC::BI__builtin_altivec_lvx:
+ ID = Intrinsic::ppc_altivec_lvx;
+ break;
+ case PPC::BI__builtin_altivec_lvxl:
+ ID = Intrinsic::ppc_altivec_lvxl;
+ break;
+ case PPC::BI__builtin_altivec_lvebx:
+ ID = Intrinsic::ppc_altivec_lvebx;
+ break;
+ case PPC::BI__builtin_altivec_lvehx:
+ ID = Intrinsic::ppc_altivec_lvehx;
+ break;
+ case PPC::BI__builtin_altivec_lvewx:
+ ID = Intrinsic::ppc_altivec_lvewx;
+ break;
+ case PPC::BI__builtin_altivec_lvsl:
+ ID = Intrinsic::ppc_altivec_lvsl;
+ break;
+ case PPC::BI__builtin_altivec_lvsr:
+ ID = Intrinsic::ppc_altivec_lvsr;
+ break;
+ }
+ llvm::Function *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "");
+ }
+
+ // vec_st
+ case PPC::BI__builtin_altivec_stvx:
+ case PPC::BI__builtin_altivec_stvxl:
+ case PPC::BI__builtin_altivec_stvebx:
+ case PPC::BI__builtin_altivec_stvehx:
+ case PPC::BI__builtin_altivec_stvewx:
+ {
+ Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy);
+ Ops[1] = Builder.CreateGEP(Ops[2], Ops[1], "tmp");
+ Ops.pop_back();
+
+ switch (BuiltinID) {
+ default: assert(0 && "Unsupported st intrinsic!");
+ case PPC::BI__builtin_altivec_stvx:
+ ID = Intrinsic::ppc_altivec_stvx;
+ break;
+ case PPC::BI__builtin_altivec_stvxl:
+ ID = Intrinsic::ppc_altivec_stvxl;
+ break;
+ case PPC::BI__builtin_altivec_stvebx:
+ ID = Intrinsic::ppc_altivec_stvebx;
+ break;
+ case PPC::BI__builtin_altivec_stvehx:
+ ID = Intrinsic::ppc_altivec_stvehx;
+ break;
+ case PPC::BI__builtin_altivec_stvewx:
+ ID = Intrinsic::ppc_altivec_stvewx;
+ break;
+ }
+ llvm::Function *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "");
+ }
+ }
+ return 0;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
new file mode 100644
index 0000000..7ffc6e7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
@@ -0,0 +1,390 @@
+//===--- CGCXX.cpp - Emit LLVM Code for declarations ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation.
+//
+//===----------------------------------------------------------------------===//
+
+// We might split this into multiple files if it gets too unwieldy
+
+#include "CGCXXABI.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace CodeGen;
+
+/// Determines whether the given function has a trivial body that does
+/// not require any specific codegen.
+static bool HasTrivialBody(const FunctionDecl *FD) {
+ Stmt *S = FD->getBody();
+ if (!S)
+ return true;
+ if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
+ return true;
+ return false;
+}
+
+/// Try to emit a base destructor as an alias to its primary
+/// base-class destructor.
+bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
+ if (!getCodeGenOpts().CXXCtorDtorAliases)
+ return true;
+
+ // If the destructor doesn't have a trivial body, we have to emit it
+ // separately.
+ if (!HasTrivialBody(D))
+ return true;
+
+ const CXXRecordDecl *Class = D->getParent();
+
+ // If we need to manipulate a VTT parameter, give up.
+ if (Class->getNumVBases()) {
+ // Extra Credit: passing extra parameters is perfectly safe
+ // in many calling conventions, so only bail out if the ctor's
+ // calling convention is nonstandard.
+ return true;
+ }
+
+ // If any field has a non-trivial destructor, we have to emit the
+ // destructor separately.
+ for (CXXRecordDecl::field_iterator I = Class->field_begin(),
+ E = Class->field_end(); I != E; ++I)
+ if ((*I)->getType().isDestructedType())
+ return true;
+
+ // Try to find a unique base class with a non-trivial destructor.
+ const CXXRecordDecl *UniqueBase = 0;
+ for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
+ E = Class->bases_end(); I != E; ++I) {
+
+ // We're in the base destructor, so skip virtual bases.
+ if (I->isVirtual()) continue;
+
+ // Skip base classes with trivial destructors.
+ const CXXRecordDecl *Base
+ = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ if (Base->hasTrivialDestructor()) continue;
+
+ // If we've already found a base class with a non-trivial
+ // destructor, give up.
+ if (UniqueBase) return true;
+ UniqueBase = Base;
+ }
+
+ // If we didn't find any bases with a non-trivial destructor, then
+ // the base destructor is actually effectively trivial, which can
+ // happen if it was needlessly user-defined or if there are virtual
+ // bases with non-trivial destructors.
+ if (!UniqueBase)
+ return true;
+
+ /// If we don't have a definition for the destructor yet, don't
+ /// emit. We can't emit aliases to declarations; that's just not
+ /// how aliases work.
+ const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
+ if (!BaseD->isImplicit() && !BaseD->hasBody())
+ return true;
+
+ // If the base is at a non-zero offset, give up.
+ const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
+ if (ClassLayout.getBaseClassOffsetInBits(UniqueBase) != 0)
+ return true;
+
+ return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
+ GlobalDecl(BaseD, Dtor_Base));
+}
+
+/// Try to emit a definition as a global alias for another definition.
+bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
+ GlobalDecl TargetDecl) {
+ if (!getCodeGenOpts().CXXCtorDtorAliases)
+ return true;
+
+ // The alias will use the linkage of the referrent. If we can't
+ // support aliases with that linkage, fail.
+ llvm::GlobalValue::LinkageTypes Linkage
+ = getFunctionLinkage(cast<FunctionDecl>(AliasDecl.getDecl()));
+
+ switch (Linkage) {
+ // We can definitely emit aliases to definitions with external linkage.
+ case llvm::GlobalValue::ExternalLinkage:
+ case llvm::GlobalValue::ExternalWeakLinkage:
+ break;
+
+ // Same with local linkage.
+ case llvm::GlobalValue::InternalLinkage:
+ case llvm::GlobalValue::PrivateLinkage:
+ case llvm::GlobalValue::LinkerPrivateLinkage:
+ break;
+
+ // We should try to support linkonce linkages.
+ case llvm::GlobalValue::LinkOnceAnyLinkage:
+ case llvm::GlobalValue::LinkOnceODRLinkage:
+ return true;
+
+ // Other linkages will probably never be supported.
+ default:
+ return true;
+ }
+
+ llvm::GlobalValue::LinkageTypes TargetLinkage
+ = getFunctionLinkage(cast<FunctionDecl>(TargetDecl.getDecl()));
+
+ if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
+ return true;
+
+ // Derive the type for the alias.
+ const llvm::PointerType *AliasType
+ = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+
+ // Find the referrent. Some aliases might require a bitcast, in
+ // which case the caller is responsible for ensuring the soundness
+ // of these semantics.
+ llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+ llvm::Constant *Aliasee = Ref;
+ if (Ref->getType() != AliasType)
+ Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+
+ // Create the alias with no name.
+ llvm::GlobalAlias *Alias =
+ new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
+
+ // Switch any previous uses to the alias.
+ llvm::StringRef MangledName = getMangledName(AliasDecl);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry) {
+ assert(Entry->isDeclaration() && "definition already exists for alias");
+ assert(Entry->getType() == AliasType &&
+ "declaration exists with different type");
+ Alias->takeName(Entry);
+ Entry->replaceAllUsesWith(Alias);
+ Entry->eraseFromParent();
+ } else {
+ Alias->setName(MangledName);
+ }
+
+ // Finally, set up the alias with its proper name and attributes.
+ SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
+
+ return false;
+}
+
+void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
+ // The constructor used for constructing this as a complete class;
+ // constucts the virtual bases, then calls the base constructor.
+ EmitGlobal(GlobalDecl(D, Ctor_Complete));
+
+ // The constructor used for constructing this as a base class;
+ // ignores virtual bases.
+ EmitGlobal(GlobalDecl(D, Ctor_Base));
+}
+
+void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
+ CXXCtorType Type) {
+ // The complete constructor is equivalent to the base constructor
+ // for classes with no virtual bases. Try to emit it as an alias.
+ if (Type == Ctor_Complete &&
+ !D->getParent()->getNumVBases() &&
+ !TryEmitDefinitionAsAlias(GlobalDecl(D, Ctor_Complete),
+ GlobalDecl(D, Ctor_Base)))
+ return;
+
+ llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type));
+ setFunctionLinkage(D, Fn);
+
+ CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
+
+ SetFunctionDefinitionAttributes(D, Fn);
+ SetLLVMFunctionAttributesForDefinition(D, Fn);
+}
+
+llvm::GlobalValue *
+CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
+ CXXCtorType Type) {
+ GlobalDecl GD(D, Type);
+
+ llvm::StringRef Name = getMangledName(GD);
+ if (llvm::GlobalValue *V = GetGlobalValue(Name))
+ return V;
+
+ const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
+ const llvm::FunctionType *FTy =
+ getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
+ FPT->isVariadic());
+ return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD,
+ /*ForVTable=*/false));
+}
+
+void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
+ // The destructor in a virtual table is always a 'deleting'
+ // destructor, which calls the complete destructor and then uses the
+ // appropriate operator delete.
+ if (D->isVirtual())
+ EmitGlobal(GlobalDecl(D, Dtor_Deleting));
+
+ // The destructor used for destructing this as a most-derived class;
+ // call the base destructor and then destructs any virtual bases.
+ EmitGlobal(GlobalDecl(D, Dtor_Complete));
+
+ // The destructor used for destructing this as a base class; ignores
+ // virtual bases.
+ EmitGlobal(GlobalDecl(D, Dtor_Base));
+}
+
+void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
+ CXXDtorType Type) {
+ // The complete destructor is equivalent to the base destructor for
+ // classes with no virtual bases, so try to emit it as an alias.
+ if (Type == Dtor_Complete &&
+ !D->getParent()->getNumVBases() &&
+ !TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Complete),
+ GlobalDecl(D, Dtor_Base)))
+ return;
+
+ // The base destructor is equivalent to the base destructor of its
+ // base class if there is exactly one non-virtual base class with a
+ // non-trivial destructor, there are no fields with a non-trivial
+ // destructor, and the body of the destructor is trivial.
+ if (Type == Dtor_Base && !TryEmitBaseDestructorAsAlias(D))
+ return;
+
+ llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
+ setFunctionLinkage(D, Fn);
+
+ CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
+
+ SetFunctionDefinitionAttributes(D, Fn);
+ SetLLVMFunctionAttributesForDefinition(D, Fn);
+}
+
+llvm::GlobalValue *
+CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
+ CXXDtorType Type) {
+ GlobalDecl GD(D, Type);
+
+ llvm::StringRef Name = getMangledName(GD);
+ if (llvm::GlobalValue *V = GetGlobalValue(Name))
+ return V;
+
+ const llvm::FunctionType *FTy =
+ getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
+
+ return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD,
+ /*ForVTable=*/false));
+}
+
+static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex,
+ llvm::Value *This, const llvm::Type *Ty) {
+ Ty = Ty->getPointerTo()->getPointerTo();
+
+ llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
+ llvm::Value *VFuncPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
+ return CGF.Builder.CreateLoad(VFuncPtr);
+}
+
+llvm::Value *
+CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
+ const llvm::Type *Ty) {
+ MD = MD->getCanonicalDecl();
+ uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(MD);
+
+ return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
+}
+
+/// BuildVirtualCall - This routine is to support gcc's kext ABI making
+/// indirect call to virtual functions. It makes the call through indexing
+/// into the vtable.
+llvm::Value *
+CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ NestedNameSpecifier *Qual,
+ const llvm::Type *Ty) {
+ llvm::Value *VTable = 0;
+ assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
+ "BuildAppleKextVirtualCall - bad Qual kind");
+
+ const Type *QTy = Qual->getAsType();
+ QualType T = QualType(QTy, 0);
+ const RecordType *RT = T->getAs<RecordType>();
+ assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
+ return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD);
+
+ VTable = CGM.getVTables().GetAddrOfVTable(RD);
+ Ty = Ty->getPointerTo()->getPointerTo();
+ VTable = Builder.CreateBitCast(VTable, Ty);
+ assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
+ MD = MD->getCanonicalDecl();
+ uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(MD);
+ uint64_t AddressPoint =
+ CGM.getVTables().getAddressPoint(BaseSubobject(RD, 0), RD);
+ VTableIndex += AddressPoint;
+ llvm::Value *VFuncPtr =
+ Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
+ return Builder.CreateLoad(VFuncPtr);
+}
+
+/// BuildVirtualCall - This routine makes indirect vtable call for
+/// call to virtual destructors. It returns 0 if it could not do it.
+llvm::Value *
+CodeGenFunction::BuildAppleKextVirtualDestructorCall(
+ const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const CXXRecordDecl *RD) {
+ llvm::Value * Callee = 0;
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(DD);
+ // FIXME. Dtor_Base dtor is always direct!!
+ // It need be somehow inline expanded into the caller.
+ // -O does that. But need to support -O0 as well.
+ if (MD->isVirtual() && Type != Dtor_Base) {
+ // Compute the function type we're calling.
+ const CGFunctionInfo *FInfo =
+ &CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
+ Dtor_Complete);
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty
+ = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic());
+
+ llvm::Value *VTable = CGM.getVTables().GetAddrOfVTable(RD);
+ Ty = Ty->getPointerTo()->getPointerTo();
+ VTable = Builder.CreateBitCast(VTable, Ty);
+ DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
+ uint64_t VTableIndex =
+ CGM.getVTables().getMethodVTableIndex(GlobalDecl(DD, Type));
+ uint64_t AddressPoint =
+ CGM.getVTables().getAddressPoint(BaseSubobject(RD, 0), RD);
+ VTableIndex += AddressPoint;
+ llvm::Value *VFuncPtr =
+ Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
+ Callee = Builder.CreateLoad(VFuncPtr);
+ }
+ return Callee;
+}
+
+llvm::Value *
+CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
+ llvm::Value *This, const llvm::Type *Ty) {
+ DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
+ uint64_t VTableIndex =
+ CGM.getVTables().getMethodVTableIndex(GlobalDecl(DD, Type));
+
+ return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
new file mode 100644
index 0000000..8373b66
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
@@ -0,0 +1,174 @@
+//===----- CGCXXABI.cpp - Interface to C++ ABIs -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ code generation. Concrete subclasses
+// of this implement code generation for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGCXXABI.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+CGCXXABI::~CGCXXABI() { }
+
+static void ErrorUnsupportedABI(CodeGenFunction &CGF,
+ llvm::StringRef S) {
+ Diagnostic &Diags = CGF.CGM.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ "cannot yet compile %1 in this ABI");
+ Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
+ DiagID)
+ << S;
+}
+
+static llvm::Constant *GetBogusMemberPointer(CodeGenModule &CGM,
+ QualType T) {
+ return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
+}
+
+const llvm::Type *
+CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
+ return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+}
+
+llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "calls through member pointers");
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+ const llvm::FunctionType *FTy =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+ return llvm::Constant::getNullValue(FTy->getPointerTo());
+}
+
+llvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "loads of member pointers");
+ const llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
+ return llvm::Constant::getNullValue(Ty);
+}
+
+llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src) {
+ ErrorUnsupportedABI(CGF, "member function pointer conversions");
+ return GetBogusMemberPointer(CGM, E->getType());
+}
+
+llvm::Value *
+CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ ErrorUnsupportedABI(CGF, "member function pointer comparison");
+ return CGF.Builder.getFalse();
+}
+
+llvm::Value *
+CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "member function pointer null testing");
+ return CGF.Builder.getFalse();
+}
+
+llvm::Constant *
+CGCXXABI::EmitMemberPointerConversion(llvm::Constant *C, const CastExpr *E) {
+ return GetBogusMemberPointer(CGM, E->getType());
+}
+
+llvm::Constant *
+CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
+ return GetBogusMemberPointer(CGM, QualType(MPT, 0));
+}
+
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ return GetBogusMemberPointer(CGM,
+ CGM.getContext().getMemberPointerType(MD->getType(),
+ MD->getParent()->getTypeForDecl()));
+}
+
+llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
+ return GetBogusMemberPointer(CGM, QualType(MPT, 0));
+}
+
+bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
+ // Fake answer.
+ return true;
+}
+
+void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+
+ // FIXME: I'm not entirely sure I like using a fake decl just for code
+ // generation. Maybe we can come up with a better way?
+ ImplicitParamDecl *ThisDecl
+ = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
+ &CGM.getContext().Idents.get("this"),
+ MD->getThisType(CGM.getContext()));
+ Params.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
+ getThisDecl(CGF) = ThisDecl;
+}
+
+void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
+ /// Initialize the 'this' slot.
+ assert(getThisDecl(CGF) && "no 'this' variable for function");
+ getThisValue(CGF)
+ = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
+ "this");
+}
+
+void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType) {
+ CGF.EmitReturnOfRValue(RV, ResultType);
+}
+
+CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
+ return CharUnits::Zero();
+}
+
+llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) {
+ // Should never be called.
+ ErrorUnsupportedABI(CGF, "array cookie initialization");
+ return 0;
+}
+
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ const CXXDeleteExpr *expr, QualType ElementType,
+ llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize) {
+ ErrorUnsupportedABI(CGF, "array cookie reading");
+
+ // This should be enough to avoid assertions.
+ NumElements = 0;
+ AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
+ CookieSize = CharUnits::Zero();
+}
+
+void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ ErrorUnsupportedABI(CGF, "static local variable initialization");
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
new file mode 100644
index 0000000..de4df3d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
@@ -0,0 +1,248 @@
+//===----- CGCXXABI.h - Interface to C++ ABIs -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ code generation. Concrete subclasses
+// of this implement code generation for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CXXABI_H
+#define CLANG_CODEGEN_CXXABI_H
+
+#include "CodeGenFunction.h"
+
+namespace llvm {
+ class Constant;
+ class Type;
+ class Value;
+
+ template <class T> class SmallVectorImpl;
+}
+
+namespace clang {
+ class CastExpr;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class CXXRecordDecl;
+ class FieldDecl;
+ class MangleContext;
+
+namespace CodeGen {
+ class CodeGenFunction;
+ class CodeGenModule;
+
+/// Implements C++ ABI-specific code generation functions.
+class CGCXXABI {
+protected:
+ CodeGenModule &CGM;
+ llvm::OwningPtr<MangleContext> MangleCtx;
+
+ CGCXXABI(CodeGenModule &CGM)
+ : CGM(CGM), MangleCtx(CGM.getContext().createMangleContext()) {}
+
+protected:
+ ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) {
+ return CGF.CXXThisDecl;
+ }
+ llvm::Value *&getThisValue(CodeGenFunction &CGF) {
+ return CGF.CXXThisValue;
+ }
+
+ ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
+ return CGF.CXXVTTDecl;
+ }
+ llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
+ return CGF.CXXVTTValue;
+ }
+
+ /// Build a parameter variable suitable for 'this'.
+ void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
+
+ /// Perform prolog initialization of the parameter variable suitable
+ /// for 'this' emitted by BuildThisParam.
+ void EmitThisParam(CodeGenFunction &CGF);
+
+ ASTContext &getContext() const { return CGM.getContext(); }
+
+public:
+
+ virtual ~CGCXXABI();
+
+ /// Gets the mangle context.
+ MangleContext &getMangleContext() {
+ return *MangleCtx;
+ }
+
+ /// Find the LLVM type used to represent the given member pointer
+ /// type.
+ virtual const llvm::Type *
+ ConvertMemberPointerType(const MemberPointerType *MPT);
+
+ /// Load a member function from an object and a member function
+ /// pointer. Apply the this-adjustment and set 'This' to the
+ /// adjusted value.
+ virtual llvm::Value *
+ EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Calculate an l-value from an object and a data member pointer.
+ virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Perform a derived-to-base or base-to-derived member pointer
+ /// conversion.
+ virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src);
+
+ /// Perform a derived-to-base or base-to-derived member pointer
+ /// conversion on a constant member pointer.
+ virtual llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E);
+
+ /// Return true if the given member pointer can be zero-initialized
+ /// (in the C++ sense) with an LLVM zeroinitializer.
+ virtual bool isZeroInitializable(const MemberPointerType *MPT);
+
+ /// Create a null member pointer of the given type.
+ virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
+
+ /// Create a member pointer for the given method.
+ virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+
+ /// Create a member pointer for the given field.
+ virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
+
+ /// Emit a comparison between two member pointers. Returns an i1.
+ virtual llvm::Value *
+ EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ /// Determine if a member pointer is non-null. Returns an i1.
+ virtual llvm::Value *
+ EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Build the signature of the given constructor variant by adding
+ /// any required parameters. For convenience, ResTy has been
+ /// initialized to 'void', and ArgTys has been initialized with the
+ /// type of 'this' (although this may be changed by the ABI) and
+ /// will have the formal parameters added to it afterwards.
+ ///
+ /// If there are ever any ABIs where the implicit parameters are
+ /// intermixed with the formal parameters, we can address those
+ /// then.
+ virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+ /// Build the signature of the given destructor variant by adding
+ /// any required parameters. For convenience, ResTy has been
+ /// initialized to 'void' and ArgTys has been initialized with the
+ /// type of 'this' (although this may be changed by the ABI).
+ virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+ /// Build the ABI-specific portion of the parameter list for a
+ /// function. This generally involves a 'this' parameter and
+ /// possibly some extra data for constructors and destructors.
+ ///
+ /// ABIs may also choose to override the return type, which has been
+ /// initialized with the formal return type of the function.
+ virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) = 0;
+
+ /// Emit the ABI-specific prolog for the function.
+ virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
+
+ virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType);
+
+ /**************************** Array cookies ******************************/
+
+ /// Returns the extra size required in order to store the array
+ /// cookie for the given type. May return 0 to indicate that no
+ /// array cookie is required.
+ ///
+ /// Several cases are filtered out before this method is called:
+ /// - non-array allocations never need a cookie
+ /// - calls to ::operator new(size_t, void*) never need a cookie
+ ///
+ /// \param ElementType - the allocated type of the expression,
+ /// i.e. the pointee type of the expression result type
+ virtual CharUnits GetArrayCookieSize(const CXXNewExpr *expr);
+
+ /// Initialize the array cookie for the given allocation.
+ ///
+ /// \param NewPtr - a char* which is the presumed-non-null
+ /// return value of the allocation function
+ /// \param NumElements - the computed number of elements,
+ /// potentially collapsed from the multidimensional array case
+ /// \param ElementType - the base element allocated type,
+ /// i.e. the allocated type after stripping all array types
+ virtual llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType);
+
+ /// Reads the array cookie associated with the given pointer,
+ /// if it has one.
+ ///
+ /// \param Ptr - a pointer to the first element in the array
+ /// \param ElementType - the base element type of elements of the array
+ /// \param NumElements - an out parameter which will be initialized
+ /// with the number of elements allocated, or zero if there is no
+ /// cookie
+ /// \param AllocPtr - an out parameter which will be initialized
+ /// with a char* pointing to the address returned by the allocation
+ /// function
+ /// \param CookieSize - an out parameter which will be initialized
+ /// with the size of the cookie, or zero if there is no cookie
+ virtual void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ const CXXDeleteExpr *expr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+ /*************************** Static local guards ****************************/
+
+ /// Emits the guarded initializer and destructor setup for the given
+ /// variable, given that it couldn't be emitted as a constant.
+ ///
+ /// The variable may be:
+ /// - a static local variable
+ /// - a static data member of a class template instantiation
+ virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
+
+};
+
+/// Creates an instance of a C++ ABI class.
+CGCXXABI *CreateARMCXXABI(CodeGenModule &CGM);
+CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
+CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
new file mode 100644
index 0000000..ae84b61
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -0,0 +1,1416 @@
+//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGCall.h"
+#include "CGCXXABI.h"
+#include "ABIInfo.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Attributes.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+/***/
+
+static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
+ switch (CC) {
+ default: return llvm::CallingConv::C;
+ case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
+ case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
+ case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
+ // TODO: add support for CC_X86Pascal to llvm
+ }
+}
+
+/// Derives the 'this' type for codegen purposes, i.e. ignoring method
+/// qualification.
+/// FIXME: address space qualification?
+static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD) {
+ QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
+ return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
+}
+
+/// Returns the canonical formal type of the given C++ method.
+static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) {
+ return MD->getType()->getCanonicalTypeUnqualified()
+ .getAs<FunctionProtoType>();
+}
+
+/// Returns the "extra-canonicalized" return type, which discards
+/// qualifiers on the return type. Codegen doesn't care about them,
+/// and it makes ABI code a little easier to be able to assume that
+/// all parameter and return types are top-level unqualified.
+static CanQualType GetReturnType(QualType RetTy) {
+ return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType();
+}
+
+const CGFunctionInfo &
+CodeGenTypes::getFunctionInfo(CanQual<FunctionNoProtoType> FTNP,
+ bool IsRecursive) {
+ return getFunctionInfo(FTNP->getResultType().getUnqualifiedType(),
+ llvm::SmallVector<CanQualType, 16>(),
+ FTNP->getExtInfo(), IsRecursive);
+}
+
+/// \param Args - contains any initial parameters besides those
+/// in the formal type
+static const CGFunctionInfo &getFunctionInfo(CodeGenTypes &CGT,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys,
+ CanQual<FunctionProtoType> FTP,
+ bool IsRecursive = false) {
+ // FIXME: Kill copy.
+ for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+ ArgTys.push_back(FTP->getArgType(i));
+ CanQualType ResTy = FTP->getResultType().getUnqualifiedType();
+ return CGT.getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo(), IsRecursive);
+}
+
+const CGFunctionInfo &
+CodeGenTypes::getFunctionInfo(CanQual<FunctionProtoType> FTP,
+ bool IsRecursive) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ return ::getFunctionInfo(*this, ArgTys, FTP, IsRecursive);
+}
+
+static CallingConv getCallingConventionForDecl(const Decl *D) {
+ // Set the appropriate calling convention for the Function.
+ if (D->hasAttr<StdCallAttr>())
+ return CC_X86StdCall;
+
+ if (D->hasAttr<FastCallAttr>())
+ return CC_X86FastCall;
+
+ if (D->hasAttr<ThisCallAttr>())
+ return CC_X86ThisCall;
+
+ if (D->hasAttr<PascalAttr>())
+ return CC_X86Pascal;
+
+ return CC_C;
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
+ const FunctionProtoType *FTP) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+
+ // Add the 'this' pointer.
+ ArgTys.push_back(GetThisType(Context, RD));
+
+ return ::getFunctionInfo(*this, ArgTys,
+ FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+
+ assert(!isa<CXXConstructorDecl>(MD) && "wrong method for contructors!");
+ assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
+
+ // Add the 'this' pointer unless this is a static method.
+ if (MD->isInstance())
+ ArgTys.push_back(GetThisType(Context, MD->getParent()));
+
+ return ::getFunctionInfo(*this, ArgTys, GetFormalType(MD));
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
+ CXXCtorType Type) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ ArgTys.push_back(GetThisType(Context, D->getParent()));
+ CanQualType ResTy = Context.VoidTy;
+
+ TheCXXABI.BuildConstructorSignature(D, Type, ResTy, ArgTys);
+
+ CanQual<FunctionProtoType> FTP = GetFormalType(D);
+
+ // Add the formal parameters.
+ for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+ ArgTys.push_back(FTP->getArgType(i));
+
+ return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
+ CXXDtorType Type) {
+ llvm::SmallVector<CanQualType, 2> ArgTys;
+ ArgTys.push_back(GetThisType(Context, D->getParent()));
+ CanQualType ResTy = Context.VoidTy;
+
+ TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
+
+ CanQual<FunctionProtoType> FTP = GetFormalType(D);
+ assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
+
+ return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
+ if (MD->isInstance())
+ return getFunctionInfo(MD);
+
+ CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified();
+ assert(isa<FunctionType>(FTy));
+ if (isa<FunctionNoProtoType>(FTy))
+ return getFunctionInfo(FTy.getAs<FunctionNoProtoType>());
+ assert(isa<FunctionProtoType>(FTy));
+ return getFunctionInfo(FTy.getAs<FunctionProtoType>());
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ ArgTys.push_back(Context.getCanonicalParamType(MD->getSelfDecl()->getType()));
+ ArgTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
+ // FIXME: Kill copy?
+ for (ObjCMethodDecl::param_iterator i = MD->param_begin(),
+ e = MD->param_end(); i != e; ++i) {
+ ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
+ }
+ return getFunctionInfo(GetReturnType(MD->getResultType()),
+ ArgTys,
+ FunctionType::ExtInfo(
+ /*NoReturn*/ false,
+ /*RegParm*/ 0,
+ getCallingConventionForDecl(MD)));
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(GlobalDecl GD) {
+ // FIXME: Do we need to handle ObjCMethodDecl?
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
+ return getFunctionInfo(CD, GD.getCtorType());
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
+ return getFunctionInfo(DD, GD.getDtorType());
+
+ return getFunctionInfo(FD);
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
+ const CallArgList &Args,
+ const FunctionType::ExtInfo &Info) {
+ // FIXME: Kill copy.
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ for (CallArgList::const_iterator i = Args.begin(), e = Args.end();
+ i != e; ++i)
+ ArgTys.push_back(Context.getCanonicalParamType(i->second));
+ return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info);
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy,
+ const FunctionArgList &Args,
+ const FunctionType::ExtInfo &Info) {
+ // FIXME: Kill copy.
+ llvm::SmallVector<CanQualType, 16> ArgTys;
+ for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
+ i != e; ++i)
+ ArgTys.push_back(Context.getCanonicalParamType(i->second));
+ return getFunctionInfo(GetReturnType(ResTy), ArgTys, Info);
+}
+
+const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys,
+ const FunctionType::ExtInfo &Info,
+ bool IsRecursive) {
+#ifndef NDEBUG
+ for (llvm::SmallVectorImpl<CanQualType>::const_iterator
+ I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I)
+ assert(I->isCanonicalAsParam());
+#endif
+
+ unsigned CC = ClangCallConvToLLVMCallConv(Info.getCC());
+
+ // Lookup or create unique function info.
+ llvm::FoldingSetNodeID ID;
+ CGFunctionInfo::Profile(ID, Info, ResTy,
+ ArgTys.begin(), ArgTys.end());
+
+ void *InsertPos = 0;
+ CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, InsertPos);
+ if (FI)
+ return *FI;
+
+ // Construct the function info.
+ FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getRegParm(), ResTy,
+ ArgTys.data(), ArgTys.size());
+ FunctionInfos.InsertNode(FI, InsertPos);
+
+ // Compute ABI information.
+ getABIInfo().computeInfo(*FI);
+
+ // Loop over all of the computed argument and return value info. If any of
+ // them are direct or extend without a specified coerce type, specify the
+ // default now.
+ ABIArgInfo &RetInfo = FI->getReturnInfo();
+ if (RetInfo.canHaveCoerceToType() && RetInfo.getCoerceToType() == 0)
+ RetInfo.setCoerceToType(ConvertTypeRecursive(FI->getReturnType()));
+
+ for (CGFunctionInfo::arg_iterator I = FI->arg_begin(), E = FI->arg_end();
+ I != E; ++I)
+ if (I->info.canHaveCoerceToType() && I->info.getCoerceToType() == 0)
+ I->info.setCoerceToType(ConvertTypeRecursive(I->type));
+
+ // If this is a top-level call and ConvertTypeRecursive hit unresolved pointer
+ // types, resolve them now. These pointers may point to this function, which
+ // we *just* filled in the FunctionInfo for.
+ if (!IsRecursive && !PointersToResolve.empty())
+ HandleLateResolvedPointers();
+
+ return *FI;
+}
+
+CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
+ bool _NoReturn, unsigned _RegParm,
+ CanQualType ResTy,
+ const CanQualType *ArgTys,
+ unsigned NumArgTys)
+ : CallingConvention(_CallingConvention),
+ EffectiveCallingConvention(_CallingConvention),
+ NoReturn(_NoReturn), RegParm(_RegParm)
+{
+ NumArgs = NumArgTys;
+
+ // FIXME: Coallocate with the CGFunctionInfo object.
+ Args = new ArgInfo[1 + NumArgTys];
+ Args[0].type = ResTy;
+ for (unsigned i = 0; i != NumArgTys; ++i)
+ Args[1 + i].type = ArgTys[i];
+}
+
+/***/
+
+void CodeGenTypes::GetExpandedTypes(QualType Ty,
+ std::vector<const llvm::Type*> &ArgTys,
+ bool IsRecursive) {
+ const RecordType *RT = Ty->getAsStructureType();
+ assert(RT && "Can only expand structure types.");
+ const RecordDecl *RD = RT->getDecl();
+ assert(!RD->hasFlexibleArrayMember() &&
+ "Cannot expand structure with flexible array.");
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+
+ QualType FT = FD->getType();
+ if (CodeGenFunction::hasAggregateLLVMType(FT))
+ GetExpandedTypes(FT, ArgTys, IsRecursive);
+ else
+ ArgTys.push_back(ConvertType(FT, IsRecursive));
+ }
+}
+
+llvm::Function::arg_iterator
+CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
+ llvm::Function::arg_iterator AI) {
+ const RecordType *RT = Ty->getAsStructureType();
+ assert(RT && "Can only expand structure types.");
+
+ RecordDecl *RD = RT->getDecl();
+ assert(LV.isSimple() &&
+ "Unexpected non-simple lvalue during struct expansion.");
+ llvm::Value *Addr = LV.getAddress();
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+ QualType FT = FD->getType();
+
+ // FIXME: What are the right qualifiers here?
+ LValue LV = EmitLValueForField(Addr, FD, 0);
+ if (CodeGenFunction::hasAggregateLLVMType(FT)) {
+ AI = ExpandTypeFromArgs(FT, LV, AI);
+ } else {
+ EmitStoreThroughLValue(RValue::get(AI), LV, FT);
+ ++AI;
+ }
+ }
+
+ return AI;
+}
+
+void
+CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
+ llvm::SmallVector<llvm::Value*, 16> &Args) {
+ const RecordType *RT = Ty->getAsStructureType();
+ assert(RT && "Can only expand structure types.");
+
+ RecordDecl *RD = RT->getDecl();
+ assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
+ llvm::Value *Addr = RV.getAggregateAddr();
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+ QualType FT = FD->getType();
+
+ // FIXME: What are the right qualifiers here?
+ LValue LV = EmitLValueForField(Addr, FD, 0);
+ if (CodeGenFunction::hasAggregateLLVMType(FT)) {
+ ExpandTypeToArgs(FT, RValue::getAggregate(LV.getAddress()), Args);
+ } else {
+ RValue RV = EmitLoadOfLValue(LV, FT);
+ assert(RV.isScalar() &&
+ "Unexpected non-scalar rvalue during struct expansion.");
+ Args.push_back(RV.getScalarVal());
+ }
+ }
+}
+
+/// EnterStructPointerForCoercedAccess - Given a struct pointer that we are
+/// accessing some number of bytes out of it, try to gep into the struct to get
+/// at its inner goodness. Dive as deep as possible without entering an element
+/// with an in-memory size smaller than DstSize.
+static llvm::Value *
+EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr,
+ const llvm::StructType *SrcSTy,
+ uint64_t DstSize, CodeGenFunction &CGF) {
+ // We can't dive into a zero-element struct.
+ if (SrcSTy->getNumElements() == 0) return SrcPtr;
+
+ const llvm::Type *FirstElt = SrcSTy->getElementType(0);
+
+ // If the first elt is at least as large as what we're looking for, or if the
+ // first element is the same size as the whole struct, we can enter it.
+ uint64_t FirstEltSize =
+ CGF.CGM.getTargetData().getTypeAllocSize(FirstElt);
+ if (FirstEltSize < DstSize &&
+ FirstEltSize < CGF.CGM.getTargetData().getTypeAllocSize(SrcSTy))
+ return SrcPtr;
+
+ // GEP into the first element.
+ SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcPtr, 0, 0, "coerce.dive");
+
+ // If the first element is a struct, recurse.
+ const llvm::Type *SrcTy =
+ cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ if (const llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy))
+ return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF);
+
+ return SrcPtr;
+}
+
+/// CoerceIntOrPtrToIntOrPtr - Convert a value Val to the specific Ty where both
+/// are either integers or pointers. This does a truncation of the value if it
+/// is too large or a zero extension if it is too small.
+static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
+ const llvm::Type *Ty,
+ CodeGenFunction &CGF) {
+ if (Val->getType() == Ty)
+ return Val;
+
+ if (isa<llvm::PointerType>(Val->getType())) {
+ // If this is Pointer->Pointer avoid conversion to and from int.
+ if (isa<llvm::PointerType>(Ty))
+ return CGF.Builder.CreateBitCast(Val, Ty, "coerce.val");
+
+ // Convert the pointer to an integer so we can play with its width.
+ Val = CGF.Builder.CreatePtrToInt(Val, CGF.IntPtrTy, "coerce.val.pi");
+ }
+
+ const llvm::Type *DestIntTy = Ty;
+ if (isa<llvm::PointerType>(DestIntTy))
+ DestIntTy = CGF.IntPtrTy;
+
+ if (Val->getType() != DestIntTy)
+ Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii");
+
+ if (isa<llvm::PointerType>(Ty))
+ Val = CGF.Builder.CreateIntToPtr(Val, Ty, "coerce.val.ip");
+ return Val;
+}
+
+
+
+/// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as
+/// a pointer to an object of type \arg Ty.
+///
+/// This safely handles the case when the src type is smaller than the
+/// destination type; in this situation the values of bits which not
+/// present in the src are undefined.
+static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
+ const llvm::Type *Ty,
+ CodeGenFunction &CGF) {
+ const llvm::Type *SrcTy =
+ cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+
+ // If SrcTy and Ty are the same, just do a load.
+ if (SrcTy == Ty)
+ return CGF.Builder.CreateLoad(SrcPtr);
+
+ uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(Ty);
+
+ if (const llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) {
+ SrcPtr = EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF);
+ SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ }
+
+ uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy);
+
+ // If the source and destination are integer or pointer types, just do an
+ // extension or truncation to the desired type.
+ if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
+ (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
+ llvm::LoadInst *Load = CGF.Builder.CreateLoad(SrcPtr);
+ return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
+ }
+
+ // If load is legal, just bitcast the src pointer.
+ if (SrcSize >= DstSize) {
+ // Generally SrcSize is never greater than DstSize, since this means we are
+ // losing bits. However, this can happen in cases where the structure has
+ // additional padding, for example due to a user specified alignment.
+ //
+ // FIXME: Assert that we aren't truncating non-padding bits when have access
+ // to that information.
+ llvm::Value *Casted =
+ CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty));
+ llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted);
+ // FIXME: Use better alignment / avoid requiring aligned load.
+ Load->setAlignment(1);
+ return Load;
+ }
+
+ // Otherwise do coercion through memory. This is stupid, but
+ // simple.
+ llvm::Value *Tmp = CGF.CreateTempAlloca(Ty);
+ llvm::Value *Casted =
+ CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(SrcTy));
+ llvm::StoreInst *Store =
+ CGF.Builder.CreateStore(CGF.Builder.CreateLoad(SrcPtr), Casted);
+ // FIXME: Use better alignment / avoid requiring aligned store.
+ Store->setAlignment(1);
+ return CGF.Builder.CreateLoad(Tmp);
+}
+
+/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
+/// where the source and destination may have different types.
+///
+/// This safely handles the case when the src type is larger than the
+/// destination type; the upper bits of the src will be lost.
+static void CreateCoercedStore(llvm::Value *Src,
+ llvm::Value *DstPtr,
+ bool DstIsVolatile,
+ CodeGenFunction &CGF) {
+ const llvm::Type *SrcTy = Src->getType();
+ const llvm::Type *DstTy =
+ cast<llvm::PointerType>(DstPtr->getType())->getElementType();
+ if (SrcTy == DstTy) {
+ CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
+ return;
+ }
+
+ uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy);
+
+ if (const llvm::StructType *DstSTy = dyn_cast<llvm::StructType>(DstTy)) {
+ DstPtr = EnterStructPointerForCoercedAccess(DstPtr, DstSTy, SrcSize, CGF);
+ DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType();
+ }
+
+ // If the source and destination are integer or pointer types, just do an
+ // extension or truncation to the desired type.
+ if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) &&
+ (isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) {
+ Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF);
+ CGF.Builder.CreateStore(Src, DstPtr, DstIsVolatile);
+ return;
+ }
+
+ uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(DstTy);
+
+ // If store is legal, just bitcast the src pointer.
+ if (SrcSize <= DstSize) {
+ llvm::Value *Casted =
+ CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
+ // FIXME: Use better alignment / avoid requiring aligned store.
+ CGF.Builder.CreateStore(Src, Casted, DstIsVolatile)->setAlignment(1);
+ } else {
+ // Otherwise do coercion through memory. This is stupid, but
+ // simple.
+
+ // Generally SrcSize is never greater than DstSize, since this means we are
+ // losing bits. However, this can happen in cases where the structure has
+ // additional padding, for example due to a user specified alignment.
+ //
+ // FIXME: Assert that we aren't truncating non-padding bits when have access
+ // to that information.
+ llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
+ CGF.Builder.CreateStore(Src, Tmp);
+ llvm::Value *Casted =
+ CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(DstTy));
+ llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted);
+ // FIXME: Use better alignment / avoid requiring aligned load.
+ Load->setAlignment(1);
+ CGF.Builder.CreateStore(Load, DstPtr, DstIsVolatile);
+ }
+}
+
+/***/
+
+bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) {
+ return FI.getReturnInfo().isIndirect();
+}
+
+bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) {
+ if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ default:
+ return false;
+ case BuiltinType::Float:
+ return getContext().Target.useObjCFPRetForRealType(TargetInfo::Float);
+ case BuiltinType::Double:
+ return getContext().Target.useObjCFPRetForRealType(TargetInfo::Double);
+ case BuiltinType::LongDouble:
+ return getContext().Target.useObjCFPRetForRealType(
+ TargetInfo::LongDouble);
+ }
+ }
+
+ return false;
+}
+
+const llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) {
+ const CGFunctionInfo &FI = getFunctionInfo(GD);
+
+ // For definition purposes, don't consider a K&R function variadic.
+ bool Variadic = false;
+ if (const FunctionProtoType *FPT =
+ cast<FunctionDecl>(GD.getDecl())->getType()->getAs<FunctionProtoType>())
+ Variadic = FPT->isVariadic();
+
+ return GetFunctionType(FI, Variadic, false);
+}
+
+const llvm::FunctionType *
+CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
+ bool IsRecursive) {
+ std::vector<const llvm::Type*> ArgTys;
+
+ const llvm::Type *ResultType = 0;
+
+ QualType RetTy = FI.getReturnType();
+ const ABIArgInfo &RetAI = FI.getReturnInfo();
+ switch (RetAI.getKind()) {
+ case ABIArgInfo::Expand:
+ assert(0 && "Invalid ABI kind for return argument");
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct:
+ ResultType = RetAI.getCoerceToType();
+ break;
+
+ case ABIArgInfo::Indirect: {
+ assert(!RetAI.getIndirectAlign() && "Align unused on indirect return.");
+ ResultType = llvm::Type::getVoidTy(getLLVMContext());
+ const llvm::Type *STy = ConvertType(RetTy, IsRecursive);
+ ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace()));
+ break;
+ }
+
+ case ABIArgInfo::Ignore:
+ ResultType = llvm::Type::getVoidTy(getLLVMContext());
+ break;
+ }
+
+ for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
+ ie = FI.arg_end(); it != ie; ++it) {
+ const ABIArgInfo &AI = it->info;
+
+ switch (AI.getKind()) {
+ case ABIArgInfo::Ignore:
+ break;
+
+ case ABIArgInfo::Indirect: {
+ // indirect arguments are always on the stack, which is addr space #0.
+ const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
+ ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
+ break;
+ }
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ // If the coerce-to type is a first class aggregate, flatten it. Either
+ // way is semantically identical, but fast-isel and the optimizer
+ // generally likes scalar values better than FCAs.
+ const llvm::Type *ArgTy = AI.getCoerceToType();
+ if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgTy)) {
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
+ ArgTys.push_back(STy->getElementType(i));
+ } else {
+ ArgTys.push_back(ArgTy);
+ }
+ break;
+ }
+
+ case ABIArgInfo::Expand:
+ GetExpandedTypes(it->type, ArgTys, IsRecursive);
+ break;
+ }
+ }
+
+ return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
+}
+
+const llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+
+ if (!VerifyFuncTypeComplete(FPT)) {
+ const CGFunctionInfo *Info;
+ if (isa<CXXDestructorDecl>(MD))
+ Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+ else
+ Info = &getFunctionInfo(MD);
+ return GetFunctionType(*Info, FPT->isVariadic(), false);
+ }
+
+ return llvm::OpaqueType::get(getLLVMContext());
+}
+
+void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
+ const Decl *TargetDecl,
+ AttributeListType &PAL,
+ unsigned &CallingConv) {
+ unsigned FuncAttrs = 0;
+ unsigned RetAttrs = 0;
+
+ CallingConv = FI.getEffectiveCallingConvention();
+
+ if (FI.isNoReturn())
+ FuncAttrs |= llvm::Attribute::NoReturn;
+
+ // FIXME: handle sseregparm someday...
+ if (TargetDecl) {
+ if (TargetDecl->hasAttr<NoThrowAttr>())
+ FuncAttrs |= llvm::Attribute::NoUnwind;
+ else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
+ const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
+ if (FPT && FPT->hasEmptyExceptionSpec())
+ FuncAttrs |= llvm::Attribute::NoUnwind;
+ }
+
+ if (TargetDecl->hasAttr<NoReturnAttr>())
+ FuncAttrs |= llvm::Attribute::NoReturn;
+ if (TargetDecl->hasAttr<ConstAttr>())
+ FuncAttrs |= llvm::Attribute::ReadNone;
+ else if (TargetDecl->hasAttr<PureAttr>())
+ FuncAttrs |= llvm::Attribute::ReadOnly;
+ if (TargetDecl->hasAttr<MallocAttr>())
+ RetAttrs |= llvm::Attribute::NoAlias;
+ }
+
+ if (CodeGenOpts.OptimizeSize)
+ FuncAttrs |= llvm::Attribute::OptimizeForSize;
+ if (CodeGenOpts.DisableRedZone)
+ FuncAttrs |= llvm::Attribute::NoRedZone;
+ if (CodeGenOpts.NoImplicitFloat)
+ FuncAttrs |= llvm::Attribute::NoImplicitFloat;
+
+ QualType RetTy = FI.getReturnType();
+ unsigned Index = 1;
+ const ABIArgInfo &RetAI = FI.getReturnInfo();
+ switch (RetAI.getKind()) {
+ case ABIArgInfo::Extend:
+ if (RetTy->hasSignedIntegerRepresentation())
+ RetAttrs |= llvm::Attribute::SExt;
+ else if (RetTy->hasUnsignedIntegerRepresentation())
+ RetAttrs |= llvm::Attribute::ZExt;
+ break;
+ case ABIArgInfo::Direct:
+ case ABIArgInfo::Ignore:
+ break;
+
+ case ABIArgInfo::Indirect:
+ PAL.push_back(llvm::AttributeWithIndex::get(Index,
+ llvm::Attribute::StructRet));
+ ++Index;
+ // sret disables readnone and readonly
+ FuncAttrs &= ~(llvm::Attribute::ReadOnly |
+ llvm::Attribute::ReadNone);
+ break;
+
+ case ABIArgInfo::Expand:
+ assert(0 && "Invalid ABI kind for return argument");
+ }
+
+ if (RetAttrs)
+ PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs));
+
+ // FIXME: RegParm should be reduced in case of global register variable.
+ signed RegParm = FI.getRegParm();
+ if (!RegParm)
+ RegParm = CodeGenOpts.NumRegisterParameters;
+
+ unsigned PointerWidth = getContext().Target.getPointerWidth(0);
+ for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
+ ie = FI.arg_end(); it != ie; ++it) {
+ QualType ParamType = it->type;
+ const ABIArgInfo &AI = it->info;
+ unsigned Attributes = 0;
+
+ // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
+ // have the corresponding parameter variable. It doesn't make
+ // sense to do it here because parameters are so messed up.
+ switch (AI.getKind()) {
+ case ABIArgInfo::Extend:
+ if (ParamType->isSignedIntegerType())
+ Attributes |= llvm::Attribute::SExt;
+ else if (ParamType->isUnsignedIntegerType())
+ Attributes |= llvm::Attribute::ZExt;
+ // FALL THROUGH
+ case ABIArgInfo::Direct:
+ if (RegParm > 0 &&
+ (ParamType->isIntegerType() || ParamType->isPointerType())) {
+ RegParm -=
+ (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
+ if (RegParm >= 0)
+ Attributes |= llvm::Attribute::InReg;
+ }
+ // FIXME: handle sseregparm someday...
+
+ if (const llvm::StructType *STy =
+ dyn_cast<llvm::StructType>(AI.getCoerceToType()))
+ Index += STy->getNumElements()-1; // 1 will be added below.
+ break;
+
+ case ABIArgInfo::Indirect:
+ if (AI.getIndirectByVal())
+ Attributes |= llvm::Attribute::ByVal;
+
+ Attributes |=
+ llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
+ // byval disables readnone and readonly.
+ FuncAttrs &= ~(llvm::Attribute::ReadOnly |
+ llvm::Attribute::ReadNone);
+ break;
+
+ case ABIArgInfo::Ignore:
+ // Skip increment, no matching LLVM parameter.
+ continue;
+
+ case ABIArgInfo::Expand: {
+ std::vector<const llvm::Type*> Tys;
+ // FIXME: This is rather inefficient. Do we ever actually need to do
+ // anything here? The result should be just reconstructed on the other
+ // side, so extension should be a non-issue.
+ getTypes().GetExpandedTypes(ParamType, Tys, false);
+ Index += Tys.size();
+ continue;
+ }
+ }
+
+ if (Attributes)
+ PAL.push_back(llvm::AttributeWithIndex::get(Index, Attributes));
+ ++Index;
+ }
+ if (FuncAttrs)
+ PAL.push_back(llvm::AttributeWithIndex::get(~0, FuncAttrs));
+}
+
+void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
+ llvm::Function *Fn,
+ const FunctionArgList &Args) {
+ // If this is an implicit-return-zero function, go ahead and
+ // initialize the return value. TODO: it might be nice to have
+ // a more general mechanism for this that didn't require synthesized
+ // return statements.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
+ if (FD->hasImplicitReturnZero()) {
+ QualType RetTy = FD->getResultType().getUnqualifiedType();
+ const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
+ llvm::Constant* Zero = llvm::Constant::getNullValue(LLVMTy);
+ Builder.CreateStore(Zero, ReturnValue);
+ }
+ }
+
+ // FIXME: We no longer need the types from FunctionArgList; lift up and
+ // simplify.
+
+ // Emit allocs for param decls. Give the LLVM Argument nodes names.
+ llvm::Function::arg_iterator AI = Fn->arg_begin();
+
+ // Name the struct return argument.
+ if (CGM.ReturnTypeUsesSRet(FI)) {
+ AI->setName("agg.result");
+ ++AI;
+ }
+
+ assert(FI.arg_size() == Args.size() &&
+ "Mismatch between function signature & arguments.");
+ CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin();
+ for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
+ i != e; ++i, ++info_it) {
+ const VarDecl *Arg = i->first;
+ QualType Ty = info_it->type;
+ const ABIArgInfo &ArgI = info_it->info;
+
+ switch (ArgI.getKind()) {
+ case ABIArgInfo::Indirect: {
+ llvm::Value *V = AI;
+
+ if (hasAggregateLLVMType(Ty)) {
+ // Aggregates and complex variables are accessed by reference. All we
+ // need to do is realign the value, if requested
+ if (ArgI.getIndirectRealign()) {
+ llvm::Value *AlignedTemp = CreateMemTemp(Ty, "coerce");
+
+ // Copy from the incoming argument pointer to the temporary with the
+ // appropriate alignment.
+ //
+ // FIXME: We should have a common utility for generating an aggregate
+ // copy.
+ const llvm::Type *I8PtrTy = Builder.getInt8PtrTy();
+ CharUnits Size = getContext().getTypeSizeInChars(Ty);
+ Builder.CreateMemCpy(Builder.CreateBitCast(AlignedTemp, I8PtrTy),
+ Builder.CreateBitCast(V, I8PtrTy),
+ llvm::ConstantInt::get(IntPtrTy,
+ Size.getQuantity()),
+ ArgI.getIndirectAlign(),
+ false);
+ V = AlignedTemp;
+ }
+ } else {
+ // Load scalar value from indirect argument.
+ CharUnits Alignment = getContext().getTypeAlignInChars(Ty);
+ V = EmitLoadOfScalar(V, false, Alignment.getQuantity(), Ty);
+ if (!getContext().typesAreCompatible(Ty, Arg->getType())) {
+ // This must be a promotion, for something like
+ // "void a(x) short x; {..."
+ V = EmitScalarConversion(V, Ty, Arg->getType());
+ }
+ }
+ EmitParmDecl(*Arg, V);
+ break;
+ }
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ // If we have the trivial case, handle it with no muss and fuss.
+ if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
+ ArgI.getCoerceToType() == ConvertType(Ty) &&
+ ArgI.getDirectOffset() == 0) {
+ assert(AI != Fn->arg_end() && "Argument mismatch!");
+ llvm::Value *V = AI;
+
+ if (Arg->getType().isRestrictQualified())
+ AI->addAttr(llvm::Attribute::NoAlias);
+
+ if (!getContext().typesAreCompatible(Ty, Arg->getType())) {
+ // This must be a promotion, for something like
+ // "void a(x) short x; {..."
+ V = EmitScalarConversion(V, Ty, Arg->getType());
+ }
+ EmitParmDecl(*Arg, V);
+ break;
+ }
+
+ llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce");
+
+ // The alignment we need to use is the max of the requested alignment for
+ // the argument plus the alignment required by our access code below.
+ unsigned AlignmentToUse =
+ CGM.getTargetData().getABITypeAlignment(ArgI.getCoerceToType());
+ AlignmentToUse = std::max(AlignmentToUse,
+ (unsigned)getContext().getDeclAlign(Arg).getQuantity());
+
+ Alloca->setAlignment(AlignmentToUse);
+ llvm::Value *V = Alloca;
+ llvm::Value *Ptr = V; // Pointer to store into.
+
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = ArgI.getDirectOffset()) {
+ Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy());
+ Ptr = Builder.CreateConstGEP1_32(Ptr, Offs);
+ Ptr = Builder.CreateBitCast(Ptr,
+ llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
+ }
+
+ // If the coerce-to type is a first class aggregate, we flatten it and
+ // pass the elements. Either way is semantically identical, but fast-isel
+ // and the optimizer generally likes scalar values better than FCAs.
+ if (const llvm::StructType *STy =
+ dyn_cast<llvm::StructType>(ArgI.getCoerceToType())) {
+ Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
+
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ assert(AI != Fn->arg_end() && "Argument mismatch!");
+ AI->setName(Arg->getName() + ".coerce" + llvm::Twine(i));
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(Ptr, 0, i);
+ Builder.CreateStore(AI++, EltPtr);
+ }
+ } else {
+ // Simple case, just do a coerced store of the argument into the alloca.
+ assert(AI != Fn->arg_end() && "Argument mismatch!");
+ AI->setName(Arg->getName() + ".coerce");
+ CreateCoercedStore(AI++, Ptr, /*DestIsVolatile=*/false, *this);
+ }
+
+
+ // Match to what EmitParmDecl is expecting for this type.
+ if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty);
+ if (!getContext().typesAreCompatible(Ty, Arg->getType())) {
+ // This must be a promotion, for something like
+ // "void a(x) short x; {..."
+ V = EmitScalarConversion(V, Ty, Arg->getType());
+ }
+ }
+ EmitParmDecl(*Arg, V);
+ continue; // Skip ++AI increment, already done.
+ }
+
+ case ABIArgInfo::Expand: {
+ // If this structure was expanded into multiple arguments then
+ // we need to create a temporary and reconstruct it from the
+ // arguments.
+ llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
+ llvm::Function::arg_iterator End =
+ ExpandTypeFromArgs(Ty, MakeAddrLValue(Temp, Ty), AI);
+ EmitParmDecl(*Arg, Temp);
+
+ // Name the arguments used in expansion and increment AI.
+ unsigned Index = 0;
+ for (; AI != End; ++AI, ++Index)
+ AI->setName(Arg->getName() + "." + llvm::Twine(Index));
+ continue;
+ }
+
+ case ABIArgInfo::Ignore:
+ // Initialize the local variable appropriately.
+ if (hasAggregateLLVMType(Ty))
+ EmitParmDecl(*Arg, CreateMemTemp(Ty));
+ else
+ EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
+
+ // Skip increment, no matching LLVM parameter.
+ continue;
+ }
+
+ ++AI;
+ }
+ assert(AI == Fn->arg_end() && "Argument mismatch!");
+}
+
+void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
+ // Functions with no result always return void.
+ if (ReturnValue == 0) {
+ Builder.CreateRetVoid();
+ return;
+ }
+
+ llvm::DebugLoc RetDbgLoc;
+ llvm::Value *RV = 0;
+ QualType RetTy = FI.getReturnType();
+ const ABIArgInfo &RetAI = FI.getReturnInfo();
+
+ switch (RetAI.getKind()) {
+ case ABIArgInfo::Indirect: {
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
+ if (RetTy->isAnyComplexType()) {
+ ComplexPairTy RT = LoadComplexFromAddr(ReturnValue, false);
+ StoreComplexToAddr(RT, CurFn->arg_begin(), false);
+ } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ // Do nothing; aggregrates get evaluated directly into the destination.
+ } else {
+ EmitStoreOfScalar(Builder.CreateLoad(ReturnValue), CurFn->arg_begin(),
+ false, Alignment, RetTy);
+ }
+ break;
+ }
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct:
+ if (RetAI.getCoerceToType() == ConvertType(RetTy) &&
+ RetAI.getDirectOffset() == 0) {
+ // The internal return value temp always will have pointer-to-return-type
+ // type, just do a load.
+
+ // If the instruction right before the insertion point is a store to the
+ // return value, we can elide the load, zap the store, and usually zap the
+ // alloca.
+ llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
+ llvm::StoreInst *SI = 0;
+ if (InsertBB->empty() ||
+ !(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
+ SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
+ RV = Builder.CreateLoad(ReturnValue);
+ } else {
+ // Get the stored value and nuke the now-dead store.
+ RetDbgLoc = SI->getDebugLoc();
+ RV = SI->getValueOperand();
+ SI->eraseFromParent();
+
+ // If that was the only use of the return value, nuke it as well now.
+ if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
+ cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
+ ReturnValue = 0;
+ }
+ }
+ } else {
+ llvm::Value *V = ReturnValue;
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = RetAI.getDirectOffset()) {
+ V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
+ V = Builder.CreateConstGEP1_32(V, Offs);
+ V = Builder.CreateBitCast(V,
+ llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
+ }
+
+ RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
+ }
+ break;
+
+ case ABIArgInfo::Ignore:
+ break;
+
+ case ABIArgInfo::Expand:
+ assert(0 && "Invalid ABI kind for return argument");
+ }
+
+ llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid();
+ if (!RetDbgLoc.isUnknown())
+ Ret->setDebugLoc(RetDbgLoc);
+}
+
+RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
+ // StartFunction converted the ABI-lowered parameter(s) into a
+ // local alloca. We need to turn that into an r-value suitable
+ // for EmitCall.
+ llvm::Value *Local = GetAddrOfLocalVar(Param);
+
+ QualType ArgType = Param->getType();
+
+ // For the most part, we just need to load the alloca, except:
+ // 1) aggregate r-values are actually pointers to temporaries, and
+ // 2) references to aggregates are pointers directly to the aggregate.
+ // I don't know why references to non-aggregates are different here.
+ if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) {
+ if (hasAggregateLLVMType(RefType->getPointeeType()))
+ return RValue::getAggregate(Local);
+
+ // Locals which are references to scalars are represented
+ // with allocas holding the pointer.
+ return RValue::get(Builder.CreateLoad(Local));
+ }
+
+ if (ArgType->isAnyComplexType())
+ return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false));
+
+ if (hasAggregateLLVMType(ArgType))
+ return RValue::getAggregate(Local);
+
+ unsigned Alignment = getContext().getDeclAlign(Param).getQuantity();
+ return RValue::get(EmitLoadOfScalar(Local, false, Alignment, ArgType));
+}
+
+RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
+ if (ArgType->isReferenceType())
+ return EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
+
+ return EmitAnyExprToTemp(E);
+}
+
+/// Emits a call or invoke instruction to the given function, depending
+/// on the current state of the EH stack.
+llvm::CallSite
+CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
+ llvm::Value * const *ArgBegin,
+ llvm::Value * const *ArgEnd,
+ const llvm::Twine &Name) {
+ llvm::BasicBlock *InvokeDest = getInvokeDest();
+ if (!InvokeDest)
+ return Builder.CreateCall(Callee, ArgBegin, ArgEnd, Name);
+
+ llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont");
+ llvm::InvokeInst *Invoke = Builder.CreateInvoke(Callee, ContBB, InvokeDest,
+ ArgBegin, ArgEnd, Name);
+ EmitBlock(ContBB);
+ return Invoke;
+}
+
+RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
+ llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ const CallArgList &CallArgs,
+ const Decl *TargetDecl,
+ llvm::Instruction **callOrInvoke) {
+ // FIXME: We no longer need the types from CallArgs; lift up and simplify.
+ llvm::SmallVector<llvm::Value*, 16> Args;
+
+ // Handle struct-return functions by passing a pointer to the
+ // location that we would like to return into.
+ QualType RetTy = CallInfo.getReturnType();
+ const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
+
+
+ // If the call returns a temporary with struct return, create a temporary
+ // alloca to hold the result, unless one is given to us.
+ if (CGM.ReturnTypeUsesSRet(CallInfo)) {
+ llvm::Value *Value = ReturnValue.getValue();
+ if (!Value)
+ Value = CreateMemTemp(RetTy);
+ Args.push_back(Value);
+ }
+
+ assert(CallInfo.arg_size() == CallArgs.size() &&
+ "Mismatch between function signature & arguments.");
+ CGFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin();
+ for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
+ I != E; ++I, ++info_it) {
+ const ABIArgInfo &ArgInfo = info_it->info;
+ RValue RV = I->first;
+
+ unsigned Alignment =
+ getContext().getTypeAlignInChars(I->second).getQuantity();
+ switch (ArgInfo.getKind()) {
+ case ABIArgInfo::Indirect: {
+ if (RV.isScalar() || RV.isComplex()) {
+ // Make a temporary alloca to pass the argument.
+ Args.push_back(CreateMemTemp(I->second));
+ if (RV.isScalar())
+ EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false,
+ Alignment, I->second);
+ else
+ StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
+ } else {
+ Args.push_back(RV.getAggregateAddr());
+ }
+ break;
+ }
+
+ case ABIArgInfo::Ignore:
+ break;
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
+ ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
+ ArgInfo.getDirectOffset() == 0) {
+ if (RV.isScalar())
+ Args.push_back(RV.getScalarVal());
+ else
+ Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
+ break;
+ }
+
+ // FIXME: Avoid the conversion through memory if possible.
+ llvm::Value *SrcPtr;
+ if (RV.isScalar()) {
+ SrcPtr = CreateMemTemp(I->second, "coerce");
+ EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, Alignment,
+ I->second);
+ } else if (RV.isComplex()) {
+ SrcPtr = CreateMemTemp(I->second, "coerce");
+ StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false);
+ } else
+ SrcPtr = RV.getAggregateAddr();
+
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = ArgInfo.getDirectOffset()) {
+ SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy());
+ SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs);
+ SrcPtr = Builder.CreateBitCast(SrcPtr,
+ llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
+
+ }
+
+ // If the coerce-to type is a first class aggregate, we flatten it and
+ // pass the elements. Either way is semantically identical, but fast-isel
+ // and the optimizer generally likes scalar values better than FCAs.
+ if (const llvm::StructType *STy =
+ dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType())) {
+ SrcPtr = Builder.CreateBitCast(SrcPtr,
+ llvm::PointerType::getUnqual(STy));
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i);
+ llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);
+ // We don't know what we're loading from.
+ LI->setAlignment(1);
+ Args.push_back(LI);
+ }
+ } else {
+ // In the simple case, just pass the coerced loaded value.
+ Args.push_back(CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(),
+ *this));
+ }
+
+ break;
+ }
+
+ case ABIArgInfo::Expand:
+ ExpandTypeToArgs(I->second, RV, Args);
+ break;
+ }
+ }
+
+ // If the callee is a bitcast of a function to a varargs pointer to function
+ // type, check to see if we can remove the bitcast. This handles some cases
+ // with unprototyped functions.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee))
+ if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) {
+ const llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType());
+ const llvm::FunctionType *CurFT =
+ cast<llvm::FunctionType>(CurPT->getElementType());
+ const llvm::FunctionType *ActualFT = CalleeF->getFunctionType();
+
+ if (CE->getOpcode() == llvm::Instruction::BitCast &&
+ ActualFT->getReturnType() == CurFT->getReturnType() &&
+ ActualFT->getNumParams() == CurFT->getNumParams() &&
+ ActualFT->getNumParams() == Args.size()) {
+ bool ArgsMatch = true;
+ for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
+ if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
+ ArgsMatch = false;
+ break;
+ }
+
+ // Strip the cast if we can get away with it. This is a nice cleanup,
+ // but also allows us to inline the function at -O0 if it is marked
+ // always_inline.
+ if (ArgsMatch)
+ Callee = CalleeF;
+ }
+ }
+
+
+ unsigned CallingConv;
+ CodeGen::AttributeListType AttributeList;
+ CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList, CallingConv);
+ llvm::AttrListPtr Attrs = llvm::AttrListPtr::get(AttributeList.begin(),
+ AttributeList.end());
+
+ llvm::BasicBlock *InvokeDest = 0;
+ if (!(Attrs.getFnAttributes() & llvm::Attribute::NoUnwind))
+ InvokeDest = getInvokeDest();
+
+ llvm::CallSite CS;
+ if (!InvokeDest) {
+ CS = Builder.CreateCall(Callee, Args.data(), Args.data()+Args.size());
+ } else {
+ llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
+ CS = Builder.CreateInvoke(Callee, Cont, InvokeDest,
+ Args.data(), Args.data()+Args.size());
+ EmitBlock(Cont);
+ }
+ if (callOrInvoke)
+ *callOrInvoke = CS.getInstruction();
+
+ CS.setAttributes(Attrs);
+ CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
+
+ // If the call doesn't return, finish the basic block and clear the
+ // insertion point; this allows the rest of IRgen to discard
+ // unreachable code.
+ if (CS.doesNotReturn()) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+
+ // FIXME: For now, emit a dummy basic block because expr emitters in
+ // generally are not ready to handle emitting expressions at unreachable
+ // points.
+ EnsureInsertPoint();
+
+ // Return a reasonable RValue.
+ return GetUndefRValue(RetTy);
+ }
+
+ llvm::Instruction *CI = CS.getInstruction();
+ if (Builder.isNamePreserving() && !CI->getType()->isVoidTy())
+ CI->setName("call");
+
+ switch (RetAI.getKind()) {
+ case ABIArgInfo::Indirect: {
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
+ if (RetTy->isAnyComplexType())
+ return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
+ if (CodeGenFunction::hasAggregateLLVMType(RetTy))
+ return RValue::getAggregate(Args[0]);
+ return RValue::get(EmitLoadOfScalar(Args[0], false, Alignment, RetTy));
+ }
+
+ case ABIArgInfo::Ignore:
+ // If we are ignoring an argument that had a result, make sure to
+ // construct the appropriate return value for our caller.
+ return GetUndefRValue(RetTy);
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ if (RetAI.getCoerceToType() == ConvertType(RetTy) &&
+ RetAI.getDirectOffset() == 0) {
+ if (RetTy->isAnyComplexType()) {
+ llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
+ llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
+ return RValue::getComplex(std::make_pair(Real, Imag));
+ }
+ if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ llvm::Value *DestPtr = ReturnValue.getValue();
+ bool DestIsVolatile = ReturnValue.isVolatile();
+
+ if (!DestPtr) {
+ DestPtr = CreateMemTemp(RetTy, "agg.tmp");
+ DestIsVolatile = false;
+ }
+ Builder.CreateStore(CI, DestPtr, DestIsVolatile);
+ return RValue::getAggregate(DestPtr);
+ }
+ return RValue::get(CI);
+ }
+
+ llvm::Value *DestPtr = ReturnValue.getValue();
+ bool DestIsVolatile = ReturnValue.isVolatile();
+
+ if (!DestPtr) {
+ DestPtr = CreateMemTemp(RetTy, "coerce");
+ DestIsVolatile = false;
+ }
+
+ // If the value is offset in memory, apply the offset now.
+ llvm::Value *StorePtr = DestPtr;
+ if (unsigned Offs = RetAI.getDirectOffset()) {
+ StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
+ StorePtr = Builder.CreateConstGEP1_32(StorePtr, Offs);
+ StorePtr = Builder.CreateBitCast(StorePtr,
+ llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
+ }
+ CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
+
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
+ if (RetTy->isAnyComplexType())
+ return RValue::getComplex(LoadComplexFromAddr(DestPtr, false));
+ if (CodeGenFunction::hasAggregateLLVMType(RetTy))
+ return RValue::getAggregate(DestPtr);
+ return RValue::get(EmitLoadOfScalar(DestPtr, false, Alignment, RetTy));
+ }
+
+ case ABIArgInfo::Expand:
+ assert(0 && "Invalid ABI kind for return argument");
+ }
+
+ assert(0 && "Unhandled ABIArgInfo::Kind");
+ return RValue::get(0);
+}
+
+/* VarArg handling */
+
+llvm::Value *CodeGenFunction::EmitVAArg(llvm::Value *VAListAddr, QualType Ty) {
+ return CGM.getTypes().getABIInfo().EmitVAArg(VAListAddr, Ty, *this);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
new file mode 100644
index 0000000..41e707a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
@@ -0,0 +1,164 @@
+//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGCALL_H
+#define CLANG_CODEGEN_CGCALL_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Value.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
+
+#include "CGValue.h"
+
+// FIXME: Restructure so we don't have to expose so much stuff.
+#include "ABIInfo.h"
+
+namespace llvm {
+ struct AttributeWithIndex;
+ class Function;
+ class Type;
+ class Value;
+
+ template<typename T, unsigned> class SmallVector;
+}
+
+namespace clang {
+ class ASTContext;
+ class Decl;
+ class FunctionDecl;
+ class ObjCMethodDecl;
+ class VarDecl;
+
+namespace CodeGen {
+ typedef llvm::SmallVector<llvm::AttributeWithIndex, 8> AttributeListType;
+
+ /// CallArgList - Type for representing both the value and type of
+ /// arguments in a call.
+ typedef llvm::SmallVector<std::pair<RValue, QualType>, 16> CallArgList;
+
+ /// FunctionArgList - Type for representing both the decl and type
+ /// of parameters to a function. The decl must be either a
+ /// ParmVarDecl or ImplicitParamDecl.
+ typedef llvm::SmallVector<std::pair<const VarDecl*, QualType>,
+ 16> FunctionArgList;
+
+ /// CGFunctionInfo - Class to encapsulate the information about a
+ /// function definition.
+ class CGFunctionInfo : public llvm::FoldingSetNode {
+ struct ArgInfo {
+ CanQualType type;
+ ABIArgInfo info;
+ };
+
+ /// The LLVM::CallingConv to use for this function (as specified by the
+ /// user).
+ unsigned CallingConvention;
+
+ /// The LLVM::CallingConv to actually use for this function, which may
+ /// depend on the ABI.
+ unsigned EffectiveCallingConvention;
+
+ /// Whether this function is noreturn.
+ bool NoReturn;
+
+ unsigned NumArgs;
+ ArgInfo *Args;
+
+ /// How many arguments to pass inreg.
+ unsigned RegParm;
+
+ public:
+ typedef const ArgInfo *const_arg_iterator;
+ typedef ArgInfo *arg_iterator;
+
+ CGFunctionInfo(unsigned CallingConvention, bool NoReturn,
+ unsigned RegParm, CanQualType ResTy,
+ const CanQualType *ArgTys, unsigned NumArgTys);
+ ~CGFunctionInfo() { delete[] Args; }
+
+ const_arg_iterator arg_begin() const { return Args + 1; }
+ const_arg_iterator arg_end() const { return Args + 1 + NumArgs; }
+ arg_iterator arg_begin() { return Args + 1; }
+ arg_iterator arg_end() { return Args + 1 + NumArgs; }
+
+ unsigned arg_size() const { return NumArgs; }
+
+ bool isNoReturn() const { return NoReturn; }
+
+ /// getCallingConvention - Return the user specified calling
+ /// convention.
+ unsigned getCallingConvention() const { return CallingConvention; }
+
+ /// getEffectiveCallingConvention - Return the actual calling convention to
+ /// use, which may depend on the ABI.
+ unsigned getEffectiveCallingConvention() const {
+ return EffectiveCallingConvention;
+ }
+ void setEffectiveCallingConvention(unsigned Value) {
+ EffectiveCallingConvention = Value;
+ }
+
+ unsigned getRegParm() const { return RegParm; }
+
+ CanQualType getReturnType() const { return Args[0].type; }
+
+ ABIArgInfo &getReturnInfo() { return Args[0].info; }
+ const ABIArgInfo &getReturnInfo() const { return Args[0].info; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddInteger(getCallingConvention());
+ ID.AddBoolean(NoReturn);
+ ID.AddInteger(RegParm);
+ getReturnType().Profile(ID);
+ for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
+ it->type.Profile(ID);
+ }
+ template<class Iterator>
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const FunctionType::ExtInfo &Info,
+ CanQualType ResTy,
+ Iterator begin,
+ Iterator end) {
+ ID.AddInteger(Info.getCC());
+ ID.AddBoolean(Info.getNoReturn());
+ ID.AddInteger(Info.getRegParm());
+ ResTy.Profile(ID);
+ for (; begin != end; ++begin) {
+ CanQualType T = *begin; // force iterator to be over canonical types
+ T.Profile(ID);
+ }
+ }
+ };
+
+ /// ReturnValueSlot - Contains the address where the return value of a
+ /// function can be stored, and whether the address is volatile or not.
+ class ReturnValueSlot {
+ llvm::PointerIntPair<llvm::Value *, 1, bool> Value;
+
+ public:
+ ReturnValueSlot() {}
+ ReturnValueSlot(llvm::Value *Value, bool IsVolatile)
+ : Value(Value, IsVolatile) {}
+
+ bool isNull() const { return !getValue(); }
+
+ bool isVolatile() const { return Value.getInt(); }
+ llvm::Value *getValue() const { return Value.getPointer(); }
+ };
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
new file mode 100644
index 0000000..8e88beb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -0,0 +1,1475 @@
+//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of classes
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtCXX.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+static uint64_t
+ComputeNonVirtualBaseClassOffset(ASTContext &Context,
+ const CXXRecordDecl *DerivedClass,
+ CastExpr::path_const_iterator Start,
+ CastExpr::path_const_iterator End) {
+ uint64_t Offset = 0;
+
+ const CXXRecordDecl *RD = DerivedClass;
+
+ for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
+ const CXXBaseSpecifier *Base = *I;
+ assert(!Base->isVirtual() && "Should not see virtual bases here!");
+
+ // Get the layout.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ // Add the offset.
+ Offset += Layout.getBaseClassOffsetInBits(BaseDecl);
+
+ RD = BaseDecl;
+ }
+
+ // FIXME: We should not use / 8 here.
+ return Offset / 8;
+}
+
+llvm::Constant *
+CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd) {
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
+
+ uint64_t Offset =
+ ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
+ PathBegin, PathEnd);
+ if (!Offset)
+ return 0;
+
+ const llvm::Type *PtrDiffTy =
+ Types.ConvertType(getContext().getPointerDiffType());
+
+ return llvm::ConstantInt::get(PtrDiffTy, Offset);
+}
+
+/// Gets the address of a direct base class within a complete object.
+/// This should only be used for (1) non-virtual bases or (2) virtual bases
+/// when the type is known to be complete (e.g. in complete destructors).
+///
+/// The object pointed to by 'This' is assumed to be non-null.
+llvm::Value *
+CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This,
+ const CXXRecordDecl *Derived,
+ const CXXRecordDecl *Base,
+ bool BaseIsVirtual) {
+ // 'this' must be a pointer (in some address space) to Derived.
+ assert(This->getType()->isPointerTy() &&
+ cast<llvm::PointerType>(This->getType())->getElementType()
+ == ConvertType(Derived));
+
+ // Compute the offset of the virtual base.
+ uint64_t Offset;
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
+ if (BaseIsVirtual)
+ Offset = Layout.getVBaseClassOffsetInBits(Base);
+ else
+ Offset = Layout.getBaseClassOffsetInBits(Base);
+
+ // Shift and cast down to the base type.
+ // TODO: for complete types, this should be possible with a GEP.
+ llvm::Value *V = This;
+ if (Offset) {
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
+ V = Builder.CreateBitCast(V, Int8PtrTy);
+ V = Builder.CreateConstInBoundsGEP1_64(V, Offset / 8);
+ }
+ V = Builder.CreateBitCast(V, ConvertType(Base)->getPointerTo());
+
+ return V;
+}
+
+static llvm::Value *
+ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr,
+ uint64_t NonVirtual, llvm::Value *Virtual) {
+ const llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+
+ llvm::Value *NonVirtualOffset = 0;
+ if (NonVirtual)
+ NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, NonVirtual);
+
+ llvm::Value *BaseOffset;
+ if (Virtual) {
+ if (NonVirtualOffset)
+ BaseOffset = CGF.Builder.CreateAdd(Virtual, NonVirtualOffset);
+ else
+ BaseOffset = Virtual;
+ } else
+ BaseOffset = NonVirtualOffset;
+
+ // Apply the base offset.
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ ThisPtr = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
+ ThisPtr = CGF.Builder.CreateGEP(ThisPtr, BaseOffset, "add.ptr");
+
+ return ThisPtr;
+}
+
+llvm::Value *
+CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue) {
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
+
+ CastExpr::path_const_iterator Start = PathBegin;
+ const CXXRecordDecl *VBase = 0;
+
+ // Get the virtual base.
+ if ((*Start)->isVirtual()) {
+ VBase =
+ cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl());
+ ++Start;
+ }
+
+ uint64_t NonVirtualOffset =
+ ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
+ Start, PathEnd);
+
+ // Get the base pointer type.
+ const llvm::Type *BasePtrTy =
+ ConvertType((PathEnd[-1])->getType())->getPointerTo();
+
+ if (!NonVirtualOffset && !VBase) {
+ // Just cast back.
+ return Builder.CreateBitCast(Value, BasePtrTy);
+ }
+
+ llvm::BasicBlock *CastNull = 0;
+ llvm::BasicBlock *CastNotNull = 0;
+ llvm::BasicBlock *CastEnd = 0;
+
+ if (NullCheckValue) {
+ CastNull = createBasicBlock("cast.null");
+ CastNotNull = createBasicBlock("cast.notnull");
+ CastEnd = createBasicBlock("cast.end");
+
+ llvm::Value *IsNull =
+ Builder.CreateICmpEQ(Value,
+ llvm::Constant::getNullValue(Value->getType()));
+ Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
+ EmitBlock(CastNotNull);
+ }
+
+ llvm::Value *VirtualOffset = 0;
+
+ if (VBase) {
+ if (Derived->hasAttr<FinalAttr>()) {
+ VirtualOffset = 0;
+
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
+
+ uint64_t VBaseOffset = Layout.getVBaseClassOffsetInBits(VBase);
+ NonVirtualOffset += VBaseOffset / 8;
+ } else
+ VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
+ }
+
+ // Apply the offsets.
+ Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
+ VirtualOffset);
+
+ // Cast back.
+ Value = Builder.CreateBitCast(Value, BasePtrTy);
+
+ if (NullCheckValue) {
+ Builder.CreateBr(CastEnd);
+ EmitBlock(CastNull);
+ Builder.CreateBr(CastEnd);
+ EmitBlock(CastEnd);
+
+ llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(Value, CastNotNull);
+ PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
+ CastNull);
+ Value = PHI;
+ }
+
+ return Value;
+}
+
+llvm::Value *
+CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue) {
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
+
+ QualType DerivedTy =
+ getContext().getCanonicalType(getContext().getTagDeclType(Derived));
+ const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
+
+ llvm::Value *NonVirtualOffset =
+ CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
+
+ if (!NonVirtualOffset) {
+ // No offset, we can just cast back.
+ return Builder.CreateBitCast(Value, DerivedPtrTy);
+ }
+
+ llvm::BasicBlock *CastNull = 0;
+ llvm::BasicBlock *CastNotNull = 0;
+ llvm::BasicBlock *CastEnd = 0;
+
+ if (NullCheckValue) {
+ CastNull = createBasicBlock("cast.null");
+ CastNotNull = createBasicBlock("cast.notnull");
+ CastEnd = createBasicBlock("cast.end");
+
+ llvm::Value *IsNull =
+ Builder.CreateICmpEQ(Value,
+ llvm::Constant::getNullValue(Value->getType()));
+ Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
+ EmitBlock(CastNotNull);
+ }
+
+ // Apply the offset.
+ Value = Builder.CreatePtrToInt(Value, NonVirtualOffset->getType());
+ Value = Builder.CreateSub(Value, NonVirtualOffset);
+ Value = Builder.CreateIntToPtr(Value, DerivedPtrTy);
+
+ // Just cast.
+ Value = Builder.CreateBitCast(Value, DerivedPtrTy);
+
+ if (NullCheckValue) {
+ Builder.CreateBr(CastEnd);
+ EmitBlock(CastNull);
+ Builder.CreateBr(CastEnd);
+ EmitBlock(CastEnd);
+
+ llvm::PHINode *PHI = Builder.CreatePHI(Value->getType());
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(Value, CastNotNull);
+ PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
+ CastNull);
+ Value = PHI;
+ }
+
+ return Value;
+}
+
+/// GetVTTParameter - Return the VTT parameter that should be passed to a
+/// base constructor/destructor with virtual bases.
+static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
+ bool ForVirtualBase) {
+ if (!CodeGenVTables::needsVTTParameter(GD)) {
+ // This constructor/destructor does not need a VTT parameter.
+ return 0;
+ }
+
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(CGF.CurFuncDecl)->getParent();
+ const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
+
+ llvm::Value *VTT;
+
+ uint64_t SubVTTIndex;
+
+ // If the record matches the base, this is the complete ctor/dtor
+ // variant calling the base variant in a class with virtual bases.
+ if (RD == Base) {
+ assert(!CodeGenVTables::needsVTTParameter(CGF.CurGD) &&
+ "doing no-op VTT offset in base dtor/ctor?");
+ assert(!ForVirtualBase && "Can't have same class as virtual base!");
+ SubVTTIndex = 0;
+ } else {
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(RD);
+ uint64_t BaseOffset = ForVirtualBase ?
+ Layout.getVBaseClassOffsetInBits(Base) :
+ Layout.getBaseClassOffsetInBits(Base);
+
+ SubVTTIndex =
+ CGF.CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
+ assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
+ }
+
+ if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
+ // A VTT parameter was passed to the constructor, use it.
+ VTT = CGF.LoadCXXVTT();
+ VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex);
+ } else {
+ // We're the complete constructor, so get the VTT by name.
+ VTT = CGF.CGM.getVTables().GetAddrOfVTT(RD);
+ VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex);
+ }
+
+ return VTT;
+}
+
+namespace {
+ /// Call the destructor for a direct base class.
+ struct CallBaseDtor : EHScopeStack::Cleanup {
+ const CXXRecordDecl *BaseClass;
+ bool BaseIsVirtual;
+ CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
+ : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXRecordDecl *DerivedClass =
+ cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
+
+ const CXXDestructorDecl *D = BaseClass->getDestructor();
+ llvm::Value *Addr =
+ CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(),
+ DerivedClass, BaseClass,
+ BaseIsVirtual);
+ CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, Addr);
+ }
+ };
+
+ /// A visitor which checks whether an initializer uses 'this' in a
+ /// way which requires the vtable to be properly set.
+ struct DynamicThisUseChecker : EvaluatedExprVisitor<DynamicThisUseChecker> {
+ typedef EvaluatedExprVisitor<DynamicThisUseChecker> super;
+
+ bool UsesThis;
+
+ DynamicThisUseChecker(ASTContext &C) : super(C), UsesThis(false) {}
+
+ // Black-list all explicit and implicit references to 'this'.
+ //
+ // Do we need to worry about external references to 'this' derived
+ // from arbitrary code? If so, then anything which runs arbitrary
+ // external code might potentially access the vtable.
+ void VisitCXXThisExpr(CXXThisExpr *E) { UsesThis = true; }
+ };
+}
+
+static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
+ DynamicThisUseChecker Checker(C);
+ Checker.Visit(const_cast<Expr*>(Init));
+ return Checker.UsesThis;
+}
+
+static void EmitBaseInitializer(CodeGenFunction &CGF,
+ const CXXRecordDecl *ClassDecl,
+ CXXCtorInitializer *BaseInit,
+ CXXCtorType CtorType) {
+ assert(BaseInit->isBaseInitializer() &&
+ "Must have base initializer!");
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+
+ const Type *BaseType = BaseInit->getBaseClass();
+ CXXRecordDecl *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+
+ bool isBaseVirtual = BaseInit->isBaseVirtual();
+
+ // The base constructor doesn't construct virtual bases.
+ if (CtorType == Ctor_Base && isBaseVirtual)
+ return;
+
+ // If the initializer for the base (other than the constructor
+ // itself) accesses 'this' in any way, we need to initialize the
+ // vtables.
+ if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit()))
+ CGF.InitializeVTablePointers(ClassDecl);
+
+ // We can pretend to be a complete class because it only matters for
+ // virtual bases, and we only do virtual bases for complete ctors.
+ llvm::Value *V =
+ CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
+ BaseClassDecl,
+ isBaseVirtual);
+
+ AggValueSlot AggSlot = AggValueSlot::forAddr(V, false, /*Lifetime*/ true);
+
+ CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
+
+ if (CGF.CGM.getLangOptions().areExceptionsEnabled() &&
+ !BaseClassDecl->hasTrivialDestructor())
+ CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl,
+ isBaseVirtual);
+}
+
+static void EmitAggMemberInitializer(CodeGenFunction &CGF,
+ LValue LHS,
+ llvm::Value *ArrayIndexVar,
+ CXXCtorInitializer *MemberInit,
+ QualType T,
+ unsigned Index) {
+ if (Index == MemberInit->getNumArrayIndices()) {
+ CodeGenFunction::RunCleanupsScope Cleanups(CGF);
+
+ llvm::Value *Dest = LHS.getAddress();
+ if (ArrayIndexVar) {
+ // If we have an array index variable, load it and use it as an offset.
+ // Then, increment the value.
+ llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
+ Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
+ llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
+ Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
+ CGF.Builder.CreateStore(Next, ArrayIndexVar);
+ }
+
+ AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.isVolatileQualified(),
+ /*Lifetime*/ true);
+
+ CGF.EmitAggExpr(MemberInit->getInit(), Slot);
+
+ return;
+ }
+
+ const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T);
+ assert(Array && "Array initialization without the array type?");
+ llvm::Value *IndexVar
+ = CGF.GetAddrOfLocalVar(MemberInit->getArrayIndex(Index));
+ assert(IndexVar && "Array index variable not loaded");
+
+ // Initialize this index variable to zero.
+ llvm::Value* Zero
+ = llvm::Constant::getNullValue(
+ CGF.ConvertType(CGF.getContext().getSizeType()));
+ CGF.Builder.CreateStore(Zero, IndexVar);
+
+ // Start the loop with a block that tests the condition.
+ llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end");
+
+ CGF.EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body");
+ // Generate: if (loop-index < number-of-elements) fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ uint64_t NumElements = Array->getSize().getZExtValue();
+ llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar);
+ llvm::Value *NumElementsPtr =
+ llvm::ConstantInt::get(Counter->getType(), NumElements);
+ llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr,
+ "isless");
+
+ // If the condition is true, execute the body.
+ CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor);
+
+ CGF.EmitBlock(ForBody);
+ llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
+
+ {
+ CodeGenFunction::RunCleanupsScope Cleanups(CGF);
+
+ // Inside the loop body recurse to emit the inner loop or, eventually, the
+ // constructor call.
+ EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit,
+ Array->getElementType(), Index + 1);
+ }
+
+ CGF.EmitBlock(ContinueBlock);
+
+ // Emit the increment of the loop counter.
+ llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
+ Counter = CGF.Builder.CreateLoad(IndexVar);
+ NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc");
+ CGF.Builder.CreateStore(NextVal, IndexVar);
+
+ // Finally, branch back up to the condition for the next iteration.
+ CGF.EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ CGF.EmitBlock(AfterFor, true);
+}
+
+namespace {
+ struct CallMemberDtor : EHScopeStack::Cleanup {
+ FieldDecl *Field;
+ CXXDestructorDecl *Dtor;
+
+ CallMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor)
+ : Field(Field), Dtor(Dtor) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // FIXME: Is this OK for C++0x delegating constructors?
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
+
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
+ }
+ };
+}
+
+static void EmitMemberInitializer(CodeGenFunction &CGF,
+ const CXXRecordDecl *ClassDecl,
+ CXXCtorInitializer *MemberInit,
+ const CXXConstructorDecl *Constructor,
+ FunctionArgList &Args) {
+ assert(MemberInit->isAnyMemberInitializer() &&
+ "Must have member initializer!");
+
+ // non-static data member initializers.
+ FieldDecl *Field = MemberInit->getAnyMember();
+ QualType FieldType = CGF.getContext().getCanonicalType(Field->getType());
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS;
+
+ // If we are initializing an anonymous union field, drill down to the field.
+ if (MemberInit->isIndirectMemberInitializer()) {
+ LHS = CGF.EmitLValueForAnonRecordField(ThisPtr,
+ MemberInit->getIndirectMember(), 0);
+ FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
+ } else {
+ LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
+ }
+
+ // FIXME: If there's no initializer and the CXXCtorInitializer
+ // was implicitly generated, we shouldn't be zeroing memory.
+ RValue RHS;
+ if (FieldType->isReferenceType()) {
+ RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), Field);
+ CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+ } else if (FieldType->isArrayType() && !MemberInit->getInit()) {
+ CGF.EmitNullInitialization(LHS.getAddress(), Field->getType());
+ } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
+ RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit()));
+ CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+ } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
+ CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
+ LHS.isVolatileQualified());
+ } else {
+ llvm::Value *ArrayIndexVar = 0;
+ const ConstantArrayType *Array
+ = CGF.getContext().getAsConstantArrayType(FieldType);
+ if (Array && Constructor->isImplicit() &&
+ Constructor->isCopyConstructor()) {
+ const llvm::Type *SizeTy
+ = CGF.ConvertType(CGF.getContext().getSizeType());
+
+ // The LHS is a pointer to the first object we'll be constructing, as
+ // a flat array.
+ QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(),
+ BasePtr);
+ LHS = CGF.MakeAddrLValue(BaseAddrPtr, BaseElementTy);
+
+ // Create an array index that will be used to walk over all of the
+ // objects we're constructing.
+ ArrayIndexVar = CGF.CreateTempAlloca(SizeTy, "object.index");
+ llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
+ CGF.Builder.CreateStore(Zero, ArrayIndexVar);
+
+ // If we are copying an array of scalars or classes with trivial copy
+ // constructors, perform a single aggregate copy.
+ const RecordType *Record = BaseElementTy->getAs<RecordType>();
+ if (!Record ||
+ cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) {
+ // Find the source pointer. We knows it's the last argument because
+ // we know we're in a copy constructor.
+ unsigned SrcArgIndex = Args.size() - 1;
+ llvm::Value *SrcPtr
+ = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(Args[SrcArgIndex].first));
+ LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0);
+
+ // Copy the aggregate.
+ CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
+ LHS.isVolatileQualified());
+ return;
+ }
+
+ // Emit the block variables for the array indices, if any.
+ for (unsigned I = 0, N = MemberInit->getNumArrayIndices(); I != N; ++I)
+ CGF.EmitAutoVarDecl(*MemberInit->getArrayIndex(I));
+ }
+
+ EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0);
+
+ if (!CGF.CGM.getLangOptions().areExceptionsEnabled())
+ return;
+
+ // FIXME: If we have an array of classes w/ non-trivial destructors,
+ // we need to destroy in reverse order of construction along the exception
+ // path.
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ if (!RT)
+ return;
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (!RD->hasTrivialDestructor())
+ CGF.EHStack.pushCleanup<CallMemberDtor>(EHCleanup, Field,
+ RD->getDestructor());
+ }
+}
+
+/// Checks whether the given constructor is a valid subject for the
+/// complete-to-base constructor delegation optimization, i.e.
+/// emitting the complete constructor as a simple call to the base
+/// constructor.
+static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) {
+
+ // Currently we disable the optimization for classes with virtual
+ // bases because (1) the addresses of parameter variables need to be
+ // consistent across all initializers but (2) the delegate function
+ // call necessarily creates a second copy of the parameter variable.
+ //
+ // The limiting example (purely theoretical AFAIK):
+ // struct A { A(int &c) { c++; } };
+ // struct B : virtual A {
+ // B(int count) : A(count) { printf("%d\n", count); }
+ // };
+ // ...although even this example could in principle be emitted as a
+ // delegation since the address of the parameter doesn't escape.
+ if (Ctor->getParent()->getNumVBases()) {
+ // TODO: white-list trivial vbase initializers. This case wouldn't
+ // be subject to the restrictions below.
+
+ // TODO: white-list cases where:
+ // - there are no non-reference parameters to the constructor
+ // - the initializers don't access any non-reference parameters
+ // - the initializers don't take the address of non-reference
+ // parameters
+ // - etc.
+ // If we ever add any of the above cases, remember that:
+ // - function-try-blocks will always blacklist this optimization
+ // - we need to perform the constructor prologue and cleanup in
+ // EmitConstructorBody.
+
+ return false;
+ }
+
+ // We also disable the optimization for variadic functions because
+ // it's impossible to "re-pass" varargs.
+ if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic())
+ return false;
+
+ return true;
+}
+
+/// EmitConstructorBody - Emits the body of the current constructor.
+void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
+ const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
+ CXXCtorType CtorType = CurGD.getCtorType();
+
+ // Before we go any further, try the complete->base constructor
+ // delegation optimization.
+ if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitStopPoint(Builder);
+ EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
+ return;
+ }
+
+ Stmt *Body = Ctor->getBody();
+
+ // Enter the function-try-block before the constructor prologue if
+ // applicable.
+ bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
+ if (IsTryBody)
+ EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
+
+ EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
+
+ // Emit the constructor prologue, i.e. the base and member
+ // initializers.
+ EmitCtorPrologue(Ctor, CtorType, Args);
+
+ // Emit the body of the statement.
+ if (IsTryBody)
+ EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
+ else if (Body)
+ EmitStmt(Body);
+
+ // Emit any cleanup blocks associated with the member or base
+ // initializers, which includes (along the exceptional path) the
+ // destructors for those members and bases that were fully
+ // constructed.
+ PopCleanupBlocks(CleanupDepth);
+
+ if (IsTryBody)
+ ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
+}
+
+/// EmitCtorPrologue - This routine generates necessary code to initialize
+/// base classes and non-static data members belonging to this constructor.
+void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
+ CXXCtorType CtorType,
+ FunctionArgList &Args) {
+ const CXXRecordDecl *ClassDecl = CD->getParent();
+
+ llvm::SmallVector<CXXCtorInitializer *, 8> MemberInitializers;
+
+ for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
+ E = CD->init_end();
+ B != E; ++B) {
+ CXXCtorInitializer *Member = (*B);
+
+ if (Member->isBaseInitializer())
+ EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
+ else
+ MemberInitializers.push_back(Member);
+ }
+
+ InitializeVTablePointers(ClassDecl);
+
+ for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I)
+ EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args);
+}
+
+/// EmitDestructorBody - Emits the body of the current destructor.
+void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
+ CXXDtorType DtorType = CurGD.getDtorType();
+
+ // The call to operator delete in a deleting destructor happens
+ // outside of the function-try-block, which means it's always
+ // possible to delegate the destructor body to the complete
+ // destructor. Do so.
+ if (DtorType == Dtor_Deleting) {
+ EnterDtorCleanups(Dtor, Dtor_Deleting);
+ EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ LoadCXXThis());
+ PopCleanupBlock();
+ return;
+ }
+
+ Stmt *Body = Dtor->getBody();
+
+ // If the body is a function-try-block, enter the try before
+ // anything else.
+ bool isTryBody = (Body && isa<CXXTryStmt>(Body));
+ if (isTryBody)
+ EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
+
+ // Enter the epilogue cleanups.
+ RunCleanupsScope DtorEpilogue(*this);
+
+ // If this is the complete variant, just invoke the base variant;
+ // the epilogue will destruct the virtual bases. But we can't do
+ // this optimization if the body is a function-try-block, because
+ // we'd introduce *two* handler blocks.
+ switch (DtorType) {
+ case Dtor_Deleting: llvm_unreachable("already handled deleting case");
+
+ case Dtor_Complete:
+ // Enter the cleanup scopes for virtual bases.
+ EnterDtorCleanups(Dtor, Dtor_Complete);
+
+ if (!isTryBody) {
+ EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
+ LoadCXXThis());
+ break;
+ }
+ // Fallthrough: act like we're in the base variant.
+
+ case Dtor_Base:
+ // Enter the cleanup scopes for fields and non-virtual bases.
+ EnterDtorCleanups(Dtor, Dtor_Base);
+
+ // Initialize the vtable pointers before entering the body.
+ InitializeVTablePointers(Dtor->getParent());
+
+ if (isTryBody)
+ EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
+ else if (Body)
+ EmitStmt(Body);
+ else {
+ assert(Dtor->isImplicit() && "bodyless dtor not implicit");
+ // nothing to do besides what's in the epilogue
+ }
+ // -fapple-kext must inline any call to this dtor into
+ // the caller's body.
+ if (getContext().getLangOptions().AppleKext)
+ CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
+ break;
+ }
+
+ // Jump out through the epilogue cleanups.
+ DtorEpilogue.ForceCleanup();
+
+ // Exit the try if applicable.
+ if (isTryBody)
+ ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
+}
+
+namespace {
+ /// Call the operator delete associated with the current destructor.
+ struct CallDtorDelete : EHScopeStack::Cleanup {
+ CallDtorDelete() {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
+ CGF.getContext().getTagDeclType(ClassDecl));
+ }
+ };
+
+ struct CallArrayFieldDtor : EHScopeStack::Cleanup {
+ const FieldDecl *Field;
+ CallArrayFieldDtor(const FieldDecl *Field) : Field(Field) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ QualType FieldType = Field->getType();
+ const ConstantArrayType *Array =
+ CGF.getContext().getAsConstantArrayType(FieldType);
+
+ QualType BaseType =
+ CGF.getContext().getBaseElementType(Array->getElementType());
+ const CXXRecordDecl *FieldClassDecl = BaseType->getAsCXXRecordDecl();
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field,
+ // FIXME: Qualifiers?
+ /*CVRQualifiers=*/0);
+
+ const llvm::Type *BasePtr = CGF.ConvertType(BaseType)->getPointerTo();
+ llvm::Value *BaseAddrPtr =
+ CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+ CGF.EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(),
+ Array, BaseAddrPtr);
+ }
+ };
+
+ struct CallFieldDtor : EHScopeStack::Cleanup {
+ const FieldDecl *Field;
+ CallFieldDtor(const FieldDecl *Field) : Field(Field) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXRecordDecl *FieldClassDecl =
+ Field->getType()->getAsCXXRecordDecl();
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field,
+ // FIXME: Qualifiers?
+ /*CVRQualifiers=*/0);
+
+ CGF.EmitCXXDestructorCall(FieldClassDecl->getDestructor(),
+ Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
+ }
+ };
+}
+
+/// EmitDtorEpilogue - Emit all code that comes at the end of class's
+/// destructor. This is to call destructors on members and base classes
+/// in reverse order of their construction.
+void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
+ CXXDtorType DtorType) {
+ assert(!DD->isTrivial() &&
+ "Should not emit dtor epilogue for trivial dtor!");
+
+ // The deleting-destructor phase just needs to call the appropriate
+ // operator delete that Sema picked up.
+ if (DtorType == Dtor_Deleting) {
+ assert(DD->getOperatorDelete() &&
+ "operator delete missing - EmitDtorEpilogue");
+ EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
+ return;
+ }
+
+ const CXXRecordDecl *ClassDecl = DD->getParent();
+
+ // The complete-destructor phase just destructs all the virtual bases.
+ if (DtorType == Dtor_Complete) {
+
+ // We push them in the forward order so that they'll be popped in
+ // the reverse order.
+ for (CXXRecordDecl::base_class_const_iterator I =
+ ClassDecl->vbases_begin(), E = ClassDecl->vbases_end();
+ I != E; ++I) {
+ const CXXBaseSpecifier &Base = *I;
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore trivial destructors.
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup,
+ BaseClassDecl,
+ /*BaseIsVirtual*/ true);
+ }
+
+ return;
+ }
+
+ assert(DtorType == Dtor_Base);
+
+ // Destroy non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I =
+ ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) {
+ const CXXBaseSpecifier &Base = *I;
+
+ // Ignore virtual bases.
+ if (Base.isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();
+
+ // Ignore trivial destructors.
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup,
+ BaseClassDecl,
+ /*BaseIsVirtual*/ false);
+ }
+
+ // Destroy direct fields.
+ llvm::SmallVector<const FieldDecl *, 16> FieldDecls;
+ for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); I != E; ++I) {
+ const FieldDecl *Field = *I;
+
+ QualType FieldType = getContext().getCanonicalType(Field->getType());
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(FieldType);
+ if (Array)
+ FieldType = getContext().getBaseElementType(Array->getElementType());
+
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ if (!RT)
+ continue;
+
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
+ continue;
+
+ if (Array)
+ EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
+ else
+ EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
+ }
+}
+
+/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
+/// for-loop to call the default constructor on individual members of the
+/// array.
+/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the
+/// array type and 'ArrayPtr' points to the beginning fo the array.
+/// It is assumed that all relevant checks have been made by the caller.
+///
+/// \param ZeroInitialization True if each element should be zero-initialized
+/// before it is constructed.
+void
+CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+ const ConstantArrayType *ArrayTy,
+ llvm::Value *ArrayPtr,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization) {
+
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ llvm::Value * NumElements =
+ llvm::ConstantInt::get(SizeTy,
+ getContext().getConstantArrayElementCount(ArrayTy));
+
+ EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd,
+ ZeroInitialization);
+}
+
+void
+CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+ llvm::Value *NumElements,
+ llvm::Value *ArrayPtr,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization) {
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+
+ // Create a temporary for the loop index and initialize it with 0.
+ llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index");
+ llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
+ Builder.CreateStore(Zero, IndexPtr);
+
+ // Start the loop with a block that tests the condition.
+ llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
+
+ EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+
+ // Generate: if (loop-index < number-of-elements fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless");
+ // If the condition is true, execute the body.
+ Builder.CreateCondBr(IsLess, ForBody, AfterFor);
+
+ EmitBlock(ForBody);
+
+ llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
+ // Inside the loop body, emit the constructor call on the array element.
+ Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter,
+ "arrayidx");
+
+ // Zero initialize the storage, if requested.
+ if (ZeroInitialization)
+ EmitNullInitialization(Address,
+ getContext().getTypeDeclType(D->getParent()));
+
+ // C++ [class.temporary]p4:
+ // There are two contexts in which temporaries are destroyed at a different
+ // point than the end of the full-expression. The first context is when a
+ // default constructor is called to initialize an element of an array.
+ // If the constructor has one or more default arguments, the destruction of
+ // every temporary created in a default argument expression is sequenced
+ // before the construction of the next array element, if any.
+
+ // Keep track of the current number of live temporaries.
+ {
+ RunCleanupsScope Scope(*this);
+
+ EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address,
+ ArgBeg, ArgEnd);
+ }
+
+ EmitBlock(ContinueBlock);
+
+ // Emit the increment of the loop counter.
+ llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1);
+ Counter = Builder.CreateLoad(IndexPtr);
+ NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
+ Builder.CreateStore(NextVal, IndexPtr);
+
+ // Finally, branch back up to the condition for the next iteration.
+ EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ EmitBlock(AfterFor, true);
+}
+
+/// EmitCXXAggrDestructorCall - calls the default destructor on array
+/// elements in reverse order of construction.
+void
+CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This) {
+ const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
+ assert(CA && "Do we support VLA for destruction ?");
+ uint64_t ElementCount = getContext().getConstantArrayElementCount(CA);
+
+ const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType());
+ llvm::Value* ElementCountPtr = llvm::ConstantInt::get(SizeLTy, ElementCount);
+ EmitCXXAggrDestructorCall(D, ElementCountPtr, This);
+}
+
+/// EmitCXXAggrDestructorCall - calls the default destructor on array
+/// elements in reverse order of construction.
+void
+CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ llvm::Value *UpperCount,
+ llvm::Value *This) {
+ const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType());
+ llvm::Value *One = llvm::ConstantInt::get(SizeLTy, 1);
+
+ // Create a temporary for the loop index and initialize it with count of
+ // array elements.
+ llvm::Value *IndexPtr = CreateTempAlloca(SizeLTy, "loop.index");
+
+ // Store the number of elements in the index pointer.
+ Builder.CreateStore(UpperCount, IndexPtr);
+
+ // Start the loop with a block that tests the condition.
+ llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
+
+ EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+
+ // Generate: if (loop-index != 0 fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ llvm::Value* zeroConstant =
+ llvm::Constant::getNullValue(SizeLTy);
+ llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant,
+ "isne");
+ // If the condition is true, execute the body.
+ Builder.CreateCondBr(IsNE, ForBody, AfterFor);
+
+ EmitBlock(ForBody);
+
+ llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
+ // Inside the loop body, emit the constructor call on the array element.
+ Counter = Builder.CreateLoad(IndexPtr);
+ Counter = Builder.CreateSub(Counter, One);
+ llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
+ EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Address);
+
+ EmitBlock(ContinueBlock);
+
+ // Emit the decrement of the loop counter.
+ Counter = Builder.CreateLoad(IndexPtr);
+ Counter = Builder.CreateSub(Counter, One, "dec");
+ Builder.CreateStore(Counter, IndexPtr);
+
+ // Finally, branch back up to the condition for the next iteration.
+ EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ EmitBlock(AfterFor, true);
+}
+
+void
+CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
+ CXXCtorType Type, bool ForVirtualBase,
+ llvm::Value *This,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd) {
+ if (D->isTrivial()) {
+ if (ArgBeg == ArgEnd) {
+ // Trivial default constructor, no codegen required.
+ assert(D->isDefaultConstructor() &&
+ "trivial 0-arg ctor not a default ctor");
+ return;
+ }
+
+ assert(ArgBeg + 1 == ArgEnd && "unexpected argcount for trivial ctor");
+ assert(D->isCopyConstructor() && "trivial 1-arg ctor not a copy ctor");
+
+ const Expr *E = (*ArgBeg);
+ QualType Ty = E->getType();
+ llvm::Value *Src = EmitLValue(E).getAddress();
+ EmitAggregateCopy(This, Src, Ty);
+ return;
+ }
+
+ llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase);
+ llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
+
+ EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
+}
+
+void
+CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
+ llvm::Value *This, llvm::Value *Src,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd) {
+ if (D->isTrivial()) {
+ assert(ArgBeg + 1 == ArgEnd && "unexpected argcount for trivial ctor");
+ assert(D->isCopyConstructor() && "trivial 1-arg ctor not a copy ctor");
+ EmitAggregateCopy(This, Src, (*ArgBeg)->getType());
+ return;
+ }
+ llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D,
+ clang::Ctor_Complete);
+ assert(D->isInstance() &&
+ "Trying to emit a member call expr on a static method!");
+
+ const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
+
+ CallArgList Args;
+
+ // Push the this ptr.
+ Args.push_back(std::make_pair(RValue::get(This),
+ D->getThisType(getContext())));
+
+
+ // Push the src ptr.
+ QualType QT = *(FPT->arg_type_begin());
+ const llvm::Type *t = CGM.getTypes().ConvertType(QT);
+ Src = Builder.CreateBitCast(Src, t);
+ Args.push_back(std::make_pair(RValue::get(Src), QT));
+
+ // Skip over first argument (Src).
+ ++ArgBeg;
+ CallExpr::const_arg_iterator Arg = ArgBeg;
+ for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin()+1,
+ E = FPT->arg_type_end(); I != E; ++I, ++Arg) {
+ assert(Arg != ArgEnd && "Running over edge of argument list!");
+ QualType ArgType = *I;
+ Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType),
+ ArgType));
+ }
+ // Either we've emitted all the call args, or we have a call to a
+ // variadic function.
+ assert((Arg == ArgEnd || FPT->isVariadic()) &&
+ "Extra arguments in non-variadic function!");
+ // If we still have any arguments, emit them using the type of the argument.
+ for (; Arg != ArgEnd; ++Arg) {
+ QualType ArgType = Arg->getType();
+ Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType),
+ ArgType));
+ }
+
+ QualType ResultType = FPT->getResultType();
+ EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
+ FPT->getExtInfo()),
+ Callee, ReturnValueSlot(), Args, D);
+}
+
+void
+CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+ CXXCtorType CtorType,
+ const FunctionArgList &Args) {
+ CallArgList DelegateArgs;
+
+ FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
+ assert(I != E && "no parameters to constructor");
+
+ // this
+ DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()),
+ I->second));
+ ++I;
+
+ // vtt
+ if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType),
+ /*ForVirtualBase=*/false)) {
+ QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
+ DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP));
+
+ if (CodeGenVTables::needsVTTParameter(CurGD)) {
+ assert(I != E && "cannot skip vtt parameter, already done with args");
+ assert(I->second == VoidPP && "skipping parameter not of vtt type");
+ ++I;
+ }
+ }
+
+ // Explicit arguments.
+ for (; I != E; ++I) {
+ const VarDecl *Param = I->first;
+ QualType ArgType = Param->getType(); // because we're passing it to itself
+ RValue Arg = EmitDelegateCallArg(Param);
+
+ DelegateArgs.push_back(std::make_pair(Arg, ArgType));
+ }
+
+ EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType),
+ CGM.GetAddrOfCXXConstructor(Ctor, CtorType),
+ ReturnValueSlot(), DelegateArgs, Ctor);
+}
+
+void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ bool ForVirtualBase,
+ llvm::Value *This) {
+ llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type),
+ ForVirtualBase);
+ llvm::Value *Callee = 0;
+ if (getContext().getLangOptions().AppleKext)
+ Callee = BuildAppleKextVirtualDestructorCall(DD, Type,
+ DD->getParent());
+
+ if (!Callee)
+ Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
+
+ EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0);
+}
+
+namespace {
+ struct CallLocalDtor : EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ llvm::Value *Addr;
+
+ CallLocalDtor(const CXXDestructorDecl *D, llvm::Value *Addr)
+ : Dtor(D), Addr(Addr) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false, Addr);
+ }
+ };
+}
+
+void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
+ llvm::Value *Addr) {
+ EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr);
+}
+
+void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
+ CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
+ if (!ClassDecl) return;
+ if (ClassDecl->hasTrivialDestructor()) return;
+
+ const CXXDestructorDecl *D = ClassDecl->getDestructor();
+ PushDestructorCleanup(D, Addr);
+}
+
+llvm::Value *
+CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl) {
+ llvm::Value *VTablePtr = GetVTablePtr(This, Int8PtrTy);
+ int64_t VBaseOffsetOffset =
+ CGM.getVTables().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl);
+
+ llvm::Value *VBaseOffsetPtr =
+ Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset, "vbase.offset.ptr");
+ const llvm::Type *PtrDiffTy =
+ ConvertType(getContext().getPointerDiffType());
+
+ VBaseOffsetPtr = Builder.CreateBitCast(VBaseOffsetPtr,
+ PtrDiffTy->getPointerTo());
+
+ llvm::Value *VBaseOffset = Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset");
+
+ return VBaseOffset;
+}
+
+void
+CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // Compute the address point.
+ llvm::Value *VTableAddressPoint;
+
+ // Check if we need to use a vtable from the VTT.
+ if (CodeGenVTables::needsVTTParameter(CurGD) &&
+ (RD->getNumVBases() || NearestVBase)) {
+ // Get the secondary vpointer index.
+ uint64_t VirtualPointerIndex =
+ CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
+
+ /// Load the VTT.
+ llvm::Value *VTT = LoadCXXVTT();
+ if (VirtualPointerIndex)
+ VTT = Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
+
+ // And load the address point from the VTT.
+ VTableAddressPoint = Builder.CreateLoad(VTT);
+ } else {
+ uint64_t AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass);
+ VTableAddressPoint =
+ Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
+ }
+
+ // Compute where to store the address point.
+ llvm::Value *VirtualOffset = 0;
+ uint64_t NonVirtualOffset = 0;
+
+ if (CodeGenVTables::needsVTTParameter(CurGD) && NearestVBase) {
+ // We need to use the virtual base offset offset because the virtual base
+ // might have a different offset in the most derived class.
+ VirtualOffset = GetVirtualBaseClassOffset(LoadCXXThis(), VTableClass,
+ NearestVBase);
+ NonVirtualOffset = OffsetFromNearestVBase / 8;
+ } else {
+ // We can just use the base offset in the complete class.
+ NonVirtualOffset = Base.getBaseOffset() / 8;
+ }
+
+ // Apply the offsets.
+ llvm::Value *VTableField = LoadCXXThis();
+
+ if (NonVirtualOffset || VirtualOffset)
+ VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField,
+ NonVirtualOffset,
+ VirtualOffset);
+
+ // Finally, store the address point.
+ const llvm::Type *AddressPointPtrTy =
+ VTableAddressPoint->getType()->getPointerTo();
+ VTableField = Builder.CreateBitCast(VTableField, AddressPointPtrTy);
+ Builder.CreateStore(VTableAddressPoint, VTableField);
+}
+
+void
+CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
+ bool BaseIsNonVirtualPrimaryBase,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy& VBases) {
+ // If this base is a non-virtual primary base the address point has already
+ // been set.
+ if (!BaseIsNonVirtualPrimaryBase) {
+ // Initialize the vtable pointer for this base.
+ InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
+ VTable, VTableClass);
+ }
+
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // Traverse bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ CXXRecordDecl *BaseDecl
+ = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore classes without a vtable.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
+ uint64_t BaseOffset;
+ uint64_t BaseOffsetFromNearestVBase;
+ bool BaseDeclIsNonVirtualPrimaryBase;
+
+ if (I->isVirtual()) {
+ // Check if we've visited this virtual base before.
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ const ASTRecordLayout &Layout =
+ getContext().getASTRecordLayout(VTableClass);
+
+ BaseOffset = Layout.getVBaseClassOffsetInBits(BaseDecl);
+ BaseOffsetFromNearestVBase = 0;
+ BaseDeclIsNonVirtualPrimaryBase = false;
+ } else {
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+
+ BaseOffset =
+ Base.getBaseOffset() + Layout.getBaseClassOffsetInBits(BaseDecl);
+ BaseOffsetFromNearestVBase =
+ OffsetFromNearestVBase + Layout.getBaseClassOffsetInBits(BaseDecl);
+ BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
+ }
+
+ InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
+ I->isVirtual() ? BaseDecl : NearestVBase,
+ BaseOffsetFromNearestVBase,
+ BaseDeclIsNonVirtualPrimaryBase,
+ VTable, VTableClass, VBases);
+ }
+}
+
+void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
+ // Ignore classes without a vtable.
+ if (!RD->isDynamicClass())
+ return;
+
+ // Get the VTable.
+ llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD);
+
+ // Initialize the vtable pointers for this class and all of its bases.
+ VisitedVirtualBasesSetTy VBases;
+ InitializeVTablePointers(BaseSubobject(RD, 0), /*NearestVBase=*/0,
+ /*OffsetFromNearestVBase=*/0,
+ /*BaseIsNonVirtualPrimaryBase=*/false,
+ VTable, RD, VBases);
+}
+
+llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This,
+ const llvm::Type *Ty) {
+ llvm::Value *VTablePtrSrc = Builder.CreateBitCast(This, Ty->getPointerTo());
+ return Builder.CreateLoad(VTablePtrSrc, "vtable");
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
new file mode 100644
index 0000000..374ede8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -0,0 +1,1144 @@
+//===--- CGCleanup.cpp - Bookkeeping and code emission for cleanups -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code dealing with the IR generation for cleanups
+// and related information.
+//
+// A "cleanup" is a piece of code which needs to be executed whenever
+// control transfers out of a particular scope. This can be
+// conditionalized to occur only on exceptional control flow, only on
+// normal control flow, or both.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CGCleanup.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) {
+ if (rv.isScalar())
+ return DominatingLLVMValue::needsSaving(rv.getScalarVal());
+ if (rv.isAggregate())
+ return DominatingLLVMValue::needsSaving(rv.getAggregateAddr());
+ return true;
+}
+
+DominatingValue<RValue>::saved_type
+DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
+ if (rv.isScalar()) {
+ llvm::Value *V = rv.getScalarVal();
+
+ // These automatically dominate and don't need to be saved.
+ if (!DominatingLLVMValue::needsSaving(V))
+ return saved_type(V, ScalarLiteral);
+
+ // Everything else needs an alloca.
+ llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
+ CGF.Builder.CreateStore(V, addr);
+ return saved_type(addr, ScalarAddress);
+ }
+
+ if (rv.isComplex()) {
+ CodeGenFunction::ComplexPairTy V = rv.getComplexVal();
+ const llvm::Type *ComplexTy =
+ llvm::StructType::get(CGF.getLLVMContext(),
+ V.first->getType(), V.second->getType(),
+ (void*) 0);
+ llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
+ CGF.StoreComplexToAddr(V, addr, /*volatile*/ false);
+ return saved_type(addr, ComplexAddress);
+ }
+
+ assert(rv.isAggregate());
+ llvm::Value *V = rv.getAggregateAddr(); // TODO: volatile?
+ if (!DominatingLLVMValue::needsSaving(V))
+ return saved_type(V, AggregateLiteral);
+
+ llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
+ CGF.Builder.CreateStore(V, addr);
+ return saved_type(addr, AggregateAddress);
+}
+
+/// Given a saved r-value produced by SaveRValue, perform the code
+/// necessary to restore it to usability at the current insertion
+/// point.
+RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
+ switch (K) {
+ case ScalarLiteral:
+ return RValue::get(Value);
+ case ScalarAddress:
+ return RValue::get(CGF.Builder.CreateLoad(Value));
+ case AggregateLiteral:
+ return RValue::getAggregate(Value);
+ case AggregateAddress:
+ return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
+ case ComplexAddress:
+ return RValue::getComplex(CGF.LoadComplexFromAddr(Value, false));
+ }
+
+ llvm_unreachable("bad saved r-value kind");
+ return RValue();
+}
+
+/// Push an entry of the given size onto this protected-scope stack.
+char *EHScopeStack::allocate(size_t Size) {
+ if (!StartOfBuffer) {
+ unsigned Capacity = 1024;
+ while (Capacity < Size) Capacity *= 2;
+ StartOfBuffer = new char[Capacity];
+ StartOfData = EndOfBuffer = StartOfBuffer + Capacity;
+ } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) {
+ unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer;
+ unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer);
+
+ unsigned NewCapacity = CurrentCapacity;
+ do {
+ NewCapacity *= 2;
+ } while (NewCapacity < UsedCapacity + Size);
+
+ char *NewStartOfBuffer = new char[NewCapacity];
+ char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity;
+ char *NewStartOfData = NewEndOfBuffer - UsedCapacity;
+ memcpy(NewStartOfData, StartOfData, UsedCapacity);
+ delete [] StartOfBuffer;
+ StartOfBuffer = NewStartOfBuffer;
+ EndOfBuffer = NewEndOfBuffer;
+ StartOfData = NewStartOfData;
+ }
+
+ assert(StartOfBuffer + Size <= StartOfData);
+ StartOfData -= Size;
+ return StartOfData;
+}
+
+EHScopeStack::stable_iterator
+EHScopeStack::getEnclosingEHCleanup(iterator it) const {
+ assert(it != end());
+ do {
+ if (isa<EHCleanupScope>(*it)) {
+ if (cast<EHCleanupScope>(*it).isEHCleanup())
+ return stabilize(it);
+ return cast<EHCleanupScope>(*it).getEnclosingEHCleanup();
+ }
+ ++it;
+ } while (it != end());
+ return stable_end();
+}
+
+
+void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
+ assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned");
+ char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
+ bool IsNormalCleanup = Kind & NormalCleanup;
+ bool IsEHCleanup = Kind & EHCleanup;
+ bool IsActive = !(Kind & InactiveCleanup);
+ EHCleanupScope *Scope =
+ new (Buffer) EHCleanupScope(IsNormalCleanup,
+ IsEHCleanup,
+ IsActive,
+ Size,
+ BranchFixups.size(),
+ InnermostNormalCleanup,
+ InnermostEHCleanup);
+ if (IsNormalCleanup)
+ InnermostNormalCleanup = stable_begin();
+ if (IsEHCleanup)
+ InnermostEHCleanup = stable_begin();
+
+ return Scope->getCleanupBuffer();
+}
+
+void EHScopeStack::popCleanup() {
+ assert(!empty() && "popping exception stack when not empty");
+
+ assert(isa<EHCleanupScope>(*begin()));
+ EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
+ InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
+ InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
+ StartOfData += Cleanup.getAllocatedSize();
+
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
+ // Destroy the cleanup.
+ Cleanup.~EHCleanupScope();
+
+ // Check whether we can shrink the branch-fixups stack.
+ if (!BranchFixups.empty()) {
+ // If we no longer have any normal cleanups, all the fixups are
+ // complete.
+ if (!hasNormalCleanups())
+ BranchFixups.clear();
+
+ // Otherwise we can still trim out unnecessary nulls.
+ else
+ popNullFixups();
+ }
+}
+
+EHFilterScope *EHScopeStack::pushFilter(unsigned NumFilters) {
+ char *Buffer = allocate(EHFilterScope::getSizeForNumFilters(NumFilters));
+ CatchDepth++;
+ return new (Buffer) EHFilterScope(NumFilters);
+}
+
+void EHScopeStack::popFilter() {
+ assert(!empty() && "popping exception stack when not empty");
+
+ EHFilterScope &Filter = cast<EHFilterScope>(*begin());
+ StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters());
+
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
+ assert(CatchDepth > 0 && "mismatched filter push/pop");
+ CatchDepth--;
+}
+
+EHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) {
+ char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers));
+ CatchDepth++;
+ EHCatchScope *Scope = new (Buffer) EHCatchScope(NumHandlers);
+ for (unsigned I = 0; I != NumHandlers; ++I)
+ Scope->getHandlers()[I].Index = getNextEHDestIndex();
+ return Scope;
+}
+
+void EHScopeStack::pushTerminate() {
+ char *Buffer = allocate(EHTerminateScope::getSize());
+ CatchDepth++;
+ new (Buffer) EHTerminateScope(getNextEHDestIndex());
+}
+
+/// Remove any 'null' fixups on the stack. However, we can't pop more
+/// fixups than the fixup depth on the innermost normal cleanup, or
+/// else fixups that we try to add to that cleanup will end up in the
+/// wrong place. We *could* try to shrink fixup depths, but that's
+/// actually a lot of work for little benefit.
+void EHScopeStack::popNullFixups() {
+ // We expect this to only be called when there's still an innermost
+ // normal cleanup; otherwise there really shouldn't be any fixups.
+ assert(hasNormalCleanups());
+
+ EHScopeStack::iterator it = find(InnermostNormalCleanup);
+ unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth();
+ assert(BranchFixups.size() >= MinSize && "fixup stack out of order");
+
+ while (BranchFixups.size() > MinSize &&
+ BranchFixups.back().Destination == 0)
+ BranchFixups.pop_back();
+}
+
+void CodeGenFunction::initFullExprCleanup() {
+ // Create a variable to decide whether the cleanup needs to be run.
+ llvm::AllocaInst *active
+ = CreateTempAlloca(Builder.getInt1Ty(), "cleanup.cond");
+
+ // Initialize it to false at a site that's guaranteed to be run
+ // before each evaluation.
+ llvm::BasicBlock *block = OutermostConditional->getStartingBlock();
+ new llvm::StoreInst(Builder.getFalse(), active, &block->back());
+
+ // Initialize it to true at the current location.
+ Builder.CreateStore(Builder.getTrue(), active);
+
+ // Set that as the active flag in the cleanup.
+ EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
+ assert(cleanup.getActiveFlag() == 0 && "cleanup already has active flag?");
+ cleanup.setActiveFlag(active);
+
+ if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup();
+ if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup();
+}
+
+EHScopeStack::Cleanup::~Cleanup() {
+ llvm_unreachable("Cleanup is indestructable");
+}
+
+/// All the branch fixups on the EH stack have propagated out past the
+/// outermost normal cleanup; resolve them all by adding cases to the
+/// given switch instruction.
+static void ResolveAllBranchFixups(CodeGenFunction &CGF,
+ llvm::SwitchInst *Switch,
+ llvm::BasicBlock *CleanupEntry) {
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded;
+
+ for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) {
+ // Skip this fixup if its destination isn't set.
+ BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I);
+ if (Fixup.Destination == 0) continue;
+
+ // If there isn't an OptimisticBranchBlock, then InitialBranch is
+ // still pointing directly to its destination; forward it to the
+ // appropriate cleanup entry. This is required in the specific
+ // case of
+ // { std::string s; goto lbl; }
+ // lbl:
+ // i.e. where there's an unresolved fixup inside a single cleanup
+ // entry which we're currently popping.
+ if (Fixup.OptimisticBranchBlock == 0) {
+ new llvm::StoreInst(CGF.Builder.getInt32(Fixup.DestinationIndex),
+ CGF.getNormalCleanupDestSlot(),
+ Fixup.InitialBranch);
+ Fixup.InitialBranch->setSuccessor(0, CleanupEntry);
+ }
+
+ // Don't add this case to the switch statement twice.
+ if (!CasesAdded.insert(Fixup.Destination)) continue;
+
+ Switch->addCase(CGF.Builder.getInt32(Fixup.DestinationIndex),
+ Fixup.Destination);
+ }
+
+ CGF.EHStack.clearFixups();
+}
+
+/// Transitions the terminator of the given exit-block of a cleanup to
+/// be a cleanup switch.
+static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
+ llvm::BasicBlock *Block) {
+ // If it's a branch, turn it into a switch whose default
+ // destination is its original target.
+ llvm::TerminatorInst *Term = Block->getTerminator();
+ assert(Term && "can't transition block without terminator");
+
+ if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
+ assert(Br->isUnconditional());
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(CGF.getNormalCleanupDestSlot(), "cleanup.dest", Term);
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block);
+ Br->eraseFromParent();
+ return Switch;
+ } else {
+ return cast<llvm::SwitchInst>(Term);
+ }
+}
+
+void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) {
+ assert(Block && "resolving a null target block");
+ if (!EHStack.getNumBranchFixups()) return;
+
+ assert(EHStack.hasNormalCleanups() &&
+ "branch fixups exist with no normal cleanups on stack");
+
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> ModifiedOptimisticBlocks;
+ bool ResolvedAny = false;
+
+ for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) {
+ // Skip this fixup if its destination doesn't match.
+ BranchFixup &Fixup = EHStack.getBranchFixup(I);
+ if (Fixup.Destination != Block) continue;
+
+ Fixup.Destination = 0;
+ ResolvedAny = true;
+
+ // If it doesn't have an optimistic branch block, LatestBranch is
+ // already pointing to the right place.
+ llvm::BasicBlock *BranchBB = Fixup.OptimisticBranchBlock;
+ if (!BranchBB)
+ continue;
+
+ // Don't process the same optimistic branch block twice.
+ if (!ModifiedOptimisticBlocks.insert(BranchBB))
+ continue;
+
+ llvm::SwitchInst *Switch = TransitionToCleanupSwitch(*this, BranchBB);
+
+ // Add a case to the switch.
+ Switch->addCase(Builder.getInt32(Fixup.DestinationIndex), Block);
+ }
+
+ if (ResolvedAny)
+ EHStack.popNullFixups();
+}
+
+/// Pops cleanup blocks until the given savepoint is reached.
+void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) {
+ assert(Old.isValid());
+
+ while (EHStack.stable_begin() != Old) {
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
+
+ // As long as Old strictly encloses the scope's enclosing normal
+ // cleanup, we're going to emit another normal cleanup which
+ // fallthrough can propagate through.
+ bool FallThroughIsBranchThrough =
+ Old.strictlyEncloses(Scope.getEnclosingNormalCleanup());
+
+ PopCleanupBlock(FallThroughIsBranchThrough);
+ }
+}
+
+static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF,
+ EHCleanupScope &Scope) {
+ assert(Scope.isNormalCleanup());
+ llvm::BasicBlock *Entry = Scope.getNormalBlock();
+ if (!Entry) {
+ Entry = CGF.createBasicBlock("cleanup");
+ Scope.setNormalBlock(Entry);
+ }
+ return Entry;
+}
+
+static llvm::BasicBlock *CreateEHEntry(CodeGenFunction &CGF,
+ EHCleanupScope &Scope) {
+ assert(Scope.isEHCleanup());
+ llvm::BasicBlock *Entry = Scope.getEHBlock();
+ if (!Entry) {
+ Entry = CGF.createBasicBlock("eh.cleanup");
+ Scope.setEHBlock(Entry);
+ }
+ return Entry;
+}
+
+/// Attempts to reduce a cleanup's entry block to a fallthrough. This
+/// is basically llvm::MergeBlockIntoPredecessor, except
+/// simplified/optimized for the tighter constraints on cleanup blocks.
+///
+/// Returns the new block, whatever it is.
+static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF,
+ llvm::BasicBlock *Entry) {
+ llvm::BasicBlock *Pred = Entry->getSinglePredecessor();
+ if (!Pred) return Entry;
+
+ llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator());
+ if (!Br || Br->isConditional()) return Entry;
+ assert(Br->getSuccessor(0) == Entry);
+
+ // If we were previously inserting at the end of the cleanup entry
+ // block, we'll need to continue inserting at the end of the
+ // predecessor.
+ bool WasInsertBlock = CGF.Builder.GetInsertBlock() == Entry;
+ assert(!WasInsertBlock || CGF.Builder.GetInsertPoint() == Entry->end());
+
+ // Kill the branch.
+ Br->eraseFromParent();
+
+ // Merge the blocks.
+ Pred->getInstList().splice(Pred->end(), Entry->getInstList());
+
+ // Replace all uses of the entry with the predecessor, in case there
+ // are phis in the cleanup.
+ Entry->replaceAllUsesWith(Pred);
+
+ // Kill the entry block.
+ Entry->eraseFromParent();
+
+ if (WasInsertBlock)
+ CGF.Builder.SetInsertPoint(Pred);
+
+ return Pred;
+}
+
+static void EmitCleanup(CodeGenFunction &CGF,
+ EHScopeStack::Cleanup *Fn,
+ bool ForEH,
+ llvm::Value *ActiveFlag) {
+ // EH cleanups always occur within a terminate scope.
+ if (ForEH) CGF.EHStack.pushTerminate();
+
+ // If there's an active flag, load it and skip the cleanup if it's
+ // false.
+ llvm::BasicBlock *ContBB = 0;
+ if (ActiveFlag) {
+ ContBB = CGF.createBasicBlock("cleanup.done");
+ llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action");
+ llvm::Value *IsActive
+ = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active");
+ CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB);
+ CGF.EmitBlock(CleanupBB);
+ }
+
+ // Ask the cleanup to emit itself.
+ Fn->Emit(CGF, ForEH);
+ assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?");
+
+ // Emit the continuation block if there was an active flag.
+ if (ActiveFlag)
+ CGF.EmitBlock(ContBB);
+
+ // Leave the terminate scope.
+ if (ForEH) CGF.EHStack.popTerminate();
+}
+
+static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
+ llvm::BasicBlock *From,
+ llvm::BasicBlock *To) {
+ // Exit is the exit block of a cleanup, so it always terminates in
+ // an unconditional branch or a switch.
+ llvm::TerminatorInst *Term = Exit->getTerminator();
+
+ if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
+ assert(Br->isUnconditional() && Br->getSuccessor(0) == From);
+ Br->setSuccessor(0, To);
+ } else {
+ llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Term);
+ for (unsigned I = 0, E = Switch->getNumSuccessors(); I != E; ++I)
+ if (Switch->getSuccessor(I) == From)
+ Switch->setSuccessor(I, To);
+ }
+}
+
+/// Pops a cleanup block. If the block includes a normal cleanup, the
+/// current insertion point is threaded through the cleanup, as are
+/// any branch fixups on the cleanup.
+void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
+ assert(!EHStack.empty() && "cleanup stack is empty!");
+ assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!");
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
+ assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups());
+
+ // Remember activation information.
+ bool IsActive = Scope.isActive();
+ llvm::Value *NormalActiveFlag =
+ Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() : 0;
+ llvm::Value *EHActiveFlag =
+ Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() : 0;
+
+ // Check whether we need an EH cleanup. This is only true if we've
+ // generated a lazy EH cleanup block.
+ bool RequiresEHCleanup = Scope.hasEHBranches();
+
+ // Check the three conditions which might require a normal cleanup:
+
+ // - whether there are branch fix-ups through this cleanup
+ unsigned FixupDepth = Scope.getFixupDepth();
+ bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth;
+
+ // - whether there are branch-throughs or branch-afters
+ bool HasExistingBranches = Scope.hasBranches();
+
+ // - whether there's a fallthrough
+ llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock();
+ bool HasFallthrough = (FallthroughSource != 0 && IsActive);
+
+ // Branch-through fall-throughs leave the insertion point set to the
+ // end of the last cleanup, which points to the current scope. The
+ // rest of IR gen doesn't need to worry about this; it only happens
+ // during the execution of PopCleanupBlocks().
+ bool HasPrebranchedFallthrough =
+ (FallthroughSource && FallthroughSource->getTerminator());
+
+ // If this is a normal cleanup, then having a prebranched
+ // fallthrough implies that the fallthrough source unconditionally
+ // jumps here.
+ assert(!Scope.isNormalCleanup() || !HasPrebranchedFallthrough ||
+ (Scope.getNormalBlock() &&
+ FallthroughSource->getTerminator()->getSuccessor(0)
+ == Scope.getNormalBlock()));
+
+ bool RequiresNormalCleanup = false;
+ if (Scope.isNormalCleanup() &&
+ (HasFixups || HasExistingBranches || HasFallthrough)) {
+ RequiresNormalCleanup = true;
+ }
+
+ // Even if we don't need the normal cleanup, we might still have
+ // prebranched fallthrough to worry about.
+ if (Scope.isNormalCleanup() && !RequiresNormalCleanup &&
+ HasPrebranchedFallthrough) {
+ assert(!IsActive);
+
+ llvm::BasicBlock *NormalEntry = Scope.getNormalBlock();
+
+ // If we're branching through this cleanup, just forward the
+ // prebranched fallthrough to the next cleanup, leaving the insert
+ // point in the old block.
+ if (FallthroughIsBranchThrough) {
+ EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup());
+ llvm::BasicBlock *EnclosingEntry =
+ CreateNormalEntry(*this, cast<EHCleanupScope>(S));
+
+ ForwardPrebranchedFallthrough(FallthroughSource,
+ NormalEntry, EnclosingEntry);
+ assert(NormalEntry->use_empty() &&
+ "uses of entry remain after forwarding?");
+ delete NormalEntry;
+
+ // Otherwise, we're branching out; just emit the next block.
+ } else {
+ EmitBlock(NormalEntry);
+ SimplifyCleanupEntry(*this, NormalEntry);
+ }
+ }
+
+ // If we don't need the cleanup at all, we're done.
+ if (!RequiresNormalCleanup && !RequiresEHCleanup) {
+ EHStack.popCleanup(); // safe because there are no fixups
+ assert(EHStack.getNumBranchFixups() == 0 ||
+ EHStack.hasNormalCleanups());
+ return;
+ }
+
+ // Copy the cleanup emission data out. Note that SmallVector
+ // guarantees maximal alignment for its buffer regardless of its
+ // type parameter.
+ llvm::SmallVector<char, 8*sizeof(void*)> CleanupBuffer;
+ CleanupBuffer.reserve(Scope.getCleanupSize());
+ memcpy(CleanupBuffer.data(),
+ Scope.getCleanupBuffer(), Scope.getCleanupSize());
+ CleanupBuffer.set_size(Scope.getCleanupSize());
+ EHScopeStack::Cleanup *Fn =
+ reinterpret_cast<EHScopeStack::Cleanup*>(CleanupBuffer.data());
+
+ // We want to emit the EH cleanup after the normal cleanup, but go
+ // ahead and do the setup for the EH cleanup while the scope is still
+ // alive.
+ llvm::BasicBlock *EHEntry = 0;
+ llvm::SmallVector<llvm::Instruction*, 2> EHInstsToAppend;
+ if (RequiresEHCleanup) {
+ EHEntry = CreateEHEntry(*this, Scope);
+
+ // Figure out the branch-through dest if necessary.
+ llvm::BasicBlock *EHBranchThroughDest = 0;
+ if (Scope.hasEHBranchThroughs()) {
+ assert(Scope.getEnclosingEHCleanup() != EHStack.stable_end());
+ EHScope &S = *EHStack.find(Scope.getEnclosingEHCleanup());
+ EHBranchThroughDest = CreateEHEntry(*this, cast<EHCleanupScope>(S));
+ }
+
+ // If we have exactly one branch-after and no branch-throughs, we
+ // can dispatch it without a switch.
+ if (!Scope.hasEHBranchThroughs() &&
+ Scope.getNumEHBranchAfters() == 1) {
+ assert(!EHBranchThroughDest);
+
+ // TODO: remove the spurious eh.cleanup.dest stores if this edge
+ // never went through any switches.
+ llvm::BasicBlock *BranchAfterDest = Scope.getEHBranchAfterBlock(0);
+ EHInstsToAppend.push_back(llvm::BranchInst::Create(BranchAfterDest));
+
+ // Otherwise, if we have any branch-afters, we need a switch.
+ } else if (Scope.getNumEHBranchAfters()) {
+ // The default of the switch belongs to the branch-throughs if
+ // they exist.
+ llvm::BasicBlock *Default =
+ (EHBranchThroughDest ? EHBranchThroughDest : getUnreachableBlock());
+
+ const unsigned SwitchCapacity = Scope.getNumEHBranchAfters();
+
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(getEHCleanupDestSlot(), "cleanup.dest");
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
+
+ EHInstsToAppend.push_back(Load);
+ EHInstsToAppend.push_back(Switch);
+
+ for (unsigned I = 0, E = Scope.getNumEHBranchAfters(); I != E; ++I)
+ Switch->addCase(Scope.getEHBranchAfterIndex(I),
+ Scope.getEHBranchAfterBlock(I));
+
+ // Otherwise, we have only branch-throughs; jump to the next EH
+ // cleanup.
+ } else {
+ assert(EHBranchThroughDest);
+ EHInstsToAppend.push_back(llvm::BranchInst::Create(EHBranchThroughDest));
+ }
+ }
+
+ if (!RequiresNormalCleanup) {
+ EHStack.popCleanup();
+ } else {
+ // If we have a fallthrough and no other need for the cleanup,
+ // emit it directly.
+ if (HasFallthrough && !HasPrebranchedFallthrough &&
+ !HasFixups && !HasExistingBranches) {
+
+ // Fixups can cause us to optimistically create a normal block,
+ // only to later have no real uses for it. Just delete it in
+ // this case.
+ // TODO: we can potentially simplify all the uses after this.
+ if (Scope.getNormalBlock()) {
+ Scope.getNormalBlock()->replaceAllUsesWith(getUnreachableBlock());
+ delete Scope.getNormalBlock();
+ }
+
+ EHStack.popCleanup();
+
+ EmitCleanup(*this, Fn, /*ForEH*/ false, NormalActiveFlag);
+
+ // Otherwise, the best approach is to thread everything through
+ // the cleanup block and then try to clean up after ourselves.
+ } else {
+ // Force the entry block to exist.
+ llvm::BasicBlock *NormalEntry = CreateNormalEntry(*this, Scope);
+
+ // I. Set up the fallthrough edge in.
+
+ // If there's a fallthrough, we need to store the cleanup
+ // destination index. For fall-throughs this is always zero.
+ if (HasFallthrough) {
+ if (!HasPrebranchedFallthrough)
+ Builder.CreateStore(Builder.getInt32(0), getNormalCleanupDestSlot());
+
+ // Otherwise, clear the IP if we don't have fallthrough because
+ // the cleanup is inactive. We don't need to save it because
+ // it's still just FallthroughSource.
+ } else if (FallthroughSource) {
+ assert(!IsActive && "source without fallthrough for active cleanup");
+ Builder.ClearInsertionPoint();
+ }
+
+ // II. Emit the entry block. This implicitly branches to it if
+ // we have fallthrough. All the fixups and existing branches
+ // should already be branched to it.
+ EmitBlock(NormalEntry);
+
+ // III. Figure out where we're going and build the cleanup
+ // epilogue.
+
+ bool HasEnclosingCleanups =
+ (Scope.getEnclosingNormalCleanup() != EHStack.stable_end());
+
+ // Compute the branch-through dest if we need it:
+ // - if there are branch-throughs threaded through the scope
+ // - if fall-through is a branch-through
+ // - if there are fixups that will be optimistically forwarded
+ // to the enclosing cleanup
+ llvm::BasicBlock *BranchThroughDest = 0;
+ if (Scope.hasBranchThroughs() ||
+ (FallthroughSource && FallthroughIsBranchThrough) ||
+ (HasFixups && HasEnclosingCleanups)) {
+ assert(HasEnclosingCleanups);
+ EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup());
+ BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S));
+ }
+
+ llvm::BasicBlock *FallthroughDest = 0;
+ llvm::SmallVector<llvm::Instruction*, 2> InstsToAppend;
+
+ // If there's exactly one branch-after and no other threads,
+ // we can route it without a switch.
+ if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough &&
+ Scope.getNumBranchAfters() == 1) {
+ assert(!BranchThroughDest || !IsActive);
+
+ // TODO: clean up the possibly dead stores to the cleanup dest slot.
+ llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
+ InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter));
+
+ // Build a switch-out if we need it:
+ // - if there are branch-afters threaded through the scope
+ // - if fall-through is a branch-after
+ // - if there are fixups that have nowhere left to go and
+ // so must be immediately resolved
+ } else if (Scope.getNumBranchAfters() ||
+ (HasFallthrough && !FallthroughIsBranchThrough) ||
+ (HasFixups && !HasEnclosingCleanups)) {
+
+ llvm::BasicBlock *Default =
+ (BranchThroughDest ? BranchThroughDest : getUnreachableBlock());
+
+ // TODO: base this on the number of branch-afters and fixups
+ const unsigned SwitchCapacity = 10;
+
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(getNormalCleanupDestSlot(), "cleanup.dest");
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
+
+ InstsToAppend.push_back(Load);
+ InstsToAppend.push_back(Switch);
+
+ // Branch-after fallthrough.
+ if (FallthroughSource && !FallthroughIsBranchThrough) {
+ FallthroughDest = createBasicBlock("cleanup.cont");
+ if (HasFallthrough)
+ Switch->addCase(Builder.getInt32(0), FallthroughDest);
+ }
+
+ for (unsigned I = 0, E = Scope.getNumBranchAfters(); I != E; ++I) {
+ Switch->addCase(Scope.getBranchAfterIndex(I),
+ Scope.getBranchAfterBlock(I));
+ }
+
+ // If there aren't any enclosing cleanups, we can resolve all
+ // the fixups now.
+ if (HasFixups && !HasEnclosingCleanups)
+ ResolveAllBranchFixups(*this, Switch, NormalEntry);
+ } else {
+ // We should always have a branch-through destination in this case.
+ assert(BranchThroughDest);
+ InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest));
+ }
+
+ // IV. Pop the cleanup and emit it.
+ EHStack.popCleanup();
+ assert(EHStack.hasNormalCleanups() == HasEnclosingCleanups);
+
+ EmitCleanup(*this, Fn, /*ForEH*/ false, NormalActiveFlag);
+
+ // Append the prepared cleanup prologue from above.
+ llvm::BasicBlock *NormalExit = Builder.GetInsertBlock();
+ for (unsigned I = 0, E = InstsToAppend.size(); I != E; ++I)
+ NormalExit->getInstList().push_back(InstsToAppend[I]);
+
+ // Optimistically hope that any fixups will continue falling through.
+ for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups();
+ I < E; ++I) {
+ BranchFixup &Fixup = EHStack.getBranchFixup(I);
+ if (!Fixup.Destination) continue;
+ if (!Fixup.OptimisticBranchBlock) {
+ new llvm::StoreInst(Builder.getInt32(Fixup.DestinationIndex),
+ getNormalCleanupDestSlot(),
+ Fixup.InitialBranch);
+ Fixup.InitialBranch->setSuccessor(0, NormalEntry);
+ }
+ Fixup.OptimisticBranchBlock = NormalExit;
+ }
+
+ // V. Set up the fallthrough edge out.
+
+ // Case 1: a fallthrough source exists but shouldn't branch to
+ // the cleanup because the cleanup is inactive.
+ if (!HasFallthrough && FallthroughSource) {
+ assert(!IsActive);
+
+ // If we have a prebranched fallthrough, that needs to be
+ // forwarded to the right block.
+ if (HasPrebranchedFallthrough) {
+ llvm::BasicBlock *Next;
+ if (FallthroughIsBranchThrough) {
+ Next = BranchThroughDest;
+ assert(!FallthroughDest);
+ } else {
+ Next = FallthroughDest;
+ }
+
+ ForwardPrebranchedFallthrough(FallthroughSource, NormalEntry, Next);
+ }
+ Builder.SetInsertPoint(FallthroughSource);
+
+ // Case 2: a fallthrough source exists and should branch to the
+ // cleanup, but we're not supposed to branch through to the next
+ // cleanup.
+ } else if (HasFallthrough && FallthroughDest) {
+ assert(!FallthroughIsBranchThrough);
+ EmitBlock(FallthroughDest);
+
+ // Case 3: a fallthrough source exists and should branch to the
+ // cleanup and then through to the next.
+ } else if (HasFallthrough) {
+ // Everything is already set up for this.
+
+ // Case 4: no fallthrough source exists.
+ } else {
+ Builder.ClearInsertionPoint();
+ }
+
+ // VI. Assorted cleaning.
+
+ // Check whether we can merge NormalEntry into a single predecessor.
+ // This might invalidate (non-IR) pointers to NormalEntry.
+ llvm::BasicBlock *NewNormalEntry =
+ SimplifyCleanupEntry(*this, NormalEntry);
+
+ // If it did invalidate those pointers, and NormalEntry was the same
+ // as NormalExit, go back and patch up the fixups.
+ if (NewNormalEntry != NormalEntry && NormalEntry == NormalExit)
+ for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups();
+ I < E; ++I)
+ EHStack.getBranchFixup(I).OptimisticBranchBlock = NewNormalEntry;
+ }
+ }
+
+ assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0);
+
+ // Emit the EH cleanup if required.
+ if (RequiresEHCleanup) {
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ EmitBlock(EHEntry);
+ EmitCleanup(*this, Fn, /*ForEH*/ true, EHActiveFlag);
+
+ // Append the prepared cleanup prologue from above.
+ llvm::BasicBlock *EHExit = Builder.GetInsertBlock();
+ for (unsigned I = 0, E = EHInstsToAppend.size(); I != E; ++I)
+ EHExit->getInstList().push_back(EHInstsToAppend[I]);
+
+ Builder.restoreIP(SavedIP);
+
+ SimplifyCleanupEntry(*this, EHEntry);
+ }
+}
+
+/// Terminate the current block by emitting a branch which might leave
+/// the current cleanup-protected scope. The target scope may not yet
+/// be known, in which case this will require a fixup.
+///
+/// As a side-effect, this method clears the insertion point.
+void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
+ assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup())
+ && "stale jump destination");
+
+ if (!HaveInsertPoint())
+ return;
+
+ // Create the branch.
+ llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
+
+ // Calculate the innermost active normal cleanup.
+ EHScopeStack::stable_iterator
+ TopCleanup = EHStack.getInnermostActiveNormalCleanup();
+
+ // If we're not in an active normal cleanup scope, or if the
+ // destination scope is within the innermost active normal cleanup
+ // scope, we don't need to worry about fixups.
+ if (TopCleanup == EHStack.stable_end() ||
+ TopCleanup.encloses(Dest.getScopeDepth())) { // works for invalid
+ Builder.ClearInsertionPoint();
+ return;
+ }
+
+ // If we can't resolve the destination cleanup scope, just add this
+ // to the current cleanup scope as a branch fixup.
+ if (!Dest.getScopeDepth().isValid()) {
+ BranchFixup &Fixup = EHStack.addBranchFixup();
+ Fixup.Destination = Dest.getBlock();
+ Fixup.DestinationIndex = Dest.getDestIndex();
+ Fixup.InitialBranch = BI;
+ Fixup.OptimisticBranchBlock = 0;
+
+ Builder.ClearInsertionPoint();
+ return;
+ }
+
+ // Otherwise, thread through all the normal cleanups in scope.
+
+ // Store the index at the start.
+ llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
+ new llvm::StoreInst(Index, getNormalCleanupDestSlot(), BI);
+
+ // Adjust BI to point to the first cleanup block.
+ {
+ EHCleanupScope &Scope =
+ cast<EHCleanupScope>(*EHStack.find(TopCleanup));
+ BI->setSuccessor(0, CreateNormalEntry(*this, Scope));
+ }
+
+ // Add this destination to all the scopes involved.
+ EHScopeStack::stable_iterator I = TopCleanup;
+ EHScopeStack::stable_iterator E = Dest.getScopeDepth();
+ if (E.strictlyEncloses(I)) {
+ while (true) {
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I));
+ assert(Scope.isNormalCleanup());
+ I = Scope.getEnclosingNormalCleanup();
+
+ // If this is the last cleanup we're propagating through, tell it
+ // that there's a resolved jump moving through it.
+ if (!E.strictlyEncloses(I)) {
+ Scope.addBranchAfter(Index, Dest.getBlock());
+ break;
+ }
+
+ // Otherwise, tell the scope that there's a jump propoagating
+ // through it. If this isn't new information, all the rest of
+ // the work has been done before.
+ if (!Scope.addBranchThrough(Dest.getBlock()))
+ break;
+ }
+ }
+
+ Builder.ClearInsertionPoint();
+}
+
+void CodeGenFunction::EmitBranchThroughEHCleanup(UnwindDest Dest) {
+ // We should never get invalid scope depths for an UnwindDest; that
+ // implies that the destination wasn't set up correctly.
+ assert(Dest.getScopeDepth().isValid() && "invalid scope depth on EH dest?");
+
+ if (!HaveInsertPoint())
+ return;
+
+ // Create the branch.
+ llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
+
+ // Calculate the innermost active cleanup.
+ EHScopeStack::stable_iterator
+ InnermostCleanup = EHStack.getInnermostActiveEHCleanup();
+
+ // If the destination is in the same EH cleanup scope as us, we
+ // don't need to thread through anything.
+ if (InnermostCleanup.encloses(Dest.getScopeDepth())) {
+ Builder.ClearInsertionPoint();
+ return;
+ }
+ assert(InnermostCleanup != EHStack.stable_end());
+
+ // Store the index at the start.
+ llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
+ new llvm::StoreInst(Index, getEHCleanupDestSlot(), BI);
+
+ // Adjust BI to point to the first cleanup block.
+ {
+ EHCleanupScope &Scope =
+ cast<EHCleanupScope>(*EHStack.find(InnermostCleanup));
+ BI->setSuccessor(0, CreateEHEntry(*this, Scope));
+ }
+
+ // Add this destination to all the scopes involved.
+ for (EHScopeStack::stable_iterator
+ I = InnermostCleanup, E = Dest.getScopeDepth(); ; ) {
+ assert(E.strictlyEncloses(I));
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I));
+ assert(Scope.isEHCleanup());
+ I = Scope.getEnclosingEHCleanup();
+
+ // If this is the last cleanup we're propagating through, add this
+ // as a branch-after.
+ if (I == E) {
+ Scope.addEHBranchAfter(Index, Dest.getBlock());
+ break;
+ }
+
+ // Otherwise, add it as a branch-through. If this isn't new
+ // information, all the rest of the work has been done before.
+ if (!Scope.addEHBranchThrough(Dest.getBlock()))
+ break;
+ }
+
+ Builder.ClearInsertionPoint();
+}
+
+static bool IsUsedAsNormalCleanup(EHScopeStack &EHStack,
+ EHScopeStack::stable_iterator C) {
+ // If we needed a normal block for any reason, that counts.
+ if (cast<EHCleanupScope>(*EHStack.find(C)).getNormalBlock())
+ return true;
+
+ // Check whether any enclosed cleanups were needed.
+ for (EHScopeStack::stable_iterator
+ I = EHStack.getInnermostNormalCleanup();
+ I != C; ) {
+ assert(C.strictlyEncloses(I));
+ EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I));
+ if (S.getNormalBlock()) return true;
+ I = S.getEnclosingNormalCleanup();
+ }
+
+ return false;
+}
+
+static bool IsUsedAsEHCleanup(EHScopeStack &EHStack,
+ EHScopeStack::stable_iterator C) {
+ // If we needed an EH block for any reason, that counts.
+ if (cast<EHCleanupScope>(*EHStack.find(C)).getEHBlock())
+ return true;
+
+ // Check whether any enclosed cleanups were needed.
+ for (EHScopeStack::stable_iterator
+ I = EHStack.getInnermostEHCleanup(); I != C; ) {
+ assert(C.strictlyEncloses(I));
+ EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I));
+ if (S.getEHBlock()) return true;
+ I = S.getEnclosingEHCleanup();
+ }
+
+ return false;
+}
+
+enum ForActivation_t {
+ ForActivation,
+ ForDeactivation
+};
+
+/// The given cleanup block is changing activation state. Configure a
+/// cleanup variable if necessary.
+///
+/// It would be good if we had some way of determining if there were
+/// extra uses *after* the change-over point.
+static void SetupCleanupBlockActivation(CodeGenFunction &CGF,
+ EHScopeStack::stable_iterator C,
+ ForActivation_t Kind) {
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C));
+
+ // We always need the flag if we're activating the cleanup, because
+ // we have to assume that the current location doesn't necessarily
+ // dominate all future uses of the cleanup.
+ bool NeedFlag = (Kind == ForActivation);
+
+ // Calculate whether the cleanup was used:
+
+ // - as a normal cleanup
+ if (Scope.isNormalCleanup() && IsUsedAsNormalCleanup(CGF.EHStack, C)) {
+ Scope.setTestFlagInNormalCleanup();
+ NeedFlag = true;
+ }
+
+ // - as an EH cleanup
+ if (Scope.isEHCleanup() && IsUsedAsEHCleanup(CGF.EHStack, C)) {
+ Scope.setTestFlagInEHCleanup();
+ NeedFlag = true;
+ }
+
+ // If it hasn't yet been used as either, we're done.
+ if (!NeedFlag) return;
+
+ llvm::AllocaInst *Var = Scope.getActiveFlag();
+ if (!Var) {
+ Var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive");
+ Scope.setActiveFlag(Var);
+
+ // Initialize to true or false depending on whether it was
+ // active up to this point.
+ CGF.InitTempAlloca(Var, CGF.Builder.getInt1(Kind == ForDeactivation));
+ }
+
+ CGF.Builder.CreateStore(CGF.Builder.getInt1(Kind == ForActivation), Var);
+}
+
+/// Activate a cleanup that was created in an inactivated state.
+void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C) {
+ assert(C != EHStack.stable_end() && "activating bottom of stack?");
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C));
+ assert(!Scope.isActive() && "double activation");
+
+ SetupCleanupBlockActivation(*this, C, ForActivation);
+
+ Scope.setActive(true);
+}
+
+/// Deactive a cleanup that was created in an active state.
+void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) {
+ assert(C != EHStack.stable_end() && "deactivating bottom of stack?");
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C));
+ assert(Scope.isActive() && "double deactivation");
+
+ // If it's the top of the stack, just pop it.
+ if (C == EHStack.stable_begin()) {
+ // If it's a normal cleanup, we need to pretend that the
+ // fallthrough is unreachable.
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+ PopCleanupBlock();
+ Builder.restoreIP(SavedIP);
+ return;
+ }
+
+ // Otherwise, follow the general case.
+ SetupCleanupBlockActivation(*this, C, ForDeactivation);
+
+ Scope.setActive(false);
+}
+
+llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() {
+ if (!NormalCleanupDest)
+ NormalCleanupDest =
+ CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
+ return NormalCleanupDest;
+}
+
+llvm::Value *CodeGenFunction::getEHCleanupDestSlot() {
+ if (!EHCleanupDest)
+ EHCleanupDest =
+ CreateTempAlloca(Builder.getInt32Ty(), "eh.cleanup.dest.slot");
+ return EHCleanupDest;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
new file mode 100644
index 0000000..c93ec5b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
@@ -0,0 +1,560 @@
+//===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes support the generation of LLVM IR for cleanups.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGCLEANUP_H
+#define CLANG_CODEGEN_CGCLEANUP_H
+
+/// EHScopeStack is defined in CodeGenFunction.h, but its
+/// implementation is in this file and in CGCleanup.cpp.
+#include "CodeGenFunction.h"
+
+namespace llvm {
+ class Value;
+ class BasicBlock;
+}
+
+namespace clang {
+namespace CodeGen {
+
+/// A protected scope for zero-cost EH handling.
+class EHScope {
+ llvm::BasicBlock *CachedLandingPad;
+
+ unsigned K : 2;
+
+protected:
+ enum { BitsRemaining = 30 };
+
+public:
+ enum Kind { Cleanup, Catch, Terminate, Filter };
+
+ EHScope(Kind K) : CachedLandingPad(0), K(K) {}
+
+ Kind getKind() const { return static_cast<Kind>(K); }
+
+ llvm::BasicBlock *getCachedLandingPad() const {
+ return CachedLandingPad;
+ }
+
+ void setCachedLandingPad(llvm::BasicBlock *Block) {
+ CachedLandingPad = Block;
+ }
+};
+
+/// A scope which attempts to handle some, possibly all, types of
+/// exceptions.
+///
+/// Objective C @finally blocks are represented using a cleanup scope
+/// after the catch scope.
+class EHCatchScope : public EHScope {
+ unsigned NumHandlers : BitsRemaining;
+
+ // In effect, we have a flexible array member
+ // Handler Handlers[0];
+ // But that's only standard in C99, not C++, so we have to do
+ // annoying pointer arithmetic instead.
+
+public:
+ struct Handler {
+ /// A type info value, or null (C++ null, not an LLVM null pointer)
+ /// for a catch-all.
+ llvm::Value *Type;
+
+ /// The catch handler for this type.
+ llvm::BasicBlock *Block;
+
+ /// The unwind destination index for this handler.
+ unsigned Index;
+ };
+
+private:
+ friend class EHScopeStack;
+
+ Handler *getHandlers() {
+ return reinterpret_cast<Handler*>(this+1);
+ }
+
+ const Handler *getHandlers() const {
+ return reinterpret_cast<const Handler*>(this+1);
+ }
+
+public:
+ static size_t getSizeForNumHandlers(unsigned N) {
+ return sizeof(EHCatchScope) + N * sizeof(Handler);
+ }
+
+ EHCatchScope(unsigned NumHandlers)
+ : EHScope(Catch), NumHandlers(NumHandlers) {
+ }
+
+ unsigned getNumHandlers() const {
+ return NumHandlers;
+ }
+
+ void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
+ setHandler(I, /*catchall*/ 0, Block);
+ }
+
+ void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
+ assert(I < getNumHandlers());
+ getHandlers()[I].Type = Type;
+ getHandlers()[I].Block = Block;
+ }
+
+ const Handler &getHandler(unsigned I) const {
+ assert(I < getNumHandlers());
+ return getHandlers()[I];
+ }
+
+ typedef const Handler *iterator;
+ iterator begin() const { return getHandlers(); }
+ iterator end() const { return getHandlers() + getNumHandlers(); }
+
+ static bool classof(const EHScope *Scope) {
+ return Scope->getKind() == Catch;
+ }
+};
+
+/// A cleanup scope which generates the cleanup blocks lazily.
+class EHCleanupScope : public EHScope {
+ /// Whether this cleanup needs to be run along normal edges.
+ bool IsNormalCleanup : 1;
+
+ /// Whether this cleanup needs to be run along exception edges.
+ bool IsEHCleanup : 1;
+
+ /// Whether this cleanup is currently active.
+ bool IsActive : 1;
+
+ /// Whether the normal cleanup should test the activation flag.
+ bool TestFlagInNormalCleanup : 1;
+
+ /// Whether the EH cleanup should test the activation flag.
+ bool TestFlagInEHCleanup : 1;
+
+ /// The amount of extra storage needed by the Cleanup.
+ /// Always a multiple of the scope-stack alignment.
+ unsigned CleanupSize : 12;
+
+ /// The number of fixups required by enclosing scopes (not including
+ /// this one). If this is the top cleanup scope, all the fixups
+ /// from this index onwards belong to this scope.
+ unsigned FixupDepth : BitsRemaining - 17; // currently 13
+
+ /// The nearest normal cleanup scope enclosing this one.
+ EHScopeStack::stable_iterator EnclosingNormal;
+
+ /// The nearest EH cleanup scope enclosing this one.
+ EHScopeStack::stable_iterator EnclosingEH;
+
+ /// The dual entry/exit block along the normal edge. This is lazily
+ /// created if needed before the cleanup is popped.
+ llvm::BasicBlock *NormalBlock;
+
+ /// The dual entry/exit block along the EH edge. This is lazily
+ /// created if needed before the cleanup is popped.
+ llvm::BasicBlock *EHBlock;
+
+ /// An optional i1 variable indicating whether this cleanup has been
+ /// activated yet.
+ llvm::AllocaInst *ActiveFlag;
+
+ /// Extra information required for cleanups that have resolved
+ /// branches through them. This has to be allocated on the side
+ /// because everything on the cleanup stack has be trivially
+ /// movable.
+ struct ExtInfo {
+ /// The destinations of normal branch-afters and branch-throughs.
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
+
+ /// Normal branch-afters.
+ llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
+ BranchAfters;
+
+ /// The destinations of EH branch-afters and branch-throughs.
+ /// TODO: optimize for the extremely common case of a single
+ /// branch-through.
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches;
+
+ /// EH branch-afters.
+ llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
+ EHBranchAfters;
+ };
+ mutable struct ExtInfo *ExtInfo;
+
+ struct ExtInfo &getExtInfo() {
+ if (!ExtInfo) ExtInfo = new struct ExtInfo();
+ return *ExtInfo;
+ }
+
+ const struct ExtInfo &getExtInfo() const {
+ if (!ExtInfo) ExtInfo = new struct ExtInfo();
+ return *ExtInfo;
+ }
+
+public:
+ /// Gets the size required for a lazy cleanup scope with the given
+ /// cleanup-data requirements.
+ static size_t getSizeForCleanupSize(size_t Size) {
+ return sizeof(EHCleanupScope) + Size;
+ }
+
+ size_t getAllocatedSize() const {
+ return sizeof(EHCleanupScope) + CleanupSize;
+ }
+
+ EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive,
+ unsigned CleanupSize, unsigned FixupDepth,
+ EHScopeStack::stable_iterator EnclosingNormal,
+ EHScopeStack::stable_iterator EnclosingEH)
+ : EHScope(EHScope::Cleanup),
+ IsNormalCleanup(IsNormal), IsEHCleanup(IsEH), IsActive(IsActive),
+ TestFlagInNormalCleanup(false), TestFlagInEHCleanup(false),
+ CleanupSize(CleanupSize), FixupDepth(FixupDepth),
+ EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
+ NormalBlock(0), EHBlock(0), ActiveFlag(0), ExtInfo(0)
+ {
+ assert(this->CleanupSize == CleanupSize && "cleanup size overflow");
+ }
+
+ ~EHCleanupScope() {
+ delete ExtInfo;
+ }
+
+ bool isNormalCleanup() const { return IsNormalCleanup; }
+ llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
+ void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
+
+ bool isEHCleanup() const { return IsEHCleanup; }
+ llvm::BasicBlock *getEHBlock() const { return EHBlock; }
+ void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; }
+
+ bool isActive() const { return IsActive; }
+ void setActive(bool A) { IsActive = A; }
+
+ llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
+ void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
+
+ void setTestFlagInNormalCleanup() { TestFlagInNormalCleanup = true; }
+ bool shouldTestFlagInNormalCleanup() const { return TestFlagInNormalCleanup; }
+
+ void setTestFlagInEHCleanup() { TestFlagInEHCleanup = true; }
+ bool shouldTestFlagInEHCleanup() const { return TestFlagInEHCleanup; }
+
+ unsigned getFixupDepth() const { return FixupDepth; }
+ EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
+ return EnclosingNormal;
+ }
+ EHScopeStack::stable_iterator getEnclosingEHCleanup() const {
+ return EnclosingEH;
+ }
+
+ size_t getCleanupSize() const { return CleanupSize; }
+ void *getCleanupBuffer() { return this + 1; }
+
+ EHScopeStack::Cleanup *getCleanup() {
+ return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
+ }
+
+ /// True if this cleanup scope has any branch-afters or branch-throughs.
+ bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
+
+ /// Add a branch-after to this cleanup scope. A branch-after is a
+ /// branch from a point protected by this (normal) cleanup to a
+ /// point in the normal cleanup scope immediately containing it.
+ /// For example,
+ /// for (;;) { A a; break; }
+ /// contains a branch-after.
+ ///
+ /// Branch-afters each have their own destination out of the
+ /// cleanup, guaranteed distinct from anything else threaded through
+ /// it. Therefore branch-afters usually force a switch after the
+ /// cleanup.
+ void addBranchAfter(llvm::ConstantInt *Index,
+ llvm::BasicBlock *Block) {
+ struct ExtInfo &ExtInfo = getExtInfo();
+ if (ExtInfo.Branches.insert(Block))
+ ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
+ }
+
+ /// Return the number of unique branch-afters on this scope.
+ unsigned getNumBranchAfters() const {
+ return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
+ }
+
+ llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
+ assert(I < getNumBranchAfters());
+ return ExtInfo->BranchAfters[I].first;
+ }
+
+ llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
+ assert(I < getNumBranchAfters());
+ return ExtInfo->BranchAfters[I].second;
+ }
+
+ /// Add a branch-through to this cleanup scope. A branch-through is
+ /// a branch from a scope protected by this (normal) cleanup to an
+ /// enclosing scope other than the immediately-enclosing normal
+ /// cleanup scope.
+ ///
+ /// In the following example, the branch through B's scope is a
+ /// branch-through, while the branch through A's scope is a
+ /// branch-after:
+ /// for (;;) { A a; B b; break; }
+ ///
+ /// All branch-throughs have a common destination out of the
+ /// cleanup, one possibly shared with the fall-through. Therefore
+ /// branch-throughs usually don't force a switch after the cleanup.
+ ///
+ /// \return true if the branch-through was new to this scope
+ bool addBranchThrough(llvm::BasicBlock *Block) {
+ return getExtInfo().Branches.insert(Block);
+ }
+
+ /// Determines if this cleanup scope has any branch throughs.
+ bool hasBranchThroughs() const {
+ if (!ExtInfo) return false;
+ return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
+ }
+
+ // Same stuff, only for EH branches instead of normal branches.
+ // It's quite possible that we could find a better representation
+ // for this.
+
+ bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); }
+ void addEHBranchAfter(llvm::ConstantInt *Index,
+ llvm::BasicBlock *Block) {
+ struct ExtInfo &ExtInfo = getExtInfo();
+ if (ExtInfo.EHBranches.insert(Block))
+ ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index));
+ }
+
+ unsigned getNumEHBranchAfters() const {
+ return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0;
+ }
+
+ llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const {
+ assert(I < getNumEHBranchAfters());
+ return ExtInfo->EHBranchAfters[I].first;
+ }
+
+ llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const {
+ assert(I < getNumEHBranchAfters());
+ return ExtInfo->EHBranchAfters[I].second;
+ }
+
+ bool addEHBranchThrough(llvm::BasicBlock *Block) {
+ return getExtInfo().EHBranches.insert(Block);
+ }
+
+ bool hasEHBranchThroughs() const {
+ if (!ExtInfo) return false;
+ return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size());
+ }
+
+ static bool classof(const EHScope *Scope) {
+ return (Scope->getKind() == Cleanup);
+ }
+};
+
+/// An exceptions scope which filters exceptions thrown through it.
+/// Only exceptions matching the filter types will be permitted to be
+/// thrown.
+///
+/// This is used to implement C++ exception specifications.
+class EHFilterScope : public EHScope {
+ unsigned NumFilters : BitsRemaining;
+
+ // Essentially ends in a flexible array member:
+ // llvm::Value *FilterTypes[0];
+
+ llvm::Value **getFilters() {
+ return reinterpret_cast<llvm::Value**>(this+1);
+ }
+
+ llvm::Value * const *getFilters() const {
+ return reinterpret_cast<llvm::Value* const *>(this+1);
+ }
+
+public:
+ EHFilterScope(unsigned NumFilters) :
+ EHScope(Filter), NumFilters(NumFilters) {}
+
+ static size_t getSizeForNumFilters(unsigned NumFilters) {
+ return sizeof(EHFilterScope) + NumFilters * sizeof(llvm::Value*);
+ }
+
+ unsigned getNumFilters() const { return NumFilters; }
+
+ void setFilter(unsigned I, llvm::Value *FilterValue) {
+ assert(I < getNumFilters());
+ getFilters()[I] = FilterValue;
+ }
+
+ llvm::Value *getFilter(unsigned I) const {
+ assert(I < getNumFilters());
+ return getFilters()[I];
+ }
+
+ static bool classof(const EHScope *Scope) {
+ return Scope->getKind() == Filter;
+ }
+};
+
+/// An exceptions scope which calls std::terminate if any exception
+/// reaches it.
+class EHTerminateScope : public EHScope {
+ unsigned DestIndex : BitsRemaining;
+public:
+ EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {}
+ static size_t getSize() { return sizeof(EHTerminateScope); }
+
+ unsigned getDestIndex() const { return DestIndex; }
+
+ static bool classof(const EHScope *Scope) {
+ return Scope->getKind() == Terminate;
+ }
+};
+
+/// A non-stable pointer into the scope stack.
+class EHScopeStack::iterator {
+ char *Ptr;
+
+ friend class EHScopeStack;
+ explicit iterator(char *Ptr) : Ptr(Ptr) {}
+
+public:
+ iterator() : Ptr(0) {}
+
+ EHScope *get() const {
+ return reinterpret_cast<EHScope*>(Ptr);
+ }
+
+ EHScope *operator->() const { return get(); }
+ EHScope &operator*() const { return *get(); }
+
+ iterator &operator++() {
+ switch (get()->getKind()) {
+ case EHScope::Catch:
+ Ptr += EHCatchScope::getSizeForNumHandlers(
+ static_cast<const EHCatchScope*>(get())->getNumHandlers());
+ break;
+
+ case EHScope::Filter:
+ Ptr += EHFilterScope::getSizeForNumFilters(
+ static_cast<const EHFilterScope*>(get())->getNumFilters());
+ break;
+
+ case EHScope::Cleanup:
+ Ptr += static_cast<const EHCleanupScope*>(get())
+ ->getAllocatedSize();
+ break;
+
+ case EHScope::Terminate:
+ Ptr += EHTerminateScope::getSize();
+ break;
+ }
+
+ return *this;
+ }
+
+ iterator next() {
+ iterator copy = *this;
+ ++copy;
+ return copy;
+ }
+
+ iterator operator++(int) {
+ iterator copy = *this;
+ operator++();
+ return copy;
+ }
+
+ bool encloses(iterator other) const { return Ptr >= other.Ptr; }
+ bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
+
+ bool operator==(iterator other) const { return Ptr == other.Ptr; }
+ bool operator!=(iterator other) const { return Ptr != other.Ptr; }
+};
+
+inline EHScopeStack::iterator EHScopeStack::begin() const {
+ return iterator(StartOfData);
+}
+
+inline EHScopeStack::iterator EHScopeStack::end() const {
+ return iterator(EndOfBuffer);
+}
+
+inline void EHScopeStack::popCatch() {
+ assert(!empty() && "popping exception stack when not empty");
+
+ assert(isa<EHCatchScope>(*begin()));
+ StartOfData += EHCatchScope::getSizeForNumHandlers(
+ cast<EHCatchScope>(*begin()).getNumHandlers());
+
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
+ assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
+ CatchDepth--;
+}
+
+inline void EHScopeStack::popTerminate() {
+ assert(!empty() && "popping exception stack when not empty");
+
+ assert(isa<EHTerminateScope>(*begin()));
+ StartOfData += EHTerminateScope::getSize();
+
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
+ assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
+ CatchDepth--;
+}
+
+inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
+ assert(sp.isValid() && "finding invalid savepoint");
+ assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
+ return iterator(EndOfBuffer - sp.Size);
+}
+
+inline EHScopeStack::stable_iterator
+EHScopeStack::stabilize(iterator ir) const {
+ assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
+ return stable_iterator(EndOfBuffer - ir.Ptr);
+}
+
+inline EHScopeStack::stable_iterator
+EHScopeStack::getInnermostActiveNormalCleanup() const {
+ for (EHScopeStack::stable_iterator
+ I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) {
+ EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
+ if (S.isActive()) return I;
+ I = S.getEnclosingNormalCleanup();
+ }
+ return stable_end();
+}
+
+inline EHScopeStack::stable_iterator
+EHScopeStack::getInnermostActiveEHCleanup() const {
+ for (EHScopeStack::stable_iterator
+ I = getInnermostEHCleanup(), E = stable_end(); I != E; ) {
+ EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
+ if (S.isActive()) return I;
+ I = S.getEnclosingEHCleanup();
+ }
+ return stable_end();
+}
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
new file mode 100644
index 0000000..469b460
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -0,0 +1,2038 @@
+//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This coordinates the debug information generation while generating code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGBlocks.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+using namespace clang;
+using namespace clang::CodeGen;
+
+CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
+ : CGM(CGM), DBuilder(CGM.getModule()),
+ BlockLiteralGenericSet(false) {
+ CreateCompileUnit();
+}
+
+CGDebugInfo::~CGDebugInfo() {
+ assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
+}
+
+void CGDebugInfo::setLocation(SourceLocation Loc) {
+ if (Loc.isValid())
+ CurLoc = CGM.getContext().getSourceManager().getInstantiationLoc(Loc);
+}
+
+/// getContextDescriptor - Get context info for the decl.
+llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) {
+ if (!Context)
+ return TheCU;
+
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
+ I = RegionMap.find(Context);
+ if (I != RegionMap.end())
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(&*I->second));
+
+ // Check namespace.
+ if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
+ return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
+
+ if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {
+ if (!RDecl->isDependentType()) {
+ llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
+ getOrCreateMainFile());
+ return llvm::DIDescriptor(Ty);
+ }
+ }
+ return TheCU;
+}
+
+/// getFunctionName - Get function name for the given FunctionDecl. If the
+/// name is constructred on demand (e.g. C++ destructor) then the name
+/// is stored on the side.
+llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
+ assert (FD && "Invalid FunctionDecl!");
+ IdentifierInfo *FII = FD->getIdentifier();
+ if (FII)
+ return FII->getName();
+
+ // Otherwise construct human readable name for debug info.
+ std::string NS = FD->getNameAsString();
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
+ memcpy(StrPtr, NS.data(), NS.length());
+ return llvm::StringRef(StrPtr, NS.length());
+}
+
+llvm::StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
+ llvm::SmallString<256> MethodName;
+ llvm::raw_svector_ostream OS(MethodName);
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const ObjCImplementationDecl *OID =
+ dyn_cast<const ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const ObjCInterfaceDecl *OID =
+ dyn_cast<const ObjCInterfaceDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const ObjCCategoryImplDecl *OCD =
+ dyn_cast<const ObjCCategoryImplDecl>(DC)){
+ OS << ((NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
+ OCD->getIdentifier()->getNameStart() << ')';
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+
+ char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
+ memcpy(StrPtr, MethodName.begin(), OS.tell());
+ return llvm::StringRef(StrPtr, OS.tell());
+}
+
+/// getClassName - Get class name including template argument list.
+llvm::StringRef
+CGDebugInfo::getClassName(RecordDecl *RD) {
+ ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD);
+ if (!Spec)
+ return RD->getName();
+
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ std::string Buffer;
+ if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(TAW->getType());
+ Args = TST->getArgs();
+ NumArgs = TST->getNumArgs();
+ } else {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ Args = TemplateArgs.data();
+ NumArgs = TemplateArgs.size();
+ }
+ Buffer = RD->getIdentifier()->getNameStart();
+ PrintingPolicy Policy(CGM.getLangOptions());
+ Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
+ NumArgs,
+ Policy);
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
+ memcpy(StrPtr, Buffer.data(), Buffer.length());
+ return llvm::StringRef(StrPtr, Buffer.length());
+}
+
+/// getOrCreateFile - Get the file debug info descriptor for the input location.
+llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
+ if (!Loc.isValid())
+ // If Location is not valid then use main input file.
+ return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+ if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty())
+ // If the location is not valid then use main input file.
+ return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+
+ // Cache the results.
+ const char *fname = PLoc.getFilename();
+ llvm::DenseMap<const char *, llvm::WeakVH>::iterator it =
+ DIFileCache.find(fname);
+
+ if (it != DIFileCache.end()) {
+ // Verify that the information still exists.
+ if (&*it->second)
+ return llvm::DIFile(cast<llvm::MDNode>(it->second));
+ }
+
+ llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname());
+
+ DIFileCache[fname] = F;
+ return F;
+
+}
+
+/// getOrCreateMainFile - Get the file info for main compile unit.
+llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
+ return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+}
+
+/// getLineNumber - Get line number for the location. If location is invalid
+/// then use current location.
+unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
+ assert (CurLoc.isValid() && "Invalid current location!");
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
+ return PLoc.isValid()? PLoc.getLine() : 0;
+}
+
+/// getColumnNumber - Get column number for the location. If location is
+/// invalid then use current location.
+unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
+ assert (CurLoc.isValid() && "Invalid current location!");
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
+ return PLoc.isValid()? PLoc.getColumn() : 0;
+}
+
+llvm::StringRef CGDebugInfo::getCurrentDirname() {
+ if (!CWDName.empty())
+ return CWDName;
+ char *CompDirnamePtr = NULL;
+ llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory();
+ CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
+ memcpy(CompDirnamePtr, CWD.c_str(), CWD.size());
+ return CWDName = llvm::StringRef(CompDirnamePtr, CWD.size());
+}
+
+/// CreateCompileUnit - Create new compile unit.
+void CGDebugInfo::CreateCompileUnit() {
+
+ // Get absolute path name.
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
+ if (MainFileName.empty())
+ MainFileName = "<unknown>";
+
+ // The main file name provided via the "-main-file-name" option contains just
+ // the file name itself with no path information. This file name may have had
+ // a relative path, so we look into the actual file entry for the main
+ // file to determine the real absolute path for the file.
+ std::string MainFileDir;
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+ MainFileDir = MainFile->getDir()->getName();
+ if (MainFileDir != ".")
+ MainFileName = MainFileDir + "/" + MainFileName;
+ }
+
+ // Save filename string.
+ char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
+ memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
+ llvm::StringRef Filename(FilenamePtr, MainFileName.length());
+
+ unsigned LangTag;
+ const LangOptions &LO = CGM.getLangOptions();
+ if (LO.CPlusPlus) {
+ if (LO.ObjC1)
+ LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
+ else
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
+ } else if (LO.ObjC1) {
+ LangTag = llvm::dwarf::DW_LANG_ObjC;
+ } else if (LO.C99) {
+ LangTag = llvm::dwarf::DW_LANG_C99;
+ } else {
+ LangTag = llvm::dwarf::DW_LANG_C89;
+ }
+
+ std::string Producer = getClangFullVersion();
+
+ // Figure out which version of the ObjC runtime we have.
+ unsigned RuntimeVers = 0;
+ if (LO.ObjC1)
+ RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
+
+ // Create new compile unit.
+ DBuilder.CreateCompileUnit(
+ LangTag, Filename, getCurrentDirname(),
+ Producer,
+ LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
+ // FIXME - Eliminate TheCU.
+ TheCU = llvm::DICompileUnit(DBuilder.getCU());
+}
+
+/// CreateType - Get the Basic type from the cache or create a new
+/// one if necessary.
+llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
+ unsigned Encoding = 0;
+ const char *BTName = NULL;
+ switch (BT->getKind()) {
+ default:
+ case BuiltinType::Void:
+ return llvm::DIType();
+ case BuiltinType::ObjCClass:
+ return DBuilder.CreateStructType(TheCU, "objc_class",
+ getOrCreateMainFile(), 0, 0, 0,
+ llvm::DIDescriptor::FlagFwdDecl,
+ llvm::DIArray());
+ case BuiltinType::ObjCId: {
+ // typedef struct objc_class *Class;
+ // typedef struct objc_object {
+ // Class isa;
+ // } *id;
+
+ llvm::DIType OCTy =
+ DBuilder.CreateStructType(TheCU, "objc_class",
+ getOrCreateMainFile(), 0, 0, 0,
+ llvm::DIDescriptor::FlagFwdDecl,
+ llvm::DIArray());
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+
+ llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size);
+
+ llvm::SmallVector<llvm::Value *, 16> EltTys;
+ llvm::DIType FieldTy =
+ DBuilder.CreateMemberType("isa", getOrCreateMainFile(),
+ 0,Size, 0, 0, 0, ISATy);
+ EltTys.push_back(FieldTy);
+ llvm::DIArray Elements =
+ DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ return DBuilder.CreateStructType(TheCU, "objc_object",
+ getOrCreateMainFile(),
+ 0, 0, 0, 0, Elements);
+ }
+ case BuiltinType::ObjCSel: {
+ return DBuilder.CreateStructType(TheCU, "objc_selector",
+ getOrCreateMainFile(), 0, 0, 0,
+ llvm::DIDescriptor::FlagFwdDecl,
+ llvm::DIArray());
+ }
+ case BuiltinType::UChar:
+ case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
+ case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
+ case BuiltinType::Float:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
+ }
+
+ switch (BT->getKind()) {
+ case BuiltinType::Long: BTName = "long int"; break;
+ case BuiltinType::LongLong: BTName = "long long int"; break;
+ case BuiltinType::ULong: BTName = "long unsigned int"; break;
+ case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
+ default:
+ BTName = BT->getName(CGM.getContext().getLangOptions());
+ break;
+ }
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(BT);
+ uint64_t Align = CGM.getContext().getTypeAlign(BT);
+ llvm::DIType DbgTy =
+ DBuilder.CreateBasicType(BTName, Size, Align, Encoding);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
+ // Bit size, align and offset of the type.
+ unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
+ if (Ty->isComplexIntegerType())
+ Encoding = llvm::dwarf::DW_ATE_lo_user;
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ llvm::DIType DbgTy =
+ DBuilder.CreateBasicType("complex", Size, Align, Encoding);
+
+ return DbgTy;
+}
+
+/// CreateCVRType - Get the qualified type from the cache or create
+/// a new one if necessary.
+llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
+ QualifierCollector Qc;
+ const Type *T = Qc.strip(Ty);
+
+ // Ignore these qualifiers for now.
+ Qc.removeObjCGCAttr();
+ Qc.removeAddressSpace();
+
+ // We will create one Derived type for one qualifier and recurse to handle any
+ // additional ones.
+ unsigned Tag;
+ if (Qc.hasConst()) {
+ Tag = llvm::dwarf::DW_TAG_const_type;
+ Qc.removeConst();
+ } else if (Qc.hasVolatile()) {
+ Tag = llvm::dwarf::DW_TAG_volatile_type;
+ Qc.removeVolatile();
+ } else if (Qc.hasRestrict()) {
+ Tag = llvm::dwarf::DW_TAG_restrict_type;
+ Qc.removeRestrict();
+ } else {
+ assert(Qc.empty() && "Unknown type qualifier for debug info");
+ return getOrCreateType(QualType(T, 0), Unit);
+ }
+
+ llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
+
+ // No need to fill in the Name, Line, Size, Alignment, Offset in case of
+ // CVR derived types.
+ llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy);
+
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
+ llvm::DIFile Unit) {
+ llvm::DIType DbgTy =
+ CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
+}
+
+/// CreatePointeeType - Create PointTee type. If Pointee is a record
+/// then emit record's fwd if debug info size reduction is enabled.
+llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
+ llvm::DIFile Unit) {
+ if (!CGM.getCodeGenOpts().LimitDebugInfo)
+ return getOrCreateType(PointeeTy, Unit);
+
+ if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
+ RecordDecl *RD = RTy->getDecl();
+ llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ unsigned Line = getLineNumber(RD->getLocation());
+ llvm::DIDescriptor FDContext =
+ getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+
+ if (RD->isStruct())
+ return DBuilder.CreateStructType(FDContext, RD->getName(), DefUnit,
+ Line, 0, 0, llvm::DIType::FlagFwdDecl,
+ llvm::DIArray());
+ else if (RD->isUnion())
+ return DBuilder.CreateUnionType(FDContext, RD->getName(), DefUnit,
+ Line, 0, 0, llvm::DIType::FlagFwdDecl,
+ llvm::DIArray());
+ else {
+ assert(RD->isClass() && "Unknown RecordType!");
+ return DBuilder.CreateClassType(FDContext, RD->getName(), DefUnit,
+ Line, 0, 0, 0, llvm::DIType::FlagFwdDecl,
+ llvm::DIType(), llvm::DIArray());
+ }
+ }
+ return getOrCreateType(PointeeTy, Unit);
+
+}
+
+llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
+ const Type *Ty,
+ QualType PointeeTy,
+ llvm::DIFile Unit) {
+
+ if (Tag == llvm::dwarf::DW_TAG_reference_type)
+ return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit));
+
+ // Bit size, align and offset of the type.
+ // Size is always the size of a pointer. We can't use getTypeSize here
+ // because that does not return the correct value for references.
+ uint64_t Size =
+ CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace());
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ return
+ DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
+ llvm::DIFile Unit) {
+ if (BlockLiteralGenericSet)
+ return BlockLiteralGeneric;
+
+ llvm::SmallVector<llvm::Value *, 8> EltTys;
+ llvm::DIType FieldTy;
+ QualType FType;
+ uint64_t FieldSize, FieldOffset;
+ unsigned FieldAlign;
+ llvm::DIArray Elements;
+ llvm::DIType EltTy, DescTy;
+
+ FieldOffset = 0;
+ FType = CGM.getContext().UnsignedLongTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
+
+ Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ EltTys.clear();
+
+ unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
+ unsigned LineNo = getLineNumber(CurLoc);
+
+ EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor",
+ Unit, LineNo, FieldOffset, 0,
+ Flags, Elements);
+
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+
+ DescTy = DBuilder.CreatePointerType(EltTy, Size);
+
+ FieldOffset = 0;
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
+
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ FieldTy = DescTy;
+ FieldSize = CGM.getContext().getTypeSize(Ty);
+ FieldAlign = CGM.getContext().getTypeAlign(Ty);
+ FieldTy = DBuilder.CreateMemberType("__descriptor", Unit,
+ LineNo, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+
+ FieldOffset += FieldSize;
+ Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic",
+ Unit, LineNo, FieldOffset, 0,
+ Flags, Elements);
+
+ BlockLiteralGenericSet = true;
+ BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size);
+ return BlockLiteralGeneric;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
+ llvm::DIFile Unit) {
+ // Typedefs are derived from some other type. If we have a typedef of a
+ // typedef, make sure to emit the whole chain.
+ llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+ if (!Src.Verify())
+ return llvm::DIType();
+ // We don't set size information, but do specify where the typedef was
+ // declared.
+ unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
+ llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(),
+ Unit, Line);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
+ llvm::DIFile Unit) {
+ llvm::SmallVector<llvm::Value *, 16> EltTys;
+
+ // Add the result type at least.
+ EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
+
+ // Set up remainder of arguments if there is a prototype.
+ // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
+ if (isa<FunctionNoProtoType>(Ty))
+ EltTys.push_back(DBuilder.CreateUnspecifiedParameter());
+ else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
+ for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+ EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
+ }
+
+ llvm::DIArray EltTypeArray =
+ DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ return DbgTy;
+}
+
+/// CollectRecordFields - A helper function to collect debug info for
+/// record fields. This is used while creating debug info entry for a Record.
+void CGDebugInfo::
+CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
+ unsigned FieldNo = 0;
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I, ++FieldNo) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
+
+ // Get the location for the field.
+ llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
+ unsigned FieldLine = getLineNumber(Field->getLocation());
+ QualType FType = Field->getType();
+ uint64_t FieldSize = 0;
+ unsigned FieldAlign = 0;
+ if (!FType->isIncompleteArrayType()) {
+
+ // Bit size, align and offset of the type.
+ FieldSize = CGM.getContext().getTypeSize(FType);
+ Expr *BitWidth = Field->getBitWidth();
+ if (BitWidth)
+ FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ FieldAlign = CGM.getContext().getTypeAlign(FType);
+ }
+
+ uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
+
+ unsigned Flags = 0;
+ AccessSpecifier Access = I->getAccess();
+ if (Access == clang::AS_private)
+ Flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ Flags |= llvm::DIDescriptor::FlagProtected;
+
+ FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
+ FieldLine, FieldSize, FieldAlign,
+ FieldOffset, Flags, FieldTy);
+ EltTys.push_back(FieldTy);
+ }
+}
+
+/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
+/// function type is not updated to include implicit "this" pointer. Use this
+/// routine to get a method type which includes "this" pointer.
+llvm::DIType
+CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
+ llvm::DIFile Unit) {
+ llvm::DIType FnTy
+ = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),
+ 0),
+ Unit);
+
+ // Add "this" pointer.
+
+ llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();
+ assert (Args.getNumElements() && "Invalid number of arguments!");
+
+ llvm::SmallVector<llvm::Value *, 16> Elts;
+
+ // First element is always return type. For 'void' functions it is NULL.
+ Elts.push_back(Args.getElement(0));
+
+ if (!Method->isStatic())
+ {
+ // "this" pointer is always first argument.
+ ASTContext &Context = CGM.getContext();
+ QualType ThisPtr =
+ Context.getPointerType(Context.getTagDeclType(Method->getParent()));
+ llvm::DIType ThisPtrType =
+ DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
+
+ TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
+ Elts.push_back(ThisPtrType);
+ }
+
+ // Copy rest of the arguments.
+ for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
+ Elts.push_back(Args.getElement(i));
+
+ llvm::DIArray EltTypeArray =
+ DBuilder.GetOrCreateArray(Elts.data(), Elts.size());
+
+ return DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+}
+
+/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
+/// inside a function.
+static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
+ if (const CXXRecordDecl *NRD =
+ dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
+ return isFunctionLocalClass(NRD);
+ else if (isa<FunctionDecl>(RD->getDeclContext()))
+ return true;
+ return false;
+
+}
+/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
+/// a single member function GlobalDecl.
+llvm::DISubprogram
+CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
+ llvm::DIFile Unit,
+ llvm::DIType RecordTy) {
+ bool IsCtorOrDtor =
+ isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
+
+ llvm::StringRef MethodName = getFunctionName(Method);
+ llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
+
+ // Since a single ctor/dtor corresponds to multiple functions, it doesn't
+ // make sense to give a single ctor/dtor a linkage name.
+ llvm::StringRef MethodLinkageName;
+ if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))
+ MethodLinkageName = CGM.getMangledName(Method);
+
+ // Get the location for the method.
+ llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
+ unsigned MethodLine = getLineNumber(Method->getLocation());
+
+ // Collect virtual method info.
+ llvm::DIType ContainingType;
+ unsigned Virtuality = 0;
+ unsigned VIndex = 0;
+
+ if (Method->isVirtual()) {
+ if (Method->isPure())
+ Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
+ else
+ Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
+
+ // It doesn't make sense to give a virtual destructor a vtable index,
+ // since a single destructor has two entries in the vtable.
+ if (!isa<CXXDestructorDecl>(Method))
+ VIndex = CGM.getVTables().getMethodVTableIndex(Method);
+ ContainingType = RecordTy;
+ }
+
+ unsigned Flags = 0;
+ if (Method->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+ AccessSpecifier Access = Method->getAccess();
+ if (Access == clang::AS_private)
+ Flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ Flags |= llvm::DIDescriptor::FlagProtected;
+ if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
+ if (CXXC->isExplicit())
+ Flags |= llvm::DIDescriptor::FlagExplicit;
+ } else if (const CXXConversionDecl *CXXC =
+ dyn_cast<CXXConversionDecl>(Method)) {
+ if (CXXC->isExplicit())
+ Flags |= llvm::DIDescriptor::FlagExplicit;
+ }
+ if (Method->hasPrototype())
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+
+ llvm::DISubprogram SP =
+ DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName,
+ MethodDefUnit, MethodLine,
+ MethodTy, /*isLocalToUnit=*/false,
+ /* isDefinition=*/ false,
+ Virtuality, VIndex, ContainingType,
+ Flags, CGM.getLangOptions().Optimize);
+
+ // Don't cache ctors or dtors since we have to emit multiple functions for
+ // a single ctor or dtor.
+ if (!IsCtorOrDtor && Method->isThisDeclarationADefinition())
+ SPCache[Method] = llvm::WeakVH(SP);
+
+ return SP;
+}
+
+/// CollectCXXMemberFunctions - A helper function to collect debug info for
+/// C++ member functions.This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+ for(CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *Method = *I;
+
+ if (Method->isImplicit() && !Method->isUsed())
+ continue;
+
+ EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ }
+}
+
+/// CollectCXXFriends - A helper function to collect debug info for
+/// C++ base classes. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+
+ for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
+ BE = RD->friend_end(); BI != BE; ++BI) {
+ if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
+ EltTys.push_back(DBuilder.CreateFriend(RecordTy,
+ getOrCreateType(TInfo->getType(),
+ Unit)));
+ }
+}
+
+/// CollectCXXBases - A helper function to collect debug info for
+/// C++ base classes. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
+ BE = RD->bases_end(); BI != BE; ++BI) {
+ unsigned BFlags = 0;
+ uint64_t BaseOffset;
+
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
+
+ if (BI->isVirtual()) {
+ // virtual base offset offset is -ve. The code generator emits dwarf
+ // expression where it expects +ve number.
+ BaseOffset = 0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base);
+ BFlags = llvm::DIDescriptor::FlagVirtual;
+ } else
+ BaseOffset = RL.getBaseClassOffsetInBits(Base);
+
+ AccessSpecifier Access = BI->getAccessSpecifier();
+ if (Access == clang::AS_private)
+ BFlags |= llvm::DIDescriptor::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ BFlags |= llvm::DIDescriptor::FlagProtected;
+
+ llvm::DIType DTy =
+ DBuilder.CreateInheritance(RecordTy,
+ getOrCreateType(BI->getType(), Unit),
+ BaseOffset, BFlags);
+ EltTys.push_back(DTy);
+ }
+}
+
+/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
+llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
+ if (VTablePtrType.isValid())
+ return VTablePtrType;
+
+ ASTContext &Context = CGM.getContext();
+
+ /* Function type */
+ llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
+ llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1);
+ llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements);
+ unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
+ llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0,
+ "__vtbl_ptr_type");
+ VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size);
+ return VTablePtrType;
+}
+
+/// getVTableName - Get vtable name for the given Class.
+llvm::StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
+ // Otherwise construct gdb compatible name name.
+ std::string Name = "_vptr$" + RD->getNameAsString();
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
+ memcpy(StrPtr, Name.data(), Name.length());
+ return llvm::StringRef(StrPtr, Name.length());
+}
+
+
+/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
+/// debug info entry in EltTys vector.
+void CGDebugInfo::
+CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+
+ // If there is a primary base then it will hold vtable info.
+ if (RL.getPrimaryBase())
+ return;
+
+ // If this class is not dynamic then there is not any vtable info to collect.
+ if (!RD->isDynamicClass())
+ return;
+
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ llvm::DIType VPTR
+ = DBuilder.CreateMemberType(getVTableName(RD), Unit,
+ 0, Size, 0, 0, 0,
+ getOrCreateVTablePtrType(Unit));
+ EltTys.push_back(VPTR);
+}
+
+/// getOrCreateRecordType - Emit record type's standalone debug info.
+llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
+ SourceLocation Loc) {
+ llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
+ DBuilder.RetainType(T);
+ return T;
+}
+
+/// CreateType - get structure or union type.
+llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
+ RecordDecl *RD = Ty->getDecl();
+ llvm::DIFile Unit = getOrCreateFile(RD->getLocation());
+
+ // Get overall information about the record type for the debug info.
+ llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ unsigned Line = getLineNumber(RD->getLocation());
+
+ // Records and classes and unions can all be recursive. To handle them, we
+ // first generate a debug descriptor for the struct as a forward declaration.
+ // Then (if it is a definition) we go through and get debug info for all of
+ // its members. Finally, we create a descriptor for the complete type (which
+ // may refer to the forward decl if the struct is recursive) and replace all
+ // uses of the forward declaration with the final definition.
+ llvm::DIDescriptor FDContext =
+ getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+
+ // If this is just a forward declaration, construct an appropriately
+ // marked node and just return it.
+ if (!RD->getDefinition()) {
+ llvm::DIType FwdDecl =
+ DBuilder.CreateStructType(FDContext, RD->getName(),
+ DefUnit, Line, 0, 0,
+ llvm::DIDescriptor::FlagFwdDecl,
+ llvm::DIArray());
+
+ return FwdDecl;
+ }
+
+ llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+
+ llvm::MDNode *MN = FwdDecl;
+ llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
+ // Otherwise, insert it into the TypeCache so that recursive uses will find
+ // it.
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
+ // Push the struct on region stack.
+ RegionStack.push_back(FwdDeclNode);
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
+
+ // Convert all the elements.
+ llvm::SmallVector<llvm::Value *, 16> EltTys;
+
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+ if (CXXDecl) {
+ CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
+ CollectVTableInfo(CXXDecl, Unit, EltTys);
+ }
+
+ // Collect static variables with initializers.
+ for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
+ I != E; ++I)
+ if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
+ if (const Expr *Init = V->getInit()) {
+ Expr::EvalResult Result;
+ if (Init->Evaluate(Result, CGM.getContext()) && Result.Val.isInt()) {
+ llvm::ConstantInt *CI
+ = llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt());
+
+ // Create the descriptor for static variable.
+ llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
+ llvm::StringRef VName = V->getName();
+ llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
+ // Do not use DIGlobalVariable for enums.
+ if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
+ DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit,
+ getLineNumber(V->getLocation()),
+ VTy, true, CI);
+ }
+ }
+ }
+ }
+
+ CollectRecordFields(RD, Unit, EltTys);
+ llvm::SmallVector<llvm::Value *, 16> TemplateParams;
+ if (CXXDecl) {
+ CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
+ CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl);
+ if (ClassTemplateSpecializationDecl *TSpecial
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ const TemplateArgumentList &TAL = TSpecial->getTemplateArgs();
+ for (unsigned i = 0, e = TAL.size(); i != e; ++i) {
+ const TemplateArgument &TA = TAL[i];
+ if (TA.getKind() == TemplateArgument::Type) {
+ llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
+ llvm::DITemplateTypeParameter TTP =
+ DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy);
+ TemplateParams.push_back(TTP);
+ } else if (TA.getKind() == TemplateArgument::Integral) {
+ llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
+ // FIXME: Get parameter name, instead of parameter type name.
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy,
+ TA.getAsIntegral()->getZExtValue());
+ TemplateParams.push_back(TVP);
+ }
+ }
+ }
+ }
+
+ RegionStack.pop_back();
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
+ RegionMap.find(Ty->getDecl());
+ if (RI != RegionMap.end())
+ RegionMap.erase(RI);
+
+ llvm::DIDescriptor RDContext =
+ getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ llvm::StringRef RDName = RD->getName();
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ llvm::DIArray Elements =
+ DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ llvm::MDNode *RealDecl = NULL;
+
+ if (RD->isStruct())
+ RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, Elements);
+ else if (RD->isUnion())
+ RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, Elements);
+ else {
+ assert(RD->isClass() && "Unknown RecordType!");
+ RDName = getClassName(RD);
+ // A class's primary base or the class itself contains the vtable.
+ llvm::MDNode *ContainingType = NULL;
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
+ // Seek non virtual primary base root.
+ while (1) {
+ const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
+ const CXXRecordDecl *PBT = BRL.getPrimaryBase();
+ if (PBT && !BRL.isPrimaryBaseVirtual())
+ PBase = PBT;
+ else
+ break;
+ }
+ ContainingType =
+ getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit);
+ }
+ else if (CXXDecl->isDynamicClass())
+ ContainingType = FwdDecl;
+ llvm::DIArray TParamsArray =
+ DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size());
+ RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, 0, llvm::DIType(),
+ Elements, ContainingType,
+ TParamsArray);
+ }
+
+ // Now that we have a real decl for the struct, replace anything using the
+ // old decl with the new one. This will recursively update the debug info.
+ llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
+ RegionMap[RD] = llvm::WeakVH(RealDecl);
+ return llvm::DIType(RealDecl);
+}
+
+/// CreateType - get objective-c object type.
+llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
+ llvm::DIFile Unit) {
+ // Ignore protocols.
+ return getOrCreateType(Ty->getBaseType(), Unit);
+}
+
+/// CreateType - get objective-c interface type.
+llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
+ llvm::DIFile Unit) {
+ ObjCInterfaceDecl *ID = Ty->getDecl();
+ if (!ID)
+ return llvm::DIType();
+
+ // Get overall information about the record type for the debug info.
+ llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
+ unsigned Line = getLineNumber(ID->getLocation());
+ unsigned RuntimeLang = TheCU.getLanguage();
+
+ // If this is just a forward declaration, return a special forward-declaration
+ // debug type.
+ if (ID->isForwardDecl()) {
+ llvm::DIType FwdDecl =
+ DBuilder.CreateStructType(Unit, ID->getName(),
+ DefUnit, Line, 0, 0, 0,
+ llvm::DIArray(), RuntimeLang);
+ return FwdDecl;
+ }
+
+ // To handle recursive interface, we
+ // first generate a debug descriptor for the struct as a forward declaration.
+ // Then (if it is a definition) we go through and get debug info for all of
+ // its members. Finally, we create a descriptor for the complete type (which
+ // may refer to the forward decl if the struct is recursive) and replace all
+ // uses of the forward declaration with the final definition.
+ llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+
+ llvm::MDNode *MN = FwdDecl;
+ llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
+ // Otherwise, insert it into the TypeCache so that recursive uses will find
+ // it.
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
+ // Push the struct on region stack.
+ RegionStack.push_back(FwdDeclNode);
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
+
+ // Convert all the elements.
+ llvm::SmallVector<llvm::Value *, 16> EltTys;
+
+ ObjCInterfaceDecl *SClass = ID->getSuperClass();
+ if (SClass) {
+ llvm::DIType SClassTy =
+ getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
+ if (!SClassTy.isValid())
+ return llvm::DIType();
+
+ llvm::DIType InhTag =
+ DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0);
+ EltTys.push_back(InhTag);
+ }
+
+ const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
+
+ unsigned FieldNo = 0;
+ for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
+ Field = Field->getNextIvar(), ++FieldNo) {
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ if (!FieldTy.isValid())
+ return llvm::DIType();
+
+ llvm::StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields.
+ if (FieldName.empty())
+ continue;
+
+ // Get the location for the field.
+ llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
+ unsigned FieldLine = getLineNumber(Field->getLocation());
+ QualType FType = Field->getType();
+ uint64_t FieldSize = 0;
+ unsigned FieldAlign = 0;
+
+ if (!FType->isIncompleteArrayType()) {
+
+ // Bit size, align and offset of the type.
+ FieldSize = CGM.getContext().getTypeSize(FType);
+ Expr *BitWidth = Field->getBitWidth();
+ if (BitWidth)
+ FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+
+ FieldAlign = CGM.getContext().getTypeAlign(FType);
+ }
+
+ uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
+
+ unsigned Flags = 0;
+ if (Field->getAccessControl() == ObjCIvarDecl::Protected)
+ Flags = llvm::DIDescriptor::FlagProtected;
+ else if (Field->getAccessControl() == ObjCIvarDecl::Private)
+ Flags = llvm::DIDescriptor::FlagPrivate;
+
+ FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
+ FieldLine, FieldSize, FieldAlign,
+ FieldOffset, Flags, FieldTy);
+ EltTys.push_back(FieldTy);
+ }
+
+ llvm::DIArray Elements =
+ DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ RegionStack.pop_back();
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
+ RegionMap.find(Ty->getDecl());
+ if (RI != RegionMap.end())
+ RegionMap.erase(RI);
+
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ llvm::DIType RealDecl =
+ DBuilder.CreateStructType(Unit, ID->getName(), DefUnit,
+ Line, Size, Align, 0,
+ Elements, RuntimeLang);
+
+ // Now that we have a real decl for the struct, replace anything using the
+ // old decl with the new one. This will recursively update the debug info.
+ llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
+ RegionMap[ID] = llvm::WeakVH(RealDecl);
+
+ return RealDecl;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const TagType *Ty) {
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+ return CreateType(RT);
+ else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
+ return CreateEnumType(ET->getDecl());
+
+ return llvm::DIType();
+}
+
+llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
+ llvm::DIFile Unit) {
+ llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
+ uint64_t NumElems = Ty->getNumElements();
+ if (NumElems > 0)
+ --NumElems;
+
+ llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems);
+ llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1);
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ return
+ DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
+ llvm::DIFile Unit) {
+ uint64_t Size;
+ uint64_t Align;
+
+
+ // FIXME: make getTypeAlign() aware of VLAs and incomplete array types
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
+ Size = 0;
+ Align =
+ CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
+ } else if (Ty->isIncompleteArrayType()) {
+ Size = 0;
+ Align = CGM.getContext().getTypeAlign(Ty->getElementType());
+ } else {
+ // Size and align of the whole array, not the element type.
+ Size = CGM.getContext().getTypeSize(Ty);
+ Align = CGM.getContext().getTypeAlign(Ty);
+ }
+
+ // Add the dimensions of the array. FIXME: This loses CV qualifiers from
+ // interior arrays, do we care? Why aren't nested arrays represented the
+ // obvious/recursive way?
+ llvm::SmallVector<llvm::Value *, 8> Subscripts;
+ QualType EltTy(Ty, 0);
+ if (Ty->isIncompleteArrayType())
+ EltTy = Ty->getElementType();
+ else {
+ while ((Ty = dyn_cast<ArrayType>(EltTy))) {
+ uint64_t Upper = 0;
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
+ if (CAT->getSize().getZExtValue())
+ Upper = CAT->getSize().getZExtValue() - 1;
+ // FIXME: Verify this is right for VLAs.
+ Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper));
+ EltTy = Ty->getElementType();
+ }
+ }
+
+ llvm::DIArray SubscriptArray =
+ DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size());
+
+ llvm::DIType DbgTy =
+ DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ SubscriptArray);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
+ Ty, Ty->getPointeeType(), Unit);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
+ Ty, Ty->getPointeeType(), Unit);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
+ llvm::DIFile U) {
+ QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
+ llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
+
+ if (!Ty->getPointeeType()->isFunctionType()) {
+ // We have a data member pointer type.
+ return PointerDiffDITy;
+ }
+
+ // We have a member function pointer type. Treat it as a struct with two
+ // ptrdiff_t members.
+ std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
+
+ uint64_t FieldOffset = 0;
+ llvm::Value *ElementTypes[2];
+
+ // FIXME: This should probably be a function type instead.
+ ElementTypes[0] =
+ DBuilder.CreateMemberType("ptr", U, 0,
+ Info.first, Info.second, FieldOffset, 0,
+ PointerDiffDITy);
+ FieldOffset += Info.first;
+
+ ElementTypes[1] =
+ DBuilder.CreateMemberType("ptr", U, 0,
+ Info.first, Info.second, FieldOffset, 0,
+ PointerDiffDITy);
+
+ llvm::DIArray Elements =
+ DBuilder.GetOrCreateArray(&ElementTypes[0],
+ llvm::array_lengthof(ElementTypes));
+
+ return DBuilder.CreateStructType(U, llvm::StringRef("test"),
+ U, 0, FieldOffset,
+ 0, 0, Elements);
+}
+
+/// CreateEnumType - get enumeration type.
+llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
+ llvm::DIFile Unit = getOrCreateFile(ED->getLocation());
+ llvm::SmallVector<llvm::Value *, 16> Enumerators;
+
+ // Create DIEnumerator elements for each enumerator.
+ for (EnumDecl::enumerator_iterator
+ Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
+ Enum != EnumEnd; ++Enum) {
+ Enumerators.push_back(
+ DBuilder.CreateEnumerator(Enum->getName(),
+ Enum->getInitVal().getZExtValue()));
+ }
+
+ // Return a CompositeType for the enum itself.
+ llvm::DIArray EltArray =
+ DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size());
+
+ llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ unsigned Line = getLineNumber(ED->getLocation());
+ uint64_t Size = 0;
+ uint64_t Align = 0;
+ if (!ED->getTypeForDecl()->isIncompleteType()) {
+ Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
+ Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ }
+ llvm::DIDescriptor EnumContext =
+ getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext()));
+ llvm::DIType DbgTy =
+ DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
+ Size, Align, EltArray);
+ return DbgTy;
+}
+
+static QualType UnwrapTypeForDebugInfo(QualType T) {
+ do {
+ QualType LastT = T;
+ switch (T->getTypeClass()) {
+ default:
+ return T;
+ case Type::TemplateSpecialization:
+ T = cast<TemplateSpecializationType>(T)->desugar();
+ break;
+ case Type::TypeOfExpr:
+ T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
+ break;
+ case Type::TypeOf:
+ T = cast<TypeOfType>(T)->getUnderlyingType();
+ break;
+ case Type::Decltype:
+ T = cast<DecltypeType>(T)->getUnderlyingType();
+ break;
+ case Type::Attributed:
+ T = cast<AttributedType>(T)->getEquivalentType();
+ case Type::Elaborated:
+ T = cast<ElaboratedType>(T)->getNamedType();
+ break;
+ case Type::Paren:
+ T = cast<ParenType>(T)->getInnerType();
+ break;
+ case Type::SubstTemplateTypeParm:
+ T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
+ break;
+ }
+
+ assert(T != LastT && "Type unwrapping failed to unwrap!");
+ if (T == LastT)
+ return T;
+ } while (true);
+
+ return T;
+}
+
+/// getOrCreateType - Get the type from the cache or create a new
+/// one if necessary.
+llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
+ llvm::DIFile Unit) {
+ if (Ty.isNull())
+ return llvm::DIType();
+
+ // Unwrap the type as needed for debug information.
+ Ty = UnwrapTypeForDebugInfo(Ty);
+
+ // Check for existing entry.
+ llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
+ TypeCache.find(Ty.getAsOpaquePtr());
+ if (it != TypeCache.end()) {
+ // Verify that the debug info still exists.
+ if (&*it->second)
+ return llvm::DIType(cast<llvm::MDNode>(it->second));
+ }
+
+ // Otherwise create the type.
+ llvm::DIType Res = CreateTypeNode(Ty, Unit);
+
+ // And update the type cache.
+ TypeCache[Ty.getAsOpaquePtr()] = Res;
+ return Res;
+}
+
+/// CreateTypeNode - Create a new debug type node.
+llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
+ llvm::DIFile Unit) {
+ // Handle qualifiers, which recursively handles what they refer to.
+ if (Ty.hasLocalQualifiers())
+ return CreateQualifiedType(Ty, Unit);
+
+ const char *Diag = 0;
+
+ // Work out details of type.
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Dependent types cannot show up in debug information");
+
+ // FIXME: Handle these.
+ case Type::ExtVector:
+ return llvm::DIType();
+
+ case Type::Vector:
+ return CreateType(cast<VectorType>(Ty), Unit);
+ case Type::ObjCObjectPointer:
+ return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
+ case Type::ObjCObject:
+ return CreateType(cast<ObjCObjectType>(Ty), Unit);
+ case Type::ObjCInterface:
+ return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
+ case Type::Builtin: return CreateType(cast<BuiltinType>(Ty));
+ case Type::Complex: return CreateType(cast<ComplexType>(Ty));
+ case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::BlockPointer:
+ return CreateType(cast<BlockPointerType>(Ty), Unit);
+ case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit);
+ case Type::Record:
+ case Type::Enum:
+ return CreateType(cast<TagType>(Ty));
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ return CreateType(cast<FunctionType>(Ty), Unit);
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ case Type::IncompleteArray:
+ return CreateType(cast<ArrayType>(Ty), Unit);
+
+ case Type::LValueReference:
+ return CreateType(cast<LValueReferenceType>(Ty), Unit);
+ case Type::RValueReference:
+ return CreateType(cast<RValueReferenceType>(Ty), Unit);
+
+ case Type::MemberPointer:
+ return CreateType(cast<MemberPointerType>(Ty), Unit);
+
+ case Type::Attributed:
+ case Type::TemplateSpecialization:
+ case Type::Elaborated:
+ case Type::Paren:
+ case Type::SubstTemplateTypeParm:
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::Auto:
+ llvm_unreachable("type should have been unwrapped!");
+ return llvm::DIType();
+ }
+
+ assert(Diag && "Fall through without a diagnostic?");
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
+ "debug information for %0 is not yet supported");
+ CGM.getDiags().Report(DiagID)
+ << Diag;
+ return llvm::DIType();
+}
+
+/// CreateMemberType - Create new member and increase Offset by FType's size.
+llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
+ llvm::StringRef Name,
+ uint64_t *Offset) {
+ llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
+ unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
+ llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0,
+ FieldSize, FieldAlign,
+ *Offset, 0, FieldTy);
+ *Offset += FieldSize;
+ return Ty;
+}
+
+/// EmitFunctionStart - Constructs the debug code for entering a function -
+/// "llvm.dbg.func.start.".
+void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
+ llvm::Function *Fn,
+ CGBuilderTy &Builder) {
+
+ llvm::StringRef Name;
+ llvm::StringRef LinkageName;
+
+ FnBeginRegionCount.push_back(RegionStack.size());
+
+ const Decl *D = GD.getDecl();
+ unsigned Flags = 0;
+ llvm::DIFile Unit = getOrCreateFile(CurLoc);
+ llvm::DIDescriptor FDContext(Unit);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If there is a DISubprogram for this function available then use it.
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ FI = SPCache.find(FD);
+ if (FI != SPCache.end()) {
+ llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(&*FI->second));
+ if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
+ llvm::MDNode *SPN = SP;
+ RegionStack.push_back(SPN);
+ RegionMap[D] = llvm::WeakVH(SP);
+ return;
+ }
+ }
+ Name = getFunctionName(FD);
+ // Use mangled name as linkage name for c/c++ functions.
+ LinkageName = CGM.getMangledName(GD);
+ if (LinkageName == Name)
+ LinkageName = llvm::StringRef();
+ if (FD->hasPrototype())
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ if (const NamespaceDecl *NSDecl =
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ FDContext = getOrCreateNameSpace(NSDecl);
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+ Name = getObjCMethodName(OMD);
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ } else {
+ // Use llvm function name.
+ Name = Fn->getName();
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ }
+ if (!Name.empty() && Name[0] == '\01')
+ Name = Name.substr(1);
+
+ // It is expected that CurLoc is set before using EmitFunctionStart.
+ // Usually, CurLoc points to the left bracket location of compound
+ // statement representing function body.
+ unsigned LineNo = getLineNumber(CurLoc);
+ if (D->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+ llvm::DISubprogram SP =
+ DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit,
+ LineNo, getOrCreateType(FnType, Unit),
+ Fn->hasInternalLinkage(), true/*definition*/,
+ Flags, CGM.getLangOptions().Optimize, Fn);
+
+ // Push function on region stack.
+ llvm::MDNode *SPN = SP;
+ RegionStack.push_back(SPN);
+ RegionMap[D] = llvm::WeakVH(SP);
+
+ // Clear stack used to keep track of #line directives.
+ LineDirectiveFiles.clear();
+}
+
+
+void CGDebugInfo::EmitStopPoint(CGBuilderTy &Builder) {
+ if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
+
+ // Don't bother if things are the same as last time.
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ if (CurLoc == PrevLoc
+ || (SM.getInstantiationLineNumber(CurLoc) ==
+ SM.getInstantiationLineNumber(PrevLoc)
+ && SM.isFromSameFile(CurLoc, PrevLoc)))
+ // New Builder may not be in sync with CGDebugInfo.
+ if (!Builder.getCurrentDebugLocation().isUnknown())
+ return;
+
+ // Update last state.
+ PrevLoc = CurLoc;
+
+ llvm::MDNode *Scope = RegionStack.back();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
+ getColumnNumber(CurLoc),
+ Scope));
+}
+
+/// UpdateLineDirectiveRegion - Update region stack only if #line directive
+/// has introduced scope change.
+void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
+ if (CurLoc.isInvalid() || CurLoc.isMacroID() ||
+ PrevLoc.isInvalid() || PrevLoc.isMacroID())
+ return;
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
+ PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
+
+ if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
+ !strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
+ return;
+
+ // If #line directive stack is empty then we are entering a new scope.
+ if (LineDirectiveFiles.empty()) {
+ EmitRegionStart(Builder);
+ LineDirectiveFiles.push_back(PCLoc.getFilename());
+ return;
+ }
+
+ assert (RegionStack.size() >= LineDirectiveFiles.size()
+ && "error handling #line regions!");
+
+ bool SeenThisFile = false;
+ // Chek if current file is already seen earlier.
+ for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(),
+ E = LineDirectiveFiles.end(); I != E; ++I)
+ if (!strcmp(PCLoc.getFilename(), *I)) {
+ SeenThisFile = true;
+ break;
+ }
+
+ // If #line for this file is seen earlier then pop out #line regions.
+ if (SeenThisFile) {
+ while (!LineDirectiveFiles.empty()) {
+ const char *LastFile = LineDirectiveFiles.back();
+ RegionStack.pop_back();
+ LineDirectiveFiles.pop_back();
+ if (!strcmp(PPLoc.getFilename(), LastFile))
+ break;
+ }
+ return;
+ }
+
+ // .. otherwise insert new #line region.
+ EmitRegionStart(Builder);
+ LineDirectiveFiles.push_back(PCLoc.getFilename());
+
+ return;
+}
+/// EmitRegionStart- Constructs the debug code for entering a declarative
+/// region - "llvm.dbg.region.start.".
+void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
+ llvm::DIDescriptor D =
+ DBuilder.CreateLexicalBlock(RegionStack.empty() ?
+ llvm::DIDescriptor() :
+ llvm::DIDescriptor(RegionStack.back()),
+ getOrCreateFile(CurLoc),
+ getLineNumber(CurLoc),
+ getColumnNumber(CurLoc));
+ llvm::MDNode *DN = D;
+ RegionStack.push_back(DN);
+}
+
+/// EmitRegionEnd - Constructs the debug code for exiting a declarative
+/// region - "llvm.dbg.region.end."
+void CGDebugInfo::EmitRegionEnd(CGBuilderTy &Builder) {
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+
+ // Provide an region stop point.
+ EmitStopPoint(Builder);
+
+ RegionStack.pop_back();
+}
+
+/// EmitFunctionEnd - Constructs the debug code for exiting a function.
+void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+ unsigned RCount = FnBeginRegionCount.back();
+ assert(RCount <= RegionStack.size() && "Region stack mismatch");
+
+ // Pop all regions for this function.
+ while (RegionStack.size() != RCount)
+ EmitRegionEnd(Builder);
+ FnBeginRegionCount.pop_back();
+}
+
+// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+// See BuildByRefType.
+llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
+ uint64_t *XOffset) {
+
+ llvm::SmallVector<llvm::Value *, 5> EltTys;
+ QualType FType;
+ uint64_t FieldSize, FieldOffset;
+ unsigned FieldAlign;
+
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ QualType Type = VD->getType();
+
+ FieldOffset = 0;
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
+
+ bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type);
+ if (HasCopyAndDispose) {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
+ &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
+ &FieldOffset));
+ }
+
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
+ if (Align > CharUnits::fromQuantity(
+ CGM.getContext().Target.getPointerAlign(0) / 8)) {
+ unsigned AlignedOffsetInBytes
+ = llvm::RoundUpToAlignment(FieldOffset/8, Align.getQuantity());
+ unsigned NumPaddingBytes
+ = AlignedOffsetInBytes - FieldOffset/8;
+
+ if (NumPaddingBytes > 0) {
+ llvm::APInt pad(32, NumPaddingBytes);
+ FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
+ pad, ArrayType::Normal, 0);
+ EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
+ }
+ }
+
+ FType = Type;
+ llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = CGM.getContext().getTypeSize(FType);
+ FieldAlign = Align.getQuantity()*8;
+
+ *XOffset = FieldOffset;
+ FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ llvm::DIArray Elements =
+ DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
+
+ return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
+ Elements);
+}
+
+/// EmitDeclare - Emit local variable declaration debug info.
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
+ llvm::Value *Storage, CGBuilderTy &Builder) {
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIType Ty;
+ uint64_t XOffset = 0;
+ if (VD->hasAttr<BlocksAttr>())
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ else
+ Ty = getOrCreateType(VD->getType(), Unit);
+
+ // If there is not any debug info for type then do not emit debug info
+ // for this variable.
+ if (!Ty)
+ return;
+
+ if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
+ // If Storage is an aggregate returned as 'sret' then let debugger know
+ // about this.
+ if (Arg->hasStructRetAttr())
+ Ty = DBuilder.CreateReferenceType(Ty);
+ else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
+ // If an aggregate variable has non trivial destructor or non trivial copy
+ // constructor than it is pass indirectly. Let debug info know about this
+ // by using reference of the aggregate type as a argument type.
+ if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor())
+ Ty = DBuilder.CreateReferenceType(Ty);
+ }
+ }
+
+ // Get location information.
+ unsigned Line = getLineNumber(VD->getLocation());
+ unsigned Column = getColumnNumber(VD->getLocation());
+ unsigned Flags = 0;
+ if (VD->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+ llvm::MDNode *Scope = RegionStack.back();
+
+ llvm::StringRef Name = VD->getName();
+ if (!Name.empty()) {
+ if (VD->hasAttr<BlocksAttr>()) {
+ CharUnits offset = CharUnits::fromQuantity(32);
+ llvm::SmallVector<llvm::Value *, 9> addr;
+ const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of __forwarding field
+ offset =
+ CharUnits::fromQuantity(CGM.getContext().Target.getPointerWidth(0)/8);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of x field
+ offset = CharUnits::fromQuantity(XOffset/8);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.CreateComplexVariable(Tag,
+ llvm::DIDescriptor(RegionStack.back()),
+ VD->getName(), Unit, Line, Ty,
+ addr.data(), addr.size());
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ return;
+ }
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ Name, Unit, Line, Ty,
+ CGM.getLangOptions().Optimize, Flags);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ return;
+ }
+
+ // If VD is an anonymous union then Storage represents value for
+ // all union fields.
+ if (const RecordType *RT = dyn_cast<RecordType>(VD->getType()))
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl()))
+ if (RD->isUnion()) {
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
+
+ // Use VarDecl's Tag, Scope and Line number.
+ llvm::DIVariable D =
+ DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ FieldName, Unit, Line, FieldTy,
+ CGM.getLangOptions().Optimize, Flags);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ }
+ }
+}
+
+/// EmitDeclare - Emit local variable declaration debug info.
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
+ llvm::Value *Storage, CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo) {
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+
+ if (Builder.GetInsertBlock() == 0)
+ return;
+
+ bool isByRef = VD->hasAttr<BlocksAttr>();
+
+ uint64_t XOffset = 0;
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIType Ty;
+ if (isByRef)
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ else
+ Ty = getOrCreateType(VD->getType(), Unit);
+
+ // Get location information.
+ unsigned Line = getLineNumber(VD->getLocation());
+ unsigned Column = getColumnNumber(VD->getLocation());
+
+ const llvm::TargetData &target = CGM.getTargetData();
+
+ CharUnits offset = CharUnits::fromQuantity(
+ target.getStructLayout(blockInfo.StructureType)
+ ->getElementOffset(blockInfo.getCapture(VD).getIndex()));
+
+ llvm::SmallVector<llvm::Value *, 9> addr;
+ const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ if (isByRef) {
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of __forwarding field
+ offset = CharUnits::fromQuantity(target.getPointerSize()/8);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of x field
+ offset = CharUnits::fromQuantity(XOffset/8);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ }
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ VD->getName(), Unit, Line, Ty,
+ addr.data(), addr.size());
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+
+ llvm::MDNode *Scope = RegionStack.back();
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+}
+
+void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
+ llvm::Value *Storage,
+ CGBuilderTy &Builder) {
+ EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
+}
+
+void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
+ const VarDecl *variable, llvm::Value *Storage, CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo) {
+ EmitDeclare(variable, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder,
+ blockInfo);
+}
+
+/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+/// variable declaration.
+void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
+ CGBuilderTy &Builder) {
+ EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
+}
+
+
+
+/// EmitGlobalVariable - Emit information about a global variable.
+void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
+ const VarDecl *D) {
+
+ // Create global variable debug descriptor.
+ llvm::DIFile Unit = getOrCreateFile(D->getLocation());
+ unsigned LineNo = getLineNumber(D->getLocation());
+
+ QualType T = D->getType();
+ if (T->isIncompleteArrayType()) {
+
+ // CodeGen turns int[] into int[1] so we'll do the same here.
+ llvm::APSInt ConstVal(32);
+
+ ConstVal = 1;
+ QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
+
+ T = CGM.getContext().getConstantArrayType(ET, ConstVal,
+ ArrayType::Normal, 0);
+ }
+ llvm::StringRef DeclName = D->getName();
+ llvm::StringRef LinkageName;
+ if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())
+ && !isa<ObjCMethodDecl>(D->getDeclContext()))
+ LinkageName = Var->getName();
+ if (LinkageName == DeclName)
+ LinkageName = llvm::StringRef();
+ llvm::DIDescriptor DContext =
+ getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
+ DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName,
+ Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var);
+}
+
+/// EmitGlobalVariable - Emit information about an objective-c interface.
+void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
+ ObjCInterfaceDecl *ID) {
+ // Create global variable debug descriptor.
+ llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
+ unsigned LineNo = getLineNumber(ID->getLocation());
+
+ llvm::StringRef Name = ID->getName();
+
+ QualType T = CGM.getContext().getObjCInterfaceType(ID);
+ if (T->isIncompleteArrayType()) {
+
+ // CodeGen turns int[] into int[1] so we'll do the same here.
+ llvm::APSInt ConstVal(32);
+
+ ConstVal = 1;
+ QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
+
+ T = CGM.getContext().getConstantArrayType(ET, ConstVal,
+ ArrayType::Normal, 0);
+ }
+
+ DBuilder.CreateGlobalVariable(Name, Unit, LineNo,
+ getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var);
+}
+
+/// EmitGlobalVariable - Emit global variable's debug info.
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
+ llvm::Constant *Init) {
+ // Create the descriptor for the variable.
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::StringRef Name = VD->getName();
+ llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
+ if (const EnumDecl *ED = dyn_cast<EnumDecl>(ECD->getDeclContext()))
+ Ty = CreateEnumType(ED);
+ }
+ // Do not use DIGlobalVariable for enums.
+ if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
+ return;
+ DBuilder.CreateStaticVariable(Unit, Name, Name, Unit,
+ getLineNumber(VD->getLocation()),
+ Ty, true, Init);
+}
+
+/// getOrCreateNamesSpace - Return namespace descriptor for the given
+/// namespace decl.
+llvm::DINameSpace
+CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
+ NameSpaceCache.find(NSDecl);
+ if (I != NameSpaceCache.end())
+ return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
+
+ unsigned LineNo = getLineNumber(NSDecl->getLocation());
+ llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
+ llvm::DIDescriptor Context =
+ getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
+ llvm::DINameSpace NS =
+ DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
+ return NS;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
new file mode 100644
index 0000000..6a9ab9c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -0,0 +1,263 @@
+//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the source level debug info generator for llvm translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGDEBUGINFO_H
+#define CLANG_CODEGEN_CGDEBUGINFO_H
+
+#include "clang/AST/Type.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Analysis/DIBuilder.h"
+#include "llvm/Support/ValueHandle.h"
+#include "llvm/Support/Allocator.h"
+
+#include "CGBuilder.h"
+
+namespace llvm {
+ class MDNode;
+}
+
+namespace clang {
+ class VarDecl;
+ class ObjCInterfaceDecl;
+
+namespace CodeGen {
+ class CodeGenModule;
+ class CodeGenFunction;
+ class GlobalDecl;
+ class CGBlockInfo;
+
+/// CGDebugInfo - This class gathers all debug information during compilation
+/// and is responsible for emitting to llvm globals or pass directly to
+/// the backend.
+class CGDebugInfo {
+ CodeGenModule &CGM;
+ llvm::DIBuilder DBuilder;
+ llvm::DICompileUnit TheCU;
+ SourceLocation CurLoc, PrevLoc;
+ llvm::DIType VTablePtrType;
+
+ /// TypeCache - Cache of previously constructed Types.
+ llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
+
+ bool BlockLiteralGenericSet;
+ llvm::DIType BlockLiteralGeneric;
+
+ std::vector<llvm::TrackingVH<llvm::MDNode> > RegionStack;
+ llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
+ // FnBeginRegionCount - Keep track of RegionStack counter at the beginning
+ // of a function. This is used to pop unbalanced regions at the end of a
+ // function.
+ std::vector<unsigned> FnBeginRegionCount;
+
+ /// LineDirectiveFiles - This stack is used to keep track of
+ /// scopes introduced by #line directives.
+ std::vector<const char *> LineDirectiveFiles;
+
+ /// DebugInfoNames - This is a storage for names that are
+ /// constructed on demand. For example, C++ destructors, C++ operators etc..
+ llvm::BumpPtrAllocator DebugInfoNames;
+ llvm::StringRef CWDName;
+
+ llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;
+
+ /// Helper functions for getOrCreateType.
+ llvm::DIType CreateType(const BuiltinType *Ty);
+ llvm::DIType CreateType(const ComplexType *Ty);
+ llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
+ llvm::DIFile F);
+ llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const TagType *Ty);
+ llvm::DIType CreateType(const RecordType *Ty);
+ llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);
+ llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateEnumType(const EnumDecl *ED);
+ llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
+ llvm::DIFile F);
+ llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
+ llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
+ llvm::DIType CreatePointeeType(QualType PointeeTy, llvm::DIFile F);
+ llvm::DIType CreatePointerLikeType(unsigned Tag,
+ const Type *Ty, QualType PointeeTy,
+ llvm::DIFile F);
+
+ llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
+ llvm::DIFile F,
+ llvm::DIType RecordTy);
+
+ void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::Value *> &E,
+ llvm::DIType T);
+
+ void CollectCXXFriends(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy);
+
+ void CollectCXXBases(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy);
+
+
+ void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::Value *> &E);
+
+ void CollectVTableInfo(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::Value *> &EltTys);
+
+public:
+ CGDebugInfo(CodeGenModule &CGM);
+ ~CGDebugInfo();
+
+ /// setLocation - Update the current source location. If \arg loc is
+ /// invalid it is ignored.
+ void setLocation(SourceLocation Loc);
+
+ /// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
+ /// source line.
+ void EmitStopPoint(CGBuilderTy &Builder);
+
+ /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
+ /// start of a new function.
+ void EmitFunctionStart(GlobalDecl GD, QualType FnType,
+ llvm::Function *Fn, CGBuilderTy &Builder);
+
+ /// EmitFunctionEnd - Constructs the debug code for exiting a function.
+ void EmitFunctionEnd(CGBuilderTy &Builder);
+
+ /// UpdateLineDirectiveRegion - Update region stack only if #line directive
+ /// has introduced scope change.
+ void UpdateLineDirectiveRegion(CGBuilderTy &Builder);
+
+ /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
+ /// of a new block.
+ void EmitRegionStart(CGBuilderTy &Builder);
+
+ /// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a
+ /// block.
+ void EmitRegionEnd(CGBuilderTy &Builder);
+
+ /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic
+ /// variable declaration.
+ void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
+ /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an
+ /// imported variable declaration in a block.
+ void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
+ llvm::Value *storage,
+ CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo);
+
+ /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+ /// variable declaration.
+ void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
+ /// EmitGlobalVariable - Emit information about a global variable.
+ void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
+
+ /// EmitGlobalVariable - Emit information about an objective-c interface.
+ void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
+
+ /// EmitGlobalVariable - Emit global variable's debug info.
+ void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
+
+ /// getOrCreateRecordType - Emit record type's standalone debug info.
+ llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
+private:
+ /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
+ void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
+ /// EmitDeclare - Emit call to llvm.dbg.declare for a variable
+ /// declaration from an enclosing block.
+ void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
+ CGBuilderTy &Builder, const CGBlockInfo &blockInfo);
+
+ // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+ // See BuildByRefType.
+ llvm::DIType EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
+ uint64_t *OffSet);
+
+ /// getContextDescriptor - Get context info for the decl.
+ llvm::DIDescriptor getContextDescriptor(const Decl *Decl);
+
+ /// getCurrentDirname - Return current directory name.
+ llvm::StringRef getCurrentDirname();
+
+ /// CreateCompileUnit - Create new compile unit.
+ void CreateCompileUnit();
+
+ /// getOrCreateFile - Get the file debug info descriptor for the input
+ /// location.
+ llvm::DIFile getOrCreateFile(SourceLocation Loc);
+
+ /// getOrCreateMainFile - Get the file info for main compile unit.
+ llvm::DIFile getOrCreateMainFile();
+
+ /// getOrCreateType - Get the type from the cache or create a new type if
+ /// necessary.
+ llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
+
+ /// CreateTypeNode - Create type metadata for a source language type.
+ llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
+
+ /// CreateMemberType - Create new member and increase Offset by FType's size.
+ llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
+ llvm::StringRef Name, uint64_t *Offset);
+
+ /// getFunctionName - Get function name for the given FunctionDecl. If the
+ /// name is constructred on demand (e.g. C++ destructor) then the name
+ /// is stored on the side.
+ llvm::StringRef getFunctionName(const FunctionDecl *FD);
+
+ /// getObjCMethodName - Returns the unmangled name of an Objective-C method.
+ /// This is the display name for the debugging info.
+ llvm::StringRef getObjCMethodName(const ObjCMethodDecl *FD);
+
+ /// getClassName - Get class name including template argument list.
+ llvm::StringRef getClassName(RecordDecl *RD);
+
+ /// getVTableName - Get vtable name for the given Class.
+ llvm::StringRef getVTableName(const CXXRecordDecl *Decl);
+
+ /// getLineNumber - Get line number for the location. If location is invalid
+ /// then use current location.
+ unsigned getLineNumber(SourceLocation Loc);
+
+ /// getColumnNumber - Get column number for the location. If location is
+ /// invalid then use current location.
+ unsigned getColumnNumber(SourceLocation Loc);
+};
+} // namespace CodeGen
+} // namespace clang
+
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
new file mode 100644
index 0000000..a87dfae
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -0,0 +1,963 @@
+//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Decl nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGBlocks.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Type.h"
+using namespace clang;
+using namespace CodeGen;
+
+
+void CodeGenFunction::EmitDecl(const Decl &D) {
+ switch (D.getKind()) {
+ case Decl::TranslationUnit:
+ case Decl::Namespace:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::TemplateTypeParm:
+ case Decl::UnresolvedUsingValue:
+ case Decl::NonTypeTemplateParm:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::Field:
+ case Decl::IndirectField:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ParmVar:
+ case Decl::ImplicitParam:
+ case Decl::ClassTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::TemplateTemplateParm:
+ case Decl::ObjCMethod:
+ case Decl::ObjCCategory:
+ case Decl::ObjCProtocol:
+ case Decl::ObjCInterface:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCProperty:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::AccessSpec:
+ case Decl::LinkageSpec:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCClass:
+ case Decl::ObjCForwardProtocol:
+ case Decl::FileScopeAsm:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::Block:
+ assert(0 && "Declaration not should not be in declstmts!");
+ case Decl::Function: // void X();
+ case Decl::Record: // struct/union/class X;
+ case Decl::Enum: // enum X;
+ case Decl::EnumConstant: // enum ? { X = ? }
+ case Decl::CXXRecord: // struct/union/class X; [C++]
+ case Decl::Using: // using X; [C++]
+ case Decl::UsingShadow:
+ case Decl::UsingDirective: // using namespace X; [C++]
+ case Decl::NamespaceAlias:
+ case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
+ case Decl::Label: // __label__ x;
+ // None of these decls require codegen support.
+ return;
+
+ case Decl::Var: {
+ const VarDecl &VD = cast<VarDecl>(D);
+ assert(VD.isLocalVarDecl() &&
+ "Should not see file-scope variables inside a function!");
+ return EmitVarDecl(VD);
+ }
+
+ case Decl::Typedef: { // typedef int X;
+ const TypedefDecl &TD = cast<TypedefDecl>(D);
+ QualType Ty = TD.getUnderlyingType();
+
+ if (Ty->isVariablyModifiedType())
+ EmitVLASize(Ty);
+ }
+ }
+}
+
+/// EmitVarDecl - This method handles emission of any variable declaration
+/// inside a function, including static vars etc.
+void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
+ switch (D.getStorageClass()) {
+ case SC_None:
+ case SC_Auto:
+ case SC_Register:
+ return EmitAutoVarDecl(D);
+ case SC_Static: {
+ llvm::GlobalValue::LinkageTypes Linkage =
+ llvm::GlobalValue::InternalLinkage;
+
+ // If the function definition has some sort of weak linkage, its
+ // static variables should also be weak so that they get properly
+ // uniqued. We can't do this in C, though, because there's no
+ // standard way to agree on which variables are the same (i.e.
+ // there's no mangling).
+ if (getContext().getLangOptions().CPlusPlus)
+ if (llvm::GlobalValue::isWeakForLinker(CurFn->getLinkage()))
+ Linkage = CurFn->getLinkage();
+
+ return EmitStaticVarDecl(D, Linkage);
+ }
+ case SC_Extern:
+ case SC_PrivateExtern:
+ // Don't emit it now, allow it to be emitted lazily on its first use.
+ return;
+ }
+
+ assert(0 && "Unknown storage class");
+}
+
+static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
+ const char *Separator) {
+ CodeGenModule &CGM = CGF.CGM;
+ if (CGF.getContext().getLangOptions().CPlusPlus) {
+ llvm::StringRef Name = CGM.getMangledName(&D);
+ return Name.str();
+ }
+
+ std::string ContextName;
+ if (!CGF.CurFuncDecl) {
+ // Better be in a block declared in global scope.
+ const NamedDecl *ND = cast<NamedDecl>(&D);
+ const DeclContext *DC = ND->getDeclContext();
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
+ MangleBuffer Name;
+ CGM.getBlockMangledName(GlobalDecl(), Name, BD);
+ ContextName = Name.getString();
+ }
+ else
+ assert(0 && "Unknown context for block static var decl");
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl)) {
+ llvm::StringRef Name = CGM.getMangledName(FD);
+ ContextName = Name.str();
+ } else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
+ ContextName = CGF.CurFn->getName();
+ else
+ assert(0 && "Unknown context for static var decl");
+
+ return ContextName + Separator + D.getNameAsString();
+}
+
+llvm::GlobalVariable *
+CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
+ const char *Separator,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ QualType Ty = D.getType();
+ assert(Ty->isConstantSizeType() && "VLAs can't be static");
+
+ std::string Name = GetStaticDeclName(*this, D, Separator);
+
+ const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), LTy,
+ Ty.isConstant(getContext()), Linkage,
+ CGM.EmitNullConstant(D.getType()), Name, 0,
+ D.isThreadSpecified(), Ty.getAddressSpace());
+ GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+ if (Linkage != llvm::GlobalValue::InternalLinkage)
+ GV->setVisibility(CurFn->getVisibility());
+ return GV;
+}
+
+/// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the
+/// global variable that has already been created for it. If the initializer
+/// has a different type than GV does, this may free GV and return a different
+/// one. Otherwise it just returns GV.
+llvm::GlobalVariable *
+CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
+
+ // If constant emission failed, then this should be a C++ static
+ // initializer.
+ if (!Init) {
+ if (!getContext().getLangOptions().CPlusPlus)
+ CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
+ else if (Builder.GetInsertBlock()) {
+ // Since we have a static initializer, this global variable can't
+ // be constant.
+ GV->setConstant(false);
+
+ EmitCXXGuardedInit(D, GV);
+ }
+ return GV;
+ }
+
+ // The initializer may differ in type from the global. Rewrite
+ // the global to match the initializer. (We have to do this
+ // because some types, like unions, can't be completely represented
+ // in the LLVM type system.)
+ if (GV->getType()->getElementType() != Init->getType()) {
+ llvm::GlobalVariable *OldGV = GV;
+
+ GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ OldGV->isConstant(),
+ OldGV->getLinkage(), Init, "",
+ /*InsertBefore*/ OldGV,
+ D.isThreadSpecified(),
+ D.getType().getAddressSpace());
+ GV->setVisibility(OldGV->getVisibility());
+
+ // Steal the name of the old global
+ GV->takeName(OldGV);
+
+ // Replace all uses of the old global with the new global
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtrForOldDecl);
+
+ // Erase the old global, since it is no longer used.
+ OldGV->eraseFromParent();
+ }
+
+ GV->setInitializer(Init);
+ return GV;
+}
+
+void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ llvm::Value *&DMEntry = LocalDeclMap[&D];
+ assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+
+ llvm::GlobalVariable *GV = CreateStaticVarDecl(D, ".", Linkage);
+
+ // Store into LocalDeclMap before generating initializer to handle
+ // circular references.
+ DMEntry = GV;
+
+ // We can't have a VLA here, but we can have a pointer to a VLA,
+ // even though that doesn't really make any sense.
+ // Make sure to evaluate VLA bounds now so that we have them for later.
+ if (D.getType()->isVariablyModifiedType())
+ EmitVLASize(D.getType());
+
+ // Local static block variables must be treated as globals as they may be
+ // referenced in their RHS initializer block-literal expresion.
+ CGM.setStaticLocalDeclAddress(&D, GV);
+
+ // If this value has an initializer, emit it.
+ if (D.getInit())
+ GV = AddInitializerToStaticVarDecl(D, GV);
+
+ GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+
+ // FIXME: Merge attribute handling.
+ if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ llvm::Constant *Ann =
+ CGM.EmitAnnotateAttr(GV, AA,
+ SM.getInstantiationLineNumber(D.getLocation()));
+ CGM.AddAnnotation(Ann);
+ }
+
+ if (const SectionAttr *SA = D.getAttr<SectionAttr>())
+ GV->setSection(SA->getName());
+
+ if (D.hasAttr<UsedAttr>())
+ CGM.AddUsedGlobal(GV);
+
+ // We may have to cast the constant because of the initializer
+ // mismatch above.
+ //
+ // FIXME: It is really dangerous to store this in the map; if anyone
+ // RAUW's the GV uses of this constant will be invalid.
+ const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
+ const llvm::Type *LPtrTy = LTy->getPointerTo(D.getType().getAddressSpace());
+ DMEntry = llvm::ConstantExpr::getBitCast(GV, LPtrTy);
+
+ // Emit global variable debug descriptor for static vars.
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI) {
+ DI->setLocation(D.getLocation());
+ DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D);
+ }
+}
+
+unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
+ assert(ByRefValueInfo.count(VD) && "Did not find value!");
+
+ return ByRefValueInfo.find(VD)->second.second;
+}
+
+llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
+ const VarDecl *V) {
+ llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
+ Loc = Builder.CreateLoad(Loc);
+ Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
+ V->getNameAsString());
+ return Loc;
+}
+
+/// BuildByRefType - This routine changes a __block variable declared as T x
+/// into:
+///
+/// struct {
+/// void *__isa;
+/// void *__forwarding;
+/// int32_t __flags;
+/// int32_t __size;
+/// void *__copy_helper; // only if needed
+/// void *__destroy_helper; // only if needed
+/// char padding[X]; // only if needed
+/// T x;
+/// } x
+///
+const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) {
+ std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
+ if (Info.first)
+ return Info.first;
+
+ QualType Ty = D->getType();
+
+ std::vector<const llvm::Type *> Types;
+
+ llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext());
+
+ // void *__isa;
+ Types.push_back(Int8PtrTy);
+
+ // void *__forwarding;
+ Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder));
+
+ // int32_t __flags;
+ Types.push_back(Int32Ty);
+
+ // int32_t __size;
+ Types.push_back(Int32Ty);
+
+ bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty);
+ if (HasCopyAndDispose) {
+ /// void *__copy_helper;
+ Types.push_back(Int8PtrTy);
+
+ /// void *__destroy_helper;
+ Types.push_back(Int8PtrTy);
+ }
+
+ bool Packed = false;
+ CharUnits Align = getContext().getDeclAlign(D);
+ if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) {
+ // We have to insert padding.
+
+ // The struct above has 2 32-bit integers.
+ unsigned CurrentOffsetInBytes = 4 * 2;
+
+ // And either 2 or 4 pointers.
+ CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) *
+ CGM.getTargetData().getTypeAllocSize(Int8PtrTy);
+
+ // Align the offset.
+ unsigned AlignedOffsetInBytes =
+ llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
+
+ unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
+ if (NumPaddingBytes > 0) {
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext());
+ // FIXME: We need a sema error for alignment larger than the minimum of
+ // the maximal stack alignmint and the alignment of malloc on the system.
+ if (NumPaddingBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
+
+ Types.push_back(Ty);
+
+ // We want a packed struct.
+ Packed = true;
+ }
+ }
+
+ // T x;
+ Types.push_back(ConvertTypeForMem(Ty));
+
+ const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed);
+
+ cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T);
+ CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(),
+ ByRefTypeHolder.get());
+
+ Info.first = ByRefTypeHolder.get();
+
+ Info.second = Types.size() - 1;
+
+ return Info.first;
+}
+
+namespace {
+ struct CallArrayDtor : EHScopeStack::Cleanup {
+ CallArrayDtor(const CXXDestructorDecl *Dtor,
+ const ConstantArrayType *Type,
+ llvm::Value *Loc)
+ : Dtor(Dtor), Type(Type), Loc(Loc) {}
+
+ const CXXDestructorDecl *Dtor;
+ const ConstantArrayType *Type;
+ llvm::Value *Loc;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ QualType BaseElementTy = CGF.getContext().getBaseElementType(Type);
+ const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(Loc, BasePtr);
+ CGF.EmitCXXAggrDestructorCall(Dtor, Type, BaseAddrPtr);
+ }
+ };
+
+ struct CallVarDtor : EHScopeStack::Cleanup {
+ CallVarDtor(const CXXDestructorDecl *Dtor,
+ llvm::Value *NRVOFlag,
+ llvm::Value *Loc)
+ : Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(Loc) {}
+
+ const CXXDestructorDecl *Dtor;
+ llvm::Value *NRVOFlag;
+ llvm::Value *Loc;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // Along the exceptions path we always execute the dtor.
+ bool NRVO = !IsForEH && NRVOFlag;
+
+ llvm::BasicBlock *SkipDtorBB = 0;
+ if (NRVO) {
+ // If we exited via NRVO, we skip the destructor call.
+ llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused");
+ SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor");
+ llvm::Value *DidNRVO = CGF.Builder.CreateLoad(NRVOFlag, "nrvo.val");
+ CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB);
+ CGF.EmitBlock(RunDtorBB);
+ }
+
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false, Loc);
+
+ if (NRVO) CGF.EmitBlock(SkipDtorBB);
+ }
+ };
+}
+
+namespace {
+ struct CallStackRestore : EHScopeStack::Cleanup {
+ llvm::Value *Stack;
+ CallStackRestore(llvm::Value *Stack) : Stack(Stack) {}
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::Value *V = CGF.Builder.CreateLoad(Stack, "tmp");
+ llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
+ CGF.Builder.CreateCall(F, V);
+ }
+ };
+
+ struct CallCleanupFunction : EHScopeStack::Cleanup {
+ llvm::Constant *CleanupFn;
+ const CGFunctionInfo &FnInfo;
+ llvm::Value *Addr;
+ const VarDecl &Var;
+
+ CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
+ llvm::Value *Addr, const VarDecl *Var)
+ : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // In some cases, the type of the function argument will be different from
+ // the type of the pointer. An example of this is
+ // void f(void* arg);
+ // __attribute__((cleanup(f))) void *g;
+ //
+ // To fix this we insert a bitcast here.
+ QualType ArgTy = FnInfo.arg_begin()->type;
+ llvm::Value *Arg =
+ CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy));
+
+ CallArgList Args;
+ Args.push_back(std::make_pair(RValue::get(Arg),
+ CGF.getContext().getPointerType(Var.getType())));
+ CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args);
+ }
+ };
+
+ struct CallBlockRelease : EHScopeStack::Cleanup {
+ llvm::Value *Addr;
+ CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
+ }
+ };
+}
+
+
+/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the
+/// non-zero parts of the specified initializer with equal or fewer than
+/// NumStores scalar stores.
+static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
+ unsigned &NumStores) {
+ // Zero and Undef never requires any extra stores.
+ if (isa<llvm::ConstantAggregateZero>(Init) ||
+ isa<llvm::ConstantPointerNull>(Init) ||
+ isa<llvm::UndefValue>(Init))
+ return true;
+ if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
+ isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
+ isa<llvm::ConstantExpr>(Init))
+ return Init->isNullValue() || NumStores--;
+
+ // See if we can emit each element.
+ if (isa<llvm::ConstantArray>(Init) || isa<llvm::ConstantStruct>(Init)) {
+ for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
+ llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i));
+ if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores))
+ return false;
+ }
+ return true;
+ }
+
+ // Anything else is hard and scary.
+ return false;
+}
+
+/// emitStoresForInitAfterMemset - For inits that
+/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
+/// stores that would be required.
+static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
+ CGBuilderTy &Builder) {
+ // Zero doesn't require any stores.
+ if (isa<llvm::ConstantAggregateZero>(Init) ||
+ isa<llvm::ConstantPointerNull>(Init) ||
+ isa<llvm::UndefValue>(Init))
+ return;
+
+ if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
+ isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
+ isa<llvm::ConstantExpr>(Init)) {
+ if (!Init->isNullValue())
+ Builder.CreateStore(Init, Loc);
+ return;
+ }
+
+ assert((isa<llvm::ConstantStruct>(Init) || isa<llvm::ConstantArray>(Init)) &&
+ "Unknown value type!");
+
+ for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
+ llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i));
+ if (Elt->isNullValue()) continue;
+
+ // Otherwise, get a pointer to the element and emit it.
+ emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
+ Builder);
+ }
+}
+
+
+/// shouldUseMemSetPlusStoresToInitialize - Decide whether we should use memset
+/// plus some stores to initialize a local variable instead of using a memcpy
+/// from a constant global. It is beneficial to use memset if the global is all
+/// zeros, or mostly zeros and large.
+static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
+ uint64_t GlobalSize) {
+ // If a global is all zeros, always use a memset.
+ if (isa<llvm::ConstantAggregateZero>(Init)) return true;
+
+
+ // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large,
+ // do it if it will require 6 or fewer scalar stores.
+ // TODO: Should budget depends on the size? Avoiding a large global warrants
+ // plopping in more stores.
+ unsigned StoreBudget = 6;
+ uint64_t SizeLimit = 32;
+
+ return GlobalSize > SizeLimit &&
+ canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);
+}
+
+
+/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
+/// variable declaration with auto, register, or no storage class specifier.
+/// These turn into simple stack objects, or GlobalValues depending on target.
+void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
+ SpecialInitFn *SpecialInit) {
+ QualType Ty = D.getType();
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+ bool isByRef = D.hasAttr<BlocksAttr>();
+ bool needsDispose = false;
+ CharUnits Align = CharUnits::Zero();
+ bool IsSimpleConstantInitializer = false;
+
+ bool NRVO = false;
+ llvm::Value *NRVOFlag = 0;
+ llvm::Value *DeclPtr;
+ if (Ty->isConstantSizeType()) {
+ if (!Target.useGlobalsForAutomaticVariables()) {
+ NRVO = getContext().getLangOptions().ElideConstructors &&
+ D.isNRVOVariable();
+ // If this value is an array or struct, is POD, and if the initializer is
+ // a staticly determinable constant, try to optimize it (unless the NRVO
+ // is already optimizing this).
+ if (!NRVO && D.getInit() && !isByRef &&
+ (Ty->isArrayType() || Ty->isRecordType()) &&
+ Ty->isPODType() &&
+ D.getInit()->isConstantInitializer(getContext(), false)) {
+ // If this variable is marked 'const', emit the value as a global.
+ if (CGM.getCodeGenOpts().MergeAllConstants &&
+ Ty.isConstant(getContext())) {
+ EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
+ return;
+ }
+
+ IsSimpleConstantInitializer = true;
+ }
+
+ // A normal fixed sized variable becomes an alloca in the entry block,
+ // unless it's an NRVO variable.
+ const llvm::Type *LTy = ConvertTypeForMem(Ty);
+
+ if (NRVO) {
+ // The named return value optimization: allocate this variable in the
+ // return slot, so that we can elide the copy when returning this
+ // variable (C++0x [class.copy]p34).
+ DeclPtr = ReturnValue;
+
+ if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
+ if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) {
+ // Create a flag that is used to indicate when the NRVO was applied
+ // to this variable. Set it to zero to indicate that NRVO was not
+ // applied.
+ llvm::Value *Zero = Builder.getFalse();
+ NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+ EnsureInsertPoint();
+ Builder.CreateStore(Zero, NRVOFlag);
+
+ // Record the NRVO flag for this variable.
+ NRVOFlags[&D] = NRVOFlag;
+ }
+ }
+ } else {
+ if (isByRef)
+ LTy = BuildByRefType(&D);
+
+ llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
+ Alloc->setName(D.getNameAsString());
+
+ Align = getContext().getDeclAlign(&D);
+ if (isByRef)
+ Align = std::max(Align,
+ getContext().toCharUnitsFromBits(Target.getPointerAlign(0)));
+ Alloc->setAlignment(Align.getQuantity());
+ DeclPtr = Alloc;
+ }
+ } else {
+ // Targets that don't support recursion emit locals as globals.
+ const char *Class =
+ D.getStorageClass() == SC_Register ? ".reg." : ".auto.";
+ DeclPtr = CreateStaticVarDecl(D, Class,
+ llvm::GlobalValue::InternalLinkage);
+ }
+
+ // FIXME: Can this happen?
+ if (Ty->isVariablyModifiedType())
+ EmitVLASize(Ty);
+ } else {
+ EnsureInsertPoint();
+
+ if (!DidCallStackSave) {
+ // Save the stack.
+ llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
+
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
+ llvm::Value *V = Builder.CreateCall(F);
+
+ Builder.CreateStore(V, Stack);
+
+ DidCallStackSave = true;
+
+ // Push a cleanup block and restore the stack there.
+ // FIXME: in general circumstances, this should be an EH cleanup.
+ EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack);
+ }
+
+ // Get the element type.
+ const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
+ const llvm::Type *LElemPtrTy = LElemTy->getPointerTo(Ty.getAddressSpace());
+
+ llvm::Value *VLASize = EmitVLASize(Ty);
+
+ // Allocate memory for the array.
+ llvm::AllocaInst *VLA =
+ Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
+ VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+
+ DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
+ }
+
+ llvm::Value *&DMEntry = LocalDeclMap[&D];
+ assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+ DMEntry = DeclPtr;
+
+ // Emit debug info for local var declaration.
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ assert(HaveInsertPoint() && "Unexpected unreachable point!");
+
+ DI->setLocation(D.getLocation());
+ if (Target.useGlobalsForAutomaticVariables()) {
+ DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D);
+ } else
+ DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
+ }
+
+ // If this local has an initializer, emit it now.
+ const Expr *Init = D.getInit();
+
+ // If we are at an unreachable point, we don't need to emit the initializer
+ // unless it contains a label.
+ if (!HaveInsertPoint()) {
+ if (!ContainsLabel(Init))
+ Init = 0;
+ else
+ EnsureInsertPoint();
+ }
+
+ if (isByRef) {
+ EnsureInsertPoint();
+ llvm::Value *V;
+
+ BlockFieldFlags fieldFlags;
+ bool fieldNeedsCopyDispose = false;
+
+ needsDispose = true;
+
+ if (Ty->isBlockPointerType()) {
+ fieldFlags |= BLOCK_FIELD_IS_BLOCK;
+ fieldNeedsCopyDispose = true;
+ } else if (getContext().isObjCNSObjectType(Ty) ||
+ Ty->isObjCObjectPointerType()) {
+ fieldFlags |= BLOCK_FIELD_IS_OBJECT;
+ fieldNeedsCopyDispose = true;
+ } else if (getLangOptions().CPlusPlus) {
+ if (getContext().getBlockVarCopyInits(&D))
+ fieldNeedsCopyDispose = true;
+ else if (const CXXRecordDecl *record = D.getType()->getAsCXXRecordDecl())
+ fieldNeedsCopyDispose = !record->hasTrivialDestructor();
+ }
+
+ // FIXME: Someone double check this.
+ if (Ty.isObjCGCWeak())
+ fieldFlags |= BLOCK_FIELD_IS_WEAK;
+
+ int isa = 0;
+ if (fieldFlags & BLOCK_FIELD_IS_WEAK)
+ isa = 1;
+ V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
+ Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa"));
+
+ Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1,
+ "byref.forwarding"));
+
+ // Blocks ABI:
+ // c) the flags field is set to either 0 if no helper functions are
+ // needed or BLOCK_HAS_COPY_DISPOSE if they are,
+ BlockFlags flags;
+ if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
+ Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ Builder.CreateStructGEP(DeclPtr, 2, "byref.flags"));
+
+ const llvm::Type *V1;
+ V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+ V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
+ Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size"));
+
+ if (fieldNeedsCopyDispose) {
+ llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
+ Builder.CreateStore(CGM.BuildbyrefCopyHelper(DeclPtr->getType(),
+ fieldFlags,
+ Align.getQuantity(), &D),
+ copy_helper);
+
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
+ Builder.CreateStore(CGM.BuildbyrefDestroyHelper(DeclPtr->getType(),
+ fieldFlags,
+ Align.getQuantity(), &D),
+ destroy_helper);
+ }
+ }
+
+ if (SpecialInit) {
+ SpecialInit(*this, D, DeclPtr);
+ } else if (Init) {
+ llvm::Value *Loc = DeclPtr;
+
+ bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
+
+ // If the initializer was a simple constant initializer, we can optimize it
+ // in various ways.
+ if (IsSimpleConstantInitializer) {
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this);
+ assert(Init != 0 && "Wasn't a simple constant init?");
+
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(IntPtrTy,
+ getContext().getTypeSizeInChars(Ty).getQuantity());
+
+ const llvm::Type *BP = Int8PtrTy;
+ if (Loc->getType() != BP)
+ Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+
+ // If the initializer is all or mostly zeros, codegen with memset then do
+ // a few stores afterward.
+ if (shouldUseMemSetPlusStoresToInitialize(Init,
+ CGM.getTargetData().getTypeAllocSize(Init->getType()))) {
+ Builder.CreateMemSet(Loc, Builder.getInt8(0), SizeVal,
+ Align.getQuantity(), false);
+ if (!Init->isNullValue()) {
+ Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
+ emitStoresForInitAfterMemset(Init, Loc, Builder);
+ }
+
+ } else {
+ // Otherwise, create a temporary global with the initializer then
+ // memcpy from the global to the alloca.
+ std::string Name = GetStaticDeclName(*this, D, ".");
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ Init, Name, 0, false, 0);
+ GV->setAlignment(Align.getQuantity());
+
+ llvm::Value *SrcPtr = GV;
+ if (SrcPtr->getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
+
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, Align.getQuantity(), false);
+ }
+ } else if (Ty->isReferenceType()) {
+ RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+ EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
+ } else if (!hasAggregateLLVMType(Init->getType())) {
+ llvm::Value *V = EmitScalarExpr(Init);
+ if (isByRef) {
+ // When RHS has side-effect, must go through "forwarding' field
+ // to get to the address of the __block variable descriptor.
+ if (Init->HasSideEffects(getContext()))
+ Loc = BuildBlockByrefAddress(DeclPtr, &D);
+ else
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+ }
+ EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
+ } else if (Init->getType()->isAnyComplexType()) {
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+ EmitComplexExprIntoAddr(Init, Loc, isVolatile);
+ } else {
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+ EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
+ }
+ }
+
+ // Handle CXX destruction of variables.
+ QualType DtorTy(Ty);
+ while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
+ DtorTy = getContext().getBaseElementType(Array);
+ if (const RecordType *RT = DtorTy->getAs<RecordType>())
+ if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (!ClassDecl->hasTrivialDestructor()) {
+ // Note: We suppress the destructor call when the corresponding NRVO
+ // flag has been set.
+ llvm::Value *Loc = DeclPtr;
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+
+ const CXXDestructorDecl *D = ClassDecl->getDestructor();
+ assert(D && "EmitLocalBlockVarDecl - destructor is nul");
+
+ if (const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(Ty)) {
+ EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup,
+ D, Array, Loc);
+ } else {
+ EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup,
+ D, NRVOFlag, Loc);
+ }
+ }
+ }
+
+ // Handle the cleanup attribute
+ if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
+ const FunctionDecl *FD = CA->getFunctionDecl();
+
+ llvm::Constant* F = CGM.GetAddrOfFunction(FD);
+ assert(F && "Could not find function!");
+
+ const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
+ EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup,
+ F, &Info, DeclPtr, &D);
+ }
+
+ // If this is a block variable, clean it up.
+ if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
+ EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, DeclPtr);
+}
+
+/// Emit an alloca (or GlobalValue depending on target)
+/// for the specified parameter and set up LocalDeclMap.
+void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
+ // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
+ assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
+ "Invalid argument to EmitParmDecl");
+ QualType Ty = D.getType();
+
+ llvm::Value *DeclPtr;
+ // If this is an aggregate or variable sized value, reuse the input pointer.
+ if (!Ty->isConstantSizeType() ||
+ CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ DeclPtr = Arg;
+ } else {
+ // Otherwise, create a temporary to hold the value.
+ DeclPtr = CreateMemTemp(Ty, D.getName() + ".addr");
+
+ // Store the initial value into the alloca.
+ EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(),
+ getContext().getDeclAlign(&D).getQuantity(), Ty,
+ CGM.getTBAAInfo(Ty));
+ }
+ Arg->setName(D.getName());
+
+ llvm::Value *&DMEntry = LocalDeclMap[&D];
+ assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
+ DMEntry = DeclPtr;
+
+ // Emit debug info for param declaration.
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
new file mode 100644
index 0000000..e295267
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -0,0 +1,341 @@
+//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with code generation of C++ declarations
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CGObjCRuntime.h"
+#include "CGCXXABI.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Intrinsics.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::Constant *DeclPtr) {
+ assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
+ assert(!D.getType()->isReferenceType() &&
+ "Should not call EmitDeclInit on a reference!");
+
+ ASTContext &Context = CGF.getContext();
+
+ const Expr *Init = D.getInit();
+ QualType T = D.getType();
+ bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
+
+ unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
+ if (!CGF.hasAggregateLLVMType(T)) {
+ llvm::Value *V = CGF.EmitScalarExpr(Init);
+ CodeGenModule &CGM = CGF.CGM;
+ Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
+ if (GCAttr == Qualifiers::Strong)
+ CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
+ D.isThreadSpecified());
+ else if (GCAttr == Qualifiers::Weak)
+ CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
+ else
+ CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
+ } else if (T->isAnyComplexType()) {
+ CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
+ } else {
+ CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
+ }
+}
+
+/// Emit code to cause the destruction of the given variable with
+/// static storage duration.
+static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::Constant *DeclPtr) {
+ CodeGenModule &CGM = CGF.CGM;
+ ASTContext &Context = CGF.getContext();
+
+ QualType T = D.getType();
+
+ // Drill down past array types.
+ const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
+ if (Array)
+ T = Context.getBaseElementType(Array);
+
+ /// If that's not a record, we're done.
+ /// FIXME: __attribute__((cleanup)) ?
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return;
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialDestructor())
+ return;
+
+ CXXDestructorDecl *Dtor = RD->getDestructor();
+
+ llvm::Constant *DtorFn;
+ if (Array) {
+ DtorFn =
+ CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
+ DeclPtr);
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
+ } else
+ DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
+
+ CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
+}
+
+void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
+ llvm::Constant *DeclPtr) {
+
+ const Expr *Init = D.getInit();
+ QualType T = D.getType();
+
+ if (!T->isReferenceType()) {
+ EmitDeclInit(*this, D, DeclPtr);
+ EmitDeclDestroy(*this, D, DeclPtr);
+ return;
+ }
+
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+ RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
+}
+
+void
+CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
+ llvm::Constant *DeclPtr) {
+ // Generate a global destructor entry if not using __cxa_atexit.
+ if (!CGM.getCodeGenOpts().CXAAtExit) {
+ CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
+ return;
+ }
+
+ std::vector<const llvm::Type *> Params;
+ Params.push_back(Int8PtrTy);
+
+ // Get the destructor function type
+ const llvm::Type *DtorFnTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
+ Params, false);
+ DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
+
+ Params.clear();
+ Params.push_back(DtorFnTy);
+ Params.push_back(Int8PtrTy);
+ Params.push_back(Int8PtrTy);
+
+ // Get the __cxa_atexit function type
+ // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
+ const llvm::FunctionType *AtExitFnTy =
+ llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
+
+ llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
+ "__cxa_atexit");
+
+ llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
+ "__dso_handle");
+ llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
+ llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
+ llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
+ Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
+}
+
+void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr) {
+ CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
+}
+
+static llvm::Function *
+CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
+ const llvm::FunctionType *FTy,
+ llvm::StringRef Name) {
+ llvm::Function *Fn =
+ llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
+ Name, &CGM.getModule());
+ if (!CGM.getContext().getLangOptions().AppleKext) {
+ // Set the section if needed.
+ if (const char *Section =
+ CGM.getContext().Target.getStaticInitSectionSpecifier())
+ Fn->setSection(Section);
+ }
+
+ if (!CGM.getLangOptions().areExceptionsEnabled())
+ Fn->setDoesNotThrow();
+
+ return Fn;
+}
+
+void
+CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
+
+ // Create a variable initialization function.
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
+
+ CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
+
+ if (D->hasAttr<InitPriorityAttr>()) {
+ unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
+ OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
+ PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
+ DelayedCXXInitPosition.erase(D);
+ }
+ else {
+ llvm::DenseMap<const Decl *, unsigned>::iterator I =
+ DelayedCXXInitPosition.find(D);
+ if (I == DelayedCXXInitPosition.end()) {
+ CXXGlobalInits.push_back(Fn);
+ } else {
+ assert(CXXGlobalInits[I->second] == 0);
+ CXXGlobalInits[I->second] = Fn;
+ DelayedCXXInitPosition.erase(I);
+ }
+ }
+}
+
+void
+CodeGenModule::EmitCXXGlobalInitFunc() {
+ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
+ CXXGlobalInits.pop_back();
+
+ if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
+ return;
+
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
+
+ // Create our global initialization function.
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
+
+ if (!PrioritizedCXXGlobalInits.empty()) {
+ llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
+ llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
+ PrioritizedCXXGlobalInits.end());
+ for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
+ llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
+ LocalCXXGlobalInits.push_back(Fn);
+ }
+ LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
+ &LocalCXXGlobalInits[0],
+ LocalCXXGlobalInits.size());
+ }
+ else
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
+ &CXXGlobalInits[0],
+ CXXGlobalInits.size());
+ AddGlobalCtor(Fn);
+}
+
+void CodeGenModule::EmitCXXGlobalDtorFunc() {
+ if (CXXGlobalDtors.empty())
+ return;
+
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
+
+ // Create our global destructor function.
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
+
+ CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
+ AddGlobalDtor(Fn);
+}
+
+/// Emit the code necessary to initialize the given global variable.
+void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
+ const VarDecl *D,
+ llvm::GlobalVariable *Addr) {
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
+ SourceLocation());
+
+ // Use guarded initialization if the global variable is weak due to
+ // being a class template's static data member.
+ if (Addr->hasWeakLinkage() && D->getInstantiatedFromStaticDataMember()) {
+ EmitCXXGuardedInit(*D, Addr);
+ } else {
+ EmitCXXGlobalVarDeclInit(*D, Addr);
+ }
+
+ FinishFunction();
+}
+
+void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
+ llvm::Constant **Decls,
+ unsigned NumDecls) {
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
+ SourceLocation());
+
+ for (unsigned i = 0; i != NumDecls; ++i)
+ if (Decls[i])
+ Builder.CreateCall(Decls[i]);
+
+ FinishFunction();
+}
+
+void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
+ const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
+ &DtorsAndObjects) {
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
+ SourceLocation());
+
+ // Emit the dtors, in reverse order from construction.
+ for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
+ llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
+ llvm::CallInst *CI = Builder.CreateCall(Callee,
+ DtorsAndObjects[e - i - 1].second);
+ // Make sure the call and the callee agree on calling convention.
+ if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
+ CI->setCallingConv(F->getCallingConv());
+ }
+
+ FinishFunction();
+}
+
+/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
+/// invoked, calls the default destructor on array elements in reverse order of
+/// construction.
+llvm::Function *
+CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This) {
+ FunctionArgList Args;
+ ImplicitParamDecl *Dst =
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Dst, Dst->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
+ FunctionType::ExtInfo());
+ const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
+
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
+
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
+ llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
+
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+
+ FinishFunction();
+
+ return Fn;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
new file mode 100644
index 0000000..6181965
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -0,0 +1,1456 @@
+//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ exception related code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtCXX.h"
+
+#include "llvm/Intrinsics.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Support/CallSite.h"
+
+#include "CGObjCRuntime.h"
+#include "CodeGenFunction.h"
+#include "CGException.h"
+#include "CGCleanup.h"
+#include "TargetInfo.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
+ // void *__cxa_allocate_exception(size_t thrown_size);
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+ std::vector<const llvm::Type*> Args(1, SizeTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
+}
+
+static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) {
+ // void __cxa_free_exception(void *thrown_exception);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
+}
+
+static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
+ // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
+ // void (*dest) (void *));
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(3, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
+}
+
+static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) {
+ // void __cxa_rethrow();
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
+}
+
+static llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) {
+ // void *__cxa_get_exception_ptr(void*);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(Int8PtrTy, Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
+}
+
+static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) {
+ // void *__cxa_begin_catch(void*);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(Int8PtrTy, Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
+}
+
+static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) {
+ // void __cxa_end_catch();
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
+}
+
+static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) {
+ // void __cxa_call_unexepcted(void *thrown_exception);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
+}
+
+llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args,
+ false);
+
+ if (CGM.getLangOptions().SjLjExceptions)
+ return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow");
+ return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
+}
+
+static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
+ // void __terminate();
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy,
+ CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort");
+}
+
+static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF,
+ llvm::StringRef Name) {
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext());
+ const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, Name);
+}
+
+const EHPersonality EHPersonality::GNU_C("__gcc_personality_v0");
+const EHPersonality EHPersonality::GNU_C_SJLJ("__gcc_personality_sj0");
+const EHPersonality EHPersonality::NeXT_ObjC("__objc_personality_v0");
+const EHPersonality EHPersonality::GNU_CPlusPlus("__gxx_personality_v0");
+const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ("__gxx_personality_sj0");
+const EHPersonality EHPersonality::GNU_ObjC("__gnu_objc_personality_v0",
+ "objc_exception_throw");
+
+static const EHPersonality &getCPersonality(const LangOptions &L) {
+ if (L.SjLjExceptions)
+ return EHPersonality::GNU_C_SJLJ;
+ return EHPersonality::GNU_C;
+}
+
+static const EHPersonality &getObjCPersonality(const LangOptions &L) {
+ if (L.NeXTRuntime) {
+ if (L.ObjCNonFragileABI) return EHPersonality::NeXT_ObjC;
+ else return getCPersonality(L);
+ } else {
+ return EHPersonality::GNU_ObjC;
+ }
+}
+
+static const EHPersonality &getCXXPersonality(const LangOptions &L) {
+ if (L.SjLjExceptions)
+ return EHPersonality::GNU_CPlusPlus_SJLJ;
+ else
+ return EHPersonality::GNU_CPlusPlus;
+}
+
+/// Determines the personality function to use when both C++
+/// and Objective-C exceptions are being caught.
+static const EHPersonality &getObjCXXPersonality(const LangOptions &L) {
+ // The ObjC personality defers to the C++ personality for non-ObjC
+ // handlers. Unlike the C++ case, we use the same personality
+ // function on targets using (backend-driven) SJLJ EH.
+ if (L.NeXTRuntime) {
+ if (L.ObjCNonFragileABI)
+ return EHPersonality::NeXT_ObjC;
+
+ // In the fragile ABI, just use C++ exception handling and hope
+ // they're not doing crazy exception mixing.
+ else
+ return getCXXPersonality(L);
+ }
+
+ // The GNU runtime's personality function inherently doesn't support
+ // mixed EH. Use the C++ personality just to avoid returning null.
+ return getCXXPersonality(L);
+}
+
+const EHPersonality &EHPersonality::get(const LangOptions &L) {
+ if (L.CPlusPlus && L.ObjC1)
+ return getObjCXXPersonality(L);
+ else if (L.CPlusPlus)
+ return getCXXPersonality(L);
+ else if (L.ObjC1)
+ return getObjCPersonality(L);
+ else
+ return getCPersonality(L);
+}
+
+static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
+ const EHPersonality &Personality) {
+ llvm::Constant *Fn =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::Type::getInt32Ty(CGM.getLLVMContext()),
+ true),
+ Personality.getPersonalityFnName());
+ return Fn;
+}
+
+static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
+ const EHPersonality &Personality) {
+ llvm::Constant *Fn = getPersonalityFn(CGM, Personality);
+ return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
+}
+
+/// Check whether a personality function could reasonably be swapped
+/// for a C++ personality function.
+static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
+ for (llvm::Constant::use_iterator
+ I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) {
+ llvm::User *User = *I;
+
+ // Conditionally white-list bitcasts.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) {
+ if (CE->getOpcode() != llvm::Instruction::BitCast) return false;
+ if (!PersonalityHasOnlyCXXUses(CE))
+ return false;
+ continue;
+ }
+
+ // Otherwise, it has to be a selector call.
+ if (!isa<llvm::EHSelectorInst>(User)) return false;
+
+ llvm::EHSelectorInst *Selector = cast<llvm::EHSelectorInst>(User);
+ for (unsigned I = 2, E = Selector->getNumArgOperands(); I != E; ++I) {
+ // Look for something that would've been returned by the ObjC
+ // runtime's GetEHType() method.
+ llvm::GlobalVariable *GV
+ = dyn_cast<llvm::GlobalVariable>(Selector->getArgOperand(I));
+ if (!GV) continue;
+
+ // ObjC EH selector entries are always global variables with
+ // names starting like this.
+ if (GV->getName().startswith("OBJC_EHTYPE"))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/// Try to use the C++ personality function in ObjC++. Not doing this
+/// can cause some incompatibilities with gcc, which is more
+/// aggressive about only using the ObjC++ personality in a function
+/// when it really needs it.
+void CodeGenModule::SimplifyPersonality() {
+ // For now, this is really a Darwin-specific operation.
+ if (Context.Target.getTriple().getOS() != llvm::Triple::Darwin)
+ return;
+
+ // If we're not in ObjC++ -fexceptions, there's nothing to do.
+ if (!Features.CPlusPlus || !Features.ObjC1 || !Features.Exceptions)
+ return;
+
+ const EHPersonality &ObjCXX = EHPersonality::get(Features);
+ const EHPersonality &CXX = getCXXPersonality(Features);
+ if (&ObjCXX == &CXX ||
+ ObjCXX.getPersonalityFnName() == CXX.getPersonalityFnName())
+ return;
+
+ llvm::Function *Fn =
+ getModule().getFunction(ObjCXX.getPersonalityFnName());
+
+ // Nothing to do if it's unused.
+ if (!Fn || Fn->use_empty()) return;
+
+ // Can't do the optimization if it has non-C++ uses.
+ if (!PersonalityHasOnlyCXXUses(Fn)) return;
+
+ // Create the C++ personality function and kill off the old
+ // function.
+ llvm::Constant *CXXFn = getPersonalityFn(*this, CXX);
+
+ // This can happen if the user is screwing with us.
+ if (Fn->getType() != CXXFn->getType()) return;
+
+ Fn->replaceAllUsesWith(CXXFn);
+ Fn->eraseFromParent();
+}
+
+/// Returns the value to inject into a selector to indicate the
+/// presence of a catch-all.
+static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) {
+ // Possibly we should use @llvm.eh.catch.all.value here.
+ return llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
+}
+
+/// Returns the value to inject into a selector to indicate the
+/// presence of a cleanup.
+static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) {
+ return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
+}
+
+namespace {
+ /// A cleanup to free the exception object if its initialization
+ /// throws.
+ struct FreeException {
+ static void Emit(CodeGenFunction &CGF, bool forEH,
+ llvm::Value *exn) {
+ CGF.Builder.CreateCall(getFreeExceptionFn(CGF), exn)
+ ->setDoesNotThrow();
+ }
+ };
+}
+
+// Emits an exception expression into the given location. This
+// differs from EmitAnyExprToMem only in that, if a final copy-ctor
+// call is required, an exception within that copy ctor causes
+// std::terminate to be invoked.
+static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e,
+ llvm::Value *addr) {
+ // Make sure the exception object is cleaned up if there's an
+ // exception during initialization.
+ CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr);
+ EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin();
+
+ // __cxa_allocate_exception returns a void*; we need to cast this
+ // to the appropriate type for the object.
+ const llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo();
+ llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty);
+
+ // FIXME: this isn't quite right! If there's a final unelided call
+ // to a copy constructor, then according to [except.terminate]p1 we
+ // must call std::terminate() if that constructor throws, because
+ // technically that copy occurs after the exception expression is
+ // evaluated but before the exception is caught. But the best way
+ // to handle that is to teach EmitAggExpr to do the final copy
+ // differently if it can't be elided.
+ CGF.EmitAnyExprToMem(e, typedAddr, /*Volatile*/ false, /*IsInit*/ true);
+
+ // Deactivate the cleanup block.
+ CGF.DeactivateCleanupBlock(cleanup);
+}
+
+llvm::Value *CodeGenFunction::getExceptionSlot() {
+ if (!ExceptionSlot) {
+ const llvm::Type *i8p = llvm::Type::getInt8PtrTy(getLLVMContext());
+ ExceptionSlot = CreateTempAlloca(i8p, "exn.slot");
+ }
+ return ExceptionSlot;
+}
+
+void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
+ if (!E->getSubExpr()) {
+ if (getInvokeDest()) {
+ Builder.CreateInvoke(getReThrowFn(*this),
+ getUnreachableBlock(),
+ getInvokeDest())
+ ->setDoesNotReturn();
+ } else {
+ Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn();
+ Builder.CreateUnreachable();
+ }
+
+ // throw is an expression, and the expression emitters expect us
+ // to leave ourselves at a valid insertion point.
+ EmitBlock(createBasicBlock("throw.cont"));
+
+ return;
+ }
+
+ QualType ThrowType = E->getSubExpr()->getType();
+
+ // Now allocate the exception object.
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
+
+ llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
+ llvm::CallInst *ExceptionPtr =
+ Builder.CreateCall(AllocExceptionFn,
+ llvm::ConstantInt::get(SizeTy, TypeSize),
+ "exception");
+ ExceptionPtr->setDoesNotThrow();
+
+ EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr);
+
+ // Now throw the exception.
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
+ llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
+ /*ForEH=*/true);
+
+ // The address of the destructor. If the exception type has a
+ // trivial destructor (or isn't a record), we just pass null.
+ llvm::Constant *Dtor = 0;
+ if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!Record->hasTrivialDestructor()) {
+ CXXDestructorDecl *DtorD = Record->getDestructor();
+ Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete);
+ Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy);
+ }
+ }
+ if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy);
+
+ if (getInvokeDest()) {
+ llvm::InvokeInst *ThrowCall =
+ Builder.CreateInvoke3(getThrowFn(*this),
+ getUnreachableBlock(), getInvokeDest(),
+ ExceptionPtr, TypeInfo, Dtor);
+ ThrowCall->setDoesNotReturn();
+ } else {
+ llvm::CallInst *ThrowCall =
+ Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
+ ThrowCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+ }
+
+ // throw is an expression, and the expression emitters expect us
+ // to leave ourselves at a valid insertion point.
+ EmitBlock(createBasicBlock("throw.cont"));
+}
+
+void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
+ if (!CGM.getLangOptions().areExceptionsEnabled())
+ return;
+
+ const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (FD == 0)
+ return;
+ const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
+ if (Proto == 0)
+ return;
+
+ assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");
+
+ if (!Proto->hasExceptionSpec())
+ return;
+
+ unsigned NumExceptions = Proto->getNumExceptions();
+ EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
+
+ for (unsigned I = 0; I != NumExceptions; ++I) {
+ QualType Ty = Proto->getExceptionType(I);
+ QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType();
+ llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType,
+ /*ForEH=*/true);
+ Filter->setFilter(I, EHType);
+ }
+}
+
+void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
+ if (!CGM.getLangOptions().areExceptionsEnabled())
+ return;
+
+ const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (FD == 0)
+ return;
+ const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
+ if (Proto == 0)
+ return;
+
+ if (!Proto->hasExceptionSpec())
+ return;
+
+ EHStack.popFilter();
+}
+
+void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
+ EnterCXXTryStmt(S);
+ EmitStmt(S.getTryBlock());
+ ExitCXXTryStmt(S);
+}
+
+void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
+ unsigned NumHandlers = S.getNumHandlers();
+ EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);
+
+ for (unsigned I = 0; I != NumHandlers; ++I) {
+ const CXXCatchStmt *C = S.getHandler(I);
+
+ llvm::BasicBlock *Handler = createBasicBlock("catch");
+ if (C->getExceptionDecl()) {
+ // FIXME: Dropping the reference type on the type into makes it
+ // impossible to correctly implement catch-by-reference
+ // semantics for pointers. Unfortunately, this is what all
+ // existing compilers do, and it's not clear that the standard
+ // personality routine is capable of doing this right. See C++ DR 388:
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
+ QualType CaughtType = C->getCaughtType();
+ CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();
+
+ llvm::Value *TypeInfo = 0;
+ if (CaughtType->isObjCObjectPointerType())
+ TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
+ else
+ TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true);
+ CatchScope->setHandler(I, TypeInfo, Handler);
+ } else {
+ // No exception decl indicates '...', a catch-all.
+ CatchScope->setCatchAllHandler(I, Handler);
+ }
+ }
+}
+
+/// Check whether this is a non-EH scope, i.e. a scope which doesn't
+/// affect exception handling. Currently, the only non-EH scopes are
+/// normal-only cleanup scopes.
+static bool isNonEHScope(const EHScope &S) {
+ switch (S.getKind()) {
+ case EHScope::Cleanup:
+ return !cast<EHCleanupScope>(S).isEHCleanup();
+ case EHScope::Filter:
+ case EHScope::Catch:
+ case EHScope::Terminate:
+ return false;
+ }
+
+ // Suppress warning.
+ return false;
+}
+
+llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
+ assert(EHStack.requiresLandingPad());
+ assert(!EHStack.empty());
+
+ if (!CGM.getLangOptions().areExceptionsEnabled())
+ return 0;
+
+ // Check the innermost scope for a cached landing pad. If this is
+ // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
+ llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();
+ if (LP) return LP;
+
+ // Build the landing pad for this scope.
+ LP = EmitLandingPad();
+ assert(LP);
+
+ // Cache the landing pad on the innermost scope. If this is a
+ // non-EH scope, cache the landing pad on the enclosing scope, too.
+ for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) {
+ ir->setCachedLandingPad(LP);
+ if (!isNonEHScope(*ir)) break;
+ }
+
+ return LP;
+}
+
+llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
+ assert(EHStack.requiresLandingPad());
+
+ // This function contains a hack to work around a design flaw in
+ // LLVM's EH IR which breaks semantics after inlining. This same
+ // hack is implemented in llvm-gcc.
+ //
+ // The LLVM EH abstraction is basically a thin veneer over the
+ // traditional GCC zero-cost design: for each range of instructions
+ // in the function, there is (at most) one "landing pad" with an
+ // associated chain of EH actions. A language-specific personality
+ // function interprets this chain of actions and (1) decides whether
+ // or not to resume execution at the landing pad and (2) if so,
+ // provides an integer indicating why it's stopping. In LLVM IR,
+ // the association of a landing pad with a range of instructions is
+ // achieved via an invoke instruction, the chain of actions becomes
+ // the arguments to the @llvm.eh.selector call, and the selector
+ // call returns the integer indicator. Other than the required
+ // presence of two intrinsic function calls in the landing pad,
+ // the IR exactly describes the layout of the output code.
+ //
+ // A principal advantage of this design is that it is completely
+ // language-agnostic; in theory, the LLVM optimizers can treat
+ // landing pads neutrally, and targets need only know how to lower
+ // the intrinsics to have a functioning exceptions system (assuming
+ // that platform exceptions follow something approximately like the
+ // GCC design). Unfortunately, landing pads cannot be combined in a
+ // language-agnostic way: given selectors A and B, there is no way
+ // to make a single landing pad which faithfully represents the
+ // semantics of propagating an exception first through A, then
+ // through B, without knowing how the personality will interpret the
+ // (lowered form of the) selectors. This means that inlining has no
+ // choice but to crudely chain invokes (i.e., to ignore invokes in
+ // the inlined function, but to turn all unwindable calls into
+ // invokes), which is only semantically valid if every unwind stops
+ // at every landing pad.
+ //
+ // Therefore, the invoke-inline hack is to guarantee that every
+ // landing pad has a catch-all.
+ const bool UseInvokeInlineHack = true;
+
+ for (EHScopeStack::iterator ir = EHStack.begin(); ; ) {
+ assert(ir != EHStack.end() &&
+ "stack requiring landing pad is nothing but non-EH scopes?");
+
+ // If this is a terminate scope, just use the singleton terminate
+ // landing pad.
+ if (isa<EHTerminateScope>(*ir))
+ return getTerminateLandingPad();
+
+ // If this isn't an EH scope, iterate; otherwise break out.
+ if (!isNonEHScope(*ir)) break;
+ ++ir;
+
+ // We haven't checked this scope for a cached landing pad yet.
+ if (llvm::BasicBlock *LP = ir->getCachedLandingPad())
+ return LP;
+ }
+
+ // Save the current IR generation state.
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ const EHPersonality &Personality = EHPersonality::get(getLangOptions());
+
+ // Create and configure the landing pad.
+ llvm::BasicBlock *LP = createBasicBlock("lpad");
+ EmitBlock(LP);
+
+ // Save the exception pointer. It's safe to use a single exception
+ // pointer per function because EH cleanups can never have nested
+ // try/catches.
+ llvm::CallInst *Exn =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
+ Exn->setDoesNotThrow();
+ Builder.CreateStore(Exn, getExceptionSlot());
+
+ // Build the selector arguments.
+ llvm::SmallVector<llvm::Value*, 8> EHSelector;
+ EHSelector.push_back(Exn);
+ EHSelector.push_back(getOpaquePersonalityFn(CGM, Personality));
+
+ // Accumulate all the handlers in scope.
+ llvm::DenseMap<llvm::Value*, UnwindDest> EHHandlers;
+ UnwindDest CatchAll;
+ bool HasEHCleanup = false;
+ bool HasEHFilter = false;
+ llvm::SmallVector<llvm::Value*, 8> EHFilters;
+ for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end();
+ I != E; ++I) {
+
+ switch (I->getKind()) {
+ case EHScope::Cleanup:
+ if (!HasEHCleanup)
+ HasEHCleanup = cast<EHCleanupScope>(*I).isEHCleanup();
+ // We otherwise don't care about cleanups.
+ continue;
+
+ case EHScope::Filter: {
+ assert(I.next() == EHStack.end() && "EH filter is not end of EH stack");
+ assert(!CatchAll.isValid() && "EH filter reached after catch-all");
+
+ // Filter scopes get added to the selector in wierd ways.
+ EHFilterScope &Filter = cast<EHFilterScope>(*I);
+ HasEHFilter = true;
+
+ // Add all the filter values which we aren't already explicitly
+ // catching.
+ for (unsigned I = 0, E = Filter.getNumFilters(); I != E; ++I) {
+ llvm::Value *FV = Filter.getFilter(I);
+ if (!EHHandlers.count(FV))
+ EHFilters.push_back(FV);
+ }
+ goto done;
+ }
+
+ case EHScope::Terminate:
+ // Terminate scopes are basically catch-alls.
+ assert(!CatchAll.isValid());
+ CatchAll = UnwindDest(getTerminateHandler(),
+ EHStack.getEnclosingEHCleanup(I),
+ cast<EHTerminateScope>(*I).getDestIndex());
+ goto done;
+
+ case EHScope::Catch:
+ break;
+ }
+
+ EHCatchScope &Catch = cast<EHCatchScope>(*I);
+ for (unsigned HI = 0, HE = Catch.getNumHandlers(); HI != HE; ++HI) {
+ EHCatchScope::Handler Handler = Catch.getHandler(HI);
+
+ // Catch-all. We should only have one of these per catch.
+ if (!Handler.Type) {
+ assert(!CatchAll.isValid());
+ CatchAll = UnwindDest(Handler.Block,
+ EHStack.getEnclosingEHCleanup(I),
+ Handler.Index);
+ continue;
+ }
+
+ // Check whether we already have a handler for this type.
+ UnwindDest &Dest = EHHandlers[Handler.Type];
+ if (Dest.isValid()) continue;
+
+ EHSelector.push_back(Handler.Type);
+ Dest = UnwindDest(Handler.Block,
+ EHStack.getEnclosingEHCleanup(I),
+ Handler.Index);
+ }
+
+ // Stop if we found a catch-all.
+ if (CatchAll.isValid()) break;
+ }
+
+ done:
+ unsigned LastToEmitInLoop = EHSelector.size();
+
+ // If we have a catch-all, add null to the selector.
+ if (CatchAll.isValid()) {
+ EHSelector.push_back(getCatchAllValue(*this));
+
+ // If we have an EH filter, we need to add those handlers in the
+ // right place in the selector, which is to say, at the end.
+ } else if (HasEHFilter) {
+ // Create a filter expression: an integer constant saying how many
+ // filters there are (+1 to avoid ambiguity with 0 for cleanup),
+ // followed by the filter types. The personality routine only
+ // lands here if the filter doesn't match.
+ EHSelector.push_back(llvm::ConstantInt::get(Builder.getInt32Ty(),
+ EHFilters.size() + 1));
+ EHSelector.append(EHFilters.begin(), EHFilters.end());
+
+ // Also check whether we need a cleanup.
+ if (UseInvokeInlineHack || HasEHCleanup)
+ EHSelector.push_back(UseInvokeInlineHack
+ ? getCatchAllValue(*this)
+ : getCleanupValue(*this));
+
+ // Otherwise, signal that we at least have cleanups.
+ } else if (UseInvokeInlineHack || HasEHCleanup) {
+ EHSelector.push_back(UseInvokeInlineHack
+ ? getCatchAllValue(*this)
+ : getCleanupValue(*this));
+ } else {
+ assert(LastToEmitInLoop > 2);
+ LastToEmitInLoop--;
+ }
+
+ assert(EHSelector.size() >= 3 && "selector call has only two arguments!");
+
+ // Tell the backend how to generate the landing pad.
+ llvm::CallInst *Selection =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
+ EHSelector.begin(), EHSelector.end(), "eh.selector");
+ Selection->setDoesNotThrow();
+
+ // Select the right handler.
+ llvm::Value *llvm_eh_typeid_for =
+ CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
+
+ // The results of llvm_eh_typeid_for aren't reliable --- at least
+ // not locally --- so we basically have to do this as an 'if' chain.
+ // We walk through the first N-1 catch clauses, testing and chaining,
+ // and then fall into the final clause (which is either a cleanup, a
+ // filter (possibly with a cleanup), a catch-all, or another catch).
+ for (unsigned I = 2; I != LastToEmitInLoop; ++I) {
+ llvm::Value *Type = EHSelector[I];
+ UnwindDest Dest = EHHandlers[Type];
+ assert(Dest.isValid() && "no handler entry for value in selector?");
+
+ // Figure out where to branch on a match. As a debug code-size
+ // optimization, if the scope depth matches the innermost cleanup,
+ // we branch directly to the catch handler.
+ llvm::BasicBlock *Match = Dest.getBlock();
+ bool MatchNeedsCleanup =
+ Dest.getScopeDepth() != EHStack.getInnermostEHCleanup();
+ if (MatchNeedsCleanup)
+ Match = createBasicBlock("eh.match");
+
+ llvm::BasicBlock *Next = createBasicBlock("eh.next");
+
+ // Check whether the exception matches.
+ llvm::CallInst *Id
+ = Builder.CreateCall(llvm_eh_typeid_for,
+ Builder.CreateBitCast(Type, Int8PtrTy));
+ Id->setDoesNotThrow();
+ Builder.CreateCondBr(Builder.CreateICmpEQ(Selection, Id),
+ Match, Next);
+
+ // Emit match code if necessary.
+ if (MatchNeedsCleanup) {
+ EmitBlock(Match);
+ EmitBranchThroughEHCleanup(Dest);
+ }
+
+ // Continue to the next match.
+ EmitBlock(Next);
+ }
+
+ // Emit the final case in the selector.
+ // This might be a catch-all....
+ if (CatchAll.isValid()) {
+ assert(isa<llvm::ConstantPointerNull>(EHSelector.back()));
+ EmitBranchThroughEHCleanup(CatchAll);
+
+ // ...or an EH filter...
+ } else if (HasEHFilter) {
+ llvm::Value *SavedSelection = Selection;
+
+ // First, unwind out to the outermost scope if necessary.
+ if (EHStack.hasEHCleanups()) {
+ // The end here might not dominate the beginning, so we might need to
+ // save the selector if we need it.
+ llvm::AllocaInst *SelectorVar = 0;
+ if (HasEHCleanup) {
+ SelectorVar = CreateTempAlloca(Builder.getInt32Ty(), "selector.var");
+ Builder.CreateStore(Selection, SelectorVar);
+ }
+
+ llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont");
+ EmitBranchThroughEHCleanup(UnwindDest(CleanupContBB, EHStack.stable_end(),
+ EHStack.getNextEHDestIndex()));
+ EmitBlock(CleanupContBB);
+
+ if (HasEHCleanup)
+ SavedSelection = Builder.CreateLoad(SelectorVar, "ehspec.saved-selector");
+ }
+
+ // If there was a cleanup, we'll need to actually check whether we
+ // landed here because the filter triggered.
+ if (UseInvokeInlineHack || HasEHCleanup) {
+ llvm::BasicBlock *RethrowBB = createBasicBlock("cleanup");
+ llvm::BasicBlock *UnexpectedBB = createBasicBlock("ehspec.unexpected");
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(Builder.getInt32Ty(), 0);
+ llvm::Value *FailsFilter =
+ Builder.CreateICmpSLT(SavedSelection, Zero, "ehspec.fails");
+ Builder.CreateCondBr(FailsFilter, UnexpectedBB, RethrowBB);
+
+ // The rethrow block is where we land if this was a cleanup.
+ // TODO: can this be _Unwind_Resume if the InvokeInlineHack is off?
+ EmitBlock(RethrowBB);
+ Builder.CreateCall(getUnwindResumeOrRethrowFn(),
+ Builder.CreateLoad(getExceptionSlot()))
+ ->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ EmitBlock(UnexpectedBB);
+ }
+
+ // Call __cxa_call_unexpected. This doesn't need to be an invoke
+ // because __cxa_call_unexpected magically filters exceptions
+ // according to the last landing pad the exception was thrown
+ // into. Seriously.
+ Builder.CreateCall(getUnexpectedFn(*this),
+ Builder.CreateLoad(getExceptionSlot()))
+ ->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // ...or a normal catch handler...
+ } else if (!UseInvokeInlineHack && !HasEHCleanup) {
+ llvm::Value *Type = EHSelector.back();
+ EmitBranchThroughEHCleanup(EHHandlers[Type]);
+
+ // ...or a cleanup.
+ } else {
+ EmitBranchThroughEHCleanup(getRethrowDest());
+ }
+
+ // Restore the old IR generation state.
+ Builder.restoreIP(SavedIP);
+
+ return LP;
+}
+
+namespace {
+ /// A cleanup to call __cxa_end_catch. In many cases, the caught
+ /// exception type lets us state definitively that the thrown exception
+ /// type does not have a destructor. In particular:
+ /// - Catch-alls tell us nothing, so we have to conservatively
+ /// assume that the thrown exception might have a destructor.
+ /// - Catches by reference behave according to their base types.
+ /// - Catches of non-record types will only trigger for exceptions
+ /// of non-record types, which never have destructors.
+ /// - Catches of record types can trigger for arbitrary subclasses
+ /// of the caught type, so we have to assume the actual thrown
+ /// exception type might have a throwing destructor, even if the
+ /// caught type's destructor is trivial or nothrow.
+ struct CallEndCatch : EHScopeStack::Cleanup {
+ CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
+ bool MightThrow;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ if (!MightThrow) {
+ CGF.Builder.CreateCall(getEndCatchFn(CGF))->setDoesNotThrow();
+ return;
+ }
+
+ CGF.EmitCallOrInvoke(getEndCatchFn(CGF), 0, 0);
+ }
+ };
+}
+
+/// Emits a call to __cxa_begin_catch and enters a cleanup to call
+/// __cxa_end_catch.
+///
+/// \param EndMightThrow - true if __cxa_end_catch might throw
+static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
+ llvm::Value *Exn,
+ bool EndMightThrow) {
+ llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn);
+ Call->setDoesNotThrow();
+
+ CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
+
+ return Call;
+}
+
+/// A "special initializer" callback for initializing a catch
+/// parameter during catch initialization.
+static void InitCatchParam(CodeGenFunction &CGF,
+ const VarDecl &CatchParam,
+ llvm::Value *ParamAddr) {
+ // Load the exception from where the landing pad saved it.
+ llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn");
+
+ CanQualType CatchType =
+ CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
+ const llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
+
+ // If we're catching by reference, we can just cast the object
+ // pointer to the appropriate pointer.
+ if (isa<ReferenceType>(CatchType)) {
+ QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
+ bool EndCatchMightThrow = CaughtType->isRecordType();
+
+ // __cxa_begin_catch returns the adjusted object pointer.
+ llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
+
+ // We have no way to tell the personality function that we're
+ // catching by reference, so if we're catching a pointer,
+ // __cxa_begin_catch will actually return that pointer by value.
+ if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
+ QualType PointeeType = PT->getPointeeType();
+
+ // When catching by reference, generally we should just ignore
+ // this by-value pointer and use the exception object instead.
+ if (!PointeeType->isRecordType()) {
+
+ // Exn points to the struct _Unwind_Exception header, which
+ // we have to skip past in order to reach the exception data.
+ unsigned HeaderSize =
+ CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
+ AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);
+
+ // However, if we're catching a pointer-to-record type that won't
+ // work, because the personality function might have adjusted
+ // the pointer. There's actually no way for us to fully satisfy
+ // the language/ABI contract here: we can't use Exn because it
+ // might have the wrong adjustment, but we can't use the by-value
+ // pointer because it's off by a level of abstraction.
+ //
+ // The current solution is to dump the adjusted pointer into an
+ // alloca, which breaks language semantics (because changing the
+ // pointer doesn't change the exception) but at least works.
+ // The better solution would be to filter out non-exact matches
+ // and rethrow them, but this is tricky because the rethrow
+ // really needs to be catchable by other sites at this landing
+ // pad. The best solution is to fix the personality function.
+ } else {
+ // Pull the pointer for the reference type off.
+ const llvm::Type *PtrTy =
+ cast<llvm::PointerType>(LLVMCatchTy)->getElementType();
+
+ // Create the temporary and write the adjusted pointer into it.
+ llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
+ llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+ CGF.Builder.CreateStore(Casted, ExnPtrTmp);
+
+ // Bind the reference to the temporary.
+ AdjustedExn = ExnPtrTmp;
+ }
+ }
+
+ llvm::Value *ExnCast =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
+ CGF.Builder.CreateStore(ExnCast, ParamAddr);
+ return;
+ }
+
+ // Non-aggregates (plus complexes).
+ bool IsComplex = false;
+ if (!CGF.hasAggregateLLVMType(CatchType) ||
+ (IsComplex = CatchType->isAnyComplexType())) {
+ llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
+
+ // If the catch type is a pointer type, __cxa_begin_catch returns
+ // the pointer by value.
+ if (CatchType->hasPointerRepresentation()) {
+ llvm::Value *CastExn =
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
+ CGF.Builder.CreateStore(CastExn, ParamAddr);
+ return;
+ }
+
+ // Otherwise, it returns a pointer into the exception object.
+
+ const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
+ llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+
+ if (IsComplex) {
+ CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false),
+ ParamAddr, /*volatile*/ false);
+ } else {
+ unsigned Alignment =
+ CGF.getContext().getDeclAlign(&CatchParam).getQuantity();
+ llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar");
+ CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment,
+ CatchType);
+ }
+ return;
+ }
+
+ assert(isa<RecordType>(CatchType) && "unexpected catch type!");
+
+ const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
+
+ // Check for a copy expression. If we don't have a copy expression,
+ // that means a trivial copy is okay.
+ const Expr *copyExpr = CatchParam.getInit();
+ if (!copyExpr) {
+ llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
+ llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+ CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);
+ return;
+ }
+
+ // We have to call __cxa_get_exception_ptr to get the adjusted
+ // pointer before copying.
+ llvm::CallInst *rawAdjustedExn =
+ CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn);
+ rawAdjustedExn->setDoesNotThrow();
+
+ // Cast that to the appropriate type.
+ llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+
+ // The copy expression is defined in terms of an OpaqueValueExpr.
+ // Find it and map it to the adjusted expression.
+ CodeGenFunction::OpaqueValueMapping
+ opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+ CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
+
+ // Call the copy ctor in a terminate scope.
+ CGF.EHStack.pushTerminate();
+
+ // Perform the copy construction.
+ CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, false, false));
+
+ // Leave the terminate scope.
+ CGF.EHStack.popTerminate();
+
+ // Undo the opaque value mapping.
+ opaque.pop();
+
+ // Finally we can call __cxa_begin_catch.
+ CallBeginCatch(CGF, Exn, true);
+}
+
+/// Begins a catch statement by initializing the catch variable and
+/// calling __cxa_begin_catch.
+static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
+ // We have to be very careful with the ordering of cleanups here:
+ // C++ [except.throw]p4:
+ // The destruction [of the exception temporary] occurs
+ // immediately after the destruction of the object declared in
+ // the exception-declaration in the handler.
+ //
+ // So the precise ordering is:
+ // 1. Construct catch variable.
+ // 2. __cxa_begin_catch
+ // 3. Enter __cxa_end_catch cleanup
+ // 4. Enter dtor cleanup
+ //
+ // We do this by initializing the exception variable with a
+ // "special initializer", InitCatchParam. Delegation sequence:
+ // - ExitCXXTryStmt opens a RunCleanupsScope
+ // - EmitLocalBlockVarDecl creates the variable and debug info
+ // - InitCatchParam initializes the variable from the exception
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitLocalBlockVarDecl enters the variable destructor cleanup
+ // - EmitCXXTryStmt emits the code for the catch body
+ // - EmitCXXTryStmt close the RunCleanupsScope
+
+ VarDecl *CatchParam = S->getExceptionDecl();
+ if (!CatchParam) {
+ llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn");
+ CallBeginCatch(CGF, Exn, true);
+ return;
+ }
+
+ // Emit the local.
+ CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam);
+}
+
+namespace {
+ struct CallRethrow : EHScopeStack::Cleanup {
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitCallOrInvoke(getReThrowFn(CGF), 0, 0);
+ }
+ };
+}
+
+void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
+ unsigned NumHandlers = S.getNumHandlers();
+ EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
+ assert(CatchScope.getNumHandlers() == NumHandlers);
+
+ // Copy the handler blocks off before we pop the EH stack. Emitting
+ // the handlers might scribble on this memory.
+ llvm::SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers);
+ memcpy(Handlers.data(), CatchScope.begin(),
+ NumHandlers * sizeof(EHCatchScope::Handler));
+ EHStack.popCatch();
+
+ // The fall-through block.
+ llvm::BasicBlock *ContBB = createBasicBlock("try.cont");
+
+ // We just emitted the body of the try; jump to the continue block.
+ if (HaveInsertPoint())
+ Builder.CreateBr(ContBB);
+
+ // Determine if we need an implicit rethrow for all these catch handlers.
+ bool ImplicitRethrow = false;
+ if (IsFnTryBlock)
+ ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
+ isa<CXXConstructorDecl>(CurCodeDecl);
+
+ for (unsigned I = 0; I != NumHandlers; ++I) {
+ llvm::BasicBlock *CatchBlock = Handlers[I].Block;
+ EmitBlock(CatchBlock);
+
+ // Catch the exception if this isn't a catch-all.
+ const CXXCatchStmt *C = S.getHandler(I);
+
+ // Enter a cleanup scope, including the catch variable and the
+ // end-catch.
+ RunCleanupsScope CatchScope(*this);
+
+ // Initialize the catch variable and set up the cleanups.
+ BeginCatch(*this, C);
+
+ // If there's an implicit rethrow, push a normal "cleanup" to call
+ // _cxa_rethrow. This needs to happen before __cxa_end_catch is
+ // called, and so it is pushed after BeginCatch.
+ if (ImplicitRethrow)
+ EHStack.pushCleanup<CallRethrow>(NormalCleanup);
+
+ // Perform the body of the catch.
+ EmitStmt(C->getHandlerBlock());
+
+ // Fall out through the catch cleanups.
+ CatchScope.ForceCleanup();
+
+ // Branch out of the try.
+ if (HaveInsertPoint())
+ Builder.CreateBr(ContBB);
+ }
+
+ EmitBlock(ContBB);
+}
+
+namespace {
+ struct CallEndCatchForFinally : EHScopeStack::Cleanup {
+ llvm::Value *ForEHVar;
+ llvm::Value *EndCatchFn;
+ CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn)
+ : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch");
+ llvm::BasicBlock *CleanupContBB =
+ CGF.createBasicBlock("finally.cleanup.cont");
+
+ llvm::Value *ShouldEndCatch =
+ CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch");
+ CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
+ CGF.EmitBlock(EndCatchBB);
+ CGF.EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw
+ CGF.EmitBlock(CleanupContBB);
+ }
+ };
+
+ struct PerformFinally : EHScopeStack::Cleanup {
+ const Stmt *Body;
+ llvm::Value *ForEHVar;
+ llvm::Value *EndCatchFn;
+ llvm::Value *RethrowFn;
+ llvm::Value *SavedExnVar;
+
+ PerformFinally(const Stmt *Body, llvm::Value *ForEHVar,
+ llvm::Value *EndCatchFn,
+ llvm::Value *RethrowFn, llvm::Value *SavedExnVar)
+ : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn),
+ RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // Enter a cleanup to call the end-catch function if one was provided.
+ if (EndCatchFn)
+ CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup,
+ ForEHVar, EndCatchFn);
+
+ // Save the current cleanup destination in case there are
+ // cleanups in the finally block.
+ llvm::Value *SavedCleanupDest =
+ CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(),
+ "cleanup.dest.saved");
+
+ // Emit the finally block.
+ CGF.EmitStmt(Body);
+
+ // If the end of the finally is reachable, check whether this was
+ // for EH. If so, rethrow.
+ if (CGF.HaveInsertPoint()) {
+ llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow");
+ llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");
+
+ llvm::Value *ShouldRethrow =
+ CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
+ CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
+
+ CGF.EmitBlock(RethrowBB);
+ if (SavedExnVar) {
+ llvm::Value *Args[] = { CGF.Builder.CreateLoad(SavedExnVar) };
+ CGF.EmitCallOrInvoke(RethrowFn, Args, Args+1);
+ } else {
+ CGF.EmitCallOrInvoke(RethrowFn, 0, 0);
+ }
+ CGF.Builder.CreateUnreachable();
+
+ CGF.EmitBlock(ContBB);
+
+ // Restore the cleanup destination.
+ CGF.Builder.CreateStore(SavedCleanupDest,
+ CGF.getNormalCleanupDestSlot());
+ }
+
+ // Leave the end-catch cleanup. As an optimization, pretend that
+ // the fallthrough path was inaccessible; we've dynamically proven
+ // that we're not in the EH case along that path.
+ if (EndCatchFn) {
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+ CGF.PopCleanupBlock();
+ CGF.Builder.restoreIP(SavedIP);
+ }
+
+ // Now make sure we actually have an insertion point or the
+ // cleanup gods will hate us.
+ CGF.EnsureInsertPoint();
+ }
+ };
+}
+
+/// Enters a finally block for an implementation using zero-cost
+/// exceptions. This is mostly general, but hard-codes some
+/// language/ABI-specific behavior in the catch-all sections.
+CodeGenFunction::FinallyInfo
+CodeGenFunction::EnterFinallyBlock(const Stmt *Body,
+ llvm::Constant *BeginCatchFn,
+ llvm::Constant *EndCatchFn,
+ llvm::Constant *RethrowFn) {
+ assert((BeginCatchFn != 0) == (EndCatchFn != 0) &&
+ "begin/end catch functions not paired");
+ assert(RethrowFn && "rethrow function is required");
+
+ // The rethrow function has one of the following two types:
+ // void (*)()
+ // void (*)(void*)
+ // In the latter case we need to pass it the exception object.
+ // But we can't use the exception slot because the @finally might
+ // have a landing pad (which would overwrite the exception slot).
+ const llvm::FunctionType *RethrowFnTy =
+ cast<llvm::FunctionType>(
+ cast<llvm::PointerType>(RethrowFn->getType())
+ ->getElementType());
+ llvm::Value *SavedExnVar = 0;
+ if (RethrowFnTy->getNumParams())
+ SavedExnVar = CreateTempAlloca(Builder.getInt8PtrTy(), "finally.exn");
+
+ // A finally block is a statement which must be executed on any edge
+ // out of a given scope. Unlike a cleanup, the finally block may
+ // contain arbitrary control flow leading out of itself. In
+ // addition, finally blocks should always be executed, even if there
+ // are no catch handlers higher on the stack. Therefore, we
+ // surround the protected scope with a combination of a normal
+ // cleanup (to catch attempts to break out of the block via normal
+ // control flow) and an EH catch-all (semantically "outside" any try
+ // statement to which the finally block might have been attached).
+ // The finally block itself is generated in the context of a cleanup
+ // which conditionally leaves the catch-all.
+
+ FinallyInfo Info;
+
+ // Jump destination for performing the finally block on an exception
+ // edge. We'll never actually reach this block, so unreachable is
+ // fine.
+ JumpDest RethrowDest = getJumpDestInCurrentScope(getUnreachableBlock());
+
+ // Whether the finally block is being executed for EH purposes.
+ llvm::AllocaInst *ForEHVar = CreateTempAlloca(Builder.getInt1Ty(),
+ "finally.for-eh");
+ InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext()));
+
+ // Enter a normal cleanup which will perform the @finally block.
+ EHStack.pushCleanup<PerformFinally>(NormalCleanup, Body,
+ ForEHVar, EndCatchFn,
+ RethrowFn, SavedExnVar);
+
+ // Enter a catch-all scope.
+ llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall");
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
+ Builder.SetInsertPoint(CatchAllBB);
+
+ // If there's a begin-catch function, call it.
+ if (BeginCatchFn) {
+ Builder.CreateCall(BeginCatchFn, Builder.CreateLoad(getExceptionSlot()))
+ ->setDoesNotThrow();
+ }
+
+ // If we need to remember the exception pointer to rethrow later, do so.
+ if (SavedExnVar) {
+ llvm::Value *SavedExn = Builder.CreateLoad(getExceptionSlot());
+ Builder.CreateStore(SavedExn, SavedExnVar);
+ }
+
+ // Tell the finally block that we're in EH.
+ Builder.CreateStore(llvm::ConstantInt::getTrue(getLLVMContext()), ForEHVar);
+
+ // Thread a jump through the finally cleanup.
+ EmitBranchThroughCleanup(RethrowDest);
+
+ Builder.restoreIP(SavedIP);
+
+ EHCatchScope *CatchScope = EHStack.pushCatch(1);
+ CatchScope->setCatchAllHandler(0, CatchAllBB);
+
+ return Info;
+}
+
+void CodeGenFunction::ExitFinallyBlock(FinallyInfo &Info) {
+ // Leave the finally catch-all.
+ EHCatchScope &Catch = cast<EHCatchScope>(*EHStack.begin());
+ llvm::BasicBlock *CatchAllBB = Catch.getHandler(0).Block;
+ EHStack.popCatch();
+
+ // And leave the normal cleanup.
+ PopCleanupBlock();
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+ EmitBlock(CatchAllBB, true);
+
+ Builder.restoreIP(SavedIP);
+}
+
+llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
+ if (TerminateLandingPad)
+ return TerminateLandingPad;
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ // This will get inserted at the end of the function.
+ TerminateLandingPad = createBasicBlock("terminate.lpad");
+ Builder.SetInsertPoint(TerminateLandingPad);
+
+ // Tell the backend that this is a landing pad.
+ llvm::CallInst *Exn =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
+ Exn->setDoesNotThrow();
+
+ const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
+
+ // Tell the backend what the exception table should be:
+ // nothing but a catch-all.
+ llvm::Value *Args[3] = { Exn, getOpaquePersonalityFn(CGM, Personality),
+ getCatchAllValue(*this) };
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
+ Args, Args+3, "eh.selector")
+ ->setDoesNotThrow();
+
+ llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this));
+ TerminateCall->setDoesNotReturn();
+ TerminateCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+
+ // Restore the saved insertion state.
+ Builder.restoreIP(SavedIP);
+
+ return TerminateLandingPad;
+}
+
+llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
+ if (TerminateHandler)
+ return TerminateHandler;
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+
+ // Set up the terminate handler. This block is inserted at the very
+ // end of the function by FinishFunction.
+ TerminateHandler = createBasicBlock("terminate.handler");
+ Builder.SetInsertPoint(TerminateHandler);
+ llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this));
+ TerminateCall->setDoesNotReturn();
+ TerminateCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+
+ // Restore the saved insertion state.
+ Builder.restoreIP(SavedIP);
+
+ return TerminateHandler;
+}
+
+CodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() {
+ if (RethrowBlock.isValid()) return RethrowBlock;
+
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
+
+ // We emit a jump to a notional label at the outermost unwind state.
+ llvm::BasicBlock *Unwind = createBasicBlock("eh.resume");
+ Builder.SetInsertPoint(Unwind);
+
+ const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
+
+ // This can always be a call because we necessarily didn't find
+ // anything on the EH stack which needs our help.
+ llvm::StringRef RethrowName = Personality.getCatchallRethrowFnName();
+ llvm::Constant *RethrowFn;
+ if (!RethrowName.empty())
+ RethrowFn = getCatchallRethrowFn(*this, RethrowName);
+ else
+ RethrowFn = getUnwindResumeOrRethrowFn();
+
+ Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot()))
+ ->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ Builder.restoreIP(SavedIP);
+
+ RethrowBlock = UnwindDest(Unwind, EHStack.stable_end(), 0);
+ return RethrowBlock;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.h b/contrib/llvm/tools/clang/lib/CodeGen/CGException.h
new file mode 100644
index 0000000..1f9b896
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.h
@@ -0,0 +1,55 @@
+//===-- CGException.h - Classes for exceptions IR generation ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes support the generation of LLVM IR for exceptions in
+// C++ and Objective C.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGEXCEPTION_H
+#define CLANG_CODEGEN_CGEXCEPTION_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class LangOptions;
+
+namespace CodeGen {
+
+/// The exceptions personality for a function. When
+class EHPersonality {
+ llvm::StringRef PersonalityFn;
+
+ // If this is non-null, this personality requires a non-standard
+ // function for rethrowing an exception after a catchall cleanup.
+ // This function must have prototype void(void*).
+ llvm::StringRef CatchallRethrowFn;
+
+ EHPersonality(llvm::StringRef PersonalityFn,
+ llvm::StringRef CatchallRethrowFn = llvm::StringRef())
+ : PersonalityFn(PersonalityFn),
+ CatchallRethrowFn(CatchallRethrowFn) {}
+
+public:
+ static const EHPersonality &get(const LangOptions &Lang);
+ static const EHPersonality GNU_C;
+ static const EHPersonality GNU_C_SJLJ;
+ static const EHPersonality GNU_ObjC;
+ static const EHPersonality NeXT_ObjC;
+ static const EHPersonality GNU_CPlusPlus;
+ static const EHPersonality GNU_CPlusPlus_SJLJ;
+
+ llvm::StringRef getPersonalityFnName() const { return PersonalityFn; }
+ llvm::StringRef getCatchallRethrowFnName() const { return CatchallRethrowFn; }
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
new file mode 100644
index 0000000..1b7e7a0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -0,0 +1,2104 @@
+//===--- CGExpr.cpp - Emit LLVM Code from Expressions ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Expr nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGCall.h"
+#include "CGCXXABI.h"
+#include "CGRecordLayout.h"
+#include "CGObjCRuntime.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "llvm/Intrinsics.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===--------------------------------------------------------------------===//
+// Miscellaneous Helper Methods
+//===--------------------------------------------------------------------===//
+
+llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
+ unsigned addressSpace =
+ cast<llvm::PointerType>(value->getType())->getAddressSpace();
+
+ const llvm::PointerType *destType = Int8PtrTy;
+ if (addressSpace)
+ destType = llvm::Type::getInt8PtrTy(getLLVMContext(), addressSpace);
+
+ if (value->getType() == destType) return value;
+ return Builder.CreateBitCast(value, destType);
+}
+
+/// CreateTempAlloca - This creates a alloca and inserts it into the entry
+/// block.
+llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
+ const llvm::Twine &Name) {
+ if (!Builder.isNamePreserving())
+ return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);
+ return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
+}
+
+void CodeGenFunction::InitTempAlloca(llvm::AllocaInst *Var,
+ llvm::Value *Init) {
+ llvm::StoreInst *Store = new llvm::StoreInst(Init, Var);
+ llvm::BasicBlock *Block = AllocaInsertPt->getParent();
+ Block->getInstList().insertAfter(&*AllocaInsertPt, Store);
+}
+
+llvm::AllocaInst *CodeGenFunction::CreateIRTemp(QualType Ty,
+ const llvm::Twine &Name) {
+ llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertType(Ty), Name);
+ // FIXME: Should we prefer the preferred type alignment here?
+ CharUnits Align = getContext().getTypeAlignInChars(Ty);
+ Alloc->setAlignment(Align.getQuantity());
+ return Alloc;
+}
+
+llvm::AllocaInst *CodeGenFunction::CreateMemTemp(QualType Ty,
+ const llvm::Twine &Name) {
+ llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), Name);
+ // FIXME: Should we prefer the preferred type alignment here?
+ CharUnits Align = getContext().getTypeAlignInChars(Ty);
+ Alloc->setAlignment(Align.getQuantity());
+ return Alloc;
+}
+
+/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+/// expression and compare the result against zero, returning an Int1Ty value.
+llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
+ if (const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>()) {
+ llvm::Value *MemPtr = EmitScalarExpr(E);
+ return CGM.getCXXABI().EmitMemberPointerIsNotNull(*this, MemPtr, MPT);
+ }
+
+ QualType BoolTy = getContext().BoolTy;
+ if (!E->getType()->isAnyComplexType())
+ return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy);
+
+ return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),BoolTy);
+}
+
+/// EmitIgnoredExpr - Emit code to compute the specified expression,
+/// ignoring the result.
+void CodeGenFunction::EmitIgnoredExpr(const Expr *E) {
+ if (E->isRValue())
+ return (void) EmitAnyExpr(E, AggValueSlot::ignored(), true);
+
+ // Just emit it as an l-value and drop the result.
+ EmitLValue(E);
+}
+
+/// EmitAnyExpr - Emit code to compute the specified expression which
+/// can have any type. The result is returned as an RValue struct.
+/// If this is an aggregate expression, AggSlot indicates where the
+/// result should be returned.
+RValue CodeGenFunction::EmitAnyExpr(const Expr *E, AggValueSlot AggSlot,
+ bool IgnoreResult) {
+ if (!hasAggregateLLVMType(E->getType()))
+ return RValue::get(EmitScalarExpr(E, IgnoreResult));
+ else if (E->getType()->isAnyComplexType())
+ return RValue::getComplex(EmitComplexExpr(E, IgnoreResult, IgnoreResult));
+
+ EmitAggExpr(E, AggSlot, IgnoreResult);
+ return AggSlot.asRValue();
+}
+
+/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
+/// always be accessible even if no aggregate location is provided.
+RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
+ AggValueSlot AggSlot = AggValueSlot::ignored();
+
+ if (hasAggregateLLVMType(E->getType()) &&
+ !E->getType()->isAnyComplexType())
+ AggSlot = CreateAggTemp(E->getType(), "agg.tmp");
+ return EmitAnyExpr(E, AggSlot);
+}
+
+/// EmitAnyExprToMem - Evaluate an expression into a given memory
+/// location.
+void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
+ llvm::Value *Location,
+ bool IsLocationVolatile,
+ bool IsInit) {
+ if (E->getType()->isComplexType())
+ EmitComplexExprIntoAddr(E, Location, IsLocationVolatile);
+ else if (hasAggregateLLVMType(E->getType()))
+ EmitAggExpr(E, AggValueSlot::forAddr(Location, IsLocationVolatile, IsInit));
+ else {
+ RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false));
+ LValue LV = MakeAddrLValue(Location, E->getType());
+ EmitStoreThroughLValue(RV, LV, E->getType());
+ }
+}
+
+namespace {
+/// \brief An adjustment to be made to the temporary created when emitting a
+/// reference binding, which accesses a particular subobject of that temporary.
+ struct SubobjectAdjustment {
+ enum { DerivedToBaseAdjustment, FieldAdjustment } Kind;
+
+ union {
+ struct {
+ const CastExpr *BasePath;
+ const CXXRecordDecl *DerivedClass;
+ } DerivedToBase;
+
+ FieldDecl *Field;
+ };
+
+ SubobjectAdjustment(const CastExpr *BasePath,
+ const CXXRecordDecl *DerivedClass)
+ : Kind(DerivedToBaseAdjustment) {
+ DerivedToBase.BasePath = BasePath;
+ DerivedToBase.DerivedClass = DerivedClass;
+ }
+
+ SubobjectAdjustment(FieldDecl *Field)
+ : Kind(FieldAdjustment) {
+ this->Field = Field;
+ }
+ };
+}
+
+static llvm::Value *
+CreateReferenceTemporary(CodeGenFunction& CGF, QualType Type,
+ const NamedDecl *InitializedDecl) {
+ if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
+ if (VD->hasGlobalStorage()) {
+ llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ CGF.CGM.getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
+ Out.flush();
+
+ const llvm::Type *RefTempTy = CGF.ConvertTypeForMem(Type);
+
+ // Create the reference temporary.
+ llvm::GlobalValue *RefTemp =
+ new llvm::GlobalVariable(CGF.CGM.getModule(),
+ RefTempTy, /*isConstant=*/false,
+ llvm::GlobalValue::InternalLinkage,
+ llvm::Constant::getNullValue(RefTempTy),
+ Name.str());
+ return RefTemp;
+ }
+ }
+
+ return CGF.CreateMemTemp(Type, "ref.tmp");
+}
+
+static llvm::Value *
+EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
+ llvm::Value *&ReferenceTemporary,
+ const CXXDestructorDecl *&ReferenceTemporaryDtor,
+ const NamedDecl *InitializedDecl) {
+ if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
+ E = DAE->getExpr();
+
+ if (const ExprWithCleanups *TE = dyn_cast<ExprWithCleanups>(E)) {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+
+ return EmitExprForReferenceBinding(CGF, TE->getSubExpr(),
+ ReferenceTemporary,
+ ReferenceTemporaryDtor,
+ InitializedDecl);
+ }
+
+ RValue RV;
+ if (E->isGLValue()) {
+ // Emit the expression as an lvalue.
+ LValue LV = CGF.EmitLValue(E);
+ if (LV.isSimple())
+ return LV.getAddress();
+
+ // We have to load the lvalue.
+ RV = CGF.EmitLoadOfLValue(LV, E->getType());
+ } else {
+ QualType ResultTy = E->getType();
+
+ llvm::SmallVector<SubobjectAdjustment, 2> Adjustments;
+ while (true) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ E = PE->getSubExpr();
+ continue;
+ }
+
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if ((CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase) &&
+ E->getType()->isRecordType()) {
+ E = CE->getSubExpr();
+ CXXRecordDecl *Derived
+ = cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ Adjustments.push_back(SubobjectAdjustment(CE, Derived));
+ continue;
+ }
+
+ if (CE->getCastKind() == CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ if (!ME->isArrow() && ME->getBase()->isRValue()) {
+ assert(ME->getBase()->getType()->isRecordType());
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ E = ME->getBase();
+ Adjustments.push_back(SubobjectAdjustment(Field));
+ continue;
+ }
+ }
+ }
+
+ // Nothing changed.
+ break;
+ }
+
+ // Create a reference temporary if necessary.
+ AggValueSlot AggSlot = AggValueSlot::ignored();
+ if (CGF.hasAggregateLLVMType(E->getType()) &&
+ !E->getType()->isAnyComplexType()) {
+ ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
+ InitializedDecl);
+ AggSlot = AggValueSlot::forAddr(ReferenceTemporary, false,
+ InitializedDecl != 0);
+ }
+
+ RV = CGF.EmitAnyExpr(E, AggSlot);
+
+ if (InitializedDecl) {
+ // Get the destructor for the reference temporary.
+ if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (!ClassDecl->hasTrivialDestructor())
+ ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ }
+ }
+
+ // Check if need to perform derived-to-base casts and/or field accesses, to
+ // get from the temporary object we created (and, potentially, for which we
+ // extended the lifetime) to the subobject we're binding the reference to.
+ if (!Adjustments.empty()) {
+ llvm::Value *Object = RV.getAggregateAddr();
+ for (unsigned I = Adjustments.size(); I != 0; --I) {
+ SubobjectAdjustment &Adjustment = Adjustments[I-1];
+ switch (Adjustment.Kind) {
+ case SubobjectAdjustment::DerivedToBaseAdjustment:
+ Object =
+ CGF.GetAddressOfBaseClass(Object,
+ Adjustment.DerivedToBase.DerivedClass,
+ Adjustment.DerivedToBase.BasePath->path_begin(),
+ Adjustment.DerivedToBase.BasePath->path_end(),
+ /*NullCheckValue=*/false);
+ break;
+
+ case SubobjectAdjustment::FieldAdjustment: {
+ LValue LV =
+ CGF.EmitLValueForField(Object, Adjustment.Field, 0);
+ if (LV.isSimple()) {
+ Object = LV.getAddress();
+ break;
+ }
+
+ // For non-simple lvalues, we actually have to create a copy of
+ // the object we're binding to.
+ QualType T = Adjustment.Field->getType().getNonReferenceType()
+ .getUnqualifiedType();
+ Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
+ LValue TempLV = CGF.MakeAddrLValue(Object,
+ Adjustment.Field->getType());
+ CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV, T), TempLV, T);
+ break;
+ }
+
+ }
+ }
+
+ const llvm::Type *ResultPtrTy = CGF.ConvertType(ResultTy)->getPointerTo();
+ return CGF.Builder.CreateBitCast(Object, ResultPtrTy, "temp");
+ }
+ }
+
+ if (RV.isAggregate())
+ return RV.getAggregateAddr();
+
+ // Create a temporary variable that we can bind the reference to.
+ ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
+ InitializedDecl);
+
+
+ unsigned Alignment =
+ CGF.getContext().getTypeAlignInChars(E->getType()).getQuantity();
+ if (RV.isScalar())
+ CGF.EmitStoreOfScalar(RV.getScalarVal(), ReferenceTemporary,
+ /*Volatile=*/false, Alignment, E->getType());
+ else
+ CGF.StoreComplexToAddr(RV.getComplexVal(), ReferenceTemporary,
+ /*Volatile=*/false);
+ return ReferenceTemporary;
+}
+
+RValue
+CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E,
+ const NamedDecl *InitializedDecl) {
+ llvm::Value *ReferenceTemporary = 0;
+ const CXXDestructorDecl *ReferenceTemporaryDtor = 0;
+ llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
+ ReferenceTemporaryDtor,
+ InitializedDecl);
+ if (!ReferenceTemporaryDtor)
+ return RValue::get(Value);
+
+ // Make sure to call the destructor for the reference temporary.
+ if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
+ if (VD->hasGlobalStorage()) {
+ llvm::Constant *DtorFn =
+ CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
+ EmitCXXGlobalDtorRegistration(DtorFn,
+ cast<llvm::Constant>(ReferenceTemporary));
+
+ return RValue::get(Value);
+ }
+ }
+
+ PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
+
+ return RValue::get(Value);
+}
+
+
+/// getAccessedFieldNo - Given an encoded value and a result number, return the
+/// input field number being accessed.
+unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
+ const llvm::Constant *Elts) {
+ if (isa<llvm::ConstantAggregateZero>(Elts))
+ return 0;
+
+ return cast<llvm::ConstantInt>(Elts->getOperand(Idx))->getZExtValue();
+}
+
+void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) {
+ if (!CatchUndefined)
+ return;
+
+ // This needs to be to the standard address space.
+ Address = Builder.CreateBitCast(Address, Int8PtrTy);
+
+ const llvm::Type *IntPtrT = IntPtrTy;
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, &IntPtrT, 1);
+
+ // In time, people may want to control this and use a 1 here.
+ llvm::Value *Arg = Builder.getFalse();
+ llvm::Value *C = Builder.CreateCall2(F, Address, Arg);
+ llvm::BasicBlock *Cont = createBasicBlock();
+ llvm::BasicBlock *Check = createBasicBlock();
+ llvm::Value *NegativeOne = llvm::ConstantInt::get(IntPtrTy, -1ULL);
+ Builder.CreateCondBr(Builder.CreateICmpEQ(C, NegativeOne), Cont, Check);
+
+ EmitBlock(Check);
+ Builder.CreateCondBr(Builder.CreateICmpUGE(C,
+ llvm::ConstantInt::get(IntPtrTy, Size)),
+ Cont, getTrapBB());
+ EmitBlock(Cont);
+}
+
+
+CodeGenFunction::ComplexPairTy CodeGenFunction::
+EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre) {
+ ComplexPairTy InVal = LoadComplexFromAddr(LV.getAddress(),
+ LV.isVolatileQualified());
+
+ llvm::Value *NextVal;
+ if (isa<llvm::IntegerType>(InVal.first->getType())) {
+ uint64_t AmountVal = isInc ? 1 : -1;
+ NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
+ } else {
+ QualType ElemTy = E->getType()->getAs<ComplexType>()->getElementType();
+ llvm::APFloat FVal(getContext().getFloatTypeSemantics(ElemTy), 1);
+ if (!isInc)
+ FVal.changeSign();
+ NextVal = llvm::ConstantFP::get(getLLVMContext(), FVal);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
+ }
+
+ ComplexPairTy IncVal(NextVal, InVal.second);
+
+ // Store the updated result through the lvalue.
+ StoreComplexToAddr(IncVal, LV.getAddress(), LV.isVolatileQualified());
+
+ // If this is a postinc, return the value read from memory, otherwise use the
+ // updated value.
+ return isPre ? IncVal : InVal;
+}
+
+
+//===----------------------------------------------------------------------===//
+// LValue Expression Emission
+//===----------------------------------------------------------------------===//
+
+RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
+ if (Ty->isVoidType())
+ return RValue::get(0);
+
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
+ const llvm::Type *EltTy = ConvertType(CTy->getElementType());
+ llvm::Value *U = llvm::UndefValue::get(EltTy);
+ return RValue::getComplex(std::make_pair(U, U));
+ }
+
+ // If this is a use of an undefined aggregate type, the aggregate must have an
+ // identifiable address. Just because the contents of the value are undefined
+ // doesn't mean that the address can't be taken and compared.
+ if (hasAggregateLLVMType(Ty)) {
+ llvm::Value *DestPtr = CreateMemTemp(Ty, "undef.agg.tmp");
+ return RValue::getAggregate(DestPtr);
+ }
+
+ return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
+}
+
+RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E,
+ const char *Name) {
+ ErrorUnsupported(E, Name);
+ return GetUndefRValue(E->getType());
+}
+
+LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
+ const char *Name) {
+ ErrorUnsupported(E, Name);
+ llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
+ return MakeAddrLValue(llvm::UndefValue::get(Ty), E->getType());
+}
+
+LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) {
+ LValue LV = EmitLValue(E);
+ if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple())
+ EmitCheck(LV.getAddress(),
+ getContext().getTypeSizeInChars(E->getType()).getQuantity());
+ return LV;
+}
+
+/// EmitLValue - Emit code to compute a designator that specifies the location
+/// of the expression.
+///
+/// This can return one of two things: a simple address or a bitfield reference.
+/// In either case, the LLVM Value* in the LValue structure is guaranteed to be
+/// an LLVM pointer type.
+///
+/// If this returns a bitfield reference, nothing about the pointee type of the
+/// LLVM value is known: For example, it may not be a pointer to an integer.
+///
+/// If this returns a normal address, and if the lvalue's C type is fixed size,
+/// this method guarantees that the returned pointer type will point to an LLVM
+/// type of the same size of the lvalue's type. If the lvalue has a variable
+/// length type, this is not possible.
+///
+LValue CodeGenFunction::EmitLValue(const Expr *E) {
+ switch (E->getStmtClass()) {
+ default: return EmitUnsupportedLValue(E, "l-value expression");
+
+ case Expr::ObjCSelectorExprClass:
+ return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E));
+ case Expr::ObjCIsaExprClass:
+ return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
+ case Expr::BinaryOperatorClass:
+ return EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
+ case Expr::CompoundAssignOperatorClass:
+ if (!E->getType()->isAnyComplexType())
+ return EmitCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+ return EmitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(E));
+ case Expr::CallExprClass:
+ case Expr::CXXMemberCallExprClass:
+ case Expr::CXXOperatorCallExprClass:
+ return EmitCallExprLValue(cast<CallExpr>(E));
+ case Expr::VAArgExprClass:
+ return EmitVAArgExprLValue(cast<VAArgExpr>(E));
+ case Expr::DeclRefExprClass:
+ return EmitDeclRefLValue(cast<DeclRefExpr>(E));
+ case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+ case Expr::PredefinedExprClass:
+ return EmitPredefinedLValue(cast<PredefinedExpr>(E));
+ case Expr::StringLiteralClass:
+ return EmitStringLiteralLValue(cast<StringLiteral>(E));
+ case Expr::ObjCEncodeExprClass:
+ return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));
+
+ case Expr::BlockDeclRefExprClass:
+ return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E));
+
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXConstructExprClass:
+ return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
+ case Expr::CXXBindTemporaryExprClass:
+ return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
+ case Expr::ExprWithCleanupsClass:
+ return EmitExprWithCleanupsLValue(cast<ExprWithCleanups>(E));
+ case Expr::CXXScalarValueInitExprClass:
+ return EmitNullInitializationLValue(cast<CXXScalarValueInitExpr>(E));
+ case Expr::CXXDefaultArgExprClass:
+ return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr());
+ case Expr::CXXTypeidExprClass:
+ return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
+
+ case Expr::ObjCMessageExprClass:
+ return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E));
+ case Expr::ObjCIvarRefExprClass:
+ return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E));
+ case Expr::ObjCPropertyRefExprClass:
+ return EmitObjCPropertyRefLValue(cast<ObjCPropertyRefExpr>(E));
+ case Expr::StmtExprClass:
+ return EmitStmtExprLValue(cast<StmtExpr>(E));
+ case Expr::UnaryOperatorClass:
+ return EmitUnaryOpLValue(cast<UnaryOperator>(E));
+ case Expr::ArraySubscriptExprClass:
+ return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+ case Expr::ExtVectorElementExprClass:
+ return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E));
+ case Expr::MemberExprClass:
+ return EmitMemberExpr(cast<MemberExpr>(E));
+ case Expr::CompoundLiteralExprClass:
+ return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E));
+ case Expr::ConditionalOperatorClass:
+ return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E));
+ case Expr::BinaryConditionalOperatorClass:
+ return EmitConditionalOperatorLValue(cast<BinaryConditionalOperator>(E));
+ case Expr::ChooseExprClass:
+ return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
+ case Expr::OpaqueValueExprClass:
+ return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
+ case Expr::ImplicitCastExprClass:
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXDynamicCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass:
+ return EmitCastLValue(cast<CastExpr>(E));
+ }
+}
+
+llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
+ unsigned Alignment, QualType Ty,
+ llvm::MDNode *TBAAInfo) {
+ llvm::LoadInst *Load = Builder.CreateLoad(Addr, "tmp");
+ if (Volatile)
+ Load->setVolatile(true);
+ if (Alignment)
+ Load->setAlignment(Alignment);
+ if (TBAAInfo)
+ CGM.DecorateInstruction(Load, TBAAInfo);
+
+ return EmitFromMemory(Load, Ty);
+}
+
+static bool isBooleanUnderlyingType(QualType Ty) {
+ if (const EnumType *ET = dyn_cast<EnumType>(Ty))
+ return ET->getDecl()->getIntegerType()->isBooleanType();
+ return false;
+}
+
+llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
+ // Bool has a different representation in memory than in registers.
+ if (Ty->isBooleanType() || isBooleanUnderlyingType(Ty)) {
+ // This should really always be an i1, but sometimes it's already
+ // an i8, and it's awkward to track those cases down.
+ if (Value->getType()->isIntegerTy(1))
+ return Builder.CreateZExt(Value, Builder.getInt8Ty(), "frombool");
+ assert(Value->getType()->isIntegerTy(8) && "value rep of bool not i1/i8");
+ }
+
+ return Value;
+}
+
+llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
+ // Bool has a different representation in memory than in registers.
+ if (Ty->isBooleanType() || isBooleanUnderlyingType(Ty)) {
+ assert(Value->getType()->isIntegerTy(8) && "memory rep of bool not i8");
+ return Builder.CreateTrunc(Value, Builder.getInt1Ty(), "tobool");
+ }
+
+ return Value;
+}
+
+void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
+ bool Volatile, unsigned Alignment,
+ QualType Ty,
+ llvm::MDNode *TBAAInfo) {
+ Value = EmitToMemory(Value, Ty);
+ llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
+ if (Alignment)
+ Store->setAlignment(Alignment);
+ if (TBAAInfo)
+ CGM.DecorateInstruction(Store, TBAAInfo);
+}
+
+/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
+/// method emits the address of the lvalue, then loads the result as an rvalue,
+/// returning the rvalue.
+RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
+ if (LV.isObjCWeak()) {
+ // load of a __weak object.
+ llvm::Value *AddrWeakObj = LV.getAddress();
+ return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
+ AddrWeakObj));
+ }
+
+ if (LV.isSimple()) {
+ llvm::Value *Ptr = LV.getAddress();
+
+ // Functions are l-values that don't require loading.
+ if (ExprType->isFunctionType())
+ return RValue::get(Ptr);
+
+ // Everything needs a load.
+ return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(),
+ LV.getAlignment(), ExprType,
+ LV.getTBAAInfo()));
+
+ }
+
+ if (LV.isVectorElt()) {
+ llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(),
+ LV.isVolatileQualified(), "tmp");
+ return RValue::get(Builder.CreateExtractElement(Vec, LV.getVectorIdx(),
+ "vecext"));
+ }
+
+ // If this is a reference to a subset of the elements of a vector, either
+ // shuffle the input or extract/insert them as appropriate.
+ if (LV.isExtVectorElt())
+ return EmitLoadOfExtVectorElementLValue(LV, ExprType);
+
+ if (LV.isBitField())
+ return EmitLoadOfBitfieldLValue(LV, ExprType);
+
+ assert(LV.isPropertyRef() && "Unknown LValue type!");
+ return EmitLoadOfPropertyRefLValue(LV);
+}
+
+RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
+ QualType ExprType) {
+ const CGBitFieldInfo &Info = LV.getBitFieldInfo();
+
+ // Get the output type.
+ const llvm::Type *ResLTy = ConvertType(ExprType);
+ unsigned ResSizeInBits = CGM.getTargetData().getTypeSizeInBits(ResLTy);
+
+ // Compute the result as an OR of all of the individual component accesses.
+ llvm::Value *Res = 0;
+ for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
+ const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
+
+ // Get the field pointer.
+ llvm::Value *Ptr = LV.getBitFieldBaseAddr();
+
+ // Only offset by the field index if used, so that incoming values are not
+ // required to be structures.
+ if (AI.FieldIndex)
+ Ptr = Builder.CreateStructGEP(Ptr, AI.FieldIndex, "bf.field");
+
+ // Offset by the byte offset, if used.
+ if (AI.FieldByteOffset) {
+ Ptr = EmitCastToVoidPtr(Ptr);
+ Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset,"bf.field.offs");
+ }
+
+ // Cast to the access type.
+ const llvm::Type *PTy = llvm::Type::getIntNPtrTy(getLLVMContext(),
+ AI.AccessWidth,
+ ExprType.getAddressSpace());
+ Ptr = Builder.CreateBitCast(Ptr, PTy);
+
+ // Perform the load.
+ llvm::LoadInst *Load = Builder.CreateLoad(Ptr, LV.isVolatileQualified());
+ if (AI.AccessAlignment)
+ Load->setAlignment(AI.AccessAlignment);
+
+ // Shift out unused low bits and mask out unused high bits.
+ llvm::Value *Val = Load;
+ if (AI.FieldBitStart)
+ Val = Builder.CreateLShr(Load, AI.FieldBitStart);
+ Val = Builder.CreateAnd(Val, llvm::APInt::getLowBitsSet(AI.AccessWidth,
+ AI.TargetBitWidth),
+ "bf.clear");
+
+ // Extend or truncate to the target size.
+ if (AI.AccessWidth < ResSizeInBits)
+ Val = Builder.CreateZExt(Val, ResLTy);
+ else if (AI.AccessWidth > ResSizeInBits)
+ Val = Builder.CreateTrunc(Val, ResLTy);
+
+ // Shift into place, and OR into the result.
+ if (AI.TargetBitOffset)
+ Val = Builder.CreateShl(Val, AI.TargetBitOffset);
+ Res = Res ? Builder.CreateOr(Res, Val) : Val;
+ }
+
+ // If the bit-field is signed, perform the sign-extension.
+ //
+ // FIXME: This can easily be folded into the load of the high bits, which
+ // could also eliminate the mask of high bits in some situations.
+ if (Info.isSigned()) {
+ unsigned ExtraBits = ResSizeInBits - Info.getSize();
+ if (ExtraBits)
+ Res = Builder.CreateAShr(Builder.CreateShl(Res, ExtraBits),
+ ExtraBits, "bf.val.sext");
+ }
+
+ return RValue::get(Res);
+}
+
+// If this is a reference to a subset of the elements of a vector, create an
+// appropriate shufflevector.
+RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
+ QualType ExprType) {
+ llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
+ LV.isVolatileQualified(), "tmp");
+
+ const llvm::Constant *Elts = LV.getExtVectorElts();
+
+ // If the result of the expression is a non-vector type, we must be extracting
+ // a single element. Just codegen as an extractelement.
+ const VectorType *ExprVT = ExprType->getAs<VectorType>();
+ if (!ExprVT) {
+ unsigned InIdx = getAccessedFieldNo(0, Elts);
+ llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
+ return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
+ }
+
+ // Always use shuffle vector to try to retain the original program structure
+ unsigned NumResultElts = ExprVT->getNumElements();
+
+ llvm::SmallVector<llvm::Constant*, 4> Mask;
+ for (unsigned i = 0; i != NumResultElts; ++i) {
+ unsigned InIdx = getAccessedFieldNo(i, Elts);
+ Mask.push_back(llvm::ConstantInt::get(Int32Ty, InIdx));
+ }
+
+ llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
+ Vec = Builder.CreateShuffleVector(Vec, llvm::UndefValue::get(Vec->getType()),
+ MaskV, "tmp");
+ return RValue::get(Vec);
+}
+
+
+
+/// EmitStoreThroughLValue - Store the specified rvalue into the specified
+/// lvalue, where both are guaranteed to the have the same type, and that type
+/// is 'Ty'.
+void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
+ QualType Ty) {
+ if (!Dst.isSimple()) {
+ if (Dst.isVectorElt()) {
+ // Read/modify/write the vector, inserting the new element.
+ llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddr(),
+ Dst.isVolatileQualified(), "tmp");
+ Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(),
+ Dst.getVectorIdx(), "vecins");
+ Builder.CreateStore(Vec, Dst.getVectorAddr(),Dst.isVolatileQualified());
+ return;
+ }
+
+ // If this is an update of extended vector elements, insert them as
+ // appropriate.
+ if (Dst.isExtVectorElt())
+ return EmitStoreThroughExtVectorComponentLValue(Src, Dst, Ty);
+
+ if (Dst.isBitField())
+ return EmitStoreThroughBitfieldLValue(Src, Dst, Ty);
+
+ assert(Dst.isPropertyRef() && "Unknown LValue type");
+ return EmitStoreThroughPropertyRefLValue(Src, Dst);
+ }
+
+ if (Dst.isObjCWeak() && !Dst.isNonGC()) {
+ // load of a __weak object.
+ llvm::Value *LvalueDst = Dst.getAddress();
+ llvm::Value *src = Src.getScalarVal();
+ CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst);
+ return;
+ }
+
+ if (Dst.isObjCStrong() && !Dst.isNonGC()) {
+ // load of a __strong object.
+ llvm::Value *LvalueDst = Dst.getAddress();
+ llvm::Value *src = Src.getScalarVal();
+ if (Dst.isObjCIvar()) {
+ assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL");
+ const llvm::Type *ResultType = ConvertType(getContext().LongTy);
+ llvm::Value *RHS = EmitScalarExpr(Dst.getBaseIvarExp());
+ llvm::Value *dst = RHS;
+ RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
+ llvm::Value *LHS =
+ Builder.CreatePtrToInt(LvalueDst, ResultType, "sub.ptr.lhs.cast");
+ llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
+ CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
+ BytesBetween);
+ } else if (Dst.isGlobalObjCRef()) {
+ CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst,
+ Dst.isThreadLocalRef());
+ }
+ else
+ CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
+ return;
+ }
+
+ assert(Src.isScalar() && "Can't emit an agg store with this method");
+ EmitStoreOfScalar(Src.getScalarVal(), Dst.getAddress(),
+ Dst.isVolatileQualified(), Dst.getAlignment(), Ty,
+ Dst.getTBAAInfo());
+}
+
+void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
+ QualType Ty,
+ llvm::Value **Result) {
+ const CGBitFieldInfo &Info = Dst.getBitFieldInfo();
+
+ // Get the output type.
+ const llvm::Type *ResLTy = ConvertTypeForMem(Ty);
+ unsigned ResSizeInBits = CGM.getTargetData().getTypeSizeInBits(ResLTy);
+
+ // Get the source value, truncated to the width of the bit-field.
+ llvm::Value *SrcVal = Src.getScalarVal();
+
+ if (Ty->isBooleanType())
+ SrcVal = Builder.CreateIntCast(SrcVal, ResLTy, /*IsSigned=*/false);
+
+ SrcVal = Builder.CreateAnd(SrcVal, llvm::APInt::getLowBitsSet(ResSizeInBits,
+ Info.getSize()),
+ "bf.value");
+
+ // Return the new value of the bit-field, if requested.
+ if (Result) {
+ // Cast back to the proper type for result.
+ const llvm::Type *SrcTy = Src.getScalarVal()->getType();
+ llvm::Value *ReloadVal = Builder.CreateIntCast(SrcVal, SrcTy, false,
+ "bf.reload.val");
+
+ // Sign extend if necessary.
+ if (Info.isSigned()) {
+ unsigned ExtraBits = ResSizeInBits - Info.getSize();
+ if (ExtraBits)
+ ReloadVal = Builder.CreateAShr(Builder.CreateShl(ReloadVal, ExtraBits),
+ ExtraBits, "bf.reload.sext");
+ }
+
+ *Result = ReloadVal;
+ }
+
+ // Iterate over the components, writing each piece to memory.
+ for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
+ const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
+
+ // Get the field pointer.
+ llvm::Value *Ptr = Dst.getBitFieldBaseAddr();
+ unsigned addressSpace =
+ cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
+
+ // Only offset by the field index if used, so that incoming values are not
+ // required to be structures.
+ if (AI.FieldIndex)
+ Ptr = Builder.CreateStructGEP(Ptr, AI.FieldIndex, "bf.field");
+
+ // Offset by the byte offset, if used.
+ if (AI.FieldByteOffset) {
+ Ptr = EmitCastToVoidPtr(Ptr);
+ Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset,"bf.field.offs");
+ }
+
+ // Cast to the access type.
+ const llvm::Type *AccessLTy =
+ llvm::Type::getIntNTy(getLLVMContext(), AI.AccessWidth);
+
+ const llvm::Type *PTy = AccessLTy->getPointerTo(addressSpace);
+ Ptr = Builder.CreateBitCast(Ptr, PTy);
+
+ // Extract the piece of the bit-field value to write in this access, limited
+ // to the values that are part of this access.
+ llvm::Value *Val = SrcVal;
+ if (AI.TargetBitOffset)
+ Val = Builder.CreateLShr(Val, AI.TargetBitOffset);
+ Val = Builder.CreateAnd(Val, llvm::APInt::getLowBitsSet(ResSizeInBits,
+ AI.TargetBitWidth));
+
+ // Extend or truncate to the access size.
+ if (ResSizeInBits < AI.AccessWidth)
+ Val = Builder.CreateZExt(Val, AccessLTy);
+ else if (ResSizeInBits > AI.AccessWidth)
+ Val = Builder.CreateTrunc(Val, AccessLTy);
+
+ // Shift into the position in memory.
+ if (AI.FieldBitStart)
+ Val = Builder.CreateShl(Val, AI.FieldBitStart);
+
+ // If necessary, load and OR in bits that are outside of the bit-field.
+ if (AI.TargetBitWidth != AI.AccessWidth) {
+ llvm::LoadInst *Load = Builder.CreateLoad(Ptr, Dst.isVolatileQualified());
+ if (AI.AccessAlignment)
+ Load->setAlignment(AI.AccessAlignment);
+
+ // Compute the mask for zeroing the bits that are part of the bit-field.
+ llvm::APInt InvMask =
+ ~llvm::APInt::getBitsSet(AI.AccessWidth, AI.FieldBitStart,
+ AI.FieldBitStart + AI.TargetBitWidth);
+
+ // Apply the mask and OR in to the value to write.
+ Val = Builder.CreateOr(Builder.CreateAnd(Load, InvMask), Val);
+ }
+
+ // Write the value.
+ llvm::StoreInst *Store = Builder.CreateStore(Val, Ptr,
+ Dst.isVolatileQualified());
+ if (AI.AccessAlignment)
+ Store->setAlignment(AI.AccessAlignment);
+ }
+}
+
+void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
+ LValue Dst,
+ QualType Ty) {
+ // This access turns into a read/modify/write of the vector. Load the input
+ // value now.
+ llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(),
+ Dst.isVolatileQualified(), "tmp");
+ const llvm::Constant *Elts = Dst.getExtVectorElts();
+
+ llvm::Value *SrcVal = Src.getScalarVal();
+
+ if (const VectorType *VTy = Ty->getAs<VectorType>()) {
+ unsigned NumSrcElts = VTy->getNumElements();
+ unsigned NumDstElts =
+ cast<llvm::VectorType>(Vec->getType())->getNumElements();
+ if (NumDstElts == NumSrcElts) {
+ // Use shuffle vector is the src and destination are the same number of
+ // elements and restore the vector mask since it is on the side it will be
+ // stored.
+ llvm::SmallVector<llvm::Constant*, 4> Mask(NumDstElts);
+ for (unsigned i = 0; i != NumSrcElts; ++i) {
+ unsigned InIdx = getAccessedFieldNo(i, Elts);
+ Mask[InIdx] = llvm::ConstantInt::get(Int32Ty, i);
+ }
+
+ llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
+ Vec = Builder.CreateShuffleVector(SrcVal,
+ llvm::UndefValue::get(Vec->getType()),
+ MaskV, "tmp");
+ } else if (NumDstElts > NumSrcElts) {
+ // Extended the source vector to the same length and then shuffle it
+ // into the destination.
+ // FIXME: since we're shuffling with undef, can we just use the indices
+ // into that? This could be simpler.
+ llvm::SmallVector<llvm::Constant*, 4> ExtMask;
+ unsigned i;
+ for (i = 0; i != NumSrcElts; ++i)
+ ExtMask.push_back(llvm::ConstantInt::get(Int32Ty, i));
+ for (; i != NumDstElts; ++i)
+ ExtMask.push_back(llvm::UndefValue::get(Int32Ty));
+ llvm::Value *ExtMaskV = llvm::ConstantVector::get(ExtMask);
+ llvm::Value *ExtSrcVal =
+ Builder.CreateShuffleVector(SrcVal,
+ llvm::UndefValue::get(SrcVal->getType()),
+ ExtMaskV, "tmp");
+ // build identity
+ llvm::SmallVector<llvm::Constant*, 4> Mask;
+ for (unsigned i = 0; i != NumDstElts; ++i)
+ Mask.push_back(llvm::ConstantInt::get(Int32Ty, i));
+
+ // modify when what gets shuffled in
+ for (unsigned i = 0; i != NumSrcElts; ++i) {
+ unsigned Idx = getAccessedFieldNo(i, Elts);
+ Mask[Idx] = llvm::ConstantInt::get(Int32Ty, i+NumDstElts);
+ }
+ llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
+ Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
+ } else {
+ // We should never shorten the vector
+ assert(0 && "unexpected shorten vector length");
+ }
+ } else {
+ // If the Src is a scalar (not a vector) it must be updating one element.
+ unsigned InIdx = getAccessedFieldNo(0, Elts);
+ llvm::Value *Elt = llvm::ConstantInt::get(Int32Ty, InIdx);
+ Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
+ }
+
+ Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified());
+}
+
+// setObjCGCLValueClass - sets class of he lvalue for the purpose of
+// generating write-barries API. It is currently a global, ivar,
+// or neither.
+static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
+ LValue &LV) {
+ if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC)
+ return;
+
+ if (isa<ObjCIvarRefExpr>(E)) {
+ LV.setObjCIvar(true);
+ ObjCIvarRefExpr *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr*>(E));
+ LV.setBaseIvarExp(Exp->getBase());
+ LV.setObjCArray(E->getType()->isArrayType());
+ return;
+ }
+
+ if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
+ if (VD->hasGlobalStorage()) {
+ LV.setGlobalObjCRef(true);
+ LV.setThreadLocalRef(VD->isThreadSpecified());
+ }
+ }
+ LV.setObjCArray(E->getType()->isArrayType());
+ return;
+ }
+
+ if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ return;
+ }
+
+ if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ if (LV.isObjCIvar()) {
+ // If cast is to a structure pointer, follow gcc's behavior and make it
+ // a non-ivar write-barrier.
+ QualType ExpTy = E->getType();
+ if (ExpTy->isPointerType())
+ ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
+ if (ExpTy->isRecordType())
+ LV.setObjCIvar(false);
+ }
+ return;
+ }
+ if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ return;
+ }
+
+ if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ return;
+ }
+
+ if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+ if (LV.isObjCIvar() && !LV.isObjCArray())
+ // Using array syntax to assigning to what an ivar points to is not
+ // same as assigning to the ivar itself. {id *Names;} Names[i] = 0;
+ LV.setObjCIvar(false);
+ else if (LV.isGlobalObjCRef() && !LV.isObjCArray())
+ // Using array syntax to assigning to what global points to is not
+ // same as assigning to the global itself. {id *G;} G[i] = 0;
+ LV.setGlobalObjCRef(false);
+ return;
+ }
+
+ if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+ // We don't know if member is an 'ivar', but this flag is looked at
+ // only in the context of LV.isObjCIvar().
+ LV.setObjCArray(E->getType()->isArrayType());
+ return;
+ }
+}
+
+static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
+ const Expr *E, const VarDecl *VD) {
+ assert((VD->hasExternalStorage() || VD->isFileVarDecl()) &&
+ "Var decl must have external storage or be a file var decl!");
+
+ llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
+ if (VD->getType()->isReferenceType())
+ V = CGF.Builder.CreateLoad(V, "tmp");
+ unsigned Alignment = CGF.getContext().getDeclAlign(VD).getQuantity();
+ LValue LV = CGF.MakeAddrLValue(V, E->getType(), Alignment);
+ setObjCGCLValueClass(CGF.getContext(), E, LV);
+ return LV;
+}
+
+static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
+ const Expr *E, const FunctionDecl *FD) {
+ llvm::Value *V = CGF.CGM.GetAddrOfFunction(FD);
+ if (!FD->hasPrototype()) {
+ if (const FunctionProtoType *Proto =
+ FD->getType()->getAs<FunctionProtoType>()) {
+ // Ugly case: for a K&R-style definition, the type of the definition
+ // isn't the same as the type of a use. Correct for this with a
+ // bitcast.
+ QualType NoProtoType =
+ CGF.getContext().getFunctionNoProtoType(Proto->getResultType());
+ NoProtoType = CGF.getContext().getPointerType(NoProtoType);
+ V = CGF.Builder.CreateBitCast(V, CGF.ConvertType(NoProtoType), "tmp");
+ }
+ }
+ unsigned Alignment = CGF.getContext().getDeclAlign(FD).getQuantity();
+ return CGF.MakeAddrLValue(V, E->getType(), Alignment);
+}
+
+LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
+ const NamedDecl *ND = E->getDecl();
+ unsigned Alignment = getContext().getDeclAlign(ND).getQuantity();
+
+ if (ND->hasAttr<WeakRefAttr>()) {
+ const ValueDecl *VD = cast<ValueDecl>(ND);
+ llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
+ return MakeAddrLValue(Aliasee, E->getType(), Alignment);
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+
+ // Check if this is a global variable.
+ if (VD->hasExternalStorage() || VD->isFileVarDecl())
+ return EmitGlobalVarDeclLValue(*this, E, VD);
+
+ bool NonGCable = VD->hasLocalStorage() &&
+ !VD->getType()->isReferenceType() &&
+ !VD->hasAttr<BlocksAttr>();
+
+ llvm::Value *V = LocalDeclMap[VD];
+ if (!V && VD->isStaticLocal())
+ V = CGM.getStaticLocalDeclAddress(VD);
+ assert(V && "DeclRefExpr not entered in LocalDeclMap?");
+
+ if (VD->hasAttr<BlocksAttr>())
+ V = BuildBlockByrefAddress(V, VD);
+
+ if (VD->getType()->isReferenceType())
+ V = Builder.CreateLoad(V, "tmp");
+
+ LValue LV = MakeAddrLValue(V, E->getType(), Alignment);
+ if (NonGCable) {
+ LV.getQuals().removeObjCGCAttr();
+ LV.setNonGC(true);
+ }
+ setObjCGCLValueClass(getContext(), E, LV);
+ return LV;
+ }
+
+ if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, fn);
+
+ assert(false && "Unhandled DeclRefExpr");
+
+ // an invalid LValue, but the assert will
+ // ensure that this point is never reached.
+ return LValue();
+}
+
+LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
+ unsigned Alignment =
+ getContext().getDeclAlign(E->getDecl()).getQuantity();
+ return MakeAddrLValue(GetAddrOfBlockDecl(E), E->getType(), Alignment);
+}
+
+LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
+ // __extension__ doesn't affect lvalue-ness.
+ if (E->getOpcode() == UO_Extension)
+ return EmitLValue(E->getSubExpr());
+
+ QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType());
+ switch (E->getOpcode()) {
+ default: assert(0 && "Unknown unary operator lvalue!");
+ case UO_Deref: {
+ QualType T = E->getSubExpr()->getType()->getPointeeType();
+ assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
+
+ LValue LV = MakeAddrLValue(EmitScalarExpr(E->getSubExpr()), T);
+ LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
+
+ // We should not generate __weak write barrier on indirect reference
+ // of a pointer to object; as in void foo (__weak id *param); *param = 0;
+ // But, we continue to generate __strong write barrier on indirect write
+ // into a pointer to object.
+ if (getContext().getLangOptions().ObjC1 &&
+ getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
+ LV.isObjCWeak())
+ LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
+ return LV;
+ }
+ case UO_Real:
+ case UO_Imag: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ assert(LV.isSimple() && "real/imag on non-ordinary l-value");
+ llvm::Value *Addr = LV.getAddress();
+
+ // real and imag are valid on scalars. This is a faster way of
+ // testing that.
+ if (!cast<llvm::PointerType>(Addr->getType())
+ ->getElementType()->isStructTy()) {
+ assert(E->getSubExpr()->getType()->isArithmeticType());
+ return LV;
+ }
+
+ assert(E->getSubExpr()->getType()->isAnyComplexType());
+
+ unsigned Idx = E->getOpcode() == UO_Imag;
+ return MakeAddrLValue(Builder.CreateStructGEP(LV.getAddress(),
+ Idx, "idx"),
+ ExprTy);
+ }
+ case UO_PreInc:
+ case UO_PreDec: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ bool isInc = E->getOpcode() == UO_PreInc;
+
+ if (E->getType()->isAnyComplexType())
+ EmitComplexPrePostIncDec(E, LV, isInc, true/*isPre*/);
+ else
+ EmitScalarPrePostIncDec(E, LV, isInc, true/*isPre*/);
+ return LV;
+ }
+ }
+}
+
+LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
+ return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
+ E->getType());
+}
+
+LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
+ return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E),
+ E->getType());
+}
+
+
+LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
+ switch (E->getIdentType()) {
+ default:
+ return EmitUnsupportedLValue(E, "predefined expression");
+
+ case PredefinedExpr::Func:
+ case PredefinedExpr::Function:
+ case PredefinedExpr::PrettyFunction: {
+ unsigned Type = E->getIdentType();
+ std::string GlobalVarName;
+
+ switch (Type) {
+ default: assert(0 && "Invalid type");
+ case PredefinedExpr::Func:
+ GlobalVarName = "__func__.";
+ break;
+ case PredefinedExpr::Function:
+ GlobalVarName = "__FUNCTION__.";
+ break;
+ case PredefinedExpr::PrettyFunction:
+ GlobalVarName = "__PRETTY_FUNCTION__.";
+ break;
+ }
+
+ llvm::StringRef FnName = CurFn->getName();
+ if (FnName.startswith("\01"))
+ FnName = FnName.substr(1);
+ GlobalVarName += FnName;
+
+ const Decl *CurDecl = CurCodeDecl;
+ if (CurDecl == 0)
+ CurDecl = getContext().getTranslationUnitDecl();
+
+ std::string FunctionName =
+ (isa<BlockDecl>(CurDecl)
+ ? FnName.str()
+ : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)Type, CurDecl));
+
+ llvm::Constant *C =
+ CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
+ return MakeAddrLValue(C, E->getType());
+ }
+ }
+}
+
+llvm::BasicBlock *CodeGenFunction::getTrapBB() {
+ const CodeGenOptions &GCO = CGM.getCodeGenOpts();
+
+ // If we are not optimzing, don't collapse all calls to trap in the function
+ // to the same call, that way, in the debugger they can see which operation
+ // did in fact fail. If we are optimizing, we collapse all calls to trap down
+ // to just one per function to save on codesize.
+ if (GCO.OptimizationLevel && TrapBB)
+ return TrapBB;
+
+ llvm::BasicBlock *Cont = 0;
+ if (HaveInsertPoint()) {
+ Cont = createBasicBlock("cont");
+ EmitBranch(Cont);
+ }
+ TrapBB = createBasicBlock("trap");
+ EmitBlock(TrapBB);
+
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap, 0, 0);
+ llvm::CallInst *TrapCall = Builder.CreateCall(F);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+
+ if (Cont)
+ EmitBlock(Cont);
+ return TrapBB;
+}
+
+/// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an
+/// array to pointer, return the array subexpression.
+static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
+ // If this isn't just an array->pointer decay, bail out.
+ const CastExpr *CE = dyn_cast<CastExpr>(E);
+ if (CE == 0 || CE->getCastKind() != CK_ArrayToPointerDecay)
+ return 0;
+
+ // If this is a decay from variable width array, bail out.
+ const Expr *SubExpr = CE->getSubExpr();
+ if (SubExpr->getType()->isVariableArrayType())
+ return 0;
+
+ return SubExpr;
+}
+
+LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
+ // The index must always be an integer, which is not an aggregate. Emit it.
+ llvm::Value *Idx = EmitScalarExpr(E->getIdx());
+ QualType IdxTy = E->getIdx()->getType();
+ bool IdxSigned = IdxTy->isSignedIntegerType();
+
+ // If the base is a vector type, then we are forming a vector element lvalue
+ // with this subscript.
+ if (E->getBase()->getType()->isVectorType()) {
+ // Emit the vector as an lvalue to get its address.
+ LValue LHS = EmitLValue(E->getBase());
+ assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
+ Idx = Builder.CreateIntCast(Idx, Int32Ty, IdxSigned, "vidx");
+ return LValue::MakeVectorElt(LHS.getAddress(), Idx,
+ E->getBase()->getType().getCVRQualifiers());
+ }
+
+ // Extend or truncate the index type to 32 or 64-bits.
+ if (Idx->getType() != IntPtrTy)
+ Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom");
+
+ // FIXME: As llvm implements the object size checking, this can come out.
+ if (CatchUndefined) {
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E->getBase())){
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
+ if (ICE->getCastKind() == CK_ArrayToPointerDecay) {
+ if (const ConstantArrayType *CAT
+ = getContext().getAsConstantArrayType(DRE->getType())) {
+ llvm::APInt Size = CAT->getSize();
+ llvm::BasicBlock *Cont = createBasicBlock("cont");
+ Builder.CreateCondBr(Builder.CreateICmpULE(Idx,
+ llvm::ConstantInt::get(Idx->getType(), Size)),
+ Cont, getTrapBB());
+ EmitBlock(Cont);
+ }
+ }
+ }
+ }
+ }
+
+ // We know that the pointer points to a type of the correct size, unless the
+ // size is a VLA or Objective-C interface.
+ llvm::Value *Address = 0;
+ if (const VariableArrayType *VAT =
+ getContext().getAsVariableArrayType(E->getType())) {
+ llvm::Value *VLASize = GetVLASize(VAT);
+
+ Idx = Builder.CreateMul(Idx, VLASize);
+
+ // The base must be a pointer, which is not an aggregate. Emit it.
+ llvm::Value *Base = EmitScalarExpr(E->getBase());
+
+ Address = EmitCastToVoidPtr(Base);
+ Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
+ Address = Builder.CreateBitCast(Address, Base->getType());
+ } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
+ // Indexing over an interface, as in "NSString *P; P[4];"
+ llvm::Value *InterfaceSize =
+ llvm::ConstantInt::get(Idx->getType(),
+ getContext().getTypeSizeInChars(OIT).getQuantity());
+
+ Idx = Builder.CreateMul(Idx, InterfaceSize);
+
+ // The base must be a pointer, which is not an aggregate. Emit it.
+ llvm::Value *Base = EmitScalarExpr(E->getBase());
+ Address = EmitCastToVoidPtr(Base);
+ Address = Builder.CreateGEP(Address, Idx, "arrayidx");
+ Address = Builder.CreateBitCast(Address, Base->getType());
+ } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
+ // If this is A[i] where A is an array, the frontend will have decayed the
+ // base to be a ArrayToPointerDecay implicit cast. While correct, it is
+ // inefficient at -O0 to emit a "gep A, 0, 0" when codegen'ing it, then a
+ // "gep x, i" here. Emit one "gep A, 0, i".
+ assert(Array->getType()->isArrayType() &&
+ "Array to pointer decay must have array source type!");
+ llvm::Value *ArrayPtr = EmitLValue(Array).getAddress();
+ llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0);
+ llvm::Value *Args[] = { Zero, Idx };
+
+ Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx");
+ } else {
+ // The base must be a pointer, which is not an aggregate. Emit it.
+ llvm::Value *Base = EmitScalarExpr(E->getBase());
+ Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx");
+ }
+
+ QualType T = E->getBase()->getType()->getPointeeType();
+ assert(!T.isNull() &&
+ "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
+
+ LValue LV = MakeAddrLValue(Address, T);
+ LV.getQuals().setAddressSpace(E->getBase()->getType().getAddressSpace());
+
+ if (getContext().getLangOptions().ObjC1 &&
+ getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
+ LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
+ setObjCGCLValueClass(getContext(), E, LV);
+ }
+ return LV;
+}
+
+static
+llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext,
+ llvm::SmallVector<unsigned, 4> &Elts) {
+ llvm::SmallVector<llvm::Constant*, 4> CElts;
+
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+ for (unsigned i = 0, e = Elts.size(); i != e; ++i)
+ CElts.push_back(llvm::ConstantInt::get(Int32Ty, Elts[i]));
+
+ return llvm::ConstantVector::get(CElts);
+}
+
+LValue CodeGenFunction::
+EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
+ // Emit the base vector as an l-value.
+ LValue Base;
+
+ // ExtVectorElementExpr's base can either be a vector or pointer to vector.
+ if (E->isArrow()) {
+ // If it is a pointer to a vector, emit the address and form an lvalue with
+ // it.
+ llvm::Value *Ptr = EmitScalarExpr(E->getBase());
+ const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
+ Base = MakeAddrLValue(Ptr, PT->getPointeeType());
+ Base.getQuals().removeObjCGCAttr();
+ } else if (E->getBase()->isGLValue()) {
+ // Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
+ // emit the base as an lvalue.
+ assert(E->getBase()->getType()->isVectorType());
+ Base = EmitLValue(E->getBase());
+ } else {
+ // Otherwise, the base is a normal rvalue (as in (V+V).x), emit it as such.
+ assert(E->getBase()->getType()->getAs<VectorType>() &&
+ "Result must be a vector");
+ llvm::Value *Vec = EmitScalarExpr(E->getBase());
+
+ // Store the vector to memory (because LValue wants an address).
+ llvm::Value *VecMem = CreateMemTemp(E->getBase()->getType());
+ Builder.CreateStore(Vec, VecMem);
+ Base = MakeAddrLValue(VecMem, E->getBase()->getType());
+ }
+
+ // Encode the element access list into a vector of unsigned indices.
+ llvm::SmallVector<unsigned, 4> Indices;
+ E->getEncodedElementAccess(Indices);
+
+ if (Base.isSimple()) {
+ llvm::Constant *CV = GenerateConstantVector(getLLVMContext(), Indices);
+ return LValue::MakeExtVectorElt(Base.getAddress(), CV,
+ Base.getVRQualifiers());
+ }
+ assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
+
+ llvm::Constant *BaseElts = Base.getExtVectorElts();
+ llvm::SmallVector<llvm::Constant *, 4> CElts;
+
+ for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
+ if (isa<llvm::ConstantAggregateZero>(BaseElts))
+ CElts.push_back(llvm::ConstantInt::get(Int32Ty, 0));
+ else
+ CElts.push_back(cast<llvm::Constant>(BaseElts->getOperand(Indices[i])));
+ }
+ llvm::Constant *CV = llvm::ConstantVector::get(CElts);
+ return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
+ Base.getVRQualifiers());
+}
+
+LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
+ bool isNonGC = false;
+ Expr *BaseExpr = E->getBase();
+ llvm::Value *BaseValue = NULL;
+ Qualifiers BaseQuals;
+
+ // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
+ if (E->isArrow()) {
+ BaseValue = EmitScalarExpr(BaseExpr);
+ const PointerType *PTy =
+ BaseExpr->getType()->getAs<PointerType>();
+ BaseQuals = PTy->getPointeeType().getQualifiers();
+ } else {
+ LValue BaseLV = EmitLValue(BaseExpr);
+ if (BaseLV.isNonGC())
+ isNonGC = true;
+ // FIXME: this isn't right for bitfields.
+ BaseValue = BaseLV.getAddress();
+ QualType BaseTy = BaseExpr->getType();
+ BaseQuals = BaseTy.getQualifiers();
+ }
+
+ NamedDecl *ND = E->getMemberDecl();
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
+ LValue LV = EmitLValueForField(BaseValue, Field,
+ BaseQuals.getCVRQualifiers());
+ LV.setNonGC(isNonGC);
+ setObjCGCLValueClass(getContext(), E, LV);
+ return LV;
+ }
+
+ if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+ return EmitGlobalVarDeclLValue(*this, E, VD);
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, FD);
+
+ assert(false && "Unhandled member declaration!");
+ return LValue();
+}
+
+LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value *BaseValue,
+ const FieldDecl *Field,
+ unsigned CVRQualifiers) {
+ const CGRecordLayout &RL =
+ CGM.getTypes().getCGRecordLayout(Field->getParent());
+ const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field);
+ return LValue::MakeBitfield(BaseValue, Info,
+ Field->getType().getCVRQualifiers()|CVRQualifiers);
+}
+
+/// EmitLValueForAnonRecordField - Given that the field is a member of
+/// an anonymous struct or union buried inside a record, and given
+/// that the base value is a pointer to the enclosing record, derive
+/// an lvalue for the ultimate field.
+LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
+ const IndirectFieldDecl *Field,
+ unsigned CVRQualifiers) {
+ IndirectFieldDecl::chain_iterator I = Field->chain_begin(),
+ IEnd = Field->chain_end();
+ while (true) {
+ LValue LV = EmitLValueForField(BaseValue, cast<FieldDecl>(*I), CVRQualifiers);
+ if (++I == IEnd) return LV;
+
+ assert(LV.isSimple());
+ BaseValue = LV.getAddress();
+ CVRQualifiers |= LV.getVRQualifiers();
+ }
+}
+
+LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
+ const FieldDecl *Field,
+ unsigned CVRQualifiers) {
+ if (Field->isBitField())
+ return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
+
+ const CGRecordLayout &RL =
+ CGM.getTypes().getCGRecordLayout(Field->getParent());
+ unsigned idx = RL.getLLVMFieldNo(Field);
+ llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+
+ // Match union field type.
+ if (Field->getParent()->isUnion()) {
+ const llvm::Type *FieldTy =
+ CGM.getTypes().ConvertTypeForMem(Field->getType());
+ const llvm::PointerType *BaseTy =
+ cast<llvm::PointerType>(BaseValue->getType());
+ unsigned AS = BaseTy->getAddressSpace();
+ V = Builder.CreateBitCast(V,
+ llvm::PointerType::get(FieldTy, AS),
+ "tmp");
+ }
+ if (Field->getType()->isReferenceType())
+ V = Builder.CreateLoad(V, "tmp");
+
+ unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
+ LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
+ LV.getQuals().addCVRQualifiers(CVRQualifiers);
+
+ // __weak attribute on a field is ignored.
+ if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
+ LV.getQuals().removeObjCGCAttr();
+
+ return LV;
+}
+
+LValue
+CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value *BaseValue,
+ const FieldDecl *Field,
+ unsigned CVRQualifiers) {
+ QualType FieldType = Field->getType();
+
+ if (!FieldType->isReferenceType())
+ return EmitLValueForField(BaseValue, Field, CVRQualifiers);
+
+ const CGRecordLayout &RL =
+ CGM.getTypes().getCGRecordLayout(Field->getParent());
+ unsigned idx = RL.getLLVMFieldNo(Field);
+ llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+
+ assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
+
+ unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
+ return MakeAddrLValue(V, FieldType, Alignment);
+}
+
+LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
+ llvm::Value *DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
+ const Expr *InitExpr = E->getInitializer();
+ LValue Result = MakeAddrLValue(DeclPtr, E->getType());
+
+ EmitAnyExprToMem(InitExpr, DeclPtr, /*Volatile*/ false, /*Init*/ true);
+
+ return Result;
+}
+
+LValue CodeGenFunction::
+EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
+ if (!expr->isGLValue()) {
+ // ?: here should be an aggregate.
+ assert((hasAggregateLLVMType(expr->getType()) &&
+ !expr->getType()->isAnyComplexType()) &&
+ "Unexpected conditional operator!");
+ return EmitAggExprToLValue(expr);
+ }
+
+ const Expr *condExpr = expr->getCond();
+
+ if (int condValue = ConstantFoldsToSimpleInteger(condExpr)) {
+ const Expr *live = expr->getTrueExpr(), *dead = expr->getFalseExpr();
+ if (condValue == -1) std::swap(live, dead);
+
+ if (!ContainsLabel(dead))
+ return EmitLValue(live);
+ }
+
+ OpaqueValueMapping binding(*this, expr);
+
+ llvm::BasicBlock *lhsBlock = createBasicBlock("cond.true");
+ llvm::BasicBlock *rhsBlock = createBasicBlock("cond.false");
+ llvm::BasicBlock *contBlock = createBasicBlock("cond.end");
+
+ ConditionalEvaluation eval(*this);
+ EmitBranchOnBoolExpr(condExpr, lhsBlock, rhsBlock);
+
+ // Any temporaries created here are conditional.
+ EmitBlock(lhsBlock);
+ eval.begin(*this);
+ LValue lhs = EmitLValue(expr->getTrueExpr());
+ eval.end(*this);
+
+ if (!lhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
+
+ lhsBlock = Builder.GetInsertBlock();
+ Builder.CreateBr(contBlock);
+
+ // Any temporaries created here are conditional.
+ EmitBlock(rhsBlock);
+ eval.begin(*this);
+ LValue rhs = EmitLValue(expr->getFalseExpr());
+ eval.end(*this);
+ if (!rhs.isSimple())
+ return EmitUnsupportedLValue(expr, "conditional operator");
+ rhsBlock = Builder.GetInsertBlock();
+
+ EmitBlock(contBlock);
+
+ llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(),
+ "cond-lvalue");
+ phi->reserveOperandSpace(2);
+ phi->addIncoming(lhs.getAddress(), lhsBlock);
+ phi->addIncoming(rhs.getAddress(), rhsBlock);
+ return MakeAddrLValue(phi, expr->getType());
+}
+
+/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
+/// If the cast is a dynamic_cast, we can have the usual lvalue result,
+/// otherwise if a cast is needed by the code generator in an lvalue context,
+/// then it must mean that we need the address of an aggregate in order to
+/// access one of its fields. This can happen for all the reasons that casts
+/// are permitted with aggregate result, including noop aggregate casts, and
+/// cast from scalar to union.
+LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
+ switch (E->getCastKind()) {
+ case CK_ToVoid:
+ return EmitUnsupportedLValue(E, "unexpected cast lvalue");
+
+ case CK_Dependent:
+ llvm_unreachable("dependent cast kind in IR gen!");
+
+ case CK_GetObjCProperty: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ assert(LV.isPropertyRef());
+ RValue RV = EmitLoadOfPropertyRefLValue(LV);
+
+ // Property is an aggregate r-value.
+ if (RV.isAggregate()) {
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+ }
+
+ // Implicit property returns an l-value.
+ assert(RV.isScalar());
+ return MakeAddrLValue(RV.getScalarVal(), E->getSubExpr()->getType());
+ }
+
+ case CK_NoOp:
+ case CK_LValueToRValue:
+ if (!E->getSubExpr()->Classify(getContext()).isPRValue()
+ || E->getType()->isRecordType())
+ return EmitLValue(E->getSubExpr());
+ // Fall through to synthesize a temporary.
+
+ case CK_BitCast:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToMemberPointer:
+ case CK_NullToPointer:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_IntegralToBoolean:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
+ case CK_FloatingCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexToBoolean:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_MemberPointerToBoolean:
+ case CK_AnyPointerToBlockPointerCast: {
+ // These casts only produce lvalues when we're binding a reference to a
+ // temporary realized from a (converted) pure rvalue. Emit the expression
+ // as a value, copy it into a temporary, and return an lvalue referring to
+ // that temporary.
+ llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
+ EmitAnyExprToMem(E, V, false, false);
+ return MakeAddrLValue(V, E->getType());
+ }
+
+ case CK_Dynamic: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ llvm::Value *V = LV.getAddress();
+ const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(E);
+ return MakeAddrLValue(EmitDynamicCast(V, DCE), E->getType());
+ }
+
+ case CK_ConstructorConversion:
+ case CK_UserDefinedConversion:
+ case CK_AnyPointerToObjCPointerCast:
+ return EmitLValue(E->getSubExpr());
+
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBase: {
+ const RecordType *DerivedClassTy =
+ E->getSubExpr()->getType()->getAs<RecordType>();
+ CXXRecordDecl *DerivedClassDecl =
+ cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+
+ LValue LV = EmitLValue(E->getSubExpr());
+ llvm::Value *This = LV.getAddress();
+
+ // Perform the derived-to-base conversion
+ llvm::Value *Base =
+ GetAddressOfBaseClass(This, DerivedClassDecl,
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
+
+ return MakeAddrLValue(Base, E->getType());
+ }
+ case CK_ToUnion:
+ return EmitAggExprToLValue(E);
+ case CK_BaseToDerived: {
+ const RecordType *DerivedClassTy = E->getType()->getAs<RecordType>();
+ CXXRecordDecl *DerivedClassDecl =
+ cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+
+ LValue LV = EmitLValue(E->getSubExpr());
+
+ // Perform the base-to-derived conversion
+ llvm::Value *Derived =
+ GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
+
+ return MakeAddrLValue(Derived, E->getType());
+ }
+ case CK_LValueBitCast: {
+ // This must be a reinterpret_cast (or c-style equivalent).
+ const ExplicitCastExpr *CE = cast<ExplicitCastExpr>(E);
+
+ LValue LV = EmitLValue(E->getSubExpr());
+ llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
+ ConvertType(CE->getTypeAsWritten()));
+ return MakeAddrLValue(V, E->getType());
+ }
+ case CK_ObjCObjectLValueCast: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ QualType ToType = getContext().getLValueReferenceType(E->getType());
+ llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
+ ConvertType(ToType));
+ return MakeAddrLValue(V, E->getType());
+ }
+ }
+
+ llvm_unreachable("Unhandled lvalue cast kind?");
+}
+
+LValue CodeGenFunction::EmitNullInitializationLValue(
+ const CXXScalarValueInitExpr *E) {
+ QualType Ty = E->getType();
+ LValue LV = MakeAddrLValue(CreateMemTemp(Ty), Ty);
+ EmitNullInitialization(LV.getAddress(), Ty);
+ return LV;
+}
+
+LValue CodeGenFunction::EmitOpaqueValueLValue(const OpaqueValueExpr *e) {
+ assert(e->isGLValue() || e->getType()->isRecordType());
+ return getOpaqueLValueMapping(e);
+}
+
+//===--------------------------------------------------------------------===//
+// Expression Emission
+//===--------------------------------------------------------------------===//
+
+
+RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
+ ReturnValueSlot ReturnValue) {
+ // Builtins never have block type.
+ if (E->getCallee()->getType()->isBlockPointerType())
+ return EmitBlockCallExpr(E, ReturnValue);
+
+ if (const CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(E))
+ return EmitCXXMemberCallExpr(CE, ReturnValue);
+
+ const Decl *TargetDecl = 0;
+ if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+ TargetDecl = DRE->getDecl();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(TargetDecl))
+ if (unsigned builtinID = FD->getBuiltinID())
+ return EmitBuiltinExpr(FD, builtinID, E);
+ }
+ }
+
+ if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E))
+ if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
+ return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
+
+ if (isa<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
+ // C++ [expr.pseudo]p1:
+ // The result shall only be used as the operand for the function call
+ // operator (), and the result of such a call has type void. The only
+ // effect is the evaluation of the postfix-expression before the dot or
+ // arrow.
+ EmitScalarExpr(E->getCallee());
+ return RValue::get(0);
+ }
+
+ llvm::Value *Callee = EmitScalarExpr(E->getCallee());
+ return EmitCall(E->getCallee()->getType(), Callee, ReturnValue,
+ E->arg_begin(), E->arg_end(), TargetDecl);
+}
+
+LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
+ // Comma expressions just emit their LHS then their RHS as an l-value.
+ if (E->getOpcode() == BO_Comma) {
+ EmitIgnoredExpr(E->getLHS());
+ EnsureInsertPoint();
+ return EmitLValue(E->getRHS());
+ }
+
+ if (E->getOpcode() == BO_PtrMemD ||
+ E->getOpcode() == BO_PtrMemI)
+ return EmitPointerToDataMemberBinaryExpr(E);
+
+ assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
+
+ if (!hasAggregateLLVMType(E->getType())) {
+ // __block variables need the RHS evaluated first.
+ RValue RV = EmitAnyExpr(E->getRHS());
+ LValue LV = EmitLValue(E->getLHS());
+ EmitStoreThroughLValue(RV, LV, E->getType());
+ return LV;
+ }
+
+ if (E->getType()->isAnyComplexType())
+ return EmitComplexAssignmentLValue(E);
+
+ return EmitAggExprToLValue(E);
+}
+
+LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
+ RValue RV = EmitCallExpr(E);
+
+ if (!RV.isScalar())
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+
+ assert(E->getCallReturnType()->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
+
+ return MakeAddrLValue(RV.getScalarVal(), E->getType());
+}
+
+LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
+ // FIXME: This shouldn't require another copy.
+ return EmitAggExprToLValue(E);
+}
+
+LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
+ assert(E->getType()->getAsCXXRecordDecl()->hasTrivialDestructor()
+ && "binding l-value to type which needs a temporary");
+ AggValueSlot Slot = CreateAggTemp(E->getType(), "tmp");
+ EmitCXXConstructExpr(E, Slot);
+ return MakeAddrLValue(Slot.getAddr(), E->getType());
+}
+
+LValue
+CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
+ return MakeAddrLValue(EmitCXXTypeidExpr(E), E->getType());
+}
+
+LValue
+CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
+ AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
+ Slot.setLifetimeExternallyManaged();
+ EmitAggExpr(E->getSubExpr(), Slot);
+ EmitCXXTemporary(E->getTemporary(), Slot.getAddr());
+ return MakeAddrLValue(Slot.getAddr(), E->getType());
+}
+
+LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
+ RValue RV = EmitObjCMessageExpr(E);
+
+ if (!RV.isScalar())
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+
+ assert(E->getMethodDecl()->getResultType()->isReferenceType() &&
+ "Can't have a scalar return unless the return type is a "
+ "reference type!");
+
+ return MakeAddrLValue(RV.getScalarVal(), E->getType());
+}
+
+LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
+ llvm::Value *V =
+ CGM.getObjCRuntime().GetSelector(Builder, E->getSelector(), true);
+ return MakeAddrLValue(V, E->getType());
+}
+
+llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) {
+ return CGM.getObjCRuntime().EmitIvarOffset(*this, Interface, Ivar);
+}
+
+LValue CodeGenFunction::EmitLValueForIvar(QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers) {
+ return CGM.getObjCRuntime().EmitObjCValueForIvar(*this, ObjectTy, BaseValue,
+ Ivar, CVRQualifiers);
+}
+
+LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
+ // FIXME: A lot of the code below could be shared with EmitMemberExpr.
+ llvm::Value *BaseValue = 0;
+ const Expr *BaseExpr = E->getBase();
+ Qualifiers BaseQuals;
+ QualType ObjectTy;
+ if (E->isArrow()) {
+ BaseValue = EmitScalarExpr(BaseExpr);
+ ObjectTy = BaseExpr->getType()->getPointeeType();
+ BaseQuals = ObjectTy.getQualifiers();
+ } else {
+ LValue BaseLV = EmitLValue(BaseExpr);
+ // FIXME: this isn't right for bitfields.
+ BaseValue = BaseLV.getAddress();
+ ObjectTy = BaseExpr->getType();
+ BaseQuals = ObjectTy.getQualifiers();
+ }
+
+ LValue LV =
+ EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
+ BaseQuals.getCVRQualifiers());
+ setObjCGCLValueClass(getContext(), E, LV);
+ return LV;
+}
+
+LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
+ // Can only get l-value for message expression returning aggregate type
+ RValue RV = EmitAnyExprToTemp(E);
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+}
+
+RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ const Decl *TargetDecl) {
+ // Get the actual function type. The callee type will always be a pointer to
+ // function type or a block pointer type.
+ assert(CalleeType->isFunctionPointerType() &&
+ "Call must have function pointer type!");
+
+ CalleeType = getContext().getCanonicalType(CalleeType);
+
+ const FunctionType *FnType
+ = cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+
+ CallArgList Args;
+ EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
+
+ return EmitCall(CGM.getTypes().getFunctionInfo(Args, FnType),
+ Callee, ReturnValue, Args, TargetDecl);
+}
+
+LValue CodeGenFunction::
+EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
+ llvm::Value *BaseV;
+ if (E->getOpcode() == BO_PtrMemI)
+ BaseV = EmitScalarExpr(E->getLHS());
+ else
+ BaseV = EmitLValue(E->getLHS()).getAddress();
+
+ llvm::Value *OffsetV = EmitScalarExpr(E->getRHS());
+
+ const MemberPointerType *MPT
+ = E->getRHS()->getType()->getAs<MemberPointerType>();
+
+ llvm::Value *AddV =
+ CGM.getCXXABI().EmitMemberDataPointerAddress(*this, BaseV, OffsetV, MPT);
+
+ return MakeAddrLValue(AddV, MPT->getPointeeType());
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
new file mode 100644
index 0000000..f992dc7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
@@ -0,0 +1,944 @@
+//===--- CGExprAgg.cpp - Emit LLVM Code from Aggregate Expressions --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Aggregate Expr nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGObjCRuntime.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Intrinsics.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===----------------------------------------------------------------------===//
+// Aggregate Expression Emitter
+//===----------------------------------------------------------------------===//
+
+namespace {
+class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
+ CodeGenFunction &CGF;
+ CGBuilderTy &Builder;
+ AggValueSlot Dest;
+ bool IgnoreResult;
+
+ ReturnValueSlot getReturnValueSlot() const {
+ // If the destination slot requires garbage collection, we can't
+ // use the real return value slot, because we have to use the GC
+ // API.
+ if (Dest.requiresGCollection()) return ReturnValueSlot();
+
+ return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile());
+ }
+
+ AggValueSlot EnsureSlot(QualType T) {
+ if (!Dest.isIgnored()) return Dest;
+ return CGF.CreateAggTemp(T, "agg.tmp.ensured");
+ }
+
+public:
+ AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest,
+ bool ignore)
+ : CGF(cgf), Builder(CGF.Builder), Dest(Dest),
+ IgnoreResult(ignore) {
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Utilities
+ //===--------------------------------------------------------------------===//
+
+ /// EmitAggLoadOfLValue - Given an expression with aggregate type that
+ /// represents a value lvalue, this method emits the address of the lvalue,
+ /// then loads the result into DestPtr.
+ void EmitAggLoadOfLValue(const Expr *E);
+
+ /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
+ void EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore = false);
+ void EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore = false);
+
+ void EmitGCMove(const Expr *E, RValue Src);
+
+ bool TypeRequiresGCollection(QualType T);
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ void VisitStmt(Stmt *S) {
+ CGF.ErrorUnsupported(S, "aggregate expression");
+ }
+ void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); }
+ void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); }
+
+ // l-values.
+ void VisitDeclRefExpr(DeclRefExpr *DRE) { EmitAggLoadOfLValue(DRE); }
+ void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
+ void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); }
+ void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); }
+ void VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ EmitAggLoadOfLValue(E);
+ }
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ EmitAggLoadOfLValue(E);
+ }
+ void VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) {
+ EmitAggLoadOfLValue(E);
+ }
+ void VisitPredefinedExpr(const PredefinedExpr *E) {
+ EmitAggLoadOfLValue(E);
+ }
+
+ // Operators.
+ void VisitCastExpr(CastExpr *E);
+ void VisitCallExpr(const CallExpr *E);
+ void VisitStmtExpr(const StmtExpr *E);
+ void VisitBinaryOperator(const BinaryOperator *BO);
+ void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
+ void VisitBinAssign(const BinaryOperator *E);
+ void VisitBinComma(const BinaryOperator *E);
+
+ void VisitObjCMessageExpr(ObjCMessageExpr *E);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ EmitAggLoadOfLValue(E);
+ }
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
+
+ void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
+ void VisitChooseExpr(const ChooseExpr *CE);
+ void VisitInitListExpr(InitListExpr *E);
+ void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ Visit(DAE->getExpr());
+ }
+ void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+ void VisitCXXConstructExpr(const CXXConstructExpr *E);
+ void VisitExprWithCleanups(ExprWithCleanups *E);
+ void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
+
+ void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
+ void VisitVAArgExpr(VAArgExpr *E);
+
+ void EmitInitializationToLValue(Expr *E, LValue Address, QualType T);
+ void EmitNullInitializationToLValue(LValue Address, QualType T);
+ // case Expr::ChooseExprClass:
+ void VisitCXXThrowExpr(const CXXThrowExpr *E) { CGF.EmitCXXThrowExpr(E); }
+};
+} // end anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// EmitAggLoadOfLValue - Given an expression with aggregate type that
+/// represents a value lvalue, this method emits the address of the lvalue,
+/// then loads the result into DestPtr.
+void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) {
+ LValue LV = CGF.EmitLValue(E);
+ EmitFinalDestCopy(E, LV);
+}
+
+/// \brief True if the given aggregate type requires special GC API calls.
+bool AggExprEmitter::TypeRequiresGCollection(QualType T) {
+ // Only record types have members that might require garbage collection.
+ const RecordType *RecordTy = T->getAs<RecordType>();
+ if (!RecordTy) return false;
+
+ // Don't mess with non-trivial C++ types.
+ RecordDecl *Record = RecordTy->getDecl();
+ if (isa<CXXRecordDecl>(Record) &&
+ (!cast<CXXRecordDecl>(Record)->hasTrivialCopyConstructor() ||
+ !cast<CXXRecordDecl>(Record)->hasTrivialDestructor()))
+ return false;
+
+ // Check whether the type has an object member.
+ return Record->hasObjectMember();
+}
+
+/// \brief Perform the final move to DestPtr if RequiresGCollection is set.
+///
+/// The idea is that you do something like this:
+/// RValue Result = EmitSomething(..., getReturnValueSlot());
+/// EmitGCMove(E, Result);
+/// If GC doesn't interfere, this will cause the result to be emitted
+/// directly into the return value slot. If GC does interfere, a final
+/// move will be performed.
+void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) {
+ if (Dest.requiresGCollection()) {
+ std::pair<uint64_t, unsigned> TypeInfo =
+ CGF.getContext().getTypeInfo(E->getType());
+ unsigned long size = TypeInfo.first/8;
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+ llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size);
+ CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, Dest.getAddr(),
+ Src.getAggregateAddr(),
+ SizeVal);
+ }
+}
+
+/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
+void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) {
+ assert(Src.isAggregate() && "value must be aggregate value!");
+
+ // If Dest is ignored, then we're evaluating an aggregate expression
+ // in a context (like an expression statement) that doesn't care
+ // about the result. C says that an lvalue-to-rvalue conversion is
+ // performed in these cases; C++ says that it is not. In either
+ // case, we don't actually need to do anything unless the value is
+ // volatile.
+ if (Dest.isIgnored()) {
+ if (!Src.isVolatileQualified() ||
+ CGF.CGM.getLangOptions().CPlusPlus ||
+ (IgnoreResult && Ignore))
+ return;
+
+ // If the source is volatile, we must read from it; to do that, we need
+ // some place to put it.
+ Dest = CGF.CreateAggTemp(E->getType(), "agg.tmp");
+ }
+
+ if (Dest.requiresGCollection()) {
+ std::pair<uint64_t, unsigned> TypeInfo =
+ CGF.getContext().getTypeInfo(E->getType());
+ unsigned long size = TypeInfo.first/8;
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+ llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size);
+ CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF,
+ Dest.getAddr(),
+ Src.getAggregateAddr(),
+ SizeVal);
+ return;
+ }
+ // If the result of the assignment is used, copy the LHS there also.
+ // FIXME: Pass VolatileDest as well. I think we also need to merge volatile
+ // from the source as well, as we can't eliminate it if either operand
+ // is volatile, unless copy has volatile for both source and destination..
+ CGF.EmitAggregateCopy(Dest.getAddr(), Src.getAggregateAddr(), E->getType(),
+ Dest.isVolatile()|Src.isVolatileQualified());
+}
+
+/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
+void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
+ assert(Src.isSimple() && "Can't have aggregate bitfield, vector, etc");
+
+ EmitFinalDestCopy(E, RValue::getAggregate(Src.getAddress(),
+ Src.isVolatileQualified()),
+ Ignore);
+}
+
+//===----------------------------------------------------------------------===//
+// Visitor Methods
+//===----------------------------------------------------------------------===//
+
+void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
+ EmitFinalDestCopy(e, CGF.getOpaqueLValueMapping(e));
+}
+
+void AggExprEmitter::VisitCastExpr(CastExpr *E) {
+ if (Dest.isIgnored() && E->getCastKind() != CK_Dynamic) {
+ Visit(E->getSubExpr());
+ return;
+ }
+
+ switch (E->getCastKind()) {
+ case CK_Dynamic: {
+ assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?");
+ LValue LV = CGF.EmitCheckedLValue(E->getSubExpr());
+ // FIXME: Do we also need to handle property references here?
+ if (LV.isSimple())
+ CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E));
+ else
+ CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast");
+
+ if (!Dest.isIgnored())
+ CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination");
+ break;
+ }
+
+ case CK_ToUnion: {
+ // GCC union extension
+ QualType Ty = E->getSubExpr()->getType();
+ QualType PtrTy = CGF.getContext().getPointerType(Ty);
+ llvm::Value *CastPtr = Builder.CreateBitCast(Dest.getAddr(),
+ CGF.ConvertType(PtrTy));
+ EmitInitializationToLValue(E->getSubExpr(), CGF.MakeAddrLValue(CastPtr, Ty),
+ Ty);
+ break;
+ }
+
+ case CK_DerivedToBase:
+ case CK_BaseToDerived:
+ case CK_UncheckedDerivedToBase: {
+ assert(0 && "cannot perform hierarchy conversion in EmitAggExpr: "
+ "should have been unpacked before we got here");
+ break;
+ }
+
+ case CK_GetObjCProperty: {
+ LValue LV = CGF.EmitLValue(E->getSubExpr());
+ assert(LV.isPropertyRef());
+ RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV, getReturnValueSlot());
+ EmitGCMove(E, RV);
+ break;
+ }
+
+ case CK_LValueToRValue: // hope for downstream optimization
+ case CK_NoOp:
+ case CK_UserDefinedConversion:
+ case CK_ConstructorConversion:
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(),
+ E->getType()) &&
+ "Implicit cast types must be compatible");
+ Visit(E->getSubExpr());
+ break;
+
+ case CK_LValueBitCast:
+ llvm_unreachable("should not be emitting lvalue bitcast as rvalue");
+ break;
+
+ case CK_Dependent:
+ case CK_BitCast:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToPointer:
+ case CK_NullToMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_MemberPointerToBoolean:
+ 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_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexToBoolean:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ llvm_unreachable("cast kind invalid for aggregate types");
+ }
+}
+
+void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
+ if (E->getCallReturnType()->isReferenceType()) {
+ EmitAggLoadOfLValue(E);
+ return;
+ }
+
+ RValue RV = CGF.EmitCallExpr(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
+}
+
+void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ RValue RV = CGF.EmitObjCMessageExpr(E, getReturnValueSlot());
+ EmitGCMove(E, RV);
+}
+
+void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ llvm_unreachable("direct property access not surrounded by "
+ "lvalue-to-rvalue cast");
+}
+
+void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
+ CGF.EmitIgnoredExpr(E->getLHS());
+ Visit(E->getRHS());
+}
+
+void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
+ CodeGenFunction::StmtExprEvaluation eval(CGF);
+ CGF.EmitCompoundStmt(*E->getSubStmt(), true, Dest);
+}
+
+void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
+ if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI)
+ VisitPointerToDataMemberBinaryOperator(E);
+ else
+ CGF.ErrorUnsupported(E, "aggregate binary expression");
+}
+
+void AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
+ const BinaryOperator *E) {
+ LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E);
+ EmitFinalDestCopy(E, LV);
+}
+
+void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ // For an assignment to work, the value on the right has
+ // to be compatible with the value on the left.
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
+ E->getRHS()->getType())
+ && "Invalid assignment");
+
+ // FIXME: __block variables need the RHS evaluated first!
+ LValue LHS = CGF.EmitLValue(E->getLHS());
+
+ // We have to special case property setters, otherwise we must have
+ // a simple lvalue (no aggregates inside vectors, bitfields).
+ if (LHS.isPropertyRef()) {
+ AggValueSlot Slot = EnsureSlot(E->getRHS()->getType());
+ CGF.EmitAggExpr(E->getRHS(), Slot);
+ CGF.EmitStoreThroughPropertyRefLValue(Slot.asRValue(), LHS);
+ } else {
+ bool GCollection = false;
+ if (CGF.getContext().getLangOptions().getGCMode())
+ GCollection = TypeRequiresGCollection(E->getLHS()->getType());
+
+ // Codegen the RHS so that it stores directly into the LHS.
+ AggValueSlot LHSSlot = AggValueSlot::forLValue(LHS, true,
+ GCollection);
+ CGF.EmitAggExpr(E->getRHS(), LHSSlot, false);
+ EmitFinalDestCopy(E, LHS, true);
+ }
+}
+
+void AggExprEmitter::
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
+ llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
+
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
+
+ // Save whether the destination's lifetime is externally managed.
+ bool DestLifetimeManaged = Dest.isLifetimeExternallyManaged();
+
+ eval.begin(CGF);
+ CGF.EmitBlock(LHSBlock);
+ Visit(E->getTrueExpr());
+ eval.end(CGF);
+
+ assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!");
+ CGF.Builder.CreateBr(ContBlock);
+
+ // If the result of an agg expression is unused, then the emission
+ // of the LHS might need to create a destination slot. That's fine
+ // with us, and we can safely emit the RHS into the same slot, but
+ // we shouldn't claim that its lifetime is externally managed.
+ Dest.setLifetimeExternallyManaged(DestLifetimeManaged);
+
+ eval.begin(CGF);
+ CGF.EmitBlock(RHSBlock);
+ Visit(E->getFalseExpr());
+ eval.end(CGF);
+
+ CGF.EmitBlock(ContBlock);
+}
+
+void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
+ Visit(CE->getChosenSubExpr(CGF.getContext()));
+}
+
+void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
+ llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
+ llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+
+ if (!ArgPtr) {
+ CGF.ErrorUnsupported(VE, "aggregate va_arg expression");
+ return;
+ }
+
+ EmitFinalDestCopy(VE, CGF.MakeAddrLValue(ArgPtr, VE->getType()));
+}
+
+void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ // Ensure that we have a slot, but if we already do, remember
+ // whether its lifetime was externally managed.
+ bool WasManaged = Dest.isLifetimeExternallyManaged();
+ Dest = EnsureSlot(E->getType());
+ Dest.setLifetimeExternallyManaged();
+
+ Visit(E->getSubExpr());
+
+ // Set up the temporary's destructor if its lifetime wasn't already
+ // being managed.
+ if (!WasManaged)
+ CGF.EmitCXXTemporary(E->getTemporary(), Dest.getAddr());
+}
+
+void
+AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
+ AggValueSlot Slot = EnsureSlot(E->getType());
+ CGF.EmitCXXConstructExpr(E, Slot);
+}
+
+void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
+ CGF.EmitExprWithCleanups(E, Dest);
+}
+
+void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ QualType T = E->getType();
+ AggValueSlot Slot = EnsureSlot(T);
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T), T);
+}
+
+void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+ QualType T = E->getType();
+ AggValueSlot Slot = EnsureSlot(T);
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T), T);
+}
+
+/// isSimpleZero - If emitting this value will obviously just cause a store of
+/// zero to memory, return true. This can return false if uncertain, so it just
+/// handles simple cases.
+static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
+ // (0)
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ return isSimpleZero(PE->getSubExpr(), CGF);
+ // 0
+ if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E))
+ return IL->getValue() == 0;
+ // +0.0
+ if (const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(E))
+ return FL->getValue().isPosZero();
+ // int()
+ if ((isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) &&
+ CGF.getTypes().isZeroInitializable(E->getType()))
+ return true;
+ // (int*)0 - Null pointer expressions.
+ if (const CastExpr *ICE = dyn_cast<CastExpr>(E))
+ return ICE->getCastKind() == CK_NullToPointer;
+ // '\0'
+ if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E))
+ return CL->getValue() == 0;
+
+ // Otherwise, hard case: conservatively return false.
+ return false;
+}
+
+
+void
+AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV, QualType T) {
+ // FIXME: Ignore result?
+ // FIXME: Are initializers affected by volatile?
+ if (Dest.isZeroed() && isSimpleZero(E, CGF)) {
+ // Storing "i32 0" to a zero'd memory location is a noop.
+ } else if (isa<ImplicitValueInitExpr>(E)) {
+ EmitNullInitializationToLValue(LV, T);
+ } else if (T->isReferenceType()) {
+ RValue RV = CGF.EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
+ CGF.EmitStoreThroughLValue(RV, LV, T);
+ } else if (T->isAnyComplexType()) {
+ CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
+ } else if (CGF.hasAggregateLLVMType(T)) {
+ CGF.EmitAggExpr(E, AggValueSlot::forAddr(LV.getAddress(), false, true,
+ false, Dest.isZeroed()));
+ } else {
+ CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV, T);
+ }
+}
+
+void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) {
+ // If the destination slot is already zeroed out before the aggregate is
+ // copied into it, we don't have to emit any zeros here.
+ if (Dest.isZeroed() && CGF.getTypes().isZeroInitializable(T))
+ return;
+
+ if (!CGF.hasAggregateLLVMType(T)) {
+ // For non-aggregates, we can store zero
+ llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T));
+ CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T);
+ } else {
+ // There's a potential optimization opportunity in combining
+ // memsets; that would be easy for arrays, but relatively
+ // difficult for structures with the current code.
+ CGF.EmitNullInitialization(LV.getAddress(), T);
+ }
+}
+
+void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
+#if 0
+ // FIXME: Assess perf here? Figure out what cases are worth optimizing here
+ // (Length of globals? Chunks of zeroed-out space?).
+ //
+ // If we can, prefer a copy from a global; this is a lot less code for long
+ // globals, and it's easier for the current optimizers to analyze.
+ if (llvm::Constant* C = CGF.CGM.EmitConstantExpr(E, E->getType(), &CGF)) {
+ llvm::GlobalVariable* GV =
+ new llvm::GlobalVariable(CGF.CGM.getModule(), C->getType(), true,
+ llvm::GlobalValue::InternalLinkage, C, "");
+ EmitFinalDestCopy(E, CGF.MakeAddrLValue(GV, E->getType()));
+ return;
+ }
+#endif
+ if (E->hadArrayRangeDesignator())
+ CGF.ErrorUnsupported(E, "GNU array range designator extension");
+
+ llvm::Value *DestPtr = Dest.getAddr();
+
+ // Handle initialization of an array.
+ if (E->getType()->isArrayType()) {
+ const llvm::PointerType *APType =
+ cast<llvm::PointerType>(DestPtr->getType());
+ const llvm::ArrayType *AType =
+ cast<llvm::ArrayType>(APType->getElementType());
+
+ uint64_t NumInitElements = E->getNumInits();
+
+ if (E->getNumInits() > 0) {
+ QualType T1 = E->getType();
+ QualType T2 = E->getInit(0)->getType();
+ if (CGF.getContext().hasSameUnqualifiedType(T1, T2)) {
+ EmitAggLoadOfLValue(E->getInit(0));
+ return;
+ }
+ }
+
+ uint64_t NumArrayElements = AType->getNumElements();
+ QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
+ ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
+
+ // FIXME: were we intentionally ignoring address spaces and GC attributes?
+
+ for (uint64_t i = 0; i != NumArrayElements; ++i) {
+ // If we're done emitting initializers and the destination is known-zeroed
+ // then we're done.
+ if (i == NumInitElements &&
+ Dest.isZeroed() &&
+ CGF.getTypes().isZeroInitializable(ElementType))
+ break;
+
+ llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
+ LValue LV = CGF.MakeAddrLValue(NextVal, ElementType);
+
+ if (i < NumInitElements)
+ EmitInitializationToLValue(E->getInit(i), LV, ElementType);
+ else
+ EmitNullInitializationToLValue(LV, ElementType);
+
+ // If the GEP didn't get used because of a dead zero init or something
+ // else, clean it up for -O0 builds and general tidiness.
+ if (llvm::GetElementPtrInst *GEP =
+ dyn_cast<llvm::GetElementPtrInst>(NextVal))
+ if (GEP->use_empty())
+ GEP->eraseFromParent();
+ }
+ return;
+ }
+
+ assert(E->getType()->isRecordType() && "Only support structs/unions here!");
+
+ // Do struct initialization; this code just sets each individual member
+ // to the approprate value. This makes bitfield support automatic;
+ // the disadvantage is that the generated code is more difficult for
+ // the optimizer, especially with bitfields.
+ unsigned NumInitElements = E->getNumInits();
+ RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl();
+
+ if (E->getType()->isUnionType()) {
+ // Only initialize one field of a union. The field itself is
+ // specified by the initializer list.
+ if (!E->getInitializedFieldInUnion()) {
+ // Empty union; we have nothing to do.
+
+#ifndef NDEBUG
+ // Make sure that it's really an empty and not a failure of
+ // semantic analysis.
+ for (RecordDecl::field_iterator Field = SD->field_begin(),
+ FieldEnd = SD->field_end();
+ Field != FieldEnd; ++Field)
+ assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
+#endif
+ return;
+ }
+
+ // FIXME: volatility
+ FieldDecl *Field = E->getInitializedFieldInUnion();
+
+ LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, Field, 0);
+ if (NumInitElements) {
+ // Store the initializer into the field
+ EmitInitializationToLValue(E->getInit(0), FieldLoc, Field->getType());
+ } else {
+ // Default-initialize to null.
+ EmitNullInitializationToLValue(FieldLoc, Field->getType());
+ }
+
+ return;
+ }
+
+ // Here we iterate over the fields; this makes it simpler to both
+ // default-initialize fields and skip over unnamed fields.
+ unsigned CurInitVal = 0;
+ for (RecordDecl::field_iterator Field = SD->field_begin(),
+ FieldEnd = SD->field_end();
+ Field != FieldEnd; ++Field) {
+ // We're done once we hit the flexible array member
+ if (Field->getType()->isIncompleteArrayType())
+ break;
+
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ // Don't emit GEP before a noop store of zero.
+ if (CurInitVal == NumInitElements && Dest.isZeroed() &&
+ CGF.getTypes().isZeroInitializable(E->getType()))
+ break;
+
+ // FIXME: volatility
+ LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, *Field, 0);
+ // We never generate write-barries for initialized fields.
+ FieldLoc.setNonGC(true);
+
+ if (CurInitVal < NumInitElements) {
+ // Store the initializer into the field.
+ EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc,
+ Field->getType());
+ } else {
+ // We're out of initalizers; default-initialize to null
+ EmitNullInitializationToLValue(FieldLoc, Field->getType());
+ }
+
+ // If the GEP didn't get used because of a dead zero init or something
+ // else, clean it up for -O0 builds and general tidiness.
+ if (FieldLoc.isSimple())
+ if (llvm::GetElementPtrInst *GEP =
+ dyn_cast<llvm::GetElementPtrInst>(FieldLoc.getAddress()))
+ if (GEP->use_empty())
+ GEP->eraseFromParent();
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Entry Points into this File
+//===----------------------------------------------------------------------===//
+
+/// GetNumNonZeroBytesInInit - Get an approximate count of the number of
+/// non-zero bytes that will be stored when outputting the initializer for the
+/// specified initializer expression.
+static uint64_t GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ return GetNumNonZeroBytesInInit(PE->getSubExpr(), CGF);
+
+ // 0 and 0.0 won't require any non-zero stores!
+ if (isSimpleZero(E, CGF)) return 0;
+
+ // If this is an initlist expr, sum up the size of sizes of the (present)
+ // elements. If this is something weird, assume the whole thing is non-zero.
+ const InitListExpr *ILE = dyn_cast<InitListExpr>(E);
+ if (ILE == 0 || !CGF.getTypes().isZeroInitializable(ILE->getType()))
+ return CGF.getContext().getTypeSize(E->getType())/8;
+
+ // InitListExprs for structs have to be handled carefully. If there are
+ // reference members, we need to consider the size of the reference, not the
+ // referencee. InitListExprs for unions and arrays can't have references.
+ if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
+ if (!RT->isUnionType()) {
+ RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl();
+ uint64_t NumNonZeroBytes = 0;
+
+ unsigned ILEElement = 0;
+ for (RecordDecl::field_iterator Field = SD->field_begin(),
+ FieldEnd = SD->field_end(); Field != FieldEnd; ++Field) {
+ // We're done once we hit the flexible array member or run out of
+ // InitListExpr elements.
+ if (Field->getType()->isIncompleteArrayType() ||
+ ILEElement == ILE->getNumInits())
+ break;
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ const Expr *E = ILE->getInit(ILEElement++);
+
+ // Reference values are always non-null and have the width of a pointer.
+ if (Field->getType()->isReferenceType())
+ NumNonZeroBytes += CGF.getContext().Target.getPointerWidth(0);
+ else
+ NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF);
+ }
+
+ return NumNonZeroBytes;
+ }
+ }
+
+
+ uint64_t NumNonZeroBytes = 0;
+ for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)
+ NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF);
+ return NumNonZeroBytes;
+}
+
+/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of
+/// zeros in it, emit a memset and avoid storing the individual zeros.
+///
+static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
+ CodeGenFunction &CGF) {
+ // If the slot is already known to be zeroed, nothing to do. Don't mess with
+ // volatile stores.
+ if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return;
+
+ // If the type is 16-bytes or smaller, prefer individual stores over memset.
+ std::pair<uint64_t, unsigned> TypeInfo =
+ CGF.getContext().getTypeInfo(E->getType());
+ if (TypeInfo.first/8 <= 16)
+ return;
+
+ // Check to see if over 3/4 of the initializer are known to be zero. If so,
+ // we prefer to emit memset + individual stores for the rest.
+ uint64_t NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
+ if (NumNonZeroBytes*4 > TypeInfo.first/8)
+ return;
+
+ // Okay, it seems like a good idea to use an initial memset, emit the call.
+ llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first/8);
+ unsigned Align = TypeInfo.second/8;
+
+ llvm::Value *Loc = Slot.getAddr();
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+
+ Loc = CGF.Builder.CreateBitCast(Loc, BP);
+ CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, Align, false);
+
+ // Tell the AggExprEmitter that the slot is known zero.
+ Slot.setZeroed();
+}
+
+
+
+
+/// EmitAggExpr - Emit the computation of the specified expression of aggregate
+/// type. The result is computed into DestPtr. Note that if DestPtr is null,
+/// the value of the aggregate expression is not needed. If VolatileDest is
+/// true, DestPtr cannot be 0.
+///
+/// \param IsInitializer - true if this evaluation is initializing an
+/// object whose lifetime is already being managed.
+//
+// FIXME: Take Qualifiers object.
+void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot,
+ bool IgnoreResult) {
+ assert(E && hasAggregateLLVMType(E->getType()) &&
+ "Invalid aggregate expression to emit");
+ assert((Slot.getAddr() != 0 || Slot.isIgnored()) &&
+ "slot has bits but no address");
+
+ // Optimize the slot if possible.
+ CheckAggExprForMemSetUse(Slot, E, *this);
+
+ AggExprEmitter(*this, Slot, IgnoreResult).Visit(const_cast<Expr*>(E));
+}
+
+LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
+ assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!");
+ llvm::Value *Temp = CreateMemTemp(E->getType());
+ LValue LV = MakeAddrLValue(Temp, E->getType());
+ EmitAggExpr(E, AggValueSlot::forAddr(Temp, LV.isVolatileQualified(), false));
+ return LV;
+}
+
+void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
+ llvm::Value *SrcPtr, QualType Ty,
+ bool isVolatile) {
+ assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
+
+ if (getContext().getLangOptions().CPlusPlus) {
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
+ assert((Record->hasTrivialCopyConstructor() ||
+ Record->hasTrivialCopyAssignment()) &&
+ "Trying to aggregate-copy a type without a trivial copy "
+ "constructor or assignment operator");
+ // Ignore empty classes in C++.
+ if (Record->isEmpty())
+ return;
+ }
+ }
+
+ // Aggregate assignment turns into llvm.memcpy. This is almost valid per
+ // C99 6.5.16.1p3, which states "If the value being stored in an object is
+ // read from another object that overlaps in anyway the storage of the first
+ // object, then the overlap shall be exact and the two objects shall have
+ // qualified or unqualified versions of a compatible type."
+ //
+ // memcpy is not defined if the source and destination pointers are exactly
+ // equal, but other compilers do this optimization, and almost every memcpy
+ // implementation handles this case safely. If there is a libc that does not
+ // safely handle this, we can add a target hook.
+
+ // Get size and alignment info for this aggregate.
+ std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty);
+
+ // FIXME: Handle variable sized types.
+
+ // FIXME: If we have a volatile struct, the optimizer can remove what might
+ // appear to be `extra' memory ops:
+ //
+ // volatile struct { int i; } a, b;
+ //
+ // int main() {
+ // a = b;
+ // a = b;
+ // }
+ //
+ // we need to use a different call here. We use isVolatile to indicate when
+ // either the source or the destination is volatile.
+
+ const llvm::PointerType *DPT = cast<llvm::PointerType>(DestPtr->getType());
+ const llvm::Type *DBP =
+ llvm::Type::getInt8PtrTy(getLLVMContext(), DPT->getAddressSpace());
+ DestPtr = Builder.CreateBitCast(DestPtr, DBP, "tmp");
+
+ const llvm::PointerType *SPT = cast<llvm::PointerType>(SrcPtr->getType());
+ const llvm::Type *SBP =
+ llvm::Type::getInt8PtrTy(getLLVMContext(), SPT->getAddressSpace());
+ SrcPtr = Builder.CreateBitCast(SrcPtr, SBP, "tmp");
+
+ if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
+ RecordDecl *Record = RecordTy->getDecl();
+ if (Record->hasObjectMember()) {
+ unsigned long size = TypeInfo.first/8;
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size);
+ CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
+ SizeVal);
+ return;
+ }
+ } else if (getContext().getAsArrayType(Ty)) {
+ QualType BaseType = getContext().getBaseElementType(Ty);
+ if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
+ if (RecordTy->getDecl()->hasObjectMember()) {
+ unsigned long size = TypeInfo.first/8;
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+ llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size);
+ CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr,
+ SizeVal);
+ return;
+ }
+ }
+ }
+
+ Builder.CreateMemCpy(DestPtr, SrcPtr,
+ llvm::ConstantInt::get(IntPtrTy, TypeInfo.first/8),
+ TypeInfo.second/8, isVolatile);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
new file mode 100644
index 0000000..bba7864
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
@@ -0,0 +1,1478 @@
+//===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with code generation of C++ expressions
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CodeGenOptions.h"
+#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "CGDebugInfo.h"
+#include "llvm/Intrinsics.h"
+using namespace clang;
+using namespace CodeGen;
+
+RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
+ llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This,
+ llvm::Value *VTT,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd) {
+ assert(MD->isInstance() &&
+ "Trying to emit a member call expr on a static method!");
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+
+ CallArgList Args;
+
+ // Push the this ptr.
+ Args.push_back(std::make_pair(RValue::get(This),
+ MD->getThisType(getContext())));
+
+ // If there is a VTT parameter, emit it.
+ if (VTT) {
+ QualType T = getContext().getPointerType(getContext().VoidPtrTy);
+ Args.push_back(std::make_pair(RValue::get(VTT), T));
+ }
+
+ // And the rest of the call args
+ EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
+
+ QualType ResultType = FPT->getResultType();
+ return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
+ FPT->getExtInfo()),
+ Callee, ReturnValue, Args, MD);
+}
+
+static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) {
+ const Expr *E = Base;
+
+ while (true) {
+ E = E->IgnoreParens();
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase ||
+ CE->getCastKind() == CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ QualType DerivedType = E->getType();
+ if (const PointerType *PTy = DerivedType->getAs<PointerType>())
+ DerivedType = PTy->getPointeeType();
+
+ return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl());
+}
+
+/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
+/// expr can be devirtualized.
+static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
+ const Expr *Base,
+ const CXXMethodDecl *MD) {
+
+ // When building with -fapple-kext, all calls must go through the vtable since
+ // the kernel linker can do runtime patching of vtables.
+ if (Context.getLangOptions().AppleKext)
+ return false;
+
+ // If the most derived class is marked final, we know that no subclass can
+ // override this member function and so we can devirtualize it. For example:
+ //
+ // struct A { virtual void f(); }
+ // struct B final : A { };
+ //
+ // void f(B *b) {
+ // b->f();
+ // }
+ //
+ const CXXRecordDecl *MostDerivedClassDecl = getMostDerivedClassDecl(Base);
+ if (MostDerivedClassDecl->hasAttr<FinalAttr>())
+ return true;
+
+ // If the member function is marked 'final', we know that it can't be
+ // overridden and can therefore devirtualize it.
+ if (MD->hasAttr<FinalAttr>())
+ return true;
+
+ // Similarly, if the class itself is marked 'final' it can't be overridden
+ // and we can therefore devirtualize the member function call.
+ if (MD->getParent()->hasAttr<FinalAttr>())
+ return true;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ // This is a record decl. We know the type and can devirtualize it.
+ return VD->getType()->isRecordType();
+ }
+
+ return false;
+ }
+
+ // We can always devirtualize calls on temporary object expressions.
+ if (isa<CXXConstructExpr>(Base))
+ return true;
+
+ // And calls on bound temporaries.
+ if (isa<CXXBindTemporaryExpr>(Base))
+ return true;
+
+ // Check if this is a call expr that returns a record type.
+ if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
+ return CE->getCallReturnType()->isRecordType();
+
+ // We can't devirtualize the call.
+ return false;
+}
+
+// Note: This function also emit constructor calls to support a MSVC
+// extensions allowing explicit constructor function call.
+RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
+ ReturnValueSlot ReturnValue) {
+ if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens()))
+ return EmitCXXMemberPointerCallExpr(CE, ReturnValue);
+
+ const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens());
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI && CGM.getCodeGenOpts().LimitDebugInfo
+ && !isa<CallExpr>(ME->getBase())) {
+ QualType PQTy = ME->getBase()->IgnoreParenImpCasts()->getType();
+ if (const PointerType * PTy = dyn_cast<PointerType>(PQTy)) {
+ DI->getOrCreateRecordType(PTy->getPointeeType(),
+ MD->getParent()->getLocation());
+ }
+ }
+
+ if (MD->isStatic()) {
+ // The method is static, emit it as we would a regular call.
+ llvm::Value *Callee = CGM.GetAddrOfFunction(MD);
+ return EmitCall(getContext().getPointerType(MD->getType()), Callee,
+ ReturnValue, CE->arg_begin(), CE->arg_end());
+ }
+
+ // Compute the object pointer.
+ llvm::Value *This;
+ if (ME->isArrow())
+ This = EmitScalarExpr(ME->getBase());
+ else
+ This = EmitLValue(ME->getBase()).getAddress();
+
+ if (MD->isTrivial()) {
+ if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
+ if (isa<CXXConstructorDecl>(MD) &&
+ cast<CXXConstructorDecl>(MD)->isDefaultConstructor())
+ return RValue::get(0);
+
+ if (MD->isCopyAssignmentOperator()) {
+ // We don't like to generate the trivial copy assignment operator when
+ // it isn't necessary; just produce the proper effect here.
+ llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
+ EmitAggregateCopy(This, RHS, CE->getType());
+ return RValue::get(This);
+ }
+
+ if (isa<CXXConstructorDecl>(MD) &&
+ cast<CXXConstructorDecl>(MD)->isCopyConstructor()) {
+ llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
+ EmitSynthesizedCXXCopyCtorCall(cast<CXXConstructorDecl>(MD), This, RHS,
+ CE->arg_begin(), CE->arg_end());
+ return RValue::get(This);
+ }
+ llvm_unreachable("unknown trivial member function");
+ }
+
+ // Compute the function type we're calling.
+ const CGFunctionInfo *FInfo = 0;
+ if (isa<CXXDestructorDecl>(MD))
+ FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
+ Dtor_Complete);
+ else if (isa<CXXConstructorDecl>(MD))
+ FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXConstructorDecl>(MD),
+ Ctor_Complete);
+ else
+ FInfo = &CGM.getTypes().getFunctionInfo(MD);
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty
+ = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic());
+
+ // C++ [class.virtual]p12:
+ // Explicit qualification with the scope operator (5.1) suppresses the
+ // virtual call mechanism.
+ //
+ // We also don't emit a virtual call if the base expression has a record type
+ // because then we know what the type is.
+ bool UseVirtualCall;
+ UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
+ && !canDevirtualizeMemberFunctionCalls(getContext(),
+ ME->getBase(), MD);
+ llvm::Value *Callee;
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (UseVirtualCall) {
+ Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty);
+ } else {
+ if (getContext().getLangOptions().AppleKext &&
+ MD->isVirtual() &&
+ ME->hasQualifier())
+ Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
+ else
+ Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
+ }
+ } else if (const CXXConstructorDecl *Ctor =
+ dyn_cast<CXXConstructorDecl>(MD)) {
+ Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
+ } else if (UseVirtualCall) {
+ Callee = BuildVirtualCall(MD, This, Ty);
+ } else {
+ if (getContext().getLangOptions().AppleKext &&
+ MD->isVirtual() &&
+ ME->hasQualifier())
+ Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
+ else
+ Callee = CGM.GetAddrOfFunction(MD, Ty);
+ }
+
+ return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
+ CE->arg_begin(), CE->arg_end());
+}
+
+RValue
+CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
+ ReturnValueSlot ReturnValue) {
+ const BinaryOperator *BO =
+ cast<BinaryOperator>(E->getCallee()->IgnoreParens());
+ const Expr *BaseExpr = BO->getLHS();
+ const Expr *MemFnExpr = BO->getRHS();
+
+ const MemberPointerType *MPT =
+ MemFnExpr->getType()->getAs<MemberPointerType>();
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+
+ // Get the member function pointer.
+ llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
+
+ // Emit the 'this' pointer.
+ llvm::Value *This;
+
+ if (BO->getOpcode() == BO_PtrMemI)
+ This = EmitScalarExpr(BaseExpr);
+ else
+ This = EmitLValue(BaseExpr).getAddress();
+
+ // Ask the ABI to load the callee. Note that This is modified.
+ llvm::Value *Callee =
+ CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, This, MemFnPtr, MPT);
+
+ CallArgList Args;
+
+ QualType ThisType =
+ getContext().getPointerType(getContext().getTagDeclType(RD));
+
+ // Push the this ptr.
+ Args.push_back(std::make_pair(RValue::get(This), ThisType));
+
+ // And the rest of the call args
+ EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end());
+ const FunctionType *BO_FPT = BO->getType()->getAs<FunctionProtoType>();
+ return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee,
+ ReturnValue, Args);
+}
+
+RValue
+CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
+ const CXXMethodDecl *MD,
+ ReturnValueSlot ReturnValue) {
+ assert(MD->isInstance() &&
+ "Trying to emit a member call expr on a static method!");
+ LValue LV = EmitLValue(E->getArg(0));
+ llvm::Value *This = LV.getAddress();
+
+ if (MD->isCopyAssignmentOperator()) {
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext());
+ if (ClassDecl->hasTrivialCopyAssignment()) {
+ assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
+ "EmitCXXOperatorMemberCallExpr - user declared copy assignment");
+ llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress();
+ QualType Ty = E->getType();
+ EmitAggregateCopy(This, Src, Ty);
+ return RValue::get(This);
+ }
+ }
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ FPT->isVariadic());
+ llvm::Value *Callee;
+ if (MD->isVirtual() &&
+ !canDevirtualizeMemberFunctionCalls(getContext(),
+ E->getArg(0), MD))
+ Callee = BuildVirtualCall(MD, This, Ty);
+ else
+ Callee = CGM.GetAddrOfFunction(MD, Ty);
+
+ return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
+ E->arg_begin() + 1, E->arg_end());
+}
+
+void
+CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
+ AggValueSlot Dest) {
+ assert(!Dest.isIgnored() && "Must have a destination!");
+ const CXXConstructorDecl *CD = E->getConstructor();
+
+ // If we require zero initialization before (or instead of) calling the
+ // constructor, as can be the case with a non-user-provided default
+ // constructor, emit the zero initialization now.
+ if (E->requiresZeroInitialization())
+ EmitNullInitialization(Dest.getAddr(), E->getType());
+
+ // If this is a call to a trivial default constructor, do nothing.
+ if (CD->isTrivial() && CD->isDefaultConstructor())
+ return;
+
+ // Elide the constructor if we're constructing from a temporary.
+ // The temporary check is required because Sema sets this on NRVO
+ // returns.
+ if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
+ assert(getContext().hasSameUnqualifiedType(E->getType(),
+ E->getArg(0)->getType()));
+ if (E->getArg(0)->isTemporaryObject(getContext(), CD->getParent())) {
+ EmitAggExpr(E->getArg(0), Dest);
+ return;
+ }
+ }
+
+ const ConstantArrayType *Array
+ = getContext().getAsConstantArrayType(E->getType());
+ if (Array) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(Dest.getAddr(), BasePtr);
+
+ EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr,
+ E->arg_begin(), E->arg_end());
+ }
+ else {
+ CXXCtorType Type =
+ (E->getConstructionKind() == CXXConstructExpr::CK_Complete)
+ ? Ctor_Complete : Ctor_Base;
+ bool ForVirtualBase =
+ E->getConstructionKind() == CXXConstructExpr::CK_VirtualBase;
+
+ // Call the constructor.
+ EmitCXXConstructorCall(CD, Type, ForVirtualBase, Dest.getAddr(),
+ E->arg_begin(), E->arg_end());
+ }
+}
+
+void
+CodeGenFunction::EmitSynthesizedCXXCopyCtor(llvm::Value *Dest,
+ llvm::Value *Src,
+ const Expr *Exp) {
+ if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(Exp))
+ Exp = E->getSubExpr();
+ assert(isa<CXXConstructExpr>(Exp) &&
+ "EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");
+ const CXXConstructExpr* E = cast<CXXConstructExpr>(Exp);
+ const CXXConstructorDecl *CD = E->getConstructor();
+ RunCleanupsScope Scope(*this);
+
+ // If we require zero initialization before (or instead of) calling the
+ // constructor, as can be the case with a non-user-provided default
+ // constructor, emit the zero initialization now.
+ // FIXME. Do I still need this for a copy ctor synthesis?
+ if (E->requiresZeroInitialization())
+ EmitNullInitialization(Dest, E->getType());
+
+ assert(!getContext().getAsConstantArrayType(E->getType())
+ && "EmitSynthesizedCXXCopyCtor - Copied-in Array");
+ EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src,
+ E->arg_begin(), E->arg_end());
+}
+
+/// Check whether the given operator new[] is the global placement
+/// operator new[].
+static bool IsPlacementOperatorNewArray(ASTContext &Ctx,
+ const FunctionDecl *Fn) {
+ // Must be in global scope. Note that allocation functions can't be
+ // declared in namespaces.
+ if (!Fn->getDeclContext()->getRedeclContext()->isFileContext())
+ return false;
+
+ // Signature must be void *operator new[](size_t, void*).
+ // The size_t is common to all operator new[]s.
+ if (Fn->getNumParams() != 2)
+ return false;
+
+ CanQualType ParamType = Ctx.getCanonicalType(Fn->getParamDecl(1)->getType());
+ return (ParamType == Ctx.VoidPtrTy);
+}
+
+static CharUnits CalculateCookiePadding(CodeGenFunction &CGF,
+ const CXXNewExpr *E) {
+ if (!E->isArray())
+ return CharUnits::Zero();
+
+ // No cookie is required if the new operator being used is
+ // ::operator new[](size_t, void*).
+ const FunctionDecl *OperatorNew = E->getOperatorNew();
+ if (IsPlacementOperatorNewArray(CGF.getContext(), OperatorNew))
+ return CharUnits::Zero();
+
+ return CGF.CGM.getCXXABI().GetArrayCookieSize(E);
+}
+
+static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
+ CodeGenFunction &CGF,
+ const CXXNewExpr *E,
+ llvm::Value *&NumElements,
+ llvm::Value *&SizeWithoutCookie) {
+ QualType ElemType = E->getAllocatedType();
+
+ const llvm::IntegerType *SizeTy =
+ cast<llvm::IntegerType>(CGF.ConvertType(CGF.getContext().getSizeType()));
+
+ CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(ElemType);
+
+ if (!E->isArray()) {
+ SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+ return SizeWithoutCookie;
+ }
+
+ // Figure out the cookie size.
+ CharUnits CookieSize = CalculateCookiePadding(CGF, E);
+
+ // Emit the array size expression.
+ // We multiply the size of all dimensions for NumElements.
+ // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
+ NumElements = CGF.EmitScalarExpr(E->getArraySize());
+ assert(NumElements->getType() == SizeTy && "element count not a size_t");
+
+ uint64_t ArraySizeMultiplier = 1;
+ while (const ConstantArrayType *CAT
+ = CGF.getContext().getAsConstantArrayType(ElemType)) {
+ ElemType = CAT->getElementType();
+ ArraySizeMultiplier *= CAT->getSize().getZExtValue();
+ }
+
+ llvm::Value *Size;
+
+ // If someone is doing 'new int[42]' there is no need to do a dynamic check.
+ // Don't bloat the -O0 code.
+ if (llvm::ConstantInt *NumElementsC =
+ dyn_cast<llvm::ConstantInt>(NumElements)) {
+ llvm::APInt NEC = NumElementsC->getValue();
+ unsigned SizeWidth = NEC.getBitWidth();
+
+ // Determine if there is an overflow here by doing an extended multiply.
+ NEC = NEC.zext(SizeWidth*2);
+ llvm::APInt SC(SizeWidth*2, TypeSize.getQuantity());
+ SC *= NEC;
+
+ if (!CookieSize.isZero()) {
+ // Save the current size without a cookie. We don't care if an
+ // overflow's already happened because SizeWithoutCookie isn't
+ // used if the allocator returns null or throws, as it should
+ // always do on an overflow.
+ llvm::APInt SWC = SC.trunc(SizeWidth);
+ SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, SWC);
+
+ // Add the cookie size.
+ SC += llvm::APInt(SizeWidth*2, CookieSize.getQuantity());
+ }
+
+ if (SC.countLeadingZeros() >= SizeWidth) {
+ SC = SC.trunc(SizeWidth);
+ Size = llvm::ConstantInt::get(SizeTy, SC);
+ } else {
+ // On overflow, produce a -1 so operator new throws.
+ Size = llvm::Constant::getAllOnesValue(SizeTy);
+ }
+
+ // Scale NumElements while we're at it.
+ uint64_t N = NEC.getZExtValue() * ArraySizeMultiplier;
+ NumElements = llvm::ConstantInt::get(SizeTy, N);
+
+ // Otherwise, we don't need to do an overflow-checked multiplication if
+ // we're multiplying by one.
+ } else if (TypeSize.isOne()) {
+ assert(ArraySizeMultiplier == 1);
+
+ Size = NumElements;
+
+ // If we need a cookie, add its size in with an overflow check.
+ // This is maybe a little paranoid.
+ if (!CookieSize.isZero()) {
+ SizeWithoutCookie = Size;
+
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+
+ const llvm::Type *Types[] = { SizeTy };
+ llvm::Value *UAddF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, Types, 1);
+ llvm::Value *AddRes
+ = CGF.Builder.CreateCall2(UAddF, Size, CookieSizeV);
+
+ Size = CGF.Builder.CreateExtractValue(AddRes, 0);
+ llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(AddRes, 1);
+ Size = CGF.Builder.CreateSelect(DidOverflow,
+ llvm::ConstantInt::get(SizeTy, -1),
+ Size);
+ }
+
+ // Otherwise use the int.umul.with.overflow intrinsic.
+ } else {
+ llvm::Value *OutermostElementSize
+ = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+
+ llvm::Value *NumOutermostElements = NumElements;
+
+ // Scale NumElements by the array size multiplier. This might
+ // overflow, but only if the multiplication below also overflows,
+ // in which case this multiplication isn't used.
+ if (ArraySizeMultiplier != 1)
+ NumElements = CGF.Builder.CreateMul(NumElements,
+ llvm::ConstantInt::get(SizeTy, ArraySizeMultiplier));
+
+ // The requested size of the outermost array is non-constant.
+ // Multiply that by the static size of the elements of that array;
+ // on unsigned overflow, set the size to -1 to trigger an
+ // exception from the allocation routine. This is sufficient to
+ // prevent buffer overruns from the allocator returning a
+ // seemingly valid pointer to insufficient space. This idea comes
+ // originally from MSVC, and GCC has an open bug requesting
+ // similar behavior:
+ // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19351
+ //
+ // This will not be sufficient for C++0x, which requires a
+ // specific exception class (std::bad_array_new_length).
+ // That will require ABI support that has not yet been specified.
+ const llvm::Type *Types[] = { SizeTy };
+ llvm::Value *UMulF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, Types, 1);
+ llvm::Value *MulRes = CGF.Builder.CreateCall2(UMulF, NumOutermostElements,
+ OutermostElementSize);
+
+ // The overflow bit.
+ llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(MulRes, 1);
+
+ // The result of the multiplication.
+ Size = CGF.Builder.CreateExtractValue(MulRes, 0);
+
+ // If we have a cookie, we need to add that size in, too.
+ if (!CookieSize.isZero()) {
+ SizeWithoutCookie = Size;
+
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+ llvm::Value *UAddF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, Types, 1);
+ llvm::Value *AddRes
+ = CGF.Builder.CreateCall2(UAddF, SizeWithoutCookie, CookieSizeV);
+
+ Size = CGF.Builder.CreateExtractValue(AddRes, 0);
+
+ llvm::Value *AddDidOverflow = CGF.Builder.CreateExtractValue(AddRes, 1);
+ DidOverflow = CGF.Builder.CreateAnd(DidOverflow, AddDidOverflow);
+ }
+
+ Size = CGF.Builder.CreateSelect(DidOverflow,
+ llvm::ConstantInt::get(SizeTy, -1),
+ Size);
+ }
+
+ if (CookieSize.isZero())
+ SizeWithoutCookie = Size;
+ else
+ assert(SizeWithoutCookie && "didn't set SizeWithoutCookie?");
+
+ return Size;
+}
+
+static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
+ llvm::Value *NewPtr) {
+
+ assert(E->getNumConstructorArgs() == 1 &&
+ "Can only have one argument to initializer of POD type.");
+
+ const Expr *Init = E->getConstructorArg(0);
+ QualType AllocType = E->getAllocatedType();
+
+ unsigned Alignment =
+ CGF.getContext().getTypeAlignInChars(AllocType).getQuantity();
+ if (!CGF.hasAggregateLLVMType(AllocType))
+ CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
+ AllocType.isVolatileQualified(), Alignment,
+ AllocType);
+ else if (AllocType->isAnyComplexType())
+ CGF.EmitComplexExprIntoAddr(Init, NewPtr,
+ AllocType.isVolatileQualified());
+ else {
+ AggValueSlot Slot
+ = AggValueSlot::forAddr(NewPtr, AllocType.isVolatileQualified(), true);
+ CGF.EmitAggExpr(Init, Slot);
+ }
+}
+
+void
+CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements) {
+ // We have a POD type.
+ if (E->getNumConstructorArgs() == 0)
+ return;
+
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+
+ // Create a temporary for the loop index and initialize it with 0.
+ llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index");
+ llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
+ Builder.CreateStore(Zero, IndexPtr);
+
+ // Start the loop with a block that tests the condition.
+ llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
+ llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
+
+ EmitBlock(CondBlock);
+
+ llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+
+ // Generate: if (loop-index < number-of-elements fall to the loop body,
+ // otherwise, go to the block after the for-loop.
+ llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless");
+ // If the condition is true, execute the body.
+ Builder.CreateCondBr(IsLess, ForBody, AfterFor);
+
+ EmitBlock(ForBody);
+
+ llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
+ // Inside the loop body, emit the constructor call on the array element.
+ Counter = Builder.CreateLoad(IndexPtr);
+ llvm::Value *Address = Builder.CreateInBoundsGEP(NewPtr, Counter,
+ "arrayidx");
+ StoreAnyExprIntoOneUnit(*this, E, Address);
+
+ EmitBlock(ContinueBlock);
+
+ // Emit the increment of the loop counter.
+ llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1);
+ Counter = Builder.CreateLoad(IndexPtr);
+ NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
+ Builder.CreateStore(NextVal, IndexPtr);
+
+ // Finally, branch back up to the condition for the next iteration.
+ EmitBranch(CondBlock);
+
+ // Emit the fall-through block.
+ EmitBlock(AfterFor, true);
+}
+
+static void EmitZeroMemSet(CodeGenFunction &CGF, QualType T,
+ llvm::Value *NewPtr, llvm::Value *Size) {
+ CGF.EmitCastToVoidPtr(NewPtr);
+ CharUnits Alignment = CGF.getContext().getTypeAlignInChars(T);
+ CGF.Builder.CreateMemSet(NewPtr, CGF.Builder.getInt8(0), Size,
+ Alignment.getQuantity(), false);
+}
+
+static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
+ if (E->isArray()) {
+ if (CXXConstructorDecl *Ctor = E->getConstructor()) {
+ bool RequiresZeroInitialization = false;
+ if (Ctor->getParent()->hasTrivialConstructor()) {
+ // If new expression did not specify value-initialization, then there
+ // is no initialization.
+ if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
+ return;
+
+ if (CGF.CGM.getTypes().isZeroInitializable(E->getAllocatedType())) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ }
+
+ RequiresZeroInitialization = true;
+ }
+
+ CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
+ E->constructor_arg_begin(),
+ E->constructor_arg_end(),
+ RequiresZeroInitialization);
+ return;
+ } else if (E->getNumConstructorArgs() == 1 &&
+ isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ } else {
+ CGF.EmitNewArrayInitializer(E, NewPtr, NumElements);
+ return;
+ }
+ }
+
+ if (CXXConstructorDecl *Ctor = E->getConstructor()) {
+ // Per C++ [expr.new]p15, if we have an initializer, then we're performing
+ // direct initialization. C++ [dcl.init]p5 requires that we
+ // zero-initialize storage if there are no user-declared constructors.
+ if (E->hasInitializer() &&
+ !Ctor->getParent()->hasUserDeclaredConstructor() &&
+ !Ctor->getParent()->isEmpty())
+ CGF.EmitNullInitialization(NewPtr, E->getAllocatedType());
+
+ CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,
+ NewPtr, E->constructor_arg_begin(),
+ E->constructor_arg_end());
+
+ return;
+ }
+ // We have a POD type.
+ if (E->getNumConstructorArgs() == 0)
+ return;
+
+ StoreAnyExprIntoOneUnit(CGF, E, NewPtr);
+}
+
+namespace {
+ /// A cleanup to call the given 'operator delete' function upon
+ /// abnormal exit from a new expression.
+ class CallDeleteDuringNew : public EHScopeStack::Cleanup {
+ size_t NumPlacementArgs;
+ const FunctionDecl *OperatorDelete;
+ llvm::Value *Ptr;
+ llvm::Value *AllocSize;
+
+ RValue *getPlacementArgs() { return reinterpret_cast<RValue*>(this+1); }
+
+ public:
+ static size_t getExtraSize(size_t NumPlacementArgs) {
+ return NumPlacementArgs * sizeof(RValue);
+ }
+
+ CallDeleteDuringNew(size_t NumPlacementArgs,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr,
+ llvm::Value *AllocSize)
+ : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete),
+ Ptr(Ptr), AllocSize(AllocSize) {}
+
+ void setPlacementArg(unsigned I, RValue Arg) {
+ assert(I < NumPlacementArgs && "index out of range");
+ getPlacementArgs()[I] = Arg;
+ }
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const FunctionProtoType *FPT
+ = OperatorDelete->getType()->getAs<FunctionProtoType>();
+ assert(FPT->getNumArgs() == NumPlacementArgs + 1 ||
+ (FPT->getNumArgs() == 2 && NumPlacementArgs == 0));
+
+ CallArgList DeleteArgs;
+
+ // The first argument is always a void*.
+ FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin();
+ DeleteArgs.push_back(std::make_pair(RValue::get(Ptr), *AI++));
+
+ // A member 'operator delete' can take an extra 'size_t' argument.
+ if (FPT->getNumArgs() == NumPlacementArgs + 2)
+ DeleteArgs.push_back(std::make_pair(RValue::get(AllocSize), *AI++));
+
+ // Pass the rest of the arguments, which must match exactly.
+ for (unsigned I = 0; I != NumPlacementArgs; ++I)
+ DeleteArgs.push_back(std::make_pair(getPlacementArgs()[I], *AI++));
+
+ // Call 'operator delete'.
+ CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT),
+ CGF.CGM.GetAddrOfFunction(OperatorDelete),
+ ReturnValueSlot(), DeleteArgs, OperatorDelete);
+ }
+ };
+
+ /// A cleanup to call the given 'operator delete' function upon
+ /// abnormal exit from a new expression when the new expression is
+ /// conditional.
+ class CallDeleteDuringConditionalNew : public EHScopeStack::Cleanup {
+ size_t NumPlacementArgs;
+ const FunctionDecl *OperatorDelete;
+ DominatingValue<RValue>::saved_type Ptr;
+ DominatingValue<RValue>::saved_type AllocSize;
+
+ DominatingValue<RValue>::saved_type *getPlacementArgs() {
+ return reinterpret_cast<DominatingValue<RValue>::saved_type*>(this+1);
+ }
+
+ public:
+ static size_t getExtraSize(size_t NumPlacementArgs) {
+ return NumPlacementArgs * sizeof(DominatingValue<RValue>::saved_type);
+ }
+
+ CallDeleteDuringConditionalNew(size_t NumPlacementArgs,
+ const FunctionDecl *OperatorDelete,
+ DominatingValue<RValue>::saved_type Ptr,
+ DominatingValue<RValue>::saved_type AllocSize)
+ : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete),
+ Ptr(Ptr), AllocSize(AllocSize) {}
+
+ void setPlacementArg(unsigned I, DominatingValue<RValue>::saved_type Arg) {
+ assert(I < NumPlacementArgs && "index out of range");
+ getPlacementArgs()[I] = Arg;
+ }
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const FunctionProtoType *FPT
+ = OperatorDelete->getType()->getAs<FunctionProtoType>();
+ assert(FPT->getNumArgs() == NumPlacementArgs + 1 ||
+ (FPT->getNumArgs() == 2 && NumPlacementArgs == 0));
+
+ CallArgList DeleteArgs;
+
+ // The first argument is always a void*.
+ FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin();
+ DeleteArgs.push_back(std::make_pair(Ptr.restore(CGF), *AI++));
+
+ // A member 'operator delete' can take an extra 'size_t' argument.
+ if (FPT->getNumArgs() == NumPlacementArgs + 2) {
+ RValue RV = AllocSize.restore(CGF);
+ DeleteArgs.push_back(std::make_pair(RV, *AI++));
+ }
+
+ // Pass the rest of the arguments, which must match exactly.
+ for (unsigned I = 0; I != NumPlacementArgs; ++I) {
+ RValue RV = getPlacementArgs()[I].restore(CGF);
+ DeleteArgs.push_back(std::make_pair(RV, *AI++));
+ }
+
+ // Call 'operator delete'.
+ CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT),
+ CGF.CGM.GetAddrOfFunction(OperatorDelete),
+ ReturnValueSlot(), DeleteArgs, OperatorDelete);
+ }
+ };
+}
+
+/// Enter a cleanup to call 'operator delete' if the initializer in a
+/// new-expression throws.
+static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
+ const CXXNewExpr *E,
+ llvm::Value *NewPtr,
+ llvm::Value *AllocSize,
+ const CallArgList &NewArgs) {
+ // If we're not inside a conditional branch, then the cleanup will
+ // dominate and we can do the easier (and more efficient) thing.
+ if (!CGF.isInConditionalBranch()) {
+ CallDeleteDuringNew *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<CallDeleteDuringNew>(EHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ NewPtr, AllocSize);
+ for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
+ Cleanup->setPlacementArg(I, NewArgs[I+1].first);
+
+ return;
+ }
+
+ // Otherwise, we need to save all this stuff.
+ DominatingValue<RValue>::saved_type SavedNewPtr =
+ DominatingValue<RValue>::save(CGF, RValue::get(NewPtr));
+ DominatingValue<RValue>::saved_type SavedAllocSize =
+ DominatingValue<RValue>::save(CGF, RValue::get(AllocSize));
+
+ CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(InactiveEHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ SavedNewPtr,
+ SavedAllocSize);
+ for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
+ Cleanup->setPlacementArg(I,
+ DominatingValue<RValue>::save(CGF, NewArgs[I+1].first));
+
+ CGF.ActivateCleanupBlock(CGF.EHStack.stable_begin());
+}
+
+llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
+ QualType AllocType = E->getAllocatedType();
+ if (AllocType->isArrayType())
+ while (const ArrayType *AType = getContext().getAsArrayType(AllocType))
+ AllocType = AType->getElementType();
+
+ FunctionDecl *NewFD = E->getOperatorNew();
+ const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
+
+ CallArgList NewArgs;
+
+ // The allocation size is the first argument.
+ QualType SizeTy = getContext().getSizeType();
+
+ llvm::Value *NumElements = 0;
+ llvm::Value *AllocSizeWithoutCookie = 0;
+ llvm::Value *AllocSize = EmitCXXNewAllocSize(getContext(),
+ *this, E, NumElements,
+ AllocSizeWithoutCookie);
+
+ NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
+
+ // Emit the rest of the arguments.
+ // FIXME: Ideally, this should just use EmitCallArgs.
+ CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
+
+ // First, use the types from the function type.
+ // We start at 1 here because the first argument (the allocation size)
+ // has already been emitted.
+ for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
+ QualType ArgType = NewFTy->getArgType(i);
+
+ assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
+ getTypePtr() ==
+ getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
+ "type mismatch in call argument!");
+
+ NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
+ ArgType));
+
+ }
+
+ // Either we've emitted all the call args, or we have a call to a
+ // variadic function.
+ assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
+ "Extra arguments in non-variadic function!");
+
+ // If we still have any arguments, emit them using the type of the argument.
+ for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
+ NewArg != NewArgEnd; ++NewArg) {
+ QualType ArgType = NewArg->getType();
+ NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
+ ArgType));
+ }
+
+ // Emit the call to new.
+ RValue RV =
+ EmitCall(CGM.getTypes().getFunctionInfo(NewArgs, NewFTy),
+ CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD);
+
+ // If an allocation function is declared with an empty exception specification
+ // it returns null to indicate failure to allocate storage. [expr.new]p13.
+ // (We don't need to check for null when there's no new initializer and
+ // we're allocating a POD type).
+ bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
+ !(AllocType->isPODType() && !E->hasInitializer());
+
+ llvm::BasicBlock *NullCheckSource = 0;
+ llvm::BasicBlock *NewNotNull = 0;
+ llvm::BasicBlock *NewEnd = 0;
+
+ llvm::Value *NewPtr = RV.getScalarVal();
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
+
+ if (NullCheckResult) {
+ NullCheckSource = Builder.GetInsertBlock();
+ NewNotNull = createBasicBlock("new.notnull");
+ NewEnd = createBasicBlock("new.end");
+
+ llvm::Value *IsNull = Builder.CreateIsNull(NewPtr, "new.isnull");
+ Builder.CreateCondBr(IsNull, NewEnd, NewNotNull);
+ EmitBlock(NewNotNull);
+ }
+
+ assert((AllocSize == AllocSizeWithoutCookie) ==
+ CalculateCookiePadding(*this, E).isZero());
+ if (AllocSize != AllocSizeWithoutCookie) {
+ assert(E->isArray());
+ NewPtr = CGM.getCXXABI().InitializeArrayCookie(*this, NewPtr, NumElements,
+ E, AllocType);
+ }
+
+ // If there's an operator delete, enter a cleanup to call it if an
+ // exception is thrown.
+ EHScopeStack::stable_iterator CallOperatorDelete;
+ if (E->getOperatorDelete()) {
+ EnterNewDeleteCleanup(*this, E, NewPtr, AllocSize, NewArgs);
+ CallOperatorDelete = EHStack.stable_begin();
+ }
+
+ const llvm::Type *ElementPtrTy
+ = ConvertTypeForMem(AllocType)->getPointerTo(AS);
+ NewPtr = Builder.CreateBitCast(NewPtr, ElementPtrTy);
+
+ if (E->isArray()) {
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
+
+ // NewPtr is a pointer to the base element type. If we're
+ // allocating an array of arrays, we'll need to cast back to the
+ // array pointer type.
+ const llvm::Type *ResultTy = ConvertTypeForMem(E->getType());
+ if (NewPtr->getType() != ResultTy)
+ NewPtr = Builder.CreateBitCast(NewPtr, ResultTy);
+ } else {
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
+ }
+
+ // Deactivate the 'operator delete' cleanup if we finished
+ // initialization.
+ if (CallOperatorDelete.isValid())
+ DeactivateCleanupBlock(CallOperatorDelete);
+
+ if (NullCheckResult) {
+ Builder.CreateBr(NewEnd);
+ llvm::BasicBlock *NotNullSource = Builder.GetInsertBlock();
+ EmitBlock(NewEnd);
+
+ llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(NewPtr, NotNullSource);
+ PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()),
+ NullCheckSource);
+
+ NewPtr = PHI;
+ }
+
+ return NewPtr;
+}
+
+void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
+ llvm::Value *Ptr,
+ QualType DeleteTy) {
+ assert(DeleteFD->getOverloadedOperator() == OO_Delete);
+
+ const FunctionProtoType *DeleteFTy =
+ DeleteFD->getType()->getAs<FunctionProtoType>();
+
+ CallArgList DeleteArgs;
+
+ // Check if we need to pass the size to the delete operator.
+ llvm::Value *Size = 0;
+ QualType SizeTy;
+ if (DeleteFTy->getNumArgs() == 2) {
+ SizeTy = DeleteFTy->getArgType(1);
+ CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy);
+ Size = llvm::ConstantInt::get(ConvertType(SizeTy),
+ DeleteTypeSize.getQuantity());
+ }
+
+ QualType ArgTy = DeleteFTy->getArgType(0);
+ llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
+ DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
+
+ if (Size)
+ DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
+
+ // Emit the call to delete.
+ EmitCall(CGM.getTypes().getFunctionInfo(DeleteArgs, DeleteFTy),
+ CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(),
+ DeleteArgs, DeleteFD);
+}
+
+namespace {
+ /// Calls the given 'operator delete' on a single object.
+ struct CallObjectDelete : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ QualType ElementType;
+
+ CallObjectDelete(llvm::Value *Ptr,
+ const FunctionDecl *OperatorDelete,
+ QualType ElementType)
+ : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);
+ }
+ };
+}
+
+/// Emit the code for deleting a single object.
+static void EmitObjectDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr,
+ QualType ElementType) {
+ // Find the destructor for the type, if applicable. If the
+ // destructor is virtual, we'll just emit the vcall and return.
+ const CXXDestructorDecl *Dtor = 0;
+ if (const RecordType *RT = ElementType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (!RD->hasTrivialDestructor()) {
+ Dtor = RD->getDestructor();
+
+ if (Dtor->isVirtual()) {
+ const llvm::Type *Ty =
+ CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
+ Dtor_Complete),
+ /*isVariadic=*/false);
+
+ llvm::Value *Callee
+ = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
+ CGF.EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
+ 0, 0);
+
+ // The dtor took care of deleting the object.
+ return;
+ }
+ }
+ }
+
+ // Make sure that we call delete even if the dtor throws.
+ // This doesn't have to a conditional cleanup because we're going
+ // to pop it off in a second.
+ CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
+ Ptr, OperatorDelete, ElementType);
+
+ if (Dtor)
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false, Ptr);
+
+ CGF.PopCleanupBlock();
+}
+
+namespace {
+ /// Calls the given 'operator delete' on an array of objects.
+ struct CallArrayDelete : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ llvm::Value *NumElements;
+ QualType ElementType;
+ CharUnits CookieSize;
+
+ CallArrayDelete(llvm::Value *Ptr,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *NumElements,
+ QualType ElementType,
+ CharUnits CookieSize)
+ : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),
+ ElementType(ElementType), CookieSize(CookieSize) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const FunctionProtoType *DeleteFTy =
+ OperatorDelete->getType()->getAs<FunctionProtoType>();
+ assert(DeleteFTy->getNumArgs() == 1 || DeleteFTy->getNumArgs() == 2);
+
+ CallArgList Args;
+
+ // Pass the pointer as the first argument.
+ QualType VoidPtrTy = DeleteFTy->getArgType(0);
+ llvm::Value *DeletePtr
+ = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy));
+ Args.push_back(std::make_pair(RValue::get(DeletePtr), VoidPtrTy));
+
+ // Pass the original requested size as the second argument.
+ if (DeleteFTy->getNumArgs() == 2) {
+ QualType size_t = DeleteFTy->getArgType(1);
+ const llvm::IntegerType *SizeTy
+ = cast<llvm::IntegerType>(CGF.ConvertType(size_t));
+
+ CharUnits ElementTypeSize =
+ CGF.CGM.getContext().getTypeSizeInChars(ElementType);
+
+ // The size of an element, multiplied by the number of elements.
+ llvm::Value *Size
+ = llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity());
+ Size = CGF.Builder.CreateMul(Size, NumElements);
+
+ // Plus the size of the cookie if applicable.
+ if (!CookieSize.isZero()) {
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+ Size = CGF.Builder.CreateAdd(Size, CookieSizeV);
+ }
+
+ Args.push_back(std::make_pair(RValue::get(Size), size_t));
+ }
+
+ // Emit the call to delete.
+ CGF.EmitCall(CGF.getTypes().getFunctionInfo(Args, DeleteFTy),
+ CGF.CGM.GetAddrOfFunction(OperatorDelete),
+ ReturnValueSlot(), Args, OperatorDelete);
+ }
+ };
+}
+
+/// Emit the code for deleting an array of objects.
+static void EmitArrayDelete(CodeGenFunction &CGF,
+ const CXXDeleteExpr *E,
+ llvm::Value *Ptr,
+ QualType ElementType) {
+ llvm::Value *NumElements = 0;
+ llvm::Value *AllocatedPtr = 0;
+ CharUnits CookieSize;
+ CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, E, ElementType,
+ NumElements, AllocatedPtr, CookieSize);
+
+ assert(AllocatedPtr && "ReadArrayCookie didn't set AllocatedPtr");
+
+ // Make sure that we call delete even if one of the dtors throws.
+ const FunctionDecl *OperatorDelete = E->getOperatorDelete();
+ CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup,
+ AllocatedPtr, OperatorDelete,
+ NumElements, ElementType,
+ CookieSize);
+
+ if (const CXXRecordDecl *RD = ElementType->getAsCXXRecordDecl()) {
+ if (!RD->hasTrivialDestructor()) {
+ assert(NumElements && "ReadArrayCookie didn't find element count"
+ " for a class with destructor");
+ CGF.EmitCXXAggrDestructorCall(RD->getDestructor(), NumElements, Ptr);
+ }
+ }
+
+ CGF.PopCleanupBlock();
+}
+
+void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
+
+ // Get at the argument before we performed the implicit conversion
+ // to void*.
+ const Expr *Arg = E->getArgument();
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ if (ICE->getCastKind() != CK_UserDefinedConversion &&
+ ICE->getType()->isVoidPointerType())
+ Arg = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ llvm::Value *Ptr = EmitScalarExpr(Arg);
+
+ // Null check the pointer.
+ llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
+ llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
+
+ llvm::Value *IsNull =
+ Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()),
+ "isnull");
+
+ Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
+ EmitBlock(DeleteNotNull);
+
+ // We might be deleting a pointer to array. If so, GEP down to the
+ // first non-array element.
+ // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*)
+ QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
+ if (DeleteTy->isConstantArrayType()) {
+ llvm::Value *Zero = Builder.getInt32(0);
+ llvm::SmallVector<llvm::Value*,8> GEP;
+
+ GEP.push_back(Zero); // point at the outermost array
+
+ // For each layer of array type we're pointing at:
+ while (const ConstantArrayType *Arr
+ = getContext().getAsConstantArrayType(DeleteTy)) {
+ // 1. Unpeel the array type.
+ DeleteTy = Arr->getElementType();
+
+ // 2. GEP to the first element of the array.
+ GEP.push_back(Zero);
+ }
+
+ Ptr = Builder.CreateInBoundsGEP(Ptr, GEP.begin(), GEP.end(), "del.first");
+ }
+
+ assert(ConvertTypeForMem(DeleteTy) ==
+ cast<llvm::PointerType>(Ptr->getType())->getElementType());
+
+ if (E->isArrayForm()) {
+ EmitArrayDelete(*this, E, Ptr, DeleteTy);
+ } else {
+ EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy);
+ }
+
+ EmitBlock(DeleteEnd);
+}
+
+llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
+ QualType Ty = E->getType();
+ const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
+
+ if (E->isTypeOperand()) {
+ llvm::Constant *TypeInfo =
+ CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand());
+ return Builder.CreateBitCast(TypeInfo, LTy);
+ }
+
+ Expr *subE = E->getExprOperand();
+ Ty = subE->getType();
+ CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType().getNonReferenceType();
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->isPolymorphic()) {
+ // FIXME: if subE is an lvalue do
+ LValue Obj = EmitLValue(subE);
+ llvm::Value *This = Obj.getAddress();
+ // We need to do a zero check for *p, unless it has NonNullAttr.
+ // FIXME: PointerType->hasAttr<NonNullAttr>()
+ bool CanBeZero = false;
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
+ if (UO->getOpcode() == UO_Deref)
+ CanBeZero = true;
+ if (CanBeZero) {
+ llvm::BasicBlock *NonZeroBlock = createBasicBlock();
+ llvm::BasicBlock *ZeroBlock = createBasicBlock();
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(This->getType());
+ Builder.CreateCondBr(Builder.CreateICmpNE(This, Zero),
+ NonZeroBlock, ZeroBlock);
+ EmitBlock(ZeroBlock);
+ /// Call __cxa_bad_typeid
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(getLLVMContext());
+ const llvm::FunctionType *FTy;
+ FTy = llvm::FunctionType::get(ResultType, false);
+ llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
+ Builder.CreateCall(F)->setDoesNotReturn();
+ Builder.CreateUnreachable();
+ EmitBlock(NonZeroBlock);
+ }
+ llvm::Value *V = GetVTablePtr(This, LTy->getPointerTo());
+ V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
+ V = Builder.CreateLoad(V);
+ return V;
+ }
+ }
+ return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy);
+}
+
+llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
+ const CXXDynamicCastExpr *DCE) {
+ QualType SrcTy = DCE->getSubExpr()->getType();
+ QualType DestTy = DCE->getTypeAsWritten();
+ QualType InnerType = DestTy->getPointeeType();
+
+ const llvm::Type *LTy = ConvertType(DCE->getType());
+
+ bool CanBeZero = false;
+ bool ToVoid = false;
+ bool ThrowOnBad = false;
+ if (DestTy->isPointerType()) {
+ // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
+ CanBeZero = true;
+ if (InnerType->isVoidType())
+ ToVoid = true;
+ } else {
+ LTy = LTy->getPointerTo();
+
+ // FIXME: What if exceptions are disabled?
+ ThrowOnBad = true;
+ }
+
+ if (SrcTy->isPointerType() || SrcTy->isReferenceType())
+ SrcTy = SrcTy->getPointeeType();
+ SrcTy = SrcTy.getUnqualifiedType();
+
+ if (DestTy->isPointerType() || DestTy->isReferenceType())
+ DestTy = DestTy->getPointeeType();
+ DestTy = DestTy.getUnqualifiedType();
+
+ llvm::BasicBlock *ContBlock = createBasicBlock();
+ llvm::BasicBlock *NullBlock = 0;
+ llvm::BasicBlock *NonZeroBlock = 0;
+ if (CanBeZero) {
+ NonZeroBlock = createBasicBlock();
+ NullBlock = createBasicBlock();
+ Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock);
+ EmitBlock(NonZeroBlock);
+ }
+
+ llvm::BasicBlock *BadCastBlock = 0;
+
+ const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
+
+ // See if this is a dynamic_cast(void*)
+ if (ToVoid) {
+ llvm::Value *This = V;
+ V = GetVTablePtr(This, PtrDiffTy->getPointerTo());
+ V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
+ V = Builder.CreateLoad(V, "offset to top");
+ This = EmitCastToVoidPtr(This);
+ V = Builder.CreateInBoundsGEP(This, V);
+ V = Builder.CreateBitCast(V, LTy);
+ } else {
+ /// Call __dynamic_cast
+ const llvm::Type *ResultType = Int8PtrTy;
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(PtrDiffTy);
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+
+ // FIXME: Calculate better hint.
+ llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
+
+ assert(SrcTy->isRecordType() && "Src type must be record type!");
+ assert(DestTy->isRecordType() && "Dest type must be record type!");
+
+ llvm::Value *SrcArg
+ = CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType());
+ llvm::Value *DestArg
+ = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType());
+
+ V = Builder.CreateBitCast(V, Int8PtrTy);
+ V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
+ V, SrcArg, DestArg, hint);
+ V = Builder.CreateBitCast(V, LTy);
+
+ if (ThrowOnBad) {
+ BadCastBlock = createBasicBlock();
+ Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock);
+ EmitBlock(BadCastBlock);
+ /// Invoke __cxa_bad_cast
+ ResultType = llvm::Type::getVoidTy(getLLVMContext());
+ const llvm::FunctionType *FBadTy;
+ FBadTy = llvm::FunctionType::get(ResultType, false);
+ llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
+ if (llvm::BasicBlock *InvokeDest = getInvokeDest()) {
+ llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
+ Builder.CreateInvoke(F, Cont, InvokeDest)->setDoesNotReturn();
+ EmitBlock(Cont);
+ } else {
+ // FIXME: Does this ever make sense?
+ Builder.CreateCall(F)->setDoesNotReturn();
+ }
+ Builder.CreateUnreachable();
+ }
+ }
+
+ if (CanBeZero) {
+ Builder.CreateBr(ContBlock);
+ EmitBlock(NullBlock);
+ Builder.CreateBr(ContBlock);
+ }
+ EmitBlock(ContBlock);
+ if (CanBeZero) {
+ llvm::PHINode *PHI = Builder.CreatePHI(LTy);
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(V, NonZeroBlock);
+ PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
+ V = PHI;
+ }
+
+ return V;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
new file mode 100644
index 0000000..7b0292b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
@@ -0,0 +1,784 @@
+//===--- CGExprComplex.cpp - Emit LLVM Code for Complex Exprs -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Expr nodes with complex types as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===----------------------------------------------------------------------===//
+// Complex Expression Emitter
+//===----------------------------------------------------------------------===//
+
+typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
+
+namespace {
+class ComplexExprEmitter
+ : public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
+ CodeGenFunction &CGF;
+ CGBuilderTy &Builder;
+ // True is we should ignore the value of a
+ bool IgnoreReal;
+ bool IgnoreImag;
+public:
+ ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false)
+ : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) {
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Utilities
+ //===--------------------------------------------------------------------===//
+
+ bool TestAndClearIgnoreReal() {
+ bool I = IgnoreReal;
+ IgnoreReal = false;
+ return I;
+ }
+ bool TestAndClearIgnoreImag() {
+ bool I = IgnoreImag;
+ IgnoreImag = false;
+ return I;
+ }
+
+ /// EmitLoadOfLValue - Given an expression with complex type that represents a
+ /// value l-value, this method emits the address of the l-value, then loads
+ /// and returns the result.
+ ComplexPairTy EmitLoadOfLValue(const Expr *E) {
+ return EmitLoadOfLValue(CGF.EmitLValue(E));
+ }
+
+ ComplexPairTy EmitLoadOfLValue(LValue LV) {
+ if (LV.isSimple())
+ return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+
+ assert(LV.isPropertyRef() && "Unknown LValue type!");
+ return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal();
+ }
+
+ /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load
+ /// the real and imaginary pieces.
+ ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile);
+
+ /// EmitStoreThroughLValue - Given an l-value of complex type, store
+ /// a complex number into it.
+ void EmitStoreThroughLValue(ComplexPairTy Val, LValue LV) {
+ if (LV.isSimple())
+ return EmitStoreOfComplex(Val, LV.getAddress(), LV.isVolatileQualified());
+
+ assert(LV.isPropertyRef() && "Unknown LValue type!");
+ CGF.EmitStoreThroughPropertyRefLValue(RValue::getComplex(Val), LV);
+ }
+
+ /// EmitStoreOfComplex - Store the specified real/imag parts into the
+ /// specified value pointer.
+ void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol);
+
+ /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
+ ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
+ QualType DestType);
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ ComplexPairTy Visit(Expr *E) {
+ return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E);
+ }
+
+ ComplexPairTy VisitStmt(Stmt *S) {
+ S->dump(CGF.getContext().getSourceManager());
+ assert(0 && "Stmt can't have complex result type!");
+ return ComplexPairTy();
+ }
+ ComplexPairTy VisitExpr(Expr *S);
+ ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
+ ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
+
+ // l-values.
+ ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ return EmitLoadOfLValue(E);
+ }
+ ComplexPairTy VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ assert(E->getObjectKind() == OK_Ordinary);
+ return EmitLoadOfLValue(E);
+ }
+ ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ return CGF.EmitObjCMessageExpr(E).getComplexVal();
+ }
+ ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E));
+ return CGF.getOpaqueRValueMapping(E).getComplexVal();
+ }
+
+ // FIXME: CompoundLiteralExpr
+
+ ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy);
+ ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ // Unlike for scalars, we don't have to worry about function->ptr demotion
+ // here.
+ return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
+ }
+ ComplexPairTy VisitCastExpr(CastExpr *E) {
+ return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
+ }
+ ComplexPairTy VisitCallExpr(const CallExpr *E);
+ ComplexPairTy VisitStmtExpr(const StmtExpr *E);
+
+ // Operators.
+ ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E,
+ bool isInc, bool isPre) {
+ LValue LV = CGF.EmitLValue(E->getSubExpr());
+ return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre);
+ }
+ ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) {
+ return VisitPrePostIncDec(E, false, false);
+ }
+ ComplexPairTy VisitUnaryPostInc(const UnaryOperator *E) {
+ return VisitPrePostIncDec(E, true, false);
+ }
+ ComplexPairTy VisitUnaryPreDec(const UnaryOperator *E) {
+ return VisitPrePostIncDec(E, false, true);
+ }
+ ComplexPairTy VisitUnaryPreInc(const UnaryOperator *E) {
+ return VisitPrePostIncDec(E, true, true);
+ }
+ ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
+ ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ return Visit(E->getSubExpr());
+ }
+ ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
+ ComplexPairTy VisitUnaryNot (const UnaryOperator *E);
+ // LNot,Real,Imag never return complex.
+ ComplexPairTy VisitUnaryExtension(const UnaryOperator *E) {
+ return Visit(E->getSubExpr());
+ }
+ ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
+ ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
+ return CGF.EmitExprWithCleanups(E).getComplexVal();
+ }
+ ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ assert(E->getType()->isAnyComplexType() && "Expected complex type!");
+ QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
+ llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem));
+ return ComplexPairTy(Null, Null);
+ }
+ ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+ assert(E->getType()->isAnyComplexType() && "Expected complex type!");
+ QualType Elem = E->getType()->getAs<ComplexType>()->getElementType();
+ llvm::Constant *Null =
+ llvm::Constant::getNullValue(CGF.ConvertType(Elem));
+ return ComplexPairTy(Null, Null);
+ }
+
+ struct BinOpInfo {
+ ComplexPairTy LHS;
+ ComplexPairTy RHS;
+ QualType Ty; // Computation Type.
+ };
+
+ BinOpInfo EmitBinOps(const BinaryOperator *E);
+ LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
+ ComplexPairTy (ComplexExprEmitter::*Func)
+ (const BinOpInfo &),
+ ComplexPairTy &Val);
+ ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
+ ComplexPairTy (ComplexExprEmitter::*Func)
+ (const BinOpInfo &));
+
+ ComplexPairTy EmitBinAdd(const BinOpInfo &Op);
+ ComplexPairTy EmitBinSub(const BinOpInfo &Op);
+ ComplexPairTy EmitBinMul(const BinOpInfo &Op);
+ ComplexPairTy EmitBinDiv(const BinOpInfo &Op);
+
+ ComplexPairTy VisitBinAdd(const BinaryOperator *E) {
+ return EmitBinAdd(EmitBinOps(E));
+ }
+ ComplexPairTy VisitBinSub(const BinaryOperator *E) {
+ return EmitBinSub(EmitBinOps(E));
+ }
+ ComplexPairTy VisitBinMul(const BinaryOperator *E) {
+ return EmitBinMul(EmitBinOps(E));
+ }
+ ComplexPairTy VisitBinDiv(const BinaryOperator *E) {
+ return EmitBinDiv(EmitBinOps(E));
+ }
+
+ // Compound assignments.
+ ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) {
+ return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd);
+ }
+ ComplexPairTy VisitBinSubAssign(const CompoundAssignOperator *E) {
+ return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinSub);
+ }
+ ComplexPairTy VisitBinMulAssign(const CompoundAssignOperator *E) {
+ return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinMul);
+ }
+ ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) {
+ return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv);
+ }
+
+ // GCC rejects rem/and/or/xor for integer complex.
+ // Logical and/or always return int, never complex.
+
+ // No comparisons produce a complex result.
+
+ LValue EmitBinAssignLValue(const BinaryOperator *E,
+ ComplexPairTy &Val);
+ ComplexPairTy VisitBinAssign (const BinaryOperator *E);
+ ComplexPairTy VisitBinComma (const BinaryOperator *E);
+
+
+ ComplexPairTy
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
+ ComplexPairTy VisitChooseExpr(ChooseExpr *CE);
+
+ ComplexPairTy VisitInitListExpr(InitListExpr *E);
+
+ ComplexPairTy VisitVAArgExpr(VAArgExpr *E);
+};
+} // end anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
+/// load the real and imaginary pieces, returning them as Real/Imag.
+ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
+ bool isVolatile) {
+ llvm::Value *Real=0, *Imag=0;
+
+ if (!IgnoreReal || isVolatile) {
+ llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,
+ SrcPtr->getName() + ".realp");
+ Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr->getName() + ".real");
+ }
+
+ if (!IgnoreImag || isVolatile) {
+ llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1,
+ SrcPtr->getName() + ".imagp");
+ Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr->getName() + ".imag");
+ }
+ return ComplexPairTy(Real, Imag);
+}
+
+/// EmitStoreOfComplex - Store the specified real/imag parts into the
+/// specified value pointer.
+void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr,
+ bool isVolatile) {
+ llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real");
+ llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag");
+
+ Builder.CreateStore(Val.first, RealPtr, isVolatile);
+ Builder.CreateStore(Val.second, ImagPtr, isVolatile);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Visitor Methods
+//===----------------------------------------------------------------------===//
+
+ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
+ CGF.ErrorUnsupported(E, "complex expression");
+ const llvm::Type *EltTy =
+ CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
+ llvm::Value *U = llvm::UndefValue::get(EltTy);
+ return ComplexPairTy(U, U);
+}
+
+ComplexPairTy ComplexExprEmitter::
+VisitImaginaryLiteral(const ImaginaryLiteral *IL) {
+ llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr());
+ return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag);
+}
+
+
+ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
+ if (E->getCallReturnType()->isReferenceType())
+ return EmitLoadOfLValue(E);
+
+ return CGF.EmitCallExpr(E).getComplexVal();
+}
+
+ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
+ CodeGenFunction::StmtExprEvaluation eval(CGF);
+ return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
+}
+
+/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
+ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
+ QualType SrcType,
+ QualType DestType) {
+ // Get the src/dest element type.
+ SrcType = SrcType->getAs<ComplexType>()->getElementType();
+ DestType = DestType->getAs<ComplexType>()->getElementType();
+
+ // C99 6.3.1.6: When a value of complex type is converted to another
+ // complex type, both the real and imaginary parts follow the conversion
+ // rules for the corresponding real types.
+ Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType);
+ Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType);
+ return Val;
+}
+
+ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
+ QualType DestTy) {
+ switch (CK) {
+ case CK_GetObjCProperty: {
+ LValue LV = CGF.EmitLValue(Op);
+ assert(LV.isPropertyRef() && "Unknown LValue type!");
+ return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal();
+ }
+
+ case CK_NoOp:
+ case CK_LValueToRValue:
+ return Visit(Op);
+
+ // TODO: do all of these
+ default:
+ break;
+ }
+
+ // Two cases here: cast from (complex to complex) and (scalar to complex).
+ if (Op->getType()->isAnyComplexType())
+ return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy);
+
+ // FIXME: We should be looking at all of the cast kinds here, not
+ // cherry-picking the ones we have test cases for.
+ if (CK == CK_LValueBitCast) {
+ llvm::Value *V = CGF.EmitLValue(Op).getAddress();
+ V = Builder.CreateBitCast(V,
+ CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
+ // FIXME: Are the qualifiers correct here?
+ return EmitLoadOfComplex(V, DestTy.isVolatileQualified());
+ }
+
+ // C99 6.3.1.7: When a value of real type is converted to a complex type, the
+ // real part of the complex result value is determined by the rules of
+ // conversion to the corresponding real type and the imaginary part of the
+ // complex result value is a positive zero or an unsigned zero.
+ llvm::Value *Elt = CGF.EmitScalarExpr(Op);
+
+ // Convert the input element to the element type of the complex.
+ DestTy = DestTy->getAs<ComplexType>()->getElementType();
+ Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
+
+ // Return (realval, 0).
+ return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
+}
+
+ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ ComplexPairTy Op = Visit(E->getSubExpr());
+
+ llvm::Value *ResR, *ResI;
+ if (Op.first->getType()->isFloatingPointTy()) {
+ ResR = Builder.CreateFNeg(Op.first, "neg.r");
+ ResI = Builder.CreateFNeg(Op.second, "neg.i");
+ } else {
+ ResR = Builder.CreateNeg(Op.first, "neg.r");
+ ResI = Builder.CreateNeg(Op.second, "neg.i");
+ }
+ return ComplexPairTy(ResR, ResI);
+}
+
+ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ // ~(a+ib) = a + i*-b
+ ComplexPairTy Op = Visit(E->getSubExpr());
+ llvm::Value *ResI;
+ if (Op.second->getType()->isFloatingPointTy())
+ ResI = Builder.CreateFNeg(Op.second, "conj.i");
+ else
+ ResI = Builder.CreateNeg(Op.second, "conj.i");
+
+ return ComplexPairTy(Op.first, ResI);
+}
+
+ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
+ llvm::Value *ResR, *ResI;
+
+ if (Op.LHS.first->getType()->isFloatingPointTy()) {
+ ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ } else {
+ ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ }
+ return ComplexPairTy(ResR, ResI);
+}
+
+ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
+ llvm::Value *ResR, *ResI;
+ if (Op.LHS.first->getType()->isFloatingPointTy()) {
+ ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ } else {
+ ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ }
+ return ComplexPairTy(ResR, ResI);
+}
+
+
+ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
+ using llvm::Value;
+ Value *ResR, *ResI;
+
+ if (Op.LHS.first->getType()->isFloatingPointTy()) {
+ Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i");
+ } else {
+ Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
+ }
+ return ComplexPairTy(ResR, ResI);
+}
+
+ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
+ llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
+ llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
+
+
+ llvm::Value *DSTr, *DSTi;
+ if (Op.LHS.first->getType()->isFloatingPointTy()) {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
+ DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp");
+ DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp");
+ } else {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
+ if (Op.Ty->getAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) {
+ DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp");
+ DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp");
+ } else {
+ DSTr = Builder.CreateSDiv(Tmp3, Tmp6, "tmp");
+ DSTi = Builder.CreateSDiv(Tmp9, Tmp6, "tmp");
+ }
+ }
+
+ return ComplexPairTy(DSTr, DSTi);
+}
+
+ComplexExprEmitter::BinOpInfo
+ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ BinOpInfo Ops;
+ Ops.LHS = Visit(E->getLHS());
+ Ops.RHS = Visit(E->getRHS());
+ Ops.Ty = E->getType();
+ return Ops;
+}
+
+
+LValue ComplexExprEmitter::
+EmitCompoundAssignLValue(const CompoundAssignOperator *E,
+ ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
+ ComplexPairTy &Val) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ QualType LHSTy = E->getLHS()->getType();
+
+ BinOpInfo OpInfo;
+
+ // Load the RHS and LHS operands.
+ // __block variables need to have the rhs evaluated first, plus this should
+ // improve codegen a little.
+ OpInfo.Ty = E->getComputationResultType();
+
+ // The RHS should have been converted to the computation type.
+ assert(OpInfo.Ty->isAnyComplexType());
+ assert(CGF.getContext().hasSameUnqualifiedType(OpInfo.Ty,
+ E->getRHS()->getType()));
+ OpInfo.RHS = Visit(E->getRHS());
+
+ LValue LHS = CGF.EmitLValue(E->getLHS());
+
+ // Load from the l-value.
+ ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS);
+
+ OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty);
+
+ // Expand the binary operator.
+ ComplexPairTy Result = (this->*Func)(OpInfo);
+
+ // Truncate the result back to the LHS type.
+ Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
+ Val = Result;
+
+ // Store the result value into the LHS lvalue.
+ EmitStoreThroughLValue(Result, LHS);
+
+ return LHS;
+}
+
+// Compound assignments.
+ComplexPairTy ComplexExprEmitter::
+EmitCompoundAssign(const CompoundAssignOperator *E,
+ ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
+ ComplexPairTy Val;
+ LValue LV = EmitCompoundAssignLValue(E, Func, Val);
+
+ // The result of an assignment in C is the assigned r-value.
+ if (!CGF.getContext().getLangOptions().CPlusPlus)
+ return Val;
+
+ // Objective-C property assignment never reloads the value following a store.
+ if (LV.isPropertyRef())
+ return Val;
+
+ // If the lvalue is non-volatile, return the computed value of the assignment.
+ if (!LV.isVolatileQualified())
+ return Val;
+
+ return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+}
+
+LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E,
+ ComplexPairTy &Val) {
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
+ E->getRHS()->getType()) &&
+ "Invalid assignment");
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+
+ // Emit the RHS. __block variables need the RHS evaluated first.
+ Val = Visit(E->getRHS());
+
+ // Compute the address to store into.
+ LValue LHS = CGF.EmitLValue(E->getLHS());
+
+ // Store the result value into the LHS lvalue.
+ EmitStoreThroughLValue(Val, LHS);
+
+ return LHS;
+}
+
+ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ ComplexPairTy Val;
+ LValue LV = EmitBinAssignLValue(E, Val);
+
+ // The result of an assignment in C is the assigned r-value.
+ if (!CGF.getContext().getLangOptions().CPlusPlus)
+ return Val;
+
+ // Objective-C property assignment never reloads the value following a store.
+ if (LV.isPropertyRef())
+ return Val;
+
+ // If the lvalue is non-volatile, return the computed value of the assignment.
+ if (!LV.isVolatileQualified())
+ return Val;
+
+ return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+}
+
+ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
+ CGF.EmitIgnoredExpr(E->getLHS());
+ return Visit(E->getRHS());
+}
+
+ComplexPairTy ComplexExprEmitter::
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
+ llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
+
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+ CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock);
+
+ eval.begin(CGF);
+ CGF.EmitBlock(LHSBlock);
+ ComplexPairTy LHS = Visit(E->getTrueExpr());
+ LHSBlock = Builder.GetInsertBlock();
+ CGF.EmitBranch(ContBlock);
+ eval.end(CGF);
+
+ eval.begin(CGF);
+ CGF.EmitBlock(RHSBlock);
+ ComplexPairTy RHS = Visit(E->getFalseExpr());
+ RHSBlock = Builder.GetInsertBlock();
+ CGF.EmitBlock(ContBlock);
+ eval.end(CGF);
+
+ // Create a PHI node for the real part.
+ llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), "cond.r");
+ RealPN->reserveOperandSpace(2);
+ RealPN->addIncoming(LHS.first, LHSBlock);
+ RealPN->addIncoming(RHS.first, RHSBlock);
+
+ // Create a PHI node for the imaginary part.
+ llvm::PHINode *ImagPN = Builder.CreatePHI(LHS.first->getType(), "cond.i");
+ ImagPN->reserveOperandSpace(2);
+ ImagPN->addIncoming(LHS.second, LHSBlock);
+ ImagPN->addIncoming(RHS.second, RHSBlock);
+
+ return ComplexPairTy(RealPN, ImagPN);
+}
+
+ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
+ return Visit(E->getChosenSubExpr(CGF.getContext()));
+}
+
+ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
+ bool Ignore = TestAndClearIgnoreReal();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ Ignore = TestAndClearIgnoreImag();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ if (E->getNumInits())
+ return Visit(E->getInit(0));
+
+ // Empty init list intializes to null
+ QualType Ty = E->getType()->getAs<ComplexType>()->getElementType();
+ const llvm::Type* LTy = CGF.ConvertType(Ty);
+ llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy);
+ return ComplexPairTy(zeroConstant, zeroConstant);
+}
+
+ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
+ llvm::Value *ArgValue = CGF.EmitVAListRef(E->getSubExpr());
+ llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, E->getType());
+
+ if (!ArgPtr) {
+ CGF.ErrorUnsupported(E, "complex va_arg expression");
+ const llvm::Type *EltTy =
+ CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType());
+ llvm::Value *U = llvm::UndefValue::get(EltTy);
+ return ComplexPairTy(U, U);
+ }
+
+ // FIXME Volatility.
+ return EmitLoadOfComplex(ArgPtr, false);
+}
+
+//===----------------------------------------------------------------------===//
+// Entry Point into this File
+//===----------------------------------------------------------------------===//
+
+/// EmitComplexExpr - Emit the computation of the specified expression of
+/// complex type, ignoring the result.
+ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
+ bool IgnoreImag) {
+ assert(E && E->getType()->isAnyComplexType() &&
+ "Invalid complex expression to emit");
+
+ return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag)
+ .Visit(const_cast<Expr*>(E));
+}
+
+/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
+/// of complex type, storing into the specified Value*.
+void CodeGenFunction::EmitComplexExprIntoAddr(const Expr *E,
+ llvm::Value *DestAddr,
+ bool DestIsVolatile) {
+ assert(E && E->getType()->isAnyComplexType() &&
+ "Invalid complex expression to emit");
+ ComplexExprEmitter Emitter(*this);
+ ComplexPairTy Val = Emitter.Visit(const_cast<Expr*>(E));
+ Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
+}
+
+/// StoreComplexToAddr - Store a complex number into the specified address.
+void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
+ llvm::Value *DestAddr,
+ bool DestIsVolatile) {
+ ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
+}
+
+/// LoadComplexFromAddr - Load a complex number from the specified address.
+ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr,
+ bool SrcIsVolatile) {
+ return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile);
+}
+
+LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
+ assert(E->getOpcode() == BO_Assign);
+ ComplexPairTy Val; // ignored
+ return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
+}
+
+LValue CodeGenFunction::
+EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
+ ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
+ switch (E->getOpcode()) {
+ case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
+ case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
+ case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
+ case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
+
+ default:
+ llvm_unreachable("unexpected complex compound assignment");
+ Op = 0;
+ }
+
+ ComplexPairTy Val; // ignored
+ return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
new file mode 100644
index 0000000..40d7b6c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
@@ -0,0 +1,1188 @@
+//===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Constant Expr nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "CGRecordLayout.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Builtins.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===----------------------------------------------------------------------===//
+// ConstStructBuilder
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ConstStructBuilder {
+ CodeGenModule &CGM;
+ CodeGenFunction *CGF;
+
+ bool Packed;
+ unsigned NextFieldOffsetInBytes;
+ unsigned LLVMStructAlignment;
+ std::vector<llvm::Constant *> Elements;
+public:
+ static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
+ InitListExpr *ILE);
+
+private:
+ ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
+ : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0),
+ LLVMStructAlignment(1) { }
+
+ bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitExpr);
+
+ void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::ConstantInt *InitExpr);
+
+ void AppendPadding(uint64_t NumBytes);
+
+ void AppendTailPadding(uint64_t RecordSize);
+
+ void ConvertStructToPacked();
+
+ bool Build(InitListExpr *ILE);
+
+ unsigned getAlignment(const llvm::Constant *C) const {
+ if (Packed) return 1;
+ return CGM.getTargetData().getABITypeAlignment(C->getType());
+ }
+
+ uint64_t getSizeInBytes(const llvm::Constant *C) const {
+ return CGM.getTargetData().getTypeAllocSize(C->getType());
+ }
+};
+
+bool ConstStructBuilder::
+AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+ llvm::Constant *InitCst) {
+ uint64_t FieldOffsetInBytes = FieldOffset / 8;
+
+ assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
+ && "Field offset mismatch!");
+
+ unsigned FieldAlignment = getAlignment(InitCst);
+
+ // Round up the field offset to the alignment of the field type.
+ uint64_t AlignedNextFieldOffsetInBytes =
+ llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
+
+ if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
+ assert(!Packed && "Alignment is wrong even with a packed struct!");
+
+ // Convert the struct to a packed struct.
+ ConvertStructToPacked();
+
+ AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
+ }
+
+ if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
+ // We need to append padding.
+ AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);
+
+ assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
+ "Did not add enough padding!");
+
+ AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
+ }
+
+ // Add the field.
+ Elements.push_back(InitCst);
+ NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes +
+ getSizeInBytes(InitCst);
+
+ if (Packed)
+ assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
+ else
+ LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
+
+ return true;
+}
+
+void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
+ uint64_t FieldOffset,
+ llvm::ConstantInt *CI) {
+ if (FieldOffset > NextFieldOffsetInBytes * 8) {
+ // We need to add padding.
+ uint64_t NumBytes =
+ llvm::RoundUpToAlignment(FieldOffset -
+ NextFieldOffsetInBytes * 8, 8) / 8;
+
+ AppendPadding(NumBytes);
+ }
+
+ uint64_t FieldSize =
+ Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();
+
+ llvm::APInt FieldValue = CI->getValue();
+
+ // Promote the size of FieldValue if necessary
+ // FIXME: This should never occur, but currently it can because initializer
+ // constants are cast to bool, and because clang is not enforcing bitfield
+ // width limits.
+ if (FieldSize > FieldValue.getBitWidth())
+ FieldValue = FieldValue.zext(FieldSize);
+
+ // Truncate the size of FieldValue to the bit field size.
+ if (FieldSize < FieldValue.getBitWidth())
+ FieldValue = FieldValue.trunc(FieldSize);
+
+ if (FieldOffset < NextFieldOffsetInBytes * 8) {
+ // Either part of the field or the entire field can go into the previous
+ // byte.
+ assert(!Elements.empty() && "Elements can't be empty!");
+
+ unsigned BitsInPreviousByte =
+ NextFieldOffsetInBytes * 8 - FieldOffset;
+
+ bool FitsCompletelyInPreviousByte =
+ BitsInPreviousByte >= FieldValue.getBitWidth();
+
+ llvm::APInt Tmp = FieldValue;
+
+ if (!FitsCompletelyInPreviousByte) {
+ unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;
+
+ if (CGM.getTargetData().isBigEndian()) {
+ Tmp = Tmp.lshr(NewFieldWidth);
+ Tmp = Tmp.trunc(BitsInPreviousByte);
+
+ // We want the remaining high bits.
+ FieldValue = FieldValue.trunc(NewFieldWidth);
+ } else {
+ Tmp = Tmp.trunc(BitsInPreviousByte);
+
+ // We want the remaining low bits.
+ FieldValue = FieldValue.lshr(BitsInPreviousByte);
+ FieldValue = FieldValue.trunc(NewFieldWidth);
+ }
+ }
+
+ Tmp = Tmp.zext(8);
+ if (CGM.getTargetData().isBigEndian()) {
+ if (FitsCompletelyInPreviousByte)
+ Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth());
+ } else {
+ Tmp = Tmp.shl(8 - BitsInPreviousByte);
+ }
+
+ // 'or' in the bits that go into the previous byte.
+ llvm::Value *LastElt = Elements.back();
+ if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(LastElt))
+ Tmp |= Val->getValue();
+ else {
+ assert(isa<llvm::UndefValue>(LastElt));
+ // If there is an undef field that we're adding to, it can either be a
+ // scalar undef (in which case, we just replace it with our field) or it
+ // is an array. If it is an array, we have to pull one byte off the
+ // array so that the other undef bytes stay around.
+ if (!isa<llvm::IntegerType>(LastElt->getType())) {
+ // The undef padding will be a multibyte array, create a new smaller
+ // padding and then an hole for our i8 to get plopped into.
+ assert(isa<llvm::ArrayType>(LastElt->getType()) &&
+ "Expected array padding of undefs");
+ const llvm::ArrayType *AT = cast<llvm::ArrayType>(LastElt->getType());
+ assert(AT->getElementType()->isIntegerTy(8) &&
+ AT->getNumElements() != 0 &&
+ "Expected non-empty array padding of undefs");
+
+ // Remove the padding array.
+ NextFieldOffsetInBytes -= AT->getNumElements();
+ Elements.pop_back();
+
+ // Add the padding back in two chunks.
+ AppendPadding(AT->getNumElements()-1);
+ AppendPadding(1);
+ assert(isa<llvm::UndefValue>(Elements.back()) &&
+ Elements.back()->getType()->isIntegerTy(8) &&
+ "Padding addition didn't work right");
+ }
+ }
+
+ Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);
+
+ if (FitsCompletelyInPreviousByte)
+ return;
+ }
+
+ while (FieldValue.getBitWidth() > 8) {
+ llvm::APInt Tmp;
+
+ if (CGM.getTargetData().isBigEndian()) {
+ // We want the high bits.
+ Tmp = FieldValue.lshr(FieldValue.getBitWidth() - 8).trunc(8);
+ } else {
+ // We want the low bits.
+ Tmp = FieldValue.trunc(8);
+
+ FieldValue = FieldValue.lshr(8);
+ }
+
+ Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
+ NextFieldOffsetInBytes++;
+
+ FieldValue = FieldValue.trunc(FieldValue.getBitWidth() - 8);
+ }
+
+ assert(FieldValue.getBitWidth() > 0 &&
+ "Should have at least one bit left!");
+ assert(FieldValue.getBitWidth() <= 8 &&
+ "Should not have more than a byte left!");
+
+ if (FieldValue.getBitWidth() < 8) {
+ if (CGM.getTargetData().isBigEndian()) {
+ unsigned BitWidth = FieldValue.getBitWidth();
+
+ FieldValue = FieldValue.zext(8) << (8 - BitWidth);
+ } else
+ FieldValue = FieldValue.zext(8);
+ }
+
+ // Append the last element.
+ Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
+ FieldValue));
+ NextFieldOffsetInBytes++;
+}
+
+void ConstStructBuilder::AppendPadding(uint64_t NumBytes) {
+ if (!NumBytes)
+ return;
+
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ if (NumBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumBytes);
+
+ llvm::Constant *C = llvm::UndefValue::get(Ty);
+ Elements.push_back(C);
+ assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
+
+ NextFieldOffsetInBytes += getSizeInBytes(C);
+}
+
+void ConstStructBuilder::AppendTailPadding(uint64_t RecordSize) {
+ assert(RecordSize % 8 == 0 && "Invalid record size!");
+
+ uint64_t RecordSizeInBytes = RecordSize / 8;
+ assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
+
+ unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
+ AppendPadding(NumPadBytes);
+}
+
+void ConstStructBuilder::ConvertStructToPacked() {
+ std::vector<llvm::Constant *> PackedElements;
+ uint64_t ElementOffsetInBytes = 0;
+
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ llvm::Constant *C = Elements[i];
+
+ unsigned ElementAlign =
+ CGM.getTargetData().getABITypeAlignment(C->getType());
+ uint64_t AlignedElementOffsetInBytes =
+ llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);
+
+ if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
+ // We need some padding.
+ uint64_t NumBytes =
+ AlignedElementOffsetInBytes - ElementOffsetInBytes;
+
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ if (NumBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumBytes);
+
+ llvm::Constant *Padding = llvm::UndefValue::get(Ty);
+ PackedElements.push_back(Padding);
+ ElementOffsetInBytes += getSizeInBytes(Padding);
+ }
+
+ PackedElements.push_back(C);
+ ElementOffsetInBytes += getSizeInBytes(C);
+ }
+
+ assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
+ "Packing the struct changed its size!");
+
+ Elements = PackedElements;
+ LLVMStructAlignment = 1;
+ Packed = true;
+}
+
+bool ConstStructBuilder::Build(InitListExpr *ILE) {
+ RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ unsigned FieldNo = 0;
+ unsigned ElementNo = 0;
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+
+ // If this is a union, skip all the fields that aren't being initialized.
+ if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
+ continue;
+
+ // Don't emit anonymous bitfields, they just affect layout.
+ if (Field->isBitField() && !Field->getIdentifier())
+ continue;
+
+ // Get the initializer. A struct can include fields without initializers,
+ // we just use explicit null values for them.
+ llvm::Constant *EltInit;
+ if (ElementNo < ILE->getNumInits())
+ EltInit = CGM.EmitConstantExpr(ILE->getInit(ElementNo++),
+ Field->getType(), CGF);
+ else
+ EltInit = CGM.EmitNullConstant(Field->getType());
+
+ if (!EltInit)
+ return false;
+
+ if (!Field->isBitField()) {
+ // Handle non-bitfield members.
+ if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
+ return false;
+ } else {
+ // Otherwise we have a bitfield.
+ AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
+ cast<llvm::ConstantInt>(EltInit));
+ }
+ }
+
+ uint64_t LayoutSizeInBytes = Layout.getSize().getQuantity();
+
+ if (NextFieldOffsetInBytes > LayoutSizeInBytes) {
+ // If the struct is bigger than the size of the record type,
+ // we must have a flexible array member at the end.
+ assert(RD->hasFlexibleArrayMember() &&
+ "Must have flexible array member if struct is bigger than type!");
+
+ // No tail padding is necessary.
+ return true;
+ }
+
+ uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes,
+ LLVMStructAlignment);
+
+ // Check if we need to convert the struct to a packed struct.
+ if (NextFieldOffsetInBytes <= LayoutSizeInBytes &&
+ LLVMSizeInBytes > LayoutSizeInBytes) {
+ assert(!Packed && "Size mismatch!");
+
+ ConvertStructToPacked();
+ assert(NextFieldOffsetInBytes <= LayoutSizeInBytes &&
+ "Converting to packed did not help!");
+ }
+
+ // Append tail padding if necessary.
+ AppendTailPadding(CGM.getContext().toBits(Layout.getSize()));
+
+ assert(Layout.getSize().getQuantity() == NextFieldOffsetInBytes &&
+ "Tail padding mismatch!");
+
+ return true;
+}
+
+llvm::Constant *ConstStructBuilder::
+ BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, InitListExpr *ILE) {
+ ConstStructBuilder Builder(CGM, CGF);
+
+ if (!Builder.Build(ILE))
+ return 0;
+
+ llvm::Constant *Result =
+ llvm::ConstantStruct::get(CGM.getLLVMContext(),
+ Builder.Elements, Builder.Packed);
+
+ assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes,
+ Builder.getAlignment(Result)) ==
+ Builder.getSizeInBytes(Result) && "Size mismatch!");
+
+ return Result;
+}
+
+
+//===----------------------------------------------------------------------===//
+// ConstExprEmitter
+//===----------------------------------------------------------------------===//
+
+class ConstExprEmitter :
+ public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
+ CodeGenModule &CGM;
+ CodeGenFunction *CGF;
+ llvm::LLVMContext &VMContext;
+public:
+ ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf)
+ : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) {
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ llvm::Constant *VisitStmt(Stmt *S) {
+ return 0;
+ }
+
+ llvm::Constant *VisitParenExpr(ParenExpr *PE) {
+ return Visit(PE->getSubExpr());
+ }
+
+ llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ return Visit(E->getInitializer());
+ }
+
+ llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
+ if (E->getType()->isMemberPointerType())
+ return CGM.getMemberPointerConstant(E);
+
+ return 0;
+ }
+
+ llvm::Constant *VisitBinSub(BinaryOperator *E) {
+ // This must be a pointer/pointer subtraction. This only happens for
+ // address of label.
+ if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) ||
+ !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext())))
+ return 0;
+
+ llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(),
+ E->getLHS()->getType(), CGF);
+ llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(),
+ E->getRHS()->getType(), CGF);
+
+ const llvm::Type *ResultType = ConvertType(E->getType());
+ LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType);
+ RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType);
+
+ // No need to divide by element size, since addr of label is always void*,
+ // which has size 1 in GNUish.
+ return llvm::ConstantExpr::getSub(LHS, RHS);
+ }
+
+ llvm::Constant *VisitCastExpr(CastExpr* E) {
+ switch (E->getCastKind()) {
+ case CK_ToUnion: {
+ // GCC cast to union extension
+ assert(E->getType()->isUnionType() &&
+ "Destination type is not union type!");
+ const llvm::Type *Ty = ConvertType(E->getType());
+ Expr *SubExpr = E->getSubExpr();
+
+ llvm::Constant *C =
+ CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
+ if (!C)
+ return 0;
+
+ // Build a struct with the union sub-element as the first member,
+ // and padded to the appropriate size
+ std::vector<llvm::Constant*> Elts;
+ std::vector<const llvm::Type*> Types;
+ Elts.push_back(C);
+ Types.push_back(C->getType());
+ unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType());
+ unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty);
+
+ assert(CurSize <= TotalSize && "Union size mismatch!");
+ if (unsigned NumPadBytes = TotalSize - CurSize) {
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
+ if (NumPadBytes > 1)
+ Ty = llvm::ArrayType::get(Ty, NumPadBytes);
+
+ Elts.push_back(llvm::UndefValue::get(Ty));
+ Types.push_back(Ty);
+ }
+
+ llvm::StructType* STy =
+ llvm::StructType::get(C->getType()->getContext(), Types, false);
+ return llvm::ConstantStruct::get(STy, Elts);
+ }
+ case CK_NullToMemberPointer: {
+ const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ return CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ }
+
+ case CK_BaseToDerivedMemberPointer: {
+ Expr *SubExpr = E->getSubExpr();
+ llvm::Constant *C =
+ CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
+ if (!C) return 0;
+
+ return CGM.getCXXABI().EmitMemberPointerConversion(C, E);
+ }
+
+ case CK_BitCast:
+ // This must be a member function pointer cast.
+ return Visit(E->getSubExpr());
+
+ default: {
+ // FIXME: This should be handled by the CK_NoOp cast kind.
+ // Explicit and implicit no-op casts
+ QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType();
+ if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy))
+ return Visit(E->getSubExpr());
+
+ // Handle integer->integer casts for address-of-label differences.
+ if (Ty->isIntegerType() && SubTy->isIntegerType() &&
+ CGF) {
+ llvm::Value *Src = Visit(E->getSubExpr());
+ if (Src == 0) return 0;
+
+ // Use EmitScalarConversion to perform the conversion.
+ return cast<llvm::Constant>(CGF->EmitScalarConversion(Src, SubTy, Ty));
+ }
+
+ return 0;
+ }
+ }
+ }
+
+ llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
+
+ llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
+ unsigned NumInitElements = ILE->getNumInits();
+ if (NumInitElements == 1 &&
+ (isa<StringLiteral>(ILE->getInit(0)) ||
+ isa<ObjCEncodeExpr>(ILE->getInit(0))))
+ return Visit(ILE->getInit(0));
+
+ std::vector<llvm::Constant*> Elts;
+ const llvm::ArrayType *AType =
+ cast<llvm::ArrayType>(ConvertType(ILE->getType()));
+ const llvm::Type *ElemTy = AType->getElementType();
+ unsigned NumElements = AType->getNumElements();
+
+ // Initialising an array requires us to automatically
+ // initialise any elements that have not been initialised explicitly
+ unsigned NumInitableElts = std::min(NumInitElements, NumElements);
+
+ // Copy initializer elements.
+ unsigned i = 0;
+ bool RewriteType = false;
+ for (; i < NumInitableElts; ++i) {
+ Expr *Init = ILE->getInit(i);
+ llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
+ if (!C)
+ return 0;
+ RewriteType |= (C->getType() != ElemTy);
+ Elts.push_back(C);
+ }
+
+ // Initialize remaining array elements.
+ // FIXME: This doesn't handle member pointers correctly!
+ for (; i < NumElements; ++i)
+ Elts.push_back(llvm::Constant::getNullValue(ElemTy));
+
+ if (RewriteType) {
+ // FIXME: Try to avoid packing the array
+ std::vector<const llvm::Type*> Types;
+ for (unsigned i = 0; i < Elts.size(); ++i)
+ Types.push_back(Elts[i]->getType());
+ const llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
+ Types, true);
+ return llvm::ConstantStruct::get(SType, Elts);
+ }
+
+ return llvm::ConstantArray::get(AType, Elts);
+ }
+
+ llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
+ return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
+ }
+
+ llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
+ return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
+ }
+
+ llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) {
+ return CGM.EmitNullConstant(E->getType());
+ }
+
+ llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
+ if (ILE->getType()->isScalarType()) {
+ // We have a scalar in braces. Just use the first element.
+ if (ILE->getNumInits() > 0) {
+ Expr *Init = ILE->getInit(0);
+ return CGM.EmitConstantExpr(Init, Init->getType(), CGF);
+ }
+ return CGM.EmitNullConstant(ILE->getType());
+ }
+
+ if (ILE->getType()->isArrayType())
+ return EmitArrayInitialization(ILE);
+
+ if (ILE->getType()->isRecordType())
+ return EmitStructInitialization(ILE);
+
+ if (ILE->getType()->isUnionType())
+ return EmitUnionInitialization(ILE);
+
+ // If ILE was a constant vector, we would have handled it already.
+ if (ILE->getType()->isVectorType())
+ return 0;
+
+ assert(0 && "Unable to handle InitListExpr");
+ // Get rid of control reaches end of void function warning.
+ // Not reached.
+ return 0;
+ }
+
+ llvm::Constant *VisitCXXConstructExpr(CXXConstructExpr *E) {
+ if (!E->getConstructor()->isTrivial())
+ return 0;
+
+ QualType Ty = E->getType();
+
+ // FIXME: We should not have to call getBaseElementType here.
+ const RecordType *RT =
+ CGM.getContext().getBaseElementType(Ty)->getAs<RecordType>();
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ // If the class doesn't have a trivial destructor, we can't emit it as a
+ // constant expr.
+ if (!RD->hasTrivialDestructor())
+ return 0;
+
+ // Only copy and default constructors can be trivial.
+
+
+ if (E->getNumArgs()) {
+ assert(E->getNumArgs() == 1 && "trivial ctor with > 1 argument");
+ assert(E->getConstructor()->isCopyConstructor() &&
+ "trivial ctor has argument but isn't a copy ctor");
+
+ Expr *Arg = E->getArg(0);
+ assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) &&
+ "argument to copy ctor is of wrong type");
+
+ return Visit(Arg);
+ }
+
+ return CGM.EmitNullConstant(Ty);
+ }
+
+ llvm::Constant *VisitStringLiteral(StringLiteral *E) {
+ assert(!E->getType()->isPointerType() && "Strings are always arrays");
+
+ // This must be a string initializing an array in a static initializer.
+ // Don't emit it as the address of the string, emit the string data itself
+ // as an inline array.
+ return llvm::ConstantArray::get(VMContext,
+ CGM.GetStringForStringLiteral(E), false);
+ }
+
+ llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ // This must be an @encode initializing an array in a static initializer.
+ // Don't emit it as the address of the string, emit the string data itself
+ // as an inline array.
+ std::string Str;
+ CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType());
+
+ // Resize the string to the right size, adding zeros at the end, or
+ // truncating as needed.
+ Str.resize(CAT->getSize().getZExtValue(), '\0');
+ return llvm::ConstantArray::get(VMContext, Str, false);
+ }
+
+ llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) {
+ return Visit(E->getSubExpr());
+ }
+
+ // Utility methods
+ const llvm::Type *ConvertType(QualType T) {
+ return CGM.getTypes().ConvertType(T);
+ }
+
+public:
+ llvm::Constant *EmitLValue(Expr *E) {
+ switch (E->getStmtClass()) {
+ default: break;
+ case Expr::CompoundLiteralExprClass: {
+ // Note that due to the nature of compound literals, this is guaranteed
+ // to be the only use of the variable, so we just generate it here.
+ CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
+ llvm::Constant* C = Visit(CLE->getInitializer());
+ // FIXME: "Leaked" on failure.
+ if (C)
+ C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+ E->getType().isConstant(CGM.getContext()),
+ llvm::GlobalValue::InternalLinkage,
+ C, ".compoundliteral", 0, false,
+ E->getType().getAddressSpace());
+ return C;
+ }
+ case Expr::DeclRefExprClass: {
+ ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
+ if (Decl->hasAttr<WeakRefAttr>())
+ return CGM.GetWeakRefReference(Decl);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+ return CGM.GetAddrOfFunction(FD);
+ if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
+ // We can never refer to a variable with local storage.
+ if (!VD->hasLocalStorage()) {
+ if (VD->isFileVarDecl() || VD->hasExternalStorage())
+ return CGM.GetAddrOfGlobalVar(VD);
+ else if (VD->isLocalVarDecl()) {
+ assert(CGF && "Can't access static local vars without CGF");
+ return CGF->GetAddrOfStaticLocalVar(VD);
+ }
+ }
+ }
+ break;
+ }
+ case Expr::StringLiteralClass:
+ return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
+ case Expr::ObjCEncodeExprClass:
+ return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
+ case Expr::ObjCStringLiteralClass: {
+ ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
+ llvm::Constant *C =
+ CGM.getObjCRuntime().GenerateConstantString(SL->getString());
+ return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
+ }
+ case Expr::PredefinedExprClass: {
+ unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
+ if (CGF) {
+ LValue Res = CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E));
+ return cast<llvm::Constant>(Res.getAddress());
+ } else if (Type == PredefinedExpr::PrettyFunction) {
+ return CGM.GetAddrOfConstantCString("top level", ".tmp");
+ }
+
+ return CGM.GetAddrOfConstantCString("", ".tmp");
+ }
+ case Expr::AddrLabelExprClass: {
+ assert(CGF && "Invalid address of label expression outside function.");
+ llvm::Constant *Ptr =
+ CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
+ return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+ }
+ case Expr::CallExprClass: {
+ CallExpr* CE = cast<CallExpr>(E);
+ unsigned builtin = CE->isBuiltinCall(CGM.getContext());
+ if (builtin !=
+ Builtin::BI__builtin___CFStringMakeConstantString &&
+ builtin !=
+ Builtin::BI__builtin___NSStringMakeConstantString)
+ break;
+ const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
+ const StringLiteral *Literal = cast<StringLiteral>(Arg);
+ if (builtin ==
+ Builtin::BI__builtin___NSStringMakeConstantString) {
+ return CGM.getObjCRuntime().GenerateConstantString(Literal);
+ }
+ // FIXME: need to deal with UCN conversion issues.
+ return CGM.GetAddrOfConstantCFString(Literal);
+ }
+ case Expr::BlockExprClass: {
+ std::string FunctionName;
+ if (CGF)
+ FunctionName = CGF->CurFn->getName();
+ else
+ FunctionName = "global";
+
+ return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
+ }
+ }
+
+ return 0;
+ }
+};
+
+} // end anonymous namespace.
+
+llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
+ QualType DestType,
+ CodeGenFunction *CGF) {
+ Expr::EvalResult Result;
+
+ bool Success = false;
+
+ if (DestType->isReferenceType())
+ Success = E->EvaluateAsLValue(Result, Context);
+ else
+ Success = E->Evaluate(Result, Context);
+
+ if (Success && !Result.HasSideEffects) {
+ switch (Result.Val.getKind()) {
+ case APValue::Uninitialized:
+ assert(0 && "Constant expressions should be initialized.");
+ return 0;
+ case APValue::LValue: {
+ const llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
+ llvm::Constant *Offset =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ Result.Val.getLValueOffset().getQuantity());
+
+ llvm::Constant *C;
+ if (const Expr *LVBase = Result.Val.getLValueBase()) {
+ C = ConstExprEmitter(*this, CGF).EmitLValue(const_cast<Expr*>(LVBase));
+
+ // Apply offset if necessary.
+ if (!Offset->isNullValue()) {
+ const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
+ llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
+ Casted = llvm::ConstantExpr::getGetElementPtr(Casted, &Offset, 1);
+ C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
+ }
+
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer.
+ if (isa<llvm::PointerType>(DestTy))
+ return llvm::ConstantExpr::getBitCast(C, DestTy);
+
+ return llvm::ConstantExpr::getPtrToInt(C, DestTy);
+ } else {
+ C = Offset;
+
+ // Convert to the appropriate type; this could be an lvalue for
+ // an integer.
+ if (isa<llvm::PointerType>(DestTy))
+ return llvm::ConstantExpr::getIntToPtr(C, DestTy);
+
+ // If the types don't match this should only be a truncate.
+ if (C->getType() != DestTy)
+ return llvm::ConstantExpr::getTrunc(C, DestTy);
+
+ return C;
+ }
+ }
+ case APValue::Int: {
+ llvm::Constant *C = llvm::ConstantInt::get(VMContext,
+ Result.Val.getInt());
+
+ if (C->getType()->isIntegerTy(1)) {
+ const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ }
+ return C;
+ }
+ case APValue::ComplexInt: {
+ llvm::Constant *Complex[2];
+
+ Complex[0] = llvm::ConstantInt::get(VMContext,
+ Result.Val.getComplexIntReal());
+ Complex[1] = llvm::ConstantInt::get(VMContext,
+ Result.Val.getComplexIntImag());
+
+ // FIXME: the target may want to specify that this is packed.
+ return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
+ }
+ case APValue::Float:
+ return llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
+ case APValue::ComplexFloat: {
+ llvm::Constant *Complex[2];
+
+ Complex[0] = llvm::ConstantFP::get(VMContext,
+ Result.Val.getComplexFloatReal());
+ Complex[1] = llvm::ConstantFP::get(VMContext,
+ Result.Val.getComplexFloatImag());
+
+ // FIXME: the target may want to specify that this is packed.
+ return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
+ }
+ case APValue::Vector: {
+ llvm::SmallVector<llvm::Constant *, 4> Inits;
+ unsigned NumElts = Result.Val.getVectorLength();
+
+ for (unsigned i = 0; i != NumElts; ++i) {
+ APValue &Elt = Result.Val.getVectorElt(i);
+ if (Elt.isInt())
+ Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
+ else
+ Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
+ }
+ return llvm::ConstantVector::get(Inits);
+ }
+ }
+ }
+
+ llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+ if (C && C->getType()->isIntegerTy(1)) {
+ const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+ C = llvm::ConstantExpr::getZExt(C, BoolTy);
+ }
+ return C;
+}
+
+static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) {
+ const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent());
+ return layout.getFieldOffset(field->getFieldIndex());
+}
+
+llvm::Constant *
+CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
+ // Member pointer constants always have a very particular form.
+ const MemberPointerType *type = cast<MemberPointerType>(uo->getType());
+ const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl();
+
+ // A member function pointer.
+ if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
+ return getCXXABI().EmitMemberPointer(method);
+
+ // Otherwise, a member data pointer.
+ uint64_t fieldOffset;
+ if (const FieldDecl *field = dyn_cast<FieldDecl>(decl))
+ fieldOffset = getFieldOffset(getContext(), field);
+ else {
+ const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl);
+
+ fieldOffset = 0;
+ for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(),
+ ce = ifield->chain_end(); ci != ce; ++ci)
+ fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci));
+ }
+
+ CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset);
+ return getCXXABI().EmitMemberDataPointer(type, chars);
+}
+
+static void
+FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
+ std::vector<llvm::Constant *> &Elements,
+ uint64_t StartOffset) {
+ assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!");
+
+ if (CGM.getTypes().isZeroInitializable(T))
+ return;
+
+ if (const ConstantArrayType *CAT =
+ CGM.getContext().getAsConstantArrayType(T)) {
+ QualType ElementTy = CAT->getElementType();
+ uint64_t ElementSize = CGM.getContext().getTypeSize(ElementTy);
+
+ for (uint64_t I = 0, E = CAT->getSize().getZExtValue(); I != E; ++I) {
+ FillInNullDataMemberPointers(CGM, ElementTy, Elements,
+ StartOffset + I * ElementSize);
+ }
+ } else if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ // Go through all bases and fill in any null pointer to data members.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual()) {
+ // Ignore virtual bases.
+ continue;
+ }
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore empty bases.
+ if (BaseDecl->isEmpty())
+ continue;
+
+ // Ignore bases that don't have any pointer to data members.
+ if (CGM.getTypes().isZeroInitializable(BaseDecl))
+ continue;
+
+ uint64_t BaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl);
+ FillInNullDataMemberPointers(CGM, I->getType(),
+ Elements, StartOffset + BaseOffset);
+ }
+
+ // Visit all fields.
+ unsigned FieldNo = 0;
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I, ++FieldNo) {
+ QualType FieldType = I->getType();
+
+ if (CGM.getTypes().isZeroInitializable(FieldType))
+ continue;
+
+ uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo);
+ FillInNullDataMemberPointers(CGM, FieldType, Elements, FieldOffset);
+ }
+ } else {
+ assert(T->isMemberPointerType() && "Should only see member pointers here!");
+ assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
+ "Should only see pointers to data members here!");
+
+ uint64_t StartIndex = StartOffset / 8;
+ uint64_t EndIndex = StartIndex + CGM.getContext().getTypeSize(T) / 8;
+
+ // FIXME: hardcodes Itanium member pointer representation!
+ llvm::Constant *NegativeOne =
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(CGM.getLLVMContext()),
+ -1ULL, /*isSigned*/true);
+
+ // Fill in the null data member pointer.
+ for (uint64_t I = StartIndex; I != EndIndex; ++I)
+ Elements[I] = NegativeOne;
+ }
+}
+
+static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
+ const llvm::Type *baseType,
+ const CXXRecordDecl *base);
+
+static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
+ const CXXRecordDecl *record,
+ bool asCompleteObject) {
+ const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record);
+ const llvm::StructType *structure =
+ (asCompleteObject ? layout.getLLVMType()
+ : layout.getBaseSubobjectLLVMType());
+
+ unsigned numElements = structure->getNumElements();
+ std::vector<llvm::Constant *> elements(numElements);
+
+ // Fill in all the bases.
+ for (CXXRecordDecl::base_class_const_iterator
+ I = record->bases_begin(), E = record->bases_end(); I != E; ++I) {
+ if (I->isVirtual()) {
+ // Ignore virtual bases; if we're laying out for a complete
+ // object, we'll lay these out later.
+ continue;
+ }
+
+ const CXXRecordDecl *base =
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
+
+ // Ignore empty bases.
+ if (base->isEmpty())
+ continue;
+
+ unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base);
+ const llvm::Type *baseType = structure->getElementType(fieldIndex);
+ elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
+ }
+
+ // Fill in all the fields.
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end(); I != E; ++I) {
+ const FieldDecl *field = *I;
+
+ // Ignore bit fields.
+ if (field->isBitField())
+ continue;
+
+ unsigned fieldIndex = layout.getLLVMFieldNo(field);
+ elements[fieldIndex] = CGM.EmitNullConstant(field->getType());
+ }
+
+ // Fill in the virtual bases, if we're working with the complete object.
+ if (asCompleteObject) {
+ for (CXXRecordDecl::base_class_const_iterator
+ I = record->vbases_begin(), E = record->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *base =
+ cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl());
+
+ // Ignore empty bases.
+ if (base->isEmpty())
+ continue;
+
+ unsigned fieldIndex = layout.getVirtualBaseIndex(base);
+
+ // We might have already laid this field out.
+ if (elements[fieldIndex]) continue;
+
+ const llvm::Type *baseType = structure->getElementType(fieldIndex);
+ elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
+ }
+ }
+
+ // Now go through all other fields and zero them out.
+ for (unsigned i = 0; i != numElements; ++i) {
+ if (!elements[i])
+ elements[i] = llvm::Constant::getNullValue(structure->getElementType(i));
+ }
+
+ return llvm::ConstantStruct::get(structure, elements);
+}
+
+/// Emit the null constant for a base subobject.
+static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
+ const llvm::Type *baseType,
+ const CXXRecordDecl *base) {
+ const CGRecordLayout &baseLayout = CGM.getTypes().getCGRecordLayout(base);
+
+ // Just zero out bases that don't have any pointer to data members.
+ if (baseLayout.isZeroInitializableAsBase())
+ return llvm::Constant::getNullValue(baseType);
+
+ // If the base type is a struct, we can just use its null constant.
+ if (isa<llvm::StructType>(baseType)) {
+ return EmitNullConstant(CGM, base, /*complete*/ false);
+ }
+
+ // Otherwise, some bases are represented as arrays of i8 if the size
+ // of the base is smaller than its corresponding LLVM type. Figure
+ // out how many elements this base array has.
+ const llvm::ArrayType *baseArrayType = cast<llvm::ArrayType>(baseType);
+ unsigned numBaseElements = baseArrayType->getNumElements();
+
+ // Fill in null data member pointers.
+ std::vector<llvm::Constant *> baseElements(numBaseElements);
+ FillInNullDataMemberPointers(CGM, CGM.getContext().getTypeDeclType(base),
+ baseElements, 0);
+
+ // Now go through all other elements and zero them out.
+ if (numBaseElements) {
+ const llvm::Type *i8 = llvm::Type::getInt8Ty(CGM.getLLVMContext());
+ llvm::Constant *i8_zero = llvm::Constant::getNullValue(i8);
+ for (unsigned i = 0; i != numBaseElements; ++i) {
+ if (!baseElements[i])
+ baseElements[i] = i8_zero;
+ }
+ }
+
+ return llvm::ConstantArray::get(baseArrayType, baseElements);
+}
+
+llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
+ if (getTypes().isZeroInitializable(T))
+ return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
+
+ if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
+
+ QualType ElementTy = CAT->getElementType();
+
+ llvm::Constant *Element = EmitNullConstant(ElementTy);
+ unsigned NumElements = CAT->getSize().getZExtValue();
+ std::vector<llvm::Constant *> Array(NumElements);
+ for (unsigned i = 0; i != NumElements; ++i)
+ Array[i] = Element;
+
+ const llvm::ArrayType *ATy =
+ cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
+ return llvm::ConstantArray::get(ATy, Array);
+ }
+
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ return ::EmitNullConstant(*this, RD, /*complete object*/ true);
+ }
+
+ assert(T->isMemberPointerType() && "Should only see member pointers here!");
+ assert(!T->getAs<MemberPointerType>()->getPointeeType()->isFunctionType() &&
+ "Should only see pointers to data members here!");
+
+ // Itanium C++ ABI 2.3:
+ // A NULL pointer is represented as -1.
+ return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>());
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
new file mode 100644
index 0000000..3e1debd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -0,0 +1,2655 @@
+//===--- CGExprScalar.cpp - Emit LLVM Code for Scalar Exprs ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Expr nodes with scalar LLVM types as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CodeGenOptions.h"
+#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "CodeGenModule.h"
+#include "CGDebugInfo.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Target/TargetData.h"
+#include <cstdarg>
+
+using namespace clang;
+using namespace CodeGen;
+using llvm::Value;
+
+//===----------------------------------------------------------------------===//
+// Scalar Expression Emitter
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct BinOpInfo {
+ Value *LHS;
+ Value *RHS;
+ QualType Ty; // Computation Type.
+ BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform
+ const Expr *E; // Entire expr, for error unsupported. May not be binop.
+};
+
+static bool MustVisitNullValue(const Expr *E) {
+ // If a null pointer expression's type is the C++0x nullptr_t, then
+ // it's not necessarily a simple constant and it must be evaluated
+ // for its potential side effects.
+ return E->getType()->isNullPtrType();
+}
+
+class ScalarExprEmitter
+ : public StmtVisitor<ScalarExprEmitter, Value*> {
+ CodeGenFunction &CGF;
+ CGBuilderTy &Builder;
+ bool IgnoreResultAssign;
+ llvm::LLVMContext &VMContext;
+public:
+
+ ScalarExprEmitter(CodeGenFunction &cgf, bool ira=false)
+ : CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira),
+ VMContext(cgf.getLLVMContext()) {
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Utilities
+ //===--------------------------------------------------------------------===//
+
+ bool TestAndClearIgnoreResultAssign() {
+ bool I = IgnoreResultAssign;
+ IgnoreResultAssign = false;
+ return I;
+ }
+
+ const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); }
+ LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); }
+ LValue EmitCheckedLValue(const Expr *E) { return CGF.EmitCheckedLValue(E); }
+
+ Value *EmitLoadOfLValue(LValue LV, QualType T) {
+ return CGF.EmitLoadOfLValue(LV, T).getScalarVal();
+ }
+
+ /// EmitLoadOfLValue - Given an expression with complex type that represents a
+ /// value l-value, this method emits the address of the l-value, then loads
+ /// and returns the result.
+ Value *EmitLoadOfLValue(const Expr *E) {
+ return EmitLoadOfLValue(EmitCheckedLValue(E), E->getType());
+ }
+
+ /// EmitConversionToBool - Convert the specified expression value to a
+ /// boolean (i1) truth value. This is equivalent to "Val != 0".
+ Value *EmitConversionToBool(Value *Src, QualType DstTy);
+
+ /// EmitScalarConversion - Emit a conversion from the specified type to the
+ /// specified destination type, both of which are LLVM scalar types.
+ Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy);
+
+ /// EmitComplexToScalarConversion - Emit a conversion from the specified
+ /// complex type to the specified destination type, where the destination type
+ /// is an LLVM scalar type.
+ Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
+ QualType SrcTy, QualType DstTy);
+
+ /// EmitNullValue - Emit a value that corresponds to null for the given type.
+ Value *EmitNullValue(QualType Ty);
+
+ /// EmitFloatToBoolConversion - Perform an FP to boolean conversion.
+ Value *EmitFloatToBoolConversion(Value *V) {
+ // Compare against 0.0 for fp scalars.
+ llvm::Value *Zero = llvm::Constant::getNullValue(V->getType());
+ return Builder.CreateFCmpUNE(V, Zero, "tobool");
+ }
+
+ /// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
+ Value *EmitPointerToBoolConversion(Value *V) {
+ Value *Zero = llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(V->getType()));
+ return Builder.CreateICmpNE(V, Zero, "tobool");
+ }
+
+ Value *EmitIntToBoolConversion(Value *V) {
+ // Because of the type rules of C, we often end up computing a
+ // logical value, then zero extending it to int, then wanting it
+ // as a logical value again. Optimize this common case.
+ if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(V)) {
+ if (ZI->getOperand(0)->getType() == Builder.getInt1Ty()) {
+ Value *Result = ZI->getOperand(0);
+ // If there aren't any more uses, zap the instruction to save space.
+ // Note that there can be more uses, for example if this
+ // is the result of an assignment.
+ if (ZI->use_empty())
+ ZI->eraseFromParent();
+ return Result;
+ }
+ }
+
+ const llvm::IntegerType *Ty = cast<llvm::IntegerType>(V->getType());
+ Value *Zero = llvm::ConstantInt::get(Ty, 0);
+ return Builder.CreateICmpNE(V, Zero, "tobool");
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Visitor Methods
+ //===--------------------------------------------------------------------===//
+
+ Value *Visit(Expr *E) {
+ return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E);
+ }
+
+ Value *VisitStmt(Stmt *S) {
+ S->dump(CGF.getContext().getSourceManager());
+ assert(0 && "Stmt can't have complex result type!");
+ return 0;
+ }
+ Value *VisitExpr(Expr *S);
+
+ Value *VisitParenExpr(ParenExpr *PE) {
+ return Visit(PE->getSubExpr());
+ }
+
+ // Leaves.
+ Value *VisitIntegerLiteral(const IntegerLiteral *E) {
+ return llvm::ConstantInt::get(VMContext, E->getValue());
+ }
+ Value *VisitFloatingLiteral(const FloatingLiteral *E) {
+ return llvm::ConstantFP::get(VMContext, E->getValue());
+ }
+ Value *VisitCharacterLiteral(const CharacterLiteral *E) {
+ return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
+ }
+ Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
+ return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
+ }
+ Value *VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
+ return EmitNullValue(E->getType());
+ }
+ Value *VisitGNUNullExpr(const GNUNullExpr *E) {
+ return EmitNullValue(E->getType());
+ }
+ Value *VisitOffsetOfExpr(OffsetOfExpr *E);
+ Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
+ Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
+ llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
+ return Builder.CreateBitCast(V, ConvertType(E->getType()));
+ }
+
+ Value *VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ return llvm::ConstantInt::get(ConvertType(E->getType()),
+ E->getPackLength());
+ }
+
+ Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ if (E->isGLValue())
+ return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getType());
+
+ // Otherwise, assume the mapping is the scalar directly.
+ return CGF.getOpaqueRValueMapping(E).getScalarVal();
+ }
+
+ // l-values.
+ Value *VisitDeclRefExpr(DeclRefExpr *E) {
+ Expr::EvalResult Result;
+ if (!E->Evaluate(Result, CGF.getContext()))
+ return EmitLoadOfLValue(E);
+
+ assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
+
+ llvm::Constant *C;
+ if (Result.Val.isInt()) {
+ C = llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+ } else if (Result.Val.isFloat()) {
+ C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
+ } else {
+ return EmitLoadOfLValue(E);
+ }
+
+ // Make sure we emit a debug reference to the global variable.
+ if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (!CGF.getContext().DeclMustBeEmitted(VD))
+ CGF.EmitDeclRefExprDbgValue(E, C);
+ } else if (isa<EnumConstantDecl>(E->getDecl())) {
+ CGF.EmitDeclRefExprDbgValue(E, C);
+ }
+
+ return C;
+ }
+ Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+ return CGF.EmitObjCSelectorExpr(E);
+ }
+ Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+ return CGF.EmitObjCProtocolExpr(E);
+ }
+ Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ return EmitLoadOfLValue(E);
+ }
+ Value *VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ assert(E->getObjectKind() == OK_Ordinary &&
+ "reached property reference without lvalue-to-rvalue");
+ return EmitLoadOfLValue(E);
+ }
+ Value *VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ return CGF.EmitObjCMessageExpr(E).getScalarVal();
+ }
+
+ Value *VisitObjCIsaExpr(ObjCIsaExpr *E) {
+ LValue LV = CGF.EmitObjCIsaExpr(E);
+ Value *V = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal();
+ return V;
+ }
+
+ Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+ Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+ Value *VisitMemberExpr(MemberExpr *E);
+ Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
+ Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ return EmitLoadOfLValue(E);
+ }
+
+ Value *VisitInitListExpr(InitListExpr *E);
+
+ Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
+ return CGF.CGM.EmitNullConstant(E->getType());
+ }
+ Value *VisitCastExpr(CastExpr *E) {
+ // Make sure to evaluate VLA bounds now so that we have them for later.
+ if (E->getType()->isVariablyModifiedType())
+ CGF.EmitVLASize(E->getType());
+
+ return EmitCastExpr(E);
+ }
+ Value *EmitCastExpr(CastExpr *E);
+
+ Value *VisitCallExpr(const CallExpr *E) {
+ if (E->getCallReturnType()->isReferenceType())
+ return EmitLoadOfLValue(E);
+
+ return CGF.EmitCallExpr(E).getScalarVal();
+ }
+
+ Value *VisitStmtExpr(const StmtExpr *E);
+
+ Value *VisitBlockDeclRefExpr(const BlockDeclRefExpr *E);
+
+ // Unary Operators.
+ Value *VisitUnaryPostDec(const UnaryOperator *E) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ return EmitScalarPrePostIncDec(E, LV, false, false);
+ }
+ Value *VisitUnaryPostInc(const UnaryOperator *E) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ return EmitScalarPrePostIncDec(E, LV, true, false);
+ }
+ Value *VisitUnaryPreDec(const UnaryOperator *E) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ return EmitScalarPrePostIncDec(E, LV, false, true);
+ }
+ Value *VisitUnaryPreInc(const UnaryOperator *E) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ return EmitScalarPrePostIncDec(E, LV, true, true);
+ }
+
+ llvm::Value *EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
+ llvm::Value *InVal,
+ llvm::Value *NextVal,
+ bool IsInc);
+
+ llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre);
+
+
+ Value *VisitUnaryAddrOf(const UnaryOperator *E) {
+ if (isa<MemberPointerType>(E->getType())) // never sugared
+ return CGF.CGM.getMemberPointerConstant(E);
+
+ return EmitLValue(E->getSubExpr()).getAddress();
+ }
+ Value *VisitUnaryDeref(const UnaryOperator *E) {
+ if (E->getType()->isVoidType())
+ return Visit(E->getSubExpr()); // the actual value should be unused
+ return EmitLoadOfLValue(E);
+ }
+ Value *VisitUnaryPlus(const UnaryOperator *E) {
+ // This differs from gcc, though, most likely due to a bug in gcc.
+ TestAndClearIgnoreResultAssign();
+ return Visit(E->getSubExpr());
+ }
+ Value *VisitUnaryMinus (const UnaryOperator *E);
+ Value *VisitUnaryNot (const UnaryOperator *E);
+ Value *VisitUnaryLNot (const UnaryOperator *E);
+ Value *VisitUnaryReal (const UnaryOperator *E);
+ Value *VisitUnaryImag (const UnaryOperator *E);
+ Value *VisitUnaryExtension(const UnaryOperator *E) {
+ return Visit(E->getSubExpr());
+ }
+
+ // C++
+ Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
+ return Visit(DAE->getExpr());
+ }
+ Value *VisitCXXThisExpr(CXXThisExpr *TE) {
+ return CGF.LoadCXXThis();
+ }
+
+ Value *VisitExprWithCleanups(ExprWithCleanups *E) {
+ return CGF.EmitExprWithCleanups(E).getScalarVal();
+ }
+ Value *VisitCXXNewExpr(const CXXNewExpr *E) {
+ return CGF.EmitCXXNewExpr(E);
+ }
+ Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
+ CGF.EmitCXXDeleteExpr(E);
+ return 0;
+ }
+ Value *VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
+ return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
+ }
+
+ Value *VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+ return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
+ }
+
+ Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
+ // C++ [expr.pseudo]p1:
+ // The result shall only be used as the operand for the function call
+ // operator (), and the result of such a call has type void. The only
+ // effect is the evaluation of the postfix-expression before the dot or
+ // arrow.
+ CGF.EmitScalarExpr(E->getBase());
+ return 0;
+ }
+
+ Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
+ return EmitNullValue(E->getType());
+ }
+
+ Value *VisitCXXThrowExpr(const CXXThrowExpr *E) {
+ CGF.EmitCXXThrowExpr(E);
+ return 0;
+ }
+
+ Value *VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
+ return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
+ }
+
+ // Binary Operators.
+ Value *EmitMul(const BinOpInfo &Ops) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
+ switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+ case LangOptions::SOB_Undefined:
+ return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+ case LangOptions::SOB_Defined:
+ return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+ case LangOptions::SOB_Trapping:
+ return EmitOverflowCheckedBinOp(Ops);
+ }
+ }
+
+ if (Ops.LHS->getType()->isFPOrFPVectorTy())
+ return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
+ return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+ }
+ bool isTrapvOverflowBehavior() {
+ return CGF.getContext().getLangOptions().getSignedOverflowBehavior()
+ == LangOptions::SOB_Trapping;
+ }
+ /// Create a binary op that checks for overflow.
+ /// Currently only supports +, - and *.
+ Value *EmitOverflowCheckedBinOp(const BinOpInfo &Ops);
+ // Emit the overflow BB when -ftrapv option is activated.
+ void EmitOverflowBB(llvm::BasicBlock *overflowBB) {
+ Builder.SetInsertPoint(overflowBB);
+ llvm::Function *Trap = CGF.CGM.getIntrinsic(llvm::Intrinsic::trap);
+ Builder.CreateCall(Trap);
+ Builder.CreateUnreachable();
+ }
+ // Check for undefined division and modulus behaviors.
+ void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
+ llvm::Value *Zero,bool isDiv);
+ Value *EmitDiv(const BinOpInfo &Ops);
+ Value *EmitRem(const BinOpInfo &Ops);
+ Value *EmitAdd(const BinOpInfo &Ops);
+ Value *EmitSub(const BinOpInfo &Ops);
+ Value *EmitShl(const BinOpInfo &Ops);
+ Value *EmitShr(const BinOpInfo &Ops);
+ Value *EmitAnd(const BinOpInfo &Ops) {
+ return Builder.CreateAnd(Ops.LHS, Ops.RHS, "and");
+ }
+ Value *EmitXor(const BinOpInfo &Ops) {
+ return Builder.CreateXor(Ops.LHS, Ops.RHS, "xor");
+ }
+ Value *EmitOr (const BinOpInfo &Ops) {
+ return Builder.CreateOr(Ops.LHS, Ops.RHS, "or");
+ }
+
+ BinOpInfo EmitBinOps(const BinaryOperator *E);
+ LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
+ Value *(ScalarExprEmitter::*F)(const BinOpInfo &),
+ Value *&Result);
+
+ Value *EmitCompoundAssign(const CompoundAssignOperator *E,
+ Value *(ScalarExprEmitter::*F)(const BinOpInfo &));
+
+ // Binary operators and binary compound assignment operators.
+#define HANDLEBINOP(OP) \
+ Value *VisitBin ## OP(const BinaryOperator *E) { \
+ return Emit ## OP(EmitBinOps(E)); \
+ } \
+ Value *VisitBin ## OP ## Assign(const CompoundAssignOperator *E) { \
+ return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP); \
+ }
+ HANDLEBINOP(Mul)
+ HANDLEBINOP(Div)
+ HANDLEBINOP(Rem)
+ HANDLEBINOP(Add)
+ HANDLEBINOP(Sub)
+ HANDLEBINOP(Shl)
+ HANDLEBINOP(Shr)
+ HANDLEBINOP(And)
+ HANDLEBINOP(Xor)
+ HANDLEBINOP(Or)
+#undef HANDLEBINOP
+
+ // Comparisons.
+ Value *EmitCompare(const BinaryOperator *E, unsigned UICmpOpc,
+ unsigned SICmpOpc, unsigned FCmpOpc);
+#define VISITCOMP(CODE, UI, SI, FP) \
+ Value *VisitBin##CODE(const BinaryOperator *E) { \
+ return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \
+ llvm::FCmpInst::FP); }
+ VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT)
+ VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT)
+ VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE)
+ VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE)
+ VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ)
+ VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE)
+#undef VISITCOMP
+
+ Value *VisitBinAssign (const BinaryOperator *E);
+
+ Value *VisitBinLAnd (const BinaryOperator *E);
+ Value *VisitBinLOr (const BinaryOperator *E);
+ Value *VisitBinComma (const BinaryOperator *E);
+
+ Value *VisitBinPtrMemD(const Expr *E) { return EmitLoadOfLValue(E); }
+ Value *VisitBinPtrMemI(const Expr *E) { return EmitLoadOfLValue(E); }
+
+ // Other Operators.
+ Value *VisitBlockExpr(const BlockExpr *BE);
+ Value *VisitAbstractConditionalOperator(const AbstractConditionalOperator *);
+ Value *VisitChooseExpr(ChooseExpr *CE);
+ Value *VisitVAArgExpr(VAArgExpr *VE);
+ Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
+ return CGF.EmitObjCStringLiteral(E);
+ }
+};
+} // end anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// EmitConversionToBool - Convert the specified expression value to a
+/// boolean (i1) truth value. This is equivalent to "Val != 0".
+Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
+ assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
+
+ if (SrcType->isRealFloatingType())
+ return EmitFloatToBoolConversion(Src);
+
+ if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
+
+ assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
+ "Unknown scalar type to convert");
+
+ if (isa<llvm::IntegerType>(Src->getType()))
+ return EmitIntToBoolConversion(Src);
+
+ assert(isa<llvm::PointerType>(Src->getType()));
+ return EmitPointerToBoolConversion(Src);
+}
+
+/// EmitScalarConversion - Emit a conversion from the specified type to the
+/// specified destination type, both of which are LLVM scalar types.
+Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
+ QualType DstType) {
+ SrcType = CGF.getContext().getCanonicalType(SrcType);
+ DstType = CGF.getContext().getCanonicalType(DstType);
+ if (SrcType == DstType) return Src;
+
+ if (DstType->isVoidType()) return 0;
+
+ // Handle conversions to bool first, they are special: comparisons against 0.
+ if (DstType->isBooleanType())
+ return EmitConversionToBool(Src, SrcType);
+
+ const llvm::Type *DstTy = ConvertType(DstType);
+
+ // Ignore conversions like int -> uint.
+ if (Src->getType() == DstTy)
+ return Src;
+
+ // Handle pointer conversions next: pointers can only be converted to/from
+ // other pointers and integers. Check for pointer types in terms of LLVM, as
+ // some native types (like Obj-C id) may map to a pointer type.
+ if (isa<llvm::PointerType>(DstTy)) {
+ // The source value may be an integer, or a pointer.
+ if (isa<llvm::PointerType>(Src->getType()))
+ return Builder.CreateBitCast(Src, DstTy, "conv");
+
+ assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
+ // First, convert to the correct width so that we control the kind of
+ // extension.
+ const llvm::Type *MiddleTy = CGF.IntPtrTy;
+ bool InputSigned = SrcType->isSignedIntegerType();
+ llvm::Value* IntResult =
+ Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
+ // Then, cast to pointer.
+ return Builder.CreateIntToPtr(IntResult, DstTy, "conv");
+ }
+
+ if (isa<llvm::PointerType>(Src->getType())) {
+ // Must be an ptr to int cast.
+ assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?");
+ return Builder.CreatePtrToInt(Src, DstTy, "conv");
+ }
+
+ // A scalar can be splatted to an extended vector of the same element type
+ if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
+ // Cast the scalar to element type
+ QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType();
+ llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
+
+ // Insert the element in element zero of an undef vector
+ llvm::Value *UnV = llvm::UndefValue::get(DstTy);
+ llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0);
+ UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
+
+ // Splat the element across to all elements
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+ unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+ for (unsigned i = 0; i != NumElements; ++i)
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
+
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
+ return Yay;
+ }
+
+ // Allow bitcast from vector to integer/fp of the same size.
+ if (isa<llvm::VectorType>(Src->getType()) ||
+ isa<llvm::VectorType>(DstTy))
+ return Builder.CreateBitCast(Src, DstTy, "conv");
+
+ // Finally, we have the arithmetic types: real int/float.
+ if (isa<llvm::IntegerType>(Src->getType())) {
+ bool InputSigned = SrcType->isSignedIntegerType();
+ if (isa<llvm::IntegerType>(DstTy))
+ return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
+ else if (InputSigned)
+ return Builder.CreateSIToFP(Src, DstTy, "conv");
+ else
+ return Builder.CreateUIToFP(Src, DstTy, "conv");
+ }
+
+ assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion");
+ if (isa<llvm::IntegerType>(DstTy)) {
+ if (DstType->isSignedIntegerType())
+ return Builder.CreateFPToSI(Src, DstTy, "conv");
+ else
+ return Builder.CreateFPToUI(Src, DstTy, "conv");
+ }
+
+ assert(DstTy->isFloatingPointTy() && "Unknown real conversion");
+ if (DstTy->getTypeID() < Src->getType()->getTypeID())
+ return Builder.CreateFPTrunc(Src, DstTy, "conv");
+ else
+ return Builder.CreateFPExt(Src, DstTy, "conv");
+}
+
+/// EmitComplexToScalarConversion - Emit a conversion from the specified complex
+/// type to the specified destination type, where the destination type is an
+/// LLVM scalar type.
+Value *ScalarExprEmitter::
+EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
+ QualType SrcTy, QualType DstTy) {
+ // Get the source element type.
+ SrcTy = SrcTy->getAs<ComplexType>()->getElementType();
+
+ // Handle conversions to bool first, they are special: comparisons against 0.
+ if (DstTy->isBooleanType()) {
+ // Complex != 0 -> (Real != 0) | (Imag != 0)
+ Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy);
+ Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy);
+ return Builder.CreateOr(Src.first, Src.second, "tobool");
+ }
+
+ // C99 6.3.1.7p2: "When a value of complex type is converted to a real type,
+ // the imaginary part of the complex value is discarded and the value of the
+ // real part is converted according to the conversion rules for the
+ // corresponding real type.
+ return EmitScalarConversion(Src.first, SrcTy, DstTy);
+}
+
+Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
+
+ return llvm::Constant::getNullValue(ConvertType(Ty));
+}
+
+//===----------------------------------------------------------------------===//
+// Visitor Methods
+//===----------------------------------------------------------------------===//
+
+Value *ScalarExprEmitter::VisitExpr(Expr *E) {
+ CGF.ErrorUnsupported(E, "scalar expression");
+ if (E->getType()->isVoidType())
+ return 0;
+ return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
+}
+
+Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+ // Vector Mask Case
+ if (E->getNumSubExprs() == 2 ||
+ (E->getNumSubExprs() == 3 && E->getExpr(2)->getType()->isVectorType())) {
+ Value *LHS = CGF.EmitScalarExpr(E->getExpr(0));
+ Value *RHS = CGF.EmitScalarExpr(E->getExpr(1));
+ Value *Mask;
+
+ const llvm::VectorType *LTy = cast<llvm::VectorType>(LHS->getType());
+ unsigned LHSElts = LTy->getNumElements();
+
+ if (E->getNumSubExprs() == 3) {
+ Mask = CGF.EmitScalarExpr(E->getExpr(2));
+
+ // Shuffle LHS & RHS into one input vector.
+ llvm::SmallVector<llvm::Constant*, 32> concat;
+ for (unsigned i = 0; i != LHSElts; ++i) {
+ concat.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 2*i));
+ concat.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 2*i+1));
+ }
+
+ Value* CV = llvm::ConstantVector::get(concat);
+ LHS = Builder.CreateShuffleVector(LHS, RHS, CV, "concat");
+ LHSElts *= 2;
+ } else {
+ Mask = RHS;
+ }
+
+ const llvm::VectorType *MTy = cast<llvm::VectorType>(Mask->getType());
+ llvm::Constant* EltMask;
+
+ // Treat vec3 like vec4.
+ if ((LHSElts == 6) && (E->getNumSubExprs() == 3))
+ EltMask = llvm::ConstantInt::get(MTy->getElementType(),
+ (1 << llvm::Log2_32(LHSElts+2))-1);
+ else if ((LHSElts == 3) && (E->getNumSubExprs() == 2))
+ EltMask = llvm::ConstantInt::get(MTy->getElementType(),
+ (1 << llvm::Log2_32(LHSElts+1))-1);
+ else
+ EltMask = llvm::ConstantInt::get(MTy->getElementType(),
+ (1 << llvm::Log2_32(LHSElts))-1);
+
+ // Mask off the high bits of each shuffle index.
+ llvm::SmallVector<llvm::Constant *, 32> MaskV;
+ for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i)
+ MaskV.push_back(EltMask);
+
+ Value* MaskBits = llvm::ConstantVector::get(MaskV);
+ Mask = Builder.CreateAnd(Mask, MaskBits, "mask");
+
+ // newv = undef
+ // mask = mask & maskbits
+ // for each elt
+ // n = extract mask i
+ // x = extract val n
+ // newv = insert newv, x, i
+ const llvm::VectorType *RTy = llvm::VectorType::get(LTy->getElementType(),
+ MTy->getNumElements());
+ Value* NewV = llvm::UndefValue::get(RTy);
+ for (unsigned i = 0, e = MTy->getNumElements(); i != e; ++i) {
+ Value *Indx = llvm::ConstantInt::get(CGF.Int32Ty, i);
+ Indx = Builder.CreateExtractElement(Mask, Indx, "shuf_idx");
+ Indx = Builder.CreateZExt(Indx, CGF.Int32Ty, "idx_zext");
+
+ // Handle vec3 special since the index will be off by one for the RHS.
+ if ((LHSElts == 6) && (E->getNumSubExprs() == 3)) {
+ Value *cmpIndx, *newIndx;
+ cmpIndx = Builder.CreateICmpUGT(Indx,
+ llvm::ConstantInt::get(CGF.Int32Ty, 3),
+ "cmp_shuf_idx");
+ newIndx = Builder.CreateSub(Indx, llvm::ConstantInt::get(CGF.Int32Ty,1),
+ "shuf_idx_adj");
+ Indx = Builder.CreateSelect(cmpIndx, newIndx, Indx, "sel_shuf_idx");
+ }
+ Value *VExt = Builder.CreateExtractElement(LHS, Indx, "shuf_elt");
+ NewV = Builder.CreateInsertElement(NewV, VExt, Indx, "shuf_ins");
+ }
+ return NewV;
+ }
+
+ Value* V1 = CGF.EmitScalarExpr(E->getExpr(0));
+ Value* V2 = CGF.EmitScalarExpr(E->getExpr(1));
+
+ // Handle vec3 special since the index will be off by one for the RHS.
+ llvm::SmallVector<llvm::Constant*, 32> indices;
+ for (unsigned i = 2; i < E->getNumSubExprs(); i++) {
+ llvm::Constant *C = cast<llvm::Constant>(CGF.EmitScalarExpr(E->getExpr(i)));
+ const llvm::VectorType *VTy = cast<llvm::VectorType>(V1->getType());
+ if (VTy->getNumElements() == 3) {
+ if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) {
+ uint64_t cVal = CI->getZExtValue();
+ if (cVal > 3) {
+ C = llvm::ConstantInt::get(C->getType(), cVal-1);
+ }
+ }
+ }
+ indices.push_back(C);
+ }
+
+ Value *SV = llvm::ConstantVector::get(indices);
+ return Builder.CreateShuffleVector(V1, V2, SV, "shuffle");
+}
+Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
+ Expr::EvalResult Result;
+ if (E->Evaluate(Result, CGF.getContext()) && Result.Val.isInt()) {
+ if (E->isArrow())
+ CGF.EmitScalarExpr(E->getBase());
+ else
+ EmitLValue(E->getBase());
+ return llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+ }
+
+ // Emit debug info for aggregate now, if it was delayed to reduce
+ // debug info size.
+ CGDebugInfo *DI = CGF.getDebugInfo();
+ if (DI && CGF.CGM.getCodeGenOpts().LimitDebugInfo) {
+ QualType PQTy = E->getBase()->IgnoreParenImpCasts()->getType();
+ if (const PointerType * PTy = dyn_cast<PointerType>(PQTy))
+ if (FieldDecl *M = dyn_cast<FieldDecl>(E->getMemberDecl()))
+ DI->getOrCreateRecordType(PTy->getPointeeType(),
+ M->getParent()->getLocation());
+ }
+ return EmitLoadOfLValue(E);
+}
+
+Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ TestAndClearIgnoreResultAssign();
+
+ // Emit subscript expressions in rvalue context's. For most cases, this just
+ // loads the lvalue formed by the subscript expr. However, we have to be
+ // careful, because the base of a vector subscript is occasionally an rvalue,
+ // so we can't get it as an lvalue.
+ if (!E->getBase()->getType()->isVectorType())
+ return EmitLoadOfLValue(E);
+
+ // Handle the vector case. The base must be a vector, the index must be an
+ // integer value.
+ Value *Base = Visit(E->getBase());
+ Value *Idx = Visit(E->getIdx());
+ bool IdxSigned = E->getIdx()->getType()->isSignedIntegerType();
+ Idx = Builder.CreateIntCast(Idx, CGF.Int32Ty, IdxSigned, "vecidxcast");
+ return Builder.CreateExtractElement(Base, Idx, "vecext");
+}
+
+static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
+ unsigned Off, const llvm::Type *I32Ty) {
+ int MV = SVI->getMaskValue(Idx);
+ if (MV == -1)
+ return llvm::UndefValue::get(I32Ty);
+ return llvm::ConstantInt::get(I32Ty, Off+MV);
+}
+
+Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
+ bool Ignore = TestAndClearIgnoreResultAssign();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ unsigned NumInitElements = E->getNumInits();
+
+ if (E->hadArrayRangeDesignator())
+ CGF.ErrorUnsupported(E, "GNU array range designator extension");
+
+ const llvm::VectorType *VType =
+ dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
+
+ // We have a scalar in braces. Just use the first element.
+ if (!VType)
+ return Visit(E->getInit(0));
+
+ unsigned ResElts = VType->getNumElements();
+
+ // Loop over initializers collecting the Value for each, and remembering
+ // whether the source was swizzle (ExtVectorElementExpr). This will allow
+ // us to fold the shuffle for the swizzle into the shuffle for the vector
+ // initializer, since LLVM optimizers generally do not want to touch
+ // shuffles.
+ unsigned CurIdx = 0;
+ bool VIsUndefShuffle = false;
+ llvm::Value *V = llvm::UndefValue::get(VType);
+ for (unsigned i = 0; i != NumInitElements; ++i) {
+ Expr *IE = E->getInit(i);
+ Value *Init = Visit(IE);
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+
+ const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
+
+ // Handle scalar elements. If the scalar initializer is actually one
+ // element of a different vector of the same width, use shuffle instead of
+ // extract+insert.
+ if (!VVT) {
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init);
+
+ if (EI->getVectorOperandType()->getNumElements() == ResElts) {
+ llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
+ Value *LHS = 0, *RHS = 0;
+ if (CurIdx == 0) {
+ // insert into undef -> shuffle (src, undef)
+ Args.push_back(C);
+ for (unsigned j = 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+
+ LHS = EI->getVectorOperand();
+ RHS = V;
+ VIsUndefShuffle = true;
+ } else if (VIsUndefShuffle) {
+ // insert into undefshuffle && size match -> shuffle (v, src)
+ llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V);
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(getMaskElt(SVV, j, 0, CGF.Int32Ty));
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty,
+ ResElts + C->getZExtValue()));
+ for (unsigned j = CurIdx + 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+
+ LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+ RHS = EI->getVectorOperand();
+ VIsUndefShuffle = false;
+ }
+ if (!Args.empty()) {
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ V = Builder.CreateShuffleVector(LHS, RHS, Mask);
+ ++CurIdx;
+ continue;
+ }
+ }
+ }
+ Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, CurIdx);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ VIsUndefShuffle = false;
+ ++CurIdx;
+ continue;
+ }
+
+ unsigned InitElts = VVT->getNumElements();
+
+ // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
+ // input is the same width as the vector being constructed, generate an
+ // optimized shuffle of the swizzle input into the result.
+ unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
+ Value *SVOp = SVI->getOperand(0);
+ const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
+
+ if (OpTy->getNumElements() == ResElts) {
+ for (unsigned j = 0; j != CurIdx; ++j) {
+ // If the current vector initializer is a shuffle with undef, merge
+ // this shuffle directly into it.
+ if (VIsUndefShuffle) {
+ Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0,
+ CGF.Int32Ty));
+ } else {
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j));
+ }
+ }
+ for (unsigned j = 0, je = InitElts; j != je; ++j)
+ Args.push_back(getMaskElt(SVI, j, Offset, CGF.Int32Ty));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+
+ if (VIsUndefShuffle)
+ V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+
+ Init = SVOp;
+ }
+ }
+
+ // Extend init to result vector length, and then shuffle its contribution
+ // to the vector initializer into V.
+ if (Args.empty()) {
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j));
+ for (unsigned j = InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
+ Mask, "vext");
+
+ Args.clear();
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j));
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, j+Offset));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+ }
+
+ // If V is undef, make sure it ends up on the RHS of the shuffle to aid
+ // merging subsequent shuffles into this one.
+ if (CurIdx == 0)
+ std::swap(V, Init);
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit");
+ VIsUndefShuffle = isa<llvm::UndefValue>(Init);
+ CurIdx += InitElts;
+ }
+
+ // FIXME: evaluate codegen vs. shuffling against constant null vector.
+ // Emit remaining default initializers.
+ const llvm::Type *EltTy = VType->getElementType();
+
+ // Emit remaining default initializers
+ for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
+ Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, CurIdx);
+ llvm::Value *Init = llvm::Constant::getNullValue(EltTy);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ }
+ return V;
+}
+
+static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+
+ if (CE->getCastKind() == CK_UncheckedDerivedToBase)
+ return false;
+
+ if (isa<CXXThisExpr>(E)) {
+ // We always assume that 'this' is never null.
+ return false;
+ }
+
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
+ // And that glvalue casts are never null.
+ if (ICE->getValueKind() != VK_RValue)
+ return false;
+ }
+
+ return true;
+}
+
+// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
+// have to handle a more broad range of conversions than explicit casts, as they
+// handle things like function to ptr-to-function decay etc.
+Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
+ Expr *E = CE->getSubExpr();
+ QualType DestTy = CE->getType();
+ CastKind Kind = CE->getCastKind();
+
+ if (!DestTy->isVoidType())
+ TestAndClearIgnoreResultAssign();
+
+ // Since almost all cast kinds apply to scalars, this switch doesn't have
+ // a default case, so the compiler will warn on a missing case. The cases
+ // are in the same order as in the CastKind enum.
+ switch (Kind) {
+ case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
+
+ case CK_LValueBitCast:
+ case CK_ObjCObjectLValueCast: {
+ Value *V = EmitLValue(E).getAddress();
+ V = Builder.CreateBitCast(V,
+ ConvertType(CGF.getContext().getPointerType(DestTy)));
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), DestTy);
+ }
+
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_BitCast: {
+ Value *Src = Visit(const_cast<Expr*>(E));
+ return Builder.CreateBitCast(Src, ConvertType(DestTy));
+ }
+ case CK_NoOp:
+ case CK_UserDefinedConversion:
+ return Visit(const_cast<Expr*>(E));
+
+ case CK_BaseToDerived: {
+ const CXXRecordDecl *DerivedClassDecl =
+ DestTy->getCXXRecordDeclForPointerType();
+
+ return CGF.GetAddressOfDerivedClass(Visit(E), DerivedClassDecl,
+ CE->path_begin(), CE->path_end(),
+ ShouldNullCheckClassCastValue(CE));
+ }
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBase: {
+ const RecordType *DerivedClassTy =
+ E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>();
+ CXXRecordDecl *DerivedClassDecl =
+ cast<CXXRecordDecl>(DerivedClassTy->getDecl());
+
+ return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
+ CE->path_begin(), CE->path_end(),
+ ShouldNullCheckClassCastValue(CE));
+ }
+ case CK_Dynamic: {
+ Value *V = Visit(const_cast<Expr*>(E));
+ const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
+ return CGF.EmitDynamicCast(V, DCE);
+ }
+
+ case CK_ArrayToPointerDecay: {
+ assert(E->getType()->isArrayType() &&
+ "Array to pointer decay must have array source type!");
+
+ Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays.
+
+ // Note that VLA pointers are always decayed, so we don't need to do
+ // anything here.
+ if (!E->getType()->isVariableArrayType()) {
+ assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
+ assert(isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType())
+ ->getElementType()) &&
+ "Expected pointer to array");
+ V = Builder.CreateStructGEP(V, 0, "arraydecay");
+ }
+
+ return V;
+ }
+ case CK_FunctionToPointerDecay:
+ return EmitLValue(E).getAddress();
+
+ case CK_NullToPointer:
+ if (MustVisitNullValue(E))
+ (void) Visit(E);
+
+ return llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(ConvertType(DestTy)));
+
+ case CK_NullToMemberPointer: {
+ if (MustVisitNullValue(E))
+ (void) Visit(E);
+
+ const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ }
+
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer: {
+ Value *Src = Visit(E);
+
+ // Note that the AST doesn't distinguish between checked and
+ // unchecked member pointer conversions, so we always have to
+ // implement checked conversions here. This is inefficient when
+ // actual control flow may be required in order to perform the
+ // check, which it is for data member pointers (but not member
+ // function pointers on Itanium and ARM).
+ return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
+ }
+
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexCast:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_ConstructorConversion:
+ case CK_ToUnion:
+ llvm_unreachable("scalar cast to non-scalar value");
+ break;
+
+ case CK_GetObjCProperty: {
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
+ assert(E->isGLValue() && E->getObjectKind() == OK_ObjCProperty &&
+ "CK_GetObjCProperty for non-lvalue or non-ObjCProperty");
+ RValue RV = CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType());
+ return RV.getScalarVal();
+ }
+
+ case CK_LValueToRValue:
+ assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
+ assert(E->isGLValue() && "lvalue-to-rvalue applied to r-value!");
+ return Visit(const_cast<Expr*>(E));
+
+ case CK_IntegralToPointer: {
+ Value *Src = Visit(const_cast<Expr*>(E));
+
+ // First, convert to the correct width so that we control the kind of
+ // extension.
+ const llvm::Type *MiddleTy = CGF.IntPtrTy;
+ bool InputSigned = E->getType()->isSignedIntegerType();
+ llvm::Value* IntResult =
+ Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
+
+ return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
+ }
+ case CK_PointerToIntegral: {
+ Value *Src = Visit(const_cast<Expr*>(E));
+
+ // Handle conversion to bool correctly.
+ if (DestTy->isBooleanType())
+ return EmitScalarConversion(Src, E->getType(), DestTy);
+
+ return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
+ }
+ case CK_ToVoid: {
+ CGF.EmitIgnoredExpr(E);
+ return 0;
+ }
+ case CK_VectorSplat: {
+ const llvm::Type *DstTy = ConvertType(DestTy);
+ Value *Elt = Visit(const_cast<Expr*>(E));
+
+ // Insert the element in element zero of an undef vector
+ llvm::Value *UnV = llvm::UndefValue::get(DstTy);
+ llvm::Value *Idx = llvm::ConstantInt::get(CGF.Int32Ty, 0);
+ UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
+
+ // Splat the element across to all elements
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+ unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+ llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Int32Ty, 0);
+ for (unsigned i = 0; i < NumElements; i++)
+ Args.push_back(Zero);
+
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
+ return Yay;
+ }
+
+ case CK_IntegralCast:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy);
+
+ case CK_IntegralToBoolean:
+ return EmitIntToBoolConversion(Visit(E));
+ case CK_PointerToBoolean:
+ return EmitPointerToBoolConversion(Visit(E));
+ case CK_FloatingToBoolean:
+ return EmitFloatToBoolConversion(Visit(E));
+ case CK_MemberPointerToBoolean: {
+ llvm::Value *MemPtr = Visit(E);
+ const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
+ }
+
+ case CK_FloatingComplexToReal:
+ case CK_IntegralComplexToReal:
+ return CGF.EmitComplexExpr(E, false, true).first;
+
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean: {
+ CodeGenFunction::ComplexPairTy V = CGF.EmitComplexExpr(E);
+
+ // TODO: kill this function off, inline appropriate case here
+ return EmitComplexToScalarConversion(V, E->getType(), DestTy);
+ }
+
+ }
+
+ llvm_unreachable("unknown scalar cast");
+ return 0;
+}
+
+Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
+ CodeGenFunction::StmtExprEvaluation eval(CGF);
+ return CGF.EmitCompoundStmt(*E->getSubStmt(), !E->getType()->isVoidType())
+ .getScalarVal();
+}
+
+Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) {
+ llvm::Value *V = CGF.GetAddrOfBlockDecl(E);
+ if (E->getType().isObjCGCWeak())
+ return CGF.CGM.getObjCRuntime().EmitObjCWeakRead(CGF, V);
+ return CGF.EmitLoadOfScalar(V, false, 0, E->getType());
+}
+
+//===----------------------------------------------------------------------===//
+// Unary Operators
+//===----------------------------------------------------------------------===//
+
+llvm::Value *ScalarExprEmitter::
+EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
+ llvm::Value *InVal,
+ llvm::Value *NextVal, bool IsInc) {
+ switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+ case LangOptions::SOB_Undefined:
+ return Builder.CreateNSWAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+ break;
+ case LangOptions::SOB_Defined:
+ return Builder.CreateAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+ break;
+ case LangOptions::SOB_Trapping:
+ BinOpInfo BinOp;
+ BinOp.LHS = InVal;
+ BinOp.RHS = NextVal;
+ BinOp.Ty = E->getType();
+ BinOp.Opcode = BO_Add;
+ BinOp.E = E;
+ return EmitOverflowCheckedBinOp(BinOp);
+ break;
+ }
+ assert(false && "Unknown SignedOverflowBehaviorTy");
+ return 0;
+}
+
+llvm::Value *
+ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre) {
+
+ QualType type = E->getSubExpr()->getType();
+ llvm::Value *value = EmitLoadOfLValue(LV, type);
+ llvm::Value *input = value;
+
+ int amount = (isInc ? 1 : -1);
+
+ // Special case of integer increment that we have to check first: bool++.
+ // Due to promotion rules, we get:
+ // bool++ -> bool = bool + 1
+ // -> bool = (int)bool + 1
+ // -> bool = ((int)bool + 1 != 0)
+ // An interesting aspect of this is that increment is always true.
+ // Decrement does not have this property.
+ if (isInc && type->isBooleanType()) {
+ value = Builder.getTrue();
+
+ // Most common case by far: integer increment.
+ } else if (type->isIntegerType()) {
+
+ llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount);
+
+ if (type->isSignedIntegerType())
+ value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
+
+ // Unsigned integer inc is always two's complement.
+ else
+ value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
+
+ // Next most common: pointer increment.
+ } else if (const PointerType *ptr = type->getAs<PointerType>()) {
+ QualType type = ptr->getPointeeType();
+
+ // VLA types don't have constant size.
+ if (type->isVariableArrayType()) {
+ llvm::Value *vlaSize =
+ CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type));
+ value = CGF.EmitCastToVoidPtr(value);
+ if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize");
+ value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc");
+ value = Builder.CreateBitCast(value, input->getType());
+
+ // Arithmetic on function pointers (!) is just +-1.
+ } else if (type->isFunctionType()) {
+ llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount);
+
+ value = CGF.EmitCastToVoidPtr(value);
+ value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr");
+ value = Builder.CreateBitCast(value, input->getType());
+
+ // For everything else, we can just do a simple increment.
+ } else {
+ llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount);
+ value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr");
+ }
+
+ // Vector increment/decrement.
+ } else if (type->isVectorType()) {
+ if (type->hasIntegerRepresentation()) {
+ llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount);
+
+ if (type->hasSignedIntegerRepresentation())
+ value = EmitAddConsiderOverflowBehavior(E, value, amt, isInc);
+ else
+ value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
+ } else {
+ value = Builder.CreateFAdd(
+ value,
+ llvm::ConstantFP::get(value->getType(), amount),
+ isInc ? "inc" : "dec");
+ }
+
+ // Floating point.
+ } else if (type->isRealFloatingType()) {
+ // Add the inc/dec to the real part.
+ llvm::Value *amt;
+ if (value->getType()->isFloatTy())
+ amt = llvm::ConstantFP::get(VMContext,
+ llvm::APFloat(static_cast<float>(amount)));
+ else if (value->getType()->isDoubleTy())
+ amt = llvm::ConstantFP::get(VMContext,
+ llvm::APFloat(static_cast<double>(amount)));
+ else {
+ llvm::APFloat F(static_cast<float>(amount));
+ bool ignored;
+ F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero,
+ &ignored);
+ amt = llvm::ConstantFP::get(VMContext, F);
+ }
+ value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec");
+
+ // Objective-C pointer types.
+ } else {
+ const ObjCObjectPointerType *OPT = type->castAs<ObjCObjectPointerType>();
+ value = CGF.EmitCastToVoidPtr(value);
+
+ CharUnits size = CGF.getContext().getTypeSizeInChars(OPT->getObjectType());
+ if (!isInc) size = -size;
+ llvm::Value *sizeValue =
+ llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity());
+
+ value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
+ value = Builder.CreateBitCast(value, input->getType());
+ }
+
+ // Store the updated result through the lvalue.
+ if (LV.isBitField())
+ CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, type, &value);
+ else
+ CGF.EmitStoreThroughLValue(RValue::get(value), LV, type);
+
+ // If this is a postinc, return the value read from memory, otherwise use the
+ // updated value.
+ return isPre ? value : input;
+}
+
+
+
+Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
+ TestAndClearIgnoreResultAssign();
+ // Emit unary minus with EmitSub so we handle overflow cases etc.
+ BinOpInfo BinOp;
+ BinOp.RHS = Visit(E->getSubExpr());
+
+ if (BinOp.RHS->getType()->isFPOrFPVectorTy())
+ BinOp.LHS = llvm::ConstantFP::getZeroValueForNegation(BinOp.RHS->getType());
+ else
+ BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
+ BinOp.Ty = E->getType();
+ BinOp.Opcode = BO_Sub;
+ BinOp.E = E;
+ return EmitSub(BinOp);
+}
+
+Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
+ TestAndClearIgnoreResultAssign();
+ Value *Op = Visit(E->getSubExpr());
+ return Builder.CreateNot(Op, "neg");
+}
+
+Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
+ // Compare operand to zero.
+ Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr());
+
+ // Invert value.
+ // TODO: Could dynamically modify easy computations here. For example, if
+ // the operand is an icmp ne, turn into icmp eq.
+ BoolVal = Builder.CreateNot(BoolVal, "lnot");
+
+ // ZExt result to the expr type.
+ return Builder.CreateZExt(BoolVal, ConvertType(E->getType()), "lnot.ext");
+}
+
+Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ // Try folding the offsetof to a constant.
+ Expr::EvalResult EvalResult;
+ if (E->Evaluate(EvalResult, CGF.getContext()))
+ return llvm::ConstantInt::get(VMContext, EvalResult.Val.getInt());
+
+ // Loop over the components of the offsetof to compute the value.
+ unsigned n = E->getNumComponents();
+ const llvm::Type* ResultType = ConvertType(E->getType());
+ llvm::Value* Result = llvm::Constant::getNullValue(ResultType);
+ QualType CurrentType = E->getTypeSourceInfo()->getType();
+ for (unsigned i = 0; i != n; ++i) {
+ OffsetOfExpr::OffsetOfNode ON = E->getComponent(i);
+ llvm::Value *Offset = 0;
+ switch (ON.getKind()) {
+ case OffsetOfExpr::OffsetOfNode::Array: {
+ // Compute the index
+ Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
+ llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
+ bool IdxSigned = IdxExpr->getType()->isSignedIntegerType();
+ Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv");
+
+ // Save the element type
+ CurrentType =
+ CGF.getContext().getAsArrayType(CurrentType)->getElementType();
+
+ // Compute the element size
+ llvm::Value* ElemSize = llvm::ConstantInt::get(ResultType,
+ CGF.getContext().getTypeSizeInChars(CurrentType).getQuantity());
+
+ // Multiply out to compute the result
+ Offset = Builder.CreateMul(Idx, ElemSize);
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Field: {
+ FieldDecl *MemberDecl = ON.getField();
+ RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+
+ // Compute the index of the field in its parent.
+ unsigned i = 0;
+ // FIXME: It would be nice if we didn't have to loop here!
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == MemberDecl)
+ break;
+ }
+ assert(i < RL.getFieldCount() && "offsetof field in wrong type");
+
+ // Compute the offset to the field
+ int64_t OffsetInt = RL.getFieldOffset(i) /
+ CGF.getContext().getCharWidth();
+ Offset = llvm::ConstantInt::get(ResultType, OffsetInt);
+
+ // Save the element type.
+ CurrentType = MemberDecl->getType();
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Identifier:
+ llvm_unreachable("dependent __builtin_offsetof");
+
+ case OffsetOfExpr::OffsetOfNode::Base: {
+ if (ON.getBase()->isVirtual()) {
+ CGF.ErrorUnsupported(E, "virtual base in offsetof");
+ continue;
+ }
+
+ RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+
+ // Save the element type.
+ CurrentType = ON.getBase()->getType();
+
+ // Compute the offset to the base.
+ const RecordType *BaseRT = CurrentType->getAs<RecordType>();
+ CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
+ int64_t OffsetInt = RL.getBaseClassOffsetInBits(BaseRD) /
+ CGF.getContext().getCharWidth();
+ Offset = llvm::ConstantInt::get(ResultType, OffsetInt);
+ break;
+ }
+ }
+ Result = Builder.CreateAdd(Result, Offset);
+ }
+ return Result;
+}
+
+/// VisitSizeOfAlignOfExpr - Return the size or alignment of the type of
+/// argument of the sizeof expression as an integer.
+Value *
+ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
+ QualType TypeToSize = E->getTypeOfArgument();
+ if (E->isSizeOf()) {
+ if (const VariableArrayType *VAT =
+ CGF.getContext().getAsVariableArrayType(TypeToSize)) {
+ if (E->isArgumentType()) {
+ // sizeof(type) - make sure to emit the VLA size.
+ CGF.EmitVLASize(TypeToSize);
+ } else {
+ // C99 6.5.3.4p2: If the argument is an expression of type
+ // VLA, it is evaluated.
+ CGF.EmitIgnoredExpr(E->getArgumentExpr());
+ }
+
+ return CGF.GetVLASize(VAT);
+ }
+ }
+
+ // If this isn't sizeof(vla), the result must be constant; use the constant
+ // folding logic so we don't have to duplicate it here.
+ Expr::EvalResult Result;
+ E->Evaluate(Result, CGF.getContext());
+ return llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+}
+
+Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
+ Expr *Op = E->getSubExpr();
+ if (Op->getType()->isAnyComplexType()) {
+ // If it's an l-value, load through the appropriate subobject l-value.
+ // Note that we have to ask E because Op might be an l-value that
+ // this won't work for, e.g. an Obj-C property.
+ if (E->isGLValue())
+ return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType())
+ .getScalarVal();
+
+ // Otherwise, calculate and project.
+ return CGF.EmitComplexExpr(Op, false, true).first;
+ }
+
+ return Visit(Op);
+}
+
+Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
+ Expr *Op = E->getSubExpr();
+ if (Op->getType()->isAnyComplexType()) {
+ // If it's an l-value, load through the appropriate subobject l-value.
+ // Note that we have to ask E because Op might be an l-value that
+ // this won't work for, e.g. an Obj-C property.
+ if (Op->isGLValue())
+ return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType())
+ .getScalarVal();
+
+ // Otherwise, calculate and project.
+ return CGF.EmitComplexExpr(Op, true, false).second;
+ }
+
+ // __imag on a scalar returns zero. Emit the subexpr to ensure side
+ // effects are evaluated, but not the actual value.
+ CGF.EmitScalarExpr(Op, true);
+ return llvm::Constant::getNullValue(ConvertType(E->getType()));
+}
+
+//===----------------------------------------------------------------------===//
+// Binary Operators
+//===----------------------------------------------------------------------===//
+
+BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
+ TestAndClearIgnoreResultAssign();
+ BinOpInfo Result;
+ Result.LHS = Visit(E->getLHS());
+ Result.RHS = Visit(E->getRHS());
+ Result.Ty = E->getType();
+ Result.Opcode = E->getOpcode();
+ Result.E = E;
+ return Result;
+}
+
+LValue ScalarExprEmitter::EmitCompoundAssignLValue(
+ const CompoundAssignOperator *E,
+ Value *(ScalarExprEmitter::*Func)(const BinOpInfo &),
+ Value *&Result) {
+ QualType LHSTy = E->getLHS()->getType();
+ BinOpInfo OpInfo;
+
+ if (E->getComputationResultType()->isAnyComplexType()) {
+ // This needs to go through the complex expression emitter, but it's a tad
+ // complicated to do that... I'm leaving it out for now. (Note that we do
+ // actually need the imaginary part of the RHS for multiplication and
+ // division.)
+ CGF.ErrorUnsupported(E, "complex compound assignment");
+ Result = llvm::UndefValue::get(CGF.ConvertType(E->getType()));
+ return LValue();
+ }
+
+ // Emit the RHS first. __block variables need to have the rhs evaluated
+ // first, plus this should improve codegen a little.
+ OpInfo.RHS = Visit(E->getRHS());
+ OpInfo.Ty = E->getComputationResultType();
+ OpInfo.Opcode = E->getOpcode();
+ OpInfo.E = E;
+ // Load/convert the LHS.
+ LValue LHSLV = EmitCheckedLValue(E->getLHS());
+ OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
+ OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
+ E->getComputationLHSType());
+
+ // Expand the binary operator.
+ Result = (this->*Func)(OpInfo);
+
+ // Convert the result back to the LHS type.
+ Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy);
+
+ // Store the result value into the LHS lvalue. Bit-fields are handled
+ // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
+ // 'An assignment expression has the value of the left operand after the
+ // assignment...'.
+ if (LHSLV.isBitField())
+ CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy,
+ &Result);
+ else
+ CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, LHSTy);
+
+ return LHSLV;
+}
+
+Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
+ Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
+ bool Ignore = TestAndClearIgnoreResultAssign();
+ Value *RHS;
+ LValue LHS = EmitCompoundAssignLValue(E, Func, RHS);
+
+ // If the result is clearly ignored, return now.
+ if (Ignore)
+ return 0;
+
+ // The result of an assignment in C is the assigned r-value.
+ if (!CGF.getContext().getLangOptions().CPlusPlus)
+ return RHS;
+
+ // Objective-C property assignment never reloads the value following a store.
+ if (LHS.isPropertyRef())
+ return RHS;
+
+ // If the lvalue is non-volatile, return the computed value of the assignment.
+ if (!LHS.isVolatileQualified())
+ return RHS;
+
+ // Otherwise, reload the value.
+ return EmitLoadOfLValue(LHS, E->getType());
+}
+
+void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
+ const BinOpInfo &Ops,
+ llvm::Value *Zero, bool isDiv) {
+ llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn);
+ llvm::BasicBlock *contBB =
+ CGF.createBasicBlock(isDiv ? "div.cont" : "rem.cont", CGF.CurFn);
+
+ const llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType());
+
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
+ llvm::Value *IntMin =
+ llvm::ConstantInt::get(VMContext,
+ llvm::APInt::getSignedMinValue(Ty->getBitWidth()));
+ llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL);
+
+ llvm::Value *Cond1 = Builder.CreateICmpEQ(Ops.RHS, Zero);
+ llvm::Value *LHSCmp = Builder.CreateICmpEQ(Ops.LHS, IntMin);
+ llvm::Value *RHSCmp = Builder.CreateICmpEQ(Ops.RHS, NegOne);
+ llvm::Value *Cond2 = Builder.CreateAnd(LHSCmp, RHSCmp, "and");
+ Builder.CreateCondBr(Builder.CreateOr(Cond1, Cond2, "or"),
+ overflowBB, contBB);
+ } else {
+ CGF.Builder.CreateCondBr(Builder.CreateICmpEQ(Ops.RHS, Zero),
+ overflowBB, contBB);
+ }
+ EmitOverflowBB(overflowBB);
+ Builder.SetInsertPoint(contBB);
+}
+
+Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
+ if (isTrapvOverflowBehavior()) {
+ llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
+
+ if (Ops.Ty->isIntegerType())
+ EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true);
+ else if (Ops.Ty->isRealFloatingType()) {
+ llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow",
+ CGF.CurFn);
+ llvm::BasicBlock *DivCont = CGF.createBasicBlock("div.cont", CGF.CurFn);
+ CGF.Builder.CreateCondBr(Builder.CreateFCmpOEQ(Ops.RHS, Zero),
+ overflowBB, DivCont);
+ EmitOverflowBB(overflowBB);
+ Builder.SetInsertPoint(DivCont);
+ }
+ }
+ if (Ops.LHS->getType()->isFPOrFPVectorTy())
+ return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
+ else if (Ops.Ty->hasUnsignedIntegerRepresentation())
+ return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div");
+ else
+ return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div");
+}
+
+Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
+ // Rem in C can't be a floating point type: C99 6.5.5p2.
+ if (isTrapvOverflowBehavior()) {
+ llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
+
+ if (Ops.Ty->isIntegerType())
+ EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false);
+ }
+
+ if (Ops.Ty->isUnsignedIntegerType())
+ return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem");
+ else
+ return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem");
+}
+
+Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
+ unsigned IID;
+ unsigned OpID = 0;
+
+ switch (Ops.Opcode) {
+ case BO_Add:
+ case BO_AddAssign:
+ OpID = 1;
+ IID = llvm::Intrinsic::sadd_with_overflow;
+ break;
+ case BO_Sub:
+ case BO_SubAssign:
+ OpID = 2;
+ IID = llvm::Intrinsic::ssub_with_overflow;
+ break;
+ case BO_Mul:
+ case BO_MulAssign:
+ OpID = 3;
+ IID = llvm::Intrinsic::smul_with_overflow;
+ break;
+ default:
+ assert(false && "Unsupported operation for overflow detection");
+ IID = 0;
+ }
+ OpID <<= 1;
+ OpID |= 1;
+
+ const llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ops.Ty);
+
+ llvm::Function *intrinsic = CGF.CGM.getIntrinsic(IID, &opTy, 1);
+
+ Value *resultAndOverflow = Builder.CreateCall2(intrinsic, Ops.LHS, Ops.RHS);
+ Value *result = Builder.CreateExtractValue(resultAndOverflow, 0);
+ Value *overflow = Builder.CreateExtractValue(resultAndOverflow, 1);
+
+ // Branch in case of overflow.
+ llvm::BasicBlock *initialBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn);
+ llvm::BasicBlock *continueBB = CGF.createBasicBlock("nooverflow", CGF.CurFn);
+
+ Builder.CreateCondBr(overflow, overflowBB, continueBB);
+
+ // Handle overflow with llvm.trap.
+ const std::string *handlerName =
+ &CGF.getContext().getLangOptions().OverflowHandler;
+ if (handlerName->empty()) {
+ EmitOverflowBB(overflowBB);
+ Builder.SetInsertPoint(continueBB);
+ return result;
+ }
+
+ // If an overflow handler is set, then we want to call it and then use its
+ // result, if it returns.
+ Builder.SetInsertPoint(overflowBB);
+
+ // Get the overflow handler.
+ const llvm::Type *Int8Ty = llvm::Type::getInt8Ty(VMContext);
+ std::vector<const llvm::Type*> argTypes;
+ argTypes.push_back(CGF.Int64Ty); argTypes.push_back(CGF.Int64Ty);
+ argTypes.push_back(Int8Ty); argTypes.push_back(Int8Ty);
+ llvm::FunctionType *handlerTy =
+ llvm::FunctionType::get(CGF.Int64Ty, argTypes, true);
+ llvm::Value *handler = CGF.CGM.CreateRuntimeFunction(handlerTy, *handlerName);
+
+ // Sign extend the args to 64-bit, so that we can use the same handler for
+ // all types of overflow.
+ llvm::Value *lhs = Builder.CreateSExt(Ops.LHS, CGF.Int64Ty);
+ llvm::Value *rhs = Builder.CreateSExt(Ops.RHS, CGF.Int64Ty);
+
+ // Call the handler with the two arguments, the operation, and the size of
+ // the result.
+ llvm::Value *handlerResult = Builder.CreateCall4(handler, lhs, rhs,
+ Builder.getInt8(OpID),
+ Builder.getInt8(cast<llvm::IntegerType>(opTy)->getBitWidth()));
+
+ // Truncate the result back to the desired size.
+ handlerResult = Builder.CreateTrunc(handlerResult, opTy);
+ Builder.CreateBr(continueBB);
+
+ Builder.SetInsertPoint(continueBB);
+ llvm::PHINode *phi = Builder.CreatePHI(opTy);
+ phi->reserveOperandSpace(2);
+ phi->addIncoming(result, initialBB);
+ phi->addIncoming(handlerResult, overflowBB);
+
+ return phi;
+}
+
+Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
+ if (!Ops.Ty->isAnyPointerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
+ switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+ case LangOptions::SOB_Undefined:
+ return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
+ case LangOptions::SOB_Defined:
+ return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
+ case LangOptions::SOB_Trapping:
+ return EmitOverflowCheckedBinOp(Ops);
+ }
+ }
+
+ if (Ops.LHS->getType()->isFPOrFPVectorTy())
+ return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add");
+
+ return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
+ }
+
+ // Must have binary (not unary) expr here. Unary pointer decrement doesn't
+ // use this path.
+ const BinaryOperator *BinOp = cast<BinaryOperator>(Ops.E);
+
+ if (Ops.Ty->isPointerType() &&
+ Ops.Ty->getAs<PointerType>()->isVariableArrayType()) {
+ // The amount of the addition needs to account for the VLA size
+ CGF.ErrorUnsupported(BinOp, "VLA pointer addition");
+ }
+
+ Value *Ptr, *Idx;
+ Expr *IdxExp;
+ const PointerType *PT = BinOp->getLHS()->getType()->getAs<PointerType>();
+ const ObjCObjectPointerType *OPT =
+ BinOp->getLHS()->getType()->getAs<ObjCObjectPointerType>();
+ if (PT || OPT) {
+ Ptr = Ops.LHS;
+ Idx = Ops.RHS;
+ IdxExp = BinOp->getRHS();
+ } else { // int + pointer
+ PT = BinOp->getRHS()->getType()->getAs<PointerType>();
+ OPT = BinOp->getRHS()->getType()->getAs<ObjCObjectPointerType>();
+ assert((PT || OPT) && "Invalid add expr");
+ Ptr = Ops.RHS;
+ Idx = Ops.LHS;
+ IdxExp = BinOp->getLHS();
+ }
+
+ unsigned Width = cast<llvm::IntegerType>(Idx->getType())->getBitWidth();
+ if (Width < CGF.PointerWidthInBits) {
+ // Zero or sign extend the pointer value based on whether the index is
+ // signed or not.
+ const llvm::Type *IdxType = CGF.IntPtrTy;
+ if (IdxExp->getType()->isSignedIntegerType())
+ Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext");
+ else
+ Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
+ }
+ const QualType ElementType = PT ? PT->getPointeeType() : OPT->getPointeeType();
+ // Handle interface types, which are not represented with a concrete type.
+ if (const ObjCObjectType *OIT = ElementType->getAs<ObjCObjectType>()) {
+ llvm::Value *InterfaceSize =
+ llvm::ConstantInt::get(Idx->getType(),
+ CGF.getContext().getTypeSizeInChars(OIT).getQuantity());
+ Idx = Builder.CreateMul(Idx, InterfaceSize);
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
+ Value *Casted = Builder.CreateBitCast(Ptr, i8Ty);
+ Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr");
+ return Builder.CreateBitCast(Res, Ptr->getType());
+ }
+
+ // Explicitly handle GNU void* and function pointer arithmetic extensions. The
+ // GNU void* casts amount to no-ops since our void* type is i8*, but this is
+ // future proof.
+ if (ElementType->isVoidType() || ElementType->isFunctionType()) {
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
+ Value *Casted = Builder.CreateBitCast(Ptr, i8Ty);
+ Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr");
+ return Builder.CreateBitCast(Res, Ptr->getType());
+ }
+
+ return Builder.CreateInBoundsGEP(Ptr, Idx, "add.ptr");
+}
+
+Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
+ if (!isa<llvm::PointerType>(Ops.LHS->getType())) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
+ switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+ case LangOptions::SOB_Undefined:
+ return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
+ case LangOptions::SOB_Defined:
+ return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
+ case LangOptions::SOB_Trapping:
+ return EmitOverflowCheckedBinOp(Ops);
+ }
+ }
+
+ if (Ops.LHS->getType()->isFPOrFPVectorTy())
+ return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub");
+
+ return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
+ }
+
+ // Must have binary (not unary) expr here. Unary pointer increment doesn't
+ // use this path.
+ const BinaryOperator *BinOp = cast<BinaryOperator>(Ops.E);
+
+ if (BinOp->getLHS()->getType()->isPointerType() &&
+ BinOp->getLHS()->getType()->getAs<PointerType>()->isVariableArrayType()) {
+ // The amount of the addition needs to account for the VLA size for
+ // ptr-int
+ // The amount of the division needs to account for the VLA size for
+ // ptr-ptr.
+ CGF.ErrorUnsupported(BinOp, "VLA pointer subtraction");
+ }
+
+ const QualType LHSType = BinOp->getLHS()->getType();
+ const QualType LHSElementType = LHSType->getPointeeType();
+ if (!isa<llvm::PointerType>(Ops.RHS->getType())) {
+ // pointer - int
+ Value *Idx = Ops.RHS;
+ unsigned Width = cast<llvm::IntegerType>(Idx->getType())->getBitWidth();
+ if (Width < CGF.PointerWidthInBits) {
+ // Zero or sign extend the pointer value based on whether the index is
+ // signed or not.
+ const llvm::Type *IdxType = CGF.IntPtrTy;
+ if (BinOp->getRHS()->getType()->isSignedIntegerType())
+ Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext");
+ else
+ Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext");
+ }
+ Idx = Builder.CreateNeg(Idx, "sub.ptr.neg");
+
+ // Handle interface types, which are not represented with a concrete type.
+ if (const ObjCObjectType *OIT = LHSElementType->getAs<ObjCObjectType>()) {
+ llvm::Value *InterfaceSize =
+ llvm::ConstantInt::get(Idx->getType(),
+ CGF.getContext().
+ getTypeSizeInChars(OIT).getQuantity());
+ Idx = Builder.CreateMul(Idx, InterfaceSize);
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
+ Value *LHSCasted = Builder.CreateBitCast(Ops.LHS, i8Ty);
+ Value *Res = Builder.CreateGEP(LHSCasted, Idx, "add.ptr");
+ return Builder.CreateBitCast(Res, Ops.LHS->getType());
+ }
+
+ // Explicitly handle GNU void* and function pointer arithmetic
+ // extensions. The GNU void* casts amount to no-ops since our void* type is
+ // i8*, but this is future proof.
+ if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) {
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext);
+ Value *LHSCasted = Builder.CreateBitCast(Ops.LHS, i8Ty);
+ Value *Res = Builder.CreateGEP(LHSCasted, Idx, "sub.ptr");
+ return Builder.CreateBitCast(Res, Ops.LHS->getType());
+ }
+
+ return Builder.CreateInBoundsGEP(Ops.LHS, Idx, "sub.ptr");
+ } else {
+ // pointer - pointer
+ Value *LHS = Ops.LHS;
+ Value *RHS = Ops.RHS;
+
+ CharUnits ElementSize;
+
+ // Handle GCC extension for pointer arithmetic on void* and function pointer
+ // types.
+ if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) {
+ ElementSize = CharUnits::One();
+ } else {
+ ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType);
+ }
+
+ const llvm::Type *ResultType = ConvertType(Ops.Ty);
+ LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast");
+ RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
+ Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub");
+
+ // Optimize out the shift for element size of 1.
+ if (ElementSize.isOne())
+ return BytesBetween;
+
+ // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since
+ // pointer difference in C is only defined in the case where both operands
+ // are pointing to elements of an array.
+ Value *BytesPerElt =
+ llvm::ConstantInt::get(ResultType, ElementSize.getQuantity());
+ return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div");
+ }
+}
+
+Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
+ // LLVM requires the LHS and RHS to be the same type: promote or truncate the
+ // RHS to the same size as the LHS.
+ Value *RHS = Ops.RHS;
+ if (Ops.LHS->getType() != RHS->getType())
+ RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
+
+ if (CGF.CatchUndefined
+ && isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
+ llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
+ CGF.Builder.CreateCondBr(Builder.CreateICmpULT(RHS,
+ llvm::ConstantInt::get(RHS->getType(), Width)),
+ Cont, CGF.getTrapBB());
+ CGF.EmitBlock(Cont);
+ }
+
+ return Builder.CreateShl(Ops.LHS, RHS, "shl");
+}
+
+Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
+ // LLVM requires the LHS and RHS to be the same type: promote or truncate the
+ // RHS to the same size as the LHS.
+ Value *RHS = Ops.RHS;
+ if (Ops.LHS->getType() != RHS->getType())
+ RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
+
+ if (CGF.CatchUndefined
+ && isa<llvm::IntegerType>(Ops.LHS->getType())) {
+ unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
+ llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
+ CGF.Builder.CreateCondBr(Builder.CreateICmpULT(RHS,
+ llvm::ConstantInt::get(RHS->getType(), Width)),
+ Cont, CGF.getTrapBB());
+ CGF.EmitBlock(Cont);
+ }
+
+ if (Ops.Ty->hasUnsignedIntegerRepresentation())
+ return Builder.CreateLShr(Ops.LHS, RHS, "shr");
+ return Builder.CreateAShr(Ops.LHS, RHS, "shr");
+}
+
+enum IntrinsicType { VCMPEQ, VCMPGT };
+// return corresponding comparison intrinsic for given vector type
+static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT,
+ BuiltinType::Kind ElemKind) {
+ switch (ElemKind) {
+ default: assert(0 && "unexpected element type");
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtub_p;
+ break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequb_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtsb_p;
+ break;
+ case BuiltinType::UShort:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtuh_p;
+ break;
+ case BuiltinType::Short:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequh_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtsh_p;
+ break;
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtuw_p;
+ break;
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpequw_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtsw_p;
+ break;
+ case BuiltinType::Float:
+ return (IT == VCMPEQ) ? llvm::Intrinsic::ppc_altivec_vcmpeqfp_p :
+ llvm::Intrinsic::ppc_altivec_vcmpgtfp_p;
+ break;
+ }
+ return llvm::Intrinsic::not_intrinsic;
+}
+
+Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
+ unsigned SICmpOpc, unsigned FCmpOpc) {
+ TestAndClearIgnoreResultAssign();
+ Value *Result;
+ QualType LHSTy = E->getLHS()->getType();
+ if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) {
+ assert(E->getOpcode() == BO_EQ ||
+ E->getOpcode() == BO_NE);
+ Value *LHS = CGF.EmitScalarExpr(E->getLHS());
+ Value *RHS = CGF.EmitScalarExpr(E->getRHS());
+ Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison(
+ CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE);
+ } else if (!LHSTy->isAnyComplexType()) {
+ Value *LHS = Visit(E->getLHS());
+ Value *RHS = Visit(E->getRHS());
+
+ // If AltiVec, the comparison results in a numeric type, so we use
+ // intrinsics comparing vectors and giving 0 or 1 as a result
+ if (LHSTy->isVectorType() && CGF.getContext().getLangOptions().AltiVec) {
+ // constants for mapping CR6 register bits to predicate result
+ enum { CR6_EQ=0, CR6_EQ_REV, CR6_LT, CR6_LT_REV } CR6;
+
+ llvm::Intrinsic::ID ID = llvm::Intrinsic::not_intrinsic;
+
+ // in several cases vector arguments order will be reversed
+ Value *FirstVecArg = LHS,
+ *SecondVecArg = RHS;
+
+ QualType ElTy = LHSTy->getAs<VectorType>()->getElementType();
+ const BuiltinType *BTy = ElTy->getAs<BuiltinType>();
+ BuiltinType::Kind ElementKind = BTy->getKind();
+
+ switch(E->getOpcode()) {
+ default: assert(0 && "is not a comparison operation");
+ case BO_EQ:
+ CR6 = CR6_LT;
+ ID = GetIntrinsic(VCMPEQ, ElementKind);
+ break;
+ case BO_NE:
+ CR6 = CR6_EQ;
+ ID = GetIntrinsic(VCMPEQ, ElementKind);
+ break;
+ case BO_LT:
+ CR6 = CR6_LT;
+ ID = GetIntrinsic(VCMPGT, ElementKind);
+ std::swap(FirstVecArg, SecondVecArg);
+ break;
+ case BO_GT:
+ CR6 = CR6_LT;
+ ID = GetIntrinsic(VCMPGT, ElementKind);
+ break;
+ case BO_LE:
+ if (ElementKind == BuiltinType::Float) {
+ CR6 = CR6_LT;
+ ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p;
+ std::swap(FirstVecArg, SecondVecArg);
+ }
+ else {
+ CR6 = CR6_EQ;
+ ID = GetIntrinsic(VCMPGT, ElementKind);
+ }
+ break;
+ case BO_GE:
+ if (ElementKind == BuiltinType::Float) {
+ CR6 = CR6_LT;
+ ID = llvm::Intrinsic::ppc_altivec_vcmpgefp_p;
+ }
+ else {
+ CR6 = CR6_EQ;
+ ID = GetIntrinsic(VCMPGT, ElementKind);
+ std::swap(FirstVecArg, SecondVecArg);
+ }
+ break;
+ }
+
+ Value *CR6Param = llvm::ConstantInt::get(CGF.Int32Ty, CR6);
+ llvm::Function *F = CGF.CGM.getIntrinsic(ID);
+ Result = Builder.CreateCall3(F, CR6Param, FirstVecArg, SecondVecArg, "");
+ return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
+ }
+
+ if (LHS->getType()->isFPOrFPVectorTy()) {
+ Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc,
+ LHS, RHS, "cmp");
+ } else if (LHSTy->hasSignedIntegerRepresentation()) {
+ Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc,
+ LHS, RHS, "cmp");
+ } else {
+ // Unsigned integers and pointers.
+ Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
+ LHS, RHS, "cmp");
+ }
+
+ // If this is a vector comparison, sign extend the result to the appropriate
+ // vector integer type and return it (don't convert to bool).
+ if (LHSTy->isVectorType())
+ return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext");
+
+ } else {
+ // Complex Comparison: can only be an equality comparison.
+ CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS());
+ CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS());
+
+ QualType CETy = LHSTy->getAs<ComplexType>()->getElementType();
+
+ Value *ResultR, *ResultI;
+ if (CETy->isRealFloatingType()) {
+ ResultR = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc,
+ LHS.first, RHS.first, "cmp.r");
+ ResultI = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc,
+ LHS.second, RHS.second, "cmp.i");
+ } else {
+ // Complex comparisons can only be equality comparisons. As such, signed
+ // and unsigned opcodes are the same.
+ ResultR = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
+ LHS.first, RHS.first, "cmp.r");
+ ResultI = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
+ LHS.second, RHS.second, "cmp.i");
+ }
+
+ if (E->getOpcode() == BO_EQ) {
+ Result = Builder.CreateAnd(ResultR, ResultI, "and.ri");
+ } else {
+ assert(E->getOpcode() == BO_NE &&
+ "Complex comparison other than == or != ?");
+ Result = Builder.CreateOr(ResultR, ResultI, "or.ri");
+ }
+ }
+
+ return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
+}
+
+Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ bool Ignore = TestAndClearIgnoreResultAssign();
+
+ // __block variables need to have the rhs evaluated first, plus this should
+ // improve codegen just a little.
+ Value *RHS = Visit(E->getRHS());
+ LValue LHS = EmitCheckedLValue(E->getLHS());
+
+ // Store the value into the LHS. Bit-fields are handled specially
+ // because the result is altered by the store, i.e., [C99 6.5.16p1]
+ // 'An assignment expression has the value of the left operand after
+ // the assignment...'.
+ if (LHS.isBitField())
+ CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(),
+ &RHS);
+ else
+ CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType());
+
+ // If the result is clearly ignored, return now.
+ if (Ignore)
+ return 0;
+
+ // The result of an assignment in C is the assigned r-value.
+ if (!CGF.getContext().getLangOptions().CPlusPlus)
+ return RHS;
+
+ // Objective-C property assignment never reloads the value following a store.
+ if (LHS.isPropertyRef())
+ return RHS;
+
+ // If the lvalue is non-volatile, return the computed value of the assignment.
+ if (!LHS.isVolatileQualified())
+ return RHS;
+
+ // Otherwise, reload the value.
+ return EmitLoadOfLValue(LHS, E->getType());
+}
+
+Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
+ // If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
+ // If we have 1 && X, just emit X without inserting the control flow.
+ if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
+ if (Cond == 1) { // If we have 1 && X, just emit X.
+ Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");
+ }
+
+ // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
+ if (!CGF.ContainsLabel(E->getRHS()))
+ return llvm::Constant::getNullValue(ResTy);
+ }
+
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end");
+ llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("land.rhs");
+
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+
+ // Branch on the LHS first. If it is false, go to the failure (cont) block.
+ CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, ContBlock);
+
+ // Any edges into the ContBlock are now from an (indeterminate number of)
+ // edges from this first condition. All of these values will be false. Start
+ // setting up the PHI node in the Cont Block for this.
+ llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext),
+ "", ContBlock);
+ PN->reserveOperandSpace(2); // Normal case, two inputs.
+ for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock);
+ PI != PE; ++PI)
+ PN->addIncoming(llvm::ConstantInt::getFalse(VMContext), *PI);
+
+ eval.begin(CGF);
+ CGF.EmitBlock(RHSBlock);
+ Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+ eval.end(CGF);
+
+ // Reaquire the RHS block, as there may be subblocks inserted.
+ RHSBlock = Builder.GetInsertBlock();
+
+ // Emit an unconditional branch from this block to ContBlock. Insert an entry
+ // into the phi node for the edge with the value of RHSCond.
+ CGF.EmitBlock(ContBlock);
+ PN->addIncoming(RHSCond, RHSBlock);
+
+ // ZExt result to int.
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
+}
+
+Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
+ // If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
+ // If we have 0 || X, just emit X without inserting the control flow.
+ if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
+ if (Cond == -1) { // If we have 0 || X, just emit X.
+ Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");
+ }
+
+ // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
+ if (!CGF.ContainsLabel(E->getRHS()))
+ return llvm::ConstantInt::get(ResTy, 1);
+ }
+
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end");
+ llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("lor.rhs");
+
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+
+ // Branch on the LHS first. If it is true, go to the success (cont) block.
+ CGF.EmitBranchOnBoolExpr(E->getLHS(), ContBlock, RHSBlock);
+
+ // Any edges into the ContBlock are now from an (indeterminate number of)
+ // edges from this first condition. All of these values will be true. Start
+ // setting up the PHI node in the Cont Block for this.
+ llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext),
+ "", ContBlock);
+ PN->reserveOperandSpace(2); // Normal case, two inputs.
+ for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock);
+ PI != PE; ++PI)
+ PN->addIncoming(llvm::ConstantInt::getTrue(VMContext), *PI);
+
+ eval.begin(CGF);
+
+ // Emit the RHS condition as a bool value.
+ CGF.EmitBlock(RHSBlock);
+ Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
+
+ eval.end(CGF);
+
+ // Reaquire the RHS block, as there may be subblocks inserted.
+ RHSBlock = Builder.GetInsertBlock();
+
+ // Emit an unconditional branch from this block to ContBlock. Insert an entry
+ // into the phi node for the edge with the value of RHSCond.
+ CGF.EmitBlock(ContBlock);
+ PN->addIncoming(RHSCond, RHSBlock);
+
+ // ZExt result to int.
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");
+}
+
+Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
+ CGF.EmitIgnoredExpr(E->getLHS());
+ CGF.EnsureInsertPoint();
+ return Visit(E->getRHS());
+}
+
+//===----------------------------------------------------------------------===//
+// Other Operators
+//===----------------------------------------------------------------------===//
+
+/// isCheapEnoughToEvaluateUnconditionally - Return true if the specified
+/// expression is cheap enough and side-effect-free enough to evaluate
+/// unconditionally instead of conditionally. This is used to convert control
+/// flow into selects in some cases.
+static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+ CodeGenFunction &CGF) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr(), CGF);
+
+ // TODO: Allow anything we can constant fold to an integer or fp constant.
+ if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) ||
+ isa<FloatingLiteral>(E))
+ return true;
+
+ // Non-volatile automatic variables too, to get "cond ? X : Y" where
+ // X and Y are local variables.
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VD->hasLocalStorage() && !(CGF.getContext()
+ .getCanonicalType(VD->getType())
+ .isVolatileQualified()))
+ return true;
+
+ return false;
+}
+
+
+Value *ScalarExprEmitter::
+VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ TestAndClearIgnoreResultAssign();
+
+ // Bind the common expression if necessary.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E);
+
+ Expr *condExpr = E->getCond();
+ Expr *lhsExpr = E->getTrueExpr();
+ Expr *rhsExpr = E->getFalseExpr();
+
+ // If the condition constant folds and can be elided, try to avoid emitting
+ // the condition and the dead arm.
+ if (int Cond = CGF.ConstantFoldsToSimpleInteger(condExpr)){
+ Expr *live = lhsExpr, *dead = rhsExpr;
+ if (Cond == -1) std::swap(live, dead);
+
+ // If the dead side doesn't have labels we need, and if the Live side isn't
+ // the gnu missing ?: extension (which we could handle, but don't bother
+ // to), just emit the Live part.
+ if (!CGF.ContainsLabel(dead))
+ return Visit(live);
+ }
+
+ // OpenCL: If the condition is a vector, we can treat this condition like
+ // the select function.
+ if (CGF.getContext().getLangOptions().OpenCL
+ && condExpr->getType()->isVectorType()) {
+ llvm::Value *CondV = CGF.EmitScalarExpr(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
+
+ const llvm::Type *condType = ConvertType(condExpr->getType());
+ const llvm::VectorType *vecTy = cast<llvm::VectorType>(condType);
+
+ unsigned numElem = vecTy->getNumElements();
+ const llvm::Type *elemType = vecTy->getElementType();
+
+ std::vector<llvm::Constant*> Zvals;
+ for (unsigned i = 0; i < numElem; ++i)
+ Zvals.push_back(llvm::ConstantInt::get(elemType,0));
+
+ llvm::Value *zeroVec = llvm::ConstantVector::get(Zvals);
+ llvm::Value *TestMSB = Builder.CreateICmpSLT(CondV, zeroVec);
+ llvm::Value *tmp = Builder.CreateSExt(TestMSB,
+ llvm::VectorType::get(elemType,
+ numElem),
+ "sext");
+ llvm::Value *tmp2 = Builder.CreateNot(tmp);
+
+ // Cast float to int to perform ANDs if necessary.
+ llvm::Value *RHSTmp = RHS;
+ llvm::Value *LHSTmp = LHS;
+ bool wasCast = false;
+ const llvm::VectorType *rhsVTy = cast<llvm::VectorType>(RHS->getType());
+ if (rhsVTy->getElementType()->isFloatTy()) {
+ RHSTmp = Builder.CreateBitCast(RHS, tmp2->getType());
+ LHSTmp = Builder.CreateBitCast(LHS, tmp->getType());
+ wasCast = true;
+ }
+
+ llvm::Value *tmp3 = Builder.CreateAnd(RHSTmp, tmp2);
+ llvm::Value *tmp4 = Builder.CreateAnd(LHSTmp, tmp);
+ llvm::Value *tmp5 = Builder.CreateOr(tmp3, tmp4, "cond");
+ if (wasCast)
+ tmp5 = Builder.CreateBitCast(tmp5, RHS->getType());
+
+ return tmp5;
+ }
+
+ // If this is a really simple expression (like x ? 4 : 5), emit this as a
+ // select instead of as control flow. We can only do this if it is cheap and
+ // safe to evaluate the LHS and RHS unconditionally.
+ if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) &&
+ isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) {
+ llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
+ llvm::Value *LHS = Visit(lhsExpr);
+ llvm::Value *RHS = Visit(rhsExpr);
+ return Builder.CreateSelect(CondV, LHS, RHS, "cond");
+ }
+
+ llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
+ llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
+
+ CodeGenFunction::ConditionalEvaluation eval(CGF);
+ CGF.EmitBranchOnBoolExpr(condExpr, LHSBlock, RHSBlock);
+
+ CGF.EmitBlock(LHSBlock);
+ eval.begin(CGF);
+ Value *LHS = Visit(lhsExpr);
+ eval.end(CGF);
+
+ LHSBlock = Builder.GetInsertBlock();
+ Builder.CreateBr(ContBlock);
+
+ CGF.EmitBlock(RHSBlock);
+ eval.begin(CGF);
+ Value *RHS = Visit(rhsExpr);
+ eval.end(CGF);
+
+ RHSBlock = Builder.GetInsertBlock();
+ CGF.EmitBlock(ContBlock);
+
+ // If the LHS or RHS is a throw expression, it will be legitimately null.
+ if (!LHS)
+ return RHS;
+ if (!RHS)
+ return LHS;
+
+ // Create a PHI node for the real part.
+ llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), "cond");
+ PN->reserveOperandSpace(2);
+ PN->addIncoming(LHS, LHSBlock);
+ PN->addIncoming(RHS, RHSBlock);
+ return PN;
+}
+
+Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
+ return Visit(E->getChosenSubExpr(CGF.getContext()));
+}
+
+Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
+ llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
+ llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+
+ // If EmitVAArg fails, we fall back to the LLVM instruction.
+ if (!ArgPtr)
+ return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType()));
+
+ // FIXME Volatility.
+ return Builder.CreateLoad(ArgPtr);
+}
+
+Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) {
+ return CGF.EmitBlockLiteral(block);
+}
+
+//===----------------------------------------------------------------------===//
+// Entry Point into this File
+//===----------------------------------------------------------------------===//
+
+/// EmitScalarExpr - Emit the computation of the specified expression of scalar
+/// type, ignoring the result.
+Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
+ assert(E && !hasAggregateLLVMType(E->getType()) &&
+ "Invalid scalar expression to emit");
+
+ return ScalarExprEmitter(*this, IgnoreResultAssign)
+ .Visit(const_cast<Expr*>(E));
+}
+
+/// EmitScalarConversion - Emit a conversion from the specified type to the
+/// specified destination type, both of which are LLVM scalar types.
+Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy,
+ QualType DstTy) {
+ assert(!hasAggregateLLVMType(SrcTy) && !hasAggregateLLVMType(DstTy) &&
+ "Invalid scalar expression to emit");
+ return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy);
+}
+
+/// EmitComplexToScalarConversion - Emit a conversion from the specified complex
+/// type to the specified destination type, where the destination type is an
+/// LLVM scalar type.
+Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src,
+ QualType SrcTy,
+ QualType DstTy) {
+ assert(SrcTy->isAnyComplexType() && !hasAggregateLLVMType(DstTy) &&
+ "Invalid complex -> scalar conversion");
+ return ScalarExprEmitter(*this).EmitComplexToScalarConversion(Src, SrcTy,
+ DstTy);
+}
+
+
+llvm::Value *CodeGenFunction::
+EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre) {
+ return ScalarExprEmitter(*this).EmitScalarPrePostIncDec(E, LV, isInc, isPre);
+}
+
+LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
+ llvm::Value *V;
+ // object->isa or (*object).isa
+ // Generate code as for: *(Class*)object
+ // build Class* type
+ const llvm::Type *ClassPtrTy = ConvertType(E->getType());
+
+ Expr *BaseExpr = E->getBase();
+ if (BaseExpr->isRValue()) {
+ V = CreateTempAlloca(ClassPtrTy, "resval");
+ llvm::Value *Src = EmitScalarExpr(BaseExpr);
+ Builder.CreateStore(Src, V);
+ V = ScalarExprEmitter(*this).EmitLoadOfLValue(
+ MakeAddrLValue(V, E->getType()), E->getType());
+ } else {
+ if (E->isArrow())
+ V = ScalarExprEmitter(*this).EmitLoadOfLValue(BaseExpr);
+ else
+ V = EmitLValue(BaseExpr).getAddress();
+ }
+
+ // build Class* type
+ ClassPtrTy = ClassPtrTy->getPointerTo();
+ V = Builder.CreateBitCast(V, ClassPtrTy);
+ return MakeAddrLValue(V, E->getType());
+}
+
+
+LValue CodeGenFunction::EmitCompoundAssignmentLValue(
+ const CompoundAssignOperator *E) {
+ ScalarExprEmitter Scalar(*this);
+ Value *Result = 0;
+ switch (E->getOpcode()) {
+#define COMPOUND_OP(Op) \
+ case BO_##Op##Assign: \
+ return Scalar.EmitCompoundAssignLValue(E, &ScalarExprEmitter::Emit##Op, \
+ Result)
+ COMPOUND_OP(Mul);
+ COMPOUND_OP(Div);
+ COMPOUND_OP(Rem);
+ COMPOUND_OP(Add);
+ COMPOUND_OP(Sub);
+ COMPOUND_OP(Shl);
+ COMPOUND_OP(Shr);
+ COMPOUND_OP(And);
+ COMPOUND_OP(Xor);
+ COMPOUND_OP(Or);
+#undef COMPOUND_OP
+
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_Assign:
+ case BO_Comma:
+ assert(false && "Not valid compound assignment operators");
+ break;
+ }
+
+ llvm_unreachable("Unhandled compound assignment operator");
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
new file mode 100644
index 0000000..08c458b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -0,0 +1,923 @@
+//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Objective-C code as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CGObjCRuntime.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+/// Emits an instance of NSConstantString representing the object.
+llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
+{
+ llvm::Constant *C =
+ CGM.getObjCRuntime().GenerateConstantString(E->getString());
+ // FIXME: This bitcast should just be made an invariant on the Runtime.
+ return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
+}
+
+/// Emit a selector.
+llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
+ // Untyped selector.
+ // Note that this implementation allows for non-constant strings to be passed
+ // as arguments to @selector(). Currently, the only thing preventing this
+ // behaviour is the type checking in the front end.
+ return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector());
+}
+
+llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
+ // FIXME: This should pass the Decl not the name.
+ return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol());
+}
+
+
+RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
+ ReturnValueSlot Return) {
+ // Only the lookup mechanism and first two arguments of the method
+ // implementation vary between runtimes. We can get the receiver and
+ // arguments in generic code.
+
+ CGObjCRuntime &Runtime = CGM.getObjCRuntime();
+ bool isSuperMessage = false;
+ bool isClassMessage = false;
+ ObjCInterfaceDecl *OID = 0;
+ // Find the receiver
+ llvm::Value *Receiver = 0;
+ switch (E->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ Receiver = EmitScalarExpr(E->getInstanceReceiver());
+ break;
+
+ case ObjCMessageExpr::Class: {
+ const ObjCObjectType *ObjTy
+ = E->getClassReceiver()->getAs<ObjCObjectType>();
+ assert(ObjTy && "Invalid Objective-C class message send");
+ OID = ObjTy->getInterface();
+ assert(OID && "Invalid Objective-C class message send");
+ Receiver = Runtime.GetClass(Builder, OID);
+ isClassMessage = true;
+ break;
+ }
+
+ case ObjCMessageExpr::SuperInstance:
+ Receiver = LoadObjCSelf();
+ isSuperMessage = true;
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ Receiver = LoadObjCSelf();
+ isSuperMessage = true;
+ isClassMessage = true;
+ break;
+ }
+
+ CallArgList Args;
+ EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end());
+
+ QualType ResultType =
+ E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType();
+
+ if (isSuperMessage) {
+ // super is only valid in an Objective-C method
+ const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
+ bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
+ return Runtime.GenerateMessageSendSuper(*this, Return, ResultType,
+ E->getSelector(),
+ OMD->getClassInterface(),
+ isCategoryImpl,
+ Receiver,
+ isClassMessage,
+ Args,
+ E->getMethodDecl());
+ }
+
+ return Runtime.GenerateMessageSend(*this, Return, ResultType,
+ E->getSelector(),
+ Receiver, Args, OID,
+ E->getMethodDecl());
+}
+
+/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
+/// the LLVM function and sets the other context used by
+/// CodeGenFunction.
+void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) {
+ FunctionArgList Args;
+ // Check if we should generate debug info for this method.
+ if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>())
+ DebugInfo = CGM.getDebugInfo();
+
+ llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
+
+ const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD);
+ CGM.SetInternalFunctionAttributes(OMD, Fn, FI);
+
+ Args.push_back(std::make_pair(OMD->getSelfDecl(),
+ OMD->getSelfDecl()->getType()));
+ Args.push_back(std::make_pair(OMD->getCmdDecl(),
+ OMD->getCmdDecl()->getType()));
+
+ for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+ E = OMD->param_end(); PI != E; ++PI)
+ Args.push_back(std::make_pair(*PI, (*PI)->getType()));
+
+ CurGD = OMD;
+
+ StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart());
+}
+
+void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar,
+ bool IsAtomic, bool IsStrong) {
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
+ Ivar, 0);
+ llvm::Value *GetCopyStructFn =
+ CGM.getObjCRuntime().GetGetStructFunction();
+ CodeGenTypes &Types = CGM.getTypes();
+ // objc_copyStruct (ReturnValue, &structIvar,
+ // sizeof (Type of Ivar), isAtomic, false);
+ CallArgList Args;
+ RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue,
+ Types.ConvertType(getContext().VoidPtrTy)));
+ Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+ RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
+ Types.ConvertType(getContext().VoidPtrTy)));
+ Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+ // sizeof (Type of Ivar)
+ CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
+ Size.getQuantity());
+ Args.push_back(std::make_pair(RValue::get(SizeVal),
+ getContext().LongTy));
+ llvm::Value *isAtomic =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
+ IsAtomic ? 1 : 0);
+ Args.push_back(std::make_pair(RValue::get(isAtomic),
+ getContext().BoolTy));
+ llvm::Value *hasStrong =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
+ IsStrong ? 1 : 0);
+ Args.push_back(std::make_pair(RValue::get(hasStrong),
+ getContext().BoolTy));
+ EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+ FunctionType::ExtInfo()),
+ GetCopyStructFn, ReturnValueSlot(), Args);
+}
+
+/// Generate an Objective-C method. An Objective-C method is a C function with
+/// its pointer, name, and types registered in the class struture.
+void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
+ StartObjCMethod(OMD, OMD->getClassInterface());
+ EmitStmt(OMD->getBody());
+ FinishFunction(OMD->getBodyRBrace());
+}
+
+// FIXME: I wasn't sure about the synthesis approach. If we end up generating an
+// AST for the whole body we can just fall back to having a GenerateFunction
+// which takes the body Stmt.
+
+/// GenerateObjCGetter - Generate an Objective-C property getter
+/// function. The given Decl must be an ObjCImplementationDecl. @synthesize
+/// is illegal within a category.
+void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
+ const ObjCPropertyImplDecl *PID) {
+ ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+ const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+ bool IsAtomic =
+ !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
+ ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
+ assert(OMD && "Invalid call to generate getter (empty method)");
+ StartObjCMethod(OMD, IMP->getClassInterface());
+
+ // Determine if we should use an objc_getProperty call for
+ // this. Non-atomic properties are directly evaluated.
+ // atomic 'copy' and 'retain' properties are also directly
+ // evaluated in gc-only mode.
+ if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
+ IsAtomic &&
+ (PD->getSetterKind() == ObjCPropertyDecl::Copy ||
+ PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
+ llvm::Value *GetPropertyFn =
+ CGM.getObjCRuntime().GetPropertyGetFunction();
+
+ if (!GetPropertyFn) {
+ CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
+ FinishFunction();
+ return;
+ }
+
+ // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
+ // FIXME: Can't this be simpler? This might even be worse than the
+ // corresponding gcc code.
+ CodeGenTypes &Types = CGM.getTypes();
+ ValueDecl *Cmd = OMD->getCmdDecl();
+ llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
+ QualType IdTy = getContext().getObjCIdType();
+ llvm::Value *SelfAsId =
+ Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
+ llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
+ llvm::Value *True =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+ CallArgList Args;
+ Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
+ Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
+ Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
+ Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
+ // FIXME: We shouldn't need to get the function info here, the
+ // runtime already should have computed it to build the function.
+ RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args,
+ FunctionType::ExtInfo()),
+ GetPropertyFn, ReturnValueSlot(), Args);
+ // We need to fix the type here. Ivars with copy & retain are
+ // always objects so we don't need to worry about complex or
+ // aggregates.
+ RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
+ Types.ConvertType(PD->getType())));
+ EmitReturnOfRValue(RV, PD->getType());
+ } else {
+ const llvm::Triple &Triple = getContext().Target.getTriple();
+ QualType IVART = Ivar->getType();
+ if (IsAtomic &&
+ IVART->isScalarType() &&
+ (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) &&
+ (getContext().getTypeSizeInChars(IVART)
+ > CharUnits::fromQuantity(4)) &&
+ CGM.getObjCRuntime().GetGetStructFunction()) {
+ GenerateObjCGetterBody(Ivar, true, false);
+ }
+ else if (IVART->isAnyComplexType()) {
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
+ Ivar, 0);
+ ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(),
+ LV.isVolatileQualified());
+ StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
+ }
+ else if (hasAggregateLLVMType(IVART)) {
+ bool IsStrong = false;
+ if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(IVART)))
+ && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
+ && CGM.getObjCRuntime().GetGetStructFunction()) {
+ GenerateObjCGetterBody(Ivar, IsAtomic, IsStrong);
+ }
+ else {
+ if (PID->getGetterCXXConstructor()) {
+ ReturnStmt *Stmt =
+ new (getContext()) ReturnStmt(SourceLocation(),
+ PID->getGetterCXXConstructor(),
+ 0);
+ EmitReturnStmt(*Stmt);
+ }
+ else {
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
+ Ivar, 0);
+ EmitAggregateCopy(ReturnValue, LV.getAddress(), IVART);
+ }
+ }
+ }
+ else {
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
+ Ivar, 0);
+ CodeGenTypes &Types = CGM.getTypes();
+ RValue RV = EmitLoadOfLValue(LV, IVART);
+ RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
+ Types.ConvertType(PD->getType())));
+ EmitReturnOfRValue(RV, PD->getType());
+ }
+ }
+
+ FinishFunction();
+}
+
+void CodeGenFunction::GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD,
+ ObjCIvarDecl *Ivar) {
+ // objc_copyStruct (&structIvar, &Arg,
+ // sizeof (struct something), true, false);
+ llvm::Value *GetCopyStructFn =
+ CGM.getObjCRuntime().GetSetStructFunction();
+ CodeGenTypes &Types = CGM.getTypes();
+ CallArgList Args;
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
+ RValue RV =
+ RValue::get(Builder.CreateBitCast(LV.getAddress(),
+ Types.ConvertType(getContext().VoidPtrTy)));
+ Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+ llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
+ llvm::Value *ArgAsPtrTy =
+ Builder.CreateBitCast(Arg,
+ Types.ConvertType(getContext().VoidPtrTy));
+ RV = RValue::get(ArgAsPtrTy);
+ Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+ // sizeof (Type of Ivar)
+ CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType());
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy),
+ Size.getQuantity());
+ Args.push_back(std::make_pair(RValue::get(SizeVal),
+ getContext().LongTy));
+ llvm::Value *True =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+ Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
+ llvm::Value *False =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
+ Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
+ EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+ FunctionType::ExtInfo()),
+ GetCopyStructFn, ReturnValueSlot(), Args);
+}
+
+/// GenerateObjCSetter - Generate an Objective-C property setter
+/// function. The given Decl must be an ObjCImplementationDecl. @synthesize
+/// is illegal within a category.
+void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
+ const ObjCPropertyImplDecl *PID) {
+ ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+ const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+ ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
+ assert(OMD && "Invalid call to generate setter (empty method)");
+ StartObjCMethod(OMD, IMP->getClassInterface());
+
+ bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
+ bool IsAtomic =
+ !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
+
+ // Determine if we should use an objc_setProperty call for
+ // this. Properties with 'copy' semantics always use it, as do
+ // non-atomic properties with 'release' semantics as long as we are
+ // not in gc-only mode.
+ if (IsCopy ||
+ (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
+ PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
+ llvm::Value *SetPropertyFn =
+ CGM.getObjCRuntime().GetPropertySetFunction();
+
+ if (!SetPropertyFn) {
+ CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
+ FinishFunction();
+ return;
+ }
+
+ // Emit objc_setProperty((id) self, _cmd, offset, arg,
+ // <is-atomic>, <is-copy>).
+ // FIXME: Can't this be simpler? This might even be worse than the
+ // corresponding gcc code.
+ CodeGenTypes &Types = CGM.getTypes();
+ ValueDecl *Cmd = OMD->getCmdDecl();
+ llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
+ QualType IdTy = getContext().getObjCIdType();
+ llvm::Value *SelfAsId =
+ Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
+ llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
+ llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
+ llvm::Value *ArgAsId =
+ Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"),
+ Types.ConvertType(IdTy));
+ llvm::Value *True =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+ llvm::Value *False =
+ llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
+ CallArgList Args;
+ Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
+ Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
+ Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
+ Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy));
+ Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False),
+ getContext().BoolTy));
+ Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False),
+ getContext().BoolTy));
+ // FIXME: We shouldn't need to get the function info here, the runtime
+ // already should have computed it to build the function.
+ EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+ FunctionType::ExtInfo()),
+ SetPropertyFn,
+ ReturnValueSlot(), Args);
+ } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) &&
+ !Ivar->getType()->isAnyComplexType() &&
+ IndirectObjCSetterArg(*CurFnInfo)
+ && CGM.getObjCRuntime().GetSetStructFunction()) {
+ // objc_copyStruct (&structIvar, &Arg,
+ // sizeof (struct something), true, false);
+ GenerateObjCAtomicSetterBody(OMD, Ivar);
+ } else if (PID->getSetterCXXAssignment()) {
+ EmitIgnoredExpr(PID->getSetterCXXAssignment());
+ } else {
+ const llvm::Triple &Triple = getContext().Target.getTriple();
+ QualType IVART = Ivar->getType();
+ if (IsAtomic &&
+ IVART->isScalarType() &&
+ (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) &&
+ (getContext().getTypeSizeInChars(IVART)
+ > CharUnits::fromQuantity(4)) &&
+ CGM.getObjCRuntime().GetGetStructFunction()) {
+ GenerateObjCAtomicSetterBody(OMD, Ivar);
+ }
+ else {
+ // FIXME: Find a clean way to avoid AST node creation.
+ SourceLocation Loc = PD->getLocation();
+ ValueDecl *Self = OMD->getSelfDecl();
+ ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
+ DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc);
+ ParmVarDecl *ArgDecl = *OMD->param_begin();
+ DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc);
+ ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
+
+ // The property type can differ from the ivar type in some situations with
+ // Objective-C pointer types, we can always bit cast the RHS in these cases.
+ if (getContext().getCanonicalType(Ivar->getType()) !=
+ getContext().getCanonicalType(ArgDecl->getType())) {
+ ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
+ Ivar->getType(), CK_BitCast, &Arg,
+ VK_RValue);
+ BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
+ Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
+ EmitStmt(&Assign);
+ } else {
+ BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
+ Ivar->getType(), VK_RValue, OK_Ordinary, Loc);
+ EmitStmt(&Assign);
+ }
+ }
+ }
+
+ FinishFunction();
+}
+
+void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
+ ObjCMethodDecl *MD,
+ bool ctor) {
+ llvm::SmallVector<CXXCtorInitializer *, 8> IvarInitializers;
+ MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface());
+ StartObjCMethod(MD, IMP->getClassInterface());
+ for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(),
+ E = IMP->init_end(); B != E; ++B) {
+ CXXCtorInitializer *Member = (*B);
+ IvarInitializers.push_back(Member);
+ }
+ if (ctor) {
+ for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) {
+ CXXCtorInitializer *IvarInit = IvarInitializers[I];
+ FieldDecl *Field = IvarInit->getAnyMember();
+ ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
+ LoadObjCSelf(), Ivar, 0);
+ EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, true));
+ }
+ // constructor returns 'self'.
+ CodeGenTypes &Types = CGM.getTypes();
+ QualType IdTy(CGM.getContext().getObjCIdType());
+ llvm::Value *SelfAsId =
+ Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
+ EmitReturnOfRValue(RValue::get(SelfAsId), IdTy);
+ } else {
+ // dtor
+ for (size_t i = IvarInitializers.size(); i > 0; --i) {
+ FieldDecl *Field = IvarInitializers[i - 1]->getAnyMember();
+ QualType FieldType = Field->getType();
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(FieldType);
+ if (Array)
+ FieldType = getContext().getBaseElementType(FieldType);
+
+ ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
+ LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
+ LoadObjCSelf(), Ivar, 0);
+ const RecordType *RT = FieldType->getAs<RecordType>();
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor();
+ if (!Dtor->isTrivial()) {
+ if (Array) {
+ const llvm::Type *BasePtr = ConvertType(FieldType);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(LV.getAddress(), BasePtr);
+ EmitCXXAggrDestructorCall(Dtor,
+ Array, BaseAddrPtr);
+ } else {
+ EmitCXXDestructorCall(Dtor,
+ Dtor_Complete, /*ForVirtualBase=*/false,
+ LV.getAddress());
+ }
+ }
+ }
+ }
+ FinishFunction();
+}
+
+bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
+ CGFunctionInfo::const_arg_iterator it = FI.arg_begin();
+ it++; it++;
+ const ABIArgInfo &AI = it->info;
+ // FIXME. Is this sufficient check?
+ return (AI.getKind() == ABIArgInfo::Indirect);
+}
+
+bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
+ if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+ return false;
+ if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>())
+ return FDTTy->getDecl()->hasObjectMember();
+ return false;
+}
+
+llvm::Value *CodeGenFunction::LoadObjCSelf() {
+ const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
+ return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
+}
+
+QualType CodeGenFunction::TypeOfSelfObject() {
+ const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
+ ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
+ const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>(
+ getContext().getCanonicalType(selfDecl->getType()));
+ return PTy->getPointeeType();
+}
+
+LValue
+CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) {
+ // This is a special l-value that just issues sends when we load or
+ // store through it.
+
+ // For certain base kinds, we need to emit the base immediately.
+ llvm::Value *Base;
+ if (E->isSuperReceiver())
+ Base = LoadObjCSelf();
+ else if (E->isClassReceiver())
+ Base = CGM.getObjCRuntime().GetClass(Builder, E->getClassReceiver());
+ else
+ Base = EmitScalarExpr(E->getBase());
+ return LValue::MakePropertyRef(E, Base);
+}
+
+static RValue GenerateMessageSendSuper(CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector S,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs) {
+ const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CGF.CurFuncDecl);
+ bool isClassMessage = OMD->isClassMethod();
+ bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
+ return CGF.CGM.getObjCRuntime()
+ .GenerateMessageSendSuper(CGF, Return, ResultType,
+ S, OMD->getClassInterface(),
+ isCategoryImpl, Receiver,
+ isClassMessage, CallArgs);
+}
+
+RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV,
+ ReturnValueSlot Return) {
+ const ObjCPropertyRefExpr *E = LV.getPropertyRefExpr();
+ QualType ResultType;
+ Selector S;
+ if (E->isExplicitProperty()) {
+ const ObjCPropertyDecl *Property = E->getExplicitProperty();
+ S = Property->getGetterName();
+ ResultType = E->getType();
+ } else {
+ const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter();
+ S = Getter->getSelector();
+ ResultType = Getter->getResultType(); // with reference!
+ }
+
+ llvm::Value *Receiver = LV.getPropertyRefBaseAddr();
+
+ // Accesses to 'super' follow a different code path.
+ if (E->isSuperReceiver())
+ return GenerateMessageSendSuper(*this, Return, ResultType,
+ S, Receiver, CallArgList());
+
+ const ObjCInterfaceDecl *ReceiverClass
+ = (E->isClassReceiver() ? E->getClassReceiver() : 0);
+ return CGM.getObjCRuntime().
+ GenerateMessageSend(*this, Return, ResultType, S,
+ Receiver, CallArgList(), ReceiverClass);
+}
+
+void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src,
+ LValue Dst) {
+ const ObjCPropertyRefExpr *E = Dst.getPropertyRefExpr();
+ Selector S = E->getSetterSelector();
+ QualType ArgType;
+ if (E->isImplicitProperty()) {
+ const ObjCMethodDecl *Setter = E->getImplicitPropertySetter();
+ ObjCMethodDecl::param_iterator P = Setter->param_begin();
+ ArgType = (*P)->getType();
+ } else {
+ ArgType = E->getType();
+ }
+ // FIXME. Other than scalars, AST is not adequate for setter and
+ // getter type mismatches which require conversion.
+ if (Src.isScalar()) {
+ llvm::Value *SrcVal = Src.getScalarVal();
+ QualType DstType = getContext().getCanonicalType(ArgType);
+ const llvm::Type *DstTy = ConvertType(DstType);
+ if (SrcVal->getType() != DstTy)
+ Src =
+ RValue::get(EmitScalarConversion(SrcVal, E->getType(), DstType));
+ }
+
+ CallArgList Args;
+ Args.push_back(std::make_pair(Src, ArgType));
+
+ llvm::Value *Receiver = Dst.getPropertyRefBaseAddr();
+ QualType ResultType = getContext().VoidTy;
+
+ if (E->isSuperReceiver()) {
+ GenerateMessageSendSuper(*this, ReturnValueSlot(),
+ ResultType, S, Receiver, Args);
+ return;
+ }
+
+ const ObjCInterfaceDecl *ReceiverClass
+ = (E->isClassReceiver() ? E->getClassReceiver() : 0);
+
+ CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+ ResultType, S, Receiver, Args,
+ ReceiverClass);
+}
+
+void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
+ llvm::Constant *EnumerationMutationFn =
+ CGM.getObjCRuntime().EnumerationMutationFunction();
+
+ if (!EnumerationMutationFn) {
+ CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
+ return;
+ }
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI) {
+ DI->setLocation(S.getSourceRange().getBegin());
+ DI->EmitRegionStart(Builder);
+ }
+
+ JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end");
+ JumpDest AfterBody = getJumpDestInCurrentScope("forcoll.next");
+
+ // Fast enumeration state.
+ QualType StateTy = getContext().getObjCFastEnumerationStateType();
+ llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
+ EmitNullInitialization(StatePtr, StateTy);
+
+ // Number of elements in the items array.
+ static const unsigned NumItems = 16;
+
+ // Fetch the countByEnumeratingWithState:objects:count: selector.
+ IdentifierInfo *II[] = {
+ &CGM.getContext().Idents.get("countByEnumeratingWithState"),
+ &CGM.getContext().Idents.get("objects"),
+ &CGM.getContext().Idents.get("count")
+ };
+ Selector FastEnumSel =
+ CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]);
+
+ QualType ItemsTy =
+ getContext().getConstantArrayType(getContext().getObjCIdType(),
+ llvm::APInt(32, NumItems),
+ ArrayType::Normal, 0);
+ llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
+
+ // Emit the collection pointer.
+ llvm::Value *Collection = EmitScalarExpr(S.getCollection());
+
+ // Send it our message:
+ CallArgList Args;
+
+ // The first argument is a temporary of the enumeration-state type.
+ Args.push_back(std::make_pair(RValue::get(StatePtr),
+ getContext().getPointerType(StateTy)));
+
+ // The second argument is a temporary array with space for NumItems
+ // pointers. We'll actually be loading elements from the array
+ // pointer written into the control state; this buffer is so that
+ // collections that *aren't* backed by arrays can still queue up
+ // batches of elements.
+ Args.push_back(std::make_pair(RValue::get(ItemsPtr),
+ getContext().getPointerType(ItemsTy)));
+
+ // The third argument is the capacity of that temporary array.
+ const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
+ llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
+ Args.push_back(std::make_pair(RValue::get(Count),
+ getContext().UnsignedLongTy));
+
+ // Start the enumeration.
+ RValue CountRV =
+ CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+ getContext().UnsignedLongTy,
+ FastEnumSel,
+ Collection, Args);
+
+ // The initial number of objects that were returned in the buffer.
+ llvm::Value *initialBufferLimit = CountRV.getScalarVal();
+
+ llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty");
+ llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit");
+
+ llvm::Value *zero = llvm::Constant::getNullValue(UnsignedLongLTy);
+
+ // If the limit pointer was zero to begin with, the collection is
+ // empty; skip all this.
+ Builder.CreateCondBr(Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"),
+ EmptyBB, LoopInitBB);
+
+ // Otherwise, initialize the loop.
+ EmitBlock(LoopInitBB);
+
+ // Save the initial mutations value. This is the value at an
+ // address that was written into the state object by
+ // countByEnumeratingWithState:objects:count:.
+ llvm::Value *StateMutationsPtrPtr =
+ Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
+ llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
+ "mutationsptr");
+
+ llvm::Value *initialMutations =
+ Builder.CreateLoad(StateMutationsPtr, "forcoll.initial-mutations");
+
+ // Start looping. This is the point we return to whenever we have a
+ // fresh, non-empty batch of objects.
+ llvm::BasicBlock *LoopBodyBB = createBasicBlock("forcoll.loopbody");
+ EmitBlock(LoopBodyBB);
+
+ // The current index into the buffer.
+ llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, "forcoll.index");
+ index->addIncoming(zero, LoopInitBB);
+
+ // The current buffer size.
+ llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, "forcoll.count");
+ count->addIncoming(initialBufferLimit, LoopInitBB);
+
+ // Check whether the mutations value has changed from where it was
+ // at start. StateMutationsPtr should actually be invariant between
+ // refreshes.
+ StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
+ llvm::Value *currentMutations
+ = Builder.CreateLoad(StateMutationsPtr, "statemutations");
+
+ llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated");
+ llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcool.notmutated");
+
+ Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations),
+ WasNotMutatedBB, WasMutatedBB);
+
+ // If so, call the enumeration-mutation function.
+ EmitBlock(WasMutatedBB);
+ llvm::Value *V =
+ Builder.CreateBitCast(Collection,
+ ConvertType(getContext().getObjCIdType()),
+ "tmp");
+ CallArgList Args2;
+ Args2.push_back(std::make_pair(RValue::get(V),
+ getContext().getObjCIdType()));
+ // FIXME: We shouldn't need to get the function info here, the runtime already
+ // should have computed it to build the function.
+ EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
+ FunctionType::ExtInfo()),
+ EnumerationMutationFn, ReturnValueSlot(), Args2);
+
+ // Otherwise, or if the mutation function returns, just continue.
+ EmitBlock(WasNotMutatedBB);
+
+ // Initialize the element variable.
+ RunCleanupsScope elementVariableScope(*this);
+ bool elementIsDecl;
+ LValue elementLValue;
+ QualType elementType;
+ if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
+ EmitStmt(SD);
+ const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
+
+ DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
+ VK_LValue, SourceLocation());
+ elementLValue = EmitLValue(&tempDRE);
+ elementType = D->getType();
+ elementIsDecl = true;
+ } else {
+ elementLValue = LValue(); // suppress warning
+ elementType = cast<Expr>(S.getElement())->getType();
+ elementIsDecl = false;
+ }
+ const llvm::Type *convertedElementType = ConvertType(elementType);
+
+ // Fetch the buffer out of the enumeration state.
+ // TODO: this pointer should actually be invariant between
+ // refreshes, which would help us do certain loop optimizations.
+ llvm::Value *StateItemsPtr =
+ Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
+ llvm::Value *EnumStateItems =
+ Builder.CreateLoad(StateItemsPtr, "stateitems");
+
+ // Fetch the value at the current index from the buffer.
+ llvm::Value *CurrentItemPtr =
+ Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr");
+ llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr);
+
+ // Cast that value to the right type.
+ CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType,
+ "currentitem");
+
+ // Make sure we have an l-value. Yes, this gets evaluated every
+ // time through the loop.
+ if (!elementIsDecl)
+ elementLValue = EmitLValue(cast<Expr>(S.getElement()));
+
+ EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
+
+ // Perform the loop body, setting up break and continue labels.
+ BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
+ {
+ RunCleanupsScope Scope(*this);
+ EmitStmt(S.getBody());
+ }
+ BreakContinueStack.pop_back();
+
+ // Destroy the element variable now.
+ elementVariableScope.ForceCleanup();
+
+ // Check whether there are more elements.
+ EmitBlock(AfterBody.getBlock());
+
+ llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch");
+
+ // First we check in the local buffer.
+ llvm::Value *indexPlusOne
+ = Builder.CreateAdd(index, llvm::ConstantInt::get(UnsignedLongLTy, 1));
+
+ // If we haven't overrun the buffer yet, we can continue.
+ Builder.CreateCondBr(Builder.CreateICmpULT(indexPlusOne, count),
+ LoopBodyBB, FetchMoreBB);
+
+ index->addIncoming(indexPlusOne, AfterBody.getBlock());
+ count->addIncoming(count, AfterBody.getBlock());
+
+ // Otherwise, we have to fetch more elements.
+ EmitBlock(FetchMoreBB);
+
+ CountRV =
+ CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+ getContext().UnsignedLongTy,
+ FastEnumSel,
+ Collection, Args);
+
+ // If we got a zero count, we're done.
+ llvm::Value *refetchCount = CountRV.getScalarVal();
+
+ // (note that the message send might split FetchMoreBB)
+ index->addIncoming(zero, Builder.GetInsertBlock());
+ count->addIncoming(refetchCount, Builder.GetInsertBlock());
+
+ Builder.CreateCondBr(Builder.CreateICmpEQ(refetchCount, zero),
+ EmptyBB, LoopBodyBB);
+
+ // No more elements.
+ EmitBlock(EmptyBB);
+
+ if (!elementIsDecl) {
+ // If the element was not a declaration, set it to be null.
+
+ llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
+ elementLValue = EmitLValue(cast<Expr>(S.getElement()));
+ EmitStoreThroughLValue(RValue::get(null), elementLValue, elementType);
+ }
+
+ if (DI) {
+ DI->setLocation(S.getSourceRange().getEnd());
+ DI->EmitRegionEnd(Builder);
+ }
+
+ EmitBlock(LoopEnd.getBlock());
+}
+
+void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) {
+ CGM.getObjCRuntime().EmitTryStmt(*this, S);
+}
+
+void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) {
+ CGM.getObjCRuntime().EmitThrowStmt(*this, S);
+}
+
+void CodeGenFunction::EmitObjCAtSynchronizedStmt(
+ const ObjCAtSynchronizedStmt &S) {
+ CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S);
+}
+
+CGObjCRuntime::~CGObjCRuntime() {}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
new file mode 100644
index 0000000..d481e77
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -0,0 +1,2253 @@
+//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides Objective-C code generation targetting the GNU runtime. The
+// class in this file generates structures used by the GNU Objective-C runtime
+// library. These structures are defined in objc/objc.h and objc/objc-api.h in
+// the GNU runtime distribution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGObjCRuntime.h"
+#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
+#include "CGCleanup.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtObjC.h"
+
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Target/TargetData.h"
+
+#include <map>
+
+
+using namespace clang;
+using namespace CodeGen;
+using llvm::dyn_cast;
+
+// The version of the runtime that this class targets. Must match the version
+// in the runtime.
+static const int RuntimeVersion = 8;
+static const int NonFragileRuntimeVersion = 9;
+static const int ProtocolVersion = 2;
+static const int NonFragileProtocolVersion = 3;
+
+namespace {
+class CGObjCGNU : public CodeGen::CGObjCRuntime {
+private:
+ CodeGen::CodeGenModule &CGM;
+ llvm::Module &TheModule;
+ const llvm::PointerType *SelectorTy;
+ const llvm::IntegerType *Int8Ty;
+ const llvm::PointerType *PtrToInt8Ty;
+ const llvm::FunctionType *IMPTy;
+ const llvm::PointerType *IdTy;
+ const llvm::PointerType *PtrToIdTy;
+ CanQualType ASTIdTy;
+ const llvm::IntegerType *IntTy;
+ const llvm::PointerType *PtrTy;
+ const llvm::IntegerType *LongTy;
+ const llvm::IntegerType *SizeTy;
+ const llvm::IntegerType *PtrDiffTy;
+ const llvm::PointerType *PtrToIntTy;
+ const llvm::Type *BoolTy;
+ llvm::GlobalAlias *ClassPtrAlias;
+ llvm::GlobalAlias *MetaClassPtrAlias;
+ std::vector<llvm::Constant*> Classes;
+ std::vector<llvm::Constant*> Categories;
+ std::vector<llvm::Constant*> ConstantStrings;
+ llvm::StringMap<llvm::Constant*> ObjCStrings;
+ llvm::Function *LoadFunction;
+ llvm::StringMap<llvm::Constant*> ExistingProtocols;
+ typedef std::pair<std::string, std::string> TypedSelector;
+ std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
+ llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
+ // Selectors that we don't emit in GC mode
+ Selector RetainSel, ReleaseSel, AutoreleaseSel;
+ // Functions used for GC.
+ llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn,
+ *WeakAssignFn, *GlobalAssignFn;
+ // Some zeros used for GEPs in lots of places.
+ llvm::Constant *Zeros[2];
+ llvm::Constant *NULLPtr;
+ llvm::LLVMContext &VMContext;
+ /// Metadata kind used to tie method lookups to message sends.
+ unsigned msgSendMDKind;
+private:
+ llvm::Constant *GenerateIvarList(
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
+ llvm::Constant *GenerateMethodList(const std::string &ClassName,
+ const std::string &CategoryName,
+ const llvm::SmallVectorImpl<Selector> &MethodSels,
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
+ bool isClassMethodList);
+ llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
+ llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
+ llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
+ llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
+ llvm::Constant *GenerateProtocolList(
+ const llvm::SmallVectorImpl<std::string> &Protocols);
+ // To ensure that all protocols are seen by the runtime, we add a category on
+ // a class defined in the runtime, declaring no methods, but adopting the
+ // protocols.
+ void GenerateProtocolHolderCategory(void);
+ llvm::Constant *GenerateClassStructure(
+ llvm::Constant *MetaClass,
+ llvm::Constant *SuperClass,
+ unsigned info,
+ const char *Name,
+ llvm::Constant *Version,
+ llvm::Constant *InstanceSize,
+ llvm::Constant *IVars,
+ llvm::Constant *Methods,
+ llvm::Constant *Protocols,
+ llvm::Constant *IvarOffsets,
+ llvm::Constant *Properties,
+ bool isMeta=false);
+ llvm::Constant *GenerateProtocolMethodList(
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
+ llvm::Constant *MakeConstantString(const std::string &Str, const std::string
+ &Name="");
+ llvm::Constant *ExportUniqueString(const std::string &Str, const std::string
+ prefix);
+ llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
+ std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
+ llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
+ llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
+ std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
+ llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
+ llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar);
+ void EmitClassRef(const std::string &className);
+ llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){
+ if (V->getType() == Ty) return V;
+ return B.CreateBitCast(V, Ty);
+ }
+public:
+ CGObjCGNU(CodeGen::CodeGenModule &cgm);
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *);
+ virtual CodeGen::RValue
+ GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method);
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method);
+ virtual llvm::Value *GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *OID);
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval = false);
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
+ *Method);
+ virtual llvm::Constant *GetEHType(QualType T);
+
+ virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD);
+ virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
+ virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
+ virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD);
+ virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
+ virtual llvm::Function *ModuleInitFunction();
+ virtual llvm::Function *GetPropertyGetFunction();
+ virtual llvm::Function *GetPropertySetFunction();
+ virtual llvm::Function *GetSetStructFunction();
+ virtual llvm::Function *GetGetStructFunction();
+ virtual llvm::Constant *EnumerationMutationFunction();
+
+ virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S);
+ virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S);
+ virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S);
+ virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj);
+ virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst);
+ virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal=false);
+ virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ llvm::Value *ivarOffset);
+ virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest);
+ virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *DestPtr,
+ llvm::Value *SrcPtr,
+ llvm::Value *Size);
+ virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers);
+ virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar);
+ virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ return NULLPtr;
+ }
+};
+} // end anonymous namespace
+
+
+/// Emits a reference to a dummy variable which is emitted with each class.
+/// This ensures that a linker error will be generated when trying to link
+/// together modules where a referenced class is not defined.
+void CGObjCGNU::EmitClassRef(const std::string &className) {
+ std::string symbolRef = "__objc_class_ref_" + className;
+ // Don't emit two copies of the same symbol
+ if (TheModule.getGlobalVariable(symbolRef))
+ return;
+ std::string symbolName = "__objc_class_name_" + className;
+ llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
+ if (!ClassSymbol) {
+ ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
+ llvm::GlobalValue::ExternalLinkage, 0, symbolName);
+ }
+ new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
+ llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
+}
+
+static std::string SymbolNameForMethod(const std::string &ClassName, const
+ std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
+{
+ std::string MethodNameColonStripped = MethodName;
+ std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
+ ':', '_');
+ return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
+ CategoryName + "_" + MethodNameColonStripped;
+}
+static std::string MangleSelectorTypes(const std::string &TypeString) {
+ std::string Mangled = TypeString;
+ // Simple mangling to avoid breaking when we mix JIT / static code.
+ // Not part of the ABI, subject to change without notice.
+ std::replace(Mangled.begin(), Mangled.end(), '@', '_');
+ std::replace(Mangled.begin(), Mangled.end(), ':', 'J');
+ std::replace(Mangled.begin(), Mangled.end(), '*', 'e');
+ std::replace(Mangled.begin(), Mangled.end(), '#', 'E');
+ std::replace(Mangled.begin(), Mangled.end(), ':', 'j');
+ std::replace(Mangled.begin(), Mangled.end(), '(', 'g');
+ std::replace(Mangled.begin(), Mangled.end(), ')', 'G');
+ std::replace(Mangled.begin(), Mangled.end(), '[', 'h');
+ std::replace(Mangled.begin(), Mangled.end(), ']', 'H');
+ return Mangled;
+}
+
+CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
+ : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0),
+ MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) {
+
+ msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
+
+ IntTy = cast<llvm::IntegerType>(
+ CGM.getTypes().ConvertType(CGM.getContext().IntTy));
+ LongTy = cast<llvm::IntegerType>(
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy));
+ SizeTy = cast<llvm::IntegerType>(
+ CGM.getTypes().ConvertType(CGM.getContext().getSizeType()));
+ PtrDiffTy = cast<llvm::IntegerType>(
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()));
+ BoolTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
+
+ Int8Ty = llvm::Type::getInt8Ty(VMContext);
+ // C string type. Used in lots of places.
+ PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
+
+ Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
+ Zeros[1] = Zeros[0];
+ NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
+ // Get the selector Type.
+ QualType selTy = CGM.getContext().getObjCSelType();
+ if (QualType() == selTy) {
+ SelectorTy = PtrToInt8Ty;
+ } else {
+ SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
+ }
+
+ PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
+ PtrTy = PtrToInt8Ty;
+
+ // Object type
+ ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType());
+ if (QualType() == ASTIdTy) {
+ IdTy = PtrToInt8Ty;
+ } else {
+ IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
+ }
+ PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
+
+ // IMP type
+ std::vector<const llvm::Type*> IMPArgs;
+ IMPArgs.push_back(IdTy);
+ IMPArgs.push_back(SelectorTy);
+ IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
+
+ if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ // Get selectors needed in GC mode
+ RetainSel = GetNullarySelector("retain", CGM.getContext());
+ ReleaseSel = GetNullarySelector("release", CGM.getContext());
+ AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext());
+
+ // Get functions needed in GC mode
+
+ // id objc_assign_ivar(id, id, ptrdiff_t);
+ std::vector<const llvm::Type*> Args(1, IdTy);
+ Args.push_back(PtrToIdTy);
+ Args.push_back(PtrDiffTy);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false);
+ IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
+ // id objc_assign_strongCast (id, id*)
+ Args.pop_back();
+ FTy = llvm::FunctionType::get(IdTy, Args, false);
+ StrongCastAssignFn =
+ CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
+ // id objc_assign_global(id, id*);
+ FTy = llvm::FunctionType::get(IdTy, Args, false);
+ GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
+ // id objc_assign_weak(id, id*);
+ FTy = llvm::FunctionType::get(IdTy, Args, false);
+ WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
+ // id objc_read_weak(id*);
+ Args.clear();
+ Args.push_back(PtrToIdTy);
+ FTy = llvm::FunctionType::get(IdTy, Args, false);
+ WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
+ // void *objc_memmove_collectable(void*, void *, size_t);
+ Args.clear();
+ Args.push_back(PtrToInt8Ty);
+ Args.push_back(PtrToInt8Ty);
+ Args.push_back(SizeTy);
+ FTy = llvm::FunctionType::get(IdTy, Args, false);
+ MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
+ }
+}
+
+// This has to perform the lookup every time, since posing and related
+// techniques can modify the name -> class mapping.
+llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *OID) {
+ llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
+ // With the incompatible ABI, this will need to be replaced with a direct
+ // reference to the class symbol. For the compatible nonfragile ABI we are
+ // still performing this lookup at run time but emitting the symbol for the
+ // class externally so that we can make the switch later.
+ EmitClassRef(OID->getNameAsString());
+ ClassName = Builder.CreateStructGEP(ClassName, 0);
+
+ std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
+ llvm::Constant *ClassLookupFn =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy,
+ Params,
+ true),
+ "objc_lookup_class");
+ return Builder.CreateCall(ClassLookupFn, ClassName);
+}
+
+llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval) {
+ llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
+ if (US == 0)
+ US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
+ llvm::GlobalValue::PrivateLinkage,
+ ".objc_untyped_selector_alias"+Sel.getAsString(),
+ NULL, &TheModule);
+ if (lval)
+ return US;
+ return Builder.CreateLoad(US);
+}
+
+llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
+ *Method) {
+
+ std::string SelName = Method->getSelector().getAsString();
+ std::string SelTypes;
+ CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
+ // Typed selectors
+ TypedSelector Selector = TypedSelector(SelName,
+ SelTypes);
+
+ // If it's already cached, return it.
+ if (TypedSelectors[Selector]) {
+ return Builder.CreateLoad(TypedSelectors[Selector]);
+ }
+
+ // If it isn't, cache it.
+ llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
+ llvm::PointerType::getUnqual(SelectorTy),
+ llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName,
+ NULL, &TheModule);
+ TypedSelectors[Selector] = Sel;
+
+ return Builder.CreateLoad(Sel);
+}
+
+llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
+ llvm_unreachable("asking for catch type for ObjC type in GNU runtime");
+ return 0;
+}
+
+llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
+ const std::string &Name) {
+ llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
+}
+llvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str,
+ const std::string prefix) {
+ std::string name = prefix + Str;
+ llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
+ if (!ConstStr) {
+ llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true);
+ ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
+ llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
+ }
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
+}
+
+llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
+ std::vector<llvm::Constant*> &V, llvm::StringRef Name,
+ llvm::GlobalValue::LinkageTypes linkage) {
+ llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
+ return new llvm::GlobalVariable(TheModule, Ty, false,
+ linkage, C, Name);
+}
+
+llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
+ std::vector<llvm::Constant*> &V, llvm::StringRef Name,
+ llvm::GlobalValue::LinkageTypes linkage) {
+ llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
+ return new llvm::GlobalVariable(TheModule, Ty, false,
+ linkage, C, Name);
+}
+
+/// Generate an NSConstantString object.
+llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
+
+ std::string Str = SL->getString().str();
+
+ // Look for an existing one
+ llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
+ if (old != ObjCStrings.end())
+ return old->getValue();
+
+ std::vector<llvm::Constant*> Ivars;
+ Ivars.push_back(NULLPtr);
+ Ivars.push_back(MakeConstantString(Str));
+ Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
+ llvm::Constant *ObjCStr = MakeGlobal(
+ llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
+ Ivars, ".objc_str");
+ ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
+ ObjCStrings[Str] = ObjCStr;
+ ConstantStrings.push_back(ObjCStr);
+ return ObjCStr;
+}
+
+///Generates a message send where the super is the receiver. This is a message
+///send to self with special delivery semantics indicating which class's method
+///should be called.
+CodeGen::RValue
+CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method) {
+ if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ if (Sel == RetainSel || Sel == AutoreleaseSel) {
+ return RValue::get(Receiver);
+ }
+ if (Sel == ReleaseSel) {
+ return RValue::get(0);
+ }
+ }
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *cmd = GetSelector(Builder, Sel);
+
+
+ CallArgList ActualArgs;
+
+ ActualArgs.push_back(
+ std::make_pair(RValue::get(Builder.CreateBitCast(Receiver, IdTy)),
+ ASTIdTy));
+ ActualArgs.push_back(std::make_pair(RValue::get(cmd),
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ FunctionType::ExtInfo());
+ const llvm::FunctionType *impType =
+ Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
+
+ llvm::Value *ReceiverClass = 0;
+ if (isCategoryImpl) {
+ llvm::Constant *classLookupFunction = 0;
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(PtrTy);
+ if (IsClassMessage) {
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, Params, true), "objc_get_meta_class");
+ } else {
+ classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ IdTy, Params, true), "objc_get_class");
+ }
+ ReceiverClass = Builder.CreateCall(classLookupFunction,
+ MakeConstantString(Class->getNameAsString()));
+ } else {
+ // Set up global aliases for the metaclass or class pointer if they do not
+ // already exist. These will are forward-references which will be set to
+ // pointers to the class and metaclass structure created for the runtime
+ // load function. To send a message to super, we look up the value of the
+ // super_class pointer from either the class or metaclass structure.
+ if (IsClassMessage) {
+ if (!MetaClassPtrAlias) {
+ MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
+ llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
+ Class->getNameAsString(), NULL, &TheModule);
+ }
+ ReceiverClass = MetaClassPtrAlias;
+ } else {
+ if (!ClassPtrAlias) {
+ ClassPtrAlias = new llvm::GlobalAlias(IdTy,
+ llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
+ Class->getNameAsString(), NULL, &TheModule);
+ }
+ ReceiverClass = ClassPtrAlias;
+ }
+ }
+ // Cast the pointer to a simplified version of the class structure
+ ReceiverClass = Builder.CreateBitCast(ReceiverClass,
+ llvm::PointerType::getUnqual(
+ llvm::StructType::get(VMContext, IdTy, IdTy, NULL)));
+ // Get the superclass pointer
+ ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1);
+ // Load the superclass pointer
+ ReceiverClass = Builder.CreateLoad(ReceiverClass);
+ // Construct the structure used to look up the IMP
+ llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext,
+ Receiver->getType(), IdTy, NULL);
+ llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
+
+ Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
+ Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
+
+ // Get the IMP
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy));
+ Params.push_back(SelectorTy);
+
+ llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
+ llvm::Value *imp;
+
+ if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
+ // The lookup function returns a slot, which can be safely cached.
+ llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
+ IntTy, llvm::PointerType::getUnqual(impType), NULL);
+
+ llvm::Constant *lookupFunction =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::PointerType::getUnqual(SlotTy), Params, true),
+ "objc_slot_lookup_super");
+
+ llvm::CallInst *slot = Builder.CreateCall(lookupFunction, lookupArgs,
+ lookupArgs+2);
+ slot->setOnlyReadsMemory();
+
+ imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+ } else {
+ llvm::Constant *lookupFunction =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::PointerType::getUnqual(impType), Params, true),
+ "objc_msg_lookup_super");
+ imp = Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2);
+ }
+
+ llvm::Value *impMD[] = {
+ llvm::MDString::get(VMContext, Sel.getAsString()),
+ llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsClassMessage)
+ };
+ llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3);
+
+ llvm::Instruction *call;
+ RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
+ 0, &call);
+ call->setMetadata(msgSendMDKind, node);
+ return msgRet;
+}
+
+/// Generate code for a message send expression.
+CodeGen::RValue
+CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method) {
+ // Strip out message sends to retain / release in GC mode
+ if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ if (Sel == RetainSel || Sel == AutoreleaseSel) {
+ return RValue::get(Receiver);
+ }
+ if (Sel == ReleaseSel) {
+ return RValue::get(0);
+ }
+ }
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // If the return type is something that goes in an integer register, the
+ // runtime will handle 0 returns. For other cases, we fill in the 0 value
+ // ourselves.
+ //
+ // The language spec says the result of this kind of message send is
+ // undefined, but lots of people seem to have forgotten to read that
+ // paragraph and insist on sending messages to nil that have structure
+ // returns. With GCC, this generates a random return value (whatever happens
+ // to be on the stack / in those registers at the time) on most platforms,
+ // and generates a SegV on SPARC. With LLVM it corrupts the stack.
+ bool isPointerSizedReturn = false;
+ if (ResultType->isAnyPointerType() ||
+ ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType())
+ isPointerSizedReturn = true;
+
+ llvm::BasicBlock *startBB = 0;
+ llvm::BasicBlock *messageBB = 0;
+ llvm::BasicBlock *continueBB = 0;
+
+ if (!isPointerSizedReturn) {
+ startBB = Builder.GetInsertBlock();
+ messageBB = CGF.createBasicBlock("msgSend");
+ continueBB = CGF.createBasicBlock("continue");
+
+ llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
+ llvm::Constant::getNullValue(Receiver->getType()));
+ Builder.CreateCondBr(isNil, continueBB, messageBB);
+ CGF.EmitBlock(messageBB);
+ }
+
+ IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
+ llvm::Value *cmd;
+ if (Method)
+ cmd = GetSelector(Builder, Method);
+ else
+ cmd = GetSelector(Builder, Sel);
+ CallArgList ActualArgs;
+
+ Receiver = Builder.CreateBitCast(Receiver, IdTy);
+ ActualArgs.push_back(
+ std::make_pair(RValue::get(Receiver), ASTIdTy));
+ ActualArgs.push_back(std::make_pair(RValue::get(cmd),
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ FunctionType::ExtInfo());
+ const llvm::FunctionType *impType =
+ Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
+
+ llvm::Value *impMD[] = {
+ llvm::MDString::get(VMContext, Sel.getAsString()),
+ llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0)
+ };
+ llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3);
+
+
+ llvm::Value *imp;
+ // For sender-aware dispatch, we pass the sender as the third argument to a
+ // lookup function. When sending messages from C code, the sender is nil.
+ // objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
+ if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
+
+ std::vector<const llvm::Type*> Params;
+ llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType());
+ Builder.CreateStore(Receiver, ReceiverPtr);
+ Params.push_back(ReceiverPtr->getType());
+ Params.push_back(SelectorTy);
+ llvm::Value *self;
+
+ if (isa<ObjCMethodDecl>(CGF.CurCodeDecl)) {
+ self = CGF.LoadObjCSelf();
+ } else {
+ self = llvm::ConstantPointerNull::get(IdTy);
+ }
+
+ Params.push_back(self->getType());
+
+ // The lookup function returns a slot, which can be safely cached.
+ llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
+ IntTy, llvm::PointerType::getUnqual(impType), NULL);
+ llvm::Constant *lookupFunction =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::PointerType::getUnqual(SlotTy), Params, true),
+ "objc_msg_lookup_sender");
+
+ // The lookup function is guaranteed not to capture the receiver pointer.
+ if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) {
+ LookupFn->setDoesNotCapture(1);
+ }
+
+ llvm::CallInst *slot =
+ Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self);
+ slot->setOnlyReadsMemory();
+ slot->setMetadata(msgSendMDKind, node);
+
+ imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
+
+ // The lookup function may have changed the receiver, so make sure we use
+ // the new one.
+ ActualArgs[0] = std::make_pair(RValue::get(
+ Builder.CreateLoad(ReceiverPtr, true)), ASTIdTy);
+ } else {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Receiver->getType());
+ Params.push_back(SelectorTy);
+ llvm::Constant *lookupFunction =
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::PointerType::getUnqual(impType), Params, true),
+ "objc_msg_lookup");
+
+ imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
+ cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node);
+ }
+ llvm::Instruction *call;
+ RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
+ 0, &call);
+ call->setMetadata(msgSendMDKind, node);
+
+
+ if (!isPointerSizedReturn) {
+ messageBB = CGF.Builder.GetInsertBlock();
+ CGF.Builder.CreateBr(continueBB);
+ CGF.EmitBlock(continueBB);
+ if (msgRet.isScalar()) {
+ llvm::Value *v = msgRet.getScalarVal();
+ llvm::PHINode *phi = Builder.CreatePHI(v->getType());
+ phi->addIncoming(v, messageBB);
+ phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB);
+ msgRet = RValue::get(phi);
+ } else if (msgRet.isAggregate()) {
+ llvm::Value *v = msgRet.getAggregateAddr();
+ llvm::PHINode *phi = Builder.CreatePHI(v->getType());
+ const llvm::PointerType *RetTy = cast<llvm::PointerType>(v->getType());
+ llvm::AllocaInst *NullVal =
+ CGF.CreateTempAlloca(RetTy->getElementType(), "null");
+ CGF.InitTempAlloca(NullVal,
+ llvm::Constant::getNullValue(RetTy->getElementType()));
+ phi->addIncoming(v, messageBB);
+ phi->addIncoming(NullVal, startBB);
+ msgRet = RValue::getAggregate(phi);
+ } else /* isComplex() */ {
+ std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal();
+ llvm::PHINode *phi = Builder.CreatePHI(v.first->getType());
+ phi->addIncoming(v.first, messageBB);
+ phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
+ startBB);
+ llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType());
+ phi2->addIncoming(v.second, messageBB);
+ phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
+ startBB);
+ msgRet = RValue::getComplex(phi, phi2);
+ }
+ }
+ return msgRet;
+}
+
+/// Generates a MethodList. Used in construction of a objc_class and
+/// objc_category structures.
+llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
+ const std::string &CategoryName,
+ const llvm::SmallVectorImpl<Selector> &MethodSels,
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
+ bool isClassMethodList) {
+ if (MethodSels.empty())
+ return NULLPtr;
+ // Get the method structure type.
+ llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty, // Really a selector, but the runtime creates it us.
+ PtrToInt8Ty, // Method types
+ llvm::PointerType::getUnqual(IMPTy), //Method pointer
+ NULL);
+ std::vector<llvm::Constant*> Methods;
+ std::vector<llvm::Constant*> Elements;
+ for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
+ Elements.clear();
+ if (llvm::Constant *Method =
+ TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
+ MethodSels[i].getAsString(),
+ isClassMethodList))) {
+ llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
+ Elements.push_back(C);
+ Elements.push_back(MethodTypes[i]);
+ Method = llvm::ConstantExpr::getBitCast(Method,
+ llvm::PointerType::getUnqual(IMPTy));
+ Elements.push_back(Method);
+ Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
+ }
+ }
+
+ // Array of method structures
+ llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
+ Methods.size());
+ llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
+ Methods);
+
+ // Structure containing list pointer, array and array count
+ llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
+ llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext);
+ llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
+ llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext,
+ NextPtrTy,
+ IntTy,
+ ObjCMethodArrayTy,
+ NULL);
+ // Refine next pointer type to concrete type
+ llvm::cast<llvm::OpaqueType>(
+ OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
+ ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
+
+ Methods.clear();
+ Methods.push_back(llvm::ConstantPointerNull::get(
+ llvm::PointerType::getUnqual(ObjCMethodListTy)));
+ Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
+ MethodTypes.size()));
+ Methods.push_back(MethodArray);
+
+ // Create an instance of the structure
+ return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
+}
+
+/// Generates an IvarList. Used in construction of a objc_class.
+llvm::Constant *CGObjCGNU::GenerateIvarList(
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
+ const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
+ if (IvarNames.size() == 0)
+ return NULLPtr;
+ // Get the method structure type.
+ llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty,
+ PtrToInt8Ty,
+ IntTy,
+ NULL);
+ std::vector<llvm::Constant*> Ivars;
+ std::vector<llvm::Constant*> Elements;
+ for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
+ Elements.clear();
+ Elements.push_back(IvarNames[i]);
+ Elements.push_back(IvarTypes[i]);
+ Elements.push_back(IvarOffsets[i]);
+ Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
+ }
+
+ // Array of method structures
+ llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
+ IvarNames.size());
+
+
+ Elements.clear();
+ Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size()));
+ Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
+ // Structure containing array and array count
+ llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy,
+ ObjCIvarArrayTy,
+ NULL);
+
+ // Create an instance of the structure
+ return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
+}
+
+/// Generate a class structure
+llvm::Constant *CGObjCGNU::GenerateClassStructure(
+ llvm::Constant *MetaClass,
+ llvm::Constant *SuperClass,
+ unsigned info,
+ const char *Name,
+ llvm::Constant *Version,
+ llvm::Constant *InstanceSize,
+ llvm::Constant *IVars,
+ llvm::Constant *Methods,
+ llvm::Constant *Protocols,
+ llvm::Constant *IvarOffsets,
+ llvm::Constant *Properties,
+ bool isMeta) {
+ // Set up the class structure
+ // Note: Several of these are char*s when they should be ids. This is
+ // because the runtime performs this translation on load.
+ //
+ // Fields marked New ABI are part of the GNUstep runtime. We emit them
+ // anyway; the classes will still work with the GNU runtime, they will just
+ // be ignored.
+ llvm::StructType *ClassTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty, // class_pointer
+ PtrToInt8Ty, // super_class
+ PtrToInt8Ty, // name
+ LongTy, // version
+ LongTy, // info
+ LongTy, // instance_size
+ IVars->getType(), // ivars
+ Methods->getType(), // methods
+ // These are all filled in by the runtime, so we pretend
+ PtrTy, // dtable
+ PtrTy, // subclass_list
+ PtrTy, // sibling_class
+ PtrTy, // protocols
+ PtrTy, // gc_object_type
+ // New ABI:
+ LongTy, // abi_version
+ IvarOffsets->getType(), // ivar_offsets
+ Properties->getType(), // properties
+ NULL);
+ llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
+ // Fill in the structure
+ std::vector<llvm::Constant*> Elements;
+ Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
+ Elements.push_back(SuperClass);
+ Elements.push_back(MakeConstantString(Name, ".class_name"));
+ Elements.push_back(Zero);
+ Elements.push_back(llvm::ConstantInt::get(LongTy, info));
+ Elements.push_back(InstanceSize);
+ Elements.push_back(IVars);
+ Elements.push_back(Methods);
+ Elements.push_back(NULLPtr);
+ Elements.push_back(NULLPtr);
+ Elements.push_back(NULLPtr);
+ Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
+ Elements.push_back(NULLPtr);
+ Elements.push_back(Zero);
+ Elements.push_back(IvarOffsets);
+ Elements.push_back(Properties);
+ // Create an instance of the structure
+ // This is now an externally visible symbol, so that we can speed up class
+ // messages in the next ABI.
+ return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_":
+ "_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage);
+}
+
+llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
+ const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
+ // Get the method structure type.
+ llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
+ PtrToInt8Ty,
+ NULL);
+ std::vector<llvm::Constant*> Methods;
+ std::vector<llvm::Constant*> Elements;
+ for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
+ Elements.clear();
+ Elements.push_back(MethodNames[i]);
+ Elements.push_back(MethodTypes[i]);
+ Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
+ }
+ llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
+ MethodNames.size());
+ llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
+ Methods);
+ llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext,
+ IntTy, ObjCMethodArrayTy, NULL);
+ Methods.clear();
+ Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
+ Methods.push_back(Array);
+ return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
+}
+
+// Create the protocol list structure used in classes, categories and so on
+llvm::Constant *CGObjCGNU::GenerateProtocolList(
+ const llvm::SmallVectorImpl<std::string> &Protocols) {
+ llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
+ Protocols.size());
+ llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
+ PtrTy, //Should be a recurisve pointer, but it's always NULL here.
+ SizeTy,
+ ProtocolArrayTy,
+ NULL);
+ std::vector<llvm::Constant*> Elements;
+ for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
+ iter != endIter ; iter++) {
+ llvm::Constant *protocol = 0;
+ llvm::StringMap<llvm::Constant*>::iterator value =
+ ExistingProtocols.find(*iter);
+ if (value == ExistingProtocols.end()) {
+ protocol = GenerateEmptyProtocol(*iter);
+ } else {
+ protocol = value->getValue();
+ }
+ llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
+ PtrToInt8Ty);
+ Elements.push_back(Ptr);
+ }
+ llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
+ Elements);
+ Elements.clear();
+ Elements.push_back(NULLPtr);
+ Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
+ Elements.push_back(ProtocolArray);
+ return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
+}
+
+llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD) {
+ llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
+ const llvm::Type *T =
+ CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
+ return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
+}
+
+llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
+ const std::string &ProtocolName) {
+ llvm::SmallVector<std::string, 0> EmptyStringVector;
+ llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector;
+
+ llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
+ llvm::Constant *MethodList =
+ GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
+ // Protocols are objects containing lists of the methods implemented and
+ // protocols adopted.
+ llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
+ PtrToInt8Ty,
+ ProtocolList->getType(),
+ MethodList->getType(),
+ MethodList->getType(),
+ MethodList->getType(),
+ MethodList->getType(),
+ NULL);
+ std::vector<llvm::Constant*> Elements;
+ // The isa pointer must be set to a magic number so the runtime knows it's
+ // the correct layout.
+ int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
+ NonFragileProtocolVersion : ProtocolVersion;
+ Elements.push_back(llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
+ Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
+ Elements.push_back(ProtocolList);
+ Elements.push_back(MethodList);
+ Elements.push_back(MethodList);
+ Elements.push_back(MethodList);
+ Elements.push_back(MethodList);
+ return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
+}
+
+void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
+ ASTContext &Context = CGM.getContext();
+ std::string ProtocolName = PD->getNameAsString();
+ llvm::SmallVector<std::string, 16> Protocols;
+ for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
+ E = PD->protocol_end(); PI != E; ++PI)
+ Protocols.push_back((*PI)->getNameAsString());
+ llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
+ llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
+ llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
+ for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
+ E = PD->instmeth_end(); iter != E; iter++) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
+ if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
+ InstanceMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ OptionalInstanceMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+ }
+ // Collect information about class methods:
+ llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
+ llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
+ llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
+ for (ObjCProtocolDecl::classmeth_iterator
+ iter = PD->classmeth_begin(), endIter = PD->classmeth_end();
+ iter != endIter ; iter++) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
+ if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
+ ClassMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ } else {
+ OptionalClassMethodNames.push_back(
+ MakeConstantString((*iter)->getSelector().getAsString()));
+ OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+ }
+
+ llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
+ llvm::Constant *InstanceMethodList =
+ GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
+ llvm::Constant *ClassMethodList =
+ GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
+ llvm::Constant *OptionalInstanceMethodList =
+ GenerateProtocolMethodList(OptionalInstanceMethodNames,
+ OptionalInstanceMethodTypes);
+ llvm::Constant *OptionalClassMethodList =
+ GenerateProtocolMethodList(OptionalClassMethodNames,
+ OptionalClassMethodTypes);
+
+ // Property metadata: name, attributes, isSynthesized, setter name, setter
+ // types, getter name, getter types.
+ // The isSynthesized value is always set to 0 in a protocol. It exists to
+ // simplify the runtime library by allowing it to use the same data
+ // structures for protocol metadata everywhere.
+ llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
+ PtrToInt8Ty, NULL);
+ std::vector<llvm::Constant*> Properties;
+ std::vector<llvm::Constant*> OptionalProperties;
+
+ // Add all of the property methods need adding to the method list and to the
+ // property metadata list.
+ for (ObjCContainerDecl::prop_iterator
+ iter = PD->prop_begin(), endIter = PD->prop_end();
+ iter != endIter ; iter++) {
+ std::vector<llvm::Constant*> Fields;
+ ObjCPropertyDecl *property = (*iter);
+
+ Fields.push_back(MakeConstantString(property->getNameAsString()));
+ Fields.push_back(llvm::ConstantInt::get(Int8Ty,
+ property->getPropertyAttributes()));
+ Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
+ if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl(getter,TypeStr);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ InstanceMethodTypes.push_back(TypeEncoding);
+ Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
+ Fields.push_back(TypeEncoding);
+ } else {
+ Fields.push_back(NULLPtr);
+ Fields.push_back(NULLPtr);
+ }
+ if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl(setter,TypeStr);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ InstanceMethodTypes.push_back(TypeEncoding);
+ Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
+ Fields.push_back(TypeEncoding);
+ } else {
+ Fields.push_back(NULLPtr);
+ Fields.push_back(NULLPtr);
+ }
+ if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
+ OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+ } else {
+ Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+ }
+ }
+ llvm::Constant *PropertyArray = llvm::ConstantArray::get(
+ llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
+ llvm::Constant* PropertyListInitFields[] =
+ {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
+
+ llvm::Constant *PropertyListInit =
+ llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
+ llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
+ PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
+ PropertyListInit, ".objc_property_list");
+
+ llvm::Constant *OptionalPropertyArray =
+ llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
+ OptionalProperties.size()) , OptionalProperties);
+ llvm::Constant* OptionalPropertyListInitFields[] = {
+ llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
+ OptionalPropertyArray };
+
+ llvm::Constant *OptionalPropertyListInit =
+ llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false);
+ llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
+ OptionalPropertyListInit->getType(), false,
+ llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
+ ".objc_property_list");
+
+ // Protocols are objects containing lists of the methods implemented and
+ // protocols adopted.
+ llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
+ PtrToInt8Ty,
+ ProtocolList->getType(),
+ InstanceMethodList->getType(),
+ ClassMethodList->getType(),
+ OptionalInstanceMethodList->getType(),
+ OptionalClassMethodList->getType(),
+ PropertyList->getType(),
+ OptionalPropertyList->getType(),
+ NULL);
+ std::vector<llvm::Constant*> Elements;
+ // The isa pointer must be set to a magic number so the runtime knows it's
+ // the correct layout.
+ int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
+ NonFragileProtocolVersion : ProtocolVersion;
+ Elements.push_back(llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
+ Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
+ Elements.push_back(ProtocolList);
+ Elements.push_back(InstanceMethodList);
+ Elements.push_back(ClassMethodList);
+ Elements.push_back(OptionalInstanceMethodList);
+ Elements.push_back(OptionalClassMethodList);
+ Elements.push_back(PropertyList);
+ Elements.push_back(OptionalPropertyList);
+ ExistingProtocols[ProtocolName] =
+ llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
+ ".objc_protocol"), IdTy);
+}
+void CGObjCGNU::GenerateProtocolHolderCategory(void) {
+ // Collect information about instance methods
+ llvm::SmallVector<Selector, 1> MethodSels;
+ llvm::SmallVector<llvm::Constant*, 1> MethodTypes;
+
+ std::vector<llvm::Constant*> Elements;
+ const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
+ const std::string CategoryName = "AnotherHack";
+ Elements.push_back(MakeConstantString(CategoryName));
+ Elements.push_back(MakeConstantString(ClassName));
+ // Instance method list
+ Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+ ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
+ // Class method list
+ Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+ ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
+ // Protocol list
+ llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
+ ExistingProtocols.size());
+ llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
+ PtrTy, //Should be a recurisve pointer, but it's always NULL here.
+ SizeTy,
+ ProtocolArrayTy,
+ NULL);
+ std::vector<llvm::Constant*> ProtocolElements;
+ for (llvm::StringMapIterator<llvm::Constant*> iter =
+ ExistingProtocols.begin(), endIter = ExistingProtocols.end();
+ iter != endIter ; iter++) {
+ llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
+ PtrTy);
+ ProtocolElements.push_back(Ptr);
+ }
+ llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
+ ProtocolElements);
+ ProtocolElements.clear();
+ ProtocolElements.push_back(NULLPtr);
+ ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
+ ExistingProtocols.size()));
+ ProtocolElements.push_back(ProtocolArray);
+ Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
+ ProtocolElements, ".objc_protocol_list"), PtrTy));
+ Categories.push_back(llvm::ConstantExpr::getBitCast(
+ MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
+ PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
+}
+
+void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
+ std::string ClassName = OCD->getClassInterface()->getNameAsString();
+ std::string CategoryName = OCD->getNameAsString();
+ // Collect information about instance methods
+ llvm::SmallVector<Selector, 16> InstanceMethodSels;
+ llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ for (ObjCCategoryImplDecl::instmeth_iterator
+ iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end();
+ iter != endIter ; iter++) {
+ InstanceMethodSels.push_back((*iter)->getSelector());
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+
+ // Collect information about class methods
+ llvm::SmallVector<Selector, 16> ClassMethodSels;
+ llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ for (ObjCCategoryImplDecl::classmeth_iterator
+ iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end();
+ iter != endIter ; iter++) {
+ ClassMethodSels.push_back((*iter)->getSelector());
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+
+ // Collect the names of referenced protocols
+ llvm::SmallVector<std::string, 16> Protocols;
+ const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
+ const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
+ E = Protos.end(); I != E; ++I)
+ Protocols.push_back((*I)->getNameAsString());
+
+ std::vector<llvm::Constant*> Elements;
+ Elements.push_back(MakeConstantString(CategoryName));
+ Elements.push_back(MakeConstantString(ClassName));
+ // Instance method list
+ Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+ ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
+ false), PtrTy));
+ // Class method list
+ Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+ ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
+ PtrTy));
+ // Protocol list
+ Elements.push_back(llvm::ConstantExpr::getBitCast(
+ GenerateProtocolList(Protocols), PtrTy));
+ Categories.push_back(llvm::ConstantExpr::getBitCast(
+ MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
+ PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
+}
+
+llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
+ llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
+ llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
+ ASTContext &Context = CGM.getContext();
+ //
+ // Property metadata: name, attributes, isSynthesized, setter name, setter
+ // types, getter name, getter types.
+ llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
+ PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
+ PtrToInt8Ty, NULL);
+ std::vector<llvm::Constant*> Properties;
+
+
+ // Add all of the property methods need adding to the method list and to the
+ // property metadata list.
+ for (ObjCImplDecl::propimpl_iterator
+ iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
+ iter != endIter ; iter++) {
+ std::vector<llvm::Constant*> Fields;
+ ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
+ ObjCPropertyImplDecl *propertyImpl = *iter;
+ bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
+ ObjCPropertyImplDecl::Synthesize);
+
+ Fields.push_back(MakeConstantString(property->getNameAsString()));
+ Fields.push_back(llvm::ConstantInt::get(Int8Ty,
+ property->getPropertyAttributes()));
+ Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized));
+ if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl(getter,TypeStr);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(getter->getSelector());
+ }
+ Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
+ Fields.push_back(TypeEncoding);
+ } else {
+ Fields.push_back(NULLPtr);
+ Fields.push_back(NULLPtr);
+ }
+ if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl(setter,TypeStr);
+ llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
+ if (isSynthesized) {
+ InstanceMethodTypes.push_back(TypeEncoding);
+ InstanceMethodSels.push_back(setter->getSelector());
+ }
+ Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
+ Fields.push_back(TypeEncoding);
+ } else {
+ Fields.push_back(NULLPtr);
+ Fields.push_back(NULLPtr);
+ }
+ Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+ }
+ llvm::ArrayType *PropertyArrayTy =
+ llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
+ llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
+ Properties);
+ llvm::Constant* PropertyListInitFields[] =
+ {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
+
+ llvm::Constant *PropertyListInit =
+ llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
+ return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
+ llvm::GlobalValue::InternalLinkage, PropertyListInit,
+ ".objc_property_list");
+}
+
+void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
+ ASTContext &Context = CGM.getContext();
+
+ // Get the superclass name.
+ const ObjCInterfaceDecl * SuperClassDecl =
+ OID->getClassInterface()->getSuperClass();
+ std::string SuperClassName;
+ if (SuperClassDecl) {
+ SuperClassName = SuperClassDecl->getNameAsString();
+ EmitClassRef(SuperClassName);
+ }
+
+ // Get the class name
+ ObjCInterfaceDecl *ClassDecl =
+ const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
+ std::string ClassName = ClassDecl->getNameAsString();
+ // Emit the symbol that is used to generate linker errors if this class is
+ // referenced in other modules but not declared.
+ std::string classSymbolName = "__objc_class_name_" + ClassName;
+ if (llvm::GlobalVariable *symbol =
+ TheModule.getGlobalVariable(classSymbolName)) {
+ symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
+ } else {
+ new llvm::GlobalVariable(TheModule, LongTy, false,
+ llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0),
+ classSymbolName);
+ }
+
+ // Get the size of instances.
+ int instanceSize =
+ Context.getASTObjCImplementationLayout(OID).getSize().getQuantity();
+
+ // Collect information about instance variables.
+ llvm::SmallVector<llvm::Constant*, 16> IvarNames;
+ llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
+ llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
+
+ std::vector<llvm::Constant*> IvarOffsetValues;
+
+ int superInstanceSize = !SuperClassDecl ? 0 :
+ Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
+ // For non-fragile ivars, set the instance size to 0 - {the size of just this
+ // class}. The runtime will then set this to the correct value on load.
+ if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
+ instanceSize = 0 - (instanceSize - superInstanceSize);
+ }
+
+ // Collect declared and synthesized ivars.
+ llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
+ CGM.getContext().ShallowCollectObjCIvars(ClassDecl, OIvars);
+
+ for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
+ ObjCIvarDecl *IVD = OIvars[i];
+ // Store the name
+ IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
+ // Get the type encoding for this ivar
+ std::string TypeStr;
+ Context.getObjCEncodingForType(IVD->getType(), TypeStr);
+ IvarTypes.push_back(MakeConstantString(TypeStr));
+ // Get the offset
+ uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
+ uint64_t Offset = BaseOffset;
+ if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
+ Offset = BaseOffset - superInstanceSize;
+ }
+ IvarOffsets.push_back(
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset));
+ IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy,
+ false, llvm::GlobalValue::ExternalLinkage,
+ llvm::ConstantInt::get(IntTy, Offset),
+ "__objc_ivar_offset_value_" + ClassName +"." +
+ IVD->getNameAsString()));
+ }
+ llvm::Constant *IvarOffsetArrayInit =
+ llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy,
+ IvarOffsetValues.size()), IvarOffsetValues);
+ llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule,
+ IvarOffsetArrayInit->getType(), false,
+ llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit,
+ ".ivar.offsets");
+
+ // Collect information about instance methods
+ llvm::SmallVector<Selector, 16> InstanceMethodSels;
+ llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
+ for (ObjCImplementationDecl::instmeth_iterator
+ iter = OID->instmeth_begin(), endIter = OID->instmeth_end();
+ iter != endIter ; iter++) {
+ InstanceMethodSels.push_back((*iter)->getSelector());
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
+ InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+
+ llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
+ InstanceMethodTypes);
+
+
+ // Collect information about class methods
+ llvm::SmallVector<Selector, 16> ClassMethodSels;
+ llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
+ for (ObjCImplementationDecl::classmeth_iterator
+ iter = OID->classmeth_begin(), endIter = OID->classmeth_end();
+ iter != endIter ; iter++) {
+ ClassMethodSels.push_back((*iter)->getSelector());
+ std::string TypeStr;
+ Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
+ ClassMethodTypes.push_back(MakeConstantString(TypeStr));
+ }
+ // Collect the names of referenced protocols
+ llvm::SmallVector<std::string, 16> Protocols;
+ const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
+ E = Protos.end(); I != E; ++I)
+ Protocols.push_back((*I)->getNameAsString());
+
+
+
+ // Get the superclass pointer.
+ llvm::Constant *SuperClass;
+ if (!SuperClassName.empty()) {
+ SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
+ } else {
+ SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
+ }
+ // Empty vector used to construct empty method lists
+ llvm::SmallVector<llvm::Constant*, 1> empty;
+ // Generate the method and instance variable lists
+ llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
+ InstanceMethodSels, InstanceMethodTypes, false);
+ llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
+ ClassMethodSels, ClassMethodTypes, true);
+ llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
+ IvarOffsets);
+ // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
+ // we emit a symbol containing the offset for each ivar in the class. This
+ // allows code compiled for the non-Fragile ABI to inherit from code compiled
+ // for the legacy ABI, without causing problems. The converse is also
+ // possible, but causes all ivar accesses to be fragile.
+
+ // Offset pointer for getting at the correct field in the ivar list when
+ // setting up the alias. These are: The base address for the global, the
+ // ivar array (second field), the ivar in this list (set for each ivar), and
+ // the offset (third field in ivar structure)
+ const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
+ llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
+ llvm::ConstantInt::get(IndexTy, 1), 0,
+ llvm::ConstantInt::get(IndexTy, 2) };
+
+
+ for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
+ ObjCIvarDecl *IVD = OIvars[i];
+ const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
+ + IVD->getNameAsString();
+ offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i);
+ // Get the correct ivar field
+ llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
+ IvarList, offsetPointerIndexes, 4);
+ // Get the existing variable, if one exists.
+ llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
+ if (offset) {
+ offset->setInitializer(offsetValue);
+ // If this is the real definition, change its linkage type so that
+ // different modules will use this one, rather than their private
+ // copy.
+ offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else {
+ // Add a new alias if there isn't one already.
+ offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
+ false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
+ }
+ }
+ //Generate metaclass for class methods
+ llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
+ NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
+ empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr, true);
+
+ // Generate the class structure
+ llvm::Constant *ClassStruct =
+ GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L,
+ ClassName.c_str(), 0,
+ llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
+ MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
+ Properties);
+
+ // Resolve the class aliases, if they exist.
+ if (ClassPtrAlias) {
+ ClassPtrAlias->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
+ ClassPtrAlias->eraseFromParent();
+ ClassPtrAlias = 0;
+ }
+ if (MetaClassPtrAlias) {
+ MetaClassPtrAlias->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
+ MetaClassPtrAlias->eraseFromParent();
+ MetaClassPtrAlias = 0;
+ }
+
+ // Add class structure to list to be added to the symtab later
+ ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
+ Classes.push_back(ClassStruct);
+}
+
+
+llvm::Function *CGObjCGNU::ModuleInitFunction() {
+ // Only emit an ObjC load function if no Objective-C stuff has been called
+ if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
+ ExistingProtocols.empty() && TypedSelectors.empty() &&
+ UntypedSelectors.empty())
+ return NULL;
+
+ // Add all referenced protocols to a category.
+ GenerateProtocolHolderCategory();
+
+ const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
+ SelectorTy->getElementType());
+ const llvm::Type *SelStructPtrTy = SelectorTy;
+ bool isSelOpaque = false;
+ if (SelStructTy == 0) {
+ SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty,
+ PtrToInt8Ty, NULL);
+ SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
+ isSelOpaque = true;
+ }
+
+ // Name the ObjC types to make the IR a bit easier to read
+ TheModule.addTypeName(".objc_selector", SelStructPtrTy);
+ TheModule.addTypeName(".objc_id", IdTy);
+ TheModule.addTypeName(".objc_imp", IMPTy);
+
+ std::vector<llvm::Constant*> Elements;
+ llvm::Constant *Statics = NULLPtr;
+ // Generate statics list:
+ if (ConstantStrings.size()) {
+ llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
+ ConstantStrings.size() + 1);
+ ConstantStrings.push_back(NULLPtr);
+
+ llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass;
+ if (StringClass.empty()) StringClass = "NXConstantString";
+ Elements.push_back(MakeConstantString(StringClass,
+ ".objc_static_class_name"));
+ Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
+ ConstantStrings));
+ llvm::StructType *StaticsListTy =
+ llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL);
+ llvm::Type *StaticsListPtrTy =
+ llvm::PointerType::getUnqual(StaticsListTy);
+ Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
+ llvm::ArrayType *StaticsListArrayTy =
+ llvm::ArrayType::get(StaticsListPtrTy, 2);
+ Elements.clear();
+ Elements.push_back(Statics);
+ Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
+ Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
+ Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
+ }
+ // Array of classes, categories, and constant objects
+ llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
+ Classes.size() + Categories.size() + 2);
+ llvm::StructType *SymTabTy = llvm::StructType::get(VMContext,
+ LongTy, SelStructPtrTy,
+ llvm::Type::getInt16Ty(VMContext),
+ llvm::Type::getInt16Ty(VMContext),
+ ClassListTy, NULL);
+
+ Elements.clear();
+ // Pointer to an array of selectors used in this module.
+ std::vector<llvm::Constant*> Selectors;
+ for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
+ iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
+ iter != iterEnd ; ++iter) {
+ Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name"));
+ Elements.push_back(MakeConstantString(iter->first.second,
+ ".objc_sel_types"));
+ Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
+ Elements.clear();
+ }
+ for (llvm::StringMap<llvm::GlobalAlias*>::iterator
+ iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
+ iter != iterEnd; ++iter) {
+ Elements.push_back(
+ ExportUniqueString(iter->getKeyData(), ".objc_sel_name"));
+ Elements.push_back(NULLPtr);
+ Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
+ Elements.clear();
+ }
+ Elements.push_back(NULLPtr);
+ Elements.push_back(NULLPtr);
+ Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
+ Elements.clear();
+ // Number of static selectors
+ Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
+ llvm::Constant *SelectorList = MakeGlobal(
+ llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
+ ".objc_selector_list");
+ Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
+ SelStructPtrTy));
+
+ // Now that all of the static selectors exist, create pointers to them.
+ int index = 0;
+ for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
+ iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
+ iter != iterEnd; ++iter) {
+ llvm::Constant *Idxs[] = {Zeros[0],
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
+ llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
+ true, llvm::GlobalValue::LinkOnceODRLinkage,
+ llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
+ MangleSelectorTypes(".objc_sel_ptr"+iter->first.first+"."+
+ iter->first.second));
+ // If selectors are defined as an opaque type, cast the pointer to this
+ // type.
+ if (isSelOpaque) {
+ SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
+ llvm::PointerType::getUnqual(SelectorTy));
+ }
+ (*iter).second->replaceAllUsesWith(SelPtr);
+ (*iter).second->eraseFromParent();
+ }
+ for (llvm::StringMap<llvm::GlobalAlias*>::iterator
+ iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
+ iter != iterEnd; iter++) {
+ llvm::Constant *Idxs[] = {Zeros[0],
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
+ llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
+ true, llvm::GlobalValue::LinkOnceODRLinkage,
+ llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
+ MangleSelectorTypes(std::string(".objc_sel_ptr")+iter->getKey().str()));
+ // If selectors are defined as an opaque type, cast the pointer to this
+ // type.
+ if (isSelOpaque) {
+ SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
+ llvm::PointerType::getUnqual(SelectorTy));
+ }
+ (*iter).second->replaceAllUsesWith(SelPtr);
+ (*iter).second->eraseFromParent();
+ }
+ // Number of classes defined.
+ Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
+ Classes.size()));
+ // Number of categories defined
+ Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
+ Categories.size()));
+ // Create an array of classes, then categories, then static object instances
+ Classes.insert(Classes.end(), Categories.begin(), Categories.end());
+ // NULL-terminated list of static object instances (mainly constant strings)
+ Classes.push_back(Statics);
+ Classes.push_back(NULLPtr);
+ llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
+ Elements.push_back(ClassList);
+ // Construct the symbol table
+ llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
+
+ // The symbol table is contained in a module which has some version-checking
+ // constants
+ llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy,
+ PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
+ Elements.clear();
+ // Runtime version used for compatibility checking.
+ if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
+ Elements.push_back(llvm::ConstantInt::get(LongTy,
+ NonFragileRuntimeVersion));
+ } else {
+ Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
+ }
+ // sizeof(ModuleTy)
+ llvm::TargetData td(&TheModule);
+ Elements.push_back(llvm::ConstantInt::get(LongTy,
+ td.getTypeSizeInBits(ModuleTy)/8));
+ //FIXME: Should be the path to the file where this module was declared
+ Elements.push_back(NULLPtr);
+ Elements.push_back(SymTab);
+ llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
+
+ // Create the load function calling the runtime entry point with the module
+ // structure
+ llvm::Function * LoadFunction = llvm::Function::Create(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
+ llvm::GlobalValue::InternalLinkage, ".objc_load_function",
+ &TheModule);
+ llvm::BasicBlock *EntryBB =
+ llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
+ CGBuilderTy Builder(VMContext);
+ Builder.SetInsertPoint(EntryBB);
+
+ std::vector<const llvm::Type*> Params(1,
+ llvm::PointerType::getUnqual(ModuleTy));
+ llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class");
+ Builder.CreateCall(Register, Module);
+ Builder.CreateRetVoid();
+
+ return LoadFunction;
+}
+
+llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) {
+ const ObjCCategoryImplDecl *OCD =
+ dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
+ std::string CategoryName = OCD ? OCD->getNameAsString() : "";
+ std::string ClassName = CD->getName();
+ std::string MethodName = OMD->getSelector().getAsString();
+ bool isClassMethod = !OMD->isInstanceMethod();
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *MethodTy =
+ Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
+ std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
+ MethodName, isClassMethod);
+
+ llvm::Function *Method
+ = llvm::Function::Create(MethodTy,
+ llvm::GlobalValue::InternalLinkage,
+ FunctionName,
+ &TheModule);
+ return Method;
+}
+
+llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(IdTy);
+ Params.push_back(SelectorTy);
+ Params.push_back(IntTy);
+ Params.push_back(BoolTy);
+ // void objc_getProperty (id, SEL, int, bool)
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(IdTy, Params, false);
+ return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
+ "objc_getProperty"));
+}
+
+llvm::Function *CGObjCGNU::GetPropertySetFunction() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(IdTy);
+ Params.push_back(SelectorTy);
+ Params.push_back(IntTy);
+ Params.push_back(IdTy);
+ Params.push_back(BoolTy);
+ Params.push_back(BoolTy);
+ // void objc_setProperty (id, SEL, int, id, bool, bool)
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
+ return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
+ "objc_setProperty"));
+}
+
+llvm::Function *CGObjCGNU::GetGetStructFunction() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(PtrTy);
+ Params.push_back(PtrTy);
+ Params.push_back(PtrDiffTy);
+ Params.push_back(BoolTy);
+ Params.push_back(BoolTy);
+ // objc_setPropertyStruct (void*, void*, ptrdiff_t, BOOL, BOOL)
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
+ return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
+ "objc_getPropertyStruct"));
+}
+llvm::Function *CGObjCGNU::GetSetStructFunction() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(PtrTy);
+ Params.push_back(PtrTy);
+ Params.push_back(PtrDiffTy);
+ Params.push_back(BoolTy);
+ Params.push_back(BoolTy);
+ // objc_setPropertyStruct (void*, void*, ptrdiff_t, BOOL, BOOL)
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
+ return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
+ "objc_setPropertyStruct"));
+}
+
+llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+ // void objc_enumerationMutation (id)
+ llvm::SmallVector<CanQualType,1> Params;
+ Params.push_back(ASTIdTy);
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ FunctionType::ExtInfo()), false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
+}
+
+namespace {
+ struct CallSyncExit : EHScopeStack::Cleanup {
+ llvm::Value *SyncExitFn;
+ llvm::Value *SyncArg;
+ CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
+ : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ }
+ };
+}
+
+void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S) {
+ std::vector<const llvm::Type*> Args(1, IdTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+
+ // Evaluate the lock operand. This should dominate the cleanup.
+ llvm::Value *SyncArg =
+ CGF.EmitScalarExpr(S.getSynchExpr());
+
+ // Acquire the lock.
+ llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
+ SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
+ CGF.Builder.CreateCall(SyncEnter, SyncArg);
+
+ // Register an all-paths cleanup to release the lock.
+ llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
+ CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, SyncExit, SyncArg);
+
+ // Emit the body of the statement.
+ CGF.EmitStmt(S.getSynchBody());
+
+ // Pop the lock-release cleanup.
+ CGF.PopCleanupBlock();
+}
+
+namespace {
+ struct CatchHandler {
+ const VarDecl *Variable;
+ const Stmt *Body;
+ llvm::BasicBlock *Block;
+ llvm::Value *TypeInfo;
+ };
+}
+
+void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S) {
+ // Unlike the Apple non-fragile runtimes, which also uses
+ // unwind-based zero cost exceptions, the GNU Objective C runtime's
+ // EH support isn't a veneer over C++ EH. Instead, exception
+ // objects are created by __objc_exception_throw and destroyed by
+ // the personality function; this avoids the need for bracketing
+ // catch handlers with calls to __blah_begin_catch/__blah_end_catch
+ // (or even _Unwind_DeleteException), but probably doesn't
+ // interoperate very well with foreign exceptions.
+
+ // Jump destination for falling out of catch bodies.
+ CodeGenFunction::JumpDest Cont;
+ if (S.getNumCatchStmts())
+ Cont = CGF.getJumpDestInCurrentScope("eh.cont");
+
+ // We handle @finally statements by pushing them as a cleanup
+ // before entering the catch.
+ CodeGenFunction::FinallyInfo FinallyInfo;
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
+ std::vector<const llvm::Type*> Args(1, IdTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ llvm::Constant *Rethrow =
+ CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
+
+ FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), 0, 0,
+ Rethrow);
+ }
+
+ llvm::SmallVector<CatchHandler, 8> Handlers;
+
+ // Enter the catch, if there is one.
+ if (S.getNumCatchStmts()) {
+ for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
+ const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
+ const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
+
+ Handlers.push_back(CatchHandler());
+ CatchHandler &Handler = Handlers.back();
+ Handler.Variable = CatchDecl;
+ Handler.Body = CatchStmt->getCatchBody();
+ Handler.Block = CGF.createBasicBlock("catch");
+
+ // @catch() and @catch(id) both catch any ObjC exception.
+ // Treat them as catch-alls.
+ // FIXME: this is what this code was doing before, but should 'id'
+ // really be catching foreign exceptions?
+ if (!CatchDecl
+ || CatchDecl->getType()->isObjCIdType()
+ || CatchDecl->getType()->isObjCQualifiedIdType()) {
+
+ Handler.TypeInfo = 0; // catch-all
+
+ // Don't consider any other catches.
+ break;
+ }
+
+ // All other types should be Objective-C interface pointer types.
+ const ObjCObjectPointerType *OPT =
+ CatchDecl->getType()->getAs<ObjCObjectPointerType>();
+ assert(OPT && "Invalid @catch type.");
+ const ObjCInterfaceDecl *IDecl =
+ OPT->getObjectType()->getInterface();
+ assert(IDecl && "Invalid @catch type.");
+ Handler.TypeInfo = MakeConstantString(IDecl->getNameAsString());
+ }
+
+ EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
+ Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
+ }
+
+ // Emit the try body.
+ CGF.EmitStmt(S.getTryBody());
+
+ // Leave the try.
+ if (S.getNumCatchStmts())
+ CGF.EHStack.popCatch();
+
+ // Remember where we were.
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+
+ // Emit the handlers.
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ CatchHandler &Handler = Handlers[I];
+ CGF.EmitBlock(Handler.Block);
+
+ llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
+
+ // Bind the catch parameter if it exists.
+ if (const VarDecl *CatchParam = Handler.Variable) {
+ const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
+ Exn = CGF.Builder.CreateBitCast(Exn, CatchType);
+
+ CGF.EmitAutoVarDecl(*CatchParam);
+ CGF.Builder.CreateStore(Exn, CGF.GetAddrOfLocalVar(CatchParam));
+ }
+
+ CGF.ObjCEHValueStack.push_back(Exn);
+ CGF.EmitStmt(Handler.Body);
+ CGF.ObjCEHValueStack.pop_back();
+
+ CGF.EmitBranchThroughCleanup(Cont);
+ }
+
+ // Go back to the try-statement fallthrough.
+ CGF.Builder.restoreIP(SavedIP);
+
+ // Pop out of the finally.
+ if (S.getFinallyStmt())
+ CGF.ExitFinallyBlock(FinallyInfo);
+
+ if (Cont.isValid()) {
+ if (Cont.getBlock()->use_empty())
+ delete Cont.getBlock();
+ else
+ CGF.EmitBlock(Cont.getBlock());
+ }
+}
+
+void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S) {
+ llvm::Value *ExceptionAsObject;
+
+ std::vector<const llvm::Type*> Args(1, IdTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ llvm::Value *ThrowFn =
+ CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
+
+ if (const Expr *ThrowExpr = S.getThrowExpr()) {
+ llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ ExceptionAsObject = Exception;
+ } else {
+ assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
+ "Unexpected rethrow outside @catch block.");
+ ExceptionAsObject = CGF.ObjCEHValueStack.back();
+ }
+ ExceptionAsObject =
+ CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp");
+
+ // Note: This may have to be an invoke, if we want to support constructs like:
+ // @try {
+ // @throw(obj);
+ // }
+ // @catch(id) ...
+ //
+ // This is effectively turning @throw into an incredibly-expensive goto, but
+ // it may happen as a result of inlining followed by missed optimizations, or
+ // as a result of stupidity.
+ llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
+ if (!UnwindBB) {
+ CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject);
+ CGF.Builder.CreateUnreachable();
+ } else {
+ CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject,
+ &ExceptionAsObject+1);
+ }
+ // Clear the insertion point to indicate we are in unreachable code.
+ CGF.Builder.ClearInsertionPoint();
+}
+
+llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj) {
+ CGBuilderTy B = CGF.Builder;
+ AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy);
+ return B.CreateCall(WeakReadFn, AddrWeakObj);
+}
+
+void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ CGBuilderTy B = CGF.Builder;
+ src = EnforceType(B, src, IdTy);
+ dst = EnforceType(B, dst, PtrToIdTy);
+ B.CreateCall2(WeakAssignFn, src, dst);
+}
+
+void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
+ CGBuilderTy B = CGF.Builder;
+ src = EnforceType(B, src, IdTy);
+ dst = EnforceType(B, dst, PtrToIdTy);
+ if (!threadlocal)
+ B.CreateCall2(GlobalAssignFn, src, dst);
+ else
+ // FIXME. Add threadloca assign API
+ assert(false && "EmitObjCGlobalAssign - Threal Local API NYI");
+}
+
+void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst,
+ llvm::Value *ivarOffset) {
+ CGBuilderTy B = CGF.Builder;
+ src = EnforceType(B, src, IdTy);
+ dst = EnforceType(B, dst, PtrToIdTy);
+ B.CreateCall3(IvarAssignFn, src, dst, ivarOffset);
+}
+
+void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ CGBuilderTy B = CGF.Builder;
+ src = EnforceType(B, src, IdTy);
+ dst = EnforceType(B, dst, PtrToIdTy);
+ B.CreateCall2(StrongCastAssignFn, src, dst);
+}
+
+void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *DestPtr,
+ llvm::Value *SrcPtr,
+ llvm::Value *Size) {
+ CGBuilderTy B = CGF.Builder;
+ DestPtr = EnforceType(B, DestPtr, IdTy);
+ SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy);
+
+ B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, Size);
+}
+
+llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
+ const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar) {
+ const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
+ + '.' + Ivar->getNameAsString();
+ // Emit the variable and initialize it with what we think the correct value
+ // is. This allows code compiled with non-fragile ivars to work correctly
+ // when linked against code which isn't (most of the time).
+ llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
+ if (!IvarOffsetPointer) {
+ // This will cause a run-time crash if we accidentally use it. A value of
+ // 0 would seem more sensible, but will silently overwrite the isa pointer
+ // causing a great deal of confusion.
+ uint64_t Offset = -1;
+ // We can't call ComputeIvarBaseOffset() here if we have the
+ // implementation, because it will create an invalid ASTRecordLayout object
+ // that we are then stuck with forever, so we only initialize the ivar
+ // offset variable with a guess if we only have the interface. The
+ // initializer will be reset later anyway, when we are generating the class
+ // description.
+ if (!CGM.getContext().getObjCImplementation(
+ const_cast<ObjCInterfaceDecl *>(ID)))
+ Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
+
+ llvm::ConstantInt *OffsetGuess =
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset, "ivar");
+ // Don't emit the guess in non-PIC code because the linker will not be able
+ // to replace it with the real version for a library. In non-PIC code you
+ // must compile with the fragile ABI if you want to use ivars from a
+ // GCC-compiled class.
+ if (CGM.getLangOptions().PICLevel) {
+ llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
+ llvm::Type::getInt32Ty(VMContext), false,
+ llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
+ IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+ IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
+ IvarOffsetGV, Name);
+ } else {
+ IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
+ llvm::Type::getInt32PtrTy(VMContext), false,
+ llvm::GlobalValue::ExternalLinkage, 0, Name);
+ }
+ }
+ return IvarOffsetPointer;
+}
+
+LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers) {
+ const ObjCInterfaceDecl *ID =
+ ObjectTy->getAs<ObjCObjectType>()->getInterface();
+ return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+ EmitIvarOffset(CGF, ID, Ivar));
+}
+
+static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
+ const ObjCInterfaceDecl *OID,
+ const ObjCIvarDecl *OIVD) {
+ llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+ Context.ShallowCollectObjCIvars(OID, Ivars);
+ for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
+ if (OIVD == Ivars[k])
+ return OID;
+ }
+
+ // Otherwise check in the super class.
+ if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
+ return FindIvarInterface(Context, Super, OIVD);
+
+ return 0;
+}
+
+llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) {
+ if (CGM.getLangOptions().ObjCNonFragileABI) {
+ Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
+ return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
+ ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"));
+ }
+ uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
+ return llvm::ConstantInt::get(LongTy, Offset, "ivar");
+}
+
+CodeGen::CGObjCRuntime *
+CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) {
+ return new CGObjCGNU(CGM);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
new file mode 100644
index 0000000..7c679b9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -0,0 +1,6288 @@
+//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides Objective-C code generation targetting the Apple runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGObjCRuntime.h"
+
+#include "CGRecordLayout.h"
+#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
+#include "CGBlocks.h"
+#include "CGCleanup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+#include "llvm/InlineAsm.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetData.h"
+#include <cstdio>
+
+using namespace clang;
+using namespace CodeGen;
+
+// Common CGObjCRuntime functions, these don't belong here, but they
+// don't belong in CGObjCRuntime either so we will live with it for
+// now.
+
+static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
+ const ObjCInterfaceDecl *OID,
+ const ObjCImplementationDecl *ID,
+ const ObjCIvarDecl *Ivar) {
+ const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
+
+ // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
+ // in here; it should never be necessary because that should be the lexical
+ // decl context for the ivar.
+
+ // If we know have an implementation (and the ivar is in it) then
+ // look up in the implementation layout.
+ const ASTRecordLayout *RL;
+ if (ID && ID->getClassInterface() == Container)
+ RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
+ else
+ RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
+
+ // Compute field index.
+ //
+ // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
+ // implemented. This should be fixed to get the information from the layout
+ // directly.
+ unsigned Index = 0;
+ llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+ CGM.getContext().ShallowCollectObjCIvars(Container, Ivars);
+ for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
+ if (Ivar == Ivars[k])
+ break;
+ ++Index;
+ }
+ assert(Index != Ivars.size() && "Ivar is not inside container!");
+ assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
+
+ return RL->getFieldOffset(Index);
+}
+
+uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
+ const ObjCInterfaceDecl *OID,
+ const ObjCIvarDecl *Ivar) {
+ return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
+}
+
+uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
+ const ObjCImplementationDecl *OID,
+ const ObjCIvarDecl *Ivar) {
+ return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
+}
+
+LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *OID,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers,
+ llvm::Value *Offset) {
+ // Compute (type*) ( (char *) BaseValue + Offset)
+ const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ QualType IvarTy = Ivar->getType();
+ const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
+ llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
+ V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
+ V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
+
+ if (!Ivar->isBitField()) {
+ LValue LV = CGF.MakeAddrLValue(V, IvarTy);
+ LV.getQuals().addCVRQualifiers(CVRQualifiers);
+ return LV;
+ }
+
+ // We need to compute an access strategy for this bit-field. We are given the
+ // offset to the first byte in the bit-field, the sub-byte offset is taken
+ // from the original layout. We reuse the normal bit-field access strategy by
+ // treating this as an access to a struct where the bit-field is in byte 0,
+ // and adjust the containing type size as appropriate.
+ //
+ // FIXME: Note that currently we make a very conservative estimate of the
+ // alignment of the bit-field, because (a) it is not clear what guarantees the
+ // runtime makes us, and (b) we don't have a way to specify that the struct is
+ // at an alignment plus offset.
+ //
+ // Note, there is a subtle invariant here: we can only call this routine on
+ // non-synthesized ivars but we may be called for synthesized ivars. However,
+ // a synthesized ivar can never be a bit-field, so this is safe.
+ const ASTRecordLayout &RL =
+ CGF.CGM.getContext().getASTObjCInterfaceLayout(OID);
+ uint64_t TypeSizeInBits = CGF.CGM.getContext().toBits(RL.getSize());
+ uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar);
+ uint64_t BitOffset = FieldBitOffset % 8;
+ uint64_t ContainingTypeAlign = 8;
+ uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset);
+ uint64_t BitFieldSize =
+ Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
+
+ // Allocate a new CGBitFieldInfo object to describe this access.
+ //
+ // FIXME: This is incredibly wasteful, these should be uniqued or part of some
+ // layout object. However, this is blocked on other cleanups to the
+ // Objective-C code, so for now we just live with allocating a bunch of these
+ // objects.
+ CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
+ CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
+ ContainingTypeSize, ContainingTypeAlign));
+
+ return LValue::MakeBitfield(V, *Info,
+ IvarTy.getCVRQualifiers() | CVRQualifiers);
+}
+
+///
+
+namespace {
+
+typedef std::vector<llvm::Constant*> ConstantVector;
+
+// FIXME: We should find a nicer way to make the labels for metadata, string
+// concatenation is lame.
+
+class ObjCCommonTypesHelper {
+protected:
+ llvm::LLVMContext &VMContext;
+
+private:
+ llvm::Constant *getMessageSendFn() const {
+ // id objc_msgSend (id, SEL, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSend");
+ }
+
+ llvm::Constant *getMessageSendStretFn() const {
+ // id objc_msgSend_stret (id, SEL, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ Params, true),
+ "objc_msgSend_stret");
+
+ }
+
+ llvm::Constant *getMessageSendFpretFn() const {
+ // FIXME: This should be long double on x86_64?
+ // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+ llvm::Type::getDoubleTy(VMContext),
+ Params,
+ true),
+ "objc_msgSend_fpret");
+
+ }
+
+ llvm::Constant *getMessageSendSuperFn() const {
+ // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
+ const char *SuperName = "objc_msgSendSuper";
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ SuperName);
+ }
+
+ llvm::Constant *getMessageSendSuperFn2() const {
+ // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
+ const char *SuperName = "objc_msgSendSuper2";
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ SuperName);
+ }
+
+ llvm::Constant *getMessageSendSuperStretFn() const {
+ // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
+ // SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Int8PtrTy);
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ Params, true),
+ "objc_msgSendSuper_stret");
+ }
+
+ llvm::Constant *getMessageSendSuperStretFn2() const {
+ // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
+ // SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Int8PtrTy);
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ Params, true),
+ "objc_msgSendSuper2_stret");
+ }
+
+ llvm::Constant *getMessageSendSuperFpretFn() const {
+ // There is no objc_msgSendSuper_fpret? How can that work?
+ return getMessageSendSuperFn();
+ }
+
+ llvm::Constant *getMessageSendSuperFpretFn2() const {
+ // There is no objc_msgSendSuper_fpret? How can that work?
+ return getMessageSendSuperFn2();
+ }
+
+protected:
+ CodeGen::CodeGenModule &CGM;
+
+public:
+ const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
+ const llvm::Type *Int8PtrTy;
+
+ /// ObjectPtrTy - LLVM type for object handles (typeof(id))
+ const llvm::Type *ObjectPtrTy;
+
+ /// PtrObjectPtrTy - LLVM type for id *
+ const llvm::Type *PtrObjectPtrTy;
+
+ /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
+ const llvm::Type *SelectorPtrTy;
+ /// ProtocolPtrTy - LLVM type for external protocol handles
+ /// (typeof(Protocol))
+ const llvm::Type *ExternalProtocolPtrTy;
+
+ // SuperCTy - clang type for struct objc_super.
+ QualType SuperCTy;
+ // SuperPtrCTy - clang type for struct objc_super *.
+ QualType SuperPtrCTy;
+
+ /// SuperTy - LLVM type for struct objc_super.
+ const llvm::StructType *SuperTy;
+ /// SuperPtrTy - LLVM type for struct objc_super *.
+ const llvm::Type *SuperPtrTy;
+
+ /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
+ /// in GCC parlance).
+ const llvm::StructType *PropertyTy;
+
+ /// PropertyListTy - LLVM type for struct objc_property_list
+ /// (_prop_list_t in GCC parlance).
+ const llvm::StructType *PropertyListTy;
+ /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
+ const llvm::Type *PropertyListPtrTy;
+
+ // MethodTy - LLVM type for struct objc_method.
+ const llvm::StructType *MethodTy;
+
+ /// CacheTy - LLVM type for struct objc_cache.
+ const llvm::Type *CacheTy;
+ /// CachePtrTy - LLVM type for struct objc_cache *.
+ const llvm::Type *CachePtrTy;
+
+ llvm::Constant *getGetPropertyFn() {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+ // id objc_getProperty (id, SEL, ptrdiff_t, bool)
+ llvm::SmallVector<CanQualType,4> Params;
+ CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
+ CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
+ Params.push_back(IdType);
+ Params.push_back(SelType);
+ Params.push_back(Ctx.LongTy);
+ Params.push_back(Ctx.BoolTy);
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
+ FunctionType::ExtInfo()),
+ false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
+ }
+
+ llvm::Constant *getSetPropertyFn() {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+ // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
+ llvm::SmallVector<CanQualType,6> Params;
+ CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
+ CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
+ Params.push_back(IdType);
+ Params.push_back(SelType);
+ Params.push_back(Ctx.LongTy);
+ Params.push_back(IdType);
+ Params.push_back(Ctx.BoolTy);
+ Params.push_back(Ctx.BoolTy);
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ FunctionType::ExtInfo()),
+ false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
+ }
+
+
+ llvm::Constant *getCopyStructFn() {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+ // void objc_copyStruct (void *, const void *, size_t, bool, bool)
+ llvm::SmallVector<CanQualType,5> Params;
+ Params.push_back(Ctx.VoidPtrTy);
+ Params.push_back(Ctx.VoidPtrTy);
+ Params.push_back(Ctx.LongTy);
+ Params.push_back(Ctx.BoolTy);
+ Params.push_back(Ctx.BoolTy);
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ FunctionType::ExtInfo()),
+ false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
+ }
+
+ llvm::Constant *getEnumerationMutationFn() {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+ // void objc_enumerationMutation (id)
+ llvm::SmallVector<CanQualType,1> Params;
+ Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
+ FunctionType::ExtInfo()),
+ false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
+ }
+
+ /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
+ llvm::Constant *getGcReadWeakFn() {
+ // id objc_read_weak (id *)
+ std::vector<const llvm::Type*> Args;
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
+ }
+
+ /// GcAssignWeakFn -- LLVM objc_assign_weak function.
+ llvm::Constant *getGcAssignWeakFn() {
+ // id objc_assign_weak (id, id *)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
+ }
+
+ /// GcAssignGlobalFn -- LLVM objc_assign_global function.
+ llvm::Constant *getGcAssignGlobalFn() {
+ // id objc_assign_global(id, id *)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
+ }
+
+ /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
+ llvm::Constant *getGcAssignThreadLocalFn() {
+ // id objc_assign_threadlocal(id src, id * dest)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
+ }
+
+ /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
+ llvm::Constant *getGcAssignIvarFn() {
+ // id objc_assign_ivar(id, id *, ptrdiff_t)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ Args.push_back(LongTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
+ }
+
+ /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
+ llvm::Constant *GcMemmoveCollectableFn() {
+ // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+ Args.push_back(Int8PtrTy);
+ Args.push_back(LongTy);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
+ }
+
+ /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
+ llvm::Constant *getGcAssignStrongCastFn() {
+ // id objc_assign_strongCast(id, id *)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
+ }
+
+ /// ExceptionThrowFn - LLVM objc_exception_throw function.
+ llvm::Constant *getExceptionThrowFn() {
+ // void objc_exception_throw(id)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
+ }
+
+ /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
+ llvm::Constant *getExceptionRethrowFn() {
+ // void objc_exception_rethrow(void)
+ std::vector<const llvm::Type*> Args;
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
+ }
+
+ /// SyncEnterFn - LLVM object_sync_enter function.
+ llvm::Constant *getSyncEnterFn() {
+ // void objc_sync_enter (id)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
+ }
+
+ /// SyncExitFn - LLVM object_sync_exit function.
+ llvm::Constant *getSyncExitFn() {
+ // void objc_sync_exit (id)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
+ }
+
+ llvm::Constant *getSendFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
+ }
+
+ llvm::Constant *getSendFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
+ }
+
+ llvm::Constant *getSendStretFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
+ }
+
+ llvm::Constant *getSendStretFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
+ }
+
+ llvm::Constant *getSendFpretFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
+ }
+
+ llvm::Constant *getSendFpretFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
+ }
+
+ ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
+ ~ObjCCommonTypesHelper(){}
+};
+
+/// ObjCTypesHelper - Helper class that encapsulates lazy
+/// construction of varies types used during ObjC generation.
+class ObjCTypesHelper : public ObjCCommonTypesHelper {
+public:
+ /// SymtabTy - LLVM type for struct objc_symtab.
+ const llvm::StructType *SymtabTy;
+ /// SymtabPtrTy - LLVM type for struct objc_symtab *.
+ const llvm::Type *SymtabPtrTy;
+ /// ModuleTy - LLVM type for struct objc_module.
+ const llvm::StructType *ModuleTy;
+
+ /// ProtocolTy - LLVM type for struct objc_protocol.
+ const llvm::StructType *ProtocolTy;
+ /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
+ const llvm::Type *ProtocolPtrTy;
+ /// ProtocolExtensionTy - LLVM type for struct
+ /// objc_protocol_extension.
+ const llvm::StructType *ProtocolExtensionTy;
+ /// ProtocolExtensionTy - LLVM type for struct
+ /// objc_protocol_extension *.
+ const llvm::Type *ProtocolExtensionPtrTy;
+ /// MethodDescriptionTy - LLVM type for struct
+ /// objc_method_description.
+ const llvm::StructType *MethodDescriptionTy;
+ /// MethodDescriptionListTy - LLVM type for struct
+ /// objc_method_description_list.
+ const llvm::StructType *MethodDescriptionListTy;
+ /// MethodDescriptionListPtrTy - LLVM type for struct
+ /// objc_method_description_list *.
+ const llvm::Type *MethodDescriptionListPtrTy;
+ /// ProtocolListTy - LLVM type for struct objc_property_list.
+ const llvm::Type *ProtocolListTy;
+ /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
+ const llvm::Type *ProtocolListPtrTy;
+ /// CategoryTy - LLVM type for struct objc_category.
+ const llvm::StructType *CategoryTy;
+ /// ClassTy - LLVM type for struct objc_class.
+ const llvm::StructType *ClassTy;
+ /// ClassPtrTy - LLVM type for struct objc_class *.
+ const llvm::Type *ClassPtrTy;
+ /// ClassExtensionTy - LLVM type for struct objc_class_ext.
+ const llvm::StructType *ClassExtensionTy;
+ /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
+ const llvm::Type *ClassExtensionPtrTy;
+ // IvarTy - LLVM type for struct objc_ivar.
+ const llvm::StructType *IvarTy;
+ /// IvarListTy - LLVM type for struct objc_ivar_list.
+ const llvm::Type *IvarListTy;
+ /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
+ const llvm::Type *IvarListPtrTy;
+ /// MethodListTy - LLVM type for struct objc_method_list.
+ const llvm::Type *MethodListTy;
+ /// MethodListPtrTy - LLVM type for struct objc_method_list *.
+ const llvm::Type *MethodListPtrTy;
+
+ /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
+ const llvm::Type *ExceptionDataTy;
+
+ /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
+ llvm::Constant *getExceptionTryEnterFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ Params, false),
+ "objc_exception_try_enter");
+ }
+
+ /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
+ llvm::Constant *getExceptionTryExitFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ Params, false),
+ "objc_exception_try_exit");
+ }
+
+ /// ExceptionExtractFn - LLVM objc_exception_extract function.
+ llvm::Constant *getExceptionExtractFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, false),
+ "objc_exception_extract");
+
+ }
+
+ /// ExceptionMatchFn - LLVM objc_exception_match function.
+ llvm::Constant *getExceptionMatchFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ClassPtrTy);
+ Params.push_back(ObjectPtrTy);
+ return CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
+ Params, false),
+ "objc_exception_match");
+
+ }
+
+ /// SetJmpFn - LLVM _setjmp function.
+ llvm::Constant *getSetJmpFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
+ Params, false),
+ "_setjmp");
+
+ }
+
+public:
+ ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
+ ~ObjCTypesHelper() {}
+};
+
+/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
+/// modern abi
+class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
+public:
+
+ // MethodListnfABITy - LLVM for struct _method_list_t
+ const llvm::StructType *MethodListnfABITy;
+
+ // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
+ const llvm::Type *MethodListnfABIPtrTy;
+
+ // ProtocolnfABITy = LLVM for struct _protocol_t
+ const llvm::StructType *ProtocolnfABITy;
+
+ // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
+ const llvm::Type *ProtocolnfABIPtrTy;
+
+ // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
+ const llvm::StructType *ProtocolListnfABITy;
+
+ // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
+ const llvm::Type *ProtocolListnfABIPtrTy;
+
+ // ClassnfABITy - LLVM for struct _class_t
+ const llvm::StructType *ClassnfABITy;
+
+ // ClassnfABIPtrTy - LLVM for struct _class_t*
+ const llvm::Type *ClassnfABIPtrTy;
+
+ // IvarnfABITy - LLVM for struct _ivar_t
+ const llvm::StructType *IvarnfABITy;
+
+ // IvarListnfABITy - LLVM for struct _ivar_list_t
+ const llvm::StructType *IvarListnfABITy;
+
+ // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
+ const llvm::Type *IvarListnfABIPtrTy;
+
+ // ClassRonfABITy - LLVM for struct _class_ro_t
+ const llvm::StructType *ClassRonfABITy;
+
+ // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
+ const llvm::Type *ImpnfABITy;
+
+ // CategorynfABITy - LLVM for struct _category_t
+ const llvm::StructType *CategorynfABITy;
+
+ // New types for nonfragile abi messaging.
+
+ // MessageRefTy - LLVM for:
+ // struct _message_ref_t {
+ // IMP messenger;
+ // SEL name;
+ // };
+ const llvm::StructType *MessageRefTy;
+ // MessageRefCTy - clang type for struct _message_ref_t
+ QualType MessageRefCTy;
+
+ // MessageRefPtrTy - LLVM for struct _message_ref_t*
+ const llvm::Type *MessageRefPtrTy;
+ // MessageRefCPtrTy - clang type for struct _message_ref_t*
+ QualType MessageRefCPtrTy;
+
+ // MessengerTy - Type of the messenger (shown as IMP above)
+ const llvm::FunctionType *MessengerTy;
+
+ // SuperMessageRefTy - LLVM for:
+ // struct _super_message_ref_t {
+ // SUPER_IMP messenger;
+ // SEL name;
+ // };
+ const llvm::StructType *SuperMessageRefTy;
+
+ // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
+ const llvm::Type *SuperMessageRefPtrTy;
+
+ llvm::Constant *getMessageSendFixupFn() {
+ // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(MessageRefPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSend_fixup");
+ }
+
+ llvm::Constant *getMessageSendFpretFixupFn() {
+ // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(MessageRefPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSend_fpret_fixup");
+ }
+
+ llvm::Constant *getMessageSendStretFixupFn() {
+ // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(MessageRefPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSend_stret_fixup");
+ }
+
+ llvm::Constant *getMessageSendSuper2FixupFn() {
+ // id objc_msgSendSuper2_fixup (struct objc_super *,
+ // struct _super_message_ref_t*, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SuperMessageRefPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSendSuper2_fixup");
+ }
+
+ llvm::Constant *getMessageSendSuper2StretFixupFn() {
+ // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
+ // struct _super_message_ref_t*, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SuperMessageRefPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSendSuper2_stret_fixup");
+ }
+
+ llvm::Constant *getObjCEndCatchFn() {
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false),
+ "objc_end_catch");
+
+ }
+
+ llvm::Constant *getObjCBeginCatchFn() {
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Int8PtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
+ Params, false),
+ "objc_begin_catch");
+ }
+
+ const llvm::StructType *EHTypeTy;
+ const llvm::Type *EHTypePtrTy;
+
+ ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
+ ~ObjCNonFragileABITypesHelper(){}
+};
+
+class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
+public:
+ // FIXME - accessibility
+ class GC_IVAR {
+ public:
+ unsigned ivar_bytepos;
+ unsigned ivar_size;
+ GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
+ : ivar_bytepos(bytepos), ivar_size(size) {}
+
+ // Allow sorting based on byte pos.
+ bool operator<(const GC_IVAR &b) const {
+ return ivar_bytepos < b.ivar_bytepos;
+ }
+ };
+
+ class SKIP_SCAN {
+ public:
+ unsigned skip;
+ unsigned scan;
+ SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
+ : skip(_skip), scan(_scan) {}
+ };
+
+protected:
+ CodeGen::CodeGenModule &CGM;
+ llvm::LLVMContext &VMContext;
+ // FIXME! May not be needing this after all.
+ unsigned ObjCABI;
+
+ // gc ivar layout bitmap calculation helper caches.
+ llvm::SmallVector<GC_IVAR, 16> SkipIvars;
+ llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
+
+ /// LazySymbols - Symbols to generate a lazy reference for. See
+ /// DefinedSymbols and FinishModule().
+ llvm::SetVector<IdentifierInfo*> LazySymbols;
+
+ /// DefinedSymbols - External symbols which are defined by this
+ /// module. The symbols in this list and LazySymbols are used to add
+ /// special linker symbols which ensure that Objective-C modules are
+ /// linked properly.
+ llvm::SetVector<IdentifierInfo*> DefinedSymbols;
+
+ /// ClassNames - uniqued class names.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
+
+ /// MethodVarNames - uniqued method variable names.
+ llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
+
+ /// DefinedCategoryNames - list of category names in form Class_Category.
+ llvm::SetVector<std::string> DefinedCategoryNames;
+
+ /// MethodVarTypes - uniqued method type signatures. We have to use
+ /// a StringMap here because have no other unique reference.
+ llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
+
+ /// MethodDefinitions - map of methods which have been defined in
+ /// this translation unit.
+ llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
+
+ /// PropertyNames - uniqued method variable names.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
+
+ /// ClassReferences - uniqued class references.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
+
+ /// SelectorReferences - uniqued selector references.
+ llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
+
+ /// Protocols - Protocols for which an objc_protocol structure has
+ /// been emitted. Forward declarations are handled by creating an
+ /// empty structure whose initializer is filled in when/if defined.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
+
+ /// DefinedProtocols - Protocols which have actually been
+ /// defined. We should not need this, see FIXME in GenerateProtocol.
+ llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
+
+ /// DefinedClasses - List of defined classes.
+ std::vector<llvm::GlobalValue*> DefinedClasses;
+
+ /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
+ std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
+
+ /// DefinedCategories - List of defined categories.
+ std::vector<llvm::GlobalValue*> DefinedCategories;
+
+ /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
+ std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
+
+ /// GetNameForMethod - Return a name for the given method.
+ /// \param[out] NameOut - The return value.
+ void GetNameForMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD,
+ llvm::SmallVectorImpl<char> &NameOut);
+
+ /// GetMethodVarName - Return a unique constant for the given
+ /// selector's name. The return value has type char *.
+ llvm::Constant *GetMethodVarName(Selector Sel);
+ llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
+
+ /// GetMethodVarType - Return a unique constant for the given
+ /// selector's name. The return value has type char *.
+
+ // FIXME: This is a horrible name.
+ llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
+ llvm::Constant *GetMethodVarType(const FieldDecl *D);
+
+ /// GetPropertyName - Return a unique constant for the given
+ /// name. The return value has type char *.
+ llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
+
+ // FIXME: This can be dropped once string functions are unified.
+ llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
+ const Decl *Container);
+
+ /// GetClassName - Return a unique constant for the given selector's
+ /// name. The return value has type char *.
+ llvm::Constant *GetClassName(IdentifierInfo *Ident);
+
+ llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
+
+ /// BuildIvarLayout - Builds ivar layout bitmap for the class
+ /// implementation for the __strong or __weak case.
+ ///
+ llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
+ bool ForStrongLayout);
+
+ llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
+
+ void BuildAggrIvarRecordLayout(const RecordType *RT,
+ unsigned int BytePos, bool ForStrongLayout,
+ bool &HasUnion);
+ void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
+ const llvm::StructLayout *Layout,
+ const RecordDecl *RD,
+ const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
+ unsigned int BytePos, bool ForStrongLayout,
+ bool &HasUnion);
+
+ /// GetIvarLayoutName - Returns a unique constant for the given
+ /// ivar layout bitmap.
+ llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
+ const ObjCCommonTypesHelper &ObjCTypes);
+
+ /// EmitPropertyList - Emit the given property list. The return
+ /// value has type PropertyListPtrTy.
+ llvm::Constant *EmitPropertyList(llvm::Twine Name,
+ const Decl *Container,
+ const ObjCContainerDecl *OCD,
+ const ObjCCommonTypesHelper &ObjCTypes);
+
+ /// PushProtocolProperties - Push protocol's property on the input stack.
+ void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
+ std::vector<llvm::Constant*> &Properties,
+ const Decl *Container,
+ const ObjCProtocolDecl *PROTO,
+ const ObjCCommonTypesHelper &ObjCTypes);
+
+ /// GetProtocolRef - Return a reference to the internal protocol
+ /// description, creating an empty one if it has not been
+ /// defined. The return value has type ProtocolPtrTy.
+ llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
+
+ /// CreateMetadataVar - Create a global variable with internal
+ /// linkage for use by the Objective-C runtime.
+ ///
+ /// This is a convenience wrapper which not only creates the
+ /// variable, but also sets the section and alignment and adds the
+ /// global to the "llvm.used" list.
+ ///
+ /// \param Name - The variable name.
+ /// \param Init - The variable initializer; this is also used to
+ /// define the type of the variable.
+ /// \param Section - The section the variable should go into, or 0.
+ /// \param Align - The alignment for the variable, or 0.
+ /// \param AddToUsed - Whether the variable should be added to
+ /// "llvm.used".
+ llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
+ llvm::Constant *Init,
+ const char *Section,
+ unsigned Align,
+ bool AddToUsed);
+
+ CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ llvm::Value *Sel,
+ llvm::Value *Arg0,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *OMD,
+ const ObjCCommonTypesHelper &ObjCTypes);
+
+ /// EmitImageInfo - Emit the image info marker used to encode some module
+ /// level information.
+ void EmitImageInfo();
+
+public:
+ CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
+ CGM(cgm), VMContext(cgm.getLLVMContext()) { }
+
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
+
+ virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD=0);
+
+ virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
+
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
+
+ /// GetOrEmitProtocolRef - Get a forward reference to the protocol
+ /// object for the given declaration, emitting it if needed. These
+ /// forward references will be filled in with empty bodies if no
+ /// definition is seen. The return value has type ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
+ virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo);
+
+};
+
+class CGObjCMac : public CGObjCCommonMac {
+private:
+ ObjCTypesHelper ObjCTypes;
+
+ /// EmitModuleInfo - Another marker encoding module level
+ /// information.
+ void EmitModuleInfo();
+
+ /// EmitModuleSymols - Emit module symbols, the list of defined
+ /// classes and categories. The result has type SymtabPtrTy.
+ llvm::Constant *EmitModuleSymbols();
+
+ /// FinishModule - Write out global data structures at the end of
+ /// processing a translation unit.
+ void FinishModule();
+
+ /// EmitClassExtension - Generate the class extension structure used
+ /// to store the weak ivar layout and properties. The return value
+ /// has type ClassExtensionPtrTy.
+ llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
+
+ /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
+ /// for the given class.
+ llvm::Value *EmitClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ /// EmitSuperClassRef - Emits reference to class's main metadata class.
+ llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
+
+ /// EmitIvarList - Emit the ivar list for the given
+ /// implementation. If ForClass is true the list of class ivars
+ /// (i.e. metaclass ivars) is emitted, otherwise the list of
+ /// interface ivars will be emitted. The return value has type
+ /// IvarListPtrTy.
+ llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
+ bool ForClass);
+
+ /// EmitMetaClass - Emit a forward reference to the class structure
+ /// for the metaclass of the given interface. The return value has
+ /// type ClassPtrTy.
+ llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
+
+ /// EmitMetaClass - Emit a class structure for the metaclass of the
+ /// given implementation. The return value has type ClassPtrTy.
+ llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
+ llvm::Constant *Protocols,
+ const ConstantVector &Methods);
+
+ llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
+
+ llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
+
+ /// EmitMethodList - Emit the method list for the given
+ /// implementation. The return value has type MethodListPtrTy.
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods);
+
+ /// EmitMethodDescList - Emit a method description list for a list of
+ /// method declarations.
+ /// - TypeName: The name for the type containing the methods.
+ /// - IsProtocol: True iff these methods are for a protocol.
+ /// - ClassMethds: True iff these are class methods.
+ /// - Required: When true, only "required" methods are
+ /// listed. Similarly, when false only "optional" methods are
+ /// listed. For classes this should always be true.
+ /// - begin, end: The method list to output.
+ ///
+ /// The return value has type MethodDescriptionListPtrTy.
+ llvm::Constant *EmitMethodDescList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods);
+
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
+
+ /// GetOrEmitProtocolRef - Get a forward reference to the protocol
+ /// object for the given declaration, emitting it if needed. These
+ /// forward references will be filled in with empty bodies if no
+ /// definition is seen. The return value has type ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
+
+ /// EmitProtocolExtension - Generate the protocol extension
+ /// structure used to store optional instance and class methods, and
+ /// protocol properties. The return value has type
+ /// ProtocolExtensionPtrTy.
+ llvm::Constant *
+ EmitProtocolExtension(const ObjCProtocolDecl *PD,
+ const ConstantVector &OptInstanceMethods,
+ const ConstantVector &OptClassMethods);
+
+ /// EmitProtocolList - Generate the list of referenced
+ /// protocols. The return value has type ProtocolListPtrTy.
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end);
+
+ /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
+ /// for the given selector.
+ llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval=false);
+
+public:
+ CGObjCMac(CodeGen::CodeGenModule &cgm);
+
+ virtual llvm::Function *ModuleInitFunction();
+
+ virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method);
+
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method);
+
+ virtual llvm::Value *GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval = false);
+
+ /// The NeXT/Apple runtimes do not support typed selectors; just emit an
+ /// untyped one.
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
+ const ObjCMethodDecl *Method);
+
+ virtual llvm::Constant *GetEHType(QualType T);
+
+ virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
+
+ virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
+
+ virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD);
+
+ virtual llvm::Constant *GetPropertyGetFunction();
+ virtual llvm::Constant *GetPropertySetFunction();
+ virtual llvm::Constant *GetGetStructFunction();
+ virtual llvm::Constant *GetSetStructFunction();
+ virtual llvm::Constant *EnumerationMutationFunction();
+
+ virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S);
+ virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S);
+ void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
+ virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S);
+ virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj);
+ virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst);
+ virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal = false);
+ virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ llvm::Value *ivarOffset);
+ virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest);
+ virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *dest, llvm::Value *src,
+ llvm::Value *size);
+
+ virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers);
+ virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar);
+};
+
+class CGObjCNonFragileABIMac : public CGObjCCommonMac {
+private:
+ ObjCNonFragileABITypesHelper ObjCTypes;
+ llvm::GlobalVariable* ObjCEmptyCacheVar;
+ llvm::GlobalVariable* ObjCEmptyVtableVar;
+
+ /// SuperClassReferences - uniqued super class references.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
+
+ /// MetaClassReferences - uniqued meta class references.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
+
+ /// EHTypeReferences - uniqued class ehtype references.
+ llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
+
+ /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
+ /// legacy messaging dispatch.
+ llvm::DenseSet<Selector> NonLegacyDispatchMethods;
+
+ /// DefinedMetaClasses - List of defined meta-classes.
+ std::vector<llvm::GlobalValue*> DefinedMetaClasses;
+
+ /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
+ /// NonLegacyDispatchMethods; false otherwise.
+ bool LegacyDispatchedSelector(Selector Sel);
+
+ /// FinishNonFragileABIModule - Write out global data structures at the end of
+ /// processing a translation unit.
+ void FinishNonFragileABIModule();
+
+ /// AddModuleClassList - Add the given list of class pointers to the
+ /// module with the provided symbol and section names.
+ void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
+ const char *SymbolName,
+ const char *SectionName);
+
+ llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
+ unsigned InstanceStart,
+ unsigned InstanceSize,
+ const ObjCImplementationDecl *ID);
+ llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
+ llvm::Constant *IsAGV,
+ llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV,
+ bool HiddenVisibility);
+
+ llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
+
+ llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
+
+ /// EmitMethodList - Emit the method list for the given
+ /// implementation. The return value has type MethodListnfABITy.
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods);
+ /// EmitIvarList - Emit the ivar list for the given
+ /// implementation. If ForClass is true the list of class ivars
+ /// (i.e. metaclass ivars) is emitted, otherwise the list of
+ /// interface ivars will be emitted. The return value has type
+ /// IvarListnfABIPtrTy.
+ llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
+
+ llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar,
+ unsigned long int offset);
+
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
+
+ /// GetOrEmitProtocolRef - Get a forward reference to the protocol
+ /// object for the given declaration, emitting it if needed. These
+ /// forward references will be filled in with empty bodies if no
+ /// definition is seen. The return value has type ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
+
+ /// EmitProtocolList - Generate the list of referenced
+ /// protocols. The return value has type ProtocolListPtrTy.
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end);
+
+ CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs);
+
+ /// GetClassGlobal - Return the global variable for the Objective-C
+ /// class of the given name.
+ llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
+
+ /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
+ /// for the given class reference.
+ llvm::Value *EmitClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
+ /// for the given super class reference.
+ llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ /// EmitMetaClassRef - Return a Value * of the address of _class_t
+ /// meta-data
+ llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
+ /// the given ivar.
+ ///
+ llvm::GlobalVariable * ObjCIvarOffsetVariable(
+ const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar);
+
+ /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
+ /// for the given selector.
+ llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval=false);
+
+ /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
+ /// interface. The return value has type EHTypePtrTy.
+ llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
+ bool ForDefinition);
+
+ const char *getMetaclassSymbolPrefix() const {
+ return "OBJC_METACLASS_$_";
+ }
+
+ const char *getClassSymbolPrefix() const {
+ return "OBJC_CLASS_$_";
+ }
+
+ void GetClassSizeInfo(const ObjCImplementationDecl *OID,
+ uint32_t &InstanceStart,
+ uint32_t &InstanceSize);
+
+ // Shamelessly stolen from Analysis/CFRefCount.cpp
+ Selector GetNullarySelector(const char* name) const {
+ IdentifierInfo* II = &CGM.getContext().Idents.get(name);
+ return CGM.getContext().Selectors.getSelector(0, &II);
+ }
+
+ Selector GetUnarySelector(const char* name) const {
+ IdentifierInfo* II = &CGM.getContext().Idents.get(name);
+ return CGM.getContext().Selectors.getSelector(1, &II);
+ }
+
+ /// ImplementationIsNonLazy - Check whether the given category or
+ /// class implementation is "non-lazy".
+ bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
+
+public:
+ CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
+ // FIXME. All stubs for now!
+ virtual llvm::Function *ModuleInitFunction();
+
+ virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method);
+
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method);
+
+ virtual llvm::Value *GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID);
+
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lvalue = false)
+ { return EmitSelector(Builder, Sel, lvalue); }
+
+ /// The NeXT/Apple runtimes do not support typed selectors; just emit an
+ /// untyped one.
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
+ const ObjCMethodDecl *Method)
+ { return EmitSelector(Builder, Method->getSelector()); }
+
+ virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
+
+ virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
+ virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD);
+
+ virtual llvm::Constant *GetEHType(QualType T);
+
+ virtual llvm::Constant *GetPropertyGetFunction() {
+ return ObjCTypes.getGetPropertyFn();
+ }
+ virtual llvm::Constant *GetPropertySetFunction() {
+ return ObjCTypes.getSetPropertyFn();
+ }
+
+ virtual llvm::Constant *GetSetStructFunction() {
+ return ObjCTypes.getCopyStructFn();
+ }
+ virtual llvm::Constant *GetGetStructFunction() {
+ return ObjCTypes.getCopyStructFn();
+ }
+
+ virtual llvm::Constant *EnumerationMutationFunction() {
+ return ObjCTypes.getEnumerationMutationFn();
+ }
+
+ virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S);
+ virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S);
+ virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S);
+ virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj);
+ virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst);
+ virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal = false);
+ virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ llvm::Value *ivarOffset);
+ virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest);
+ virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *dest, llvm::Value *src,
+ llvm::Value *size);
+ virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers);
+ virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar);
+};
+
+} // end anonymous namespace
+
+/* *** Helper Functions *** */
+
+/// getConstantGEP() - Help routine to construct simple GEPs.
+static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
+ llvm::Constant *C,
+ unsigned idx0,
+ unsigned idx1) {
+ llvm::Value *Idxs[] = {
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
+ };
+ return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
+}
+
+/// hasObjCExceptionAttribute - Return true if this class or any super
+/// class has the __objc_exception__ attribute.
+static bool hasObjCExceptionAttribute(ASTContext &Context,
+ const ObjCInterfaceDecl *OID) {
+ if (OID->hasAttr<ObjCExceptionAttr>())
+ return true;
+ if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
+ return hasObjCExceptionAttribute(Context, Super);
+ return false;
+}
+
+/* *** CGObjCMac Public Interface *** */
+
+CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
+ ObjCTypes(cgm) {
+ ObjCABI = 1;
+ EmitImageInfo();
+}
+
+/// GetClass - Return a reference to the class for the given interface
+/// decl.
+llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ return EmitClassRef(Builder, ID);
+}
+
+/// GetSelector - Return the pointer to the unique'd string for this selector.
+llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lval) {
+ return EmitSelector(Builder, Sel, lval);
+}
+llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
+ *Method) {
+ return EmitSelector(Builder, Method->getSelector());
+}
+
+llvm::Constant *CGObjCMac::GetEHType(QualType T) {
+ llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
+ return 0;
+}
+
+/// Generate a constant CFString object.
+/*
+ struct __builtin_CFString {
+ const int *isa; // point to __CFConstantStringClassReference
+ int flags;
+ const char *str;
+ long length;
+ };
+*/
+
+/// or Generate a constant NSString object.
+/*
+ struct __builtin_NSString {
+ const int *isa; // point to __NSConstantStringClassReference
+ const char *str;
+ unsigned int length;
+ };
+*/
+
+llvm::Constant *CGObjCCommonMac::GenerateConstantString(
+ const StringLiteral *SL) {
+ return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
+ CGM.GetAddrOfConstantCFString(SL) :
+ CGM.GetAddrOfConstantString(SL));
+}
+
+/// Generates a message send where the super is the receiver. This is
+/// a message send to self with special delivery semantics indicating
+/// which class's method should be called.
+CodeGen::RValue
+CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CodeGen::CallArgList &CallArgs,
+ const ObjCMethodDecl *Method) {
+ // Create and init a super structure; this is a (receiver, class)
+ // pair we will pass to objc_msgSendSuper.
+ llvm::Value *ObjCSuper =
+ CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
+ llvm::Value *ReceiverAsObject =
+ CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
+ CGF.Builder.CreateStore(ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+
+ // If this is a class message the metaclass is passed as the target.
+ llvm::Value *Target;
+ if (IsClassMessage) {
+ if (isCategoryImpl) {
+ // Message sent to 'super' in a class method defined in a category
+ // implementation requires an odd treatment.
+ // If we are in a class method, we must retrieve the
+ // _metaclass_ for the current class, pointed at by
+ // the class's "isa" pointer. The following assumes that
+ // isa" is the first ivar in a class (which it must be).
+ Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
+ Target = CGF.Builder.CreateStructGEP(Target, 0);
+ Target = CGF.Builder.CreateLoad(Target);
+ } else {
+ llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
+ llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
+ llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
+ Target = Super;
+ }
+ }
+ else if (isCategoryImpl)
+ Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
+ else {
+ llvm::Value *ClassPtr = EmitSuperClassRef(Class);
+ ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
+ Target = CGF.Builder.CreateLoad(ClassPtr);
+ }
+ // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
+ // ObjCTypes types.
+ const llvm::Type *ClassTy =
+ CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
+ Target = CGF.Builder.CreateBitCast(Target, ClassTy);
+ CGF.Builder.CreateStore(Target,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+ return EmitLegacyMessageSend(CGF, Return, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs, Method, ObjCTypes);
+}
+
+/// Generate code for a message send expression.
+CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method) {
+ return EmitLegacyMessageSend(CGF, Return, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs, Method, ObjCTypes);
+}
+
+CodeGen::RValue
+CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ llvm::Value *Sel,
+ llvm::Value *Arg0,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method,
+ const ObjCCommonTypesHelper &ObjCTypes) {
+ CallArgList ActualArgs;
+ if (!IsSuper)
+ Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
+ ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
+ ActualArgs.push_back(std::make_pair(RValue::get(Sel),
+ CGF.getContext().getObjCSelType()));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
+ FunctionType::ExtInfo());
+ const llvm::FunctionType *FTy =
+ Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
+
+ if (Method)
+ assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
+ CGM.getContext().getCanonicalType(ResultType) &&
+ "Result type mismatch!");
+
+ llvm::Constant *Fn = NULL;
+ if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
+ : ObjCTypes.getSendStretFn(IsSuper);
+ } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
+ Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
+ : ObjCTypes.getSendFpretFn(IsSuper);
+ } else {
+ Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
+ : ObjCTypes.getSendFn(IsSuper);
+ }
+ Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
+ return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
+}
+
+static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
+ if (FQT.isObjCGCStrong())
+ return Qualifiers::Strong;
+
+ if (FQT.isObjCGCWeak())
+ return Qualifiers::Weak;
+
+ if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
+ return Qualifiers::Strong;
+
+ if (const PointerType *PT = FQT->getAs<PointerType>())
+ return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
+
+ return Qualifiers::GCNone;
+}
+
+llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
+ const CGBlockInfo &blockInfo) {
+ llvm::Constant *nullPtr =
+ llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
+
+ if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+ return nullPtr;
+
+ bool hasUnion = false;
+ SkipIvars.clear();
+ IvarsInfo.clear();
+ unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
+ unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
+
+ // __isa is the first field in block descriptor and must assume by runtime's
+ // convention that it is GC'able.
+ IvarsInfo.push_back(GC_IVAR(0, 1));
+
+ const BlockDecl *blockDecl = blockInfo.getBlockDecl();
+
+ // Calculate the basic layout of the block structure.
+ const llvm::StructLayout *layout =
+ CGM.getTargetData().getStructLayout(blockInfo.StructureType);
+
+ // Ignore the optional 'this' capture: C++ objects are not assumed
+ // to be GC'ed.
+
+ // Walk the captured variables.
+ for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
+ ce = blockDecl->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ QualType type = variable->getType();
+
+ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
+
+ // Ignore constant captures.
+ if (capture.isConstant()) continue;
+
+ uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
+
+ // __block variables are passed by their descriptor address.
+ if (ci->isByRef()) {
+ IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
+ continue;
+ }
+
+ assert(!type->isArrayType() && "array variable should not be caught");
+ if (const RecordType *record = type->getAs<RecordType>()) {
+ BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
+ continue;
+ }
+
+ Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
+ unsigned fieldSize = CGM.getContext().getTypeSize(type);
+
+ if (GCAttr == Qualifiers::Strong)
+ IvarsInfo.push_back(GC_IVAR(fieldOffset,
+ fieldSize / WordSizeInBits));
+ else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
+ SkipIvars.push_back(GC_IVAR(fieldOffset,
+ fieldSize / ByteSizeInBits));
+ }
+
+ if (IvarsInfo.empty())
+ return nullPtr;
+
+ // Sort on byte position; captures might not be allocated in order,
+ // and unions can do funny things.
+ llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
+ llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
+
+ std::string BitMap;
+ llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
+ if (CGM.getLangOptions().ObjCGCBitmapPrint) {
+ printf("\n block variable layout for block: ");
+ const unsigned char *s = (unsigned char*)BitMap.c_str();
+ for (unsigned i = 0; i < BitMap.size(); i++)
+ if (!(s[i] & 0xf0))
+ printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
+ else
+ printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
+ printf("\n");
+ }
+
+ return C;
+}
+
+llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD) {
+ // FIXME: I don't understand why gcc generates this, or where it is
+ // resolved. Investigate. Its also wasteful to look this up over and over.
+ LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
+
+ return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
+ ObjCTypes.ExternalProtocolPtrTy);
+}
+
+void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
+ // FIXME: We shouldn't need this, the protocol decl should contain enough
+ // information to tell us whether this was a declaration or a definition.
+ DefinedProtocols.insert(PD->getIdentifier());
+
+ // If we have generated a forward reference to this protocol, emit
+ // it now. Otherwise do nothing, the protocol objects are lazily
+ // emitted.
+ if (Protocols.count(PD->getIdentifier()))
+ GetOrEmitProtocol(PD);
+}
+
+llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
+ if (DefinedProtocols.count(PD->getIdentifier()))
+ return GetOrEmitProtocol(PD);
+ return GetOrEmitProtocolRef(PD);
+}
+
+/*
+// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
+struct _objc_protocol {
+struct _objc_protocol_extension *isa;
+char *protocol_name;
+struct _objc_protocol_list *protocol_list;
+struct _objc__method_prototype_list *instance_methods;
+struct _objc__method_prototype_list *class_methods
+};
+
+See EmitProtocolExtension().
+*/
+llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ // Early exit if a defining object has already been generated.
+ if (Entry && Entry->hasInitializer())
+ return Entry;
+
+ // FIXME: I don't understand why gcc generates this, or where it is
+ // resolved. Investigate. Its also wasteful to look this up over and over.
+ LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
+
+ // Construct method lists.
+ std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
+ std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
+ for (ObjCProtocolDecl::instmeth_iterator
+ i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodDescriptionConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptInstanceMethods.push_back(C);
+ } else {
+ InstanceMethods.push_back(C);
+ }
+ }
+
+ for (ObjCProtocolDecl::classmeth_iterator
+ i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodDescriptionConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptClassMethods.push_back(C);
+ } else {
+ ClassMethods.push_back(C);
+ }
+ }
+
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
+ Values[1] = GetClassName(PD->getIdentifier());
+ Values[2] =
+ EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
+ PD->protocol_begin(),
+ PD->protocol_end());
+ Values[3] =
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
+ "__OBJC,__cat_inst_meth,regular,no_dead_strip",
+ InstanceMethods);
+ Values[4] =
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
+ "__OBJC,__cat_cls_meth,regular,no_dead_strip",
+ ClassMethods);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
+ Values);
+
+ if (Entry) {
+ // Already created, fix the linkage and update the initializer.
+ Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
+ Entry->setInitializer(Init);
+ } else {
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
+ Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
+ // FIXME: Is this necessary? Why only for protocol?
+ Entry->setAlignment(4);
+ }
+ CGM.AddUsedGlobal(Entry);
+
+ return Entry;
+}
+
+llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ if (!Entry) {
+ // We use the initializer as a marker of whether this is a forward
+ // reference or not. At module finalization we add the empty
+ // contents for protocols which were referenced but never defined.
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
+ Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
+ // FIXME: Is this necessary? Why only for protocol?
+ Entry->setAlignment(4);
+ }
+
+ return Entry;
+}
+
+/*
+ struct _objc_protocol_extension {
+ uint32_t size;
+ struct objc_method_description_list *optional_instance_methods;
+ struct objc_method_description_list *optional_class_methods;
+ struct objc_property_list *instance_properties;
+ };
+*/
+llvm::Constant *
+CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
+ const ConstantVector &OptInstanceMethods,
+ const ConstantVector &OptClassMethods) {
+ uint64_t Size =
+ CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
+ std::vector<llvm::Constant*> Values(4);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values[1] =
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
+ + PD->getName(),
+ "__OBJC,__cat_inst_meth,regular,no_dead_strip",
+ OptInstanceMethods);
+ Values[2] =
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
+ "__OBJC,__cat_cls_meth,regular,no_dead_strip",
+ OptClassMethods);
+ Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
+ 0, PD, ObjCTypes);
+
+ // Return null if no extension bits are used.
+ if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
+ Values[3]->isNullValue())
+ return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
+
+ llvm::Constant *Init =
+ llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
+
+ // No special section, but goes in llvm.used
+ return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
+ Init,
+ 0, 0, true);
+}
+
+/*
+ struct objc_protocol_list {
+ struct objc_protocol_list *next;
+ long count;
+ Protocol *list[];
+ };
+*/
+llvm::Constant *
+CGObjCMac::EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
+ std::vector<llvm::Constant*> ProtocolRefs;
+
+ for (; begin != end; ++begin)
+ ProtocolRefs.push_back(GetProtocolRef(*begin));
+
+ // Just return null for empty protocol lists
+ if (ProtocolRefs.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+
+ // This list is null terminated.
+ ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
+
+ std::vector<llvm::Constant*> Values(3);
+ // This field is only used by the runtime.
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
+ ProtocolRefs.size() - 1);
+ Values[2] =
+ llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
+ ProtocolRefs.size()),
+ ProtocolRefs);
+
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
+ 4, false);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
+}
+
+void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
+ std::vector<llvm::Constant*> &Properties,
+ const Decl *Container,
+ const ObjCProtocolDecl *PROTO,
+ const ObjCCommonTypesHelper &ObjCTypes) {
+ std::vector<llvm::Constant*> Prop(2);
+ for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
+ E = PROTO->protocol_end(); P != E; ++P)
+ PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
+ for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
+ E = PROTO->prop_end(); I != E; ++I) {
+ const ObjCPropertyDecl *PD = *I;
+ if (!PropertySet.insert(PD->getIdentifier()))
+ continue;
+ Prop[0] = GetPropertyName(PD->getIdentifier());
+ Prop[1] = GetPropertyTypeString(PD, Container);
+ Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
+ }
+}
+
+/*
+ struct _objc_property {
+ const char * const name;
+ const char * const attributes;
+ };
+
+ struct _objc_property_list {
+ uint32_t entsize; // sizeof (struct _objc_property)
+ uint32_t prop_count;
+ struct _objc_property[prop_count];
+ };
+*/
+llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
+ const Decl *Container,
+ const ObjCContainerDecl *OCD,
+ const ObjCCommonTypesHelper &ObjCTypes) {
+ std::vector<llvm::Constant*> Properties, Prop(2);
+ llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+ for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
+ E = OCD->prop_end(); I != E; ++I) {
+ const ObjCPropertyDecl *PD = *I;
+ PropertySet.insert(PD->getIdentifier());
+ Prop[0] = GetPropertyName(PD->getIdentifier());
+ Prop[1] = GetPropertyTypeString(PD, Container);
+ Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
+ Prop));
+ }
+ if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); P != E; ++P)
+ PushProtocolProperties(PropertySet, Properties, Container, (*P),
+ ObjCTypes);
+ }
+ else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
+ for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
+ E = CD->protocol_end(); P != E; ++P)
+ PushProtocolProperties(PropertySet, Properties, Container, (*P),
+ ObjCTypes);
+ }
+
+ // Return null for empty list.
+ if (Properties.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+
+ unsigned PropertySize =
+ CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
+ std::vector<llvm::Constant*> Values(3);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
+ Properties.size());
+ Values[2] = llvm::ConstantArray::get(AT, Properties);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar(Name, Init,
+ (ObjCABI == 2) ? "__DATA, __objc_const" :
+ "__OBJC,__property,regular,no_dead_strip",
+ (ObjCABI == 2) ? 8 : 4,
+ true);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
+}
+
+/*
+ struct objc_method_description_list {
+ int count;
+ struct objc_method_description list[];
+ };
+*/
+llvm::Constant *
+CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
+ std::vector<llvm::Constant*> Desc(2);
+ Desc[0] =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ Desc[1] = GetMethodVarType(MD);
+ return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
+ Desc);
+}
+
+llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods) {
+ // Return null for empty list.
+ if (Methods.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
+
+ std::vector<llvm::Constant*> Values(2);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
+ Methods.size());
+ Values[1] = llvm::ConstantArray::get(AT, Methods);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ return llvm::ConstantExpr::getBitCast(GV,
+ ObjCTypes.MethodDescriptionListPtrTy);
+}
+
+/*
+ struct _objc_category {
+ char *category_name;
+ char *class_name;
+ struct _objc_method_list *instance_methods;
+ struct _objc_method_list *class_methods;
+ struct _objc_protocol_list *protocols;
+ uint32_t size; // <rdar://4585769>
+ struct _objc_property_list *instance_properties;
+ };
+*/
+void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
+
+ // FIXME: This is poor design, the OCD should have a pointer to the category
+ // decl. Additionally, note that Category can be null for the @implementation
+ // w/o an @interface case. Sema should just create one for us as it does for
+ // @implementation so everyone else can live life under a clear blue sky.
+ const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
+ const ObjCCategoryDecl *Category =
+ Interface->FindCategoryDeclaration(OCD->getIdentifier());
+
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
+ << OCD->getName();
+
+ std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
+ for (ObjCCategoryImplDecl::instmeth_iterator
+ i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
+ // Instance methods should always be defined.
+ InstanceMethods.push_back(GetMethodConstant(*i));
+ }
+ for (ObjCCategoryImplDecl::classmeth_iterator
+ i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
+ // Class methods should always be defined.
+ ClassMethods.push_back(GetMethodConstant(*i));
+ }
+
+ std::vector<llvm::Constant*> Values(7);
+ Values[0] = GetClassName(OCD->getIdentifier());
+ Values[1] = GetClassName(Interface->getIdentifier());
+ LazySymbols.insert(Interface->getIdentifier());
+ Values[2] =
+ EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
+ "__OBJC,__cat_inst_meth,regular,no_dead_strip",
+ InstanceMethods);
+ Values[3] =
+ EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
+ "__OBJC,__cat_cls_meth,regular,no_dead_strip",
+ ClassMethods);
+ if (Category) {
+ Values[4] =
+ EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
+ Category->protocol_begin(),
+ Category->protocol_end());
+ } else {
+ Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+ }
+ Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+
+ // If there is no category @interface then there can be no properties.
+ if (Category) {
+ Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes);
+ } else {
+ Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ }
+
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
+ Values);
+
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
+ "__OBJC,__category,regular,no_dead_strip",
+ 4, true);
+ DefinedCategories.push_back(GV);
+ DefinedCategoryNames.insert(ExtName.str());
+}
+
+// FIXME: Get from somewhere?
+enum ClassFlags {
+ eClassFlags_Factory = 0x00001,
+ eClassFlags_Meta = 0x00002,
+ // <rdr://5142207>
+ eClassFlags_HasCXXStructors = 0x02000,
+ eClassFlags_Hidden = 0x20000,
+ eClassFlags_ABI2_Hidden = 0x00010,
+ eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
+};
+
+/*
+ struct _objc_class {
+ Class isa;
+ Class super_class;
+ const char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct _objc_ivar_list *ivars;
+ struct _objc_method_list *methods;
+ struct _objc_cache *cache;
+ struct _objc_protocol_list *protocols;
+ // Objective-C 1.0 extensions (<rdr://4585769>)
+ const char *ivar_layout;
+ struct _objc_class_ext *ext;
+ };
+
+ See EmitClassExtension();
+*/
+void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
+ DefinedSymbols.insert(ID->getIdentifier());
+
+ std::string ClassName = ID->getNameAsString();
+ // FIXME: Gross
+ ObjCInterfaceDecl *Interface =
+ const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
+ llvm::Constant *Protocols =
+ EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
+ Interface->all_referenced_protocol_begin(),
+ Interface->all_referenced_protocol_end());
+ unsigned Flags = eClassFlags_Factory;
+ if (ID->getNumIvarInitializers())
+ Flags |= eClassFlags_HasCXXStructors;
+ unsigned Size =
+ CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
+
+ // FIXME: Set CXX-structors flag.
+ if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
+ Flags |= eClassFlags_Hidden;
+
+ std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
+ for (ObjCImplementationDecl::instmeth_iterator
+ i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
+ // Instance methods should always be defined.
+ InstanceMethods.push_back(GetMethodConstant(*i));
+ }
+ for (ObjCImplementationDecl::classmeth_iterator
+ i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
+ // Class methods should always be defined.
+ ClassMethods.push_back(GetMethodConstant(*i));
+ }
+
+ for (ObjCImplementationDecl::propimpl_iterator
+ i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
+ ObjCPropertyImplDecl *PID = *i;
+
+ if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
+ ObjCPropertyDecl *PD = PID->getPropertyDecl();
+
+ if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
+ if (llvm::Constant *C = GetMethodConstant(MD))
+ InstanceMethods.push_back(C);
+ if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
+ if (llvm::Constant *C = GetMethodConstant(MD))
+ InstanceMethods.push_back(C);
+ }
+ }
+
+ std::vector<llvm::Constant*> Values(12);
+ Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
+ if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
+ // Record a reference to the super class.
+ LazySymbols.insert(Super->getIdentifier());
+
+ Values[ 1] =
+ llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
+ ObjCTypes.ClassPtrTy);
+ } else {
+ Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
+ }
+ Values[ 2] = GetClassName(ID->getIdentifier());
+ // Version is always 0.
+ Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
+ Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
+ Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
+ Values[ 6] = EmitIvarList(ID, false);
+ Values[ 7] =
+ EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
+ "__OBJC,__inst_meth,regular,no_dead_strip",
+ InstanceMethods);
+ // cache is always NULL.
+ Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
+ Values[ 9] = Protocols;
+ Values[10] = BuildIvarLayout(ID, true);
+ Values[11] = EmitClassExtension(ID);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
+ Values);
+ std::string Name("\01L_OBJC_CLASS_");
+ Name += ClassName;
+ const char *Section = "__OBJC,__class,regular,no_dead_strip";
+ // Check for a forward reference.
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GV->setInitializer(Init);
+ GV->setSection(Section);
+ GV->setAlignment(4);
+ CGM.AddUsedGlobal(GV);
+ }
+ else
+ GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ DefinedClasses.push_back(GV);
+}
+
+llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
+ llvm::Constant *Protocols,
+ const ConstantVector &Methods) {
+ unsigned Flags = eClassFlags_Meta;
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
+
+ if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
+ Flags |= eClassFlags_Hidden;
+
+ std::vector<llvm::Constant*> Values(12);
+ // The isa for the metaclass is the root of the hierarchy.
+ const ObjCInterfaceDecl *Root = ID->getClassInterface();
+ while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
+ Root = Super;
+ Values[ 0] =
+ llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
+ ObjCTypes.ClassPtrTy);
+ // The super class for the metaclass is emitted as the name of the
+ // super class. The runtime fixes this up to point to the
+ // *metaclass* for the super class.
+ if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
+ Values[ 1] =
+ llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
+ ObjCTypes.ClassPtrTy);
+ } else {
+ Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
+ }
+ Values[ 2] = GetClassName(ID->getIdentifier());
+ // Version is always 0.
+ Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
+ Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
+ Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
+ Values[ 6] = EmitIvarList(ID, true);
+ Values[ 7] =
+ EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
+ "__OBJC,__cls_meth,regular,no_dead_strip",
+ Methods);
+ // cache is always NULL.
+ Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
+ Values[ 9] = Protocols;
+ // ivar_layout for metaclass is always NULL.
+ Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ // The class extension is always unused for metaclasses.
+ Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
+ Values);
+
+ std::string Name("\01L_OBJC_METACLASS_");
+ Name += ID->getNameAsCString();
+
+ // Check for a forward reference.
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (GV) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+ GV->setInitializer(Init);
+ } else {
+ GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init, Name);
+ }
+ GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
+ GV->setAlignment(4);
+ CGM.AddUsedGlobal(GV);
+
+ return GV;
+}
+
+llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
+ std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
+
+ // FIXME: Should we look these up somewhere other than the module. Its a bit
+ // silly since we only generate these while processing an implementation, so
+ // exactly one pointer would work if know when we entered/exitted an
+ // implementation block.
+
+ // Check for an existing forward reference.
+ // Previously, metaclass with internal linkage may have been defined.
+ // pass 'true' as 2nd argument so it is returned.
+ if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
+ true)) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward metaclass reference has incorrect type.");
+ return GV;
+ } else {
+ // Generate as an external reference to keep a consistent
+ // module. This will be patched up when we emit the metaclass.
+ return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ Name);
+ }
+}
+
+llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
+ std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
+
+ if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
+ true)) {
+ assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+ "Forward class metadata reference has incorrect type.");
+ return GV;
+ } else {
+ return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ Name);
+ }
+}
+
+/*
+ struct objc_class_ext {
+ uint32_t size;
+ const char *weak_ivar_layout;
+ struct _objc_property_list *properties;
+ };
+*/
+llvm::Constant *
+CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
+ uint64_t Size =
+ CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
+
+ std::vector<llvm::Constant*> Values(3);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values[1] = BuildIvarLayout(ID, false);
+ Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
+ ID, ID->getClassInterface(), ObjCTypes);
+
+ // Return null if no extension bits are used.
+ if (Values[1]->isNullValue() && Values[2]->isNullValue())
+ return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
+
+ llvm::Constant *Init =
+ llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
+ return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
+ Init, "__OBJC,__class_ext,regular,no_dead_strip",
+ 4, true);
+}
+
+/*
+ struct objc_ivar {
+ char *ivar_name;
+ char *ivar_type;
+ int ivar_offset;
+ };
+
+ struct objc_ivar_list {
+ int ivar_count;
+ struct objc_ivar list[count];
+ };
+*/
+llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
+ bool ForClass) {
+ std::vector<llvm::Constant*> Ivars, Ivar(3);
+
+ // When emitting the root class GCC emits ivar entries for the
+ // actual class structure. It is not clear if we need to follow this
+ // behavior; for now lets try and get away with not doing it. If so,
+ // the cleanest solution would be to make up an ObjCInterfaceDecl
+ // for the class.
+ if (ForClass)
+ return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
+
+ ObjCInterfaceDecl *OID =
+ const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
+
+ llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
+ CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
+
+ for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
+ ObjCIvarDecl *IVD = OIvars[i];
+ // Ignore unnamed bit-fields.
+ if (!IVD->getDeclName())
+ continue;
+ Ivar[0] = GetMethodVarName(IVD->getIdentifier());
+ Ivar[1] = GetMethodVarType(IVD);
+ Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
+ ComputeIvarBaseOffset(CGM, OID, IVD));
+ Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
+ }
+
+ // Return null for empty list.
+ if (Ivars.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
+
+ std::vector<llvm::Constant*> Values(2);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
+ Ivars.size());
+ Values[1] = llvm::ConstantArray::get(AT, Ivars);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV;
+ if (ForClass)
+ GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
+ Init, "__OBJC,__class_vars,regular,no_dead_strip",
+ 4, true);
+ else
+ GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
+ Init, "__OBJC,__instance_vars,regular,no_dead_strip",
+ 4, true);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
+}
+
+/*
+ struct objc_method {
+ SEL method_name;
+ char *method_types;
+ void *method;
+ };
+
+ struct objc_method_list {
+ struct objc_method_list *obsolete;
+ int count;
+ struct objc_method methods_list[count];
+ };
+*/
+
+/// GetMethodConstant - Return a struct objc_method constant for the
+/// given method if it has been defined. The result is null if the
+/// method has not been defined. The return value has type MethodPtrTy.
+llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
+ llvm::Function *Fn = GetMethodDefinition(MD);
+ if (!Fn)
+ return 0;
+
+ std::vector<llvm::Constant*> Method(3);
+ Method[0] =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ Method[1] = GetMethodVarType(MD);
+ Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
+ return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
+}
+
+llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods) {
+ // Return null for empty list.
+ if (Methods.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
+
+ std::vector<llvm::Constant*> Values(3);
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
+ Methods.size());
+ Values[2] = llvm::ConstantArray::get(AT, Methods);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ return llvm::ConstantExpr::getBitCast(GV,
+ ObjCTypes.MethodListPtrTy);
+}
+
+llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) {
+ llvm::SmallString<256> Name;
+ GetNameForMethod(OMD, CD, Name);
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *MethodTy =
+ Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
+ llvm::Function *Method =
+ llvm::Function::Create(MethodTy,
+ llvm::GlobalValue::InternalLinkage,
+ Name.str(),
+ &CGM.getModule());
+ MethodDefinitions.insert(std::make_pair(OMD, Method));
+
+ return Method;
+}
+
+llvm::GlobalVariable *
+CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
+ llvm::Constant *Init,
+ const char *Section,
+ unsigned Align,
+ bool AddToUsed) {
+ const llvm::Type *Ty = Init->getType();
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Ty, false,
+ llvm::GlobalValue::InternalLinkage, Init, Name);
+ if (Section)
+ GV->setSection(Section);
+ if (Align)
+ GV->setAlignment(Align);
+ if (AddToUsed)
+ CGM.AddUsedGlobal(GV);
+ return GV;
+}
+
+llvm::Function *CGObjCMac::ModuleInitFunction() {
+ // Abuse this interface function as a place to finalize.
+ FinishModule();
+ return NULL;
+}
+
+llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
+ return ObjCTypes.getGetPropertyFn();
+}
+
+llvm::Constant *CGObjCMac::GetPropertySetFunction() {
+ return ObjCTypes.getSetPropertyFn();
+}
+
+llvm::Constant *CGObjCMac::GetGetStructFunction() {
+ return ObjCTypes.getCopyStructFn();
+}
+llvm::Constant *CGObjCMac::GetSetStructFunction() {
+ return ObjCTypes.getCopyStructFn();
+}
+
+llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
+ return ObjCTypes.getEnumerationMutationFn();
+}
+
+void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
+ return EmitTryOrSynchronizedStmt(CGF, S);
+}
+
+void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S) {
+ return EmitTryOrSynchronizedStmt(CGF, S);
+}
+
+namespace {
+ struct PerformFragileFinally : EHScopeStack::Cleanup {
+ const Stmt &S;
+ llvm::Value *SyncArgSlot;
+ llvm::Value *CallTryExitVar;
+ llvm::Value *ExceptionData;
+ ObjCTypesHelper &ObjCTypes;
+ PerformFragileFinally(const Stmt *S,
+ llvm::Value *SyncArgSlot,
+ llvm::Value *CallTryExitVar,
+ llvm::Value *ExceptionData,
+ ObjCTypesHelper *ObjCTypes)
+ : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
+ ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // Check whether we need to call objc_exception_try_exit.
+ // In optimized code, this branch will always be folded.
+ llvm::BasicBlock *FinallyCallExit =
+ CGF.createBasicBlock("finally.call_exit");
+ llvm::BasicBlock *FinallyNoCallExit =
+ CGF.createBasicBlock("finally.no_call_exit");
+ CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
+ FinallyCallExit, FinallyNoCallExit);
+
+ CGF.EmitBlock(FinallyCallExit);
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
+ ->setDoesNotThrow();
+
+ CGF.EmitBlock(FinallyNoCallExit);
+
+ if (isa<ObjCAtTryStmt>(S)) {
+ if (const ObjCAtFinallyStmt* FinallyStmt =
+ cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
+ // Save the current cleanup destination in case there's
+ // control flow inside the finally statement.
+ llvm::Value *CurCleanupDest =
+ CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
+
+ CGF.EmitStmt(FinallyStmt->getFinallyBody());
+
+ if (CGF.HaveInsertPoint()) {
+ CGF.Builder.CreateStore(CurCleanupDest,
+ CGF.getNormalCleanupDestSlot());
+ } else {
+ // Currently, the end of the cleanup must always exist.
+ CGF.EnsureInsertPoint();
+ }
+ }
+ } else {
+ // Emit objc_sync_exit(expr); as finally's sole statement for
+ // @synchronized.
+ llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
+ CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
+ ->setDoesNotThrow();
+ }
+ }
+ };
+
+ class FragileHazards {
+ CodeGenFunction &CGF;
+ llvm::SmallVector<llvm::Value*, 20> Locals;
+ llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
+
+ llvm::InlineAsm *ReadHazard;
+ llvm::InlineAsm *WriteHazard;
+
+ llvm::FunctionType *GetAsmFnType();
+
+ void collectLocals();
+ void emitReadHazard(CGBuilderTy &Builder);
+
+ public:
+ FragileHazards(CodeGenFunction &CGF);
+
+ void emitWriteHazard();
+ void emitHazardsInNewBlocks();
+ };
+}
+
+/// Create the fragile-ABI read and write hazards based on the current
+/// state of the function, which is presumed to be immediately prior
+/// to a @try block. These hazards are used to maintain correct
+/// semantics in the face of optimization and the fragile ABI's
+/// cavalier use of setjmp/longjmp.
+FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
+ collectLocals();
+
+ if (Locals.empty()) return;
+
+ // Collect all the blocks in the function.
+ for (llvm::Function::iterator
+ I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
+ BlocksBeforeTry.insert(&*I);
+
+ llvm::FunctionType *AsmFnTy = GetAsmFnType();
+
+ // Create a read hazard for the allocas. This inhibits dead-store
+ // optimizations and forces the values to memory. This hazard is
+ // inserted before any 'throwing' calls in the protected scope to
+ // reflect the possibility that the variables might be read from the
+ // catch block if the call throws.
+ {
+ std::string Constraint;
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
+ if (I) Constraint += ',';
+ Constraint += "*m";
+ }
+
+ ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
+ }
+
+ // Create a write hazard for the allocas. This inhibits folding
+ // loads across the hazard. This hazard is inserted at the
+ // beginning of the catch path to reflect the possibility that the
+ // variables might have been written within the protected scope.
+ {
+ std::string Constraint;
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
+ if (I) Constraint += ',';
+ Constraint += "=*m";
+ }
+
+ WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
+ }
+}
+
+/// Emit a write hazard at the current location.
+void FragileHazards::emitWriteHazard() {
+ if (Locals.empty()) return;
+
+ CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
+ ->setDoesNotThrow();
+}
+
+void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
+ assert(!Locals.empty());
+ Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
+ ->setDoesNotThrow();
+}
+
+/// Emit read hazards in all the protected blocks, i.e. all the blocks
+/// which have been inserted since the beginning of the try.
+void FragileHazards::emitHazardsInNewBlocks() {
+ if (Locals.empty()) return;
+
+ CGBuilderTy Builder(CGF.getLLVMContext());
+
+ // Iterate through all blocks, skipping those prior to the try.
+ for (llvm::Function::iterator
+ FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
+ llvm::BasicBlock &BB = *FI;
+ if (BlocksBeforeTry.count(&BB)) continue;
+
+ // Walk through all the calls in the block.
+ for (llvm::BasicBlock::iterator
+ BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
+ llvm::Instruction &I = *BI;
+
+ // Ignore instructions that aren't non-intrinsic calls.
+ // These are the only calls that can possibly call longjmp.
+ if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
+ if (isa<llvm::IntrinsicInst>(I))
+ continue;
+
+ // Ignore call sites marked nounwind. This may be questionable,
+ // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
+ llvm::CallSite CS(&I);
+ if (CS.doesNotThrow()) continue;
+
+ // Insert a read hazard before the call. This will ensure that
+ // any writes to the locals are performed before making the
+ // call. If the call throws, then this is sufficient to
+ // guarantee correctness as long as it doesn't also write to any
+ // locals.
+ Builder.SetInsertPoint(&BB, BI);
+ emitReadHazard(Builder);
+ }
+ }
+}
+
+static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
+ if (V) S.insert(V);
+}
+
+void FragileHazards::collectLocals() {
+ // Compute a set of allocas to ignore.
+ llvm::DenseSet<llvm::Value*> AllocasToIgnore;
+ addIfPresent(AllocasToIgnore, CGF.ReturnValue);
+ addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
+ addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
+
+ // Collect all the allocas currently in the function. This is
+ // probably way too aggressive.
+ llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
+ for (llvm::BasicBlock::iterator
+ I = Entry.begin(), E = Entry.end(); I != E; ++I)
+ if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
+ Locals.push_back(&*I);
+}
+
+llvm::FunctionType *FragileHazards::GetAsmFnType() {
+ std::vector<const llvm::Type *> Tys(Locals.size());
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I)
+ Tys[I] = Locals[I]->getType();
+ return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
+}
+
+/*
+
+ Objective-C setjmp-longjmp (sjlj) Exception Handling
+ --
+
+ A catch buffer is a setjmp buffer plus:
+ - a pointer to the exception that was caught
+ - a pointer to the previous exception data buffer
+ - two pointers of reserved storage
+ Therefore catch buffers form a stack, with a pointer to the top
+ of the stack kept in thread-local storage.
+
+ objc_exception_try_enter pushes a catch buffer onto the EH stack.
+ objc_exception_try_exit pops the given catch buffer, which is
+ required to be the top of the EH stack.
+ objc_exception_throw pops the top of the EH stack, writes the
+ thrown exception into the appropriate field, and longjmps
+ to the setjmp buffer. It crashes the process (with a printf
+ and an abort()) if there are no catch buffers on the stack.
+ objc_exception_extract just reads the exception pointer out of the
+ catch buffer.
+
+ There's no reason an implementation couldn't use a light-weight
+ setjmp here --- something like __builtin_setjmp, but API-compatible
+ with the heavyweight setjmp. This will be more important if we ever
+ want to implement correct ObjC/C++ exception interactions for the
+ fragile ABI.
+
+ Note that for this use of setjmp/longjmp to be correct, we may need
+ to mark some local variables volatile: if a non-volatile local
+ variable is modified between the setjmp and the longjmp, it has
+ indeterminate value. For the purposes of LLVM IR, it may be
+ sufficient to make loads and stores within the @try (to variables
+ declared outside the @try) volatile. This is necessary for
+ optimized correctness, but is not currently being done; this is
+ being tracked as rdar://problem/8160285
+
+ The basic framework for a @try-catch-finally is as follows:
+ {
+ objc_exception_data d;
+ id _rethrow = null;
+ bool _call_try_exit = true;
+
+ objc_exception_try_enter(&d);
+ if (!setjmp(d.jmp_buf)) {
+ ... try body ...
+ } else {
+ // exception path
+ id _caught = objc_exception_extract(&d);
+
+ // enter new try scope for handlers
+ if (!setjmp(d.jmp_buf)) {
+ ... match exception and execute catch blocks ...
+
+ // fell off end, rethrow.
+ _rethrow = _caught;
+ ... jump-through-finally to finally_rethrow ...
+ } else {
+ // exception in catch block
+ _rethrow = objc_exception_extract(&d);
+ _call_try_exit = false;
+ ... jump-through-finally to finally_rethrow ...
+ }
+ }
+ ... jump-through-finally to finally_end ...
+
+ finally:
+ if (_call_try_exit)
+ objc_exception_try_exit(&d);
+
+ ... finally block ....
+ ... dispatch to finally destination ...
+
+ finally_rethrow:
+ objc_exception_throw(_rethrow);
+
+ finally_end:
+ }
+
+ This framework differs slightly from the one gcc uses, in that gcc
+ uses _rethrow to determine if objc_exception_try_exit should be called
+ and if the object should be rethrown. This breaks in the face of
+ throwing nil and introduces unnecessary branches.
+
+ We specialize this framework for a few particular circumstances:
+
+ - If there are no catch blocks, then we avoid emitting the second
+ exception handling context.
+
+ - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
+ e)) we avoid emitting the code to rethrow an uncaught exception.
+
+ - FIXME: If there is no @finally block we can do a few more
+ simplifications.
+
+ Rethrows and Jumps-Through-Finally
+ --
+
+ '@throw;' is supported by pushing the currently-caught exception
+ onto ObjCEHStack while the @catch blocks are emitted.
+
+ Branches through the @finally block are handled with an ordinary
+ normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
+ exceptions are not compatible with C++ exceptions, and this is
+ hardly the only place where this will go wrong.
+
+ @synchronized(expr) { stmt; } is emitted as if it were:
+ id synch_value = expr;
+ objc_sync_enter(synch_value);
+ @try { stmt; } @finally { objc_sync_exit(synch_value); }
+*/
+
+void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const Stmt &S) {
+ bool isTry = isa<ObjCAtTryStmt>(S);
+
+ // A destination for the fall-through edges of the catch handlers to
+ // jump to.
+ CodeGenFunction::JumpDest FinallyEnd =
+ CGF.getJumpDestInCurrentScope("finally.end");
+
+ // A destination for the rethrow edge of the catch handlers to jump
+ // to.
+ CodeGenFunction::JumpDest FinallyRethrow =
+ CGF.getJumpDestInCurrentScope("finally.rethrow");
+
+ // For @synchronized, call objc_sync_enter(sync.expr). The
+ // evaluation of the expression must occur before we enter the
+ // @synchronized. We can't avoid a temp here because we need the
+ // value to be preserved. If the backend ever does liveness
+ // correctly after setjmp, this will be unnecessary.
+ llvm::Value *SyncArgSlot = 0;
+ if (!isTry) {
+ llvm::Value *SyncArg =
+ CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
+ SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
+ CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
+ ->setDoesNotThrow();
+
+ SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
+ CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
+ }
+
+ // Allocate memory for the setjmp buffer. This needs to be kept
+ // live throughout the try and catch blocks.
+ llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
+ "exceptiondata.ptr");
+
+ // Create the fragile hazards. Note that this will not capture any
+ // of the allocas required for exception processing, but will
+ // capture the current basic block (which extends all the way to the
+ // setjmp call) as "before the @try".
+ FragileHazards Hazards(CGF);
+
+ // Create a flag indicating whether the cleanup needs to call
+ // objc_exception_try_exit. This is true except when
+ // - no catches match and we're branching through the cleanup
+ // just to rethrow the exception, or
+ // - a catch matched and we're falling out of the catch handler.
+ // The setjmp-safety rule here is that we should always store to this
+ // variable in a place that dominates the branch through the cleanup
+ // without passing through any setjmps.
+ llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
+ "_call_try_exit");
+
+ // A slot containing the exception to rethrow. Only needed when we
+ // have both a @catch and a @finally.
+ llvm::Value *PropagatingExnVar = 0;
+
+ // Push a normal cleanup to leave the try scope.
+ CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
+ SyncArgSlot,
+ CallTryExitVar,
+ ExceptionData,
+ &ObjCTypes);
+
+ // Enter a try block:
+ // - Call objc_exception_try_enter to push ExceptionData on top of
+ // the EH stack.
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
+ ->setDoesNotThrow();
+
+ // - Call setjmp on the exception data buffer.
+ llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
+ llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
+ llvm::Value *SetJmpBuffer =
+ CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
+ llvm::CallInst *SetJmpResult =
+ CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
+ SetJmpResult->setDoesNotThrow();
+
+ // If setjmp returned 0, enter the protected block; otherwise,
+ // branch to the handler.
+ llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
+ llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
+ llvm::Value *DidCatch =
+ CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
+ CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
+
+ // Emit the protected block.
+ CGF.EmitBlock(TryBlock);
+ CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
+ CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
+ : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
+
+ CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
+
+ // Emit the exception handler block.
+ CGF.EmitBlock(TryHandler);
+
+ // Don't optimize loads of the in-scope locals across this point.
+ Hazards.emitWriteHazard();
+
+ // For a @synchronized (or a @try with no catches), just branch
+ // through the cleanup to the rethrow block.
+ if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
+ // Tell the cleanup not to re-pop the exit.
+ CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
+ CGF.EmitBranchThroughCleanup(FinallyRethrow);
+
+ // Otherwise, we have to match against the caught exceptions.
+ } else {
+ // Retrieve the exception object. We may emit multiple blocks but
+ // nothing can cross this so the value is already in SSA form.
+ llvm::CallInst *Caught =
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
+ ExceptionData, "caught");
+ Caught->setDoesNotThrow();
+
+ // Push the exception to rethrow onto the EH value stack for the
+ // benefit of any @throws in the handlers.
+ CGF.ObjCEHValueStack.push_back(Caught);
+
+ const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
+
+ bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
+
+ llvm::BasicBlock *CatchBlock = 0;
+ llvm::BasicBlock *CatchHandler = 0;
+ if (HasFinally) {
+ // Save the currently-propagating exception before
+ // objc_exception_try_enter clears the exception slot.
+ PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
+ "propagating_exception");
+ CGF.Builder.CreateStore(Caught, PropagatingExnVar);
+
+ // Enter a new exception try block (in case a @catch block
+ // throws an exception).
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
+ ->setDoesNotThrow();
+
+ llvm::CallInst *SetJmpResult =
+ CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
+ "setjmp.result");
+ SetJmpResult->setDoesNotThrow();
+
+ llvm::Value *Threw =
+ CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
+
+ CatchBlock = CGF.createBasicBlock("catch");
+ CatchHandler = CGF.createBasicBlock("catch_for_catch");
+ CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
+
+ CGF.EmitBlock(CatchBlock);
+ }
+
+ CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
+
+ // Handle catch list. As a special case we check if everything is
+ // matched and avoid generating code for falling off the end if
+ // so.
+ bool AllMatched = false;
+ for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
+ const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
+
+ const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
+ const ObjCObjectPointerType *OPT = 0;
+
+ // catch(...) always matches.
+ if (!CatchParam) {
+ AllMatched = true;
+ } else {
+ OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
+
+ // catch(id e) always matches under this ABI, since only
+ // ObjC exceptions end up here in the first place.
+ // FIXME: For the time being we also match id<X>; this should
+ // be rejected by Sema instead.
+ if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
+ AllMatched = true;
+ }
+
+ // If this is a catch-all, we don't need to test anything.
+ if (AllMatched) {
+ CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
+
+ if (CatchParam) {
+ CGF.EmitAutoVarDecl(*CatchParam);
+ assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
+
+ // These types work out because ConvertType(id) == i8*.
+ CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
+ }
+
+ CGF.EmitStmt(CatchStmt->getCatchBody());
+
+ // The scope of the catch variable ends right here.
+ CatchVarCleanups.ForceCleanup();
+
+ CGF.EmitBranchThroughCleanup(FinallyEnd);
+ break;
+ }
+
+ assert(OPT && "Unexpected non-object pointer type in @catch");
+ const ObjCObjectType *ObjTy = OPT->getObjectType();
+
+ // FIXME: @catch (Class c) ?
+ ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
+ assert(IDecl && "Catch parameter must have Objective-C type!");
+
+ // Check if the @catch block matches the exception object.
+ llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
+
+ llvm::CallInst *Match =
+ CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
+ Class, Caught, "match");
+ Match->setDoesNotThrow();
+
+ llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
+ llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
+
+ CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
+ MatchedBlock, NextCatchBlock);
+
+ // Emit the @catch block.
+ CGF.EmitBlock(MatchedBlock);
+
+ // Collect any cleanups for the catch variable. The scope lasts until
+ // the end of the catch body.
+ CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
+
+ CGF.EmitAutoVarDecl(*CatchParam);
+ assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
+
+ // Initialize the catch variable.
+ llvm::Value *Tmp =
+ CGF.Builder.CreateBitCast(Caught,
+ CGF.ConvertType(CatchParam->getType()),
+ "tmp");
+ CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
+
+ CGF.EmitStmt(CatchStmt->getCatchBody());
+
+ // We're done with the catch variable.
+ CatchVarCleanups.ForceCleanup();
+
+ CGF.EmitBranchThroughCleanup(FinallyEnd);
+
+ CGF.EmitBlock(NextCatchBlock);
+ }
+
+ CGF.ObjCEHValueStack.pop_back();
+
+ // If nothing wanted anything to do with the caught exception,
+ // kill the extract call.
+ if (Caught->use_empty())
+ Caught->eraseFromParent();
+
+ if (!AllMatched)
+ CGF.EmitBranchThroughCleanup(FinallyRethrow);
+
+ if (HasFinally) {
+ // Emit the exception handler for the @catch blocks.
+ CGF.EmitBlock(CatchHandler);
+
+ // In theory we might now need a write hazard, but actually it's
+ // unnecessary because there's no local-accessing code between
+ // the try's write hazard and here.
+ //Hazards.emitWriteHazard();
+
+ // Extract the new exception and save it to the
+ // propagating-exception slot.
+ assert(PropagatingExnVar);
+ llvm::CallInst *NewCaught =
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
+ ExceptionData, "caught");
+ NewCaught->setDoesNotThrow();
+ CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
+
+ // Don't pop the catch handler; the throw already did.
+ CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
+ CGF.EmitBranchThroughCleanup(FinallyRethrow);
+ }
+ }
+
+ // Insert read hazards as required in the new blocks.
+ Hazards.emitHazardsInNewBlocks();
+
+ // Pop the cleanup.
+ CGF.Builder.restoreIP(TryFallthroughIP);
+ if (CGF.HaveInsertPoint())
+ CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
+ CGF.PopCleanupBlock();
+ CGF.EmitBlock(FinallyEnd.getBlock(), true);
+
+ // Emit the rethrow block.
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+ CGF.EmitBlock(FinallyRethrow.getBlock(), true);
+ if (CGF.HaveInsertPoint()) {
+ // If we have a propagating-exception variable, check it.
+ llvm::Value *PropagatingExn;
+ if (PropagatingExnVar) {
+ PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
+
+ // Otherwise, just look in the buffer for the exception to throw.
+ } else {
+ llvm::CallInst *Caught =
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
+ ExceptionData);
+ Caught->setDoesNotThrow();
+ PropagatingExn = Caught;
+ }
+
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
+ ->setDoesNotThrow();
+ CGF.Builder.CreateUnreachable();
+ }
+
+ CGF.Builder.restoreIP(SavedIP);
+}
+
+void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S) {
+ llvm::Value *ExceptionAsObject;
+
+ if (const Expr *ThrowExpr = S.getThrowExpr()) {
+ llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ ExceptionAsObject =
+ CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
+ } else {
+ assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
+ "Unexpected rethrow outside @catch block.");
+ ExceptionAsObject = CGF.ObjCEHValueStack.back();
+ }
+
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
+ ->setDoesNotReturn();
+ CGF.Builder.CreateUnreachable();
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ CGF.Builder.ClearInsertionPoint();
+}
+
+/// EmitObjCWeakRead - Code gen for loading value of a __weak
+/// object: objc_read_weak (id *src)
+///
+llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj) {
+ const llvm::Type* DestTy =
+ cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
+ AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
+ ObjCTypes.PtrObjectPtrTy);
+ llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
+ AddrWeakObj, "weakread");
+ read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
+ return read_weak;
+}
+
+/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
+/// objc_assign_weak (id src, id *dst)
+///
+void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
+ src, dst, "weakassign");
+ return;
+}
+
+/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
+/// objc_assign_global (id src, id *dst)
+///
+void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ if (!threadlocal)
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
+ src, dst, "globalassign");
+ else
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
+ src, dst, "threadlocalassign");
+ return;
+}
+
+/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
+/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
+///
+void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst,
+ llvm::Value *ivarOffset) {
+ assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
+ src, dst, ivarOffset);
+ return;
+}
+
+/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
+/// objc_assign_strongCast (id src, id *dst)
+///
+void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
+ src, dst, "weakassign");
+ return;
+}
+
+void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *DestPtr,
+ llvm::Value *SrcPtr,
+ llvm::Value *size) {
+ SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
+ DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
+ CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
+ DestPtr, SrcPtr, size);
+ return;
+}
+
+/// EmitObjCValueForIvar - Code Gen for ivar reference.
+///
+LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers) {
+ const ObjCInterfaceDecl *ID =
+ ObjectTy->getAs<ObjCObjectType>()->getInterface();
+ return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+ EmitIvarOffset(CGF, ID, Ivar));
+}
+
+llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) {
+ uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
+ return llvm::ConstantInt::get(
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy),
+ Offset);
+}
+
+/* *** Private Interface *** */
+
+/// EmitImageInfo - Emit the image info marker used to encode some module
+/// level information.
+///
+/// See: <rdr://4810609&4810587&4810587>
+/// struct IMAGE_INFO {
+/// unsigned version;
+/// unsigned flags;
+/// };
+enum ImageInfoFlags {
+ eImageInfo_FixAndContinue = (1 << 0),
+ eImageInfo_GarbageCollected = (1 << 1),
+ eImageInfo_GCOnly = (1 << 2),
+ eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
+
+ // A flag indicating that the module has no instances of a @synthesize of a
+ // superclass variable. <rdar://problem/6803242>
+ eImageInfo_CorrectedSynthesize = (1 << 4)
+};
+
+void CGObjCCommonMac::EmitImageInfo() {
+ unsigned version = 0; // Version is unused?
+ unsigned flags = 0;
+
+ // FIXME: Fix and continue?
+ if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
+ flags |= eImageInfo_GarbageCollected;
+ if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
+ flags |= eImageInfo_GCOnly;
+
+ // We never allow @synthesize of a superclass property.
+ flags |= eImageInfo_CorrectedSynthesize;
+
+ const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
+
+ // Emitted as int[2];
+ llvm::Constant *values[2] = {
+ llvm::ConstantInt::get(Int32Ty, version),
+ llvm::ConstantInt::get(Int32Ty, flags)
+ };
+ llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
+
+ const char *Section;
+ if (ObjCABI == 1)
+ Section = "__OBJC, __image_info,regular";
+ else
+ Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
+ llvm::ConstantArray::get(AT, values, 2),
+ Section,
+ 0,
+ true);
+ GV->setConstant(true);
+}
+
+
+// struct objc_module {
+// unsigned long version;
+// unsigned long size;
+// const char *name;
+// Symtab symtab;
+// };
+
+// FIXME: Get from somewhere
+static const int ModuleVersion = 7;
+
+void CGObjCMac::EmitModuleInfo() {
+ uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
+
+ std::vector<llvm::Constant*> Values(4);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
+ // This used to be the filename, now it is unused. <rdr://4327263>
+ Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
+ Values[3] = EmitModuleSymbols();
+ CreateMetadataVar("\01L_OBJC_MODULES",
+ llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
+ "__OBJC,__module_info,regular,no_dead_strip",
+ 4, true);
+}
+
+llvm::Constant *CGObjCMac::EmitModuleSymbols() {
+ unsigned NumClasses = DefinedClasses.size();
+ unsigned NumCategories = DefinedCategories.size();
+
+ // Return null if no symbols were defined.
+ if (!NumClasses && !NumCategories)
+ return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
+
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
+ Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
+ Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
+ Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
+
+ // The runtime expects exactly the list of defined classes followed
+ // by the list of defined categories, in a single array.
+ std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
+ for (unsigned i=0; i<NumClasses; i++)
+ Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
+ ObjCTypes.Int8PtrTy);
+ for (unsigned i=0; i<NumCategories; i++)
+ Symbols[NumClasses + i] =
+ llvm::ConstantExpr::getBitCast(DefinedCategories[i],
+ ObjCTypes.Int8PtrTy);
+
+ Values[4] =
+ llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
+ NumClasses + NumCategories),
+ Symbols);
+
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
+ "__OBJC,__symbols,regular,no_dead_strip",
+ 4, true);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
+}
+
+llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ LazySymbols.insert(ID->getIdentifier());
+
+ llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
+
+ if (!Entry) {
+ llvm::Constant *Casted =
+ llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
+ ObjCTypes.ClassPtrTy);
+ Entry =
+ CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
+ "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
+ 4, true);
+ }
+
+ return Builder.CreateLoad(Entry, "tmp");
+}
+
+llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
+ bool lvalue) {
+ llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
+
+ if (!Entry) {
+ llvm::Constant *Casted =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
+ ObjCTypes.SelectorPtrTy);
+ Entry =
+ CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
+ "__OBJC,__message_refs,literal_pointers,no_dead_strip",
+ 4, true);
+ }
+
+ if (lvalue)
+ return Entry;
+ return Builder.CreateLoad(Entry, "tmp");
+}
+
+llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
+ llvm::GlobalVariable *&Entry = ClassNames[Ident];
+
+ if (!Entry)
+ Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
+ llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
+ I = MethodDefinitions.find(MD);
+ if (I != MethodDefinitions.end())
+ return I->second;
+
+ if (MD->hasBody() && MD->getPCHLevel() > 0) {
+ // MD isn't emitted yet because it comes from PCH.
+ CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
+ assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
+ return MethodDefinitions[MD];
+ }
+
+ return NULL;
+}
+
+/// GetIvarLayoutName - Returns a unique constant for the given
+/// ivar layout bitmap.
+llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
+ const ObjCCommonTypesHelper &ObjCTypes) {
+ return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+}
+
+void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
+ unsigned int BytePos,
+ bool ForStrongLayout,
+ bool &HasUnion) {
+ const RecordDecl *RD = RT->getDecl();
+ // FIXME - Use iterator.
+ llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
+ const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
+ const llvm::StructLayout *RecLayout =
+ CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
+
+ BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
+ ForStrongLayout, HasUnion);
+}
+
+void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
+ const llvm::StructLayout *Layout,
+ const RecordDecl *RD,
+ const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
+ unsigned int BytePos, bool ForStrongLayout,
+ bool &HasUnion) {
+ bool IsUnion = (RD && RD->isUnion());
+ uint64_t MaxUnionIvarSize = 0;
+ uint64_t MaxSkippedUnionIvarSize = 0;
+ FieldDecl *MaxField = 0;
+ FieldDecl *MaxSkippedField = 0;
+ FieldDecl *LastFieldBitfieldOrUnnamed = 0;
+ uint64_t MaxFieldOffset = 0;
+ uint64_t MaxSkippedFieldOffset = 0;
+ uint64_t LastBitfieldOrUnnamedOffset = 0;
+
+ if (RecFields.empty())
+ return;
+ unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
+ unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
+
+ for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+ FieldDecl *Field = RecFields[i];
+ uint64_t FieldOffset;
+ if (RD) {
+ // Note that 'i' here is actually the field index inside RD of Field,
+ // although this dependency is hidden.
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ FieldOffset = RL.getFieldOffset(i) / 8;
+ } else
+ FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
+
+ // Skip over unnamed or bitfields
+ if (!Field->getIdentifier() || Field->isBitField()) {
+ LastFieldBitfieldOrUnnamed = Field;
+ LastBitfieldOrUnnamedOffset = FieldOffset;
+ continue;
+ }
+
+ LastFieldBitfieldOrUnnamed = 0;
+ QualType FQT = Field->getType();
+ if (FQT->isRecordType() || FQT->isUnionType()) {
+ if (FQT->isUnionType())
+ HasUnion = true;
+
+ BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
+ BytePos + FieldOffset,
+ ForStrongLayout, HasUnion);
+ continue;
+ }
+
+ if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
+ const ConstantArrayType *CArray =
+ dyn_cast_or_null<ConstantArrayType>(Array);
+ uint64_t ElCount = CArray->getSize().getZExtValue();
+ assert(CArray && "only array with known element size is supported");
+ FQT = CArray->getElementType();
+ while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
+ const ConstantArrayType *CArray =
+ dyn_cast_or_null<ConstantArrayType>(Array);
+ ElCount *= CArray->getSize().getZExtValue();
+ FQT = CArray->getElementType();
+ }
+
+ assert(!FQT->isUnionType() &&
+ "layout for array of unions not supported");
+ if (FQT->isRecordType() && ElCount) {
+ int OldIndex = IvarsInfo.size() - 1;
+ int OldSkIndex = SkipIvars.size() -1;
+
+ const RecordType *RT = FQT->getAs<RecordType>();
+ BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
+ ForStrongLayout, HasUnion);
+
+ // Replicate layout information for each array element. Note that
+ // one element is already done.
+ uint64_t ElIx = 1;
+ for (int FirstIndex = IvarsInfo.size() - 1,
+ FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
+ uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
+ for (int i = OldIndex+1; i <= FirstIndex; ++i)
+ IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
+ IvarsInfo[i].ivar_size));
+ for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
+ SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
+ SkipIvars[i].ivar_size));
+ }
+ continue;
+ }
+ }
+ // At this point, we are done with Record/Union and array there of.
+ // For other arrays we are down to its element type.
+ Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
+
+ unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
+ if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
+ || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
+ if (IsUnion) {
+ uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
+ if (UnionIvarSize > MaxUnionIvarSize) {
+ MaxUnionIvarSize = UnionIvarSize;
+ MaxField = Field;
+ MaxFieldOffset = FieldOffset;
+ }
+ } else {
+ IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
+ FieldSize / WordSizeInBits));
+ }
+ } else if ((ForStrongLayout &&
+ (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
+ || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
+ if (IsUnion) {
+ // FIXME: Why the asymmetry? We divide by word size in bits on other
+ // side.
+ uint64_t UnionIvarSize = FieldSize;
+ if (UnionIvarSize > MaxSkippedUnionIvarSize) {
+ MaxSkippedUnionIvarSize = UnionIvarSize;
+ MaxSkippedField = Field;
+ MaxSkippedFieldOffset = FieldOffset;
+ }
+ } else {
+ // FIXME: Why the asymmetry, we divide by byte size in bits here?
+ SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
+ FieldSize / ByteSizeInBits));
+ }
+ }
+ }
+
+ if (LastFieldBitfieldOrUnnamed) {
+ if (LastFieldBitfieldOrUnnamed->isBitField()) {
+ // Last field was a bitfield. Must update skip info.
+ Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
+ uint64_t BitFieldSize =
+ BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ GC_IVAR skivar;
+ skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
+ skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
+ + ((BitFieldSize % ByteSizeInBits) != 0);
+ SkipIvars.push_back(skivar);
+ } else {
+ assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
+ // Last field was unnamed. Must update skip info.
+ unsigned FieldSize
+ = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
+ SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
+ FieldSize / ByteSizeInBits));
+ }
+ }
+
+ if (MaxField)
+ IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
+ MaxUnionIvarSize));
+ if (MaxSkippedField)
+ SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
+ MaxSkippedUnionIvarSize));
+}
+
+/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
+/// the computations and returning the layout bitmap (for ivar or blocks) in
+/// the given argument BitMap string container. Routine reads
+/// two containers, IvarsInfo and SkipIvars which are assumed to be
+/// filled already by the caller.
+llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
+ unsigned int WordsToScan, WordsToSkip;
+ const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+
+ // Build the string of skip/scan nibbles
+ llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
+ unsigned int WordSize =
+ CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
+ if (IvarsInfo[0].ivar_bytepos == 0) {
+ WordsToSkip = 0;
+ WordsToScan = IvarsInfo[0].ivar_size;
+ } else {
+ WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
+ WordsToScan = IvarsInfo[0].ivar_size;
+ }
+ for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
+ unsigned int TailPrevGCObjC =
+ IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
+ if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
+ // consecutive 'scanned' object pointers.
+ WordsToScan += IvarsInfo[i].ivar_size;
+ } else {
+ // Skip over 'gc'able object pointer which lay over each other.
+ if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
+ continue;
+ // Must skip over 1 or more words. We save current skip/scan values
+ // and start a new pair.
+ SKIP_SCAN SkScan;
+ SkScan.skip = WordsToSkip;
+ SkScan.scan = WordsToScan;
+ SkipScanIvars.push_back(SkScan);
+
+ // Skip the hole.
+ SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
+ SkScan.scan = 0;
+ SkipScanIvars.push_back(SkScan);
+ WordsToSkip = 0;
+ WordsToScan = IvarsInfo[i].ivar_size;
+ }
+ }
+ if (WordsToScan > 0) {
+ SKIP_SCAN SkScan;
+ SkScan.skip = WordsToSkip;
+ SkScan.scan = WordsToScan;
+ SkipScanIvars.push_back(SkScan);
+ }
+
+ if (!SkipIvars.empty()) {
+ unsigned int LastIndex = SkipIvars.size()-1;
+ int LastByteSkipped =
+ SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
+ LastIndex = IvarsInfo.size()-1;
+ int LastByteScanned =
+ IvarsInfo[LastIndex].ivar_bytepos +
+ IvarsInfo[LastIndex].ivar_size * WordSize;
+ // Compute number of bytes to skip at the tail end of the last ivar scanned.
+ if (LastByteSkipped > LastByteScanned) {
+ unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
+ SKIP_SCAN SkScan;
+ SkScan.skip = TotalWords - (LastByteScanned/WordSize);
+ SkScan.scan = 0;
+ SkipScanIvars.push_back(SkScan);
+ }
+ }
+ // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
+ // as 0xMN.
+ int SkipScan = SkipScanIvars.size()-1;
+ for (int i = 0; i <= SkipScan; i++) {
+ if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
+ && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
+ // 0xM0 followed by 0x0N detected.
+ SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
+ for (int j = i+1; j < SkipScan; j++)
+ SkipScanIvars[j] = SkipScanIvars[j+1];
+ --SkipScan;
+ }
+ }
+
+ // Generate the string.
+ for (int i = 0; i <= SkipScan; i++) {
+ unsigned char byte;
+ unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
+ unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
+ unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
+ unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
+
+ // first skip big.
+ for (unsigned int ix = 0; ix < skip_big; ix++)
+ BitMap += (unsigned char)(0xf0);
+
+ // next (skip small, scan)
+ if (skip_small) {
+ byte = skip_small << 4;
+ if (scan_big > 0) {
+ byte |= 0xf;
+ --scan_big;
+ } else if (scan_small) {
+ byte |= scan_small;
+ scan_small = 0;
+ }
+ BitMap += byte;
+ }
+ // next scan big
+ for (unsigned int ix = 0; ix < scan_big; ix++)
+ BitMap += (unsigned char)(0x0f);
+ // last scan small
+ if (scan_small) {
+ byte = scan_small;
+ BitMap += byte;
+ }
+ }
+ // null terminate string.
+ unsigned char zero = 0;
+ BitMap += zero;
+
+ llvm::GlobalVariable * Entry =
+ CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
+ llvm::ConstantArray::get(VMContext, BitMap.c_str()),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+/// BuildIvarLayout - Builds ivar layout bitmap for the class
+/// implementation for the __strong or __weak case.
+/// The layout map displays which words in ivar list must be skipped
+/// and which must be scanned by GC (see below). String is built of bytes.
+/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
+/// of words to skip and right nibble is count of words to scan. So, each
+/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
+/// represented by a 0x00 byte which also ends the string.
+/// 1. when ForStrongLayout is true, following ivars are scanned:
+/// - id, Class
+/// - object *
+/// - __strong anything
+///
+/// 2. When ForStrongLayout is false, following ivars are scanned:
+/// - __weak anything
+///
+llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
+ const ObjCImplementationDecl *OMD,
+ bool ForStrongLayout) {
+ bool hasUnion = false;
+
+ const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+ return llvm::Constant::getNullValue(PtrTy);
+
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ const ObjCInterfaceDecl *OI = OMD->getClassInterface();
+ CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
+
+ llvm::SmallVector<FieldDecl*, 32> RecFields;
+ for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
+ RecFields.push_back(cast<FieldDecl>(Ivars[k]));
+
+ if (RecFields.empty())
+ return llvm::Constant::getNullValue(PtrTy);
+
+ SkipIvars.clear();
+ IvarsInfo.clear();
+
+ BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
+ if (IvarsInfo.empty())
+ return llvm::Constant::getNullValue(PtrTy);
+ // Sort on byte position in case we encounterred a union nested in
+ // the ivar list.
+ if (hasUnion && !IvarsInfo.empty())
+ std::sort(IvarsInfo.begin(), IvarsInfo.end());
+ if (hasUnion && !SkipIvars.empty())
+ std::sort(SkipIvars.begin(), SkipIvars.end());
+
+ std::string BitMap;
+ llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
+
+ if (CGM.getLangOptions().ObjCGCBitmapPrint) {
+ printf("\n%s ivar layout for class '%s': ",
+ ForStrongLayout ? "strong" : "weak",
+ OMD->getClassInterface()->getName().data());
+ const unsigned char *s = (unsigned char*)BitMap.c_str();
+ for (unsigned i = 0; i < BitMap.size(); i++)
+ if (!(s[i] & 0xf0))
+ printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
+ else
+ printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
+ printf("\n");
+ }
+ return C;
+}
+
+llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
+ llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
+
+ // FIXME: Avoid std::string copying.
+ if (!Entry)
+ Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
+ llvm::ConstantArray::get(VMContext, Sel.getAsString()),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+// FIXME: Merge into a single cstring creation function.
+llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
+ return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
+}
+
+llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
+
+ llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
+
+ if (!Entry)
+ Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
+ llvm::ConstantArray::get(VMContext, TypeStr),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
+ TypeStr);
+
+ llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
+
+ if (!Entry)
+ Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
+ llvm::ConstantArray::get(VMContext, TypeStr),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+// FIXME: Merge into a single cstring creation function.
+llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
+ llvm::GlobalVariable *&Entry = PropertyNames[Ident];
+
+ if (!Entry)
+ Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
+
+// FIXME: Merge into a single cstring creation function.
+// FIXME: This Decl should be more precise.
+llvm::Constant *
+CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
+ const Decl *Container) {
+ std::string TypeStr;
+ CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
+ return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
+}
+
+void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
+ const ObjCContainerDecl *CD,
+ llvm::SmallVectorImpl<char> &Name) {
+ llvm::raw_svector_ostream OS(Name);
+ assert (CD && "Missing container decl in GetNameForMethod");
+ OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
+ << '[' << CD->getName();
+ if (const ObjCCategoryImplDecl *CID =
+ dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
+ OS << '(' << CID << ')';
+ OS << ' ' << D->getSelector().getAsString() << ']';
+}
+
+void CGObjCMac::FinishModule() {
+ EmitModuleInfo();
+
+ // Emit the dummy bodies for any protocols which were referenced but
+ // never defined.
+ for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
+ I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
+ if (I->second->hasInitializer())
+ continue;
+
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
+ Values[1] = GetClassName(I->first);
+ Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+ Values[3] = Values[4] =
+ llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
+ I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
+ I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
+ Values));
+ CGM.AddUsedGlobal(I->second);
+ }
+
+ // Add assembler directives to add lazy undefined symbol references
+ // for classes which are referenced but not defined. This is
+ // important for correct linker interaction.
+ //
+ // FIXME: It would be nice if we had an LLVM construct for this.
+ if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
+ llvm::SmallString<256> Asm;
+ Asm += CGM.getModule().getModuleInlineAsm();
+ if (!Asm.empty() && Asm.back() != '\n')
+ Asm += '\n';
+
+ llvm::raw_svector_ostream OS(Asm);
+ for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
+ e = DefinedSymbols.end(); I != e; ++I)
+ OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
+ << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
+ for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
+ e = LazySymbols.end(); I != e; ++I) {
+ OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
+ }
+
+ for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
+ OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
+ << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
+ }
+
+ CGM.getModule().setModuleInlineAsm(OS.str());
+ }
+}
+
+CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
+ : CGObjCCommonMac(cgm),
+ ObjCTypes(cgm) {
+ ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
+ ObjCABI = 2;
+}
+
+/* *** */
+
+ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
+ : VMContext(cgm.getLLVMContext()), CGM(cgm) {
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+
+ ShortTy = Types.ConvertType(Ctx.ShortTy);
+ IntTy = Types.ConvertType(Ctx.IntTy);
+ LongTy = Types.ConvertType(Ctx.LongTy);
+ LongLongTy = Types.ConvertType(Ctx.LongLongTy);
+ Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+
+ ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
+ PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
+ SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
+
+ // FIXME: It would be nice to unify this with the opaque type, so that the IR
+ // comes out a bit cleaner.
+ const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
+ ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
+
+ // I'm not sure I like this. The implicit coordination is a bit
+ // gross. We should solve this in a reasonable fashion because this
+ // is a pretty common task (match some runtime data structure with
+ // an LLVM data structure).
+
+ // FIXME: This is leaked.
+ // FIXME: Merge with rewriter code?
+
+ // struct _objc_super {
+ // id self;
+ // Class cls;
+ // }
+ RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
+ Ctx.getTranslationUnitDecl(),
+ SourceLocation(),
+ &Ctx.Idents.get("_objc_super"));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.getObjCIdType(), 0, 0, false));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.getObjCClassType(), 0, 0, false));
+ RD->completeDefinition();
+
+ SuperCTy = Ctx.getTagDeclType(RD);
+ SuperPtrCTy = Ctx.getPointerType(SuperCTy);
+
+ SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
+ SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
+
+ // struct _prop_t {
+ // char *name;
+ // char *attributes;
+ // }
+ PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
+ CGM.getModule().addTypeName("struct._prop_t",
+ PropertyTy);
+
+ // struct _prop_list_t {
+ // uint32_t entsize; // sizeof(struct _prop_t)
+ // uint32_t count_of_properties;
+ // struct _prop_t prop_list[count_of_properties];
+ // }
+ PropertyListTy = llvm::StructType::get(VMContext, IntTy,
+ IntTy,
+ llvm::ArrayType::get(PropertyTy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._prop_list_t",
+ PropertyListTy);
+ // struct _prop_list_t *
+ PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
+
+ // struct _objc_method {
+ // SEL _cmd;
+ // char *method_type;
+ // char *_imp;
+ // }
+ MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
+ Int8PtrTy,
+ Int8PtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_method", MethodTy);
+
+ // struct _objc_cache *
+ CacheTy = llvm::OpaqueType::get(VMContext);
+ CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
+ CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
+}
+
+ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
+ : ObjCCommonTypesHelper(cgm) {
+ // struct _objc_method_description {
+ // SEL name;
+ // char *types;
+ // }
+ MethodDescriptionTy =
+ llvm::StructType::get(VMContext, SelectorPtrTy,
+ Int8PtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_method_description",
+ MethodDescriptionTy);
+
+ // struct _objc_method_description_list {
+ // int count;
+ // struct _objc_method_description[1];
+ // }
+ MethodDescriptionListTy =
+ llvm::StructType::get(VMContext, IntTy,
+ llvm::ArrayType::get(MethodDescriptionTy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_method_description_list",
+ MethodDescriptionListTy);
+
+ // struct _objc_method_description_list *
+ MethodDescriptionListPtrTy =
+ llvm::PointerType::getUnqual(MethodDescriptionListTy);
+
+ // Protocol description structures
+
+ // struct _objc_protocol_extension {
+ // uint32_t size; // sizeof(struct _objc_protocol_extension)
+ // struct _objc_method_description_list *optional_instance_methods;
+ // struct _objc_method_description_list *optional_class_methods;
+ // struct _objc_property_list *instance_properties;
+ // }
+ ProtocolExtensionTy =
+ llvm::StructType::get(VMContext, IntTy,
+ MethodDescriptionListPtrTy,
+ MethodDescriptionListPtrTy,
+ PropertyListPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_protocol_extension",
+ ProtocolExtensionTy);
+
+ // struct _objc_protocol_extension *
+ ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
+
+ // Handle recursive construction of Protocol and ProtocolList types
+
+ llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
+ llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
+
+ const llvm::Type *T =
+ llvm::StructType::get(VMContext,
+ llvm::PointerType::getUnqual(ProtocolListTyHolder),
+ LongTy,
+ llvm::ArrayType::get(ProtocolTyHolder, 0),
+ NULL);
+ cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
+
+ // struct _objc_protocol {
+ // struct _objc_protocol_extension *isa;
+ // char *protocol_name;
+ // struct _objc_protocol **_objc_protocol_list;
+ // struct _objc_method_description_list *instance_methods;
+ // struct _objc_method_description_list *class_methods;
+ // }
+ T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
+ Int8PtrTy,
+ llvm::PointerType::getUnqual(ProtocolListTyHolder),
+ MethodDescriptionListPtrTy,
+ MethodDescriptionListPtrTy,
+ NULL);
+ cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
+
+ ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
+ CGM.getModule().addTypeName("struct._objc_protocol_list",
+ ProtocolListTy);
+ // struct _objc_protocol_list *
+ ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
+
+ ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
+ CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
+ ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
+
+ // Class description structures
+
+ // struct _objc_ivar {
+ // char *ivar_name;
+ // char *ivar_type;
+ // int ivar_offset;
+ // }
+ IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
+ Int8PtrTy,
+ IntTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
+
+ // struct _objc_ivar_list *
+ IvarListTy = llvm::OpaqueType::get(VMContext);
+ CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
+ IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
+
+ // struct _objc_method_list *
+ MethodListTy = llvm::OpaqueType::get(VMContext);
+ CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
+ MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
+
+ // struct _objc_class_extension *
+ ClassExtensionTy =
+ llvm::StructType::get(VMContext, IntTy,
+ Int8PtrTy,
+ PropertyListPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
+ ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
+
+ llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
+
+ // struct _objc_class {
+ // Class isa;
+ // Class super_class;
+ // char *name;
+ // long version;
+ // long info;
+ // long instance_size;
+ // struct _objc_ivar_list *ivars;
+ // struct _objc_method_list *methods;
+ // struct _objc_cache *cache;
+ // struct _objc_protocol_list *protocols;
+ // char *ivar_layout;
+ // struct _objc_class_ext *ext;
+ // };
+ T = llvm::StructType::get(VMContext,
+ llvm::PointerType::getUnqual(ClassTyHolder),
+ llvm::PointerType::getUnqual(ClassTyHolder),
+ Int8PtrTy,
+ LongTy,
+ LongTy,
+ LongTy,
+ IvarListPtrTy,
+ MethodListPtrTy,
+ CachePtrTy,
+ ProtocolListPtrTy,
+ Int8PtrTy,
+ ClassExtensionPtrTy,
+ NULL);
+ cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
+
+ ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
+ CGM.getModule().addTypeName("struct._objc_class", ClassTy);
+ ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
+
+ // struct _objc_category {
+ // char *category_name;
+ // char *class_name;
+ // struct _objc_method_list *instance_method;
+ // struct _objc_method_list *class_method;
+ // uint32_t size; // sizeof(struct _objc_category)
+ // struct _objc_property_list *instance_properties;// category's @property
+ // }
+ CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
+ Int8PtrTy,
+ MethodListPtrTy,
+ MethodListPtrTy,
+ ProtocolListPtrTy,
+ IntTy,
+ PropertyListPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
+
+ // Global metadata structures
+
+ // struct _objc_symtab {
+ // long sel_ref_cnt;
+ // SEL *refs;
+ // short cls_def_cnt;
+ // short cat_def_cnt;
+ // char *defs[cls_def_cnt + cat_def_cnt];
+ // }
+ SymtabTy = llvm::StructType::get(VMContext, LongTy,
+ SelectorPtrTy,
+ ShortTy,
+ ShortTy,
+ llvm::ArrayType::get(Int8PtrTy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
+ SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
+
+ // struct _objc_module {
+ // long version;
+ // long size; // sizeof(struct _objc_module)
+ // char *name;
+ // struct _objc_symtab* symtab;
+ // }
+ ModuleTy =
+ llvm::StructType::get(VMContext, LongTy,
+ LongTy,
+ Int8PtrTy,
+ SymtabPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
+
+
+ // FIXME: This is the size of the setjmp buffer and should be target
+ // specific. 18 is what's used on 32-bit X86.
+ uint64_t SetJmpBufferSize = 18;
+
+ // Exceptions
+ const llvm::Type *StackPtrTy = llvm::ArrayType::get(
+ llvm::Type::getInt8PtrTy(VMContext), 4);
+
+ ExceptionDataTy =
+ llvm::StructType::get(VMContext,
+ llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
+ SetJmpBufferSize),
+ StackPtrTy, NULL);
+ CGM.getModule().addTypeName("struct._objc_exception_data",
+ ExceptionDataTy);
+
+}
+
+ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
+ : ObjCCommonTypesHelper(cgm) {
+ // struct _method_list_t {
+ // uint32_t entsize; // sizeof(struct _objc_method)
+ // uint32_t method_count;
+ // struct _objc_method method_list[method_count];
+ // }
+ MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
+ IntTy,
+ llvm::ArrayType::get(MethodTy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct.__method_list_t",
+ MethodListnfABITy);
+ // struct method_list_t *
+ MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
+
+ // struct _protocol_t {
+ // id isa; // NULL
+ // const char * const protocol_name;
+ // const struct _protocol_list_t * protocol_list; // super protocols
+ // const struct method_list_t * const instance_methods;
+ // const struct method_list_t * const class_methods;
+ // const struct method_list_t *optionalInstanceMethods;
+ // const struct method_list_t *optionalClassMethods;
+ // const struct _prop_list_t * properties;
+ // const uint32_t size; // sizeof(struct _protocol_t)
+ // const uint32_t flags; // = 0
+ // }
+
+ // Holder for struct _protocol_list_t *
+ llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
+
+ ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
+ Int8PtrTy,
+ llvm::PointerType::getUnqual(
+ ProtocolListTyHolder),
+ MethodListnfABIPtrTy,
+ MethodListnfABIPtrTy,
+ MethodListnfABIPtrTy,
+ MethodListnfABIPtrTy,
+ PropertyListPtrTy,
+ IntTy,
+ IntTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._protocol_t",
+ ProtocolnfABITy);
+
+ // struct _protocol_t*
+ ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
+
+ // struct _protocol_list_t {
+ // long protocol_count; // Note, this is 32/64 bit
+ // struct _protocol_t *[protocol_count];
+ // }
+ ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
+ llvm::ArrayType::get(
+ ProtocolnfABIPtrTy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_protocol_list",
+ ProtocolListnfABITy);
+ cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
+ ProtocolListnfABITy);
+
+ // struct _objc_protocol_list*
+ ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
+
+ // struct _ivar_t {
+ // unsigned long int *offset; // pointer to ivar offset location
+ // char *name;
+ // char *type;
+ // uint32_t alignment;
+ // uint32_t size;
+ // }
+ IvarnfABITy = llvm::StructType::get(VMContext,
+ llvm::PointerType::getUnqual(LongTy),
+ Int8PtrTy,
+ Int8PtrTy,
+ IntTy,
+ IntTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
+
+ // struct _ivar_list_t {
+ // uint32 entsize; // sizeof(struct _ivar_t)
+ // uint32 count;
+ // struct _iver_t list[count];
+ // }
+ IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
+ IntTy,
+ llvm::ArrayType::get(
+ IvarnfABITy, 0),
+ NULL);
+ CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
+
+ IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
+
+ // struct _class_ro_t {
+ // uint32_t const flags;
+ // uint32_t const instanceStart;
+ // uint32_t const instanceSize;
+ // uint32_t const reserved; // only when building for 64bit targets
+ // const uint8_t * const ivarLayout;
+ // const char *const name;
+ // const struct _method_list_t * const baseMethods;
+ // const struct _objc_protocol_list *const baseProtocols;
+ // const struct _ivar_list_t *const ivars;
+ // const uint8_t * const weakIvarLayout;
+ // const struct _prop_list_t * const properties;
+ // }
+
+ // FIXME. Add 'reserved' field in 64bit abi mode!
+ ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
+ IntTy,
+ IntTy,
+ Int8PtrTy,
+ Int8PtrTy,
+ MethodListnfABIPtrTy,
+ ProtocolListnfABIPtrTy,
+ IvarListnfABIPtrTy,
+ Int8PtrTy,
+ PropertyListPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._class_ro_t",
+ ClassRonfABITy);
+
+ // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ ImpnfABITy = llvm::PointerType::getUnqual(
+ llvm::FunctionType::get(ObjectPtrTy, Params, false));
+
+ // struct _class_t {
+ // struct _class_t *isa;
+ // struct _class_t * const superclass;
+ // void *cache;
+ // IMP *vtable;
+ // struct class_ro_t *ro;
+ // }
+
+ llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
+ ClassnfABITy =
+ llvm::StructType::get(VMContext,
+ llvm::PointerType::getUnqual(ClassTyHolder),
+ llvm::PointerType::getUnqual(ClassTyHolder),
+ CachePtrTy,
+ llvm::PointerType::getUnqual(ImpnfABITy),
+ llvm::PointerType::getUnqual(ClassRonfABITy),
+ NULL);
+ CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
+
+ cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
+ ClassnfABITy);
+
+ // LLVM for struct _class_t *
+ ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
+
+ // struct _category_t {
+ // const char * const name;
+ // struct _class_t *const cls;
+ // const struct _method_list_t * const instance_methods;
+ // const struct _method_list_t * const class_methods;
+ // const struct _protocol_list_t * const protocols;
+ // const struct _prop_list_t * const properties;
+ // }
+ CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
+ ClassnfABIPtrTy,
+ MethodListnfABIPtrTy,
+ MethodListnfABIPtrTy,
+ ProtocolListnfABIPtrTy,
+ PropertyListPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
+
+ // New types for nonfragile abi messaging.
+ CodeGen::CodeGenTypes &Types = CGM.getTypes();
+ ASTContext &Ctx = CGM.getContext();
+
+ // MessageRefTy - LLVM for:
+ // struct _message_ref_t {
+ // IMP messenger;
+ // SEL name;
+ // };
+
+ // First the clang type for struct _message_ref_t
+ RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
+ Ctx.getTranslationUnitDecl(),
+ SourceLocation(),
+ &Ctx.Idents.get("_message_ref_t"));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.VoidPtrTy, 0, 0, false));
+ RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
+ Ctx.getObjCSelType(), 0, 0, false));
+ RD->completeDefinition();
+
+ MessageRefCTy = Ctx.getTagDeclType(RD);
+ MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
+ MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
+
+ // MessageRefPtrTy - LLVM for struct _message_ref_t*
+ MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
+
+ // SuperMessageRefTy - LLVM for:
+ // struct _super_message_ref_t {
+ // SUPER_IMP messenger;
+ // SEL name;
+ // };
+ SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
+ SelectorPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
+
+ // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
+ SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
+
+
+ // struct objc_typeinfo {
+ // const void** vtable; // objc_ehtype_vtable + 2
+ // const char* name; // c++ typeinfo string
+ // Class cls;
+ // };
+ EHTypeTy = llvm::StructType::get(VMContext,
+ llvm::PointerType::getUnqual(Int8PtrTy),
+ Int8PtrTy,
+ ClassnfABIPtrTy,
+ NULL);
+ CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
+ EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
+}
+
+llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
+ FinishNonFragileABIModule();
+
+ return NULL;
+}
+
+void CGObjCNonFragileABIMac::AddModuleClassList(const
+ std::vector<llvm::GlobalValue*>
+ &Container,
+ const char *SymbolName,
+ const char *SectionName) {
+ unsigned NumClasses = Container.size();
+
+ if (!NumClasses)
+ return;
+
+ std::vector<llvm::Constant*> Symbols(NumClasses);
+ for (unsigned i=0; i<NumClasses; i++)
+ Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
+ ObjCTypes.Int8PtrTy);
+ llvm::Constant* Init =
+ llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
+ NumClasses),
+ Symbols);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ SymbolName);
+ GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
+ GV->setSection(SectionName);
+ CGM.AddUsedGlobal(GV);
+}
+
+void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
+ // nonfragile abi has no module definition.
+
+ // Build list of all implemented class addresses in array
+ // L_OBJC_LABEL_CLASS_$.
+ AddModuleClassList(DefinedClasses,
+ "\01L_OBJC_LABEL_CLASS_$",
+ "__DATA, __objc_classlist, regular, no_dead_strip");
+
+ for (unsigned i = 0; i < DefinedClasses.size(); i++) {
+ llvm::GlobalValue *IMPLGV = DefinedClasses[i];
+ if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
+ continue;
+ IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ }
+
+ for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
+ llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
+ if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
+ continue;
+ IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ }
+
+ AddModuleClassList(DefinedNonLazyClasses,
+ "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
+ "__DATA, __objc_nlclslist, regular, no_dead_strip");
+
+ // Build list of all implemented category addresses in array
+ // L_OBJC_LABEL_CATEGORY_$.
+ AddModuleClassList(DefinedCategories,
+ "\01L_OBJC_LABEL_CATEGORY_$",
+ "__DATA, __objc_catlist, regular, no_dead_strip");
+ AddModuleClassList(DefinedNonLazyCategories,
+ "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
+ "__DATA, __objc_nlcatlist, regular, no_dead_strip");
+
+ EmitImageInfo();
+}
+
+/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
+/// NonLegacyDispatchMethods; false otherwise. What this means is that
+/// except for the 19 selectors in the list, we generate 32bit-style
+/// message dispatch call for all the rest.
+///
+bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
+ switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
+ default:
+ assert(0 && "Invalid dispatch method!");
+ case CodeGenOptions::Legacy:
+ return true;
+ case CodeGenOptions::NonLegacy:
+ return false;
+ case CodeGenOptions::Mixed:
+ break;
+ }
+
+ // If so, see whether this selector is in the white-list of things which must
+ // use the new dispatch convention. We lazily build a dense set for this.
+ if (NonLegacyDispatchMethods.empty()) {
+ NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
+ NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
+
+ NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
+ NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
+ // "countByEnumeratingWithState:objects:count"
+ IdentifierInfo *KeyIdents[] = {
+ &CGM.getContext().Idents.get("countByEnumeratingWithState"),
+ &CGM.getContext().Idents.get("objects"),
+ &CGM.getContext().Idents.get("count")
+ };
+ NonLegacyDispatchMethods.insert(
+ CGM.getContext().Selectors.getSelector(3, KeyIdents));
+ }
+
+ return (NonLegacyDispatchMethods.count(Sel) == 0);
+}
+
+// Metadata flags
+enum MetaDataDlags {
+ CLS = 0x0,
+ CLS_META = 0x1,
+ CLS_ROOT = 0x2,
+ OBJC2_CLS_HIDDEN = 0x10,
+ CLS_EXCEPTION = 0x20
+};
+/// BuildClassRoTInitializer - generate meta-data for:
+/// struct _class_ro_t {
+/// uint32_t const flags;
+/// uint32_t const instanceStart;
+/// uint32_t const instanceSize;
+/// uint32_t const reserved; // only when building for 64bit targets
+/// const uint8_t * const ivarLayout;
+/// const char *const name;
+/// const struct _method_list_t * const baseMethods;
+/// const struct _protocol_list_t *const baseProtocols;
+/// const struct _ivar_list_t *const ivars;
+/// const uint8_t * const weakIvarLayout;
+/// const struct _prop_list_t * const properties;
+/// }
+///
+llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
+ unsigned flags,
+ unsigned InstanceStart,
+ unsigned InstanceSize,
+ const ObjCImplementationDecl *ID) {
+ std::string ClassName = ID->getNameAsString();
+ std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
+ Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
+ Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
+ Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
+ // FIXME. For 64bit targets add 0 here.
+ Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
+ : BuildIvarLayout(ID, true);
+ Values[ 4] = GetClassName(ID->getIdentifier());
+ // const struct _method_list_t * const baseMethods;
+ std::vector<llvm::Constant*> Methods;
+ std::string MethodListName("\01l_OBJC_$_");
+ if (flags & CLS_META) {
+ MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
+ for (ObjCImplementationDecl::classmeth_iterator
+ i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
+ // Class methods should always be defined.
+ Methods.push_back(GetMethodConstant(*i));
+ }
+ } else {
+ MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
+ for (ObjCImplementationDecl::instmeth_iterator
+ i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
+ // Instance methods should always be defined.
+ Methods.push_back(GetMethodConstant(*i));
+ }
+ for (ObjCImplementationDecl::propimpl_iterator
+ i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
+ ObjCPropertyImplDecl *PID = *i;
+
+ if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
+ ObjCPropertyDecl *PD = PID->getPropertyDecl();
+
+ if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
+ if (llvm::Constant *C = GetMethodConstant(MD))
+ Methods.push_back(C);
+ if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
+ if (llvm::Constant *C = GetMethodConstant(MD))
+ Methods.push_back(C);
+ }
+ }
+ }
+ Values[ 5] = EmitMethodList(MethodListName,
+ "__DATA, __objc_const", Methods);
+
+ const ObjCInterfaceDecl *OID = ID->getClassInterface();
+ assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
+ Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ + OID->getName(),
+ OID->all_referenced_protocol_begin(),
+ OID->all_referenced_protocol_end());
+
+ if (flags & CLS_META)
+ Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
+ else
+ Values[ 7] = EmitIvarList(ID);
+ Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
+ : BuildIvarLayout(ID, false);
+ if (flags & CLS_META)
+ Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ else
+ Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
+ ID, ID->getClassInterface(), ObjCTypes);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
+ Values);
+ llvm::GlobalVariable *CLASS_RO_GV =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ (flags & CLS_META) ?
+ std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
+ std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
+ CLASS_RO_GV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
+ CLASS_RO_GV->setSection("__DATA, __objc_const");
+ return CLASS_RO_GV;
+
+}
+
+/// BuildClassMetaData - This routine defines that to-level meta-data
+/// for the given ClassName for:
+/// struct _class_t {
+/// struct _class_t *isa;
+/// struct _class_t * const superclass;
+/// void *cache;
+/// IMP *vtable;
+/// struct class_ro_t *ro;
+/// }
+///
+llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
+ std::string &ClassName,
+ llvm::Constant *IsAGV,
+ llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV,
+ bool HiddenVisibility) {
+ std::vector<llvm::Constant*> Values(5);
+ Values[0] = IsAGV;
+ Values[1] = SuperClassGV;
+ if (!Values[1])
+ Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
+ Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
+ Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
+ Values[4] = ClassRoGV; // &CLASS_RO_GV
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
+ Values);
+ llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
+ GV->setInitializer(Init);
+ GV->setSection("__DATA, __objc_data");
+ GV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
+ if (HiddenVisibility)
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ return GV;
+}
+
+bool
+CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
+ return OD->getClassMethod(GetNullarySelector("load")) != 0;
+}
+
+void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
+ uint32_t &InstanceStart,
+ uint32_t &InstanceSize) {
+ const ASTRecordLayout &RL =
+ CGM.getContext().getASTObjCImplementationLayout(OID);
+
+ // InstanceSize is really instance end.
+ InstanceSize = RL.getDataSize().getQuantity();
+
+ // If there are no fields, the start is the same as the end.
+ if (!RL.getFieldCount())
+ InstanceStart = InstanceSize;
+ else
+ InstanceStart = RL.getFieldOffset(0) / 8;
+}
+
+void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
+ std::string ClassName = ID->getNameAsString();
+ if (!ObjCEmptyCacheVar) {
+ ObjCEmptyCacheVar = new llvm::GlobalVariable(
+ CGM.getModule(),
+ ObjCTypes.CacheTy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "_objc_empty_cache");
+
+ ObjCEmptyVtableVar = new llvm::GlobalVariable(
+ CGM.getModule(),
+ ObjCTypes.ImpnfABITy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "_objc_empty_vtable");
+ }
+ assert(ID->getClassInterface() &&
+ "CGObjCNonFragileABIMac::GenerateClass - class is 0");
+ // FIXME: Is this correct (that meta class size is never computed)?
+ uint32_t InstanceStart =
+ CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
+ uint32_t InstanceSize = InstanceStart;
+ uint32_t flags = CLS_META;
+ std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
+ std::string ObjCClassName(getClassSymbolPrefix());
+
+ llvm::GlobalVariable *SuperClassGV, *IsAGV;
+
+ bool classIsHidden =
+ ID->getClassInterface()->getVisibility() == HiddenVisibility;
+ if (classIsHidden)
+ flags |= OBJC2_CLS_HIDDEN;
+ if (ID->getNumIvarInitializers())
+ flags |= eClassFlags_ABI2_HasCXXStructors;
+ if (!ID->getClassInterface()->getSuperClass()) {
+ // class is root
+ flags |= CLS_ROOT;
+ SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
+ IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
+ } else {
+ // Has a root. Current class is not a root.
+ const ObjCInterfaceDecl *Root = ID->getClassInterface();
+ while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
+ Root = Super;
+ IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
+ if (Root->hasAttr<WeakImportAttr>())
+ IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ // work on super class metadata symbol.
+ std::string SuperClassName =
+ ObjCMetaClassName +
+ ID->getClassInterface()->getSuperClass()->getNameAsString();
+ SuperClassGV = GetClassGlobal(SuperClassName);
+ if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+ SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ }
+ llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
+ InstanceStart,
+ InstanceSize,ID);
+ std::string TClassName = ObjCMetaClassName + ClassName;
+ llvm::GlobalVariable *MetaTClass =
+ BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
+ classIsHidden);
+ DefinedMetaClasses.push_back(MetaTClass);
+
+ // Metadata for the class
+ flags = CLS;
+ if (classIsHidden)
+ flags |= OBJC2_CLS_HIDDEN;
+ if (ID->getNumIvarInitializers())
+ flags |= eClassFlags_ABI2_HasCXXStructors;
+
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
+ flags |= CLS_EXCEPTION;
+
+ if (!ID->getClassInterface()->getSuperClass()) {
+ flags |= CLS_ROOT;
+ SuperClassGV = 0;
+ } else {
+ // Has a root. Current class is not a root.
+ std::string RootClassName =
+ ID->getClassInterface()->getSuperClass()->getNameAsString();
+ SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
+ if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
+ SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ }
+ GetClassSizeInfo(ID, InstanceStart, InstanceSize);
+ CLASS_RO_GV = BuildClassRoTInitializer(flags,
+ InstanceStart,
+ InstanceSize,
+ ID);
+
+ TClassName = ObjCClassName + ClassName;
+ llvm::GlobalVariable *ClassMD =
+ BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
+ classIsHidden);
+ DefinedClasses.push_back(ClassMD);
+
+ // Determine if this class is also "non-lazy".
+ if (ImplementationIsNonLazy(ID))
+ DefinedNonLazyClasses.push_back(ClassMD);
+
+ // Force the definition of the EHType if necessary.
+ if (flags & CLS_EXCEPTION)
+ GetInterfaceEHType(ID->getClassInterface(), true);
+}
+
+/// GenerateProtocolRef - This routine is called to generate code for
+/// a protocol reference expression; as in:
+/// @code
+/// @protocol(Proto1);
+/// @endcode
+/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
+/// which will hold address of the protocol meta-data.
+///
+llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *PD) {
+
+ // This routine is called for @protocol only. So, we must build definition
+ // of protocol's meta-data (not a reference to it!)
+ //
+ llvm::Constant *Init =
+ llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
+ ObjCTypes.ExternalProtocolPtrTy);
+
+ std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
+ ProtocolName += PD->getName();
+
+ llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
+ if (PTGV)
+ return Builder.CreateLoad(PTGV, "tmp");
+ PTGV = new llvm::GlobalVariable(
+ CGM.getModule(),
+ Init->getType(), false,
+ llvm::GlobalValue::WeakAnyLinkage,
+ Init,
+ ProtocolName);
+ PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
+ PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.AddUsedGlobal(PTGV);
+ return Builder.CreateLoad(PTGV, "tmp");
+}
+
+/// GenerateCategory - Build metadata for a category implementation.
+/// struct _category_t {
+/// const char * const name;
+/// struct _class_t *const cls;
+/// const struct _method_list_t * const instance_methods;
+/// const struct _method_list_t * const class_methods;
+/// const struct _protocol_list_t * const protocols;
+/// const struct _prop_list_t * const properties;
+/// }
+///
+void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
+ const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
+ const char *Prefix = "\01l_OBJC_$_CATEGORY_";
+ std::string ExtCatName(Prefix + Interface->getNameAsString()+
+ "_$_" + OCD->getNameAsString());
+ std::string ExtClassName(getClassSymbolPrefix() +
+ Interface->getNameAsString());
+
+ std::vector<llvm::Constant*> Values(6);
+ Values[0] = GetClassName(OCD->getIdentifier());
+ // meta-class entry symbol
+ llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
+ if (Interface->hasAttr<WeakImportAttr>())
+ ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+
+ Values[1] = ClassGV;
+ std::vector<llvm::Constant*> Methods;
+ std::string MethodListName(Prefix);
+ MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
+ "_$_" + OCD->getNameAsString();
+
+ for (ObjCCategoryImplDecl::instmeth_iterator
+ i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
+ // Instance methods should always be defined.
+ Methods.push_back(GetMethodConstant(*i));
+ }
+
+ Values[2] = EmitMethodList(MethodListName,
+ "__DATA, __objc_const",
+ Methods);
+
+ MethodListName = Prefix;
+ MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
+ OCD->getNameAsString();
+ Methods.clear();
+ for (ObjCCategoryImplDecl::classmeth_iterator
+ i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
+ // Class methods should always be defined.
+ Methods.push_back(GetMethodConstant(*i));
+ }
+
+ Values[3] = EmitMethodList(MethodListName,
+ "__DATA, __objc_const",
+ Methods);
+ const ObjCCategoryDecl *Category =
+ Interface->FindCategoryDeclaration(OCD->getIdentifier());
+ if (Category) {
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
+ << OCD->getName();
+ Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
+ + Interface->getName() + "_$_"
+ + Category->getName(),
+ Category->protocol_begin(),
+ Category->protocol_end());
+ Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes);
+ } else {
+ Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+ Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ }
+
+ llvm::Constant *Init =
+ llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
+ Values);
+ llvm::GlobalVariable *GCATV
+ = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
+ false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ ExtCatName);
+ GCATV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
+ GCATV->setSection("__DATA, __objc_const");
+ CGM.AddUsedGlobal(GCATV);
+ DefinedCategories.push_back(GCATV);
+
+ // Determine if this category is also "non-lazy".
+ if (ImplementationIsNonLazy(OCD))
+ DefinedNonLazyCategories.push_back(GCATV);
+}
+
+/// GetMethodConstant - Return a struct objc_method constant for the
+/// given method if it has been defined. The result is null if the
+/// method has not been defined. The return value has type MethodPtrTy.
+llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
+ const ObjCMethodDecl *MD) {
+ llvm::Function *Fn = GetMethodDefinition(MD);
+ if (!Fn)
+ return 0;
+
+ std::vector<llvm::Constant*> Method(3);
+ Method[0] =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ Method[1] = GetMethodVarType(MD);
+ Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
+ return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
+}
+
+/// EmitMethodList - Build meta-data for method declarations
+/// struct _method_list_t {
+/// uint32_t entsize; // sizeof(struct _objc_method)
+/// uint32_t method_count;
+/// struct _objc_method method_list[method_count];
+/// }
+///
+llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods) {
+ // Return null for empty list.
+ if (Methods.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
+
+ std::vector<llvm::Constant*> Values(3);
+ // sizeof(struct _objc_method)
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ // method_count
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
+ Methods.size());
+ Values[2] = llvm::ConstantArray::get(AT, Methods);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ Name);
+ GV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(Init->getType()));
+ GV->setSection(Section);
+ CGM.AddUsedGlobal(GV);
+ return llvm::ConstantExpr::getBitCast(GV,
+ ObjCTypes.MethodListnfABIPtrTy);
+}
+
+/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
+/// the given ivar.
+llvm::GlobalVariable *
+CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar) {
+ const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
+ std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
+ '.' + Ivar->getNameAsString();
+ llvm::GlobalVariable *IvarOffsetGV =
+ CGM.getModule().getGlobalVariable(Name);
+ if (!IvarOffsetGV)
+ IvarOffsetGV =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ Name);
+ return IvarOffsetGV;
+}
+
+llvm::Constant *
+CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
+ const ObjCIvarDecl *Ivar,
+ unsigned long int Offset) {
+ llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
+ IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
+ Offset));
+ IvarOffsetGV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
+
+ // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
+ // well (i.e., in ObjCIvarOffsetVariable).
+ if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
+ Ivar->getAccessControl() == ObjCIvarDecl::Package ||
+ ID->getVisibility() == HiddenVisibility)
+ IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ else
+ IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
+ IvarOffsetGV->setSection("__DATA, __objc_const");
+ return IvarOffsetGV;
+}
+
+/// EmitIvarList - Emit the ivar list for the given
+/// implementation. The return value has type
+/// IvarListnfABIPtrTy.
+/// struct _ivar_t {
+/// unsigned long int *offset; // pointer to ivar offset location
+/// char *name;
+/// char *type;
+/// uint32_t alignment;
+/// uint32_t size;
+/// }
+/// struct _ivar_list_t {
+/// uint32 entsize; // sizeof(struct _ivar_t)
+/// uint32 count;
+/// struct _iver_t list[count];
+/// }
+///
+
+llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
+ const ObjCImplementationDecl *ID) {
+
+ std::vector<llvm::Constant*> Ivars, Ivar(5);
+
+ const ObjCInterfaceDecl *OID = ID->getClassInterface();
+ assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
+
+ // FIXME. Consolidate this with similar code in GenerateClass.
+
+ // Collect declared and synthesized ivars in a small vector.
+ llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
+ CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
+
+ for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
+ ObjCIvarDecl *IVD = OIvars[i];
+ // Ignore unnamed bit-fields.
+ if (!IVD->getDeclName())
+ continue;
+ Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
+ ComputeIvarBaseOffset(CGM, ID, IVD));
+ Ivar[1] = GetMethodVarName(IVD->getIdentifier());
+ Ivar[2] = GetMethodVarType(IVD);
+ const llvm::Type *FieldTy =
+ CGM.getTypes().ConvertTypeForMem(IVD->getType());
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
+ unsigned Align = CGM.getContext().getPreferredTypeAlign(
+ IVD->getType().getTypePtr()) >> 3;
+ Align = llvm::Log2_32(Align);
+ Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
+ // NOTE. Size of a bitfield does not match gcc's, because of the
+ // way bitfields are treated special in each. But I am told that
+ // 'size' for bitfield ivars is ignored by the runtime so it does
+ // not matter. If it matters, there is enough info to get the
+ // bitfield right!
+ Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
+ }
+ // Return null for empty list.
+ if (Ivars.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
+ std::vector<llvm::Constant*> Values(3);
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
+ Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
+ Ivars.size());
+ Values[2] = llvm::ConstantArray::get(AT, Ivars);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+ const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ Prefix + OID->getName());
+ GV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(Init->getType()));
+ GV->setSection("__DATA, __objc_const");
+
+ CGM.AddUsedGlobal(GV);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
+}
+
+llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
+ const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ if (!Entry) {
+ // We use the initializer as a marker of whether this is a forward
+ // reference or not. At module finalization we add the empty
+ // contents for protocols which were referenced but never defined.
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ }
+
+ return Entry;
+}
+
+/// GetOrEmitProtocol - Generate the protocol meta-data:
+/// @code
+/// struct _protocol_t {
+/// id isa; // NULL
+/// const char * const protocol_name;
+/// const struct _protocol_list_t * protocol_list; // super protocols
+/// const struct method_list_t * const instance_methods;
+/// const struct method_list_t * const class_methods;
+/// const struct method_list_t *optionalInstanceMethods;
+/// const struct method_list_t *optionalClassMethods;
+/// const struct _prop_list_t * properties;
+/// const uint32_t size; // sizeof(struct _protocol_t)
+/// const uint32_t flags; // = 0
+/// }
+/// @endcode
+///
+
+llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
+ const ObjCProtocolDecl *PD) {
+ llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+
+ // Early exit if a defining object has already been generated.
+ if (Entry && Entry->hasInitializer())
+ return Entry;
+
+ // Construct method lists.
+ std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
+ std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
+ for (ObjCProtocolDecl::instmeth_iterator
+ i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodDescriptionConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptInstanceMethods.push_back(C);
+ } else {
+ InstanceMethods.push_back(C);
+ }
+ }
+
+ for (ObjCProtocolDecl::classmeth_iterator
+ i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ llvm::Constant *C = GetMethodDescriptionConstant(MD);
+ if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
+ OptClassMethods.push_back(C);
+ } else {
+ ClassMethods.push_back(C);
+ }
+ }
+
+ std::vector<llvm::Constant*> Values(10);
+ // isa is NULL
+ Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
+ Values[1] = GetClassName(PD->getIdentifier());
+ Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
+ PD->protocol_begin(),
+ PD->protocol_end());
+
+ Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
+ + PD->getName(),
+ "__DATA, __objc_const",
+ InstanceMethods);
+ Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
+ + PD->getName(),
+ "__DATA, __objc_const",
+ ClassMethods);
+ Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
+ + PD->getName(),
+ "__DATA, __objc_const",
+ OptInstanceMethods);
+ Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
+ + PD->getName(),
+ "__DATA, __objc_const",
+ OptClassMethods);
+ Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
+ 0, PD, ObjCTypes);
+ uint32_t Size =
+ CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
+ Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
+ llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
+ Values);
+
+ if (Entry) {
+ // Already created, fix the linkage and update the initializer.
+ Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+ Entry->setInitializer(Init);
+ } else {
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Init,
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
+ Entry->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ }
+ Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.AddUsedGlobal(Entry);
+
+ // Use this protocol meta-data to build protocol list table in section
+ // __DATA, __objc_protolist
+ llvm::GlobalVariable *PTGV =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Entry,
+ "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
+ PTGV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
+ PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
+ PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ CGM.AddUsedGlobal(PTGV);
+ return Entry;
+}
+
+/// EmitProtocolList - Generate protocol list meta-data:
+/// @code
+/// struct _protocol_list_t {
+/// long protocol_count; // Note, this is 32/64 bit
+/// struct _protocol_t[protocol_count];
+/// }
+/// @endcode
+///
+llvm::Constant *
+CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
+ std::vector<llvm::Constant*> ProtocolRefs;
+
+ // Just return null for empty protocol lists
+ if (begin == end)
+ return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+
+ // FIXME: We shouldn't need to do this lookup here, should we?
+ llvm::SmallString<256> TmpName;
+ Name.toVector(TmpName);
+ llvm::GlobalVariable *GV =
+ CGM.getModule().getGlobalVariable(TmpName.str(), true);
+ if (GV)
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
+
+ for (; begin != end; ++begin)
+ ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
+
+ // This list is null terminated.
+ ProtocolRefs.push_back(llvm::Constant::getNullValue(
+ ObjCTypes.ProtocolnfABIPtrTy));
+
+ std::vector<llvm::Constant*> Values(2);
+ Values[0] =
+ llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
+ Values[1] =
+ llvm::ConstantArray::get(
+ llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
+ ProtocolRefs.size()),
+ ProtocolRefs);
+
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+ GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::InternalLinkage,
+ Init,
+ Name);
+ GV->setSection("__DATA, __objc_const");
+ GV->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(Init->getType()));
+ CGM.AddUsedGlobal(GV);
+ return llvm::ConstantExpr::getBitCast(GV,
+ ObjCTypes.ProtocolListnfABIPtrTy);
+}
+
+/// GetMethodDescriptionConstant - This routine build following meta-data:
+/// struct _objc_method {
+/// SEL _cmd;
+/// char *method_type;
+/// char *_imp;
+/// }
+
+llvm::Constant *
+CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
+ std::vector<llvm::Constant*> Desc(3);
+ Desc[0] =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ Desc[1] = GetMethodVarType(MD);
+ // Protocol methods have no implementation. So, this entry is always NULL.
+ Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
+}
+
+/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
+/// This code gen. amounts to generating code for:
+/// @code
+/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
+/// @encode
+///
+LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
+ CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers) {
+ ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
+ return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
+ EmitIvarOffset(CGF, ID, Ivar));
+}
+
+llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
+ CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) {
+ return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
+}
+
+CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
+ CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs) {
+ // FIXME. Even though IsSuper is passes. This function doese not handle calls
+ // to 'super' receivers.
+ CodeGenTypes &Types = CGM.getTypes();
+ llvm::Value *Arg0 = Receiver;
+ if (!IsSuper)
+ Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
+
+ // Find the message function name.
+ // FIXME. This is too much work to get the ABI-specific result type needed to
+ // find the message name.
+ const CGFunctionInfo &FnInfo
+ = Types.getFunctionInfo(ResultType, CallArgList(),
+ FunctionType::ExtInfo());
+ llvm::Constant *Fn = 0;
+ std::string Name("\01l_");
+ if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ if (IsSuper) {
+ Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
+ Name += "objc_msgSendSuper2_stret_fixup";
+ } else {
+ Fn = ObjCTypes.getMessageSendStretFixupFn();
+ Name += "objc_msgSend_stret_fixup";
+ }
+ } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
+ Fn = ObjCTypes.getMessageSendFpretFixupFn();
+ Name += "objc_msgSend_fpret_fixup";
+ } else {
+ if (IsSuper) {
+ Fn = ObjCTypes.getMessageSendSuper2FixupFn();
+ Name += "objc_msgSendSuper2_fixup";
+ } else {
+ Fn = ObjCTypes.getMessageSendFixupFn();
+ Name += "objc_msgSend_fixup";
+ }
+ }
+ assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
+ Name += '_';
+ std::string SelName(Sel.getAsString());
+ // Replace all ':' in selector name with '_' ouch!
+ for (unsigned i = 0; i < SelName.size(); i++)
+ if (SelName[i] == ':')
+ SelName[i] = '_';
+ Name += SelName;
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (!GV) {
+ // Build message ref table entry.
+ std::vector<llvm::Constant*> Values(2);
+ Values[0] = Fn;
+ Values[1] = GetMethodVarName(Sel);
+ llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
+ GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
+ llvm::GlobalValue::WeakAnyLinkage,
+ Init,
+ Name);
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ GV->setAlignment(16);
+ GV->setSection("__DATA, __objc_msgrefs, coalesced");
+ }
+ llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
+
+ CallArgList ActualArgs;
+ ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
+ ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
+ ObjCTypes.MessageRefCPtrTy));
+ ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+ const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
+ FunctionType::ExtInfo());
+ llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
+ Callee = CGF.Builder.CreateLoad(Callee);
+ const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
+ Callee = CGF.Builder.CreateBitCast(Callee,
+ llvm::PointerType::getUnqual(FTy));
+ return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs);
+}
+
+/// Generate code for a message send expression in the nonfragile abi.
+CodeGen::RValue
+CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class,
+ const ObjCMethodDecl *Method) {
+ return LegacyDispatchedSelector(Sel)
+ ? EmitLegacyMessageSend(CGF, Return, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs, Method, ObjCTypes)
+ : EmitMessageSend(CGF, Return, ResultType, Sel,
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs);
+}
+
+llvm::GlobalVariable *
+CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+
+ if (!GV) {
+ GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
+ false, llvm::GlobalValue::ExternalLinkage,
+ 0, Name);
+ }
+
+ return GV;
+}
+
+llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
+
+ if (!Entry) {
+ std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+ llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
+ false, llvm::GlobalValue::InternalLinkage,
+ ClassGV,
+ "\01L_OBJC_CLASSLIST_REFERENCES_$_");
+ Entry->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(
+ ObjCTypes.ClassnfABIPtrTy));
+ Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
+ CGM.AddUsedGlobal(Entry);
+ }
+
+ return Builder.CreateLoad(Entry, "tmp");
+}
+
+llvm::Value *
+CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
+
+ if (!Entry) {
+ std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+ llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
+ false, llvm::GlobalValue::InternalLinkage,
+ ClassGV,
+ "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
+ Entry->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(
+ ObjCTypes.ClassnfABIPtrTy));
+ Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
+ CGM.AddUsedGlobal(Entry);
+ }
+
+ return Builder.CreateLoad(Entry, "tmp");
+}
+
+/// EmitMetaClassRef - Return a Value * of the address of _class_t
+/// meta-data
+///
+llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
+ if (Entry)
+ return Builder.CreateLoad(Entry, "tmp");
+
+ std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
+ llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
+ llvm::GlobalValue::InternalLinkage,
+ MetaClassGV,
+ "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
+ Entry->setAlignment(
+ CGM.getTargetData().getABITypeAlignment(
+ ObjCTypes.ClassnfABIPtrTy));
+
+ Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
+ CGM.AddUsedGlobal(Entry);
+
+ return Builder.CreateLoad(Entry, "tmp");
+}
+
+/// GetClass - Return a reference to the class for the given interface
+/// decl.
+llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *ID) {
+ if (ID->hasAttr<WeakImportAttr>()) {
+ std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+ llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
+ ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+ }
+
+ return EmitClassRef(Builder, ID);
+}
+
+/// Generates a message send where the super is the receiver. This is
+/// a message send to self with special delivery semantics indicating
+/// which class's method should be called.
+CodeGen::RValue
+CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot Return,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Receiver,
+ bool IsClassMessage,
+ const CodeGen::CallArgList &CallArgs,
+ const ObjCMethodDecl *Method) {
+ // ...
+ // Create and init a super structure; this is a (receiver, class)
+ // pair we will pass to objc_msgSendSuper.
+ llvm::Value *ObjCSuper =
+ CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
+
+ llvm::Value *ReceiverAsObject =
+ CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
+ CGF.Builder.CreateStore(ReceiverAsObject,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+
+ // If this is a class message the metaclass is passed as the target.
+ llvm::Value *Target;
+ if (IsClassMessage) {
+ if (isCategoryImpl) {
+ // Message sent to "super' in a class method defined in
+ // a category implementation.
+ Target = EmitClassRef(CGF.Builder, Class);
+ Target = CGF.Builder.CreateStructGEP(Target, 0);
+ Target = CGF.Builder.CreateLoad(Target);
+ } else
+ Target = EmitMetaClassRef(CGF.Builder, Class);
+ } else
+ Target = EmitSuperClassRef(CGF.Builder, Class);
+
+ // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
+ // ObjCTypes types.
+ const llvm::Type *ClassTy =
+ CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
+ Target = CGF.Builder.CreateBitCast(Target, ClassTy);
+ CGF.Builder.CreateStore(Target,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+
+ return (LegacyDispatchedSelector(Sel))
+ ? EmitLegacyMessageSend(CGF, Return, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs, Method, ObjCTypes)
+ : EmitMessageSend(CGF, Return, ResultType, Sel,
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs);
+}
+
+llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
+ Selector Sel, bool lval) {
+ llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
+
+ if (!Entry) {
+ llvm::Constant *Casted =
+ llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
+ ObjCTypes.SelectorPtrTy);
+ Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
+ llvm::GlobalValue::InternalLinkage,
+ Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
+ Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
+ CGM.AddUsedGlobal(Entry);
+ }
+
+ if (lval)
+ return Entry;
+ return Builder.CreateLoad(Entry, "tmp");
+}
+/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
+/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
+///
+void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src,
+ llvm::Value *dst,
+ llvm::Value *ivarOffset) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
+ src, dst, ivarOffset);
+ return;
+}
+
+/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
+/// objc_assign_strongCast (id src, id *dst)
+///
+void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
+ CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
+ src, dst, "weakassign");
+ return;
+}
+
+void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
+ CodeGen::CodeGenFunction &CGF,
+ llvm::Value *DestPtr,
+ llvm::Value *SrcPtr,
+ llvm::Value *Size) {
+ SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
+ DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
+ CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
+ DestPtr, SrcPtr, Size);
+ return;
+}
+
+/// EmitObjCWeakRead - Code gen for loading value of a __weak
+/// object: objc_read_weak (id *src)
+///
+llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
+ CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj) {
+ const llvm::Type* DestTy =
+ cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
+ AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
+ llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
+ AddrWeakObj, "weakread");
+ read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
+ return read_weak;
+}
+
+/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
+/// objc_assign_weak (id src, id *dst)
+///
+void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
+ src, dst, "weakassign");
+ return;
+}
+
+/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
+/// objc_assign_global (id src, id *dst)
+///
+void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
+ const llvm::Type * SrcTy = src->getType();
+ if (!isa<llvm::PointerType>(SrcTy)) {
+ unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
+ assert(Size <= 8 && "does not support size > 8");
+ src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
+ : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
+ src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
+ }
+ src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
+ dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
+ if (!threadlocal)
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
+ src, dst, "globalassign");
+ else
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
+ src, dst, "threadlocalassign");
+ return;
+}
+
+namespace {
+ struct CallSyncExit : EHScopeStack::Cleanup {
+ llvm::Value *SyncExitFn;
+ llvm::Value *SyncArg;
+ CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
+ : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ }
+ };
+}
+
+void
+CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S) {
+ // Evaluate the lock operand. This should dominate the cleanup.
+ llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr());
+
+ // Acquire the lock.
+ SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
+ CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
+ ->setDoesNotThrow();
+
+ // Register an all-paths cleanup to release the lock.
+ CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
+ ObjCTypes.getSyncExitFn(),
+ SyncArg);
+
+ // Emit the body of the statement.
+ CGF.EmitStmt(S.getSynchBody());
+
+ // Pop the lock-release cleanup.
+ CGF.PopCleanupBlock();
+}
+
+namespace {
+ struct CatchHandler {
+ const VarDecl *Variable;
+ const Stmt *Body;
+ llvm::BasicBlock *Block;
+ llvm::Value *TypeInfo;
+ };
+
+ struct CallObjCEndCatch : EHScopeStack::Cleanup {
+ CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
+ MightThrow(MightThrow), Fn(Fn) {}
+ bool MightThrow;
+ llvm::Value *Fn;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ if (!MightThrow) {
+ CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
+ return;
+ }
+
+ CGF.EmitCallOrInvoke(Fn, 0, 0);
+ }
+ };
+}
+
+llvm::Constant *
+CGObjCNonFragileABIMac::GetEHType(QualType T) {
+ // There's a particular fixed type info for 'id'.
+ if (T->isObjCIdType() ||
+ T->isObjCQualifiedIdType()) {
+ llvm::Constant *IDEHType =
+ CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
+ if (!IDEHType)
+ IDEHType =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, "OBJC_EHTYPE_id");
+ return IDEHType;
+ }
+
+ // All other types should be Objective-C interface pointer types.
+ const ObjCObjectPointerType *PT =
+ T->getAs<ObjCObjectPointerType>();
+ assert(PT && "Invalid @catch type.");
+ const ObjCInterfaceType *IT = PT->getInterfaceType();
+ assert(IT && "Invalid @catch type.");
+ return GetInterfaceEHType(IT->getDecl(), false);
+}
+
+void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S) {
+ // Jump destination for falling out of catch bodies.
+ CodeGenFunction::JumpDest Cont;
+ if (S.getNumCatchStmts())
+ Cont = CGF.getJumpDestInCurrentScope("eh.cont");
+
+ CodeGenFunction::FinallyInfo FinallyInfo;
+ if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
+ FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(),
+ ObjCTypes.getObjCBeginCatchFn(),
+ ObjCTypes.getObjCEndCatchFn(),
+ ObjCTypes.getExceptionRethrowFn());
+
+ llvm::SmallVector<CatchHandler, 8> Handlers;
+
+ // Enter the catch, if there is one.
+ if (S.getNumCatchStmts()) {
+ for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
+ const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
+ const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
+
+ Handlers.push_back(CatchHandler());
+ CatchHandler &Handler = Handlers.back();
+ Handler.Variable = CatchDecl;
+ Handler.Body = CatchStmt->getCatchBody();
+ Handler.Block = CGF.createBasicBlock("catch");
+
+ // @catch(...) always matches.
+ if (!CatchDecl) {
+ Handler.TypeInfo = 0; // catch-all
+ // Don't consider any other catches.
+ break;
+ }
+
+ Handler.TypeInfo = GetEHType(CatchDecl->getType());
+ }
+
+ EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
+ Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
+ }
+
+ // Emit the try body.
+ CGF.EmitStmt(S.getTryBody());
+
+ // Leave the try.
+ if (S.getNumCatchStmts())
+ CGF.EHStack.popCatch();
+
+ // Remember where we were.
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+
+ // Emit the handlers.
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ CatchHandler &Handler = Handlers[I];
+
+ CGF.EmitBlock(Handler.Block);
+ llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
+
+ // Enter the catch.
+ llvm::CallInst *Exn =
+ CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn,
+ "exn.adjusted");
+ Exn->setDoesNotThrow();
+
+ // Add a cleanup to leave the catch.
+ bool EndCatchMightThrow = (Handler.Variable == 0);
+ CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
+ EndCatchMightThrow,
+ ObjCTypes.getObjCEndCatchFn());
+
+ // Bind the catch parameter if it exists.
+ if (const VarDecl *CatchParam = Handler.Variable) {
+ const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
+ llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
+
+ CGF.EmitAutoVarDecl(*CatchParam);
+ CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
+ }
+
+ CGF.ObjCEHValueStack.push_back(Exn);
+ CGF.EmitStmt(Handler.Body);
+ CGF.ObjCEHValueStack.pop_back();
+
+ // Leave the earlier cleanup.
+ CGF.PopCleanupBlock();
+
+ CGF.EmitBranchThroughCleanup(Cont);
+ }
+
+ // Go back to the try-statement fallthrough.
+ CGF.Builder.restoreIP(SavedIP);
+
+ // Pop out of the normal cleanup on the finally.
+ if (S.getFinallyStmt())
+ CGF.ExitFinallyBlock(FinallyInfo);
+
+ if (Cont.isValid())
+ CGF.EmitBlock(Cont.getBlock());
+}
+
+/// EmitThrowStmt - Generate code for a throw statement.
+void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S) {
+ if (const Expr *ThrowExpr = S.getThrowExpr()) {
+ llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
+ "tmp");
+ llvm::Value *Args[] = { Exception };
+ CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
+ Args, Args+1)
+ .setDoesNotReturn();
+ } else {
+ CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
+ .setDoesNotReturn();
+ }
+
+ CGF.Builder.CreateUnreachable();
+ CGF.Builder.ClearInsertionPoint();
+}
+
+llvm::Constant *
+CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
+ bool ForDefinition) {
+ llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
+
+ // If we don't need a definition, return the entry if found or check
+ // if we use an external reference.
+ if (!ForDefinition) {
+ if (Entry)
+ return Entry;
+
+ // If this type (or a super class) has the __objc_exception__
+ // attribute, emit an external reference.
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID))
+ return Entry =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ ("OBJC_EHTYPE_$_" +
+ ID->getIdentifier()->getName()));
+ }
+
+ // Otherwise we need to either make a new entry or fill in the
+ // initializer.
+ assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
+ std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+ std::string VTableName = "objc_ehtype_vtable";
+ llvm::GlobalVariable *VTableGV =
+ CGM.getModule().getGlobalVariable(VTableName);
+ if (!VTableGV)
+ VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, VTableName);
+
+ llvm::Value *VTableIdx =
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
+
+ std::vector<llvm::Constant*> Values(3);
+ Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
+ Values[1] = GetClassName(ID->getIdentifier());
+ Values[2] = GetClassGlobal(ClassName);
+ llvm::Constant *Init =
+ llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
+
+ if (Entry) {
+ Entry->setInitializer(Init);
+ } else {
+ Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
+ llvm::GlobalValue::WeakAnyLinkage,
+ Init,
+ ("OBJC_EHTYPE_$_" +
+ ID->getIdentifier()->getName()));
+ }
+
+ if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
+ Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
+ ObjCTypes.EHTypeTy));
+
+ if (ForDefinition) {
+ Entry->setSection("__DATA,__objc_const");
+ Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else {
+ Entry->setSection("__DATA,__datacoal_nt,coalesced");
+ }
+
+ return Entry;
+}
+
+/* *** */
+
+CodeGen::CGObjCRuntime *
+CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
+ return new CGObjCMac(CGM);
+}
+
+CodeGen::CGObjCRuntime *
+CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
+ return new CGObjCNonFragileABIMac(CGM);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
new file mode 100644
index 0000000..5ad3a50
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
@@ -0,0 +1,236 @@
+//===----- CGObjCRuntime.h - Interface to ObjC Runtimes ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for Objective-C code generation. Concrete
+// subclasses of this implement code generation for specific Objective-C
+// runtime libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_OBCJRUNTIME_H
+#define CLANG_CODEGEN_OBCJRUNTIME_H
+#include "clang/Basic/IdentifierTable.h" // Selector
+#include "clang/AST/DeclObjC.h"
+#include <string>
+
+#include "CGBuilder.h"
+#include "CGCall.h"
+#include "CGValue.h"
+
+namespace llvm {
+ class Constant;
+ class Function;
+ class Module;
+ class StructLayout;
+ class StructType;
+ class Type;
+ class Value;
+}
+
+namespace clang {
+namespace CodeGen {
+ class CodeGenFunction;
+}
+
+ class FieldDecl;
+ class ObjCAtTryStmt;
+ class ObjCAtThrowStmt;
+ class ObjCAtSynchronizedStmt;
+ class ObjCContainerDecl;
+ class ObjCCategoryImplDecl;
+ class ObjCImplementationDecl;
+ class ObjCInterfaceDecl;
+ class ObjCMessageExpr;
+ class ObjCMethodDecl;
+ class ObjCProtocolDecl;
+ class Selector;
+ class ObjCIvarDecl;
+ class ObjCStringLiteral;
+ class BlockDeclRefExpr;
+
+namespace CodeGen {
+ class CodeGenModule;
+ class CGBlockInfo;
+
+// FIXME: Several methods should be pure virtual but aren't to avoid the
+// partially-implemented subclass breaking.
+
+/// Implements runtime-specific code generation functions.
+class CGObjCRuntime {
+protected:
+ // Utility functions for unified ivar access. These need to
+ // eventually be folded into other places (the structure layout
+ // code).
+
+ /// Compute an offset to the given ivar, suitable for passing to
+ /// EmitValueForIvarAtOffset. Note that the correct handling of
+ /// bit-fields is carefully coordinated by these two, use caution!
+ ///
+ /// The latter overload is suitable for computing the offset of a
+ /// sythesized ivar.
+ uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
+ const ObjCInterfaceDecl *OID,
+ const ObjCIvarDecl *Ivar);
+ uint64_t ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
+ const ObjCImplementationDecl *OID,
+ const ObjCIvarDecl *Ivar);
+
+ LValue EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *OID,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers,
+ llvm::Value *Offset);
+
+public:
+ virtual ~CGObjCRuntime();
+
+ /// Generate the function required to register all Objective-C components in
+ /// this compilation unit with the runtime library.
+ virtual llvm::Function *ModuleInitFunction() = 0;
+
+ /// Get a selector for the specified name and type values. The
+ /// return value should have the LLVM type for pointer-to
+ /// ASTContext::getObjCSelType().
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
+ Selector Sel, bool lval=false) = 0;
+
+ /// Get a typed selector.
+ virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
+ const ObjCMethodDecl *Method) = 0;
+
+ /// Get the type constant to catch for the given ObjC pointer type.
+ /// This is used externally to implement catching ObjC types in C++.
+ /// Runtimes which don't support this should add the appropriate
+ /// error to Sema.
+ virtual llvm::Constant *GetEHType(QualType T) = 0;
+
+ /// Generate a constant string object.
+ virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
+
+ /// Generate a category. A category contains a list of methods (and
+ /// accompanying metadata) and a list of protocols.
+ virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0;
+
+ /// Generate a class stucture for this class.
+ virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0;
+
+ /// Generate an Objective-C message send operation.
+ ///
+ /// \param Method - The method being called, this may be null if synthesizing
+ /// a property setter or getter.
+ virtual CodeGen::RValue
+ GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot ReturnSlot,
+ QualType ResultType,
+ Selector Sel,
+ llvm::Value *Receiver,
+ const CallArgList &CallArgs,
+ const ObjCInterfaceDecl *Class = 0,
+ const ObjCMethodDecl *Method = 0) = 0;
+
+ /// Generate an Objective-C message send operation to the super
+ /// class initiated in a method for Class and with the given Self
+ /// object.
+ ///
+ /// \param Method - The method being called, this may be null if synthesizing
+ /// a property setter or getter.
+ virtual CodeGen::RValue
+ GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
+ ReturnValueSlot ReturnSlot,
+ QualType ResultType,
+ Selector Sel,
+ const ObjCInterfaceDecl *Class,
+ bool isCategoryImpl,
+ llvm::Value *Self,
+ bool IsClassMessage,
+ const CallArgList &CallArgs,
+ const ObjCMethodDecl *Method = 0) = 0;
+
+ /// Emit the code to return the named protocol as an object, as in a
+ /// @protocol expression.
+ virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
+ const ObjCProtocolDecl *OPD) = 0;
+
+ /// Generate the named protocol. Protocols contain method metadata but no
+ /// implementations.
+ virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0;
+
+ /// Generate a function preamble for a method with the specified
+ /// types.
+
+ // FIXME: Current this just generates the Function definition, but really this
+ // should also be generating the loads of the parameters, as the runtime
+ // should have full control over how parameters are passed.
+ virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) = 0;
+
+ /// Return the runtime function for getting properties.
+ virtual llvm::Constant *GetPropertyGetFunction() = 0;
+
+ /// Return the runtime function for setting properties.
+ virtual llvm::Constant *GetPropertySetFunction() = 0;
+
+ // API for atomic copying of qualified aggregates in getter.
+ virtual llvm::Constant *GetGetStructFunction() = 0;
+ // API for atomic copying of qualified aggregates in setter.
+ virtual llvm::Constant *GetSetStructFunction() = 0;
+
+ /// GetClass - Return a reference to the class for the given
+ /// interface decl.
+ virtual llvm::Value *GetClass(CGBuilderTy &Builder,
+ const ObjCInterfaceDecl *OID) = 0;
+
+ /// EnumerationMutationFunction - Return the function that's called by the
+ /// compiler when a mutation is detected during foreach iteration.
+ virtual llvm::Constant *EnumerationMutationFunction() = 0;
+
+ virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtSynchronizedStmt &S) = 0;
+ virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtTryStmt &S) = 0;
+ virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
+ const ObjCAtThrowStmt &S) = 0;
+ virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *AddrWeakObj) = 0;
+ virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest) = 0;
+ virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal=false) = 0;
+ virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest,
+ llvm::Value *ivarOffset) = 0;
+ virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *src, llvm::Value *dest) = 0;
+
+ virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
+ QualType ObjectTy,
+ llvm::Value *BaseValue,
+ const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers) = 0;
+ virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
+ const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar) = 0;
+ virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *DestPtr,
+ llvm::Value *SrcPtr,
+ llvm::Value *Size) = 0;
+ virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
+ const CodeGen::CGBlockInfo &blockInfo) = 0;
+};
+
+/// Creates an instance of an Objective-C runtime class.
+//TODO: This should include some way of selecting which runtime to target.
+CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM);
+CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM);
+CGObjCRuntime *CreateMacNonFragileABIObjCRuntime(CodeGenModule &CGM);
+}
+}
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp
new file mode 100644
index 0000000..7ec0ee4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRTTI.cpp
@@ -0,0 +1,1005 @@
+//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of RTTI descriptors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+class RTTIBuilder {
+ CodeGenModule &CGM; // Per-module state.
+ llvm::LLVMContext &VMContext;
+
+ const llvm::Type *Int8PtrTy;
+
+ /// Fields - The fields of the RTTI descriptor currently being built.
+ llvm::SmallVector<llvm::Constant *, 16> Fields;
+
+ /// GetAddrOfTypeName - Returns the mangled type name of the given type.
+ llvm::GlobalVariable *
+ GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
+
+ /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
+ /// descriptor of the given type.
+ llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
+
+ /// BuildVTablePointer - Build the vtable pointer for the given type.
+ void BuildVTablePointer(const Type *Ty);
+
+ /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+ /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
+ void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+ /// classes with bases that do not satisfy the abi::__si_class_type_info
+ /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+ void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
+ /// for pointer types.
+ void BuildPointerTypeInfo(QualType PointeeTy);
+
+ /// BuildObjCObjectTypeInfo - Build the appropriate kind of
+ /// type_info for an object type.
+ void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
+
+ /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+ /// struct, used for member pointer types.
+ void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
+
+public:
+ RTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
+ VMContext(CGM.getModule().getContext()),
+ Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { }
+
+ // Pointer type info flags.
+ enum {
+ /// PTI_Const - Type has const qualifier.
+ PTI_Const = 0x1,
+
+ /// PTI_Volatile - Type has volatile qualifier.
+ PTI_Volatile = 0x2,
+
+ /// PTI_Restrict - Type has restrict qualifier.
+ PTI_Restrict = 0x4,
+
+ /// PTI_Incomplete - Type is incomplete.
+ PTI_Incomplete = 0x8,
+
+ /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+ /// (in pointer to member).
+ PTI_ContainingClassIncomplete = 0x10
+ };
+
+ // VMI type info flags.
+ enum {
+ /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
+ VMI_NonDiamondRepeat = 0x1,
+
+ /// VMI_DiamondShaped - Class is diamond shaped.
+ VMI_DiamondShaped = 0x2
+ };
+
+ // Base class type info flags.
+ enum {
+ /// BCTI_Virtual - Base class is virtual.
+ BCTI_Virtual = 0x1,
+
+ /// BCTI_Public - Base class is public.
+ BCTI_Public = 0x2
+ };
+
+ /// BuildTypeInfo - Build the RTTI type info struct for the given type.
+ ///
+ /// \param Force - true to force the creation of this RTTI value
+ /// \param ForEH - true if this is for exception handling
+ llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
+};
+}
+
+llvm::GlobalVariable *
+RTTIBuilder::GetAddrOfTypeName(QualType Ty,
+ llvm::GlobalVariable::LinkageTypes Linkage) {
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ // We know that the mangled name of the type starts at index 4 of the
+ // mangled name of the typename, so we can just index into it in order to
+ // get the mangled name of the type.
+ llvm::Constant *Init = llvm::ConstantArray::get(VMContext, Name.substr(4));
+
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
+
+ GV->setInitializer(Init);
+
+ return GV;
+}
+
+llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
+ // Mangle the RTTI name.
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ // Look for an existing global.
+ llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
+
+ if (!GV) {
+ // Create a new global variable.
+ GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, /*Constant=*/true,
+ llvm::GlobalValue::ExternalLinkage, 0, Name);
+ }
+
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+}
+
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
+ // Itanium C++ ABI 2.9.2:
+ // Basic type information (e.g. for "int", "bool", etc.) will be kept in
+ // the run-time support library. Specifically, the run-time support
+ // library should contain type_info objects for the types X, X* and
+ // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
+ // unsigned char, signed char, short, unsigned short, int, unsigned int,
+ // long, unsigned long, long long, unsigned long long, float, double,
+ // long double, char16_t, char32_t, and the IEEE 754r decimal and
+ // half-precision floating point types.
+ switch (Ty->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Bool:
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ return true;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ assert(false && "Should not see this type here!");
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ assert(false && "FIXME: Objective-C types are unsupported!");
+ }
+
+ // Silent gcc.
+ return false;
+}
+
+static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
+ if (!BuiltinTy)
+ return false;
+
+ // Check the qualifiers.
+ Qualifiers Quals = PointeeTy.getQualifiers();
+ Quals.removeConst();
+
+ if (!Quals.empty())
+ return false;
+
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+}
+
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
+ // Type info for builtin types is defined in the standard library.
+ if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+
+ // Type info for some pointer types to builtin types is defined in the
+ // standard library.
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return TypeInfoIsInStandardLibrary(PointerTy);
+
+ return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit. Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
+ ASTContext &Context = CGM.getContext();
+
+ // If RTTI is disabled, don't consider key functions.
+ if (!Context.getLangOptions().RTTI) return false;
+
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!RD->hasDefinition())
+ return false;
+
+ if (!RD->isDynamicClass())
+ return false;
+
+ return !CGM.getVTables().ShouldEmitVTableInThisTU(RD);
+ }
+
+ return false;
+}
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+static bool IsIncompleteClassType(const RecordType *RecordTy) {
+ return !RecordTy->getDecl()->isDefinition();
+}
+
+/// ContainsIncompleteClassType - Returns whether the given type contains an
+/// incomplete class type. This is true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whoise pointee type contains an
+/// incomplete class type.
+/// is an indirect or direct pointer to an incomplete class type.
+static bool ContainsIncompleteClassType(QualType Ty) {
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ if (IsIncompleteClassType(RecordTy))
+ return true;
+ }
+
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return ContainsIncompleteClassType(PointerTy->getPointeeType());
+
+ if (const MemberPointerType *MemberPointerTy =
+ dyn_cast<MemberPointerType>(Ty)) {
+ // Check if the class type is incomplete.
+ const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
+ if (IsIncompleteClassType(ClassType))
+ return true;
+
+ return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
+ }
+
+ return false;
+}
+
+/// getTypeInfoLinkage - Return the linkage that the type info and type info
+/// name constants should have for the given type.
+static llvm::GlobalVariable::LinkageTypes
+getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
+ // Itanium C++ ABI 2.9.5p7:
+ // In addition, it and all of the intermediate abi::__pointer_type_info
+ // structs in the chain down to the abi::__class_type_info for the
+ // incomplete class type must be prevented from resolving to the
+ // corresponding type_info structs for the complete class type, possibly
+ // by making them local static objects. Finally, a dummy class RTTI is
+ // generated for the incomplete type that will not resolve to the final
+ // complete class RTTI (because the latter need not exist), possibly by
+ // making it a local static object.
+ if (ContainsIncompleteClassType(Ty))
+ return llvm::GlobalValue::InternalLinkage;
+
+ switch (Ty->getLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return llvm::GlobalValue::InternalLinkage;
+
+ case ExternalLinkage:
+ if (!CGM.getLangOptions().RTTI) {
+ // RTTI is not enabled, which means that this type info struct is going
+ // to be used for exception handling. Give it linkonce_odr linkage.
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (RD->isDynamicClass())
+ return CGM.getVTableLinkage(RD);
+ }
+
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+}
+
+// CanUseSingleInheritance - Return whether the given record decl has a "single,
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
+ // Check the number of bases.
+ if (RD->getNumBases() != 1)
+ return false;
+
+ // Get the base.
+ CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+
+ // Check that the base is not virtual.
+ if (Base->isVirtual())
+ return false;
+
+ // Check that the base is public.
+ if (Base->getAccessSpecifier() != AS_public)
+ return false;
+
+ // Check that the class is dynamic iff the base is.
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseDecl->isEmpty() &&
+ BaseDecl->isDynamicClass() != RD->isDynamicClass())
+ return false;
+
+ return true;
+}
+
+void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
+ // abi::__class_type_info.
+ static const char * const ClassTypeInfo =
+ "_ZTVN10__cxxabiv117__class_type_infoE";
+ // abi::__si_class_type_info.
+ static const char * const SIClassTypeInfo =
+ "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ // abi::__vmi_class_type_info.
+ static const char * const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+
+ const char *VTableName = 0;
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical and dependent types shouldn't get here");
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ assert(false && "References shouldn't get here");
+
+ case Type::Builtin:
+ // GCC treats vector and complex types as fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ // FIXME: GCC treats block pointers as fundamental types?!
+ case Type::BlockPointer:
+ // abi::__fundamental_type_info.
+ VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
+ break;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // abi::__array_type_info.
+ VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // abi::__function_type_info.
+ VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
+ break;
+
+ case Type::Enum:
+ // abi::__enum_type_info.
+ VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ VTableName = ClassTypeInfo;
+ } else if (CanUseSingleInheritance(RD)) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = VMIClassTypeInfo;
+ }
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ // Ignore protocol qualifiers.
+ Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ VTableName = ClassTypeInfo;
+ break;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ // Fall through.
+
+ case Type::ObjCInterface:
+ if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = ClassTypeInfo;
+ }
+ break;
+
+ case Type::ObjCObjectPointer:
+ case Type::Pointer:
+ // abi::__pointer_type_info.
+ VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
+ break;
+
+ case Type::MemberPointer:
+ // abi::__pointer_to_member_type_info.
+ VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
+ break;
+ }
+
+ llvm::Constant *VTable =
+ CGM.getModule().getOrInsertGlobal(VTableName, Int8PtrTy);
+
+ const llvm::Type *PtrDiffTy =
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+ // The vtable address point is 2.
+ llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
+ VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, &Two, 1);
+ VTable = llvm::ConstantExpr::getBitCast(VTable, Int8PtrTy);
+
+ Fields.push_back(VTable);
+}
+
+// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures
+// from available_externally to the correct linkage if necessary. An example of
+// this is:
+//
+// struct A {
+// virtual void f();
+// };
+//
+// const std::type_info &g() {
+// return typeid(A);
+// }
+//
+// void A::f() { }
+//
+// When we're generating the typeid(A) expression, we do not yet know that
+// A's key function is defined in this translation unit, so we will give the
+// typeinfo and typename structures available_externally linkage. When A::f
+// forces the vtable to be generated, we need to change the linkage of the
+// typeinfo and typename structs, otherwise we'll end up with undefined
+// externals when linking.
+static void
+maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,
+ QualType Ty) {
+ // We're only interested in globals with available_externally linkage.
+ if (!GV->hasAvailableExternallyLinkage())
+ return;
+
+ // Get the real linkage for the type.
+ llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // If variable is supposed to have available_externally linkage, we don't
+ // need to do anything.
+ if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
+ return;
+
+ // Update the typeinfo linkage.
+ GV->setLinkage(Linkage);
+
+ // Get the typename global.
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);
+
+ assert(TypeNameGV->hasAvailableExternallyLinkage() &&
+ "Type name has different linkage from type info!");
+
+ // And update its linkage.
+ TypeNameGV->setLinkage(Linkage);
+}
+
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+ // We want to operate on the canonical type.
+ Ty = CGM.getContext().getCanonicalType(Ty);
+
+ // Check if we've already emitted an RTTI descriptor for this type.
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
+ if (OldGV && !OldGV->isDeclaration()) {
+ maybeUpdateRTTILinkage(CGM, OldGV, Ty);
+
+ return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy);
+ }
+
+ // Check if there is already an external RTTI descriptor for this type.
+ bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+ if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
+ return GetAddrOfExternalRTTIDescriptor(Ty);
+
+ // Emit the standard library with external linkage.
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (IsStdLib)
+ Linkage = llvm::GlobalValue::ExternalLinkage;
+ else
+ Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // Add the vtable pointer.
+ BuildVTablePointer(cast<Type>(Ty));
+
+ // And the name.
+ llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, Int8PtrTy));
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical and dependent types shouldn't get here");
+
+ // GCC treats vector types as fundamental types.
+ case Type::Builtin:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ case Type::BlockPointer:
+ // Itanium C++ ABI 2.9.5p4:
+ // abi::__fundamental_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ assert(false && "References shouldn't get here");
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__array_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__function_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Enum:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__enum_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ // We don't need to emit any fields.
+ break;
+ }
+
+ if (CanUseSingleInheritance(RD))
+ BuildSIClassTypeInfo(RD);
+ else
+ BuildVMIClassTypeInfo(RD);
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
+ break;
+
+ case Type::ObjCObjectPointer:
+ BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::Pointer:
+ BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::MemberPointer:
+ BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
+ break;
+ }
+
+ llvm::Constant *Init =
+ llvm::ConstantStruct::get(VMContext, &Fields[0], Fields.size(),
+ /*Packed=*/false);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*Constant=*/true, Linkage, Init, Name);
+
+ // If there's already an old global variable, replace it with the new one.
+ if (OldGV) {
+ GV->takeName(OldGV);
+ llvm::Constant *NewPtr =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtr);
+ OldGV->eraseFromParent();
+ }
+
+ // GCC only relies on the uniqueness of the type names, not the
+ // type_infos themselves, so we can emit these as hidden symbols.
+ // But don't do this if we're worried about strict visibility
+ // compatibility.
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI);
+ CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName);
+ } else {
+ Visibility TypeInfoVisibility = DefaultVisibility;
+ if (CGM.getCodeGenOpts().HiddenWeakVTables &&
+ Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
+ TypeInfoVisibility = HiddenVisibility;
+
+ // The type name should have the same visibility as the type itself.
+ Visibility ExplicitVisibility = Ty->getVisibility();
+ TypeName->setVisibility(CodeGenModule::
+ GetLLVMVisibility(ExplicitVisibility));
+
+ TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility());
+ GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility));
+ }
+
+ GV->setUnnamedAddr(true);
+
+ return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
+}
+
+/// ComputeQualifierFlags - Compute the pointer type info flags from the
+/// given qualifier.
+static unsigned ComputeQualifierFlags(Qualifiers Quals) {
+ unsigned Flags = 0;
+
+ if (Quals.hasConst())
+ Flags |= RTTIBuilder::PTI_Const;
+ if (Quals.hasVolatile())
+ Flags |= RTTIBuilder::PTI_Volatile;
+ if (Quals.hasRestrict())
+ Flags |= RTTIBuilder::PTI_Restrict;
+
+ return Flags;
+}
+
+/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
+/// for the given Objective-C object type.
+void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+ // Drop qualifiers.
+ const Type *T = OT->getBaseType().getTypePtr();
+ assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
+
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T)) return;
+
+ ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
+ ObjCInterfaceDecl *Super = Class->getSuperClass();
+
+ // Root classes are also __class_type_info.
+ if (!Super) return;
+
+ QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
+
+ // Everything else is single inheritance.
+ llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
+ Fields.push_back(BaseTypeInfo);
+}
+
+/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
+void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+ // Itanium C++ ABI 2.9.5p6b:
+ // It adds to abi::__class_type_info a single member pointing to the
+ // type_info structure for the base type,
+ llvm::Constant *BaseTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
+ Fields.push_back(BaseTypeInfo);
+}
+
+namespace {
+ /// SeenBases - Contains virtual and non-virtual bases seen when traversing
+ /// a class hierarchy.
+ struct SeenBases {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+ };
+}
+
+/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
+/// abi::__vmi_class_type_info.
+///
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases) {
+
+ unsigned Flags = 0;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isVirtual()) {
+ if (Bases.VirtualBases.count(BaseDecl)) {
+ // If this virtual base has been seen before, then the class is diamond
+ // shaped.
+ Flags |= RTTIBuilder::VMI_DiamondShaped;
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl))
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+
+ // Mark the virtual base as seen.
+ Bases.VirtualBases.insert(BaseDecl);
+ }
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl)) {
+ // If this non-virtual base has been seen before, then the class has non-
+ // diamond shaped repeated inheritance.
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ } else {
+ if (Bases.VirtualBases.count(BaseDecl))
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+
+ // Mark the non-virtual base as seen.
+ Bases.NonVirtualBases.insert(BaseDecl);
+ }
+ }
+
+ // Walk all bases.
+ for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(),
+ E = BaseDecl->bases_end(); I != E; ++I)
+ Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
+
+ return Flags;
+}
+
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
+ unsigned Flags = 0;
+ SeenBases Bases;
+
+ // Walk all bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I)
+ Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
+
+ return Flags;
+}
+
+/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+/// classes with bases that do not satisfy the abi::__si_class_type_info
+/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
+ const llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __flags is a word with flags describing details about the class
+ // structure, which may be referenced by using the __flags_masks
+ // enumeration. These flags refer to both direct and indirect bases.
+ unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_count is a word with the number of direct proper base class
+ // descriptions that follow.
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
+
+ if (!RD->getNumBases())
+ return;
+
+ const llvm::Type *LongLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy);
+
+ // Now add the base class descriptions.
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_info[] is an array of base class descriptions -- one for every
+ // direct proper base. Each description is of the type:
+ //
+ // struct abi::__base_class_type_info {
+ // public:
+ // const __class_type_info *__base_type;
+ // long __offset_flags;
+ //
+ // enum __offset_flags_masks {
+ // __virtual_mask = 0x1,
+ // __public_mask = 0x2,
+ // __offset_shift = 8
+ // };
+ // };
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXBaseSpecifier *Base = I;
+
+ // The __base_type member points to the RTTI for the base type.
+ Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType()));
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ int64_t OffsetFlags = 0;
+
+ // All but the lower 8 bits of __offset_flags are a signed offset.
+ // For a non-virtual base, this is the offset in the object of the base
+ // subobject. For a virtual base, this is the offset in the virtual table of
+ // the virtual base offset for the virtual base referenced (negative).
+ if (Base->isVirtual())
+ OffsetFlags = CGM.getVTables().getVirtualBaseOffsetOffset(RD, BaseDecl);
+ else {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ OffsetFlags = Layout.getBaseClassOffsetInBits(BaseDecl) / 8;
+ };
+
+ OffsetFlags <<= 8;
+
+ // The low-order byte of __offset_flags contains flags, as given by the
+ // masks from the enumeration __offset_flags_masks.
+ if (Base->isVirtual())
+ OffsetFlags |= BCTI_Virtual;
+ if (Base->getAccessSpecifier() == AS_public)
+ OffsetFlags |= BCTI_Public;
+
+ Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
+ }
+}
+
+/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
+/// used for pointer types.
+void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ const llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+}
+
+/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+/// struct, used for member pointer types.
+void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+ QualType PointeeTy = Ty->getPointeeType();
+
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to.
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ const RecordType *ClassType = cast<RecordType>(Ty->getClass());
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ if (IsIncompleteClassType(ClassType))
+ Flags |= PTI_ContainingClassIncomplete;
+
+ const llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+
+ // Itanium C++ ABI 2.9.5p9:
+ // __context is a pointer to an abi::__class_type_info corresponding to the
+ // class type containing the member pointed to
+ // (e.g., the "A" in "int A::*").
+ Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
+}
+
+llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
+ bool ForEH) {
+ // Return a bogus pointer if RTTI is disabled, unless it's for EH.
+ // FIXME: should we even be calling this method if RTTI is disabled
+ // and it's not for EH?
+ if (!ForEH && !getContext().getLangOptions().RTTI) {
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ return llvm::Constant::getNullValue(Int8PtrTy);
+ }
+
+ return RTTIBuilder(*this).BuildTypeInfo(Ty);
+}
+
+void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
+ QualType PointerType = Context.getPointerType(Type);
+ QualType PointerTypeConst = Context.getPointerType(Type.withConst());
+ RTTIBuilder(*this).BuildTypeInfo(Type, true);
+ RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
+ RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+}
+
+void CodeGenModule::EmitFundamentalRTTIDescriptors() {
+ QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,
+ Context.BoolTy, Context.WCharTy,
+ Context.CharTy, Context.UnsignedCharTy,
+ Context.SignedCharTy, Context.ShortTy,
+ Context.UnsignedShortTy, Context.IntTy,
+ Context.UnsignedIntTy, Context.LongTy,
+ Context.UnsignedLongTy, Context.LongLongTy,
+ Context.UnsignedLongLongTy, Context.FloatTy,
+ Context.DoubleTy, Context.LongDoubleTy,
+ Context.Char16Ty, Context.Char32Ty };
+ for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)
+ EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
new file mode 100644
index 0000000..30da05f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayout.h
@@ -0,0 +1,279 @@
+//===--- CGRecordLayout.h - LLVM Record Layout Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGRECORDLAYOUT_H
+#define CLANG_CODEGEN_CGRECORDLAYOUT_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DerivedTypes.h"
+#include "clang/AST/Decl.h"
+namespace llvm {
+ class raw_ostream;
+ class StructType;
+}
+
+namespace clang {
+namespace CodeGen {
+
+/// \brief Helper object for describing how to generate the code for access to a
+/// bit-field.
+///
+/// This structure is intended to describe the "policy" of how the bit-field
+/// should be accessed, which may be target, language, or ABI dependent.
+class CGBitFieldInfo {
+public:
+ /// Descriptor for a single component of a bit-field access. The entire
+ /// bit-field is constituted of a bitwise OR of all of the individual
+ /// components.
+ ///
+ /// Each component describes an accessed value, which is how the component
+ /// should be transferred to/from memory, and a target placement, which is how
+ /// that component fits into the constituted bit-field. The pseudo-IR for a
+ /// load is:
+ ///
+ /// %0 = gep %base, 0, FieldIndex
+ /// %1 = gep (i8*) %0, FieldByteOffset
+ /// %2 = (i(AccessWidth) *) %1
+ /// %3 = load %2, align AccessAlignment
+ /// %4 = shr %3, FieldBitStart
+ ///
+ /// and the composed bit-field is formed as the boolean OR of all accesses,
+ /// masked to TargetBitWidth bits and shifted to TargetBitOffset.
+ struct AccessInfo {
+ /// Offset of the field to load in the LLVM structure, if any.
+ unsigned FieldIndex;
+
+ /// Byte offset from the field address, if any. This should generally be
+ /// unused as the cleanest IR comes from having a well-constructed LLVM type
+ /// with proper GEP instructions, but sometimes its use is required, for
+ /// example if an access is intended to straddle an LLVM field boundary.
+ unsigned FieldByteOffset;
+
+ /// Bit offset in the accessed value to use. The width is implied by \see
+ /// TargetBitWidth.
+ unsigned FieldBitStart;
+
+ /// Bit width of the memory access to perform.
+ unsigned AccessWidth;
+
+ /// The alignment of the memory access, or 0 if the default alignment should
+ /// be used.
+ //
+ // FIXME: Remove use of 0 to encode default, instead have IRgen do the right
+ // thing when it generates the code, if avoiding align directives is
+ // desired.
+ unsigned AccessAlignment;
+
+ /// Offset for the target value.
+ unsigned TargetBitOffset;
+
+ /// Number of bits in the access that are destined for the bit-field.
+ unsigned TargetBitWidth;
+ };
+
+private:
+ /// The components to use to access the bit-field. We may need up to three
+ /// separate components to support up to i64 bit-field access (4 + 2 + 1 byte
+ /// accesses).
+ //
+ // FIXME: De-hardcode this, just allocate following the struct.
+ AccessInfo Components[3];
+
+ /// The total size of the bit-field, in bits.
+ unsigned Size;
+
+ /// The number of access components to use.
+ unsigned NumComponents;
+
+ /// Whether the bit-field is signed.
+ bool IsSigned : 1;
+
+public:
+ CGBitFieldInfo(unsigned Size, unsigned NumComponents, AccessInfo *_Components,
+ bool IsSigned) : Size(Size), NumComponents(NumComponents),
+ IsSigned(IsSigned) {
+ assert(NumComponents <= 3 && "invalid number of components!");
+ for (unsigned i = 0; i != NumComponents; ++i)
+ Components[i] = _Components[i];
+
+ // Check some invariants.
+ unsigned AccessedSize = 0;
+ for (unsigned i = 0, e = getNumComponents(); i != e; ++i) {
+ const AccessInfo &AI = getComponent(i);
+ AccessedSize += AI.TargetBitWidth;
+
+ // We shouldn't try to load 0 bits.
+ assert(AI.TargetBitWidth > 0);
+
+ // We can't load more bits than we accessed.
+ assert(AI.FieldBitStart + AI.TargetBitWidth <= AI.AccessWidth);
+
+ // We shouldn't put any bits outside the result size.
+ assert(AI.TargetBitWidth + AI.TargetBitOffset <= Size);
+ }
+
+ // Check that the total number of target bits matches the total bit-field
+ // size.
+ assert(AccessedSize == Size && "Total size does not match accessed size!");
+ }
+
+public:
+ /// \brief Check whether this bit-field access is (i.e., should be sign
+ /// extended on loads).
+ bool isSigned() const { return IsSigned; }
+
+ /// \brief Get the size of the bit-field, in bits.
+ unsigned getSize() const { return Size; }
+
+ /// @name Component Access
+ /// @{
+
+ unsigned getNumComponents() const { return NumComponents; }
+
+ const AccessInfo &getComponent(unsigned Index) const {
+ assert(Index < getNumComponents() && "Invalid access!");
+ return Components[Index];
+ }
+
+ /// @}
+
+ void print(llvm::raw_ostream &OS) const;
+ void dump() const;
+
+ /// \brief Given a bit-field decl, build an appropriate helper object for
+ /// accessing that field (which is expected to have the given offset and
+ /// size).
+ static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types, const FieldDecl *FD,
+ uint64_t FieldOffset, uint64_t FieldSize);
+
+ /// \brief Given a bit-field decl, build an appropriate helper object for
+ /// accessing that field (which is expected to have the given offset and
+ /// size). The field decl should be known to be contained within a type of at
+ /// least the given size and with the given alignment.
+ static CGBitFieldInfo MakeInfo(CodeGenTypes &Types, const FieldDecl *FD,
+ uint64_t FieldOffset, uint64_t FieldSize,
+ uint64_t ContainingTypeSizeInBits,
+ unsigned ContainingTypeAlign);
+};
+
+/// CGRecordLayout - This class handles struct and union layout info while
+/// lowering AST types to LLVM types.
+///
+/// These layout objects are only created on demand as IR generation requires.
+class CGRecordLayout {
+ friend class CodeGenTypes;
+
+ CGRecordLayout(const CGRecordLayout&); // DO NOT IMPLEMENT
+ void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT
+
+private:
+ /// The LLVM type corresponding to this record layout; used when
+ /// laying it out as a complete object.
+ llvm::PATypeHolder CompleteObjectType;
+
+ /// The LLVM type for the non-virtual part of this record layout;
+ /// used when laying it out as a base subobject.
+ llvm::PATypeHolder BaseSubobjectType;
+
+ /// Map from (non-bit-field) struct field to the corresponding llvm struct
+ /// type field no. This info is populated by record builder.
+ llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo;
+
+ /// Map from (bit-field) struct field to the corresponding llvm struct type
+ /// field no. This info is populated by record builder.
+ llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
+
+ // FIXME: Maybe we could use a CXXBaseSpecifier as the key and use a single
+ // map for both virtual and non virtual bases.
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
+
+ /// Map from virtual bases to their field index in the complete object.
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> CompleteObjectVirtualBases;
+
+ /// False if any direct or indirect subobject of this class, when
+ /// considered as a complete object, requires a non-zero bitpattern
+ /// when zero-initialized.
+ bool IsZeroInitializable : 1;
+
+ /// False if any direct or indirect subobject of this class, when
+ /// considered as a base subobject, requires a non-zero bitpattern
+ /// when zero-initialized.
+ bool IsZeroInitializableAsBase : 1;
+
+public:
+ CGRecordLayout(const llvm::StructType *CompleteObjectType,
+ const llvm::StructType *BaseSubobjectType,
+ bool IsZeroInitializable,
+ bool IsZeroInitializableAsBase)
+ : CompleteObjectType(CompleteObjectType),
+ BaseSubobjectType(BaseSubobjectType),
+ IsZeroInitializable(IsZeroInitializable),
+ IsZeroInitializableAsBase(IsZeroInitializableAsBase) {}
+
+ /// \brief Return the "complete object" LLVM type associated with
+ /// this record.
+ const llvm::StructType *getLLVMType() const {
+ return cast<llvm::StructType>(CompleteObjectType.get());
+ }
+
+ /// \brief Return the "base subobject" LLVM type associated with
+ /// this record.
+ const llvm::StructType *getBaseSubobjectLLVMType() const {
+ return cast<llvm::StructType>(BaseSubobjectType.get());
+ }
+
+ /// \brief Check whether this struct can be C++ zero-initialized
+ /// with a zeroinitializer.
+ bool isZeroInitializable() const {
+ return IsZeroInitializable;
+ }
+
+ /// \brief Check whether this struct can be C++ zero-initialized
+ /// with a zeroinitializer when considered as a base subobject.
+ bool isZeroInitializableAsBase() const {
+ return IsZeroInitializableAsBase;
+ }
+
+ /// \brief Return llvm::StructType element number that corresponds to the
+ /// field FD.
+ unsigned getLLVMFieldNo(const FieldDecl *FD) const {
+ assert(!FD->isBitField() && "Invalid call for bit-field decl!");
+ assert(FieldInfo.count(FD) && "Invalid field for record!");
+ return FieldInfo.lookup(FD);
+ }
+
+ unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const {
+ assert(NonVirtualBases.count(RD) && "Invalid non-virtual base!");
+ return NonVirtualBases.lookup(RD);
+ }
+
+ /// \brief Return the LLVM field index corresponding to the given
+ /// virtual base. Only valid when operating on the complete object.
+ unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const {
+ assert(CompleteObjectVirtualBases.count(base) && "Invalid virtual base!");
+ return CompleteObjectVirtualBases.lookup(base);
+ }
+
+ /// \brief Return the BitFieldInfo that corresponds to the field FD.
+ const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const {
+ assert(FD->isBitField() && "Invalid call for non bit-field decl!");
+ llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator
+ it = BitFields.find(FD);
+ assert(it != BitFields.end() && "Unable to find bitfield info");
+ return it->second;
+ }
+
+ void print(llvm::raw_ostream &OS) const;
+ void dump() const;
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
new file mode 100644
index 0000000..4b19aef
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -0,0 +1,998 @@
+//===--- CGRecordLayoutBuilder.cpp - CGRecordLayout builder ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Builder implementation for CGRecordLayout objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGRecordLayout.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "CodeGenTypes.h"
+#include "CGCXXABI.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Type.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+
+class CGRecordLayoutBuilder {
+public:
+ /// FieldTypes - Holds the LLVM types that the struct is created from.
+ ///
+ std::vector<const llvm::Type *> FieldTypes;
+
+ /// BaseSubobjectType - Holds the LLVM type for the non-virtual part
+ /// of the struct. For example, consider:
+ ///
+ /// struct A { int i; };
+ /// struct B { void *v; };
+ /// struct C : virtual A, B { };
+ ///
+ /// The LLVM type of C will be
+ /// %struct.C = type { i32 (...)**, %struct.A, i32, %struct.B }
+ ///
+ /// And the LLVM type of the non-virtual base struct will be
+ /// %struct.C.base = type { i32 (...)**, %struct.A, i32 }
+ ///
+ /// This only gets initialized if the base subobject type is
+ /// different from the complete-object type.
+ const llvm::StructType *BaseSubobjectType;
+
+ /// FieldInfo - Holds a field and its corresponding LLVM field number.
+ llvm::DenseMap<const FieldDecl *, unsigned> Fields;
+
+ /// BitFieldInfo - Holds location and size information about a bit field.
+ llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
+
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
+
+ /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
+ /// primary base classes for some other direct or indirect base class.
+ CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
+
+ /// LaidOutVirtualBases - A set of all laid out virtual bases, used to avoid
+ /// avoid laying out virtual bases more than once.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> LaidOutVirtualBases;
+
+ /// IsZeroInitializable - Whether this struct can be C++
+ /// zero-initialized with an LLVM zeroinitializer.
+ bool IsZeroInitializable;
+ bool IsZeroInitializableAsBase;
+
+ /// Packed - Whether the resulting LLVM struct will be packed or not.
+ bool Packed;
+
+private:
+ CodeGenTypes &Types;
+
+ /// Alignment - Contains the alignment of the RecordDecl.
+ //
+ // FIXME: This is not needed and should be removed.
+ CharUnits Alignment;
+
+ /// BitsAvailableInLastField - If a bit field spans only part of a LLVM field,
+ /// this will have the number of bits still available in the field.
+ char BitsAvailableInLastField;
+
+ /// NextFieldOffset - Holds the next field offset.
+ CharUnits NextFieldOffset;
+
+ /// LayoutUnionField - Will layout a field in an union and return the type
+ /// that the field will have.
+ const llvm::Type *LayoutUnionField(const FieldDecl *Field,
+ const ASTRecordLayout &Layout);
+
+ /// LayoutUnion - Will layout a union RecordDecl.
+ void LayoutUnion(const RecordDecl *D);
+
+ /// LayoutField - try to layout all fields in the record decl.
+ /// Returns false if the operation failed because the struct is not packed.
+ bool LayoutFields(const RecordDecl *D);
+
+ /// Layout a single base, virtual or non-virtual
+ void LayoutBase(const CXXRecordDecl *base,
+ const CGRecordLayout &baseLayout,
+ CharUnits baseOffset);
+
+ /// LayoutVirtualBase - layout a single virtual base.
+ void LayoutVirtualBase(const CXXRecordDecl *base,
+ CharUnits baseOffset);
+
+ /// LayoutVirtualBases - layout the virtual bases of a record decl.
+ void LayoutVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout);
+
+ /// LayoutNonVirtualBase - layout a single non-virtual base.
+ void LayoutNonVirtualBase(const CXXRecordDecl *base,
+ CharUnits baseOffset);
+
+ /// LayoutNonVirtualBases - layout the virtual bases of a record decl.
+ void LayoutNonVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout);
+
+ /// ComputeNonVirtualBaseType - Compute the non-virtual base field types.
+ bool ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
+
+ /// LayoutField - layout a single field. Returns false if the operation failed
+ /// because the current struct is not packed.
+ bool LayoutField(const FieldDecl *D, uint64_t FieldOffset);
+
+ /// LayoutBitField - layout a single bit field.
+ void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset);
+
+ /// AppendField - Appends a field with the given offset and type.
+ void AppendField(CharUnits fieldOffset, const llvm::Type *FieldTy);
+
+ /// AppendPadding - Appends enough padding bytes so that the total
+ /// struct size is a multiple of the field alignment.
+ void AppendPadding(CharUnits fieldOffset, CharUnits fieldAlignment);
+
+ /// getByteArrayType - Returns a byte array type with the given number of
+ /// elements.
+ const llvm::Type *getByteArrayType(CharUnits NumBytes);
+
+ /// AppendBytes - Append a given number of bytes to the record.
+ void AppendBytes(CharUnits numBytes);
+
+ /// AppendTailPadding - Append enough tail padding so that the type will have
+ /// the passed size.
+ void AppendTailPadding(uint64_t RecordSize);
+
+ CharUnits getTypeAlignment(const llvm::Type *Ty) const;
+
+ /// getAlignmentAsLLVMStruct - Returns the maximum alignment of all the
+ /// LLVM element types.
+ CharUnits getAlignmentAsLLVMStruct() const;
+
+ /// CheckZeroInitializable - Check if the given type contains a pointer
+ /// to data member.
+ void CheckZeroInitializable(QualType T);
+
+public:
+ CGRecordLayoutBuilder(CodeGenTypes &Types)
+ : BaseSubobjectType(0),
+ IsZeroInitializable(true), IsZeroInitializableAsBase(true),
+ Packed(false), Types(Types), BitsAvailableInLastField(0) { }
+
+ /// Layout - Will layout a RecordDecl.
+ void Layout(const RecordDecl *D);
+};
+
+}
+
+void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
+ Alignment = Types.getContext().getASTRecordLayout(D).getAlignment();
+ Packed = D->hasAttr<PackedAttr>();
+
+ if (D->isUnion()) {
+ LayoutUnion(D);
+ return;
+ }
+
+ if (LayoutFields(D))
+ return;
+
+ // We weren't able to layout the struct. Try again with a packed struct
+ Packed = true;
+ NextFieldOffset = CharUnits::Zero();
+ FieldTypes.clear();
+ Fields.clear();
+ BitFields.clear();
+ NonVirtualBases.clear();
+ VirtualBases.clear();
+
+ LayoutFields(D);
+}
+
+CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
+ const FieldDecl *FD,
+ uint64_t FieldOffset,
+ uint64_t FieldSize,
+ uint64_t ContainingTypeSizeInBits,
+ unsigned ContainingTypeAlign) {
+ const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
+ uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
+ uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
+
+ bool IsSigned = FD->getType()->isSignedIntegerType();
+
+ if (FieldSize > TypeSizeInBits) {
+ // We have a wide bit-field. The extra bits are only used for padding, so
+ // if we have a bitfield of type T, with size N:
+ //
+ // T t : N;
+ //
+ // We can just assume that it's:
+ //
+ // T t : sizeof(T);
+ //
+ FieldSize = TypeSizeInBits;
+ }
+
+ // in big-endian machines the first fields are in higher bit positions,
+ // so revert the offset. The byte offsets are reversed(back) later.
+ if (Types.getTargetData().isBigEndian()) {
+ FieldOffset = ((ContainingTypeSizeInBits)-FieldOffset-FieldSize);
+ }
+
+ // Compute the access components. The policy we use is to start by attempting
+ // to access using the width of the bit-field type itself and to always access
+ // at aligned indices of that type. If such an access would fail because it
+ // extends past the bound of the type, then we reduce size to the next smaller
+ // power of two and retry. The current algorithm assumes pow2 sized types,
+ // although this is easy to fix.
+ //
+ assert(llvm::isPowerOf2_32(TypeSizeInBits) && "Unexpected type size!");
+ CGBitFieldInfo::AccessInfo Components[3];
+ unsigned NumComponents = 0;
+ unsigned AccessedTargetBits = 0; // The tumber of target bits accessed.
+ unsigned AccessWidth = TypeSizeInBits; // The current access width to attempt.
+
+ // Round down from the field offset to find the first access position that is
+ // at an aligned offset of the initial access type.
+ uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth);
+
+ // Adjust initial access size to fit within record.
+ while (AccessWidth > 8 &&
+ AccessStart + AccessWidth > ContainingTypeSizeInBits) {
+ AccessWidth >>= 1;
+ AccessStart = FieldOffset - (FieldOffset % AccessWidth);
+ }
+
+ while (AccessedTargetBits < FieldSize) {
+ // Check that we can access using a type of this size, without reading off
+ // the end of the structure. This can occur with packed structures and
+ // -fno-bitfield-type-align, for example.
+ if (AccessStart + AccessWidth > ContainingTypeSizeInBits) {
+ // If so, reduce access size to the next smaller power-of-two and retry.
+ AccessWidth >>= 1;
+ assert(AccessWidth >= 8 && "Cannot access under byte size!");
+ continue;
+ }
+
+ // Otherwise, add an access component.
+
+ // First, compute the bits inside this access which are part of the
+ // target. We are reading bits [AccessStart, AccessStart + AccessWidth); the
+ // intersection with [FieldOffset, FieldOffset + FieldSize) gives the bits
+ // in the target that we are reading.
+ assert(FieldOffset < AccessStart + AccessWidth && "Invalid access start!");
+ assert(AccessStart < FieldOffset + FieldSize && "Invalid access start!");
+ uint64_t AccessBitsInFieldStart = std::max(AccessStart, FieldOffset);
+ uint64_t AccessBitsInFieldSize =
+ std::min(AccessWidth + AccessStart,
+ FieldOffset + FieldSize) - AccessBitsInFieldStart;
+
+ assert(NumComponents < 3 && "Unexpected number of components!");
+ CGBitFieldInfo::AccessInfo &AI = Components[NumComponents++];
+ AI.FieldIndex = 0;
+ // FIXME: We still follow the old access pattern of only using the field
+ // byte offset. We should switch this once we fix the struct layout to be
+ // pretty.
+
+ // on big-endian machines we reverted the bit offset because first fields are
+ // in higher bits. But this also reverts the bytes, so fix this here by reverting
+ // the byte offset on big-endian machines.
+ if (Types.getTargetData().isBigEndian()) {
+ AI.FieldByteOffset = (ContainingTypeSizeInBits - AccessStart - AccessWidth )/8;
+ } else {
+ AI.FieldByteOffset = AccessStart / 8;
+ }
+ AI.FieldBitStart = AccessBitsInFieldStart - AccessStart;
+ AI.AccessWidth = AccessWidth;
+ AI.AccessAlignment = llvm::MinAlign(ContainingTypeAlign, AccessStart) / 8;
+ AI.TargetBitOffset = AccessedTargetBits;
+ AI.TargetBitWidth = AccessBitsInFieldSize;
+
+ AccessStart += AccessWidth;
+ AccessedTargetBits += AI.TargetBitWidth;
+ }
+
+ assert(AccessedTargetBits == FieldSize && "Invalid bit-field access!");
+ return CGBitFieldInfo(FieldSize, NumComponents, Components, IsSigned);
+}
+
+CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
+ const FieldDecl *FD,
+ uint64_t FieldOffset,
+ uint64_t FieldSize) {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Types.getContext().getASTRecordLayout(RD);
+ uint64_t ContainingTypeSizeInBits = Types.getContext().toBits(RL.getSize());
+ unsigned ContainingTypeAlign = Types.getContext().toBits(RL.getAlignment());
+
+ return MakeInfo(Types, FD, FieldOffset, FieldSize, ContainingTypeSizeInBits,
+ ContainingTypeAlign);
+}
+
+void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
+ uint64_t fieldOffset) {
+ uint64_t fieldSize =
+ D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
+
+ if (fieldSize == 0)
+ return;
+
+ uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8;
+ unsigned numBytesToAppend;
+
+ if (fieldOffset < nextFieldOffsetInBits) {
+ assert(BitsAvailableInLastField && "Bitfield size mismatch!");
+ assert(!NextFieldOffset.isZero() && "Must have laid out at least one byte");
+
+ // The bitfield begins in the previous bit-field.
+ numBytesToAppend =
+ llvm::RoundUpToAlignment(fieldSize - BitsAvailableInLastField, 8) / 8;
+ } else {
+ assert(fieldOffset % 8 == 0 && "Field offset not aligned correctly");
+
+ // Append padding if necessary.
+ AppendPadding(CharUnits::fromQuantity(fieldOffset / 8), CharUnits::One());
+
+ numBytesToAppend = llvm::RoundUpToAlignment(fieldSize, 8) / 8;
+
+ assert(numBytesToAppend && "No bytes to append!");
+ }
+
+ // Add the bit field info.
+ BitFields.insert(std::make_pair(D,
+ CGBitFieldInfo::MakeInfo(Types, D, fieldOffset, fieldSize)));
+
+ AppendBytes(CharUnits::fromQuantity(numBytesToAppend));
+
+ BitsAvailableInLastField =
+ NextFieldOffset.getQuantity() * 8 - (fieldOffset + fieldSize);
+}
+
+bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
+ uint64_t fieldOffset) {
+ // If the field is packed, then we need a packed struct.
+ if (!Packed && D->hasAttr<PackedAttr>())
+ return false;
+
+ if (D->isBitField()) {
+ // We must use packed structs for unnamed bit fields since they
+ // don't affect the struct alignment.
+ if (!Packed && !D->getDeclName())
+ return false;
+
+ LayoutBitField(D, fieldOffset);
+ return true;
+ }
+
+ CheckZeroInitializable(D->getType());
+
+ assert(fieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
+ CharUnits fieldOffsetInBytes = CharUnits::fromQuantity(fieldOffset / 8);
+
+ const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
+ CharUnits typeAlignment = getTypeAlignment(Ty);
+
+ // If the type alignment is larger then the struct alignment, we must use
+ // a packed struct.
+ if (typeAlignment > Alignment) {
+ assert(!Packed && "Alignment is wrong even with packed struct!");
+ return false;
+ }
+
+ if (!Packed) {
+ if (const RecordType *RT = D->getType()->getAs<RecordType>()) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (const MaxFieldAlignmentAttr *MFAA =
+ RD->getAttr<MaxFieldAlignmentAttr>()) {
+ if (MFAA->getAlignment() != typeAlignment.getQuantity() * 8)
+ return false;
+ }
+ }
+ }
+
+ // Round up the field offset to the alignment of the field type.
+ CharUnits alignedNextFieldOffsetInBytes =
+ NextFieldOffset.RoundUpToAlignment(typeAlignment);
+
+ if (fieldOffsetInBytes < alignedNextFieldOffsetInBytes) {
+ assert(!Packed && "Could not place field even with packed struct!");
+ return false;
+ }
+
+ AppendPadding(fieldOffsetInBytes, typeAlignment);
+
+ // Now append the field.
+ Fields[D] = FieldTypes.size();
+ AppendField(fieldOffsetInBytes, Ty);
+
+ return true;
+}
+
+const llvm::Type *
+CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field,
+ const ASTRecordLayout &Layout) {
+ if (Field->isBitField()) {
+ uint64_t FieldSize =
+ Field->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
+
+ // Ignore zero sized bit fields.
+ if (FieldSize == 0)
+ return 0;
+
+ const llvm::Type *FieldTy = llvm::Type::getInt8Ty(Types.getLLVMContext());
+ unsigned NumBytesToAppend =
+ llvm::RoundUpToAlignment(FieldSize, 8) / 8;
+
+ if (NumBytesToAppend > 1)
+ FieldTy = llvm::ArrayType::get(FieldTy, NumBytesToAppend);
+
+ // Add the bit field info.
+ BitFields.insert(std::make_pair(Field,
+ CGBitFieldInfo::MakeInfo(Types, Field, 0, FieldSize)));
+ return FieldTy;
+ }
+
+ // This is a regular union field.
+ Fields[Field] = 0;
+ return Types.ConvertTypeForMemRecursive(Field->getType());
+}
+
+void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
+ assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!");
+
+ const ASTRecordLayout &layout = Types.getContext().getASTRecordLayout(D);
+
+ const llvm::Type *unionType = 0;
+ CharUnits unionSize = CharUnits::Zero();
+ CharUnits unionAlign = CharUnits::Zero();
+
+ bool hasOnlyZeroSizedBitFields = true;
+
+ unsigned fieldNo = 0;
+ for (RecordDecl::field_iterator field = D->field_begin(),
+ fieldEnd = D->field_end(); field != fieldEnd; ++field, ++fieldNo) {
+ assert(layout.getFieldOffset(fieldNo) == 0 &&
+ "Union field offset did not start at the beginning of record!");
+ const llvm::Type *fieldType = LayoutUnionField(*field, layout);
+
+ if (!fieldType)
+ continue;
+
+ hasOnlyZeroSizedBitFields = false;
+
+ CharUnits fieldAlign = CharUnits::fromQuantity(
+ Types.getTargetData().getABITypeAlignment(fieldType));
+ CharUnits fieldSize = CharUnits::fromQuantity(
+ Types.getTargetData().getTypeAllocSize(fieldType));
+
+ if (fieldAlign < unionAlign)
+ continue;
+
+ if (fieldAlign > unionAlign || fieldSize > unionSize) {
+ unionType = fieldType;
+ unionAlign = fieldAlign;
+ unionSize = fieldSize;
+ }
+ }
+
+ // Now add our field.
+ if (unionType) {
+ AppendField(CharUnits::Zero(), unionType);
+
+ if (getTypeAlignment(unionType) > layout.getAlignment()) {
+ // We need a packed struct.
+ Packed = true;
+ unionAlign = CharUnits::One();
+ }
+ }
+ if (unionAlign.isZero()) {
+ assert(hasOnlyZeroSizedBitFields &&
+ "0-align record did not have all zero-sized bit-fields!");
+ unionAlign = CharUnits::One();
+ }
+
+ // Append tail padding.
+ CharUnits recordSize = layout.getSize();
+ if (recordSize > unionSize)
+ AppendPadding(recordSize, unionAlign);
+}
+
+void CGRecordLayoutBuilder::LayoutBase(const CXXRecordDecl *base,
+ const CGRecordLayout &baseLayout,
+ CharUnits baseOffset) {
+ AppendPadding(baseOffset, CharUnits::One());
+
+ const ASTRecordLayout &baseASTLayout
+ = Types.getContext().getASTRecordLayout(base);
+
+ // Fields and bases can be laid out in the tail padding of previous
+ // bases. If this happens, we need to allocate the base as an i8
+ // array; otherwise, we can use the subobject type. However,
+ // actually doing that would require knowledge of what immediately
+ // follows this base in the layout, so instead we do a conservative
+ // approximation, which is to use the base subobject type if it
+ // has the same LLVM storage size as the nvsize.
+
+ // The nvsize, i.e. the unpadded size of the base class.
+ CharUnits nvsize = baseASTLayout.getNonVirtualSize();
+
+#if 0
+ const llvm::StructType *subobjectType = baseLayout.getBaseSubobjectLLVMType();
+ const llvm::StructLayout *baseLLVMLayout =
+ Types.getTargetData().getStructLayout(subobjectType);
+ CharUnits stsize = CharUnits::fromQuantity(baseLLVMLayout->getSizeInBytes());
+
+ if (nvsize == stsize)
+ AppendField(baseOffset, subobjectType);
+ else
+#endif
+ AppendBytes(nvsize);
+}
+
+void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *base,
+ CharUnits baseOffset) {
+ // Ignore empty bases.
+ if (base->isEmpty()) return;
+
+ const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base);
+ if (IsZeroInitializableAsBase) {
+ assert(IsZeroInitializable &&
+ "class zero-initializable as base but not as complete object");
+
+ IsZeroInitializable = IsZeroInitializableAsBase =
+ baseLayout.isZeroInitializableAsBase();
+ }
+
+ LayoutBase(base, baseLayout, baseOffset);
+ NonVirtualBases[base] = (FieldTypes.size() - 1);
+}
+
+void
+CGRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *base,
+ CharUnits baseOffset) {
+ // Ignore empty bases.
+ if (base->isEmpty()) return;
+
+ const CGRecordLayout &baseLayout = Types.getCGRecordLayout(base);
+ if (IsZeroInitializable)
+ IsZeroInitializable = baseLayout.isZeroInitializableAsBase();
+
+ LayoutBase(base, baseLayout, baseOffset);
+ VirtualBases[base] = (FieldTypes.size() - 1);
+}
+
+/// LayoutVirtualBases - layout the non-virtual bases of a record decl.
+void
+CGRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // We only want to lay out virtual bases that aren't indirect primary bases
+ // of some other base.
+ if (I->isVirtual() && !IndirectPrimaryBases.count(BaseDecl)) {
+ // Only lay out the base once.
+ if (!LaidOutVirtualBases.insert(BaseDecl))
+ continue;
+
+ CharUnits vbaseOffset = Layout.getVBaseClassOffset(BaseDecl);
+ LayoutVirtualBase(BaseDecl, vbaseOffset);
+ }
+
+ if (!BaseDecl->getNumVBases()) {
+ // This base isn't interesting since it doesn't have any virtual bases.
+ continue;
+ }
+
+ LayoutVirtualBases(BaseDecl, Layout);
+ }
+}
+
+void
+CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout) {
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ // Check if we need to add a vtable pointer.
+ if (RD->isDynamicClass()) {
+ if (!PrimaryBase) {
+ const llvm::Type *FunctionType =
+ llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()),
+ /*isVarArg=*/true);
+ const llvm::Type *VTableTy = FunctionType->getPointerTo();
+
+ assert(NextFieldOffset.isZero() &&
+ "VTable pointer must come first!");
+ AppendField(CharUnits::Zero(), VTableTy->getPointerTo());
+ } else {
+ if (!Layout.isPrimaryBaseVirtual())
+ LayoutNonVirtualBase(PrimaryBase, CharUnits::Zero());
+ else
+ LayoutVirtualBase(PrimaryBase, CharUnits::Zero());
+ }
+ }
+
+ // Layout the non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // We've already laid out the primary base.
+ if (BaseDecl == PrimaryBase && !Layout.isPrimaryBaseVirtual())
+ continue;
+
+ LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl));
+ }
+}
+
+bool
+CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
+ const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);
+
+ CharUnits NonVirtualSize = Layout.getNonVirtualSize();
+ CharUnits NonVirtualAlign = Layout.getNonVirtualAlign();
+ CharUnits AlignedNonVirtualTypeSize =
+ NonVirtualSize.RoundUpToAlignment(NonVirtualAlign);
+
+ // First check if we can use the same fields as for the complete class.
+ CharUnits RecordSize = Layout.getSize();
+ if (AlignedNonVirtualTypeSize == RecordSize)
+ return true;
+
+ // Check if we need padding.
+ CharUnits AlignedNextFieldOffset =
+ NextFieldOffset.RoundUpToAlignment(getAlignmentAsLLVMStruct());
+
+ if (AlignedNextFieldOffset > AlignedNonVirtualTypeSize) {
+ assert(!Packed && "cannot layout even as packed struct");
+ return false; // Needs packing.
+ }
+
+ bool needsPadding = (AlignedNonVirtualTypeSize != AlignedNextFieldOffset);
+ if (needsPadding) {
+ CharUnits NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset;
+ FieldTypes.push_back(getByteArrayType(NumBytes));
+ }
+
+ BaseSubobjectType = llvm::StructType::get(Types.getLLVMContext(),
+ FieldTypes, Packed);
+
+ if (needsPadding) {
+ // Pull the padding back off.
+ FieldTypes.pop_back();
+ }
+
+ return true;
+}
+
+bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
+ assert(!D->isUnion() && "Can't call LayoutFields on a union!");
+ assert(!Alignment.isZero() && "Did not set alignment!");
+
+ const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D);
+
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
+ if (RD)
+ LayoutNonVirtualBases(RD, Layout);
+
+ unsigned FieldNo = 0;
+
+ for (RecordDecl::field_iterator Field = D->field_begin(),
+ FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+ if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) {
+ assert(!Packed &&
+ "Could not layout fields even with a packed LLVM struct!");
+ return false;
+ }
+ }
+
+ if (RD) {
+ // We've laid out the non-virtual bases and the fields, now compute the
+ // non-virtual base field types.
+ if (!ComputeNonVirtualBaseType(RD)) {
+ assert(!Packed && "Could not layout even with a packed LLVM struct!");
+ return false;
+ }
+
+ // And lay out the virtual bases.
+ RD->getIndirectPrimaryBases(IndirectPrimaryBases);
+ if (Layout.isPrimaryBaseVirtual())
+ IndirectPrimaryBases.insert(Layout.getPrimaryBase());
+ LayoutVirtualBases(RD, Layout);
+ }
+
+ // Append tail padding if necessary.
+ AppendTailPadding(Types.getContext().toBits(Layout.getSize()));
+
+ return true;
+}
+
+void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
+ assert(RecordSize % 8 == 0 && "Invalid record size!");
+
+ CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8);
+ assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!");
+
+ CharUnits AlignedNextFieldOffset =
+ NextFieldOffset.RoundUpToAlignment(getAlignmentAsLLVMStruct());
+
+ if (AlignedNextFieldOffset == RecordSizeInBytes) {
+ // We don't need any padding.
+ return;
+ }
+
+ CharUnits NumPadBytes = RecordSizeInBytes - NextFieldOffset;
+ AppendBytes(NumPadBytes);
+}
+
+void CGRecordLayoutBuilder::AppendField(CharUnits fieldOffset,
+ const llvm::Type *fieldType) {
+ CharUnits fieldSize =
+ CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(fieldType));
+
+ FieldTypes.push_back(fieldType);
+
+ NextFieldOffset = fieldOffset + fieldSize;
+ BitsAvailableInLastField = 0;
+}
+
+void CGRecordLayoutBuilder::AppendPadding(CharUnits fieldOffset,
+ CharUnits fieldAlignment) {
+ assert(NextFieldOffset <= fieldOffset &&
+ "Incorrect field layout!");
+
+ // Round up the field offset to the alignment of the field type.
+ CharUnits alignedNextFieldOffset =
+ NextFieldOffset.RoundUpToAlignment(fieldAlignment);
+
+ if (alignedNextFieldOffset < fieldOffset) {
+ // Even with alignment, the field offset is not at the right place,
+ // insert padding.
+ CharUnits padding = fieldOffset - NextFieldOffset;
+
+ AppendBytes(padding);
+ }
+}
+
+const llvm::Type *CGRecordLayoutBuilder::getByteArrayType(CharUnits numBytes) {
+ assert(!numBytes.isZero() && "Empty byte arrays aren't allowed.");
+
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext());
+ if (numBytes > CharUnits::One())
+ Ty = llvm::ArrayType::get(Ty, numBytes.getQuantity());
+
+ return Ty;
+}
+
+void CGRecordLayoutBuilder::AppendBytes(CharUnits numBytes) {
+ if (numBytes.isZero())
+ return;
+
+ // Append the padding field
+ AppendField(NextFieldOffset, getByteArrayType(numBytes));
+}
+
+CharUnits CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
+ if (Packed)
+ return CharUnits::One();
+
+ return CharUnits::fromQuantity(Types.getTargetData().getABITypeAlignment(Ty));
+}
+
+CharUnits CGRecordLayoutBuilder::getAlignmentAsLLVMStruct() const {
+ if (Packed)
+ return CharUnits::One();
+
+ CharUnits maxAlignment = CharUnits::One();
+ for (size_t i = 0; i != FieldTypes.size(); ++i)
+ maxAlignment = std::max(maxAlignment, getTypeAlignment(FieldTypes[i]));
+
+ return maxAlignment;
+}
+
+/// Merge in whether a field of the given type is zero-initializable.
+void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) {
+ // This record already contains a member pointer.
+ if (!IsZeroInitializableAsBase)
+ return;
+
+ // Can only have member pointers if we're compiling C++.
+ if (!Types.getContext().getLangOptions().CPlusPlus)
+ return;
+
+ const Type *elementType = T->getBaseElementTypeUnsafe();
+
+ if (const MemberPointerType *MPT = elementType->getAs<MemberPointerType>()) {
+ if (!Types.getCXXABI().isZeroInitializable(MPT))
+ IsZeroInitializable = IsZeroInitializableAsBase = false;
+ } else if (const RecordType *RT = elementType->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
+ if (!Layout.isZeroInitializable())
+ IsZeroInitializable = IsZeroInitializableAsBase = false;
+ }
+}
+
+CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
+ CGRecordLayoutBuilder Builder(*this);
+
+ Builder.Layout(D);
+
+ const llvm::StructType *Ty = llvm::StructType::get(getLLVMContext(),
+ Builder.FieldTypes,
+ Builder.Packed);
+
+ // If we're in C++, compute the base subobject type.
+ const llvm::StructType *BaseTy = 0;
+ if (isa<CXXRecordDecl>(D)) {
+ BaseTy = Builder.BaseSubobjectType;
+ if (!BaseTy) BaseTy = Ty;
+ }
+
+ CGRecordLayout *RL =
+ new CGRecordLayout(Ty, BaseTy, Builder.IsZeroInitializable,
+ Builder.IsZeroInitializableAsBase);
+
+ RL->NonVirtualBases.swap(Builder.NonVirtualBases);
+ RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
+
+ // Add all the field numbers.
+ RL->FieldInfo.swap(Builder.Fields);
+
+ // Add bitfield info.
+ RL->BitFields.swap(Builder.BitFields);
+
+ // Dump the layout, if requested.
+ if (getContext().getLangOptions().DumpRecordLayouts) {
+ llvm::errs() << "\n*** Dumping IRgen Record Layout\n";
+ llvm::errs() << "Record: ";
+ D->dump();
+ llvm::errs() << "\nLayout: ";
+ RL->dump();
+ }
+
+#ifndef NDEBUG
+ // Verify that the computed LLVM struct size matches the AST layout size.
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(D);
+
+ uint64_t TypeSizeInBits = getContext().toBits(Layout.getSize());
+ assert(TypeSizeInBits == getTargetData().getTypeAllocSizeInBits(Ty) &&
+ "Type size mismatch!");
+
+ if (BaseTy) {
+ CharUnits NonVirtualSize = Layout.getNonVirtualSize();
+ CharUnits NonVirtualAlign = Layout.getNonVirtualAlign();
+ CharUnits AlignedNonVirtualTypeSize =
+ NonVirtualSize.RoundUpToAlignment(NonVirtualAlign);
+
+ uint64_t AlignedNonVirtualTypeSizeInBits =
+ getContext().toBits(AlignedNonVirtualTypeSize);
+
+ assert(AlignedNonVirtualTypeSizeInBits ==
+ getTargetData().getTypeAllocSizeInBits(BaseTy) &&
+ "Type size mismatch!");
+ }
+
+ // Verify that the LLVM and AST field offsets agree.
+ const llvm::StructType *ST =
+ dyn_cast<llvm::StructType>(RL->getLLVMType());
+ const llvm::StructLayout *SL = getTargetData().getStructLayout(ST);
+
+ const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
+ RecordDecl::field_iterator it = D->field_begin();
+ for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) {
+ const FieldDecl *FD = *it;
+
+ // For non-bit-fields, just check that the LLVM struct offset matches the
+ // AST offset.
+ if (!FD->isBitField()) {
+ unsigned FieldNo = RL->getLLVMFieldNo(FD);
+ assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
+ "Invalid field offset!");
+ continue;
+ }
+
+ // Ignore unnamed bit-fields.
+ if (!FD->getDeclName())
+ continue;
+
+ const CGBitFieldInfo &Info = RL->getBitFieldInfo(FD);
+ for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
+ const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
+
+ // Verify that every component access is within the structure.
+ uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex);
+ uint64_t AccessBitOffset = FieldOffset + AI.FieldByteOffset * 8;
+ assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits &&
+ "Invalid bit-field access (out of range)!");
+ }
+ }
+#endif
+
+ return RL;
+}
+
+void CGRecordLayout::print(llvm::raw_ostream &OS) const {
+ OS << "<CGRecordLayout\n";
+ OS << " LLVMType:" << *CompleteObjectType << "\n";
+ if (BaseSubobjectType)
+ OS << " NonVirtualBaseLLVMType:" << *BaseSubobjectType << "\n";
+ OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
+ OS << " BitFields:[\n";
+
+ // Print bit-field infos in declaration order.
+ std::vector<std::pair<unsigned, const CGBitFieldInfo*> > BFIs;
+ for (llvm::DenseMap<const FieldDecl*, CGBitFieldInfo>::const_iterator
+ it = BitFields.begin(), ie = BitFields.end();
+ it != ie; ++it) {
+ const RecordDecl *RD = it->first->getParent();
+ unsigned Index = 0;
+ for (RecordDecl::field_iterator
+ it2 = RD->field_begin(); *it2 != it->first; ++it2)
+ ++Index;
+ BFIs.push_back(std::make_pair(Index, &it->second));
+ }
+ llvm::array_pod_sort(BFIs.begin(), BFIs.end());
+ for (unsigned i = 0, e = BFIs.size(); i != e; ++i) {
+ OS.indent(4);
+ BFIs[i].second->print(OS);
+ OS << "\n";
+ }
+
+ OS << "]>\n";
+}
+
+void CGRecordLayout::dump() const {
+ print(llvm::errs());
+}
+
+void CGBitFieldInfo::print(llvm::raw_ostream &OS) const {
+ OS << "<CGBitFieldInfo";
+ OS << " Size:" << Size;
+ OS << " IsSigned:" << IsSigned << "\n";
+
+ OS.indent(4 + strlen("<CGBitFieldInfo"));
+ OS << " NumComponents:" << getNumComponents();
+ OS << " Components: [";
+ if (getNumComponents()) {
+ OS << "\n";
+ for (unsigned i = 0, e = getNumComponents(); i != e; ++i) {
+ const AccessInfo &AI = getComponent(i);
+ OS.indent(8);
+ OS << "<AccessInfo"
+ << " FieldIndex:" << AI.FieldIndex
+ << " FieldByteOffset:" << AI.FieldByteOffset
+ << " FieldBitStart:" << AI.FieldBitStart
+ << " AccessWidth:" << AI.AccessWidth << "\n";
+ OS.indent(8 + strlen("<AccessInfo"));
+ OS << " AccessAlignment:" << AI.AccessAlignment
+ << " TargetBitOffset:" << AI.TargetBitOffset
+ << " TargetBitWidth:" << AI.TargetBitWidth
+ << ">\n";
+ }
+ OS.indent(4);
+ }
+ OS << "]>";
+}
+
+void CGBitFieldInfo::dump() const {
+ print(llvm::errs());
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
new file mode 100644
index 0000000..cd23811
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
@@ -0,0 +1,1313 @@
+//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Stmt nodes as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
+#include "TargetInfo.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+//===----------------------------------------------------------------------===//
+// Statement Emission
+//===----------------------------------------------------------------------===//
+
+void CodeGenFunction::EmitStopPoint(const Stmt *S) {
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ if (isa<DeclStmt>(S))
+ DI->setLocation(S->getLocEnd());
+ else
+ DI->setLocation(S->getLocStart());
+ DI->UpdateLineDirectiveRegion(Builder);
+ DI->EmitStopPoint(Builder);
+ }
+}
+
+void CodeGenFunction::EmitStmt(const Stmt *S) {
+ assert(S && "Null statement?");
+
+ // Check if we can handle this without bothering to generate an
+ // insert point or debug info.
+ if (EmitSimpleStmt(S))
+ return;
+
+ // Check if we are generating unreachable code.
+ if (!HaveInsertPoint()) {
+ // If so, and the statement doesn't contain a label, then we do not need to
+ // generate actual code. This is safe because (1) the current point is
+ // unreachable, so we don't need to execute the code, and (2) we've already
+ // handled the statements which update internal data structures (like the
+ // local variable map) which could be used by subsequent statements.
+ if (!ContainsLabel(S)) {
+ // Verify that any decl statements were handled as simple, they may be in
+ // scope of subsequent reachable statements.
+ assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
+ return;
+ }
+
+ // Otherwise, make a new block to hold the code.
+ EnsureInsertPoint();
+ }
+
+ // Generate a stoppoint if we are emitting debug info.
+ EmitStopPoint(S);
+
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass:
+ case Stmt::CXXCatchStmtClass:
+ llvm_unreachable("invalid statement class to emit generically");
+ case Stmt::NullStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::DeclStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::BreakStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::CaseStmtClass:
+ llvm_unreachable("should have emitted these statements as simple");
+
+#define STMT(Type, Base)
+#define ABSTRACT_STMT(Op)
+#define EXPR(Type, Base) \
+ case Stmt::Type##Class:
+#include "clang/AST/StmtNodes.inc"
+ {
+ // Remember the block we came in on.
+ llvm::BasicBlock *incoming = Builder.GetInsertBlock();
+ assert(incoming && "expression emission must have an insertion point");
+
+ EmitIgnoredExpr(cast<Expr>(S));
+
+ llvm::BasicBlock *outgoing = Builder.GetInsertBlock();
+ assert(outgoing && "expression emission cleared block!");
+
+ // The expression emitters assume (reasonably!) that the insertion
+ // point is always set. To maintain that, the call-emission code
+ // for noreturn functions has to enter a new block with no
+ // predecessors. We want to kill that block and mark the current
+ // insertion point unreachable in the common case of a call like
+ // "exit();". Since expression emission doesn't otherwise create
+ // blocks with no predecessors, we can just test for that.
+ // However, we must be careful not to do this to our incoming
+ // block, because *statement* emission does sometimes create
+ // reachable blocks which will have no predecessors until later in
+ // the function. This occurs with, e.g., labels that are not
+ // reachable by fallthrough.
+ if (incoming != outgoing && outgoing->use_empty()) {
+ outgoing->eraseFromParent();
+ Builder.ClearInsertionPoint();
+ }
+ break;
+ }
+
+ case Stmt::IndirectGotoStmtClass:
+ EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
+
+ case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
+ case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
+ case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break;
+ case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
+
+ case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
+
+ case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
+ case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
+
+ case Stmt::ObjCAtTryStmtClass:
+ EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
+ break;
+ case Stmt::ObjCAtCatchStmtClass:
+ assert(0 && "@catch statements should be handled by EmitObjCAtTryStmt");
+ break;
+ case Stmt::ObjCAtFinallyStmtClass:
+ assert(0 && "@finally statements should be handled by EmitObjCAtTryStmt");
+ break;
+ case Stmt::ObjCAtThrowStmtClass:
+ EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S));
+ break;
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S));
+ break;
+ case Stmt::ObjCForCollectionStmtClass:
+ EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
+ break;
+
+ case Stmt::CXXTryStmtClass:
+ EmitCXXTryStmt(cast<CXXTryStmt>(*S));
+ break;
+ }
+}
+
+bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default: return false;
+ case Stmt::NullStmtClass: break;
+ case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
+ case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
+ case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
+ case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
+ case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
+ case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
+ case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
+ case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
+ }
+
+ return true;
+}
+
+/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
+/// this captures the expression result of the last sub-statement and returns it
+/// (for use by the statement expression extension).
+RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
+ AggValueSlot AggSlot) {
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
+ "LLVM IR generation of compound statement ('{}')");
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI) {
+ DI->setLocation(S.getLBracLoc());
+ DI->EmitRegionStart(Builder);
+ }
+
+ // Keep track of the current cleanup stack depth.
+ RunCleanupsScope Scope(*this);
+
+ for (CompoundStmt::const_body_iterator I = S.body_begin(),
+ E = S.body_end()-GetLast; I != E; ++I)
+ EmitStmt(*I);
+
+ if (DI) {
+ DI->setLocation(S.getRBracLoc());
+ DI->EmitRegionEnd(Builder);
+ }
+
+ RValue RV;
+ if (!GetLast)
+ RV = RValue::get(0);
+ else {
+ // We have to special case labels here. They are statements, but when put
+ // at the end of a statement expression, they yield the value of their
+ // subexpression. Handle this by walking through all labels we encounter,
+ // emitting them before we evaluate the subexpr.
+ const Stmt *LastStmt = S.body_back();
+ while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) {
+ EmitLabel(LS->getDecl());
+ LastStmt = LS->getSubStmt();
+ }
+
+ EnsureInsertPoint();
+
+ RV = EmitAnyExpr(cast<Expr>(LastStmt), AggSlot);
+ }
+
+ return RV;
+}
+
+void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
+ llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
+
+ // If there is a cleanup stack, then we it isn't worth trying to
+ // simplify this block (we would need to remove it from the scope map
+ // and cleanup entry).
+ if (!EHStack.empty())
+ return;
+
+ // Can only simplify direct branches.
+ if (!BI || !BI->isUnconditional())
+ return;
+
+ BB->replaceAllUsesWith(BI->getSuccessor(0));
+ BI->eraseFromParent();
+ BB->eraseFromParent();
+}
+
+void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
+ llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
+
+ // Fall out of the current block (if necessary).
+ EmitBranch(BB);
+
+ if (IsFinished && BB->use_empty()) {
+ delete BB;
+ return;
+ }
+
+ // Place the block after the current block, if possible, or else at
+ // the end of the function.
+ if (CurBB && CurBB->getParent())
+ CurFn->getBasicBlockList().insertAfter(CurBB, BB);
+ else
+ CurFn->getBasicBlockList().push_back(BB);
+ Builder.SetInsertPoint(BB);
+}
+
+void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
+ // Emit a branch from the current block to the target one if this
+ // was a real block. If this was just a fall-through block after a
+ // terminator, don't emit it.
+ llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
+
+ if (!CurBB || CurBB->getTerminator()) {
+ // If there is no insert point or the previous block is already
+ // terminated, don't touch it.
+ } else {
+ // Otherwise, create a fall-through branch.
+ Builder.CreateBr(Target);
+ }
+
+ Builder.ClearInsertionPoint();
+}
+
+CodeGenFunction::JumpDest
+CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) {
+ JumpDest &Dest = LabelMap[D];
+ if (Dest.isValid()) return Dest;
+
+ // Create, but don't insert, the new block.
+ Dest = JumpDest(createBasicBlock(D->getName()),
+ EHScopeStack::stable_iterator::invalid(),
+ NextCleanupDestIndex++);
+ return Dest;
+}
+
+void CodeGenFunction::EmitLabel(const LabelDecl *D) {
+ JumpDest &Dest = LabelMap[D];
+
+ // If we didn't need a forward reference to this label, just go
+ // ahead and create a destination at the current scope.
+ if (!Dest.isValid()) {
+ Dest = getJumpDestInCurrentScope(D->getName());
+
+ // Otherwise, we need to give this label a target depth and remove
+ // it from the branch-fixups list.
+ } else {
+ assert(!Dest.getScopeDepth().isValid() && "already emitted label!");
+ Dest = JumpDest(Dest.getBlock(),
+ EHStack.stable_begin(),
+ Dest.getDestIndex());
+
+ ResolveBranchFixups(Dest.getBlock());
+ }
+
+ EmitBlock(Dest.getBlock());
+}
+
+
+void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
+ EmitLabel(S.getDecl());
+ EmitStmt(S.getSubStmt());
+}
+
+void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
+
+ EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
+}
+
+
+void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
+ if (const LabelDecl *Target = S.getConstantTarget()) {
+ EmitBranchThroughCleanup(getJumpDestForLabel(Target));
+ return;
+ }
+
+ // Ensure that we have an i8* for our PHI node.
+ llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
+ Int8PtrTy, "addr");
+ llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
+
+
+ // Get the basic block for the indirect goto.
+ llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock();
+
+ // The first instruction in the block has to be the PHI for the switch dest,
+ // add an entry for this branch.
+ cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
+
+ EmitBranch(IndGotoBB);
+}
+
+void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
+ // C99 6.8.4.1: The first substatement is executed if the expression compares
+ // unequal to 0. The condition must be a scalar type.
+ RunCleanupsScope ConditionScope(*this);
+
+ if (S.getConditionVariable())
+ EmitAutoVarDecl(*S.getConditionVariable());
+
+ // If the condition constant folds and can be elided, try to avoid emitting
+ // the condition and the dead arm of the if/else.
+ if (int Cond = ConstantFoldsToSimpleInteger(S.getCond())) {
+ // Figure out which block (then or else) is executed.
+ const Stmt *Executed = S.getThen(), *Skipped = S.getElse();
+ if (Cond == -1) // Condition false?
+ std::swap(Executed, Skipped);
+
+ // If the skipped block has no labels in it, just emit the executed block.
+ // This avoids emitting dead code and simplifies the CFG substantially.
+ if (!ContainsLabel(Skipped)) {
+ if (Executed) {
+ RunCleanupsScope ExecutedScope(*this);
+ EmitStmt(Executed);
+ }
+ return;
+ }
+ }
+
+ // Otherwise, the condition did not fold, or we couldn't elide it. Just emit
+ // the conditional branch.
+ llvm::BasicBlock *ThenBlock = createBasicBlock("if.then");
+ llvm::BasicBlock *ContBlock = createBasicBlock("if.end");
+ llvm::BasicBlock *ElseBlock = ContBlock;
+ if (S.getElse())
+ ElseBlock = createBasicBlock("if.else");
+ EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock);
+
+ // Emit the 'then' code.
+ EmitBlock(ThenBlock);
+ {
+ RunCleanupsScope ThenScope(*this);
+ EmitStmt(S.getThen());
+ }
+ EmitBranch(ContBlock);
+
+ // Emit the 'else' code if present.
+ if (const Stmt *Else = S.getElse()) {
+ EmitBlock(ElseBlock);
+ {
+ RunCleanupsScope ElseScope(*this);
+ EmitStmt(Else);
+ }
+ EmitBranch(ContBlock);
+ }
+
+ // Emit the continuation block for code after the if.
+ EmitBlock(ContBlock, true);
+}
+
+void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
+ // Emit the header for the loop, which will also become
+ // the continue target.
+ JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
+ EmitBlock(LoopHeader.getBlock());
+
+ // Create an exit block for when the condition fails, which will
+ // also become the break target.
+ JumpDest LoopExit = getJumpDestInCurrentScope("while.end");
+
+ // Store the blocks to use for break and continue.
+ BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader));
+
+ // C++ [stmt.while]p2:
+ // When the condition of a while statement is a declaration, the
+ // scope of the variable that is declared extends from its point
+ // of declaration (3.3.2) to the end of the while statement.
+ // [...]
+ // The object created in a condition is destroyed and created
+ // with each iteration of the loop.
+ RunCleanupsScope ConditionScope(*this);
+
+ if (S.getConditionVariable())
+ EmitAutoVarDecl(*S.getConditionVariable());
+
+ // Evaluate the conditional in the while header. C99 6.8.5.1: The
+ // evaluation of the controlling expression takes place before each
+ // execution of the loop body.
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+ // while(1) is common, avoid extra exit blocks. Be sure
+ // to correctly handle break/continue though.
+ bool EmitBoolCondBranch = true;
+ if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
+ if (C->isOne())
+ EmitBoolCondBranch = false;
+
+ // As long as the condition is true, go to the loop body.
+ llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
+ if (EmitBoolCondBranch) {
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
+ if (ConditionScope.requiresCleanups())
+ ExitBlock = createBasicBlock("while.exit");
+
+ Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
+
+ if (ExitBlock != LoopExit.getBlock()) {
+ EmitBlock(ExitBlock);
+ EmitBranchThroughCleanup(LoopExit);
+ }
+ }
+
+ // Emit the loop body. We have to emit this in a cleanup scope
+ // because it might be a singleton DeclStmt.
+ {
+ RunCleanupsScope BodyScope(*this);
+ EmitBlock(LoopBody);
+ EmitStmt(S.getBody());
+ }
+
+ BreakContinueStack.pop_back();
+
+ // Immediately force cleanup.
+ ConditionScope.ForceCleanup();
+
+ // Branch to the loop header again.
+ EmitBranch(LoopHeader.getBlock());
+
+ // Emit the exit block.
+ EmitBlock(LoopExit.getBlock(), true);
+
+ // The LoopHeader typically is just a branch if we skipped emitting
+ // a branch, try to erase it.
+ if (!EmitBoolCondBranch)
+ SimplifyForwardingBlocks(LoopHeader.getBlock());
+}
+
+void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
+ JumpDest LoopExit = getJumpDestInCurrentScope("do.end");
+ JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");
+
+ // Store the blocks to use for break and continue.
+ BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));
+
+ // Emit the body of the loop.
+ llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
+ EmitBlock(LoopBody);
+ {
+ RunCleanupsScope BodyScope(*this);
+ EmitStmt(S.getBody());
+ }
+
+ BreakContinueStack.pop_back();
+
+ EmitBlock(LoopCond.getBlock());
+
+ // C99 6.8.5.2: "The evaluation of the controlling expression takes place
+ // after each execution of the loop body."
+
+ // Evaluate the conditional in the while header.
+ // C99 6.8.5p2/p4: The first substatement is executed if the expression
+ // compares unequal to 0. The condition must be a scalar type.
+ llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+ // "do {} while (0)" is common in macros, avoid extra blocks. Be sure
+ // to correctly handle break/continue though.
+ bool EmitBoolCondBranch = true;
+ if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
+ if (C->isZero())
+ EmitBoolCondBranch = false;
+
+ // As long as the condition is true, iterate the loop.
+ if (EmitBoolCondBranch)
+ Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock());
+
+ // Emit the exit block.
+ EmitBlock(LoopExit.getBlock());
+
+ // The DoCond block typically is just a branch if we skipped
+ // emitting a branch, try to erase it.
+ if (!EmitBoolCondBranch)
+ SimplifyForwardingBlocks(LoopCond.getBlock());
+}
+
+void CodeGenFunction::EmitForStmt(const ForStmt &S) {
+ JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
+
+ RunCleanupsScope ForScope(*this);
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI) {
+ DI->setLocation(S.getSourceRange().getBegin());
+ DI->EmitRegionStart(Builder);
+ }
+
+ // Evaluate the first part before the loop.
+ if (S.getInit())
+ EmitStmt(S.getInit());
+
+ // Start the loop with a block that tests the condition.
+ // If there's an increment, the continue scope will be overwritten
+ // later.
+ JumpDest Continue = getJumpDestInCurrentScope("for.cond");
+ llvm::BasicBlock *CondBlock = Continue.getBlock();
+ EmitBlock(CondBlock);
+
+ // Create a cleanup scope for the condition variable cleanups.
+ RunCleanupsScope ConditionScope(*this);
+
+ llvm::Value *BoolCondVal = 0;
+ if (S.getCond()) {
+ // If the for statement has a condition scope, emit the local variable
+ // declaration.
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
+ if (S.getConditionVariable()) {
+ EmitAutoVarDecl(*S.getConditionVariable());
+ }
+
+ // If there are any cleanups between here and the loop-exit scope,
+ // create a block to stage a loop exit along.
+ if (ForScope.requiresCleanups())
+ ExitBlock = createBasicBlock("for.cond.cleanup");
+
+ // As long as the condition is true, iterate the loop.
+ llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+
+ // C99 6.8.5p2/p4: The first substatement is executed if the expression
+ // compares unequal to 0. The condition must be a scalar type.
+ BoolCondVal = EvaluateExprAsBool(S.getCond());
+ Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock);
+
+ if (ExitBlock != LoopExit.getBlock()) {
+ EmitBlock(ExitBlock);
+ EmitBranchThroughCleanup(LoopExit);
+ }
+
+ EmitBlock(ForBody);
+ } else {
+ // Treat it as a non-zero constant. Don't even create a new block for the
+ // body, just fall into it.
+ }
+
+ // If the for loop doesn't have an increment we can just use the
+ // condition as the continue block. Otherwise we'll need to create
+ // a block for it (in the current scope, i.e. in the scope of the
+ // condition), and that we will become our continue block.
+ if (S.getInc())
+ Continue = getJumpDestInCurrentScope("for.inc");
+
+ // Store the blocks to use for break and continue.
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+
+ {
+ // Create a separate cleanup scope for the body, in case it is not
+ // a compound statement.
+ RunCleanupsScope BodyScope(*this);
+ EmitStmt(S.getBody());
+ }
+
+ // If there is an increment, emit it next.
+ if (S.getInc()) {
+ EmitBlock(Continue.getBlock());
+ EmitStmt(S.getInc());
+ }
+
+ BreakContinueStack.pop_back();
+
+ ConditionScope.ForceCleanup();
+ EmitBranch(CondBlock);
+
+ ForScope.ForceCleanup();
+
+ if (DI) {
+ DI->setLocation(S.getSourceRange().getEnd());
+ DI->EmitRegionEnd(Builder);
+ }
+
+ // Emit the fall-through block.
+ EmitBlock(LoopExit.getBlock(), true);
+}
+
+void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
+ if (RV.isScalar()) {
+ Builder.CreateStore(RV.getScalarVal(), ReturnValue);
+ } else if (RV.isAggregate()) {
+ EmitAggregateCopy(ReturnValue, RV.getAggregateAddr(), Ty);
+ } else {
+ StoreComplexToAddr(RV.getComplexVal(), ReturnValue, false);
+ }
+ EmitBranchThroughCleanup(ReturnBlock);
+}
+
+/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
+/// if the function returns void, or may be missing one if the function returns
+/// non-void. Fun stuff :).
+void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+ // Emit the result value, even if unused, to evalute the side effects.
+ const Expr *RV = S.getRetValue();
+
+ // FIXME: Clean this up by using an LValue for ReturnTemp,
+ // EmitStoreThroughLValue, and EmitAnyExpr.
+ if (S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable() &&
+ !Target.useGlobalsForAutomaticVariables()) {
+ // Apply the named return value optimization for this return statement,
+ // which means doing nothing: the appropriate result has already been
+ // constructed into the NRVO variable.
+
+ // If there is an NRVO flag for this variable, set it to 1 into indicate
+ // that the cleanup code should not destroy the variable.
+ if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()])
+ Builder.CreateStore(Builder.getTrue(), NRVOFlag);
+ } else if (!ReturnValue) {
+ // Make sure not to return anything, but evaluate the expression
+ // for side effects.
+ if (RV)
+ EmitAnyExpr(RV);
+ } else if (RV == 0) {
+ // Do nothing (return value is left uninitialized)
+ } else if (FnRetTy->isReferenceType()) {
+ // If this function returns a reference, take the address of the expression
+ // rather than the value.
+ RValue Result = EmitReferenceBindingToExpr(RV, /*InitializedDecl=*/0);
+ Builder.CreateStore(Result.getScalarVal(), ReturnValue);
+ } else if (!hasAggregateLLVMType(RV->getType())) {
+ Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
+ } else if (RV->getType()->isAnyComplexType()) {
+ EmitComplexExprIntoAddr(RV, ReturnValue, false);
+ } else {
+ EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, false, true));
+ }
+
+ EmitBranchThroughCleanup(ReturnBlock);
+}
+
+void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
+ // As long as debug info is modeled with instructions, we have to ensure we
+ // have a place to insert here and write the stop point here.
+ if (getDebugInfo()) {
+ EnsureInsertPoint();
+ EmitStopPoint(&S);
+ }
+
+ for (DeclStmt::const_decl_iterator I = S.decl_begin(), E = S.decl_end();
+ I != E; ++I)
+ EmitDecl(**I);
+}
+
+void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
+ assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
+
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
+
+ JumpDest Block = BreakContinueStack.back().BreakBlock;
+ EmitBranchThroughCleanup(Block);
+}
+
+void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
+ assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
+
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
+
+ JumpDest Block = BreakContinueStack.back().ContinueBlock;
+ EmitBranchThroughCleanup(Block);
+}
+
+/// EmitCaseStmtRange - If case statement range is not too big then
+/// add multiple cases to switch instruction, one for each value within
+/// the range. If range is too big then emit "if" condition check.
+void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
+ assert(S.getRHS() && "Expected RHS value in CaseStmt");
+
+ llvm::APSInt LHS = S.getLHS()->EvaluateAsInt(getContext());
+ llvm::APSInt RHS = S.getRHS()->EvaluateAsInt(getContext());
+
+ // Emit the code for this case. We do this first to make sure it is
+ // properly chained from our predecessor before generating the
+ // switch machinery to enter this block.
+ EmitBlock(createBasicBlock("sw.bb"));
+ llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
+ EmitStmt(S.getSubStmt());
+
+ // If range is empty, do nothing.
+ if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
+ return;
+
+ llvm::APInt Range = RHS - LHS;
+ // FIXME: parameters such as this should not be hardcoded.
+ if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
+ // Range is small enough to add multiple switch instruction cases.
+ for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) {
+ SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), LHS),
+ CaseDest);
+ LHS++;
+ }
+ return;
+ }
+
+ // The range is too big. Emit "if" condition into a new block,
+ // making sure to save and restore the current insertion point.
+ llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();
+
+ // Push this test onto the chain of range checks (which terminates
+ // in the default basic block). The switch's default will be changed
+ // to the top of this chain after switch emission is complete.
+ llvm::BasicBlock *FalseDest = CaseRangeBlock;
+ CaseRangeBlock = createBasicBlock("sw.caserange");
+
+ CurFn->getBasicBlockList().push_back(CaseRangeBlock);
+ Builder.SetInsertPoint(CaseRangeBlock);
+
+ // Emit range check.
+ llvm::Value *Diff =
+ Builder.CreateSub(SwitchInsn->getCondition(),
+ llvm::ConstantInt::get(getLLVMContext(), LHS), "tmp");
+ llvm::Value *Cond =
+ Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(getLLVMContext(), Range),
+ "inbounds");
+ Builder.CreateCondBr(Cond, CaseDest, FalseDest);
+
+ // Restore the appropriate insertion point.
+ if (RestoreBB)
+ Builder.SetInsertPoint(RestoreBB);
+ else
+ Builder.ClearInsertionPoint();
+}
+
+void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
+ if (S.getRHS()) {
+ EmitCaseStmtRange(S);
+ return;
+ }
+
+ EmitBlock(createBasicBlock("sw.bb"));
+ llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
+ llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext());
+ SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), CaseVal),
+ CaseDest);
+
+ // Recursively emitting the statement is acceptable, but is not wonderful for
+ // code where we have many case statements nested together, i.e.:
+ // case 1:
+ // case 2:
+ // case 3: etc.
+ // Handling this recursively will create a new block for each case statement
+ // that falls through to the next case which is IR intensive. It also causes
+ // deep recursion which can run into stack depth limitations. Handle
+ // sequential non-range case statements specially.
+ const CaseStmt *CurCase = &S;
+ const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
+
+ // Otherwise, iteratively add consequtive cases to this switch stmt.
+ while (NextCase && NextCase->getRHS() == 0) {
+ CurCase = NextCase;
+ CaseVal = CurCase->getLHS()->EvaluateAsInt(getContext());
+ SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), CaseVal),
+ CaseDest);
+
+ NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt());
+ }
+
+ // Normal default recursion for non-cases.
+ EmitStmt(CurCase->getSubStmt());
+}
+
+void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) {
+ llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
+ assert(DefaultBlock->empty() &&
+ "EmitDefaultStmt: Default block already defined?");
+ EmitBlock(DefaultBlock);
+ EmitStmt(S.getSubStmt());
+}
+
+void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
+ JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog");
+
+ RunCleanupsScope ConditionScope(*this);
+
+ if (S.getConditionVariable())
+ EmitAutoVarDecl(*S.getConditionVariable());
+
+ llvm::Value *CondV = EmitScalarExpr(S.getCond());
+
+ // Handle nested switch statements.
+ llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
+ llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
+
+ // Create basic block to hold stuff that comes after switch
+ // statement. We also need to create a default block now so that
+ // explicit case ranges tests can have a place to jump to on
+ // failure.
+ llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
+ SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
+ CaseRangeBlock = DefaultBlock;
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
+
+ // All break statements jump to NextBlock. If BreakContinueStack is non empty
+ // then reuse last ContinueBlock.
+ JumpDest OuterContinue;
+ if (!BreakContinueStack.empty())
+ OuterContinue = BreakContinueStack.back().ContinueBlock;
+
+ BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
+
+ // Emit switch body.
+ EmitStmt(S.getBody());
+
+ BreakContinueStack.pop_back();
+
+ // Update the default block in case explicit case range tests have
+ // been chained on top.
+ SwitchInsn->setSuccessor(0, CaseRangeBlock);
+
+ // If a default was never emitted:
+ if (!DefaultBlock->getParent()) {
+ // If we have cleanups, emit the default block so that there's a
+ // place to jump through the cleanups from.
+ if (ConditionScope.requiresCleanups()) {
+ EmitBlock(DefaultBlock);
+
+ // Otherwise, just forward the default block to the switch end.
+ } else {
+ DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
+ delete DefaultBlock;
+ }
+ }
+
+ ConditionScope.ForceCleanup();
+
+ // Emit continuation.
+ EmitBlock(SwitchExit.getBlock(), true);
+
+ SwitchInsn = SavedSwitchInsn;
+ CaseRangeBlock = SavedCRBlock;
+}
+
+static std::string
+SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
+ llvm::SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=0) {
+ std::string Result;
+
+ while (*Constraint) {
+ switch (*Constraint) {
+ default:
+ Result += Target.convertConstraint(*Constraint);
+ break;
+ // Ignore these
+ case '*':
+ case '?':
+ case '!':
+ case '=': // Will see this and the following in mult-alt constraints.
+ case '+':
+ break;
+ case ',':
+ Result += "|";
+ break;
+ case 'g':
+ Result += "imr";
+ break;
+ case '[': {
+ assert(OutCons &&
+ "Must pass output names to constraints with a symbolic name");
+ unsigned Index;
+ bool result = Target.resolveSymbolicName(Constraint,
+ &(*OutCons)[0],
+ OutCons->size(), Index);
+ assert(result && "Could not resolve symbolic name"); (void)result;
+ Result += llvm::utostr(Index);
+ break;
+ }
+ }
+
+ Constraint++;
+ }
+
+ return Result;
+}
+
+/// AddVariableConstraints - Look at AsmExpr and if it is a variable declared
+/// as using a particular register add that as a constraint that will be used
+/// in this asm stmt.
+static std::string
+AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr,
+ const TargetInfo &Target, CodeGenModule &CGM,
+ const AsmStmt &Stmt) {
+ const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
+ if (!AsmDeclRef)
+ return Constraint;
+ const ValueDecl &Value = *AsmDeclRef->getDecl();
+ const VarDecl *Variable = dyn_cast<VarDecl>(&Value);
+ if (!Variable)
+ return Constraint;
+ AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>();
+ if (!Attr)
+ return Constraint;
+ llvm::StringRef Register = Attr->getLabel();
+ assert(Target.isValidGCCRegisterName(Register));
+ // FIXME: We should check which registers are compatible with "r" or "x".
+ if (Constraint != "r" && Constraint != "x") {
+ CGM.ErrorUnsupported(&Stmt, "__asm__");
+ return Constraint;
+ }
+ return "{" + Register.str() + "}";
+}
+
+llvm::Value*
+CodeGenFunction::EmitAsmInputLValue(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ LValue InputValue, QualType InputType,
+ std::string &ConstraintStr) {
+ llvm::Value *Arg;
+ if (Info.allowsRegister() || !Info.allowsMemory()) {
+ if (!CodeGenFunction::hasAggregateLLVMType(InputType)) {
+ Arg = EmitLoadOfLValue(InputValue, InputType).getScalarVal();
+ } else {
+ const llvm::Type *Ty = ConvertType(InputType);
+ uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty);
+ if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
+ Ty = llvm::IntegerType::get(getLLVMContext(), Size);
+ Ty = llvm::PointerType::getUnqual(Ty);
+
+ Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(),
+ Ty));
+ } else {
+ Arg = InputValue.getAddress();
+ ConstraintStr += '*';
+ }
+ }
+ } else {
+ Arg = InputValue.getAddress();
+ ConstraintStr += '*';
+ }
+
+ return Arg;
+}
+
+llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ const Expr *InputExpr,
+ std::string &ConstraintStr) {
+ if (Info.allowsRegister() || !Info.allowsMemory())
+ if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType()))
+ return EmitScalarExpr(InputExpr);
+
+ InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
+ LValue Dest = EmitLValue(InputExpr);
+ return EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(), ConstraintStr);
+}
+
+/// getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline
+/// asm call instruction. The !srcloc MDNode contains a list of constant
+/// integers which are the source locations of the start of each line in the
+/// asm.
+static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
+ CodeGenFunction &CGF) {
+ llvm::SmallVector<llvm::Value *, 8> Locs;
+ // Add the location of the first line to the MDNode.
+ Locs.push_back(llvm::ConstantInt::get(CGF.Int32Ty,
+ Str->getLocStart().getRawEncoding()));
+ llvm::StringRef StrVal = Str->getString();
+ if (!StrVal.empty()) {
+ const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
+ const LangOptions &LangOpts = CGF.CGM.getLangOptions();
+
+ // Add the location of the start of each subsequent line of the asm to the
+ // MDNode.
+ for (unsigned i = 0, e = StrVal.size()-1; i != e; ++i) {
+ if (StrVal[i] != '\n') continue;
+ SourceLocation LineLoc = Str->getLocationOfByte(i+1, SM, LangOpts,
+ CGF.Target);
+ Locs.push_back(llvm::ConstantInt::get(CGF.Int32Ty,
+ LineLoc.getRawEncoding()));
+ }
+ }
+
+ return llvm::MDNode::get(CGF.getLLVMContext(), Locs.data(), Locs.size());
+}
+
+void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
+ // Analyze the asm string to decompose it into its pieces. We know that Sema
+ // has already done this, so it is guaranteed to be successful.
+ llvm::SmallVector<AsmStmt::AsmStringPiece, 4> Pieces;
+ unsigned DiagOffs;
+ S.AnalyzeAsmString(Pieces, getContext(), DiagOffs);
+
+ // Assemble the pieces into the final asm string.
+ std::string AsmString;
+ for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
+ if (Pieces[i].isString())
+ AsmString += Pieces[i].getString();
+ else if (Pieces[i].getModifier() == '\0')
+ AsmString += '$' + llvm::utostr(Pieces[i].getOperandNo());
+ else
+ AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' +
+ Pieces[i].getModifier() + '}';
+ }
+
+ // Get all the output and input constraints together.
+ llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
+ llvm::SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
+
+ for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
+ TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i),
+ S.getOutputName(i));
+ bool IsValid = Target.validateOutputConstraint(Info); (void)IsValid;
+ assert(IsValid && "Failed to parse output constraint");
+ OutputConstraintInfos.push_back(Info);
+ }
+
+ for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
+ TargetInfo::ConstraintInfo Info(S.getInputConstraint(i),
+ S.getInputName(i));
+ bool IsValid = Target.validateInputConstraint(OutputConstraintInfos.data(),
+ S.getNumOutputs(), Info);
+ assert(IsValid && "Failed to parse input constraint"); (void)IsValid;
+ InputConstraintInfos.push_back(Info);
+ }
+
+ std::string Constraints;
+
+ std::vector<LValue> ResultRegDests;
+ std::vector<QualType> ResultRegQualTys;
+ std::vector<const llvm::Type *> ResultRegTypes;
+ std::vector<const llvm::Type *> ResultTruncRegTypes;
+ std::vector<const llvm::Type*> ArgTypes;
+ std::vector<llvm::Value*> Args;
+
+ // Keep track of inout constraints.
+ std::string InOutConstraints;
+ std::vector<llvm::Value*> InOutArgs;
+ std::vector<const llvm::Type*> InOutArgTypes;
+
+ for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
+ TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
+
+ // Simplify the output constraint.
+ std::string OutputConstraint(S.getOutputConstraint(i));
+ OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target);
+
+ const Expr *OutExpr = S.getOutputExpr(i);
+ OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
+
+ OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr, Target,
+ CGM, S);
+
+ LValue Dest = EmitLValue(OutExpr);
+ if (!Constraints.empty())
+ Constraints += ',';
+
+ // If this is a register output, then make the inline asm return it
+ // by-value. If this is a memory result, return the value by-reference.
+ if (!Info.allowsMemory() && !hasAggregateLLVMType(OutExpr->getType())) {
+ Constraints += "=" + OutputConstraint;
+ ResultRegQualTys.push_back(OutExpr->getType());
+ ResultRegDests.push_back(Dest);
+ ResultRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
+ ResultTruncRegTypes.push_back(ResultRegTypes.back());
+
+ // If this output is tied to an input, and if the input is larger, then
+ // we need to set the actual result type of the inline asm node to be the
+ // same as the input type.
+ if (Info.hasMatchingInput()) {
+ unsigned InputNo;
+ for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
+ TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
+ if (Input.hasTiedOperand() && Input.getTiedOperand() == i)
+ break;
+ }
+ assert(InputNo != S.getNumInputs() && "Didn't find matching input!");
+
+ QualType InputTy = S.getInputExpr(InputNo)->getType();
+ QualType OutputType = OutExpr->getType();
+
+ uint64_t InputSize = getContext().getTypeSize(InputTy);
+ if (getContext().getTypeSize(OutputType) < InputSize) {
+ // Form the asm to return the value as a larger integer or fp type.
+ ResultRegTypes.back() = ConvertType(InputTy);
+ }
+ }
+ if (const llvm::Type* AdjTy =
+ getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
+ ResultRegTypes.back()))
+ ResultRegTypes.back() = AdjTy;
+ } else {
+ ArgTypes.push_back(Dest.getAddress()->getType());
+ Args.push_back(Dest.getAddress());
+ Constraints += "=*";
+ Constraints += OutputConstraint;
+ }
+
+ if (Info.isReadWrite()) {
+ InOutConstraints += ',';
+
+ const Expr *InputExpr = S.getOutputExpr(i);
+ llvm::Value *Arg = EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(),
+ InOutConstraints);
+
+ if (Info.allowsRegister())
+ InOutConstraints += llvm::utostr(i);
+ else
+ InOutConstraints += OutputConstraint;
+
+ InOutArgTypes.push_back(Arg->getType());
+ InOutArgs.push_back(Arg);
+ }
+ }
+
+ unsigned NumConstraints = S.getNumOutputs() + S.getNumInputs();
+
+ for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
+ const Expr *InputExpr = S.getInputExpr(i);
+
+ TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+
+ if (!Constraints.empty())
+ Constraints += ',';
+
+ // Simplify the input constraint.
+ std::string InputConstraint(S.getInputConstraint(i));
+ InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target,
+ &OutputConstraintInfos);
+
+ InputConstraint =
+ AddVariableConstraints(InputConstraint,
+ *InputExpr->IgnoreParenNoopCasts(getContext()),
+ Target, CGM, S);
+
+ llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, Constraints);
+
+ // If this input argument is tied to a larger output result, extend the
+ // input to be the same size as the output. The LLVM backend wants to see
+ // the input and output of a matching constraint be the same size. Note
+ // that GCC does not define what the top bits are here. We use zext because
+ // that is usually cheaper, but LLVM IR should really get an anyext someday.
+ if (Info.hasTiedOperand()) {
+ unsigned Output = Info.getTiedOperand();
+ QualType OutputType = S.getOutputExpr(Output)->getType();
+ QualType InputTy = InputExpr->getType();
+
+ if (getContext().getTypeSize(OutputType) >
+ getContext().getTypeSize(InputTy)) {
+ // Use ptrtoint as appropriate so that we can do our extension.
+ if (isa<llvm::PointerType>(Arg->getType()))
+ Arg = Builder.CreatePtrToInt(Arg, IntPtrTy);
+ const llvm::Type *OutputTy = ConvertType(OutputType);
+ if (isa<llvm::IntegerType>(OutputTy))
+ Arg = Builder.CreateZExt(Arg, OutputTy);
+ else
+ Arg = Builder.CreateFPExt(Arg, OutputTy);
+ }
+ }
+ if (const llvm::Type* AdjTy =
+ getTargetHooks().adjustInlineAsmType(*this, InputConstraint,
+ Arg->getType()))
+ Arg = Builder.CreateBitCast(Arg, AdjTy);
+
+ ArgTypes.push_back(Arg->getType());
+ Args.push_back(Arg);
+ Constraints += InputConstraint;
+ }
+
+ // Append the "input" part of inout constraints last.
+ for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
+ ArgTypes.push_back(InOutArgTypes[i]);
+ Args.push_back(InOutArgs[i]);
+ }
+ Constraints += InOutConstraints;
+
+ // Clobbers
+ for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
+ llvm::StringRef Clobber = S.getClobber(i)->getString();
+
+ Clobber = Target.getNormalizedGCCRegisterName(Clobber);
+
+ if (i != 0 || NumConstraints != 0)
+ Constraints += ',';
+
+ Constraints += "~{";
+ Constraints += Clobber;
+ Constraints += '}';
+ }
+
+ // Add machine specific clobbers
+ std::string MachineClobbers = Target.getClobbers();
+ if (!MachineClobbers.empty()) {
+ if (!Constraints.empty())
+ Constraints += ',';
+ Constraints += MachineClobbers;
+ }
+
+ const llvm::Type *ResultType;
+ if (ResultRegTypes.empty())
+ ResultType = llvm::Type::getVoidTy(getLLVMContext());
+ else if (ResultRegTypes.size() == 1)
+ ResultType = ResultRegTypes[0];
+ else
+ ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ResultType, ArgTypes, false);
+
+ llvm::InlineAsm *IA =
+ llvm::InlineAsm::get(FTy, AsmString, Constraints,
+ S.isVolatile() || S.getNumOutputs() == 0);
+ llvm::CallInst *Result = Builder.CreateCall(IA, Args.begin(), Args.end());
+ Result->addAttribute(~0, llvm::Attribute::NoUnwind);
+
+ // Slap the source location of the inline asm into a !srcloc metadata on the
+ // call.
+ Result->setMetadata("srcloc", getAsmSrcLocInfo(S.getAsmString(), *this));
+
+ // Extract all of the register value results from the asm.
+ std::vector<llvm::Value*> RegResults;
+ if (ResultRegTypes.size() == 1) {
+ RegResults.push_back(Result);
+ } else {
+ for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
+ llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult");
+ RegResults.push_back(Tmp);
+ }
+ }
+
+ for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
+ llvm::Value *Tmp = RegResults[i];
+
+ // If the result type of the LLVM IR asm doesn't match the result type of
+ // the expression, do the conversion.
+ if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
+ const llvm::Type *TruncTy = ResultTruncRegTypes[i];
+
+ // Truncate the integer result to the right size, note that TruncTy can be
+ // a pointer.
+ if (TruncTy->isFloatingPointTy())
+ Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
+ else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
+ uint64_t ResSize = CGM.getTargetData().getTypeSizeInBits(TruncTy);
+ Tmp = Builder.CreateTrunc(Tmp,
+ llvm::IntegerType::get(getLLVMContext(), (unsigned)ResSize));
+ Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
+ } else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
+ uint64_t TmpSize =CGM.getTargetData().getTypeSizeInBits(Tmp->getType());
+ Tmp = Builder.CreatePtrToInt(Tmp,
+ llvm::IntegerType::get(getLLVMContext(), (unsigned)TmpSize));
+ Tmp = Builder.CreateTrunc(Tmp, TruncTy);
+ } else if (TruncTy->isIntegerTy()) {
+ Tmp = Builder.CreateTrunc(Tmp, TruncTy);
+ } else if (TruncTy->isVectorTy()) {
+ Tmp = Builder.CreateBitCast(Tmp, TruncTy);
+ }
+ }
+
+ EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i],
+ ResultRegQualTys[i]);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGTemporaries.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGTemporaries.cpp
new file mode 100644
index 0000000..3b4c509
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGTemporaries.cpp
@@ -0,0 +1,46 @@
+//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of temporaries
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+ struct DestroyTemporary {
+ static void Emit(CodeGenFunction &CGF, bool forEH,
+ const CXXDestructorDecl *dtor, llvm::Value *addr) {
+ CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ addr);
+ }
+ };
+}
+
+/// Emits all the code to cause the given temporary to be cleaned up.
+void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
+ llvm::Value *Ptr) {
+ pushFullExprCleanup<DestroyTemporary>(NormalAndEHCleanup,
+ Temporary->getDestructor(),
+ Ptr);
+}
+
+RValue
+CodeGenFunction::EmitExprWithCleanups(const ExprWithCleanups *E,
+ AggValueSlot Slot) {
+ RunCleanupsScope Scope(*this);
+ return EmitAnyExpr(E->getSubExpr(), Slot);
+}
+
+LValue CodeGenFunction::EmitExprWithCleanupsLValue(const ExprWithCleanups *E) {
+ RunCleanupsScope Scope(*this);
+ return EmitLValue(E->getSubExpr());
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
new file mode 100644
index 0000000..78b2dbe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
@@ -0,0 +1,484 @@
+//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of VTTs (vtable tables).
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "clang/AST/RecordLayout.h"
+using namespace clang;
+using namespace CodeGen;
+
+#define D1(x)
+
+namespace {
+
+/// VTT builder - Class for building VTT layout information.
+class VTTBuilder {
+
+ CodeGenModule &CGM;
+
+ /// MostDerivedClass - The most derived class for which we're building this
+ /// vtable.
+ const CXXRecordDecl *MostDerivedClass;
+
+ typedef llvm::SmallVector<llvm::Constant *, 64> VTTComponentsVectorTy;
+
+ /// VTTComponents - The VTT components.
+ VTTComponentsVectorTy VTTComponents;
+
+ /// MostDerivedClassLayout - the AST record layout of the most derived class.
+ const ASTRecordLayout &MostDerivedClassLayout;
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+
+ /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
+ /// class.
+ llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
+
+ /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of
+ /// all subobjects of the most derived class.
+ llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
+
+ /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
+ /// the VTT.
+ bool GenerateDefinition;
+
+ /// GetAddrOfVTable - Returns the address of the vtable for the base class in
+ /// the given vtable class.
+ ///
+ /// \param AddressPoints - If the returned vtable is a construction vtable,
+ /// this will hold the address points for it.
+ llvm::Constant *GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
+ AddressPointsMapTy& AddressPoints);
+
+ /// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
+ ///
+ /// \param AddressPoints - If the vtable is a construction vtable, this has
+ /// the address points for it.
+ void AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ const AddressPointsMapTy& AddressPoints);
+
+ /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
+ /// subobject.
+ void LayoutSecondaryVTTs(BaseSubobject Base);
+
+ /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
+ /// for the given base subobject.
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ ///
+ /// \param AddressPoints - If the vtable is a construction vtable, this has
+ /// the address points for it.
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ const AddressPointsMapTy& AddressPoints,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
+ /// for the given base subobject.
+ ///
+ /// \param AddressPoints - If the vtable is a construction vtable, this has
+ /// the address points for it.
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ llvm::Constant *VTable,
+ const AddressPointsMapTy& AddressPoints);
+
+ /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
+ /// given record decl.
+ void LayoutVirtualVTTs(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// LayoutVTT - Will lay out the VTT for the given subobject, including any
+ /// secondary VTTs, secondary virtual pointers and virtual VTTs.
+ void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
+
+public:
+ VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass,
+ bool GenerateDefinition);
+
+ // getVTTComponents - Returns a reference to the VTT components.
+ const VTTComponentsVectorTy &getVTTComponents() const {
+ return VTTComponents;
+ }
+
+ /// getSubVTTIndicies - Returns a reference to the sub-VTT indices.
+ const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
+ return SubVTTIndicies;
+ }
+
+ /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary
+ /// virtual pointer indices.
+ const llvm::DenseMap<BaseSubobject, uint64_t> &
+ getSecondaryVirtualPointerIndices() const {
+ return SecondaryVirtualPointerIndices;
+ }
+
+};
+
+VTTBuilder::VTTBuilder(CodeGenModule &CGM,
+ const CXXRecordDecl *MostDerivedClass,
+ bool GenerateDefinition)
+ : CGM(CGM), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)),
+ GenerateDefinition(GenerateDefinition) {
+
+ // Lay out this VTT.
+ LayoutVTT(BaseSubobject(MostDerivedClass, 0), /*BaseIsVirtual=*/false);
+}
+
+llvm::Constant *
+VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual,
+ AddressPointsMapTy& AddressPoints) {
+ if (!GenerateDefinition)
+ return 0;
+
+ if (Base.getBase() == MostDerivedClass) {
+ assert(Base.getBaseOffset() == 0 &&
+ "Most derived class vtable must have a zero offset!");
+ // This is a regular vtable.
+ return CGM.getVTables().GetAddrOfVTable(MostDerivedClass);
+ }
+
+ return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass,
+ Base, BaseIsVirtual,
+ AddressPoints);
+}
+
+void VTTBuilder::AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ const AddressPointsMapTy& AddressPoints) {
+ // Store the vtable pointer index if we're generating the primary VTT.
+ if (VTableClass == MostDerivedClass) {
+ assert(!SecondaryVirtualPointerIndices.count(Base) &&
+ "A virtual pointer index already exists for this base subobject!");
+ SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
+ }
+
+ if (!GenerateDefinition) {
+ VTTComponents.push_back(0);
+ return;
+ }
+
+ uint64_t AddressPoint;
+ if (VTableClass != MostDerivedClass) {
+ // The vtable is a construction vtable, look in the construction vtable
+ // address points.
+ AddressPoint = AddressPoints.lookup(Base);
+ assert(AddressPoint != 0 && "Did not find ctor vtable address point!");
+ } else {
+ // Just get the address point for the regular vtable.
+ AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass);
+ assert(AddressPoint != 0 && "Did not find vtable address point!");
+ }
+
+ if (!AddressPoint) AddressPoint = 0;
+
+ llvm::Value *Idxs[] = {
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()),
+ AddressPoint)
+ };
+
+ llvm::Constant *Init =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs, 2);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
+
+ VTTComponents.push_back(Init);
+}
+
+void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+
+ // Don't layout virtual bases.
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ uint64_t BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffsetInBits(BaseDecl);
+
+ // Layout the VTT for this base.
+ LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
+ }
+}
+
+void
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ const AddressPointsMapTy& AddressPoints,
+ VisitedVirtualBasesSetTy &VBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // We're not interested in bases that don't have virtual bases, and not
+ // morally virtual bases.
+ if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
+ return;
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Itanium C++ ABI 2.6.2:
+ // Secondary virtual pointers are present for all bases with either
+ // virtual bases or virtual function declarations overridden along a
+ // virtual path.
+ //
+ // If the base class is not dynamic, we don't want to add it, nor any
+ // of its base classes.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
+ bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
+ bool BaseDeclIsNonVirtualPrimaryBase = false;
+ uint64_t BaseOffset;
+ if (I->isVirtual()) {
+ // Ignore virtual bases that we've already visited.
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+ BaseDeclIsMorallyVirtual = true;
+ } else {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ BaseOffset =
+ Base.getBaseOffset() + Layout.getBaseClassOffsetInBits(BaseDecl);
+
+ if (!Layout.isPrimaryBaseVirtual() &&
+ Layout.getPrimaryBase() == BaseDecl)
+ BaseDeclIsNonVirtualPrimaryBase = true;
+ }
+
+ // Itanium C++ ABI 2.6.2:
+ // Secondary virtual pointers: for each base class X which (a) has virtual
+ // bases or is reachable along a virtual path from D, and (b) is not a
+ // non-virtual primary base, the address of the virtual table for X-in-D
+ // or an appropriate construction virtual table.
+ if (!BaseDeclIsNonVirtualPrimaryBase &&
+ (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
+ // Add the vtable pointer.
+ AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, VTableClass,
+ AddressPoints);
+ }
+
+ // And lay out the secondary virtual pointers for the base class.
+ LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
+ BaseDeclIsMorallyVirtual, VTable,
+ VTableClass, AddressPoints, VBases);
+ }
+}
+
+void
+VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ llvm::Constant *VTable,
+ const AddressPointsMapTy& AddressPoints) {
+ VisitedVirtualBasesSetTy VBases;
+ LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
+ VTable, Base.getBase(), AddressPoints, VBases);
+}
+
+void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a virtual base.
+ if (I->isVirtual()) {
+ // Check if we've seen this base before.
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ uint64_t BaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+
+ LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
+ }
+
+ // We only need to layout virtual VTTs for this base if it actually has
+ // virtual bases.
+ if (BaseDecl->getNumVBases())
+ LayoutVirtualVTTs(BaseDecl, VBases);
+ }
+}
+
+void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ // Itanium C++ ABI 2.6.2:
+ // An array of virtual table addresses, called the VTT, is declared for
+ // each class type that has indirect or direct virtual base classes.
+ if (RD->getNumVBases() == 0)
+ return;
+
+ bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
+
+ if (!IsPrimaryVTT) {
+ // Remember the sub-VTT index.
+ SubVTTIndicies[Base] = VTTComponents.size();
+ }
+
+ AddressPointsMapTy AddressPoints;
+ llvm::Constant *VTable = GetAddrOfVTable(Base, BaseIsVirtual, AddressPoints);
+
+ // Add the primary vtable pointer.
+ AddVTablePointer(Base, VTable, RD, AddressPoints);
+
+ // Add the secondary VTTs.
+ LayoutSecondaryVTTs(Base);
+
+ // Add the secondary virtual pointers.
+ LayoutSecondaryVirtualPointers(Base, VTable, AddressPoints);
+
+ // If this is the primary VTT, we want to lay out virtual VTTs as well.
+ if (IsPrimaryVTT) {
+ VisitedVirtualBasesSetTy VBases;
+ LayoutVirtualVTTs(Base.getBase(), VBases);
+ }
+}
+
+}
+
+void
+CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD) {
+ VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/true);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ const llvm::ArrayType *ArrayType =
+ llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
+
+ llvm::Constant *Init =
+ llvm::ConstantArray::get(ArrayType, Builder.getVTTComponents().data(),
+ Builder.getVTTComponents().size());
+
+ VTT->setInitializer(Init);
+
+ // Set the correct linkage.
+ VTT->setLinkage(Linkage);
+
+ // Set the right visibility.
+ CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT);
+}
+
+llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
+ assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT");
+
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
+
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ const llvm::ArrayType *ArrayType =
+ llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
+
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ llvm::GlobalValue::ExternalLinkage);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
+
+bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // We don't have any virtual bases, just return early.
+ if (!MD->getParent()->getNumVBases())
+ return false;
+
+ // Check if we have a base constructor.
+ if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+ return true;
+
+ // Check if we have a base destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+ return true;
+
+ return false;
+}
+
+uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
+ BaseSubobject Base) {
+ BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
+
+ SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair);
+ if (I != SubVTTIndicies.end())
+ return I->second;
+
+ VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
+
+ for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
+ Builder.getSubVTTIndicies().begin(),
+ E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
+ // Insert all indices.
+ BaseSubobjectPairTy ClassSubobjectPair(RD, I->first);
+
+ SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second));
+ }
+
+ I = SubVTTIndicies.find(ClassSubobjectPair);
+ assert(I != SubVTTIndicies.end() && "Did not find index!");
+
+ return I->second;
+}
+
+uint64_t
+CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
+ BaseSubobject Base) {
+ SecondaryVirtualPointerIndicesMapTy::iterator I =
+ SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
+
+ if (I != SecondaryVirtualPointerIndices.end())
+ return I->second;
+
+ VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false);
+
+ // Insert all secondary vpointer indices.
+ for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
+ Builder.getSecondaryVirtualPointerIndices().begin(),
+ E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
+ std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
+ std::make_pair(RD, I->first);
+
+ SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
+ }
+
+ I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
+ assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
+
+ return I->second;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
new file mode 100644
index 0000000..891697f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -0,0 +1,3106 @@
+//===--- CGVTables.cpp - Emit LLVM Code for C++ vtables -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of virtual tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
+#include <algorithm>
+#include <cstdio>
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+
+/// BaseOffset - Represents an offset from a derived class to a direct or
+/// indirect base class.
+struct BaseOffset {
+ /// DerivedClass - The derived class.
+ const CXXRecordDecl *DerivedClass;
+
+ /// VirtualBase - If the path from the derived class to the base class
+ /// involves a virtual base class, this holds its declaration.
+ const CXXRecordDecl *VirtualBase;
+
+ /// NonVirtualOffset - The offset from the derived class to the base class.
+ /// (Or the offset from the virtual base class to the base class, if the
+ /// path from the derived class to the base class involves a virtual base
+ /// class.
+ int64_t NonVirtualOffset;
+
+ BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
+ BaseOffset(const CXXRecordDecl *DerivedClass,
+ const CXXRecordDecl *VirtualBase, int64_t NonVirtualOffset)
+ : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
+ NonVirtualOffset(NonVirtualOffset) { }
+
+ bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; }
+};
+
+/// FinalOverriders - Contains the final overrider member functions for all
+/// member functions in the base subobjects of a class.
+class FinalOverriders {
+public:
+ /// OverriderInfo - Information about a final overrider.
+ struct OverriderInfo {
+ /// Method - The method decl of the overrider.
+ const CXXMethodDecl *Method;
+
+ /// Offset - the base offset of the overrider in the layout class.
+ uint64_t Offset;
+
+ OverriderInfo() : Method(0), Offset(0) { }
+ };
+
+private:
+ /// MostDerivedClass - The most derived class for which the final overriders
+ /// are stored.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// MostDerivedClassOffset - If we're building final overriders for a
+ /// construction vtable, this holds the offset from the layout class to the
+ /// most derived class.
+ const uint64_t MostDerivedClassOffset;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if the final overriders are for a
+ /// construction vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ ASTContext &Context;
+
+ /// MostDerivedClassLayout - the AST record layout of the most derived class.
+ const ASTRecordLayout &MostDerivedClassLayout;
+
+ /// MethodBaseOffsetPairTy - Uniquely identifies a member function
+ /// in a base subobject.
+ typedef std::pair<const CXXMethodDecl *, uint64_t> MethodBaseOffsetPairTy;
+
+ typedef llvm::DenseMap<MethodBaseOffsetPairTy,
+ OverriderInfo> OverridersMapTy;
+
+ /// OverridersMap - The final overriders for all virtual member functions of
+ /// all the base subobjects of the most derived class.
+ OverridersMapTy OverridersMap;
+
+ /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
+ /// as a record decl and a subobject number) and its offsets in the most
+ /// derived class as well as the layout class.
+ typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
+ uint64_t> SubobjectOffsetMapTy;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
+
+ /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
+ /// given base.
+ void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ uint64_t OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts);
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ /// dump - dump the final overriders for a base subobject, and all its direct
+ /// and indirect base subobjects.
+ void dump(llvm::raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy& VisitedVirtualBases);
+
+public:
+ FinalOverriders(const CXXRecordDecl *MostDerivedClass,
+ uint64_t MostDerivedClassOffset,
+ const CXXRecordDecl *LayoutClass);
+
+ /// getOverrider - Get the final overrider for the given method declaration in
+ /// the subobject with the given base offset.
+ OverriderInfo getOverrider(const CXXMethodDecl *MD,
+ uint64_t BaseOffset) const {
+ assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
+ "Did not find overrider!");
+
+ return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
+ }
+
+ /// dump - dump the final overriders.
+ void dump() {
+ VisitedVirtualBasesSetTy VisitedVirtualBases;
+ dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0), VisitedVirtualBases);
+ }
+
+};
+
+#define DUMP_OVERRIDERS 0
+
+FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
+ uint64_t MostDerivedClassOffset,
+ const CXXRecordDecl *LayoutClass)
+ : MostDerivedClass(MostDerivedClass),
+ MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
+ Context(MostDerivedClass->getASTContext()),
+ MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
+
+ // Compute base offsets.
+ SubobjectOffsetMapTy SubobjectOffsets;
+ SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
+ SubobjectCountMapTy SubobjectCounts;
+ ComputeBaseOffsets(BaseSubobject(MostDerivedClass, 0), /*IsVirtual=*/false,
+ MostDerivedClassOffset, SubobjectOffsets,
+ SubobjectLayoutClassOffsets, SubobjectCounts);
+
+ // Get the the final overriders.
+ CXXFinalOverriderMap FinalOverriders;
+ MostDerivedClass->getFinalOverriders(FinalOverriders);
+
+ for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
+ E = FinalOverriders.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const OverridingMethods& Methods = I->second;
+
+ for (OverridingMethods::const_iterator I = Methods.begin(),
+ E = Methods.end(); I != E; ++I) {
+ unsigned SubobjectNumber = I->first;
+ assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
+ SubobjectNumber)) &&
+ "Did not find subobject offset!");
+
+ uint64_t BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
+ SubobjectNumber)];
+
+ assert(I->second.size() == 1 && "Final overrider is not unique!");
+ const UniqueVirtualMethod &Method = I->second.front();
+
+ const CXXRecordDecl *OverriderRD = Method.Method->getParent();
+ assert(SubobjectLayoutClassOffsets.count(
+ std::make_pair(OverriderRD, Method.Subobject))
+ && "Did not find subobject offset!");
+ uint64_t OverriderOffset =
+ SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
+ Method.Subobject)];
+
+ OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
+ assert(!Overrider.Method && "Overrider should not exist yet!");
+
+ Overrider.Offset = OverriderOffset;
+ Overrider.Method = Method.Method;
+ }
+ }
+
+#if DUMP_OVERRIDERS
+ // And dump them (for now).
+ dump();
+#endif
+}
+
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *DerivedRD,
+ const CXXBasePath &Path) {
+ int64_t NonVirtualOffset = 0;
+
+ unsigned NonVirtualStart = 0;
+ const CXXRecordDecl *VirtualBase = 0;
+
+ // First, look for the virtual base class.
+ for (unsigned I = 0, E = Path.size(); I != E; ++I) {
+ const CXXBasePathElement &Element = Path[I];
+
+ if (Element.Base->isVirtual()) {
+ // FIXME: Can we break when we find the first virtual base?
+ // (If we can't, can't we just iterate over the path in reverse order?)
+ NonVirtualStart = I + 1;
+ QualType VBaseType = Element.Base->getType();
+ VirtualBase =
+ cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+ }
+ }
+
+ // Now compute the non-virtual offset.
+ for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
+ const CXXBasePathElement &Element = Path[I];
+
+ // Check the base class offset.
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
+
+ const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
+ const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
+
+ NonVirtualOffset += Layout.getBaseClassOffsetInBits(Base);
+ }
+
+ // FIXME: This should probably use CharUnits or something. Maybe we should
+ // even change the base offsets in ASTRecordLayout to be specified in
+ // CharUnits.
+ return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset / 8);
+
+}
+
+static BaseOffset ComputeBaseOffset(ASTContext &Context,
+ const CXXRecordDecl *BaseRD,
+ const CXXRecordDecl *DerivedRD) {
+ CXXBasePaths Paths(/*FindAmbiguities=*/false,
+ /*RecordPaths=*/true, /*DetectVirtual=*/false);
+
+ if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+ isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+ assert(false && "Class must be derived from the passed in base class!");
+ return BaseOffset();
+ }
+
+ return ComputeBaseOffset(Context, DerivedRD, Paths.front());
+}
+
+static BaseOffset
+ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
+ const CXXMethodDecl *DerivedMD,
+ const CXXMethodDecl *BaseMD) {
+ const FunctionType *BaseFT = BaseMD->getType()->getAs<FunctionType>();
+ const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>();
+
+ // Canonicalize the return types.
+ CanQualType CanDerivedReturnType =
+ Context.getCanonicalType(DerivedFT->getResultType());
+ CanQualType CanBaseReturnType =
+ Context.getCanonicalType(BaseFT->getResultType());
+
+ assert(CanDerivedReturnType->getTypeClass() ==
+ CanBaseReturnType->getTypeClass() &&
+ "Types must have same type class!");
+
+ if (CanDerivedReturnType == CanBaseReturnType) {
+ // No adjustment needed.
+ return BaseOffset();
+ }
+
+ if (isa<ReferenceType>(CanDerivedReturnType)) {
+ CanDerivedReturnType =
+ CanDerivedReturnType->getAs<ReferenceType>()->getPointeeType();
+ CanBaseReturnType =
+ CanBaseReturnType->getAs<ReferenceType>()->getPointeeType();
+ } else if (isa<PointerType>(CanDerivedReturnType)) {
+ CanDerivedReturnType =
+ CanDerivedReturnType->getAs<PointerType>()->getPointeeType();
+ CanBaseReturnType =
+ CanBaseReturnType->getAs<PointerType>()->getPointeeType();
+ } else {
+ assert(false && "Unexpected return type!");
+ }
+
+ // We need to compare unqualified types here; consider
+ // const T *Base::foo();
+ // T *Derived::foo();
+ if (CanDerivedReturnType.getUnqualifiedType() ==
+ CanBaseReturnType.getUnqualifiedType()) {
+ // No adjustment needed.
+ return BaseOffset();
+ }
+
+ const CXXRecordDecl *DerivedRD =
+ cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
+
+ const CXXRecordDecl *BaseRD =
+ cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
+
+ return ComputeBaseOffset(Context, BaseRD, DerivedRD);
+}
+
+void
+FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ uint64_t OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts) {
+ const CXXRecordDecl *RD = Base.getBase();
+
+ unsigned SubobjectNumber = 0;
+ if (!IsVirtual)
+ SubobjectNumber = ++SubobjectCounts[RD];
+
+ // Set up the subobject to offset mapping.
+ assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+ assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+
+ SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
+ Base.getBaseOffset();
+ SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
+ OffsetInLayoutClass;
+
+ // Traverse our bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t BaseOffset;
+ uint64_t BaseOffsetInLayoutClass;
+ if (I->isVirtual()) {
+ // Check if we've visited this virtual base before.
+ if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
+ continue;
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+ BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+ } else {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ uint64_t Offset = Layout.getBaseClassOffsetInBits(BaseDecl);
+
+ BaseOffset = Base.getBaseOffset() + Offset;
+ BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
+ }
+
+ ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), I->isVirtual(),
+ BaseOffsetInLayoutClass, SubobjectOffsets,
+ SubobjectLayoutClassOffsets, SubobjectCounts);
+ }
+}
+
+void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy &VisitedVirtualBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore bases that don't have any virtual member functions.
+ if (!BaseDecl->isPolymorphic())
+ continue;
+
+ uint64_t BaseOffset;
+ if (I->isVirtual()) {
+ if (!VisitedVirtualBases.insert(BaseDecl)) {
+ // We've visited this base before.
+ continue;
+ }
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+ } else {
+ BaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl) +
+ Base.getBaseOffset();
+ }
+
+ dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
+ }
+
+ Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", ";
+ Out << Base.getBaseOffset() / 8 << ")\n";
+
+ // Now dump the overriders for this base subobject.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
+
+ Out << " " << MD->getQualifiedNameAsString() << " - (";
+ Out << Overrider.Method->getQualifiedNameAsString();
+ Out << ", " << ", " << Overrider.Offset / 8 << ')';
+
+ BaseOffset Offset;
+ if (!Overrider.Method->isPure())
+ Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+
+ if (!Offset.isEmpty()) {
+ Out << " [ret-adj: ";
+ if (Offset.VirtualBase)
+ Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
+
+ Out << Offset.NonVirtualOffset << " nv]";
+ }
+
+ Out << "\n";
+ }
+}
+
+/// VTableComponent - Represents a single component in a vtable.
+class VTableComponent {
+public:
+ enum Kind {
+ CK_VCallOffset,
+ CK_VBaseOffset,
+ CK_OffsetToTop,
+ CK_RTTI,
+ CK_FunctionPointer,
+
+ /// CK_CompleteDtorPointer - A pointer to the complete destructor.
+ CK_CompleteDtorPointer,
+
+ /// CK_DeletingDtorPointer - A pointer to the deleting destructor.
+ CK_DeletingDtorPointer,
+
+ /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer
+ /// will end up never being called. Such vtable function pointers are
+ /// represented as a CK_UnusedFunctionPointer.
+ CK_UnusedFunctionPointer
+ };
+
+ static VTableComponent MakeVCallOffset(int64_t Offset) {
+ return VTableComponent(CK_VCallOffset, Offset);
+ }
+
+ static VTableComponent MakeVBaseOffset(int64_t Offset) {
+ return VTableComponent(CK_VBaseOffset, Offset);
+ }
+
+ static VTableComponent MakeOffsetToTop(int64_t Offset) {
+ return VTableComponent(CK_OffsetToTop, Offset);
+ }
+
+ static VTableComponent MakeRTTI(const CXXRecordDecl *RD) {
+ return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
+ }
+
+ static VTableComponent MakeFunction(const CXXMethodDecl *MD) {
+ assert(!isa<CXXDestructorDecl>(MD) &&
+ "Don't use MakeFunction with destructors!");
+
+ return VTableComponent(CK_FunctionPointer,
+ reinterpret_cast<uintptr_t>(MD));
+ }
+
+ static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
+ return VTableComponent(CK_CompleteDtorPointer,
+ reinterpret_cast<uintptr_t>(DD));
+ }
+
+ static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
+ return VTableComponent(CK_DeletingDtorPointer,
+ reinterpret_cast<uintptr_t>(DD));
+ }
+
+ static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) {
+ assert(!isa<CXXDestructorDecl>(MD) &&
+ "Don't use MakeUnusedFunction with destructors!");
+ return VTableComponent(CK_UnusedFunctionPointer,
+ reinterpret_cast<uintptr_t>(MD));
+ }
+
+ static VTableComponent getFromOpaqueInteger(uint64_t I) {
+ return VTableComponent(I);
+ }
+
+ /// getKind - Get the kind of this vtable component.
+ Kind getKind() const {
+ return (Kind)(Value & 0x7);
+ }
+
+ int64_t getVCallOffset() const {
+ assert(getKind() == CK_VCallOffset && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ int64_t getVBaseOffset() const {
+ assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ int64_t getOffsetToTop() const {
+ assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ const CXXRecordDecl *getRTTIDecl() const {
+ assert(getKind() == CK_RTTI && "Invalid component kind!");
+
+ return reinterpret_cast<CXXRecordDecl *>(getPointer());
+ }
+
+ const CXXMethodDecl *getFunctionDecl() const {
+ assert(getKind() == CK_FunctionPointer);
+
+ return reinterpret_cast<CXXMethodDecl *>(getPointer());
+ }
+
+ const CXXDestructorDecl *getDestructorDecl() const {
+ assert((getKind() == CK_CompleteDtorPointer ||
+ getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
+
+ return reinterpret_cast<CXXDestructorDecl *>(getPointer());
+ }
+
+ const CXXMethodDecl *getUnusedFunctionDecl() const {
+ assert(getKind() == CK_UnusedFunctionPointer);
+
+ return reinterpret_cast<CXXMethodDecl *>(getPointer());
+ }
+
+private:
+ VTableComponent(Kind ComponentKind, int64_t Offset) {
+ assert((ComponentKind == CK_VCallOffset ||
+ ComponentKind == CK_VBaseOffset ||
+ ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
+ assert(Offset <= ((1LL << 56) - 1) && "Offset is too big!");
+
+ Value = ((Offset << 3) | ComponentKind);
+ }
+
+ VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
+ assert((ComponentKind == CK_RTTI ||
+ ComponentKind == CK_FunctionPointer ||
+ ComponentKind == CK_CompleteDtorPointer ||
+ ComponentKind == CK_DeletingDtorPointer ||
+ ComponentKind == CK_UnusedFunctionPointer) &&
+ "Invalid component kind!");
+
+ assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
+
+ Value = Ptr | ComponentKind;
+ }
+
+ int64_t getOffset() const {
+ assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
+ getKind() == CK_OffsetToTop) && "Invalid component kind!");
+
+ return Value >> 3;
+ }
+
+ uintptr_t getPointer() const {
+ assert((getKind() == CK_RTTI ||
+ getKind() == CK_FunctionPointer ||
+ getKind() == CK_CompleteDtorPointer ||
+ getKind() == CK_DeletingDtorPointer ||
+ getKind() == CK_UnusedFunctionPointer) &&
+ "Invalid component kind!");
+
+ return static_cast<uintptr_t>(Value & ~7ULL);
+ }
+
+ explicit VTableComponent(uint64_t Value)
+ : Value(Value) { }
+
+ /// The kind is stored in the lower 3 bits of the value. For offsets, we
+ /// make use of the facts that classes can't be larger than 2^55 bytes,
+ /// so we store the offset in the lower part of the 61 bytes that remain.
+ /// (The reason that we're not simply using a PointerIntPair here is that we
+ /// need the offsets to be 64-bit, even when on a 32-bit machine).
+ int64_t Value;
+};
+
+/// VCallOffsetMap - Keeps track of vcall offsets when building a vtable.
+struct VCallOffsetMap {
+
+ typedef std::pair<const CXXMethodDecl *, int64_t> MethodAndOffsetPairTy;
+
+ /// Offsets - Keeps track of methods and their offsets.
+ // FIXME: This should be a real map and not a vector.
+ llvm::SmallVector<MethodAndOffsetPairTy, 16> Offsets;
+
+ /// MethodsCanShareVCallOffset - Returns whether two virtual member functions
+ /// can share the same vcall offset.
+ static bool MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS);
+
+public:
+ /// AddVCallOffset - Adds a vcall offset to the map. Returns true if the
+ /// add was successful, or false if there was already a member function with
+ /// the same signature in the map.
+ bool AddVCallOffset(const CXXMethodDecl *MD, int64_t OffsetOffset);
+
+ /// getVCallOffsetOffset - Returns the vcall offset offset (relative to the
+ /// vtable address point) for the given virtual member function.
+ int64_t getVCallOffsetOffset(const CXXMethodDecl *MD);
+
+ // empty - Return whether the offset map is empty or not.
+ bool empty() const { return Offsets.empty(); }
+};
+
+static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ ASTContext &C = LHS->getASTContext(); // TODO: thread this down
+ CanQual<FunctionProtoType>
+ LT = C.getCanonicalType(LHS->getType()).getAs<FunctionProtoType>(),
+ RT = C.getCanonicalType(RHS->getType()).getAs<FunctionProtoType>();
+
+ // Fast-path matches in the canonical types.
+ if (LT == RT) return true;
+
+ // Force the signatures to match. We can't rely on the overrides
+ // list here because there isn't necessarily an inheritance
+ // relationship between the two methods.
+ if (LT.getQualifiers() != RT.getQualifiers() ||
+ LT->getNumArgs() != RT->getNumArgs())
+ return false;
+ for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I)
+ if (LT->getArgType(I) != RT->getArgType(I))
+ return false;
+ return true;
+}
+
+bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
+ const CXXMethodDecl *RHS) {
+ assert(LHS->isVirtual() && "LHS must be virtual!");
+ assert(RHS->isVirtual() && "LHS must be virtual!");
+
+ // A destructor can share a vcall offset with another destructor.
+ if (isa<CXXDestructorDecl>(LHS))
+ return isa<CXXDestructorDecl>(RHS);
+
+ // FIXME: We need to check more things here.
+
+ // The methods must have the same name.
+ DeclarationName LHSName = LHS->getDeclName();
+ DeclarationName RHSName = RHS->getDeclName();
+ if (LHSName != RHSName)
+ return false;
+
+ // And the same signatures.
+ return HasSameVirtualSignature(LHS, RHS);
+}
+
+bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
+ int64_t OffsetOffset) {
+ // Check if we can reuse an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return false;
+ }
+
+ // Add the offset.
+ Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
+ return true;
+}
+
+int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
+ // Look for an offset.
+ for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
+ if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ return Offsets[I].second;
+ }
+
+ assert(false && "Should always find a vcall offset offset!");
+ return 0;
+}
+
+/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
+class VCallAndVBaseOffsetBuilder {
+public:
+ typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
+ VBaseOffsetOffsetsMapTy;
+
+private:
+ /// MostDerivedClass - The most derived class for which we're building vcall
+ /// and vbase offsets.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ /// Context - The ASTContext which we will use for layout information.
+ ASTContext &Context;
+
+ /// Components - vcall and vbase offset components
+ typedef llvm::SmallVector<VTableComponent, 64> VTableComponentVectorTy;
+ VTableComponentVectorTy Components;
+
+ /// VisitedVirtualBases - Visited virtual bases.
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
+
+ /// VCallOffsets - Keeps track of vcall offsets.
+ VCallOffsetMap VCallOffsets;
+
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
+ /// relative to the address point.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
+ /// FinalOverriders - The final overriders of the most derived class.
+ /// (Can be null when we're not building a vtable of the most derived class).
+ const FinalOverriders *Overriders;
+
+ /// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
+ /// given base subobject.
+ void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t RealBaseOffset);
+
+ /// AddVCallOffsets - Add vcall offsets for the given base subobject.
+ void AddVCallOffsets(BaseSubobject Base, uint64_t VBaseOffset);
+
+ /// AddVBaseOffsets - Add vbase offsets for the given class.
+ void AddVBaseOffsets(const CXXRecordDecl *Base, uint64_t OffsetInLayoutClass);
+
+ /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
+ /// bytes, relative to the vtable address point.
+ int64_t getCurrentOffsetOffset() const;
+
+public:
+ VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
+ const CXXRecordDecl *LayoutClass,
+ const FinalOverriders *Overriders,
+ BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t OffsetInLayoutClass)
+ : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
+ Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
+
+ // Add vcall and vbase offsets.
+ AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
+ }
+
+ /// Methods for iterating over the components.
+ typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
+ const_iterator components_begin() const { return Components.rbegin(); }
+ const_iterator components_end() const { return Components.rend(); }
+
+ const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
+ const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
+ return VBaseOffsetOffsets;
+ }
+};
+
+void
+VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
+ bool BaseIsVirtual,
+ uint64_t RealBaseOffset) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
+
+ // Itanium C++ ABI 2.5.2:
+ // ..in classes sharing a virtual table with a primary base class, the vcall
+ // and vbase offsets added by the derived class all come before the vcall
+ // and vbase offsets required by the base class, so that the latter may be
+ // laid out as required by the base class without regard to additions from
+ // the derived class(es).
+
+ // (Since we're emitting the vcall and vbase offsets in reverse order, we'll
+ // emit them for the primary base first).
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
+
+ uint64_t PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (PrimaryBaseIsVirtual) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseIsVirtual, RealBaseOffset);
+ }
+
+ AddVBaseOffsets(Base.getBase(), RealBaseOffset);
+
+ // We only want to add vcall offsets for virtual bases.
+ if (BaseIsVirtual)
+ AddVCallOffsets(Base, RealBaseOffset);
+}
+
+int64_t VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
+ // OffsetIndex is the index of this vcall or vbase offset, relative to the
+ // vtable address point. (We subtract 3 to account for the information just
+ // above the address point, the RTTI info, the offset to top, and the
+ // vcall offset itself).
+ int64_t OffsetIndex = -(int64_t)(3 + Components.size());
+
+ // FIXME: We shouldn't use / 8 here.
+ int64_t OffsetOffset = OffsetIndex *
+ (int64_t)Context.Target.getPointerWidth(0) / 8;
+
+ return OffsetOffset;
+}
+
+void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
+ uint64_t VBaseOffset) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ // Handle the primary base first.
+ // We only want to add vcall offsets if the base is non-virtual; a virtual
+ // primary base will have its vcall and vbase offsets emitted already.
+ if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
+ // Get the base offset of the primary base.
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
+ VBaseOffset);
+ }
+
+ // Add the vcall offsets.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ int64_t OffsetOffset = getCurrentOffsetOffset();
+
+ // Don't add a vcall offset if we already have one for this member function
+ // signature.
+ if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
+ continue;
+
+ int64_t Offset = 0;
+
+ if (Overriders) {
+ // Get the final overrider.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders->getOverrider(MD, Base.getBaseOffset());
+
+ /// The vcall offset is the offset from the virtual base to the object
+ /// where the function was overridden.
+ // FIXME: We should not use / 8 here.
+ Offset = (int64_t)(Overrider.Offset - VBaseOffset) / 8;
+ }
+
+ Components.push_back(VTableComponent::MakeVCallOffset(Offset));
+ }
+
+ // And iterate over all non-virtual bases (ignoring the primary base).
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ if (BaseDecl == PrimaryBase)
+ continue;
+
+ // Get the base offset of this base.
+ uint64_t BaseOffset = Base.getBaseOffset() +
+ Layout.getBaseClassOffsetInBits(BaseDecl);
+
+ AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), VBaseOffset);
+ }
+}
+
+void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
+ uint64_t OffsetInLayoutClass) {
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Add vbase offsets.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this is a virtual base that we haven't visited before.
+ if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) {
+ // FIXME: We shouldn't use / 8 here.
+ int64_t Offset =
+ (int64_t)(LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl) -
+ OffsetInLayoutClass) / 8;
+
+ // Add the vbase offset offset.
+ assert(!VBaseOffsetOffsets.count(BaseDecl) &&
+ "vbase offset offset already exists!");
+
+ int64_t VBaseOffsetOffset = getCurrentOffsetOffset();
+ VBaseOffsetOffsets.insert(std::make_pair(BaseDecl, VBaseOffsetOffset));
+
+ Components.push_back(VTableComponent::MakeVBaseOffset(Offset));
+ }
+
+ // Check the base class looking for more vbase offsets.
+ AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
+ }
+}
+
+/// VTableBuilder - Class for building vtable layout information.
+class VTableBuilder {
+public:
+ /// PrimaryBasesSetVectorTy - A set vector of direct and indirect
+ /// primary bases.
+ typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
+ PrimaryBasesSetVectorTy;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
+ VBaseOffsetOffsetsMapTy;
+
+ typedef llvm::DenseMap<BaseSubobject, uint64_t>
+ AddressPointsMapTy;
+
+private:
+ /// VTables - Global vtable information.
+ CodeGenVTables &VTables;
+
+ /// MostDerivedClass - The most derived class for which we're building this
+ /// vtable.
+ const CXXRecordDecl *MostDerivedClass;
+
+ /// MostDerivedClassOffset - If we're building a construction vtable, this
+ /// holds the offset from the layout class to the most derived class.
+ const uint64_t MostDerivedClassOffset;
+
+ /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
+ /// base. (This only makes sense when building a construction vtable).
+ bool MostDerivedClassIsVirtual;
+
+ /// LayoutClass - The class we're using for layout information. Will be
+ /// different than the most derived class if we're building a construction
+ /// vtable.
+ const CXXRecordDecl *LayoutClass;
+
+ /// Context - The ASTContext which we will use for layout information.
+ ASTContext &Context;
+
+ /// FinalOverriders - The final overriders of the most derived class.
+ const FinalOverriders Overriders;
+
+ /// VCallOffsetsForVBases - Keeps track of vcall offsets for the virtual
+ /// bases in this vtable.
+ llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
+ /// the most derived class.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
+ /// Components - The components of the vtable being built.
+ llvm::SmallVector<VTableComponent, 64> Components;
+
+ /// AddressPoints - Address points for the vtable being built.
+ AddressPointsMapTy AddressPoints;
+
+ /// MethodInfo - Contains information about a method in a vtable.
+ /// (Used for computing 'this' pointer adjustment thunks.
+ struct MethodInfo {
+ /// BaseOffset - The base offset of this method.
+ const uint64_t BaseOffset;
+
+ /// BaseOffsetInLayoutClass - The base offset in the layout class of this
+ /// method.
+ const uint64_t BaseOffsetInLayoutClass;
+
+ /// VTableIndex - The index in the vtable that this method has.
+ /// (For destructors, this is the index of the complete destructor).
+ const uint64_t VTableIndex;
+
+ MethodInfo(uint64_t BaseOffset, uint64_t BaseOffsetInLayoutClass,
+ uint64_t VTableIndex)
+ : BaseOffset(BaseOffset),
+ BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
+ VTableIndex(VTableIndex) { }
+
+ MethodInfo() : BaseOffset(0), BaseOffsetInLayoutClass(0), VTableIndex(0) { }
+ };
+
+ typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
+
+ /// MethodInfoMap - The information for all methods in the vtable we're
+ /// currently building.
+ MethodInfoMapTy MethodInfoMap;
+
+ typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
+
+ /// VTableThunks - The thunks by vtable index in the vtable currently being
+ /// built.
+ VTableThunksMapTy VTableThunks;
+
+ typedef llvm::SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+ typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
+
+ /// Thunks - A map that contains all the thunks needed for all methods in the
+ /// most derived class for which the vtable is currently being built.
+ ThunksMapTy Thunks;
+
+ /// AddThunk - Add a thunk for the given method.
+ void AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk);
+
+ /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
+ /// part of the vtable we're currently building.
+ void ComputeThisAdjustments();
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ /// PrimaryVirtualBases - All known virtual bases who are a primary base of
+ /// some other base.
+ VisitedVirtualBasesSetTy PrimaryVirtualBases;
+
+ /// ComputeReturnAdjustment - Compute the return adjustment given a return
+ /// adjustment base offset.
+ ReturnAdjustment ComputeReturnAdjustment(BaseOffset Offset);
+
+ /// ComputeThisAdjustmentBaseOffset - Compute the base offset for adjusting
+ /// the 'this' pointer from the base subobject to the derived subobject.
+ BaseOffset ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const;
+
+ /// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
+ /// given virtual member function, its offset in the layout class and its
+ /// final overrider.
+ ThisAdjustment
+ ComputeThisAdjustment(const CXXMethodDecl *MD,
+ uint64_t BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider);
+
+ /// AddMethod - Add a single virtual member function to the vtable
+ /// components vector.
+ void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+
+ /// IsOverriderUsed - Returns whether the overrider will ever be used in this
+ /// part of the vtable.
+ ///
+ /// Itanium C++ ABI 2.5.2:
+ ///
+ /// struct A { virtual void f(); };
+ /// struct B : virtual public A { int i; };
+ /// struct C : virtual public A { int j; };
+ /// struct D : public B, public C {};
+ ///
+ /// When B and C are declared, A is a primary base in each case, so although
+ /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
+ /// adjustment is required and no thunk is generated. However, inside D
+ /// objects, A is no longer a primary base of C, so if we allowed calls to
+ /// C::f() to use the copy of A's vtable in the C subobject, we would need
+ /// to adjust this from C* to B::A*, which would require a third-party
+ /// thunk. Since we require that a call to C::f() first convert to A*,
+ /// C-in-D's copy of A's vtable is never referenced, so this is not
+ /// necessary.
+ bool IsOverriderUsed(const CXXMethodDecl *Overrider,
+ uint64_t BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ uint64_t FirstBaseOffsetInLayoutClass) const;
+
+
+ /// AddMethods - Add the methods of this base subobject and all its
+ /// primary bases to the vtable components vector.
+ void AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ uint64_t FirstBaseOffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases);
+
+ // LayoutVTable - Layout the vtable for the given base class, including its
+ // secondary vtables and any vtables for virtual bases.
+ void LayoutVTable();
+
+ /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
+ /// given base subobject, as well as all its secondary vtables.
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ ///
+ /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
+ /// in the layout class.
+ void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ bool BaseIsVirtualInLayoutClass,
+ uint64_t OffsetInLayoutClass);
+
+ /// LayoutSecondaryVTables - Layout the secondary vtables for the given base
+ /// subobject.
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ void LayoutSecondaryVTables(BaseSubobject Base, bool BaseIsMorallyVirtual,
+ uint64_t OffsetInLayoutClass);
+
+ /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
+ /// class hierarchy.
+ void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ uint64_t OffsetInLayoutClass,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// LayoutVTablesForVirtualBases - Layout vtables for all virtual bases of the
+ /// given base (excluding any primary bases).
+ void LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// isBuildingConstructionVTable - Return whether this vtable builder is
+ /// building a construction vtable.
+ bool isBuildingConstructorVTable() const {
+ return MostDerivedClass != LayoutClass;
+ }
+
+public:
+ VTableBuilder(CodeGenVTables &VTables, const CXXRecordDecl *MostDerivedClass,
+ uint64_t MostDerivedClassOffset, bool MostDerivedClassIsVirtual,
+ const CXXRecordDecl *LayoutClass)
+ : VTables(VTables), MostDerivedClass(MostDerivedClass),
+ MostDerivedClassOffset(MostDerivedClassOffset),
+ MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
+ LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
+ Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
+
+ LayoutVTable();
+ }
+
+ ThunksMapTy::const_iterator thunks_begin() const {
+ return Thunks.begin();
+ }
+
+ ThunksMapTy::const_iterator thunks_end() const {
+ return Thunks.end();
+ }
+
+ const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
+ return VBaseOffsetOffsets;
+ }
+
+ /// getNumVTableComponents - Return the number of components in the vtable
+ /// currently built.
+ uint64_t getNumVTableComponents() const {
+ return Components.size();
+ }
+
+ const uint64_t *vtable_components_data_begin() const {
+ return reinterpret_cast<const uint64_t *>(Components.begin());
+ }
+
+ const uint64_t *vtable_components_data_end() const {
+ return reinterpret_cast<const uint64_t *>(Components.end());
+ }
+
+ AddressPointsMapTy::const_iterator address_points_begin() const {
+ return AddressPoints.begin();
+ }
+
+ AddressPointsMapTy::const_iterator address_points_end() const {
+ return AddressPoints.end();
+ }
+
+ VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
+ return VTableThunks.begin();
+ }
+
+ VTableThunksMapTy::const_iterator vtable_thunks_end() const {
+ return VTableThunks.end();
+ }
+
+ /// dumpLayout - Dump the vtable layout.
+ void dumpLayout(llvm::raw_ostream&);
+};
+
+void VTableBuilder::AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
+ assert(!isBuildingConstructorVTable() &&
+ "Can't add thunks for construction vtable");
+
+ llvm::SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
+
+ // Check if we have this thunk already.
+ if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
+ ThunksVector.end())
+ return;
+
+ ThunksVector.push_back(Thunk);
+}
+
+typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
+
+/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
+/// the overridden methods that the function decl overrides.
+static void
+ComputeAllOverriddenMethods(const CXXMethodDecl *MD,
+ OverriddenMethodsSetTy& OverriddenMethods) {
+ assert(MD->isVirtual() && "Method is not virtual!");
+
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ OverriddenMethods.insert(OverriddenMD);
+
+ ComputeAllOverriddenMethods(OverriddenMD, OverriddenMethods);
+ }
+}
+
+void VTableBuilder::ComputeThisAdjustments() {
+ // Now go through the method info map and see if any of the methods need
+ // 'this' pointer adjustments.
+ for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
+ E = MethodInfoMap.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const MethodInfo &MethodInfo = I->second;
+
+ // Ignore adjustments for unused function pointers.
+ uint64_t VTableIndex = MethodInfo.VTableIndex;
+ if (Components[VTableIndex].getKind() ==
+ VTableComponent::CK_UnusedFunctionPointer)
+ continue;
+
+ // Get the final overrider for this method.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(MD, MethodInfo.BaseOffset);
+
+ // Check if we need an adjustment at all.
+ if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
+ // When a return thunk is needed by a derived class that overrides a
+ // virtual base, gcc uses a virtual 'this' adjustment as well.
+ // While the thunk itself might be needed by vtables in subclasses or
+ // in construction vtables, there doesn't seem to be a reason for using
+ // the thunk in this vtable. Still, we do so to match gcc.
+ if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
+ continue;
+ }
+
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
+
+ if (ThisAdjustment.isEmpty())
+ continue;
+
+ // Add it.
+ VTableThunks[VTableIndex].This = ThisAdjustment;
+
+ if (isa<CXXDestructorDecl>(MD)) {
+ // Add an adjustment for the deleting destructor as well.
+ VTableThunks[VTableIndex + 1].This = ThisAdjustment;
+ }
+ }
+
+ /// Clear the method info map.
+ MethodInfoMap.clear();
+
+ if (isBuildingConstructorVTable()) {
+ // We don't need to store thunk information for construction vtables.
+ return;
+ }
+
+ for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(),
+ E = VTableThunks.end(); I != E; ++I) {
+ const VTableComponent &Component = Components[I->first];
+ const ThunkInfo &Thunk = I->second;
+ const CXXMethodDecl *MD;
+
+ switch (Component.getKind()) {
+ default:
+ llvm_unreachable("Unexpected vtable component kind!");
+ case VTableComponent::CK_FunctionPointer:
+ MD = Component.getFunctionDecl();
+ break;
+ case VTableComponent::CK_CompleteDtorPointer:
+ MD = Component.getDestructorDecl();
+ break;
+ case VTableComponent::CK_DeletingDtorPointer:
+ // We've already added the thunk when we saw the complete dtor pointer.
+ continue;
+ }
+
+ if (MD->getParent() == MostDerivedClass)
+ AddThunk(MD, Thunk);
+ }
+}
+
+ReturnAdjustment VTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
+ ReturnAdjustment Adjustment;
+
+ if (!Offset.isEmpty()) {
+ if (Offset.VirtualBase) {
+ // Get the virtual base offset offset.
+ if (Offset.DerivedClass == MostDerivedClass) {
+ // We can get the offset offset directly from our map.
+ Adjustment.VBaseOffsetOffset =
+ VBaseOffsetOffsets.lookup(Offset.VirtualBase);
+ } else {
+ Adjustment.VBaseOffsetOffset =
+ VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
+ Offset.VirtualBase);
+ }
+ }
+
+ Adjustment.NonVirtual = Offset.NonVirtualOffset;
+ }
+
+ return Adjustment;
+}
+
+BaseOffset
+VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
+ BaseSubobject Derived) const {
+ const CXXRecordDecl *BaseRD = Base.getBase();
+ const CXXRecordDecl *DerivedRD = Derived.getBase();
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true,
+ /*RecordPaths=*/true, /*DetectVirtual=*/true);
+
+ if (!const_cast<CXXRecordDecl *>(DerivedRD)->
+ isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) {
+ assert(false && "Class must be derived from the passed in base class!");
+ return BaseOffset();
+ }
+
+ // We have to go through all the paths, and see which one leads us to the
+ // right base subobject.
+ for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
+ I != E; ++I) {
+ BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
+
+ // FIXME: Should not use * 8 here.
+ uint64_t OffsetToBaseSubobject = Offset.NonVirtualOffset * 8;
+
+ if (Offset.VirtualBase) {
+ // If we have a virtual base class, the non-virtual offset is relative
+ // to the virtual base class offset.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ /// Get the virtual base offset, relative to the most derived class
+ /// layout.
+ OffsetToBaseSubobject +=
+ LayoutClassLayout.getVBaseClassOffsetInBits(Offset.VirtualBase);
+ } else {
+ // Otherwise, the non-virtual offset is relative to the derived class
+ // offset.
+ OffsetToBaseSubobject += Derived.getBaseOffset();
+ }
+
+ // Check if this path gives us the right base subobject.
+ if (OffsetToBaseSubobject == Base.getBaseOffset()) {
+ // Since we're going from the base class _to_ the derived class, we'll
+ // invert the non-virtual offset here.
+ Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
+ return Offset;
+ }
+ }
+
+ return BaseOffset();
+}
+
+ThisAdjustment
+VTableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
+ uint64_t BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider) {
+ // Ignore adjustments for pure virtual member functions.
+ if (Overrider.Method->isPure())
+ return ThisAdjustment();
+
+ BaseSubobject OverriddenBaseSubobject(MD->getParent(),
+ BaseOffsetInLayoutClass);
+
+ BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
+ Overrider.Offset);
+
+ // Compute the adjustment offset.
+ BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
+ OverriderBaseSubobject);
+ if (Offset.isEmpty())
+ return ThisAdjustment();
+
+ ThisAdjustment Adjustment;
+
+ if (Offset.VirtualBase) {
+ // Get the vcall offset map for this virtual base.
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
+
+ if (VCallOffsets.empty()) {
+ // We don't have vcall offsets for this virtual base, go ahead and
+ // build them.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
+ /*FinalOverriders=*/0,
+ BaseSubobject(Offset.VirtualBase, 0),
+ /*BaseIsVirtual=*/true,
+ /*OffsetInLayoutClass=*/0);
+
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
+ Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
+ }
+
+ // Set the non-virtual part of the adjustment.
+ Adjustment.NonVirtual = Offset.NonVirtualOffset;
+
+ return Adjustment;
+}
+
+void
+VTableBuilder::AddMethod(const CXXMethodDecl *MD,
+ ReturnAdjustment ReturnAdjustment) {
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ assert(ReturnAdjustment.isEmpty() &&
+ "Destructor can't have return adjustment!");
+
+ // Add both the complete destructor and the deleting destructor.
+ Components.push_back(VTableComponent::MakeCompleteDtor(DD));
+ Components.push_back(VTableComponent::MakeDeletingDtor(DD));
+ } else {
+ // Add the return adjustment if necessary.
+ if (!ReturnAdjustment.isEmpty())
+ VTableThunks[Components.size()].Return = ReturnAdjustment;
+
+ // Add the function.
+ Components.push_back(VTableComponent::MakeFunction(MD));
+ }
+}
+
+/// OverridesIndirectMethodInBase - Return whether the given member function
+/// overrides any methods in the set of given bases.
+/// Unlike OverridesMethodInBase, this checks "overriders of overriders".
+/// For example, if we have:
+///
+/// struct A { virtual void f(); }
+/// struct B : A { virtual void f(); }
+/// struct C : B { virtual void f(); }
+///
+/// OverridesIndirectMethodInBase will return true if given C::f as the method
+/// and { A } as the set of bases.
+static bool
+OverridesIndirectMethodInBases(const CXXMethodDecl *MD,
+ VTableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ if (Bases.count(MD->getParent()))
+ return true;
+
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ // Check "indirect overriders".
+ if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
+ return true;
+ }
+
+ return false;
+}
+
+bool
+VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider,
+ uint64_t BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ uint64_t FirstBaseOffsetInLayoutClass) const {
+ // If the base and the first base in the primary base chain have the same
+ // offsets, then this overrider will be used.
+ if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
+ return true;
+
+ // We know now that Base (or a direct or indirect base of it) is a primary
+ // base in part of the class hierarchy, but not a primary base in the most
+ // derived class.
+
+ // If the overrider is the first base in the primary base chain, we know
+ // that the overrider will be used.
+ if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
+ return true;
+
+ VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
+
+ const CXXRecordDecl *RD = FirstBaseInPrimaryBaseChain;
+ PrimaryBases.insert(RD);
+
+ // Now traverse the base chain, starting with the first base, until we find
+ // the base that is no longer a primary base.
+ while (true) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ break;
+
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ // Now check if this is the primary base that is not a primary base in the
+ // most derived class.
+ if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) !=
+ FirstBaseOffsetInLayoutClass) {
+ // We found it, stop walking the chain.
+ break;
+ }
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should always be at offset 0!");
+ }
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ assert(false && "Found a duplicate primary base!");
+
+ RD = PrimaryBase;
+ }
+
+ // If the final overrider is an override of one of the primary bases,
+ // then we know that it will be used.
+ return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
+}
+
+/// FindNearestOverriddenMethod - Given a method, returns the overridden method
+/// from the nearest base. Returns null if no method was found.
+static const CXXMethodDecl *
+FindNearestOverriddenMethod(const CXXMethodDecl *MD,
+ VTableBuilder::PrimaryBasesSetVectorTy &Bases) {
+ OverriddenMethodsSetTy OverriddenMethods;
+ ComputeAllOverriddenMethods(MD, OverriddenMethods);
+
+ for (int I = Bases.size(), E = 0; I != E; --I) {
+ const CXXRecordDecl *PrimaryBase = Bases[I - 1];
+
+ // Now check the overriden methods.
+ for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(),
+ E = OverriddenMethods.end(); I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+
+ // We found our overridden method.
+ if (OverriddenMD->getParent() == PrimaryBase)
+ return OverriddenMD;
+ }
+ }
+
+ return 0;
+}
+
+void
+VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
+ const CXXRecordDecl *FirstBaseInPrimaryBaseChain,
+ uint64_t FirstBaseOffsetInLayoutClass,
+ PrimaryBasesSetVectorTy &PrimaryBases) {
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ uint64_t PrimaryBaseOffset;
+ uint64_t PrimaryBaseOffsetInLayoutClass;
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ PrimaryBaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
+ }
+
+ AddMethods(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
+ FirstBaseOffsetInLayoutClass, PrimaryBases);
+
+ if (!PrimaryBases.insert(PrimaryBase))
+ assert(false && "Found a duplicate primary base!");
+ }
+
+ // Now go through all virtual member functions and add them.
+ for (CXXRecordDecl::method_iterator I = RD->method_begin(),
+ E = RD->method_end(); I != E; ++I) {
+ const CXXMethodDecl *MD = *I;
+
+ if (!MD->isVirtual())
+ continue;
+
+ // Get the final overrider.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(MD, Base.getBaseOffset());
+
+ // Check if this virtual member function overrides a method in a primary
+ // base. If this is the case, and the return type doesn't require adjustment
+ // then we can just use the member function from the primary base.
+ if (const CXXMethodDecl *OverriddenMD =
+ FindNearestOverriddenMethod(MD, PrimaryBases)) {
+ if (ComputeReturnAdjustmentBaseOffset(Context, MD,
+ OverriddenMD).isEmpty()) {
+ // Replace the method info of the overridden method with our own
+ // method.
+ assert(MethodInfoMap.count(OverriddenMD) &&
+ "Did not find the overridden method!");
+ MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
+
+ MethodInfo MethodInfo(Base.getBaseOffset(),
+ BaseOffsetInLayoutClass,
+ OverriddenMethodInfo.VTableIndex);
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+ MethodInfoMap.erase(OverriddenMD);
+
+ // If the overridden method exists in a virtual base class or a direct
+ // or indirect base class of a virtual base class, we need to emit a
+ // thunk if we ever have a class hierarchy where the base class is not
+ // a primary base in the complete object.
+ if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
+ // Compute the this adjustment.
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
+ Overrider);
+
+ if (ThisAdjustment.VCallOffsetOffset &&
+ Overrider.Method->getParent() == MostDerivedClass) {
+
+ // There's no return adjustment from OverriddenMD and MD,
+ // but that doesn't mean there isn't one between MD and
+ // the final overrider.
+ BaseOffset ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+ ReturnAdjustment ReturnAdjustment =
+ ComputeReturnAdjustment(ReturnAdjustmentOffset);
+
+ // This is a virtual thunk for the most derived class, add it.
+ AddThunk(Overrider.Method,
+ ThunkInfo(ThisAdjustment, ReturnAdjustment));
+ }
+ }
+
+ continue;
+ }
+ }
+
+ // Insert the method info for this method.
+ MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
+ Components.size());
+
+ assert(!MethodInfoMap.count(MD) &&
+ "Should not have method info for this method yet!");
+ MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
+
+ // Check if this overrider is going to be used.
+ const CXXMethodDecl *OverriderMD = Overrider.Method;
+ if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
+ FirstBaseInPrimaryBaseChain,
+ FirstBaseOffsetInLayoutClass)) {
+ Components.push_back(VTableComponent::MakeUnusedFunction(OverriderMD));
+ continue;
+ }
+
+ // Check if this overrider needs a return adjustment.
+ // We don't want to do this for pure virtual member functions.
+ BaseOffset ReturnAdjustmentOffset;
+ if (!OverriderMD->isPure()) {
+ ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
+ }
+
+ ReturnAdjustment ReturnAdjustment =
+ ComputeReturnAdjustment(ReturnAdjustmentOffset);
+
+ AddMethod(Overrider.Method, ReturnAdjustment);
+ }
+}
+
+void VTableBuilder::LayoutVTable() {
+ LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, 0),
+ /*BaseIsMorallyVirtual=*/false,
+ MostDerivedClassIsVirtual,
+ MostDerivedClassOffset);
+
+ VisitedVirtualBasesSetTy VBases;
+
+ // Determine the primary virtual bases.
+ DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
+ VBases);
+ VBases.clear();
+
+ LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
+}
+
+void
+VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ bool BaseIsVirtualInLayoutClass,
+ uint64_t OffsetInLayoutClass) {
+ assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
+
+ // Add vcall and vbase offsets for this vtable.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
+ Base, BaseIsVirtualInLayoutClass,
+ OffsetInLayoutClass);
+ Components.append(Builder.components_begin(), Builder.components_end());
+
+ // Check if we need to add these vcall offsets.
+ if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.getBase()];
+
+ if (VCallOffsets.empty())
+ VCallOffsets = Builder.getVCallOffsets();
+ }
+
+ // If we're laying out the most derived class we want to keep track of the
+ // virtual base class offset offsets.
+ if (Base.getBase() == MostDerivedClass)
+ VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
+
+ // Add the offset to top.
+ // FIXME: We should not use / 8 here.
+ int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass -
+ MostDerivedClassOffset) / 8;
+ Components.push_back(VTableComponent::MakeOffsetToTop(OffsetToTop));
+
+ // Next, add the RTTI.
+ Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
+
+ uint64_t AddressPoint = Components.size();
+
+ // Now go through all virtual member functions and add them.
+ PrimaryBasesSetVectorTy PrimaryBases;
+ AddMethods(Base, OffsetInLayoutClass, Base.getBase(), OffsetInLayoutClass,
+ PrimaryBases);
+
+ // Compute 'this' pointer adjustments.
+ ComputeThisAdjustments();
+
+ // Add all address points.
+ const CXXRecordDecl *RD = Base.getBase();
+ while (true) {
+ AddressPoints.insert(std::make_pair(BaseSubobject(RD, OffsetInLayoutClass),
+ AddressPoint));
+
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (!PrimaryBase)
+ break;
+
+ if (Layout.isPrimaryBaseVirtual()) {
+ // Check if this virtual primary base is a primary base in the layout
+ // class. If it's not, we don't want to add it.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) !=
+ OffsetInLayoutClass) {
+ // We don't want to add this class (or any of its primary bases).
+ break;
+ }
+ }
+
+ RD = PrimaryBase;
+ }
+
+ // Layout secondary vtables.
+ LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
+}
+
+void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ uint64_t OffsetInLayoutClass) {
+ // Itanium C++ ABI 2.5.2:
+ // Following the primary virtual table of a derived class are secondary
+ // virtual tables for each of its proper base classes, except any primary
+ // base(s) with which it shares its primary virtual table.
+
+ const CXXRecordDecl *RD = Base.getBase();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ // Ignore virtual bases, we'll emit them later.
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Ignore bases that don't have a vtable.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
+ if (isBuildingConstructorVTable()) {
+ // Itanium C++ ABI 2.6.4:
+ // Some of the base class subobjects may not need construction virtual
+ // tables, which will therefore not be present in the construction
+ // virtual table group, even though the subobject virtual tables are
+ // present in the main virtual table group for the complete object.
+ if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
+ continue;
+ }
+
+ // Get the base offset of this base.
+ uint64_t RelativeBaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl);
+ uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
+
+ uint64_t BaseOffsetInLayoutClass = OffsetInLayoutClass + RelativeBaseOffset;
+
+ // Don't emit a secondary vtable for a primary base. We might however want
+ // to emit secondary vtables for other bases of this base.
+ if (BaseDecl == PrimaryBase) {
+ LayoutSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
+ BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
+ continue;
+ }
+
+ // Layout the primary vtable (and any secondary vtables) for this base.
+ LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
+ BaseIsMorallyVirtual,
+ /*BaseIsVirtualInLayoutClass=*/false,
+ BaseOffsetInLayoutClass);
+ }
+}
+
+void
+VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ uint64_t OffsetInLayoutClass,
+ VisitedVirtualBasesSetTy &VBases) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Check if this base has a primary base.
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+
+ // Check if it's virtual.
+ if (Layout.isPrimaryBaseVirtual()) {
+ bool IsPrimaryVirtualBase = true;
+
+ if (isBuildingConstructorVTable()) {
+ // Check if the base is actually a primary base in the class we use for
+ // layout.
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ uint64_t PrimaryBaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
+
+ // We know that the base is not a primary base in the layout class if
+ // the base offsets are different.
+ if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
+ IsPrimaryVirtualBase = false;
+ }
+
+ if (IsPrimaryVirtualBase)
+ PrimaryVirtualBases.insert(PrimaryBase);
+ }
+ }
+
+ // Traverse bases, looking for more primary virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ uint64_t BaseOffsetInLayoutClass;
+
+ if (I->isVirtual()) {
+ if (!VBases.insert(BaseDecl))
+ continue;
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+
+ BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+ } else {
+ BaseOffsetInLayoutClass =
+ OffsetInLayoutClass + Layout.getBaseClassOffsetInBits(BaseDecl);
+ }
+
+ DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
+ }
+}
+
+void
+VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ // Itanium C++ ABI 2.5.2:
+ // Then come the virtual base virtual tables, also in inheritance graph
+ // order, and again excluding primary bases (which share virtual tables with
+ // the classes for which they are primary).
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ // Check if this base needs a vtable. (If it's virtual, not a primary base
+ // of some other class, and we haven't visited it before).
+ if (I->isVirtual() && BaseDecl->isDynamicClass() &&
+ !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) {
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+ uint64_t BaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
+ uint64_t BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
+
+ LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
+ /*BaseIsMorallyVirtual=*/true,
+ /*BaseIsVirtualInLayoutClass=*/true,
+ BaseOffsetInLayoutClass);
+ }
+
+ // We only need to check the base for virtual base vtables if it actually
+ // has virtual bases.
+ if (BaseDecl->getNumVBases())
+ LayoutVTablesForVirtualBases(BaseDecl, VBases);
+ }
+}
+
+/// dumpLayout - Dump the vtable layout.
+void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) {
+
+ if (isBuildingConstructorVTable()) {
+ Out << "Construction vtable for ('";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "', ";
+ // FIXME: Don't use / 8 .
+ Out << MostDerivedClassOffset / 8 << ") in '";
+ Out << LayoutClass->getQualifiedNameAsString();
+ } else {
+ Out << "Vtable for '";
+ Out << MostDerivedClass->getQualifiedNameAsString();
+ }
+ Out << "' (" << Components.size() << " entries).\n";
+
+ // Iterate through the address points and insert them into a new map where
+ // they are keyed by the index and not the base object.
+ // Since an address point can be shared by multiple subobjects, we use an
+ // STL multimap.
+ std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
+ for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(),
+ E = AddressPoints.end(); I != E; ++I) {
+ const BaseSubobject& Base = I->first;
+ uint64_t Index = I->second;
+
+ AddressPointsByIndex.insert(std::make_pair(Index, Base));
+ }
+
+ for (unsigned I = 0, E = Components.size(); I != E; ++I) {
+ uint64_t Index = I;
+
+ Out << llvm::format("%4d | ", I);
+
+ const VTableComponent &Component = Components[I];
+
+ // Dump the component.
+ switch (Component.getKind()) {
+
+ case VTableComponent::CK_VCallOffset:
+ Out << "vcall_offset (" << Component.getVCallOffset() << ")";
+ break;
+
+ case VTableComponent::CK_VBaseOffset:
+ Out << "vbase_offset (" << Component.getVBaseOffset() << ")";
+ break;
+
+ case VTableComponent::CK_OffsetToTop:
+ Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
+ break;
+
+ case VTableComponent::CK_RTTI:
+ Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI";
+ break;
+
+ case VTableComponent::CK_FunctionPointer: {
+ const CXXMethodDecl *MD = Component.getFunctionDecl();
+
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+ Out << Str;
+ if (MD->isPure())
+ Out << " [pure]";
+
+ ThunkInfo Thunk = VTableThunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this function pointer has a return adjustment, dump it.
+ if (!Thunk.Return.isEmpty()) {
+ Out << "\n [return adjustment: ";
+ Out << Thunk.Return.NonVirtual << " non-virtual";
+
+ if (Thunk.Return.VBaseOffsetOffset) {
+ Out << ", " << Thunk.Return.VBaseOffsetOffset;
+ Out << " vbase offset offset";
+ }
+
+ Out << ']';
+ }
+
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+
+ Out << ']';
+ }
+ }
+
+ break;
+ }
+
+ case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_DeletingDtorPointer: {
+ bool IsComplete =
+ Component.getKind() == VTableComponent::CK_CompleteDtorPointer;
+
+ const CXXDestructorDecl *DD = Component.getDestructorDecl();
+
+ Out << DD->getQualifiedNameAsString();
+ if (IsComplete)
+ Out << "() [complete]";
+ else
+ Out << "() [deleting]";
+
+ if (DD->isPure())
+ Out << " [pure]";
+
+ ThunkInfo Thunk = VTableThunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this destructor has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+
+ Out << ']';
+ }
+ }
+
+ break;
+ }
+
+ case VTableComponent::CK_UnusedFunctionPointer: {
+ const CXXMethodDecl *MD = Component.getUnusedFunctionDecl();
+
+ std::string Str =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+ Out << "[unused] " << Str;
+ if (MD->isPure())
+ Out << " [pure]";
+ }
+
+ }
+
+ Out << '\n';
+
+ // Dump the next address point.
+ uint64_t NextIndex = Index + 1;
+ if (AddressPointsByIndex.count(NextIndex)) {
+ if (AddressPointsByIndex.count(NextIndex) == 1) {
+ const BaseSubobject &Base =
+ AddressPointsByIndex.find(NextIndex)->second;
+
+ // FIXME: Instead of dividing by 8, we should be using CharUnits.
+ Out << " -- (" << Base.getBase()->getQualifiedNameAsString();
+ Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
+ } else {
+ uint64_t BaseOffset =
+ AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
+
+ // We store the class names in a set to get a stable order.
+ std::set<std::string> ClassNames;
+ for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
+ AddressPointsByIndex.lower_bound(NextIndex), E =
+ AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
+ assert(I->second.getBaseOffset() == BaseOffset &&
+ "Invalid base offset!");
+ const CXXRecordDecl *RD = I->second.getBase();
+ ClassNames.insert(RD->getQualifiedNameAsString());
+ }
+
+ for (std::set<std::string>::const_iterator I = ClassNames.begin(),
+ E = ClassNames.end(); I != E; ++I) {
+ // FIXME: Instead of dividing by 8, we should be using CharUnits.
+ Out << " -- (" << *I;
+ Out << ", " << BaseOffset / 8 << ") vtable address --\n";
+ }
+ }
+ }
+ }
+
+ Out << '\n';
+
+ if (isBuildingConstructorVTable())
+ return;
+
+ if (MostDerivedClass->getNumVBases()) {
+ // We store the virtual base class names and their offsets in a map to get
+ // a stable order.
+
+ std::map<std::string, int64_t> ClassNamesAndOffsets;
+ for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
+ E = VBaseOffsetOffsets.end(); I != E; ++I) {
+ std::string ClassName = I->first->getQualifiedNameAsString();
+ int64_t OffsetOffset = I->second;
+ ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
+ }
+
+ Out << "Virtual base offset offsets for '";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "' (";
+ Out << ClassNamesAndOffsets.size();
+ Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
+
+ for (std::map<std::string, int64_t>::const_iterator I =
+ ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
+ I != E; ++I)
+ Out << " " << I->first << " | " << I->second << '\n';
+
+ Out << "\n";
+ }
+
+ if (!Thunks.empty()) {
+ // We store the method names in a map to get a stable order.
+ std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
+
+ for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
+ I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ std::string MethodName =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+
+ MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
+ }
+
+ for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
+ MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
+ I != E; ++I) {
+ const std::string &MethodName = I->first;
+ const CXXMethodDecl *MD = I->second;
+
+ ThunkInfoVectorTy ThunksVector = Thunks[MD];
+ std::sort(ThunksVector.begin(), ThunksVector.end());
+
+ Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
+ Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
+
+ for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
+ const ThunkInfo &Thunk = ThunksVector[I];
+
+ Out << llvm::format("%4d | ", I);
+
+ // If this function pointer has a return pointer adjustment, dump it.
+ if (!Thunk.Return.isEmpty()) {
+ Out << "return adjustment: " << Thunk.This.NonVirtual;
+ Out << " non-virtual";
+ if (Thunk.Return.VBaseOffsetOffset) {
+ Out << ", " << Thunk.Return.VBaseOffsetOffset;
+ Out << " vbase offset offset";
+ }
+
+ if (!Thunk.This.isEmpty())
+ Out << "\n ";
+ }
+
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+ }
+
+ Out << '\n';
+ }
+
+ Out << '\n';
+
+ }
+ }
+}
+
+}
+
+static void
+CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
+ VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) {
+ while (RD) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ if (PrimaryBase)
+ PrimaryBases.insert(PrimaryBase);
+
+ RD = PrimaryBase;
+ }
+}
+
+void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
+
+ // Itanium C++ ABI 2.5.2:
+ // The order of the virtual function pointers in a virtual table is the
+ // order of declaration of the corresponding member functions in the class.
+ //
+ // There is an entry for any virtual function declared in a class,
+ // whether it is a new function or overrides a base class function,
+ // unless it overrides a function from the primary base, and conversion
+ // between their return types does not require an adjustment.
+
+ int64_t CurrentIndex = 0;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+
+ if (PrimaryBase) {
+ assert(PrimaryBase->isDefinition() &&
+ "Should have the definition decl of the primary base!");
+
+ // Since the record decl shares its vtable pointer with the primary base
+ // we need to start counting at the end of the primary base's vtable.
+ CurrentIndex = getNumVirtualFunctionPointers(PrimaryBase);
+ }
+
+ // Collect all the primary bases, so we can check whether methods override
+ // a method from the base.
+ VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
+ CollectPrimaryBases(RD, CGM.getContext(), PrimaryBases);
+
+ const CXXDestructorDecl *ImplicitVirtualDtor = 0;
+
+ for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+ e = RD->method_end(); i != e; ++i) {
+ const CXXMethodDecl *MD = *i;
+
+ // We only want virtual methods.
+ if (!MD->isVirtual())
+ continue;
+
+ // Check if this method overrides a method in the primary base.
+ if (const CXXMethodDecl *OverriddenMD =
+ FindNearestOverriddenMethod(MD, PrimaryBases)) {
+ // Check if converting from the return type of the method to the
+ // return type of the overridden method requires conversion.
+ if (ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD,
+ OverriddenMD).isEmpty()) {
+ // This index is shared between the index in the vtable of the primary
+ // base class.
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ const CXXDestructorDecl *OverriddenDD =
+ cast<CXXDestructorDecl>(OverriddenMD);
+
+ // Add both the complete and deleting entries.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Complete));
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] =
+ getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting));
+ } else {
+ MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD);
+ }
+
+ // We don't need to add an entry for this method.
+ continue;
+ }
+ }
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (MD->isImplicit()) {
+ assert(!ImplicitVirtualDtor &&
+ "Did already see an implicit virtual dtor!");
+ ImplicitVirtualDtor = DD;
+ continue;
+ }
+
+ // Add the complete dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = CurrentIndex++;
+
+ // Add the deleting dtor.
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++;
+ } else {
+ // Add the entry.
+ MethodVTableIndices[MD] = CurrentIndex++;
+ }
+ }
+
+ if (ImplicitVirtualDtor) {
+ // Itanium C++ ABI 2.5.2:
+ // If a class has an implicitly-defined virtual destructor,
+ // its entries come after the declared virtual function pointers.
+
+ // Add the complete dtor.
+ MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Complete)] =
+ CurrentIndex++;
+
+ // Add the deleting dtor.
+ MethodVTableIndices[GlobalDecl(ImplicitVirtualDtor, Dtor_Deleting)] =
+ CurrentIndex++;
+ }
+
+ NumVirtualFunctionPointers[RD] = CurrentIndex;
+}
+
+bool CodeGenVTables::ShouldEmitVTableInThisTU(const CXXRecordDecl *RD) {
+ assert(RD->isDynamicClass() && "Non dynamic classes have no VTable.");
+
+ TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind();
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ return false;
+
+ const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
+ if (!KeyFunction)
+ return true;
+
+ // Itanium C++ ABI, 5.2.6 Instantiated Templates:
+ // An instantiation of a class template requires:
+ // - In the object where instantiated, the virtual table...
+ if (TSK == TSK_ImplicitInstantiation ||
+ TSK == TSK_ExplicitInstantiationDefinition)
+ return true;
+
+ // If we're building with optimization, we always emit VTables since that
+ // allows for virtual function calls to be devirtualized.
+ // (We don't want to do this in -fapple-kext mode however).
+ if (CGM.getCodeGenOpts().OptimizationLevel && !CGM.getLangOptions().AppleKext)
+ return true;
+
+ return KeyFunction->hasBody();
+}
+
+uint64_t CodeGenVTables::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
+ NumVirtualFunctionPointers.find(RD);
+ if (I != NumVirtualFunctionPointers.end())
+ return I->second;
+
+ ComputeMethodVTableIndices(RD);
+
+ I = NumVirtualFunctionPointers.find(RD);
+ assert(I != NumVirtualFunctionPointers.end() && "Did not find entry!");
+ return I->second;
+}
+
+uint64_t CodeGenVTables::getMethodVTableIndex(GlobalDecl GD) {
+ MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
+ if (I != MethodVTableIndices.end())
+ return I->second;
+
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
+
+ ComputeMethodVTableIndices(RD);
+
+ I = MethodVTableIndices.find(GD);
+ assert(I != MethodVTableIndices.end() && "Did not find index!");
+ return I->second;
+}
+
+int64_t CodeGenVTables::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase) {
+ ClassPairTy ClassPair(RD, VBase);
+
+ VirtualBaseClassOffsetOffsetsMapTy::iterator I =
+ VirtualBaseClassOffsetOffsets.find(ClassPair);
+ if (I != VirtualBaseClassOffsetOffsets.end())
+ return I->second;
+
+ VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0,
+ BaseSubobject(RD, 0),
+ /*BaseIsVirtual=*/false,
+ /*OffsetInLayoutClass=*/0);
+
+ for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
+ Builder.getVBaseOffsetOffsets().begin(),
+ E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
+ // Insert all types.
+ ClassPairTy ClassPair(RD, I->first);
+
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
+ }
+
+ I = VirtualBaseClassOffsetOffsets.find(ClassPair);
+ assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
+
+ return I->second;
+}
+
+uint64_t
+CodeGenVTables::getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD) {
+ assert(AddressPoints.count(std::make_pair(RD, Base)) &&
+ "Did not find address point!");
+
+ uint64_t AddressPoint = AddressPoints.lookup(std::make_pair(RD, Base));
+ assert(AddressPoint && "Address point must not be zero!");
+
+ return AddressPoint;
+}
+
+llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+ // Compute the mangled name.
+ llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
+ if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
+ getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
+ Thunk.This, Out);
+ else
+ getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Out);
+ Out.flush();
+
+ const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
+ return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true);
+}
+
+static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ int64_t NonVirtualAdjustment,
+ int64_t VirtualAdjustment) {
+ if (!NonVirtualAdjustment && !VirtualAdjustment)
+ return Ptr;
+
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+
+ llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
+
+ if (NonVirtualAdjustment) {
+ // Do the non-virtual adjustment.
+ V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
+ }
+
+ if (VirtualAdjustment) {
+ const llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+
+ // Do the virtual adjustment.
+ llvm::Value *VTablePtrPtr =
+ CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo());
+
+ llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
+
+ llvm::Value *OffsetPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
+
+ OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
+
+ // Load the adjustment offset from the vtable.
+ llvm::Value *Offset = CGF.Builder.CreateLoad(OffsetPtr);
+
+ // Adjust our pointer.
+ V = CGF.Builder.CreateInBoundsGEP(V, Offset);
+ }
+
+ // Cast back to the original type.
+ return CGF.Builder.CreateBitCast(V, Ptr->getType());
+}
+
+static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk, llvm::Function *Fn) {
+ CGM.setGlobalVisibility(Fn, MD);
+
+ if (!CGM.getCodeGenOpts().HiddenWeakVTables)
+ return;
+
+ // If the thunk has weak/linkonce linkage, but the function must be
+ // emitted in every translation unit that references it, then we can
+ // emit its thunks with hidden visibility, since its thunks must be
+ // emitted when the function is.
+
+ // This follows CodeGenModule::setTypeVisibility; see the comments
+ // there for explanation.
+
+ if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage &&
+ Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) ||
+ Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
+ return;
+
+ if (MD->hasAttr<VisibilityAttr>())
+ return;
+
+ switch (MD->getTemplateSpecializationKind()) {
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ return;
+
+ case TSK_Undeclared:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ if (!CGM.getCodeGenOpts().HiddenWeakTemplateVTables)
+ return;
+ break;
+ }
+
+ // If there's an explicit definition, and that definition is
+ // out-of-line, then we can't assume that all users will have a
+ // definition to emit.
+ const FunctionDecl *Def = 0;
+ if (MD->hasBody(Def) && Def->isOutOfLine())
+ return;
+
+ Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
+}
+
+void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ QualType ResultType = FPT->getResultType();
+ QualType ThisType = MD->getThisType(getContext());
+
+ FunctionArgList FunctionArgs;
+
+ // FIXME: It would be nice if more of this code could be shared with
+ // CodeGenFunction::GenerateCode.
+
+ // Create the implicit 'this' parameter declaration.
+ CurGD = GD;
+ CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
+
+ // Add the rest of the parameters.
+ for (FunctionDecl::param_const_iterator I = MD->param_begin(),
+ E = MD->param_end(); I != E; ++I) {
+ ParmVarDecl *Param = *I;
+
+ FunctionArgs.push_back(std::make_pair(Param, Param->getType()));
+ }
+
+ StartFunction(GlobalDecl(), ResultType, Fn, FunctionArgs, SourceLocation());
+
+ CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
+ // Adjust the 'this' pointer if necessary.
+ llvm::Value *AdjustedThisPtr =
+ PerformTypeAdjustment(*this, LoadCXXThis(),
+ Thunk.This.NonVirtual,
+ Thunk.This.VCallOffsetOffset);
+
+ CallArgList CallArgs;
+
+ // Add our adjusted 'this' pointer.
+ CallArgs.push_back(std::make_pair(RValue::get(AdjustedThisPtr), ThisType));
+
+ // Add the rest of the parameters.
+ for (FunctionDecl::param_const_iterator I = MD->param_begin(),
+ E = MD->param_end(); I != E; ++I) {
+ ParmVarDecl *Param = *I;
+ QualType ArgType = Param->getType();
+ RValue Arg = EmitDelegateCallArg(Param);
+
+ CallArgs.push_back(std::make_pair(Arg, ArgType));
+ }
+
+ // Get our callee.
+ const llvm::Type *Ty =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
+ FPT->isVariadic());
+ llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
+ FPT->getExtInfo());
+
+ // Determine whether we have a return value slot to use.
+ ReturnValueSlot Slot;
+ if (!ResultType->isVoidType() &&
+ FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+ hasAggregateLLVMType(CurFnInfo->getReturnType()))
+ Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
+
+ // Now emit our call.
+ RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD);
+
+ if (!Thunk.Return.isEmpty()) {
+ // Emit the return adjustment.
+ bool NullCheckValue = !ResultType->isReferenceType();
+
+ llvm::BasicBlock *AdjustNull = 0;
+ llvm::BasicBlock *AdjustNotNull = 0;
+ llvm::BasicBlock *AdjustEnd = 0;
+
+ llvm::Value *ReturnValue = RV.getScalarVal();
+
+ if (NullCheckValue) {
+ AdjustNull = createBasicBlock("adjust.null");
+ AdjustNotNull = createBasicBlock("adjust.notnull");
+ AdjustEnd = createBasicBlock("adjust.end");
+
+ llvm::Value *IsNull = Builder.CreateIsNull(ReturnValue);
+ Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull);
+ EmitBlock(AdjustNotNull);
+ }
+
+ ReturnValue = PerformTypeAdjustment(*this, ReturnValue,
+ Thunk.Return.NonVirtual,
+ Thunk.Return.VBaseOffsetOffset);
+
+ if (NullCheckValue) {
+ Builder.CreateBr(AdjustEnd);
+ EmitBlock(AdjustNull);
+ Builder.CreateBr(AdjustEnd);
+ EmitBlock(AdjustEnd);
+
+ llvm::PHINode *PHI = Builder.CreatePHI(ReturnValue->getType());
+ PHI->reserveOperandSpace(2);
+ PHI->addIncoming(ReturnValue, AdjustNotNull);
+ PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
+ AdjustNull);
+ ReturnValue = PHI;
+ }
+
+ RV = RValue::get(ReturnValue);
+ }
+
+ if (!ResultType->isVoidType() && Slot.isNull())
+ CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
+
+ FinishFunction();
+
+ // Set the right linkage.
+ CGM.setFunctionLinkage(MD, Fn);
+
+ // Set the right visibility.
+ setThunkVisibility(CGM, MD, Thunk, Fn);
+}
+
+void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
+ bool UseAvailableExternallyLinkage)
+{
+ llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
+
+ // Strip off a bitcast if we got one back.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ assert(CE->getOpcode() == llvm::Instruction::BitCast);
+ Entry = CE->getOperand(0);
+ }
+
+ // There's already a declaration with the same name, check if it has the same
+ // type or if we need to replace it.
+ if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() !=
+ CGM.getTypes().GetFunctionTypeForVTable(GD)) {
+ llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry);
+
+ // If the types mismatch then we have to rewrite the definition.
+ assert(OldThunkFn->isDeclaration() &&
+ "Shouldn't replace non-declaration");
+
+ // Remove the name from the old thunk function and get a new thunk.
+ OldThunkFn->setName(llvm::StringRef());
+ Entry = CGM.GetAddrOfThunk(GD, Thunk);
+
+ // If needed, replace the old thunk with a bitcast.
+ if (!OldThunkFn->use_empty()) {
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(Entry, OldThunkFn->getType());
+ OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl);
+ }
+
+ // Remove the old thunk.
+ OldThunkFn->eraseFromParent();
+ }
+
+ llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
+
+ if (!ThunkFn->isDeclaration()) {
+ if (UseAvailableExternallyLinkage) {
+ // There is already a thunk emitted for this function, do nothing.
+ return;
+ }
+
+ // If a function has a body, it should have available_externally linkage.
+ assert(ThunkFn->hasAvailableExternallyLinkage() &&
+ "Function should have available_externally linkage!");
+
+ // Change the linkage.
+ CGM.setFunctionLinkage(cast<CXXMethodDecl>(GD.getDecl()), ThunkFn);
+ return;
+ }
+
+ // Actually generate the thunk body.
+ CodeGenFunction(CGM).GenerateThunk(ThunkFn, GD, Thunk);
+
+ if (UseAvailableExternallyLinkage)
+ ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+}
+
+void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ // We only want to do this when building with optimizations.
+ if (!CGM.getCodeGenOpts().OptimizationLevel)
+ return;
+
+ // We can't emit thunks for member functions with incomplete types.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+ return;
+
+ EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
+}
+
+void CodeGenVTables::EmitThunks(GlobalDecl GD)
+{
+ const CXXMethodDecl *MD =
+ cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();
+
+ // We don't need to generate thunks for the base destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+ return;
+
+ const CXXRecordDecl *RD = MD->getParent();
+
+ // Compute VTable related info for this class.
+ ComputeVTableRelatedInformation(RD, false);
+
+ ThunksMapTy::const_iterator I = Thunks.find(MD);
+ if (I == Thunks.end()) {
+ // We did not find a thunk for this method.
+ return;
+ }
+
+ const ThunkInfoVectorTy &ThunkInfoVector = I->second;
+ for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I)
+ EmitThunk(GD, ThunkInfoVector[I], /*UseAvailableExternallyLinkage=*/false);
+}
+
+void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
+ bool RequireVTable) {
+ VTableLayoutData &Entry = VTableLayoutMap[RD];
+
+ // We may need to generate a definition for this vtable.
+ if (RequireVTable && !Entry.getInt()) {
+ if (ShouldEmitVTableInThisTU(RD))
+ CGM.DeferredVTables.push_back(RD);
+
+ Entry.setInt(true);
+ }
+
+ // Check if we've computed this information before.
+ if (Entry.getPointer())
+ return;
+
+ VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD);
+
+ // Add the VTable layout.
+ uint64_t NumVTableComponents = Builder.getNumVTableComponents();
+ // -fapple-kext adds an extra entry at end of vtbl.
+ bool IsAppleKext = CGM.getContext().getLangOptions().AppleKext;
+ if (IsAppleKext)
+ NumVTableComponents += 1;
+
+ uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
+ if (IsAppleKext)
+ LayoutData[NumVTableComponents] = 0;
+ Entry.setPointer(LayoutData);
+
+ // Store the number of components.
+ LayoutData[0] = NumVTableComponents;
+
+ // Store the components.
+ std::copy(Builder.vtable_components_data_begin(),
+ Builder.vtable_components_data_end(),
+ &LayoutData[1]);
+
+ // Add the known thunks.
+ Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
+
+ // Add the thunks needed in this vtable.
+ assert(!VTableThunksMap.count(RD) &&
+ "Thunks already exists for this vtable!");
+
+ VTableThunksTy &VTableThunks = VTableThunksMap[RD];
+ VTableThunks.append(Builder.vtable_thunks_begin(),
+ Builder.vtable_thunks_end());
+
+ // Sort them.
+ std::sort(VTableThunks.begin(), VTableThunks.end());
+
+ // Add the address points.
+ for (VTableBuilder::AddressPointsMapTy::const_iterator I =
+ Builder.address_points_begin(), E = Builder.address_points_end();
+ I != E; ++I) {
+
+ uint64_t &AddressPoint = AddressPoints[std::make_pair(RD, I->first)];
+
+ // Check if we already have the address points for this base.
+ assert(!AddressPoint && "Address point already exists for this base!");
+
+ AddressPoint = I->second;
+ }
+
+ // If we don't have the vbase information for this class, insert it.
+ // getVirtualBaseOffsetOffset will compute it separately without computing
+ // the rest of the vtable related information.
+ if (!RD->getNumVBases())
+ return;
+
+ const RecordType *VBaseRT =
+ RD->vbases_begin()->getType()->getAs<RecordType>();
+ const CXXRecordDecl *VBase = cast<CXXRecordDecl>(VBaseRT->getDecl());
+
+ if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
+ return;
+
+ for (VTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
+ Builder.getVBaseOffsetOffsets().begin(),
+ E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
+ // Insert all types.
+ ClassPairTy ClassPair(RD, I->first);
+
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
+ }
+}
+
+llvm::Constant *
+CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
+ const uint64_t *Components,
+ unsigned NumComponents,
+ const VTableThunksTy &VTableThunks) {
+ llvm::SmallVector<llvm::Constant *, 64> Inits;
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+
+ const llvm::Type *PtrDiffTy =
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+ QualType ClassType = CGM.getContext().getTagDeclType(RD);
+ llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType);
+
+ unsigned NextVTableThunkIndex = 0;
+
+ llvm::Constant* PureVirtualFn = 0;
+
+ for (unsigned I = 0; I != NumComponents; ++I) {
+ VTableComponent Component =
+ VTableComponent::getFromOpaqueInteger(Components[I]);
+
+ llvm::Constant *Init = 0;
+
+ switch (Component.getKind()) {
+ case VTableComponent::CK_VCallOffset:
+ Init = llvm::ConstantInt::get(PtrDiffTy, Component.getVCallOffset());
+ Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ break;
+ case VTableComponent::CK_VBaseOffset:
+ Init = llvm::ConstantInt::get(PtrDiffTy, Component.getVBaseOffset());
+ Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ break;
+ case VTableComponent::CK_OffsetToTop:
+ Init = llvm::ConstantInt::get(PtrDiffTy, Component.getOffsetToTop());
+ Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ break;
+ case VTableComponent::CK_RTTI:
+ Init = llvm::ConstantExpr::getBitCast(RTTI, Int8PtrTy);
+ break;
+ case VTableComponent::CK_FunctionPointer:
+ case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_DeletingDtorPointer: {
+ GlobalDecl GD;
+
+ // Get the right global decl.
+ switch (Component.getKind()) {
+ default:
+ llvm_unreachable("Unexpected vtable component kind");
+ case VTableComponent::CK_FunctionPointer:
+ GD = Component.getFunctionDecl();
+ break;
+ case VTableComponent::CK_CompleteDtorPointer:
+ GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Complete);
+ break;
+ case VTableComponent::CK_DeletingDtorPointer:
+ GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Deleting);
+ break;
+ }
+
+ if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
+ // We have a pure virtual member function.
+ if (!PureVirtualFn) {
+ const llvm::FunctionType *Ty =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ /*isVarArg=*/false);
+ PureVirtualFn =
+ CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual");
+ PureVirtualFn = llvm::ConstantExpr::getBitCast(PureVirtualFn,
+ Int8PtrTy);
+ }
+
+ Init = PureVirtualFn;
+ } else {
+ // Check if we should use a thunk.
+ if (NextVTableThunkIndex < VTableThunks.size() &&
+ VTableThunks[NextVTableThunkIndex].first == I) {
+ const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
+
+ Init = CGM.GetAddrOfThunk(GD, Thunk);
+ MaybeEmitThunkAvailableExternally(GD, Thunk);
+
+ NextVTableThunkIndex++;
+ } else {
+ const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
+
+ Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ }
+
+ Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
+ }
+ break;
+ }
+
+ case VTableComponent::CK_UnusedFunctionPointer:
+ Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
+ break;
+ };
+
+ Inits.push_back(Init);
+ }
+
+ llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, NumComponents);
+ return llvm::ConstantArray::get(ArrayType, Inits.data(), Inits.size());
+}
+
+llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ ComputeVTableRelatedInformation(RD, true);
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ llvm::ArrayType *ArrayType =
+ llvm::ArrayType::get(Int8PtrTy, getNumVTableComponents(RD));
+
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ llvm::GlobalValue::ExternalLinkage);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
+
+void
+CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD) {
+ // Dump the vtable layout if necessary.
+ if (CGM.getLangOptions().DumpVTableLayouts) {
+ VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD);
+
+ Builder.dumpLayout(llvm::errs());
+ }
+
+ assert(VTableThunksMap.count(RD) &&
+ "No thunk status for this record decl!");
+
+ const VTableThunksTy& Thunks = VTableThunksMap[RD];
+
+ // Create and set the initializer.
+ llvm::Constant *Init =
+ CreateVTableInitializer(RD, getVTableComponentsData(RD),
+ getNumVTableComponents(RD), Thunks);
+ VTable->setInitializer(Init);
+
+ // Set the correct linkage.
+ VTable->setLinkage(Linkage);
+
+ // Set the right visibility.
+ CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
+}
+
+llvm::GlobalVariable *
+CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
+ const BaseSubobject &Base,
+ bool BaseIsVirtual,
+ VTableAddressPointsMapTy& AddressPoints) {
+ VTableBuilder Builder(*this, Base.getBase(), Base.getBaseOffset(),
+ /*MostDerivedClassIsVirtual=*/BaseIsVirtual, RD);
+
+ // Dump the vtable layout if necessary.
+ if (CGM.getLangOptions().DumpVTableLayouts)
+ Builder.dumpLayout(llvm::errs());
+
+ // Add the address points.
+ AddressPoints.insert(Builder.address_points_begin(),
+ Builder.address_points_end());
+
+ // Get the mangled construction vtable name.
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().
+ mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), Out);
+ Out.flush();
+ llvm::StringRef Name = OutName.str();
+
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+ llvm::ArrayType *ArrayType =
+ llvm::ArrayType::get(Int8PtrTy, Builder.getNumVTableComponents());
+
+ // Create the variable that will hold the construction vtable.
+ llvm::GlobalVariable *VTable =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ llvm::GlobalValue::InternalLinkage);
+
+ // Add the thunks.
+ VTableThunksTy VTableThunks;
+ VTableThunks.append(Builder.vtable_thunks_begin(),
+ Builder.vtable_thunks_end());
+
+ // Sort them.
+ std::sort(VTableThunks.begin(), VTableThunks.end());
+
+ // Create and set the initializer.
+ llvm::Constant *Init =
+ CreateVTableInitializer(Base.getBase(),
+ Builder.vtable_components_data_begin(),
+ Builder.getNumVTableComponents(), VTableThunks);
+ VTable->setInitializer(Init);
+
+ return VTable;
+}
+
+void
+CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD) {
+ llvm::GlobalVariable *&VTable = VTables[RD];
+ if (VTable) {
+ assert(VTable->getInitializer() && "VTable doesn't have a definition!");
+ return;
+ }
+
+ VTable = GetAddrOfVTable(RD);
+ EmitVTableDefinition(VTable, Linkage, RD);
+
+ if (RD->getNumVBases()) {
+ llvm::GlobalVariable *VTT = GetAddrOfVTT(RD);
+ EmitVTTDefinition(VTT, Linkage, RD);
+ }
+
+ // If this is the magic class __cxxabiv1::__fundamental_type_info,
+ // we will emit the typeinfo for the fundamental types. This is the
+ // same behaviour as GCC.
+ const DeclContext *DC = RD->getDeclContext();
+ if (RD->getIdentifier() &&
+ RD->getIdentifier()->isStr("__fundamental_type_info") &&
+ isa<NamespaceDecl>(DC) &&
+ cast<NamespaceDecl>(DC)->getIdentifier() &&
+ cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
+ DC->getParent()->isTranslationUnit())
+ CGM.EmitFundamentalRTTIDescriptors();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
new file mode 100644
index 0000000..7c119fa
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
@@ -0,0 +1,287 @@
+//===--- CGVTables.h - Emit LLVM Code for C++ vtables ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of virtual tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGVTABLE_H
+#define CLANG_CODEGEN_CGVTABLE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/GlobalVariable.h"
+#include "clang/Basic/ABI.h"
+#include "GlobalDecl.h"
+
+namespace clang {
+ class CXXRecordDecl;
+
+namespace CodeGen {
+ class CodeGenModule;
+
+// BaseSubobject - Uniquely identifies a direct or indirect base class.
+// Stores both the base class decl and the offset from the most derived class to
+// the base class.
+class BaseSubobject {
+ /// Base - The base class declaration.
+ const CXXRecordDecl *Base;
+
+ /// BaseOffset - The offset from the most derived class to the base class.
+ uint64_t BaseOffset;
+
+public:
+ BaseSubobject(const CXXRecordDecl *Base, uint64_t BaseOffset)
+ : Base(Base), BaseOffset(BaseOffset) { }
+
+ /// getBase - Returns the base class declaration.
+ const CXXRecordDecl *getBase() const { return Base; }
+
+ /// getBaseOffset - Returns the base class offset.
+ uint64_t getBaseOffset() const { return BaseOffset; }
+
+ friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
+ return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+namespace llvm {
+
+template<> struct DenseMapInfo<clang::CodeGen::BaseSubobject> {
+ static clang::CodeGen::BaseSubobject getEmptyKey() {
+ return clang::CodeGen::BaseSubobject(
+ DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
+ DenseMapInfo<uint64_t>::getEmptyKey());
+ }
+
+ static clang::CodeGen::BaseSubobject getTombstoneKey() {
+ return clang::CodeGen::BaseSubobject(
+ DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
+ DenseMapInfo<uint64_t>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const clang::CodeGen::BaseSubobject &Base) {
+ return
+ DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^
+ DenseMapInfo<uint64_t>::getHashValue(Base.getBaseOffset());
+ }
+
+ static bool isEqual(const clang::CodeGen::BaseSubobject &LHS,
+ const clang::CodeGen::BaseSubobject &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// It's OK to treat BaseSubobject as a POD type.
+template <> struct isPodLike<clang::CodeGen::BaseSubobject> {
+ static const bool value = true;
+};
+
+}
+
+namespace clang {
+namespace CodeGen {
+
+class CodeGenVTables {
+ CodeGenModule &CGM;
+
+ /// MethodVTableIndices - Contains the index (relative to the vtable address
+ /// point) where the function pointer for a virtual function is stored.
+ typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
+ MethodVTableIndicesTy MethodVTableIndices;
+
+ typedef std::pair<const CXXRecordDecl *,
+ const CXXRecordDecl *> ClassPairTy;
+
+ /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
+ /// the address point) in bytes where the offsets for virtual bases of a class
+ /// are stored.
+ typedef llvm::DenseMap<ClassPairTy, int64_t>
+ VirtualBaseClassOffsetOffsetsMapTy;
+ VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
+
+ /// VTables - All the vtables which have been defined.
+ llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
+
+ /// NumVirtualFunctionPointers - Contains the number of virtual function
+ /// pointers in the vtable for a given record decl.
+ llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
+
+ typedef llvm::SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+ typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
+
+ /// Thunks - Contains all thunks that a given method decl will need.
+ ThunksMapTy Thunks;
+
+ // The layout entry and a bool indicating whether we've actually emitted
+ // the vtable.
+ typedef llvm::PointerIntPair<uint64_t *, 1, bool> VTableLayoutData;
+ typedef llvm::DenseMap<const CXXRecordDecl *, VTableLayoutData>
+ VTableLayoutMapTy;
+
+ /// VTableLayoutMap - Stores the vtable layout for all record decls.
+ /// The layout is stored as an array of 64-bit integers, where the first
+ /// integer is the number of vtable entries in the layout, and the subsequent
+ /// integers are the vtable components.
+ VTableLayoutMapTy VTableLayoutMap;
+
+ typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
+ typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> AddressPointsMapTy;
+
+ /// Address points - Address points for all vtables.
+ AddressPointsMapTy AddressPoints;
+
+ /// VTableAddressPointsMapTy - Address points for a single vtable.
+ typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;
+
+ typedef llvm::SmallVector<std::pair<uint64_t, ThunkInfo>, 1>
+ VTableThunksTy;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, VTableThunksTy>
+ VTableThunksMapTy;
+
+ /// VTableThunksMap - Contains thunks needed by vtables.
+ VTableThunksMapTy VTableThunksMap;
+
+ uint64_t getNumVTableComponents(const CXXRecordDecl *RD) const {
+ assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
+
+ return VTableLayoutMap.lookup(RD).getPointer()[0];
+ }
+
+ const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) const {
+ assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
+
+ uint64_t *Components = VTableLayoutMap.lookup(RD).getPointer();
+ return &Components[1];
+ }
+
+ typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy;
+
+ /// SubVTTIndicies - Contains indices into the various sub-VTTs.
+ SubVTTIndiciesMapTy SubVTTIndicies;
+
+ typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t>
+ SecondaryVirtualPointerIndicesMapTy;
+
+ /// SecondaryVirtualPointerIndices - Contains the secondary virtual pointer
+ /// indices.
+ SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices;
+
+ /// getNumVirtualFunctionPointers - Return the number of virtual function
+ /// pointers in the vtable for a given record decl.
+ uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
+
+ void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
+
+ /// EmitThunk - Emit a single thunk.
+ void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
+ bool UseAvailableExternallyLinkage);
+
+ /// MaybeEmitThunkAvailableExternally - Try to emit the given thunk with
+ /// available_externally linkage to allow for inlining of thunks.
+ /// This will be done iff optimizations are enabled and the member function
+ /// doesn't contain any incomplete types.
+ void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk);
+
+ /// ComputeVTableRelatedInformation - Compute and store all vtable related
+ /// information (vtable layout, vbase offset offsets, thunks etc) for the
+ /// given record decl.
+ void ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
+ bool VTableRequired);
+
+ /// CreateVTableInitializer - Create a vtable initializer for the given record
+ /// decl.
+ /// \param Components - The vtable components; this is really an array of
+ /// VTableComponents.
+ llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,
+ const uint64_t *Components,
+ unsigned NumComponents,
+ const VTableThunksTy &VTableThunks);
+
+public:
+ CodeGenVTables(CodeGenModule &CGM)
+ : CGM(CGM) { }
+
+ /// \brief True if the VTable of this record must be emitted in the
+ /// translation unit.
+ bool ShouldEmitVTableInThisTU(const CXXRecordDecl *RD);
+
+ /// needsVTTParameter - Return whether the given global decl needs a VTT
+ /// parameter, which it does if it's a base constructor or destructor with
+ /// virtual bases.
+ static bool needsVTTParameter(GlobalDecl GD);
+
+ /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
+ /// given record decl.
+ uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base);
+
+ /// getSecondaryVirtualPointerIndex - Return the index in the VTT where the
+ /// virtual pointer for the given subobject is located.
+ uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
+ BaseSubobject Base);
+
+ /// getMethodVTableIndex - Return the index (relative to the vtable address
+ /// point) where the function pointer for the given virtual function is
+ /// stored.
+ uint64_t getMethodVTableIndex(GlobalDecl GD);
+
+ /// getVirtualBaseOffsetOffset - Return the offset in bytes (relative to the
+ /// vtable address point) where the offset of the virtual base that contains
+ /// the given base is stored, otherwise, if no virtual base contains the given
+ /// class, return 0. Base must be a virtual base class or an unambigious
+ /// base.
+ int64_t getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase);
+
+ /// getAddressPoint - Get the address point of the given subobject in the
+ /// class decl.
+ uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD);
+
+ /// GetAddrOfVTable - Get the address of the vtable for the given record decl.
+ llvm::GlobalVariable *GetAddrOfVTable(const CXXRecordDecl *RD);
+
+ /// EmitVTableDefinition - Emit the definition of the given vtable.
+ void EmitVTableDefinition(llvm::GlobalVariable *VTable,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD);
+
+ /// GenerateConstructionVTable - Generate a construction vtable for the given
+ /// base subobject.
+ llvm::GlobalVariable *
+ GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base,
+ bool BaseIsVirtual,
+ VTableAddressPointsMapTy& AddressPoints);
+
+
+ /// GetAddrOfVTable - Get the address of the VTT for the given record decl.
+ llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD);
+
+ /// EmitVTTDefinition - Emit the definition of the given vtable.
+ void EmitVTTDefinition(llvm::GlobalVariable *VTT,
+ llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD);
+
+ /// EmitThunks - Emit the associated thunks for the given global decl.
+ void EmitThunks(GlobalDecl GD);
+
+ /// GenerateClassData - Generate all the class data required to be generated
+ /// upon definition of a KeyFunction. This includes the vtable, the
+ /// rtti data structure and the VTT.
+ ///
+ /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
+ void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD);
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
new file mode 100644
index 0000000..7f77d55
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
@@ -0,0 +1,405 @@
+//===-- CGValue.h - LLVM CodeGen wrappers for llvm::Value* ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement wrappers around llvm::Value in order to
+// fully represent the range of values for C L- and R- values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGVALUE_H
+#define CLANG_CODEGEN_CGVALUE_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+namespace llvm {
+ class Constant;
+ class Value;
+}
+
+namespace clang {
+ class ObjCPropertyRefExpr;
+
+namespace CodeGen {
+ class CGBitFieldInfo;
+
+/// RValue - This trivial value class is used to represent the result of an
+/// expression that is evaluated. It can be one of three things: either a
+/// simple LLVM SSA value, a pair of SSA values for complex numbers, or the
+/// address of an aggregate value in memory.
+class RValue {
+ enum Flavor { Scalar, Complex, Aggregate };
+
+ // Stores first value and flavor.
+ llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1;
+ // Stores second value and volatility.
+ llvm::PointerIntPair<llvm::Value *, 1, bool> V2;
+
+public:
+ bool isScalar() const { return V1.getInt() == Scalar; }
+ bool isComplex() const { return V1.getInt() == Complex; }
+ bool isAggregate() const { return V1.getInt() == Aggregate; }
+
+ bool isVolatileQualified() const { return V2.getInt(); }
+
+ /// getScalarVal() - Return the Value* of this scalar value.
+ llvm::Value *getScalarVal() const {
+ assert(isScalar() && "Not a scalar!");
+ return V1.getPointer();
+ }
+
+ /// getComplexVal - Return the real/imag components of this complex value.
+ ///
+ std::pair<llvm::Value *, llvm::Value *> getComplexVal() const {
+ return std::make_pair(V1.getPointer(), V2.getPointer());
+ }
+
+ /// getAggregateAddr() - Return the Value* of the address of the aggregate.
+ llvm::Value *getAggregateAddr() const {
+ assert(isAggregate() && "Not an aggregate!");
+ return V1.getPointer();
+ }
+
+ static RValue get(llvm::Value *V) {
+ RValue ER;
+ ER.V1.setPointer(V);
+ ER.V1.setInt(Scalar);
+ ER.V2.setInt(false);
+ return ER;
+ }
+ static RValue getComplex(llvm::Value *V1, llvm::Value *V2) {
+ RValue ER;
+ ER.V1.setPointer(V1);
+ ER.V2.setPointer(V2);
+ ER.V1.setInt(Complex);
+ ER.V2.setInt(false);
+ return ER;
+ }
+ static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) {
+ return getComplex(C.first, C.second);
+ }
+ // FIXME: Aggregate rvalues need to retain information about whether they are
+ // volatile or not. Remove default to find all places that probably get this
+ // wrong.
+ static RValue getAggregate(llvm::Value *V, bool Volatile = false) {
+ RValue ER;
+ ER.V1.setPointer(V);
+ ER.V1.setInt(Aggregate);
+ ER.V2.setInt(Volatile);
+ return ER;
+ }
+};
+
+
+/// LValue - This represents an lvalue references. Because C/C++ allow
+/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
+/// bitrange.
+class LValue {
+ // FIXME: alignment?
+
+ enum {
+ Simple, // This is a normal l-value, use getAddress().
+ VectorElt, // This is a vector element l-value (V[i]), use getVector*
+ BitField, // This is a bitfield l-value, use getBitfield*.
+ ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
+ PropertyRef // This is an Objective-C property reference, use
+ // getPropertyRefExpr
+ } LVType;
+
+ llvm::Value *V;
+
+ union {
+ // Index into a vector subscript: V[i]
+ llvm::Value *VectorIdx;
+
+ // ExtVector element subset: V.xyx
+ llvm::Constant *VectorElts;
+
+ // BitField start bit and size
+ const CGBitFieldInfo *BitFieldInfo;
+
+ // Obj-C property reference expression
+ const ObjCPropertyRefExpr *PropertyRefExpr;
+ };
+
+ // 'const' is unused here
+ Qualifiers Quals;
+
+ /// The alignment to use when accessing this lvalue.
+ unsigned short Alignment;
+
+ // objective-c's ivar
+ bool Ivar:1;
+
+ // objective-c's ivar is an array
+ bool ObjIsArray:1;
+
+ // LValue is non-gc'able for any reason, including being a parameter or local
+ // variable.
+ bool NonGC: 1;
+
+ // Lvalue is a global reference of an objective-c object
+ bool GlobalObjCRef : 1;
+
+ // Lvalue is a thread local reference
+ bool ThreadLocalRef : 1;
+
+ Expr *BaseIvarExp;
+
+ /// TBAAInfo - TBAA information to attach to dereferences of this LValue.
+ llvm::MDNode *TBAAInfo;
+
+private:
+ void Initialize(Qualifiers Quals, unsigned Alignment = 0,
+ llvm::MDNode *TBAAInfo = 0) {
+ this->Quals = Quals;
+ this->Alignment = Alignment;
+ assert(this->Alignment == Alignment && "Alignment exceeds allowed max!");
+
+ // Initialize Objective-C flags.
+ this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
+ this->ThreadLocalRef = false;
+ this->BaseIvarExp = 0;
+ this->TBAAInfo = TBAAInfo;
+ }
+
+public:
+ bool isSimple() const { return LVType == Simple; }
+ bool isVectorElt() const { return LVType == VectorElt; }
+ bool isBitField() const { return LVType == BitField; }
+ bool isExtVectorElt() const { return LVType == ExtVectorElt; }
+ bool isPropertyRef() const { return LVType == PropertyRef; }
+
+ bool isVolatileQualified() const { return Quals.hasVolatile(); }
+ bool isRestrictQualified() const { return Quals.hasRestrict(); }
+ unsigned getVRQualifiers() const {
+ return Quals.getCVRQualifiers() & ~Qualifiers::Const;
+ }
+
+ bool isObjCIvar() const { return Ivar; }
+ void setObjCIvar(bool Value) { Ivar = Value; }
+
+ bool isObjCArray() const { return ObjIsArray; }
+ void setObjCArray(bool Value) { ObjIsArray = Value; }
+
+ bool isNonGC () const { return NonGC; }
+ void setNonGC(bool Value) { NonGC = Value; }
+
+ bool isGlobalObjCRef() const { return GlobalObjCRef; }
+ void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; }
+
+ bool isThreadLocalRef() const { return ThreadLocalRef; }
+ void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;}
+
+ bool isObjCWeak() const {
+ return Quals.getObjCGCAttr() == Qualifiers::Weak;
+ }
+ bool isObjCStrong() const {
+ return Quals.getObjCGCAttr() == Qualifiers::Strong;
+ }
+
+ Expr *getBaseIvarExp() const { return BaseIvarExp; }
+ void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
+
+ llvm::MDNode *getTBAAInfo() const { return TBAAInfo; }
+ void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; }
+
+ const Qualifiers &getQuals() const { return Quals; }
+ Qualifiers &getQuals() { return Quals; }
+
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+ unsigned getAlignment() const { return Alignment; }
+
+ // simple lvalue
+ llvm::Value *getAddress() const { assert(isSimple()); return V; }
+
+ // vector elt lvalue
+ llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; }
+ llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
+
+ // extended vector elements.
+ llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; }
+ llvm::Constant *getExtVectorElts() const {
+ assert(isExtVectorElt());
+ return VectorElts;
+ }
+
+ // bitfield lvalue
+ llvm::Value *getBitFieldBaseAddr() const {
+ assert(isBitField());
+ return V;
+ }
+ const CGBitFieldInfo &getBitFieldInfo() const {
+ assert(isBitField());
+ return *BitFieldInfo;
+ }
+
+ // property ref lvalue
+ llvm::Value *getPropertyRefBaseAddr() const {
+ assert(isPropertyRef());
+ return V;
+ }
+ const ObjCPropertyRefExpr *getPropertyRefExpr() const {
+ assert(isPropertyRef());
+ return PropertyRefExpr;
+ }
+
+ static LValue MakeAddr(llvm::Value *V, QualType T, unsigned Alignment,
+ ASTContext &Context,
+ llvm::MDNode *TBAAInfo = 0) {
+ Qualifiers Quals = T.getQualifiers();
+ Quals.setObjCGCAttr(Context.getObjCGCAttrKind(T));
+
+ LValue R;
+ R.LVType = Simple;
+ R.V = V;
+ R.Initialize(Quals, Alignment, TBAAInfo);
+ return R;
+ }
+
+ static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
+ unsigned CVR) {
+ LValue R;
+ R.LVType = VectorElt;
+ R.V = Vec;
+ R.VectorIdx = Idx;
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
+ return R;
+ }
+
+ static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
+ unsigned CVR) {
+ LValue R;
+ R.LVType = ExtVectorElt;
+ R.V = Vec;
+ R.VectorElts = Elts;
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
+ return R;
+ }
+
+ /// \brief Create a new object to represent a bit-field access.
+ ///
+ /// \param BaseValue - The base address of the structure containing the
+ /// bit-field.
+ /// \param Info - The information describing how to perform the bit-field
+ /// access.
+ static LValue MakeBitfield(llvm::Value *BaseValue, const CGBitFieldInfo &Info,
+ unsigned CVR) {
+ LValue R;
+ R.LVType = BitField;
+ R.V = BaseValue;
+ R.BitFieldInfo = &Info;
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
+ return R;
+ }
+
+ // FIXME: It is probably bad that we aren't emitting the target when we build
+ // the lvalue. However, this complicates the code a bit, and I haven't figured
+ // out how to make it go wrong yet.
+ static LValue MakePropertyRef(const ObjCPropertyRefExpr *E,
+ llvm::Value *Base) {
+ LValue R;
+ R.LVType = PropertyRef;
+ R.V = Base;
+ R.PropertyRefExpr = E;
+ R.Initialize(Qualifiers());
+ return R;
+ }
+};
+
+/// An aggregate value slot.
+class AggValueSlot {
+ /// The address.
+ llvm::Value *Addr;
+
+ // Associated flags.
+ bool VolatileFlag : 1;
+ bool LifetimeFlag : 1;
+ bool RequiresGCollection : 1;
+
+ /// IsZeroed - This is set to true if the destination is known to be zero
+ /// before the assignment into it. This means that zero fields don't need to
+ /// be set.
+ bool IsZeroed : 1;
+
+public:
+ /// ignored - Returns an aggregate value slot indicating that the
+ /// aggregate value is being ignored.
+ static AggValueSlot ignored() {
+ AggValueSlot AV;
+ AV.Addr = 0;
+ AV.VolatileFlag = AV.LifetimeFlag = AV.RequiresGCollection = AV.IsZeroed =0;
+ return AV;
+ }
+
+ /// forAddr - Make a slot for an aggregate value.
+ ///
+ /// \param Volatile - true if the slot should be volatile-initialized
+ /// \param LifetimeExternallyManaged - true if the slot's lifetime
+ /// is being externally managed; false if a destructor should be
+ /// registered for any temporaries evaluated into the slot
+ /// \param RequiresGCollection - true if the slot is located
+ /// somewhere that ObjC GC calls should be emitted for
+ static AggValueSlot forAddr(llvm::Value *Addr, bool Volatile,
+ bool LifetimeExternallyManaged,
+ bool RequiresGCollection = false,
+ bool IsZeroed = false) {
+ AggValueSlot AV;
+ AV.Addr = Addr;
+ AV.VolatileFlag = Volatile;
+ AV.LifetimeFlag = LifetimeExternallyManaged;
+ AV.RequiresGCollection = RequiresGCollection;
+ AV.IsZeroed = IsZeroed;
+ return AV;
+ }
+
+ static AggValueSlot forLValue(LValue LV, bool LifetimeExternallyManaged,
+ bool RequiresGCollection = false) {
+ return forAddr(LV.getAddress(), LV.isVolatileQualified(),
+ LifetimeExternallyManaged, RequiresGCollection);
+ }
+
+ bool isLifetimeExternallyManaged() const {
+ return LifetimeFlag;
+ }
+ void setLifetimeExternallyManaged(bool Managed = true) {
+ LifetimeFlag = Managed;
+ }
+
+ bool isVolatile() const {
+ return VolatileFlag;
+ }
+
+ bool requiresGCollection() const {
+ return RequiresGCollection;
+ }
+
+ llvm::Value *getAddr() const {
+ return Addr;
+ }
+
+ bool isIgnored() const {
+ return Addr == 0;
+ }
+
+ RValue asRValue() const {
+ return RValue::getAggregate(getAddr(), isVolatile());
+ }
+
+ void setZeroed(bool V = true) { IsZeroed = V; }
+ bool isZeroed() const {
+ return IsZeroed;
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
new file mode 100644
index 0000000..a24bbc4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
@@ -0,0 +1,362 @@
+//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/IRReader.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/Timer.h"
+using namespace clang;
+using namespace llvm;
+
+namespace clang {
+ class BackendConsumer : public ASTConsumer {
+ Diagnostic &Diags;
+ BackendAction Action;
+ const CodeGenOptions &CodeGenOpts;
+ const TargetOptions &TargetOpts;
+ llvm::raw_ostream *AsmOutStream;
+ ASTContext *Context;
+
+ Timer LLVMIRGeneration;
+
+ llvm::OwningPtr<CodeGenerator> Gen;
+
+ llvm::OwningPtr<llvm::Module> TheModule;
+
+ public:
+ BackendConsumer(BackendAction action, Diagnostic &_Diags,
+ const CodeGenOptions &compopts,
+ const TargetOptions &targetopts, bool TimePasses,
+ const std::string &infile, llvm::raw_ostream *OS,
+ LLVMContext &C) :
+ Diags(_Diags),
+ Action(action),
+ CodeGenOpts(compopts),
+ TargetOpts(targetopts),
+ AsmOutStream(OS),
+ LLVMIRGeneration("LLVM IR Generation Time"),
+ Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)) {
+ llvm::TimePassesIsEnabled = TimePasses;
+ }
+
+ llvm::Module *takeModule() { return TheModule.take(); }
+
+ virtual void Initialize(ASTContext &Ctx) {
+ Context = &Ctx;
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.startTimer();
+
+ Gen->Initialize(Ctx);
+
+ TheModule.reset(Gen->GetModule());
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.stopTimer();
+ }
+
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
+ Context->getSourceManager(),
+ "LLVM IR generation of declaration");
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.startTimer();
+
+ Gen->HandleTopLevelDecl(D);
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.stopTimer();
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &C) {
+ {
+ PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.startTimer();
+
+ Gen->HandleTranslationUnit(C);
+
+ if (llvm::TimePassesIsEnabled)
+ LLVMIRGeneration.stopTimer();
+ }
+
+ // Silently ignore if we weren't initialized for some reason.
+ if (!TheModule)
+ return;
+
+ // Make sure IR generation is happy with the module. This is released by
+ // the module provider.
+ Module *M = Gen->ReleaseModule();
+ if (!M) {
+ // The module has been released by IR gen on failures, do not double
+ // free.
+ TheModule.take();
+ return;
+ }
+
+ assert(TheModule.get() == M &&
+ "Unexpected module change during IR generation");
+
+ // Install an inline asm handler so that diagnostics get printed through
+ // our diagnostics hooks.
+ LLVMContext &Ctx = TheModule->getContext();
+ LLVMContext::InlineAsmDiagHandlerTy OldHandler =
+ Ctx.getInlineAsmDiagnosticHandler();
+ void *OldContext = Ctx.getInlineAsmDiagnosticContext();
+ Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
+
+ EmitBackendOutput(Diags, CodeGenOpts, TargetOpts,
+ TheModule.get(), Action, AsmOutStream);
+
+ Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
+ }
+
+ virtual void HandleTagDeclDefinition(TagDecl *D) {
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ Context->getSourceManager(),
+ "LLVM IR generation of declaration");
+ Gen->HandleTagDeclDefinition(D);
+ }
+
+ virtual void CompleteTentativeDefinition(VarDecl *D) {
+ Gen->CompleteTentativeDefinition(D);
+ }
+
+ virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {
+ Gen->HandleVTable(RD, DefinitionRequired);
+ }
+
+ static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
+ unsigned LocCookie) {
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
+ ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
+ }
+
+ void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
+ SourceLocation LocCookie);
+ };
+}
+
+/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
+/// buffer to be a valid FullSourceLoc.
+static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
+ SourceManager &CSM) {
+ // Get both the clang and llvm source managers. The location is relative to
+ // a memory buffer that the LLVM Source Manager is handling, we need to add
+ // a copy to the Clang source manager.
+ const llvm::SourceMgr &LSM = *D.getSourceMgr();
+
+ // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
+ // already owns its one and clang::SourceManager wants to own its one.
+ const MemoryBuffer *LBuf =
+ LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
+
+ // Create the copy and transfer ownership to clang::SourceManager.
+ llvm::MemoryBuffer *CBuf =
+ llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
+ LBuf->getBufferIdentifier());
+ FileID FID = CSM.createFileIDForMemBuffer(CBuf);
+
+ // Translate the offset into the file.
+ unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
+ SourceLocation NewLoc =
+ CSM.getLocForStartOfFile(FID).getFileLocWithOffset(Offset);
+ return FullSourceLoc(NewLoc, CSM);
+}
+
+
+/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an
+/// error parsing inline asm. The SMDiagnostic indicates the error relative to
+/// the temporary memory buffer that the inline asm parser has set up.
+void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
+ SourceLocation LocCookie) {
+ // There are a couple of different kinds of errors we could get here. First,
+ // we re-format the SMDiagnostic in terms of a clang diagnostic.
+
+ // Strip "error: " off the start of the message string.
+ llvm::StringRef Message = D.getMessage();
+ if (Message.startswith("error: "))
+ Message = Message.substr(7);
+
+ // If the SMDiagnostic has an inline asm source location, translate it.
+ FullSourceLoc Loc;
+ if (D.getLoc() != SMLoc())
+ Loc = ConvertBackendLocation(D, Context->getSourceManager());
+
+
+ // If this problem has clang-level source location information, report the
+ // issue as being an error in the source with a note showing the instantiated
+ // code.
+ if (LocCookie.isValid()) {
+ Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message);
+
+ if (D.getLoc().isValid())
+ Diags.Report(Loc, diag::note_fe_inline_asm_here);
+ return;
+ }
+
+ // Otherwise, report the backend error as occuring in the generated .s file.
+ // If Loc is invalid, we still need to report the error, it just gets no
+ // location info.
+ Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message);
+}
+
+//
+
+CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
+ : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
+ OwnsVMContext(!_VMContext) {}
+
+CodeGenAction::~CodeGenAction() {
+ TheModule.reset();
+ if (OwnsVMContext)
+ delete VMContext;
+}
+
+bool CodeGenAction::hasIRSupport() const { return true; }
+
+void CodeGenAction::EndSourceFileAction() {
+ // If the consumer creation failed, do nothing.
+ if (!getCompilerInstance().hasASTConsumer())
+ return;
+
+ // Steal the module from the consumer.
+ TheModule.reset(BEConsumer->takeModule());
+}
+
+llvm::Module *CodeGenAction::takeModule() {
+ return TheModule.take();
+}
+
+llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
+ OwnsVMContext = false;
+ return VMContext;
+}
+
+static raw_ostream *GetOutputStream(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ BackendAction Action) {
+ switch (Action) {
+ case Backend_EmitAssembly:
+ return CI.createDefaultOutputFile(false, InFile, "s");
+ case Backend_EmitLL:
+ return CI.createDefaultOutputFile(false, InFile, "ll");
+ case Backend_EmitBC:
+ return CI.createDefaultOutputFile(true, InFile, "bc");
+ case Backend_EmitNothing:
+ return 0;
+ case Backend_EmitMCNull:
+ case Backend_EmitObj:
+ return CI.createDefaultOutputFile(true, InFile, "o");
+ }
+
+ assert(0 && "Invalid action!");
+ return 0;
+}
+
+ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ BackendAction BA = static_cast<BackendAction>(Act);
+ llvm::OwningPtr<llvm::raw_ostream> OS(GetOutputStream(CI, InFile, BA));
+ if (BA != Backend_EmitNothing && !OS)
+ return 0;
+
+ BEConsumer =
+ new BackendConsumer(BA, CI.getDiagnostics(),
+ CI.getCodeGenOpts(), CI.getTargetOpts(),
+ CI.getFrontendOpts().ShowTimers, InFile, OS.take(),
+ *VMContext);
+ return BEConsumer;
+}
+
+void CodeGenAction::ExecuteAction() {
+ // If this is an IR file, we have to treat it specially.
+ if (getCurrentFileKind() == IK_LLVM_IR) {
+ BackendAction BA = static_cast<BackendAction>(Act);
+ CompilerInstance &CI = getCompilerInstance();
+ raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA);
+ if (BA != Backend_EmitNothing && !OS)
+ return;
+
+ bool Invalid;
+ SourceManager &SM = CI.getSourceManager();
+ const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(),
+ &Invalid);
+ if (Invalid)
+ return;
+
+ // FIXME: This is stupid, IRReader shouldn't take ownership.
+ llvm::MemoryBuffer *MainFileCopy =
+ llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(),
+ getCurrentFile().c_str());
+
+ llvm::SMDiagnostic Err;
+ TheModule.reset(ParseIR(MainFileCopy, Err, *VMContext));
+ if (!TheModule) {
+ // Translate from the diagnostic info to the SourceManager location.
+ SourceLocation Loc = SM.getLocation(
+ SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(),
+ Err.getColumnNo() + 1);
+
+ // Get a custom diagnostic for the error. We strip off a leading
+ // diagnostic code if there is one.
+ llvm::StringRef Msg = Err.getMessage();
+ if (Msg.startswith("error: "))
+ Msg = Msg.substr(7);
+ unsigned DiagID = CI.getDiagnostics().getCustomDiagID(Diagnostic::Error,
+ Msg);
+
+ CI.getDiagnostics().Report(Loc, DiagID);
+ return;
+ }
+
+ EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(),
+ CI.getTargetOpts(), TheModule.get(),
+ BA, OS);
+ return;
+ }
+
+ // Otherwise follow the normal AST path.
+ this->ASTFrontendAction::ExecuteAction();
+}
+
+//
+
+EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitAssembly, _VMContext) {}
+
+EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitBC, _VMContext) {}
+
+EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitLL, _VMContext) {}
+
+EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitNothing, _VMContext) {}
+
+EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitMCNull, _VMContext) {}
+
+EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext)
+ : CodeGenAction(Backend_EmitObj, _VMContext) {}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
new file mode 100644
index 0000000..f1b7286
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -0,0 +1,790 @@
+//===--- CodeGenFunction.cpp - Emit LLVM Code from ASTs for a Function ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This coordinates the per-function state used while generating code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "CGDebugInfo.h"
+#include "CGException.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Intrinsics.h"
+using namespace clang;
+using namespace CodeGen;
+
+CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
+ : CodeGenTypeCache(cgm), CGM(cgm),
+ Target(CGM.getContext().Target), Builder(cgm.getModule().getContext()),
+ BlockInfo(0), BlockPointer(0),
+ NormalCleanupDest(0), EHCleanupDest(0), NextCleanupDestIndex(1),
+ ExceptionSlot(0), DebugInfo(0), IndirectBranch(0),
+ SwitchInsn(0), CaseRangeBlock(0),
+ DidCallStackSave(false), UnreachableBlock(0),
+ CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0),
+ OutermostConditional(0), TerminateLandingPad(0), TerminateHandler(0),
+ TrapBB(0) {
+
+ CatchUndefined = getContext().getLangOptions().CatchUndefined;
+ CGM.getCXXABI().getMangleContext().startNewFunction();
+}
+
+ASTContext &CodeGenFunction::getContext() const {
+ return CGM.getContext();
+}
+
+
+const llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
+ return CGM.getTypes().ConvertTypeForMem(T);
+}
+
+const llvm::Type *CodeGenFunction::ConvertType(QualType T) {
+ return CGM.getTypes().ConvertType(T);
+}
+
+bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
+ return T->isRecordType() || T->isArrayType() || T->isAnyComplexType() ||
+ T->isObjCObjectType();
+}
+
+void CodeGenFunction::EmitReturnBlock() {
+ // For cleanliness, we try to avoid emitting the return block for
+ // simple cases.
+ llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
+
+ if (CurBB) {
+ assert(!CurBB->getTerminator() && "Unexpected terminated block.");
+
+ // We have a valid insert point, reuse it if it is empty or there are no
+ // explicit jumps to the return block.
+ if (CurBB->empty() || ReturnBlock.getBlock()->use_empty()) {
+ ReturnBlock.getBlock()->replaceAllUsesWith(CurBB);
+ delete ReturnBlock.getBlock();
+ } else
+ EmitBlock(ReturnBlock.getBlock());
+ return;
+ }
+
+ // Otherwise, if the return block is the target of a single direct
+ // branch then we can just put the code in that block instead. This
+ // cleans up functions which started with a unified return block.
+ if (ReturnBlock.getBlock()->hasOneUse()) {
+ llvm::BranchInst *BI =
+ dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->use_begin());
+ if (BI && BI->isUnconditional() &&
+ BI->getSuccessor(0) == ReturnBlock.getBlock()) {
+ // Reset insertion point and delete the branch.
+ Builder.SetInsertPoint(BI->getParent());
+ BI->eraseFromParent();
+ delete ReturnBlock.getBlock();
+ return;
+ }
+ }
+
+ // FIXME: We are at an unreachable point, there is no reason to emit the block
+ // unless it has uses. However, we still need a place to put the debug
+ // region.end for now.
+
+ EmitBlock(ReturnBlock.getBlock());
+}
+
+static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
+ if (!BB) return;
+ if (!BB->use_empty())
+ return CGF.CurFn->getBasicBlockList().push_back(BB);
+ delete BB;
+}
+
+void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
+ assert(BreakContinueStack.empty() &&
+ "mismatched push/pop in break/continue stack!");
+
+ // Emit function epilog (to return).
+ EmitReturnBlock();
+
+ if (ShouldInstrumentFunction())
+ EmitFunctionInstrumentation("__cyg_profile_func_exit");
+
+ // Emit debug descriptor for function end.
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(EndLoc);
+ DI->EmitFunctionEnd(Builder);
+ }
+
+ EmitFunctionEpilog(*CurFnInfo);
+ EmitEndEHSpec(CurCodeDecl);
+
+ assert(EHStack.empty() &&
+ "did not remove all scopes from cleanup stack!");
+
+ // If someone did an indirect goto, emit the indirect goto block at the end of
+ // the function.
+ if (IndirectBranch) {
+ EmitBlock(IndirectBranch->getParent());
+ Builder.ClearInsertionPoint();
+ }
+
+ // Remove the AllocaInsertPt instruction, which is just a convenience for us.
+ llvm::Instruction *Ptr = AllocaInsertPt;
+ AllocaInsertPt = 0;
+ Ptr->eraseFromParent();
+
+ // If someone took the address of a label but never did an indirect goto, we
+ // made a zero entry PHI node, which is illegal, zap it now.
+ if (IndirectBranch) {
+ llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
+ if (PN->getNumIncomingValues() == 0) {
+ PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType()));
+ PN->eraseFromParent();
+ }
+ }
+
+ EmitIfUsed(*this, RethrowBlock.getBlock());
+ EmitIfUsed(*this, TerminateLandingPad);
+ EmitIfUsed(*this, TerminateHandler);
+ EmitIfUsed(*this, UnreachableBlock);
+
+ if (CGM.getCodeGenOpts().EmitDeclMetadata)
+ EmitDeclMetadata();
+}
+
+/// ShouldInstrumentFunction - Return true if the current function should be
+/// instrumented with __cyg_profile_func_* calls
+bool CodeGenFunction::ShouldInstrumentFunction() {
+ if (!CGM.getCodeGenOpts().InstrumentFunctions)
+ return false;
+ if (CurFuncDecl->hasAttr<NoInstrumentFunctionAttr>())
+ return false;
+ return true;
+}
+
+/// EmitFunctionInstrumentation - Emit LLVM code to call the specified
+/// instrumentation function with the current function and the call site, if
+/// function instrumentation is enabled.
+void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) {
+ const llvm::PointerType *PointerTy;
+ const llvm::FunctionType *FunctionTy;
+ std::vector<const llvm::Type*> ProfileFuncArgs;
+
+ // void __cyg_profile_func_{enter,exit} (void *this_fn, void *call_site);
+ PointerTy = Int8PtrTy;
+ ProfileFuncArgs.push_back(PointerTy);
+ ProfileFuncArgs.push_back(PointerTy);
+ FunctionTy = llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
+ ProfileFuncArgs, false);
+
+ llvm::Constant *F = CGM.CreateRuntimeFunction(FunctionTy, Fn);
+ llvm::CallInst *CallSite = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::returnaddress, 0, 0),
+ llvm::ConstantInt::get(Int32Ty, 0),
+ "callsite");
+
+ Builder.CreateCall2(F,
+ llvm::ConstantExpr::getBitCast(CurFn, PointerTy),
+ CallSite);
+}
+
+void CodeGenFunction::EmitMCountInstrumentation() {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), false);
+
+ llvm::Constant *MCountFn = CGM.CreateRuntimeFunction(FTy,
+ Target.getMCountName());
+ Builder.CreateCall(MCountFn);
+}
+
+void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
+ llvm::Function *Fn,
+ const FunctionArgList &Args,
+ SourceLocation StartLoc) {
+ const Decl *D = GD.getDecl();
+
+ DidCallStackSave = false;
+ CurCodeDecl = CurFuncDecl = D;
+ FnRetTy = RetTy;
+ CurFn = Fn;
+ assert(CurFn->isDeclaration() && "Function already has body?");
+
+ // Pass inline keyword to optimizer if it appears explicitly on any
+ // declaration.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ for (FunctionDecl::redecl_iterator RI = FD->redecls_begin(),
+ RE = FD->redecls_end(); RI != RE; ++RI)
+ if (RI->isInlineSpecified()) {
+ Fn->addFnAttr(llvm::Attribute::InlineHint);
+ break;
+ }
+
+ if (getContext().getLangOptions().OpenCL) {
+ // Add metadata for a kernel function.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (FD->hasAttr<OpenCLKernelAttr>()) {
+ llvm::LLVMContext &Context = getLLVMContext();
+ llvm::NamedMDNode *OpenCLMetadata =
+ CGM.getModule().getOrInsertNamedMetadata("opencl.kernels");
+
+ llvm::Value *Op = Fn;
+ OpenCLMetadata->addOperand(llvm::MDNode::get(Context, &Op, 1));
+ }
+ }
+
+ llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
+
+ // Create a marker to make it easy to insert allocas into the entryblock
+ // later. Don't create this with the builder, because we don't want it
+ // folded.
+ llvm::Value *Undef = llvm::UndefValue::get(Int32Ty);
+ AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "", EntryBB);
+ if (Builder.isNamePreserving())
+ AllocaInsertPt->setName("allocapt");
+
+ ReturnBlock = getJumpDestInCurrentScope("return");
+
+ Builder.SetInsertPoint(EntryBB);
+
+ // Emit subprogram debug descriptor.
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ // FIXME: what is going on here and why does it ignore all these
+ // interesting type properties?
+ QualType FnType =
+ getContext().getFunctionType(RetTy, 0, 0,
+ FunctionProtoType::ExtProtoInfo());
+
+ DI->setLocation(StartLoc);
+ DI->EmitFunctionStart(GD, FnType, CurFn, Builder);
+ }
+
+ if (ShouldInstrumentFunction())
+ EmitFunctionInstrumentation("__cyg_profile_func_enter");
+
+ if (CGM.getCodeGenOpts().InstrumentForProfiling)
+ EmitMCountInstrumentation();
+
+ // FIXME: Leaked.
+ // CC info is ignored, hopefully?
+ CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args,
+ FunctionType::ExtInfo());
+
+ if (RetTy->isVoidType()) {
+ // Void type; nothing to return.
+ ReturnValue = 0;
+ } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+ hasAggregateLLVMType(CurFnInfo->getReturnType())) {
+ // Indirect aggregate return; emit returned value directly into sret slot.
+ // This reduces code size, and affects correctness in C++.
+ ReturnValue = CurFn->arg_begin();
+ } else {
+ ReturnValue = CreateIRTemp(RetTy, "retval");
+ }
+
+ EmitStartEHSpec(CurCodeDecl);
+ EmitFunctionProlog(*CurFnInfo, CurFn, Args);
+
+ if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
+ // If any of the arguments have a variably modified type, make sure to
+ // emit the type size.
+ for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
+ i != e; ++i) {
+ QualType Ty = i->second;
+
+ if (Ty->isVariablyModifiedType())
+ EmitVLASize(Ty);
+ }
+}
+
+void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
+ const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl());
+ assert(FD->getBody());
+ EmitStmt(FD->getBody());
+}
+
+/// Tries to mark the given function nounwind based on the
+/// non-existence of any throwing calls within it. We believe this is
+/// lightweight enough to do at -O0.
+static void TryMarkNoThrow(llvm::Function *F) {
+ // LLVM treats 'nounwind' on a function as part of the type, so we
+ // can't do this on functions that can be overwritten.
+ if (F->mayBeOverridden()) return;
+
+ for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
+ for (llvm::BasicBlock::iterator
+ BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
+ if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI))
+ if (!Call->doesNotThrow())
+ return;
+ F->setDoesNotThrow(true);
+}
+
+void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ // Check if we should generate debug info for this function.
+ if (CGM.getDebugInfo() && !FD->hasAttr<NoDebugAttr>())
+ DebugInfo = CGM.getDebugInfo();
+
+ FunctionArgList Args;
+ QualType ResTy = FD->getResultType();
+
+ CurGD = GD;
+ if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
+ CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
+
+ if (FD->getNumParams()) {
+ const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>();
+ assert(FProto && "Function def must have prototype!");
+
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
+ Args.push_back(std::make_pair(FD->getParamDecl(i),
+ FProto->getArgType(i)));
+ }
+
+ SourceRange BodyRange;
+ if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
+
+ // Emit the standard function prologue.
+ StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin());
+
+ // Generate the body of the function.
+ if (isa<CXXDestructorDecl>(FD))
+ EmitDestructorBody(Args);
+ else if (isa<CXXConstructorDecl>(FD))
+ EmitConstructorBody(Args);
+ else
+ EmitFunctionBody(Args);
+
+ // Emit the standard function epilogue.
+ FinishFunction(BodyRange.getEnd());
+
+ // If we haven't marked the function nothrow through other means, do
+ // a quick pass now to see if we can.
+ if (!CurFn->doesNotThrow())
+ TryMarkNoThrow(CurFn);
+}
+
+/// ContainsLabel - Return true if the statement contains a label in it. If
+/// this statement is not executed normally, it not containing a label means
+/// that we can just remove the code.
+bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
+ // Null statement, not a label!
+ if (S == 0) return false;
+
+ // If this is a label, we have to emit the code, consider something like:
+ // if (0) { ... foo: bar(); } goto foo;
+ if (isa<LabelStmt>(S))
+ return true;
+
+ // If this is a case/default statement, and we haven't seen a switch, we have
+ // to emit the code.
+ if (isa<SwitchCase>(S) && !IgnoreCaseStmts)
+ return true;
+
+ // If this is a switch statement, we want to ignore cases below it.
+ if (isa<SwitchStmt>(S))
+ IgnoreCaseStmts = true;
+
+ // Scan subexpressions for verboten labels.
+ for (Stmt::const_child_range I = S->children(); I; ++I)
+ if (ContainsLabel(*I, IgnoreCaseStmts))
+ return true;
+
+ return false;
+}
+
+
+/// ConstantFoldsToSimpleInteger - If the sepcified expression does not fold to
+/// a constant, or if it does but contains a label, return 0. If it constant
+/// folds to 'true' and does not contain a label, return 1, if it constant folds
+/// to 'false' and does not contain a label, return -1.
+int CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond) {
+ // FIXME: Rename and handle conversion of other evaluatable things
+ // to bool.
+ Expr::EvalResult Result;
+ if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() ||
+ Result.HasSideEffects)
+ return 0; // Not foldable, not integer or not fully evaluatable.
+
+ if (CodeGenFunction::ContainsLabel(Cond))
+ return 0; // Contains a label.
+
+ return Result.Val.getInt().getBoolValue() ? 1 : -1;
+}
+
+
+/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if
+/// statement) to the specified blocks. Based on the condition, this might try
+/// to simplify the codegen of the conditional based on the branch.
+///
+void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
+ llvm::BasicBlock *TrueBlock,
+ llvm::BasicBlock *FalseBlock) {
+ if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond))
+ return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock);
+
+ if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
+ // Handle X && Y in a condition.
+ if (CondBOp->getOpcode() == BO_LAnd) {
+ // If we have "1 && X", simplify the code. "0 && X" would have constant
+ // folded if the case was simple enough.
+ if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == 1) {
+ // br(1 && X) -> br(X).
+ return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
+ }
+
+ // If we have "X && 1", simplify the code to use an uncond branch.
+ // "X && 0" would have been constant folded to 0.
+ if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == 1) {
+ // br(X && 1) -> br(X).
+ return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock);
+ }
+
+ // Emit the LHS as a conditional. If the LHS conditional is false, we
+ // want to jump to the FalseBlock.
+ llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true");
+
+ ConditionalEvaluation eval(*this);
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock);
+ EmitBlock(LHSTrue);
+
+ // Any temporaries created here are conditional.
+ eval.begin(*this);
+ EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
+ eval.end(*this);
+
+ return;
+ } else if (CondBOp->getOpcode() == BO_LOr) {
+ // If we have "0 || X", simplify the code. "1 || X" would have constant
+ // folded if the case was simple enough.
+ if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == -1) {
+ // br(0 || X) -> br(X).
+ return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
+ }
+
+ // If we have "X || 0", simplify the code to use an uncond branch.
+ // "X || 1" would have been constant folded to 1.
+ if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == -1) {
+ // br(X || 0) -> br(X).
+ return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock);
+ }
+
+ // Emit the LHS as a conditional. If the LHS conditional is true, we
+ // want to jump to the TrueBlock.
+ llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false");
+
+ ConditionalEvaluation eval(*this);
+ EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse);
+ EmitBlock(LHSFalse);
+
+ // Any temporaries created here are conditional.
+ eval.begin(*this);
+ EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
+ eval.end(*this);
+
+ return;
+ }
+ }
+
+ if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) {
+ // br(!x, t, f) -> br(x, f, t)
+ if (CondUOp->getOpcode() == UO_LNot)
+ return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock);
+ }
+
+ if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) {
+ // Handle ?: operator.
+
+ // Just ignore GNU ?: extension.
+ if (CondOp->getLHS()) {
+ // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f))
+ llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
+ llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
+
+ ConditionalEvaluation cond(*this);
+ EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock);
+
+ cond.begin(*this);
+ EmitBlock(LHSBlock);
+ EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock);
+ cond.end(*this);
+
+ cond.begin(*this);
+ EmitBlock(RHSBlock);
+ EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock);
+ cond.end(*this);
+
+ return;
+ }
+ }
+
+ // Emit the code with the fully general case.
+ llvm::Value *CondV = EvaluateExprAsBool(Cond);
+ Builder.CreateCondBr(CondV, TrueBlock, FalseBlock);
+}
+
+/// ErrorUnsupported - Print out an error that codegen doesn't support the
+/// specified stmt yet.
+void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
+ bool OmitOnError) {
+ CGM.ErrorUnsupported(S, Type, OmitOnError);
+}
+
+/// emitNonZeroVLAInit - Emit the "zero" initialization of a
+/// variable-length array whose elements have a non-zero bit-pattern.
+///
+/// \param src - a char* pointing to the bit-pattern for a single
+/// base element of the array
+/// \param sizeInChars - the total size of the VLA, in chars
+/// \param align - the total alignment of the VLA
+static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
+ llvm::Value *dest, llvm::Value *src,
+ llvm::Value *sizeInChars) {
+ std::pair<CharUnits,CharUnits> baseSizeAndAlign
+ = CGF.getContext().getTypeInfoInChars(baseType);
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ llvm::Value *baseSizeInChars
+ = llvm::ConstantInt::get(CGF.IntPtrTy, baseSizeAndAlign.first.getQuantity());
+
+ const llvm::Type *i8p = Builder.getInt8PtrTy();
+
+ llvm::Value *begin = Builder.CreateBitCast(dest, i8p, "vla.begin");
+ llvm::Value *end = Builder.CreateInBoundsGEP(dest, sizeInChars, "vla.end");
+
+ llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
+ llvm::BasicBlock *contBB = CGF.createBasicBlock("vla-init.cont");
+
+ // Make a loop over the VLA. C99 guarantees that the VLA element
+ // count must be nonzero.
+ CGF.EmitBlock(loopBB);
+
+ llvm::PHINode *cur = Builder.CreatePHI(i8p, "vla.cur");
+ cur->reserveOperandSpace(2);
+ cur->addIncoming(begin, originBB);
+
+ // memcpy the individual element bit-pattern.
+ Builder.CreateMemCpy(cur, src, baseSizeInChars,
+ baseSizeAndAlign.second.getQuantity(),
+ /*volatile*/ false);
+
+ // Go to the next element.
+ llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(cur, 1, "vla.next");
+
+ // Leave if that's the end of the VLA.
+ llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
+ Builder.CreateCondBr(done, contBB, loopBB);
+ cur->addIncoming(next, loopBB);
+
+ CGF.EmitBlock(contBB);
+}
+
+void
+CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
+ // Ignore empty classes in C++.
+ if (getContext().getLangOptions().CPlusPlus) {
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty())
+ return;
+ }
+ }
+
+ // Cast the dest ptr to the appropriate i8 pointer type.
+ unsigned DestAS =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+ const llvm::Type *BP = Builder.getInt8PtrTy(DestAS);
+ if (DestPtr->getType() != BP)
+ DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
+
+ // Get size and alignment info for this aggregate.
+ std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty);
+ uint64_t Size = TypeInfo.first / 8;
+ unsigned Align = TypeInfo.second / 8;
+
+ llvm::Value *SizeVal;
+ const VariableArrayType *vla;
+
+ // Don't bother emitting a zero-byte memset.
+ if (Size == 0) {
+ // But note that getTypeInfo returns 0 for a VLA.
+ if (const VariableArrayType *vlaType =
+ dyn_cast_or_null<VariableArrayType>(
+ getContext().getAsArrayType(Ty))) {
+ SizeVal = GetVLASize(vlaType);
+ vla = vlaType;
+ } else {
+ return;
+ }
+ } else {
+ SizeVal = llvm::ConstantInt::get(IntPtrTy, Size);
+ vla = 0;
+ }
+
+ // If the type contains a pointer to data member we can't memset it to zero.
+ // Instead, create a null constant and copy it to the destination.
+ // TODO: there are other patterns besides zero that we can usefully memset,
+ // like -1, which happens to be the pattern used by member-pointers.
+ if (!CGM.getTypes().isZeroInitializable(Ty)) {
+ // For a VLA, emit a single element, then splat that over the VLA.
+ if (vla) Ty = getContext().getBaseElementType(vla);
+
+ llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
+
+ llvm::GlobalVariable *NullVariable =
+ new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalVariable::PrivateLinkage,
+ NullConstant, llvm::Twine());
+ llvm::Value *SrcPtr =
+ Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy());
+
+ if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
+
+ // Get and call the appropriate llvm.memcpy overload.
+ Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align, false);
+ return;
+ }
+
+ // Otherwise, just memset the whole thing to zero. This is legal
+ // because in LLVM, all default initializers (other than the ones we just
+ // handled above) are guaranteed to have a bit pattern of all zeros.
+ Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, Align, false);
+}
+
+llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
+ // Make sure that there is a block for the indirect goto.
+ if (IndirectBranch == 0)
+ GetIndirectGotoBlock();
+
+ llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock();
+
+ // Make sure the indirect branch includes all of the address-taken blocks.
+ IndirectBranch->addDestination(BB);
+ return llvm::BlockAddress::get(CurFn, BB);
+}
+
+llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
+ // If we already made the indirect branch for indirect goto, return its block.
+ if (IndirectBranch) return IndirectBranch->getParent();
+
+ CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
+
+ // Create the PHI node that indirect gotos will add entries to.
+ llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest");
+
+ // Create the indirect branch instruction.
+ IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
+ return IndirectBranch->getParent();
+}
+
+llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
+ llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
+
+ assert(SizeEntry && "Did not emit size for type");
+ return SizeEntry;
+}
+
+llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) {
+ assert(Ty->isVariablyModifiedType() &&
+ "Must pass variably modified type to EmitVLASizes!");
+
+ EnsureInsertPoint();
+
+ if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
+ // unknown size indication requires no size computation.
+ if (!VAT->getSizeExpr())
+ return 0;
+ llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
+
+ if (!SizeEntry) {
+ const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
+
+ // Get the element size;
+ QualType ElemTy = VAT->getElementType();
+ llvm::Value *ElemSize;
+ if (ElemTy->isVariableArrayType())
+ ElemSize = EmitVLASize(ElemTy);
+ else
+ ElemSize = llvm::ConstantInt::get(SizeTy,
+ getContext().getTypeSizeInChars(ElemTy).getQuantity());
+
+ llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr());
+ NumElements = Builder.CreateIntCast(NumElements, SizeTy, false, "tmp");
+
+ SizeEntry = Builder.CreateMul(ElemSize, NumElements);
+ }
+
+ return SizeEntry;
+ }
+
+ if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
+ EmitVLASize(AT->getElementType());
+ return 0;
+ }
+
+ if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
+ EmitVLASize(PT->getInnerType());
+ return 0;
+ }
+
+ const PointerType *PT = Ty->getAs<PointerType>();
+ assert(PT && "unknown VM type!");
+ EmitVLASize(PT->getPointeeType());
+ return 0;
+}
+
+llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
+ if (getContext().getBuiltinVaListType()->isArrayType())
+ return EmitScalarExpr(E);
+ return EmitLValue(E).getAddress();
+}
+
+void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
+ llvm::Constant *Init) {
+ assert (Init && "Invalid DeclRefExpr initializer!");
+ if (CGDebugInfo *Dbg = getDebugInfo())
+ Dbg->EmitGlobalVariable(E->getDecl(), Init);
+}
+
+CodeGenFunction::PeepholeProtection
+CodeGenFunction::protectFromPeepholes(RValue rvalue) {
+ // At the moment, the only aggressive peephole we do in IR gen
+ // is trunc(zext) folding, but if we add more, we can easily
+ // extend this protection.
+
+ if (!rvalue.isScalar()) return PeepholeProtection();
+ llvm::Value *value = rvalue.getScalarVal();
+ if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();
+
+ // Just make an extra bitcast.
+ assert(HaveInsertPoint());
+ llvm::Instruction *inst = new llvm::BitCastInst(value, value->getType(), "",
+ Builder.GetInsertBlock());
+
+ PeepholeProtection protection;
+ protection.Inst = inst;
+ return protection;
+}
+
+void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
+ if (!protection.Inst) return;
+
+ // In theory, we could try to duplicate the peepholes now, but whatever.
+ protection.Inst->eraseFromParent();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
new file mode 100644
index 0000000..67ef414
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -0,0 +1,2187 @@
+//===-- CodeGenFunction.h - Per-Function state for LLVM CodeGen -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-function state used for llvm translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CODEGENFUNCTION_H
+#define CLANG_CODEGEN_CODEGENFUNCTION_H
+
+#include "clang/AST/Type.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/Basic/ABI.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ValueHandle.h"
+#include "CodeGenModule.h"
+#include "CGBuilder.h"
+#include "CGCall.h"
+#include "CGValue.h"
+
+namespace llvm {
+ class BasicBlock;
+ class LLVMContext;
+ class MDNode;
+ class Module;
+ class SwitchInst;
+ class Twine;
+ class Value;
+ class CallSite;
+}
+
+namespace clang {
+ class APValue;
+ class ASTContext;
+ class CXXDestructorDecl;
+ class CXXTryStmt;
+ class Decl;
+ class LabelDecl;
+ class EnumConstantDecl;
+ class FunctionDecl;
+ class FunctionProtoType;
+ class LabelStmt;
+ class ObjCContainerDecl;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
+ class ObjCMethodDecl;
+ class ObjCImplementationDecl;
+ class ObjCPropertyImplDecl;
+ class TargetInfo;
+ class TargetCodeGenInfo;
+ class VarDecl;
+ class ObjCForCollectionStmt;
+ class ObjCAtTryStmt;
+ class ObjCAtThrowStmt;
+ class ObjCAtSynchronizedStmt;
+
+namespace CodeGen {
+ class CodeGenTypes;
+ class CGDebugInfo;
+ class CGFunctionInfo;
+ class CGRecordLayout;
+ class CGBlockInfo;
+ class CGCXXABI;
+ class BlockFlags;
+ class BlockFieldFlags;
+
+/// A branch fixup. These are required when emitting a goto to a
+/// label which hasn't been emitted yet. The goto is optimistically
+/// emitted as a branch to the basic block for the label, and (if it
+/// occurs in a scope with non-trivial cleanups) a fixup is added to
+/// the innermost cleanup. When a (normal) cleanup is popped, any
+/// unresolved fixups in that scope are threaded through the cleanup.
+struct BranchFixup {
+ /// The block containing the terminator which needs to be modified
+ /// into a switch if this fixup is resolved into the current scope.
+ /// If null, LatestBranch points directly to the destination.
+ llvm::BasicBlock *OptimisticBranchBlock;
+
+ /// The ultimate destination of the branch.
+ ///
+ /// This can be set to null to indicate that this fixup was
+ /// successfully resolved.
+ llvm::BasicBlock *Destination;
+
+ /// The destination index value.
+ unsigned DestinationIndex;
+
+ /// The initial branch of the fixup.
+ llvm::BranchInst *InitialBranch;
+};
+
+template <class T> struct InvariantValue {
+ typedef T type;
+ typedef T saved_type;
+ static bool needsSaving(type value) { return false; }
+ static saved_type save(CodeGenFunction &CGF, type value) { return value; }
+ static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
+};
+
+/// A metaprogramming class for ensuring that a value will dominate an
+/// arbitrary position in a function.
+template <class T> struct DominatingValue : InvariantValue<T> {};
+
+template <class T, bool mightBeInstruction =
+ llvm::is_base_of<llvm::Value, T>::value &&
+ !llvm::is_base_of<llvm::Constant, T>::value &&
+ !llvm::is_base_of<llvm::BasicBlock, T>::value>
+struct DominatingPointer;
+template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
+// template <class T> struct DominatingPointer<T,true> at end of file
+
+template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
+
+enum CleanupKind {
+ EHCleanup = 0x1,
+ NormalCleanup = 0x2,
+ NormalAndEHCleanup = EHCleanup | NormalCleanup,
+
+ InactiveCleanup = 0x4,
+ InactiveEHCleanup = EHCleanup | InactiveCleanup,
+ InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
+ InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
+};
+
+/// A stack of scopes which respond to exceptions, including cleanups
+/// and catch blocks.
+class EHScopeStack {
+public:
+ /// A saved depth on the scope stack. This is necessary because
+ /// pushing scopes onto the stack invalidates iterators.
+ class stable_iterator {
+ friend class EHScopeStack;
+
+ /// Offset from StartOfData to EndOfBuffer.
+ ptrdiff_t Size;
+
+ stable_iterator(ptrdiff_t Size) : Size(Size) {}
+
+ public:
+ static stable_iterator invalid() { return stable_iterator(-1); }
+ stable_iterator() : Size(-1) {}
+
+ bool isValid() const { return Size >= 0; }
+
+ /// Returns true if this scope encloses I.
+ /// Returns false if I is invalid.
+ /// This scope must be valid.
+ bool encloses(stable_iterator I) const { return Size <= I.Size; }
+
+ /// Returns true if this scope strictly encloses I: that is,
+ /// if it encloses I and is not I.
+ /// Returns false is I is invalid.
+ /// This scope must be valid.
+ bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
+
+ friend bool operator==(stable_iterator A, stable_iterator B) {
+ return A.Size == B.Size;
+ }
+ friend bool operator!=(stable_iterator A, stable_iterator B) {
+ return A.Size != B.Size;
+ }
+ };
+
+ /// Information for lazily generating a cleanup. Subclasses must be
+ /// POD-like: cleanups will not be destructed, and they will be
+ /// allocated on the cleanup stack and freely copied and moved
+ /// around.
+ ///
+ /// Cleanup implementations should generally be declared in an
+ /// anonymous namespace.
+ class Cleanup {
+ public:
+ // Anchor the construction vtable. We use the destructor because
+ // gcc gives an obnoxious warning if there are virtual methods
+ // with an accessible non-virtual destructor. Unfortunately,
+ // declaring this destructor makes it non-trivial, but there
+ // doesn't seem to be any other way around this warning.
+ //
+ // This destructor will never be called.
+ virtual ~Cleanup();
+
+ /// Emit the cleanup. For normal cleanups, this is run in the
+ /// same EH context as when the cleanup was pushed, i.e. the
+ /// immediately-enclosing context of the cleanup scope. For
+ /// EH cleanups, this is run in a terminate context.
+ ///
+ // \param IsForEHCleanup true if this is for an EH cleanup, false
+ /// if for a normal cleanup.
+ virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0;
+ };
+
+ /// UnconditionalCleanupN stores its N parameters and just passes
+ /// them to the real cleanup function.
+ template <class T, class A0>
+ class UnconditionalCleanup1 : public Cleanup {
+ A0 a0;
+ public:
+ UnconditionalCleanup1(A0 a0) : a0(a0) {}
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ T::Emit(CGF, IsForEHCleanup, a0);
+ }
+ };
+
+ template <class T, class A0, class A1>
+ class UnconditionalCleanup2 : public Cleanup {
+ A0 a0; A1 a1;
+ public:
+ UnconditionalCleanup2(A0 a0, A1 a1) : a0(a0), a1(a1) {}
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ T::Emit(CGF, IsForEHCleanup, a0, a1);
+ }
+ };
+
+ /// ConditionalCleanupN stores the saved form of its N parameters,
+ /// then restores them and performs the cleanup.
+ template <class T, class A0>
+ class ConditionalCleanup1 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ A0_saved a0_saved;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ T::Emit(CGF, IsForEHCleanup, a0);
+ }
+
+ public:
+ ConditionalCleanup1(A0_saved a0)
+ : a0_saved(a0) {}
+ };
+
+ template <class T, class A0, class A1>
+ class ConditionalCleanup2 : public Cleanup {
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A1>::saved_type A1_saved;
+ A0_saved a0_saved;
+ A1_saved a1_saved;
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
+ T::Emit(CGF, IsForEHCleanup, a0, a1);
+ }
+
+ public:
+ ConditionalCleanup2(A0_saved a0, A1_saved a1)
+ : a0_saved(a0), a1_saved(a1) {}
+ };
+
+private:
+ // The implementation for this class is in CGException.h and
+ // CGException.cpp; the definition is here because it's used as a
+ // member of CodeGenFunction.
+
+ /// The start of the scope-stack buffer, i.e. the allocated pointer
+ /// for the buffer. All of these pointers are either simultaneously
+ /// null or simultaneously valid.
+ char *StartOfBuffer;
+
+ /// The end of the buffer.
+ char *EndOfBuffer;
+
+ /// The first valid entry in the buffer.
+ char *StartOfData;
+
+ /// The innermost normal cleanup on the stack.
+ stable_iterator InnermostNormalCleanup;
+
+ /// The innermost EH cleanup on the stack.
+ stable_iterator InnermostEHCleanup;
+
+ /// The number of catches on the stack.
+ unsigned CatchDepth;
+
+ /// The current EH destination index. Reset to FirstCatchIndex
+ /// whenever the last EH cleanup is popped.
+ unsigned NextEHDestIndex;
+ enum { FirstEHDestIndex = 1 };
+
+ /// The current set of branch fixups. A branch fixup is a jump to
+ /// an as-yet unemitted label, i.e. a label for which we don't yet
+ /// know the EH stack depth. Whenever we pop a cleanup, we have
+ /// to thread all the current branch fixups through it.
+ ///
+ /// Fixups are recorded as the Use of the respective branch or
+ /// switch statement. The use points to the final destination.
+ /// When popping out of a cleanup, these uses are threaded through
+ /// the cleanup and adjusted to point to the new cleanup.
+ ///
+ /// Note that branches are allowed to jump into protected scopes
+ /// in certain situations; e.g. the following code is legal:
+ /// struct A { ~A(); }; // trivial ctor, non-trivial dtor
+ /// goto foo;
+ /// A a;
+ /// foo:
+ /// bar();
+ llvm::SmallVector<BranchFixup, 8> BranchFixups;
+
+ char *allocate(size_t Size);
+
+ void *pushCleanup(CleanupKind K, size_t DataSize);
+
+public:
+ EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
+ InnermostNormalCleanup(stable_end()),
+ InnermostEHCleanup(stable_end()),
+ CatchDepth(0), NextEHDestIndex(FirstEHDestIndex) {}
+ ~EHScopeStack() { delete[] StartOfBuffer; }
+
+ // Variadic templates would make this not terrible.
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T>
+ void pushCleanup(CleanupKind Kind) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T();
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0>
+ void pushCleanup(CleanupKind Kind, A0 a0) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3, class A4>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
+ (void) Obj;
+ }
+
+ // Feel free to add more variants of the following:
+
+ /// Push a cleanup with non-constant storage requirements on the
+ /// stack. The cleanup type must provide an additional static method:
+ /// static size_t getExtraSize(size_t);
+ /// The argument to this method will be the value N, which will also
+ /// be passed as the first argument to the constructor.
+ ///
+ /// The data stored in the extra storage must obey the same
+ /// restrictions as normal cleanup member data.
+ ///
+ /// The pointer returned from this method is valid until the cleanup
+ /// stack is modified.
+ template <class T, class A0, class A1, class A2>
+ T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
+ return new (Buffer) T(N, a0, a1, a2);
+ }
+
+ /// Pops a cleanup scope off the stack. This should only be called
+ /// by CodeGenFunction::PopCleanupBlock.
+ void popCleanup();
+
+ /// Push a set of catch handlers on the stack. The catch is
+ /// uninitialized and will need to have the given number of handlers
+ /// set on it.
+ class EHCatchScope *pushCatch(unsigned NumHandlers);
+
+ /// Pops a catch scope off the stack.
+ void popCatch();
+
+ /// Push an exceptions filter on the stack.
+ class EHFilterScope *pushFilter(unsigned NumFilters);
+
+ /// Pops an exceptions filter off the stack.
+ void popFilter();
+
+ /// Push a terminate handler on the stack.
+ void pushTerminate();
+
+ /// Pops a terminate handler off the stack.
+ void popTerminate();
+
+ /// Determines whether the exception-scopes stack is empty.
+ bool empty() const { return StartOfData == EndOfBuffer; }
+
+ bool requiresLandingPad() const {
+ return (CatchDepth || hasEHCleanups());
+ }
+
+ /// Determines whether there are any normal cleanups on the stack.
+ bool hasNormalCleanups() const {
+ return InnermostNormalCleanup != stable_end();
+ }
+
+ /// Returns the innermost normal cleanup on the stack, or
+ /// stable_end() if there are no normal cleanups.
+ stable_iterator getInnermostNormalCleanup() const {
+ return InnermostNormalCleanup;
+ }
+ stable_iterator getInnermostActiveNormalCleanup() const; // CGException.h
+
+ /// Determines whether there are any EH cleanups on the stack.
+ bool hasEHCleanups() const {
+ return InnermostEHCleanup != stable_end();
+ }
+
+ /// Returns the innermost EH cleanup on the stack, or stable_end()
+ /// if there are no EH cleanups.
+ stable_iterator getInnermostEHCleanup() const {
+ return InnermostEHCleanup;
+ }
+ stable_iterator getInnermostActiveEHCleanup() const; // CGException.h
+
+ /// An unstable reference to a scope-stack depth. Invalidated by
+ /// pushes but not pops.
+ class iterator;
+
+ /// Returns an iterator pointing to the innermost EH scope.
+ iterator begin() const;
+
+ /// Returns an iterator pointing to the outermost EH scope.
+ iterator end() const;
+
+ /// Create a stable reference to the top of the EH stack. The
+ /// returned reference is valid until that scope is popped off the
+ /// stack.
+ stable_iterator stable_begin() const {
+ return stable_iterator(EndOfBuffer - StartOfData);
+ }
+
+ /// Create a stable reference to the bottom of the EH stack.
+ static stable_iterator stable_end() {
+ return stable_iterator(0);
+ }
+
+ /// Translates an iterator into a stable_iterator.
+ stable_iterator stabilize(iterator it) const;
+
+ /// Finds the nearest cleanup enclosing the given iterator.
+ /// Returns stable_iterator::invalid() if there are no such cleanups.
+ stable_iterator getEnclosingEHCleanup(iterator it) const;
+
+ /// Turn a stable reference to a scope depth into a unstable pointer
+ /// to the EH stack.
+ iterator find(stable_iterator save) const;
+
+ /// Removes the cleanup pointed to by the given stable_iterator.
+ void removeCleanup(stable_iterator save);
+
+ /// Add a branch fixup to the current cleanup scope.
+ BranchFixup &addBranchFixup() {
+ assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
+ BranchFixups.push_back(BranchFixup());
+ return BranchFixups.back();
+ }
+
+ unsigned getNumBranchFixups() const { return BranchFixups.size(); }
+ BranchFixup &getBranchFixup(unsigned I) {
+ assert(I < getNumBranchFixups());
+ return BranchFixups[I];
+ }
+
+ /// Pops lazily-removed fixups from the end of the list. This
+ /// should only be called by procedures which have just popped a
+ /// cleanup or resolved one or more fixups.
+ void popNullFixups();
+
+ /// Clears the branch-fixups list. This should only be called by
+ /// ResolveAllBranchFixups.
+ void clearFixups() { BranchFixups.clear(); }
+
+ /// Gets the next EH destination index.
+ unsigned getNextEHDestIndex() { return NextEHDestIndex++; }
+};
+
+/// CodeGenFunction - This class organizes the per-function state that is used
+/// while generating LLVM code.
+class CodeGenFunction : public CodeGenTypeCache {
+ CodeGenFunction(const CodeGenFunction&); // DO NOT IMPLEMENT
+ void operator=(const CodeGenFunction&); // DO NOT IMPLEMENT
+
+ friend class CGCXXABI;
+public:
+ /// A jump destination is an abstract label, branching to which may
+ /// require a jump out through normal cleanups.
+ struct JumpDest {
+ JumpDest() : Block(0), ScopeDepth(), Index(0) {}
+ JumpDest(llvm::BasicBlock *Block,
+ EHScopeStack::stable_iterator Depth,
+ unsigned Index)
+ : Block(Block), ScopeDepth(Depth), Index(Index) {}
+
+ bool isValid() const { return Block != 0; }
+ llvm::BasicBlock *getBlock() const { return Block; }
+ EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
+ unsigned getDestIndex() const { return Index; }
+
+ private:
+ llvm::BasicBlock *Block;
+ EHScopeStack::stable_iterator ScopeDepth;
+ unsigned Index;
+ };
+
+ /// An unwind destination is an abstract label, branching to which
+ /// may require a jump out through EH cleanups.
+ struct UnwindDest {
+ UnwindDest() : Block(0), ScopeDepth(), Index(0) {}
+ UnwindDest(llvm::BasicBlock *Block,
+ EHScopeStack::stable_iterator Depth,
+ unsigned Index)
+ : Block(Block), ScopeDepth(Depth), Index(Index) {}
+
+ bool isValid() const { return Block != 0; }
+ llvm::BasicBlock *getBlock() const { return Block; }
+ EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
+ unsigned getDestIndex() const { return Index; }
+
+ private:
+ llvm::BasicBlock *Block;
+ EHScopeStack::stable_iterator ScopeDepth;
+ unsigned Index;
+ };
+
+ CodeGenModule &CGM; // Per-module state.
+ const TargetInfo &Target;
+
+ typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy;
+ CGBuilderTy Builder;
+
+ /// CurFuncDecl - Holds the Decl for the current function or ObjC method.
+ /// This excludes BlockDecls.
+ const Decl *CurFuncDecl;
+ /// CurCodeDecl - This is the inner-most code context, which includes blocks.
+ const Decl *CurCodeDecl;
+ const CGFunctionInfo *CurFnInfo;
+ QualType FnRetTy;
+ llvm::Function *CurFn;
+
+ /// CurGD - The GlobalDecl for the current function being compiled.
+ GlobalDecl CurGD;
+
+ /// ReturnBlock - Unified return block.
+ JumpDest ReturnBlock;
+
+ /// ReturnValue - The temporary alloca to hold the return value. This is null
+ /// iff the function has no return value.
+ llvm::Value *ReturnValue;
+
+ /// RethrowBlock - Unified rethrow block.
+ UnwindDest RethrowBlock;
+
+ /// AllocaInsertPoint - This is an instruction in the entry block before which
+ /// we prefer to insert allocas.
+ llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
+
+ bool CatchUndefined;
+
+ const CodeGen::CGBlockInfo *BlockInfo;
+ llvm::Value *BlockPointer;
+
+ /// \brief A mapping from NRVO variables to the flags used to indicate
+ /// when the NRVO has been applied to this variable.
+ llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags;
+
+ EHScopeStack EHStack;
+
+ /// i32s containing the indexes of the cleanup destinations.
+ llvm::AllocaInst *NormalCleanupDest;
+ llvm::AllocaInst *EHCleanupDest;
+
+ unsigned NextCleanupDestIndex;
+
+ /// The exception slot. All landing pads write the current
+ /// exception pointer into this alloca.
+ llvm::Value *ExceptionSlot;
+
+ /// Emits a landing pad for the current EH stack.
+ llvm::BasicBlock *EmitLandingPad();
+
+ llvm::BasicBlock *getInvokeDestImpl();
+
+ /// Set up the last cleaup that was pushed as a conditional
+ /// full-expression cleanup.
+ void initFullExprCleanup();
+
+ template <class T>
+ typename DominatingValue<T>::saved_type saveValueInCond(T value) {
+ return DominatingValue<T>::save(*this, value);
+ }
+
+public:
+ /// ObjCEHValueStack - Stack of Objective-C exception values, used for
+ /// rethrows.
+ llvm::SmallVector<llvm::Value*, 8> ObjCEHValueStack;
+
+ // A struct holding information about a finally block's IR
+ // generation. For now, doesn't actually hold anything.
+ struct FinallyInfo {
+ };
+
+ FinallyInfo EnterFinallyBlock(const Stmt *Stmt,
+ llvm::Constant *BeginCatchFn,
+ llvm::Constant *EndCatchFn,
+ llvm::Constant *RethrowFn);
+ void ExitFinallyBlock(FinallyInfo &FinallyInfo);
+
+ /// pushFullExprCleanup - Push a cleanup to be run at the end of the
+ /// current full-expression. Safe against the possibility that
+ /// we're currently inside a conditionally-evaluated expression.
+ template <class T, class A0>
+ void pushFullExprCleanup(CleanupKind kind, A0 a0) {
+ // If we're not in a conditional branch, or if none of the
+ // arguments requires saving, then use the unconditional cleanup.
+ if (!isInConditionalBranch()) {
+ typedef EHScopeStack::UnconditionalCleanup1<T, A0> CleanupType;
+ return EHStack.pushCleanup<CleanupType>(kind, a0);
+ }
+
+ typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
+
+ typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType;
+ EHStack.pushCleanup<CleanupType>(kind, a0_saved);
+ initFullExprCleanup();
+ }
+
+ /// pushFullExprCleanup - Push a cleanup to be run at the end of the
+ /// current full-expression. Safe against the possibility that
+ /// we're currently inside a conditionally-evaluated expression.
+ template <class T, class A0, class A1>
+ void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) {
+ // If we're not in a conditional branch, or if none of the
+ // arguments requires saving, then use the unconditional cleanup.
+ if (!isInConditionalBranch()) {
+ typedef EHScopeStack::UnconditionalCleanup2<T, A0, A1> CleanupType;
+ return EHStack.pushCleanup<CleanupType>(kind, a0, a1);
+ }
+
+ typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
+ typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
+
+ typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType;
+ EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved);
+ initFullExprCleanup();
+ }
+
+ /// PushDestructorCleanup - Push a cleanup to call the
+ /// complete-object destructor of an object of the given type at the
+ /// given address. Does nothing if T is not a C++ class type with a
+ /// non-trivial destructor.
+ void PushDestructorCleanup(QualType T, llvm::Value *Addr);
+
+ /// PushDestructorCleanup - Push a cleanup to call the
+ /// complete-object variant of the given destructor on the object at
+ /// the given address.
+ void PushDestructorCleanup(const CXXDestructorDecl *Dtor,
+ llvm::Value *Addr);
+
+ /// PopCleanupBlock - Will pop the cleanup entry on the stack and
+ /// process all branch fixups.
+ void PopCleanupBlock(bool FallThroughIsBranchThrough = false);
+
+ /// DeactivateCleanupBlock - Deactivates the given cleanup block.
+ /// The block cannot be reactivated. Pops it if it's the top of the
+ /// stack.
+ void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup);
+
+ /// ActivateCleanupBlock - Activates an initially-inactive cleanup.
+ /// Cannot be used to resurrect a deactivated cleanup.
+ void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup);
+
+ /// \brief Enters a new scope for capturing cleanups, all of which
+ /// will be executed once the scope is exited.
+ class RunCleanupsScope {
+ CodeGenFunction& CGF;
+ EHScopeStack::stable_iterator CleanupStackDepth;
+ bool OldDidCallStackSave;
+ bool PerformCleanup;
+
+ RunCleanupsScope(const RunCleanupsScope &); // DO NOT IMPLEMENT
+ RunCleanupsScope &operator=(const RunCleanupsScope &); // DO NOT IMPLEMENT
+
+ public:
+ /// \brief Enter a new cleanup scope.
+ explicit RunCleanupsScope(CodeGenFunction &CGF)
+ : CGF(CGF), PerformCleanup(true)
+ {
+ CleanupStackDepth = CGF.EHStack.stable_begin();
+ OldDidCallStackSave = CGF.DidCallStackSave;
+ CGF.DidCallStackSave = false;
+ }
+
+ /// \brief Exit this cleanup scope, emitting any accumulated
+ /// cleanups.
+ ~RunCleanupsScope() {
+ if (PerformCleanup) {
+ CGF.DidCallStackSave = OldDidCallStackSave;
+ CGF.PopCleanupBlocks(CleanupStackDepth);
+ }
+ }
+
+ /// \brief Determine whether this scope requires any cleanups.
+ bool requiresCleanups() const {
+ return CGF.EHStack.stable_begin() != CleanupStackDepth;
+ }
+
+ /// \brief Force the emission of cleanups now, instead of waiting
+ /// until this object is destroyed.
+ void ForceCleanup() {
+ assert(PerformCleanup && "Already forced cleanup");
+ CGF.DidCallStackSave = OldDidCallStackSave;
+ CGF.PopCleanupBlocks(CleanupStackDepth);
+ PerformCleanup = false;
+ }
+ };
+
+
+ /// PopCleanupBlocks - Takes the old cleanup stack size and emits
+ /// the cleanup blocks that have been added.
+ void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize);
+
+ void ResolveBranchFixups(llvm::BasicBlock *Target);
+
+ /// The given basic block lies in the current EH scope, but may be a
+ /// target of a potentially scope-crossing jump; get a stable handle
+ /// to which we can perform this jump later.
+ JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) {
+ return JumpDest(Target,
+ EHStack.getInnermostNormalCleanup(),
+ NextCleanupDestIndex++);
+ }
+
+ /// The given basic block lies in the current EH scope, but may be a
+ /// target of a potentially scope-crossing jump; get a stable handle
+ /// to which we can perform this jump later.
+ JumpDest getJumpDestInCurrentScope(llvm::StringRef Name = llvm::StringRef()) {
+ return getJumpDestInCurrentScope(createBasicBlock(Name));
+ }
+
+ /// EmitBranchThroughCleanup - Emit a branch from the current insert
+ /// block through the normal cleanup handling code (if any) and then
+ /// on to \arg Dest.
+ void EmitBranchThroughCleanup(JumpDest Dest);
+
+ /// EmitBranchThroughEHCleanup - Emit a branch from the current
+ /// insert block through the EH cleanup handling code (if any) and
+ /// then on to \arg Dest.
+ void EmitBranchThroughEHCleanup(UnwindDest Dest);
+
+ /// getRethrowDest - Returns the unified outermost-scope rethrow
+ /// destination.
+ UnwindDest getRethrowDest();
+
+ /// An object to manage conditionally-evaluated expressions.
+ class ConditionalEvaluation {
+ llvm::BasicBlock *StartBB;
+
+ public:
+ ConditionalEvaluation(CodeGenFunction &CGF)
+ : StartBB(CGF.Builder.GetInsertBlock()) {}
+
+ void begin(CodeGenFunction &CGF) {
+ assert(CGF.OutermostConditional != this);
+ if (!CGF.OutermostConditional)
+ CGF.OutermostConditional = this;
+ }
+
+ void end(CodeGenFunction &CGF) {
+ assert(CGF.OutermostConditional != 0);
+ if (CGF.OutermostConditional == this)
+ CGF.OutermostConditional = 0;
+ }
+
+ /// Returns a block which will be executed prior to each
+ /// evaluation of the conditional code.
+ llvm::BasicBlock *getStartingBlock() const {
+ return StartBB;
+ }
+ };
+
+ /// isInConditionalBranch - Return true if we're currently emitting
+ /// one branch or the other of a conditional expression.
+ bool isInConditionalBranch() const { return OutermostConditional != 0; }
+
+ /// An RAII object to record that we're evaluating a statement
+ /// expression.
+ class StmtExprEvaluation {
+ CodeGenFunction &CGF;
+
+ /// We have to save the outermost conditional: cleanups in a
+ /// statement expression aren't conditional just because the
+ /// StmtExpr is.
+ ConditionalEvaluation *SavedOutermostConditional;
+
+ public:
+ StmtExprEvaluation(CodeGenFunction &CGF)
+ : CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) {
+ CGF.OutermostConditional = 0;
+ }
+
+ ~StmtExprEvaluation() {
+ CGF.OutermostConditional = SavedOutermostConditional;
+ CGF.EnsureInsertPoint();
+ }
+ };
+
+ /// An object which temporarily prevents a value from being
+ /// destroyed by aggressive peephole optimizations that assume that
+ /// all uses of a value have been realized in the IR.
+ class PeepholeProtection {
+ llvm::Instruction *Inst;
+ friend class CodeGenFunction;
+
+ public:
+ PeepholeProtection() : Inst(0) {}
+ };
+
+ /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
+ class OpaqueValueMapping {
+ CodeGenFunction &CGF;
+ const OpaqueValueExpr *OpaqueValue;
+ bool BoundLValue;
+ CodeGenFunction::PeepholeProtection Protection;
+
+ public:
+ static bool shouldBindAsLValue(const Expr *expr) {
+ return expr->isGLValue() || expr->getType()->isRecordType();
+ }
+
+ /// Build the opaque value mapping for the given conditional
+ /// operator if it's the GNU ?: extension. This is a common
+ /// enough pattern that the convenience operator is really
+ /// helpful.
+ ///
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const AbstractConditionalOperator *op) : CGF(CGF) {
+ if (isa<ConditionalOperator>(op)) {
+ OpaqueValue = 0;
+ BoundLValue = false;
+ return;
+ }
+
+ const BinaryConditionalOperator *e = cast<BinaryConditionalOperator>(op);
+ init(e->getOpaqueValue(), e->getCommon());
+ }
+
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const OpaqueValueExpr *opaqueValue,
+ LValue lvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(true) {
+ assert(opaqueValue && "no opaque value expression!");
+ assert(shouldBindAsLValue(opaqueValue));
+ initLValue(lvalue);
+ }
+
+ OpaqueValueMapping(CodeGenFunction &CGF,
+ const OpaqueValueExpr *opaqueValue,
+ RValue rvalue)
+ : CGF(CGF), OpaqueValue(opaqueValue), BoundLValue(false) {
+ assert(opaqueValue && "no opaque value expression!");
+ assert(!shouldBindAsLValue(opaqueValue));
+ initRValue(rvalue);
+ }
+
+ void pop() {
+ assert(OpaqueValue && "mapping already popped!");
+ popImpl();
+ OpaqueValue = 0;
+ }
+
+ ~OpaqueValueMapping() {
+ if (OpaqueValue) popImpl();
+ }
+
+ private:
+ void popImpl() {
+ if (BoundLValue)
+ CGF.OpaqueLValues.erase(OpaqueValue);
+ else {
+ CGF.OpaqueRValues.erase(OpaqueValue);
+ CGF.unprotectFromPeepholes(Protection);
+ }
+ }
+
+ void init(const OpaqueValueExpr *ov, const Expr *e) {
+ OpaqueValue = ov;
+ BoundLValue = shouldBindAsLValue(ov);
+ assert(BoundLValue == shouldBindAsLValue(e)
+ && "inconsistent expression value kinds!");
+ if (BoundLValue)
+ initLValue(CGF.EmitLValue(e));
+ else
+ initRValue(CGF.EmitAnyExpr(e));
+ }
+
+ void initLValue(const LValue &lv) {
+ CGF.OpaqueLValues.insert(std::make_pair(OpaqueValue, lv));
+ }
+
+ void initRValue(const RValue &rv) {
+ // Work around an extremely aggressive peephole optimization in
+ // EmitScalarConversion which assumes that all other uses of a
+ // value are extant.
+ Protection = CGF.protectFromPeepholes(rv);
+ CGF.OpaqueRValues.insert(std::make_pair(OpaqueValue, rv));
+ }
+ };
+
+ /// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
+ /// number that holds the value.
+ unsigned getByRefValueLLVMField(const ValueDecl *VD) const;
+
+ /// BuildBlockByrefAddress - Computes address location of the
+ /// variable which is declared as __block.
+ llvm::Value *BuildBlockByrefAddress(llvm::Value *BaseAddr,
+ const VarDecl *V);
+private:
+ CGDebugInfo *DebugInfo;
+
+ /// IndirectBranch - The first time an indirect goto is seen we create a block
+ /// with an indirect branch. Every time we see the address of a label taken,
+ /// we add the label to the indirect goto. Every subsequent indirect goto is
+ /// codegen'd as a jump to the IndirectBranch's basic block.
+ llvm::IndirectBrInst *IndirectBranch;
+
+ /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
+ /// decls.
+ typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
+ DeclMapTy LocalDeclMap;
+
+ /// LabelMap - This keeps track of the LLVM basic block for each C label.
+ llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
+
+ // BreakContinueStack - This keeps track of where break and continue
+ // statements should jump to.
+ struct BreakContinue {
+ BreakContinue(JumpDest Break, JumpDest Continue)
+ : BreakBlock(Break), ContinueBlock(Continue) {}
+
+ JumpDest BreakBlock;
+ JumpDest ContinueBlock;
+ };
+ llvm::SmallVector<BreakContinue, 8> BreakContinueStack;
+
+ /// SwitchInsn - This is nearest current switch instruction. It is null if if
+ /// current context is not in a switch.
+ llvm::SwitchInst *SwitchInsn;
+
+ /// CaseRangeBlock - This block holds if condition check for last case
+ /// statement range in current switch instruction.
+ llvm::BasicBlock *CaseRangeBlock;
+
+ /// OpaqueLValues - Keeps track of the current set of opaque value
+ /// expressions.
+ llvm::DenseMap<const OpaqueValueExpr *, LValue> OpaqueLValues;
+ llvm::DenseMap<const OpaqueValueExpr *, RValue> OpaqueRValues;
+
+ // VLASizeMap - This keeps track of the associated size for each VLA type.
+ // We track this by the size expression rather than the type itself because
+ // in certain situations, like a const qualifier applied to an VLA typedef,
+ // multiple VLA types can share the same size expression.
+ // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
+ // enter/leave scopes.
+ llvm::DenseMap<const Expr*, llvm::Value*> VLASizeMap;
+
+ /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
+ /// calling llvm.stacksave for multiple VLAs in the same scope.
+ bool DidCallStackSave;
+
+ /// A block containing a single 'unreachable' instruction. Created
+ /// lazily by getUnreachableBlock().
+ llvm::BasicBlock *UnreachableBlock;
+
+ /// CXXThisDecl - When generating code for a C++ member function,
+ /// this will hold the implicit 'this' declaration.
+ ImplicitParamDecl *CXXThisDecl;
+ llvm::Value *CXXThisValue;
+
+ /// CXXVTTDecl - When generating code for a base object constructor or
+ /// base object destructor with virtual bases, this will hold the implicit
+ /// VTT parameter.
+ ImplicitParamDecl *CXXVTTDecl;
+ llvm::Value *CXXVTTValue;
+
+ /// OutermostConditional - Points to the outermost active
+ /// conditional control. This is used so that we know if a
+ /// temporary should be destroyed conditionally.
+ ConditionalEvaluation *OutermostConditional;
+
+
+ /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM
+ /// type as well as the field number that contains the actual data.
+ llvm::DenseMap<const ValueDecl *, std::pair<const llvm::Type *,
+ unsigned> > ByRefValueInfo;
+
+ llvm::BasicBlock *TerminateLandingPad;
+ llvm::BasicBlock *TerminateHandler;
+ llvm::BasicBlock *TrapBB;
+
+public:
+ CodeGenFunction(CodeGenModule &cgm);
+
+ CodeGenTypes &getTypes() const { return CGM.getTypes(); }
+ ASTContext &getContext() const;
+ CGDebugInfo *getDebugInfo() { return DebugInfo; }
+
+ const LangOptions &getLangOptions() const { return CGM.getLangOptions(); }
+
+ /// Returns a pointer to the function's exception object slot, which
+ /// is assigned in every landing pad.
+ llvm::Value *getExceptionSlot();
+
+ llvm::Value *getNormalCleanupDestSlot();
+ llvm::Value *getEHCleanupDestSlot();
+
+ llvm::BasicBlock *getUnreachableBlock() {
+ if (!UnreachableBlock) {
+ UnreachableBlock = createBasicBlock("unreachable");
+ new llvm::UnreachableInst(getLLVMContext(), UnreachableBlock);
+ }
+ return UnreachableBlock;
+ }
+
+ llvm::BasicBlock *getInvokeDest() {
+ if (!EHStack.requiresLandingPad()) return 0;
+ return getInvokeDestImpl();
+ }
+
+ llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); }
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C
+ //===--------------------------------------------------------------------===//
+
+ void GenerateObjCMethod(const ObjCMethodDecl *OMD);
+
+ void StartObjCMethod(const ObjCMethodDecl *MD,
+ const ObjCContainerDecl *CD);
+
+ /// GenerateObjCGetter - Synthesize an Objective-C property getter function.
+ void GenerateObjCGetter(ObjCImplementationDecl *IMP,
+ const ObjCPropertyImplDecl *PID);
+ void GenerateObjCGetterBody(ObjCIvarDecl *Ivar, bool IsAtomic, bool IsStrong);
+ void GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD,
+ ObjCIvarDecl *Ivar);
+
+ void GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
+ ObjCMethodDecl *MD, bool ctor);
+
+ /// GenerateObjCSetter - Synthesize an Objective-C property setter function
+ /// for the given property.
+ void GenerateObjCSetter(ObjCImplementationDecl *IMP,
+ const ObjCPropertyImplDecl *PID);
+ bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
+ bool IvarTypeWithAggrGCObjects(QualType Ty);
+
+ //===--------------------------------------------------------------------===//
+ // Block Bits
+ //===--------------------------------------------------------------------===//
+
+ llvm::Value *EmitBlockLiteral(const BlockExpr *);
+ llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
+ const CGBlockInfo &Info,
+ const llvm::StructType *,
+ llvm::Constant *BlockVarLayout);
+
+ llvm::Function *GenerateBlockFunction(GlobalDecl GD,
+ const CGBlockInfo &Info,
+ const Decl *OuterFuncDecl,
+ const DeclMapTy &ldm);
+
+ llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
+ llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
+
+ llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *,
+ BlockFieldFlags flags,
+ const VarDecl *BD);
+ llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
+ BlockFieldFlags flags,
+ const VarDecl *BD);
+
+ void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);
+
+ llvm::Value *LoadBlockStruct() {
+ assert(BlockPointer && "no block pointer set!");
+ return BlockPointer;
+ }
+
+ void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
+ void AllocateBlockDecl(const BlockDeclRefExpr *E);
+ llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+ return GetAddrOfBlockDecl(E->getDecl(), E->isByRef());
+ }
+ llvm::Value *GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
+ const llvm::Type *BuildByRefType(const VarDecl *var);
+
+ void GenerateCode(GlobalDecl GD, llvm::Function *Fn);
+ void StartFunction(GlobalDecl GD, QualType RetTy,
+ llvm::Function *Fn,
+ const FunctionArgList &Args,
+ SourceLocation StartLoc);
+
+ void EmitConstructorBody(FunctionArgList &Args);
+ void EmitDestructorBody(FunctionArgList &Args);
+ void EmitFunctionBody(FunctionArgList &Args);
+
+ /// EmitReturnBlock - Emit the unified return block, trying to avoid its
+ /// emission when possible.
+ void EmitReturnBlock();
+
+ /// FinishFunction - Complete IR generation of the current function. It is
+ /// legal to call this function even if there is no current insertion point.
+ void FinishFunction(SourceLocation EndLoc=SourceLocation());
+
+ /// GenerateThunk - Generate a thunk for the given method.
+ void GenerateThunk(llvm::Function *Fn, GlobalDecl GD, const ThunkInfo &Thunk);
+
+ void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
+ FunctionArgList &Args);
+
+ /// InitializeVTablePointer - Initialize the vtable pointer of the given
+ /// subobject.
+ ///
+ void InitializeVTablePointer(BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass);
+
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+ void InitializeVTablePointers(BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
+ bool BaseIsNonVirtualPrimaryBase,
+ llvm::Constant *VTable,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy& VBases);
+
+ void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
+
+ /// GetVTablePtr - Return the Value of the vtable pointer member pointed
+ /// to by This.
+ llvm::Value *GetVTablePtr(llvm::Value *This, const llvm::Type *Ty);
+
+ /// EnterDtorCleanups - Enter the cleanups necessary to complete the
+ /// given phase of destruction for a destructor. The end result
+ /// should call destructors on members and base classes in reverse
+ /// order of their construction.
+ void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type);
+
+ /// ShouldInstrumentFunction - Return true if the current function should be
+ /// instrumented with __cyg_profile_func_* calls
+ bool ShouldInstrumentFunction();
+
+ /// EmitFunctionInstrumentation - Emit LLVM code to call the specified
+ /// instrumentation function with the current function and the call site, if
+ /// function instrumentation is enabled.
+ void EmitFunctionInstrumentation(const char *Fn);
+
+ /// EmitMCountInstrumentation - Emit call to .mcount.
+ void EmitMCountInstrumentation();
+
+ /// EmitFunctionProlog - Emit the target specific LLVM code to load the
+ /// arguments for the given function. This is also responsible for naming the
+ /// LLVM function arguments.
+ void EmitFunctionProlog(const CGFunctionInfo &FI,
+ llvm::Function *Fn,
+ const FunctionArgList &Args);
+
+ /// EmitFunctionEpilog - Emit the target specific LLVM code to return the
+ /// given temporary.
+ void EmitFunctionEpilog(const CGFunctionInfo &FI);
+
+ /// EmitStartEHSpec - Emit the start of the exception spec.
+ void EmitStartEHSpec(const Decl *D);
+
+ /// EmitEndEHSpec - Emit the end of the exception spec.
+ void EmitEndEHSpec(const Decl *D);
+
+ /// getTerminateLandingPad - Return a landing pad that just calls terminate.
+ llvm::BasicBlock *getTerminateLandingPad();
+
+ /// getTerminateHandler - Return a handler (not a landing pad, just
+ /// a catch handler) that just calls terminate. This is used when
+ /// a terminate scope encloses a try.
+ llvm::BasicBlock *getTerminateHandler();
+
+ const llvm::Type *ConvertTypeForMem(QualType T);
+ const llvm::Type *ConvertType(QualType T);
+ const llvm::Type *ConvertType(const TypeDecl *T) {
+ return ConvertType(getContext().getTypeDeclType(T));
+ }
+
+ /// LoadObjCSelf - Load the value of self. This function is only valid while
+ /// generating code for an Objective-C method.
+ llvm::Value *LoadObjCSelf();
+
+ /// TypeOfSelfObject - Return type of object that this self represents.
+ QualType TypeOfSelfObject();
+
+ /// hasAggregateLLVMType - Return true if the specified AST type will map into
+ /// an aggregate LLVM type or is void.
+ static bool hasAggregateLLVMType(QualType T);
+
+ /// createBasicBlock - Create an LLVM basic block.
+ llvm::BasicBlock *createBasicBlock(llvm::StringRef name = "",
+ llvm::Function *parent = 0,
+ llvm::BasicBlock *before = 0) {
+#ifdef NDEBUG
+ return llvm::BasicBlock::Create(getLLVMContext(), "", parent, before);
+#else
+ return llvm::BasicBlock::Create(getLLVMContext(), name, parent, before);
+#endif
+ }
+
+ /// getBasicBlockForLabel - Return the LLVM basicblock that the specified
+ /// label maps to.
+ JumpDest getJumpDestForLabel(const LabelDecl *S);
+
+ /// SimplifyForwardingBlocks - If the given basic block is only a branch to
+ /// another basic block, simplify it. This assumes that no other code could
+ /// potentially reference the basic block.
+ void SimplifyForwardingBlocks(llvm::BasicBlock *BB);
+
+ /// EmitBlock - Emit the given block \arg BB and set it as the insert point,
+ /// adding a fall-through branch from the current insert block if
+ /// necessary. It is legal to call this function even if there is no current
+ /// insertion point.
+ ///
+ /// IsFinished - If true, indicates that the caller has finished emitting
+ /// branches to the given block and does not expect to emit code into it. This
+ /// means the block can be ignored if it is unreachable.
+ void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false);
+
+ /// EmitBranch - Emit a branch to the specified basic block from the current
+ /// insert block, taking care to avoid creation of branches from dummy
+ /// blocks. It is legal to call this function even if there is no current
+ /// insertion point.
+ ///
+ /// This function clears the current insertion point. The caller should follow
+ /// calls to this function with calls to Emit*Block prior to generation new
+ /// code.
+ void EmitBranch(llvm::BasicBlock *Block);
+
+ /// HaveInsertPoint - True if an insertion point is defined. If not, this
+ /// indicates that the current code being emitted is unreachable.
+ bool HaveInsertPoint() const {
+ return Builder.GetInsertBlock() != 0;
+ }
+
+ /// EnsureInsertPoint - Ensure that an insertion point is defined so that
+ /// emitted IR has a place to go. Note that by definition, if this function
+ /// creates a block then that block is unreachable; callers may do better to
+ /// detect when no insertion point is defined and simply skip IR generation.
+ void EnsureInsertPoint() {
+ if (!HaveInsertPoint())
+ EmitBlock(createBasicBlock());
+ }
+
+ /// ErrorUnsupported - Print out an error that codegen doesn't support the
+ /// specified stmt yet.
+ void ErrorUnsupported(const Stmt *S, const char *Type,
+ bool OmitOnError=false);
+
+ //===--------------------------------------------------------------------===//
+ // Helpers
+ //===--------------------------------------------------------------------===//
+
+ LValue MakeAddrLValue(llvm::Value *V, QualType T, unsigned Alignment = 0) {
+ return LValue::MakeAddr(V, T, Alignment, getContext(),
+ CGM.getTBAAInfo(T));
+ }
+
+ /// CreateTempAlloca - This creates a alloca and inserts it into the entry
+ /// block. The caller is responsible for setting an appropriate alignment on
+ /// the alloca.
+ llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
+ const llvm::Twine &Name = "tmp");
+
+ /// InitTempAlloca - Provide an initial value for the given alloca.
+ void InitTempAlloca(llvm::AllocaInst *Alloca, llvm::Value *Value);
+
+ /// CreateIRTemp - Create a temporary IR object of the given type, with
+ /// appropriate alignment. This routine should only be used when an temporary
+ /// value needs to be stored into an alloca (for example, to avoid explicit
+ /// PHI construction), but the type is the IR type, not the type appropriate
+ /// for storing in memory.
+ llvm::AllocaInst *CreateIRTemp(QualType T, const llvm::Twine &Name = "tmp");
+
+ /// CreateMemTemp - Create a temporary memory object of the given type, with
+ /// appropriate alignment.
+ llvm::AllocaInst *CreateMemTemp(QualType T, const llvm::Twine &Name = "tmp");
+
+ /// CreateAggTemp - Create a temporary memory object for the given
+ /// aggregate type.
+ AggValueSlot CreateAggTemp(QualType T, const llvm::Twine &Name = "tmp") {
+ return AggValueSlot::forAddr(CreateMemTemp(T, Name), false, false);
+ }
+
+ /// Emit a cast to void* in the appropriate address space.
+ llvm::Value *EmitCastToVoidPtr(llvm::Value *value);
+
+ /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+ /// expression and compare the result against zero, returning an Int1Ty value.
+ llvm::Value *EvaluateExprAsBool(const Expr *E);
+
+ /// EmitIgnoredExpr - Emit an expression in a context which ignores the result.
+ void EmitIgnoredExpr(const Expr *E);
+
+ /// EmitAnyExpr - Emit code to compute the specified expression which can have
+ /// any type. The result is returned as an RValue struct. If this is an
+ /// aggregate expression, the aggloc/agglocvolatile arguments indicate where
+ /// the result should be returned.
+ ///
+ /// \param IgnoreResult - True if the resulting value isn't used.
+ RValue EmitAnyExpr(const Expr *E,
+ AggValueSlot AggSlot = AggValueSlot::ignored(),
+ bool IgnoreResult = false);
+
+ // EmitVAListRef - Emit a "reference" to a va_list; this is either the address
+ // or the value of the expression, depending on how va_list is defined.
+ llvm::Value *EmitVAListRef(const Expr *E);
+
+ /// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
+ /// always be accessible even if no aggregate location is provided.
+ RValue EmitAnyExprToTemp(const Expr *E);
+
+ /// EmitsAnyExprToMem - Emits the code necessary to evaluate an
+ /// arbitrary expression into the given memory location.
+ void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
+ bool IsLocationVolatile,
+ bool IsInitializer);
+
+ /// EmitAggregateCopy - Emit an aggrate copy.
+ ///
+ /// \param isVolatile - True iff either the source or the destination is
+ /// volatile.
+ void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ QualType EltTy, bool isVolatile=false);
+
+ /// StartBlock - Start new block named N. If insert block is a dummy block
+ /// then reuse it.
+ void StartBlock(const char *N);
+
+ /// GetAddrOfStaticLocalVar - Return the address of a static local variable.
+ llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD) {
+ return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
+ }
+
+ /// GetAddrOfLocalVar - Return the address of a local variable.
+ llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
+ llvm::Value *Res = LocalDeclMap[VD];
+ assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
+ return Res;
+ }
+
+ /// getOpaqueLValueMapping - Given an opaque value expression (which
+ /// must be mapped to an l-value), return its mapping.
+ const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+ assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
+ return it->second;
+ }
+
+ /// getOpaqueRValueMapping - Given an opaque value expression (which
+ /// must be mapped to an r-value), return its mapping.
+ const RValue &getOpaqueRValueMapping(const OpaqueValueExpr *e) {
+ assert(!OpaqueValueMapping::shouldBindAsLValue(e));
+
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
+ assert(it != OpaqueRValues.end() && "no mapping for opaque value!");
+ return it->second;
+ }
+
+ /// getAccessedFieldNo - Given an encoded value and a result number, return
+ /// the input field number being accessed.
+ static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
+
+ llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L);
+ llvm::BasicBlock *GetIndirectGotoBlock();
+
+ /// EmitNullInitialization - Generate code to set a value of the given type to
+ /// null, If the type contains data member pointers, they will be initialized
+ /// to -1 in accordance with the Itanium C++ ABI.
+ void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty);
+
+ // EmitVAArg - Generate code to get an argument from the passed in pointer
+ // and update it accordingly. The return value is a pointer to the argument.
+ // FIXME: We should be able to get rid of this method and use the va_arg
+ // instruction in LLVM instead once it works well enough.
+ llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
+
+ /// EmitVLASize - Generate code for any VLA size expressions that might occur
+ /// in a variably modified type. If Ty is a VLA, will return the value that
+ /// corresponds to the size in bytes of the VLA type. Will return 0 otherwise.
+ ///
+ /// This function can be called with a null (unreachable) insert point.
+ llvm::Value *EmitVLASize(QualType Ty);
+
+ // GetVLASize - Returns an LLVM value that corresponds to the size in bytes
+ // of a variable length array type.
+ llvm::Value *GetVLASize(const VariableArrayType *);
+
+ /// LoadCXXThis - Load the value of 'this'. This function is only valid while
+ /// generating code for an C++ member function.
+ llvm::Value *LoadCXXThis() {
+ assert(CXXThisValue && "no 'this' value for this function");
+ return CXXThisValue;
+ }
+
+ /// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
+ /// virtual bases.
+ llvm::Value *LoadCXXVTT() {
+ assert(CXXVTTValue && "no VTT value for this function");
+ return CXXVTTValue;
+ }
+
+ /// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
+ /// complete class to the given direct base.
+ llvm::Value *
+ GetAddressOfDirectBaseInCompleteClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ const CXXRecordDecl *Base,
+ bool BaseIsVirtual);
+
+ /// GetAddressOfBaseClass - This function will add the necessary delta to the
+ /// load of 'this' and returns address of the base class.
+ llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue);
+
+ llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue);
+
+ llvm::Value *GetVirtualBaseClassOffset(llvm::Value *This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl);
+
+ void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
+ CXXCtorType CtorType,
+ const FunctionArgList &Args);
+ void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
+ bool ForVirtualBase, llvm::Value *This,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd);
+
+ void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
+ llvm::Value *This, llvm::Value *Src,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd);
+
+ void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+ const ConstantArrayType *ArrayTy,
+ llvm::Value *ArrayPtr,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization = false);
+
+ void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
+ llvm::Value *NumElements,
+ llvm::Value *ArrayPtr,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization = false);
+
+ void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This);
+
+ void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
+ llvm::Value *NumElements,
+ llvm::Value *This);
+
+ llvm::Function *GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
+ const ArrayType *Array,
+ llvm::Value *This);
+
+ void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
+ bool ForVirtualBase, llvm::Value *This);
+
+ void EmitNewArrayInitializer(const CXXNewExpr *E, llvm::Value *NewPtr,
+ llvm::Value *NumElements);
+
+ void EmitCXXTemporary(const CXXTemporary *Temporary, llvm::Value *Ptr);
+
+ llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
+ void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
+
+ void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
+ QualType DeleteTy);
+
+ llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
+ llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
+
+ void EmitCheck(llvm::Value *, unsigned Size);
+
+ llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre);
+ ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre);
+ //===--------------------------------------------------------------------===//
+ // Declaration Emission
+ //===--------------------------------------------------------------------===//
+
+ /// EmitDecl - Emit a declaration.
+ ///
+ /// This function can be called with a null (unreachable) insert point.
+ void EmitDecl(const Decl &D);
+
+ /// EmitVarDecl - Emit a local variable declaration.
+ ///
+ /// This function can be called with a null (unreachable) insert point.
+ void EmitVarDecl(const VarDecl &D);
+
+ typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
+ llvm::Value *Address);
+
+ /// EmitAutoVarDecl - Emit an auto variable declaration.
+ ///
+ /// This function can be called with a null (unreachable) insert point.
+ void EmitAutoVarDecl(const VarDecl &D, SpecialInitFn *SpecialInit = 0);
+
+ void EmitStaticVarDecl(const VarDecl &D,
+ llvm::GlobalValue::LinkageTypes Linkage);
+
+ /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
+ void EmitParmDecl(const VarDecl &D, llvm::Value *Arg);
+
+ /// protectFromPeepholes - Protect a value that we're intending to
+ /// store to the side, but which will probably be used later, from
+ /// aggressive peepholing optimizations that might delete it.
+ ///
+ /// Pass the result to unprotectFromPeepholes to declare that
+ /// protection is no longer required.
+ ///
+ /// There's no particular reason why this shouldn't apply to
+ /// l-values, it's just that no existing peepholes work on pointers.
+ PeepholeProtection protectFromPeepholes(RValue rvalue);
+ void unprotectFromPeepholes(PeepholeProtection protection);
+
+ //===--------------------------------------------------------------------===//
+ // Statement Emission
+ //===--------------------------------------------------------------------===//
+
+ /// EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
+ void EmitStopPoint(const Stmt *S);
+
+ /// EmitStmt - Emit the code for the statement \arg S. It is legal to call
+ /// this function even if there is no current insertion point.
+ ///
+ /// This function may clear the current insertion point; callers should use
+ /// EnsureInsertPoint if they wish to subsequently generate code without first
+ /// calling EmitBlock, EmitBranch, or EmitStmt.
+ void EmitStmt(const Stmt *S);
+
+ /// EmitSimpleStmt - Try to emit a "simple" statement which does not
+ /// necessarily require an insertion point or debug information; typically
+ /// because the statement amounts to a jump or a container of other
+ /// statements.
+ ///
+ /// \return True if the statement was handled.
+ bool EmitSimpleStmt(const Stmt *S);
+
+ RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+ AggValueSlot AVS = AggValueSlot::ignored());
+
+ /// EmitLabel - Emit the block for the given label. It is legal to call this
+ /// function even if there is no current insertion point.
+ void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.
+
+ void EmitLabelStmt(const LabelStmt &S);
+ void EmitGotoStmt(const GotoStmt &S);
+ void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
+ void EmitIfStmt(const IfStmt &S);
+ void EmitWhileStmt(const WhileStmt &S);
+ void EmitDoStmt(const DoStmt &S);
+ void EmitForStmt(const ForStmt &S);
+ void EmitReturnStmt(const ReturnStmt &S);
+ void EmitDeclStmt(const DeclStmt &S);
+ void EmitBreakStmt(const BreakStmt &S);
+ void EmitContinueStmt(const ContinueStmt &S);
+ void EmitSwitchStmt(const SwitchStmt &S);
+ void EmitDefaultStmt(const DefaultStmt &S);
+ void EmitCaseStmt(const CaseStmt &S);
+ void EmitCaseStmtRange(const CaseStmt &S);
+ void EmitAsmStmt(const AsmStmt &S);
+
+ void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
+ void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
+ void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
+ void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
+
+ llvm::Constant *getUnwindResumeOrRethrowFn();
+ void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
+ void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
+
+ void EmitCXXTryStmt(const CXXTryStmt &S);
+
+ //===--------------------------------------------------------------------===//
+ // LValue Expression Emission
+ //===--------------------------------------------------------------------===//
+
+ /// GetUndefRValue - Get an appropriate 'undef' rvalue for the given type.
+ RValue GetUndefRValue(QualType Ty);
+
+ /// EmitUnsupportedRValue - Emit a dummy r-value using the type of E
+ /// and issue an ErrorUnsupported style diagnostic (using the
+ /// provided Name).
+ RValue EmitUnsupportedRValue(const Expr *E,
+ const char *Name);
+
+ /// EmitUnsupportedLValue - Emit a dummy l-value using the type of E and issue
+ /// an ErrorUnsupported style diagnostic (using the provided Name).
+ LValue EmitUnsupportedLValue(const Expr *E,
+ const char *Name);
+
+ /// EmitLValue - Emit code to compute a designator that specifies the location
+ /// of the expression.
+ ///
+ /// This can return one of two things: a simple address or a bitfield
+ /// reference. In either case, the LLVM Value* in the LValue structure is
+ /// guaranteed to be an LLVM pointer type.
+ ///
+ /// If this returns a bitfield reference, nothing about the pointee type of
+ /// the LLVM value is known: For example, it may not be a pointer to an
+ /// integer.
+ ///
+ /// If this returns a normal address, and if the lvalue's C type is fixed
+ /// size, this method guarantees that the returned pointer type will point to
+ /// an LLVM type of the same size of the lvalue's type. If the lvalue has a
+ /// variable length type, this is not possible.
+ ///
+ LValue EmitLValue(const Expr *E);
+
+ /// EmitCheckedLValue - Same as EmitLValue but additionally we generate
+ /// checking code to guard against undefined behavior. This is only
+ /// suitable when we know that the address will be used to access the
+ /// object.
+ LValue EmitCheckedLValue(const Expr *E);
+
+ /// EmitToMemory - Change a scalar value from its value
+ /// representation to its in-memory representation.
+ llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty);
+
+ /// EmitFromMemory - Change a scalar value from its memory
+ /// representation to its value representation.
+ llvm::Value *EmitFromMemory(llvm::Value *Value, QualType Ty);
+
+ /// EmitLoadOfScalar - Load a scalar value from an address, taking
+ /// care to appropriately convert from the memory representation to
+ /// the LLVM value representation.
+ llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
+ unsigned Alignment, QualType Ty,
+ llvm::MDNode *TBAAInfo = 0);
+
+ /// EmitStoreOfScalar - Store a scalar value to an address, taking
+ /// care to appropriately convert from the memory representation to
+ /// the LLVM value representation.
+ void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
+ bool Volatile, unsigned Alignment, QualType Ty,
+ llvm::MDNode *TBAAInfo = 0);
+
+ /// EmitLoadOfLValue - Given an expression that represents a value lvalue,
+ /// this method emits the address of the lvalue, then loads the result as an
+ /// rvalue, returning the rvalue.
+ RValue EmitLoadOfLValue(LValue V, QualType LVType);
+ RValue EmitLoadOfExtVectorElementLValue(LValue V, QualType LVType);
+ RValue EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType);
+ RValue EmitLoadOfPropertyRefLValue(LValue LV,
+ ReturnValueSlot Return = ReturnValueSlot());
+
+ /// EmitStoreThroughLValue - Store the specified rvalue into the specified
+ /// lvalue, where both are guaranteed to the have the same type, and that type
+ /// is 'Ty'.
+ void EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty);
+ void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst,
+ QualType Ty);
+ void EmitStoreThroughPropertyRefLValue(RValue Src, LValue Dst);
+
+ /// EmitStoreThroughLValue - Store Src into Dst with same constraints as
+ /// EmitStoreThroughLValue.
+ ///
+ /// \param Result [out] - If non-null, this will be set to a Value* for the
+ /// bit-field contents after the store, appropriate for use as the result of
+ /// an assignment to the bit-field.
+ void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, QualType Ty,
+ llvm::Value **Result=0);
+
+ /// Emit an l-value for an assignment (simple or compound) of complex type.
+ LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
+ LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
+
+ // Note: only availabe for agg return types
+ LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
+ LValue EmitCompoundAssignmentLValue(const CompoundAssignOperator *E);
+ // Note: only available for agg return types
+ LValue EmitCallExprLValue(const CallExpr *E);
+ // Note: only available for agg return types
+ LValue EmitVAArgExprLValue(const VAArgExpr *E);
+ LValue EmitDeclRefLValue(const DeclRefExpr *E);
+ LValue EmitStringLiteralLValue(const StringLiteral *E);
+ LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
+ LValue EmitPredefinedLValue(const PredefinedExpr *E);
+ LValue EmitUnaryOpLValue(const UnaryOperator *E);
+ LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E);
+ LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E);
+ LValue EmitMemberExpr(const MemberExpr *E);
+ LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
+ LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
+ LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
+ LValue EmitCastLValue(const CastExpr *E);
+ LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);
+ LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
+
+ llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
+ const ObjCIvarDecl *Ivar);
+ LValue EmitLValueForAnonRecordField(llvm::Value* Base,
+ const IndirectFieldDecl* Field,
+ unsigned CVRQualifiers);
+ LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
+ unsigned CVRQualifiers);
+
+ /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
+ /// if the Field is a reference, this will return the address of the reference
+ /// and not the address of the value stored in the reference.
+ LValue EmitLValueForFieldInitialization(llvm::Value* Base,
+ const FieldDecl* Field,
+ unsigned CVRQualifiers);
+
+ LValue EmitLValueForIvar(QualType ObjectTy,
+ llvm::Value* Base, const ObjCIvarDecl *Ivar,
+ unsigned CVRQualifiers);
+
+ LValue EmitLValueForBitfield(llvm::Value* Base, const FieldDecl* Field,
+ unsigned CVRQualifiers);
+
+ LValue EmitBlockDeclRefLValue(const BlockDeclRefExpr *E);
+
+ LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
+ LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
+ LValue EmitExprWithCleanupsLValue(const ExprWithCleanups *E);
+ LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
+
+ LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E);
+ LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E);
+ LValue EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E);
+ LValue EmitStmtExprLValue(const StmtExpr *E);
+ LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
+ LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
+ void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
+
+ //===--------------------------------------------------------------------===//
+ // Scalar Expression Emission
+ //===--------------------------------------------------------------------===//
+
+ /// EmitCall - Generate a call of the given function, expecting the given
+ /// result type, and using the given argument list which specifies both the
+ /// LLVM arguments and the types they were derived from.
+ ///
+ /// \param TargetDecl - If given, the decl of the function in a direct call;
+ /// used to set attributes on the call (noreturn, etc.).
+ RValue EmitCall(const CGFunctionInfo &FnInfo,
+ llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ const CallArgList &Args,
+ const Decl *TargetDecl = 0,
+ llvm::Instruction **callOrInvoke = 0);
+
+ RValue EmitCall(QualType FnType, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ const Decl *TargetDecl = 0);
+ RValue EmitCallExpr(const CallExpr *E,
+ ReturnValueSlot ReturnValue = ReturnValueSlot());
+
+ llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
+ llvm::Value * const *ArgBegin,
+ llvm::Value * const *ArgEnd,
+ const llvm::Twine &Name = "");
+
+ llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
+ const llvm::Type *Ty);
+ llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
+ llvm::Value *This, const llvm::Type *Ty);
+ llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ NestedNameSpecifier *Qual,
+ const llvm::Type *Ty);
+
+ llvm::Value *BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const CXXRecordDecl *RD);
+
+ RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
+ llvm::Value *Callee,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This,
+ llvm::Value *VTT,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd);
+ RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
+ ReturnValueSlot ReturnValue);
+ RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
+ ReturnValueSlot ReturnValue);
+
+ RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
+ const CXXMethodDecl *MD,
+ ReturnValueSlot ReturnValue);
+
+
+ RValue EmitBuiltinExpr(const FunctionDecl *FD,
+ unsigned BuiltinID, const CallExpr *E);
+
+ RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
+
+ /// EmitTargetBuiltinExpr - Emit the given builtin call. Returns 0 if the call
+ /// is unhandled by the current target.
+ llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+
+ llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitNeonCall(llvm::Function *F,
+ llvm::SmallVectorImpl<llvm::Value*> &O,
+ const char *name,
+ unsigned shift = 0, bool rightshift = false);
+ llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx);
+ llvm::Value *EmitNeonShiftVector(llvm::Value *V, const llvm::Type *Ty,
+ bool negateForRightShift);
+
+ llvm::Value *BuildVector(const llvm::SmallVectorImpl<llvm::Value*> &Ops);
+ llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+
+ llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
+ llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
+ llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E);
+ RValue EmitObjCMessageExpr(const ObjCMessageExpr *E,
+ ReturnValueSlot Return = ReturnValueSlot());
+
+ /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in
+ /// expression. Will emit a temporary variable if E is not an LValue.
+ RValue EmitReferenceBindingToExpr(const Expr* E,
+ const NamedDecl *InitializedDecl);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Emission
+ //===--------------------------------------------------------------------===//
+
+ // Expressions are broken into three classes: scalar, complex, aggregate.
+
+ /// EmitScalarExpr - Emit the computation of the specified expression of LLVM
+ /// scalar type, returning the result.
+ llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false);
+
+ /// EmitScalarConversion - Emit a conversion from the specified type to the
+ /// specified destination type, both of which are LLVM scalar types.
+ llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy,
+ QualType DstTy);
+
+ /// EmitComplexToScalarConversion - Emit a conversion from the specified
+ /// complex type to the specified destination type, where the destination type
+ /// is an LLVM scalar type.
+ llvm::Value *EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy,
+ QualType DstTy);
+
+
+ /// EmitAggExpr - Emit the computation of the specified expression
+ /// of aggregate type. The result is computed into the given slot,
+ /// which may be null to indicate that the value is not needed.
+ void EmitAggExpr(const Expr *E, AggValueSlot AS, bool IgnoreResult = false);
+
+ /// EmitAggExprToLValue - Emit the computation of the specified expression of
+ /// aggregate type into a temporary LValue.
+ LValue EmitAggExprToLValue(const Expr *E);
+
+ /// EmitGCMemmoveCollectable - Emit special API for structs with object
+ /// pointers.
+ void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ QualType Ty);
+
+ /// EmitComplexExpr - Emit the computation of the specified expression of
+ /// complex type, returning the result.
+ ComplexPairTy EmitComplexExpr(const Expr *E,
+ bool IgnoreReal = false,
+ bool IgnoreImag = false);
+
+ /// EmitComplexExprIntoAddr - Emit the computation of the specified expression
+ /// of complex type, storing into the specified Value*.
+ void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
+ bool DestIsVolatile);
+
+ /// StoreComplexToAddr - Store a complex number into the specified address.
+ void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
+ bool DestIsVolatile);
+ /// LoadComplexFromAddr - Load a complex number from the specified address.
+ ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
+
+ /// CreateStaticVarDecl - Create a zero-initialized LLVM global for
+ /// a static local variable.
+ llvm::GlobalVariable *CreateStaticVarDecl(const VarDecl &D,
+ const char *Separator,
+ llvm::GlobalValue::LinkageTypes Linkage);
+
+ /// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the
+ /// global variable that has already been created for it. If the initializer
+ /// has a different type than GV does, this may free GV and return a different
+ /// one. Otherwise it just returns GV.
+ llvm::GlobalVariable *
+ AddInitializerToStaticVarDecl(const VarDecl &D,
+ llvm::GlobalVariable *GV);
+
+
+ /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
+ /// variable with global storage.
+ void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr);
+
+ /// EmitCXXGlobalDtorRegistration - Emits a call to register the global ptr
+ /// with the C++ runtime so that its destructor will be called at exit.
+ void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
+ llvm::Constant *DeclPtr);
+
+ /// Emit code in this function to perform a guarded variable
+ /// initialization. Guarded initializations are used when it's not
+ /// possible to prove that an initialization will be done exactly
+ /// once, e.g. with a static local variable or a static data member
+ /// of a class template.
+ void EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr);
+
+ /// GenerateCXXGlobalInitFunc - Generates code for initializing global
+ /// variables.
+ void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
+ llvm::Constant **Decls,
+ unsigned NumDecls);
+
+ /// GenerateCXXGlobalDtorFunc - Generates code for destroying global
+ /// variables.
+ void GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
+ const std::vector<std::pair<llvm::WeakVH,
+ llvm::Constant*> > &DtorsAndObjects);
+
+ void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D,
+ llvm::GlobalVariable *Addr);
+
+ void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
+
+ void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
+ const Expr *Exp);
+
+ RValue EmitExprWithCleanups(const ExprWithCleanups *E,
+ AggValueSlot Slot =AggValueSlot::ignored());
+
+ void EmitCXXThrowExpr(const CXXThrowExpr *E);
+
+ //===--------------------------------------------------------------------===//
+ // Internal Helpers
+ //===--------------------------------------------------------------------===//
+
+ /// ContainsLabel - Return true if the statement contains a label in it. If
+ /// this statement is not executed normally, it not containing a label means
+ /// that we can just remove the code.
+ static bool ContainsLabel(const Stmt *S, bool IgnoreCaseStmts = false);
+
+ /// ConstantFoldsToSimpleInteger - If the specified expression does not fold
+ /// to a constant, or if it does but contains a label, return 0. If it
+ /// constant folds to 'true' and does not contain a label, return 1, if it
+ /// constant folds to 'false' and does not contain a label, return -1.
+ int ConstantFoldsToSimpleInteger(const Expr *Cond);
+
+ /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an
+ /// if statement) to the specified blocks. Based on the condition, this might
+ /// try to simplify the codegen of the conditional based on the branch.
+ void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock,
+ llvm::BasicBlock *FalseBlock);
+
+ /// getTrapBB - Create a basic block that will call the trap intrinsic. We'll
+ /// generate a branch around the created basic block as necessary.
+ llvm::BasicBlock *getTrapBB();
+
+ /// EmitCallArg - Emit a single call argument.
+ RValue EmitCallArg(const Expr *E, QualType ArgType);
+
+ /// EmitDelegateCallArg - We are performing a delegate call; that
+ /// is, the current function is delegating to another one. Produce
+ /// a r-value suitable for passing the given parameter.
+ RValue EmitDelegateCallArg(const VarDecl *Param);
+
+private:
+ void EmitReturnOfRValue(RValue RV, QualType Ty);
+
+ /// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty
+ /// from function arguments into \arg Dst. See ABIArgInfo::Expand.
+ ///
+ /// \param AI - The first function argument of the expansion.
+ /// \return The argument following the last expanded function
+ /// argument.
+ llvm::Function::arg_iterator
+ ExpandTypeFromArgs(QualType Ty, LValue Dst,
+ llvm::Function::arg_iterator AI);
+
+ /// ExpandTypeToArgs - Expand an RValue \arg Src, with the LLVM type for \arg
+ /// Ty, into individual arguments on the provided vector \arg Args. See
+ /// ABIArgInfo::Expand.
+ void ExpandTypeToArgs(QualType Ty, RValue Src,
+ llvm::SmallVector<llvm::Value*, 16> &Args);
+
+ llvm::Value* EmitAsmInput(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ const Expr *InputExpr, std::string &ConstraintStr);
+
+ llvm::Value* EmitAsmInputLValue(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ LValue InputValue, QualType InputType,
+ std::string &ConstraintStr);
+
+ /// EmitCallArgs - Emit call arguments for a function.
+ /// The CallArgTypeInfo parameter is used for iterating over the known
+ /// argument types of the function being called.
+ template<typename T>
+ void EmitCallArgs(CallArgList& Args, const T* CallArgTypeInfo,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd) {
+ CallExpr::const_arg_iterator Arg = ArgBeg;
+
+ // First, use the argument types that the type info knows about
+ if (CallArgTypeInfo) {
+ for (typename T::arg_type_iterator I = CallArgTypeInfo->arg_type_begin(),
+ E = CallArgTypeInfo->arg_type_end(); I != E; ++I, ++Arg) {
+ assert(Arg != ArgEnd && "Running over edge of argument list!");
+ QualType ArgType = *I;
+#ifndef NDEBUG
+ QualType ActualArgType = Arg->getType();
+ if (ArgType->isPointerType() && ActualArgType->isPointerType()) {
+ QualType ActualBaseType =
+ ActualArgType->getAs<PointerType>()->getPointeeType();
+ QualType ArgBaseType =
+ ArgType->getAs<PointerType>()->getPointeeType();
+ if (ArgBaseType->isVariableArrayType()) {
+ if (const VariableArrayType *VAT =
+ getContext().getAsVariableArrayType(ActualBaseType)) {
+ if (!VAT->getSizeExpr())
+ ActualArgType = ArgType;
+ }
+ }
+ }
+ assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
+ getTypePtr() ==
+ getContext().getCanonicalType(ActualArgType).getTypePtr() &&
+ "type mismatch in call argument!");
+#endif
+ Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType),
+ ArgType));
+ }
+
+ // Either we've emitted all the call args, or we have a call to a
+ // variadic function.
+ assert((Arg == ArgEnd || CallArgTypeInfo->isVariadic()) &&
+ "Extra arguments in non-variadic function!");
+
+ }
+
+ // If we still have any arguments, emit them using the type of the argument.
+ for (; Arg != ArgEnd; ++Arg) {
+ QualType ArgType = Arg->getType();
+ Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType),
+ ArgType));
+ }
+ }
+
+ const TargetCodeGenInfo &getTargetHooks() const {
+ return CGM.getTargetCodeGenInfo();
+ }
+
+ void EmitDeclMetadata();
+};
+
+/// Helper class with most of the code for saving a value for a
+/// conditional expression cleanup.
+struct DominatingLLVMValue {
+ typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
+
+ /// Answer whether the given value needs extra work to be saved.
+ static bool needsSaving(llvm::Value *value) {
+ // If it's not an instruction, we don't need to save.
+ if (!isa<llvm::Instruction>(value)) return false;
+
+ // If it's an instruction in the entry block, we don't need to save.
+ llvm::BasicBlock *block = cast<llvm::Instruction>(value)->getParent();
+ return (block != &block->getParent()->getEntryBlock());
+ }
+
+ /// Try to save the given value.
+ static saved_type save(CodeGenFunction &CGF, llvm::Value *value) {
+ if (!needsSaving(value)) return saved_type(value, false);
+
+ // Otherwise we need an alloca.
+ llvm::Value *alloca =
+ CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save");
+ CGF.Builder.CreateStore(value, alloca);
+
+ return saved_type(alloca, true);
+ }
+
+ static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) {
+ if (!value.getInt()) return value.getPointer();
+ return CGF.Builder.CreateLoad(value.getPointer());
+ }
+};
+
+/// A partial specialization of DominatingValue for llvm::Values that
+/// might be llvm::Instructions.
+template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
+ typedef T *type;
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
+ }
+};
+
+/// A specialization of DominatingValue for RValue.
+template <> struct DominatingValue<RValue> {
+ typedef RValue type;
+ class saved_type {
+ enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
+ AggregateAddress, ComplexAddress };
+
+ llvm::Value *Value;
+ Kind K;
+ saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
+
+ public:
+ static bool needsSaving(RValue value);
+ static saved_type save(CodeGenFunction &CGF, RValue value);
+ RValue restore(CodeGenFunction &CGF);
+
+ // implementations in CGExprCXX.cpp
+ };
+
+ static bool needsSaving(type value) {
+ return saved_type::needsSaving(value);
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return saved_type::save(CGF, value);
+ }
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return value.restore(CGF);
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
new file mode 100644
index 0000000..9e5d7cf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -0,0 +1,2251 @@
+//===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This coordinates the per-module state used while generating code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
+#include "CodeGenTBAA.h"
+#include "CGCall.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "TargetInfo.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/ConvertUTF.h"
+#include "llvm/CallingConv.h"
+#include "llvm/Module.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+using namespace CodeGen;
+
+static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
+ switch (CGM.getContext().Target.getCXXABI()) {
+ case CXXABI_ARM: return *CreateARMCXXABI(CGM);
+ case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM);
+ case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM);
+ }
+
+ llvm_unreachable("invalid C++ ABI kind");
+ return *CreateItaniumCXXABI(CGM);
+}
+
+
+CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
+ llvm::Module &M, const llvm::TargetData &TD,
+ Diagnostic &diags)
+ : Context(C), Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
+ TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
+ ABI(createCXXABI(*this)),
+ Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI),
+ TBAA(0),
+ VTables(*this), Runtime(0),
+ CFConstantStringClassRef(0), ConstantStringClassRef(0),
+ VMContext(M.getContext()),
+ NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0),
+ NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),
+ BlockObjectAssignDecl(0), BlockObjectDisposeDecl(0),
+ BlockObjectAssign(0), BlockObjectDispose(0),
+ BlockDescriptorType(0), GenericBlockLiteralType(0) {
+ if (!Features.ObjC1)
+ Runtime = 0;
+ else if (!Features.NeXTRuntime)
+ Runtime = CreateGNUObjCRuntime(*this);
+ else if (Features.ObjCNonFragileABI)
+ Runtime = CreateMacNonFragileABIObjCRuntime(*this);
+ else
+ Runtime = CreateMacObjCRuntime(*this);
+
+ // Enable TBAA unless it's suppressed.
+ if (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)
+ TBAA = new CodeGenTBAA(Context, VMContext, getLangOptions(),
+ ABI.getMangleContext());
+
+ // If debug info generation is enabled, create the CGDebugInfo object.
+ DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0;
+
+ Block.GlobalUniqueCount = 0;
+
+ // Initialize the type cache.
+ llvm::LLVMContext &LLVMContext = M.getContext();
+ Int8Ty = llvm::Type::getInt8Ty(LLVMContext);
+ Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
+ Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
+ PointerWidthInBits = C.Target.getPointerWidth(0);
+ IntTy = llvm::IntegerType::get(LLVMContext, C.Target.getIntWidth());
+ IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
+ Int8PtrTy = Int8Ty->getPointerTo(0);
+ Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
+}
+
+CodeGenModule::~CodeGenModule() {
+ delete Runtime;
+ delete &ABI;
+ delete TBAA;
+ delete DebugInfo;
+}
+
+void CodeGenModule::createObjCRuntime() {
+ if (!Features.NeXTRuntime)
+ Runtime = CreateGNUObjCRuntime(*this);
+ else if (Features.ObjCNonFragileABI)
+ Runtime = CreateMacNonFragileABIObjCRuntime(*this);
+ else
+ Runtime = CreateMacObjCRuntime(*this);
+}
+
+void CodeGenModule::Release() {
+ EmitDeferred();
+ EmitCXXGlobalInitFunc();
+ EmitCXXGlobalDtorFunc();
+ if (Runtime)
+ if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
+ AddGlobalCtor(ObjCInitFunction);
+ EmitCtorList(GlobalCtors, "llvm.global_ctors");
+ EmitCtorList(GlobalDtors, "llvm.global_dtors");
+ EmitAnnotations();
+ EmitLLVMUsed();
+
+ SimplifyPersonality();
+
+ if (getCodeGenOpts().EmitDeclMetadata)
+ EmitDeclMetadata();
+}
+
+llvm::MDNode *CodeGenModule::getTBAAInfo(QualType QTy) {
+ if (!TBAA)
+ return 0;
+ return TBAA->getTBAAInfo(QTy);
+}
+
+void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
+ llvm::MDNode *TBAAInfo) {
+ Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);
+}
+
+bool CodeGenModule::isTargetDarwin() const {
+ return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin;
+}
+
+/// ErrorUnsupported - Print out an error that codegen doesn't support the
+/// specified stmt yet.
+void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
+ bool OmitOnError) {
+ if (OmitOnError && getDiags().hasErrorOccurred())
+ return;
+ unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
+ "cannot compile this %0 yet");
+ std::string Msg = Type;
+ getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID)
+ << Msg << S->getSourceRange();
+}
+
+/// ErrorUnsupported - Print out an error that codegen doesn't support the
+/// specified decl yet.
+void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
+ bool OmitOnError) {
+ if (OmitOnError && getDiags().hasErrorOccurred())
+ return;
+ unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
+ "cannot compile this %0 yet");
+ std::string Msg = Type;
+ getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
+}
+
+void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
+ // Internal definitions always have default visibility.
+ if (GV->hasLocalLinkage()) {
+ GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
+ return;
+ }
+
+ // Set visibility for definitions.
+ NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
+ if (LV.visibilityExplicit() || !GV->hasAvailableExternallyLinkage())
+ GV->setVisibility(GetLLVMVisibility(LV.visibility()));
+}
+
+/// Set the symbol visibility of type information (vtable and RTTI)
+/// associated with the given type.
+void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
+ const CXXRecordDecl *RD,
+ TypeVisibilityKind TVK) const {
+ setGlobalVisibility(GV, RD);
+
+ if (!CodeGenOpts.HiddenWeakVTables)
+ return;
+
+ // We never want to drop the visibility for RTTI names.
+ if (TVK == TVK_ForRTTIName)
+ return;
+
+ // We want to drop the visibility to hidden for weak type symbols.
+ // This isn't possible if there might be unresolved references
+ // elsewhere that rely on this symbol being visible.
+
+ // This should be kept roughly in sync with setThunkVisibility
+ // in CGVTables.cpp.
+
+ // Preconditions.
+ if (GV->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage ||
+ GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
+ return;
+
+ // Don't override an explicit visibility attribute.
+ if (RD->hasAttr<VisibilityAttr>())
+ return;
+
+ switch (RD->getTemplateSpecializationKind()) {
+ // We have to disable the optimization if this is an EI definition
+ // because there might be EI declarations in other shared objects.
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ return;
+
+ // Every use of a non-template class's type information has to emit it.
+ case TSK_Undeclared:
+ break;
+
+ // In theory, implicit instantiations can ignore the possibility of
+ // an explicit instantiation declaration because there necessarily
+ // must be an EI definition somewhere with default visibility. In
+ // practice, it's possible to have an explicit instantiation for
+ // an arbitrary template class, and linkers aren't necessarily able
+ // to deal with mixed-visibility symbols.
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ if (!CodeGenOpts.HiddenWeakTemplateVTables)
+ return;
+ break;
+ }
+
+ // If there's a key function, there may be translation units
+ // that don't have the key function's definition. But ignore
+ // this if we're emitting RTTI under -fno-rtti.
+ if (!(TVK != TVK_ForRTTI) || Features.RTTI) {
+ if (Context.getKeyFunction(RD))
+ return;
+ }
+
+ // Otherwise, drop the visibility to hidden.
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ GV->setUnnamedAddr(true);
+}
+
+llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
+
+ llvm::StringRef &Str = MangledDeclNames[GD.getCanonicalDecl()];
+ if (!Str.empty())
+ return Str;
+
+ if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+ IdentifierInfo *II = ND->getIdentifier();
+ assert(II && "Attempt to mangle unnamed decl.");
+
+ Str = II->getName();
+ return Str;
+ }
+
+ llvm::SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
+ getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
+ else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
+ getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
+ else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND))
+ getCXXABI().getMangleContext().mangleBlock(BD, Out);
+ else
+ getCXXABI().getMangleContext().mangleName(ND, Out);
+
+ // Allocate space for the mangled name.
+ Out.flush();
+ size_t Length = Buffer.size();
+ char *Name = MangledNamesAllocator.Allocate<char>(Length);
+ std::copy(Buffer.begin(), Buffer.end(), Name);
+
+ Str = llvm::StringRef(Name, Length);
+
+ return Str;
+}
+
+void CodeGenModule::getBlockMangledName(GlobalDecl GD, MangleBuffer &Buffer,
+ const BlockDecl *BD) {
+ MangleContext &MangleCtx = getCXXABI().getMangleContext();
+ const Decl *D = GD.getDecl();
+ llvm::raw_svector_ostream Out(Buffer.getBuffer());
+ if (D == 0)
+ MangleCtx.mangleGlobalBlock(BD, Out);
+ else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
+ MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out);
+ else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))
+ MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out);
+ else
+ MangleCtx.mangleBlock(cast<DeclContext>(D), BD, Out);
+}
+
+llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) {
+ return getModule().getNamedValue(Name);
+}
+
+/// AddGlobalCtor - Add a function to the list that will be called before
+/// main() runs.
+void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
+ // FIXME: Type coercion of void()* types.
+ GlobalCtors.push_back(std::make_pair(Ctor, Priority));
+}
+
+/// AddGlobalDtor - Add a function to the list that will be called
+/// when the module is unloaded.
+void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) {
+ // FIXME: Type coercion of void()* types.
+ GlobalDtors.push_back(std::make_pair(Dtor, Priority));
+}
+
+void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
+ // Ctor function type is void()*.
+ llvm::FunctionType* CtorFTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false);
+ llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
+
+ // Get the type of a ctor entry, { i32, void ()* }.
+ llvm::StructType* CtorStructTy =
+ llvm::StructType::get(VMContext, llvm::Type::getInt32Ty(VMContext),
+ llvm::PointerType::getUnqual(CtorFTy), NULL);
+
+ // Construct the constructor and destructor arrays.
+ std::vector<llvm::Constant*> Ctors;
+ for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+ std::vector<llvm::Constant*> S;
+ S.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
+ I->second, false));
+ S.push_back(llvm::ConstantExpr::getBitCast(I->first, CtorPFTy));
+ Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
+ }
+
+ if (!Ctors.empty()) {
+ llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
+ new llvm::GlobalVariable(TheModule, AT, false,
+ llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(AT, Ctors),
+ GlobalName);
+ }
+}
+
+void CodeGenModule::EmitAnnotations() {
+ if (Annotations.empty())
+ return;
+
+ // Create a new global variable for the ConstantStruct in the Module.
+ llvm::Constant *Array =
+ llvm::ConstantArray::get(llvm::ArrayType::get(Annotations[0]->getType(),
+ Annotations.size()),
+ Annotations);
+ llvm::GlobalValue *gv =
+ new llvm::GlobalVariable(TheModule, Array->getType(), false,
+ llvm::GlobalValue::AppendingLinkage, Array,
+ "llvm.global.annotations");
+ gv->setSection("llvm.metadata");
+}
+
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
+ GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
+
+ if (Linkage == GVA_Internal)
+ return llvm::Function::InternalLinkage;
+
+ if (D->hasAttr<DLLExportAttr>())
+ return llvm::Function::DLLExportLinkage;
+
+ if (D->hasAttr<WeakAttr>())
+ return llvm::Function::WeakAnyLinkage;
+
+ // In C99 mode, 'inline' functions are guaranteed to have a strong
+ // definition somewhere else, so we can use available_externally linkage.
+ if (Linkage == GVA_C99Inline)
+ return llvm::Function::AvailableExternallyLinkage;
+
+ // In C++, the compiler has to emit a definition in every translation unit
+ // that references the function. We should use linkonce_odr because
+ // a) if all references in this translation unit are optimized away, we
+ // don't need to codegen it. b) if the function persists, it needs to be
+ // merged with other definitions. c) C++ has the ODR, so we know the
+ // definition is dependable.
+ if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+ return !Context.getLangOptions().AppleKext
+ ? llvm::Function::LinkOnceODRLinkage
+ : llvm::Function::InternalLinkage;
+
+ // An explicit instantiation of a template has weak linkage, since
+ // explicit instantiations can occur in multiple translation units
+ // and must all be equivalent. However, we are not allowed to
+ // throw away these explicit instantiations.
+ if (Linkage == GVA_ExplicitTemplateInstantiation)
+ return !Context.getLangOptions().AppleKext
+ ? llvm::Function::WeakODRLinkage
+ : llvm::Function::InternalLinkage;
+
+ // Otherwise, we have strong external linkage.
+ assert(Linkage == GVA_StrongExternal);
+ return llvm::Function::ExternalLinkage;
+}
+
+
+/// SetFunctionDefinitionAttributes - Set attributes for a global.
+///
+/// FIXME: This is currently only done for aliases and functions, but not for
+/// variables (these details are set in EmitGlobalVarDefinition for variables).
+void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
+ llvm::GlobalValue *GV) {
+ SetCommonAttributes(D, GV);
+}
+
+void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
+ const CGFunctionInfo &Info,
+ llvm::Function *F) {
+ unsigned CallingConv;
+ AttributeListType AttributeList;
+ ConstructAttributeList(Info, D, AttributeList, CallingConv);
+ F->setAttributes(llvm::AttrListPtr::get(AttributeList.begin(),
+ AttributeList.size()));
+ F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
+}
+
+void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
+ llvm::Function *F) {
+ if (!Features.Exceptions && !Features.ObjCNonFragileABI)
+ F->addFnAttr(llvm::Attribute::NoUnwind);
+
+ if (D->hasAttr<AlwaysInlineAttr>())
+ F->addFnAttr(llvm::Attribute::AlwaysInline);
+
+ if (D->hasAttr<NakedAttr>())
+ F->addFnAttr(llvm::Attribute::Naked);
+
+ if (D->hasAttr<NoInlineAttr>())
+ F->addFnAttr(llvm::Attribute::NoInline);
+
+ if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D))
+ F->setUnnamedAddr(true);
+
+ if (Features.getStackProtectorMode() == LangOptions::SSPOn)
+ F->addFnAttr(llvm::Attribute::StackProtect);
+ else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
+ F->addFnAttr(llvm::Attribute::StackProtectReq);
+
+ unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
+ if (alignment)
+ F->setAlignment(alignment);
+
+ // C++ ABI requires 2-byte alignment for member functions.
+ if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
+ F->setAlignment(2);
+}
+
+void CodeGenModule::SetCommonAttributes(const Decl *D,
+ llvm::GlobalValue *GV) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ setGlobalVisibility(GV, ND);
+ else
+ GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
+
+ if (D->hasAttr<UsedAttr>())
+ AddUsedGlobal(GV);
+
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ GV->setSection(SA->getName());
+
+ getTargetCodeGenInfo().SetTargetAttributes(D, GV, *this);
+}
+
+void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
+ llvm::Function *F,
+ const CGFunctionInfo &FI) {
+ SetLLVMFunctionAttributes(D, FI, F);
+ SetLLVMFunctionAttributesForDefinition(D, F);
+
+ F->setLinkage(llvm::Function::InternalLinkage);
+
+ SetCommonAttributes(D, F);
+}
+
+void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,
+ llvm::Function *F,
+ bool IsIncompleteFunction) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ if (!IsIncompleteFunction)
+ SetLLVMFunctionAttributes(FD, getTypes().getFunctionInfo(GD), F);
+
+ // Only a few attributes are set on declarations; these may later be
+ // overridden by a definition.
+
+ if (FD->hasAttr<DLLImportAttr>()) {
+ F->setLinkage(llvm::Function::DLLImportLinkage);
+ } else if (FD->hasAttr<WeakAttr>() ||
+ FD->hasAttr<WeakImportAttr>()) {
+ // "extern_weak" is overloaded in LLVM; we probably should have
+ // separate linkage types for this.
+ F->setLinkage(llvm::Function::ExternalWeakLinkage);
+ } else {
+ F->setLinkage(llvm::Function::ExternalLinkage);
+
+ NamedDecl::LinkageInfo LV = FD->getLinkageAndVisibility();
+ if (LV.linkage() == ExternalLinkage && LV.visibilityExplicit()) {
+ F->setVisibility(GetLLVMVisibility(LV.visibility()));
+ }
+ }
+
+ if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
+ F->setSection(SA->getName());
+}
+
+void CodeGenModule::AddUsedGlobal(llvm::GlobalValue *GV) {
+ assert(!GV->isDeclaration() &&
+ "Only globals with definition can force usage.");
+ LLVMUsed.push_back(GV);
+}
+
+void CodeGenModule::EmitLLVMUsed() {
+ // Don't create llvm.used if there is no need.
+ if (LLVMUsed.empty())
+ return;
+
+ const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(VMContext);
+
+ // Convert LLVMUsed to what ConstantArray needs.
+ std::vector<llvm::Constant*> UsedArray;
+ UsedArray.resize(LLVMUsed.size());
+ for (unsigned i = 0, e = LLVMUsed.size(); i != e; ++i) {
+ UsedArray[i] =
+ llvm::ConstantExpr::getBitCast(cast<llvm::Constant>(&*LLVMUsed[i]),
+ i8PTy);
+ }
+
+ if (UsedArray.empty())
+ return;
+ llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedArray.size());
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(getModule(), ATy, false,
+ llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(ATy, UsedArray),
+ "llvm.used");
+
+ GV->setSection("llvm.metadata");
+}
+
+void CodeGenModule::EmitDeferred() {
+ // Emit code for any potentially referenced deferred decls. Since a
+ // previously unused static decl may become used during the generation of code
+ // for a static function, iterate until no changes are made.
+
+ while (!DeferredDeclsToEmit.empty() || !DeferredVTables.empty()) {
+ if (!DeferredVTables.empty()) {
+ const CXXRecordDecl *RD = DeferredVTables.back();
+ DeferredVTables.pop_back();
+ getVTables().GenerateClassData(getVTableLinkage(RD), RD);
+ continue;
+ }
+
+ GlobalDecl D = DeferredDeclsToEmit.back();
+ DeferredDeclsToEmit.pop_back();
+
+ // Check to see if we've already emitted this. This is necessary
+ // for a couple of reasons: first, decls can end up in the
+ // deferred-decls queue multiple times, and second, decls can end
+ // up with definitions in unusual ways (e.g. by an extern inline
+ // function acquiring a strong function redefinition). Just
+ // ignore these cases.
+ //
+ // TODO: That said, looking this up multiple times is very wasteful.
+ llvm::StringRef Name = getMangledName(D);
+ llvm::GlobalValue *CGRef = GetGlobalValue(Name);
+ assert(CGRef && "Deferred decl wasn't referenced?");
+
+ if (!CGRef->isDeclaration())
+ continue;
+
+ // GlobalAlias::isDeclaration() defers to the aliasee, but for our
+ // purposes an alias counts as a definition.
+ if (isa<llvm::GlobalAlias>(CGRef))
+ continue;
+
+ // Otherwise, emit the definition and move on to the next one.
+ EmitGlobalDefinition(D);
+ }
+}
+
+/// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the
+/// annotation information for a given GlobalValue. The annotation struct is
+/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the
+/// GlobalValue being annotated. The second field is the constant string
+/// created from the AnnotateAttr's annotation. The third field is a constant
+/// string containing the name of the translation unit. The fourth field is
+/// the line number in the file of the annotated value declaration.
+///
+/// FIXME: this does not unique the annotation string constants, as llvm-gcc
+/// appears to.
+///
+llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
+ const AnnotateAttr *AA,
+ unsigned LineNo) {
+ llvm::Module *M = &getModule();
+
+ // get [N x i8] constants for the annotation string, and the filename string
+ // which are the 2nd and 3rd elements of the global annotation structure.
+ const llvm::Type *SBP = llvm::Type::getInt8PtrTy(VMContext);
+ llvm::Constant *anno = llvm::ConstantArray::get(VMContext,
+ AA->getAnnotation(), true);
+ llvm::Constant *unit = llvm::ConstantArray::get(VMContext,
+ M->getModuleIdentifier(),
+ true);
+
+ // Get the two global values corresponding to the ConstantArrays we just
+ // created to hold the bytes of the strings.
+ llvm::GlobalValue *annoGV =
+ new llvm::GlobalVariable(*M, anno->getType(), false,
+ llvm::GlobalValue::PrivateLinkage, anno,
+ GV->getName());
+ // translation unit name string, emitted into the llvm.metadata section.
+ llvm::GlobalValue *unitGV =
+ new llvm::GlobalVariable(*M, unit->getType(), false,
+ llvm::GlobalValue::PrivateLinkage, unit,
+ ".str");
+ unitGV->setUnnamedAddr(true);
+
+ // Create the ConstantStruct for the global annotation.
+ llvm::Constant *Fields[4] = {
+ llvm::ConstantExpr::getBitCast(GV, SBP),
+ llvm::ConstantExpr::getBitCast(annoGV, SBP),
+ llvm::ConstantExpr::getBitCast(unitGV, SBP),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), LineNo)
+ };
+ return llvm::ConstantStruct::get(VMContext, Fields, 4, false);
+}
+
+bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
+ // Never defer when EmitAllDecls is specified.
+ if (Features.EmitAllDecls)
+ return false;
+
+ return !getContext().DeclMustBeEmitted(Global);
+}
+
+llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
+ const AliasAttr *AA = VD->getAttr<AliasAttr>();
+ assert(AA && "No alias?");
+
+ const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType());
+
+ // See if there is already something with the target's name in the module.
+ llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee());
+
+ llvm::Constant *Aliasee;
+ if (isa<llvm::FunctionType>(DeclTy))
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl(),
+ /*ForVTable=*/false);
+ else
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
+ llvm::PointerType::getUnqual(DeclTy), 0);
+ if (!Entry) {
+ llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee);
+ F->setLinkage(llvm::Function::ExternalWeakLinkage);
+ WeakRefReferences.insert(F);
+ }
+
+ return Aliasee;
+}
+
+void CodeGenModule::EmitGlobal(GlobalDecl GD) {
+ const ValueDecl *Global = cast<ValueDecl>(GD.getDecl());
+
+ // Weak references don't produce any output by themselves.
+ if (Global->hasAttr<WeakRefAttr>())
+ return;
+
+ // If this is an alias definition (which otherwise looks like a declaration)
+ // emit it now.
+ if (Global->hasAttr<AliasAttr>())
+ return EmitAliasDefinition(GD);
+
+ // Ignore declarations, they will be emitted on their first use.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
+ if (FD->getIdentifier()) {
+ llvm::StringRef Name = FD->getName();
+ if (Name == "_Block_object_assign") {
+ BlockObjectAssignDecl = FD;
+ } else if (Name == "_Block_object_dispose") {
+ BlockObjectDisposeDecl = FD;
+ }
+ }
+
+ // Forward declarations are emitted lazily on first use.
+ if (!FD->isThisDeclarationADefinition())
+ return;
+ } else {
+ const VarDecl *VD = cast<VarDecl>(Global);
+ assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
+
+ if (VD->getIdentifier()) {
+ llvm::StringRef Name = VD->getName();
+ if (Name == "_NSConcreteGlobalBlock") {
+ NSConcreteGlobalBlockDecl = VD;
+ } else if (Name == "_NSConcreteStackBlock") {
+ NSConcreteStackBlockDecl = VD;
+ }
+ }
+
+
+ if (VD->isThisDeclarationADefinition() != VarDecl::Definition)
+ return;
+ }
+
+ // Defer code generation when possible if this is a static definition, inline
+ // function etc. These we only want to emit if they are used.
+ if (!MayDeferGeneration(Global)) {
+ // Emit the definition if it can't be deferred.
+ EmitGlobalDefinition(GD);
+ return;
+ }
+
+ // If we're deferring emission of a C++ variable with an
+ // initializer, remember the order in which it appeared in the file.
+ if (getLangOptions().CPlusPlus && isa<VarDecl>(Global) &&
+ cast<VarDecl>(Global)->hasInit()) {
+ DelayedCXXInitPosition[Global] = CXXGlobalInits.size();
+ CXXGlobalInits.push_back(0);
+ }
+
+ // If the value has already been used, add it directly to the
+ // DeferredDeclsToEmit list.
+ llvm::StringRef MangledName = getMangledName(GD);
+ if (GetGlobalValue(MangledName))
+ DeferredDeclsToEmit.push_back(GD);
+ else {
+ // Otherwise, remember that we saw a deferred decl with this name. The
+ // first use of the mangled name will cause it to move into
+ // DeferredDeclsToEmit.
+ DeferredDecls[MangledName] = GD;
+ }
+}
+
+void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
+ const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+
+ PrettyStackTraceDecl CrashInfo(const_cast<ValueDecl *>(D), D->getLocation(),
+ Context.getSourceManager(),
+ "Generating code for declaration");
+
+ if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // At -O0, don't generate IR for functions with available_externally
+ // linkage.
+ if (CodeGenOpts.OptimizationLevel == 0 &&
+ !Function->hasAttr<AlwaysInlineAttr>() &&
+ getFunctionLinkage(Function)
+ == llvm::Function::AvailableExternallyLinkage)
+ return;
+
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Method->isVirtual())
+ getVTables().EmitThunks(GD);
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Method))
+ return EmitCXXConstructor(CD, GD.getCtorType());
+
+ if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(Method))
+ return EmitCXXDestructor(DD, GD.getDtorType());
+ }
+
+ return EmitGlobalFunctionDefinition(GD);
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ return EmitGlobalVarDefinition(VD);
+
+ assert(0 && "Invalid argument to EmitGlobalDefinition()");
+}
+
+/// GetOrCreateLLVMFunction - If the specified mangled name is not in the
+/// module, create and return an llvm Function with the specified type. If there
+/// is something in the module with the specified name, return it potentially
+/// bitcasted to the right type.
+///
+/// If D is non-null, it specifies a decl that correspond to this. This is used
+/// to set the attributes on the function when it is first created.
+llvm::Constant *
+CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
+ const llvm::Type *Ty,
+ GlobalDecl D, bool ForVTable) {
+ // Lookup the entry, lazily creating it if necessary.
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry) {
+ if (WeakRefReferences.count(Entry)) {
+ const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl());
+ if (FD && !FD->hasAttr<WeakAttr>())
+ Entry->setLinkage(llvm::Function::ExternalLinkage);
+
+ WeakRefReferences.erase(Entry);
+ }
+
+ if (Entry->getType()->getElementType() == Ty)
+ return Entry;
+
+ // Make sure the result is of the correct type.
+ const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
+ return llvm::ConstantExpr::getBitCast(Entry, PTy);
+ }
+
+ // This function doesn't have a complete type (for example, the return
+ // type is an incomplete struct). Use a fake type instead, and make
+ // sure not to try to set attributes.
+ bool IsIncompleteFunction = false;
+
+ const llvm::FunctionType *FTy;
+ if (isa<llvm::FunctionType>(Ty)) {
+ FTy = cast<llvm::FunctionType>(Ty);
+ } else {
+ FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false);
+ IsIncompleteFunction = true;
+ }
+
+ llvm::Function *F = llvm::Function::Create(FTy,
+ llvm::Function::ExternalLinkage,
+ MangledName, &getModule());
+ assert(F->getName() == MangledName && "name was uniqued!");
+ if (D.getDecl())
+ SetFunctionAttributes(D, F, IsIncompleteFunction);
+
+ // This is the first use or definition of a mangled name. If there is a
+ // deferred decl with this name, remember that we need to emit it at the end
+ // of the file.
+ llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+ if (DDI != DeferredDecls.end()) {
+ // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
+ // list, and remove it from DeferredDecls (since we don't need it anymore).
+ DeferredDeclsToEmit.push_back(DDI->second);
+ DeferredDecls.erase(DDI);
+
+ // Otherwise, there are cases we have to worry about where we're
+ // using a declaration for which we must emit a definition but where
+ // we might not find a top-level definition:
+ // - member functions defined inline in their classes
+ // - friend functions defined inline in some class
+ // - special member functions with implicit definitions
+ // If we ever change our AST traversal to walk into class methods,
+ // this will be unnecessary.
+ //
+ // We also don't emit a definition for a function if it's going to be an entry
+ // in a vtable, unless it's already marked as used.
+ } else if (getLangOptions().CPlusPlus && D.getDecl()) {
+ // Look for a declaration that's lexically in a record.
+ const FunctionDecl *FD = cast<FunctionDecl>(D.getDecl());
+ do {
+ if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
+ if (FD->isImplicit() && !ForVTable) {
+ assert(FD->isUsed() && "Sema didn't mark implicit function as used!");
+ DeferredDeclsToEmit.push_back(D.getWithDecl(FD));
+ break;
+ } else if (FD->isThisDeclarationADefinition()) {
+ DeferredDeclsToEmit.push_back(D.getWithDecl(FD));
+ break;
+ }
+ }
+ FD = FD->getPreviousDeclaration();
+ } while (FD);
+ }
+
+ // Make sure the result is of the requested type.
+ if (!IsIncompleteFunction) {
+ assert(F->getType()->getElementType() == Ty);
+ return F;
+ }
+
+ const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
+ return llvm::ConstantExpr::getBitCast(F, PTy);
+}
+
+/// GetAddrOfFunction - Return the address of the given function. If Ty is
+/// non-null, then this function will use the specified type if it has to
+/// create it (this occurs when we see a definition of the function).
+llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
+ const llvm::Type *Ty,
+ bool ForVTable) {
+ // If there was no specific requested type, just convert it now.
+ if (!Ty)
+ Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
+
+ llvm::StringRef MangledName = getMangledName(GD);
+ return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable);
+}
+
+/// CreateRuntimeFunction - Create a new runtime function with the specified
+/// type and name.
+llvm::Constant *
+CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
+ llvm::StringRef Name) {
+ return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false);
+}
+
+static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D) {
+ if (!D->getType().isConstant(Context) && !D->getType()->isReferenceType())
+ return false;
+ if (Context.getLangOptions().CPlusPlus &&
+ Context.getBaseElementType(D->getType())->getAs<RecordType>()) {
+ // FIXME: We should do something fancier here!
+ return false;
+ }
+ return true;
+}
+
+/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
+/// create and return an llvm GlobalVariable with the specified type. If there
+/// is something in the module with the specified name, return it potentially
+/// bitcasted to the right type.
+///
+/// If D is non-null, it specifies a decl that correspond to this. This is used
+/// to set the attributes on the global when it is first created.
+llvm::Constant *
+CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
+ const llvm::PointerType *Ty,
+ const VarDecl *D,
+ bool UnnamedAddr) {
+ // Lookup the entry, lazily creating it if necessary.
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry) {
+ if (WeakRefReferences.count(Entry)) {
+ if (D && !D->hasAttr<WeakAttr>())
+ Entry->setLinkage(llvm::Function::ExternalLinkage);
+
+ WeakRefReferences.erase(Entry);
+ }
+
+ if (UnnamedAddr)
+ Entry->setUnnamedAddr(true);
+
+ if (Entry->getType() == Ty)
+ return Entry;
+
+ // Make sure the result is of the correct type.
+ return llvm::ConstantExpr::getBitCast(Entry, Ty);
+ }
+
+ // This is the first use or definition of a mangled name. If there is a
+ // deferred decl with this name, remember that we need to emit it at the end
+ // of the file.
+ llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+ if (DDI != DeferredDecls.end()) {
+ // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
+ // list, and remove it from DeferredDecls (since we don't need it anymore).
+ DeferredDeclsToEmit.push_back(DDI->second);
+ DeferredDecls.erase(DDI);
+ }
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, MangledName, 0,
+ false, Ty->getAddressSpace());
+
+ // Handle things which are present even on external declarations.
+ if (D) {
+ // FIXME: This code is overly simple and should be merged with other global
+ // handling.
+ GV->setConstant(DeclIsConstantGlobal(Context, D));
+
+ // Set linkage and visibility in case we never see a definition.
+ NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
+ if (LV.linkage() != ExternalLinkage) {
+ // Don't set internal linkage on declarations.
+ } else {
+ if (D->hasAttr<DLLImportAttr>())
+ GV->setLinkage(llvm::GlobalValue::DLLImportLinkage);
+ else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
+ GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
+
+ // Set visibility on a declaration only if it's explicit.
+ if (LV.visibilityExplicit())
+ GV->setVisibility(GetLLVMVisibility(LV.visibility()));
+ }
+
+ GV->setThreadLocal(D->isThreadSpecified());
+ }
+
+ return GV;
+}
+
+
+llvm::GlobalVariable *
+CodeGenModule::CreateOrReplaceCXXRuntimeVariable(llvm::StringRef Name,
+ const llvm::Type *Ty,
+ llvm::GlobalValue::LinkageTypes Linkage) {
+ llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name);
+ llvm::GlobalVariable *OldGV = 0;
+
+
+ if (GV) {
+ // Check if the variable has the right type.
+ if (GV->getType()->getElementType() == Ty)
+ return GV;
+
+ // Because C++ name mangling, the only way we can end up with an already
+ // existing global with the same name is if it has been declared extern "C".
+ assert(GV->isDeclaration() && "Declaration has wrong type!");
+ OldGV = GV;
+ }
+
+ // Create a new variable.
+ GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true,
+ Linkage, 0, Name);
+
+ if (OldGV) {
+ // Replace occurrences of the old variable if needed.
+ GV->takeName(OldGV);
+
+ if (!OldGV->use_empty()) {
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtrForOldDecl);
+ }
+
+ OldGV->eraseFromParent();
+ }
+
+ return GV;
+}
+
+/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
+/// given global variable. If Ty is non-null and if the global doesn't exist,
+/// then it will be greated with the specified type instead of whatever the
+/// normal requested type would be.
+llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
+ const llvm::Type *Ty) {
+ assert(D->hasGlobalStorage() && "Not a global variable");
+ QualType ASTTy = D->getType();
+ if (Ty == 0)
+ Ty = getTypes().ConvertTypeForMem(ASTTy);
+
+ const llvm::PointerType *PTy =
+ llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
+
+ llvm::StringRef MangledName = getMangledName(D);
+ return GetOrCreateLLVMGlobal(MangledName, PTy, D);
+}
+
+/// CreateRuntimeVariable - Create a new runtime global variable with the
+/// specified type and name.
+llvm::Constant *
+CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
+ llvm::StringRef Name) {
+ return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0,
+ true);
+}
+
+void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
+ assert(!D->getInit() && "Cannot emit definite definitions here!");
+
+ if (MayDeferGeneration(D)) {
+ // If we have not seen a reference to this variable yet, place it
+ // into the deferred declarations table to be emitted if needed
+ // later.
+ llvm::StringRef MangledName = getMangledName(D);
+ if (!GetGlobalValue(MangledName)) {
+ DeferredDecls[MangledName] = D;
+ return;
+ }
+ }
+
+ // The tentative definition is the only definition.
+ EmitGlobalVarDefinition(D);
+}
+
+void CodeGenModule::EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired) {
+ if (DefinitionRequired)
+ getVTables().GenerateClassData(getVTableLinkage(Class), Class);
+}
+
+llvm::GlobalVariable::LinkageTypes
+CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
+ if (RD->isInAnonymousNamespace() || !RD->hasLinkage())
+ return llvm::GlobalVariable::InternalLinkage;
+
+ if (const CXXMethodDecl *KeyFunction
+ = RD->getASTContext().getKeyFunction(RD)) {
+ // If this class has a key function, use that to determine the linkage of
+ // the vtable.
+ const FunctionDecl *Def = 0;
+ if (KeyFunction->hasBody(Def))
+ KeyFunction = cast<CXXMethodDecl>(Def);
+
+ switch (KeyFunction->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ // When compiling with optimizations turned on, we emit all vtables,
+ // even if the key function is not defined in the current translation
+ // unit. If this is the case, use available_externally linkage.
+ if (!Def && CodeGenOpts.OptimizationLevel)
+ return llvm::GlobalVariable::AvailableExternallyLinkage;
+
+ if (KeyFunction->isInlined())
+ return !Context.getLangOptions().AppleKext ?
+ llvm::GlobalVariable::LinkOnceODRLinkage :
+ llvm::Function::InternalLinkage;
+
+ return llvm::GlobalVariable::ExternalLinkage;
+
+ case TSK_ImplicitInstantiation:
+ return !Context.getLangOptions().AppleKext ?
+ llvm::GlobalVariable::LinkOnceODRLinkage :
+ llvm::Function::InternalLinkage;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return !Context.getLangOptions().AppleKext ?
+ llvm::GlobalVariable::WeakODRLinkage :
+ llvm::Function::InternalLinkage;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ // FIXME: Use available_externally linkage. However, this currently
+ // breaks LLVM's build due to undefined symbols.
+ // return llvm::GlobalVariable::AvailableExternallyLinkage;
+ return !Context.getLangOptions().AppleKext ?
+ llvm::GlobalVariable::LinkOnceODRLinkage :
+ llvm::Function::InternalLinkage;
+ }
+ }
+
+ if (Context.getLangOptions().AppleKext)
+ return llvm::Function::InternalLinkage;
+
+ switch (RD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ // FIXME: Use available_externally linkage. However, this currently
+ // breaks LLVM's build due to undefined symbols.
+ // return llvm::GlobalVariable::AvailableExternallyLinkage;
+ case TSK_ExplicitInstantiationDeclaration:
+ return llvm::GlobalVariable::LinkOnceODRLinkage;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return llvm::GlobalVariable::WeakODRLinkage;
+ }
+
+ // Silence GCC warning.
+ return llvm::GlobalVariable::LinkOnceODRLinkage;
+}
+
+CharUnits CodeGenModule::GetTargetTypeStoreSize(const llvm::Type *Ty) const {
+ return Context.toCharUnitsFromBits(
+ TheTargetData.getTypeStoreSizeInBits(Ty));
+}
+
+void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
+ llvm::Constant *Init = 0;
+ QualType ASTTy = D->getType();
+ bool NonConstInit = false;
+
+ const Expr *InitExpr = D->getAnyInitializer();
+
+ if (!InitExpr) {
+ // This is a tentative definition; tentative definitions are
+ // implicitly initialized with { 0 }.
+ //
+ // Note that tentative definitions are only emitted at the end of
+ // a translation unit, so they should never have incomplete
+ // type. In addition, EmitTentativeDefinition makes sure that we
+ // never attempt to emit a tentative definition if a real one
+ // exists. A use may still exists, however, so we still may need
+ // to do a RAUW.
+ assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
+ Init = EmitNullConstant(D->getType());
+ } else {
+ Init = EmitConstantExpr(InitExpr, D->getType());
+ if (!Init) {
+ QualType T = InitExpr->getType();
+ if (D->getType()->isReferenceType())
+ T = D->getType();
+
+ if (getLangOptions().CPlusPlus) {
+ Init = EmitNullConstant(T);
+ NonConstInit = true;
+ } else {
+ ErrorUnsupported(D, "static initializer");
+ Init = llvm::UndefValue::get(getTypes().ConvertType(T));
+ }
+ } else {
+ // We don't need an initializer, so remove the entry for the delayed
+ // initializer position (just in case this entry was delayed).
+ if (getLangOptions().CPlusPlus)
+ DelayedCXXInitPosition.erase(D);
+ }
+ }
+
+ const llvm::Type* InitType = Init->getType();
+ llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType);
+
+ // Strip off a bitcast if we got one back.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+ // all zero index gep.
+ CE->getOpcode() == llvm::Instruction::GetElementPtr);
+ Entry = CE->getOperand(0);
+ }
+
+ // Entry is now either a Function or GlobalVariable.
+ llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Entry);
+
+ // We have a definition after a declaration with the wrong type.
+ // We must make a new GlobalVariable* and update everything that used OldGV
+ // (a declaration or tentative definition) with the new GlobalVariable*
+ // (which will be a definition).
+ //
+ // This happens if there is a prototype for a global (e.g.
+ // "extern int x[];") and then a definition of a different type (e.g.
+ // "int x[10];"). This also happens when an initializer has a different type
+ // from the type of the global (this happens with unions).
+ if (GV == 0 ||
+ GV->getType()->getElementType() != InitType ||
+ GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) {
+
+ // Move the old entry aside so that we'll create a new one.
+ Entry->setName(llvm::StringRef());
+
+ // Make a new global with the correct type, this is now guaranteed to work.
+ GV = cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, InitType));
+
+ // Replace all uses of the old global with the new global
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(GV, Entry->getType());
+ Entry->replaceAllUsesWith(NewPtrForOldDecl);
+
+ // Erase the old global, since it is no longer used.
+ cast<llvm::GlobalValue>(Entry)->eraseFromParent();
+ }
+
+ if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
+ SourceManager &SM = Context.getSourceManager();
+ AddAnnotation(EmitAnnotateAttr(GV, AA,
+ SM.getInstantiationLineNumber(D->getLocation())));
+ }
+
+ GV->setInitializer(Init);
+
+ // If it is safe to mark the global 'constant', do so now.
+ GV->setConstant(false);
+ if (!NonConstInit && DeclIsConstantGlobal(Context, D))
+ GV->setConstant(true);
+
+ GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
+
+ // Set the llvm linkage type as appropriate.
+ llvm::GlobalValue::LinkageTypes Linkage =
+ GetLLVMLinkageVarDefinition(D, GV);
+ GV->setLinkage(Linkage);
+ if (Linkage == llvm::GlobalVariable::CommonLinkage)
+ // common vars aren't constant even if declared const.
+ GV->setConstant(false);
+
+ SetCommonAttributes(D, GV);
+
+ // Emit the initializer function if necessary.
+ if (NonConstInit)
+ EmitCXXGlobalVarDeclInitFunc(D, GV);
+
+ // Emit global variable debug information.
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(D->getLocation());
+ DI->EmitGlobalVariable(GV, D);
+ }
+}
+
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
+ llvm::GlobalVariable *GV) {
+ GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
+ if (Linkage == GVA_Internal)
+ return llvm::Function::InternalLinkage;
+ else if (D->hasAttr<DLLImportAttr>())
+ return llvm::Function::DLLImportLinkage;
+ else if (D->hasAttr<DLLExportAttr>())
+ return llvm::Function::DLLExportLinkage;
+ else if (D->hasAttr<WeakAttr>()) {
+ if (GV->isConstant())
+ return llvm::GlobalVariable::WeakODRLinkage;
+ else
+ return llvm::GlobalVariable::WeakAnyLinkage;
+ } else if (Linkage == GVA_TemplateInstantiation ||
+ Linkage == GVA_ExplicitTemplateInstantiation)
+ // FIXME: It seems like we can provide more specific linkage here
+ // (LinkOnceODR, WeakODR).
+ return llvm::GlobalVariable::WeakAnyLinkage;
+ else if (!getLangOptions().CPlusPlus &&
+ ((!CodeGenOpts.NoCommon && !D->getAttr<NoCommonAttr>()) ||
+ D->getAttr<CommonAttr>()) &&
+ !D->hasExternalStorage() && !D->getInit() &&
+ !D->getAttr<SectionAttr>() && !D->isThreadSpecified()) {
+ // Thread local vars aren't considered common linkage.
+ return llvm::GlobalVariable::CommonLinkage;
+ }
+ return llvm::GlobalVariable::ExternalLinkage;
+}
+
+/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we
+/// implement a function with no prototype, e.g. "int foo() {}". If there are
+/// existing call uses of the old function in the module, this adjusts them to
+/// call the new function directly.
+///
+/// This is not just a cleanup: the always_inline pass requires direct calls to
+/// functions to be able to inline them. If there is a bitcast in the way, it
+/// won't inline them. Instcombine normally deletes these calls, but it isn't
+/// run at -O0.
+static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
+ llvm::Function *NewFn) {
+ // If we're redefining a global as a function, don't transform it.
+ llvm::Function *OldFn = dyn_cast<llvm::Function>(Old);
+ if (OldFn == 0) return;
+
+ const llvm::Type *NewRetTy = NewFn->getReturnType();
+ llvm::SmallVector<llvm::Value*, 4> ArgList;
+
+ for (llvm::Value::use_iterator UI = OldFn->use_begin(), E = OldFn->use_end();
+ UI != E; ) {
+ // TODO: Do invokes ever occur in C code? If so, we should handle them too.
+ llvm::Value::use_iterator I = UI++; // Increment before the CI is erased.
+ llvm::CallInst *CI = dyn_cast<llvm::CallInst>(*I);
+ if (!CI) continue; // FIXME: when we allow Invoke, just do CallSite CS(*I)
+ llvm::CallSite CS(CI);
+ if (!CI || !CS.isCallee(I)) continue;
+
+ // If the return types don't match exactly, and if the call isn't dead, then
+ // we can't transform this call.
+ if (CI->getType() != NewRetTy && !CI->use_empty())
+ continue;
+
+ // If the function was passed too few arguments, don't transform. If extra
+ // arguments were passed, we silently drop them. If any of the types
+ // mismatch, we don't transform.
+ unsigned ArgNo = 0;
+ bool DontTransform = false;
+ for (llvm::Function::arg_iterator AI = NewFn->arg_begin(),
+ E = NewFn->arg_end(); AI != E; ++AI, ++ArgNo) {
+ if (CS.arg_size() == ArgNo ||
+ CS.getArgument(ArgNo)->getType() != AI->getType()) {
+ DontTransform = true;
+ break;
+ }
+ }
+ if (DontTransform)
+ continue;
+
+ // Okay, we can transform this. Create the new call instruction and copy
+ // over the required information.
+ ArgList.append(CS.arg_begin(), CS.arg_begin() + ArgNo);
+ llvm::CallInst *NewCall = llvm::CallInst::Create(NewFn, ArgList.begin(),
+ ArgList.end(), "", CI);
+ ArgList.clear();
+ if (!NewCall->getType()->isVoidTy())
+ NewCall->takeName(CI);
+ NewCall->setAttributes(CI->getAttributes());
+ NewCall->setCallingConv(CI->getCallingConv());
+
+ // Finally, remove the old call, replacing any uses with the new one.
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(NewCall);
+
+ // Copy debug location attached to CI.
+ if (!CI->getDebugLoc().isUnknown())
+ NewCall->setDebugLoc(CI->getDebugLoc());
+ CI->eraseFromParent();
+ }
+}
+
+
+void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
+ const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
+ const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
+ // Get or create the prototype for the function.
+ llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
+
+ // Strip off a bitcast if we got one back.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ assert(CE->getOpcode() == llvm::Instruction::BitCast);
+ Entry = CE->getOperand(0);
+ }
+
+
+ if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != Ty) {
+ llvm::GlobalValue *OldFn = cast<llvm::GlobalValue>(Entry);
+
+ // If the types mismatch then we have to rewrite the definition.
+ assert(OldFn->isDeclaration() &&
+ "Shouldn't replace non-declaration");
+
+ // F is the Function* for the one with the wrong type, we must make a new
+ // Function* and update everything that used F (a declaration) with the new
+ // Function* (which will be a definition).
+ //
+ // This happens if there is a prototype for a function
+ // (e.g. "int f()") and then a definition of a different type
+ // (e.g. "int f(int x)"). Move the old function aside so that it
+ // doesn't interfere with GetAddrOfFunction.
+ OldFn->setName(llvm::StringRef());
+ llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
+
+ // If this is an implementation of a function without a prototype, try to
+ // replace any existing uses of the function (which may be calls) with uses
+ // of the new function
+ if (D->getType()->isFunctionNoProtoType()) {
+ ReplaceUsesOfNonProtoTypeWithRealFunction(OldFn, NewFn);
+ OldFn->removeDeadConstantUsers();
+ }
+
+ // Replace uses of F with the Function we will endow with a body.
+ if (!Entry->use_empty()) {
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
+ Entry->replaceAllUsesWith(NewPtrForOldDecl);
+ }
+
+ // Ok, delete the old function now, which is dead.
+ OldFn->eraseFromParent();
+
+ Entry = NewFn;
+ }
+
+ // We need to set linkage and visibility on the function before
+ // generating code for it because various parts of IR generation
+ // want to propagate this information down (e.g. to local static
+ // declarations).
+ llvm::Function *Fn = cast<llvm::Function>(Entry);
+ setFunctionLinkage(D, Fn);
+
+ // FIXME: this is redundant with part of SetFunctionDefinitionAttributes
+ setGlobalVisibility(Fn, D);
+
+ CodeGenFunction(*this).GenerateCode(D, Fn);
+
+ SetFunctionDefinitionAttributes(D, Fn);
+ SetLLVMFunctionAttributesForDefinition(D, Fn);
+
+ if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
+ AddGlobalCtor(Fn, CA->getPriority());
+ if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
+ AddGlobalDtor(Fn, DA->getPriority());
+}
+
+void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
+ const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
+ const AliasAttr *AA = D->getAttr<AliasAttr>();
+ assert(AA && "Not an alias?");
+
+ llvm::StringRef MangledName = getMangledName(GD);
+
+ // If there is a definition in the module, then it wins over the alias.
+ // This is dubious, but allow it to be safe. Just ignore the alias.
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration())
+ return;
+
+ const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
+
+ // Create a reference to the named value. This ensures that it is emitted
+ // if a deferred decl.
+ llvm::Constant *Aliasee;
+ if (isa<llvm::FunctionType>(DeclTy))
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl(),
+ /*ForVTable=*/false);
+ else
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
+ llvm::PointerType::getUnqual(DeclTy), 0);
+
+ // Create the new alias itself, but don't set a name yet.
+ llvm::GlobalValue *GA =
+ new llvm::GlobalAlias(Aliasee->getType(),
+ llvm::Function::ExternalLinkage,
+ "", Aliasee, &getModule());
+
+ if (Entry) {
+ assert(Entry->isDeclaration());
+
+ // If there is a declaration in the module, then we had an extern followed
+ // by the alias, as in:
+ // extern int test6();
+ // ...
+ // int test6() __attribute__((alias("test7")));
+ //
+ // Remove it and replace uses of it with the alias.
+ GA->takeName(Entry);
+
+ Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA,
+ Entry->getType()));
+ Entry->eraseFromParent();
+ } else {
+ GA->setName(MangledName);
+ }
+
+ // Set attributes which are particular to an alias; this is a
+ // specialization of the attributes which may be set on a global
+ // variable/function.
+ if (D->hasAttr<DLLExportAttr>()) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // The dllexport attribute is ignored for undefined symbols.
+ if (FD->hasBody())
+ GA->setLinkage(llvm::Function::DLLExportLinkage);
+ } else {
+ GA->setLinkage(llvm::Function::DLLExportLinkage);
+ }
+ } else if (D->hasAttr<WeakAttr>() ||
+ D->hasAttr<WeakRefAttr>() ||
+ D->hasAttr<WeakImportAttr>()) {
+ GA->setLinkage(llvm::Function::WeakAnyLinkage);
+ }
+
+ SetCommonAttributes(D, GA);
+}
+
+/// getBuiltinLibFunction - Given a builtin id for a function like
+/// "__builtin_fabsf", return a Function* for "fabsf".
+llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
+ unsigned BuiltinID) {
+ assert((Context.BuiltinInfo.isLibFunction(BuiltinID) ||
+ Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) &&
+ "isn't a lib fn");
+
+ // Get the name, skip over the __builtin_ prefix (if necessary).
+ const char *Name = Context.BuiltinInfo.GetName(BuiltinID);
+ if (Context.BuiltinInfo.isLibFunction(BuiltinID))
+ Name += 10;
+
+ const llvm::FunctionType *Ty =
+ cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType()));
+
+ return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD), /*ForVTable=*/false);
+}
+
+llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys,
+ unsigned NumTys) {
+ return llvm::Intrinsic::getDeclaration(&getModule(),
+ (llvm::Intrinsic::ID)IID, Tys, NumTys);
+}
+
+static llvm::StringMapEntry<llvm::Constant*> &
+GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
+ const StringLiteral *Literal,
+ bool TargetIsLSB,
+ bool &IsUTF16,
+ unsigned &StringLength) {
+ llvm::StringRef String = Literal->getString();
+ unsigned NumBytes = String.size();
+
+ // Check for simple case.
+ if (!Literal->containsNonAsciiOrNull()) {
+ StringLength = NumBytes;
+ return Map.GetOrCreateValue(String);
+ }
+
+ // Otherwise, convert the UTF8 literals into a byte string.
+ llvm::SmallVector<UTF16, 128> ToBuf(NumBytes);
+ const UTF8 *FromPtr = (UTF8 *)String.data();
+ UTF16 *ToPtr = &ToBuf[0];
+
+ (void)ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
+ &ToPtr, ToPtr + NumBytes,
+ strictConversion);
+
+ // ConvertUTF8toUTF16 returns the length in ToPtr.
+ StringLength = ToPtr - &ToBuf[0];
+
+ // Render the UTF-16 string into a byte array and convert to the target byte
+ // order.
+ //
+ // FIXME: This isn't something we should need to do here.
+ llvm::SmallString<128> AsBytes;
+ AsBytes.reserve(StringLength * 2);
+ for (unsigned i = 0; i != StringLength; ++i) {
+ unsigned short Val = ToBuf[i];
+ if (TargetIsLSB) {
+ AsBytes.push_back(Val & 0xFF);
+ AsBytes.push_back(Val >> 8);
+ } else {
+ AsBytes.push_back(Val >> 8);
+ AsBytes.push_back(Val & 0xFF);
+ }
+ }
+ // Append one extra null character, the second is automatically added by our
+ // caller.
+ AsBytes.push_back(0);
+
+ IsUTF16 = true;
+ return Map.GetOrCreateValue(llvm::StringRef(AsBytes.data(), AsBytes.size()));
+}
+
+llvm::Constant *
+CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
+ unsigned StringLength = 0;
+ bool isUTF16 = false;
+ llvm::StringMapEntry<llvm::Constant*> &Entry =
+ GetConstantCFStringEntry(CFConstantStringMap, Literal,
+ getTargetData().isLittleEndian(),
+ isUTF16, StringLength);
+
+ if (llvm::Constant *C = Entry.getValue())
+ return C;
+
+ llvm::Constant *Zero =
+ llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext));
+ llvm::Constant *Zeros[] = { Zero, Zero };
+
+ // If we don't already have it, get __CFConstantStringClassReference.
+ if (!CFConstantStringClassRef) {
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+ Ty = llvm::ArrayType::get(Ty, 0);
+ llvm::Constant *GV = CreateRuntimeVariable(Ty,
+ "__CFConstantStringClassReference");
+ // Decay array -> ptr
+ CFConstantStringClassRef =
+ llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2);
+ }
+
+ QualType CFTy = getContext().getCFConstantStringType();
+
+ const llvm::StructType *STy =
+ cast<llvm::StructType>(getTypes().ConvertType(CFTy));
+
+ std::vector<llvm::Constant*> Fields(4);
+
+ // Class pointer.
+ Fields[0] = CFConstantStringClassRef;
+
+ // Flags.
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
+ Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0) :
+ llvm::ConstantInt::get(Ty, 0x07C8);
+
+ // String pointer.
+ llvm::Constant *C = llvm::ConstantArray::get(VMContext, Entry.getKey().str());
+
+ llvm::GlobalValue::LinkageTypes Linkage;
+ bool isConstant;
+ if (isUTF16) {
+ // FIXME: why do utf strings get "_" labels instead of "L" labels?
+ Linkage = llvm::GlobalValue::InternalLinkage;
+ // Note: -fwritable-strings doesn't make unicode CFStrings writable, but
+ // does make plain ascii ones writable.
+ isConstant = true;
+ } else {
+ Linkage = llvm::GlobalValue::PrivateLinkage;
+ isConstant = !Features.WritableStrings;
+ }
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C,
+ ".str");
+ GV->setUnnamedAddr(true);
+ if (isUTF16) {
+ CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy);
+ GV->setAlignment(Align.getQuantity());
+ }
+ Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2);
+
+ // String length.
+ Ty = getTypes().ConvertType(getContext().LongTy);
+ Fields[3] = llvm::ConstantInt::get(Ty, StringLength);
+
+ // The struct.
+ C = llvm::ConstantStruct::get(STy, Fields);
+ GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
+ llvm::GlobalVariable::PrivateLinkage, C,
+ "_unnamed_cfstring_");
+ if (const char *Sect = getContext().Target.getCFStringSection())
+ GV->setSection(Sect);
+ Entry.setValue(GV);
+
+ return GV;
+}
+
+llvm::Constant *
+CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
+ unsigned StringLength = 0;
+ bool isUTF16 = false;
+ llvm::StringMapEntry<llvm::Constant*> &Entry =
+ GetConstantCFStringEntry(CFConstantStringMap, Literal,
+ getTargetData().isLittleEndian(),
+ isUTF16, StringLength);
+
+ if (llvm::Constant *C = Entry.getValue())
+ return C;
+
+ llvm::Constant *Zero =
+ llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext));
+ llvm::Constant *Zeros[] = { Zero, Zero };
+
+ // If we don't already have it, get _NSConstantStringClassReference.
+ if (!ConstantStringClassRef) {
+ std::string StringClass(getLangOptions().ObjCConstantStringClass);
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+ Ty = llvm::ArrayType::get(Ty, 0);
+ llvm::Constant *GV;
+ if (StringClass.empty())
+ GV = CreateRuntimeVariable(Ty,
+ Features.ObjCNonFragileABI ?
+ "OBJC_CLASS_$_NSConstantString" :
+ "_NSConstantStringClassReference");
+ else {
+ std::string str;
+ if (Features.ObjCNonFragileABI)
+ str = "OBJC_CLASS_$_" + StringClass;
+ else
+ str = "_" + StringClass + "ClassReference";
+ GV = CreateRuntimeVariable(Ty, str);
+ }
+ // Decay array -> ptr
+ ConstantStringClassRef =
+ llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2);
+ }
+
+ QualType NSTy = getContext().getNSConstantStringType();
+
+ const llvm::StructType *STy =
+ cast<llvm::StructType>(getTypes().ConvertType(NSTy));
+
+ std::vector<llvm::Constant*> Fields(3);
+
+ // Class pointer.
+ Fields[0] = ConstantStringClassRef;
+
+ // String pointer.
+ llvm::Constant *C = llvm::ConstantArray::get(VMContext, Entry.getKey().str());
+
+ llvm::GlobalValue::LinkageTypes Linkage;
+ bool isConstant;
+ if (isUTF16) {
+ // FIXME: why do utf strings get "_" labels instead of "L" labels?
+ Linkage = llvm::GlobalValue::InternalLinkage;
+ // Note: -fwritable-strings doesn't make unicode NSStrings writable, but
+ // does make plain ascii ones writable.
+ isConstant = true;
+ } else {
+ Linkage = llvm::GlobalValue::PrivateLinkage;
+ isConstant = !Features.WritableStrings;
+ }
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C,
+ ".str");
+ GV->setUnnamedAddr(true);
+ if (isUTF16) {
+ CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy);
+ GV->setAlignment(Align.getQuantity());
+ }
+ Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2);
+
+ // String length.
+ const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
+ Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
+
+ // The struct.
+ C = llvm::ConstantStruct::get(STy, Fields);
+ GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
+ llvm::GlobalVariable::PrivateLinkage, C,
+ "_unnamed_nsstring_");
+ // FIXME. Fix section.
+ if (const char *Sect =
+ Features.ObjCNonFragileABI
+ ? getContext().Target.getNSStringNonFragileABISection()
+ : getContext().Target.getNSStringSection())
+ GV->setSection(Sect);
+ Entry.setValue(GV);
+
+ return GV;
+}
+
+/// GetStringForStringLiteral - Return the appropriate bytes for a
+/// string literal, properly padded to match the literal type.
+std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) {
+ const ASTContext &Context = getContext();
+ const ConstantArrayType *CAT =
+ Context.getAsConstantArrayType(E->getType());
+ assert(CAT && "String isn't pointer or array!");
+
+ // Resize the string to the right size.
+ uint64_t RealLen = CAT->getSize().getZExtValue();
+
+ if (E->isWide())
+ RealLen *= Context.Target.getWCharWidth() / Context.getCharWidth();
+
+ std::string Str = E->getString().str();
+ Str.resize(RealLen, '\0');
+
+ return Str;
+}
+
+/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
+/// constant array for the given string literal.
+llvm::Constant *
+CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
+ // FIXME: This can be more efficient.
+ // FIXME: We shouldn't need to bitcast the constant in the wide string case.
+ llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S));
+ if (S->isWide()) {
+ llvm::Type *DestTy =
+ llvm::PointerType::getUnqual(getTypes().ConvertType(S->getType()));
+ C = llvm::ConstantExpr::getBitCast(C, DestTy);
+ }
+ return C;
+}
+
+/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
+/// array for the given ObjCEncodeExpr node.
+llvm::Constant *
+CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
+ std::string Str;
+ getContext().getObjCEncodingForType(E->getEncodedType(), Str);
+
+ return GetAddrOfConstantCString(Str);
+}
+
+
+/// GenerateWritableString -- Creates storage for a string literal.
+static llvm::Constant *GenerateStringLiteral(const std::string &str,
+ bool constant,
+ CodeGenModule &CGM,
+ const char *GlobalName) {
+ // Create Constant for this string literal. Don't add a '\0'.
+ llvm::Constant *C =
+ llvm::ConstantArray::get(CGM.getLLVMContext(), str, false);
+
+ // Create a global variable for this string
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), C->getType(), constant,
+ llvm::GlobalValue::PrivateLinkage,
+ C, GlobalName);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
+
+/// GetAddrOfConstantString - Returns a pointer to a character array
+/// containing the literal. This contents are exactly that of the
+/// given string, i.e. it will not be null terminated automatically;
+/// see GetAddrOfConstantCString. Note that whether the result is
+/// actually a pointer to an LLVM constant depends on
+/// Feature.WriteableStrings.
+///
+/// The result has pointer to array type.
+llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str,
+ const char *GlobalName) {
+ bool IsConstant = !Features.WritableStrings;
+
+ // Get the default prefix if a name wasn't specified.
+ if (!GlobalName)
+ GlobalName = ".str";
+
+ // Don't share any string literals if strings aren't constant.
+ if (!IsConstant)
+ return GenerateStringLiteral(str, false, *this, GlobalName);
+
+ llvm::StringMapEntry<llvm::Constant *> &Entry =
+ ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
+
+ if (Entry.getValue())
+ return Entry.getValue();
+
+ // Create a global variable for this.
+ llvm::Constant *C = GenerateStringLiteral(str, true, *this, GlobalName);
+ Entry.setValue(C);
+ return C;
+}
+
+/// GetAddrOfConstantCString - Returns a pointer to a character
+/// array containing the literal and a terminating '\-'
+/// character. The result has pointer to array type.
+llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str,
+ const char *GlobalName){
+ return GetAddrOfConstantString(str + '\0', GlobalName);
+}
+
+/// EmitObjCPropertyImplementations - Emit information for synthesized
+/// properties for an implementation.
+void CodeGenModule::EmitObjCPropertyImplementations(const
+ ObjCImplementationDecl *D) {
+ for (ObjCImplementationDecl::propimpl_iterator
+ i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
+ ObjCPropertyImplDecl *PID = *i;
+
+ // Dynamic is just for type-checking.
+ if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
+ ObjCPropertyDecl *PD = PID->getPropertyDecl();
+
+ // Determine which methods need to be implemented, some may have
+ // been overridden. Note that ::isSynthesized is not the method
+ // we want, that just indicates if the decl came from a
+ // property. What we want to know is if the method is defined in
+ // this implementation.
+ if (!D->getInstanceMethod(PD->getGetterName()))
+ CodeGenFunction(*this).GenerateObjCGetter(
+ const_cast<ObjCImplementationDecl *>(D), PID);
+ if (!PD->isReadOnly() &&
+ !D->getInstanceMethod(PD->getSetterName()))
+ CodeGenFunction(*this).GenerateObjCSetter(
+ const_cast<ObjCImplementationDecl *>(D), PID);
+ }
+ }
+}
+
+/// EmitObjCIvarInitializations - Emit information for ivar initialization
+/// for an implementation.
+void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
+ if (!Features.NeXTRuntime || D->getNumIvarInitializers() == 0)
+ return;
+ DeclContext* DC = const_cast<DeclContext*>(dyn_cast<DeclContext>(D));
+ assert(DC && "EmitObjCIvarInitializations - null DeclContext");
+ IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct");
+ Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
+ ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(getContext(),
+ D->getLocation(),
+ D->getLocation(), cxxSelector,
+ getContext().VoidTy, 0,
+ DC, true, false, true, false,
+ ObjCMethodDecl::Required);
+ D->addInstanceMethod(DTORMethod);
+ CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
+
+ II = &getContext().Idents.get(".cxx_construct");
+ cxxSelector = getContext().Selectors.getSelector(0, &II);
+ // The constructor returns 'self'.
+ ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
+ D->getLocation(),
+ D->getLocation(), cxxSelector,
+ getContext().getObjCIdType(), 0,
+ DC, true, false, true, false,
+ ObjCMethodDecl::Required);
+ D->addInstanceMethod(CTORMethod);
+ CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
+
+
+}
+
+/// EmitNamespace - Emit all declarations in a namespace.
+void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
+ for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end();
+ I != E; ++I)
+ EmitTopLevelDecl(*I);
+}
+
+// EmitLinkageSpec - Emit all declarations in a linkage spec.
+void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
+ if (LSD->getLanguage() != LinkageSpecDecl::lang_c &&
+ LSD->getLanguage() != LinkageSpecDecl::lang_cxx) {
+ ErrorUnsupported(LSD, "linkage spec");
+ return;
+ }
+
+ for (RecordDecl::decl_iterator I = LSD->decls_begin(), E = LSD->decls_end();
+ I != E; ++I)
+ EmitTopLevelDecl(*I);
+}
+
+/// EmitTopLevelDecl - Emit code for a single top level declaration.
+void CodeGenModule::EmitTopLevelDecl(Decl *D) {
+ // If an error has occurred, stop code generation, but continue
+ // parsing and semantic analysis (to ensure all warnings and errors
+ // are emitted).
+ if (Diags.hasErrorOccurred())
+ return;
+
+ // Ignore dependent declarations.
+ if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
+ return;
+
+ switch (D->getKind()) {
+ case Decl::CXXConversion:
+ case Decl::CXXMethod:
+ case Decl::Function:
+ // Skip function templates
+ if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate())
+ return;
+
+ EmitGlobal(cast<FunctionDecl>(D));
+ break;
+
+ case Decl::Var:
+ EmitGlobal(cast<VarDecl>(D));
+ break;
+
+ // C++ Decls
+ case Decl::Namespace:
+ EmitNamespace(cast<NamespaceDecl>(D));
+ break;
+ // No code generation needed.
+ case Decl::UsingShadow:
+ case Decl::Using:
+ case Decl::UsingDirective:
+ case Decl::ClassTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::NamespaceAlias:
+ break;
+ case Decl::CXXConstructor:
+ // Skip function templates
+ if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate())
+ return;
+
+ EmitCXXConstructors(cast<CXXConstructorDecl>(D));
+ break;
+ case Decl::CXXDestructor:
+ EmitCXXDestructors(cast<CXXDestructorDecl>(D));
+ break;
+
+ case Decl::StaticAssert:
+ // Nothing to do.
+ break;
+
+ // Objective-C Decls
+
+ // Forward declarations, no (immediate) code generation.
+ case Decl::ObjCClass:
+ case Decl::ObjCForwardProtocol:
+ case Decl::ObjCInterface:
+ break;
+
+ case Decl::ObjCCategory: {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
+ if (CD->IsClassExtension() && CD->hasSynthBitfield())
+ Context.ResetObjCLayout(CD->getClassInterface());
+ break;
+ }
+
+
+ case Decl::ObjCProtocol:
+ Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
+ break;
+
+ case Decl::ObjCCategoryImpl:
+ // Categories have properties but don't support synthesize so we
+ // can ignore them here.
+ Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
+ break;
+
+ case Decl::ObjCImplementation: {
+ ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+ if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
+ Context.ResetObjCLayout(OMD->getClassInterface());
+ EmitObjCPropertyImplementations(OMD);
+ EmitObjCIvarInitializations(OMD);
+ Runtime->GenerateClass(OMD);
+ break;
+ }
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
+ // If this is not a prototype, emit the body.
+ if (OMD->getBody())
+ CodeGenFunction(*this).GenerateObjCMethod(OMD);
+ break;
+ }
+ case Decl::ObjCCompatibleAlias:
+ // compatibility-alias is a directive and has no code gen.
+ break;
+
+ case Decl::LinkageSpec:
+ EmitLinkageSpec(cast<LinkageSpecDecl>(D));
+ break;
+
+ case Decl::FileScopeAsm: {
+ FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
+ llvm::StringRef AsmString = AD->getAsmString()->getString();
+
+ const std::string &S = getModule().getModuleInlineAsm();
+ if (S.empty())
+ getModule().setModuleInlineAsm(AsmString);
+ else
+ getModule().setModuleInlineAsm(S + '\n' + AsmString.str());
+ break;
+ }
+
+ default:
+ // Make sure we handled everything we should, every other kind is a
+ // non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind
+ // function. Need to recode Decl::Kind to do that easily.
+ assert(isa<TypeDecl>(D) && "Unsupported decl kind");
+ }
+}
+
+/// Turns the given pointer into a constant.
+static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
+ const void *Ptr) {
+ uintptr_t PtrInt = reinterpret_cast<uintptr_t>(Ptr);
+ const llvm::Type *i64 = llvm::Type::getInt64Ty(Context);
+ return llvm::ConstantInt::get(i64, PtrInt);
+}
+
+static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
+ llvm::NamedMDNode *&GlobalMetadata,
+ GlobalDecl D,
+ llvm::GlobalValue *Addr) {
+ if (!GlobalMetadata)
+ GlobalMetadata =
+ CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");
+
+ // TODO: should we report variant information for ctors/dtors?
+ llvm::Value *Ops[] = {
+ Addr,
+ GetPointerConstant(CGM.getLLVMContext(), D.getDecl())
+ };
+ GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops, 2));
+}
+
+/// Emits metadata nodes associating all the global values in the
+/// current module with the Decls they came from. This is useful for
+/// projects using IR gen as a subroutine.
+///
+/// Since there's currently no way to associate an MDNode directly
+/// with an llvm::GlobalValue, we create a global named metadata
+/// with the name 'clang.global.decl.ptrs'.
+void CodeGenModule::EmitDeclMetadata() {
+ llvm::NamedMDNode *GlobalMetadata = 0;
+
+ // StaticLocalDeclMap
+ for (llvm::DenseMap<GlobalDecl,llvm::StringRef>::iterator
+ I = MangledDeclNames.begin(), E = MangledDeclNames.end();
+ I != E; ++I) {
+ llvm::GlobalValue *Addr = getModule().getNamedValue(I->second);
+ EmitGlobalDeclMetadata(*this, GlobalMetadata, I->first, Addr);
+ }
+}
+
+/// Emits metadata nodes for all the local variables in the current
+/// function.
+void CodeGenFunction::EmitDeclMetadata() {
+ if (LocalDeclMap.empty()) return;
+
+ llvm::LLVMContext &Context = getLLVMContext();
+
+ // Find the unique metadata ID for this name.
+ unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr");
+
+ llvm::NamedMDNode *GlobalMetadata = 0;
+
+ for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
+ I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
+ const Decl *D = I->first;
+ llvm::Value *Addr = I->second;
+
+ if (llvm::AllocaInst *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
+ llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
+ Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, &DAddr, 1));
+ } else if (llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
+ GlobalDecl GD = GlobalDecl(cast<VarDecl>(D));
+ EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV);
+ }
+ }
+}
+
+///@name Custom Runtime Function Interfaces
+///@{
+//
+// FIXME: These can be eliminated once we can have clients just get the required
+// AST nodes from the builtin tables.
+
+llvm::Constant *CodeGenModule::getBlockObjectDispose() {
+ if (BlockObjectDispose)
+ return BlockObjectDispose;
+
+ // If we saw an explicit decl, use that.
+ if (BlockObjectDisposeDecl) {
+ return BlockObjectDispose = GetAddrOfFunction(
+ BlockObjectDisposeDecl,
+ getTypes().GetFunctionType(BlockObjectDisposeDecl));
+ }
+
+ // Otherwise construct the function by hand.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ return BlockObjectDispose =
+ CreateRuntimeFunction(FTy, "_Block_object_dispose");
+}
+
+llvm::Constant *CodeGenModule::getBlockObjectAssign() {
+ if (BlockObjectAssign)
+ return BlockObjectAssign;
+
+ // If we saw an explicit decl, use that.
+ if (BlockObjectAssignDecl) {
+ return BlockObjectAssign = GetAddrOfFunction(
+ BlockObjectAssignDecl,
+ getTypes().GetFunctionType(BlockObjectAssignDecl));
+ }
+
+ // Otherwise construct the function by hand.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(Int8PtrTy);
+ ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ return BlockObjectAssign =
+ CreateRuntimeFunction(FTy, "_Block_object_assign");
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
+ if (NSConcreteGlobalBlock)
+ return NSConcreteGlobalBlock;
+
+ // If we saw an explicit decl, use that.
+ if (NSConcreteGlobalBlockDecl) {
+ return NSConcreteGlobalBlock = GetAddrOfGlobalVar(
+ NSConcreteGlobalBlockDecl,
+ getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType()));
+ }
+
+ // Otherwise construct the variable by hand.
+ return NSConcreteGlobalBlock =
+ CreateRuntimeVariable(Int8PtrTy, "_NSConcreteGlobalBlock");
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
+ if (NSConcreteStackBlock)
+ return NSConcreteStackBlock;
+
+ // If we saw an explicit decl, use that.
+ if (NSConcreteStackBlockDecl) {
+ return NSConcreteStackBlock = GetAddrOfGlobalVar(
+ NSConcreteStackBlockDecl,
+ getTypes().ConvertType(NSConcreteStackBlockDecl->getType()));
+ }
+
+ // Otherwise construct the variable by hand.
+ return NSConcreteStackBlock =
+ CreateRuntimeVariable(Int8PtrTy, "_NSConcreteStackBlock");
+}
+
+///@}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
new file mode 100644
index 0000000..b6bd37c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -0,0 +1,720 @@
+//===--- CodeGenModule.h - Per-Module state for LLVM CodeGen ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for llvm translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CODEGENMODULE_H
+#define CLANG_CODEGEN_CODEGENMODULE_H
+
+#include "clang/Basic/ABI.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Mangle.h"
+#include "CGCall.h"
+#include "CGVTables.h"
+#include "CodeGenTypes.h"
+#include "GlobalDecl.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ValueHandle.h"
+
+namespace llvm {
+ class Module;
+ class Constant;
+ class Function;
+ class GlobalValue;
+ class TargetData;
+ class FunctionType;
+ class LLVMContext;
+}
+
+namespace clang {
+ class TargetCodeGenInfo;
+ class ASTContext;
+ class FunctionDecl;
+ class IdentifierInfo;
+ class ObjCMethodDecl;
+ class ObjCImplementationDecl;
+ class ObjCCategoryImplDecl;
+ class ObjCProtocolDecl;
+ class ObjCEncodeExpr;
+ class BlockExpr;
+ class CharUnits;
+ class Decl;
+ class Expr;
+ class Stmt;
+ class StringLiteral;
+ class NamedDecl;
+ class ValueDecl;
+ class VarDecl;
+ class LangOptions;
+ class CodeGenOptions;
+ class Diagnostic;
+ class AnnotateAttr;
+ class CXXDestructorDecl;
+ class MangleBuffer;
+
+namespace CodeGen {
+
+ class CodeGenFunction;
+ class CodeGenTBAA;
+ class CGCXXABI;
+ class CGDebugInfo;
+ class CGObjCRuntime;
+ class BlockFieldFlags;
+
+ struct OrderGlobalInits {
+ unsigned int priority;
+ unsigned int lex_order;
+ OrderGlobalInits(unsigned int p, unsigned int l)
+ : priority(p), lex_order(l) {}
+
+ bool operator==(const OrderGlobalInits &RHS) const {
+ return priority == RHS.priority &&
+ lex_order == RHS.lex_order;
+ }
+
+ bool operator<(const OrderGlobalInits &RHS) const {
+ if (priority < RHS.priority)
+ return true;
+
+ return priority == RHS.priority && lex_order < RHS.lex_order;
+ }
+ };
+
+ struct CodeGenTypeCache {
+ /// i8, i32, and i64
+ const llvm::IntegerType *Int8Ty, *Int32Ty, *Int64Ty;
+
+ /// int
+ const llvm::IntegerType *IntTy;
+
+ /// intptr_t and size_t, which we assume are the same
+ union {
+ const llvm::IntegerType *IntPtrTy;
+ const llvm::IntegerType *SizeTy;
+ };
+
+ /// void* in address space 0
+ union {
+ const llvm::PointerType *VoidPtrTy;
+ const llvm::PointerType *Int8PtrTy;
+ };
+
+ /// void** in address space 0
+ union {
+ const llvm::PointerType *VoidPtrPtrTy;
+ const llvm::PointerType *Int8PtrPtrTy;
+ };
+
+ /// The width of an address-zero pointer.
+ unsigned char PointerWidthInBits;
+ };
+
+/// CodeGenModule - This class organizes the cross-function state that is used
+/// while generating LLVM code.
+class CodeGenModule : public CodeGenTypeCache {
+ CodeGenModule(const CodeGenModule&); // DO NOT IMPLEMENT
+ void operator=(const CodeGenModule&); // DO NOT IMPLEMENT
+
+ typedef std::vector<std::pair<llvm::Constant*, int> > CtorList;
+
+ ASTContext &Context;
+ const LangOptions &Features;
+ const CodeGenOptions &CodeGenOpts;
+ llvm::Module &TheModule;
+ const llvm::TargetData &TheTargetData;
+ mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
+ Diagnostic &Diags;
+ CGCXXABI &ABI;
+ CodeGenTypes Types;
+ CodeGenTBAA *TBAA;
+
+ /// VTables - Holds information about C++ vtables.
+ CodeGenVTables VTables;
+ friend class CodeGenVTables;
+
+ CGObjCRuntime* Runtime;
+ CGDebugInfo* DebugInfo;
+
+ // WeakRefReferences - A set of references that have only been seen via
+ // a weakref so far. This is used to remove the weak of the reference if we ever
+ // see a direct reference or a definition.
+ llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences;
+
+ /// DeferredDecls - This contains all the decls which have definitions but
+ /// which are deferred for emission and therefore should only be output if
+ /// they are actually used. If a decl is in this, then it is known to have
+ /// not been referenced yet.
+ llvm::StringMap<GlobalDecl> DeferredDecls;
+
+ /// DeferredDeclsToEmit - This is a list of deferred decls which we have seen
+ /// that *are* actually referenced. These get code generated when the module
+ /// is done.
+ std::vector<GlobalDecl> DeferredDeclsToEmit;
+
+ /// LLVMUsed - List of global values which are required to be
+ /// present in the object file; bitcast to i8*. This is used for
+ /// forcing visibility of symbols which may otherwise be optimized
+ /// out.
+ std::vector<llvm::WeakVH> LLVMUsed;
+
+ /// GlobalCtors - Store the list of global constructors and their respective
+ /// priorities to be emitted when the translation unit is complete.
+ CtorList GlobalCtors;
+
+ /// GlobalDtors - Store the list of global destructors and their respective
+ /// priorities to be emitted when the translation unit is complete.
+ CtorList GlobalDtors;
+
+ /// MangledDeclNames - A map of canonical GlobalDecls to their mangled names.
+ llvm::DenseMap<GlobalDecl, llvm::StringRef> MangledDeclNames;
+ llvm::BumpPtrAllocator MangledNamesAllocator;
+
+ std::vector<llvm::Constant*> Annotations;
+
+ llvm::StringMap<llvm::Constant*> CFConstantStringMap;
+ llvm::StringMap<llvm::Constant*> ConstantStringMap;
+ llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap;
+
+ /// CXXGlobalInits - Global variables with initializers that need to run
+ /// before main.
+ std::vector<llvm::Constant*> CXXGlobalInits;
+
+ /// When a C++ decl with an initializer is deferred, null is
+ /// appended to CXXGlobalInits, and the index of that null is placed
+ /// here so that the initializer will be performed in the correct
+ /// order.
+ llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
+
+ /// - Global variables with initializers whose order of initialization
+ /// is set by init_priority attribute.
+
+ llvm::SmallVector<std::pair<OrderGlobalInits, llvm::Function*>, 8>
+ PrioritizedCXXGlobalInits;
+
+ /// CXXGlobalDtors - Global destructor functions and arguments that need to
+ /// run on termination.
+ std::vector<std::pair<llvm::WeakVH,llvm::Constant*> > CXXGlobalDtors;
+
+ /// CFConstantStringClassRef - Cached reference to the class for constant
+ /// strings. This value has type int * but is actually an Obj-C class pointer.
+ llvm::Constant *CFConstantStringClassRef;
+
+ /// ConstantStringClassRef - Cached reference to the class for constant
+ /// strings. This value has type int * but is actually an Obj-C class pointer.
+ llvm::Constant *ConstantStringClassRef;
+
+ /// Lazily create the Objective-C runtime
+ void createObjCRuntime();
+
+ llvm::LLVMContext &VMContext;
+
+ /// @name Cache for Blocks Runtime Globals
+ /// @{
+
+ const VarDecl *NSConcreteGlobalBlockDecl;
+ const VarDecl *NSConcreteStackBlockDecl;
+ llvm::Constant *NSConcreteGlobalBlock;
+ llvm::Constant *NSConcreteStackBlock;
+
+ const FunctionDecl *BlockObjectAssignDecl;
+ const FunctionDecl *BlockObjectDisposeDecl;
+ llvm::Constant *BlockObjectAssign;
+ llvm::Constant *BlockObjectDispose;
+
+ const llvm::Type *BlockDescriptorType;
+ const llvm::Type *GenericBlockLiteralType;
+
+ struct {
+ int GlobalUniqueCount;
+ } Block;
+
+ llvm::DenseMap<uint64_t, llvm::Constant *> AssignCache;
+ llvm::DenseMap<uint64_t, llvm::Constant *> DestroyCache;
+
+ /// @}
+public:
+ CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
+ llvm::Module &M, const llvm::TargetData &TD, Diagnostic &Diags);
+
+ ~CodeGenModule();
+
+ /// Release - Finalize LLVM code generation.
+ void Release();
+
+ /// getObjCRuntime() - Return a reference to the configured
+ /// Objective-C runtime.
+ CGObjCRuntime &getObjCRuntime() {
+ if (!Runtime) createObjCRuntime();
+ return *Runtime;
+ }
+
+ /// hasObjCRuntime() - Return true iff an Objective-C runtime has
+ /// been configured.
+ bool hasObjCRuntime() { return !!Runtime; }
+
+ /// getCXXABI() - Return a reference to the configured C++ ABI.
+ CGCXXABI &getCXXABI() { return ABI; }
+
+ llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) {
+ return StaticLocalDeclMap[VD];
+ }
+ void setStaticLocalDeclAddress(const VarDecl *D,
+ llvm::GlobalVariable *GV) {
+ StaticLocalDeclMap[D] = GV;
+ }
+
+ CGDebugInfo *getDebugInfo() { return DebugInfo; }
+ ASTContext &getContext() const { return Context; }
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
+ const LangOptions &getLangOptions() const { return Features; }
+ llvm::Module &getModule() const { return TheModule; }
+ CodeGenTypes &getTypes() { return Types; }
+ CodeGenVTables &getVTables() { return VTables; }
+ Diagnostic &getDiags() const { return Diags; }
+ const llvm::TargetData &getTargetData() const { return TheTargetData; }
+ const TargetInfo &getTarget() const { return Context.Target; }
+ llvm::LLVMContext &getLLVMContext() { return VMContext; }
+ const TargetCodeGenInfo &getTargetCodeGenInfo();
+ bool isTargetDarwin() const;
+
+ llvm::MDNode *getTBAAInfo(QualType QTy);
+
+ static void DecorateInstruction(llvm::Instruction *Inst,
+ llvm::MDNode *TBAAInfo);
+
+ /// setGlobalVisibility - Set the visibility for the given LLVM
+ /// GlobalValue.
+ void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
+
+ /// TypeVisibilityKind - The kind of global variable that is passed to
+ /// setTypeVisibility
+ enum TypeVisibilityKind {
+ TVK_ForVTT,
+ TVK_ForVTable,
+ TVK_ForRTTI,
+ TVK_ForRTTIName
+ };
+
+ /// setTypeVisibility - Set the visibility for the given global
+ /// value which holds information about a type.
+ void setTypeVisibility(llvm::GlobalValue *GV, const CXXRecordDecl *D,
+ TypeVisibilityKind TVK) const;
+
+ static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) {
+ switch (V) {
+ case DefaultVisibility: return llvm::GlobalValue::DefaultVisibility;
+ case HiddenVisibility: return llvm::GlobalValue::HiddenVisibility;
+ case ProtectedVisibility: return llvm::GlobalValue::ProtectedVisibility;
+ }
+ llvm_unreachable("unknown visibility!");
+ return llvm::GlobalValue::DefaultVisibility;
+ }
+
+ llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
+ if (isa<CXXConstructorDecl>(GD.getDecl()))
+ return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
+ GD.getCtorType());
+ else if (isa<CXXDestructorDecl>(GD.getDecl()))
+ return GetAddrOfCXXDestructor(cast<CXXDestructorDecl>(GD.getDecl()),
+ GD.getDtorType());
+ else if (isa<FunctionDecl>(GD.getDecl()))
+ return GetAddrOfFunction(GD);
+ else
+ return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
+ }
+
+ /// CreateOrReplaceCXXRuntimeVariable - Will return a global variable of the given
+ /// type. If a variable with a different type already exists then a new
+ /// variable with the right type will be created and all uses of the old
+ /// variable will be replaced with a bitcast to the new variable.
+ llvm::GlobalVariable *
+ CreateOrReplaceCXXRuntimeVariable(llvm::StringRef Name, const llvm::Type *Ty,
+ llvm::GlobalValue::LinkageTypes Linkage);
+
+ /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
+ /// given global variable. If Ty is non-null and if the global doesn't exist,
+ /// then it will be greated with the specified type instead of whatever the
+ /// normal requested type would be.
+ llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
+ const llvm::Type *Ty = 0);
+
+ /// GetAddrOfFunction - Return the address of the given function. If Ty is
+ /// non-null, then this function will use the specified type if it has to
+ /// create it.
+ llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
+ const llvm::Type *Ty = 0,
+ bool ForVTable = false);
+
+ /// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor
+ /// for the given type.
+ llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
+
+ /// GetAddrOfThunk - Get the address of the thunk for the given global decl.
+ llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk);
+
+ /// GetWeakRefReference - Get a reference to the target of VD.
+ llvm::Constant *GetWeakRefReference(const ValueDecl *VD);
+
+ /// GetNonVirtualBaseClassOffset - Returns the offset from a derived class to
+ /// a class. Returns null if the offset is 0.
+ llvm::Constant *
+ GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd);
+
+ llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T,
+ BlockFieldFlags flags,
+ unsigned Align,
+ const VarDecl *variable);
+ llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T,
+ BlockFieldFlags flags,
+ unsigned Align,
+ const VarDecl *variable);
+
+ /// getGlobalUniqueCount - Fetches the global unique block count.
+ int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
+
+ /// getBlockDescriptorType - Fetches the type of a generic block
+ /// descriptor.
+ const llvm::Type *getBlockDescriptorType();
+
+ /// getGenericBlockLiteralType - The type of a generic block literal.
+ const llvm::Type *getGenericBlockLiteralType();
+
+ /// GetAddrOfGlobalBlock - Gets the address of a block which
+ /// requires no captures.
+ llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
+
+ /// GetStringForStringLiteral - Return the appropriate bytes for a string
+ /// literal, properly padded to match the literal type. If only the address of
+ /// a constant is needed consider using GetAddrOfConstantStringLiteral.
+ std::string GetStringForStringLiteral(const StringLiteral *E);
+
+ /// GetAddrOfConstantCFString - Return a pointer to a constant CFString object
+ /// for the given string.
+ llvm::Constant *GetAddrOfConstantCFString(const StringLiteral *Literal);
+
+ /// GetAddrOfConstantString - Return a pointer to a constant NSString object
+ /// for the given string. Or a user defined String object as defined via
+ /// -fconstant-string-class=class_name option.
+ llvm::Constant *GetAddrOfConstantString(const StringLiteral *Literal);
+
+ /// GetAddrOfConstantStringFromLiteral - Return a pointer to a constant array
+ /// for the given string literal.
+ llvm::Constant *GetAddrOfConstantStringFromLiteral(const StringLiteral *S);
+
+ /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
+ /// array for the given ObjCEncodeExpr node.
+ llvm::Constant *GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
+
+ /// GetAddrOfConstantString - Returns a pointer to a character array
+ /// containing the literal. This contents are exactly that of the given
+ /// string, i.e. it will not be null terminated automatically; see
+ /// GetAddrOfConstantCString. Note that whether the result is actually a
+ /// pointer to an LLVM constant depends on Feature.WriteableStrings.
+ ///
+ /// The result has pointer to array type.
+ ///
+ /// \param GlobalName If provided, the name to use for the global
+ /// (if one is created).
+ llvm::Constant *GetAddrOfConstantString(const std::string& str,
+ const char *GlobalName=0);
+
+ /// GetAddrOfConstantCString - Returns a pointer to a character array
+ /// containing the literal and a terminating '\0' character. The result has
+ /// pointer to array type.
+ ///
+ /// \param GlobalName If provided, the name to use for the global (if one is
+ /// created).
+ llvm::Constant *GetAddrOfConstantCString(const std::string &str,
+ const char *GlobalName=0);
+
+ /// GetAddrOfCXXConstructor - Return the address of the constructor of the
+ /// given type.
+ llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
+ CXXCtorType Type);
+
+ /// GetAddrOfCXXDestructor - Return the address of the constructor of the
+ /// given type.
+ llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
+ CXXDtorType Type);
+
+ /// getBuiltinLibFunction - Given a builtin id for a function like
+ /// "__builtin_fabsf", return a Function* for "fabsf".
+ llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,
+ unsigned BuiltinID);
+
+ llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0,
+ unsigned NumTys = 0);
+
+ /// EmitTopLevelDecl - Emit code for a single top level declaration.
+ void EmitTopLevelDecl(Decl *D);
+
+ /// AddUsedGlobal - Add a global which should be forced to be
+ /// present in the object file; these are emitted to the llvm.used
+ /// metadata global.
+ void AddUsedGlobal(llvm::GlobalValue *GV);
+
+ void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
+
+ /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global
+ /// destructor function.
+ void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
+ CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
+ }
+
+ /// CreateRuntimeFunction - Create a new runtime function with the specified
+ /// type and name.
+ llvm::Constant *CreateRuntimeFunction(const llvm::FunctionType *Ty,
+ llvm::StringRef Name);
+ /// CreateRuntimeVariable - Create a new runtime global variable with the
+ /// specified type and name.
+ llvm::Constant *CreateRuntimeVariable(const llvm::Type *Ty,
+ llvm::StringRef Name);
+
+ ///@name Custom Blocks Runtime Interfaces
+ ///@{
+
+ llvm::Constant *getNSConcreteGlobalBlock();
+ llvm::Constant *getNSConcreteStackBlock();
+ llvm::Constant *getBlockObjectAssign();
+ llvm::Constant *getBlockObjectDispose();
+
+ ///@}
+
+ void UpdateCompletedType(const TagDecl *TD) {
+ // Make sure that this type is translated.
+ Types.UpdateCompletedType(TD);
+ }
+
+ llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
+
+ /// EmitConstantExpr - Try to emit the given expression as a
+ /// constant; returns 0 if the expression cannot be emitted as a
+ /// constant.
+ llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
+ CodeGenFunction *CGF = 0);
+
+ /// EmitNullConstant - Return the result of value-initializing the given
+ /// type, i.e. a null expression of the given type. This is usually,
+ /// but not always, an LLVM null constant.
+ llvm::Constant *EmitNullConstant(QualType T);
+
+ llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
+ const AnnotateAttr *AA, unsigned LineNo);
+
+ /// ErrorUnsupported - Print out an error that codegen doesn't support the
+ /// specified stmt yet.
+ /// \param OmitOnError - If true, then this error should only be emitted if no
+ /// other errors have been reported.
+ void ErrorUnsupported(const Stmt *S, const char *Type,
+ bool OmitOnError=false);
+
+ /// ErrorUnsupported - Print out an error that codegen doesn't support the
+ /// specified decl yet.
+ /// \param OmitOnError - If true, then this error should only be emitted if no
+ /// other errors have been reported.
+ void ErrorUnsupported(const Decl *D, const char *Type,
+ bool OmitOnError=false);
+
+ /// SetInternalFunctionAttributes - Set the attributes on the LLVM
+ /// function for the given decl and function info. This applies
+ /// attributes necessary for handling the ABI as well as user
+ /// specified attributes like section.
+ void SetInternalFunctionAttributes(const Decl *D, llvm::Function *F,
+ const CGFunctionInfo &FI);
+
+ /// SetLLVMFunctionAttributes - Set the LLVM function attributes
+ /// (sext, zext, etc).
+ void SetLLVMFunctionAttributes(const Decl *D,
+ const CGFunctionInfo &Info,
+ llvm::Function *F);
+
+ /// SetLLVMFunctionAttributesForDefinition - Set the LLVM function attributes
+ /// which only apply to a function definintion.
+ void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F);
+
+ /// ReturnTypeUsesSRet - Return true iff the given type uses 'sret' when used
+ /// as a return type.
+ bool ReturnTypeUsesSRet(const CGFunctionInfo &FI);
+
+ /// ReturnTypeUsesSret - Return true iff the given type uses 'fpret' when used
+ /// as a return type.
+ bool ReturnTypeUsesFPRet(QualType ResultType);
+
+ /// ConstructAttributeList - Get the LLVM attributes and calling convention to
+ /// use for a particular function type.
+ ///
+ /// \param Info - The function type information.
+ /// \param TargetDecl - The decl these attributes are being constructed
+ /// for. If supplied the attributes applied to this decl may contribute to the
+ /// function attributes and calling convention.
+ /// \param PAL [out] - On return, the attribute list to use.
+ /// \param CallingConv [out] - On return, the LLVM calling convention to use.
+ void ConstructAttributeList(const CGFunctionInfo &Info,
+ const Decl *TargetDecl,
+ AttributeListType &PAL,
+ unsigned &CallingConv);
+
+ llvm::StringRef getMangledName(GlobalDecl GD);
+ void getBlockMangledName(GlobalDecl GD, MangleBuffer &Buffer,
+ const BlockDecl *BD);
+
+ void EmitTentativeDefinition(const VarDecl *D);
+
+ void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
+
+ llvm::GlobalVariable::LinkageTypes
+ getFunctionLinkage(const FunctionDecl *FD);
+
+ void setFunctionLinkage(const FunctionDecl *FD, llvm::GlobalValue *V) {
+ V->setLinkage(getFunctionLinkage(FD));
+ }
+
+ /// getVTableLinkage - Return the appropriate linkage for the vtable, VTT,
+ /// and type information of the given class.
+ llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
+
+ /// GetTargetTypeStoreSize - Return the store size, in character units, of
+ /// the given LLVM type.
+ CharUnits GetTargetTypeStoreSize(const llvm::Type *Ty) const;
+
+ /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global
+ /// variable.
+ llvm::GlobalValue::LinkageTypes
+ GetLLVMLinkageVarDefinition(const VarDecl *D,
+ llvm::GlobalVariable *GV);
+
+ std::vector<const CXXRecordDecl*> DeferredVTables;
+
+private:
+ llvm::GlobalValue *GetGlobalValue(llvm::StringRef Ref);
+
+ llvm::Constant *GetOrCreateLLVMFunction(llvm::StringRef MangledName,
+ const llvm::Type *Ty,
+ GlobalDecl D,
+ bool ForVTable);
+ llvm::Constant *GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
+ const llvm::PointerType *PTy,
+ const VarDecl *D,
+ bool UnnamedAddr = false);
+
+ /// SetCommonAttributes - Set attributes which are common to any
+ /// form of a global definition (alias, Objective-C method,
+ /// function, global variable).
+ ///
+ /// NOTE: This should only be called for definitions.
+ void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
+
+ /// SetFunctionDefinitionAttributes - Set attributes for a global definition.
+ void SetFunctionDefinitionAttributes(const FunctionDecl *D,
+ llvm::GlobalValue *GV);
+
+ /// SetFunctionAttributes - Set function attributes for a function
+ /// declaration.
+ void SetFunctionAttributes(GlobalDecl GD,
+ llvm::Function *F,
+ bool IsIncompleteFunction);
+
+ /// EmitGlobal - Emit code for a singal global function or var decl. Forward
+ /// declarations are emitted lazily.
+ void EmitGlobal(GlobalDecl D);
+
+ void EmitGlobalDefinition(GlobalDecl D);
+
+ void EmitGlobalFunctionDefinition(GlobalDecl GD);
+ void EmitGlobalVarDefinition(const VarDecl *D);
+ void EmitAliasDefinition(GlobalDecl GD);
+ void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
+ void EmitObjCIvarInitializations(ObjCImplementationDecl *D);
+
+ // C++ related functions.
+
+ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+ bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
+
+ void EmitNamespace(const NamespaceDecl *D);
+ void EmitLinkageSpec(const LinkageSpecDecl *D);
+
+ /// EmitCXXConstructors - Emit constructors (base, complete) from a
+ /// C++ constructor Decl.
+ void EmitCXXConstructors(const CXXConstructorDecl *D);
+
+ /// EmitCXXConstructor - Emit a single constructor with the given type from
+ /// a C++ constructor Decl.
+ void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type);
+
+ /// EmitCXXDestructors - Emit destructors (base, complete) from a
+ /// C++ destructor Decl.
+ void EmitCXXDestructors(const CXXDestructorDecl *D);
+
+ /// EmitCXXDestructor - Emit a single destructor with the given type from
+ /// a C++ destructor Decl.
+ void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
+
+ /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals.
+ void EmitCXXGlobalInitFunc();
+
+ /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals.
+ void EmitCXXGlobalDtorFunc();
+
+ void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
+ llvm::GlobalVariable *Addr);
+
+ // FIXME: Hardcoding priority here is gross.
+ void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
+ void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
+
+ /// EmitCtorList - Generates a global array of functions and priorities using
+ /// the given list and name. This array will have appending linkage and is
+ /// suitable for use as a LLVM constructor or destructor array.
+ void EmitCtorList(const CtorList &Fns, const char *GlobalName);
+
+ void EmitAnnotations(void);
+
+ /// EmitFundamentalRTTIDescriptor - Emit the RTTI descriptors for the
+ /// given type.
+ void EmitFundamentalRTTIDescriptor(QualType Type);
+
+ /// EmitFundamentalRTTIDescriptors - Emit the RTTI descriptors for the
+ /// builtin types.
+ void EmitFundamentalRTTIDescriptors();
+
+ /// EmitDeferred - Emit any needed decls for which code generation
+ /// was deferred.
+ void EmitDeferred(void);
+
+ /// EmitLLVMUsed - Emit the llvm.used metadata used to force
+ /// references to global which may otherwise be optimized out.
+ void EmitLLVMUsed(void);
+
+ void EmitDeclMetadata();
+
+ /// MayDeferGeneration - Determine if the given decl can be emitted
+ /// lazily; this is only relevant for definitions. The given decl
+ /// must be either a function or var decl.
+ bool MayDeferGeneration(const ValueDecl *D);
+
+ /// SimplifyPersonality - Check whether we can use a "simpler", more
+ /// core exceptions personality function.
+ void SimplifyPersonality();
+};
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
new file mode 100644
index 0000000..3f2c6ca
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -0,0 +1,180 @@
+//===--- CodeGenTypes.cpp - TBAA information for LLVM CodeGen -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the code that manages TBAA information and defines the TBAA policy
+// for the optimizer to use. Relevant standards text includes:
+//
+// C99 6.5p7
+// C++ [basic.lval] (p10 in n3126, p15 in some earlier versions)
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTBAA.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Mangle.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Metadata.h"
+#include "llvm/Constants.h"
+#include "llvm/Type.h"
+using namespace clang;
+using namespace CodeGen;
+
+CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
+ const LangOptions &Features, MangleContext &MContext)
+ : Context(Ctx), VMContext(VMContext), Features(Features), MContext(MContext),
+ Root(0), Char(0) {
+}
+
+CodeGenTBAA::~CodeGenTBAA() {
+}
+
+llvm::MDNode *CodeGenTBAA::getRoot() {
+ // Define the root of the tree. This identifies the tree, so that
+ // if our LLVM IR is linked with LLVM IR from a different front-end
+ // (or a different version of this front-end), their TBAA trees will
+ // remain distinct, and the optimizer will treat them conservatively.
+ if (!Root)
+ Root = getTBAAInfoForNamedType("Simple C/C++ TBAA", 0);
+
+ return Root;
+}
+
+llvm::MDNode *CodeGenTBAA::getChar() {
+ // Define the root of the tree for user-accessible memory. C and C++
+ // give special powers to char and certain similar types. However,
+ // these special powers only cover user-accessible memory, and doesn't
+ // include things like vtables.
+ if (!Char)
+ Char = getTBAAInfoForNamedType("omnipotent char", getRoot());
+
+ return Char;
+}
+
+/// getTBAAInfoForNamedType - Create a TBAA tree node with the given string
+/// as its identifier, and the given Parent node as its tree parent.
+llvm::MDNode *CodeGenTBAA::getTBAAInfoForNamedType(llvm::StringRef NameStr,
+ llvm::MDNode *Parent,
+ bool Readonly) {
+ // Currently there is only one flag defined - the readonly flag.
+ llvm::Value *Flags = 0;
+ if (Readonly)
+ Flags = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), true);
+
+ // Set up the mdnode operand list.
+ llvm::Value *Ops[] = {
+ llvm::MDString::get(VMContext, NameStr),
+ Parent,
+ Flags
+ };
+
+ // Create the mdnode.
+ return llvm::MDNode::get(VMContext, Ops, llvm::array_lengthof(Ops) - !Flags);
+}
+
+static bool TypeHasMayAlias(QualType QTy) {
+ // Tagged types have declarations, and therefore may have attributes.
+ if (const TagType *TTy = dyn_cast<TagType>(QTy))
+ return TTy->getDecl()->hasAttr<MayAliasAttr>();
+
+ // Typedef types have declarations, and therefore may have attributes.
+ if (const TypedefType *TTy = dyn_cast<TypedefType>(QTy)) {
+ if (TTy->getDecl()->hasAttr<MayAliasAttr>())
+ return true;
+ // Also, their underlying types may have relevant attributes.
+ return TypeHasMayAlias(TTy->desugar());
+ }
+
+ return false;
+}
+
+llvm::MDNode *
+CodeGenTBAA::getTBAAInfo(QualType QTy) {
+ // If the type has the may_alias attribute (even on a typedef), it is
+ // effectively in the general char alias class.
+ if (TypeHasMayAlias(QTy))
+ return getChar();
+
+ const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
+
+ if (llvm::MDNode *N = MetadataCache[Ty])
+ return N;
+
+ // Handle builtin types.
+ if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
+ switch (BTy->getKind()) {
+ // Character types are special and can alias anything.
+ // In C++, this technically only includes "char" and "unsigned char",
+ // and not "signed char". In C, it includes all three. For now,
+ // the risk of exploiting this detail in C++ seems likely to outweigh
+ // the benefit.
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ return getChar();
+
+ // Unsigned types can alias their corresponding signed types.
+ case BuiltinType::UShort:
+ return getTBAAInfo(Context.ShortTy);
+ case BuiltinType::UInt:
+ return getTBAAInfo(Context.IntTy);
+ case BuiltinType::ULong:
+ return getTBAAInfo(Context.LongTy);
+ case BuiltinType::ULongLong:
+ return getTBAAInfo(Context.LongLongTy);
+ case BuiltinType::UInt128:
+ return getTBAAInfo(Context.Int128Ty);
+
+ // Treat all other builtin types as distinct types. This includes
+ // treating wchar_t, char16_t, and char32_t as distinct from their
+ // "underlying types".
+ default:
+ return MetadataCache[Ty] =
+ getTBAAInfoForNamedType(BTy->getName(Features), getChar());
+ }
+ }
+
+ // Handle pointers.
+ // TODO: Implement C++'s type "similarity" and consider dis-"similar"
+ // pointers distinct.
+ if (Ty->isPointerType())
+ return MetadataCache[Ty] = getTBAAInfoForNamedType("any pointer",
+ getChar());
+
+ // Enum types are distinct types. In C++ they have "underlying types",
+ // however they aren't related for TBAA.
+ if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
+ // In C mode, two anonymous enums are compatible iff their members
+ // are the same -- see C99 6.2.7p1. For now, be conservative. We could
+ // theoretically implement this by combining information about all the
+ // members into a single identifying MDNode.
+ if (!Features.CPlusPlus &&
+ ETy->getDecl()->getTypedefForAnonDecl())
+ return MetadataCache[Ty] = getChar();
+
+ // In C++ mode, types have linkage, so we can rely on the ODR and
+ // on their mangled names, if they're external.
+ // TODO: Is there a way to get a program-wide unique name for a
+ // decl with local linkage or no linkage?
+ if (Features.CPlusPlus &&
+ ETy->getDecl()->getLinkage() != ExternalLinkage)
+ return MetadataCache[Ty] = getChar();
+
+ // TODO: This is using the RTTI name. Is there a better way to get
+ // a unique string for a type?
+ llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ MContext.mangleCXXRTTIName(QualType(ETy, 0), Out);
+ Out.flush();
+ return MetadataCache[Ty] = getTBAAInfoForNamedType(OutName, getChar());
+ }
+
+ // For now, handle any other kind of type conservatively.
+ return MetadataCache[Ty] = getChar();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
new file mode 100644
index 0000000..c458347
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.h
@@ -0,0 +1,76 @@
+//===--- CodeGenTBAA.h - TBAA information for LLVM CodeGen ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the code that manages TBAA information and defines the TBAA policy
+// for the optimizer to use.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CODEGENTBAA_H
+#define CLANG_CODEGEN_CODEGENTBAA_H
+
+#include "llvm/LLVMContext.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+ class LLVMContext;
+ class MDNode;
+}
+
+namespace clang {
+ class ASTContext;
+ class LangOptions;
+ class MangleContext;
+ class QualType;
+ class Type;
+
+namespace CodeGen {
+ class CGRecordLayout;
+
+/// CodeGenTBAA - This class organizes the cross-module state that is used
+/// while lowering AST types to LLVM types.
+class CodeGenTBAA {
+ ASTContext &Context;
+ llvm::LLVMContext& VMContext;
+ const LangOptions &Features;
+ MangleContext &MContext;
+
+ /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
+ llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
+
+ llvm::MDNode *Root;
+ llvm::MDNode *Char;
+
+ /// getRoot - This is the mdnode for the root of the metadata type graph
+ /// for this translation unit.
+ llvm::MDNode *getRoot();
+
+ /// getChar - This is the mdnode for "char", which is special, and any types
+ /// considered to be equivalent to it.
+ llvm::MDNode *getChar();
+
+ llvm::MDNode *getTBAAInfoForNamedType(llvm::StringRef NameStr,
+ llvm::MDNode *Parent,
+ bool Readonly = false);
+
+public:
+ CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
+ const LangOptions &Features,
+ MangleContext &MContext);
+ ~CodeGenTBAA();
+
+ /// getTBAAInfo - Get the TBAA MDNode to be used for a dereference
+ /// of the given type.
+ llvm::MDNode *getTBAAInfo(QualType QTy);
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
new file mode 100644
index 0000000..5254922
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -0,0 +1,527 @@
+//===--- CodeGenTypes.cpp - Type translation for LLVM CodeGen -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the code that handles AST -> LLVM type lowering.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTypes.h"
+#include "CGCall.h"
+#include "CGCXXABI.h"
+#include "CGRecordLayout.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetData.h"
+using namespace clang;
+using namespace CodeGen;
+
+CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
+ const llvm::TargetData &TD, const ABIInfo &Info,
+ CGCXXABI &CXXABI)
+ : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
+ TheABIInfo(Info), TheCXXABI(CXXABI) {
+}
+
+CodeGenTypes::~CodeGenTypes() {
+ for (llvm::DenseMap<const Type *, CGRecordLayout *>::iterator
+ I = CGRecordLayouts.begin(), E = CGRecordLayouts.end();
+ I != E; ++I)
+ delete I->second;
+
+ for (llvm::FoldingSet<CGFunctionInfo>::iterator
+ I = FunctionInfos.begin(), E = FunctionInfos.end(); I != E; )
+ delete &*I++;
+}
+
+/// HandleLateResolvedPointers - For top-level ConvertType calls, this handles
+/// pointers that are referenced but have not been converted yet. This is used
+/// to handle cyclic structures properly.
+void CodeGenTypes::HandleLateResolvedPointers() {
+ assert(!PointersToResolve.empty() && "No pointers to resolve!");
+
+ // Any pointers that were converted deferred evaluation of their pointee type,
+ // creating an opaque type instead. This is in order to avoid problems with
+ // circular types. Loop through all these defered pointees, if any, and
+ // resolve them now.
+ while (!PointersToResolve.empty()) {
+ std::pair<QualType, llvm::OpaqueType*> P = PointersToResolve.pop_back_val();
+
+ // We can handle bare pointers here because we know that the only pointers
+ // to the Opaque type are P.second and from other types. Refining the
+ // opqaue type away will invalidate P.second, but we don't mind :).
+ const llvm::Type *NT = ConvertTypeForMemRecursive(P.first);
+ P.second->refineAbstractTypeTo(NT);
+ }
+}
+
+
+/// ConvertType - Convert the specified type to its LLVM form.
+const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) {
+ const llvm::Type *Result = ConvertTypeRecursive(T);
+
+ // If this is a top-level call to ConvertType and sub-conversions caused
+ // pointers to get lazily built as opaque types, resolve the pointers, which
+ // might cause Result to be merged away.
+ if (!IsRecursive && !PointersToResolve.empty()) {
+ llvm::PATypeHolder ResultHandle = Result;
+ HandleLateResolvedPointers();
+ Result = ResultHandle;
+ }
+ return Result;
+}
+
+const llvm::Type *CodeGenTypes::ConvertTypeRecursive(QualType T) {
+ T = Context.getCanonicalType(T);
+
+ // See if type is already cached.
+ llvm::DenseMap<const Type *, llvm::PATypeHolder>::iterator
+ I = TypeCache.find(T.getTypePtr());
+ // If type is found in map and this is not a definition for a opaque
+ // place holder type then use it. Otherwise, convert type T.
+ if (I != TypeCache.end())
+ return I->second.get();
+
+ const llvm::Type *ResultType = ConvertNewType(T);
+ TypeCache.insert(std::make_pair(T.getTypePtr(),
+ llvm::PATypeHolder(ResultType)));
+ return ResultType;
+}
+
+/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
+/// ConvertType in that it is used to convert to the memory representation for
+/// a type. For example, the scalar representation for _Bool is i1, but the
+/// memory representation is usually i8 or i32, depending on the target.
+const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool IsRecursive){
+ const llvm::Type *R = ConvertType(T, IsRecursive);
+
+ // If this is a non-bool type, don't map it.
+ if (!R->isIntegerTy(1))
+ return R;
+
+ // Otherwise, return an integer of the target-specified size.
+ return llvm::IntegerType::get(getLLVMContext(),
+ (unsigned)Context.getTypeSize(T));
+
+}
+
+// Code to verify a given function type is complete, i.e. the return type
+// and all of the argument types are complete.
+const TagType *CodeGenTypes::VerifyFuncTypeComplete(const Type* T) {
+ const FunctionType *FT = cast<FunctionType>(T);
+ if (const TagType* TT = FT->getResultType()->getAs<TagType>())
+ if (!TT->getDecl()->isDefinition())
+ return TT;
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(T))
+ for (unsigned i = 0; i < FPT->getNumArgs(); i++)
+ if (const TagType* TT = FPT->getArgType(i)->getAs<TagType>())
+ if (!TT->getDecl()->isDefinition())
+ return TT;
+ return 0;
+}
+
+/// UpdateCompletedType - When we find the full definition for a TagDecl,
+/// replace the 'opaque' type we previously made for it if applicable.
+void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
+ const Type *Key = Context.getTagDeclType(TD).getTypePtr();
+ llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI =
+ TagDeclTypes.find(Key);
+ if (TDTI == TagDeclTypes.end()) return;
+
+ // Remember the opaque LLVM type for this tagdecl.
+ llvm::PATypeHolder OpaqueHolder = TDTI->second;
+ assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) &&
+ "Updating compilation of an already non-opaque type?");
+
+ // Remove it from TagDeclTypes so that it will be regenerated.
+ TagDeclTypes.erase(TDTI);
+
+ // Generate the new type.
+ const llvm::Type *NT = ConvertTagDeclType(TD);
+
+ // Refine the old opaque type to its new definition.
+ cast<llvm::OpaqueType>(OpaqueHolder.get())->refineAbstractTypeTo(NT);
+
+ // Since we just completed a tag type, check to see if any function types
+ // were completed along with the tag type.
+ // FIXME: This is very inefficient; if we track which function types depend
+ // on which tag types, though, it should be reasonably efficient.
+ llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator i;
+ for (i = FunctionTypes.begin(); i != FunctionTypes.end(); ++i) {
+ if (const TagType* TT = VerifyFuncTypeComplete(i->first)) {
+ // This function type still depends on an incomplete tag type; make sure
+ // that tag type has an associated opaque type.
+ ConvertTagDeclType(TT->getDecl());
+ } else {
+ // This function no longer depends on an incomplete tag type; create the
+ // function type, and refine the opaque type to the new function type.
+ llvm::PATypeHolder OpaqueHolder = i->second;
+ const llvm::Type *NFT = ConvertNewType(QualType(i->first, 0));
+ cast<llvm::OpaqueType>(OpaqueHolder.get())->refineAbstractTypeTo(NFT);
+ FunctionTypes.erase(i);
+ }
+ }
+}
+
+static const llvm::Type* getTypeForFormat(llvm::LLVMContext &VMContext,
+ const llvm::fltSemantics &format) {
+ if (&format == &llvm::APFloat::IEEEsingle)
+ return llvm::Type::getFloatTy(VMContext);
+ if (&format == &llvm::APFloat::IEEEdouble)
+ return llvm::Type::getDoubleTy(VMContext);
+ if (&format == &llvm::APFloat::IEEEquad)
+ return llvm::Type::getFP128Ty(VMContext);
+ if (&format == &llvm::APFloat::PPCDoubleDouble)
+ return llvm::Type::getPPC_FP128Ty(VMContext);
+ if (&format == &llvm::APFloat::x87DoubleExtended)
+ return llvm::Type::getX86_FP80Ty(VMContext);
+ assert(0 && "Unknown float format!");
+ return 0;
+}
+
+const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
+ const clang::Type &Ty = *Context.getCanonicalType(T).getTypePtr();
+
+ switch (Ty.getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical or dependent types aren't possible.");
+ break;
+
+ case Type::Builtin: {
+ switch (cast<BuiltinType>(Ty).getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ // LLVM void type can only be used as the result of a function call. Just
+ // map to the same as char.
+ return llvm::Type::getInt8Ty(getLLVMContext());
+
+ case BuiltinType::Bool:
+ // Note that we always return bool as i1 for use as a scalar type.
+ return llvm::Type::getInt1Ty(getLLVMContext());
+
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ return llvm::IntegerType::get(getLLVMContext(),
+ static_cast<unsigned>(Context.getTypeSize(T)));
+
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ return getTypeForFormat(getLLVMContext(),
+ Context.getFloatTypeSemantics(T));
+
+ case BuiltinType::NullPtr: {
+ // Model std::nullptr_t as i8*
+ const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext());
+ return llvm::PointerType::getUnqual(Ty);
+ }
+
+ case BuiltinType::UInt128:
+ case BuiltinType::Int128:
+ return llvm::IntegerType::get(getLLVMContext(), 128);
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ assert(0 && "Unexpected builtin type!");
+ break;
+ }
+ assert(0 && "Unknown builtin type!");
+ break;
+ }
+ case Type::Complex: {
+ const llvm::Type *EltTy =
+ ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType());
+ return llvm::StructType::get(TheModule.getContext(), EltTy, EltTy, NULL);
+ }
+ case Type::LValueReference:
+ case Type::RValueReference: {
+ const ReferenceType &RTy = cast<ReferenceType>(Ty);
+ QualType ETy = RTy.getPointeeType();
+ llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
+ PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
+ return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
+ }
+ case Type::Pointer: {
+ const PointerType &PTy = cast<PointerType>(Ty);
+ QualType ETy = PTy.getPointeeType();
+ llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
+ PointersToResolve.push_back(std::make_pair(ETy, PointeeType));
+ return llvm::PointerType::get(PointeeType, ETy.getAddressSpace());
+ }
+
+ case Type::VariableArray: {
+ const VariableArrayType &A = cast<VariableArrayType>(Ty);
+ assert(A.getIndexTypeCVRQualifiers() == 0 &&
+ "FIXME: We only handle trivial array types so far!");
+ // VLAs resolve to the innermost element type; this matches
+ // the return of alloca, and there isn't any obviously better choice.
+ return ConvertTypeForMemRecursive(A.getElementType());
+ }
+ case Type::IncompleteArray: {
+ const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);
+ assert(A.getIndexTypeCVRQualifiers() == 0 &&
+ "FIXME: We only handle trivial array types so far!");
+ // int X[] -> [0 x int]
+ return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()),
+ 0);
+ }
+ case Type::ConstantArray: {
+ const ConstantArrayType &A = cast<ConstantArrayType>(Ty);
+ const llvm::Type *EltTy = ConvertTypeForMemRecursive(A.getElementType());
+ return llvm::ArrayType::get(EltTy, A.getSize().getZExtValue());
+ }
+ case Type::ExtVector:
+ case Type::Vector: {
+ const VectorType &VT = cast<VectorType>(Ty);
+ return llvm::VectorType::get(ConvertTypeRecursive(VT.getElementType()),
+ VT.getNumElements());
+ }
+ case Type::FunctionNoProto:
+ case Type::FunctionProto: {
+ // First, check whether we can build the full function type. If the
+ // function type depends on an incomplete type (e.g. a struct or enum), we
+ // cannot lower the function type. Instead, turn it into an Opaque pointer
+ // and have UpdateCompletedType revisit the function type when/if the opaque
+ // argument type is defined.
+ if (const TagType *TT = VerifyFuncTypeComplete(&Ty)) {
+ // This function's type depends on an incomplete tag type; make sure
+ // we have an opaque type corresponding to the tag type.
+ ConvertTagDeclType(TT->getDecl());
+ // Create an opaque type for this function type, save it, and return it.
+ llvm::Type *ResultType = llvm::OpaqueType::get(getLLVMContext());
+ FunctionTypes.insert(std::make_pair(&Ty, ResultType));
+ return ResultType;
+ }
+
+ // The function type can be built; call the appropriate routines to
+ // build it.
+ const CGFunctionInfo *FI;
+ bool isVariadic;
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(&Ty)) {
+ FI = &getFunctionInfo(
+ CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)),
+ true /*Recursive*/);
+ isVariadic = FPT->isVariadic();
+ } else {
+ const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(&Ty);
+ FI = &getFunctionInfo(
+ CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0)),
+ true /*Recursive*/);
+ isVariadic = true;
+ }
+
+ return GetFunctionType(*FI, isVariadic, true);
+ }
+
+ case Type::ObjCObject:
+ return ConvertTypeRecursive(cast<ObjCObjectType>(Ty).getBaseType());
+
+ case Type::ObjCInterface: {
+ // Objective-C interfaces are always opaque (outside of the
+ // runtime, which can do whatever it likes); we never refine
+ // these.
+ const llvm::Type *&T = InterfaceTypes[cast<ObjCInterfaceType>(&Ty)];
+ if (!T)
+ T = llvm::OpaqueType::get(getLLVMContext());
+ return T;
+ }
+
+ case Type::ObjCObjectPointer: {
+ // Protocol qualifications do not influence the LLVM type, we just return a
+ // pointer to the underlying interface type. We don't need to worry about
+ // recursive conversion.
+ const llvm::Type *T =
+ ConvertTypeRecursive(cast<ObjCObjectPointerType>(Ty).getPointeeType());
+ return llvm::PointerType::getUnqual(T);
+ }
+
+ case Type::Record:
+ case Type::Enum: {
+ const TagDecl *TD = cast<TagType>(Ty).getDecl();
+ const llvm::Type *Res = ConvertTagDeclType(TD);
+
+ llvm::SmallString<256> TypeName;
+ llvm::raw_svector_ostream OS(TypeName);
+ OS << TD->getKindName() << '.';
+
+ // Name the codegen type after the typedef name
+ // if there is no tag type name available
+ if (TD->getIdentifier()) {
+ // FIXME: We should not have to check for a null decl context here.
+ // Right now we do it because the implicit Obj-C decls don't have one.
+ if (TD->getDeclContext())
+ OS << TD->getQualifiedNameAsString();
+ else
+ TD->printName(OS);
+ } else if (const TypedefDecl *TDD = TD->getTypedefForAnonDecl()) {
+ // FIXME: We should not have to check for a null decl context here.
+ // Right now we do it because the implicit Obj-C decls don't have one.
+ if (TDD->getDeclContext())
+ OS << TDD->getQualifiedNameAsString();
+ else
+ TDD->printName(OS);
+ } else
+ OS << "anon";
+
+ TheModule.addTypeName(OS.str(), Res);
+ return Res;
+ }
+
+ case Type::BlockPointer: {
+ const QualType FTy = cast<BlockPointerType>(Ty).getPointeeType();
+ llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext());
+ PointersToResolve.push_back(std::make_pair(FTy, PointeeType));
+ return llvm::PointerType::get(PointeeType, FTy.getAddressSpace());
+ }
+
+ case Type::MemberPointer: {
+ return getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(&Ty));
+ }
+ }
+
+ // FIXME: implement.
+ return llvm::OpaqueType::get(getLLVMContext());
+}
+
+/// ConvertTagDeclType - Lay out a tagged decl type like struct or union or
+/// enum.
+const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
+ // TagDecl's are not necessarily unique, instead use the (clang)
+ // type connected to the decl.
+ const Type *Key =
+ Context.getTagDeclType(TD).getTypePtr();
+ llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI =
+ TagDeclTypes.find(Key);
+
+ // If we've already compiled this tag type, use the previous definition.
+ if (TDTI != TagDeclTypes.end())
+ return TDTI->second;
+
+ const EnumDecl *ED = dyn_cast<EnumDecl>(TD);
+
+ // If this is still a forward declaration, just define an opaque
+ // type to use for this tagged decl.
+ // C++0x: If this is a enumeration type with fixed underlying type,
+ // consider it complete.
+ if (!TD->isDefinition() && !(ED && ED->isFixed())) {
+ llvm::Type *ResultType = llvm::OpaqueType::get(getLLVMContext());
+ TagDeclTypes.insert(std::make_pair(Key, ResultType));
+ return ResultType;
+ }
+
+ // Okay, this is a definition of a type. Compile the implementation now.
+
+ if (ED) // Don't bother storing enums in TagDeclTypes.
+ return ConvertTypeRecursive(ED->getIntegerType());
+
+ // This decl could well be recursive. In this case, insert an opaque
+ // definition of this type, which the recursive uses will get. We will then
+ // refine this opaque version later.
+
+ // Create new OpaqueType now for later use in case this is a recursive
+ // type. This will later be refined to the actual type.
+ llvm::PATypeHolder ResultHolder = llvm::OpaqueType::get(getLLVMContext());
+ TagDeclTypes.insert(std::make_pair(Key, ResultHolder));
+
+ const RecordDecl *RD = cast<const RecordDecl>(TD);
+
+ // Force conversion of non-virtual base classes recursively.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ if (!i->isVirtual()) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ ConvertTagDeclType(Base);
+ }
+ }
+ }
+
+ // Layout fields.
+ CGRecordLayout *Layout = ComputeRecordLayout(RD);
+
+ CGRecordLayouts[Key] = Layout;
+ const llvm::Type *ResultType = Layout->getLLVMType();
+
+ // Refine our Opaque type to ResultType. This can invalidate ResultType, so
+ // make sure to read the result out of the holder.
+ cast<llvm::OpaqueType>(ResultHolder.get())
+ ->refineAbstractTypeTo(ResultType);
+
+ return ResultHolder.get();
+}
+
+/// getCGRecordLayout - Return record layout info for the given record decl.
+const CGRecordLayout &
+CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) {
+ const Type *Key = Context.getTagDeclType(RD).getTypePtr();
+
+ const CGRecordLayout *Layout = CGRecordLayouts.lookup(Key);
+ if (!Layout) {
+ // Compute the type information.
+ ConvertTagDeclType(RD);
+
+ // Now try again.
+ Layout = CGRecordLayouts.lookup(Key);
+ }
+
+ assert(Layout && "Unable to find record layout information for type");
+ return *Layout;
+}
+
+bool CodeGenTypes::isZeroInitializable(QualType T) {
+ // No need to check for member pointers when not compiling C++.
+ if (!Context.getLangOptions().CPlusPlus)
+ return true;
+
+ T = Context.getBaseElementType(T);
+
+ // Records are non-zero-initializable if they contain any
+ // non-zero-initializable subobjects.
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ return isZeroInitializable(RD);
+ }
+
+ // We have to ask the ABI about member pointers.
+ if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
+ return getCXXABI().isZeroInitializable(MPT);
+
+ // Everything else is okay.
+ return true;
+}
+
+bool CodeGenTypes::isZeroInitializable(const CXXRecordDecl *RD) {
+ return getCGRecordLayout(RD).isZeroInitializable();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
new file mode 100644
index 0000000..41513da
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
@@ -0,0 +1,224 @@
+//===--- CodeGenTypes.h - Type translation for LLVM CodeGen -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the code that handles AST -> LLVM type lowering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CODEGENTYPES_H
+#define CLANG_CODEGEN_CODEGENTYPES_H
+
+#include "CGCall.h"
+#include "GlobalDecl.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+
+namespace llvm {
+ class FunctionType;
+ class Module;
+ class OpaqueType;
+ class PATypeHolder;
+ class TargetData;
+ class Type;
+ class LLVMContext;
+}
+
+namespace clang {
+ class ABIInfo;
+ class ASTContext;
+ template <typename> class CanQual;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class FieldDecl;
+ class FunctionProtoType;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
+ class PointerType;
+ class QualType;
+ class RecordDecl;
+ class TagDecl;
+ class TargetInfo;
+ class Type;
+ typedef CanQual<Type> CanQualType;
+
+namespace CodeGen {
+ class CGCXXABI;
+ class CGRecordLayout;
+
+/// CodeGenTypes - This class organizes the cross-module state that is used
+/// while lowering AST types to LLVM types.
+class CodeGenTypes {
+ ASTContext &Context;
+ const TargetInfo &Target;
+ llvm::Module& TheModule;
+ const llvm::TargetData& TheTargetData;
+ const ABIInfo& TheABIInfo;
+ CGCXXABI &TheCXXABI;
+
+ llvm::SmallVector<std::pair<QualType,
+ llvm::OpaqueType *>, 8> PointersToResolve;
+
+ llvm::DenseMap<const Type*, llvm::PATypeHolder> TagDeclTypes;
+
+ llvm::DenseMap<const Type*, llvm::PATypeHolder> FunctionTypes;
+
+ /// The opaque type map for Objective-C interfaces. All direct
+ /// manipulation is done by the runtime interfaces, which are
+ /// responsible for coercing to the appropriate type; these opaque
+ /// types are never refined.
+ llvm::DenseMap<const ObjCInterfaceType*, const llvm::Type *> InterfaceTypes;
+
+ /// CGRecordLayouts - This maps llvm struct type with corresponding
+ /// record layout info.
+ llvm::DenseMap<const Type*, CGRecordLayout *> CGRecordLayouts;
+
+ /// FunctionInfos - Hold memoized CGFunctionInfo results.
+ llvm::FoldingSet<CGFunctionInfo> FunctionInfos;
+
+private:
+ /// TypeCache - This map keeps cache of llvm::Types (through PATypeHolder)
+ /// and maps llvm::Types to corresponding clang::Type. llvm::PATypeHolder is
+ /// used instead of llvm::Type because it allows us to bypass potential
+ /// dangling type pointers due to type refinement on llvm side.
+ llvm::DenseMap<const Type *, llvm::PATypeHolder> TypeCache;
+
+ /// ConvertNewType - Convert type T into a llvm::Type. Do not use this
+ /// method directly because it does not do any type caching. This method
+ /// is available only for ConvertType(). CovertType() is preferred
+ /// interface to convert type T into a llvm::Type.
+ const llvm::Type *ConvertNewType(QualType T);
+
+ /// HandleLateResolvedPointers - For top-level ConvertType calls, this handles
+ /// pointers that are referenced but have not been converted yet. This is
+ /// used to handle cyclic structures properly.
+ void HandleLateResolvedPointers();
+
+public:
+ CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
+ const ABIInfo &Info, CGCXXABI &CXXABI);
+ ~CodeGenTypes();
+
+ const llvm::TargetData &getTargetData() const { return TheTargetData; }
+ const TargetInfo &getTarget() const { return Target; }
+ ASTContext &getContext() const { return Context; }
+ const ABIInfo &getABIInfo() const { return TheABIInfo; }
+ CGCXXABI &getCXXABI() const { return TheCXXABI; }
+ llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
+
+ /// ConvertType - Convert type T into a llvm::Type.
+ const llvm::Type *ConvertType(QualType T, bool IsRecursive = false);
+ const llvm::Type *ConvertTypeRecursive(QualType T);
+
+ /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
+ /// ConvertType in that it is used to convert to the memory representation for
+ /// a type. For example, the scalar representation for _Bool is i1, but the
+ /// memory representation is usually i8 or i32, depending on the target.
+ const llvm::Type *ConvertTypeForMem(QualType T, bool IsRecursive = false);
+ const llvm::Type *ConvertTypeForMemRecursive(QualType T) {
+ return ConvertTypeForMem(T, true);
+ }
+
+ /// GetFunctionType - Get the LLVM function type for \arg Info.
+ const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info,
+ bool IsVariadic,
+ bool IsRecursive = false);
+
+ const llvm::FunctionType *GetFunctionType(GlobalDecl GD);
+
+ /// VerifyFuncTypeComplete - Utility to check whether a function type can
+ /// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag
+ /// type).
+ static const TagType *VerifyFuncTypeComplete(const Type* T);
+
+ /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
+ /// given a CXXMethodDecl. If the method to has an incomplete return type,
+ /// and/or incomplete argument types, this will return the opaque type.
+ const llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD);
+
+ const CGRecordLayout &getCGRecordLayout(const RecordDecl*);
+
+ /// UpdateCompletedType - When we find the full definition for a TagDecl,
+ /// replace the 'opaque' type we previously made for it if applicable.
+ void UpdateCompletedType(const TagDecl *TD);
+
+ /// getFunctionInfo - Get the function info for the specified function decl.
+ const CGFunctionInfo &getFunctionInfo(GlobalDecl GD);
+
+ const CGFunctionInfo &getFunctionInfo(const FunctionDecl *FD);
+ const CGFunctionInfo &getFunctionInfo(const CXXMethodDecl *MD);
+ const CGFunctionInfo &getFunctionInfo(const ObjCMethodDecl *MD);
+ const CGFunctionInfo &getFunctionInfo(const CXXConstructorDecl *D,
+ CXXCtorType Type);
+ const CGFunctionInfo &getFunctionInfo(const CXXDestructorDecl *D,
+ CXXDtorType Type);
+
+ const CGFunctionInfo &getFunctionInfo(const CallArgList &Args,
+ const FunctionType *Ty) {
+ return getFunctionInfo(Ty->getResultType(), Args,
+ Ty->getExtInfo());
+ }
+
+ const CGFunctionInfo &getFunctionInfo(CanQual<FunctionProtoType> Ty,
+ bool IsRecursive = false);
+ const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty,
+ bool IsRecursive = false);
+
+ /// getFunctionInfo - Get the function info for a member function of
+ /// the given type. This is used for calls through member function
+ /// pointers.
+ const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
+ const FunctionProtoType *FTP);
+
+ /// getFunctionInfo - Get the function info for a function described by a
+ /// return type and argument types. If the calling convention is not
+ /// specified, the "C" calling convention will be used.
+ const CGFunctionInfo &getFunctionInfo(QualType ResTy,
+ const CallArgList &Args,
+ const FunctionType::ExtInfo &Info);
+ const CGFunctionInfo &getFunctionInfo(QualType ResTy,
+ const FunctionArgList &Args,
+ const FunctionType::ExtInfo &Info);
+
+ /// Retrieves the ABI information for the given function signature.
+ ///
+ /// \param ArgTys - must all actually be canonical as params
+ const CGFunctionInfo &getFunctionInfo(CanQualType RetTy,
+ const llvm::SmallVectorImpl<CanQualType> &ArgTys,
+ const FunctionType::ExtInfo &Info,
+ bool IsRecursive = false);
+
+ /// \brief Compute a new LLVM record layout object for the given record.
+ CGRecordLayout *ComputeRecordLayout(const RecordDecl *D);
+
+public: // These are internal details of CGT that shouldn't be used externally.
+ /// ConvertTagDeclType - Lay out a tagged decl type like struct or union or
+ /// enum.
+ const llvm::Type *ConvertTagDeclType(const TagDecl *TD);
+
+ /// GetExpandedTypes - Expand the type \arg Ty into the LLVM
+ /// argument types it would be passed as on the provided vector \arg
+ /// ArgTys. See ABIArgInfo::Expand.
+ void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys,
+ bool IsRecursive);
+
+ /// IsZeroInitializable - Return whether a type can be
+ /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
+ bool isZeroInitializable(QualType T);
+
+ /// IsZeroInitializable - Return whether a record type can be
+ /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
+ bool isZeroInitializable(const CXXRecordDecl *RD);
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/GlobalDecl.h b/contrib/llvm/tools/clang/lib/CodeGen/GlobalDecl.h
new file mode 100644
index 0000000..c2f36d2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/GlobalDecl.h
@@ -0,0 +1,127 @@
+//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
+// together with its type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_GLOBALDECL_H
+#define CLANG_CODEGEN_GLOBALDECL_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/ABI.h"
+
+namespace clang {
+
+namespace CodeGen {
+
+/// GlobalDecl - represents a global declaration. This can either be a
+/// CXXConstructorDecl and the constructor type (Base, Complete).
+/// a CXXDestructorDecl and the destructor type (Base, Complete) or
+/// a VarDecl, a FunctionDecl or a BlockDecl.
+class GlobalDecl {
+ llvm::PointerIntPair<const Decl*, 2> Value;
+
+ void Init(const Decl *D) {
+ assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
+ assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
+
+ Value.setPointer(D);
+ }
+
+public:
+ GlobalDecl() {}
+
+ GlobalDecl(const VarDecl *D) { Init(D);}
+ GlobalDecl(const FunctionDecl *D) { Init(D); }
+ GlobalDecl(const BlockDecl *D) { Init(D); }
+ GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
+
+ GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
+ : Value(D, Type) {}
+ GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
+ : Value(D, Type) {}
+
+ GlobalDecl getCanonicalDecl() const {
+ GlobalDecl CanonGD;
+ CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
+ CanonGD.Value.setInt(Value.getInt());
+
+ return CanonGD;
+ }
+
+ const Decl *getDecl() const { return Value.getPointer(); }
+
+ CXXCtorType getCtorType() const {
+ assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
+ return static_cast<CXXCtorType>(Value.getInt());
+ }
+
+ CXXDtorType getDtorType() const {
+ assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
+ return static_cast<CXXDtorType>(Value.getInt());
+ }
+
+ friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
+ return LHS.Value == RHS.Value;
+ }
+
+ void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
+
+ static GlobalDecl getFromOpaquePtr(void *P) {
+ GlobalDecl GD;
+ GD.Value.setFromOpaqueValue(P);
+ return GD;
+ }
+
+ GlobalDecl getWithDecl(const Decl *D) {
+ GlobalDecl Result(*this);
+ Result.Value.setPointer(D);
+ return Result;
+ }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+namespace llvm {
+ template<class> struct DenseMapInfo;
+
+ template<> struct DenseMapInfo<clang::CodeGen::GlobalDecl> {
+ static inline clang::CodeGen::GlobalDecl getEmptyKey() {
+ return clang::CodeGen::GlobalDecl();
+ }
+
+ static inline clang::CodeGen::GlobalDecl getTombstoneKey() {
+ return clang::CodeGen::GlobalDecl::
+ getFromOpaquePtr(reinterpret_cast<void*>(-1));
+ }
+
+ static unsigned getHashValue(clang::CodeGen::GlobalDecl GD) {
+ return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
+ }
+
+ static bool isEqual(clang::CodeGen::GlobalDecl LHS,
+ clang::CodeGen::GlobalDecl RHS) {
+ return LHS == RHS;
+ }
+
+ };
+
+ // GlobalDecl isn't *technically* a POD type. However, its copy constructor,
+ // copy assignment operator, and destructor are all trivial.
+ template <>
+ struct isPodLike<clang::CodeGen::GlobalDecl> {
+ static const bool value = true;
+ };
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
new file mode 100644
index 0000000..95654a3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -0,0 +1,1168 @@
+//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ code generation targetting the Itanium C++ ABI. The class
+// in this file generates structures that follow the Itanium C++ ABI, which is
+// documented at:
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//
+// It also supports the closely-related ARM ABI, documented at:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGCXXABI.h"
+#include "CGRecordLayout.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include <clang/AST/Mangle.h>
+#include <clang/AST/Type.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Value.h>
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+class ItaniumCXXABI : public CodeGen::CGCXXABI {
+private:
+ const llvm::IntegerType *PtrDiffTy;
+protected:
+ bool IsARM;
+
+ // It's a little silly for us to cache this.
+ const llvm::IntegerType *getPtrDiffTy() {
+ if (!PtrDiffTy) {
+ QualType T = getContext().getPointerDiffType();
+ const llvm::Type *Ty = CGM.getTypes().ConvertTypeRecursive(T);
+ PtrDiffTy = cast<llvm::IntegerType>(Ty);
+ }
+ return PtrDiffTy;
+ }
+
+ bool NeedsArrayCookie(const CXXNewExpr *expr);
+ bool NeedsArrayCookie(const CXXDeleteExpr *expr,
+ QualType elementType);
+
+public:
+ ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
+ CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { }
+
+ bool isZeroInitializable(const MemberPointerType *MPT);
+
+ const llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
+
+ llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT);
+
+ llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src);
+
+ llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E);
+
+ llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
+
+ llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+ llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset);
+
+ llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *Addr,
+ const MemberPointerType *MPT);
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params);
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+
+ CharUnits GetArrayCookieSize(const CXXNewExpr *expr);
+ llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType);
+ void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ const CXXDeleteExpr *expr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+ void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::GlobalVariable *DeclPtr);
+};
+
+class ARMCXXABI : public ItaniumCXXABI {
+public:
+ ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params);
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+
+ void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
+
+ CharUnits GetArrayCookieSize(const CXXNewExpr *expr);
+ llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType);
+ void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ const CXXDeleteExpr *expr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+private:
+ /// \brief Returns true if the given instance method is one of the
+ /// kinds that the ARM ABI says returns 'this'.
+ static bool HasThisReturn(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||
+ (isa<CXXConstructorDecl>(MD)));
+ }
+};
+}
+
+CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
+ return new ItaniumCXXABI(CGM);
+}
+
+CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
+ return new ARMCXXABI(CGM);
+}
+
+const llvm::Type *
+ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
+ if (MPT->isMemberDataPointer())
+ return getPtrDiffTy();
+ else
+ return llvm::StructType::get(CGM.getLLVMContext(),
+ getPtrDiffTy(), getPtrDiffTy(), NULL);
+}
+
+/// In the Itanium and ARM ABIs, method pointers have the form:
+/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
+///
+/// In the Itanium ABI:
+/// - method pointers are virtual if (memptr.ptr & 1) is nonzero
+/// - the this-adjustment is (memptr.adj)
+/// - the virtual offset is (memptr.ptr - 1)
+///
+/// In the ARM ABI:
+/// - method pointers are virtual if (memptr.adj & 1) is nonzero
+/// - the this-adjustment is (memptr.adj >> 1)
+/// - the virtual offset is (memptr.ptr)
+/// ARM uses 'adj' for the virtual flag because Thumb functions
+/// may be only single-byte aligned.
+///
+/// If the member is virtual, the adjusted 'this' pointer points
+/// to a vtable pointer from which the virtual offset is applied.
+///
+/// If the member is non-virtual, memptr.ptr is the address of
+/// the function to call.
+llvm::Value *
+ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+
+ const llvm::FunctionType *FTy =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+
+ const llvm::IntegerType *ptrdiff = getPtrDiffTy();
+ llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1);
+
+ llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
+ llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
+ llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
+
+ // Extract memptr.adj, which is in the second field.
+ llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
+
+ // Compute the true adjustment.
+ llvm::Value *Adj = RawAdj;
+ if (IsARM)
+ Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
+
+ // Apply the adjustment and cast back to the original struct type
+ // for consistency.
+ llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
+ Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
+ This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
+
+ // Load the function pointer.
+ llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
+
+ // If the LSB in the function pointer is 1, the function pointer points to
+ // a virtual function.
+ llvm::Value *IsVirtual;
+ if (IsARM)
+ IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
+ else
+ IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
+ IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
+ Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
+
+ // In the virtual path, the adjustment left 'This' pointing to the
+ // vtable of the correct base subobject. The "function pointer" is an
+ // offset within the vtable (+1 for the virtual flag on non-ARM).
+ CGF.EmitBlock(FnVirtual);
+
+ // Cast the adjusted this to a pointer to vtable pointer and load.
+ const llvm::Type *VTableTy = Builder.getInt8PtrTy();
+ llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
+ VTable = Builder.CreateLoad(VTable, "memptr.vtable");
+
+ // Apply the offset.
+ llvm::Value *VTableOffset = FnAsInt;
+ if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
+ VTable = Builder.CreateGEP(VTable, VTableOffset);
+
+ // Load the virtual function to call.
+ VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
+ llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn");
+ CGF.EmitBranch(FnEnd);
+
+ // In the non-virtual path, the function pointer is actually a
+ // function pointer.
+ CGF.EmitBlock(FnNonVirtual);
+ llvm::Value *NonVirtualFn =
+ Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
+
+ // We're done.
+ CGF.EmitBlock(FnEnd);
+ llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
+ Callee->reserveOperandSpace(2);
+ Callee->addIncoming(VirtualFn, FnVirtual);
+ Callee->addIncoming(NonVirtualFn, FnNonVirtual);
+ return Callee;
+}
+
+/// Compute an l-value by applying the given pointer-to-member to a
+/// base object.
+llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ assert(MemPtr->getType() == getPtrDiffTy());
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace();
+
+ // Cast to char*.
+ Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
+
+ // Apply the offset, which we assume is non-null.
+ llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset");
+
+ // Cast the address to the appropriate pointer type, adopting the
+ // address space of the base pointer.
+ const llvm::Type *PType
+ = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
+ return Builder.CreateBitCast(Addr, PType);
+}
+
+/// Perform a derived-to-base or base-to-derived member pointer conversion.
+///
+/// Obligatory offset/adjustment diagram:
+/// <-- offset --> <-- adjustment -->
+/// |--------------------------|----------------------|--------------------|
+/// ^Derived address point ^Base address point ^Member address point
+///
+/// So when converting a base member pointer to a derived member pointer,
+/// we add the offset to the adjustment because the address point has
+/// decreased; and conversely, when converting a derived MP to a base MP
+/// we subtract the offset from the adjustment because the address point
+/// has increased.
+///
+/// The standard forbids (at compile time) conversion to and from
+/// virtual bases, which is why we don't have to consider them here.
+///
+/// The standard forbids (at run time) casting a derived MP to a base
+/// MP when the derived MP does not point to a member of the base.
+/// This is why -1 is a reasonable choice for null data member
+/// pointers.
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src) {
+ assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
+ E->getCastKind() == CK_BaseToDerivedMemberPointer);
+
+ if (isa<llvm::Constant>(Src))
+ return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E);
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->getAs<MemberPointerType>();
+ const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>();
+
+ const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl();
+ const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl();
+
+ bool DerivedToBase =
+ E->getCastKind() == CK_DerivedToBaseMemberPointer;
+
+ const CXXRecordDecl *DerivedDecl;
+ if (DerivedToBase)
+ DerivedDecl = SrcDecl;
+ else
+ DerivedDecl = DestDecl;
+
+ llvm::Constant *Adj =
+ CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ E->path_begin(),
+ E->path_end());
+ if (!Adj) return Src;
+
+ // For member data pointers, this is just a matter of adding the
+ // offset if the source is non-null.
+ if (SrcTy->isMemberDataPointer()) {
+ llvm::Value *Dst;
+ if (DerivedToBase)
+ Dst = Builder.CreateNSWSub(Src, Adj, "adj");
+ else
+ Dst = Builder.CreateNSWAdd(Src, Adj, "adj");
+
+ // Null check.
+ llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType());
+ llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull");
+ return Builder.CreateSelect(IsNull, Src, Dst);
+ }
+
+ // The this-adjustment is left-shifted by 1 on ARM.
+ if (IsARM) {
+ uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue();
+ Offset <<= 1;
+ Adj = llvm::ConstantInt::get(Adj->getType(), Offset);
+ }
+
+ llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj");
+ llvm::Value *DstAdj;
+ if (DerivedToBase)
+ DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj");
+ else
+ DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj");
+
+ return Builder.CreateInsertValue(Src, DstAdj, 1);
+}
+
+llvm::Constant *
+ItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E) {
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->getAs<MemberPointerType>();
+ const MemberPointerType *DestTy =
+ E->getType()->getAs<MemberPointerType>();
+
+ bool DerivedToBase =
+ E->getCastKind() == CK_DerivedToBaseMemberPointer;
+
+ const CXXRecordDecl *DerivedDecl;
+ if (DerivedToBase)
+ DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl();
+ else
+ DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl();
+
+ // Calculate the offset to the base class.
+ llvm::Constant *Offset =
+ CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ E->path_begin(),
+ E->path_end());
+ // If there's no offset, we're done.
+ if (!Offset) return C;
+
+ // If the source is a member data pointer, we have to do a null
+ // check and then add the offset. In the common case, we can fold
+ // away the offset.
+ if (SrcTy->isMemberDataPointer()) {
+ assert(C->getType() == getPtrDiffTy());
+
+ // If it's a constant int, just create a new constant int.
+ if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) {
+ int64_t Src = CI->getSExtValue();
+
+ // Null converts to null.
+ if (Src == -1) return CI;
+
+ // Otherwise, just add the offset.
+ int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue();
+ int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV);
+ return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true);
+ }
+
+ // Otherwise, we have to form a constant select expression.
+ llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType());
+
+ llvm::Constant *IsNull =
+ llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null);
+
+ llvm::Constant *Dst;
+ if (DerivedToBase)
+ Dst = llvm::ConstantExpr::getNSWSub(C, Offset);
+ else
+ Dst = llvm::ConstantExpr::getNSWAdd(C, Offset);
+
+ return llvm::ConstantExpr::getSelect(IsNull, Null, Dst);
+ }
+
+ // The this-adjustment is left-shifted by 1 on ARM.
+ if (IsARM) {
+ int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue();
+ OffsetV <<= 1;
+ Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV);
+ }
+
+ llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
+
+ llvm::Constant *Values[2] = { CS->getOperand(0), 0 };
+ if (DerivedToBase)
+ Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset);
+ else
+ Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
+
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
+ /*Packed=*/false);
+}
+
+
+llvm::Constant *
+ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
+ const llvm::Type *ptrdiff_t = getPtrDiffTy();
+
+ // Itanium C++ ABI 2.3:
+ // A NULL pointer is represented as -1.
+ if (MPT->isMemberDataPointer())
+ return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true);
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0);
+ llvm::Constant *Values[2] = { Zero, Zero };
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
+ /*Packed=*/false);
+}
+
+llvm::Constant *
+ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
+ CharUnits offset) {
+ // Itanium C++ ABI 2.3:
+ // A pointer to data member is an offset from the base address of
+ // the class object containing it, represented as a ptrdiff_t
+ return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity());
+}
+
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ assert(MD->isInstance() && "Member function must not be static!");
+ MD = MD->getCanonicalDecl();
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::Type *ptrdiff_t = getPtrDiffTy();
+
+ // Get the function pointer (or index if this is a virtual function).
+ llvm::Constant *MemPtr[2];
+ if (MD->isVirtual()) {
+ uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
+
+ // FIXME: We shouldn't use / 8 here.
+ uint64_t PointerWidthInBytes =
+ getContext().Target.getPointerWidth(0) / 8;
+ uint64_t VTableOffset = (Index * PointerWidthInBytes);
+
+ if (IsARM) {
+ // ARM C++ ABI 3.2.1:
+ // This ABI specifies that adj contains twice the this
+ // adjustment, plus 1 if the member function is virtual. The
+ // least significant bit of adj then makes exactly the same
+ // discrimination as the least significant bit of ptr does for
+ // Itanium.
+ MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1);
+ } else {
+ // Itanium C++ ABI 2.3:
+ // For a virtual function, [the pointer field] is 1 plus the
+ // virtual table offset (in bytes) of the function,
+ // represented as a ptrdiff_t.
+ MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ }
+ } else {
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty;
+ // Check whether the function has a computable LLVM signature.
+ if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+ // The function has a computable LLVM signature; use the correct type.
+ Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+ } else {
+ // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+ // function type is incomplete.
+ Ty = ptrdiff_t;
+ }
+
+ llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
+ MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ }
+
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(),
+ MemPtr, 2, /*Packed=*/false);
+}
+
+/// The comparison algorithm is pretty easy: the member pointers are
+/// the same if they're either bitwise identical *or* both null.
+///
+/// ARM is different here only because null-ness is more complicated.
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ llvm::ICmpInst::Predicate Eq;
+ llvm::Instruction::BinaryOps And, Or;
+ if (Inequality) {
+ Eq = llvm::ICmpInst::ICMP_NE;
+ And = llvm::Instruction::Or;
+ Or = llvm::Instruction::And;
+ } else {
+ Eq = llvm::ICmpInst::ICMP_EQ;
+ And = llvm::Instruction::And;
+ Or = llvm::Instruction::Or;
+ }
+
+ // Member data pointers are easy because there's a unique null
+ // value, so it just comes down to bitwise equality.
+ if (MPT->isMemberDataPointer())
+ return Builder.CreateICmp(Eq, L, R);
+
+ // For member function pointers, the tautologies are more complex.
+ // The Itanium tautology is:
+ // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj))
+ // The ARM tautology is:
+ // (L == R) <==> (L.ptr == R.ptr &&
+ // (L.adj == R.adj ||
+ // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0)))
+ // The inequality tautologies have exactly the same structure, except
+ // applying De Morgan's laws.
+
+ llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
+ llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
+
+ // This condition tests whether L.ptr == R.ptr. This must always be
+ // true for equality to hold.
+ llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
+
+ // This condition, together with the assumption that L.ptr == R.ptr,
+ // tests whether the pointers are both null. ARM imposes an extra
+ // condition.
+ llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
+ llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
+
+ // This condition tests whether L.adj == R.adj. If this isn't
+ // true, the pointers are unequal unless they're both null.
+ llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
+ llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
+ llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
+
+ // Null member function pointers on ARM clear the low bit of Adj,
+ // so the zero condition has to check that neither low bit is set.
+ if (IsARM) {
+ llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
+
+ // Compute (l.adj | r.adj) & 1 and test it against zero.
+ llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
+ llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
+ llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
+ "cmp.or.adj");
+ EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
+ }
+
+ // Tie together all our conditions.
+ llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
+ Result = Builder.CreateBinOp(And, PtrEq, Result,
+ Inequality ? "memptr.ne" : "memptr.eq");
+ return Result;
+}
+
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ /// For member data pointers, this is just a check against -1.
+ if (MPT->isMemberDataPointer()) {
+ assert(MemPtr->getType() == getPtrDiffTy());
+ llvm::Value *NegativeOne =
+ llvm::Constant::getAllOnesValue(MemPtr->getType());
+ return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
+ }
+
+ // In Itanium, a member function pointer is null if 'ptr' is null.
+ llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
+ llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
+
+ // In ARM, it's that, plus the low bit of 'adj' must be zero.
+ if (IsARM) {
+ llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
+ llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
+ llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
+ llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero,
+ "memptr.notvirtual");
+ Result = Builder.CreateAnd(Result, IsNotVirtual);
+ }
+
+ return Result;
+}
+
+/// The Itanium ABI requires non-zero initialization only for data
+/// member pointers, for which '0' is a valid offset.
+bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
+ return MPT->getPointeeType()->isFunctionType();
+}
+
+/// The generic ABI passes 'this', plus a VTT if it's initializing a
+/// base subobject.
+void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ASTContext &Context = getContext();
+
+ // 'this' is already there.
+
+ // Check if we need to add a VTT parameter (which has type void **).
+ if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
+ ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
+void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
+ ResTy = ArgTys[0];
+}
+
+/// The generic ABI passes 'this', plus a VTT if it's destroying a
+/// base subobject.
+void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ASTContext &Context = getContext();
+
+ // 'this' is already there.
+
+ // Check if we need to add a VTT parameter (which has type void **).
+ if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
+ ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
+/// for non-deleting destructors.
+void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
+
+ if (Type != Dtor_Deleting)
+ ResTy = ArgTys[0];
+}
+
+void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ /// Create the 'this' variable.
+ BuildThisParam(CGF, Params);
+
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+ assert(MD->isInstance());
+
+ // Check if we need a VTT parameter as well.
+ if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
+ ASTContext &Context = getContext();
+
+ // FIXME: avoid the fake decl
+ QualType T = Context.getPointerType(Context.VoidPtrTy);
+ ImplicitParamDecl *VTTDecl
+ = ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
+ &Context.Idents.get("vtt"), T);
+ Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType()));
+ getVTTDecl(CGF) = VTTDecl;
+ }
+}
+
+void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
+
+ // Return 'this' from certain constructors and destructors.
+ if (HasThisReturn(CGF.CurGD))
+ ResTy = Params[0].second;
+}
+
+void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ /// Initialize the 'this' slot.
+ EmitThisParam(CGF);
+
+ /// Initialize the 'vtt' slot if needed.
+ if (getVTTDecl(CGF)) {
+ getVTTValue(CGF)
+ = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
+ "vtt");
+ }
+}
+
+void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
+
+ /// Initialize the return slot to 'this' at the start of the
+ /// function.
+ if (HasThisReturn(CGF.CurGD))
+ CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue);
+}
+
+void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType) {
+ if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
+ return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
+
+ // Destructor thunks in the ARM ABI have indeterminate results.
+ const llvm::Type *T =
+ cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType();
+ RValue Undef = RValue::get(llvm::UndefValue::get(T));
+ return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
+}
+
+/************************** Array allocation cookies **************************/
+
+bool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) {
+ // If the class's usual deallocation function takes two arguments,
+ // it needs a cookie.
+ if (expr->doesUsualArrayDeleteWantSize())
+ return true;
+
+ // Otherwise, if the class has a non-trivial destructor, it always
+ // needs a cookie.
+ const CXXRecordDecl *record =
+ expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ return (record && !record->hasTrivialDestructor());
+}
+
+bool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr,
+ QualType elementType) {
+ // If the class's usual deallocation function takes two arguments,
+ // it needs a cookie.
+ if (expr->doesUsualArrayDeleteWantSize())
+ return true;
+
+ // Otherwise, if the class has a non-trivial destructor, it always
+ // needs a cookie.
+ const CXXRecordDecl *record =
+ elementType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+ return (record && !record->hasTrivialDestructor());
+}
+
+CharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
+ if (!NeedsArrayCookie(expr))
+ return CharUnits::Zero();
+
+ // Padding is the maximum of sizeof(size_t) and alignof(elementType)
+ ASTContext &Ctx = getContext();
+ return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
+ Ctx.getTypeAlignInChars(expr->getAllocatedType()));
+}
+
+llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) {
+ assert(NeedsArrayCookie(expr));
+
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
+
+ ASTContext &Ctx = getContext();
+ QualType SizeTy = Ctx.getSizeType();
+ CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy);
+
+ // The size of the cookie.
+ CharUnits CookieSize =
+ std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType));
+
+ // Compute an offset to the cookie.
+ llvm::Value *CookiePtr = NewPtr;
+ CharUnits CookieOffset = CookieSize - SizeSize;
+ if (!CookieOffset.isZero())
+ CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr,
+ CookieOffset.getQuantity());
+
+ // Write the number of elements into the appropriate slot.
+ llvm::Value *NumElementsPtr
+ = CGF.Builder.CreateBitCast(CookiePtr,
+ CGF.ConvertType(SizeTy)->getPointerTo(AS));
+ CGF.Builder.CreateStore(NumElements, NumElementsPtr);
+
+ // Finally, compute a pointer to the actual data buffer by skipping
+ // over the cookie completely.
+ return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
+ CookieSize.getQuantity());
+}
+
+void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ const CXXDeleteExpr *expr,
+ QualType ElementType,
+ llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr,
+ CharUnits &CookieSize) {
+ // Derive a char* in the same address space as the pointer.
+ unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
+ const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
+
+ // If we don't need an array cookie, bail out early.
+ if (!NeedsArrayCookie(expr, ElementType)) {
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ NumElements = 0;
+ CookieSize = CharUnits::Zero();
+ return;
+ }
+
+ QualType SizeTy = getContext().getSizeType();
+ CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
+ const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
+
+ CookieSize
+ = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType));
+
+ CharUnits NumElementsOffset = CookieSize - SizeSize;
+
+ // Compute the allocated pointer.
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ -CookieSize.getQuantity());
+
+ llvm::Value *NumElementsPtr = AllocPtr;
+ if (!NumElementsOffset.isZero())
+ NumElementsPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr,
+ NumElementsOffset.getQuantity());
+ NumElementsPtr =
+ CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
+ NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
+}
+
+CharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
+ if (!NeedsArrayCookie(expr))
+ return CharUnits::Zero();
+
+ // On ARM, the cookie is always:
+ // struct array_cookie {
+ // std::size_t element_size; // element_size != 0
+ // std::size_t element_count;
+ // };
+ // TODO: what should we do if the allocated type actually wants
+ // greater alignment?
+ return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2;
+}
+
+llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) {
+ assert(NeedsArrayCookie(expr));
+
+ // NewPtr is a char*.
+
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
+
+ ASTContext &Ctx = getContext();
+ CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType());
+ const llvm::IntegerType *SizeTy =
+ cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType()));
+
+ // The cookie is always at the start of the buffer.
+ llvm::Value *CookiePtr = NewPtr;
+
+ // The first element is the element size.
+ CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS));
+ llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy,
+ Ctx.getTypeSizeInChars(ElementType).getQuantity());
+ CGF.Builder.CreateStore(ElementSize, CookiePtr);
+
+ // The second element is the element count.
+ CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1);
+ CGF.Builder.CreateStore(NumElements, CookiePtr);
+
+ // Finally, compute a pointer to the actual data buffer by skipping
+ // over the cookie completely.
+ CharUnits CookieSize = 2 * SizeSize;
+ return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
+ CookieSize.getQuantity());
+}
+
+void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ const CXXDeleteExpr *expr,
+ QualType ElementType,
+ llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr,
+ CharUnits &CookieSize) {
+ // Derive a char* in the same address space as the pointer.
+ unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
+ const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
+
+ // If we don't need an array cookie, bail out early.
+ if (!NeedsArrayCookie(expr, ElementType)) {
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ NumElements = 0;
+ CookieSize = CharUnits::Zero();
+ return;
+ }
+
+ QualType SizeTy = getContext().getSizeType();
+ CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
+ const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
+
+ // The cookie size is always 2 * sizeof(size_t).
+ CookieSize = 2 * SizeSize;
+
+ // The allocated pointer is the input ptr, minus that amount.
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ -CookieSize.getQuantity());
+
+ // The number of elements is at offset sizeof(size_t) relative to that.
+ llvm::Value *NumElementsPtr
+ = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ SizeSize.getQuantity());
+ NumElementsPtr =
+ CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
+ NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
+}
+
+/*********************** Static local initialization **************************/
+
+static llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // int __cxa_guard_acquire(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
+ Args, /*isVarArg=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
+}
+
+static llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // void __cxa_guard_release(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ Args, /*isVarArg=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
+}
+
+static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
+ const llvm::PointerType *GuardPtrTy) {
+ // void __cxa_guard_abort(__guard *guard_object);
+
+ std::vector<const llvm::Type*> Args(1, GuardPtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
+ Args, /*isVarArg=*/false);
+
+ return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
+}
+
+namespace {
+ struct CallGuardAbort : EHScopeStack::Cleanup {
+ llvm::GlobalVariable *Guard;
+ CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard)
+ ->setDoesNotThrow();
+ }
+ };
+}
+
+/// The ARM code here follows the Itanium code closely enough that we
+/// just special-case it at particular places.
+void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ // We only need to use thread-safe statics for local variables;
+ // global initialization is always single-threaded.
+ bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics &&
+ D.isLocalVarDecl());
+
+ // Guard variables are 64 bits in the generic ABI and 32 bits on ARM.
+ const llvm::IntegerType *GuardTy
+ = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty());
+ const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo();
+
+ // Create the guard variable.
+ llvm::SmallString<256> GuardVName;
+ llvm::raw_svector_ostream Out(GuardVName);
+ getMangleContext().mangleItaniumGuardVariable(&D, Out);
+ Out.flush();
+
+ // Just absorb linkage and visibility from the variable.
+ llvm::GlobalVariable *GuardVariable =
+ new llvm::GlobalVariable(CGM.getModule(), GuardTy,
+ false, GV->getLinkage(),
+ llvm::ConstantInt::get(GuardTy, 0),
+ GuardVName.str());
+ GuardVariable->setVisibility(GV->getVisibility());
+
+ // Test whether the variable has completed initialization.
+ llvm::Value *IsInitialized;
+
+ // ARM C++ ABI 3.2.3.1:
+ // To support the potential use of initialization guard variables
+ // as semaphores that are the target of ARM SWP and LDREX/STREX
+ // synchronizing instructions we define a static initialization
+ // guard variable to be a 4-byte aligned, 4- byte word with the
+ // following inline access protocol.
+ // #define INITIALIZED 1
+ // if ((obj_guard & INITIALIZED) != INITIALIZED) {
+ // if (__cxa_guard_acquire(&obj_guard))
+ // ...
+ // }
+ if (IsARM) {
+ llvm::Value *V = Builder.CreateLoad(GuardVariable);
+ V = Builder.CreateAnd(V, Builder.getInt32(1));
+ IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+
+ // Itanium C++ ABI 3.3.2:
+ // The following is pseudo-code showing how these functions can be used:
+ // if (obj_guard.first_byte == 0) {
+ // if ( __cxa_guard_acquire (&obj_guard) ) {
+ // try {
+ // ... initialize the object ...;
+ // } catch (...) {
+ // __cxa_guard_abort (&obj_guard);
+ // throw;
+ // }
+ // ... queue object destructor with __cxa_atexit() ...;
+ // __cxa_guard_release (&obj_guard);
+ // }
+ // }
+ } else {
+ // Load the first byte of the guard variable.
+ const llvm::Type *PtrTy = Builder.getInt8PtrTy();
+ llvm::Value *V =
+ Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
+
+ IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized");
+ }
+
+ llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
+
+ // Check if the first byte of the guard variable is zero.
+ Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock);
+
+ CGF.EmitBlock(InitCheckBlock);
+
+ // Variables used when coping with thread-safe statics and exceptions.
+ if (ThreadsafeStatics) {
+ // Call __cxa_guard_acquire.
+ llvm::Value *V
+ = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable);
+
+ llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
+
+ Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
+ InitBlock, EndBlock);
+
+ // Call __cxa_guard_abort along the exceptional edge.
+ CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
+
+ CGF.EmitBlock(InitBlock);
+ }
+
+ // Emit the initializer and add a global destructor if appropriate.
+ CGF.EmitCXXGlobalVarDeclInit(D, GV);
+
+ if (ThreadsafeStatics) {
+ // Pop the guard-abort cleanup if we pushed one.
+ CGF.PopCleanupBlock();
+
+ // Call __cxa_guard_release. This cannot throw.
+ Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable);
+ } else {
+ Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable);
+ }
+
+ CGF.EmitBlock(EndBlock);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
new file mode 100644
index 0000000..3a63eba
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -0,0 +1,88 @@
+//===--- MicrosoftCXXABI.cpp - Emit LLVM Code from ASTs for a Module ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ code generation targetting the Microsoft Visual C++ ABI.
+// The class in this file generates structures that follow the Microsoft
+// Visual C++ ABI, which is actually not very well documented at all outside
+// of Microsoft.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGCXXABI.h"
+#include "CodeGenModule.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+
+class MicrosoftCXXABI : public CGCXXABI {
+public:
+ MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ // 'this' is already in place
+ // TODO: 'for base' flag
+ }
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ // 'this' is already in place
+ // TODO: 'for base' flag
+ }
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ BuildThisParam(CGF, Params);
+ // TODO: 'for base' flag
+ }
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ EmitThisParam(CGF);
+ // TODO: 'for base' flag
+ }
+
+ // ==== Notes on array cookies =========
+ //
+ // MSVC seems to only use cookies when the class has a destructor; a
+ // two-argument usual array deallocation function isn't sufficient.
+ //
+ // For example, this code prints "100" and "1":
+ // struct A {
+ // char x;
+ // void *operator new[](size_t sz) {
+ // printf("%u\n", sz);
+ // return malloc(sz);
+ // }
+ // void operator delete[](void *p, size_t sz) {
+ // printf("%u\n", sz);
+ // free(p);
+ // }
+ // };
+ // int main() {
+ // A *p = new A[100];
+ // delete[] p;
+ // }
+ // Whereas it prints "104" and "104" if you give A a destructor.
+};
+
+}
+
+CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
+ return new MicrosoftCXXABI(CGM);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
new file mode 100644
index 0000000..8945028
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -0,0 +1,120 @@
+//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This builds an AST and converts it to LLVM Code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "CodeGenModule.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/ADT/OwningPtr.h"
+using namespace clang;
+
+namespace {
+ class CodeGeneratorImpl : public CodeGenerator {
+ Diagnostic &Diags;
+ llvm::OwningPtr<const llvm::TargetData> TD;
+ ASTContext *Ctx;
+ const CodeGenOptions CodeGenOpts; // Intentionally copied in.
+ protected:
+ llvm::OwningPtr<llvm::Module> M;
+ llvm::OwningPtr<CodeGen::CodeGenModule> Builder;
+ public:
+ CodeGeneratorImpl(Diagnostic &diags, const std::string& ModuleName,
+ const CodeGenOptions &CGO, llvm::LLVMContext& C)
+ : Diags(diags), CodeGenOpts(CGO), M(new llvm::Module(ModuleName, C)) {}
+
+ virtual ~CodeGeneratorImpl() {}
+
+ virtual llvm::Module* GetModule() {
+ return M.get();
+ }
+
+ virtual llvm::Module* ReleaseModule() {
+ return M.take();
+ }
+
+ virtual void Initialize(ASTContext &Context) {
+ Ctx = &Context;
+
+ M->setTargetTriple(Ctx->Target.getTriple().getTriple());
+ M->setDataLayout(Ctx->Target.getTargetDescription());
+ TD.reset(new llvm::TargetData(Ctx->Target.getTargetDescription()));
+ Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts,
+ *M, *TD, Diags));
+ }
+
+ virtual void HandleTopLevelDecl(DeclGroupRef DG) {
+ // Make sure to emit all elements of a Decl.
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ Builder->EmitTopLevelDecl(*I);
+ }
+
+ /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
+ /// to (e.g. struct, union, enum, class) is completed. This allows the
+ /// client hack on the type, which can occur at any point in the file
+ /// (because these can be defined in declspecs).
+ virtual void HandleTagDeclDefinition(TagDecl *D) {
+ Builder->UpdateCompletedType(D);
+
+ // In C++, we may have member functions that need to be emitted at this
+ // point.
+ if (Ctx->getLangOptions().CPlusPlus && !D->isDependentContext()) {
+ for (DeclContext::decl_iterator M = D->decls_begin(),
+ MEnd = D->decls_end();
+ M != MEnd; ++M)
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*M))
+ if (Method->isThisDeclarationADefinition() &&
+ (Method->hasAttr<UsedAttr>() ||
+ Method->hasAttr<ConstructorAttr>()))
+ Builder->EmitTopLevelDecl(Method);
+ }
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ if (Diags.hasErrorOccurred()) {
+ M.reset();
+ return;
+ }
+
+ if (Builder)
+ Builder->Release();
+ }
+
+ virtual void CompleteTentativeDefinition(VarDecl *D) {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ Builder->EmitTentativeDefinition(D);
+ }
+
+ virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ Builder->EmitVTable(RD, DefinitionRequired);
+ }
+ };
+}
+
+CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags,
+ const std::string& ModuleName,
+ const CodeGenOptions &CGO,
+ llvm::LLVMContext& C) {
+ return new CodeGeneratorImpl(Diags, ModuleName, CGO, C);
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
new file mode 100644
index 0000000..d74b3f3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -0,0 +1,2861 @@
+//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetInfo.h"
+#include "ABIInfo.h"
+#include "CodeGenFunction.h"
+#include "clang/AST/RecordLayout.h"
+#include "llvm/Type.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+using namespace CodeGen;
+
+static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
+ llvm::Value *Array,
+ llvm::Value *Value,
+ unsigned FirstIndex,
+ unsigned LastIndex) {
+ // Alternatively, we could emit this as a loop in the source.
+ for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
+ llvm::Value *Cell = Builder.CreateConstInBoundsGEP1_32(Array, I);
+ Builder.CreateStore(Value, Cell);
+ }
+}
+
+static bool isAggregateTypeForABI(QualType T) {
+ return CodeGenFunction::hasAggregateLLVMType(T) ||
+ T->isMemberFunctionPointerType();
+}
+
+ABIInfo::~ABIInfo() {}
+
+ASTContext &ABIInfo::getContext() const {
+ return CGT.getContext();
+}
+
+llvm::LLVMContext &ABIInfo::getVMContext() const {
+ return CGT.getLLVMContext();
+}
+
+const llvm::TargetData &ABIInfo::getTargetData() const {
+ return CGT.getTargetData();
+}
+
+
+void ABIArgInfo::dump() const {
+ llvm::raw_ostream &OS = llvm::errs();
+ OS << "(ABIArgInfo Kind=";
+ switch (TheKind) {
+ case Direct:
+ OS << "Direct Type=";
+ if (const llvm::Type *Ty = getCoerceToType())
+ Ty->print(OS);
+ else
+ OS << "null";
+ break;
+ case Extend:
+ OS << "Extend";
+ break;
+ case Ignore:
+ OS << "Ignore";
+ break;
+ case Indirect:
+ OS << "Indirect Align=" << getIndirectAlign()
+ << " Byal=" << getIndirectByVal()
+ << " Realign=" << getIndirectRealign();
+ break;
+ case Expand:
+ OS << "Expand";
+ break;
+ }
+ OS << ")\n";
+}
+
+TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; }
+
+static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
+
+/// isEmptyField - Return true iff a the field is "empty", that is it
+/// is an unnamed bit-field or an (array of) empty record(s).
+static bool isEmptyField(ASTContext &Context, const FieldDecl *FD,
+ bool AllowArrays) {
+ if (FD->isUnnamedBitfield())
+ return true;
+
+ QualType FT = FD->getType();
+
+ // Constant arrays of empty records count as empty, strip them off.
+ if (AllowArrays)
+ while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT))
+ FT = AT->getElementType();
+
+ const RecordType *RT = FT->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ // C++ record fields are never empty, at least in the Itanium ABI.
+ //
+ // FIXME: We should use a predicate for whether this behavior is true in the
+ // current ABI.
+ if (isa<CXXRecordDecl>(RT->getDecl()))
+ return false;
+
+ return isEmptyRecord(Context, FT, AllowArrays);
+}
+
+/// isEmptyRecord - Return true iff a structure contains only empty
+/// fields. Note that a structure with a flexible array member is not
+/// considered empty.
+static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return 0;
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->hasFlexibleArrayMember())
+ return false;
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i)
+ if (!isEmptyRecord(Context, i->getType(), true))
+ return false;
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i)
+ if (!isEmptyField(Context, *i, AllowArrays))
+ return false;
+ return true;
+}
+
+/// hasNonTrivialDestructorOrCopyConstructor - Determine if a type has either
+/// a non-trivial destructor or a non-trivial copy constructor.
+static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) {
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ if (!RD)
+ return false;
+
+ return !RD->hasTrivialDestructor() || !RD->hasTrivialCopyConstructor();
+}
+
+/// isRecordWithNonTrivialDestructorOrCopyConstructor - Determine if a type is
+/// a record type with either a non-trivial destructor or a non-trivial copy
+/// constructor.
+static bool isRecordWithNonTrivialDestructorOrCopyConstructor(QualType T) {
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ return hasNonTrivialDestructorOrCopyConstructor(RT);
+}
+
+/// isSingleElementStruct - Determine if a structure is a "single
+/// element struct", i.e. it has exactly one non-empty field or
+/// exactly one field which is itself a single element
+/// struct. Structures with flexible array members are never
+/// considered single element structs.
+///
+/// \return The field declaration for the single non-empty field, if
+/// it exists.
+static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
+ const RecordType *RT = T->getAsStructureType();
+ if (!RT)
+ return 0;
+
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->hasFlexibleArrayMember())
+ return 0;
+
+ const Type *Found = 0;
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i) {
+ // Ignore empty records.
+ if (isEmptyRecord(Context, i->getType(), true))
+ continue;
+
+ // If we already found an element then this isn't a single-element struct.
+ if (Found)
+ return 0;
+
+ // If this is non-empty and not a single element struct, the composite
+ // cannot be a single element struct.
+ Found = isSingleElementStruct(i->getType(), Context);
+ if (!Found)
+ return 0;
+ }
+ }
+
+ // Check for single element.
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ QualType FT = FD->getType();
+
+ // Ignore empty fields.
+ if (isEmptyField(Context, FD, true))
+ continue;
+
+ // If we already found an element then this isn't a single-element
+ // struct.
+ if (Found)
+ return 0;
+
+ // Treat single element arrays as the element.
+ while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
+ if (AT->getSize().getZExtValue() != 1)
+ break;
+ FT = AT->getElementType();
+ }
+
+ if (!isAggregateTypeForABI(FT)) {
+ Found = FT.getTypePtr();
+ } else {
+ Found = isSingleElementStruct(FT, Context);
+ if (!Found)
+ return 0;
+ }
+ }
+
+ return Found;
+}
+
+static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) {
+ if (!Ty->getAs<BuiltinType>() && !Ty->hasPointerRepresentation() &&
+ !Ty->isAnyComplexType() && !Ty->isEnumeralType() &&
+ !Ty->isBlockPointerType())
+ return false;
+
+ uint64_t Size = Context.getTypeSize(Ty);
+ return Size == 32 || Size == 64;
+}
+
+/// canExpandIndirectArgument - Test whether an argument type which is to be
+/// passed indirectly (on the stack) would have the equivalent layout if it was
+/// expanded into separate arguments. If so, we prefer to do the latter to avoid
+/// inhibiting optimizations.
+///
+// FIXME: This predicate is missing many cases, currently it just follows
+// llvm-gcc (checks that all fields are 32-bit or 64-bit primitive types). We
+// should probably make this smarter, or better yet make the LLVM backend
+// capable of handling it.
+static bool canExpandIndirectArgument(QualType Ty, ASTContext &Context) {
+ // We can only expand structure types.
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ // We can only expand (C) structures.
+ //
+ // FIXME: This needs to be generalized to handle classes as well.
+ const RecordDecl *RD = RT->getDecl();
+ if (!RD->isStruct() || isa<CXXRecordDecl>(RD))
+ return false;
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+
+ if (!is32Or64BitBasicType(FD->getType(), Context))
+ return false;
+
+ // FIXME: Reject bit-fields wholesale; there are two problems, we don't know
+ // how to expand them yet, and the predicate for telling if a bitfield still
+ // counts as "basic" is more complicated than what we were doing previously.
+ if (FD->isBitField())
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+/// DefaultABIInfo - The default implementation for ABI specific
+/// details. This implementation provides information which results in
+/// self-consistent and sensible LLVM IR generation, but does not
+/// conform to any particular ABI.
+class DefaultABIInfo : public ABIInfo {
+public:
+ DefaultABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
+ }
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+};
+
+llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ return 0;
+}
+
+ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
+ if (isAggregateTypeForABI(Ty))
+ return ABIArgInfo::getIndirect(0);
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ if (isAggregateTypeForABI(RetTy))
+ return ABIArgInfo::getIndirect(0);
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+/// UseX86_MMXType - Return true if this is an MMX type that should use the special
+/// x86_mmx type.
+bool UseX86_MMXType(const llvm::Type *IRType) {
+ // If the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>, use the
+ // special x86_mmx type.
+ return IRType->isVectorTy() && IRType->getPrimitiveSizeInBits() == 64 &&
+ cast<llvm::VectorType>(IRType)->getElementType()->isIntegerTy() &&
+ IRType->getScalarSizeInBits() != 64;
+}
+
+static const llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
+ llvm::StringRef Constraint,
+ const llvm::Type* Ty) {
+ if (Constraint=="y" && Ty->isVectorTy())
+ return llvm::Type::getX86_MMXTy(CGF.getLLVMContext());
+ return Ty;
+}
+
+//===----------------------------------------------------------------------===//
+// X86-32 ABI Implementation
+//===----------------------------------------------------------------------===//
+
+/// X86_32ABIInfo - The X86-32 ABI information.
+class X86_32ABIInfo : public ABIInfo {
+ static const unsigned MinABIStackAlignInBytes = 4;
+
+ bool IsDarwinVectorABI;
+ bool IsSmallStructInRegABI;
+
+ static bool isRegisterSize(unsigned Size) {
+ return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
+ }
+
+ static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context);
+
+ /// getIndirectResult - Give a source type \arg Ty, return a suitable result
+ /// such that the argument will be passed in memory.
+ ABIArgInfo getIndirectResult(QualType Ty, bool ByVal = true) const;
+
+ /// \brief Return the alignment to use for the given type on the stack.
+ unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
+
+public:
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
+ }
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+
+ X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p)
+ : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p) {}
+};
+
+class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p)
+ :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p)) {}
+
+ void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const;
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
+ // Darwin uses different dwarf register numbers for EH.
+ if (CGM.isTargetDarwin()) return 5;
+
+ return 4;
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const;
+
+ const llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
+ llvm::StringRef Constraint,
+ const llvm::Type* Ty) const {
+ return X86AdjustInlineAsmType(CGF, Constraint, Ty);
+ }
+
+};
+
+}
+
+/// shouldReturnTypeInRegister - Determine if the given type should be
+/// passed in a register (for the Darwin ABI).
+bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
+ ASTContext &Context) {
+ uint64_t Size = Context.getTypeSize(Ty);
+
+ // Type must be register sized.
+ if (!isRegisterSize(Size))
+ return false;
+
+ if (Ty->isVectorType()) {
+ // 64- and 128- bit vectors inside structures are not returned in
+ // registers.
+ if (Size == 64 || Size == 128)
+ return false;
+
+ return true;
+ }
+
+ // If this is a builtin, pointer, enum, complex type, member pointer, or
+ // member function pointer it is ok.
+ if (Ty->getAs<BuiltinType>() || Ty->hasPointerRepresentation() ||
+ Ty->isAnyComplexType() || Ty->isEnumeralType() ||
+ Ty->isBlockPointerType() || Ty->isMemberPointerType())
+ return true;
+
+ // Arrays are treated like records.
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty))
+ return shouldReturnTypeInRegister(AT->getElementType(), Context);
+
+ // Otherwise, it must be a record type.
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (!RT) return false;
+
+ // FIXME: Traverse bases here too.
+
+ // Structure types are passed in register if all fields would be
+ // passed in a register.
+ for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(),
+ e = RT->getDecl()->field_end(); i != e; ++i) {
+ const FieldDecl *FD = *i;
+
+ // Empty fields are ignored.
+ if (isEmptyField(Context, FD, true))
+ continue;
+
+ // Check fields recursively.
+ if (!shouldReturnTypeInRegister(FD->getType(), Context))
+ return false;
+ }
+
+ return true;
+}
+
+ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ if (const VectorType *VT = RetTy->getAs<VectorType>()) {
+ // On Darwin, some vectors are returned in registers.
+ if (IsDarwinVectorABI) {
+ uint64_t Size = getContext().getTypeSize(RetTy);
+
+ // 128-bit vectors are a special case; they are returned in
+ // registers and we need to make sure to pick a type the LLVM
+ // backend will like.
+ if (Size == 128)
+ return ABIArgInfo::getDirect(llvm::VectorType::get(
+ llvm::Type::getInt64Ty(getVMContext()), 2));
+
+ // Always return in register if it fits in a general purpose
+ // register, or if it is 64 bits and has a single element.
+ if ((Size == 8 || Size == 16 || Size == 32) ||
+ (Size == 64 && VT->getNumElements() == 1))
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+
+ return ABIArgInfo::getIndirect(0);
+ }
+
+ return ABIArgInfo::getDirect();
+ }
+
+ if (isAggregateTypeForABI(RetTy)) {
+ if (const RecordType *RT = RetTy->getAs<RecordType>()) {
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (hasNonTrivialDestructorOrCopyConstructor(RT))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Structures with flexible arrays are always indirect.
+ if (RT->getDecl()->hasFlexibleArrayMember())
+ return ABIArgInfo::getIndirect(0);
+ }
+
+ // If specified, structs and unions are always indirect.
+ if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
+ return ABIArgInfo::getIndirect(0);
+
+ // Classify "single element" structs as their element type.
+ if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) {
+ if (const BuiltinType *BT = SeltTy->getAs<BuiltinType>()) {
+ if (BT->isIntegerType()) {
+ // We need to use the size of the structure, padding
+ // bit-fields can adjust that to be larger than the single
+ // element type.
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ return ABIArgInfo::getDirect(
+ llvm::IntegerType::get(getVMContext(), (unsigned)Size));
+ }
+
+ if (BT->getKind() == BuiltinType::Float) {
+ assert(getContext().getTypeSize(RetTy) ==
+ getContext().getTypeSize(SeltTy) &&
+ "Unexpect single element structure size!");
+ return ABIArgInfo::getDirect(llvm::Type::getFloatTy(getVMContext()));
+ }
+
+ if (BT->getKind() == BuiltinType::Double) {
+ assert(getContext().getTypeSize(RetTy) ==
+ getContext().getTypeSize(SeltTy) &&
+ "Unexpect single element structure size!");
+ return ABIArgInfo::getDirect(llvm::Type::getDoubleTy(getVMContext()));
+ }
+ } else if (SeltTy->isPointerType()) {
+ // FIXME: It would be really nice if this could come out as the proper
+ // pointer type.
+ const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(getVMContext());
+ return ABIArgInfo::getDirect(PtrTy);
+ } else if (SeltTy->isVectorType()) {
+ // 64- and 128-bit vectors are never returned in a
+ // register when inside a structure.
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size == 64 || Size == 128)
+ return ABIArgInfo::getIndirect(0);
+
+ return classifyReturnType(QualType(SeltTy, 0));
+ }
+ }
+
+ // Small structures which are register sized are generally returned
+ // in a register.
+ if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) {
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
+ }
+
+ return ABIArgInfo::getIndirect(0);
+ }
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+static bool isRecordWithSSEVectorType(ASTContext &Context, QualType Ty) {
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (!RT)
+ return 0;
+ const RecordDecl *RD = RT->getDecl();
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i)
+ if (!isRecordWithSSEVectorType(Context, i->getType()))
+ return false;
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ QualType FT = i->getType();
+
+ if (FT->getAs<VectorType>() && Context.getTypeSize(Ty) == 128)
+ return true;
+
+ if (isRecordWithSSEVectorType(Context, FT))
+ return true;
+ }
+
+ return false;
+}
+
+unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
+ unsigned Align) const {
+ // Otherwise, if the alignment is less than or equal to the minimum ABI
+ // alignment, just use the default; the backend will handle this.
+ if (Align <= MinABIStackAlignInBytes)
+ return 0; // Use default alignment.
+
+ // On non-Darwin, the stack type alignment is always 4.
+ if (!IsDarwinVectorABI) {
+ // Set explicit alignment, since we may need to realign the top.
+ return MinABIStackAlignInBytes;
+ }
+
+ // Otherwise, if the type contains an SSE vector type, the alignment is 16.
+ if (isRecordWithSSEVectorType(getContext(), Ty))
+ return 16;
+
+ return MinABIStackAlignInBytes;
+}
+
+ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal) const {
+ if (!ByVal)
+ return ABIArgInfo::getIndirect(0, false);
+
+ // Compute the byval alignment.
+ unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
+ unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign);
+ if (StackAlign == 0)
+ return ABIArgInfo::getIndirect(0);
+
+ // If the stack alignment is less than the type alignment, realign the
+ // argument.
+ if (StackAlign < TypeAlign)
+ return ABIArgInfo::getIndirect(StackAlign, /*ByVal=*/true,
+ /*Realign=*/true);
+
+ return ABIArgInfo::getIndirect(StackAlign);
+}
+
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
+ // FIXME: Set alignment on indirect arguments.
+ if (isAggregateTypeForABI(Ty)) {
+ // Structures with flexible arrays are always indirect.
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (hasNonTrivialDestructorOrCopyConstructor(RT))
+ return getIndirectResult(Ty, /*ByVal=*/false);
+
+ if (RT->getDecl()->hasFlexibleArrayMember())
+ return getIndirectResult(Ty);
+ }
+
+ // Ignore empty structs.
+ if (Ty->isStructureType() && getContext().getTypeSize(Ty) == 0)
+ return ABIArgInfo::getIgnore();
+
+ // Expand small (<= 128-bit) record types when we know that the stack layout
+ // of those arguments will match the struct. This is important because the
+ // LLVM backend isn't smart enough to remove byval, which inhibits many
+ // optimizations.
+ if (getContext().getTypeSize(Ty) <= 4*32 &&
+ canExpandIndirectArgument(Ty, getContext()))
+ return ABIArgInfo::getExpand();
+
+ return getIndirectResult(Ty);
+ }
+
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ // On Darwin, some vectors are passed in memory, we handle this by passing
+ // it as an i8/i16/i32/i64.
+ if (IsDarwinVectorABI) {
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if ((Size == 8 || Size == 16 || Size == 32) ||
+ (Size == 64 && VT->getNumElements() == 1))
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+ }
+
+ const llvm::Type *IRType = CGT.ConvertTypeRecursive(Ty);
+ if (UseX86_MMXType(IRType)) {
+ ABIArgInfo AAI = ABIArgInfo::getDirect(IRType);
+ AAI.setCoerceToType(llvm::Type::getX86_MMXTy(getVMContext()));
+ return AAI;
+ }
+
+ return ABIArgInfo::getDirect();
+ }
+
+
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
+ "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *PTy =
+ llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
+}
+
+void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
+ // Get the LLVM function.
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+
+ // Now add the 'alignstack' attribute with a value of 16.
+ Fn->addFnAttr(llvm::Attribute::constructStackAlignmentFromInt(16));
+ }
+ }
+}
+
+bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
+ CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
+
+ // 0-7 are the eight integer registers; the order is different
+ // on Darwin (for EH), but the range is the same.
+ // 8 is %eip.
+ AssignToArrayRange(Builder, Address, Four8, 0, 8);
+
+ if (CGF.CGM.isTargetDarwin()) {
+ // 12-16 are st(0..4). Not sure why we stop at 4.
+ // These have size 16, which is sizeof(long double) on
+ // platforms with 8-byte alignment for that type.
+ llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16);
+ AssignToArrayRange(Builder, Address, Sixteen8, 12, 16);
+
+ } else {
+ // 9 is %eflags, which doesn't get a size on Darwin for some
+ // reason.
+ Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9));
+
+ // 11-16 are st(0..5). Not sure why we stop at 5.
+ // These have size 12, which is sizeof(long double) on
+ // platforms with 4-byte alignment for that type.
+ llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12);
+ AssignToArrayRange(Builder, Address, Twelve8, 11, 16);
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// X86-64 ABI Implementation
+//===----------------------------------------------------------------------===//
+
+
+namespace {
+/// X86_64ABIInfo - The X86_64 ABI information.
+class X86_64ABIInfo : public ABIInfo {
+ enum Class {
+ Integer = 0,
+ SSE,
+ SSEUp,
+ X87,
+ X87Up,
+ ComplexX87,
+ NoClass,
+ Memory
+ };
+
+ /// merge - Implement the X86_64 ABI merging algorithm.
+ ///
+ /// Merge an accumulating classification \arg Accum with a field
+ /// classification \arg Field.
+ ///
+ /// \param Accum - The accumulating classification. This should
+ /// always be either NoClass or the result of a previous merge
+ /// call. In addition, this should never be Memory (the caller
+ /// should just return Memory for the aggregate).
+ static Class merge(Class Accum, Class Field);
+
+ /// classify - Determine the x86_64 register classes in which the
+ /// given type T should be passed.
+ ///
+ /// \param Lo - The classification for the parts of the type
+ /// residing in the low word of the containing object.
+ ///
+ /// \param Hi - The classification for the parts of the type
+ /// residing in the high word of the containing object.
+ ///
+ /// \param OffsetBase - The bit offset of this type in the
+ /// containing object. Some parameters are classified different
+ /// depending on whether they straddle an eightbyte boundary.
+ ///
+ /// If a word is unused its result will be NoClass; if a type should
+ /// be passed in Memory then at least the classification of \arg Lo
+ /// will be Memory.
+ ///
+ /// The \arg Lo class will be NoClass iff the argument is ignored.
+ ///
+ /// If the \arg Lo class is ComplexX87, then the \arg Hi class will
+ /// also be ComplexX87.
+ void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi) const;
+
+ const llvm::Type *Get16ByteVectorType(QualType Ty) const;
+ const llvm::Type *GetSSETypeAtOffset(const llvm::Type *IRType,
+ unsigned IROffset, QualType SourceTy,
+ unsigned SourceOffset) const;
+ const llvm::Type *GetINTEGERTypeAtOffset(const llvm::Type *IRType,
+ unsigned IROffset, QualType SourceTy,
+ unsigned SourceOffset) const;
+
+ /// getIndirectResult - Give a source type \arg Ty, return a suitable result
+ /// such that the argument will be returned in memory.
+ ABIArgInfo getIndirectReturnResult(QualType Ty) const;
+
+ /// getIndirectResult - Give a source type \arg Ty, return a suitable result
+ /// such that the argument will be passed in memory.
+ ABIArgInfo getIndirectResult(QualType Ty) const;
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+
+ ABIArgInfo classifyArgumentType(QualType Ty,
+ unsigned &neededInt,
+ unsigned &neededSSE) const;
+
+public:
+ X86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ virtual void computeInfo(CGFunctionInfo &FI) const;
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+/// WinX86_64ABIInfo - The Windows X86_64 ABI information.
+class WinX86_64ABIInfo : public ABIInfo {
+
+ ABIArgInfo classify(QualType Ty) const;
+
+public:
+ WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ virtual void computeInfo(CGFunctionInfo &FI) const;
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new X86_64ABIInfo(CGT)) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
+ return 7;
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
+
+ // 0-15 are the 16 integer registers.
+ // 16 is %rip.
+ AssignToArrayRange(Builder, Address, Eight8, 0, 16);
+
+ return false;
+ }
+
+ const llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
+ llvm::StringRef Constraint,
+ const llvm::Type* Ty) const {
+ return X86AdjustInlineAsmType(CGF, Constraint, Ty);
+ }
+
+};
+
+class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
+ return 7;
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
+
+ // 0-15 are the 16 integer registers.
+ // 16 is %rip.
+ AssignToArrayRange(Builder, Address, Eight8, 0, 16);
+
+ return false;
+ }
+};
+
+}
+
+X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum, Class Field) {
+ // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
+ // classified recursively so that always two fields are
+ // considered. The resulting class is calculated according to
+ // the classes of the fields in the eightbyte:
+ //
+ // (a) If both classes are equal, this is the resulting class.
+ //
+ // (b) If one of the classes is NO_CLASS, the resulting class is
+ // the other class.
+ //
+ // (c) If one of the classes is MEMORY, the result is the MEMORY
+ // class.
+ //
+ // (d) If one of the classes is INTEGER, the result is the
+ // INTEGER.
+ //
+ // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class,
+ // MEMORY is used as class.
+ //
+ // (f) Otherwise class SSE is used.
+
+ // Accum should never be memory (we should have returned) or
+ // ComplexX87 (because this cannot be passed in a structure).
+ assert((Accum != Memory && Accum != ComplexX87) &&
+ "Invalid accumulated classification during merge.");
+ if (Accum == Field || Field == NoClass)
+ return Accum;
+ if (Field == Memory)
+ return Memory;
+ if (Accum == NoClass)
+ return Field;
+ if (Accum == Integer || Field == Integer)
+ return Integer;
+ if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
+ Accum == X87 || Accum == X87Up)
+ return Memory;
+ return SSE;
+}
+
+void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
+ Class &Lo, Class &Hi) const {
+ // FIXME: This code can be simplified by introducing a simple value class for
+ // Class pairs with appropriate constructor methods for the various
+ // situations.
+
+ // FIXME: Some of the split computations are wrong; unaligned vectors
+ // shouldn't be passed in registers for example, so there is no chance they
+ // can straddle an eightbyte. Verify & simplify.
+
+ Lo = Hi = NoClass;
+
+ Class &Current = OffsetBase < 64 ? Lo : Hi;
+ Current = Memory;
+
+ if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
+ BuiltinType::Kind k = BT->getKind();
+
+ if (k == BuiltinType::Void) {
+ Current = NoClass;
+ } else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
+ Lo = Integer;
+ Hi = Integer;
+ } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
+ Current = Integer;
+ } else if (k == BuiltinType::Float || k == BuiltinType::Double) {
+ Current = SSE;
+ } else if (k == BuiltinType::LongDouble) {
+ Lo = X87;
+ Hi = X87Up;
+ }
+ // FIXME: _Decimal32 and _Decimal64 are SSE.
+ // FIXME: _float128 and _Decimal128 are (SSE, SSEUp).
+ return;
+ }
+
+ if (const EnumType *ET = Ty->getAs<EnumType>()) {
+ // Classify the underlying integer type.
+ classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi);
+ return;
+ }
+
+ if (Ty->hasPointerRepresentation()) {
+ Current = Integer;
+ return;
+ }
+
+ if (Ty->isMemberPointerType()) {
+ if (Ty->isMemberFunctionPointerType())
+ Lo = Hi = Integer;
+ else
+ Current = Integer;
+ return;
+ }
+
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ uint64_t Size = getContext().getTypeSize(VT);
+ if (Size == 32) {
+ // gcc passes all <4 x char>, <2 x short>, <1 x int>, <1 x
+ // float> as integer.
+ Current = Integer;
+
+ // If this type crosses an eightbyte boundary, it should be
+ // split.
+ uint64_t EB_Real = (OffsetBase) / 64;
+ uint64_t EB_Imag = (OffsetBase + Size - 1) / 64;
+ if (EB_Real != EB_Imag)
+ Hi = Lo;
+ } else if (Size == 64) {
+ // gcc passes <1 x double> in memory. :(
+ if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::Double))
+ return;
+
+ // gcc passes <1 x long long> as INTEGER.
+ if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::LongLong) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::ULongLong) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::Long) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::ULong))
+ Current = Integer;
+ else
+ Current = SSE;
+
+ // If this type crosses an eightbyte boundary, it should be
+ // split.
+ if (OffsetBase && OffsetBase != 64)
+ Hi = Lo;
+ } else if (Size == 128) {
+ Lo = SSE;
+ Hi = SSEUp;
+ }
+ return;
+ }
+
+ if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
+ QualType ET = getContext().getCanonicalType(CT->getElementType());
+
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if (ET->isIntegralOrEnumerationType()) {
+ if (Size <= 64)
+ Current = Integer;
+ else if (Size <= 128)
+ Lo = Hi = Integer;
+ } else if (ET == getContext().FloatTy)
+ Current = SSE;
+ else if (ET == getContext().DoubleTy)
+ Lo = Hi = SSE;
+ else if (ET == getContext().LongDoubleTy)
+ Current = ComplexX87;
+
+ // If this complex type crosses an eightbyte boundary then it
+ // should be split.
+ uint64_t EB_Real = (OffsetBase) / 64;
+ uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
+ if (Hi == NoClass && EB_Real != EB_Imag)
+ Hi = Lo;
+
+ return;
+ }
+
+ if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
+ // Arrays are treated like structures.
+
+ uint64_t Size = getContext().getTypeSize(Ty);
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
+ // than two eightbytes, ..., it has class MEMORY.
+ if (Size > 128)
+ return;
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
+ // fields, it has class MEMORY.
+ //
+ // Only need to check alignment of array base.
+ if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
+ return;
+
+ // Otherwise implement simplified merge. We could be smarter about
+ // this, but it isn't worth it and would be harder to verify.
+ Current = NoClass;
+ uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
+ uint64_t ArraySize = AT->getSize().getZExtValue();
+ for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
+ Class FieldLo, FieldHi;
+ classify(AT->getElementType(), Offset, FieldLo, FieldHi);
+ Lo = merge(Lo, FieldLo);
+ Hi = merge(Hi, FieldHi);
+ if (Lo == Memory || Hi == Memory)
+ break;
+ }
+
+ // Do post merger cleanup (see below). Only case we worry about is Memory.
+ if (Hi == Memory)
+ Lo = Memory;
+ assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp array classification.");
+ return;
+ }
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ uint64_t Size = getContext().getTypeSize(Ty);
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
+ // than two eightbytes, ..., it has class MEMORY.
+ if (Size > 128)
+ return;
+
+ // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
+ // copy constructor or a non-trivial destructor, it is passed by invisible
+ // reference.
+ if (hasNonTrivialDestructorOrCopyConstructor(RT))
+ return;
+
+ const RecordDecl *RD = RT->getDecl();
+
+ // Assume variable sized types are passed in memory.
+ if (RD->hasFlexibleArrayMember())
+ return;
+
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+
+ // Reset Lo class, this will be recomputed.
+ Current = NoClass;
+
+ // If this is a C++ record, classify the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i) {
+ assert(!i->isVirtual() && !i->getType()->isDependentType() &&
+ "Unexpected base class!");
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+ // Classify this field.
+ //
+ // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate exceeds a
+ // single eightbyte, each is classified separately. Each eightbyte gets
+ // initialized to class NO_CLASS.
+ Class FieldLo, FieldHi;
+ uint64_t Offset = OffsetBase + Layout.getBaseClassOffsetInBits(Base);
+ classify(i->getType(), Offset, FieldLo, FieldHi);
+ Lo = merge(Lo, FieldLo);
+ Hi = merge(Hi, FieldHi);
+ if (Lo == Memory || Hi == Memory)
+ break;
+ }
+ }
+
+ // Classify the fields one at a time, merging the results.
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i, ++idx) {
+ uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
+ bool BitField = i->isBitField();
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
+ // fields, it has class MEMORY.
+ //
+ // Note, skip this test for bit-fields, see below.
+ if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+ Lo = Memory;
+ return;
+ }
+
+ // Classify this field.
+ //
+ // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate
+ // exceeds a single eightbyte, each is classified
+ // separately. Each eightbyte gets initialized to class
+ // NO_CLASS.
+ Class FieldLo, FieldHi;
+
+ // Bit-fields require special handling, they do not force the
+ // structure to be passed in memory even if unaligned, and
+ // therefore they can straddle an eightbyte.
+ if (BitField) {
+ // Ignore padding bit-fields.
+ if (i->isUnnamedBitfield())
+ continue;
+
+ uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
+ uint64_t Size =
+ i->getBitWidth()->EvaluateAsInt(getContext()).getZExtValue();
+
+ uint64_t EB_Lo = Offset / 64;
+ uint64_t EB_Hi = (Offset + Size - 1) / 64;
+ FieldLo = FieldHi = NoClass;
+ if (EB_Lo) {
+ assert(EB_Hi == EB_Lo && "Invalid classification, type > 16 bytes.");
+ FieldLo = NoClass;
+ FieldHi = Integer;
+ } else {
+ FieldLo = Integer;
+ FieldHi = EB_Hi ? Integer : NoClass;
+ }
+ } else
+ classify(i->getType(), Offset, FieldLo, FieldHi);
+ Lo = merge(Lo, FieldLo);
+ Hi = merge(Hi, FieldHi);
+ if (Lo == Memory || Hi == Memory)
+ break;
+ }
+
+ // AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done:
+ //
+ // (a) If one of the classes is MEMORY, the whole argument is
+ // passed in memory.
+ //
+ // (b) If SSEUP is not preceeded by SSE, it is converted to SSE.
+
+ // The first of these conditions is guaranteed by how we implement
+ // the merge (just bail).
+ //
+ // The second condition occurs in the case of unions; for example
+ // union { _Complex double; unsigned; }.
+ if (Hi == Memory)
+ Lo = Memory;
+ if (Hi == SSEUp && Lo != SSE)
+ Hi = SSE;
+ }
+}
+
+ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
+ // If this is a scalar LLVM value then assume LLVM will pass it in the right
+ // place naturally.
+ if (!isAggregateTypeForABI(Ty)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ }
+
+ return ABIArgInfo::getIndirect(0);
+}
+
+ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty) const {
+ // If this is a scalar LLVM value then assume LLVM will pass it in the right
+ // place naturally.
+ if (!isAggregateTypeForABI(Ty)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ }
+
+ if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Compute the byval alignment. We trust the back-end to honor the
+ // minimum ABI alignment for byval, to make cleaner IR.
+ const unsigned MinABIAlign = 8;
+ unsigned Align = getContext().getTypeAlign(Ty) / 8;
+ if (Align > MinABIAlign)
+ return ABIArgInfo::getIndirect(Align);
+ return ABIArgInfo::getIndirect(0);
+}
+
+/// Get16ByteVectorType - The ABI specifies that a value should be passed in an
+/// full vector XMM register. Pick an LLVM IR type that will be passed as a
+/// vector register.
+const llvm::Type *X86_64ABIInfo::Get16ByteVectorType(QualType Ty) const {
+ const llvm::Type *IRType = CGT.ConvertTypeRecursive(Ty);
+
+ // Wrapper structs that just contain vectors are passed just like vectors,
+ // strip them off if present.
+ const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType);
+ while (STy && STy->getNumElements() == 1) {
+ IRType = STy->getElementType(0);
+ STy = dyn_cast<llvm::StructType>(IRType);
+ }
+
+ // If the preferred type is a 16-byte vector, prefer to pass it.
+ if (const llvm::VectorType *VT = dyn_cast<llvm::VectorType>(IRType)){
+ const llvm::Type *EltTy = VT->getElementType();
+ if (VT->getBitWidth() == 128 &&
+ (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
+ EltTy->isIntegerTy(8) || EltTy->isIntegerTy(16) ||
+ EltTy->isIntegerTy(32) || EltTy->isIntegerTy(64) ||
+ EltTy->isIntegerTy(128)))
+ return VT;
+ }
+
+ return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()), 2);
+}
+
+/// BitsContainNoUserData - Return true if the specified [start,end) bit range
+/// is known to either be off the end of the specified type or being in
+/// alignment padding. The user type specified is known to be at most 128 bits
+/// in size, and have passed through X86_64ABIInfo::classify with a successful
+/// classification that put one of the two halves in the INTEGER class.
+///
+/// It is conservatively correct to return false.
+static bool BitsContainNoUserData(QualType Ty, unsigned StartBit,
+ unsigned EndBit, ASTContext &Context) {
+ // If the bytes being queried are off the end of the type, there is no user
+ // data hiding here. This handles analysis of builtins, vectors and other
+ // types that don't contain interesting padding.
+ unsigned TySize = (unsigned)Context.getTypeSize(Ty);
+ if (TySize <= StartBit)
+ return true;
+
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
+ unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType());
+ unsigned NumElts = (unsigned)AT->getSize().getZExtValue();
+
+ // Check each element to see if the element overlaps with the queried range.
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // If the element is after the span we care about, then we're done..
+ unsigned EltOffset = i*EltSize;
+ if (EltOffset >= EndBit) break;
+
+ unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
+ if (!BitsContainNoUserData(AT->getElementType(), EltStart,
+ EndBit-EltOffset, Context))
+ return false;
+ }
+ // If it overlaps no elements, then it is safe to process as padding.
+ return true;
+ }
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i) {
+ assert(!i->isVirtual() && !i->getType()->isDependentType() &&
+ "Unexpected base class!");
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+ // If the base is after the span we care about, ignore it.
+ unsigned BaseOffset = (unsigned)Layout.getBaseClassOffsetInBits(Base);
+ if (BaseOffset >= EndBit) continue;
+
+ unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
+ if (!BitsContainNoUserData(i->getType(), BaseStart,
+ EndBit-BaseOffset, Context))
+ return false;
+ }
+ }
+
+ // Verify that no field has data that overlaps the region of interest. Yes
+ // this could be sped up a lot by being smarter about queried fields,
+ // however we're only looking at structs up to 16 bytes, so we don't care
+ // much.
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i, ++idx) {
+ unsigned FieldOffset = (unsigned)Layout.getFieldOffset(idx);
+
+ // If we found a field after the region we care about, then we're done.
+ if (FieldOffset >= EndBit) break;
+
+ unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
+ if (!BitsContainNoUserData(i->getType(), FieldStart, EndBit-FieldOffset,
+ Context))
+ return false;
+ }
+
+ // If nothing in this record overlapped the area of interest, then we're
+ // clean.
+ return true;
+ }
+
+ return false;
+}
+
+/// ContainsFloatAtOffset - Return true if the specified LLVM IR type has a
+/// float member at the specified offset. For example, {int,{float}} has a
+/// float at offset 4. It is conservatively correct for this routine to return
+/// false.
+static bool ContainsFloatAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ const llvm::TargetData &TD) {
+ // Base case if we find a float.
+ if (IROffset == 0 && IRType->isFloatTy())
+ return true;
+
+ // If this is a struct, recurse into the field at the specified offset.
+ if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
+ const llvm::StructLayout *SL = TD.getStructLayout(STy);
+ unsigned Elt = SL->getElementContainingOffset(IROffset);
+ IROffset -= SL->getElementOffset(Elt);
+ return ContainsFloatAtOffset(STy->getElementType(Elt), IROffset, TD);
+ }
+
+ // If this is an array, recurse into the field at the specified offset.
+ if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
+ const llvm::Type *EltTy = ATy->getElementType();
+ unsigned EltSize = TD.getTypeAllocSize(EltTy);
+ IROffset -= IROffset/EltSize*EltSize;
+ return ContainsFloatAtOffset(EltTy, IROffset, TD);
+ }
+
+ return false;
+}
+
+
+/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the
+/// low 8 bytes of an XMM register, corresponding to the SSE class.
+const llvm::Type *X86_64ABIInfo::
+GetSSETypeAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ QualType SourceTy, unsigned SourceOffset) const {
+ // The only three choices we have are either double, <2 x float>, or float. We
+ // pass as float if the last 4 bytes is just padding. This happens for
+ // structs that contain 3 floats.
+ if (BitsContainNoUserData(SourceTy, SourceOffset*8+32,
+ SourceOffset*8+64, getContext()))
+ return llvm::Type::getFloatTy(getVMContext());
+
+ // We want to pass as <2 x float> if the LLVM IR type contains a float at
+ // offset+0 and offset+4. Walk the LLVM IR type to find out if this is the
+ // case.
+ if (ContainsFloatAtOffset(IRType, IROffset, getTargetData()) &&
+ ContainsFloatAtOffset(IRType, IROffset+4, getTargetData()))
+ return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2);
+
+ return llvm::Type::getDoubleTy(getVMContext());
+}
+
+
+/// GetINTEGERTypeAtOffset - The ABI specifies that a value should be passed in
+/// an 8-byte GPR. This means that we either have a scalar or we are talking
+/// about the high or low part of an up-to-16-byte struct. This routine picks
+/// the best LLVM IR type to represent this, which may be i64 or may be anything
+/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*,
+/// etc).
+///
+/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for
+/// the source type. IROffset is an offset in bytes into the LLVM IR type that
+/// the 8-byte value references. PrefType may be null.
+///
+/// SourceTy is the source level type for the entire argument. SourceOffset is
+/// an offset into this that we're processing (which is always either 0 or 8).
+///
+const llvm::Type *X86_64ABIInfo::
+GetINTEGERTypeAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ QualType SourceTy, unsigned SourceOffset) const {
+ // If we're dealing with an un-offset LLVM IR type, then it means that we're
+ // returning an 8-byte unit starting with it. See if we can safely use it.
+ if (IROffset == 0) {
+ // Pointers and int64's always fill the 8-byte unit.
+ if (isa<llvm::PointerType>(IRType) || IRType->isIntegerTy(64))
+ return IRType;
+
+ // If we have a 1/2/4-byte integer, we can use it only if the rest of the
+ // goodness in the source type is just tail padding. This is allowed to
+ // kick in for struct {double,int} on the int, but not on
+ // struct{double,int,int} because we wouldn't return the second int. We
+ // have to do this analysis on the source type because we can't depend on
+ // unions being lowered a specific way etc.
+ if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
+ IRType->isIntegerTy(32)) {
+ unsigned BitWidth = cast<llvm::IntegerType>(IRType)->getBitWidth();
+
+ if (BitsContainNoUserData(SourceTy, SourceOffset*8+BitWidth,
+ SourceOffset*8+64, getContext()))
+ return IRType;
+ }
+ }
+
+ if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
+ // If this is a struct, recurse into the field at the specified offset.
+ const llvm::StructLayout *SL = getTargetData().getStructLayout(STy);
+ if (IROffset < SL->getSizeInBytes()) {
+ unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
+ IROffset -= SL->getElementOffset(FieldIdx);
+
+ return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
+ SourceTy, SourceOffset);
+ }
+ }
+
+ if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
+ const llvm::Type *EltTy = ATy->getElementType();
+ unsigned EltSize = getTargetData().getTypeAllocSize(EltTy);
+ unsigned EltOffset = IROffset/EltSize*EltSize;
+ return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
+ SourceOffset);
+ }
+
+ // Okay, we don't have any better idea of what to pass, so we pass this in an
+ // integer register that isn't too big to fit the rest of the struct.
+ unsigned TySizeInBytes =
+ (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
+
+ assert(TySizeInBytes != SourceOffset && "Empty field?");
+
+ // It is always safe to classify this as an integer type up to i64 that
+ // isn't larger than the structure.
+ return llvm::IntegerType::get(getVMContext(),
+ std::min(TySizeInBytes-SourceOffset, 8U)*8);
+}
+
+
+/// GetX86_64ByValArgumentPair - Given a high and low type that can ideally
+/// be used as elements of a two register pair to pass or return, return a
+/// first class aggregate to represent them. For example, if the low part of
+/// a by-value argument should be passed as i32* and the high part as float,
+/// return {i32*, float}.
+static const llvm::Type *
+GetX86_64ByValArgumentPair(const llvm::Type *Lo, const llvm::Type *Hi,
+ const llvm::TargetData &TD) {
+ // In order to correctly satisfy the ABI, we need to the high part to start
+ // at offset 8. If the high and low parts we inferred are both 4-byte types
+ // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have
+ // the second element at offset 8. Check for this:
+ unsigned LoSize = (unsigned)TD.getTypeAllocSize(Lo);
+ unsigned HiAlign = TD.getABITypeAlignment(Hi);
+ unsigned HiStart = llvm::TargetData::RoundUpAlignment(LoSize, HiAlign);
+ assert(HiStart != 0 && HiStart <= 8 && "Invalid x86-64 argument pair!");
+
+ // To handle this, we have to increase the size of the low part so that the
+ // second element will start at an 8 byte offset. We can't increase the size
+ // of the second element because it might make us access off the end of the
+ // struct.
+ if (HiStart != 8) {
+ // There are only two sorts of types the ABI generation code can produce for
+ // the low part of a pair that aren't 8 bytes in size: float or i8/i16/i32.
+ // Promote these to a larger type.
+ if (Lo->isFloatTy())
+ Lo = llvm::Type::getDoubleTy(Lo->getContext());
+ else {
+ assert(Lo->isIntegerTy() && "Invalid/unknown lo type");
+ Lo = llvm::Type::getInt64Ty(Lo->getContext());
+ }
+ }
+
+ const llvm::StructType *Result =
+ llvm::StructType::get(Lo->getContext(), Lo, Hi, NULL);
+
+
+ // Verify that the second element is at an 8-byte offset.
+ assert(TD.getStructLayout(Result)->getElementOffset(1) == 8 &&
+ "Invalid x86-64 argument pair!");
+ return Result;
+}
+
+ABIArgInfo X86_64ABIInfo::
+classifyReturnType(QualType RetTy) const {
+ // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
+ // classification algorithm.
+ X86_64ABIInfo::Class Lo, Hi;
+ classify(RetTy, 0, Lo, Hi);
+
+ // Check some invariants.
+ assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
+ assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
+
+ const llvm::Type *ResType = 0;
+ switch (Lo) {
+ case NoClass:
+ if (Hi == NoClass)
+ return ABIArgInfo::getIgnore();
+ // If the low part is just padding, it takes no register, leave ResType
+ // null.
+ assert((Hi == SSE || Hi == Integer || Hi == X87Up) &&
+ "Unknown missing lo part");
+ break;
+
+ case SSEUp:
+ case X87Up:
+ assert(0 && "Invalid classification for lo word.");
+
+ // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via
+ // hidden argument.
+ case Memory:
+ return getIndirectReturnResult(RetTy);
+
+ // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
+ // available register of the sequence %rax, %rdx is used.
+ case Integer:
+ ResType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0,
+ RetTy, 0);
+
+ // If we have a sign or zero extended integer, make sure to return Extend
+ // so that the parameter gets the right LLVM IR attributes.
+ if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ if (RetTy->isIntegralOrEnumerationType() &&
+ RetTy->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+ }
+ break;
+
+ // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
+ // available SSE register of the sequence %xmm0, %xmm1 is used.
+ case SSE:
+ ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0, RetTy, 0);
+ break;
+
+ // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is
+ // returned on the X87 stack in %st0 as 80-bit x87 number.
+ case X87:
+ ResType = llvm::Type::getX86_FP80Ty(getVMContext());
+ break;
+
+ // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real
+ // part of the value is returned in %st0 and the imaginary part in
+ // %st1.
+ case ComplexX87:
+ assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification.");
+ ResType = llvm::StructType::get(getVMContext(),
+ llvm::Type::getX86_FP80Ty(getVMContext()),
+ llvm::Type::getX86_FP80Ty(getVMContext()),
+ NULL);
+ break;
+ }
+
+ const llvm::Type *HighPart = 0;
+ switch (Hi) {
+ // Memory was handled previously and X87 should
+ // never occur as a hi class.
+ case Memory:
+ case X87:
+ assert(0 && "Invalid classification for hi word.");
+
+ case ComplexX87: // Previously handled.
+ case NoClass:
+ break;
+
+ case Integer:
+ HighPart = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(RetTy),
+ 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+ break;
+ case SSE:
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+ break;
+
+ // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte
+ // is passed in the upper half of the last used SSE register.
+ //
+ // SSEUP should always be preceeded by SSE, just widen.
+ case SSEUp:
+ assert(Lo == SSE && "Unexpected SSEUp classification.");
+ ResType = Get16ByteVectorType(RetTy);
+ break;
+
+ // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is
+ // returned together with the previous X87 value in %st0.
+ case X87Up:
+ // If X87Up is preceeded by X87, we don't need to do
+ // anything. However, in some cases with unions it may not be
+ // preceeded by X87. In such situations we follow gcc and pass the
+ // extra bits in an SSE reg.
+ if (Lo != X87) {
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy),
+ 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+ }
+ break;
+ }
+
+ // If a high part was specified, merge it together with the low part. It is
+ // known to pass in the high eightbyte of the result. We do this by forming a
+ // first class struct aggregate with the high and low part: {low, high}
+ if (HighPart)
+ ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getTargetData());
+
+ return ABIArgInfo::getDirect(ResType);
+}
+
+ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt,
+ unsigned &neededSSE) const {
+ X86_64ABIInfo::Class Lo, Hi;
+ classify(Ty, 0, Lo, Hi);
+
+ // Check some invariants.
+ // FIXME: Enforce these by construction.
+ assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
+ assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
+
+ neededInt = 0;
+ neededSSE = 0;
+ const llvm::Type *ResType = 0;
+ switch (Lo) {
+ case NoClass:
+ if (Hi == NoClass)
+ return ABIArgInfo::getIgnore();
+ // If the low part is just padding, it takes no register, leave ResType
+ // null.
+ assert((Hi == SSE || Hi == Integer || Hi == X87Up) &&
+ "Unknown missing lo part");
+ break;
+
+ // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument
+ // on the stack.
+ case Memory:
+
+ // AMD64-ABI 3.2.3p3: Rule 5. If the class is X87, X87UP or
+ // COMPLEX_X87, it is passed in memory.
+ case X87:
+ case ComplexX87:
+ return getIndirectResult(Ty);
+
+ case SSEUp:
+ case X87Up:
+ assert(0 && "Invalid classification for lo word.");
+
+ // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next
+ // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8
+ // and %r9 is used.
+ case Integer:
+ ++neededInt;
+
+ // Pick an 8-byte type based on the preferred type.
+ ResType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(Ty), 0, Ty, 0);
+
+ // If we have a sign or zero extended integer, make sure to return Extend
+ // so that the parameter gets the right LLVM IR attributes.
+ if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ if (Ty->isIntegralOrEnumerationType() &&
+ Ty->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+ }
+
+ break;
+
+ // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next
+ // available SSE register is used, the registers are taken in the
+ // order from %xmm0 to %xmm7.
+ case SSE: {
+ const llvm::Type *IRType = CGT.ConvertTypeRecursive(Ty);
+ if (Hi != NoClass || !UseX86_MMXType(IRType))
+ ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
+ else
+ // This is an MMX type. Treat it as such.
+ ResType = llvm::Type::getX86_MMXTy(getVMContext());
+
+ ++neededSSE;
+ break;
+ }
+ }
+
+ const llvm::Type *HighPart = 0;
+ switch (Hi) {
+ // Memory was handled previously, ComplexX87 and X87 should
+ // never occur as hi classes, and X87Up must be preceed by X87,
+ // which is passed in memory.
+ case Memory:
+ case X87:
+ case ComplexX87:
+ assert(0 && "Invalid classification for hi word.");
+ break;
+
+ case NoClass: break;
+
+ case Integer:
+ ++neededInt;
+ // Pick an 8-byte type based on the preferred type.
+ HighPart = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8);
+
+ if (Lo == NoClass) // Pass HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+ break;
+
+ // X87Up generally doesn't occur here (long double is passed in
+ // memory), except in situations involving unions.
+ case X87Up:
+ case SSE:
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8);
+
+ if (Lo == NoClass) // Pass HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+
+ ++neededSSE;
+ break;
+
+ // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
+ // eightbyte is passed in the upper half of the last used SSE
+ // register. This only happens when 128-bit vectors are passed.
+ case SSEUp:
+ assert(Lo == SSE && "Unexpected SSEUp classification");
+ ResType = Get16ByteVectorType(Ty);
+ break;
+ }
+
+ // If a high part was specified, merge it together with the low part. It is
+ // known to pass in the high eightbyte of the result. We do this by forming a
+ // first class struct aggregate with the high and low part: {low, high}
+ if (HighPart)
+ ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getTargetData());
+
+ return ABIArgInfo::getDirect(ResType);
+}
+
+void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+ // Keep track of the number of assigned registers.
+ unsigned freeIntRegs = 6, freeSSERegs = 8;
+
+ // If the return value is indirect, then the hidden argument is consuming one
+ // integer register.
+ if (FI.getReturnInfo().isIndirect())
+ --freeIntRegs;
+
+ // AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
+ // get assigned (in left-to-right order) for passing as follows...
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it) {
+ unsigned neededInt, neededSSE;
+ it->info = classifyArgumentType(it->type, neededInt, neededSSE);
+
+ // AMD64-ABI 3.2.3p3: If there are no registers available for any
+ // eightbyte of an argument, the whole argument is passed on the
+ // stack. If registers have already been assigned for some
+ // eightbytes of such an argument, the assignments get reverted.
+ if (freeIntRegs >= neededInt && freeSSERegs >= neededSSE) {
+ freeIntRegs -= neededInt;
+ freeSSERegs -= neededSSE;
+ } else {
+ it->info = getIndirectResult(it->type);
+ }
+ }
+}
+
+static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
+ QualType Ty,
+ CodeGenFunction &CGF) {
+ llvm::Value *overflow_arg_area_p =
+ CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_p");
+ llvm::Value *overflow_arg_area =
+ CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area");
+
+ // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16
+ // byte boundary if alignment needed by type exceeds 8 byte boundary.
+ uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
+ if (Align > 8) {
+ // Note that we follow the ABI & gcc here, even though the type
+ // could in theory have an alignment greater than 16. This case
+ // shouldn't ever matter in practice.
+
+ // overflow_arg_area = (overflow_arg_area + 15) & ~15;
+ llvm::Value *Offset =
+ llvm::ConstantInt::get(CGF.Int32Ty, 15);
+ overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset);
+ llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(overflow_arg_area,
+ CGF.Int64Ty);
+ llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int64Ty, ~15LL);
+ overflow_arg_area =
+ CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
+ overflow_arg_area->getType(),
+ "overflow_arg_area.align");
+ }
+
+ // AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
+ const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
+ llvm::Value *Res =
+ CGF.Builder.CreateBitCast(overflow_arg_area,
+ llvm::PointerType::getUnqual(LTy));
+
+ // AMD64-ABI 3.5.7p5: Step 9. Set l->overflow_arg_area to:
+ // l->overflow_arg_area + sizeof(type).
+ // AMD64-ABI 3.5.7p5: Step 10. Align l->overflow_arg_area upwards to
+ // an 8 byte boundary.
+
+ uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
+ llvm::Value *Offset =
+ llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7) & ~7);
+ overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset,
+ "overflow_arg_area.next");
+ CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p);
+
+ // AMD64-ABI 3.5.7p5: Step 11. Return the fetched type.
+ return Res;
+}
+
+llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ llvm::LLVMContext &VMContext = CGF.getLLVMContext();
+
+ // Assume that va_list type is correct; should be pointer to LLVM type:
+ // struct {
+ // i32 gp_offset;
+ // i32 fp_offset;
+ // i8* overflow_arg_area;
+ // i8* reg_save_area;
+ // };
+ unsigned neededInt, neededSSE;
+
+ Ty = CGF.getContext().getCanonicalType(Ty);
+ ABIArgInfo AI = classifyArgumentType(Ty, neededInt, neededSSE);
+
+ // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
+ // in the registers. If not go to step 7.
+ if (!neededInt && !neededSSE)
+ return EmitVAArgFromMemory(VAListAddr, Ty, CGF);
+
+ // AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
+ // general purpose registers needed to pass type and num_fp to hold
+ // the number of floating point registers needed.
+
+ // AMD64-ABI 3.5.7p5: Step 3. Verify whether arguments fit into
+ // registers. In the case: l->gp_offset > 48 - num_gp * 8 or
+ // l->fp_offset > 304 - num_fp * 16 go to step 7.
+ //
+ // NOTE: 304 is a typo, there are (6 * 8 + 8 * 16) = 176 bytes of
+ // register save space).
+
+ llvm::Value *InRegs = 0;
+ llvm::Value *gp_offset_p = 0, *gp_offset = 0;
+ llvm::Value *fp_offset_p = 0, *fp_offset = 0;
+ if (neededInt) {
+ gp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "gp_offset_p");
+ gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
+ InRegs = llvm::ConstantInt::get(CGF.Int32Ty, 48 - neededInt * 8);
+ InRegs = CGF.Builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp");
+ }
+
+ if (neededSSE) {
+ fp_offset_p = CGF.Builder.CreateStructGEP(VAListAddr, 1, "fp_offset_p");
+ fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset");
+ llvm::Value *FitsInFP =
+ llvm::ConstantInt::get(CGF.Int32Ty, 176 - neededSSE * 16);
+ FitsInFP = CGF.Builder.CreateICmpULE(fp_offset, FitsInFP, "fits_in_fp");
+ InRegs = InRegs ? CGF.Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
+ }
+
+ llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
+ llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem");
+ llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
+ CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
+
+ // Emit code to load the value if it was passed in registers.
+
+ CGF.EmitBlock(InRegBlock);
+
+ // AMD64-ABI 3.5.7p5: Step 4. Fetch type from l->reg_save_area with
+ // an offset of l->gp_offset and/or l->fp_offset. This may require
+ // copying to a temporary location in case the parameter is passed
+ // in different register classes or requires an alignment greater
+ // than 8 for general purpose registers and 16 for XMM registers.
+ //
+ // FIXME: This really results in shameful code when we end up needing to
+ // collect arguments from different places; often what should result in a
+ // simple assembling of a structure from scattered addresses has many more
+ // loads than necessary. Can we clean this up?
+ const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
+ llvm::Value *RegAddr =
+ CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3),
+ "reg_save_area");
+ if (neededInt && neededSSE) {
+ // FIXME: Cleanup.
+ assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
+ const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
+ llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
+ assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
+ const llvm::Type *TyLo = ST->getElementType(0);
+ const llvm::Type *TyHi = ST->getElementType(1);
+ assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
+ "Unexpected ABI info for mixed regs");
+ const llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo);
+ const llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
+ llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
+ llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
+ llvm::Value *RegLoAddr = TyLo->isFloatingPointTy() ? FPAddr : GPAddr;
+ llvm::Value *RegHiAddr = TyLo->isFloatingPointTy() ? GPAddr : FPAddr;
+ llvm::Value *V =
+ CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+
+ RegAddr = CGF.Builder.CreateBitCast(Tmp,
+ llvm::PointerType::getUnqual(LTy));
+ } else if (neededInt) {
+ RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
+ RegAddr = CGF.Builder.CreateBitCast(RegAddr,
+ llvm::PointerType::getUnqual(LTy));
+ } else if (neededSSE == 1) {
+ RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
+ RegAddr = CGF.Builder.CreateBitCast(RegAddr,
+ llvm::PointerType::getUnqual(LTy));
+ } else {
+ assert(neededSSE == 2 && "Invalid number of needed registers!");
+ // SSE registers are spaced 16 bytes apart in the register save
+ // area, we need to collect the two eightbytes together.
+ llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset);
+ llvm::Value *RegAddrHi = CGF.Builder.CreateConstGEP1_32(RegAddrLo, 16);
+ const llvm::Type *DoubleTy = llvm::Type::getDoubleTy(VMContext);
+ const llvm::Type *DblPtrTy =
+ llvm::PointerType::getUnqual(DoubleTy);
+ const llvm::StructType *ST = llvm::StructType::get(VMContext, DoubleTy,
+ DoubleTy, NULL);
+ llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST);
+ V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
+ DblPtrTy));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 0));
+ V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi,
+ DblPtrTy));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+ RegAddr = CGF.Builder.CreateBitCast(Tmp,
+ llvm::PointerType::getUnqual(LTy));
+ }
+
+ // AMD64-ABI 3.5.7p5: Step 5. Set:
+ // l->gp_offset = l->gp_offset + num_gp * 8
+ // l->fp_offset = l->fp_offset + num_fp * 16.
+ if (neededInt) {
+ llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, neededInt * 8);
+ CGF.Builder.CreateStore(CGF.Builder.CreateAdd(gp_offset, Offset),
+ gp_offset_p);
+ }
+ if (neededSSE) {
+ llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, neededSSE * 16);
+ CGF.Builder.CreateStore(CGF.Builder.CreateAdd(fp_offset, Offset),
+ fp_offset_p);
+ }
+ CGF.EmitBranch(ContBlock);
+
+ // Emit code to load the value if it was passed in memory.
+
+ CGF.EmitBlock(InMemBlock);
+ llvm::Value *MemAddr = EmitVAArgFromMemory(VAListAddr, Ty, CGF);
+
+ // Return the appropriate result.
+
+ CGF.EmitBlock(ContBlock);
+ llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(RegAddr->getType(),
+ "vaarg.addr");
+ ResAddr->reserveOperandSpace(2);
+ ResAddr->addIncoming(RegAddr, InRegBlock);
+ ResAddr->addIncoming(MemAddr, InMemBlock);
+ return ResAddr;
+}
+
+ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
+
+ if (Ty->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ uint64_t Size = getContext().getTypeSize(Ty);
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ if (hasNonTrivialDestructorOrCopyConstructor(RT) ||
+ RT->getDecl()->hasFlexibleArrayMember())
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // FIXME: mingw64-gcc emits 128-bit struct as i128
+ if (Size <= 128 &&
+ (Size & (Size - 1)) == 0)
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ }
+
+ if (Ty->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+
+ return ABIArgInfo::getDirect();
+}
+
+void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+
+ QualType RetTy = FI.getReturnType();
+ FI.getReturnInfo() = classify(RetTy);
+
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classify(it->type);
+}
+
+llvm::Value *WinX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
+ "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *PTy =
+ llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 8);
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
+}
+
+// PowerPC-32
+
+namespace {
+class PPC32TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
+public:
+ PPC32TargetCodeGenInfo(CodeGenTypes &CGT) : DefaultTargetCodeGenInfo(CGT) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
+ // This is recovered from gcc output.
+ return 1; // r1 is the dedicated stack pointer
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const;
+};
+
+}
+
+bool
+PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ // This is calculated from the LLVM and GCC tables and verified
+ // against gcc output. AFAIK all ABIs use the same encoding.
+
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
+ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
+ llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16);
+
+ // 0-31: r0-31, the 4-byte general-purpose registers
+ AssignToArrayRange(Builder, Address, Four8, 0, 31);
+
+ // 32-63: fp0-31, the 8-byte floating-point registers
+ AssignToArrayRange(Builder, Address, Eight8, 32, 63);
+
+ // 64-76 are various 4-byte special-purpose registers:
+ // 64: mq
+ // 65: lr
+ // 66: ctr
+ // 67: ap
+ // 68-75 cr0-7
+ // 76: xer
+ AssignToArrayRange(Builder, Address, Four8, 64, 76);
+
+ // 77-108: v0-31, the 16-byte vector registers
+ AssignToArrayRange(Builder, Address, Sixteen8, 77, 108);
+
+ // 109: vrsave
+ // 110: vscr
+ // 111: spe_acc
+ // 112: spefscr
+ // 113: sfp
+ AssignToArrayRange(Builder, Address, Four8, 109, 113);
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// ARM ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class ARMABIInfo : public ABIInfo {
+public:
+ enum ABIKind {
+ APCS = 0,
+ AAPCS = 1,
+ AAPCS_VFP
+ };
+
+private:
+ ABIKind Kind;
+
+public:
+ ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {}
+
+private:
+ ABIKind getABIKind() const { return Kind; }
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const;
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K)
+ :TargetCodeGenInfo(new ARMABIInfo(CGT, K)) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
+ return 13;
+ }
+};
+
+}
+
+void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
+
+ const llvm::Triple &Triple(getContext().Target.getTriple());
+ llvm::CallingConv::ID DefaultCC;
+ if (Triple.getEnvironmentName() == "gnueabi" ||
+ Triple.getEnvironmentName() == "eabi")
+ DefaultCC = llvm::CallingConv::ARM_AAPCS;
+ else
+ DefaultCC = llvm::CallingConv::ARM_APCS;
+
+ switch (getABIKind()) {
+ case APCS:
+ if (DefaultCC != llvm::CallingConv::ARM_APCS)
+ FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_APCS);
+ break;
+
+ case AAPCS:
+ if (DefaultCC != llvm::CallingConv::ARM_AAPCS)
+ FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS);
+ break;
+
+ case AAPCS_VFP:
+ FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP);
+ break;
+ }
+}
+
+ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
+ if (!isAggregateTypeForABI(Ty)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ }
+
+ // Ignore empty records.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Otherwise, pass by coercing to a structure of the appropriate size.
+ //
+ // FIXME: This is kind of nasty... but there isn't much choice because the ARM
+ // backend doesn't support byval.
+ // FIXME: This doesn't handle alignment > 64 bits.
+ const llvm::Type* ElemTy;
+ unsigned SizeRegs;
+ if (getContext().getTypeAlign(Ty) > 32) {
+ ElemTy = llvm::Type::getInt64Ty(getVMContext());
+ SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
+ } else {
+ ElemTy = llvm::Type::getInt32Ty(getVMContext());
+ SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
+ }
+ std::vector<const llvm::Type*> LLVMFields;
+ LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs));
+ const llvm::Type* STy = llvm::StructType::get(getVMContext(), LLVMFields,
+ true);
+ return ABIArgInfo::getDirect(STy);
+}
+
+static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
+ llvm::LLVMContext &VMContext) {
+ // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure
+ // is called integer-like if its size is less than or equal to one word, and
+ // the offset of each of its addressable sub-fields is zero.
+
+ uint64_t Size = Context.getTypeSize(Ty);
+
+ // Check that the type fits in a word.
+ if (Size > 32)
+ return false;
+
+ // FIXME: Handle vector types!
+ if (Ty->isVectorType())
+ return false;
+
+ // Float types are never treated as "integer like".
+ if (Ty->isRealFloatingType())
+ return false;
+
+ // If this is a builtin or pointer type then it is ok.
+ if (Ty->getAs<BuiltinType>() || Ty->isPointerType())
+ return true;
+
+ // Small complex integer types are "integer like".
+ if (const ComplexType *CT = Ty->getAs<ComplexType>())
+ return isIntegerLikeType(CT->getElementType(), Context, VMContext);
+
+ // Single element and zero sized arrays should be allowed, by the definition
+ // above, but they are not.
+
+ // Otherwise, it must be a record type.
+ const RecordType *RT = Ty->getAs<RecordType>();
+ if (!RT) return false;
+
+ // Ignore records with flexible arrays.
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->hasFlexibleArrayMember())
+ return false;
+
+ // Check that all sub-fields are at offset 0, and are themselves "integer
+ // like".
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ bool HadField = false;
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i, ++idx) {
+ const FieldDecl *FD = *i;
+
+ // Bit-fields are not addressable, we only need to verify they are "integer
+ // like". We still have to disallow a subsequent non-bitfield, for example:
+ // struct { int : 0; int x }
+ // is non-integer like according to gcc.
+ if (FD->isBitField()) {
+ if (!RD->isUnion())
+ HadField = true;
+
+ if (!isIntegerLikeType(FD->getType(), Context, VMContext))
+ return false;
+
+ continue;
+ }
+
+ // Check if this field is at offset 0.
+ if (Layout.getFieldOffset(idx) != 0)
+ return false;
+
+ if (!isIntegerLikeType(FD->getType(), Context, VMContext))
+ return false;
+
+ // Only allow at most one field in a structure. This doesn't match the
+ // wording above, but follows gcc in situations with a field following an
+ // empty structure.
+ if (!RD->isUnion()) {
+ if (HadField)
+ return false;
+
+ HadField = true;
+ }
+ }
+
+ return true;
+}
+
+ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+
+ // Large vector types should be returned via memory.
+ if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128)
+ return ABIArgInfo::getIndirect(0);
+
+ if (!isAggregateTypeForABI(RetTy)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ }
+
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (isRecordWithNonTrivialDestructorOrCopyConstructor(RetTy))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Are we following APCS?
+ if (getABIKind() == APCS) {
+ if (isEmptyRecord(getContext(), RetTy, false))
+ return ABIArgInfo::getIgnore();
+
+ // Complex types are all returned as packed integers.
+ //
+ // FIXME: Consider using 2 x vector types if the back end handles them
+ // correctly.
+ if (RetTy->isAnyComplexType())
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ getContext().getTypeSize(RetTy)));
+
+ // Integer like structures are returned in r0.
+ if (isIntegerLikeType(RetTy, getContext(), getVMContext())) {
+ // Return in the smallest viable integer type.
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size <= 8)
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
+ if (Size <= 16)
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+ }
+
+ // Otherwise return in memory.
+ return ABIArgInfo::getIndirect(0);
+ }
+
+ // Otherwise this is an AAPCS variant.
+
+ if (isEmptyRecord(getContext(), RetTy, true))
+ return ABIArgInfo::getIgnore();
+
+ // Aggregates <= 4 bytes are returned in r0; other aggregates
+ // are returned indirectly.
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ if (Size <= 32) {
+ // Return in the smallest viable integer type.
+ if (Size <= 8)
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
+ if (Size <= 16)
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+ }
+
+ return ABIArgInfo::getIndirect(0);
+}
+
+llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ // FIXME: Need to handle alignment
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
+ "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *PTy =
+ llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
+}
+
+//===----------------------------------------------------------------------===//
+// SystemZ ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class SystemZABIInfo : public ABIInfo {
+public:
+ SystemZABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ bool isPromotableIntegerType(QualType Ty) const;
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
+ }
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ SystemZTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new SystemZABIInfo(CGT)) {}
+};
+
+}
+
+bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const {
+ // SystemZ ABI requires all 8, 16 and 32 bit quantities to be extended.
+ if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ case BuiltinType::Bool:
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ // FIXME: Implement
+ return 0;
+}
+
+
+ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+ if (isAggregateTypeForABI(RetTy))
+ return ABIArgInfo::getIndirect(0);
+
+ return (isPromotableIntegerType(RetTy) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
+ if (isAggregateTypeForABI(Ty))
+ return ABIArgInfo::getIndirect(0);
+
+ return (isPromotableIntegerType(Ty) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+//===----------------------------------------------------------------------===//
+// MBlaze ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class MBlazeABIInfo : public ABIInfo {
+public:
+ MBlazeABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ bool isPromotableIntegerType(QualType Ty) const;
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
+ }
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
+
+class MBlazeTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ MBlazeTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new MBlazeABIInfo(CGT)) {}
+ void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const;
+};
+
+}
+
+bool MBlazeABIInfo::isPromotableIntegerType(QualType Ty) const {
+ // MBlaze ABI requires all 8 and 16 bit quantities to be extended.
+ if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ case BuiltinType::Bool:
+ case BuiltinType::Char_S:
+ case BuiltinType::Char_U:
+ case BuiltinType::SChar:
+ case BuiltinType::UChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+llvm::Value *MBlazeABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ // FIXME: Implement
+ return 0;
+}
+
+
+ABIArgInfo MBlazeABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
+ return ABIArgInfo::getIgnore();
+ if (isAggregateTypeForABI(RetTy))
+ return ABIArgInfo::getIndirect(0);
+
+ return (isPromotableIntegerType(RetTy) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+ABIArgInfo MBlazeABIInfo::classifyArgumentType(QualType Ty) const {
+ if (isAggregateTypeForABI(Ty))
+ return ABIArgInfo::getIndirect(0);
+
+ return (isPromotableIntegerType(Ty) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+void MBlazeTargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M)
+ const {
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) return;
+
+ llvm::CallingConv::ID CC = llvm::CallingConv::C;
+ if (FD->hasAttr<MBlazeInterruptHandlerAttr>())
+ CC = llvm::CallingConv::MBLAZE_INTR;
+ else if (FD->hasAttr<MBlazeSaveVolatilesAttr>())
+ CC = llvm::CallingConv::MBLAZE_SVOL;
+
+ if (CC != llvm::CallingConv::C) {
+ // Handle 'interrupt_handler' attribute:
+ llvm::Function *F = cast<llvm::Function>(GV);
+
+ // Step 1: Set ISR calling convention.
+ F->setCallingConv(CC);
+
+ // Step 2: Add attributes goodness.
+ F->addFnAttr(llvm::Attribute::NoInline);
+ }
+
+ // Step 3: Emit _interrupt_handler alias.
+ if (CC == llvm::CallingConv::MBLAZE_INTR)
+ new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
+ "_interrupt_handler", GV, &M.getModule());
+}
+
+
+//===----------------------------------------------------------------------===//
+// MSP430 ABI Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+ void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const;
+};
+
+}
+
+void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
+ // Handle 'interrupt' attribute:
+ llvm::Function *F = cast<llvm::Function>(GV);
+
+ // Step 1: Set ISR calling convention.
+ F->setCallingConv(llvm::CallingConv::MSP430_INTR);
+
+ // Step 2: Add attributes goodness.
+ F->addFnAttr(llvm::Attribute::NoInline);
+
+ // Step 3: Emit ISR vector alias.
+ unsigned Num = attr->getNumber() + 0xffe0;
+ new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
+ "vector_" + llvm::Twine::utohexstr(Num),
+ GV, &M.getModule());
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// MIPS ABI Implementation. This works for both little-endian and
+// big-endian variants.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ MIPSTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
+ return 29;
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const;
+};
+}
+
+bool
+MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ // This information comes from gcc's implementation, which seems to
+ // as canonical as it gets.
+
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ // Everything on MIPS is 4 bytes. Double-precision FP registers
+ // are aliased to pairs of single-precision FP registers.
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
+
+ // 0-31 are the general purpose registers, $0 - $31.
+ // 32-63 are the floating-point registers, $f0 - $f31.
+ // 64 and 65 are the multiply/divide registers, $hi and $lo.
+ // 66 is the (notional, I think) register for signal-handler return.
+ AssignToArrayRange(Builder, Address, Four8, 0, 65);
+
+ // 67-74 are the floating-point status registers, $fcc0 - $fcc7.
+ // They are one bit wide and ignored here.
+
+ // 80-111 are the coprocessor 0 registers, $c0r0 - $c0r31.
+ // (coprocessor 1 is the FP unit)
+ // 112-143 are the coprocessor 2 registers, $c2r0 - $c2r31.
+ // 144-175 are the coprocessor 3 registers, $c3r0 - $c3r31.
+ // 176-181 are the DSP accumulator registers.
+ AssignToArrayRange(Builder, Address, Four8, 80, 181);
+
+ return false;
+}
+
+
+const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
+ if (TheTargetCodeGenInfo)
+ return *TheTargetCodeGenInfo;
+
+ // For now we just cache the TargetCodeGenInfo in CodeGenModule and don't
+ // free it.
+
+ const llvm::Triple &Triple = getContext().Target.getTriple();
+ switch (Triple.getArch()) {
+ default:
+ return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo(Types));
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types));
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // FIXME: We want to know the float calling convention as well.
+ if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0)
+ return *(TheTargetCodeGenInfo =
+ new ARMTargetCodeGenInfo(Types, ARMABIInfo::APCS));
+
+ return *(TheTargetCodeGenInfo =
+ new ARMTargetCodeGenInfo(Types, ARMABIInfo::AAPCS));
+
+ case llvm::Triple::ppc:
+ return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types));
+
+ case llvm::Triple::systemz:
+ return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types));
+
+ case llvm::Triple::mblaze:
+ return *(TheTargetCodeGenInfo = new MBlazeTargetCodeGenInfo(Types));
+
+ case llvm::Triple::msp430:
+ return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types));
+
+ case llvm::Triple::x86:
+ switch (Triple.getOS()) {
+ case llvm::Triple::Darwin:
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Types, true, true));
+ case llvm::Triple::Cygwin:
+ case llvm::Triple::MinGW32:
+ case llvm::Triple::AuroraUX:
+ case llvm::Triple::DragonFly:
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::NetBSD:
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Types, false, true));
+
+ default:
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Types, false, false));
+ }
+
+ case llvm::Triple::x86_64:
+ switch (Triple.getOS()) {
+ case llvm::Triple::Win32:
+ case llvm::Triple::MinGW32:
+ case llvm::Triple::Cygwin:
+ return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types));
+ default:
+ return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types));
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
new file mode 100644
index 0000000..4f59eb6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
@@ -0,0 +1,117 @@
+//===---- TargetInfo.h - Encapsulate target details -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_TARGETINFO_H
+#define CLANG_CODEGEN_TARGETINFO_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+ class GlobalValue;
+ class Type;
+ class Value;
+}
+
+namespace clang {
+ class ABIInfo;
+ class Decl;
+
+ namespace CodeGen {
+ class CodeGenModule;
+ class CodeGenFunction;
+ }
+
+ /// TargetCodeGenInfo - This class organizes various target-specific
+ /// codegeneration issues, like target-specific attributes, builtins and so
+ /// on.
+ class TargetCodeGenInfo {
+ ABIInfo *Info;
+ public:
+ // WARNING: Acquires the ownership of ABIInfo.
+ TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { }
+ virtual ~TargetCodeGenInfo();
+
+ /// getABIInfo() - Returns ABI info helper for the target.
+ const ABIInfo& getABIInfo() const { return *Info; }
+
+ /// SetTargetAttributes - Provides a convenient hook to handle extra
+ /// target-specific attributes for the given global.
+ virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const { }
+
+ /// Determines the size of struct _Unwind_Exception on this platform,
+ /// in 8-bit units. The Itanium ABI defines this as:
+ /// struct _Unwind_Exception {
+ /// uint64 exception_class;
+ /// _Unwind_Exception_Cleanup_Fn exception_cleanup;
+ /// uint64 private_1;
+ /// uint64 private_2;
+ /// };
+ unsigned getSizeOfUnwindException() const { return 32; }
+
+ /// Controls whether __builtin_extend_pointer should sign-extend
+ /// pointers to uint64_t or zero-extend them (the default). Has
+ /// no effect for targets:
+ /// - that have 64-bit pointers, or
+ /// - that cannot address through registers larger than pointers, or
+ /// - that implicitly ignore/truncate the top bits when addressing
+ /// through such registers.
+ virtual bool extendPointerWithSExt() const { return false; }
+
+ /// Determines the DWARF register number for the stack pointer, for
+ /// exception-handling purposes. Implements __builtin_dwarf_sp_column.
+ ///
+ /// Returns -1 if the operation is unsupported by this target.
+ virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
+ return -1;
+ }
+
+ /// Initializes the given DWARF EH register-size table, a char*.
+ /// Implements __builtin_init_dwarf_reg_size_table.
+ ///
+ /// Returns true if the operation is unsupported by this target.
+ virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return true;
+ }
+
+ /// Performs the code-generation required to convert a return
+ /// address as stored by the system into the actual address of the
+ /// next instruction that will be executed.
+ ///
+ /// Used by __builtin_extract_return_addr().
+ virtual llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
+
+ /// Performs the code-generation required to convert the address
+ /// of an instruction into a return address suitable for storage
+ /// by the system in a return slot.
+ ///
+ /// Used by __builtin_frob_return_addr().
+ virtual llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ return Address;
+ }
+
+ virtual const llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
+ llvm::StringRef Constraint,
+ const llvm::Type* Ty) const {
+ return Ty;
+ }
+ };
+}
+
+#endif // CLANG_CODEGEN_TARGETINFO_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
new file mode 100644
index 0000000..549ce0a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
@@ -0,0 +1,86 @@
+//===--- Action.cpp - Abstract compilation steps --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Action.h"
+
+#include <cassert>
+using namespace clang::driver;
+
+Action::~Action() {
+ if (OwnsInputs) {
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ delete *it;
+ }
+}
+
+const char *Action::getClassName(ActionClass AC) {
+ switch (AC) {
+ case InputClass: return "input";
+ case BindArchClass: return "bind-arch";
+ case PreprocessJobClass: return "preprocessor";
+ case PrecompileJobClass: return "precompiler";
+ case AnalyzeJobClass: return "analyzer";
+ case CompileJobClass: return "compiler";
+ case AssembleJobClass: return "assembler";
+ case LinkJobClass: return "linker";
+ case LipoJobClass: return "lipo";
+ case DsymutilJobClass: return "dsymutil";
+ }
+
+ assert(0 && "invalid class");
+ return 0;
+}
+
+InputAction::InputAction(const Arg &_Input, types::ID _Type)
+ : Action(InputClass, _Type), Input(_Input) {
+}
+
+BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
+ : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) {
+}
+
+JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
+ : Action(Kind, Input, Type) {
+}
+
+JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
+ : Action(Kind, Inputs, Type) {
+}
+
+PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PreprocessJobClass, Input, OutputType) {
+}
+
+PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PrecompileJobClass, Input, OutputType) {
+}
+
+AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AnalyzeJobClass, Input, OutputType) {
+}
+
+CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(CompileJobClass, Input, OutputType) {
+}
+
+AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AssembleJobClass, Input, OutputType) {
+}
+
+LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(LinkJobClass, Inputs, Type) {
+}
+
+LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(LipoJobClass, Inputs, Type) {
+}
+
+DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(DsymutilJobClass, Inputs, Type) {
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp
new file mode 100644
index 0000000..f1177cf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp
@@ -0,0 +1,121 @@
+//===--- Arg.cpp - Argument Implementations -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Option.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+
+Arg::Arg(const Option *_Opt, unsigned _Index, const Arg *_BaseArg)
+ : Opt(_Opt), BaseArg(_BaseArg), Index(_Index),
+ Claimed(false), OwnsValues(false) {
+}
+
+Arg::Arg(const Option *_Opt, unsigned _Index,
+ const char *Value0, const Arg *_BaseArg)
+ : Opt(_Opt), BaseArg(_BaseArg), Index(_Index),
+ Claimed(false), OwnsValues(false) {
+ Values.push_back(Value0);
+}
+
+Arg::Arg(const Option *_Opt, unsigned _Index,
+ const char *Value0, const char *Value1, const Arg *_BaseArg)
+ : Opt(_Opt), BaseArg(_BaseArg), Index(_Index),
+ Claimed(false), OwnsValues(false) {
+ Values.push_back(Value0);
+ Values.push_back(Value1);
+}
+
+Arg::~Arg() {
+ if (OwnsValues) {
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ delete[] Values[i];
+ }
+}
+
+void Arg::dump() const {
+ llvm::errs() << "<";
+
+ llvm::errs() << " Opt:";
+ Opt->dump();
+
+ llvm::errs() << " Index:" << Index;
+
+ llvm::errs() << " Values: [";
+ for (unsigned i = 0, e = Values.size(); i != e; ++i) {
+ if (i) llvm::errs() << ", ";
+ llvm::errs() << "'" << Values[i] << "'";
+ }
+
+ llvm::errs() << "]>\n";
+}
+
+std::string Arg::getAsString(const ArgList &Args) const {
+ llvm::SmallString<256> Res;
+ llvm::raw_svector_ostream OS(Res);
+
+ ArgStringList ASL;
+ render(Args, ASL);
+ for (ArgStringList::iterator
+ it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
+ if (it != ASL.begin())
+ OS << ' ';
+ OS << *it;
+ }
+
+ return OS.str();
+}
+
+void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
+ if (!getOption().hasNoOptAsInput()) {
+ render(Args, Output);
+ return;
+ }
+
+ for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+ Output.push_back(getValue(Args, i));
+}
+
+void Arg::render(const ArgList &Args, ArgStringList &Output) const {
+ switch (getOption().getRenderStyle()) {
+ case Option::RenderValuesStyle:
+ for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+ Output.push_back(getValue(Args, i));
+ break;
+
+ case Option::RenderCommaJoinedStyle: {
+ llvm::SmallString<256> Res;
+ llvm::raw_svector_ostream OS(Res);
+ OS << getOption().getName();
+ for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
+ if (i) OS << ',';
+ OS << getValue(Args, i);
+ }
+ Output.push_back(Args.MakeArgString(OS.str()));
+ break;
+ }
+
+ case Option::RenderJoinedStyle:
+ Output.push_back(Args.GetOrMakeJoinedArgString(
+ getIndex(), getOption().getName(), getValue(Args, 0)));
+ for (unsigned i = 1, e = getNumValues(); i != e; ++i)
+ Output.push_back(getValue(Args, i));
+ break;
+
+ case Option::RenderSeparateStyle:
+ Output.push_back(getOption().getName());
+ for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+ Output.push_back(getValue(Args, i));
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp
new file mode 100644
index 0000000..596e2a7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp
@@ -0,0 +1,296 @@
+//===--- ArgList.cpp - Argument List Management ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Option.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+void arg_iterator::SkipToNextArg() {
+ for (; Current != Args.end(); ++Current) {
+ // Done if there are no filters.
+ if (!Id0.isValid())
+ break;
+
+ // Otherwise require a match.
+ const Option &O = (*Current)->getOption();
+ if (O.matches(Id0) ||
+ (Id1.isValid() && O.matches(Id1)) ||
+ (Id2.isValid() && O.matches(Id2)))
+ break;
+ }
+}
+
+//
+
+ArgList::ArgList() {
+}
+
+ArgList::~ArgList() {
+}
+
+void ArgList::append(Arg *A) {
+ Args.push_back(A);
+}
+
+Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
+ // FIXME: Make search efficient?
+ for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
+ if ((*it)->getOption().matches(Id))
+ return *it;
+ return 0;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id) const {
+ Arg *Res = 0;
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((*it)->getOption().matches(Id)) {
+ Res = *it;
+ Res->claim();
+ }
+ }
+
+ return Res;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
+ Arg *Res = 0;
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((*it)->getOption().matches(Id0) ||
+ (*it)->getOption().matches(Id1)) {
+ Res = *it;
+ Res->claim();
+
+ }
+ }
+
+ return Res;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
+ OptSpecifier Id2) const {
+ Arg *Res = 0;
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((*it)->getOption().matches(Id0) ||
+ (*it)->getOption().matches(Id1) ||
+ (*it)->getOption().matches(Id2)) {
+ Res = *it;
+ Res->claim();
+ }
+ }
+
+ return Res;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
+ OptSpecifier Id2, OptSpecifier Id3) const {
+ Arg *Res = 0;
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((*it)->getOption().matches(Id0) ||
+ (*it)->getOption().matches(Id1) ||
+ (*it)->getOption().matches(Id2) ||
+ (*it)->getOption().matches(Id3)) {
+ Res = *it;
+ Res->claim();
+ }
+ }
+
+ return Res;
+}
+
+bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
+ if (Arg *A = getLastArg(Pos, Neg))
+ return A->getOption().matches(Pos);
+ return Default;
+}
+
+llvm::StringRef ArgList::getLastArgValue(OptSpecifier Id,
+ llvm::StringRef Default) const {
+ if (Arg *A = getLastArg(Id))
+ return A->getValue(*this);
+ return Default;
+}
+
+int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
+ clang::Diagnostic &Diags) const {
+ int Res = Default;
+
+ if (Arg *A = getLastArg(Id)) {
+ if (llvm::StringRef(A->getValue(*this)).getAsInteger(10, Res))
+ Diags.Report(diag::err_drv_invalid_int_value)
+ << A->getAsString(*this) << A->getValue(*this);
+ }
+
+ return Res;
+}
+
+std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
+ llvm::SmallVector<const char *, 16> Values;
+ AddAllArgValues(Values, Id);
+ return std::vector<std::string>(Values.begin(), Values.end());
+}
+
+void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
+ if (Arg *A = getLastArg(Id)) {
+ A->claim();
+ A->render(*this, Output);
+ }
+}
+
+void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1, OptSpecifier Id2) const {
+ for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
+ ie = filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+ (*it)->render(*this, Output);
+ }
+}
+
+void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1, OptSpecifier Id2) const {
+ for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
+ ie = filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+ for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
+ Output.push_back((*it)->getValue(*this, i));
+ }
+}
+
+void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
+ const char *Translation,
+ bool Joined) const {
+ for (arg_iterator it = filtered_begin(Id0),
+ ie = filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+
+ if (Joined) {
+ Output.push_back(MakeArgString(llvm::StringRef(Translation) +
+ (*it)->getValue(*this, 0)));
+ } else {
+ Output.push_back(Translation);
+ Output.push_back((*it)->getValue(*this, 0));
+ }
+ }
+}
+
+void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
+ for (arg_iterator it = filtered_begin(Id0),
+ ie = filtered_end(); it != ie; ++it)
+ (*it)->claim();
+}
+
+const char *ArgList::MakeArgString(const llvm::Twine &T) const {
+ llvm::SmallString<256> Str;
+ T.toVector(Str);
+ return MakeArgString(Str.str());
+}
+
+const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
+ llvm::StringRef LHS,
+ llvm::StringRef RHS) const {
+ llvm::StringRef Cur = getArgString(Index);
+ if (Cur.size() == LHS.size() + RHS.size() &&
+ Cur.startswith(LHS) && Cur.endswith(RHS))
+ return Cur.data();
+
+ return MakeArgString(LHS + RHS);
+}
+
+//
+
+InputArgList::InputArgList(const char* const *ArgBegin,
+ const char* const *ArgEnd)
+ : NumInputArgStrings(ArgEnd - ArgBegin) {
+ ArgStrings.append(ArgBegin, ArgEnd);
+}
+
+InputArgList::~InputArgList() {
+ // An InputArgList always owns its arguments.
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ delete *it;
+}
+
+unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
+ unsigned Index = ArgStrings.size();
+
+ // Tuck away so we have a reliable const char *.
+ SynthesizedStrings.push_back(String0);
+ ArgStrings.push_back(SynthesizedStrings.back().c_str());
+
+ return Index;
+}
+
+unsigned InputArgList::MakeIndex(llvm::StringRef String0,
+ llvm::StringRef String1) const {
+ unsigned Index0 = MakeIndex(String0);
+ unsigned Index1 = MakeIndex(String1);
+ assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
+ (void) Index1;
+ return Index0;
+}
+
+const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
+ return getArgString(MakeIndex(Str));
+}
+
+//
+
+DerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
+ : BaseArgs(_BaseArgs) {
+}
+
+DerivedArgList::~DerivedArgList() {
+ // We only own the arguments we explicitly synthesized.
+ for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
+ it != ie; ++it)
+ delete *it;
+}
+
+const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
+ return BaseArgs.MakeArgString(Str);
+}
+
+Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
+ Arg *A = new Arg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
+ SynthesizedArgs.push_back(A);
+ return A;
+}
+
+Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
+ unsigned Index = BaseArgs.MakeIndex(Value);
+ Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index), BaseArg);
+ SynthesizedArgs.push_back(A);
+ return A;
+}
+
+Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
+ unsigned Index = BaseArgs.MakeIndex(Opt->getName(), Value);
+ Arg *A = new Arg(Opt, Index, BaseArgs.getArgString(Index + 1), BaseArg);
+ SynthesizedArgs.push_back(A);
+ return A;
+}
+
+Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
+ unsigned Index = BaseArgs.MakeIndex(Opt->getName() + Value.str());
+ Arg *A = new Arg(Opt, Index,
+ BaseArgs.getArgString(Index) + strlen(Opt->getName()),
+ BaseArg);
+ SynthesizedArgs.push_back(A);
+ return A;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp
new file mode 100644
index 0000000..90c69ff
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp
@@ -0,0 +1,39 @@
+//===--- CC1AsOptions.cpp - Clang Assembler Options Table -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/CC1AsOptions.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/OptTable.h"
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::driver::cc1asoptions;
+
+static const OptTable::Info CC1AsInfoTable[] = {
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/CC1AsOptions.inc"
+};
+
+namespace {
+
+class CC1AsOptTable : public OptTable {
+public:
+ CC1AsOptTable()
+ : OptTable(CC1AsInfoTable,
+ sizeof(CC1AsInfoTable) / sizeof(CC1AsInfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createCC1AsOptTable() {
+ return new CC1AsOptTable();
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp
new file mode 100644
index 0000000..14cf090
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp
@@ -0,0 +1,38 @@
+//===--- CC1Options.cpp - Clang CC1 Options Table -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/OptTable.h"
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::driver::cc1options;
+
+static const OptTable::Info CC1InfoTable[] = {
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/CC1Options.inc"
+};
+
+namespace {
+
+class CC1OptTable : public OptTable {
+public:
+ CC1OptTable()
+ : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createCC1OptTable() {
+ return new CC1OptTable();
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
new file mode 100644
index 0000000..5619212
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -0,0 +1,191 @@
+//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Compilation.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Program.h"
+#include <sys/stat.h>
+#include <errno.h>
+using namespace clang::driver;
+
+Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
+ InputArgList *_Args, DerivedArgList *_TranslatedArgs)
+ : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
+ TranslatedArgs(_TranslatedArgs) {
+}
+
+Compilation::~Compilation() {
+ delete TranslatedArgs;
+ delete Args;
+
+ // Free any derived arg lists.
+ for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+ DerivedArgList*>::iterator it = TCArgs.begin(),
+ ie = TCArgs.end(); it != ie; ++it)
+ if (it->second != TranslatedArgs)
+ delete it->second;
+
+ // Free the actions, if built.
+ for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
+ it != ie; ++it)
+ delete *it;
+}
+
+const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
+ const char *BoundArch) {
+ if (!TC)
+ TC = &DefaultToolChain;
+
+ DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
+ if (!Entry) {
+ Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
+ if (!Entry)
+ Entry = TranslatedArgs;
+ }
+
+ return *Entry;
+}
+
+void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
+ const char *Terminator, bool Quote) const {
+ if (const Command *C = dyn_cast<Command>(&J)) {
+ OS << " \"" << C->getExecutable() << '"';
+ for (ArgStringList::const_iterator it = C->getArguments().begin(),
+ ie = C->getArguments().end(); it != ie; ++it) {
+ OS << ' ';
+ if (!Quote) {
+ OS << *it;
+ continue;
+ }
+
+ // Quote the argument and escape shell special characters; this isn't
+ // really complete but is good enough.
+ OS << '"';
+ for (const char *s = *it; *s; ++s) {
+ if (*s == '"' || *s == '\\' || *s == '$')
+ OS << '\\';
+ OS << *s;
+ }
+ OS << '"';
+ }
+ OS << Terminator;
+ } else {
+ const JobList *Jobs = cast<JobList>(&J);
+ for (JobList::const_iterator
+ it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
+ PrintJob(OS, **it, Terminator, Quote);
+ }
+}
+
+bool Compilation::CleanupFileList(const ArgStringList &Files,
+ bool IssueErrors) const {
+ bool Success = true;
+
+ for (ArgStringList::const_iterator
+ it = Files.begin(), ie = Files.end(); it != ie; ++it) {
+
+ llvm::sys::Path P(*it);
+ std::string Error;
+
+ if (P.eraseFromDisk(false, &Error)) {
+ // Failure is only failure if the file exists and is "regular". There is
+ // a race condition here due to the limited interface of
+ // llvm::sys::Path, we want to know if the removal gave ENOENT.
+
+ // FIXME: Grumble, P.exists() is broken. PR3837.
+ struct stat buf;
+ if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG :
+ (errno != ENOENT)) {
+ if (IssueErrors)
+ getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+ << Error;
+ Success = false;
+ }
+ }
+ }
+
+ return Success;
+}
+
+int Compilation::ExecuteCommand(const Command &C,
+ const Command *&FailingCommand) const {
+ llvm::sys::Path Prog(C.getExecutable());
+ const char **Argv = new const char*[C.getArguments().size() + 2];
+ Argv[0] = C.getExecutable();
+ std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
+ Argv[C.getArguments().size() + 1] = 0;
+
+ if (getDriver().CCCEcho || getDriver().CCPrintOptions ||
+ getArgs().hasArg(options::OPT_v)) {
+ llvm::raw_ostream *OS = &llvm::errs();
+
+ // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
+ // output stream.
+ if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
+ std::string Error;
+ OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename,
+ Error,
+ llvm::raw_fd_ostream::F_Append);
+ if (!Error.empty()) {
+ getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
+ << Error;
+ FailingCommand = &C;
+ delete OS;
+ return 1;
+ }
+ }
+
+ if (getDriver().CCPrintOptions)
+ *OS << "[Logging clang options]";
+
+ PrintJob(*OS, C, "\n", /*Quote=*/getDriver().CCPrintOptions);
+
+ if (OS != &llvm::errs())
+ delete OS;
+ }
+
+ std::string Error;
+ int Res =
+ llvm::sys::Program::ExecuteAndWait(Prog, Argv,
+ /*env*/0, /*redirects*/0,
+ /*secondsToWait*/0, /*memoryLimit*/0,
+ &Error);
+ if (!Error.empty()) {
+ assert(Res && "Error string set with 0 result code!");
+ getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
+ }
+
+ if (Res)
+ FailingCommand = &C;
+
+ delete[] Argv;
+ return Res;
+}
+
+int Compilation::ExecuteJob(const Job &J,
+ const Command *&FailingCommand) const {
+ if (const Command *C = dyn_cast<Command>(&J)) {
+ return ExecuteCommand(*C, FailingCommand);
+ } else {
+ const JobList *Jobs = cast<JobList>(&J);
+ for (JobList::const_iterator
+ it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
+ if (int Res = ExecuteJob(**it, FailingCommand))
+ return Res;
+ return 0;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
new file mode 100644
index 0000000..4b6aef6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -0,0 +1,1433 @@
+//===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef HAVE_CLANG_CONFIG_H
+# include "clang/Config/config.h"
+#endif
+
+#include "clang/Driver/Driver.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Types.h"
+
+#include "clang/Basic/Version.h"
+
+#include "llvm/Config/config.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+
+#include "InputInfo.h"
+
+#include <map>
+
+#ifdef __CYGWIN__
+#include <cygwin/version.h>
+#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007
+#define IS_CYGWIN15 1
+#endif
+#endif
+
+using namespace clang::driver;
+using namespace clang;
+
+Driver::Driver(llvm::StringRef _ClangExecutable,
+ llvm::StringRef _DefaultHostTriple,
+ llvm::StringRef _DefaultImageName,
+ bool IsProduction, bool CXXIsProduction,
+ Diagnostic &_Diags)
+ : Opts(createDriverOptTable()), Diags(_Diags),
+ ClangExecutable(_ClangExecutable), DefaultHostTriple(_DefaultHostTriple),
+ DefaultImageName(_DefaultImageName),
+ DriverTitle("clang \"gcc-compatible\" driver"),
+ Host(0),
+ CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), CCCIsCXX(false),
+ CCCEcho(false), CCCPrintBindings(false), CCPrintOptions(false),
+ CCPrintHeaders(false), CCCGenericGCCName("gcc"),
+ CheckInputsExist(true), CCCUseClang(true), CCCUseClangCXX(true),
+ CCCUseClangCPP(true), CCCUsePCH(true), SuppressMissingInputWarning(false) {
+ if (IsProduction) {
+ // In a "production" build, only use clang on architectures we expect to
+ // work, and don't use clang C++.
+ //
+ // During development its more convenient to always have the driver use
+ // clang, but we don't want users to be confused when things don't work, or
+ // to file bugs for things we don't support.
+ CCCClangArchs.insert(llvm::Triple::x86);
+ CCCClangArchs.insert(llvm::Triple::x86_64);
+ CCCClangArchs.insert(llvm::Triple::arm);
+
+ if (!CXXIsProduction)
+ CCCUseClangCXX = false;
+ }
+
+ Name = llvm::sys::path::stem(ClangExecutable);
+ Dir = llvm::sys::path::parent_path(ClangExecutable);
+
+ // Compute the path to the resource directory.
+ llvm::StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
+ llvm::SmallString<128> P(Dir);
+ if (ClangResourceDir != "")
+ llvm::sys::path::append(P, ClangResourceDir);
+ else
+ llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING);
+ ResourceDir = P.str();
+}
+
+Driver::~Driver() {
+ delete Opts;
+ delete Host;
+}
+
+InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
+ const char **ArgEnd) {
+ llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
+ unsigned MissingArgIndex, MissingArgCount;
+ InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd,
+ MissingArgIndex, MissingArgCount);
+
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diag(clang::diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+ // Check for unsupported options.
+ for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
+ it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().isUnsupported()) {
+ Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
+ continue;
+ }
+ }
+
+ return Args;
+}
+
+DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
+ DerivedArgList *DAL = new DerivedArgList(Args);
+
+ bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
+ for (ArgList::const_iterator it = Args.begin(),
+ ie = Args.end(); it != ie; ++it) {
+ const Arg *A = *it;
+
+ // Unfortunately, we have to parse some forwarding options (-Xassembler,
+ // -Xlinker, -Xpreprocessor) because we either integrate their functionality
+ // (assembler and preprocessor), or bypass a previous driver ('collect2').
+
+ // Rewrite linker options, to replace --no-demangle with a custom internal
+ // option.
+ if ((A->getOption().matches(options::OPT_Wl_COMMA) ||
+ A->getOption().matches(options::OPT_Xlinker)) &&
+ A->containsValue("--no-demangle")) {
+ // Add the rewritten no-demangle argument.
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle));
+
+ // Add the remaining values as Xlinker arguments.
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
+ if (llvm::StringRef(A->getValue(Args, i)) != "--no-demangle")
+ DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker),
+ A->getValue(Args, i));
+
+ continue;
+ }
+
+ // Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by
+ // some build systems. We don't try to be complete here because we don't
+ // care to encourage this usage model.
+ if (A->getOption().matches(options::OPT_Wp_COMMA) &&
+ A->getNumValues() == 2 &&
+ (A->getValue(Args, 0) == llvm::StringRef("-MD") ||
+ A->getValue(Args, 0) == llvm::StringRef("-MMD"))) {
+ // Rewrite to -MD/-MMD along with -MF.
+ if (A->getValue(Args, 0) == llvm::StringRef("-MD"))
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD));
+ else
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD));
+ DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF),
+ A->getValue(Args, 1));
+ continue;
+ }
+
+ // Rewrite reserved library names.
+ if (A->getOption().matches(options::OPT_l)) {
+ llvm::StringRef Value = A->getValue(Args);
+
+ // Rewrite unless -nostdlib is present.
+ if (!HasNostdlib && Value == "stdc++") {
+ DAL->AddFlagArg(A, Opts->getOption(
+ options::OPT_Z_reserved_lib_stdcxx));
+ continue;
+ }
+
+ // Rewrite unconditionally.
+ if (Value == "cc_kext") {
+ DAL->AddFlagArg(A, Opts->getOption(
+ options::OPT_Z_reserved_lib_cckext));
+ continue;
+ }
+ }
+
+ DAL->append(*it);
+ }
+
+ // Add a default value of -mlinker-version=, if one was given and the user
+ // didn't specify one.
+#if defined(HOST_LINK_VERSION)
+ if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+ DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
+ HOST_LINK_VERSION);
+ DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
+ }
+#endif
+
+ return DAL;
+}
+
+Compilation *Driver::BuildCompilation(int argc, const char **argv) {
+ llvm::PrettyStackTraceString CrashInfo("Compilation construction");
+
+ // FIXME: Handle environment options which effect driver behavior, somewhere
+ // (client?). GCC_EXEC_PREFIX, COMPILER_PATH, LIBRARY_PATH, LPATH,
+ // CC_PRINT_OPTIONS.
+
+ // FIXME: What are we going to do with -V and -b?
+
+ // FIXME: This stuff needs to go into the Compilation, not the driver.
+ bool CCCPrintOptions = false, CCCPrintActions = false;
+
+ const char **Start = argv + 1, **End = argv + argc;
+
+ InputArgList *Args = ParseArgStrings(Start, End);
+
+ // -no-canonical-prefixes is used very early in main.
+ Args->ClaimAllArgs(options::OPT_no_canonical_prefixes);
+
+ // Ignore -pipe.
+ Args->ClaimAllArgs(options::OPT_pipe);
+
+ // Extract -ccc args.
+ //
+ // FIXME: We need to figure out where this behavior should live. Most of it
+ // should be outside in the client; the parts that aren't should have proper
+ // options, either by introducing new ones or by overloading gcc ones like -V
+ // or -b.
+ CCCPrintOptions = Args->hasArg(options::OPT_ccc_print_options);
+ CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases);
+ CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings);
+ CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX;
+ if (CCCIsCXX) {
+#ifdef IS_CYGWIN15
+ CCCGenericGCCName = "g++-4";
+#else
+ CCCGenericGCCName = "g++";
+#endif
+ }
+ CCCEcho = Args->hasArg(options::OPT_ccc_echo);
+ if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name))
+ CCCGenericGCCName = A->getValue(*Args);
+ CCCUseClangCXX = Args->hasFlag(options::OPT_ccc_clang_cxx,
+ options::OPT_ccc_no_clang_cxx,
+ CCCUseClangCXX);
+ CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch,
+ options::OPT_ccc_pch_is_pth);
+ CCCUseClang = !Args->hasArg(options::OPT_ccc_no_clang);
+ CCCUseClangCPP = !Args->hasArg(options::OPT_ccc_no_clang_cpp);
+ if (const Arg *A = Args->getLastArg(options::OPT_ccc_clang_archs)) {
+ llvm::StringRef Cur = A->getValue(*Args);
+
+ CCCClangArchs.clear();
+ while (!Cur.empty()) {
+ std::pair<llvm::StringRef, llvm::StringRef> Split = Cur.split(',');
+
+ if (!Split.first.empty()) {
+ llvm::Triple::ArchType Arch =
+ llvm::Triple(Split.first, "", "").getArch();
+
+ if (Arch == llvm::Triple::UnknownArch)
+ Diag(clang::diag::err_drv_invalid_arch_name) << Split.first;
+
+ CCCClangArchs.insert(Arch);
+ }
+
+ Cur = Split.second;
+ }
+ }
+ // FIXME: We shouldn't overwrite the default host triple here, but we have
+ // nowhere else to put this currently.
+ if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple))
+ DefaultHostTriple = A->getValue(*Args);
+ if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
+ Dir = InstalledDir = A->getValue(*Args);
+ for (arg_iterator it = Args->filtered_begin(options::OPT_B),
+ ie = Args->filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+ PrefixDirs.push_back(A->getValue(*Args, 0));
+ }
+
+ Host = GetHostInfo(DefaultHostTriple.c_str());
+
+ // Perform the default argument translations.
+ DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
+
+ // The compilation takes ownership of Args.
+ Compilation *C = new Compilation(*this, *Host->CreateToolChain(*Args), Args,
+ TranslatedArgs);
+
+ // FIXME: This behavior shouldn't be here.
+ if (CCCPrintOptions) {
+ PrintOptions(C->getInputArgs());
+ return C;
+ }
+
+ if (!HandleImmediateArgs(*C))
+ return C;
+
+ // Construct the list of abstract actions to perform for this compilation.
+ if (Host->useDriverDriver())
+ BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
+ C->getActions());
+ else
+ BuildActions(C->getDefaultToolChain(), C->getArgs(), C->getActions());
+
+ if (CCCPrintActions) {
+ PrintActions(*C);
+ return C;
+ }
+
+ BuildJobs(*C);
+
+ return C;
+}
+
+int Driver::ExecuteCompilation(const Compilation &C) const {
+ // Just print if -### was present.
+ if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
+ C.PrintJob(llvm::errs(), C.getJobs(), "\n", true);
+ return 0;
+ }
+
+ // If there were errors building the compilation, quit now.
+ if (getDiags().hasErrorOccurred())
+ return 1;
+
+ const Command *FailingCommand = 0;
+ int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
+
+ // Remove temp files.
+ C.CleanupFileList(C.getTempFiles());
+
+ // If the command succeeded, we are done.
+ if (Res == 0)
+ return Res;
+
+ // Otherwise, remove result files as well.
+ if (!C.getArgs().hasArg(options::OPT_save_temps))
+ C.CleanupFileList(C.getResultFiles(), true);
+
+ // Print extra information about abnormal failures, if possible.
+ //
+ // This is ad-hoc, but we don't want to be excessively noisy. If the result
+ // status was 1, assume the command failed normally. In particular, if it was
+ // the compiler then assume it gave a reasonable error code. Failures in other
+ // tools are less common, and they generally have worse diagnostics, so always
+ // print the diagnostic there.
+ const Tool &FailingTool = FailingCommand->getCreator();
+
+ if (!FailingCommand->getCreator().hasGoodDiagnostics() || Res != 1) {
+ // FIXME: See FIXME above regarding result code interpretation.
+ if (Res < 0)
+ Diag(clang::diag::err_drv_command_signalled)
+ << FailingTool.getShortName() << -Res;
+ else
+ Diag(clang::diag::err_drv_command_failed)
+ << FailingTool.getShortName() << Res;
+ }
+
+ return Res;
+}
+
+void Driver::PrintOptions(const ArgList &Args) const {
+ unsigned i = 0;
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ it != ie; ++it, ++i) {
+ Arg *A = *it;
+ llvm::errs() << "Option " << i << " - "
+ << "Name: \"" << A->getOption().getName() << "\", "
+ << "Values: {";
+ for (unsigned j = 0; j < A->getNumValues(); ++j) {
+ if (j)
+ llvm::errs() << ", ";
+ llvm::errs() << '"' << A->getValue(Args, j) << '"';
+ }
+ llvm::errs() << "}\n";
+ }
+}
+
+void Driver::PrintHelp(bool ShowHidden) const {
+ getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
+ ShowHidden);
+}
+
+void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
+ OS << getClangFullVersion() << '\n';
+ const ToolChain &TC = C.getDefaultToolChain();
+ OS << "Target: " << TC.getTripleString() << '\n';
+
+ // Print the threading model.
+ //
+ // FIXME: Implement correctly.
+ OS << "Thread model: " << "posix" << '\n';
+}
+
+/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
+/// option.
+static void PrintDiagnosticCategories(llvm::raw_ostream &OS) {
+ for (unsigned i = 1; // Skip the empty category.
+ const char *CategoryName = DiagnosticIDs::getCategoryNameFromID(i); ++i)
+ OS << i << ',' << CategoryName << '\n';
+}
+
+bool Driver::HandleImmediateArgs(const Compilation &C) {
+ // The order these options are handled in gcc is all over the place, but we
+ // don't expect inconsistencies w.r.t. that to matter in practice.
+
+ if (C.getArgs().hasArg(options::OPT_dumpmachine)) {
+ llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n';
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_dumpversion)) {
+ // Since -dumpversion is only implemented for pedantic GCC compatibility, we
+ // return an answer which matches our definition of __VERSION__.
+ //
+ // If we want to return a more correct answer some day, then we should
+ // introduce a non-pedantically GCC compatible mode to Clang in which we
+ // provide sensible definitions for -dumpversion, __VERSION__, etc.
+ llvm::outs() << "4.2.1\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) {
+ PrintDiagnosticCategories(llvm::outs());
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__help) ||
+ C.getArgs().hasArg(options::OPT__help_hidden)) {
+ PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__version)) {
+ // Follow gcc behavior and use stdout for --version and stderr for -v.
+ PrintVersion(C, llvm::outs());
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_v) ||
+ C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
+ PrintVersion(C, llvm::errs());
+ SuppressMissingInputWarning = true;
+ }
+
+ const ToolChain &TC = C.getDefaultToolChain();
+ if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
+ llvm::outs() << "programs: =";
+ for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(),
+ ie = TC.getProgramPaths().end(); it != ie; ++it) {
+ if (it != TC.getProgramPaths().begin())
+ llvm::outs() << ':';
+ llvm::outs() << *it;
+ }
+ llvm::outs() << "\n";
+ llvm::outs() << "libraries: =";
+ for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
+ ie = TC.getFilePaths().end(); it != ie; ++it) {
+ if (it != TC.getFilePaths().begin())
+ llvm::outs() << ':';
+ llvm::outs() << *it;
+ }
+ llvm::outs() << "\n";
+ return false;
+ }
+
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
+ llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC) << "\n";
+ return false;
+ }
+
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
+ llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC) << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
+ llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
+ // FIXME: We need tool chain support for this.
+ llvm::outs() << ".;\n";
+
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "x86_64;@m64" << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64;@m64" << "\n";
+ break;
+ }
+ return false;
+ }
+
+ // FIXME: What is the difference between print-multi-directory and
+ // print-multi-os-directory?
+ if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
+ C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::ppc:
+ llvm::outs() << "." << "\n";
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "." << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64" << "\n";
+ break;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+static unsigned PrintActions1(const Compilation &C, Action *A,
+ std::map<Action*, unsigned> &Ids) {
+ if (Ids.count(A))
+ return Ids[A];
+
+ std::string str;
+ llvm::raw_string_ostream os(str);
+
+ os << Action::getClassName(A->getKind()) << ", ";
+ if (InputAction *IA = dyn_cast<InputAction>(A)) {
+ os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\"";
+ } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
+ os << '"' << (BIA->getArchName() ? BIA->getArchName() :
+ C.getDefaultToolChain().getArchName()) << '"'
+ << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
+ } else {
+ os << "{";
+ for (Action::iterator it = A->begin(), ie = A->end(); it != ie;) {
+ os << PrintActions1(C, *it, Ids);
+ ++it;
+ if (it != ie)
+ os << ", ";
+ }
+ os << "}";
+ }
+
+ unsigned Id = Ids.size();
+ Ids[A] = Id;
+ llvm::errs() << Id << ": " << os.str() << ", "
+ << types::getTypeName(A->getType()) << "\n";
+
+ return Id;
+}
+
+void Driver::PrintActions(const Compilation &C) const {
+ std::map<Action*, unsigned> Ids;
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it)
+ PrintActions1(C, *it, Ids);
+}
+
+/// \brief Check whether the given input tree contains any compilation (or
+/// assembly) actions.
+static bool ContainsCompileAction(const Action *A) {
+ if (isa<CompileJobAction>(A) || isa<AssembleJobAction>(A))
+ return true;
+
+ for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
+ if (ContainsCompileAction(*it))
+ return true;
+
+ return false;
+}
+
+void Driver::BuildUniversalActions(const ToolChain &TC,
+ const ArgList &Args,
+ ActionList &Actions) const {
+ llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
+ // Collect the list of architectures. Duplicates are allowed, but should only
+ // be handled once (in the order seen).
+ llvm::StringSet<> ArchNames;
+ llvm::SmallVector<const char *, 4> Archs;
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ it != ie; ++it) {
+ Arg *A = *it;
+
+ if (A->getOption().matches(options::OPT_arch)) {
+ // Validate the option here; we don't save the type here because its
+ // particular spelling may participate in other driver choices.
+ llvm::Triple::ArchType Arch =
+ llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+ if (Arch == llvm::Triple::UnknownArch) {
+ Diag(clang::diag::err_drv_invalid_arch_name)
+ << A->getAsString(Args);
+ continue;
+ }
+
+ A->claim();
+ if (ArchNames.insert(A->getValue(Args)))
+ Archs.push_back(A->getValue(Args));
+ }
+ }
+
+ // When there is no explicit arch for this platform, make sure we still bind
+ // the architecture (to the default) so that -Xarch_ is handled correctly.
+ if (!Archs.size())
+ Archs.push_back(0);
+
+ // FIXME: We killed off some others but these aren't yet detected in a
+ // functional manner. If we added information to jobs about which "auxiliary"
+ // files they wrote then we could detect the conflict these cause downstream.
+ if (Archs.size() > 1) {
+ // No recovery needed, the point of this is just to prevent
+ // overwriting the same files.
+ if (const Arg *A = Args.getLastArg(options::OPT_save_temps))
+ Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs)
+ << A->getAsString(Args);
+ }
+
+ ActionList SingleActions;
+ BuildActions(TC, Args, SingleActions);
+
+ // Add in arch bindings for every top level action, as well as lipo and
+ // dsymutil steps if needed.
+ for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) {
+ Action *Act = SingleActions[i];
+
+ // Make sure we can lipo this kind of output. If not (and it is an actual
+ // output) then we disallow, since we can't create an output file with the
+ // right name without overwriting it. We could remove this oddity by just
+ // changing the output names to include the arch, which would also fix
+ // -save-temps. Compatibility wins for now.
+
+ if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
+ Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
+ << types::getTypeName(Act->getType());
+
+ ActionList Inputs;
+ for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
+ Inputs.push_back(new BindArchAction(Act, Archs[i]));
+ if (i != 0)
+ Inputs.back()->setOwnsInputs(false);
+ }
+
+ // Lipo if necessary, we do it this way because we need to set the arch flag
+ // so that -Xarch_ gets overwritten.
+ if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
+ Actions.append(Inputs.begin(), Inputs.end());
+ else
+ Actions.push_back(new LipoJobAction(Inputs, Act->getType()));
+
+ // Add a 'dsymutil' step if necessary, when debug info is enabled and we
+ // have a compile input. We need to run 'dsymutil' ourselves in such cases
+ // because the debug info will refer to a temporary object file which is
+ // will be removed at the end of the compilation process.
+ if (Act->getType() == types::TY_Image) {
+ Arg *A = Args.getLastArg(options::OPT_g_Group);
+ if (A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_gstabs) &&
+ ContainsCompileAction(Actions.back())) {
+ ActionList Inputs;
+ Inputs.push_back(Actions.back());
+ Actions.pop_back();
+
+ Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
+ }
+ }
+ }
+}
+
+void Driver::BuildActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
+ // Start by constructing the list of inputs and their types.
+
+ // Track the current user specified (-x) input. We also explicitly track the
+ // argument used to set the type; we only want to claim the type when we
+ // actually use it, so we warn about unused -x arguments.
+ types::ID InputType = types::TY_Nothing;
+ Arg *InputTypeArg = 0;
+
+ llvm::SmallVector<std::pair<types::ID, const Arg*>, 16> Inputs;
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ it != ie; ++it) {
+ Arg *A = *it;
+
+ if (isa<InputOption>(A->getOption())) {
+ const char *Value = A->getValue(Args);
+ types::ID Ty = types::TY_INVALID;
+
+ // Infer the input type if necessary.
+ if (InputType == types::TY_Nothing) {
+ // If there was an explicit arg for this, claim it.
+ if (InputTypeArg)
+ InputTypeArg->claim();
+
+ // stdin must be handled specially.
+ if (memcmp(Value, "-", 2) == 0) {
+ // If running with -E, treat as a C input (this changes the builtin
+ // macros, for example). This may be overridden by -ObjC below.
+ //
+ // Otherwise emit an error but still use a valid type to avoid
+ // spurious errors (e.g., no inputs).
+ if (!Args.hasArgNoClaim(options::OPT_E))
+ Diag(clang::diag::err_drv_unknown_stdin_type);
+ Ty = types::TY_C;
+ } else {
+ // Otherwise lookup by extension, and fallback to ObjectType if not
+ // found. We use a host hook here because Darwin at least has its own
+ // idea of what .s is.
+ if (const char *Ext = strrchr(Value, '.'))
+ Ty = TC.LookupTypeForExtension(Ext + 1);
+
+ if (Ty == types::TY_INVALID)
+ Ty = types::TY_Object;
+
+ // If the driver is invoked as C++ compiler (like clang++ or c++) it
+ // should autodetect some input files as C++ for g++ compatibility.
+ if (CCCIsCXX) {
+ types::ID OldTy = Ty;
+ Ty = types::lookupCXXTypeForCType(Ty);
+
+ if (Ty != OldTy)
+ Diag(clang::diag::warn_drv_treating_input_as_cxx)
+ << getTypeName(OldTy) << getTypeName(Ty);
+ }
+ }
+
+ // -ObjC and -ObjC++ override the default language, but only for "source
+ // files". We just treat everything that isn't a linker input as a
+ // source file.
+ //
+ // FIXME: Clean this up if we move the phase sequence into the type.
+ if (Ty != types::TY_Object) {
+ if (Args.hasArg(options::OPT_ObjC))
+ Ty = types::TY_ObjC;
+ else if (Args.hasArg(options::OPT_ObjCXX))
+ Ty = types::TY_ObjCXX;
+ }
+ } else {
+ assert(InputTypeArg && "InputType set w/o InputTypeArg");
+ InputTypeArg->claim();
+ Ty = InputType;
+ }
+
+ // Check that the file exists, if enabled.
+ if (CheckInputsExist && memcmp(Value, "-", 2) != 0) {
+ llvm::SmallString<64> Path(Value);
+ if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory))
+ if (llvm::sys::path::is_absolute(Path.str())) {
+ Path = WorkDir->getValue(Args);
+ llvm::sys::path::append(Path, Value);
+ }
+
+ bool exists = false;
+ if (/*error_code ec =*/llvm::sys::fs::exists(Value, exists) || !exists)
+ Diag(clang::diag::err_drv_no_such_file) << Path.str();
+ else
+ Inputs.push_back(std::make_pair(Ty, A));
+ } else
+ Inputs.push_back(std::make_pair(Ty, A));
+
+ } else if (A->getOption().isLinkerInput()) {
+ // Just treat as object type, we could make a special type for this if
+ // necessary.
+ Inputs.push_back(std::make_pair(types::TY_Object, A));
+
+ } else if (A->getOption().matches(options::OPT_x)) {
+ InputTypeArg = A;
+ InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args));
+
+ // Follow gcc behavior and treat as linker input for invalid -x
+ // options. Its not clear why we shouldn't just revert to unknown; but
+ // this isn't very important, we might as well be bug compatible.
+ if (!InputType) {
+ Diag(clang::diag::err_drv_unknown_language) << A->getValue(Args);
+ InputType = types::TY_Object;
+ }
+ }
+ }
+
+ if (!SuppressMissingInputWarning && Inputs.empty()) {
+ Diag(clang::diag::err_drv_no_input_files);
+ return;
+ }
+
+ // Determine which compilation mode we are in. We look for options which
+ // affect the phase, starting with the earliest phases, and record which
+ // option we used to determine the final phase.
+ Arg *FinalPhaseArg = 0;
+ phases::ID FinalPhase;
+
+ // -{E,M,MM} only run the preprocessor.
+ if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) {
+ FinalPhase = phases::Preprocess;
+
+ // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
+ } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT_rewrite_objc)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT__analyze,
+ options::OPT__analyze_auto)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT_S))) {
+ FinalPhase = phases::Compile;
+
+ // -c only runs up to the assembler.
+ } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) {
+ FinalPhase = phases::Assemble;
+
+ // Otherwise do everything.
+ } else
+ FinalPhase = phases::Link;
+
+ // Reject -Z* at the top level, these options should never have been exposed
+ // by gcc.
+ if (Arg *A = Args.getLastArg(options::OPT_Z_Joined))
+ Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args);
+
+ // Construct the actions to perform.
+ ActionList LinkerInputs;
+ for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+ types::ID InputType = Inputs[i].first;
+ const Arg *InputArg = Inputs[i].second;
+
+ unsigned NumSteps = types::getNumCompilationPhases(InputType);
+ assert(NumSteps && "Invalid number of steps!");
+
+ // If the first step comes after the final phase we are doing as part of
+ // this compilation, warn the user about it.
+ phases::ID InitialPhase = types::getCompilationPhase(InputType, 0);
+ if (InitialPhase > FinalPhase) {
+ // Claim here to avoid the more general unused warning.
+ InputArg->claim();
+
+ // Special case '-E' warning on a previously preprocessed file to make
+ // more sense.
+ if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess &&
+ getPreprocessedType(InputType) == types::TY_INVALID)
+ Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
+ << InputArg->getAsString(Args)
+ << FinalPhaseArg->getOption().getName();
+ else
+ Diag(clang::diag::warn_drv_input_file_unused)
+ << InputArg->getAsString(Args)
+ << getPhaseName(InitialPhase)
+ << FinalPhaseArg->getOption().getName();
+ continue;
+ }
+
+ // Build the pipeline for this file.
+ llvm::OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
+ for (unsigned i = 0; i != NumSteps; ++i) {
+ phases::ID Phase = types::getCompilationPhase(InputType, i);
+
+ // We are done if this step is past what the user requested.
+ if (Phase > FinalPhase)
+ break;
+
+ // Queue linker inputs.
+ if (Phase == phases::Link) {
+ assert(i + 1 == NumSteps && "linking must be final compilation step.");
+ LinkerInputs.push_back(Current.take());
+ break;
+ }
+
+ // Some types skip the assembler phase (e.g., llvm-bc), but we can't
+ // encode this in the steps because the intermediate type depends on
+ // arguments. Just special case here.
+ if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm)
+ continue;
+
+ // Otherwise construct the appropriate action.
+ Current.reset(ConstructPhaseAction(Args, Phase, Current.take()));
+ if (Current->getType() == types::TY_Nothing)
+ break;
+ }
+
+ // If we ended with something, add to the output list.
+ if (Current)
+ Actions.push_back(Current.take());
+ }
+
+ // Add a link action if necessary.
+ if (!LinkerInputs.empty())
+ Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+
+ // If we are linking, claim any options which are obviously only used for
+ // compilation.
+ if (FinalPhase == phases::Link)
+ Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
+}
+
+Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+ Action *Input) const {
+ llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
+ // Build the appropriate action.
+ switch (Phase) {
+ case phases::Link: assert(0 && "link action invalid here.");
+ case phases::Preprocess: {
+ types::ID OutputTy;
+ // -{M, MM} alter the output type.
+ if (Args.hasArg(options::OPT_M, options::OPT_MM)) {
+ OutputTy = types::TY_Dependencies;
+ } else {
+ OutputTy = types::getPreprocessedType(Input->getType());
+ assert(OutputTy != types::TY_INVALID &&
+ "Cannot preprocess this input type!");
+ }
+ return new PreprocessJobAction(Input, OutputTy);
+ }
+ case phases::Precompile:
+ return new PrecompileJobAction(Input, types::TY_PCH);
+ case phases::Compile: {
+ bool HasO4 = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group))
+ HasO4 = A->getOption().matches(options::OPT_O4);
+
+ if (Args.hasArg(options::OPT_fsyntax_only)) {
+ return new CompileJobAction(Input, types::TY_Nothing);
+ } else if (Args.hasArg(options::OPT_rewrite_objc)) {
+ return new CompileJobAction(Input, types::TY_RewrittenObjC);
+ } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) {
+ return new AnalyzeJobAction(Input, types::TY_Plist);
+ } else if (Args.hasArg(options::OPT_emit_ast)) {
+ return new CompileJobAction(Input, types::TY_AST);
+ } else if (Args.hasArg(options::OPT_emit_llvm) ||
+ Args.hasArg(options::OPT_flto) || HasO4) {
+ types::ID Output =
+ Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
+ return new CompileJobAction(Input, Output);
+ } else {
+ return new CompileJobAction(Input, types::TY_PP_Asm);
+ }
+ }
+ case phases::Assemble:
+ return new AssembleJobAction(Input, types::TY_Object);
+ }
+
+ assert(0 && "invalid phase in ConstructPhaseAction");
+ return 0;
+}
+
+void Driver::BuildJobs(Compilation &C) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+
+ Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+
+ // It is an error to provide a -o option if we are making multiple output
+ // files.
+ if (FinalOutput) {
+ unsigned NumOutputs = 0;
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it)
+ if ((*it)->getType() != types::TY_Nothing)
+ ++NumOutputs;
+
+ if (NumOutputs > 1) {
+ Diag(clang::diag::err_drv_output_argument_with_multiple_files);
+ FinalOutput = 0;
+ }
+ }
+
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it) {
+ Action *A = *it;
+
+ // If we are linking an image for multiple archs then the linker wants
+ // -arch_multiple and -final_output <final image name>. Unfortunately, this
+ // doesn't fit in cleanly because we have to pass this information down.
+ //
+ // FIXME: This is a hack; find a cleaner way to integrate this into the
+ // process.
+ const char *LinkingOutput = 0;
+ if (isa<LipoJobAction>(A)) {
+ if (FinalOutput)
+ LinkingOutput = FinalOutput->getValue(C.getArgs());
+ else
+ LinkingOutput = DefaultImageName.c_str();
+ }
+
+ InputInfo II;
+ BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+ /*BoundArch*/0,
+ /*AtTopLevel*/ true,
+ /*LinkingOutput*/ LinkingOutput,
+ II);
+ }
+
+ // If the user passed -Qunused-arguments or there were errors, don't warn
+ // about any unused arguments.
+ if (Diags.hasErrorOccurred() ||
+ C.getArgs().hasArg(options::OPT_Qunused_arguments))
+ return;
+
+ // Claim -### here.
+ (void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
+
+ for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
+ it != ie; ++it) {
+ Arg *A = *it;
+
+ // FIXME: It would be nice to be able to send the argument to the
+ // Diagnostic, so that extra values, position, and so on could be printed.
+ if (!A->isClaimed()) {
+ if (A->getOption().hasNoArgumentUnused())
+ continue;
+
+ // Suppress the warning automatically if this is just a flag, and it is an
+ // instance of an argument we already claimed.
+ const Option &Opt = A->getOption();
+ if (isa<FlagOption>(Opt)) {
+ bool DuplicateClaimed = false;
+
+ for (arg_iterator it = C.getArgs().filtered_begin(&Opt),
+ ie = C.getArgs().filtered_end(); it != ie; ++it) {
+ if ((*it)->isClaimed()) {
+ DuplicateClaimed = true;
+ break;
+ }
+ }
+
+ if (DuplicateClaimed)
+ continue;
+ }
+
+ Diag(clang::diag::warn_drv_unused_argument)
+ << A->getAsString(C.getArgs());
+ }
+ }
+}
+
+static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
+ const JobAction *JA,
+ const ActionList *&Inputs) {
+ const Tool *ToolForJob = 0;
+
+ // See if we should look for a compiler with an integrated assembler. We match
+ // bottom up, so what we are actually looking for is an assembler job with a
+ // compiler input.
+
+ // FIXME: This doesn't belong here, but ideally we will support static soon
+ // anyway.
+ bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) ||
+ C.getArgs().hasArg(options::OPT_static) ||
+ C.getArgs().hasArg(options::OPT_fapple_kext));
+ bool IsIADefault = (TC->IsIntegratedAssemblerDefault() && !HasStatic);
+ if (C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIADefault) &&
+ !C.getArgs().hasArg(options::OPT_save_temps) &&
+ isa<AssembleJobAction>(JA) &&
+ Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
+ const Tool &Compiler = TC->SelectTool(C,cast<JobAction>(**Inputs->begin()));
+ if (Compiler.hasIntegratedAssembler()) {
+ Inputs = &(*Inputs)[0]->getInputs();
+ ToolForJob = &Compiler;
+ }
+ }
+
+ // Otherwise use the tool for the current job.
+ if (!ToolForJob)
+ ToolForJob = &TC->SelectTool(C, *JA);
+
+ // See if we should use an integrated preprocessor. We do so when we have
+ // exactly one input, since this is the only use case we care about
+ // (irrelevant since we don't support combine yet).
+ if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) &&
+ !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
+ !C.getArgs().hasArg(options::OPT_traditional_cpp) &&
+ !C.getArgs().hasArg(options::OPT_save_temps) &&
+ ToolForJob->hasIntegratedCPP())
+ Inputs = &(*Inputs)[0]->getInputs();
+
+ return *ToolForJob;
+}
+
+void Driver::BuildJobsForAction(Compilation &C,
+ const Action *A,
+ const ToolChain *TC,
+ const char *BoundArch,
+ bool AtTopLevel,
+ const char *LinkingOutput,
+ InputInfo &Result) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+
+ if (const InputAction *IA = dyn_cast<InputAction>(A)) {
+ // FIXME: It would be nice to not claim this here; maybe the old scheme of
+ // just using Args was better?
+ const Arg &Input = IA->getInputArg();
+ Input.claim();
+ if (Input.getOption().matches(options::OPT_INPUT)) {
+ const char *Name = Input.getValue(C.getArgs());
+ Result = InputInfo(Name, A->getType(), Name);
+ } else
+ Result = InputInfo(&Input, A->getType(), "");
+ return;
+ }
+
+ if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
+ const ToolChain *TC = &C.getDefaultToolChain();
+
+ std::string Arch;
+ if (BAA->getArchName())
+ TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName());
+
+ BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
+ AtTopLevel, LinkingOutput, Result);
+ return;
+ }
+
+ const ActionList *Inputs = &A->getInputs();
+
+ const JobAction *JA = cast<JobAction>(A);
+ const Tool &T = SelectToolForJob(C, TC, JA, Inputs);
+
+ // Only use pipes when there is exactly one input.
+ InputInfoList InputInfos;
+ for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
+ it != ie; ++it) {
+ // Treat dsymutil sub-jobs as being at the top-level too, they shouldn't get
+ // temporary output names.
+ //
+ // FIXME: Clean this up.
+ bool SubJobAtTopLevel = false;
+ if (AtTopLevel && isa<DsymutilJobAction>(A))
+ SubJobAtTopLevel = true;
+
+ InputInfo II;
+ BuildJobsForAction(C, *it, TC, BoundArch,
+ SubJobAtTopLevel, LinkingOutput, II);
+ InputInfos.push_back(II);
+ }
+
+ // Always use the first input as the base input.
+ const char *BaseInput = InputInfos[0].getBaseInput();
+
+ // ... except dsymutil actions, which use their actual input as the base
+ // input.
+ if (JA->getType() == types::TY_dSYM)
+ BaseInput = InputInfos[0].getFilename();
+
+ // Determine the place to write output to, if any.
+ if (JA->getType() == types::TY_Nothing) {
+ Result = InputInfo(A->getType(), BaseInput);
+ } else {
+ Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel),
+ A->getType(), BaseInput);
+ }
+
+ if (CCCPrintBindings) {
+ llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"'
+ << " - \"" << T.getName() << "\", inputs: [";
+ for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
+ llvm::errs() << InputInfos[i].getAsString();
+ if (i + 1 != e)
+ llvm::errs() << ", ";
+ }
+ llvm::errs() << "], output: " << Result.getAsString() << "\n";
+ } else {
+ T.ConstructJob(C, *JA, Result, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
+ }
+}
+
+const char *Driver::GetNamedOutputPath(Compilation &C,
+ const JobAction &JA,
+ const char *BaseInput,
+ bool AtTopLevel) const {
+ llvm::PrettyStackTraceString CrashInfo("Computing output path");
+ // Output to a user requested destination?
+ if (AtTopLevel && !isa<DsymutilJobAction>(JA)) {
+ if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
+ return C.addResultFile(FinalOutput->getValue(C.getArgs()));
+ }
+
+ // Default to writing to stdout?
+ if (AtTopLevel && isa<PreprocessJobAction>(JA))
+ return "-";
+
+ // Output to a temporary file?
+ if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) {
+ std::string TmpName =
+ GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
+ return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+ }
+
+ llvm::SmallString<128> BasePath(BaseInput);
+ llvm::StringRef BaseName = llvm::sys::path::filename(BasePath);
+
+ // Determine what the derived output name should be.
+ const char *NamedOutput;
+ if (JA.getType() == types::TY_Image) {
+ NamedOutput = DefaultImageName.c_str();
+ } else {
+ const char *Suffix = types::getTypeTempSuffix(JA.getType());
+ assert(Suffix && "All types used for output should have a suffix.");
+
+ std::string::size_type End = std::string::npos;
+ if (!types::appendSuffixForType(JA.getType()))
+ End = BaseName.rfind('.');
+ std::string Suffixed(BaseName.substr(0, End));
+ Suffixed += '.';
+ Suffixed += Suffix;
+ NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
+ }
+
+ // As an annoying special case, PCH generation doesn't strip the pathname.
+ if (JA.getType() == types::TY_PCH) {
+ llvm::sys::path::remove_filename(BasePath);
+ if (BasePath.empty())
+ BasePath = NamedOutput;
+ else
+ llvm::sys::path::append(BasePath, NamedOutput);
+ return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()));
+ } else {
+ return C.addResultFile(NamedOutput);
+ }
+}
+
+std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // attempting to use this prefix when lokup up program paths.
+ for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
+ ie = PrefixDirs.end(); it != ie; ++it) {
+ llvm::sys::Path P(*it);
+ P.appendComponent(Name);
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ return P.str();
+ }
+
+ const ToolChain::path_list &List = TC.getFilePaths();
+ for (ToolChain::path_list::const_iterator
+ it = List.begin(), ie = List.end(); it != ie; ++it) {
+ llvm::sys::Path P(*it);
+ P.appendComponent(Name);
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ return P.str();
+ }
+
+ return Name;
+}
+
+std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC,
+ bool WantFile) const {
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // attempting to use this prefix when lokup up program paths.
+ for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
+ ie = PrefixDirs.end(); it != ie; ++it) {
+ llvm::sys::Path P(*it);
+ P.appendComponent(Name);
+ bool Exists;
+ if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists
+ : P.canExecute())
+ return P.str();
+ }
+
+ const ToolChain::path_list &List = TC.getProgramPaths();
+ for (ToolChain::path_list::const_iterator
+ it = List.begin(), ie = List.end(); it != ie; ++it) {
+ llvm::sys::Path P(*it);
+ P.appendComponent(Name);
+ bool Exists;
+ if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists
+ : P.canExecute())
+ return P.str();
+ }
+
+ // If all else failed, search the path.
+ llvm::sys::Path P(llvm::sys::Program::FindProgramByName(Name));
+ if (!P.empty())
+ return P.str();
+
+ return Name;
+}
+
+std::string Driver::GetTemporaryPath(const char *Suffix) const {
+ // FIXME: This is lame; sys::Path should provide this function (in particular,
+ // it should know how to find the temporary files dir).
+ std::string Error;
+ const char *TmpDir = ::getenv("TMPDIR");
+ if (!TmpDir)
+ TmpDir = ::getenv("TEMP");
+ if (!TmpDir)
+ TmpDir = ::getenv("TMP");
+ if (!TmpDir)
+ TmpDir = "/tmp";
+ llvm::sys::Path P(TmpDir);
+ P.appendComponent("cc");
+ if (P.makeUnique(false, &Error)) {
+ Diag(clang::diag::err_drv_unable_to_make_temp) << Error;
+ return "";
+ }
+
+ // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837.
+ P.eraseFromDisk(false, 0);
+
+ P.appendSuffix(Suffix);
+ return P.str();
+}
+
+const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
+ llvm::PrettyStackTraceString CrashInfo("Constructing host");
+ llvm::Triple Triple(TripleStr);
+
+ // TCE is an osless target
+ if (Triple.getArchName() == "tce")
+ return createTCEHostInfo(*this, Triple);
+
+ switch (Triple.getOS()) {
+ case llvm::Triple::AuroraUX:
+ return createAuroraUXHostInfo(*this, Triple);
+ case llvm::Triple::Darwin:
+ return createDarwinHostInfo(*this, Triple);
+ case llvm::Triple::DragonFly:
+ return createDragonFlyHostInfo(*this, Triple);
+ case llvm::Triple::OpenBSD:
+ return createOpenBSDHostInfo(*this, Triple);
+ case llvm::Triple::NetBSD:
+ return createNetBSDHostInfo(*this, Triple);
+ case llvm::Triple::FreeBSD:
+ return createFreeBSDHostInfo(*this, Triple);
+ case llvm::Triple::Minix:
+ return createMinixHostInfo(*this, Triple);
+ case llvm::Triple::Linux:
+ return createLinuxHostInfo(*this, Triple);
+ case llvm::Triple::Win32:
+ return createWindowsHostInfo(*this, Triple);
+ case llvm::Triple::MinGW32:
+ return createMinGWHostInfo(*this, Triple);
+ default:
+ return createUnknownHostInfo(*this, Triple);
+ }
+}
+
+bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
+ const llvm::Triple &Triple) const {
+ // Check if user requested no clang, or clang doesn't understand this type (we
+ // only handle single inputs for now).
+ if (!CCCUseClang || JA.size() != 1 ||
+ !types::isAcceptedByClang((*JA.begin())->getType()))
+ return false;
+
+ // Otherwise make sure this is an action clang understands.
+ if (isa<PreprocessJobAction>(JA)) {
+ if (!CCCUseClangCPP) {
+ Diag(clang::diag::warn_drv_not_using_clang_cpp);
+ return false;
+ }
+ } else if (!isa<PrecompileJobAction>(JA) && !isa<CompileJobAction>(JA))
+ return false;
+
+ // Use clang for C++?
+ if (!CCCUseClangCXX && types::isCXX((*JA.begin())->getType())) {
+ Diag(clang::diag::warn_drv_not_using_clang_cxx);
+ return false;
+ }
+
+ // Always use clang for precompiling, AST generation, and rewriting,
+ // regardless of archs.
+ if (isa<PrecompileJobAction>(JA) ||
+ types::isOnlyAcceptedByClang(JA.getType()))
+ return true;
+
+ // Finally, don't use clang if this isn't one of the user specified archs to
+ // build.
+ if (!CCCClangArchs.empty() && !CCCClangArchs.count(Triple.getArch())) {
+ Diag(clang::diag::warn_drv_not_using_clang_arch) << Triple.getArchName();
+ return false;
+ }
+
+ return true;
+}
+
+/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
+/// grouped values as integers. Numbers which are not provided are set to 0.
+///
+/// \return True if the entire string was parsed (9.2), or all groups were
+/// parsed (10.3.5extrastuff).
+bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
+ unsigned &Minor, unsigned &Micro,
+ bool &HadExtra) {
+ HadExtra = false;
+
+ Major = Minor = Micro = 0;
+ if (*Str == '\0')
+ return true;
+
+ char *End;
+ Major = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (*End != '.')
+ return false;
+
+ Str = End+1;
+ Minor = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (*End != '.')
+ return false;
+
+ Str = End+1;
+ Micro = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (Str == End)
+ return false;
+ HadExtra = true;
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
new file mode 100644
index 0000000..f2d9af8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
@@ -0,0 +1,37 @@
+//===--- DriverOptions.cpp - Driver Options Table -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+static const OptTable::Info InfoTable[] = {
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/Options.inc"
+};
+
+namespace {
+
+class DriverOptTable : public OptTable {
+public:
+ DriverOptTable()
+ : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createDriverOptTable() {
+ return new DriverOptTable();
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp
new file mode 100644
index 0000000..cd413180
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp
@@ -0,0 +1,731 @@
+//===--- HostInfo.cpp - Host specific information -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/HostInfo.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ToolChains.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+
+HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple)
+ : TheDriver(D), Triple(_Triple) {
+}
+
+HostInfo::~HostInfo() {
+}
+
+namespace {
+
+// Darwin Host Info
+
+/// DarwinHostInfo - Darwin host information implementation.
+class DarwinHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains;
+
+public:
+ DarwinHostInfo(const Driver &D, const llvm::Triple &Triple);
+ ~DarwinHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+}
+
+DarwinHostInfo::~DarwinHostInfo() {
+ for (llvm::DenseMap<unsigned, ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool DarwinHostInfo::useDriverDriver() const {
+ return true;
+}
+
+ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ llvm::Triple::ArchType Arch;
+
+ if (!ArchName) {
+ // If we aren't looking for a specific arch, infer the default architecture
+ // based on -arch and -m32/-m64 command line options.
+ if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+ // The gcc driver behavior with multiple -arch flags wasn't consistent for
+ // things which rely on a default architecture. We just use the last -arch
+ // to find the default tool chain (assuming it is valid).
+ Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+
+ // If it was invalid just use the host, we will reject this command line
+ // later.
+ if (Arch == llvm::Triple::UnknownArch)
+ Arch = getTriple().getArch();
+ } else {
+ // Otherwise default to the arch of the host.
+ Arch = getTriple().getArch();
+ }
+
+ // Honor -m32 and -m64 when finding the default tool chain.
+ //
+ // FIXME: Should this information be in llvm::Triple?
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (A->getOption().matches(options::OPT_m32)) {
+ if (Arch == llvm::Triple::x86_64)
+ Arch = llvm::Triple::x86;
+ if (Arch == llvm::Triple::ppc64)
+ Arch = llvm::Triple::ppc;
+ } else {
+ if (Arch == llvm::Triple::x86)
+ Arch = llvm::Triple::x86_64;
+ if (Arch == llvm::Triple::ppc)
+ Arch = llvm::Triple::ppc64;
+ }
+ }
+ } else
+ Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName);
+
+ assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!");
+ ToolChain *&TC = ToolChains[Arch];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArch(Arch);
+
+ // If we recognized the arch, match it to the toolchains we support.
+ const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN");
+ if (UseNewToolChain ||
+ Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 ||
+ Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
+ TC = new toolchains::DarwinClang(*this, TCTriple);
+ } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ // We still use the legacy DarwinGCC toolchain on X86.
+ TC = new toolchains::DarwinGCC(*this, TCTriple);
+ } else
+ TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// TCE Host Info
+
+/// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi)
+class TCEHostInfo : public HostInfo {
+
+public:
+ TCEHostInfo(const Driver &D, const llvm::Triple &Triple);
+ ~TCEHostInfo() {}
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+}
+
+bool TCEHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ llvm::Triple TCTriple(getTriple());
+// TCTriple.setArchName(ArchName);
+ return new toolchains::TCEToolChain(*this, TCTriple);
+}
+
+
+// Unknown Host Info
+
+/// UnknownHostInfo - Generic host information to use for unknown hosts.
+class UnknownHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ UnknownHostInfo(const Driver &D, const llvm::Triple& Triple);
+ ~UnknownHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+}
+
+UnknownHostInfo::~UnknownHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool UnknownHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ } else if (Triple.getArch() == llvm::Triple::ppc ||
+ Triple.getArch() == llvm::Triple::ppc64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::Generic_GCC(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// OpenBSD Host Info
+
+/// OpenBSDHostInfo - OpenBSD host information implementation.
+class OpenBSDHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~OpenBSDHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+OpenBSDHostInfo::~OpenBSDHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool OpenBSDHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::OpenBSD(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// AuroraUX Host Info
+
+/// AuroraUXHostInfo - AuroraUX host information implementation.
+class AuroraUXHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~AuroraUXHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+AuroraUXHostInfo::~AuroraUXHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool AuroraUXHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ ToolChain *&TC = ToolChains[getArchName()];
+
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(getArchName());
+
+ TC = new toolchains::AuroraUX(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// FreeBSD Host Info
+
+/// FreeBSDHostInfo - FreeBSD host information implementation.
+class FreeBSDHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~FreeBSDHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+FreeBSDHostInfo::~FreeBSDHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool FreeBSDHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ } else if (Triple.getArch() == llvm::Triple::ppc ||
+ Triple.getArch() == llvm::Triple::ppc64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::FreeBSD(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// NetBSD Host Info
+
+/// NetBSDHostInfo - NetBSD host information implementation.
+class NetBSDHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ NetBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~NetBSDHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+NetBSDHostInfo::~NetBSDHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool NetBSDHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *NetBSDHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ } else if (Triple.getArch() == llvm::Triple::ppc ||
+ Triple.getArch() == llvm::Triple::ppc64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::NetBSD(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// Minix Host Info
+
+/// MinixHostInfo - Minix host information implementation.
+class MinixHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ MinixHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~MinixHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+MinixHostInfo::~MinixHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it){
+ delete it->second;
+ }
+}
+
+bool MinixHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *MinixHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::Minix(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// DragonFly Host Info
+
+/// DragonFlyHostInfo - DragonFly host information implementation.
+class DragonFlyHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~DragonFlyHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+DragonFlyHostInfo::~DragonFlyHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool DragonFlyHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ ToolChain *&TC = ToolChains[getArchName()];
+
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(getArchName());
+
+ TC = new toolchains::DragonFly(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// Linux Host Info
+
+/// LinuxHostInfo - Linux host information implementation.
+class LinuxHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ LinuxHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~LinuxHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+LinuxHostInfo::~LinuxHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool LinuxHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ } else if (Triple.getArch() == llvm::Triple::ppc ||
+ Triple.getArch() == llvm::Triple::ppc64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::Linux(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// Windows Host Info
+
+/// WindowsHostInfo - Host information to use on Microsoft Windows.
+class WindowsHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ WindowsHostInfo(const Driver &D, const llvm::Triple& Triple);
+ ~WindowsHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual types::ID lookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+ }
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+WindowsHostInfo::WindowsHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+}
+
+WindowsHostInfo::~WindowsHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool WindowsHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *WindowsHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::Windows(*this, TCTriple);
+ }
+
+ return TC;
+}
+
+// FIXME: This is a placeholder.
+class MinGWHostInfo : public UnknownHostInfo {
+public:
+ MinGWHostInfo(const Driver &D, const llvm::Triple& Triple);
+};
+
+MinGWHostInfo::MinGWHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : UnknownHostInfo(D, Triple) {}
+
+} // end anon namespace
+
+const HostInfo *
+clang::driver::createAuroraUXHostInfo(const Driver &D,
+ const llvm::Triple& Triple){
+ return new AuroraUXHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createDarwinHostInfo(const Driver &D,
+ const llvm::Triple& Triple){
+ return new DarwinHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createOpenBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new OpenBSDHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createFreeBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new FreeBSDHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createNetBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new NetBSDHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createMinixHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new MinixHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createDragonFlyHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new DragonFlyHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createLinuxHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new LinuxHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createTCEHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new TCEHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createWindowsHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new WindowsHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createMinGWHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new MinGWHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createUnknownHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new UnknownHostInfo(D, Triple);
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
new file mode 100644
index 0000000..2a2f4b9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
@@ -0,0 +1,88 @@
+//===--- InputInfo.h - Input Source & Type Information ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_INPUTINFO_H_
+#define CLANG_LIB_DRIVER_INPUTINFO_H_
+
+#include "clang/Driver/Types.h"
+
+#include <cassert>
+#include <string>
+
+namespace clang {
+namespace driver {
+
+/// InputInfo - Wrapper for information about an input source.
+class InputInfo {
+ // FIXME: The distinction between filenames and inputarg here is
+ // gross; we should probably drop the idea of a "linker
+ // input". Doing so means tweaking pipelining to still create link
+ // steps when it sees linker inputs (but not treat them as
+ // arguments), and making sure that arguments get rendered
+ // correctly.
+ enum Class {
+ Nothing,
+ Filename,
+ InputArg,
+ Pipe
+ };
+
+ union {
+ const char *Filename;
+ const Arg *InputArg;
+ } Data;
+ Class Kind;
+ types::ID Type;
+ const char *BaseInput;
+
+public:
+ InputInfo() {}
+ InputInfo(types::ID _Type, const char *_BaseInput)
+ : Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
+ }
+ InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput)
+ : Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
+ Data.Filename = _Filename;
+ }
+ InputInfo(const Arg *_InputArg, types::ID _Type, const char *_BaseInput)
+ : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
+ Data.InputArg = _InputArg;
+ }
+
+ bool isNothing() const { return Kind == Nothing; }
+ bool isFilename() const { return Kind == Filename; }
+ bool isInputArg() const { return Kind == InputArg; }
+ types::ID getType() const { return Type; }
+ const char *getBaseInput() const { return BaseInput; }
+
+ const char *getFilename() const {
+ assert(isFilename() && "Invalid accessor.");
+ return Data.Filename;
+ }
+ const Arg &getInputArg() const {
+ assert(isInputArg() && "Invalid accessor.");
+ return *Data.InputArg;
+ }
+
+ /// getAsString - Return a string name for this input, for
+ /// debugging.
+ std::string getAsString() const {
+ if (isFilename())
+ return std::string("\"") + getFilename() + '"';
+ else if (isInputArg())
+ return "(input arg)";
+ else
+ return "(nothing)";
+ }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
new file mode 100644
index 0000000..51055e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -0,0 +1,34 @@
+//===--- Job.cpp - Command to Execute -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Job.h"
+
+#include <cassert>
+using namespace clang::driver;
+
+Job::~Job() {}
+
+Command::Command(const Action &_Source, const Tool &_Creator,
+ const char *_Executable, const ArgStringList &_Arguments)
+ : Job(CommandClass), Source(_Source), Creator(_Creator),
+ Executable(_Executable), Arguments(_Arguments)
+{
+}
+
+JobList::JobList() : Job(JobListClass) {}
+
+JobList::~JobList() {
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ delete *it;
+}
+
+void Job::addCommand(Command *C) {
+ cast<JobList>(this)->addJob(C);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
new file mode 100644
index 0000000..c3d3048
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
@@ -0,0 +1,383 @@
+//===--- OptTable.cpp - Option Table Implementation -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <map>
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+// Ordering on Info. The ordering is *almost* lexicographic, with two
+// exceptions. First, '\0' comes at the end of the alphabet instead of
+// the beginning (thus options preceed any other options which prefix
+// them). Second, for options with the same name, the less permissive
+// version should come first; a Flag option should preceed a Joined
+// option, for example.
+
+static int StrCmpOptionName(const char *A, const char *B) {
+ char a = *A, b = *B;
+ while (a == b) {
+ if (a == '\0')
+ return 0;
+
+ a = *++A;
+ b = *++B;
+ }
+
+ if (a == '\0') // A is a prefix of B.
+ return 1;
+ if (b == '\0') // B is a prefix of A.
+ return -1;
+
+ // Otherwise lexicographic.
+ return (a < b) ? -1 : 1;
+}
+
+namespace clang {
+namespace driver {
+static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
+ if (&A == &B)
+ return false;
+
+ if (int N = StrCmpOptionName(A.Name, B.Name))
+ return N == -1;
+
+ // Names are the same, check that classes are in order; exactly one
+ // should be joined, and it should succeed the other.
+ assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
+ "Unexpected classes for options with same name.");
+ return B.Kind == Option::JoinedClass;
+}
+
+// Support lower_bound between info and an option name.
+static inline bool operator<(const OptTable::Info &I, const char *Name) {
+ return StrCmpOptionName(I.Name, Name) == -1;
+}
+static inline bool operator<(const char *Name, const OptTable::Info &I) {
+ return StrCmpOptionName(Name, I.Name) == -1;
+}
+}
+}
+
+//
+
+OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
+
+//
+
+OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
+ : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
+ Options(new Option*[NumOptionInfos]),
+ TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+{
+ // Explicitly zero initialize the error to work around a bug in array
+ // value-initialization on MinGW with gcc 4.3.5.
+ memset(Options, 0, sizeof(*Options) * NumOptionInfos);
+
+ // Find start of normal options.
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+ unsigned Kind = getInfo(i + 1).Kind;
+ if (Kind == Option::InputClass) {
+ assert(!TheInputOption && "Cannot have multiple input options!");
+ TheInputOption = getOption(i + 1);
+ } else if (Kind == Option::UnknownClass) {
+ assert(!TheUnknownOption && "Cannot have multiple input options!");
+ TheUnknownOption = getOption(i + 1);
+ } else if (Kind != Option::GroupClass) {
+ FirstSearchableIndex = i;
+ break;
+ }
+ }
+ assert(FirstSearchableIndex != 0 && "No searchable options?");
+
+#ifndef NDEBUG
+ // Check that everything after the first searchable option is a
+ // regular option class.
+ for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
+ Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
+ assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
+ Kind != Option::GroupClass) &&
+ "Special options should be defined first!");
+ }
+
+ // Check that options are in order.
+ for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+ if (!(getInfo(i) < getInfo(i + 1))) {
+ getOption(i)->dump();
+ getOption(i + 1)->dump();
+ assert(0 && "Options are not in order!");
+ }
+ }
+#endif
+}
+
+OptTable::~OptTable() {
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
+ delete Options[i];
+ delete[] Options;
+}
+
+Option *OptTable::CreateOption(unsigned id) const {
+ const Info &info = getInfo(id);
+ const OptionGroup *Group =
+ cast_or_null<OptionGroup>(getOption(info.GroupID));
+ const Option *Alias = getOption(info.AliasID);
+
+ Option *Opt = 0;
+ switch (info.Kind) {
+ case Option::InputClass:
+ Opt = new InputOption(id); break;
+ case Option::UnknownClass:
+ Opt = new UnknownOption(id); break;
+ case Option::GroupClass:
+ Opt = new OptionGroup(id, info.Name, Group); break;
+ case Option::FlagClass:
+ Opt = new FlagOption(id, info.Name, Group, Alias); break;
+ case Option::JoinedClass:
+ Opt = new JoinedOption(id, info.Name, Group, Alias); break;
+ case Option::SeparateClass:
+ Opt = new SeparateOption(id, info.Name, Group, Alias); break;
+ case Option::CommaJoinedClass:
+ Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
+ case Option::MultiArgClass:
+ Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
+ case Option::JoinedOrSeparateClass:
+ Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
+ case Option::JoinedAndSeparateClass:
+ Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
+ }
+
+ if (info.Flags & DriverOption)
+ Opt->setDriverOption(true);
+ if (info.Flags & LinkerInput)
+ Opt->setLinkerInput(true);
+ if (info.Flags & NoArgumentUnused)
+ Opt->setNoArgumentUnused(true);
+ if (info.Flags & NoForward)
+ Opt->setNoForward(true);
+ if (info.Flags & RenderAsInput)
+ Opt->setNoOptAsInput(true);
+ if (info.Flags & RenderJoined) {
+ assert((info.Kind == Option::JoinedOrSeparateClass ||
+ info.Kind == Option::SeparateClass) && "Invalid option.");
+ Opt->setRenderStyle(Option::RenderJoinedStyle);
+ }
+ if (info.Flags & RenderSeparate) {
+ assert((info.Kind == Option::JoinedOrSeparateClass ||
+ info.Kind == Option::JoinedClass) && "Invalid option.");
+ Opt->setRenderStyle(Option::RenderSeparateStyle);
+ }
+ if (info.Flags & Unsupported)
+ Opt->setUnsupported(true);
+
+ return Opt;
+}
+
+Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
+ unsigned Prev = Index;
+ const char *Str = Args.getArgString(Index);
+
+ // Anything that doesn't start with '-' is an input, as is '-' itself.
+ if (Str[0] != '-' || Str[1] == '\0')
+ return new Arg(TheInputOption, Index++, Str);
+
+ const Info *Start = OptionInfos + FirstSearchableIndex;
+ const Info *End = OptionInfos + getNumOptions();
+
+ // Search for the first next option which could be a prefix.
+ Start = std::lower_bound(Start, End, Str);
+
+ // Options are stored in sorted order, with '\0' at the end of the
+ // alphabet. Since the only options which can accept a string must
+ // prefix it, we iteratively search for the next option which could
+ // be a prefix.
+ //
+ // FIXME: This is searching much more than necessary, but I am
+ // blanking on the simplest way to make it fast. We can solve this
+ // problem when we move to TableGen.
+ for (; Start != End; ++Start) {
+ // Scan for first option which is a proper prefix.
+ for (; Start != End; ++Start)
+ if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0)
+ break;
+ if (Start == End)
+ break;
+
+ // See if this option matches.
+ if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
+ return A;
+
+ // Otherwise, see if this argument was missing values.
+ if (Prev != Index)
+ return 0;
+ }
+
+ return new Arg(TheUnknownOption, Index++, Str);
+}
+
+InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
+ const char* const *ArgEnd,
+ unsigned &MissingArgIndex,
+ unsigned &MissingArgCount) const {
+ InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
+
+ // FIXME: Handle '@' args (or at least error on them).
+
+ MissingArgIndex = MissingArgCount = 0;
+ unsigned Index = 0, End = ArgEnd - ArgBegin;
+ while (Index < End) {
+ // Ignore empty arguments (other things may still take them as arguments).
+ if (Args->getArgString(Index)[0] == '\0') {
+ ++Index;
+ continue;
+ }
+
+ unsigned Prev = Index;
+ Arg *A = ParseOneArg(*Args, Index);
+ assert(Index > Prev && "Parser failed to consume argument.");
+
+ // Check for missing argument error.
+ if (!A) {
+ assert(Index >= End && "Unexpected parser error.");
+ assert(Index - Prev - 1 && "No missing arguments!");
+ MissingArgIndex = Prev;
+ MissingArgCount = Index - Prev - 1;
+ break;
+ }
+
+ Args->append(A);
+ }
+
+ return Args;
+}
+
+static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
+ std::string Name = Opts.getOptionName(Id);
+
+ // Add metavar, if used.
+ switch (Opts.getOptionKind(Id)) {
+ case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
+ assert(0 && "Invalid option with help text.");
+
+ case Option::MultiArgClass:
+ assert(0 && "Cannot print metavar for this kind of option.");
+
+ case Option::FlagClass:
+ break;
+
+ case Option::SeparateClass: case Option::JoinedOrSeparateClass:
+ Name += ' ';
+ // FALLTHROUGH
+ case Option::JoinedClass: case Option::CommaJoinedClass:
+ case Option::JoinedAndSeparateClass:
+ if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
+ Name += MetaVarName;
+ else
+ Name += "<value>";
+ break;
+ }
+
+ return Name;
+}
+
+static void PrintHelpOptionList(llvm::raw_ostream &OS, llvm::StringRef Title,
+ std::vector<std::pair<std::string,
+ const char*> > &OptionHelp) {
+ OS << Title << ":\n";
+
+ // Find the maximum option length.
+ unsigned OptionFieldWidth = 0;
+ for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+ // Skip titles.
+ if (!OptionHelp[i].second)
+ continue;
+
+ // Limit the amount of padding we are willing to give up for alignment.
+ unsigned Length = OptionHelp[i].first.size();
+ if (Length <= 23)
+ OptionFieldWidth = std::max(OptionFieldWidth, Length);
+ }
+
+ const unsigned InitialPad = 2;
+ for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+ const std::string &Option = OptionHelp[i].first;
+ int Pad = OptionFieldWidth - int(Option.size());
+ OS.indent(InitialPad) << Option;
+
+ // Break on long option names.
+ if (Pad < 0) {
+ OS << "\n";
+ Pad = OptionFieldWidth + InitialPad;
+ }
+ OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
+ }
+}
+
+static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
+ unsigned GroupID = Opts.getOptionGroupID(Id);
+
+ // If not in a group, return the default help group.
+ if (!GroupID)
+ return "OPTIONS";
+
+ // Abuse the help text of the option groups to store the "help group"
+ // name.
+ //
+ // FIXME: Split out option groups.
+ if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
+ return GroupHelp;
+
+ // Otherwise keep looking.
+ return getOptionHelpGroup(Opts, GroupID);
+}
+
+void OptTable::PrintHelp(llvm::raw_ostream &OS, const char *Name,
+ const char *Title, bool ShowHidden) const {
+ OS << "OVERVIEW: " << Title << "\n";
+ OS << '\n';
+ OS << "USAGE: " << Name << " [options] <inputs>\n";
+ OS << '\n';
+
+ // Render help text into a map of group-name to a list of (option, help)
+ // pairs.
+ typedef std::map<std::string,
+ std::vector<std::pair<std::string, const char*> > > helpmap_ty;
+ helpmap_ty GroupedOptionHelp;
+
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+ unsigned Id = i + 1;
+
+ // FIXME: Split out option groups.
+ if (getOptionKind(Id) == Option::GroupClass)
+ continue;
+
+ if (!ShowHidden && isOptionHelpHidden(Id))
+ continue;
+
+ if (const char *Text = getOptionHelpText(Id)) {
+ const char *HelpGroup = getOptionHelpGroup(*this, Id);
+ const std::string &OptName = getOptionHelpName(*this, Id);
+ GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
+ }
+ }
+
+ for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
+ ie = GroupedOptionHelp.end(); it != ie; ++it) {
+ if (it != GroupedOptionHelp .begin())
+ OS << "\n";
+ PrintHelpOptionList(OS, it->first, it->second);
+ }
+
+ OS.flush();
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp
new file mode 100644
index 0000000..a992cef
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Option.cpp
@@ -0,0 +1,284 @@
+//===--- Option.cpp - Abstract Driver Options -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Option.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <algorithm>
+using namespace clang::driver;
+
+Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
+ const OptionGroup *_Group, const Option *_Alias)
+ : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
+ Unsupported(false), LinkerInput(false), NoOptAsInput(false),
+ DriverOption(false), NoArgumentUnused(false), NoForward(false) {
+
+ // Multi-level aliases are not supported, and alias options cannot
+ // have groups. This just simplifies option tracking, it is not an
+ // inherent limitation.
+ assert((!Alias || (!Alias->Alias && !Group)) &&
+ "Multi-level aliases and aliases with groups are unsupported.");
+
+ // Initialize rendering options based on the class.
+ switch (Kind) {
+ case GroupClass:
+ case InputClass:
+ case UnknownClass:
+ RenderStyle = RenderValuesStyle;
+ break;
+
+ case JoinedClass:
+ case JoinedAndSeparateClass:
+ RenderStyle = RenderJoinedStyle;
+ break;
+
+ case CommaJoinedClass:
+ RenderStyle = RenderCommaJoinedStyle;
+ break;
+
+ case FlagClass:
+ case SeparateClass:
+ case MultiArgClass:
+ case JoinedOrSeparateClass:
+ RenderStyle = RenderSeparateStyle;
+ break;
+ }
+}
+
+Option::~Option() {
+}
+
+void Option::dump() const {
+ llvm::errs() << "<";
+ switch (Kind) {
+ default:
+ assert(0 && "Invalid kind");
+#define P(N) case N: llvm::errs() << #N; break
+ P(GroupClass);
+ P(InputClass);
+ P(UnknownClass);
+ P(FlagClass);
+ P(JoinedClass);
+ P(SeparateClass);
+ P(CommaJoinedClass);
+ P(MultiArgClass);
+ P(JoinedOrSeparateClass);
+ P(JoinedAndSeparateClass);
+#undef P
+ }
+
+ llvm::errs() << " Name:\"" << Name << '"';
+
+ if (Group) {
+ llvm::errs() << " Group:";
+ Group->dump();
+ }
+
+ if (Alias) {
+ llvm::errs() << " Alias:";
+ Alias->dump();
+ }
+
+ if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
+ llvm::errs() << " NumArgs:" << MOA->getNumArgs();
+
+ llvm::errs() << ">\n";
+}
+
+bool Option::matches(OptSpecifier Opt) const {
+ // Aliases are never considered in matching, look through them.
+ if (Alias)
+ return Alias->matches(Opt);
+
+ // Check exact match.
+ if (ID == Opt)
+ return true;
+
+ if (Group)
+ return Group->matches(Opt);
+ return false;
+}
+
+OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group)
+ : Option(Option::GroupClass, ID, Name, Group, 0) {
+}
+
+Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
+ assert(0 && "accept() should never be called on an OptionGroup");
+ return 0;
+}
+
+InputOption::InputOption(OptSpecifier ID)
+ : Option(Option::InputClass, ID, "<input>", 0, 0) {
+}
+
+Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
+ assert(0 && "accept() should never be called on an InputOption");
+ return 0;
+}
+
+UnknownOption::UnknownOption(OptSpecifier ID)
+ : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
+}
+
+Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
+ assert(0 && "accept() should never be called on an UnknownOption");
+ return 0;
+}
+
+FlagOption::FlagOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias)
+ : Option(Option::FlagClass, ID, Name, Group, Alias) {
+}
+
+Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
+ // Matches iff this is an exact match.
+ // FIXME: Avoid strlen.
+ if (strlen(getName()) != strlen(Args.getArgString(Index)))
+ return 0;
+
+ return new Arg(getUnaliasedOption(), Index++);
+}
+
+JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias)
+ : Option(Option::JoinedClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
+ // Always matches.
+ const char *Value = Args.getArgString(Index) + strlen(getName());
+ return new Arg(getUnaliasedOption(), Index++, Value);
+}
+
+CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
+}
+
+Arg *CommaJoinedOption::accept(const ArgList &Args,
+ unsigned &Index) const {
+ // Always matches.
+ const char *Str = Args.getArgString(Index) + strlen(getName());
+ Arg *A = new Arg(getUnaliasedOption(), Index++);
+
+ // Parse out the comma separated values.
+ const char *Prev = Str;
+ for (;; ++Str) {
+ char c = *Str;
+
+ if (!c || c == ',') {
+ if (Prev != Str) {
+ char *Value = new char[Str - Prev + 1];
+ memcpy(Value, Prev, Str - Prev);
+ Value[Str - Prev] = '\0';
+ A->getValues().push_back(Value);
+ }
+
+ if (!c)
+ break;
+
+ Prev = Str + 1;
+ }
+ }
+ A->setOwnsValues(true);
+
+ return A;
+}
+
+SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias)
+ : Option(Option::SeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
+ // Matches iff this is an exact match.
+ // FIXME: Avoid strlen.
+ if (strlen(getName()) != strlen(Args.getArgString(Index)))
+ return 0;
+
+ Index += 2;
+ if (Index > Args.getNumInputArgStrings())
+ return 0;
+
+ return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
+}
+
+MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias,
+ unsigned _NumArgs)
+ : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
+ assert(NumArgs > 1 && "Invalid MultiArgOption!");
+}
+
+Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
+ // Matches iff this is an exact match.
+ // FIXME: Avoid strlen.
+ if (strlen(getName()) != strlen(Args.getArgString(Index)))
+ return 0;
+
+ Index += 1 + NumArgs;
+ if (Index > Args.getNumInputArgStrings())
+ return 0;
+
+ Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
+ Args.getArgString(Index - NumArgs));
+ for (unsigned i = 1; i != NumArgs; ++i)
+ A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
+ return A;
+}
+
+JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
+ const char *Name,
+ const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
+ unsigned &Index) const {
+ // If this is not an exact match, it is a joined arg.
+ // FIXME: Avoid strlen.
+ if (strlen(getName()) != strlen(Args.getArgString(Index))) {
+ const char *Value = Args.getArgString(Index) + strlen(getName());
+ return new Arg(this, Index++, Value);
+ }
+
+ // Otherwise it must be separate.
+ Index += 2;
+ if (Index > Args.getNumInputArgStrings())
+ return 0;
+
+ return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
+}
+
+JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
+ const char *Name,
+ const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
+ unsigned &Index) const {
+ // Always matches.
+
+ Index += 2;
+ if (Index > Args.getNumInputArgStrings())
+ return 0;
+
+ return new Arg(getUnaliasedOption(), Index - 2,
+ Args.getArgString(Index-2)+strlen(getName()),
+ Args.getArgString(Index-1));
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp
new file mode 100644
index 0000000..f360002
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp
@@ -0,0 +1,27 @@
+//===--- Phases.cpp - Transformations on Driver Types ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Phases.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+
+const char *phases::getPhaseName(ID Id) {
+ switch (Id) {
+ case Preprocess: return "preprocessor";
+ case Precompile: return "precompiler";
+ case Compile: return "compiler";
+ case Assemble: return "assembler";
+ case Link: return "linker";
+ }
+
+ assert(0 && "Invalid phase id.");
+ return 0;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tool.cpp b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp
new file mode 100644
index 0000000..b93864f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp
@@ -0,0 +1,21 @@
+//===--- Tool.cpp - Compilation Tools -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Tool.h"
+
+using namespace clang::driver;
+
+Tool::Tool(const char *_Name, const char *_ShortName,
+ const ToolChain &TC) : Name(_Name), ShortName(_ShortName),
+ TheToolChain(TC)
+{
+}
+
+Tool::~Tool() {
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
new file mode 100644
index 0000000..e4051a1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -0,0 +1,229 @@
+//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/ToolChain.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Options.h"
+
+using namespace clang::driver;
+
+ToolChain::ToolChain(const HostInfo &_Host, const llvm::Triple &_Triple)
+ : Host(_Host), Triple(_Triple) {
+}
+
+ToolChain::~ToolChain() {
+}
+
+const Driver &ToolChain::getDriver() const {
+ return Host.getDriver();
+}
+
+std::string ToolChain::GetFilePath(const char *Name) const {
+ return Host.getDriver().GetFilePath(Name, *this);
+
+}
+
+std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const {
+ return Host.getDriver().GetProgramPath(Name, *this, WantFile);
+}
+
+types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+}
+
+bool ToolChain::HasNativeLLVMSupport() const {
+ return false;
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue(Args);
+
+ llvm::StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue(Args);
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ if (MArch == "armv2" || MArch == "armv2a")
+ return "arm2";
+ if (MArch == "armv3")
+ return "arm6";
+ if (MArch == "armv3m")
+ return "arm7m";
+ if (MArch == "armv4" || MArch == "armv4t")
+ return "arm7tdmi";
+ if (MArch == "armv5" || MArch == "armv5t")
+ return "arm10tdmi";
+ if (MArch == "armv5e" || MArch == "armv5te")
+ return "arm1026ejs";
+ if (MArch == "armv5tej")
+ return "arm926ej-s";
+ if (MArch == "armv6" || MArch == "armv6k")
+ return "arm1136jf-s";
+ if (MArch == "armv6j")
+ return "arm1136j-s";
+ if (MArch == "armv6z" || MArch == "armv6zk")
+ return "arm1176jzf-s";
+ if (MArch == "armv6t2")
+ return "arm1156t2-s";
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ return "cortex-a8";
+ if (MArch == "armv7r" || MArch == "armv7-r")
+ return "cortex-r4";
+ if (MArch == "armv7m" || MArch == "armv7-m")
+ return "cortex-m3";
+ if (MArch == "ep9312")
+ return "ep9312";
+ if (MArch == "iwmmxt")
+ return "iwmmxt";
+ if (MArch == "xscale")
+ return "xscale";
+
+ // If all else failed, return the most base CPU LLVM supports.
+ return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+ if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+ CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+ CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+ CPU == "arm940t" || CPU == "ep9312")
+ return "v4t";
+
+ if (CPU == "arm10tdmi" || CPU == "arm1020t")
+ return "v5";
+
+ if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+ CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+ CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+ CPU == "iwmmxt")
+ return "v5e";
+
+ if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+ CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+ return "v6";
+
+ if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+ return "v6t2";
+
+ if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ return "v7";
+
+ return "";
+}
+
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getTripleString();
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ // FIXME: Factor into subclasses.
+ llvm::Triple Triple = getTriple();
+
+ // Thumb2 is the default for V7 on Darwin.
+ //
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ llvm::StringRef Suffix =
+ getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ bool ThumbDefault =
+ (Suffix == "v7" && getTriple().getOS() == llvm::Triple::Darwin);
+ std::string ArchName = "arm";
+ if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+ ArchName = "thumb";
+ Triple.setArchName(ArchName + Suffix.str());
+
+ return Triple.getTriple();
+ }
+ }
+}
+
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+ // non-Darwin.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+ options::OPT_miphoneos_version_min_EQ))
+ getDriver().Diag(clang::diag::err_drv_clang_unsupported)
+ << A->getAsString(Args);
+
+ return ComputeLLVMTriple(Args);
+}
+
+ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ llvm::StringRef Value = A->getValue(Args);
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libstdcxx;
+}
+
+void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-cxx-system-include");
+ CmdArgs.push_back("/usr/include/c++/v1");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ // Currently handled by the mass of goop in InitHeaderSearch.
+ break;
+ }
+}
+
+void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+}
+
+void ToolChain::AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-lcc_kext");
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
new file mode 100644
index 0000000..8028fe0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -0,0 +1,1643 @@
+//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ToolChains.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+#include "clang/Basic/Version.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/system_error.h"
+
+#include <cstdlib> // ::getenv
+
+#ifndef CLANG_PREFIX
+#define CLANG_PREFIX
+#endif
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+
+/// Darwin - Darwin tool chain for i386 and x86_64.
+
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple), TargetInitialized(false)
+{
+ // Compute the initial Darwin version based on the host.
+ bool HadExtra;
+ std::string OSName = Triple.getOSName();
+ if (!Driver::GetReleaseVersion(&OSName[6],
+ DarwinVersion[0], DarwinVersion[1],
+ DarwinVersion[2], HadExtra))
+ getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
+
+ llvm::raw_string_ostream(MacosxVersionMin)
+ << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
+ << DarwinVersion[1];
+}
+
+types::ID Darwin::LookupTypeForExtension(const char *Ext) const {
+ types::ID Ty = types::lookupTypeForExtension(Ext);
+
+ // Darwin always preprocesses assembly files (unless -x is used explicitly).
+ if (Ty == types::TY_PP_Asm)
+ return types::TY_Asm;
+
+ return Ty;
+}
+
+bool Darwin::HasNativeLLVMSupport() const {
+ return true;
+}
+
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMArch(llvm::StringRef Value) {
+ if (Value == "armv6k")
+ return "armv6";
+
+ if (Value == "armv5tej")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
+
+ if (Value == "armv4t")
+ return "armv4t";
+
+ if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
+ Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
+ Value == "armv7m")
+ return "armv7";
+
+ return 0;
+}
+
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMCpu(llvm::StringRef Value) {
+ if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
+ Value == "arm946e-s" || Value == "arm966e-s" ||
+ Value == "arm968e-s" || Value == "arm10e" ||
+ Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
+ Value == "arm1026ej-s")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
+
+ if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
+ Value == "arm1176jz-s" || Value == "arm1176jzf-s")
+ return "armv6";
+
+ if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
+ return "armv7";
+
+ return 0;
+}
+
+llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getArchName();
+
+ case llvm::Triple::arm: {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ if (const char *Arch = GetArmArchForMArch(A->getValue(Args)))
+ return Arch;
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ if (const char *Arch = GetArmArchForMCpu(A->getValue(Args)))
+ return Arch;
+
+ return "arm";
+ }
+ }
+}
+
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
+{
+ // We can only work with 4.2.1 currently.
+ GCCVersion[0] = 4;
+ GCCVersion[1] = 2;
+ GCCVersion[2] = 1;
+
+ // Set up the tool chain paths to match gcc.
+ ToolChainDir = "i686-apple-darwin";
+ ToolChainDir += llvm::utostr(DarwinVersion[0]);
+ ToolChainDir += "/";
+ ToolChainDir += llvm::utostr(GCCVersion[0]);
+ ToolChainDir += '.';
+ ToolChainDir += llvm::utostr(GCCVersion[1]);
+ ToolChainDir += '.';
+ ToolChainDir += llvm::utostr(GCCVersion[2]);
+
+ // Try the next major version if that tool chain dir is invalid.
+ std::string Tmp = "/usr/lib/gcc/" + ToolChainDir;
+ bool Exists;
+ if (llvm::sys::fs::exists(Tmp, Exists) || Exists) {
+ std::string Next = "i686-apple-darwin";
+ Next += llvm::utostr(DarwinVersion[0] + 1);
+ Next += "/";
+ Next += llvm::utostr(GCCVersion[0]);
+ Next += '.';
+ Next += llvm::utostr(GCCVersion[1]);
+ Next += '.';
+ Next += llvm::utostr(GCCVersion[2]);
+
+ // Use that if it exists, otherwise hope the user isn't linking.
+ //
+ // FIXME: Drop dependency on gcc's tool chain.
+ Tmp = "/usr/lib/gcc/" + Next;
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
+ ToolChainDir = Next;
+ }
+
+ std::string Path;
+ if (getArchName() == "x86_64") {
+ Path = getDriver().Dir;
+ Path += "/../lib/gcc/";
+ Path += ToolChainDir;
+ Path += "/x86_64";
+ getFilePaths().push_back(Path);
+
+ Path = "/usr/lib/gcc/";
+ Path += ToolChainDir;
+ Path += "/x86_64";
+ getFilePaths().push_back(Path);
+ }
+
+ Path = getDriver().Dir;
+ Path += "/../lib/gcc/";
+ Path += ToolChainDir;
+ getFilePaths().push_back(Path);
+
+ Path = "/usr/lib/gcc/";
+ Path += ToolChainDir;
+ getFilePaths().push_back(Path);
+
+ Path = getDriver().Dir;
+ Path += "/../libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
+
+ Path = "/usr/libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
+
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+Darwin::~Darwin() {
+ // Free tool implementations.
+ for (llvm::DenseMap<unsigned, Tool*>::iterator
+ it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
+ delete it->second;
+}
+
+std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args));
+
+ // If the target isn't initialized (e.g., an unknown Darwin platform, return
+ // the default triple).
+ if (!isTargetInitialized())
+ return Triple.getTriple();
+
+ unsigned Version[3];
+ getTargetVersion(Version);
+
+ // Mangle the target version into the OS triple component. For historical
+ // reasons that make little sense, the version passed here is the "darwin"
+ // version, which drops the 10 and offsets by 4. See inverse code when
+ // setting the OS version preprocessor define.
+ if (!isTargetIPhoneOS()) {
+ Version[0] = Version[1] + 4;
+ Version[1] = Version[2];
+ Version[2] = 0;
+ } else {
+ // Use the environment to communicate that we are targetting iPhoneOS.
+ Triple.setEnvironmentName("iphoneos");
+ }
+
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
+ << "." << Version[1] << "." << Version[2];
+ Triple.setOSName(Str.str());
+
+ return Triple.getTriple();
+}
+
+Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ // FIXME: This doesn't belong here, but ideally we will support static soon
+ // anyway.
+ bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) ||
+ C.getArgs().hasArg(options::OPT_static) ||
+ C.getArgs().hasArg(options::OPT_fapple_kext));
+ bool IsIADefault = IsIntegratedAssemblerDefault() && !HasStatic;
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIADefault);
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::InputClass:
+ case Action::BindArchClass:
+ assert(0 && "Invalid tool kind.");
+ case Action::PreprocessJobClass:
+ T = new tools::darwin::Preprocess(*this); break;
+ case Action::AnalyzeJobClass:
+ T = new tools::Clang(*this); break;
+ case Action::PrecompileJobClass:
+ case Action::CompileJobClass:
+ T = new tools::darwin::Compile(*this); break;
+ case Action::AssembleJobClass: {
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::darwin::Assemble(*this);
+ break;
+ }
+ case Action::LinkJobClass:
+ T = new tools::darwin::Link(*this); break;
+ case Action::LipoJobClass:
+ T = new tools::darwin::Lipo(*this); break;
+ case Action::DsymutilJobClass:
+ T = new tools::darwin::Dsymutil(*this); break;
+ }
+ }
+
+ return *T;
+}
+
+void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string Tmp;
+
+ // FIXME: Derive these correctly.
+ if (getArchName() == "x86_64") {
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/x86_64"));
+ // Intentionally duplicated for (temporary) gcc bug compatibility.
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/x86_64"));
+ }
+
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
+
+ Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir;
+ bool Exists;
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
+ Tmp = getDriver().Dir + "/../lib/gcc";
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+ // Intentionally duplicated for (temporary) gcc bug compatibility.
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+ Tmp = getDriver().Dir + "/../lib/" + ToolChainDir;
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
+ Tmp = getDriver().Dir + "/../lib";
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/../../../" + ToolChainDir));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/../../.."));
+}
+
+void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Note that this routine is only used for targetting OS X.
+
+ // Derived from libgcc and lib specs but refactored.
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_static");
+ } else {
+ if (Args.hasArg(options::OPT_static_libgcc)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
+ // Derived from darwin_iphoneos_libgcc spec.
+ if (isTargetIPhoneOS()) {
+ CmdArgs.push_back("-lgcc_s.1");
+ } else {
+ CmdArgs.push_back("-lgcc_s.10.5");
+ }
+ } else if (Args.hasArg(options::OPT_shared_libgcc) ||
+ Args.hasFlag(options::OPT_fexceptions,
+ options::OPT_fno_exceptions) ||
+ Args.hasArg(options::OPT_fgnu_runtime)) {
+ // FIXME: This is probably broken on 10.3?
+ if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+ } else {
+ if (isMacosxVersionLT(10, 3, 9))
+ ; // Do nothing.
+ else if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+ }
+
+ if (isTargetIPhoneOS() || isMacosxVersionLT(10, 6)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lSystem");
+ } else {
+ CmdArgs.push_back("-lSystem");
+ CmdArgs.push_back("-lgcc");
+ }
+ }
+}
+
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
+{
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ // For fallback, we need to know how to find the GCC cc1 executables, so we
+ // also add the GCC libexec paths. This is legiy code that can be removed once
+ // fallback is no longer useful.
+ std::string ToolChainDir = "i686-apple-darwin";
+ ToolChainDir += llvm::utostr(DarwinVersion[0]);
+ ToolChainDir += "/4.2.1";
+
+ std::string Path = getDriver().Dir;
+ Path += "/../libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
+
+ Path = "/usr/libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
+}
+
+void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // The Clang toolchain uses explicit paths for internal libraries.
+
+ // Unfortunately, we still might depend on a few of the libraries that are
+ // only available in the gcc library directory (in particular
+ // libstdc++.dylib). For now, hardcode the path to the known install location.
+ llvm::sys::Path P(getDriver().Dir);
+ P.eraseComponent(); // .../usr/bin -> ../usr
+ P.appendComponent("lib");
+ P.appendComponent("gcc");
+ switch (getTriple().getArch()) {
+ default:
+ assert(0 && "Invalid Darwin arch!");
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ P.appendComponent("i686-apple-darwin10");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ P.appendComponent("arm-apple-darwin10");
+ break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ P.appendComponent("powerpc-apple-darwin10");
+ break;
+ }
+ P.appendComponent("4.2.1");
+
+ // Determine the arch specific GCC subdirectory.
+ const char *ArchSpecificDir = 0;
+ switch (getTriple().getArch()) {
+ default:
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ std::string Triple = ComputeLLVMTriple(Args);
+ llvm::StringRef TripleStr = Triple;
+ if (TripleStr.startswith("armv5") || TripleStr.startswith("thumbv5"))
+ ArchSpecificDir = "v5";
+ else if (TripleStr.startswith("armv6") || TripleStr.startswith("thumbv6"))
+ ArchSpecificDir = "v6";
+ else if (TripleStr.startswith("armv7") || TripleStr.startswith("thumbv7"))
+ ArchSpecificDir = "v7";
+ break;
+ }
+ case llvm::Triple::ppc64:
+ ArchSpecificDir = "ppc64";
+ break;
+ case llvm::Triple::x86_64:
+ ArchSpecificDir = "x86_64";
+ break;
+ }
+
+ if (ArchSpecificDir) {
+ P.appendComponent(ArchSpecificDir);
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
+ P.eraseComponent();
+ }
+
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
+}
+
+void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Darwin doesn't support real static executables, don't link any runtime
+ // libraries with -static.
+ if (Args.hasArg(options::OPT_static))
+ return;
+
+ // Reject -static-libgcc for now, we can deal with this when and if someone
+ // cares. This is useful in situations where someone wants to statically link
+ // something like libstdc++, and needs its runtime support routines.
+ if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
+ getDriver().Diag(clang::diag::err_drv_unsupported_opt)
+ << A->getAsString(Args);
+ return;
+ }
+
+ // Otherwise link libSystem, then the dynamic runtime library, and finally any
+ // target specific static runtime library.
+ CmdArgs.push_back("-lSystem");
+
+ // Select the dynamic runtime library and the target specific static library.
+ const char *DarwinStaticLib = 0;
+ if (isTargetIPhoneOS()) {
+ CmdArgs.push_back("-lgcc_s.1");
+
+ // We may need some static functions for armv6/thumb which are required to
+ // be in the same linkage unit as their caller.
+ if (getDarwinArchName(Args) == "armv6")
+ DarwinStaticLib = "libclang_rt.armv6.a";
+ } else {
+ // The dynamic runtime library was merged with libSystem for 10.6 and
+ // beyond; only 10.4 and 10.5 need an additional runtime library.
+ if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+
+ // For OS X, we thought we would only need a static runtime library when
+ // targetting 10.4, to provide versions of the static functions which were
+ // omitted from 10.4.dylib.
+ //
+ // Unfortunately, that turned out to not be true, because Darwin system
+ // headers can still use eprintf on i386, and it is not exported from
+ // libSystem. Therefore, we still must provide a runtime library just for
+ // the tiny tiny handful of projects that *might* use that symbol.
+ if (isMacosxVersionLT(10, 5)) {
+ DarwinStaticLib = "libclang_rt.10.4.a";
+ } else {
+ if (getTriple().getArch() == llvm::Triple::x86)
+ DarwinStaticLib = "libclang_rt.eprintf.a";
+ }
+ }
+
+ /// Add the target specific static library, if needed.
+ if (DarwinStaticLib) {
+ llvm::sys::Path P(getDriver().ResourceDir);
+ P.appendComponent("lib");
+ P.appendComponent("darwin");
+ P.appendComponent(DarwinStaticLib);
+
+ // For now, allow missing resource libraries to support developers who may
+ // not have compiler-rt checked out or integrated into their build.
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ }
+}
+
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
+ const OptTable &Opts = getDriver().getOpts();
+
+ Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
+ Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
+ if (OSXVersion && iPhoneVersion) {
+ getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << OSXVersion->getAsString(Args)
+ << iPhoneVersion->getAsString(Args);
+ iPhoneVersion = 0;
+ } else if (!OSXVersion && !iPhoneVersion) {
+ // If neither OS X nor iPhoneOS targets were specified, check for
+ // environment defines.
+ const char *OSXTarget = ::getenv("MACOSX_DEPLOYMENT_TARGET");
+ const char *iPhoneOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET");
+
+ // Ignore empty strings.
+ if (OSXTarget && OSXTarget[0] == '\0')
+ OSXTarget = 0;
+ if (iPhoneOSTarget && iPhoneOSTarget[0] == '\0')
+ iPhoneOSTarget = 0;
+
+ // Diagnose conflicting deployment targets, and choose default platform
+ // based on the tool chain.
+ //
+ // FIXME: Don't hardcode default here.
+ if (OSXTarget && iPhoneOSTarget) {
+ // FIXME: We should see if we can get away with warning or erroring on
+ // this. Perhaps put under -pedantic?
+ if (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb)
+ OSXTarget = 0;
+ else
+ iPhoneOSTarget = 0;
+ }
+
+ if (OSXTarget) {
+ const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
+ Args.append(OSXVersion);
+ } else if (iPhoneOSTarget) {
+ const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+ iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget);
+ Args.append(iPhoneVersion);
+ } else {
+ // Otherwise, assume we are targeting OS X.
+ const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
+ Args.append(OSXVersion);
+ }
+ }
+
+ // Set the tool chain target information.
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (OSXVersion) {
+ assert(!iPhoneVersion && "Unknown target platform!");
+ if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major != 10 || Minor >= 10 || Micro >= 10)
+ getDriver().Diag(clang::diag::err_drv_invalid_version_number)
+ << OSXVersion->getAsString(Args);
+ } else {
+ assert(iPhoneVersion && "Unknown target platform!");
+ if (!Driver::GetReleaseVersion(iPhoneVersion->getValue(Args), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major >= 10 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(clang::diag::err_drv_invalid_version_number)
+ << iPhoneVersion->getAsString(Args);
+ }
+ setTarget(iPhoneVersion, Major, Minor, Micro);
+}
+
+void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx: {
+ // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
+ // it was previously found in the gcc lib dir. However, for all the Darwin
+ // platforms we care about it was -lstdc++.6, so we search for that
+ // explicitly if we can't see an obvious -lstdc++ candidate.
+
+ // Check in the sysroot first.
+ bool Exists;
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ llvm::sys::Path P(A->getValue(Args));
+ P.appendComponent("usr");
+ P.appendComponent("lib");
+ P.appendComponent("libstdc++.dylib");
+
+ if (llvm::sys::fs::exists(P.str(), Exists) || !Exists) {
+ P.eraseComponent();
+ P.appendComponent("libstdc++.6.dylib");
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ return;
+ }
+ }
+ }
+
+ // Otherwise, look in the root.
+ if ((llvm::sys::fs::exists("/usr/lib/libstdc++.dylib", Exists) || !Exists)&&
+ (!llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib", Exists) && Exists)){
+ CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
+ return;
+ }
+
+ // Otherwise, let the linker search.
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+ }
+}
+
+void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+
+ // For Darwin platforms, use the compiler-rt-based support library
+ // instead of the gcc-provided one (which is also incidentally
+ // only present in the gcc lib dir, which makes it hard to find).
+
+ llvm::sys::Path P(getDriver().ResourceDir);
+ P.appendComponent("lib");
+ P.appendComponent("darwin");
+ P.appendComponent("libclang_rt.cc_kext.a");
+
+ // For now, allow missing resource libraries to support developers who may
+ // not have compiler-rt checked out or integrated into their build.
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+}
+
+DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // FIXME: We really want to get out of the tool chain level argument
+ // translation business, as it makes the driver functionality much
+ // more opaque. For now, we follow gcc closely solely for the
+ // purpose of easily achieving feature parity & testability. Once we
+ // have something that works, we should reevaluate each translation
+ // and try to push it down into tool specific logic.
+
+ for (ArgList::const_iterator it = Args.begin(),
+ ie = Args.end(); it != ie; ++it) {
+ Arg *A = *it;
+
+ if (A->getOption().matches(options::OPT_Xarch__)) {
+ // FIXME: Canonicalize name.
+ if (getArchName() != A->getValue(Args, 0))
+ continue;
+
+ Arg *OriginalArg = A;
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(Args, 1));
+ unsigned Prev = Index;
+ Arg *XarchArg = Opts.ParseOneArg(Args, Index);
+
+ // If the argument parsing failed or more than one argument was
+ // consumed, the -Xarch_ argument's parameter tried to consume
+ // extra arguments. Emit an error and ignore.
+ //
+ // We also want to disallow any options which would alter the
+ // driver behavior; that isn't going to work in our model. We
+ // use isDriverOption() as an approximation, although things
+ // like -O4 are going to slip through.
+ if (!XarchArg || Index > Prev + 1 ||
+ XarchArg->getOption().isDriverOption()) {
+ getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument)
+ << A->getAsString(Args);
+ continue;
+ }
+
+ XarchArg->setBaseArg(A);
+ A = XarchArg;
+
+ DAL->AddSynthesizedArg(A);
+
+ // Linker input arguments require custom handling. The problem is that we
+ // have already constructed the phase actions, so we can not treat them as
+ // "input arguments".
+ if (A->getOption().isLinkerInput()) {
+ // Convert the argument into individual Zlinker_input_args.
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ DAL->AddSeparateArg(OriginalArg,
+ Opts.getOption(options::OPT_Zlinker_input),
+ A->getValue(Args, i));
+
+ }
+ continue;
+ }
+ }
+
+ // Sob. These is strictly gcc compatible for the time being. Apple
+ // gcc translates options twice, which means that self-expanding
+ // options add duplicates.
+ switch ((options::ID) A->getOption().getID()) {
+ default:
+ DAL->append(A);
+ break;
+
+ case options::OPT_mkernel:
+ case options::OPT_fapple_kext:
+ DAL->append(A);
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
+ break;
+
+ case options::OPT_dependency_file:
+ DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF),
+ A->getValue(Args));
+ break;
+
+ case options::OPT_gfull:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
+ break;
+
+ case options::OPT_gused:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
+ break;
+
+ case options::OPT_fterminated_vtables:
+ case options::OPT_findirect_virtual_calls:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_fapple_kext));
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
+ break;
+
+ case options::OPT_shared:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
+ break;
+
+ case options::OPT_fconstant_cfstrings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
+ break;
+
+ case options::OPT_fno_constant_cfstrings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
+ break;
+
+ case options::OPT_Wnonportable_cfstrings:
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
+ break;
+
+ case options::OPT_Wno_nonportable_cfstrings:
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
+ break;
+
+ case options::OPT_fpascal_strings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
+ break;
+
+ case options::OPT_fno_pascal_strings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
+ break;
+ }
+ }
+
+ if (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64)
+ if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
+ DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2");
+
+ // Add the arch options based on the particular spelling of -arch, to match
+ // how the driver driver works.
+ if (BoundArch) {
+ llvm::StringRef Name = BoundArch;
+ const Option *MCpu = Opts.getOption(options::OPT_mcpu_EQ);
+ const Option *MArch = Opts.getOption(options::OPT_march_EQ);
+
+ // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
+ // which defines the list of which architectures we accept.
+ if (Name == "ppc")
+ ;
+ else if (Name == "ppc601")
+ DAL->AddJoinedArg(0, MCpu, "601");
+ else if (Name == "ppc603")
+ DAL->AddJoinedArg(0, MCpu, "603");
+ else if (Name == "ppc604")
+ DAL->AddJoinedArg(0, MCpu, "604");
+ else if (Name == "ppc604e")
+ DAL->AddJoinedArg(0, MCpu, "604e");
+ else if (Name == "ppc750")
+ DAL->AddJoinedArg(0, MCpu, "750");
+ else if (Name == "ppc7400")
+ DAL->AddJoinedArg(0, MCpu, "7400");
+ else if (Name == "ppc7450")
+ DAL->AddJoinedArg(0, MCpu, "7450");
+ else if (Name == "ppc970")
+ DAL->AddJoinedArg(0, MCpu, "970");
+
+ else if (Name == "ppc64")
+ DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+
+ else if (Name == "i386")
+ ;
+ else if (Name == "i486")
+ DAL->AddJoinedArg(0, MArch, "i486");
+ else if (Name == "i586")
+ DAL->AddJoinedArg(0, MArch, "i586");
+ else if (Name == "i686")
+ DAL->AddJoinedArg(0, MArch, "i686");
+ else if (Name == "pentium")
+ DAL->AddJoinedArg(0, MArch, "pentium");
+ else if (Name == "pentium2")
+ DAL->AddJoinedArg(0, MArch, "pentium2");
+ else if (Name == "pentpro")
+ DAL->AddJoinedArg(0, MArch, "pentiumpro");
+ else if (Name == "pentIIm3")
+ DAL->AddJoinedArg(0, MArch, "pentium2");
+
+ else if (Name == "x86_64")
+ DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+
+ else if (Name == "arm")
+ DAL->AddJoinedArg(0, MArch, "armv4t");
+ else if (Name == "armv4t")
+ DAL->AddJoinedArg(0, MArch, "armv4t");
+ else if (Name == "armv5")
+ DAL->AddJoinedArg(0, MArch, "armv5tej");
+ else if (Name == "xscale")
+ DAL->AddJoinedArg(0, MArch, "xscale");
+ else if (Name == "armv6")
+ DAL->AddJoinedArg(0, MArch, "armv6k");
+ else if (Name == "armv7")
+ DAL->AddJoinedArg(0, MArch, "armv7a");
+
+ else
+ llvm_unreachable("invalid Darwin arch");
+ }
+
+ // Add an explicit version min argument for the deployment target. We do this
+ // after argument translation because -Xarch_ arguments may add a version min
+ // argument.
+ AddDeploymentTarget(*DAL);
+
+ return DAL;
+}
+
+bool Darwin::IsUnwindTablesDefault() const {
+ // FIXME: Gross; we should probably have some separate target
+ // definition, possibly even reusing the one in clang.
+ return getArchName() == "x86_64";
+}
+
+bool Darwin::UseDwarfDebugFlags() const {
+ if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
+ return S[0] != '\0';
+ return false;
+}
+
+bool Darwin::UseSjLjExceptions() const {
+ // Darwin uses SjLj exceptions on ARM.
+ return (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb);
+}
+
+const char *Darwin::GetDefaultRelocationModel() const {
+ return "pic";
+}
+
+const char *Darwin::GetForcedPicModel() const {
+ if (getArchName() == "x86_64")
+ return "pic";
+ return 0;
+}
+
+bool Darwin::SupportsObjCGC() const {
+ // Garbage collection is supported everywhere except on iPhone OS.
+ return !isTargetIPhoneOS();
+}
+
+std::string
+Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ return ComputeLLVMTriple(Args);
+}
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+
+Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple) {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+Generic_GCC::~Generic_GCC() {
+ // Free tool implementations.
+ for (llvm::DenseMap<unsigned, Tool*>::iterator
+ it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
+ delete it->second;
+}
+
+Tool &Generic_GCC::SelectTool(const Compilation &C,
+ const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::InputClass:
+ case Action::BindArchClass:
+ assert(0 && "Invalid tool kind.");
+ case Action::PreprocessJobClass:
+ T = new tools::gcc::Preprocess(*this); break;
+ case Action::PrecompileJobClass:
+ T = new tools::gcc::Precompile(*this); break;
+ case Action::AnalyzeJobClass:
+ T = new tools::Clang(*this); break;
+ case Action::CompileJobClass:
+ T = new tools::gcc::Compile(*this); break;
+ case Action::AssembleJobClass:
+ T = new tools::gcc::Assemble(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::gcc::Link(*this); break;
+
+ // This is a bit ungeneric, but the only platform using a driver
+ // driver is Darwin.
+ case Action::LipoJobClass:
+ T = new tools::darwin::Lipo(*this); break;
+ case Action::DsymutilJobClass:
+ T = new tools::darwin::Dsymutil(*this); break;
+ }
+ }
+
+ return *T;
+}
+
+bool Generic_GCC::IsUnwindTablesDefault() const {
+ // FIXME: Gross; we should probably have some separate target
+ // definition, possibly even reusing the one in clang.
+ return getArchName() == "x86_64";
+}
+
+const char *Generic_GCC::GetDefaultRelocationModel() const {
+ return "static";
+}
+
+const char *Generic_GCC::GetForcedPicModel() const {
+ return 0;
+}
+
+/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
+/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
+/// Currently does not support anything else but compilation.
+
+TCEToolChain::TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple) {
+ // Path mangling to find libexec
+ std::string Path(getDriver().Dir);
+
+ Path += "/../libexec";
+ getProgramPaths().push_back(Path);
+}
+
+TCEToolChain::~TCEToolChain() {
+ for (llvm::DenseMap<unsigned, Tool*>::iterator
+ it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool TCEToolChain::IsMathErrnoDefault() const {
+ return true;
+}
+
+bool TCEToolChain::IsUnwindTablesDefault() const {
+ return false;
+}
+
+const char *TCEToolChain::GetDefaultRelocationModel() const {
+ return "static";
+}
+
+const char *TCEToolChain::GetForcedPicModel() const {
+ return 0;
+}
+
+Tool &TCEToolChain::SelectTool(const Compilation &C,
+ const JobAction &JA) const {
+ Action::ActionClass Key;
+ Key = Action::AnalyzeJobClass;
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::PreprocessJobClass:
+ T = new tools::gcc::Preprocess(*this); break;
+ case Action::AnalyzeJobClass:
+ T = new tools::Clang(*this); break;
+ default:
+ assert(false && "Unsupported action for TCE target.");
+ }
+ }
+ return *T;
+}
+
+/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
+
+OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_ELF(Host, Triple) {
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+}
+
+Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass: {
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::openbsd::Assemble(*this);
+ break;
+ }
+ case Action::LinkJobClass:
+ T = new tools::openbsd::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
+
+FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_ELF(Host, Triple) {
+
+ // Determine if we are compiling 32-bit code on an x86_64 platform.
+ bool Lib32 = false;
+ if (Triple.getArch() == llvm::Triple::x86 &&
+ llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+ llvm::Triple::x86_64)
+ Lib32 = true;
+
+ getProgramPaths().push_back(getDriver().Dir + "/../libexec");
+ getProgramPaths().push_back("/usr/libexec");
+ if (Lib32) {
+ getFilePaths().push_back(CLANG_PREFIX "/usr/lib32");
+ } else {
+ getFilePaths().push_back(CLANG_PREFIX "/usr/lib");
+ }
+}
+
+Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::freebsd::Assemble(*this);
+ break;
+ case Action::LinkJobClass:
+ T = new tools::freebsd::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
+
+NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_ELF(Host, Triple) {
+
+ // Determine if we are compiling 32-bit code on an x86_64 platform.
+ bool Lib32 = false;
+ if (Triple.getArch() == llvm::Triple::x86 &&
+ llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+ llvm::Triple::x86_64)
+ Lib32 = true;
+
+ getProgramPaths().push_back(getDriver().Dir + "/../libexec");
+ getProgramPaths().push_back("/usr/libexec");
+ if (Lib32) {
+ getFilePaths().push_back("/usr/lib/i386");
+ } else {
+ getFilePaths().push_back("/usr/lib");
+ }
+}
+
+Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::netbsd::Assemble(*this);
+ break;
+ case Action::LinkJobClass:
+ T = new tools::netbsd::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
+
+Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_GCC(Host, Triple) {
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back("/usr/gnu/lib");
+ getFilePaths().push_back("/usr/gnu/lib/gcc/i686-pc-minix/4.4.3");
+}
+
+Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::minix::Assemble(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::minix::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
+
+AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_GCC(Host, Triple) {
+
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
+
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back("/usr/sfw/lib");
+ getFilePaths().push_back("/opt/gcc4/lib");
+ getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
+
+}
+
+Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::auroraux::Assemble(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::auroraux::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+
+/// Linux toolchain (very bare-bones at the moment).
+
+enum LinuxDistro {
+ DebianLenny,
+ DebianSqueeze,
+ Exherbo,
+ Fedora13,
+ Fedora14,
+ OpenSuse11_3,
+ UbuntuJaunty,
+ UbuntuKarmic,
+ UbuntuLucid,
+ UbuntuMaverick,
+ UnknownDistro
+};
+
+static bool IsFedora(enum LinuxDistro Distro) {
+ return Distro == Fedora13 || Distro == Fedora14;
+}
+
+static bool IsOpenSuse(enum LinuxDistro Distro) {
+ return Distro == OpenSuse11_3;
+}
+
+static bool IsDebian(enum LinuxDistro Distro) {
+ return Distro == DebianLenny || Distro == DebianSqueeze;
+}
+
+static bool IsUbuntu(enum LinuxDistro Distro) {
+ return Distro == UbuntuLucid || Distro == UbuntuMaverick ||
+ Distro == UbuntuJaunty || Distro == UbuntuKarmic;
+}
+
+static bool IsDebianBased(enum LinuxDistro Distro) {
+ return IsDebian(Distro) || IsUbuntu(Distro);
+}
+
+static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) {
+ if (Arch == llvm::Triple::x86_64) {
+ bool Exists;
+ if (Distro == Exherbo &&
+ (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists))
+ return false;
+
+ return true;
+ }
+ if (Arch == llvm::Triple::x86 && IsDebianBased(Distro))
+ return true;
+ return false;
+}
+
+static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
+ llvm::OwningPtr<llvm::MemoryBuffer> File;
+ if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ llvm::SmallVector<llvm::StringRef, 8> Lines;
+ Data.split(Lines, "\n");
+ for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) {
+ if (Lines[i] == "DISTRIB_CODENAME=maverick")
+ return UbuntuMaverick;
+ else if (Lines[i] == "DISTRIB_CODENAME=lucid")
+ return UbuntuLucid;
+ else if (Lines[i] == "DISTRIB_CODENAME=jaunty")
+ return UbuntuJaunty;
+ else if (Lines[i] == "DISTRIB_CODENAME=karmic")
+ return UbuntuKarmic;
+ }
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("Fedora release 14 (Laughlin)"))
+ return Fedora14;
+ else if (Data.startswith("Fedora release 13 (Goddard)"))
+ return Fedora13;
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data[0] == '5')
+ return DebianLenny;
+ else if (Data.startswith("squeeze/sid"))
+ return DebianSqueeze;
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("openSUSE 11.3"))
+ return OpenSuse11_3;
+ return UnknownDistro;
+ }
+
+ bool Exists;
+ if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists)
+ return Exherbo;
+
+ return UnknownDistro;
+}
+
+Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
+ : Generic_ELF(Host, Triple) {
+ llvm::Triple::ArchType Arch =
+ llvm::Triple(getDriver().DefaultHostTriple).getArch();
+
+ std::string Suffix32 = "";
+ if (Arch == llvm::Triple::x86_64)
+ Suffix32 = "/32";
+
+ std::string Suffix64 = "";
+ if (Arch == llvm::Triple::x86)
+ Suffix64 = "/64";
+
+ std::string Lib32 = "lib";
+
+ bool Exists;
+ if (!llvm::sys::fs::exists("/lib32", Exists) && Exists)
+ Lib32 = "lib32";
+
+ std::string Lib64 = "lib";
+ bool Symlink;
+ if (!llvm::sys::fs::exists("/lib64", Exists) && Exists &&
+ (llvm::sys::fs::is_symlink("/lib64", Symlink) || !Symlink))
+ Lib64 = "lib64";
+
+ std::string GccTriple = "";
+ if (Arch == llvm::Triple::arm) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) &&
+ Exists)
+ GccTriple = "arm-linux-gnueabi";
+ } else if (Arch == llvm::Triple::x86_64) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "x86_64-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-unknown-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-unknown-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-pc-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-pc-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux",
+ Exists) && Exists)
+ GccTriple = "x86_64-redhat-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib64/gcc/x86_64-suse-linux",
+ Exists) && Exists)
+ GccTriple = "x86_64-suse-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-manbo-linux-gnu";
+ } else if (Arch == llvm::Triple::x86) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-linux-gnu", Exists) && Exists)
+ GccTriple = "i686-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-pc-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "i686-pc-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "i486-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-redhat-linux", Exists) &&
+ Exists)
+ GccTriple = "i686-redhat-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) &&
+ Exists)
+ GccTriple = "i586-suse-linux";
+ }
+
+ const char* GccVersions[] = {"4.5.1", "4.5", "4.4.5", "4.4.4", "4.4.3", "4.4",
+ "4.3.4", "4.3.3", "4.3.2"};
+ std::string Base = "";
+ for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) {
+ std::string Suffix = GccTriple + "/" + GccVersions[i];
+ std::string t1 = "/usr/lib/gcc/" + Suffix;
+ if (!llvm::sys::fs::exists(t1 + "/crtbegin.o", Exists) && Exists) {
+ Base = t1;
+ break;
+ }
+ std::string t2 = "/usr/lib64/gcc/" + Suffix;
+ if (!llvm::sys::fs::exists(t2 + "/crtbegin.o", Exists) && Exists) {
+ Base = t2;
+ break;
+ }
+ }
+
+ path_list &Paths = getFilePaths();
+ bool Is32Bits = getArch() == llvm::Triple::x86;
+
+ std::string Suffix;
+ std::string Lib;
+
+ if (Is32Bits) {
+ Suffix = Suffix32;
+ Lib = Lib32;
+ } else {
+ Suffix = Suffix64;
+ Lib = Lib64;
+ }
+
+ llvm::sys::Path LinkerPath(Base + "/../../../../" + GccTriple + "/bin/ld");
+ if (!llvm::sys::fs::exists(LinkerPath.str(), Exists) && Exists)
+ Linker = LinkerPath.str();
+ else
+ Linker = GetProgramPath("ld");
+
+ LinuxDistro Distro = DetectLinuxDistro(Arch);
+
+ if (IsUbuntu(Distro)) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("relro");
+ }
+
+ if (Arch == llvm::Triple::arm)
+ ExtraOpts.push_back("-X");
+
+ if (IsFedora(Distro) || Distro == UbuntuMaverick)
+ ExtraOpts.push_back("--hash-style=gnu");
+
+ if (IsDebian(Distro) || Distro == UbuntuLucid || Distro == UbuntuJaunty ||
+ Distro == UbuntuKarmic)
+ ExtraOpts.push_back("--hash-style=both");
+
+ if (IsFedora(Distro))
+ ExtraOpts.push_back("--no-add-needed");
+
+ if (Distro == DebianSqueeze || IsOpenSuse(Distro) ||
+ IsFedora(Distro) || Distro == UbuntuLucid || Distro == UbuntuMaverick ||
+ Distro == UbuntuKarmic)
+ ExtraOpts.push_back("--build-id");
+
+ Paths.push_back(Base + Suffix);
+ if (HasMultilib(Arch, Distro)) {
+ if (IsOpenSuse(Distro) && Is32Bits)
+ Paths.push_back(Base + "/../../../../" + GccTriple + "/lib/../lib");
+ Paths.push_back(Base + "/../../../../" + Lib);
+ Paths.push_back("/lib/../" + Lib);
+ Paths.push_back("/usr/lib/../" + Lib);
+ }
+ if (!Suffix.empty())
+ Paths.push_back(Base);
+ if (IsOpenSuse(Distro))
+ Paths.push_back(Base + "/../../../../" + GccTriple + "/lib");
+ Paths.push_back(Base + "/../../..");
+ if (Arch == getArch() && IsUbuntu(Distro))
+ Paths.push_back("/usr/lib/" + GccTriple);
+}
+
+bool Linux::HasNativeLLVMSupport() const {
+ return true;
+}
+
+Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::linuxtools::Assemble(*this);
+ break;
+ case Action::LinkJobClass:
+ T = new tools::linuxtools::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
+
+DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_ELF(Host, Triple) {
+
+ // Path mangling to find libexec
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
+
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back("/usr/lib/gcc41");
+}
+
+Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::dragonfly::Assemble(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::dragonfly::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
+Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple) {
+}
+
+Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::InputClass:
+ case Action::BindArchClass:
+ case Action::LipoJobClass:
+ case Action::DsymutilJobClass:
+ assert(0 && "Invalid tool kind.");
+ case Action::PreprocessJobClass:
+ case Action::PrecompileJobClass:
+ case Action::AnalyzeJobClass:
+ case Action::CompileJobClass:
+ T = new tools::Clang(*this); break;
+ case Action::AssembleJobClass:
+ T = new tools::ClangAs(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::visualstudio::Link(*this); break;
+ }
+ }
+
+ return *T;
+}
+
+bool Windows::IsIntegratedAssemblerDefault() const {
+ return true;
+}
+
+bool Windows::IsUnwindTablesDefault() const {
+ // FIXME: Gross; we should probably have some separate target
+ // definition, possibly even reusing the one in clang.
+ return getArchName() == "x86_64";
+}
+
+const char *Windows::GetDefaultRelocationModel() const {
+ return "static";
+}
+
+const char *Windows::GetForcedPicModel() const {
+ if (getArchName() == "x86_64")
+ return "pic";
+ return 0;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
new file mode 100644
index 0000000..0e3645c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
@@ -0,0 +1,384 @@
+//===--- ToolChains.h - ToolChain Implementations ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_TOOLCHAINS_H_
+#define CLANG_LIB_DRIVER_TOOLCHAINS_H_
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/ToolChain.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Compiler.h"
+
+#include "Tools.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
+protected:
+ mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+public:
+ Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple);
+ ~Generic_GCC();
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+ virtual bool IsUnwindTablesDefault() const;
+ virtual const char *GetDefaultRelocationModel() const;
+ virtual const char *GetForcedPicModel() const;
+};
+
+/// Darwin - The base Darwin tool chain.
+class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
+public:
+ /// The host version.
+ unsigned DarwinVersion[3];
+
+private:
+ mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+ /// Whether the information on the target has been initialized.
+ //
+ // FIXME: This should be eliminated. What we want to do is make this part of
+ // the "default target for arguments" selection process, once we get out of
+ // the argument translation business.
+ mutable bool TargetInitialized;
+
+ /// Whether we are targetting iPhoneOS target.
+ mutable bool TargetIsIPhoneOS;
+
+ /// The OS version we are targetting.
+ mutable unsigned TargetVersion[3];
+
+ /// The default macosx-version-min of this tool chain; empty until
+ /// initialized.
+ std::string MacosxVersionMin;
+
+private:
+ void AddDeploymentTarget(DerivedArgList &Args) const;
+
+public:
+ Darwin(const HostInfo &Host, const llvm::Triple& Triple);
+ ~Darwin();
+
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
+ /// @name Darwin Specific Toolchain API
+ /// {
+
+ // FIXME: Eliminate these ...Target functions and derive separate tool chains
+ // for these targets and put version in constructor.
+ void setTarget(bool isIPhoneOS, unsigned Major, unsigned Minor,
+ unsigned Micro) const {
+ // FIXME: For now, allow reinitialization as long as values don't
+ // change. This will go away when we move away from argument translation.
+ if (TargetInitialized && TargetIsIPhoneOS == isIPhoneOS &&
+ TargetVersion[0] == Major && TargetVersion[1] == Minor &&
+ TargetVersion[2] == Micro)
+ return;
+
+ assert(!TargetInitialized && "Target already initialized!");
+ TargetInitialized = true;
+ TargetIsIPhoneOS = isIPhoneOS;
+ TargetVersion[0] = Major;
+ TargetVersion[1] = Minor;
+ TargetVersion[2] = Micro;
+ }
+
+ bool isTargetIPhoneOS() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetIsIPhoneOS;
+ }
+
+ bool isTargetInitialized() const { return TargetInitialized; }
+
+ void getTargetVersion(unsigned (&Res)[3]) const {
+ assert(TargetInitialized && "Target not initialized!");
+ Res[0] = TargetVersion[0];
+ Res[1] = TargetVersion[1];
+ Res[2] = TargetVersion[2];
+ }
+
+ /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler
+ /// invocation. For example, Darwin treats different ARM variations as
+ /// distinct architectures.
+ llvm::StringRef getDarwinArchName(const ArgList &Args) const;
+
+ static bool isVersionLT(unsigned (&A)[3], unsigned (&B)[3]) {
+ for (unsigned i=0; i < 3; ++i) {
+ if (A[i] > B[i]) return false;
+ if (A[i] < B[i]) return true;
+ }
+ return false;
+ }
+
+ bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ assert(isTargetIPhoneOS() && "Unexpected call for OS X target!");
+ unsigned B[3] = { V0, V1, V2 };
+ return isVersionLT(TargetVersion, B);
+ }
+
+ bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ assert(!isTargetIPhoneOS() && "Unexpected call for iPhoneOS target!");
+ unsigned B[3] = { V0, V1, V2 };
+ return isVersionLT(TargetVersion, B);
+ }
+
+ /// AddLinkSearchPathArgs - Add the linker search paths to \arg CmdArgs.
+ ///
+ /// \param Args - The input argument list.
+ /// \param CmdArgs [out] - The command argument list to append the paths
+ /// (prefixed by -L) to.
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const = 0;
+
+ /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler
+ /// runtime library.
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const = 0;
+
+ /// }
+ /// @name ToolChain Implementation
+ /// {
+
+ virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
+ virtual bool HasNativeLLVMSupport() const;
+
+ virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const;
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+ virtual bool IsBlocksDefault() const {
+ // Always allow blocks on Darwin; users interested in versioning are
+ // expected to use /usr/include/Blocks.h.
+ return true;
+ }
+ virtual bool IsIntegratedAssemblerDefault() const {
+#ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER
+ return false;
+#else
+ // Default integrated assembler to on for x86.
+ return (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64);
+#endif
+ }
+ virtual bool IsStrictAliasingDefault() const {
+#ifdef DISABLE_DEFAULT_STRICT_ALIASING
+ return false;
+#else
+ return ToolChain::IsStrictAliasingDefault();
+#endif
+ }
+
+ virtual bool IsObjCDefaultSynthPropertiesDefault() const {
+ return false;
+ }
+
+ virtual bool IsObjCNonFragileABIDefault() const {
+ // Non-fragile ABI is default for everything but i386.
+ return getTriple().getArch() != llvm::Triple::x86;
+ }
+ virtual bool IsObjCLegacyDispatchDefault() const {
+ // This is only used with the non-fragile ABI.
+
+ // Legacy dispatch is used everywhere except on x86_64.
+ return getTriple().getArch() != llvm::Triple::x86_64;
+ }
+ virtual bool UseObjCMixedDispatch() const {
+ // This is only used with the non-fragile ABI and non-legacy dispatch.
+
+ // Mixed dispatch is used everywhere except OS X before 10.6.
+ return !(!isTargetIPhoneOS() && isMacosxVersionLT(10, 6));
+ }
+ virtual bool IsUnwindTablesDefault() const;
+ virtual unsigned GetDefaultStackProtectorLevel() const {
+ // Stack protectors default to on for 10.6 and beyond.
+ return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 6);
+ }
+ virtual const char *GetDefaultRelocationModel() const;
+ virtual const char *GetForcedPicModel() const;
+
+ virtual bool SupportsObjCGC() const;
+
+ virtual bool UseDwarfDebugFlags() const;
+
+ virtual bool UseSjLjExceptions() const;
+
+ /// }
+};
+
+/// DarwinClang - The Darwin toolchain used by Clang.
+class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
+public:
+ DarwinClang(const HostInfo &Host, const llvm::Triple& Triple);
+
+ /// @name Darwin ToolChain Implementation
+ /// {
+
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// }
+};
+
+/// DarwinGCC - The Darwin toolchain used by GCC.
+class LLVM_LIBRARY_VISIBILITY DarwinGCC : public Darwin {
+ /// GCC version to use.
+ unsigned GCCVersion[3];
+
+ /// The directory suffix for this tool chain.
+ std::string ToolChainDir;
+
+public:
+ DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple);
+
+ /// @name Darwin ToolChain Implementation
+ /// {
+
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// }
+};
+
+/// Darwin_Generic_GCC - Generic Darwin tool chain using gcc.
+class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC {
+public:
+ Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_GCC(Host, Triple) {}
+
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
+ virtual const char *GetDefaultRelocationModel() const { return "pic"; }
+};
+
+class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
+ public:
+ Generic_ELF(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_GCC(Host, Triple) {}
+
+ virtual bool IsIntegratedAssemblerDefault() const {
+ // Default integrated assembler to on for x86.
+ return (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64);
+ }
+};
+
+class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC {
+public:
+ AuroraUX(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
+public:
+ OpenBSD(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
+public:
+ FreeBSD(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
+public:
+ NetBSD(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY Minix : public Generic_GCC {
+public:
+ Minix(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
+public:
+ DragonFly(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
+public:
+ Linux(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual bool HasNativeLLVMSupport() const;
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+ std::string Linker;
+ std::vector<std::string> ExtraOpts;
+};
+
+
+/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
+/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
+class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
+public:
+ TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple);
+ ~TCEToolChain();
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+ bool IsMathErrnoDefault() const;
+ bool IsUnwindTablesDefault() const;
+ const char* GetDefaultRelocationModel() const;
+ const char* GetForcedPicModel() const;
+
+private:
+ mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+};
+
+class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
+ mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+public:
+ Windows(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+ virtual bool IsIntegratedAssemblerDefault() const;
+ virtual bool IsUnwindTablesDefault() const;
+ virtual const char *GetDefaultRelocationModel() const;
+ virtual const char *GetForcedPicModel() const;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
new file mode 100644
index 0000000..5a63213
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -0,0 +1,3909 @@
+//===--- Tools.cpp - Tools Implementations --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Process.h"
+
+#include "InputInfo.h"
+#include "ToolChains.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+
+/// CheckPreprocessingOptions - Perform some validation of preprocessing
+/// arguments that is shared with gcc.
+static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
+ if (!Args.hasArg(options::OPT_E))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-E";
+}
+
+/// CheckCodeGenerationOptions - Perform some validation of code generation
+/// arguments that is shared with gcc.
+static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
+ // In gcc, only ARM checks this, but it seems reasonable to check universally.
+ if (Args.hasArg(options::OPT_static))
+ if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
+ options::OPT_mdynamic_no_pic))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-static";
+}
+
+// Quote target names for inclusion in GNU Make dependency files.
+// Only the characters '$', '#', ' ', '\t' are quoted.
+static void QuoteTarget(llvm::StringRef Target,
+ llvm::SmallVectorImpl<char> &Res) {
+ for (unsigned i = 0, e = Target.size(); i != e; ++i) {
+ switch (Target[i]) {
+ case ' ':
+ case '\t':
+ // Escape the preceding backslashes
+ for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
+ Res.push_back('\\');
+
+ // Escape the space/tab
+ Res.push_back('\\');
+ break;
+ case '$':
+ Res.push_back('$');
+ break;
+ case '#':
+ Res.push_back('\\');
+ break;
+ default:
+ break;
+ }
+
+ Res.push_back(Target[i]);
+ }
+}
+
+static void AddLinkerInputs(const ToolChain &TC,
+ const InputInfoList &Inputs, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+
+ // Add extra linker input arguments which are not treated as inputs
+ // (constructed via -Xarch_).
+ Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ if (!TC.HasNativeLLVMSupport()) {
+ // Don't try to pass LLVM inputs unless we have native support.
+ if (II.getType() == types::TY_LLVM_IR ||
+ II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC ||
+ II.getType() == types::TY_LTO_BC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << TC.getTripleString();
+ }
+
+ // Add filenames immediately.
+ if (II.isFilename()) {
+ CmdArgs.push_back(II.getFilename());
+ continue;
+ }
+
+ // Otherwise, this is a linker input argument.
+ const Arg &A = II.getInputArg();
+
+ // Handle reserved library options.
+ if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) {
+ TC.AddCCKextLibArgs(Args, CmdArgs);
+ } else
+ A.renderAsInput(Args, CmdArgs);
+ }
+}
+
+void Clang::AddPreprocessingOptions(const Driver &D,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs) const {
+ Arg *A;
+
+ CheckPreprocessingOptions(D, Args);
+
+ Args.AddLastArg(CmdArgs, options::OPT_C);
+ Args.AddLastArg(CmdArgs, options::OPT_CC);
+
+ // Handle dependency file generation.
+ if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
+ (A = Args.getLastArg(options::OPT_MD)) ||
+ (A = Args.getLastArg(options::OPT_MMD))) {
+ // Determine the output location.
+ const char *DepFile;
+ if (Output.getType() == types::TY_Dependencies) {
+ DepFile = Output.getFilename();
+ } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
+ DepFile = MF->getValue(Args);
+ } else if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MM)) {
+ DepFile = "-";
+ } else {
+ DepFile = darwin::CC1::getDependencyFileName(Args, Inputs);
+ }
+ CmdArgs.push_back("-dependency-file");
+ CmdArgs.push_back(DepFile);
+
+ // Add a default target if one wasn't specified.
+ if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
+ const char *DepTarget;
+
+ // If user provided -o, that is the dependency target, except
+ // when we are only generating a dependency file.
+ Arg *OutputOpt = Args.getLastArg(options::OPT_o);
+ if (OutputOpt && Output.getType() != types::TY_Dependencies) {
+ DepTarget = OutputOpt->getValue(Args);
+ } else {
+ // Otherwise derive from the base input.
+ //
+ // FIXME: This should use the computed output file location.
+ llvm::SmallString<128> P(Inputs[0].getBaseInput());
+ llvm::sys::path::replace_extension(P, "o");
+ DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
+ }
+
+ CmdArgs.push_back("-MT");
+ llvm::SmallString<128> Quoted;
+ QuoteTarget(DepTarget, Quoted);
+ CmdArgs.push_back(Args.MakeArgString(Quoted));
+ }
+
+ if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MD))
+ CmdArgs.push_back("-sys-header-deps");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_MP);
+
+ // Convert all -MQ <target> args to -MT <quoted target>
+ for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
+ options::OPT_MQ),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+
+ if (A->getOption().matches(options::OPT_MQ)) {
+ CmdArgs.push_back("-MT");
+ llvm::SmallString<128> Quoted;
+ QuoteTarget(A->getValue(Args), Quoted);
+ CmdArgs.push_back(Args.MakeArgString(Quoted));
+
+ // -MT flag - no change
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ // Add -i* options, and automatically translate to
+ // -include-pch/-include-pth for transparent PCH support. It's
+ // wonky, but we include looking for .gch so we can support seamless
+ // replacement into a build system already set up to be generating
+ // .gch files.
+ bool RenderedImplicitInclude = false;
+ for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = it;
+
+ if (A->getOption().matches(options::OPT_include)) {
+ bool IsFirstImplicitInclude = !RenderedImplicitInclude;
+ RenderedImplicitInclude = true;
+
+ // Use PCH if the user requested it.
+ bool UsePCH = D.CCCUsePCH;
+
+ bool FoundPTH = false;
+ bool FoundPCH = false;
+ llvm::sys::Path P(A->getValue(Args));
+ bool Exists;
+ if (UsePCH) {
+ P.appendSuffix("pch");
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ FoundPCH = true;
+ else
+ P.eraseSuffix();
+ }
+
+ if (!FoundPCH) {
+ P.appendSuffix("pth");
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ FoundPTH = true;
+ else
+ P.eraseSuffix();
+ }
+
+ if (!FoundPCH && !FoundPTH) {
+ P.appendSuffix("gch");
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ FoundPCH = UsePCH;
+ FoundPTH = !UsePCH;
+ }
+ else
+ P.eraseSuffix();
+ }
+
+ if (FoundPCH || FoundPTH) {
+ if (IsFirstImplicitInclude) {
+ A->claim();
+ if (UsePCH)
+ CmdArgs.push_back("-include-pch");
+ else
+ CmdArgs.push_back("-include-pth");
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ continue;
+ } else {
+ // Ignore the PCH if not first on command line and emit warning.
+ D.Diag(clang::diag::warn_drv_pch_not_first_include)
+ << P.str() << A->getAsString(Args);
+ }
+ }
+ }
+
+ // Not translated, render as usual.
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+ Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
+
+ // Add C++ include arguments, if needed.
+ types::ID InputType = Inputs[0].getType();
+ if (types::isCXX(InputType))
+ getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+
+ // Add -Wp, and -Xassembler if using the preprocessor.
+
+ // FIXME: There is a very unfortunate problem here, some troubled
+ // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
+ // really support that we would have to parse and then translate
+ // those options. :(
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
+ options::OPT_Xpreprocessor);
+
+ // -I- is a deprecated GCC feature, reject it.
+ if (Arg *A = Args.getLastArg(options::OPT_I_))
+ D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
+
+ // If we have a --sysroot, and don't have an explicit -isysroot flag, add an
+ // -isysroot to the CC1 invocation.
+ if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
+ if (!Args.hasArg(options::OPT_isysroot)) {
+ CmdArgs.push_back("-isysroot");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+ }
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue(Args);
+
+ llvm::StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue(Args);
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ if (MArch == "armv2" || MArch == "armv2a")
+ return "arm2";
+ if (MArch == "armv3")
+ return "arm6";
+ if (MArch == "armv3m")
+ return "arm7m";
+ if (MArch == "armv4" || MArch == "armv4t")
+ return "arm7tdmi";
+ if (MArch == "armv5" || MArch == "armv5t")
+ return "arm10tdmi";
+ if (MArch == "armv5e" || MArch == "armv5te")
+ return "arm1026ejs";
+ if (MArch == "armv5tej")
+ return "arm926ej-s";
+ if (MArch == "armv6" || MArch == "armv6k")
+ return "arm1136jf-s";
+ if (MArch == "armv6j")
+ return "arm1136j-s";
+ if (MArch == "armv6z" || MArch == "armv6zk")
+ return "arm1176jzf-s";
+ if (MArch == "armv6t2")
+ return "arm1156t2-s";
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ return "cortex-a8";
+ if (MArch == "armv7r" || MArch == "armv7-r")
+ return "cortex-r4";
+ if (MArch == "armv7m" || MArch == "armv7-m")
+ return "cortex-m3";
+ if (MArch == "ep9312")
+ return "ep9312";
+ if (MArch == "iwmmxt")
+ return "iwmmxt";
+ if (MArch == "xscale")
+ return "xscale";
+
+ // If all else failed, return the most base CPU LLVM supports.
+ return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+ if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+ CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+ CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+ CPU == "arm940t" || CPU == "ep9312")
+ return "v4t";
+
+ if (CPU == "arm10tdmi" || CPU == "arm1020t")
+ return "v5";
+
+ if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+ CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+ CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+ CPU == "iwmmxt")
+ return "v5e";
+
+ if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+ CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+ return "v6";
+
+ if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+ return "v6t2";
+
+ if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ return "v7";
+
+ return "";
+}
+
+// FIXME: Move to target hook.
+static bool isSignedCharDefault(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return true;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ if (Triple.getOS() == llvm::Triple::Darwin)
+ return true;
+ return false;
+
+ case llvm::Triple::systemz:
+ return false;
+ }
+}
+
+void Clang::AddARMTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ llvm::Triple Triple = getToolChain().getTriple();
+
+ // Select the ABI to use.
+ //
+ // FIXME: Support -meabi.
+ const char *ABIName = 0;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ ABIName = A->getValue(Args);
+ } else {
+ // Select the default based on the platform.
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABI:
+ ABIName = "aapcs-linux";
+ break;
+ case llvm::Triple::EABI:
+ ABIName = "aapcs";
+ break;
+ default:
+ ABIName = "apcs-gnu";
+ }
+ }
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ // Set the CPU based on -march= and -mcpu=.
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(getARMTargetCPU(Args, Triple));
+
+ // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ // -mfloat-abi=.
+ llvm::StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ else {
+ FloatABI = A->getValue(Args);
+ if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
+ D.Diag(clang::diag::err_drv_invalid_mfloat_abi)
+ << A->getAsString(Args);
+ FloatABI = "soft";
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ switch (Triple.getOS()) {
+ case llvm::Triple::Darwin: {
+ // Darwin defaults to "softfp" for v6 and v7.
+ //
+ // FIXME: Factor out an ARM class so we can cache the arch somewhere.
+ llvm::StringRef ArchName =
+ getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ if (ArchName.startswith("v6") || ArchName.startswith("v7"))
+ FloatABI = "softfp";
+ else
+ FloatABI = "soft";
+ break;
+ }
+
+ case llvm::Triple::Linux: {
+ if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUEABI) {
+ FloatABI = "softfp";
+ break;
+ }
+ }
+ // fall through
+
+ default:
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABI:
+ FloatABI = "softfp";
+ break;
+ case llvm::Triple::EABI:
+ // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
+ FloatABI = "softfp";
+ break;
+ default:
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ break;
+ }
+ }
+ }
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ } else if (FloatABI == "softfp") {
+ // Floating point operations are hard, but argument passing is soft.
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ } else {
+ // Floating point operations and argument passing are hard.
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
+ // Set appropriate target features for floating point mode.
+ //
+ // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
+ // yet (it uses the -mfloat-abi and -msoft-float options above), and it is
+ // stripped out by the ARM target.
+
+ // Use software floating point operations?
+ if (FloatABI == "soft") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+soft-float");
+ }
+
+ // Use software floating point argument passing?
+ if (FloatABI != "hard") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+soft-float-abi");
+ }
+
+ // Honor -mfpu=.
+ //
+ // FIXME: Centralize feature selection, defaulting shouldn't be also in the
+ // frontend target.
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
+ llvm::StringRef FPU = A->getValue(Args);
+
+ // Set the target features based on the FPU.
+ if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
+ // Disable any default FPU support.
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-vfp2");
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-vfp3");
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-neon");
+ } else if (FPU == "vfp") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+vfp2");
+ } else if (FPU == "vfp3") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+vfp3");
+ } else if (FPU == "neon") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+neon");
+ } else
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ }
+}
+
+void Clang::AddMIPSTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ // Select the ABI to use.
+ const char *ABIName = 0;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ ABIName = A->getValue(Args);
+ } else {
+ ABIName = "o32";
+ }
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ llvm::StringRef MArch = A->getValue(Args);
+ CmdArgs.push_back("-target-cpu");
+
+ if ((MArch == "r2000") || (MArch == "r3000"))
+ CmdArgs.push_back("mips1");
+ else if (MArch == "r6000")
+ CmdArgs.push_back("mips2");
+ else
+ CmdArgs.push_back(MArch.str().c_str());
+ }
+
+ // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ llvm::StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ }
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-msoft-float");
+ } else {
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mhard-float");
+ }
+}
+
+void Clang::AddSparcTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ llvm::StringRef MArch = A->getValue(Args);
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(MArch.str().c_str());
+ }
+
+ // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ llvm::StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ switch (getToolChain().getTriple().getOS()) {
+ default:
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ break;
+ }
+ }
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("soft");
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+soft-float");
+ } else {
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mhard-float");
+ }
+}
+
+void Clang::AddX86TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ if (!Args.hasFlag(options::OPT_mred_zone,
+ options::OPT_mno_red_zone,
+ true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ if (Args.hasFlag(options::OPT_msoft_float,
+ options::OPT_mno_soft_float,
+ false))
+ CmdArgs.push_back("-no-implicit-float");
+
+ const char *CPUName = 0;
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ if (llvm::StringRef(A->getValue(Args)) == "native") {
+ // FIXME: Reject attempts to use -march=native unless the target matches
+ // the host.
+ //
+ // FIXME: We should also incorporate the detected target features for use
+ // with -native.
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (!CPU.empty())
+ CPUName = Args.MakeArgString(CPU);
+ } else
+ CPUName = A->getValue(Args);
+ }
+
+ // Select the default CPU if none was given (or detection failed).
+ if (!CPUName) {
+ // FIXME: Need target hooks.
+ if (getToolChain().getOS().startswith("darwin")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "core2";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "yonah";
+ } else if (getToolChain().getOS().startswith("haiku")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i586";
+ } else if (getToolChain().getOS().startswith("openbsd")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i486";
+ } else if (getToolChain().getOS().startswith("netbsd")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i486";
+ } else if (getToolChain().getOS().startswith("freebsd")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i486";
+ } else {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "pentium4";
+ }
+ }
+
+ if (CPUName) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(CPUName);
+ }
+
+ for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ llvm::StringRef Name = (*it)->getOption().getName();
+ (*it)->claim();
+
+ // Skip over "-m".
+ assert(Name.startswith("-m") && "Invalid feature name.");
+ Name = Name.substr(2);
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
+}
+
+static bool needsExceptions(const ArgList &Args, types::ID InputType,
+ const llvm::Triple &Triple) {
+ // Handle -fno-exceptions.
+ if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
+ options::OPT_fno_exceptions)) {
+ if (A->getOption().matches(options::OPT_fexceptions))
+ return true;
+ else
+ return false;
+ }
+
+ // Otherwise, C++ inputs use exceptions.
+ if (types::isCXX(InputType))
+ return true;
+
+ // As do Objective-C non-fragile ABI inputs and all Objective-C inputs on
+ // x86_64 and ARM after SnowLeopard.
+ if (types::isObjC(InputType)) {
+ if (Args.hasArg(options::OPT_fobjc_nonfragile_abi))
+ return true;
+ if (Triple.getOS() != llvm::Triple::Darwin)
+ return false;
+ return (Triple.getDarwinMajorNumber() >= 9 &&
+ (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::arm));
+ }
+
+ return false;
+}
+
+void Clang::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
+ options::OPT_fapple_kext);
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+
+ // Invoke ourselves in -cc1 mode.
+ //
+ // FIXME: Implement custom jobs for internal actions.
+ CmdArgs.push_back("-cc1");
+
+ // Add the "effective" target triple.
+ CmdArgs.push_back("-triple");
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ // Select the appropriate action.
+ bool IsRewriter = false;
+ if (isa<AnalyzeJobAction>(JA)) {
+ assert(JA.getType() == types::TY_Plist && "Invalid output type.");
+ CmdArgs.push_back("-analyze");
+ } else if (isa<PreprocessJobAction>(JA)) {
+ if (Output.getType() == types::TY_Dependencies)
+ CmdArgs.push_back("-Eonly");
+ else
+ CmdArgs.push_back("-E");
+ } else if (isa<AssembleJobAction>(JA)) {
+ CmdArgs.push_back("-emit-obj");
+
+ // At -O0, we use -mrelax-all by default.
+ bool IsOpt = false;
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ IsOpt = !A->getOption().matches(options::OPT_O0);
+ if (Args.hasFlag(options::OPT_mrelax_all,
+ options::OPT_mno_relax_all,
+ !IsOpt))
+ CmdArgs.push_back("-mrelax-all");
+
+ // When using an integrated assembler, translate -Wa, and -Xassembler
+ // options.
+ for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
+ options::OPT_Xassembler),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ llvm::StringRef Value = A->getValue(Args, i);
+
+ if (Value == "-force_cpusubtype_ALL") {
+ // Do nothing, this is the default and we don't support anything else.
+ } else if (Value == "-L") {
+ // We don't support -L yet, but it isn't important enough to error
+ // on. No one should really be using it for a semantic change.
+ D.Diag(clang::diag::warn_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ } else {
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+ }
+
+ // Also ignore explicit -force_cpusubtype_ALL option.
+ (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
+ } else if (isa<PrecompileJobAction>(JA)) {
+ // Use PCH if the user requested it.
+ bool UsePCH = D.CCCUsePCH;
+
+ if (UsePCH)
+ CmdArgs.push_back("-emit-pch");
+ else
+ CmdArgs.push_back("-emit-pth");
+ } else {
+ assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
+
+ if (JA.getType() == types::TY_Nothing) {
+ CmdArgs.push_back("-fsyntax-only");
+ } else if (JA.getType() == types::TY_LLVM_IR ||
+ JA.getType() == types::TY_LTO_IR) {
+ CmdArgs.push_back("-emit-llvm");
+ } else if (JA.getType() == types::TY_LLVM_BC ||
+ JA.getType() == types::TY_LTO_BC) {
+ CmdArgs.push_back("-emit-llvm-bc");
+ } else if (JA.getType() == types::TY_PP_Asm) {
+ CmdArgs.push_back("-S");
+ } else if (JA.getType() == types::TY_AST) {
+ CmdArgs.push_back("-emit-pch");
+ } else if (JA.getType() == types::TY_RewrittenObjC) {
+ CmdArgs.push_back("-rewrite-objc");
+ IsRewriter = true;
+ } else {
+ assert(JA.getType() == types::TY_PP_Asm &&
+ "Unexpected output type!");
+ }
+ }
+
+ // The make clang go fast button.
+ CmdArgs.push_back("-disable-free");
+
+ // Disable the verification pass in -asserts builds.
+#ifdef NDEBUG
+ CmdArgs.push_back("-disable-llvm-verifier");
+#endif
+
+ // Set the main file name, so that debug info works even with
+ // -save-temps.
+ CmdArgs.push_back("-main-file-name");
+ CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
+
+ // Some flags which affect the language (via preprocessor
+ // defines). See darwin::CC1::AddCPPArgs.
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-static-define");
+
+ if (isa<AnalyzeJobAction>(JA)) {
+ // Enable region store model by default.
+ CmdArgs.push_back("-analyzer-store=region");
+
+ // Treat blocks as analysis entry points.
+ CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
+
+ // Add default argument set.
+ if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
+ types::ID InputType = Inputs[0].getType();
+
+ // Checks to perform for all language types.
+
+ CmdArgs.push_back("-analyzer-checker=core");
+ if (getToolChain().getTriple().getOS() != llvm::Triple::Win32)
+ CmdArgs.push_back("-analyzer-checker=unix");
+ if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
+ CmdArgs.push_back("-analyzer-checker=macosx");
+
+ // Checks to perform for Objective-C/Objective-C++.
+ if (types::isObjC(InputType)) {
+ // Enable all checkers in 'cocoa' package.
+ CmdArgs.push_back("-analyzer-checker=cocoa");
+ }
+
+ // NOTE: Leaving -analyzer-check-objc-mem here is intentional.
+ // It also checks C code.
+ CmdArgs.push_back("-analyzer-check-objc-mem");
+
+ CmdArgs.push_back("-analyzer-eagerly-assume");
+ }
+
+ // Set the output format. The default is plist, for (lame) historical
+ // reasons.
+ CmdArgs.push_back("-analyzer-output");
+ if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
+ CmdArgs.push_back(A->getValue(Args));
+ else
+ CmdArgs.push_back("plist");
+
+ // Disable the presentation of standard compiler warnings when
+ // using --analyze. We only want to show static analyzer diagnostics
+ // or frontend errors.
+ CmdArgs.push_back("-w");
+
+ // Add -Xanalyzer arguments when running as analyzer.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
+ }
+
+ CheckCodeGenerationOptions(D, Args);
+
+ // Perform argument translation for LLVM backend. This
+ // takes some care in reconciling with llvm-gcc. The
+ // issue is that llvm-gcc translates these options based on
+ // the values in cc1, whereas we are processing based on
+ // the driver arguments.
+
+ // This comes from the default translation the driver + cc1
+ // would do to enable flag_pic.
+ //
+ // FIXME: Centralize this code.
+ bool PICEnabled = (Args.hasArg(options::OPT_fPIC) ||
+ Args.hasArg(options::OPT_fpic) ||
+ Args.hasArg(options::OPT_fPIE) ||
+ Args.hasArg(options::OPT_fpie));
+ bool PICDisabled = (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_static));
+ const char *Model = getToolChain().GetForcedPicModel();
+ if (!Model) {
+ if (Args.hasArg(options::OPT_mdynamic_no_pic))
+ Model = "dynamic-no-pic";
+ else if (PICDisabled)
+ Model = "static";
+ else if (PICEnabled)
+ Model = "pic";
+ else
+ Model = getToolChain().GetDefaultRelocationModel();
+ }
+ if (llvm::StringRef(Model) != "pic") {
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back(Model);
+ }
+
+ // Infer the __PIC__ value.
+ //
+ // FIXME: This isn't quite right on Darwin, which always sets
+ // __PIC__=2.
+ if (strcmp(Model, "pic") == 0 || strcmp(Model, "dynamic-no-pic") == 0) {
+ CmdArgs.push_back("-pic-level");
+ CmdArgs.push_back(Args.hasArg(options::OPT_fPIC) ? "2" : "1");
+ }
+ if (!Args.hasFlag(options::OPT_fmerge_all_constants,
+ options::OPT_fno_merge_all_constants))
+ CmdArgs.push_back("-no-merge-all-constants");
+
+ // LLVM Code Generator Options.
+
+ if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
+ CmdArgs.push_back("-mregparm");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // FIXME: Set --enable-unsafe-fp-math.
+ if (Args.hasFlag(options::OPT_fno_omit_frame_pointer,
+ options::OPT_fomit_frame_pointer))
+ CmdArgs.push_back("-mdisable-fp-elim");
+ if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
+ options::OPT_fno_zero_initialized_in_bss))
+ CmdArgs.push_back("-mno-zero-initialized-in-bss");
+ if (!Args.hasFlag(options::OPT_fstrict_aliasing,
+ options::OPT_fno_strict_aliasing,
+ getToolChain().IsStrictAliasingDefault()))
+ CmdArgs.push_back("-relaxed-aliasing");
+
+ // Decide whether to use verbose asm. Verbose assembly is the default on
+ // toolchains which have the integrated assembler on by default.
+ bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
+ if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
+ IsVerboseAsmDefault) ||
+ Args.hasArg(options::OPT_dA))
+ CmdArgs.push_back("-masm-verbose");
+
+ if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
+ CmdArgs.push_back("-mdebug-pass");
+ CmdArgs.push_back("Structure");
+ }
+ if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
+ CmdArgs.push_back("-mdebug-pass");
+ CmdArgs.push_back("Arguments");
+ }
+
+ // Enable -mconstructor-aliases except on darwin, where we have to
+ // work around a linker bug; see <rdar://problem/7651567>.
+ if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin)
+ CmdArgs.push_back("-mconstructor-aliases");
+
+ if (Args.hasArg(options::OPT_mms_bitfields)) {
+ CmdArgs.push_back("-mms-bitfields");
+ }
+
+ // This is a coarse approximation of what llvm-gcc actually does, both
+ // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
+ // complicated ways.
+ bool AsynchronousUnwindTables =
+ Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ getToolChain().IsUnwindTablesDefault() &&
+ !KernelOrKext);
+ if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
+ AsynchronousUnwindTables))
+ CmdArgs.push_back("-munwind-tables");
+
+ if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+ CmdArgs.push_back("-mlimit-float-precision");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // FIXME: Handle -mtune=.
+ (void) Args.hasArg(options::OPT_mtune_EQ);
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ CmdArgs.push_back("-mcode-model");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // Add target specific cpu and features flags.
+ switch(getToolChain().getTriple().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ AddARMTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparc:
+ AddSparcTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
+ }
+
+ // Pass the linker version in use.
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+ CmdArgs.push_back("-target-linker-version");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // -mno-omit-leaf-frame-pointer is the default on Darwin.
+ if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
+ options::OPT_mno_omit_leaf_frame_pointer,
+ getToolChain().getTriple().getOS() != llvm::Triple::Darwin))
+ CmdArgs.push_back("-momit-leaf-frame-pointer");
+
+ // -fno-math-errno is default.
+ if (Args.hasFlag(options::OPT_fmath_errno,
+ options::OPT_fno_math_errno,
+ false))
+ CmdArgs.push_back("-fmath-errno");
+
+ // Explicitly error on some things we know we don't support and can't just
+ // ignore.
+ types::ID InputType = Inputs[0].getType();
+ if (!Args.hasArg(options::OPT_fallow_unsupported)) {
+ Arg *Unsupported;
+ if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
+ (Unsupported = Args.getLastArg(options::OPT_iframework)))
+ D.Diag(clang::diag::err_drv_clang_unsupported)
+ << Unsupported->getOption().getName();
+
+ if (types::isCXX(InputType) &&
+ getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
+ getToolChain().getTriple().getArch() == llvm::Triple::x86) {
+ if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)))
+ D.Diag(clang::diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
+ << Unsupported->getOption().getName();
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_v);
+ Args.AddLastArg(CmdArgs, options::OPT_H);
+ if (D.CCPrintHeaders) {
+ CmdArgs.push_back("-header-include-file");
+ CmdArgs.push_back(D.CCPrintHeadersFilename ?
+ D.CCPrintHeadersFilename : "-");
+ }
+ Args.AddLastArg(CmdArgs, options::OPT_P);
+ Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
+
+ // Special case debug options to only pass -g to clang. This is
+ // wrong.
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("-g");
+
+ Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
+ Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+
+ Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
+ Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
+ Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
+
+ // Pass the path to compiler resource files.
+ CmdArgs.push_back("-resource-dir");
+ CmdArgs.push_back(D.ResourceDir.c_str());
+
+ Args.AddLastArg(CmdArgs, options::OPT_working_directory);
+
+ // Add preprocessing options like -I, -D, etc. if we are using the
+ // preprocessor.
+ //
+ // FIXME: Support -fpreprocessed
+ if (types::getPreprocessedType(InputType) != types::TY_INVALID)
+ AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs);
+
+ // Manually translate -O to -O2 and -O4 to -O3; let clang reject
+ // others.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4))
+ CmdArgs.push_back("-O3");
+ else if (A->getOption().matches(options::OPT_O) &&
+ A->getValue(Args)[0] == '\0')
+ CmdArgs.push_back("-O2");
+ else if (A->getOption().matches(options::OPT_O) &&
+ A->getValue(Args)[0] == 'z' &&
+ A->getValue(Args)[1] == '\0')
+ CmdArgs.push_back("-Os");
+ else
+ A->render(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic);
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+
+ // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
+ // (-ansi is equivalent to -std=c89).
+ //
+ // If a std is supplied, only add -trigraphs if it follows the
+ // option.
+ if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+ if (Std->getOption().matches(options::OPT_ansi))
+ if (types::isCXX(InputType))
+ CmdArgs.push_back("-std=c++98");
+ else
+ CmdArgs.push_back("-std=c89");
+ else
+ Std->render(Args, CmdArgs);
+
+ if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
+ options::OPT_trigraphs))
+ if (A != Std)
+ A->render(Args, CmdArgs);
+ } else {
+ // Honor -std-default.
+ //
+ // FIXME: Clang doesn't correctly handle -std= when the input language
+ // doesn't match. For the time being just ignore this for C++ inputs;
+ // eventually we want to do all the standard defaulting here instead of
+ // splitting it between the driver and clang -cc1.
+ if (!types::isCXX(InputType))
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+ "-std=", /*Joined=*/true);
+ Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
+ }
+
+ // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
+ if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
+ if (Asm->getOption().matches(options::OPT_fasm))
+ CmdArgs.push_back("-fgnu-keywords");
+ else
+ CmdArgs.push_back("-fno-gnu-keywords");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) {
+ CmdArgs.push_back("-ftemplate-depth");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
+ options::OPT_Wlarge_by_value_copy_def)) {
+ CmdArgs.push_back("-Wlarge-by-value-copy");
+ if (A->getNumValues())
+ CmdArgs.push_back(A->getValue(Args));
+ else
+ CmdArgs.push_back("64"); // default value for -Wlarge-by-value-copy.
+ }
+
+ if (Args.hasArg(options::OPT__relocatable_pch))
+ CmdArgs.push_back("-relocatable-pch");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+ CmdArgs.push_back("-fconstant-string-class");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
+ CmdArgs.push_back("-ftabstop");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ CmdArgs.push_back("-ferror-limit");
+ if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
+ CmdArgs.push_back(A->getValue(Args));
+ else
+ CmdArgs.push_back("19");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
+ CmdArgs.push_back("-fmacro-backtrace-limit");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
+ CmdArgs.push_back("-ftemplate-backtrace-limit");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // Pass -fmessage-length=.
+ CmdArgs.push_back("-fmessage-length");
+ if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
+ CmdArgs.push_back(A->getValue(Args));
+ } else {
+ // If -fmessage-length=N was not specified, determine whether this is a
+ // terminal and, if so, implicitly define -fmessage-length appropriately.
+ unsigned N = llvm::sys::Process::StandardErrColumns();
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N)));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) {
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+
+ // -fhosted is default.
+ if (KernelOrKext || Args.hasFlag(options::OPT_ffreestanding,
+ options::OPT_fhosted,
+ false))
+ CmdArgs.push_back("-ffreestanding");
+
+ // Forward -f (flag) options which we can pass directly.
+ Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior);
+ Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
+ Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
+ Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
+ Args.AddLastArg(CmdArgs, options::OPT_pg);
+
+ // -flax-vector-conversions is default.
+ if (!Args.hasFlag(options::OPT_flax_vector_conversions,
+ options::OPT_fno_lax_vector_conversions))
+ CmdArgs.push_back("-fno-lax-vector-conversions");
+
+ // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
+ // takes precedence.
+ const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
+ if (!GCArg)
+ GCArg = Args.getLastArg(options::OPT_fobjc_gc);
+ if (GCArg) {
+ if (getToolChain().SupportsObjCGC()) {
+ GCArg->render(Args, CmdArgs);
+ } else {
+ // FIXME: We should move this to a hard error.
+ D.Diag(clang::diag::warn_drv_objc_gc_unsupported)
+ << GCArg->getAsString(Args);
+ }
+ }
+
+ if (Args.getLastArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-fapple-kext");
+
+ Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
+ Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
+ Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
+ Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
+ CmdArgs.push_back("-ftrapv-handler");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fwrapv);
+ Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
+ Args.AddLastArg(CmdArgs, options::OPT_funroll_loops);
+
+ Args.AddLastArg(CmdArgs, options::OPT_pthread);
+
+ // -stack-protector=0 is default.
+ unsigned StackProtectorLevel = 0;
+ if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+ options::OPT_fstack_protector_all,
+ options::OPT_fstack_protector)) {
+ if (A->getOption().matches(options::OPT_fstack_protector))
+ StackProtectorLevel = 1;
+ else if (A->getOption().matches(options::OPT_fstack_protector_all))
+ StackProtectorLevel = 2;
+ } else
+ StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel();
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector");
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine(StackProtectorLevel)));
+ }
+
+ // Forward -f options with positive and negative forms; we translate
+ // these by hand.
+
+ if (Args.hasArg(options::OPT_mkernel)) {
+ if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
+ CmdArgs.push_back("-fapple-kext");
+ if (!Args.hasArg(options::OPT_fbuiltin))
+ CmdArgs.push_back("-fno-builtin");
+ }
+ // -fbuiltin is default.
+ else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
+ CmdArgs.push_back("-fno-builtin");
+
+ if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new))
+ CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+ // -fblocks=0 is default.
+ if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
+ getToolChain().IsBlocksDefault())) {
+ CmdArgs.push_back("-fblocks");
+ }
+
+ // -faccess-control is default.
+ if (Args.hasFlag(options::OPT_fno_access_control,
+ options::OPT_faccess_control,
+ false))
+ CmdArgs.push_back("-fno-access-control");
+
+ // -felide-constructors is the default.
+ if (Args.hasFlag(options::OPT_fno_elide_constructors,
+ options::OPT_felide_constructors,
+ false))
+ CmdArgs.push_back("-fno-elide-constructors");
+
+ // -fexceptions=0 is default.
+ if (!KernelOrKext &&
+ needsExceptions(Args, InputType, getToolChain().getTriple()))
+ CmdArgs.push_back("-fexceptions");
+
+ if (getToolChain().UseSjLjExceptions())
+ CmdArgs.push_back("-fsjlj-exceptions");
+
+ // -frtti is default.
+ if (KernelOrKext ||
+ !Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
+ CmdArgs.push_back("-fno-rtti");
+
+ // -fshort-enums=0 is default.
+ // FIXME: Are there targers where -fshort-enums is on by default ?
+ if (Args.hasFlag(options::OPT_fshort_enums,
+ options::OPT_fno_short_enums, false))
+ CmdArgs.push_back("-fshort-enums");
+
+ // -fsigned-char is default.
+ if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
+ isSignedCharDefault(getToolChain().getTriple())))
+ CmdArgs.push_back("-fno-signed-char");
+
+ // -fthreadsafe-static is default.
+ if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
+ options::OPT_fno_threadsafe_statics))
+ CmdArgs.push_back("-fno-threadsafe-statics");
+
+ // -fuse-cxa-atexit is default.
+ if (KernelOrKext ||
+ !Args.hasFlag(options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
+ getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
+ getToolChain().getTriple().getOS() != llvm::Triple::MinGW32))
+ CmdArgs.push_back("-fno-use-cxa-atexit");
+
+ // -fms-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ getToolChain().getTriple().getOS() == llvm::Triple::Win32))
+ CmdArgs.push_back("-fms-extensions");
+
+ // -fmsc-version=1300 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
+ Args.hasArg(options::OPT_fmsc_version)) {
+ llvm::StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
+ if (msc_ver.empty())
+ CmdArgs.push_back("-fmsc-version=1300");
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
+ }
+
+
+ // -fborland-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fborland_extensions,
+ options::OPT_fno_borland_extensions, false))
+ CmdArgs.push_back("-fborland-extensions");
+
+ // -fgnu-keywords default varies depending on language; only pass if
+ // specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
+ options::OPT_fno_gnu_keywords))
+ A->render(Args, CmdArgs);
+
+ // -fnext-runtime defaults to on Darwin and when rewriting Objective-C, and is
+ // -the -cc1 default.
+ bool NeXTRuntimeIsDefault =
+ IsRewriter || getToolChain().getTriple().getOS() == llvm::Triple::Darwin;
+ if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
+ NeXTRuntimeIsDefault))
+ CmdArgs.push_back("-fgnu-runtime");
+
+ // -fobjc-nonfragile-abi=0 is default.
+ if (types::isObjC(InputType)) {
+ // Compute the Objective-C ABI "version" to use. Version numbers are
+ // slightly confusing for historical reasons:
+ // 1 - Traditional "fragile" ABI
+ // 2 - Non-fragile ABI, version 1
+ // 3 - Non-fragile ABI, version 2
+ unsigned Version = 1;
+ // If -fobjc-abi-version= is present, use that to set the version.
+ if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
+ if (llvm::StringRef(A->getValue(Args)) == "1")
+ Version = 1;
+ else if (llvm::StringRef(A->getValue(Args)) == "2")
+ Version = 2;
+ else if (llvm::StringRef(A->getValue(Args)) == "3")
+ Version = 3;
+ else
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ } else {
+ // Otherwise, determine if we are using the non-fragile ABI.
+ if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi,
+ options::OPT_fno_objc_nonfragile_abi,
+ getToolChain().IsObjCNonFragileABIDefault())) {
+ // Determine the non-fragile ABI version to use.
+#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
+ unsigned NonFragileABIVersion = 1;
+#else
+ unsigned NonFragileABIVersion = 2;
+#endif
+
+ if (Arg *A = Args.getLastArg(
+ options::OPT_fobjc_nonfragile_abi_version_EQ)) {
+ if (llvm::StringRef(A->getValue(Args)) == "1")
+ NonFragileABIVersion = 1;
+ else if (llvm::StringRef(A->getValue(Args)) == "2")
+ NonFragileABIVersion = 2;
+ else
+ D.Diag(clang::diag::err_drv_clang_unsupported)
+ << A->getAsString(Args);
+ }
+
+ Version = 1 + NonFragileABIVersion;
+ } else {
+ Version = 1;
+ }
+ }
+
+ if (Version == 2 || Version == 3) {
+ CmdArgs.push_back("-fobjc-nonfragile-abi");
+
+ // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
+ // legacy is the default.
+ if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
+ options::OPT_fno_objc_legacy_dispatch,
+ getToolChain().IsObjCLegacyDispatchDefault())) {
+ if (getToolChain().UseObjCMixedDispatch())
+ CmdArgs.push_back("-fobjc-dispatch-method=mixed");
+ else
+ CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
+ }
+ }
+
+ // -fobjc-default-synthesize-properties=0 is default.
+ if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties,
+ options::OPT_fno_objc_default_synthesize_properties,
+ getToolChain().IsObjCDefaultSynthPropertiesDefault())) {
+ CmdArgs.push_back("-fobjc-default-synthesize-properties");
+ }
+
+ // -fobjc-exceptions is default.
+ if (!Args.hasFlag(options::OPT_fobjc_exceptions,
+ options::OPT_fno_objc_exceptions))
+ CmdArgs.push_back("-fno-objc-exceptions");
+ }
+
+ if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new))
+ CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+ // -fconstant-cfstrings is default, and may be subject to argument translation
+ // on Darwin.
+ if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
+ options::OPT_fno_constant_cfstrings) ||
+ !Args.hasFlag(options::OPT_mconstant_cfstrings,
+ options::OPT_mno_constant_cfstrings))
+ CmdArgs.push_back("-fno-constant-cfstrings");
+
+ // -fshort-wchar default varies depending on platform; only
+ // pass if specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
+ A->render(Args, CmdArgs);
+
+ // -fno-pascal-strings is default, only pass non-default. If the tool chain
+ // happened to translate to -mpascal-strings, we want to back translate here.
+ //
+ // FIXME: This is gross; that translation should be pulled from the
+ // tool chain.
+ if (Args.hasFlag(options::OPT_fpascal_strings,
+ options::OPT_fno_pascal_strings,
+ false) ||
+ Args.hasFlag(options::OPT_mpascal_strings,
+ options::OPT_mno_pascal_strings,
+ false))
+ CmdArgs.push_back("-fpascal-strings");
+
+ if (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext)) {
+ if (!Args.hasArg(options::OPT_fcommon))
+ CmdArgs.push_back("-fno-common");
+ }
+ // -fcommon is default, only pass non-default.
+ else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
+ CmdArgs.push_back("-fno-common");
+
+ // -fsigned-bitfields is default, and clang doesn't yet support
+ // -funsigned-bitfields.
+ if (!Args.hasFlag(options::OPT_fsigned_bitfields,
+ options::OPT_funsigned_bitfields))
+ D.Diag(clang::diag::warn_drv_clang_unsupported)
+ << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
+
+ // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
+ if (!Args.hasFlag(options::OPT_ffor_scope,
+ options::OPT_fno_for_scope))
+ D.Diag(clang::diag::err_drv_clang_unsupported)
+ << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
+
+ // -fcaret-diagnostics is default.
+ if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
+ options::OPT_fno_caret_diagnostics, true))
+ CmdArgs.push_back("-fno-caret-diagnostics");
+
+ // -fdiagnostics-fixit-info is default, only pass non-default.
+ if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
+ options::OPT_fno_diagnostics_fixit_info))
+ CmdArgs.push_back("-fno-diagnostics-fixit-info");
+
+ // Enable -fdiagnostics-show-option by default.
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option))
+ CmdArgs.push_back("-fdiagnostics-show-option");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-show-category");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ // Color diagnostics are the default, unless the terminal doesn't support
+ // them.
+ if (Args.hasFlag(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics,
+ llvm::sys::Process::StandardErrHasColors()))
+ CmdArgs.push_back("-fcolor-diagnostics");
+
+ if (!Args.hasFlag(options::OPT_fshow_source_location,
+ options::OPT_fno_show_source_location))
+ CmdArgs.push_back("-fno-show-source-location");
+
+ if (!Args.hasFlag(options::OPT_fspell_checking,
+ options::OPT_fno_spell_checking))
+ CmdArgs.push_back("-fno-spell-checking");
+
+
+ // Silently ignore -fasm-blocks for now.
+ (void) Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
+ false);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
+ A->render(Args, CmdArgs);
+
+ // -fdollars-in-identifiers default varies depending on platform and
+ // language; only pass if specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
+ options::OPT_fno_dollars_in_identifiers)) {
+ if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
+ CmdArgs.push_back("-fdollars-in-identifiers");
+ else
+ CmdArgs.push_back("-fno-dollars-in-identifiers");
+ }
+
+ // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
+ // practical purposes.
+ if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
+ options::OPT_fno_unit_at_a_time)) {
+ if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
+ D.Diag(clang::diag::warn_drv_clang_unsupported) << A->getAsString(Args);
+ }
+
+ // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
+ //
+ // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
+#if 0
+ if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
+ (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
+ if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+ CmdArgs.push_back("-fno-builtin-strcat");
+ if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+ CmdArgs.push_back("-fno-builtin-strcpy");
+ }
+#endif
+
+ if (Arg *A = Args.getLastArg(options::OPT_traditional,
+ options::OPT_traditional_cpp))
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
+ Args.AddLastArg(CmdArgs, options::OPT_dM);
+ Args.AddLastArg(CmdArgs, options::OPT_dD);
+
+ // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
+ // parser.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
+ for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+
+ // We translate this by hand to the -cc1 argument, since nightly test uses
+ // it and developers have been trained to spell it with -mllvm.
+ if (llvm::StringRef((*it)->getValue(Args, 0)) == "-disable-llvm-optzns")
+ CmdArgs.push_back("-disable-llvm-optzns");
+ else
+ (*it)->render(Args, CmdArgs);
+ }
+
+ if (Output.getType() == types::TY_Dependencies) {
+ // Handled with other dependency code.
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back("-x");
+ CmdArgs.push_back(types::getTypeName(II.getType()));
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+
+ // Optionally embed the -cc1 level arguments into the debug info, for build
+ // analysis.
+ if (getToolChain().UseDwarfDebugFlags()) {
+ ArgStringList OriginalArgs;
+ for (ArgList::const_iterator it = Args.begin(),
+ ie = Args.end(); it != ie; ++it)
+ (*it)->render(Args, OriginalArgs);
+
+ llvm::SmallString<256> Flags;
+ Flags += Exec;
+ for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+ Flags += " ";
+ Flags += OriginalArgs[i];
+ }
+ CmdArgs.push_back("-dwarf-debug-flags");
+ CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+ }
+
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ if (Arg *A = Args.getLastArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << "-fomit-frame-pointer" << A->getAsString(Args);
+
+ // Claim some arguments which clang supports automatically.
+
+ // -fpch-preprocess is used with gcc to add a special marker in the output to
+ // include the PCH file. Clang's PTH solution is completely transparent, so we
+ // do not need to deal with it at all.
+ Args.ClaimAllArgs(options::OPT_fpch_preprocess);
+
+ // Claim some arguments which clang doesn't support, but we don't
+ // care to warn the user about.
+ Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
+ Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
+}
+
+void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+
+ // Don't warn about "clang -w -c foo.s"
+ Args.ClaimAllArgs(options::OPT_w);
+
+ // Invoke ourselves in -cc1as mode.
+ //
+ // FIXME: Implement custom jobs for internal actions.
+ CmdArgs.push_back("-cc1as");
+
+ // Add the "effective" target triple.
+ CmdArgs.push_back("-triple");
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ // Set the output mode, we currently only expect to be used as a real
+ // assembler.
+ CmdArgs.push_back("-filetype");
+ CmdArgs.push_back("obj");
+
+ // At -O0, we use -mrelax-all by default.
+ bool IsOpt = false;
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ IsOpt = !A->getOption().matches(options::OPT_O0);
+ if (Args.hasFlag(options::OPT_mrelax_all,
+ options::OPT_mno_relax_all,
+ !IsOpt))
+ CmdArgs.push_back("-relax-all");
+
+ // FIXME: Add -force_cpusubtype_ALL support, once we have it.
+
+ // FIXME: Add -g support, once we have it.
+
+ // FIXME: Add -static support, once we have it.
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ assert(Output.isFilename() && "Unexpected lipo output.");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ for (ArgList::const_iterator
+ it = Args.begin(), ie = Args.end(); it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().hasForwardToGCC()) {
+ // Don't forward any -g arguments to assembly steps.
+ if (isa<AssembleJobAction>(JA) &&
+ A->getOption().matches(options::OPT_g_Group))
+ continue;
+
+ // It is unfortunate that we have to claim here, as this means
+ // we will basically never report anything interesting for
+ // platforms using a generic gcc, even if we are just using gcc
+ // to get to the assembler.
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ RenderExtraToolArgs(JA, CmdArgs);
+
+ // If using a driver driver, force the arch.
+ const std::string &Arch = getToolChain().getArchName();
+ if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin) {
+ CmdArgs.push_back("-arch");
+
+ // FIXME: Remove these special cases.
+ if (Arch == "powerpc")
+ CmdArgs.push_back("ppc");
+ else if (Arch == "powerpc64")
+ CmdArgs.push_back("ppc64");
+ else
+ CmdArgs.push_back(Args.MakeArgString(Arch));
+ }
+
+ // Try to force gcc to match the tool chain we want, if we recognize
+ // the arch.
+ //
+ // FIXME: The triple class should directly provide the information we want
+ // here.
+ if (Arch == "i386" || Arch == "powerpc")
+ CmdArgs.push_back("-m32");
+ else if (Arch == "x86_64" || Arch == "powerpc64")
+ CmdArgs.push_back("-m64");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Unexpected output");
+ CmdArgs.push_back("-fsyntax-only");
+ }
+
+
+ // Only pass -x if gcc will understand it; otherwise hope gcc
+ // understands the suffix correctly. The main use case this would go
+ // wrong in is for linker inputs if they happened to have an odd
+ // suffix; really the only way to get this to happen is a command
+ // like '-x foobar a.c' which will treat a.c like a linker input.
+ //
+ // FIXME: For the linker case specifically, can we safely convert
+ // inputs into '-Wl,' options?
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ // Don't try to pass LLVM or AST inputs to a generic gcc.
+ if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_AST)
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+
+ if (types::canTypeBeUserSpecified(II.getType())) {
+ CmdArgs.push_back("-x");
+ CmdArgs.push_back(types::getTypeName(II.getType()));
+ }
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else {
+ const Arg &A = II.getInputArg();
+
+ // Reverse translate some rewritten options.
+ if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
+ CmdArgs.push_back("-lstdc++");
+ continue;
+ }
+
+ // Don't render as input, we need gcc to do the translations.
+ A.render(Args, CmdArgs);
+ }
+ }
+
+ const char *GCCName = getToolChain().getDriver().getCCCGenericGCCName().c_str();
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-E");
+}
+
+void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ // The type is good enough.
+}
+
+void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ // If -flto, etc. are present then make sure not to force assembly output.
+ if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
+ JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
+ CmdArgs.push_back("-c");
+ else {
+ if (JA.getType() != types::TY_PP_Asm)
+ D.Diag(clang::diag::err_drv_invalid_gcc_output_type)
+ << getTypeName(JA.getType());
+
+ CmdArgs.push_back("-S");
+ }
+}
+
+void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-c");
+}
+
+void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ // The types are (hopefully) good enough.
+}
+
+const char *darwin::CC1::getCC1Name(types::ID Type) const {
+ switch (Type) {
+ default:
+ assert(0 && "Unexpected type for Darwin CC1 tool.");
+ case types::TY_Asm:
+ case types::TY_C: case types::TY_CHeader:
+ case types::TY_PP_C: case types::TY_PP_CHeader:
+ return "cc1";
+ case types::TY_ObjC: case types::TY_ObjCHeader:
+ case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
+ return "cc1obj";
+ case types::TY_CXX: case types::TY_CXXHeader:
+ case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
+ return "cc1plus";
+ case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
+ case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
+ return "cc1objplus";
+ }
+}
+
+const char *darwin::CC1::getBaseInputName(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ return Args.MakeArgString(
+ llvm::sys::path::filename(Inputs[0].getBaseInput()));
+}
+
+const char *darwin::CC1::getBaseInputStem(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ const char *Str = getBaseInputName(Args, Inputs);
+
+ if (const char *End = strrchr(Str, '.'))
+ return Args.MakeArgString(std::string(Str, End));
+
+ return Str;
+}
+
+const char *
+darwin::CC1::getDependencyFileName(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ // FIXME: Think about this more.
+ std::string Res;
+
+ if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+ std::string Str(OutputOpt->getValue(Args));
+
+ Res = Str.substr(0, Str.rfind('.'));
+ } else
+ Res = darwin::CC1::getBaseInputStem(Args, Inputs);
+
+ return Args.MakeArgString(Res + ".d");
+}
+
+void darwin::CC1::AddCC1Args(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ CheckCodeGenerationOptions(D, Args);
+
+ // Derived from cc1 spec.
+ if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) &&
+ !Args.hasArg(options::OPT_mdynamic_no_pic))
+ CmdArgs.push_back("-fPIC");
+
+ if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+ if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+ CmdArgs.push_back("-fno-builtin-strcat");
+ if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+ CmdArgs.push_back("-fno-builtin-strcpy");
+ }
+
+ // gcc has some code here to deal with when no -mmacosx-version-min
+ // and no -miphoneos-version-min is present, but this never happens
+ // due to tool chain specific argument translation.
+
+ if (Args.hasArg(options::OPT_g_Flag) &&
+ !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols))
+ CmdArgs.push_back("-feliminate-unused-debug-symbols");
+}
+
+void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ const InputInfoList &Inputs,
+ const ArgStringList &OutputArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ // Derived from cc1_options spec.
+ if (Args.hasArg(options::OPT_fast) ||
+ Args.hasArg(options::OPT_fastf) ||
+ Args.hasArg(options::OPT_fastcp))
+ CmdArgs.push_back("-O3");
+
+ if (Arg *A = Args.getLastArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fomit-frame-pointer";
+
+ AddCC1Args(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_Q))
+ CmdArgs.push_back("-quiet");
+
+ CmdArgs.push_back("-dumpbase");
+ CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_a_Group);
+
+ // FIXME: The goal is to use the user provided -o if that is our
+ // final output, otherwise to drive from the original input
+ // name. Find a clean way to go about this.
+ if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
+ Args.hasArg(options::OPT_o)) {
+ Arg *OutputOpt = Args.getLastArg(options::OPT_o);
+ CmdArgs.push_back("-auxbase-strip");
+ CmdArgs.push_back(OutputOpt->getValue(Args));
+ } else {
+ CmdArgs.push_back("-auxbase");
+ CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_g_Group);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_O);
+ // FIXME: -Wall is getting some special treatment. Investigate.
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+ Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
+ options::OPT_trigraphs);
+ if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+ // Honor -std-default.
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+ "-std=", /*Joined=*/true);
+ }
+
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-version");
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-p");
+ Args.AddLastArg(CmdArgs, options::OPT_p);
+
+ // The driver treats -fsyntax-only specially.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+ // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are
+ // used to inhibit the default -fno-builtin-str{cat,cpy}.
+ //
+ // FIXME: Should we grow a better way to deal with "removing" args?
+ for (arg_iterator it = Args.filtered_begin(options::OPT_f_Group,
+ options::OPT_fsyntax_only),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ if (!(*it)->getOption().matches(options::OPT_fbuiltin_strcat) &&
+ !(*it)->getOption().matches(options::OPT_fbuiltin_strcpy)) {
+ (*it)->claim();
+ (*it)->render(Args, CmdArgs);
+ }
+ }
+ } else
+ Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+ if (Args.hasArg(options::OPT_Qn))
+ CmdArgs.push_back("-fno-ident");
+
+ // FIXME: This isn't correct.
+ //Args.AddLastArg(CmdArgs, options::OPT__help)
+ //Args.AddLastArg(CmdArgs, options::OPT__targetHelp)
+
+ CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+
+ // FIXME: Still don't get what is happening here. Investigate.
+ Args.AddAllArgs(CmdArgs, options::OPT__param);
+
+ if (Args.hasArg(options::OPT_fmudflap) ||
+ Args.hasArg(options::OPT_fmudflapth)) {
+ CmdArgs.push_back("-fno-builtin");
+ CmdArgs.push_back("-fno-merge-constants");
+ }
+
+ if (Args.hasArg(options::OPT_coverage)) {
+ CmdArgs.push_back("-fprofile-arcs");
+ CmdArgs.push_back("-ftest-coverage");
+ }
+
+ if (types::isCXX(Inputs[0].getType()))
+ CmdArgs.push_back("-D__private_extern__=extern");
+}
+
+void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ const InputInfoList &Inputs,
+ const ArgStringList &OutputArgs) const {
+ // Derived from cpp_options
+ AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
+
+ CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+
+ AddCC1Args(Args, CmdArgs);
+
+ // NOTE: The code below has some commonality with cpp_options, but
+ // in classic gcc style ends up sending things in different
+ // orders. This may be a good merge candidate once we drop pedantic
+ // compatibility.
+
+ Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
+ options::OPT_trigraphs);
+ if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+ // Honor -std-default.
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+ "-std=", /*Joined=*/true);
+ }
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+
+ // The driver treats -fsyntax-only specially.
+ Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
+
+ if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) &&
+ !Args.hasArg(options::OPT_fno_working_directory))
+ CmdArgs.push_back("-fworking-directory");
+
+ Args.AddAllArgs(CmdArgs, options::OPT_O);
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+ if (Args.hasArg(options::OPT_save_temps))
+ CmdArgs.push_back("-fpch-preprocess");
+}
+
+void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ CheckPreprocessingOptions(D, Args);
+
+ // Derived from cpp_unique_options.
+ // -{C,CC} only with -E is checked in CheckPreprocessingOptions().
+ Args.AddLastArg(CmdArgs, options::OPT_C);
+ Args.AddLastArg(CmdArgs, options::OPT_CC);
+ if (!Args.hasArg(options::OPT_Q))
+ CmdArgs.push_back("-quiet");
+ Args.AddAllArgs(CmdArgs, options::OPT_nostdinc);
+ Args.AddAllArgs(CmdArgs, options::OPT_nostdincxx);
+ Args.AddLastArg(CmdArgs, options::OPT_v);
+ Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
+ Args.AddLastArg(CmdArgs, options::OPT_P);
+
+ // FIXME: Handle %I properly.
+ if (getToolChain().getArchName() == "x86_64") {
+ CmdArgs.push_back("-imultilib");
+ CmdArgs.push_back("x86_64");
+ }
+
+ if (Args.hasArg(options::OPT_MD)) {
+ CmdArgs.push_back("-MD");
+ CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
+ }
+
+ if (Args.hasArg(options::OPT_MMD)) {
+ CmdArgs.push_back("-MMD");
+ CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_M);
+ Args.AddLastArg(CmdArgs, options::OPT_MM);
+ Args.AddAllArgs(CmdArgs, options::OPT_MF);
+ Args.AddLastArg(CmdArgs, options::OPT_MG);
+ Args.AddLastArg(CmdArgs, options::OPT_MP);
+ Args.AddAllArgs(CmdArgs, options::OPT_MQ);
+ Args.AddAllArgs(CmdArgs, options::OPT_MT);
+ if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) &&
+ (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) {
+ if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+ CmdArgs.push_back("-MQ");
+ CmdArgs.push_back(OutputOpt->getValue(Args));
+ }
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_remap);
+ if (Args.hasArg(options::OPT_g3))
+ CmdArgs.push_back("-dD");
+ Args.AddLastArg(CmdArgs, options::OPT_H);
+
+ AddCPPArgs(Args, CmdArgs);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A);
+ Args.AddAllArgs(CmdArgs, options::OPT_i_Group);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
+ options::OPT_Xpreprocessor);
+
+ if (Args.hasArg(options::OPT_fmudflap)) {
+ CmdArgs.push_back("-D_MUDFLAP");
+ CmdArgs.push_back("-include");
+ CmdArgs.push_back("mf-runtime.h");
+ }
+
+ if (Args.hasArg(options::OPT_fmudflapth)) {
+ CmdArgs.push_back("-D_MUDFLAP");
+ CmdArgs.push_back("-D_MUDFLAPTH");
+ CmdArgs.push_back("-include");
+ CmdArgs.push_back("mf-runtime.h");
+ }
+}
+
+void darwin::CC1::AddCPPArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Derived from cpp spec.
+
+ if (Args.hasArg(options::OPT_static)) {
+ // The gcc spec is broken here, it refers to dynamic but
+ // that has been translated. Start by being bug compatible.
+
+ // if (!Args.hasArg(arglist.parser.dynamicOption))
+ CmdArgs.push_back("-D__STATIC__");
+ } else
+ CmdArgs.push_back("-D__DYNAMIC__");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-D_REENTRANT");
+}
+
+void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs!");
+
+ CmdArgs.push_back("-E");
+
+ if (Args.hasArg(options::OPT_traditional) ||
+ Args.hasArg(options::OPT_traditional_cpp))
+ CmdArgs.push_back("-traditional-cpp");
+
+ ArgStringList OutputArgs;
+ assert(Output.isFilename() && "Unexpected CC1 output.");
+ OutputArgs.push_back("-o");
+ OutputArgs.push_back(Output.getFilename());
+
+ if (Args.hasArg(options::OPT_E)) {
+ AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+ } else {
+ AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+ CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
+
+ const char *CC1Name = getCC1Name(Inputs[0].getType());
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs!");
+
+ types::ID InputType = Inputs[0].getType();
+ const Arg *A;
+ if ((A = Args.getLastArg(options::OPT_traditional)))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-E";
+
+ if (JA.getType() == types::TY_LLVM_IR ||
+ JA.getType() == types::TY_LTO_IR)
+ CmdArgs.push_back("-emit-llvm");
+ else if (JA.getType() == types::TY_LLVM_BC ||
+ JA.getType() == types::TY_LTO_BC)
+ CmdArgs.push_back("-emit-llvm-bc");
+ else if (Output.getType() == types::TY_AST)
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+ else if (JA.getType() != types::TY_PP_Asm &&
+ JA.getType() != types::TY_PCH)
+ D.Diag(clang::diag::err_drv_invalid_gcc_output_type)
+ << getTypeName(JA.getType());
+
+ ArgStringList OutputArgs;
+ if (Output.getType() != types::TY_PCH) {
+ OutputArgs.push_back("-o");
+ if (Output.isNothing())
+ OutputArgs.push_back("/dev/null");
+ else
+ OutputArgs.push_back(Output.getFilename());
+ }
+
+ // There is no need for this level of compatibility, but it makes
+ // diffing easier.
+ bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) ||
+ Args.hasArg(options::OPT_S));
+
+ if (types::getPreprocessedType(InputType) != types::TY_INVALID) {
+ AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
+ if (OutputArgsEarly) {
+ AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+ } else {
+ AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+ CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+ }
+ } else {
+ CmdArgs.push_back("-fpreprocessed");
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ // Reject AST inputs.
+ if (II.getType() == types::TY_AST) {
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+ return;
+ }
+
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ if (OutputArgsEarly) {
+ AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+ } else {
+ AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+ CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+ }
+ }
+
+ if (Output.getType() == types::TY_PCH) {
+ assert(Output.isFilename() && "Invalid PCH output.");
+
+ CmdArgs.push_back("-o");
+ // NOTE: gcc uses a temp .s file for this, but there doesn't seem
+ // to be a good reason.
+ CmdArgs.push_back("/dev/null");
+
+ CmdArgs.push_back("--output-pch=");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ const char *CC1Name = getCC1Name(Inputs[0].getType());
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+
+ // Bit of a hack, this is only used for original inputs.
+ //
+ // FIXME: This is broken for preprocessed .s inputs.
+ if (Input.isFilename() &&
+ strcmp(Input.getFilename(), Input.getBaseInput()) == 0) {
+ if (Args.hasArg(options::OPT_gstabs))
+ CmdArgs.push_back("--gstabs");
+ else if (Args.hasArg(options::OPT_g_Group))
+ CmdArgs.push_back("--gdwarf2");
+ }
+
+ // Derived from asm spec.
+ AddDarwinArch(Args, CmdArgs);
+
+ // Use -force_cpusubtype_ALL on x86 by default.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
+ Args.hasArg(options::OPT_force__cpusubtype__ALL))
+ CmdArgs.push_back("-force_cpusubtype_ALL");
+
+ if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
+ (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_fapple_kext)))
+ CmdArgs.push_back("-static");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ assert(Output.isFilename() && "Unexpected lipo output.");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ // asm_final spec is empty.
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
+
+ // Derived from darwin_arch spec.
+ CmdArgs.push_back("-arch");
+ CmdArgs.push_back(Args.MakeArgString(ArchName));
+
+ // FIXME: Is this needed anymore?
+ if (ArchName == "arm")
+ CmdArgs.push_back("-force_cpusubtype_ALL");
+}
+
+void darwin::Link::AddLinkArgs(Compilation &C,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ unsigned Version[3] = { 0, 0, 0 };
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Version[0],
+ Version[1], Version[2], HadExtra) ||
+ HadExtra)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ }
+
+ // Newer linkers support -demangle, pass it if supported and not disabled by
+ // the user.
+ //
+ // FIXME: We temporarily avoid passing -demangle to any iOS linker, because
+ // unfortunately we can't be guaranteed that the linker version used there
+ // will match the linker version detected at configure time. We need the
+ // universal driver.
+ if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle) &&
+ !getDarwinToolChain().isTargetIPhoneOS()) {
+ // Don't pass -demangle to ld_classic.
+ //
+ // FIXME: This is a temporary workaround, ld should be handling this.
+ bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 &&
+ Args.hasArg(options::OPT_static));
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker,
+ options::OPT_Wl_COMMA),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
+ if (llvm::StringRef(A->getValue(Args, i)) == "-kext")
+ UsesLdClassic = true;
+ }
+ }
+ if (!UsesLdClassic)
+ CmdArgs.push_back("-demangle");
+ }
+
+ // Derived from the "link" spec.
+ Args.AddAllArgs(CmdArgs, options::OPT_static);
+ if (!Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-dynamic");
+ if (Args.hasArg(options::OPT_fgnu_runtime)) {
+ // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
+ // here. How do we wish to handle such things?
+ }
+
+ if (!Args.hasArg(options::OPT_dynamiclib)) {
+ AddDarwinArch(Args, CmdArgs);
+ // FIXME: Why do this only on this path?
+ Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
+
+ Args.AddLastArg(CmdArgs, options::OPT_bundle);
+ Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
+ Args.AddAllArgs(CmdArgs, options::OPT_client__name);
+
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
+ (A = Args.getLastArg(options::OPT_current__version)) ||
+ (A = Args.getLastArg(options::OPT_install__name)))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-dynamiclib";
+
+ Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
+ Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
+ Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
+ } else {
+ CmdArgs.push_back("-dylib");
+
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_bundle)) ||
+ (A = Args.getLastArg(options::OPT_bundle__loader)) ||
+ (A = Args.getLastArg(options::OPT_client__name)) ||
+ (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
+ (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
+ (A = Args.getLastArg(options::OPT_private__bundle)))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-dynamiclib";
+
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
+ "-dylib_compatibility_version");
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
+ "-dylib_current_version");
+
+ AddDarwinArch(Args, CmdArgs);
+
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
+ "-dylib_install_name");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_all__load);
+ Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
+ Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
+ if (getDarwinToolChain().isTargetIPhoneOS())
+ Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
+ Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
+ Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
+ Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
+ Args.AddLastArg(CmdArgs, options::OPT_dynamic);
+ Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
+ Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
+ Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
+ Args.AddAllArgs(CmdArgs, options::OPT_image__base);
+ Args.AddAllArgs(CmdArgs, options::OPT_init);
+
+ // Adding all arguments doesn't make sense here but this is what gcc does. One
+ // of this should always be present thanks to argument translation.
+ assert((Args.hasArg(options::OPT_mmacosx_version_min_EQ) ||
+ Args.hasArg(options::OPT_miphoneos_version_min_EQ)) &&
+ "Missing version argument (lost in translation)?");
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
+ "-macosx_version_min");
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
+ "-iphoneos_version_min");
+ Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
+ Args.AddLastArg(CmdArgs, options::OPT_multi__module);
+ Args.AddLastArg(CmdArgs, options::OPT_single__module);
+ Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
+ Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
+ options::OPT_fno_pie,
+ options::OPT_fno_PIE)) {
+ if (A->getOption().matches(options::OPT_fpie) ||
+ A->getOption().matches(options::OPT_fPIE))
+ CmdArgs.push_back("-pie");
+ else
+ CmdArgs.push_back("-no_pie");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_prebind);
+ Args.AddLastArg(CmdArgs, options::OPT_noprebind);
+ Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
+ Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
+ Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segprot);
+ Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
+ Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
+ Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
+
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_isysroot, "-syslibroot");
+ if (getDarwinToolChain().isTargetIPhoneOS()) {
+ if (!Args.hasArg(options::OPT_isysroot)) {
+ CmdArgs.push_back("-syslibroot");
+ CmdArgs.push_back("/Developer/SDKs/Extra");
+ }
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
+ Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
+ Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
+ Args.AddAllArgs(CmdArgs, options::OPT_undefined);
+ Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
+ Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
+ Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_y);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+ Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
+ Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
+ Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
+ Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
+ Args.AddLastArg(CmdArgs, options::OPT_whyload);
+ Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
+ Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
+ Args.AddLastArg(CmdArgs, options::OPT_dylinker);
+ Args.AddLastArg(CmdArgs, options::OPT_Mach);
+}
+
+void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
+
+ // The logic here is derived from gcc's behavior; most of which
+ // comes from specs (starting with link_command). Consult gcc for
+ // more information.
+ ArgStringList CmdArgs;
+
+ // I'm not sure why this particular decomposition exists in gcc, but
+ // we follow suite for ease of comparison.
+ AddLinkArgs(C, Args, CmdArgs);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_A);
+ Args.AddLastArg(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
+ // members of static archive libraries which implement Objective-C classes or
+ // categories.
+ if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
+ CmdArgs.push_back("-ObjC");
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_A) &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ // Derived from startfile spec.
+ if (Args.hasArg(options::OPT_dynamiclib)) {
+ // Derived from darwin_dylib1 spec.
+ if (getDarwinToolChain().isTargetIPhoneOS()) {
+ if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-ldylib1.o");
+ } else {
+ if (getDarwinToolChain().isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-ldylib1.o");
+ else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-ldylib1.10.5.o");
+ }
+ } else {
+ if (Args.hasArg(options::OPT_bundle)) {
+ if (!Args.hasArg(options::OPT_static)) {
+ // Derived from darwin_bundle1 spec.
+ if (getDarwinToolChain().isTargetIPhoneOS()) {
+ if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-lbundle1.o");
+ } else {
+ if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lbundle1.o");
+ }
+ }
+ } else {
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload)) {
+ CmdArgs.push_back("-lgcrt0.o");
+ } else {
+ CmdArgs.push_back("-lgcrt1.o");
+
+ // darwin_crt2 spec is empty.
+ }
+ } else {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload)) {
+ CmdArgs.push_back("-lcrt0.o");
+ } else {
+ // Derived from darwin_crt1 spec.
+ if (getDarwinToolChain().isTargetIPhoneOS()) {
+ if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-lcrt1.o");
+ else
+ CmdArgs.push_back("-lcrt1.3.1.o");
+ } else {
+ if (getDarwinToolChain().isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lcrt1.o");
+ else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lcrt1.10.5.o");
+ else
+ CmdArgs.push_back("-lcrt1.10.6.o");
+
+ // darwin_crt2 spec is empty.
+ }
+ }
+ }
+ }
+ }
+
+ if (!getDarwinToolChain().isTargetIPhoneOS() &&
+ Args.hasArg(options::OPT_shared_libgcc) &&
+ getDarwinToolChain().isMacosxVersionLT(10, 5)) {
+ const char *Str =
+ Args.MakeArgString(getToolChain().GetFilePath("crt3.o"));
+ CmdArgs.push_back(Str);
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+
+ if (Args.hasArg(options::OPT_fopenmp))
+ // This is more complicated in gcc...
+ CmdArgs.push_back("-lgomp");
+
+ getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (LinkingOutput) {
+ CmdArgs.push_back("-arch_multiple");
+ CmdArgs.push_back("-final_output");
+ CmdArgs.push_back(LinkingOutput);
+ }
+
+ if (Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-lgcov");
+
+ if (Args.hasArg(options::OPT_fnested_functions))
+ CmdArgs.push_back("-allow_stack_execute");
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (getToolChain().getDriver().CCCIsCXX)
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+
+ // link_ssp spec is empty.
+
+ // Let the tool chain choose which runtime library to link.
+ getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
+ }
+
+ if (!Args.hasArg(options::OPT_A) &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ // endfile_spec is empty.
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_F);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-create");
+ assert(Output.isFilename() && "Unexpected lipo output.");
+
+ CmdArgs.push_back("-output");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ assert(II.isFilename() && "Unexpected lipo input.");
+ CmdArgs.push_back(II.getFilename());
+ }
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Unexpected dsymutil input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("gas"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("_start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("-dn");
+ } else {
+// CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("--dynamic-linker");
+ CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtn.o")));
+ }
+
+ CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
+ + getToolChain().getTripleString()
+ + "/4.2.4"));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-pthread");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("__start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld.so");
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ std::string Triple = getToolChain().getTripleString();
+ if (Triple.substr(0, 6) == "x86_64")
+ Triple.replace(0, 6, "amd64");
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
+ "/4.2.1"));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-pthread");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // When building 32-bit code on FreeBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--32");
+
+
+ // Set byte order explicitly
+ if (getToolChain().getArchName() == "mips")
+ CmdArgs.push_back("-EB");
+ else if (getToolChain().getArchName() == "mipsel")
+ CmdArgs.push_back("-EL");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld-elf.so.1");
+ }
+ }
+
+ // When building 32-bit code on FreeBSD/amd64, we have to explicitly
+ // instruct ld in the base system to link 32-bit code.
+ if (getToolChain().getArchName() == "i386") {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386_fbsd");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt1.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ CmdArgs.push_back("-L/usr/lib");
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+ // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+ // the default system libraries. Just mimic this for now.
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgcc_p");
+ else
+ CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ else
+ CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lgcc_p");
+ } else {
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtn.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // When building 32-bit code on NetBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--32");
+
+
+ // Set byte order explicitly
+ if (getToolChain().getArchName() == "mips")
+ CmdArgs.push_back("-EB");
+ else if (getToolChain().getArchName() == "mipsel")
+ CmdArgs.push_back("-EL");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld.elf_so");
+ }
+ }
+
+ // When building 32-bit code on NetBSD/amd64, we have to explicitly
+ // instruct ld in the base system to link 32-bit code.
+ if (getToolChain().getArchName() == "i386") {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+ // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lc");
+
+ CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtn.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // Add --32/--64 to make sure we get the format we want.
+ // This is incomplete
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("--32");
+ } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+ CmdArgs.push_back("--64");
+ } else if (getToolChain().getArch() == llvm::Triple::arm) {
+ llvm::StringRef MArch = getToolChain().getArchName();
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ CmdArgs.push_back("-mfpu=neon");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::Linux& ToolChain =
+ static_cast<const toolchains::Linux&>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and for "clang -g foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
+ CmdArgs.push_back("--sysroot");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
+ if (Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
+ e = ToolChain.ExtraOpts.end();
+ i != e; ++i)
+ CmdArgs.push_back(i->c_str());
+
+ if (!Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--eh-frame-hdr");
+ }
+
+ CmdArgs.push_back("-m");
+ if (ToolChain.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("elf_i386");
+ else if (ToolChain.getArch() == llvm::Triple::arm)
+ CmdArgs.push_back("armelf_linux_eabi");
+ else
+ CmdArgs.push_back("elf_x86_64");
+
+ if (Args.hasArg(options::OPT_static)) {
+ if (ToolChain.getArch() == llvm::Triple::arm)
+ CmdArgs.push_back("-Bstatic");
+ else
+ CmdArgs.push_back("-static");
+ } else if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ }
+
+ if (ToolChain.getArch() == llvm::Triple::arm ||
+ (!Args.hasArg(options::OPT_static) &&
+ !Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-dynamic-linker");
+ if (ToolChain.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("/lib/ld-linux.so.2");
+ else if (ToolChain.getArch() == llvm::Triple::arm)
+ CmdArgs.push_back("/lib/ld-linux.so.3");
+ else
+ CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2");
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crt1 = NULL;
+ if (!Args.hasArg(options::OPT_shared)){
+ if (Args.hasArg(options::OPT_pie))
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin;
+ if (Args.hasArg(options::OPT_static))
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+
+ const ToolChain::path_list Paths = ToolChain.getFilePaths();
+
+ for (ToolChain::path_list::const_iterator i = Paths.begin(),
+ e = Paths.end();
+ i != e; ++i) {
+ const std::string &s = *i;
+ CmdArgs.push_back(Args.MakeArgString(std::string("-L") + s));
+ }
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--start-group");
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_static)) {
+ if (D.CCCIsCXX)
+ CmdArgs.push_back("-lgcc");
+ } else {
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-lgcc_eh");
+ else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads))
+ CmdArgs.push_back("-lpthread");
+
+ CmdArgs.push_back("-lc");
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--end-group");
+ else {
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("-lgcc");
+
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ if (!D.CCCIsCXX)
+ CmdArgs.push_back("--no-as-needed");
+
+ if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
+ CmdArgs.push_back("-lgcc");
+ }
+
+
+ if (!Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crtend;
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ crtend = "crtendS.o";
+ else
+ crtend = "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ }
+
+ if (Args.hasArg(options::OPT_use_gold_plugin)) {
+ CmdArgs.push_back("-plugin");
+ std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
+ CmdArgs.push_back(Args.MakeArgString(Plugin));
+ }
+
+ C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
+}
+
+void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("gas"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "/usr/gnu/lib/crtso.o")));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-L/usr/gnu/lib");
+ // FIXME: fill in the correct search path for the final
+ // support libraries.
+ CmdArgs.push_back("-L/usr/gnu/lib/gcc/i686-pc-minix/4.4.3");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "/usr/gnu/lib/libend.a")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("/usr/gnu/bin/gld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+/// DragonFly Tools
+
+// For now, DragonFly Assemble does just about the same as for
+// FreeBSD, but this may change soon.
+void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // When building 32-bit code on DragonFly/pc64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--32");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-Bshareable");
+ else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
+ }
+ }
+
+ // When building 32-bit code on DragonFly/pc64, we have to explicitly
+ // instruct ld in the base system to link 32-bit code.
+ if (getToolChain().getArchName() == "i386") {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
+ // rpaths
+ CmdArgs.push_back("-L/usr/lib/gcc41");
+
+ if (!Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc41");
+
+ CmdArgs.push_back("-rpath-link");
+ CmdArgs.push_back("/usr/lib/gcc41");
+
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib");
+
+ CmdArgs.push_back("-rpath-link");
+ CmdArgs.push_back("/usr/lib");
+ }
+
+ if (D.CCCIsCXX) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-lgcc_pic");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ }
+
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+
+ if (!Args.hasArg(options::OPT_nolibc)) {
+ CmdArgs.push_back("-lc");
+ }
+
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-lgcc_pic");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtn.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back(Args.MakeArgString(std::string("-out:") +
+ Output.getFilename()));
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back("-defaultlib:libcmt");
+ }
+
+ CmdArgs.push_back("-nologo");
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h
new file mode 100644
index 0000000..10c8839
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h
@@ -0,0 +1,501 @@
+//===--- Tools.h - Tool Implementations -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_TOOLS_H_
+#define CLANG_LIB_DRIVER_TOOLS_H_
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace driver {
+ class Driver;
+
+namespace toolchains {
+ class Darwin;
+}
+
+namespace tools {
+
+ /// \brief Clang compiler tool.
+ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
+ void AddPreprocessingOptions(const Driver &D,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs) const;
+
+ void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+ public:
+ Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedAssembler() const { return true; }
+ virtual bool hasIntegratedCPP() const { return true; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ /// \brief Clang integrated assembler tool.
+ class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
+ public:
+ ClangAs(const ToolChain &TC) : Tool("clang::as",
+ "clang integrated assembler", TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedAssembler() const { return false; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ /// gcc - Generic GCC tool implementations.
+namespace gcc {
+ class LLVM_LIBRARY_VISIBILITY Common : public Tool {
+ public:
+ Common(const char *Name, const char *ShortName,
+ const ToolChain &TC) : Tool(Name, ShortName, TC) {}
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+
+ /// RenderExtraToolArgs - Render any arguments necessary to force
+ /// the particular tool mode.
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const = 0;
+ };
+
+
+ class LLVM_LIBRARY_VISIBILITY Preprocess : public Common {
+ public:
+ Preprocess(const ToolChain &TC) : Common("gcc::Preprocess",
+ "gcc preprocessor", TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Precompile : public Common {
+ public:
+ Precompile(const ToolChain &TC) : Common("gcc::Precompile",
+ "gcc precompile", TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedCPP() const { return true; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Compile : public Common {
+ public:
+ Compile(const ToolChain &TC) : Common("gcc::Compile",
+ "gcc frontend", TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedCPP() const { return true; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Common {
+ public:
+ Assemble(const ToolChain &TC) : Common("gcc::Assemble",
+ "assembler (via gcc)", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public Common {
+ public:
+ Link(const ToolChain &TC) : Common("gcc::Link",
+ "linker (via gcc)", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const;
+ };
+} // end namespace gcc
+
+namespace darwin {
+ class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool {
+ protected:
+ void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+ const toolchains::Darwin &getDarwinToolChain() const {
+ return reinterpret_cast<const toolchains::Darwin&>(getToolChain());
+ }
+
+ public:
+ DarwinTool(const char *Name, const char *ShortName,
+ const ToolChain &TC) : Tool(Name, ShortName, TC) {}
+ };
+
+ class LLVM_LIBRARY_VISIBILITY CC1 : public DarwinTool {
+ public:
+ static const char *getBaseInputName(const ArgList &Args,
+ const InputInfoList &Input);
+ static const char *getBaseInputStem(const ArgList &Args,
+ const InputInfoList &Input);
+ static const char *getDependencyFileName(const ArgList &Args,
+ const InputInfoList &Inputs);
+
+ protected:
+ const char *getCC1Name(types::ID Type) const;
+
+ void AddCC1Args(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ const InputInfoList &Inputs,
+ const ArgStringList &OutputArgs) const;
+ void AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ const InputInfoList &Inputs,
+ const ArgStringList &OutputArgs) const;
+ void AddCPPUniqueOptionsArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const;
+ void AddCPPArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+ public:
+ CC1(const char *Name, const char *ShortName,
+ const ToolChain &TC) : DarwinTool(Name, ShortName, TC) {}
+
+ virtual bool hasGoodDiagnostics() const { return true; }
+ virtual bool hasIntegratedCPP() const { return true; }
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Preprocess : public CC1 {
+ public:
+ Preprocess(const ToolChain &TC) : CC1("darwin::Preprocess",
+ "gcc preprocessor", TC) {}
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Compile : public CC1 {
+ public:
+ Compile(const ToolChain &TC) : CC1("darwin::Compile", "gcc frontend", TC) {}
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Assemble : public DarwinTool {
+ public:
+ Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble",
+ "assembler", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public DarwinTool {
+ void AddLinkArgs(Compilation &C, const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ public:
+ Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Lipo : public DarwinTool {
+ public:
+ Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", "lipo", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Dsymutil : public DarwinTool {
+ public:
+ Dsymutil(const ToolChain &TC) : DarwinTool("darwin::Dsymutil",
+ "dsymutil", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+}
+
+ /// openbsd -- Directly call GNU Binutils assembler and linker
+namespace openbsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace openbsd
+
+ /// freebsd -- Directly call GNU Binutils assembler and linker
+namespace freebsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace freebsd
+
+ /// netbsd -- Directly call GNU Binutils assembler and linker
+namespace netbsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("netbsd::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("netbsd::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace netbsd
+
+ /// linux -- Directly call GNU Binutils assembler and linker
+namespace linuxtools {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("linux::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("linux::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+}
+ /// minix -- Directly call GNU Binutils assembler and linker
+namespace minix {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("minix::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace minix
+
+ /// auroraux -- Directly call GNU Binutils assembler and linker
+namespace auroraux {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace auroraux
+
+ /// dragonfly -- Directly call GNU Binutils assembler and linker
+namespace dragonfly {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace dragonfly
+
+ /// Visual studio tools.
+namespace visualstudio {
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace visualstudio
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // CLANG_LIB_DRIVER_TOOLS_H_
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
new file mode 100644
index 0000000..4a4312b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -0,0 +1,251 @@
+//===--- Types.cpp - Driver input & temporary type information ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Types.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include <string.h>
+#include <cassert>
+
+using namespace clang::driver;
+using namespace clang::driver::types;
+
+struct TypeInfo {
+ const char *Name;
+ const char *Flags;
+ const char *TempSuffix;
+ ID PreprocessedType;
+};
+
+static const TypeInfo TypeInfos[] = {
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \
+ { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, },
+#include "clang/Driver/Types.def"
+#undef TYPE
+};
+static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]);
+
+static const TypeInfo &getInfo(unsigned id) {
+ assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
+ return TypeInfos[id - 1];
+}
+
+const char *types::getTypeName(ID Id) {
+ return getInfo(Id).Name;
+}
+
+types::ID types::getPreprocessedType(ID Id) {
+ return getInfo(Id).PreprocessedType;
+}
+
+const char *types::getTypeTempSuffix(ID Id) {
+ return getInfo(Id).TempSuffix;
+}
+
+bool types::onlyAssembleType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'a');
+}
+
+bool types::onlyPrecompileType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'p');
+}
+
+bool types::canTypeBeUserSpecified(ID Id) {
+ return strchr(getInfo(Id).Flags, 'u');
+}
+
+bool types::appendSuffixForType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'A');
+}
+
+bool types::canLipoType(ID Id) {
+ return (Id == TY_Nothing ||
+ Id == TY_Image ||
+ Id == TY_Object);
+}
+
+bool types::isAcceptedByClang(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_Asm:
+ case TY_C: case TY_PP_C:
+ case TY_CL:
+ case TY_CUDA:
+ case TY_ObjC: case TY_PP_ObjC:
+ case TY_CXX: case TY_PP_CXX:
+ case TY_ObjCXX: case TY_PP_ObjCXX:
+ case TY_CHeader: case TY_PP_CHeader:
+ case TY_ObjCHeader: case TY_PP_ObjCHeader:
+ case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ case TY_AST:
+ case TY_LLVM_IR: case TY_LLVM_BC:
+ return true;
+ }
+}
+
+bool types::isOnlyAcceptedByClang(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_AST:
+ case TY_LLVM_IR:
+ case TY_LLVM_BC:
+ case TY_RewrittenObjC:
+ return true;
+ }
+}
+
+bool types::isObjC(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_ObjC: case TY_PP_ObjC:
+ case TY_ObjCXX: case TY_PP_ObjCXX:
+ case TY_ObjCHeader: case TY_PP_ObjCHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ return true;
+ }
+}
+
+bool types::isCXX(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_CXX: case TY_PP_CXX:
+ case TY_ObjCXX: case TY_PP_ObjCXX:
+ case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ return true;
+ }
+}
+
+types::ID types::lookupTypeForExtension(const char *Ext) {
+ return llvm::StringSwitch<types::ID>(Ext)
+ .Case("c", TY_C)
+ .Case("i", TY_PP_C)
+ .Case("m", TY_ObjC)
+ .Case("M", TY_ObjCXX)
+ .Case("h", TY_CHeader)
+ .Case("C", TY_CXX)
+ .Case("H", TY_CXXHeader)
+ .Case("f", TY_PP_Fortran)
+ .Case("F", TY_Fortran)
+ .Case("s", TY_PP_Asm)
+ .Case("S", TY_Asm)
+ .Case("ii", TY_PP_CXX)
+ .Case("mi", TY_PP_ObjC)
+ .Case("mm", TY_ObjCXX)
+ .Case("bc", TY_LLVM_BC)
+ .Case("cc", TY_CXX)
+ .Case("CC", TY_CXX)
+ .Case("cl", TY_CL)
+ .Case("cp", TY_CXX)
+ .Case("cu", TY_CUDA)
+ .Case("hh", TY_CXXHeader)
+ .Case("ll", TY_LLVM_IR)
+ .Case("hpp", TY_CXXHeader)
+ .Case("ads", TY_Ada)
+ .Case("adb", TY_Ada)
+ .Case("ast", TY_AST)
+ .Case("c++", TY_CXX)
+ .Case("C++", TY_CXX)
+ .Case("cxx", TY_CXX)
+ .Case("cpp", TY_CXX)
+ .Case("CPP", TY_CXX)
+ .Case("CXX", TY_CXX)
+ .Case("for", TY_PP_Fortran)
+ .Case("FOR", TY_PP_Fortran)
+ .Case("fpp", TY_Fortran)
+ .Case("FPP", TY_Fortran)
+ .Case("f90", TY_PP_Fortran)
+ .Case("f95", TY_PP_Fortran)
+ .Case("F90", TY_Fortran)
+ .Case("F95", TY_Fortran)
+ .Case("mii", TY_PP_ObjCXX)
+ .Default(TY_INVALID);
+}
+
+types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
+ unsigned N = strlen(Name);
+
+ for (unsigned i=0; i<numTypes; ++i) {
+ types::ID Id = (types::ID) (i + 1);
+ if (canTypeBeUserSpecified(Id) &&
+ memcmp(Name, getInfo(Id).Name, N + 1) == 0)
+ return Id;
+ }
+
+ return TY_INVALID;
+}
+
+// FIXME: Why don't we just put this list in the defs file, eh.
+
+unsigned types::getNumCompilationPhases(ID Id) {
+ if (Id == TY_Object)
+ return 1;
+
+ unsigned N = 0;
+ if (getPreprocessedType(Id) != TY_INVALID)
+ N += 1;
+
+ if (onlyAssembleType(Id))
+ return N + 2; // assemble, link
+ if (onlyPrecompileType(Id))
+ return N + 1; // precompile
+
+ return N + 3; // compile, assemble, link
+}
+
+phases::ID types::getCompilationPhase(ID Id, unsigned N) {
+ assert(N < getNumCompilationPhases(Id) && "Invalid index.");
+
+ if (Id == TY_Object)
+ return phases::Link;
+
+ if (getPreprocessedType(Id) != TY_INVALID) {
+ if (N == 0)
+ return phases::Preprocess;
+ --N;
+ }
+
+ if (onlyAssembleType(Id))
+ return N == 0 ? phases::Assemble : phases::Link;
+
+ if (onlyPrecompileType(Id))
+ return phases::Precompile;
+
+ if (N == 0)
+ return phases::Compile;
+ if (N == 1)
+ return phases::Assemble;
+
+ return phases::Link;
+}
+
+ID types::lookupCXXTypeForCType(ID Id) {
+ switch (Id) {
+ default:
+ return Id;
+
+ case types::TY_C:
+ return types::TY_CXX;
+ case types::TY_PP_C:
+ return types::TY_PP_CXX;
+ case types::TY_CHeader:
+ return types::TY_CXXHeader;
+ case types::TY_PP_CHeader:
+ return types::TY_PP_CXXHeader;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
new file mode 100644
index 0000000..92fb1e8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTConsumers.cpp
@@ -0,0 +1,453 @@
+//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumer Implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "llvm/Module.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+/// ASTPrinter - Pretty-printer and dumper of ASTs
+
+namespace {
+ class ASTPrinter : public ASTConsumer {
+ llvm::raw_ostream &Out;
+ bool Dump;
+
+ public:
+ ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
+ : Out(o? *o : llvm::outs()), Dump(Dump) { }
+
+ virtual void HandleTranslationUnit(ASTContext &Context) {
+ PrintingPolicy Policy = Context.PrintingPolicy;
+ Policy.Dump = Dump;
+ Context.getTranslationUnitDecl()->print(Out, Policy);
+ }
+ };
+} // end anonymous namespace
+
+ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
+ return new ASTPrinter(out);
+}
+
+//===----------------------------------------------------------------------===//
+/// ASTPrinterXML - XML-printer of ASTs
+
+namespace {
+ class ASTPrinterXML : public ASTConsumer {
+ DocumentXML Doc;
+
+ public:
+ ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
+
+ void Initialize(ASTContext &Context) {
+ Doc.initialize(Context);
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ Doc.addSubNode("TranslationUnit");
+ for (DeclContext::decl_iterator
+ D = Ctx.getTranslationUnitDecl()->decls_begin(),
+ DEnd = Ctx.getTranslationUnitDecl()->decls_end();
+ D != DEnd;
+ ++D)
+ Doc.PrintDecl(*D);
+ Doc.toParent();
+ Doc.finalize();
+ }
+ };
+} // end anonymous namespace
+
+
+ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
+ return new ASTPrinterXML(out ? *out : llvm::outs());
+}
+
+ASTConsumer *clang::CreateASTDumper() {
+ return new ASTPrinter(0, true);
+}
+
+//===----------------------------------------------------------------------===//
+/// ASTViewer - AST Visualization
+
+namespace {
+ class ASTViewer : public ASTConsumer {
+ ASTContext *Context;
+ public:
+ void Initialize(ASTContext &Context) {
+ this->Context = &Context;
+ }
+
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+
+ void HandleTopLevelSingleDecl(Decl *D);
+ };
+}
+
+void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ D->print(llvm::errs());
+
+ if (Stmt *Body = D->getBody()) {
+ llvm::errs() << '\n';
+ Body->viewAST();
+ llvm::errs() << '\n';
+ }
+ }
+}
+
+
+ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
+
+//===----------------------------------------------------------------------===//
+/// DeclContextPrinter - Decl and DeclContext Visualization
+
+namespace {
+
+class DeclContextPrinter : public ASTConsumer {
+ llvm::raw_ostream& Out;
+public:
+ DeclContextPrinter() : Out(llvm::errs()) {}
+
+ void HandleTranslationUnit(ASTContext &C) {
+ PrintDeclContext(C.getTranslationUnitDecl(), 4);
+ }
+
+ void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
+};
+} // end anonymous namespace
+
+void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
+ unsigned Indentation) {
+ // Print DeclContext name.
+ switch (DC->getDeclKind()) {
+ case Decl::TranslationUnit:
+ Out << "[translation unit] " << DC;
+ break;
+ case Decl::Namespace: {
+ Out << "[namespace] ";
+ const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
+ Out << ND;
+ break;
+ }
+ case Decl::Enum: {
+ const EnumDecl* ED = cast<EnumDecl>(DC);
+ if (ED->isDefinition())
+ Out << "[enum] ";
+ else
+ Out << "<enum> ";
+ Out << ED;
+ break;
+ }
+ case Decl::Record: {
+ const RecordDecl* RD = cast<RecordDecl>(DC);
+ if (RD->isDefinition())
+ Out << "[struct] ";
+ else
+ Out << "<struct> ";
+ Out << RD;
+ break;
+ }
+ case Decl::CXXRecord: {
+ const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
+ if (RD->isDefinition())
+ Out << "[class] ";
+ else
+ Out << "<class> ";
+ Out << RD << ' ' << DC;
+ break;
+ }
+ case Decl::ObjCMethod:
+ Out << "[objc method]";
+ break;
+ case Decl::ObjCInterface:
+ Out << "[objc interface]";
+ break;
+ case Decl::ObjCCategory:
+ Out << "[objc category]";
+ break;
+ case Decl::ObjCProtocol:
+ Out << "[objc protocol]";
+ break;
+ case Decl::ObjCImplementation:
+ Out << "[objc implementation]";
+ break;
+ case Decl::ObjCCategoryImpl:
+ Out << "[objc categoryimpl]";
+ break;
+ case Decl::LinkageSpec:
+ Out << "[linkage spec]";
+ break;
+ case Decl::Block:
+ Out << "[block]";
+ break;
+ case Decl::Function: {
+ const FunctionDecl* FD = cast<FunctionDecl>(DC);
+ if (FD->isThisDeclarationADefinition())
+ Out << "[function] ";
+ else
+ Out << "<function> ";
+ Out << FD;
+ // Print the parameters.
+ Out << "(";
+ bool PrintComma = false;
+ for (FunctionDecl::param_const_iterator I = FD->param_begin(),
+ E = FD->param_end(); I != E; ++I) {
+ if (PrintComma)
+ Out << ", ";
+ else
+ PrintComma = true;
+ Out << *I;
+ }
+ Out << ")";
+ break;
+ }
+ case Decl::CXXMethod: {
+ const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
+ if (D->isOutOfLine())
+ Out << "[c++ method] ";
+ else if (D->isImplicit())
+ Out << "(c++ method) ";
+ else
+ Out << "<c++ method> ";
+ Out << D;
+ // Print the parameters.
+ Out << "(";
+ bool PrintComma = false;
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end(); I != E; ++I) {
+ if (PrintComma)
+ Out << ", ";
+ else
+ PrintComma = true;
+ Out << *I;
+ }
+ Out << ")";
+
+ // Check the semantic DeclContext.
+ const DeclContext* SemaDC = D->getDeclContext();
+ const DeclContext* LexicalDC = D->getLexicalDeclContext();
+ if (SemaDC != LexicalDC)
+ Out << " [[" << SemaDC << "]]";
+
+ break;
+ }
+ case Decl::CXXConstructor: {
+ const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
+ if (D->isOutOfLine())
+ Out << "[c++ ctor] ";
+ else if (D->isImplicit())
+ Out << "(c++ ctor) ";
+ else
+ Out << "<c++ ctor> ";
+ Out << D;
+ // Print the parameters.
+ Out << "(";
+ bool PrintComma = false;
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end(); I != E; ++I) {
+ if (PrintComma)
+ Out << ", ";
+ else
+ PrintComma = true;
+ Out << *I;
+ }
+ Out << ")";
+
+ // Check the semantic DC.
+ const DeclContext* SemaDC = D->getDeclContext();
+ const DeclContext* LexicalDC = D->getLexicalDeclContext();
+ if (SemaDC != LexicalDC)
+ Out << " [[" << SemaDC << "]]";
+ break;
+ }
+ case Decl::CXXDestructor: {
+ const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
+ if (D->isOutOfLine())
+ Out << "[c++ dtor] ";
+ else if (D->isImplicit())
+ Out << "(c++ dtor) ";
+ else
+ Out << "<c++ dtor> ";
+ Out << D;
+ // Check the semantic DC.
+ const DeclContext* SemaDC = D->getDeclContext();
+ const DeclContext* LexicalDC = D->getLexicalDeclContext();
+ if (SemaDC != LexicalDC)
+ Out << " [[" << SemaDC << "]]";
+ break;
+ }
+ case Decl::CXXConversion: {
+ const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
+ if (D->isOutOfLine())
+ Out << "[c++ conversion] ";
+ else if (D->isImplicit())
+ Out << "(c++ conversion) ";
+ else
+ Out << "<c++ conversion> ";
+ Out << D;
+ // Check the semantic DC.
+ const DeclContext* SemaDC = D->getDeclContext();
+ const DeclContext* LexicalDC = D->getLexicalDeclContext();
+ if (SemaDC != LexicalDC)
+ Out << " [[" << SemaDC << "]]";
+ break;
+ }
+
+ default:
+ assert(0 && "a decl that inherits DeclContext isn't handled");
+ }
+
+ Out << "\n";
+
+ // Print decls in the DeclContext.
+ for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+ I != E; ++I) {
+ for (unsigned i = 0; i < Indentation; ++i)
+ Out << " ";
+
+ Decl::Kind DK = I->getKind();
+ switch (DK) {
+ case Decl::Namespace:
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ObjCMethod:
+ case Decl::ObjCInterface:
+ case Decl::ObjCCategory:
+ case Decl::ObjCProtocol:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCCategoryImpl:
+ case Decl::LinkageSpec:
+ case Decl::Block:
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ {
+ DeclContext* DC = cast<DeclContext>(*I);
+ PrintDeclContext(DC, Indentation+2);
+ break;
+ }
+ case Decl::IndirectField: {
+ IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
+ Out << "<IndirectField> " << IFD << '\n';
+ break;
+ }
+ case Decl::Label: {
+ LabelDecl *LD = cast<LabelDecl>(*I);
+ Out << "<Label> " << LD << '\n';
+ break;
+ }
+ case Decl::Field: {
+ FieldDecl *FD = cast<FieldDecl>(*I);
+ Out << "<field> " << FD << '\n';
+ break;
+ }
+ case Decl::Typedef: {
+ TypedefDecl* TD = cast<TypedefDecl>(*I);
+ Out << "<typedef> " << TD << '\n';
+ break;
+ }
+ case Decl::EnumConstant: {
+ EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
+ Out << "<enum constant> " << ECD << '\n';
+ break;
+ }
+ case Decl::Var: {
+ VarDecl* VD = cast<VarDecl>(*I);
+ Out << "<var> " << VD << '\n';
+ break;
+ }
+ case Decl::ImplicitParam: {
+ ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
+ Out << "<implicit parameter> " << IPD << '\n';
+ break;
+ }
+ case Decl::ParmVar: {
+ ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
+ Out << "<parameter> " << PVD << '\n';
+ break;
+ }
+ case Decl::ObjCProperty: {
+ ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
+ Out << "<objc property> " << OPD << '\n';
+ break;
+ }
+ case Decl::FunctionTemplate: {
+ FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
+ Out << "<function template> " << FTD << '\n';
+ break;
+ }
+ case Decl::FileScopeAsm: {
+ Out << "<file-scope asm>\n";
+ break;
+ }
+ case Decl::UsingDirective: {
+ Out << "<using directive>\n";
+ break;
+ }
+ case Decl::NamespaceAlias: {
+ NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
+ Out << "<namespace alias> " << NAD << '\n';
+ break;
+ }
+ case Decl::ClassTemplate: {
+ ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
+ Out << "<class template> " << CTD << '\n';
+ break;
+ }
+ default:
+ Out << "DeclKind: " << DK << '"' << *I << "\"\n";
+ assert(0 && "decl unhandled");
+ }
+ }
+}
+ASTConsumer *clang::CreateDeclContextPrinter() {
+ return new DeclContextPrinter();
+}
+
+//===----------------------------------------------------------------------===//
+/// ASTDumperXML - In-depth XML dumping.
+
+namespace {
+class ASTDumpXML : public ASTConsumer {
+ llvm::raw_ostream &OS;
+
+public:
+ ASTDumpXML(llvm::raw_ostream &OS) : OS(OS) {}
+
+ void HandleTranslationUnit(ASTContext &C) {
+ C.getTranslationUnitDecl()->dumpXML(OS);
+ }
+};
+}
+
+ASTConsumer *clang::CreateASTDumperXML(llvm::raw_ostream &OS) {
+ return new ASTDumpXML(OS);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
new file mode 100644
index 0000000..3905b99
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
@@ -0,0 +1,110 @@
+//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/Basic/Diagnostic.h"
+
+using namespace clang;
+
+ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return AdaptedAction->CreateASTConsumer(CI, InFile);
+}
+
+bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ // FIXME: This is a hack. We need a better way to communicate the
+ // AST file, compiler instance, and file name than member variables
+ // of FrontendAction.
+ AdaptedAction->setCurrentFile(getCurrentFile(), getCurrentFileKind(),
+ takeCurrentASTUnit());
+ AdaptedAction->setCompilerInstance(&CI);
+ return AdaptedAction->BeginSourceFileAction(CI, Filename);
+}
+
+void ASTMergeAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ CI.getDiagnostics().getClient()->BeginSourceFile(
+ CI.getASTContext().getLangOptions());
+ CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+ &CI.getASTContext());
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs>
+ DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
+ for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
+ llvm::IntrusiveRefCntPtr<Diagnostic>
+ Diags(new Diagnostic(DiagIDs, CI.getDiagnostics().getClient(),
+ /*ShouldOwnClient=*/false));
+ ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
+ CI.getFileSystemOpts(), false);
+ if (!Unit)
+ continue;
+
+ ASTImporter Importer(CI.getASTContext(),
+ CI.getFileManager(),
+ Unit->getASTContext(),
+ Unit->getFileManager(),
+ /*MinimalImport=*/false);
+
+ TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
+ for (DeclContext::decl_iterator D = TU->decls_begin(),
+ DEnd = TU->decls_end();
+ D != DEnd; ++D) {
+ // Don't re-import __va_list_tag, __builtin_va_list.
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ if (IdentifierInfo *II = ND->getIdentifier())
+ if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list"))
+ continue;
+
+ Importer.Import(*D);
+ }
+
+ delete Unit;
+ }
+
+ AdaptedAction->ExecuteAction();
+ CI.getDiagnostics().getClient()->EndSourceFile();
+}
+
+void ASTMergeAction::EndSourceFileAction() {
+ return AdaptedAction->EndSourceFileAction();
+}
+
+ASTMergeAction::ASTMergeAction(FrontendAction *AdaptedAction,
+ std::string *ASTFiles, unsigned NumASTFiles)
+ : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles, ASTFiles + NumASTFiles) {
+ assert(AdaptedAction && "ASTMergeAction needs an action to adapt");
+}
+
+ASTMergeAction::~ASTMergeAction() {
+ delete AdaptedAction;
+}
+
+bool ASTMergeAction::usesPreprocessorOnly() const {
+ return AdaptedAction->usesPreprocessorOnly();
+}
+
+bool ASTMergeAction::usesCompleteTranslationUnit() {
+ return AdaptedAction->usesCompleteTranslationUnit();
+}
+
+bool ASTMergeAction::hasPCHSupport() const {
+ return AdaptedAction->hasPCHSupport();
+}
+
+bool ASTMergeAction::hasASTFileSupport() const {
+ return AdaptedAction->hasASTFileSupport();
+}
+
+bool ASTMergeAction::hasCodeCompletionSupport() const {
+ return AdaptedAction->hasCodeCompletionSupport();
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
new file mode 100644
index 0000000..4a5a51d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -0,0 +1,2099 @@
+//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit Implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/ASTSerializationListener.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Atomic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Timer.h"
+#include <cstdlib>
+#include <cstdio>
+#include <sys/stat.h>
+using namespace clang;
+
+using llvm::TimeRecord;
+
+namespace {
+ class SimpleTimer {
+ bool WantTiming;
+ TimeRecord Start;
+ std::string Output;
+
+ public:
+ explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
+ if (WantTiming)
+ Start = TimeRecord::getCurrentTime();
+ }
+
+ void setOutput(const llvm::Twine &Output) {
+ if (WantTiming)
+ this->Output = Output.str();
+ }
+
+ ~SimpleTimer() {
+ if (WantTiming) {
+ TimeRecord Elapsed = TimeRecord::getCurrentTime();
+ Elapsed -= Start;
+ llvm::errs() << Output << ':';
+ Elapsed.print(Elapsed, llvm::errs());
+ llvm::errs() << '\n';
+ }
+ }
+ };
+}
+
+/// \brief After failing to build a precompiled preamble (due to
+/// errors in the source that occurs in the preamble), the number of
+/// reparses during which we'll skip even trying to precompile the
+/// preamble.
+const unsigned DefaultPreambleRebuildInterval = 5;
+
+/// \brief Tracks the number of ASTUnit objects that are currently active.
+///
+/// Used for debugging purposes only.
+static llvm::sys::cas_flag ActiveASTUnitObjects;
+
+ASTUnit::ASTUnit(bool _MainFileIsAST)
+ : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
+ CompleteTranslationUnit(true), WantTiming(getenv("LIBCLANG_TIMING")),
+ NumStoredDiagnosticsFromDriver(0),
+ ConcurrencyCheckValue(CheckUnlocked),
+ PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
+ ShouldCacheCodeCompletionResults(false),
+ CompletionCacheTopLevelHashValue(0),
+ PreambleTopLevelHashValue(0),
+ CurrentTopLevelHashValue(0),
+ UnsafeToFree(false) {
+ if (getenv("LIBCLANG_OBJTRACKING")) {
+ llvm::sys::AtomicIncrement(&ActiveASTUnitObjects);
+ fprintf(stderr, "+++ %d translation units\n", ActiveASTUnitObjects);
+ }
+}
+
+ASTUnit::~ASTUnit() {
+ ConcurrencyCheckValue = CheckLocked;
+ CleanTemporaryFiles();
+ if (!PreambleFile.empty())
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+
+ // Free the buffers associated with remapped files. We are required to
+ // perform this operation here because we explicitly request that the
+ // compiler instance *not* free these buffers for each invocation of the
+ // parser.
+ if (Invocation.get()) {
+ PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ FB = PPOpts.remapped_file_buffer_begin(),
+ FBEnd = PPOpts.remapped_file_buffer_end();
+ FB != FBEnd;
+ ++FB)
+ delete FB->second;
+ }
+
+ delete SavedMainFileBuffer;
+ delete PreambleBuffer;
+
+ ClearCachedCompletionResults();
+
+ if (getenv("LIBCLANG_OBJTRACKING")) {
+ llvm::sys::AtomicDecrement(&ActiveASTUnitObjects);
+ fprintf(stderr, "--- %d translation units\n", ActiveASTUnitObjects);
+ }
+}
+
+void ASTUnit::CleanTemporaryFiles() {
+ for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
+ TemporaryFiles[I].eraseFromDisk();
+ TemporaryFiles.clear();
+}
+
+/// \brief Determine the set of code-completion contexts in which this
+/// declaration should be shown.
+static unsigned getDeclShowContexts(NamedDecl *ND,
+ const LangOptions &LangOpts,
+ bool &IsNestedNameSpecifier) {
+ IsNestedNameSpecifier = false;
+
+ if (isa<UsingShadowDecl>(ND))
+ ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
+ if (!ND)
+ return 0;
+
+ unsigned Contexts = 0;
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
+ isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
+ // Types can appear in these contexts.
+ if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
+ Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Type - 1))
+ | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
+
+ // In C++, types can appear in expressions contexts (for functional casts).
+ if (LangOpts.CPlusPlus)
+ Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
+
+ // In Objective-C, message sends can send interfaces. In Objective-C++,
+ // all types are available due to functional casts.
+ if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
+ Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+
+ // Deal with tag names.
+ if (isa<EnumDecl>(ND)) {
+ Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
+
+ // Part of the nested-name-specifier in C++0x.
+ if (LangOpts.CPlusPlus0x)
+ IsNestedNameSpecifier = true;
+ } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
+ if (Record->isUnion())
+ Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
+ else
+ Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+
+ if (LangOpts.CPlusPlus)
+ IsNestedNameSpecifier = true;
+ } else if (isa<ClassTemplateDecl>(ND))
+ IsNestedNameSpecifier = true;
+ } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ // Values can appear in these contexts.
+ Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+ } else if (isa<ObjCProtocolDecl>(ND)) {
+ Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+ } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
+ Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
+
+ // Part of the nested-name-specifier.
+ IsNestedNameSpecifier = true;
+ }
+
+ return Contexts;
+}
+
+void ASTUnit::CacheCodeCompletionResults() {
+ if (!TheSema)
+ return;
+
+ SimpleTimer Timer(WantTiming);
+ Timer.setOutput("Cache global code completions for " + getMainFileName());
+
+ // Clear out the previous results.
+ ClearCachedCompletionResults();
+
+ // Gather the set of global code completions.
+ typedef CodeCompletionResult Result;
+ llvm::SmallVector<Result, 8> Results;
+ CachedCompletionAllocator = new GlobalCodeCompletionAllocator;
+ TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results);
+
+ // Translate global code completions into cached completions.
+ llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
+
+ for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+ switch (Results[I].Kind) {
+ case Result::RK_Declaration: {
+ bool IsNestedNameSpecifier = false;
+ CachedCodeCompletionResult CachedResult;
+ CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
+ *CachedCompletionAllocator);
+ CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
+ Ctx->getLangOptions(),
+ IsNestedNameSpecifier);
+ CachedResult.Priority = Results[I].Priority;
+ CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.Availability = Results[I].Availability;
+
+ // Keep track of the type of this completion in an ASTContext-agnostic
+ // way.
+ QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
+ if (UsageType.isNull()) {
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ } else {
+ CanQualType CanUsageType
+ = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
+ CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
+
+ // Determine whether we have already seen this type. If so, we save
+ // ourselves the work of formatting the type string by using the
+ // temporary, CanQualType-based hash table to find the associated value.
+ unsigned &TypeValue = CompletionTypes[CanUsageType];
+ if (TypeValue == 0) {
+ TypeValue = CompletionTypes.size();
+ CachedCompletionTypes[QualType(CanUsageType).getAsString()]
+ = TypeValue;
+ }
+
+ CachedResult.Type = TypeValue;
+ }
+
+ CachedCompletionResults.push_back(CachedResult);
+
+ /// Handle nested-name-specifiers in C++.
+ if (TheSema->Context.getLangOptions().CPlusPlus &&
+ IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
+ // The contexts in which a nested-name-specifier can appear in C++.
+ unsigned NNSContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+ | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
+ | (1 << (CodeCompletionContext::CCC_Type - 1))
+ | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1))
+ | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
+
+ if (isa<NamespaceDecl>(Results[I].Declaration) ||
+ isa<NamespaceAliasDecl>(Results[I].Declaration))
+ NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
+
+ if (unsigned RemainingContexts
+ = NNSContexts & ~CachedResult.ShowInContexts) {
+ // If there any contexts where this completion can be a
+ // nested-name-specifier but isn't already an option, create a
+ // nested-name-specifier completion.
+ Results[I].StartsNestedNameSpecifier = true;
+ CachedResult.Completion
+ = Results[I].CreateCodeCompletionString(*TheSema,
+ *CachedCompletionAllocator);
+ CachedResult.ShowInContexts = RemainingContexts;
+ CachedResult.Priority = CCP_NestedNameSpecifier;
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ CachedCompletionResults.push_back(CachedResult);
+ }
+ }
+ break;
+ }
+
+ case Result::RK_Keyword:
+ case Result::RK_Pattern:
+ // Ignore keywords and patterns; we don't care, since they are so
+ // easily regenerated.
+ break;
+
+ case Result::RK_Macro: {
+ CachedCodeCompletionResult CachedResult;
+ CachedResult.Completion
+ = Results[I].CreateCodeCompletionString(*TheSema,
+ *CachedCompletionAllocator);
+ CachedResult.ShowInContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
+ | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1))
+ | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
+ | (1 << (CodeCompletionContext::CCC_OtherWithMacros - 1));
+
+ CachedResult.Priority = Results[I].Priority;
+ CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.Availability = Results[I].Availability;
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ CachedCompletionResults.push_back(CachedResult);
+ break;
+ }
+ }
+ }
+
+ // Save the current top-level hash value.
+ CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
+}
+
+void ASTUnit::ClearCachedCompletionResults() {
+ CachedCompletionResults.clear();
+ CachedCompletionTypes.clear();
+ CachedCompletionAllocator = 0;
+}
+
+namespace {
+
+/// \brief Gathers information from ASTReader that will be used to initialize
+/// a Preprocessor.
+class ASTInfoCollector : public ASTReaderListener {
+ LangOptions &LangOpt;
+ HeaderSearch &HSI;
+ std::string &TargetTriple;
+ std::string &Predefines;
+ unsigned &Counter;
+
+ unsigned NumHeaderInfos;
+
+public:
+ ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+ std::string &TargetTriple, std::string &Predefines,
+ unsigned &Counter)
+ : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
+ Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ LangOpt = LangOpts;
+ return false;
+ }
+
+ virtual bool ReadTargetTriple(llvm::StringRef Triple) {
+ TargetTriple = Triple;
+ return false;
+ }
+
+ virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
+ llvm::StringRef OriginalFileName,
+ std::string &SuggestedPredefines) {
+ Predefines = Buffers[0].Data;
+ for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
+ Predefines += Buffers[I].Data;
+ }
+ return false;
+ }
+
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
+ HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ }
+
+ virtual void ReadCounter(unsigned Value) {
+ Counter = Value;
+ }
+};
+
+class StoredDiagnosticClient : public DiagnosticClient {
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
+
+public:
+ explicit StoredDiagnosticClient(
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
+ : StoredDiags(StoredDiags) { }
+
+ virtual void HandleDiagnostic(Diagnostic::Level Level,
+ const DiagnosticInfo &Info);
+};
+
+/// \brief RAII object that optionally captures diagnostics, if
+/// there is no diagnostic client to capture them already.
+class CaptureDroppedDiagnostics {
+ Diagnostic &Diags;
+ StoredDiagnosticClient Client;
+ DiagnosticClient *PreviousClient;
+
+public:
+ CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
+ : Diags(Diags), Client(StoredDiags), PreviousClient(0)
+ {
+ if (RequestCapture || Diags.getClient() == 0) {
+ PreviousClient = Diags.takeClient();
+ Diags.setClient(&Client);
+ }
+ }
+
+ ~CaptureDroppedDiagnostics() {
+ if (Diags.getClient() == &Client) {
+ Diags.takeClient();
+ Diags.setClient(PreviousClient);
+ }
+ }
+};
+
+} // anonymous namespace
+
+void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
+ const DiagnosticInfo &Info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticClient::HandleDiagnostic(Level, Info);
+
+ StoredDiags.push_back(StoredDiagnostic(Level, Info));
+}
+
+const std::string &ASTUnit::getOriginalSourceFileName() {
+ return OriginalSourceFile;
+}
+
+const std::string &ASTUnit::getASTFileName() {
+ assert(isMainFileAST() && "Not an ASTUnit from an AST file!");
+ return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName();
+}
+
+llvm::MemoryBuffer *ASTUnit::getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr) {
+ assert(FileMgr);
+ return FileMgr->getBufferForFile(Filename, ErrorStr);
+}
+
+/// \brief Configure the diagnostics object for use with ASTUnit.
+void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
+ const char **ArgBegin, const char **ArgEnd,
+ ASTUnit &AST, bool CaptureDiagnostics) {
+ if (!Diags.getPtr()) {
+ // No diagnostics engine was provided, so create our own diagnostics object
+ // with the default options.
+ DiagnosticOptions DiagOpts;
+ DiagnosticClient *Client = 0;
+ if (CaptureDiagnostics)
+ Client = new StoredDiagnosticClient(AST.StoredDiagnostics);
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin,
+ ArgBegin, Client);
+ } else if (CaptureDiagnostics) {
+ Diags->setClient(new StoredDiagnosticClient(AST.StoredDiagnostics));
+ }
+}
+
+ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ const FileSystemOptions &FileSystemOpts,
+ bool OnlyLocalDecls,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles,
+ bool CaptureDiagnostics) {
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
+ ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
+
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->CaptureDiagnostics = CaptureDiagnostics;
+ AST->Diagnostics = Diags;
+ AST->FileMgr.reset(new FileManager(FileSystemOpts));
+ AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics(),
+ AST->getFileManager()));
+ AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
+
+ for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile
+ = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
+ RemappedFiles[I].second->getBufferSize(),
+ 0);
+ if (!FromFile) {
+ AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
+ << RemappedFiles[I].first;
+ delete RemappedFiles[I].second;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ AST->getSourceManager().overrideFileContents(FromFile,
+ RemappedFiles[I].second);
+ }
+
+ // Gather Info for preprocessor construction later on.
+
+ LangOptions LangInfo;
+ HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+ std::string TargetTriple;
+ std::string Predefines;
+ unsigned Counter;
+
+ llvm::OwningPtr<ASTReader> Reader;
+
+ Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(),
+ AST->getDiagnostics()));
+ Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+ Predefines, Counter));
+
+ switch (Reader->ReadAST(Filename, ASTReader::MainFile)) {
+ case ASTReader::Success:
+ break;
+
+ case ASTReader::Failure:
+ case ASTReader::IgnorePCH:
+ AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
+ return NULL;
+ }
+
+ AST->OriginalSourceFile = Reader->getOriginalSourceFile();
+
+ // AST file loaded successfully. Now create the preprocessor.
+
+ // Get information about the target being compiled for.
+ //
+ // FIXME: This is broken, we should store the TargetOptions in the AST file.
+ TargetOptions TargetOpts;
+ TargetOpts.ABI = "";
+ TargetOpts.CXXABI = "";
+ TargetOpts.CPU = "";
+ TargetOpts.Features.clear();
+ TargetOpts.Triple = TargetTriple;
+ AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
+ TargetOpts));
+ AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
+ *AST->Target.get(),
+ AST->getSourceManager(), HeaderInfo));
+ Preprocessor &PP = *AST->PP.get();
+
+ PP.setPredefines(Reader->getSuggestedPredefines());
+ PP.setCounterValue(Counter);
+ Reader->setPreprocessor(PP);
+
+ // Create and initialize the ASTContext.
+
+ AST->Ctx.reset(new ASTContext(LangInfo,
+ AST->getSourceManager(),
+ *AST->Target.get(),
+ PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ PP.getBuiltinInfo(),
+ /* size_reserve = */0));
+ ASTContext &Context = *AST->Ctx.get();
+
+ Reader->InitializeContext(Context);
+
+ // Attach the AST reader to the AST context as an external AST
+ // source, so that declarations will be deserialized from the
+ // AST file as needed.
+ ASTReader *ReaderPtr = Reader.get();
+ llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
+ Context.setExternalSource(Source);
+
+ // Create an AST consumer, even though it isn't used.
+ AST->Consumer.reset(new ASTConsumer);
+
+ // Create a semantic analysis object and tell the AST reader about it.
+ AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
+ AST->TheSema->Initialize();
+ ReaderPtr->InitializeSema(*AST->TheSema);
+
+ return AST.take();
+}
+
+namespace {
+
+/// \brief Preprocessor callback class that updates a hash value with the names
+/// of all macros that have been defined by the translation unit.
+class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
+ unsigned &Hash;
+
+public:
+ explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
+
+ virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
+ Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
+ }
+};
+
+/// \brief Add the given declaration to the hash of all top-level entities.
+void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
+ if (!D)
+ return;
+
+ DeclContext *DC = D->getDeclContext();
+ if (!DC)
+ return;
+
+ if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
+ return;
+
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ if (ND->getIdentifier())
+ Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash);
+ else if (DeclarationName Name = ND->getDeclName()) {
+ std::string NameStr = Name.getAsString();
+ Hash = llvm::HashString(NameStr, Hash);
+ }
+ return;
+ }
+
+ if (ObjCForwardProtocolDecl *Forward
+ = dyn_cast<ObjCForwardProtocolDecl>(D)) {
+ for (ObjCForwardProtocolDecl::protocol_iterator
+ P = Forward->protocol_begin(),
+ PEnd = Forward->protocol_end();
+ P != PEnd; ++P)
+ AddTopLevelDeclarationToHash(*P, Hash);
+ return;
+ }
+
+ if (ObjCClassDecl *Class = llvm::dyn_cast<ObjCClassDecl>(D)) {
+ for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
+ I != IEnd; ++I)
+ AddTopLevelDeclarationToHash(I->getInterface(), Hash);
+ return;
+ }
+}
+
+class TopLevelDeclTrackerConsumer : public ASTConsumer {
+ ASTUnit &Unit;
+ unsigned &Hash;
+
+public:
+ TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
+ : Unit(_Unit), Hash(Hash) {
+ Hash = 0;
+ }
+
+ void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
+ Decl *D = *it;
+ // FIXME: Currently ObjC method declarations are incorrectly being
+ // reported as top-level declarations, even though their DeclContext
+ // is the containing ObjC @interface/@implementation. This is a
+ // fundamental problem in the parser right now.
+ if (isa<ObjCMethodDecl>(D))
+ continue;
+
+ AddTopLevelDeclarationToHash(D, Hash);
+ Unit.addTopLevelDecl(D);
+ }
+ }
+
+ // We're not interested in "interesting" decls.
+ void HandleInterestingDecl(DeclGroupRef) {}
+};
+
+class TopLevelDeclTrackerAction : public ASTFrontendAction {
+public:
+ ASTUnit &Unit;
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ CI.getPreprocessor().addPPCallbacks(
+ new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
+ return new TopLevelDeclTrackerConsumer(Unit,
+ Unit.getCurrentTopLevelHashValue());
+ }
+
+public:
+ TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
+
+ virtual bool hasCodeCompletionSupport() const { return false; }
+ virtual bool usesCompleteTranslationUnit() {
+ return Unit.isCompleteTranslationUnit();
+ }
+};
+
+class PrecompilePreambleConsumer : public PCHGenerator,
+ public ASTSerializationListener {
+ ASTUnit &Unit;
+ unsigned &Hash;
+ std::vector<Decl *> TopLevelDecls;
+
+public:
+ PrecompilePreambleConsumer(ASTUnit &Unit,
+ const Preprocessor &PP, bool Chaining,
+ const char *isysroot, llvm::raw_ostream *Out)
+ : PCHGenerator(PP, "", Chaining, isysroot, Out), Unit(Unit),
+ Hash(Unit.getCurrentTopLevelHashValue()) {
+ Hash = 0;
+ }
+
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
+ Decl *D = *it;
+ // FIXME: Currently ObjC method declarations are incorrectly being
+ // reported as top-level declarations, even though their DeclContext
+ // is the containing ObjC @interface/@implementation. This is a
+ // fundamental problem in the parser right now.
+ if (isa<ObjCMethodDecl>(D))
+ continue;
+ AddTopLevelDeclarationToHash(D, Hash);
+ TopLevelDecls.push_back(D);
+ }
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ PCHGenerator::HandleTranslationUnit(Ctx);
+ if (!Unit.getDiagnostics().hasErrorOccurred()) {
+ // Translate the top-level declarations we captured during
+ // parsing into declaration IDs in the precompiled
+ // preamble. This will allow us to deserialize those top-level
+ // declarations when requested.
+ for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
+ Unit.addTopLevelDeclFromPreamble(
+ getWriter().getDeclID(TopLevelDecls[I]));
+ }
+ }
+
+ virtual void SerializedPreprocessedEntity(PreprocessedEntity *Entity,
+ uint64_t Offset) {
+ Unit.addPreprocessedEntityFromPreamble(Offset);
+ }
+
+ virtual ASTSerializationListener *GetASTSerializationListener() {
+ return this;
+ }
+};
+
+class PrecompilePreambleAction : public ASTFrontendAction {
+ ASTUnit &Unit;
+
+public:
+ explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ std::string Sysroot;
+ std::string OutputFile;
+ llvm::raw_ostream *OS = 0;
+ bool Chaining;
+ if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
+ OutputFile,
+ OS, Chaining))
+ return 0;
+
+ const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+ Sysroot.c_str() : 0;
+ CI.getPreprocessor().addPPCallbacks(
+ new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
+ return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
+ isysroot, OS);
+ }
+
+ virtual bool hasCodeCompletionSupport() const { return false; }
+ virtual bool hasASTFileSupport() const { return false; }
+ virtual bool usesCompleteTranslationUnit() { return false; }
+};
+
+}
+
+/// Parse the source file into a translation unit using the given compiler
+/// invocation, replacing the current translation unit.
+///
+/// \returns True if a failure occurred that causes the ASTUnit not to
+/// contain any translation-unit information, false otherwise.
+bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
+ delete SavedMainFileBuffer;
+ SavedMainFileBuffer = 0;
+
+ if (!Invocation.get()) {
+ delete OverrideMainBuffer;
+ return true;
+ }
+
+ // Create the compiler instance to use for building the AST.
+ CompilerInstance Clang;
+ Clang.setInvocation(Invocation.take());
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing any diagnostics that would
+ // otherwise be dropped.
+ Clang.setDiagnostics(&getDiagnostics());
+
+ // Create the target instance.
+ Clang.getTargetOpts().Features = TargetFeatures;
+ Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+ Clang.getTargetOpts()));
+ if (!Clang.hasTarget()) {
+ delete OverrideMainBuffer;
+ return true;
+ }
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+ assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+ "Invocation must have exactly one source file!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
+ "FIXME: AST inputs not yet supported here!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+ "IR inputs not support here!");
+
+ // Configure the various subsystems.
+ // FIXME: Should we retain the previous file manager?
+ FileSystemOpts = Clang.getFileSystemOpts();
+ FileMgr.reset(new FileManager(Clang.getFileSystemOpts()));
+ SourceMgr.reset(new SourceManager(getDiagnostics(), *FileMgr));
+ TheSema.reset();
+ Ctx.reset();
+ PP.reset();
+
+ // Clear out old caches and data.
+ TopLevelDecls.clear();
+ PreprocessedEntities.clear();
+ CleanTemporaryFiles();
+ PreprocessedEntitiesByFile.clear();
+
+ if (!OverrideMainBuffer) {
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
+ TopLevelDeclsInPreamble.clear();
+ PreprocessedEntitiesInPreamble.clear();
+ }
+
+ // Create a file manager object to provide access to and cache the filesystem.
+ Clang.setFileManager(&getFileManager());
+
+ // Create the source manager.
+ Clang.setSourceManager(&getSourceManager());
+
+ // If the main file has been overridden due to the use of a preamble,
+ // make that override happen and introduce the preamble.
+ PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
+ std::string PriorImplicitPCHInclude;
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
+ PreprocessorOpts.PrecompiledPreambleBytes.second
+ = PreambleEndsAtStartOfLine;
+ PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
+ PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
+ PreprocessorOpts.DisablePCHValidation = true;
+
+ // The stored diagnostic has the old source manager in it; update
+ // the locations to refer into the new source manager. Since we've
+ // been careful to make sure that the source manager's state
+ // before and after are identical, so that we can reuse the source
+ // location itself.
+ for (unsigned I = NumStoredDiagnosticsFromDriver,
+ N = StoredDiagnostics.size();
+ I < N; ++I) {
+ FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
+ getSourceManager());
+ StoredDiagnostics[I].setLocation(Loc);
+ }
+
+ // Keep track of the override buffer;
+ SavedMainFileBuffer = OverrideMainBuffer;
+ } else {
+ PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
+ PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+ }
+
+ llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
+ Act.reset(new TopLevelDeclTrackerAction(*this));
+ if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Clang.getFrontendOpts().Inputs[0].first))
+ goto error;
+
+ Act->Execute();
+
+ // Steal the created target, context, and preprocessor, and take back the
+ // source and file managers.
+ TheSema.reset(Clang.takeSema());
+ Consumer.reset(Clang.takeASTConsumer());
+ Ctx.reset(Clang.takeASTContext());
+ PP.reset(Clang.takePreprocessor());
+ Clang.takeSourceManager();
+ Clang.takeFileManager();
+ Target.reset(Clang.takeTarget());
+
+ Act->EndSourceFile();
+
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
+ }
+
+ Invocation.reset(Clang.takeInvocation());
+ return false;
+
+error:
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
+ delete OverrideMainBuffer;
+ SavedMainFileBuffer = 0;
+ }
+
+ StoredDiagnostics.clear();
+ Clang.takeSourceManager();
+ Clang.takeFileManager();
+ Invocation.reset(Clang.takeInvocation());
+ return true;
+}
+
+/// \brief Simple function to retrieve a path for a preamble precompiled header.
+static std::string GetPreamblePCHPath() {
+ // FIXME: This is lame; sys::Path should provide this function (in particular,
+ // it should know how to find the temporary files dir).
+ // FIXME: This is really lame. I copied this code from the Driver!
+ // FIXME: This is a hack so that we can override the preamble file during
+ // crash-recovery testing, which is the only case where the preamble files
+ // are not necessarily cleaned up.
+ const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
+ if (TmpFile)
+ return TmpFile;
+
+ std::string Error;
+ const char *TmpDir = ::getenv("TMPDIR");
+ if (!TmpDir)
+ TmpDir = ::getenv("TEMP");
+ if (!TmpDir)
+ TmpDir = ::getenv("TMP");
+#ifdef LLVM_ON_WIN32
+ if (!TmpDir)
+ TmpDir = ::getenv("USERPROFILE");
+#endif
+ if (!TmpDir)
+ TmpDir = "/tmp";
+ llvm::sys::Path P(TmpDir);
+ P.createDirectoryOnDisk(true);
+ P.appendComponent("preamble");
+ P.appendSuffix("pch");
+ if (P.createTemporaryFileOnDisk())
+ return std::string();
+
+ return P.str();
+}
+
+/// \brief Compute the preamble for the main file, providing the source buffer
+/// that corresponds to the main file along with a pair (bytes, start-of-line)
+/// that describes the preamble.
+std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
+ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines, bool &CreatedBuffer) {
+ FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
+ CreatedBuffer = false;
+
+ // Try to determine if the main file has been remapped, either from the
+ // command line (to another file) or directly through the compiler invocation
+ // (to a memory buffer).
+ llvm::MemoryBuffer *Buffer = 0;
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+ if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
+ // Check whether there is a file-file remapping of the main file
+ for (PreprocessorOptions::remapped_file_iterator
+ M = PreprocessorOpts.remapped_file_begin(),
+ E = PreprocessorOpts.remapped_file_end();
+ M != E;
+ ++M) {
+ llvm::sys::PathWithStatus MPath(M->first);
+ if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
+ if (MainFileStatus->uniqueID == MStatus->uniqueID) {
+ // We found a remapping. Try to load the resulting, remapped source.
+ if (CreatedBuffer) {
+ delete Buffer;
+ CreatedBuffer = false;
+ }
+
+ Buffer = getBufferForFile(M->second);
+ if (!Buffer)
+ return std::make_pair((llvm::MemoryBuffer*)0,
+ std::make_pair(0, true));
+ CreatedBuffer = true;
+ }
+ }
+ }
+
+ // Check whether there is a file-buffer remapping. It supercedes the
+ // file-file remapping.
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ M = PreprocessorOpts.remapped_file_buffer_begin(),
+ E = PreprocessorOpts.remapped_file_buffer_end();
+ M != E;
+ ++M) {
+ llvm::sys::PathWithStatus MPath(M->first);
+ if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
+ if (MainFileStatus->uniqueID == MStatus->uniqueID) {
+ // We found a remapping.
+ if (CreatedBuffer) {
+ delete Buffer;
+ CreatedBuffer = false;
+ }
+
+ Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
+ }
+ }
+ }
+ }
+
+ // If the main source file was not remapped, load it now.
+ if (!Buffer) {
+ Buffer = getBufferForFile(FrontendOpts.Inputs[0].second);
+ if (!Buffer)
+ return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
+
+ CreatedBuffer = true;
+ }
+
+ return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines));
+}
+
+static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
+ unsigned NewSize,
+ llvm::StringRef NewName) {
+ llvm::MemoryBuffer *Result
+ = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
+ memcpy(const_cast<char*>(Result->getBufferStart()),
+ Old->getBufferStart(), Old->getBufferSize());
+ memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
+ ' ', NewSize - Old->getBufferSize() - 1);
+ const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
+
+ return Result;
+}
+
+/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
+/// the source file.
+///
+/// This routine will compute the preamble of the main source file. If a
+/// non-trivial preamble is found, it will precompile that preamble into a
+/// precompiled header so that the precompiled preamble can be used to reduce
+/// reparsing time. If a precompiled preamble has already been constructed,
+/// this routine will determine if it is still valid and, if so, avoid
+/// rebuilding the precompiled preamble.
+///
+/// \param AllowRebuild When true (the default), this routine is
+/// allowed to rebuild the precompiled preamble if it is found to be
+/// out-of-date.
+///
+/// \param MaxLines When non-zero, the maximum number of lines that
+/// can occur within the preamble.
+///
+/// \returns If the precompiled preamble can be used, returns a newly-allocated
+/// buffer that should be used in place of the main file when doing so.
+/// Otherwise, returns a NULL pointer.
+llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
+ bool AllowRebuild,
+ unsigned MaxLines) {
+ FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts
+ = PreambleInvocation.getPreprocessorOpts();
+
+ bool CreatedPreambleBuffer = false;
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
+ = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer);
+
+ // If ComputePreamble() Take ownership of the
+ llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer;
+ if (CreatedPreambleBuffer)
+ OwnedPreambleBuffer.reset(NewPreamble.first);
+
+ if (!NewPreamble.second.first) {
+ // We couldn't find a preamble in the main source. Clear out the current
+ // preamble, if we have one. It's obviously no good any more.
+ Preamble.clear();
+ if (!PreambleFile.empty()) {
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+ PreambleFile.clear();
+ }
+
+ // The next time we actually see a preamble, precompile it.
+ PreambleRebuildCounter = 1;
+ return 0;
+ }
+
+ if (!Preamble.empty()) {
+ // We've previously computed a preamble. Check whether we have the same
+ // preamble now that we did before, and that there's enough space in
+ // the main-file buffer within the precompiled preamble to fit the
+ // new main file.
+ if (Preamble.size() == NewPreamble.second.first &&
+ PreambleEndsAtStartOfLine == NewPreamble.second.second &&
+ NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
+ memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
+ NewPreamble.second.first) == 0) {
+ // The preamble has not changed. We may be able to re-use the precompiled
+ // preamble.
+
+ // Check that none of the files used by the preamble have changed.
+ bool AnyFileChanged = false;
+
+ // First, make a record of those files that have been overridden via
+ // remapping or unsaved_files.
+ llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
+ for (PreprocessorOptions::remapped_file_iterator
+ R = PreprocessorOpts.remapped_file_begin(),
+ REnd = PreprocessorOpts.remapped_file_end();
+ !AnyFileChanged && R != REnd;
+ ++R) {
+ struct stat StatBuf;
+ if (stat(R->second.c_str(), &StatBuf)) {
+ // If we can't stat the file we're remapping to, assume that something
+ // horrible happened.
+ AnyFileChanged = true;
+ break;
+ }
+
+ OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
+ StatBuf.st_mtime);
+ }
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ R = PreprocessorOpts.remapped_file_buffer_begin(),
+ REnd = PreprocessorOpts.remapped_file_buffer_end();
+ !AnyFileChanged && R != REnd;
+ ++R) {
+ // FIXME: Should we actually compare the contents of file->buffer
+ // remappings?
+ OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
+ 0);
+ }
+
+ // Check whether anything has changed.
+ for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
+ F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
+ !AnyFileChanged && F != FEnd;
+ ++F) {
+ llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
+ = OverriddenFiles.find(F->first());
+ if (Overridden != OverriddenFiles.end()) {
+ // This file was remapped; check whether the newly-mapped file
+ // matches up with the previous mapping.
+ if (Overridden->second != F->second)
+ AnyFileChanged = true;
+ continue;
+ }
+
+ // The file was not remapped; check whether it has changed on disk.
+ struct stat StatBuf;
+ if (stat(F->first(), &StatBuf)) {
+ // If we can't stat the file, assume that something horrible happened.
+ AnyFileChanged = true;
+ } else if (StatBuf.st_size != F->second.first ||
+ StatBuf.st_mtime != F->second.second)
+ AnyFileChanged = true;
+ }
+
+ if (!AnyFileChanged) {
+ // Okay! We can re-use the precompiled preamble.
+
+ // Set the state of the diagnostic object to mimic its state
+ // after parsing the preamble.
+ // FIXME: This won't catch any #pragma push warning changes that
+ // have occurred in the preamble.
+ getDiagnostics().Reset();
+ ProcessWarningOptions(getDiagnostics(),
+ PreambleInvocation.getDiagnosticOpts());
+ getDiagnostics().setNumWarnings(NumWarningsInPreamble);
+ if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
+ StoredDiagnostics.end());
+
+ // Create a version of the main file buffer that is padded to
+ // buffer size we reserved when creating the preamble.
+ return CreatePaddedMainFileBuffer(NewPreamble.first,
+ PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+ }
+ }
+
+ // If we aren't allowed to rebuild the precompiled preamble, just
+ // return now.
+ if (!AllowRebuild)
+ return 0;
+
+ // We can't reuse the previously-computed preamble. Build a new one.
+ Preamble.clear();
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+ PreambleRebuildCounter = 1;
+ } else if (!AllowRebuild) {
+ // We aren't allowed to rebuild the precompiled preamble; just
+ // return now.
+ return 0;
+ }
+
+ // If the preamble rebuild counter > 1, it's because we previously
+ // failed to build a preamble and we're not yet ready to try
+ // again. Decrement the counter and return a failure.
+ if (PreambleRebuildCounter > 1) {
+ --PreambleRebuildCounter;
+ return 0;
+ }
+
+ // Create a temporary file for the precompiled preamble. In rare
+ // circumstances, this can fail.
+ std::string PreamblePCHPath = GetPreamblePCHPath();
+ if (PreamblePCHPath.empty()) {
+ // Try again next time.
+ PreambleRebuildCounter = 1;
+ return 0;
+ }
+
+ // We did not previously compute a preamble, or it can't be reused anyway.
+ SimpleTimer PreambleTimer(WantTiming);
+ PreambleTimer.setOutput("Precompiling preamble");
+
+ // Create a new buffer that stores the preamble. The buffer also contains
+ // extra space for the original contents of the file (which will be present
+ // when we actually parse the file) along with more room in case the file
+ // grows.
+ PreambleReservedSize = NewPreamble.first->getBufferSize();
+ if (PreambleReservedSize < 4096)
+ PreambleReservedSize = 8191;
+ else
+ PreambleReservedSize *= 2;
+
+ // Save the preamble text for later; we'll need to compare against it for
+ // subsequent reparses.
+ Preamble.assign(NewPreamble.first->getBufferStart(),
+ NewPreamble.first->getBufferStart()
+ + NewPreamble.second.first);
+ PreambleEndsAtStartOfLine = NewPreamble.second.second;
+
+ delete PreambleBuffer;
+ PreambleBuffer
+ = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+ memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
+ NewPreamble.first->getBufferStart(), Preamble.size());
+ memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
+ ' ', PreambleReservedSize - Preamble.size() - 1);
+ const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
+
+ // Remap the main source file to the preamble buffer.
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+ PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
+
+ // Tell the compiler invocation to generate a temporary precompiled header.
+ FrontendOpts.ProgramAction = frontend::GeneratePCH;
+ FrontendOpts.ChainedPCH = true;
+ // FIXME: Generate the precompiled header into memory?
+ FrontendOpts.OutputFile = PreamblePCHPath;
+ PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
+ PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+
+ // Create the compiler instance to use for building the precompiled preamble.
+ CompilerInstance Clang;
+ Clang.setInvocation(&PreambleInvocation);
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing all of the diagnostics produced.
+ Clang.setDiagnostics(&getDiagnostics());
+
+ // Create the target instance.
+ Clang.getTargetOpts().Features = TargetFeatures;
+ Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+ Clang.getTargetOpts()));
+ if (!Clang.hasTarget()) {
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+ assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+ "Invocation must have exactly one source file!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
+ "FIXME: AST inputs not yet supported here!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+ "IR inputs not support here!");
+
+ // Clear out old caches and data.
+ getDiagnostics().Reset();
+ ProcessWarningOptions(getDiagnostics(), Clang.getDiagnosticOpts());
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
+ TopLevelDecls.clear();
+ TopLevelDeclsInPreamble.clear();
+ PreprocessedEntities.clear();
+ PreprocessedEntitiesInPreamble.clear();
+
+ // Create a file manager object to provide access to and cache the filesystem.
+ Clang.setFileManager(new FileManager(Clang.getFileSystemOpts()));
+
+ // Create the source manager.
+ Clang.setSourceManager(new SourceManager(getDiagnostics(),
+ Clang.getFileManager()));
+
+ llvm::OwningPtr<PrecompilePreambleAction> Act;
+ Act.reset(new PrecompilePreambleAction(*this));
+ if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Clang.getFrontendOpts().Inputs[0].first)) {
+ Clang.takeInvocation();
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ Act->Execute();
+ Act->EndSourceFile();
+ Clang.takeInvocation();
+
+ if (Diagnostics->hasErrorOccurred()) {
+ // There were errors parsing the preamble, so no precompiled header was
+ // generated. Forget that we even tried.
+ // FIXME: Should we leave a note for ourselves to try again?
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ TopLevelDeclsInPreamble.clear();
+ PreprocessedEntities.clear();
+ PreprocessedEntitiesInPreamble.clear();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ // Keep track of the preamble we precompiled.
+ PreambleFile = FrontendOpts.OutputFile;
+ NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
+ NumWarningsInPreamble = getDiagnostics().getNumWarnings();
+
+ // Keep track of all of the files that the source manager knows about,
+ // so we can verify whether they have changed or not.
+ FilesInPreamble.clear();
+ SourceManager &SourceMgr = Clang.getSourceManager();
+ const llvm::MemoryBuffer *MainFileBuffer
+ = SourceMgr.getBuffer(SourceMgr.getMainFileID());
+ for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
+ FEnd = SourceMgr.fileinfo_end();
+ F != FEnd;
+ ++F) {
+ const FileEntry *File = F->second->Entry;
+ if (!File || F->second->getRawBuffer() == MainFileBuffer)
+ continue;
+
+ FilesInPreamble[File->getName()]
+ = std::make_pair(F->second->getSize(), File->getModificationTime());
+ }
+
+ PreambleRebuildCounter = 1;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+
+ // If the hash of top-level entities differs from the hash of the top-level
+ // entities the last time we rebuilt the preamble, clear out the completion
+ // cache.
+ if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
+ CompletionCacheTopLevelHashValue = 0;
+ PreambleTopLevelHashValue = CurrentTopLevelHashValue;
+ }
+
+ return CreatePaddedMainFileBuffer(NewPreamble.first,
+ PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+}
+
+void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
+ std::vector<Decl *> Resolved;
+ Resolved.reserve(TopLevelDeclsInPreamble.size());
+ ExternalASTSource &Source = *getASTContext().getExternalSource();
+ for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
+ // Resolve the declaration ID to an actual declaration, possibly
+ // deserializing the declaration in the process.
+ Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
+ if (D)
+ Resolved.push_back(D);
+ }
+ TopLevelDeclsInPreamble.clear();
+ TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
+}
+
+void ASTUnit::RealizePreprocessedEntitiesFromPreamble() {
+ if (!PP)
+ return;
+
+ PreprocessingRecord *PPRec = PP->getPreprocessingRecord();
+ if (!PPRec)
+ return;
+
+ ExternalPreprocessingRecordSource *External = PPRec->getExternalSource();
+ if (!External)
+ return;
+
+ for (unsigned I = 0, N = PreprocessedEntitiesInPreamble.size(); I != N; ++I) {
+ if (PreprocessedEntity *PE
+ = External->ReadPreprocessedEntityAtOffset(
+ PreprocessedEntitiesInPreamble[I]))
+ PreprocessedEntities.push_back(PE);
+ }
+
+ if (PreprocessedEntities.empty())
+ return;
+
+ PreprocessedEntities.insert(PreprocessedEntities.end(),
+ PPRec->begin(true), PPRec->end(true));
+}
+
+ASTUnit::pp_entity_iterator ASTUnit::pp_entity_begin() {
+ if (!PreprocessedEntitiesInPreamble.empty() &&
+ PreprocessedEntities.empty())
+ RealizePreprocessedEntitiesFromPreamble();
+
+ if (PreprocessedEntities.empty())
+ if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
+ return PPRec->begin(true);
+
+ return PreprocessedEntities.begin();
+}
+
+ASTUnit::pp_entity_iterator ASTUnit::pp_entity_end() {
+ if (!PreprocessedEntitiesInPreamble.empty() &&
+ PreprocessedEntities.empty())
+ RealizePreprocessedEntitiesFromPreamble();
+
+ if (PreprocessedEntities.empty())
+ if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
+ return PPRec->end(true);
+
+ return PreprocessedEntities.end();
+}
+
+unsigned ASTUnit::getMaxPCHLevel() const {
+ if (!getOnlyLocalDecls())
+ return Decl::MaxPCHLevel;
+
+ return 0;
+}
+
+llvm::StringRef ASTUnit::getMainFileName() const {
+ return Invocation->getFrontendOpts().Inputs[0].second;
+}
+
+bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
+ if (!Invocation)
+ return true;
+
+ // We'll manage file buffers ourselves.
+ Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
+ Invocation->getFrontendOpts().DisableFree = false;
+ ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
+
+ // Save the target features.
+ TargetFeatures = Invocation->getTargetOpts().Features;
+
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ if (PrecompilePreamble) {
+ PreambleRebuildCounter = 2;
+ OverrideMainBuffer
+ = getMainBufferWithPrecompiledPreamble(*Invocation);
+ }
+
+ SimpleTimer ParsingTimer(WantTiming);
+ ParsingTimer.setOutput("Parsing " + getMainFileName());
+
+ return Parse(OverrideMainBuffer);
+}
+
+ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ bool OnlyLocalDecls,
+ bool CaptureDiagnostics,
+ bool PrecompilePreamble,
+ bool CompleteTranslationUnit,
+ bool CacheCodeCompletionResults) {
+ // Create the AST unit.
+ llvm::OwningPtr<ASTUnit> AST;
+ AST.reset(new ASTUnit(false));
+ ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
+ AST->Diagnostics = Diags;
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->CaptureDiagnostics = CaptureDiagnostics;
+ AST->CompleteTranslationUnit = CompleteTranslationUnit;
+ AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->Invocation.reset(CI);
+
+ return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
+}
+
+ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
+ const char **ArgEnd,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ llvm::StringRef ResourceFilesPath,
+ bool OnlyLocalDecls,
+ bool CaptureDiagnostics,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles,
+ bool PrecompilePreamble,
+ bool CompleteTranslationUnit,
+ bool CacheCodeCompletionResults,
+ bool CXXPrecompilePreamble,
+ bool CXXChainedPCH) {
+ if (!Diags.getPtr()) {
+ // No diagnostics engine was provided, so create our own diagnostics object
+ // with the default options.
+ DiagnosticOptions DiagOpts;
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,
+ ArgBegin);
+ }
+
+ llvm::SmallVector<const char *, 16> Args;
+ Args.push_back("<clang>"); // FIXME: Remove dummy argument.
+ Args.insert(Args.end(), ArgBegin, ArgEnd);
+
+ // FIXME: Find a cleaner way to force the driver into restricted modes. We
+ // also want to force it to use clang.
+ Args.push_back("-fsyntax-only");
+
+ llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+
+ llvm::OwningPtr<CompilerInvocation> CI;
+
+ {
+ CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
+ StoredDiagnostics);
+
+ // FIXME: We shouldn't have to pass in the path info.
+ driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
+ "a.out", false, false, *Diags);
+
+ // Don't check that inputs exist, they have been remapped.
+ TheDriver.setCheckInputsExist(false);
+
+ llvm::OwningPtr<driver::Compilation> C(
+ TheDriver.BuildCompilation(Args.size(), Args.data()));
+
+ // We expect to get back exactly one command job, if we didn't something
+ // failed.
+ const driver::JobList &Jobs = C->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+ llvm::SmallString<256> Msg;
+ llvm::raw_svector_ostream OS(Msg);
+ C->PrintJob(OS, C->getJobs(), "; ", true);
+ Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
+ return 0;
+ }
+
+ const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
+ if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+ Diags->Report(diag::err_fe_expected_clang_command);
+ return 0;
+ }
+
+ const driver::ArgStringList &CCArgs = Cmd->getArguments();
+ CI.reset(new CompilerInvocation);
+ CompilerInvocation::CreateFromArgs(*CI,
+ const_cast<const char **>(CCArgs.data()),
+ const_cast<const char **>(CCArgs.data()) +
+ CCArgs.size(),
+ *Diags);
+ }
+
+ // Override any files that need remapping
+ for (unsigned I = 0; I != NumRemappedFiles; ++I)
+ CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+
+ // Override the resources path.
+ CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
+
+ // Check whether we should precompile the preamble and/or use chained PCH.
+ // FIXME: This is a temporary hack while we debug C++ chained PCH.
+ if (CI->getLangOpts().CPlusPlus) {
+ PrecompilePreamble = PrecompilePreamble && CXXPrecompilePreamble;
+
+ if (PrecompilePreamble && !CXXChainedPCH &&
+ !CI->getPreprocessorOpts().ImplicitPCHInclude.empty())
+ PrecompilePreamble = false;
+ }
+
+ // Create the AST unit.
+ llvm::OwningPtr<ASTUnit> AST;
+ AST.reset(new ASTUnit(false));
+ ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
+ AST->Diagnostics = Diags;
+
+ AST->FileMgr.reset(new FileManager(FileSystemOptions()));
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->CaptureDiagnostics = CaptureDiagnostics;
+ AST->CompleteTranslationUnit = CompleteTranslationUnit;
+ AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
+ AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
+ AST->StoredDiagnostics.swap(StoredDiagnostics);
+ AST->Invocation.reset(CI.take());
+ return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take();
+}
+
+bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
+ if (!Invocation.get())
+ return true;
+
+ SimpleTimer ParsingTimer(WantTiming);
+ ParsingTimer.setOutput("Reparsing " + getMainFileName());
+
+ // Remap files.
+ PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+ PPOpts.DisableStatCache = true;
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ R = PPOpts.remapped_file_buffer_begin(),
+ REnd = PPOpts.remapped_file_buffer_end();
+ R != REnd;
+ ++R) {
+ delete R->second;
+ }
+ Invocation->getPreprocessorOpts().clearRemappedFiles();
+ for (unsigned I = 0; I != NumRemappedFiles; ++I)
+ Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+
+ // If we have a preamble file lying around, or if we might try to
+ // build a precompiled preamble, do so now.
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
+ OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
+
+ // Clear out the diagnostics state.
+ if (!OverrideMainBuffer) {
+ getDiagnostics().Reset();
+ ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
+ }
+
+ // Parse the sources
+ bool Result = Parse(OverrideMainBuffer);
+
+ // If we're caching global code-completion results, and the top-level
+ // declarations have changed, clear out the code-completion cache.
+ if (!Result && ShouldCacheCodeCompletionResults &&
+ CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
+ CacheCodeCompletionResults();
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------//
+// Code completion
+//----------------------------------------------------------------------------//
+
+namespace {
+ /// \brief Code completion consumer that combines the cached code-completion
+ /// results from an ASTUnit with the code-completion results provided to it,
+ /// then passes the result on to
+ class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
+ unsigned NormalContexts;
+ ASTUnit &AST;
+ CodeCompleteConsumer &Next;
+
+ public:
+ AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
+ bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals)
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ Next.isOutputBinary()), AST(AST), Next(Next)
+ {
+ // Compute the set of contexts in which we will look when we don't have
+ // any information about the specific context.
+ NormalContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
+ | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
+ | (1 << (CodeCompletionContext::CCC_Recovery - 1));
+
+ if (AST.getASTContext().getLangOptions().CPlusPlus)
+ NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+ | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+ }
+
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults);
+
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) {
+ Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
+ }
+
+ virtual CodeCompletionAllocator &getAllocator() {
+ return Next.getAllocator();
+ }
+ };
+}
+
+/// \brief Helper function that computes which global names are hidden by the
+/// local code-completion results.
+static void CalculateHiddenNames(const CodeCompletionContext &Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults,
+ ASTContext &Ctx,
+ llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
+ bool OnlyTagNames = false;
+ switch (Context.getKind()) {
+ case CodeCompletionContext::CCC_Recovery:
+ case CodeCompletionContext::CCC_TopLevel:
+ case CodeCompletionContext::CCC_ObjCInterface:
+ case CodeCompletionContext::CCC_ObjCImplementation:
+ case CodeCompletionContext::CCC_ObjCIvarList:
+ case CodeCompletionContext::CCC_ClassStructUnion:
+ case CodeCompletionContext::CCC_Statement:
+ case CodeCompletionContext::CCC_Expression:
+ case CodeCompletionContext::CCC_ObjCMessageReceiver:
+ case CodeCompletionContext::CCC_MemberAccess:
+ case CodeCompletionContext::CCC_Namespace:
+ case CodeCompletionContext::CCC_Type:
+ case CodeCompletionContext::CCC_Name:
+ case CodeCompletionContext::CCC_PotentiallyQualifiedName:
+ case CodeCompletionContext::CCC_ParenthesizedExpression:
+ break;
+
+ case CodeCompletionContext::CCC_EnumTag:
+ case CodeCompletionContext::CCC_UnionTag:
+ case CodeCompletionContext::CCC_ClassOrStructTag:
+ OnlyTagNames = true;
+ break;
+
+ case CodeCompletionContext::CCC_ObjCProtocolName:
+ case CodeCompletionContext::CCC_MacroName:
+ case CodeCompletionContext::CCC_MacroNameUse:
+ case CodeCompletionContext::CCC_PreprocessorExpression:
+ case CodeCompletionContext::CCC_PreprocessorDirective:
+ case CodeCompletionContext::CCC_NaturalLanguage:
+ case CodeCompletionContext::CCC_SelectorName:
+ case CodeCompletionContext::CCC_TypeQualifiers:
+ case CodeCompletionContext::CCC_Other:
+ case CodeCompletionContext::CCC_OtherWithMacros:
+ // We're looking for nothing, or we're looking for names that cannot
+ // be hidden.
+ return;
+ }
+
+ typedef CodeCompletionResult Result;
+ for (unsigned I = 0; I != NumResults; ++I) {
+ if (Results[I].Kind != Result::RK_Declaration)
+ continue;
+
+ unsigned IDNS
+ = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
+
+ bool Hiding = false;
+ if (OnlyTagNames)
+ Hiding = (IDNS & Decl::IDNS_Tag);
+ else {
+ unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
+ Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
+ Decl::IDNS_NonMemberOperator);
+ if (Ctx.getLangOptions().CPlusPlus)
+ HiddenIDNS |= Decl::IDNS_Tag;
+ Hiding = (IDNS & HiddenIDNS);
+ }
+
+ if (!Hiding)
+ continue;
+
+ DeclarationName Name = Results[I].Declaration->getDeclName();
+ if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
+ HiddenNames.insert(Identifier->getName());
+ else
+ HiddenNames.insert(Name.getAsString());
+ }
+}
+
+
+void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
+ // Merge the results we were given with the results we cached.
+ bool AddedResult = false;
+ unsigned InContexts
+ = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts
+ : (1 << (Context.getKind() - 1)));
+
+ // Contains the set of names that are hidden by "local" completion results.
+ llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
+ typedef CodeCompletionResult Result;
+ llvm::SmallVector<Result, 8> AllResults;
+ for (ASTUnit::cached_completion_iterator
+ C = AST.cached_completion_begin(),
+ CEnd = AST.cached_completion_end();
+ C != CEnd; ++C) {
+ // If the context we are in matches any of the contexts we are
+ // interested in, we'll add this result.
+ if ((C->ShowInContexts & InContexts) == 0)
+ continue;
+
+ // If we haven't added any results previously, do so now.
+ if (!AddedResult) {
+ CalculateHiddenNames(Context, Results, NumResults, S.Context,
+ HiddenNames);
+ AllResults.insert(AllResults.end(), Results, Results + NumResults);
+ AddedResult = true;
+ }
+
+ // Determine whether this global completion result is hidden by a local
+ // completion result. If so, skip it.
+ if (C->Kind != CXCursor_MacroDefinition &&
+ HiddenNames.count(C->Completion->getTypedText()))
+ continue;
+
+ // Adjust priority based on similar type classes.
+ unsigned Priority = C->Priority;
+ CXCursorKind CursorKind = C->Kind;
+ CodeCompletionString *Completion = C->Completion;
+ if (!Context.getPreferredType().isNull()) {
+ if (C->Kind == CXCursor_MacroDefinition) {
+ Priority = getMacroUsagePriority(C->Completion->getTypedText(),
+ S.getLangOptions(),
+ Context.getPreferredType()->isAnyPointerType());
+ } else if (C->Type) {
+ CanQualType Expected
+ = S.Context.getCanonicalType(
+ Context.getPreferredType().getUnqualifiedType());
+ SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
+ if (ExpectedSTC == C->TypeClass) {
+ // We know this type is similar; check for an exact match.
+ llvm::StringMap<unsigned> &CachedCompletionTypes
+ = AST.getCachedCompletionTypes();
+ llvm::StringMap<unsigned>::iterator Pos
+ = CachedCompletionTypes.find(QualType(Expected).getAsString());
+ if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
+ Priority /= CCF_ExactTypeMatch;
+ else
+ Priority /= CCF_SimilarTypeMatch;
+ }
+ }
+ }
+
+ // Adjust the completion string, if required.
+ if (C->Kind == CXCursor_MacroDefinition &&
+ Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
+ // Create a new code-completion string that just contains the
+ // macro name, without its arguments.
+ CodeCompletionBuilder Builder(getAllocator(), CCP_CodePattern,
+ C->Availability);
+ Builder.AddTypedTextChunk(C->Completion->getTypedText());
+ CursorKind = CXCursor_NotImplemented;
+ Priority = CCP_CodePattern;
+ Completion = Builder.TakeString();
+ }
+
+ AllResults.push_back(Result(Completion, Priority, CursorKind,
+ C->Availability));
+ }
+
+ // If we did not add any cached completion results, just forward the
+ // results we were given to the next consumer.
+ if (!AddedResult) {
+ Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
+ return;
+ }
+
+ Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
+ AllResults.size());
+}
+
+
+
+void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles,
+ bool IncludeMacros,
+ bool IncludeCodePatterns,
+ CodeCompleteConsumer &Consumer,
+ Diagnostic &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
+ if (!Invocation.get())
+ return;
+
+ SimpleTimer CompletionTimer(WantTiming);
+ CompletionTimer.setOutput("Code completion @ " + File + ":" +
+ llvm::Twine(Line) + ":" + llvm::Twine(Column));
+
+ CompilerInvocation CCInvocation(*Invocation);
+ FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
+
+ FrontendOpts.ShowMacrosInCodeCompletion
+ = IncludeMacros && CachedCompletionResults.empty();
+ FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
+ FrontendOpts.ShowGlobalSymbolsInCodeCompletion
+ = CachedCompletionResults.empty();
+ FrontendOpts.CodeCompletionAt.FileName = File;
+ FrontendOpts.CodeCompletionAt.Line = Line;
+ FrontendOpts.CodeCompletionAt.Column = Column;
+
+ // Set the language options appropriately.
+ LangOpts = CCInvocation.getLangOpts();
+
+ CompilerInstance Clang;
+ Clang.setInvocation(&CCInvocation);
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing any diagnostics produced.
+ Clang.setDiagnostics(&Diag);
+ ProcessWarningOptions(Diag, CCInvocation.getDiagnosticOpts());
+ CaptureDroppedDiagnostics Capture(true,
+ Clang.getDiagnostics(),
+ StoredDiagnostics);
+
+ // Create the target instance.
+ Clang.getTargetOpts().Features = TargetFeatures;
+ Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+ Clang.getTargetOpts()));
+ if (!Clang.hasTarget()) {
+ Clang.takeInvocation();
+ return;
+ }
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+ assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+ "Invocation must have exactly one source file!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
+ "FIXME: AST inputs not yet supported here!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+ "IR inputs not support here!");
+
+
+ // Use the source and file managers that we were given.
+ Clang.setFileManager(&FileMgr);
+ Clang.setSourceManager(&SourceMgr);
+
+ // Remap files.
+ PreprocessorOpts.clearRemappedFiles();
+ PreprocessorOpts.RetainRemappedFileBuffers = true;
+ for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+ PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+ OwnedBuffers.push_back(RemappedFiles[I].second);
+ }
+
+ // Use the code completion consumer we were given, but adding any cached
+ // code-completion results.
+ AugmentedCodeCompleteConsumer *AugmentedConsumer
+ = new AugmentedCodeCompleteConsumer(*this, Consumer,
+ FrontendOpts.ShowMacrosInCodeCompletion,
+ FrontendOpts.ShowCodePatternsInCodeCompletion,
+ FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
+ Clang.setCodeCompletionConsumer(AugmentedConsumer);
+
+ // If we have a precompiled preamble, try to use it. We only allow
+ // the use of the precompiled preamble if we're if the completion
+ // point is within the main file, after the end of the precompiled
+ // preamble.
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ if (!PreambleFile.empty()) {
+ using llvm::sys::FileStatus;
+ llvm::sys::PathWithStatus CompleteFilePath(File);
+ llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
+ if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
+ if (const FileStatus *MainStatus = MainPath.getFileStatus())
+ if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
+ OverrideMainBuffer
+ = getMainBufferWithPrecompiledPreamble(CCInvocation, false,
+ Line - 1);
+ }
+
+ // If the main file has been overridden due to the use of a preamble,
+ // make that override happen and introduce the preamble.
+ PreprocessorOpts.DisableStatCache = true;
+ StoredDiagnostics.insert(StoredDiagnostics.end(),
+ this->StoredDiagnostics.begin(),
+ this->StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver);
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
+ PreprocessorOpts.PrecompiledPreambleBytes.second
+ = PreambleEndsAtStartOfLine;
+ PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
+ PreprocessorOpts.DisablePCHValidation = true;
+
+ // The stored diagnostics have the old source manager. Copy them
+ // to our output set of stored diagnostics, updating the source
+ // manager to the one we were given.
+ for (unsigned I = NumStoredDiagnosticsFromDriver,
+ N = this->StoredDiagnostics.size();
+ I < N; ++I) {
+ StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
+ FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
+ StoredDiagnostics[I].setLocation(Loc);
+ }
+
+ OwnedBuffers.push_back(OverrideMainBuffer);
+ } else {
+ PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
+ PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+ }
+
+ llvm::OwningPtr<SyntaxOnlyAction> Act;
+ Act.reset(new SyntaxOnlyAction);
+ if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Clang.getFrontendOpts().Inputs[0].first)) {
+ Act->Execute();
+ Act->EndSourceFile();
+ }
+
+ // Steal back our resources.
+ Clang.takeFileManager();
+ Clang.takeSourceManager();
+ Clang.takeInvocation();
+}
+
+bool ASTUnit::Save(llvm::StringRef File) {
+ if (getDiagnostics().hasErrorOccurred())
+ return true;
+
+ // FIXME: Can we somehow regenerate the stat cache here, or do we need to
+ // unconditionally create a stat cache when we parse the file?
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo,
+ llvm::raw_fd_ostream::F_Binary);
+ if (!ErrorInfo.empty() || Out.has_error())
+ return true;
+
+ std::vector<unsigned char> Buffer;
+ llvm::BitstreamWriter Stream(Buffer);
+ ASTWriter Writer(Stream);
+ Writer.WriteAST(getSema(), 0, std::string(), 0);
+
+ // Write the generated bitstream to "Out".
+ if (!Buffer.empty())
+ Out.write((char *)&Buffer.front(), Buffer.size());
+ Out.close();
+ return Out.has_error();
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/BoostConAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/BoostConAction.cpp
new file mode 100644
index 0000000..4a12ff2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/BoostConAction.cpp
@@ -0,0 +1,39 @@
+//===-- BoostConAction.cpp - BoostCon Workshop Action -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include <cstdio>
+#include <iostream>
+using namespace clang;
+
+namespace {
+ class BoostConASTConsumer : public ASTConsumer,
+ public RecursiveASTVisitor<BoostConASTConsumer> {
+ public:
+ /// HandleTranslationUnit - This method is called when the ASTs for entire
+ /// translation unit have been parsed.
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+
+ bool VisitCXXRecordDecl(CXXRecordDecl *D) {
+ std::cout << D->getNameAsString() << std::endl;
+ return true;
+ }
+ };
+}
+
+ASTConsumer *BoostConAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new BoostConASTConsumer();
+}
+
+void BoostConASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
+ fprintf(stderr, "Welcome to BoostCon!\n");
+ TraverseDecl(Ctx.getTranslationUnitDecl());
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
new file mode 100644
index 0000000..ee3fdd8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
@@ -0,0 +1,654 @@
+//===--- CacheTokens.cpp - Caching of lexer tokens for PTH support --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides a possible implementation of PTH support for Clang that is
+// based on caching lexed tokens and identifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+
+// FIXME: put this somewhere else?
+#ifndef S_ISDIR
+#define S_ISDIR(x) (((x)&_S_IFDIR)!=0)
+#endif
+
+using namespace clang;
+using namespace clang::io;
+
+//===----------------------------------------------------------------------===//
+// PTH-specific stuff.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PTHEntry {
+ Offset TokenData, PPCondData;
+
+public:
+ PTHEntry() {}
+
+ PTHEntry(Offset td, Offset ppcd)
+ : TokenData(td), PPCondData(ppcd) {}
+
+ Offset getTokenOffset() const { return TokenData; }
+ Offset getPPCondTableOffset() const { return PPCondData; }
+};
+
+
+class PTHEntryKeyVariant {
+ union { const FileEntry* FE; const char* Path; };
+ enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
+ struct stat *StatBuf;
+public:
+ PTHEntryKeyVariant(const FileEntry *fe)
+ : FE(fe), Kind(IsFE), StatBuf(0) {}
+
+ PTHEntryKeyVariant(struct stat* statbuf, const char* path)
+ : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {}
+
+ explicit PTHEntryKeyVariant(const char* path)
+ : Path(path), Kind(IsNoExist), StatBuf(0) {}
+
+ bool isFile() const { return Kind == IsFE; }
+
+ llvm::StringRef getString() const {
+ return Kind == IsFE ? FE->getName() : Path;
+ }
+
+ unsigned getKind() const { return (unsigned) Kind; }
+
+ void EmitData(llvm::raw_ostream& Out) {
+ switch (Kind) {
+ case IsFE:
+ // Emit stat information.
+ ::Emit32(Out, FE->getInode());
+ ::Emit32(Out, FE->getDevice());
+ ::Emit16(Out, FE->getFileMode());
+ ::Emit64(Out, FE->getModificationTime());
+ ::Emit64(Out, FE->getSize());
+ break;
+ case IsDE:
+ // Emit stat information.
+ ::Emit32(Out, (uint32_t) StatBuf->st_ino);
+ ::Emit32(Out, (uint32_t) StatBuf->st_dev);
+ ::Emit16(Out, (uint16_t) StatBuf->st_mode);
+ ::Emit64(Out, (uint64_t) StatBuf->st_mtime);
+ ::Emit64(Out, (uint64_t) StatBuf->st_size);
+ delete StatBuf;
+ break;
+ default:
+ break;
+ }
+ }
+
+ unsigned getRepresentationLength() const {
+ return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8;
+ }
+};
+
+class FileEntryPTHEntryInfo {
+public:
+ typedef PTHEntryKeyVariant key_type;
+ typedef key_type key_type_ref;
+
+ typedef PTHEntry data_type;
+ typedef const PTHEntry& data_type_ref;
+
+ static unsigned ComputeHash(PTHEntryKeyVariant V) {
+ return llvm::HashString(V.getString());
+ }
+
+ static std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
+ const PTHEntry& E) {
+
+ unsigned n = V.getString().size() + 1 + 1;
+ ::Emit16(Out, n);
+
+ unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
+ ::Emit8(Out, m);
+
+ return std::make_pair(n, m);
+ }
+
+ static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){
+ // Emit the entry kind.
+ ::Emit8(Out, (unsigned) V.getKind());
+ // Emit the string.
+ Out.write(V.getString().data(), n - 1);
+ }
+
+ static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
+ const PTHEntry& E, unsigned) {
+
+
+ // For file entries emit the offsets into the PTH file for token data
+ // and the preprocessor blocks table.
+ if (V.isFile()) {
+ ::Emit32(Out, E.getTokenOffset());
+ ::Emit32(Out, E.getPPCondTableOffset());
+ }
+
+ // Emit any other data associated with the key (i.e., stat information).
+ V.EmitData(Out);
+ }
+};
+
+class OffsetOpt {
+ bool valid;
+ Offset off;
+public:
+ OffsetOpt() : valid(false) {}
+ bool hasOffset() const { return valid; }
+ Offset getOffset() const { assert(valid); return off; }
+ void setOffset(Offset o) { off = o; valid = true; }
+};
+} // end anonymous namespace
+
+typedef OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap;
+
+namespace {
+class PTHWriter {
+ typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
+ typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
+
+ IDMap IM;
+ llvm::raw_fd_ostream& Out;
+ Preprocessor& PP;
+ uint32_t idcount;
+ PTHMap PM;
+ CachedStrsTy CachedStrs;
+ Offset CurStrOffset;
+ std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
+
+ //// Get the persistent id for the given IdentifierInfo*.
+ uint32_t ResolveID(const IdentifierInfo* II);
+
+ /// Emit a token to the PTH file.
+ void EmitToken(const Token& T);
+
+ void Emit8(uint32_t V) { ::Emit8(Out, V); }
+
+ void Emit16(uint32_t V) { ::Emit16(Out, V); }
+
+ void Emit32(uint32_t V) { ::Emit32(Out, V); }
+
+ void EmitBuf(const char *Ptr, unsigned NumBytes) {
+ Out.write(Ptr, NumBytes);
+ }
+
+ void EmitString(llvm::StringRef V) {
+ ::Emit16(Out, V.size());
+ EmitBuf(V.data(), V.size());
+ }
+
+ /// EmitIdentifierTable - Emits two tables to the PTH file. The first is
+ /// a hashtable mapping from identifier strings to persistent IDs.
+ /// The second is a straight table mapping from persistent IDs to string data
+ /// (the keys of the first table).
+ std::pair<Offset, Offset> EmitIdentifierTable();
+
+ /// EmitFileTable - Emit a table mapping from file name strings to PTH
+ /// token data.
+ Offset EmitFileTable() { return PM.Emit(Out); }
+
+ PTHEntry LexTokens(Lexer& L);
+ Offset EmitCachedSpellings();
+
+public:
+ PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
+ : Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
+
+ PTHMap &getPM() { return PM; }
+ void GeneratePTH(const std::string &MainFile);
+};
+} // end anonymous namespace
+
+uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
+ // Null IdentifierInfo's map to the persistent ID 0.
+ if (!II)
+ return 0;
+
+ IDMap::iterator I = IM.find(II);
+ if (I != IM.end())
+ return I->second; // We've already added 1.
+
+ IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
+ return idcount;
+}
+
+void PTHWriter::EmitToken(const Token& T) {
+ // Emit the token kind, flags, and length.
+ Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)|
+ (((uint32_t) T.getLength()) << 16));
+
+ if (!T.isLiteral()) {
+ Emit32(ResolveID(T.getIdentifierInfo()));
+ } else {
+ // We cache *un-cleaned* spellings. This gives us 100% fidelity with the
+ // source code.
+ const char* s = T.getLiteralData();
+ unsigned len = T.getLength();
+
+ // Get the string entry.
+ llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len);
+
+ // If this is a new string entry, bump the PTH offset.
+ if (!E->getValue().hasOffset()) {
+ E->getValue().setOffset(CurStrOffset);
+ StrEntries.push_back(E);
+ CurStrOffset += len + 1;
+ }
+
+ // Emit the relative offset into the PTH file for the spelling string.
+ Emit32(E->getValue().getOffset());
+ }
+
+ // Emit the offset into the original source file of this token so that we
+ // can reconstruct its SourceLocation.
+ Emit32(PP.getSourceManager().getFileOffset(T.getLocation()));
+}
+
+PTHEntry PTHWriter::LexTokens(Lexer& L) {
+ // Pad 0's so that we emit tokens to a 4-byte alignment.
+ // This speed up reading them back in.
+ Pad(Out, 4);
+ Offset TokenOff = (Offset) Out.tell();
+
+ // Keep track of matching '#if' ... '#endif'.
+ typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
+ PPCondTable PPCond;
+ std::vector<unsigned> PPStartCond;
+ bool ParsingPreprocessorDirective = false;
+ Token Tok;
+
+ do {
+ L.LexFromRawLexer(Tok);
+ NextToken:
+
+ if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
+ ParsingPreprocessorDirective) {
+ // Insert an eom token into the token cache. It has the same
+ // position as the next token that is not on the same line as the
+ // preprocessor directive. Observe that we continue processing
+ // 'Tok' when we exit this branch.
+ Token Tmp = Tok;
+ Tmp.setKind(tok::eom);
+ Tmp.clearFlag(Token::StartOfLine);
+ Tmp.setIdentifierInfo(0);
+ EmitToken(Tmp);
+ ParsingPreprocessorDirective = false;
+ }
+
+ if (Tok.is(tok::raw_identifier)) {
+ PP.LookUpIdentifierInfo(Tok);
+ EmitToken(Tok);
+ continue;
+ }
+
+ if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
+ // Special processing for #include. Store the '#' token and lex
+ // the next token.
+ assert(!ParsingPreprocessorDirective);
+ Offset HashOff = (Offset) Out.tell();
+
+ // Get the next token.
+ Token NextTok;
+ L.LexFromRawLexer(NextTok);
+
+ // If we see the start of line, then we had a null directive "#". In
+ // this case, discard both tokens.
+ if (NextTok.isAtStartOfLine())
+ goto NextToken;
+
+ // The token is the start of a directive. Emit it.
+ EmitToken(Tok);
+ Tok = NextTok;
+
+ // Did we see 'include'/'import'/'include_next'?
+ if (Tok.isNot(tok::raw_identifier)) {
+ EmitToken(Tok);
+ continue;
+ }
+
+ IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
+ tok::PPKeywordKind K = II->getPPKeywordID();
+
+ ParsingPreprocessorDirective = true;
+
+ switch (K) {
+ case tok::pp_not_keyword:
+ // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass
+ // them through.
+ default:
+ break;
+
+ case tok::pp_include:
+ case tok::pp_import:
+ case tok::pp_include_next: {
+ // Save the 'include' token.
+ EmitToken(Tok);
+ // Lex the next token as an include string.
+ L.setParsingPreprocessorDirective(true);
+ L.LexIncludeFilename(Tok);
+ L.setParsingPreprocessorDirective(false);
+ assert(!Tok.isAtStartOfLine());
+ if (Tok.is(tok::raw_identifier))
+ PP.LookUpIdentifierInfo(Tok);
+
+ break;
+ }
+ case tok::pp_if:
+ case tok::pp_ifdef:
+ case tok::pp_ifndef: {
+ // Add an entry for '#if' and friends. We initially set the target
+ // index to 0. This will get backpatched when we hit #endif.
+ PPStartCond.push_back(PPCond.size());
+ PPCond.push_back(std::make_pair(HashOff, 0U));
+ break;
+ }
+ case tok::pp_endif: {
+ // Add an entry for '#endif'. We set the target table index to itself.
+ // This will later be set to zero when emitting to the PTH file. We
+ // use 0 for uninitialized indices because that is easier to debug.
+ unsigned index = PPCond.size();
+ // Backpatch the opening '#if' entry.
+ assert(!PPStartCond.empty());
+ assert(PPCond.size() > PPStartCond.back());
+ assert(PPCond[PPStartCond.back()].second == 0);
+ PPCond[PPStartCond.back()].second = index;
+ PPStartCond.pop_back();
+ // Add the new entry to PPCond.
+ PPCond.push_back(std::make_pair(HashOff, index));
+ EmitToken(Tok);
+
+ // Some files have gibberish on the same line as '#endif'.
+ // Discard these tokens.
+ do
+ L.LexFromRawLexer(Tok);
+ while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine());
+ // We have the next token in hand.
+ // Don't immediately lex the next one.
+ goto NextToken;
+ }
+ case tok::pp_elif:
+ case tok::pp_else: {
+ // Add an entry for #elif or #else.
+ // This serves as both a closing and opening of a conditional block.
+ // This means that its entry will get backpatched later.
+ unsigned index = PPCond.size();
+ // Backpatch the previous '#if' entry.
+ assert(!PPStartCond.empty());
+ assert(PPCond.size() > PPStartCond.back());
+ assert(PPCond[PPStartCond.back()].second == 0);
+ PPCond[PPStartCond.back()].second = index;
+ PPStartCond.pop_back();
+ // Now add '#elif' as a new block opening.
+ PPCond.push_back(std::make_pair(HashOff, 0U));
+ PPStartCond.push_back(index);
+ break;
+ }
+ }
+ }
+
+ EmitToken(Tok);
+ }
+ while (Tok.isNot(tok::eof));
+
+ assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");
+
+ // Next write out PPCond.
+ Offset PPCondOff = (Offset) Out.tell();
+
+ // Write out the size of PPCond so that clients can identifer empty tables.
+ Emit32(PPCond.size());
+
+ for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
+ Emit32(PPCond[i].first - TokenOff);
+ uint32_t x = PPCond[i].second;
+ assert(x != 0 && "PPCond entry not backpatched.");
+ // Emit zero for #endifs. This allows us to do checking when
+ // we read the PTH file back in.
+ Emit32(x == i ? 0 : x);
+ }
+
+ return PTHEntry(TokenOff, PPCondOff);
+}
+
+Offset PTHWriter::EmitCachedSpellings() {
+ // Write each cached strings to the PTH file.
+ Offset SpellingsOff = Out.tell();
+
+ for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator
+ I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I)
+ EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/);
+
+ return SpellingsOff;
+}
+
+void PTHWriter::GeneratePTH(const std::string &MainFile) {
+ // Generate the prologue.
+ Out << "cfe-pth";
+ Emit32(PTHManager::Version);
+
+ // Leave 4 words for the prologue.
+ Offset PrologueOffset = Out.tell();
+ for (unsigned i = 0; i < 4; ++i)
+ Emit32(0);
+
+ // Write the name of the MainFile.
+ if (!MainFile.empty()) {
+ EmitString(MainFile);
+ } else {
+ // String with 0 bytes.
+ Emit16(0);
+ }
+ Emit8(0);
+
+ // Iterate over all the files in SourceManager. Create a lexer
+ // for each file and cache the tokens.
+ SourceManager &SM = PP.getSourceManager();
+ const LangOptions &LOpts = PP.getLangOptions();
+
+ for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
+ E = SM.fileinfo_end(); I != E; ++I) {
+ const SrcMgr::ContentCache &C = *I->second;
+ const FileEntry *FE = C.Entry;
+
+ // FIXME: Handle files with non-absolute paths.
+ if (llvm::sys::path::is_relative(FE->getName()))
+ continue;
+
+ const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM);
+ if (!B) continue;
+
+ FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+ Lexer L(FID, FromFile, SM, LOpts);
+ PM.insert(FE, LexTokens(L));
+ }
+
+ // Write out the identifier table.
+ const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable();
+
+ // Write out the cached strings table.
+ Offset SpellingOff = EmitCachedSpellings();
+
+ // Write out the file table.
+ Offset FileTableOff = EmitFileTable();
+
+ // Finally, write the prologue.
+ Out.seek(PrologueOffset);
+ Emit32(IdTableOff.first);
+ Emit32(IdTableOff.second);
+ Emit32(FileTableOff);
+ Emit32(SpellingOff);
+}
+
+namespace {
+/// StatListener - A simple "interpose" object used to monitor stat calls
+/// invoked by FileManager while processing the original sources used
+/// as input to PTH generation. StatListener populates the PTHWriter's
+/// file map with stat information for directories as well as negative stats.
+/// Stat information for files are populated elsewhere.
+class StatListener : public FileSystemStatCache {
+ PTHMap &PM;
+public:
+ StatListener(PTHMap &pm) : PM(pm) {}
+ ~StatListener() {}
+
+ LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ LookupResult Result = statChained(Path, StatBuf, FileDescriptor);
+
+ if (Result == CacheMissing) // Failed 'stat'.
+ PM.insert(PTHEntryKeyVariant(Path), PTHEntry());
+ else if (S_ISDIR(StatBuf.st_mode)) {
+ // Only cache directories with absolute paths.
+ if (llvm::sys::path::is_relative(Path))
+ return Result;
+
+ PM.insert(PTHEntryKeyVariant(&StatBuf, Path), PTHEntry());
+ }
+
+ return Result;
+ }
+};
+} // end anonymous namespace
+
+
+void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
+ // Get the name of the main file.
+ const SourceManager &SrcMgr = PP.getSourceManager();
+ const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
+ llvm::SmallString<128> MainFilePath(MainFile->getName());
+
+ llvm::sys::fs::make_absolute(MainFilePath);
+
+ // Create the PTHWriter.
+ PTHWriter PW(*OS, PP);
+
+ // Install the 'stat' system call listener in the FileManager.
+ StatListener *StatCache = new StatListener(PW.getPM());
+ PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);
+
+ // Lex through the entire file. This will populate SourceManager with
+ // all of the header information.
+ Token Tok;
+ PP.EnterMainSourceFile();
+ do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
+
+ // Generate the PTH file.
+ PP.getFileManager().removeStatCache(StatCache);
+ PW.GeneratePTH(MainFilePath.str());
+}
+
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PTHIdKey {
+public:
+ const IdentifierInfo* II;
+ uint32_t FileOffset;
+};
+
+class PTHIdentifierTableTrait {
+public:
+ typedef PTHIdKey* key_type;
+ typedef key_type key_type_ref;
+
+ typedef uint32_t data_type;
+ typedef data_type data_type_ref;
+
+ static unsigned ComputeHash(PTHIdKey* key) {
+ return llvm::HashString(key->II->getName());
+ }
+
+ static std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
+ unsigned n = key->II->getLength() + 1;
+ ::Emit16(Out, n);
+ return std::make_pair(n, sizeof(uint32_t));
+ }
+
+ static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) {
+ // Record the location of the key data. This is used when generating
+ // the mapping from persistent IDs to strings.
+ key->FileOffset = Out.tell();
+ Out.write(key->II->getNameStart(), n);
+ }
+
+ static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID,
+ unsigned) {
+ ::Emit32(Out, pID);
+ }
+};
+} // end anonymous namespace
+
+/// EmitIdentifierTable - Emits two tables to the PTH file. The first is
+/// a hashtable mapping from identifier strings to persistent IDs. The second
+/// is a straight table mapping from persistent IDs to string data (the
+/// keys of the first table).
+///
+std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
+ // Build two maps:
+ // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset)
+ // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs
+
+ // Note that we use 'calloc', so all the bytes are 0.
+ PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey));
+
+ // Create the hashtable.
+ OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
+
+ // Generate mapping from persistent IDs -> IdentifierInfo*.
+ for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
+ // Decrement by 1 because we are using a vector for the lookup and
+ // 0 is reserved for NULL.
+ assert(I->second > 0);
+ assert(I->second-1 < idcount);
+ unsigned idx = I->second-1;
+
+ // Store the mapping from persistent ID to IdentifierInfo*
+ IIDMap[idx].II = I->first;
+
+ // Store the reverse mapping in a hashtable.
+ IIOffMap.insert(&IIDMap[idx], I->second);
+ }
+
+ // Write out the inverse map first. This causes the PCIDKey entries to
+ // record PTH file offsets for the string data. This is used to write
+ // the second table.
+ Offset StringTableOffset = IIOffMap.Emit(Out);
+
+ // Now emit the table mapping from persistent IDs to PTH file offsets.
+ Offset IDOff = Out.tell();
+ Emit32(idcount); // Emit the number of identifiers.
+ for (unsigned i = 0 ; i < idcount; ++i)
+ Emit32(IIDMap[i].FileOffset);
+
+ // Finally, release the inverse map.
+ free(IIDMap);
+
+ return std::make_pair(IDOff, StringTableOffset);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
new file mode 100644
index 0000000..fd593de
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -0,0 +1,591 @@
+//===--- CompilerInstance.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Sema/Sema.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Frontend/ChainedDiagnosticClient.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+using namespace clang;
+
+CompilerInstance::CompilerInstance()
+ : Invocation(new CompilerInvocation()) {
+}
+
+CompilerInstance::~CompilerInstance() {
+}
+
+void CompilerInstance::setInvocation(CompilerInvocation *Value) {
+ Invocation.reset(Value);
+}
+
+void CompilerInstance::setDiagnostics(Diagnostic *Value) {
+ Diagnostics = Value;
+}
+
+void CompilerInstance::setTarget(TargetInfo *Value) {
+ Target.reset(Value);
+}
+
+void CompilerInstance::setFileManager(FileManager *Value) {
+ FileMgr.reset(Value);
+}
+
+void CompilerInstance::setSourceManager(SourceManager *Value) {
+ SourceMgr.reset(Value);
+}
+
+void CompilerInstance::setPreprocessor(Preprocessor *Value) {
+ PP.reset(Value);
+}
+
+void CompilerInstance::setASTContext(ASTContext *Value) {
+ Context.reset(Value);
+}
+
+void CompilerInstance::setSema(Sema *S) {
+ TheSema.reset(S);
+}
+
+void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
+ Consumer.reset(Value);
+}
+
+void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
+ CompletionConsumer.reset(Value);
+}
+
+// Diagnostics
+static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
+ unsigned argc, const char* const *argv,
+ Diagnostic &Diags) {
+ std::string ErrorInfo;
+ llvm::OwningPtr<llvm::raw_ostream> OS(
+ new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
+ if (!ErrorInfo.empty()) {
+ Diags.Report(diag::err_fe_unable_to_open_logfile)
+ << DiagOpts.DumpBuildInformation << ErrorInfo;
+ return;
+ }
+
+ (*OS) << "clang -cc1 command line arguments: ";
+ for (unsigned i = 0; i != argc; ++i)
+ (*OS) << argv[i] << ' ';
+ (*OS) << '\n';
+
+ // Chain in a diagnostic client which will log the diagnostics.
+ DiagnosticClient *Logger =
+ new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
+ Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
+}
+
+void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
+ DiagnosticClient *Client) {
+ Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client);
+}
+
+llvm::IntrusiveRefCntPtr<Diagnostic>
+CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
+ int Argc, const char* const *Argv,
+ DiagnosticClient *Client) {
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
+
+ // Create the diagnostic client for reporting errors or for
+ // implementing -verify.
+ if (Client)
+ Diags->setClient(Client);
+ else
+ Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
+
+ // Chain in -verify checker, if requested.
+ if (Opts.VerifyDiagnostics)
+ Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
+
+ if (!Opts.DumpBuildInformation.empty())
+ SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
+
+ // Configure our handling of diagnostics.
+ ProcessWarningOptions(*Diags, Opts);
+
+ return Diags;
+}
+
+// File Manager
+
+void CompilerInstance::createFileManager() {
+ FileMgr.reset(new FileManager(getFileSystemOpts()));
+}
+
+// Source Manager
+
+void CompilerInstance::createSourceManager(FileManager &FileMgr) {
+ SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr));
+}
+
+// Preprocessor
+
+void CompilerInstance::createPreprocessor() {
+ PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
+ getPreprocessorOpts(), getHeaderSearchOpts(),
+ getDependencyOutputOpts(), getTarget(),
+ getFrontendOpts(), getSourceManager(),
+ getFileManager()));
+}
+
+Preprocessor *
+CompilerInstance::createPreprocessor(Diagnostic &Diags,
+ const LangOptions &LangInfo,
+ const PreprocessorOptions &PPOpts,
+ const HeaderSearchOptions &HSOpts,
+ const DependencyOutputOptions &DepOpts,
+ const TargetInfo &Target,
+ const FrontendOptions &FEOpts,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr) {
+ // Create a PTH manager if we are using some form of a token cache.
+ PTHManager *PTHMgr = 0;
+ if (!PPOpts.TokenCache.empty())
+ PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
+
+ // Create the Preprocessor.
+ HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
+ Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
+ SourceMgr, *HeaderInfo, PTHMgr,
+ /*OwnsHeaderSearch=*/true);
+
+ // Note that this is different then passing PTHMgr to Preprocessor's ctor.
+ // That argument is used as the IdentifierInfoLookup argument to
+ // IdentifierTable's ctor.
+ if (PTHMgr) {
+ PTHMgr->setPreprocessor(PP);
+ PP->setPTHManager(PTHMgr);
+ }
+
+ if (PPOpts.DetailedRecord)
+ PP->createPreprocessingRecord();
+
+ InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
+
+ // Handle generating dependencies, if requested.
+ if (!DepOpts.OutputFile.empty())
+ AttachDependencyFileGen(*PP, DepOpts);
+
+ // Handle generating header include information, if requested.
+ if (DepOpts.ShowHeaderIncludes)
+ AttachHeaderIncludeGen(*PP);
+ if (!DepOpts.HeaderIncludeOutputFile.empty()) {
+ llvm::StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
+ if (OutputPath == "-")
+ OutputPath = "";
+ AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath);
+ }
+
+ return PP;
+}
+
+// ASTContext
+
+void CompilerInstance::createASTContext() {
+ Preprocessor &PP = getPreprocessor();
+ Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
+ getTarget(), PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo(),
+ /*size_reserve=*/ 0));
+}
+
+// ExternalASTSource
+
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+ bool DisablePCHValidation,
+ bool DisableStatCache,
+ void *DeserializationListener){
+ llvm::OwningPtr<ExternalASTSource> Source;
+ bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
+ Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
+ DisablePCHValidation,
+ DisableStatCache,
+ getPreprocessor(), getASTContext(),
+ DeserializationListener,
+ Preamble));
+ getASTContext().setExternalSource(Source);
+}
+
+ExternalASTSource *
+CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+ const std::string &Sysroot,
+ bool DisablePCHValidation,
+ bool DisableStatCache,
+ Preprocessor &PP,
+ ASTContext &Context,
+ void *DeserializationListener,
+ bool Preamble) {
+ llvm::OwningPtr<ASTReader> Reader;
+ Reader.reset(new ASTReader(PP, &Context,
+ Sysroot.empty() ? 0 : Sysroot.c_str(),
+ DisablePCHValidation, DisableStatCache));
+
+ Reader->setDeserializationListener(
+ static_cast<ASTDeserializationListener *>(DeserializationListener));
+ switch (Reader->ReadAST(Path,
+ Preamble ? ASTReader::Preamble : ASTReader::PCH)) {
+ case ASTReader::Success:
+ // Set the predefines buffer as suggested by the PCH reader. Typically, the
+ // predefines buffer will be empty.
+ PP.setPredefines(Reader->getSuggestedPredefines());
+ return Reader.take();
+
+ case ASTReader::Failure:
+ // Unrecoverable failure: don't even try to process the input file.
+ break;
+
+ case ASTReader::IgnorePCH:
+ // No suitable PCH file could be found. Return an error.
+ break;
+ }
+
+ return 0;
+}
+
+// Code Completion
+
+static bool EnableCodeCompletion(Preprocessor &PP,
+ const std::string &Filename,
+ unsigned Line,
+ unsigned Column) {
+ // Tell the source manager to chop off the given file at a specific
+ // line and column.
+ const FileEntry *Entry = PP.getFileManager().getFile(Filename);
+ if (!Entry) {
+ PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
+ << Filename;
+ return true;
+ }
+
+ // Truncate the named file at the given line/column.
+ PP.SetCodeCompletionPoint(Entry, Line, Column);
+ return false;
+}
+
+void CompilerInstance::createCodeCompletionConsumer() {
+ const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
+ if (!CompletionConsumer) {
+ CompletionConsumer.reset(
+ createCodeCompletionConsumer(getPreprocessor(),
+ Loc.FileName, Loc.Line, Loc.Column,
+ getFrontendOpts().ShowMacrosInCodeCompletion,
+ getFrontendOpts().ShowCodePatternsInCodeCompletion,
+ getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
+ llvm::outs()));
+ if (!CompletionConsumer)
+ return;
+ } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
+ Loc.Line, Loc.Column)) {
+ CompletionConsumer.reset();
+ return;
+ }
+
+ if (CompletionConsumer->isOutputBinary() &&
+ llvm::sys::Program::ChangeStdoutToBinary()) {
+ getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
+ CompletionConsumer.reset();
+ }
+}
+
+void CompilerInstance::createFrontendTimer() {
+ FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
+}
+
+CodeCompleteConsumer *
+CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
+ const std::string &Filename,
+ unsigned Line,
+ unsigned Column,
+ bool ShowMacros,
+ bool ShowCodePatterns,
+ bool ShowGlobals,
+ llvm::raw_ostream &OS) {
+ if (EnableCodeCompletion(PP, Filename, Line, Column))
+ return 0;
+
+ // Set up the creation routine for code-completion.
+ return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
+ ShowGlobals, OS);
+}
+
+void CompilerInstance::createSema(bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer) {
+ TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
+ CompleteTranslationUnit, CompletionConsumer));
+}
+
+// Output Files
+
+void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
+ assert(OutFile.OS && "Attempt to add empty stream to output list!");
+ OutputFiles.push_back(OutFile);
+}
+
+void CompilerInstance::clearOutputFiles(bool EraseFiles) {
+ for (std::list<OutputFile>::iterator
+ it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
+ delete it->OS;
+ if (!it->TempFilename.empty()) {
+ llvm::sys::Path TempPath(it->TempFilename);
+ if (EraseFiles)
+ TempPath.eraseFromDisk();
+ else {
+ std::string Error;
+ llvm::sys::Path NewOutFile(it->Filename);
+ // If '-working-directory' was passed, the output filename should be
+ // relative to that.
+ FileManager::FixupRelativePath(NewOutFile, getFileSystemOpts());
+ if (TempPath.renamePathOnDisk(NewOutFile, &Error)) {
+ getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
+ << it->TempFilename << it->Filename << Error;
+ TempPath.eraseFromDisk();
+ }
+ }
+ } else if (!it->Filename.empty() && EraseFiles)
+ llvm::sys::Path(it->Filename).eraseFromDisk();
+
+ }
+ OutputFiles.clear();
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createDefaultOutputFile(bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ return createOutputFile(getFrontendOpts().OutputFile, Binary,
+ /*RemoveFileOnSignal=*/true, InFile, Extension);
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ bool Binary, bool RemoveFileOnSignal,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ std::string Error, OutputPathName, TempPathName;
+ llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
+ RemoveFileOnSignal,
+ InFile, Extension,
+ &OutputPathName,
+ &TempPathName);
+ if (!OS) {
+ getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+ << OutputPath << Error;
+ return 0;
+ }
+
+ // Add the output file -- but don't try to remove "-", since this means we are
+ // using stdin.
+ addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
+ TempPathName, OS));
+
+ return OS;
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ std::string &Error,
+ bool Binary,
+ bool RemoveFileOnSignal,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension,
+ std::string *ResultPathName,
+ std::string *TempPathName) {
+ std::string OutFile, TempFile;
+ if (!OutputPath.empty()) {
+ OutFile = OutputPath;
+ } else if (InFile == "-") {
+ OutFile = "-";
+ } else if (!Extension.empty()) {
+ llvm::sys::Path Path(InFile);
+ Path.eraseSuffix();
+ Path.appendSuffix(Extension);
+ OutFile = Path.str();
+ } else {
+ OutFile = "-";
+ }
+
+ if (OutFile != "-") {
+ llvm::sys::Path OutPath(OutFile);
+ // Only create the temporary if we can actually write to OutPath, otherwise
+ // we want to fail early.
+ bool Exists;
+ if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
+ (OutPath.isRegularFile() && OutPath.canWrite())) {
+ // Create a temporary file.
+ llvm::sys::Path TempPath(OutFile);
+ if (!TempPath.createTemporaryFileOnDisk())
+ TempFile = TempPath.str();
+ }
+ }
+
+ std::string OSFile = OutFile;
+ if (!TempFile.empty())
+ OSFile = TempFile;
+
+ llvm::OwningPtr<llvm::raw_fd_ostream> OS(
+ new llvm::raw_fd_ostream(OSFile.c_str(), Error,
+ (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
+ if (!Error.empty())
+ return 0;
+
+ // Make sure the out stream file gets removed if we crash.
+ if (RemoveFileOnSignal)
+ llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
+
+ if (ResultPathName)
+ *ResultPathName = OutFile;
+ if (TempPathName)
+ *TempPathName = TempFile;
+
+ return OS.take();
+}
+
+// Initialization Utilities
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
+ return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
+ getSourceManager(), getFrontendOpts());
+}
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
+ Diagnostic &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts) {
+ // Figure out where to get and map in the main file, unless it's already
+ // been created (e.g., by a precompiled preamble).
+ if (!SourceMgr.getMainFileID().isInvalid()) {
+ // Do nothing: the main file has already been set.
+ } else if (InputFile != "-") {
+ const FileEntry *File = FileMgr.getFile(InputFile);
+ if (!File) {
+ Diags.Report(diag::err_fe_error_reading) << InputFile;
+ return false;
+ }
+ SourceMgr.createMainFileID(File);
+ } else {
+ llvm::OwningPtr<llvm::MemoryBuffer> SB;
+ if (llvm::MemoryBuffer::getSTDIN(SB)) {
+ // FIXME: Give ec.message() in this diag.
+ Diags.Report(diag::err_fe_error_reading_stdin);
+ return false;
+ }
+ const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
+ SB->getBufferSize(), 0);
+ SourceMgr.createMainFileID(File);
+ SourceMgr.overrideFileContents(File, SB.take());
+ }
+
+ assert(!SourceMgr.getMainFileID().isInvalid() &&
+ "Couldn't establish MainFileID!");
+ return true;
+}
+
+// High-Level Operations
+
+bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
+ assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
+ assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
+ assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
+
+ // FIXME: Take this as an argument, once all the APIs we used have moved to
+ // taking it as an input instead of hard-coding llvm::errs.
+ llvm::raw_ostream &OS = llvm::errs();
+
+ // Create the target instance.
+ setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
+ if (!hasTarget())
+ return false;
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ getTarget().setForcedLangOptions(getLangOpts());
+
+ // Validate/process some options.
+ if (getHeaderSearchOpts().Verbose)
+ OS << "clang -cc1 version " CLANG_VERSION_STRING
+ << " based upon " << PACKAGE_STRING
+ << " hosted on " << llvm::sys::getHostTriple() << "\n";
+
+ if (getFrontendOpts().ShowTimers)
+ createFrontendTimer();
+
+ if (getFrontendOpts().ShowStats)
+ llvm::EnableStatistics();
+
+ for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
+ const std::string &InFile = getFrontendOpts().Inputs[i].second;
+
+ // Reset the ID tables if we are reusing the SourceManager.
+ if (hasSourceManager())
+ getSourceManager().clearIDTables();
+
+ if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
+ Act.Execute();
+ Act.EndSourceFile();
+ }
+ }
+
+ if (getDiagnosticOpts().ShowCarets) {
+ // We can have multiple diagnostics sharing one diagnostic client.
+ // Get the total number of warnings/errors from the client.
+ unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
+ unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
+
+ if (NumWarnings)
+ OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
+ if (NumWarnings && NumErrors)
+ OS << " and ";
+ if (NumErrors)
+ OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
+ if (NumWarnings || NumErrors)
+ OS << " generated.\n";
+ }
+
+ if (getFrontendOpts().ShowStats && hasFileManager()) {
+ getFileManager().PrintStats();
+ OS << "\n";
+ }
+
+ return !getDiagnostics().getClient()->getNumErrors();
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
new file mode 100644
index 0000000..beb5ad2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -0,0 +1,1674 @@
+//===--- CompilerInvocation.cpp -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/Version.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/LangStandard.h"
+#include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+using namespace clang;
+
+static const char *getAnalysisName(Analyses Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown analysis kind!");
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+ case NAME: return "-" CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisStoreName(AnalysisStores Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown analysis constraints!");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown analysis client!");
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
+ case PD_##NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Serialization (to args)
+//===----------------------------------------------------------------------===//
+
+static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
+ Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+ if (Opts.AnalysisStoreOpt != BasicStoreModel) {
+ Res.push_back("-analyzer-store");
+ Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
+ }
+ if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+ Res.push_back("-analyzer-constraints");
+ Res.push_back(getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
+ }
+ if (Opts.AnalysisDiagOpt != PD_HTML) {
+ Res.push_back("-analyzer-output");
+ Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
+ }
+ if (!Opts.AnalyzeSpecificFunction.empty()) {
+ Res.push_back("-analyze-function");
+ Res.push_back(Opts.AnalyzeSpecificFunction);
+ }
+ if (Opts.AnalyzeAll)
+ Res.push_back("-analyzer-opt-analyze-headers");
+ if (Opts.AnalyzerDisplayProgress)
+ Res.push_back("-analyzer-display-progress");
+ if (Opts.AnalyzeNestedBlocks)
+ Res.push_back("-analyzer-opt-analyze-nested-blocks");
+ if (Opts.AnalyzerStats)
+ Res.push_back("-analyzer-stats");
+ if (Opts.EagerlyAssume)
+ Res.push_back("-analyzer-eagerly-assume");
+ if (!Opts.PurgeDead)
+ Res.push_back("-analyzer-no-purge-dead");
+ if (Opts.TrimGraph)
+ Res.push_back("-trim-egraph");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-graphviz");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-ubigraph");
+ if (Opts.EnableExperimentalChecks)
+ Res.push_back("-analyzer-experimental-checks");
+ if (Opts.EnableExperimentalInternalChecks)
+ Res.push_back("-analyzer-experimental-internal-checks");
+ if (Opts.BufferOverflows)
+ Res.push_back("-analyzer-check-buffer-overflows");
+
+ for (unsigned i = 0, e = Opts.CheckersControlList.size(); i != e; ++i) {
+ const std::pair<std::string, bool> &opt = Opts.CheckersControlList[i];
+ if (opt.second)
+ Res.push_back("-analyzer-disable-checker");
+ else
+ Res.push_back("-analyzer-checker");
+ Res.push_back(opt.first);
+ }
+}
+
+static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.DebugInfo)
+ Res.push_back("-g");
+ if (Opts.DisableLLVMOpts)
+ Res.push_back("-disable-llvm-optzns");
+ if (Opts.DisableRedZone)
+ Res.push_back("-disable-red-zone");
+ if (!Opts.DwarfDebugFlags.empty()) {
+ Res.push_back("-dwarf-debug-flags");
+ Res.push_back(Opts.DwarfDebugFlags);
+ }
+ if (!Opts.MergeAllConstants)
+ Res.push_back("-fno-merge-all-constants");
+ if (Opts.NoCommon)
+ Res.push_back("-fno-common");
+ if (Opts.NoImplicitFloat)
+ Res.push_back("-no-implicit-float");
+ if (Opts.OmitLeafFramePointer)
+ Res.push_back("-momit-leaf-frame-pointer");
+ if (Opts.OptimizeSize) {
+ assert(Opts.OptimizationLevel == 2 && "Invalid options!");
+ Res.push_back("-Os");
+ } else if (Opts.OptimizationLevel != 0)
+ Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel));
+ if (!Opts.MainFileName.empty()) {
+ Res.push_back("-main-file-name");
+ Res.push_back(Opts.MainFileName);
+ }
+ // SimplifyLibCalls is only derived.
+ // TimePasses is only derived.
+ // UnitAtATime is unused.
+ // Inlining is only derived.
+
+ // UnrollLoops is derived, but also accepts an option, no
+ // harm in pushing it back here.
+ if (Opts.UnrollLoops)
+ Res.push_back("-funroll-loops");
+ if (Opts.DataSections)
+ Res.push_back("-fdata-sections");
+ if (Opts.FunctionSections)
+ Res.push_back("-ffunction-sections");
+ if (Opts.AsmVerbose)
+ Res.push_back("-masm-verbose");
+ if (!Opts.CodeModel.empty()) {
+ Res.push_back("-mcode-model");
+ Res.push_back(Opts.CodeModel);
+ }
+ if (!Opts.CXAAtExit)
+ Res.push_back("-fno-use-cxa-atexit");
+ if (Opts.CXXCtorDtorAliases)
+ Res.push_back("-mconstructor-aliases");
+ if (!Opts.DebugPass.empty()) {
+ Res.push_back("-mdebug-pass");
+ Res.push_back(Opts.DebugPass);
+ }
+ if (Opts.DisableFPElim)
+ Res.push_back("-mdisable-fp-elim");
+ if (!Opts.FloatABI.empty()) {
+ Res.push_back("-mfloat-abi");
+ Res.push_back(Opts.FloatABI);
+ }
+ if (!Opts.LimitFloatPrecision.empty()) {
+ Res.push_back("-mlimit-float-precision");
+ Res.push_back(Opts.LimitFloatPrecision);
+ }
+ if (Opts.NoZeroInitializedInBSS)
+ Res.push_back("-mno-zero-initialized-bss");
+ switch (Opts.getObjCDispatchMethod()) {
+ case CodeGenOptions::Legacy:
+ break;
+ case CodeGenOptions::Mixed:
+ Res.push_back("-fobjc-dispatch-method=mixed");
+ break;
+ case CodeGenOptions::NonLegacy:
+ Res.push_back("-fobjc-dispatch-method=non-legacy");
+ break;
+ }
+ if (Opts.NumRegisterParameters) {
+ Res.push_back("-mregparm");
+ Res.push_back(llvm::utostr(Opts.NumRegisterParameters));
+ }
+ if (Opts.RelaxAll)
+ Res.push_back("-mrelax-all");
+ if (Opts.SoftFloat)
+ Res.push_back("-msoft-float");
+ if (Opts.UnwindTables)
+ Res.push_back("-munwind-tables");
+ if (Opts.RelocationModel != "pic") {
+ Res.push_back("-mrelocation-model");
+ Res.push_back(Opts.RelocationModel);
+ }
+ if (!Opts.VerifyModule)
+ Res.push_back("-disable-llvm-verifier");
+}
+
+static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IncludeSystemHeaders)
+ Res.push_back("-sys-header-deps");
+ if (Opts.ShowHeaderIncludes)
+ Res.push_back("-H");
+ if (!Opts.HeaderIncludeOutputFile.empty()) {
+ Res.push_back("-header-include-file");
+ Res.push_back(Opts.HeaderIncludeOutputFile);
+ }
+ if (Opts.UsePhonyTargets)
+ Res.push_back("-MP");
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-dependency-file");
+ Res.push_back(Opts.OutputFile);
+ }
+ for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i) {
+ Res.push_back("-MT");
+ Res.push_back(Opts.Targets[i]);
+ }
+}
+
+static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IgnoreWarnings)
+ Res.push_back("-w");
+ if (Opts.NoRewriteMacros)
+ Res.push_back("-Wno-rewrite-macros");
+ if (Opts.Pedantic)
+ Res.push_back("-pedantic");
+ if (Opts.PedanticErrors)
+ Res.push_back("-pedantic-errors");
+ if (!Opts.ShowColumn)
+ Res.push_back("-fno-show-column");
+ if (!Opts.ShowLocation)
+ Res.push_back("-fno-show-source-location");
+ if (!Opts.ShowCarets)
+ Res.push_back("-fno-caret-diagnostics");
+ if (!Opts.ShowFixits)
+ Res.push_back("-fno-diagnostics-fixit-info");
+ if (Opts.ShowSourceRanges)
+ Res.push_back("-fdiagnostics-print-source-range-info");
+ if (Opts.ShowParseableFixits)
+ Res.push_back("-fdiagnostics-parseable-fixits");
+ if (Opts.ShowColors)
+ Res.push_back("-fcolor-diagnostics");
+ if (Opts.VerifyDiagnostics)
+ Res.push_back("-verify");
+ if (Opts.ShowOptionNames)
+ Res.push_back("-fdiagnostics-show-option");
+ if (Opts.ShowCategories == 1)
+ Res.push_back("-fdiagnostics-show-category=id");
+ else if (Opts.ShowCategories == 2)
+ Res.push_back("-fdiagnostics-show-category=name");
+ if (Opts.ErrorLimit) {
+ Res.push_back("-ferror-limit");
+ Res.push_back(llvm::utostr(Opts.ErrorLimit));
+ }
+ if (Opts.MacroBacktraceLimit
+ != DiagnosticOptions::DefaultMacroBacktraceLimit) {
+ Res.push_back("-fmacro-backtrace-limit");
+ Res.push_back(llvm::utostr(Opts.MacroBacktraceLimit));
+ }
+ if (Opts.TemplateBacktraceLimit
+ != DiagnosticOptions::DefaultTemplateBacktraceLimit) {
+ Res.push_back("-ftemplate-backtrace-limit");
+ Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit));
+ }
+
+ if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) {
+ Res.push_back("-ftabstop");
+ Res.push_back(llvm::utostr(Opts.TabStop));
+ }
+ if (Opts.MessageLength) {
+ Res.push_back("-fmessage-length");
+ Res.push_back(llvm::utostr(Opts.MessageLength));
+ }
+ if (!Opts.DumpBuildInformation.empty()) {
+ Res.push_back("-dump-build-information");
+ Res.push_back(Opts.DumpBuildInformation);
+ }
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
+ Res.push_back("-W" + Opts.Warnings[i]);
+}
+
+static const char *getInputKindName(InputKind Kind) {
+ switch (Kind) {
+ case IK_None: break;
+ case IK_AST: return "ast";
+ case IK_Asm: return "assembler-with-cpp";
+ case IK_C: return "c";
+ case IK_CXX: return "c++";
+ case IK_LLVM_IR: return "ir";
+ case IK_ObjC: return "objective-c";
+ case IK_ObjCXX: return "objective-c++";
+ case IK_OpenCL: return "cl";
+ case IK_CUDA: return "cuda";
+ case IK_PreprocessedC: return "cpp-output";
+ case IK_PreprocessedCXX: return "c++-cpp-output";
+ case IK_PreprocessedObjC: return "objective-c-cpp-output";
+ case IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
+ }
+
+ llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static const char *getActionName(frontend::ActionKind Kind) {
+ switch (Kind) {
+ case frontend::PluginAction:
+ llvm_unreachable("Invalid kind!");
+
+ case frontend::ASTDump: return "-ast-dump";
+ case frontend::ASTDumpXML: return "-ast-dump-xml";
+ case frontend::ASTPrint: return "-ast-print";
+ case frontend::ASTPrintXML: return "-ast-print-xml";
+ case frontend::ASTView: return "-ast-view";
+ case frontend::BoostCon: return "-boostcon";
+ case frontend::CreateModule: return "-create-module";
+ case frontend::DumpRawTokens: return "-dump-raw-tokens";
+ case frontend::DumpTokens: return "-dump-tokens";
+ case frontend::EmitAssembly: return "-S";
+ case frontend::EmitBC: return "-emit-llvm-bc";
+ case frontend::EmitHTML: return "-emit-html";
+ case frontend::EmitLLVM: return "-emit-llvm";
+ case frontend::EmitLLVMOnly: return "-emit-llvm-only";
+ case frontend::EmitCodeGenOnly: return "-emit-codegen-only";
+ case frontend::EmitObj: return "-emit-obj";
+ case frontend::FixIt: return "-fixit";
+ case frontend::GeneratePCH: return "-emit-pch";
+ case frontend::GeneratePTH: return "-emit-pth";
+ case frontend::InitOnly: return "-init-only";
+ case frontend::ParseSyntaxOnly: return "-fsyntax-only";
+ case frontend::PrintDeclContext: return "-print-decl-contexts";
+ case frontend::PrintPreamble: return "-print-preamble";
+ case frontend::PrintPreprocessedInput: return "-E";
+ case frontend::RewriteMacros: return "-rewrite-macros";
+ case frontend::RewriteObjC: return "-rewrite-objc";
+ case frontend::RewriteTest: return "-rewrite-test";
+ case frontend::RunAnalysis: return "-analyze";
+ case frontend::RunPreprocessorOnly: return "-Eonly";
+ }
+
+ llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static void FileSystemOptsToArgs(const FileSystemOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.WorkingDir.empty()) {
+ Res.push_back("-working-directory");
+ Res.push_back(Opts.WorkingDir);
+ }
+}
+
+static void FrontendOptsToArgs(const FrontendOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.DisableFree)
+ Res.push_back("-disable-free");
+ if (Opts.RelocatablePCH)
+ Res.push_back("-relocatable-pch");
+ if (Opts.ChainedPCH)
+ Res.push_back("-chained-pch");
+ if (Opts.ShowHelp)
+ Res.push_back("-help");
+ if (Opts.ShowMacrosInCodeCompletion)
+ Res.push_back("-code-completion-macros");
+ if (Opts.ShowCodePatternsInCodeCompletion)
+ Res.push_back("-code-completion-patterns");
+ if (!Opts.ShowGlobalSymbolsInCodeCompletion)
+ Res.push_back("-no-code-completion-globals");
+ if (Opts.ShowStats)
+ Res.push_back("-print-stats");
+ if (Opts.ShowTimers)
+ Res.push_back("-ftime-report");
+ if (Opts.ShowVersion)
+ Res.push_back("-version");
+ if (Opts.FixWhatYouCan)
+ Res.push_back("-fix-what-you-can");
+
+ bool NeedLang = false;
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
+ if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
+ Opts.Inputs[i].first)
+ NeedLang = true;
+ if (NeedLang) {
+ Res.push_back("-x");
+ Res.push_back(getInputKindName(Opts.Inputs[0].first));
+ }
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
+ assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
+ "Unable to represent this input vector!");
+ Res.push_back(Opts.Inputs[i].second);
+ }
+
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-o");
+ Res.push_back(Opts.OutputFile);
+ }
+ if (!Opts.CodeCompletionAt.FileName.empty()) {
+ Res.push_back("-code-completion-at");
+ Res.push_back(Opts.CodeCompletionAt.FileName + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Column));
+ }
+ if (Opts.ProgramAction != frontend::PluginAction)
+ Res.push_back(getActionName(Opts.ProgramAction));
+ if (!Opts.ActionName.empty()) {
+ Res.push_back("-plugin");
+ Res.push_back(Opts.ActionName);
+ for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i) {
+ Res.push_back("-plugin-arg-" + Opts.ActionName);
+ Res.push_back(Opts.PluginArgs[i]);
+ }
+ }
+ for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i) {
+ Res.push_back("-load");
+ Res.push_back(Opts.Plugins[i]);
+ }
+ for (unsigned i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
+ Res.push_back("-add-plugin");
+ Res.push_back(Opts.AddPluginActions[i]);
+ for(unsigned ai = 0, ae = Opts.AddPluginArgs.size(); ai != ae; ++ai) {
+ Res.push_back("-plugin-arg-" + Opts.AddPluginActions[i]);
+ Res.push_back(Opts.AddPluginArgs[i][ai]);
+ }
+ }
+ for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i) {
+ Res.push_back("-ast-merge");
+ Res.push_back(Opts.ASTMergeFiles[i]);
+ }
+ for (unsigned i = 0, e = Opts.Modules.size(); i != e; ++i) {
+ Res.push_back("-import-module");
+ Res.push_back(Opts.Modules[i]);
+ }
+ for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) {
+ Res.push_back("-mllvm");
+ Res.push_back(Opts.LLVMArgs[i]);
+ }
+}
+
+static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.Sysroot != "/") {
+ Res.push_back("-isysroot");
+ Res.push_back(Opts.Sysroot);
+ }
+
+ for (unsigned i = 0, e = Opts.CXXSystemIncludes.size(); i != e; ++i) {
+ Res.push_back("-cxx-system-include");
+ Res.push_back(Opts.CXXSystemIncludes[i]);
+ }
+
+ /// User specified include entries.
+ for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
+ if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied))
+ llvm::report_fatal_error("Invalid option set!");
+ if (E.IsUserSupplied) {
+ if (E.Group == frontend::After) {
+ Res.push_back("-idirafter");
+ } else if (E.Group == frontend::Quoted) {
+ Res.push_back("-iquote");
+ } else if (E.Group == frontend::System) {
+ Res.push_back("-isystem");
+ } else {
+ assert(E.Group == frontend::Angled && "Invalid group!");
+ Res.push_back(E.IsFramework ? "-F" : "-I");
+ }
+ } else {
+ if (E.Group != frontend::Angled && E.Group != frontend::System)
+ llvm::report_fatal_error("Invalid option set!");
+ Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
+ "-iwithprefix");
+ }
+ Res.push_back(E.Path);
+ }
+
+ if (!Opts.EnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::report_fatal_error("Not yet implemented!");
+ }
+ if (!Opts.CEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::report_fatal_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::report_fatal_error("Not yet implemented!");
+ }
+ if (!Opts.CXXEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::report_fatal_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCXXEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::report_fatal_error("Not yet implemented!");
+ }
+ if (!Opts.ResourceDir.empty()) {
+ Res.push_back("-resource-dir");
+ Res.push_back(Opts.ResourceDir);
+ }
+ if (!Opts.UseStandardIncludes)
+ Res.push_back("-nostdinc");
+ if (!Opts.UseStandardCXXIncludes)
+ Res.push_back("-nostdinc++");
+ if (Opts.Verbose)
+ Res.push_back("-v");
+}
+
+static void LangOptsToArgs(const LangOptions &Opts,
+ std::vector<std::string> &Res) {
+ LangOptions DefaultLangOpts;
+
+ // FIXME: Need to set -std to get all the implicit options.
+
+ // FIXME: We want to only pass options relative to the defaults, which
+ // requires constructing a target. :(
+ //
+ // It would be better to push the all target specific choices into the driver,
+ // so that everything below that was more uniform.
+
+ if (Opts.Trigraphs)
+ Res.push_back("-trigraphs");
+ // Implicit based on the input kind:
+ // AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
+ // Implicit based on the input language standard:
+ // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
+ if (Opts.DollarIdents)
+ Res.push_back("-fdollars-in-identifiers");
+ if (Opts.GNUMode && !Opts.GNUKeywords)
+ Res.push_back("-fno-gnu-keywords");
+ if (!Opts.GNUMode && Opts.GNUKeywords)
+ Res.push_back("-fgnu-keywords");
+ if (Opts.Microsoft)
+ Res.push_back("-fms-extensions");
+ if (Opts.MSCVersion != 0)
+ Res.push_back("-fmsc-version=" + llvm::utostr(Opts.MSCVersion));
+ if (Opts.Borland)
+ Res.push_back("-fborland-extensions");
+ if (Opts.ObjCNonFragileABI)
+ Res.push_back("-fobjc-nonfragile-abi");
+ if (Opts.ObjCNonFragileABI2)
+ Res.push_back("-fobjc-nonfragile-abi");
+ if (Opts.ObjCDefaultSynthProperties)
+ Res.push_back("-fobjc-default-synthesize-properties");
+ // NoInline is implicit.
+ if (!Opts.CXXOperatorNames)
+ Res.push_back("-fno-operator-names");
+ if (Opts.PascalStrings)
+ Res.push_back("-fpascal-strings");
+ if (Opts.CatchUndefined)
+ Res.push_back("-fcatch-undefined-behavior");
+ if (Opts.WritableStrings)
+ Res.push_back("-fwritable-strings");
+ if (Opts.ConstStrings)
+ Res.push_back("-Wwrite-strings");
+ if (!Opts.LaxVectorConversions)
+ Res.push_back("-fno-lax-vector-conversions");
+ if (Opts.AltiVec)
+ Res.push_back("-faltivec");
+ if (Opts.Exceptions)
+ Res.push_back("-fexceptions");
+ if (Opts.SjLjExceptions)
+ Res.push_back("-fsjlj-exceptions");
+ if (!Opts.ObjCExceptions)
+ Res.push_back("-fno-objc-exceptions");
+ if (!Opts.RTTI)
+ Res.push_back("-fno-rtti");
+ if (Opts.MSBitfields)
+ Res.push_back("-mms-bitfields");
+ if (!Opts.NeXTRuntime)
+ Res.push_back("-fgnu-runtime");
+ if (Opts.Freestanding)
+ Res.push_back("-ffreestanding");
+ if (Opts.FormatExtensions)
+ Res.push_back("-fformat-extensions");
+ if (Opts.NoBuiltin)
+ Res.push_back("-fno-builtin");
+ if (!Opts.AssumeSaneOperatorNew)
+ Res.push_back("-fno-assume-sane-operator-new");
+ if (!Opts.ThreadsafeStatics)
+ Res.push_back("-fno-threadsafe-statics");
+ if (Opts.POSIXThreads)
+ Res.push_back("-pthread");
+ if (Opts.Blocks)
+ Res.push_back("-fblocks");
+ if (Opts.EmitAllDecls)
+ Res.push_back("-femit-all-decls");
+ if (Opts.MathErrno)
+ Res.push_back("-fmath-errno");
+ switch (Opts.getSignedOverflowBehavior()) {
+ case LangOptions::SOB_Undefined: break;
+ case LangOptions::SOB_Defined: Res.push_back("-fwrapv"); break;
+ case LangOptions::SOB_Trapping:
+ Res.push_back("-ftrapv"); break;
+ if (!Opts.OverflowHandler.empty()) {
+ Res.push_back("-ftrapv-handler");
+ Res.push_back(Opts.OverflowHandler);
+ }
+ }
+ if (Opts.HeinousExtensions)
+ Res.push_back("-fheinous-gnu-extensions");
+ // Optimize is implicit.
+ // OptimizeSize is implicit.
+ if (Opts.Static)
+ Res.push_back("-static-define");
+ if (Opts.DumpRecordLayouts)
+ Res.push_back("-fdump-record-layouts");
+ if (Opts.DumpVTableLayouts)
+ Res.push_back("-fdump-vtable-layouts");
+ if (Opts.NoBitFieldTypeAlign)
+ Res.push_back("-fno-bitfield-type-alignment");
+ if (Opts.PICLevel) {
+ Res.push_back("-pic-level");
+ Res.push_back(llvm::utostr(Opts.PICLevel));
+ }
+ if (Opts.ObjCGCBitmapPrint)
+ Res.push_back("-print-ivar-layout");
+ if (Opts.NoConstantCFStrings)
+ Res.push_back("-fno-constant-cfstrings");
+ if (!Opts.AccessControl)
+ Res.push_back("-fno-access-control");
+ if (!Opts.CharIsSigned)
+ Res.push_back("-fno-signed-char");
+ if (Opts.ShortWChar)
+ Res.push_back("-fshort-wchar");
+ if (!Opts.ElideConstructors)
+ Res.push_back("-fno-elide-constructors");
+ if (Opts.getGCMode() != LangOptions::NonGC) {
+ if (Opts.getGCMode() == LangOptions::HybridGC) {
+ Res.push_back("-fobjc-gc");
+ } else {
+ assert(Opts.getGCMode() == LangOptions::GCOnly && "Invalid GC mode!");
+ Res.push_back("-fobjc-gc-only");
+ }
+ }
+ if (Opts.AppleKext)
+ Res.push_back("-fapple-kext");
+
+ if (Opts.getVisibilityMode() != DefaultVisibility) {
+ Res.push_back("-fvisibility");
+ if (Opts.getVisibilityMode() == HiddenVisibility) {
+ Res.push_back("hidden");
+ } else {
+ assert(Opts.getVisibilityMode() == ProtectedVisibility &&
+ "Invalid visibility!");
+ Res.push_back("protected");
+ }
+ }
+ if (Opts.InlineVisibilityHidden)
+ Res.push_back("-fvisibility-inlines-hidden");
+
+ if (Opts.getStackProtectorMode() != 0) {
+ Res.push_back("-stack-protector");
+ Res.push_back(llvm::utostr(Opts.getStackProtectorMode()));
+ }
+ if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) {
+ Res.push_back("-ftemplate-depth");
+ Res.push_back(llvm::utostr(Opts.InstantiationDepth));
+ }
+ if (!Opts.ObjCConstantStringClass.empty()) {
+ Res.push_back("-fconstant-string-class");
+ Res.push_back(Opts.ObjCConstantStringClass);
+ }
+}
+
+static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
+ Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") +
+ Opts.Macros[i].first);
+ for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
+ // FIXME: We need to avoid reincluding the implicit PCH and PTH includes.
+ Res.push_back("-include");
+ Res.push_back(Opts.Includes[i]);
+ }
+ for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
+ Res.push_back("-imacros");
+ Res.push_back(Opts.MacroIncludes[i]);
+ }
+ if (!Opts.UsePredefines)
+ Res.push_back("-undef");
+ if (Opts.DetailedRecord)
+ Res.push_back("-detailed-preprocessing-record");
+ if (!Opts.ImplicitPCHInclude.empty()) {
+ Res.push_back("-include-pch");
+ Res.push_back(Opts.ImplicitPCHInclude);
+ }
+ if (!Opts.ImplicitPTHInclude.empty()) {
+ Res.push_back("-include-pth");
+ Res.push_back(Opts.ImplicitPTHInclude);
+ }
+ if (!Opts.TokenCache.empty()) {
+ if (Opts.ImplicitPTHInclude.empty()) {
+ Res.push_back("-token-cache");
+ Res.push_back(Opts.TokenCache);
+ } else
+ assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
+ "Unsupported option combination!");
+ }
+ for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
+ Res.push_back("-remap-file");
+ Res.push_back(Opts.RemappedFiles[i].first + ";" +
+ Opts.RemappedFiles[i].second);
+ }
+}
+
+static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.ShowCPP && !Opts.ShowMacros)
+ llvm::report_fatal_error("Invalid option combination!");
+
+ if (Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dD");
+ else if (!Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dM");
+
+ if (!Opts.ShowLineMarkers)
+ Res.push_back("-P");
+ if (Opts.ShowComments)
+ Res.push_back("-C");
+ if (Opts.ShowMacroComments)
+ Res.push_back("-CC");
+}
+
+static void TargetOptsToArgs(const TargetOptions &Opts,
+ std::vector<std::string> &Res) {
+ Res.push_back("-triple");
+ Res.push_back(Opts.Triple);
+ if (!Opts.CPU.empty()) {
+ Res.push_back("-target-cpu");
+ Res.push_back(Opts.CPU);
+ }
+ if (!Opts.ABI.empty()) {
+ Res.push_back("-target-abi");
+ Res.push_back(Opts.ABI);
+ }
+ if (!Opts.LinkerVersion.empty()) {
+ Res.push_back("-target-linker-version");
+ Res.push_back(Opts.LinkerVersion);
+ }
+ if (!Opts.CXXABI.empty()) {
+ Res.push_back("-cxx-abi");
+ Res.push_back(Opts.CXXABI);
+ }
+ for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
+ Res.push_back("-target-feature");
+ Res.push_back(Opts.Features[i]);
+ }
+}
+
+void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
+ AnalyzerOptsToArgs(getAnalyzerOpts(), Res);
+ CodeGenOptsToArgs(getCodeGenOpts(), Res);
+ DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
+ DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
+ FileSystemOptsToArgs(getFileSystemOpts(), Res);
+ FrontendOptsToArgs(getFrontendOpts(), Res);
+ HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
+ LangOptsToArgs(getLangOpts(), Res);
+ PreprocessorOptsToArgs(getPreprocessorOpts(), Res);
+ PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res);
+ TargetOptsToArgs(getTargetOpts(), Res);
+}
+
+//===----------------------------------------------------------------------===//
+// Deserialization (to args)
+//===----------------------------------------------------------------------===//
+
+using namespace clang::driver;
+using namespace clang::driver::cc1options;
+
+//
+
+static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
+ Diagnostic &Diags) {
+ unsigned DefaultOpt = 0;
+ if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable))
+ DefaultOpt = 2;
+ // -Os implies -O2
+ return Args.hasArg(OPT_Os) ? 2 :
+ Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags);
+}
+
+static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
+ Diagnostic &Diags) {
+ using namespace cc1options;
+
+ Opts.AnalysisList.clear();
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \
+ if (Args.hasArg(OPT_analysis_##NAME)) Opts.AnalysisList.push_back(NAME);
+#include "clang/Frontend/Analyses.def"
+
+ if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
+ llvm::StringRef Name = A->getValue(Args);
+ AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ .Case(CMDFLAG, NAME##Model)
+#include "clang/Frontend/Analyses.def"
+ .Default(NumStores);
+ // FIXME: Error handling.
+ if (Value == NumStores)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << Name;
+ else
+ Opts.AnalysisStoreOpt = Value;
+ }
+
+ if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
+ llvm::StringRef Name = A->getValue(Args);
+ AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ .Case(CMDFLAG, NAME##Model)
+#include "clang/Frontend/Analyses.def"
+ .Default(NumConstraints);
+ // FIXME: Error handling.
+ if (Value == NumConstraints)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << Name;
+ else
+ Opts.AnalysisConstraintsOpt = Value;
+ }
+
+ if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
+ llvm::StringRef Name = A->getValue(Args);
+ AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
+ .Case(CMDFLAG, PD_##NAME)
+#include "clang/Frontend/Analyses.def"
+ .Default(NUM_ANALYSIS_DIAG_CLIENTS);
+ // FIXME: Error handling.
+ if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << Name;
+ else
+ Opts.AnalysisDiagOpt = Value;
+ }
+
+ Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
+ Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
+ Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
+ Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+ Opts.AnalyzeNestedBlocks =
+ Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
+ Opts.AnalyzerStats = Args.hasArg(OPT_analysis_AnalyzerStats);
+ Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
+ Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
+ Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
+ Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
+ Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors);
+ Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers);
+ Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
+ Opts.EnableExperimentalInternalChecks =
+ Args.hasArg(OPT_analyzer_experimental_internal_checks);
+ Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
+ Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
+ Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
+ Opts.EagerlyTrimEGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph);
+ Opts.InlineCall = Args.hasArg(OPT_analyzer_inline_call);
+ Opts.BufferOverflows = Args.hasArg(OPT_analysis_WarnBufferOverflows);
+
+ Opts.CheckersControlList.clear();
+ for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker,
+ OPT_analyzer_disable_checker),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+ bool enable = (A->getOption().getID() == OPT_analyzer_checker);
+ Opts.CheckersControlList.push_back(std::make_pair(A->getValue(Args),
+ enable));
+ }
+}
+
+static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+ Diagnostic &Diags) {
+ using namespace cc1options;
+
+ Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
+ if (Opts.OptimizationLevel > 3) {
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel;
+ Opts.OptimizationLevel = 3;
+ }
+
+ // We must always run at least the always inlining pass.
+ Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
+ : CodeGenOptions::OnlyAlwaysInlining;
+
+ Opts.DebugInfo = Args.hasArg(OPT_g);
+ Opts.LimitDebugInfo = Args.hasArg(OPT_flimit_debug_info);
+ Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
+ Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
+ Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
+ Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
+ Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
+ Opts.NoCommon = Args.hasArg(OPT_fno_common);
+ Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
+ Opts.OptimizeSize = Args.hasArg(OPT_Os);
+ Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
+ Args.hasArg(OPT_ffreestanding));
+ Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) ||
+ (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
+
+ Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+ Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
+ Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
+ Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
+ Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
+ Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
+ Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
+ Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables);
+ Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable);
+ Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
+ Opts.NoInfsFPMath = Opts.NoNaNsFPMath = Args.hasArg(OPT_cl_finite_math_only)||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
+ Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
+ Opts.NumRegisterParameters = Args.getLastArgIntValue(OPT_mregparm, 0, Diags);
+ Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
+ Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
+ Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
+ Opts.UnsafeFPMath = Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
+ Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
+ Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
+
+ Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections);
+ Opts.DataSections = Args.hasArg(OPT_fdata_sections);
+
+ Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
+ Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
+
+ Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+ Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
+
+ if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
+ llvm::StringRef Name = A->getValue(Args);
+ unsigned Method = llvm::StringSwitch<unsigned>(Name)
+ .Case("legacy", CodeGenOptions::Legacy)
+ .Case("non-legacy", CodeGenOptions::NonLegacy)
+ .Case("mixed", CodeGenOptions::Mixed)
+ .Default(~0U);
+ if (Method == ~0U)
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ else
+ Opts.ObjCDispatchMethod = Method;
+ }
+}
+
+static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
+ ArgList &Args) {
+ using namespace cc1options;
+ Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
+ Opts.Targets = Args.getAllArgValues(OPT_MT);
+ Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
+ Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
+ Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
+ Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
+}
+
+static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+ Diagnostic &Diags) {
+ using namespace cc1options;
+ Opts.IgnoreWarnings = Args.hasArg(OPT_w);
+ Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
+ Opts.Pedantic = Args.hasArg(OPT_pedantic);
+ Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
+ Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
+ Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics);
+ Opts.ShowColumn = !Args.hasArg(OPT_fno_show_column);
+ Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
+ Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
+ Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
+
+ llvm::StringRef ShowOverloads =
+ Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
+ if (ShowOverloads == "best")
+ Opts.ShowOverloads = Diagnostic::Ovl_Best;
+ else if (ShowOverloads == "all")
+ Opts.ShowOverloads = Diagnostic::Ovl_All;
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
+ << ShowOverloads;
+
+ llvm::StringRef ShowCategory =
+ Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
+ if (ShowCategory == "none")
+ Opts.ShowCategories = 0;
+ else if (ShowCategory == "id")
+ Opts.ShowCategories = 1;
+ else if (ShowCategory == "name")
+ Opts.ShowCategories = 2;
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
+ << ShowCategory;
+
+ Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
+ Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
+ Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);
+ Opts.MacroBacktraceLimit
+ = Args.getLastArgIntValue(OPT_fmacro_backtrace_limit,
+ DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
+ Opts.TemplateBacktraceLimit
+ = Args.getLastArgIntValue(OPT_ftemplate_backtrace_limit,
+ DiagnosticOptions::DefaultTemplateBacktraceLimit,
+ Diags);
+ Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop,
+ DiagnosticOptions::DefaultTabStop, Diags);
+ if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
+ Diags.Report(diag::warn_ignoring_ftabstop_value)
+ << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
+ Opts.TabStop = DiagnosticOptions::DefaultTabStop;
+ }
+ Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
+ Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
+ Opts.Warnings = Args.getAllArgValues(OPT_W);
+}
+
+static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
+ Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory);
+}
+
+static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
+ Diagnostic &Diags) {
+ using namespace cc1options;
+ Opts.ProgramAction = frontend::ParseSyntaxOnly;
+ if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
+ switch (A->getOption().getID()) {
+ default:
+ assert(0 && "Invalid option in group!");
+ case OPT_ast_dump:
+ Opts.ProgramAction = frontend::ASTDump; break;
+ case OPT_ast_dump_xml:
+ Opts.ProgramAction = frontend::ASTDumpXML; break;
+ case OPT_ast_print:
+ Opts.ProgramAction = frontend::ASTPrint; break;
+ case OPT_ast_print_xml:
+ Opts.ProgramAction = frontend::ASTPrintXML; break;
+ case OPT_ast_view:
+ Opts.ProgramAction = frontend::ASTView; break;
+ case OPT_boostcon:
+ Opts.ProgramAction = frontend::BoostCon; break;
+ case OPT_dump_raw_tokens:
+ Opts.ProgramAction = frontend::DumpRawTokens; break;
+ case OPT_dump_tokens:
+ Opts.ProgramAction = frontend::DumpTokens; break;
+ case OPT_S:
+ Opts.ProgramAction = frontend::EmitAssembly; break;
+ case OPT_emit_llvm_bc:
+ Opts.ProgramAction = frontend::EmitBC; break;
+ case OPT_emit_html:
+ Opts.ProgramAction = frontend::EmitHTML; break;
+ case OPT_emit_llvm:
+ Opts.ProgramAction = frontend::EmitLLVM; break;
+ case OPT_emit_llvm_only:
+ Opts.ProgramAction = frontend::EmitLLVMOnly; break;
+ case OPT_emit_codegen_only:
+ Opts.ProgramAction = frontend::EmitCodeGenOnly; break;
+ case OPT_emit_obj:
+ Opts.ProgramAction = frontend::EmitObj; break;
+ case OPT_fixit_EQ:
+ Opts.FixItSuffix = A->getValue(Args);
+ // fall-through!
+ case OPT_fixit:
+ Opts.ProgramAction = frontend::FixIt; break;
+ case OPT_emit_pch:
+ Opts.ProgramAction = frontend::GeneratePCH; break;
+ case OPT_emit_pth:
+ Opts.ProgramAction = frontend::GeneratePTH; break;
+ case OPT_init_only:
+ Opts.ProgramAction = frontend::InitOnly; break;
+ case OPT_fsyntax_only:
+ Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
+ case OPT_print_decl_contexts:
+ Opts.ProgramAction = frontend::PrintDeclContext; break;
+ case OPT_print_preamble:
+ Opts.ProgramAction = frontend::PrintPreamble; break;
+ case OPT_E:
+ Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
+ case OPT_rewrite_macros:
+ Opts.ProgramAction = frontend::RewriteMacros; break;
+ case OPT_rewrite_objc:
+ Opts.ProgramAction = frontend::RewriteObjC; break;
+ case OPT_rewrite_test:
+ Opts.ProgramAction = frontend::RewriteTest; break;
+ case OPT_analyze:
+ Opts.ProgramAction = frontend::RunAnalysis; break;
+ case OPT_Eonly:
+ Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
+ case OPT_create_module:
+ Opts.ProgramAction = frontend::CreateModule; break;
+ }
+ }
+
+ if (const Arg* A = Args.getLastArg(OPT_plugin)) {
+ Opts.Plugins.push_back(A->getValue(Args,0));
+ Opts.ProgramAction = frontend::PluginAction;
+ Opts.ActionName = A->getValue(Args);
+
+ for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
+ end = Args.filtered_end(); it != end; ++it) {
+ if ((*it)->getValue(Args, 0) == Opts.ActionName)
+ Opts.PluginArgs.push_back((*it)->getValue(Args, 1));
+ }
+ }
+
+ Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
+ Opts.AddPluginArgs.resize(Opts.AddPluginActions.size());
+ for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
+ for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
+ end = Args.filtered_end(); it != end; ++it) {
+ if ((*it)->getValue(Args, 0) == Opts.AddPluginActions[i])
+ Opts.AddPluginArgs[i].push_back((*it)->getValue(Args, 1));
+ }
+ }
+
+ if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
+ Opts.CodeCompletionAt =
+ ParsedSourceLocation::FromString(A->getValue(Args));
+ if (Opts.CodeCompletionAt.FileName.empty())
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue(Args);
+ }
+ Opts.DisableFree = Args.hasArg(OPT_disable_free);
+
+ Opts.OutputFile = Args.getLastArgValue(OPT_o);
+ Opts.Plugins = Args.getAllArgValues(OPT_load);
+ Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
+ Opts.ChainedPCH = Args.hasArg(OPT_chained_pch);
+ Opts.ShowHelp = Args.hasArg(OPT_help);
+ Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
+ Opts.ShowCodePatternsInCodeCompletion
+ = Args.hasArg(OPT_code_completion_patterns);
+ Opts.ShowGlobalSymbolsInCodeCompletion
+ = !Args.hasArg(OPT_no_code_completion_globals);
+ Opts.ShowStats = Args.hasArg(OPT_print_stats);
+ Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
+ Opts.ShowVersion = Args.hasArg(OPT_version);
+ Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
+ Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
+ Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
+ Opts.Modules = Args.getAllArgValues(OPT_import_module);
+
+ InputKind DashX = IK_None;
+ if (const Arg *A = Args.getLastArg(OPT_x)) {
+ DashX = llvm::StringSwitch<InputKind>(A->getValue(Args))
+ .Case("c", IK_C)
+ .Case("cl", IK_OpenCL)
+ .Case("c", IK_C)
+ .Case("cl", IK_OpenCL)
+ .Case("cuda", IK_CUDA)
+ .Case("c++", IK_CXX)
+ .Case("objective-c", IK_ObjC)
+ .Case("objective-c++", IK_ObjCXX)
+ .Case("cpp-output", IK_PreprocessedC)
+ .Case("assembler-with-cpp", IK_Asm)
+ .Case("c++-cpp-output", IK_PreprocessedCXX)
+ .Case("objective-c-cpp-output", IK_PreprocessedObjC)
+ .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX)
+ .Case("c-header", IK_C)
+ .Case("objective-c-header", IK_ObjC)
+ .Case("c++-header", IK_CXX)
+ .Case("objective-c++-header", IK_ObjCXX)
+ .Case("ast", IK_AST)
+ .Case("ir", IK_LLVM_IR)
+ .Default(IK_None);
+ if (DashX == IK_None)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue(Args);
+ }
+
+ // '-' is the default input if none is given.
+ std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
+ Opts.Inputs.clear();
+ if (Inputs.empty())
+ Inputs.push_back("-");
+ for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+ InputKind IK = DashX;
+ if (IK == IK_None) {
+ IK = FrontendOptions::getInputKindForExtension(
+ llvm::StringRef(Inputs[i]).rsplit('.').second);
+ // FIXME: Remove this hack.
+ if (i == 0)
+ DashX = IK;
+ }
+ Opts.Inputs.push_back(std::make_pair(IK, Inputs[i]));
+ }
+
+ return DashX;
+}
+
+std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
+ void *MainAddr) {
+ llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
+
+ if (!P.isEmpty()) {
+ P.eraseComponent(); // Remove /clang from foo/bin/clang
+ P.eraseComponent(); // Remove /bin from foo/bin
+
+ // Get foo/lib/clang/<version>/include
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ }
+
+ return P.str();
+}
+
+static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
+ using namespace cc1options;
+ Opts.CXXSystemIncludes = Args.getAllArgValues(OPT_cxx_system_include);
+ Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
+ Opts.Verbose = Args.hasArg(OPT_v);
+ Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
+ Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc);
+ Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx);
+ Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
+
+ // Add -I... and -F... options in order.
+ for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F),
+ ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args), frontend::Angled, true,
+ /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true);
+
+ // Add -iprefix/-iwith-prefix/-iwithprefixbefore options.
+ llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
+ for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix,
+ OPT_iwithprefixbefore),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ if (A->getOption().matches(OPT_iprefix))
+ Prefix = A->getValue(Args);
+ else if (A->getOption().matches(OPT_iwithprefix))
+ Opts.AddPath(Prefix.str() + A->getValue(Args),
+ frontend::System, false, false, true);
+ else
+ Opts.AddPath(Prefix.str() + A->getValue(Args),
+ frontend::Angled, false, false, true);
+ }
+
+ for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
+ ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, true);
+ for (arg_iterator it = Args.filtered_begin(OPT_iquote),
+ ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true);
+ for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot),
+ ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
+ (*it)->getOption().matches(OPT_iwithsysroot));
+
+ // FIXME: Need options for the various environment variables!
+}
+
+void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
+ LangStandard::Kind LangStd) {
+ // Set some properties which depend soley on the input kind; it would be nice
+ // to move these to the language standard, and have the driver resolve the
+ // input kind + language standard.
+ if (IK == IK_Asm) {
+ Opts.AsmPreprocessor = 1;
+ } else if (IK == IK_ObjC ||
+ IK == IK_ObjCXX ||
+ IK == IK_PreprocessedObjC ||
+ IK == IK_PreprocessedObjCXX) {
+ Opts.ObjC1 = Opts.ObjC2 = 1;
+ }
+
+ if (LangStd == LangStandard::lang_unspecified) {
+ // Based on the base language, pick one.
+ switch (IK) {
+ case IK_None:
+ case IK_AST:
+ case IK_LLVM_IR:
+ assert(0 && "Invalid input kind!");
+ case IK_OpenCL:
+ LangStd = LangStandard::lang_opencl;
+ break;
+ case IK_CUDA:
+ LangStd = LangStandard::lang_cuda;
+ break;
+ case IK_Asm:
+ case IK_C:
+ case IK_PreprocessedC:
+ case IK_ObjC:
+ case IK_PreprocessedObjC:
+ LangStd = LangStandard::lang_gnu99;
+ break;
+ case IK_CXX:
+ case IK_PreprocessedCXX:
+ case IK_ObjCXX:
+ case IK_PreprocessedObjCXX:
+ LangStd = LangStandard::lang_gnucxx98;
+ break;
+ }
+ }
+
+ const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
+ Opts.BCPLComment = Std.hasBCPLComments();
+ Opts.C99 = Std.isC99();
+ Opts.CPlusPlus = Std.isCPlusPlus();
+ Opts.CPlusPlus0x = Std.isCPlusPlus0x();
+ Opts.Digraphs = Std.hasDigraphs();
+ Opts.GNUMode = Std.isGNUMode();
+ Opts.GNUInline = !Std.isC99();
+ Opts.HexFloats = Std.hasHexFloats();
+ Opts.ImplicitInt = Std.hasImplicitInt();
+
+ // OpenCL has some additional defaults.
+ if (LangStd == LangStandard::lang_opencl) {
+ Opts.OpenCL = 1;
+ Opts.AltiVec = 1;
+ Opts.CXXOperatorNames = 1;
+ Opts.LaxVectorConversions = 1;
+ Opts.DefaultFPContract = 1;
+ }
+
+ if (LangStd == LangStandard::lang_cuda)
+ Opts.CUDA = 1;
+
+ // OpenCL and C++ both have bool, true, false keywords.
+ Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+
+ Opts.GNUKeywords = Opts.GNUMode;
+ Opts.CXXOperatorNames = Opts.CPlusPlus;
+
+ // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+ // is specified, or -std is set to a conforming mode.
+ Opts.Trigraphs = !Opts.GNUMode;
+
+ Opts.DollarIdents = !Opts.AsmPreprocessor;
+}
+
+static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
+ Diagnostic &Diags) {
+ // FIXME: Cleanup per-file based stuff.
+ LangStandard::Kind LangStd = LangStandard::lang_unspecified;
+ if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
+ LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
+#define LANGSTANDARD(id, name, desc, features) \
+ .Case(name, LangStandard::lang_##id)
+#include "clang/Frontend/LangStandards.def"
+ .Default(LangStandard::lang_unspecified);
+ if (LangStd == LangStandard::lang_unspecified)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue(Args);
+ }
+
+ if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
+ if (strcmp(A->getValue(Args), "CL1.1") != 0) {
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue(Args);
+ }
+ }
+
+ CompilerInvocation::setLangDefaults(Opts, IK, LangStd);
+
+ // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
+ // keywords. This behavior is provided by GCC's poorly named '-fasm' flag,
+ // while a subset (the non-C++ GNU keywords) is provided by GCC's
+ // '-fgnu-keywords'. Clang conflates the two for simplicity under the single
+ // name, as it doesn't seem a useful distinction.
+ Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
+ Opts.GNUKeywords);
+
+ if (Args.hasArg(OPT_fno_operator_names))
+ Opts.CXXOperatorNames = 0;
+
+ if (Args.hasArg(OPT_fobjc_gc_only))
+ Opts.setGCMode(LangOptions::GCOnly);
+ else if (Args.hasArg(OPT_fobjc_gc))
+ Opts.setGCMode(LangOptions::HybridGC);
+
+ if (Args.hasArg(OPT_fapple_kext)) {
+ if (!Opts.CPlusPlus)
+ Diags.Report(diag::warn_c_kext);
+ else
+ Opts.AppleKext = 1;
+ }
+
+ if (Args.hasArg(OPT_print_ivar_layout))
+ Opts.ObjCGCBitmapPrint = 1;
+ if (Args.hasArg(OPT_fno_constant_cfstrings))
+ Opts.NoConstantCFStrings = 1;
+
+ if (Args.hasArg(OPT_faltivec))
+ Opts.AltiVec = 1;
+
+ if (Args.hasArg(OPT_pthread))
+ Opts.POSIXThreads = 1;
+
+ llvm::StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
+ if (Vis == "default")
+ Opts.setVisibilityMode(DefaultVisibility);
+ else if (Vis == "hidden")
+ Opts.setVisibilityMode(HiddenVisibility);
+ else if (Vis == "protected")
+ Opts.setVisibilityMode(ProtectedVisibility);
+ else
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+
+ if (Args.hasArg(OPT_fvisibility_inlines_hidden))
+ Opts.InlineVisibilityHidden = 1;
+
+ if (Args.hasArg(OPT_ftrapv)) {
+ Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
+ // Set the handler, if one is specified.
+ Opts.OverflowHandler =
+ Args.getLastArgValue(OPT_ftrapv_handler);
+ }
+ else if (Args.hasArg(OPT_fwrapv))
+ Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
+
+ if (Args.hasArg(OPT_trigraphs))
+ Opts.Trigraphs = 1;
+
+ Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
+ OPT_fno_dollars_in_identifiers,
+ Opts.DollarIdents);
+ Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
+ Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+ Opts.MSCVersion = Args.getLastArgIntValue(OPT_fmsc_version, 0, Diags);
+ Opts.Borland = Args.hasArg(OPT_fborland_extensions);
+ Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
+ Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
+ if (Args.hasArg(OPT_fno_lax_vector_conversions))
+ Opts.LaxVectorConversions = 0;
+ if (Args.hasArg(OPT_fno_threadsafe_statics))
+ Opts.ThreadsafeStatics = 0;
+ Opts.Exceptions = Args.hasArg(OPT_fexceptions);
+ Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
+ Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+ Opts.Blocks = Args.hasArg(OPT_fblocks);
+ Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
+ Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
+ Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
+ Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
+ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions);
+ Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
+ Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
+ Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
+ Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
+ Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
+ Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
+ Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024,
+ Diags);
+ Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy,
+ 0, Diags);
+ Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields);
+ Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
+ Opts.ObjCConstantStringClass =
+ Args.getLastArgValue(OPT_fconstant_string_class);
+ Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
+ if (Opts.ObjCNonFragileABI)
+ Opts.ObjCNonFragileABI2 = true;
+ Opts.ObjCDefaultSynthProperties =
+ Args.hasArg(OPT_fobjc_default_synthesize_properties);
+ Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
+ Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
+ Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
+ Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
+ Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
+ Opts.Static = Args.hasArg(OPT_static_define);
+ Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts);
+ Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
+ Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking);
+ Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align);
+ Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant);
+ Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math);
+ Opts.OptimizeSize = 0;
+
+ // FIXME: Eliminate this dependency.
+ unsigned Opt = getOptimizationLevel(Args, IK, Diags);
+ Opts.Optimize = Opt != 0;
+
+ // This is the __NO_INLINE__ define, which just depends on things like the
+ // optimization level and -fno-inline, not actually whether the backend has
+ // inlining enabled.
+ //
+ // FIXME: This is affected by other options (-fno-inline).
+ Opts.NoInline = !Opt;
+
+ unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags);
+ switch (SSP) {
+ default:
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
+ break;
+ case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
+ case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break;
+ case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
+ }
+}
+
+static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+ FileManager &FileMgr,
+ Diagnostic &Diags) {
+ using namespace cc1options;
+ Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
+ Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
+ if (const Arg *A = Args.getLastArg(OPT_token_cache))
+ Opts.TokenCache = A->getValue(Args);
+ else
+ Opts.TokenCache = Opts.ImplicitPTHInclude;
+ Opts.UsePredefines = !Args.hasArg(OPT_undef);
+ Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
+ Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
+
+ Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
+ for (arg_iterator it = Args.filtered_begin(OPT_error_on_deserialized_pch_decl),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue(Args));
+ }
+
+ if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
+ llvm::StringRef Value(A->getValue(Args));
+ size_t Comma = Value.find(',');
+ unsigned Bytes = 0;
+ unsigned EndOfLine = 0;
+
+ if (Comma == llvm::StringRef::npos ||
+ Value.substr(0, Comma).getAsInteger(10, Bytes) ||
+ Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
+ Diags.Report(diag::err_drv_preamble_format);
+ else {
+ Opts.PrecompiledPreambleBytes.first = Bytes;
+ Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
+ }
+ }
+
+ // Add macros from the command line.
+ for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ if ((*it)->getOption().matches(OPT_D))
+ Opts.addMacroDef((*it)->getValue(Args));
+ else
+ Opts.addMacroUndef((*it)->getValue(Args));
+ }
+
+ Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
+
+ // Add the ordered list of -includes.
+ for (arg_iterator it = Args.filtered_begin(OPT_include, OPT_include_pch,
+ OPT_include_pth),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ // PCH is handled specially, we need to extra the original include path.
+ if (A->getOption().matches(OPT_include_pch)) {
+ std::string OriginalFile =
+ ASTReader::getOriginalSourceFile(A->getValue(Args), FileMgr, Diags);
+ if (OriginalFile.empty())
+ continue;
+
+ Opts.Includes.push_back(OriginalFile);
+ } else
+ Opts.Includes.push_back(A->getValue(Args));
+ }
+
+ // Include 'altivec.h' if -faltivec option present
+ if (Args.hasArg(OPT_faltivec))
+ Opts.Includes.push_back("altivec.h");
+
+ for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(A->getValue(Args)).split(';');
+
+ if (Split.second.empty()) {
+ Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
+ continue;
+ }
+
+ Opts.addRemappedFile(Split.first, Split.second);
+ }
+}
+
+static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
+ ArgList &Args) {
+ using namespace cc1options;
+ Opts.ShowCPP = !Args.hasArg(OPT_dM);
+ Opts.ShowComments = Args.hasArg(OPT_C);
+ Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
+ Opts.ShowMacroComments = Args.hasArg(OPT_CC);
+ Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+}
+
+static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
+ using namespace cc1options;
+ Opts.ABI = Args.getLastArgValue(OPT_target_abi);
+ Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
+ Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
+ Opts.Features = Args.getAllArgValues(OPT_target_feature);
+ Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
+ Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
+
+ // Use the host triple if unspecified.
+ if (Opts.Triple.empty())
+ Opts.Triple = llvm::sys::getHostTriple();
+}
+
+//
+
+void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+ const char *const *ArgBegin,
+ const char *const *ArgEnd,
+ Diagnostic &Diags) {
+ // Parse the arguments.
+ llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
+ unsigned MissingArgIndex, MissingArgCount;
+ llvm::OwningPtr<InputArgList> Args(
+ Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
+
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diags.Report(diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+ // Issue errors on unknown arguments.
+ for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
+ ie = Args->filtered_end(); it != ie; ++it)
+ Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
+
+ ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags);
+ ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
+ ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
+ ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
+ // FIXME: We shouldn't have to pass the DashX option around here
+ InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
+ ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags);
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
+ if (DashX != IK_AST && DashX != IK_LLVM_IR)
+ ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
+ // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
+ // PCH file and find the original header name. Remove the need to do that in
+ // ParsePreprocessorArgs and remove the FileManager
+ // parameters from the function and the "FileManager.h" #include.
+ FileManager FileMgr(Res.getFileSystemOpts());
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
+ ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
+ ParseTargetArgs(Res.getTargetOpts(), *Args);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..8d3d225
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,183 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
+ DocumentXML& Doc;
+
+ void addSubNodes(FunctionDecl* FD) {
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+ Visit(FD->getParamDecl(i));
+ Doc.toParent();
+ }
+ }
+
+ void addFunctionBody(FunctionDecl* FD) {
+ if (FD->isThisDeclarationADefinition()) {
+ Doc.addSubNode("Body");
+ Doc.PrintStmt(FD->getBody());
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(RecordDecl* RD) {
+ for (RecordDecl::decl_iterator i = RD->decls_begin(),
+ e = RD->decls_end(); i != e; ++i) {
+ if (!(*i)->isImplicit()) {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+ }
+
+ void addSubNodes(CXXRecordDecl* RD) {
+ addSubNodes(cast<RecordDecl>(RD));
+
+ if (RD->isDefinition()) {
+ // FIXME: This breaks XML generation
+ //Doc.addAttribute("num_bases", RD->getNumBases());
+
+ for (CXXRecordDecl::base_class_iterator
+ base = RD->bases_begin(),
+ bend = RD->bases_end();
+ base != bend;
+ ++base) {
+ Doc.addSubNode("Base");
+ Doc.addAttribute("id", base->getType());
+ AccessSpecifier as = base->getAccessSpecifierAsWritten();
+ const char* as_name = "";
+ switch(as) {
+ case AS_none: as_name = ""; break;
+ case AS_public: as_name = "public"; break;
+ case AS_protected: as_name = "protected"; break;
+ case AS_private: as_name = "private"; break;
+ }
+ Doc.addAttributeOptional("access", as_name);
+ Doc.addAttribute("is_virtual", base->isVirtual());
+ Doc.toParent();
+ }
+ }
+ }
+
+ void addSubNodes(EnumDecl* ED) {
+ for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
+ e = ED->enumerator_end(); i != e; ++i) {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumConstantDecl* ECD) {
+ if (ECD->getInitExpr())
+ Doc.PrintStmt(ECD->getInitExpr());
+ }
+
+ void addSubNodes(FieldDecl* FdD) {
+ if (FdD->isBitField())
+ Doc.PrintStmt(FdD->getBitWidth());
+ }
+
+ void addSubNodes(VarDecl* V) {
+ if (V->getInit())
+ Doc.PrintStmt(V->getInit());
+ }
+
+ void addSubNodes(ParmVarDecl* argDecl) {
+ if (argDecl->getDefaultArg())
+ Doc.PrintStmt(argDecl->getDefaultArg());
+ }
+
+ void addSubNodes(DeclContext* ns) {
+
+ for (DeclContext::decl_iterator
+ d = ns->decls_begin(),
+ dend = ns->decls_end();
+ d != dend;
+ ++d) {
+ Visit(*d);
+ Doc.toParent();
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, EnumDecl* ED) {
+ const QualType& enumType = ED->getIntegerType();
+ if (!enumType.isNull())
+ Doc.addAttribute(pName, enumType);
+ }
+
+ void addIdAttribute(LinkageSpecDecl* ED) {
+ Doc.addAttribute("id", ED);
+ }
+
+ void addIdAttribute(NamedDecl* ND) {
+ Doc.addAttribute("id", ND);
+ }
+
+public:
+ DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define SUB_NODE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
+
+#define SUB_NODE_FN_BODY_XML addFunctionBody(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D) {
+ DeclPrinter(*this).Visit(D);
+ toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
new file mode 100644
index 0000000..bc5a55d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
@@ -0,0 +1,184 @@
+//===--- DependencyFile.cpp - Generate dependency file --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code generates dependency files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+namespace {
+class DependencyFileCallback : public PPCallbacks {
+ std::vector<std::string> Files;
+ llvm::StringSet<> FilesSet;
+ const Preprocessor *PP;
+ std::vector<std::string> Targets;
+ llvm::raw_ostream *OS;
+ bool IncludeSystemHeaders;
+ bool PhonyTarget;
+private:
+ bool FileMatchesDepCriteria(const char *Filename,
+ SrcMgr::CharacteristicKind FileType);
+ void OutputDependencyFile();
+
+public:
+ DependencyFileCallback(const Preprocessor *_PP,
+ llvm::raw_ostream *_OS,
+ const DependencyOutputOptions &Opts)
+ : PP(_PP), Targets(Opts.Targets), OS(_OS),
+ IncludeSystemHeaders(Opts.IncludeSystemHeaders),
+ PhonyTarget(Opts.UsePhonyTargets) {}
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType);
+
+ virtual void EndOfMainFile() {
+ OutputDependencyFile();
+ delete OS;
+ OS = 0;
+ }
+};
+}
+
+void clang::AttachDependencyFileGen(Preprocessor &PP,
+ const DependencyOutputOptions &Opts) {
+ if (Opts.Targets.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
+ return;
+ }
+
+ std::string Err;
+ llvm::raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err));
+ if (!Err.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_error_opening)
+ << Opts.OutputFile << Err;
+ return;
+ }
+
+ PP.addPPCallbacks(new DependencyFileCallback(&PP, OS, Opts));
+}
+
+/// FileMatchesDepCriteria - Determine whether the given Filename should be
+/// considered as a dependency.
+bool DependencyFileCallback::FileMatchesDepCriteria(const char *Filename,
+ SrcMgr::CharacteristicKind FileType) {
+ if (strcmp("<built-in>", Filename) == 0)
+ return false;
+
+ if (IncludeSystemHeaders)
+ return true;
+
+ return FileType == SrcMgr::C_User;
+}
+
+void DependencyFileCallback::FileChanged(SourceLocation Loc,
+ FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType) {
+ if (Reason != PPCallbacks::EnterFile)
+ return;
+
+ // Dependency generation really does want to go all the way to the
+ // file entry for a source location to find out what is depended on.
+ // We do not want #line markers to affect dependency generation!
+ SourceManager &SM = PP->getSourceManager();
+
+ const FileEntry *FE =
+ SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc)));
+ if (FE == 0) return;
+
+ const char *Filename = FE->getName();
+ if (!FileMatchesDepCriteria(Filename, FileType))
+ return;
+
+ // Remove leading "./"
+ if (Filename[0] == '.' && Filename[1] == '/')
+ Filename = &Filename[2];
+
+ if (FilesSet.insert(Filename))
+ Files.push_back(Filename);
+}
+
+/// PrintFilename - GCC escapes spaces, but apparently not ' or " or other
+/// scary characters.
+static void PrintFilename(llvm::raw_ostream &OS, llvm::StringRef Filename) {
+ for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
+ if (Filename[i] == ' ')
+ OS << '\\';
+ OS << Filename[i];
+ }
+}
+
+void DependencyFileCallback::OutputDependencyFile() {
+ // Write out the dependency targets, trying to avoid overly long
+ // lines when possible. We try our best to emit exactly the same
+ // dependency file as GCC (4.2), assuming the included files are the
+ // same.
+ const unsigned MaxColumns = 75;
+ unsigned Columns = 0;
+
+ for (std::vector<std::string>::iterator
+ I = Targets.begin(), E = Targets.end(); I != E; ++I) {
+ unsigned N = I->length();
+ if (Columns == 0) {
+ Columns += N;
+ } else if (Columns + N + 2 > MaxColumns) {
+ Columns = N + 2;
+ *OS << " \\\n ";
+ } else {
+ Columns += N + 1;
+ *OS << ' ';
+ }
+ // Targets already quoted as needed.
+ *OS << *I;
+ }
+
+ *OS << ':';
+ Columns += 1;
+
+ // Now add each dependency in the order it was seen, but avoiding
+ // duplicates.
+ for (std::vector<std::string>::iterator I = Files.begin(),
+ E = Files.end(); I != E; ++I) {
+ // Start a new line if this would exceed the column limit. Make
+ // sure to leave space for a trailing " \" in case we need to
+ // break the line on the next iteration.
+ unsigned N = I->length();
+ if (Columns + (N + 1) + 2 > MaxColumns) {
+ *OS << " \\\n ";
+ Columns = 2;
+ }
+ *OS << ' ';
+ PrintFilename(*OS, *I);
+ Columns += N + 1;
+ }
+ *OS << '\n';
+
+ // Create phony targets if requested.
+ if (PhonyTarget) {
+ // Skip the first entry, this is always the input file itself.
+ for (std::vector<std::string>::iterator I = Files.begin() + 1,
+ E = Files.end(); I != E; ++I) {
+ *OS << '\n';
+ PrintFilename(*OS, *I);
+ *OS << ":\n";
+ }
+ }
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DiagChecker.cpp b/contrib/llvm/tools/clang/lib/Frontend/DiagChecker.cpp
new file mode 100644
index 0000000..66d7ed7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/DiagChecker.cpp
@@ -0,0 +1,301 @@
+//===--- DiagChecker.cpp - Diagnostic Checking Functions ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Process the input files and check that the diagnostic messages are expected.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){
+ unsigned ID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, String);
+ PP.Diag(Pos, ID);
+}
+
+
+// USING THE DIAGNOSTIC CHECKER:
+//
+// Indicating that a line expects an error or a warning is simple. Put a comment
+// on the line that has the diagnostic, use "expected-{error,warning}" to tag
+// if it's an expected error or warning, and place the expected text between {{
+// and }} markers. The full text doesn't have to be included, only enough to
+// ensure that the correct diagnostic was emitted.
+//
+// Here's an example:
+//
+// int A = B; // expected-error {{use of undeclared identifier 'B'}}
+//
+// You can place as many diagnostics on one line as you wish. To make the code
+// more readable, you can use slash-newline to separate out the diagnostics.
+//
+// The simple syntax above allows each specification to match exactly one error.
+// You can use the extended syntax to customize this. The extended syntax is
+// "expected-<type> <n> {{diag text}}", where <type> is one of "error",
+// "warning" or "note", and <n> is a positive integer. This allows the
+// diagnostic to appear as many times as specified. Example:
+//
+// void f(); // expected-note 2 {{previous declaration is here}}
+//
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+///
+static void FindDiagnostics(const char *CommentStart, unsigned CommentLen,
+ DiagList &ExpectedDiags,
+ Preprocessor &PP, SourceLocation Pos,
+ const char *ExpectedStr) {
+ const char *CommentEnd = CommentStart+CommentLen;
+ unsigned ExpectedStrLen = strlen(ExpectedStr);
+
+ // Find all expected-foo diagnostics in the string and add them to
+ // ExpectedDiags.
+ while (CommentStart != CommentEnd) {
+ CommentStart = std::find(CommentStart, CommentEnd, 'e');
+ if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
+
+ // If this isn't expected-foo, ignore it.
+ if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
+ ++CommentStart;
+ continue;
+ }
+
+ CommentStart += ExpectedStrLen;
+
+ // Skip whitespace.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // Default, if we find the '{' now, is 1 time.
+ int Times = 1;
+ int Temp = 0;
+ // In extended syntax, there could be a digit now.
+ while (CommentStart != CommentEnd &&
+ CommentStart[0] >= '0' && CommentStart[0] <= '9') {
+ Temp *= 10;
+ Temp += CommentStart[0] - '0';
+ ++CommentStart;
+ }
+ if (Temp > 0)
+ Times = Temp;
+
+ // Skip whitespace again.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // We should have a {{ now.
+ if (CommentEnd-CommentStart < 2 ||
+ CommentStart[0] != '{' || CommentStart[1] != '{') {
+ if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
+ EmitError(PP, Pos, "bogus characters before '{{' in expected string");
+ else
+ EmitError(PP, Pos, "cannot find start ('{{') of expected string");
+ return;
+ }
+ CommentStart += 2;
+
+ // Find the }}.
+ const char *ExpectedEnd = CommentStart;
+ while (1) {
+ ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
+ if (CommentEnd-ExpectedEnd < 2) {
+ EmitError(PP, Pos, "cannot find end ('}}') of expected string");
+ return;
+ }
+
+ if (ExpectedEnd[1] == '}')
+ break;
+
+ ++ExpectedEnd; // Skip over singular }'s
+ }
+
+ std::string Msg(CommentStart, ExpectedEnd);
+ std::string::size_type FindPos;
+ while ((FindPos = Msg.find("\\n")) != std::string::npos)
+ Msg.replace(FindPos, 2, "\n");
+ // Add is possibly multiple times.
+ for (int i = 0; i < Times; ++i)
+ ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+
+ CommentStart = ExpectedEnd;
+ }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+// expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP,
+ DiagList &ExpectedErrors,
+ DiagList &ExpectedWarnings,
+ DiagList &ExpectedNotes) {
+ // Create a raw lexer to pull all the comments out of the main file. We don't
+ // want to look in #include'd headers for expected-error strings.
+ FileID FID = PP.getSourceManager().getMainFileID();
+
+ // Create a lexer to lex all the tokens of the main file in raw mode.
+ const llvm::MemoryBuffer *FromFile = PP.getSourceManager().getBuffer(FID);
+ Lexer RawLex(FID, FromFile, PP.getSourceManager(), PP.getLangOptions());
+
+ // Return comments as tokens, this is how we find expected diagnostics.
+ RawLex.SetCommentRetentionState(true);
+
+ Token Tok;
+ Tok.setKind(tok::comment);
+ while (Tok.isNot(tok::eof)) {
+ RawLex.Lex(Tok);
+ if (!Tok.is(tok::comment)) continue;
+
+ std::string Comment = PP.getSpelling(Tok);
+ if (Comment.empty()) continue;
+
+
+ // Find all expected errors.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
+ Tok.getLocation(), "expected-error");
+
+ // Find all expected warnings.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
+ Tok.getLocation(), "expected-warning");
+
+ // Find all expected notes.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
+ Tok.getLocation(), "expected-note");
+ };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static bool PrintProblem(SourceManager &SourceMgr,
+ const_diag_iterator diag_begin,
+ const_diag_iterator diag_end,
+ const char *Msg) {
+ if (diag_begin == diag_end) return false;
+
+ llvm::errs() << Msg << "\n";
+ for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
+ llvm::errs() << " Line " << SourceMgr.getInstantiationLineNumber(I->first)
+ << " " << I->second << "\n";
+
+ return true;
+}
+
+/// CompareDiagLists - Compare two diagnostic lists and return the difference
+/// between them.
+///
+static bool CompareDiagLists(SourceManager &SourceMgr,
+ const_diag_iterator d1_begin,
+ const_diag_iterator d1_end,
+ const_diag_iterator d2_begin,
+ const_diag_iterator d2_end,
+ const char *MsgLeftOnly,
+ const char *MsgRightOnly) {
+ DiagList LeftOnly;
+ DiagList Left(d1_begin, d1_end);
+ DiagList Right(d2_begin, d2_end);
+
+ for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+ unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first);
+ const std::string &Diag1 = I->second;
+
+ DiagList::iterator II, IE;
+ for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+ unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ if (LineNo1 != LineNo2) continue;
+
+ const std::string &Diag2 = II->second;
+ if (Diag2.find(Diag1) != std::string::npos ||
+ Diag1.find(Diag2) != std::string::npos) {
+ break;
+ }
+ }
+ if (II == IE) {
+ // Not found.
+ LeftOnly.push_back(*I);
+ } else {
+ // Found. The same cannot be found twice.
+ Right.erase(II);
+ }
+ }
+ // Now all that's left in Right are those that were not matched.
+
+ return PrintProblem(SourceMgr, LeftOnly.begin(), LeftOnly.end(), MsgLeftOnly)
+ | PrintProblem(SourceMgr, Right.begin(), Right.end(), MsgRightOnly);
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static bool CheckResults(Preprocessor &PP,
+ const DiagList &ExpectedErrors,
+ const DiagList &ExpectedWarnings,
+ const DiagList &ExpectedNotes) {
+ const DiagnosticClient *DiagClient = PP.getDiagnostics().getClient();
+ assert(DiagClient != 0 &&
+ "DiagChecker requires a valid TextDiagnosticBuffer");
+ const TextDiagnosticBuffer &Diags =
+ static_cast<const TextDiagnosticBuffer&>(*DiagClient);
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // We want to capture the delta between what was expected and what was
+ // seen.
+ //
+ // Expected \ Seen - set expected but not seen
+ // Seen \ Expected - set seen but not expected
+ bool HadProblem = false;
+
+ // See if there are error mismatches.
+ HadProblem |= CompareDiagLists(SourceMgr,
+ ExpectedErrors.begin(), ExpectedErrors.end(),
+ Diags.err_begin(), Diags.err_end(),
+ "Errors expected but not seen:",
+ "Errors seen but not expected:");
+
+ // See if there are warning mismatches.
+ HadProblem |= CompareDiagLists(SourceMgr,
+ ExpectedWarnings.begin(),
+ ExpectedWarnings.end(),
+ Diags.warn_begin(), Diags.warn_end(),
+ "Warnings expected but not seen:",
+ "Warnings seen but not expected:");
+
+ // See if there are note mismatches.
+ HadProblem |= CompareDiagLists(SourceMgr,
+ ExpectedNotes.begin(),
+ ExpectedNotes.end(),
+ Diags.note_begin(), Diags.note_end(),
+ "Notes expected but not seen:",
+ "Notes seen but not expected:");
+
+ return HadProblem;
+}
+
+
+/// CheckDiagnostics - Gather the expected diagnostics and check them.
+bool clang::CheckDiagnostics(Preprocessor &PP) {
+ // Gather the set of expected diagnostics.
+ DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
+ FindExpectedDiags(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+
+ // Check that the expected diagnostics occurred.
+ return CheckResults(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
new file mode 100644
index 0000000..b24ece5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
@@ -0,0 +1,376 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include <cstdio>
+
+namespace clang {
+
+//---------------------------------------------------------
+DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
+ Out(out),
+ Ctx(0),
+ HasCurrentNodeSubNodes(false) {
+ NodeStack.push(rootName);
+ Out << "<?xml version=\"1.0\"?>\n<" << rootName;
+}
+
+//---------------------------------------------------------
+DocumentXML& DocumentXML::addSubNode(const std::string& name) {
+ if (!HasCurrentNodeSubNodes)
+ Out << ">\n";
+ NodeStack.push(name);
+ HasCurrentNodeSubNodes = false;
+ Indent();
+ Out << "<" << NodeStack.top();
+ return *this;
+}
+
+//---------------------------------------------------------
+void DocumentXML::Indent() {
+ for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
+ Out << ' ';
+}
+
+//---------------------------------------------------------
+DocumentXML& DocumentXML::toParent() {
+ assert(NodeStack.size() > 1 && "too much backtracking");
+
+ if (HasCurrentNodeSubNodes) {
+ Indent();
+ Out << "</" << NodeStack.top() << ">\n";
+ } else
+ Out << "/>\n";
+ NodeStack.pop();
+ HasCurrentNodeSubNodes = true;
+ return *this;
+}
+
+//---------------------------------------------------------
+namespace {
+
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
+
+unsigned getNewId(tIdType idType) {
+ static unsigned int idCounts[ID_LAST] = { 0 };
+ return ++idCounts[idType];
+}
+
+//---------------------------------------------------------
+inline std::string getPrefixedId(unsigned uId, tIdType idType) {
+ static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
+ char buffer[20];
+ char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
+ *--BufPtr = idPrefix[idType];
+ return BufPtr;
+}
+
+//---------------------------------------------------------
+template<class T, class V>
+bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) {
+ typename T::iterator i = idMap.find(value);
+ bool toAdd = i == idMap.end();
+ if (toAdd)
+ idMap.insert(typename T::value_type(value, getNewId(idType)));
+ return toAdd;
+}
+
+} // anon NS
+
+
+//---------------------------------------------------------
+std::string DocumentXML::escapeString(const char* pStr,
+ std::string::size_type len) {
+ std::string value;
+ value.reserve(len + 1);
+ char buffer[16];
+ for (unsigned i = 0; i < len; ++i) {
+ switch (char C = pStr[i]) {
+ default:
+ if (isprint(C))
+ value += C;
+ else {
+#ifdef LLVM_ON_WIN32
+ sprintf(buffer, "\\%03o", C);
+#else
+ snprintf(buffer, sizeof(buffer), "\\%03o", C);
+#endif
+ value += buffer;
+ }
+ break;
+
+ case '\n': value += "\\n"; break;
+ case '\t': value += "\\t"; break;
+ case '\a': value += "\\a"; break;
+ case '\b': value += "\\b"; break;
+ case '\r': value += "\\r"; break;
+
+ case '&': value += "&amp;"; break;
+ case '<': value += "&lt;"; break;
+ case '>': value += "&gt;"; break;
+ case '"': value += "&quot;"; break;
+ case '\'': value += "&apos;"; break;
+
+ }
+ }
+ return value;
+}
+
+//---------------------------------------------------------
+void DocumentXML::finalize() {
+ assert(NodeStack.size() == 1 && "not completely backtracked");
+
+ addSubNode("ReferenceSection");
+ addSubNode("Types");
+
+ for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
+ i != e; ++i) {
+ if (i->first.hasLocalQualifiers()) {
+ writeTypeToXML(i->first);
+ addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+ toParent();
+ }
+ }
+
+ for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(),
+ e = BasicTypes.end(); i != e; ++i) {
+ writeTypeToXML(i->first);
+ addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+ toParent();
+ }
+
+
+ toParent().addSubNode("Contexts");
+
+ for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(),
+ e = Contexts.end(); i != e; ++i) {
+ addSubNode(i->first->getDeclKindName());
+ addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first))
+ addAttribute("name", ND->getNameAsString());
+ if (const TagDecl *TD = dyn_cast<TagDecl>(i->first))
+ addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL));
+ else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first))
+ addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL));
+
+ if (const DeclContext* parent = i->first->getParent())
+ addAttribute("context", parent);
+ toParent();
+ }
+
+ toParent().addSubNode("Files");
+
+ for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(),
+ e = SourceFiles.end(); i != e; ++i) {
+ addSubNode("File");
+ addAttribute("id", getPrefixedId(i->second, ID_FILE));
+ addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
+ toParent();
+ }
+
+ toParent().toParent();
+
+ // write the root closing node (which has always subnodes)
+ Out << "</" << NodeStack.top() << ">\n";
+}
+
+//---------------------------------------------------------
+void DocumentXML::addAttribute(const char* pAttributeName,
+ const QualType& pType) {
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName,
+ const Type* pType) {
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName,
+ const NestedNameSpecifier* pNNS) {
+ switch (pNNS->getKind()) {
+ case NestedNameSpecifier::Identifier: {
+ IdentifierInfo *ii = pNNS->getAsIdentifier();
+ // FIXME how should we handle those ?
+ addPtrAttribute(pAttributeName, ii->getName().data());
+ break;
+ }
+ case NestedNameSpecifier::Namespace: {
+ addPtrAttribute(pAttributeName, pNNS->getAsNamespace());
+ break;
+ }
+ case NestedNameSpecifier::TypeSpec: {
+ addPtrAttribute(pAttributeName, pNNS->getAsType());
+ break;
+ }
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ addPtrAttribute(pAttributeName, pNNS->getAsType());
+ break;
+ }
+ case NestedNameSpecifier::Global: {
+ addPtrAttribute(pAttributeName, "::");
+ break;
+ }
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addTypeRecursively(const QualType& pType)
+{
+ if (addToMap(Types, pType))
+ {
+ addTypeRecursively(pType.getTypePtr());
+ // beautifier: a non-qualified type shall be transparent
+ if (!pType.hasLocalQualifiers())
+ {
+ Types[pType] = BasicTypes[pType.getTypePtr()];
+ }
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addTypeRecursively(const Type* pType)
+{
+ if (addToMap(BasicTypes, pType))
+ {
+ addParentTypes(pType);
+/*
+ // FIXME: doesn't work in the immediate streaming approach
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+ {
+ addSubNode("VariableArraySizeExpression");
+ PrintStmt(VAT->getSizeExpr());
+ toParent();
+ }
+*/
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
+{
+ addContextsRecursively(DC);
+ addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+ if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+ {
+ addContextsRecursively(DC);
+ addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+ }
+ else
+ {
+ addToMap(Decls, D);
+ addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+ addPtrAttribute(pName, static_cast<const DeclContext*>(D));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addContextsRecursively(const DeclContext *DC)
+{
+ if (DC != 0 && addToMap(Contexts, DC))
+ {
+ addContextsRecursively(DC->getParent());
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addSourceFileAttribute(const std::string& fileName)
+{
+ addToMap(SourceFiles, fileName, ID_FILE);
+ addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
+}
+
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+ addToMap(Labels, L, ID_LABEL);
+ addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
+//---------------------------------------------------------
+PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
+{
+ SourceManager& SM = Ctx->getSourceManager();
+ SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+ PresumedLoc PLoc;
+ if (!SpellingLoc.isInvalid())
+ {
+ PLoc = SM.getPresumedLoc(SpellingLoc);
+ if (PLoc.isValid()) {
+ addSourceFileAttribute(PLoc.getFilename());
+ addAttribute("line", PLoc.getLine());
+ addAttribute("col", PLoc.getColumn());
+ }
+ }
+ // else there is no error in some cases (eg. CXXThisExpr)
+ return PLoc;
+}
+
+//---------------------------------------------------------
+void DocumentXML::addLocationRange(const SourceRange& R)
+{
+ PresumedLoc PStartLoc = addLocation(R.getBegin());
+ if (R.getBegin() != R.getEnd())
+ {
+ SourceManager& SM = Ctx->getSourceManager();
+ SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd());
+ if (!SpellingLoc.isInvalid())
+ {
+ PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc);
+ if (PLoc.isInvalid()) {
+ } else if (PStartLoc.isInvalid() ||
+ strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) {
+ addToMap(SourceFiles, PLoc.getFilename(), ID_FILE);
+ addAttribute("endfile", PLoc.getFilename());
+ addAttribute("endline", PLoc.getLine());
+ addAttribute("endcol", PLoc.getColumn());
+ } else if (PLoc.getLine() != PStartLoc.getLine()) {
+ addAttribute("endline", PLoc.getLine());
+ addAttribute("endcol", PLoc.getColumn());
+ } else {
+ addAttribute("endcol", PLoc.getColumn());
+ }
+ }
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::PrintDecl(Decl *D)
+{
+ writeDeclToXML(D);
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
new file mode 100644
index 0000000..e3d8b85
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -0,0 +1,374 @@
+//===--- FrontendAction.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+
+/// \brief Dumps deserialized declarations.
+class DeserializedDeclsDumper : public ASTDeserializationListener {
+ ASTDeserializationListener *Previous;
+
+public:
+ DeserializedDeclsDumper(ASTDeserializationListener *Previous)
+ : Previous(Previous) { }
+
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
+ llvm::outs() << "PCH DECL: " << D->getDeclKindName();
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ llvm::outs() << " - " << ND->getNameAsString();
+ llvm::outs() << "\n";
+
+ if (Previous)
+ Previous->DeclRead(ID, D);
+ }
+};
+
+ /// \brief Checks deserialized declarations and emits error if a name
+ /// matches one given in command-line using -error-on-deserialized-decl.
+ class DeserializedDeclsChecker : public ASTDeserializationListener {
+ ASTContext &Ctx;
+ std::set<std::string> NamesToCheck;
+ ASTDeserializationListener *Previous;
+
+ public:
+ DeserializedDeclsChecker(ASTContext &Ctx,
+ const std::set<std::string> &NamesToCheck,
+ ASTDeserializationListener *Previous)
+ : Ctx(Ctx), NamesToCheck(NamesToCheck), Previous(Previous) { }
+
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
+ unsigned DiagID
+ = Ctx.getDiagnostics().getCustomDiagID(Diagnostic::Error,
+ "%0 was deserialized");
+ Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
+ << ND->getNameAsString();
+ }
+
+ if (Previous)
+ Previous->DeclRead(ID, D);
+ }
+};
+
+} // end anonymous namespace
+
+FrontendAction::FrontendAction() : Instance(0) {}
+
+FrontendAction::~FrontendAction() {}
+
+void FrontendAction::setCurrentFile(llvm::StringRef Value, InputKind Kind,
+ ASTUnit *AST) {
+ CurrentFile = Value;
+ CurrentFileKind = Kind;
+ CurrentASTUnit.reset(AST);
+}
+
+ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ ASTConsumer* Consumer = CreateASTConsumer(CI, InFile);
+ if (!Consumer)
+ return 0;
+
+ if (CI.getFrontendOpts().AddPluginActions.size() == 0)
+ return Consumer;
+
+ // Make sure the non-plugin consumer is first, so that plugins can't
+ // modifiy the AST.
+ std::vector<ASTConsumer*> Consumers(1, Consumer);
+
+ for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size();
+ i != e; ++i) {
+ // This is O(|plugins| * |add_plugins|), but since both numbers are
+ // way below 50 in practice, that's ok.
+ for (FrontendPluginRegistry::iterator
+ it = FrontendPluginRegistry::begin(),
+ ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().AddPluginActions[i]) {
+ llvm::OwningPtr<PluginASTAction> P(it->instantiate());
+ FrontendAction* c = P.get();
+ if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i]))
+ Consumers.push_back(c->CreateASTConsumer(CI, InFile));
+ }
+ }
+ }
+
+ return new MultiplexConsumer(Consumers);
+}
+
+bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
+ llvm::StringRef Filename,
+ InputKind InputKind) {
+ assert(!Instance && "Already processing a source file!");
+ assert(!Filename.empty() && "Unexpected empty filename!");
+ setCurrentFile(Filename, InputKind);
+ setCompilerInstance(&CI);
+
+ // AST files follow a very different path, since they share objects via the
+ // AST unit.
+ if (InputKind == IK_AST) {
+ assert(!usesPreprocessorOnly() &&
+ "Attempt to pass AST file to preprocessor only action!");
+ assert(hasASTFileSupport() &&
+ "This action does not have AST file support!");
+
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
+ std::string Error;
+ ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags,
+ CI.getFileSystemOpts());
+ if (!AST)
+ goto failure;
+
+ setCurrentFile(Filename, InputKind, AST);
+
+ // Set the shared objects, these are reset when we finish processing the
+ // file, otherwise the CompilerInstance will happily destroy them.
+ CI.setFileManager(&AST->getFileManager());
+ CI.setSourceManager(&AST->getSourceManager());
+ CI.setPreprocessor(&AST->getPreprocessor());
+ CI.setASTContext(&AST->getASTContext());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST consumer.
+ CI.setASTConsumer(CreateWrappedASTConsumer(CI, Filename));
+ if (!CI.hasASTConsumer())
+ goto failure;
+
+ return true;
+ }
+
+ // Set up the file and source managers, if needed.
+ if (!CI.hasFileManager())
+ CI.createFileManager();
+ if (!CI.hasSourceManager())
+ CI.createSourceManager(CI.getFileManager());
+
+ // IR files bypass the rest of initialization.
+ if (InputKind == IK_LLVM_IR) {
+ assert(hasIRSupport() &&
+ "This action does not have IR file support!");
+
+ // Inform the diagnostic client we are processing a source file.
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ return true;
+ }
+
+ // Set up the preprocessor.
+ CI.createPreprocessor();
+
+ // Inform the diagnostic client we are processing a source file.
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
+ &CI.getPreprocessor());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST context and consumer unless this is a preprocessor only
+ /// action.
+ if (!usesPreprocessorOnly()) {
+ CI.createASTContext();
+
+ llvm::OwningPtr<ASTConsumer> Consumer(
+ CreateWrappedASTConsumer(CI, Filename));
+ if (!Consumer)
+ goto failure;
+
+ CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
+
+ /// Use PCH?
+ if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
+ assert(hasPCHSupport() && "This action does not have PCH support!");
+ ASTDeserializationListener *DeserialListener
+ = CI.getInvocation().getFrontendOpts().ChainedPCH ?
+ Consumer->GetASTDeserializationListener() : 0;
+ if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls)
+ DeserialListener = new DeserializedDeclsDumper(DeserialListener);
+ if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty())
+ DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(),
+ CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
+ DeserialListener);
+ CI.createPCHExternalASTSource(
+ CI.getPreprocessorOpts().ImplicitPCHInclude,
+ CI.getPreprocessorOpts().DisablePCHValidation,
+ CI.getPreprocessorOpts().DisableStatCache,
+ DeserialListener);
+ if (!CI.getASTContext().getExternalSource())
+ goto failure;
+ }
+
+ CI.setASTConsumer(Consumer.take());
+ if (!CI.hasASTConsumer())
+ goto failure;
+ }
+
+ // Initialize builtin info as long as we aren't using an external AST
+ // source.
+ if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+ PP.getLangOptions());
+ }
+
+ return true;
+
+ // If we failed, reset state since the client will not end up calling the
+ // matching EndSourceFile().
+ failure:
+ if (isCurrentFileAST()) {
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ CI.getDiagnosticClient().EndSourceFile();
+ setCurrentFile("", IK_None);
+ setCompilerInstance(0);
+ return false;
+}
+
+void FrontendAction::Execute() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Initialize the main file entry. This needs to be delayed until after PCH
+ // has loaded.
+ if (isCurrentFileAST()) {
+ // Set the main file ID to an empty file.
+ //
+ // FIXME: We probably shouldn't need this, but for now this is the
+ // simplest way to reuse the logic in ParseAST.
+ const char *EmptyStr = "";
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBuffer(EmptyStr, "<dummy input>");
+ CI.getSourceManager().createMainFileIDForMemBuffer(SB);
+ } else {
+ if (!CI.InitializeSourceManager(getCurrentFile()))
+ return;
+ }
+
+ if (CI.hasFrontendTimer()) {
+ llvm::TimeRegion Timer(CI.getFrontendTimer());
+ ExecuteAction();
+ }
+ else ExecuteAction();
+}
+
+void FrontendAction::EndSourceFile() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Inform the diagnostic client we are done with this source file.
+ CI.getDiagnosticClient().EndSourceFile();
+
+ // Finalize the action.
+ EndSourceFileAction();
+
+ // Release the consumer and the AST, in that order since the consumer may
+ // perform actions in its destructor which require the context.
+ //
+ // FIXME: There is more per-file stuff we could just drop here?
+ if (CI.getFrontendOpts().DisableFree) {
+ CI.takeASTConsumer();
+ if (!isCurrentFileAST()) {
+ CI.takeSema();
+ CI.takeASTContext();
+ }
+ } else {
+ if (!isCurrentFileAST()) {
+ CI.setSema(0);
+ CI.setASTContext(0);
+ }
+ CI.setASTConsumer(0);
+ }
+
+ // Inform the preprocessor we are done.
+ if (CI.hasPreprocessor())
+ CI.getPreprocessor().EndSourceFile();
+
+ if (CI.getFrontendOpts().ShowStats) {
+ llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
+ CI.getPreprocessor().PrintStats();
+ CI.getPreprocessor().getIdentifierTable().PrintStats();
+ CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
+ CI.getSourceManager().PrintStats();
+ llvm::errs() << "\n";
+ }
+
+ // Cleanup the output streams, and erase the output files if we encountered
+ // an error.
+ CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred());
+
+ if (isCurrentFileAST()) {
+ CI.takeSema();
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ setCompilerInstance(0);
+ setCurrentFile("", IK_None);
+}
+
+//===----------------------------------------------------------------------===//
+// Utility Actions
+//===----------------------------------------------------------------------===//
+
+void ASTFrontendAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ if (hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ // Use a code completion consumer?
+ CodeCompleteConsumer *CompletionConsumer = 0;
+ if (CI.hasCodeCompletionConsumer())
+ CompletionConsumer = &CI.getCodeCompletionConsumer();
+
+ if (!CI.hasSema())
+ CI.createSema(usesCompleteTranslationUnit(), CompletionConsumer);
+
+ ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
+}
+
+ASTConsumer *
+PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
new file mode 100644
index 0000000..d8e7d29
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -0,0 +1,231 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Custom Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+void InitOnlyAction::ExecuteAction() {
+}
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+ return CreateASTPrinter(OS);
+ return 0;
+}
+
+ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
+ return CreateASTPrinterXML(OS);
+ return 0;
+}
+
+ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTDumper();
+}
+
+ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ llvm::raw_ostream *OS;
+ if (CI.getFrontendOpts().OutputFile.empty())
+ OS = &llvm::outs();
+ else
+ OS = CI.createDefaultOutputFile(false, InFile);
+ if (!OS) return 0;
+ return CreateASTDumperXML(*OS);
+}
+
+ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTViewer();
+}
+
+ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateDeclContextPrinter();
+}
+
+ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ std::string Sysroot;
+ std::string OutputFile;
+ llvm::raw_ostream *OS = 0;
+ bool Chaining;
+ if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining))
+ return 0;
+
+ const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+ Sysroot.c_str() : 0;
+ return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS);
+}
+
+bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ std::string &Sysroot,
+ std::string &OutputFile,
+ llvm::raw_ostream *&OS,
+ bool &Chaining) {
+ Sysroot = CI.getHeaderSearchOpts().Sysroot;
+ if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
+ CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
+ return true;
+ }
+
+ // We use createOutputFile here because this is exposed via libclang, and we
+ // must disable the RemoveFileOnSignal behavior.
+ OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile);
+ if (!OS)
+ return true;
+
+ OutputFile = CI.getFrontendOpts().OutputFile;
+ Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
+ !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
+ return false;
+}
+
+ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+void DumpRawTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ SourceManager &SM = PP.getSourceManager();
+
+ // Start lexing the specified input file.
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+ Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
+ RawLex.SetKeepWhitespaceMode(true);
+
+ Token RawTok;
+ RawLex.LexFromRawLexer(RawTok);
+ while (RawTok.isNot(tok::eof)) {
+ PP.DumpToken(RawTok, true);
+ llvm::errs() << "\n";
+ RawLex.LexFromRawLexer(RawTok);
+ }
+}
+
+void DumpTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ // Start preprocessing the specified input file.
+ Token Tok;
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ PP.DumpToken(Tok, true);
+ llvm::errs() << "\n";
+ } while (Tok.isNot(tok::eof));
+}
+
+void GeneratePTHAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ if (CI.getFrontendOpts().OutputFile.empty() ||
+ CI.getFrontendOpts().OutputFile == "-") {
+ // FIXME: Don't fail this way.
+ // FIXME: Verify that we can actually seek in the given file.
+ llvm::report_fatal_error("PTH requires a seekable file for output!");
+ }
+ llvm::raw_fd_ostream *OS =
+ CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS) return;
+
+ CacheTokens(CI.getPreprocessor(), OS);
+}
+
+void PreprocessOnlyAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+
+ // Ignore unknown pragmas.
+ PP.AddPragmaHandler(new EmptyPragmaHandler());
+
+ Token Tok;
+ // Start parsing the specified input file.
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ } while (Tok.isNot(tok::eof));
+}
+
+void PrintPreprocessedAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ // Output file needs to be set to 'Binary', to avoid converting Unix style
+ // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS) return;
+
+ DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
+ CI.getPreprocessorOutputOpts());
+}
+
+void PrintPreambleAction::ExecuteAction() {
+ switch (getCurrentFileKind()) {
+ case IK_C:
+ case IK_CXX:
+ case IK_ObjC:
+ case IK_ObjCXX:
+ case IK_OpenCL:
+ case IK_CUDA:
+ break;
+
+ case IK_None:
+ case IK_Asm:
+ case IK_PreprocessedC:
+ case IK_PreprocessedCXX:
+ case IK_PreprocessedObjC:
+ case IK_PreprocessedObjCXX:
+ case IK_AST:
+ case IK_LLVM_IR:
+ // We can't do anything with these.
+ return;
+ }
+
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::MemoryBuffer *Buffer
+ = CI.getFileManager().getBufferForFile(getCurrentFile());
+ if (Buffer) {
+ unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
+ llvm::outs().write(Buffer->getBufferStart(), Preamble);
+ delete Buffer;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
new file mode 100644
index 0000000..0a20051
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendOptions.cpp
@@ -0,0 +1,32 @@
+//===--- FrontendOptions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+InputKind FrontendOptions::getInputKindForExtension(llvm::StringRef Extension) {
+ return llvm::StringSwitch<InputKind>(Extension)
+ .Case("ast", IK_AST)
+ .Case("c", IK_C)
+ .Cases("S", "s", IK_Asm)
+ .Case("i", IK_PreprocessedC)
+ .Case("ii", IK_PreprocessedCXX)
+ .Case("m", IK_ObjC)
+ .Case("mi", IK_PreprocessedObjC)
+ .Cases("mm", "M", IK_ObjCXX)
+ .Case("mii", IK_PreprocessedObjCXX)
+ .Case("C", IK_CXX)
+ .Cases("C", "cc", "cp", IK_CXX)
+ .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
+ .Case("cl", IK_OpenCL)
+ .Case("cu", IK_CUDA)
+ .Cases("ll", "bc", IK_LLVM_IR)
+ .Default(IK_C);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
new file mode 100644
index 0000000..45ff1d2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -0,0 +1,113 @@
+//===--- HeaderIncludes.cpp - Generate Header Includes --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+namespace {
+class HeaderIncludesCallback : public PPCallbacks {
+ SourceManager &SM;
+ llvm::raw_ostream *OutputFile;
+ unsigned CurrentIncludeDepth;
+ bool HasProcessedPredefines;
+ bool OwnsOutputFile;
+ bool ShowAllHeaders;
+
+public:
+ HeaderIncludesCallback(const Preprocessor *PP, bool ShowAllHeaders_,
+ llvm::raw_ostream *OutputFile_, bool OwnsOutputFile_)
+ : SM(PP->getSourceManager()), OutputFile(OutputFile_),
+ CurrentIncludeDepth(0), HasProcessedPredefines(false),
+ OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_) {}
+
+ ~HeaderIncludesCallback() {
+ if (OwnsOutputFile)
+ delete OutputFile;
+ }
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType);
+};
+}
+
+void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
+ llvm::StringRef OutputPath) {
+ llvm::raw_ostream *OutputFile = &llvm::errs();
+ bool OwnsOutputFile = false;
+
+ // Open the output file, if used.
+ if (!OutputPath.empty()) {
+ std::string Error;
+ llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream(
+ OutputPath.str().c_str(), Error, llvm::raw_fd_ostream::F_Append);
+ if (!Error.empty()) {
+ PP.getDiagnostics().Report(
+ clang::diag::warn_fe_cc_print_header_failure) << Error;
+ delete OS;
+ } else {
+ OS->SetUnbuffered();
+ OS->SetUseAtomicWrites(true);
+ OutputFile = OS;
+ OwnsOutputFile = true;
+ }
+ }
+
+ PP.addPPCallbacks(new HeaderIncludesCallback(&PP, ShowAllHeaders,
+ OutputFile, OwnsOutputFile));
+}
+
+void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
+ FileChangeReason Reason,
+ SrcMgr::CharacteristicKind NewFileType) {
+ // Unless we are exiting a #include, make sure to skip ahead to the line the
+ // #include directive was at.
+ PresumedLoc UserLoc = SM.getPresumedLoc(Loc);
+ if (UserLoc.isInvalid())
+ return;
+
+ // Adjust the current include depth.
+ if (Reason == PPCallbacks::EnterFile) {
+ ++CurrentIncludeDepth;
+ } else {
+ if (CurrentIncludeDepth)
+ --CurrentIncludeDepth;
+
+ // We track when we are done with the predefines by watching for the first
+ // place where we drop back to a nesting depth of 0.
+ if (CurrentIncludeDepth == 0 && !HasProcessedPredefines)
+ HasProcessedPredefines = true;
+ }
+
+ // Show the header if we are (a) past the predefines, or (b) showing all
+ // headers and in the predefines at a depth past the initial file and command
+ // line buffers.
+ bool ShowHeader = (HasProcessedPredefines ||
+ (ShowAllHeaders && CurrentIncludeDepth > 2));
+
+ // Dump the header include information we are past the predefines buffer or
+ // are showing all headers.
+ if (ShowHeader && Reason == PPCallbacks::EnterFile) {
+ // Write to a temporary string to avoid unnecessary flushing on errs().
+ llvm::SmallString<512> Filename(UserLoc.getFilename());
+ Lexer::Stringify(Filename);
+
+ llvm::SmallString<256> Msg;
+ for (unsigned i = 0; i != CurrentIncludeDepth; ++i)
+ Msg += '.';
+ Msg += ' ';
+ Msg += Filename;
+ Msg += '\n';
+
+ OutputFile->write(Msg.data(), Msg.size());
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
new file mode 100644
index 0000000..69199e2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -0,0 +1,994 @@
+//===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the InitHeaderSearch class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef HAVE_CLANG_CONFIG_H
+# include "clang/Config/config.h"
+#endif
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Config/config.h"
+#ifdef _MSC_VER
+ #define WIN32_LEAN_AND_MEAN 1
+ #include <windows.h>
+#endif
+#ifndef CLANG_PREFIX
+#define CLANG_PREFIX
+#endif
+using namespace clang;
+using namespace clang::frontend;
+
+namespace {
+
+/// InitHeaderSearch - This class makes it easier to set the search paths of
+/// a HeaderSearch object. InitHeaderSearch stores several search path lists
+/// internally, which can be sent to a HeaderSearch object in one swoop.
+class InitHeaderSearch {
+ std::vector<DirectoryLookup> IncludeGroup[4];
+ HeaderSearch& Headers;
+ bool Verbose;
+ std::string IncludeSysroot;
+ bool IsNotEmptyOrRoot;
+
+public:
+
+ InitHeaderSearch(HeaderSearch &HS, bool verbose, llvm::StringRef sysroot)
+ : Headers(HS), Verbose(verbose), IncludeSysroot(sysroot),
+ IsNotEmptyOrRoot(!(sysroot.empty() || sysroot == "/")) {
+ }
+
+ /// AddPath - Add the specified path to the specified group list.
+ void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
+ bool isCXXAware, bool isUserSupplied,
+ bool isFramework, bool IgnoreSysRoot = false);
+
+ /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
+ /// libstdc++.
+ void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef ArchDir,
+ llvm::StringRef Dir32,
+ llvm::StringRef Dir64,
+ const llvm::Triple &triple);
+
+ /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW
+ /// libstdc++.
+ void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef Arch,
+ llvm::StringRef Version);
+
+ /// AddDelimitedPaths - Add a list of paths delimited by the system PATH
+ /// separator. The processing follows that of the CPATH variable for gcc.
+ void AddDelimitedPaths(llvm::StringRef String);
+
+ // AddDefaultCIncludePaths - Add paths that should always be searched.
+ void AddDefaultCIncludePaths(const llvm::Triple &triple,
+ const HeaderSearchOptions &HSOpts);
+
+ // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
+ // compiling c++.
+ void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+ /// AddDefaultSystemIncludePaths - Adds the default system include paths so
+ /// that e.g. stdio.h is found.
+ void AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple,
+ const HeaderSearchOptions &HSOpts);
+
+ /// Realize - Merges all search path lists into one list and send it to
+ /// HeaderSearch.
+ void Realize();
+};
+
+}
+
+void InitHeaderSearch::AddPath(const llvm::Twine &Path,
+ IncludeDirGroup Group, bool isCXXAware,
+ bool isUserSupplied, bool isFramework,
+ bool IgnoreSysRoot) {
+ assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
+ FileManager &FM = Headers.getFileMgr();
+
+ // Compute the actual path, taking into consideration -isysroot.
+ llvm::SmallString<256> MappedPathStorage;
+ llvm::StringRef MappedPathStr = Path.toStringRef(MappedPathStorage);
+
+ // Handle isysroot.
+ if (Group == System && !IgnoreSysRoot &&
+ llvm::sys::path::is_absolute(MappedPathStr) &&
+ IsNotEmptyOrRoot) {
+ MappedPathStorage.clear();
+ MappedPathStr =
+ (IncludeSysroot + Path).toStringRef(MappedPathStorage);
+ }
+
+ // Compute the DirectoryLookup type.
+ SrcMgr::CharacteristicKind Type;
+ if (Group == Quoted || Group == Angled)
+ Type = SrcMgr::C_User;
+ else if (isCXXAware)
+ Type = SrcMgr::C_System;
+ else
+ Type = SrcMgr::C_ExternCSystem;
+
+
+ // If the directory exists, add it.
+ if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
+ IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
+ isFramework));
+ return;
+ }
+
+ // Check to see if this is an apple-style headermap (which are not allowed to
+ // be frameworks).
+ if (!isFramework) {
+ if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
+ if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
+ // It is a headermap, add it to the search path.
+ IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
+ return;
+ }
+ }
+ }
+
+ if (Verbose)
+ llvm::errs() << "ignoring nonexistent directory \""
+ << MappedPathStr << "\"\n";
+}
+
+
+void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
+ if (at.empty()) // Empty string should not add '.' path.
+ return;
+
+ llvm::StringRef::size_type delim;
+ while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
+ if (delim == 0)
+ AddPath(".", Angled, false, true, false);
+ else
+ AddPath(at.substr(0, delim), Angled, false, true, false);
+ at = at.substr(delim + 1);
+ }
+
+ if (at.empty())
+ AddPath(".", Angled, false, true, false);
+ else
+ AddPath(at, Angled, false, true, false);
+}
+
+void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef ArchDir,
+ llvm::StringRef Dir32,
+ llvm::StringRef Dir64,
+ const llvm::Triple &triple) {
+ // Add the base dir
+ AddPath(Base, System, true, false, false);
+
+ // Add the multilib dirs
+ llvm::Triple::ArchType arch = triple.getArch();
+ bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
+ if (is64bit)
+ AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
+ else
+ AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
+
+ // Add the backward dir
+ AddPath(Base + "/backward", System, true, false, false);
+}
+
+void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef Arch,
+ llvm::StringRef Version) {
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
+ System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
+ System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
+ System, true, false, false);
+}
+
+ // FIXME: This probably should goto to some platform utils place.
+#ifdef _MSC_VER
+
+ // Read registry string.
+ // This also supports a means to look for high-versioned keys by use
+ // of a $VERSION placeholder in the key path.
+ // $VERSION in the key path is a placeholder for the version number,
+ // causing the highest value path to be searched for and used.
+ // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
+ // There can be additional characters in the component. Only the numberic
+ // characters are compared.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+ char *value, size_t maxLength) {
+ HKEY hRootKey = NULL;
+ HKEY hKey = NULL;
+ const char* subKey = NULL;
+ DWORD valueType;
+ DWORD valueSize = maxLength - 1;
+ long lResult;
+ bool returnValue = false;
+ if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
+ hRootKey = HKEY_CLASSES_ROOT;
+ subKey = keyPath + 18;
+ }
+ else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
+ hRootKey = HKEY_USERS;
+ subKey = keyPath + 11;
+ }
+ else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
+ hRootKey = HKEY_LOCAL_MACHINE;
+ subKey = keyPath + 19;
+ }
+ else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
+ hRootKey = HKEY_CURRENT_USER;
+ subKey = keyPath + 18;
+ }
+ else
+ return(false);
+ const char *placeHolder = strstr(subKey, "$VERSION");
+ char bestName[256];
+ bestName[0] = '\0';
+ // If we have a $VERSION placeholder, do the highest-version search.
+ if (placeHolder) {
+ const char *keyEnd = placeHolder - 1;
+ const char *nextKey = placeHolder;
+ // Find end of previous key.
+ while ((keyEnd > subKey) && (*keyEnd != '\\'))
+ keyEnd--;
+ // Find end of key containing $VERSION.
+ while (*nextKey && (*nextKey != '\\'))
+ nextKey++;
+ size_t partialKeyLength = keyEnd - subKey;
+ char partialKey[256];
+ if (partialKeyLength > sizeof(partialKey))
+ partialKeyLength = sizeof(partialKey);
+ strncpy(partialKey, subKey, partialKeyLength);
+ partialKey[partialKeyLength] = '\0';
+ HKEY hTopKey = NULL;
+ lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
+ if (lResult == ERROR_SUCCESS) {
+ char keyName[256];
+ int bestIndex = -1;
+ double bestValue = 0.0;
+ DWORD index, size = sizeof(keyName) - 1;
+ for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
+ NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
+ const char *sp = keyName;
+ while (*sp && !isdigit(*sp))
+ sp++;
+ if (!*sp)
+ continue;
+ const char *ep = sp + 1;
+ while (*ep && (isdigit(*ep) || (*ep == '.')))
+ ep++;
+ char numBuf[32];
+ strncpy(numBuf, sp, sizeof(numBuf) - 1);
+ numBuf[sizeof(numBuf) - 1] = '\0';
+ double value = strtod(numBuf, NULL);
+ if (value > bestValue) {
+ bestIndex = (int)index;
+ bestValue = value;
+ strcpy(bestName, keyName);
+ }
+ size = sizeof(keyName) - 1;
+ }
+ // If we found the highest versioned key, open the key and get the value.
+ if (bestIndex != -1) {
+ // Append rest of key.
+ strncat(bestName, nextKey, sizeof(bestName) - 1);
+ bestName[sizeof(bestName) - 1] = '\0';
+ // Open the chosen key path remainder.
+ lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
+ if (lResult == ERROR_SUCCESS) {
+ lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+ (LPBYTE)value, &valueSize);
+ if (lResult == ERROR_SUCCESS)
+ returnValue = true;
+ RegCloseKey(hKey);
+ }
+ }
+ RegCloseKey(hTopKey);
+ }
+ }
+ else {
+ lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
+ if (lResult == ERROR_SUCCESS) {
+ lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+ (LPBYTE)value, &valueSize);
+ if (lResult == ERROR_SUCCESS)
+ returnValue = true;
+ RegCloseKey(hKey);
+ }
+ }
+ return(returnValue);
+}
+#else // _MSC_VER
+ // Read registry string.
+static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
+ return(false);
+}
+#endif // _MSC_VER
+
+ // Get Visual Studio installation directory.
+static bool getVisualStudioDir(std::string &path) {
+ // First check the environment variables that vsvars32.bat sets.
+ const char* vcinstalldir = getenv("VCINSTALLDIR");
+ if(vcinstalldir) {
+ char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
+ if (p)
+ *p = '\0';
+ path = vcinstalldir;
+ return(true);
+ }
+
+ char vsIDEInstallDir[256];
+ char vsExpressIDEInstallDir[256];
+ // Then try the windows registry.
+ bool hasVCDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
+ "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
+ bool hasVCExpressDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
+ "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
+ // If we have both vc80 and vc90, pick version we were compiled with.
+ if (hasVCDir && vsIDEInstallDir[0]) {
+ char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
+ if (p)
+ *p = '\0';
+ path = vsIDEInstallDir;
+ return(true);
+ }
+ else if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
+ char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
+ if (p)
+ *p = '\0';
+ path = vsExpressIDEInstallDir;
+ return(true);
+ }
+ else {
+ // Try the environment.
+ const char* vs100comntools = getenv("VS100COMNTOOLS");
+ const char* vs90comntools = getenv("VS90COMNTOOLS");
+ const char* vs80comntools = getenv("VS80COMNTOOLS");
+ const char* vscomntools = NULL;
+
+ // Try to find the version that we were compiled with
+ if(false) {}
+ #if (_MSC_VER >= 1600) // VC100
+ else if(vs100comntools) {
+ vscomntools = vs100comntools;
+ }
+ #elif (_MSC_VER == 1500) // VC80
+ else if(vs90comntools) {
+ vscomntools = vs90comntools;
+ }
+ #elif (_MSC_VER == 1400) // VC80
+ else if(vs80comntools) {
+ vscomntools = vs80comntools;
+ }
+ #endif
+ // Otherwise find any version we can
+ else if (vs100comntools)
+ vscomntools = vs100comntools;
+ else if (vs90comntools)
+ vscomntools = vs90comntools;
+ else if (vs80comntools)
+ vscomntools = vs80comntools;
+
+ if (vscomntools && *vscomntools) {
+ char *p = const_cast<char *>(strstr(vscomntools, "\\Common7\\Tools"));
+ if (p)
+ *p = '\0';
+ path = vscomntools;
+ return(true);
+ }
+ else
+ return(false);
+ }
+ return(false);
+}
+
+ // Get Windows SDK installation directory.
+static bool getWindowsSDKDir(std::string &path) {
+ char windowsSDKInstallDir[256];
+ // Try the Windows registry.
+ bool hasSDKDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
+ "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1);
+ // If we have both vc80 and vc90, pick version we were compiled with.
+ if (hasSDKDir && windowsSDKInstallDir[0]) {
+ path = windowsSDKInstallDir;
+ return(true);
+ }
+ return(false);
+}
+
+void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
+ const HeaderSearchOptions &HSOpts) {
+ llvm::Triple::OSType os = triple.getOS();
+
+ switch (os) {
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ break;
+ default:
+ // FIXME: temporary hack: hard-coded paths.
+ AddPath("/usr/local/include", System, true, false, false);
+ break;
+ }
+
+ // Builtin includes use #include_next directives and should be positioned
+ // just prior C include dirs.
+ if (HSOpts.UseBuiltinIncludes) {
+ // Ignore the sys root, we *always* look for clang headers relative to
+ // supplied path.
+ llvm::sys::Path P(HSOpts.ResourceDir);
+ P.appendComponent("include");
+ AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
+ }
+
+ // Add dirs specified via 'configure --with-c-include-dirs'.
+ llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ llvm::SmallVector<llvm::StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
+ i != dirs.end();
+ ++i)
+ AddPath(*i, System, false, false, false);
+ return;
+ }
+
+ switch (os) {
+ case llvm::Triple::Win32: {
+ std::string VSDir;
+ std::string WindowsSDKDir;
+ if (getVisualStudioDir(VSDir)) {
+ AddPath(VSDir + "\\VC\\include", System, false, false, false);
+ if (getWindowsSDKDir(WindowsSDKDir))
+ AddPath(WindowsSDKDir + "\\include", System, false, false, false);
+ else
+ AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
+ System, false, false, false);
+ } else {
+ // Default install paths.
+ AddPath("C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
+ System, false, false, false);
+ AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
+ System, false, false, false);
+ AddPath(
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
+ System, false, false, false);
+ AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include",
+ System, false, false, false);
+ AddPath(
+ "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include",
+ System, false, false, false);
+ }
+ break;
+ }
+ case llvm::Triple::Haiku:
+ AddPath("/boot/common/include", System, true, false, false);
+ AddPath("/boot/develop/headers/os", System, true, false, false);
+ AddPath("/boot/develop/headers/os/app", System, true, false, false);
+ AddPath("/boot/develop/headers/os/arch", System, true, false, false);
+ AddPath("/boot/develop/headers/os/device", System, true, false, false);
+ AddPath("/boot/develop/headers/os/drivers", System, true, false, false);
+ AddPath("/boot/develop/headers/os/game", System, true, false, false);
+ AddPath("/boot/develop/headers/os/interface", System, true, false, false);
+ AddPath("/boot/develop/headers/os/kernel", System, true, false, false);
+ AddPath("/boot/develop/headers/os/locale", System, true, false, false);
+ AddPath("/boot/develop/headers/os/mail", System, true, false, false);
+ AddPath("/boot/develop/headers/os/media", System, true, false, false);
+ AddPath("/boot/develop/headers/os/midi", System, true, false, false);
+ AddPath("/boot/develop/headers/os/midi2", System, true, false, false);
+ AddPath("/boot/develop/headers/os/net", System, true, false, false);
+ AddPath("/boot/develop/headers/os/storage", System, true, false, false);
+ AddPath("/boot/develop/headers/os/support", System, true, false, false);
+ AddPath("/boot/develop/headers/os/translation",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/add-ons/graphics",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/add-ons/input_server",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/add-ons/screen_saver",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/add-ons/tracker",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/be_apps/Deskbar",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/be_apps/NetPositive",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/os/be_apps/Tracker",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/cpp", System, true, false, false);
+ AddPath("/boot/develop/headers/cpp/i586-pc-haiku",
+ System, true, false, false);
+ AddPath("/boot/develop/headers/3rdparty", System, true, false, false);
+ AddPath("/boot/develop/headers/bsd", System, true, false, false);
+ AddPath("/boot/develop/headers/glibc", System, true, false, false);
+ AddPath("/boot/develop/headers/posix", System, true, false, false);
+ AddPath("/boot/develop/headers", System, true, false, false);
+ break;
+ case llvm::Triple::Cygwin:
+ AddPath("/usr/include/w32api", System, true, false, false);
+ break;
+ case llvm::Triple::MinGW32:
+ AddPath("c:/mingw/include", System, true, false, false);
+ break;
+ case llvm::Triple::FreeBSD:
+ AddPath(CLANG_PREFIX "/usr/include/clang/" CLANG_VERSION_STRING,
+ System, false, false, false);
+ break;
+ default:
+ break;
+ }
+
+ AddPath(CLANG_PREFIX "/usr/include", System, false, false, false);
+}
+
+void InitHeaderSearch::
+AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
+ llvm::Triple::OSType os = triple.getOS();
+ llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
+ if (CxxIncludeRoot != "") {
+ llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
+ if (CxxIncludeArch == "")
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
+ triple);
+ else
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR,
+ triple);
+ return;
+ }
+ // FIXME: temporary hack: hard-coded paths.
+ switch (os) {
+ case llvm::Triple::Cygwin:
+ // Cygwin-1.7
+ AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4");
+ // g++-4 / Cygwin-1.5
+ AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2");
+ // FIXME: Do we support g++-3.4.4?
+ AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4");
+ break;
+ case llvm::Triple::MinGW32:
+ // mingw-w64-20110207
+ AddPath("c:/MinGW/include/c++/4.5.3", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/backward", System, true, false, false);
+ // mingw-w64-20101129
+ AddPath("c:/MinGW/include/c++/4.5.2", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/backward", System, true, false, false);
+ // Try gcc 4.5.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
+ // Try gcc 4.4.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
+ // Try gcc 4.3.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0");
+ break;
+ case llvm::Triple::Darwin:
+ switch (triple.getArch()) {
+ default: break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "powerpc-apple-darwin10", "", "ppc64",
+ triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+ "powerpc-apple-darwin10", "", "ppc64",
+ triple);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "i686-apple-darwin10", "", "x86_64", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
+ "i686-apple-darwin8", "", "", triple);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "arm-apple-darwin10", "v7", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
+ "arm-apple-darwin10", "v6", "", triple);
+ break;
+ }
+ break;
+ case llvm::Triple::DragonFly:
+ AddPath("/usr/include/c++/4.1", System, true, false, false);
+ break;
+ case llvm::Triple::Linux:
+ //===------------------------------------------------------------------===//
+ // Debian based distros.
+ // Note: these distros symlink /usr/include/c++/X.Y.Z -> X.Y
+ //===------------------------------------------------------------------===//
+ // Ubuntu 10.10 "Maverick Meerkat" -- gcc-4.4.5
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "i686-linux-gnu", "", "64", triple);
+ // The rest of 10.10 is the same as previous versions.
+
+ // Ubuntu 10.04 LTS "Lucid Lynx" -- gcc-4.4.3
+ // Ubuntu 9.10 "Karmic Koala" -- gcc-4.4.1
+ // Debian 6.0 "squeeze" -- gcc-4.4.2
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "x86_64-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "i486-linux-gnu", "", "64", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "arm-linux-gnueabi", "", "", triple);
+ // Ubuntu 9.04 "Jaunty Jackalope" -- gcc-4.3.3
+ // Ubuntu 8.10 "Intrepid Ibex" -- gcc-4.3.2
+ // Debian 5.0 "lenny" -- gcc-4.3.2
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "x86_64-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-linux-gnu", "", "64", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "arm-linux-gnueabi", "", "", triple);
+ // Ubuntu 8.04.4 LTS "Hardy Heron" -- gcc-4.2.4
+ // Ubuntu 8.04.[0-3] LTS "Hardy Heron" -- gcc-4.2.3
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
+ "x86_64-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2",
+ "i486-linux-gnu", "", "64", triple);
+ // Ubuntu 7.10 "Gutsy Gibbon" -- gcc-4.1.3
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
+ "x86_64-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1",
+ "i486-linux-gnu", "", "64", triple);
+
+ //===------------------------------------------------------------------===//
+ // Redhat based distros.
+ //===------------------------------------------------------------------===//
+ // Fedora 14
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1",
+ "i686-redhat-linux", "", "", triple);
+ // Fedora 13
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4",
+ "i686-redhat-linux","", "", triple);
+ // Fedora 12
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+ "i686-redhat-linux","", "", triple);
+ // Fedora 12 (pre-FEB-2010)
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "i686-redhat-linux","", "", triple);
+ // Fedora 11
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "i586-redhat-linux","", "", triple);
+ // Fedora 10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
+ "i386-redhat-linux","", "", triple);
+ // Fedora 9
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
+ "x86_64-redhat-linux", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
+ "i386-redhat-linux", "", "", triple);
+ // Fedora 8
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
+ "x86_64-redhat-linux", "", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
+ "i386-redhat-linux", "", "", triple);
+
+ //===------------------------------------------------------------------===//
+
+ // Exherbo (2010-01-25)
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3",
+ "i686-pc-linux-gnu", "", "", triple);
+
+ // openSUSE 11.1 32 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i586-suse-linux", "", "", triple);
+ // openSUSE 11.1 64 bit
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "x86_64-suse-linux", "32", "", triple);
+ // openSUSE 11.2
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "i586-suse-linux", "", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
+ "x86_64-suse-linux", "", "", triple);
+
+ // openSUSE 11.4
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
+ "i586-suse-linux", "", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5",
+ "x86_64-suse-linux", "", "", triple);
+
+ // Arch Linux 2008-06-24
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "i686-pc-linux-gnu", "", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
+ "x86_64-unknown-linux-gnu", "", "", triple);
+ // Gentoo x86 2010.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
+ // Gentoo x86 2009.1 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
+ // Gentoo x86 2009.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
+ // Gentoo x86 2008.0 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
+
+ // Gentoo amd64 gcc 4.4.5
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.5/include/g++-v4",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ // Gentoo amd64 gcc 4.4.4
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ // Gentoo amd64 gcc 4.4.3
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ // Gentoo amd64 gcc 4.3.2
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4",
+ "x86_64-pc-linux-gnu", "", "", triple);
+ // Gentoo amd64 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
+
+ // Gentoo amd64 llvm-gcc trunk
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1",
+ "x86_64-pc-linux-gnu", "", "", triple);
+
+ break;
+ case llvm::Triple::FreeBSD:
+ // FreeBSD 8.0
+ // FreeBSD 7.3
+ AddGnuCPlusPlusIncludePaths(CLANG_PREFIX "/usr/include/c++/4.2",
+ "", "", "", triple);
+ AddGnuCPlusPlusIncludePaths(CLANG_PREFIX "/usr/include/c++/4.2/backward",
+ "", "", "", triple);
+ break;
+ case llvm::Triple::NetBSD:
+ AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple);
+ break;
+ case llvm::Triple::OpenBSD: {
+ std::string t = triple.getTriple();
+ if (t.substr(0, 6) == "x86_64")
+ t.replace(0, 6, "amd64");
+ AddGnuCPlusPlusIncludePaths("/usr/include/g++",
+ t, "", "", triple);
+ break;
+ }
+ case llvm::Triple::Minix:
+ AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
+ "", "", "", triple);
+ break;
+ case llvm::Triple::Solaris:
+ // Solaris - Fall though..
+ case llvm::Triple::AuroraUX:
+ // AuroraUX
+ AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
+ "i386-pc-solaris2.11", "", "", triple);
+ break;
+ default:
+ break;
+ }
+}
+
+void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple,
+ const HeaderSearchOptions &HSOpts) {
+ if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) {
+ if (!HSOpts.CXXSystemIncludes.empty()) {
+ for (unsigned i = 0, e = HSOpts.CXXSystemIncludes.size(); i != e; ++i)
+ AddPath(HSOpts.CXXSystemIncludes[i], System, true, false, false);
+ } else
+ AddDefaultCPlusPlusIncludePaths(triple);
+ }
+
+ AddDefaultCIncludePaths(triple, HSOpts);
+
+ // Add the default framework include paths on Darwin.
+ if (triple.getOS() == llvm::Triple::Darwin) {
+ AddPath("/System/Library/Frameworks", System, true, false, true);
+ AddPath("/Library/Frameworks", System, true, false, true);
+ }
+}
+
+/// RemoveDuplicates - If there are duplicate directory entries in the specified
+/// search list, remove the later (dead) ones.
+static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
+ bool Verbose) {
+ llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
+ llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
+ llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
+ for (unsigned i = 0; i != SearchList.size(); ++i) {
+ unsigned DirToRemove = i;
+
+ const DirectoryLookup &CurEntry = SearchList[i];
+
+ if (CurEntry.isNormalDir()) {
+ // If this isn't the first time we've seen this dir, remove it.
+ if (SeenDirs.insert(CurEntry.getDir()))
+ continue;
+ } else if (CurEntry.isFramework()) {
+ // If this isn't the first time we've seen this framework dir, remove it.
+ if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
+ continue;
+ } else {
+ assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
+ // If this isn't the first time we've seen this headermap, remove it.
+ if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
+ continue;
+ }
+
+ // If we have a normal #include dir/framework/headermap that is shadowed
+ // later in the chain by a system include location, we actually want to
+ // ignore the user's request and drop the user dir... keeping the system
+ // dir. This is weird, but required to emulate GCC's search path correctly.
+ //
+ // Since dupes of system dirs are rare, just rescan to find the original
+ // that we're nuking instead of using a DenseMap.
+ if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
+ // Find the dir that this is the same of.
+ unsigned FirstDir;
+ for (FirstDir = 0; ; ++FirstDir) {
+ assert(FirstDir != i && "Didn't find dupe?");
+
+ const DirectoryLookup &SearchEntry = SearchList[FirstDir];
+
+ // If these are different lookup types, then they can't be the dupe.
+ if (SearchEntry.getLookupType() != CurEntry.getLookupType())
+ continue;
+
+ bool isSame;
+ if (CurEntry.isNormalDir())
+ isSame = SearchEntry.getDir() == CurEntry.getDir();
+ else if (CurEntry.isFramework())
+ isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir();
+ else {
+ assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
+ isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap();
+ }
+
+ if (isSame)
+ break;
+ }
+
+ // If the first dir in the search path is a non-system dir, zap it
+ // instead of the system one.
+ if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
+ DirToRemove = FirstDir;
+ }
+
+ if (Verbose) {
+ llvm::errs() << "ignoring duplicate directory \""
+ << CurEntry.getName() << "\"\n";
+ if (DirToRemove != i)
+ llvm::errs() << " as it is a non-system directory that duplicates "
+ << "a system directory\n";
+ }
+
+ // This is reached if the current entry is a duplicate. Remove the
+ // DirToRemove (usually the current dir).
+ SearchList.erase(SearchList.begin()+DirToRemove);
+ --i;
+ }
+}
+
+
+void InitHeaderSearch::Realize() {
+ // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
+ std::vector<DirectoryLookup> SearchList;
+ SearchList = IncludeGroup[Angled];
+ SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
+ IncludeGroup[System].end());
+ SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
+ IncludeGroup[After].end());
+ RemoveDuplicates(SearchList, Verbose);
+ RemoveDuplicates(IncludeGroup[Quoted], Verbose);
+
+ // Prepend QUOTED list on the search list.
+ SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
+ IncludeGroup[Quoted].end());
+
+
+ bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
+ Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
+ DontSearchCurDir);
+
+ // If verbose, print the list of directories that will be searched.
+ if (Verbose) {
+ llvm::errs() << "#include \"...\" search starts here:\n";
+ unsigned QuotedIdx = IncludeGroup[Quoted].size();
+ for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
+ if (i == QuotedIdx)
+ llvm::errs() << "#include <...> search starts here:\n";
+ const char *Name = SearchList[i].getName();
+ const char *Suffix;
+ if (SearchList[i].isNormalDir())
+ Suffix = "";
+ else if (SearchList[i].isFramework())
+ Suffix = " (framework directory)";
+ else {
+ assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
+ Suffix = " (headermap)";
+ }
+ llvm::errs() << " " << Name << Suffix << "\n";
+ }
+ llvm::errs() << "End of search list.\n";
+ }
+}
+
+void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &Triple) {
+ InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+
+ // Add the user defined entries.
+ for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
+ Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
+ !E.IsSysRootRelative);
+ }
+
+ // Add entries from CPATH and friends.
+ Init.AddDelimitedPaths(HSOpts.EnvIncPath);
+ if (Lang.CPlusPlus && Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
+ else if (Lang.CPlusPlus)
+ Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
+ else if (Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
+ else
+ Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
+
+ if (HSOpts.UseStandardIncludes)
+ Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);
+
+ Init.Realize();
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
new file mode 100644
index 0000000..d0111a5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -0,0 +1,619 @@
+//===--- InitPreprocessor.cpp - PP initialization code. ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the clang::InitializePreprocessor function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/PreprocessorOptions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+using namespace clang;
+
+// Append a #define line to Buf for Macro. Macro should be of the form XXX,
+// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
+// "#define XXX Y z W". To get a #define with no value, use "XXX=".
+static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro,
+ Diagnostic &Diags) {
+ std::pair<llvm::StringRef, llvm::StringRef> MacroPair = Macro.split('=');
+ llvm::StringRef MacroName = MacroPair.first;
+ llvm::StringRef MacroBody = MacroPair.second;
+ if (MacroName.size() != Macro.size()) {
+ // Per GCC -D semantics, the macro ends at \n if it exists.
+ llvm::StringRef::size_type End = MacroBody.find_first_of("\n\r");
+ if (End != llvm::StringRef::npos)
+ Diags.Report(diag::warn_fe_macro_contains_embedded_newline)
+ << MacroName;
+ Builder.defineMacro(MacroName, MacroBody.substr(0, End));
+ } else {
+ // Push "macroname 1".
+ Builder.defineMacro(Macro);
+ }
+}
+
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
+ // Implicit include paths should be resolved relative to the current
+ // working directory first, and then use the regular header search
+ // mechanism. The proper way to handle this is to have the
+ // predefines buffer located at the current working directory, but
+ // it has not file entry. For now, workaround this by using an
+ // absolute path if we find the file here, and otherwise letting
+ // header search handle it.
+ llvm::SmallString<128> Path(File);
+ llvm::sys::fs::make_absolute(Path);
+ bool exists;
+ if (llvm::sys::fs::exists(Path.str(), exists) || !exists)
+ Path = File;
+
+ return Lexer::Stringify(Path.str());
+}
+
+/// AddImplicitInclude - Add an implicit #include of the specified file to the
+/// predefines buffer.
+static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) {
+ Builder.append("#include \"" +
+ llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+}
+
+static void AddImplicitIncludeMacros(MacroBuilder &Builder,
+ llvm::StringRef File) {
+ Builder.append("#__include_macros \"" +
+ llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+ // Marker token to stop the __include_macros fetch loop.
+ Builder.append("##"); // ##?
+}
+
+/// AddImplicitIncludePTH - Add an implicit #include using the original file
+/// used to generate a PTH cache.
+static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
+ llvm::StringRef ImplicitIncludePTH) {
+ PTHManager *P = PP.getPTHManager();
+ // Null check 'P' in the corner case where it couldn't be created.
+ const char *OriginalFile = P ? P->getOriginalSourceFile() : 0;
+
+ if (!OriginalFile) {
+ PP.getDiagnostics().Report(diag::err_fe_pth_file_has_no_source_header)
+ << ImplicitIncludePTH;
+ return;
+ }
+
+ AddImplicitInclude(Builder, OriginalFile);
+}
+
+/// PickFP - This is used to pick a value based on the FP semantics of the
+/// specified FP model.
+template <typename T>
+static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
+ T IEEEDoubleVal, T X87DoubleExtendedVal, T PPCDoubleDoubleVal,
+ T IEEEQuadVal) {
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle)
+ return IEEESingleVal;
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble)
+ return IEEEDoubleVal;
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::x87DoubleExtended)
+ return X87DoubleExtendedVal;
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::PPCDoubleDouble)
+ return PPCDoubleDoubleVal;
+ assert(Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEquad);
+ return IEEEQuadVal;
+}
+
+static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
+ const llvm::fltSemantics *Sem) {
+ const char *DenormMin, *Epsilon, *Max, *Min;
+ DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324",
+ "3.64519953188247460253e-4951L",
+ "4.94065645841246544176568792868221e-324L",
+ "6.47517511943802511092443895822764655e-4966L");
+ int Digits = PickFP(Sem, 6, 15, 18, 31, 33);
+ Epsilon = PickFP(Sem, "1.19209290e-7F", "2.2204460492503131e-16",
+ "1.08420217248550443401e-19L",
+ "4.94065645841246544176568792868221e-324L",
+ "1.92592994438723585305597794258492732e-34L");
+ int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113);
+ int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931);
+ int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932);
+ int MinExp = PickFP(Sem, -125, -1021, -16381, -968, -16381);
+ int MaxExp = PickFP(Sem, 128, 1024, 16384, 1024, 16384);
+ Min = PickFP(Sem, "1.17549435e-38F", "2.2250738585072014e-308",
+ "3.36210314311209350626e-4932L",
+ "2.00416836000897277799610805135016e-292L",
+ "3.36210314311209350626267781732175260e-4932L");
+ Max = PickFP(Sem, "3.40282347e+38F", "1.7976931348623157e+308",
+ "1.18973149535723176502e+4932L",
+ "1.79769313486231580793728971405301e+308L",
+ "1.18973149535723176508575932662800702e+4932L");
+
+ llvm::SmallString<32> DefPrefix;
+ DefPrefix = "__";
+ DefPrefix += Prefix;
+ DefPrefix += "_";
+
+ Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin);
+ Builder.defineMacro(DefPrefix + "HAS_DENORM__");
+ Builder.defineMacro(DefPrefix + "DIG__", llvm::Twine(Digits));
+ Builder.defineMacro(DefPrefix + "EPSILON__", llvm::Twine(Epsilon));
+ Builder.defineMacro(DefPrefix + "HAS_INFINITY__");
+ Builder.defineMacro(DefPrefix + "HAS_QUIET_NAN__");
+ Builder.defineMacro(DefPrefix + "MANT_DIG__", llvm::Twine(MantissaDigits));
+
+ Builder.defineMacro(DefPrefix + "MAX_10_EXP__", llvm::Twine(Max10Exp));
+ Builder.defineMacro(DefPrefix + "MAX_EXP__", llvm::Twine(MaxExp));
+ Builder.defineMacro(DefPrefix + "MAX__", llvm::Twine(Max));
+
+ Builder.defineMacro(DefPrefix + "MIN_10_EXP__","("+llvm::Twine(Min10Exp)+")");
+ Builder.defineMacro(DefPrefix + "MIN_EXP__", "("+llvm::Twine(MinExp)+")");
+ Builder.defineMacro(DefPrefix + "MIN__", llvm::Twine(Min));
+}
+
+
+/// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro
+/// named MacroName with the max value for a type with width 'TypeWidth' a
+/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
+static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth,
+ llvm::StringRef ValSuffix, bool isSigned,
+ MacroBuilder& Builder) {
+ long long MaxVal;
+ if (isSigned) {
+ assert(TypeWidth != 1);
+ MaxVal = ~0ULL >> (65-TypeWidth);
+ } else
+ MaxVal = ~0ULL >> (64-TypeWidth);
+
+ Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix);
+}
+
+/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
+/// the width, suffix, and signedness of the given type
+static void DefineTypeSize(llvm::StringRef MacroName, TargetInfo::IntType Ty,
+ const TargetInfo &TI, MacroBuilder &Builder) {
+ DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
+ TI.isTypeSigned(Ty), Builder);
+}
+
+static void DefineType(const llvm::Twine &MacroName, TargetInfo::IntType Ty,
+ MacroBuilder &Builder) {
+ Builder.defineMacro(MacroName, TargetInfo::getTypeName(Ty));
+}
+
+static void DefineTypeWidth(llvm::StringRef MacroName, TargetInfo::IntType Ty,
+ const TargetInfo &TI, MacroBuilder &Builder) {
+ Builder.defineMacro(MacroName, llvm::Twine(TI.getTypeWidth(Ty)));
+}
+
+static void DefineTypeSizeof(llvm::StringRef MacroName, unsigned BitWidth,
+ const TargetInfo &TI, MacroBuilder &Builder) {
+ Builder.defineMacro(MacroName,
+ llvm::Twine(BitWidth / TI.getCharWidth()));
+}
+
+static void DefineExactWidthIntType(TargetInfo::IntType Ty,
+ const TargetInfo &TI, MacroBuilder &Builder) {
+ int TypeWidth = TI.getTypeWidth(Ty);
+
+ // Use the target specified int64 type, when appropriate, so that [u]int64_t
+ // ends up being defined in terms of the correct type.
+ if (TypeWidth == 64)
+ Ty = TI.getInt64Type();
+
+ DefineType("__INT" + llvm::Twine(TypeWidth) + "_TYPE__", Ty, Builder);
+
+ llvm::StringRef ConstSuffix(TargetInfo::getTypeConstantSuffix(Ty));
+ if (!ConstSuffix.empty())
+ Builder.defineMacro("__INT" + llvm::Twine(TypeWidth) + "_C_SUFFIX__",
+ ConstSuffix);
+}
+
+static void InitializePredefinedMacros(const TargetInfo &TI,
+ const LangOptions &LangOpts,
+ const FrontendOptions &FEOpts,
+ MacroBuilder &Builder) {
+ // Compiler version introspection macros.
+ Builder.defineMacro("__llvm__"); // LLVM Backend
+ Builder.defineMacro("__clang__"); // Clang Frontend
+#define TOSTR2(X) #X
+#define TOSTR(X) TOSTR2(X)
+ Builder.defineMacro("__clang_major__", TOSTR(CLANG_VERSION_MAJOR));
+ Builder.defineMacro("__clang_minor__", TOSTR(CLANG_VERSION_MINOR));
+#ifdef CLANG_VERSION_PATCHLEVEL
+ Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL));
+#else
+ Builder.defineMacro("__clang_patchlevel__", "0");
+#endif
+ Builder.defineMacro("__clang_version__",
+ "\"" CLANG_VERSION_STRING " ("
+ + getClangFullRepositoryVersion() + ")\"");
+#undef TOSTR
+#undef TOSTR2
+ // Currently claim to be compatible with GCC 4.2.1-5621.
+ Builder.defineMacro("__GNUC_MINOR__", "2");
+ Builder.defineMacro("__GNUC_PATCHLEVEL__", "1");
+ Builder.defineMacro("__GNUC__", "4");
+ Builder.defineMacro("__GXX_ABI_VERSION", "1002");
+ Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible Clang Compiler\"");
+
+ // Initialize language-specific preprocessor defines.
+
+ // These should all be defined in the preprocessor according to the
+ // current language configuration.
+ if (!LangOpts.Microsoft)
+ Builder.defineMacro("__STDC__");
+ if (LangOpts.AsmPreprocessor)
+ Builder.defineMacro("__ASSEMBLER__");
+
+ if (!LangOpts.CPlusPlus) {
+ if (LangOpts.C99)
+ Builder.defineMacro("__STDC_VERSION__", "199901L");
+ else if (!LangOpts.GNUMode && LangOpts.Digraphs)
+ Builder.defineMacro("__STDC_VERSION__", "199409L");
+ }
+
+ // Standard conforming mode?
+ if (!LangOpts.GNUMode)
+ Builder.defineMacro("__STRICT_ANSI__");
+
+ if (LangOpts.CPlusPlus0x)
+ Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__");
+
+ if (LangOpts.Freestanding)
+ Builder.defineMacro("__STDC_HOSTED__", "0");
+ else
+ Builder.defineMacro("__STDC_HOSTED__");
+
+ if (LangOpts.ObjC1) {
+ Builder.defineMacro("__OBJC__");
+ if (LangOpts.ObjCNonFragileABI) {
+ Builder.defineMacro("__OBJC2__");
+ Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS");
+ }
+
+ if (LangOpts.getGCMode() != LangOptions::NonGC)
+ Builder.defineMacro("__OBJC_GC__");
+
+ if (LangOpts.NeXTRuntime)
+ Builder.defineMacro("__NEXT_RUNTIME__");
+ }
+
+ // darwin_constant_cfstrings controls this. This is also dependent
+ // on other things like the runtime I believe. This is set even for C code.
+ Builder.defineMacro("__CONSTANT_CFSTRINGS__");
+
+ if (LangOpts.ObjC2)
+ Builder.defineMacro("OBJC_NEW_PROPERTIES");
+
+ if (LangOpts.PascalStrings)
+ Builder.defineMacro("__PASCAL_STRINGS__");
+
+ if (LangOpts.Blocks) {
+ Builder.defineMacro("__block", "__attribute__((__blocks__(byref)))");
+ Builder.defineMacro("__BLOCKS__");
+ }
+
+ if (LangOpts.Exceptions)
+ Builder.defineMacro("__EXCEPTIONS");
+ if (LangOpts.RTTI)
+ Builder.defineMacro("__GXX_RTTI");
+ if (LangOpts.SjLjExceptions)
+ Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__");
+
+ if (LangOpts.CPlusPlus) {
+ Builder.defineMacro("__DEPRECATED");
+ Builder.defineMacro("__GNUG__", "4");
+ Builder.defineMacro("__GXX_WEAK__");
+ if (LangOpts.GNUMode)
+ Builder.defineMacro("__cplusplus");
+ else
+ // C++ [cpp.predefined]p1:
+ // The name_ _cplusplusis defined to the value 199711L when compiling a
+ // C++ translation unit.
+ Builder.defineMacro("__cplusplus", "199711L");
+ Builder.defineMacro("__private_extern__", "extern");
+ }
+
+ if (LangOpts.Microsoft) {
+ // Filter out some microsoft extensions when trying to parse in ms-compat
+ // mode.
+ Builder.defineMacro("__int8", "__INT8_TYPE__");
+ Builder.defineMacro("__int16", "__INT16_TYPE__");
+ Builder.defineMacro("__int32", "__INT32_TYPE__");
+ Builder.defineMacro("__int64", "__INT64_TYPE__");
+ // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however
+ // VC++ appears to only like __FUNCTION__.
+ Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__");
+ // Work around some issues with Visual C++ headerws.
+ if (LangOpts.CPlusPlus) {
+ // Since we define wchar_t in C++ mode.
+ Builder.defineMacro("_WCHAR_T_DEFINED");
+ Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED");
+ Builder.append("class type_info;");
+ }
+
+ if (LangOpts.CPlusPlus0x) {
+ Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", "1");
+ }
+ }
+
+ if (LangOpts.Optimize)
+ Builder.defineMacro("__OPTIMIZE__");
+ if (LangOpts.OptimizeSize)
+ Builder.defineMacro("__OPTIMIZE_SIZE__");
+
+ // Initialize target-specific preprocessor defines.
+
+ // Define type sizing macros based on the target properties.
+ assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
+ Builder.defineMacro("__CHAR_BIT__", "8");
+
+ DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Builder);
+ DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder);
+ DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder);
+ DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder);
+ DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder);
+ DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder);
+ DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
+
+ DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_INT__", TI.getIntWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_LONG__", TI.getLongWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_LONG_DOUBLE__",TI.getLongDoubleWidth(),TI,Builder);
+ DefineTypeSizeof("__SIZEOF_LONG_LONG__", TI.getLongLongWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_POINTER__", TI.getPointerWidth(0), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_SHORT__", TI.getShortWidth(), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_PTRDIFF_T__",
+ TI.getTypeWidth(TI.getPtrDiffType(0)), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_SIZE_T__",
+ TI.getTypeWidth(TI.getSizeType()), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_WCHAR_T__",
+ TI.getTypeWidth(TI.getWCharType()), TI, Builder);
+ DefineTypeSizeof("__SIZEOF_WINT_T__",
+ TI.getTypeWidth(TI.getWIntType()), TI, Builder);
+
+ DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder);
+ DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder);
+ DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Builder);
+ DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Builder);
+ DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Builder);
+ DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder);
+ DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Builder);
+ DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder);
+ DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Builder);
+ DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder);
+ DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Builder);
+ DefineType("__WINT_TYPE__", TI.getWIntType(), Builder);
+ DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Builder);
+ DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Builder);
+ DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
+ DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);
+
+ DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat());
+ DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat());
+ DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat());
+
+ // Define a __POINTER_WIDTH__ macro for stdint.h.
+ Builder.defineMacro("__POINTER_WIDTH__",
+ llvm::Twine((int)TI.getPointerWidth(0)));
+
+ if (!LangOpts.CharIsSigned)
+ Builder.defineMacro("__CHAR_UNSIGNED__");
+
+ // Define exact-width integer types for stdint.h
+ Builder.defineMacro("__INT" + llvm::Twine(TI.getCharWidth()) + "_TYPE__",
+ "char");
+
+ if (TI.getShortWidth() > TI.getCharWidth())
+ DefineExactWidthIntType(TargetInfo::SignedShort, TI, Builder);
+
+ if (TI.getIntWidth() > TI.getShortWidth())
+ DefineExactWidthIntType(TargetInfo::SignedInt, TI, Builder);
+
+ if (TI.getLongWidth() > TI.getIntWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLong, TI, Builder);
+
+ if (TI.getLongLongWidth() > TI.getLongWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
+
+ // Add __builtin_va_list typedef.
+ Builder.append(TI.getVAListDeclaration());
+
+ if (const char *Prefix = TI.getUserLabelPrefix())
+ Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix);
+
+ // Build configuration options. FIXME: these should be controlled by
+ // command line options or something.
+ Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
+
+ if (LangOpts.GNUInline)
+ Builder.defineMacro("__GNUC_GNU_INLINE__");
+ else
+ Builder.defineMacro("__GNUC_STDC_INLINE__");
+
+ if (LangOpts.NoInline)
+ Builder.defineMacro("__NO_INLINE__");
+
+ if (unsigned PICLevel = LangOpts.PICLevel) {
+ Builder.defineMacro("__PIC__", llvm::Twine(PICLevel));
+ Builder.defineMacro("__pic__", llvm::Twine(PICLevel));
+ }
+
+ // Macros to control C99 numerics and <float.h>
+ Builder.defineMacro("__FLT_EVAL_METHOD__", "0");
+ Builder.defineMacro("__FLT_RADIX__", "2");
+ int Dig = PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36);
+ Builder.defineMacro("__DECIMAL_DIG__", llvm::Twine(Dig));
+
+ if (LangOpts.getStackProtectorMode() == LangOptions::SSPOn)
+ Builder.defineMacro("__SSP__");
+ else if (LangOpts.getStackProtectorMode() == LangOptions::SSPReq)
+ Builder.defineMacro("__SSP_ALL__", "2");
+
+ if (FEOpts.ProgramAction == frontend::RewriteObjC)
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+
+ // Define a macro that exists only when using the static analyzer.
+ if (FEOpts.ProgramAction == frontend::RunAnalysis)
+ Builder.defineMacro("__clang_analyzer__");
+
+ if (LangOpts.FastRelaxedMath)
+ Builder.defineMacro("__FAST_RELAXED_MATH__");
+
+ // Get other target #defines.
+ TI.getTargetDefines(LangOpts, Builder);
+}
+
+// Initialize the remapping of files to alternative contents, e.g.,
+// those specified through other files.
+static void InitializeFileRemapping(Diagnostic &Diags,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr,
+ const PreprocessorOptions &InitOpts) {
+ // Remap files in the source manager (with buffers).
+ for (PreprocessorOptions::const_remapped_file_buffer_iterator
+ Remap = InitOpts.remapped_file_buffer_begin(),
+ RemapEnd = InitOpts.remapped_file_buffer_end();
+ Remap != RemapEnd;
+ ++Remap) {
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+ Remap->second->getBufferSize(),
+ 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << Remap->first;
+ if (!InitOpts.RetainRemappedFileBuffers)
+ delete Remap->second;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, Remap->second,
+ InitOpts.RetainRemappedFileBuffers);
+ }
+
+ // Remap files in the source manager (with other files).
+ for (PreprocessorOptions::const_remapped_file_iterator
+ Remap = InitOpts.remapped_file_begin(),
+ RemapEnd = InitOpts.remapped_file_end();
+ Remap != RemapEnd;
+ ++Remap) {
+ // Find the file that we're mapping to.
+ const FileEntry *ToFile = FileMgr.getFile(Remap->second);
+ if (!ToFile) {
+ Diags.Report(diag::err_fe_remap_missing_to_file)
+ << Remap->first << Remap->second;
+ continue;
+ }
+
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+ ToFile->getSize(), 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << Remap->first;
+ continue;
+ }
+
+ // Load the contents of the file we're mapping to.
+ std::string ErrorStr;
+ const llvm::MemoryBuffer *Buffer
+ = FileMgr.getBufferForFile(ToFile->getName(), &ErrorStr);
+ if (!Buffer) {
+ Diags.Report(diag::err_fe_error_opening)
+ << Remap->second << ErrorStr;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, Buffer);
+ }
+}
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file. This returns true on error.
+///
+void clang::InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorOptions &InitOpts,
+ const HeaderSearchOptions &HSOpts,
+ const FrontendOptions &FEOpts) {
+ std::string PredefineBuffer;
+ PredefineBuffer.reserve(4080);
+ llvm::raw_string_ostream Predefines(PredefineBuffer);
+ MacroBuilder Builder(Predefines);
+
+ InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
+ PP.getFileManager(), InitOpts);
+
+ // Emit line markers for various builtin sections of the file. We don't do
+ // this in asm preprocessor mode, because "# 4" is not a line marker directive
+ // in this mode.
+ if (!PP.getLangOptions().AsmPreprocessor)
+ Builder.append("# 1 \"<built-in>\" 3");
+
+ // Install things like __POWERPC__, __GNUC__, etc into the macro table.
+ if (InitOpts.UsePredefines)
+ InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
+ FEOpts, Builder);
+
+ // Add on the predefines from the driver. Wrap in a #line directive to report
+ // that they come from the command line.
+ if (!PP.getLangOptions().AsmPreprocessor)
+ Builder.append("# 1 \"<command line>\" 1");
+
+ // Process #define's and #undef's in the order they are given.
+ for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) {
+ if (InitOpts.Macros[i].second) // isUndef
+ Builder.undefineMacro(InitOpts.Macros[i].first);
+ else
+ DefineBuiltinMacro(Builder, InitOpts.Macros[i].first,
+ PP.getDiagnostics());
+ }
+
+ // If -imacros are specified, include them now. These are processed before
+ // any -include directives.
+ for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
+ AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
+
+ // Process -include directives.
+ for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
+ const std::string &Path = InitOpts.Includes[i];
+ if (Path == InitOpts.ImplicitPTHInclude)
+ AddImplicitIncludePTH(Builder, PP, Path);
+ else
+ AddImplicitInclude(Builder, Path);
+ }
+
+ // Exit the command line and go back to <built-in> (2 is LC_LEAVE).
+ if (!PP.getLangOptions().AsmPreprocessor)
+ Builder.append("# 1 \"<built-in>\" 2");
+
+ // Instruct the preprocessor to skip the preamble.
+ PP.setSkipMainFilePreamble(InitOpts.PrecompiledPreambleBytes.first,
+ InitOpts.PrecompiledPreambleBytes.second);
+
+ // Copy PredefinedBuffer into the Preprocessor.
+ PP.setPredefines(Predefines.str());
+
+ // Initialize the header search object.
+ ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
+ PP.getLangOptions(),
+ PP.getTargetInfo().getTriple());
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/LangStandards.cpp b/contrib/llvm/tools/clang/lib/Frontend/LangStandards.cpp
new file mode 100644
index 0000000..af1721d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/LangStandards.cpp
@@ -0,0 +1,44 @@
+//===--- LangStandards.cpp - Language Standard Definitions ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/LangStandard.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+using namespace clang::frontend;
+
+#define LANGSTANDARD(id, name, desc, features) \
+ static const LangStandard Lang_##id = { name, desc, features };
+#include "clang/Frontend/LangStandards.def"
+
+const LangStandard &LangStandard::getLangStandardForKind(Kind K) {
+ switch (K) {
+ default:
+ llvm_unreachable("Invalid language kind!");
+ case lang_unspecified:
+ llvm::report_fatal_error("getLangStandardForKind() on unspecified kind");
+#define LANGSTANDARD(id, name, desc, features) \
+ case lang_##id: return Lang_##id;
+#include "clang/Frontend/LangStandards.def"
+ }
+}
+
+const LangStandard *LangStandard::getLangStandardForName(llvm::StringRef Name) {
+ Kind K = llvm::StringSwitch<Kind>(Name)
+#define LANGSTANDARD(id, name, desc, features) \
+ .Case(name, lang_##id)
+#include "clang/Frontend/LangStandards.def"
+ .Default(lang_unspecified);
+ if (K == lang_unspecified)
+ return 0;
+
+ return &getLangStandardForKind(K);
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
new file mode 100644
index 0000000..3649c3c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -0,0 +1,221 @@
+//===- MultiplexConsumer.cpp - AST Consumer for PCH Generation --*- 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 MultiplexConsumer class. It also declares and defines
+// MultiplexASTDeserializationListener and MultiplexASTMutationListener, which
+// are implementation details of MultiplexConsumer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/MultiplexConsumer.h"
+
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+
+using namespace clang;
+
+namespace clang {
+
+// This ASTDeserializationListener forwards its notifications to a set of
+// child listeners.
+class MultiplexASTDeserializationListener
+ : public ASTDeserializationListener {
+public:
+ // Does NOT take ownership of the elements in L.
+ MultiplexASTDeserializationListener(
+ const std::vector<ASTDeserializationListener*>& L);
+ virtual void ReaderInitialized(ASTReader *Reader);
+ virtual void IdentifierRead(serialization::IdentID ID,
+ IdentifierInfo *II);
+ virtual void TypeRead(serialization::TypeIdx Idx, QualType T);
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D);
+ virtual void SelectorRead(serialization::SelectorID iD, Selector Sel);
+ virtual void MacroDefinitionRead(serialization::MacroID,
+ MacroDefinition *MD);
+private:
+ std::vector<ASTDeserializationListener*> Listeners;
+};
+
+MultiplexASTDeserializationListener::MultiplexASTDeserializationListener(
+ const std::vector<ASTDeserializationListener*>& L)
+ : Listeners(L) {
+}
+
+void MultiplexASTDeserializationListener::ReaderInitialized(
+ ASTReader *Reader) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->ReaderInitialized(Reader);
+}
+
+void MultiplexASTDeserializationListener::IdentifierRead(
+ serialization::IdentID ID, IdentifierInfo *II) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->IdentifierRead(ID, II);
+}
+
+void MultiplexASTDeserializationListener::TypeRead(
+ serialization::TypeIdx Idx, QualType T) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->TypeRead(Idx, T);
+}
+
+void MultiplexASTDeserializationListener::DeclRead(
+ serialization::DeclID ID, const Decl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->DeclRead(ID, D);
+}
+
+void MultiplexASTDeserializationListener::SelectorRead(
+ serialization::SelectorID ID, Selector Sel) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->SelectorRead(ID, Sel);
+}
+
+void MultiplexASTDeserializationListener::MacroDefinitionRead(
+ serialization::MacroID ID, MacroDefinition *MD) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->MacroDefinitionRead(ID, MD);
+}
+
+// This ASTMutationListener forwards its notifications to a set of
+// child listeners.
+class MultiplexASTMutationListener : public ASTMutationListener {
+public:
+ // Does NOT take ownership of the elements in L.
+ MultiplexASTMutationListener(const std::vector<ASTMutationListener*>& L);
+ virtual void CompletedTagDefinition(const TagDecl *D);
+ virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D);
+ virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
+ virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D);
+private:
+ std::vector<ASTMutationListener*> Listeners;
+};
+
+MultiplexASTMutationListener::MultiplexASTMutationListener(
+ const std::vector<ASTMutationListener*>& L)
+ : Listeners(L) {
+}
+
+void MultiplexASTMutationListener::CompletedTagDefinition(const TagDecl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->CompletedTagDefinition(D);
+}
+
+void MultiplexASTMutationListener::AddedVisibleDecl(
+ const DeclContext *DC, const Decl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->AddedVisibleDecl(DC, D);
+}
+
+void MultiplexASTMutationListener::AddedCXXImplicitMember(
+ const CXXRecordDecl *RD, const Decl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->AddedCXXImplicitMember(RD, D);
+}
+void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
+ const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
+}
+
+} // end namespace clang
+
+
+MultiplexConsumer::MultiplexConsumer(const std::vector<ASTConsumer*>& C)
+ : Consumers(C), MutationListener(0), DeserializationListener(0) {
+ // Collect the mutation listeners and deserialization listeners of all
+ // children, and create a multiplex listener each if so.
+ std::vector<ASTMutationListener*> mutationListeners;
+ std::vector<ASTDeserializationListener*> serializationListeners;
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i) {
+ ASTMutationListener* mutationListener =
+ Consumers[i]->GetASTMutationListener();
+ if (mutationListener)
+ mutationListeners.push_back(mutationListener);
+ ASTDeserializationListener* serializationListener =
+ Consumers[i]->GetASTDeserializationListener();
+ if (serializationListener)
+ serializationListeners.push_back(serializationListener);
+ }
+ if (mutationListeners.size()) {
+ MutationListener.reset(new MultiplexASTMutationListener(mutationListeners));
+ }
+ if (serializationListeners.size()) {
+ DeserializationListener.reset(
+ new MultiplexASTDeserializationListener(serializationListeners));
+ }
+}
+
+MultiplexConsumer::~MultiplexConsumer() {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ delete Consumers[i];
+}
+
+void MultiplexConsumer::Initialize(ASTContext &Context) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->Initialize(Context);
+}
+
+void MultiplexConsumer::HandleTopLevelDecl(DeclGroupRef D) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleTopLevelDecl(D);
+}
+
+void MultiplexConsumer::HandleInterestingDecl(DeclGroupRef D) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleInterestingDecl(D);
+}
+
+void MultiplexConsumer::HandleTranslationUnit(ASTContext &Ctx) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleTranslationUnit(Ctx);
+}
+
+void MultiplexConsumer::HandleTagDeclDefinition(TagDecl *D) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleTagDeclDefinition(D);
+}
+
+void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->CompleteTentativeDefinition(D);
+}
+
+void MultiplexConsumer::HandleVTable(
+ CXXRecordDecl *RD, bool DefinitionRequired) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->HandleVTable(RD, DefinitionRequired);
+}
+
+ASTMutationListener *MultiplexConsumer::GetASTMutationListener() {
+ return MutationListener.get();
+}
+
+ASTDeserializationListener *MultiplexConsumer::GetASTDeserializationListener() {
+ return DeserializationListener.get();
+}
+
+void MultiplexConsumer::PrintStats() {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ Consumers[i]->PrintStats();
+}
+
+void MultiplexConsumer::InitializeSema(Sema &S) {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumers[i]))
+ SC->InitializeSema(S);
+}
+
+void MultiplexConsumer::ForgetSema() {
+ for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumers[i]))
+ SC->ForgetSema();
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
new file mode 100644
index 0000000..922d743
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -0,0 +1,584 @@
+//===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code simply runs the preprocessor on the input file and prints out the
+// result. This is the traditional behavior of the -E option.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/TokenConcatenation.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+using namespace clang;
+
+/// PrintMacroDefinition - Print a macro definition in a form that will be
+/// properly accepted back as a definition.
+static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
+ Preprocessor &PP, llvm::raw_ostream &OS) {
+ OS << "#define " << II.getName();
+
+ if (MI.isFunctionLike()) {
+ OS << '(';
+ if (!MI.arg_empty()) {
+ MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
+ for (; AI+1 != E; ++AI) {
+ OS << (*AI)->getName();
+ OS << ',';
+ }
+
+ // Last argument.
+ if ((*AI)->getName() == "__VA_ARGS__")
+ OS << "...";
+ else
+ OS << (*AI)->getName();
+ }
+
+ if (MI.isGNUVarargs())
+ OS << "..."; // #define foo(x...)
+
+ OS << ')';
+ }
+
+ // GCC always emits a space, even if the macro body is empty. However, do not
+ // want to emit two spaces if the first token has a leading space.
+ if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
+ OS << ' ';
+
+ llvm::SmallString<128> SpellingBuffer;
+ for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
+ I != E; ++I) {
+ if (I->hasLeadingSpace())
+ OS << ' ';
+
+ OS << PP.getSpelling(*I, SpellingBuffer);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessed token printer
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PrintPPOutputPPCallbacks : public PPCallbacks {
+ Preprocessor &PP;
+ SourceManager &SM;
+ TokenConcatenation ConcatInfo;
+public:
+ llvm::raw_ostream &OS;
+private:
+ unsigned CurLine;
+
+ bool EmittedTokensOnThisLine;
+ bool EmittedMacroOnThisLine;
+ SrcMgr::CharacteristicKind FileType;
+ llvm::SmallString<512> CurFilename;
+ bool Initialized;
+ bool DisableLineMarkers;
+ bool DumpDefines;
+ bool UseLineDirective;
+public:
+ PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
+ bool lineMarkers, bool defines)
+ : PP(pp), SM(PP.getSourceManager()),
+ ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
+ DumpDefines(defines) {
+ CurLine = 0;
+ CurFilename += "<uninit>";
+ EmittedTokensOnThisLine = false;
+ EmittedMacroOnThisLine = false;
+ FileType = SrcMgr::C_User;
+ Initialized = false;
+
+ // If we're in microsoft mode, use normal #line instead of line markers.
+ UseLineDirective = PP.getLangOptions().Microsoft;
+ }
+
+ void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
+ bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
+
+ bool StartNewLineIfNeeded();
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType);
+ virtual void Ident(SourceLocation Loc, const std::string &str);
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str);
+ virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str);
+
+ bool HandleFirstTokOnLine(Token &Tok);
+ bool MoveToLine(SourceLocation Loc) {
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ if (PLoc.isInvalid())
+ return false;
+ return MoveToLine(PLoc.getLine());
+ }
+ bool MoveToLine(unsigned LineNo);
+
+ bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
+ const Token &Tok) {
+ return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
+ }
+ void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+ bool LineMarkersAreDisabled() const { return DisableLineMarkers; }
+ void HandleNewlinesInToken(const char *TokStr, unsigned Len);
+
+ /// MacroDefined - This hook is called whenever a macro definition is seen.
+ void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI);
+
+ /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI);
+};
+} // end anonymous namespace
+
+void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
+ const char *Extra,
+ unsigned ExtraLen) {
+ if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
+ OS << '\n';
+ EmittedTokensOnThisLine = false;
+ EmittedMacroOnThisLine = false;
+ }
+
+ // Emit #line directives or GNU line markers depending on what mode we're in.
+ if (UseLineDirective) {
+ OS << "#line" << ' ' << LineNo << ' ' << '"';
+ OS.write(CurFilename.data(), CurFilename.size());
+ OS << '"';
+ } else {
+ OS << '#' << ' ' << LineNo << ' ' << '"';
+ OS.write(CurFilename.data(), CurFilename.size());
+ OS << '"';
+
+ if (ExtraLen)
+ OS.write(Extra, ExtraLen);
+
+ if (FileType == SrcMgr::C_System)
+ OS.write(" 3", 2);
+ else if (FileType == SrcMgr::C_ExternCSystem)
+ OS.write(" 3 4", 4);
+ }
+ OS << '\n';
+}
+
+/// MoveToLine - Move the output to the source line specified by the location
+/// object. We can do this by emitting some number of \n's, or be emitting a
+/// #line directive. This returns false if already at the specified line, true
+/// if some newlines were emitted.
+bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) {
+ // If this line is "close enough" to the original line, just print newlines,
+ // otherwise print a #line directive.
+ if (LineNo-CurLine <= 8) {
+ if (LineNo-CurLine == 1)
+ OS << '\n';
+ else if (LineNo == CurLine)
+ return false; // Spelling line moved, but instantiation line didn't.
+ else {
+ const char *NewLines = "\n\n\n\n\n\n\n\n";
+ OS.write(NewLines, LineNo-CurLine);
+ }
+ } else if (!DisableLineMarkers) {
+ // Emit a #line or line marker.
+ WriteLineInfo(LineNo, 0, 0);
+ } else {
+ // Okay, we're in -P mode, which turns off line markers. However, we still
+ // need to emit a newline between tokens on different lines.
+ if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
+ OS << '\n';
+ EmittedTokensOnThisLine = false;
+ EmittedMacroOnThisLine = false;
+ }
+ }
+
+ CurLine = LineNo;
+ return true;
+}
+
+bool PrintPPOutputPPCallbacks::StartNewLineIfNeeded() {
+ if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
+ OS << '\n';
+ EmittedTokensOnThisLine = false;
+ EmittedMacroOnThisLine = false;
+ ++CurLine;
+ return true;
+ }
+
+ return false;
+}
+
+/// FileChanged - Whenever the preprocessor enters or exits a #include file
+/// it invokes this handler. Update our conception of the current source
+/// position.
+void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
+ FileChangeReason Reason,
+ SrcMgr::CharacteristicKind NewFileType) {
+ // Unless we are exiting a #include, make sure to skip ahead to the line the
+ // #include directive was at.
+ SourceManager &SourceMgr = SM;
+
+ PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
+ if (UserLoc.isInvalid())
+ return;
+
+ unsigned NewLine = UserLoc.getLine();
+
+ if (Reason == PPCallbacks::EnterFile) {
+ SourceLocation IncludeLoc = UserLoc.getIncludeLoc();
+ if (IncludeLoc.isValid())
+ MoveToLine(IncludeLoc);
+ } else if (Reason == PPCallbacks::SystemHeaderPragma) {
+ MoveToLine(NewLine);
+
+ // TODO GCC emits the # directive for this directive on the line AFTER the
+ // directive and emits a bunch of spaces that aren't needed. Emulate this
+ // strange behavior.
+ }
+
+ CurLine = NewLine;
+
+ CurFilename.clear();
+ CurFilename += UserLoc.getFilename();
+ Lexer::Stringify(CurFilename);
+ FileType = NewFileType;
+
+ if (DisableLineMarkers) return;
+
+ if (!Initialized) {
+ WriteLineInfo(CurLine);
+ Initialized = true;
+ }
+
+ switch (Reason) {
+ case PPCallbacks::EnterFile:
+ WriteLineInfo(CurLine, " 1", 2);
+ break;
+ case PPCallbacks::ExitFile:
+ WriteLineInfo(CurLine, " 2", 2);
+ break;
+ case PPCallbacks::SystemHeaderPragma:
+ case PPCallbacks::RenameFile:
+ WriteLineInfo(CurLine);
+ break;
+ }
+}
+
+/// Ident - Handle #ident directives when read by the preprocessor.
+///
+void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
+ MoveToLine(Loc);
+
+ OS.write("#ident ", strlen("#ident "));
+ OS.write(&S[0], S.size());
+ EmittedTokensOnThisLine = true;
+}
+
+/// MacroDefined - This hook is called whenever a macro definition is seen.
+void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
+ const MacroInfo *MI) {
+ // Only print out macro definitions in -dD mode.
+ if (!DumpDefines ||
+ // Ignore __FILE__ etc.
+ MI->isBuiltinMacro()) return;
+
+ MoveToLine(MI->getDefinitionLoc());
+ PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
+ EmittedMacroOnThisLine = true;
+}
+
+void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
+ const MacroInfo *MI) {
+ // Only print out macro definitions in -dD mode.
+ if (!DumpDefines) return;
+
+ MoveToLine(MacroNameTok.getLocation());
+ OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName();
+ EmittedMacroOnThisLine = true;
+}
+
+void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
+ const IdentifierInfo *Kind,
+ const std::string &Str) {
+ MoveToLine(Loc);
+ OS << "#pragma comment(" << Kind->getName();
+
+ if (!Str.empty()) {
+ OS << ", \"";
+
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ unsigned char Char = Str[i];
+ if (isprint(Char) && Char != '\\' && Char != '"')
+ OS << (char)Char;
+ else // Output anything hard as an octal escape.
+ OS << '\\'
+ << (char)('0'+ ((Char >> 6) & 7))
+ << (char)('0'+ ((Char >> 3) & 7))
+ << (char)('0'+ ((Char >> 0) & 7));
+ }
+ OS << '"';
+ }
+
+ OS << ')';
+ EmittedTokensOnThisLine = true;
+}
+
+void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
+ llvm::StringRef Str) {
+ MoveToLine(Loc);
+ OS << "#pragma message(";
+
+ OS << '"';
+
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ unsigned char Char = Str[i];
+ if (isprint(Char) && Char != '\\' && Char != '"')
+ OS << (char)Char;
+ else // Output anything hard as an octal escape.
+ OS << '\\'
+ << (char)('0'+ ((Char >> 6) & 7))
+ << (char)('0'+ ((Char >> 3) & 7))
+ << (char)('0'+ ((Char >> 0) & 7));
+ }
+ OS << '"';
+
+ OS << ')';
+ EmittedTokensOnThisLine = true;
+}
+
+
+/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
+/// is called for the first token on each new line. If this really is the start
+/// of a new logical line, handle it and return true, otherwise return false.
+/// This may not be the start of a logical line because the "start of line"
+/// marker is set for spelling lines, not instantiation ones.
+bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
+ // Figure out what line we went to and insert the appropriate number of
+ // newline characters.
+ if (!MoveToLine(Tok.getLocation()))
+ return false;
+
+ // Print out space characters so that the first token on a line is
+ // indented for easy reading.
+ unsigned ColNo = SM.getInstantiationColumnNumber(Tok.getLocation());
+
+ // This hack prevents stuff like:
+ // #define HASH #
+ // HASH define foo bar
+ // From having the # character end up at column 1, which makes it so it
+ // is not handled as a #define next time through the preprocessor if in
+ // -fpreprocessed mode.
+ if (ColNo <= 1 && Tok.is(tok::hash))
+ OS << ' ';
+
+ // Otherwise, indent the appropriate number of spaces.
+ for (; ColNo > 1; --ColNo)
+ OS << ' ';
+
+ return true;
+}
+
+void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
+ unsigned Len) {
+ unsigned NumNewlines = 0;
+ for (; Len; --Len, ++TokStr) {
+ if (*TokStr != '\n' &&
+ *TokStr != '\r')
+ continue;
+
+ ++NumNewlines;
+
+ // If we have \n\r or \r\n, skip both and count as one line.
+ if (Len != 1 &&
+ (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+ TokStr[0] != TokStr[1])
+ ++TokStr, --Len;
+ }
+
+ if (NumNewlines == 0) return;
+
+ CurLine += NumNewlines;
+}
+
+
+namespace {
+struct UnknownPragmaHandler : public PragmaHandler {
+ const char *Prefix;
+ PrintPPOutputPPCallbacks *Callbacks;
+
+ UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
+ : Prefix(prefix), Callbacks(callbacks) {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PragmaTok) {
+ // Figure out what line we went to and insert the appropriate number of
+ // newline characters.
+ Callbacks->StartNewLineIfNeeded();
+ Callbacks->MoveToLine(PragmaTok.getLocation());
+ Callbacks->OS.write(Prefix, strlen(Prefix));
+ Callbacks->SetEmittedTokensOnThisLine();
+ // Read and print all of the pragma tokens.
+ while (PragmaTok.isNot(tok::eom)) {
+ if (PragmaTok.hasLeadingSpace())
+ Callbacks->OS << ' ';
+ std::string TokSpell = PP.getSpelling(PragmaTok);
+ Callbacks->OS.write(&TokSpell[0], TokSpell.size());
+ PP.LexUnexpandedToken(PragmaTok);
+ }
+ Callbacks->StartNewLineIfNeeded();
+ }
+};
+} // end anonymous namespace
+
+
+static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
+ PrintPPOutputPPCallbacks *Callbacks,
+ llvm::raw_ostream &OS) {
+ char Buffer[256];
+ Token PrevPrevTok, PrevTok;
+ PrevPrevTok.startToken();
+ PrevTok.startToken();
+ while (1) {
+
+ // If this token is at the start of a line, emit newlines if needed.
+ if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
+ // done.
+ } else if (Tok.hasLeadingSpace() ||
+ // If we haven't emitted a token on this line yet, PrevTok isn't
+ // useful to look at and no concatenation could happen anyway.
+ (Callbacks->hasEmittedTokensOnThisLine() &&
+ // Don't print "-" next to "-", it would form "--".
+ Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) {
+ OS << ' ';
+ }
+
+ if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+ OS << II->getName();
+ } else if (Tok.isLiteral() && !Tok.needsCleaning() &&
+ Tok.getLiteralData()) {
+ OS.write(Tok.getLiteralData(), Tok.getLength());
+ } else if (Tok.getLength() < 256) {
+ const char *TokPtr = Buffer;
+ unsigned Len = PP.getSpelling(Tok, TokPtr);
+ OS.write(TokPtr, Len);
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(TokPtr, Len);
+ } else {
+ std::string S = PP.getSpelling(Tok);
+ OS.write(&S[0], S.size());
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(&S[0], S.size());
+ }
+ Callbacks->SetEmittedTokensOnThisLine();
+
+ if (Tok.is(tok::eof)) break;
+
+ PrevPrevTok = PrevTok;
+ PrevTok = Tok;
+ PP.Lex(Tok);
+ }
+}
+
+typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
+static int MacroIDCompare(const void* a, const void* b) {
+ const id_macro_pair *LHS = static_cast<const id_macro_pair*>(a);
+ const id_macro_pair *RHS = static_cast<const id_macro_pair*>(b);
+ return LHS->first->getName().compare(RHS->first->getName());
+}
+
+static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
+ // Ignore unknown pragmas.
+ PP.AddPragmaHandler(new EmptyPragmaHandler());
+
+ // -dM mode just scans and ignores all tokens in the files, then dumps out
+ // the macro table at the end.
+ PP.EnterMainSourceFile();
+
+ Token Tok;
+ do PP.Lex(Tok);
+ while (Tok.isNot(tok::eof));
+
+ llvm::SmallVector<id_macro_pair, 128>
+ MacrosByID(PP.macro_begin(), PP.macro_end());
+ llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
+
+ for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
+ MacroInfo &MI = *MacrosByID[i].second;
+ // Ignore computed macros like __LINE__ and friends.
+ if (MI.isBuiltinMacro()) continue;
+
+ PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS);
+ *OS << '\n';
+ }
+}
+
+/// DoPrintPreprocessedInput - This implements -E mode.
+///
+void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
+ const PreprocessorOutputOptions &Opts) {
+ // Show macros with no output is handled specially.
+ if (!Opts.ShowCPP) {
+ assert(Opts.ShowMacros && "Not yet implemented!");
+ DoPrintMacros(PP, OS);
+ return;
+ }
+
+ // Inform the preprocessor whether we want it to retain comments or not, due
+ // to -C or -CC.
+ PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
+
+ PrintPPOutputPPCallbacks *Callbacks =
+ new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
+ Opts.ShowMacros);
+ PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks));
+ PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks));
+ PP.AddPragmaHandler("clang",
+ new UnknownPragmaHandler("#pragma clang", Callbacks));
+
+ PP.addPPCallbacks(Callbacks);
+
+ // After we have configured the preprocessor, enter the main file.
+ PP.EnterMainSourceFile();
+
+ // Consume all of the tokens that come from the predefines buffer. Those
+ // should not be emitted into the output and are guaranteed to be at the
+ // start.
+ const SourceManager &SourceMgr = PP.getSourceManager();
+ Token Tok;
+ do {
+ PP.Lex(Tok);
+ if (Tok.is(tok::eof) || !Tok.getLocation().isFileID())
+ break;
+
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation());
+ if (PLoc.isInvalid())
+ break;
+
+ if (strcmp(PLoc.getFilename(), "<built-in>"))
+ break;
+ } while (true);
+
+ // Read all the preprocessed tokens, printing them out to the stream.
+ PrintPreprocessedTokens(PP, Tok, Callbacks, *OS);
+ *OS << '\n';
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp
new file mode 100644
index 0000000..c113cc1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/StmtXML.cpp
@@ -0,0 +1,439 @@
+//===--- StmtXML.cpp - XML implementation for Stmt ASTs ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dumpXML methods, which dump out the
+// AST to an XML document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// StmtXML Visitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class StmtXML : public StmtVisitor<StmtXML> {
+ DocumentXML& Doc;
+
+ //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+ void addSpecialAttribute(const char* pName, StringLiteral* Str) {
+ Doc.addAttribute(pName, Doc.escapeString(Str->getString().data(),
+ Str->getString().size()));
+ }
+
+ void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) {
+ if (S->isArgumentType())
+ Doc.addAttribute(pName, S->getArgumentType());
+ }
+
+ void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) {
+ if (S->isTypeOperand())
+ Doc.addAttribute(pName, S->getTypeOperand());
+ }
+
+
+ public:
+ StmtXML(DocumentXML& doc)
+ : Doc(doc) {
+ }
+
+ void DumpSubTree(Stmt *S) {
+ if (S) {
+ Visit(S);
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(),
+ DE = DS->decl_end(); DI != DE; ++DI) {
+ Doc.PrintDecl(*DI);
+ }
+ } else {
+ for (Stmt::child_range i = S->children(); i; ++i)
+ DumpSubTree(*i);
+ }
+ Doc.toParent();
+ } else {
+ Doc.addSubNode("NULL").toParent();
+ }
+ }
+
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* S) \
+ { \
+ typedef CLASS tStmtType; \
+ Doc.addSubNode(NAME);
+
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
+
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
+ // Stmts.
+ void VisitStmt(Stmt *Node);
+ void VisitDeclStmt(DeclStmt *Node);
+ void VisitLabelStmt(LabelStmt *Node);
+ void VisitGotoStmt(GotoStmt *Node);
+
+ // Exprs
+ void VisitExpr(Expr *Node);
+ void VisitDeclRefExpr(DeclRefExpr *Node);
+ void VisitPredefinedExpr(PredefinedExpr *Node);
+ void VisitCharacterLiteral(CharacterLiteral *Node);
+ void VisitIntegerLiteral(IntegerLiteral *Node);
+ void VisitFloatingLiteral(FloatingLiteral *Node);
+ void VisitStringLiteral(StringLiteral *Str);
+ void VisitUnaryOperator(UnaryOperator *Node);
+ void VisitOffsetOfExpr(OffsetOfExpr *Node);
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
+ void VisitMemberExpr(MemberExpr *Node);
+ void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
+ void VisitBinaryOperator(BinaryOperator *Node);
+ void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
+ void VisitAddrLabelExpr(AddrLabelExpr *Node);
+
+ // C++
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
+ void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
+ void VisitCXXThisExpr(CXXThisExpr *Node);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
+
+ // ObjC
+ void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
+ void VisitObjCMessageExpr(ObjCMessageExpr* Node);
+ void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+ void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
+ void VisitObjCImplicitSetterGetterRefExpr(
+ ObjCImplicitSetterGetterRefExpr *Node);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
+#endif
+ };
+}
+
+//===----------------------------------------------------------------------===//
+// Stmt printing methods.
+//===----------------------------------------------------------------------===//
+#if (0)
+void StmtXML::VisitStmt(Stmt *Node) {
+ // nothing special to do
+}
+
+void StmtXML::VisitDeclStmt(DeclStmt *Node) {
+ for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
+ DI != DE; ++DI) {
+ Doc.PrintDecl(*DI);
+ }
+}
+
+void StmtXML::VisitLabelStmt(LabelStmt *Node) {
+ Doc.addAttribute("name", Node->getName());
+}
+
+void StmtXML::VisitGotoStmt(GotoStmt *Node) {
+ Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+//===----------------------------------------------------------------------===//
+// Expr printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitExpr(Expr *Node) {
+ DumpExpr(Node);
+}
+
+void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
+ DumpExpr(Node);
+
+ const char* pKind;
+ switch (Node->getDecl()->getKind()) {
+ case Decl::Function: pKind = "FunctionDecl"; break;
+ case Decl::Var: pKind = "Var"; break;
+ case Decl::ParmVar: pKind = "ParmVar"; break;
+ case Decl::EnumConstant: pKind = "EnumConstant"; break;
+ case Decl::Typedef: pKind = "Typedef"; break;
+ case Decl::Record: pKind = "Record"; break;
+ case Decl::Enum: pKind = "Enum"; break;
+ case Decl::CXXRecord: pKind = "CXXRecord"; break;
+ case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
+ case Decl::ObjCClass: pKind = "ObjCClass"; break;
+ default: pKind = "Decl"; break;
+ }
+
+ Doc.addAttribute("kind", pKind);
+ Doc.addAttribute("name", Node->getDecl()->getNameAsString());
+ Doc.addRefAttribute(Node->getDecl());
+}
+
+void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
+ DumpExpr(Node);
+ switch (Node->getIdentType()) {
+ default: assert(0 && "unknown case");
+ case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break;
+ case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break;
+ case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
+ }
+}
+
+void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("value", Node->getValue());
+}
+
+void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) {
+ DumpExpr(Node);
+ bool isSigned = Node->getType()->isSignedIntegerType();
+ Doc.addAttribute("value", Node->getValue().toString(10, isSigned));
+}
+
+void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) {
+ DumpExpr(Node);
+ // FIXME: output float as written in source (no approximation or the like)
+ //Doc.addAttribute("value", Node->getValueAsApproximateDouble()));
+ Doc.addAttribute("value", "FIXME");
+}
+
+void StmtXML::VisitStringLiteral(StringLiteral *Str) {
+ DumpExpr(Str);
+ if (Str->isWide())
+ Doc.addAttribute("is_wide", "1");
+
+ Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+}
+
+
+const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
+ switch (Op) {
+ default: assert(0 && "Unknown unary operator");
+ case UnaryOperator::PostInc: return "postinc";
+ case UnaryOperator::PostDec: return "postdec";
+ case UnaryOperator::PreInc: return "preinc";
+ case UnaryOperator::PreDec: return "predec";
+ case UnaryOperator::AddrOf: return "addrof";
+ case UnaryOperator::Deref: return "deref";
+ case UnaryOperator::Plus: return "plus";
+ case UnaryOperator::Minus: return "minus";
+ case UnaryOperator::Not: return "not";
+ case UnaryOperator::LNot: return "lnot";
+ case UnaryOperator::Real: return "__real";
+ case UnaryOperator::Imag: return "__imag";
+ case UnaryOperator::Extension: return "__extension__";
+ }
+}
+
+
+const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) {
+ switch (Op) {
+ default: assert(0 && "Unknown binary operator");
+ case BinaryOperator::PtrMemD: return "ptrmemd";
+ case BinaryOperator::PtrMemI: return "ptrmemi";
+ case BinaryOperator::Mul: return "mul";
+ case BinaryOperator::Div: return "div";
+ case BinaryOperator::Rem: return "rem";
+ case BinaryOperator::Add: return "add";
+ case BinaryOperator::Sub: return "sub";
+ case BinaryOperator::Shl: return "shl";
+ case BinaryOperator::Shr: return "shr";
+ case BinaryOperator::LT: return "lt";
+ case BinaryOperator::GT: return "gt";
+ case BinaryOperator::LE: return "le";
+ case BinaryOperator::GE: return "ge";
+ case BinaryOperator::EQ: return "eq";
+ case BinaryOperator::NE: return "ne";
+ case BinaryOperator::And: return "and";
+ case BinaryOperator::Xor: return "xor";
+ case BinaryOperator::Or: return "or";
+ case BinaryOperator::LAnd: return "land";
+ case BinaryOperator::LOr: return "lor";
+ case BinaryOperator::Assign: return "assign";
+ case BinaryOperator::MulAssign: return "mulassign";
+ case BinaryOperator::DivAssign: return "divassign";
+ case BinaryOperator::RemAssign: return "remassign";
+ case BinaryOperator::AddAssign: return "addassign";
+ case BinaryOperator::SubAssign: return "subassign";
+ case BinaryOperator::ShlAssign: return "shlassign";
+ case BinaryOperator::ShrAssign: return "shrassign";
+ case BinaryOperator::AndAssign: return "andassign";
+ case BinaryOperator::XorAssign: return "xorassign";
+ case BinaryOperator::OrAssign: return "orassign";
+ case BinaryOperator::Comma: return "comma";
+ }
+}
+
+void StmtXML::VisitUnaryOperator(UnaryOperator *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::OffsetOfExpr(OffsetOfExpr *Node) {
+ DumpExpr(Node);
+}
+
+void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");
+ Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0");
+ if (Node->isArgumentType())
+ DumpTypeExpr(Node->getArgumentType());
+}
+
+void StmtXML::VisitMemberExpr(MemberExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0");
+ Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString());
+ Doc.addRefAttribute(Node->getMemberDecl());
+}
+
+void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("name", Node->getAccessor().getName());
+}
+
+void StmtXML::VisitBinaryOperator(BinaryOperator *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
+ VisitBinaryOperator(Node);
+/* FIXME: is this needed in the AST?
+ DumpExpr(Node);
+ CurrentNode = CurrentNode->addSubNode("ComputeLHSTy");
+ DumpType(Node->getComputationLHSType());
+ CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy");
+ DumpType(Node->getComputationResultType());
+ Doc.toParent();
+*/
+}
+
+// GNU extensions.
+
+void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("kind", Node->getCastName());
+ DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("value", Node->getValue() ? "true" : "false");
+}
+
+void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) {
+ DumpExpr(Node);
+}
+
+void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+ DumpExpr(Node);
+ DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+//===----------------------------------------------------------------------===//
+// Obj-C Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("selector", Node->getSelector().getAsString());
+ IdentifierInfo* clsName = Node->getClassName();
+ if (clsName)
+ Doc.addAttribute("class", clsName->getName());
+}
+
+void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
+ DumpExpr(Node);
+ DumpTypeExpr(Node->getEncodedType());
+}
+
+void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("selector", Node->getSelector().getAsString());
+}
+
+void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString());
+}
+
+void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("property", Node->getProperty()->getNameAsString());
+}
+
+void StmtXML::VisitObjCImplicitSetterGetterRefExpr(
+ ObjCImplicitSetterGetterRefExpr *Node) {
+ DumpExpr(Node);
+ ObjCMethodDecl *Getter = Node->getGetterMethod();
+ ObjCMethodDecl *Setter = Node->getSetterMethod();
+ Doc.addAttribute("Getter", Getter->getSelector().getAsString());
+ Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)");
+}
+
+void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ DumpExpr(Node);
+ Doc.addAttribute("kind", Node->getDecl()->getDeclKindName());
+ Doc.addAttribute("decl", Node->getDecl()->getNameAsString());
+ if (Node->isFreeIvar())
+ Doc.addAttribute("isFreeIvar", "1");
+}
+#endif
+//===----------------------------------------------------------------------===//
+// Stmt method implementations
+//===----------------------------------------------------------------------===//
+
+/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+void DocumentXML::PrintStmt(const Stmt *S) {
+ StmtXML P(*this);
+ P.DumpSubTree(const_cast<Stmt*>(S));
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
new file mode 100644
index 0000000..069c86d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -0,0 +1,51 @@
+//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+
+/// HandleDiagnostic - Store the errors, warnings, and notes that are
+/// reported.
+///
+void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
+ const DiagnosticInfo &Info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticClient::HandleDiagnostic(Level, Info);
+
+ llvm::SmallString<100> Buf;
+ Info.FormatDiagnostic(Buf);
+ switch (Level) {
+ default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
+ case Diagnostic::Note:
+ Notes.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ break;
+ case Diagnostic::Warning:
+ Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ break;
+ case Diagnostic::Error:
+ case Diagnostic::Fatal:
+ Errors.push_back(std::make_pair(Info.getLocation(), Buf.str()));
+ break;
+ }
+}
+
+void TextDiagnosticBuffer::FlushDiagnostics(Diagnostic &Diags) const {
+ // FIXME: Flush the diagnostics in order.
+ for (const_iterator it = err_begin(), ie = err_end(); it != ie; ++it)
+ Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, it->second.c_str()));
+ for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it)
+ Diags.Report(Diags.getCustomDiagID(Diagnostic::Warning,it->second.c_str()));
+ for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it)
+ Diags.Report(Diags.getCustomDiagID(Diagnostic::Note, it->second.c_str()));
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
new file mode 100644
index 0000000..04c6a68
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -0,0 +1,1033 @@
+//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This diagnostic client prints out their diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include <algorithm>
+using namespace clang;
+
+static const enum llvm::raw_ostream::Colors noteColor =
+ llvm::raw_ostream::BLACK;
+static const enum llvm::raw_ostream::Colors fixitColor =
+ llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors caretColor =
+ llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors warningColor =
+ llvm::raw_ostream::MAGENTA;
+static const enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED;
+// Used for changing only the bold attribute.
+static const enum llvm::raw_ostream::Colors savedColor =
+ llvm::raw_ostream::SAVEDCOLOR;
+
+/// \brief Number of spaces to indent when word-wrapping.
+const unsigned WordWrapIndentation = 6;
+
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
+ const DiagnosticOptions &diags,
+ bool _OwnsOutputStream)
+ : OS(os), LangOpts(0), DiagOpts(&diags),
+ LastCaretDiagnosticWasNote(0),
+ OwnsOutputStream(_OwnsOutputStream) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter() {
+ if (OwnsOutputStream)
+ delete &OS;
+}
+
+void TextDiagnosticPrinter::
+PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
+ if (Loc.isInvalid()) return;
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ if (PLoc.isInvalid())
+ return;
+
+ // Print out the other include frames first.
+ PrintIncludeStack(PLoc.getIncludeLoc(), SM);
+
+ if (DiagOpts->ShowLocation)
+ OS << "In file included from " << PLoc.getFilename()
+ << ':' << PLoc.getLine() << ":\n";
+ else
+ OS << "In included file:\n";
+}
+
+/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
+/// any characters in LineNo that intersect the SourceRange.
+void TextDiagnosticPrinter::HighlightRange(const CharSourceRange &R,
+ const SourceManager &SM,
+ unsigned LineNo, FileID FID,
+ std::string &CaretLine,
+ const std::string &SourceLine) {
+ assert(CaretLine.size() == SourceLine.size() &&
+ "Expect a correspondence between source and caret line!");
+ if (!R.isValid()) return;
+
+ SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
+ SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+
+ // If the End location and the start location are the same and are a macro
+ // location, then the range was something that came from a macro expansion
+ // or _Pragma. If this is an object-like macro, the best we can do is to
+ // highlight the range. If this is a function-like macro, we'd also like to
+ // highlight the arguments.
+ if (Begin == End && R.getEnd().isMacroID())
+ End = SM.getInstantiationRange(R.getEnd()).second;
+
+ unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
+ if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
+ return; // No intersection.
+
+ unsigned EndLineNo = SM.getInstantiationLineNumber(End);
+ if (EndLineNo < LineNo || SM.getFileID(End) != FID)
+ return; // No intersection.
+
+ // Compute the column number of the start.
+ unsigned StartColNo = 0;
+ if (StartLineNo == LineNo) {
+ StartColNo = SM.getInstantiationColumnNumber(Begin);
+ if (StartColNo) --StartColNo; // Zero base the col #.
+ }
+
+ // Compute the column number of the end.
+ unsigned EndColNo = CaretLine.size();
+ if (EndLineNo == LineNo) {
+ EndColNo = SM.getInstantiationColumnNumber(End);
+ if (EndColNo) {
+ --EndColNo; // Zero base the col #.
+
+ // Add in the length of the token, so that we cover multi-char tokens if
+ // this is a token range.
+ if (R.isTokenRange())
+ EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
+ } else {
+ EndColNo = CaretLine.size();
+ }
+ }
+
+ assert(StartColNo <= EndColNo && "Invalid range!");
+
+ // Check that a token range does not highlight only whitespace.
+ if (R.isTokenRange()) {
+ // Pick the first non-whitespace column.
+ while (StartColNo < SourceLine.size() &&
+ (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
+ ++StartColNo;
+
+ // Pick the last non-whitespace column.
+ if (EndColNo > SourceLine.size())
+ EndColNo = SourceLine.size();
+ while (EndColNo-1 &&
+ (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
+ --EndColNo;
+
+ // If the start/end passed each other, then we are trying to highlight a
+ // range that just exists in whitespace, which must be some sort of other
+ // bug.
+ assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
+ }
+
+ // Fill the range with ~'s.
+ for (unsigned i = StartColNo; i < EndColNo; ++i)
+ CaretLine[i] = '~';
+}
+
+/// \brief When the source code line we want to print is too long for
+/// the terminal, select the "interesting" region.
+static void SelectInterestingSourceRegion(std::string &SourceLine,
+ std::string &CaretLine,
+ std::string &FixItInsertionLine,
+ unsigned EndOfCaretToken,
+ unsigned Columns) {
+ unsigned MaxSize = std::max(SourceLine.size(),
+ std::max(CaretLine.size(),
+ FixItInsertionLine.size()));
+ if (MaxSize > SourceLine.size())
+ SourceLine.resize(MaxSize, ' ');
+ if (MaxSize > CaretLine.size())
+ CaretLine.resize(MaxSize, ' ');
+ if (!FixItInsertionLine.empty() && MaxSize > FixItInsertionLine.size())
+ FixItInsertionLine.resize(MaxSize, ' ');
+
+ // Find the slice that we need to display the full caret line
+ // correctly.
+ unsigned CaretStart = 0, CaretEnd = CaretLine.size();
+ for (; CaretStart != CaretEnd; ++CaretStart)
+ if (!isspace(CaretLine[CaretStart]))
+ break;
+
+ for (; CaretEnd != CaretStart; --CaretEnd)
+ if (!isspace(CaretLine[CaretEnd - 1]))
+ break;
+
+ // Make sure we don't chop the string shorter than the caret token
+ // itself.
+ if (CaretEnd < EndOfCaretToken)
+ CaretEnd = EndOfCaretToken;
+
+ // If we have a fix-it line, make sure the slice includes all of the
+ // fix-it information.
+ if (!FixItInsertionLine.empty()) {
+ unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
+ for (; FixItStart != FixItEnd; ++FixItStart)
+ if (!isspace(FixItInsertionLine[FixItStart]))
+ break;
+
+ for (; FixItEnd != FixItStart; --FixItEnd)
+ if (!isspace(FixItInsertionLine[FixItEnd - 1]))
+ break;
+
+ if (FixItStart < CaretStart)
+ CaretStart = FixItStart;
+ if (FixItEnd > CaretEnd)
+ CaretEnd = FixItEnd;
+ }
+
+ // CaretLine[CaretStart, CaretEnd) contains all of the interesting
+ // parts of the caret line. While this slice is smaller than the
+ // number of columns we have, try to grow the slice to encompass
+ // more context.
+
+ // If the end of the interesting region comes before we run out of
+ // space in the terminal, start at the beginning of the line.
+ if (Columns > 3 && CaretEnd < Columns - 3)
+ CaretStart = 0;
+
+ unsigned TargetColumns = Columns;
+ if (TargetColumns > 8)
+ TargetColumns -= 8; // Give us extra room for the ellipses.
+ unsigned SourceLength = SourceLine.size();
+ while ((CaretEnd - CaretStart) < TargetColumns) {
+ bool ExpandedRegion = false;
+ // Move the start of the interesting region left until we've
+ // pulled in something else interesting.
+ if (CaretStart == 1)
+ CaretStart = 0;
+ else if (CaretStart > 1) {
+ unsigned NewStart = CaretStart - 1;
+
+ // Skip over any whitespace we see here; we're looking for
+ // another bit of interesting text.
+ while (NewStart && isspace(SourceLine[NewStart]))
+ --NewStart;
+
+ // Skip over this bit of "interesting" text.
+ while (NewStart && !isspace(SourceLine[NewStart]))
+ --NewStart;
+
+ // Move up to the non-whitespace character we just saw.
+ if (NewStart)
+ ++NewStart;
+
+ // If we're still within our limit, update the starting
+ // position within the source/caret line.
+ if (CaretEnd - NewStart <= TargetColumns) {
+ CaretStart = NewStart;
+ ExpandedRegion = true;
+ }
+ }
+
+ // Move the end of the interesting region right until we've
+ // pulled in something else interesting.
+ if (CaretEnd != SourceLength) {
+ assert(CaretEnd < SourceLength && "Unexpected caret position!");
+ unsigned NewEnd = CaretEnd;
+
+ // Skip over any whitespace we see here; we're looking for
+ // another bit of interesting text.
+ while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1]))
+ ++NewEnd;
+
+ // Skip over this bit of "interesting" text.
+ while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1]))
+ ++NewEnd;
+
+ if (NewEnd - CaretStart <= TargetColumns) {
+ CaretEnd = NewEnd;
+ ExpandedRegion = true;
+ }
+ }
+
+ if (!ExpandedRegion)
+ break;
+ }
+
+ // [CaretStart, CaretEnd) is the slice we want. Update the various
+ // output lines to show only this slice, with two-space padding
+ // before the lines so that it looks nicer.
+ if (CaretEnd < SourceLine.size())
+ SourceLine.replace(CaretEnd, std::string::npos, "...");
+ if (CaretEnd < CaretLine.size())
+ CaretLine.erase(CaretEnd, std::string::npos);
+ if (FixItInsertionLine.size() > CaretEnd)
+ FixItInsertionLine.erase(CaretEnd, std::string::npos);
+
+ if (CaretStart > 2) {
+ SourceLine.replace(0, CaretStart, " ...");
+ CaretLine.replace(0, CaretStart, " ");
+ if (FixItInsertionLine.size() >= CaretStart)
+ FixItInsertionLine.replace(0, CaretStart, " ");
+ }
+}
+
+void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
+ CharSourceRange *Ranges,
+ unsigned NumRanges,
+ const SourceManager &SM,
+ const FixItHint *Hints,
+ unsigned NumHints,
+ unsigned Columns,
+ unsigned OnMacroInst,
+ unsigned MacroSkipStart,
+ unsigned MacroSkipEnd) {
+ assert(LangOpts && "Unexpected diagnostic outside source file processing");
+ assert(!Loc.isInvalid() && "must have a valid source location here");
+
+ // If this is a macro ID, first emit information about where this was
+ // instantiated (recursively) then emit information about where the token was
+ // spelled from.
+ if (!Loc.isFileID()) {
+ // Whether to suppress printing this macro instantiation.
+ bool Suppressed
+ = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd;
+
+
+ SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
+ // FIXME: Map ranges?
+ EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns,
+ OnMacroInst + 1, MacroSkipStart, MacroSkipEnd);
+
+ // Map the location.
+ Loc = SM.getImmediateSpellingLoc(Loc);
+
+ // Map the ranges.
+ for (unsigned i = 0; i != NumRanges; ++i) {
+ CharSourceRange &R = Ranges[i];
+ SourceLocation S = R.getBegin(), E = R.getEnd();
+ if (S.isMacroID())
+ R.setBegin(SM.getImmediateSpellingLoc(S));
+ if (E.isMacroID())
+ R.setEnd(SM.getImmediateSpellingLoc(E));
+ }
+
+ if (!Suppressed) {
+ // Get the pretty name, according to #line directives etc.
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ if (PLoc.isInvalid())
+ return;
+
+ // If this diagnostic is not in the main file, print out the
+ // "included from" lines.
+ if (LastWarningLoc != PLoc.getIncludeLoc()) {
+ LastWarningLoc = PLoc.getIncludeLoc();
+ PrintIncludeStack(LastWarningLoc, SM);
+ }
+
+ if (DiagOpts->ShowLocation) {
+ // Emit the file/line/column that this expansion came from.
+ OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
+ if (DiagOpts->ShowColumn)
+ OS << PLoc.getColumn() << ':';
+ OS << ' ';
+ }
+ OS << "note: instantiated from:\n";
+
+ EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns,
+ OnMacroInst + 1, MacroSkipStart, MacroSkipEnd);
+ return;
+ }
+
+ if (OnMacroInst == MacroSkipStart) {
+ // Tell the user that we've skipped contexts.
+ OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart)
+ << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see "
+ "all)\n";
+ }
+
+ return;
+ }
+
+ // Decompose the location into a FID/Offset pair.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ // Get information about the buffer it points into.
+ bool Invalid = false;
+ const char *BufStart = SM.getBufferData(FID, &Invalid).data();
+ if (Invalid)
+ return;
+
+ unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
+ unsigned CaretEndColNo
+ = ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts);
+
+ // Rewind from the current position to the start of the line.
+ const char *TokPtr = BufStart+FileOffset;
+ const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
+
+
+ // Compute the line end. Scan forward from the error position to the end of
+ // the line.
+ const char *LineEnd = TokPtr;
+ while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
+ ++LineEnd;
+
+ // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
+ // the source line length as currently being computed. See
+ // test/Misc/message-length.c.
+ CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
+
+ // Copy the line of code into an std::string for ease of manipulation.
+ std::string SourceLine(LineStart, LineEnd);
+
+ // Create a line for the caret that is filled with spaces that is the same
+ // length as the line of source code.
+ std::string CaretLine(LineEnd-LineStart, ' ');
+
+ // Highlight all of the characters covered by Ranges with ~ characters.
+ if (NumRanges) {
+ unsigned LineNo = SM.getLineNumber(FID, FileOffset);
+
+ for (unsigned i = 0, e = NumRanges; i != e; ++i)
+ HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
+ }
+
+ // Next, insert the caret itself.
+ if (ColNo-1 < CaretLine.size())
+ CaretLine[ColNo-1] = '^';
+ else
+ CaretLine.push_back('^');
+
+ // Scan the source line, looking for tabs. If we find any, manually expand
+ // them to spaces and update the CaretLine to match.
+ for (unsigned i = 0; i != SourceLine.size(); ++i) {
+ if (SourceLine[i] != '\t') continue;
+
+ // Replace this tab with at least one space.
+ SourceLine[i] = ' ';
+
+ // Compute the number of spaces we need to insert.
+ unsigned TabStop = DiagOpts->TabStop;
+ assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
+ "Invalid -ftabstop value");
+ unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1);
+ assert(NumSpaces < TabStop && "Invalid computation of space amt");
+
+ // Insert spaces into the SourceLine.
+ SourceLine.insert(i+1, NumSpaces, ' ');
+
+ // Insert spaces or ~'s into CaretLine.
+ CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
+ }
+
+ // If we are in -fdiagnostics-print-source-range-info mode, we are trying to
+ // produce easily machine parsable output. Add a space before the source line
+ // and the caret to make it trivial to tell the main diagnostic line from what
+ // the user is intended to see.
+ if (DiagOpts->ShowSourceRanges) {
+ SourceLine = ' ' + SourceLine;
+ CaretLine = ' ' + CaretLine;
+ }
+
+ std::string FixItInsertionLine;
+ if (NumHints && DiagOpts->ShowFixits) {
+ for (const FixItHint *Hint = Hints, *LastHint = Hints + NumHints;
+ Hint != LastHint; ++Hint) {
+ if (!Hint->CodeToInsert.empty()) {
+ // We have an insertion hint. Determine whether the inserted
+ // code is on the same line as the caret.
+ std::pair<FileID, unsigned> HintLocInfo
+ = SM.getDecomposedInstantiationLoc(Hint->RemoveRange.getBegin());
+ if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) ==
+ SM.getLineNumber(FID, FileOffset)) {
+ // Insert the new code into the line just below the code
+ // that the user wrote.
+ unsigned HintColNo
+ = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
+ unsigned LastColumnModified
+ = HintColNo - 1 + Hint->CodeToInsert.size();
+ if (LastColumnModified > FixItInsertionLine.size())
+ FixItInsertionLine.resize(LastColumnModified, ' ');
+ std::copy(Hint->CodeToInsert.begin(), Hint->CodeToInsert.end(),
+ FixItInsertionLine.begin() + HintColNo - 1);
+ } else {
+ FixItInsertionLine.clear();
+ break;
+ }
+ }
+ }
+ // Now that we have the entire fixit line, expand the tabs in it.
+ // Since we don't want to insert spaces in the middle of a word,
+ // find each word and the column it should line up with and insert
+ // spaces until they match.
+ if (!FixItInsertionLine.empty()) {
+ unsigned FixItPos = 0;
+ unsigned LinePos = 0;
+ unsigned TabExpandedCol = 0;
+ unsigned LineLength = LineEnd - LineStart;
+
+ while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
+ // Find the next word in the FixIt line.
+ while (FixItPos < FixItInsertionLine.size() &&
+ FixItInsertionLine[FixItPos] == ' ')
+ ++FixItPos;
+ unsigned CharDistance = FixItPos - TabExpandedCol;
+
+ // Walk forward in the source line, keeping track of
+ // the tab-expanded column.
+ for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
+ if (LinePos >= LineLength || LineStart[LinePos] != '\t')
+ ++TabExpandedCol;
+ else
+ TabExpandedCol =
+ (TabExpandedCol/DiagOpts->TabStop + 1) * DiagOpts->TabStop;
+
+ // Adjust the fixit line to match this column.
+ FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
+ FixItPos = TabExpandedCol;
+
+ // Walk to the end of the word.
+ while (FixItPos < FixItInsertionLine.size() &&
+ FixItInsertionLine[FixItPos] != ' ')
+ ++FixItPos;
+ }
+ }
+ }
+
+ // If the source line is too long for our terminal, select only the
+ // "interesting" source region within that line.
+ if (Columns && SourceLine.size() > Columns)
+ SelectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
+ CaretEndColNo, Columns);
+
+ // Finally, remove any blank spaces from the end of CaretLine.
+ while (CaretLine[CaretLine.size()-1] == ' ')
+ CaretLine.erase(CaretLine.end()-1);
+
+ // Emit what we have computed.
+ OS << SourceLine << '\n';
+
+ if (DiagOpts->ShowColors)
+ OS.changeColor(caretColor, true);
+ OS << CaretLine << '\n';
+ if (DiagOpts->ShowColors)
+ OS.resetColor();
+
+ if (!FixItInsertionLine.empty()) {
+ if (DiagOpts->ShowColors)
+ // Print fixit line in color
+ OS.changeColor(fixitColor, false);
+ if (DiagOpts->ShowSourceRanges)
+ OS << ' ';
+ OS << FixItInsertionLine << '\n';
+ if (DiagOpts->ShowColors)
+ OS.resetColor();
+ }
+
+ if (DiagOpts->ShowParseableFixits) {
+
+ // We follow FixItRewriter's example in not (yet) handling
+ // fix-its in macros.
+ bool BadApples = false;
+ for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
+ if (Hint->RemoveRange.isInvalid() ||
+ Hint->RemoveRange.getBegin().isMacroID() ||
+ Hint->RemoveRange.getEnd().isMacroID()) {
+ BadApples = true;
+ break;
+ }
+ }
+
+ if (!BadApples) {
+ for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
+
+ SourceLocation B = Hint->RemoveRange.getBegin();
+ SourceLocation E = Hint->RemoveRange.getEnd();
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+
+ // Adjust for token ranges.
+ if (Hint->RemoveRange.isTokenRange())
+ EInfo.second += Lexer::MeasureTokenLength(E, SM, *LangOpts);
+
+ // We specifically do not do word-wrapping or tab-expansion here,
+ // because this is supposed to be easy to parse.
+ PresumedLoc PLoc = SM.getPresumedLoc(B);
+ if (PLoc.isInvalid())
+ break;
+
+ OS << "fix-it:\"";
+ OS.write_escaped(SM.getPresumedLoc(B).getFilename());
+ OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
+ << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
+ << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
+ << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
+ << "}:\"";
+ OS.write_escaped(Hint->CodeToInsert);
+ OS << "\"\n";
+ }
+ }
+ }
+}
+
+/// \brief Skip over whitespace in the string, starting at the given
+/// index.
+///
+/// \returns The index of the first non-whitespace character that is
+/// greater than or equal to Idx or, if no such character exists,
+/// returns the end of the string.
+static unsigned skipWhitespace(unsigned Idx,
+ const llvm::SmallVectorImpl<char> &Str,
+ unsigned Length) {
+ while (Idx < Length && isspace(Str[Idx]))
+ ++Idx;
+ return Idx;
+}
+
+/// \brief If the given character is the start of some kind of
+/// balanced punctuation (e.g., quotes or parentheses), return the
+/// character that will terminate the punctuation.
+///
+/// \returns The ending punctuation character, if any, or the NULL
+/// character if the input character does not start any punctuation.
+static inline char findMatchingPunctuation(char c) {
+ switch (c) {
+ case '\'': return '\'';
+ case '`': return '\'';
+ case '"': return '"';
+ case '(': return ')';
+ case '[': return ']';
+ case '{': return '}';
+ default: break;
+ }
+
+ return 0;
+}
+
+/// \brief Find the end of the word starting at the given offset
+/// within a string.
+///
+/// \returns the index pointing one character past the end of the
+/// word.
+static unsigned findEndOfWord(unsigned Start,
+ const llvm::SmallVectorImpl<char> &Str,
+ unsigned Length, unsigned Column,
+ unsigned Columns) {
+ assert(Start < Str.size() && "Invalid start position!");
+ unsigned End = Start + 1;
+
+ // If we are already at the end of the string, take that as the word.
+ if (End == Str.size())
+ return End;
+
+ // Determine if the start of the string is actually opening
+ // punctuation, e.g., a quote or parentheses.
+ char EndPunct = findMatchingPunctuation(Str[Start]);
+ if (!EndPunct) {
+ // This is a normal word. Just find the first space character.
+ while (End < Length && !isspace(Str[End]))
+ ++End;
+ return End;
+ }
+
+ // We have the start of a balanced punctuation sequence (quotes,
+ // parentheses, etc.). Determine the full sequence is.
+ llvm::SmallString<16> PunctuationEndStack;
+ PunctuationEndStack.push_back(EndPunct);
+ while (End < Length && !PunctuationEndStack.empty()) {
+ if (Str[End] == PunctuationEndStack.back())
+ PunctuationEndStack.pop_back();
+ else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
+ PunctuationEndStack.push_back(SubEndPunct);
+
+ ++End;
+ }
+
+ // Find the first space character after the punctuation ended.
+ while (End < Length && !isspace(Str[End]))
+ ++End;
+
+ unsigned PunctWordLength = End - Start;
+ if (// If the word fits on this line
+ Column + PunctWordLength <= Columns ||
+ // ... or the word is "short enough" to take up the next line
+ // without too much ugly white space
+ PunctWordLength < Columns/3)
+ return End; // Take the whole thing as a single "word".
+
+ // The whole quoted/parenthesized string is too long to print as a
+ // single "word". Instead, find the "word" that starts just after
+ // the punctuation and use that end-point instead. This will recurse
+ // until it finds something small enough to consider a word.
+ return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
+}
+
+/// \brief Print the given string to a stream, word-wrapping it to
+/// some number of columns in the process.
+///
+/// \brief OS the stream to which the word-wrapping string will be
+/// emitted.
+///
+/// \brief Str the string to word-wrap and output.
+///
+/// \brief Columns the number of columns to word-wrap to.
+///
+/// \brief Column the column number at which the first character of \p
+/// Str will be printed. This will be non-zero when part of the first
+/// line has already been printed.
+///
+/// \brief Indentation the number of spaces to indent any lines beyond
+/// the first line.
+///
+/// \returns true if word-wrapping was required, or false if the
+/// string fit on the first line.
+static bool PrintWordWrapped(llvm::raw_ostream &OS,
+ const llvm::SmallVectorImpl<char> &Str,
+ unsigned Columns,
+ unsigned Column = 0,
+ unsigned Indentation = WordWrapIndentation) {
+ unsigned Length = Str.size();
+
+ // If there is a newline in this message somewhere, find that
+ // newline and split the message into the part before the newline
+ // (which will be word-wrapped) and the part from the newline one
+ // (which will be emitted unchanged).
+ for (unsigned I = 0; I != Length; ++I)
+ if (Str[I] == '\n') {
+ Length = I;
+ break;
+ }
+
+ // The string used to indent each line.
+ llvm::SmallString<16> IndentStr;
+ IndentStr.assign(Indentation, ' ');
+ bool Wrapped = false;
+ for (unsigned WordStart = 0, WordEnd; WordStart < Length;
+ WordStart = WordEnd) {
+ // Find the beginning of the next word.
+ WordStart = skipWhitespace(WordStart, Str, Length);
+ if (WordStart == Length)
+ break;
+
+ // Find the end of this word.
+ WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
+
+ // Does this word fit on the current line?
+ unsigned WordLength = WordEnd - WordStart;
+ if (Column + WordLength < Columns) {
+ // This word fits on the current line; print it there.
+ if (WordStart) {
+ OS << ' ';
+ Column += 1;
+ }
+ OS.write(&Str[WordStart], WordLength);
+ Column += WordLength;
+ continue;
+ }
+
+ // This word does not fit on the current line, so wrap to the next
+ // line.
+ OS << '\n';
+ OS.write(&IndentStr[0], Indentation);
+ OS.write(&Str[WordStart], WordLength);
+ Column = Indentation + WordLength;
+ Wrapped = true;
+ }
+
+ if (Length == Str.size())
+ return Wrapped; // We're done.
+
+ // There is a newline in the message, followed by something that
+ // will not be word-wrapped. Print that.
+ OS.write(&Str[Length], Str.size() - Length);
+ return true;
+}
+
+void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
+ const DiagnosticInfo &Info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticClient::HandleDiagnostic(Level, Info);
+
+ // Keeps track of the the starting position of the location
+ // information (e.g., "foo.c:10:4:") that precedes the error
+ // message. We use this information to determine how long the
+ // file+line+column number prefix is.
+ uint64_t StartOfLocationInfo = OS.tell();
+
+ if (!Prefix.empty())
+ OS << Prefix << ": ";
+
+ // If the location is specified, print out a file/line/col and include trace
+ // if enabled.
+ if (Info.getLocation().isValid()) {
+ const SourceManager &SM = Info.getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
+ if (PLoc.isInvalid()) {
+ // At least print the file name if available:
+ FileID FID = SM.getFileID(Info.getLocation());
+ if (!FID.isInvalid()) {
+ const FileEntry* FE = SM.getFileEntryForID(FID);
+ if (FE && FE->getName()) {
+ OS << FE->getName();
+ if (FE->getDevice() == 0 && FE->getInode() == 0
+ && FE->getFileMode() == 0) {
+ // in PCH is a guess, but a good one:
+ OS << " (in PCH)";
+ }
+ OS << ": ";
+ }
+ }
+ } else {
+ unsigned LineNo = PLoc.getLine();
+
+ // First, if this diagnostic is not in the main file, print out the
+ // "included from" lines.
+ if (LastWarningLoc != PLoc.getIncludeLoc()) {
+ LastWarningLoc = PLoc.getIncludeLoc();
+ PrintIncludeStack(LastWarningLoc, SM);
+ StartOfLocationInfo = OS.tell();
+ }
+
+ // Compute the column number.
+ if (DiagOpts->ShowLocation && PLoc.isValid()) {
+ if (DiagOpts->ShowColors)
+ OS.changeColor(savedColor, true);
+
+ // Emit a Visual Studio compatible line number syntax.
+ if (LangOpts && LangOpts->Microsoft) {
+ OS << PLoc.getFilename() << '(' << LineNo << ')';
+ OS << " : ";
+ } else {
+ OS << PLoc.getFilename() << ':' << LineNo << ':';
+ if (DiagOpts->ShowColumn)
+ if (unsigned ColNo = PLoc.getColumn())
+ OS << ColNo << ':';
+ }
+ if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
+ FileID CaretFileID =
+ SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
+ bool PrintedRange = false;
+
+ for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) {
+ // Ignore invalid ranges.
+ if (!Info.getRange(i).isValid()) continue;
+
+ SourceLocation B = Info.getRange(i).getBegin();
+ SourceLocation E = Info.getRange(i).getEnd();
+ B = SM.getInstantiationLoc(B);
+ E = SM.getInstantiationLoc(E);
+
+ // If the End location and the start location are the same and are a
+ // macro location, then the range was something that came from a
+ // macro expansion or _Pragma. If this is an object-like macro, the
+ // best we can do is to highlight the range. If this is a
+ // function-like macro, we'd also like to highlight the arguments.
+ if (B == E && Info.getRange(i).getEnd().isMacroID())
+ E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+
+ // If the start or end of the range is in another file, just discard
+ // it.
+ if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
+ continue;
+
+ // Add in the length of the token, so that we cover multi-char
+ // tokens.
+ unsigned TokSize = 0;
+ if (Info.getRange(i).isTokenRange())
+ TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
+
+ OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
+ << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
+ << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
+ << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
+ << '}';
+ PrintedRange = true;
+ }
+
+ if (PrintedRange)
+ OS << ':';
+ }
+ }
+ OS << ' ';
+ if (DiagOpts->ShowColors)
+ OS.resetColor();
+ }
+ }
+
+ if (DiagOpts->ShowColors) {
+ // Print diagnostic category in bold and color
+ switch (Level) {
+ case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
+ case Diagnostic::Note: OS.changeColor(noteColor, true); break;
+ case Diagnostic::Warning: OS.changeColor(warningColor, true); break;
+ case Diagnostic::Error: OS.changeColor(errorColor, true); break;
+ case Diagnostic::Fatal: OS.changeColor(fatalColor, true); break;
+ }
+ }
+
+ switch (Level) {
+ case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
+ case Diagnostic::Note: OS << "note: "; break;
+ case Diagnostic::Warning: OS << "warning: "; break;
+ case Diagnostic::Error: OS << "error: "; break;
+ case Diagnostic::Fatal: OS << "fatal error: "; break;
+ }
+
+ if (DiagOpts->ShowColors)
+ OS.resetColor();
+
+ llvm::SmallString<100> OutStr;
+ Info.FormatDiagnostic(OutStr);
+
+ std::string OptionName;
+ if (DiagOpts->ShowOptionNames) {
+ if (const char *
+ Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) {
+ OptionName = "-W";
+ OptionName += Opt;
+ } else if (Info.getID() == diag::fatal_too_many_errors) {
+ OptionName = "-ferror-limit=";
+ } else {
+ // If the diagnostic is an extension diagnostic and not enabled by default
+ // then it must have been turned on with -pedantic.
+ bool EnabledByDefault;
+ if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
+ EnabledByDefault) &&
+ !EnabledByDefault)
+ OptionName = "-pedantic";
+ }
+ }
+
+ // If the user wants to see category information, include it too.
+ unsigned DiagCategory = 0;
+ if (DiagOpts->ShowCategories)
+ DiagCategory = DiagnosticIDs::getCategoryNumberForDiag(Info.getID());
+
+ // If there is any categorization information, include it.
+ if (!OptionName.empty() || DiagCategory != 0) {
+ bool NeedsComma = false;
+ OutStr += " [";
+
+ if (!OptionName.empty()) {
+ OutStr += OptionName;
+ NeedsComma = true;
+ }
+
+ if (DiagCategory) {
+ if (NeedsComma) OutStr += ',';
+ if (DiagOpts->ShowCategories == 1)
+ OutStr += llvm::utostr(DiagCategory);
+ else {
+ assert(DiagOpts->ShowCategories == 2 && "Invalid ShowCategories value");
+ OutStr += DiagnosticIDs::getCategoryNameFromID(DiagCategory);
+ }
+ }
+
+ OutStr += "]";
+ }
+
+
+ if (DiagOpts->ShowColors) {
+ // Print warnings, errors and fatal errors in bold, no color
+ switch (Level) {
+ case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
+ case Diagnostic::Error: OS.changeColor(savedColor, true); break;
+ case Diagnostic::Fatal: OS.changeColor(savedColor, true); break;
+ default: break; //don't bold notes
+ }
+ }
+
+ if (DiagOpts->MessageLength) {
+ // We will be word-wrapping the error message, so compute the
+ // column number where we currently are (after printing the
+ // location information).
+ unsigned Column = OS.tell() - StartOfLocationInfo;
+ PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
+ } else {
+ OS.write(OutStr.begin(), OutStr.size());
+ }
+ OS << '\n';
+ if (DiagOpts->ShowColors)
+ OS.resetColor();
+
+ // If caret diagnostics are enabled and we have location, we want to
+ // emit the caret. However, we only do this if the location moved
+ // from the last diagnostic, if the last diagnostic was a note that
+ // was part of a different warning or error diagnostic, or if the
+ // diagnostic has ranges. We don't want to emit the same caret
+ // multiple times if one loc has multiple diagnostics.
+ if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
+ ((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
+ (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
+ Info.getNumFixItHints())) {
+ // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
+ LastLoc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
+ LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
+
+ // Get the ranges into a local array we can hack on.
+ CharSourceRange Ranges[20];
+ unsigned NumRanges = Info.getNumRanges();
+ assert(NumRanges < 20 && "Out of space");
+ for (unsigned i = 0; i != NumRanges; ++i)
+ Ranges[i] = Info.getRange(i);
+
+ unsigned NumHints = Info.getNumFixItHints();
+ for (unsigned i = 0; i != NumHints; ++i) {
+ const FixItHint &Hint = Info.getFixItHint(i);
+ if (Hint.RemoveRange.isValid()) {
+ assert(NumRanges < 20 && "Out of space");
+ Ranges[NumRanges++] = Hint.RemoveRange;
+ }
+ }
+
+ unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0;
+ if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) {
+ // Compute the length of the macro-instantiation backtrace, so that we
+ // can establish which steps in the macro backtrace we'll skip.
+ SourceLocation Loc = LastLoc;
+ unsigned Depth = 0;
+ do {
+ ++Depth;
+ Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first;
+ } while (!Loc.isFileID());
+
+ if (Depth > DiagOpts->MacroBacktraceLimit) {
+ MacroInstSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
+ DiagOpts->MacroBacktraceLimit % 2;
+ MacroInstSkipEnd = Depth - DiagOpts->MacroBacktraceLimit / 2;
+ }
+ }
+
+ EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
+ Info.getFixItHints(),
+ Info.getNumFixItHints(),
+ DiagOpts->MessageLength,
+ 0, MacroInstSkipStart, MacroInstSkipEnd);
+ }
+
+ OS.flush();
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..a8c8f75
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,119 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+ namespace XML {
+ namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter> {
+ DocumentXML& Doc;
+
+public:
+ TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(const CLASS* T) { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+ } // anon clang
+ } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder> {
+ DocumentXML& Doc;
+
+ void addIfType(const Type* pType) {
+ Doc.addTypeRecursively(pType);
+ }
+
+ void addIfType(const QualType& pType) {
+ Doc.addTypeRecursively(pType);
+ }
+
+ template<class T> void addIfType(T) {}
+
+public:
+ TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(const CLASS* T) \
+ {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType) {
+ TypeAdder(*this).Visit(pType);
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType) {
+ XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType) {
+ XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
new file mode 100644
index 0000000..51b351f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -0,0 +1,513 @@
+//===--- VerifyDiagnosticsClient.cpp - Verifying Diagnostic Client --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags,
+ DiagnosticClient *_Primary)
+ : Diags(_Diags), PrimaryClient(_Primary),
+ Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0) {
+}
+
+VerifyDiagnosticsClient::~VerifyDiagnosticsClient() {
+ CheckDiagnostics();
+}
+
+// DiagnosticClient interface.
+
+void VerifyDiagnosticsClient::BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) {
+ // FIXME: Const hack, we screw up the preprocessor but in practice its ok
+ // because it doesn't get reused. It would be better if we could make a copy
+ // though.
+ CurrentPreprocessor = const_cast<Preprocessor*>(PP);
+
+ PrimaryClient->BeginSourceFile(LangOpts, PP);
+}
+
+void VerifyDiagnosticsClient::EndSourceFile() {
+ CheckDiagnostics();
+
+ PrimaryClient->EndSourceFile();
+
+ CurrentPreprocessor = 0;
+}
+
+void VerifyDiagnosticsClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Send the diagnostic to the buffer, we will check it once we reach the end
+ // of the source file (or are destructed).
+ Buffer->HandleDiagnostic(DiagLevel, Info);
+}
+
+//===----------------------------------------------------------------------===//
+// Checking diagnostics implementation.
+//===----------------------------------------------------------------------===//
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+namespace {
+
+/// Directive - Abstract class representing a parsed verify directive.
+///
+class Directive {
+public:
+ static Directive* Create(bool RegexKind, const SourceLocation &Location,
+ const std::string &Text, unsigned Count);
+public:
+ SourceLocation Location;
+ const std::string Text;
+ unsigned Count;
+
+ virtual ~Directive() { }
+
+ // Returns true if directive text is valid.
+ // Otherwise returns false and populates E.
+ virtual bool isValid(std::string &Error) = 0;
+
+ // Returns true on match.
+ virtual bool Match(const std::string &S) = 0;
+
+protected:
+ Directive(const SourceLocation &Location, const std::string &Text,
+ unsigned Count)
+ : Location(Location), Text(Text), Count(Count) { }
+
+private:
+ Directive(const Directive&); // DO NOT IMPLEMENT
+ void operator=(const Directive&); // DO NOT IMPLEMENT
+};
+
+/// StandardDirective - Directive with string matching.
+///
+class StandardDirective : public Directive {
+public:
+ StandardDirective(const SourceLocation &Location, const std::string &Text,
+ unsigned Count)
+ : Directive(Location, Text, Count) { }
+
+ virtual bool isValid(std::string &Error) {
+ // all strings are considered valid; even empty ones
+ return true;
+ }
+
+ virtual bool Match(const std::string &S) {
+ return S.find(Text) != std::string::npos ||
+ Text.find(S) != std::string::npos;
+ }
+};
+
+/// RegexDirective - Directive with regular-expression matching.
+///
+class RegexDirective : public Directive {
+public:
+ RegexDirective(const SourceLocation &Location, const std::string &Text,
+ unsigned Count)
+ : Directive(Location, Text, Count), Regex(Text) { }
+
+ virtual bool isValid(std::string &Error) {
+ if (Regex.isValid(Error))
+ return true;
+ return false;
+ }
+
+ virtual bool Match(const std::string &S) {
+ return Regex.match(S);
+ }
+
+private:
+ llvm::Regex Regex;
+};
+
+typedef std::vector<Directive*> DirectiveList;
+
+/// ExpectedData - owns directive objects and deletes on destructor.
+///
+struct ExpectedData {
+ DirectiveList Errors;
+ DirectiveList Warnings;
+ DirectiveList Notes;
+
+ ~ExpectedData() {
+ DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 };
+ for (DirectiveList **PL = Lists; *PL; ++PL) {
+ DirectiveList * const L = *PL;
+ for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I)
+ delete *I;
+ }
+ }
+};
+
+class ParseHelper
+{
+public:
+ ParseHelper(const char *Begin, const char *End)
+ : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { }
+
+ // Return true if string literal is next.
+ bool Next(llvm::StringRef S) {
+ P = C;
+ PEnd = C + S.size();
+ if (PEnd > End)
+ return false;
+ return !memcmp(P, S.data(), S.size());
+ }
+
+ // Return true if number is next.
+ // Output N only if number is next.
+ bool Next(unsigned &N) {
+ unsigned TMP = 0;
+ P = C;
+ for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) {
+ TMP *= 10;
+ TMP += P[0] - '0';
+ }
+ if (P == C)
+ return false;
+ PEnd = P;
+ N = TMP;
+ return true;
+ }
+
+ // Return true if string literal is found.
+ // When true, P marks begin-position of S in content.
+ bool Search(llvm::StringRef S) {
+ P = std::search(C, End, S.begin(), S.end());
+ PEnd = P + S.size();
+ return P != End;
+ }
+
+ // Advance 1-past previous next/search.
+ // Behavior is undefined if previous next/search failed.
+ bool Advance() {
+ C = PEnd;
+ return C < End;
+ }
+
+ // Skip zero or more whitespace.
+ void SkipWhitespace() {
+ for (; C < End && isspace(*C); ++C)
+ ;
+ }
+
+ // Return true if EOF reached.
+ bool Done() {
+ return !(C < End);
+ }
+
+ const char * const Begin; // beginning of expected content
+ const char * const End; // end of expected content (1-past)
+ const char *C; // position of next char in content
+ const char *P;
+
+private:
+ const char *PEnd; // previous next/search subject end (1-past)
+};
+
+} // namespace anonymous
+
+/// ParseDirective - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in the appropriate directive list.
+///
+static void ParseDirective(const char *CommentStart, unsigned CommentLen,
+ ExpectedData &ED, Preprocessor &PP,
+ SourceLocation Pos) {
+ // A single comment may contain multiple directives.
+ for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {
+ // search for token: expected
+ if (!PH.Search("expected"))
+ break;
+ PH.Advance();
+
+ // next token: -
+ if (!PH.Next("-"))
+ continue;
+ PH.Advance();
+
+ // next token: { error | warning | note }
+ DirectiveList* DL = NULL;
+ if (PH.Next("error"))
+ DL = &ED.Errors;
+ else if (PH.Next("warning"))
+ DL = &ED.Warnings;
+ else if (PH.Next("note"))
+ DL = &ED.Notes;
+ else
+ continue;
+ PH.Advance();
+
+ // default directive kind
+ bool RegexKind = false;
+ const char* KindStr = "string";
+
+ // next optional token: -
+ if (PH.Next("-re")) {
+ PH.Advance();
+ RegexKind = true;
+ KindStr = "regex";
+ }
+
+ // skip optional whitespace
+ PH.SkipWhitespace();
+
+ // next optional token: positive integer
+ unsigned Count = 1;
+ if (PH.Next(Count))
+ PH.Advance();
+
+ // skip optional whitespace
+ PH.SkipWhitespace();
+
+ // next token: {{
+ if (!PH.Next("{{")) {
+ PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_start) << KindStr;
+ continue;
+ }
+ PH.Advance();
+ const char* const ContentBegin = PH.C; // mark content begin
+
+ // search for token: }}
+ if (!PH.Search("}}")) {
+ PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_end) << KindStr;
+ continue;
+ }
+ const char* const ContentEnd = PH.P; // mark content end
+ PH.Advance();
+
+ // build directive text; convert \n to newlines
+ std::string Text;
+ llvm::StringRef NewlineStr = "\\n";
+ llvm::StringRef Content(ContentBegin, ContentEnd-ContentBegin);
+ size_t CPos = 0;
+ size_t FPos;
+ while ((FPos = Content.find(NewlineStr, CPos)) != llvm::StringRef::npos) {
+ Text += Content.substr(CPos, FPos-CPos);
+ Text += '\n';
+ CPos = FPos + NewlineStr.size();
+ }
+ if (Text.empty())
+ Text.assign(ContentBegin, ContentEnd);
+
+ // construct new directive
+ Directive *D = Directive::Create(RegexKind, Pos, Text, Count);
+ std::string Error;
+ if (D->isValid(Error))
+ DL->push_back(D);
+ else {
+ PP.Diag(Pos.getFileLocWithOffset(ContentBegin-PH.Begin),
+ diag::err_verify_invalid_content)
+ << KindStr << Error;
+ }
+ }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+// expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED) {
+ // Create a raw lexer to pull all the comments out of the main file. We don't
+ // want to look in #include'd headers for expected-error strings.
+ SourceManager &SM = PP.getSourceManager();
+ FileID FID = SM.getMainFileID();
+ if (SM.getMainFileID().isInvalid())
+ return;
+
+ // Create a lexer to lex all the tokens of the main file in raw mode.
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+ Lexer RawLex(FID, FromFile, SM, PP.getLangOptions());
+
+ // Return comments as tokens, this is how we find expected diagnostics.
+ RawLex.SetCommentRetentionState(true);
+
+ Token Tok;
+ Tok.setKind(tok::comment);
+ while (Tok.isNot(tok::eof)) {
+ RawLex.Lex(Tok);
+ if (!Tok.is(tok::comment)) continue;
+
+ std::string Comment = PP.getSpelling(Tok);
+ if (Comment.empty()) continue;
+
+ // Find all expected errors/warnings/notes.
+ ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation());
+ };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
+ const_diag_iterator diag_begin,
+ const_diag_iterator diag_end,
+ const char *Kind, bool Expected) {
+ if (diag_begin == diag_end) return 0;
+
+ llvm::SmallString<256> Fmt;
+ llvm::raw_svector_ostream OS(Fmt);
+ for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
+ if (I->first.isInvalid() || !SourceMgr)
+ OS << "\n (frontend)";
+ else
+ OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first);
+ OS << ": " << I->second;
+ }
+
+ Diags.Report(diag::err_verify_inconsistent_diags)
+ << Kind << !Expected << OS.str();
+ return std::distance(diag_begin, diag_end);
+}
+
+static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
+ DirectiveList &DL, const char *Kind,
+ bool Expected) {
+ if (DL.empty())
+ return 0;
+
+ llvm::SmallString<256> Fmt;
+ llvm::raw_svector_ostream OS(Fmt);
+ for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
+ Directive& D = **I;
+ if (D.Location.isInvalid() || !SourceMgr)
+ OS << "\n (frontend)";
+ else
+ OS << "\n Line " << SourceMgr->getInstantiationLineNumber(D.Location);
+ OS << ": " << D.Text;
+ }
+
+ Diags.Report(diag::err_verify_inconsistent_diags)
+ << Kind << !Expected << OS.str();
+ return DL.size();
+}
+
+/// CheckLists - Compare expected to seen diagnostic lists and return the
+/// the difference between them.
+///
+static unsigned CheckLists(Diagnostic &Diags, SourceManager &SourceMgr,
+ const char *Label,
+ DirectiveList &Left,
+ const_diag_iterator d2_begin,
+ const_diag_iterator d2_end) {
+ DirectiveList LeftOnly;
+ DiagList Right(d2_begin, d2_end);
+
+ for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+ Directive& D = **I;
+ unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(D.Location);
+
+ for (unsigned i = 0; i < D.Count; ++i) {
+ DiagList::iterator II, IE;
+ for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+ unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ if (LineNo1 != LineNo2)
+ continue;
+
+ const std::string &RightText = II->second;
+ if (D.Match(RightText))
+ break;
+ }
+ if (II == IE) {
+ // Not found.
+ LeftOnly.push_back(*I);
+ } else {
+ // Found. The same cannot be found twice.
+ Right.erase(II);
+ }
+ }
+ }
+ // Now all that's left in Right are those that were not matched.
+
+ return (PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true) +
+ PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),
+ Label, false));
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr,
+ const TextDiagnosticBuffer &Buffer,
+ ExpectedData &ED) {
+ // We want to capture the delta between what was expected and what was
+ // seen.
+ //
+ // Expected \ Seen - set expected but not seen
+ // Seen \ Expected - set seen but not expected
+ unsigned NumProblems = 0;
+
+ // See if there are error mismatches.
+ NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
+ Buffer.err_begin(), Buffer.err_end());
+
+ // See if there are warning mismatches.
+ NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
+ Buffer.warn_begin(), Buffer.warn_end());
+
+ // See if there are note mismatches.
+ NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
+ Buffer.note_begin(), Buffer.note_end());
+
+ return NumProblems;
+}
+
+void VerifyDiagnosticsClient::CheckDiagnostics() {
+ ExpectedData ED;
+
+ // Ensure any diagnostics go to the primary client.
+ DiagnosticClient *CurClient = Diags.takeClient();
+ Diags.setClient(PrimaryClient.get());
+
+ // If we have a preprocessor, scan the source for expected diagnostic
+ // markers. If not then any diagnostics are unexpected.
+ if (CurrentPreprocessor) {
+ FindExpectedDiags(*CurrentPreprocessor, ED);
+
+ // Check that the expected diagnostics occurred.
+ NumErrors += CheckResults(Diags, CurrentPreprocessor->getSourceManager(),
+ *Buffer, ED);
+ } else {
+ NumErrors += (PrintProblem(Diags, 0,
+ Buffer->err_begin(), Buffer->err_end(),
+ "error", false) +
+ PrintProblem(Diags, 0,
+ Buffer->warn_begin(), Buffer->warn_end(),
+ "warn", false) +
+ PrintProblem(Diags, 0,
+ Buffer->note_begin(), Buffer->note_end(),
+ "note", false));
+ }
+
+ Diags.takeClient();
+ Diags.setClient(CurClient);
+
+ // Reset the buffer, we have processed all the diagnostics in it.
+ Buffer.reset(new TextDiagnosticBuffer());
+}
+
+Directive* Directive::Create(bool RegexKind, const SourceLocation &Location,
+ const std::string &Text, unsigned Count) {
+ if (RegexKind)
+ return new RegexDirective(Location, Text, Count);
+ return new StandardDirective(Location, Text, Count);
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Warnings.cpp b/contrib/llvm/tools/clang/lib/Frontend/Warnings.cpp
new file mode 100644
index 0000000..8cc5616
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/Warnings.cpp
@@ -0,0 +1,133 @@
+//===--- Warnings.cpp - C-Language Front-end ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Command line warning options handler.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is responsible for handling all warning options. This includes
+// a number of -Wfoo options and their variants, which are driven by TableGen-
+// generated data, and the special cases -pedantic, -pedantic-errors, -w,
+// -Werror and -Wfatal-errors.
+//
+// Each warning option controls any number of actual warnings.
+// Given a warning option 'foo', the following are valid:
+// -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo
+//
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include <cstring>
+#include <utility>
+#include <algorithm>
+using namespace clang;
+
+void clang::ProcessWarningOptions(Diagnostic &Diags,
+ const DiagnosticOptions &Opts) {
+ Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
+ Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
+ Diags.setShowOverloads(
+ static_cast<Diagnostic::OverloadsShown>(Opts.ShowOverloads));
+
+ // Handle -ferror-limit
+ if (Opts.ErrorLimit)
+ Diags.setErrorLimit(Opts.ErrorLimit);
+ if (Opts.TemplateBacktraceLimit)
+ Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit);
+
+ // If -pedantic or -pedantic-errors was specified, then we want to map all
+ // extension diagnostics onto WARNING or ERROR unless the user has futz'd
+ // around with them explicitly.
+ if (Opts.PedanticErrors)
+ Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Error);
+ else if (Opts.Pedantic)
+ Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn);
+ else
+ Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore);
+
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+ const std::string &Opt = Opts.Warnings[i];
+ const char *OptStart = &Opt[0];
+ const char *OptEnd = OptStart+Opt.size();
+ assert(*OptEnd == 0 && "Expect null termination for lower-bound search");
+
+ // Check to see if this warning starts with "no-", if so, this is a negative
+ // form of the option.
+ bool isPositive = true;
+ if (OptEnd-OptStart > 3 && memcmp(OptStart, "no-", 3) == 0) {
+ isPositive = false;
+ OptStart += 3;
+ }
+
+ // Figure out how this option affects the warning. If -Wfoo, map the
+ // diagnostic to a warning, if -Wno-foo, map it to ignore.
+ diag::Mapping Mapping = isPositive ? diag::MAP_WARNING : diag::MAP_IGNORE;
+
+ // -Wsystem-headers is a special case, not driven by the option table. It
+ // cannot be controlled with -Werror.
+ if (OptEnd-OptStart == 14 && memcmp(OptStart, "system-headers", 14) == 0) {
+ Diags.setSuppressSystemWarnings(!isPositive);
+ continue;
+ }
+
+ // -Werror/-Wno-error is a special case, not controlled by the option table.
+ // It also has the "specifier" form of -Werror=foo and -Werror-foo.
+ if (OptEnd-OptStart >= 5 && memcmp(OptStart, "error", 5) == 0) {
+ const char *Specifier = 0;
+ if (OptEnd-OptStart != 5) { // Specifier must be present.
+ if ((OptStart[5] != '=' && OptStart[5] != '-') ||
+ OptEnd-OptStart == 6) {
+ Diags.Report(diag::warn_unknown_warning_specifier)
+ << "-Werror" << ("-W" + Opt);
+ continue;
+ }
+ Specifier = OptStart+6;
+ }
+
+ if (Specifier == 0) {
+ Diags.setWarningsAsErrors(isPositive);
+ continue;
+ }
+
+ // -Werror=foo maps foo to Error, -Wno-error=foo maps it to Warning.
+ Mapping = isPositive ? diag::MAP_ERROR : diag::MAP_WARNING_NO_WERROR;
+ OptStart = Specifier;
+ }
+
+ // -Wfatal-errors is yet another special case.
+ if (OptEnd-OptStart >= 12 && memcmp(OptStart, "fatal-errors", 12) == 0) {
+ const char* Specifier = 0;
+ if (OptEnd-OptStart != 12) {
+ if ((OptStart[12] != '=' && OptStart[12] != '-') ||
+ OptEnd-OptStart == 13) {
+ Diags.Report(diag::warn_unknown_warning_specifier)
+ << "-Wfatal-errors" << ("-W" + Opt);
+ continue;
+ }
+ Specifier = OptStart + 13;
+ }
+
+ if (Specifier == 0) {
+ Diags.setErrorsAsFatal(isPositive);
+ continue;
+ }
+
+ // -Wfatal-errors=foo maps foo to Fatal, -Wno-fatal-errors=foo
+ // maps it to Error.
+ Mapping = isPositive ? diag::MAP_FATAL : diag::MAP_ERROR_NO_WFATAL;
+ OptStart = Specifier;
+ }
+
+ if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
+ Diags.Report(diag::warn_unknown_warning_option) << ("-W" + Opt);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
new file mode 100644
index 0000000..4bb85e7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -0,0 +1,155 @@
+//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds ExecuteCompilerInvocation(). It is split into its own file to
+// minimize the impact of pulling in essentially everything else in Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/FrontendTool/Utils.h"
+#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Rewrite/FrontendActions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/DynamicLibrary.h"
+using namespace clang;
+
+static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
+ using namespace clang::frontend;
+
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ llvm_unreachable("Invalid program action!");
+
+ case ASTDump: return new ASTDumpAction();
+ case ASTDumpXML: return new ASTDumpXMLAction();
+ case ASTPrint: return new ASTPrintAction();
+ case ASTPrintXML: return new ASTPrintXMLAction();
+ case ASTView: return new ASTViewAction();
+ case BoostCon: return new BoostConAction();
+ case CreateModule: return 0;
+ case DumpRawTokens: return new DumpRawTokensAction();
+ case DumpTokens: return new DumpTokensAction();
+ case EmitAssembly: return new EmitAssemblyAction();
+ case EmitBC: return new EmitBCAction();
+ case EmitHTML: return new HTMLPrintAction();
+ case EmitLLVM: return new EmitLLVMAction();
+ case EmitLLVMOnly: return new EmitLLVMOnlyAction();
+ case EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
+ case EmitObj: return new EmitObjAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InitOnly: return new InitOnlyAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+
+ case PluginAction: {
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().ActionName) {
+ llvm::OwningPtr<PluginASTAction> P(it->instantiate());
+ if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
+ return 0;
+ return P.take();
+ }
+ }
+
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+ << CI.getFrontendOpts().ActionName;
+ return 0;
+ }
+
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreamble: return new PrintPreambleAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteObjC: return new RewriteObjCAction();
+ case RewriteTest: return new RewriteTestAction();
+ case RunAnalysis: return new ento::AnalysisAction();
+ case RunPreprocessorOnly: return new PreprocessOnlyAction();
+ }
+}
+
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+ // Create the underlying action.
+ FrontendAction *Act = CreateFrontendBaseAction(CI);
+ if (!Act)
+ return 0;
+
+ // If there are any AST files to merge, create a frontend action
+ // adaptor to perform the merge.
+ if (!CI.getFrontendOpts().ASTMergeFiles.empty())
+ Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
+ CI.getFrontendOpts().ASTMergeFiles.size());
+
+ return Act;
+}
+
+bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
+ // Honor -help.
+ if (Clang->getFrontendOpts().ShowHelp) {
+ llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
+ Opts->PrintHelp(llvm::outs(), "clang -cc1",
+ "LLVM 'Clang' Compiler: http://clang.llvm.org");
+ return 0;
+ }
+
+ // Honor -version.
+ //
+ // FIXME: Use a better -version message?
+ if (Clang->getFrontendOpts().ShowVersion) {
+ llvm::cl::PrintVersionMessage();
+ return 0;
+ }
+
+ // Honor -mllvm.
+ //
+ // FIXME: Remove this, one day.
+ if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
+ unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
+ const char **Args = new const char*[NumArgs + 2];
+ Args[0] = "clang (LLVM option parsing)";
+ for (unsigned i = 0; i != NumArgs; ++i)
+ Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
+ Args[NumArgs + 1] = 0;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
+ }
+
+ // Load any requested plugins.
+ for (unsigned i = 0,
+ e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) {
+ const std::string &Path = Clang->getFrontendOpts().Plugins[i];
+ std::string Error;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
+ Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
+ << Path << Error;
+ }
+
+ // If there were errors in processing arguments, don't do anything else.
+ bool Success = false;
+ if (!Clang->getDiagnostics().hasErrorOccurred()) {
+ // Create and execute the frontend action.
+ llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(*Clang));
+ if (Act) {
+ Success = Clang->ExecuteAction(*Act);
+ if (Clang->getFrontendOpts().DisableFree)
+ Act.take();
+ }
+ }
+
+ return Success;
+}
diff --git a/contrib/llvm/tools/clang/lib/Headers/altivec.h b/contrib/llvm/tools/clang/lib/Headers/altivec.h
new file mode 100644
index 0000000..a225378
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/altivec.h
@@ -0,0 +1,11856 @@
+/*===---- altivec.h - Standard header for type generic math ---------------===*\
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __ALTIVEC_H
+#define __ALTIVEC_H
+
+#ifndef __ALTIVEC__
+#error "AltiVec support not enabled"
+#endif
+
+/* constants for mapping CR6 bits to predicate result. */
+
+#define __CR6_EQ 0
+#define __CR6_EQ_REV 1
+#define __CR6_LT 2
+#define __CR6_LT_REV 3
+
+#define __ATTRS_o_ai __attribute__((__overloadable__, __always_inline__))
+
+static vector signed char __ATTRS_o_ai
+vec_perm(vector signed char a, vector signed char b, vector unsigned char c);
+
+static vector unsigned char __ATTRS_o_ai
+vec_perm(vector unsigned char a,
+ vector unsigned char b,
+ vector unsigned char c);
+
+static vector bool char __ATTRS_o_ai
+vec_perm(vector bool char a, vector bool char b, vector unsigned char c);
+
+static vector short __ATTRS_o_ai
+vec_perm(vector short a, vector short b, vector unsigned char c);
+
+static vector unsigned short __ATTRS_o_ai
+vec_perm(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned char c);
+
+static vector bool short __ATTRS_o_ai
+vec_perm(vector bool short a, vector bool short b, vector unsigned char c);
+
+static vector pixel __ATTRS_o_ai
+vec_perm(vector pixel a, vector pixel b, vector unsigned char c);
+
+static vector int __ATTRS_o_ai
+vec_perm(vector int a, vector int b, vector unsigned char c);
+
+static vector unsigned int __ATTRS_o_ai
+vec_perm(vector unsigned int a, vector unsigned int b, vector unsigned char c);
+
+static vector bool int __ATTRS_o_ai
+vec_perm(vector bool int a, vector bool int b, vector unsigned char c);
+
+static vector float __ATTRS_o_ai
+vec_perm(vector float a, vector float b, vector unsigned char c);
+
+/* vec_abs */
+
+#define __builtin_altivec_abs_v16qi vec_abs
+#define __builtin_altivec_abs_v8hi vec_abs
+#define __builtin_altivec_abs_v4si vec_abs
+
+static vector signed char __ATTRS_o_ai
+vec_abs(vector signed char a)
+{
+ return __builtin_altivec_vmaxsb(a, -a);
+}
+
+static vector signed short __ATTRS_o_ai
+vec_abs(vector signed short a)
+{
+ return __builtin_altivec_vmaxsh(a, -a);
+}
+
+static vector signed int __ATTRS_o_ai
+vec_abs(vector signed int a)
+{
+ return __builtin_altivec_vmaxsw(a, -a);
+}
+
+static vector float __ATTRS_o_ai
+vec_abs(vector float a)
+{
+ vector unsigned int res = (vector unsigned int)a
+ & (vector unsigned int)(0x7FFFFFFF);
+ return (vector float)res;
+}
+
+/* vec_abss */
+
+#define __builtin_altivec_abss_v16qi vec_abss
+#define __builtin_altivec_abss_v8hi vec_abss
+#define __builtin_altivec_abss_v4si vec_abss
+
+static vector signed char __ATTRS_o_ai
+vec_abss(vector signed char a)
+{
+ return __builtin_altivec_vmaxsb
+ (a, __builtin_altivec_vsubsbs((vector signed char)(0), a));
+}
+
+static vector signed short __ATTRS_o_ai
+vec_abss(vector signed short a)
+{
+ return __builtin_altivec_vmaxsh
+ (a, __builtin_altivec_vsubshs((vector signed short)(0), a));
+}
+
+static vector signed int __ATTRS_o_ai
+vec_abss(vector signed int a)
+{
+ return __builtin_altivec_vmaxsw
+ (a, __builtin_altivec_vsubsws((vector signed int)(0), a));
+}
+
+/* vec_add */
+
+static vector signed char __ATTRS_o_ai
+vec_add(vector signed char a, vector signed char b)
+{
+ return a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_add(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_add(vector signed char a, vector bool char b)
+{
+ return a + (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_add(vector unsigned char a, vector unsigned char b)
+{
+ return a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_add(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_add(vector unsigned char a, vector bool char b)
+{
+ return a + (vector unsigned char)b;
+}
+
+static vector short __ATTRS_o_ai
+vec_add(vector short a, vector short b)
+{
+ return a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_add(vector bool short a, vector short b)
+{
+ return (vector short)a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_add(vector short a, vector bool short b)
+{
+ return a + (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_add(vector unsigned short a, vector unsigned short b)
+{
+ return a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_add(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_add(vector unsigned short a, vector bool short b)
+{
+ return a + (vector unsigned short)b;
+}
+
+static vector int __ATTRS_o_ai
+vec_add(vector int a, vector int b)
+{
+ return a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_add(vector bool int a, vector int b)
+{
+ return (vector int)a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_add(vector int a, vector bool int b)
+{
+ return a + (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_add(vector unsigned int a, vector unsigned int b)
+{
+ return a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_add(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_add(vector unsigned int a, vector bool int b)
+{
+ return a + (vector unsigned int)b;
+}
+
+static vector float __ATTRS_o_ai
+vec_add(vector float a, vector float b)
+{
+ return a + b;
+}
+
+/* vec_vaddubm */
+
+#define __builtin_altivec_vaddubm vec_vaddubm
+
+static vector signed char __ATTRS_o_ai
+vec_vaddubm(vector signed char a, vector signed char b)
+{
+ return a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddubm(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddubm(vector signed char a, vector bool char b)
+{
+ return a + (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubm(vector unsigned char a, vector unsigned char b)
+{
+ return a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubm(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubm(vector unsigned char a, vector bool char b)
+{
+ return a + (vector unsigned char)b;
+}
+
+/* vec_vadduhm */
+
+#define __builtin_altivec_vadduhm vec_vadduhm
+
+static vector short __ATTRS_o_ai
+vec_vadduhm(vector short a, vector short b)
+{
+ return a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vadduhm(vector bool short a, vector short b)
+{
+ return (vector short)a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vadduhm(vector short a, vector bool short b)
+{
+ return a + (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhm(vector unsigned short a, vector unsigned short b)
+{
+ return a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhm(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhm(vector unsigned short a, vector bool short b)
+{
+ return a + (vector unsigned short)b;
+}
+
+/* vec_vadduwm */
+
+#define __builtin_altivec_vadduwm vec_vadduwm
+
+static vector int __ATTRS_o_ai
+vec_vadduwm(vector int a, vector int b)
+{
+ return a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vadduwm(vector bool int a, vector int b)
+{
+ return (vector int)a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vadduwm(vector int a, vector bool int b)
+{
+ return a + (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduwm(vector unsigned int a, vector unsigned int b)
+{
+ return a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduwm(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduwm(vector unsigned int a, vector bool int b)
+{
+ return a + (vector unsigned int)b;
+}
+
+/* vec_vaddfp */
+
+#define __builtin_altivec_vaddfp vec_vaddfp
+
+static vector float __attribute__((__always_inline__))
+vec_vaddfp(vector float a, vector float b)
+{
+ return a + b;
+}
+
+/* vec_addc */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_addc(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vaddcuw(a, b);
+}
+
+/* vec_vaddcuw */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vaddcuw(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vaddcuw(a, b);
+}
+
+/* vec_adds */
+
+static vector signed char __ATTRS_o_ai
+vec_adds(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_adds(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_adds(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vaddsbs(a, (vector signed char)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_adds(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_adds(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_adds(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vaddubs(a, (vector unsigned char)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_adds(vector short a, vector short b)
+{
+ return __builtin_altivec_vaddshs(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_adds(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vaddshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_adds(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vaddshs(a, (vector short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_adds(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_adds(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_adds(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vadduhs(a, (vector unsigned short)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_adds(vector int a, vector int b)
+{
+ return __builtin_altivec_vaddsws(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_adds(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vaddsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_adds(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vaddsws(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_adds(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_adds(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_adds(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vadduws(a, (vector unsigned int)b);
+}
+
+/* vec_vaddsbs */
+
+static vector signed char __ATTRS_o_ai
+vec_vaddsbs(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddsbs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddsbs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vaddsbs(a, (vector signed char)b);
+}
+
+/* vec_vaddubs */
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubs(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vaddubs(a, (vector unsigned char)b);
+}
+
+/* vec_vaddshs */
+
+static vector short __ATTRS_o_ai
+vec_vaddshs(vector short a, vector short b)
+{
+ return __builtin_altivec_vaddshs(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vaddshs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vaddshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vaddshs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vaddshs(a, (vector short)b);
+}
+
+/* vec_vadduhs */
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhs(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vadduhs(a, (vector unsigned short)b);
+}
+
+/* vec_vaddsws */
+
+static vector int __ATTRS_o_ai
+vec_vaddsws(vector int a, vector int b)
+{
+ return __builtin_altivec_vaddsws(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vaddsws(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vaddsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vaddsws(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vaddsws(a, (vector int)b);
+}
+
+/* vec_vadduws */
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduws(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduws(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduws(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vadduws(a, (vector unsigned int)b);
+}
+
+/* vec_and */
+
+#define __builtin_altivec_vand vec_and
+
+static vector signed char __ATTRS_o_ai
+vec_and(vector signed char a, vector signed char b)
+{
+ return a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_and(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_and(vector signed char a, vector bool char b)
+{
+ return a & (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_and(vector unsigned char a, vector unsigned char b)
+{
+ return a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_and(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_and(vector unsigned char a, vector bool char b)
+{
+ return a & (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_and(vector bool char a, vector bool char b)
+{
+ return a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_and(vector short a, vector short b)
+{
+ return a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_and(vector bool short a, vector short b)
+{
+ return (vector short)a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_and(vector short a, vector bool short b)
+{
+ return a & (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_and(vector unsigned short a, vector unsigned short b)
+{
+ return a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_and(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_and(vector unsigned short a, vector bool short b)
+{
+ return a & (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_and(vector bool short a, vector bool short b)
+{
+ return a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_and(vector int a, vector int b)
+{
+ return a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_and(vector bool int a, vector int b)
+{
+ return (vector int)a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_and(vector int a, vector bool int b)
+{
+ return a & (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_and(vector unsigned int a, vector unsigned int b)
+{
+ return a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_and(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_and(vector unsigned int a, vector bool int b)
+{
+ return a & (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_and(vector bool int a, vector bool int b)
+{
+ return a & b;
+}
+
+static vector float __ATTRS_o_ai
+vec_and(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_and(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_and(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_vand */
+
+static vector signed char __ATTRS_o_ai
+vec_vand(vector signed char a, vector signed char b)
+{
+ return a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vand(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vand(vector signed char a, vector bool char b)
+{
+ return a & (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vand(vector unsigned char a, vector unsigned char b)
+{
+ return a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vand(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vand(vector unsigned char a, vector bool char b)
+{
+ return a & (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vand(vector bool char a, vector bool char b)
+{
+ return a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vand(vector short a, vector short b)
+{
+ return a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vand(vector bool short a, vector short b)
+{
+ return (vector short)a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vand(vector short a, vector bool short b)
+{
+ return a & (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vand(vector unsigned short a, vector unsigned short b)
+{
+ return a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vand(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vand(vector unsigned short a, vector bool short b)
+{
+ return a & (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vand(vector bool short a, vector bool short b)
+{
+ return a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vand(vector int a, vector int b)
+{
+ return a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vand(vector bool int a, vector int b)
+{
+ return (vector int)a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vand(vector int a, vector bool int b)
+{
+ return a & (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vand(vector unsigned int a, vector unsigned int b)
+{
+ return a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vand(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vand(vector unsigned int a, vector bool int b)
+{
+ return a & (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vand(vector bool int a, vector bool int b)
+{
+ return a & b;
+}
+
+static vector float __ATTRS_o_ai
+vec_vand(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vand(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vand(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_andc */
+
+#define __builtin_altivec_vandc vec_andc
+
+static vector signed char __ATTRS_o_ai
+vec_andc(vector signed char a, vector signed char b)
+{
+ return a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_andc(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_andc(vector signed char a, vector bool char b)
+{
+ return a & ~(vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_andc(vector unsigned char a, vector unsigned char b)
+{
+ return a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_andc(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_andc(vector unsigned char a, vector bool char b)
+{
+ return a & ~(vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_andc(vector bool char a, vector bool char b)
+{
+ return a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_andc(vector short a, vector short b)
+{
+ return a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_andc(vector bool short a, vector short b)
+{
+ return (vector short)a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_andc(vector short a, vector bool short b)
+{
+ return a & ~(vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_andc(vector unsigned short a, vector unsigned short b)
+{
+ return a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_andc(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_andc(vector unsigned short a, vector bool short b)
+{
+ return a & ~(vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_andc(vector bool short a, vector bool short b)
+{
+ return a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_andc(vector int a, vector int b)
+{
+ return a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_andc(vector bool int a, vector int b)
+{
+ return (vector int)a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_andc(vector int a, vector bool int b)
+{
+ return a & ~(vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_andc(vector unsigned int a, vector unsigned int b)
+{
+ return a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_andc(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_andc(vector unsigned int a, vector bool int b)
+{
+ return a & ~(vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_andc(vector bool int a, vector bool int b)
+{
+ return a & ~b;
+}
+
+static vector float __ATTRS_o_ai
+vec_andc(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_andc(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_andc(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_vandc */
+
+static vector signed char __ATTRS_o_ai
+vec_vandc(vector signed char a, vector signed char b)
+{
+ return a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vandc(vector signed char a, vector bool char b)
+{
+ return a & ~(vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vandc(vector unsigned char a, vector unsigned char b)
+{
+ return a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vandc(vector unsigned char a, vector bool char b)
+{
+ return a & ~(vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector bool char b)
+{
+ return a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vandc(vector short a, vector short b)
+{
+ return a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector short b)
+{
+ return (vector short)a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vandc(vector short a, vector bool short b)
+{
+ return a & ~(vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vandc(vector unsigned short a, vector unsigned short b)
+{
+ return a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vandc(vector unsigned short a, vector bool short b)
+{
+ return a & ~(vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector bool short b)
+{
+ return a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vandc(vector int a, vector int b)
+{
+ return a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector int b)
+{
+ return (vector int)a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vandc(vector int a, vector bool int b)
+{
+ return a & ~(vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vandc(vector unsigned int a, vector unsigned int b)
+{
+ return a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vandc(vector unsigned int a, vector bool int b)
+{
+ return a & ~(vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector bool int b)
+{
+ return a & ~b;
+}
+
+static vector float __ATTRS_o_ai
+vec_vandc(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vandc(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vandc(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_avg */
+
+static vector signed char __ATTRS_o_ai
+vec_avg(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vavgsb(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_avg(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vavgub(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_avg(vector short a, vector short b)
+{
+ return __builtin_altivec_vavgsh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_avg(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vavguh(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_avg(vector int a, vector int b)
+{
+ return __builtin_altivec_vavgsw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_avg(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vavguw(a, b);
+}
+
+/* vec_vavgsb */
+
+static vector signed char __attribute__((__always_inline__))
+vec_vavgsb(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vavgsb(a, b);
+}
+
+/* vec_vavgub */
+
+static vector unsigned char __attribute__((__always_inline__))
+vec_vavgub(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vavgub(a, b);
+}
+
+/* vec_vavgsh */
+
+static vector short __attribute__((__always_inline__))
+vec_vavgsh(vector short a, vector short b)
+{
+ return __builtin_altivec_vavgsh(a, b);
+}
+
+/* vec_vavguh */
+
+static vector unsigned short __attribute__((__always_inline__))
+vec_vavguh(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vavguh(a, b);
+}
+
+/* vec_vavgsw */
+
+static vector int __attribute__((__always_inline__))
+vec_vavgsw(vector int a, vector int b)
+{
+ return __builtin_altivec_vavgsw(a, b);
+}
+
+/* vec_vavguw */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vavguw(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vavguw(a, b);
+}
+
+/* vec_ceil */
+
+static vector float __attribute__((__always_inline__))
+vec_ceil(vector float a)
+{
+ return __builtin_altivec_vrfip(a);
+}
+
+/* vec_vrfip */
+
+static vector float __attribute__((__always_inline__))
+vec_vrfip(vector float a)
+{
+ return __builtin_altivec_vrfip(a);
+}
+
+/* vec_cmpb */
+
+static vector int __attribute__((__always_inline__))
+vec_cmpb(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpbfp(a, b);
+}
+
+/* vec_vcmpbfp */
+
+static vector int __attribute__((__always_inline__))
+vec_vcmpbfp(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpbfp(a, b);
+}
+
+/* vec_cmpeq */
+
+static vector bool char __ATTRS_o_ai
+vec_cmpeq(vector signed char a, vector signed char b)
+{
+ return (vector bool char)
+ __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_cmpeq(vector unsigned char a, vector unsigned char b)
+{
+ return (vector bool char)
+ __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpeq(vector short a, vector short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpequh(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpeq(vector unsigned short a, vector unsigned short b)
+{
+ return (vector bool short)
+ __builtin_altivec_vcmpequh((vector short)a, (vector short)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpeq(vector int a, vector int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpequw(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpeq(vector unsigned int a, vector unsigned int b)
+{
+ return (vector bool int)
+ __builtin_altivec_vcmpequw((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpeq(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpeqfp(a, b);
+}
+
+/* vec_cmpge */
+
+static vector bool int __attribute__((__always_inline__))
+vec_cmpge(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgefp(a, b);
+}
+
+/* vec_vcmpgefp */
+
+static vector bool int __attribute__((__always_inline__))
+vec_vcmpgefp(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgefp(a, b);
+}
+
+/* vec_cmpgt */
+
+static vector bool char __ATTRS_o_ai
+vec_cmpgt(vector signed char a, vector signed char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtsb(a, b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_cmpgt(vector unsigned char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtub(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpgt(vector short a, vector short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtsh(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpgt(vector unsigned short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtuh(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpgt(vector int a, vector int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtsw(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpgt(vector unsigned int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtuw(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpgt(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtfp(a, b);
+}
+
+/* vec_vcmpgtsb */
+
+static vector bool char __attribute__((__always_inline__))
+vec_vcmpgtsb(vector signed char a, vector signed char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtsb(a, b);
+}
+
+/* vec_vcmpgtub */
+
+static vector bool char __attribute__((__always_inline__))
+vec_vcmpgtub(vector unsigned char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtub(a, b);
+}
+
+/* vec_vcmpgtsh */
+
+static vector bool short __attribute__((__always_inline__))
+vec_vcmpgtsh(vector short a, vector short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtsh(a, b);
+}
+
+/* vec_vcmpgtuh */
+
+static vector bool short __attribute__((__always_inline__))
+vec_vcmpgtuh(vector unsigned short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtuh(a, b);
+}
+
+/* vec_vcmpgtsw */
+
+static vector bool int __attribute__((__always_inline__))
+vec_vcmpgtsw(vector int a, vector int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtsw(a, b);
+}
+
+/* vec_vcmpgtuw */
+
+static vector bool int __attribute__((__always_inline__))
+vec_vcmpgtuw(vector unsigned int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtuw(a, b);
+}
+
+/* vec_vcmpgtfp */
+
+static vector bool int __attribute__((__always_inline__))
+vec_vcmpgtfp(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtfp(a, b);
+}
+
+/* vec_cmple */
+
+static vector bool int __attribute__((__always_inline__))
+vec_cmple(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgefp(b, a);
+}
+
+/* vec_cmplt */
+
+static vector bool char __ATTRS_o_ai
+vec_cmplt(vector signed char a, vector signed char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtsb(b, a);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_cmplt(vector unsigned char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vcmpgtub(b, a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmplt(vector short a, vector short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtsh(b, a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmplt(vector unsigned short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vcmpgtuh(b, a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmplt(vector int a, vector int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtsw(b, a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmplt(vector unsigned int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtuw(b, a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmplt(vector float a, vector float b)
+{
+ return (vector bool int)__builtin_altivec_vcmpgtfp(b, a);
+}
+
+/* vec_ctf */
+
+static vector float __ATTRS_o_ai
+vec_ctf(vector int a, int b)
+{
+ return __builtin_altivec_vcfsx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_ctf(vector unsigned int a, int b)
+{
+ return __builtin_altivec_vcfux((vector int)a, b);
+}
+
+/* vec_vcfsx */
+
+static vector float __attribute__((__always_inline__))
+vec_vcfsx(vector int a, int b)
+{
+ return __builtin_altivec_vcfsx(a, b);
+}
+
+/* vec_vcfux */
+
+static vector float __attribute__((__always_inline__))
+vec_vcfux(vector unsigned int a, int b)
+{
+ return __builtin_altivec_vcfux((vector int)a, b);
+}
+
+/* vec_cts */
+
+static vector int __attribute__((__always_inline__))
+vec_cts(vector float a, int b)
+{
+ return __builtin_altivec_vctsxs(a, b);
+}
+
+/* vec_vctsxs */
+
+static vector int __attribute__((__always_inline__))
+vec_vctsxs(vector float a, int b)
+{
+ return __builtin_altivec_vctsxs(a, b);
+}
+
+/* vec_ctu */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_ctu(vector float a, int b)
+{
+ return __builtin_altivec_vctuxs(a, b);
+}
+
+/* vec_vctuxs */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vctuxs(vector float a, int b)
+{
+ return __builtin_altivec_vctuxs(a, b);
+}
+
+/* vec_dss */
+
+static void __attribute__((__always_inline__))
+vec_dss(int a)
+{
+ __builtin_altivec_dss(a);
+}
+
+/* vec_dssall */
+
+static void __attribute__((__always_inline__))
+vec_dssall(void)
+{
+ __builtin_altivec_dssall();
+}
+
+/* vec_dst */
+
+static void __attribute__((__always_inline__))
+vec_dst(const void *a, int b, int c)
+{
+ __builtin_altivec_dst(a, b, c);
+}
+
+/* vec_dstst */
+
+static void __attribute__((__always_inline__))
+vec_dstst(const void *a, int b, int c)
+{
+ __builtin_altivec_dstst(a, b, c);
+}
+
+/* vec_dststt */
+
+static void __attribute__((__always_inline__))
+vec_dststt(const void *a, int b, int c)
+{
+ __builtin_altivec_dststt(a, b, c);
+}
+
+/* vec_dstt */
+
+static void __attribute__((__always_inline__))
+vec_dstt(const void *a, int b, int c)
+{
+ __builtin_altivec_dstt(a, b, c);
+}
+
+/* vec_expte */
+
+static vector float __attribute__((__always_inline__))
+vec_expte(vector float a)
+{
+ return __builtin_altivec_vexptefp(a);
+}
+
+/* vec_vexptefp */
+
+static vector float __attribute__((__always_inline__))
+vec_vexptefp(vector float a)
+{
+ return __builtin_altivec_vexptefp(a);
+}
+
+/* vec_floor */
+
+static vector float __attribute__((__always_inline__))
+vec_floor(vector float a)
+{
+ return __builtin_altivec_vrfim(a);
+}
+
+/* vec_vrfim */
+
+static vector float __attribute__((__always_inline__))
+vec_vrfim(vector float a)
+{
+ return __builtin_altivec_vrfim(a);
+}
+
+/* vec_ld */
+
+static vector signed char __ATTRS_o_ai
+vec_ld(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvx(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_ld(int a, const signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_ld(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_ld(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_ld(int a, const vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvx(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_ld(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvx(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_ld(int a, const short *b)
+{
+ return (vector short)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_ld(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_ld(int a, const unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_ld(int a, const vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvx(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_ld(int a, const vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvx(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_ld(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvx(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_ld(int a, const int *b)
+{
+ return (vector int)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_ld(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_ld(int a, const unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_ld(int a, const vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_ld(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_ld(int a, const float *b)
+{
+ return (vector float)__builtin_altivec_lvx(a, b);
+}
+
+/* vec_lvx */
+
+static vector signed char __ATTRS_o_ai
+vec_lvx(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvx(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvx(int a, const signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvx(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvx(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvx(int a, const vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvx(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_lvx(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvx(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_lvx(int a, const short *b)
+{
+ return (vector short)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvx(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvx(int a, const unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvx(int a, const vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvx(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvx(int a, const vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvx(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_lvx(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvx(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_lvx(int a, const int *b)
+{
+ return (vector int)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvx(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvx(int a, const unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvx(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvx(int a, const vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lvx(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lvx(int a, const float *b)
+{
+ return (vector float)__builtin_altivec_lvx(a, b);
+}
+
+/* vec_lde */
+
+static vector signed char __ATTRS_o_ai
+vec_lde(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvebx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lde(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvebx(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_lde(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvehx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lde(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvehx(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_lde(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvewx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lde(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvewx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lde(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvewx(a, b);
+}
+
+/* vec_lvebx */
+
+static vector signed char __ATTRS_o_ai
+vec_lvebx(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvebx(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvebx(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvebx(a, b);
+}
+
+/* vec_lvehx */
+
+static vector short __ATTRS_o_ai
+vec_lvehx(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvehx(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvehx(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvehx(a, b);
+}
+
+/* vec_lvewx */
+
+static vector int __ATTRS_o_ai
+vec_lvewx(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvewx(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvewx(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvewx(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lvewx(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvewx(a, b);
+}
+
+/* vec_ldl */
+
+static vector signed char __ATTRS_o_ai
+vec_ldl(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_ldl(int a, const signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_ldl(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_ldl(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_ldl(int a, const vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_ldl(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_ldl(int a, const short *b)
+{
+ return (vector short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_ldl(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_ldl(int a, const unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_ldl(int a, const vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_ldl(int a, const vector pixel *b)
+{
+ return (vector pixel short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_ldl(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_ldl(int a, const int *b)
+{
+ return (vector int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_ldl(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_ldl(int a, const unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_ldl(int a, const vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_ldl(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvxl(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_ldl(int a, const float *b)
+{
+ return (vector float)__builtin_altivec_lvxl(a, b);
+}
+
+/* vec_lvxl */
+
+static vector signed char __ATTRS_o_ai
+vec_lvxl(int a, const vector signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvxl(int a, const signed char *b)
+{
+ return (vector signed char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvxl(int a, const vector unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvxl(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvxl(int a, const vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvxl(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_lvxl(int a, const vector short *b)
+{
+ return (vector short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_lvxl(int a, const short *b)
+{
+ return (vector short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvxl(int a, const vector unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvxl(int a, const unsigned short *b)
+{
+ return (vector unsigned short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvxl(int a, const vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvxl(int a, const vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvxl(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_lvxl(int a, const vector int *b)
+{
+ return (vector int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_lvxl(int a, const int *b)
+{
+ return (vector int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvxl(int a, const vector unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvxl(int a, const unsigned int *b)
+{
+ return (vector unsigned int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvxl(int a, const vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvxl(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lvxl(int a, const vector float *b)
+{
+ return (vector float)__builtin_altivec_lvxl(a, b);
+}
+
+static vector float __ATTRS_o_ai
+vec_lvxl(int a, const float *b)
+{
+ return (vector float)__builtin_altivec_lvxl(a, b);
+}
+
+/* vec_loge */
+
+static vector float __attribute__((__always_inline__))
+vec_loge(vector float a)
+{
+ return __builtin_altivec_vlogefp(a);
+}
+
+/* vec_vlogefp */
+
+static vector float __attribute__((__always_inline__))
+vec_vlogefp(vector float a)
+{
+ return __builtin_altivec_vlogefp(a);
+}
+
+/* vec_lvsl */
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const signed char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const short *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const unsigned short *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const int *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const unsigned int *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsl(int a, const float *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsl(a, b);
+}
+
+/* vec_lvsr */
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const signed char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const unsigned char *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const short *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const unsigned short *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const int *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const unsigned int *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvsr(int a, const float *b)
+{
+ return (vector unsigned char)__builtin_altivec_lvsr(a, b);
+}
+
+/* vec_madd */
+
+static vector float __attribute__((__always_inline__))
+vec_madd(vector float a, vector float b, vector float c)
+{
+ return __builtin_altivec_vmaddfp(a, b, c);
+}
+
+/* vec_vmaddfp */
+
+static vector float __attribute__((__always_inline__))
+vec_vmaddfp(vector float a, vector float b, vector float c)
+{
+ return __builtin_altivec_vmaddfp(a, b, c);
+}
+
+/* vec_madds */
+
+static vector signed short __attribute__((__always_inline__))
+vec_madds(vector signed short a, vector signed short b, vector signed short c)
+{
+ return __builtin_altivec_vmhaddshs(a, b, c);
+}
+
+/* vec_vmhaddshs */
+static vector signed short __attribute__((__always_inline__))
+vec_vmhaddshs(vector signed short a,
+ vector signed short b,
+ vector signed short c)
+{
+ return __builtin_altivec_vmhaddshs(a, b, c);
+}
+
+/* vec_max */
+
+static vector signed char __ATTRS_o_ai
+vec_max(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_max(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_max(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxsb(a, (vector signed char)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_max(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_max(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_max(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxub(a, (vector unsigned char)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_max(vector short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_max(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_max(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxsh(a, (vector short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_max(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_max(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_max(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxuh(a, (vector unsigned short)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_max(vector int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_max(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_max(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxsw(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_max(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_max(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_max(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxuw(a, (vector unsigned int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_max(vector float a, vector float b)
+{
+ return __builtin_altivec_vmaxfp(a, b);
+}
+
+/* vec_vmaxsb */
+
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxsb(a, (vector signed char)b);
+}
+
+/* vec_vmaxub */
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxub(a, (vector unsigned char)b);
+}
+
+/* vec_vmaxsh */
+
+static vector short __ATTRS_o_ai
+vec_vmaxsh(vector short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vmaxsh(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vmaxsh(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxsh(a, (vector short)b);
+}
+
+/* vec_vmaxuh */
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmaxuh(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmaxuh(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmaxuh(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxuh(a, (vector unsigned short)b);
+}
+
+/* vec_vmaxsw */
+
+static vector int __ATTRS_o_ai
+vec_vmaxsw(vector int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vmaxsw(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vmaxsw(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxsw(a, (vector int)b);
+}
+
+/* vec_vmaxuw */
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmaxuw(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmaxuw(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmaxuw(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxuw(a, (vector unsigned int)b);
+}
+
+/* vec_vmaxfp */
+
+static vector float __attribute__((__always_inline__))
+vec_vmaxfp(vector float a, vector float b)
+{
+ return __builtin_altivec_vmaxfp(a, b);
+}
+
+/* vec_mergeh */
+
+static vector signed char __ATTRS_o_ai
+vec_mergeh(vector signed char a, vector signed char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_mergeh(vector unsigned char a, vector unsigned char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_mergeh(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+static vector short __ATTRS_o_ai
+vec_mergeh(vector short a, vector short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_mergeh(vector unsigned short a, vector unsigned short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_mergeh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_mergeh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector int __ATTRS_o_ai
+vec_mergeh(vector int a, vector int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_mergeh(vector unsigned int a, vector unsigned int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_mergeh(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector float __ATTRS_o_ai
+vec_mergeh(vector float a, vector float b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+/* vec_vmrghb */
+
+#define __builtin_altivec_vmrghb vec_vmrghb
+
+static vector signed char __ATTRS_o_ai
+vec_vmrghb(vector signed char a, vector signed char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmrghb(vector unsigned char a, vector unsigned char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vmrghb(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
+/* vec_vmrghh */
+
+#define __builtin_altivec_vmrghh vec_vmrghh
+
+static vector short __ATTRS_o_ai
+vec_vmrghh(vector short a, vector short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmrghh(vector unsigned short a, vector unsigned short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vmrghh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vmrghh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+/* vec_vmrghw */
+
+#define __builtin_altivec_vmrghw vec_vmrghw
+
+static vector int __ATTRS_o_ai
+vec_vmrghw(vector int a, vector int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmrghw(vector unsigned int a, vector unsigned int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vmrghw(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+static vector float __ATTRS_o_ai
+vec_vmrghw(vector float a, vector float b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
+/* vec_mergel */
+
+static vector signed char __ATTRS_o_ai
+vec_mergel(vector signed char a, vector signed char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_mergel(vector unsigned char a, vector unsigned char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_mergel(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+static vector short __ATTRS_o_ai
+vec_mergel(vector short a, vector short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_mergel(vector unsigned short a, vector unsigned short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_mergel(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_mergel(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector int __ATTRS_o_ai
+vec_mergel(vector int a, vector int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_mergel(vector unsigned int a, vector unsigned int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_mergel(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector float __ATTRS_o_ai
+vec_mergel(vector float a, vector float b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+/* vec_vmrglb */
+
+#define __builtin_altivec_vmrglb vec_vmrglb
+
+static vector signed char __ATTRS_o_ai
+vec_vmrglb(vector signed char a, vector signed char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmrglb(vector unsigned char a, vector unsigned char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vmrglb(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
+/* vec_vmrglh */
+
+#define __builtin_altivec_vmrglh vec_vmrglh
+
+static vector short __ATTRS_o_ai
+vec_vmrglh(vector short a, vector short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmrglh(vector unsigned short a, vector unsigned short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vmrglh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vmrglh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+/* vec_vmrglw */
+
+#define __builtin_altivec_vmrglw vec_vmrglw
+
+static vector int __ATTRS_o_ai
+vec_vmrglw(vector int a, vector int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmrglw(vector unsigned int a, vector unsigned int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vmrglw(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static vector float __ATTRS_o_ai
+vec_vmrglw(vector float a, vector float b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+/* vec_mfvscr */
+
+static vector unsigned short __attribute__((__always_inline__))
+vec_mfvscr(void)
+{
+ return __builtin_altivec_mfvscr();
+}
+
+/* vec_min */
+
+static vector signed char __ATTRS_o_ai
+vec_min(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_min(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_min(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vminsb(a, (vector signed char)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_min(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_min(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_min(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vminub(a, (vector unsigned char)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_min(vector short a, vector short b)
+{
+ return __builtin_altivec_vminsh(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_min(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vminsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_min(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vminsh(a, (vector short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_min(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_min(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_min(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vminuh(a, (vector unsigned short)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_min(vector int a, vector int b)
+{
+ return __builtin_altivec_vminsw(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_min(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vminsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_min(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vminsw(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_min(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_min(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_min(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vminuw(a, (vector unsigned int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_min(vector float a, vector float b)
+{
+ return __builtin_altivec_vminfp(a, b);
+}
+
+/* vec_vminsb */
+
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vminsb(a, (vector signed char)b);
+}
+
+/* vec_vminub */
+
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vminub(a, (vector unsigned char)b);
+}
+
+/* vec_vminsh */
+
+static vector short __ATTRS_o_ai
+vec_vminsh(vector short a, vector short b)
+{
+ return __builtin_altivec_vminsh(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vminsh(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vminsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vminsh(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vminsh(a, (vector short)b);
+}
+
+/* vec_vminuh */
+
+static vector unsigned short __ATTRS_o_ai
+vec_vminuh(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vminuh(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vminuh(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vminuh(a, (vector unsigned short)b);
+}
+
+/* vec_vminsw */
+
+static vector int __ATTRS_o_ai
+vec_vminsw(vector int a, vector int b)
+{
+ return __builtin_altivec_vminsw(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vminsw(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vminsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vminsw(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vminsw(a, (vector int)b);
+}
+
+/* vec_vminuw */
+
+static vector unsigned int __ATTRS_o_ai
+vec_vminuw(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vminuw(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vminuw(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vminuw(a, (vector unsigned int)b);
+}
+
+/* vec_vminfp */
+
+static vector float __attribute__((__always_inline__))
+vec_vminfp(vector float a, vector float b)
+{
+ return __builtin_altivec_vminfp(a, b);
+}
+
+/* vec_mladd */
+
+#define __builtin_altivec_vmladduhm vec_mladd
+
+static vector short __ATTRS_o_ai
+vec_mladd(vector short a, vector short b, vector short c)
+{
+ return a * b + c;
+}
+
+static vector short __ATTRS_o_ai
+vec_mladd(vector short a, vector unsigned short b, vector unsigned short c)
+{
+ return a * (vector short)b + (vector short)c;
+}
+
+static vector short __ATTRS_o_ai
+vec_mladd(vector unsigned short a, vector short b, vector short c)
+{
+ return (vector short)a * b + c;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_mladd(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned short c)
+{
+ return a * b + c;
+}
+
+/* vec_vmladduhm */
+
+static vector short __ATTRS_o_ai
+vec_vmladduhm(vector short a, vector short b, vector short c)
+{
+ return a * b + c;
+}
+
+static vector short __ATTRS_o_ai
+vec_vmladduhm(vector short a, vector unsigned short b, vector unsigned short c)
+{
+ return a * (vector short)b + (vector short)c;
+}
+
+static vector short __ATTRS_o_ai
+vec_vmladduhm(vector unsigned short a, vector short b, vector short c)
+{
+ return (vector short)a * b + c;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmladduhm(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned short c)
+{
+ return a * b + c;
+}
+
+/* vec_mradds */
+
+static vector short __attribute__((__always_inline__))
+vec_mradds(vector short a, vector short b, vector short c)
+{
+ return __builtin_altivec_vmhraddshs(a, b, c);
+}
+
+/* vec_vmhraddshs */
+
+static vector short __attribute__((__always_inline__))
+vec_vmhraddshs(vector short a, vector short b, vector short c)
+{
+ return __builtin_altivec_vmhraddshs(a, b, c);
+}
+
+/* vec_msum */
+
+static vector int __ATTRS_o_ai
+vec_msum(vector signed char a, vector unsigned char b, vector int c)
+{
+ return __builtin_altivec_vmsummbm(a, b, c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_msum(vector unsigned char a, vector unsigned char b, vector unsigned int c)
+{
+ return __builtin_altivec_vmsumubm(a, b, c);
+}
+
+static vector int __ATTRS_o_ai
+vec_msum(vector short a, vector short b, vector int c)
+{
+ return __builtin_altivec_vmsumshm(a, b, c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_msum(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned int c)
+{
+ return __builtin_altivec_vmsumuhm(a, b, c);
+}
+
+/* vec_vmsummbm */
+
+static vector int __attribute__((__always_inline__))
+vec_vmsummbm(vector signed char a, vector unsigned char b, vector int c)
+{
+ return __builtin_altivec_vmsummbm(a, b, c);
+}
+
+/* vec_vmsumubm */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vmsumubm(vector unsigned char a,
+ vector unsigned char b,
+ vector unsigned int c)
+{
+ return __builtin_altivec_vmsumubm(a, b, c);
+}
+
+/* vec_vmsumshm */
+
+static vector int __attribute__((__always_inline__))
+vec_vmsumshm(vector short a, vector short b, vector int c)
+{
+ return __builtin_altivec_vmsumshm(a, b, c);
+}
+
+/* vec_vmsumuhm */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vmsumuhm(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned int c)
+{
+ return __builtin_altivec_vmsumuhm(a, b, c);
+}
+
+/* vec_msums */
+
+static vector int __ATTRS_o_ai
+vec_msums(vector short a, vector short b, vector int c)
+{
+ return __builtin_altivec_vmsumshs(a, b, c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_msums(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned int c)
+{
+ return __builtin_altivec_vmsumuhs(a, b, c);
+}
+
+/* vec_vmsumshs */
+
+static vector int __attribute__((__always_inline__))
+vec_vmsumshs(vector short a, vector short b, vector int c)
+{
+ return __builtin_altivec_vmsumshs(a, b, c);
+}
+
+/* vec_vmsumuhs */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vmsumuhs(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned int c)
+{
+ return __builtin_altivec_vmsumuhs(a, b, c);
+}
+
+/* vec_mtvscr */
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector signed char a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector unsigned char a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector bool char a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector short a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector unsigned short a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector bool short a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector pixel a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector int a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector unsigned int a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector bool int a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector float a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+/* vec_mule */
+
+static vector short __ATTRS_o_ai
+vec_mule(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmulesb(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_mule(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmuleub(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_mule(vector short a, vector short b)
+{
+ return __builtin_altivec_vmulesh(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_mule(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmuleuh(a, b);
+}
+
+/* vec_vmulesb */
+
+static vector short __attribute__((__always_inline__))
+vec_vmulesb(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmulesb(a, b);
+}
+
+/* vec_vmuleub */
+
+static vector unsigned short __attribute__((__always_inline__))
+vec_vmuleub(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmuleub(a, b);
+}
+
+/* vec_vmulesh */
+
+static vector int __attribute__((__always_inline__))
+vec_vmulesh(vector short a, vector short b)
+{
+ return __builtin_altivec_vmulesh(a, b);
+}
+
+/* vec_vmuleuh */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vmuleuh(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmuleuh(a, b);
+}
+
+/* vec_mulo */
+
+static vector short __ATTRS_o_ai
+vec_mulo(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmulosb(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_mulo(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmuloub(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_mulo(vector short a, vector short b)
+{
+ return __builtin_altivec_vmulosh(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_mulo(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmulouh(a, b);
+}
+
+/* vec_vmulosb */
+
+static vector short __attribute__((__always_inline__))
+vec_vmulosb(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vmulosb(a, b);
+}
+
+/* vec_vmuloub */
+
+static vector unsigned short __attribute__((__always_inline__))
+vec_vmuloub(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmuloub(a, b);
+}
+
+/* vec_vmulosh */
+
+static vector int __attribute__((__always_inline__))
+vec_vmulosh(vector short a, vector short b)
+{
+ return __builtin_altivec_vmulosh(a, b);
+}
+
+/* vec_vmulouh */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vmulouh(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmulouh(a, b);
+}
+
+/* vec_nmsub */
+
+static vector float __attribute__((__always_inline__))
+vec_nmsub(vector float a, vector float b, vector float c)
+{
+ return __builtin_altivec_vnmsubfp(a, b, c);
+}
+
+/* vec_vnmsubfp */
+
+static vector float __attribute__((__always_inline__))
+vec_vnmsubfp(vector float a, vector float b, vector float c)
+{
+ return __builtin_altivec_vnmsubfp(a, b, c);
+}
+
+/* vec_nor */
+
+#define __builtin_altivec_vnor vec_nor
+
+static vector signed char __ATTRS_o_ai
+vec_nor(vector signed char a, vector signed char b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_nor(vector unsigned char a, vector unsigned char b)
+{
+ return ~(a | b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_nor(vector bool char a, vector bool char b)
+{
+ return ~(a | b);
+}
+
+static vector short __ATTRS_o_ai
+vec_nor(vector short a, vector short b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_nor(vector unsigned short a, vector unsigned short b)
+{
+ return ~(a | b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_nor(vector bool short a, vector bool short b)
+{
+ return ~(a | b);
+}
+
+static vector int __ATTRS_o_ai
+vec_nor(vector int a, vector int b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_nor(vector unsigned int a, vector unsigned int b)
+{
+ return ~(a | b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_nor(vector bool int a, vector bool int b)
+{
+ return ~(a | b);
+}
+
+static vector float __ATTRS_o_ai
+vec_nor(vector float a, vector float b)
+{
+ vector unsigned int res = ~((vector unsigned int)a | (vector unsigned int)b);
+ return (vector float)res;
+}
+
+/* vec_vnor */
+
+static vector signed char __ATTRS_o_ai
+vec_vnor(vector signed char a, vector signed char b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vnor(vector unsigned char a, vector unsigned char b)
+{
+ return ~(a | b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vnor(vector bool char a, vector bool char b)
+{
+ return ~(a | b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vnor(vector short a, vector short b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vnor(vector unsigned short a, vector unsigned short b)
+{
+ return ~(a | b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vnor(vector bool short a, vector bool short b)
+{
+ return ~(a | b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vnor(vector int a, vector int b)
+{
+ return ~(a | b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vnor(vector unsigned int a, vector unsigned int b)
+{
+ return ~(a | b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vnor(vector bool int a, vector bool int b)
+{
+ return ~(a | b);
+}
+
+static vector float __ATTRS_o_ai
+vec_vnor(vector float a, vector float b)
+{
+ vector unsigned int res = ~((vector unsigned int)a | (vector unsigned int)b);
+ return (vector float)res;
+}
+
+/* vec_or */
+
+#define __builtin_altivec_vor vec_or
+
+static vector signed char __ATTRS_o_ai
+vec_or(vector signed char a, vector signed char b)
+{
+ return a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_or(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_or(vector signed char a, vector bool char b)
+{
+ return a | (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_or(vector unsigned char a, vector unsigned char b)
+{
+ return a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_or(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_or(vector unsigned char a, vector bool char b)
+{
+ return a | (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_or(vector bool char a, vector bool char b)
+{
+ return a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_or(vector short a, vector short b)
+{
+ return a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_or(vector bool short a, vector short b)
+{
+ return (vector short)a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_or(vector short a, vector bool short b)
+{
+ return a | (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_or(vector unsigned short a, vector unsigned short b)
+{
+ return a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_or(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_or(vector unsigned short a, vector bool short b)
+{
+ return a | (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_or(vector bool short a, vector bool short b)
+{
+ return a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_or(vector int a, vector int b)
+{
+ return a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_or(vector bool int a, vector int b)
+{
+ return (vector int)a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_or(vector int a, vector bool int b)
+{
+ return a | (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_or(vector unsigned int a, vector unsigned int b)
+{
+ return a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_or(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_or(vector unsigned int a, vector bool int b)
+{
+ return a | (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_or(vector bool int a, vector bool int b)
+{
+ return a | b;
+}
+
+static vector float __ATTRS_o_ai
+vec_or(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_or(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_or(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_vor */
+
+static vector signed char __ATTRS_o_ai
+vec_vor(vector signed char a, vector signed char b)
+{
+ return a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vor(vector signed char a, vector bool char b)
+{
+ return a | (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vor(vector unsigned char a, vector unsigned char b)
+{
+ return a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vor(vector unsigned char a, vector bool char b)
+{
+ return a | (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vor(vector bool char a, vector bool char b)
+{
+ return a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vor(vector short a, vector short b)
+{
+ return a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vor(vector bool short a, vector short b)
+{
+ return (vector short)a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vor(vector short a, vector bool short b)
+{
+ return a | (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vor(vector unsigned short a, vector unsigned short b)
+{
+ return a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vor(vector unsigned short a, vector bool short b)
+{
+ return a | (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vor(vector bool short a, vector bool short b)
+{
+ return a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vor(vector int a, vector int b)
+{
+ return a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vor(vector bool int a, vector int b)
+{
+ return (vector int)a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vor(vector int a, vector bool int b)
+{
+ return a | (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vor(vector unsigned int a, vector unsigned int b)
+{
+ return a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vor(vector unsigned int a, vector bool int b)
+{
+ return a | (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vor(vector bool int a, vector bool int b)
+{
+ return a | b;
+}
+
+static vector float __ATTRS_o_ai
+vec_vor(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_pack */
+
+static vector signed char __ATTRS_o_ai
+vec_pack(vector signed short a, vector signed short b)
+{
+ return (vector signed char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_pack(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_pack(vector bool short a, vector bool short b)
+{
+ return (vector bool char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+static vector short __ATTRS_o_ai
+vec_pack(vector int a, vector int b)
+{
+ return (vector short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_pack(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_pack(vector bool int a, vector bool int b)
+{
+ return (vector bool short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+/* vec_vpkuhum */
+
+#define __builtin_altivec_vpkuhum vec_vpkuhum
+
+static vector signed char __ATTRS_o_ai
+vec_vpkuhum(vector signed short a, vector signed short b)
+{
+ return (vector signed char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vpkuhum(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vpkuhum(vector bool short a, vector bool short b)
+{
+ return (vector bool char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
+/* vec_vpkuwum */
+
+#define __builtin_altivec_vpkuwum vec_vpkuwum
+
+static vector short __ATTRS_o_ai
+vec_vpkuwum(vector int a, vector int b)
+{
+ return (vector short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vpkuwum(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vpkuwum(vector bool int a, vector bool int b)
+{
+ return (vector bool short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
+/* vec_packpx */
+
+static vector pixel __attribute__((__always_inline__))
+vec_packpx(vector unsigned int a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vpkpx(a, b);
+}
+
+/* vec_vpkpx */
+
+static vector pixel __attribute__((__always_inline__))
+vec_vpkpx(vector unsigned int a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vpkpx(a, b);
+}
+
+/* vec_packs */
+
+static vector signed char __ATTRS_o_ai
+vec_packs(vector short a, vector short b)
+{
+ return __builtin_altivec_vpkshss(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_packs(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vpkuhus(a, b);
+}
+
+static vector signed short __ATTRS_o_ai
+vec_packs(vector int a, vector int b)
+{
+ return __builtin_altivec_vpkswss(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_packs(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vpkuwus(a, b);
+}
+
+/* vec_vpkshss */
+
+static vector signed char __attribute__((__always_inline__))
+vec_vpkshss(vector short a, vector short b)
+{
+ return __builtin_altivec_vpkshss(a, b);
+}
+
+/* vec_vpkuhus */
+
+static vector unsigned char __attribute__((__always_inline__))
+vec_vpkuhus(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vpkuhus(a, b);
+}
+
+/* vec_vpkswss */
+
+static vector signed short __attribute__((__always_inline__))
+vec_vpkswss(vector int a, vector int b)
+{
+ return __builtin_altivec_vpkswss(a, b);
+}
+
+/* vec_vpkuwus */
+
+static vector unsigned short __attribute__((__always_inline__))
+vec_vpkuwus(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vpkuwus(a, b);
+}
+
+/* vec_packsu */
+
+static vector unsigned char __ATTRS_o_ai
+vec_packsu(vector short a, vector short b)
+{
+ return __builtin_altivec_vpkshus(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_packsu(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vpkuhus(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_packsu(vector int a, vector int b)
+{
+ return __builtin_altivec_vpkswus(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_packsu(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vpkuwus(a, b);
+}
+
+/* vec_vpkshus */
+
+static vector unsigned char __ATTRS_o_ai
+vec_vpkshus(vector short a, vector short b)
+{
+ return __builtin_altivec_vpkshus(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vpkshus(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vpkuhus(a, b);
+}
+
+/* vec_vpkswus */
+
+static vector unsigned short __ATTRS_o_ai
+vec_vpkswus(vector int a, vector int b)
+{
+ return __builtin_altivec_vpkswus(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vpkswus(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vpkuwus(a, b);
+}
+
+/* vec_perm */
+
+vector signed char __ATTRS_o_ai
+vec_perm(vector signed char a, vector signed char b, vector unsigned char c)
+{
+ return (vector signed char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector unsigned char __ATTRS_o_ai
+vec_perm(vector unsigned char a,
+ vector unsigned char b,
+ vector unsigned char c)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool char __ATTRS_o_ai
+vec_perm(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (vector bool char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector short __ATTRS_o_ai
+vec_perm(vector short a, vector short b, vector unsigned char c)
+{
+ return (vector short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector unsigned short __ATTRS_o_ai
+vec_perm(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned char c)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool short __ATTRS_o_ai
+vec_perm(vector bool short a, vector bool short b, vector unsigned char c)
+{
+ return (vector bool short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector pixel __ATTRS_o_ai
+vec_perm(vector pixel a, vector pixel b, vector unsigned char c)
+{
+ return (vector pixel)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector int __ATTRS_o_ai
+vec_perm(vector int a, vector int b, vector unsigned char c)
+{
+ return (vector int)__builtin_altivec_vperm_4si(a, b, c);
+}
+
+vector unsigned int __ATTRS_o_ai
+vec_perm(vector unsigned int a, vector unsigned int b, vector unsigned char c)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool int __ATTRS_o_ai
+vec_perm(vector bool int a, vector bool int b, vector unsigned char c)
+{
+ return (vector bool int)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector float __ATTRS_o_ai
+vec_perm(vector float a, vector float b, vector unsigned char c)
+{
+ return (vector float)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+/* vec_vperm */
+
+vector signed char __ATTRS_o_ai
+vec_vperm(vector signed char a, vector signed char b, vector unsigned char c)
+{
+ return (vector signed char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector unsigned char __ATTRS_o_ai
+vec_vperm(vector unsigned char a,
+ vector unsigned char b,
+ vector unsigned char c)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool char __ATTRS_o_ai
+vec_vperm(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (vector bool char)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector short __ATTRS_o_ai
+vec_vperm(vector short a, vector short b, vector unsigned char c)
+{
+ return (vector short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector unsigned short __ATTRS_o_ai
+vec_vperm(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned char c)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool short __ATTRS_o_ai
+vec_vperm(vector bool short a, vector bool short b, vector unsigned char c)
+{
+ return (vector bool short)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector pixel __ATTRS_o_ai
+vec_vperm(vector pixel a, vector pixel b, vector unsigned char c)
+{
+ return (vector pixel)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector int __ATTRS_o_ai
+vec_vperm(vector int a, vector int b, vector unsigned char c)
+{
+ return (vector int)__builtin_altivec_vperm_4si(a, b, c);
+}
+
+vector unsigned int __ATTRS_o_ai
+vec_vperm(vector unsigned int a, vector unsigned int b, vector unsigned char c)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector bool int __ATTRS_o_ai
+vec_vperm(vector bool int a, vector bool int b, vector unsigned char c)
+{
+ return (vector bool int)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector float __ATTRS_o_ai
+vec_vperm(vector float a, vector float b, vector unsigned char c)
+{
+ return (vector float)
+ __builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+/* vec_re */
+
+vector float __attribute__((__always_inline__))
+vec_re(vector float a)
+{
+ return __builtin_altivec_vrefp(a);
+}
+
+/* vec_vrefp */
+
+vector float __attribute__((__always_inline__))
+vec_vrefp(vector float a)
+{
+ return __builtin_altivec_vrefp(a);
+}
+
+/* vec_rl */
+
+static vector signed char __ATTRS_o_ai
+vec_rl(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)__builtin_altivec_vrlb((vector char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_rl(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)__builtin_altivec_vrlb((vector char)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_rl(vector short a, vector unsigned short b)
+{
+ return __builtin_altivec_vrlh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_rl(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)__builtin_altivec_vrlh((vector short)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_rl(vector int a, vector unsigned int b)
+{
+ return __builtin_altivec_vrlw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_rl(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)__builtin_altivec_vrlw((vector int)a, b);
+}
+
+/* vec_vrlb */
+
+static vector signed char __ATTRS_o_ai
+vec_vrlb(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)__builtin_altivec_vrlb((vector char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vrlb(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)__builtin_altivec_vrlb((vector char)a, b);
+}
+
+/* vec_vrlh */
+
+static vector short __ATTRS_o_ai
+vec_vrlh(vector short a, vector unsigned short b)
+{
+ return __builtin_altivec_vrlh(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vrlh(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)__builtin_altivec_vrlh((vector short)a, b);
+}
+
+/* vec_vrlw */
+
+static vector int __ATTRS_o_ai
+vec_vrlw(vector int a, vector unsigned int b)
+{
+ return __builtin_altivec_vrlw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vrlw(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)__builtin_altivec_vrlw((vector int)a, b);
+}
+
+/* vec_round */
+
+static vector float __attribute__((__always_inline__))
+vec_round(vector float a)
+{
+ return __builtin_altivec_vrfin(a);
+}
+
+/* vec_vrfin */
+
+static vector float __attribute__((__always_inline__))
+vec_vrfin(vector float a)
+{
+ return __builtin_altivec_vrfin(a);
+}
+
+/* vec_rsqrte */
+
+static __vector float __attribute__((__always_inline__))
+vec_rsqrte(vector float a)
+{
+ return __builtin_altivec_vrsqrtefp(a);
+}
+
+/* vec_vrsqrtefp */
+
+static __vector float __attribute__((__always_inline__))
+vec_vrsqrtefp(vector float a)
+{
+ return __builtin_altivec_vrsqrtefp(a);
+}
+
+/* vec_sel */
+
+#define __builtin_altivec_vsel_4si vec_sel
+
+static vector signed char __ATTRS_o_ai
+vec_sel(vector signed char a, vector signed char b, vector unsigned char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sel(vector signed char a, vector signed char b, vector bool char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sel(vector unsigned char a, vector unsigned char b, vector unsigned char c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sel(vector unsigned char a, vector unsigned char b, vector bool char c)
+{
+ return (a & ~(vector unsigned char)c) | (b & (vector unsigned char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sel(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (a & ~(vector bool char)c) | (b & (vector bool char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sel(vector bool char a, vector bool char b, vector bool char c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector short __ATTRS_o_ai
+vec_sel(vector short a, vector short b, vector unsigned short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
+static vector short __ATTRS_o_ai
+vec_sel(vector short a, vector short b, vector bool short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sel(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned short c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sel(vector unsigned short a, vector unsigned short b, vector bool short c)
+{
+ return (a & ~(vector unsigned short)c) | (b & (vector unsigned short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sel(vector bool short a, vector bool short b, vector unsigned short c)
+{
+ return (a & ~(vector bool short)c) | (b & (vector bool short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sel(vector bool short a, vector bool short b, vector bool short c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector int __ATTRS_o_ai
+vec_sel(vector int a, vector int b, vector unsigned int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
+static vector int __ATTRS_o_ai
+vec_sel(vector int a, vector int b, vector bool int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sel(vector unsigned int a, vector unsigned int b, vector unsigned int c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sel(vector unsigned int a, vector unsigned int b, vector bool int c)
+{
+ return (a & ~(vector unsigned int)c) | (b & (vector unsigned int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sel(vector bool int a, vector bool int b, vector unsigned int c)
+{
+ return (a & ~(vector bool int)c) | (b & (vector bool int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sel(vector bool int a, vector bool int b, vector bool int c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector float __ATTRS_o_ai
+vec_sel(vector float a, vector float b, vector unsigned int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c)
+ | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_sel(vector float a, vector float b, vector bool int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c)
+ | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
+/* vec_vsel */
+
+static vector signed char __ATTRS_o_ai
+vec_vsel(vector signed char a, vector signed char b, vector unsigned char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsel(vector signed char a, vector signed char b, vector bool char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsel(vector unsigned char a, vector unsigned char b, vector unsigned char c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsel(vector unsigned char a, vector unsigned char b, vector bool char c)
+{
+ return (a & ~(vector unsigned char)c) | (b & (vector unsigned char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsel(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (a & ~(vector bool char)c) | (b & (vector bool char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsel(vector bool char a, vector bool char b, vector bool char c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsel(vector short a, vector short b, vector unsigned short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsel(vector short a, vector short b, vector bool short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsel(vector unsigned short a,
+ vector unsigned short b,
+ vector unsigned short c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsel(vector unsigned short a, vector unsigned short b, vector bool short c)
+{
+ return (a & ~(vector unsigned short)c) | (b & (vector unsigned short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsel(vector bool short a, vector bool short b, vector unsigned short c)
+{
+ return (a & ~(vector bool short)c) | (b & (vector bool short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsel(vector bool short a, vector bool short b, vector bool short c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsel(vector int a, vector int b, vector unsigned int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsel(vector int a, vector int b, vector bool int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsel(vector unsigned int a, vector unsigned int b, vector unsigned int c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsel(vector unsigned int a, vector unsigned int b, vector bool int c)
+{
+ return (a & ~(vector unsigned int)c) | (b & (vector unsigned int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsel(vector bool int a, vector bool int b, vector unsigned int c)
+{
+ return (a & ~(vector bool int)c) | (b & (vector bool int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsel(vector bool int a, vector bool int b, vector bool int c)
+{
+ return (a & ~c) | (b & c);
+}
+
+static vector float __ATTRS_o_ai
+vec_vsel(vector float a, vector float b, vector unsigned int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c)
+ | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vsel(vector float a, vector float b, vector bool int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c)
+ | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
+/* vec_sl */
+
+static vector signed char __ATTRS_o_ai
+vec_sl(vector signed char a, vector unsigned char b)
+{
+ return a << (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sl(vector unsigned char a, vector unsigned char b)
+{
+ return a << b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sl(vector short a, vector unsigned short b)
+{
+ return a << (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sl(vector unsigned short a, vector unsigned short b)
+{
+ return a << b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sl(vector int a, vector unsigned int b)
+{
+ return a << (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sl(vector unsigned int a, vector unsigned int b)
+{
+ return a << b;
+}
+
+/* vec_vslb */
+
+#define __builtin_altivec_vslb vec_vslb
+
+static vector signed char __ATTRS_o_ai
+vec_vslb(vector signed char a, vector unsigned char b)
+{
+ return vec_sl(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vslb(vector unsigned char a, vector unsigned char b)
+{
+ return vec_sl(a, b);
+}
+
+/* vec_vslh */
+
+#define __builtin_altivec_vslh vec_vslh
+
+static vector short __ATTRS_o_ai
+vec_vslh(vector short a, vector unsigned short b)
+{
+ return vec_sl(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vslh(vector unsigned short a, vector unsigned short b)
+{
+ return vec_sl(a, b);
+}
+
+/* vec_vslw */
+
+#define __builtin_altivec_vslw vec_vslw
+
+static vector int __ATTRS_o_ai
+vec_vslw(vector int a, vector unsigned int b)
+{
+ return vec_sl(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vslw(vector unsigned int a, vector unsigned int b)
+{
+ return vec_sl(a, b);
+}
+
+/* vec_sld */
+
+#define __builtin_altivec_vsldoi_4si vec_sld
+
+static vector signed char __ATTRS_o_ai
+vec_sld(vector signed char a, vector signed char b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sld(vector unsigned char a, vector unsigned char b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector short __ATTRS_o_ai
+vec_sld(vector short a, vector short b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sld(vector unsigned short a, vector unsigned short b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sld(vector pixel a, vector pixel b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector int __ATTRS_o_ai
+vec_sld(vector int a, vector int b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sld(vector unsigned int a, vector unsigned int b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector float __ATTRS_o_ai
+vec_sld(vector float a, vector float b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+/* vec_vsldoi */
+
+static vector signed char __ATTRS_o_ai
+vec_vsldoi(vector signed char a, vector signed char b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsldoi(vector unsigned char a, vector unsigned char b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector short __ATTRS_o_ai
+vec_vsldoi(vector short a, vector short b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsldoi(vector unsigned short a, vector unsigned short b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsldoi(vector pixel a, vector pixel b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector int __ATTRS_o_ai
+vec_vsldoi(vector int a, vector int b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsldoi(vector unsigned int a, vector unsigned int b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector float __ATTRS_o_ai
+vec_vsldoi(vector float a, vector float b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+/* vec_sll */
+
+static vector signed char __ATTRS_o_ai
+vec_sll(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sll(vector signed char a, vector unsigned short b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sll(vector signed char a, vector unsigned int b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sll(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sll(vector unsigned char a, vector unsigned short b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sll(vector unsigned char a, vector unsigned int b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sll(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sll(vector short a, vector unsigned short b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sll(vector short a, vector unsigned int b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sll(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sll(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sll(vector unsigned short a, vector unsigned int b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sll(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sll(vector int a, vector unsigned short b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sll(vector int a, vector unsigned int b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sll(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sll(vector unsigned int a, vector unsigned short b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sll(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+/* vec_vsl */
+
+static vector signed char __ATTRS_o_ai
+vec_vsl(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsl(vector signed char a, vector unsigned short b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsl(vector signed char a, vector unsigned int b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsl(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsl(vector unsigned char a, vector unsigned short b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsl(vector unsigned char a, vector unsigned int b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsl(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsl(vector short a, vector unsigned short b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsl(vector short a, vector unsigned int b)
+{
+ return (vector short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsl(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsl(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsl(vector unsigned short a, vector unsigned int b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsl(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsl(vector int a, vector unsigned short b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsl(vector int a, vector unsigned int b)
+{
+ return (vector int)__builtin_altivec_vsl(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsl(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsl(vector unsigned int a, vector unsigned short b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsl(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+/* vec_slo */
+
+static vector signed char __ATTRS_o_ai
+vec_slo(vector signed char a, vector signed char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_slo(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_slo(vector unsigned char a, vector signed char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_slo(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_slo(vector short a, vector signed char b)
+{
+ return (vector short)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_slo(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_slo(vector unsigned short a, vector signed char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_slo(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_slo(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_slo(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_slo(vector int a, vector signed char b)
+{
+ return (vector int)__builtin_altivec_vslo(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_slo(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vslo(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_slo(vector unsigned int a, vector signed char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_slo(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_slo(vector float a, vector signed char b)
+{
+ return (vector float)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_slo(vector float a, vector unsigned char b)
+{
+ return (vector float)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+/* vec_vslo */
+
+static vector signed char __ATTRS_o_ai
+vec_vslo(vector signed char a, vector signed char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vslo(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vslo(vector unsigned char a, vector signed char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vslo(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vslo(vector short a, vector signed char b)
+{
+ return (vector short)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vslo(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vslo(vector unsigned short a, vector signed char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vslo(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vslo(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vslo(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vslo(vector int a, vector signed char b)
+{
+ return (vector int)__builtin_altivec_vslo(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vslo(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vslo(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vslo(vector unsigned int a, vector signed char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vslo(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_vslo(vector float a, vector signed char b)
+{
+ return (vector float)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_vslo(vector float a, vector unsigned char b)
+{
+ return (vector float)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+/* vec_splat */
+
+static vector signed char __ATTRS_o_ai
+vec_splat(vector signed char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_splat(vector unsigned char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_splat(vector bool char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector short __ATTRS_o_ai
+vec_splat(vector short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_splat(vector unsigned short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_splat(vector bool short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_splat(vector pixel a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector int __ATTRS_o_ai
+vec_splat(vector int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_splat(vector unsigned int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_splat(vector bool int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector float __ATTRS_o_ai
+vec_splat(vector float a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+/* vec_vspltb */
+
+#define __builtin_altivec_vspltb vec_vspltb
+
+static vector signed char __ATTRS_o_ai
+vec_vspltb(vector signed char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vspltb(vector unsigned char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vspltb(vector bool char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+/* vec_vsplth */
+
+#define __builtin_altivec_vsplth vec_vsplth
+
+static vector short __ATTRS_o_ai
+vec_vsplth(vector short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsplth(vector unsigned short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsplth(vector bool short a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsplth(vector pixel a, unsigned char b)
+{
+ b *= 2;
+ unsigned char b1=b+1;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1, b, b1));
+}
+
+/* vec_vspltw */
+
+#define __builtin_altivec_vspltw vec_vspltw
+
+static vector int __ATTRS_o_ai
+vec_vspltw(vector int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vspltw(vector unsigned int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vspltw(vector bool int a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+static vector float __ATTRS_o_ai
+vec_vspltw(vector float a, unsigned char b)
+{
+ b *= 4;
+ unsigned char b1=b+1, b2=b+2, b3=b+3;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3, b, b1, b2, b3));
+}
+
+/* vec_splat_s8 */
+
+#define __builtin_altivec_vspltisb vec_splat_s8
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector signed char __ATTRS_o_ai
+vec_splat_s8(signed char a)
+{
+ return (vector signed char)(a);
+}
+
+/* vec_vspltisb */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector signed char __ATTRS_o_ai
+vec_vspltisb(signed char a)
+{
+ return (vector signed char)(a);
+}
+
+/* vec_splat_s16 */
+
+#define __builtin_altivec_vspltish vec_splat_s16
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector short __ATTRS_o_ai
+vec_splat_s16(signed char a)
+{
+ return (vector short)(a);
+}
+
+/* vec_vspltish */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector short __ATTRS_o_ai
+vec_vspltish(signed char a)
+{
+ return (vector short)(a);
+}
+
+/* vec_splat_s32 */
+
+#define __builtin_altivec_vspltisw vec_splat_s32
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector int __ATTRS_o_ai
+vec_splat_s32(signed char a)
+{
+ return (vector int)(a);
+}
+
+/* vec_vspltisw */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector int __ATTRS_o_ai
+vec_vspltisw(signed char a)
+{
+ return (vector int)(a);
+}
+
+/* vec_splat_u8 */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector unsigned char __ATTRS_o_ai
+vec_splat_u8(unsigned char a)
+{
+ return (vector unsigned char)(a);
+}
+
+/* vec_splat_u16 */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector unsigned short __ATTRS_o_ai
+vec_splat_u16(signed char a)
+{
+ return (vector unsigned short)(a);
+}
+
+/* vec_splat_u32 */
+
+// FIXME: parameter should be treated as 5-bit signed literal
+static vector unsigned int __ATTRS_o_ai
+vec_splat_u32(signed char a)
+{
+ return (vector unsigned int)(a);
+}
+
+/* vec_sr */
+
+static vector signed char __ATTRS_o_ai
+vec_sr(vector signed char a, vector unsigned char b)
+{
+ return a >> (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sr(vector unsigned char a, vector unsigned char b)
+{
+ return a >> b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sr(vector short a, vector unsigned short b)
+{
+ return a >> (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sr(vector unsigned short a, vector unsigned short b)
+{
+ return a >> b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sr(vector int a, vector unsigned int b)
+{
+ return a >> (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sr(vector unsigned int a, vector unsigned int b)
+{
+ return a >> b;
+}
+
+/* vec_vsrb */
+
+#define __builtin_altivec_vsrb vec_vsrb
+
+static vector signed char __ATTRS_o_ai
+vec_vsrb(vector signed char a, vector unsigned char b)
+{
+ return a >> (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsrb(vector unsigned char a, vector unsigned char b)
+{
+ return a >> b;
+}
+
+/* vec_vsrh */
+
+#define __builtin_altivec_vsrh vec_vsrh
+
+static vector short __ATTRS_o_ai
+vec_vsrh(vector short a, vector unsigned short b)
+{
+ return a >> (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsrh(vector unsigned short a, vector unsigned short b)
+{
+ return a >> b;
+}
+
+/* vec_vsrw */
+
+#define __builtin_altivec_vsrw vec_vsrw
+
+static vector int __ATTRS_o_ai
+vec_vsrw(vector int a, vector unsigned int b)
+{
+ return a >> (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsrw(vector unsigned int a, vector unsigned int b)
+{
+ return a >> b;
+}
+
+/* vec_sra */
+
+static vector signed char __ATTRS_o_ai
+vec_sra(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)__builtin_altivec_vsrab((vector char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sra(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)__builtin_altivec_vsrab((vector char)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sra(vector short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsrah(a, (vector unsigned short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sra(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)__builtin_altivec_vsrah((vector short)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sra(vector int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsraw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sra(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)__builtin_altivec_vsraw((vector int)a, b);
+}
+
+/* vec_vsrab */
+
+static vector signed char __ATTRS_o_ai
+vec_vsrab(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)__builtin_altivec_vsrab((vector char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsrab(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)__builtin_altivec_vsrab((vector char)a, b);
+}
+
+/* vec_vsrah */
+
+static vector short __ATTRS_o_ai
+vec_vsrah(vector short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsrah(a, (vector unsigned short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsrah(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)__builtin_altivec_vsrah((vector short)a, b);
+}
+
+/* vec_vsraw */
+
+static vector int __ATTRS_o_ai
+vec_vsraw(vector int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsraw(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsraw(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)__builtin_altivec_vsraw((vector int)a, b);
+}
+
+/* vec_srl */
+
+static vector signed char __ATTRS_o_ai
+vec_srl(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_srl(vector signed char a, vector unsigned short b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_srl(vector signed char a, vector unsigned int b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_srl(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_srl(vector unsigned char a, vector unsigned short b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_srl(vector unsigned char a, vector unsigned int b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_srl(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_srl(vector short a, vector unsigned short b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_srl(vector short a, vector unsigned int b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_srl(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_srl(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_srl(vector unsigned short a, vector unsigned int b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_srl(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_srl(vector int a, vector unsigned short b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_srl(vector int a, vector unsigned int b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_srl(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_srl(vector unsigned int a, vector unsigned short b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_srl(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+/* vec_vsr */
+
+static vector signed char __ATTRS_o_ai
+vec_vsr(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsr(vector signed char a, vector unsigned short b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsr(vector signed char a, vector unsigned int b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsr(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsr(vector unsigned char a, vector unsigned short b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsr(vector unsigned char a, vector unsigned int b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsr(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsr(vector short a, vector unsigned short b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsr(vector short a, vector unsigned int b)
+{
+ return (vector short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsr(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsr(vector unsigned short a, vector unsigned short b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsr(vector unsigned short a, vector unsigned int b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsr(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsr(vector int a, vector unsigned short b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsr(vector int a, vector unsigned int b)
+{
+ return (vector int)__builtin_altivec_vsr(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsr(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsr(vector unsigned int a, vector unsigned short b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsr(vector unsigned int a, vector unsigned int b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+/* vec_sro */
+
+static vector signed char __ATTRS_o_ai
+vec_sro(vector signed char a, vector signed char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sro(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sro(vector unsigned char a, vector signed char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sro(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sro(vector short a, vector signed char b)
+{
+ return (vector short)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_sro(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sro(vector unsigned short a, vector signed char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sro(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sro(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sro(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sro(vector int a, vector signed char b)
+{
+ return (vector int)__builtin_altivec_vsro(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sro(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsro(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sro(vector unsigned int a, vector signed char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sro(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_sro(vector float a, vector signed char b)
+{
+ return (vector float)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_sro(vector float a, vector unsigned char b)
+{
+ return (vector float)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+/* vec_vsro */
+
+static vector signed char __ATTRS_o_ai
+vec_vsro(vector signed char a, vector signed char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsro(vector signed char a, vector unsigned char b)
+{
+ return (vector signed char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsro(vector unsigned char a, vector signed char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsro(vector unsigned char a, vector unsigned char b)
+{
+ return (vector unsigned char)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsro(vector short a, vector signed char b)
+{
+ return (vector short)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsro(vector short a, vector unsigned char b)
+{
+ return (vector short)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsro(vector unsigned short a, vector signed char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsro(vector unsigned short a, vector unsigned char b)
+{
+ return (vector unsigned short)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsro(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsro(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsro(vector int a, vector signed char b)
+{
+ return (vector int)__builtin_altivec_vsro(a, (vector int)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsro(vector int a, vector unsigned char b)
+{
+ return (vector int)__builtin_altivec_vsro(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsro(vector unsigned int a, vector signed char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsro(vector unsigned int a, vector unsigned char b)
+{
+ return (vector unsigned int)
+ __builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_vsro(vector float a, vector signed char b)
+{
+ return (vector float)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector float __ATTRS_o_ai
+vec_vsro(vector float a, vector unsigned char b)
+{
+ return (vector float)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+/* vec_st */
+
+static void __ATTRS_o_ai
+vec_st(vector signed char a, int b, vector signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned char a, int b, vector unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector short a, int b, vector short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned short a, int b, vector unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector int a, int b, vector int *c)
+{
+ __builtin_altivec_stvx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned int a, int b, vector unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector float a, int b, vector float *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+/* vec_stvx */
+
+static void __ATTRS_o_ai
+vec_stvx(vector signed char a, int b, vector signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned char a, int b, vector unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector short a, int b, vector short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned short a, int b, vector unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector int a, int b, vector int *c)
+{
+ __builtin_altivec_stvx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned int a, int b, vector unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector float a, int b, vector float *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+/* vec_ste */
+
+static void __ATTRS_o_ai
+vec_ste(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvehx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvewx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+/* vec_stvebx */
+
+static void __ATTRS_o_ai
+vec_stvebx(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvebx(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvebx(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvebx(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+/* vec_stvehx */
+
+static void __ATTRS_o_ai
+vec_stvehx(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvehx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+/* vec_stvewx */
+
+static void __ATTRS_o_ai
+vec_stvewx(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvewx(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvewx(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvewx(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvewx(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvewx(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+/* vec_stl */
+
+static void __ATTRS_o_ai
+vec_stl(vector signed char a, int b, vector signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned char a, int b, vector unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector short a, int b, vector short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned short a, int b, vector unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector int a, int b, vector int *c)
+{
+ __builtin_altivec_stvxl(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvxl(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned int a, int b, vector unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector float a, int b, vector float *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+/* vec_stvxl */
+
+static void __ATTRS_o_ai
+vec_stvxl(vector signed char a, int b, vector signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector signed char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned char a, int b, vector unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector short a, int b, vector short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned short a, int b, vector unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector int a, int b, vector int *c)
+{
+ __builtin_altivec_stvxl(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector int a, int b, int *c)
+{
+ __builtin_altivec_stvxl(a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned int a, int b, vector unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector unsigned int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector float a, int b, vector float *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector float a, int b, float *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+/* vec_sub */
+
+static vector signed char __ATTRS_o_ai
+vec_sub(vector signed char a, vector signed char b)
+{
+ return a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sub(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sub(vector signed char a, vector bool char b)
+{
+ return a - (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sub(vector unsigned char a, vector unsigned char b)
+{
+ return a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sub(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sub(vector unsigned char a, vector bool char b)
+{
+ return a - (vector unsigned char)b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sub(vector short a, vector short b)
+{
+ return a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sub(vector bool short a, vector short b)
+{
+ return (vector short)a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sub(vector short a, vector bool short b)
+{
+ return a - (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sub(vector unsigned short a, vector unsigned short b)
+{
+ return a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sub(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sub(vector unsigned short a, vector bool short b)
+{
+ return a - (vector unsigned short)b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sub(vector int a, vector int b)
+{
+ return a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sub(vector bool int a, vector int b)
+{
+ return (vector int)a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sub(vector int a, vector bool int b)
+{
+ return a - (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sub(vector unsigned int a, vector unsigned int b)
+{
+ return a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sub(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sub(vector unsigned int a, vector bool int b)
+{
+ return a - (vector unsigned int)b;
+}
+
+static vector float __ATTRS_o_ai
+vec_sub(vector float a, vector float b)
+{
+ return a - b;
+}
+
+/* vec_vsububm */
+
+#define __builtin_altivec_vsububm vec_vsububm
+
+static vector signed char __ATTRS_o_ai
+vec_vsububm(vector signed char a, vector signed char b)
+{
+ return a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsububm(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsububm(vector signed char a, vector bool char b)
+{
+ return a - (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububm(vector unsigned char a, vector unsigned char b)
+{
+ return a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububm(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububm(vector unsigned char a, vector bool char b)
+{
+ return a - (vector unsigned char)b;
+}
+
+/* vec_vsubuhm */
+
+#define __builtin_altivec_vsubuhm vec_vsubuhm
+
+static vector short __ATTRS_o_ai
+vec_vsubuhm(vector short a, vector short b)
+{
+ return a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubuhm(vector bool short a, vector short b)
+{
+ return (vector short)a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubuhm(vector short a, vector bool short b)
+{
+ return a - (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhm(vector unsigned short a, vector unsigned short b)
+{
+ return a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhm(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhm(vector unsigned short a, vector bool short b)
+{
+ return a - (vector unsigned short)b;
+}
+
+/* vec_vsubuwm */
+
+#define __builtin_altivec_vsubuwm vec_vsubuwm
+
+static vector int __ATTRS_o_ai
+vec_vsubuwm(vector int a, vector int b)
+{
+ return a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubuwm(vector bool int a, vector int b)
+{
+ return (vector int)a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubuwm(vector int a, vector bool int b)
+{
+ return a - (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuwm(vector unsigned int a, vector unsigned int b)
+{
+ return a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuwm(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuwm(vector unsigned int a, vector bool int b)
+{
+ return a - (vector unsigned int)b;
+}
+
+/* vec_vsubfp */
+
+#define __builtin_altivec_vsubfp vec_vsubfp
+
+static vector float __attribute__((__always_inline__))
+vec_vsubfp(vector float a, vector float b)
+{
+ return a - b;
+}
+
+/* vec_subc */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_subc(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubcuw(a, b);
+}
+
+/* vec_vsubcuw */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vsubcuw(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubcuw(a, b);
+}
+
+/* vec_subs */
+
+static vector signed char __ATTRS_o_ai
+vec_subs(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_subs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_subs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vsubsbs(a, (vector signed char)b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_subs(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_subs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_subs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vsububs(a, (vector unsigned char)b);
+}
+
+static vector short __ATTRS_o_ai
+vec_subs(vector short a, vector short b)
+{
+ return __builtin_altivec_vsubshs(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_subs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vsubshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_subs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vsubshs(a, (vector short)b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_subs(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_subs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_subs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vsubuhs(a, (vector unsigned short)b);
+}
+
+static vector int __ATTRS_o_ai
+vec_subs(vector int a, vector int b)
+{
+ return __builtin_altivec_vsubsws(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_subs(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vsubsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_subs(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vsubsws(a, (vector int)b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_subs(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_subs(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_subs(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vsubuws(a, (vector unsigned int)b);
+}
+
+/* vec_vsubsbs */
+
+static vector signed char __ATTRS_o_ai
+vec_vsubsbs(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs(a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsubsbs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsubsbs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vsubsbs(a, (vector signed char)b);
+}
+
+/* vec_vsububs */
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububs(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs(a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vsububs(a, (vector unsigned char)b);
+}
+
+/* vec_vsubshs */
+
+static vector short __ATTRS_o_ai
+vec_vsubshs(vector short a, vector short b)
+{
+ return __builtin_altivec_vsubshs(a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubshs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vsubshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubshs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vsubshs(a, (vector short)b);
+}
+
+/* vec_vsubuhs */
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhs(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs(a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vsubuhs(a, (vector unsigned short)b);
+}
+
+/* vec_vsubsws */
+
+static vector int __ATTRS_o_ai
+vec_vsubsws(vector int a, vector int b)
+{
+ return __builtin_altivec_vsubsws(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubsws(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vsubsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubsws(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vsubsws(a, (vector int)b);
+}
+
+/* vec_vsubuws */
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuws(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuws(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuws(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vsubuws(a, (vector unsigned int)b);
+}
+
+/* vec_sum4s */
+
+static vector int __ATTRS_o_ai
+vec_sum4s(vector signed char a, vector int b)
+{
+ return __builtin_altivec_vsum4sbs(a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sum4s(vector unsigned char a, vector unsigned int b)
+{
+ return __builtin_altivec_vsum4ubs(a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_sum4s(vector signed short a, vector int b)
+{
+ return __builtin_altivec_vsum4shs(a, b);
+}
+
+/* vec_vsum4sbs */
+
+static vector int __attribute__((__always_inline__))
+vec_vsum4sbs(vector signed char a, vector int b)
+{
+ return __builtin_altivec_vsum4sbs(a, b);
+}
+
+/* vec_vsum4ubs */
+
+static vector unsigned int __attribute__((__always_inline__))
+vec_vsum4ubs(vector unsigned char a, vector unsigned int b)
+{
+ return __builtin_altivec_vsum4ubs(a, b);
+}
+
+/* vec_vsum4shs */
+
+static vector int __attribute__((__always_inline__))
+vec_vsum4shs(vector signed short a, vector int b)
+{
+ return __builtin_altivec_vsum4shs(a, b);
+}
+
+/* vec_sum2s */
+
+static vector signed int __attribute__((__always_inline__))
+vec_sum2s(vector int a, vector int b)
+{
+ return __builtin_altivec_vsum2sws(a, b);
+}
+
+/* vec_vsum2sws */
+
+static vector signed int __attribute__((__always_inline__))
+vec_vsum2sws(vector int a, vector int b)
+{
+ return __builtin_altivec_vsum2sws(a, b);
+}
+
+/* vec_sums */
+
+static vector signed int __attribute__((__always_inline__))
+vec_sums(vector signed int a, vector signed int b)
+{
+ return __builtin_altivec_vsumsws(a, b);
+}
+
+/* vec_vsumsws */
+
+static vector signed int __attribute__((__always_inline__))
+vec_vsumsws(vector signed int a, vector signed int b)
+{
+ return __builtin_altivec_vsumsws(a, b);
+}
+
+/* vec_trunc */
+
+static vector float __attribute__((__always_inline__))
+vec_trunc(vector float a)
+{
+ return __builtin_altivec_vrfiz(a);
+}
+
+/* vec_vrfiz */
+
+static vector float __attribute__((__always_inline__))
+vec_vrfiz(vector float a)
+{
+ return __builtin_altivec_vrfiz(a);
+}
+
+/* vec_unpackh */
+
+static vector short __ATTRS_o_ai
+vec_unpackh(vector signed char a)
+{
+ return __builtin_altivec_vupkhsb((vector char)a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_unpackh(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupkhsb((vector char)a);
+}
+
+static vector int __ATTRS_o_ai
+vec_unpackh(vector short a)
+{
+ return __builtin_altivec_vupkhsh(a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_unpackh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_unpackh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+/* vec_vupkhsb */
+
+static vector short __ATTRS_o_ai
+vec_vupkhsb(vector signed char a)
+{
+ return __builtin_altivec_vupkhsb((vector char)a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vupkhsb(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupkhsb((vector char)a);
+}
+
+/* vec_vupkhsh */
+
+static vector int __ATTRS_o_ai
+vec_vupkhsh(vector short a)
+{
+ return __builtin_altivec_vupkhsh(a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vupkhsh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vupkhsh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+/* vec_unpackl */
+
+static vector short __ATTRS_o_ai
+vec_unpackl(vector signed char a)
+{
+ return __builtin_altivec_vupklsb((vector char)a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_unpackl(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupklsb((vector char)a);
+}
+
+static vector int __ATTRS_o_ai
+vec_unpackl(vector short a)
+{
+ return __builtin_altivec_vupklsh(a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_unpackl(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_unpackl(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+/* vec_vupklsb */
+
+static vector short __ATTRS_o_ai
+vec_vupklsb(vector signed char a)
+{
+ return __builtin_altivec_vupklsb((vector char)a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vupklsb(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupklsb((vector char)a);
+}
+
+/* vec_vupklsh */
+
+static vector int __ATTRS_o_ai
+vec_vupklsh(vector short a)
+{
+ return __builtin_altivec_vupklsh(a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vupklsh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vupklsh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+/* vec_xor */
+
+#define __builtin_altivec_vxor vec_xor
+
+static vector signed char __ATTRS_o_ai
+vec_xor(vector signed char a, vector signed char b)
+{
+ return a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_xor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_xor(vector signed char a, vector bool char b)
+{
+ return a ^ (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_xor(vector unsigned char a, vector unsigned char b)
+{
+ return a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_xor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_xor(vector unsigned char a, vector bool char b)
+{
+ return a ^ (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_xor(vector bool char a, vector bool char b)
+{
+ return a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_xor(vector short a, vector short b)
+{
+ return a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_xor(vector bool short a, vector short b)
+{
+ return (vector short)a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_xor(vector short a, vector bool short b)
+{
+ return a ^ (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_xor(vector unsigned short a, vector unsigned short b)
+{
+ return a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_xor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_xor(vector unsigned short a, vector bool short b)
+{
+ return a ^ (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_xor(vector bool short a, vector bool short b)
+{
+ return a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_xor(vector int a, vector int b)
+{
+ return a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_xor(vector bool int a, vector int b)
+{
+ return (vector int)a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_xor(vector int a, vector bool int b)
+{
+ return a ^ (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_xor(vector unsigned int a, vector unsigned int b)
+{
+ return a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_xor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_xor(vector unsigned int a, vector bool int b)
+{
+ return a ^ (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_xor(vector bool int a, vector bool int b)
+{
+ return a ^ b;
+}
+
+static vector float __ATTRS_o_ai
+vec_xor(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_xor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_xor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* vec_vxor */
+
+static vector signed char __ATTRS_o_ai
+vec_vxor(vector signed char a, vector signed char b)
+{
+ return a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vxor(vector signed char a, vector bool char b)
+{
+ return a ^ (vector signed char)b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vxor(vector unsigned char a, vector unsigned char b)
+{
+ return a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vxor(vector unsigned char a, vector bool char b)
+{
+ return a ^ (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector bool char b)
+{
+ return a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vxor(vector short a, vector short b)
+{
+ return a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector short b)
+{
+ return (vector short)a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vxor(vector short a, vector bool short b)
+{
+ return a ^ (vector short)b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vxor(vector unsigned short a, vector unsigned short b)
+{
+ return a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vxor(vector unsigned short a, vector bool short b)
+{
+ return a ^ (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector bool short b)
+{
+ return a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vxor(vector int a, vector int b)
+{
+ return a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector int b)
+{
+ return (vector int)a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vxor(vector int a, vector bool int b)
+{
+ return a ^ (vector int)b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vxor(vector unsigned int a, vector unsigned int b)
+{
+ return a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vxor(vector unsigned int a, vector bool int b)
+{
+ return a ^ (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector bool int b)
+{
+ return a ^ b;
+}
+
+static vector float __ATTRS_o_ai
+vec_vxor(vector float a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vxor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vxor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+/* ------------------------ extensions for CBEA ----------------------------- */
+
+/* vec_extract */
+
+static signed char __ATTRS_o_ai
+vec_extract(vector signed char a, int b)
+{
+ return a[b];
+}
+
+static unsigned char __ATTRS_o_ai
+vec_extract(vector unsigned char a, int b)
+{
+ return a[b];
+}
+
+static short __ATTRS_o_ai
+vec_extract(vector short a, int b)
+{
+ return a[b];
+}
+
+static unsigned short __ATTRS_o_ai
+vec_extract(vector unsigned short a, int b)
+{
+ return a[b];
+}
+
+static int __ATTRS_o_ai
+vec_extract(vector int a, int b)
+{
+ return a[b];
+}
+
+static unsigned int __ATTRS_o_ai
+vec_extract(vector unsigned int a, int b)
+{
+ return a[b];
+}
+
+static float __ATTRS_o_ai
+vec_extract(vector float a, int b)
+{
+ return a[b];
+}
+
+/* vec_insert */
+
+static vector signed char __ATTRS_o_ai
+vec_insert(signed char a, vector signed char b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_insert(unsigned char a, vector unsigned char b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector short __ATTRS_o_ai
+vec_insert(short a, vector short b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_insert(unsigned short a, vector unsigned short b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector int __ATTRS_o_ai
+vec_insert(int a, vector int b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_insert(unsigned int a, vector unsigned int b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+static vector float __ATTRS_o_ai
+vec_insert(float a, vector float b, int c)
+{
+ b[c] = a;
+ return b;
+}
+
+/* vec_lvlx */
+
+static vector signed char __ATTRS_o_ai
+vec_lvlx(int a, const signed char *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector signed char)(0),
+ vec_lvsl(a, b));
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvlx(int a, const vector signed char *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector signed char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvlx(int a, const unsigned char *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned char)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvlx(int a, const vector unsigned char *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvlx(int a, const vector bool char *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector bool char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvlx(int a, const short *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector short)(0),
+ vec_lvsl(a, b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvlx(int a, const vector short *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvlx(int a, const unsigned short *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned short)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvlx(int a, const vector unsigned short *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvlx(int a, const vector bool short *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector bool short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvlx(int a, const vector pixel *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector pixel)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvlx(int a, const int *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector int)(0),
+ vec_lvsl(a, b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvlx(int a, const vector int *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvlx(int a, const unsigned int *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned int)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvlx(int a, const vector unsigned int *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector unsigned int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvlx(int a, const vector bool int *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector bool int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvlx(int a, const float *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector float)(0),
+ vec_lvsl(a, b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvlx(int a, const vector float *b)
+{
+ return vec_perm(vec_ld(a, b),
+ (vector float)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+/* vec_lvlxl */
+
+static vector signed char __ATTRS_o_ai
+vec_lvlxl(int a, const signed char *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector signed char)(0),
+ vec_lvsl(a, b));
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvlxl(int a, const vector signed char *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector signed char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvlxl(int a, const unsigned char *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned char)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvlxl(int a, const vector unsigned char *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvlxl(int a, const vector bool char *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector bool char)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvlxl(int a, const short *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector short)(0),
+ vec_lvsl(a, b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvlxl(int a, const vector short *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvlxl(int a, const unsigned short *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned short)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvlxl(int a, const vector unsigned short *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvlxl(int a, const vector bool short *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector bool short)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvlxl(int a, const vector pixel *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector pixel)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvlxl(int a, const int *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector int)(0),
+ vec_lvsl(a, b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvlxl(int a, const vector int *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvlxl(int a, const unsigned int *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned int)(0),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvlxl(int a, const vector unsigned int *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector unsigned int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvlxl(int a, const vector bool int *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector bool int)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvlxl(int a, const float *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector float)(0),
+ vec_lvsl(a, b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvlxl(int a, vector float *b)
+{
+ return vec_perm(vec_ldl(a, b),
+ (vector float)(0),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+/* vec_lvrx */
+
+static vector signed char __ATTRS_o_ai
+vec_lvrx(int a, const signed char *b)
+{
+ return vec_perm((vector signed char)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvrx(int a, const vector signed char *b)
+{
+ return vec_perm((vector signed char)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvrx(int a, const unsigned char *b)
+{
+ return vec_perm((vector unsigned char)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvrx(int a, const vector unsigned char *b)
+{
+ return vec_perm((vector unsigned char)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvrx(int a, const vector bool char *b)
+{
+ return vec_perm((vector bool char)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvrx(int a, const short *b)
+{
+ return vec_perm((vector short)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvrx(int a, const vector short *b)
+{
+ return vec_perm((vector short)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvrx(int a, const unsigned short *b)
+{
+ return vec_perm((vector unsigned short)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvrx(int a, const vector unsigned short *b)
+{
+ return vec_perm((vector unsigned short)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvrx(int a, const vector bool short *b)
+{
+ return vec_perm((vector bool short)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvrx(int a, const vector pixel *b)
+{
+ return vec_perm((vector pixel)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvrx(int a, const int *b)
+{
+ return vec_perm((vector int)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvrx(int a, const vector int *b)
+{
+ return vec_perm((vector int)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvrx(int a, const unsigned int *b)
+{
+ return vec_perm((vector unsigned int)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvrx(int a, const vector unsigned int *b)
+{
+ return vec_perm((vector unsigned int)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvrx(int a, const vector bool int *b)
+{
+ return vec_perm((vector bool int)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvrx(int a, const float *b)
+{
+ return vec_perm((vector float)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvrx(int a, const vector float *b)
+{
+ return vec_perm((vector float)(0),
+ vec_ld(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+/* vec_lvrxl */
+
+static vector signed char __ATTRS_o_ai
+vec_lvrxl(int a, const signed char *b)
+{
+ return vec_perm((vector signed char)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector signed char __ATTRS_o_ai
+vec_lvrxl(int a, const vector signed char *b)
+{
+ return vec_perm((vector signed char)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvrxl(int a, const unsigned char *b)
+{
+ return vec_perm((vector unsigned char)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_lvrxl(int a, const vector unsigned char *b)
+{
+ return vec_perm((vector unsigned char)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_lvrxl(int a, const vector bool char *b)
+{
+ return vec_perm((vector bool char)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvrxl(int a, const short *b)
+{
+ return vec_perm((vector short)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector short __ATTRS_o_ai
+vec_lvrxl(int a, const vector short *b)
+{
+ return vec_perm((vector short)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvrxl(int a, const unsigned short *b)
+{
+ return vec_perm((vector unsigned short)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_lvrxl(int a, const vector unsigned short *b)
+{
+ return vec_perm((vector unsigned short)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_lvrxl(int a, const vector bool short *b)
+{
+ return vec_perm((vector bool short)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvrxl(int a, const vector pixel *b)
+{
+ return vec_perm((vector pixel)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvrxl(int a, const int *b)
+{
+ return vec_perm((vector int)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector int __ATTRS_o_ai
+vec_lvrxl(int a, const vector int *b)
+{
+ return vec_perm((vector int)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvrxl(int a, const unsigned int *b)
+{
+ return vec_perm((vector unsigned int)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_lvrxl(int a, const vector unsigned int *b)
+{
+ return vec_perm((vector unsigned int)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_lvrxl(int a, const vector bool int *b)
+{
+ return vec_perm((vector bool int)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvrxl(int a, const float *b)
+{
+ return vec_perm((vector float)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, b));
+}
+
+static vector float __ATTRS_o_ai
+vec_lvrxl(int a, const vector float *b)
+{
+ return vec_perm((vector float)(0),
+ vec_ldl(a, b),
+ vec_lvsl(a, (unsigned char *)b));
+}
+
+/* vec_stvlx */
+
+static void __ATTRS_o_ai
+vec_stvlx(vector signed char a, int b, signed char *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector signed char a, int b, vector signed char *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned char a, int b, unsigned char *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned char a, int b, vector unsigned char *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector bool char a, int b, vector bool char *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector short a, int b, short *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector short a, int b, vector short *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned short a, int b, unsigned short *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned short a, int b, vector unsigned short *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector bool short a, int b, vector bool short *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector pixel a, int b, vector pixel *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector int a, int b, int *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector int a, int b, vector int *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned int a, int b, unsigned int *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector unsigned int a, int b, vector unsigned int *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector bool int a, int b, vector bool int *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlx(vector float a, int b, vector float *c)
+{
+ return vec_st(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+/* vec_stvlxl */
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector signed char a, int b, signed char *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector signed char a, int b, vector signed char *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned char a, int b, unsigned char *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned char a, int b, vector unsigned char *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector bool char a, int b, vector bool char *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector short a, int b, short *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector short a, int b, vector short *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned short a, int b, unsigned short *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned short a, int b, vector unsigned short *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector bool short a, int b, vector bool short *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector pixel a, int b, vector pixel *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector int a, int b, int *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector int a, int b, vector int *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned int a, int b, unsigned int *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector unsigned int a, int b, vector unsigned int *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector bool int a, int b, vector bool int *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvlxl(vector float a, int b, vector float *c)
+{
+ return vec_stl(vec_perm(vec_lvrx(b, c),
+ a,
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+/* vec_stvrx */
+
+static void __ATTRS_o_ai
+vec_stvrx(vector signed char a, int b, signed char *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector signed char a, int b, vector signed char *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned char a, int b, unsigned char *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned char a, int b, vector unsigned char *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector bool char a, int b, vector bool char *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector short a, int b, short *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector short a, int b, vector short *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned short a, int b, unsigned short *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned short a, int b, vector unsigned short *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector bool short a, int b, vector bool short *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector pixel a, int b, vector pixel *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector int a, int b, int *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector int a, int b, vector int *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned int a, int b, unsigned int *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector unsigned int a, int b, vector unsigned int *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector bool int a, int b, vector bool int *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrx(vector float a, int b, vector float *c)
+{
+ return vec_st(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+/* vec_stvrxl */
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector signed char a, int b, signed char *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector signed char a, int b, vector signed char *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned char a, int b, unsigned char *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned char a, int b, vector unsigned char *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector bool char a, int b, vector bool char *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector short a, int b, short *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector short a, int b, vector short *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned short a, int b, unsigned short *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned short a, int b, vector unsigned short *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector bool short a, int b, vector bool short *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector pixel a, int b, vector pixel *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector int a, int b, int *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector int a, int b, vector int *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned int a, int b, unsigned int *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector unsigned int a, int b, vector unsigned int *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector bool int a, int b, vector bool int *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvrxl(vector float a, int b, vector float *c)
+{
+ return vec_stl(vec_perm(a,
+ vec_lvlx(b, c),
+ vec_lvsr(b, (unsigned char *)c)),
+ b, c);
+}
+
+/* vec_promote */
+
+static vector signed char __ATTRS_o_ai
+vec_promote(signed char a, int b)
+{
+ vector signed char res = (vector signed char)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_promote(unsigned char a, int b)
+{
+ vector unsigned char res = (vector unsigned char)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector short __ATTRS_o_ai
+vec_promote(short a, int b)
+{
+ vector short res = (vector short)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_promote(unsigned short a, int b)
+{
+ vector unsigned short res = (vector unsigned short)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector int __ATTRS_o_ai
+vec_promote(int a, int b)
+{
+ vector int res = (vector int)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_promote(unsigned int a, int b)
+{
+ vector unsigned int res = (vector unsigned int)(0);
+ res[b] = a;
+ return res;
+}
+
+static vector float __ATTRS_o_ai
+vec_promote(float a, int b)
+{
+ vector float res = (vector float)(0);
+ res[b] = a;
+ return res;
+}
+
+/* vec_splats */
+
+static vector signed char __ATTRS_o_ai
+vec_splats(signed char a)
+{
+ return (vector signed char)(a);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_splats(unsigned char a)
+{
+ return (vector unsigned char)(a);
+}
+
+static vector short __ATTRS_o_ai
+vec_splats(short a)
+{
+ return (vector short)(a);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_splats(unsigned short a)
+{
+ return (vector unsigned short)(a);
+}
+
+static vector int __ATTRS_o_ai
+vec_splats(int a)
+{
+ return (vector int)(a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_splats(unsigned int a)
+{
+ return (vector unsigned int)(a);
+}
+
+static vector float __ATTRS_o_ai
+vec_splats(float a)
+{
+ return (vector float)(a);
+}
+
+/* ----------------------------- predicates --------------------------------- */
+
+/* vec_all_eq */
+
+static int __ATTRS_o_ai
+vec_all_eq(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector pixel a, vector pixel b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_LT, a, b);
+}
+
+/* vec_all_ge */
+
+static int __ATTRS_o_ai
+vec_all_ge(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_LT, a, b);
+}
+
+/* vec_all_gt */
+
+static int __ATTRS_o_ai
+vec_all_gt(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_LT, a, b);
+}
+
+/* vec_all_in */
+
+static int __attribute__((__always_inline__))
+vec_all_in(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpbfp_p(__CR6_EQ, a, b);
+}
+
+/* vec_all_le */
+
+static int __ATTRS_o_ai
+vec_all_le(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_LT, b, a);
+}
+
+/* vec_all_lt */
+
+static int __ATTRS_o_ai
+vec_all_lt(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_LT, b, a);
+}
+
+/* vec_all_nan */
+
+static int __attribute__((__always_inline__))
+vec_all_nan(vector float a)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, a, a);
+}
+
+/* vec_all_ne */
+
+static int __ATTRS_o_ai
+vec_all_ne(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector pixel a, vector pixel b)
+{
+ return
+ __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, a, b);
+}
+
+/* vec_all_nge */
+
+static int __attribute__((__always_inline__))
+vec_all_nge(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_EQ, a, b);
+}
+
+/* vec_all_ngt */
+
+static int __attribute__((__always_inline__))
+vec_all_ngt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, a, b);
+}
+
+/* vec_all_nle */
+
+static int __attribute__((__always_inline__))
+vec_all_nle(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_EQ, b, a);
+}
+
+/* vec_all_nlt */
+
+static int __attribute__((__always_inline__))
+vec_all_nlt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, b, a);
+}
+
+/* vec_all_numeric */
+
+static int __attribute__((__always_inline__))
+vec_all_numeric(vector float a)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_LT, a, a);
+}
+
+/* vec_any_eq */
+
+static int __ATTRS_o_ai
+vec_any_eq(vector signed char a, vector signed char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector signed char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector signed char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned int a, vector unsigned int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector unsigned int a, vector bool int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector unsigned int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector bool int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, a, b);
+}
+
+/* vec_any_ge */
+
+static int __ATTRS_o_ai
+vec_any_ge(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, a, b);
+}
+
+/* vec_any_gt */
+
+static int __ATTRS_o_ai
+vec_any_gt(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, a, b);
+}
+
+/* vec_any_le */
+
+static int __ATTRS_o_ai
+vec_any_le(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV,
+ (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV,
+ (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV,
+ (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, b, a);
+}
+
+/* vec_any_lt */
+
+static int __ATTRS_o_ai
+vec_any_lt(vector signed char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV,
+ (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV,
+ (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV,
+ (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, b, a);
+}
+
+/* vec_any_nan */
+
+static int __attribute__((__always_inline__))
+vec_any_nan(vector float a)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, a, a);
+}
+
+/* vec_any_ne */
+
+static int __ATTRS_o_ai
+vec_any_ne(vector signed char a, vector signed char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector signed char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector signed char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV,
+ (vector short)a,
+ (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned int a, vector unsigned int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector unsigned int a, vector bool int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector unsigned int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector bool int b)
+{
+ return
+ __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, a, b);
+}
+
+/* vec_any_nge */
+
+static int __attribute__((__always_inline__))
+vec_any_nge(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, a, b);
+}
+
+/* vec_any_ngt */
+
+static int __attribute__((__always_inline__))
+vec_any_ngt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, a, b);
+}
+
+/* vec_any_nle */
+
+static int __attribute__((__always_inline__))
+vec_any_nle(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, b, a);
+}
+
+/* vec_any_nlt */
+
+static int __attribute__((__always_inline__))
+vec_any_nlt(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, b, a);
+}
+
+/* vec_any_numeric */
+
+static int __attribute__((__always_inline__))
+vec_any_numeric(vector float a)
+{
+ return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, a, a);
+}
+
+/* vec_any_out */
+
+static int __attribute__((__always_inline__))
+vec_any_out(vector float a, vector float b)
+{
+ return __builtin_altivec_vcmpbfp_p(__CR6_EQ_REV, a, b);
+}
+
+#undef __ATTRS_o_ai
+
+#endif /* __ALTIVEC_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
new file mode 100644
index 0000000..884d31c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
@@ -0,0 +1,1156 @@
+/*===---- avxintrin.h - AVX intrinsics -------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <avxintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+typedef double __v4df __attribute__ ((__vector_size__ (32)));
+typedef float __v8sf __attribute__ ((__vector_size__ (32)));
+typedef long long __v4di __attribute__ ((__vector_size__ (32)));
+typedef int __v8si __attribute__ ((__vector_size__ (32)));
+typedef short __v16hi __attribute__ ((__vector_size__ (32)));
+typedef char __v32qi __attribute__ ((__vector_size__ (32)));
+
+typedef float __m256 __attribute__ ((__vector_size__ (32)));
+typedef double __m256d __attribute__((__vector_size__(32)));
+typedef long long __m256i __attribute__((__vector_size__(32)));
+
+/* Arithmetic */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_add_pd(__m256d a, __m256d b)
+{
+ return a+b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_add_ps(__m256 a, __m256 b)
+{
+ return a+b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_sub_pd(__m256d a, __m256d b)
+{
+ return a-b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_sub_ps(__m256 a, __m256 b)
+{
+ return a-b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_addsub_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_addsubpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_addsub_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_addsubps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_div_pd(__m256d a, __m256d b)
+{
+ return a / b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_div_ps(__m256 a, __m256 b)
+{
+ return a / b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_max_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_maxpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_max_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_maxps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_min_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_minpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_min_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_minps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_mul_pd(__m256d a, __m256d b)
+{
+ return a * b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_mul_ps(__m256 a, __m256 b)
+{
+ return a * b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_sqrt_pd(__m256d a)
+{
+ return (__m256d)__builtin_ia32_sqrtpd256((__v4df)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_sqrt_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_sqrtps256((__v8sf)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_rsqrt_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_rsqrtps256((__v8sf)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_rcp_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_rcpps256((__v8sf)a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_round_pd(__m256d v, const int m)
+{
+ return (__m256d)__builtin_ia32_roundpd256((__v4df)v, m);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_round_ps(__m256 v, const int m)
+{
+ return (__m256)__builtin_ia32_roundps256((__v8sf)v, m);
+}
+
+#define _mm256_ceil_pd(V) _mm256_round_pd((V), _MM_FROUND_CEIL)
+#define _mm256_floor_pd(V) _mm256_round_pd((V), _MM_FROUND_FLOOR)
+#define _mm256_ceil_ps(V) _mm256_round_ps((V), _MM_FROUND_CEIL)
+#define _mm256_floor_ps(V) _mm256_round_ps((V), _MM_FROUND_FLOOR)
+
+/* Logical */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_and_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a & (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_and_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a & (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_andnot_pd(__m256d a, __m256d b)
+{
+ return (__m256d)(~(__v4di)a & (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_andnot_ps(__m256 a, __m256 b)
+{
+ return (__m256)(~(__v8si)a & (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_or_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a | (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_or_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a | (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_xor_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a ^ (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_xor_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a ^ (__v8si)b);
+}
+
+/* Horizontal arithmetic */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_hadd_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_haddpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_hadd_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_haddps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_hsub_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_hsubpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_hsub_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_hsubps256((__v8sf)a, (__v8sf)b);
+}
+
+/* Vector permutations */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_permutevar_pd(__m128d a, __m128i c)
+{
+ return (__m128d)__builtin_ia32_vpermilvarpd((__v2df)a, (__v2di)c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permutevar_pd(__m256d a, __m256i c)
+{
+ return (__m256d)__builtin_ia32_vpermilvarpd256((__v4df)a, (__v4di)c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_permutevar_ps(__m128 a, __m128i c)
+{
+ return (__m128)__builtin_ia32_vpermilvarps((__v4sf)a, (__v4si)c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permutevar_ps(__m256 a, __m256i c)
+{
+ return (__m256)__builtin_ia32_vpermilvarps256((__v8sf)a,
+ (__v8si)c);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_permute_pd(__m128d a, const int c)
+{
+ return (__m128d)__builtin_ia32_vpermilpd((__v2df)a, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permute_pd(__m256d a, const int c)
+{
+ return (__m256d)__builtin_ia32_vpermilpd256((__v4df)a, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_permute_ps(__m128 a, const int c)
+{
+ return (__m128)__builtin_ia32_vpermilps((__v4sf)a, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permute_ps(__m256 a, const int c)
+{
+ return (__m256)__builtin_ia32_vpermilps256((__v8sf)a, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_si256(__m256i a, __m256i b, const int c)
+{
+ return (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)a, (__v8si)b, c);
+}
+
+/* Vector Blend */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_blend_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_blendpd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_blend_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_blendps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_blendv_pd(__m256d a, __m256d b, __m256d c)
+{
+ return (__m256d)__builtin_ia32_blendvpd256((__v4df)a, (__v4df)b, (__v4df)c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_blendv_ps(__m256 a, __m256 b, __m256 c)
+{
+ return (__m256)__builtin_ia32_blendvps256((__v8sf)a, (__v8sf)b, (__v8sf)c);
+}
+
+/* Vector Dot Product */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_dp_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_dpps256((__v8sf)a, (__v8sf)b, c);
+}
+
+/* Vector shuffle */
+#define _mm256_shuffle_ps(a, b, mask) \
+ (__builtin_shufflevector((__v8sf)(a), (__v8sf)(b), \
+ (mask) & 0x3, ((mask) & 0xc) >> 2, \
+ (((mask) & 0x30) >> 4) + 8, (((mask) & 0xc0) >> 6) + 8, \
+ (mask) & 0x3 + 4, (((mask) & 0xc) >> 2) + 4, \
+ (((mask) & 0x30) >> 4) + 12, (((mask) & 0xc0) >> 6) + 12))
+
+#define _mm256_shuffle_pd(a, b, mask) \
+ (__builtin_shufflevector((__v4df)(a), (__v4df)(b), \
+ (mask) & 0x1, \
+ (((mask) & 0x2) >> 1) + 4, \
+ (((mask) & 0x4) >> 2) + 2, \
+ (((mask) & 0x8) >> 3) + 6))
+
+/* Compare */
+#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
+#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */
+#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */
+#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */
+#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */
+#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */
+#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */
+#define _CMP_ORD_Q 0x07 /* Ordered (nonsignaling) */
+#define _CMP_EQ_UQ 0x08 /* Equal (unordered, non-signaling) */
+#define _CMP_NGE_US 0x09 /* Not-greater-than-or-equal (unord, signaling) */
+#define _CMP_NGT_US 0x0a /* Not-greater-than (unordered, signaling) */
+#define _CMP_FALSE_OQ 0x0b /* False (ordered, non-signaling) */
+#define _CMP_NEQ_OQ 0x0c /* Not-equal (ordered, non-signaling) */
+#define _CMP_GE_OS 0x0d /* Greater-than-or-equal (ordered, signaling) */
+#define _CMP_GT_OS 0x0e /* Greater-than (ordered, signaling) */
+#define _CMP_TRUE_UQ 0x0f /* True (unordered, non-signaling) */
+#define _CMP_EQ_OS 0x10 /* Equal (ordered, signaling) */
+#define _CMP_LT_OQ 0x11 /* Less-than (ordered, non-signaling) */
+#define _CMP_LE_OQ 0x12 /* Less-than-or-equal (ordered, non-signaling) */
+#define _CMP_UNORD_S 0x13 /* Unordered (signaling) */
+#define _CMP_NEQ_US 0x14 /* Not-equal (unordered, signaling) */
+#define _CMP_NLT_UQ 0x15 /* Not-less-than (unordered, non-signaling) */
+#define _CMP_NLE_UQ 0x16 /* Not-less-than-or-equal (unord, non-signaling) */
+#define _CMP_ORD_S 0x17 /* Ordered (signaling) */
+#define _CMP_EQ_US 0x18 /* Equal (unordered, signaling) */
+#define _CMP_NGE_UQ 0x19 /* Not-greater-than-or-equal (unord, non-sign) */
+#define _CMP_NGT_UQ 0x1a /* Not-greater-than (unordered, non-signaling) */
+#define _CMP_FALSE_OS 0x1b /* False (ordered, signaling) */
+#define _CMP_NEQ_OS 0x1c /* Not-equal (ordered, signaling) */
+#define _CMP_GE_OQ 0x1d /* Greater-than-or-equal (ordered, non-signaling) */
+#define _CMP_GT_OQ 0x1e /* Greater-than (ordered, non-signaling) */
+#define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_pd(__m128d a, __m128d b, const int c)
+{
+ return (__m128d)__builtin_ia32_cmppd((__v2df)a, (__v2df)b, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_ps(__m128 a, __m128 b, const int c)
+{
+ return (__m128)__builtin_ia32_cmpps((__v4sf)a, (__v4sf)b, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cmp_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_cmppd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_cmp_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_cmpps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_sd(__m128d a, __m128d b, const int c)
+{
+ return (__m128d)__builtin_ia32_cmpsd((__v2df)a, (__v2df)b, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_ss(__m128 a, __m128 b, const int c)
+{
+ return (__m128)__builtin_ia32_cmpss((__v4sf)a, (__v4sf)b, c);
+}
+
+/* Vector extract */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_pd(__m256d a, const int o)
+{
+ return (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)a, o);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_ps(__m256 a, const int o)
+{
+ return (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)a, o);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_si256(__m256i a, const int o)
+{
+ return (__m128i)__builtin_ia32_vextractf128_si256((__v8si)a, o);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi32(__m256i a, int const imm)
+{
+ __v8si b = (__v8si)a;
+ return b[imm];
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi16(__m256i a, int const imm)
+{
+ __v16hi b = (__v16hi)a;
+ return b[imm];
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi8(__m256i a, int const imm)
+{
+ __v32qi b = (__v32qi)a;
+ return b[imm];
+}
+
+#ifdef __x86_64__
+static __inline long long __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi64(__m256i a, const int imm)
+{
+ __v4di b = (__v4di)a;
+ return b[imm];
+}
+#endif
+
+/* Vector insert */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_pd(__m256d a, __m128d b, const int o)
+{
+ return (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)a, (__v2df)b, o);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_ps(__m256 a, __m128 b, const int o)
+{
+ return (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)a, (__v4sf)b, o);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_si256(__m256i a, __m128i b, const int o)
+{
+ return (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)a, (__v4si)b, o);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi32(__m256i a, int b, int const imm)
+{
+ __v8si c = (__v8si)a;
+ c[imm & 7] = b;
+ return (__m256i)c;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi16(__m256i a, int b, int const imm)
+{
+ __v16hi c = (__v16hi)a;
+ c[imm & 15] = b;
+ return (__m256i)c;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi8(__m256i a, int b, int const imm)
+{
+ __v32qi c = (__v32qi)a;
+ c[imm & 31] = b;
+ return (__m256i)c;
+}
+
+#ifdef __x86_64__
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi64(__m256i a, int b, int const imm)
+{
+ __v4di c = (__v4di)a;
+ c[imm & 3] = b;
+ return (__m256i)c;
+}
+#endif
+
+/* Conversion */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtepi32_pd(__m128i a)
+{
+ return (__m256d)__builtin_ia32_cvtdq2pd256((__v4si) a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtepi32_ps(__m256i a)
+{
+ return (__m256)__builtin_ia32_cvtdq2ps256((__v8si) a);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtpd_ps(__m256d a)
+{
+ return (__m128)__builtin_ia32_cvtpd2ps256((__v4df) a);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtps_epi32(__m256 a)
+{
+ return (__m256i)__builtin_ia32_cvtps2dq256((__v8sf) a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtps_pd(__m128 a)
+{
+ return (__m256d)__builtin_ia32_cvtps2pd256((__v4sf) a);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvttpd_epi32(__m256d a)
+{
+ return (__m128i)__builtin_ia32_cvttpd2dq256((__v4df) a);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtpd_epi32(__m256d a)
+{
+ return (__m128i)__builtin_ia32_cvtpd2dq256((__v4df) a);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvttps_epi32(__m256 a)
+{
+ return (__m256i)__builtin_ia32_cvttps2dq256((__v8sf) a);
+}
+
+/* Vector replicate */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_movehdup_ps(__m256 a)
+{
+ return __builtin_shufflevector(a, a, 1, 1, 3, 3, 5, 5, 7, 7);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_moveldup_ps(__m256 a)
+{
+ return __builtin_shufflevector(a, a, 0, 0, 2, 2, 4, 4, 6, 6);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_movedup_pd(__m256d a)
+{
+ return __builtin_shufflevector(a, a, 0, 0, 2, 2);
+}
+
+/* Unpack and Interleave */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_unpackhi_pd(__m256d a, __m256d b)
+{
+ return __builtin_shufflevector(a, b, 1, 5, 1+2, 5+2);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_unpacklo_pd(__m256d a, __m256d b)
+{
+ return __builtin_shufflevector(a, b, 0, 4, 0+2, 4+2);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_unpackhi_ps(__m256 a, __m256 b)
+{
+ return __builtin_shufflevector(a, b, 2, 10, 2+1, 10+1, 6, 14, 6+1, 14+1);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_unpacklo_ps(__m256 a, __m256 b)
+{
+ return __builtin_shufflevector(a, b, 0, 8, 0+1, 8+1, 4, 12, 4+1, 12+1);
+}
+
+/* Bit Test */
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testz_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestzpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testc_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestcpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testnzc_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestnzcpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testz_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestzps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testc_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestcps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testnzc_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestnzcps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestzpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestcpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestnzcpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestzps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestcps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestnzcps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestz256((__v4di)a, (__v4di)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestc256((__v4di)a, (__v4di)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestnzc256((__v4di)a, (__v4di)b);
+}
+
+/* Vector extract sign mask */
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_movemask_pd(__m256d a)
+{
+ return __builtin_ia32_movmskpd256((__v4df)a);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_movemask_ps(__m256 a)
+{
+ return __builtin_ia32_movmskps256((__v8sf)a);
+}
+
+/* Vector zero */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_zeroall(void)
+{
+ __builtin_ia32_vzeroall();
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_zeroupper(void)
+{
+ __builtin_ia32_vzeroupper();
+}
+
+/* Vector load with broadcast */
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_broadcast_ss(float const *a)
+{
+ return (__m128)__builtin_ia32_vbroadcastss(a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_sd(double const *a)
+{
+ return (__m256d)__builtin_ia32_vbroadcastsd256(a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_ss(float const *a)
+{
+ return (__m256)__builtin_ia32_vbroadcastss256(a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_pd(__m128d const *a)
+{
+ return (__m256d)__builtin_ia32_vbroadcastf128_pd256(a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_ps(__m128 const *a)
+{
+ return (__m256)__builtin_ia32_vbroadcastf128_ps256(a);
+}
+
+/* SIMD load ops */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_load_pd(double const *p)
+{
+ return *(__m256d *)p;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_load_ps(float const *p)
+{
+ return *(__m256 *)p;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_pd(double const *p)
+{
+ return (__m256d)__builtin_ia32_loadupd256(p);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_ps(float const *p)
+{
+ return (__m256)__builtin_ia32_loadups256(p);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_load_si256(__m256i const *p)
+{
+ return *p;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_si256(__m256i const *p)
+{
+ return (__m256i)__builtin_ia32_loaddqu256((char const *)p);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_lddqu_si256(__m256i const *p)
+{
+ return (__m256i)__builtin_ia32_lddqu256((char const *)p);
+}
+
+/* SIMD store ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_pd(double *p, __m256d a)
+{
+ *(__m256d *)p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_ps(float *p, __m256 a)
+{
+ *(__m256 *)p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_pd(double *p, __m256d a)
+{
+ __builtin_ia32_storeupd256(p, (__v4df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_ps(float *p, __m256 a)
+{
+ __builtin_ia32_storeups256(p, (__v8sf)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_si256(__m256i *p, __m256i a)
+{
+ *p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_si256(__m256i *p, __m256i a)
+{
+ __builtin_ia32_storedqu256((char *)p, (__v32qi)a);
+}
+
+/* Conditional load ops */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_maskload_pd(double const *p, __m128d m)
+{
+ return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)p, (__v2df)m);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_maskload_pd(double const *p, __m256d m)
+{
+ return (__m256d)__builtin_ia32_maskloadpd256((const __v4df *)p, (__v4df)m);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_maskload_ps(float const *p, __m128 m)
+{
+ return (__m128)__builtin_ia32_maskloadps((const __v4sf *)p, (__v4sf)m);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_maskload_ps(float const *p, __m256 m)
+{
+ return (__m256)__builtin_ia32_maskloadps256((const __v8sf *)p, (__v8sf)m);
+}
+
+/* Conditional store ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_maskstore_ps(float *p, __m256 m, __m256 a)
+{
+ __builtin_ia32_maskstoreps256((__v8sf *)p, (__v8sf)m, (__v8sf)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm_maskstore_pd(double *p, __m128d m, __m128d a)
+{
+ __builtin_ia32_maskstorepd((__v2df *)p, (__v2df)m, (__v2df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_maskstore_pd(double *p, __m256d m, __m256d a)
+{
+ __builtin_ia32_maskstorepd256((__v4df *)p, (__v4df)m, (__v4df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm_maskstore_ps(float *p, __m128 m, __m128 a)
+{
+ __builtin_ia32_maskstoreps((__v4sf *)p, (__v4sf)m, (__v4sf)a);
+}
+
+/* Cacheability support ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_si256(__m256i *a, __m256i b)
+{
+ __builtin_ia32_movntdq256((__v4di *)a, (__v4di)b);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_pd(double *a, __m256d b)
+{
+ __builtin_ia32_movntpd256(a, (__v4df)b);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_ps(float *p, __m256 a)
+{
+ __builtin_ia32_movntps256(p, (__v8sf)a);
+}
+
+/* Create vectors */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_set_pd(double a, double b, double c, double d)
+{
+ return (__m256d){ d, c, b, a };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_set_ps(float a, float b, float c, float d,
+ float e, float f, float g, float h)
+{
+ return (__m256){ h, g, f, e, d, c, b, a };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi32(int i0, int i1, int i2, int i3,
+ int i4, int i5, int i6, int i7)
+{
+ return (__m256i)(__v8si){ i7, i6, i5, i4, i3, i2, i1, i0 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi16(short w15, short w14, short w13, short w12,
+ short w11, short w10, short w09, short w08,
+ short w07, short w06, short w05, short w04,
+ short w03, short w02, short w01, short w00)
+{
+ return (__m256i)(__v16hi){ w00, w01, w02, w03, w04, w05, w06, w07,
+ w08, w09, w10, w11, w12, w13, w14, w15 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi8(char b31, char b30, char b29, char b28,
+ char b27, char b26, char b25, char b24,
+ char b23, char b22, char b21, char b20,
+ char b19, char b18, char b17, char b16,
+ char b15, char b14, char b13, char b12,
+ char b11, char b10, char b09, char b08,
+ char b07, char b06, char b05, char b04,
+ char b03, char b02, char b01, char b00)
+{
+ return (__m256i)(__v32qi){
+ b00, b01, b02, b03, b04, b05, b06, b07,
+ b08, b09, b10, b11, b12, b13, b14, b15,
+ b16, b17, b18, b19, b20, b21, b22, b23,
+ b24, b25, b26, b27, b28, b29, b30, b31
+ };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi64x(long long a, long long b, long long c, long long d)
+{
+ return (__m256i)(__v4di){ d, c, b, a };
+}
+
+/* Create vectors with elements in reverse order */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_pd(double a, double b, double c, double d)
+{
+ return (__m256d){ a, b, c, d };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_ps(float a, float b, float c, float d,
+ float e, float f, float g, float h)
+{
+ return (__m256){ a, b, c, d, e, f, g, h };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi32(int i0, int i1, int i2, int i3,
+ int i4, int i5, int i6, int i7)
+{
+ return (__m256i)(__v8si){ i0, i1, i2, i3, i4, i5, i6, i7 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi16(short w15, short w14, short w13, short w12,
+ short w11, short w10, short w09, short w08,
+ short w07, short w06, short w05, short w04,
+ short w03, short w02, short w01, short w00)
+{
+ return (__m256i)(__v16hi){ w15, w14, w13, w12, w11, w10, w09, w08,
+ w07, w06, w05, w04, w03, w02, w01, w00 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi8(char b31, char b30, char b29, char b28,
+ char b27, char b26, char b25, char b24,
+ char b23, char b22, char b21, char b20,
+ char b19, char b18, char b17, char b16,
+ char b15, char b14, char b13, char b12,
+ char b11, char b10, char b09, char b08,
+ char b07, char b06, char b05, char b04,
+ char b03, char b02, char b01, char b00)
+{
+ return (__m256i)(__v32qi){
+ b31, b30, b29, b28, b27, b26, b25, b24,
+ b23, b22, b21, b20, b19, b18, b17, b16,
+ b15, b14, b13, b12, b11, b10, b09, b08,
+ b07, b06, b05, b04, b03, b02, b01, b00 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi64x(long long a, long long b, long long c, long long d)
+{
+ return (__m256i)(__v4di){ a, b, c, d };
+}
+
+/* Create vectors with repeated elements */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_pd(double w)
+{
+ return (__m256d){ w, w, w, w };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_ps(float w)
+{
+ return (__m256){ w, w, w, w, w, w, w, w };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi32(int i)
+{
+ return (__m256i)(__v8si){ i, i, i, i, i, i, i, i };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi16(short w)
+{
+ return (__m256i)(__v16hi){ w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi8(char b)
+{
+ return (__m256i)(__v32qi){ b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b,
+ b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi64x(long long q)
+{
+ return (__m256i)(__v4di){ q, q, q, q };
+}
+
+/* Create zeroed vectors */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_pd(void)
+{
+ return (__m256d){ 0, 0, 0, 0 };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_ps(void)
+{
+ return (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_si256(void)
+{
+ return (__m256i){ 0LL, 0LL, 0LL, 0LL };
+}
+
+/* Cast between vector types */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd_ps(__m256d in)
+{
+ return (__m256)in;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd_si256(__m256d in)
+{
+ return (__m256i)in;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castps_pd(__m256 in)
+{
+ return (__m256d)in;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castps_si256(__m256 in)
+{
+ return (__m256i)in;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_ps(__m256i in)
+{
+ return (__m256)in;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_pd(__m256i in)
+{
+ return (__m256d)in;
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd256_pd128(__m256d in)
+{
+ return __builtin_shufflevector(in, in, 0, 1);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_castps256_ps128(__m256 in)
+{
+ return __builtin_shufflevector(in, in, 0, 1, 2, 3);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_si128(__m256i in)
+{
+ return __builtin_shufflevector(in, in, 0, 1);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd128_pd256(__m128d in)
+{
+ __m128d zero = _mm_setzero_pd();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 2);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castps128_ps256(__m128 in)
+{
+ __m128 zero = _mm_setzero_ps();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 3, 4, 4, 4, 4);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi128_si256(__m128i in)
+{
+ __m128i zero = _mm_setzero_si128();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 2);
+}
diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
new file mode 100644
index 0000000..11b2581
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
@@ -0,0 +1,1362 @@
+/*===---- emmintrin.h - SSE2 intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __EMMINTRIN_H
+#define __EMMINTRIN_H
+
+#ifndef __SSE2__
+#error "SSE2 instruction set not enabled"
+#else
+
+#include <xmmintrin.h>
+
+typedef double __m128d __attribute__((__vector_size__(16)));
+typedef long long __m128i __attribute__((__vector_size__(16)));
+
+/* Type defines. */
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef long long __v2di __attribute__ ((__vector_size__ (16)));
+typedef short __v8hi __attribute__((__vector_size__(16)));
+typedef char __v16qi __attribute__((__vector_size__(16)));
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_add_sd(__m128d a, __m128d b)
+{
+ a[0] += b[0];
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_add_pd(__m128d a, __m128d b)
+{
+ return a + b;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_sub_sd(__m128d a, __m128d b)
+{
+ a[0] -= b[0];
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_sub_pd(__m128d a, __m128d b)
+{
+ return a - b;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_mul_sd(__m128d a, __m128d b)
+{
+ a[0] *= b[0];
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_mul_pd(__m128d a, __m128d b)
+{
+ return a * b;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_div_sd(__m128d a, __m128d b)
+{
+ a[0] /= b[0];
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_div_pd(__m128d a, __m128d b)
+{
+ return a / b;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_sqrt_sd(__m128d a, __m128d b)
+{
+ __m128d c = __builtin_ia32_sqrtsd(b);
+ return (__m128d) { c[0], a[1] };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_sqrt_pd(__m128d a)
+{
+ return __builtin_ia32_sqrtpd(a);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_min_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_minsd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_min_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_minpd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_max_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_maxsd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_max_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_maxpd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_and_pd(__m128d a, __m128d b)
+{
+ return (__m128d)((__v4si)a & (__v4si)b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_andnot_pd(__m128d a, __m128d b)
+{
+ return (__m128d)(~(__v4si)a & (__v4si)b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_or_pd(__m128d a, __m128d b)
+{
+ return (__m128d)((__v4si)a | (__v4si)b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_xor_pd(__m128d a, __m128d b)
+{
+ return (__m128d)((__v4si)a ^ (__v4si)b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 0);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmple_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(b, a, 1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpge_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(b, a, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpord_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 7);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpunord_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 3);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpneq_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 4);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnlt_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 5);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnle_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(a, b, 6);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpngt_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(b, a, 5);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnge_pd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmppd(b, a, 6);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 0);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmple_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(b, a, 1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpge_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(b, a, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpord_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 7);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpunord_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 3);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpneq_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 4);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnlt_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 5);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnle_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(a, b, 6);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpngt_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(b, a, 5);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnge_sd(__m128d a, __m128d b)
+{
+ return (__m128d)__builtin_ia32_cmpsd(b, a, 6);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comieq_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_comisdeq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comilt_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_comisdlt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comile_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_comisdle(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comigt_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_comisdgt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comineq_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_comisdneq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomieq_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_ucomisdeq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomilt_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_ucomisdlt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomile_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_ucomisdle(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomigt_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_ucomisdgt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomineq_sd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_ucomisdneq(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpd_ps(__m128d a)
+{
+ return __builtin_ia32_cvtpd2ps(a);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtps_pd(__m128 a)
+{
+ return __builtin_ia32_cvtps2pd(a);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi32_pd(__m128i a)
+{
+ return __builtin_ia32_cvtdq2pd((__v4si)a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpd_epi32(__m128d a)
+{
+ return __builtin_ia32_cvtpd2dq(a);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsd_si32(__m128d a)
+{
+ return __builtin_ia32_cvtsd2si(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsd_ss(__m128 a, __m128d b)
+{
+ a[0] = b[0];
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi32_sd(__m128d a, int b)
+{
+ a[0] = b;
+ return a;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtss_sd(__m128d a, __m128 b)
+{
+ a[0] = b[0];
+ return a;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvttpd_epi32(__m128d a)
+{
+ return (__m128i)__builtin_ia32_cvttpd2dq(a);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvttsd_si32(__m128d a)
+{
+ return a[0];
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpd_pi32(__m128d a)
+{
+ return (__m64)__builtin_ia32_cvtpd2pi(a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvttpd_pi32(__m128d a)
+{
+ return (__m64)__builtin_ia32_cvttpd2pi(a);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpi32_pd(__m64 a)
+{
+ return __builtin_ia32_cvtpi2pd((__v2si)a);
+}
+
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsd_f64(__m128d a)
+{
+ return a[0];
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_load_pd(double const *dp)
+{
+ return *(__m128d*)dp;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_load1_pd(double const *dp)
+{
+ return (__m128d){ dp[0], dp[0] };
+}
+
+#define _mm_load_pd1(dp) _mm_load1_pd(dp)
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_loadr_pd(double const *dp)
+{
+ return (__m128d){ dp[1], dp[0] };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_loadu_pd(double const *dp)
+{
+ return __builtin_ia32_loadupd(dp);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_load_sd(double const *dp)
+{
+ return (__m128d){ *dp, 0.0 };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_loadh_pd(__m128d a, double const *dp)
+{
+ return __builtin_shufflevector(a, *(__m128d *)dp, 0, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_loadl_pd(__m128d a, double const *dp)
+{
+ return __builtin_shufflevector(a, *(__m128d *)dp, 2, 1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_set_sd(double w)
+{
+ return (__m128d){ w, 0 };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_set1_pd(double w)
+{
+ return (__m128d){ w, w };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_set_pd(double w, double x)
+{
+ return (__m128d){ x, w };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_setr_pd(double w, double x)
+{
+ return (__m128d){ w, x };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_setzero_pd(void)
+{
+ return (__m128d){ 0, 0 };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_move_sd(__m128d a, __m128d b)
+{
+ return (__m128d){ b[0], a[1] };
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_sd(double *dp, __m128d a)
+{
+ dp[0] = a[0];
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store1_pd(double *dp, __m128d a)
+{
+ dp[0] = a[0];
+ dp[1] = a[0];
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_pd(double *dp, __m128d a)
+{
+ *(__m128d *)dp = a;
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storeu_pd(double *dp, __m128d a)
+{
+ __builtin_ia32_storeupd(dp, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storer_pd(double *dp, __m128d a)
+{
+ dp[0] = a[1];
+ dp[1] = a[0];
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storeh_pd(double *dp, __m128d a)
+{
+ dp[0] = a[1];
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storel_pd(double *dp, __m128d a)
+{
+ dp[0] = a[0];
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_add_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)((__v16qi)a + (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_add_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)((__v8hi)a + (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_add_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)((__v4si)a + (__v4si)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_add_si64(__m64 a, __m64 b)
+{
+ return a + b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_add_epi64(__m128i a, __m128i b)
+{
+ return a + b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_adds_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_paddsb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_adds_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_paddsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_adds_epu8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_paddusb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_adds_epu16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_paddusw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_avg_epu8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pavgb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_avg_epu16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pavgw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_madd_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmaddwd128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmaxsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epu8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmaxub128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pminsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epu8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pminub128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mulhi_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmulhw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mulhi_epu16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmulhuw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mullo_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)((__v8hi)a * (__v8hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_mul_su32(__m64 a, __m64 b)
+{
+ return __builtin_ia32_pmuludq((__v2si)a, (__v2si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mul_epu32(__m128i a, __m128i b)
+{
+ return __builtin_ia32_pmuludq128((__v4si)a, (__v4si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sad_epu8(__m128i a, __m128i b)
+{
+ return __builtin_ia32_psadbw128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sub_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)((__v16qi)a - (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sub_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)((__v8hi)a - (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sub_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)((__v4si)a - (__v4si)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_si64(__m64 a, __m64 b)
+{
+ return a - b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sub_epi64(__m128i a, __m128i b)
+{
+ return a - b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_subs_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psubsb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_subs_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psubsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_subs_epu8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psubusb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_subs_epu16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psubusw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_and_si128(__m128i a, __m128i b)
+{
+ return a & b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_andnot_si128(__m128i a, __m128i b)
+{
+ return ~a & b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_or_si128(__m128i a, __m128i b)
+{
+ return a | b;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_xor_si128(__m128i a, __m128i b)
+{
+ return a ^ b;
+}
+
+#define _mm_slli_si128(VEC, IMM) \
+ ((__m128i)__builtin_ia32_pslldqi128((__m128i)(VEC), (IMM)*8))
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_slli_epi16(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_psllwi128((__v8hi)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sll_epi16(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_psllw128((__v8hi)a, (__v8hi)count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_slli_epi32(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_pslldi128((__v4si)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sll_epi32(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_pslld128((__v4si)a, (__v4si)count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_slli_epi64(__m128i a, int count)
+{
+ return __builtin_ia32_psllqi128(a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sll_epi64(__m128i a, __m128i count)
+{
+ return __builtin_ia32_psllq128(a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srai_epi16(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_psrawi128((__v8hi)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sra_epi16(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_psraw128((__v8hi)a, (__v8hi)count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srai_epi32(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_psradi128((__v4si)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sra_epi32(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_psrad128((__v4si)a, (__v4si)count);
+}
+
+
+#define _mm_srli_si128(VEC, IMM) \
+ ((__m128i)__builtin_ia32_psrldqi128((__m128i)(VEC), (IMM)*8))
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srli_epi16(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_psrlwi128((__v8hi)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srl_epi16(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_psrlw128((__v8hi)a, (__v8hi)count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srli_epi32(__m128i a, int count)
+{
+ return (__m128i)__builtin_ia32_psrldi128((__v4si)a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srl_epi32(__m128i a, __m128i count)
+{
+ return (__m128i)__builtin_ia32_psrld128((__v4si)a, (__v4si)count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srli_epi64(__m128i a, int count)
+{
+ return __builtin_ia32_psrlqi128(a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_srl_epi64(__m128i a, __m128i count)
+{
+ return __builtin_ia32_psrlq128(a, count);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)((__v16qi)a == (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)((__v8hi)a == (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)((__v4si)a == (__v4si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)((__v16qi)a > (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)((__v8hi)a > (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)((__v4si)a > (__v4si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_epi8(__m128i a, __m128i b)
+{
+ return _mm_cmpgt_epi8(b,a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_epi16(__m128i a, __m128i b)
+{
+ return _mm_cmpgt_epi16(b,a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_epi32(__m128i a, __m128i b)
+{
+ return _mm_cmpgt_epi32(b,a);
+}
+
+#ifdef __x86_64__
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi64_sd(__m128d a, long long b)
+{
+ a[0] = b;
+ return a;
+}
+
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsd_si64(__m128d a)
+{
+ return __builtin_ia32_cvtsd2si64(a);
+}
+
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvttsd_si64(__m128d a)
+{
+ return a[0];
+}
+#endif
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi32_ps(__m128i a)
+{
+ return __builtin_ia32_cvtdq2ps((__v4si)a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtps_epi32(__m128 a)
+{
+ return (__m128i)__builtin_ia32_cvtps2dq(a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvttps_epi32(__m128 a)
+{
+ return (__m128i)__builtin_ia32_cvttps2dq(a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi32_si128(int a)
+{
+ return (__m128i)(__v4si){ a, 0, 0, 0 };
+}
+
+#ifdef __x86_64__
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi64_si128(long long a)
+{
+ return (__m128i){ a, 0 };
+}
+#endif
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi128_si32(__m128i a)
+{
+ __v4si b = (__v4si)a;
+ return b[0];
+}
+
+#ifdef __x86_64__
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi128_si64(__m128i a)
+{
+ return a[0];
+}
+#endif
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_load_si128(__m128i const *p)
+{
+ return *p;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_loadu_si128(__m128i const *p)
+{
+ return (__m128i)__builtin_ia32_loaddqu((char const *)p);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_loadl_epi64(__m128i const *p)
+{
+ return (__m128i) { *(long long*)p, 0};
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set_epi64x(long long q1, long long q0)
+{
+ return (__m128i){ q0, q1 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set_epi64(__m64 q1, __m64 q0)
+{
+ return (__m128i){ (long long)q0, (long long)q1 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set_epi32(int i3, int i2, int i1, int i0)
+{
+ return (__m128i)(__v4si){ i0, i1, i2, i3};
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set_epi16(short w7, short w6, short w5, short w4, short w3, short w2, short w1, short w0)
+{
+ return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set_epi8(char b15, char b14, char b13, char b12, char b11, char b10, char b9, char b8, char b7, char b6, char b5, char b4, char b3, char b2, char b1, char b0)
+{
+ return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set1_epi64x(long long q)
+{
+ return (__m128i){ q, q };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set1_epi64(__m64 q)
+{
+ return (__m128i){ (long long)q, (long long)q };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set1_epi32(int i)
+{
+ return (__m128i)(__v4si){ i, i, i, i };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set1_epi16(short w)
+{
+ return (__m128i)(__v8hi){ w, w, w, w, w, w, w, w };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_set1_epi8(char b)
+{
+ return (__m128i)(__v16qi){ b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_setr_epi64(__m64 q0, __m64 q1)
+{
+ return (__m128i){ (long long)q0, (long long)q1 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_setr_epi32(int i0, int i1, int i2, int i3)
+{
+ return (__m128i)(__v4si){ i0, i1, i2, i3};
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_setr_epi16(short w0, short w1, short w2, short w3, short w4, short w5, short w6, short w7)
+{
+ return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_setr_epi8(char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
+{
+ return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_setzero_si128(void)
+{
+ return (__m128i){ 0LL, 0LL };
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_si128(__m128i *p, __m128i b)
+{
+ *p = b;
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storeu_si128(__m128i *p, __m128i b)
+{
+ __builtin_ia32_storedqu((char *)p, (__v16qi)b);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_maskmoveu_si128(__m128i d, __m128i n, char *p)
+{
+ __builtin_ia32_maskmovdqu((__v16qi)d, (__v16qi)n, p);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storel_epi64(__m128i *p, __m128i a)
+{
+ __builtin_ia32_storelv4si((__v2si *)p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_stream_pd(double *p, __m128d a)
+{
+ __builtin_ia32_movntpd(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_stream_si128(__m128i *p, __m128i a)
+{
+ __builtin_ia32_movntdq(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_stream_si32(int *p, int a)
+{
+ __builtin_ia32_movnti(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_clflush(void const *p)
+{
+ __builtin_ia32_clflush(p);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_lfence(void)
+{
+ __builtin_ia32_lfence();
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_mfence(void)
+{
+ __builtin_ia32_mfence();
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_packs_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_packsswb128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_packs_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_packssdw128((__v4si)a, (__v4si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_packus_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_packuswb128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_extract_epi16(__m128i a, int imm)
+{
+ __v8hi b = (__v8hi)a;
+ return (unsigned short)b[imm];
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_insert_epi16(__m128i a, int b, int imm)
+{
+ __v8hi c = (__v8hi)a;
+ c[imm & 7] = b;
+ return (__m128i)c;
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_movemask_epi8(__m128i a)
+{
+ return __builtin_ia32_pmovmskb128((__v16qi)a);
+}
+
+#define _mm_shuffle_epi32(a, imm) \
+ ((__m128i)__builtin_shufflevector((__v4si)(a), (__v4si) {0}, \
+ (imm) & 0x3, ((imm) & 0xc) >> 2, \
+ ((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6))
+#define _mm_shufflelo_epi16(a, imm) \
+ ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) {0}, \
+ (imm) & 0x3, ((imm) & 0xc) >> 2, \
+ ((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \
+ 4, 5, 6, 7))
+#define _mm_shufflehi_epi16(a, imm) \
+ ((__m128i)__builtin_shufflevector((__v8hi)(a), (__v8hi) {0}, 0, 1, 2, 3, \
+ 4 + (((imm) & 0x03) >> 0), \
+ 4 + (((imm) & 0x0c) >> 2), \
+ 4 + (((imm) & 0x30) >> 4), \
+ 4 + (((imm) & 0xc0) >> 6)))
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v16qi)a, (__v16qi)b, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v8hi)a, (__v8hi)b, 4, 8+4, 5, 8+5, 6, 8+6, 7, 8+7);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v4si)a, (__v4si)b, 2, 4+2, 3, 4+3);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_epi64(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector(a, b, 1, 2+1);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v16qi)a, (__v16qi)b, 0, 16+0, 1, 16+1, 2, 16+2, 3, 16+3, 4, 16+4, 5, 16+5, 6, 16+6, 7, 16+7);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v8hi)a, (__v8hi)b, 0, 8+0, 1, 8+1, 2, 8+2, 3, 8+3);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector((__v4si)a, (__v4si)b, 0, 4+0, 1, 4+1);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_epi64(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_shufflevector(a, b, 0, 2+0);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_movepi64_pi64(__m128i a)
+{
+ return (__m64)a[0];
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_movpi64_pi64(__m64 a)
+{
+ return (__m128i){ (long long)a, 0 };
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_move_epi64(__m128i a)
+{
+ return __builtin_shufflevector(a, (__m128i){ 0 }, 0, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_pd(__m128d a, __m128d b)
+{
+ return __builtin_shufflevector(a, b, 1, 2+1);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_pd(__m128d a, __m128d b)
+{
+ return __builtin_shufflevector(a, b, 0, 2+0);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_movemask_pd(__m128d a)
+{
+ return __builtin_ia32_movmskpd(a);
+}
+
+#define _mm_shuffle_pd(a, b, i) \
+ (__builtin_shufflevector((__m128d)(a), (__m128d)(b), (i) & 1, \
+ (((i) & 2) >> 1) + 2))
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_castpd_ps(__m128d in)
+{
+ return (__m128)in;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_castpd_si128(__m128d in)
+{
+ return (__m128i)in;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_castps_pd(__m128 in)
+{
+ return (__m128d)in;
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_castps_si128(__m128 in)
+{
+ return (__m128i)in;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_castsi128_ps(__m128i in)
+{
+ return (__m128)in;
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_castsi128_pd(__m128i in)
+{
+ return (__m128d)in;
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_pause(void)
+{
+ __asm__ volatile ("pause");
+}
+
+#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))
+
+#endif /* __SSE2__ */
+
+#endif /* __EMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/float.h b/contrib/llvm/tools/clang/lib/Headers/float.h
new file mode 100644
index 0000000..28fb882
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/float.h
@@ -0,0 +1,71 @@
+/*===---- float.h - Characteristics of floating point types ----------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __FLOAT_H
+#define __FLOAT_H
+
+/* Characteristics of floating point types, C99 5.2.4.2.2 */
+
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#define FLT_ROUNDS (__builtin_flt_rounds())
+#define FLT_RADIX __FLT_RADIX__
+
+#define FLT_MANT_DIG __FLT_MANT_DIG__
+#define DBL_MANT_DIG __DBL_MANT_DIG__
+#define LDBL_MANT_DIG __LDBL_MANT_DIG__
+
+#define DECIMAL_DIG __DECIMAL_DIG__
+
+#define FLT_DIG __FLT_DIG__
+#define DBL_DIG __DBL_DIG__
+#define LDBL_DIG __LDBL_DIG__
+
+#define FLT_MIN_EXP __FLT_MIN_EXP__
+#define DBL_MIN_EXP __DBL_MIN_EXP__
+#define LDBL_MIN_EXP __LDBL_MIN_EXP__
+
+#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
+#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
+#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
+
+#define FLT_MAX_EXP __FLT_MAX_EXP__
+#define DBL_MAX_EXP __DBL_MAX_EXP__
+#define LDBL_MAX_EXP __LDBL_MAX_EXP__
+
+#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
+#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
+#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
+
+#define FLT_MAX __FLT_MAX__
+#define DBL_MAX __DBL_MAX__
+#define LDBL_MAX __LDBL_MAX__
+
+#define FLT_EPSILON __FLT_EPSILON__
+#define DBL_EPSILON __DBL_EPSILON__
+#define LDBL_EPSILON __LDBL_EPSILON__
+
+#define FLT_MIN __FLT_MIN__
+#define DBL_MIN __DBL_MIN__
+#define LDBL_MIN __LDBL_MIN__
+
+#endif /* __FLOAT_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/immintrin.h b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
new file mode 100644
index 0000000..a19deaa
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
@@ -0,0 +1,59 @@
+/*===---- immintrin.h - Intel intrinsics -----------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#define __IMMINTRIN_H
+
+#ifdef __MMX__
+#include <mmintrin.h>
+#endif
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#ifdef __SSE3__
+#include <pmmintrin.h>
+#endif
+
+#ifdef __SSSE3__
+#include <tmmintrin.h>
+#endif
+
+#if defined (__SSE4_2__) || defined (__SSE4_1__)
+#include <smmintrin.h>
+#endif
+
+#if defined (__AES__) || defined (__PCLMUL__)
+#include <wmmintrin.h>
+#endif
+
+#ifdef __AVX__
+#include <avxintrin.h>
+#endif
+
+#endif /* __IMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/iso646.h b/contrib/llvm/tools/clang/lib/Headers/iso646.h
new file mode 100644
index 0000000..dca13c5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/iso646.h
@@ -0,0 +1,43 @@
+/*===---- iso646.h - Standard header for alternate spellings of operators---===
+ *
+ * Copyright (c) 2008 Eli Friedman
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __ISO646_H
+#define __ISO646_H
+
+#ifndef __cplusplus
+#define and &&
+#define and_eq &=
+#define bitand &
+#define bitor |
+#define compl ~
+#define not !
+#define not_eq !=
+#define or ||
+#define or_eq |=
+#define xor ^
+#define xor_eq ^=
+#endif
+
+#endif /* __ISO646_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/limits.h b/contrib/llvm/tools/clang/lib/Headers/limits.h
new file mode 100644
index 0000000..ecd09a4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/limits.h
@@ -0,0 +1,117 @@
+/*===---- limits.h - Standard header for integer sizes --------------------===*\
+ *
+ * Copyright (c) 2009 Chris Lattner
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __CLANG_LIMITS_H
+#define __CLANG_LIMITS_H
+
+/* The system's limits.h may, in turn, try to #include_next GCC's limits.h.
+ Avert this #include_next madness. */
+#if defined __GNUC__ && !defined _GCC_LIMITS_H_
+#define _GCC_LIMITS_H_
+#endif
+
+/* System headers include a number of constants from POSIX in <limits.h>.
+ Include it if we're hosted. */
+#if __STDC_HOSTED__ && \
+ defined(__has_include_next) && __has_include_next(<limits.h>)
+#include_next <limits.h>
+#endif
+
+/* Many system headers try to "help us out" by defining these. No really, we
+ know how big each datatype is. */
+#undef SCHAR_MIN
+#undef SCHAR_MAX
+#undef UCHAR_MAX
+#undef SHRT_MIN
+#undef SHRT_MAX
+#undef USHRT_MAX
+#undef INT_MIN
+#undef INT_MAX
+#undef UINT_MAX
+#undef LONG_MIN
+#undef LONG_MAX
+#undef ULONG_MAX
+
+#undef CHAR_BIT
+#undef CHAR_MIN
+#undef CHAR_MAX
+
+/* C90/99 5.2.4.2.1 */
+#define SCHAR_MAX __SCHAR_MAX__
+#define SHRT_MAX __SHRT_MAX__
+#define INT_MAX __INT_MAX__
+#define LONG_MAX __LONG_MAX__
+
+#define SCHAR_MIN (-__SCHAR_MAX__-1)
+#define SHRT_MIN (-__SHRT_MAX__ -1)
+#define INT_MIN (-__INT_MAX__ -1)
+#define LONG_MIN (-__LONG_MAX__ -1L)
+
+#define UCHAR_MAX (__SCHAR_MAX__*2 +1)
+#define USHRT_MAX (__SHRT_MAX__ *2 +1)
+#define UINT_MAX (__INT_MAX__ *2U +1U)
+#define ULONG_MAX (__LONG_MAX__ *2UL+1UL)
+
+#ifndef MB_LEN_MAX
+#define MB_LEN_MAX 1
+#endif
+
+#define CHAR_BIT __CHAR_BIT__
+
+#ifdef __CHAR_UNSIGNED__ /* -funsigned-char */
+#define CHAR_MIN 0
+#define CHAR_MAX UCHAR_MAX
+#else
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX __SCHAR_MAX__
+#endif
+
+/* C99 5.2.4.2.1: Added long long. */
+#if __STDC_VERSION__ >= 199901
+
+#undef LLONG_MIN
+#undef LLONG_MAX
+#undef ULLONG_MAX
+
+#define LLONG_MAX __LONG_LONG_MAX__
+#define LLONG_MIN (-__LONG_LONG_MAX__-1LL)
+#define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL)
+#endif
+
+/* LONG_LONG_MIN/LONG_LONG_MAX/ULONG_LONG_MAX are a GNU extension. It's too bad
+ that we don't have something like #pragma poison that could be used to
+ deprecate a macro - the code should just use LLONG_MAX and friends.
+ */
+#if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__)
+
+#undef LONG_LONG_MIN
+#undef LONG_LONG_MAX
+#undef ULONG_LONG_MAX
+
+#define LONG_LONG_MAX __LONG_LONG_MAX__
+#define LONG_LONG_MIN (-__LONG_LONG_MAX__-1LL)
+#define ULONG_LONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL)
+#endif
+
+#endif /* __CLANG_LIMITS_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h b/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h
new file mode 100644
index 0000000..e7da543
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/mm_malloc.h
@@ -0,0 +1,71 @@
+/*===---- mm_malloc.h - Allocating and Freeing Aligned Memory Blocks -------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __MM_MALLOC_H
+#define __MM_MALLOC_H
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#ifndef __cplusplus
+extern int posix_memalign(void **memptr, size_t alignment, size_t size);
+#else
+// Some systems (e.g. those with GNU libc) declare posix_memalign with an
+// exception specifier. Via an "egregious workaround" in
+// Sema::CheckEquivalentExceptionSpec, Clang accepts the following as a valid
+// redeclaration of glibc's declaration.
+extern "C" int posix_memalign(void **memptr, size_t alignment, size_t size);
+#endif
+#endif
+
+static __inline__ void *__attribute__((__always_inline__, __nodebug__,
+ __malloc__))
+_mm_malloc(size_t size, size_t align)
+{
+ if (align == 1) {
+ return malloc(size);
+ }
+
+ if (!(align & (align - 1)) && align < sizeof(void *))
+ align = sizeof(void *);
+
+ void *mallocedMemory;
+#ifdef _WIN32
+ mallocedMemory = _aligned_malloc(size, align);
+#else
+ if (posix_memalign(&mallocedMemory, align, size))
+ return 0;
+#endif
+
+ return mallocedMemory;
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_free(void *p)
+{
+ free(p);
+}
+
+#endif /* __MM_MALLOC_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
new file mode 100644
index 0000000..fefb42f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
@@ -0,0 +1,503 @@
+/*===---- mmintrin.h - MMX intrinsics --------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __MMINTRIN_H
+#define __MMINTRIN_H
+
+#ifndef __MMX__
+#error "MMX instruction set not enabled"
+#else
+
+typedef long long __m64 __attribute__((__vector_size__(8)));
+
+typedef int __v2si __attribute__((__vector_size__(8)));
+typedef short __v4hi __attribute__((__vector_size__(8)));
+typedef char __v8qi __attribute__((__vector_size__(8)));
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_empty(void)
+{
+ __builtin_ia32_emms();
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi32_si64(int __i)
+{
+ return (__m64)__builtin_ia32_vec_init_v2si(__i, 0);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi64_si32(__m64 __m)
+{
+ return __builtin_ia32_vec_ext_v2si((__v2si)__m, 0);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi64_m64(long long __i)
+{
+ return (__m64)__i;
+}
+
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvtm64_si64(__m64 __m)
+{
+ return (long long)__m;
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_packs_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_packsswb((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_packs_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_packssdw((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_packs_pu16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_packuswb((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpckhbw((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpckhwd((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpckhdq((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpcklbw((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpcklwd((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_punpckldq((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_add_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_add_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_add_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddd((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_adds_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_adds_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_adds_pu8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_adds_pu16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_paddusw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubd((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_subs_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubsb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_subs_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubsw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_subs_pu8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubusb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_subs_pu16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_psubusw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_madd_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pmaddwd((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_mulhi_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pmulhw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_mullo_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pmullw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sll_pi16(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psllw((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_slli_pi16(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psllwi((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sll_pi32(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_pslld((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_slli_pi32(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_pslldi((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sll_si64(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psllq(__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_slli_si64(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psllqi(__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sra_pi16(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psraw((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srai_pi16(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psrawi((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sra_pi32(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psrad((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srai_pi32(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psradi((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srl_pi16(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psrlw((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srli_pi16(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psrlwi((__v4hi)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srl_pi32(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psrld((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srli_pi32(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psrldi((__v2si)__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srl_si64(__m64 __m, __m64 __count)
+{
+ return (__m64)__builtin_ia32_psrlq(__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_srli_si64(__m64 __m, int __count)
+{
+ return (__m64)__builtin_ia32_psrlqi(__m, __count);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_and_si64(__m64 __m1, __m64 __m2)
+{
+ return __builtin_ia32_pand(__m1, __m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_andnot_si64(__m64 __m1, __m64 __m2)
+{
+ return __builtin_ia32_pandn(__m1, __m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_or_si64(__m64 __m1, __m64 __m2)
+{
+ return __builtin_ia32_por(__m1, __m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_xor_si64(__m64 __m1, __m64 __m2)
+{
+ return __builtin_ia32_pxor(__m1, __m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpeqb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpeqw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpeqd((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_pi8(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpgtb((__v8qi)__m1, (__v8qi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_pi16(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpgtw((__v4hi)__m1, (__v4hi)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_pi32(__m64 __m1, __m64 __m2)
+{
+ return (__m64)__builtin_ia32_pcmpgtd((__v2si)__m1, (__v2si)__m2);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_setzero_si64(void)
+{
+ return (__m64){ 0LL };
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set_pi32(int __i1, int __i0)
+{
+ return (__m64)__builtin_ia32_vec_init_v2si(__i0, __i1);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set_pi16(short __s3, short __s2, short __s1, short __s0)
+{
+ return (__m64)__builtin_ia32_vec_init_v4hi(__s0, __s1, __s2, __s3);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
+ char __b1, char __b0)
+{
+ return (__m64)__builtin_ia32_vec_init_v8qi(__b0, __b1, __b2, __b3,
+ __b4, __b5, __b6, __b7);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set1_pi32(int __i)
+{
+ return _mm_set_pi32(__i, __i);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set1_pi16(short __w)
+{
+ return _mm_set_pi16(__w, __w, __w, __w);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_set1_pi8(char __b)
+{
+ return _mm_set_pi8(__b, __b, __b, __b, __b, __b, __b, __b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_setr_pi32(int __i1, int __i0)
+{
+ return _mm_set_pi32(__i1, __i0);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_setr_pi16(short __w3, short __w2, short __w1, short __w0)
+{
+ return _mm_set_pi16(__w3, __w2, __w1, __w0);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_setr_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
+ char __b1, char __b0)
+{
+ return _mm_set_pi8(__b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0);
+}
+
+
+/* Aliases for compatibility. */
+#define _m_empty _mm_empty
+#define _m_from_int _mm_cvtsi32_si64
+#define _m_to_int _mm_cvtsi64_si32
+#define _m_packsswb _mm_packs_pi16
+#define _m_packssdw _mm_packs_pi32
+#define _m_packuswb _mm_packs_pu16
+#define _m_punpckhbw _mm_unpackhi_pi8
+#define _m_punpckhwd _mm_unpackhi_pi16
+#define _m_punpckhdq _mm_unpackhi_pi32
+#define _m_punpcklbw _mm_unpacklo_pi8
+#define _m_punpcklwd _mm_unpacklo_pi16
+#define _m_punpckldq _mm_unpacklo_pi32
+#define _m_paddb _mm_add_pi8
+#define _m_paddw _mm_add_pi16
+#define _m_paddd _mm_add_pi32
+#define _m_paddsb _mm_adds_pi8
+#define _m_paddsw _mm_adds_pi16
+#define _m_paddusb _mm_adds_pu8
+#define _m_paddusw _mm_adds_pu16
+#define _m_psubb _mm_sub_pi8
+#define _m_psubw _mm_sub_pi16
+#define _m_psubd _mm_sub_pi32
+#define _m_psubsb _mm_subs_pi8
+#define _m_psubsw _mm_subs_pi16
+#define _m_psubusb _mm_subs_pu8
+#define _m_psubusw _mm_subs_pu16
+#define _m_pmaddwd _mm_madd_pi16
+#define _m_pmulhw _mm_mulhi_pi16
+#define _m_pmullw _mm_mullo_pi16
+#define _m_psllw _mm_sll_pi16
+#define _m_psllwi _mm_slli_pi16
+#define _m_pslld _mm_sll_pi32
+#define _m_pslldi _mm_slli_pi32
+#define _m_psllq _mm_sll_si64
+#define _m_psllqi _mm_slli_si64
+#define _m_psraw _mm_sra_pi16
+#define _m_psrawi _mm_srai_pi16
+#define _m_psrad _mm_sra_pi32
+#define _m_psradi _mm_srai_pi32
+#define _m_psrlw _mm_srl_pi16
+#define _m_psrlwi _mm_srli_pi16
+#define _m_psrld _mm_srl_pi32
+#define _m_psrldi _mm_srli_pi32
+#define _m_psrlq _mm_srl_si64
+#define _m_psrlqi _mm_srli_si64
+#define _m_pand _mm_and_si64
+#define _m_pandn _mm_andnot_si64
+#define _m_por _mm_or_si64
+#define _m_pxor _mm_xor_si64
+#define _m_pcmpeqb _mm_cmpeq_pi8
+#define _m_pcmpeqw _mm_cmpeq_pi16
+#define _m_pcmpeqd _mm_cmpeq_pi32
+#define _m_pcmpgtb _mm_cmpgt_pi8
+#define _m_pcmpgtw _mm_cmpgt_pi16
+#define _m_pcmpgtd _mm_cmpgt_pi32
+
+#endif /* __MMX__ */
+
+#endif /* __MMINTRIN_H */
+
diff --git a/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
new file mode 100644
index 0000000..f12622d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
@@ -0,0 +1,35 @@
+/*===---- nmmintrin.h - SSE4 intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef _NMMINTRIN_H
+#define _NMMINTRIN_H
+
+#ifndef __SSE4_2__
+#error "SSE4.2 instruction set not enabled"
+#else
+
+/* To match expectations of gcc we put the sse4.2 definitions into smmintrin.h,
+ just include it now then. */
+#include <smmintrin.h>
+#endif /* __SSE4_2__ */
+#endif /* _NMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
new file mode 100644
index 0000000..7ca386c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
@@ -0,0 +1,121 @@
+/*===---- pmmintrin.h - SSE3 intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __PMMINTRIN_H
+#define __PMMINTRIN_H
+
+#ifndef __SSE3__
+#error "SSE3 instruction set not enabled"
+#else
+
+#include <emmintrin.h>
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_lddqu_si128(__m128i const *p)
+{
+ return (__m128i)__builtin_ia32_lddqu((char const *)p);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_addsub_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_addsubps(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_haddps(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_hsubps(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_movehdup_ps(__m128 a)
+{
+ return __builtin_shufflevector(a, a, 1, 1, 3, 3);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_moveldup_ps(__m128 a)
+{
+ return __builtin_shufflevector(a, a, 0, 0, 2, 2);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_addsub_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_addsubpd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_haddpd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_hsubpd(a, b);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_loaddup_pd(double const *dp)
+{
+ return (__m128d){ *dp, *dp };
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_movedup_pd(__m128d a)
+{
+ return __builtin_shufflevector(a, a, 0, 0);
+}
+
+#define _MM_DENORMALS_ZERO_ON (0x0040)
+#define _MM_DENORMALS_ZERO_OFF (0x0000)
+
+#define _MM_DENORMALS_ZERO_MASK (0x0040)
+
+#define _MM_GET_DENORMALS_ZERO_MODE() (_mm_getcsr() & _MM_DENORMALS_ZERO_MASK)
+#define _MM_SET_DENORMALS_ZERO_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_DENORMALS_ZERO_MASK) | (x)))
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_monitor(void const *p, unsigned extensions, unsigned hints)
+{
+ __builtin_ia32_monitor((void *)p, extensions, hints);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_mwait(unsigned extensions, unsigned hints)
+{
+ __builtin_ia32_mwait(extensions, hints);
+}
+
+#endif /* __SSE3__ */
+
+#endif /* __PMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
new file mode 100644
index 0000000..2b8b321
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
@@ -0,0 +1,452 @@
+/*===---- smmintrin.h - SSE4 intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef _SMMINTRIN_H
+#define _SMMINTRIN_H
+
+#ifndef __SSE4_1__
+#error "SSE4.1 instruction set not enabled"
+#else
+
+#include <tmmintrin.h>
+
+/* SSE4 Rounding macros. */
+#define _MM_FROUND_TO_NEAREST_INT 0x00
+#define _MM_FROUND_TO_NEG_INF 0x01
+#define _MM_FROUND_TO_POS_INF 0x02
+#define _MM_FROUND_TO_ZERO 0x03
+#define _MM_FROUND_CUR_DIRECTION 0x04
+
+#define _MM_FROUND_RAISE_EXC 0x00
+#define _MM_FROUND_NO_EXC 0x08
+
+#define _MM_FROUND_NINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEAREST_INT)
+#define _MM_FROUND_FLOOR (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEG_INF)
+#define _MM_FROUND_CEIL (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF)
+#define _MM_FROUND_TRUNC (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO)
+#define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION)
+#define _MM_FROUND_NEARBYINT (_MM_FROUND_NO_EXC | _MM_FROUND_CUR_DIRECTION)
+
+#define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL)
+#define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL)
+#define _mm_ceil_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_CEIL)
+#define _mm_ceil_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_CEIL)
+
+#define _mm_floor_ps(X) _mm_round_ps((X), _MM_FROUND_FLOOR)
+#define _mm_floor_pd(X) _mm_round_pd((X), _MM_FROUND_FLOOR)
+#define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR)
+#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR)
+
+#define _mm_round_ps(X, Y) __builtin_ia32_roundps((X), (Y))
+#define _mm_round_ss(X, Y, M) __builtin_ia32_roundss((X), (Y), (M))
+#define _mm_round_pd(X, M) __builtin_ia32_roundpd((X), (M))
+#define _mm_round_sd(X, Y, M) __builtin_ia32_roundsd((X), (Y), (M))
+
+/* SSE4 Packed Blending Intrinsics. */
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_blend_pd (__m128d __V1, __m128d __V2, const int __M)
+{
+ return (__m128d) __builtin_ia32_blendpd ((__v2df)__V1, (__v2df)__V2, __M);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_blend_ps (__m128 __V1, __m128 __V2, const int __M)
+{
+ return (__m128) __builtin_ia32_blendps ((__v4sf)__V1, (__v4sf)__V2, __M);
+}
+
+static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
+{
+ return (__m128d) __builtin_ia32_blendvpd ((__v2df)__V1, (__v2df)__V2,
+ (__v2df)__M);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
+{
+ return (__m128) __builtin_ia32_blendvps ((__v4sf)__V1, (__v4sf)__V2,
+ (__v4sf)__M);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
+{
+ return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__V1, (__v16qi)__V2,
+ (__v16qi)__M);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_blend_epi16 (__m128i __V1, __m128i __V2, const int __M)
+{
+ return (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__V1, (__v8hi)__V2, __M);
+}
+
+/* SSE4 Dword Multiply Instructions. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mullo_epi32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) ((__v4si)__V1 * (__v4si)__V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mul_epi32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pmuldq128 ((__v4si)__V1, (__v4si)__V2);
+}
+
+/* SSE4 Floating Point Dot Product Instructions. */
+#define _mm_dp_ps(X, Y, M) __builtin_ia32_dpps ((X), (Y), (M))
+#define _mm_dp_pd(X, Y, M) __builtin_ia32_dppd ((X), (Y), (M))
+
+/* SSE4 Streaming Load Hint Instruction. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_stream_load_si128 (__m128i *__V)
+{
+ return (__m128i) __builtin_ia32_movntdqa ((__v2di *) __V);
+}
+
+/* SSE4 Packed Integer Min/Max Instructions. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epi8 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pminsb128 ((__v16qi) __V1, (__v16qi) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epi8 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi) __V1, (__v16qi) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epu16 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pminuw128 ((__v8hi) __V1, (__v8hi) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epu16 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi) __V1, (__v8hi) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epi32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pminsd128 ((__v4si) __V1, (__v4si) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epi32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si) __V1, (__v4si) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_min_epu32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pminud128((__v4si) __V1, (__v4si) __V2);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_max_epu32 (__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pmaxud128((__v4si) __V1, (__v4si) __V2);
+}
+
+/* SSE4 Insertion and Extraction from XMM Register Instructions. */
+#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
+#define _mm_extract_ps(X, N) (__extension__ \
+ ({ union { int i; float f; } __t; \
+ __v4sf __a = (__v4sf)(X); \
+ __t.f = __a[N]; \
+ __t.i;}))
+
+/* Miscellaneous insert and extract macros. */
+/* Extract a single-precision float from X at index N into D. */
+#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)(X); \
+ (D) = __a[N]; }))
+
+/* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create
+ an index suitable for _mm_insert_ps. */
+#define _MM_MK_INSERTPS_NDX(X, Y, Z) (((X) << 6) | ((Y) << 4) | (Z))
+
+/* Extract a float from X at index N into the first index of the return. */
+#define _MM_PICK_OUT_PS(X, N) _mm_insert_ps (_mm_setzero_ps(), (X), \
+ _MM_MK_INSERTPS_NDX((N), 0, 0x0e))
+
+/* Insert int into packed integer array at index. */
+#define _mm_insert_epi8(X, I, N) (__extension__ ({ __v16qi __a = (__v16qi)(X); \
+ __a[N] = I; \
+ __a;}))
+#define _mm_insert_epi32(X, I, N) (__extension__ ({ __v4si __a = (__v4si)(X); \
+ __a[N] = I; \
+ __a;}))
+#ifdef __x86_64__
+#define _mm_insert_epi64(X, I, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
+ __a[N] = I; \
+ __a;}))
+#endif /* __x86_64__ */
+
+/* Extract int from packed integer array at index. This returns the element
+ * as a zero extended value, so it is unsigned.
+ */
+#define _mm_extract_epi8(X, N) (__extension__ ({ __v16qi __a = (__v16qi)(X); \
+ (unsigned char)__a[N];}))
+#define _mm_extract_epi32(X, N) (__extension__ ({ __v4si __a = (__v4si)(X); \
+ (unsigned)__a[N];}))
+#ifdef __x86_64__
+#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
+ __a[N];}))
+#endif /* __x86_64 */
+
+/* SSE4 128-bit Packed Integer Comparisons. */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_testz_si128(__m128i __M, __m128i __V)
+{
+ return __builtin_ia32_ptestz128((__v2di)__M, (__v2di)__V);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_testc_si128(__m128i __M, __m128i __V)
+{
+ return __builtin_ia32_ptestc128((__v2di)__M, (__v2di)__V);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_testnzc_si128(__m128i __M, __m128i __V)
+{
+ return __builtin_ia32_ptestnzc128((__v2di)__M, (__v2di)__V);
+}
+
+#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_cmpeq_epi32((V), (V)))
+#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128((M), (V))
+#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((V), (V))
+
+/* SSE4 64-bit Packed Integer Comparisons. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_pcmpeqq((__v2di)__V1, (__v2di)__V2);
+}
+
+/* SSE4 Packed Integer Sign-Extension. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi8_epi16(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxbw128((__v16qi) __V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi8_epi32(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxbd128((__v16qi) __V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi8_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxbq128((__v16qi) __V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi16_epi32(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxwd128((__v8hi) __V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi16_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxwq128((__v8hi)__V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepi32_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovsxdq128((__v4si)__V);
+}
+
+/* SSE4 Packed Integer Zero-Extension. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu8_epi16(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxbw128((__v16qi) __V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu8_epi32(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxbd128((__v16qi)__V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu8_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxbq128((__v16qi)__V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu16_epi32(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxwd128((__v8hi)__V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu16_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxwq128((__v8hi)__V);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cvtepu32_epi64(__m128i __V)
+{
+ return (__m128i) __builtin_ia32_pmovzxdq128((__v4si)__V);
+}
+
+/* SSE4 Pack with Unsigned Saturation. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_packus_epi32(__m128i __V1, __m128i __V2)
+{
+ return (__m128i) __builtin_ia32_packusdw128((__v4si)__V1, (__v4si)__V2);
+}
+
+/* SSE4 Multiple Packed Sums of Absolute Difference. */
+#define _mm_mpsadbw_epu8(X, Y, M) __builtin_ia32_mpsadbw128((X), (Y), (M))
+
+/* These definitions are normally in nmmintrin.h, but gcc puts them in here
+ so we'll do the same. */
+#ifdef __SSE4_2__
+
+/* These specify the type of data that we're comparing. */
+#define _SIDD_UBYTE_OPS 0x00
+#define _SIDD_UWORD_OPS 0x01
+#define _SIDD_SBYTE_OPS 0x02
+#define _SIDD_SWORD_OPS 0x03
+
+/* These specify the type of comparison operation. */
+#define _SIDD_CMP_EQUAL_ANY 0x00
+#define _SIDD_CMP_RANGES 0x04
+#define _SIDD_CMP_EQUAL_EACH 0x08
+#define _SIDD_CMP_EQUAL_ORDERED 0x0c
+
+/* These macros specify the polarity of the operation. */
+#define _SIDD_POSITIVE_POLARITY 0x00
+#define _SIDD_NEGATIVE_POLARITY 0x10
+#define _SIDD_MASKED_POSITIVE_POLARITY 0x20
+#define _SIDD_MASKED_NEGATIVE_POLARITY 0x30
+
+/* These macros are used in _mm_cmpXstri() to specify the return. */
+#define _SIDD_LEAST_SIGNIFICANT 0x00
+#define _SIDD_MOST_SIGNIFICANT 0x40
+
+/* These macros are used in _mm_cmpXstri() to specify the return. */
+#define _SIDD_BIT_MASK 0x00
+#define _SIDD_UNIT_MASK 0x40
+
+/* SSE4.2 Packed Comparison Intrinsics. */
+#define _mm_cmpistrm(A, B, M) __builtin_ia32_pcmpistrm128((A), (B), (M))
+#define _mm_cmpistri(A, B, M) __builtin_ia32_pcmpistri128((A), (B), (M))
+
+#define _mm_cmpestrm(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestrm128((A), (LA), (B), (LB), (M))
+#define _mm_cmpestri(X, LX, Y, LY, M) \
+ __builtin_ia32_pcmpestri128((A), (LA), (B), (LB), (M))
+
+/* SSE4.2 Packed Comparison Intrinsics and EFlag Reading. */
+#define _mm_cmpistra(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpistria128((A), (LA), (B), (LB), (M))
+#define _mm_cmpistrc(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpistric128((A), (LA), (B), (LB), (M))
+#define _mm_cmpistro(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpistrio128((A), (LA), (B), (LB), (M))
+#define _mm_cmpistrs(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpistris128((A), (LA), (B), (LB), (M))
+#define _mm_cmpistrz(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpistriz128((A), (LA), (B), (LB), (M))
+
+#define _mm_cmpestra(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestria128((A), (LA), (B), (LB), (M))
+#define _mm_cmpestrc(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestric128((A), (LA), (B), (LB), (M))
+#define _mm_cmpestro(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestrio128((A), (LA), (B), (LB), (M))
+#define _mm_cmpestrs(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestris128((A), (LA), (B), (LB), (M))
+#define _mm_cmpestrz(A, LA, B, LB, M) \
+ __builtin_ia32_pcmpestriz128((A), (LA), (B), (LB), (M))
+
+/* SSE4.2 Compare Packed Data -- Greater Than. */
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
+{
+ return __builtin_ia32_pcmpgtq((__v2di)__V1, (__v2di)__V2);
+}
+
+/* SSE4.2 Accumulate CRC32. */
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+_mm_crc32_u8(unsigned int __C, unsigned char __D)
+{
+ return __builtin_ia32_crc32qi(__C, __D);
+}
+
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+_mm_crc32_u16(unsigned int __C, unsigned short __D)
+{
+ return __builtin_ia32_crc32hi(__C, __D);
+}
+
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+_mm_crc32_u32(unsigned int __C, unsigned int __D)
+{
+ return __builtin_ia32_crc32si(__C, __D);
+}
+
+#ifdef __x86_64__
+static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+_mm_crc32_u64(unsigned long long __C, unsigned long long __D)
+{
+ return __builtin_ia32_crc32di(__C, __D);
+}
+#endif /* __x86_64__ */
+
+/* SSE4.2 Population Count. */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_popcnt_u32(unsigned int __A)
+{
+ return __builtin_popcount(__A);
+}
+
+#ifdef __x86_64__
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_popcnt_u64(unsigned long long __A)
+{
+ return __builtin_popcountll(__A);
+}
+#endif /* __x86_64__ */
+
+#endif /* __SSE4_2__ */
+#endif /* __SSE4_1__ */
+
+#endif /* _SMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdarg.h b/contrib/llvm/tools/clang/lib/Headers/stdarg.h
new file mode 100644
index 0000000..c36ab12
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/stdarg.h
@@ -0,0 +1,50 @@
+/*===---- stdarg.h - Variable argument handling ----------------------------===
+ *
+ * Copyright (c) 2008 Eli Friedman
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __STDARG_H
+#define __STDARG_H
+
+#ifndef _VA_LIST
+typedef __builtin_va_list va_list;
+#define _VA_LIST
+#endif
+#define va_start(ap, param) __builtin_va_start(ap, param)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_arg(ap, type) __builtin_va_arg(ap, type)
+
+/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
+ * or -ansi is not specified, since it was not part of C90.
+ */
+#define __va_copy(d,s) __builtin_va_copy(d,s)
+
+#if __STDC_VERSION__ >= 199900L || !defined(__STRICT_ANSI__)
+#define va_copy(dest, src) __builtin_va_copy(dest, src)
+#endif
+
+/* Hack required to make standard headers work, at least on Ubuntu */
+#define __GNUC_VA_LIST 1
+typedef __builtin_va_list __gnuc_va_list;
+
+#endif /* __STDARG_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdbool.h b/contrib/llvm/tools/clang/lib/Headers/stdbool.h
new file mode 100644
index 0000000..0467893
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/stdbool.h
@@ -0,0 +1,44 @@
+/*===---- stdbool.h - Standard header for booleans -------------------------===
+ *
+ * Copyright (c) 2008 Eli Friedman
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __STDBOOL_H
+#define __STDBOOL_H
+
+/* Don't define bool, true, and false in C++, except as a GNU extension. */
+#ifndef __cplusplus
+#define bool _Bool
+#define true 1
+#define false 0
+#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Define _Bool, bool, false, true as a GNU extension. */
+#define _Bool bool
+#define bool bool
+#define false false
+#define true true
+#endif
+
+#define __bool_true_false_are_defined 1
+
+#endif /* __STDBOOL_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stddef.h b/contrib/llvm/tools/clang/lib/Headers/stddef.h
new file mode 100644
index 0000000..7cc0bc1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/stddef.h
@@ -0,0 +1,61 @@
+/*===---- stddef.h - Basic type definitions --------------------------------===
+ *
+ * Copyright (c) 2008 Eli Friedman
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __STDDEF_H
+#define __STDDEF_H
+
+typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t;
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __typeof__(sizeof(int)) size_t;
+#endif
+#ifndef __cplusplus
+#ifndef _WCHAR_T
+#define _WCHAR_T
+typedef __WCHAR_TYPE__ wchar_t;
+#endif
+#endif
+
+#undef NULL
+#ifdef __cplusplus
+#undef __null // VC++ hack.
+#define NULL __null
+#else
+#define NULL ((void*)0)
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
+
+#endif /* __STDDEF_H */
+
+/* Some C libraries expect to see a wint_t here. Others (notably MinGW) will use
+__WINT_TYPE__ directly; accomodate both by requiring __need_wint_t */
+#if defined(__need_wint_t)
+#if !defined(_WINT_T)
+#define _WINT_T
+typedef __WINT_TYPE__ wint_t;
+#endif /* _WINT_T */
+#undef __need_wint_t
+#endif /* __need_wint_t */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdint.h b/contrib/llvm/tools/clang/lib/Headers/stdint.h
new file mode 100644
index 0000000..9498ed5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/stdint.h
@@ -0,0 +1,654 @@
+/*===---- stdint.h - Standard header for sized integer types --------------===*\
+ *
+ * Copyright (c) 2009 Chris Lattner
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __CLANG_STDINT_H
+#define __CLANG_STDINT_H
+
+/* If we're hosted, fall back to the system's stdint.h, which might have
+ * additional definitions.
+ */
+#if __STDC_HOSTED__ && \
+ defined(__has_include_next) && __has_include_next(<stdint.h>)
+# include_next <stdint.h>
+#else
+
+/* C99 7.18.1.1 Exact-width integer types.
+ * C99 7.18.1.2 Minimum-width integer types.
+ * C99 7.18.1.3 Fastest minimum-width integer types.
+ *
+ * The standard requires that exact-width type be defined for 8-, 16-, 32-, and
+ * 64-bit types if they are implemented. Other exact width types are optional.
+ * This implementation defines an exact-width types for every integer width
+ * that is represented in the standard integer types.
+ *
+ * The standard also requires minimum-width types be defined for 8-, 16-, 32-,
+ * and 64-bit widths regardless of whether there are corresponding exact-width
+ * types.
+ *
+ * To accomodate targets that are missing types that are exactly 8, 16, 32, or
+ * 64 bits wide, this implementation takes an approach of cascading
+ * redefintions, redefining __int_leastN_t to successively smaller exact-width
+ * types. It is therefore important that the types are defined in order of
+ * descending widths.
+ *
+ * We currently assume that the minimum-width types and the fastest
+ * minimum-width types are the same. This is allowed by the standard, but is
+ * suboptimal.
+ *
+ * In violation of the standard, some targets do not implement a type that is
+ * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit).
+ * To accomodate these targets, a required minimum-width type is only
+ * defined if there exists an exact-width type of equal or greater width.
+ */
+
+#ifdef __INT64_TYPE__
+# ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/
+typedef signed __INT64_TYPE__ int64_t;
+# endif /* __int8_t_defined */
+typedef unsigned __INT64_TYPE__ uint64_t;
+# define __int_least64_t int64_t
+# define __uint_least64_t uint64_t
+# define __int_least32_t int64_t
+# define __uint_least32_t uint64_t
+# define __int_least16_t int64_t
+# define __uint_least16_t uint64_t
+# define __int_least8_t int64_t
+# define __uint_least8_t uint64_t
+#endif /* __INT64_TYPE__ */
+
+#ifdef __int_least64_t
+typedef __int_least64_t int_least64_t;
+typedef __uint_least64_t uint_least64_t;
+typedef __int_least64_t int_fast64_t;
+typedef __uint_least64_t uint_fast64_t;
+#endif /* __int_least64_t */
+
+#ifdef __INT56_TYPE__
+typedef signed __INT56_TYPE__ int56_t;
+typedef unsigned __INT56_TYPE__ uint56_t;
+typedef int56_t int_least56_t;
+typedef uint56_t uint_least56_t;
+typedef int56_t int_fast56_t;
+typedef uint56_t uint_fast56_t;
+# define __int_least32_t int56_t
+# define __uint_least32_t uint56_t
+# define __int_least16_t int56_t
+# define __uint_least16_t uint56_t
+# define __int_least8_t int56_t
+# define __uint_least8_t uint56_t
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+typedef signed __INT48_TYPE__ int48_t;
+typedef unsigned __INT48_TYPE__ uint48_t;
+typedef int48_t int_least48_t;
+typedef uint48_t uint_least48_t;
+typedef int48_t int_fast48_t;
+typedef uint48_t uint_fast48_t;
+# define __int_least32_t int48_t
+# define __uint_least32_t uint48_t
+# define __int_least16_t int48_t
+# define __uint_least16_t uint48_t
+# define __int_least8_t int48_t
+# define __uint_least8_t uint48_t
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+typedef signed __INT40_TYPE__ int40_t;
+typedef unsigned __INT40_TYPE__ uint40_t;
+typedef int40_t int_least40_t;
+typedef uint40_t uint_least40_t;
+typedef int40_t int_fast40_t;
+typedef uint40_t uint_fast40_t;
+# define __int_least32_t int40_t
+# define __uint_least32_t uint40_t
+# define __int_least16_t int40_t
+# define __uint_least16_t uint40_t
+# define __int_least8_t int40_t
+# define __uint_least8_t uint40_t
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+
+# ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/
+typedef signed __INT32_TYPE__ int32_t;
+# endif /* __int8_t_defined */
+
+# ifndef __uint32_t_defined /* more glibc compatibility */
+# define __uint32_t_defined
+typedef unsigned __INT32_TYPE__ uint32_t;
+# endif /* __uint32_t_defined */
+
+# define __int_least32_t int32_t
+# define __uint_least32_t uint32_t
+# define __int_least16_t int32_t
+# define __uint_least16_t uint32_t
+# define __int_least8_t int32_t
+# define __uint_least8_t uint32_t
+#endif /* __INT32_TYPE__ */
+
+#ifdef __int_least32_t
+typedef __int_least32_t int_least32_t;
+typedef __uint_least32_t uint_least32_t;
+typedef __int_least32_t int_fast32_t;
+typedef __uint_least32_t uint_fast32_t;
+#endif /* __int_least32_t */
+
+#ifdef __INT24_TYPE__
+typedef signed __INT24_TYPE__ int24_t;
+typedef unsigned __INT24_TYPE__ uint24_t;
+typedef int24_t int_least24_t;
+typedef uint24_t uint_least24_t;
+typedef int24_t int_fast24_t;
+typedef uint24_t uint_fast24_t;
+# define __int_least16_t int24_t
+# define __uint_least16_t uint24_t
+# define __int_least8_t int24_t
+# define __uint_least8_t uint24_t
+#endif /* __INT24_TYPE__ */
+
+#ifdef __INT16_TYPE__
+#ifndef __int8_t_defined /* glibc sys/types.h also defines int16_t*/
+typedef signed __INT16_TYPE__ int16_t;
+#endif /* __int8_t_defined */
+typedef unsigned __INT16_TYPE__ uint16_t;
+# define __int_least16_t int16_t
+# define __uint_least16_t uint16_t
+# define __int_least8_t int16_t
+# define __uint_least8_t uint16_t
+#endif /* __INT16_TYPE__ */
+
+#ifdef __int_least16_t
+typedef __int_least16_t int_least16_t;
+typedef __uint_least16_t uint_least16_t;
+typedef __int_least16_t int_fast16_t;
+typedef __uint_least16_t uint_fast16_t;
+#endif /* __int_least16_t */
+
+
+#ifdef __INT8_TYPE__
+#ifndef __int8_t_defined /* glibc sys/types.h also defines int8_t*/
+typedef signed __INT8_TYPE__ int8_t;
+#endif /* __int8_t_defined */
+typedef unsigned __INT8_TYPE__ uint8_t;
+# define __int_least8_t int8_t
+# define __uint_least8_t uint8_t
+#endif /* __INT8_TYPE__ */
+
+#ifdef __int_least8_t
+typedef __int_least8_t int_least8_t;
+typedef __uint_least8_t uint_least8_t;
+typedef __int_least8_t int_fast8_t;
+typedef __uint_least8_t uint_fast8_t;
+#endif /* __int_least8_t */
+
+/* prevent glibc sys/types.h from defining conflicting types */
+#ifndef __int8_t_defined
+# define __int8_t_defined
+#endif /* __int8_t_defined */
+
+/* C99 7.18.1.4 Integer types capable of holding object pointers.
+ */
+#define __stdint_join3(a,b,c) a ## b ## c
+
+#define __intn_t(n) __stdint_join3( int, n, _t)
+#define __uintn_t(n) __stdint_join3(uint, n, _t)
+
+#ifndef _INTPTR_T
+#ifndef __intptr_t_defined
+typedef __intn_t(__INTPTR_WIDTH__) intptr_t;
+#define __intptr_t_defined
+#define _INTPTR_T
+#endif
+#endif
+
+#ifndef _UINTPTR_T
+typedef __uintn_t(__INTPTR_WIDTH__) uintptr_t;
+#define _UINTPTR_T
+#endif
+
+/* C99 7.18.1.5 Greatest-width integer types.
+ */
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+
+/* C99 7.18.4 Macros for minimum-width integer constants.
+ *
+ * The standard requires that integer constant macros be defined for all the
+ * minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width
+ * types are required, the corresponding integer constant macros are defined
+ * here. This implementation also defines minimum-width types for every other
+ * integer width that the target implements, so corresponding macros are
+ * defined below, too.
+ *
+ * These macros are defined using the same successive-shrinking approach as
+ * the type definitions above. It is likewise important that macros are defined
+ * in order of decending width.
+ *
+ * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the
+ * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
+ */
+
+#define __int_c_join(a, b) a ## b
+#define __int_c(v, suffix) __int_c_join(v, suffix)
+#define __uint_c(v, suffix) __int_c_join(v##U, suffix)
+
+
+#ifdef __INT64_TYPE__
+# ifdef __INT64_C_SUFFIX__
+# define __int64_c_suffix __INT64_C_SUFFIX__
+# define __int32_c_suffix __INT64_C_SUFFIX__
+# define __int16_c_suffix __INT64_C_SUFFIX__
+# define __int8_c_suffix __INT64_C_SUFFIX__
+# else
+# undef __int64_c_suffix
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT64_C_SUFFIX__ */
+#endif /* __INT64_TYPE__ */
+
+#ifdef __int_least64_t
+# ifdef __int64_c_suffix
+# define INT64_C(v) __int_c(v, __int64_c_suffix)
+# define UINT64_C(v) __uint_c(v, __int64_c_suffix)
+# else
+# define INT64_C(v) v
+# define UINT64_C(v) v ## U
+# endif /* __int64_c_suffix */
+#endif /* __int_least64_t */
+
+
+#ifdef __INT56_TYPE__
+# ifdef __INT56_C_SUFFIX__
+# define INT56_C(v) __int_c(v, __INT56_C_SUFFIX__)
+# define UINT56_C(v) __uint_c(v, __INT56_C_SUFFIX__)
+# define __int32_c_suffix __INT56_C_SUFFIX__
+# define __int16_c_suffix __INT56_C_SUFFIX__
+# define __int8_c_suffix __INT56_C_SUFFIX__
+# else
+# define INT56_C(v) v
+# define UINT56_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT56_C_SUFFIX__ */
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+# ifdef __INT48_C_SUFFIX__
+# define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__)
+# define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__)
+# define __int32_c_suffix __INT48_C_SUFFIX__
+# define __int16_c_suffix __INT48_C_SUFFIX__
+# define __int8_c_suffix __INT48_C_SUFFIX__
+# else
+# define INT48_C(v) v
+# define UINT48_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT48_C_SUFFIX__ */
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+# ifdef __INT40_C_SUFFIX__
+# define INT40_C(v) __int_c(v, __INT40_C_SUFFIX__)
+# define UINT40_C(v) __uint_c(v, __INT40_C_SUFFIX__)
+# define __int32_c_suffix __INT40_C_SUFFIX__
+# define __int16_c_suffix __INT40_C_SUFFIX__
+# define __int8_c_suffix __INT40_C_SUFFIX__
+# else
+# define INT40_C(v) v
+# define UINT40_C(v) v ## U
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT40_C_SUFFIX__ */
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+# ifdef __INT32_C_SUFFIX__
+# define __int32_c_suffix __INT32_C_SUFFIX__
+# define __int16_c_suffix __INT32_C_SUFFIX__
+# define __int8_c_suffix __INT32_C_SUFFIX__
+#else
+# undef __int32_c_suffix
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT32_C_SUFFIX__ */
+#endif /* __INT32_TYPE__ */
+
+#ifdef __int_least32_t
+# ifdef __int32_c_suffix
+# define INT32_C(v) __int_c(v, __int32_c_suffix)
+# define UINT32_C(v) __uint_c(v, __int32_c_suffix)
+# else
+# define INT32_C(v) v
+# define UINT32_C(v) v ## U
+# endif /* __int32_c_suffix */
+#endif /* __int_least32_t */
+
+
+#ifdef __INT24_TYPE__
+# ifdef __INT24_C_SUFFIX__
+# define INT24_C(v) __int_c(v, __INT24_C_SUFFIX__)
+# define UINT24_C(v) __uint_c(v, __INT24_C_SUFFIX__)
+# define __int16_c_suffix __INT24_C_SUFFIX__
+# define __int8_c_suffix __INT24_C_SUFFIX__
+# else
+# define INT24_C(v) v
+# define UINT24_C(v) v ## U
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT24_C_SUFFIX__ */
+#endif /* __INT24_TYPE__ */
+
+
+#ifdef __INT16_TYPE__
+# ifdef __INT16_C_SUFFIX__
+# define __int16_c_suffix __INT16_C_SUFFIX__
+# define __int8_c_suffix __INT16_C_SUFFIX__
+#else
+# undef __int16_c_suffix
+# undef __int8_c_suffix
+# endif /* __INT16_C_SUFFIX__ */
+#endif /* __INT16_TYPE__ */
+
+#ifdef __int_least16_t
+# ifdef __int16_c_suffix
+# define INT16_C(v) __int_c(v, __int16_c_suffix)
+# define UINT16_C(v) __uint_c(v, __int16_c_suffix)
+# else
+# define INT16_C(v) v
+# define UINT16_C(v) v ## U
+# endif /* __int16_c_suffix */
+#endif /* __int_least16_t */
+
+
+#ifdef __INT8_TYPE__
+# ifdef __INT8_C_SUFFIX__
+# define __int8_c_suffix __INT8_C_SUFFIX__
+#else
+# undef __int8_c_suffix
+# endif /* __INT8_C_SUFFIX__ */
+#endif /* __INT8_TYPE__ */
+
+#ifdef __int_least8_t
+# ifdef __int8_c_suffix
+# define INT8_C(v) __int_c(v, __int8_c_suffix)
+# define UINT8_C(v) __uint_c(v, __int8_c_suffix)
+# else
+# define INT8_C(v) v
+# define UINT8_C(v) v ## U
+# endif /* __int8_c_suffix */
+#endif /* __int_least8_t */
+
+
+/* C99 7.18.2.1 Limits of exact-width integer types.
+ * C99 7.18.2.2 Limits of minimum-width integer types.
+ * C99 7.18.2.3 Limits of fastest minimum-width integer types.
+ *
+ * The presence of limit macros are completely optional in C99. This
+ * implementation defines limits for all of the types (exact- and
+ * minimum-width) that it defines above, using the limits of the minimum-width
+ * type for any types that do not have exact-width representations.
+ *
+ * As in the type definitions, this section takes an approach of
+ * successive-shrinking to determine which limits to use for the standard (8,
+ * 16, 32, 64) bit widths when they don't have exact representations. It is
+ * therefore important that the defintions be kept in order of decending
+ * widths.
+ *
+ * Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the
+ * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]).
+ */
+
+#ifdef __INT64_TYPE__
+# define INT64_MAX INT64_C( 9223372036854775807)
+# define INT64_MIN (-INT64_C( 9223372036854775807)-1)
+# define UINT64_MAX UINT64_C(18446744073709551615)
+# define __INT_LEAST64_MIN INT64_MIN
+# define __INT_LEAST64_MAX INT64_MAX
+# define __UINT_LEAST64_MAX UINT64_MAX
+# define __INT_LEAST32_MIN INT64_MIN
+# define __INT_LEAST32_MAX INT64_MAX
+# define __UINT_LEAST32_MAX UINT64_MAX
+# define __INT_LEAST16_MIN INT64_MIN
+# define __INT_LEAST16_MAX INT64_MAX
+# define __UINT_LEAST16_MAX UINT64_MAX
+# define __INT_LEAST8_MIN INT64_MIN
+# define __INT_LEAST8_MAX INT64_MAX
+# define __UINT_LEAST8_MAX UINT64_MAX
+#endif /* __INT64_TYPE__ */
+
+#ifdef __INT_LEAST64_MIN
+# define INT_LEAST64_MIN __INT_LEAST64_MIN
+# define INT_LEAST64_MAX __INT_LEAST64_MAX
+# define UINT_LEAST64_MAX __UINT_LEAST64_MAX
+# define INT_FAST64_MIN __INT_LEAST64_MIN
+# define INT_FAST64_MAX __INT_LEAST64_MAX
+# define UINT_FAST64_MAX __UINT_LEAST64_MAX
+#endif /* __INT_LEAST64_MIN */
+
+
+#ifdef __INT56_TYPE__
+# define INT56_MAX INT56_C(36028797018963967)
+# define INT56_MIN (-INT56_C(36028797018963967)-1)
+# define UINT56_MAX UINT56_C(72057594037927935)
+# define INT_LEAST56_MIN INT56_MIN
+# define INT_LEAST56_MAX INT56_MAX
+# define UINT_LEAST56_MAX UINT56_MAX
+# define INT_FAST56_MIN INT56_MIN
+# define INT_FAST56_MAX INT56_MAX
+# define UINT_FAST56_MAX UINT56_MAX
+# define __INT_LEAST32_MIN INT56_MIN
+# define __INT_LEAST32_MAX INT56_MAX
+# define __UINT_LEAST32_MAX UINT56_MAX
+# define __INT_LEAST16_MIN INT56_MIN
+# define __INT_LEAST16_MAX INT56_MAX
+# define __UINT_LEAST16_MAX UINT56_MAX
+# define __INT_LEAST8_MIN INT56_MIN
+# define __INT_LEAST8_MAX INT56_MAX
+# define __UINT_LEAST8_MAX UINT56_MAX
+#endif /* __INT56_TYPE__ */
+
+
+#ifdef __INT48_TYPE__
+# define INT48_MAX INT48_C(140737488355327)
+# define INT48_MIN (-INT48_C(140737488355327)-1)
+# define UINT48_MAX UINT48_C(281474976710655)
+# define INT_LEAST48_MIN INT48_MIN
+# define INT_LEAST48_MAX INT48_MAX
+# define UINT_LEAST48_MAX UINT48_MAX
+# define INT_FAST48_MIN INT48_MIN
+# define INT_FAST48_MAX INT48_MAX
+# define UINT_FAST48_MAX UINT48_MAX
+# define __INT_LEAST32_MIN INT48_MIN
+# define __INT_LEAST32_MAX INT48_MAX
+# define __UINT_LEAST32_MAX UINT48_MAX
+# define __INT_LEAST16_MIN INT48_MIN
+# define __INT_LEAST16_MAX INT48_MAX
+# define __UINT_LEAST16_MAX UINT48_MAX
+# define __INT_LEAST8_MIN INT48_MIN
+# define __INT_LEAST8_MAX INT48_MAX
+# define __UINT_LEAST8_MAX UINT48_MAX
+#endif /* __INT48_TYPE__ */
+
+
+#ifdef __INT40_TYPE__
+# define INT40_MAX INT40_C(549755813887)
+# define INT40_MIN (-INT40_C(549755813887)-1)
+# define UINT40_MAX UINT40_C(1099511627775)
+# define INT_LEAST40_MIN INT40_MIN
+# define INT_LEAST40_MAX INT40_MAX
+# define UINT_LEAST40_MAX UINT40_MAX
+# define INT_FAST40_MIN INT40_MIN
+# define INT_FAST40_MAX INT40_MAX
+# define UINT_FAST40_MAX UINT40_MAX
+# define __INT_LEAST32_MIN INT40_MIN
+# define __INT_LEAST32_MAX INT40_MAX
+# define __UINT_LEAST32_MAX UINT40_MAX
+# define __INT_LEAST16_MIN INT40_MIN
+# define __INT_LEAST16_MAX INT40_MAX
+# define __UINT_LEAST16_MAX UINT40_MAX
+# define __INT_LEAST8_MIN INT40_MIN
+# define __INT_LEAST8_MAX INT40_MAX
+# define __UINT_LEAST8_MAX UINT40_MAX
+#endif /* __INT40_TYPE__ */
+
+
+#ifdef __INT32_TYPE__
+# define INT32_MAX INT32_C(2147483647)
+# define INT32_MIN (-INT32_C(2147483647)-1)
+# define UINT32_MAX UINT32_C(4294967295)
+# define __INT_LEAST32_MIN INT32_MIN
+# define __INT_LEAST32_MAX INT32_MAX
+# define __UINT_LEAST32_MAX UINT32_MAX
+# define __INT_LEAST16_MIN INT32_MIN
+# define __INT_LEAST16_MAX INT32_MAX
+# define __UINT_LEAST16_MAX UINT32_MAX
+# define __INT_LEAST8_MIN INT32_MIN
+# define __INT_LEAST8_MAX INT32_MAX
+# define __UINT_LEAST8_MAX UINT32_MAX
+#endif /* __INT32_TYPE__ */
+
+#ifdef __INT_LEAST32_MIN
+# define INT_LEAST32_MIN __INT_LEAST32_MIN
+# define INT_LEAST32_MAX __INT_LEAST32_MAX
+# define UINT_LEAST32_MAX __UINT_LEAST32_MAX
+# define INT_FAST32_MIN __INT_LEAST32_MIN
+# define INT_FAST32_MAX __INT_LEAST32_MAX
+# define UINT_FAST32_MAX __UINT_LEAST32_MAX
+#endif /* __INT_LEAST32_MIN */
+
+
+#ifdef __INT24_TYPE__
+# define INT24_MAX INT24_C(8388607)
+# define INT24_MIN (-INT24_C(8388607)-1)
+# define UINT24_MAX UINT24_C(16777215)
+# define INT_LEAST24_MIN INT24_MIN
+# define INT_LEAST24_MAX INT24_MAX
+# define UINT_LEAST24_MAX UINT24_MAX
+# define INT_FAST24_MIN INT24_MIN
+# define INT_FAST24_MAX INT24_MAX
+# define UINT_FAST24_MAX UINT24_MAX
+# define __INT_LEAST16_MIN INT24_MIN
+# define __INT_LEAST16_MAX INT24_MAX
+# define __UINT_LEAST16_MAX UINT24_MAX
+# define __INT_LEAST8_MIN INT24_MIN
+# define __INT_LEAST8_MAX INT24_MAX
+# define __UINT_LEAST8_MAX UINT24_MAX
+#endif /* __INT24_TYPE__ */
+
+
+#ifdef __INT16_TYPE__
+#define INT16_MAX INT16_C(32767)
+#define INT16_MIN (-INT16_C(32767)-1)
+#define UINT16_MAX UINT16_C(65535)
+# define __INT_LEAST16_MIN INT16_MIN
+# define __INT_LEAST16_MAX INT16_MAX
+# define __UINT_LEAST16_MAX UINT16_MAX
+# define __INT_LEAST8_MIN INT16_MIN
+# define __INT_LEAST8_MAX INT16_MAX
+# define __UINT_LEAST8_MAX UINT16_MAX
+#endif /* __INT16_TYPE__ */
+
+#ifdef __INT_LEAST16_MIN
+# define INT_LEAST16_MIN __INT_LEAST16_MIN
+# define INT_LEAST16_MAX __INT_LEAST16_MAX
+# define UINT_LEAST16_MAX __UINT_LEAST16_MAX
+# define INT_FAST16_MIN __INT_LEAST16_MIN
+# define INT_FAST16_MAX __INT_LEAST16_MAX
+# define UINT_FAST16_MAX __UINT_LEAST16_MAX
+#endif /* __INT_LEAST16_MIN */
+
+
+#ifdef __INT8_TYPE__
+# define INT8_MAX INT8_C(127)
+# define INT8_MIN (-INT8_C(127)-1)
+# define UINT8_MAX UINT8_C(255)
+# define __INT_LEAST8_MIN INT8_MIN
+# define __INT_LEAST8_MAX INT8_MAX
+# define __UINT_LEAST8_MAX UINT8_MAX
+#endif /* __INT8_TYPE__ */
+
+#ifdef __INT_LEAST8_MIN
+# define INT_LEAST8_MIN __INT_LEAST8_MIN
+# define INT_LEAST8_MAX __INT_LEAST8_MAX
+# define UINT_LEAST8_MAX __UINT_LEAST8_MAX
+# define INT_FAST8_MIN __INT_LEAST8_MIN
+# define INT_FAST8_MAX __INT_LEAST8_MAX
+# define UINT_FAST8_MAX __UINT_LEAST8_MAX
+#endif /* __INT_LEAST8_MIN */
+
+/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */
+/* C99 7.18.3 Limits of other integer types. */
+#define __INTN_MIN(n) __stdint_join3( INT, n, _MIN)
+#define __INTN_MAX(n) __stdint_join3( INT, n, _MAX)
+#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX)
+
+#define INTPTR_MIN __INTN_MIN(__INTPTR_WIDTH__)
+#define INTPTR_MAX __INTN_MAX(__INTPTR_WIDTH__)
+#define UINTPTR_MAX __UINTN_MAX(__INTPTR_WIDTH__)
+#define PTRDIFF_MIN __INTN_MIN(__PTRDIFF_WIDTH__)
+#define PTRDIFF_MAX __INTN_MAX(__PTRDIFF_WIDTH__)
+#define SIZE_MAX __UINTN_MAX(__SIZE_WIDTH__)
+
+/* C99 7.18.2.5 Limits of greatest-width integer types. */
+#define INTMAX_MIN __INTN_MIN(__INTMAX_WIDTH__)
+#define INTMAX_MAX __INTN_MAX(__INTMAX_WIDTH__)
+#define UINTMAX_MAX __UINTN_MAX(__INTMAX_WIDTH__)
+
+/* C99 7.18.3 Limits of other integer types. */
+#define SIG_ATOMIC_MIN __INTN_MIN(__SIG_ATOMIC_WIDTH__)
+#define SIG_ATOMIC_MAX __INTN_MAX(__SIG_ATOMIC_WIDTH__)
+#define WINT_MIN __INTN_MIN(__WINT_WIDTH__)
+#define WINT_MAX __INTN_MAX(__WINT_WIDTH__)
+
+/* FIXME: if we ever support a target with unsigned wchar_t, this should be
+ * 0 .. Max.
+ */
+#ifndef WCHAR_MAX
+#define WCHAR_MAX __INTN_MAX(__WCHAR_WIDTH__)
+#endif
+#ifndef WCHAR_MIN
+#define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__)
+#endif
+
+/* 7.18.4.2 Macros for greatest-width integer constants. */
+#define __INTN_C(n, v) __stdint_join3( INT, n, _C(v))
+#define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v))
+
+#define INTMAX_C(v) __INTN_C(__INTMAX_WIDTH__, v)
+#define UINTMAX_C(v) __UINTN_C(__INTMAX_WIDTH__, v)
+
+#endif /* __STDC_HOSTED__ */
+#endif /* __CLANG_STDINT_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/tgmath.h b/contrib/llvm/tools/clang/lib/Headers/tgmath.h
new file mode 100644
index 0000000..e1a0023
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/tgmath.h
@@ -0,0 +1,1358 @@
+/*===---- tgmath.h - Standard header for type generic math ----------------===*\
+ *
+ * Copyright (c) 2009 Howard Hinnant
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifndef __TGMATH_H
+#define __TGMATH_H
+
+/* C99 7.22 Type-generic math <tgmath.h>. */
+#include <math.h>
+
+/* C++ handles type genericity with overloading in math.h. */
+#ifndef __cplusplus
+#include <complex.h>
+
+#define _TG_ATTRSp __attribute__((__overloadable__))
+#define _TG_ATTRS __attribute__((__overloadable__, __always_inline__))
+
+// promotion
+
+typedef void _Argument_type_is_not_arithmetic;
+static _Argument_type_is_not_arithmetic __tg_promote(...)
+ __attribute__((__unavailable__,__overloadable__));
+static double _TG_ATTRSp __tg_promote(int);
+static double _TG_ATTRSp __tg_promote(unsigned int);
+static double _TG_ATTRSp __tg_promote(long);
+static double _TG_ATTRSp __tg_promote(unsigned long);
+static double _TG_ATTRSp __tg_promote(long long);
+static double _TG_ATTRSp __tg_promote(unsigned long long);
+static float _TG_ATTRSp __tg_promote(float);
+static double _TG_ATTRSp __tg_promote(double);
+static long double _TG_ATTRSp __tg_promote(long double);
+static float _Complex _TG_ATTRSp __tg_promote(float _Complex);
+static double _Complex _TG_ATTRSp __tg_promote(double _Complex);
+static long double _Complex _TG_ATTRSp __tg_promote(long double _Complex);
+
+#define __tg_promote1(__x) (__typeof__(__tg_promote(__x)))
+#define __tg_promote2(__x, __y) (__typeof__(__tg_promote(__x) + \
+ __tg_promote(__y)))
+#define __tg_promote3(__x, __y, __z) (__typeof__(__tg_promote(__x) + \
+ __tg_promote(__y) + \
+ __tg_promote(__z)))
+
+// acos
+
+static float
+ _TG_ATTRS
+ __tg_acos(float __x) {return acosf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_acos(double __x) {return acos(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_acos(long double __x) {return acosl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_acos(float _Complex __x) {return cacosf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_acos(double _Complex __x) {return cacos(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_acos(long double _Complex __x) {return cacosl(__x);}
+
+#undef acos
+#define acos(__x) __tg_acos(__tg_promote1((__x))(__x))
+
+// asin
+
+static float
+ _TG_ATTRS
+ __tg_asin(float __x) {return asinf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_asin(double __x) {return asin(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_asin(long double __x) {return asinl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_asin(float _Complex __x) {return casinf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_asin(double _Complex __x) {return casin(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_asin(long double _Complex __x) {return casinl(__x);}
+
+#undef asin
+#define asin(__x) __tg_asin(__tg_promote1((__x))(__x))
+
+// atan
+
+static float
+ _TG_ATTRS
+ __tg_atan(float __x) {return atanf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_atan(double __x) {return atan(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_atan(long double __x) {return atanl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_atan(float _Complex __x) {return catanf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_atan(double _Complex __x) {return catan(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_atan(long double _Complex __x) {return catanl(__x);}
+
+#undef atan
+#define atan(__x) __tg_atan(__tg_promote1((__x))(__x))
+
+// acosh
+
+static float
+ _TG_ATTRS
+ __tg_acosh(float __x) {return acoshf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_acosh(double __x) {return acosh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_acosh(long double __x) {return acoshl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_acosh(float _Complex __x) {return cacoshf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_acosh(double _Complex __x) {return cacosh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_acosh(long double _Complex __x) {return cacoshl(__x);}
+
+#undef acosh
+#define acosh(__x) __tg_acosh(__tg_promote1((__x))(__x))
+
+// asinh
+
+static float
+ _TG_ATTRS
+ __tg_asinh(float __x) {return asinhf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_asinh(double __x) {return asinh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_asinh(long double __x) {return asinhl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_asinh(float _Complex __x) {return casinhf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_asinh(double _Complex __x) {return casinh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_asinh(long double _Complex __x) {return casinhl(__x);}
+
+#undef asinh
+#define asinh(__x) __tg_asinh(__tg_promote1((__x))(__x))
+
+// atanh
+
+static float
+ _TG_ATTRS
+ __tg_atanh(float __x) {return atanhf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_atanh(double __x) {return atanh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_atanh(long double __x) {return atanhl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_atanh(float _Complex __x) {return catanhf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_atanh(double _Complex __x) {return catanh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_atanh(long double _Complex __x) {return catanhl(__x);}
+
+#undef atanh
+#define atanh(__x) __tg_atanh(__tg_promote1((__x))(__x))
+
+// cos
+
+static float
+ _TG_ATTRS
+ __tg_cos(float __x) {return cosf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_cos(double __x) {return cos(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_cos(long double __x) {return cosl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_cos(float _Complex __x) {return ccosf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_cos(double _Complex __x) {return ccos(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_cos(long double _Complex __x) {return ccosl(__x);}
+
+#undef cos
+#define cos(__x) __tg_cos(__tg_promote1((__x))(__x))
+
+// sin
+
+static float
+ _TG_ATTRS
+ __tg_sin(float __x) {return sinf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_sin(double __x) {return sin(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_sin(long double __x) {return sinl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_sin(float _Complex __x) {return csinf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_sin(double _Complex __x) {return csin(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_sin(long double _Complex __x) {return csinl(__x);}
+
+#undef sin
+#define sin(__x) __tg_sin(__tg_promote1((__x))(__x))
+
+// tan
+
+static float
+ _TG_ATTRS
+ __tg_tan(float __x) {return tanf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_tan(double __x) {return tan(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_tan(long double __x) {return tanl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_tan(float _Complex __x) {return ctanf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_tan(double _Complex __x) {return ctan(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_tan(long double _Complex __x) {return ctanl(__x);}
+
+#undef tan
+#define tan(__x) __tg_tan(__tg_promote1((__x))(__x))
+
+// cosh
+
+static float
+ _TG_ATTRS
+ __tg_cosh(float __x) {return coshf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_cosh(double __x) {return cosh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_cosh(long double __x) {return coshl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_cosh(float _Complex __x) {return ccoshf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_cosh(double _Complex __x) {return ccosh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_cosh(long double _Complex __x) {return ccoshl(__x);}
+
+#undef cosh
+#define cosh(__x) __tg_cosh(__tg_promote1((__x))(__x))
+
+// sinh
+
+static float
+ _TG_ATTRS
+ __tg_sinh(float __x) {return sinhf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_sinh(double __x) {return sinh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_sinh(long double __x) {return sinhl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_sinh(float _Complex __x) {return csinhf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_sinh(double _Complex __x) {return csinh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_sinh(long double _Complex __x) {return csinhl(__x);}
+
+#undef sinh
+#define sinh(__x) __tg_sinh(__tg_promote1((__x))(__x))
+
+// tanh
+
+static float
+ _TG_ATTRS
+ __tg_tanh(float __x) {return tanhf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_tanh(double __x) {return tanh(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_tanh(long double __x) {return tanhl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_tanh(float _Complex __x) {return ctanhf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_tanh(double _Complex __x) {return ctanh(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_tanh(long double _Complex __x) {return ctanhl(__x);}
+
+#undef tanh
+#define tanh(__x) __tg_tanh(__tg_promote1((__x))(__x))
+
+// exp
+
+static float
+ _TG_ATTRS
+ __tg_exp(float __x) {return expf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_exp(double __x) {return exp(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_exp(long double __x) {return expl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_exp(float _Complex __x) {return cexpf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_exp(double _Complex __x) {return cexp(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_exp(long double _Complex __x) {return cexpl(__x);}
+
+#undef exp
+#define exp(__x) __tg_exp(__tg_promote1((__x))(__x))
+
+// log
+
+static float
+ _TG_ATTRS
+ __tg_log(float __x) {return logf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_log(double __x) {return log(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_log(long double __x) {return logl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_log(float _Complex __x) {return clogf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_log(double _Complex __x) {return clog(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_log(long double _Complex __x) {return clogl(__x);}
+
+#undef log
+#define log(__x) __tg_log(__tg_promote1((__x))(__x))
+
+// pow
+
+static float
+ _TG_ATTRS
+ __tg_pow(float __x, float __y) {return powf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_pow(double __x, double __y) {return pow(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_pow(long double __x, long double __y) {return powl(__x, __y);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_pow(float _Complex __x, float _Complex __y) {return cpowf(__x, __y);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_pow(double _Complex __x, double _Complex __y) {return cpow(__x, __y);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_pow(long double _Complex __x, long double _Complex __y)
+ {return cpowl(__x, __y);}
+
+#undef pow
+#define pow(__x, __y) __tg_pow(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// sqrt
+
+static float
+ _TG_ATTRS
+ __tg_sqrt(float __x) {return sqrtf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_sqrt(double __x) {return sqrt(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_sqrt(long double __x) {return sqrtl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_sqrt(float _Complex __x) {return csqrtf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_sqrt(double _Complex __x) {return csqrt(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_sqrt(long double _Complex __x) {return csqrtl(__x);}
+
+#undef sqrt
+#define sqrt(__x) __tg_sqrt(__tg_promote1((__x))(__x))
+
+// fabs
+
+static float
+ _TG_ATTRS
+ __tg_fabs(float __x) {return fabsf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_fabs(double __x) {return fabs(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_fabs(long double __x) {return fabsl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_fabs(float _Complex __x) {return cabsf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_fabs(double _Complex __x) {return cabs(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_fabs(long double _Complex __x) {return cabsl(__x);}
+
+#undef fabs
+#define fabs(__x) __tg_fabs(__tg_promote1((__x))(__x))
+
+// atan2
+
+static float
+ _TG_ATTRS
+ __tg_atan2(float __x, float __y) {return atan2f(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_atan2(double __x, double __y) {return atan2(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_atan2(long double __x, long double __y) {return atan2l(__x, __y);}
+
+#undef atan2
+#define atan2(__x, __y) __tg_atan2(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// cbrt
+
+static float
+ _TG_ATTRS
+ __tg_cbrt(float __x) {return cbrtf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_cbrt(double __x) {return cbrt(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_cbrt(long double __x) {return cbrtl(__x);}
+
+#undef cbrt
+#define cbrt(__x) __tg_cbrt(__tg_promote1((__x))(__x))
+
+// ceil
+
+static float
+ _TG_ATTRS
+ __tg_ceil(float __x) {return ceilf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_ceil(double __x) {return ceil(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_ceil(long double __x) {return ceill(__x);}
+
+#undef ceil
+#define ceil(__x) __tg_ceil(__tg_promote1((__x))(__x))
+
+// copysign
+
+static float
+ _TG_ATTRS
+ __tg_copysign(float __x, float __y) {return copysignf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_copysign(double __x, double __y) {return copysign(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_copysign(long double __x, long double __y) {return copysignl(__x, __y);}
+
+#undef copysign
+#define copysign(__x, __y) __tg_copysign(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// erf
+
+static float
+ _TG_ATTRS
+ __tg_erf(float __x) {return erff(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_erf(double __x) {return erf(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_erf(long double __x) {return erfl(__x);}
+
+#undef erf
+#define erf(__x) __tg_erf(__tg_promote1((__x))(__x))
+
+// erfc
+
+static float
+ _TG_ATTRS
+ __tg_erfc(float __x) {return erfcf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_erfc(double __x) {return erfc(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_erfc(long double __x) {return erfcl(__x);}
+
+#undef erfc
+#define erfc(__x) __tg_erfc(__tg_promote1((__x))(__x))
+
+// exp2
+
+static float
+ _TG_ATTRS
+ __tg_exp2(float __x) {return exp2f(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_exp2(double __x) {return exp2(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_exp2(long double __x) {return exp2l(__x);}
+
+#undef exp2
+#define exp2(__x) __tg_exp2(__tg_promote1((__x))(__x))
+
+// expm1
+
+static float
+ _TG_ATTRS
+ __tg_expm1(float __x) {return expm1f(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_expm1(double __x) {return expm1(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_expm1(long double __x) {return expm1l(__x);}
+
+#undef expm1
+#define expm1(__x) __tg_expm1(__tg_promote1((__x))(__x))
+
+// fdim
+
+static float
+ _TG_ATTRS
+ __tg_fdim(float __x, float __y) {return fdimf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_fdim(double __x, double __y) {return fdim(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_fdim(long double __x, long double __y) {return fdiml(__x, __y);}
+
+#undef fdim
+#define fdim(__x, __y) __tg_fdim(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// floor
+
+static float
+ _TG_ATTRS
+ __tg_floor(float __x) {return floorf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_floor(double __x) {return floor(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_floor(long double __x) {return floorl(__x);}
+
+#undef floor
+#define floor(__x) __tg_floor(__tg_promote1((__x))(__x))
+
+// fma
+
+static float
+ _TG_ATTRS
+ __tg_fma(float __x, float __y, float __z)
+ {return fmaf(__x, __y, __z);}
+
+static double
+ _TG_ATTRS
+ __tg_fma(double __x, double __y, double __z)
+ {return fma(__x, __y, __z);}
+
+static long double
+ _TG_ATTRS
+ __tg_fma(long double __x,long double __y, long double __z)
+ {return fmal(__x, __y, __z);}
+
+#undef fma
+#define fma(__x, __y, __z) \
+ __tg_fma(__tg_promote3((__x), (__y), (__z))(__x), \
+ __tg_promote3((__x), (__y), (__z))(__y), \
+ __tg_promote3((__x), (__y), (__z))(__z))
+
+// fmax
+
+static float
+ _TG_ATTRS
+ __tg_fmax(float __x, float __y) {return fmaxf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_fmax(double __x, double __y) {return fmax(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_fmax(long double __x, long double __y) {return fmaxl(__x, __y);}
+
+#undef fmax
+#define fmax(__x, __y) __tg_fmax(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// fmin
+
+static float
+ _TG_ATTRS
+ __tg_fmin(float __x, float __y) {return fminf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_fmin(double __x, double __y) {return fmin(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_fmin(long double __x, long double __y) {return fminl(__x, __y);}
+
+#undef fmin
+#define fmin(__x, __y) __tg_fmin(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// fmod
+
+static float
+ _TG_ATTRS
+ __tg_fmod(float __x, float __y) {return fmodf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_fmod(double __x, double __y) {return fmod(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_fmod(long double __x, long double __y) {return fmodl(__x, __y);}
+
+#undef fmod
+#define fmod(__x, __y) __tg_fmod(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// frexp
+
+static float
+ _TG_ATTRS
+ __tg_frexp(float __x, int* __y) {return frexpf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_frexp(double __x, int* __y) {return frexp(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_frexp(long double __x, int* __y) {return frexpl(__x, __y);}
+
+#undef frexp
+#define frexp(__x, __y) __tg_frexp(__tg_promote1((__x))(__x), __y)
+
+// hypot
+
+static float
+ _TG_ATTRS
+ __tg_hypot(float __x, float __y) {return hypotf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_hypot(double __x, double __y) {return hypot(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_hypot(long double __x, long double __y) {return hypotl(__x, __y);}
+
+#undef hypot
+#define hypot(__x, __y) __tg_hypot(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// ilogb
+
+static int
+ _TG_ATTRS
+ __tg_ilogb(float __x) {return ilogbf(__x);}
+
+static int
+ _TG_ATTRS
+ __tg_ilogb(double __x) {return ilogb(__x);}
+
+static int
+ _TG_ATTRS
+ __tg_ilogb(long double __x) {return ilogbl(__x);}
+
+#undef ilogb
+#define ilogb(__x) __tg_ilogb(__tg_promote1((__x))(__x))
+
+// ldexp
+
+static float
+ _TG_ATTRS
+ __tg_ldexp(float __x, int __y) {return ldexpf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_ldexp(double __x, int __y) {return ldexp(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_ldexp(long double __x, int __y) {return ldexpl(__x, __y);}
+
+#undef ldexp
+#define ldexp(__x, __y) __tg_ldexp(__tg_promote1((__x))(__x), __y)
+
+// lgamma
+
+static float
+ _TG_ATTRS
+ __tg_lgamma(float __x) {return lgammaf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_lgamma(double __x) {return lgamma(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_lgamma(long double __x) {return lgammal(__x);}
+
+#undef lgamma
+#define lgamma(__x) __tg_lgamma(__tg_promote1((__x))(__x))
+
+// llrint
+
+static long long
+ _TG_ATTRS
+ __tg_llrint(float __x) {return llrintf(__x);}
+
+static long long
+ _TG_ATTRS
+ __tg_llrint(double __x) {return llrint(__x);}
+
+static long long
+ _TG_ATTRS
+ __tg_llrint(long double __x) {return llrintl(__x);}
+
+#undef llrint
+#define llrint(__x) __tg_llrint(__tg_promote1((__x))(__x))
+
+// llround
+
+static long long
+ _TG_ATTRS
+ __tg_llround(float __x) {return llroundf(__x);}
+
+static long long
+ _TG_ATTRS
+ __tg_llround(double __x) {return llround(__x);}
+
+static long long
+ _TG_ATTRS
+ __tg_llround(long double __x) {return llroundl(__x);}
+
+#undef llround
+#define llround(__x) __tg_llround(__tg_promote1((__x))(__x))
+
+// log10
+
+static float
+ _TG_ATTRS
+ __tg_log10(float __x) {return log10f(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_log10(double __x) {return log10(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_log10(long double __x) {return log10l(__x);}
+
+#undef log10
+#define log10(__x) __tg_log10(__tg_promote1((__x))(__x))
+
+// log1p
+
+static float
+ _TG_ATTRS
+ __tg_log1p(float __x) {return log1pf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_log1p(double __x) {return log1p(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_log1p(long double __x) {return log1pl(__x);}
+
+#undef log1p
+#define log1p(__x) __tg_log1p(__tg_promote1((__x))(__x))
+
+// log2
+
+static float
+ _TG_ATTRS
+ __tg_log2(float __x) {return log2f(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_log2(double __x) {return log2(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_log2(long double __x) {return log2l(__x);}
+
+#undef log2
+#define log2(__x) __tg_log2(__tg_promote1((__x))(__x))
+
+// lrint
+
+static long
+ _TG_ATTRS
+ __tg_lrint(float __x) {return lrintf(__x);}
+
+static long
+ _TG_ATTRS
+ __tg_lrint(double __x) {return lrint(__x);}
+
+static long
+ _TG_ATTRS
+ __tg_lrint(long double __x) {return lrintl(__x);}
+
+#undef lrint
+#define lrint(__x) __tg_lrint(__tg_promote1((__x))(__x))
+
+// lround
+
+static long
+ _TG_ATTRS
+ __tg_lround(float __x) {return lroundf(__x);}
+
+static long
+ _TG_ATTRS
+ __tg_lround(double __x) {return lround(__x);}
+
+static long
+ _TG_ATTRS
+ __tg_lround(long double __x) {return lroundl(__x);}
+
+#undef lround
+#define lround(__x) __tg_lround(__tg_promote1((__x))(__x))
+
+// nearbyint
+
+static float
+ _TG_ATTRS
+ __tg_nearbyint(float __x) {return nearbyintf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_nearbyint(double __x) {return nearbyint(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_nearbyint(long double __x) {return nearbyintl(__x);}
+
+#undef nearbyint
+#define nearbyint(__x) __tg_nearbyint(__tg_promote1((__x))(__x))
+
+// nextafter
+
+static float
+ _TG_ATTRS
+ __tg_nextafter(float __x, float __y) {return nextafterf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_nextafter(double __x, double __y) {return nextafter(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_nextafter(long double __x, long double __y) {return nextafterl(__x, __y);}
+
+#undef nextafter
+#define nextafter(__x, __y) __tg_nextafter(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// nexttoward
+
+static float
+ _TG_ATTRS
+ __tg_nexttoward(float __x, float __y) {return nexttowardf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_nexttoward(double __x, double __y) {return nexttoward(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_nexttoward(long double __x, long double __y) {return nexttowardl(__x, __y);}
+
+#undef nexttoward
+#define nexttoward(__x, __y) __tg_nexttoward(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// remainder
+
+static float
+ _TG_ATTRS
+ __tg_remainder(float __x, float __y) {return remainderf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_remainder(double __x, double __y) {return remainder(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_remainder(long double __x, long double __y) {return remainderl(__x, __y);}
+
+#undef remainder
+#define remainder(__x, __y) __tg_remainder(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y))
+
+// remquo
+
+static float
+ _TG_ATTRS
+ __tg_remquo(float __x, float __y, int* __z)
+ {return remquof(__x, __y, __z);}
+
+static double
+ _TG_ATTRS
+ __tg_remquo(double __x, double __y, int* __z)
+ {return remquo(__x, __y, __z);}
+
+static long double
+ _TG_ATTRS
+ __tg_remquo(long double __x,long double __y, int* __z)
+ {return remquol(__x, __y, __z);}
+
+#undef remquo
+#define remquo(__x, __y, __z) \
+ __tg_remquo(__tg_promote2((__x), (__y))(__x), \
+ __tg_promote2((__x), (__y))(__y), \
+ (__z))
+
+// rint
+
+static float
+ _TG_ATTRS
+ __tg_rint(float __x) {return rintf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_rint(double __x) {return rint(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_rint(long double __x) {return rintl(__x);}
+
+#undef rint
+#define rint(__x) __tg_rint(__tg_promote1((__x))(__x))
+
+// round
+
+static float
+ _TG_ATTRS
+ __tg_round(float __x) {return roundf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_round(double __x) {return round(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_round(long double __x) {return roundl(__x);}
+
+#undef round
+#define round(__x) __tg_round(__tg_promote1((__x))(__x))
+
+// scalbn
+
+static float
+ _TG_ATTRS
+ __tg_scalbn(float __x, int __y) {return scalbnf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_scalbn(double __x, int __y) {return scalbn(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_scalbn(long double __x, int __y) {return scalbnl(__x, __y);}
+
+#undef scalbn
+#define scalbn(__x, __y) __tg_scalbn(__tg_promote1((__x))(__x), __y)
+
+// scalbln
+
+static float
+ _TG_ATTRS
+ __tg_scalbln(float __x, long __y) {return scalblnf(__x, __y);}
+
+static double
+ _TG_ATTRS
+ __tg_scalbln(double __x, long __y) {return scalbln(__x, __y);}
+
+static long double
+ _TG_ATTRS
+ __tg_scalbln(long double __x, long __y) {return scalblnl(__x, __y);}
+
+#undef scalbln
+#define scalbln(__x, __y) __tg_scalbln(__tg_promote1((__x))(__x), __y)
+
+// tgamma
+
+static float
+ _TG_ATTRS
+ __tg_tgamma(float __x) {return tgammaf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_tgamma(double __x) {return tgamma(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_tgamma(long double __x) {return tgammal(__x);}
+
+#undef tgamma
+#define tgamma(__x) __tg_tgamma(__tg_promote1((__x))(__x))
+
+// trunc
+
+static float
+ _TG_ATTRS
+ __tg_trunc(float __x) {return truncf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_trunc(double __x) {return trunc(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_trunc(long double __x) {return truncl(__x);}
+
+#undef trunc
+#define trunc(__x) __tg_trunc(__tg_promote1((__x))(__x))
+
+// carg
+
+static float
+ _TG_ATTRS
+ __tg_carg(float __x) {return atan2f(0.F, __x);}
+
+static double
+ _TG_ATTRS
+ __tg_carg(double __x) {return atan2(0., __x);}
+
+static long double
+ _TG_ATTRS
+ __tg_carg(long double __x) {return atan2l(0.L, __x);}
+
+static float
+ _TG_ATTRS
+ __tg_carg(float _Complex __x) {return cargf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_carg(double _Complex __x) {return carg(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_carg(long double _Complex __x) {return cargl(__x);}
+
+#undef carg
+#define carg(__x) __tg_carg(__tg_promote1((__x))(__x))
+
+// cimag
+
+static float
+ _TG_ATTRS
+ __tg_cimag(float __x) {return 0;}
+
+static double
+ _TG_ATTRS
+ __tg_cimag(double __x) {return 0;}
+
+static long double
+ _TG_ATTRS
+ __tg_cimag(long double __x) {return 0;}
+
+static float
+ _TG_ATTRS
+ __tg_cimag(float _Complex __x) {return cimagf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_cimag(double _Complex __x) {return cimag(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_cimag(long double _Complex __x) {return cimagl(__x);}
+
+#undef cimag
+#define cimag(__x) __tg_cimag(__tg_promote1((__x))(__x))
+
+// conj
+
+static float _Complex
+ _TG_ATTRS
+ __tg_conj(float __x) {return __x;}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_conj(double __x) {return __x;}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_conj(long double __x) {return __x;}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_conj(float _Complex __x) {return conjf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_conj(double _Complex __x) {return conj(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_conj(long double _Complex __x) {return conjl(__x);}
+
+#undef conj
+#define conj(__x) __tg_conj(__tg_promote1((__x))(__x))
+
+// cproj
+
+static float _Complex
+ _TG_ATTRS
+ __tg_cproj(float __x) {return cprojf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_cproj(double __x) {return cproj(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_cproj(long double __x) {return cprojl(__x);}
+
+static float _Complex
+ _TG_ATTRS
+ __tg_cproj(float _Complex __x) {return cprojf(__x);}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_cproj(double _Complex __x) {return cproj(__x);}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_cproj(long double _Complex __x) {return cprojl(__x);}
+
+#undef cproj
+#define cproj(__x) __tg_cproj(__tg_promote1((__x))(__x))
+
+// creal
+
+static float _Complex
+ _TG_ATTRS
+ __tg_creal(float __x) {return __x;}
+
+static double _Complex
+ _TG_ATTRS
+ __tg_creal(double __x) {return __x;}
+
+static long double _Complex
+ _TG_ATTRS
+ __tg_creal(long double __x) {return __x;}
+
+static float
+ _TG_ATTRS
+ __tg_creal(float _Complex __x) {return crealf(__x);}
+
+static double
+ _TG_ATTRS
+ __tg_creal(double _Complex __x) {return creal(__x);}
+
+static long double
+ _TG_ATTRS
+ __tg_creal(long double _Complex __x) {return creall(__x);}
+
+#undef creal
+#define creal(__x) __tg_creal(__tg_promote1((__x))(__x))
+
+#undef _TG_ATTRSp
+#undef _TG_ATTRS
+
+#endif /* __cplusplus */
+#endif /* __TGMATH_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
new file mode 100644
index 0000000..07fea1c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
@@ -0,0 +1,218 @@
+/*===---- tmmintrin.h - SSSE3 intrinsics -----------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __TMMINTRIN_H
+#define __TMMINTRIN_H
+
+#ifndef __SSSE3__
+#error "SSSE3 instruction set not enabled"
+#else
+
+#include <pmmintrin.h>
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_abs_pi8(__m64 a)
+{
+ return (__m64)__builtin_ia32_pabsb((__v8qi)a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_abs_epi8(__m128i a)
+{
+ return (__m128i)__builtin_ia32_pabsb128((__v16qi)a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_abs_pi16(__m64 a)
+{
+ return (__m64)__builtin_ia32_pabsw((__v4hi)a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_abs_epi16(__m128i a)
+{
+ return (__m128i)__builtin_ia32_pabsw128((__v8hi)a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_abs_pi32(__m64 a)
+{
+ return (__m64)__builtin_ia32_pabsd((__v2si)a);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_abs_epi32(__m128i a)
+{
+ return (__m128i)__builtin_ia32_pabsd128((__v4si)a);
+}
+
+#define _mm_alignr_epi8(a, b, n) (__builtin_ia32_palignr128((a), (b), (n)))
+#define _mm_alignr_pi8(a, b, n) (__builtin_ia32_palignr((a), (b), (n)))
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phaddw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phaddd128((__v4si)a, (__v4si)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phaddw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hadd_pi32(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phaddd((__v2si)a, (__v2si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hadds_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phaddsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hadds_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phaddsw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phsubw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phsubd128((__v4si)a, (__v4si)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phsubw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hsub_pi32(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phsubd((__v2si)a, (__v2si)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_hsubs_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_phsubsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_hsubs_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_phsubsw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_maddubs_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmaddubsw128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_maddubs_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pmaddubsw((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_mulhrs_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pmulhrsw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_mulhrs_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pmulhrsw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_shuffle_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_pshufb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_shuffle_pi8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pshufb((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sign_epi8(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psignb128((__v16qi)a, (__v16qi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sign_epi16(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psignw128((__v8hi)a, (__v8hi)b);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_sign_epi32(__m128i a, __m128i b)
+{
+ return (__m128i)__builtin_ia32_psignd128((__v4si)a, (__v4si)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sign_pi8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_psignb((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sign_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_psignw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sign_pi32(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_psignd((__v2si)a, (__v2si)b);
+}
+
+#endif /* __SSSE3__ */
+
+#endif /* __TMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/varargs.h b/contrib/llvm/tools/clang/lib/Headers/varargs.h
new file mode 100644
index 0000000..b5477d0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/varargs.h
@@ -0,0 +1,26 @@
+/*===---- varargs.h - Variable argument handling -------------------------------------===
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*===-----------------------------------------------------------------------===
+*/
+#ifndef __VARARGS_H
+#define __VARARGS_H
+ #error "Please use <stdarg.h> instead of <varargs.h>"
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
new file mode 100644
index 0000000..6b2e468
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
@@ -0,0 +1,67 @@
+/*===---- wmmintrin.h - AES intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef _WMMINTRIN_H
+#define _WMMINTRIN_H
+
+#if !defined (__AES__)
+# error "AES instructions not enabled"
+#else
+
+#include <smmintrin.h>
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_aesenc_si128(__m128i __V, __m128i __R)
+{
+ return (__m128i)__builtin_ia32_aesenc128(__V, __R);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_aesenclast_si128(__m128i __V, __m128i __R)
+{
+ return (__m128i)__builtin_ia32_aesenclast128(__V, __R);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_aesdec_si128(__m128i __V, __m128i __R)
+{
+ return (__m128i)__builtin_ia32_aesdec128(__V, __R);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_aesdeclast_si128(__m128i __V, __m128i __R)
+{
+ return (__m128i)__builtin_ia32_aesdeclast128(__V, __R);
+}
+
+static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
+_mm_aesimc_si128(__m128i __V)
+{
+ return (__m128i)__builtin_ia32_aesimc128(__V);
+}
+
+#define _mm_aeskeygenassist_si128(C, R) \
+ __builtin_ia32_aeskeygenassist128((C), (R))
+
+#endif /* __AES__ */
+#endif /* _WMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/x86intrin.h b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
new file mode 100644
index 0000000..e5e7a6a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
@@ -0,0 +1,31 @@
+/*===---- x86intrin.h - X86 intrinsics -------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __X86INTRIN_H
+#define __X86INTRIN_H
+
+#include <immintrin.h>
+
+// FIXME: SSE4A, 3dNOW, FMA4, XOP, LWP, ABM, POPCNT
+
+#endif /* __X86INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
new file mode 100644
index 0000000..42dd3e8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
@@ -0,0 +1,967 @@
+/*===---- xmmintrin.h - SSE intrinsics -------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __XMMINTRIN_H
+#define __XMMINTRIN_H
+
+#ifndef __SSE__
+#error "SSE instruction set not enabled"
+#else
+
+#include <mmintrin.h>
+
+typedef int __v4si __attribute__((__vector_size__(16)));
+typedef float __v4sf __attribute__((__vector_size__(16)));
+typedef float __m128 __attribute__((__vector_size__(16)));
+
+// This header should only be included in a hosted environment as it depends on
+// a standard library to provide allocation routines.
+#if __STDC_HOSTED__
+#include <mm_malloc.h>
+#endif
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_add_ss(__m128 a, __m128 b)
+{
+ a[0] += b[0];
+ return a;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_add_ps(__m128 a, __m128 b)
+{
+ return a + b;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_ss(__m128 a, __m128 b)
+{
+ a[0] -= b[0];
+ return a;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_sub_ps(__m128 a, __m128 b)
+{
+ return a - b;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_mul_ss(__m128 a, __m128 b)
+{
+ a[0] *= b[0];
+ return a;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_mul_ps(__m128 a, __m128 b)
+{
+ return a * b;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_div_ss(__m128 a, __m128 b)
+{
+ a[0] /= b[0];
+ return a;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_div_ps(__m128 a, __m128 b)
+{
+ return a / b;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_sqrt_ss(__m128 a)
+{
+ return __builtin_ia32_sqrtss(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_sqrt_ps(__m128 a)
+{
+ return __builtin_ia32_sqrtps(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_rcp_ss(__m128 a)
+{
+ return __builtin_ia32_rcpss(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_rcp_ps(__m128 a)
+{
+ return __builtin_ia32_rcpps(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_rsqrt_ss(__m128 a)
+{
+ return __builtin_ia32_rsqrtss(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_rsqrt_ps(__m128 a)
+{
+ return __builtin_ia32_rsqrtps(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_min_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_minss(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_min_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_minps(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_max_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_maxss(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_max_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_maxps(a, b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_and_ps(__m128 a, __m128 b)
+{
+ return (__m128)((__v4si)a & (__v4si)b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_andnot_ps(__m128 a, __m128 b)
+{
+ return (__m128)(~(__v4si)a & (__v4si)b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_or_ps(__m128 a, __m128 b)
+{
+ return (__m128)((__v4si)a | (__v4si)b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_xor_ps(__m128 a, __m128 b)
+{
+ return (__m128)((__v4si)a ^ (__v4si)b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 0);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpeq_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 0);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 1);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmplt_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 1);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmple_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 2);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmple_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 2);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(b, a, 1);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpgt_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(b, a, 1);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpge_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(b, a, 2);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpge_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(b, a, 2);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpneq_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 4);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpneq_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 4);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnlt_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnlt_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnle_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 6);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnle_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 6);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpngt_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(b, a, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpngt_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(b, a, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnge_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(b, a, 6);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpnge_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(b, a, 6);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpord_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 7);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpord_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 7);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpunord_ss(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpss(a, b, 3);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmpunord_ps(__m128 a, __m128 b)
+{
+ return (__m128)__builtin_ia32_cmpps(a, b, 3);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comieq_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comieq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comilt_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comilt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comile_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comile(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comigt_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comigt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comige_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comige(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_comineq_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_comineq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomieq_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomieq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomilt_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomilt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomile_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomile(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomigt_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomigt(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomige_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomige(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_ucomineq_ss(__m128 a, __m128 b)
+{
+ return __builtin_ia32_ucomineq(a, b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvtss_si32(__m128 a)
+{
+ return __builtin_ia32_cvtss2si(a);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_ss2si(__m128 a)
+{
+ return _mm_cvtss_si32(a);
+}
+
+#ifdef __x86_64__
+
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvtss_si64(__m128 a)
+{
+ return __builtin_ia32_cvtss2si64(a);
+}
+
+#endif
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtps_pi32(__m128 a)
+{
+ return (__m64)__builtin_ia32_cvtps2pi(a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_ps2pi(__m128 a)
+{
+ return _mm_cvtps_pi32(a);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvttss_si32(__m128 a)
+{
+ return a[0];
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_cvtt_ss2si(__m128 a)
+{
+ return _mm_cvttss_si32(a);
+}
+
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+_mm_cvttss_si64(__m128 a)
+{
+ return a[0];
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvttps_pi32(__m128 a)
+{
+ return (__m64)__builtin_ia32_cvttps2pi(a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtt_ps2pi(__m128 a)
+{
+ return _mm_cvttps_pi32(a);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi32_ss(__m128 a, int b)
+{
+ a[0] = b;
+ return a;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_si2ss(__m128 a, int b)
+{
+ return _mm_cvtsi32_ss(a, b);
+}
+
+#ifdef __x86_64__
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtsi64_ss(__m128 a, long long b)
+{
+ a[0] = b;
+ return a;
+}
+
+#endif
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpi32_ps(__m128 a, __m64 b)
+{
+ return __builtin_ia32_cvtpi2ps(a, (__v2si)b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_pi2ps(__m128 a, __m64 b)
+{
+ return _mm_cvtpi32_ps(a, b);
+}
+
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+_mm_cvtss_f32(__m128 a)
+{
+ return a[0];
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_loadh_pi(__m128 a, const __m64 *p)
+{
+ __m128 b;
+ b[0] = *(float*)p;
+ b[1] = *((float*)p+1);
+ return __builtin_shufflevector(a, b, 0, 1, 4, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_loadl_pi(__m128 a, const __m64 *p)
+{
+ __m128 b;
+ b[0] = *(float*)p;
+ b[1] = *((float*)p+1);
+ return __builtin_shufflevector(a, b, 4, 5, 2, 3);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_load_ss(const float *p)
+{
+ return (__m128){ *p, 0, 0, 0 };
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_load1_ps(const float *p)
+{
+ return (__m128){ *p, *p, *p, *p };
+}
+
+#define _mm_load_ps1(p) _mm_load1_ps(p)
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_load_ps(const float *p)
+{
+ return *(__m128*)p;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_loadu_ps(const float *p)
+{
+ return __builtin_ia32_loadups(p);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_loadr_ps(const float *p)
+{
+ __m128 a = _mm_load_ps(p);
+ return __builtin_shufflevector(a, a, 3, 2, 1, 0);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_set_ss(float w)
+{
+ return (__m128){ w, 0, 0, 0 };
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_set1_ps(float w)
+{
+ return (__m128){ w, w, w, w };
+}
+
+// Microsoft specific.
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_set_ps1(float w)
+{
+ return _mm_set1_ps(w);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_set_ps(float z, float y, float x, float w)
+{
+ return (__m128){ w, x, y, z };
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_setr_ps(float z, float y, float x, float w)
+{
+ return (__m128){ z, y, x, w };
+}
+
+static __inline__ __m128 __attribute__((__always_inline__))
+_mm_setzero_ps(void)
+{
+ return (__m128){ 0, 0, 0, 0 };
+}
+
+static __inline__ void __attribute__((__always_inline__))
+_mm_storeh_pi(__m64 *p, __m128 a)
+{
+ __builtin_ia32_storehps((__v2si *)p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__))
+_mm_storel_pi(__m64 *p, __m128 a)
+{
+ __builtin_ia32_storelps((__v2si *)p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__))
+_mm_store_ss(float *p, __m128 a)
+{
+ *p = a[0];
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storeu_ps(float *p, __m128 a)
+{
+ __builtin_ia32_storeups(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store1_ps(float *p, __m128 a)
+{
+ a = __builtin_shufflevector(a, a, 0, 0, 0, 0);
+ _mm_storeu_ps(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_ps1(float *p, __m128 a)
+{
+ return _mm_store1_ps(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_ps(float *p, __m128 a)
+{
+ *(__m128 *)p = a;
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_storer_ps(float *p, __m128 a)
+{
+ a = __builtin_shufflevector(a, a, 3, 2, 1, 0);
+ _mm_store_ps(p, a);
+}
+
+#define _MM_HINT_T0 3
+#define _MM_HINT_T1 2
+#define _MM_HINT_T2 1
+#define _MM_HINT_NTA 0
+
+/* FIXME: We have to #define this because "sel" must be a constant integer, and
+ Sema doesn't do any form of constant propagation yet. */
+
+#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, sel))
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_stream_pi(__m64 *p, __m64 a)
+{
+ __builtin_ia32_movntq(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_stream_ps(float *p, __m128 a)
+{
+ __builtin_ia32_movntps(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_sfence(void)
+{
+ __builtin_ia32_sfence();
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_extract_pi16(__m64 a, int n)
+{
+ __v4hi b = (__v4hi)a;
+ return (unsigned short)b[n & 3];
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_insert_pi16(__m64 a, int d, int n)
+{
+ __v4hi b = (__v4hi)a;
+ b[n & 3] = d;
+ return (__m64)b;
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_max_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pmaxsw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_max_pu8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pmaxub((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_min_pi16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pminsw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_min_pu8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pminub((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_movemask_pi8(__m64 a)
+{
+ return __builtin_ia32_pmovmskb((__v8qi)a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_mulhi_pu16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pmulhuw((__v4hi)a, (__v4hi)b);
+}
+
+#define _mm_shuffle_pi16(a, n) \
+ ((__m64)__builtin_ia32_pshufw(a, n))
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_maskmove_si64(__m64 d, __m64 n, char *p)
+{
+ __builtin_ia32_maskmovq((__v8qi)d, (__v8qi)n, p);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_avg_pu8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pavgb((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_avg_pu16(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_pavgw((__v4hi)a, (__v4hi)b);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_sad_pu8(__m64 a, __m64 b)
+{
+ return (__m64)__builtin_ia32_psadbw((__v8qi)a, (__v8qi)b);
+}
+
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+_mm_getcsr(void)
+{
+ return __builtin_ia32_stmxcsr();
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_setcsr(unsigned int i)
+{
+ __builtin_ia32_ldmxcsr(i);
+}
+
+#define _mm_shuffle_ps(a, b, mask) \
+ (__builtin_shufflevector((__v4sf)(a), (__v4sf)(b), \
+ (mask) & 0x3, ((mask) & 0xc) >> 2, \
+ (((mask) & 0x30) >> 4) + 4, \
+ (((mask) & 0xc0) >> 6) + 4))
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_unpackhi_ps(__m128 a, __m128 b)
+{
+ return __builtin_shufflevector(a, b, 2, 6, 3, 7);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_unpacklo_ps(__m128 a, __m128 b)
+{
+ return __builtin_shufflevector(a, b, 0, 4, 1, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_move_ss(__m128 a, __m128 b)
+{
+ return __builtin_shufflevector(a, b, 4, 1, 2, 3);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_movehl_ps(__m128 a, __m128 b)
+{
+ return __builtin_shufflevector(a, b, 6, 7, 2, 3);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_movelh_ps(__m128 a, __m128 b)
+{
+ return __builtin_shufflevector(a, b, 0, 1, 4, 5);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpi16_ps(__m64 a)
+{
+ __m64 b, c;
+ __m128 r;
+
+ b = _mm_setzero_si64();
+ b = _mm_cmpgt_pi16(b, a);
+ c = _mm_unpackhi_pi16(a, b);
+ r = _mm_setzero_ps();
+ r = _mm_cvtpi32_ps(r, c);
+ r = _mm_movelh_ps(r, r);
+ c = _mm_unpacklo_pi16(a, b);
+ r = _mm_cvtpi32_ps(r, c);
+
+ return r;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpu16_ps(__m64 a)
+{
+ __m64 b, c;
+ __m128 r;
+
+ b = _mm_setzero_si64();
+ c = _mm_unpackhi_pi16(a, b);
+ r = _mm_setzero_ps();
+ r = _mm_cvtpi32_ps(r, c);
+ r = _mm_movelh_ps(r, r);
+ c = _mm_unpacklo_pi16(a, b);
+ r = _mm_cvtpi32_ps(r, c);
+
+ return r;
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpi8_ps(__m64 a)
+{
+ __m64 b;
+
+ b = _mm_setzero_si64();
+ b = _mm_cmpgt_pi8(b, a);
+ b = _mm_unpacklo_pi8(a, b);
+
+ return _mm_cvtpi16_ps(b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpu8_ps(__m64 a)
+{
+ __m64 b;
+
+ b = _mm_setzero_si64();
+ b = _mm_unpacklo_pi8(a, b);
+
+ return _mm_cvtpi16_ps(b);
+}
+
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtpi32x2_ps(__m64 a, __m64 b)
+{
+ __m128 c;
+
+ c = _mm_setzero_ps();
+ c = _mm_cvtpi32_ps(c, b);
+ c = _mm_movelh_ps(c, c);
+
+ return _mm_cvtpi32_ps(c, a);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtps_pi16(__m128 a)
+{
+ __m64 b, c;
+
+ b = _mm_cvtps_pi32(a);
+ a = _mm_movehl_ps(a, a);
+ c = _mm_cvtps_pi32(a);
+
+ return _mm_packs_pi16(b, c);
+}
+
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtps_pi8(__m128 a)
+{
+ __m64 b, c;
+
+ b = _mm_cvtps_pi16(a);
+ c = _mm_setzero_si64();
+
+ return _mm_packs_pi16(b, c);
+}
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+_mm_movemask_ps(__m128 a)
+{
+ return __builtin_ia32_movmskps(a);
+}
+
+#define _MM_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
+
+#define _MM_EXCEPT_INVALID (0x0001)
+#define _MM_EXCEPT_DENORM (0x0002)
+#define _MM_EXCEPT_DIV_ZERO (0x0004)
+#define _MM_EXCEPT_OVERFLOW (0x0008)
+#define _MM_EXCEPT_UNDERFLOW (0x0010)
+#define _MM_EXCEPT_INEXACT (0x0020)
+#define _MM_EXCEPT_MASK (0x003f)
+
+#define _MM_MASK_INVALID (0x0080)
+#define _MM_MASK_DENORM (0x0100)
+#define _MM_MASK_DIV_ZERO (0x0200)
+#define _MM_MASK_OVERFLOW (0x0400)
+#define _MM_MASK_UNDERFLOW (0x0800)
+#define _MM_MASK_INEXACT (0x1000)
+#define _MM_MASK_MASK (0x1f80)
+
+#define _MM_ROUND_NEAREST (0x0000)
+#define _MM_ROUND_DOWN (0x2000)
+#define _MM_ROUND_UP (0x4000)
+#define _MM_ROUND_TOWARD_ZERO (0x6000)
+#define _MM_ROUND_MASK (0x6000)
+
+#define _MM_FLUSH_ZERO_MASK (0x8000)
+#define _MM_FLUSH_ZERO_ON (0x8000)
+#define _MM_FLUSH_ZERO_OFF (0x8000)
+
+#define _MM_GET_EXCEPTION_MASK() (_mm_getcsr() & _MM_MASK_MASK)
+#define _MM_GET_EXCEPTION_STATE() (_mm_getcsr() & _MM_EXCEPT_MASK)
+#define _MM_GET_FLUSH_ZERO_MODE() (_mm_getcsr() & _MM_FLUSH_ZERO_MASK)
+#define _MM_GET_ROUNDING_MODE() (_mm_getcsr() & _MM_ROUND_MASK)
+
+#define _MM_SET_EXCEPTION_MASK(x) (_mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | (x)))
+#define _MM_SET_EXCEPTION_STATE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_EXCEPT_MASK) | (x)))
+#define _MM_SET_FLUSH_ZERO_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_FLUSH_ZERO_MASK) | (x)))
+#define _MM_SET_ROUNDING_MODE(x) (_mm_setcsr((_mm_getcsr() & ~_MM_ROUND_MASK) | (x)))
+
+#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
+do { \
+ __m128 tmp3, tmp2, tmp1, tmp0; \
+ tmp0 = _mm_unpacklo_ps((row0), (row1)); \
+ tmp2 = _mm_unpacklo_ps((row2), (row3)); \
+ tmp1 = _mm_unpackhi_ps((row0), (row1)); \
+ tmp3 = _mm_unpackhi_ps((row2), (row3)); \
+ (row0) = _mm_movelh_ps(tmp0, tmp2); \
+ (row1) = _mm_movehl_ps(tmp2, tmp0); \
+ (row2) = _mm_movelh_ps(tmp1, tmp3); \
+ (row3) = _mm_movehl_ps(tmp3, tmp1); \
+} while (0)
+
+/* Aliases for compatibility. */
+#define _m_pextrw _mm_extract_pi16
+#define _m_pinsrw _mm_insert_pi16
+#define _m_pmaxsw _mm_max_pi16
+#define _m_pmaxub _mm_max_pu8
+#define _m_pminsw _mm_min_pi16
+#define _m_pminub _mm_min_pu8
+#define _m_pmovmskb _mm_movemask_pi8
+#define _m_pmulhuw _mm_mulhi_pu16
+#define _m_pshufw _mm_shuffle_pi16
+#define _m_maskmovq _mm_maskmove_si64
+#define _m_pavgb _mm_avg_pu8
+#define _m_pavgw _mm_avg_pu16
+#define _m_psadbw _mm_sad_pu8
+#define _m_ _mm_
+#define _m_ _mm_
+
+/* Ugly hack for backwards-compatibility (compatible with gcc) */
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#endif /* __SSE__ */
+
+#endif /* __XMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp b/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp
new file mode 100644
index 0000000..bd3b5ee
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/ASTLocation.cpp
@@ -0,0 +1,117 @@
+//===--- ASTLocation.cpp - A <Decl, Stmt> pair ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTLocation is Decl or a Stmt and its immediate Decl parent.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+using namespace clang;
+using namespace idx;
+
+static Decl *getDeclFromExpr(Stmt *E) {
+ if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
+ return RefExpr->getDecl();
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
+ return RE->getDecl();
+
+ if (CallExpr *CE = dyn_cast<CallExpr>(E))
+ return getDeclFromExpr(CE->getCallee());
+ if (CastExpr *CE = dyn_cast<CastExpr>(E))
+ return getDeclFromExpr(CE->getSubExpr());
+
+ return 0;
+}
+
+Decl *ASTLocation::getReferencedDecl() {
+ if (isInvalid())
+ return 0;
+
+ switch (getKind()) {
+ default: assert(0 && "Invalid Kind");
+ case N_Type:
+ return 0;
+ case N_Decl:
+ return D;
+ case N_NamedRef:
+ return NDRef.ND;
+ case N_Stmt:
+ return getDeclFromExpr(Stm);
+ }
+
+ return 0;
+}
+
+SourceRange ASTLocation::getSourceRange() const {
+ if (isInvalid())
+ return SourceRange();
+
+ switch (getKind()) {
+ default: assert(0 && "Invalid Kind");
+ return SourceRange();
+ case N_Decl:
+ return D->getSourceRange();
+ case N_Stmt:
+ return Stm->getSourceRange();
+ case N_NamedRef:
+ return SourceRange(AsNamedRef().Loc, AsNamedRef().Loc);
+ case N_Type:
+ return AsTypeLoc().getLocalSourceRange();
+ }
+
+ return SourceRange();
+}
+
+void ASTLocation::print(llvm::raw_ostream &OS) const {
+ if (isInvalid()) {
+ OS << "<< Invalid ASTLocation >>\n";
+ return;
+ }
+
+ ASTContext &Ctx = getParentDecl()->getASTContext();
+
+ switch (getKind()) {
+ case N_Decl:
+ OS << "[Decl: " << AsDecl()->getDeclKindName() << " ";
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl()))
+ OS << ND;
+ break;
+
+ case N_Stmt:
+ OS << "[Stmt: " << AsStmt()->getStmtClassName() << " ";
+ AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
+ break;
+
+ case N_NamedRef:
+ OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " ";
+ OS << AsNamedRef().ND;
+ break;
+
+ case N_Type: {
+ QualType T = AsTypeLoc().getType();
+ OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
+ }
+ }
+
+ OS << "] <";
+
+ SourceRange Range = getSourceRange();
+ SourceManager &SourceMgr = Ctx.getSourceManager();
+ Range.getBegin().print(OS, SourceMgr);
+ OS << ", ";
+ Range.getEnd().print(OS, SourceMgr);
+ OS << ">\n";
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h b/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h
new file mode 100644
index 0000000..0b8425b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/ASTVisitor.h
@@ -0,0 +1,143 @@
+//===--- ASTVisitor.h - Visitor for an ASTContext ---------------*- 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 ASTVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ASTVISITOR_H
+#define LLVM_CLANG_INDEX_ASTVISITOR_H
+
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLocVisitor.h"
+
+namespace clang {
+
+namespace idx {
+
+/// \brief Traverses the full AST, both Decls and Stmts.
+template<typename ImplClass>
+class ASTVisitor : public DeclVisitor<ImplClass>,
+ public StmtVisitor<ImplClass>,
+ public TypeLocVisitor<ImplClass> {
+public:
+ ASTVisitor() : CurrentDecl(0) { }
+
+ Decl *CurrentDecl;
+
+ typedef ASTVisitor<ImplClass> Base;
+ typedef DeclVisitor<ImplClass> BaseDeclVisitor;
+ typedef StmtVisitor<ImplClass> BaseStmtVisitor;
+ typedef TypeLocVisitor<ImplClass> BaseTypeLocVisitor;
+
+ using BaseStmtVisitor::Visit;
+
+ //===--------------------------------------------------------------------===//
+ // DeclVisitor
+ //===--------------------------------------------------------------------===//
+
+ void Visit(Decl *D) {
+ Decl *PrevDecl = CurrentDecl;
+ CurrentDecl = D;
+ BaseDeclVisitor::Visit(D);
+ CurrentDecl = PrevDecl;
+ }
+
+ void VisitDeclaratorDecl(DeclaratorDecl *D) {
+ BaseDeclVisitor::VisitDeclaratorDecl(D);
+ if (TypeSourceInfo *TInfo = D->getTypeSourceInfo())
+ Visit(TInfo->getTypeLoc());
+ }
+
+ void VisitFunctionDecl(FunctionDecl *D) {
+ BaseDeclVisitor::VisitFunctionDecl(D);
+ if (D->isThisDeclarationADefinition())
+ Visit(D->getBody());
+ }
+
+ void VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ BaseDeclVisitor::VisitObjCMethodDecl(D);
+ if (D->getBody())
+ Visit(D->getBody());
+ }
+
+ void VisitBlockDecl(BlockDecl *D) {
+ BaseDeclVisitor::VisitBlockDecl(D);
+ Visit(D->getBody());
+ }
+
+ void VisitVarDecl(VarDecl *D) {
+ BaseDeclVisitor::VisitVarDecl(D);
+ if (Expr *Init = D->getInit())
+ Visit(Init);
+ }
+
+ void VisitDecl(Decl *D) {
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D))
+ return;
+
+ if (DeclContext *DC = dyn_cast<DeclContext>(D))
+ static_cast<ImplClass*>(this)->VisitDeclContext(DC);
+ }
+
+ void VisitDeclContext(DeclContext *DC) {
+ for (DeclContext::decl_iterator
+ I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
+ Visit(*I);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // StmtVisitor
+ //===--------------------------------------------------------------------===//
+
+ void VisitDeclStmt(DeclStmt *Node) {
+ for (DeclStmt::decl_iterator
+ I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I)
+ Visit(*I);
+ }
+
+ void VisitBlockExpr(BlockExpr *Node) {
+ // The BlockDecl is also visited by 'VisitDeclContext()'. No need to visit it twice.
+ }
+
+ void VisitStmt(Stmt *Node) {
+ for (Stmt::child_range I = Node->children(); I; ++I)
+ if (*I)
+ Visit(*I);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // TypeLocVisitor
+ //===--------------------------------------------------------------------===//
+
+ void Visit(TypeLoc TL) {
+ for (; TL; TL = TL.getNextTypeLoc())
+ BaseTypeLocVisitor::Visit(TL);
+ }
+
+ void VisitArrayLoc(ArrayTypeLoc TL) {
+ BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
+ if (TL.getSizeExpr())
+ Visit(TL.getSizeExpr());
+ }
+
+ void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
+ for (unsigned i = 0; i != TL.getNumArgs(); ++i)
+ Visit(TL.getArg(i));
+ }
+
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp b/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp
new file mode 100644
index 0000000..6be35ab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/Analyzer.cpp
@@ -0,0 +1,470 @@
+//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Analyzer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/Analyzer.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/TranslationUnit.h"
+#include "clang/Index/Handlers.h"
+#include "clang/Index/ASTLocation.h"
+#include "clang/Index/GlobalSelector.h"
+#include "clang/Index/DeclReferenceMap.h"
+#include "clang/Index/SelectorMap.h"
+#include "clang/Index/IndexProvider.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "llvm/ADT/SmallSet.h"
+using namespace clang;
+using namespace idx;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// DeclEntityAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+class DeclEntityAnalyzer : public TranslationUnitHandler {
+ Entity Ent;
+ TULocationHandler &TULocHandler;
+
+public:
+ DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
+ : Ent(ent), TULocHandler(handler) { }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+
+ Decl *D = Ent.getDecl(TU->getASTContext());
+ assert(D && "Couldn't resolve Entity");
+
+ for (Decl::redecl_iterator I = D->redecls_begin(),
+ E = D->redecls_end(); I != E; ++I)
+ TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// RefEntityAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+class RefEntityAnalyzer : public TranslationUnitHandler {
+ Entity Ent;
+ TULocationHandler &TULocHandler;
+
+public:
+ RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
+ : Ent(ent), TULocHandler(handler) { }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+
+ Decl *D = Ent.getDecl(TU->getASTContext());
+ assert(D && "Couldn't resolve Entity");
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return;
+
+ DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
+ for (DeclReferenceMap::astlocation_iterator
+ I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
+ TULocHandler.Handle(TULocation(TU, *I));
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// RefSelectorAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Accepts an ObjC method and finds all message expressions that this
+/// method may respond to.
+class RefSelectorAnalyzer : public TranslationUnitHandler {
+ Program &Prog;
+ TULocationHandler &TULocHandler;
+
+ // The original ObjCInterface associated with the method.
+ Entity IFaceEnt;
+ GlobalSelector GlobSel;
+ bool IsInstanceMethod;
+
+ /// \brief Super classes of the ObjCInterface.
+ typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
+ EntitiesSetTy HierarchyEntities;
+
+public:
+ RefSelectorAnalyzer(ObjCMethodDecl *MD,
+ Program &prog, TULocationHandler &handler)
+ : Prog(prog), TULocHandler(handler) {
+ assert(MD);
+
+ // FIXME: Protocol methods.
+ assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
+ "Protocol methods not supported yet");
+
+ ObjCInterfaceDecl *IFD = MD->getClassInterface();
+ assert(IFD);
+ IFaceEnt = Entity::get(IFD, Prog);
+ GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
+ IsInstanceMethod = MD->isInstanceMethod();
+
+ for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
+ Cls; Cls = Cls->getSuperClass())
+ HierarchyEntities.insert(Entity::get(Cls, Prog));
+ }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+
+ ASTContext &Ctx = TU->getASTContext();
+ // Null means it doesn't exist in this translation unit.
+ ObjCInterfaceDecl *IFace =
+ cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
+ Selector Sel = GlobSel.getSelector(Ctx);
+
+ SelectorMap &SelMap = TU->getSelectorMap();
+ for (SelectorMap::astlocation_iterator
+ I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
+ if (ValidReference(*I, IFace))
+ TULocHandler.Handle(TULocation(TU, *I));
+ }
+ }
+
+ /// \brief Determines whether the given message expression is likely to end
+ /// up at the given interface decl.
+ ///
+ /// It returns true "eagerly", meaning it will return false only if it can
+ /// "prove" statically that the interface cannot accept this message.
+ bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
+ assert(ASTLoc.isStmt());
+
+ // FIXME: Finding @selector references should be through another Analyzer
+ // method, like FindSelectors.
+ if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
+ return false;
+
+ ObjCInterfaceDecl *MsgD = 0;
+ ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
+
+ switch (Msg->getReceiverKind()) {
+ case ObjCMessageExpr::Instance: {
+ const ObjCObjectPointerType *OPT =
+ Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
+
+ // Can be anything! Accept it as a possibility..
+ if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
+ return true;
+
+ // Expecting class method.
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
+ return !IsInstanceMethod;
+
+ MsgD = OPT->getInterfaceDecl();
+ assert(MsgD);
+
+ // Should be an instance method.
+ if (!IsInstanceMethod)
+ return false;
+ break;
+ }
+
+ case ObjCMessageExpr::Class: {
+ // Expecting class method.
+ if (IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
+ break;
+ }
+
+ case ObjCMessageExpr::SuperClass:
+ // Expecting class method.
+ if (IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ // Expecting instance method.
+ if (!IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl();
+ break;
+ }
+
+ assert(MsgD);
+
+ // Same interface ? We have a winner!
+ if (MsgD == IFace)
+ return true;
+
+ // If the message interface is a superclass of the original interface,
+ // accept this message as a possibility.
+ if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
+ return true;
+
+ // If the message interface is a subclass of the original interface, accept
+ // the message unless there is a subclass in the hierarchy that will
+ // "steal" the message (thus the message "will go" to the subclass and not
+ /// the original interface).
+ if (IFace) {
+ Selector Sel = Msg->getSelector();
+ for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
+ if (Cls == IFace)
+ return true;
+ if (Cls->getMethod(Sel, IsInstanceMethod))
+ return false;
+ }
+ }
+
+ // The interfaces are unrelated, don't accept the message.
+ return false;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// MessageAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Accepts an ObjC message expression and finds all methods that may
+/// respond to it.
+class MessageAnalyzer : public TranslationUnitHandler {
+ Program &Prog;
+ TULocationHandler &TULocHandler;
+
+ // The ObjCInterface associated with the message. Can be null/invalid.
+ Entity MsgIFaceEnt;
+ GlobalSelector GlobSel;
+ bool CanBeInstanceMethod;
+ bool CanBeClassMethod;
+
+ /// \brief Super classes of the ObjCInterface.
+ typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
+ EntitiesSetTy HierarchyEntities;
+
+ /// \brief The interface in the message interface hierarchy that "intercepts"
+ /// the selector.
+ Entity ReceiverIFaceEnt;
+
+public:
+ MessageAnalyzer(ObjCMessageExpr *Msg,
+ Program &prog, TULocationHandler &handler)
+ : Prog(prog), TULocHandler(handler),
+ CanBeInstanceMethod(false),
+ CanBeClassMethod(false) {
+
+ assert(Msg);
+
+ ObjCInterfaceDecl *MsgD = 0;
+
+ while (true) {
+ switch (Msg->getReceiverKind()) {
+ case ObjCMessageExpr::Instance: {
+ const ObjCObjectPointerType *OPT =
+ Msg->getInstanceReceiver()->getType()
+ ->getAsObjCInterfacePointerType();
+
+ if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
+ CanBeInstanceMethod = CanBeClassMethod = true;
+ break;
+ }
+
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ CanBeClassMethod = true;
+ break;
+ }
+
+ MsgD = OPT->getInterfaceDecl();
+ assert(MsgD);
+ CanBeInstanceMethod = true;
+ break;
+ }
+
+ case ObjCMessageExpr::Class:
+ CanBeClassMethod = true;
+ MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ CanBeClassMethod = true;
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ CanBeInstanceMethod = true;
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl();
+ break;
+ }
+ }
+
+ assert(CanBeInstanceMethod || CanBeClassMethod);
+
+ Selector sel = Msg->getSelector();
+ assert(!sel.isNull());
+
+ MsgIFaceEnt = Entity::get(MsgD, Prog);
+ GlobSel = GlobalSelector::get(sel, Prog);
+
+ if (MsgD) {
+ for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
+ Cls; Cls = Cls->getSuperClass())
+ HierarchyEntities.insert(Entity::get(Cls, Prog));
+
+ // Find the interface in the hierarchy that "receives" the message.
+ for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
+ bool isReceiver = false;
+
+ ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
+ for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
+ Meth != MethEnd; ++Meth) {
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
+ if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
+ (MD->isClassMethod() && CanBeClassMethod)) {
+ isReceiver = true;
+ break;
+ }
+ }
+
+ if (isReceiver) {
+ ReceiverIFaceEnt = Entity::get(Cls, Prog);
+ break;
+ }
+ }
+ }
+ }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+ ASTContext &Ctx = TU->getASTContext();
+
+ // Null means it doesn't exist in this translation unit or there was no
+ // interface that was determined to receive the original message.
+ ObjCInterfaceDecl *ReceiverIFace =
+ cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
+
+ // No subclass for the original receiver interface, so it remains the
+ // receiver.
+ if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
+ return;
+
+ // Null means it doesn't exist in this translation unit or there was no
+ // interface associated with the message in the first place.
+ ObjCInterfaceDecl *MsgIFace =
+ cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
+
+ Selector Sel = GlobSel.getSelector(Ctx);
+ SelectorMap &SelMap = TU->getSelectorMap();
+ for (SelectorMap::method_iterator
+ I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
+ I != E; ++I) {
+ ObjCMethodDecl *D = *I;
+ if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
+ for (ObjCMethodDecl::redecl_iterator
+ RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
+ TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
+ }
+ }
+ }
+
+ /// \brief Determines whether the given method is likely to accept the
+ /// original message.
+ ///
+ /// It returns true "eagerly", meaning it will return false only if it can
+ /// "prove" statically that the method cannot accept the original message.
+ bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
+ ObjCInterfaceDecl *ReceiverIFace) {
+ assert(D);
+
+ // FIXME: Protocol methods ?
+ if (isa<ObjCProtocolDecl>(D->getDeclContext()))
+ return false;
+
+ // No specific interface associated with the message. Can be anything.
+ if (MsgIFaceEnt.isInvalid())
+ return true;
+
+ if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
+ (!CanBeClassMethod && D->isClassMethod()))
+ return false;
+
+ ObjCInterfaceDecl *IFace = D->getClassInterface();
+ assert(IFace);
+
+ // If the original message interface is the same or a superclass of the
+ // given interface, accept the method as a possibility.
+ if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
+ return true;
+
+ if (ReceiverIFace) {
+ // The given interface, "overrides" the receiver.
+ if (ReceiverIFace->isSuperClassOf(IFace))
+ return true;
+ } else {
+ // No receiver was found for the original message.
+ assert(ReceiverIFaceEnt.isInvalid());
+
+ // If the original message interface is a subclass of the given interface,
+ // accept the message.
+ if (HierarchyEntities.count(Entity::get(IFace, Prog)))
+ return true;
+ }
+
+ // The interfaces are unrelated, or the receiver interface wasn't
+ // "overriden".
+ return false;
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Analyzer Implementation
+//===----------------------------------------------------------------------===//
+
+void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
+ assert(D && "Passed null declaration");
+ Entity Ent = Entity::get(D, Prog);
+ if (Ent.isInvalid())
+ return;
+
+ DeclEntityAnalyzer DEA(Ent, Handler);
+ Idxer.GetTranslationUnitsFor(Ent, DEA);
+}
+
+void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
+ assert(D && "Passed null declaration");
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ RefSelectorAnalyzer RSA(MD, Prog, Handler);
+ GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
+ Idxer.GetTranslationUnitsFor(Sel, RSA);
+ return;
+ }
+
+ Entity Ent = Entity::get(D, Prog);
+ if (Ent.isInvalid())
+ return;
+
+ RefEntityAnalyzer REA(Ent, Handler);
+ Idxer.GetTranslationUnitsFor(Ent, REA);
+}
+
+/// \brief Find methods that may respond to the given message and pass them
+/// to Handler.
+void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
+ TULocationHandler &Handler) {
+ assert(Msg);
+ MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
+ GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
+ Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp b/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp
new file mode 100644
index 0000000..bf3f5a8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/CallGraph.cpp
@@ -0,0 +1,150 @@
+//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the CallGraph and CGBuilder classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/CallGraph.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/StmtVisitor.h"
+
+#include "llvm/Support/GraphWriter.h"
+
+using namespace clang;
+using namespace idx;
+
+namespace {
+class CGBuilder : public StmtVisitor<CGBuilder> {
+
+ CallGraph &G;
+ FunctionDecl *FD;
+
+ Entity CallerEnt;
+
+ CallGraphNode *CallerNode;
+
+public:
+ CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
+ : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
+
+ void VisitStmt(Stmt *S) { VisitChildren(S); }
+
+ void VisitCallExpr(CallExpr *CE);
+
+ void VisitChildren(Stmt *S) {
+ for (Stmt::child_range I = S->children(); I; ++I)
+ if (*I)
+ static_cast<CGBuilder*>(this)->Visit(*I);
+ }
+};
+}
+
+void CGBuilder::VisitCallExpr(CallExpr *CE) {
+ if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
+ Entity Ent = Entity::get(CalleeDecl, G.getProgram());
+ CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
+ CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
+ }
+}
+
+CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
+ ExternalCallingNode = getOrInsertFunction(Entity());
+}
+
+CallGraph::~CallGraph() {
+ if (!FunctionMap.empty()) {
+ for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
+ I != E; ++I)
+ delete I->second;
+ FunctionMap.clear();
+ }
+}
+
+void CallGraph::addTU(ASTContext& Ctx) {
+ DeclContext *DC = Ctx.getTranslationUnitDecl();
+ for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+ I != E; ++I) {
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ if (FD->isThisDeclarationADefinition()) {
+ // Set caller's ASTContext.
+ Entity Ent = Entity::get(FD, Prog);
+ CallGraphNode *Node = getOrInsertFunction(Ent);
+ CallerCtx[Node] = &Ctx;
+
+ // If this function has external linkage, anything could call it.
+ if (FD->isGlobal())
+ ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
+
+ // Set root node to 'main' function.
+ if (FD->getNameAsString() == "main")
+ Root = Node;
+
+ CGBuilder builder(*this, FD, Ent, Node);
+ builder.Visit(FD->getBody());
+ }
+ }
+ }
+}
+
+CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
+ CallGraphNode *&Node = FunctionMap[F];
+ if (Node)
+ return Node;
+
+ return Node = new CallGraphNode(F);
+}
+
+Decl *CallGraph::getDecl(CallGraphNode *Node) {
+ // Get the function's context.
+ ASTContext *Ctx = CallerCtx[Node];
+
+ return Node->getDecl(*Ctx);
+}
+
+void CallGraph::print(llvm::raw_ostream &os) {
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ if (I->second->hasCallee()) {
+ os << "function: " << I->first.getPrintableName()
+ << " calls:\n";
+ for (CallGraphNode::iterator CI = I->second->begin(),
+ CE = I->second->end(); CI != CE; ++CI) {
+ os << " " << CI->second->getName();
+ }
+ os << '\n';
+ }
+ }
+}
+
+void CallGraph::dump() {
+ print(llvm::errs());
+}
+
+void CallGraph::ViewCallGraph() const {
+ llvm::ViewGraph(*this, "CallGraph");
+}
+
+namespace llvm {
+
+template <>
+struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
+
+ DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+
+ static std::string getNodeLabel(const CallGraphNode *Node,
+ const CallGraph &CG) {
+ return Node->getName();
+
+ }
+
+};
+
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp
new file mode 100644
index 0000000..d6e30ab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/DeclReferenceMap.cpp
@@ -0,0 +1,90 @@
+//===--- DeclReferenceMap.cpp - Map Decls to their references -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
+// reference them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/DeclReferenceMap.h"
+#include "clang/Index/ASTLocation.h"
+#include "ASTVisitor.h"
+using namespace clang;
+using namespace idx;
+
+namespace {
+
+class RefMapper : public ASTVisitor<RefMapper> {
+ DeclReferenceMap::MapTy &Map;
+
+public:
+ RefMapper(DeclReferenceMap::MapTy &map) : Map(map) { }
+
+ void VisitDeclRefExpr(DeclRefExpr *Node);
+ void VisitMemberExpr(MemberExpr *Node);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
+
+ void VisitTypedefTypeLoc(TypedefTypeLoc TL);
+ void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
+};
+
+} // anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RefMapper Implementation
+//===----------------------------------------------------------------------===//
+
+void RefMapper::VisitDeclRefExpr(DeclRefExpr *Node) {
+ NamedDecl *PrimD = cast<NamedDecl>(Node->getDecl()->getCanonicalDecl());
+ Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
+}
+
+void RefMapper::VisitMemberExpr(MemberExpr *Node) {
+ NamedDecl *PrimD = cast<NamedDecl>(Node->getMemberDecl()->getCanonicalDecl());
+ Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
+}
+
+void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));
+}
+
+void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ NamedDecl *ND = TL.getTypedefDecl();
+ Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
+}
+
+void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ NamedDecl *ND = TL.getIFaceDecl();
+ Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
+}
+
+//===----------------------------------------------------------------------===//
+// DeclReferenceMap Implementation
+//===----------------------------------------------------------------------===//
+
+DeclReferenceMap::DeclReferenceMap(ASTContext &Ctx) {
+ RefMapper(Map).Visit(Ctx.getTranslationUnitDecl());
+}
+
+DeclReferenceMap::astlocation_iterator
+DeclReferenceMap::refs_begin(NamedDecl *D) const {
+ NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
+ return astlocation_iterator(Map.lower_bound(Prim));
+}
+
+DeclReferenceMap::astlocation_iterator
+DeclReferenceMap::refs_end(NamedDecl *D) const {
+ NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
+ return astlocation_iterator(Map.upper_bound(Prim));
+}
+
+bool DeclReferenceMap::refs_empty(NamedDecl *D) const {
+ NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
+ return refs_begin(Prim) == refs_end(Prim);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/Entity.cpp b/contrib/llvm/tools/clang/lib/Index/Entity.cpp
new file mode 100644
index 0000000..749dcc8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/Entity.cpp
@@ -0,0 +1,270 @@
+//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Entity is a ASTContext-independent way to refer to declarations that are
+// visible across translation units.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EntityImpl.h"
+#include "ProgramImpl.h"
+#include "clang/Index/Program.h"
+#include "clang/Index/GlobalSelector.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+using namespace clang;
+using namespace idx;
+
+// FIXME: Entity is really really basic currently, mostly written to work
+// on variables and functions. Should support types and other decls eventually..
+
+
+//===----------------------------------------------------------------------===//
+// EntityGetter
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace idx {
+
+/// \brief Gets the Entity associated with a Decl.
+class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
+ Program &Prog;
+ ProgramImpl &ProgImpl;
+
+public:
+ EntityGetter(Program &prog, ProgramImpl &progImpl)
+ : Prog(prog), ProgImpl(progImpl) { }
+
+ // Get an Entity.
+ Entity getEntity(Entity Parent, DeclarationName Name,
+ unsigned IdNS, bool isObjCInstanceMethod);
+
+ // Get an Entity associated with the name in the global namespace.
+ Entity getGlobalEntity(llvm::StringRef Name);
+
+ Entity VisitNamedDecl(NamedDecl *D);
+ Entity VisitVarDecl(VarDecl *D);
+ Entity VisitFieldDecl(FieldDecl *D);
+ Entity VisitFunctionDecl(FunctionDecl *D);
+ Entity VisitTypeDecl(TypeDecl *D);
+};
+
+}
+}
+
+Entity EntityGetter::getEntity(Entity Parent, DeclarationName Name,
+ unsigned IdNS, bool isObjCInstanceMethod) {
+ llvm::FoldingSetNodeID ID;
+ EntityImpl::Profile(ID, Parent, Name, IdNS, isObjCInstanceMethod);
+
+ ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
+ void *InsertPos = 0;
+ if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
+ return Entity(Ent);
+
+ void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
+ EntityImpl *New =
+ new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod);
+ Entities.InsertNode(New, InsertPos);
+
+ return Entity(New);
+}
+
+Entity EntityGetter::getGlobalEntity(llvm::StringRef Name) {
+ IdentifierInfo *II = &ProgImpl.getIdents().get(Name);
+ DeclarationName GlobName(II);
+ unsigned IdNS = Decl::IDNS_Ordinary;
+ return getEntity(Entity(), GlobName, IdNS, false);
+}
+
+Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
+ Entity Parent;
+ if (!D->getDeclContext()->isTranslationUnit()) {
+ Parent = Visit(cast<Decl>(D->getDeclContext()));
+ // FIXME: Anonymous structs ?
+ if (Parent.isInvalid())
+ return Entity();
+ }
+ if (Parent.isValid() && Parent.isInternalToTU())
+ return Entity(D);
+
+ // FIXME: Only works for DeclarationNames that are identifiers and selectors.
+ // Treats other DeclarationNames as internal Decls for now..
+
+ DeclarationName LocalName = D->getDeclName();
+ if (!LocalName)
+ return Entity(D);
+
+ DeclarationName GlobName;
+
+ if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
+ IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
+ GlobName = DeclarationName(GlobII);
+ } else {
+ Selector LocalSel = LocalName.getObjCSelector();
+
+ // Treats other DeclarationNames as internal Decls for now..
+ if (LocalSel.isNull())
+ return Entity(D);
+
+ Selector GlobSel =
+ (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
+ GlobName = DeclarationName(GlobSel);
+ }
+
+ assert(GlobName);
+
+ unsigned IdNS = D->getIdentifierNamespace();
+
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
+ bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
+ return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
+}
+
+Entity EntityGetter::VisitVarDecl(VarDecl *D) {
+ // Local variables have no linkage, make invalid Entities.
+ if (D->hasLocalStorage())
+ return Entity();
+
+ // If it's static it cannot be referred to by another translation unit.
+ if (D->getStorageClass() == SC_Static)
+ return Entity(D);
+
+ return VisitNamedDecl(D);
+}
+
+Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
+ // If it's static it cannot be refered to by another translation unit.
+ if (D->getStorageClass() == SC_Static)
+ return Entity(D);
+
+ return VisitNamedDecl(D);
+}
+
+Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
+ // Make FieldDecl an invalid Entity since it has no linkage.
+ return Entity();
+}
+
+Entity EntityGetter::VisitTypeDecl(TypeDecl *D) {
+ // Although in C++ class name has external linkage, usually the definition of
+ // the class is available in the same translation unit when it's needed. So we
+ // make all of them invalid Entity.
+ return Entity();
+}
+
+//===----------------------------------------------------------------------===//
+// EntityImpl Implementation
+//===----------------------------------------------------------------------===//
+
+Decl *EntityImpl::getDecl(ASTContext &AST) {
+ DeclContext *DC =
+ Parent.isInvalid() ? AST.getTranslationUnitDecl()
+ : cast<DeclContext>(Parent.getDecl(AST));
+ if (!DC)
+ return 0; // Couldn't get the parent context.
+
+ DeclarationName LocalName;
+
+ if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
+ IdentifierInfo &II = AST.Idents.get(GlobII->getName());
+ LocalName = DeclarationName(&II);
+ } else {
+ Selector GlobSel = Name.getObjCSelector();
+ assert(!GlobSel.isNull() && "A not handled yet declaration name");
+ GlobalSelector GSel =
+ GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
+ LocalName = GSel.getSelector(AST);
+ }
+
+ assert(LocalName);
+
+ DeclContext::lookup_result Res = DC->lookup(LocalName);
+ for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
+ Decl *D = *I;
+ if (D->getIdentifierNamespace() == IdNS) {
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (MD->isInstanceMethod() == IsObjCInstanceMethod)
+ return MD;
+ } else
+ return D;
+ }
+ }
+
+ return 0; // Failed to find a decl using this Entity.
+}
+
+/// \brief Get an Entity associated with the given Decl.
+/// \returns Null if an Entity cannot refer to this Decl.
+Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
+ assert(D && "Passed null Decl");
+ return EntityGetter(Prog, ProgImpl).Visit(D);
+}
+
+/// \brief Get an Entity associated with a global name.
+Entity EntityImpl::get(llvm::StringRef Name, Program &Prog,
+ ProgramImpl &ProgImpl) {
+ return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
+}
+
+std::string EntityImpl::getPrintableName() {
+ return Name.getAsString();
+}
+
+//===----------------------------------------------------------------------===//
+// Entity Implementation
+//===----------------------------------------------------------------------===//
+
+Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
+
+/// \brief Find the Decl that can be referred to by this entity.
+Decl *Entity::getDecl(ASTContext &AST) const {
+ if (isInvalid())
+ return 0;
+
+ if (Decl *D = Val.dyn_cast<Decl *>())
+ // Check that the passed AST is actually the one that this Decl belongs to.
+ return (&D->getASTContext() == &AST) ? D : 0;
+
+ return Val.get<EntityImpl *>()->getDecl(AST);
+}
+
+std::string Entity::getPrintableName() const {
+ if (isInvalid())
+ return "<< Invalid >>";
+
+ if (Decl *D = Val.dyn_cast<Decl *>()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ return ND->getNameAsString();
+ else
+ return std::string();
+ }
+
+ return Val.get<EntityImpl *>()->getPrintableName();
+}
+
+/// \brief Get an Entity associated with the given Decl.
+/// \returns Null if an Entity cannot refer to this Decl.
+Entity Entity::get(Decl *D, Program &Prog) {
+ if (D == 0)
+ return Entity();
+ ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
+ return EntityImpl::get(D, Prog, ProgImpl);
+}
+
+Entity Entity::get(llvm::StringRef Name, Program &Prog) {
+ ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
+ return EntityImpl::get(Name, Prog, ProgImpl);
+}
+
+unsigned
+llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
+ return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/EntityImpl.h b/contrib/llvm/tools/clang/lib/Index/EntityImpl.h
new file mode 100644
index 0000000..da52ccf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/EntityImpl.h
@@ -0,0 +1,71 @@
+//===--- EntityImpl.h - Internal Entity implementation---------*- C++ -*-=====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal implementation for the Entity class
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ENTITYIMPL_H
+#define LLVM_CLANG_INDEX_ENTITYIMPL_H
+
+#include "clang/Index/Entity.h"
+#include "clang/AST/DeclarationName.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace clang {
+
+namespace idx {
+ class ProgramImpl;
+
+class EntityImpl : public llvm::FoldingSetNode {
+ Entity Parent;
+ DeclarationName Name;
+
+ /// \brief Identifier namespace.
+ unsigned IdNS;
+
+ /// \brief If Name is a selector, this keeps track whether it's for an
+ /// instance method.
+ bool IsObjCInstanceMethod;
+
+public:
+ EntityImpl(Entity parent, DeclarationName name, unsigned idNS,
+ bool isObjCInstanceMethod)
+ : Parent(parent), Name(name), IdNS(idNS),
+ IsObjCInstanceMethod(isObjCInstanceMethod) { }
+
+ /// \brief Find the Decl that can be referred to by this entity.
+ Decl *getDecl(ASTContext &AST);
+
+ /// \brief Get an Entity associated with the given Decl.
+ /// \returns Null if an Entity cannot refer to this Decl.
+ static Entity get(Decl *D, Program &Prog, ProgramImpl &ProgImpl);
+ static Entity get(llvm::StringRef Name, Program &Prog, ProgramImpl &ProgImpl);
+
+ std::string getPrintableName();
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, Parent, Name, IdNS, IsObjCInstanceMethod);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent,
+ DeclarationName Name, unsigned IdNS,
+ bool isObjCInstanceMethod) {
+ ID.AddPointer(Parent.getAsOpaquePtr());
+ ID.AddPointer(Name.getAsOpaquePtr());
+ ID.AddInteger(IdNS);
+ ID.AddBoolean(isObjCInstanceMethod);
+ }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp b/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp
new file mode 100644
index 0000000..3467918
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/GlobalSelector.cpp
@@ -0,0 +1,71 @@
+//===-- GlobalSelector.cpp - Cross-translation-unit "token" for selectors -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// GlobalSelector is a ASTContext-independent way to refer to selectors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/GlobalSelector.h"
+#include "ProgramImpl.h"
+#include "clang/Index/Program.h"
+#include "clang/AST/ASTContext.h"
+using namespace clang;
+using namespace idx;
+
+/// \brief Get the ASTContext-specific selector.
+Selector GlobalSelector::getSelector(ASTContext &AST) const {
+ if (isInvalid())
+ return Selector();
+
+ Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
+
+ llvm::SmallVector<IdentifierInfo *, 8> Ids;
+ for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
+ i != e; ++i) {
+ IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
+ IdentifierInfo *II = &AST.Idents.get(GlobII->getName());
+ Ids.push_back(II);
+ }
+
+ return AST.Selectors.getSelector(GlobSel.getNumArgs(), Ids.data());
+}
+
+/// \brief Get a printable name for debugging purpose.
+std::string GlobalSelector::getPrintableName() const {
+ if (isInvalid())
+ return "<< Invalid >>";
+
+ Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
+ return GlobSel.getAsString();
+}
+
+/// \brief Get a GlobalSelector for the ASTContext-specific selector.
+GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
+ if (Sel.isNull())
+ return GlobalSelector();
+
+ ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
+
+ llvm::SmallVector<IdentifierInfo *, 8> Ids;
+ for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
+ i != e; ++i) {
+ IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
+ IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
+ Ids.push_back(GlobII);
+ }
+
+ Selector GlobSel = ProgImpl.getSelectors().getSelector(Sel.getNumArgs(),
+ Ids.data());
+ return GlobalSelector(GlobSel.getAsOpaquePtr());
+}
+
+unsigned
+llvm::DenseMapInfo<GlobalSelector>::getHashValue(GlobalSelector Sel) {
+ return DenseMapInfo<void*>::getHashValue(Sel.getAsOpaquePtr());
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/Handlers.cpp b/contrib/llvm/tools/clang/lib/Index/Handlers.cpp
new file mode 100644
index 0000000..1e9a27d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/Handlers.cpp
@@ -0,0 +1,22 @@
+//===--- Handlers.cpp - Interfaces for receiving information ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract interfaces for receiving information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/Handlers.h"
+#include "clang/Index/Entity.h"
+using namespace clang;
+using namespace idx;
+
+// Out-of-line to give the virtual tables a home.
+EntityHandler::~EntityHandler() { }
+TranslationUnitHandler::~TranslationUnitHandler() { }
+TULocationHandler::~TULocationHandler() { }
diff --git a/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp b/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp
new file mode 100644
index 0000000..eea0988
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/IndexProvider.cpp
@@ -0,0 +1,20 @@
+//===- IndexProvider.cpp - Maps information to translation units -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Maps information to TranslationUnits.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/IndexProvider.h"
+#include "clang/Index/Entity.h"
+using namespace clang;
+using namespace idx;
+
+// Out-of-line to give the virtual table a home.
+IndexProvider::~IndexProvider() { }
diff --git a/contrib/llvm/tools/clang/lib/Index/Indexer.cpp b/contrib/llvm/tools/clang/lib/Index/Indexer.cpp
new file mode 100644
index 0000000..7f21c4f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/Indexer.cpp
@@ -0,0 +1,121 @@
+//===--- Indexer.cpp - IndexProvider implementation -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// IndexProvider implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/Indexer.h"
+#include "clang/Index/Program.h"
+#include "clang/Index/Handlers.h"
+#include "clang/Index/TranslationUnit.h"
+#include "ASTVisitor.h"
+#include "clang/AST/DeclBase.h"
+using namespace clang;
+using namespace idx;
+
+namespace {
+
+class EntityIndexer : public EntityHandler {
+ TranslationUnit *TU;
+ Indexer::MapTy &Map;
+ Indexer::DefMapTy &DefMap;
+
+public:
+ EntityIndexer(TranslationUnit *tu, Indexer::MapTy &map,
+ Indexer::DefMapTy &defmap)
+ : TU(tu), Map(map), DefMap(defmap) { }
+
+ virtual void Handle(Entity Ent) {
+ if (Ent.isInternalToTU())
+ return;
+ Map[Ent].insert(TU);
+
+ Decl *D = Ent.getDecl(TU->getASTContext());
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isThisDeclarationADefinition())
+ DefMap[Ent] = std::make_pair(FD, TU);
+ }
+};
+
+class SelectorIndexer : public ASTVisitor<SelectorIndexer> {
+ Program &Prog;
+ TranslationUnit *TU;
+ Indexer::SelMapTy &Map;
+
+public:
+ SelectorIndexer(Program &prog, TranslationUnit *tu, Indexer::SelMapTy &map)
+ : Prog(prog), TU(tu), Map(map) { }
+
+ void VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ Map[GlobalSelector::get(D->getSelector(), Prog)].insert(TU);
+ Base::VisitObjCMethodDecl(D);
+ }
+
+ void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
+ Map[GlobalSelector::get(Node->getSelector(), Prog)].insert(TU);
+ Base::VisitObjCMessageExpr(Node);
+ }
+};
+
+} // anonymous namespace
+
+void Indexer::IndexAST(TranslationUnit *TU) {
+ assert(TU && "Passed null TranslationUnit");
+ ASTContext &Ctx = TU->getASTContext();
+ CtxTUMap[&Ctx] = TU;
+ EntityIndexer Idx(TU, Map, DefMap);
+ Prog.FindEntities(Ctx, Idx);
+
+ SelectorIndexer SelIdx(Prog, TU, SelMap);
+ SelIdx.Visit(Ctx.getTranslationUnitDecl());
+}
+
+void Indexer::GetTranslationUnitsFor(Entity Ent,
+ TranslationUnitHandler &Handler) {
+ assert(Ent.isValid() && "Expected valid Entity");
+
+ if (Ent.isInternalToTU()) {
+ Decl *D = Ent.getInternalDecl();
+ CtxTUMapTy::iterator I = CtxTUMap.find(&D->getASTContext());
+ if (I != CtxTUMap.end())
+ Handler.Handle(I->second);
+ return;
+ }
+
+ MapTy::iterator I = Map.find(Ent);
+ if (I == Map.end())
+ return;
+
+ TUSetTy &Set = I->second;
+ for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
+ Handler.Handle(*I);
+}
+
+void Indexer::GetTranslationUnitsFor(GlobalSelector Sel,
+ TranslationUnitHandler &Handler) {
+ assert(Sel.isValid() && "Expected valid GlobalSelector");
+
+ SelMapTy::iterator I = SelMap.find(Sel);
+ if (I == SelMap.end())
+ return;
+
+ TUSetTy &Set = I->second;
+ for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
+ Handler.Handle(*I);
+}
+
+std::pair<FunctionDecl *, TranslationUnit *>
+Indexer::getDefinitionFor(Entity Ent) {
+ DefMapTy::iterator I = DefMap.find(Ent);
+ if (I == DefMap.end())
+ return std::make_pair((FunctionDecl *)0, (TranslationUnit *)0);
+ else
+ return I->second;
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/Program.cpp b/contrib/llvm/tools/clang/lib/Index/Program.cpp
new file mode 100644
index 0000000..4efad2c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/Program.cpp
@@ -0,0 +1,50 @@
+//===--- Program.cpp - Entity originator and misc -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Storage for Entities and utility functions
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/Program.h"
+#include "ProgramImpl.h"
+#include "clang/Index/Handlers.h"
+#include "clang/Index/TranslationUnit.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+using namespace idx;
+
+// Out-of-line to give the virtual tables a home.
+TranslationUnit::~TranslationUnit() { }
+
+Program::Program() : Impl(new ProgramImpl()) { }
+
+Program::~Program() {
+ delete static_cast<ProgramImpl *>(Impl);
+}
+
+static void FindEntitiesInDC(DeclContext *DC, Program &Prog,
+ EntityHandler &Handler) {
+ for (DeclContext::decl_iterator
+ I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
+ if (I->getLocation().isInvalid())
+ continue;
+ Entity Ent = Entity::get(*I, Prog);
+ if (Ent.isValid())
+ Handler.Handle(Ent);
+ if (DeclContext *SubDC = dyn_cast<DeclContext>(*I))
+ FindEntitiesInDC(SubDC, Prog, Handler);
+ }
+}
+
+/// \brief Traverses the AST and passes all the entities to the Handler.
+void Program::FindEntities(ASTContext &Ctx, EntityHandler &Handler) {
+ FindEntitiesInDC(Ctx.getTranslationUnitDecl(), *this, Handler);
+}
diff --git a/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h b/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h
new file mode 100644
index 0000000..57b9ce3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/ProgramImpl.h
@@ -0,0 +1,56 @@
+//===--- ProgramImpl.h - Internal Program implementation---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal implementation for the Program class
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H
+#define LLVM_CLANG_INDEX_PROGRAMIMPL_H
+
+#include "EntityImpl.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+
+namespace idx {
+ class EntityListener;
+
+class ProgramImpl {
+public:
+ typedef llvm::FoldingSet<EntityImpl> EntitySetTy;
+
+private:
+ EntitySetTy Entities;
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ IdentifierTable Identifiers;
+ SelectorTable Selectors;
+
+ ProgramImpl(const ProgramImpl&); // do not implement
+ ProgramImpl &operator=(const ProgramImpl &); // do not implement
+
+public:
+ ProgramImpl() : Identifiers(LangOptions()) { }
+
+ EntitySetTy &getEntities() { return Entities; }
+ IdentifierTable &getIdents() { return Identifiers; }
+ SelectorTable &getSelectors() { return Selectors; }
+
+ void *Allocate(unsigned Size, unsigned Align = 8) {
+ return BumpAlloc.Allocate(Size, Align);
+ }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp b/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp
new file mode 100644
index 0000000..0f11e31
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Index/SelectorMap.cpp
@@ -0,0 +1,84 @@
+//===- SelectorMap.cpp - Maps selectors to methods and messages -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SelectorMap creates a mapping from selectors to ObjC method declarations
+// and ObjC message expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Index/SelectorMap.h"
+#include "ASTVisitor.h"
+using namespace clang;
+using namespace idx;
+
+namespace {
+
+class SelMapper : public ASTVisitor<SelMapper> {
+ SelectorMap::SelMethMapTy &SelMethMap;
+ SelectorMap::SelRefMapTy &SelRefMap;
+
+public:
+ SelMapper(SelectorMap::SelMethMapTy &MethMap,
+ SelectorMap::SelRefMapTy &RefMap)
+ : SelMethMap(MethMap), SelRefMap(RefMap) { }
+
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCMessageExpr(ObjCMessageExpr *Node);
+ void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+};
+
+} // anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// SelMapper Implementation
+//===----------------------------------------------------------------------===//
+
+void SelMapper::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ if (D->getCanonicalDecl() == D)
+ SelMethMap.insert(std::make_pair(D->getSelector(), D));
+ Base::VisitObjCMethodDecl(D);
+}
+
+void SelMapper::VisitObjCMessageExpr(ObjCMessageExpr *Node) {
+ ASTLocation ASTLoc(CurrentDecl, Node);
+ SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
+}
+
+void SelMapper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+ ASTLocation ASTLoc(CurrentDecl, Node);
+ SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
+}
+
+//===----------------------------------------------------------------------===//
+// SelectorMap Implementation
+//===----------------------------------------------------------------------===//
+
+SelectorMap::SelectorMap(ASTContext &Ctx) {
+ SelMapper(SelMethMap, SelRefMap).Visit(Ctx.getTranslationUnitDecl());
+}
+
+SelectorMap::method_iterator
+SelectorMap::methods_begin(Selector Sel) const {
+ return method_iterator(SelMethMap.lower_bound(Sel));
+}
+
+SelectorMap::method_iterator
+SelectorMap::methods_end(Selector Sel) const {
+ return method_iterator(SelMethMap.upper_bound(Sel));
+}
+
+SelectorMap::astlocation_iterator
+SelectorMap::refs_begin(Selector Sel) const {
+ return astlocation_iterator(SelRefMap.lower_bound(Sel));
+}
+
+SelectorMap::astlocation_iterator
+SelectorMap::refs_end(Selector Sel) const {
+ return astlocation_iterator(SelRefMap.upper_bound(Sel));
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp
new file mode 100644
index 0000000..e424f91
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp
@@ -0,0 +1,228 @@
+//===--- HeaderMap.cpp - A file that acts like dir of symlinks ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the HeaderMap interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/HeaderMap.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cctype>
+#include <cstdio>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Data Structures and Manifest Constants
+//===----------------------------------------------------------------------===//
+
+enum {
+ HMAP_HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p',
+ HMAP_HeaderVersion = 1,
+
+ HMAP_EmptyBucketKey = 0
+};
+
+namespace clang {
+struct HMapBucket {
+ uint32_t Key; // Offset (into strings) of key.
+
+ uint32_t Prefix; // Offset (into strings) of value prefix.
+ uint32_t Suffix; // Offset (into strings) of value suffix.
+};
+
+struct HMapHeader {
+ uint32_t Magic; // Magic word, also indicates byte order.
+ uint16_t Version; // Version number -- currently 1.
+ uint16_t Reserved; // Reserved for future use - zero for now.
+ uint32_t StringsOffset; // Offset to start of string pool.
+ uint32_t NumEntries; // Number of entries in the string table.
+ uint32_t NumBuckets; // Number of buckets (always a power of 2).
+ uint32_t MaxValueLength; // Length of longest result path (excluding nul).
+ // An array of 'NumBuckets' HMapBucket objects follows this header.
+ // Strings follow the buckets, at StringsOffset.
+};
+} // end namespace clang.
+
+/// HashHMapKey - This is the 'well known' hash function required by the file
+/// format, used to look up keys in the hash table. The hash table uses simple
+/// linear probing based on this function.
+static inline unsigned HashHMapKey(llvm::StringRef Str) {
+ unsigned Result = 0;
+ const char *S = Str.begin(), *End = Str.end();
+
+ for (; S != End; S++)
+ Result += tolower(*S) * 13;
+ return Result;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Verification and Construction
+//===----------------------------------------------------------------------===//
+
+/// HeaderMap::Create - This attempts to load the specified file as a header
+/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
+/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
+/// into the string error argument and returns null.
+const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
+ // If the file is too small to be a header map, ignore it.
+ unsigned FileSize = FE->getSize();
+ if (FileSize <= sizeof(HMapHeader)) return 0;
+
+ llvm::OwningPtr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE));
+ if (FileBuffer == 0) return 0; // Unreadable file?
+ const char *FileStart = FileBuffer->getBufferStart();
+
+ // We know the file is at least as big as the header, check it now.
+ const HMapHeader *Header = reinterpret_cast<const HMapHeader*>(FileStart);
+
+ // Sniff it to see if it's a headermap by checking the magic number and
+ // version.
+ bool NeedsByteSwap;
+ if (Header->Magic == HMAP_HeaderMagicNumber &&
+ Header->Version == HMAP_HeaderVersion)
+ NeedsByteSwap = false;
+ else if (Header->Magic == llvm::ByteSwap_32(HMAP_HeaderMagicNumber) &&
+ Header->Version == llvm::ByteSwap_16(HMAP_HeaderVersion))
+ NeedsByteSwap = true; // Mixed endianness headermap.
+ else
+ return 0; // Not a header map.
+
+ if (Header->Reserved != 0) return 0;
+
+ // Okay, everything looks good, create the header map.
+ return new HeaderMap(FileBuffer.take(), NeedsByteSwap);
+}
+
+HeaderMap::~HeaderMap() {
+ delete FileBuffer;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility Methods
+//===----------------------------------------------------------------------===//
+
+
+/// getFileName - Return the filename of the headermap.
+const char *HeaderMap::getFileName() const {
+ return FileBuffer->getBufferIdentifier();
+}
+
+unsigned HeaderMap::getEndianAdjustedWord(unsigned X) const {
+ if (!NeedsBSwap) return X;
+ return llvm::ByteSwap_32(X);
+}
+
+/// getHeader - Return a reference to the file header, in unbyte-swapped form.
+/// This method cannot fail.
+const HMapHeader &HeaderMap::getHeader() const {
+ // We know the file is at least as big as the header. Return it.
+ return *reinterpret_cast<const HMapHeader*>(FileBuffer->getBufferStart());
+}
+
+/// getBucket - Return the specified hash table bucket from the header map,
+/// bswap'ing its fields as appropriate. If the bucket number is not valid,
+/// this return a bucket with an empty key (0).
+HMapBucket HeaderMap::getBucket(unsigned BucketNo) const {
+ HMapBucket Result;
+ Result.Key = HMAP_EmptyBucketKey;
+
+ const HMapBucket *BucketArray =
+ reinterpret_cast<const HMapBucket*>(FileBuffer->getBufferStart() +
+ sizeof(HMapHeader));
+
+ const HMapBucket *BucketPtr = BucketArray+BucketNo;
+ if ((char*)(BucketPtr+1) > FileBuffer->getBufferEnd()) {
+ Result.Prefix = 0;
+ Result.Suffix = 0;
+ return Result; // Invalid buffer, corrupt hmap.
+ }
+
+ // Otherwise, the bucket is valid. Load the values, bswapping as needed.
+ Result.Key = getEndianAdjustedWord(BucketPtr->Key);
+ Result.Prefix = getEndianAdjustedWord(BucketPtr->Prefix);
+ Result.Suffix = getEndianAdjustedWord(BucketPtr->Suffix);
+ return Result;
+}
+
+/// getString - Look up the specified string in the string table. If the string
+/// index is not valid, it returns an empty string.
+const char *HeaderMap::getString(unsigned StrTabIdx) const {
+ // Add the start of the string table to the idx.
+ StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);
+
+ // Check for invalid index.
+ if (StrTabIdx >= FileBuffer->getBufferSize())
+ return 0;
+
+ // Otherwise, we have a valid pointer into the file. Just return it. We know
+ // that the "string" can not overrun the end of the file, because the buffer
+ // is nul terminated by virtue of being a MemoryBuffer.
+ return FileBuffer->getBufferStart()+StrTabIdx;
+}
+
+//===----------------------------------------------------------------------===//
+// The Main Drivers
+//===----------------------------------------------------------------------===//
+
+/// dump - Print the contents of this headermap to stderr.
+void HeaderMap::dump() const {
+ const HMapHeader &Hdr = getHeader();
+ unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
+
+ fprintf(stderr, "Header Map %s:\n %d buckets, %d entries\n",
+ getFileName(), NumBuckets,
+ getEndianAdjustedWord(Hdr.NumEntries));
+
+ for (unsigned i = 0; i != NumBuckets; ++i) {
+ HMapBucket B = getBucket(i);
+ if (B.Key == HMAP_EmptyBucketKey) continue;
+
+ const char *Key = getString(B.Key);
+ const char *Prefix = getString(B.Prefix);
+ const char *Suffix = getString(B.Suffix);
+ fprintf(stderr, " %d. %s -> '%s' '%s'\n", i, Key, Prefix, Suffix);
+ }
+}
+
+/// LookupFile - Check to see if the specified relative filename is located in
+/// this HeaderMap. If so, open it and return its FileEntry.
+const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename,
+ FileManager &FM) const {
+ const HMapHeader &Hdr = getHeader();
+ unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
+
+ // If the number of buckets is not a power of two, the headermap is corrupt.
+ // Don't probe infinitely.
+ if (NumBuckets & (NumBuckets-1))
+ return 0;
+
+ // Linearly probe the hash table.
+ for (unsigned Bucket = HashHMapKey(Filename);; ++Bucket) {
+ HMapBucket B = getBucket(Bucket & (NumBuckets-1));
+ if (B.Key == HMAP_EmptyBucketKey) return 0; // Hash miss.
+
+ // See if the key matches. If not, probe on.
+ if (!Filename.equals_lower(getString(B.Key)))
+ continue;
+
+ // If so, we have a match in the hash table. Construct the destination
+ // path.
+ llvm::SmallString<1024> DestPath;
+ DestPath += getString(B.Prefix);
+ DestPath += getString(B.Suffix);
+ return FM.getFile(DestPath.str());
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
new file mode 100644
index 0000000..b028e33
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
@@ -0,0 +1,448 @@
+//===--- HeaderSearch.cpp - Resolve Header File Locations ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DirectoryLookup and HeaderSearch interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderMap.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/ADT/SmallString.h"
+#include <cstdio>
+using namespace clang;
+
+const IdentifierInfo *
+HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
+ if (ControllingMacro)
+ return ControllingMacro;
+
+ if (!ControllingMacroID || !External)
+ return 0;
+
+ ControllingMacro = External->GetIdentifier(ControllingMacroID);
+ return ControllingMacro;
+}
+
+ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
+
+HeaderSearch::HeaderSearch(FileManager &FM)
+ : FileMgr(FM), FrameworkMap(64) {
+ SystemDirIdx = 0;
+ NoCurDirSearch = false;
+
+ ExternalLookup = 0;
+ ExternalSource = 0;
+ NumIncluded = 0;
+ NumMultiIncludeFileOptzn = 0;
+ NumFrameworkLookups = NumSubFrameworkLookups = 0;
+}
+
+HeaderSearch::~HeaderSearch() {
+ // Delete headermaps.
+ for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
+ delete HeaderMaps[i].second;
+}
+
+void HeaderSearch::PrintStats() {
+ fprintf(stderr, "\n*** HeaderSearch Stats:\n");
+ fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
+ unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0;
+ for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) {
+ NumOnceOnlyFiles += FileInfo[i].isImport;
+ if (MaxNumIncludes < FileInfo[i].NumIncludes)
+ MaxNumIncludes = FileInfo[i].NumIncludes;
+ NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1;
+ }
+ fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles);
+ fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles);
+ fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes);
+
+ fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded);
+ fprintf(stderr, " %d #includes skipped due to"
+ " the multi-include optimization.\n", NumMultiIncludeFileOptzn);
+
+ fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups);
+ fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups);
+}
+
+/// CreateHeaderMap - This method returns a HeaderMap for the specified
+/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
+ // We expect the number of headermaps to be small, and almost always empty.
+ // If it ever grows, use of a linear search should be re-evaluated.
+ if (!HeaderMaps.empty()) {
+ for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
+ // Pointer equality comparison of FileEntries works because they are
+ // already uniqued by inode.
+ if (HeaderMaps[i].first == FE)
+ return HeaderMaps[i].second;
+ }
+
+ if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) {
+ HeaderMaps.push_back(std::make_pair(FE, HM));
+ return HM;
+ }
+
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// File lookup within a DirectoryLookup scope
+//===----------------------------------------------------------------------===//
+
+/// getName - Return the directory or filename corresponding to this lookup
+/// object.
+const char *DirectoryLookup::getName() const {
+ if (isNormalDir())
+ return getDir()->getName();
+ if (isFramework())
+ return getFrameworkDir()->getName();
+ assert(isHeaderMap() && "Unknown DirectoryLookup");
+ return getHeaderMap()->getFileName();
+}
+
+
+/// LookupFile - Lookup the specified file in this search path, returning it
+/// if it exists or returning null if not.
+const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename,
+ HeaderSearch &HS) const {
+ llvm::SmallString<1024> TmpDir;
+ if (isNormalDir()) {
+ // Concatenate the requested file onto the directory.
+ // FIXME: Portability. Filename concatenation should be in sys::Path.
+ TmpDir += getDir()->getName();
+ TmpDir.push_back('/');
+ TmpDir.append(Filename.begin(), Filename.end());
+ return HS.getFileMgr().getFile(TmpDir.str());
+ }
+
+ if (isFramework())
+ return DoFrameworkLookup(Filename, HS);
+
+ assert(isHeaderMap() && "Unknown directory lookup");
+ return getHeaderMap()->LookupFile(Filename, HS.getFileMgr());
+}
+
+
+/// DoFrameworkLookup - Do a lookup of the specified file in the current
+/// DirectoryLookup, which is a framework directory.
+const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
+ HeaderSearch &HS) const {
+ FileManager &FileMgr = HS.getFileMgr();
+
+ // Framework names must have a '/' in the filename.
+ size_t SlashPos = Filename.find('/');
+ if (SlashPos == llvm::StringRef::npos) return 0;
+
+ // Find out if this is the home for the specified framework, by checking
+ // HeaderSearch. Possible answer are yes/no and unknown.
+ const DirectoryEntry *&FrameworkDirCache =
+ HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
+
+ // If it is known and in some other directory, fail.
+ if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir())
+ return 0;
+
+ // Otherwise, construct the path to this framework dir.
+
+ // FrameworkName = "/System/Library/Frameworks/"
+ llvm::SmallString<1024> FrameworkName;
+ FrameworkName += getFrameworkDir()->getName();
+ if (FrameworkName.empty() || FrameworkName.back() != '/')
+ FrameworkName.push_back('/');
+
+ // FrameworkName = "/System/Library/Frameworks/Cocoa"
+ FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
+
+ // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
+ FrameworkName += ".framework/";
+
+ // If the cache entry is still unresolved, query to see if the cache entry is
+ // still unresolved. If so, check its existence now.
+ if (FrameworkDirCache == 0) {
+ HS.IncrementFrameworkLookupCount();
+
+ // If the framework dir doesn't exist, we fail.
+ // FIXME: It's probably more efficient to query this with FileMgr.getDir.
+ bool Exists;
+ if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists)
+ return 0;
+
+ // Otherwise, if it does, remember that this is the right direntry for this
+ // framework.
+ FrameworkDirCache = getFrameworkDir();
+ }
+
+ // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
+ unsigned OrigSize = FrameworkName.size();
+
+ FrameworkName += "Headers/";
+ FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
+ if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str()))
+ return FE;
+
+ // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
+ const char *Private = "Private";
+ FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
+ Private+strlen(Private));
+ return FileMgr.getFile(FrameworkName.str());
+}
+
+
+//===----------------------------------------------------------------------===//
+// Header File Location.
+//===----------------------------------------------------------------------===//
+
+
+/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+/// return null on failure. isAngled indicates whether the file reference is
+/// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if
+/// non-null, indicates where the #including file is, in case a relative search
+/// is needed.
+const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename,
+ bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir,
+ const FileEntry *CurFileEnt) {
+ // If 'Filename' is absolute, check to see if it exists and no searching.
+ if (llvm::sys::path::is_absolute(Filename)) {
+ CurDir = 0;
+
+ // If this was an #include_next "/absolute/file", fail.
+ if (FromDir) return 0;
+
+ // Otherwise, just return the file.
+ return FileMgr.getFile(Filename);
+ }
+
+ // Step #0, unless disabled, check to see if the file is in the #includer's
+ // directory. This has to be based on CurFileEnt, not CurDir, because
+ // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and
+ // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
+ // This search is not done for <> headers.
+ if (CurFileEnt && !isAngled && !NoCurDirSearch) {
+ llvm::SmallString<1024> TmpDir;
+ // Concatenate the requested file onto the directory.
+ // FIXME: Portability. Filename concatenation should be in sys::Path.
+ TmpDir += CurFileEnt->getDir()->getName();
+ TmpDir.push_back('/');
+ TmpDir.append(Filename.begin(), Filename.end());
+ if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) {
+ // Leave CurDir unset.
+ // This file is a system header or C++ unfriendly if the old file is.
+ //
+ // Note that the temporary 'DirInfo' is required here, as either call to
+ // getFileInfo could resize the vector and we don't want to rely on order
+ // of evaluation.
+ unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo;
+ getFileInfo(FE).DirInfo = DirInfo;
+ return FE;
+ }
+ }
+
+ CurDir = 0;
+
+ // If this is a system #include, ignore the user #include locs.
+ unsigned i = isAngled ? SystemDirIdx : 0;
+
+ // If this is a #include_next request, start searching after the directory the
+ // file was found in.
+ if (FromDir)
+ i = FromDir-&SearchDirs[0];
+
+ // Cache all of the lookups performed by this method. Many headers are
+ // multiply included, and the "pragma once" optimization prevents them from
+ // being relex/pp'd, but they would still have to search through a
+ // (potentially huge) series of SearchDirs to find it.
+ std::pair<unsigned, unsigned> &CacheLookup =
+ LookupFileCache.GetOrCreateValue(Filename).getValue();
+
+ // If the entry has been previously looked up, the first value will be
+ // non-zero. If the value is equal to i (the start point of our search), then
+ // this is a matching hit.
+ if (CacheLookup.first == i+1) {
+ // Skip querying potentially lots of directories for this lookup.
+ i = CacheLookup.second;
+ } else {
+ // Otherwise, this is the first query, or the previous query didn't match
+ // our search start. We will fill in our found location below, so prime the
+ // start point value.
+ CacheLookup.first = i+1;
+ }
+
+ // Check each directory in sequence to see if it contains this file.
+ for (; i != SearchDirs.size(); ++i) {
+ const FileEntry *FE =
+ SearchDirs[i].LookupFile(Filename, *this);
+ if (!FE) continue;
+
+ CurDir = &SearchDirs[i];
+
+ // This file is a system header or C++ unfriendly if the dir is.
+ getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic();
+
+ // Remember this location for the next lookup we do.
+ CacheLookup.second = i;
+ return FE;
+ }
+
+ // Otherwise, didn't find it. Remember we didn't find this.
+ CacheLookup.second = SearchDirs.size();
+ return 0;
+}
+
+/// LookupSubframeworkHeader - Look up a subframework for the specified
+/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
+/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
+/// is a subframework within Carbon.framework. If so, return the FileEntry
+/// for the designated file, otherwise return null.
+const FileEntry *HeaderSearch::
+LookupSubframeworkHeader(llvm::StringRef Filename,
+ const FileEntry *ContextFileEnt) {
+ assert(ContextFileEnt && "No context file?");
+
+ // Framework names must have a '/' in the filename. Find it.
+ size_t SlashPos = Filename.find('/');
+ if (SlashPos == llvm::StringRef::npos) return 0;
+
+ // Look up the base framework name of the ContextFileEnt.
+ const char *ContextName = ContextFileEnt->getName();
+
+ // If the context info wasn't a framework, couldn't be a subframework.
+ const char *FrameworkPos = strstr(ContextName, ".framework/");
+ if (FrameworkPos == 0)
+ return 0;
+
+ llvm::SmallString<1024> FrameworkName(ContextName,
+ FrameworkPos+strlen(".framework/"));
+
+ // Append Frameworks/HIToolbox.framework/
+ FrameworkName += "Frameworks/";
+ FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
+ FrameworkName += ".framework/";
+
+ llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup =
+ FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos));
+
+ // Some other location?
+ if (CacheLookup.getValue() &&
+ CacheLookup.getKeyLength() == FrameworkName.size() &&
+ memcmp(CacheLookup.getKeyData(), &FrameworkName[0],
+ CacheLookup.getKeyLength()) != 0)
+ return 0;
+
+ // Cache subframework.
+ if (CacheLookup.getValue() == 0) {
+ ++NumSubFrameworkLookups;
+
+ // If the framework dir doesn't exist, we fail.
+ const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
+ if (Dir == 0) return 0;
+
+ // Otherwise, if it does, remember that this is the right direntry for this
+ // framework.
+ CacheLookup.setValue(Dir);
+ }
+
+ const FileEntry *FE = 0;
+
+ // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
+ llvm::SmallString<1024> HeadersFilename(FrameworkName);
+ HeadersFilename += "Headers/";
+ HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
+ if (!(FE = FileMgr.getFile(HeadersFilename.str()))) {
+
+ // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
+ HeadersFilename = FrameworkName;
+ HeadersFilename += "PrivateHeaders/";
+ HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
+ if (!(FE = FileMgr.getFile(HeadersFilename.str())))
+ return 0;
+ }
+
+ // This file is a system header or C++ unfriendly if the old file is.
+ //
+ // Note that the temporary 'DirInfo' is required here, as either call to
+ // getFileInfo could resize the vector and we don't want to rely on order
+ // of evaluation.
+ unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
+ getFileInfo(FE).DirInfo = DirInfo;
+ return FE;
+}
+
+//===----------------------------------------------------------------------===//
+// File Info Management.
+//===----------------------------------------------------------------------===//
+
+
+/// getFileInfo - Return the HeaderFileInfo structure for the specified
+/// FileEntry.
+HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
+ if (FE->getUID() >= FileInfo.size())
+ FileInfo.resize(FE->getUID()+1);
+
+ HeaderFileInfo &HFI = FileInfo[FE->getUID()];
+ if (ExternalSource && !HFI.Resolved) {
+ HFI = ExternalSource->GetHeaderFileInfo(FE);
+ HFI.Resolved = true;
+ }
+ return HFI;
+}
+
+void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) {
+ if (UID >= FileInfo.size())
+ FileInfo.resize(UID+1);
+ HFI.Resolved = true;
+ FileInfo[UID] = HFI;
+}
+
+/// ShouldEnterIncludeFile - Mark the specified file as a target of of a
+/// #include, #include_next, or #import directive. Return false if #including
+/// the file will have no effect or true if we should include it.
+bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
+ ++NumIncluded; // Count # of attempted #includes.
+
+ // Get information about this file.
+ HeaderFileInfo &FileInfo = getFileInfo(File);
+
+ // If this is a #import directive, check that we have not already imported
+ // this header.
+ if (isImport) {
+ // If this has already been imported, don't import it again.
+ FileInfo.isImport = true;
+
+ // Has this already been #import'ed or #include'd?
+ if (FileInfo.NumIncludes) return false;
+ } else {
+ // Otherwise, if this is a #include of a file that was previously #import'd
+ // or if this is the second #include of a #pragma once file, ignore it.
+ if (FileInfo.isImport)
+ return false;
+ }
+
+ // Next, check to see if the file is wrapped with #ifndef guards. If so, and
+ // if the macro that guards it is defined, we know the #include has no effect.
+ if (const IdentifierInfo *ControllingMacro
+ = FileInfo.getControllingMacro(ExternalLookup))
+ if (ControllingMacro->hasMacroDefinition()) {
+ ++NumMultiIncludeFileOptzn;
+ return false;
+ }
+
+ // Increment the number of times this file has been included.
+ ++FileInfo.NumIncludes;
+
+ return true;
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
new file mode 100644
index 0000000..b17198b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
@@ -0,0 +1,2489 @@
+//===--- Lexer.cpp - C Language Family Lexer ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Lexer and Token interfaces.
+//
+//===----------------------------------------------------------------------===//
+//
+// TODO: GCC Diagnostics emitted by the lexer:
+// PEDWARN: (form feed|vertical tab) in preprocessing directive
+//
+// Universal characters, unicode, char mapping:
+// WARNING: `%.*s' is not in NFKC
+// WARNING: `%.*s' is not in NFC
+//
+// Other:
+// TODO: Options to support:
+// -fexec-charset,-fwide-exec-charset
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cctype>
+using namespace clang;
+
+static void InitCharacterInfo();
+
+//===----------------------------------------------------------------------===//
+// Token Class Implementation
+//===----------------------------------------------------------------------===//
+
+/// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
+bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const {
+ if (IdentifierInfo *II = getIdentifierInfo())
+ return II->getObjCKeywordID() == objcKey;
+ return false;
+}
+
+/// getObjCKeywordID - Return the ObjC keyword kind.
+tok::ObjCKeywordKind Token::getObjCKeywordID() const {
+ IdentifierInfo *specId = getIdentifierInfo();
+ return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Lexer Class Implementation
+//===----------------------------------------------------------------------===//
+
+void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
+ const char *BufEnd) {
+ InitCharacterInfo();
+
+ BufferStart = BufStart;
+ BufferPtr = BufPtr;
+ BufferEnd = BufEnd;
+
+ assert(BufEnd[0] == 0 &&
+ "We assume that the input buffer has a null character at the end"
+ " to simplify lexing!");
+
+ Is_PragmaLexer = false;
+ IsInConflictMarker = false;
+
+ // Start of the file is a start of line.
+ IsAtStartOfLine = true;
+
+ // We are not after parsing a #.
+ ParsingPreprocessorDirective = false;
+
+ // We are not after parsing #include.
+ ParsingFilename = false;
+
+ // We are not in raw mode. Raw mode disables diagnostics and interpretation
+ // of tokens (e.g. identifiers, thus disabling macro expansion). It is used
+ // to quickly lex the tokens of the buffer, e.g. when handling a "#if 0" block
+ // or otherwise skipping over tokens.
+ LexingRawMode = false;
+
+ // Default to not keeping comments.
+ ExtendedTokenMode = 0;
+}
+
+/// Lexer constructor - Create a new lexer object for the specified buffer
+/// with the specified preprocessor managing the lexing process. This lexer
+/// assumes that the associated file buffer and Preprocessor objects will
+/// outlive it, so it doesn't take ownership of either of them.
+Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP)
+ : PreprocessorLexer(&PP, FID),
+ FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)),
+ Features(PP.getLangOptions()) {
+
+ InitLexer(InputFile->getBufferStart(), InputFile->getBufferStart(),
+ InputFile->getBufferEnd());
+
+ // Default to keeping comments if the preprocessor wants them.
+ SetCommentRetentionState(PP.getCommentRetentionState());
+}
+
+/// Lexer constructor - Create a new raw lexer object. This object is only
+/// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+/// range will outlive it, so it doesn't take ownership of it.
+Lexer::Lexer(SourceLocation fileloc, const LangOptions &features,
+ const char *BufStart, const char *BufPtr, const char *BufEnd)
+ : FileLoc(fileloc), Features(features) {
+
+ InitLexer(BufStart, BufPtr, BufEnd);
+
+ // We *are* in raw mode.
+ LexingRawMode = true;
+}
+
+/// Lexer constructor - Create a new raw lexer object. This object is only
+/// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+/// range will outlive it, so it doesn't take ownership of it.
+Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
+ const SourceManager &SM, const LangOptions &features)
+ : FileLoc(SM.getLocForStartOfFile(FID)), Features(features) {
+
+ InitLexer(FromFile->getBufferStart(), FromFile->getBufferStart(),
+ FromFile->getBufferEnd());
+
+ // We *are* in raw mode.
+ LexingRawMode = true;
+}
+
+/// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
+/// _Pragma expansion. This has a variety of magic semantics that this method
+/// sets up. It returns a new'd Lexer that must be delete'd when done.
+///
+/// On entrance to this routine, TokStartLoc is a macro location which has a
+/// spelling loc that indicates the bytes to be lexed for the token and an
+/// instantiation location that indicates where all lexed tokens should be
+/// "expanded from".
+///
+/// FIXME: It would really be nice to make _Pragma just be a wrapper around a
+/// normal lexer that remaps tokens as they fly by. This would require making
+/// Preprocessor::Lex virtual. Given that, we could just dump in a magic lexer
+/// interface that could handle this stuff. This would pull GetMappedTokenLoc
+/// out of the critical path of the lexer!
+///
+Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc,
+ SourceLocation InstantiationLocStart,
+ SourceLocation InstantiationLocEnd,
+ unsigned TokLen, Preprocessor &PP) {
+ SourceManager &SM = PP.getSourceManager();
+
+ // Create the lexer as if we were going to lex the file normally.
+ FileID SpellingFID = SM.getFileID(SpellingLoc);
+ const llvm::MemoryBuffer *InputFile = SM.getBuffer(SpellingFID);
+ Lexer *L = new Lexer(SpellingFID, InputFile, PP);
+
+ // Now that the lexer is created, change the start/end locations so that we
+ // just lex the subsection of the file that we want. This is lexing from a
+ // scratch buffer.
+ const char *StrData = SM.getCharacterData(SpellingLoc);
+
+ L->BufferPtr = StrData;
+ L->BufferEnd = StrData+TokLen;
+ assert(L->BufferEnd[0] == 0 && "Buffer is not nul terminated!");
+
+ // Set the SourceLocation with the remapping information. This ensures that
+ // GetMappedTokenLoc will remap the tokens as they are lexed.
+ L->FileLoc = SM.createInstantiationLoc(SM.getLocForStartOfFile(SpellingFID),
+ InstantiationLocStart,
+ InstantiationLocEnd, TokLen);
+
+ // Ensure that the lexer thinks it is inside a directive, so that end \n will
+ // return an EOM token.
+ L->ParsingPreprocessorDirective = true;
+
+ // This lexer really is for _Pragma.
+ L->Is_PragmaLexer = true;
+ return L;
+}
+
+
+/// Stringify - Convert the specified string into a C string, with surrounding
+/// ""'s, and with escaped \ and " characters.
+std::string Lexer::Stringify(const std::string &Str, bool Charify) {
+ std::string Result = Str;
+ char Quote = Charify ? '\'' : '"';
+ for (unsigned i = 0, e = Result.size(); i != e; ++i) {
+ if (Result[i] == '\\' || Result[i] == Quote) {
+ Result.insert(Result.begin()+i, '\\');
+ ++i; ++e;
+ }
+ }
+ return Result;
+}
+
+/// Stringify - Convert the specified string into a C string by escaping '\'
+/// and " characters. This does not add surrounding ""'s to the string.
+void Lexer::Stringify(llvm::SmallVectorImpl<char> &Str) {
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (Str[i] == '\\' || Str[i] == '"') {
+ Str.insert(Str.begin()+i, '\\');
+ ++i; ++e;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Token Spelling
+//===----------------------------------------------------------------------===//
+
+/// getSpelling() - Return the 'spelling' of this token. The spelling of a
+/// token are the characters used to represent the token in the source file
+/// after trigraph expansion and escaped-newline folding. In particular, this
+/// wants to get the true, uncanonicalized, spelling of things like digraphs
+/// UCNs, etc.
+std::string Lexer::getSpelling(const Token &Tok, const SourceManager &SourceMgr,
+ const LangOptions &Features, bool *Invalid) {
+ assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
+
+ // If this token contains nothing interesting, return it directly.
+ bool CharDataInvalid = false;
+ const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation(),
+ &CharDataInvalid);
+ if (Invalid)
+ *Invalid = CharDataInvalid;
+ if (CharDataInvalid)
+ return std::string();
+
+ if (!Tok.needsCleaning())
+ return std::string(TokStart, TokStart+Tok.getLength());
+
+ std::string Result;
+ Result.reserve(Tok.getLength());
+
+ // Otherwise, hard case, relex the characters into the string.
+ for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength();
+ Ptr != End; ) {
+ unsigned CharSize;
+ Result.push_back(Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features));
+ Ptr += CharSize;
+ }
+ assert(Result.size() != unsigned(Tok.getLength()) &&
+ "NeedsCleaning flag set on something that didn't need cleaning!");
+ return Result;
+}
+
+/// getSpelling - This method is used to get the spelling of a token into a
+/// preallocated buffer, instead of as an std::string. The caller is required
+/// to allocate enough space for the token, which is guaranteed to be at least
+/// Tok.getLength() bytes long. The actual length of the token is returned.
+///
+/// Note that this method may do two possible things: it may either fill in
+/// the buffer specified with characters, or it may *change the input pointer*
+/// to point to a constant buffer with the data already in it (avoiding a
+/// copy). The caller is not allowed to modify the returned buffer pointer
+/// if an internal buffer is returned.
+unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
+ const SourceManager &SourceMgr,
+ const LangOptions &Features, bool *Invalid) {
+ assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
+
+ const char *TokStart = 0;
+ // NOTE: this has to be checked *before* testing for an IdentifierInfo.
+ if (Tok.is(tok::raw_identifier))
+ TokStart = Tok.getRawIdentifierData();
+ else if (const IdentifierInfo *II = Tok.getIdentifierInfo()) {
+ // Just return the string from the identifier table, which is very quick.
+ Buffer = II->getNameStart();
+ return II->getLength();
+ }
+
+ // NOTE: this can be checked even after testing for an IdentifierInfo.
+ if (Tok.isLiteral())
+ TokStart = Tok.getLiteralData();
+
+ if (TokStart == 0) {
+ // Compute the start of the token in the input lexer buffer.
+ bool CharDataInvalid = false;
+ TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid);
+ if (Invalid)
+ *Invalid = CharDataInvalid;
+ if (CharDataInvalid) {
+ Buffer = "";
+ return 0;
+ }
+ }
+
+ // If this token contains nothing interesting, return it directly.
+ if (!Tok.needsCleaning()) {
+ Buffer = TokStart;
+ return Tok.getLength();
+ }
+
+ // Otherwise, hard case, relex the characters into the string.
+ char *OutBuf = const_cast<char*>(Buffer);
+ for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength();
+ Ptr != End; ) {
+ unsigned CharSize;
+ *OutBuf++ = Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features);
+ Ptr += CharSize;
+ }
+ assert(unsigned(OutBuf-Buffer) != Tok.getLength() &&
+ "NeedsCleaning flag set on something that didn't need cleaning!");
+
+ return OutBuf-Buffer;
+}
+
+
+
+static bool isWhitespace(unsigned char c);
+
+/// MeasureTokenLength - Relex the token at the specified location and return
+/// its length in bytes in the input file. If the token needs cleaning (e.g.
+/// includes a trigraph or an escaped newline) then this count includes bytes
+/// that are part of that.
+unsigned Lexer::MeasureTokenLength(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ // TODO: this could be special cased for common tokens like identifiers, ')',
+ // etc to make this faster, if it mattered. Just look at StrData[0] to handle
+ // all obviously single-char tokens. This could use
+ // Lexer::isObviouslySimpleCharacter for example to handle identifiers or
+ // something.
+
+ // If this comes from a macro expansion, we really do want the macro name, not
+ // the token this macro expanded to.
+ Loc = SM.getInstantiationLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ bool Invalid = false;
+ llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return 0;
+
+ const char *StrData = Buffer.data()+LocInfo.second;
+
+ if (isWhitespace(StrData[0]))
+ return 0;
+
+ // Create a lexer starting at the beginning of this token.
+ Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
+ Buffer.begin(), StrData, Buffer.end());
+ TheLexer.SetCommentRetentionState(true);
+ Token TheTok;
+ TheLexer.LexFromRawLexer(TheTok);
+ return TheTok.getLength();
+}
+
+SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (LocInfo.first.isInvalid())
+ return Loc;
+
+ bool Invalid = false;
+ llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return Loc;
+
+ // Back up from the current location until we hit the beginning of a line
+ // (or the buffer). We'll relex from that point.
+ const char *BufStart = Buffer.data();
+ if (LocInfo.second >= Buffer.size())
+ return Loc;
+
+ const char *StrData = BufStart+LocInfo.second;
+ if (StrData[0] == '\n' || StrData[0] == '\r')
+ return Loc;
+
+ const char *LexStart = StrData;
+ while (LexStart != BufStart) {
+ if (LexStart[0] == '\n' || LexStart[0] == '\r') {
+ ++LexStart;
+ break;
+ }
+
+ --LexStart;
+ }
+
+ // Create a lexer starting at the beginning of this token.
+ SourceLocation LexerStartLoc = Loc.getFileLocWithOffset(-LocInfo.second);
+ Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end());
+ TheLexer.SetCommentRetentionState(true);
+
+ // Lex tokens until we find the token that contains the source location.
+ Token TheTok;
+ do {
+ TheLexer.LexFromRawLexer(TheTok);
+
+ if (TheLexer.getBufferLocation() > StrData) {
+ // Lexing this token has taken the lexer past the source location we're
+ // looking for. If the current token encompasses our source location,
+ // return the beginning of that token.
+ if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
+ return TheTok.getLocation();
+
+ // We ended up skipping over the source location entirely, which means
+ // that it points into whitespace. We're done here.
+ break;
+ }
+ } while (TheTok.getKind() != tok::eof);
+
+ // We've passed our source location; just return the original source location.
+ return Loc;
+}
+
+namespace {
+ enum PreambleDirectiveKind {
+ PDK_Skipped,
+ PDK_StartIf,
+ PDK_EndIf,
+ PDK_Unknown
+ };
+}
+
+std::pair<unsigned, bool>
+Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines) {
+ // Create a lexer starting at the beginning of the file. Note that we use a
+ // "fake" file source location at offset 1 so that the lexer will track our
+ // position within the file.
+ const unsigned StartOffset = 1;
+ SourceLocation StartLoc = SourceLocation::getFromRawEncoding(StartOffset);
+ LangOptions LangOpts;
+ Lexer TheLexer(StartLoc, LangOpts, Buffer->getBufferStart(),
+ Buffer->getBufferStart(), Buffer->getBufferEnd());
+
+ bool InPreprocessorDirective = false;
+ Token TheTok;
+ Token IfStartTok;
+ unsigned IfCount = 0;
+ unsigned Line = 0;
+
+ do {
+ TheLexer.LexFromRawLexer(TheTok);
+
+ if (InPreprocessorDirective) {
+ // If we've hit the end of the file, we're done.
+ if (TheTok.getKind() == tok::eof) {
+ InPreprocessorDirective = false;
+ break;
+ }
+
+ // If we haven't hit the end of the preprocessor directive, skip this
+ // token.
+ if (!TheTok.isAtStartOfLine())
+ continue;
+
+ // We've passed the end of the preprocessor directive, and will look
+ // at this token again below.
+ InPreprocessorDirective = false;
+ }
+
+ // Keep track of the # of lines in the preamble.
+ if (TheTok.isAtStartOfLine()) {
+ ++Line;
+
+ // If we were asked to limit the number of lines in the preamble,
+ // and we're about to exceed that limit, we're done.
+ if (MaxLines && Line >= MaxLines)
+ break;
+ }
+
+ // Comments are okay; skip over them.
+ if (TheTok.getKind() == tok::comment)
+ continue;
+
+ if (TheTok.isAtStartOfLine() && TheTok.getKind() == tok::hash) {
+ // This is the start of a preprocessor directive.
+ Token HashTok = TheTok;
+ InPreprocessorDirective = true;
+
+ // Figure out which direective this is. Since we're lexing raw tokens,
+ // we don't have an identifier table available. Instead, just look at
+ // the raw identifier to recognize and categorize preprocessor directives.
+ TheLexer.LexFromRawLexer(TheTok);
+ if (TheTok.getKind() == tok::raw_identifier && !TheTok.needsCleaning()) {
+ llvm::StringRef Keyword(TheTok.getRawIdentifierData(),
+ TheTok.getLength());
+ PreambleDirectiveKind PDK
+ = llvm::StringSwitch<PreambleDirectiveKind>(Keyword)
+ .Case("include", PDK_Skipped)
+ .Case("__include_macros", PDK_Skipped)
+ .Case("define", PDK_Skipped)
+ .Case("undef", PDK_Skipped)
+ .Case("line", PDK_Skipped)
+ .Case("error", PDK_Skipped)
+ .Case("pragma", PDK_Skipped)
+ .Case("import", PDK_Skipped)
+ .Case("include_next", PDK_Skipped)
+ .Case("warning", PDK_Skipped)
+ .Case("ident", PDK_Skipped)
+ .Case("sccs", PDK_Skipped)
+ .Case("assert", PDK_Skipped)
+ .Case("unassert", PDK_Skipped)
+ .Case("if", PDK_StartIf)
+ .Case("ifdef", PDK_StartIf)
+ .Case("ifndef", PDK_StartIf)
+ .Case("elif", PDK_Skipped)
+ .Case("else", PDK_Skipped)
+ .Case("endif", PDK_EndIf)
+ .Default(PDK_Unknown);
+
+ switch (PDK) {
+ case PDK_Skipped:
+ continue;
+
+ case PDK_StartIf:
+ if (IfCount == 0)
+ IfStartTok = HashTok;
+
+ ++IfCount;
+ continue;
+
+ case PDK_EndIf:
+ // Mismatched #endif. The preamble ends here.
+ if (IfCount == 0)
+ break;
+
+ --IfCount;
+ continue;
+
+ case PDK_Unknown:
+ // We don't know what this directive is; stop at the '#'.
+ break;
+ }
+ }
+
+ // We only end up here if we didn't recognize the preprocessor
+ // directive or it was one that can't occur in the preamble at this
+ // point. Roll back the current token to the location of the '#'.
+ InPreprocessorDirective = false;
+ TheTok = HashTok;
+ }
+
+ // We hit a token that we don't recognize as being in the
+ // "preprocessing only" part of the file, so we're no longer in
+ // the preamble.
+ break;
+ } while (true);
+
+ SourceLocation End = IfCount? IfStartTok.getLocation() : TheTok.getLocation();
+ return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(),
+ IfCount? IfStartTok.isAtStartOfLine()
+ : TheTok.isAtStartOfLine());
+}
+
+
+/// AdvanceToTokenCharacter - Given a location that specifies the start of a
+/// token, return a new location that specifies a character within the token.
+SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned CharNo,
+ const SourceManager &SM,
+ const LangOptions &Features) {
+ // Figure out how many physical characters away the specified instantiation
+ // character is. This needs to take into consideration newlines and
+ // trigraphs.
+ bool Invalid = false;
+ const char *TokPtr = SM.getCharacterData(TokStart, &Invalid);
+
+ // If they request the first char of the token, we're trivially done.
+ if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
+ return TokStart;
+
+ unsigned PhysOffset = 0;
+
+ // The usual case is that tokens don't contain anything interesting. Skip
+ // over the uninteresting characters. If a token only consists of simple
+ // chars, this method is extremely fast.
+ while (Lexer::isObviouslySimpleCharacter(*TokPtr)) {
+ if (CharNo == 0)
+ return TokStart.getFileLocWithOffset(PhysOffset);
+ ++TokPtr, --CharNo, ++PhysOffset;
+ }
+
+ // If we have a character that may be a trigraph or escaped newline, use a
+ // lexer to parse it correctly.
+ for (; CharNo; --CharNo) {
+ unsigned Size;
+ Lexer::getCharAndSizeNoWarn(TokPtr, Size, Features);
+ TokPtr += Size;
+ PhysOffset += Size;
+ }
+
+ // Final detail: if we end up on an escaped newline, we want to return the
+ // location of the actual byte of the token. For example foo\<newline>bar
+ // advanced by 3 should return the location of b, not of \\. One compounding
+ // detail of this is that the escape may be made by a trigraph.
+ if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
+ PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
+
+ return TokStart.getFileLocWithOffset(PhysOffset);
+}
+
+/// \brief Computes the source location just past the end of the
+/// token at this source location.
+///
+/// This routine can be used to produce a source location that
+/// points just past the end of the token referenced by \p Loc, and
+/// is generally used when a diagnostic needs to point just after a
+/// token where it expected something different that it received. If
+/// the returned source location would not be meaningful (e.g., if
+/// it points into a macro), this routine returns an invalid
+/// source location.
+///
+/// \param Offset an offset from the end of the token, where the source
+/// location should refer to. The default offset (0) produces a source
+/// location pointing just past the end of the token; an offset of 1 produces
+/// a source location pointing to the last character in the token, etc.
+SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
+ const SourceManager &SM,
+ const LangOptions &Features) {
+ if (Loc.isInvalid() || !Loc.isFileID())
+ return SourceLocation();
+
+ unsigned Len = Lexer::MeasureTokenLength(Loc, SM, Features);
+ if (Len > Offset)
+ Len = Len - Offset;
+ else
+ return Loc;
+
+ return AdvanceToTokenCharacter(Loc, Len, SM, Features);
+}
+
+//===----------------------------------------------------------------------===//
+// Character information.
+//===----------------------------------------------------------------------===//
+
+enum {
+ CHAR_HORZ_WS = 0x01, // ' ', '\t', '\f', '\v'. Note, no '\0'
+ CHAR_VERT_WS = 0x02, // '\r', '\n'
+ CHAR_LETTER = 0x04, // a-z,A-Z
+ CHAR_NUMBER = 0x08, // 0-9
+ CHAR_UNDER = 0x10, // _
+ CHAR_PERIOD = 0x20 // .
+};
+
+// Statically initialize CharInfo table based on ASCII character set
+// Reference: FreeBSD 7.2 /usr/share/misc/ascii
+static const unsigned char CharInfo[256] =
+{
+// 0 NUL 1 SOH 2 STX 3 ETX
+// 4 EOT 5 ENQ 6 ACK 7 BEL
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+// 8 BS 9 HT 10 NL 11 VT
+//12 NP 13 CR 14 SO 15 SI
+ 0 , CHAR_HORZ_WS, CHAR_VERT_WS, CHAR_HORZ_WS,
+ CHAR_HORZ_WS, CHAR_VERT_WS, 0 , 0 ,
+//16 DLE 17 DC1 18 DC2 19 DC3
+//20 DC4 21 NAK 22 SYN 23 ETB
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+//24 CAN 25 EM 26 SUB 27 ESC
+//28 FS 29 GS 30 RS 31 US
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+//32 SP 33 ! 34 " 35 #
+//36 $ 37 % 38 & 39 '
+ CHAR_HORZ_WS, 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+//40 ( 41 ) 42 * 43 +
+//44 , 45 - 46 . 47 /
+ 0 , 0 , 0 , 0 ,
+ 0 , 0 , CHAR_PERIOD , 0 ,
+//48 0 49 1 50 2 51 3
+//52 4 53 5 54 6 55 7
+ CHAR_NUMBER , CHAR_NUMBER , CHAR_NUMBER , CHAR_NUMBER ,
+ CHAR_NUMBER , CHAR_NUMBER , CHAR_NUMBER , CHAR_NUMBER ,
+//56 8 57 9 58 : 59 ;
+//60 < 61 = 62 > 63 ?
+ CHAR_NUMBER , CHAR_NUMBER , 0 , 0 ,
+ 0 , 0 , 0 , 0 ,
+//64 @ 65 A 66 B 67 C
+//68 D 69 E 70 F 71 G
+ 0 , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//72 H 73 I 74 J 75 K
+//76 L 77 M 78 N 79 O
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//80 P 81 Q 82 R 83 S
+//84 T 85 U 86 V 87 W
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//88 X 89 Y 90 Z 91 [
+//92 \ 93 ] 94 ^ 95 _
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , 0 ,
+ 0 , 0 , 0 , CHAR_UNDER ,
+//96 ` 97 a 98 b 99 c
+//100 d 101 e 102 f 103 g
+ 0 , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//104 h 105 i 106 j 107 k
+//108 l 109 m 110 n 111 o
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//112 p 113 q 114 r 115 s
+//116 t 117 u 118 v 119 w
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , CHAR_LETTER ,
+//120 x 121 y 122 z 123 {
+//124 | 125 } 126 ~ 127 DEL
+ CHAR_LETTER , CHAR_LETTER , CHAR_LETTER , 0 ,
+ 0 , 0 , 0 , 0
+};
+
+static void InitCharacterInfo() {
+ static bool isInited = false;
+ if (isInited) return;
+ // check the statically-initialized CharInfo table
+ assert(CHAR_HORZ_WS == CharInfo[(int)' ']);
+ assert(CHAR_HORZ_WS == CharInfo[(int)'\t']);
+ assert(CHAR_HORZ_WS == CharInfo[(int)'\f']);
+ assert(CHAR_HORZ_WS == CharInfo[(int)'\v']);
+ assert(CHAR_VERT_WS == CharInfo[(int)'\n']);
+ assert(CHAR_VERT_WS == CharInfo[(int)'\r']);
+ assert(CHAR_UNDER == CharInfo[(int)'_']);
+ assert(CHAR_PERIOD == CharInfo[(int)'.']);
+ for (unsigned i = 'a'; i <= 'z'; ++i) {
+ assert(CHAR_LETTER == CharInfo[i]);
+ assert(CHAR_LETTER == CharInfo[i+'A'-'a']);
+ }
+ for (unsigned i = '0'; i <= '9'; ++i)
+ assert(CHAR_NUMBER == CharInfo[i]);
+
+ isInited = true;
+}
+
+
+/// isIdentifierBody - Return true if this is the body character of an
+/// identifier, which is [a-zA-Z0-9_].
+static inline bool isIdentifierBody(unsigned char c) {
+ return (CharInfo[c] & (CHAR_LETTER|CHAR_NUMBER|CHAR_UNDER)) ? true : false;
+}
+
+/// isHorizontalWhitespace - Return true if this character is horizontal
+/// whitespace: ' ', '\t', '\f', '\v'. Note that this returns false for '\0'.
+static inline bool isHorizontalWhitespace(unsigned char c) {
+ return (CharInfo[c] & CHAR_HORZ_WS) ? true : false;
+}
+
+/// isWhitespace - Return true if this character is horizontal or vertical
+/// whitespace: ' ', '\t', '\f', '\v', '\n', '\r'. Note that this returns false
+/// for '\0'.
+static inline bool isWhitespace(unsigned char c) {
+ return (CharInfo[c] & (CHAR_HORZ_WS|CHAR_VERT_WS)) ? true : false;
+}
+
+/// isNumberBody - Return true if this is the body character of an
+/// preprocessing number, which is [a-zA-Z0-9_.].
+static inline bool isNumberBody(unsigned char c) {
+ return (CharInfo[c] & (CHAR_LETTER|CHAR_NUMBER|CHAR_UNDER|CHAR_PERIOD)) ?
+ true : false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Diagnostics forwarding code.
+//===----------------------------------------------------------------------===//
+
+/// GetMappedTokenLoc - If lexing out of a 'mapped buffer', where we pretend the
+/// lexer buffer was all instantiated at a single point, perform the mapping.
+/// This is currently only used for _Pragma implementation, so it is the slow
+/// path of the hot getSourceLocation method. Do not allow it to be inlined.
+static LLVM_ATTRIBUTE_NOINLINE SourceLocation GetMappedTokenLoc(
+ Preprocessor &PP, SourceLocation FileLoc, unsigned CharNo, unsigned TokLen);
+static SourceLocation GetMappedTokenLoc(Preprocessor &PP,
+ SourceLocation FileLoc,
+ unsigned CharNo, unsigned TokLen) {
+ assert(FileLoc.isMacroID() && "Must be an instantiation");
+
+ // Otherwise, we're lexing "mapped tokens". This is used for things like
+ // _Pragma handling. Combine the instantiation location of FileLoc with the
+ // spelling location.
+ SourceManager &SM = PP.getSourceManager();
+
+ // Create a new SLoc which is expanded from Instantiation(FileLoc) but whose
+ // characters come from spelling(FileLoc)+Offset.
+ SourceLocation SpellingLoc = SM.getSpellingLoc(FileLoc);
+ SpellingLoc = SpellingLoc.getFileLocWithOffset(CharNo);
+
+ // Figure out the expansion loc range, which is the range covered by the
+ // original _Pragma(...) sequence.
+ std::pair<SourceLocation,SourceLocation> II =
+ SM.getImmediateInstantiationRange(FileLoc);
+
+ return SM.createInstantiationLoc(SpellingLoc, II.first, II.second, TokLen);
+}
+
+/// getSourceLocation - Return a source location identifier for the specified
+/// offset in the current file.
+SourceLocation Lexer::getSourceLocation(const char *Loc,
+ unsigned TokLen) const {
+ assert(Loc >= BufferStart && Loc <= BufferEnd &&
+ "Location out of range for this buffer!");
+
+ // In the normal case, we're just lexing from a simple file buffer, return
+ // the file id from FileLoc with the offset specified.
+ unsigned CharNo = Loc-BufferStart;
+ if (FileLoc.isFileID())
+ return FileLoc.getFileLocWithOffset(CharNo);
+
+ // Otherwise, this is the _Pragma lexer case, which pretends that all of the
+ // tokens are lexed from where the _Pragma was defined.
+ assert(PP && "This doesn't work on raw lexers");
+ return GetMappedTokenLoc(*PP, FileLoc, CharNo, TokLen);
+}
+
+/// Diag - Forwarding function for diagnostics. This translate a source
+/// position in the current buffer into a SourceLocation object for rendering.
+DiagnosticBuilder Lexer::Diag(const char *Loc, unsigned DiagID) const {
+ return PP->Diag(getSourceLocation(Loc), DiagID);
+}
+
+//===----------------------------------------------------------------------===//
+// Trigraph and Escaped Newline Handling Code.
+//===----------------------------------------------------------------------===//
+
+/// GetTrigraphCharForLetter - Given a character that occurs after a ?? pair,
+/// return the decoded trigraph letter it corresponds to, or '\0' if nothing.
+static char GetTrigraphCharForLetter(char Letter) {
+ switch (Letter) {
+ default: return 0;
+ case '=': return '#';
+ case ')': return ']';
+ case '(': return '[';
+ case '!': return '|';
+ case '\'': return '^';
+ case '>': return '}';
+ case '/': return '\\';
+ case '<': return '{';
+ case '-': return '~';
+ }
+}
+
+/// DecodeTrigraphChar - If the specified character is a legal trigraph when
+/// prefixed with ??, emit a trigraph warning. If trigraphs are enabled,
+/// return the result character. Finally, emit a warning about trigraph use
+/// whether trigraphs are enabled or not.
+static char DecodeTrigraphChar(const char *CP, Lexer *L) {
+ char Res = GetTrigraphCharForLetter(*CP);
+ if (!Res || !L) return Res;
+
+ if (!L->getFeatures().Trigraphs) {
+ if (!L->isLexingRawMode())
+ L->Diag(CP-2, diag::trigraph_ignored);
+ return 0;
+ }
+
+ if (!L->isLexingRawMode())
+ L->Diag(CP-2, diag::trigraph_converted) << llvm::StringRef(&Res, 1);
+ return Res;
+}
+
+/// getEscapedNewLineSize - Return the size of the specified escaped newline,
+/// or 0 if it is not an escaped newline. P[-1] is known to be a "\" or a
+/// trigraph equivalent on entry to this function.
+unsigned Lexer::getEscapedNewLineSize(const char *Ptr) {
+ unsigned Size = 0;
+ while (isWhitespace(Ptr[Size])) {
+ ++Size;
+
+ if (Ptr[Size-1] != '\n' && Ptr[Size-1] != '\r')
+ continue;
+
+ // If this is a \r\n or \n\r, skip the other half.
+ if ((Ptr[Size] == '\r' || Ptr[Size] == '\n') &&
+ Ptr[Size-1] != Ptr[Size])
+ ++Size;
+
+ return Size;
+ }
+
+ // Not an escaped newline, must be a \t or something else.
+ return 0;
+}
+
+/// SkipEscapedNewLines - If P points to an escaped newline (or a series of
+/// them), skip over them and return the first non-escaped-newline found,
+/// otherwise return P.
+const char *Lexer::SkipEscapedNewLines(const char *P) {
+ while (1) {
+ const char *AfterEscape;
+ if (*P == '\\') {
+ AfterEscape = P+1;
+ } else if (*P == '?') {
+ // If not a trigraph for escape, bail out.
+ if (P[1] != '?' || P[2] != '/')
+ return P;
+ AfterEscape = P+3;
+ } else {
+ return P;
+ }
+
+ unsigned NewLineSize = Lexer::getEscapedNewLineSize(AfterEscape);
+ if (NewLineSize == 0) return P;
+ P = AfterEscape+NewLineSize;
+ }
+}
+
+
+/// getCharAndSizeSlow - Peek a single 'character' from the specified buffer,
+/// get its size, and return it. This is tricky in several cases:
+/// 1. If currently at the start of a trigraph, we warn about the trigraph,
+/// then either return the trigraph (skipping 3 chars) or the '?',
+/// depending on whether trigraphs are enabled or not.
+/// 2. If this is an escaped newline (potentially with whitespace between
+/// the backslash and newline), implicitly skip the newline and return
+/// the char after it.
+/// 3. If this is a UCN, return it. FIXME: C++ UCN's?
+///
+/// This handles the slow/uncommon case of the getCharAndSize method. Here we
+/// know that we can accumulate into Size, and that we have already incremented
+/// Ptr by Size bytes.
+///
+/// NOTE: When this method is updated, getCharAndSizeSlowNoWarn (below) should
+/// be updated to match.
+///
+char Lexer::getCharAndSizeSlow(const char *Ptr, unsigned &Size,
+ Token *Tok) {
+ // If we have a slash, look for an escaped newline.
+ if (Ptr[0] == '\\') {
+ ++Size;
+ ++Ptr;
+Slash:
+ // Common case, backslash-char where the char is not whitespace.
+ if (!isWhitespace(Ptr[0])) return '\\';
+
+ // See if we have optional whitespace characters between the slash and
+ // newline.
+ if (unsigned EscapedNewLineSize = getEscapedNewLineSize(Ptr)) {
+ // Remember that this token needs to be cleaned.
+ if (Tok) Tok->setFlag(Token::NeedsCleaning);
+
+ // Warn if there was whitespace between the backslash and newline.
+ if (Ptr[0] != '\n' && Ptr[0] != '\r' && Tok && !isLexingRawMode())
+ Diag(Ptr, diag::backslash_newline_space);
+
+ // Found backslash<whitespace><newline>. Parse the char after it.
+ Size += EscapedNewLineSize;
+ Ptr += EscapedNewLineSize;
+ // Use slow version to accumulate a correct size field.
+ return getCharAndSizeSlow(Ptr, Size, Tok);
+ }
+
+ // Otherwise, this is not an escaped newline, just return the slash.
+ return '\\';
+ }
+
+ // If this is a trigraph, process it.
+ if (Ptr[0] == '?' && Ptr[1] == '?') {
+ // If this is actually a legal trigraph (not something like "??x"), emit
+ // a trigraph warning. If so, and if trigraphs are enabled, return it.
+ if (char C = DecodeTrigraphChar(Ptr+2, Tok ? this : 0)) {
+ // Remember that this token needs to be cleaned.
+ if (Tok) Tok->setFlag(Token::NeedsCleaning);
+
+ Ptr += 3;
+ Size += 3;
+ if (C == '\\') goto Slash;
+ return C;
+ }
+ }
+
+ // If this is neither, return a single character.
+ ++Size;
+ return *Ptr;
+}
+
+
+/// getCharAndSizeSlowNoWarn - Handle the slow/uncommon case of the
+/// getCharAndSizeNoWarn method. Here we know that we can accumulate into Size,
+/// and that we have already incremented Ptr by Size bytes.
+///
+/// NOTE: When this method is updated, getCharAndSizeSlow (above) should
+/// be updated to match.
+char Lexer::getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &Features) {
+ // If we have a slash, look for an escaped newline.
+ if (Ptr[0] == '\\') {
+ ++Size;
+ ++Ptr;
+Slash:
+ // Common case, backslash-char where the char is not whitespace.
+ if (!isWhitespace(Ptr[0])) return '\\';
+
+ // See if we have optional whitespace characters followed by a newline.
+ if (unsigned EscapedNewLineSize = getEscapedNewLineSize(Ptr)) {
+ // Found backslash<whitespace><newline>. Parse the char after it.
+ Size += EscapedNewLineSize;
+ Ptr += EscapedNewLineSize;
+
+ // Use slow version to accumulate a correct size field.
+ return getCharAndSizeSlowNoWarn(Ptr, Size, Features);
+ }
+
+ // Otherwise, this is not an escaped newline, just return the slash.
+ return '\\';
+ }
+
+ // If this is a trigraph, process it.
+ if (Features.Trigraphs && Ptr[0] == '?' && Ptr[1] == '?') {
+ // If this is actually a legal trigraph (not something like "??x"), return
+ // it.
+ if (char C = GetTrigraphCharForLetter(Ptr[2])) {
+ Ptr += 3;
+ Size += 3;
+ if (C == '\\') goto Slash;
+ return C;
+ }
+ }
+
+ // If this is neither, return a single character.
+ ++Size;
+ return *Ptr;
+}
+
+//===----------------------------------------------------------------------===//
+// Helper methods for lexing.
+//===----------------------------------------------------------------------===//
+
+/// \brief Routine that indiscriminately skips bytes in the source file.
+void Lexer::SkipBytes(unsigned Bytes, bool StartOfLine) {
+ BufferPtr += Bytes;
+ if (BufferPtr > BufferEnd)
+ BufferPtr = BufferEnd;
+ IsAtStartOfLine = StartOfLine;
+}
+
+void Lexer::LexIdentifier(Token &Result, const char *CurPtr) {
+ // Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$]
+ unsigned Size;
+ unsigned char C = *CurPtr++;
+ while (isIdentifierBody(C))
+ C = *CurPtr++;
+
+ --CurPtr; // Back up over the skipped character.
+
+ // Fast path, no $,\,? in identifier found. '\' might be an escaped newline
+ // or UCN, and ? might be a trigraph for '\', an escaped newline or UCN.
+ // FIXME: UCNs.
+ //
+ // TODO: Could merge these checks into a CharInfo flag to make the comparison
+ // cheaper
+ if (C != '\\' && C != '?' && (C != '$' || !Features.DollarIdents)) {
+FinishIdentifier:
+ const char *IdStart = BufferPtr;
+ FormTokenWithChars(Result, CurPtr, tok::raw_identifier);
+ Result.setRawIdentifierData(IdStart);
+
+ // If we are in raw mode, return this identifier raw. There is no need to
+ // look up identifier information or attempt to macro expand it.
+ if (LexingRawMode)
+ return;
+
+ // Fill in Result.IdentifierInfo and update the token kind,
+ // looking up the identifier in the identifier table.
+ IdentifierInfo *II = PP->LookUpIdentifierInfo(Result);
+
+ // Finally, now that we know we have an identifier, pass this off to the
+ // preprocessor, which may macro expand it or something.
+ if (II->isHandleIdentifierCase())
+ PP->HandleIdentifier(Result);
+ return;
+ }
+
+ // Otherwise, $,\,? in identifier found. Enter slower path.
+
+ C = getCharAndSize(CurPtr, Size);
+ while (1) {
+ if (C == '$') {
+ // If we hit a $ and they are not supported in identifiers, we are done.
+ if (!Features.DollarIdents) goto FinishIdentifier;
+
+ // Otherwise, emit a diagnostic and continue.
+ if (!isLexingRawMode())
+ Diag(CurPtr, diag::ext_dollar_in_identifier);
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+ C = getCharAndSize(CurPtr, Size);
+ continue;
+ } else if (!isIdentifierBody(C)) { // FIXME: UCNs.
+ // Found end of identifier.
+ goto FinishIdentifier;
+ }
+
+ // Otherwise, this character is good, consume it.
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+
+ C = getCharAndSize(CurPtr, Size);
+ while (isIdentifierBody(C)) { // FIXME: UCNs.
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+ C = getCharAndSize(CurPtr, Size);
+ }
+ }
+}
+
+/// isHexaLiteral - Return true if Start points to a hex constant.
+/// in microsoft mode (where this is supposed to be several different tokens).
+static bool isHexaLiteral(const char *Start, const LangOptions &Features) {
+ unsigned Size;
+ char C1 = Lexer::getCharAndSizeNoWarn(Start, Size, Features);
+ if (C1 != '0')
+ return false;
+ char C2 = Lexer::getCharAndSizeNoWarn(Start + Size, Size, Features);
+ return (C2 == 'x' || C2 == 'X');
+}
+
+/// LexNumericConstant - Lex the remainder of a integer or floating point
+/// constant. From[-1] is the first character lexed. Return the end of the
+/// constant.
+void Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
+ unsigned Size;
+ char C = getCharAndSize(CurPtr, Size);
+ char PrevCh = 0;
+ while (isNumberBody(C)) { // FIXME: UCNs?
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+ PrevCh = C;
+ C = getCharAndSize(CurPtr, Size);
+ }
+
+ // If we fell out, check for a sign, due to 1e+12. If we have one, continue.
+ if ((C == '-' || C == '+') && (PrevCh == 'E' || PrevCh == 'e')) {
+ // If we are in Microsoft mode, don't continue if the constant is hex.
+ // For example, MSVC will accept the following as 3 tokens: 0x1234567e+1
+ if (!Features.Microsoft || !isHexaLiteral(BufferPtr, Features))
+ return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+ }
+
+ // If we have a hex FP constant, continue.
+ if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p') &&
+ !Features.CPlusPlus0x)
+ return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+
+ // Update the location of token as well as BufferPtr.
+ const char *TokStart = BufferPtr;
+ FormTokenWithChars(Result, CurPtr, tok::numeric_constant);
+ Result.setLiteralData(TokStart);
+}
+
+/// LexStringLiteral - Lex the remainder of a string literal, after having lexed
+/// either " or L".
+void Lexer::LexStringLiteral(Token &Result, const char *CurPtr, bool Wide) {
+ const char *NulCharacter = 0; // Does this string contain the \0 character?
+
+ char C = getAndAdvanceChar(CurPtr, Result);
+ while (C != '"') {
+ // Skip escaped characters. Escaped newlines will already be processed by
+ // getAndAdvanceChar.
+ if (C == '\\')
+ C = getAndAdvanceChar(CurPtr, Result);
+
+ if (C == '\n' || C == '\r' || // Newline.
+ (C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
+ if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode() && !Features.AsmPreprocessor)
+ Diag(BufferPtr, diag::warn_unterminated_string);
+ FormTokenWithChars(Result, CurPtr-1, tok::unknown);
+ return;
+ }
+
+ if (C == 0)
+ NulCharacter = CurPtr-1;
+ C = getAndAdvanceChar(CurPtr, Result);
+ }
+
+ // If a nul character existed in the string, warn about it.
+ if (NulCharacter && !isLexingRawMode())
+ Diag(NulCharacter, diag::null_in_string);
+
+ // Update the location of the token as well as the BufferPtr instance var.
+ const char *TokStart = BufferPtr;
+ FormTokenWithChars(Result, CurPtr,
+ Wide ? tok::wide_string_literal : tok::string_literal);
+ Result.setLiteralData(TokStart);
+}
+
+/// LexAngledStringLiteral - Lex the remainder of an angled string literal,
+/// after having lexed the '<' character. This is used for #include filenames.
+void Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
+ const char *NulCharacter = 0; // Does this string contain the \0 character?
+ const char *AfterLessPos = CurPtr;
+ char C = getAndAdvanceChar(CurPtr, Result);
+ while (C != '>') {
+ // Skip escaped characters.
+ if (C == '\\') {
+ // Skip the escaped character.
+ C = getAndAdvanceChar(CurPtr, Result);
+ } else if (C == '\n' || C == '\r' || // Newline.
+ (C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
+ // If the filename is unterminated, then it must just be a lone <
+ // character. Return this as such.
+ FormTokenWithChars(Result, AfterLessPos, tok::less);
+ return;
+ } else if (C == 0) {
+ NulCharacter = CurPtr-1;
+ }
+ C = getAndAdvanceChar(CurPtr, Result);
+ }
+
+ // If a nul character existed in the string, warn about it.
+ if (NulCharacter && !isLexingRawMode())
+ Diag(NulCharacter, diag::null_in_string);
+
+ // Update the location of token as well as BufferPtr.
+ const char *TokStart = BufferPtr;
+ FormTokenWithChars(Result, CurPtr, tok::angle_string_literal);
+ Result.setLiteralData(TokStart);
+}
+
+
+/// LexCharConstant - Lex the remainder of a character constant, after having
+/// lexed either ' or L'.
+void Lexer::LexCharConstant(Token &Result, const char *CurPtr) {
+ const char *NulCharacter = 0; // Does this character contain the \0 character?
+
+ char C = getAndAdvanceChar(CurPtr, Result);
+ if (C == '\'') {
+ if (!isLexingRawMode() && !Features.AsmPreprocessor)
+ Diag(BufferPtr, diag::err_empty_character);
+ FormTokenWithChars(Result, CurPtr, tok::unknown);
+ return;
+ }
+
+ while (C != '\'') {
+ // Skip escaped characters.
+ if (C == '\\') {
+ // Skip the escaped character.
+ // FIXME: UCN's
+ C = getAndAdvanceChar(CurPtr, Result);
+ } else if (C == '\n' || C == '\r' || // Newline.
+ (C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
+ if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode() && !Features.AsmPreprocessor)
+ Diag(BufferPtr, diag::warn_unterminated_char);
+ FormTokenWithChars(Result, CurPtr-1, tok::unknown);
+ return;
+ } else if (C == 0) {
+ NulCharacter = CurPtr-1;
+ }
+ C = getAndAdvanceChar(CurPtr, Result);
+ }
+
+ // If a nul character existed in the character, warn about it.
+ if (NulCharacter && !isLexingRawMode())
+ Diag(NulCharacter, diag::null_in_char);
+
+ // Update the location of token as well as BufferPtr.
+ const char *TokStart = BufferPtr;
+ FormTokenWithChars(Result, CurPtr, tok::char_constant);
+ Result.setLiteralData(TokStart);
+}
+
+/// SkipWhitespace - Efficiently skip over a series of whitespace characters.
+/// Update BufferPtr to point to the next non-whitespace character and return.
+///
+/// This method forms a token and returns true if KeepWhitespaceMode is enabled.
+///
+bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr) {
+ // Whitespace - Skip it, then return the token after the whitespace.
+ unsigned char Char = *CurPtr; // Skip consequtive spaces efficiently.
+ while (1) {
+ // Skip horizontal whitespace very aggressively.
+ while (isHorizontalWhitespace(Char))
+ Char = *++CurPtr;
+
+ // Otherwise if we have something other than whitespace, we're done.
+ if (Char != '\n' && Char != '\r')
+ break;
+
+ if (ParsingPreprocessorDirective) {
+ // End of preprocessor directive line, let LexTokenInternal handle this.
+ BufferPtr = CurPtr;
+ return false;
+ }
+
+ // ok, but handle newline.
+ // The returned token is at the start of the line.
+ Result.setFlag(Token::StartOfLine);
+ // No leading whitespace seen so far.
+ Result.clearFlag(Token::LeadingSpace);
+ Char = *++CurPtr;
+ }
+
+ // If this isn't immediately after a newline, there is leading space.
+ char PrevChar = CurPtr[-1];
+ if (PrevChar != '\n' && PrevChar != '\r')
+ Result.setFlag(Token::LeadingSpace);
+
+ // If the client wants us to return whitespace, return it now.
+ if (isKeepWhitespaceMode()) {
+ FormTokenWithChars(Result, CurPtr, tok::unknown);
+ return true;
+ }
+
+ BufferPtr = CurPtr;
+ return false;
+}
+
+// SkipBCPLComment - We have just read the // characters from input. Skip until
+// we find the newline character thats terminate the comment. Then update
+/// BufferPtr and return.
+///
+/// If we're in KeepCommentMode or any CommentHandler has inserted
+/// some tokens, this will store the first token and return true.
+bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) {
+ // If BCPL comments aren't explicitly enabled for this language, emit an
+ // extension warning.
+ if (!Features.BCPLComment && !isLexingRawMode()) {
+ Diag(BufferPtr, diag::ext_bcpl_comment);
+
+ // Mark them enabled so we only emit one warning for this translation
+ // unit.
+ Features.BCPLComment = true;
+ }
+
+ // Scan over the body of the comment. The common case, when scanning, is that
+ // the comment contains normal ascii characters with nothing interesting in
+ // them. As such, optimize for this case with the inner loop.
+ char C;
+ do {
+ C = *CurPtr;
+ // FIXME: Speedup BCPL comment lexing. Just scan for a \n or \r character.
+ // If we find a \n character, scan backwards, checking to see if it's an
+ // escaped newline, like we do for block comments.
+
+ // Skip over characters in the fast loop.
+ while (C != 0 && // Potentially EOF.
+ C != '\\' && // Potentially escaped newline.
+ C != '?' && // Potentially trigraph.
+ C != '\n' && C != '\r') // Newline or DOS-style newline.
+ C = *++CurPtr;
+
+ // If this is a newline, we're done.
+ if (C == '\n' || C == '\r')
+ break; // Found the newline? Break out!
+
+ // Otherwise, this is a hard case. Fall back on getAndAdvanceChar to
+ // properly decode the character. Read it in raw mode to avoid emitting
+ // diagnostics about things like trigraphs. If we see an escaped newline,
+ // we'll handle it below.
+ const char *OldPtr = CurPtr;
+ bool OldRawMode = isLexingRawMode();
+ LexingRawMode = true;
+ C = getAndAdvanceChar(CurPtr, Result);
+ LexingRawMode = OldRawMode;
+
+ // If the char that we finally got was a \n, then we must have had something
+ // like \<newline><newline>. We don't want to have consumed the second
+ // newline, we want CurPtr, to end up pointing to it down below.
+ if (C == '\n' || C == '\r') {
+ --CurPtr;
+ C = 'x'; // doesn't matter what this is.
+ }
+
+ // If we read multiple characters, and one of those characters was a \r or
+ // \n, then we had an escaped newline within the comment. Emit diagnostic
+ // unless the next line is also a // comment.
+ if (CurPtr != OldPtr+1 && C != '/' && CurPtr[0] != '/') {
+ for (; OldPtr != CurPtr; ++OldPtr)
+ if (OldPtr[0] == '\n' || OldPtr[0] == '\r') {
+ // Okay, we found a // comment that ends in a newline, if the next
+ // line is also a // comment, but has spaces, don't emit a diagnostic.
+ if (isspace(C)) {
+ const char *ForwardPtr = CurPtr;
+ while (isspace(*ForwardPtr)) // Skip whitespace.
+ ++ForwardPtr;
+ if (ForwardPtr[0] == '/' && ForwardPtr[1] == '/')
+ break;
+ }
+
+ if (!isLexingRawMode())
+ Diag(OldPtr-1, diag::ext_multi_line_bcpl_comment);
+ break;
+ }
+ }
+
+ if (CurPtr == BufferEnd+1) {
+ if (PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+
+ --CurPtr;
+ break;
+ }
+ } while (C != '\n' && C != '\r');
+
+ // Found but did not consume the newline. Notify comment handlers about the
+ // comment unless we're in a #if 0 block.
+ if (PP && !isLexingRawMode() &&
+ PP->HandleComment(Result, SourceRange(getSourceLocation(BufferPtr),
+ getSourceLocation(CurPtr)))) {
+ BufferPtr = CurPtr;
+ return true; // A token has to be returned.
+ }
+
+ // If we are returning comments as tokens, return this comment as a token.
+ if (inKeepCommentMode())
+ return SaveBCPLComment(Result, CurPtr);
+
+ // If we are inside a preprocessor directive and we see the end of line,
+ // return immediately, so that the lexer can return this as an EOM token.
+ if (ParsingPreprocessorDirective || CurPtr == BufferEnd) {
+ BufferPtr = CurPtr;
+ return false;
+ }
+
+ // Otherwise, eat the \n character. We don't care if this is a \n\r or
+ // \r\n sequence. This is an efficiency hack (because we know the \n can't
+ // contribute to another token), it isn't needed for correctness. Note that
+ // this is ok even in KeepWhitespaceMode, because we would have returned the
+ /// comment above in that mode.
+ ++CurPtr;
+
+ // The next returned token is at the start of the line.
+ Result.setFlag(Token::StartOfLine);
+ // No leading whitespace seen so far.
+ Result.clearFlag(Token::LeadingSpace);
+ BufferPtr = CurPtr;
+ return false;
+}
+
+/// SaveBCPLComment - If in save-comment mode, package up this BCPL comment in
+/// an appropriate way and return it.
+bool Lexer::SaveBCPLComment(Token &Result, const char *CurPtr) {
+ // If we're not in a preprocessor directive, just return the // comment
+ // directly.
+ FormTokenWithChars(Result, CurPtr, tok::comment);
+
+ if (!ParsingPreprocessorDirective)
+ return true;
+
+ // If this BCPL-style comment is in a macro definition, transmogrify it into
+ // a C-style block comment.
+ bool Invalid = false;
+ std::string Spelling = PP->getSpelling(Result, &Invalid);
+ if (Invalid)
+ return true;
+
+ assert(Spelling[0] == '/' && Spelling[1] == '/' && "Not bcpl comment?");
+ Spelling[1] = '*'; // Change prefix to "/*".
+ Spelling += "*/"; // add suffix.
+
+ Result.setKind(tok::comment);
+ PP->CreateString(&Spelling[0], Spelling.size(), Result,
+ Result.getLocation());
+ return true;
+}
+
+/// isBlockCommentEndOfEscapedNewLine - Return true if the specified newline
+/// character (either \n or \r) is part of an escaped newline sequence. Issue a
+/// diagnostic if so. We know that the newline is inside of a block comment.
+static bool isEndOfBlockCommentWithEscapedNewLine(const char *CurPtr,
+ Lexer *L) {
+ assert(CurPtr[0] == '\n' || CurPtr[0] == '\r');
+
+ // Back up off the newline.
+ --CurPtr;
+
+ // If this is a two-character newline sequence, skip the other character.
+ if (CurPtr[0] == '\n' || CurPtr[0] == '\r') {
+ // \n\n or \r\r -> not escaped newline.
+ if (CurPtr[0] == CurPtr[1])
+ return false;
+ // \n\r or \r\n -> skip the newline.
+ --CurPtr;
+ }
+
+ // If we have horizontal whitespace, skip over it. We allow whitespace
+ // between the slash and newline.
+ bool HasSpace = false;
+ while (isHorizontalWhitespace(*CurPtr) || *CurPtr == 0) {
+ --CurPtr;
+ HasSpace = true;
+ }
+
+ // If we have a slash, we know this is an escaped newline.
+ if (*CurPtr == '\\') {
+ if (CurPtr[-1] != '*') return false;
+ } else {
+ // It isn't a slash, is it the ?? / trigraph?
+ if (CurPtr[0] != '/' || CurPtr[-1] != '?' || CurPtr[-2] != '?' ||
+ CurPtr[-3] != '*')
+ return false;
+
+ // This is the trigraph ending the comment. Emit a stern warning!
+ CurPtr -= 2;
+
+ // If no trigraphs are enabled, warn that we ignored this trigraph and
+ // ignore this * character.
+ if (!L->getFeatures().Trigraphs) {
+ if (!L->isLexingRawMode())
+ L->Diag(CurPtr, diag::trigraph_ignored_block_comment);
+ return false;
+ }
+ if (!L->isLexingRawMode())
+ L->Diag(CurPtr, diag::trigraph_ends_block_comment);
+ }
+
+ // Warn about having an escaped newline between the */ characters.
+ if (!L->isLexingRawMode())
+ L->Diag(CurPtr, diag::escaped_newline_block_comment_end);
+
+ // If there was space between the backslash and newline, warn about it.
+ if (HasSpace && !L->isLexingRawMode())
+ L->Diag(CurPtr, diag::backslash_newline_space);
+
+ return true;
+}
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#elif __ALTIVEC__
+#include <altivec.h>
+#undef bool
+#endif
+
+/// SkipBlockComment - We have just read the /* characters from input. Read
+/// until we find the */ characters that terminate the comment. Note that we
+/// don't bother decoding trigraphs or escaped newlines in block comments,
+/// because they cannot cause the comment to end. The only thing that can
+/// happen is the comment could end with an escaped newline between the */ end
+/// of comment.
+///
+/// If we're in KeepCommentMode or any CommentHandler has inserted
+/// some tokens, this will store the first token and return true.
+bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
+ // Scan one character past where we should, looking for a '/' character. Once
+ // we find it, check to see if it was preceeded by a *. This common
+ // optimization helps people who like to put a lot of * characters in their
+ // comments.
+
+ // The first character we get with newlines and trigraphs skipped to handle
+ // the degenerate /*/ case below correctly if the * has an escaped newline
+ // after it.
+ unsigned CharSize;
+ unsigned char C = getCharAndSize(CurPtr, CharSize);
+ CurPtr += CharSize;
+ if (C == 0 && CurPtr == BufferEnd+1) {
+ if (!isLexingRawMode() &&
+ !PP->isCodeCompletionFile(FileLoc))
+ Diag(BufferPtr, diag::err_unterminated_block_comment);
+ --CurPtr;
+
+ // KeepWhitespaceMode should return this broken comment as a token. Since
+ // it isn't a well formed comment, just return it as an 'unknown' token.
+ if (isKeepWhitespaceMode()) {
+ FormTokenWithChars(Result, CurPtr, tok::unknown);
+ return true;
+ }
+
+ BufferPtr = CurPtr;
+ return false;
+ }
+
+ // Check to see if the first character after the '/*' is another /. If so,
+ // then this slash does not end the block comment, it is part of it.
+ if (C == '/')
+ C = *CurPtr++;
+
+ while (1) {
+ // Skip over all non-interesting characters until we find end of buffer or a
+ // (probably ending) '/' character.
+ if (CurPtr + 24 < BufferEnd) {
+ // While not aligned to a 16-byte boundary.
+ while (C != '/' && ((intptr_t)CurPtr & 0x0F) != 0)
+ C = *CurPtr++;
+
+ if (C == '/') goto FoundSlash;
+
+#ifdef __SSE2__
+ __m128i Slashes = _mm_set_epi8('/', '/', '/', '/', '/', '/', '/', '/',
+ '/', '/', '/', '/', '/', '/', '/', '/');
+ while (CurPtr+16 <= BufferEnd &&
+ _mm_movemask_epi8(_mm_cmpeq_epi8(*(__m128i*)CurPtr, Slashes)) == 0)
+ CurPtr += 16;
+#elif __ALTIVEC__
+ __vector unsigned char Slashes = {
+ '/', '/', '/', '/', '/', '/', '/', '/',
+ '/', '/', '/', '/', '/', '/', '/', '/'
+ };
+ while (CurPtr+16 <= BufferEnd &&
+ !vec_any_eq(*(vector unsigned char*)CurPtr, Slashes))
+ CurPtr += 16;
+#else
+ // Scan for '/' quickly. Many block comments are very large.
+ while (CurPtr[0] != '/' &&
+ CurPtr[1] != '/' &&
+ CurPtr[2] != '/' &&
+ CurPtr[3] != '/' &&
+ CurPtr+4 < BufferEnd) {
+ CurPtr += 4;
+ }
+#endif
+
+ // It has to be one of the bytes scanned, increment to it and read one.
+ C = *CurPtr++;
+ }
+
+ // Loop to scan the remainder.
+ while (C != '/' && C != '\0')
+ C = *CurPtr++;
+
+ FoundSlash:
+ if (C == '/') {
+ if (CurPtr[-2] == '*') // We found the final */. We're done!
+ break;
+
+ if ((CurPtr[-2] == '\n' || CurPtr[-2] == '\r')) {
+ if (isEndOfBlockCommentWithEscapedNewLine(CurPtr-2, this)) {
+ // We found the final */, though it had an escaped newline between the
+ // * and /. We're done!
+ break;
+ }
+ }
+ if (CurPtr[0] == '*' && CurPtr[1] != '/') {
+ // If this is a /* inside of the comment, emit a warning. Don't do this
+ // if this is a /*/, which will end the comment. This misses cases with
+ // embedded escaped newlines, but oh well.
+ if (!isLexingRawMode())
+ Diag(CurPtr-1, diag::warn_nested_block_comment);
+ }
+ } else if (C == 0 && CurPtr == BufferEnd+1) {
+ if (PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode())
+ Diag(BufferPtr, diag::err_unterminated_block_comment);
+ // Note: the user probably forgot a */. We could continue immediately
+ // after the /*, but this would involve lexing a lot of what really is the
+ // comment, which surely would confuse the parser.
+ --CurPtr;
+
+ // KeepWhitespaceMode should return this broken comment as a token. Since
+ // it isn't a well formed comment, just return it as an 'unknown' token.
+ if (isKeepWhitespaceMode()) {
+ FormTokenWithChars(Result, CurPtr, tok::unknown);
+ return true;
+ }
+
+ BufferPtr = CurPtr;
+ return false;
+ }
+ C = *CurPtr++;
+ }
+
+ // Notify comment handlers about the comment unless we're in a #if 0 block.
+ if (PP && !isLexingRawMode() &&
+ PP->HandleComment(Result, SourceRange(getSourceLocation(BufferPtr),
+ getSourceLocation(CurPtr)))) {
+ BufferPtr = CurPtr;
+ return true; // A token has to be returned.
+ }
+
+ // If we are returning comments as tokens, return this comment as a token.
+ if (inKeepCommentMode()) {
+ FormTokenWithChars(Result, CurPtr, tok::comment);
+ return true;
+ }
+
+ // It is common for the tokens immediately after a /**/ comment to be
+ // whitespace. Instead of going through the big switch, handle it
+ // efficiently now. This is safe even in KeepWhitespaceMode because we would
+ // have already returned above with the comment as a token.
+ if (isHorizontalWhitespace(*CurPtr)) {
+ Result.setFlag(Token::LeadingSpace);
+ SkipWhitespace(Result, CurPtr+1);
+ return false;
+ }
+
+ // Otherwise, just return so that the next character will be lexed as a token.
+ BufferPtr = CurPtr;
+ Result.setFlag(Token::LeadingSpace);
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Primary Lexing Entry Points
+//===----------------------------------------------------------------------===//
+
+/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
+/// uninterpreted string. This switches the lexer out of directive mode.
+std::string Lexer::ReadToEndOfLine() {
+ assert(ParsingPreprocessorDirective && ParsingFilename == false &&
+ "Must be in a preprocessing directive!");
+ std::string Result;
+ Token Tmp;
+
+ // CurPtr - Cache BufferPtr in an automatic variable.
+ const char *CurPtr = BufferPtr;
+ while (1) {
+ char Char = getAndAdvanceChar(CurPtr, Tmp);
+ switch (Char) {
+ default:
+ Result += Char;
+ break;
+ case 0: // Null.
+ // Found end of file?
+ if (CurPtr-1 != BufferEnd) {
+ // Nope, normal character, continue.
+ Result += Char;
+ break;
+ }
+ // FALL THROUGH.
+ case '\r':
+ case '\n':
+ // Okay, we found the end of the line. First, back up past the \0, \r, \n.
+ assert(CurPtr[-1] == Char && "Trigraphs for newline?");
+ BufferPtr = CurPtr-1;
+
+ // Next, lex the character, which should handle the EOM transition.
+ Lex(Tmp);
+ if (Tmp.is(tok::code_completion)) {
+ if (PP && PP->getCodeCompletionHandler())
+ PP->getCodeCompletionHandler()->CodeCompleteNaturalLanguage();
+ Lex(Tmp);
+ }
+ assert(Tmp.is(tok::eom) && "Unexpected token!");
+
+ // Finally, we're done, return the string we found.
+ return Result;
+ }
+ }
+}
+
+/// LexEndOfFile - CurPtr points to the end of this file. Handle this
+/// condition, reporting diagnostics and handling other edge cases as required.
+/// This returns true if Result contains a token, false if PP.Lex should be
+/// called again.
+bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
+ // Check if we are performing code completion.
+ if (PP && PP->isCodeCompletionFile(FileLoc)) {
+ // We're at the end of the file, but we've been asked to consider the
+ // end of the file to be a code-completion token. Return the
+ // code-completion token.
+ Result.startToken();
+ FormTokenWithChars(Result, CurPtr, tok::code_completion);
+
+ // Only do the eof -> code_completion translation once.
+ PP->SetCodeCompletionPoint(0, 0, 0);
+
+ // Silence any diagnostics that occur once we hit the code-completion point.
+ PP->getDiagnostics().setSuppressAllDiagnostics(true);
+ return true;
+ }
+
+ // If we hit the end of the file while parsing a preprocessor directive,
+ // end the preprocessor directive first. The next token returned will
+ // then be the end of file.
+ if (ParsingPreprocessorDirective) {
+ // Done parsing the "line".
+ ParsingPreprocessorDirective = false;
+ // Update the location of token as well as BufferPtr.
+ FormTokenWithChars(Result, CurPtr, tok::eom);
+
+ // Restore comment saving mode, in case it was disabled for directive.
+ SetCommentRetentionState(PP->getCommentRetentionState());
+ return true; // Have a token.
+ }
+
+ // If we are in raw mode, return this event as an EOF token. Let the caller
+ // that put us in raw mode handle the event.
+ if (isLexingRawMode()) {
+ Result.startToken();
+ BufferPtr = BufferEnd;
+ FormTokenWithChars(Result, BufferEnd, tok::eof);
+ return true;
+ }
+
+ // Issue diagnostics for unterminated #if and missing newline.
+
+ // If we are in a #if directive, emit an error.
+ while (!ConditionalStack.empty()) {
+ if (!PP->isCodeCompletionFile(FileLoc))
+ PP->Diag(ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
+ ConditionalStack.pop_back();
+ }
+
+ // C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
+ // a pedwarn.
+ if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r'))
+ Diag(BufferEnd, diag::ext_no_newline_eof)
+ << FixItHint::CreateInsertion(getSourceLocation(BufferEnd), "\n");
+
+ BufferPtr = CurPtr;
+
+ // Finally, let the preprocessor handle this.
+ return PP->HandleEndOfFile(Result);
+}
+
+/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from
+/// the specified lexer will return a tok::l_paren token, 0 if it is something
+/// else and 2 if there are no more tokens in the buffer controlled by the
+/// lexer.
+unsigned Lexer::isNextPPTokenLParen() {
+ assert(!LexingRawMode && "How can we expand a macro from a skipping buffer?");
+
+ // Switch to 'skipping' mode. This will ensure that we can lex a token
+ // without emitting diagnostics, disables macro expansion, and will cause EOF
+ // to return an EOF token instead of popping the include stack.
+ LexingRawMode = true;
+
+ // Save state that can be changed while lexing so that we can restore it.
+ const char *TmpBufferPtr = BufferPtr;
+ bool inPPDirectiveMode = ParsingPreprocessorDirective;
+
+ Token Tok;
+ Tok.startToken();
+ LexTokenInternal(Tok);
+
+ // Restore state that may have changed.
+ BufferPtr = TmpBufferPtr;
+ ParsingPreprocessorDirective = inPPDirectiveMode;
+
+ // Restore the lexer back to non-skipping mode.
+ LexingRawMode = false;
+
+ if (Tok.is(tok::eof))
+ return 2;
+ return Tok.is(tok::l_paren);
+}
+
+/// FindConflictEnd - Find the end of a version control conflict marker.
+static const char *FindConflictEnd(const char *CurPtr, const char *BufferEnd) {
+ llvm::StringRef RestOfBuffer(CurPtr+7, BufferEnd-CurPtr-7);
+ size_t Pos = RestOfBuffer.find(">>>>>>>");
+ while (Pos != llvm::StringRef::npos) {
+ // Must occur at start of line.
+ if (RestOfBuffer[Pos-1] != '\r' &&
+ RestOfBuffer[Pos-1] != '\n') {
+ RestOfBuffer = RestOfBuffer.substr(Pos+7);
+ Pos = RestOfBuffer.find(">>>>>>>");
+ continue;
+ }
+ return RestOfBuffer.data()+Pos;
+ }
+ return 0;
+}
+
+/// IsStartOfConflictMarker - If the specified pointer is the start of a version
+/// control conflict marker like '<<<<<<<', recognize it as such, emit an error
+/// and recover nicely. This returns true if it is a conflict marker and false
+/// if not.
+bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
+ // Only a conflict marker if it starts at the beginning of a line.
+ if (CurPtr != BufferStart &&
+ CurPtr[-1] != '\n' && CurPtr[-1] != '\r')
+ return false;
+
+ // Check to see if we have <<<<<<<.
+ if (BufferEnd-CurPtr < 8 ||
+ llvm::StringRef(CurPtr, 7) != "<<<<<<<")
+ return false;
+
+ // If we have a situation where we don't care about conflict markers, ignore
+ // it.
+ if (IsInConflictMarker || isLexingRawMode())
+ return false;
+
+ // Check to see if there is a >>>>>>> somewhere in the buffer at the start of
+ // a line to terminate this conflict marker.
+ if (FindConflictEnd(CurPtr, BufferEnd)) {
+ // We found a match. We are really in a conflict marker.
+ // Diagnose this, and ignore to the end of line.
+ Diag(CurPtr, diag::err_conflict_marker);
+ IsInConflictMarker = true;
+
+ // Skip ahead to the end of line. We know this exists because the
+ // end-of-conflict marker starts with \r or \n.
+ while (*CurPtr != '\r' && *CurPtr != '\n') {
+ assert(CurPtr != BufferEnd && "Didn't find end of line");
+ ++CurPtr;
+ }
+ BufferPtr = CurPtr;
+ return true;
+ }
+
+ // No end of conflict marker found.
+ return false;
+}
+
+
+/// HandleEndOfConflictMarker - If this is a '=======' or '|||||||' or '>>>>>>>'
+/// marker, then it is the end of a conflict marker. Handle it by ignoring up
+/// until the end of the line. This returns true if it is a conflict marker and
+/// false if not.
+bool Lexer::HandleEndOfConflictMarker(const char *CurPtr) {
+ // Only a conflict marker if it starts at the beginning of a line.
+ if (CurPtr != BufferStart &&
+ CurPtr[-1] != '\n' && CurPtr[-1] != '\r')
+ return false;
+
+ // If we have a situation where we don't care about conflict markers, ignore
+ // it.
+ if (!IsInConflictMarker || isLexingRawMode())
+ return false;
+
+ // Check to see if we have the marker (7 characters in a row).
+ for (unsigned i = 1; i != 7; ++i)
+ if (CurPtr[i] != CurPtr[0])
+ return false;
+
+ // If we do have it, search for the end of the conflict marker. This could
+ // fail if it got skipped with a '#if 0' or something. Note that CurPtr might
+ // be the end of conflict marker.
+ if (const char *End = FindConflictEnd(CurPtr, BufferEnd)) {
+ CurPtr = End;
+
+ // Skip ahead to the end of line.
+ while (CurPtr != BufferEnd && *CurPtr != '\r' && *CurPtr != '\n')
+ ++CurPtr;
+
+ BufferPtr = CurPtr;
+
+ // No longer in the conflict marker.
+ IsInConflictMarker = false;
+ return true;
+ }
+
+ return false;
+}
+
+
+/// LexTokenInternal - This implements a simple C family lexer. It is an
+/// extremely performance critical piece of code. This assumes that the buffer
+/// has a null character at the end of the file. This returns a preprocessing
+/// token, not a normal token, as such, it is an internal interface. It assumes
+/// that the Flags of result have been cleared before calling this.
+void Lexer::LexTokenInternal(Token &Result) {
+LexNextToken:
+ // New token, can't need cleaning yet.
+ Result.clearFlag(Token::NeedsCleaning);
+ Result.setIdentifierInfo(0);
+
+ // CurPtr - Cache BufferPtr in an automatic variable.
+ const char *CurPtr = BufferPtr;
+
+ // Small amounts of horizontal whitespace is very common between tokens.
+ if ((*CurPtr == ' ') || (*CurPtr == '\t')) {
+ ++CurPtr;
+ while ((*CurPtr == ' ') || (*CurPtr == '\t'))
+ ++CurPtr;
+
+ // If we are keeping whitespace and other tokens, just return what we just
+ // skipped. The next lexer invocation will return the token after the
+ // whitespace.
+ if (isKeepWhitespaceMode()) {
+ FormTokenWithChars(Result, CurPtr, tok::unknown);
+ return;
+ }
+
+ BufferPtr = CurPtr;
+ Result.setFlag(Token::LeadingSpace);
+ }
+
+ unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below.
+
+ // Read a character, advancing over it.
+ char Char = getAndAdvanceChar(CurPtr, Result);
+ tok::TokenKind Kind;
+
+ switch (Char) {
+ case 0: // Null.
+ // Found end of file?
+ if (CurPtr-1 == BufferEnd) {
+ // Read the PP instance variable into an automatic variable, because
+ // LexEndOfFile will often delete 'this'.
+ Preprocessor *PPCache = PP;
+ if (LexEndOfFile(Result, CurPtr-1)) // Retreat back into the file.
+ return; // Got a token to return.
+ assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
+ return PPCache->Lex(Result);
+ }
+
+ if (!isLexingRawMode())
+ Diag(CurPtr-1, diag::null_in_file);
+ Result.setFlag(Token::LeadingSpace);
+ if (SkipWhitespace(Result, CurPtr))
+ return; // KeepWhitespaceMode
+
+ goto LexNextToken; // GCC isn't tail call eliminating.
+
+ case 26: // DOS & CP/M EOF: "^Z".
+ // If we're in Microsoft extensions mode, treat this as end of file.
+ if (Features.Microsoft) {
+ // Read the PP instance variable into an automatic variable, because
+ // LexEndOfFile will often delete 'this'.
+ Preprocessor *PPCache = PP;
+ if (LexEndOfFile(Result, CurPtr-1)) // Retreat back into the file.
+ return; // Got a token to return.
+ assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
+ return PPCache->Lex(Result);
+ }
+ // If Microsoft extensions are disabled, this is just random garbage.
+ Kind = tok::unknown;
+ break;
+
+ case '\n':
+ case '\r':
+ // If we are inside a preprocessor directive and we see the end of line,
+ // we know we are done with the directive, so return an EOM token.
+ if (ParsingPreprocessorDirective) {
+ // Done parsing the "line".
+ ParsingPreprocessorDirective = false;
+
+ // Restore comment saving mode, in case it was disabled for directive.
+ SetCommentRetentionState(PP->getCommentRetentionState());
+
+ // Since we consumed a newline, we are back at the start of a line.
+ IsAtStartOfLine = true;
+
+ Kind = tok::eom;
+ break;
+ }
+ // The returned token is at the start of the line.
+ Result.setFlag(Token::StartOfLine);
+ // No leading whitespace seen so far.
+ Result.clearFlag(Token::LeadingSpace);
+
+ if (SkipWhitespace(Result, CurPtr))
+ return; // KeepWhitespaceMode
+ goto LexNextToken; // GCC isn't tail call eliminating.
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\v':
+ SkipHorizontalWhitespace:
+ Result.setFlag(Token::LeadingSpace);
+ if (SkipWhitespace(Result, CurPtr))
+ return; // KeepWhitespaceMode
+
+ SkipIgnoredUnits:
+ CurPtr = BufferPtr;
+
+ // If the next token is obviously a // or /* */ comment, skip it efficiently
+ // too (without going through the big switch stmt).
+ if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inKeepCommentMode() &&
+ Features.BCPLComment) {
+ if (SkipBCPLComment(Result, CurPtr+2))
+ return; // There is a token to return.
+ goto SkipIgnoredUnits;
+ } else if (CurPtr[0] == '/' && CurPtr[1] == '*' && !inKeepCommentMode()) {
+ if (SkipBlockComment(Result, CurPtr+2))
+ return; // There is a token to return.
+ goto SkipIgnoredUnits;
+ } else if (isHorizontalWhitespace(*CurPtr)) {
+ goto SkipHorizontalWhitespace;
+ }
+ goto LexNextToken; // GCC isn't tail call eliminating.
+
+ // C99 6.4.4.1: Integer Constants.
+ // C99 6.4.4.2: Floating Constants.
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ return LexNumericConstant(Result, CurPtr);
+
+ case 'L': // Identifier (Loony) or wide literal (L'x' or L"xyz").
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ Char = getCharAndSize(CurPtr, SizeTmp);
+
+ // Wide string literal.
+ if (Char == '"')
+ return LexStringLiteral(Result, ConsumeChar(CurPtr, SizeTmp, Result),
+ true);
+
+ // Wide character constant.
+ if (Char == '\'')
+ return LexCharConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result));
+ // FALL THROUGH, treating L like the start of an identifier.
+
+ // C99 6.4.2: Identifiers.
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+ case 'H': case 'I': case 'J': case 'K': /*'L'*/case 'M': case 'N':
+ case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
+ case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ case '_':
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ return LexIdentifier(Result, CurPtr);
+
+ case '$': // $ in identifiers.
+ if (Features.DollarIdents) {
+ if (!isLexingRawMode())
+ Diag(CurPtr-1, diag::ext_dollar_in_identifier);
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ return LexIdentifier(Result, CurPtr);
+ }
+
+ Kind = tok::unknown;
+ break;
+
+ // C99 6.4.4: Character Constants.
+ case '\'':
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ return LexCharConstant(Result, CurPtr);
+
+ // C99 6.4.5: String Literals.
+ case '"':
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+ return LexStringLiteral(Result, CurPtr, false);
+
+ // C99 6.4.6: Punctuators.
+ case '?':
+ Kind = tok::question;
+ break;
+ case '[':
+ Kind = tok::l_square;
+ break;
+ case ']':
+ Kind = tok::r_square;
+ break;
+ case '(':
+ Kind = tok::l_paren;
+ break;
+ case ')':
+ Kind = tok::r_paren;
+ break;
+ case '{':
+ Kind = tok::l_brace;
+ break;
+ case '}':
+ Kind = tok::r_brace;
+ break;
+ case '.':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char >= '0' && Char <= '9') {
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+
+ return LexNumericConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result));
+ } else if (Features.CPlusPlus && Char == '*') {
+ Kind = tok::periodstar;
+ CurPtr += SizeTmp;
+ } else if (Char == '.' &&
+ getCharAndSize(CurPtr+SizeTmp, SizeTmp2) == '.') {
+ Kind = tok::ellipsis;
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ } else {
+ Kind = tok::period;
+ }
+ break;
+ case '&':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '&') {
+ Kind = tok::ampamp;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Char == '=') {
+ Kind = tok::ampequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::amp;
+ }
+ break;
+ case '*':
+ if (getCharAndSize(CurPtr, SizeTmp) == '=') {
+ Kind = tok::starequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::star;
+ }
+ break;
+ case '+':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '+') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::plusplus;
+ } else if (Char == '=') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::plusequal;
+ } else {
+ Kind = tok::plus;
+ }
+ break;
+ case '-':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '-') { // --
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::minusminus;
+ } else if (Char == '>' && Features.CPlusPlus &&
+ getCharAndSize(CurPtr+SizeTmp, SizeTmp2) == '*') { // C++ ->*
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ Kind = tok::arrowstar;
+ } else if (Char == '>') { // ->
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::arrow;
+ } else if (Char == '=') { // -=
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::minusequal;
+ } else {
+ Kind = tok::minus;
+ }
+ break;
+ case '~':
+ Kind = tok::tilde;
+ break;
+ case '!':
+ if (getCharAndSize(CurPtr, SizeTmp) == '=') {
+ Kind = tok::exclaimequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::exclaim;
+ }
+ break;
+ case '/':
+ // 6.4.9: Comments
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '/') { // BCPL comment.
+ // Even if BCPL comments are disabled (e.g. in C89 mode), we generally
+ // want to lex this as a comment. There is one problem with this though,
+ // that in one particular corner case, this can change the behavior of the
+ // resultant program. For example, In "foo //**/ bar", C89 would lex
+ // this as "foo / bar" and langauges with BCPL comments would lex it as
+ // "foo". Check to see if the character after the second slash is a '*'.
+ // If so, we will lex that as a "/" instead of the start of a comment.
+ if (Features.BCPLComment ||
+ getCharAndSize(CurPtr+SizeTmp, SizeTmp2) != '*') {
+ if (SkipBCPLComment(Result, ConsumeChar(CurPtr, SizeTmp, Result)))
+ return; // There is a token to return.
+
+ // It is common for the tokens immediately after a // comment to be
+ // whitespace (indentation for the next line). Instead of going through
+ // the big switch, handle it efficiently now.
+ goto SkipIgnoredUnits;
+ }
+ }
+
+ if (Char == '*') { // /**/ comment.
+ if (SkipBlockComment(Result, ConsumeChar(CurPtr, SizeTmp, Result)))
+ return; // There is a token to return.
+ goto LexNextToken; // GCC isn't tail call eliminating.
+ }
+
+ if (Char == '=') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::slashequal;
+ } else {
+ Kind = tok::slash;
+ }
+ break;
+ case '%':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '=') {
+ Kind = tok::percentequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Features.Digraphs && Char == '>') {
+ Kind = tok::r_brace; // '%>' -> '}'
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Features.Digraphs && Char == ':') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '%' && getCharAndSize(CurPtr+SizeTmp, SizeTmp2) == ':') {
+ Kind = tok::hashhash; // '%:%:' -> '##'
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ } else if (Char == '@' && Features.Microsoft) { // %:@ -> #@ -> Charize
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ if (!isLexingRawMode())
+ Diag(BufferPtr, diag::charize_microsoft_ext);
+ Kind = tok::hashat;
+ } else { // '%:' -> '#'
+ // We parsed a # character. If this occurs at the start of the line,
+ // it's actually the start of a preprocessing directive. Callback to
+ // the preprocessor to handle it.
+ // FIXME: -fpreprocessed mode??
+ if (Result.isAtStartOfLine() && !LexingRawMode && !Is_PragmaLexer) {
+ FormTokenWithChars(Result, CurPtr, tok::hash);
+ PP->HandleDirective(Result);
+
+ // As an optimization, if the preprocessor didn't switch lexers, tail
+ // recurse.
+ if (PP->isCurrentLexer(this)) {
+ // Start a new token. If this is a #include or something, the PP may
+ // want us starting at the beginning of the line again. If so, set
+ // the StartOfLine flag and clear LeadingSpace.
+ if (IsAtStartOfLine) {
+ Result.setFlag(Token::StartOfLine);
+ Result.clearFlag(Token::LeadingSpace);
+ IsAtStartOfLine = false;
+ }
+ goto LexNextToken; // GCC isn't tail call eliminating.
+ }
+
+ return PP->Lex(Result);
+ }
+
+ Kind = tok::hash;
+ }
+ } else {
+ Kind = tok::percent;
+ }
+ break;
+ case '<':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (ParsingFilename) {
+ return LexAngledStringLiteral(Result, CurPtr);
+ } else if (Char == '<') {
+ char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
+ if (After == '=') {
+ Kind = tok::lesslessequal;
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ } else if (After == '<' && IsStartOfConflictMarker(CurPtr-1)) {
+ // If this is actually a '<<<<<<<' version control conflict marker,
+ // recognize it as such and recover nicely.
+ goto LexNextToken;
+ } else if (Features.CUDA && After == '<') {
+ Kind = tok::lesslessless;
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ } else {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::lessless;
+ }
+ } else if (Char == '=') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::lessequal;
+ } else if (Features.Digraphs && Char == ':') { // '<:' -> '['
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::l_square;
+ } else if (Features.Digraphs && Char == '%') { // '<%' -> '{'
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::l_brace;
+ } else {
+ Kind = tok::less;
+ }
+ break;
+ case '>':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '=') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::greaterequal;
+ } else if (Char == '>') {
+ char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
+ if (After == '=') {
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ Kind = tok::greatergreaterequal;
+ } else if (After == '>' && HandleEndOfConflictMarker(CurPtr-1)) {
+ // If this is '>>>>>>>' and we're in a conflict marker, ignore it.
+ goto LexNextToken;
+ } else if (Features.CUDA && After == '>') {
+ Kind = tok::greatergreatergreater;
+ CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
+ SizeTmp2, Result);
+ } else {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::greatergreater;
+ }
+
+ } else {
+ Kind = tok::greater;
+ }
+ break;
+ case '^':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '=') {
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ Kind = tok::caretequal;
+ } else {
+ Kind = tok::caret;
+ }
+ break;
+ case '|':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '=') {
+ Kind = tok::pipeequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Char == '|') {
+ // If this is '|||||||' and we're in a conflict marker, ignore it.
+ if (CurPtr[1] == '|' && HandleEndOfConflictMarker(CurPtr-1))
+ goto LexNextToken;
+ Kind = tok::pipepipe;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::pipe;
+ }
+ break;
+ case ':':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Features.Digraphs && Char == '>') {
+ Kind = tok::r_square; // ':>' -> ']'
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Features.CPlusPlus && Char == ':') {
+ Kind = tok::coloncolon;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::colon;
+ }
+ break;
+ case ';':
+ Kind = tok::semi;
+ break;
+ case '=':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '=') {
+ // If this is '=======' and we're in a conflict marker, ignore it.
+ if (CurPtr[1] == '=' && HandleEndOfConflictMarker(CurPtr-1))
+ goto LexNextToken;
+
+ Kind = tok::equalequal;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ Kind = tok::equal;
+ }
+ break;
+ case ',':
+ Kind = tok::comma;
+ break;
+ case '#':
+ Char = getCharAndSize(CurPtr, SizeTmp);
+ if (Char == '#') {
+ Kind = tok::hashhash;
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else if (Char == '@' && Features.Microsoft) { // #@ -> Charize
+ Kind = tok::hashat;
+ if (!isLexingRawMode())
+ Diag(BufferPtr, diag::charize_microsoft_ext);
+ CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
+ } else {
+ // We parsed a # character. If this occurs at the start of the line,
+ // it's actually the start of a preprocessing directive. Callback to
+ // the preprocessor to handle it.
+ // FIXME: -fpreprocessed mode??
+ if (Result.isAtStartOfLine() && !LexingRawMode && !Is_PragmaLexer) {
+ FormTokenWithChars(Result, CurPtr, tok::hash);
+ PP->HandleDirective(Result);
+
+ // As an optimization, if the preprocessor didn't switch lexers, tail
+ // recurse.
+ if (PP->isCurrentLexer(this)) {
+ // Start a new token. If this is a #include or something, the PP may
+ // want us starting at the beginning of the line again. If so, set
+ // the StartOfLine flag and clear LeadingSpace.
+ if (IsAtStartOfLine) {
+ Result.setFlag(Token::StartOfLine);
+ Result.clearFlag(Token::LeadingSpace);
+ IsAtStartOfLine = false;
+ }
+ goto LexNextToken; // GCC isn't tail call eliminating.
+ }
+ return PP->Lex(Result);
+ }
+
+ Kind = tok::hash;
+ }
+ break;
+
+ case '@':
+ // Objective C support.
+ if (CurPtr[-1] == '@' && Features.ObjC1)
+ Kind = tok::at;
+ else
+ Kind = tok::unknown;
+ break;
+
+ case '\\':
+ // FIXME: UCN's.
+ // FALL THROUGH.
+ default:
+ Kind = tok::unknown;
+ break;
+ }
+
+ // Notify MIOpt that we read a non-whitespace/non-comment token.
+ MIOpt.ReadToken();
+
+ // Update the location of token as well as BufferPtr.
+ FormTokenWithChars(Result, CurPtr, Kind);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
new file mode 100644
index 0000000..16d7b36
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -0,0 +1,1069 @@
+//===--- LiteralSupport.cpp - Code to parse and process literals ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the NumericLiteralParser, CharLiteralParser, and
+// StringLiteralParser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+
+/// HexDigitValue - Return the value of the specified hex digit, or -1 if it's
+/// not valid.
+static int HexDigitValue(char C) {
+ if (C >= '0' && C <= '9') return C-'0';
+ if (C >= 'a' && C <= 'f') return C-'a'+10;
+ if (C >= 'A' && C <= 'F') return C-'A'+10;
+ return -1;
+}
+
+/// ProcessCharEscape - Parse a standard C escape sequence, which can occur in
+/// either a character or a string literal.
+static unsigned ProcessCharEscape(const char *&ThisTokBuf,
+ const char *ThisTokEnd, bool &HadError,
+ FullSourceLoc Loc, bool IsWide,
+ Diagnostic *Diags, const TargetInfo &Target) {
+ // Skip the '\' char.
+ ++ThisTokBuf;
+
+ // We know that this character can't be off the end of the buffer, because
+ // that would have been \", which would not have been the end of string.
+ unsigned ResultChar = *ThisTokBuf++;
+ switch (ResultChar) {
+ // These map to themselves.
+ case '\\': case '\'': case '"': case '?': break;
+
+ // These have fixed mappings.
+ case 'a':
+ // TODO: K&R: the meaning of '\\a' is different in traditional C
+ ResultChar = 7;
+ break;
+ case 'b':
+ ResultChar = 8;
+ break;
+ case 'e':
+ if (Diags)
+ Diags->Report(Loc, diag::ext_nonstandard_escape) << "e";
+ ResultChar = 27;
+ break;
+ case 'E':
+ if (Diags)
+ Diags->Report(Loc, diag::ext_nonstandard_escape) << "E";
+ ResultChar = 27;
+ break;
+ case 'f':
+ ResultChar = 12;
+ break;
+ case 'n':
+ ResultChar = 10;
+ break;
+ case 'r':
+ ResultChar = 13;
+ break;
+ case 't':
+ ResultChar = 9;
+ break;
+ case 'v':
+ ResultChar = 11;
+ break;
+ case 'x': { // Hex escape.
+ ResultChar = 0;
+ if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) {
+ if (Diags)
+ Diags->Report(Loc, diag::err_hex_escape_no_digits);
+ HadError = 1;
+ break;
+ }
+
+ // Hex escapes are a maximal series of hex digits.
+ bool Overflow = false;
+ for (; ThisTokBuf != ThisTokEnd; ++ThisTokBuf) {
+ int CharVal = HexDigitValue(ThisTokBuf[0]);
+ if (CharVal == -1) break;
+ // About to shift out a digit?
+ Overflow |= (ResultChar & 0xF0000000) ? true : false;
+ ResultChar <<= 4;
+ ResultChar |= CharVal;
+ }
+
+ // See if any bits will be truncated when evaluated as a character.
+ unsigned CharWidth =
+ IsWide ? Target.getWCharWidth() : Target.getCharWidth();
+
+ if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
+ Overflow = true;
+ ResultChar &= ~0U >> (32-CharWidth);
+ }
+
+ // Check for overflow.
+ if (Overflow && Diags) // Too many digits to fit in
+ Diags->Report(Loc, diag::warn_hex_escape_too_large);
+ break;
+ }
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7': {
+ // Octal escapes.
+ --ThisTokBuf;
+ ResultChar = 0;
+
+ // Octal escapes are a series of octal digits with maximum length 3.
+ // "\0123" is a two digit sequence equal to "\012" "3".
+ unsigned NumDigits = 0;
+ do {
+ ResultChar <<= 3;
+ ResultChar |= *ThisTokBuf++ - '0';
+ ++NumDigits;
+ } while (ThisTokBuf != ThisTokEnd && NumDigits < 3 &&
+ ThisTokBuf[0] >= '0' && ThisTokBuf[0] <= '7');
+
+ // Check for overflow. Reject '\777', but not L'\777'.
+ unsigned CharWidth =
+ IsWide ? Target.getWCharWidth() : Target.getCharWidth();
+
+ if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
+ if (Diags)
+ Diags->Report(Loc, diag::warn_octal_escape_too_large);
+ ResultChar &= ~0U >> (32-CharWidth);
+ }
+ break;
+ }
+
+ // Otherwise, these are not valid escapes.
+ case '(': case '{': case '[': case '%':
+ // GCC accepts these as extensions. We warn about them as such though.
+ if (Diags)
+ Diags->Report(Loc, diag::ext_nonstandard_escape)
+ << std::string()+(char)ResultChar;
+ break;
+ default:
+ if (Diags == 0)
+ break;
+
+ if (isgraph(ResultChar))
+ Diags->Report(Loc, diag::ext_unknown_escape)
+ << std::string()+(char)ResultChar;
+ else
+ Diags->Report(Loc, diag::ext_unknown_escape)
+ << "x"+llvm::utohexstr(ResultChar);
+ break;
+ }
+
+ return ResultChar;
+}
+
+/// ProcessUCNEscape - Read the Universal Character Name, check constraints and
+/// return the UTF32.
+static bool ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
+ uint32_t &UcnVal, unsigned short &UcnLen,
+ FullSourceLoc Loc, Diagnostic *Diags,
+ const LangOptions &Features) {
+ if (!Features.CPlusPlus && !Features.C99 && Diags)
+ Diags->Report(Loc, diag::warn_ucn_not_valid_in_c89);
+
+ // Save the beginning of the string (for error diagnostics).
+ const char *ThisTokBegin = ThisTokBuf;
+
+ // Skip the '\u' char's.
+ ThisTokBuf += 2;
+
+ if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) {
+ if (Diags)
+ Diags->Report(Loc, diag::err_ucn_escape_no_digits);
+ return false;
+ }
+ UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8);
+ unsigned short UcnLenSave = UcnLen;
+ for (; ThisTokBuf != ThisTokEnd && UcnLenSave; ++ThisTokBuf, UcnLenSave--) {
+ int CharVal = HexDigitValue(ThisTokBuf[0]);
+ if (CharVal == -1) break;
+ UcnVal <<= 4;
+ UcnVal |= CharVal;
+ }
+ // If we didn't consume the proper number of digits, there is a problem.
+ if (UcnLenSave) {
+ if (Diags) {
+ SourceLocation L =
+ Lexer::AdvanceToTokenCharacter(Loc, ThisTokBuf-ThisTokBegin,
+ Loc.getManager(), Features);
+ Diags->Report(FullSourceLoc(L, Loc.getManager()),
+ diag::err_ucn_escape_incomplete);
+ }
+ return false;
+ }
+ // Check UCN constraints (C99 6.4.3p2).
+ if ((UcnVal < 0xa0 &&
+ (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60 )) // $, @, `
+ || (UcnVal >= 0xD800 && UcnVal <= 0xDFFF)
+ || (UcnVal > 0x10FFFF)) /* the maximum legal UTF32 value */ {
+ if (Diags)
+ Diags->Report(Loc, diag::err_ucn_escape_invalid);
+ return false;
+ }
+ return true;
+}
+
+/// EncodeUCNEscape - Read the Universal Character Name, check constraints and
+/// convert the UTF32 to UTF8 or UTF16. This is a subroutine of
+/// StringLiteralParser. When we decide to implement UCN's for identifiers,
+/// we will likely rework our support for UCN's.
+static void EncodeUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
+ char *&ResultBuf, bool &HadError,
+ FullSourceLoc Loc, bool wide, Diagnostic *Diags,
+ const LangOptions &Features) {
+ typedef uint32_t UTF32;
+ UTF32 UcnVal = 0;
+ unsigned short UcnLen = 0;
+ if (!ProcessUCNEscape(ThisTokBuf, ThisTokEnd, UcnVal, UcnLen, Loc, Diags,
+ Features)) {
+ HadError = 1;
+ return;
+ }
+
+ if (wide) {
+ (void)UcnLen;
+ assert((UcnLen== 4 || UcnLen== 8) && "only ucn length of 4 or 8 supported");
+
+ if (!Features.ShortWChar) {
+ // Note: our internal rep of wide char tokens is always little-endian.
+ *ResultBuf++ = (UcnVal & 0x000000FF);
+ *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8;
+ *ResultBuf++ = (UcnVal & 0x00FF0000) >> 16;
+ *ResultBuf++ = (UcnVal & 0xFF000000) >> 24;
+ return;
+ }
+
+ // Convert to UTF16.
+ if (UcnVal < (UTF32)0xFFFF) {
+ *ResultBuf++ = (UcnVal & 0x000000FF);
+ *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8;
+ return;
+ }
+ if (Diags) Diags->Report(Loc, diag::warn_ucn_escape_too_large);
+
+ typedef uint16_t UTF16;
+ UcnVal -= 0x10000;
+ UTF16 surrogate1 = 0xD800 + (UcnVal >> 10);
+ UTF16 surrogate2 = 0xDC00 + (UcnVal & 0x3FF);
+ *ResultBuf++ = (surrogate1 & 0x000000FF);
+ *ResultBuf++ = (surrogate1 & 0x0000FF00) >> 8;
+ *ResultBuf++ = (surrogate2 & 0x000000FF);
+ *ResultBuf++ = (surrogate2 & 0x0000FF00) >> 8;
+ return;
+ }
+ // Now that we've parsed/checked the UCN, we convert from UTF32->UTF8.
+ // The conversion below was inspired by:
+ // http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+ // First, we determine how many bytes the result will require.
+ typedef uint8_t UTF8;
+
+ unsigned short bytesToWrite = 0;
+ if (UcnVal < (UTF32)0x80)
+ bytesToWrite = 1;
+ else if (UcnVal < (UTF32)0x800)
+ bytesToWrite = 2;
+ else if (UcnVal < (UTF32)0x10000)
+ bytesToWrite = 3;
+ else
+ bytesToWrite = 4;
+
+ const unsigned byteMask = 0xBF;
+ const unsigned byteMark = 0x80;
+
+ // Once the bits are split out into bytes of UTF8, this is a mask OR-ed
+ // into the first byte, depending on how many bytes follow.
+ static const UTF8 firstByteMark[5] = {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0
+ };
+ // Finally, we write the bytes into ResultBuf.
+ ResultBuf += bytesToWrite;
+ switch (bytesToWrite) { // note: everything falls through.
+ case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
+ case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]);
+ }
+ // Update the buffer.
+ ResultBuf += bytesToWrite;
+}
+
+
+/// integer-constant: [C99 6.4.4.1]
+/// decimal-constant integer-suffix
+/// octal-constant integer-suffix
+/// hexadecimal-constant integer-suffix
+/// decimal-constant:
+/// nonzero-digit
+/// decimal-constant digit
+/// octal-constant:
+/// 0
+/// octal-constant octal-digit
+/// hexadecimal-constant:
+/// hexadecimal-prefix hexadecimal-digit
+/// hexadecimal-constant hexadecimal-digit
+/// hexadecimal-prefix: one of
+/// 0x 0X
+/// integer-suffix:
+/// unsigned-suffix [long-suffix]
+/// unsigned-suffix [long-long-suffix]
+/// long-suffix [unsigned-suffix]
+/// long-long-suffix [unsigned-sufix]
+/// nonzero-digit:
+/// 1 2 3 4 5 6 7 8 9
+/// octal-digit:
+/// 0 1 2 3 4 5 6 7
+/// hexadecimal-digit:
+/// 0 1 2 3 4 5 6 7 8 9
+/// a b c d e f
+/// A B C D E F
+/// unsigned-suffix: one of
+/// u U
+/// long-suffix: one of
+/// l L
+/// long-long-suffix: one of
+/// ll LL
+///
+/// floating-constant: [C99 6.4.4.2]
+/// TODO: add rules...
+///
+NumericLiteralParser::
+NumericLiteralParser(const char *begin, const char *end,
+ SourceLocation TokLoc, Preprocessor &pp)
+ : PP(pp), ThisTokBegin(begin), ThisTokEnd(end) {
+
+ // This routine assumes that the range begin/end matches the regex for integer
+ // and FP constants (specifically, the 'pp-number' regex), and assumes that
+ // the byte at "*end" is both valid and not part of the regex. Because of
+ // this, it doesn't have to check for 'overscan' in various places.
+ assert(!isalnum(*end) && *end != '.' && *end != '_' &&
+ "Lexer didn't maximally munch?");
+
+ s = DigitsBegin = begin;
+ saw_exponent = false;
+ saw_period = false;
+ isLong = false;
+ isUnsigned = false;
+ isLongLong = false;
+ isFloat = false;
+ isImaginary = false;
+ isMicrosoftInteger = false;
+ hadError = false;
+
+ if (*s == '0') { // parse radix
+ ParseNumberStartingWithZero(TokLoc);
+ if (hadError)
+ return;
+ } else { // the first digit is non-zero
+ radix = 10;
+ s = SkipDigits(s);
+ if (s == ThisTokEnd) {
+ // Done.
+ } else if (isxdigit(*s) && !(*s == 'e' || *s == 'E')) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
+ diag::err_invalid_decimal_digit) << llvm::StringRef(s, 1);
+ hadError = true;
+ return;
+ } else if (*s == '.') {
+ s++;
+ saw_period = true;
+ s = SkipDigits(s);
+ }
+ if ((*s == 'e' || *s == 'E')) { // exponent
+ const char *Exponent = s;
+ s++;
+ saw_exponent = true;
+ if (*s == '+' || *s == '-') s++; // sign
+ const char *first_non_digit = SkipDigits(s);
+ if (first_non_digit != s) {
+ s = first_non_digit;
+ } else {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-begin),
+ diag::err_exponent_has_no_digits);
+ hadError = true;
+ return;
+ }
+ }
+ }
+
+ SuffixBegin = s;
+
+ // Parse the suffix. At this point we can classify whether we have an FP or
+ // integer constant.
+ bool isFPConstant = isFloatingLiteral();
+
+ // Loop over all of the characters of the suffix. If we see something bad,
+ // we break out of the loop.
+ for (; s != ThisTokEnd; ++s) {
+ switch (*s) {
+ case 'f': // FP Suffix for "float"
+ case 'F':
+ if (!isFPConstant) break; // Error for integer constant.
+ if (isFloat || isLong) break; // FF, LF invalid.
+ isFloat = true;
+ continue; // Success.
+ case 'u':
+ case 'U':
+ if (isFPConstant) break; // Error for floating constant.
+ if (isUnsigned) break; // Cannot be repeated.
+ isUnsigned = true;
+ continue; // Success.
+ case 'l':
+ case 'L':
+ if (isLong || isLongLong) break; // Cannot be repeated.
+ if (isFloat) break; // LF invalid.
+
+ // Check for long long. The L's need to be adjacent and the same case.
+ if (s+1 != ThisTokEnd && s[1] == s[0]) {
+ if (isFPConstant) break; // long long invalid for floats.
+ isLongLong = true;
+ ++s; // Eat both of them.
+ } else {
+ isLong = true;
+ }
+ continue; // Success.
+ case 'i':
+ case 'I':
+ if (PP.getLangOptions().Microsoft) {
+ if (isFPConstant || isLong || isLongLong) break;
+
+ // Allow i8, i16, i32, i64, and i128.
+ if (s + 1 != ThisTokEnd) {
+ switch (s[1]) {
+ case '8':
+ s += 2; // i8 suffix
+ isMicrosoftInteger = true;
+ break;
+ case '1':
+ if (s + 2 == ThisTokEnd) break;
+ if (s[2] == '6') {
+ s += 3; // i16 suffix
+ isMicrosoftInteger = true;
+ }
+ else if (s[2] == '2') {
+ if (s + 3 == ThisTokEnd) break;
+ if (s[3] == '8') {
+ s += 4; // i128 suffix
+ isMicrosoftInteger = true;
+ }
+ }
+ break;
+ case '3':
+ if (s + 2 == ThisTokEnd) break;
+ if (s[2] == '2') {
+ s += 3; // i32 suffix
+ isLong = true;
+ isMicrosoftInteger = true;
+ }
+ break;
+ case '6':
+ if (s + 2 == ThisTokEnd) break;
+ if (s[2] == '4') {
+ s += 3; // i64 suffix
+ isLongLong = true;
+ isMicrosoftInteger = true;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ // fall through.
+ case 'j':
+ case 'J':
+ if (isImaginary) break; // Cannot be repeated.
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
+ diag::ext_imaginary_constant);
+ isImaginary = true;
+ continue; // Success.
+ }
+ // If we reached here, there was an error.
+ break;
+ }
+
+ // Report an error if there are any.
+ if (s != ThisTokEnd) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
+ isFPConstant ? diag::err_invalid_suffix_float_constant :
+ diag::err_invalid_suffix_integer_constant)
+ << llvm::StringRef(SuffixBegin, ThisTokEnd-SuffixBegin);
+ hadError = true;
+ return;
+ }
+}
+
+/// ParseNumberStartingWithZero - This method is called when the first character
+/// of the number is found to be a zero. This means it is either an octal
+/// number (like '04') or a hex number ('0x123a') a binary number ('0b1010') or
+/// a floating point number (01239.123e4). Eat the prefix, determining the
+/// radix etc.
+void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
+ assert(s[0] == '0' && "Invalid method call");
+ s++;
+
+ // Handle a hex number like 0x1234.
+ if ((*s == 'x' || *s == 'X') && (isxdigit(s[1]) || s[1] == '.')) {
+ s++;
+ radix = 16;
+ DigitsBegin = s;
+ s = SkipHexDigits(s);
+ if (s == ThisTokEnd) {
+ // Done.
+ } else if (*s == '.') {
+ s++;
+ saw_period = true;
+ s = SkipHexDigits(s);
+ }
+ // A binary exponent can appear with or with a '.'. If dotted, the
+ // binary exponent is required.
+ if ((*s == 'p' || *s == 'P') && !PP.getLangOptions().CPlusPlus0x) {
+ const char *Exponent = s;
+ s++;
+ saw_exponent = true;
+ if (*s == '+' || *s == '-') s++; // sign
+ const char *first_non_digit = SkipDigits(s);
+ if (first_non_digit == s) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
+ diag::err_exponent_has_no_digits);
+ hadError = true;
+ return;
+ }
+ s = first_non_digit;
+
+ // In C++0x, we cannot support hexadecmial floating literals because
+ // they conflict with user-defined literals, so we warn in previous
+ // versions of C++ by default.
+ if (PP.getLangOptions().CPlusPlus)
+ PP.Diag(TokLoc, diag::ext_hexconstant_cplusplus);
+ else if (!PP.getLangOptions().HexFloats)
+ PP.Diag(TokLoc, diag::ext_hexconstant_invalid);
+ } else if (saw_period) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
+ diag::err_hexconstant_requires_exponent);
+ hadError = true;
+ }
+ return;
+ }
+
+ // Handle simple binary numbers 0b01010
+ if (*s == 'b' || *s == 'B') {
+ // 0b101010 is a GCC extension.
+ PP.Diag(TokLoc, diag::ext_binary_literal);
+ ++s;
+ radix = 2;
+ DigitsBegin = s;
+ s = SkipBinaryDigits(s);
+ if (s == ThisTokEnd) {
+ // Done.
+ } else if (isxdigit(*s)) {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
+ diag::err_invalid_binary_digit) << llvm::StringRef(s, 1);
+ hadError = true;
+ }
+ // Other suffixes will be diagnosed by the caller.
+ return;
+ }
+
+ // For now, the radix is set to 8. If we discover that we have a
+ // floating point constant, the radix will change to 10. Octal floating
+ // point constants are not permitted (only decimal and hexadecimal).
+ radix = 8;
+ DigitsBegin = s;
+ s = SkipOctalDigits(s);
+ if (s == ThisTokEnd)
+ return; // Done, simple octal number like 01234
+
+ // If we have some other non-octal digit that *is* a decimal digit, see if
+ // this is part of a floating point number like 094.123 or 09e1.
+ if (isdigit(*s)) {
+ const char *EndDecimal = SkipDigits(s);
+ if (EndDecimal[0] == '.' || EndDecimal[0] == 'e' || EndDecimal[0] == 'E') {
+ s = EndDecimal;
+ radix = 10;
+ }
+ }
+
+ // If we have a hex digit other than 'e' (which denotes a FP exponent) then
+ // the code is using an incorrect base.
+ if (isxdigit(*s) && *s != 'e' && *s != 'E') {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
+ diag::err_invalid_octal_digit) << llvm::StringRef(s, 1);
+ hadError = true;
+ return;
+ }
+
+ if (*s == '.') {
+ s++;
+ radix = 10;
+ saw_period = true;
+ s = SkipDigits(s); // Skip suffix.
+ }
+ if (*s == 'e' || *s == 'E') { // exponent
+ const char *Exponent = s;
+ s++;
+ radix = 10;
+ saw_exponent = true;
+ if (*s == '+' || *s == '-') s++; // sign
+ const char *first_non_digit = SkipDigits(s);
+ if (first_non_digit != s) {
+ s = first_non_digit;
+ } else {
+ PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
+ diag::err_exponent_has_no_digits);
+ hadError = true;
+ return;
+ }
+ }
+}
+
+
+/// GetIntegerValue - Convert this numeric literal value to an APInt that
+/// matches Val's input width. If there is an overflow, set Val to the low bits
+/// of the result and return true. Otherwise, return false.
+bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) {
+ // Fast path: Compute a conservative bound on the maximum number of
+ // bits per digit in this radix. If we can't possibly overflow a
+ // uint64 based on that bound then do the simple conversion to
+ // integer. This avoids the expensive overflow checking below, and
+ // handles the common cases that matter (small decimal integers and
+ // hex/octal values which don't overflow).
+ unsigned MaxBitsPerDigit = 1;
+ while ((1U << MaxBitsPerDigit) < radix)
+ MaxBitsPerDigit += 1;
+ if ((SuffixBegin - DigitsBegin) * MaxBitsPerDigit <= 64) {
+ uint64_t N = 0;
+ for (s = DigitsBegin; s != SuffixBegin; ++s)
+ N = N*radix + HexDigitValue(*s);
+
+ // This will truncate the value to Val's input width. Simply check
+ // for overflow by comparing.
+ Val = N;
+ return Val.getZExtValue() != N;
+ }
+
+ Val = 0;
+ s = DigitsBegin;
+
+ llvm::APInt RadixVal(Val.getBitWidth(), radix);
+ llvm::APInt CharVal(Val.getBitWidth(), 0);
+ llvm::APInt OldVal = Val;
+
+ bool OverflowOccurred = false;
+ while (s < SuffixBegin) {
+ unsigned C = HexDigitValue(*s++);
+
+ // If this letter is out of bound for this radix, reject it.
+ assert(C < radix && "NumericLiteralParser ctor should have rejected this");
+
+ CharVal = C;
+
+ // Add the digit to the value in the appropriate radix. If adding in digits
+ // made the value smaller, then this overflowed.
+ OldVal = Val;
+
+ // Multiply by radix, did overflow occur on the multiply?
+ Val *= RadixVal;
+ OverflowOccurred |= Val.udiv(RadixVal) != OldVal;
+
+ // Add value, did overflow occur on the value?
+ // (a + b) ult b <=> overflow
+ Val += CharVal;
+ OverflowOccurred |= Val.ult(CharVal);
+ }
+ return OverflowOccurred;
+}
+
+llvm::APFloat::opStatus
+NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
+ using llvm::APFloat;
+ using llvm::StringRef;
+
+ unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin);
+ return Result.convertFromString(StringRef(ThisTokBegin, n),
+ APFloat::rmNearestTiesToEven);
+}
+
+
+CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP) {
+ // At this point we know that the character matches the regex "L?'.*'".
+ HadError = false;
+
+ // Determine if this is a wide character.
+ IsWide = begin[0] == 'L';
+ if (IsWide) ++begin;
+
+ // Skip over the entry quote.
+ assert(begin[0] == '\'' && "Invalid token lexed");
+ ++begin;
+
+ // FIXME: The "Value" is an uint64_t so we can handle char literals of
+ // upto 64-bits.
+ // FIXME: This extensively assumes that 'char' is 8-bits.
+ assert(PP.getTargetInfo().getCharWidth() == 8 &&
+ "Assumes char is 8 bits");
+ assert(PP.getTargetInfo().getIntWidth() <= 64 &&
+ (PP.getTargetInfo().getIntWidth() & 7) == 0 &&
+ "Assumes sizeof(int) on target is <= 64 and a multiple of char");
+ assert(PP.getTargetInfo().getWCharWidth() <= 64 &&
+ "Assumes sizeof(wchar) on target is <= 64");
+
+ // This is what we will use for overflow detection
+ llvm::APInt LitVal(PP.getTargetInfo().getIntWidth(), 0);
+
+ unsigned NumCharsSoFar = 0;
+ bool Warned = false;
+ while (begin[0] != '\'') {
+ uint64_t ResultChar;
+
+ // Is this a Universal Character Name escape?
+ if (begin[0] != '\\') // If this is a normal character, consume it.
+ ResultChar = *begin++;
+ else { // Otherwise, this is an escape character.
+ // Check for UCN.
+ if (begin[1] == 'u' || begin[1] == 'U') {
+ uint32_t utf32 = 0;
+ unsigned short UcnLen = 0;
+ if (!ProcessUCNEscape(begin, end, utf32, UcnLen,
+ FullSourceLoc(Loc, PP.getSourceManager()),
+ &PP.getDiagnostics(), PP.getLangOptions())) {
+ HadError = 1;
+ }
+ ResultChar = utf32;
+ } else {
+ // Otherwise, this is a non-UCN escape character. Process it.
+ ResultChar = ProcessCharEscape(begin, end, HadError,
+ FullSourceLoc(Loc,PP.getSourceManager()),
+ IsWide,
+ &PP.getDiagnostics(), PP.getTargetInfo());
+ }
+ }
+
+ // If this is a multi-character constant (e.g. 'abc'), handle it. These are
+ // implementation defined (C99 6.4.4.4p10).
+ if (NumCharsSoFar) {
+ if (IsWide) {
+ // Emulate GCC's (unintentional?) behavior: L'ab' -> L'b'.
+ LitVal = 0;
+ } else {
+ // Narrow character literals act as though their value is concatenated
+ // in this implementation, but warn on overflow.
+ if (LitVal.countLeadingZeros() < 8 && !Warned) {
+ PP.Diag(Loc, diag::warn_char_constant_too_large);
+ Warned = true;
+ }
+ LitVal <<= 8;
+ }
+ }
+
+ LitVal = LitVal + ResultChar;
+ ++NumCharsSoFar;
+ }
+
+ // If this is the second character being processed, do special handling.
+ if (NumCharsSoFar > 1) {
+ // Warn about discarding the top bits for multi-char wide-character
+ // constants (L'abcd').
+ if (IsWide)
+ PP.Diag(Loc, diag::warn_extraneous_wide_char_constant);
+ else if (NumCharsSoFar != 4)
+ PP.Diag(Loc, diag::ext_multichar_character_literal);
+ else
+ PP.Diag(Loc, diag::ext_four_char_character_literal);
+ IsMultiChar = true;
+ } else
+ IsMultiChar = false;
+
+ // Transfer the value from APInt to uint64_t
+ Value = LitVal.getZExtValue();
+
+ if (IsWide && PP.getLangOptions().ShortWChar && Value > 0xFFFF)
+ PP.Diag(Loc, diag::warn_ucn_escape_too_large);
+
+ // If this is a single narrow character, sign extend it (e.g. '\xFF' is "-1")
+ // if 'char' is signed for this target (C99 6.4.4.4p10). Note that multiple
+ // character constants are not sign extended in the this implementation:
+ // '\xFF\xFF' = 65536 and '\x0\xFF' = 255, which matches GCC.
+ if (!IsWide && NumCharsSoFar == 1 && (Value & 128) &&
+ PP.getLangOptions().CharIsSigned)
+ Value = (signed char)Value;
+}
+
+
+/// string-literal: [C99 6.4.5]
+/// " [s-char-sequence] "
+/// L" [s-char-sequence] "
+/// s-char-sequence:
+/// s-char
+/// s-char-sequence s-char
+/// s-char:
+/// any source character except the double quote ",
+/// backslash \, or newline character
+/// escape-character
+/// universal-character-name
+/// escape-character: [C99 6.4.4.4]
+/// \ escape-code
+/// universal-character-name
+/// escape-code:
+/// character-escape-code
+/// octal-escape-code
+/// hex-escape-code
+/// character-escape-code: one of
+/// n t b r f v a
+/// \ ' " ?
+/// octal-escape-code:
+/// octal-digit
+/// octal-digit octal-digit
+/// octal-digit octal-digit octal-digit
+/// hex-escape-code:
+/// x hex-digit
+/// hex-escape-code hex-digit
+/// universal-character-name:
+/// \u hex-quad
+/// \U hex-quad hex-quad
+/// hex-quad:
+/// hex-digit hex-digit hex-digit hex-digit
+///
+StringLiteralParser::
+StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ Preprocessor &PP, bool Complain)
+ : SM(PP.getSourceManager()), Features(PP.getLangOptions()),
+ Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() : 0) {
+ init(StringToks, NumStringToks);
+}
+
+void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
+ // Scan all of the string portions, remember the max individual token length,
+ // computing a bound on the concatenated string length, and see whether any
+ // piece is a wide-string. If any of the string portions is a wide-string
+ // literal, the result is a wide-string literal [C99 6.4.5p4].
+ MaxTokenLength = StringToks[0].getLength();
+ SizeBound = StringToks[0].getLength()-2; // -2 for "".
+ AnyWide = StringToks[0].is(tok::wide_string_literal);
+
+ hadError = false;
+
+ // Implement Translation Phase #6: concatenation of string literals
+ /// (C99 5.1.1.2p1). The common case is only one string fragment.
+ for (unsigned i = 1; i != NumStringToks; ++i) {
+ // The string could be shorter than this if it needs cleaning, but this is a
+ // reasonable bound, which is all we need.
+ SizeBound += StringToks[i].getLength()-2; // -2 for "".
+
+ // Remember maximum string piece length.
+ if (StringToks[i].getLength() > MaxTokenLength)
+ MaxTokenLength = StringToks[i].getLength();
+
+ // Remember if we see any wide strings.
+ AnyWide |= StringToks[i].is(tok::wide_string_literal);
+ }
+
+ // Include space for the null terminator.
+ ++SizeBound;
+
+ // TODO: K&R warning: "traditional C rejects string constant concatenation"
+
+ // Get the width in bytes of wchar_t. If no wchar_t strings are used, do not
+ // query the target. As such, wchar_tByteWidth is only valid if AnyWide=true.
+ wchar_tByteWidth = ~0U;
+ if (AnyWide) {
+ wchar_tByteWidth = Target.getWCharWidth();
+ assert((wchar_tByteWidth & 7) == 0 && "Assumes wchar_t is byte multiple!");
+ wchar_tByteWidth /= 8;
+ }
+
+ // The output buffer size needs to be large enough to hold wide characters.
+ // This is a worst-case assumption which basically corresponds to L"" "long".
+ if (AnyWide)
+ SizeBound *= wchar_tByteWidth;
+
+ // Size the temporary buffer to hold the result string data.
+ ResultBuf.resize(SizeBound);
+
+ // Likewise, but for each string piece.
+ llvm::SmallString<512> TokenBuf;
+ TokenBuf.resize(MaxTokenLength);
+
+ // Loop over all the strings, getting their spelling, and expanding them to
+ // wide strings as appropriate.
+ ResultPtr = &ResultBuf[0]; // Next byte to fill in.
+
+ Pascal = false;
+
+ for (unsigned i = 0, e = NumStringToks; i != e; ++i) {
+ const char *ThisTokBuf = &TokenBuf[0];
+ // Get the spelling of the token, which eliminates trigraphs, etc. We know
+ // that ThisTokBuf points to a buffer that is big enough for the whole token
+ // and 'spelled' tokens can only shrink.
+ bool StringInvalid = false;
+ unsigned ThisTokLen =
+ Lexer::getSpelling(StringToks[i], ThisTokBuf, SM, Features,
+ &StringInvalid);
+ if (StringInvalid) {
+ hadError = 1;
+ continue;
+ }
+
+ const char *ThisTokEnd = ThisTokBuf+ThisTokLen-1; // Skip end quote.
+ bool wide = false;
+ // TODO: Input character set mapping support.
+
+ // Skip L marker for wide strings.
+ if (ThisTokBuf[0] == 'L') {
+ wide = true;
+ ++ThisTokBuf;
+ }
+
+ assert(ThisTokBuf[0] == '"' && "Expected quote, lexer broken?");
+ ++ThisTokBuf;
+
+ // Check if this is a pascal string
+ if (Features.PascalStrings && ThisTokBuf + 1 != ThisTokEnd &&
+ ThisTokBuf[0] == '\\' && ThisTokBuf[1] == 'p') {
+
+ // If the \p sequence is found in the first token, we have a pascal string
+ // Otherwise, if we already have a pascal string, ignore the first \p
+ if (i == 0) {
+ ++ThisTokBuf;
+ Pascal = true;
+ } else if (Pascal)
+ ThisTokBuf += 2;
+ }
+
+ while (ThisTokBuf != ThisTokEnd) {
+ // Is this a span of non-escape characters?
+ if (ThisTokBuf[0] != '\\') {
+ const char *InStart = ThisTokBuf;
+ do {
+ ++ThisTokBuf;
+ } while (ThisTokBuf != ThisTokEnd && ThisTokBuf[0] != '\\');
+
+ // Copy the character span over.
+ unsigned Len = ThisTokBuf-InStart;
+ if (!AnyWide) {
+ memcpy(ResultPtr, InStart, Len);
+ ResultPtr += Len;
+ } else {
+ // Note: our internal rep of wide char tokens is always little-endian.
+ for (; Len; --Len, ++InStart) {
+ *ResultPtr++ = InStart[0];
+ // Add zeros at the end.
+ for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
+ *ResultPtr++ = 0;
+ }
+ }
+ continue;
+ }
+ // Is this a Universal Character Name escape?
+ if (ThisTokBuf[1] == 'u' || ThisTokBuf[1] == 'U') {
+ EncodeUCNEscape(ThisTokBuf, ThisTokEnd, ResultPtr,
+ hadError, FullSourceLoc(StringToks[i].getLocation(),SM),
+ wide, Diags, Features);
+ continue;
+ }
+ // Otherwise, this is a non-UCN escape character. Process it.
+ unsigned ResultChar =
+ ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError,
+ FullSourceLoc(StringToks[i].getLocation(), SM),
+ AnyWide, Diags, Target);
+
+ // Note: our internal rep of wide char tokens is always little-endian.
+ *ResultPtr++ = ResultChar & 0xFF;
+
+ if (AnyWide) {
+ for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
+ *ResultPtr++ = ResultChar >> i*8;
+ }
+ }
+ }
+
+ if (Pascal) {
+ ResultBuf[0] = ResultPtr-&ResultBuf[0]-1;
+ if (AnyWide)
+ ResultBuf[0] /= wchar_tByteWidth;
+
+ // Verify that pascal strings aren't too large.
+ if (GetStringLength() > 256) {
+ if (Diags)
+ Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM),
+ diag::err_pascal_string_too_long)
+ << SourceRange(StringToks[0].getLocation(),
+ StringToks[NumStringToks-1].getLocation());
+ hadError = 1;
+ return;
+ }
+ } else if (Diags) {
+ // Complain if this string literal has too many characters.
+ unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509;
+
+ if (GetNumStringChars() > MaxChars)
+ Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM),
+ diag::ext_string_too_long)
+ << GetNumStringChars() << MaxChars
+ << (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0)
+ << SourceRange(StringToks[0].getLocation(),
+ StringToks[NumStringToks-1].getLocation());
+ }
+}
+
+
+/// getOffsetOfStringByte - This function returns the offset of the
+/// specified byte of the string data represented by Token. This handles
+/// advancing over escape sequences in the string.
+unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
+ unsigned ByteNo) const {
+ // Get the spelling of the token.
+ llvm::SmallString<32> SpellingBuffer;
+ SpellingBuffer.resize(Tok.getLength());
+
+ bool StringInvalid = false;
+ const char *SpellingPtr = &SpellingBuffer[0];
+ unsigned TokLen = Lexer::getSpelling(Tok, SpellingPtr, SM, Features,
+ &StringInvalid);
+ if (StringInvalid)
+ return 0;
+
+ assert(SpellingPtr[0] != 'L' && "Doesn't handle wide strings yet");
+
+
+ const char *SpellingStart = SpellingPtr;
+ const char *SpellingEnd = SpellingPtr+TokLen;
+
+ // Skip over the leading quote.
+ assert(SpellingPtr[0] == '"' && "Should be a string literal!");
+ ++SpellingPtr;
+
+ // Skip over bytes until we find the offset we're looking for.
+ while (ByteNo) {
+ assert(SpellingPtr < SpellingEnd && "Didn't find byte offset!");
+
+ // Step over non-escapes simply.
+ if (*SpellingPtr != '\\') {
+ ++SpellingPtr;
+ --ByteNo;
+ continue;
+ }
+
+ // Otherwise, this is an escape character. Advance over it.
+ bool HadError = false;
+ ProcessCharEscape(SpellingPtr, SpellingEnd, HadError,
+ FullSourceLoc(Tok.getLocation(), SM),
+ false, Diags, Target);
+ assert(!HadError && "This method isn't valid on erroneous strings");
+ --ByteNo;
+ }
+
+ return SpellingPtr-SpellingStart;
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
new file mode 100644
index 0000000..89f6368
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp
@@ -0,0 +1,293 @@
+//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MacroArgs.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LexDiagnostic.h"
+using namespace clang;
+
+/// MacroArgs ctor function - This destroys the vector passed in.
+MacroArgs *MacroArgs::create(const MacroInfo *MI,
+ const Token *UnexpArgTokens,
+ unsigned NumToks, bool VarargsElided,
+ Preprocessor &PP) {
+ assert(MI->isFunctionLike() &&
+ "Can't have args for an object-like macro!");
+ MacroArgs **ResultEnt = 0;
+ unsigned ClosestMatch = ~0U;
+
+ // See if we have an entry with a big enough argument list to reuse on the
+ // free list. If so, reuse it.
+ for (MacroArgs **Entry = &PP.MacroArgCache; *Entry;
+ Entry = &(*Entry)->ArgCache)
+ if ((*Entry)->NumUnexpArgTokens >= NumToks &&
+ (*Entry)->NumUnexpArgTokens < ClosestMatch) {
+ ResultEnt = Entry;
+
+ // If we have an exact match, use it.
+ if ((*Entry)->NumUnexpArgTokens == NumToks)
+ break;
+ // Otherwise, use the best fit.
+ ClosestMatch = (*Entry)->NumUnexpArgTokens;
+ }
+
+ MacroArgs *Result;
+ if (ResultEnt == 0) {
+ // Allocate memory for a MacroArgs object with the lexer tokens at the end.
+ Result = (MacroArgs*)malloc(sizeof(MacroArgs) + NumToks*sizeof(Token));
+ // Construct the MacroArgs object.
+ new (Result) MacroArgs(NumToks, VarargsElided);
+ } else {
+ Result = *ResultEnt;
+ // Unlink this node from the preprocessors singly linked list.
+ *ResultEnt = Result->ArgCache;
+ Result->NumUnexpArgTokens = NumToks;
+ Result->VarargsElided = VarargsElided;
+ }
+
+ // Copy the actual unexpanded tokens to immediately after the result ptr.
+ if (NumToks)
+ memcpy(const_cast<Token*>(Result->getUnexpArgument(0)),
+ UnexpArgTokens, NumToks*sizeof(Token));
+
+ return Result;
+}
+
+/// destroy - Destroy and deallocate the memory for this object.
+///
+void MacroArgs::destroy(Preprocessor &PP) {
+ StringifiedArgs.clear();
+
+ // Don't clear PreExpArgTokens, just clear the entries. Clearing the entries
+ // would deallocate the element vectors.
+ for (unsigned i = 0, e = PreExpArgTokens.size(); i != e; ++i)
+ PreExpArgTokens[i].clear();
+
+ // Add this to the preprocessor's free list.
+ ArgCache = PP.MacroArgCache;
+ PP.MacroArgCache = this;
+}
+
+/// deallocate - This should only be called by the Preprocessor when managing
+/// its freelist.
+MacroArgs *MacroArgs::deallocate() {
+ MacroArgs *Next = ArgCache;
+
+ // Run the dtor to deallocate the vectors.
+ this->~MacroArgs();
+ // Release the memory for the object.
+ free(this);
+
+ return Next;
+}
+
+
+/// getArgLength - Given a pointer to an expanded or unexpanded argument,
+/// return the number of tokens, not counting the EOF, that make up the
+/// argument.
+unsigned MacroArgs::getArgLength(const Token *ArgPtr) {
+ unsigned NumArgTokens = 0;
+ for (; ArgPtr->isNot(tok::eof); ++ArgPtr)
+ ++NumArgTokens;
+ return NumArgTokens;
+}
+
+
+/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
+///
+const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
+ // The unexpanded argument tokens start immediately after the MacroArgs object
+ // in memory.
+ const Token *Start = (const Token *)(this+1);
+ const Token *Result = Start;
+ // Scan to find Arg.
+ for (; Arg; ++Result) {
+ assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
+ if (Result->is(tok::eof))
+ --Arg;
+ }
+ assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
+ return Result;
+}
+
+
+/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
+/// by pre-expansion, return false. Otherwise, conservatively return true.
+bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok,
+ Preprocessor &PP) const {
+ // If there are no identifiers in the argument list, or if the identifiers are
+ // known to not be macros, pre-expansion won't modify it.
+ for (; ArgTok->isNot(tok::eof); ++ArgTok)
+ if (IdentifierInfo *II = ArgTok->getIdentifierInfo()) {
+ if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled())
+ // Return true even though the macro could be a function-like macro
+ // without a following '(' token.
+ return true;
+ }
+ return false;
+}
+
+/// getPreExpArgument - Return the pre-expanded form of the specified
+/// argument.
+const std::vector<Token> &
+MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI,
+ Preprocessor &PP) {
+ assert(Arg < MI->getNumArgs() && "Invalid argument number!");
+
+ // If we have already computed this, return it.
+ if (PreExpArgTokens.size() < MI->getNumArgs())
+ PreExpArgTokens.resize(MI->getNumArgs());
+
+ std::vector<Token> &Result = PreExpArgTokens[Arg];
+ if (!Result.empty()) return Result;
+
+ const Token *AT = getUnexpArgument(Arg);
+ unsigned NumToks = getArgLength(AT)+1; // Include the EOF.
+
+ // Otherwise, we have to pre-expand this argument, populating Result. To do
+ // this, we set up a fake TokenLexer to lex from the unexpanded argument
+ // list. With this installed, we lex expanded tokens until we hit the EOF
+ // token at the end of the unexp list.
+ PP.EnterTokenStream(AT, NumToks, false /*disable expand*/,
+ false /*owns tokens*/);
+
+ // Lex all of the macro-expanded tokens into Result.
+ do {
+ Result.push_back(Token());
+ Token &Tok = Result.back();
+ PP.Lex(Tok);
+ } while (Result.back().isNot(tok::eof));
+
+ // Pop the token stream off the top of the stack. We know that the internal
+ // pointer inside of it is to the "end" of the token stream, but the stack
+ // will not otherwise be popped until the next token is lexed. The problem is
+ // that the token may be lexed sometime after the vector of tokens itself is
+ // destroyed, which would be badness.
+ PP.RemoveTopOfLexerStack();
+ return Result;
+}
+
+
+/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
+/// tokens into the literal string token that should be produced by the C #
+/// preprocessor operator. If Charify is true, then it should be turned into
+/// a character literal for the Microsoft charize (#@) extension.
+///
+Token MacroArgs::StringifyArgument(const Token *ArgToks,
+ Preprocessor &PP, bool Charify) {
+ Token Tok;
+ Tok.startToken();
+ Tok.setKind(Charify ? tok::char_constant : tok::string_literal);
+
+ const Token *ArgTokStart = ArgToks;
+
+ // Stringify all the tokens.
+ llvm::SmallString<128> Result;
+ Result += "\"";
+
+ bool isFirst = true;
+ for (; ArgToks->isNot(tok::eof); ++ArgToks) {
+ const Token &Tok = *ArgToks;
+ if (!isFirst && (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()))
+ Result += ' ';
+ isFirst = false;
+
+ // If this is a string or character constant, escape the token as specified
+ // by 6.10.3.2p2.
+ if (Tok.is(tok::string_literal) || // "foo"
+ Tok.is(tok::wide_string_literal) || // L"foo"
+ Tok.is(tok::char_constant)) { // 'x' and L'x'.
+ bool Invalid = false;
+ std::string TokStr = PP.getSpelling(Tok, &Invalid);
+ if (!Invalid) {
+ std::string Str = Lexer::Stringify(TokStr);
+ Result.append(Str.begin(), Str.end());
+ }
+ } else {
+ // Otherwise, just append the token. Do some gymnastics to get the token
+ // in place and avoid copies where possible.
+ unsigned CurStrLen = Result.size();
+ Result.resize(CurStrLen+Tok.getLength());
+ const char *BufPtr = &Result[CurStrLen];
+ bool Invalid = false;
+ unsigned ActualTokLen = PP.getSpelling(Tok, BufPtr, &Invalid);
+
+ if (!Invalid) {
+ // If getSpelling returned a pointer to an already uniqued version of
+ // the string instead of filling in BufPtr, memcpy it onto our string.
+ if (BufPtr != &Result[CurStrLen])
+ memcpy(&Result[CurStrLen], BufPtr, ActualTokLen);
+
+ // If the token was dirty, the spelling may be shorter than the token.
+ if (ActualTokLen != Tok.getLength())
+ Result.resize(CurStrLen+ActualTokLen);
+ }
+ }
+ }
+
+ // If the last character of the string is a \, and if it isn't escaped, this
+ // is an invalid string literal, diagnose it as specified in C99.
+ if (Result.back() == '\\') {
+ // Count the number of consequtive \ characters. If even, then they are
+ // just escaped backslashes, otherwise it's an error.
+ unsigned FirstNonSlash = Result.size()-2;
+ // Guaranteed to find the starting " if nothing else.
+ while (Result[FirstNonSlash] == '\\')
+ --FirstNonSlash;
+ if ((Result.size()-1-FirstNonSlash) & 1) {
+ // Diagnose errors for things like: #define F(X) #X / F(\)
+ PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal);
+ Result.pop_back(); // remove one of the \'s.
+ }
+ }
+ Result += '"';
+
+ // If this is the charify operation and the result is not a legal character
+ // constant, diagnose it.
+ if (Charify) {
+ // First step, turn double quotes into single quotes:
+ Result[0] = '\'';
+ Result[Result.size()-1] = '\'';
+
+ // Check for bogus character.
+ bool isBad = false;
+ if (Result.size() == 3)
+ isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above.
+ else
+ isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x'
+
+ if (isBad) {
+ PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify);
+ Result = "' '"; // Use something arbitrary, but legal.
+ }
+ }
+
+ PP.CreateString(&Result[0], Result.size(), Tok);
+ return Tok;
+}
+
+/// getStringifiedArgument - Compute, cache, and return the specified argument
+/// that has been 'stringified' as required by the # operator.
+const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo,
+ Preprocessor &PP) {
+ assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!");
+ if (StringifiedArgs.empty()) {
+ StringifiedArgs.resize(getNumArguments());
+ memset(&StringifiedArgs[0], 0,
+ sizeof(StringifiedArgs[0])*getNumArguments());
+ }
+ if (StringifiedArgs[ArgNo].isNot(tok::string_literal))
+ StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP);
+ return StringifiedArgs[ArgNo];
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.h b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.h
new file mode 100644
index 0000000..6ff4856
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.h
@@ -0,0 +1,119 @@
+//===--- MacroArgs.h - Formal argument info for Macros ----------*- 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 MacroArgs interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_MACROARGS_H
+#define LLVM_CLANG_MACROARGS_H
+
+#include <vector>
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class Token;
+
+/// MacroArgs - An instance of this class captures information about
+/// the formal arguments specified to a function-like macro invocation.
+class MacroArgs {
+ /// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
+ /// arguments. All of the actual argument tokens are allocated immediately
+ /// after the MacroArgs object in memory. This is all of the arguments
+ /// concatenated together, with 'EOF' markers at the end of each argument.
+ unsigned NumUnexpArgTokens;
+
+ /// VarargsElided - True if this is a C99 style varargs macro invocation and
+ /// there was no argument specified for the "..." argument. If the argument
+ /// was specified (even empty) or this isn't a C99 style varargs function, or
+ /// if in strict mode and the C99 varargs macro had only a ... argument, this
+ /// is false.
+ bool VarargsElided;
+
+ /// PreExpArgTokens - Pre-expanded tokens for arguments that need them. Empty
+ /// if not yet computed. This includes the EOF marker at the end of the
+ /// stream.
+ std::vector<std::vector<Token> > PreExpArgTokens;
+
+ /// StringifiedArgs - This contains arguments in 'stringified' form. If the
+ /// stringified form of an argument has not yet been computed, this is empty.
+ std::vector<Token> StringifiedArgs;
+
+ /// ArgCache - This is a linked list of MacroArgs objects that the
+ /// Preprocessor owns which we use to avoid thrashing malloc/free.
+ MacroArgs *ArgCache;
+
+ MacroArgs(unsigned NumToks, bool varargsElided)
+ : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), ArgCache(0) {}
+ ~MacroArgs() {}
+public:
+ /// MacroArgs ctor function - Create a new MacroArgs object with the specified
+ /// macro and argument info.
+ static MacroArgs *create(const MacroInfo *MI,
+ const Token *UnexpArgTokens,
+ unsigned NumArgTokens, bool VarargsElided,
+ Preprocessor &PP);
+
+ /// destroy - Destroy and deallocate the memory for this object.
+ ///
+ void destroy(Preprocessor &PP);
+
+ /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
+ /// by pre-expansion, return false. Otherwise, conservatively return true.
+ bool ArgNeedsPreexpansion(const Token *ArgTok, Preprocessor &PP) const;
+
+ /// getUnexpArgument - Return a pointer to the first token of the unexpanded
+ /// token list for the specified formal.
+ ///
+ const Token *getUnexpArgument(unsigned Arg) const;
+
+ /// getArgLength - Given a pointer to an expanded or unexpanded argument,
+ /// return the number of tokens, not counting the EOF, that make up the
+ /// argument.
+ static unsigned getArgLength(const Token *ArgPtr);
+
+ /// getPreExpArgument - Return the pre-expanded form of the specified
+ /// argument.
+ const std::vector<Token> &
+ getPreExpArgument(unsigned Arg, const MacroInfo *MI, Preprocessor &PP);
+
+ /// getStringifiedArgument - Compute, cache, and return the specified argument
+ /// that has been 'stringified' as required by the # operator.
+ const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
+
+ /// getNumArguments - Return the number of arguments passed into this macro
+ /// invocation.
+ unsigned getNumArguments() const { return NumUnexpArgTokens; }
+
+
+ /// isVarargsElidedUse - Return true if this is a C99 style varargs macro
+ /// invocation and there was no argument specified for the "..." argument. If
+ /// the argument was specified (even empty) or this isn't a C99 style varargs
+ /// function, or if in strict mode and the C99 varargs macro had only a ...
+ /// argument, this returns false.
+ bool isVarargsElidedUse() const { return VarargsElided; }
+
+ /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
+ /// tokens into the literal string token that should be produced by the C #
+ /// preprocessor operator. If Charify is true, then it should be turned into
+ /// a character literal for the Microsoft charize (#@) extension.
+ ///
+ static Token StringifyArgument(const Token *ArgToks,
+ Preprocessor &PP, bool Charify = false);
+
+
+ /// deallocate - This should only be called by the Preprocessor when managing
+ /// its freelist.
+ MacroArgs *deallocate();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
new file mode 100644
index 0000000..c819011
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
@@ -0,0 +1,95 @@
+//===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MacroInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
+ IsFunctionLike = false;
+ IsC99Varargs = false;
+ IsGNUVarargs = false;
+ IsBuiltinMacro = false;
+ IsFromAST = false;
+ IsDisabled = false;
+ IsUsed = false;
+ IsAllowRedefinitionsWithoutWarning = false;
+ IsWarnIfUnused = false;
+
+ ArgumentList = 0;
+ NumArguments = 0;
+}
+
+MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
+ Location = MI.Location;
+ EndLocation = MI.EndLocation;
+ ReplacementTokens = MI.ReplacementTokens;
+ IsFunctionLike = MI.IsFunctionLike;
+ IsC99Varargs = MI.IsC99Varargs;
+ IsGNUVarargs = MI.IsGNUVarargs;
+ IsBuiltinMacro = MI.IsBuiltinMacro;
+ IsFromAST = MI.IsFromAST;
+ IsDisabled = MI.IsDisabled;
+ IsUsed = MI.IsUsed;
+ IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
+ ArgumentList = 0;
+ NumArguments = 0;
+ setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
+}
+
+/// isIdenticalTo - Return true if the specified macro definition is equal to
+/// this macro in spelling, arguments, and whitespace. This is used to emit
+/// duplicate definition warnings. This implements the rules in C99 6.10.3.
+///
+bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
+ // Check # tokens in replacement, number of args, and various flags all match.
+ if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
+ getNumArgs() != Other.getNumArgs() ||
+ isFunctionLike() != Other.isFunctionLike() ||
+ isC99Varargs() != Other.isC99Varargs() ||
+ isGNUVarargs() != Other.isGNUVarargs())
+ return false;
+
+ // Check arguments.
+ for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
+ I != E; ++I, ++OI)
+ if (*I != *OI) return false;
+
+ // Check all the tokens.
+ for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
+ const Token &A = ReplacementTokens[i];
+ const Token &B = Other.ReplacementTokens[i];
+ if (A.getKind() != B.getKind())
+ return false;
+
+ // If this isn't the first first token, check that the whitespace and
+ // start-of-line characteristics match.
+ if (i != 0 &&
+ (A.isAtStartOfLine() != B.isAtStartOfLine() ||
+ A.hasLeadingSpace() != B.hasLeadingSpace()))
+ return false;
+
+ // If this is an identifier, it is easy.
+ if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
+ if (A.getIdentifierInfo() != B.getIdentifierInfo())
+ return false;
+ continue;
+ }
+
+ // Otherwise, check the spelling.
+ if (PP.getSpelling(A) != PP.getSpelling(B))
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp b/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp
new file mode 100644
index 0000000..3310659
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp
@@ -0,0 +1,112 @@
+//===--- PPCaching.cpp - Handle caching lexed tokens ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements pieces of the Preprocessor interface that manage the
+// caching of lexed tokens.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+/// EnableBacktrackAtThisPos - From the point that this method is called, and
+/// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+/// keeps track of the lexed tokens so that a subsequent Backtrack() call will
+/// make the Preprocessor re-lex the same tokens.
+///
+/// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
+/// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
+/// be combined with the EnableBacktrackAtThisPos calls in reverse order.
+void Preprocessor::EnableBacktrackAtThisPos() {
+ BacktrackPositions.push_back(CachedLexPos);
+ EnterCachingLexMode();
+}
+
+/// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
+void Preprocessor::CommitBacktrackedTokens() {
+ assert(!BacktrackPositions.empty()
+ && "EnableBacktrackAtThisPos was not called!");
+ BacktrackPositions.pop_back();
+}
+
+/// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
+/// EnableBacktrackAtThisPos() was previously called.
+void Preprocessor::Backtrack() {
+ assert(!BacktrackPositions.empty()
+ && "EnableBacktrackAtThisPos was not called!");
+ CachedLexPos = BacktrackPositions.back();
+ BacktrackPositions.pop_back();
+}
+
+void Preprocessor::CachingLex(Token &Result) {
+ if (!InCachingLexMode())
+ return;
+
+ if (CachedLexPos < CachedTokens.size()) {
+ Result = CachedTokens[CachedLexPos++];
+ return;
+ }
+
+ ExitCachingLexMode();
+ Lex(Result);
+
+ if (!isBacktrackEnabled()) {
+ // All cached tokens were consumed.
+ CachedTokens.clear();
+ CachedLexPos = 0;
+ return;
+ }
+
+ // Cache the lexed token.
+ EnterCachingLexMode();
+ CachedTokens.push_back(Result);
+ ++CachedLexPos;
+}
+
+void Preprocessor::EnterCachingLexMode() {
+ if (InCachingLexMode())
+ return;
+
+ PushIncludeMacroStack();
+}
+
+
+const Token &Preprocessor::PeekAhead(unsigned N) {
+ assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
+ ExitCachingLexMode();
+ for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
+ CachedTokens.push_back(Token());
+ Lex(CachedTokens.back());
+ }
+ EnterCachingLexMode();
+ return CachedTokens.back();
+}
+
+void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ assert(CachedLexPos != 0 && "Expected to have some cached tokens");
+ assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc()
+ && "The annotation should be until the most recent cached token");
+
+ // Start from the end of the cached tokens list and look for the token
+ // that is the beginning of the annotation token.
+ for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
+ CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
+ if (AnnotBegin->getLocation() == Tok.getLocation()) {
+ assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) &&
+ "The backtrack pos points inside the annotated tokens!");
+ // Replace the cached tokens with the single annotation token.
+ if (i < CachedLexPos)
+ CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos);
+ *AnnotBegin = Tok;
+ CachedLexPos = i;
+ return;
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
new file mode 100644
index 0000000..0f0d25b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -0,0 +1,1792 @@
+//===--- PPDirectives.cpp - Directive Handling for Preprocessor -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements # directive processing for the Preprocessor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APInt.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Utility Methods for Preprocessor Directive Handling.
+//===----------------------------------------------------------------------===//
+
+MacroInfo *Preprocessor::AllocateMacroInfo() {
+ MacroInfoChain *MIChain;
+
+ if (MICache) {
+ MIChain = MICache;
+ MICache = MICache->Next;
+ }
+ else {
+ MIChain = BP.Allocate<MacroInfoChain>();
+ }
+
+ MIChain->Next = MIChainHead;
+ MIChain->Prev = 0;
+ if (MIChainHead)
+ MIChainHead->Prev = MIChain;
+ MIChainHead = MIChain;
+
+ return &(MIChain->MI);
+}
+
+MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
+ MacroInfo *MI = AllocateMacroInfo();
+ new (MI) MacroInfo(L);
+ return MI;
+}
+
+MacroInfo *Preprocessor::CloneMacroInfo(const MacroInfo &MacroToClone) {
+ MacroInfo *MI = AllocateMacroInfo();
+ new (MI) MacroInfo(MacroToClone, BP);
+ return MI;
+}
+
+/// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
+/// be reused for allocating new MacroInfo objects.
+void Preprocessor::ReleaseMacroInfo(MacroInfo *MI) {
+ MacroInfoChain *MIChain = (MacroInfoChain*) MI;
+ if (MacroInfoChain *Prev = MIChain->Prev) {
+ MacroInfoChain *Next = MIChain->Next;
+ Prev->Next = Next;
+ if (Next)
+ Next->Prev = Prev;
+ }
+ else {
+ assert(MIChainHead == MIChain);
+ MIChainHead = MIChain->Next;
+ MIChainHead->Prev = 0;
+ }
+ MIChain->Next = MICache;
+ MICache = MIChain;
+
+ MI->Destroy();
+}
+
+/// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
+/// current line until the tok::eom token is found.
+void Preprocessor::DiscardUntilEndOfDirective() {
+ Token Tmp;
+ do {
+ LexUnexpandedToken(Tmp);
+ } while (Tmp.isNot(tok::eom));
+}
+
+/// ReadMacroName - Lex and validate a macro name, which occurs after a
+/// #define or #undef. This sets the token kind to eom and discards the rest
+/// of the macro line if the macro name is invalid. isDefineUndef is 1 if
+/// this is due to a a #define, 2 if #undef directive, 0 if it is something
+/// else (e.g. #ifdef).
+void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) {
+ // Read the token, don't allow macro expansion on it.
+ LexUnexpandedToken(MacroNameTok);
+
+ if (MacroNameTok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteMacroName(isDefineUndef == 1);
+ LexUnexpandedToken(MacroNameTok);
+ return;
+ }
+
+ // Missing macro name?
+ if (MacroNameTok.is(tok::eom)) {
+ Diag(MacroNameTok, diag::err_pp_missing_macro_name);
+ return;
+ }
+
+ IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
+ if (II == 0) {
+ bool Invalid = false;
+ std::string Spelling = getSpelling(MacroNameTok, &Invalid);
+ if (Invalid)
+ return;
+
+ const IdentifierInfo &Info = Identifiers.get(Spelling);
+ if (Info.isCPlusPlusOperatorKeyword())
+ // C++ 2.5p2: Alternative tokens behave the same as its primary token
+ // except for their spellings.
+ Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name) << Spelling;
+ else
+ Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+ // Fall through on error.
+ } else if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
+ // Error if defining "defined": C99 6.10.8.4.
+ Diag(MacroNameTok, diag::err_defined_macro_name);
+ } else if (isDefineUndef && II->hasMacroDefinition() &&
+ getMacroInfo(II)->isBuiltinMacro()) {
+ // Error if defining "__LINE__" and other builtins: C99 6.10.8.4.
+ if (isDefineUndef == 1)
+ Diag(MacroNameTok, diag::pp_redef_builtin_macro);
+ else
+ Diag(MacroNameTok, diag::pp_undef_builtin_macro);
+ } else {
+ // Okay, we got a good identifier node. Return it.
+ return;
+ }
+
+ // Invalid macro name, read and discard the rest of the line. Then set the
+ // token kind to tok::eom.
+ MacroNameTok.setKind(tok::eom);
+ return DiscardUntilEndOfDirective();
+}
+
+/// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If
+/// not, emit a diagnostic and consume up until the eom. If EnableMacros is
+/// true, then we consider macros that expand to zero tokens as being ok.
+void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
+ Token Tmp;
+ // Lex unexpanded tokens for most directives: macros might expand to zero
+ // tokens, causing us to miss diagnosing invalid lines. Some directives (like
+ // #line) allow empty macros.
+ if (EnableMacros)
+ Lex(Tmp);
+ else
+ LexUnexpandedToken(Tmp);
+
+ // There should be no tokens after the directive, but we allow them as an
+ // extension.
+ while (Tmp.is(tok::comment)) // Skip comments in -C mode.
+ LexUnexpandedToken(Tmp);
+
+ if (Tmp.isNot(tok::eom)) {
+ // Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89,
+ // because it is more trouble than it is worth to insert /**/ and check that
+ // there is no /**/ in the range also.
+ FixItHint Hint;
+ if (Features.GNUMode || Features.C99 || Features.CPlusPlus)
+ Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//");
+ Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
+ DiscardUntilEndOfDirective();
+ }
+}
+
+
+
+/// SkipExcludedConditionalBlock - We just read a #if or related directive and
+/// decided that the subsequent tokens are in the #if'd out portion of the
+/// file. Lex the rest of the file, until we see an #endif. If
+/// FoundNonSkipPortion is true, then we have already emitted code for part of
+/// this #if directive, so #else/#elif blocks should never be entered. If ElseOk
+/// is true, then #else directives are ok, if not, then we have already seen one
+/// so a #else directive is a duplicate. When this returns, the caller can lex
+/// the first valid token.
+void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion,
+ bool FoundElse) {
+ ++NumSkipped;
+ assert(CurTokenLexer == 0 && CurPPLexer && "Lexing a macro, not a file?");
+
+ CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
+ FoundNonSkipPortion, FoundElse);
+
+ if (CurPTHLexer) {
+ PTHSkipExcludedConditionalBlock();
+ return;
+ }
+
+ // Enter raw mode to disable identifier lookup (and thus macro expansion),
+ // disabling warnings, etc.
+ CurPPLexer->LexingRawMode = true;
+ Token Tok;
+ while (1) {
+ CurLexer->Lex(Tok);
+
+ if (Tok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteInConditionalExclusion();
+ continue;
+ }
+
+ // If this is the end of the buffer, we have an error.
+ if (Tok.is(tok::eof)) {
+ // Emit errors for each unterminated conditional on the stack, including
+ // the current one.
+ while (!CurPPLexer->ConditionalStack.empty()) {
+ if (!isCodeCompletionFile(Tok.getLocation()))
+ Diag(CurPPLexer->ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
+ CurPPLexer->ConditionalStack.pop_back();
+ }
+
+ // Just return and let the caller lex after this #include.
+ break;
+ }
+
+ // If this token is not a preprocessor directive, just skip it.
+ if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine())
+ continue;
+
+ // We just parsed a # character at the start of a line, so we're in
+ // directive mode. Tell the lexer this so any newlines we see will be
+ // converted into an EOM token (this terminates the macro).
+ CurPPLexer->ParsingPreprocessorDirective = true;
+ if (CurLexer) CurLexer->SetCommentRetentionState(false);
+
+
+ // Read the next token, the directive flavor.
+ LexUnexpandedToken(Tok);
+
+ // If this isn't an identifier directive (e.g. is "# 1\n" or "#\n", or
+ // something bogus), skip it.
+ if (Tok.isNot(tok::raw_identifier)) {
+ CurPPLexer->ParsingPreprocessorDirective = false;
+ // Restore comment saving mode.
+ if (CurLexer) CurLexer->SetCommentRetentionState(KeepComments);
+ continue;
+ }
+
+ // If the first letter isn't i or e, it isn't intesting to us. We know that
+ // this is safe in the face of spelling differences, because there is no way
+ // to spell an i/e in a strange way that is another letter. Skipping this
+ // allows us to avoid looking up the identifier info for #define/#undef and
+ // other common directives.
+ const char *RawCharData = Tok.getRawIdentifierData();
+
+ char FirstChar = RawCharData[0];
+ if (FirstChar >= 'a' && FirstChar <= 'z' &&
+ FirstChar != 'i' && FirstChar != 'e') {
+ CurPPLexer->ParsingPreprocessorDirective = false;
+ // Restore comment saving mode.
+ if (CurLexer) CurLexer->SetCommentRetentionState(KeepComments);
+ continue;
+ }
+
+ // Get the identifier name without trigraphs or embedded newlines. Note
+ // that we can't use Tok.getIdentifierInfo() because its lookup is disabled
+ // when skipping.
+ char DirectiveBuf[20];
+ llvm::StringRef Directive;
+ if (!Tok.needsCleaning() && Tok.getLength() < 20) {
+ Directive = llvm::StringRef(RawCharData, Tok.getLength());
+ } else {
+ std::string DirectiveStr = getSpelling(Tok);
+ unsigned IdLen = DirectiveStr.size();
+ if (IdLen >= 20) {
+ CurPPLexer->ParsingPreprocessorDirective = false;
+ // Restore comment saving mode.
+ if (CurLexer) CurLexer->SetCommentRetentionState(KeepComments);
+ continue;
+ }
+ memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
+ Directive = llvm::StringRef(DirectiveBuf, IdLen);
+ }
+
+ if (Directive.startswith("if")) {
+ llvm::StringRef Sub = Directive.substr(2);
+ if (Sub.empty() || // "if"
+ Sub == "def" || // "ifdef"
+ Sub == "ndef") { // "ifndef"
+ // We know the entire #if/#ifdef/#ifndef block will be skipped, don't
+ // bother parsing the condition.
+ DiscardUntilEndOfDirective();
+ CurPPLexer->pushConditionalLevel(Tok.getLocation(), /*wasskipping*/true,
+ /*foundnonskip*/false,
+ /*foundelse*/false);
+
+ if (Callbacks)
+ Callbacks->Endif();
+ }
+ } else if (Directive[0] == 'e') {
+ llvm::StringRef Sub = Directive.substr(1);
+ if (Sub == "ndif") { // "endif"
+ CheckEndOfDirective("endif");
+ PPConditionalInfo CondInfo;
+ CondInfo.WasSkipping = true; // Silence bogus warning.
+ bool InCond = CurPPLexer->popConditionalLevel(CondInfo);
+ (void)InCond; // Silence warning in no-asserts mode.
+ assert(!InCond && "Can't be skipping if not in a conditional!");
+
+ // If we popped the outermost skipping block, we're done skipping!
+ if (!CondInfo.WasSkipping)
+ break;
+ } else if (Sub == "lse") { // "else".
+ // #else directive in a skipping conditional. If not in some other
+ // skipping conditional, and if #else hasn't already been seen, enter it
+ // as a non-skipping conditional.
+ DiscardUntilEndOfDirective(); // C99 6.10p4.
+ PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
+
+ // If this is a #else with a #else before it, report the error.
+ if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_else_after_else);
+
+ // Note that we've seen a #else in this conditional.
+ CondInfo.FoundElse = true;
+
+ if (Callbacks)
+ Callbacks->Else();
+
+ // If the conditional is at the top level, and the #if block wasn't
+ // entered, enter the #else block now.
+ if (!CondInfo.WasSkipping && !CondInfo.FoundNonSkip) {
+ CondInfo.FoundNonSkip = true;
+ break;
+ }
+ } else if (Sub == "lif") { // "elif".
+ PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
+
+ bool ShouldEnter;
+ const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
+ // If this is in a skipping block or if we're already handled this #if
+ // block, don't bother parsing the condition.
+ if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {
+ DiscardUntilEndOfDirective();
+ ShouldEnter = false;
+ } else {
+ // Restore the value of LexingRawMode so that identifiers are
+ // looked up, etc, inside the #elif expression.
+ assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
+ CurPPLexer->LexingRawMode = false;
+ IdentifierInfo *IfNDefMacro = 0;
+ ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
+ CurPPLexer->LexingRawMode = true;
+ }
+ const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
+
+ // If this is a #elif with a #else before it, report the error.
+ if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else);
+
+ if (Callbacks)
+ Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd));
+
+ // If this condition is true, enter it!
+ if (ShouldEnter) {
+ CondInfo.FoundNonSkip = true;
+ break;
+ }
+ }
+ }
+
+ CurPPLexer->ParsingPreprocessorDirective = false;
+ // Restore comment saving mode.
+ if (CurLexer) CurLexer->SetCommentRetentionState(KeepComments);
+ }
+
+ // Finally, if we are out of the conditional (saw an #endif or ran off the end
+ // of the file, just stop skipping and return to lexing whatever came after
+ // the #if block.
+ CurPPLexer->LexingRawMode = false;
+}
+
+void Preprocessor::PTHSkipExcludedConditionalBlock() {
+
+ while (1) {
+ assert(CurPTHLexer);
+ assert(CurPTHLexer->LexingRawMode == false);
+
+ // Skip to the next '#else', '#elif', or #endif.
+ if (CurPTHLexer->SkipBlock()) {
+ // We have reached an #endif. Both the '#' and 'endif' tokens
+ // have been consumed by the PTHLexer. Just pop off the condition level.
+ PPConditionalInfo CondInfo;
+ bool InCond = CurPTHLexer->popConditionalLevel(CondInfo);
+ (void)InCond; // Silence warning in no-asserts mode.
+ assert(!InCond && "Can't be skipping if not in a conditional!");
+ break;
+ }
+
+ // We have reached a '#else' or '#elif'. Lex the next token to get
+ // the directive flavor.
+ Token Tok;
+ LexUnexpandedToken(Tok);
+
+ // We can actually look up the IdentifierInfo here since we aren't in
+ // raw mode.
+ tok::PPKeywordKind K = Tok.getIdentifierInfo()->getPPKeywordID();
+
+ if (K == tok::pp_else) {
+ // #else: Enter the else condition. We aren't in a nested condition
+ // since we skip those. We're always in the one matching the last
+ // blocked we skipped.
+ PPConditionalInfo &CondInfo = CurPTHLexer->peekConditionalLevel();
+ // Note that we've seen a #else in this conditional.
+ CondInfo.FoundElse = true;
+
+ // If the #if block wasn't entered then enter the #else block now.
+ if (!CondInfo.FoundNonSkip) {
+ CondInfo.FoundNonSkip = true;
+
+ // Scan until the eom token.
+ CurPTHLexer->ParsingPreprocessorDirective = true;
+ DiscardUntilEndOfDirective();
+ CurPTHLexer->ParsingPreprocessorDirective = false;
+
+ break;
+ }
+
+ // Otherwise skip this block.
+ continue;
+ }
+
+ assert(K == tok::pp_elif);
+ PPConditionalInfo &CondInfo = CurPTHLexer->peekConditionalLevel();
+
+ // If this is a #elif with a #else before it, report the error.
+ if (CondInfo.FoundElse)
+ Diag(Tok, diag::pp_err_elif_after_else);
+
+ // If this is in a skipping block or if we're already handled this #if
+ // block, don't bother parsing the condition. We just skip this block.
+ if (CondInfo.FoundNonSkip)
+ continue;
+
+ // Evaluate the condition of the #elif.
+ IdentifierInfo *IfNDefMacro = 0;
+ CurPTHLexer->ParsingPreprocessorDirective = true;
+ bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
+ CurPTHLexer->ParsingPreprocessorDirective = false;
+
+ // If this condition is true, enter it!
+ if (ShouldEnter) {
+ CondInfo.FoundNonSkip = true;
+ break;
+ }
+
+ // Otherwise, skip this block and go to the next one.
+ continue;
+ }
+}
+
+/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+/// return null on failure. isAngled indicates whether the file reference is
+/// for system #include's or not (i.e. using <> instead of "").
+const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename,
+ bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir) {
+ // If the header lookup mechanism may be relative to the current file, pass in
+ // info about where the current file is.
+ const FileEntry *CurFileEnt = 0;
+ if (!FromDir) {
+ FileID FID = getCurrentFileLexer()->getFileID();
+ CurFileEnt = SourceMgr.getFileEntryForID(FID);
+
+ // If there is no file entry associated with this file, it must be the
+ // predefines buffer. Any other file is not lexed with a normal lexer, so
+ // it won't be scanned for preprocessor directives. If we have the
+ // predefines buffer, resolve #include references (which come from the
+ // -include command line argument) as if they came from the main file, this
+ // affects file lookup etc.
+ if (CurFileEnt == 0) {
+ FID = SourceMgr.getMainFileID();
+ CurFileEnt = SourceMgr.getFileEntryForID(FID);
+ }
+ }
+
+ // Do a standard file entry lookup.
+ CurDir = CurDirLookup;
+ const FileEntry *FE =
+ HeaderInfo.LookupFile(Filename, isAngled, FromDir, CurDir, CurFileEnt);
+ if (FE) return FE;
+
+ // Otherwise, see if this is a subframework header. If so, this is relative
+ // to one of the headers on the #include stack. Walk the list of the current
+ // headers on the #include stack and pass them to HeaderInfo.
+ if (IsFileLexer()) {
+ if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
+ if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt)))
+ return FE;
+ }
+
+ for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
+ IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
+ if (IsFileLexer(ISEntry)) {
+ if ((CurFileEnt =
+ SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID())))
+ if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt)))
+ return FE;
+ }
+ }
+
+ // Otherwise, we really couldn't find the file.
+ return 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Directive Handling.
+//===----------------------------------------------------------------------===//
+
+/// HandleDirective - This callback is invoked when the lexer sees a # token
+/// at the start of a line. This consumes the directive, modifies the
+/// lexer/preprocessor state, and advances the lexer(s) so that the next token
+/// read is the correct one.
+void Preprocessor::HandleDirective(Token &Result) {
+ // FIXME: Traditional: # with whitespace before it not recognized by K&R?
+
+ // We just parsed a # character at the start of a line, so we're in directive
+ // mode. Tell the lexer this so any newlines we see will be converted into an
+ // EOM token (which terminates the directive).
+ CurPPLexer->ParsingPreprocessorDirective = true;
+
+ ++NumDirectives;
+
+ // We are about to read a token. For the multiple-include optimization FA to
+ // work, we have to remember if we had read any tokens *before* this
+ // pp-directive.
+ bool ReadAnyTokensBeforeDirective =CurPPLexer->MIOpt.getHasReadAnyTokensVal();
+
+ // Save the '#' token in case we need to return it later.
+ Token SavedHash = Result;
+
+ // Read the next token, the directive flavor. This isn't expanded due to
+ // C99 6.10.3p8.
+ LexUnexpandedToken(Result);
+
+ // C99 6.10.3p11: Is this preprocessor directive in macro invocation? e.g.:
+ // #define A(x) #x
+ // A(abc
+ // #warning blah
+ // def)
+ // If so, the user is relying on non-portable behavior, emit a diagnostic.
+ if (InMacroArgs)
+ Diag(Result, diag::ext_embedded_directive);
+
+TryAgain:
+ switch (Result.getKind()) {
+ case tok::eom:
+ return; // null directive.
+ case tok::comment:
+ // Handle stuff like "# /*foo*/ define X" in -E -C mode.
+ LexUnexpandedToken(Result);
+ goto TryAgain;
+ case tok::code_completion:
+ if (CodeComplete)
+ CodeComplete->CodeCompleteDirective(
+ CurPPLexer->getConditionalStackDepth() > 0);
+ return;
+ case tok::numeric_constant: // # 7 GNU line marker directive.
+ if (getLangOptions().AsmPreprocessor)
+ break; // # 4 is not a preprocessor directive in .S files.
+ return HandleDigitDirective(Result);
+ default:
+ IdentifierInfo *II = Result.getIdentifierInfo();
+ if (II == 0) break; // Not an identifier.
+
+ // Ask what the preprocessor keyword ID is.
+ switch (II->getPPKeywordID()) {
+ default: break;
+ // C99 6.10.1 - Conditional Inclusion.
+ case tok::pp_if:
+ return HandleIfDirective(Result, ReadAnyTokensBeforeDirective);
+ case tok::pp_ifdef:
+ return HandleIfdefDirective(Result, false, true/*not valid for miopt*/);
+ case tok::pp_ifndef:
+ return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective);
+ case tok::pp_elif:
+ return HandleElifDirective(Result);
+ case tok::pp_else:
+ return HandleElseDirective(Result);
+ case tok::pp_endif:
+ return HandleEndifDirective(Result);
+
+ // C99 6.10.2 - Source File Inclusion.
+ case tok::pp_include:
+ // Handle #include.
+ return HandleIncludeDirective(SavedHash.getLocation(), Result);
+ case tok::pp___include_macros:
+ // Handle -imacros.
+ return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result);
+
+ // C99 6.10.3 - Macro Replacement.
+ case tok::pp_define:
+ return HandleDefineDirective(Result);
+ case tok::pp_undef:
+ return HandleUndefDirective(Result);
+
+ // C99 6.10.4 - Line Control.
+ case tok::pp_line:
+ return HandleLineDirective(Result);
+
+ // C99 6.10.5 - Error Directive.
+ case tok::pp_error:
+ return HandleUserDiagnosticDirective(Result, false);
+
+ // C99 6.10.6 - Pragma Directive.
+ case tok::pp_pragma:
+ return HandlePragmaDirective(PIK_HashPragma);
+
+ // GNU Extensions.
+ case tok::pp_import:
+ return HandleImportDirective(SavedHash.getLocation(), Result);
+ case tok::pp_include_next:
+ return HandleIncludeNextDirective(SavedHash.getLocation(), Result);
+
+ case tok::pp_warning:
+ Diag(Result, diag::ext_pp_warning_directive);
+ return HandleUserDiagnosticDirective(Result, true);
+ case tok::pp_ident:
+ return HandleIdentSCCSDirective(Result);
+ case tok::pp_sccs:
+ return HandleIdentSCCSDirective(Result);
+ case tok::pp_assert:
+ //isExtension = true; // FIXME: implement #assert
+ break;
+ case tok::pp_unassert:
+ //isExtension = true; // FIXME: implement #unassert
+ break;
+ }
+ break;
+ }
+
+ // If this is a .S file, treat unknown # directives as non-preprocessor
+ // directives. This is important because # may be a comment or introduce
+ // various pseudo-ops. Just return the # token and push back the following
+ // token to be lexed next time.
+ if (getLangOptions().AsmPreprocessor) {
+ Token *Toks = new Token[2];
+ // Return the # and the token after it.
+ Toks[0] = SavedHash;
+ Toks[1] = Result;
+
+ // If the second token is a hashhash token, then we need to translate it to
+ // unknown so the token lexer doesn't try to perform token pasting.
+ if (Result.is(tok::hashhash))
+ Toks[1].setKind(tok::unknown);
+
+ // Enter this token stream so that we re-lex the tokens. Make sure to
+ // enable macro expansion, in case the token after the # is an identifier
+ // that is expanded.
+ EnterTokenStream(Toks, 2, false, true);
+ return;
+ }
+
+ // If we reached here, the preprocessing token is not valid!
+ Diag(Result, diag::err_pp_invalid_directive);
+
+ // Read the rest of the PP line.
+ DiscardUntilEndOfDirective();
+
+ // Okay, we're done parsing the directive.
+}
+
+/// GetLineValue - Convert a numeric token into an unsigned value, emitting
+/// Diagnostic DiagID if it is invalid, and returning the value in Val.
+static bool GetLineValue(Token &DigitTok, unsigned &Val,
+ unsigned DiagID, Preprocessor &PP) {
+ if (DigitTok.isNot(tok::numeric_constant)) {
+ PP.Diag(DigitTok, DiagID);
+
+ if (DigitTok.isNot(tok::eom))
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ llvm::SmallString<64> IntegerBuffer;
+ IntegerBuffer.resize(DigitTok.getLength());
+ const char *DigitTokBegin = &IntegerBuffer[0];
+ bool Invalid = false;
+ unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid);
+ if (Invalid)
+ return true;
+
+ // Verify that we have a simple digit-sequence, and compute the value. This
+ // is always a simple digit string computed in decimal, so we do this manually
+ // here.
+ Val = 0;
+ for (unsigned i = 0; i != ActualLength; ++i) {
+ if (!isdigit(DigitTokBegin[i])) {
+ PP.Diag(PP.AdvanceToTokenCharacter(DigitTok.getLocation(), i),
+ diag::err_pp_line_digit_sequence);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ unsigned NextVal = Val*10+(DigitTokBegin[i]-'0');
+ if (NextVal < Val) { // overflow.
+ PP.Diag(DigitTok, DiagID);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+ Val = NextVal;
+ }
+
+ // Reject 0, this is needed both by #line numbers and flags.
+ if (Val == 0) {
+ PP.Diag(DigitTok, DiagID);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ if (DigitTokBegin[0] == '0')
+ PP.Diag(DigitTok.getLocation(), diag::warn_pp_line_decimal);
+
+ return false;
+}
+
+/// HandleLineDirective - Handle #line directive: C99 6.10.4. The two
+/// acceptable forms are:
+/// # line digit-sequence
+/// # line digit-sequence "s-char-sequence"
+void Preprocessor::HandleLineDirective(Token &Tok) {
+ // Read the line # and string argument. Per C99 6.10.4p5, these tokens are
+ // expanded.
+ Token DigitTok;
+ Lex(DigitTok);
+
+ // Validate the number and convert it to an unsigned.
+ unsigned LineNo;
+ if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this))
+ return;
+
+ // Enforce C99 6.10.4p3: "The digit sequence shall not specify ... a
+ // number greater than 2147483647". C90 requires that the line # be <= 32767.
+ unsigned LineLimit = Features.C99 ? 2147483648U : 32768U;
+ if (LineNo >= LineLimit)
+ Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
+
+ int FilenameID = -1;
+ Token StrTok;
+ Lex(StrTok);
+
+ // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a
+ // string followed by eom.
+ if (StrTok.is(tok::eom))
+ ; // ok
+ else if (StrTok.isNot(tok::string_literal)) {
+ Diag(StrTok, diag::err_pp_line_invalid_filename);
+ DiscardUntilEndOfDirective();
+ return;
+ } else {
+ // Parse and validate the string, converting it into a unique ID.
+ StringLiteralParser Literal(&StrTok, 1, *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return DiscardUntilEndOfDirective();
+ if (Literal.Pascal) {
+ Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
+ return DiscardUntilEndOfDirective();
+ }
+ FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(),
+ Literal.GetStringLength());
+
+ // Verify that there is nothing after the string, other than EOM. Because
+ // of C99 6.10.4p5, macros that expand to empty tokens are ok.
+ CheckEndOfDirective("line", true);
+ }
+
+ SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID);
+
+ if (Callbacks)
+ Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
+ PPCallbacks::RenameFile,
+ SrcMgr::C_User);
+}
+
+/// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line
+/// marker directive.
+static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit,
+ bool &IsSystemHeader, bool &IsExternCHeader,
+ Preprocessor &PP) {
+ unsigned FlagVal;
+ Token FlagTok;
+ PP.Lex(FlagTok);
+ if (FlagTok.is(tok::eom)) return false;
+ if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
+ return true;
+
+ if (FlagVal == 1) {
+ IsFileEntry = true;
+
+ PP.Lex(FlagTok);
+ if (FlagTok.is(tok::eom)) return false;
+ if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
+ return true;
+ } else if (FlagVal == 2) {
+ IsFileExit = true;
+
+ SourceManager &SM = PP.getSourceManager();
+ // If we are leaving the current presumed file, check to make sure the
+ // presumed include stack isn't empty!
+ FileID CurFileID =
+ SM.getDecomposedInstantiationLoc(FlagTok.getLocation()).first;
+ PresumedLoc PLoc = SM.getPresumedLoc(FlagTok.getLocation());
+ if (PLoc.isInvalid())
+ return true;
+
+ // If there is no include loc (main file) or if the include loc is in a
+ // different physical file, then we aren't in a "1" line marker flag region.
+ SourceLocation IncLoc = PLoc.getIncludeLoc();
+ if (IncLoc.isInvalid() ||
+ SM.getDecomposedInstantiationLoc(IncLoc).first != CurFileID) {
+ PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ PP.Lex(FlagTok);
+ if (FlagTok.is(tok::eom)) return false;
+ if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
+ return true;
+ }
+
+ // We must have 3 if there are still flags.
+ if (FlagVal != 3) {
+ PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ IsSystemHeader = true;
+
+ PP.Lex(FlagTok);
+ if (FlagTok.is(tok::eom)) return false;
+ if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
+ return true;
+
+ // We must have 4 if there is yet another flag.
+ if (FlagVal != 4) {
+ PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ IsExternCHeader = true;
+
+ PP.Lex(FlagTok);
+ if (FlagTok.is(tok::eom)) return false;
+
+ // There are no more valid flags here.
+ PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+}
+
+/// HandleDigitDirective - Handle a GNU line marker directive, whose syntax is
+/// one of the following forms:
+///
+/// # 42
+/// # 42 "file" ('1' | '2')?
+/// # 42 "file" ('1' | '2')? '3' '4'?
+///
+void Preprocessor::HandleDigitDirective(Token &DigitTok) {
+ // Validate the number and convert it to an unsigned. GNU does not have a
+ // line # limit other than it fit in 32-bits.
+ unsigned LineNo;
+ if (GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
+ *this))
+ return;
+
+ Token StrTok;
+ Lex(StrTok);
+
+ bool IsFileEntry = false, IsFileExit = false;
+ bool IsSystemHeader = false, IsExternCHeader = false;
+ int FilenameID = -1;
+
+ // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a
+ // string followed by eom.
+ if (StrTok.is(tok::eom))
+ ; // ok
+ else if (StrTok.isNot(tok::string_literal)) {
+ Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
+ return DiscardUntilEndOfDirective();
+ } else {
+ // Parse and validate the string, converting it into a unique ID.
+ StringLiteralParser Literal(&StrTok, 1, *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return DiscardUntilEndOfDirective();
+ if (Literal.Pascal) {
+ Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
+ return DiscardUntilEndOfDirective();
+ }
+ FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(),
+ Literal.GetStringLength());
+
+ // If a filename was present, read any flags that are present.
+ if (ReadLineMarkerFlags(IsFileEntry, IsFileExit,
+ IsSystemHeader, IsExternCHeader, *this))
+ return;
+ }
+
+ // Create a line note with this information.
+ SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID,
+ IsFileEntry, IsFileExit,
+ IsSystemHeader, IsExternCHeader);
+
+ // If the preprocessor has callbacks installed, notify them of the #line
+ // change. This is used so that the line marker comes out in -E mode for
+ // example.
+ if (Callbacks) {
+ PPCallbacks::FileChangeReason Reason = PPCallbacks::RenameFile;
+ if (IsFileEntry)
+ Reason = PPCallbacks::EnterFile;
+ else if (IsFileExit)
+ Reason = PPCallbacks::ExitFile;
+ SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User;
+ if (IsExternCHeader)
+ FileKind = SrcMgr::C_ExternCSystem;
+ else if (IsSystemHeader)
+ FileKind = SrcMgr::C_System;
+
+ Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind);
+ }
+}
+
+
+/// HandleUserDiagnosticDirective - Handle a #warning or #error directive.
+///
+void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
+ bool isWarning) {
+ // PTH doesn't emit #warning or #error directives.
+ if (CurPTHLexer)
+ return CurPTHLexer->DiscardToEndOfLine();
+
+ // Read the rest of the line raw. We do this because we don't want macros
+ // to be expanded and we don't require that the tokens be valid preprocessing
+ // tokens. For example, this is allowed: "#warning ` 'foo". GCC does
+ // collapse multiple consequtive white space between tokens, but this isn't
+ // specified by the standard.
+ std::string Message = CurLexer->ReadToEndOfLine();
+ if (isWarning)
+ Diag(Tok, diag::pp_hash_warning) << Message;
+ else
+ Diag(Tok, diag::err_pp_hash_error) << Message;
+}
+
+/// HandleIdentSCCSDirective - Handle a #ident/#sccs directive.
+///
+void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
+ // Yes, this directive is an extension.
+ Diag(Tok, diag::ext_pp_ident_directive);
+
+ // Read the string argument.
+ Token StrTok;
+ Lex(StrTok);
+
+ // If the token kind isn't a string, it's a malformed directive.
+ if (StrTok.isNot(tok::string_literal) &&
+ StrTok.isNot(tok::wide_string_literal)) {
+ Diag(StrTok, diag::err_pp_malformed_ident);
+ if (StrTok.isNot(tok::eom))
+ DiscardUntilEndOfDirective();
+ return;
+ }
+
+ // Verify that there is nothing after the string, other than EOM.
+ CheckEndOfDirective("ident");
+
+ if (Callbacks) {
+ bool Invalid = false;
+ std::string Str = getSpelling(StrTok, &Invalid);
+ if (!Invalid)
+ Callbacks->Ident(Tok.getLocation(), Str);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Include Directive Handling.
+//===----------------------------------------------------------------------===//
+
+/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+/// checked and spelled filename, e.g. as an operand of #include. This returns
+/// true if the input filename was in <>'s or false if it were in ""'s. The
+/// caller is expected to provide a buffer that is large enough to hold the
+/// spelling of the filename, but is also expected to handle the case when
+/// this method decides to use a different buffer.
+bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
+ llvm::StringRef &Buffer) {
+ // Get the text form of the filename.
+ assert(!Buffer.empty() && "Can't have tokens with empty spellings!");
+
+ // Make sure the filename is <x> or "x".
+ bool isAngled;
+ if (Buffer[0] == '<') {
+ if (Buffer.back() != '>') {
+ Diag(Loc, diag::err_pp_expects_filename);
+ Buffer = llvm::StringRef();
+ return true;
+ }
+ isAngled = true;
+ } else if (Buffer[0] == '"') {
+ if (Buffer.back() != '"') {
+ Diag(Loc, diag::err_pp_expects_filename);
+ Buffer = llvm::StringRef();
+ return true;
+ }
+ isAngled = false;
+ } else {
+ Diag(Loc, diag::err_pp_expects_filename);
+ Buffer = llvm::StringRef();
+ return true;
+ }
+
+ // Diagnose #include "" as invalid.
+ if (Buffer.size() <= 2) {
+ Diag(Loc, diag::err_pp_empty_filename);
+ Buffer = llvm::StringRef();
+ return true;
+ }
+
+ // Skip the brackets.
+ Buffer = Buffer.substr(1, Buffer.size()-2);
+ return isAngled;
+}
+
+/// ConcatenateIncludeName - Handle cases where the #include name is expanded
+/// from a macro as multiple tokens, which need to be glued together. This
+/// occurs for code like:
+/// #define FOO <a/b.h>
+/// #include FOO
+/// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
+///
+/// This code concatenates and consumes tokens up to the '>' token. It returns
+/// false if the > was found, otherwise it returns true if it finds and consumes
+/// the EOM marker.
+bool Preprocessor::ConcatenateIncludeName(
+ llvm::SmallString<128> &FilenameBuffer,
+ SourceLocation &End) {
+ Token CurTok;
+
+ Lex(CurTok);
+ while (CurTok.isNot(tok::eom)) {
+ End = CurTok.getLocation();
+
+ // FIXME: Provide code completion for #includes.
+ if (CurTok.is(tok::code_completion)) {
+ Lex(CurTok);
+ continue;
+ }
+
+ // Append the spelling of this token to the buffer. If there was a space
+ // before it, add it now.
+ if (CurTok.hasLeadingSpace())
+ FilenameBuffer.push_back(' ');
+
+ // Get the spelling of the token, directly into FilenameBuffer if possible.
+ unsigned PreAppendSize = FilenameBuffer.size();
+ FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
+
+ const char *BufPtr = &FilenameBuffer[PreAppendSize];
+ unsigned ActualLen = getSpelling(CurTok, BufPtr);
+
+ // If the token was spelled somewhere else, copy it into FilenameBuffer.
+ if (BufPtr != &FilenameBuffer[PreAppendSize])
+ memcpy(&FilenameBuffer[PreAppendSize], BufPtr, ActualLen);
+
+ // Resize FilenameBuffer to the correct size.
+ if (CurTok.getLength() != ActualLen)
+ FilenameBuffer.resize(PreAppendSize+ActualLen);
+
+ // If we found the '>' marker, return success.
+ if (CurTok.is(tok::greater))
+ return false;
+
+ Lex(CurTok);
+ }
+
+ // If we hit the eom marker, emit an error and return true so that the caller
+ // knows the EOM has been read.
+ Diag(CurTok.getLocation(), diag::err_pp_expects_filename);
+ return true;
+}
+
+/// HandleIncludeDirective - The "#include" tokens have just been read, read the
+/// file to be included from the lexer, then include it! This is a common
+/// routine with functionality shared between #include, #include_next and
+/// #import. LookupFrom is set when this is a #include_next directive, it
+/// specifies the file to start searching from.
+void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
+ Token &IncludeTok,
+ const DirectoryLookup *LookupFrom,
+ bool isImport) {
+
+ Token FilenameTok;
+ CurPPLexer->LexIncludeFilename(FilenameTok);
+
+ // Reserve a buffer to get the spelling.
+ llvm::SmallString<128> FilenameBuffer;
+ llvm::StringRef Filename;
+ SourceLocation End;
+
+ switch (FilenameTok.getKind()) {
+ case tok::eom:
+ // If the token kind is EOM, the error has already been diagnosed.
+ return;
+
+ case tok::angle_string_literal:
+ case tok::string_literal:
+ Filename = getSpelling(FilenameTok, FilenameBuffer);
+ End = FilenameTok.getLocation();
+ break;
+
+ case tok::less:
+ // This could be a <foo/bar.h> file coming from a macro expansion. In this
+ // case, glue the tokens together into FilenameBuffer and interpret those.
+ FilenameBuffer.push_back('<');
+ if (ConcatenateIncludeName(FilenameBuffer, End))
+ return; // Found <eom> but no ">"? Diagnostic already emitted.
+ Filename = FilenameBuffer.str();
+ break;
+ default:
+ Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+ DiscardUntilEndOfDirective();
+ return;
+ }
+
+ bool isAngled =
+ GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
+ // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+ // error.
+ if (Filename.empty()) {
+ DiscardUntilEndOfDirective();
+ return;
+ }
+
+ // Verify that there is nothing after the filename, other than EOM. Note that
+ // we allow macros that expand to nothing after the filename, because this
+ // falls into the category of "#include pp-tokens new-line" specified in
+ // C99 6.10.2p4.
+ CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getNameStart(), true);
+
+ // Check that we don't have infinite #include recursion.
+ if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
+ Diag(FilenameTok, diag::err_pp_include_too_deep);
+ return;
+ }
+
+ // Search include directories.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
+ if (File == 0) {
+ Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ return;
+ }
+
+ // Notify the callback object that we've seen an inclusion directive.
+ if (Callbacks)
+ Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File,
+ End);
+
+ // The #included file will be considered to be a system header if either it is
+ // in a system include directory, or if the #includer is a system include
+ // header.
+ SrcMgr::CharacteristicKind FileCharacter =
+ std::max(HeaderInfo.getFileDirFlavor(File),
+ SourceMgr.getFileCharacteristic(FilenameTok.getLocation()));
+
+ // Ask HeaderInfo if we should enter this #include file. If not, #including
+ // this file will have no effect.
+ if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) {
+ if (Callbacks)
+ Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
+ return;
+ }
+
+ // Look up the file, create a File ID for it.
+ FileID FID = SourceMgr.createFileID(File, FilenameTok.getLocation(),
+ FileCharacter);
+ if (FID.isInvalid()) {
+ Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ return;
+ }
+
+ // Finally, if all is good, enter the new file!
+ EnterSourceFile(FID, CurDir, FilenameTok.getLocation());
+}
+
+/// HandleIncludeNextDirective - Implements #include_next.
+///
+void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
+ Token &IncludeNextTok) {
+ Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
+
+ // #include_next is like #include, except that we start searching after
+ // the current found directory. If we can't do this, issue a
+ // diagnostic.
+ const DirectoryLookup *Lookup = CurDirLookup;
+ if (isInPrimaryFile()) {
+ Lookup = 0;
+ Diag(IncludeNextTok, diag::pp_include_next_in_primary);
+ } else if (Lookup == 0) {
+ Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
+ } else {
+ // Start looking up in the next directory.
+ ++Lookup;
+ }
+
+ return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup);
+}
+
+/// HandleImportDirective - Implements #import.
+///
+void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
+ Token &ImportTok) {
+ if (!Features.ObjC1) // #import is standard for ObjC.
+ Diag(ImportTok, diag::ext_pp_import_directive);
+
+ return HandleIncludeDirective(HashLoc, ImportTok, 0, true);
+}
+
+/// HandleIncludeMacrosDirective - The -imacros command line option turns into a
+/// pseudo directive in the predefines buffer. This handles it by sucking all
+/// tokens through the preprocessor and discarding them (only keeping the side
+/// effects on the preprocessor).
+void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
+ Token &IncludeMacrosTok) {
+ // This directive should only occur in the predefines buffer. If not, emit an
+ // error and reject it.
+ SourceLocation Loc = IncludeMacrosTok.getLocation();
+ if (strcmp(SourceMgr.getBufferName(Loc), "<built-in>") != 0) {
+ Diag(IncludeMacrosTok.getLocation(),
+ diag::pp_include_macros_out_of_predefines);
+ DiscardUntilEndOfDirective();
+ return;
+ }
+
+ // Treat this as a normal #include for checking purposes. If this is
+ // successful, it will push a new lexer onto the include stack.
+ HandleIncludeDirective(HashLoc, IncludeMacrosTok, 0, false);
+
+ Token TmpTok;
+ do {
+ Lex(TmpTok);
+ assert(TmpTok.isNot(tok::eof) && "Didn't find end of -imacros!");
+ } while (TmpTok.isNot(tok::hashhash));
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Macro Directive Handling.
+//===----------------------------------------------------------------------===//
+
+/// ReadMacroDefinitionArgList - The ( starting an argument list of a macro
+/// definition has just been read. Lex the rest of the arguments and the
+/// closing ), updating MI with what we learn. Return true if an error occurs
+/// parsing the arg list.
+bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) {
+ llvm::SmallVector<IdentifierInfo*, 32> Arguments;
+
+ Token Tok;
+ while (1) {
+ LexUnexpandedToken(Tok);
+ switch (Tok.getKind()) {
+ case tok::r_paren:
+ // Found the end of the argument list.
+ if (Arguments.empty()) // #define FOO()
+ return false;
+ // Otherwise we have #define FOO(A,)
+ Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
+ return true;
+ case tok::ellipsis: // #define X(... -> C99 varargs
+ // Warn if use of C99 feature in non-C99 mode.
+ if (!Features.C99) Diag(Tok, diag::ext_variadic_macro);
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ }
+ // Add the __VA_ARGS__ identifier as an argument.
+ Arguments.push_back(Ident__VA_ARGS__);
+ MI->setIsC99Varargs();
+ MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ return false;
+ case tok::eom: // #define X(
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ default:
+ // Handle keywords and identifiers here to accept things like
+ // #define Foo(for) for.
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II == 0) {
+ // #define X(1
+ Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
+ return true;
+ }
+
+ // If this is already used as an argument, it is used multiple times (e.g.
+ // #define X(A,A.
+ if (std::find(Arguments.begin(), Arguments.end(), II) !=
+ Arguments.end()) { // C99 6.10.3p6
+ Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
+ return true;
+ }
+
+ // Add the argument to the macro info.
+ Arguments.push_back(II);
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+
+ switch (Tok.getKind()) {
+ default: // #define X(A B
+ Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
+ return true;
+ case tok::r_paren: // #define X(A)
+ MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ return false;
+ case tok::comma: // #define X(A,
+ break;
+ case tok::ellipsis: // #define X(A... -> GCC extension
+ // Diagnose extension.
+ Diag(Tok, diag::ext_named_variadic_macro);
+
+ // Lex the token after the identifier.
+ LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
+ return true;
+ }
+
+ MI->setIsGNUVarargs();
+ MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ return false;
+ }
+ }
+ }
+}
+
+/// HandleDefineDirective - Implements #define. This consumes the entire macro
+/// line then lets the caller lex the next real token.
+void Preprocessor::HandleDefineDirective(Token &DefineTok) {
+ ++NumDefined;
+
+ Token MacroNameTok;
+ ReadMacroName(MacroNameTok, 1);
+
+ // Error reading macro name? If so, diagnostic already issued.
+ if (MacroNameTok.is(tok::eom))
+ return;
+
+ Token LastTok = MacroNameTok;
+
+ // If we are supposed to keep comments in #defines, reenable comment saving
+ // mode.
+ if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
+
+ // Create the new macro.
+ MacroInfo *MI = AllocateMacroInfo(MacroNameTok.getLocation());
+
+ Token Tok;
+ LexUnexpandedToken(Tok);
+
+ // If this is a function-like macro definition, parse the argument list,
+ // marking each of the identifiers as being used as macro arguments. Also,
+ // check other constraints on the first token of the macro body.
+ if (Tok.is(tok::eom)) {
+ // If there is no body to this macro, we have no special handling here.
+ } else if (Tok.hasLeadingSpace()) {
+ // This is a normal token with leading space. Clear the leading space
+ // marker on the first token to get proper expansion.
+ Tok.clearFlag(Token::LeadingSpace);
+ } else if (Tok.is(tok::l_paren)) {
+ // This is a function-like macro definition. Read the argument list.
+ MI->setIsFunctionLike();
+ if (ReadMacroDefinitionArgList(MI)) {
+ // Forget about MI.
+ ReleaseMacroInfo(MI);
+ // Throw away the rest of the line.
+ if (CurPPLexer->ParsingPreprocessorDirective)
+ DiscardUntilEndOfDirective();
+ return;
+ }
+
+ // If this is a definition of a variadic C99 function-like macro, not using
+ // the GNU named varargs extension, enabled __VA_ARGS__.
+
+ // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
+ // This gets unpoisoned where it is allowed.
+ assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned!");
+ if (MI->isC99Varargs())
+ Ident__VA_ARGS__->setIsPoisoned(false);
+
+ // Read the first token after the arg list for down below.
+ LexUnexpandedToken(Tok);
+ } else if (Features.C99) {
+ // C99 requires whitespace between the macro definition and the body. Emit
+ // a diagnostic for something like "#define X+".
+ Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
+ } else {
+ // C90 6.8 TC1 says: "In the definition of an object-like macro, if the
+ // first character of a replacement list is not a character required by
+ // subclause 5.2.1, then there shall be white-space separation between the
+ // identifier and the replacement list.". 5.2.1 lists this set:
+ // "A-Za-z0-9!"#%&'()*+,_./:;<=>?[\]^_{|}~" as well as whitespace, which
+ // is irrelevant here.
+ bool isInvalid = false;
+ if (Tok.is(tok::at)) // @ is not in the list above.
+ isInvalid = true;
+ else if (Tok.is(tok::unknown)) {
+ // If we have an unknown token, it is something strange like "`". Since
+ // all of valid characters would have lexed into a single character
+ // token of some sort, we know this is not a valid case.
+ isInvalid = true;
+ }
+ if (isInvalid)
+ Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
+ else
+ Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
+ }
+
+ if (!Tok.is(tok::eom))
+ LastTok = Tok;
+
+ // Read the rest of the macro body.
+ if (MI->isObjectLike()) {
+ // Object-like macros are very simple, just read their body.
+ while (Tok.isNot(tok::eom)) {
+ LastTok = Tok;
+ MI->AddTokenToBody(Tok);
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+ }
+
+ } else {
+ // Otherwise, read the body of a function-like macro. While we are at it,
+ // check C99 6.10.3.2p1: ensure that # operators are followed by macro
+ // parameters in function-like macro expansions.
+ while (Tok.isNot(tok::eom)) {
+ LastTok = Tok;
+
+ if (Tok.isNot(tok::hash)) {
+ MI->AddTokenToBody(Tok);
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+ continue;
+ }
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+
+ // Check for a valid macro arg identifier.
+ if (Tok.getIdentifierInfo() == 0 ||
+ MI->getArgumentNum(Tok.getIdentifierInfo()) == -1) {
+
+ // If this is assembler-with-cpp mode, we accept random gibberish after
+ // the '#' because '#' is often a comment character. However, change
+ // the kind of the token to tok::unknown so that the preprocessor isn't
+ // confused.
+ if (getLangOptions().AsmPreprocessor && Tok.isNot(tok::eom)) {
+ LastTok.setKind(tok::unknown);
+ } else {
+ Diag(Tok, diag::err_pp_stringize_not_parameter);
+ ReleaseMacroInfo(MI);
+
+ // Disable __VA_ARGS__ again.
+ Ident__VA_ARGS__->setIsPoisoned(true);
+ return;
+ }
+ }
+
+ // Things look ok, add the '#' and param name tokens to the macro.
+ MI->AddTokenToBody(LastTok);
+ MI->AddTokenToBody(Tok);
+ LastTok = Tok;
+
+ // Get the next token of the macro.
+ LexUnexpandedToken(Tok);
+ }
+ }
+
+
+ // Disable __VA_ARGS__ again.
+ Ident__VA_ARGS__->setIsPoisoned(true);
+
+ // Check that there is no paste (##) operator at the begining or end of the
+ // replacement list.
+ unsigned NumTokens = MI->getNumTokens();
+ if (NumTokens != 0) {
+ if (MI->getReplacementToken(0).is(tok::hashhash)) {
+ Diag(MI->getReplacementToken(0), diag::err_paste_at_start);
+ ReleaseMacroInfo(MI);
+ return;
+ }
+ if (MI->getReplacementToken(NumTokens-1).is(tok::hashhash)) {
+ Diag(MI->getReplacementToken(NumTokens-1), diag::err_paste_at_end);
+ ReleaseMacroInfo(MI);
+ return;
+ }
+ }
+
+ MI->setDefinitionEndLoc(LastTok.getLocation());
+
+ // Finally, if this identifier already had a macro defined for it, verify that
+ // the macro bodies are identical and free the old definition.
+ if (MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo())) {
+ // It is very common for system headers to have tons of macro redefinitions
+ // and for warnings to be disabled in system headers. If this is the case,
+ // then don't bother calling MacroInfo::isIdenticalTo.
+ if (!getDiagnostics().getSuppressSystemWarnings() ||
+ !SourceMgr.isInSystemHeader(DefineTok.getLocation())) {
+ if (!OtherMI->isUsed() && OtherMI->isWarnIfUnused())
+ Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used);
+
+ // Macros must be identical. This means all tokens and whitespace
+ // separation must be the same. C99 6.10.3.2.
+ if (!OtherMI->isAllowRedefinitionsWithoutWarning() &&
+ !MI->isIdenticalTo(*OtherMI, *this)) {
+ Diag(MI->getDefinitionLoc(), diag::ext_pp_macro_redef)
+ << MacroNameTok.getIdentifierInfo();
+ Diag(OtherMI->getDefinitionLoc(), diag::note_previous_definition);
+ }
+ }
+ if (OtherMI->isWarnIfUnused())
+ WarnUnusedMacroLocs.erase(OtherMI->getDefinitionLoc());
+ ReleaseMacroInfo(OtherMI);
+ }
+
+ setMacroInfo(MacroNameTok.getIdentifierInfo(), MI);
+
+ assert(!MI->isUsed());
+ // If we need warning for not using the macro, add its location in the
+ // warn-because-unused-macro set. If it gets used it will be removed from set.
+ if (isInPrimaryFile() && // don't warn for include'd macros.
+ Diags->getDiagnosticLevel(diag::pp_macro_not_used,
+ MI->getDefinitionLoc()) != Diagnostic::Ignored) {
+ MI->setIsWarnIfUnused(true);
+ WarnUnusedMacroLocs.insert(MI->getDefinitionLoc());
+ }
+
+ // If the callbacks want to know, tell them about the macro definition.
+ if (Callbacks)
+ Callbacks->MacroDefined(MacroNameTok, MI);
+}
+
+/// HandleUndefDirective - Implements #undef.
+///
+void Preprocessor::HandleUndefDirective(Token &UndefTok) {
+ ++NumUndefined;
+
+ Token MacroNameTok;
+ ReadMacroName(MacroNameTok, 2);
+
+ // Error reading macro name? If so, diagnostic already issued.
+ if (MacroNameTok.is(tok::eom))
+ return;
+
+ // Check to see if this is the last token on the #undef line.
+ CheckEndOfDirective("undef");
+
+ // Okay, we finally have a valid identifier to undef.
+ MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo());
+
+ // If the macro is not defined, this is a noop undef, just return.
+ if (MI == 0) return;
+
+ if (!MI->isUsed())
+ Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
+
+ // If the callbacks want to know, tell them about the macro #undef.
+ if (Callbacks)
+ Callbacks->MacroUndefined(MacroNameTok, MI);
+
+ if (MI->isWarnIfUnused())
+ WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
+
+ // Free macro definition.
+ ReleaseMacroInfo(MI);
+ setMacroInfo(MacroNameTok.getIdentifierInfo(), 0);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Conditional Directive Handling.
+//===----------------------------------------------------------------------===//
+
+/// HandleIfdefDirective - Implements the #ifdef/#ifndef directive. isIfndef is
+/// true when this is a #ifndef directive. ReadAnyTokensBeforeDirective is true
+/// if any tokens have been returned or pp-directives activated before this
+/// #ifndef has been lexed.
+///
+void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
+ bool ReadAnyTokensBeforeDirective) {
+ ++NumIf;
+ Token DirectiveTok = Result;
+
+ Token MacroNameTok;
+ ReadMacroName(MacroNameTok);
+
+ // Error reading macro name? If so, diagnostic already issued.
+ if (MacroNameTok.is(tok::eom)) {
+ // Skip code until we get to #endif. This helps with recovery by not
+ // emitting an error when the #endif is reached.
+ SkipExcludedConditionalBlock(DirectiveTok.getLocation(),
+ /*Foundnonskip*/false, /*FoundElse*/false);
+ return;
+ }
+
+ // Check to see if this is the last token on the #if[n]def line.
+ CheckEndOfDirective(isIfndef ? "ifndef" : "ifdef");
+
+ IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
+ MacroInfo *MI = getMacroInfo(MII);
+
+ if (CurPPLexer->getConditionalStackDepth() == 0) {
+ // If the start of a top-level #ifdef and if the macro is not defined,
+ // inform MIOpt that this might be the start of a proper include guard.
+ // Otherwise it is some other form of unknown conditional which we can't
+ // handle.
+ if (!ReadAnyTokensBeforeDirective && MI == 0) {
+ assert(isIfndef && "#ifdef shouldn't reach here");
+ CurPPLexer->MIOpt.EnterTopLevelIFNDEF(MII);
+ } else
+ CurPPLexer->MIOpt.EnterTopLevelConditional();
+ }
+
+ // If there is a macro, process it.
+ if (MI) // Mark it used.
+ markMacroAsUsed(MI);
+
+ // Should we include the stuff contained by this directive?
+ if (!MI == isIfndef) {
+ // Yes, remember that we are inside a conditional, then lex the next token.
+ CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
+ /*wasskip*/false, /*foundnonskip*/true,
+ /*foundelse*/false);
+ } else {
+ // No, skip the contents of this block.
+ SkipExcludedConditionalBlock(DirectiveTok.getLocation(),
+ /*Foundnonskip*/false,
+ /*FoundElse*/false);
+ }
+
+ if (Callbacks) {
+ if (isIfndef)
+ Callbacks->Ifndef(MacroNameTok);
+ else
+ Callbacks->Ifdef(MacroNameTok);
+ }
+}
+
+/// HandleIfDirective - Implements the #if directive.
+///
+void Preprocessor::HandleIfDirective(Token &IfToken,
+ bool ReadAnyTokensBeforeDirective) {
+ ++NumIf;
+
+ // Parse and evaluate the conditional expression.
+ IdentifierInfo *IfNDefMacro = 0;
+ const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
+ const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro);
+ const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
+
+ // If this condition is equivalent to #ifndef X, and if this is the first
+ // directive seen, handle it for the multiple-include optimization.
+ if (CurPPLexer->getConditionalStackDepth() == 0) {
+ if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
+ CurPPLexer->MIOpt.EnterTopLevelIFNDEF(IfNDefMacro);
+ else
+ CurPPLexer->MIOpt.EnterTopLevelConditional();
+ }
+
+ // Should we include the stuff contained by this directive?
+ if (ConditionalTrue) {
+ // Yes, remember that we are inside a conditional, then lex the next token.
+ CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
+ /*foundnonskip*/true, /*foundelse*/false);
+ } else {
+ // No, skip the contents of this block.
+ SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false,
+ /*FoundElse*/false);
+ }
+
+ if (Callbacks)
+ Callbacks->If(SourceRange(ConditionalBegin, ConditionalEnd));
+}
+
+/// HandleEndifDirective - Implements the #endif directive.
+///
+void Preprocessor::HandleEndifDirective(Token &EndifToken) {
+ ++NumEndif;
+
+ // Check that this is the whole directive.
+ CheckEndOfDirective("endif");
+
+ PPConditionalInfo CondInfo;
+ if (CurPPLexer->popConditionalLevel(CondInfo)) {
+ // No conditionals on the stack: this is an #endif without an #if.
+ Diag(EndifToken, diag::err_pp_endif_without_if);
+ return;
+ }
+
+ // If this the end of a top-level #endif, inform MIOpt.
+ if (CurPPLexer->getConditionalStackDepth() == 0)
+ CurPPLexer->MIOpt.ExitTopLevelConditional();
+
+ assert(!CondInfo.WasSkipping && !CurPPLexer->LexingRawMode &&
+ "This code should only be reachable in the non-skipping case!");
+
+ if (Callbacks)
+ Callbacks->Endif();
+}
+
+/// HandleElseDirective - Implements the #else directive.
+///
+void Preprocessor::HandleElseDirective(Token &Result) {
+ ++NumElse;
+
+ // #else directive in a non-skipping conditional... start skipping.
+ CheckEndOfDirective("else");
+
+ PPConditionalInfo CI;
+ if (CurPPLexer->popConditionalLevel(CI)) {
+ Diag(Result, diag::pp_err_else_without_if);
+ return;
+ }
+
+ // If this is a top-level #else, inform the MIOpt.
+ if (CurPPLexer->getConditionalStackDepth() == 0)
+ CurPPLexer->MIOpt.EnterTopLevelConditional();
+
+ // If this is a #else with a #else before it, report the error.
+ if (CI.FoundElse) Diag(Result, diag::pp_err_else_after_else);
+
+ // Finally, skip the rest of the contents of this block.
+ SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
+ /*FoundElse*/true);
+
+ if (Callbacks)
+ Callbacks->Else();
+}
+
+/// HandleElifDirective - Implements the #elif directive.
+///
+void Preprocessor::HandleElifDirective(Token &ElifToken) {
+ ++NumElse;
+
+ // #elif directive in a non-skipping conditional... start skipping.
+ // We don't care what the condition is, because we will always skip it (since
+ // the block immediately before it was included).
+ const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
+ DiscardUntilEndOfDirective();
+ const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
+
+ PPConditionalInfo CI;
+ if (CurPPLexer->popConditionalLevel(CI)) {
+ Diag(ElifToken, diag::pp_err_elif_without_if);
+ return;
+ }
+
+ // If this is a top-level #elif, inform the MIOpt.
+ if (CurPPLexer->getConditionalStackDepth() == 0)
+ CurPPLexer->MIOpt.EnterTopLevelConditional();
+
+ // If this is a #elif with a #else before it, report the error.
+ if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else);
+
+ // Finally, skip the rest of the contents of this block.
+ SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
+ /*FoundElse*/CI.FoundElse);
+
+ if (Callbacks)
+ Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd));
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
new file mode 100644
index 0000000..1451c5a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
@@ -0,0 +1,762 @@
+//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Preprocessor::EvaluateDirectiveExpression method,
+// which parses and evaluates integer constant expressions for #if directives.
+//
+//===----------------------------------------------------------------------===//
+//
+// FIXME: implement testing for #assert's.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "llvm/ADT/APSInt.h"
+using namespace clang;
+
+namespace {
+
+/// PPValue - Represents the value of a subexpression of a preprocessor
+/// conditional and the source range covered by it.
+class PPValue {
+ SourceRange Range;
+public:
+ llvm::APSInt Val;
+
+ // Default ctor - Construct an 'invalid' PPValue.
+ PPValue(unsigned BitWidth) : Val(BitWidth) {}
+
+ unsigned getBitWidth() const { return Val.getBitWidth(); }
+ bool isUnsigned() const { return Val.isUnsigned(); }
+
+ const SourceRange &getRange() const { return Range; }
+
+ void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
+ void setRange(SourceLocation B, SourceLocation E) {
+ Range.setBegin(B); Range.setEnd(E);
+ }
+ void setBegin(SourceLocation L) { Range.setBegin(L); }
+ void setEnd(SourceLocation L) { Range.setEnd(L); }
+};
+
+}
+
+static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
+ Token &PeekTok, bool ValueLive,
+ Preprocessor &PP);
+
+/// DefinedTracker - This struct is used while parsing expressions to keep track
+/// of whether !defined(X) has been seen.
+///
+/// With this simple scheme, we handle the basic forms:
+/// !defined(X) and !defined X
+/// but we also trivially handle (silly) stuff like:
+/// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).
+struct DefinedTracker {
+ /// Each time a Value is evaluated, it returns information about whether the
+ /// parsed value is of the form defined(X), !defined(X) or is something else.
+ enum TrackerState {
+ DefinedMacro, // defined(X)
+ NotDefinedMacro, // !defined(X)
+ Unknown // Something else.
+ } State;
+ /// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
+ /// indicates the macro that was checked.
+ IdentifierInfo *TheMacro;
+};
+
+/// EvaluateDefined - Process a 'defined(sym)' expression.
+static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
+ bool ValueLive, Preprocessor &PP) {
+ IdentifierInfo *II;
+ Result.setBegin(PeekTok.getLocation());
+
+ // Get the next token, don't expand it.
+ PP.LexUnexpandedToken(PeekTok);
+
+ // Two options, it can either be a pp-identifier or a (.
+ SourceLocation LParenLoc;
+ if (PeekTok.is(tok::l_paren)) {
+ // Found a paren, remember we saw it and skip it.
+ LParenLoc = PeekTok.getLocation();
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
+ if (PeekTok.is(tok::code_completion)) {
+ if (PP.getCodeCompletionHandler())
+ PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
+ // If we don't have a pp-identifier now, this is an error.
+ if ((II = PeekTok.getIdentifierInfo()) == 0) {
+ PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
+ return true;
+ }
+
+ // Otherwise, we got an identifier, is it defined to something?
+ Result.Val = II->hasMacroDefinition();
+ Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
+
+ // If there is a macro, mark it used.
+ if (Result.Val != 0 && ValueLive) {
+ MacroInfo *Macro = PP.getMacroInfo(II);
+ PP.markMacroAsUsed(Macro);
+ }
+
+ // Consume identifier.
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexUnexpandedToken(PeekTok);
+
+ // If we are in parens, ensure we have a trailing ).
+ if (LParenLoc.isValid()) {
+ if (PeekTok.isNot(tok::r_paren)) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return true;
+ }
+ // Consume the ).
+ Result.setEnd(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ }
+
+ // Success, remember that we saw defined(X).
+ DT.State = DefinedTracker::DefinedMacro;
+ DT.TheMacro = II;
+ return false;
+}
+
+/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
+/// return the computed value in Result. Return true if there was an error
+/// parsing. This function also returns information about the form of the
+/// expression in DT. See above for information on what DT means.
+///
+/// If ValueLive is false, then this value is being evaluated in a context where
+/// the result is not used. As such, avoid diagnostics that relate to
+/// evaluation.
+static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
+ bool ValueLive, Preprocessor &PP) {
+ DT.State = DefinedTracker::Unknown;
+
+ if (PeekTok.is(tok::code_completion)) {
+ if (PP.getCodeCompletionHandler())
+ PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
+ // If this token's spelling is a pp-identifier, check to see if it is
+ // 'defined' or if it is a macro. Note that we check here because many
+ // keywords are pp-identifiers, so we can't check the kind.
+ if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
+ // Handle "defined X" and "defined(X)".
+ if (II->isStr("defined"))
+ return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP));
+
+ // If this identifier isn't 'defined' or one of the special
+ // preprocessor keywords and it wasn't macro expanded, it turns
+ // into a simple 0, unless it is the C++ keyword "true", in which case it
+ // turns into "1".
+ if (ValueLive)
+ PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
+ Result.Val = II->getTokenID() == tok::kw_true;
+ Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
+ Result.setRange(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ return false;
+ }
+
+ switch (PeekTok.getKind()) {
+ default: // Non-value token.
+ PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
+ return true;
+ case tok::eom:
+ case tok::r_paren:
+ // If there is no expression, report and exit.
+ PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
+ return true;
+ case tok::numeric_constant: {
+ llvm::SmallString<64> IntegerBuffer;
+ bool NumberInvalid = false;
+ llvm::StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
+ &NumberInvalid);
+ if (NumberInvalid)
+ return true; // a diagnostic was already reported
+
+ NumericLiteralParser Literal(Spelling.begin(), Spelling.end(),
+ PeekTok.getLocation(), PP);
+ if (Literal.hadError)
+ return true; // a diagnostic was already reported.
+
+ if (Literal.isFloatingLiteral() || Literal.isImaginary) {
+ PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);
+ return true;
+ }
+ assert(Literal.isIntegerLiteral() && "Unknown ppnumber");
+
+ // long long is a C99 feature.
+ if (!PP.getLangOptions().C99 && !PP.getLangOptions().CPlusPlus0x
+ && Literal.isLongLong)
+ PP.Diag(PeekTok, diag::ext_longlong);
+
+ // Parse the integer literal into Result.
+ if (Literal.GetIntegerValue(Result.Val)) {
+ // Overflow parsing integer literal.
+ if (ValueLive) PP.Diag(PeekTok, diag::warn_integer_too_large);
+ Result.Val.setIsUnsigned(true);
+ } else {
+ // Set the signedness of the result to match whether there was a U suffix
+ // or not.
+ Result.Val.setIsUnsigned(Literal.isUnsigned);
+
+ // Detect overflow based on whether the value is signed. If signed
+ // and if the value is too large, emit a warning "integer constant is so
+ // large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
+ // is 64-bits.
+ if (!Literal.isUnsigned && Result.Val.isNegative()) {
+ // Don't warn for a hex literal: 0x8000..0 shouldn't warn.
+ if (ValueLive && Literal.getRadix() != 16)
+ PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
+ Result.Val.setIsUnsigned(true);
+ }
+ }
+
+ // Consume the token.
+ Result.setRange(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ return false;
+ }
+ case tok::char_constant: { // 'x'
+ llvm::SmallString<32> CharBuffer;
+ bool CharInvalid = false;
+ llvm::StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
+ if (CharInvalid)
+ return true;
+
+ CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
+ PeekTok.getLocation(), PP);
+ if (Literal.hadError())
+ return true; // A diagnostic was already emitted.
+
+ // Character literals are always int or wchar_t, expand to intmax_t.
+ const TargetInfo &TI = PP.getTargetInfo();
+ unsigned NumBits;
+ if (Literal.isMultiChar())
+ NumBits = TI.getIntWidth();
+ else if (Literal.isWide())
+ NumBits = TI.getWCharWidth();
+ else
+ NumBits = TI.getCharWidth();
+
+ // Set the width.
+ llvm::APSInt Val(NumBits);
+ // Set the value.
+ Val = Literal.getValue();
+ // Set the signedness.
+ Val.setIsUnsigned(!PP.getLangOptions().CharIsSigned);
+
+ if (Result.Val.getBitWidth() > Val.getBitWidth()) {
+ Result.Val = Val.extend(Result.Val.getBitWidth());
+ } else {
+ assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
+ "intmax_t smaller than char/wchar_t?");
+ Result.Val = Val;
+ }
+
+ // Consume the token.
+ Result.setRange(PeekTok.getLocation());
+ PP.LexNonComment(PeekTok);
+ return false;
+ }
+ case tok::l_paren: {
+ SourceLocation Start = PeekTok.getLocation();
+ PP.LexNonComment(PeekTok); // Eat the (.
+ // Parse the value and if there are any binary operators involved, parse
+ // them.
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+
+ // If this is a silly value like (X), which doesn't need parens, check for
+ // !(defined X).
+ if (PeekTok.is(tok::r_paren)) {
+ // Just use DT unmodified as our result.
+ } else {
+ // Otherwise, we have something like (x+y), and we consumed '(x'.
+ if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP))
+ return true;
+
+ if (PeekTok.isNot(tok::r_paren)) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
+ << Result.getRange();
+ PP.Diag(Start, diag::note_matching) << "(";
+ return true;
+ }
+ DT.State = DefinedTracker::Unknown;
+ }
+ Result.setRange(Start, PeekTok.getLocation());
+ PP.LexNonComment(PeekTok); // Eat the ).
+ return false;
+ }
+ case tok::plus: {
+ SourceLocation Start = PeekTok.getLocation();
+ // Unary plus doesn't modify the value.
+ PP.LexNonComment(PeekTok);
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+ Result.setBegin(Start);
+ return false;
+ }
+ case tok::minus: {
+ SourceLocation Loc = PeekTok.getLocation();
+ PP.LexNonComment(PeekTok);
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+ Result.setBegin(Loc);
+
+ // C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
+ Result.Val = -Result.Val;
+
+ // -MININT is the only thing that overflows. Unsigned never overflows.
+ bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();
+
+ // If this operator is live and overflowed, report the issue.
+ if (Overflow && ValueLive)
+ PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange();
+
+ DT.State = DefinedTracker::Unknown;
+ return false;
+ }
+
+ case tok::tilde: {
+ SourceLocation Start = PeekTok.getLocation();
+ PP.LexNonComment(PeekTok);
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+ Result.setBegin(Start);
+
+ // C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
+ Result.Val = ~Result.Val;
+ DT.State = DefinedTracker::Unknown;
+ return false;
+ }
+
+ case tok::exclaim: {
+ SourceLocation Start = PeekTok.getLocation();
+ PP.LexNonComment(PeekTok);
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
+ Result.setBegin(Start);
+ Result.Val = !Result.Val;
+ // C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
+ Result.Val.setIsUnsigned(false);
+
+ if (DT.State == DefinedTracker::DefinedMacro)
+ DT.State = DefinedTracker::NotDefinedMacro;
+ else if (DT.State == DefinedTracker::NotDefinedMacro)
+ DT.State = DefinedTracker::DefinedMacro;
+ return false;
+ }
+
+ // FIXME: Handle #assert
+ }
+}
+
+
+
+/// getPrecedence - Return the precedence of the specified binary operator
+/// token. This returns:
+/// ~0 - Invalid token.
+/// 14 -> 3 - various operators.
+/// 0 - 'eom' or ')'
+static unsigned getPrecedence(tok::TokenKind Kind) {
+ switch (Kind) {
+ default: return ~0U;
+ case tok::percent:
+ case tok::slash:
+ case tok::star: return 14;
+ case tok::plus:
+ case tok::minus: return 13;
+ case tok::lessless:
+ case tok::greatergreater: return 12;
+ case tok::lessequal:
+ case tok::less:
+ case tok::greaterequal:
+ case tok::greater: return 11;
+ case tok::exclaimequal:
+ case tok::equalequal: return 10;
+ case tok::amp: return 9;
+ case tok::caret: return 8;
+ case tok::pipe: return 7;
+ case tok::ampamp: return 6;
+ case tok::pipepipe: return 5;
+ case tok::question: return 4;
+ case tok::comma: return 3;
+ case tok::colon: return 2;
+ case tok::r_paren: return 0; // Lowest priority, end of expr.
+ case tok::eom: return 0; // Lowest priority, end of macro.
+ }
+}
+
+
+/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
+/// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS.
+///
+/// If ValueLive is false, then this value is being evaluated in a context where
+/// the result is not used. As such, avoid diagnostics that relate to
+/// evaluation, such as division by zero warnings.
+static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
+ Token &PeekTok, bool ValueLive,
+ Preprocessor &PP) {
+ unsigned PeekPrec = getPrecedence(PeekTok.getKind());
+ // If this token isn't valid, report the error.
+ if (PeekPrec == ~0U) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
+ << LHS.getRange();
+ return true;
+ }
+
+ while (1) {
+ // If this token has a lower precedence than we are allowed to parse, return
+ // it so that higher levels of the recursion can parse it.
+ if (PeekPrec < MinPrec)
+ return false;
+
+ tok::TokenKind Operator = PeekTok.getKind();
+
+ // If this is a short-circuiting operator, see if the RHS of the operator is
+ // dead. Note that this cannot just clobber ValueLive. Consider
+ // "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In
+ // this example, the RHS of the && being dead does not make the rest of the
+ // expr dead.
+ bool RHSIsLive;
+ if (Operator == tok::ampamp && LHS.Val == 0)
+ RHSIsLive = false; // RHS of "0 && x" is dead.
+ else if (Operator == tok::pipepipe && LHS.Val != 0)
+ RHSIsLive = false; // RHS of "1 || x" is dead.
+ else if (Operator == tok::question && LHS.Val == 0)
+ RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.
+ else
+ RHSIsLive = ValueLive;
+
+ // Consume the operator, remembering the operator's location for reporting.
+ SourceLocation OpLoc = PeekTok.getLocation();
+ PP.LexNonComment(PeekTok);
+
+ PPValue RHS(LHS.getBitWidth());
+ // Parse the RHS of the operator.
+ DefinedTracker DT;
+ if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
+
+ // Remember the precedence of this operator and get the precedence of the
+ // operator immediately to the right of the RHS.
+ unsigned ThisPrec = PeekPrec;
+ PeekPrec = getPrecedence(PeekTok.getKind());
+
+ // If this token isn't valid, report the error.
+ if (PeekPrec == ~0U) {
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop)
+ << RHS.getRange();
+ return true;
+ }
+
+ // Decide whether to include the next binop in this subexpression. For
+ // example, when parsing x+y*z and looking at '*', we want to recursively
+ // handle y*z as a single subexpression. We do this because the precedence
+ // of * is higher than that of +. The only strange case we have to handle
+ // here is for the ?: operator, where the precedence is actually lower than
+ // the LHS of the '?'. The grammar rule is:
+ //
+ // conditional-expression ::=
+ // logical-OR-expression ? expression : conditional-expression
+ // where 'expression' is actually comma-expression.
+ unsigned RHSPrec;
+ if (Operator == tok::question)
+ // The RHS of "?" should be maximally consumed as an expression.
+ RHSPrec = getPrecedence(tok::comma);
+ else // All others should munch while higher precedence.
+ RHSPrec = ThisPrec+1;
+
+ if (PeekPrec >= RHSPrec) {
+ if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, PP))
+ return true;
+ PeekPrec = getPrecedence(PeekTok.getKind());
+ }
+ assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
+
+ // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
+ // either operand is unsigned.
+ llvm::APSInt Res(LHS.getBitWidth());
+ switch (Operator) {
+ case tok::question: // No UAC for x and y in "x ? y : z".
+ case tok::lessless: // Shift amount doesn't UAC with shift value.
+ case tok::greatergreater: // Shift amount doesn't UAC with shift value.
+ case tok::comma: // Comma operands are not subject to UACs.
+ case tok::pipepipe: // Logical || does not do UACs.
+ case tok::ampamp: // Logical && does not do UACs.
+ break; // No UAC
+ default:
+ Res.setIsUnsigned(LHS.isUnsigned()|RHS.isUnsigned());
+ // If this just promoted something from signed to unsigned, and if the
+ // value was negative, warn about it.
+ if (ValueLive && Res.isUnsigned()) {
+ if (!LHS.isUnsigned() && LHS.Val.isNegative())
+ PP.Diag(OpLoc, diag::warn_pp_convert_lhs_to_positive)
+ << LHS.Val.toString(10, true) + " to " +
+ LHS.Val.toString(10, false)
+ << LHS.getRange() << RHS.getRange();
+ if (!RHS.isUnsigned() && RHS.Val.isNegative())
+ PP.Diag(OpLoc, diag::warn_pp_convert_rhs_to_positive)
+ << RHS.Val.toString(10, true) + " to " +
+ RHS.Val.toString(10, false)
+ << LHS.getRange() << RHS.getRange();
+ }
+ LHS.Val.setIsUnsigned(Res.isUnsigned());
+ RHS.Val.setIsUnsigned(Res.isUnsigned());
+ }
+
+ bool Overflow = false;
+ switch (Operator) {
+ default: assert(0 && "Unknown operator token!");
+ case tok::percent:
+ if (RHS.Val != 0)
+ Res = LHS.Val % RHS.Val;
+ else if (ValueLive) {
+ PP.Diag(OpLoc, diag::err_pp_remainder_by_zero)
+ << LHS.getRange() << RHS.getRange();
+ return true;
+ }
+ break;
+ case tok::slash:
+ if (RHS.Val != 0) {
+ if (LHS.Val.isSigned())
+ Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false);
+ else
+ Res = LHS.Val / RHS.Val;
+ } else if (ValueLive) {
+ PP.Diag(OpLoc, diag::err_pp_division_by_zero)
+ << LHS.getRange() << RHS.getRange();
+ return true;
+ }
+ break;
+
+ case tok::star:
+ if (Res.isSigned())
+ Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false);
+ else
+ Res = LHS.Val * RHS.Val;
+ break;
+ case tok::lessless: {
+ // Determine whether overflow is about to happen.
+ unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
+ if (LHS.isUnsigned()) {
+ Overflow = ShAmt >= LHS.Val.getBitWidth();
+ if (Overflow)
+ ShAmt = LHS.Val.getBitWidth()-1;
+ Res = LHS.Val << ShAmt;
+ } else {
+ Res = llvm::APSInt(LHS.Val.sshl_ov(ShAmt, Overflow), false);
+ }
+ break;
+ }
+ case tok::greatergreater: {
+ // Determine whether overflow is about to happen.
+ unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
+ if (ShAmt >= LHS.getBitWidth())
+ Overflow = true, ShAmt = LHS.getBitWidth()-1;
+ Res = LHS.Val >> ShAmt;
+ break;
+ }
+ case tok::plus:
+ if (LHS.isUnsigned())
+ Res = LHS.Val + RHS.Val;
+ else
+ Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false);
+ break;
+ case tok::minus:
+ if (LHS.isUnsigned())
+ Res = LHS.Val - RHS.Val;
+ else
+ Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false);
+ break;
+ case tok::lessequal:
+ Res = LHS.Val <= RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
+ break;
+ case tok::less:
+ Res = LHS.Val < RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
+ break;
+ case tok::greaterequal:
+ Res = LHS.Val >= RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
+ break;
+ case tok::greater:
+ Res = LHS.Val > RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
+ break;
+ case tok::exclaimequal:
+ Res = LHS.Val != RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
+ break;
+ case tok::equalequal:
+ Res = LHS.Val == RHS.Val;
+ Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
+ break;
+ case tok::amp:
+ Res = LHS.Val & RHS.Val;
+ break;
+ case tok::caret:
+ Res = LHS.Val ^ RHS.Val;
+ break;
+ case tok::pipe:
+ Res = LHS.Val | RHS.Val;
+ break;
+ case tok::ampamp:
+ Res = (LHS.Val != 0 && RHS.Val != 0);
+ Res.setIsUnsigned(false); // C99 6.5.13p3, result is always int (signed)
+ break;
+ case tok::pipepipe:
+ Res = (LHS.Val != 0 || RHS.Val != 0);
+ Res.setIsUnsigned(false); // C99 6.5.14p3, result is always int (signed)
+ break;
+ case tok::comma:
+ // Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99
+ // if not being evaluated.
+ if (!PP.getLangOptions().C99 || ValueLive)
+ PP.Diag(OpLoc, diag::ext_pp_comma_expr)
+ << LHS.getRange() << RHS.getRange();
+ Res = RHS.Val; // LHS = LHS,RHS -> RHS.
+ break;
+ case tok::question: {
+ // Parse the : part of the expression.
+ if (PeekTok.isNot(tok::colon)) {
+ PP.Diag(PeekTok.getLocation(), diag::err_expected_colon)
+ << LHS.getRange(), RHS.getRange();
+ PP.Diag(OpLoc, diag::note_matching) << "?";
+ return true;
+ }
+ // Consume the :.
+ PP.LexNonComment(PeekTok);
+
+ // Evaluate the value after the :.
+ bool AfterColonLive = ValueLive && LHS.Val == 0;
+ PPValue AfterColonVal(LHS.getBitWidth());
+ DefinedTracker DT;
+ if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
+ return true;
+
+ // Parse anything after the : with the same precedence as ?. We allow
+ // things of equal precedence because ?: is right associative.
+ if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,
+ PeekTok, AfterColonLive, PP))
+ return true;
+
+ // Now that we have the condition, the LHS and the RHS of the :, evaluate.
+ Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
+ RHS.setEnd(AfterColonVal.getRange().getEnd());
+
+ // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
+ // either operand is unsigned.
+ Res.setIsUnsigned(RHS.isUnsigned() | AfterColonVal.isUnsigned());
+
+ // Figure out the precedence of the token after the : part.
+ PeekPrec = getPrecedence(PeekTok.getKind());
+ break;
+ }
+ case tok::colon:
+ // Don't allow :'s to float around without being part of ?: exprs.
+ PP.Diag(OpLoc, diag::err_pp_colon_without_question)
+ << LHS.getRange() << RHS.getRange();
+ return true;
+ }
+
+ // If this operator is live and overflowed, report the issue.
+ if (Overflow && ValueLive)
+ PP.Diag(OpLoc, diag::warn_pp_expr_overflow)
+ << LHS.getRange() << RHS.getRange();
+
+ // Put the result back into 'LHS' for our next iteration.
+ LHS.Val = Res;
+ LHS.setEnd(RHS.getRange().getEnd());
+ }
+
+ return false;
+}
+
+/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
+/// may occur after a #if or #elif directive. If the expression is equivalent
+/// to "!defined(X)" return X in IfNDefMacro.
+bool Preprocessor::
+EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
+ // Save the current state of 'DisableMacroExpansion' and reset it to false. If
+ // 'DisableMacroExpansion' is true, then we must be in a macro argument list
+ // in which case a directive is undefined behavior. We want macros to be able
+ // to recursively expand in order to get more gcc-list behavior, so we force
+ // DisableMacroExpansion to false and restore it when we're done parsing the
+ // expression.
+ bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
+ DisableMacroExpansion = false;
+
+ // Peek ahead one token.
+ Token Tok;
+ Lex(Tok);
+
+ // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
+ unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
+
+ PPValue ResVal(BitWidth);
+ DefinedTracker DT;
+ if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
+ // Parse error, skip the rest of the macro line.
+ if (Tok.isNot(tok::eom))
+ DiscardUntilEndOfDirective();
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
+ return false;
+ }
+
+ // If we are at the end of the expression after just parsing a value, there
+ // must be no (unparenthesized) binary operators involved, so we can exit
+ // directly.
+ if (Tok.is(tok::eom)) {
+ // If the expression we parsed was of the form !defined(macro), return the
+ // macro in IfNDefMacro.
+ if (DT.State == DefinedTracker::NotDefinedMacro)
+ IfNDefMacro = DT.TheMacro;
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
+ return ResVal.Val != 0;
+ }
+
+ // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
+ // operator and the stuff after it.
+ if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),
+ Tok, true, *this)) {
+ // Parse error, skip the rest of the macro line.
+ if (Tok.isNot(tok::eom))
+ DiscardUntilEndOfDirective();
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
+ return false;
+ }
+
+ // If we aren't at the tok::eom token, something bad happened, like an extra
+ // ')' token.
+ if (Tok.isNot(tok::eom)) {
+ Diag(Tok, diag::err_pp_expected_eol);
+ DiscardUntilEndOfDirective();
+ }
+
+ // Restore 'DisableMacroExpansion'.
+ DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
+ return ResVal.Val != 0;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
new file mode 100644
index 0000000..eef42b6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -0,0 +1,358 @@
+//===--- PPLexerChange.cpp - Handle changing lexers in the preprocessor ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements pieces of the Preprocessor interface that manage the
+// current lexer stack.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+using namespace clang;
+
+PPCallbacks::~PPCallbacks() {}
+
+//===----------------------------------------------------------------------===//
+// Miscellaneous Methods.
+//===----------------------------------------------------------------------===//
+
+/// isInPrimaryFile - Return true if we're in the top-level file, not in a
+/// #include. This looks through macro expansions and active _Pragma lexers.
+bool Preprocessor::isInPrimaryFile() const {
+ if (IsFileLexer())
+ return IncludeMacroStack.empty();
+
+ // If there are any stacked lexers, we're in a #include.
+ assert(IsFileLexer(IncludeMacroStack[0]) &&
+ "Top level include stack isn't our primary lexer?");
+ for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i)
+ if (IsFileLexer(IncludeMacroStack[i]))
+ return false;
+ return true;
+}
+
+/// getCurrentLexer - Return the current file lexer being lexed from. Note
+/// that this ignores any potentially active macro expansions and _Pragma
+/// expansions going on at the time.
+PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
+ if (IsFileLexer())
+ return CurPPLexer;
+
+ // Look for a stacked lexer.
+ for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
+ const IncludeStackInfo& ISI = IncludeMacroStack[i-1];
+ if (IsFileLexer(ISI))
+ return ISI.ThePPLexer;
+ }
+ return 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Methods for Entering and Callbacks for leaving various contexts
+//===----------------------------------------------------------------------===//
+
+/// EnterSourceFile - Add a source file to the top of the include stack and
+/// start lexing tokens from it instead of the current buffer.
+void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
+ SourceLocation Loc) {
+ assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!");
+ ++NumEnteredSourceFiles;
+
+ if (MaxIncludeStackDepth < IncludeMacroStack.size())
+ MaxIncludeStackDepth = IncludeMacroStack.size();
+
+ if (PTH) {
+ if (PTHLexer *PL = PTH->CreateLexer(FID)) {
+ EnterSourceFileWithPTH(PL, CurDir);
+ return;
+ }
+ }
+
+ // Get the MemoryBuffer for this FID, if it fails, we fail.
+ bool Invalid = false;
+ const llvm::MemoryBuffer *InputFile =
+ getSourceManager().getBuffer(FID, Loc, &Invalid);
+ if (Invalid) {
+ SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID);
+ Diag(Loc, diag::err_pp_error_opening_file)
+ << std::string(SourceMgr.getBufferName(FileStart)) << "";
+ return;
+ }
+
+ EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);
+ return;
+}
+
+/// EnterSourceFileWithLexer - Add a source file to the top of the include stack
+/// and start lexing tokens from it instead of the current buffer.
+void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
+ const DirectoryLookup *CurDir) {
+
+ // Add the current lexer to the include stack.
+ if (CurPPLexer || CurTokenLexer)
+ PushIncludeMacroStack();
+
+ CurLexer.reset(TheLexer);
+ CurPPLexer = TheLexer;
+ CurDirLookup = CurDir;
+
+ // Notify the client, if desired, that we are in a new source file.
+ if (Callbacks && !CurLexer->Is_PragmaLexer) {
+ SrcMgr::CharacteristicKind FileType =
+ SourceMgr.getFileCharacteristic(CurLexer->getFileLoc());
+
+ Callbacks->FileChanged(CurLexer->getFileLoc(),
+ PPCallbacks::EnterFile, FileType);
+ }
+}
+
+/// EnterSourceFileWithPTH - Add a source file to the top of the include stack
+/// and start getting tokens from it using the PTH cache.
+void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
+ const DirectoryLookup *CurDir) {
+
+ if (CurPPLexer || CurTokenLexer)
+ PushIncludeMacroStack();
+
+ CurDirLookup = CurDir;
+ CurPTHLexer.reset(PL);
+ CurPPLexer = CurPTHLexer.get();
+
+ // Notify the client, if desired, that we are in a new source file.
+ if (Callbacks) {
+ FileID FID = CurPPLexer->getFileID();
+ SourceLocation EnterLoc = SourceMgr.getLocForStartOfFile(FID);
+ SrcMgr::CharacteristicKind FileType =
+ SourceMgr.getFileCharacteristic(EnterLoc);
+ Callbacks->FileChanged(EnterLoc, PPCallbacks::EnterFile, FileType);
+ }
+}
+
+/// EnterMacro - Add a Macro to the top of the include stack and start lexing
+/// tokens from it instead of the current buffer.
+void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
+ MacroArgs *Args) {
+ PushIncludeMacroStack();
+ CurDirLookup = 0;
+
+ if (NumCachedTokenLexers == 0) {
+ CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Args, *this));
+ } else {
+ CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
+ CurTokenLexer->Init(Tok, ILEnd, Args);
+ }
+}
+
+/// EnterTokenStream - Add a "macro" context to the top of the include stack,
+/// which will cause the lexer to start returning the specified tokens.
+///
+/// If DisableMacroExpansion is true, tokens lexed from the token stream will
+/// not be subject to further macro expansion. Otherwise, these tokens will
+/// be re-macro-expanded when/if expansion is enabled.
+///
+/// If OwnsTokens is false, this method assumes that the specified stream of
+/// tokens has a permanent owner somewhere, so they do not need to be copied.
+/// If it is true, it assumes the array of tokens is allocated with new[] and
+/// must be freed.
+///
+void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
+ bool DisableMacroExpansion,
+ bool OwnsTokens) {
+ // Save our current state.
+ PushIncludeMacroStack();
+ CurDirLookup = 0;
+
+ // Create a macro expander to expand from the specified token stream.
+ if (NumCachedTokenLexers == 0) {
+ CurTokenLexer.reset(new TokenLexer(Toks, NumToks, DisableMacroExpansion,
+ OwnsTokens, *this));
+ } else {
+ CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
+ CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
+ }
+}
+
+/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
+/// the current file. This either returns the EOF token or pops a level off
+/// the include stack and keeps going.
+bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
+ assert(!CurTokenLexer &&
+ "Ending a file when currently in a macro!");
+
+ // See if this file had a controlling macro.
+ if (CurPPLexer) { // Not ending a macro, ignore it.
+ if (const IdentifierInfo *ControllingMacro =
+ CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
+ // Okay, this has a controlling macro, remember in HeaderFileInfo.
+ if (const FileEntry *FE =
+ SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))
+ HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
+ }
+ }
+
+ // If this is a #include'd file, pop it off the include stack and continue
+ // lexing the #includer file.
+ if (!IncludeMacroStack.empty()) {
+ // We're done with the #included file.
+ RemoveTopOfLexerStack();
+
+ // Notify the client, if desired, that we are in a new source file.
+ if (Callbacks && !isEndOfMacro && CurPPLexer) {
+ SrcMgr::CharacteristicKind FileType =
+ SourceMgr.getFileCharacteristic(CurPPLexer->getSourceLocation());
+ Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
+ PPCallbacks::ExitFile, FileType);
+ }
+
+ // Client should lex another token.
+ return false;
+ }
+
+ // If the file ends with a newline, form the EOF token on the newline itself,
+ // rather than "on the line following it", which doesn't exist. This makes
+ // diagnostics relating to the end of file include the last file that the user
+ // actually typed, which is goodness.
+ if (CurLexer) {
+ const char *EndPos = CurLexer->BufferEnd;
+ if (EndPos != CurLexer->BufferStart &&
+ (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
+ --EndPos;
+
+ // Handle \n\r and \r\n:
+ if (EndPos != CurLexer->BufferStart &&
+ (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
+ EndPos[-1] != EndPos[0])
+ --EndPos;
+ }
+
+ Result.startToken();
+ CurLexer->BufferPtr = EndPos;
+ CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+
+ // We're done with the #included file.
+ CurLexer.reset();
+ } else {
+ assert(CurPTHLexer && "Got EOF but no current lexer set!");
+ CurPTHLexer->getEOF(Result);
+ CurPTHLexer.reset();
+ }
+
+ CurPPLexer = 0;
+
+ // This is the end of the top-level file. 'WarnUnusedMacroLocs' has collected
+ // all macro locations that we need to warn because they are not used.
+ for (WarnUnusedMacroLocsTy::iterator
+ I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I)
+ Diag(*I, diag::pp_macro_not_used);
+
+ return true;
+}
+
+/// HandleEndOfTokenLexer - This callback is invoked when the current TokenLexer
+/// hits the end of its token stream.
+bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
+ assert(CurTokenLexer && !CurPPLexer &&
+ "Ending a macro when currently in a #include file!");
+
+ // Delete or cache the now-dead macro expander.
+ if (NumCachedTokenLexers == TokenLexerCacheSize)
+ CurTokenLexer.reset();
+ else
+ TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
+
+ // Handle this like a #include file being popped off the stack.
+ return HandleEndOfFile(Result, true);
+}
+
+/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
+/// lexer stack. This should only be used in situations where the current
+/// state of the top-of-stack lexer is unknown.
+void Preprocessor::RemoveTopOfLexerStack() {
+ assert(!IncludeMacroStack.empty() && "Ran out of stack entries to load");
+
+ if (CurTokenLexer) {
+ // Delete or cache the now-dead macro expander.
+ if (NumCachedTokenLexers == TokenLexerCacheSize)
+ CurTokenLexer.reset();
+ else
+ TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
+ }
+
+ PopIncludeMacroStack();
+}
+
+/// HandleMicrosoftCommentPaste - When the macro expander pastes together a
+/// comment (/##/) in microsoft mode, this method handles updating the current
+/// state, returning the token on the next source line.
+void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
+ assert(CurTokenLexer && !CurPPLexer &&
+ "Pasted comment can only be formed from macro");
+
+ // We handle this by scanning for the closest real lexer, switching it to
+ // raw mode and preprocessor mode. This will cause it to return \n as an
+ // explicit EOM token.
+ PreprocessorLexer *FoundLexer = 0;
+ bool LexerWasInPPMode = false;
+ for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
+ IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
+ if (ISI.ThePPLexer == 0) continue; // Scan for a real lexer.
+
+ // Once we find a real lexer, mark it as raw mode (disabling macro
+ // expansions) and preprocessor mode (return EOM). We know that the lexer
+ // was *not* in raw mode before, because the macro that the comment came
+ // from was expanded. However, it could have already been in preprocessor
+ // mode (#if COMMENT) in which case we have to return it to that mode and
+ // return EOM.
+ FoundLexer = ISI.ThePPLexer;
+ FoundLexer->LexingRawMode = true;
+ LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective;
+ FoundLexer->ParsingPreprocessorDirective = true;
+ break;
+ }
+
+ // Okay, we either found and switched over the lexer, or we didn't find a
+ // lexer. In either case, finish off the macro the comment came from, getting
+ // the next token.
+ if (!HandleEndOfTokenLexer(Tok)) Lex(Tok);
+
+ // Discarding comments as long as we don't have EOF or EOM. This 'comments
+ // out' the rest of the line, including any tokens that came from other macros
+ // that were active, as in:
+ // #define submacro a COMMENT b
+ // submacro c
+ // which should lex to 'a' only: 'b' and 'c' should be removed.
+ while (Tok.isNot(tok::eom) && Tok.isNot(tok::eof))
+ Lex(Tok);
+
+ // If we got an eom token, then we successfully found the end of the line.
+ if (Tok.is(tok::eom)) {
+ assert(FoundLexer && "Can't get end of line without an active lexer");
+ // Restore the lexer back to normal mode instead of raw mode.
+ FoundLexer->LexingRawMode = false;
+
+ // If the lexer was already in preprocessor mode, just return the EOM token
+ // to finish the preprocessor line.
+ if (LexerWasInPPMode) return;
+
+ // Otherwise, switch out of PP mode and return the next lexed token.
+ FoundLexer->ParsingPreprocessorDirective = false;
+ return Lex(Tok);
+ }
+
+ // If we got an EOF token, then we reached the end of the token stream but
+ // didn't find an explicit \n. This can only happen if there was no lexer
+ // active (an active lexer would return EOM at EOF if there was no \n in
+ // preprocessor directive mode), so just return EOF as our token.
+ assert(!FoundLexer && "Lexer should return EOM before EOF in PP mode");
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
new file mode 100644
index 0000000..ba92614
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
@@ -0,0 +1,902 @@
+//===--- MacroExpansion.cpp - Top level Macro Expansion -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the top level handling of macro expasion for the
+// preprocessor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "MacroArgs.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+#include <ctime>
+using namespace clang;
+
+MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const {
+ assert(II->hasMacroDefinition() && "Identifier is not a macro!");
+
+ llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator Pos
+ = Macros.find(II);
+ if (Pos == Macros.end()) {
+ // Load this macro from the external source.
+ getExternalSource()->LoadMacroDefinition(II);
+ Pos = Macros.find(II);
+ }
+ assert(Pos != Macros.end() && "Identifier macro info is missing!");
+ return Pos->second;
+}
+
+/// setMacroInfo - Specify a macro for this identifier.
+///
+void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
+ if (MI) {
+ Macros[II] = MI;
+ II->setHasMacroDefinition(true);
+ } else if (II->hasMacroDefinition()) {
+ Macros.erase(II);
+ II->setHasMacroDefinition(false);
+ }
+}
+
+/// RegisterBuiltinMacro - Register the specified identifier in the identifier
+/// table and mark it as a builtin macro to be expanded.
+static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
+ // Get the identifier.
+ IdentifierInfo *Id = PP.getIdentifierInfo(Name);
+
+ // Mark it as being a macro that is builtin.
+ MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation());
+ MI->setIsBuiltinMacro();
+ PP.setMacroInfo(Id, MI);
+ return Id;
+}
+
+
+/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
+/// identifier table.
+void Preprocessor::RegisterBuiltinMacros() {
+ Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__");
+ Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__");
+ Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__");
+ Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__");
+ Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
+ Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
+
+ // GCC Extensions.
+ Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__");
+ Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
+ Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
+
+ // Clang Extensions.
+ Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+ Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+ Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
+ Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
+ Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
+
+ // Microsoft Extensions.
+ if (Features.Microsoft)
+ Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
+ else
+ Ident__pragma = 0;
+}
+
+/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
+/// in its expansion, currently expands to that token literally.
+static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
+ const IdentifierInfo *MacroIdent,
+ Preprocessor &PP) {
+ IdentifierInfo *II = MI->getReplacementToken(0).getIdentifierInfo();
+
+ // If the token isn't an identifier, it's always literally expanded.
+ if (II == 0) return true;
+
+ // If the identifier is a macro, and if that macro is enabled, it may be
+ // expanded so it's not a trivial expansion.
+ if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled() &&
+ // Fast expanding "#define X X" is ok, because X would be disabled.
+ II != MacroIdent)
+ return false;
+
+ // If this is an object-like macro invocation, it is safe to trivially expand
+ // it.
+ if (MI->isObjectLike()) return true;
+
+ // If this is a function-like macro invocation, it's safe to trivially expand
+ // as long as the identifier is not a macro argument.
+ for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
+ I != E; ++I)
+ if (*I == II)
+ return false; // Identifier is a macro argument.
+
+ return true;
+}
+
+
+/// isNextPPTokenLParen - Determine whether the next preprocessor token to be
+/// lexed is a '('. If so, consume the token and return true, if not, this
+/// method should have no observable side-effect on the lexed tokens.
+bool Preprocessor::isNextPPTokenLParen() {
+ // Do some quick tests for rejection cases.
+ unsigned Val;
+ if (CurLexer)
+ Val = CurLexer->isNextPPTokenLParen();
+ else if (CurPTHLexer)
+ Val = CurPTHLexer->isNextPPTokenLParen();
+ else
+ Val = CurTokenLexer->isNextTokenLParen();
+
+ if (Val == 2) {
+ // We have run off the end. If it's a source file we don't
+ // examine enclosing ones (C99 5.1.1.2p4). Otherwise walk up the
+ // macro stack.
+ if (CurPPLexer)
+ return false;
+ for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
+ IncludeStackInfo &Entry = IncludeMacroStack[i-1];
+ if (Entry.TheLexer)
+ Val = Entry.TheLexer->isNextPPTokenLParen();
+ else if (Entry.ThePTHLexer)
+ Val = Entry.ThePTHLexer->isNextPPTokenLParen();
+ else
+ Val = Entry.TheTokenLexer->isNextTokenLParen();
+
+ if (Val != 2)
+ break;
+
+ // Ran off the end of a source file?
+ if (Entry.ThePPLexer)
+ return false;
+ }
+ }
+
+ // Okay, if we know that the token is a '(', lex it and return. Otherwise we
+ // have found something that isn't a '(' or we found the end of the
+ // translation unit. In either case, return false.
+ return Val == 1;
+}
+
+/// HandleMacroExpandedIdentifier - If an identifier token is read that is to be
+/// expanded as a macro, handle it and return the next token as 'Identifier'.
+bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
+ MacroInfo *MI) {
+ if (Callbacks) Callbacks->MacroExpands(Identifier, MI);
+
+ // If this is a macro expansion in the "#if !defined(x)" line for the file,
+ // then the macro could expand to different things in other contexts, we need
+ // to disable the optimization in this case.
+ if (CurPPLexer) CurPPLexer->MIOpt.ExpandedMacro();
+
+ // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
+ if (MI->isBuiltinMacro()) {
+ ExpandBuiltinMacro(Identifier);
+ return false;
+ }
+
+ /// Args - If this is a function-like macro expansion, this contains,
+ /// for each macro argument, the list of tokens that were provided to the
+ /// invocation.
+ MacroArgs *Args = 0;
+
+ // Remember where the end of the instantiation occurred. For an object-like
+ // macro, this is the identifier. For a function-like macro, this is the ')'.
+ SourceLocation InstantiationEnd = Identifier.getLocation();
+
+ // If this is a function-like macro, read the arguments.
+ if (MI->isFunctionLike()) {
+ // C99 6.10.3p10: If the preprocessing token immediately after the the macro
+ // name isn't a '(', this macro should not be expanded.
+ if (!isNextPPTokenLParen())
+ return true;
+
+ // Remember that we are now parsing the arguments to a macro invocation.
+ // Preprocessor directives used inside macro arguments are not portable, and
+ // this enables the warning.
+ InMacroArgs = true;
+ Args = ReadFunctionLikeMacroArgs(Identifier, MI, InstantiationEnd);
+
+ // Finished parsing args.
+ InMacroArgs = false;
+
+ // If there was an error parsing the arguments, bail out.
+ if (Args == 0) return false;
+
+ ++NumFnMacroExpanded;
+ } else {
+ ++NumMacroExpanded;
+ }
+
+ // Notice that this macro has been used.
+ markMacroAsUsed(MI);
+
+ // If we started lexing a macro, enter the macro expansion body.
+
+ // If this macro expands to no tokens, don't bother to push it onto the
+ // expansion stack, only to take it right back off.
+ if (MI->getNumTokens() == 0) {
+ // No need for arg info.
+ if (Args) Args->destroy(*this);
+
+ // Ignore this macro use, just return the next token in the current
+ // buffer.
+ bool HadLeadingSpace = Identifier.hasLeadingSpace();
+ bool IsAtStartOfLine = Identifier.isAtStartOfLine();
+
+ Lex(Identifier);
+
+ // If the identifier isn't on some OTHER line, inherit the leading
+ // whitespace/first-on-a-line property of this token. This handles
+ // stuff like "! XX," -> "! ," and " XX," -> " ,", when XX is
+ // empty.
+ if (!Identifier.isAtStartOfLine()) {
+ if (IsAtStartOfLine) Identifier.setFlag(Token::StartOfLine);
+ if (HadLeadingSpace) Identifier.setFlag(Token::LeadingSpace);
+ }
+ Identifier.setFlag(Token::LeadingEmptyMacro);
+ ++NumFastMacroExpanded;
+ return false;
+
+ } else if (MI->getNumTokens() == 1 &&
+ isTrivialSingleTokenExpansion(MI, Identifier.getIdentifierInfo(),
+ *this)) {
+ // Otherwise, if this macro expands into a single trivially-expanded
+ // token: expand it now. This handles common cases like
+ // "#define VAL 42".
+
+ // No need for arg info.
+ if (Args) Args->destroy(*this);
+
+ // Propagate the isAtStartOfLine/hasLeadingSpace markers of the macro
+ // identifier to the expanded token.
+ bool isAtStartOfLine = Identifier.isAtStartOfLine();
+ bool hasLeadingSpace = Identifier.hasLeadingSpace();
+
+ // Remember where the token is instantiated.
+ SourceLocation InstantiateLoc = Identifier.getLocation();
+
+ // Replace the result token.
+ Identifier = MI->getReplacementToken(0);
+
+ // Restore the StartOfLine/LeadingSpace markers.
+ Identifier.setFlagValue(Token::StartOfLine , isAtStartOfLine);
+ Identifier.setFlagValue(Token::LeadingSpace, hasLeadingSpace);
+
+ // Update the tokens location to include both its instantiation and physical
+ // locations.
+ SourceLocation Loc =
+ SourceMgr.createInstantiationLoc(Identifier.getLocation(), InstantiateLoc,
+ InstantiationEnd,Identifier.getLength());
+ Identifier.setLocation(Loc);
+
+ // If this is a disabled macro or #define X X, we must mark the result as
+ // unexpandable.
+ if (IdentifierInfo *NewII = Identifier.getIdentifierInfo()) {
+ if (MacroInfo *NewMI = getMacroInfo(NewII))
+ if (!NewMI->isEnabled() || NewMI == MI)
+ Identifier.setFlag(Token::DisableExpand);
+ }
+
+ // Since this is not an identifier token, it can't be macro expanded, so
+ // we're done.
+ ++NumFastMacroExpanded;
+ return false;
+ }
+
+ // Start expanding the macro.
+ EnterMacro(Identifier, InstantiationEnd, Args);
+
+ // Now that the macro is at the top of the include stack, ask the
+ // preprocessor to read the next token from it.
+ Lex(Identifier);
+ return false;
+}
+
+/// ReadFunctionLikeMacroArgs - After reading "MACRO" and knowing that the next
+/// token is the '(' of the macro, this method is invoked to read all of the
+/// actual arguments specified for the macro invocation. This returns null on
+/// error.
+MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
+ MacroInfo *MI,
+ SourceLocation &MacroEnd) {
+ // The number of fixed arguments to parse.
+ unsigned NumFixedArgsLeft = MI->getNumArgs();
+ bool isVariadic = MI->isVariadic();
+
+ // Outer loop, while there are more arguments, keep reading them.
+ Token Tok;
+
+ // Read arguments as unexpanded tokens. This avoids issues, e.g., where
+ // an argument value in a macro could expand to ',' or '(' or ')'.
+ LexUnexpandedToken(Tok);
+ assert(Tok.is(tok::l_paren) && "Error computing l-paren-ness?");
+
+ // ArgTokens - Build up a list of tokens that make up each argument. Each
+ // argument is separated by an EOF token. Use a SmallVector so we can avoid
+ // heap allocations in the common case.
+ llvm::SmallVector<Token, 64> ArgTokens;
+
+ unsigned NumActuals = 0;
+ while (Tok.isNot(tok::r_paren)) {
+ assert((Tok.is(tok::l_paren) || Tok.is(tok::comma)) &&
+ "only expect argument separators here");
+
+ unsigned ArgTokenStart = ArgTokens.size();
+ SourceLocation ArgStartLoc = Tok.getLocation();
+
+ // C99 6.10.3p11: Keep track of the number of l_parens we have seen. Note
+ // that we already consumed the first one.
+ unsigned NumParens = 0;
+
+ while (1) {
+ // Read arguments as unexpanded tokens. This avoids issues, e.g., where
+ // an argument value in a macro could expand to ',' or '(' or ')'.
+ LexUnexpandedToken(Tok);
+
+ if (Tok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteMacroArgument(MacroName.getIdentifierInfo(),
+ MI, NumActuals);
+ LexUnexpandedToken(Tok);
+ }
+
+ if (Tok.is(tok::eof) || Tok.is(tok::eom)) { // "#if f(<eof>" & "#if f(\n"
+ Diag(MacroName, diag::err_unterm_macro_invoc);
+ // Do not lose the EOF/EOM. Return it to the client.
+ MacroName = Tok;
+ return 0;
+ } else if (Tok.is(tok::r_paren)) {
+ // If we found the ) token, the macro arg list is done.
+ if (NumParens-- == 0) {
+ MacroEnd = Tok.getLocation();
+ break;
+ }
+ } else if (Tok.is(tok::l_paren)) {
+ ++NumParens;
+ } else if (Tok.is(tok::comma) && NumParens == 0) {
+ // Comma ends this argument if there are more fixed arguments expected.
+ // However, if this is a variadic macro, and this is part of the
+ // variadic part, then the comma is just an argument token.
+ if (!isVariadic) break;
+ if (NumFixedArgsLeft > 1)
+ break;
+ } else if (Tok.is(tok::comment) && !KeepMacroComments) {
+ // If this is a comment token in the argument list and we're just in
+ // -C mode (not -CC mode), discard the comment.
+ continue;
+ } else if (Tok.getIdentifierInfo() != 0) {
+ // Reading macro arguments can cause macros that we are currently
+ // expanding from to be popped off the expansion stack. Doing so causes
+ // them to be reenabled for expansion. Here we record whether any
+ // identifiers we lex as macro arguments correspond to disabled macros.
+ // If so, we mark the token as noexpand. This is a subtle aspect of
+ // C99 6.10.3.4p2.
+ if (MacroInfo *MI = getMacroInfo(Tok.getIdentifierInfo()))
+ if (!MI->isEnabled())
+ Tok.setFlag(Token::DisableExpand);
+ }
+ ArgTokens.push_back(Tok);
+ }
+
+ // If this was an empty argument list foo(), don't add this as an empty
+ // argument.
+ if (ArgTokens.empty() && Tok.getKind() == tok::r_paren)
+ break;
+
+ // If this is not a variadic macro, and too many args were specified, emit
+ // an error.
+ if (!isVariadic && NumFixedArgsLeft == 0) {
+ if (ArgTokens.size() != ArgTokenStart)
+ ArgStartLoc = ArgTokens[ArgTokenStart].getLocation();
+
+ // Emit the diagnostic at the macro name in case there is a missing ).
+ // Emitting it at the , could be far away from the macro name.
+ Diag(ArgStartLoc, diag::err_too_many_args_in_macro_invoc);
+ return 0;
+ }
+
+ // Empty arguments are standard in C99 and supported as an extension in
+ // other modes.
+ if (ArgTokens.size() == ArgTokenStart && !Features.C99)
+ Diag(Tok, diag::ext_empty_fnmacro_arg);
+
+ // Add a marker EOF token to the end of the token list for this argument.
+ Token EOFTok;
+ EOFTok.startToken();
+ EOFTok.setKind(tok::eof);
+ EOFTok.setLocation(Tok.getLocation());
+ EOFTok.setLength(0);
+ ArgTokens.push_back(EOFTok);
+ ++NumActuals;
+ assert(NumFixedArgsLeft != 0 && "Too many arguments parsed");
+ --NumFixedArgsLeft;
+ }
+
+ // Okay, we either found the r_paren. Check to see if we parsed too few
+ // arguments.
+ unsigned MinArgsExpected = MI->getNumArgs();
+
+ // See MacroArgs instance var for description of this.
+ bool isVarargsElided = false;
+
+ if (NumActuals < MinArgsExpected) {
+ // There are several cases where too few arguments is ok, handle them now.
+ if (NumActuals == 0 && MinArgsExpected == 1) {
+ // #define A(X) or #define A(...) ---> A()
+
+ // If there is exactly one argument, and that argument is missing,
+ // then we have an empty "()" argument empty list. This is fine, even if
+ // the macro expects one argument (the argument is just empty).
+ isVarargsElided = MI->isVariadic();
+ } else if (MI->isVariadic() &&
+ (NumActuals+1 == MinArgsExpected || // A(x, ...) -> A(X)
+ (NumActuals == 0 && MinArgsExpected == 2))) {// A(x,...) -> A()
+ // Varargs where the named vararg parameter is missing: ok as extension.
+ // #define A(x, ...)
+ // A("blah")
+ Diag(Tok, diag::ext_missing_varargs_arg);
+
+ // Remember this occurred, allowing us to elide the comma when used for
+ // cases like:
+ // #define A(x, foo...) blah(a, ## foo)
+ // #define B(x, ...) blah(a, ## __VA_ARGS__)
+ // #define C(...) blah(a, ## __VA_ARGS__)
+ // A(x) B(x) C()
+ isVarargsElided = true;
+ } else {
+ // Otherwise, emit the error.
+ Diag(Tok, diag::err_too_few_args_in_macro_invoc);
+ return 0;
+ }
+
+ // Add a marker EOF token to the end of the token list for this argument.
+ SourceLocation EndLoc = Tok.getLocation();
+ Tok.startToken();
+ Tok.setKind(tok::eof);
+ Tok.setLocation(EndLoc);
+ Tok.setLength(0);
+ ArgTokens.push_back(Tok);
+
+ // If we expect two arguments, add both as empty.
+ if (NumActuals == 0 && MinArgsExpected == 2)
+ ArgTokens.push_back(Tok);
+
+ } else if (NumActuals > MinArgsExpected && !MI->isVariadic()) {
+ // Emit the diagnostic at the macro name in case there is a missing ).
+ // Emitting it at the , could be far away from the macro name.
+ Diag(MacroName, diag::err_too_many_args_in_macro_invoc);
+ return 0;
+ }
+
+ return MacroArgs::create(MI, ArgTokens.data(), ArgTokens.size(),
+ isVarargsElided, *this);
+}
+
+/// ComputeDATE_TIME - Compute the current time, enter it into the specified
+/// scratch buffer, then return DATELoc/TIMELoc locations with the position of
+/// the identifier tokens inserted.
+static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
+ Preprocessor &PP) {
+ time_t TT = time(0);
+ struct tm *TM = localtime(&TT);
+
+ static const char * const Months[] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+
+ char TmpBuffer[32];
+#ifdef LLVM_ON_WIN32
+ sprintf(TmpBuffer, "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday,
+ TM->tm_year+1900);
+#else
+ snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday,
+ TM->tm_year+1900);
+#endif
+
+ Token TmpTok;
+ TmpTok.startToken();
+ PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok);
+ DATELoc = TmpTok.getLocation();
+
+#ifdef LLVM_ON_WIN32
+ sprintf(TmpBuffer, "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec);
+#else
+ snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec);
+#endif
+ PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok);
+ TIMELoc = TmpTok.getLocation();
+}
+
+
+/// HasFeature - Return true if we recognize and implement the specified feature
+/// specified by the identifier.
+static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
+ const LangOptions &LangOpts = PP.getLangOptions();
+
+ return llvm::StringSwitch<bool>(II->getName())
+ .Case("attribute_analyzer_noreturn", true)
+ .Case("attribute_cf_returns_not_retained", true)
+ .Case("attribute_cf_returns_retained", true)
+ .Case("attribute_deprecated_with_message", true)
+ .Case("attribute_ext_vector_type", true)
+ .Case("attribute_ns_returns_not_retained", true)
+ .Case("attribute_ns_returns_retained", true)
+ .Case("attribute_ns_consumes_self", true)
+ .Case("attribute_ns_consumed", true)
+ .Case("attribute_cf_consumed", true)
+ .Case("attribute_objc_ivar_unused", true)
+ .Case("attribute_overloadable", true)
+ .Case("attribute_unavailable_with_message", true)
+ .Case("blocks", LangOpts.Blocks)
+ .Case("cxx_exceptions", LangOpts.Exceptions)
+ .Case("cxx_rtti", LangOpts.RTTI)
+ .Case("enumerator_attributes", true)
+ .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
+ .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
+ .Case("ownership_holds", true)
+ .Case("ownership_returns", true)
+ .Case("ownership_takes", true)
+ // C++0x features
+ .Case("cxx_attributes", LangOpts.CPlusPlus0x)
+ .Case("cxx_auto_type", LangOpts.CPlusPlus0x)
+ .Case("cxx_decltype", LangOpts.CPlusPlus0x)
+ .Case("cxx_default_function_template_args", LangOpts.CPlusPlus0x)
+ .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x)
+ .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x)
+ //.Case("cxx_lambdas", false)
+ //.Case("cxx_nullptr", false)
+ .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus0x)
+ .Case("cxx_rvalue_references", LangOpts.CPlusPlus0x)
+ .Case("cxx_strong_enums", LangOpts.CPlusPlus0x)
+ .Case("cxx_static_assert", LangOpts.CPlusPlus0x)
+ .Case("cxx_trailing_return", LangOpts.CPlusPlus0x)
+ .Case("cxx_variadic_templates", LangOpts.CPlusPlus0x)
+ // Type traits
+ .Case("has_nothrow_assign", LangOpts.CPlusPlus)
+ .Case("has_nothrow_copy", LangOpts.CPlusPlus)
+ .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
+ .Case("has_trivial_assign", LangOpts.CPlusPlus)
+ .Case("has_trivial_copy", LangOpts.CPlusPlus)
+ .Case("has_trivial_constructor", LangOpts.CPlusPlus)
+ .Case("has_trivial_destructor", LangOpts.CPlusPlus)
+ .Case("has_virtual_destructor", LangOpts.CPlusPlus)
+ .Case("is_abstract", LangOpts.CPlusPlus)
+ .Case("is_base_of", LangOpts.CPlusPlus)
+ .Case("is_class", LangOpts.CPlusPlus)
+ .Case("is_convertible_to", LangOpts.CPlusPlus)
+ .Case("is_empty", LangOpts.CPlusPlus)
+ .Case("is_enum", LangOpts.CPlusPlus)
+ .Case("is_pod", LangOpts.CPlusPlus)
+ .Case("is_polymorphic", LangOpts.CPlusPlus)
+ .Case("is_union", LangOpts.CPlusPlus)
+ .Case("is_literal", LangOpts.CPlusPlus)
+ .Case("tls", PP.getTargetInfo().isTLSSupported())
+ .Default(false);
+}
+
+/// HasAttribute - Return true if we recognize and implement the attribute
+/// specified by the given identifier.
+static bool HasAttribute(const IdentifierInfo *II) {
+ return llvm::StringSwitch<bool>(II->getName())
+#include "clang/Lex/AttrSpellings.inc"
+ .Default(false);
+}
+
+/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
+/// or '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeCommon(Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP,
+ const DirectoryLookup *LookupFrom) {
+ SourceLocation LParenLoc;
+
+ // Get '('.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a '('.
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
+ return false;
+ }
+
+ // Save '(' location for possible missing ')' message.
+ LParenLoc = Tok.getLocation();
+
+ // Get the file name.
+ PP.getCurrentLexer()->LexIncludeFilename(Tok);
+
+ // Reserve a buffer to get the spelling.
+ llvm::SmallString<128> FilenameBuffer;
+ llvm::StringRef Filename;
+ SourceLocation EndLoc;
+
+ switch (Tok.getKind()) {
+ case tok::eom:
+ // If the token kind is EOM, the error has already been diagnosed.
+ return false;
+
+ case tok::angle_string_literal:
+ case tok::string_literal: {
+ bool Invalid = false;
+ Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
+ if (Invalid)
+ return false;
+ break;
+ }
+
+ case tok::less:
+ // This could be a <foo/bar.h> file coming from a macro expansion. In this
+ // case, glue the tokens together into FilenameBuffer and interpret those.
+ FilenameBuffer.push_back('<');
+ if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc))
+ return false; // Found <eom> but no ">"? Diagnostic already emitted.
+ Filename = FilenameBuffer.str();
+ break;
+ default:
+ PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);
+ return false;
+ }
+
+ bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
+ // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+ // error.
+ if (Filename.empty())
+ return false;
+
+ // Search include directories.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = PP.LookupFile(Filename, isAngled, LookupFrom, CurDir);
+
+ // Get the result value. Result = true means the file exists.
+ bool Result = File != 0;
+
+ // Get ')'.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a trailing ).
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return false;
+ }
+
+ return Result;
+}
+
+/// EvaluateHasInclude - Process a '__has_include("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II,
+ Preprocessor &PP) {
+ return EvaluateHasIncludeCommon(Tok, II, PP, NULL);
+}
+
+/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
+/// Returns true if successful.
+static bool EvaluateHasIncludeNext(Token &Tok,
+ IdentifierInfo *II, Preprocessor &PP) {
+ // __has_include_next is like __has_include, except that we start
+ // searching after the current found directory. If we can't do this,
+ // issue a diagnostic.
+ const DirectoryLookup *Lookup = PP.GetCurDirLookup();
+ if (PP.isInPrimaryFile()) {
+ Lookup = 0;
+ PP.Diag(Tok, diag::pp_include_next_in_primary);
+ } else if (Lookup == 0) {
+ PP.Diag(Tok, diag::pp_include_next_absolute_path);
+ } else {
+ // Start looking up in the next directory.
+ ++Lookup;
+ }
+
+ return EvaluateHasIncludeCommon(Tok, II, PP, Lookup);
+}
+
+/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
+/// as a builtin macro, handle it and return the next token as 'Tok'.
+void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
+ // Figure out which token this is.
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ assert(II && "Can't be a macro without id info!");
+
+ // If this is an _Pragma or Microsoft __pragma directive, expand it,
+ // invoke the pragma handler, then lex the token after it.
+ if (II == Ident_Pragma)
+ return Handle_Pragma(Tok);
+ else if (II == Ident__pragma) // in non-MS mode this is null
+ return HandleMicrosoft__pragma(Tok);
+
+ ++NumBuiltinMacroExpanded;
+
+ llvm::SmallString<128> TmpBuffer;
+ llvm::raw_svector_ostream OS(TmpBuffer);
+
+ // Set up the return result.
+ Tok.setIdentifierInfo(0);
+ Tok.clearFlag(Token::NeedsCleaning);
+
+ if (II == Ident__LINE__) {
+ // C99 6.10.8: "__LINE__: The presumed line number (within the current
+ // source file) of the current source line (an integer constant)". This can
+ // be affected by #line.
+ SourceLocation Loc = Tok.getLocation();
+
+ // Advance to the location of the first _, this might not be the first byte
+ // of the token if it starts with an escaped newline.
+ Loc = AdvanceToTokenCharacter(Loc, 0);
+
+ // One wrinkle here is that GCC expands __LINE__ to location of the *end* of
+ // a macro instantiation. This doesn't matter for object-like macros, but
+ // can matter for a function-like macro that expands to contain __LINE__.
+ // Skip down through instantiation points until we find a file loc for the
+ // end of the instantiation history.
+ Loc = SourceMgr.getInstantiationRange(Loc).second;
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc);
+
+ // __LINE__ expands to a simple numeric value.
+ OS << (PLoc.isValid()? PLoc.getLine() : 1);
+ Tok.setKind(tok::numeric_constant);
+ } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) {
+ // C99 6.10.8: "__FILE__: The presumed name of the current source file (a
+ // character string literal)". This can be affected by #line.
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation());
+
+ // __BASE_FILE__ is a GNU extension that returns the top of the presumed
+ // #include stack instead of the current file.
+ if (II == Ident__BASE_FILE__ && PLoc.isValid()) {
+ SourceLocation NextLoc = PLoc.getIncludeLoc();
+ while (NextLoc.isValid()) {
+ PLoc = SourceMgr.getPresumedLoc(NextLoc);
+ if (PLoc.isInvalid())
+ break;
+
+ NextLoc = PLoc.getIncludeLoc();
+ }
+ }
+
+ // Escape this filename. Turn '\' -> '\\' '"' -> '\"'
+ llvm::SmallString<128> FN;
+ if (PLoc.isValid()) {
+ FN += PLoc.getFilename();
+ Lexer::Stringify(FN);
+ OS << '"' << FN.str() << '"';
+ }
+ Tok.setKind(tok::string_literal);
+ } else if (II == Ident__DATE__) {
+ if (!DATELoc.isValid())
+ ComputeDATE_TIME(DATELoc, TIMELoc, *this);
+ Tok.setKind(tok::string_literal);
+ Tok.setLength(strlen("\"Mmm dd yyyy\""));
+ Tok.setLocation(SourceMgr.createInstantiationLoc(DATELoc, Tok.getLocation(),
+ Tok.getLocation(),
+ Tok.getLength()));
+ return;
+ } else if (II == Ident__TIME__) {
+ if (!TIMELoc.isValid())
+ ComputeDATE_TIME(DATELoc, TIMELoc, *this);
+ Tok.setKind(tok::string_literal);
+ Tok.setLength(strlen("\"hh:mm:ss\""));
+ Tok.setLocation(SourceMgr.createInstantiationLoc(TIMELoc, Tok.getLocation(),
+ Tok.getLocation(),
+ Tok.getLength()));
+ return;
+ } else if (II == Ident__INCLUDE_LEVEL__) {
+ // Compute the presumed include depth of this token. This can be affected
+ // by GNU line markers.
+ unsigned Depth = 0;
+
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation());
+ if (PLoc.isValid()) {
+ PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc());
+ for (; PLoc.isValid(); ++Depth)
+ PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc());
+ }
+
+ // __INCLUDE_LEVEL__ expands to a simple numeric value.
+ OS << Depth;
+ Tok.setKind(tok::numeric_constant);
+ } else if (II == Ident__TIMESTAMP__) {
+ // MSVC, ICC, GCC, VisualAge C++ extension. The generated string should be
+ // of the form "Ddd Mmm dd hh::mm::ss yyyy", which is returned by asctime.
+
+ // Get the file that we are lexing out of. If we're currently lexing from
+ // a macro, dig into the include stack.
+ const FileEntry *CurFile = 0;
+ PreprocessorLexer *TheLexer = getCurrentFileLexer();
+
+ if (TheLexer)
+ CurFile = SourceMgr.getFileEntryForID(TheLexer->getFileID());
+
+ const char *Result;
+ if (CurFile) {
+ time_t TT = CurFile->getModificationTime();
+ struct tm *TM = localtime(&TT);
+ Result = asctime(TM);
+ } else {
+ Result = "??? ??? ?? ??:??:?? ????\n";
+ }
+ // Surround the string with " and strip the trailing newline.
+ OS << '"' << llvm::StringRef(Result, strlen(Result)-1) << '"';
+ Tok.setKind(tok::string_literal);
+ } else if (II == Ident__COUNTER__) {
+ // __COUNTER__ expands to a simple numeric value.
+ OS << CounterValue++;
+ Tok.setKind(tok::numeric_constant);
+ } else if (II == Ident__has_feature ||
+ II == Ident__has_builtin ||
+ II == Ident__has_attribute) {
+ // The argument to these two builtins should be a parenthesized identifier.
+ SourceLocation StartLoc = Tok.getLocation();
+
+ bool IsValid = false;
+ IdentifierInfo *FeatureII = 0;
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.is(tok::l_paren)) {
+ // Read the identifier
+ Lex(Tok);
+ if (Tok.is(tok::identifier)) {
+ FeatureII = Tok.getIdentifierInfo();
+
+ // Read the ')'.
+ Lex(Tok);
+ if (Tok.is(tok::r_paren))
+ IsValid = true;
+ }
+ }
+
+ bool Value = false;
+ if (!IsValid)
+ Diag(StartLoc, diag::err_feature_check_malformed);
+ else if (II == Ident__has_builtin) {
+ // Check for a builtin is trivial.
+ Value = FeatureII->getBuiltinID() != 0;
+ } else if (II == Ident__has_attribute)
+ Value = HasAttribute(FeatureII);
+ else {
+ assert(II == Ident__has_feature && "Must be feature check");
+ Value = HasFeature(*this, FeatureII);
+ }
+
+ OS << (int)Value;
+ Tok.setKind(tok::numeric_constant);
+ } else if (II == Ident__has_include ||
+ II == Ident__has_include_next) {
+ // The argument to these two builtins should be a parenthesized
+ // file name string literal using angle brackets (<>) or
+ // double-quotes ("").
+ bool Value;
+ if (II == Ident__has_include)
+ Value = EvaluateHasInclude(Tok, II, *this);
+ else
+ Value = EvaluateHasIncludeNext(Tok, II, *this);
+ OS << (int)Value;
+ Tok.setKind(tok::numeric_constant);
+ } else {
+ assert(0 && "Unknown identifier!");
+ }
+ CreateString(OS.str().data(), OS.str().size(), Tok, Tok.getLocation());
+}
+
+void Preprocessor::markMacroAsUsed(MacroInfo *MI) {
+ // If the 'used' status changed, and the macro requires 'unused' warning,
+ // remove its SourceLocation from the warn-for-unused-macro locations.
+ if (MI->isWarnIfUnused() && !MI->isUsed())
+ WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
+ MI->setIsUsed(true);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
new file mode 100644
index 0000000..975753b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp
@@ -0,0 +1,709 @@
+//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PTHLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Lex/Token.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+using namespace clang;
+using namespace clang::io;
+
+#define DISK_TOKEN_SIZE (1+1+2+4+4)
+
+//===----------------------------------------------------------------------===//
+// PTHLexer methods.
+//===----------------------------------------------------------------------===//
+
+PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
+ const unsigned char *ppcond, PTHManager &PM)
+ : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
+ PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {
+
+ FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
+}
+
+void PTHLexer::Lex(Token& Tok) {
+LexNextToken:
+
+ //===--------------------------------------==//
+ // Read the raw token data.
+ //===--------------------------------------==//
+
+ // Shadow CurPtr into an automatic variable.
+ const unsigned char *CurPtrShadow = CurPtr;
+
+ // Read in the data for the token.
+ unsigned Word0 = ReadLE32(CurPtrShadow);
+ uint32_t IdentifierID = ReadLE32(CurPtrShadow);
+ uint32_t FileOffset = ReadLE32(CurPtrShadow);
+
+ tok::TokenKind TKind = (tok::TokenKind) (Word0 & 0xFF);
+ Token::TokenFlags TFlags = (Token::TokenFlags) ((Word0 >> 8) & 0xFF);
+ uint32_t Len = Word0 >> 16;
+
+ CurPtr = CurPtrShadow;
+
+ //===--------------------------------------==//
+ // Construct the token itself.
+ //===--------------------------------------==//
+
+ Tok.startToken();
+ Tok.setKind(TKind);
+ Tok.setFlag(TFlags);
+ assert(!LexingRawMode);
+ Tok.setLocation(FileStartLoc.getFileLocWithOffset(FileOffset));
+ Tok.setLength(Len);
+
+ // Handle identifiers.
+ if (Tok.isLiteral()) {
+ Tok.setLiteralData((const char*) (PTHMgr.SpellingBase + IdentifierID));
+ }
+ else if (IdentifierID) {
+ MIOpt.ReadToken();
+ IdentifierInfo *II = PTHMgr.GetIdentifierInfo(IdentifierID-1);
+
+ Tok.setIdentifierInfo(II);
+
+ // Change the kind of this identifier to the appropriate token kind, e.g.
+ // turning "for" into a keyword.
+ Tok.setKind(II->getTokenID());
+
+ if (II->isHandleIdentifierCase())
+ PP->HandleIdentifier(Tok);
+ return;
+ }
+
+ //===--------------------------------------==//
+ // Process the token.
+ //===--------------------------------------==//
+ if (TKind == tok::eof) {
+ // Save the end-of-file token.
+ EofToken = Tok;
+
+ // Save 'PP' to 'PPCache' as LexEndOfFile can delete 'this'.
+ Preprocessor *PPCache = PP;
+
+ assert(!ParsingPreprocessorDirective);
+ assert(!LexingRawMode);
+
+ if (LexEndOfFile(Tok))
+ return;
+
+ return PPCache->Lex(Tok);
+ }
+
+ if (TKind == tok::hash && Tok.isAtStartOfLine()) {
+ LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE;
+ assert(!LexingRawMode);
+ PP->HandleDirective(Tok);
+
+ if (PP->isCurrentLexer(this))
+ goto LexNextToken;
+
+ return PP->Lex(Tok);
+ }
+
+ if (TKind == tok::eom) {
+ assert(ParsingPreprocessorDirective);
+ ParsingPreprocessorDirective = false;
+ return;
+ }
+
+ MIOpt.ReadToken();
+}
+
+bool PTHLexer::LexEndOfFile(Token &Result) {
+ // If we hit the end of the file while parsing a preprocessor directive,
+ // end the preprocessor directive first. The next token returned will
+ // then be the end of file.
+ if (ParsingPreprocessorDirective) {
+ ParsingPreprocessorDirective = false; // Done parsing the "line".
+ return true; // Have a token.
+ }
+
+ assert(!LexingRawMode);
+
+ // If we are in a #if directive, emit an error.
+ while (!ConditionalStack.empty()) {
+ if (!PP->isCodeCompletionFile(FileStartLoc))
+ PP->Diag(ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
+ ConditionalStack.pop_back();
+ }
+
+ // Finally, let the preprocessor handle this.
+ return PP->HandleEndOfFile(Result);
+}
+
+// FIXME: We can just grab the last token instead of storing a copy
+// into EofToken.
+void PTHLexer::getEOF(Token& Tok) {
+ assert(EofToken.is(tok::eof));
+ Tok = EofToken;
+}
+
+void PTHLexer::DiscardToEndOfLine() {
+ assert(ParsingPreprocessorDirective && ParsingFilename == false &&
+ "Must be in a preprocessing directive!");
+
+ // We assume that if the preprocessor wishes to discard to the end of
+ // the line that it also means to end the current preprocessor directive.
+ ParsingPreprocessorDirective = false;
+
+ // Skip tokens by only peeking at their token kind and the flags.
+ // We don't need to actually reconstruct full tokens from the token buffer.
+ // This saves some copies and it also reduces IdentifierInfo* lookup.
+ const unsigned char* p = CurPtr;
+ while (1) {
+ // Read the token kind. Are we at the end of the file?
+ tok::TokenKind x = (tok::TokenKind) (uint8_t) *p;
+ if (x == tok::eof) break;
+
+ // Read the token flags. Are we at the start of the next line?
+ Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1];
+ if (y & Token::StartOfLine) break;
+
+ // Skip to the next token.
+ p += DISK_TOKEN_SIZE;
+ }
+
+ CurPtr = p;
+}
+
+/// SkipBlock - Used by Preprocessor to skip the current conditional block.
+bool PTHLexer::SkipBlock() {
+ assert(CurPPCondPtr && "No cached PP conditional information.");
+ assert(LastHashTokPtr && "No known '#' token.");
+
+ const unsigned char* HashEntryI = 0;
+ uint32_t Offset;
+ uint32_t TableIdx;
+
+ do {
+ // Read the token offset from the side-table.
+ Offset = ReadLE32(CurPPCondPtr);
+
+ // Read the target table index from the side-table.
+ TableIdx = ReadLE32(CurPPCondPtr);
+
+ // Compute the actual memory address of the '#' token data for this entry.
+ HashEntryI = TokBuf + Offset;
+
+ // Optmization: "Sibling jumping". #if...#else...#endif blocks can
+ // contain nested blocks. In the side-table we can jump over these
+ // nested blocks instead of doing a linear search if the next "sibling"
+ // entry is not at a location greater than LastHashTokPtr.
+ if (HashEntryI < LastHashTokPtr && TableIdx) {
+ // In the side-table we are still at an entry for a '#' token that
+ // is earlier than the last one we saw. Check if the location we would
+ // stride gets us closer.
+ const unsigned char* NextPPCondPtr =
+ PPCond + TableIdx*(sizeof(uint32_t)*2);
+ assert(NextPPCondPtr >= CurPPCondPtr);
+ // Read where we should jump to.
+ uint32_t TmpOffset = ReadLE32(NextPPCondPtr);
+ const unsigned char* HashEntryJ = TokBuf + TmpOffset;
+
+ if (HashEntryJ <= LastHashTokPtr) {
+ // Jump directly to the next entry in the side table.
+ HashEntryI = HashEntryJ;
+ Offset = TmpOffset;
+ TableIdx = ReadLE32(NextPPCondPtr);
+ CurPPCondPtr = NextPPCondPtr;
+ }
+ }
+ }
+ while (HashEntryI < LastHashTokPtr);
+ assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'");
+ assert(TableIdx && "No jumping from #endifs.");
+
+ // Update our side-table iterator.
+ const unsigned char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2);
+ assert(NextPPCondPtr >= CurPPCondPtr);
+ CurPPCondPtr = NextPPCondPtr;
+
+ // Read where we should jump to.
+ HashEntryI = TokBuf + ReadLE32(NextPPCondPtr);
+ uint32_t NextIdx = ReadLE32(NextPPCondPtr);
+
+ // By construction NextIdx will be zero if this is a #endif. This is useful
+ // to know to obviate lexing another token.
+ bool isEndif = NextIdx == 0;
+
+ // This case can occur when we see something like this:
+ //
+ // #if ...
+ // /* a comment or nothing */
+ // #elif
+ //
+ // If we are skipping the first #if block it will be the case that CurPtr
+ // already points 'elif'. Just return.
+
+ if (CurPtr > HashEntryI) {
+ assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE);
+ // Did we reach a #endif? If so, go ahead and consume that token as well.
+ if (isEndif)
+ CurPtr += DISK_TOKEN_SIZE*2;
+ else
+ LastHashTokPtr = HashEntryI;
+
+ return isEndif;
+ }
+
+ // Otherwise, we need to advance. Update CurPtr to point to the '#' token.
+ CurPtr = HashEntryI;
+
+ // Update the location of the last observed '#'. This is useful if we
+ // are skipping multiple blocks.
+ LastHashTokPtr = CurPtr;
+
+ // Skip the '#' token.
+ assert(((tok::TokenKind)*CurPtr) == tok::hash);
+ CurPtr += DISK_TOKEN_SIZE;
+
+ // Did we reach a #endif? If so, go ahead and consume that token as well.
+ if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; }
+
+ return isEndif;
+}
+
+SourceLocation PTHLexer::getSourceLocation() {
+ // getSourceLocation is not on the hot path. It is used to get the location
+ // of the next token when transitioning back to this lexer when done
+ // handling a #included file. Just read the necessary data from the token
+ // data buffer to construct the SourceLocation object.
+ // NOTE: This is a virtual function; hence it is defined out-of-line.
+ const unsigned char *OffsetPtr = CurPtr + (DISK_TOKEN_SIZE - 4);
+ uint32_t Offset = ReadLE32(OffsetPtr);
+ return FileStartLoc.getFileLocWithOffset(Offset);
+}
+
+//===----------------------------------------------------------------------===//
+// PTH file lookup: map from strings to file data.
+//===----------------------------------------------------------------------===//
+
+/// PTHFileLookup - This internal data structure is used by the PTHManager
+/// to map from FileEntry objects managed by FileManager to offsets within
+/// the PTH file.
+namespace {
+class PTHFileData {
+ const uint32_t TokenOff;
+ const uint32_t PPCondOff;
+public:
+ PTHFileData(uint32_t tokenOff, uint32_t ppCondOff)
+ : TokenOff(tokenOff), PPCondOff(ppCondOff) {}
+
+ uint32_t getTokenOffset() const { return TokenOff; }
+ uint32_t getPPCondOffset() const { return PPCondOff; }
+};
+
+
+class PTHFileLookupCommonTrait {
+public:
+ typedef std::pair<unsigned char, const char*> internal_key_type;
+
+ static unsigned ComputeHash(internal_key_type x) {
+ return llvm::HashString(x.second);
+ }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ unsigned keyLen = (unsigned) ReadUnalignedLE16(d);
+ unsigned dataLen = (unsigned) *(d++);
+ return std::make_pair(keyLen, dataLen);
+ }
+
+ static internal_key_type ReadKey(const unsigned char* d, unsigned) {
+ unsigned char k = *(d++); // Read the entry kind.
+ return std::make_pair(k, (const char*) d);
+ }
+};
+
+class PTHFileLookupTrait : public PTHFileLookupCommonTrait {
+public:
+ typedef const FileEntry* external_key_type;
+ typedef PTHFileData data_type;
+
+ static internal_key_type GetInternalKey(const FileEntry* FE) {
+ return std::make_pair((unsigned char) 0x1, FE->getName());
+ }
+
+ static bool EqualKey(internal_key_type a, internal_key_type b) {
+ return a.first == b.first && strcmp(a.second, b.second) == 0;
+ }
+
+ static PTHFileData ReadData(const internal_key_type& k,
+ const unsigned char* d, unsigned) {
+ assert(k.first == 0x1 && "Only file lookups can match!");
+ uint32_t x = ::ReadUnalignedLE32(d);
+ uint32_t y = ::ReadUnalignedLE32(d);
+ return PTHFileData(x, y);
+ }
+};
+
+class PTHStringLookupTrait {
+public:
+ typedef uint32_t
+ data_type;
+
+ typedef const std::pair<const char*, unsigned>
+ external_key_type;
+
+ typedef external_key_type internal_key_type;
+
+ static bool EqualKey(const internal_key_type& a,
+ const internal_key_type& b) {
+ return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
+ : false;
+ }
+
+ static unsigned ComputeHash(const internal_key_type& a) {
+ return llvm::HashString(llvm::StringRef(a.first, a.second));
+ }
+
+ // This hopefully will just get inlined and removed by the optimizer.
+ static const internal_key_type&
+ GetInternalKey(const external_key_type& x) { return x; }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ return std::make_pair((unsigned) ReadUnalignedLE16(d), sizeof(uint32_t));
+ }
+
+ static std::pair<const char*, unsigned>
+ ReadKey(const unsigned char* d, unsigned n) {
+ assert(n >= 2 && d[n-1] == '\0');
+ return std::make_pair((const char*) d, n-1);
+ }
+
+ static uint32_t ReadData(const internal_key_type& k, const unsigned char* d,
+ unsigned) {
+ return ::ReadUnalignedLE32(d);
+ }
+};
+
+} // end anonymous namespace
+
+typedef OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
+typedef OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
+
+//===----------------------------------------------------------------------===//
+// PTHManager methods.
+//===----------------------------------------------------------------------===//
+
+PTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
+ const unsigned char* idDataTable,
+ IdentifierInfo** perIDCache,
+ void* stringIdLookup, unsigned numIds,
+ const unsigned char* spellingBase,
+ const char* originalSourceFile)
+: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup),
+ IdDataTable(idDataTable), StringIdLookup(stringIdLookup),
+ NumIds(numIds), PP(0), SpellingBase(spellingBase),
+ OriginalSourceFile(originalSourceFile) {}
+
+PTHManager::~PTHManager() {
+ delete Buf;
+ delete (PTHFileLookup*) FileLookup;
+ delete (PTHStringIdLookup*) StringIdLookup;
+ free(PerIDCache);
+}
+
+static void InvalidPTH(Diagnostic &Diags, const char *Msg) {
+ Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, Msg));
+}
+
+PTHManager *PTHManager::Create(const std::string &file, Diagnostic &Diags) {
+ // Memory map the PTH file.
+ llvm::OwningPtr<llvm::MemoryBuffer> File;
+
+ if (llvm::MemoryBuffer::getFile(file, File)) {
+ // FIXME: Add ec.message() to this diag.
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ // Get the buffer ranges and check if there are at least three 32-bit
+ // words at the end of the file.
+ const unsigned char *BufBeg = (unsigned char*)File->getBufferStart();
+ const unsigned char *BufEnd = (unsigned char*)File->getBufferEnd();
+
+ // Check the prologue of the file.
+ if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 3 + 4) ||
+ memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth") - 1) != 0) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ // Read the PTH version.
+ const unsigned char *p = BufBeg + (sizeof("cfe-pth") - 1);
+ unsigned Version = ReadLE32(p);
+
+ if (Version < PTHManager::Version) {
+ InvalidPTH(Diags,
+ Version < PTHManager::Version
+ ? "PTH file uses an older PTH format that is no longer supported"
+ : "PTH file uses a newer PTH format that cannot be read");
+ return 0;
+ }
+
+ // Compute the address of the index table at the end of the PTH file.
+ const unsigned char *PrologueOffset = p;
+
+ if (PrologueOffset >= BufEnd) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ // Construct the file lookup table. This will be used for mapping from
+ // FileEntry*'s to cached tokens.
+ const unsigned char* FileTableOffset = PrologueOffset + sizeof(uint32_t)*2;
+ const unsigned char* FileTable = BufBeg + ReadLE32(FileTableOffset);
+
+ if (!(FileTable > BufBeg && FileTable < BufEnd)) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0; // FIXME: Proper error diagnostic?
+ }
+
+ llvm::OwningPtr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg));
+
+ // Warn if the PTH file is empty. We still want to create a PTHManager
+ // as the PTH could be used with -include-pth.
+ if (FL->isEmpty())
+ InvalidPTH(Diags, "PTH file contains no cached source data");
+
+ // Get the location of the table mapping from persistent ids to the
+ // data needed to reconstruct identifiers.
+ const unsigned char* IDTableOffset = PrologueOffset + sizeof(uint32_t)*0;
+ const unsigned char* IData = BufBeg + ReadLE32(IDTableOffset);
+
+ if (!(IData >= BufBeg && IData < BufEnd)) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ // Get the location of the hashtable mapping between strings and
+ // persistent IDs.
+ const unsigned char* StringIdTableOffset = PrologueOffset + sizeof(uint32_t)*1;
+ const unsigned char* StringIdTable = BufBeg + ReadLE32(StringIdTableOffset);
+ if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ llvm::OwningPtr<PTHStringIdLookup> SL(PTHStringIdLookup::Create(StringIdTable,
+ BufBeg));
+
+ // Get the location of the spelling cache.
+ const unsigned char* spellingBaseOffset = PrologueOffset + sizeof(uint32_t)*3;
+ const unsigned char* spellingBase = BufBeg + ReadLE32(spellingBaseOffset);
+ if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) {
+ Diags.Report(diag::err_invalid_pth_file) << file;
+ return 0;
+ }
+
+ // Get the number of IdentifierInfos and pre-allocate the identifier cache.
+ uint32_t NumIds = ReadLE32(IData);
+
+ // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc()
+ // so that we in the best case only zero out memory once when the OS returns
+ // us new pages.
+ IdentifierInfo** PerIDCache = 0;
+
+ if (NumIds) {
+ PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache));
+ if (!PerIDCache) {
+ InvalidPTH(Diags, "Could not allocate memory for processing PTH file");
+ return 0;
+ }
+ }
+
+ // Compute the address of the original source file.
+ const unsigned char* originalSourceBase = PrologueOffset + sizeof(uint32_t)*4;
+ unsigned len = ReadUnalignedLE16(originalSourceBase);
+ if (!len) originalSourceBase = 0;
+
+ // Create the new PTHManager.
+ return new PTHManager(File.take(), FL.take(), IData, PerIDCache,
+ SL.take(), NumIds, spellingBase,
+ (const char*) originalSourceBase);
+}
+
+IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
+ // Look in the PTH file for the string data for the IdentifierInfo object.
+ const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID;
+ const unsigned char* IDData =
+ (const unsigned char*)Buf->getBufferStart() + ReadLE32(TableEntry);
+ assert(IDData < (const unsigned char*)Buf->getBufferEnd());
+
+ // Allocate the object.
+ std::pair<IdentifierInfo,const unsigned char*> *Mem =
+ Alloc.Allocate<std::pair<IdentifierInfo,const unsigned char*> >();
+
+ Mem->second = IDData;
+ assert(IDData[0] != '\0');
+ IdentifierInfo *II = new ((void*) Mem) IdentifierInfo();
+
+ // Store the new IdentifierInfo in the cache.
+ PerIDCache[PersistentID] = II;
+ assert(II->getNameStart() && II->getNameStart()[0] != '\0');
+ return II;
+}
+
+IdentifierInfo* PTHManager::get(llvm::StringRef Name) {
+ PTHStringIdLookup& SL = *((PTHStringIdLookup*)StringIdLookup);
+ // Double check our assumption that the last character isn't '\0'.
+ assert(Name.empty() || Name.data()[Name.size()-1] != '\0');
+ PTHStringIdLookup::iterator I = SL.find(std::make_pair(Name.data(),
+ Name.size()));
+ if (I == SL.end()) // No identifier found?
+ return 0;
+
+ // Match found. Return the identifier!
+ assert(*I > 0);
+ return GetIdentifierInfo(*I-1);
+}
+
+PTHLexer *PTHManager::CreateLexer(FileID FID) {
+ const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID);
+ if (!FE)
+ return 0;
+
+ // Lookup the FileEntry object in our file lookup data structure. It will
+ // return a variant that indicates whether or not there is an offset within
+ // the PTH file that contains cached tokens.
+ PTHFileLookup& PFL = *((PTHFileLookup*)FileLookup);
+ PTHFileLookup::iterator I = PFL.find(FE);
+
+ if (I == PFL.end()) // No tokens available?
+ return 0;
+
+ const PTHFileData& FileData = *I;
+
+ const unsigned char *BufStart = (const unsigned char *)Buf->getBufferStart();
+ // Compute the offset of the token data within the buffer.
+ const unsigned char* data = BufStart + FileData.getTokenOffset();
+
+ // Get the location of pp-conditional table.
+ const unsigned char* ppcond = BufStart + FileData.getPPCondOffset();
+ uint32_t Len = ReadLE32(ppcond);
+ if (Len == 0) ppcond = 0;
+
+ assert(PP && "No preprocessor set yet!");
+ return new PTHLexer(*PP, FID, data, ppcond, *this);
+}
+
+//===----------------------------------------------------------------------===//
+// 'stat' caching.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class PTHStatData {
+public:
+ const bool hasStat;
+ const ino_t ino;
+ const dev_t dev;
+ const mode_t mode;
+ const time_t mtime;
+ const off_t size;
+
+ PTHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
+ : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
+
+ PTHStatData()
+ : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
+};
+
+class PTHStatLookupTrait : public PTHFileLookupCommonTrait {
+public:
+ typedef const char* external_key_type; // const char*
+ typedef PTHStatData data_type;
+
+ static internal_key_type GetInternalKey(const char *path) {
+ // The key 'kind' doesn't matter here because it is ignored in EqualKey.
+ return std::make_pair((unsigned char) 0x0, path);
+ }
+
+ static bool EqualKey(internal_key_type a, internal_key_type b) {
+ // When doing 'stat' lookups we don't care about the kind of 'a' and 'b',
+ // just the paths.
+ return strcmp(a.second, b.second) == 0;
+ }
+
+ static data_type ReadData(const internal_key_type& k, const unsigned char* d,
+ unsigned) {
+
+ if (k.first /* File or Directory */) {
+ if (k.first == 0x1 /* File */) d += 4 * 2; // Skip the first 2 words.
+ ino_t ino = (ino_t) ReadUnalignedLE32(d);
+ dev_t dev = (dev_t) ReadUnalignedLE32(d);
+ mode_t mode = (mode_t) ReadUnalignedLE16(d);
+ time_t mtime = (time_t) ReadUnalignedLE64(d);
+ return data_type(ino, dev, mode, mtime, (off_t) ReadUnalignedLE64(d));
+ }
+
+ // Negative stat. Don't read anything.
+ return data_type();
+ }
+};
+
+class PTHStatCache : public FileSystemStatCache {
+ typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
+ CacheTy Cache;
+
+public:
+ PTHStatCache(PTHFileLookup &FL) :
+ Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(),
+ FL.getBase()) {}
+
+ ~PTHStatCache() {}
+
+ LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ // Do the lookup for the file's data in the PTH file.
+ CacheTy::iterator I = Cache.find(Path);
+
+ // If we don't get a hit in the PTH file just forward to 'stat'.
+ if (I == Cache.end())
+ return statChained(Path, StatBuf, FileDescriptor);
+
+ const PTHStatData &Data = *I;
+
+ if (!Data.hasStat)
+ return CacheMissing;
+
+ StatBuf.st_ino = Data.ino;
+ StatBuf.st_dev = Data.dev;
+ StatBuf.st_mtime = Data.mtime;
+ StatBuf.st_mode = Data.mode;
+ StatBuf.st_size = Data.size;
+ return CacheExists;
+ }
+};
+} // end anonymous namespace
+
+FileSystemStatCache *PTHManager::createStatCache() {
+ return new PTHStatCache(*((PTHFileLookup*) FileLookup));
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
new file mode 100644
index 0000000..f0475bc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -0,0 +1,1031 @@
+//===--- Pragma.cpp - Pragma registration and handling --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PragmaHandler/PragmaTable interfaces and implements
+// pragma related methods of the Preprocessor class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+using namespace clang;
+
+// Out-of-line destructor to provide a home for the class.
+PragmaHandler::~PragmaHandler() {
+}
+
+//===----------------------------------------------------------------------===//
+// EmptyPragmaHandler Implementation.
+//===----------------------------------------------------------------------===//
+
+EmptyPragmaHandler::EmptyPragmaHandler() {}
+
+void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &FirstToken) {}
+
+//===----------------------------------------------------------------------===//
+// PragmaNamespace Implementation.
+//===----------------------------------------------------------------------===//
+
+
+PragmaNamespace::~PragmaNamespace() {
+ for (llvm::StringMap<PragmaHandler*>::iterator
+ I = Handlers.begin(), E = Handlers.end(); I != E; ++I)
+ delete I->second;
+}
+
+/// FindHandler - Check to see if there is already a handler for the
+/// specified name. If not, return the handler for the null identifier if it
+/// exists, otherwise return null. If IgnoreNull is true (the default) then
+/// the null handler isn't returned on failure to match.
+PragmaHandler *PragmaNamespace::FindHandler(llvm::StringRef Name,
+ bool IgnoreNull) const {
+ if (PragmaHandler *Handler = Handlers.lookup(Name))
+ return Handler;
+ return IgnoreNull ? 0 : Handlers.lookup(llvm::StringRef());
+}
+
+void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
+ assert(!Handlers.lookup(Handler->getName()) &&
+ "A handler with this name is already registered in this namespace");
+ llvm::StringMapEntry<PragmaHandler *> &Entry =
+ Handlers.GetOrCreateValue(Handler->getName());
+ Entry.setValue(Handler);
+}
+
+void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) {
+ assert(Handlers.lookup(Handler->getName()) &&
+ "Handler not registered in this namespace");
+ Handlers.erase(Handler->getName());
+}
+
+void PragmaNamespace::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro
+ // expand it, the user can have a STDC #define, that should not affect this.
+ PP.LexUnexpandedToken(Tok);
+
+ // Get the handler for this token. If there is no handler, ignore the pragma.
+ PragmaHandler *Handler
+ = FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName()
+ : llvm::StringRef(),
+ /*IgnoreNull=*/false);
+ if (Handler == 0) {
+ PP.Diag(Tok, diag::warn_pragma_ignored);
+ return;
+ }
+
+ // Otherwise, pass it down.
+ Handler->HandlePragma(PP, Introducer, Tok);
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Pragma Directive Handling.
+//===----------------------------------------------------------------------===//
+
+/// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the
+/// rest of the pragma, passing it to the registered pragma handlers.
+void Preprocessor::HandlePragmaDirective(unsigned Introducer) {
+ ++NumPragma;
+
+ // Invoke the first level of pragma handlers which reads the namespace id.
+ Token Tok;
+ PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok);
+
+ // If the pragma handler didn't read the rest of the line, consume it now.
+ if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
+ DiscardUntilEndOfDirective();
+}
+
+/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+/// return the first token after the directive. The _Pragma token has just
+/// been read into 'Tok'.
+void Preprocessor::Handle_Pragma(Token &Tok) {
+ // Remember the pragma token location.
+ SourceLocation PragmaLoc = Tok.getLocation();
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ // Read the '"..."'.
+ Lex(Tok);
+ if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ // Remember the string.
+ std::string StrVal = getSpelling(Tok);
+
+ // Read the ')'.
+ Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ SourceLocation RParenLoc = Tok.getLocation();
+
+ // The _Pragma is lexically sound. Destringize according to C99 6.10.9.1:
+ // "The string literal is destringized by deleting the L prefix, if present,
+ // deleting the leading and trailing double-quotes, replacing each escape
+ // sequence \" by a double-quote, and replacing each escape sequence \\ by a
+ // single backslash."
+ if (StrVal[0] == 'L') // Remove L prefix.
+ StrVal.erase(StrVal.begin());
+ assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
+ "Invalid string token!");
+
+ // Remove the front quote, replacing it with a space, so that the pragma
+ // contents appear to have a space before them.
+ StrVal[0] = ' ';
+
+ // Replace the terminating quote with a \n.
+ StrVal[StrVal.size()-1] = '\n';
+
+ // Remove escaped quotes and escapes.
+ for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
+ if (StrVal[i] == '\\' &&
+ (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
+ // \\ -> '\' and \" -> '"'.
+ StrVal.erase(StrVal.begin()+i);
+ --e;
+ }
+ }
+
+ Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc);
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
+
+/// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
+/// is not enclosed within a string literal.
+void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
+ // Remember the pragma token location.
+ SourceLocation PragmaLoc = Tok.getLocation();
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ // Get the tokens enclosed within the __pragma().
+ llvm::SmallVector<Token, 32> PragmaToks;
+ int NumParens = 0;
+ Lex(Tok);
+ while (Tok.isNot(tok::eof)) {
+ if (Tok.is(tok::l_paren))
+ NumParens++;
+ else if (Tok.is(tok::r_paren) && NumParens-- == 0)
+ break;
+ PragmaToks.push_back(Tok);
+ Lex(Tok);
+ }
+
+ if (Tok.is(tok::eof)) {
+ Diag(PragmaLoc, diag::err_unterminated___pragma);
+ return;
+ }
+
+ // Build the pragma string.
+ std::string StrVal = " ";
+ for (llvm::SmallVector<Token, 32>::iterator I =
+ PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) {
+ StrVal += getSpelling(*I);
+ }
+
+ SourceLocation RParenLoc = Tok.getLocation();
+
+ Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc);
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
+
+void Preprocessor::Handle_Pragma(unsigned Introducer,
+ const std::string &StrVal,
+ SourceLocation PragmaLoc,
+ SourceLocation RParenLoc) {
+
+ // Plop the string (including the newline and trailing null) into a buffer
+ // where we can lex it.
+ Token TmpTok;
+ TmpTok.startToken();
+ CreateString(&StrVal[0], StrVal.size(), TmpTok);
+ SourceLocation TokLoc = TmpTok.getLocation();
+
+ // Make and enter a lexer object so that we lex and expand the tokens just
+ // like any others.
+ Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
+ StrVal.size(), *this);
+
+ EnterSourceFileWithLexer(TL, 0);
+
+ // With everything set up, lex this as a #pragma directive.
+ HandlePragmaDirective(Introducer);
+}
+
+
+
+/// HandlePragmaOnce - Handle #pragma once. OnceTok is the 'once'.
+///
+void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
+ if (isInPrimaryFile()) {
+ Diag(OnceTok, diag::pp_pragma_once_in_main_file);
+ return;
+ }
+
+ // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
+ // Mark the file as a once-only file now.
+ HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
+}
+
+void Preprocessor::HandlePragmaMark() {
+ assert(CurPPLexer && "No current lexer?");
+ if (CurLexer)
+ CurLexer->ReadToEndOfLine();
+ else
+ CurPTHLexer->DiscardToEndOfLine();
+}
+
+
+/// HandlePragmaPoison - Handle #pragma GCC poison. PoisonTok is the 'poison'.
+///
+void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
+ Token Tok;
+
+ while (1) {
+ // Read the next token to poison. While doing this, pretend that we are
+ // skipping while reading the identifier to poison.
+ // This avoids errors on code like:
+ // #pragma GCC poison X
+ // #pragma GCC poison X
+ if (CurPPLexer) CurPPLexer->LexingRawMode = true;
+ LexUnexpandedToken(Tok);
+ if (CurPPLexer) CurPPLexer->LexingRawMode = false;
+
+ // If we reached the end of line, we're done.
+ if (Tok.is(tok::eom)) return;
+
+ // Can only poison identifiers.
+ if (Tok.isNot(tok::raw_identifier)) {
+ Diag(Tok, diag::err_pp_invalid_poison);
+ return;
+ }
+
+ // Look up the identifier info for the token. We disabled identifier lookup
+ // by saying we're skipping contents, so we need to do this manually.
+ IdentifierInfo *II = LookUpIdentifierInfo(Tok);
+
+ // Already poisoned.
+ if (II->isPoisoned()) continue;
+
+ // If this is a macro identifier, emit a warning.
+ if (II->hasMacroDefinition())
+ Diag(Tok, diag::pp_poisoning_existing_macro);
+
+ // Finally, poison it!
+ II->setIsPoisoned();
+ }
+}
+
+/// HandlePragmaSystemHeader - Implement #pragma GCC system_header. We know
+/// that the whole directive has been parsed.
+void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
+ if (isInPrimaryFile()) {
+ Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
+ return;
+ }
+
+ // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
+ PreprocessorLexer *TheLexer = getCurrentFileLexer();
+
+ // Mark the file as a system header.
+ HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
+
+
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
+ if (PLoc.isInvalid())
+ return;
+
+ unsigned FilenameLen = strlen(PLoc.getFilename());
+ unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(),
+ FilenameLen);
+
+ // Emit a line marker. This will change any source locations from this point
+ // forward to realize they are in a system header.
+ // Create a line note with this information.
+ SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID,
+ false, false, true, false);
+
+ // Notify the client, if desired, that we are in a new source file.
+ if (Callbacks)
+ Callbacks->FileChanged(SysHeaderTok.getLocation(),
+ PPCallbacks::SystemHeaderPragma, SrcMgr::C_System);
+}
+
+/// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
+///
+void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
+ Token FilenameTok;
+ CurPPLexer->LexIncludeFilename(FilenameTok);
+
+ // If the token kind is EOM, the error has already been diagnosed.
+ if (FilenameTok.is(tok::eom))
+ return;
+
+ // Reserve a buffer to get the spelling.
+ llvm::SmallString<128> FilenameBuffer;
+ bool Invalid = false;
+ llvm::StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
+ if (Invalid)
+ return;
+
+ bool isAngled =
+ GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
+ // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+ // error.
+ if (Filename.empty())
+ return;
+
+ // Search include directories for this file.
+ const DirectoryLookup *CurDir;
+ const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
+ if (File == 0) {
+ Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ return;
+ }
+
+ const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
+
+ // If this file is older than the file it depends on, emit a diagnostic.
+ if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
+ // Lex tokens at the end of the message and include them in the message.
+ std::string Message;
+ Lex(DependencyTok);
+ while (DependencyTok.isNot(tok::eom)) {
+ Message += getSpelling(DependencyTok) + " ";
+ Lex(DependencyTok);
+ }
+
+ // Remove the trailing ' ' if present.
+ if (!Message.empty())
+ Message.erase(Message.end()-1);
+ Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
+ }
+}
+
+/// HandlePragmaComment - Handle the microsoft #pragma comment extension. The
+/// syntax is:
+/// #pragma comment(linker, "foo")
+/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
+/// "foo" is a string, which is fully macro expanded, and permits string
+/// concatenation, embedded escape characters etc. See MSDN for more details.
+void Preprocessor::HandlePragmaComment(Token &Tok) {
+ SourceLocation CommentLoc = Tok.getLocation();
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(CommentLoc, diag::err_pragma_comment_malformed);
+ return;
+ }
+
+ // Read the identifier.
+ Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ Diag(CommentLoc, diag::err_pragma_comment_malformed);
+ return;
+ }
+
+ // Verify that this is one of the 5 whitelisted options.
+ // FIXME: warn that 'exestr' is deprecated.
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") &&
+ !II->isStr("linker") && !II->isStr("user")) {
+ Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
+ return;
+ }
+
+ // Read the optional string if present.
+ Lex(Tok);
+ std::string ArgumentString;
+ if (Tok.is(tok::comma)) {
+ Lex(Tok); // eat the comma.
+
+ // We need at least one string.
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
+ return;
+ }
+
+ // String concatenation allows multiple strings, which can even come from
+ // macro expansion.
+ // "foo " "bar" "Baz"
+ llvm::SmallVector<Token, 4> StrToks;
+ while (Tok.is(tok::string_literal)) {
+ StrToks.push_back(Tok);
+ Lex(Tok);
+ }
+
+ // Concatenate and parse the strings.
+ StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return;
+ if (Literal.Pascal) {
+ Diag(StrToks[0].getLocation(), diag::err_pragma_comment_malformed);
+ return;
+ }
+
+ ArgumentString = std::string(Literal.GetString(),
+ Literal.GetString()+Literal.GetStringLength());
+ }
+
+ // FIXME: If the kind is "compiler" warn if the string is present (it is
+ // ignored).
+ // FIXME: 'lib' requires a comment string.
+ // FIXME: 'linker' requires a comment string, and has a specific list of
+ // things that are allowable.
+
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
+ return;
+ }
+ Lex(Tok); // eat the r_paren.
+
+ if (Tok.isNot(tok::eom)) {
+ Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
+ return;
+ }
+
+ // If the pragma is lexically sound, notify any interested PPCallbacks.
+ if (Callbacks)
+ Callbacks->PragmaComment(CommentLoc, II, ArgumentString);
+}
+
+/// HandlePragmaMessage - Handle the microsoft and gcc #pragma message
+/// extension. The syntax is:
+/// #pragma message(string)
+/// OR, in GCC mode:
+/// #pragma message string
+/// string is a string, which is fully macro expanded, and permits string
+/// concatenation, embedded escape characters, etc... See MSDN for more details.
+void Preprocessor::HandlePragmaMessage(Token &Tok) {
+ SourceLocation MessageLoc = Tok.getLocation();
+ Lex(Tok);
+ bool ExpectClosingParen = false;
+ switch (Tok.getKind()) {
+ case tok::l_paren:
+ // We have a MSVC style pragma message.
+ ExpectClosingParen = true;
+ // Read the string.
+ Lex(Tok);
+ break;
+ case tok::string_literal:
+ // We have a GCC style pragma message, and we just read the string.
+ break;
+ default:
+ Diag(MessageLoc, diag::err_pragma_message_malformed);
+ return;
+ }
+
+ // We need at least one string.
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
+ return;
+ }
+
+ // String concatenation allows multiple strings, which can even come from
+ // macro expansion.
+ // "foo " "bar" "Baz"
+ llvm::SmallVector<Token, 4> StrToks;
+ while (Tok.is(tok::string_literal)) {
+ StrToks.push_back(Tok);
+ Lex(Tok);
+ }
+
+ // Concatenate and parse the strings.
+ StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return;
+ if (Literal.Pascal) {
+ Diag(StrToks[0].getLocation(), diag::err_pragma_message_malformed);
+ return;
+ }
+
+ llvm::StringRef MessageString(Literal.GetString(), Literal.GetStringLength());
+
+ if (ExpectClosingParen) {
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
+ return;
+ }
+ Lex(Tok); // eat the r_paren.
+ }
+
+ if (Tok.isNot(tok::eom)) {
+ Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
+ return;
+ }
+
+ // Output the message.
+ Diag(MessageLoc, diag::warn_pragma_message) << MessageString;
+
+ // If the pragma is lexically sound, notify any interested PPCallbacks.
+ if (Callbacks)
+ Callbacks->PragmaMessage(MessageLoc, MessageString);
+}
+
+/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro.
+/// Return the IdentifierInfo* associated with the macro to push or pop.
+IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
+ // Remember the pragma token location.
+ Token PragmaTok = Tok;
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ // Read the macro name string.
+ Lex(Tok);
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ // Remember the macro string.
+ std::string StrVal = getSpelling(Tok);
+
+ // Read the ')'.
+ Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
+ "Invalid string token!");
+
+ // Create a Token from the string.
+ Token MacroTok;
+ MacroTok.startToken();
+ MacroTok.setKind(tok::raw_identifier);
+ CreateString(&StrVal[1], StrVal.size() - 2, MacroTok);
+
+ // Get the IdentifierInfo of MacroToPushTok.
+ return LookUpIdentifierInfo(MacroTok);
+}
+
+/// HandlePragmaPushMacro - Handle #pragma push_macro.
+/// The syntax is:
+/// #pragma push_macro("macro")
+void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
+ // Parse the pragma directive and get the macro IdentifierInfo*.
+ IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PushMacroTok);
+ if (!IdentInfo) return;
+
+ // Get the MacroInfo associated with IdentInfo.
+ MacroInfo *MI = getMacroInfo(IdentInfo);
+
+ MacroInfo *MacroCopyToPush = 0;
+ if (MI) {
+ // Make a clone of MI.
+ MacroCopyToPush = CloneMacroInfo(*MI);
+
+ // Allow the original MacroInfo to be redefined later.
+ MI->setIsAllowRedefinitionsWithoutWarning(true);
+ }
+
+ // Push the cloned MacroInfo so we can retrieve it later.
+ PragmaPushMacroInfo[IdentInfo].push_back(MacroCopyToPush);
+}
+
+/// HandlePragmaPopMacro - Handle #pragma pop_macro.
+/// The syntax is:
+/// #pragma pop_macro("macro")
+void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
+ SourceLocation MessageLoc = PopMacroTok.getLocation();
+
+ // Parse the pragma directive and get the macro IdentifierInfo*.
+ IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok);
+ if (!IdentInfo) return;
+
+ // Find the vector<MacroInfo*> associated with the macro.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter =
+ PragmaPushMacroInfo.find(IdentInfo);
+ if (iter != PragmaPushMacroInfo.end()) {
+ // Release the MacroInfo currently associated with IdentInfo.
+ MacroInfo *CurrentMI = getMacroInfo(IdentInfo);
+ if (CurrentMI) {
+ if (CurrentMI->isWarnIfUnused())
+ WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc());
+ ReleaseMacroInfo(CurrentMI);
+ }
+
+ // Get the MacroInfo we want to reinstall.
+ MacroInfo *MacroToReInstall = iter->second.back();
+
+ // Reinstall the previously pushed macro.
+ setMacroInfo(IdentInfo, MacroToReInstall);
+
+ // Pop PragmaPushMacroInfo stack.
+ iter->second.pop_back();
+ if (iter->second.size() == 0)
+ PragmaPushMacroInfo.erase(iter);
+ } else {
+ Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push)
+ << IdentInfo->getName();
+ }
+}
+
+/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
+/// If 'Namespace' is non-null, then it is a token required to exist on the
+/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
+void Preprocessor::AddPragmaHandler(llvm::StringRef Namespace,
+ PragmaHandler *Handler) {
+ PragmaNamespace *InsertNS = PragmaHandlers;
+
+ // If this is specified to be in a namespace, step down into it.
+ if (!Namespace.empty()) {
+ // If there is already a pragma handler with the name of this namespace,
+ // we either have an error (directive with the same name as a namespace) or
+ // we already have the namespace to insert into.
+ if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) {
+ InsertNS = Existing->getIfNamespace();
+ assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
+ " handler with the same name!");
+ } else {
+ // Otherwise, this namespace doesn't exist yet, create and insert the
+ // handler for it.
+ InsertNS = new PragmaNamespace(Namespace);
+ PragmaHandlers->AddPragma(InsertNS);
+ }
+ }
+
+ // Check to make sure we don't already have a pragma for this identifier.
+ assert(!InsertNS->FindHandler(Handler->getName()) &&
+ "Pragma handler already exists for this identifier!");
+ InsertNS->AddPragma(Handler);
+}
+
+/// RemovePragmaHandler - Remove the specific pragma handler from the
+/// preprocessor. If \arg Namespace is non-null, then it should be the
+/// namespace that \arg Handler was added to. It is an error to remove
+/// a handler that has not been registered.
+void Preprocessor::RemovePragmaHandler(llvm::StringRef Namespace,
+ PragmaHandler *Handler) {
+ PragmaNamespace *NS = PragmaHandlers;
+
+ // If this is specified to be in a namespace, step down into it.
+ if (!Namespace.empty()) {
+ PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace);
+ assert(Existing && "Namespace containing handler does not exist!");
+
+ NS = Existing->getIfNamespace();
+ assert(NS && "Invalid namespace, registered as a regular pragma handler!");
+ }
+
+ NS->RemovePragmaHandler(Handler);
+
+ // If this is a non-default namespace and it is now empty, remove
+ // it.
+ if (NS != PragmaHandlers && NS->IsEmpty())
+ PragmaHandlers->RemovePragmaHandler(NS);
+}
+
+bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) {
+ Token Tok;
+ LexUnexpandedToken(Tok);
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::ext_on_off_switch_syntax);
+ return true;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("ON"))
+ Result = tok::OOS_ON;
+ else if (II->isStr("OFF"))
+ Result = tok::OOS_OFF;
+ else if (II->isStr("DEFAULT"))
+ Result = tok::OOS_DEFAULT;
+ else {
+ Diag(Tok, diag::ext_on_off_switch_syntax);
+ return true;
+ }
+
+ // Verify that this is followed by EOM.
+ LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::eom))
+ Diag(Tok, diag::ext_pragma_syntax_eom);
+ return false;
+}
+
+namespace {
+/// PragmaOnceHandler - "#pragma once" marks the file as atomically included.
+struct PragmaOnceHandler : public PragmaHandler {
+ PragmaOnceHandler() : PragmaHandler("once") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &OnceTok) {
+ PP.CheckEndOfDirective("pragma once");
+ PP.HandlePragmaOnce(OnceTok);
+ }
+};
+
+/// PragmaMarkHandler - "#pragma mark ..." is ignored by the compiler, and the
+/// rest of the line is not lexed.
+struct PragmaMarkHandler : public PragmaHandler {
+ PragmaMarkHandler() : PragmaHandler("mark") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &MarkTok) {
+ PP.HandlePragmaMark();
+ }
+};
+
+/// PragmaPoisonHandler - "#pragma poison x" marks x as not usable.
+struct PragmaPoisonHandler : public PragmaHandler {
+ PragmaPoisonHandler() : PragmaHandler("poison") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PoisonTok) {
+ PP.HandlePragmaPoison(PoisonTok);
+ }
+};
+
+/// PragmaSystemHeaderHandler - "#pragma system_header" marks the current file
+/// as a system header, which silences warnings in it.
+struct PragmaSystemHeaderHandler : public PragmaHandler {
+ PragmaSystemHeaderHandler() : PragmaHandler("system_header") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &SHToken) {
+ PP.HandlePragmaSystemHeader(SHToken);
+ PP.CheckEndOfDirective("pragma");
+ }
+};
+struct PragmaDependencyHandler : public PragmaHandler {
+ PragmaDependencyHandler() : PragmaHandler("dependency") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DepToken) {
+ PP.HandlePragmaDependency(DepToken);
+ }
+};
+
+struct PragmaDebugHandler : public PragmaHandler {
+ PragmaDebugHandler() : PragmaHandler("__debug") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DepToken) {
+ Token Tok;
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (II->isStr("assert")) {
+ assert(0 && "This is an assertion!");
+ } else if (II->isStr("crash")) {
+ *(volatile int*) 0x11 = 0;
+ } else if (II->isStr("llvm_fatal_error")) {
+ llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
+ } else if (II->isStr("llvm_unreachable")) {
+ llvm_unreachable("#pragma clang __debug llvm_unreachable");
+ } else if (II->isStr("overflow_stack")) {
+ DebugOverflowStack();
+ } else if (II->isStr("handle_crash")) {
+ llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent();
+ if (CRC)
+ CRC->HandleCrash();
+ } else {
+ PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
+ << II->getName();
+ }
+ }
+
+ void DebugOverflowStack() {
+ DebugOverflowStack();
+ }
+};
+
+/// PragmaDiagnosticHandler - e.g. '#pragma GCC diagnostic ignored "-Wformat"'
+struct PragmaDiagnosticHandler : public PragmaHandler {
+public:
+ explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DiagToken) {
+ SourceLocation DiagLoc = DiagToken.getLocation();
+ Token Tok;
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ diag::Mapping Map;
+ if (II->isStr("warning"))
+ Map = diag::MAP_WARNING;
+ else if (II->isStr("error"))
+ Map = diag::MAP_ERROR;
+ else if (II->isStr("ignored"))
+ Map = diag::MAP_IGNORE;
+ else if (II->isStr("fatal"))
+ Map = diag::MAP_FATAL;
+ else if (II->isStr("pop")) {
+ if (!PP.getDiagnostics().popMappings(DiagLoc))
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
+
+ return;
+ } else if (II->isStr("push")) {
+ PP.getDiagnostics().pushMappings(DiagLoc);
+ return;
+ } else {
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ return;
+ }
+
+ PP.LexUnexpandedToken(Tok);
+
+ // We need at least one string.
+ if (Tok.isNot(tok::string_literal)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
+ return;
+ }
+
+ // String concatenation allows multiple strings, which can even come from
+ // macro expansion.
+ // "foo " "bar" "Baz"
+ llvm::SmallVector<Token, 4> StrToks;
+ while (Tok.is(tok::string_literal)) {
+ StrToks.push_back(Tok);
+ PP.LexUnexpandedToken(Tok);
+ }
+
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
+ return;
+ }
+
+ // Concatenate and parse the strings.
+ StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP);
+ assert(!Literal.AnyWide && "Didn't allow wide strings in");
+ if (Literal.hadError)
+ return;
+ if (Literal.Pascal) {
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ return;
+ }
+
+ std::string WarningName(Literal.GetString(),
+ Literal.GetString()+Literal.GetStringLength());
+
+ if (WarningName.size() < 3 || WarningName[0] != '-' ||
+ WarningName[1] != 'W') {
+ PP.Diag(StrToks[0].getLocation(),
+ diag::warn_pragma_diagnostic_invalid_option);
+ return;
+ }
+
+ if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2,
+ Map, DiagLoc))
+ PP.Diag(StrToks[0].getLocation(),
+ diag::warn_pragma_diagnostic_unknown_warning) << WarningName;
+ }
+};
+
+/// PragmaCommentHandler - "#pragma comment ...".
+struct PragmaCommentHandler : public PragmaHandler {
+ PragmaCommentHandler() : PragmaHandler("comment") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &CommentTok) {
+ PP.HandlePragmaComment(CommentTok);
+ }
+};
+
+/// PragmaMessageHandler - "#pragma message("...")".
+struct PragmaMessageHandler : public PragmaHandler {
+ PragmaMessageHandler() : PragmaHandler("message") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &CommentTok) {
+ PP.HandlePragmaMessage(CommentTok);
+ }
+};
+
+/// PragmaPushMacroHandler - "#pragma push_macro" saves the value of the
+/// macro on the top of the stack.
+struct PragmaPushMacroHandler : public PragmaHandler {
+ PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PushMacroTok) {
+ PP.HandlePragmaPushMacro(PushMacroTok);
+ }
+};
+
+
+/// PragmaPopMacroHandler - "#pragma pop_macro" sets the value of the
+/// macro to the value on the top of the stack.
+struct PragmaPopMacroHandler : public PragmaHandler {
+ PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PopMacroTok) {
+ PP.HandlePragmaPopMacro(PopMacroTok);
+ }
+};
+
+// Pragma STDC implementations.
+
+/// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...".
+struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
+ PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ tok::OnOffSwitch OOS;
+ if (PP.LexOnOffSwitch(OOS))
+ return;
+ if (OOS == tok::OOS_ON)
+ PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+ }
+};
+
+/// PragmaSTDC_CX_LIMITED_RANGEHandler - "#pragma STDC CX_LIMITED_RANGE ...".
+struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
+ PragmaSTDC_CX_LIMITED_RANGEHandler()
+ : PragmaHandler("CX_LIMITED_RANGE") {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ tok::OnOffSwitch OOS;
+ PP.LexOnOffSwitch(OOS);
+ }
+};
+
+/// PragmaSTDC_UnknownHandler - "#pragma STDC ...".
+struct PragmaSTDC_UnknownHandler : public PragmaHandler {
+ PragmaSTDC_UnknownHandler() {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &UnknownTok) {
+ // C99 6.10.6p2, unknown forms are not allowed.
+ PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
+ }
+};
+
+} // end anonymous namespace
+
+
+/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
+/// #pragma GCC poison/system_header/dependency and #pragma once.
+void Preprocessor::RegisterBuiltinPragmas() {
+ AddPragmaHandler(new PragmaOnceHandler());
+ AddPragmaHandler(new PragmaMarkHandler());
+ AddPragmaHandler(new PragmaPushMacroHandler());
+ AddPragmaHandler(new PragmaPopMacroHandler());
+ AddPragmaHandler(new PragmaMessageHandler());
+
+ // #pragma GCC ...
+ AddPragmaHandler("GCC", new PragmaPoisonHandler());
+ AddPragmaHandler("GCC", new PragmaSystemHeaderHandler());
+ AddPragmaHandler("GCC", new PragmaDependencyHandler());
+ AddPragmaHandler("GCC", new PragmaDiagnosticHandler());
+ // #pragma clang ...
+ AddPragmaHandler("clang", new PragmaPoisonHandler());
+ AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
+ AddPragmaHandler("clang", new PragmaDebugHandler());
+ AddPragmaHandler("clang", new PragmaDependencyHandler());
+ AddPragmaHandler("clang", new PragmaDiagnosticHandler());
+
+ AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
+ AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler());
+ AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
+
+ // MS extensions.
+ if (Features.Microsoft) {
+ AddPragmaHandler(new PragmaCommentHandler());
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
new file mode 100644
index 0000000..3a43ac1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
@@ -0,0 +1,183 @@
+//===--- PreprocessingRecord.cpp - Record of Preprocessing ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PreprocessingRecord class, which maintains a record
+// of what occurred during preprocessing, and its helpers.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Token.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
+
+
+InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
+ InclusionKind Kind,
+ llvm::StringRef FileName,
+ bool InQuotes, const FileEntry *File,
+ SourceRange Range)
+ : PreprocessingDirective(InclusionDirectiveKind, Range),
+ InQuotes(InQuotes), Kind(Kind), File(File)
+{
+ char *Memory
+ = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
+ memcpy(Memory, FileName.data(), FileName.size());
+ Memory[FileName.size()] = 0;
+ this->FileName = llvm::StringRef(Memory, FileName.size());
+}
+
+void PreprocessingRecord::MaybeLoadPreallocatedEntities() const {
+ if (!ExternalSource || LoadedPreallocatedEntities)
+ return;
+
+ LoadedPreallocatedEntities = true;
+ ExternalSource->ReadPreprocessedEntities();
+}
+
+PreprocessingRecord::PreprocessingRecord()
+ : ExternalSource(0), NumPreallocatedEntities(0),
+ LoadedPreallocatedEntities(false)
+{
+}
+
+PreprocessingRecord::iterator
+PreprocessingRecord::begin(bool OnlyLocalEntities) {
+ if (OnlyLocalEntities)
+ return PreprocessedEntities.begin() + NumPreallocatedEntities;
+
+ MaybeLoadPreallocatedEntities();
+ return PreprocessedEntities.begin();
+}
+
+PreprocessingRecord::iterator PreprocessingRecord::end(bool OnlyLocalEntities) {
+ if (!OnlyLocalEntities)
+ MaybeLoadPreallocatedEntities();
+
+ return PreprocessedEntities.end();
+}
+
+PreprocessingRecord::const_iterator
+PreprocessingRecord::begin(bool OnlyLocalEntities) const {
+ if (OnlyLocalEntities)
+ return PreprocessedEntities.begin() + NumPreallocatedEntities;
+
+ MaybeLoadPreallocatedEntities();
+ return PreprocessedEntities.begin();
+}
+
+PreprocessingRecord::const_iterator
+PreprocessingRecord::end(bool OnlyLocalEntities) const {
+ if (!OnlyLocalEntities)
+ MaybeLoadPreallocatedEntities();
+
+ return PreprocessedEntities.end();
+}
+
+void PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
+ PreprocessedEntities.push_back(Entity);
+}
+
+void PreprocessingRecord::SetExternalSource(
+ ExternalPreprocessingRecordSource &Source,
+ unsigned NumPreallocatedEntities) {
+ assert(!ExternalSource &&
+ "Preprocessing record already has an external source");
+ ExternalSource = &Source;
+ this->NumPreallocatedEntities = NumPreallocatedEntities;
+ PreprocessedEntities.insert(PreprocessedEntities.begin(),
+ NumPreallocatedEntities, 0);
+}
+
+void PreprocessingRecord::SetPreallocatedEntity(unsigned Index,
+ PreprocessedEntity *Entity) {
+ assert(Index < NumPreallocatedEntities &&"Out-of-bounds preallocated entity");
+ PreprocessedEntities[Index] = Entity;
+}
+
+void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
+ MacroDefinition *MD) {
+ MacroDefinitions[Macro] = MD;
+}
+
+MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
+ llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
+ = MacroDefinitions.find(MI);
+ if (Pos == MacroDefinitions.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) {
+ if (MacroDefinition *Def = findMacroDefinition(MI))
+ PreprocessedEntities.push_back(
+ new (*this) MacroInstantiation(Id.getIdentifierInfo(),
+ Id.getLocation(),
+ Def));
+}
+
+void PreprocessingRecord::MacroDefined(const Token &Id,
+ const MacroInfo *MI) {
+ SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
+ MacroDefinition *Def
+ = new (*this) MacroDefinition(Id.getIdentifierInfo(),
+ MI->getDefinitionLoc(),
+ R);
+ MacroDefinitions[MI] = Def;
+ PreprocessedEntities.push_back(Def);
+}
+
+void PreprocessingRecord::MacroUndefined(const Token &Id,
+ const MacroInfo *MI) {
+ llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
+ = MacroDefinitions.find(MI);
+ if (Pos != MacroDefinitions.end())
+ MacroDefinitions.erase(Pos);
+}
+
+void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc,
+ const clang::Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ clang::SourceLocation EndLoc) {
+ InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
+
+ switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
+ case tok::pp_include:
+ Kind = InclusionDirective::Include;
+ break;
+
+ case tok::pp_import:
+ Kind = InclusionDirective::Import;
+ break;
+
+ case tok::pp_include_next:
+ Kind = InclusionDirective::IncludeNext;
+ break;
+
+ case tok::pp___include_macros:
+ Kind = InclusionDirective::IncludeMacros;
+ break;
+
+ default:
+ llvm_unreachable("Unknown include directive kind");
+ return;
+ }
+
+ clang::InclusionDirective *ID
+ = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
+ File, SourceRange(HashLoc, EndLoc));
+ PreprocessedEntities.push_back(ID);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
new file mode 100644
index 0000000..6fe414b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
@@ -0,0 +1,494 @@
+//===--- Preprocess.cpp - C Language Family Preprocessor Implementation ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Preprocessor interface.
+//
+//===----------------------------------------------------------------------===//
+//
+// Options to support:
+// -H - Print the name of each header file used.
+// -d[DNI] - Dump various things.
+// -fworking-directory - #line's with preprocessor's working dir.
+// -fpreprocessed
+// -dependency-file,-M,-MM,-MF,-MG,-MP,-MT,-MQ,-MD,-MMD
+// -W*
+// -w
+//
+// Messages to emit:
+// "Multiple include guards may be useful for:\n"
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "MacroArgs.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
+
+Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
+ const TargetInfo &target, SourceManager &SM,
+ HeaderSearch &Headers,
+ IdentifierInfoLookup* IILookup,
+ bool OwnsHeaders)
+ : Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
+ SourceMgr(SM),
+ HeaderInfo(Headers), ExternalSource(0),
+ Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
+ CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
+ CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0),
+ MICache(0) {
+ ScratchBuf = new ScratchBuffer(SourceMgr);
+ CounterValue = 0; // __COUNTER__ starts at 0.
+ OwnsHeaderSearch = OwnsHeaders;
+
+ // Clear stats.
+ NumDirectives = NumDefined = NumUndefined = NumPragma = 0;
+ NumIf = NumElse = NumEndif = 0;
+ NumEnteredSourceFiles = 0;
+ NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0;
+ NumFastMacroExpanded = NumTokenPaste = NumFastTokenPaste = 0;
+ MaxIncludeStackDepth = 0;
+ NumSkipped = 0;
+
+ // Default to discarding comments.
+ KeepComments = false;
+ KeepMacroComments = false;
+
+ // Macro expansion is enabled.
+ DisableMacroExpansion = false;
+ InMacroArgs = false;
+ NumCachedTokenLexers = 0;
+
+ CachedLexPos = 0;
+
+ // We haven't read anything from the external source.
+ ReadMacrosFromExternalSource = false;
+
+ // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
+ // This gets unpoisoned where it is allowed.
+ (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
+
+ // Initialize the pragma handlers.
+ PragmaHandlers = new PragmaNamespace(llvm::StringRef());
+ RegisterBuiltinPragmas();
+
+ // Initialize builtin macros like __LINE__ and friends.
+ RegisterBuiltinMacros();
+}
+
+Preprocessor::~Preprocessor() {
+ assert(BacktrackPositions.empty() && "EnableBacktrack/Backtrack imbalance!");
+
+ while (!IncludeMacroStack.empty()) {
+ delete IncludeMacroStack.back().TheLexer;
+ delete IncludeMacroStack.back().TheTokenLexer;
+ IncludeMacroStack.pop_back();
+ }
+
+ // Free any macro definitions.
+ for (MacroInfoChain *I = MIChainHead ; I ; I = I->Next)
+ I->MI.Destroy();
+
+ // Free any cached macro expanders.
+ for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i)
+ delete TokenLexerCache[i];
+
+ // Free any cached MacroArgs.
+ for (MacroArgs *ArgList = MacroArgCache; ArgList; )
+ ArgList = ArgList->deallocate();
+
+ // Release pragma information.
+ delete PragmaHandlers;
+
+ // Delete the scratch buffer info.
+ delete ScratchBuf;
+
+ // Delete the header search info, if we own it.
+ if (OwnsHeaderSearch)
+ delete &HeaderInfo;
+
+ delete Callbacks;
+}
+
+void Preprocessor::setPTHManager(PTHManager* pm) {
+ PTH.reset(pm);
+ FileMgr.addStatCache(PTH->createStatCache());
+}
+
+void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
+ llvm::errs() << tok::getTokenName(Tok.getKind()) << " '"
+ << getSpelling(Tok) << "'";
+
+ if (!DumpFlags) return;
+
+ llvm::errs() << "\t";
+ if (Tok.isAtStartOfLine())
+ llvm::errs() << " [StartOfLine]";
+ if (Tok.hasLeadingSpace())
+ llvm::errs() << " [LeadingSpace]";
+ if (Tok.isExpandDisabled())
+ llvm::errs() << " [ExpandDisabled]";
+ if (Tok.needsCleaning()) {
+ const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
+ llvm::errs() << " [UnClean='" << llvm::StringRef(Start, Tok.getLength())
+ << "']";
+ }
+
+ llvm::errs() << "\tLoc=<";
+ DumpLocation(Tok.getLocation());
+ llvm::errs() << ">";
+}
+
+void Preprocessor::DumpLocation(SourceLocation Loc) const {
+ Loc.dump(SourceMgr);
+}
+
+void Preprocessor::DumpMacro(const MacroInfo &MI) const {
+ llvm::errs() << "MACRO: ";
+ for (unsigned i = 0, e = MI.getNumTokens(); i != e; ++i) {
+ DumpToken(MI.getReplacementToken(i));
+ llvm::errs() << " ";
+ }
+ llvm::errs() << "\n";
+}
+
+void Preprocessor::PrintStats() {
+ llvm::errs() << "\n*** Preprocessor Stats:\n";
+ llvm::errs() << NumDirectives << " directives found:\n";
+ llvm::errs() << " " << NumDefined << " #define.\n";
+ llvm::errs() << " " << NumUndefined << " #undef.\n";
+ llvm::errs() << " #include/#include_next/#import:\n";
+ llvm::errs() << " " << NumEnteredSourceFiles << " source files entered.\n";
+ llvm::errs() << " " << MaxIncludeStackDepth << " max include stack depth\n";
+ llvm::errs() << " " << NumIf << " #if/#ifndef/#ifdef.\n";
+ llvm::errs() << " " << NumElse << " #else/#elif.\n";
+ llvm::errs() << " " << NumEndif << " #endif.\n";
+ llvm::errs() << " " << NumPragma << " #pragma.\n";
+ llvm::errs() << NumSkipped << " #if/#ifndef#ifdef regions skipped\n";
+
+ llvm::errs() << NumMacroExpanded << "/" << NumFnMacroExpanded << "/"
+ << NumBuiltinMacroExpanded << " obj/fn/builtin macros expanded, "
+ << NumFastMacroExpanded << " on the fast path.\n";
+ llvm::errs() << (NumFastTokenPaste+NumTokenPaste)
+ << " token paste (##) operations performed, "
+ << NumFastTokenPaste << " on the fast path.\n";
+}
+
+Preprocessor::macro_iterator
+Preprocessor::macro_begin(bool IncludeExternalMacros) const {
+ if (IncludeExternalMacros && ExternalSource &&
+ !ReadMacrosFromExternalSource) {
+ ReadMacrosFromExternalSource = true;
+ ExternalSource->ReadDefinedMacros();
+ }
+
+ return Macros.begin();
+}
+
+Preprocessor::macro_iterator
+Preprocessor::macro_end(bool IncludeExternalMacros) const {
+ if (IncludeExternalMacros && ExternalSource &&
+ !ReadMacrosFromExternalSource) {
+ ReadMacrosFromExternalSource = true;
+ ExternalSource->ReadDefinedMacros();
+ }
+
+ return Macros.end();
+}
+
+bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
+ unsigned TruncateAtLine,
+ unsigned TruncateAtColumn) {
+ using llvm::MemoryBuffer;
+
+ CodeCompletionFile = File;
+
+ // Okay to clear out the code-completion point by passing NULL.
+ if (!CodeCompletionFile)
+ return false;
+
+ // Load the actual file's contents.
+ bool Invalid = false;
+ const MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File, &Invalid);
+ if (Invalid)
+ return true;
+
+ // Find the byte position of the truncation point.
+ const char *Position = Buffer->getBufferStart();
+ for (unsigned Line = 1; Line < TruncateAtLine; ++Line) {
+ for (; *Position; ++Position) {
+ if (*Position != '\r' && *Position != '\n')
+ continue;
+
+ // Eat \r\n or \n\r as a single line.
+ if ((Position[1] == '\r' || Position[1] == '\n') &&
+ Position[0] != Position[1])
+ ++Position;
+ ++Position;
+ break;
+ }
+ }
+
+ Position += TruncateAtColumn - 1;
+
+ // Truncate the buffer.
+ if (Position < Buffer->getBufferEnd()) {
+ llvm::StringRef Data(Buffer->getBufferStart(),
+ Position-Buffer->getBufferStart());
+ MemoryBuffer *TruncatedBuffer
+ = MemoryBuffer::getMemBufferCopy(Data, Buffer->getBufferIdentifier());
+ SourceMgr.overrideFileContents(File, TruncatedBuffer);
+ }
+
+ return false;
+}
+
+bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) const {
+ return CodeCompletionFile && FileLoc.isFileID() &&
+ SourceMgr.getFileEntryForID(SourceMgr.getFileID(FileLoc))
+ == CodeCompletionFile;
+}
+
+void Preprocessor::CodeCompleteNaturalLanguage() {
+ SetCodeCompletionPoint(0, 0, 0);
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ if (CodeComplete)
+ CodeComplete->CodeCompleteNaturalLanguage();
+}
+
+
+/// getSpelling - This method is used to get the spelling of a token into a
+/// SmallVector. Note that the returned StringRef may not point to the
+/// supplied buffer if a copy can be avoided.
+llvm::StringRef Preprocessor::getSpelling(const Token &Tok,
+ llvm::SmallVectorImpl<char> &Buffer,
+ bool *Invalid) const {
+ // NOTE: this has to be checked *before* testing for an IdentifierInfo.
+ if (Tok.isNot(tok::raw_identifier)) {
+ // Try the fast path.
+ if (const IdentifierInfo *II = Tok.getIdentifierInfo())
+ return II->getName();
+ }
+
+ // Resize the buffer if we need to copy into it.
+ if (Tok.needsCleaning())
+ Buffer.resize(Tok.getLength());
+
+ const char *Ptr = Buffer.data();
+ unsigned Len = getSpelling(Tok, Ptr, Invalid);
+ return llvm::StringRef(Ptr, Len);
+}
+
+/// CreateString - Plop the specified string into a scratch buffer and return a
+/// location for it. If specified, the source location provides a source
+/// location for the token.
+void Preprocessor::CreateString(const char *Buf, unsigned Len, Token &Tok,
+ SourceLocation InstantiationLoc) {
+ Tok.setLength(Len);
+
+ const char *DestPtr;
+ SourceLocation Loc = ScratchBuf->getToken(Buf, Len, DestPtr);
+
+ if (InstantiationLoc.isValid())
+ Loc = SourceMgr.createInstantiationLoc(Loc, InstantiationLoc,
+ InstantiationLoc, Len);
+ Tok.setLocation(Loc);
+
+ // If this is a raw identifier or a literal token, set the pointer data.
+ if (Tok.is(tok::raw_identifier))
+ Tok.setRawIdentifierData(DestPtr);
+ else if (Tok.isLiteral())
+ Tok.setLiteralData(DestPtr);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Initialization Methods
+//===----------------------------------------------------------------------===//
+
+
+/// EnterMainSourceFile - Enter the specified FileID as the main source file,
+/// which implicitly adds the builtin defines etc.
+void Preprocessor::EnterMainSourceFile() {
+ // We do not allow the preprocessor to reenter the main file. Doing so will
+ // cause FileID's to accumulate information from both runs (e.g. #line
+ // information) and predefined macros aren't guaranteed to be set properly.
+ assert(NumEnteredSourceFiles == 0 && "Cannot reenter the main file!");
+ FileID MainFileID = SourceMgr.getMainFileID();
+
+ // Enter the main file source buffer.
+ EnterSourceFile(MainFileID, 0, SourceLocation());
+
+ // If we've been asked to skip bytes in the main file (e.g., as part of a
+ // precompiled preamble), do so now.
+ if (SkipMainFilePreamble.first > 0)
+ CurLexer->SkipBytes(SkipMainFilePreamble.first,
+ SkipMainFilePreamble.second);
+
+ // Tell the header info that the main file was entered. If the file is later
+ // #imported, it won't be re-entered.
+ if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
+ HeaderInfo.IncrementIncludeCount(FE);
+
+ // Preprocess Predefines to populate the initial preprocessor state.
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
+ assert(SB && "Cannot create predefined source buffer");
+ FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
+ assert(!FID.isInvalid() && "Could not create FileID for predefines?");
+
+ // Start parsing the predefines.
+ EnterSourceFile(FID, 0, SourceLocation());
+}
+
+void Preprocessor::EndSourceFile() {
+ // Notify the client that we reached the end of the source file.
+ if (Callbacks)
+ Callbacks->EndOfMainFile();
+}
+
+//===----------------------------------------------------------------------===//
+// Lexer Event Handling.
+//===----------------------------------------------------------------------===//
+
+/// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
+/// identifier information for the token and install it into the token,
+/// updating the token kind accordingly.
+IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
+ assert(Identifier.getRawIdentifierData() != 0 && "No raw identifier data!");
+
+ // Look up this token, see if it is a macro, or if it is a language keyword.
+ IdentifierInfo *II;
+ if (!Identifier.needsCleaning()) {
+ // No cleaning needed, just use the characters from the lexed buffer.
+ II = getIdentifierInfo(llvm::StringRef(Identifier.getRawIdentifierData(),
+ Identifier.getLength()));
+ } else {
+ // Cleaning needed, alloca a buffer, clean into it, then use the buffer.
+ llvm::SmallString<64> IdentifierBuffer;
+ llvm::StringRef CleanedStr = getSpelling(Identifier, IdentifierBuffer);
+ II = getIdentifierInfo(CleanedStr);
+ }
+
+ // Update the token info (identifier info and appropriate token kind).
+ Identifier.setIdentifierInfo(II);
+ Identifier.setKind(II->getTokenID());
+
+ return II;
+}
+
+
+/// HandleIdentifier - This callback is invoked when the lexer reads an
+/// identifier. This callback looks up the identifier in the map and/or
+/// potentially macro expands it or turns it into a named token (like 'for').
+///
+/// Note that callers of this method are guarded by checking the
+/// IdentifierInfo's 'isHandleIdentifierCase' bit. If this method changes, the
+/// IdentifierInfo methods that compute these properties will need to change to
+/// match.
+void Preprocessor::HandleIdentifier(Token &Identifier) {
+ assert(Identifier.getIdentifierInfo() &&
+ "Can't handle identifiers without identifier info!");
+
+ IdentifierInfo &II = *Identifier.getIdentifierInfo();
+
+ // If this identifier was poisoned, and if it was not produced from a macro
+ // expansion, emit an error.
+ if (II.isPoisoned() && CurPPLexer) {
+ if (&II != Ident__VA_ARGS__) // We warn about __VA_ARGS__ with poisoning.
+ Diag(Identifier, diag::err_pp_used_poisoned_id);
+ else
+ Diag(Identifier, diag::ext_pp_bad_vaargs_use);
+ }
+
+ // If this is a macro to be expanded, do it.
+ if (MacroInfo *MI = getMacroInfo(&II)) {
+ if (!DisableMacroExpansion && !Identifier.isExpandDisabled()) {
+ if (MI->isEnabled()) {
+ if (!HandleMacroExpandedIdentifier(Identifier, MI))
+ return;
+ } else {
+ // C99 6.10.3.4p2 says that a disabled macro may never again be
+ // expanded, even if it's in a context where it could be expanded in the
+ // future.
+ Identifier.setFlag(Token::DisableExpand);
+ }
+ }
+ }
+
+ // C++ 2.11p2: If this is an alternative representation of a C++ operator,
+ // then we act as if it is the actual operator and not the textual
+ // representation of it.
+ if (II.isCPlusPlusOperatorKeyword())
+ Identifier.setIdentifierInfo(0);
+
+ // If this is an extension token, diagnose its use.
+ // We avoid diagnosing tokens that originate from macro definitions.
+ // FIXME: This warning is disabled in cases where it shouldn't be,
+ // like "#define TY typeof", "TY(1) x".
+ if (II.isExtensionToken() && !DisableMacroExpansion)
+ Diag(Identifier, diag::ext_token_used);
+}
+
+void Preprocessor::AddCommentHandler(CommentHandler *Handler) {
+ assert(Handler && "NULL comment handler");
+ assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) ==
+ CommentHandlers.end() && "Comment handler already registered");
+ CommentHandlers.push_back(Handler);
+}
+
+void Preprocessor::RemoveCommentHandler(CommentHandler *Handler) {
+ std::vector<CommentHandler *>::iterator Pos
+ = std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler);
+ assert(Pos != CommentHandlers.end() && "Comment handler not registered");
+ CommentHandlers.erase(Pos);
+}
+
+bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
+ bool AnyPendingTokens = false;
+ for (std::vector<CommentHandler *>::iterator H = CommentHandlers.begin(),
+ HEnd = CommentHandlers.end();
+ H != HEnd; ++H) {
+ if ((*H)->HandleComment(*this, Comment))
+ AnyPendingTokens = true;
+ }
+ if (!AnyPendingTokens || getCommentRetentionState())
+ return false;
+ Lex(result);
+ return true;
+}
+
+CommentHandler::~CommentHandler() { }
+
+CodeCompletionHandler::~CodeCompletionHandler() { }
+
+void Preprocessor::createPreprocessingRecord() {
+ if (Record)
+ return;
+
+ Record = new PreprocessingRecord;
+ addPPCallbacks(Record);
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
new file mode 100644
index 0000000..e005c49
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessorLexer.cpp
@@ -0,0 +1,45 @@
+//===--- PreprocessorLexer.cpp - C Language Family Lexer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PreprocessorLexer and Token interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+/// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
+/// (potentially) macro expand the filename.
+void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) {
+ assert(ParsingPreprocessorDirective &&
+ ParsingFilename == false &&
+ "Must be in a preprocessing directive!");
+
+ // We are now parsing a filename!
+ ParsingFilename = true;
+
+ // Lex the filename.
+ IndirectLex(FilenameTok);
+
+ // We should have obtained the filename now.
+ ParsingFilename = false;
+
+ // No filename?
+ if (FilenameTok.is(tok::eom))
+ PP->Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+}
+
+/// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+/// getFileID(), this only works for lexers with attached preprocessors.
+const FileEntry *PreprocessorLexer::getFileEntry() const {
+ return PP->getSourceManager().getFileEntryForID(getFileID());
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
new file mode 100644
index 0000000..0e98c17
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp
@@ -0,0 +1,73 @@
+//===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ScratchBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cstring>
+using namespace clang;
+
+// ScratchBufSize - The size of each chunk of scratch memory. Slightly less
+//than a page, almost certainly enough for anything. :)
+static const unsigned ScratchBufSize = 4060;
+
+ScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
+ // Set BytesUsed so that the first call to getToken will require an alloc.
+ BytesUsed = ScratchBufSize;
+}
+
+/// getToken - Splat the specified text into a temporary MemoryBuffer and
+/// return a SourceLocation that refers to the token. This is just like the
+/// method below, but returns a location that indicates the physloc of the
+/// token.
+SourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
+ const char *&DestPtr) {
+ if (BytesUsed+Len+2 > ScratchBufSize)
+ AllocScratchBuffer(Len+2);
+
+ // Prefix the token with a \n, so that it looks like it is the first thing on
+ // its own virtual line in caret diagnostics.
+ CurBuffer[BytesUsed++] = '\n';
+
+ // Return a pointer to the character data.
+ DestPtr = CurBuffer+BytesUsed;
+
+ // Copy the token data into the buffer.
+ memcpy(CurBuffer+BytesUsed, Buf, Len);
+
+ // Remember that we used these bytes.
+ BytesUsed += Len+1;
+
+ // Add a NUL terminator to the token. This keeps the tokens separated, in
+ // case they get relexed, and puts them on their own virtual lines in case a
+ // diagnostic points to one.
+ CurBuffer[BytesUsed-1] = '\0';
+
+ return BufferStartLoc.getFileLocWithOffset(BytesUsed-Len-1);
+}
+
+void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
+ // Only pay attention to the requested length if it is larger than our default
+ // page size. If it is, we allocate an entire chunk for it. This is to
+ // support gigantic tokens, which almost certainly won't happen. :)
+ if (RequestLen < ScratchBufSize)
+ RequestLen = ScratchBufSize;
+
+ llvm::MemoryBuffer *Buf =
+ llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
+ FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
+ BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
+ CurBuffer = const_cast<char*>(Buf->getBufferStart());
+ BytesUsed = 1;
+ CurBuffer[0] = '0'; // Start out with a \0 for cleanliness.
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
new file mode 100644
index 0000000..3e9e855
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenConcatenation.cpp
@@ -0,0 +1,231 @@
+//===--- TokenConcatenation.cpp - Token Concatenation Avoidance -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenConcatenation class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/TokenConcatenation.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+
+/// StartsWithL - Return true if the spelling of this token starts with 'L'.
+bool TokenConcatenation::StartsWithL(const Token &Tok) const {
+ if (!Tok.needsCleaning()) {
+ SourceManager &SM = PP.getSourceManager();
+ return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())) == 'L';
+ }
+
+ if (Tok.getLength() < 256) {
+ char Buffer[256];
+ const char *TokPtr = Buffer;
+ PP.getSpelling(Tok, TokPtr);
+ return TokPtr[0] == 'L';
+ }
+
+ return PP.getSpelling(Tok)[0] == 'L';
+}
+
+/// IsIdentifierL - Return true if the spelling of this token is literally
+/// 'L'.
+bool TokenConcatenation::IsIdentifierL(const Token &Tok) const {
+ if (!Tok.needsCleaning()) {
+ if (Tok.getLength() != 1)
+ return false;
+ SourceManager &SM = PP.getSourceManager();
+ return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())) == 'L';
+ }
+
+ if (Tok.getLength() < 256) {
+ char Buffer[256];
+ const char *TokPtr = Buffer;
+ if (PP.getSpelling(Tok, TokPtr) != 1)
+ return false;
+ return TokPtr[0] == 'L';
+ }
+
+ return PP.getSpelling(Tok) == "L";
+}
+
+TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
+ memset(TokenInfo, 0, sizeof(TokenInfo));
+
+ // These tokens have custom code in AvoidConcat.
+ TokenInfo[tok::identifier ] |= aci_custom;
+ TokenInfo[tok::numeric_constant] |= aci_custom_firstchar;
+ TokenInfo[tok::period ] |= aci_custom_firstchar;
+ TokenInfo[tok::amp ] |= aci_custom_firstchar;
+ TokenInfo[tok::plus ] |= aci_custom_firstchar;
+ TokenInfo[tok::minus ] |= aci_custom_firstchar;
+ TokenInfo[tok::slash ] |= aci_custom_firstchar;
+ TokenInfo[tok::less ] |= aci_custom_firstchar;
+ TokenInfo[tok::greater ] |= aci_custom_firstchar;
+ TokenInfo[tok::pipe ] |= aci_custom_firstchar;
+ TokenInfo[tok::percent ] |= aci_custom_firstchar;
+ TokenInfo[tok::colon ] |= aci_custom_firstchar;
+ TokenInfo[tok::hash ] |= aci_custom_firstchar;
+ TokenInfo[tok::arrow ] |= aci_custom_firstchar;
+
+ // These tokens change behavior if followed by an '='.
+ TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
+ TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
+ TokenInfo[tok::minus ] |= aci_avoid_equal; // -=
+ TokenInfo[tok::slash ] |= aci_avoid_equal; // /=
+ TokenInfo[tok::less ] |= aci_avoid_equal; // <=
+ TokenInfo[tok::greater ] |= aci_avoid_equal; // >=
+ TokenInfo[tok::pipe ] |= aci_avoid_equal; // |=
+ TokenInfo[tok::percent ] |= aci_avoid_equal; // %=
+ TokenInfo[tok::star ] |= aci_avoid_equal; // *=
+ TokenInfo[tok::exclaim ] |= aci_avoid_equal; // !=
+ TokenInfo[tok::lessless ] |= aci_avoid_equal; // <<=
+ TokenInfo[tok::greatergreater] |= aci_avoid_equal; // >>=
+ TokenInfo[tok::caret ] |= aci_avoid_equal; // ^=
+ TokenInfo[tok::equal ] |= aci_avoid_equal; // ==
+}
+
+/// GetFirstChar - Get the first character of the token \arg Tok,
+/// avoiding calls to getSpelling where possible.
+static char GetFirstChar(Preprocessor &PP, const Token &Tok) {
+ if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+ // Avoid spelling identifiers, the most common form of token.
+ return II->getNameStart()[0];
+ } else if (!Tok.needsCleaning()) {
+ if (Tok.isLiteral() && Tok.getLiteralData()) {
+ return *Tok.getLiteralData();
+ } else {
+ SourceManager &SM = PP.getSourceManager();
+ return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation()));
+ }
+ } else if (Tok.getLength() < 256) {
+ char Buffer[256];
+ const char *TokPtr = Buffer;
+ PP.getSpelling(Tok, TokPtr);
+ return TokPtr[0];
+ } else {
+ return PP.getSpelling(Tok)[0];
+ }
+}
+
+/// AvoidConcat - If printing PrevTok immediately followed by Tok would cause
+/// the two individual tokens to be lexed as a single token, return true
+/// (which causes a space to be printed between them). This allows the output
+/// of -E mode to be lexed to the same token stream as lexing the input
+/// directly would.
+///
+/// This code must conservatively return true if it doesn't want to be 100%
+/// accurate. This will cause the output to include extra space characters,
+/// but the resulting output won't have incorrect concatenations going on.
+/// Examples include "..", which we print with a space between, because we
+/// don't want to track enough to tell "x.." from "...".
+bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
+ const Token &PrevTok,
+ const Token &Tok) const {
+ // First, check to see if the tokens were directly adjacent in the original
+ // source. If they were, it must be okay to stick them together: if there
+ // were an issue, the tokens would have been lexed differently.
+ if (PrevTok.getLocation().isFileID() && Tok.getLocation().isFileID() &&
+ PrevTok.getLocation().getFileLocWithOffset(PrevTok.getLength()) ==
+ Tok.getLocation())
+ return false;
+
+ tok::TokenKind PrevKind = PrevTok.getKind();
+ if (PrevTok.getIdentifierInfo()) // Language keyword or named operator.
+ PrevKind = tok::identifier;
+
+ // Look up information on when we should avoid concatenation with prevtok.
+ unsigned ConcatInfo = TokenInfo[PrevKind];
+
+ // If prevtok never causes a problem for anything after it, return quickly.
+ if (ConcatInfo == 0) return false;
+
+ if (ConcatInfo & aci_avoid_equal) {
+ // If the next token is '=' or '==', avoid concatenation.
+ if (Tok.is(tok::equal) || Tok.is(tok::equalequal))
+ return true;
+ ConcatInfo &= ~aci_avoid_equal;
+ }
+
+ if (ConcatInfo == 0) return false;
+
+ // Basic algorithm: we look at the first character of the second token, and
+ // determine whether it, if appended to the first token, would form (or
+ // would contribute) to a larger token if concatenated.
+ char FirstChar = 0;
+ if (ConcatInfo & aci_custom) {
+ // If the token does not need to know the first character, don't get it.
+ } else {
+ FirstChar = GetFirstChar(PP, Tok);
+ }
+
+ switch (PrevKind) {
+ default:
+ llvm_unreachable("InitAvoidConcatTokenInfo built wrong");
+ return true;
+
+ case tok::raw_identifier:
+ llvm_unreachable("tok::raw_identifier in non-raw lexing mode!");
+ return true;
+
+ case tok::identifier: // id+id or id+number or id+L"foo".
+ // id+'.'... will not append.
+ if (Tok.is(tok::numeric_constant))
+ return GetFirstChar(PP, Tok) != '.';
+
+ if (Tok.getIdentifierInfo() || Tok.is(tok::wide_string_literal) /* ||
+ Tok.is(tok::wide_char_literal)*/)
+ return true;
+
+ // If this isn't identifier + string, we're done.
+ if (Tok.isNot(tok::char_constant) && Tok.isNot(tok::string_literal))
+ return false;
+
+ // FIXME: need a wide_char_constant!
+
+ // If the string was a wide string L"foo" or wide char L'f', it would
+ // concat with the previous identifier into fooL"bar". Avoid this.
+ if (StartsWithL(Tok))
+ return true;
+
+ // Otherwise, this is a narrow character or string. If the *identifier*
+ // is a literal 'L', avoid pasting L "foo" -> L"foo".
+ return IsIdentifierL(PrevTok);
+ case tok::numeric_constant:
+ return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
+ FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
+ case tok::period: // ..., .*, .1234
+ return (FirstChar == '.' && PrevPrevTok.is(tok::period)) ||
+ isdigit(FirstChar) ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == '*');
+ case tok::amp: // &&
+ return FirstChar == '&';
+ case tok::plus: // ++
+ return FirstChar == '+';
+ case tok::minus: // --, ->, ->*
+ return FirstChar == '-' || FirstChar == '>';
+ case tok::slash: //, /*, //
+ return FirstChar == '*' || FirstChar == '/';
+ case tok::less: // <<, <<=, <:, <%
+ return FirstChar == '<' || FirstChar == ':' || FirstChar == '%';
+ case tok::greater: // >>, >>=
+ return FirstChar == '>';
+ case tok::pipe: // ||
+ return FirstChar == '|';
+ case tok::percent: // %>, %:
+ return FirstChar == '>' || FirstChar == ':';
+ case tok::colon: // ::, :>
+ return FirstChar == '>' ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == ':');
+ case tok::hash: // ##, #@, %:%:
+ return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
+ case tok::arrow: // ->*
+ return PP.getLangOptions().CPlusPlus && FirstChar == '*';
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
new file mode 100644
index 0000000..ea39b47
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -0,0 +1,562 @@
+//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/TokenLexer.h"
+#include "MacroArgs.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/LexDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+
+/// Create a TokenLexer for the specified macro with the specified actual
+/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
+void TokenLexer::Init(Token &Tok, SourceLocation ILEnd, MacroArgs *Actuals) {
+ // If the client is reusing a TokenLexer, make sure to free any memory
+ // associated with it.
+ destroy();
+
+ Macro = PP.getMacroInfo(Tok.getIdentifierInfo());
+ ActualArgs = Actuals;
+ CurToken = 0;
+
+ InstantiateLocStart = Tok.getLocation();
+ InstantiateLocEnd = ILEnd;
+ AtStartOfLine = Tok.isAtStartOfLine();
+ HasLeadingSpace = Tok.hasLeadingSpace();
+ Tokens = &*Macro->tokens_begin();
+ OwnsTokens = false;
+ DisableMacroExpansion = false;
+ NumTokens = Macro->tokens_end()-Macro->tokens_begin();
+
+ // If this is a function-like macro, expand the arguments and change
+ // Tokens to point to the expanded tokens.
+ if (Macro->isFunctionLike() && Macro->getNumArgs())
+ ExpandFunctionArguments();
+
+ // Mark the macro as currently disabled, so that it is not recursively
+ // expanded. The macro must be disabled only after argument pre-expansion of
+ // function-like macro arguments occurs.
+ Macro->DisableMacro();
+}
+
+
+
+/// Create a TokenLexer for the specified token stream. This does not
+/// take ownership of the specified token vector.
+void TokenLexer::Init(const Token *TokArray, unsigned NumToks,
+ bool disableMacroExpansion, bool ownsTokens) {
+ // If the client is reusing a TokenLexer, make sure to free any memory
+ // associated with it.
+ destroy();
+
+ Macro = 0;
+ ActualArgs = 0;
+ Tokens = TokArray;
+ OwnsTokens = ownsTokens;
+ DisableMacroExpansion = disableMacroExpansion;
+ NumTokens = NumToks;
+ CurToken = 0;
+ InstantiateLocStart = InstantiateLocEnd = SourceLocation();
+ AtStartOfLine = false;
+ HasLeadingSpace = false;
+
+ // Set HasLeadingSpace/AtStartOfLine so that the first token will be
+ // returned unmodified.
+ if (NumToks != 0) {
+ AtStartOfLine = TokArray[0].isAtStartOfLine();
+ HasLeadingSpace = TokArray[0].hasLeadingSpace();
+ }
+}
+
+
+void TokenLexer::destroy() {
+ // If this was a function-like macro that actually uses its arguments, delete
+ // the expanded tokens.
+ if (OwnsTokens) {
+ delete [] Tokens;
+ Tokens = 0;
+ OwnsTokens = false;
+ }
+
+ // TokenLexer owns its formal arguments.
+ if (ActualArgs) ActualArgs->destroy(PP);
+}
+
+/// Expand the arguments of a function-like macro so that we can quickly
+/// return preexpanded tokens from Tokens.
+void TokenLexer::ExpandFunctionArguments() {
+ llvm::SmallVector<Token, 128> ResultToks;
+
+ // Loop through 'Tokens', expanding them into ResultToks. Keep
+ // track of whether we change anything. If not, no need to keep them. If so,
+ // we install the newly expanded sequence as the new 'Tokens' list.
+ bool MadeChange = false;
+
+ // NextTokGetsSpace - When this is true, the next token appended to the
+ // output list will get a leading space, regardless of whether it had one to
+ // begin with or not. This is used for placemarker support.
+ bool NextTokGetsSpace = false;
+
+ for (unsigned i = 0, e = NumTokens; i != e; ++i) {
+ // If we found the stringify operator, get the argument stringified. The
+ // preprocessor already verified that the following token is a macro name
+ // when the #define was parsed.
+ const Token &CurTok = Tokens[i];
+ if (CurTok.is(tok::hash) || CurTok.is(tok::hashat)) {
+ int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo());
+ assert(ArgNo != -1 && "Token following # is not an argument?");
+
+ Token Res;
+ if (CurTok.is(tok::hash)) // Stringify
+ Res = ActualArgs->getStringifiedArgument(ArgNo, PP);
+ else {
+ // 'charify': don't bother caching these.
+ Res = MacroArgs::StringifyArgument(ActualArgs->getUnexpArgument(ArgNo),
+ PP, true);
+ }
+
+ // The stringified/charified string leading space flag gets set to match
+ // the #/#@ operator.
+ if (CurTok.hasLeadingSpace() || NextTokGetsSpace)
+ Res.setFlag(Token::LeadingSpace);
+
+ ResultToks.push_back(Res);
+ MadeChange = true;
+ ++i; // Skip arg name.
+ NextTokGetsSpace = false;
+ continue;
+ }
+
+ // Otherwise, if this is not an argument token, just add the token to the
+ // output buffer.
+ IdentifierInfo *II = CurTok.getIdentifierInfo();
+ int ArgNo = II ? Macro->getArgumentNum(II) : -1;
+ if (ArgNo == -1) {
+ // This isn't an argument, just add it.
+ ResultToks.push_back(CurTok);
+
+ if (NextTokGetsSpace) {
+ ResultToks.back().setFlag(Token::LeadingSpace);
+ NextTokGetsSpace = false;
+ }
+ continue;
+ }
+
+ // An argument is expanded somehow, the result is different than the
+ // input.
+ MadeChange = true;
+
+ // Otherwise, this is a use of the argument. Find out if there is a paste
+ // (##) operator before or after the argument.
+ bool PasteBefore =
+ !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
+ bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
+
+ // If it is not the LHS/RHS of a ## operator, we must pre-expand the
+ // argument and substitute the expanded tokens into the result. This is
+ // C99 6.10.3.1p1.
+ if (!PasteBefore && !PasteAfter) {
+ const Token *ResultArgToks;
+
+ // Only preexpand the argument if it could possibly need it. This
+ // avoids some work in common cases.
+ const Token *ArgTok = ActualArgs->getUnexpArgument(ArgNo);
+ if (ActualArgs->ArgNeedsPreexpansion(ArgTok, PP))
+ ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, Macro, PP)[0];
+ else
+ ResultArgToks = ArgTok; // Use non-preexpanded tokens.
+
+ // If the arg token expanded into anything, append it.
+ if (ResultArgToks->isNot(tok::eof)) {
+ unsigned FirstResult = ResultToks.size();
+ unsigned NumToks = MacroArgs::getArgLength(ResultArgToks);
+ ResultToks.append(ResultArgToks, ResultArgToks+NumToks);
+
+ // If any tokens were substituted from the argument, the whitespace
+ // before the first token should match the whitespace of the arg
+ // identifier.
+ ResultToks[FirstResult].setFlagValue(Token::LeadingSpace,
+ CurTok.hasLeadingSpace() ||
+ NextTokGetsSpace);
+ NextTokGetsSpace = false;
+ } else {
+ // If this is an empty argument, and if there was whitespace before the
+ // formal token, make sure the next token gets whitespace before it.
+ NextTokGetsSpace = CurTok.hasLeadingSpace();
+ }
+ continue;
+ }
+
+ // Okay, we have a token that is either the LHS or RHS of a paste (##)
+ // argument. It gets substituted as its non-pre-expanded tokens.
+ const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo);
+ unsigned NumToks = MacroArgs::getArgLength(ArgToks);
+ if (NumToks) { // Not an empty argument?
+ // If this is the GNU ", ## __VA_ARG__" extension, and we just learned
+ // that __VA_ARG__ expands to multiple tokens, avoid a pasting error when
+ // the expander trys to paste ',' with the first token of the __VA_ARG__
+ // expansion.
+ if (PasteBefore && ResultToks.size() >= 2 &&
+ ResultToks[ResultToks.size()-2].is(tok::comma) &&
+ (unsigned)ArgNo == Macro->getNumArgs()-1 &&
+ Macro->isVariadic()) {
+ // Remove the paste operator, report use of the extension.
+ PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
+ ResultToks.pop_back();
+ }
+
+ ResultToks.append(ArgToks, ArgToks+NumToks);
+
+ // If this token (the macro argument) was supposed to get leading
+ // whitespace, transfer this information onto the first token of the
+ // expansion.
+ //
+ // Do not do this if the paste operator occurs before the macro argument,
+ // as in "A ## MACROARG". In valid code, the first token will get
+ // smooshed onto the preceding one anyway (forming AMACROARG). In
+ // assembler-with-cpp mode, invalid pastes are allowed through: in this
+ // case, we do not want the extra whitespace to be added. For example,
+ // we want ". ## foo" -> ".foo" not ". foo".
+ if ((CurTok.hasLeadingSpace() || NextTokGetsSpace) &&
+ !PasteBefore)
+ ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace);
+
+ NextTokGetsSpace = false;
+ continue;
+ }
+
+ // If an empty argument is on the LHS or RHS of a paste, the standard (C99
+ // 6.10.3.3p2,3) calls for a bunch of placemarker stuff to occur. We
+ // implement this by eating ## operators when a LHS or RHS expands to
+ // empty.
+ NextTokGetsSpace |= CurTok.hasLeadingSpace();
+ if (PasteAfter) {
+ // Discard the argument token and skip (don't copy to the expansion
+ // buffer) the paste operator after it.
+ NextTokGetsSpace |= Tokens[i+1].hasLeadingSpace();
+ ++i;
+ continue;
+ }
+
+ // If this is on the RHS of a paste operator, we've already copied the
+ // paste operator to the ResultToks list. Remove it.
+ assert(PasteBefore && ResultToks.back().is(tok::hashhash));
+ NextTokGetsSpace |= ResultToks.back().hasLeadingSpace();
+ ResultToks.pop_back();
+
+ // If this is the __VA_ARGS__ token, and if the argument wasn't provided,
+ // and if the macro had at least one real argument, and if the token before
+ // the ## was a comma, remove the comma.
+ if ((unsigned)ArgNo == Macro->getNumArgs()-1 && // is __VA_ARGS__
+ ActualArgs->isVarargsElidedUse() && // Argument elided.
+ !ResultToks.empty() && ResultToks.back().is(tok::comma)) {
+ // Never add a space, even if the comma, ##, or arg had a space.
+ NextTokGetsSpace = false;
+ // Remove the paste operator, report use of the extension.
+ PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
+ ResultToks.pop_back();
+
+ // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"),
+ // then removal of the comma should produce a placemarker token (in C99
+ // terms) which we model by popping off the previous ##, giving us a plain
+ // "X" when __VA_ARGS__ is empty.
+ if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash))
+ ResultToks.pop_back();
+ }
+ continue;
+ }
+
+ // If anything changed, install this as the new Tokens list.
+ if (MadeChange) {
+ assert(!OwnsTokens && "This would leak if we already own the token list");
+ // This is deleted in the dtor.
+ NumTokens = ResultToks.size();
+ llvm::BumpPtrAllocator &Alloc = PP.getPreprocessorAllocator();
+ Token *Res =
+ static_cast<Token *>(Alloc.Allocate(sizeof(Token)*ResultToks.size(),
+ llvm::alignOf<Token>()));
+ if (NumTokens)
+ memcpy(Res, &ResultToks[0], NumTokens*sizeof(Token));
+ Tokens = Res;
+
+ // The preprocessor bump pointer owns these tokens, not us.
+ OwnsTokens = false;
+ }
+}
+
+/// Lex - Lex and return a token from this macro stream.
+///
+void TokenLexer::Lex(Token &Tok) {
+ // Lexing off the end of the macro, pop this macro off the expansion stack.
+ if (isAtEnd()) {
+ // If this is a macro (not a token stream), mark the macro enabled now
+ // that it is no longer being expanded.
+ if (Macro) Macro->EnableMacro();
+
+ // Pop this context off the preprocessors lexer stack and get the next
+ // token. This will delete "this" so remember the PP instance var.
+ Preprocessor &PPCache = PP;
+ if (PP.HandleEndOfTokenLexer(Tok))
+ return;
+
+ // HandleEndOfTokenLexer may not return a token. If it doesn't, lex
+ // whatever is next.
+ return PPCache.Lex(Tok);
+ }
+
+ // If this is the first token of the expanded result, we inherit spacing
+ // properties later.
+ bool isFirstToken = CurToken == 0;
+
+ // Get the next token to return.
+ Tok = Tokens[CurToken++];
+
+ bool TokenIsFromPaste = false;
+
+ // If this token is followed by a token paste (##) operator, paste the tokens!
+ if (!isAtEnd() && Tokens[CurToken].is(tok::hashhash)) {
+ // When handling the microsoft /##/ extension, the final token is
+ // returned by PasteTokens, not the pasted token.
+ if (PasteTokens(Tok))
+ return;
+
+ TokenIsFromPaste = true;
+ }
+
+ // The token's current location indicate where the token was lexed from. We
+ // need this information to compute the spelling of the token, but any
+ // diagnostics for the expanded token should appear as if they came from
+ // InstantiationLoc. Pull this information together into a new SourceLocation
+ // that captures all of this.
+ if (InstantiateLocStart.isValid()) { // Don't do this for token streams.
+ SourceManager &SM = PP.getSourceManager();
+ Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(),
+ InstantiateLocStart,
+ InstantiateLocEnd,
+ Tok.getLength()));
+ }
+
+ // If this is the first token, set the lexical properties of the token to
+ // match the lexical properties of the macro identifier.
+ if (isFirstToken) {
+ Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
+ Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+ }
+
+ // Handle recursive expansion!
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != 0) {
+ // Change the kind of this identifier to the appropriate token kind, e.g.
+ // turning "for" into a keyword.
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ Tok.setKind(II->getTokenID());
+
+ // If this identifier was poisoned and from a paste, emit an error. This
+ // won't be handled by Preprocessor::HandleIdentifier because this is coming
+ // from a macro expansion.
+ if (II->isPoisoned() && TokenIsFromPaste) {
+ // We warn about __VA_ARGS__ with poisoning.
+ if (II->isStr("__VA_ARGS__"))
+ PP.Diag(Tok, diag::ext_pp_bad_vaargs_use);
+ else
+ PP.Diag(Tok, diag::err_pp_used_poisoned_id);
+ }
+
+ if (!DisableMacroExpansion && II->isHandleIdentifierCase())
+ PP.HandleIdentifier(Tok);
+ }
+
+ // Otherwise, return a normal token.
+}
+
+/// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
+/// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
+/// are more ## after it, chomp them iteratively. Return the result as Tok.
+/// If this returns true, the caller should immediately return the token.
+bool TokenLexer::PasteTokens(Token &Tok) {
+ llvm::SmallString<128> Buffer;
+ const char *ResultTokStrPtr = 0;
+ do {
+ // Consume the ## operator.
+ SourceLocation PasteOpLoc = Tokens[CurToken].getLocation();
+ ++CurToken;
+ assert(!isAtEnd() && "No token on the RHS of a paste operator!");
+
+ // Get the RHS token.
+ const Token &RHS = Tokens[CurToken];
+
+ // Allocate space for the result token. This is guaranteed to be enough for
+ // the two tokens.
+ Buffer.resize(Tok.getLength() + RHS.getLength());
+
+ // Get the spelling of the LHS token in Buffer.
+ const char *BufPtr = &Buffer[0];
+ bool Invalid = false;
+ unsigned LHSLen = PP.getSpelling(Tok, BufPtr, &Invalid);
+ if (BufPtr != &Buffer[0]) // Really, we want the chars in Buffer!
+ memcpy(&Buffer[0], BufPtr, LHSLen);
+ if (Invalid)
+ return true;
+
+ BufPtr = &Buffer[LHSLen];
+ unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid);
+ if (Invalid)
+ return true;
+ if (BufPtr != &Buffer[LHSLen]) // Really, we want the chars in Buffer!
+ memcpy(&Buffer[LHSLen], BufPtr, RHSLen);
+
+ // Trim excess space.
+ Buffer.resize(LHSLen+RHSLen);
+
+ // Plop the pasted result (including the trailing newline and null) into a
+ // scratch buffer where we can lex it.
+ Token ResultTokTmp;
+ ResultTokTmp.startToken();
+
+ // Claim that the tmp token is a string_literal so that we can get the
+ // character pointer back from CreateString in getLiteralData().
+ ResultTokTmp.setKind(tok::string_literal);
+ PP.CreateString(&Buffer[0], Buffer.size(), ResultTokTmp);
+ SourceLocation ResultTokLoc = ResultTokTmp.getLocation();
+ ResultTokStrPtr = ResultTokTmp.getLiteralData();
+
+ // Lex the resultant pasted token into Result.
+ Token Result;
+
+ if (Tok.isAnyIdentifier() && RHS.isAnyIdentifier()) {
+ // Common paste case: identifier+identifier = identifier. Avoid creating
+ // a lexer and other overhead.
+ PP.IncrementPasteCounter(true);
+ Result.startToken();
+ Result.setKind(tok::raw_identifier);
+ Result.setRawIdentifierData(ResultTokStrPtr);
+ Result.setLocation(ResultTokLoc);
+ Result.setLength(LHSLen+RHSLen);
+ } else {
+ PP.IncrementPasteCounter(false);
+
+ assert(ResultTokLoc.isFileID() &&
+ "Should be a raw location into scratch buffer");
+ SourceManager &SourceMgr = PP.getSourceManager();
+ FileID LocFileID = SourceMgr.getFileID(ResultTokLoc);
+
+ bool Invalid = false;
+ const char *ScratchBufStart
+ = SourceMgr.getBufferData(LocFileID, &Invalid).data();
+ if (Invalid)
+ return false;
+
+ // Make a lexer to lex this string from. Lex just this one token.
+ // Make a lexer object so that we lex and expand the paste result.
+ Lexer TL(SourceMgr.getLocForStartOfFile(LocFileID),
+ PP.getLangOptions(), ScratchBufStart,
+ ResultTokStrPtr, ResultTokStrPtr+LHSLen+RHSLen);
+
+ // Lex a token in raw mode. This way it won't look up identifiers
+ // automatically, lexing off the end will return an eof token, and
+ // warnings are disabled. This returns true if the result token is the
+ // entire buffer.
+ bool isInvalid = !TL.LexFromRawLexer(Result);
+
+ // If we got an EOF token, we didn't form even ONE token. For example, we
+ // did "/ ## /" to get "//".
+ isInvalid |= Result.is(tok::eof);
+
+ // If pasting the two tokens didn't form a full new token, this is an
+ // error. This occurs with "x ## +" and other stuff. Return with Tok
+ // unmodified and with RHS as the next token to lex.
+ if (isInvalid) {
+ // Test for the Microsoft extension of /##/ turning into // here on the
+ // error path.
+ if (PP.getLangOptions().Microsoft && Tok.is(tok::slash) &&
+ RHS.is(tok::slash)) {
+ HandleMicrosoftCommentPaste(Tok);
+ return true;
+ }
+
+ // Do not emit the error when preprocessing assembler code.
+ if (!PP.getLangOptions().AsmPreprocessor) {
+ // Explicitly convert the token location to have proper instantiation
+ // information so that the user knows where it came from.
+ SourceManager &SM = PP.getSourceManager();
+ SourceLocation Loc =
+ SM.createInstantiationLoc(PasteOpLoc, InstantiateLocStart,
+ InstantiateLocEnd, 2);
+ // If we're in microsoft extensions mode, downgrade this from a hard
+ // error to a warning that defaults to an error. This allows
+ // disabling it.
+ PP.Diag(Loc,
+ PP.getLangOptions().Microsoft ? diag::err_pp_bad_paste_ms
+ : diag::err_pp_bad_paste)
+ << Buffer.str();
+ }
+
+ // Do not consume the RHS.
+ --CurToken;
+ }
+
+ // Turn ## into 'unknown' to avoid # ## # from looking like a paste
+ // operator.
+ if (Result.is(tok::hashhash))
+ Result.setKind(tok::unknown);
+ }
+
+ // Transfer properties of the LHS over the the Result.
+ Result.setFlagValue(Token::StartOfLine , Tok.isAtStartOfLine());
+ Result.setFlagValue(Token::LeadingSpace, Tok.hasLeadingSpace());
+
+ // Finally, replace LHS with the result, consume the RHS, and iterate.
+ ++CurToken;
+ Tok = Result;
+ } while (!isAtEnd() && Tokens[CurToken].is(tok::hashhash));
+
+ // Now that we got the result token, it will be subject to expansion. Since
+ // token pasting re-lexes the result token in raw mode, identifier information
+ // isn't looked up. As such, if the result is an identifier, look up id info.
+ if (Tok.is(tok::raw_identifier)) {
+ // Look up the identifier info for the token. We disabled identifier lookup
+ // by saying we're skipping contents, so we need to do this manually.
+ PP.LookUpIdentifierInfo(Tok);
+ }
+ return false;
+}
+
+/// isNextTokenLParen - If the next token lexed will pop this macro off the
+/// expansion stack, return 2. If the next unexpanded token is a '(', return
+/// 1, otherwise return 0.
+unsigned TokenLexer::isNextTokenLParen() const {
+ // Out of tokens?
+ if (isAtEnd())
+ return 2;
+ return Tokens[CurToken].is(tok::l_paren);
+}
+
+
+/// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
+/// together to form a comment that comments out everything in the current
+/// macro, other active macros, and anything left on the current physical
+/// source line of the instantiated buffer. Handle this by returning the
+/// first token on the next line.
+void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok) {
+ // We 'comment out' the rest of this macro by just ignoring the rest of the
+ // tokens that have not been lexed yet, if any.
+
+ // Since this must be a macro, mark the macro enabled now that it is no longer
+ // being expanded.
+ assert(Macro && "Token streams can't paste comments");
+ Macro->EnableMacro();
+
+ PP.HandleMicrosoftCommentPaste(Tok);
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
new file mode 100644
index 0000000..edb1675
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
@@ -0,0 +1,90 @@
+//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the clang::ParseAST method.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Parser.h"
+#include <cstdio>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Public interface to the file
+//===----------------------------------------------------------------------===//
+
+/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
+/// the file is parsed. This inserts the parsed decls into the translation unit
+/// held by Ctx.
+///
+void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
+ ASTContext &Ctx, bool PrintStats,
+ bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer) {
+ Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
+ ParseAST(S, PrintStats);
+}
+
+void clang::ParseAST(Sema &S, bool PrintStats) {
+ // Collect global stats on Decls/Stmts (until we have a module streamer).
+ if (PrintStats) {
+ Decl::CollectingStats(true);
+ Stmt::CollectingStats(true);
+ }
+
+ ASTConsumer *Consumer = &S.getASTConsumer();
+
+ Parser P(S.getPreprocessor(), S);
+ S.getPreprocessor().EnterMainSourceFile();
+ P.Initialize();
+ S.Initialize();
+
+ if (ExternalASTSource *External = S.getASTContext().getExternalSource())
+ External->StartTranslationUnit(Consumer);
+
+ Parser::DeclGroupPtrTy ADecl;
+
+ while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl)
+ Consumer->HandleTopLevelDecl(ADecl.get());
+ };
+ // Check for any pending objective-c implementation decl.
+ while ((ADecl = P.FinishPendingObjCActions()))
+ Consumer->HandleTopLevelDecl(ADecl.get());
+
+ // Process any TopLevelDecls generated by #pragma weak.
+ for (llvm::SmallVector<Decl*,2>::iterator
+ I = S.WeakTopLevelDecls().begin(),
+ E = S.WeakTopLevelDecls().end(); I != E; ++I)
+ Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
+
+ Consumer->HandleTranslationUnit(S.getASTContext());
+
+ if (PrintStats) {
+ fprintf(stderr, "\nSTATISTICS:\n");
+ P.getActions().PrintStats();
+ S.getASTContext().PrintStats();
+ Decl::PrintStats();
+ Stmt::PrintStats();
+ Consumer->PrintStats();
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
new file mode 100644
index 0000000..3994738
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -0,0 +1,388 @@
+//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements parsing for C++ class inline methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+using namespace clang;
+
+/// ParseCXXInlineMethodDef - We parsed and verified that the specified
+/// Declarator is a well formed C++ inline method definition. Now lex its body
+/// and store its tokens for parsing after the C++ class is complete.
+Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers& VS) {
+ assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
+ assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
+ "Current token not a '{', ':' or 'try'!");
+
+ MultiTemplateParamsArg TemplateParams(Actions,
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
+
+ Decl *FnD;
+ if (D.getDeclSpec().isFriendSpecified())
+ // FIXME: Friend templates
+ FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true,
+ move(TemplateParams));
+ else { // FIXME: pass template information through
+ if (VS.isOverrideSpecified())
+ Diag(VS.getOverrideLoc(), diag::ext_override_inline) << "override";
+ if (VS.isFinalSpecified())
+ Diag(VS.getFinalLoc(), diag::ext_override_inline) << "final";
+ if (VS.isNewSpecified())
+ Diag(VS.getNewLoc(), diag::ext_override_inline) << "new";
+
+ FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
+ move(TemplateParams), 0,
+ VS, 0, /*IsDefinition*/true);
+ }
+
+ HandleMemberFunctionDefaultArgs(D, FnD);
+
+ D.complete(FnD);
+
+ // Consume the tokens and store them for later parsing.
+
+ LexedMethod* LM = new LexedMethod(this, FnD);
+ getCurrentClass().LateParsedDeclarations.push_back(LM);
+ LM->TemplateScope = getCurScope()->isTemplateParamScope();
+ CachedTokens &Toks = LM->Toks;
+
+ tok::TokenKind kind = Tok.getKind();
+ // We may have a constructor initializer or function-try-block here.
+ if (kind == tok::colon || kind == tok::kw_try) {
+ // Consume everything up to (and including) the left brace.
+ if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) {
+ // We didn't find the left-brace we expected after the
+ // constructor initializer.
+ if (Tok.is(tok::semi)) {
+ // We found a semicolon; complain, consume the semicolon, and
+ // don't try to parse this method later.
+ Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ ConsumeAnyToken();
+ delete getCurrentClass().LateParsedDeclarations.back();
+ getCurrentClass().LateParsedDeclarations.pop_back();
+ return FnD;
+ }
+ }
+
+ } else {
+ // Begin by storing the '{' token.
+ Toks.push_back(Tok);
+ ConsumeBrace();
+ }
+ // Consume everything up to (and including) the matching right brace.
+ ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
+
+ // If we're in a function-try-block, we need to store all the catch blocks.
+ if (kind == tok::kw_try) {
+ while (Tok.is(tok::kw_catch)) {
+ ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
+ ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
+ }
+ }
+
+ return FnD;
+}
+
+Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
+void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
+void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
+
+Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
+ : Self(P), Class(C) {}
+
+Parser::LateParsedClass::~LateParsedClass() {
+ Self->DeallocateParsedClasses(Class);
+}
+
+void Parser::LateParsedClass::ParseLexedMethodDeclarations() {
+ Self->ParseLexedMethodDeclarations(*Class);
+}
+
+void Parser::LateParsedClass::ParseLexedMethodDefs() {
+ Self->ParseLexedMethodDefs(*Class);
+}
+
+void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {
+ Self->ParseLexedMethodDeclaration(*this);
+}
+
+void Parser::LexedMethod::ParseLexedMethodDefs() {
+ Self->ParseLexedMethodDef(*this);
+}
+
+/// ParseLexedMethodDeclarations - We finished parsing the member
+/// specification of a top (non-nested) C++ class. Now go over the
+/// stack of method declarations with some parts for which parsing was
+/// delayed (such as default arguments) and parse them.
+void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
+ bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+ ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+ if (HasTemplateScope)
+ Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+
+ // The current scope is still active if we're the top-level class.
+ // Otherwise we'll need to push and enter a new scope.
+ bool HasClassScope = !Class.TopLevelClass;
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
+ HasClassScope);
+ if (HasClassScope)
+ Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+
+ for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+ Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
+ }
+
+ if (HasClassScope)
+ Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
+}
+
+void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
+ // If this is a member template, introduce the template parameter scope.
+ ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+ if (LM.TemplateScope)
+ Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
+
+ // Start the delayed C++ method declaration
+ Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
+
+ // Introduce the parameters into scope and parse their default
+ // arguments.
+ ParseScope PrototypeScope(this,
+ Scope::FunctionPrototypeScope|Scope::DeclScope);
+ for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
+ // Introduce the parameter into scope.
+ Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param);
+
+ if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+ // Save the current token position.
+ SourceLocation origLoc = Tok.getLocation();
+
+ // Parse the default argument from its saved token stream.
+ Toks->push_back(Tok); // So that the current token doesn't get lost
+ PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
+
+ // Consume the previously-pushed token.
+ ConsumeAnyToken();
+
+ // Consume the '='.
+ assert(Tok.is(tok::equal) && "Default argument not starting with '='");
+ SourceLocation EqualLoc = ConsumeToken();
+
+ // The argument isn't actually potentially evaluated unless it is
+ // used.
+ EnterExpressionEvaluationContext Eval(Actions,
+ Sema::PotentiallyEvaluatedIfUsed);
+
+ ExprResult DefArgResult(ParseAssignmentExpression());
+ if (DefArgResult.isInvalid())
+ Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
+ else {
+ if (Tok.is(tok::cxx_defaultarg_end))
+ ConsumeToken();
+ else
+ Diag(Tok.getLocation(), diag::err_default_arg_unparsed);
+ Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
+ DefArgResult.take());
+ }
+
+ assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+ Tok.getLocation()) &&
+ "ParseAssignmentExpression went over the default arg tokens!");
+ // There could be leftover tokens (e.g. because of an error).
+ // Skip through until we reach the original token position.
+ while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+
+ delete Toks;
+ LM.DefaultArgs[I].Toks = 0;
+ }
+ }
+ PrototypeScope.Exit();
+
+ // Finish the delayed C++ method declaration.
+ Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
+}
+
+/// ParseLexedMethodDefs - We finished parsing the member specification of a top
+/// (non-nested) C++ class. Now go over the stack of lexed methods that were
+/// collected during its parsing and parse them all.
+void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
+ bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+ ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
+ if (HasTemplateScope)
+ Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+
+ bool HasClassScope = !Class.TopLevelClass;
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
+ HasClassScope);
+
+ for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+ Class.LateParsedDeclarations[i]->ParseLexedMethodDefs();
+ }
+}
+
+void Parser::ParseLexedMethodDef(LexedMethod &LM) {
+ // If this is a member template, introduce the template parameter scope.
+ ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+ if (LM.TemplateScope)
+ Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
+
+ // Save the current token position.
+ SourceLocation origLoc = Tok.getLocation();
+
+ assert(!LM.Toks.empty() && "Empty body!");
+ // Append the current token at the end of the new token stream so that it
+ // doesn't get lost.
+ LM.Toks.push_back(Tok);
+ PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
+
+ // Consume the previously pushed token.
+ ConsumeAnyToken();
+ assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+ && "Inline method not starting with '{', ':' or 'try'");
+
+ // Parse the method body. Function body parsing code is similar enough
+ // to be re-used for method bodies as well.
+ ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+ Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
+
+ if (Tok.is(tok::kw_try)) {
+ ParseFunctionTryBlock(LM.D);
+ assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+ Tok.getLocation()) &&
+ "ParseFunctionTryBlock went over the cached tokens!");
+ // There could be leftover tokens (e.g. because of an error).
+ // Skip through until we reach the original token position.
+ while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+ return;
+ }
+ if (Tok.is(tok::colon)) {
+ ParseConstructorInitializer(LM.D);
+
+ // Error recovery.
+ if (!Tok.is(tok::l_brace)) {
+ Actions.ActOnFinishFunctionBody(LM.D, 0);
+ return;
+ }
+ } else
+ Actions.ActOnDefaultCtorInitializers(LM.D);
+
+ ParseFunctionStatementBody(LM.D);
+
+ if (Tok.getLocation() != origLoc) {
+ // Due to parsing error, we either went over the cached tokens or
+ // there are still cached tokens left. If it's the latter case skip the
+ // leftover tokens.
+ // Since this is an uncommon situation that should be avoided, use the
+ // expensive isBeforeInTranslationUnit call.
+ if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
+ origLoc))
+ while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+
+ }
+}
+
+/// ConsumeAndStoreUntil - Consume and store the token at the passed token
+/// container until the token 'T' is reached (which gets
+/// consumed/stored too, if ConsumeFinalToken).
+/// If StopAtSemi is true, then we will stop early at a ';' character.
+/// Returns true if token 'T1' or 'T2' was found.
+/// NOTE: This is a specialized version of Parser::SkipUntil.
+bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+ CachedTokens &Toks,
+ bool StopAtSemi, bool ConsumeFinalToken) {
+ // We always want this function to consume at least one token if the first
+ // token isn't T and if not at EOF.
+ bool isFirstTokenConsumed = true;
+ while (1) {
+ // If we found one of the tokens, stop and return true.
+ if (Tok.is(T1) || Tok.is(T2)) {
+ if (ConsumeFinalToken) {
+ Toks.push_back(Tok);
+ ConsumeAnyToken();
+ }
+ return true;
+ }
+
+ switch (Tok.getKind()) {
+ case tok::eof:
+ // Ran out of tokens.
+ return false;
+
+ case tok::l_paren:
+ // Recursively consume properly-nested parens.
+ Toks.push_back(Tok);
+ ConsumeParen();
+ ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
+ break;
+ case tok::l_square:
+ // Recursively consume properly-nested square brackets.
+ Toks.push_back(Tok);
+ ConsumeBracket();
+ ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
+ break;
+ case tok::l_brace:
+ // Recursively consume properly-nested braces.
+ Toks.push_back(Tok);
+ ConsumeBrace();
+ ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
+ break;
+
+ // Okay, we found a ']' or '}' or ')', which we think should be balanced.
+ // Since the user wasn't looking for this token (if they were, it would
+ // already be handled), this isn't balanced. If there is a LHS token at a
+ // higher level, we will assume that this matches the unbalanced token
+ // and return it. Otherwise, this is a spurious RHS token, which we skip.
+ case tok::r_paren:
+ if (ParenCount && !isFirstTokenConsumed)
+ return false; // Matches something.
+ Toks.push_back(Tok);
+ ConsumeParen();
+ break;
+ case tok::r_square:
+ if (BracketCount && !isFirstTokenConsumed)
+ return false; // Matches something.
+ Toks.push_back(Tok);
+ ConsumeBracket();
+ break;
+ case tok::r_brace:
+ if (BraceCount && !isFirstTokenConsumed)
+ return false; // Matches something.
+ Toks.push_back(Tok);
+ ConsumeBrace();
+ break;
+
+ case tok::string_literal:
+ case tok::wide_string_literal:
+ Toks.push_back(Tok);
+ ConsumeStringToken();
+ break;
+ case tok::semi:
+ if (StopAtSemi)
+ return false;
+ // FALL THROUGH.
+ default:
+ // consume this token.
+ Toks.push_back(Tok);
+ ConsumeToken();
+ break;
+ }
+ isFirstTokenConsumed = false;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
new file mode 100644
index 0000000..5a7fc7e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -0,0 +1,3733 @@
+//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Declaration portions of the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "RAIIObjectsForParser.h"
+#include "llvm/ADT/SmallSet.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// C99 6.7: Declarations.
+//===----------------------------------------------------------------------===//
+
+/// ParseTypeName
+/// type-name: [C99 6.7.6]
+/// specifier-qualifier-list abstract-declarator[opt]
+///
+/// Called type-id in C++.
+TypeResult Parser::ParseTypeName(SourceRange *Range,
+ Declarator::TheContext Context) {
+ // Parse the common declaration-specifiers piece.
+ DeclSpec DS;
+ ParseSpecifierQualifierList(DS);
+
+ // Parse the abstract-declarator, if present.
+ Declarator DeclaratorInfo(DS, Context);
+ ParseDeclarator(DeclaratorInfo);
+ if (Range)
+ *Range = DeclaratorInfo.getSourceRange();
+
+ if (DeclaratorInfo.isInvalidType())
+ return true;
+
+ return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+}
+
+/// ParseGNUAttributes - Parse a non-empty attributes list.
+///
+/// [GNU] attributes:
+/// attribute
+/// attributes attribute
+///
+/// [GNU] attribute:
+/// '__attribute__' '(' '(' attribute-list ')' ')'
+///
+/// [GNU] attribute-list:
+/// attrib
+/// attribute_list ',' attrib
+///
+/// [GNU] attrib:
+/// empty
+/// attrib-name
+/// attrib-name '(' identifier ')'
+/// attrib-name '(' identifier ',' nonempty-expr-list ')'
+/// attrib-name '(' argument-expression-list [C99 6.5.2] ')'
+///
+/// [GNU] attrib-name:
+/// identifier
+/// typespec
+/// typequal
+/// storageclass
+///
+/// FIXME: The GCC grammar/code for this construct implies we need two
+/// token lookahead. Comment from gcc: "If they start with an identifier
+/// which is followed by a comma or close parenthesis, then the arguments
+/// start with that identifier; otherwise they are an expression list."
+///
+/// At the moment, I am not doing 2 token lookahead. I am also unaware of
+/// any attributes that don't work (based on my limited testing). Most
+/// attributes are very simple in practice. Until we find a bug, I don't see
+/// a pressing need to implement the 2 token lookahead.
+
+void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
+ assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
+
+ while (Tok.is(tok::kw___attribute)) {
+ ConsumeToken();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "attribute")) {
+ SkipUntil(tok::r_paren, true); // skip until ) or ;
+ return;
+ }
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
+ SkipUntil(tok::r_paren, true); // skip until ) or ;
+ return;
+ }
+ // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
+ while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
+ Tok.is(tok::comma)) {
+
+ if (Tok.is(tok::comma)) {
+ // allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
+ ConsumeToken();
+ continue;
+ }
+ // we have an identifier or declaration specifier (const, int, etc.)
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+
+ // check if we have a "parameterized" attribute
+ if (Tok.is(tok::l_paren)) {
+ ConsumeParen(); // ignore the left paren loc for now
+
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *ParmName = Tok.getIdentifierInfo();
+ SourceLocation ParmLoc = ConsumeToken();
+
+ if (Tok.is(tok::r_paren)) {
+ // __attribute__(( mode(byte) ))
+ ConsumeParen(); // ignore the right paren loc for now
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ ParmName, ParmLoc, 0, 0));
+ } else if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ // __attribute__(( format(printf, 1, 2) ))
+ ExprVector ArgExprs(Actions);
+ bool ArgExprsOk = true;
+
+ // now parse the non-empty comma separated list of expressions
+ while (1) {
+ ExprResult ArgExpr(ParseAssignmentExpression());
+ if (ArgExpr.isInvalid()) {
+ ArgExprsOk = false;
+ SkipUntil(tok::r_paren);
+ break;
+ } else {
+ ArgExprs.push_back(ArgExpr.release());
+ }
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // Eat the comma, move to the next argument
+ }
+ if (ArgExprsOk && Tok.is(tok::r_paren)) {
+ ConsumeParen(); // ignore the right paren loc for now
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, ParmName, ParmLoc,
+ ArgExprs.take(), ArgExprs.size()));
+ }
+ }
+ } else { // not an identifier
+ switch (Tok.getKind()) {
+ case tok::r_paren:
+ // parse a possibly empty comma separated list of expressions
+ // __attribute__(( nonnull() ))
+ ConsumeParen(); // ignore the right paren loc for now
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
+ break;
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_bool:
+ case tok::kw_short:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_void:
+ case tok::kw_typeof: {
+ AttributeList *attr
+ = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0);
+ attrs.add(attr);
+ if (attr->getKind() == AttributeList::AT_IBOutletCollection)
+ Diag(Tok, diag::err_iboutletcollection_builtintype);
+ // If it's a builtin type name, eat it and expect a rparen
+ // __attribute__(( vec_type_hint(char) ))
+ ConsumeToken();
+ if (Tok.is(tok::r_paren))
+ ConsumeParen();
+ break;
+ }
+ default:
+ // __attribute__(( aligned(16) ))
+ ExprVector ArgExprs(Actions);
+ bool ArgExprsOk = true;
+
+ // now parse the list of expressions
+ while (1) {
+ ExprResult ArgExpr(ParseAssignmentExpression());
+ if (ArgExpr.isInvalid()) {
+ ArgExprsOk = false;
+ SkipUntil(tok::r_paren);
+ break;
+ } else {
+ ArgExprs.push_back(ArgExpr.release());
+ }
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // Eat the comma, move to the next argument
+ }
+ // Match the ')'.
+ if (ArgExprsOk && Tok.is(tok::r_paren)) {
+ ConsumeParen(); // ignore the right paren loc for now
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0,
+ AttrNameLoc, 0, SourceLocation(),
+ ArgExprs.take(), ArgExprs.size()));
+ }
+ break;
+ }
+ }
+ } else {
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0));
+ }
+ }
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ SkipUntil(tok::r_paren, false);
+ SourceLocation Loc = Tok.getLocation();
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
+ SkipUntil(tok::r_paren, false);
+ }
+ if (endLoc)
+ *endLoc = Loc;
+ }
+}
+
+/// ParseMicrosoftDeclSpec - Parse an __declspec construct
+///
+/// [MS] decl-specifier:
+/// __declspec ( extended-decl-modifier-seq )
+///
+/// [MS] extended-decl-modifier-seq:
+/// extended-decl-modifier[opt]
+/// extended-decl-modifier extended-decl-modifier-seq
+
+void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) {
+ assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
+
+ ConsumeToken();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "declspec")) {
+ SkipUntil(tok::r_paren, true); // skip until ) or ;
+ return;
+ }
+ while (Tok.getIdentifierInfo()) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ if (Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ // FIXME: This doesn't parse __declspec(property(get=get_func_name))
+ // correctly.
+ ExprResult ArgExpr(ParseAssignmentExpression());
+ if (!ArgExpr.isInvalid()) {
+ Expr *ExprList = ArgExpr.take();
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), &ExprList, 1, true));
+ }
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ SkipUntil(tok::r_paren, false);
+ } else {
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0, true));
+ }
+ }
+ if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ SkipUntil(tok::r_paren, false);
+ return;
+}
+
+void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
+ // Treat these like attributes
+ // FIXME: Allow Sema to distinguish between these and real attributes!
+ while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
+ Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) ||
+ Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
+ // FIXME: Support these properly!
+ continue;
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
+ }
+}
+
+void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
+ // Treat these like attributes
+ while (Tok.is(tok::kw___pascal)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, true));
+ }
+}
+
+void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) {
+ // Treat these like attributes
+ while (Tok.is(tok::kw___kernel)) {
+ SourceLocation AttrNameLoc = ConsumeToken();
+ attrs.add(AttrFactory.Create(PP.getIdentifierInfo("opencl_kernel_function"),
+ AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, false));
+ }
+}
+
+void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
+ Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << attrs.Range;
+}
+
+/// ParseDeclaration - Parse a full 'declaration', which consists of
+/// declaration-specifiers, some number of declarators, and a semicolon.
+/// 'Context' should be a Declarator::TheContext value. This returns the
+/// location of the semicolon in DeclEnd.
+///
+/// declaration: [C99 6.7]
+/// block-declaration ->
+/// simple-declaration
+/// others [FIXME]
+/// [C++] template-declaration
+/// [C++] namespace-definition
+/// [C++] using-directive
+/// [C++] using-declaration
+/// [C++0x] static_assert-declaration
+/// others... [FIXME]
+///
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
+ unsigned Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
+ Decl *SingleDecl = 0;
+ switch (Tok.getKind()) {
+ case tok::kw_template:
+ case tok::kw_export:
+ ProhibitAttributes(attrs);
+ SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
+ break;
+ case tok::kw_inline:
+ // Could be the start of an inline namespace. Allowed as an ext in C++03.
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
+ ProhibitAttributes(attrs);
+ SourceLocation InlineLoc = ConsumeToken();
+ SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
+ break;
+ }
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs,
+ true);
+ case tok::kw_namespace:
+ ProhibitAttributes(attrs);
+ SingleDecl = ParseNamespace(Context, DeclEnd);
+ break;
+ case tok::kw_using:
+ SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
+ DeclEnd, attrs);
+ break;
+ case tok::kw_static_assert:
+ ProhibitAttributes(attrs);
+ SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
+ break;
+ default:
+ return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, true);
+ }
+
+ // This routine returns a DeclGroup, if the thing we parsed only contains a
+ // single decl, convert it now.
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
+}
+
+/// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
+/// declaration-specifiers init-declarator-list[opt] ';'
+///[C90/C++]init-declarator-list ';' [TODO]
+/// [OMP] threadprivate-directive [TODO]
+///
+/// If RequireSemi is false, this does not check for a ';' at the end of the
+/// declaration. If it is true, it checks for and eats it.
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts,
+ unsigned Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs,
+ bool RequireSemi) {
+ // Parse the common declaration-specifiers piece.
+ ParsingDeclSpec DS(*this);
+ DS.takeAttributesFrom(attrs);
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
+ getDeclSpecContextFromDeclaratorContext(Context));
+ StmtResult R = Actions.ActOnVlaStmt(DS);
+ if (R.isUsable())
+ Stmts.push_back(R.release());
+
+ // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+ // declaration-specifiers init-declarator-list[opt] ';'
+ if (Tok.is(tok::semi)) {
+ if (RequireSemi) ConsumeToken();
+ Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
+ DS);
+ DS.complete(TheDecl);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
+
+ return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd);
+}
+
+/// ParseDeclGroup - Having concluded that this is either a function
+/// definition or a group of object declarations, actually parse the
+/// result.
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
+ unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd) {
+ // Parse the first declarator.
+ ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
+ ParseDeclarator(D);
+
+ // Bail out if the first declarator didn't seem well-formed.
+ if (!D.hasName() && !D.mayOmitIdentifier()) {
+ // Skip until ; or }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
+
+ // Check to see if we have a function *definition* which must have a body.
+ if (AllowFunctionDefinitions && D.isFunctionDeclarator() &&
+ // Look at the next token to make sure that this isn't a function
+ // declaration. We have to check this because __attribute__ might be the
+ // start of a function definition in GCC-extended K&R C.
+ !isDeclarationAfterDeclarator()) {
+
+ if (isStartOfFunctionDefinition(D)) {
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
+
+ // Recover by treating the 'typedef' as spurious.
+ DS.ClearStorageClassSpecs();
+ }
+
+ Decl *TheDecl = ParseFunctionDefinition(D);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
+
+ if (isDeclarationSpecifier()) {
+ // If there is an invalid declaration specifier right after the function
+ // prototype, then we must be in a missing semicolon case where this isn't
+ // actually a body. Just fall through into the code that handles it as a
+ // prototype, and let the top-level code handle the erroneous declspec
+ // where it would otherwise expect a comma or semicolon.
+ } else {
+ Diag(Tok, diag::err_expected_fn_body);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
+ }
+ }
+
+ llvm::SmallVector<Decl *, 8> DeclsInGroup;
+ Decl *FirstDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(FirstDecl);
+ if (FirstDecl)
+ DeclsInGroup.push_back(FirstDecl);
+
+ // If we don't have a comma, it is either the end of the list (a ';') or an
+ // error, bail out.
+ while (Tok.is(tok::comma)) {
+ // Consume the comma.
+ ConsumeToken();
+
+ // Parse the next declarator.
+ D.clear();
+
+ // Accept attributes in an init-declarator. In the first declarator in a
+ // declaration, these would be part of the declspec. In subsequent
+ // declarators, they become part of the declarator itself, so that they
+ // don't apply to declarators after *this* one. Examples:
+ // short __attribute__((common)) var; -> declspec
+ // short var __attribute__((common)); -> declarator
+ // short x, __attribute__((common)) var; -> declarator
+ MaybeParseGNUAttributes(D);
+
+ ParseDeclarator(D);
+
+ Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
+ D.complete(ThisDecl);
+ if (ThisDecl)
+ DeclsInGroup.push_back(ThisDecl);
+ }
+
+ if (DeclEnd)
+ *DeclEnd = Tok.getLocation();
+
+ if (Context != Declarator::ForContext &&
+ ExpectAndConsume(tok::semi,
+ Context == Declarator::FileContext
+ ? diag::err_invalid_token_after_toplevel_declarator
+ : diag::err_expected_semi_declaration)) {
+ // Okay, there was no semicolon and one was expected. If we see a
+ // declaration specifier, just assume it was missing and continue parsing.
+ // Otherwise things are very confused and we skip to recover.
+ if (!isDeclarationSpecifier()) {
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+ }
+
+ return Actions.FinalizeDeclaratorGroup(getCurScope(), DS,
+ DeclsInGroup.data(),
+ DeclsInGroup.size());
+}
+
+/// \brief Parse 'declaration' after parsing 'declaration-specifiers
+/// declarator'. This method parses the remainder of the declaration
+/// (including any attributes or initializer, among other things) and
+/// finalizes the declaration.
+///
+/// init-declarator: [C99 6.7]
+/// declarator
+/// declarator '=' initializer
+/// [GNU] declarator simple-asm-expr[opt] attributes[opt]
+/// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
+/// [C++] declarator initializer[opt]
+///
+/// [C++] initializer:
+/// [C++] '=' initializer-clause
+/// [C++] '(' expression-list ')'
+/// [C++0x] '=' 'default' [TODO]
+/// [C++0x] '=' 'delete'
+///
+/// According to the standard grammar, =default and =delete are function
+/// definitions, but that definitely doesn't fit with the parser here.
+///
+Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo) {
+ // If a simple-asm-expr is present, parse it.
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid()) {
+ SkipUntil(tok::semi, true, true);
+ return 0;
+ }
+
+ D.setAsmLabel(AsmLabel.release());
+ D.SetRangeEnd(Loc);
+ }
+
+ MaybeParseGNUAttributes(D);
+
+ // Inform the current actions module that we just parsed this declarator.
+ Decl *ThisDecl = 0;
+ switch (TemplateInfo.Kind) {
+ case ParsedTemplateInfo::NonTemplate:
+ ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
+ break;
+
+ case ParsedTemplateInfo::Template:
+ case ParsedTemplateInfo::ExplicitSpecialization:
+ ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
+ MultiTemplateParamsArg(Actions,
+ TemplateInfo.TemplateParams->data(),
+ TemplateInfo.TemplateParams->size()),
+ D);
+ break;
+
+ case ParsedTemplateInfo::ExplicitInstantiation: {
+ DeclResult ThisRes
+ = Actions.ActOnExplicitInstantiation(getCurScope(),
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
+ D);
+ if (ThisRes.isInvalid()) {
+ SkipUntil(tok::semi, true, true);
+ return 0;
+ }
+
+ ThisDecl = ThisRes.get();
+ break;
+ }
+ }
+
+ bool TypeContainsAuto =
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
+ // Parse declarator '=' initializer.
+ if (isTokenEqualOrMistypedEqualEqual(
+ diag::err_invalid_equalequal_after_declarator)) {
+ ConsumeToken();
+ if (Tok.is(tok::kw_delete)) {
+ SourceLocation DelLoc = ConsumeToken();
+
+ if (!getLang().CPlusPlus0x)
+ Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension);
+
+ Actions.SetDeclDeleted(ThisDecl, DelLoc);
+ } else {
+ if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+ EnterScope(0);
+ Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+ }
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::comma, true, true);
+ return ThisDecl;
+ }
+
+ ExprResult Init(ParseInitializer());
+
+ if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+ Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+ ExitScope();
+ }
+
+ if (Init.isInvalid()) {
+ SkipUntil(tok::comma, true, true);
+ Actions.ActOnInitializerError(ThisDecl);
+ } else
+ Actions.AddInitializerToDecl(ThisDecl, Init.take(),
+ /*DirectInit=*/false, TypeContainsAuto);
+ }
+ } else if (Tok.is(tok::l_paren)) {
+ // Parse C++ direct initializer: '(' expression-list ')'
+ SourceLocation LParenLoc = ConsumeParen();
+ ExprVector Exprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+ EnterScope(0);
+ Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+ }
+
+ if (ParseExpressionList(Exprs, CommaLocs)) {
+ SkipUntil(tok::r_paren);
+
+ if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+ Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+ ExitScope();
+ }
+ } else {
+ // Match the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
+ "Unexpected number of commas!");
+
+ if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+ Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+ ExitScope();
+ }
+
+ Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
+ move_arg(Exprs),
+ RParenLoc,
+ TypeContainsAuto);
+ }
+ } else {
+ Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
+ }
+
+ return ThisDecl;
+}
+
+/// ParseSpecifierQualifierList
+/// specifier-qualifier-list:
+/// type-specifier specifier-qualifier-list[opt]
+/// type-qualifier specifier-qualifier-list[opt]
+/// [GNU] attributes specifier-qualifier-list[opt]
+///
+void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
+ /// specifier-qualifier-list is a subset of declaration-specifiers. Just
+ /// parse declaration-specifiers and complain about extra stuff.
+ ParseDeclarationSpecifiers(DS);
+
+ // Validate declspec for type-name.
+ unsigned Specs = DS.getParsedSpecifiers();
+ if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
+ !DS.hasAttributes())
+ Diag(Tok, diag::err_typename_requires_specqual);
+
+ // Issue diagnostic and remove storage class if present.
+ if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
+ if (DS.getStorageClassSpecLoc().isValid())
+ Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
+ else
+ Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass);
+ DS.ClearStorageClassSpecs();
+ }
+
+ // Issue diagnostic and remove function specfier if present.
+ if (Specs & DeclSpec::PQ_FunctionSpecifier) {
+ if (DS.isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+ if (DS.isVirtualSpecified())
+ Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
+ DS.ClearFunctionSpecs();
+ }
+}
+
+/// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
+/// specified token is valid after the identifier in a declarator which
+/// immediately follows the declspec. For example, these things are valid:
+///
+/// int x [ 4]; // direct-declarator
+/// int x ( int y); // direct-declarator
+/// int(int x ) // direct-declarator
+/// int x ; // simple-declaration
+/// int x = 17; // init-declarator-list
+/// int x , y; // init-declarator-list
+/// int x __asm__ ("foo"); // init-declarator-list
+/// int x : 4; // struct-declarator
+/// int x { 5}; // C++'0x unified initializers
+///
+/// This is not, because 'x' does not immediately follow the declspec (though
+/// ')' happens to be valid anyway).
+/// int (x)
+///
+static bool isValidAfterIdentifierInDeclarator(const Token &T) {
+ return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) ||
+ T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) ||
+ T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon);
+}
+
+
+/// ParseImplicitInt - This method is called when we have an non-typename
+/// identifier in a declspec (which normally terminates the decl spec) when
+/// the declspec has no type specifier. In this case, the declspec is either
+/// malformed or is "implicit int" (in K&R and C89).
+///
+/// This method handles diagnosing this prettily and returns false if the
+/// declspec is done being processed. If it recovers and thinks there may be
+/// other pieces of declspec after it, it returns true.
+///
+bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS) {
+ assert(Tok.is(tok::identifier) && "should have identifier");
+
+ SourceLocation Loc = Tok.getLocation();
+ // If we see an identifier that is not a type name, we normally would
+ // parse it as the identifer being declared. However, when a typename
+ // is typo'd or the definition is not included, this will incorrectly
+ // parse the typename as the identifier name and fall over misparsing
+ // later parts of the diagnostic.
+ //
+ // As such, we try to do some look-ahead in cases where this would
+ // otherwise be an "implicit-int" case to see if this is invalid. For
+ // example: "static foo_t x = 4;" In this case, if we parsed foo_t as
+ // an identifier with implicit int, we'd get a parse error because the
+ // next token is obviously invalid for a type. Parse these as a case
+ // with an invalid type specifier.
+ assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
+
+ // Since we know that this either implicit int (which is rare) or an
+ // error, we'd do lookahead to try to do better recovery.
+ if (isValidAfterIdentifierInDeclarator(NextToken())) {
+ // If this token is valid for implicit int, e.g. "static x = 4", then
+ // we just avoid eating the identifier, so it will be parsed as the
+ // identifier in the declarator.
+ return false;
+ }
+
+ // Otherwise, if we don't consume this token, we are going to emit an
+ // error anyway. Try to recover from various common problems. Check
+ // to see if this was a reference to a tag name without a tag specified.
+ // This is a common problem in C (saying 'foo' instead of 'struct foo').
+ //
+ // C++ doesn't need this, and isTagName doesn't take SS.
+ if (SS == 0) {
+ const char *TagName = 0;
+ tok::TokenKind TagKind = tok::unknown;
+
+ switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
+ default: break;
+ case DeclSpec::TST_enum: TagName="enum" ;TagKind=tok::kw_enum ;break;
+ case DeclSpec::TST_union: TagName="union" ;TagKind=tok::kw_union ;break;
+ case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break;
+ case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break;
+ }
+
+ if (TagName) {
+ Diag(Loc, diag::err_use_of_tag_name_without_tag)
+ << Tok.getIdentifierInfo() << TagName << getLang().CPlusPlus
+ << FixItHint::CreateInsertion(Tok.getLocation(),TagName);
+
+ // Parse this as a tag as if the missing tag were present.
+ if (TagKind == tok::kw_enum)
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
+ else
+ ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
+ return true;
+ }
+ }
+
+ // This is almost certainly an invalid type name. Let the action emit a
+ // diagnostic and attempt to recover.
+ ParsedType T;
+ if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
+ getCurScope(), SS, T)) {
+ // The action emitted a diagnostic, so we don't have to.
+ if (T) {
+ // The action has suggested that the type T could be used. Set that as
+ // the type in the declaration specifiers, consume the would-be type
+ // name token, and we're done.
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T);
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+
+ // There may be other declaration specifiers after this.
+ return true;
+ }
+
+ // Fall through; the action had no suggestion for us.
+ } else {
+ // The action did not emit a diagnostic, so emit one now.
+ SourceRange R;
+ if (SS) R = SS->getRange();
+ Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+ }
+
+ // Mark this as an error.
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID);
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+
+ // TODO: Could inject an invalid typedef decl in an enclosing scope to
+ // avoid rippling error messages on subsequent uses of the same type,
+ // could be useful if #include was forgotten.
+ return false;
+}
+
+/// \brief Determine the declaration specifier context from the declarator
+/// context.
+///
+/// \param Context the declarator context, which is one of the
+/// Declarator::TheContext enumerator values.
+Parser::DeclSpecContext
+Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
+ if (Context == Declarator::MemberContext)
+ return DSC_class;
+ if (Context == Declarator::FileContext)
+ return DSC_top_level;
+ return DSC_normal;
+}
+
+/// ParseDeclarationSpecifiers
+/// declaration-specifiers: [C99 6.7]
+/// storage-class-specifier declaration-specifiers[opt]
+/// type-specifier declaration-specifiers[opt]
+/// [C99] function-specifier declaration-specifiers[opt]
+/// [GNU] attributes declaration-specifiers[opt]
+///
+/// storage-class-specifier: [C99 6.7.1]
+/// 'typedef'
+/// 'extern'
+/// 'static'
+/// 'auto'
+/// 'register'
+/// [C++] 'mutable'
+/// [GNU] '__thread'
+/// function-specifier: [C99 6.7.4]
+/// [C99] 'inline'
+/// [C++] 'virtual'
+/// [C++] 'explicit'
+/// [OpenCL] '__kernel'
+/// 'friend': [C++ dcl.friend]
+/// 'constexpr': [C++0x dcl.constexpr]
+
+///
+void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS,
+ DeclSpecContext DSContext) {
+ DS.SetRangeStart(Tok.getLocation());
+ DS.SetRangeEnd(Tok.getLocation());
+ while (1) {
+ bool isInvalid = false;
+ const char *PrevSpec = 0;
+ unsigned DiagID = 0;
+
+ SourceLocation Loc = Tok.getLocation();
+
+ switch (Tok.getKind()) {
+ default:
+ DoneWithDeclSpec:
+ // If this is not a declaration specifier token, we're done reading decl
+ // specifiers. First verify that DeclSpec's are consistent.
+ DS.Finish(Diags, PP);
+ return;
+
+ case tok::code_completion: {
+ Sema::ParserCompletionContext CCC = Sema::PCC_Namespace;
+ if (DS.hasTypeSpecifier()) {
+ bool AllowNonIdentifiers
+ = (getCurScope()->getFlags() & (Scope::ControlScope |
+ Scope::BlockScope |
+ Scope::TemplateParamScope |
+ Scope::FunctionPrototypeScope |
+ Scope::AtCatchScope)) == 0;
+ bool AllowNestedNameSpecifiers
+ = DSContext == DSC_top_level ||
+ (DSContext == DSC_class && DS.isFriendSpecified());
+
+ Actions.CodeCompleteDeclSpec(getCurScope(), DS,
+ AllowNonIdentifiers,
+ AllowNestedNameSpecifiers);
+ ConsumeCodeCompletionToken();
+ return;
+ }
+
+ if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
+ CCC = Sema::PCC_LocalDeclarationSpecifiers;
+ else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+ CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
+ : Sema::PCC_Template;
+ else if (DSContext == DSC_class)
+ CCC = Sema::PCC_Class;
+ else if (ObjCImpDecl)
+ CCC = Sema::PCC_ObjCImplementation;
+
+ Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
+ ConsumeCodeCompletionToken();
+ return;
+ }
+
+ case tok::coloncolon: // ::foo::bar
+ // C++ scope specifier. Annotate and loop, or bail out on error.
+ if (TryAnnotateCXXScopeToken(true)) {
+ if (!DS.hasTypeSpecifier())
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (Tok.is(tok::coloncolon)) // ::new or ::delete
+ goto DoneWithDeclSpec;
+ continue;
+
+ case tok::annot_cxxscope: {
+ if (DS.hasTypeSpecifier())
+ goto DoneWithDeclSpec;
+
+ CXXScopeSpec SS;
+ SS.setScopeRep((NestedNameSpecifier*) Tok.getAnnotationValue());
+ SS.setRange(Tok.getAnnotationRange());
+
+ // We are looking for a qualified typename.
+ Token Next = NextToken();
+ if (Next.is(tok::annot_template_id) &&
+ static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
+ ->Kind == TNK_Type_template) {
+ // We have a qualified template-id, e.g., N::A<int>
+
+ // C++ [class.qual]p2:
+ // In a lookup in which the constructor is an acceptable lookup
+ // result and the nested-name-specifier nominates a class C:
+ //
+ // - if the name specified after the
+ // nested-name-specifier, when looked up in C, is the
+ // injected-class-name of C (Clause 9), or
+ //
+ // - if the name specified after the nested-name-specifier
+ // is the same as the identifier or the
+ // simple-template-id's template-name in the last
+ // component of the nested-name-specifier,
+ //
+ // the name is instead considered to name the constructor of
+ // class C.
+ //
+ // Thus, if the template-name is actually the constructor
+ // name, then the code is ill-formed; this interpretation is
+ // reinforced by the NAD status of core issue 635.
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
+ if ((DSContext == DSC_top_level ||
+ (DSContext == DSC_class && DS.isFriendSpecified())) &&
+ TemplateId->Name &&
+ Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
+ if (isConstructorDeclarator()) {
+ // The user meant this to be an out-of-line constructor
+ // definition, but template arguments are not allowed
+ // there. Just allow this as a constructor; we'll
+ // complain about it later.
+ goto DoneWithDeclSpec;
+ }
+
+ // The user meant this to name a type, but it actually names
+ // a constructor with some extraneous template
+ // arguments. Complain, then parse it as a type as the user
+ // intended.
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_out_of_line_template_id_names_constructor)
+ << TemplateId->Name;
+ }
+
+ DS.getTypeSpecScope() = SS;
+ ConsumeToken(); // The C++ scope.
+ assert(Tok.is(tok::annot_template_id) &&
+ "ParseOptionalCXXScopeSpecifier not working");
+ AnnotateTemplateIdTokenAsType(&SS);
+ continue;
+ }
+
+ if (Next.is(tok::annot_typename)) {
+ DS.getTypeSpecScope() = SS;
+ ConsumeToken(); // The C++ scope.
+ if (Tok.getAnnotationValue()) {
+ ParsedType T = getTypeAnnotation(Tok);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
+ Tok.getAnnotationEndLoc(),
+ PrevSpec, DiagID, T);
+ }
+ else
+ DS.SetTypeSpecError();
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken(); // The typename
+ }
+
+ if (Next.isNot(tok::identifier))
+ goto DoneWithDeclSpec;
+
+ // If we're in a context where the identifier could be a class name,
+ // check whether this is a constructor declaration.
+ if ((DSContext == DSC_top_level ||
+ (DSContext == DSC_class && DS.isFriendSpecified())) &&
+ Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
+ &SS)) {
+ if (isConstructorDeclarator())
+ goto DoneWithDeclSpec;
+
+ // As noted in C++ [class.qual]p2 (cited above), when the name
+ // of the class is qualified in a context where it could name
+ // a constructor, its a constructor name. However, we've
+ // looked at the declarator, and the user probably meant this
+ // to be a type. Complain that it isn't supposed to be treated
+ // as a type, then proceed to parse it as a type.
+ Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor)
+ << Next.getIdentifierInfo();
+ }
+
+ ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
+ Next.getLocation(),
+ getCurScope(), &SS);
+
+ // If the referenced identifier is not a type, then this declspec is
+ // erroneous: We already checked about that it has no type specifier, and
+ // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
+ // typename.
+ if (TypeRep == 0) {
+ ConsumeToken(); // Eat the scope spec so the identifier is current.
+ if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue;
+ goto DoneWithDeclSpec;
+ }
+
+ DS.getTypeSpecScope() = SS;
+ ConsumeToken(); // The C++ scope.
+
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DiagID, TypeRep);
+ if (isInvalid)
+ break;
+
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken(); // The typename.
+
+ continue;
+ }
+
+ case tok::annot_typename: {
+ if (Tok.getAnnotationValue()) {
+ ParsedType T = getTypeAnnotation(Tok);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DiagID, T);
+ } else
+ DS.SetTypeSpecError();
+
+ if (isInvalid)
+ break;
+
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken(); // The typename
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ continue;
+ }
+
+ // typedef-name
+ case tok::identifier: {
+ // In C++, check to see if this is a scope specifier like foo::bar::, if
+ // so handle it as such. This is important for ctor parsing.
+ if (getLang().CPlusPlus) {
+ if (TryAnnotateCXXScopeToken(true)) {
+ if (!DS.hasTypeSpecifier())
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (!Tok.is(tok::identifier))
+ continue;
+ }
+
+ // This identifier can only be a typedef name if we haven't already seen
+ // a type-specifier. Without this check we misparse:
+ // typedef int X; struct Y { short X; }; as 'short int'.
+ if (DS.hasTypeSpecifier())
+ goto DoneWithDeclSpec;
+
+ // Check for need to substitute AltiVec keyword tokens.
+ if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
+ break;
+
+ // It has to be available as a typedef too!
+ ParsedType TypeRep =
+ Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), getCurScope());
+
+ // If this is not a typedef name, don't parse it as part of the declspec,
+ // it must be an implicit int or an error.
+ if (!TypeRep) {
+ if (ParseImplicitInt(DS, 0, TemplateInfo, AS)) continue;
+ goto DoneWithDeclSpec;
+ }
+
+ // If we're in a context where the identifier could be a class name,
+ // check whether this is a constructor declaration.
+ if (getLang().CPlusPlus && DSContext == DSC_class &&
+ Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
+ isConstructorDeclarator())
+ goto DoneWithDeclSpec;
+
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DiagID, TypeRep);
+ if (isInvalid)
+ break;
+
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken(); // The identifier
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ // Need to support trailing type qualifiers (e.g. "id<p> const").
+ // If a type specifier follows, it will be diagnosed elsewhere.
+ continue;
+ }
+
+ // type-name
+ case tok::annot_template_id: {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind != TNK_Type_template) {
+ // This template-id does not refer to a type name, so we're
+ // done with the type-specifiers.
+ goto DoneWithDeclSpec;
+ }
+
+ // If we're in a context where the template-id could be a
+ // constructor name or specialization, check whether this is a
+ // constructor declaration.
+ if (getLang().CPlusPlus && DSContext == DSC_class &&
+ Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
+ isConstructorDeclarator())
+ goto DoneWithDeclSpec;
+
+ // Turn the template-id annotation token into a type annotation
+ // token, then try again to parse it as a type-specifier.
+ AnnotateTemplateIdTokenAsType();
+ continue;
+ }
+
+ // GNU attributes support.
+ case tok::kw___attribute:
+ ParseGNUAttributes(DS.getAttributes());
+ continue;
+
+ // Microsoft declspec support.
+ case tok::kw___declspec:
+ ParseMicrosoftDeclSpec(DS.getAttributes());
+ continue;
+
+ // Microsoft single token adornments.
+ case tok::kw___forceinline:
+ // FIXME: Add handling here!
+ break;
+
+ case tok::kw___ptr64:
+ case tok::kw___w64:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
+ continue;
+
+ // Borland single token adornments.
+ case tok::kw___pascal:
+ ParseBorlandTypeAttributes(DS.getAttributes());
+ continue;
+
+ // OpenCL single token adornments.
+ case tok::kw___kernel:
+ ParseOpenCLAttributes(DS.getAttributes());
+ continue;
+
+ // storage-class-specifier
+ case tok::kw_typedef:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_extern:
+ if (DS.isThreadSpecified())
+ Diag(Tok, diag::ext_thread_before) << "extern";
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw___private_extern__:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
+ PrevSpec, DiagID, getLang());
+ break;
+ case tok::kw_static:
+ if (DS.isThreadSpecified())
+ Diag(Tok, diag::ext_thread_before) << "static";
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_auto:
+ if (getLang().CPlusPlus0x)
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+ DiagID);
+ else
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_register:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_mutable:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw___thread:
+ isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
+ break;
+
+ // function-specifier
+ case tok::kw_inline:
+ isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_virtual:
+ isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_explicit:
+ isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID);
+ break;
+
+ // friend
+ case tok::kw_friend:
+ if (DSContext == DSC_class)
+ isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
+ else {
+ PrevSpec = ""; // not actually used by the diagnostic
+ DiagID = diag::err_friend_invalid_in_context;
+ isInvalid = true;
+ }
+ break;
+
+ // constexpr
+ case tok::kw_constexpr:
+ isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
+ break;
+
+ // type-specifier
+ case tok::kw_short:
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_long:
+ if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+ DiagID);
+ else
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_signed:
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_unsigned:
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Complex:
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Imaginary:
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_void:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_char:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_int:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_float:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_double:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_wchar_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_char16_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_char32_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ if (Tok.is(tok::kw_bool) &&
+ DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ PrevSpec = ""; // Not used by the diagnostic.
+ DiagID = diag::err_bool_redeclaration;
+ isInvalid = true;
+ } else {
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
+ DiagID);
+ }
+ break;
+ case tok::kw__Decimal32:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Decimal64:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Decimal128:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw___vector:
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw___pixel:
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ break;
+
+ // class-specifier:
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union: {
+ tok::TokenKind Kind = Tok.getKind();
+ ConsumeToken();
+ ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
+ continue;
+ }
+
+ // enum-specifier:
+ case tok::kw_enum:
+ ConsumeToken();
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
+ continue;
+
+ // cv-qualifier:
+ case tok::kw_const:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+ case tok::kw_volatile:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+ case tok::kw_restrict:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+
+ // C++ typename-specifier:
+ case tok::kw_typename:
+ if (TryAnnotateTypeOrScopeToken()) {
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (!Tok.is(tok::kw_typename))
+ continue;
+ break;
+
+ // GNU typeof support.
+ case tok::kw_typeof:
+ ParseTypeofSpecifier(DS);
+ continue;
+
+ case tok::kw_decltype:
+ ParseDecltypeSpecifier(DS);
+ continue;
+
+ case tok::less:
+ // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
+ // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
+ // but we support it.
+ if (DS.hasTypeSpecifier() || !getLang().ObjC1)
+ goto DoneWithDeclSpec;
+
+ if (!ParseObjCProtocolQualifiers(DS))
+ Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
+ << FixItHint::CreateInsertion(Loc, "id")
+ << SourceRange(Loc, DS.getSourceRange().getEnd());
+
+ // Need to support trailing type qualifiers (e.g. "id<p> const").
+ // If a type specifier follows, it will be diagnosed elsewhere.
+ continue;
+ }
+ // If the specifier wasn't legal, issue a diagnostic.
+ if (isInvalid) {
+ assert(PrevSpec && "Method did not return previous specifier!");
+ assert(DiagID);
+
+ if (DiagID == diag::ext_duplicate_declspec)
+ Diag(Tok, DiagID)
+ << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
+ else
+ Diag(Tok, DiagID) << PrevSpec;
+ }
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+ }
+}
+
+/// ParseOptionalTypeSpecifier - Try to parse a single type-specifier. We
+/// primarily follow the C++ grammar with additions for C99 and GNU,
+/// which together subsume the C grammar. Note that the C++
+/// type-specifier also includes the C type-qualifier (for const,
+/// volatile, and C99 restrict). Returns true if a type-specifier was
+/// found (and parsed), false otherwise.
+///
+/// type-specifier: [C++ 7.1.5]
+/// simple-type-specifier
+/// class-specifier
+/// enum-specifier
+/// elaborated-type-specifier [TODO]
+/// cv-qualifier
+///
+/// cv-qualifier: [C++ 7.1.5.1]
+/// 'const'
+/// 'volatile'
+/// [C99] 'restrict'
+///
+/// simple-type-specifier: [ C++ 7.1.5.2]
+/// '::'[opt] nested-name-specifier[opt] type-name [TODO]
+/// '::'[opt] nested-name-specifier 'template' template-id [TODO]
+/// 'char'
+/// 'wchar_t'
+/// 'bool'
+/// 'short'
+/// 'int'
+/// 'long'
+/// 'signed'
+/// 'unsigned'
+/// 'float'
+/// 'double'
+/// 'void'
+/// [C99] '_Bool'
+/// [C99] '_Complex'
+/// [C99] '_Imaginary' // Removed in TC2?
+/// [GNU] '_Decimal32'
+/// [GNU] '_Decimal64'
+/// [GNU] '_Decimal128'
+/// [GNU] typeof-specifier
+/// [OBJC] class-name objc-protocol-refs[opt] [TODO]
+/// [OBJC] typedef-name objc-protocol-refs[opt] [TODO]
+/// [C++0x] 'decltype' ( expression )
+/// [AltiVec] '__vector'
+bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ const ParsedTemplateInfo &TemplateInfo,
+ bool SuppressDeclarations) {
+ SourceLocation Loc = Tok.getLocation();
+
+ switch (Tok.getKind()) {
+ case tok::identifier: // foo::bar
+ // If we already have a type specifier, this identifier is not a type.
+ if (DS.getTypeSpecType() != DeclSpec::TST_unspecified ||
+ DS.getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
+ DS.getTypeSpecSign() != DeclSpec::TSS_unspecified)
+ return false;
+ // Check for need to substitute AltiVec keyword tokens.
+ if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
+ break;
+ // Fall through.
+ case tok::kw_typename: // typename foo::bar
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo, SuppressDeclarations);
+ case tok::coloncolon: // ::foo::bar
+ if (NextToken().is(tok::kw_new) || // ::new
+ NextToken().is(tok::kw_delete)) // ::delete
+ return false;
+
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo, SuppressDeclarations);
+
+ // simple-type-specifier:
+ case tok::annot_typename: {
+ if (ParsedType T = getTypeAnnotation(Tok)) {
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
+ Tok.getAnnotationEndLoc(), PrevSpec,
+ DiagID, T);
+ } else
+ DS.SetTypeSpecError();
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken(); // The typename
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface. If we don't have Objective-C or a '<', this is
+ // just a normal reference to a typedef name.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ return true;
+ }
+
+ case tok::kw_short:
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_long:
+ if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+ DiagID);
+ else
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_signed:
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_unsigned:
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Complex:
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Imaginary:
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_void:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_int:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_float:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_double:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_wchar_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char16_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char32_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw__Decimal32:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Decimal64:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw__Decimal128:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw___vector:
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw___pixel:
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ break;
+
+ // class-specifier:
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union: {
+ tok::TokenKind Kind = Tok.getKind();
+ ConsumeToken();
+ ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
+ SuppressDeclarations);
+ return true;
+ }
+
+ // enum-specifier:
+ case tok::kw_enum:
+ ConsumeToken();
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS_none);
+ return true;
+
+ // cv-qualifier:
+ case tok::kw_const:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_volatile:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+ case tok::kw_restrict:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
+ DiagID, getLang());
+ break;
+
+ // GNU typeof support.
+ case tok::kw_typeof:
+ ParseTypeofSpecifier(DS);
+ return true;
+
+ // C++0x decltype support.
+ case tok::kw_decltype:
+ ParseDecltypeSpecifier(DS);
+ return true;
+
+ // C++0x auto support.
+ case tok::kw_auto:
+ if (!getLang().CPlusPlus0x)
+ return false;
+
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
+ break;
+
+ case tok::kw___ptr64:
+ case tok::kw___w64:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
+ return true;
+
+ case tok::kw___pascal:
+ ParseBorlandTypeAttributes(DS.getAttributes());
+ return true;
+
+ default:
+ // Not a type-specifier; do nothing.
+ return false;
+ }
+
+ // If the specifier combination wasn't legal, issue a diagnostic.
+ if (isInvalid) {
+ assert(PrevSpec && "Method did not return previous specifier!");
+ // Pick between error or extwarn.
+ Diag(Tok, DiagID) << PrevSpec;
+ }
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken(); // whatever we parsed above.
+ return true;
+}
+
+/// ParseStructDeclaration - Parse a struct declaration without the terminating
+/// semicolon.
+///
+/// struct-declaration:
+/// specifier-qualifier-list struct-declarator-list
+/// [GNU] __extension__ struct-declaration
+/// [GNU] specifier-qualifier-list
+/// struct-declarator-list:
+/// struct-declarator
+/// struct-declarator-list ',' struct-declarator
+/// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
+/// struct-declarator:
+/// declarator
+/// [GNU] declarator attributes[opt]
+/// declarator[opt] ':' constant-expression
+/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
+///
+void Parser::
+ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
+ if (Tok.is(tok::kw___extension__)) {
+ // __extension__ silences extension warnings in the subexpression.
+ ExtensionRAIIObject O(Diags); // Use RAII to do this.
+ ConsumeToken();
+ return ParseStructDeclaration(DS, Fields);
+ }
+
+ // Parse the common specifier-qualifiers-list piece.
+ ParseSpecifierQualifierList(DS);
+
+ // If there are no declarators, this is a free-standing declaration
+ // specifier. Let the actions module cope with it.
+ if (Tok.is(tok::semi)) {
+ Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, DS);
+ return;
+ }
+
+ // Read struct-declarators until we find the semicolon.
+ bool FirstDeclarator = true;
+ while (1) {
+ ParsingDeclRAIIObject PD(*this);
+ FieldDeclarator DeclaratorInfo(DS);
+
+ // Attributes are only allowed here on successive declarators.
+ if (!FirstDeclarator)
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
+
+ /// struct-declarator: declarator
+ /// struct-declarator: declarator[opt] ':' constant-expression
+ if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+ ParseDeclarator(DeclaratorInfo.D);
+ }
+
+ if (Tok.is(tok::colon)) {
+ ConsumeToken();
+ ExprResult Res(ParseConstantExpression());
+ if (Res.isInvalid())
+ SkipUntil(tok::semi, true, true);
+ else
+ DeclaratorInfo.BitfieldSize = Res.release();
+ }
+
+ // If attributes exist after the declarator, parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo.D);
+
+ // We're done with this declarator; invoke the callback.
+ Decl *D = Fields.invoke(DeclaratorInfo);
+ PD.complete(D);
+
+ // If we don't have a comma, it is either the end of the list (a ';')
+ // or an error, bail out.
+ if (Tok.isNot(tok::comma))
+ return;
+
+ // Consume the comma.
+ ConsumeToken();
+
+ FirstDeclarator = false;
+ }
+}
+
+/// ParseStructUnionBody
+/// struct-contents:
+/// struct-declaration-list
+/// [EXT] empty
+/// [GNU] "struct-declaration-list" without terminatoring ';'
+/// struct-declaration-list:
+/// struct-declaration
+/// struct-declaration-list struct-declaration
+/// [OBC] '@' 'defs' '(' class-name ')'
+///
+void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
+ unsigned TagType, Decl *TagDecl) {
+ PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ "parsing struct/union body");
+
+ SourceLocation LBraceLoc = ConsumeBrace();
+
+ ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
+ Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
+
+ // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
+ // C++.
+ if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
+ Diag(Tok, diag::ext_empty_struct_union)
+ << (TagType == TST_union);
+
+ llvm::SmallVector<Decl *, 32> FieldDecls;
+
+ // While we still have something to read, read the declarations in the struct.
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ // Each iteration of this loop reads one struct-declaration.
+
+ // Check for extraneous top-level semicolon.
+ if (Tok.is(tok::semi)) {
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << DeclSpec::getSpecifierName((DeclSpec::TST)TagType)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ ConsumeToken();
+ continue;
+ }
+
+ // Parse all the comma separated declarators.
+ DeclSpec DS;
+
+ if (!Tok.is(tok::at)) {
+ struct CFieldCallback : FieldCallback {
+ Parser &P;
+ Decl *TagDecl;
+ llvm::SmallVectorImpl<Decl *> &FieldDecls;
+
+ CFieldCallback(Parser &P, Decl *TagDecl,
+ llvm::SmallVectorImpl<Decl *> &FieldDecls) :
+ P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
+
+ virtual Decl *invoke(FieldDeclarator &FD) {
+ // Install the declarator into the current TagDecl.
+ Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ FD.D, FD.BitfieldSize);
+ FieldDecls.push_back(Field);
+ return Field;
+ }
+ } Callback(*this, TagDecl, FieldDecls);
+
+ ParseStructDeclaration(DS, Callback);
+ } else { // Handle @defs
+ ConsumeToken();
+ if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
+ Diag(Tok, diag::err_unexpected_at);
+ SkipUntil(tok::semi, true);
+ continue;
+ }
+ ConsumeToken();
+ ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::semi, true);
+ continue;
+ }
+ llvm::SmallVector<Decl *, 16> Fields;
+ Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
+ Tok.getIdentifierInfo(), Fields);
+ FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
+ ConsumeToken();
+ ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
+ }
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ } else if (Tok.is(tok::r_brace)) {
+ ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
+ break;
+ } else {
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
+ // Skip to end of block or statement to avoid ext-warning on extra ';'.
+ SkipUntil(tok::r_brace, true, true);
+ // If we stopped at a ';', eat it.
+ if (Tok.is(tok::semi)) ConsumeToken();
+ }
+ }
+
+ SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+ ParsedAttributes attrs;
+ // If attributes exist after struct contents, parse them.
+ MaybeParseGNUAttributes(attrs);
+
+ Actions.ActOnFields(getCurScope(),
+ RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
+ LBraceLoc, RBraceLoc,
+ attrs.getList());
+ StructScope.Exit();
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
+}
+
+/// ParseEnumSpecifier
+/// enum-specifier: [C99 6.7.2.2]
+/// 'enum' identifier[opt] '{' enumerator-list '}'
+///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
+/// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
+/// '}' attributes[opt]
+/// 'enum' identifier
+/// [GNU] 'enum' attributes[opt] identifier
+///
+/// [C++0x] enum-head '{' enumerator-list[opt] '}'
+/// [C++0x] enum-head '{' enumerator-list ',' '}'
+///
+/// enum-head: [C++0x]
+/// enum-key attributes[opt] identifier[opt] enum-base[opt]
+/// enum-key attributes[opt] nested-name-specifier identifier enum-base[opt]
+///
+/// enum-key: [C++0x]
+/// 'enum'
+/// 'enum' 'class'
+/// 'enum' 'struct'
+///
+/// enum-base: [C++0x]
+/// ':' type-specifier-seq
+///
+/// [C++] elaborated-type-specifier:
+/// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS) {
+ // Parse the tag portion of this.
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for an enum name.
+ Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);
+ ConsumeCodeCompletionToken();
+ }
+
+ // If attributes exist after tag, parse them.
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
+ if (getLang().CPlusPlus) {
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false))
+ return;
+
+ if (SS.isSet() && Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ if (Tok.isNot(tok::l_brace)) {
+ // Has no name and is not a definition.
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+ }
+ }
+
+ bool IsScopedEnum = false;
+ bool IsScopedUsingClassTag = false;
+
+ if (getLang().CPlusPlus0x &&
+ (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) {
+ IsScopedEnum = true;
+ IsScopedUsingClassTag = Tok.is(tok::kw_class);
+ ConsumeToken();
+ }
+
+ // Must have either 'enum name' or 'enum {...}'.
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
+ Diag(Tok, diag::err_expected_ident_lbrace);
+
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+
+ // If an identifier is present, consume and remember it.
+ IdentifierInfo *Name = 0;
+ SourceLocation NameLoc;
+ if (Tok.is(tok::identifier)) {
+ Name = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+ }
+
+ if (!Name && IsScopedEnum) {
+ // C++0x 7.2p2: The optional identifier shall not be omitted in the
+ // declaration of a scoped enumeration.
+ Diag(Tok, diag::err_scoped_enum_missing_identifier);
+ IsScopedEnum = false;
+ IsScopedUsingClassTag = false;
+ }
+
+ TypeResult BaseType;
+
+ // Parse the fixed underlying type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
+ bool PossibleBitfield = false;
+ if (getCurScope()->getFlags() & Scope::ClassScope) {
+ // If we're in class scope, this can either be an enum declaration with
+ // an underlying type, or a declaration of a bitfield member. We try to
+ // use a simple disambiguation scheme first to catch the common cases
+ // (integer literal, sizeof); if it's still ambiguous, we then consider
+ // anything that's a simple-type-specifier followed by '(' as an
+ // expression. This suffices because function types are not valid
+ // underlying types anyway.
+ TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
+ // If the next token starts an expression, we know we're parsing a
+ // bit-field. This is the common case.
+ if (TPR == TPResult::True())
+ PossibleBitfield = true;
+ // If the next token starts a type-specifier-seq, it may be either a
+ // a fixed underlying type or the start of a function-style cast in C++;
+ // lookahead one more token to see if it's obvious that we have a
+ // fixed underlying type.
+ else if (TPR == TPResult::False() &&
+ GetLookAheadToken(2).getKind() == tok::semi) {
+ // Consume the ':'.
+ ConsumeToken();
+ } else {
+ // We have the start of a type-specifier-seq, so we have to perform
+ // tentative parsing to determine whether we have an expression or a
+ // type.
+ TentativeParsingAction TPA(*this);
+
+ // Consume the ':'.
+ ConsumeToken();
+
+ if (isCXXDeclarationSpecifier() != TPResult::True()) {
+ // We'll parse this as a bitfield later.
+ PossibleBitfield = true;
+ TPA.Revert();
+ } else {
+ // We have a type-specifier-seq.
+ TPA.Commit();
+ }
+ }
+ } else {
+ // Consume the ':'.
+ ConsumeToken();
+ }
+
+ if (!PossibleBitfield) {
+ SourceRange Range;
+ BaseType = ParseTypeName(&Range);
+ }
+ }
+
+ // There are three options here. If we have 'enum foo;', then this is a
+ // forward declaration. If we have 'enum foo {...' then this is a
+ // definition. Otherwise we have something like 'enum foo xyz', a reference.
+ //
+ // This is needed to handle stuff like this right (C99 6.7.2.3p11):
+ // enum foo {..}; void bar() { enum foo; } <- new foo in bar.
+ // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
+ //
+ Sema::TagUseKind TUK;
+ if (Tok.is(tok::l_brace))
+ TUK = Sema::TUK_Definition;
+ else if (Tok.is(tok::semi))
+ TUK = Sema::TUK_Declaration;
+ else
+ TUK = Sema::TUK_Reference;
+
+ // enums cannot be templates, although they can be referenced from a
+ // template.
+ if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
+ TUK != Sema::TUK_Reference) {
+ Diag(Tok, diag::err_enum_template);
+
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+
+ bool Owned = false;
+ bool IsDependent = false;
+ SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
+ StartLoc, SS, Name, NameLoc, attrs.getList(),
+ AS,
+ MultiTemplateParamsArg(Actions),
+ Owned, IsDependent, IsScopedEnum,
+ IsScopedUsingClassTag, BaseType);
+
+ if (IsDependent) {
+ // This enum has a dependent nested-name-specifier. Handle it as a
+ // dependent tag.
+ if (!Name) {
+ DS.SetTypeSpecError();
+ Diag(Tok, diag::err_expected_type_name_after_typename);
+ return;
+ }
+
+ TypeResult Type = Actions.ActOnDependentTag(getCurScope(), DeclSpec::TST_enum,
+ TUK, SS, Name, StartLoc,
+ NameLoc);
+ if (Type.isInvalid()) {
+ DS.SetTypeSpecError();
+ return;
+ }
+
+ if (DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc, PrevSpec, DiagID,
+ Type.get()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+
+ return;
+ }
+
+ if (!TagDecl) {
+ // The action failed to produce an enumeration tag. If this is a
+ // definition, consume the entire definition.
+ if (Tok.is(tok::l_brace)) {
+ ConsumeBrace();
+ SkipUntil(tok::r_brace);
+ }
+
+ DS.SetTypeSpecError();
+ return;
+ }
+
+ if (Tok.is(tok::l_brace))
+ ParseEnumBody(StartLoc, TagDecl);
+
+ // FIXME: The DeclSpec should keep the locations of both the keyword
+ // and the name (if there is one).
+ if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID,
+ TagDecl, Owned))
+ Diag(StartLoc, DiagID) << PrevSpec;
+}
+
+/// ParseEnumBody - Parse a {} enclosed enumerator-list.
+/// enumerator-list:
+/// enumerator
+/// enumerator-list ',' enumerator
+/// enumerator:
+/// enumeration-constant
+/// enumeration-constant '=' constant-expression
+/// enumeration-constant:
+/// identifier
+///
+void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
+ // Enter the scope of the enum body and start the definition.
+ ParseScope EnumScope(this, Scope::DeclScope);
+ Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
+
+ SourceLocation LBraceLoc = ConsumeBrace();
+
+ // C does not allow an empty enumerator-list, C++ does [dcl.enum].
+ if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
+ Diag(Tok, diag::error_empty_enum);
+
+ llvm::SmallVector<Decl *, 32> EnumConstantDecls;
+
+ Decl *LastEnumConstDecl = 0;
+
+ // Parse the enumerator-list.
+ while (Tok.is(tok::identifier)) {
+ IdentifierInfo *Ident = Tok.getIdentifierInfo();
+ SourceLocation IdentLoc = ConsumeToken();
+
+ // If attributes exist after the enumerator, parse them.
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
+ SourceLocation EqualLoc;
+ ExprResult AssignedVal;
+ if (Tok.is(tok::equal)) {
+ EqualLoc = ConsumeToken();
+ AssignedVal = ParseConstantExpression();
+ if (AssignedVal.isInvalid())
+ SkipUntil(tok::comma, tok::r_brace, true, true);
+ }
+
+ // Install the enumerator constant into EnumDecl.
+ Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
+ LastEnumConstDecl,
+ IdentLoc, Ident,
+ attrs.getList(), EqualLoc,
+ AssignedVal.release());
+ EnumConstantDecls.push_back(EnumConstDecl);
+ LastEnumConstDecl = EnumConstDecl;
+
+ if (Tok.is(tok::identifier)) {
+ // We're missing a comma between enumerators.
+ SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
+ Diag(Loc, diag::err_enumerator_list_missing_comma)
+ << FixItHint::CreateInsertion(Loc, ", ");
+ continue;
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+ SourceLocation CommaLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::identifier) &&
+ !(getLang().C99 || getLang().CPlusPlus0x))
+ Diag(CommaLoc, diag::ext_enumerator_list_comma)
+ << getLang().CPlusPlus
+ << FixItHint::CreateRemoval(CommaLoc);
+ }
+
+ // Eat the }.
+ SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+ // If attributes exist after the identifier list, parse them.
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
+ Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
+ EnumConstantDecls.data(), EnumConstantDecls.size(),
+ getCurScope(), attrs.getList());
+
+ EnumScope.Exit();
+ Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc);
+}
+
+/// isTypeSpecifierQualifier - Return true if the current token could be the
+/// start of a type-qualifier-list.
+bool Parser::isTypeQualifier() const {
+ switch (Tok.getKind()) {
+ default: return false;
+ // type-qualifier
+ case tok::kw_const:
+ case tok::kw_volatile:
+ case tok::kw_restrict:
+ return true;
+ }
+}
+
+/// isKnownToBeTypeSpecifier - Return true if we know that the specified token
+/// is definitely a type-specifier. Return false if it isn't part of a type
+/// specifier or if we're not sure.
+bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
+ switch (Tok.getKind()) {
+ default: return false;
+ // type-specifiers
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw__Complex:
+ case tok::kw__Imaginary:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___vector:
+
+ // struct-or-union-specifier (C99) or class-specifier (C++)
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+
+ // typedef-name
+ case tok::annot_typename:
+ return true;
+ }
+}
+
+/// isTypeSpecifierQualifier - Return true if the current token could be the
+/// start of a specifier-qualifier-list.
+bool Parser::isTypeSpecifierQualifier() {
+ switch (Tok.getKind()) {
+ default: return false;
+
+ case tok::identifier: // foo::bar
+ if (TryAltiVecVectorToken())
+ return true;
+ // Fall through.
+ case tok::kw_typename: // typename T::type
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+ return isTypeSpecifierQualifier();
+
+ case tok::coloncolon: // ::foo::bar
+ if (NextToken().is(tok::kw_new) || // ::new
+ NextToken().is(tok::kw_delete)) // ::delete
+ return false;
+
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ return isTypeSpecifierQualifier();
+
+ // GNU attributes support.
+ case tok::kw___attribute:
+ // GNU typeof support.
+ case tok::kw_typeof:
+
+ // type-specifiers
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw__Complex:
+ case tok::kw__Imaginary:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___vector:
+
+ // struct-or-union-specifier (C99) or class-specifier (C++)
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+
+ // type-qualifier
+ case tok::kw_const:
+ case tok::kw_volatile:
+ case tok::kw_restrict:
+
+ // typedef-name
+ case tok::annot_typename:
+ return true;
+
+ // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
+ case tok::less:
+ return getLang().ObjC1;
+
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___w64:
+ case tok::kw___ptr64:
+ case tok::kw___pascal:
+ return true;
+ }
+}
+
+/// isDeclarationSpecifier() - Return true if the current token is part of a
+/// declaration specifier.
+///
+/// \param DisambiguatingWithExpression True to indicate that the purpose of
+/// this check is to disambiguate between an expression and a declaration.
+bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
+ switch (Tok.getKind()) {
+ default: return false;
+
+ case tok::identifier: // foo::bar
+ // Unfortunate hack to support "Class.factoryMethod" notation.
+ if (getLang().ObjC1 && NextToken().is(tok::period))
+ return false;
+ if (TryAltiVecVectorToken())
+ return true;
+ // Fall through.
+ case tok::kw_typename: // typename T::type
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+
+ // If we're in Objective-C and we have an Objective-C class type followed
+ // by an identifier and then either ':' or ']', in a place where an
+ // expression is permitted, then this is probably a class message send
+ // missing the initial '['. In this case, we won't consider this to be
+ // the start of a declaration.
+ if (DisambiguatingWithExpression &&
+ isStartOfObjCClassMessageMissingOpenBracket())
+ return false;
+
+ return isDeclarationSpecifier();
+
+ case tok::coloncolon: // ::foo::bar
+ if (NextToken().is(tok::kw_new) || // ::new
+ NextToken().is(tok::kw_delete)) // ::delete
+ return false;
+
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return true;
+ return isDeclarationSpecifier();
+
+ // storage-class-specifier
+ case tok::kw_typedef:
+ case tok::kw_extern:
+ case tok::kw___private_extern__:
+ case tok::kw_static:
+ case tok::kw_auto:
+ case tok::kw_register:
+ case tok::kw___thread:
+
+ // type-specifiers
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw__Complex:
+ case tok::kw__Imaginary:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___vector:
+
+ // struct-or-union-specifier (C99) or class-specifier (C++)
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+
+ // type-qualifier
+ case tok::kw_const:
+ case tok::kw_volatile:
+ case tok::kw_restrict:
+
+ // function-specifier
+ case tok::kw_inline:
+ case tok::kw_virtual:
+ case tok::kw_explicit:
+
+ // typedef-name
+ case tok::annot_typename:
+
+ // GNU typeof support.
+ case tok::kw_typeof:
+
+ // GNU attributes.
+ case tok::kw___attribute:
+ return true;
+
+ // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
+ case tok::less:
+ return getLang().ObjC1;
+
+ case tok::kw___declspec:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___w64:
+ case tok::kw___ptr64:
+ case tok::kw___forceinline:
+ case tok::kw___pascal:
+ return true;
+ }
+}
+
+bool Parser::isConstructorDeclarator() {
+ TentativeParsingAction TPA(*this);
+
+ // Parse the C++ scope specifier.
+ CXXScopeSpec SS;
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true)) {
+ TPA.Revert();
+ return false;
+ }
+
+ // Parse the constructor name.
+ if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
+ // We already know that we have a constructor name; just consume
+ // the token.
+ ConsumeToken();
+ } else {
+ TPA.Revert();
+ return false;
+ }
+
+ // Current class name must be followed by a left parentheses.
+ if (Tok.isNot(tok::l_paren)) {
+ TPA.Revert();
+ return false;
+ }
+ ConsumeParen();
+
+ // A right parentheses or ellipsis signals that we have a constructor.
+ if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) {
+ TPA.Revert();
+ return true;
+ }
+
+ // If we need to, enter the specified scope.
+ DeclaratorScopeObj DeclScopeObj(*this, SS);
+ if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
+ DeclScopeObj.EnterDeclaratorScope();
+
+ // Optionally skip Microsoft attributes.
+ ParsedAttributes Attrs;
+ MaybeParseMicrosoftAttributes(Attrs);
+
+ // Check whether the next token(s) are part of a declaration
+ // specifier, in which case we have the start of a parameter and,
+ // therefore, we know that this is a constructor.
+ bool IsConstructor = isDeclarationSpecifier();
+ TPA.Revert();
+ return IsConstructor;
+}
+
+/// ParseTypeQualifierListOpt
+/// type-qualifier-list: [C99 6.7.5]
+/// type-qualifier
+/// [vendor] attributes
+/// [ only if VendorAttributesAllowed=true ]
+/// type-qualifier-list type-qualifier
+/// [vendor] type-qualifier-list attributes
+/// [ only if VendorAttributesAllowed=true ]
+/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
+/// [ only if CXX0XAttributesAllowed=true ]
+/// Note: vendor can be GNU, MS, etc.
+///
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
+ bool VendorAttributesAllowed,
+ bool CXX0XAttributesAllowed) {
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ SourceLocation Loc = Tok.getLocation();
+ ParsedAttributesWithRange attrs;
+ ParseCXX0XAttributes(attrs);
+ if (CXX0XAttributesAllowed)
+ DS.takeAttributesFrom(attrs);
+ else
+ Diag(Loc, diag::err_attributes_not_allowed);
+ }
+
+ while (1) {
+ bool isInvalid = false;
+ const char *PrevSpec = 0;
+ unsigned DiagID = 0;
+ SourceLocation Loc = Tok.getLocation();
+
+ switch (Tok.getKind()) {
+ case tok::code_completion:
+ Actions.CodeCompleteTypeQualifiers(DS);
+ ConsumeCodeCompletionToken();
+ break;
+
+ case tok::kw_const:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+ case tok::kw_volatile:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+ case tok::kw_restrict:
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+ getLang());
+ break;
+ case tok::kw___w64:
+ case tok::kw___ptr64:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ if (VendorAttributesAllowed) {
+ ParseMicrosoftTypeAttributes(DS.getAttributes());
+ continue;
+ }
+ goto DoneWithTypeQuals;
+ case tok::kw___pascal:
+ if (VendorAttributesAllowed) {
+ ParseBorlandTypeAttributes(DS.getAttributes());
+ continue;
+ }
+ goto DoneWithTypeQuals;
+ case tok::kw___attribute:
+ if (VendorAttributesAllowed) {
+ ParseGNUAttributes(DS.getAttributes());
+ continue; // do *not* consume the next token!
+ }
+ // otherwise, FALL THROUGH!
+ default:
+ DoneWithTypeQuals:
+ // If this is not a type-qualifier token, we're done reading type
+ // qualifiers. First verify that DeclSpec's are consistent.
+ DS.Finish(Diags, PP);
+ return;
+ }
+
+ // If the specifier combination wasn't legal, issue a diagnostic.
+ if (isInvalid) {
+ assert(PrevSpec && "Method did not return previous specifier!");
+ Diag(Tok, DiagID) << PrevSpec;
+ }
+ ConsumeToken();
+ }
+}
+
+
+/// ParseDeclarator - Parse and verify a newly-initialized declarator.
+///
+void Parser::ParseDeclarator(Declarator &D) {
+ /// This implements the 'declarator' production in the C grammar, then checks
+ /// for well-formedness and issues diagnostics.
+ ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
+}
+
+/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
+/// is parsed by the function passed to it. Pass null, and the direct-declarator
+/// isn't parsed at all, making this function effectively parse the C++
+/// ptr-operator production.
+///
+/// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
+/// [C] pointer[opt] direct-declarator
+/// [C++] direct-declarator
+/// [C++] ptr-operator declarator
+///
+/// pointer: [C99 6.7.5]
+/// '*' type-qualifier-list[opt]
+/// '*' type-qualifier-list[opt] pointer
+///
+/// ptr-operator:
+/// '*' cv-qualifier-seq[opt]
+/// '&'
+/// [C++0x] '&&'
+/// [GNU] '&' restrict[opt] attributes[opt]
+/// [GNU?] '&&' restrict[opt] attributes[opt]
+/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+void Parser::ParseDeclaratorInternal(Declarator &D,
+ DirectDeclParseFunction DirectDeclParser) {
+ if (Diags.hasAllExtensionsSilenced())
+ D.setExtension();
+
+ // C++ member pointers start with a '::' or a nested-name.
+ // Member pointers get special handling, since there's no place for the
+ // scope spec in the generic path below.
+ if (getLang().CPlusPlus &&
+ (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
+ Tok.is(tok::annot_cxxscope))) {
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true); // ignore fail
+
+ if (SS.isNotEmpty()) {
+ if (Tok.isNot(tok::star)) {
+ // The scope spec really belongs to the direct-declarator.
+ D.getCXXScopeSpec() = SS;
+ if (DirectDeclParser)
+ (this->*DirectDeclParser)(D);
+ return;
+ }
+
+ SourceLocation Loc = ConsumeToken();
+ D.SetRangeEnd(Loc);
+ DeclSpec DS;
+ ParseTypeQualifierListOpt(DS);
+ D.ExtendWithDeclSpec(DS);
+
+ // Recurse to parse whatever is left.
+ ParseDeclaratorInternal(D, DirectDeclParser);
+
+ // Sema will have to catch (syntactically invalid) pointers into global
+ // scope. It has to catch pointers into namespace scope anyway.
+ D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
+ Loc, DS.takeAttributes()),
+ /* Don't replace range end. */SourceLocation());
+ return;
+ }
+ }
+
+ tok::TokenKind Kind = Tok.getKind();
+ // Not a pointer, C++ reference, or block.
+ if (Kind != tok::star && Kind != tok::caret &&
+ (Kind != tok::amp || !getLang().CPlusPlus) &&
+ // We parse rvalue refs in C++03, because otherwise the errors are scary.
+ (Kind != tok::ampamp || !getLang().CPlusPlus)) {
+ if (DirectDeclParser)
+ (this->*DirectDeclParser)(D);
+ return;
+ }
+
+ // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
+ // '&&' -> rvalue reference
+ SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.
+ D.SetRangeEnd(Loc);
+
+ if (Kind == tok::star || Kind == tok::caret) {
+ // Is a pointer.
+ DeclSpec DS;
+
+ ParseTypeQualifierListOpt(DS);
+ D.ExtendWithDeclSpec(DS);
+
+ // Recursively parse the declarator.
+ ParseDeclaratorInternal(D, DirectDeclParser);
+ if (Kind == tok::star)
+ // Remember that we parsed a pointer type, and remember the type-quals.
+ D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+ DS.takeAttributes()),
+ SourceLocation());
+ else
+ // Remember that we parsed a Block type, and remember the type-quals.
+ D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
+ Loc, DS.takeAttributes()),
+ SourceLocation());
+ } else {
+ // Is a reference
+ DeclSpec DS;
+
+ // Complain about rvalue references in C++03, but then go on and build
+ // the declarator.
+ if (Kind == tok::ampamp && !getLang().CPlusPlus0x)
+ Diag(Loc, diag::ext_rvalue_reference);
+
+ // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
+ // cv-qualifiers are introduced through the use of a typedef or of a
+ // template type argument, in which case the cv-qualifiers are ignored.
+ //
+ // [GNU] Retricted references are allowed.
+ // [GNU] Attributes on references are allowed.
+ // [C++0x] Attributes on references are not allowed.
+ ParseTypeQualifierListOpt(DS, true, false);
+ D.ExtendWithDeclSpec(DS);
+
+ if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(DS.getConstSpecLoc(),
+ diag::err_invalid_reference_qualifier_application) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
+ Diag(DS.getVolatileSpecLoc(),
+ diag::err_invalid_reference_qualifier_application) << "volatile";
+ }
+
+ // Recursively parse the declarator.
+ ParseDeclaratorInternal(D, DirectDeclParser);
+
+ if (D.getNumTypeObjects() > 0) {
+ // C++ [dcl.ref]p4: There shall be no references to references.
+ DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
+ if (InnerChunk.Kind == DeclaratorChunk::Reference) {
+ if (const IdentifierInfo *II = D.getIdentifier())
+ Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
+ << II;
+ else
+ Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
+ << "type name";
+
+ // Once we've complained about the reference-to-reference, we
+ // can go ahead and build the (technically ill-formed)
+ // declarator: reference collapsing will take care of it.
+ }
+ }
+
+ // Remember that we parsed a reference type. It doesn't have type-quals.
+ D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
+ DS.takeAttributes(),
+ Kind == tok::amp),
+ SourceLocation());
+ }
+}
+
+/// ParseDirectDeclarator
+/// direct-declarator: [C99 6.7.5]
+/// [C99] identifier
+/// '(' declarator ')'
+/// [GNU] '(' attributes declarator ')'
+/// [C90] direct-declarator '[' constant-expression[opt] ']'
+/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
+/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
+/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
+/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
+/// direct-declarator '(' parameter-type-list ')'
+/// direct-declarator '(' identifier-list[opt] ')'
+/// [GNU] direct-declarator '(' parameter-forward-declarations
+/// parameter-type-list[opt] ')'
+/// [C++] direct-declarator '(' parameter-declaration-clause ')'
+/// cv-qualifier-seq[opt] exception-specification[opt]
+/// [C++] declarator-id
+///
+/// declarator-id: [C++ 8]
+/// '...'[opt] id-expression
+/// '::'[opt] nested-name-specifier[opt] type-name
+///
+/// id-expression: [C++ 5.1]
+/// unqualified-id
+/// qualified-id
+///
+/// unqualified-id: [C++ 5.1]
+/// identifier
+/// operator-function-id
+/// conversion-function-id
+/// '~' class-name
+/// template-id
+///
+void Parser::ParseDirectDeclarator(Declarator &D) {
+ DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
+
+ if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
+ // ParseDeclaratorInternal might already have parsed the scope.
+ if (D.getCXXScopeSpec().isEmpty()) {
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(), true);
+ }
+
+ if (D.getCXXScopeSpec().isValid()) {
+ if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ // Change the declaration context for name lookup, until this function
+ // is exited (and the declarator has been parsed).
+ DeclScopeObj.EnterDeclaratorScope();
+ }
+
+ // C++0x [dcl.fct]p14:
+ // There is a syntactic ambiguity when an ellipsis occurs at the end
+ // of a parameter-declaration-clause without a preceding comma. In
+ // this case, the ellipsis is parsed as part of the
+ // abstract-declarator if the type of the parameter names a template
+ // parameter pack that has not been expanded; otherwise, it is parsed
+ // as part of the parameter-declaration-clause.
+ if (Tok.is(tok::ellipsis) &&
+ !((D.getContext() == Declarator::PrototypeContext ||
+ D.getContext() == Declarator::BlockLiteralContext) &&
+ NextToken().is(tok::r_paren) &&
+ !Actions.containsUnexpandedParameterPacks(D)))
+ D.setEllipsisLoc(ConsumeToken());
+
+ if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+ Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+ // We found something that indicates the start of an unqualified-id.
+ // Parse that unqualified-id.
+ bool AllowConstructorName;
+ if (D.getDeclSpec().hasTypeSpecifier())
+ AllowConstructorName = false;
+ else if (D.getCXXScopeSpec().isSet())
+ AllowConstructorName =
+ (D.getContext() == Declarator::FileContext ||
+ (D.getContext() == Declarator::MemberContext &&
+ D.getDeclSpec().isFriendSpecified()));
+ else
+ AllowConstructorName = (D.getContext() == Declarator::MemberContext);
+
+ if (ParseUnqualifiedId(D.getCXXScopeSpec(),
+ /*EnteringContext=*/true,
+ /*AllowDestructorName=*/true,
+ AllowConstructorName,
+ ParsedType(),
+ D.getName()) ||
+ // Once we're past the identifier, if the scope was bad, mark the
+ // whole declarator bad.
+ D.getCXXScopeSpec().isInvalid()) {
+ D.SetIdentifier(0, Tok.getLocation());
+ D.setInvalidType(true);
+ } else {
+ // Parsed the unqualified-id; update range information and move along.
+ if (D.getSourceRange().getBegin().isInvalid())
+ D.SetRangeBegin(D.getName().getSourceRange().getBegin());
+ D.SetRangeEnd(D.getName().getSourceRange().getEnd());
+ }
+ goto PastIdentifier;
+ }
+ } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
+ assert(!getLang().CPlusPlus &&
+ "There's a C++-specific check for tok::identifier above");
+ assert(Tok.getIdentifierInfo() && "Not an identifier?");
+ D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken();
+ goto PastIdentifier;
+ }
+
+ if (Tok.is(tok::l_paren)) {
+ // direct-declarator: '(' declarator ')'
+ // direct-declarator: '(' attributes declarator ')'
+ // Example: 'char (*X)' or 'int (*XX)(void)'
+ ParseParenDeclarator(D);
+
+ // If the declarator was parenthesized, we entered the declarator
+ // scope when parsing the parenthesized declarator, then exited
+ // the scope already. Re-enter the scope, if we need to.
+ if (D.getCXXScopeSpec().isSet()) {
+ // If there was an error parsing parenthesized declarator, declarator
+ // scope may have been enterred before. Don't do it again.
+ if (!D.isInvalidType() &&
+ Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ // Change the declaration context for name lookup, until this function
+ // is exited (and the declarator has been parsed).
+ DeclScopeObj.EnterDeclaratorScope();
+ }
+ } else if (D.mayOmitIdentifier()) {
+ // This could be something simple like "int" (in which case the declarator
+ // portion is empty), if an abstract-declarator is allowed.
+ D.SetIdentifier(0, Tok.getLocation());
+ } else {
+ if (D.getContext() == Declarator::MemberContext)
+ Diag(Tok, diag::err_expected_member_name_or_semi)
+ << D.getDeclSpec().getSourceRange();
+ else if (getLang().CPlusPlus)
+ Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
+ else
+ Diag(Tok, diag::err_expected_ident_lparen);
+ D.SetIdentifier(0, Tok.getLocation());
+ D.setInvalidType(true);
+ }
+
+ PastIdentifier:
+ assert(D.isPastIdentifier() &&
+ "Haven't past the location of the identifier yet?");
+
+ // Don't parse attributes unless we have an identifier.
+ if (D.getIdentifier())
+ MaybeParseCXX0XAttributes(D);
+
+ while (1) {
+ if (Tok.is(tok::l_paren)) {
+ // The paren may be part of a C++ direct initializer, eg. "int x(1);".
+ // In such a case, check if we actually have a function declarator; if it
+ // is not, the declarator has been fully parsed.
+ if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
+ // When not in file scope, warn for ambiguous function declarators, just
+ // in case the author intended it as a variable definition.
+ bool warnIfAmbiguous = D.getContext() != Declarator::FileContext;
+ if (!isCXXFunctionDeclarator(warnIfAmbiguous))
+ break;
+ }
+ ParsedAttributes attrs;
+ ParseFunctionDeclarator(ConsumeParen(), D, attrs);
+ } else if (Tok.is(tok::l_square)) {
+ ParseBracketDeclarator(D);
+ } else {
+ break;
+ }
+ }
+}
+
+/// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
+/// only called before the identifier, so these are most likely just grouping
+/// parens for precedence. If we find that these are actually function
+/// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
+///
+/// direct-declarator:
+/// '(' declarator ')'
+/// [GNU] '(' attributes declarator ')'
+/// direct-declarator '(' parameter-type-list ')'
+/// direct-declarator '(' identifier-list[opt] ')'
+/// [GNU] direct-declarator '(' parameter-forward-declarations
+/// parameter-type-list[opt] ')'
+///
+void Parser::ParseParenDeclarator(Declarator &D) {
+ SourceLocation StartLoc = ConsumeParen();
+ assert(!D.isPastIdentifier() && "Should be called before passing identifier");
+
+ // Eat any attributes before we look at whether this is a grouping or function
+ // declarator paren. If this is a grouping paren, the attribute applies to
+ // the type being built up, for example:
+ // int (__attribute__(()) *x)(long y)
+ // If this ends up not being a grouping paren, the attribute applies to the
+ // first argument, for example:
+ // int (__attribute__(()) int x)
+ // In either case, we need to eat any attributes to be able to determine what
+ // sort of paren this is.
+ //
+ ParsedAttributes attrs;
+ bool RequiresArg = false;
+ if (Tok.is(tok::kw___attribute)) {
+ ParseGNUAttributes(attrs);
+
+ // We require that the argument list (if this is a non-grouping paren) be
+ // present even if the attribute list was empty.
+ RequiresArg = true;
+ }
+ // Eat any Microsoft extensions.
+ if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
+ Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) ||
+ Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) {
+ ParseMicrosoftTypeAttributes(attrs);
+ }
+ // Eat any Borland extensions.
+ if (Tok.is(tok::kw___pascal))
+ ParseBorlandTypeAttributes(attrs);
+
+ // If we haven't past the identifier yet (or where the identifier would be
+ // stored, if this is an abstract declarator), then this is probably just
+ // grouping parens. However, if this could be an abstract-declarator, then
+ // this could also be the start of function arguments (consider 'void()').
+ bool isGrouping;
+
+ if (!D.mayOmitIdentifier()) {
+ // If this can't be an abstract-declarator, this *must* be a grouping
+ // paren, because we haven't seen the identifier yet.
+ isGrouping = true;
+ } else if (Tok.is(tok::r_paren) || // 'int()' is a function.
+ (getLang().CPlusPlus && Tok.is(tok::ellipsis)) || // C++ int(...)
+ isDeclarationSpecifier()) { // 'int(int)' is a function.
+ // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
+ // considered to be a type, not a K&R identifier-list.
+ isGrouping = false;
+ } else {
+ // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
+ isGrouping = true;
+ }
+
+ // If this is a grouping paren, handle:
+ // direct-declarator: '(' declarator ')'
+ // direct-declarator: '(' attributes declarator ')'
+ if (isGrouping) {
+ bool hadGroupingParens = D.hasGroupingParens();
+ D.setGroupingParens(true);
+ if (!attrs.empty())
+ D.addAttributes(attrs.getList(), SourceLocation());
+
+ ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
+ // Match the ')'.
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc);
+ D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc);
+
+ D.setGroupingParens(hadGroupingParens);
+ return;
+ }
+
+ // Okay, if this wasn't a grouping paren, it must be the start of a function
+ // argument list. Recognize that this declarator will never have an
+ // identifier (and remember where it would have been), then call into
+ // ParseFunctionDeclarator to handle of argument list.
+ D.SetIdentifier(0, Tok.getLocation());
+
+ ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg);
+}
+
+/// ParseFunctionDeclarator - We are after the identifier and have parsed the
+/// declarator D up to a paren, which indicates that we are parsing function
+/// arguments.
+///
+/// If AttrList is non-null, then the caller parsed those arguments immediately
+/// after the open paren - they should be considered to be the first argument of
+/// a parameter. If RequiresArg is true, then the first argument of the
+/// function is required to be present and required to not be an identifier
+/// list.
+///
+/// This method also handles this portion of the grammar:
+/// parameter-type-list: [C99 6.7.5]
+/// parameter-list
+/// parameter-list ',' '...'
+/// [C++] parameter-list '...'
+///
+/// parameter-list: [C99 6.7.5]
+/// parameter-declaration
+/// parameter-list ',' parameter-declaration
+///
+/// parameter-declaration: [C99 6.7.5]
+/// declaration-specifiers declarator
+/// [C++] declaration-specifiers declarator '=' assignment-expression
+/// [GNU] declaration-specifiers declarator attributes
+/// declaration-specifiers abstract-declarator[opt]
+/// [C++] declaration-specifiers abstract-declarator[opt]
+/// '=' assignment-expression
+/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
+///
+/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]",
+/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]".
+///
+void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
+ ParsedAttributes &attrs,
+ bool RequiresArg) {
+ // lparen is already consumed!
+ assert(D.isPastIdentifier() && "Should not call before identifier!");
+
+ ParsedType TrailingReturnType;
+
+ // This parameter list may be empty.
+ if (Tok.is(tok::r_paren)) {
+ if (RequiresArg)
+ Diag(Tok, diag::err_argument_required_after_attribute);
+
+ SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'.
+ SourceLocation EndLoc = RParenLoc;
+
+ // cv-qualifier-seq[opt].
+ DeclSpec DS;
+ SourceLocation RefQualifierLoc;
+ bool RefQualifierIsLValueRef = true;
+ bool hasExceptionSpec = false;
+ SourceLocation ThrowLoc;
+ bool hasAnyExceptionSpec = false;
+ llvm::SmallVector<ParsedType, 2> Exceptions;
+ llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+ if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
+ ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+ if (!DS.getSourceRange().getEnd().isInvalid())
+ EndLoc = DS.getSourceRange().getEnd();
+
+ // Parse ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ EndLoc = RefQualifierLoc;
+ }
+
+ // Parse exception-specification[opt].
+ if (Tok.is(tok::kw_throw)) {
+ hasExceptionSpec = true;
+ ThrowLoc = Tok.getLocation();
+ ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
+ hasAnyExceptionSpec);
+ assert(Exceptions.size() == ExceptionRanges.size() &&
+ "Produced different number of exception types and ranges.");
+ }
+
+ // Parse trailing-return-type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
+ TrailingReturnType = ParseTrailingReturnType().get();
+ }
+ }
+
+ // Remember that we parsed a function type, and remember the attributes.
+ // int() -> no prototype, no '...'.
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*prototype*/getLang().CPlusPlus,
+ /*variadic*/ false,
+ SourceLocation(),
+ /*arglist*/ 0, 0,
+ DS.getTypeQualifiers(),
+ RefQualifierIsLValueRef,
+ RefQualifierLoc,
+ hasExceptionSpec, ThrowLoc,
+ hasAnyExceptionSpec,
+ Exceptions.data(),
+ ExceptionRanges.data(),
+ Exceptions.size(),
+ LParenLoc, RParenLoc, D,
+ TrailingReturnType),
+ EndLoc);
+ return;
+ }
+
+ // Alternatively, this parameter list may be an identifier list form for a
+ // K&R-style function: void foo(a,b,c)
+ if (!getLang().CPlusPlus && Tok.is(tok::identifier)
+ && !TryAltiVecVectorToken()) {
+ if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) {
+ // K&R identifier lists can't have typedefs as identifiers, per
+ // C99 6.7.5.3p11.
+ if (RequiresArg)
+ Diag(Tok, diag::err_argument_required_after_attribute);
+
+ // Identifier list. Note that '(' identifier-list ')' is only allowed for
+ // normal declarators, not for abstract-declarators. Get the first
+ // identifier.
+ Token FirstTok = Tok;
+ ConsumeToken(); // eat the first identifier.
+
+ // Identifier lists follow a really simple grammar: the identifiers can
+ // be followed *only* by a ", moreidentifiers" or ")". However, K&R
+ // identifier lists are really rare in the brave new modern world, and it
+ // is very common for someone to typo a type in a non-k&r style list. If
+ // we are presented with something like: "void foo(intptr x, float y)",
+ // we don't want to start parsing the function declarator as though it is
+ // a K&R style declarator just because intptr is an invalid type.
+ //
+ // To handle this, we check to see if the token after the first identifier
+ // is a "," or ")". Only if so, do we parse it as an identifier list.
+ if (Tok.is(tok::comma) || Tok.is(tok::r_paren))
+ return ParseFunctionDeclaratorIdentifierList(LParenLoc,
+ FirstTok.getIdentifierInfo(),
+ FirstTok.getLocation(), D);
+
+ // If we get here, the code is invalid. Push the first identifier back
+ // into the token stream and parse the first argument as an (invalid)
+ // normal argument declarator.
+ PP.EnterToken(Tok);
+ Tok = FirstTok;
+ }
+ }
+
+ // Finally, a normal, non-empty parameter type list.
+
+ // Build up an array of information about the parsed arguments.
+ llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+
+ // Enter function-declaration scope, limiting any declarators to the
+ // function prototype scope, including parameter declarators.
+ ParseScope PrototypeScope(this,
+ Scope::FunctionPrototypeScope|Scope::DeclScope);
+
+ bool IsVariadic = false;
+ SourceLocation EllipsisLoc;
+ while (1) {
+ if (Tok.is(tok::ellipsis)) {
+ IsVariadic = true;
+ EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+ break;
+ }
+
+ // Parse the declaration-specifiers.
+ // Just use the ParsingDeclaration "scope" of the declarator.
+ DeclSpec DS;
+
+ // Skip any Microsoft attributes before a param.
+ if (getLang().Microsoft && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(DS.getAttributes());
+
+ SourceLocation DSStart = Tok.getLocation();
+
+ // If the caller parsed attributes for the first argument, add them now.
+ // Take them so that we only apply the attributes to the first parameter.
+ DS.takeAttributesFrom(attrs);
+
+ ParseDeclarationSpecifiers(DS);
+
+ // Parse the declarator. This is "PrototypeContext", because we must
+ // accept either 'declarator' or 'abstract-declarator' here.
+ Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ ParseDeclarator(ParmDecl);
+
+ // Parse GNU attributes, if present.
+ MaybeParseGNUAttributes(ParmDecl);
+
+ // Remember this parsed parameter in ParamInfo.
+ IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+
+ // DefArgToks is used when the parsing of default arguments needs
+ // to be delayed.
+ CachedTokens *DefArgToks = 0;
+
+ // If no parameter was specified, verify that *something* was specified,
+ // otherwise we have a missing type and identifier.
+ if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
+ ParmDecl.getNumTypeObjects() == 0) {
+ // Completely missing, emit error.
+ Diag(DSStart, diag::err_missing_param);
+ } else {
+ // Otherwise, we have something. Add it and let semantic analysis try
+ // to grok it and add the result to the ParamInfo we are building.
+
+ // Inform the actions module about the parameter declarator, so it gets
+ // added to the current scope.
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+
+ // Parse the default argument, if any. We parse the default
+ // arguments in all dialects; the semantic analysis in
+ // ActOnParamDefaultArgument will reject the default argument in
+ // C.
+ if (Tok.is(tok::equal)) {
+ SourceLocation EqualLoc = Tok.getLocation();
+
+ // Parse the default argument
+ if (D.getContext() == Declarator::MemberContext) {
+ // If we're inside a class definition, cache the tokens
+ // corresponding to the default argument. We'll actually parse
+ // them when we see the end of the class definition.
+ // FIXME: Templates will require something similar.
+ // FIXME: Can we use a smart pointer for Toks?
+ DefArgToks = new CachedTokens;
+
+ if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
+ /*StopAtSemi=*/true,
+ /*ConsumeFinalToken=*/false)) {
+ delete DefArgToks;
+ DefArgToks = 0;
+ Actions.ActOnParamDefaultArgumentError(Param);
+ } else {
+ // Mark the end of the default argument so that we know when to
+ // stop when we parse it later on.
+ Token DefArgEnd;
+ DefArgEnd.startToken();
+ DefArgEnd.setKind(tok::cxx_defaultarg_end);
+ DefArgEnd.setLocation(Tok.getLocation());
+ DefArgToks->push_back(DefArgEnd);
+ Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
+ (*DefArgToks)[1].getLocation());
+ }
+ } else {
+ // Consume the '='.
+ ConsumeToken();
+
+ // The argument isn't actually potentially evaluated unless it is
+ // used.
+ EnterExpressionEvaluationContext Eval(Actions,
+ Sema::PotentiallyEvaluatedIfUsed);
+
+ ExprResult DefArgResult(ParseAssignmentExpression());
+ if (DefArgResult.isInvalid()) {
+ Actions.ActOnParamDefaultArgumentError(Param);
+ SkipUntil(tok::comma, tok::r_paren, true, true);
+ } else {
+ // Inform the actions module about the default argument
+ Actions.ActOnParamDefaultArgument(Param, EqualLoc,
+ DefArgResult.take());
+ }
+ }
+ }
+
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+ ParmDecl.getIdentifierLoc(), Param,
+ DefArgToks));
+ }
+
+ // If the next token is a comma, consume it and keep reading arguments.
+ if (Tok.isNot(tok::comma)) {
+ if (Tok.is(tok::ellipsis)) {
+ IsVariadic = true;
+ EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+
+ if (!getLang().CPlusPlus) {
+ // We have ellipsis without a preceding ',', which is ill-formed
+ // in C. Complain and provide the fix.
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");
+ }
+ }
+
+ break;
+ }
+
+ // Consume the comma.
+ ConsumeToken();
+ }
+
+ // If we have the closing ')', eat it.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ SourceLocation EndLoc = RParenLoc;
+
+ DeclSpec DS;
+ SourceLocation RefQualifierLoc;
+ bool RefQualifierIsLValueRef = true;
+ bool hasExceptionSpec = false;
+ SourceLocation ThrowLoc;
+ bool hasAnyExceptionSpec = false;
+ llvm::SmallVector<ParsedType, 2> Exceptions;
+ llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+
+ if (getLang().CPlusPlus) {
+ MaybeParseCXX0XAttributes(attrs);
+
+ // Parse cv-qualifier-seq[opt].
+ ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+ if (!DS.getSourceRange().getEnd().isInvalid())
+ EndLoc = DS.getSourceRange().getEnd();
+
+ // Parse ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_ref_qualifier);
+
+ RefQualifierIsLValueRef = Tok.is(tok::amp);
+ RefQualifierLoc = ConsumeToken();
+ EndLoc = RefQualifierLoc;
+ }
+
+ // Parse exception-specification[opt].
+ if (Tok.is(tok::kw_throw)) {
+ hasExceptionSpec = true;
+ ThrowLoc = Tok.getLocation();
+ ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
+ hasAnyExceptionSpec);
+ assert(Exceptions.size() == ExceptionRanges.size() &&
+ "Produced different number of exception types and ranges.");
+ }
+
+ // Parse trailing-return-type.
+ if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
+ TrailingReturnType = ParseTrailingReturnType().get();
+ }
+ }
+
+ // FIXME: We should leave the prototype scope before parsing the exception
+ // specification, and then reenter it when parsing the trailing return type.
+
+ // Leave prototype scope.
+ PrototypeScope.Exit();
+
+ // Remember that we parsed a function type, and remember the attributes.
+ D.AddTypeInfo(DeclaratorChunk::getFunction(attrs,
+ /*proto*/true, IsVariadic,
+ EllipsisLoc,
+ ParamInfo.data(), ParamInfo.size(),
+ DS.getTypeQualifiers(),
+ RefQualifierIsLValueRef,
+ RefQualifierLoc,
+ hasExceptionSpec, ThrowLoc,
+ hasAnyExceptionSpec,
+ Exceptions.data(),
+ ExceptionRanges.data(),
+ Exceptions.size(),
+ LParenLoc, RParenLoc, D,
+ TrailingReturnType),
+ EndLoc);
+}
+
+/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
+/// we found a K&R-style identifier list instead of a type argument list. The
+/// first identifier has already been consumed, and the current token is the
+/// token right after it.
+///
+/// identifier-list: [C99 6.7.5]
+/// identifier
+/// identifier-list ',' identifier
+///
+void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
+ IdentifierInfo *FirstIdent,
+ SourceLocation FirstIdentLoc,
+ Declarator &D) {
+ // Build up an array of information about the parsed arguments.
+ llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+ llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
+
+ // If there was no identifier specified for the declarator, either we are in
+ // an abstract-declarator, or we are in a parameter declarator which was found
+ // to be abstract. In abstract-declarators, identifier lists are not valid:
+ // diagnose this.
+ if (!D.getIdentifier())
+ Diag(FirstIdentLoc, diag::ext_ident_list_in_param);
+
+ // The first identifier was already read, and is known to be the first
+ // identifier in the list. Remember this identifier in ParamInfo.
+ ParamsSoFar.insert(FirstIdent);
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(FirstIdent, FirstIdentLoc, 0));
+
+ while (Tok.is(tok::comma)) {
+ // Eat the comma.
+ ConsumeToken();
+
+ // If this isn't an identifier, report the error and skip until ')'.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ IdentifierInfo *ParmII = Tok.getIdentifierInfo();
+
+ // Reject 'typedef int y; int test(x, y)', but continue parsing.
+ if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope()))
+ Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
+
+ // Verify that the argument identifier has not already been mentioned.
+ if (!ParamsSoFar.insert(ParmII)) {
+ Diag(Tok, diag::err_param_redefinition) << ParmII;
+ } else {
+ // Remember this identifier in ParamInfo.
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+ Tok.getLocation(),
+ 0));
+ }
+
+ // Eat the identifier.
+ ConsumeToken();
+ }
+
+ // If we have the closing ')', eat it and we're done.
+ SourceLocation RLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ // Remember that we parsed a function type, and remember the attributes. This
+ // function type is always a K&R style function type, which is not varargs and
+ // has no prototype.
+ D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ /*proto*/false, /*varargs*/false,
+ SourceLocation(),
+ &ParamInfo[0], ParamInfo.size(),
+ /*TypeQuals*/0,
+ true, SourceLocation(),
+ /*exception*/false,
+ SourceLocation(), false, 0, 0, 0,
+ LParenLoc, RLoc, D),
+ RLoc);
+}
+
+/// [C90] direct-declarator '[' constant-expression[opt] ']'
+/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
+/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
+/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
+/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
+void Parser::ParseBracketDeclarator(Declarator &D) {
+ SourceLocation StartLoc = ConsumeBracket();
+
+ // C array syntax has many features, but by-far the most common is [] and [4].
+ // This code does a fast path to handle some of the most obvious cases.
+ if (Tok.getKind() == tok::r_square) {
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ // Remember that we parsed the empty array type.
+ ExprResult NumElements;
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, false, 0,
+ StartLoc, EndLoc),
+ EndLoc);
+ return;
+ } else if (Tok.getKind() == tok::numeric_constant &&
+ GetLookAheadToken(1).is(tok::r_square)) {
+ // [4] is very common. Parse the numeric constant expression.
+ ExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
+ ConsumeToken();
+
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ // Remember that we parsed a array type, and remember its features.
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, 0,
+ ExprRes.release(),
+ StartLoc, EndLoc),
+ EndLoc);
+ return;
+ }
+
+ // If valid, this location is the position where we read the 'static' keyword.
+ SourceLocation StaticLoc;
+ if (Tok.is(tok::kw_static))
+ StaticLoc = ConsumeToken();
+
+ // If there is a type-qualifier-list, read it now.
+ // Type qualifiers in an array subscript are a C99 feature.
+ DeclSpec DS;
+ ParseTypeQualifierListOpt(DS, false /*no attributes*/);
+
+ // If we haven't already read 'static', check to see if there is one after the
+ // type-qualifier-list.
+ if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
+ StaticLoc = ConsumeToken();
+
+ // Handle "direct-declarator [ type-qual-list[opt] * ]".
+ bool isStar = false;
+ ExprResult NumElements;
+
+ // Handle the case where we have '[*]' as the array size. However, a leading
+ // star could be the start of an expression, for example 'X[*p + 4]'. Verify
+ // the the token after the star is a ']'. Since stars in arrays are
+ // infrequent, use of lookahead is not costly here.
+ if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {
+ ConsumeToken(); // Eat the '*'.
+
+ if (StaticLoc.isValid()) {
+ Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
+ StaticLoc = SourceLocation(); // Drop the static.
+ }
+ isStar = true;
+ } else if (Tok.isNot(tok::r_square)) {
+ // Note, in C89, this production uses the constant-expr production instead
+ // of assignment-expr. The only difference is that assignment-expr allows
+ // things like '=' and '*='. Sema rejects these in C89 mode because they
+ // are not i-c-e's, so we don't need to distinguish between the two here.
+
+ // Parse the constant-expression or assignment-expression now (depending
+ // on dialect).
+ if (getLang().CPlusPlus)
+ NumElements = ParseConstantExpression();
+ else
+ NumElements = ParseAssignmentExpression();
+ }
+
+ // If there was an error parsing the assignment-expression, recover.
+ if (NumElements.isInvalid()) {
+ D.setInvalidType(true);
+ // If the expression was invalid, skip it.
+ SkipUntil(tok::r_square);
+ return;
+ }
+
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+
+ ParsedAttributes attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ // Remember that we parsed a array type, and remember its features.
+ D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), attrs,
+ StaticLoc.isValid(), isStar,
+ NumElements.release(),
+ StartLoc, EndLoc),
+ EndLoc);
+}
+
+/// [GNU] typeof-specifier:
+/// typeof ( expressions )
+/// typeof ( type-name )
+/// [GNU/C++] typeof unary-expression
+///
+void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
+ assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier");
+ Token OpTok = Tok;
+ SourceLocation StartLoc = ConsumeToken();
+
+ const bool hasParens = Tok.is(tok::l_paren);
+
+ bool isCastExpr;
+ ParsedType CastTy;
+ SourceRange CastRange;
+ ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+ isCastExpr,
+ CastTy,
+ CastRange);
+ if (hasParens)
+ DS.setTypeofParensRange(CastRange);
+
+ if (CastRange.getEnd().isInvalid())
+ // FIXME: Not accurate, the range gets one token more than it should.
+ DS.SetRangeEnd(Tok.getLocation());
+ else
+ DS.SetRangeEnd(CastRange.getEnd());
+
+ if (isCastExpr) {
+ if (!CastTy) {
+ DS.SetTypeSpecError();
+ return;
+ }
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ // Check for duplicate type specifiers (e.g. "int typeof(int)").
+ if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
+ DiagID, CastTy))
+ Diag(StartLoc, DiagID) << PrevSpec;
+ return;
+ }
+
+ // If we get here, the operand to the typeof was an expresion.
+ if (Operand.isInvalid()) {
+ DS.SetTypeSpecError();
+ return;
+ }
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ // Check for duplicate type specifiers (e.g. "int typeof(int)").
+ if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
+ DiagID, Operand.get()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+}
+
+
+/// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
+/// from TryAltiVecVectorToken.
+bool Parser::TryAltiVecVectorTokenOutOfLine() {
+ Token Next = NextToken();
+ switch (Next.getKind()) {
+ default: return false;
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw___pixel:
+ Tok.setKind(tok::kw___vector);
+ return true;
+ case tok::identifier:
+ if (Next.getIdentifierInfo() == Ident_pixel) {
+ Tok.setKind(tok::kw___vector);
+ return true;
+ }
+ return false;
+ }
+}
+
+bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid) {
+ if (Tok.getIdentifierInfo() == Ident_vector) {
+ Token Next = NextToken();
+ switch (Next.getKind()) {
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw___pixel:
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ return true;
+ case tok::identifier:
+ if (Next.getIdentifierInfo() == Ident_pixel) {
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ } else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
+ DS.isTypeAltiVecVector()) {
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ return true;
+ }
+ return false;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
new file mode 100644
index 0000000..b3ad25b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -0,0 +1,2328 @@
+//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++ Declaration portions of the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "RAIIObjectsForParser.h"
+using namespace clang;
+
+/// ParseNamespace - We know that the current token is a namespace keyword. This
+/// may either be a top level namespace or a block-level namespace alias. If
+/// there was an inline keyword, it has already been parsed.
+///
+/// namespace-definition: [C++ 7.3: basic.namespace]
+/// named-namespace-definition
+/// unnamed-namespace-definition
+///
+/// unnamed-namespace-definition:
+/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
+///
+/// named-namespace-definition:
+/// original-namespace-definition
+/// extension-namespace-definition
+///
+/// original-namespace-definition:
+/// 'inline'[opt] 'namespace' identifier attributes[opt]
+/// '{' namespace-body '}'
+///
+/// extension-namespace-definition:
+/// 'inline'[opt] 'namespace' original-namespace-name
+/// '{' namespace-body '}'
+///
+/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
+/// 'namespace' identifier '=' qualified-namespace-specifier ';'
+///
+Decl *Parser::ParseNamespace(unsigned Context,
+ SourceLocation &DeclEnd,
+ SourceLocation InlineLoc) {
+ assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
+ SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteNamespaceDecl(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ SourceLocation IdentLoc;
+ IdentifierInfo *Ident = 0;
+
+ Token attrTok;
+
+ if (Tok.is(tok::identifier)) {
+ Ident = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken(); // eat the identifier.
+ }
+
+ // Read label attributes, if present.
+ ParsedAttributes attrs;
+ if (Tok.is(tok::kw___attribute)) {
+ attrTok = Tok;
+
+ // FIXME: save these somewhere.
+ ParseGNUAttributes(attrs);
+ }
+
+ if (Tok.is(tok::equal)) {
+ if (!attrs.empty())
+ Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+ if (InlineLoc.isValid())
+ Diag(InlineLoc, diag::err_inline_namespace_alias)
+ << FixItHint::CreateRemoval(InlineLoc);
+
+ return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+ }
+
+ if (Tok.isNot(tok::l_brace)) {
+ Diag(Tok, Ident ? diag::err_expected_lbrace :
+ diag::err_expected_ident_lbrace);
+ return 0;
+ }
+
+ SourceLocation LBrace = ConsumeBrace();
+
+ if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
+ getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||
+ getCurScope()->getFnParent()) {
+ Diag(LBrace, diag::err_namespace_nonnamespace_scope);
+ SkipUntil(tok::r_brace, false);
+ return 0;
+ }
+
+ // If we're still good, complain about inline namespaces in non-C++0x now.
+ if (!getLang().CPlusPlus0x && InlineLoc.isValid())
+ Diag(InlineLoc, diag::ext_inline_namespace);
+
+ // Enter a scope for the namespace.
+ ParseScope NamespaceScope(this, Scope::DeclScope);
+
+ Decl *NamespcDecl =
+ Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, IdentLoc, Ident,
+ LBrace, attrs.getList());
+
+ PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
+ "parsing namespace");
+
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
+ }
+
+ // Leave the namespace scope.
+ NamespaceScope.Exit();
+
+ SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);
+ Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
+
+ DeclEnd = RBraceLoc;
+ return NamespcDecl;
+}
+
+/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
+/// alias definition.
+///
+Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ SourceLocation &DeclEnd) {
+ assert(Tok.is(tok::equal) && "Not equal token");
+
+ ConsumeToken(); // eat the '='.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ CXXScopeSpec SS;
+ // Parse (optional) nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+ if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_namespace_name);
+ // Skip to end of the definition and eat the ';'.
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ // Parse identifier.
+ IdentifierInfo *Ident = Tok.getIdentifierInfo();
+ SourceLocation IdentLoc = ConsumeToken();
+
+ // Eat the ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
+ "", tok::semi);
+
+ return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias,
+ SS, IdentLoc, Ident);
+}
+
+/// ParseLinkage - We know that the current token is a string_literal
+/// and just before that, that extern was seen.
+///
+/// linkage-specification: [C++ 7.5p2: dcl.link]
+/// 'extern' string-literal '{' declaration-seq[opt] '}'
+/// 'extern' string-literal declaration
+///
+Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
+ assert(Tok.is(tok::string_literal) && "Not a string literal!");
+ llvm::SmallString<8> LangBuffer;
+ bool Invalid = false;
+ llvm::StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid);
+ if (Invalid)
+ return 0;
+
+ SourceLocation Loc = ConsumeStringToken();
+
+ ParseScope LinkageScope(this, Scope::DeclScope);
+ Decl *LinkageSpec
+ = Actions.ActOnStartLinkageSpecification(getCurScope(),
+ /*FIXME: */SourceLocation(),
+ Loc, Lang,
+ Tok.is(tok::l_brace)? Tok.getLocation()
+ : SourceLocation());
+
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+
+ if (Tok.isNot(tok::l_brace)) {
+ DS.setExternInLinkageSpec(true);
+ ParseExternalDeclaration(attrs, &DS);
+ return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
+ SourceLocation());
+ }
+
+ DS.abort();
+
+ ProhibitAttributes(attrs);
+
+ SourceLocation LBrace = ConsumeBrace();
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
+ }
+
+ SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+ return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
+ RBrace);
+}
+
+/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
+/// using-directive. Assumes that current token is 'using'.
+Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs) {
+ assert(Tok.is(tok::kw_using) && "Not using token");
+
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteUsing(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ // 'using namespace' means this is a using-directive.
+ if (Tok.is(tok::kw_namespace)) {
+ // Template parameters are always an error here.
+ if (TemplateInfo.Kind) {
+ SourceRange R = TemplateInfo.getSourceRange();
+ Diag(UsingLoc, diag::err_templated_using_directive)
+ << R << FixItHint::CreateRemoval(R);
+ }
+
+ return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
+ }
+
+ // Otherwise, it must be a using-declaration.
+
+ // Using declarations can't have attributes.
+ ProhibitAttributes(attrs);
+
+ return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd);
+}
+
+/// ParseUsingDirective - Parse C++ using-directive, assumes
+/// that current token is 'namespace' and 'using' was already parsed.
+///
+/// using-directive: [C++ 7.3.p4: namespace.udir]
+/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
+/// namespace-name ;
+/// [GNU] using-directive:
+/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
+/// namespace-name attributes[opt] ;
+///
+Decl *Parser::ParseUsingDirective(unsigned Context,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ ParsedAttributes &attrs) {
+ assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
+
+ // Eat 'namespace'.
+ SourceLocation NamespcLoc = ConsumeToken();
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteUsingDirective(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ CXXScopeSpec SS;
+ // Parse (optional) nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+ IdentifierInfo *NamespcName = 0;
+ SourceLocation IdentLoc = SourceLocation();
+
+ // Parse namespace-name.
+ if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_namespace_name);
+ // If there was invalid namespace name, skip to end of decl, and eat ';'.
+ SkipUntil(tok::semi);
+ // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
+ return 0;
+ }
+
+ // Parse identifier.
+ NamespcName = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken();
+
+ // Parse (optional) attributes (most likely GNU strong-using extension).
+ bool GNUAttr = false;
+ if (Tok.is(tok::kw___attribute)) {
+ GNUAttr = true;
+ ParseGNUAttributes(attrs);
+ }
+
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi,
+ GNUAttr ? diag::err_expected_semi_after_attribute_list
+ : diag::err_expected_semi_after_namespace_name,
+ "", tok::semi);
+
+ return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
+ IdentLoc, NamespcName, attrs.getList());
+}
+
+/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
+/// 'using' was already seen.
+///
+/// using-declaration: [C++ 7.3.p3: namespace.udecl]
+/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
+/// unqualified-id
+/// 'using' :: unqualified-id
+///
+Decl *Parser::ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
+ CXXScopeSpec SS;
+ SourceLocation TypenameLoc;
+ bool IsTypeName;
+
+ // TODO: in C++0x, if we have template parameters this must be a
+ // template alias:
+ // template <...> using id = type;
+
+ // Ignore optional 'typename'.
+ // FIXME: This is wrong; we should parse this as a typename-specifier.
+ if (Tok.is(tok::kw_typename)) {
+ TypenameLoc = Tok.getLocation();
+ ConsumeToken();
+ IsTypeName = true;
+ }
+ else
+ IsTypeName = false;
+
+ // Parse nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+ // Check nested-name specifier.
+ if (SS.isInvalid()) {
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ // Parse the unqualified-id. We allow parsing of both constructor and
+ // destructor names and allow the action module to diagnose any semantic
+ // errors.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/true,
+ ParsedType(),
+ Name)) {
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ // Parse (optional) attributes (most likely GNU strong-using extension).
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ !attrs.empty() ? "attributes list" : "using declaration",
+ tok::semi);
+
+ // Diagnose an attempt to declare a templated using-declaration.
+ if (TemplateInfo.Kind) {
+ SourceRange R = TemplateInfo.getSourceRange();
+ Diag(UsingLoc, diag::err_templated_using_declaration)
+ << R << FixItHint::CreateRemoval(R);
+
+ // Unfortunately, we have to bail out instead of recovering by
+ // ignoring the parameters, just in case the nested name specifier
+ // depends on the parameters.
+ return 0;
+ }
+
+ return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
+ Name, attrs.getList(),
+ IsTypeName, TypenameLoc);
+}
+
+/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
+///
+/// static_assert-declaration:
+/// static_assert ( constant-expression , string-literal ) ;
+///
+Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
+ assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
+ SourceLocation StaticAssertLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen);
+ return 0;
+ }
+
+ SourceLocation LParenLoc = ConsumeParen();
+
+ ExprResult AssertExpr(ParseConstantExpression());
+ if (AssertExpr.isInvalid()) {
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
+ return 0;
+
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(Tok, diag::err_expected_string_literal);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ ExprResult AssertMessage(ParseStringLiteralExpression());
+ if (AssertMessage.isInvalid())
+ return 0;
+
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);
+
+ return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
+ AssertExpr.take(),
+ AssertMessage.take());
+}
+
+/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
+///
+/// 'decltype' ( expression )
+///
+void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
+ assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
+
+ SourceLocation StartLoc = ConsumeToken();
+ SourceLocation LParenLoc = Tok.getLocation();
+
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "decltype")) {
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ // Parse the expression
+
+ // C++0x [dcl.type.simple]p4:
+ // The operand of the decltype specifier is an unevaluated operand.
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::Unevaluated);
+ ExprResult Result = ParseExpression();
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ // Match the ')'
+ SourceLocation RParenLoc;
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (RParenLoc.isInvalid())
+ return;
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ // Check for duplicate type specifiers (e.g. "int decltype(a)").
+ if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
+ DiagID, Result.release()))
+ Diag(StartLoc, DiagID) << PrevSpec;
+}
+
+/// ParseClassName - Parse a C++ class-name, which names a class. Note
+/// that we only check that the result names a type; semantic analysis
+/// will need to verify that the type names a class. The result is
+/// either a type or NULL, depending on whether a type name was
+/// found.
+///
+/// class-name: [C++ 9.1]
+/// identifier
+/// simple-template-id
+///
+Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
+ CXXScopeSpec *SS) {
+ // Check whether we have a template-id that names a type.
+ if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) {
+ AnnotateTemplateIdTokenAsType(SS);
+
+ assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
+ ParsedType Type = getTypeAnnotation(Tok);
+ EndLocation = Tok.getAnnotationEndLoc();
+ ConsumeToken();
+
+ if (Type)
+ return Type;
+ return true;
+ }
+
+ // Fall through to produce an error below.
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_class_name);
+ return true;
+ }
+
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ // It looks the user intended to write a template-id here, but the
+ // template-name was wrong. Try to fix that.
+ TemplateNameKind TNK = TNK_Type_template;
+ TemplateTy Template;
+ if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(),
+ SS, Template, TNK)) {
+ Diag(IdLoc, diag::err_unknown_template_name)
+ << Id;
+ }
+
+ if (!Template)
+ return true;
+
+ // Form the template name
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Id, IdLoc);
+
+ // Parse the full template-id, then turn it into a type.
+ if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
+ SourceLocation(), true))
+ return true;
+ if (TNK == TNK_Dependent_template_name)
+ AnnotateTemplateIdTokenAsType(SS);
+
+ // If we didn't end up with a typename token, there's nothing more we
+ // can do.
+ if (Tok.isNot(tok::annot_typename))
+ return true;
+
+ // Retrieve the type from the annotation token, consume that token, and
+ // return.
+ EndLocation = Tok.getAnnotationEndLoc();
+ ParsedType Type = getTypeAnnotation(Tok);
+ ConsumeToken();
+ return Type;
+ }
+
+ // We have an identifier; check whether it is actually a type.
+ ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), SS, true);
+ if (!Type) {
+ Diag(IdLoc, diag::err_expected_class_name);
+ return true;
+ }
+
+ // Consume the identifier.
+ EndLocation = IdLoc;
+
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(IdLoc);
+ DS.SetRangeEnd(EndLocation);
+ DS.getTypeSpecScope() = *SS;
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+}
+
+/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
+/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
+/// until we reach the start of a definition or see a token that
+/// cannot start a definition. If SuppressDeclarations is true, we do know.
+///
+/// class-specifier: [C++ class]
+/// class-head '{' member-specification[opt] '}'
+/// class-head '{' member-specification[opt] '}' attributes[opt]
+/// class-head:
+/// class-key identifier[opt] base-clause[opt]
+/// class-key nested-name-specifier identifier base-clause[opt]
+/// class-key nested-name-specifier[opt] simple-template-id
+/// base-clause[opt]
+/// [GNU] class-key attributes[opt] identifier[opt] base-clause[opt]
+/// [GNU] class-key attributes[opt] nested-name-specifier
+/// identifier base-clause[opt]
+/// [GNU] class-key attributes[opt] nested-name-specifier[opt]
+/// simple-template-id base-clause[opt]
+/// class-key:
+/// 'class'
+/// 'struct'
+/// 'union'
+///
+/// elaborated-type-specifier: [C++ dcl.type.elab]
+/// class-key ::[opt] nested-name-specifier[opt] identifier
+/// class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
+/// simple-template-id
+///
+/// Note that the C++ class-specifier and elaborated-type-specifier,
+/// together, subsume the C99 struct-or-union-specifier:
+///
+/// struct-or-union-specifier: [C99 6.7.2.1]
+/// struct-or-union identifier[opt] '{' struct-contents '}'
+/// struct-or-union identifier
+/// [GNU] struct-or-union attributes[opt] identifier[opt] '{' struct-contents
+/// '}' attributes[opt]
+/// [GNU] struct-or-union attributes[opt] identifier
+/// struct-or-union:
+/// 'struct'
+/// 'union'
+void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
+ SourceLocation StartLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, bool SuppressDeclarations){
+ DeclSpec::TST TagType;
+ if (TagTokKind == tok::kw_struct)
+ TagType = DeclSpec::TST_struct;
+ else if (TagTokKind == tok::kw_class)
+ TagType = DeclSpec::TST_class;
+ else {
+ assert(TagTokKind == tok::kw_union && "Not a class specifier");
+ TagType = DeclSpec::TST_union;
+ }
+
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a struct, class, or union name.
+ Actions.CodeCompleteTag(getCurScope(), TagType);
+ ConsumeCodeCompletionToken();
+ }
+
+ // C++03 [temp.explicit] 14.7.2/8:
+ // The usual access checking rules do not apply to names used to specify
+ // explicit instantiations.
+ //
+ // As an extension we do not perform access checking on the names used to
+ // specify explicit specializations either. This is important to allow
+ // specializing traits classes for private types.
+ bool SuppressingAccessChecks = false;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) {
+ Actions.ActOnStartSuppressingAccessChecks();
+ SuppressingAccessChecks = true;
+ }
+
+ ParsedAttributes attrs;
+ // If attributes exist after tag, parse them.
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs);
+
+ // If declspecs exist after tag, parse them.
+ while (Tok.is(tok::kw___declspec))
+ ParseMicrosoftDeclSpec(attrs);
+
+ // If C++0x attributes exist here, parse them.
+ // FIXME: Are we consistent with the ordering of parsing of different
+ // styles of attributes?
+ MaybeParseCXX0XAttributes(attrs);
+
+ if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
+ // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
+ // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
+ // token sequence "struct __is_pod", make __is_pod into a normal
+ // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+ // properly.
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ }
+
+ if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
+ // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
+ // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
+ // token sequence "struct __is_empty", make __is_empty into a normal
+ // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+ // properly.
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ }
+
+ // Parse the (optional) nested-name-specifier.
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
+ if (getLang().CPlusPlus) {
+ // "FOO : BAR" is not a potential typo for "FOO::BAR".
+ ColonProtectionRAIIObject X(*this);
+
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true))
+ DS.SetTypeSpecError();
+ if (SS.isSet())
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
+ Diag(Tok, diag::err_expected_ident);
+ }
+
+ TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+
+ // Parse the (optional) class name or simple-template-id.
+ IdentifierInfo *Name = 0;
+ SourceLocation NameLoc;
+ TemplateIdAnnotation *TemplateId = 0;
+ if (Tok.is(tok::identifier)) {
+ Name = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+
+ if (Tok.is(tok::less) && getLang().CPlusPlus) {
+ // The name was supposed to refer to a template, but didn't.
+ // Eat the template argument list and try to continue parsing this as
+ // a class (or template thereof).
+ TemplateArgList TemplateArgs;
+ SourceLocation LAngleLoc, RAngleLoc;
+ if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
+ true, LAngleLoc,
+ TemplateArgs, RAngleLoc)) {
+ // We couldn't parse the template argument list at all, so don't
+ // try to give any location information for the list.
+ LAngleLoc = RAngleLoc = SourceLocation();
+ }
+
+ Diag(NameLoc, diag::err_explicit_spec_non_template)
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << (TagType == DeclSpec::TST_class? 0
+ : TagType == DeclSpec::TST_struct? 1
+ : 2)
+ << Name
+ << SourceRange(LAngleLoc, RAngleLoc);
+
+ // Strip off the last template parameter list if it was empty, since
+ // we've removed its template argument list.
+ if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+ if (TemplateParams && TemplateParams->size() > 1) {
+ TemplateParams->pop_back();
+ } else {
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ }
+ } else if (TemplateInfo.Kind
+ == ParsedTemplateInfo::ExplicitInstantiation) {
+ // Pretend this is just a forward declaration.
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
+ = SourceLocation();
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+ = SourceLocation();
+ }
+ }
+ } else if (Tok.is(tok::annot_template_id)) {
+ TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ NameLoc = ConsumeToken();
+
+ if (TemplateId->Kind != TNK_Type_template) {
+ // The template-name in the simple-template-id refers to
+ // something other than a class template. Give an appropriate
+ // error message and skip to the ';'.
+ SourceRange Range(NameLoc);
+ if (SS.isNotEmpty())
+ Range.setBegin(SS.getBeginLoc());
+
+ Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
+ << Name << static_cast<int>(TemplateId->Kind) << Range;
+
+ DS.SetTypeSpecError();
+ SkipUntil(tok::semi, false, true);
+ TemplateId->Destroy();
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
+ return;
+ }
+ }
+
+ // As soon as we're finished parsing the class's template-id, turn access
+ // checking back on.
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
+ // There are four options here. If we have 'struct foo;', then this
+ // is either a forward declaration or a friend declaration, which
+ // have to be treated differently. If we have 'struct foo {...',
+ // 'struct foo :...' or 'struct foo <class-virt-specifier>' then this is a
+ // definition. Otherwise we have something like 'struct foo xyz', a reference.
+ // However, in some contexts, things look like declarations but are just
+ // references, e.g.
+ // new struct s;
+ // or
+ // &T::operator struct s;
+ // For these, SuppressDeclarations is true.
+ Sema::TagUseKind TUK;
+ if (SuppressDeclarations)
+ TUK = Sema::TUK_Reference;
+ else if (Tok.is(tok::l_brace) ||
+ (getLang().CPlusPlus && Tok.is(tok::colon)) ||
+ isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None) {
+ if (DS.isFriendSpecified()) {
+ // C++ [class.friend]p2:
+ // A class shall not be defined in a friend declaration.
+ Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
+ << SourceRange(DS.getFriendSpecLoc());
+
+ // Skip everything up to the semicolon, so that this looks like a proper
+ // friend class (or template thereof) declaration.
+ SkipUntil(tok::semi, true, true);
+ TUK = Sema::TUK_Friend;
+ } else {
+ // Okay, this is a class definition.
+ TUK = Sema::TUK_Definition;
+ }
+ } else if (Tok.is(tok::semi))
+ TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
+ else
+ TUK = Sema::TUK_Reference;
+
+ if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error ||
+ TUK != Sema::TUK_Definition)) {
+ if (DS.getTypeSpecType() != DeclSpec::TST_error) {
+ // We have a declaration or reference to an anonymous class.
+ Diag(StartLoc, diag::err_anon_type_definition)
+ << DeclSpec::getSpecifierName(TagType);
+ }
+
+ SkipUntil(tok::comma, true);
+
+ if (TemplateId)
+ TemplateId->Destroy();
+ return;
+ }
+
+ // Create the tag portion of the class or class template.
+ DeclResult TagOrTempResult = true; // invalid
+ TypeResult TypeResult = true; // invalid
+
+ bool Owned = false;
+ if (TemplateId) {
+ // Explicit specialization, class template partial specialization,
+ // or explicit instantiation.
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+ TUK == Sema::TUK_Declaration) {
+ // This is an explicit instantiation of a class template.
+ TagOrTempResult
+ = Actions.ActOnExplicitInstantiation(getCurScope(),
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
+ TagType,
+ StartLoc,
+ SS,
+ TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc,
+ attrs.getList());
+
+ // Friend template-ids are treated as references unless
+ // they have template headers, in which case they're ill-formed
+ // (FIXME: "template <class T> friend class A<T>::B<int>;").
+ // We diagnose this error in ActOnClassTemplateSpecialization.
+ } else if (TUK == Sema::TUK_Reference ||
+ (TUK == Sema::TUK_Friend &&
+ TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
+ TypeResult
+ = Actions.ActOnTemplateIdType(TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+
+ TypeResult = Actions.ActOnTagTemplateIdType(SS, TypeResult, TUK,
+ TagType, StartLoc);
+ } else {
+ // This is an explicit specialization or a class template
+ // partial specialization.
+ TemplateParameterLists FakedParamLists;
+
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
+ // This looks like an explicit instantiation, because we have
+ // something like
+ //
+ // template class Foo<X>
+ //
+ // but it actually has a definition. Most likely, this was
+ // meant to be an explicit specialization, but the user forgot
+ // the '<>' after 'template'.
+ assert(TUK == Sema::TUK_Definition && "Expected a definition here");
+
+ SourceLocation LAngleLoc
+ = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_explicit_instantiation_with_definition)
+ << SourceRange(TemplateInfo.TemplateLoc)
+ << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+ // Create a fake template parameter list that contains only
+ // "template<>", so that we treat this construct as a class
+ // template specialization.
+ FakedParamLists.push_back(
+ Actions.ActOnTemplateParameterList(0, SourceLocation(),
+ TemplateInfo.TemplateLoc,
+ LAngleLoc,
+ 0, 0,
+ LAngleLoc));
+ TemplateParams = &FakedParamLists;
+ }
+
+ // Build the class template specialization.
+ TagOrTempResult
+ = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
+ StartLoc, SS,
+ TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc,
+ attrs.getList(),
+ MultiTemplateParamsArg(Actions,
+ TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? TemplateParams->size() : 0));
+ }
+ TemplateId->Destroy();
+ } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+ TUK == Sema::TUK_Declaration) {
+ // Explicit instantiation of a member of a class template
+ // specialization, e.g.,
+ //
+ // template struct Outer<int>::Inner;
+ //
+ TagOrTempResult
+ = Actions.ActOnExplicitInstantiation(getCurScope(),
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
+ TagType, StartLoc, SS, Name,
+ NameLoc, attrs.getList());
+ } else if (TUK == Sema::TUK_Friend &&
+ TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
+ TagOrTempResult =
+ Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(),
+ TagType, StartLoc, SS,
+ Name, NameLoc, attrs.getList(),
+ MultiTemplateParamsArg(Actions,
+ TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? TemplateParams->size() : 0));
+ } else {
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+ TUK == Sema::TUK_Definition) {
+ // FIXME: Diagnose this particular error.
+ }
+
+ bool IsDependent = false;
+
+ // Don't pass down template parameter lists if this is just a tag
+ // reference. For example, we don't need the template parameters here:
+ // template <class T> class A *makeA(T t);
+ MultiTemplateParamsArg TParams;
+ if (TUK != Sema::TUK_Reference && TemplateParams)
+ TParams =
+ MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
+
+ // Declaration or definition of a class type
+ TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
+ SS, Name, NameLoc, attrs.getList(), AS,
+ TParams, Owned, IsDependent, false,
+ false, clang::TypeResult());
+
+ // If ActOnTag said the type was dependent, try again with the
+ // less common call.
+ if (IsDependent) {
+ assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend);
+ TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK,
+ SS, Name, StartLoc, NameLoc);
+ }
+ }
+
+ // If there is a body, parse it and inform the actions module.
+ if (TUK == Sema::TUK_Definition) {
+ assert(Tok.is(tok::l_brace) ||
+ (getLang().CPlusPlus && Tok.is(tok::colon)) ||
+ isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None);
+ if (getLang().CPlusPlus)
+ ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
+ else
+ ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
+ }
+
+ // FIXME: The DeclSpec should keep the locations of both the keyword and the
+ // name (if there is one).
+ SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ bool Result;
+ if (!TypeResult.isInvalid()) {
+ Result = DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc,
+ PrevSpec, DiagID, TypeResult.get());
+ } else if (!TagOrTempResult.isInvalid()) {
+ Result = DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
+ TagOrTempResult.get(), Owned);
+ } else {
+ DS.SetTypeSpecError();
+ return;
+ }
+
+ if (Result)
+ Diag(StartLoc, DiagID) << PrevSpec;
+
+ // At this point, we've successfully parsed a class-specifier in 'definition'
+ // form (e.g. "struct foo { int x; }". While we could just return here, we're
+ // going to look at what comes after it to improve error recovery. If an
+ // impossible token occurs next, we assume that the programmer forgot a ; at
+ // the end of the declaration and recover that way.
+ //
+ // This switch enumerates the valid "follow" set for definition.
+ if (TUK == Sema::TUK_Definition) {
+ bool ExpectedSemi = true;
+ switch (Tok.getKind()) {
+ default: break;
+ case tok::semi: // struct foo {...} ;
+ case tok::star: // struct foo {...} * P;
+ case tok::amp: // struct foo {...} & R = ...
+ case tok::identifier: // struct foo {...} V ;
+ case tok::r_paren: //(struct foo {...} ) {4}
+ case tok::annot_cxxscope: // struct foo {...} a:: b;
+ case tok::annot_typename: // struct foo {...} a ::b;
+ case tok::annot_template_id: // struct foo {...} a<int> ::b;
+ case tok::l_paren: // struct foo {...} ( x);
+ case tok::comma: // __builtin_offsetof(struct foo{...} ,
+ ExpectedSemi = false;
+ break;
+ // Type qualifiers
+ case tok::kw_const: // struct foo {...} const x;
+ case tok::kw_volatile: // struct foo {...} volatile x;
+ case tok::kw_restrict: // struct foo {...} restrict x;
+ case tok::kw_inline: // struct foo {...} inline foo() {};
+ // Storage-class specifiers
+ case tok::kw_static: // struct foo {...} static x;
+ case tok::kw_extern: // struct foo {...} extern x;
+ case tok::kw_typedef: // struct foo {...} typedef x;
+ case tok::kw_register: // struct foo {...} register x;
+ case tok::kw_auto: // struct foo {...} auto x;
+ case tok::kw_mutable: // struct foo {...} mutable x;
+ // As shown above, type qualifiers and storage class specifiers absolutely
+ // can occur after class specifiers according to the grammar. However,
+ // almost noone actually writes code like this. If we see one of these,
+ // it is much more likely that someone missed a semi colon and the
+ // type/storage class specifier we're seeing is part of the *next*
+ // intended declaration, as in:
+ //
+ // struct foo { ... }
+ // typedef int X;
+ //
+ // We'd really like to emit a missing semicolon error instead of emitting
+ // an error on the 'int' saying that you can't have two type specifiers in
+ // the same declaration of X. Because of this, we look ahead past this
+ // token to see if it's a type specifier. If so, we know the code is
+ // otherwise invalid, so we can produce the expected semi error.
+ if (!isKnownToBeTypeSpecifier(NextToken()))
+ ExpectedSemi = false;
+ break;
+
+ case tok::r_brace: // struct bar { struct foo {...} }
+ // Missing ';' at end of struct is accepted as an extension in C mode.
+ if (!getLang().CPlusPlus)
+ ExpectedSemi = false;
+ break;
+ }
+
+ if (ExpectedSemi) {
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
+ TagType == DeclSpec::TST_class ? "class"
+ : TagType == DeclSpec::TST_struct? "struct" : "union");
+ // Push this token back into the preprocessor and change our current token
+ // to ';' so that the rest of the code recovers as though there were an
+ // ';' after the definition.
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::semi);
+ }
+ }
+}
+
+/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
+///
+/// base-clause : [C++ class.derived]
+/// ':' base-specifier-list
+/// base-specifier-list:
+/// base-specifier '...'[opt]
+/// base-specifier-list ',' base-specifier '...'[opt]
+void Parser::ParseBaseClause(Decl *ClassDecl) {
+ assert(Tok.is(tok::colon) && "Not a base clause");
+ ConsumeToken();
+
+ // Build up an array of parsed base specifiers.
+ llvm::SmallVector<CXXBaseSpecifier *, 8> BaseInfo;
+
+ while (true) {
+ // Parse a base-specifier.
+ BaseResult Result = ParseBaseSpecifier(ClassDecl);
+ if (Result.isInvalid()) {
+ // Skip the rest of this base specifier, up until the comma or
+ // opening brace.
+ SkipUntil(tok::comma, tok::l_brace, true, true);
+ } else {
+ // Add this to our array of base specifiers.
+ BaseInfo.push_back(Result.get());
+ }
+
+ // If the next token is a comma, consume it and keep reading
+ // base-specifiers.
+ if (Tok.isNot(tok::comma)) break;
+
+ // Consume the comma.
+ ConsumeToken();
+ }
+
+ // Attach the base specifiers
+ Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size());
+}
+
+/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
+/// one entry in the base class list of a class specifier, for example:
+/// class foo : public bar, virtual private baz {
+/// 'public bar' and 'virtual private baz' are each base-specifiers.
+///
+/// base-specifier: [C++ class.derived]
+/// ::[opt] nested-name-specifier[opt] class-name
+/// 'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
+/// class-name
+/// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
+/// class-name
+Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
+ bool IsVirtual = false;
+ SourceLocation StartLoc = Tok.getLocation();
+
+ // Parse the 'virtual' keyword.
+ if (Tok.is(tok::kw_virtual)) {
+ ConsumeToken();
+ IsVirtual = true;
+ }
+
+ // Parse an (optional) access specifier.
+ AccessSpecifier Access = getAccessSpecifierIfPresent();
+ if (Access != AS_none)
+ ConsumeToken();
+
+ // Parse the 'virtual' keyword (again!), in case it came after the
+ // access specifier.
+ if (Tok.is(tok::kw_virtual)) {
+ SourceLocation VirtualLoc = ConsumeToken();
+ if (IsVirtual) {
+ // Complain about duplicate 'virtual'
+ Diag(VirtualLoc, diag::err_dup_virtual)
+ << FixItHint::CreateRemoval(VirtualLoc);
+ }
+
+ IsVirtual = true;
+ }
+
+ // Parse optional '::' and optional nested-name-specifier.
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
+
+ // The location of the base class itself.
+ SourceLocation BaseLoc = Tok.getLocation();
+
+ // Parse the class-name.
+ SourceLocation EndLocation;
+ TypeResult BaseType = ParseClassName(EndLocation, &SS);
+ if (BaseType.isInvalid())
+ return true;
+
+ // Parse the optional ellipsis (for a pack expansion). The ellipsis is
+ // actually part of the base-specifier-list grammar productions, but we
+ // parse it here for convenience.
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
+ // Find the complete source range for the base-specifier.
+ SourceRange Range(StartLoc, EndLocation);
+
+ // Notify semantic analysis that we have parsed a complete
+ // base-specifier.
+ return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
+ BaseType.get(), BaseLoc, EllipsisLoc);
+}
+
+/// getAccessSpecifierIfPresent - Determine whether the next token is
+/// a C++ access-specifier.
+///
+/// access-specifier: [C++ class.derived]
+/// 'private'
+/// 'protected'
+/// 'public'
+AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
+ switch (Tok.getKind()) {
+ default: return AS_none;
+ case tok::kw_private: return AS_private;
+ case tok::kw_protected: return AS_protected;
+ case tok::kw_public: return AS_public;
+ }
+}
+
+void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
+ Decl *ThisDecl) {
+ // We just declared a member function. If this member function
+ // has any default arguments, we'll need to parse them later.
+ LateParsedMethodDeclaration *LateMethod = 0;
+ DeclaratorChunk::FunctionTypeInfo &FTI
+ = DeclaratorInfo.getFunctionTypeInfo();
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
+ if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
+ if (!LateMethod) {
+ // Push this method onto the stack of late-parsed method
+ // declarations.
+ LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+ getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
+ LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
+
+ // Add all of the parameters prior to this one (they don't
+ // have default arguments).
+ LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+ for (unsigned I = 0; I < ParamIdx; ++I)
+ LateMethod->DefaultArgs.push_back(
+ LateParsedDefaultArgument(FTI.ArgInfo[I].Param));
+ }
+
+ // Add this parameter to the list of parameters (it or may
+ // not have a default argument).
+ LateMethod->DefaultArgs.push_back(
+ LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
+ FTI.ArgInfo[ParamIdx].DefaultArgTokens));
+ }
+ }
+}
+
+/// isCXX0XVirtSpecifier - Determine whether the next token is a C++0x
+/// virt-specifier.
+///
+/// virt-specifier:
+/// override
+/// final
+/// new
+VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier() const {
+ if (!getLang().CPlusPlus)
+ return VirtSpecifiers::VS_None;
+
+ if (Tok.is(tok::kw_new))
+ return VirtSpecifiers::VS_New;
+
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ // Initialize the contextual keywords.
+ if (!Ident_final) {
+ Ident_final = &PP.getIdentifierTable().get("final");
+ Ident_override = &PP.getIdentifierTable().get("override");
+ }
+
+ if (II == Ident_override)
+ return VirtSpecifiers::VS_Override;
+
+ if (II == Ident_final)
+ return VirtSpecifiers::VS_Final;
+ }
+
+ return VirtSpecifiers::VS_None;
+}
+
+/// ParseOptionalCXX0XVirtSpecifierSeq - Parse a virt-specifier-seq.
+///
+/// virt-specifier-seq:
+/// virt-specifier
+/// virt-specifier-seq virt-specifier
+void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) {
+ while (true) {
+ VirtSpecifiers::Specifier Specifier = isCXX0XVirtSpecifier();
+ if (Specifier == VirtSpecifiers::VS_None)
+ return;
+
+ // C++ [class.mem]p8:
+ // A virt-specifier-seq shall contain at most one of each virt-specifier.
+ const char *PrevSpec = 0;
+ if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
+ Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
+ << PrevSpec
+ << FixItHint::CreateRemoval(Tok.getLocation());
+
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok.getLocation(), diag::ext_override_control_keyword)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ ConsumeToken();
+ }
+}
+
+/// isCXX0XClassVirtSpecifier - Determine whether the next token is a C++0x
+/// class-virt-specifier.
+///
+/// class-virt-specifier:
+/// final
+/// explicit
+ClassVirtSpecifiers::Specifier Parser::isCXX0XClassVirtSpecifier() const {
+ if (!getLang().CPlusPlus)
+ return ClassVirtSpecifiers::CVS_None;
+
+ if (Tok.is(tok::kw_explicit))
+ return ClassVirtSpecifiers::CVS_Explicit;
+
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ // Initialize the contextual keywords.
+ if (!Ident_final) {
+ Ident_final = &PP.getIdentifierTable().get("final");
+ Ident_override = &PP.getIdentifierTable().get("override");
+ }
+
+ if (II == Ident_final)
+ return ClassVirtSpecifiers::CVS_Final;
+ }
+
+ return ClassVirtSpecifiers::CVS_None;
+}
+
+/// ParseOptionalCXX0XClassVirtSpecifierSeq - Parse a class-virt-specifier-seq.
+///
+/// class-virt-specifier-seq:
+/// class-virt-specifier
+/// class-virt-specifier-seq class-virt-specifier
+void Parser::ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS) {
+ while (true) {
+ ClassVirtSpecifiers::Specifier Specifier = isCXX0XClassVirtSpecifier();
+ if (Specifier == ClassVirtSpecifiers::CVS_None)
+ return;
+
+ // C++ [class]p1:
+ // A class-virt-specifier-seq shall contain at most one of each
+ // class-virt-specifier.
+ const char *PrevSpec = 0;
+ if (CVS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
+ Diag(Tok.getLocation(), diag::err_duplicate_class_virt_specifier)
+ << PrevSpec
+ << FixItHint::CreateRemoval(Tok.getLocation());
+
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok.getLocation(), diag::ext_override_control_keyword)
+ << ClassVirtSpecifiers::getSpecifierName(Specifier);
+
+ ConsumeToken();
+ }
+}
+
+/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
+///
+/// member-declaration:
+/// decl-specifier-seq[opt] member-declarator-list[opt] ';'
+/// function-definition ';'[opt]
+/// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]
+/// using-declaration [TODO]
+/// [C++0x] static_assert-declaration
+/// template-declaration
+/// [GNU] '__extension__' member-declaration
+///
+/// member-declarator-list:
+/// member-declarator
+/// member-declarator-list ',' member-declarator
+///
+/// member-declarator:
+/// declarator virt-specifier-seq[opt] pure-specifier[opt]
+/// declarator constant-initializer[opt]
+/// identifier[opt] ':' constant-expression
+///
+/// virt-specifier-seq:
+/// virt-specifier
+/// virt-specifier-seq virt-specifier
+///
+/// virt-specifier:
+/// override
+/// final
+/// new
+///
+/// pure-specifier:
+/// '= 0'
+///
+/// constant-initializer:
+/// '=' constant-expression
+///
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject *TemplateDiags) {
+ // Access declarations.
+ if (!TemplateInfo.Kind &&
+ (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+ !TryAnnotateCXXScopeToken() &&
+ Tok.is(tok::annot_cxxscope)) {
+ bool isAccessDecl = false;
+ if (NextToken().is(tok::identifier))
+ isAccessDecl = GetLookAheadToken(2).is(tok::semi);
+ else
+ isAccessDecl = NextToken().is(tok::kw_operator);
+
+ if (isAccessDecl) {
+ // Collect the scope specifier token we annotated earlier.
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+ // Try to parse an unqualified-id.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
+ SkipUntil(tok::semi);
+ return;
+ }
+
+ // TODO: recover from mistakenly-qualified operator declarations.
+ if (ExpectAndConsume(tok::semi,
+ diag::err_expected_semi_after,
+ "access declaration",
+ tok::semi))
+ return;
+
+ Actions.ActOnUsingDeclaration(getCurScope(), AS,
+ false, SourceLocation(),
+ SS, Name,
+ /* AttrList */ 0,
+ /* IsTypeName */ false,
+ SourceLocation());
+ return;
+ }
+ }
+
+ // static_assert-declaration
+ if (Tok.is(tok::kw_static_assert)) {
+ // FIXME: Check for templates
+ SourceLocation DeclEnd;
+ ParseStaticAssertDeclaration(DeclEnd);
+ return;
+ }
+
+ if (Tok.is(tok::kw_template)) {
+ assert(!TemplateInfo.TemplateParams &&
+ "Nested template improperly parsed?");
+ SourceLocation DeclEnd;
+ ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
+ AS);
+ return;
+ }
+
+ // Handle: member-declaration ::= '__extension__' member-declaration
+ if (Tok.is(tok::kw___extension__)) {
+ // __extension__ silences extension warnings in the subexpression.
+ ExtensionRAIIObject O(Diags); // Use RAII to do this.
+ ConsumeToken();
+ return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags);
+ }
+
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
+ // is a bitfield.
+ ColonProtectionRAIIObject X(*this);
+
+ ParsedAttributesWithRange attrs;
+ // Optional C++0x attribute-specifier
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+
+ if (Tok.is(tok::kw_using)) {
+ // FIXME: Check for template aliases
+
+ ProhibitAttributes(attrs);
+
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_namespace)) {
+ Diag(UsingLoc, diag::err_using_namespace_in_class);
+ SkipUntil(tok::semi, true, true);
+ } else {
+ SourceLocation DeclEnd;
+ // Otherwise, it must be using-declaration.
+ ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
+ UsingLoc, DeclEnd, AS);
+ }
+ return;
+ }
+
+ // decl-specifier-seq:
+ // Parse the common declaration-specifiers piece.
+ ParsingDeclSpec DS(*this, TemplateDiags);
+ DS.takeAttributesFrom(attrs);
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
+
+ MultiTemplateParamsArg TemplateParams(Actions,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ Decl *TheDecl =
+ Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DS.complete(TheDecl);
+ return;
+ }
+
+ ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
+ VirtSpecifiers VS;
+
+ if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+
+ // Parse the first declarator.
+ ParseDeclarator(DeclaratorInfo);
+ // Error parsing the declarator?
+ if (!DeclaratorInfo.hasName()) {
+ // If so, skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return;
+ }
+
+ ParseOptionalCXX0XVirtSpecifierSeq(VS);
+
+ // If attributes exist after the declarator, but before an '{', parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo);
+
+ // function-definition:
+ if (Tok.is(tok::l_brace)
+ || (DeclaratorInfo.isFunctionDeclarator() &&
+ (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
+ if (!DeclaratorInfo.isFunctionDeclarator()) {
+ Diag(Tok, diag::err_func_def_no_params);
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, true);
+
+ // Consume the optional ';'
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return;
+ }
+
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
+ // This recovery skips the entire function body. It would be nice
+ // to simply call ParseCXXInlineMethodDef() below, however Sema
+ // assumes the declarator represents a function, not a typedef.
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, true);
+
+ // Consume the optional ';'
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return;
+ }
+
+ ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS);
+ // Consume the optional ';'
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+
+ return;
+ }
+ }
+
+ // member-declarator-list:
+ // member-declarator
+ // member-declarator-list ',' member-declarator
+
+ llvm::SmallVector<Decl *, 8> DeclsInGroup;
+ ExprResult BitfieldSize;
+ ExprResult Init;
+ bool Deleted = false;
+
+ while (1) {
+ // member-declarator:
+ // declarator pure-specifier[opt]
+ // declarator constant-initializer[opt]
+ // identifier[opt] ':' constant-expression
+ if (Tok.is(tok::colon)) {
+ ConsumeToken();
+ BitfieldSize = ParseConstantExpression();
+ if (BitfieldSize.isInvalid())
+ SkipUntil(tok::comma, true, true);
+ }
+
+ ParseOptionalCXX0XVirtSpecifierSeq(VS);
+
+ // pure-specifier:
+ // '= 0'
+ //
+ // constant-initializer:
+ // '=' constant-expression
+ //
+ // defaulted/deleted function-definition:
+ // '=' 'default' [TODO]
+ // '=' 'delete'
+ if (Tok.is(tok::equal)) {
+ ConsumeToken();
+ if (Tok.is(tok::kw_delete)) {
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::warn_deleted_function_accepted_as_extension);
+ ConsumeToken();
+ Deleted = true;
+ } else {
+ Init = ParseInitializer();
+ if (Init.isInvalid())
+ SkipUntil(tok::comma, true, true);
+ }
+ }
+
+ // If a simple-asm-expr is present, parse it.
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid())
+ SkipUntil(tok::comma, true, true);
+
+ DeclaratorInfo.setAsmLabel(AsmLabel.release());
+ DeclaratorInfo.SetRangeEnd(Loc);
+ }
+
+ // If attributes exist after the declarator, parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo);
+
+ // NOTE: If Sema is the Action module and declarator is an instance field,
+ // this call will *not* return the created decl; It will return null.
+ // See Sema::ActOnCXXMemberDeclarator for details.
+
+ Decl *ThisDecl = 0;
+ if (DS.isFriendSpecified()) {
+ // TODO: handle initializers, bitfields, 'delete'
+ ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
+ /*IsDefinition*/ false,
+ move(TemplateParams));
+ } else {
+ ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS,
+ DeclaratorInfo,
+ move(TemplateParams),
+ BitfieldSize.release(),
+ VS, Init.release(),
+ /*IsDefinition*/Deleted,
+ Deleted);
+ }
+ if (ThisDecl)
+ DeclsInGroup.push_back(ThisDecl);
+
+ if (DeclaratorInfo.isFunctionDeclarator() &&
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+ != DeclSpec::SCS_typedef) {
+ HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
+ }
+
+ DeclaratorInfo.complete(ThisDecl);
+
+ // If we don't have a comma, it is either the end of the list (a ';')
+ // or an error, bail out.
+ if (Tok.isNot(tok::comma))
+ break;
+
+ // Consume the comma.
+ ConsumeToken();
+
+ // Parse the next declarator.
+ DeclaratorInfo.clear();
+ VS.clear();
+ BitfieldSize = 0;
+ Init = 0;
+ Deleted = false;
+
+ // Attributes are only allowed on the second declarator.
+ MaybeParseGNUAttributes(DeclaratorInfo);
+
+ if (Tok.isNot(tok::colon))
+ ParseDeclarator(DeclaratorInfo);
+ }
+
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
+ // Skip to end of block or statement.
+ SkipUntil(tok::r_brace, true, true);
+ // If we stopped at a ';', eat it.
+ if (Tok.is(tok::semi)) ConsumeToken();
+ return;
+ }
+
+ Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup.data(),
+ DeclsInGroup.size());
+}
+
+/// ParseCXXMemberSpecification - Parse the class definition.
+///
+/// member-specification:
+/// member-declaration member-specification[opt]
+/// access-specifier ':' member-specification[opt]
+///
+void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
+ unsigned TagType, Decl *TagDecl) {
+ assert((TagType == DeclSpec::TST_struct ||
+ TagType == DeclSpec::TST_union ||
+ TagType == DeclSpec::TST_class) && "Invalid TagType!");
+
+ PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ "parsing struct/union/class body");
+
+ // Determine whether this is a non-nested class. Note that local
+ // classes are *not* considered to be nested classes.
+ bool NonNestedClass = true;
+ if (!ClassStack.empty()) {
+ for (const Scope *S = getCurScope(); S; S = S->getParent()) {
+ if (S->isClassScope()) {
+ // We're inside a class scope, so this is a nested class.
+ NonNestedClass = false;
+ break;
+ }
+
+ if ((S->getFlags() & Scope::FnScope)) {
+ // If we're in a function or function template declared in the
+ // body of a class, then this is a local class rather than a
+ // nested class.
+ const Scope *Parent = S->getParent();
+ if (Parent->isTemplateParamScope())
+ Parent = Parent->getParent();
+ if (Parent->isClassScope())
+ break;
+ }
+ }
+ }
+
+ // Enter a scope for the class.
+ ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
+
+ // Note that we are parsing a new (potentially-nested) class definition.
+ ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
+
+ if (TagDecl)
+ Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
+
+ ClassVirtSpecifiers CVS;
+ ParseOptionalCXX0XClassVirtSpecifierSeq(CVS);
+
+ if (Tok.is(tok::colon)) {
+ ParseBaseClause(TagDecl);
+
+ if (!Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::err_expected_lbrace_after_base_specifiers);
+
+ if (TagDecl)
+ Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);
+ return;
+ }
+ }
+
+ assert(Tok.is(tok::l_brace));
+
+ SourceLocation LBraceLoc = ConsumeBrace();
+
+ if (TagDecl)
+ Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, CVS,
+ LBraceLoc);
+
+ // C++ 11p3: Members of a class defined with the keyword class are private
+ // by default. Members of a class defined with the keywords struct or union
+ // are public by default.
+ AccessSpecifier CurAS;
+ if (TagType == DeclSpec::TST_class)
+ CurAS = AS_private;
+ else
+ CurAS = AS_public;
+
+ SourceLocation RBraceLoc;
+ if (TagDecl) {
+ // While we still have something to read, read the member-declarations.
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ // Each iteration of this loop reads one member-declaration.
+
+ // Check for extraneous top-level semicolon.
+ if (Tok.is(tok::semi)) {
+ Diag(Tok, diag::ext_extra_struct_semi)
+ << DeclSpec::getSpecifierName((DeclSpec::TST)TagType)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ ConsumeToken();
+ continue;
+ }
+
+ AccessSpecifier AS = getAccessSpecifierIfPresent();
+ if (AS != AS_none) {
+ // Current token is a C++ access specifier.
+ CurAS = AS;
+ SourceLocation ASLoc = Tok.getLocation();
+ ConsumeToken();
+ if (Tok.is(tok::colon))
+ Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation());
+ else
+ Diag(Tok, diag::err_expected_colon);
+ ConsumeToken();
+ continue;
+ }
+
+ // FIXME: Make sure we don't have a template here.
+
+ // Parse all the comma separated declarators.
+ ParseCXXClassMemberDeclaration(CurAS);
+ }
+
+ RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ } else {
+ SkipUntil(tok::r_brace, false, false);
+ }
+
+ // If attributes exist after class contents, parse them.
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+
+ if (TagDecl)
+ Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,
+ LBraceLoc, RBraceLoc,
+ attrs.getList());
+
+ // C++ 9.2p2: Within the class member-specification, the class is regarded as
+ // complete within function bodies, default arguments,
+ // exception-specifications, and constructor ctor-initializers (including
+ // such things in nested classes).
+ //
+ // FIXME: Only function bodies and constructor ctor-initializers are
+ // parsed correctly, fix the rest.
+ if (TagDecl && NonNestedClass) {
+ // We are not inside a nested class. This class and its nested classes
+ // are complete and we can parse the delayed portions of method
+ // declarations and the lexed inline method definitions.
+ SourceLocation SavedPrevTokLocation = PrevTokLocation;
+ ParseLexedMethodDeclarations(getCurrentClass());
+ ParseLexedMethodDefs(getCurrentClass());
+ PrevTokLocation = SavedPrevTokLocation;
+ }
+
+ if (TagDecl)
+ Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
+
+ // Leave the class scope.
+ ParsingDef.Pop();
+ ClassScope.Exit();
+}
+
+/// ParseConstructorInitializer - Parse a C++ constructor initializer,
+/// which explicitly initializes the members or base classes of a
+/// class (C++ [class.base.init]). For example, the three initializers
+/// after the ':' in the Derived constructor below:
+///
+/// @code
+/// class Base { };
+/// class Derived : Base {
+/// int x;
+/// float f;
+/// public:
+/// Derived(float f) : Base(), x(17), f(f) { }
+/// };
+/// @endcode
+///
+/// [C++] ctor-initializer:
+/// ':' mem-initializer-list
+///
+/// [C++] mem-initializer-list:
+/// mem-initializer ...[opt]
+/// mem-initializer ...[opt] , mem-initializer-list
+void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
+ assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
+
+ SourceLocation ColonLoc = ConsumeToken();
+
+ llvm::SmallVector<CXXCtorInitializer*, 4> MemInitializers;
+ bool AnyErrors = false;
+
+ do {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
+ MemInitializers.data(),
+ MemInitializers.size());
+ ConsumeCodeCompletionToken();
+ } else {
+ MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
+ if (!MemInit.isInvalid())
+ MemInitializers.push_back(MemInit.get());
+ else
+ AnyErrors = true;
+ }
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else if (Tok.is(tok::l_brace))
+ break;
+ // If the next token looks like a base or member initializer, assume that
+ // we're just missing a comma.
+ else if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
+ SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
+ Diag(Loc, diag::err_ctor_init_missing_comma)
+ << FixItHint::CreateInsertion(Loc, ", ");
+ } else {
+ // Skip over garbage, until we get to '{'. Don't eat the '{'.
+ Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
+ SkipUntil(tok::l_brace, true, true);
+ break;
+ }
+ } while (true);
+
+ Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
+ MemInitializers.data(), MemInitializers.size(),
+ AnyErrors);
+}
+
+/// ParseMemInitializer - Parse a C++ member initializer, which is
+/// part of a constructor initializer that explicitly initializes one
+/// member or base class (C++ [class.base.init]). See
+/// ParseConstructorInitializer for an example.
+///
+/// [C++] mem-initializer:
+/// mem-initializer-id '(' expression-list[opt] ')'
+///
+/// [C++] mem-initializer-id:
+/// '::'[opt] nested-name-specifier[opt] class-name
+/// identifier
+Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
+ // parse '::'[opt] nested-name-specifier[opt]
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParsedType TemplateTypeTy;
+ if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) {
+ AnnotateTemplateIdTokenAsType(&SS);
+ assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
+ TemplateTypeTy = getTypeAnnotation(Tok);
+ }
+ }
+ if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_member_or_base_name);
+ return true;
+ }
+
+ // Get the identifier. This may be a member name or a class name,
+ // but we'll let the semantic analysis determine which it is.
+ IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
+ SourceLocation IdLoc = ConsumeToken();
+
+ // Parse the '('.
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen);
+ return true;
+ }
+ SourceLocation LParenLoc = ConsumeParen();
+
+ // Parse the optional expression-list.
+ ExprVector ArgExprs(Actions);
+ CommaLocsTy CommaLocs;
+ if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
+ return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
+ TemplateTypeTy, IdLoc,
+ LParenLoc, ArgExprs.take(),
+ ArgExprs.size(), RParenLoc,
+ EllipsisLoc);
+}
+
+/// ParseExceptionSpecification - Parse a C++ exception-specification
+/// (C++ [except.spec]).
+///
+/// exception-specification:
+/// 'throw' '(' type-id-list [opt] ')'
+/// [MS] 'throw' '(' '...' ')'
+///
+/// type-id-list:
+/// type-id ... [opt]
+/// type-id-list ',' type-id ... [opt]
+///
+bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
+ llvm::SmallVectorImpl<ParsedType>
+ &Exceptions,
+ llvm::SmallVectorImpl<SourceRange>
+ &Ranges,
+ bool &hasAnyExceptionSpec) {
+ assert(Tok.is(tok::kw_throw) && "expected throw");
+
+ ConsumeToken();
+
+ if (!Tok.is(tok::l_paren)) {
+ return Diag(Tok, diag::err_expected_lparen_after) << "throw";
+ }
+ SourceLocation LParenLoc = ConsumeParen();
+
+ // Parse throw(...), a Microsoft extension that means "this function
+ // can throw anything".
+ if (Tok.is(tok::ellipsis)) {
+ hasAnyExceptionSpec = true;
+ SourceLocation EllipsisLoc = ConsumeToken();
+ if (!getLang().Microsoft)
+ Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
+ EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return false;
+ }
+
+ // Parse the sequence of type-ids.
+ SourceRange Range;
+ while (Tok.isNot(tok::r_paren)) {
+ TypeResult Res(ParseTypeName(&Range));
+
+ if (Tok.is(tok::ellipsis)) {
+ // C++0x [temp.variadic]p5:
+ // - In a dynamic-exception-specification (15.4); the pattern is a
+ // type-id.
+ SourceLocation Ellipsis = ConsumeToken();
+ if (!Res.isInvalid())
+ Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis);
+ }
+
+ if (!Res.isInvalid()) {
+ Exceptions.push_back(Res.get());
+ Ranges.push_back(Range);
+ }
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else
+ break;
+ }
+
+ EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return false;
+}
+
+/// ParseTrailingReturnType - Parse a trailing return type on a new-style
+/// function declaration.
+TypeResult Parser::ParseTrailingReturnType() {
+ assert(Tok.is(tok::arrow) && "expected arrow");
+
+ ConsumeToken();
+
+ // FIXME: Need to suppress declarations when parsing this typename.
+ // Otherwise in this function definition:
+ //
+ // auto f() -> struct X {}
+ //
+ // struct X is parsed as class definition because of the trailing
+ // brace.
+
+ SourceRange Range;
+ return ParseTypeName(&Range);
+}
+
+/// \brief We have just started parsing the definition of a new class,
+/// so push that class onto our stack of classes that is currently
+/// being parsed.
+Sema::ParsingClassState
+Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass) {
+ assert((NonNestedClass || !ClassStack.empty()) &&
+ "Nested class without outer class");
+ ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
+ return Actions.PushParsingClass();
+}
+
+/// \brief Deallocate the given parsed class and all of its nested
+/// classes.
+void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
+ for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)
+ delete Class->LateParsedDeclarations[I];
+ delete Class;
+}
+
+/// \brief Pop the top class of the stack of classes that are
+/// currently being parsed.
+///
+/// This routine should be called when we have finished parsing the
+/// definition of a class, but have not yet popped the Scope
+/// associated with the class's definition.
+///
+/// \returns true if the class we've popped is a top-level class,
+/// false otherwise.
+void Parser::PopParsingClass(Sema::ParsingClassState state) {
+ assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
+
+ Actions.PopParsingClass(state);
+
+ ParsingClass *Victim = ClassStack.top();
+ ClassStack.pop();
+ if (Victim->TopLevelClass) {
+ // Deallocate all of the nested classes of this class,
+ // recursively: we don't need to keep any of this information.
+ DeallocateParsedClasses(Victim);
+ return;
+ }
+ assert(!ClassStack.empty() && "Missing top-level class?");
+
+ if (Victim->LateParsedDeclarations.empty()) {
+ // The victim is a nested class, but we will not need to perform
+ // any processing after the definition of this class since it has
+ // no members whose handling was delayed. Therefore, we can just
+ // remove this nested class.
+ DeallocateParsedClasses(Victim);
+ return;
+ }
+
+ // This nested class has some members that will need to be processed
+ // after the top-level class is completely defined. Therefore, add
+ // it to the list of nested classes within its parent.
+ assert(getCurScope()->isClassScope() && "Nested class outside of class scope?");
+ ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim));
+ Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
+}
+
+/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
+/// parses standard attributes.
+///
+/// [C++0x] attribute-specifier:
+/// '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+/// attribute[opt]
+/// attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+/// attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+/// identifier
+/// attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+/// attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+/// identifier
+///
+/// [C++0x] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc) {
+ assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
+ && "Not a C++0x attribute list");
+
+ SourceLocation StartLoc = Tok.getLocation(), Loc;
+
+ ConsumeBracket();
+ ConsumeBracket();
+
+ if (Tok.is(tok::comma)) {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ ConsumeToken();
+ }
+
+ while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
+ // attribute not present
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ continue;
+ }
+
+ IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
+ SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+
+ // scoped attribute
+ if (Tok.is(tok::coloncolon)) {
+ ConsumeToken();
+
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ SkipUntil(tok::r_square, tok::comma, true, true);
+ continue;
+ }
+
+ ScopeName = AttrName;
+ ScopeLoc = AttrLoc;
+
+ AttrName = Tok.getIdentifierInfo();
+ AttrLoc = ConsumeToken();
+ }
+
+ bool AttrParsed = false;
+ // No scoped names are supported; ideally we could put all non-standard
+ // attributes into namespaces.
+ if (!ScopeName) {
+ switch(AttributeList::getKind(AttrName))
+ {
+ // No arguments
+ case AttributeList::AT_carries_dependency:
+ case AttributeList::AT_noreturn: {
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+ << AttrName->getName();
+ break;
+ }
+
+ attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc, 0,
+ SourceLocation(), 0, 0, false, true));
+ AttrParsed = true;
+ break;
+ }
+
+ // One argument; must be a type-id or assignment-expression
+ case AttributeList::AT_aligned: {
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
+ << AttrName->getName();
+ break;
+ }
+ SourceLocation ParamLoc = ConsumeParen();
+
+ ExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
+
+ MatchRHSPunctuation(tok::r_paren, ParamLoc);
+
+ ExprVector ArgExprs(Actions);
+ ArgExprs.push_back(ArgExpr.release());
+ attrs.add(AttrFactory.Create(AttrName, AttrLoc, 0, AttrLoc,
+ 0, ParamLoc, ArgExprs.take(), 1,
+ false, true));
+
+ AttrParsed = true;
+ break;
+ }
+
+ // Silence warnings
+ default: break;
+ }
+ }
+
+ // Skip the entire parameter clause, if any
+ if (!AttrParsed && Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ // SkipUntil maintains the balancedness of tokens.
+ SkipUntil(tok::r_paren, false);
+ }
+ }
+
+ if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ SkipUntil(tok::r_square, false);
+ Loc = Tok.getLocation();
+ if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ SkipUntil(tok::r_square, false);
+
+ attrs.Range = SourceRange(StartLoc, Loc);
+}
+
+/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
+/// attribute.
+///
+/// FIXME: Simply returns an alignof() expression if the argument is a
+/// type. Ideally, the type should be propagated directly into Sema.
+///
+/// [C++0x] 'align' '(' type-id ')'
+/// [C++0x] 'align' '(' assignment-expression ')'
+ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
+ if (isTypeIdInParens()) {
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ SourceLocation TypeLoc = Tok.getLocation();
+ ParsedType Ty = ParseTypeName().get();
+ SourceRange TypeRange(Start, Tok.getLocation());
+ return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true,
+ Ty.getAsOpaquePtr(), TypeRange);
+ } else
+ return ParseConstantExpression();
+}
+
+/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
+///
+/// [MS] ms-attribute:
+/// '[' token-seq ']'
+///
+/// [MS] ms-attribute-seq:
+/// ms-attribute[opt]
+/// ms-attribute ms-attribute-seq
+void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc) {
+ assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
+
+ while (Tok.is(tok::l_square)) {
+ ConsumeBracket();
+ SkipUntil(tok::r_square, true, true);
+ if (endLoc) *endLoc = Tok.getLocation();
+ ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
new file mode 100644
index 0000000..616c251
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -0,0 +1,1948 @@
+//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expression parsing implementation. Expressions in
+// C99 basically consist of a bunch of binary operators with unary operators and
+// other random stuff at the leaves.
+//
+// In the C99 grammar, these unary operators bind tightest and are represented
+// as the 'cast-expression' production. Everything else is either a binary
+// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are
+// handled by ParseCastExpression, the higher level pieces are handled by
+// ParseBinaryExpression.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "RAIIObjectsForParser.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+
+/// getBinOpPrecedence - Return the precedence of the specified binary operator
+/// token.
+static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
+ bool GreaterThanIsOperator,
+ bool CPlusPlus0x) {
+ switch (Kind) {
+ case tok::greater:
+ // C++ [temp.names]p3:
+ // [...] When parsing a template-argument-list, the first
+ // non-nested > is taken as the ending delimiter rather than a
+ // greater-than operator. [...]
+ if (GreaterThanIsOperator)
+ return prec::Relational;
+ return prec::Unknown;
+
+ case tok::greatergreater:
+ // C++0x [temp.names]p3:
+ //
+ // [...] Similarly, the first non-nested >> is treated as two
+ // consecutive but distinct > tokens, the first of which is
+ // taken as the end of the template-argument-list and completes
+ // the template-id. [...]
+ if (GreaterThanIsOperator || !CPlusPlus0x)
+ return prec::Shift;
+ return prec::Unknown;
+
+ default: return prec::Unknown;
+ case tok::comma: return prec::Comma;
+ case tok::equal:
+ case tok::starequal:
+ case tok::slashequal:
+ case tok::percentequal:
+ case tok::plusequal:
+ case tok::minusequal:
+ case tok::lesslessequal:
+ case tok::greatergreaterequal:
+ case tok::ampequal:
+ case tok::caretequal:
+ case tok::pipeequal: return prec::Assignment;
+ case tok::question: return prec::Conditional;
+ case tok::pipepipe: return prec::LogicalOr;
+ case tok::ampamp: return prec::LogicalAnd;
+ case tok::pipe: return prec::InclusiveOr;
+ case tok::caret: return prec::ExclusiveOr;
+ case tok::amp: return prec::And;
+ case tok::exclaimequal:
+ case tok::equalequal: return prec::Equality;
+ case tok::lessequal:
+ case tok::less:
+ case tok::greaterequal: return prec::Relational;
+ case tok::lessless: return prec::Shift;
+ case tok::plus:
+ case tok::minus: return prec::Additive;
+ case tok::percent:
+ case tok::slash:
+ case tok::star: return prec::Multiplicative;
+ case tok::periodstar:
+ case tok::arrowstar: return prec::PointerToMember;
+ }
+}
+
+
+/// ParseExpression - Simple precedence-based parser for binary/ternary
+/// operators.
+///
+/// Note: we diverge from the C99 grammar when parsing the assignment-expression
+/// production. C99 specifies that the LHS of an assignment operator should be
+/// parsed as a unary-expression, but consistency dictates that it be a
+/// conditional-expession. In practice, the important thing here is that the
+/// LHS of an assignment has to be an l-value, which productions between
+/// unary-expression and conditional-expression don't produce. Because we want
+/// consistency, we parse the LHS as a conditional-expression, then check for
+/// l-value-ness in semantic analysis stages.
+///
+/// pm-expression: [C++ 5.5]
+/// cast-expression
+/// pm-expression '.*' cast-expression
+/// pm-expression '->*' cast-expression
+///
+/// multiplicative-expression: [C99 6.5.5]
+/// Note: in C++, apply pm-expression instead of cast-expression
+/// cast-expression
+/// multiplicative-expression '*' cast-expression
+/// multiplicative-expression '/' cast-expression
+/// multiplicative-expression '%' cast-expression
+///
+/// additive-expression: [C99 6.5.6]
+/// multiplicative-expression
+/// additive-expression '+' multiplicative-expression
+/// additive-expression '-' multiplicative-expression
+///
+/// shift-expression: [C99 6.5.7]
+/// additive-expression
+/// shift-expression '<<' additive-expression
+/// shift-expression '>>' additive-expression
+///
+/// relational-expression: [C99 6.5.8]
+/// shift-expression
+/// relational-expression '<' shift-expression
+/// relational-expression '>' shift-expression
+/// relational-expression '<=' shift-expression
+/// relational-expression '>=' shift-expression
+///
+/// equality-expression: [C99 6.5.9]
+/// relational-expression
+/// equality-expression '==' relational-expression
+/// equality-expression '!=' relational-expression
+///
+/// AND-expression: [C99 6.5.10]
+/// equality-expression
+/// AND-expression '&' equality-expression
+///
+/// exclusive-OR-expression: [C99 6.5.11]
+/// AND-expression
+/// exclusive-OR-expression '^' AND-expression
+///
+/// inclusive-OR-expression: [C99 6.5.12]
+/// exclusive-OR-expression
+/// inclusive-OR-expression '|' exclusive-OR-expression
+///
+/// logical-AND-expression: [C99 6.5.13]
+/// inclusive-OR-expression
+/// logical-AND-expression '&&' inclusive-OR-expression
+///
+/// logical-OR-expression: [C99 6.5.14]
+/// logical-AND-expression
+/// logical-OR-expression '||' logical-AND-expression
+///
+/// conditional-expression: [C99 6.5.15]
+/// logical-OR-expression
+/// logical-OR-expression '?' expression ':' conditional-expression
+/// [GNU] logical-OR-expression '?' ':' conditional-expression
+/// [C++] the third operand is an assignment-expression
+///
+/// assignment-expression: [C99 6.5.16]
+/// conditional-expression
+/// unary-expression assignment-operator assignment-expression
+/// [C++] throw-expression [C++ 15]
+///
+/// assignment-operator: one of
+/// = *= /= %= += -= <<= >>= &= ^= |=
+///
+/// expression: [C99 6.5.17]
+/// assignment-expression ...[opt]
+/// expression ',' assignment-expression ...[opt]
+///
+ExprResult Parser::ParseExpression() {
+ ExprResult LHS(ParseAssignmentExpression());
+ return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// This routine is called when the '@' is seen and consumed.
+/// Current token is an Identifier and is not a 'try'. This
+/// routine is necessary to disambiguate @try-statement from,
+/// for example, @encode-expression.
+///
+ExprResult
+Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
+ ExprResult LHS(ParseObjCAtExpression(AtLoc));
+ return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// This routine is called when a leading '__extension__' is seen and
+/// consumed. This is necessary because the token gets consumed in the
+/// process of disambiguating between an expression and a declaration.
+ExprResult
+Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
+ ExprResult LHS(true);
+ {
+ // Silence extension warnings in the sub-expression
+ ExtensionRAIIObject O(Diags);
+
+ LHS = ParseCastExpression(false);
+ }
+
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,
+ LHS.take());
+
+ return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+}
+
+/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
+///
+ExprResult Parser::ParseAssignmentExpression() {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.is(tok::kw_throw))
+ return ParseThrowExpression();
+
+ ExprResult LHS(ParseCastExpression(false));
+ return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
+}
+
+/// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression
+/// where part of an objc message send has already been parsed. In this case
+/// LBracLoc indicates the location of the '[' of the message send, and either
+/// ReceiverName or ReceiverExpr is non-null indicating the receiver of the
+/// message.
+///
+/// Since this handles full assignment-expression's, it handles postfix
+/// expressions and other binary operators for these expressions as well.
+ExprResult
+Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ ParsedType ReceiverType,
+ Expr *ReceiverExpr) {
+ ExprResult R
+ = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
+ ReceiverType, ReceiverExpr);
+ R = ParsePostfixExpressionSuffix(R);
+ return ParseRHSOfBinaryExpression(R, prec::Assignment);
+}
+
+
+ExprResult Parser::ParseConstantExpression() {
+ // C++ [basic.def.odr]p2:
+ // An expression is potentially evaluated unless it appears where an
+ // integral constant expression is required (see 5.19) [...].
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::Unevaluated);
+
+ ExprResult LHS(ParseCastExpression(false));
+ return ParseRHSOfBinaryExpression(LHS, prec::Conditional);
+}
+
+/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
+/// LHS and has a precedence of at least MinPrec.
+ExprResult
+Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
+ prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),
+ GreaterThanIsOperator,
+ getLang().CPlusPlus0x);
+ SourceLocation ColonLoc;
+
+ while (1) {
+ // If this token has a lower precedence than we are allowed to parse (e.g.
+ // because we are called recursively, or because the token is not a binop),
+ // then we are done!
+ if (NextTokPrec < MinPrec)
+ return move(LHS);
+
+ // Consume the operator, saving the operator token for error reporting.
+ Token OpToken = Tok;
+ ConsumeToken();
+
+ // Special case handling for the ternary operator.
+ ExprResult TernaryMiddle(true);
+ if (NextTokPrec == prec::Conditional) {
+ if (Tok.isNot(tok::colon)) {
+ // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
+ ColonProtectionRAIIObject X(*this);
+
+ // Handle this production specially:
+ // logical-OR-expression '?' expression ':' conditional-expression
+ // In particular, the RHS of the '?' is 'expression', not
+ // 'logical-OR-expression' as we might expect.
+ TernaryMiddle = ParseExpression();
+ if (TernaryMiddle.isInvalid()) {
+ LHS = ExprError();
+ TernaryMiddle = 0;
+ }
+ } else {
+ // Special case handling of "X ? Y : Z" where Y is empty:
+ // logical-OR-expression '?' ':' conditional-expression [GNU]
+ TernaryMiddle = 0;
+ Diag(Tok, diag::ext_gnu_conditional_expr);
+ }
+
+ if (Tok.is(tok::colon)) {
+ // Eat the colon.
+ ColonLoc = ConsumeToken();
+ } else {
+ // Otherwise, we're missing a ':'. Assume that this was a typo that the
+ // user forgot. If we're not in a macro instantion, we can suggest a
+ // fixit hint. If there were two spaces before the current token,
+ // suggest inserting the colon in between them, otherwise insert ": ".
+ SourceLocation FILoc = Tok.getLocation();
+ const char *FIText = ": ";
+ if (FILoc.isFileID()) {
+ const SourceManager &SM = PP.getSourceManager();
+ bool IsInvalid = false;
+ const char *SourcePtr =
+ SM.getCharacterData(FILoc.getFileLocWithOffset(-1), &IsInvalid);
+ if (!IsInvalid && *SourcePtr == ' ') {
+ SourcePtr =
+ SM.getCharacterData(FILoc.getFileLocWithOffset(-2), &IsInvalid);
+ if (!IsInvalid && *SourcePtr == ' ') {
+ FILoc = FILoc.getFileLocWithOffset(-1);
+ FIText = ":";
+ }
+ }
+ }
+
+ Diag(Tok, diag::err_expected_colon)
+ << FixItHint::CreateInsertion(FILoc, FIText);
+ Diag(OpToken, diag::note_matching) << "?";
+ ColonLoc = Tok.getLocation();
+ }
+ }
+
+ // Code completion for the right-hand side of an assignment expression
+ // goes through a special hook that takes the left-hand side into account.
+ if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
+ Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get());
+ ConsumeCodeCompletionToken();
+ return ExprError();
+ }
+
+ // Parse another leaf here for the RHS of the operator.
+ // ParseCastExpression works here because all RHS expressions in C have it
+ // as a prefix, at least. However, in C++, an assignment-expression could
+ // be a throw-expression, which is not a valid cast-expression.
+ // Therefore we need some special-casing here.
+ // Also note that the third operand of the conditional operator is
+ // an assignment-expression in C++.
+ ExprResult RHS;
+ if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
+ RHS = ParseAssignmentExpression();
+ else
+ RHS = ParseCastExpression(false);
+
+ if (RHS.isInvalid())
+ LHS = ExprError();
+
+ // Remember the precedence of this operator and get the precedence of the
+ // operator immediately to the right of the RHS.
+ prec::Level ThisPrec = NextTokPrec;
+ NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+ getLang().CPlusPlus0x);
+
+ // Assignment and conditional expressions are right-associative.
+ bool isRightAssoc = ThisPrec == prec::Conditional ||
+ ThisPrec == prec::Assignment;
+
+ // Get the precedence of the operator to the right of the RHS. If it binds
+ // more tightly with RHS than we do, evaluate it completely first.
+ if (ThisPrec < NextTokPrec ||
+ (ThisPrec == NextTokPrec && isRightAssoc)) {
+ // If this is left-associative, only parse things on the RHS that bind
+ // more tightly than the current operator. If it is left-associative, it
+ // is okay, to bind exactly as tightly. For example, compile A=B=C=D as
+ // A=(B=(C=D)), where each paren is a level of recursion here.
+ // The function takes ownership of the RHS.
+ RHS = ParseRHSOfBinaryExpression(RHS,
+ static_cast<prec::Level>(ThisPrec + !isRightAssoc));
+
+ if (RHS.isInvalid())
+ LHS = ExprError();
+
+ NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+ getLang().CPlusPlus0x);
+ }
+ assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
+
+ if (!LHS.isInvalid()) {
+ // Combine the LHS and RHS into the LHS (e.g. build AST).
+ if (TernaryMiddle.isInvalid()) {
+ // If we're using '>>' as an operator within a template
+ // argument list (in C++98), suggest the addition of
+ // parentheses so that the code remains well-formed in C++0x.
+ if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))
+ SuggestParentheses(OpToken.getLocation(),
+ diag::warn_cxx0x_right_shift_in_template_arg,
+ SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
+ Actions.getExprRange(RHS.get()).getEnd()));
+
+ LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
+ OpToken.getKind(), LHS.take(), RHS.take());
+ } else
+ LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
+ LHS.take(), TernaryMiddle.take(),
+ RHS.take());
+ }
+ }
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers.
+///
+ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ ParsedType TypeOfCast) {
+ bool NotCastExpr;
+ ExprResult Res = ParseCastExpression(isUnaryExpression,
+ isAddressOfOperand,
+ NotCastExpr,
+ TypeOfCast);
+ if (NotCastExpr)
+ Diag(Tok, diag::err_expected_expression);
+ return move(Res);
+}
+
+/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers. NotCastExpr is set to true if the token is not the
+/// start of a cast-expression, and no diagnostic is emitted in this case.
+///
+/// cast-expression: [C99 6.5.4]
+/// unary-expression
+/// '(' type-name ')' cast-expression
+///
+/// unary-expression: [C99 6.5.3]
+/// postfix-expression
+/// '++' unary-expression
+/// '--' unary-expression
+/// unary-operator cast-expression
+/// 'sizeof' unary-expression
+/// 'sizeof' '(' type-name ')'
+/// [C++0x] 'sizeof' '...' '(' identifier ')'
+/// [GNU] '__alignof' unary-expression
+/// [GNU] '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+/// [GNU] '&&' identifier
+/// [C++] new-expression
+/// [C++] delete-expression
+/// [C++0x] 'noexcept' '(' expression ')'
+///
+/// unary-operator: one of
+/// '&' '*' '+' '-' '~' '!'
+/// [GNU] '__extension__' '__real' '__imag'
+///
+/// primary-expression: [C99 6.5.1]
+/// [C99] identifier
+/// [C++] id-expression
+/// constant
+/// string-literal
+/// [C++] boolean-literal [C++ 2.13.5]
+/// [C++0x] 'nullptr' [C++0x 2.14.7]
+/// '(' expression ')'
+/// '__func__' [C99 6.4.2.2]
+/// [GNU] '__FUNCTION__'
+/// [GNU] '__PRETTY_FUNCTION__'
+/// [GNU] '(' compound-statement ')'
+/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
+/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
+/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
+/// assign-expr ')'
+/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+/// [GNU] '__null'
+/// [OBJC] '[' objc-message-expr ']'
+/// [OBJC] '@selector' '(' objc-selector-arg ')'
+/// [OBJC] '@protocol' '(' identifier ')'
+/// [OBJC] '@encode' '(' type-name ')'
+/// [OBJC] objc-string-literal
+/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
+/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
+/// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
+/// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
+/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
+/// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
+/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
+/// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]
+/// [C++] 'this' [C++ 9.3.2]
+/// [G++] unary-type-trait '(' type-id ')'
+/// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
+/// [clang] '^' block-literal
+///
+/// constant: [C99 6.4.4]
+/// integer-constant
+/// floating-constant
+/// enumeration-constant -> identifier
+/// character-constant
+///
+/// id-expression: [C++ 5.1]
+/// unqualified-id
+/// qualified-id
+///
+/// unqualified-id: [C++ 5.1]
+/// identifier
+/// operator-function-id
+/// conversion-function-id
+/// '~' class-name
+/// template-id
+///
+/// new-expression: [C++ 5.3.4]
+/// '::'[opt] 'new' new-placement[opt] new-type-id
+/// new-initializer[opt]
+/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+/// new-initializer[opt]
+///
+/// delete-expression: [C++ 5.3.5]
+/// '::'[opt] 'delete' cast-expression
+/// '::'[opt] 'delete' '[' ']' cast-expression
+///
+/// [GNU] unary-type-trait:
+/// '__has_nothrow_assign'
+/// '__has_nothrow_copy'
+/// '__has_nothrow_constructor'
+/// '__has_trivial_assign' [TODO]
+/// '__has_trivial_copy' [TODO]
+/// '__has_trivial_constructor'
+/// '__has_trivial_destructor'
+/// '__has_virtual_destructor'
+/// '__is_abstract' [TODO]
+/// '__is_class'
+/// '__is_empty' [TODO]
+/// '__is_enum'
+/// '__is_pod'
+/// '__is_polymorphic'
+/// '__is_union'
+///
+/// binary-type-trait:
+/// [GNU] '__is_base_of'
+/// [MS] '__is_convertible_to'
+///
+ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ bool &NotCastExpr,
+ ParsedType TypeOfCast) {
+ ExprResult Res;
+ tok::TokenKind SavedKind = Tok.getKind();
+ NotCastExpr = false;
+
+ // This handles all of cast-expression, unary-expression, postfix-expression,
+ // and primary-expression. We handle them together like this for efficiency
+ // and to simplify handling of an expression starting with a '(' token: which
+ // may be one of a parenthesized expression, cast-expression, compound literal
+ // expression, or statement expression.
+ //
+ // If the parsed tokens consist of a primary-expression, the cases below
+ // break out of the switch; at the end we call ParsePostfixExpressionSuffix
+ // to handle the postfix expression suffixes. Cases that cannot be followed
+ // by postfix exprs should return without invoking
+ // ParsePostfixExpressionSuffix.
+ switch (SavedKind) {
+ case tok::l_paren: {
+ // If this expression is limited to being a unary-expression, the parent can
+ // not start a cast expression.
+ ParenParseOption ParenExprType =
+ (isUnaryExpression && !getLang().CPlusPlus)? CompoundLiteral : CastExpr;
+ ParsedType CastTy;
+ SourceLocation RParenLoc;
+
+ {
+ // The inside of the parens don't need to be a colon protected scope, and
+ // isn't immediately a message send.
+ ColonProtectionRAIIObject X(*this, false);
+
+ Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
+ TypeOfCast, CastTy, RParenLoc);
+ }
+
+ switch (ParenExprType) {
+ case SimpleExpr: break; // Nothing else to do.
+ case CompoundStmt: break; // Nothing else to do.
+ case CompoundLiteral:
+ // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
+ // postfix-expression exist, parse them now.
+ break;
+ case CastExpr:
+ // We have parsed the cast-expression and no postfix-expr pieces are
+ // following.
+ return move(Res);
+ }
+
+ break;
+ }
+
+ // primary-expression
+ case tok::numeric_constant:
+ // constant: integer-constant
+ // constant: floating-constant
+
+ Res = Actions.ActOnNumericConstant(Tok);
+ ConsumeToken();
+ break;
+
+ case tok::kw_true:
+ case tok::kw_false:
+ return ParseCXXBoolLiteral();
+
+ case tok::kw_nullptr:
+ return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
+
+ case tok::identifier: { // primary-expression: identifier
+ // unqualified-id: identifier
+ // constant: enumeration-constant
+ // Turn a potentially qualified name into a annot_typename or
+ // annot_cxxscope if it would be valid. This handles things like x::y, etc.
+ if (getLang().CPlusPlus) {
+ // Avoid the unnecessary parse-time lookup in the common case
+ // where the syntax forbids a type.
+ const Token &Next = NextToken();
+ if (Next.is(tok::coloncolon) ||
+ (!ColonIsSacred && Next.is(tok::colon)) ||
+ Next.is(tok::less) ||
+ Next.is(tok::l_paren)) {
+ // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
+ if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ if (!Tok.is(tok::identifier))
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+ }
+ }
+
+ // Consume the identifier so that we can see if it is followed by a '(' or
+ // '.'.
+ IdentifierInfo &II = *Tok.getIdentifierInfo();
+ SourceLocation ILoc = ConsumeToken();
+
+ // Support 'Class.property' and 'super.property' notation.
+ if (getLang().ObjC1 && Tok.is(tok::period) &&
+ (Actions.getTypeName(II, ILoc, getCurScope()) ||
+ // Allow the base to be 'super' if in an objc-method.
+ (&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {
+ ConsumeToken();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_property_name);
+ return ExprError();
+ }
+ IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
+ SourceLocation PropertyLoc = ConsumeToken();
+
+ Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
+ ILoc, PropertyLoc);
+ break;
+ }
+
+ // In an Objective-C method, if we have "super" followed by an identifier,
+ // the token sequence is ill-formed. However, if there's a ':' or ']' after
+ // that identifier, this is probably a message send with a missing open
+ // bracket. Treat it as such.
+ if (getLang().ObjC1 && &II == Ident_super && !InMessageExpression &&
+ getCurScope()->isInObjcMethodScope() &&
+ ((Tok.is(tok::identifier) &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
+ Tok.is(tok::code_completion))) {
+ Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
+ 0);
+ break;
+ }
+
+ // If we have an Objective-C class name followed by an identifier
+ // and either ':' or ']', this is an Objective-C class message
+ // send that's missing the opening '['. Recovery
+ // appropriately. Also take this path if we're performing code
+ // completion after an Objective-C class name.
+ if (getLang().ObjC1 &&
+ ((Tok.is(tok::identifier) && !InMessageExpression) ||
+ Tok.is(tok::code_completion))) {
+ const Token& Next = NextToken();
+ if (Tok.is(tok::code_completion) ||
+ Next.is(tok::colon) || Next.is(tok::r_square))
+ if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))
+ if (Typ.get()->isObjCObjectOrInterfaceType()) {
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(ILoc);
+ DS.SetRangeEnd(ILoc);
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
+ DeclaratorInfo);
+ if (Ty.isInvalid())
+ break;
+
+ Res = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
+ Ty.get(), 0);
+ break;
+ }
+ }
+
+ // Make sure to pass down the right value for isAddressOfOperand.
+ if (isAddressOfOperand && isPostfixExpressionSuffixStart())
+ isAddressOfOperand = false;
+
+ // Function designators are allowed to be undeclared (C99 6.5.1p2), so we
+ // need to know whether or not this identifier is a function designator or
+ // not.
+ UnqualifiedId Name;
+ CXXScopeSpec ScopeSpec;
+ Name.setIdentifier(&II, ILoc);
+ Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, Name,
+ Tok.is(tok::l_paren), isAddressOfOperand);
+ break;
+ }
+ case tok::char_constant: // constant: character-constant
+ Res = Actions.ActOnCharacterConstant(Tok);
+ ConsumeToken();
+ break;
+ case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
+ case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
+ Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
+ ConsumeToken();
+ break;
+ case tok::string_literal: // primary-expression: string-literal
+ case tok::wide_string_literal:
+ Res = ParseStringLiteralExpression();
+ break;
+ case tok::kw___builtin_va_arg:
+ case tok::kw___builtin_offsetof:
+ case tok::kw___builtin_choose_expr:
+ return ParseBuiltinPrimaryExpression();
+ case tok::kw___null:
+ return Actions.ActOnGNUNullExpr(ConsumeToken());
+ break;
+ case tok::plusplus: // unary-expression: '++' unary-expression [C99]
+ case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
+ // C++ [expr.unary] has:
+ // unary-expression:
+ // ++ cast-expression
+ // -- cast-expression
+ SourceLocation SavedLoc = ConsumeToken();
+ Res = ParseCastExpression(!getLang().CPlusPlus);
+ if (!Res.isInvalid())
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ return move(Res);
+ }
+ case tok::amp: { // unary-expression: '&' cast-expression
+ // Special treatment because of member pointers
+ SourceLocation SavedLoc = ConsumeToken();
+ Res = ParseCastExpression(false, true);
+ if (!Res.isInvalid())
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ return move(Res);
+ }
+
+ case tok::star: // unary-expression: '*' cast-expression
+ case tok::plus: // unary-expression: '+' cast-expression
+ case tok::minus: // unary-expression: '-' cast-expression
+ case tok::tilde: // unary-expression: '~' cast-expression
+ case tok::exclaim: // unary-expression: '!' cast-expression
+ case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
+ case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]
+ SourceLocation SavedLoc = ConsumeToken();
+ Res = ParseCastExpression(false);
+ if (!Res.isInvalid())
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ return move(Res);
+ }
+
+ case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
+ // __extension__ silences extension warnings in the subexpression.
+ ExtensionRAIIObject O(Diags); // Use RAII to do this.
+ SourceLocation SavedLoc = ConsumeToken();
+ Res = ParseCastExpression(false);
+ if (!Res.isInvalid())
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ return move(Res);
+ }
+ case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
+ // unary-expression: 'sizeof' '(' type-name ')'
+ case tok::kw_alignof:
+ case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
+ // unary-expression: '__alignof' '(' type-name ')'
+ // unary-expression: 'alignof' '(' type-id ')'
+ return ParseSizeofAlignofExpression();
+ case tok::ampamp: { // unary-expression: '&&' identifier
+ SourceLocation AmpAmpLoc = ConsumeToken();
+ if (Tok.isNot(tok::identifier))
+ return ExprError(Diag(Tok, diag::err_expected_ident));
+
+ if (getCurScope()->getFnParent() == 0)
+ return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
+
+ Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
+ LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
+ Tok.getLocation());
+ Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);
+ ConsumeToken();
+ return move(Res);
+ }
+ case tok::kw_const_cast:
+ case tok::kw_dynamic_cast:
+ case tok::kw_reinterpret_cast:
+ case tok::kw_static_cast:
+ Res = ParseCXXCasts();
+ break;
+ case tok::kw_typeid:
+ Res = ParseCXXTypeid();
+ break;
+ case tok::kw___uuidof:
+ Res = ParseCXXUuidof();
+ break;
+ case tok::kw_this:
+ Res = ParseCXXThis();
+ break;
+
+ case tok::annot_typename:
+ if (isStartOfObjCClassMessageMissingOpenBracket()) {
+ ParsedType Type = getTypeAnnotation(Tok);
+
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(Tok.getLocation());
+ DS.SetRangeEnd(Tok.getLastLoc());
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
+ PrevSpec, DiagID, Type);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ if (Ty.isInvalid())
+ break;
+
+ ConsumeToken();
+ Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
+ Ty.get(), 0);
+ break;
+ }
+ // Fall through
+
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_bool:
+ case tok::kw_short:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_void:
+ case tok::kw_typename:
+ case tok::kw_typeof:
+ case tok::kw___vector: {
+ if (!getLang().CPlusPlus) {
+ Diag(Tok, diag::err_expected_expression);
+ return ExprError();
+ }
+
+ if (SavedKind == tok::kw_typename) {
+ // postfix-expression: typename-specifier '(' expression-list[opt] ')'
+ if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ }
+
+ // postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
+ //
+ DeclSpec DS;
+ ParseCXXSimpleTypeSpecifier(DS);
+ if (Tok.isNot(tok::l_paren))
+ return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
+ << DS.getSourceRange());
+
+ Res = ParseCXXTypeConstructExpression(DS);
+ break;
+ }
+
+ case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
+ // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
+ // (We can end up in this situation after tentative parsing.)
+ if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ if (!Tok.is(tok::annot_cxxscope))
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, TypeOfCast);
+
+ Token Next = NextToken();
+ if (Next.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Type_template) {
+ // We have a qualified template-id that we know refers to a
+ // type, translate it into a type and continue parsing as a
+ // cast expression.
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ AnnotateTemplateIdTokenAsType(&SS);
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, TypeOfCast);
+ }
+ }
+
+ // Parse as an id-expression.
+ Res = ParseCXXIdExpression(isAddressOfOperand);
+ break;
+ }
+
+ case tok::annot_template_id: { // [C++] template-id
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Type_template) {
+ // We have a template-id that we know refers to a type,
+ // translate it into a type and continue parsing as a cast
+ // expression.
+ AnnotateTemplateIdTokenAsType();
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, TypeOfCast);
+ }
+
+ // Fall through to treat the template-id as an id-expression.
+ }
+
+ case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
+ Res = ParseCXXIdExpression(isAddressOfOperand);
+ break;
+
+ case tok::coloncolon: {
+ // ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
+ // annotates the token, tail recurse.
+ if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ if (!Tok.is(tok::coloncolon))
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+
+ // ::new -> [C++] new-expression
+ // ::delete -> [C++] delete-expression
+ SourceLocation CCLoc = ConsumeToken();
+ if (Tok.is(tok::kw_new))
+ return ParseCXXNewExpression(true, CCLoc);
+ if (Tok.is(tok::kw_delete))
+ return ParseCXXDeleteExpression(true, CCLoc);
+
+ // This is not a type name or scope specifier, it is an invalid expression.
+ Diag(CCLoc, diag::err_expected_expression);
+ return ExprError();
+ }
+
+ case tok::kw_new: // [C++] new-expression
+ return ParseCXXNewExpression(false, Tok.getLocation());
+
+ case tok::kw_delete: // [C++] delete-expression
+ return ParseCXXDeleteExpression(false, Tok.getLocation());
+
+ case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
+ SourceLocation KeyLoc = ConsumeToken();
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren,
+ diag::err_expected_lparen_after, "noexcept"))
+ return ExprError();
+ // C++ [expr.unary.noexcept]p1:
+ // The noexcept operator determines whether the evaluation of its operand,
+ // which is an unevaluated operand, can throw an exception.
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ ExprResult Result = ParseExpression();
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+ if (!Result.isInvalid())
+ Result = Actions.ActOnNoexceptExpr(KeyLoc, LParen, Result.take(), RParen);
+ return move(Result);
+ }
+
+ case tok::kw___is_pod: // [GNU] unary-type-trait
+ case tok::kw___is_class:
+ case tok::kw___is_enum:
+ case tok::kw___is_union:
+ case tok::kw___is_empty:
+ case tok::kw___is_polymorphic:
+ case tok::kw___is_abstract:
+ case tok::kw___is_literal:
+ case tok::kw___has_trivial_constructor:
+ case tok::kw___has_trivial_copy:
+ case tok::kw___has_trivial_assign:
+ case tok::kw___has_trivial_destructor:
+ case tok::kw___has_nothrow_assign:
+ case tok::kw___has_nothrow_copy:
+ case tok::kw___has_nothrow_constructor:
+ case tok::kw___has_virtual_destructor:
+ return ParseUnaryTypeTrait();
+
+ case tok::kw___builtin_types_compatible_p:
+ case tok::kw___is_base_of:
+ case tok::kw___is_convertible_to:
+ return ParseBinaryTypeTrait();
+
+ case tok::at: {
+ SourceLocation AtLoc = ConsumeToken();
+ return ParseObjCAtExpression(AtLoc);
+ }
+ case tok::caret:
+ return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
+ case tok::code_completion:
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+ ConsumeCodeCompletionToken();
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, TypeOfCast);
+ case tok::l_square:
+ // These can be followed by postfix-expr pieces.
+ if (getLang().ObjC1)
+ return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
+ // FALL THROUGH.
+ default:
+ NotCastExpr = true;
+ return ExprError();
+ }
+
+ // These can be followed by postfix-expr pieces.
+ return ParsePostfixExpressionSuffix(Res);
+}
+
+/// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
+/// is parsed, this method parses any suffixes that apply.
+///
+/// postfix-expression: [C99 6.5.2]
+/// primary-expression
+/// postfix-expression '[' expression ']'
+/// postfix-expression '(' argument-expression-list[opt] ')'
+/// postfix-expression '.' identifier
+/// postfix-expression '->' identifier
+/// postfix-expression '++'
+/// postfix-expression '--'
+/// '(' type-name ')' '{' initializer-list '}'
+/// '(' type-name ')' '{' initializer-list ',' '}'
+///
+/// argument-expression-list: [C99 6.5.2]
+/// argument-expression ...[opt]
+/// argument-expression-list ',' assignment-expression ...[opt]
+///
+ExprResult
+Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
+ // Now that the primary-expression piece of the postfix-expression has been
+ // parsed, see if there are any postfix-expression pieces here.
+ SourceLocation Loc;
+ while (1) {
+ switch (Tok.getKind()) {
+ case tok::code_completion:
+ if (InMessageExpression)
+ return move(LHS);
+
+ Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
+ ConsumeCodeCompletionToken();
+ LHS = ExprError();
+ break;
+
+ case tok::identifier:
+ // If we see identifier: after an expression, and we're not already in a
+ // message send, then this is probably a message send with a missing
+ // opening bracket '['.
+ if (getLang().ObjC1 && !InMessageExpression &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
+ LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
+ ParsedType(), LHS.get());
+ break;
+ }
+
+ // Fall through; this isn't a message send.
+
+ default: // Not a postfix-expression suffix.
+ return move(LHS);
+ case tok::l_square: { // postfix-expression: p-e '[' expression ']'
+ // If we have a array postfix expression that starts on a new line and
+ // Objective-C is enabled, it is highly likely that the user forgot a
+ // semicolon after the base expression and that the array postfix-expr is
+ // actually another message send. In this case, do some look-ahead to see
+ // if the contents of the square brackets are obviously not a valid
+ // expression and recover by pretending there is no suffix.
+ if (getLang().ObjC1 && Tok.isAtStartOfLine() &&
+ isSimpleObjCMessageExpression())
+ return move(LHS);
+
+ Loc = ConsumeBracket();
+ ExprResult Idx(ParseExpression());
+
+ SourceLocation RLoc = Tok.getLocation();
+
+ if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
+ LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.take(), Loc,
+ Idx.take(), RLoc);
+ } else
+ LHS = ExprError();
+
+ // Match the ']'.
+ MatchRHSPunctuation(tok::r_square, Loc);
+ break;
+ }
+
+ case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
+ case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'
+ // '(' argument-expression-list[opt] ')'
+ tok::TokenKind OpKind = Tok.getKind();
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
+ Expr *ExecConfig = 0;
+
+ if (OpKind == tok::lesslessless) {
+ ExprVector ExecConfigExprs(Actions);
+ CommaLocsTy ExecConfigCommaLocs;
+ SourceLocation LLLLoc, GGGLoc;
+
+ LLLLoc = ConsumeToken();
+
+ if (ParseExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
+ LHS = ExprError();
+ }
+
+ if (LHS.isInvalid()) {
+ SkipUntil(tok::greatergreatergreater);
+ } else if (Tok.isNot(tok::greatergreatergreater)) {
+ MatchRHSPunctuation(tok::greatergreatergreater, LLLLoc);
+ LHS = ExprError();
+ } else {
+ GGGLoc = ConsumeToken();
+ }
+
+ if (!LHS.isInvalid()) {
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+ LHS = ExprError();
+ else
+ Loc = PrevTokLocation;
+ }
+
+ if (!LHS.isInvalid()) {
+ ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
+ LLLLoc, move_arg(ExecConfigExprs), GGGLoc);
+ if (ECResult.isInvalid())
+ LHS = ExprError();
+ else
+ ExecConfig = ECResult.get();
+ }
+ } else {
+ Loc = ConsumeParen();
+ }
+
+ ExprVector ArgExprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteCall(getCurScope(), LHS.get(), 0, 0);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (OpKind == tok::l_paren || !LHS.isInvalid()) {
+ if (Tok.isNot(tok::r_paren)) {
+ if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
+ LHS.get())) {
+ SkipUntil(tok::r_paren);
+ LHS = ExprError();
+ }
+ }
+ }
+
+ // Match the ')'.
+ if (LHS.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ } else if (Tok.isNot(tok::r_paren)) {
+ MatchRHSPunctuation(tok::r_paren, Loc);
+ LHS = ExprError();
+ } else {
+ assert((ArgExprs.size() == 0 ||
+ ArgExprs.size()-1 == CommaLocs.size())&&
+ "Unexpected number of commas!");
+ LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
+ move_arg(ArgExprs), Tok.getLocation(),
+ ExecConfig);
+ ConsumeParen();
+ }
+
+ break;
+ }
+ case tok::arrow:
+ case tok::period: {
+ // postfix-expression: p-e '->' template[opt] id-expression
+ // postfix-expression: p-e '.' template[opt] id-expression
+ tok::TokenKind OpKind = Tok.getKind();
+ SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
+
+ CXXScopeSpec SS;
+ ParsedType ObjectType;
+ bool MayBePseudoDestructor = false;
+ if (getLang().CPlusPlus && !LHS.isInvalid()) {
+ LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), LHS.take(),
+ OpLoc, OpKind, ObjectType,
+ MayBePseudoDestructor);
+ if (LHS.isInvalid())
+ break;
+
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
+ &MayBePseudoDestructor);
+ if (SS.isNotEmpty())
+ ObjectType = ParsedType();
+ }
+
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a member access expression.
+ Actions.CodeCompleteMemberReferenceExpr(getCurScope(), LHS.get(),
+ OpLoc, OpKind == tok::arrow);
+
+ ConsumeCodeCompletionToken();
+ }
+
+ if (MayBePseudoDestructor && !LHS.isInvalid()) {
+ LHS = ParseCXXPseudoDestructor(LHS.take(), OpLoc, OpKind, SS,
+ ObjectType);
+ break;
+ }
+
+ // Either the action has told is that this cannot be a
+ // pseudo-destructor expression (based on the type of base
+ // expression), or we didn't see a '~' in the right place. We
+ // can still parse a destructor name here, but in that case it
+ // names a real destructor.
+ // Allow explicit constructor calls in Microsoft mode.
+ // FIXME: Add support for explicit call of template constructor.
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/ getLang().Microsoft,
+ ObjectType,
+ Name))
+ LHS = ExprError();
+
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc,
+ OpKind, SS, Name, ObjCImpDecl,
+ Tok.is(tok::l_paren));
+ break;
+ }
+ case tok::plusplus: // postfix-expression: postfix-expression '++'
+ case tok::minusminus: // postfix-expression: postfix-expression '--'
+ if (!LHS.isInvalid()) {
+ LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
+ Tok.getKind(), LHS.take());
+ }
+ ConsumeToken();
+ break;
+ }
+ }
+}
+
+/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
+/// we are at the start of an expression or a parenthesized type-id.
+/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
+/// (isCastExpr == false) or the type (isCastExpr == true).
+///
+/// unary-expression: [C99 6.5.3]
+/// 'sizeof' unary-expression
+/// 'sizeof' '(' type-name ')'
+/// [GNU] '__alignof' unary-expression
+/// [GNU] '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+///
+/// [GNU] typeof-specifier:
+/// typeof ( expressions )
+/// typeof ( type-name )
+/// [GNU/C++] typeof unary-expression
+///
+ExprResult
+Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+ bool &isCastExpr,
+ ParsedType &CastTy,
+ SourceRange &CastRange) {
+
+ assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
+ OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
+ "Not a typeof/sizeof/alignof expression!");
+
+ ExprResult Operand;
+
+ // If the operand doesn't start with an '(', it must be an expression.
+ if (Tok.isNot(tok::l_paren)) {
+ isCastExpr = false;
+ if (OpTok.is(tok::kw_typeof) && !getLang().CPlusPlus) {
+ Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
+ return ExprError();
+ }
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::Unevaluated);
+ Operand = ParseCastExpression(true/*isUnaryExpression*/);
+ } else {
+ // If it starts with a '(', we know that it is either a parenthesized
+ // type-name, or it is a unary-expression that starts with a compound
+ // literal, or starts with a primary-expression that is a parenthesized
+ // expression.
+ ParenParseOption ExprType = CastExpr;
+ SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::Unevaluated);
+ Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
+ ParsedType(), CastTy, RParenLoc);
+ CastRange = SourceRange(LParenLoc, RParenLoc);
+
+ // If ParseParenExpression parsed a '(typename)' sequence only, then this is
+ // a type.
+ if (ExprType == CastExpr) {
+ isCastExpr = true;
+ return ExprEmpty();
+ }
+
+ if (getLang().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
+ // GNU typeof in C requires the expression to be parenthesized. Not so for
+ // sizeof/alignof or in C++. Therefore, the parenthesized expression is
+ // the start of a unary-expression, but doesn't include any postfix
+ // pieces. Parse these now if present.
+ if (!Operand.isInvalid())
+ Operand = ParsePostfixExpressionSuffix(Operand.get());
+ }
+ }
+
+ // If we get here, the operand to the typeof/sizeof/alignof was an expresion.
+ isCastExpr = false;
+ return move(Operand);
+}
+
+
+/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
+/// unary-expression: [C99 6.5.3]
+/// 'sizeof' unary-expression
+/// 'sizeof' '(' type-name ')'
+/// [C++0x] 'sizeof' '...' '(' identifier ')'
+/// [GNU] '__alignof' unary-expression
+/// [GNU] '__alignof' '(' type-name ')'
+/// [C++0x] 'alignof' '(' type-id ')'
+ExprResult Parser::ParseSizeofAlignofExpression() {
+ assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
+ || Tok.is(tok::kw_alignof)) &&
+ "Not a sizeof/alignof expression!");
+ Token OpTok = Tok;
+ ConsumeToken();
+
+ // [C++0x] 'sizeof' '...' '(' identifier ')'
+ if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {
+ SourceLocation EllipsisLoc = ConsumeToken();
+ SourceLocation LParenLoc, RParenLoc;
+ IdentifierInfo *Name = 0;
+ SourceLocation NameLoc;
+ if (Tok.is(tok::l_paren)) {
+ LParenLoc = ConsumeParen();
+ if (Tok.is(tok::identifier)) {
+ Name = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ if (RParenLoc.isInvalid())
+ RParenLoc = PP.getLocForEndOfToken(NameLoc);
+ } else {
+ Diag(Tok, diag::err_expected_parameter_pack);
+ SkipUntil(tok::r_paren);
+ }
+ } else if (Tok.is(tok::identifier)) {
+ Name = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+ LParenLoc = PP.getLocForEndOfToken(EllipsisLoc);
+ RParenLoc = PP.getLocForEndOfToken(NameLoc);
+ Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack)
+ << Name
+ << FixItHint::CreateInsertion(LParenLoc, "(")
+ << FixItHint::CreateInsertion(RParenLoc, ")");
+ } else {
+ Diag(Tok, diag::err_sizeof_parameter_pack);
+ }
+
+ if (!Name)
+ return ExprError();
+
+ return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
+ OpTok.getLocation(),
+ *Name, NameLoc,
+ RParenLoc);
+ }
+
+ bool isCastExpr;
+ ParsedType CastTy;
+ SourceRange CastRange;
+ ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+ isCastExpr,
+ CastTy,
+ CastRange);
+
+ if (isCastExpr)
+ return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
+ OpTok.is(tok::kw_sizeof),
+ /*isType=*/true,
+ CastTy.getAsOpaquePtr(),
+ CastRange);
+
+ // If we get here, the operand to the sizeof/alignof was an expresion.
+ if (!Operand.isInvalid())
+ Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
+ OpTok.is(tok::kw_sizeof),
+ /*isType=*/false,
+ Operand.release(), CastRange);
+ return move(Operand);
+}
+
+/// ParseBuiltinPrimaryExpression
+///
+/// primary-expression: [C99 6.5.1]
+/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
+/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
+/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
+/// assign-expr ')'
+/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+///
+/// [GNU] offsetof-member-designator:
+/// [GNU] identifier
+/// [GNU] offsetof-member-designator '.' identifier
+/// [GNU] offsetof-member-designator '[' expression ']'
+///
+ExprResult Parser::ParseBuiltinPrimaryExpression() {
+ ExprResult Res;
+ const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
+
+ tok::TokenKind T = Tok.getKind();
+ SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.
+
+ // All of these start with an open paren.
+ if (Tok.isNot(tok::l_paren))
+ return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
+ << BuiltinII);
+
+ SourceLocation LParenLoc = ConsumeParen();
+ // TODO: Build AST.
+
+ switch (T) {
+ default: assert(0 && "Not a builtin primary expression!");
+ case tok::kw___builtin_va_arg: {
+ ExprResult Expr(ParseAssignmentExpression());
+
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ Expr = ExprError();
+
+ TypeResult Ty = ParseTypeName();
+
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected_rparen);
+ Expr = ExprError();
+ }
+
+ if (Expr.isInvalid() || Ty.isInvalid())
+ Res = ExprError();
+ else
+ Res = Actions.ActOnVAArg(StartLoc, Expr.take(), Ty.get(), ConsumeParen());
+ break;
+ }
+ case tok::kw___builtin_offsetof: {
+ SourceLocation TypeLoc = Tok.getLocation();
+ TypeResult Ty = ParseTypeName();
+ if (Ty.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ return ExprError();
+
+ // We must have at least one identifier here.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ // Keep track of the various subcomponents we see.
+ llvm::SmallVector<Sema::OffsetOfComponent, 4> Comps;
+
+ Comps.push_back(Sema::OffsetOfComponent());
+ Comps.back().isBrackets = false;
+ Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+ Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
+
+ // FIXME: This loop leaks the index expressions on error.
+ while (1) {
+ if (Tok.is(tok::period)) {
+ // offsetof-member-designator: offsetof-member-designator '.' identifier
+ Comps.push_back(Sema::OffsetOfComponent());
+ Comps.back().isBrackets = false;
+ Comps.back().LocStart = ConsumeToken();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+ Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+ Comps.back().LocEnd = ConsumeToken();
+
+ } else if (Tok.is(tok::l_square)) {
+ // offsetof-member-designator: offsetof-member-design '[' expression ']'
+ Comps.push_back(Sema::OffsetOfComponent());
+ Comps.back().isBrackets = true;
+ Comps.back().LocStart = ConsumeBracket();
+ Res = ParseExpression();
+ if (Res.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return move(Res);
+ }
+ Comps.back().U.E = Res.release();
+
+ Comps.back().LocEnd =
+ MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
+ } else {
+ if (Tok.isNot(tok::r_paren)) {
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ Res = ExprError();
+ } else if (Ty.isInvalid()) {
+ Res = ExprError();
+ } else {
+ Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,
+ Ty.get(), &Comps[0],
+ Comps.size(), ConsumeParen());
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case tok::kw___builtin_choose_expr: {
+ ExprResult Cond(ParseAssignmentExpression());
+ if (Cond.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return move(Cond);
+ }
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ return ExprError();
+
+ ExprResult Expr1(ParseAssignmentExpression());
+ if (Expr1.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return move(Expr1);
+ }
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ return ExprError();
+
+ ExprResult Expr2(ParseAssignmentExpression());
+ if (Expr2.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return move(Expr2);
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected_rparen);
+ return ExprError();
+ }
+ Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
+ Expr2.take(), ConsumeParen());
+ break;
+ }
+ }
+
+ if (Res.isInvalid())
+ return ExprError();
+
+ // These can be followed by postfix-expr pieces because they are
+ // primary-expressions.
+ return ParsePostfixExpressionSuffix(Res.take());
+}
+
+/// ParseParenExpression - This parses the unit that starts with a '(' token,
+/// based on what is allowed by ExprType. The actual thing parsed is returned
+/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
+/// not the parsed cast-expression.
+///
+/// primary-expression: [C99 6.5.1]
+/// '(' expression ')'
+/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
+/// postfix-expression: [C99 6.5.2]
+/// '(' type-name ')' '{' initializer-list '}'
+/// '(' type-name ')' '{' initializer-list ',' '}'
+/// cast-expression: [C99 6.5.4]
+/// '(' type-name ')' cast-expression
+///
+ExprResult
+Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
+ ParsedType TypeOfCast, ParsedType &CastTy,
+ SourceLocation &RParenLoc) {
+ assert(Tok.is(tok::l_paren) && "Not a paren expr!");
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
+ SourceLocation OpenLoc = ConsumeParen();
+ ExprResult Result(true);
+ bool isAmbiguousTypeId;
+ CastTy = ParsedType();
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
+ ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression
+ : Sema::PCC_Expression);
+ ConsumeCodeCompletionToken();
+ return ExprError();
+ }
+
+ if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
+ Diag(Tok, diag::ext_gnu_statement_expr);
+ ParsedAttributes attrs;
+ StmtResult Stmt(ParseCompoundStatement(attrs, true));
+ ExprType = CompoundStmt;
+
+ // If the substmt parsed correctly, build the AST node.
+ if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
+ Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
+
+ } else if (ExprType >= CompoundLiteral &&
+ isTypeIdInParens(isAmbiguousTypeId)) {
+
+ // Otherwise, this is a compound literal expression or cast expression.
+
+ // In C++, if the type-id is ambiguous we disambiguate based on context.
+ // If stopIfCastExpr is true the context is a typeof/sizeof/alignof
+ // in which case we should treat it as type-id.
+ // if stopIfCastExpr is false, we need to determine the context past the
+ // parens, so we defer to ParseCXXAmbiguousParenExpression for that.
+ if (isAmbiguousTypeId && !stopIfCastExpr)
+ return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
+ OpenLoc, RParenLoc);
+
+ TypeResult Ty;
+
+ {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+ Ty = ParseTypeName();
+ }
+
+ // If our type is followed by an identifier and either ':' or ']', then
+ // this is probably an Objective-C message send where the leading '[' is
+ // missing. Recover as if that were the case.
+ if (!Ty.isInvalid() && Tok.is(tok::identifier) && !InMessageExpression &&
+ getLang().ObjC1 && !Ty.get().get().isNull() &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square)) &&
+ Ty.get().get()->isObjCObjectOrInterfaceType()) {
+ Result = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
+ Ty.get(), 0);
+ } else {
+ // Match the ')'.
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, OpenLoc);
+
+ if (Tok.is(tok::l_brace)) {
+ ExprType = CompoundLiteral;
+ return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
+ }
+
+ if (ExprType == CastExpr) {
+ // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ CastTy = Ty.get();
+
+ // Note that this doesn't parse the subsequent cast-expression, it just
+ // returns the parsed type to the callee.
+ if (stopIfCastExpr)
+ return ExprResult();
+
+ // Reject the cast of super idiom in ObjC.
+ if (Tok.is(tok::identifier) && getLang().ObjC1 &&
+ Tok.getIdentifierInfo() == Ident_super &&
+ getCurScope()->isInObjcMethodScope() &&
+ GetLookAheadToken(1).isNot(tok::period)) {
+ Diag(Tok.getLocation(), diag::err_illegal_super_cast)
+ << SourceRange(OpenLoc, RParenLoc);
+ return ExprError();
+ }
+
+ // Parse the cast-expression that follows it next.
+ // TODO: For cast expression with CastTy.
+ Result = ParseCastExpression(false, false, CastTy);
+ if (!Result.isInvalid())
+ Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy,
+ RParenLoc, Result.take());
+ return move(Result);
+ }
+
+ Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
+ return ExprError();
+ }
+ } else if (TypeOfCast) {
+ // Parse the expression-list.
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
+ ExprVector ArgExprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (!ParseExpressionList(ArgExprs, CommaLocs)) {
+ ExprType = SimpleExpr;
+ Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
+ move_arg(ArgExprs), TypeOfCast);
+ }
+ } else {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
+ Result = ParseExpression();
+ ExprType = SimpleExpr;
+ if (!Result.isInvalid() && Tok.is(tok::r_paren))
+ Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
+ }
+
+ // Match the ')'.
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, OpenLoc);
+
+ return move(Result);
+}
+
+/// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name
+/// and we are at the left brace.
+///
+/// postfix-expression: [C99 6.5.2]
+/// '(' type-name ')' '{' initializer-list '}'
+/// '(' type-name ')' '{' initializer-list ',' '}'
+///
+ExprResult
+Parser::ParseCompoundLiteralExpression(ParsedType Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ assert(Tok.is(tok::l_brace) && "Not a compound literal!");
+ if (!getLang().C99) // Compound literals don't exist in C90.
+ Diag(LParenLoc, diag::ext_c99_compound_literal);
+ ExprResult Result = ParseInitializer();
+ if (!Result.isInvalid() && Ty)
+ return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take());
+ return move(Result);
+}
+
+/// ParseStringLiteralExpression - This handles the various token types that
+/// form string literals, and also handles string concatenation [C99 5.1.1.2,
+/// translation phase #6].
+///
+/// primary-expression: [C99 6.5.1]
+/// string-literal
+ExprResult Parser::ParseStringLiteralExpression() {
+ assert(isTokenStringLiteral() && "Not a string literal!");
+
+ // String concat. Note that keywords like __func__ and __FUNCTION__ are not
+ // considered to be strings for concatenation purposes.
+ llvm::SmallVector<Token, 4> StringToks;
+
+ do {
+ StringToks.push_back(Tok);
+ ConsumeStringToken();
+ } while (isTokenStringLiteral());
+
+ // Pass the set of string tokens, ready for concatenation, to the actions.
+ return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
+}
+
+/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+///
+/// argument-expression-list:
+/// assignment-expression
+/// argument-expression-list , assignment-expression
+///
+/// [C++] expression-list:
+/// [C++] assignment-expression ...[opt]
+/// [C++] expression-list , assignment-expression ...[opt]
+///
+bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
+ llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S,
+ Expr *Data,
+ Expr **Args,
+ unsigned NumArgs),
+ Expr *Data) {
+ while (1) {
+ if (Tok.is(tok::code_completion)) {
+ if (Completer)
+ (Actions.*Completer)(getCurScope(), Data, Exprs.data(), Exprs.size());
+ else
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+ ConsumeCodeCompletionToken();
+ }
+
+ ExprResult Expr(ParseAssignmentExpression());
+ if (Tok.is(tok::ellipsis))
+ Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
+ if (Expr.isInvalid())
+ return true;
+
+ Exprs.push_back(Expr.release());
+
+ if (Tok.isNot(tok::comma))
+ return false;
+ // Move to the next argument, remember where the comma was.
+ CommaLocs.push_back(ConsumeToken());
+ }
+}
+
+/// ParseBlockId - Parse a block-id, which roughly looks like int (int x).
+///
+/// [clang] block-id:
+/// [clang] specifier-qualifier-list block-declarator
+///
+void Parser::ParseBlockId() {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
+ ConsumeCodeCompletionToken();
+ }
+
+ // Parse the specifier-qualifier-list piece.
+ DeclSpec DS;
+ ParseSpecifierQualifierList(DS);
+
+ // Parse the block-declarator.
+ Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
+ ParseDeclarator(DeclaratorInfo);
+
+ // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
+ DeclaratorInfo.addAttributes(DS.takeAttributes());
+
+ MaybeParseGNUAttributes(DeclaratorInfo);
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnBlockArguments(DeclaratorInfo, getCurScope());
+}
+
+/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
+/// like ^(int x){ return x+1; }
+///
+/// block-literal:
+/// [clang] '^' block-args[opt] compound-statement
+/// [clang] '^' block-id compound-statement
+/// [clang] block-args:
+/// [clang] '(' parameter-list ')'
+///
+ExprResult Parser::ParseBlockLiteralExpression() {
+ assert(Tok.is(tok::caret) && "block literal starts with ^");
+ SourceLocation CaretLoc = ConsumeToken();
+
+ PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
+ "block literal parsing");
+
+ // Enter a scope to hold everything within the block. This includes the
+ // argument decls, decls within the compound expression, etc. This also
+ // allows determining whether a variable reference inside the block is
+ // within or outside of the block.
+ ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
+ Scope::BreakScope | Scope::ContinueScope |
+ Scope::DeclScope);
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnBlockStart(CaretLoc, getCurScope());
+
+ // Parse the return type if present.
+ DeclSpec DS;
+ Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
+ // FIXME: Since the return type isn't actually parsed, it can't be used to
+ // fill ParamInfo with an initial valid range, so do it manually.
+ ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));
+
+ // If this block has arguments, parse them. There is no ambiguity here with
+ // the expression case, because the expression case requires a parameter list.
+ if (Tok.is(tok::l_paren)) {
+ ParseParenDeclarator(ParamInfo);
+ // Parse the pieces after the identifier as if we had "int(...)".
+ // SetIdentifier sets the source range end, but in this case we're past
+ // that location.
+ SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
+ ParamInfo.SetIdentifier(0, CaretLoc);
+ ParamInfo.SetRangeEnd(Tmp);
+ if (ParamInfo.isInvalidType()) {
+ // If there was an error parsing the arguments, they may have
+ // tried to use ^(x+y) which requires an argument list. Just
+ // skip the whole block literal.
+ Actions.ActOnBlockError(CaretLoc, getCurScope());
+ return ExprError();
+ }
+
+ MaybeParseGNUAttributes(ParamInfo);
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnBlockArguments(ParamInfo, getCurScope());
+ } else if (!Tok.is(tok::l_brace)) {
+ ParseBlockId();
+ } else {
+ // Otherwise, pretend we saw (void).
+ ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ true, false,
+ SourceLocation(),
+ 0, 0, 0,
+ true, SourceLocation(),
+ false, SourceLocation(),
+ false, 0, 0, 0,
+ CaretLoc, CaretLoc,
+ ParamInfo),
+ CaretLoc);
+
+ MaybeParseGNUAttributes(ParamInfo);
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnBlockArguments(ParamInfo, getCurScope());
+ }
+
+
+ ExprResult Result(true);
+ if (!Tok.is(tok::l_brace)) {
+ // Saw something like: ^expr
+ Diag(Tok, diag::err_expected_expression);
+ Actions.ActOnBlockError(CaretLoc, getCurScope());
+ return ExprError();
+ }
+
+ StmtResult Stmt(ParseCompoundStatementBody());
+ if (!Stmt.isInvalid())
+ Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
+ else
+ Actions.ActOnBlockError(CaretLoc, getCurScope());
+ return move(Result);
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
new file mode 100644
index 0000000..e73578f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -0,0 +1,2027 @@
+//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Expression parsing implementation for C++.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+/// \brief Parse global scope or nested-name-specifier if present.
+///
+/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
+/// may be preceded by '::'). Note that this routine will not parse ::new or
+/// ::delete; it will just leave them in the token stream.
+///
+/// '::'[opt] nested-name-specifier
+/// '::'
+///
+/// nested-name-specifier:
+/// type-name '::'
+/// namespace-name '::'
+/// nested-name-specifier identifier '::'
+/// nested-name-specifier 'template'[opt] simple-template-id '::'
+///
+///
+/// \param SS the scope specifier that will be set to the parsed
+/// nested-name-specifier (or empty)
+///
+/// \param ObjectType if this nested-name-specifier is being parsed following
+/// the "." or "->" of a member access expression, this parameter provides the
+/// type of the object whose members are being accessed.
+///
+/// \param EnteringContext whether we will be entering into the context of
+/// the nested-name-specifier after parsing it.
+///
+/// \param MayBePseudoDestructor When non-NULL, points to a flag that
+/// indicates whether this nested-name-specifier may be part of a
+/// pseudo-destructor name. In this case, the flag will be set false
+/// if we don't actually end up parsing a destructor name. Moreorover,
+/// if we do end up determining that we are parsing a destructor name,
+/// the last component of the nested-name-specifier is not parsed as
+/// part of the scope specifier.
+
+/// member access expression, e.g., the \p T:: in \p p->T::m.
+///
+/// \returns true if there was an error parsing a scope specifier
+bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ bool *MayBePseudoDestructor) {
+ assert(getLang().CPlusPlus &&
+ "Call sites of this function should be guarded by checking for C++");
+
+ if (Tok.is(tok::annot_cxxscope)) {
+ SS.setScopeRep(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue()));
+ SS.setRange(Tok.getAnnotationRange());
+ ConsumeToken();
+ return false;
+ }
+
+ bool HasScopeSpecifier = false;
+
+ if (Tok.is(tok::coloncolon)) {
+ // ::new and ::delete aren't nested-name-specifiers.
+ tok::TokenKind NextKind = NextToken().getKind();
+ if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
+ return false;
+
+ // '::' - Global scope qualifier.
+ SourceLocation CCLoc = ConsumeToken();
+ SS.setBeginLoc(CCLoc);
+ SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc));
+ SS.setEndLoc(CCLoc);
+ HasScopeSpecifier = true;
+ }
+
+ bool CheckForDestructor = false;
+ if (MayBePseudoDestructor && *MayBePseudoDestructor) {
+ CheckForDestructor = true;
+ *MayBePseudoDestructor = false;
+ }
+
+ while (true) {
+ if (HasScopeSpecifier) {
+ // C++ [basic.lookup.classref]p5:
+ // If the qualified-id has the form
+ //
+ // ::class-name-or-namespace-name::...
+ //
+ // the class-name-or-namespace-name is looked up in global scope as a
+ // class-name or namespace-name.
+ //
+ // To implement this, we clear out the object type as soon as we've
+ // seen a leading '::' or part of a nested-name-specifier.
+ ObjectType = ParsedType();
+
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a nested-name-specifier, where the code
+ // code completion token follows the '::'.
+ Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext);
+ ConsumeCodeCompletionToken();
+ }
+ }
+
+ // nested-name-specifier:
+ // nested-name-specifier 'template'[opt] simple-template-id '::'
+
+ // Parse the optional 'template' keyword, then make sure we have
+ // 'identifier <' after it.
+ if (Tok.is(tok::kw_template)) {
+ // If we don't have a scope specifier or an object type, this isn't a
+ // nested-name-specifier, since they aren't allowed to start with
+ // 'template'.
+ if (!HasScopeSpecifier && !ObjectType)
+ break;
+
+ TentativeParsingAction TPA(*this);
+ SourceLocation TemplateKWLoc = ConsumeToken();
+
+ UnqualifiedId TemplateName;
+ if (Tok.is(tok::identifier)) {
+ // Consume the identifier.
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken();
+ } else if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
+ TemplateName)) {
+ TPA.Commit();
+ break;
+ }
+
+ if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
+ TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
+ Diag(TemplateName.getSourceRange().getBegin(),
+ diag::err_id_after_template_in_nested_name_spec)
+ << TemplateName.getSourceRange();
+ TPA.Commit();
+ break;
+ }
+ } else {
+ TPA.Revert();
+ break;
+ }
+
+ // If the next token is not '<', we have a qualified-id that refers
+ // to a template name, such as T::template apply, but is not a
+ // template-id.
+ if (Tok.isNot(tok::less)) {
+ TPA.Revert();
+ break;
+ }
+
+ // Commit to parsing the template-id.
+ TPA.Commit();
+ TemplateTy Template;
+ if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName(getCurScope(),
+ TemplateKWLoc,
+ SS,
+ TemplateName,
+ ObjectType,
+ EnteringContext,
+ Template)) {
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
+ TemplateKWLoc, false))
+ return true;
+ } else
+ return true;
+
+ continue;
+ }
+
+ if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
+ // We have
+ //
+ // simple-template-id '::'
+ //
+ // So we need to check whether the simple-template-id is of the
+ // right kind (it should name a type or be dependent), and then
+ // convert it into a type within the nested-name-specifier.
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
+ *MayBePseudoDestructor = true;
+ return false;
+ }
+
+ if (TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) {
+ AnnotateTemplateIdTokenAsType(&SS);
+
+ assert(Tok.is(tok::annot_typename) &&
+ "AnnotateTemplateIdTokenAsType isn't working");
+ Token TypeToken = Tok;
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+ SourceLocation CCLoc = ConsumeToken();
+
+ if (!HasScopeSpecifier) {
+ SS.setBeginLoc(TypeToken.getLocation());
+ HasScopeSpecifier = true;
+ }
+
+ if (ParsedType T = getTypeAnnotation(TypeToken)) {
+ CXXScopeTy *Scope =
+ Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
+ TypeToken.getAnnotationRange(),
+ CCLoc);
+ SS.setScopeRep(Scope);
+ } else
+ SS.setScopeRep(0);
+ SS.setEndLoc(CCLoc);
+ continue;
+ }
+
+ assert(false && "FIXME: Only type template names supported here");
+ }
+
+
+ // The rest of the nested-name-specifier possibilities start with
+ // tok::identifier.
+ if (Tok.isNot(tok::identifier))
+ break;
+
+ IdentifierInfo &II = *Tok.getIdentifierInfo();
+
+ // nested-name-specifier:
+ // type-name '::'
+ // namespace-name '::'
+ // nested-name-specifier identifier '::'
+ Token Next = NextToken();
+
+ // If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
+ // and emit a fixit hint for it.
+ if (Next.is(tok::colon) && !ColonIsSacred) {
+ if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType,
+ EnteringContext) &&
+ // If the token after the colon isn't an identifier, it's still an
+ // error, but they probably meant something else strange so don't
+ // recover like this.
+ PP.LookAhead(1).is(tok::identifier)) {
+ Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ << FixItHint::CreateReplacement(Next.getLocation(), "::");
+
+ // Recover as if the user wrote '::'.
+ Next.setKind(tok::coloncolon);
+ }
+ }
+
+ if (Next.is(tok::coloncolon)) {
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) &&
+ !Actions.isNonTypeNestedNameSpecifier(getCurScope(), SS, Tok.getLocation(),
+ II, ObjectType)) {
+ *MayBePseudoDestructor = true;
+ return false;
+ }
+
+ // We have an identifier followed by a '::'. Lookup this name
+ // as the name in a nested-name-specifier.
+ SourceLocation IdLoc = ConsumeToken();
+ assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
+ "NextToken() not working properly!");
+ SourceLocation CCLoc = ConsumeToken();
+
+ if (!HasScopeSpecifier) {
+ SS.setBeginLoc(IdLoc);
+ HasScopeSpecifier = true;
+ }
+
+ if (!SS.isInvalid())
+ SS.setScopeRep(
+ Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II,
+ ObjectType, EnteringContext));
+ SS.setEndLoc(CCLoc);
+ continue;
+ }
+
+ // nested-name-specifier:
+ // type-name '<'
+ if (Next.is(tok::less)) {
+ TemplateTy Template;
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(&II, Tok.getLocation());
+ bool MemberOfUnknownSpecialization;
+ if (TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false,
+ TemplateName,
+ ObjectType,
+ EnteringContext,
+ Template,
+ MemberOfUnknownSpecialization)) {
+ // We have found a template name, so annotate this this token
+ // with a template-id annotation. We do not permit the
+ // template-id to be translated into a type annotation,
+ // because some clients (e.g., the parsing of class template
+ // specializations) still want to see the original template-id
+ // token.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
+ SourceLocation(), false))
+ return true;
+ continue;
+ }
+
+ if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
+ IsTemplateArgumentList(1)) {
+ // We have something like t::getAs<T>, where getAs is a
+ // member of an unknown specialization. However, this will only
+ // parse correctly as a template, so suggest the keyword 'template'
+ // before 'getAs' and treat this as a dependent template name.
+ Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword)
+ << II.getName()
+ << FixItHint::CreateInsertion(Tok.getLocation(), "template ");
+
+ if (TemplateNameKind TNK
+ = Actions.ActOnDependentTemplateName(getCurScope(),
+ Tok.getLocation(), SS,
+ TemplateName, ObjectType,
+ EnteringContext, Template)) {
+ // Consume the identifier.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
+ SourceLocation(), false))
+ return true;
+ }
+ else
+ return true;
+
+ continue;
+ }
+ }
+
+ // We don't have any tokens that form the beginning of a
+ // nested-name-specifier, so we're done.
+ break;
+ }
+
+ // Even if we didn't see any pieces of a nested-name-specifier, we
+ // still check whether there is a tilde in this position, which
+ // indicates a potential pseudo-destructor.
+ if (CheckForDestructor && Tok.is(tok::tilde))
+ *MayBePseudoDestructor = true;
+
+ return false;
+}
+
+/// ParseCXXIdExpression - Handle id-expression.
+///
+/// id-expression:
+/// unqualified-id
+/// qualified-id
+///
+/// qualified-id:
+/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+/// '::' identifier
+/// '::' operator-function-id
+/// '::' template-id
+///
+/// NOTE: The standard specifies that, for qualified-id, the parser does not
+/// expect:
+///
+/// '::' conversion-function-id
+/// '::' '~' class-name
+///
+/// This may cause a slight inconsistency on diagnostics:
+///
+/// class C {};
+/// namespace A {}
+/// void f() {
+/// :: A :: ~ C(); // Some Sema error about using destructor with a
+/// // namespace.
+/// :: ~ C(); // Some Parser error like 'unexpected ~'.
+/// }
+///
+/// We simplify the parser a bit and make it work like:
+///
+/// qualified-id:
+/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+/// '::' unqualified-id
+///
+/// That way Sema can handle and report similar errors for namespaces and the
+/// global scope.
+///
+/// The isAddressOfOperand parameter indicates that this id-expression is a
+/// direct operand of the address-of operator. This is, besides member contexts,
+/// the only place where a qualified-id naming a non-static class member may
+/// appear.
+///
+ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
+ // qualified-id:
+ // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
+ // '::' unqualified-id
+ //
+ CXXScopeSpec SS;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+
+ UnqualifiedId Name;
+ if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/false,
+ /*AllowConstructorName=*/false,
+ /*ObjectType=*/ ParsedType(),
+ Name))
+ return ExprError();
+
+ // This is only the direct operand of an & operator if it is not
+ // followed by a postfix-expression suffix.
+ if (isAddressOfOperand && isPostfixExpressionSuffixStart())
+ isAddressOfOperand = false;
+
+ return Actions.ActOnIdExpression(getCurScope(), SS, Name, Tok.is(tok::l_paren),
+ isAddressOfOperand);
+
+}
+
+/// ParseCXXCasts - This handles the various ways to cast expressions to another
+/// type.
+///
+/// postfix-expression: [C++ 5.2p1]
+/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
+/// 'static_cast' '<' type-name '>' '(' expression ')'
+/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
+/// 'const_cast' '<' type-name '>' '(' expression ')'
+///
+ExprResult Parser::ParseCXXCasts() {
+ tok::TokenKind Kind = Tok.getKind();
+ const char *CastName = 0; // For error messages
+
+ switch (Kind) {
+ default: assert(0 && "Unknown C++ cast!"); abort();
+ case tok::kw_const_cast: CastName = "const_cast"; break;
+ case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
+ case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
+ case tok::kw_static_cast: CastName = "static_cast"; break;
+ }
+
+ SourceLocation OpLoc = ConsumeToken();
+ SourceLocation LAngleBracketLoc = Tok.getLocation();
+
+ if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
+ return ExprError();
+
+ TypeResult CastTy = ParseTypeName();
+ SourceLocation RAngleBracketLoc = Tok.getLocation();
+
+ if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
+ return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
+
+ SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
+ return ExprError();
+
+ ExprResult Result = ParseExpression();
+
+ // Match the ')'.
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (!Result.isInvalid() && !CastTy.isInvalid())
+ Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
+ LAngleBracketLoc, CastTy.get(),
+ RAngleBracketLoc,
+ LParenLoc, Result.take(), RParenLoc);
+
+ return move(Result);
+}
+
+/// ParseCXXTypeid - This handles the C++ typeid expression.
+///
+/// postfix-expression: [C++ 5.2p1]
+/// 'typeid' '(' expression ')'
+/// 'typeid' '(' type-id ')'
+///
+ExprResult Parser::ParseCXXTypeid() {
+ assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
+
+ SourceLocation OpLoc = ConsumeToken();
+ SourceLocation LParenLoc = Tok.getLocation();
+ SourceLocation RParenLoc;
+
+ // typeid expressions are always parenthesized.
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "typeid"))
+ return ExprError();
+
+ ExprResult Result;
+
+ if (isTypeIdInParens()) {
+ TypeResult Ty = ParseTypeName();
+
+ // Match the ')'.
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (Ty.isInvalid() || RParenLoc.isInvalid())
+ return ExprError();
+
+ Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
+ Ty.get().getAsOpaquePtr(), RParenLoc);
+ } else {
+ // C++0x [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] The expression is an unevaluated
+ // operand (Clause 5).
+ //
+ // Note that we can't tell whether the expression is an lvalue of a
+ // polymorphic class type until after we've parsed the expression, so
+ // we the expression is potentially potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::PotentiallyPotentiallyEvaluated);
+ Result = ParseExpression();
+
+ // Match the ')'.
+ if (Result.isInvalid())
+ SkipUntil(tok::r_paren);
+ else {
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ if (RParenLoc.isInvalid())
+ return ExprError();
+
+ Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
+ Result.release(), RParenLoc);
+ }
+ }
+
+ return move(Result);
+}
+
+/// ParseCXXUuidof - This handles the Microsoft C++ __uuidof expression.
+///
+/// '__uuidof' '(' expression ')'
+/// '__uuidof' '(' type-id ')'
+///
+ExprResult Parser::ParseCXXUuidof() {
+ assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!");
+
+ SourceLocation OpLoc = ConsumeToken();
+ SourceLocation LParenLoc = Tok.getLocation();
+ SourceLocation RParenLoc;
+
+ // __uuidof expressions are always parenthesized.
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+ "__uuidof"))
+ return ExprError();
+
+ ExprResult Result;
+
+ if (isTypeIdInParens()) {
+ TypeResult Ty = ParseTypeName();
+
+ // Match the ')'.
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true,
+ Ty.get().getAsOpaquePtr(), RParenLoc);
+ } else {
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ Result = ParseExpression();
+
+ // Match the ')'.
+ if (Result.isInvalid())
+ SkipUntil(tok::r_paren);
+ else {
+ RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false,
+ Result.release(), RParenLoc);
+ }
+ }
+
+ return move(Result);
+}
+
+/// \brief Parse a C++ pseudo-destructor expression after the base,
+/// . or -> operator, and nested-name-specifier have already been
+/// parsed.
+///
+/// postfix-expression: [C++ 5.2]
+/// postfix-expression . pseudo-destructor-name
+/// postfix-expression -> pseudo-destructor-name
+///
+/// pseudo-destructor-name:
+/// ::[opt] nested-name-specifier[opt] type-name :: ~type-name
+/// ::[opt] nested-name-specifier template simple-template-id ::
+/// ~type-name
+/// ::[opt] nested-name-specifier[opt] ~type-name
+///
+ExprResult
+Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ ParsedType ObjectType) {
+ // We're parsing either a pseudo-destructor-name or a dependent
+ // member access that has the same form as a
+ // pseudo-destructor-name. We parse both in the same way and let
+ // the action model sort them out.
+ //
+ // Note that the ::[opt] nested-name-specifier[opt] has already
+ // been parsed, and if there was a simple-template-id, it has
+ // been coalesced into a template-id annotation token.
+ UnqualifiedId FirstTypeName;
+ SourceLocation CCLoc;
+ if (Tok.is(tok::identifier)) {
+ FirstTypeName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else if (Tok.is(tok::annot_template_id)) {
+ FirstTypeName.setTemplateId(
+ (TemplateIdAnnotation *)Tok.getAnnotationValue());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else {
+ FirstTypeName.setIdentifier(0, SourceLocation());
+ }
+
+ // Parse the tilde.
+ assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail");
+ SourceLocation TildeLoc = ConsumeToken();
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_tilde_identifier);
+ return ExprError();
+ }
+
+ // Parse the second type.
+ UnqualifiedId SecondTypeName;
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation NameLoc = ConsumeToken();
+ SecondTypeName.setIdentifier(Name, NameLoc);
+
+ // If there is a '<', the second type name is a template-id. Parse
+ // it as such.
+ if (Tok.is(tok::less) &&
+ ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType,
+ SecondTypeName, /*AssumeTemplateName=*/true,
+ /*TemplateKWLoc*/SourceLocation()))
+ return ExprError();
+
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base,
+ OpLoc, OpKind,
+ SS, FirstTypeName, CCLoc,
+ TildeLoc, SecondTypeName,
+ Tok.is(tok::l_paren));
+}
+
+/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
+///
+/// boolean-literal: [C++ 2.13.5]
+/// 'true'
+/// 'false'
+ExprResult Parser::ParseCXXBoolLiteral() {
+ tok::TokenKind Kind = Tok.getKind();
+ return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
+}
+
+/// ParseThrowExpression - This handles the C++ throw expression.
+///
+/// throw-expression: [C++ 15]
+/// 'throw' assignment-expression[opt]
+ExprResult Parser::ParseThrowExpression() {
+ assert(Tok.is(tok::kw_throw) && "Not throw!");
+ SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
+
+ // If the current token isn't the start of an assignment-expression,
+ // then the expression is not present. This handles things like:
+ // "C ? throw : (void)42", which is crazy but legal.
+ switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
+ case tok::semi:
+ case tok::r_paren:
+ case tok::r_square:
+ case tok::r_brace:
+ case tok::colon:
+ case tok::comma:
+ return Actions.ActOnCXXThrow(ThrowLoc, 0);
+
+ default:
+ ExprResult Expr(ParseAssignmentExpression());
+ if (Expr.isInvalid()) return move(Expr);
+ return Actions.ActOnCXXThrow(ThrowLoc, Expr.take());
+ }
+}
+
+/// ParseCXXThis - This handles the C++ 'this' pointer.
+///
+/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
+/// a non-lvalue expression whose value is the address of the object for which
+/// the function is called.
+ExprResult Parser::ParseCXXThis() {
+ assert(Tok.is(tok::kw_this) && "Not 'this'!");
+ SourceLocation ThisLoc = ConsumeToken();
+ return Actions.ActOnCXXThis(ThisLoc);
+}
+
+/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
+///
+/// postfix-expression: [C++ 5.2p1]
+/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
+/// typename-specifier '(' expression-list[opt] ')' [TODO]
+///
+ExprResult
+Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
+
+ assert(Tok.is(tok::l_paren) && "Expected '('!");
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
+
+ SourceLocation LParenLoc = ConsumeParen();
+
+ ExprVector Exprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (Tok.isNot(tok::r_paren)) {
+ if (ParseExpressionList(Exprs, CommaLocs)) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+ }
+
+ // Match the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ // TypeRep could be null, if it references an invalid typedef.
+ if (!TypeRep)
+ return ExprError();
+
+ assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
+ "Unexpected number of commas!");
+ return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs),
+ RParenLoc);
+}
+
+/// ParseCXXCondition - if/switch/while condition expression.
+///
+/// condition:
+/// expression
+/// type-specifier-seq declarator '=' assignment-expression
+/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+/// '=' assignment-expression
+///
+/// \param ExprResult if the condition was parsed as an expression, the
+/// parsed expression.
+///
+/// \param DeclResult if the condition was parsed as a declaration, the
+/// parsed declaration.
+///
+/// \param Loc The location of the start of the statement that requires this
+/// condition, e.g., the "for" in a for loop.
+///
+/// \param ConvertToBoolean Whether the condition expression should be
+/// converted to a boolean value.
+///
+/// \returns true if there was a parsing, false otherwise.
+bool Parser::ParseCXXCondition(ExprResult &ExprOut,
+ Decl *&DeclOut,
+ SourceLocation Loc,
+ bool ConvertToBoolean) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (!isCXXConditionDeclaration()) {
+ // Parse the expression.
+ ExprOut = ParseExpression(); // expression
+ DeclOut = 0;
+ if (ExprOut.isInvalid())
+ return true;
+
+ // If required, convert to a boolean value.
+ if (ConvertToBoolean)
+ ExprOut
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprOut.get());
+ return ExprOut.isInvalid();
+ }
+
+ // type-specifier-seq
+ DeclSpec DS;
+ ParseSpecifierQualifierList(DS);
+
+ // declarator
+ Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
+ ParseDeclarator(DeclaratorInfo);
+
+ // simple-asm-expr[opt]
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid()) {
+ SkipUntil(tok::semi);
+ return true;
+ }
+ DeclaratorInfo.setAsmLabel(AsmLabel.release());
+ DeclaratorInfo.SetRangeEnd(Loc);
+ }
+
+ // If attributes are present, parse them.
+ MaybeParseGNUAttributes(DeclaratorInfo);
+
+ // Type-check the declaration itself.
+ DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
+ DeclaratorInfo);
+ DeclOut = Dcl.get();
+ ExprOut = ExprError();
+
+ // '=' assignment-expression
+ if (isTokenEqualOrMistypedEqualEqual(
+ diag::err_invalid_equalequal_after_declarator)) {
+ ConsumeToken();
+ ExprResult AssignExpr(ParseAssignmentExpression());
+ if (!AssignExpr.isInvalid())
+ Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false,
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+ } else {
+ // FIXME: C++0x allows a braced-init-list
+ Diag(Tok, diag::err_expected_equal_after_declarator);
+ }
+
+ // FIXME: Build a reference to this declaration? Convert it to bool?
+ // (This is currently handled by Sema).
+
+ return false;
+}
+
+/// \brief Determine whether the current token starts a C++
+/// simple-type-specifier.
+bool Parser::isCXXSimpleTypeSpecifier() const {
+ switch (Tok.getKind()) {
+ case tok::annot_typename:
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_bool:
+ // FIXME: C++0x decltype support.
+ // GNU typeof support.
+ case tok::kw_typeof:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
+/// This should only be called when the current token is known to be part of
+/// simple-type-specifier.
+///
+/// simple-type-specifier:
+/// '::'[opt] nested-name-specifier[opt] type-name
+/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
+/// char
+/// wchar_t
+/// bool
+/// short
+/// int
+/// long
+/// signed
+/// unsigned
+/// float
+/// double
+/// void
+/// [GNU] typeof-specifier
+/// [C++0x] auto [TODO]
+///
+/// type-name:
+/// class-name
+/// enum-name
+/// typedef-name
+///
+void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
+ DS.SetRangeStart(Tok.getLocation());
+ const char *PrevSpec;
+ unsigned DiagID;
+ SourceLocation Loc = Tok.getLocation();
+
+ switch (Tok.getKind()) {
+ case tok::identifier: // foo::bar
+ case tok::coloncolon: // ::foo::bar
+ assert(0 && "Annotation token should already be formed!");
+ default:
+ assert(0 && "Not a simple-type-specifier token!");
+ abort();
+
+ // type-name
+ case tok::annot_typename: {
+ if (getTypeAnnotation(Tok))
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
+ getTypeAnnotation(Tok));
+ else
+ DS.SetTypeSpecError();
+
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken();
+
+ // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
+ // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
+ // Objective-C interface. If we don't have Objective-C or a '<', this is
+ // just a normal reference to a typedef name.
+ if (Tok.is(tok::less) && getLang().ObjC1)
+ ParseObjCProtocolQualifiers(DS);
+
+ DS.Finish(Diags, PP);
+ return;
+ }
+
+ // builtin types
+ case tok::kw_short:
+ DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_long:
+ DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_signed:
+ DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_unsigned:
+ DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_void:
+ DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char:
+ DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_int:
+ DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_float:
+ DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_double:
+ DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_wchar_t:
+ DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char16_t:
+ DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char32_t:
+ DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_bool:
+ DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
+ break;
+
+ // FIXME: C++0x decltype support.
+ // GNU typeof support.
+ case tok::kw_typeof:
+ ParseTypeofSpecifier(DS);
+ DS.Finish(Diags, PP);
+ return;
+ }
+ if (Tok.is(tok::annot_typename))
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ else
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+ DS.Finish(Diags, PP);
+}
+
+/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
+/// [dcl.name]), which is a non-empty sequence of type-specifiers,
+/// e.g., "const short int". Note that the DeclSpec is *not* finished
+/// by parsing the type-specifier-seq, because these sequences are
+/// typically followed by some form of declarator. Returns true and
+/// emits diagnostics if this is not a type-specifier-seq, false
+/// otherwise.
+///
+/// type-specifier-seq: [C++ 8.1]
+/// type-specifier type-specifier-seq[opt]
+///
+bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
+ DS.SetRangeStart(Tok.getLocation());
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ bool isInvalid = 0;
+
+ // Parse one or more of the type specifiers.
+ if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
+ Diag(Tok, diag::err_expected_type);
+ return true;
+ }
+
+ while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ ParsedTemplateInfo(), /*SuppressDeclarations*/true))
+ {}
+
+ DS.Finish(Diags, PP);
+ return false;
+}
+
+/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// some form.
+///
+/// This routine is invoked when a '<' is encountered after an identifier or
+/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
+/// whether the unqualified-id is actually a template-id. This routine will
+/// then parse the template arguments and form the appropriate template-id to
+/// return to the caller.
+///
+/// \param SS the nested-name-specifier that precedes this template-id, if
+/// we're actually parsing a qualified-id.
+///
+/// \param Name for constructor and destructor names, this is the actual
+/// identifier that may be a template-name.
+///
+/// \param NameLoc the location of the class-name in a constructor or
+/// destructor.
+///
+/// \param EnteringContext whether we're entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Id as input, describes the template-name or operator-function-id
+/// that precedes the '<'. If template arguments were parsed successfully,
+/// will be updated with the template-id.
+///
+/// \param AssumeTemplateId When true, this routine will assume that the name
+/// refers to a template without performing name lookup to verify.
+///
+/// \returns true if a parse error occurred, false otherwise.
+bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Id,
+ bool AssumeTemplateId,
+ SourceLocation TemplateKWLoc) {
+ assert((AssumeTemplateId || Tok.is(tok::less)) &&
+ "Expected '<' to finish parsing a template-id");
+
+ TemplateTy Template;
+ TemplateNameKind TNK = TNK_Non_template;
+ switch (Id.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_LiteralOperatorId:
+ if (AssumeTemplateId) {
+ TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS,
+ Id, ObjectType, EnteringContext,
+ Template);
+ if (TNK == TNK_Non_template)
+ return true;
+ } else {
+ bool MemberOfUnknownSpecialization;
+ TNK = Actions.isTemplateName(getCurScope(), SS,
+ TemplateKWLoc.isValid(), Id,
+ ObjectType, EnteringContext, Template,
+ MemberOfUnknownSpecialization);
+
+ if (TNK == TNK_Non_template && MemberOfUnknownSpecialization &&
+ ObjectType && IsTemplateArgumentList()) {
+ // We have something like t->getAs<T>(), where getAs is a
+ // member of an unknown specialization. However, this will only
+ // parse correctly as a template, so suggest the keyword 'template'
+ // before 'getAs' and treat this as a dependent template name.
+ std::string Name;
+ if (Id.getKind() == UnqualifiedId::IK_Identifier)
+ Name = Id.Identifier->getName();
+ else {
+ Name = "operator ";
+ if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId)
+ Name += getOperatorSpelling(Id.OperatorFunctionId.Operator);
+ else
+ Name += Id.Identifier->getName();
+ }
+ Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
+ << Name
+ << FixItHint::CreateInsertion(Id.StartLocation, "template ");
+ TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc,
+ SS, Id, ObjectType,
+ EnteringContext, Template);
+ if (TNK == TNK_Non_template)
+ return true;
+ }
+ }
+ break;
+
+ case UnqualifiedId::IK_ConstructorName: {
+ UnqualifiedId TemplateName;
+ bool MemberOfUnknownSpecialization;
+ TemplateName.setIdentifier(Name, NameLoc);
+ TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
+ TemplateName, ObjectType,
+ EnteringContext, Template,
+ MemberOfUnknownSpecialization);
+ break;
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ UnqualifiedId TemplateName;
+ bool MemberOfUnknownSpecialization;
+ TemplateName.setIdentifier(Name, NameLoc);
+ if (ObjectType) {
+ TNK = Actions.ActOnDependentTemplateName(getCurScope(), TemplateKWLoc, SS,
+ TemplateName, ObjectType,
+ EnteringContext, Template);
+ if (TNK == TNK_Non_template)
+ return true;
+ } else {
+ TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
+ TemplateName, ObjectType,
+ EnteringContext, Template,
+ MemberOfUnknownSpecialization);
+
+ if (TNK == TNK_Non_template && !Id.DestructorName.get()) {
+ Diag(NameLoc, diag::err_destructor_template_id)
+ << Name << SS.getRange();
+ return true;
+ }
+ }
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ if (TNK == TNK_Non_template)
+ return false;
+
+ // Parse the enclosed template argument list.
+ SourceLocation LAngleLoc, RAngleLoc;
+ TemplateArgList TemplateArgs;
+ if (Tok.is(tok::less) &&
+ ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+ &SS, true, LAngleLoc,
+ TemplateArgs,
+ RAngleLoc))
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier ||
+ Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
+ Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
+ // Form a parsed representation of the template-id to be stored in the
+ // UnqualifiedId.
+ TemplateIdAnnotation *TemplateId
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+
+ if (Id.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = Id.Identifier;
+ TemplateId->Operator = OO_None;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = Id.OperatorFunctionId.Operator;
+ TemplateId->TemplateNameLoc = Id.StartLocation;
+ }
+
+ TemplateId->Template = Template;
+ TemplateId->Kind = TNK;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->RAngleLoc = RAngleLoc;
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
+ Arg != ArgEnd; ++Arg)
+ Args[Arg] = TemplateArgs[Arg];
+
+ Id.setTemplateId(TemplateId);
+ return false;
+ }
+
+ // Bundle the template arguments together.
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+ TemplateArgs.size());
+
+ // Constructor and destructor names.
+ TypeResult Type
+ = Actions.ActOnTemplateIdType(Template, NameLoc,
+ LAngleLoc, TemplateArgsPtr,
+ RAngleLoc);
+ if (Type.isInvalid())
+ return true;
+
+ if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
+ else
+ Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+
+ return false;
+}
+
+/// \brief Parse an operator-function-id or conversion-function-id as part
+/// of a C++ unqualified-id.
+///
+/// This routine is responsible only for parsing the operator-function-id or
+/// conversion-function-id; it does not handle template arguments in any way.
+///
+/// \code
+/// operator-function-id: [C++ 13.5]
+/// 'operator' operator
+///
+/// operator: one of
+/// new delete new[] delete[]
+/// + - * / % ^ & | ~
+/// ! = < > += -= *= /= %=
+/// ^= &= |= << >> >>= <<= == !=
+/// <= >= && || ++ -- , ->* ->
+/// () []
+///
+/// conversion-function-id: [C++ 12.3.2]
+/// operator conversion-type-id
+///
+/// conversion-type-id:
+/// type-specifier-seq conversion-declarator[opt]
+///
+/// conversion-declarator:
+/// ptr-operator conversion-declarator[opt]
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Result) {
+ assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
+
+ // Consume the 'operator' keyword.
+ SourceLocation KeywordLoc = ConsumeToken();
+
+ // Determine what kind of operator name we have.
+ unsigned SymbolIdx = 0;
+ SourceLocation SymbolLocations[3];
+ OverloadedOperatorKind Op = OO_None;
+ switch (Tok.getKind()) {
+ case tok::kw_new:
+ case tok::kw_delete: {
+ bool isNew = Tok.getKind() == tok::kw_new;
+ // Consume the 'new' or 'delete'.
+ SymbolLocations[SymbolIdx++] = ConsumeToken();
+ if (Tok.is(tok::l_square)) {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = isNew? OO_Array_New : OO_Array_Delete;
+ } else {
+ Op = isNew? OO_New : OO_Delete;
+ }
+ break;
+ }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case tok::Token: \
+ SymbolLocations[SymbolIdx++] = ConsumeToken(); \
+ Op = OO_##Name; \
+ break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+
+ case tok::l_paren: {
+ // Consume the '('.
+ SourceLocation LParenLoc = ConsumeParen();
+ // Consume the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
+ LParenLoc);
+ if (RParenLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LParenLoc;
+ SymbolLocations[SymbolIdx++] = RParenLoc;
+ Op = OO_Call;
+ break;
+ }
+
+ case tok::l_square: {
+ // Consume the '['.
+ SourceLocation LBracketLoc = ConsumeBracket();
+ // Consume the ']'.
+ SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+ LBracketLoc);
+ if (RBracketLoc.isInvalid())
+ return true;
+
+ SymbolLocations[SymbolIdx++] = LBracketLoc;
+ SymbolLocations[SymbolIdx++] = RBracketLoc;
+ Op = OO_Subscript;
+ break;
+ }
+
+ case tok::code_completion: {
+ // Code completion for the operator name.
+ Actions.CodeCompleteOperatorName(getCurScope());
+
+ // Consume the operator token.
+ ConsumeCodeCompletionToken();
+
+ // Don't try to parse any further.
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ if (Op != OO_None) {
+ // We have parsed an operator-function-id.
+ Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
+ return false;
+ }
+
+ // Parse a literal-operator-id.
+ //
+ // literal-operator-id: [C++0x 13.5.8]
+ // operator "" identifier
+
+ if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) {
+ if (Tok.getLength() != 2)
+ Diag(Tok.getLocation(), diag::err_operator_string_not_empty);
+ ConsumeStringToken();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ return true;
+ }
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken());
+ return false;
+ }
+
+ // Parse a conversion-function-id.
+ //
+ // conversion-function-id: [C++ 12.3.2]
+ // operator conversion-type-id
+ //
+ // conversion-type-id:
+ // type-specifier-seq conversion-declarator[opt]
+ //
+ // conversion-declarator:
+ // ptr-operator conversion-declarator[opt]
+
+ // Parse the type-specifier-seq.
+ DeclSpec DS;
+ if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
+ return true;
+
+ // Parse the conversion-declarator, which is merely a sequence of
+ // ptr-operators.
+ Declarator D(DS, Declarator::TypeNameContext);
+ ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
+
+ // Finish up the type.
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
+ if (Ty.isInvalid())
+ return true;
+
+ // Note that this is a conversion-function-id.
+ Result.setConversionFunctionId(KeywordLoc, Ty.get(),
+ D.getSourceRange().getEnd());
+ return false;
+}
+
+/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// name of an entity.
+///
+/// \code
+/// unqualified-id: [C++ expr.prim.general]
+/// identifier
+/// operator-function-id
+/// conversion-function-id
+/// [C++0x] literal-operator-id [TODO]
+/// ~ class-name
+/// template-id
+///
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the
+/// nested-name-specifier.
+///
+/// \param AllowDestructorName whether we allow parsing of a destructor name.
+///
+/// \param AllowConstructorName whether we allow parsing a constructor name.
+///
+/// \param ObjectType if this unqualified-id occurs within a member access
+/// expression, the type of the base object whose member is being accessed.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ ParsedType ObjectType,
+ UnqualifiedId &Result) {
+
+ // Handle 'A::template B'. This is for template-ids which have not
+ // already been annotated by ParseOptionalCXXScopeSpecifier().
+ bool TemplateSpecified = false;
+ SourceLocation TemplateKWLoc;
+ if (getLang().CPlusPlus && Tok.is(tok::kw_template) &&
+ (ObjectType || SS.isSet())) {
+ TemplateSpecified = true;
+ TemplateKWLoc = ConsumeToken();
+ }
+
+ // unqualified-id:
+ // identifier
+ // template-id (when it hasn't already been annotated)
+ if (Tok.is(tok::identifier)) {
+ // Consume the identifier.
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (!getLang().CPlusPlus) {
+ // If we're not in C++, only identifiers matter. Record the
+ // identifier and return.
+ Result.setIdentifier(Id, IdLoc);
+ return false;
+ }
+
+ if (AllowConstructorName &&
+ Actions.isCurrentClassName(*Id, getCurScope(), &SS)) {
+ // We have parsed a constructor name.
+ Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, getCurScope(),
+ &SS, false),
+ IdLoc, IdLoc);
+ } else {
+ // We have parsed an identifier.
+ Result.setIdentifier(Id, IdLoc);
+ }
+
+ // If the next token is a '<', we may have a template.
+ if (TemplateSpecified || Tok.is(tok::less))
+ return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
+ ObjectType, Result,
+ TemplateSpecified, TemplateKWLoc);
+
+ return false;
+ }
+
+ // unqualified-id:
+ // template-id (already parsed and annotated)
+ if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue());
+
+ // If the template-name names the current class, then this is a constructor
+ if (AllowConstructorName && TemplateId->Name &&
+ Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) {
+ if (SS.isSet()) {
+ // C++ [class.qual]p2 specifies that a qualified template-name
+ // is taken as the constructor name where a constructor can be
+ // declared. Thus, the template arguments are extraneous, so
+ // complain about them and remove them entirely.
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_out_of_line_constructor_template_id)
+ << TemplateId->Name
+ << FixItHint::CreateRemoval(
+ SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
+ Result.setConstructorName(Actions.getTypeName(*TemplateId->Name,
+ TemplateId->TemplateNameLoc,
+ getCurScope(),
+ &SS, false),
+ TemplateId->TemplateNameLoc,
+ TemplateId->RAngleLoc);
+ TemplateId->Destroy();
+ ConsumeToken();
+ return false;
+ }
+
+ Result.setConstructorTemplateId(TemplateId);
+ ConsumeToken();
+ return false;
+ }
+
+ // We have already parsed a template-id; consume the annotation token as
+ // our unqualified-id.
+ Result.setTemplateId(TemplateId);
+ ConsumeToken();
+ return false;
+ }
+
+ // unqualified-id:
+ // operator-function-id
+ // conversion-function-id
+ if (Tok.is(tok::kw_operator)) {
+ if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
+ return true;
+
+ // If we have an operator-function-id or a literal-operator-id and the next
+ // token is a '<', we may have a
+ //
+ // template-id:
+ // operator-function-id < template-argument-list[opt] >
+ if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
+ Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
+ (TemplateSpecified || Tok.is(tok::less)))
+ return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
+ EnteringContext, ObjectType,
+ Result,
+ TemplateSpecified, TemplateKWLoc);
+
+ return false;
+ }
+
+ if (getLang().CPlusPlus &&
+ (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+ // C++ [expr.unary.op]p10:
+ // There is an ambiguity in the unary-expression ~X(), where X is a
+ // class-name. The ambiguity is resolved in favor of treating ~ as a
+ // unary complement rather than treating ~X as referring to a destructor.
+
+ // Parse the '~'.
+ SourceLocation TildeLoc = ConsumeToken();
+
+ // Parse the class-name.
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_tilde_identifier);
+ return true;
+ }
+
+ // Parse the class-name (or template-name in a simple-template-id).
+ IdentifierInfo *ClassName = Tok.getIdentifierInfo();
+ SourceLocation ClassNameLoc = ConsumeToken();
+
+ if (TemplateSpecified || Tok.is(tok::less)) {
+ Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc);
+ return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
+ EnteringContext, ObjectType, Result,
+ TemplateSpecified, TemplateKWLoc);
+ }
+
+ // Note that this is a destructor name.
+ ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
+ ClassNameLoc, getCurScope(),
+ SS, ObjectType,
+ EnteringContext);
+ if (!Ty)
+ return true;
+
+ Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
+ return false;
+ }
+
+ Diag(Tok, diag::err_expected_unqualified_id)
+ << getLang().CPlusPlus;
+ return true;
+}
+
+/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
+/// memory in a typesafe manner and call constructors.
+///
+/// This method is called to parse the new expression after the optional :: has
+/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
+/// is its location. Otherwise, "Start" is the location of the 'new' token.
+///
+/// new-expression:
+/// '::'[opt] 'new' new-placement[opt] new-type-id
+/// new-initializer[opt]
+/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+/// new-initializer[opt]
+///
+/// new-placement:
+/// '(' expression-list ')'
+///
+/// new-type-id:
+/// type-specifier-seq new-declarator[opt]
+///
+/// new-declarator:
+/// ptr-operator new-declarator[opt]
+/// direct-new-declarator
+///
+/// new-initializer:
+/// '(' expression-list[opt] ')'
+/// [C++0x] braced-init-list [TODO]
+///
+ExprResult
+Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
+ assert(Tok.is(tok::kw_new) && "expected 'new' token");
+ ConsumeToken(); // Consume 'new'
+
+ // A '(' now can be a new-placement or the '(' wrapping the type-id in the
+ // second form of new-expression. It can't be a new-type-id.
+
+ ExprVector PlacementArgs(Actions);
+ SourceLocation PlacementLParen, PlacementRParen;
+
+ SourceRange TypeIdParens;
+ DeclSpec DS;
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ if (Tok.is(tok::l_paren)) {
+ // If it turns out to be a placement, we change the type location.
+ PlacementLParen = ConsumeParen();
+ if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return ExprError();
+ }
+
+ PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
+ if (PlacementRParen.isInvalid()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return ExprError();
+ }
+
+ if (PlacementArgs.empty()) {
+ // Reset the placement locations. There was no placement.
+ TypeIdParens = SourceRange(PlacementLParen, PlacementRParen);
+ PlacementLParen = PlacementRParen = SourceLocation();
+ } else {
+ // We still need the type.
+ if (Tok.is(tok::l_paren)) {
+ TypeIdParens.setBegin(ConsumeParen());
+ ParseSpecifierQualifierList(DS);
+ DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+ ParseDeclarator(DeclaratorInfo);
+ TypeIdParens.setEnd(MatchRHSPunctuation(tok::r_paren,
+ TypeIdParens.getBegin()));
+ } else {
+ if (ParseCXXTypeSpecifierSeq(DS))
+ DeclaratorInfo.setInvalidType(true);
+ else {
+ DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+ ParseDeclaratorInternal(DeclaratorInfo,
+ &Parser::ParseDirectNewDeclarator);
+ }
+ }
+ }
+ } else {
+ // A new-type-id is a simplified type-id, where essentially the
+ // direct-declarator is replaced by a direct-new-declarator.
+ if (ParseCXXTypeSpecifierSeq(DS))
+ DeclaratorInfo.setInvalidType(true);
+ else {
+ DeclaratorInfo.SetSourceRange(DS.getSourceRange());
+ ParseDeclaratorInternal(DeclaratorInfo,
+ &Parser::ParseDirectNewDeclarator);
+ }
+ }
+ if (DeclaratorInfo.isInvalidType()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return ExprError();
+ }
+
+ ExprVector ConstructorArgs(Actions);
+ SourceLocation ConstructorLParen, ConstructorRParen;
+
+ if (Tok.is(tok::l_paren)) {
+ ConstructorLParen = ConsumeParen();
+ if (Tok.isNot(tok::r_paren)) {
+ CommaLocsTy CommaLocs;
+ if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return ExprError();
+ }
+ }
+ ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
+ if (ConstructorRParen.isInvalid()) {
+ SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ return ExprError();
+ }
+ }
+
+ return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
+ move_arg(PlacementArgs), PlacementRParen,
+ TypeIdParens, DeclaratorInfo, ConstructorLParen,
+ move_arg(ConstructorArgs), ConstructorRParen);
+}
+
+/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
+/// passed to ParseDeclaratorInternal.
+///
+/// direct-new-declarator:
+/// '[' expression ']'
+/// direct-new-declarator '[' constant-expression ']'
+///
+void Parser::ParseDirectNewDeclarator(Declarator &D) {
+ // Parse the array dimensions.
+ bool first = true;
+ while (Tok.is(tok::l_square)) {
+ SourceLocation LLoc = ConsumeBracket();
+ ExprResult Size(first ? ParseExpression()
+ : ParseConstantExpression());
+ if (Size.isInvalid()) {
+ // Recover
+ SkipUntil(tok::r_square);
+ return;
+ }
+ first = false;
+
+ SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, ParsedAttributes(),
+ /*static=*/false, /*star=*/false,
+ Size.release(), LLoc, RLoc),
+ RLoc);
+
+ if (RLoc.isInvalid())
+ return;
+ }
+}
+
+/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
+/// This ambiguity appears in the syntax of the C++ new operator.
+///
+/// new-expression:
+/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+/// new-initializer[opt]
+///
+/// new-placement:
+/// '(' expression-list ')'
+///
+bool Parser::ParseExpressionListOrTypeId(
+ llvm::SmallVectorImpl<Expr*> &PlacementArgs,
+ Declarator &D) {
+ // The '(' was already consumed.
+ if (isTypeIdInParens()) {
+ ParseSpecifierQualifierList(D.getMutableDeclSpec());
+ D.SetSourceRange(D.getDeclSpec().getSourceRange());
+ ParseDeclarator(D);
+ return D.isInvalidType();
+ }
+
+ // It's not a type, it has to be an expression list.
+ // Discard the comma locations - ActOnCXXNew has enough parameters.
+ CommaLocsTy CommaLocs;
+ return ParseExpressionList(PlacementArgs, CommaLocs);
+}
+
+/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
+/// to free memory allocated by new.
+///
+/// This method is called to parse the 'delete' expression after the optional
+/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
+/// and "Start" is its location. Otherwise, "Start" is the location of the
+/// 'delete' token.
+///
+/// delete-expression:
+/// '::'[opt] 'delete' cast-expression
+/// '::'[opt] 'delete' '[' ']' cast-expression
+ExprResult
+Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
+ assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
+ ConsumeToken(); // Consume 'delete'
+
+ // Array delete?
+ bool ArrayDelete = false;
+ if (Tok.is(tok::l_square)) {
+ ArrayDelete = true;
+ SourceLocation LHS = ConsumeBracket();
+ SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
+ if (RHS.isInvalid())
+ return ExprError();
+ }
+
+ ExprResult Operand(ParseCastExpression(false));
+ if (Operand.isInvalid())
+ return move(Operand);
+
+ return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take());
+}
+
+static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
+ switch(kind) {
+ default: llvm_unreachable("Not a known unary type trait");
+ case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
+ case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
+ case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
+ case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
+ case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
+ case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+ case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
+ case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
+ case tok::kw___is_abstract: return UTT_IsAbstract;
+ case tok::kw___is_class: return UTT_IsClass;
+ case tok::kw___is_empty: return UTT_IsEmpty;
+ case tok::kw___is_enum: return UTT_IsEnum;
+ case tok::kw___is_pod: return UTT_IsPOD;
+ case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
+ case tok::kw___is_union: return UTT_IsUnion;
+ case tok::kw___is_literal: return UTT_IsLiteral;
+ }
+}
+
+static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
+ switch(kind) {
+ default: llvm_unreachable("Not a known binary type trait");
+ case tok::kw___is_base_of: return BTT_IsBaseOf;
+ case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible;
+ case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
+ }
+}
+
+/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+/// primary-expression:
+/// [GNU] unary-type-trait '(' type-id ')'
+///
+ExprResult Parser::ParseUnaryTypeTrait() {
+ UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
+ // there will be cryptic errors about mismatched parentheses and missing
+ // specifiers.
+ TypeResult Ty = ParseTypeName();
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
+}
+
+/// ParseBinaryTypeTrait - Parse the built-in binary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+/// primary-expression:
+/// [GNU] binary-type-trait '(' type-id ',' type-id ')'
+///
+ExprResult Parser::ParseBinaryTypeTrait() {
+ BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ TypeResult LhsTy = ParseTypeName();
+ if (LhsTy.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ TypeResult RhsTy = ParseTypeName();
+ if (RhsTy.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen);
+}
+
+/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
+/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
+/// based on the context past the parens.
+ExprResult
+Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+ ParsedType &CastTy,
+ SourceLocation LParenLoc,
+ SourceLocation &RParenLoc) {
+ assert(getLang().CPlusPlus && "Should only be called for C++!");
+ assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
+ assert(isTypeIdInParens() && "Not a type-id!");
+
+ ExprResult Result(true);
+ CastTy = ParsedType();
+
+ // We need to disambiguate a very ugly part of the C++ syntax:
+ //
+ // (T())x; - type-id
+ // (T())*x; - type-id
+ // (T())/x; - expression
+ // (T()); - expression
+ //
+ // The bad news is that we cannot use the specialized tentative parser, since
+ // it can only verify that the thing inside the parens can be parsed as
+ // type-id, it is not useful for determining the context past the parens.
+ //
+ // The good news is that the parser can disambiguate this part without
+ // making any unnecessary Action calls.
+ //
+ // It uses a scheme similar to parsing inline methods. The parenthesized
+ // tokens are cached, the context that follows is determined (possibly by
+ // parsing a cast-expression), and then we re-introduce the cached tokens
+ // into the token stream and parse them appropriately.
+
+ ParenParseOption ParseAs;
+ CachedTokens Toks;
+
+ // Store the tokens of the parentheses. We will parse them after we determine
+ // the context that follows them.
+ if (!ConsumeAndStoreUntil(tok::r_paren, Toks)) {
+ // We didn't find the ')' we expected.
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return ExprError();
+ }
+
+ if (Tok.is(tok::l_brace)) {
+ ParseAs = CompoundLiteral;
+ } else {
+ bool NotCastExpr;
+ // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
+ if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
+ NotCastExpr = true;
+ } else {
+ // Try parsing the cast-expression that may follow.
+ // If it is not a cast-expression, NotCastExpr will be true and no token
+ // will be consumed.
+ Result = ParseCastExpression(false/*isUnaryExpression*/,
+ false/*isAddressofOperand*/,
+ NotCastExpr,
+ ParsedType()/*TypeOfCast*/);
+ }
+
+ // If we parsed a cast-expression, it's really a type-id, otherwise it's
+ // an expression.
+ ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
+ }
+
+ // The current token should go after the cached tokens.
+ Toks.push_back(Tok);
+ // Re-enter the stored parenthesized tokens into the token stream, so we may
+ // parse them now.
+ PP.EnterTokenStream(Toks.data(), Toks.size(),
+ true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
+ // Drop the current token and bring the first cached one. It's the same token
+ // as when we entered this function.
+ ConsumeAnyToken();
+
+ if (ParseAs >= CompoundLiteral) {
+ TypeResult Ty = ParseTypeName();
+
+ // Match the ')'.
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (ParseAs == CompoundLiteral) {
+ ExprType = CompoundLiteral;
+ return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
+ }
+
+ // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
+ assert(ParseAs == CastExpr);
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ CastTy = Ty.get();
+
+ // Result is what ParseCastExpression returned earlier.
+ if (!Result.isInvalid())
+ Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc, CastTy, RParenLoc,
+ Result.take());
+ return move(Result);
+ }
+
+ // Not a compound literal, and not followed by a cast-expression.
+ assert(ParseAs == SimpleExpr);
+
+ ExprType = SimpleExpr;
+ Result = ParseExpression();
+ if (!Result.isInvalid() && Tok.is(tok::r_paren))
+ Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), Result.take());
+
+ // Match the ')'.
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return ExprError();
+ }
+
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ return move(Result);
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
new file mode 100644
index 0000000..82dda2b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp
@@ -0,0 +1,387 @@
+//===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements initializer parsing as specified by C99 6.7.8.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+
+/// MayBeDesignationStart - Return true if this token might be the start of a
+/// designator. If we can tell it is impossible that it is a designator, return
+/// false.
+static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
+ switch (K) {
+ default: return false;
+ case tok::period: // designator: '.' identifier
+ case tok::l_square: // designator: array-designator
+ return true;
+ case tok::identifier: // designation: identifier ':'
+ return PP.LookAhead(0).is(tok::colon);
+ }
+}
+
+static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
+ Designation &Desig) {
+ // If we have exactly one array designator, this used the GNU
+ // 'designation: array-designator' extension, otherwise there should be no
+ // designators at all!
+ if (Desig.getNumDesignators() == 1 &&
+ (Desig.getDesignator(0).isArrayDesignator() ||
+ Desig.getDesignator(0).isArrayRangeDesignator()))
+ P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
+ else if (Desig.getNumDesignators() > 0)
+ P.Diag(Loc, diag::err_expected_equal_designator);
+}
+
+/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
+/// checking to see if the token stream starts with a designator.
+///
+/// designation:
+/// designator-list '='
+/// [GNU] array-designator
+/// [GNU] identifier ':'
+///
+/// designator-list:
+/// designator
+/// designator-list designator
+///
+/// designator:
+/// array-designator
+/// '.' identifier
+///
+/// array-designator:
+/// '[' constant-expression ']'
+/// [GNU] '[' constant-expression '...' constant-expression ']'
+///
+/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
+/// initializer (because it is an expression). We need to consider this case
+/// when parsing array designators.
+///
+ExprResult Parser::ParseInitializerWithPotentialDesignator() {
+
+ // If this is the old-style GNU extension:
+ // designation ::= identifier ':'
+ // Handle it as a field designator. Otherwise, this must be the start of a
+ // normal expression.
+ if (Tok.is(tok::identifier)) {
+ const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
+
+ llvm::SmallString<256> NewSyntax;
+ llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
+ << " = ";
+
+ SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
+
+ assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
+ SourceLocation ColonLoc = ConsumeToken();
+
+ Diag(Tok, diag::ext_gnu_old_style_field_designator)
+ << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
+ NewSyntax.str());
+
+ Designation D;
+ D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
+ return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
+ ParseInitializer());
+ }
+
+ // Desig - This is initialized when we see our first designator. We may have
+ // an objc message send with no designator, so we don't want to create this
+ // eagerly.
+ Designation Desig;
+
+ // Parse each designator in the designator list until we find an initializer.
+ while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
+ if (Tok.is(tok::period)) {
+ // designator: '.' identifier
+ SourceLocation DotLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_expected_field_designator);
+ return ExprError();
+ }
+
+ Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc,
+ Tok.getLocation()));
+ ConsumeToken(); // Eat the identifier.
+ continue;
+ }
+
+ // We must have either an array designator now or an objc message send.
+ assert(Tok.is(tok::l_square) && "Unexpected token!");
+
+ // Handle the two forms of array designator:
+ // array-designator: '[' constant-expression ']'
+ // array-designator: '[' constant-expression '...' constant-expression ']'
+ //
+ // Also, we have to handle the case where the expression after the
+ // designator an an objc message send: '[' objc-message-expr ']'.
+ // Interesting cases are:
+ // [foo bar] -> objc message send
+ // [foo] -> array designator
+ // [foo ... bar] -> array designator
+ // [4][foo bar] -> obsolete GNU designation with objc message send.
+ //
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
+ SourceLocation StartLoc = ConsumeBracket();
+ ExprResult Idx;
+
+ // If Objective-C is enabled and this is a typename (class message
+ // send) or send to 'super', parse this as a message send
+ // expression. We handle C++ and C separately, since C++ requires
+ // much more complicated parsing.
+ if (getLang().ObjC1 && getLang().CPlusPlus) {
+ // Send to 'super'.
+ if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
+ NextToken().isNot(tok::period) &&
+ getCurScope()->isInObjcMethodScope()) {
+ CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ ConsumeToken(),
+ ParsedType(),
+ 0);
+ }
+
+ // Parse the receiver, which is either a type or an expression.
+ bool IsExpr;
+ void *TypeOrExpr;
+ if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ // If the receiver was a type, we have a class message; parse
+ // the rest of it.
+ if (!IsExpr) {
+ CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ SourceLocation(),
+ ParsedType::getFromOpaquePtr(TypeOrExpr),
+ 0);
+ }
+
+ // If the receiver was an expression, we still don't know
+ // whether we have a message send or an array designator; just
+ // adopt the expression for further analysis below.
+ // FIXME: potentially-potentially evaluated expression above?
+ Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));
+ } else if (getLang().ObjC1 && Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ SourceLocation IILoc = Tok.getLocation();
+ ParsedType ReceiverType;
+ // Three cases. This is a message send to a type: [type foo]
+ // This is a message send to super: [super foo]
+ // This is a message sent to an expr: [super.bar foo]
+ switch (Sema::ObjCMessageKind Kind
+ = Actions.getObjCMessageKind(getCurScope(), II, IILoc,
+ II == Ident_super,
+ NextToken().is(tok::period),
+ ReceiverType)) {
+ case Sema::ObjCSuperMessage:
+ case Sema::ObjCClassMessage:
+ CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
+ if (Kind == Sema::ObjCSuperMessage)
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ ConsumeToken(),
+ ParsedType(),
+ 0);
+ ConsumeToken(); // the identifier
+ if (!ReceiverType) {
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ SourceLocation(),
+ ReceiverType,
+ 0);
+
+ case Sema::ObjCInstanceMessage:
+ // Fall through; we'll just parse the expression and
+ // (possibly) treat this like an Objective-C message send
+ // later.
+ break;
+ }
+ }
+
+ // Parse the index expression, if we haven't already gotten one
+ // above (which can only happen in Objective-C++).
+ // Note that we parse this as an assignment expression, not a constant
+ // expression (allowing *=, =, etc) to handle the objc case. Sema needs
+ // to validate that the expression is a constant.
+ // FIXME: We also need to tell Sema that we're in a
+ // potentially-potentially evaluated context.
+ if (!Idx.get()) {
+ Idx = ParseAssignmentExpression();
+ if (Idx.isInvalid()) {
+ SkipUntil(tok::r_square);
+ return move(Idx);
+ }
+ }
+
+ // Given an expression, we could either have a designator (if the next
+ // tokens are '...' or ']' or an objc message send. If this is an objc
+ // message send, handle it now. An objc-message send is the start of
+ // an assignment-expression production.
+ if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
+ Tok.isNot(tok::r_square)) {
+ CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
+ return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
+ SourceLocation(),
+ ParsedType(),
+ Idx.take());
+ }
+
+ // If this is a normal array designator, remember it.
+ if (Tok.isNot(tok::ellipsis)) {
+ Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc));
+ } else {
+ // Handle the gnu array range extension.
+ Diag(Tok, diag::ext_gnu_array_range);
+ SourceLocation EllipsisLoc = ConsumeToken();
+
+ ExprResult RHS(ParseConstantExpression());
+ if (RHS.isInvalid()) {
+ SkipUntil(tok::r_square);
+ return move(RHS);
+ }
+ Desig.AddDesignator(Designator::getArrayRange(Idx.release(),
+ RHS.release(),
+ StartLoc, EllipsisLoc));
+ }
+
+ SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+ Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc);
+ }
+
+ // Okay, we're done with the designator sequence. We know that there must be
+ // at least one designator, because the only case we can get into this method
+ // without a designator is when we have an objc message send. That case is
+ // handled and returned from above.
+ assert(!Desig.empty() && "Designator is empty?");
+
+ // Handle a normal designator sequence end, which is an equal.
+ if (Tok.is(tok::equal)) {
+ SourceLocation EqualLoc = ConsumeToken();
+ return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
+ ParseInitializer());
+ }
+
+ // We read some number of designators and found something that isn't an = or
+ // an initializer. If we have exactly one array designator, this
+ // is the GNU 'designation: array-designator' extension. Otherwise, it is a
+ // parse error.
+ if (Desig.getNumDesignators() == 1 &&
+ (Desig.getDesignator(0).isArrayDesignator() ||
+ Desig.getDesignator(0).isArrayRangeDesignator())) {
+ Diag(Tok, diag::ext_gnu_missing_equal_designator)
+ << FixItHint::CreateInsertion(Tok.getLocation(), "= ");
+ return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),
+ true, ParseInitializer());
+ }
+
+ Diag(Tok, diag::err_expected_equal_designator);
+ return ExprError();
+}
+
+
+/// ParseBraceInitializer - Called when parsing an initializer that has a
+/// leading open brace.
+///
+/// initializer: [C99 6.7.8]
+/// '{' initializer-list '}'
+/// '{' initializer-list ',' '}'
+/// [GNU] '{' '}'
+///
+/// initializer-list:
+/// designation[opt] initializer ...[opt]
+/// initializer-list ',' designation[opt] initializer ...[opt]
+///
+ExprResult Parser::ParseBraceInitializer() {
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
+ SourceLocation LBraceLoc = ConsumeBrace();
+
+ /// InitExprs - This is the actual list of expressions contained in the
+ /// initializer.
+ ExprVector InitExprs(Actions);
+
+ if (Tok.is(tok::r_brace)) {
+ // Empty initializers are a C++ feature and a GNU extension to C.
+ if (!getLang().CPlusPlus)
+ Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
+ // Match the '}'.
+ return Actions.ActOnInitList(LBraceLoc, MultiExprArg(Actions),
+ ConsumeBrace());
+ }
+
+ bool InitExprsOk = true;
+
+ while (1) {
+ // Parse: designation[opt] initializer
+
+ // If we know that this cannot be a designation, just parse the nested
+ // initializer directly.
+ ExprResult SubElt;
+ if (MayBeDesignationStart(Tok.getKind(), PP))
+ SubElt = ParseInitializerWithPotentialDesignator();
+ else
+ SubElt = ParseInitializer();
+
+ if (Tok.is(tok::ellipsis))
+ SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
+
+ // If we couldn't parse the subelement, bail out.
+ if (!SubElt.isInvalid()) {
+ InitExprs.push_back(SubElt.release());
+ } else {
+ InitExprsOk = false;
+
+ // We have two ways to try to recover from this error: if the code looks
+ // gramatically ok (i.e. we have a comma coming up) try to continue
+ // parsing the rest of the initializer. This allows us to emit
+ // diagnostics for later elements that we find. If we don't see a comma,
+ // assume there is a parse error, and just skip to recover.
+ // FIXME: This comment doesn't sound right. If there is a r_brace
+ // immediately, it can't be an error, since there is no other way of
+ // leaving this loop except through this if.
+ if (Tok.isNot(tok::comma)) {
+ SkipUntil(tok::r_brace, false, true);
+ break;
+ }
+ }
+
+ // If we don't have a comma continued list, we're done.
+ if (Tok.isNot(tok::comma)) break;
+
+ // TODO: save comma locations if some client cares.
+ ConsumeToken();
+
+ // Handle trailing comma.
+ if (Tok.is(tok::r_brace)) break;
+ }
+ if (InitExprsOk && Tok.is(tok::r_brace))
+ return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs),
+ ConsumeBrace());
+
+ // Match the '}'.
+ MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ return ExprError(); // an error occurred.
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
new file mode 100644
index 0000000..f32a322
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -0,0 +1,2364 @@
+//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Objective-C portions of the Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+
+/// ParseObjCAtDirectives - Handle parts of the external-declaration production:
+/// external-declaration: [C99 6.9]
+/// [OBJC] objc-class-definition
+/// [OBJC] objc-class-declaration
+/// [OBJC] objc-alias-declaration
+/// [OBJC] objc-protocol-definition
+/// [OBJC] objc-method-definition
+/// [OBJC] '@' 'end'
+Decl *Parser::ParseObjCAtDirectives() {
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, false);
+ ConsumeCodeCompletionToken();
+ }
+
+ switch (Tok.getObjCKeywordID()) {
+ case tok::objc_class:
+ return ParseObjCAtClassDeclaration(AtLoc);
+ case tok::objc_interface: {
+ ParsedAttributes attrs;
+ return ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
+ }
+ case tok::objc_protocol: {
+ ParsedAttributes attrs;
+ return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
+ }
+ case tok::objc_implementation:
+ return ParseObjCAtImplementationDeclaration(AtLoc);
+ case tok::objc_end:
+ return ParseObjCAtEndDeclaration(AtLoc);
+ case tok::objc_compatibility_alias:
+ return ParseObjCAtAliasDeclaration(AtLoc);
+ case tok::objc_synthesize:
+ return ParseObjCPropertySynthesize(AtLoc);
+ case tok::objc_dynamic:
+ return ParseObjCPropertyDynamic(AtLoc);
+ default:
+ Diag(AtLoc, diag::err_unexpected_at);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+}
+
+///
+/// objc-class-declaration:
+/// '@' 'class' identifier-list ';'
+///
+Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+ ConsumeToken(); // the identifier "class"
+ llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+ llvm::SmallVector<SourceLocation, 8> ClassLocs;
+
+
+ while (1) {
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+ ClassNames.push_back(Tok.getIdentifierInfo());
+ ClassLocs.push_back(Tok.getLocation());
+ ConsumeToken();
+
+ if (Tok.isNot(tok::comma))
+ break;
+
+ ConsumeToken();
+ }
+
+ // Consume the ';'.
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+ return 0;
+
+ return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
+ ClassLocs.data(),
+ ClassNames.size());
+}
+
+///
+/// objc-interface:
+/// objc-class-interface-attributes[opt] objc-class-interface
+/// objc-category-interface
+///
+/// objc-class-interface:
+/// '@' 'interface' identifier objc-superclass[opt]
+/// objc-protocol-refs[opt]
+/// objc-class-instance-variables[opt]
+/// objc-interface-decl-list
+/// @end
+///
+/// objc-category-interface:
+/// '@' 'interface' identifier '(' identifier[opt] ')'
+/// objc-protocol-refs[opt]
+/// objc-interface-decl-list
+/// @end
+///
+/// objc-superclass:
+/// ':' identifier
+///
+/// objc-class-interface-attributes:
+/// __attribute__((visibility("default")))
+/// __attribute__((visibility("hidden")))
+/// __attribute__((deprecated))
+/// __attribute__((unavailable))
+/// __attribute__((objc_exception)) - used by NSException on 64-bit
+///
+Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ ParsedAttributes &attrs) {
+ assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
+ "ParseObjCAtInterfaceDeclaration(): Expected @interface");
+ ConsumeToken(); // the "interface" identifier
+
+ // Code completion after '@interface'.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ return 0;
+ }
+
+ // We have a class or category name - consume it.
+ IdentifierInfo *nameId = Tok.getIdentifierInfo();
+ SourceLocation nameLoc = ConsumeToken();
+ if (Tok.is(tok::l_paren) &&
+ !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
+ // TODO(dgregor): Use the return value from the next line to provide better
+ // recovery.
+ ConsumeParen();
+ SourceLocation categoryLoc, rparenLoc;
+ IdentifierInfo *categoryId = 0;
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
+ ConsumeCodeCompletionToken();
+ }
+
+ // For ObjC2, the category name is optional (not an error).
+ if (Tok.is(tok::identifier)) {
+ categoryId = Tok.getIdentifierInfo();
+ categoryLoc = ConsumeToken();
+ }
+ else if (!getLang().ObjC2) {
+ Diag(Tok, diag::err_expected_ident); // missing category name.
+ return 0;
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected_rparen);
+ SkipUntil(tok::r_paren, false); // don't stop at ';'
+ return 0;
+ }
+ rparenLoc = ConsumeParen();
+ // Next, we need to check for any protocol references.
+ SourceLocation LAngleLoc, EndProtoLoc;
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ if (Tok.is(tok::less) &&
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ LAngleLoc, EndProtoLoc))
+ return 0;
+
+ if (!attrs.empty()) // categories don't support attributes.
+ Diag(Tok, diag::err_objc_no_attributes_on_category);
+
+ Decl *CategoryType =
+ Actions.ActOnStartCategoryInterface(atLoc,
+ nameId, nameLoc,
+ categoryId, categoryLoc,
+ ProtocolRefs.data(),
+ ProtocolRefs.size(),
+ ProtocolLocs.data(),
+ EndProtoLoc);
+ if (Tok.is(tok::l_brace))
+ ParseObjCClassInstanceVariables(CategoryType, tok::objc_private,
+ atLoc);
+
+ ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
+ return CategoryType;
+ }
+ // Parse a class interface.
+ IdentifierInfo *superClassId = 0;
+ SourceLocation superClassLoc;
+
+ if (Tok.is(tok::colon)) { // a super class is specified.
+ ConsumeToken();
+
+ // Code completion of superclass names.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing super class name.
+ return 0;
+ }
+ superClassId = Tok.getIdentifierInfo();
+ superClassLoc = ConsumeToken();
+ }
+ // Next, we need to check for any protocol references.
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ SourceLocation LAngleLoc, EndProtoLoc;
+ if (Tok.is(tok::less) &&
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ LAngleLoc, EndProtoLoc))
+ return 0;
+
+ Decl *ClsType =
+ Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
+ superClassId, superClassLoc,
+ ProtocolRefs.data(), ProtocolRefs.size(),
+ ProtocolLocs.data(),
+ EndProtoLoc, attrs.getList());
+
+ if (Tok.is(tok::l_brace))
+ ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
+
+ ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
+ return ClsType;
+}
+
+/// The Objective-C property callback. This should be defined where
+/// it's used, but instead it's been lifted to here to support VS2005.
+struct Parser::ObjCPropertyCallback : FieldCallback {
+ Parser &P;
+ Decl *IDecl;
+ llvm::SmallVectorImpl<Decl *> &Props;
+ ObjCDeclSpec &OCDS;
+ SourceLocation AtLoc;
+ tok::ObjCKeywordKind MethodImplKind;
+
+ ObjCPropertyCallback(Parser &P, Decl *IDecl,
+ llvm::SmallVectorImpl<Decl *> &Props,
+ ObjCDeclSpec &OCDS, SourceLocation AtLoc,
+ tok::ObjCKeywordKind MethodImplKind) :
+ P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
+ MethodImplKind(MethodImplKind) {
+ }
+
+ Decl *invoke(FieldDeclarator &FD) {
+ if (FD.D.getIdentifier() == 0) {
+ P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
+ << FD.D.getSourceRange();
+ return 0;
+ }
+ if (FD.BitfieldSize) {
+ P.Diag(AtLoc, diag::err_objc_property_bitfield)
+ << FD.D.getSourceRange();
+ return 0;
+ }
+
+ // Install the property declarator into interfaceDecl.
+ IdentifierInfo *SelName =
+ OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
+
+ Selector GetterSel =
+ P.PP.getSelectorTable().getNullarySelector(SelName);
+ IdentifierInfo *SetterName = OCDS.getSetterName();
+ Selector SetterSel;
+ if (SetterName)
+ SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName);
+ else
+ SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(),
+ P.PP.getSelectorTable(),
+ FD.D.getIdentifier());
+ bool isOverridingProperty = false;
+ Decl *Property =
+ P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS,
+ GetterSel, SetterSel, IDecl,
+ &isOverridingProperty,
+ MethodImplKind);
+ if (!isOverridingProperty)
+ Props.push_back(Property);
+
+ return Property;
+ }
+};
+
+/// objc-interface-decl-list:
+/// empty
+/// objc-interface-decl-list objc-property-decl [OBJC2]
+/// objc-interface-decl-list objc-method-requirement [OBJC2]
+/// objc-interface-decl-list objc-method-proto ';'
+/// objc-interface-decl-list declaration
+/// objc-interface-decl-list ';'
+///
+/// objc-method-requirement: [OBJC2]
+/// @required
+/// @optional
+///
+void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
+ tok::ObjCKeywordKind contextKey) {
+ llvm::SmallVector<Decl *, 32> allMethods;
+ llvm::SmallVector<Decl *, 16> allProperties;
+ llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
+
+ SourceRange AtEnd;
+
+ while (1) {
+ // If this is a method prototype, parse it.
+ if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
+ Decl *methodPrototype =
+ ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
+ allMethods.push_back(methodPrototype);
+ // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
+ // method definitions.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_method_proto,
+ "", tok::semi);
+ continue;
+ }
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_minus_or_plus);
+ ParseObjCMethodDecl(Tok.getLocation(),
+ tok::minus,
+ interfaceDecl,
+ MethodImplKind);
+ continue;
+ }
+ // Ignore excess semicolons.
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ continue;
+ }
+
+ // If we got to the end of the file, exit the loop.
+ if (Tok.is(tok::eof))
+ break;
+
+ // Code completion within an Objective-C interface.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
+ ObjCImpDecl? Sema::PCC_ObjCImplementation
+ : Sema::PCC_ObjCInterface);
+ ConsumeCodeCompletionToken();
+ }
+
+ // If we don't have an @ directive, parse it as a function definition.
+ if (Tok.isNot(tok::at)) {
+ // The code below does not consume '}'s because it is afraid of eating the
+ // end of a namespace. Because of the way this code is structured, an
+ // erroneous r_brace would cause an infinite loop if not handled here.
+ if (Tok.is(tok::r_brace))
+ break;
+
+ // FIXME: as the name implies, this rule allows function definitions.
+ // We could pass a flag or check for functions during semantic analysis.
+ ParsedAttributes attrs;
+ allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
+ continue;
+ }
+
+ // Otherwise, we have an @ directive, eat the @.
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true);
+ ConsumeCodeCompletionToken();
+ break;
+ }
+
+ tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
+
+ if (DirectiveKind == tok::objc_end) { // @end -> terminate list
+ AtEnd.setBegin(AtLoc);
+ AtEnd.setEnd(Tok.getLocation());
+ break;
+ } else if (DirectiveKind == tok::objc_not_keyword) {
+ Diag(Tok, diag::err_objc_unknown_at);
+ SkipUntil(tok::semi);
+ continue;
+ }
+
+ // Eat the identifier.
+ ConsumeToken();
+
+ switch (DirectiveKind) {
+ default:
+ // FIXME: If someone forgets an @end on a protocol, this loop will
+ // continue to eat up tons of stuff and spew lots of nonsense errors. It
+ // would probably be better to bail out if we saw an @class or @interface
+ // or something like that.
+ Diag(AtLoc, diag::err_objc_illegal_interface_qual);
+ // Skip until we see an '@' or '}' or ';'.
+ SkipUntil(tok::r_brace, tok::at);
+ break;
+
+ case tok::objc_implementation:
+ case tok::objc_interface:
+ Diag(Tok, diag::err_objc_missing_end);
+ ConsumeToken();
+ break;
+
+ case tok::objc_required:
+ case tok::objc_optional:
+ // This is only valid on protocols.
+ // FIXME: Should this check for ObjC2 being enabled?
+ if (contextKey != tok::objc_protocol)
+ Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
+ else
+ MethodImplKind = DirectiveKind;
+ break;
+
+ case tok::objc_property:
+ if (!getLang().ObjC2)
+ Diag(AtLoc, diag::err_objc_properties_require_objc2);
+
+ ObjCDeclSpec OCDS;
+ // Parse property attribute list, if any.
+ if (Tok.is(tok::l_paren))
+ ParseObjCPropertyAttribute(OCDS, interfaceDecl);
+
+ ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties,
+ OCDS, AtLoc, MethodImplKind);
+
+ // Parse all the comma separated declarators.
+ DeclSpec DS;
+ ParseStructDeclaration(DS, Callback);
+
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
+ tok::at);
+ break;
+ }
+ }
+
+ // We break out of the big loop in two cases: when we see @end or when we see
+ // EOF. In the former case, eat the @end. In the later case, emit an error.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true);
+ ConsumeCodeCompletionToken();
+ } else if (Tok.isObjCAtKeyword(tok::objc_end))
+ ConsumeToken(); // the "end" identifier
+ else
+ Diag(Tok, diag::err_objc_missing_end);
+
+ // Insert collected methods declarations into the @interface object.
+ // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
+ Actions.ActOnAtEnd(getCurScope(), AtEnd, interfaceDecl,
+ allMethods.data(), allMethods.size(),
+ allProperties.data(), allProperties.size(),
+ allTUVariables.data(), allTUVariables.size());
+}
+
+/// Parse property attribute declarations.
+///
+/// property-attr-decl: '(' property-attrlist ')'
+/// property-attrlist:
+/// property-attribute
+/// property-attrlist ',' property-attribute
+/// property-attribute:
+/// getter '=' identifier
+/// setter '=' identifier ':'
+/// readonly
+/// readwrite
+/// assign
+/// retain
+/// copy
+/// nonatomic
+///
+void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
+ assert(Tok.getKind() == tok::l_paren);
+ SourceLocation LHSLoc = ConsumeParen(); // consume '('
+
+ while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
+ ConsumeCodeCompletionToken();
+ }
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ // If this is not an identifier at all, bail out early.
+ if (II == 0) {
+ MatchRHSPunctuation(tok::r_paren, LHSLoc);
+ return;
+ }
+
+ SourceLocation AttrName = ConsumeToken(); // consume last attribute name
+
+ if (II->isStr("readonly"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
+ else if (II->isStr("assign"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
+ else if (II->isStr("readwrite"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
+ else if (II->isStr("retain"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
+ else if (II->isStr("copy"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
+ else if (II->isStr("nonatomic"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
+ else if (II->isStr("atomic"))
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);
+ else if (II->isStr("getter") || II->isStr("setter")) {
+ bool IsSetter = II->getNameStart()[0] == 's';
+
+ // getter/setter require extra treatment.
+ unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
+ diag::err_objc_expected_equal_for_getter;
+
+ if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren))
+ return;
+
+ if (Tok.is(tok::code_completion)) {
+ if (IsSetter)
+ Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl);
+ else
+ Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+
+ SourceLocation SelLoc;
+ IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
+
+ if (!SelIdent) {
+ Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
+ << IsSetter;
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ if (IsSetter) {
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
+ DS.setSetterName(SelIdent);
+
+ if (ExpectAndConsume(tok::colon,
+ diag::err_expected_colon_after_setter_name, "",
+ tok::r_paren))
+ return;
+ } else {
+ DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
+ DS.setGetterName(SelIdent);
+ }
+ } else {
+ Diag(AttrName, diag::err_objc_expected_property_attr) << II;
+ SkipUntil(tok::r_paren);
+ return;
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+
+ ConsumeToken();
+ }
+
+ MatchRHSPunctuation(tok::r_paren, LHSLoc);
+}
+
+/// objc-method-proto:
+/// objc-instance-method objc-method-decl objc-method-attributes[opt]
+/// objc-class-method objc-method-decl objc-method-attributes[opt]
+///
+/// objc-instance-method: '-'
+/// objc-class-method: '+'
+///
+/// objc-method-attributes: [OBJC2]
+/// __attribute__((deprecated))
+///
+Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl,
+ tok::ObjCKeywordKind MethodImplKind) {
+ assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
+
+ tok::TokenKind methodType = Tok.getKind();
+ SourceLocation mLoc = ConsumeToken();
+ Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
+ // Since this rule is used for both method declarations and definitions,
+ // the caller is (optionally) responsible for consuming the ';'.
+ return MDecl;
+}
+
+/// objc-selector:
+/// identifier
+/// one of
+/// enum struct union if else while do for switch case default
+/// break continue return goto asm sizeof typeof __alignof
+/// unsigned long const short volatile signed restrict _Complex
+/// in out inout bycopy byref oneway int char float double void _Bool
+///
+IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
+
+ switch (Tok.getKind()) {
+ default:
+ return 0;
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::amp:
+ case tok::pipe:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::caret:
+ case tok::caretequal: {
+ std::string ThisTok(PP.getSpelling(Tok));
+ if (isalpha(ThisTok[0])) {
+ IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data());
+ Tok.setKind(tok::identifier);
+ SelectorLoc = ConsumeToken();
+ return II;
+ }
+ return 0;
+ }
+
+ case tok::identifier:
+ case tok::kw_asm:
+ case tok::kw_auto:
+ case tok::kw_bool:
+ case tok::kw_break:
+ case tok::kw_case:
+ case tok::kw_catch:
+ case tok::kw_char:
+ case tok::kw_class:
+ case tok::kw_const:
+ case tok::kw_const_cast:
+ case tok::kw_continue:
+ case tok::kw_default:
+ case tok::kw_delete:
+ case tok::kw_do:
+ case tok::kw_double:
+ case tok::kw_dynamic_cast:
+ case tok::kw_else:
+ case tok::kw_enum:
+ case tok::kw_explicit:
+ case tok::kw_export:
+ case tok::kw_extern:
+ case tok::kw_false:
+ case tok::kw_float:
+ case tok::kw_for:
+ case tok::kw_friend:
+ case tok::kw_goto:
+ case tok::kw_if:
+ case tok::kw_inline:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw_mutable:
+ case tok::kw_namespace:
+ case tok::kw_new:
+ case tok::kw_operator:
+ case tok::kw_private:
+ case tok::kw_protected:
+ case tok::kw_public:
+ case tok::kw_register:
+ case tok::kw_reinterpret_cast:
+ case tok::kw_restrict:
+ case tok::kw_return:
+ case tok::kw_short:
+ case tok::kw_signed:
+ case tok::kw_sizeof:
+ case tok::kw_static:
+ case tok::kw_static_cast:
+ case tok::kw_struct:
+ case tok::kw_switch:
+ case tok::kw_template:
+ case tok::kw_this:
+ case tok::kw_throw:
+ case tok::kw_true:
+ case tok::kw_try:
+ case tok::kw_typedef:
+ case tok::kw_typeid:
+ case tok::kw_typename:
+ case tok::kw_typeof:
+ case tok::kw_union:
+ case tok::kw_unsigned:
+ case tok::kw_using:
+ case tok::kw_virtual:
+ case tok::kw_void:
+ case tok::kw_volatile:
+ case tok::kw_wchar_t:
+ case tok::kw_while:
+ case tok::kw__Bool:
+ case tok::kw__Complex:
+ case tok::kw___alignof:
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ SelectorLoc = ConsumeToken();
+ return II;
+ }
+}
+
+/// objc-for-collection-in: 'in'
+///
+bool Parser::isTokIdentifier_in() const {
+ // FIXME: May have to do additional look-ahead to only allow for
+ // valid tokens following an 'in'; such as an identifier, unary operators,
+ // '[' etc.
+ return (getLang().ObjC2 && Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
+}
+
+/// ParseObjCTypeQualifierList - This routine parses the objective-c's type
+/// qualifier list and builds their bitmask representation in the input
+/// argument.
+///
+/// objc-type-qualifiers:
+/// objc-type-qualifier
+/// objc-type-qualifiers objc-type-qualifier
+///
+void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) {
+ while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPassingType(getCurScope(), DS, IsParameter);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier))
+ return;
+
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ for (unsigned i = 0; i != objc_NumQuals; ++i) {
+ if (II != ObjCTypeQuals[i])
+ continue;
+
+ ObjCDeclSpec::ObjCDeclQualifier Qual;
+ switch (i) {
+ default: assert(0 && "Unknown decl qualifier");
+ case objc_in: Qual = ObjCDeclSpec::DQ_In; break;
+ case objc_out: Qual = ObjCDeclSpec::DQ_Out; break;
+ case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break;
+ case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
+ case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
+ case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break;
+ }
+ DS.setObjCDeclQualifier(Qual);
+ ConsumeToken();
+ II = 0;
+ break;
+ }
+
+ // If this wasn't a recognized qualifier, bail out.
+ if (II) return;
+ }
+}
+
+/// objc-type-name:
+/// '(' objc-type-qualifiers[opt] type-name ')'
+/// '(' objc-type-qualifiers[opt] ')'
+///
+ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) {
+ assert(Tok.is(tok::l_paren) && "expected (");
+
+ SourceLocation LParenLoc = ConsumeParen();
+ SourceLocation TypeStartLoc = Tok.getLocation();
+
+ // Parse type qualifiers, in, inout, etc.
+ ParseObjCTypeQualifierList(DS, IsParameter);
+
+ ParsedType Ty;
+ if (isTypeSpecifierQualifier()) {
+ TypeResult TypeSpec = ParseTypeName();
+ if (!TypeSpec.isInvalid())
+ Ty = TypeSpec.get();
+ }
+
+ if (Tok.is(tok::r_paren))
+ ConsumeParen();
+ else if (Tok.getLocation() == TypeStartLoc) {
+ // If we didn't eat any tokens, then this isn't a type.
+ Diag(Tok, diag::err_expected_type);
+ SkipUntil(tok::r_paren);
+ } else {
+ // Otherwise, we found *something*, but didn't get a ')' in the right
+ // place. Emit an error then return what we have as the type.
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ }
+ return Ty;
+}
+
+/// objc-method-decl:
+/// objc-selector
+/// objc-keyword-selector objc-parmlist[opt]
+/// objc-type-name objc-selector
+/// objc-type-name objc-keyword-selector objc-parmlist[opt]
+///
+/// objc-keyword-selector:
+/// objc-keyword-decl
+/// objc-keyword-selector objc-keyword-decl
+///
+/// objc-keyword-decl:
+/// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
+/// objc-selector ':' objc-keyword-attributes[opt] identifier
+/// ':' objc-type-name objc-keyword-attributes[opt] identifier
+/// ':' objc-keyword-attributes[opt] identifier
+///
+/// objc-parmlist:
+/// objc-parms objc-ellipsis[opt]
+///
+/// objc-parms:
+/// objc-parms , parameter-declaration
+///
+/// objc-ellipsis:
+/// , ...
+///
+/// objc-keyword-attributes: [OBJC2]
+/// __attribute__((unused))
+///
+Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
+ tok::TokenKind mType,
+ Decl *IDecl,
+ tok::ObjCKeywordKind MethodImplKind) {
+ ParsingDeclRAIIObject PD(*this);
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
+ /*ReturnType=*/ ParsedType(), IDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+ // Parse the return type if present.
+ ParsedType ReturnType;
+ ObjCDeclSpec DSRet;
+ if (Tok.is(tok::l_paren))
+ ReturnType = ParseObjCTypeName(DSRet, false);
+
+ // If attributes exist before the method, parse them.
+ ParsedAttributes attrs;
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
+ ReturnType, IDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+ // Now parse the selector.
+ SourceLocation selLoc;
+ IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
+
+ // An unnamed colon is valid.
+ if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
+ Diag(Tok, diag::err_expected_selector_for_method)
+ << SourceRange(mLoc, Tok.getLocation());
+ // Skip until we get a ; or {}.
+ SkipUntil(tok::r_brace);
+ return 0;
+ }
+
+ llvm::SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
+ if (Tok.isNot(tok::colon)) {
+ // If attributes exist after the method, parse them.
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
+
+ Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
+ Decl *Result
+ = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
+ mType, IDecl, DSRet, ReturnType, Sel,
+ 0,
+ CParamInfo.data(), CParamInfo.size(),
+ attrs.getList(), MethodImplKind);
+ PD.complete(Result);
+ return Result;
+ }
+
+ llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+ llvm::SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
+ ParseScope PrototypeScope(this,
+ Scope::FunctionPrototypeScope|Scope::DeclScope);
+
+ while (1) {
+ Sema::ObjCArgInfo ArgInfo;
+
+ // Each iteration parses a single keyword argument.
+ if (Tok.isNot(tok::colon)) {
+ Diag(Tok, diag::err_expected_colon);
+ break;
+ }
+ ConsumeToken(); // Eat the ':'.
+
+ ArgInfo.Type = ParsedType();
+ if (Tok.is(tok::l_paren)) // Parse the argument type if present.
+ ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, true);
+
+ // If attributes exist before the argument name, parse them.
+ ArgInfo.ArgAttrs = 0;
+ if (getLang().ObjC2) {
+ ParsedAttributes attrs;
+ MaybeParseGNUAttributes(attrs);
+ ArgInfo.ArgAttrs = attrs.getList();
+ }
+
+ // Code completion for the next piece of the selector.
+ if (Tok.is(tok::code_completion)) {
+ ConsumeCodeCompletionToken();
+ KeyIdents.push_back(SelIdent);
+ Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
+ mType == tok::minus,
+ /*AtParameterName=*/true,
+ ReturnType,
+ KeyIdents.data(),
+ KeyIdents.size());
+ KeyIdents.pop_back();
+ break;
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing argument name.
+ break;
+ }
+
+ ArgInfo.Name = Tok.getIdentifierInfo();
+ ArgInfo.NameLoc = Tok.getLocation();
+ ConsumeToken(); // Eat the identifier.
+
+ ArgInfos.push_back(ArgInfo);
+ KeyIdents.push_back(SelIdent);
+
+ // Code completion for the next piece of the selector.
+ if (Tok.is(tok::code_completion)) {
+ ConsumeCodeCompletionToken();
+ Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
+ mType == tok::minus,
+ /*AtParameterName=*/false,
+ ReturnType,
+ KeyIdents.data(),
+ KeyIdents.size());
+ break;
+ }
+
+ // Check for another keyword selector.
+ SourceLocation Loc;
+ SelIdent = ParseObjCSelectorPiece(Loc);
+ if (!SelIdent && Tok.isNot(tok::colon))
+ break;
+ // We have a selector or a colon, continue parsing.
+ }
+
+ bool isVariadic = false;
+
+ // Parse the (optional) parameter list.
+ while (Tok.is(tok::comma)) {
+ ConsumeToken();
+ if (Tok.is(tok::ellipsis)) {
+ isVariadic = true;
+ ConsumeToken();
+ break;
+ }
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
+ // Parse the declarator.
+ Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ ParseDeclarator(ParmDecl);
+ IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+ CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+ ParmDecl.getIdentifierLoc(),
+ Param,
+ 0));
+
+ }
+
+ // FIXME: Add support for optional parameter list...
+ // If attributes exist after the method, parse them.
+ if (getLang().ObjC2)
+ MaybeParseGNUAttributes(attrs);
+
+ if (KeyIdents.size() == 0) {
+ // Leave prototype scope.
+ PrototypeScope.Exit();
+ return 0;
+ }
+
+ Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
+ &KeyIdents[0]);
+ Decl *Result
+ = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
+ mType, IDecl, DSRet, ReturnType, Sel,
+ &ArgInfos[0],
+ CParamInfo.data(), CParamInfo.size(),
+ attrs.getList(),
+ MethodImplKind, isVariadic);
+ // Leave prototype scope.
+ PrototypeScope.Exit();
+
+ PD.complete(Result);
+ return Result;
+}
+
+/// objc-protocol-refs:
+/// '<' identifier-list '>'
+///
+bool Parser::
+ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &Protocols,
+ llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs,
+ bool WarnOnDeclarations,
+ SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
+ assert(Tok.is(tok::less) && "expected <");
+
+ LAngleLoc = ConsumeToken(); // the "<"
+
+ llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
+
+ while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
+ ProtocolIdents.size());
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::greater);
+ return true;
+ }
+ ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
+ Tok.getLocation()));
+ ProtocolLocs.push_back(Tok.getLocation());
+ ConsumeToken();
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken();
+ }
+
+ // Consume the '>'.
+ if (Tok.isNot(tok::greater)) {
+ Diag(Tok, diag::err_expected_greater);
+ return true;
+ }
+
+ EndLoc = ConsumeAnyToken();
+
+ // Convert the list of protocols identifiers into a list of protocol decls.
+ Actions.FindProtocolDeclaration(WarnOnDeclarations,
+ &ProtocolIdents[0], ProtocolIdents.size(),
+ Protocols);
+ return false;
+}
+
+/// \brief Parse the Objective-C protocol qualifiers that follow a typename
+/// in a decl-specifier-seq, starting at the '<'.
+bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
+ assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
+ assert(getLang().ObjC1 && "Protocol qualifiers only exist in Objective-C");
+ SourceLocation LAngleLoc, EndProtoLoc;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
+ if (EndProtoLoc.isValid())
+ DS.SetRangeEnd(EndProtoLoc);
+ return Result;
+}
+
+
+/// objc-class-instance-variables:
+/// '{' objc-instance-variable-decl-list[opt] '}'
+///
+/// objc-instance-variable-decl-list:
+/// objc-visibility-spec
+/// objc-instance-variable-decl ';'
+/// ';'
+/// objc-instance-variable-decl-list objc-visibility-spec
+/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
+/// objc-instance-variable-decl-list ';'
+///
+/// objc-visibility-spec:
+/// @private
+/// @protected
+/// @public
+/// @package [OBJC2]
+///
+/// objc-instance-variable-decl:
+/// struct-declaration
+///
+void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
+ tok::ObjCKeywordKind visibility,
+ SourceLocation atLoc) {
+ assert(Tok.is(tok::l_brace) && "expected {");
+ llvm::SmallVector<Decl *, 32> AllIvarDecls;
+
+ ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
+
+ SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
+
+ // While we still have something to read, read the instance variables.
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ // Each iteration of this loop reads one objc-instance-variable-decl.
+
+ // Check for extraneous top-level semicolon.
+ if (Tok.is(tok::semi)) {
+ Diag(Tok, diag::ext_extra_ivar_semi)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ ConsumeToken();
+ continue;
+ }
+
+ // Set the default visibility to private.
+ if (Tok.is(tok::at)) { // parse objc-visibility-spec
+ ConsumeToken(); // eat the @ sign
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtVisibility(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ switch (Tok.getObjCKeywordID()) {
+ case tok::objc_private:
+ case tok::objc_public:
+ case tok::objc_protected:
+ case tok::objc_package:
+ visibility = Tok.getObjCKeywordID();
+ ConsumeToken();
+ continue;
+ default:
+ Diag(Tok, diag::err_objc_illegal_visibility_spec);
+ continue;
+ }
+ }
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
+ Sema::PCC_ObjCInstanceVariableList);
+ ConsumeCodeCompletionToken();
+ }
+
+ struct ObjCIvarCallback : FieldCallback {
+ Parser &P;
+ Decl *IDecl;
+ tok::ObjCKeywordKind visibility;
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls;
+
+ ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls) :
+ P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
+ }
+
+ Decl *invoke(FieldDeclarator &FD) {
+ // Install the declarator into the interface decl.
+ Decl *Field
+ = P.Actions.ActOnIvar(P.getCurScope(),
+ FD.D.getDeclSpec().getSourceRange().getBegin(),
+ IDecl, FD.D, FD.BitfieldSize, visibility);
+ if (Field)
+ AllIvarDecls.push_back(Field);
+ return Field;
+ }
+ } Callback(*this, interfaceDecl, visibility, AllIvarDecls);
+
+ // Parse all the comma separated declarators.
+ DeclSpec DS;
+ ParseStructDeclaration(DS, Callback);
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_expected_semi_decl_list);
+ // Skip to end of block or statement
+ SkipUntil(tok::r_brace, true, true);
+ }
+ }
+ SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls);
+ // Call ActOnFields() even if we don't have any decls. This is useful
+ // for code rewriting tools that need to be aware of the empty list.
+ Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
+ AllIvarDecls.data(), AllIvarDecls.size(),
+ LBraceLoc, RBraceLoc, 0);
+ return;
+}
+
+/// objc-protocol-declaration:
+/// objc-protocol-definition
+/// objc-protocol-forward-reference
+///
+/// objc-protocol-definition:
+/// @protocol identifier
+/// objc-protocol-refs[opt]
+/// objc-interface-decl-list
+/// @end
+///
+/// objc-protocol-forward-reference:
+/// @protocol identifier-list ';'
+///
+/// "@protocol identifier ;" should be resolved as "@protocol
+/// identifier-list ;": objc-interface-decl-list may not start with a
+/// semicolon in the first alternative if objc-protocol-refs are omitted.
+Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
+ ParsedAttributes &attrs) {
+ assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
+ "ParseObjCAtProtocolDeclaration(): Expected @protocol");
+ ConsumeToken(); // the "protocol" identifier
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProtocolDecl(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing protocol name.
+ return 0;
+ }
+ // Save the protocol name, then consume it.
+ IdentifierInfo *protocolName = Tok.getIdentifierInfo();
+ SourceLocation nameLoc = ConsumeToken();
+
+ if (Tok.is(tok::semi)) { // forward declaration of one protocol.
+ IdentifierLocPair ProtoInfo(protocolName, nameLoc);
+ ConsumeToken();
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
+ attrs.getList());
+ }
+
+ if (Tok.is(tok::comma)) { // list of forward declarations.
+ llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
+ ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
+
+ // Parse the list of forward declarations.
+ while (1) {
+ ConsumeToken(); // the ','
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+ ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
+ Tok.getLocation()));
+ ConsumeToken(); // the identifier
+
+ if (Tok.isNot(tok::comma))
+ break;
+ }
+ // Consume the ';'.
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
+ return 0;
+
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc,
+ &ProtocolRefs[0],
+ ProtocolRefs.size(),
+ attrs.getList());
+ }
+
+ // Last, and definitely not least, parse a protocol declaration.
+ SourceLocation LAngleLoc, EndProtoLoc;
+
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ if (Tok.is(tok::less) &&
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc))
+ return 0;
+
+ Decl *ProtoType =
+ Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
+ ProtocolRefs.data(),
+ ProtocolRefs.size(),
+ ProtocolLocs.data(),
+ EndProtoLoc, attrs.getList());
+ ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
+ return ProtoType;
+}
+
+/// objc-implementation:
+/// objc-class-implementation-prologue
+/// objc-category-implementation-prologue
+///
+/// objc-class-implementation-prologue:
+/// @implementation identifier objc-superclass[opt]
+/// objc-class-instance-variables[opt]
+///
+/// objc-category-implementation-prologue:
+/// @implementation identifier ( identifier )
+Decl *Parser::ParseObjCAtImplementationDeclaration(
+ SourceLocation atLoc) {
+ assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
+ "ParseObjCAtImplementationDeclaration(): Expected @implementation");
+ ConsumeToken(); // the "implementation" identifier
+
+ // Code completion after '@implementation'.
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCImplementationDecl(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing class or category name.
+ return 0;
+ }
+ // We have a class or category name - consume it.
+ IdentifierInfo *nameId = Tok.getIdentifierInfo();
+ SourceLocation nameLoc = ConsumeToken(); // consume class or category name
+
+ if (Tok.is(tok::l_paren)) {
+ // we have a category implementation.
+ ConsumeParen();
+ SourceLocation categoryLoc, rparenLoc;
+ IdentifierInfo *categoryId = 0;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.is(tok::identifier)) {
+ categoryId = Tok.getIdentifierInfo();
+ categoryLoc = ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_expected_ident); // missing category name.
+ return 0;
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected_rparen);
+ SkipUntil(tok::r_paren, false); // don't stop at ';'
+ return 0;
+ }
+ rparenLoc = ConsumeParen();
+ Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
+ atLoc, nameId, nameLoc, categoryId,
+ categoryLoc);
+ ObjCImpDecl = ImplCatType;
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
+ return 0;
+ }
+ // We have a class implementation
+ SourceLocation superClassLoc;
+ IdentifierInfo *superClassId = 0;
+ if (Tok.is(tok::colon)) {
+ // We have a super class
+ ConsumeToken();
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident); // missing super class name.
+ return 0;
+ }
+ superClassId = Tok.getIdentifierInfo();
+ superClassLoc = ConsumeToken(); // Consume super class name
+ }
+ Decl *ImplClsType = Actions.ActOnStartClassImplementation(
+ atLoc, nameId, nameLoc,
+ superClassId, superClassLoc);
+
+ if (Tok.is(tok::l_brace)) // we have ivars
+ ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/,
+ tok::objc_private, atLoc);
+ ObjCImpDecl = ImplClsType;
+ PendingObjCImpDecl.push_back(ObjCImpDecl);
+
+ return 0;
+}
+
+Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
+ assert(Tok.isObjCAtKeyword(tok::objc_end) &&
+ "ParseObjCAtEndDeclaration(): Expected @end");
+ Decl *Result = ObjCImpDecl;
+ ConsumeToken(); // the "end" identifier
+ if (ObjCImpDecl) {
+ Actions.ActOnAtEnd(getCurScope(), atEnd, ObjCImpDecl);
+ ObjCImpDecl = 0;
+ PendingObjCImpDecl.pop_back();
+ }
+ else {
+ // missing @implementation
+ Diag(atEnd.getBegin(), diag::warn_expected_implementation);
+ }
+ return Result;
+}
+
+Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
+ Actions.DiagnoseUseOfUnimplementedSelectors();
+ if (PendingObjCImpDecl.empty())
+ return Actions.ConvertDeclToDeclGroup(0);
+ Decl *ImpDecl = PendingObjCImpDecl.pop_back_val();
+ Actions.ActOnAtEnd(getCurScope(), SourceRange(), ImpDecl);
+ return Actions.ConvertDeclToDeclGroup(ImpDecl);
+}
+
+/// compatibility-alias-decl:
+/// @compatibility_alias alias-name class-name ';'
+///
+Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
+ assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
+ "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
+ ConsumeToken(); // consume compatibility_alias
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ return 0;
+ }
+ IdentifierInfo *aliasId = Tok.getIdentifierInfo();
+ SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ return 0;
+ }
+ IdentifierInfo *classId = Tok.getIdentifierInfo();
+ SourceLocation classLoc = ConsumeToken(); // consume class-name;
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ "@compatibility_alias");
+ return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc,
+ classId, classLoc);
+}
+
+/// property-synthesis:
+/// @synthesize property-ivar-list ';'
+///
+/// property-ivar-list:
+/// property-ivar
+/// property-ivar-list ',' property-ivar
+///
+/// property-ivar:
+/// identifier
+/// identifier '=' identifier
+///
+Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
+ assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
+ "ParseObjCPropertyDynamic(): Expected '@synthesize'");
+ ConsumeToken(); // consume synthesize
+
+ while (true) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_synthesized_property_name);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ IdentifierInfo *propertyIvar = 0;
+ IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+ SourceLocation propertyLoc = ConsumeToken(); // consume property name
+ SourceLocation propertyIvarLoc;
+ if (Tok.is(tok::equal)) {
+ // property '=' ivar-name
+ ConsumeToken(); // consume '='
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId,
+ ObjCImpDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ break;
+ }
+ propertyIvar = Tok.getIdentifierInfo();
+ propertyIvarLoc = ConsumeToken(); // consume ivar-name
+ }
+ Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, ObjCImpDecl,
+ propertyId, propertyIvar, propertyIvarLoc);
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // consume ','
+ }
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize");
+ return 0;
+}
+
+/// property-dynamic:
+/// @dynamic property-list
+///
+/// property-list:
+/// identifier
+/// property-list ',' identifier
+///
+Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
+ assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
+ "ParseObjCPropertyDynamic(): Expected '@dynamic'");
+ ConsumeToken(); // consume dynamic
+ while (true) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl);
+ ConsumeCodeCompletionToken();
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
+ IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+ SourceLocation propertyLoc = ConsumeToken(); // consume property name
+ Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, ObjCImpDecl,
+ propertyId, 0, SourceLocation());
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // consume ','
+ }
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic");
+ return 0;
+}
+
+/// objc-throw-statement:
+/// throw expression[opt];
+///
+StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
+ ExprResult Res;
+ ConsumeToken(); // consume throw
+ if (Tok.isNot(tok::semi)) {
+ Res = ParseExpression();
+ if (Res.isInvalid()) {
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+ }
+ // consume ';'
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
+ return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
+}
+
+/// objc-synchronized-statement:
+/// @synchronized '(' expression ')' compound-statement
+///
+StmtResult
+Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
+ ConsumeToken(); // consume synchronized
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
+ return StmtError();
+ }
+ ConsumeParen(); // '('
+ ExprResult Res(ParseExpression());
+ if (Res.isInvalid()) {
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected_lbrace);
+ return StmtError();
+ }
+ ConsumeParen(); // ')'
+ if (Tok.isNot(tok::l_brace)) {
+ Diag(Tok, diag::err_expected_lbrace);
+ return StmtError();
+ }
+ // Enter a scope to hold everything within the compound stmt. Compound
+ // statements can always hold declarations.
+ ParseScope BodyScope(this, Scope::DeclScope);
+
+ StmtResult SynchBody(ParseCompoundStatementBody());
+
+ BodyScope.Exit();
+ if (SynchBody.isInvalid())
+ SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
+ return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.take(), SynchBody.take());
+}
+
+/// objc-try-catch-statement:
+/// @try compound-statement objc-catch-list[opt]
+/// @try compound-statement objc-catch-list[opt] @finally compound-statement
+///
+/// objc-catch-list:
+/// @catch ( parameter-declaration ) compound-statement
+/// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
+/// catch-parameter-declaration:
+/// parameter-declaration
+/// '...' [OBJC2]
+///
+StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
+ bool catch_or_finally_seen = false;
+
+ ConsumeToken(); // consume try
+ if (Tok.isNot(tok::l_brace)) {
+ Diag(Tok, diag::err_expected_lbrace);
+ return StmtError();
+ }
+ StmtVector CatchStmts(Actions);
+ StmtResult FinallyStmt;
+ ParseScope TryScope(this, Scope::DeclScope);
+ StmtResult TryBody(ParseCompoundStatementBody());
+ TryScope.Exit();
+ if (TryBody.isInvalid())
+ TryBody = Actions.ActOnNullStmt(Tok.getLocation());
+
+ while (Tok.is(tok::at)) {
+ // At this point, we need to lookahead to determine if this @ is the start
+ // of an @catch or @finally. We don't want to consume the @ token if this
+ // is an @try or @encode or something else.
+ Token AfterAt = GetLookAheadToken(1);
+ if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
+ !AfterAt.isObjCAtKeyword(tok::objc_finally))
+ break;
+
+ SourceLocation AtCatchFinallyLoc = ConsumeToken();
+ if (Tok.isObjCAtKeyword(tok::objc_catch)) {
+ Decl *FirstPart = 0;
+ ConsumeToken(); // consume catch
+ if (Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
+ if (Tok.isNot(tok::ellipsis)) {
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
+ // For some odd reason, the name of the exception variable is
+ // optional. As a result, we need to use "PrototypeContext", because
+ // we must accept either 'declarator' or 'abstract-declarator' here.
+ Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ ParseDeclarator(ParmDecl);
+
+ // Inform the actions module about the declarator, so it
+ // gets added to the current scope.
+ FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
+ } else
+ ConsumeToken(); // consume '...'
+
+ SourceLocation RParenLoc;
+
+ if (Tok.is(tok::r_paren))
+ RParenLoc = ConsumeParen();
+ else // Skip over garbage, until we get to ')'. Eat the ')'.
+ SkipUntil(tok::r_paren, true, false);
+
+ StmtResult CatchBody(true);
+ if (Tok.is(tok::l_brace))
+ CatchBody = ParseCompoundStatementBody();
+ else
+ Diag(Tok, diag::err_expected_lbrace);
+ if (CatchBody.isInvalid())
+ CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
+
+ StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
+ RParenLoc,
+ FirstPart,
+ CatchBody.take());
+ if (!Catch.isInvalid())
+ CatchStmts.push_back(Catch.release());
+
+ } else {
+ Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
+ << "@catch clause";
+ return StmtError();
+ }
+ catch_or_finally_seen = true;
+ } else {
+ assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
+ ConsumeToken(); // consume finally
+ ParseScope FinallyScope(this, Scope::DeclScope);
+
+ StmtResult FinallyBody(true);
+ if (Tok.is(tok::l_brace))
+ FinallyBody = ParseCompoundStatementBody();
+ else
+ Diag(Tok, diag::err_expected_lbrace);
+ if (FinallyBody.isInvalid())
+ FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
+ FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
+ FinallyBody.take());
+ catch_or_finally_seen = true;
+ break;
+ }
+ }
+ if (!catch_or_finally_seen) {
+ Diag(atLoc, diag::err_missing_catch_finally);
+ return StmtError();
+ }
+
+ return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(),
+ move_arg(CatchStmts),
+ FinallyStmt.take());
+}
+
+/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
+///
+Decl *Parser::ParseObjCMethodDefinition() {
+ Decl *MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
+
+ PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
+ "parsing Objective-C method");
+
+ // parse optional ';'
+ if (Tok.is(tok::semi)) {
+ if (ObjCImpDecl) {
+ Diag(Tok, diag::warn_semicolon_before_method_body)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ }
+ ConsumeToken();
+ }
+
+ // We should have an opening brace now.
+ if (Tok.isNot(tok::l_brace)) {
+ Diag(Tok, diag::err_expected_method_body);
+
+ // Skip over garbage, until we get to '{'. Don't eat the '{'.
+ SkipUntil(tok::l_brace, true, true);
+
+ // If we didn't find the '{', bail out.
+ if (Tok.isNot(tok::l_brace))
+ return 0;
+ }
+ SourceLocation BraceLoc = Tok.getLocation();
+
+ // Enter a scope for the method body.
+ ParseScope BodyScope(this,
+ Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope);
+
+ // Tell the actions module that we have entered a method definition with the
+ // specified Declarator for the method.
+ Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);
+
+ if (PP.isCodeCompletionEnabled())
+ if (trySkippingFunctionBodyForCodeCompletion())
+ return Actions.ActOnFinishFunctionBody(MDecl, 0);
+
+ StmtResult FnBody(ParseCompoundStatementBody());
+
+ // If the function body could not be parsed, make a bogus compoundstmt.
+ if (FnBody.isInvalid())
+ FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
+ MultiStmtArg(Actions), false);
+
+ // TODO: Pass argument information.
+ Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
+
+ // Leave the function body scope.
+ BodyScope.Exit();
+
+ return MDecl;
+}
+
+StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCAtStatement(getCurScope());
+ ConsumeCodeCompletionToken();
+ return StmtError();
+ }
+
+ if (Tok.isObjCAtKeyword(tok::objc_try))
+ return ParseObjCTryStmt(AtLoc);
+
+ if (Tok.isObjCAtKeyword(tok::objc_throw))
+ return ParseObjCThrowStmt(AtLoc);
+
+ if (Tok.isObjCAtKeyword(tok::objc_synchronized))
+ return ParseObjCSynchronizedStmt(AtLoc);
+
+ ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
+ if (Res.isInvalid()) {
+ // If the expression is invalid, skip ahead to the next semicolon. Not
+ // doing this opens us up to the possibility of infinite loops if
+ // ParseExpression does not consume any tokens.
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+
+ // Otherwise, eat the semicolon.
+ ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+ return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.take()));
+}
+
+ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
+ switch (Tok.getKind()) {
+ case tok::code_completion:
+ Actions.CodeCompleteObjCAtExpression(getCurScope());
+ ConsumeCodeCompletionToken();
+ return ExprError();
+
+ case tok::string_literal: // primary-expression: string-literal
+ case tok::wide_string_literal:
+ return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
+ default:
+ if (Tok.getIdentifierInfo() == 0)
+ return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+
+ switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
+ case tok::objc_encode:
+ return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
+ case tok::objc_protocol:
+ return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
+ case tok::objc_selector:
+ return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
+ default:
+ return ExprError(Diag(AtLoc, diag::err_unexpected_at));
+ }
+ }
+}
+
+/// \brirg Parse the receiver of an Objective-C++ message send.
+///
+/// This routine parses the receiver of a message send in
+/// Objective-C++ either as a type or as an expression. Note that this
+/// routine must not be called to parse a send to 'super', since it
+/// has no way to return such a result.
+///
+/// \param IsExpr Whether the receiver was parsed as an expression.
+///
+/// \param TypeOrExpr If the receiver was parsed as an expression (\c
+/// IsExpr is true), the parsed expression. If the receiver was parsed
+/// as a type (\c IsExpr is false), the parsed type.
+///
+/// \returns True if an error occurred during parsing or semantic
+/// analysis, in which case the arguments do not have valid
+/// values. Otherwise, returns false for a successful parse.
+///
+/// objc-receiver: [C++]
+/// 'super' [not parsed here]
+/// expression
+/// simple-type-specifier
+/// typename-specifier
+bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
+ if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
+ TryAnnotateTypeOrScopeToken();
+
+ if (!isCXXSimpleTypeSpecifier()) {
+ // objc-receiver:
+ // expression
+ ExprResult Receiver = ParseExpression();
+ if (Receiver.isInvalid())
+ return true;
+
+ IsExpr = true;
+ TypeOrExpr = Receiver.take();
+ return false;
+ }
+
+ // objc-receiver:
+ // typename-specifier
+ // simple-type-specifier
+ // expression (that starts with one of the above)
+ DeclSpec DS;
+ ParseCXXSimpleTypeSpecifier(DS);
+
+ if (Tok.is(tok::l_paren)) {
+ // If we see an opening parentheses at this point, we are
+ // actually parsing an expression that starts with a
+ // function-style cast, e.g.,
+ //
+ // postfix-expression:
+ // simple-type-specifier ( expression-list [opt] )
+ // typename-specifier ( expression-list [opt] )
+ //
+ // Parse the remainder of this case, then the (optional)
+ // postfix-expression suffix, followed by the (optional)
+ // right-hand side of the binary expression. We have an
+ // instance method.
+ ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
+ if (!Receiver.isInvalid())
+ Receiver = ParsePostfixExpressionSuffix(Receiver.take());
+ if (!Receiver.isInvalid())
+ Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma);
+ if (Receiver.isInvalid())
+ return true;
+
+ IsExpr = true;
+ TypeOrExpr = Receiver.take();
+ return false;
+ }
+
+ // We have a class message. Turn the simple-type-specifier or
+ // typename-specifier we parsed into a type and parse the
+ // remainder of the class message.
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
+ if (Type.isInvalid())
+ return true;
+
+ IsExpr = false;
+ TypeOrExpr = Type.get().getAsOpaquePtr();
+ return false;
+}
+
+/// \brief Determine whether the parser is currently referring to a an
+/// Objective-C message send, using a simplified heuristic to avoid overhead.
+///
+/// This routine will only return true for a subset of valid message-send
+/// expressions.
+bool Parser::isSimpleObjCMessageExpression() {
+ assert(Tok.is(tok::l_square) && getLang().ObjC1 &&
+ "Incorrect start for isSimpleObjCMessageExpression");
+ return GetLookAheadToken(1).is(tok::identifier) &&
+ GetLookAheadToken(2).is(tok::identifier);
+}
+
+bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
+ if (!getLang().ObjC1 || !NextToken().is(tok::identifier) ||
+ InMessageExpression)
+ return false;
+
+
+ ParsedType Type;
+
+ if (Tok.is(tok::annot_typename))
+ Type = getTypeAnnotation(Tok);
+ else if (Tok.is(tok::identifier))
+ Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
+ getCurScope());
+ else
+ return false;
+
+ if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
+ const Token &AfterNext = GetLookAheadToken(2);
+ if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) {
+ if (Tok.is(tok::identifier))
+ TryAnnotateTypeOrScopeToken();
+
+ return Tok.is(tok::annot_typename);
+ }
+ }
+
+ return false;
+}
+
+/// objc-message-expr:
+/// '[' objc-receiver objc-message-args ']'
+///
+/// objc-receiver: [C]
+/// 'super'
+/// expression
+/// class-name
+/// type-name
+///
+ExprResult Parser::ParseObjCMessageExpression() {
+ assert(Tok.is(tok::l_square) && "'[' expected");
+ SourceLocation LBracLoc = ConsumeBracket(); // consume '['
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCMessageReceiver(getCurScope());
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
+ if (getLang().CPlusPlus) {
+ // We completely separate the C and C++ cases because C++ requires
+ // more complicated (read: slower) parsing.
+
+ // Handle send to super.
+ // FIXME: This doesn't benefit from the same typo-correction we
+ // get in Objective-C.
+ if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
+ NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
+ return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
+ ParsedType(), 0);
+
+ // Parse the receiver, which is either a type or an expression.
+ bool IsExpr;
+ void *TypeOrExpr = NULL;
+ if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ if (IsExpr)
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ParsedType(),
+ static_cast<Expr*>(TypeOrExpr));
+
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ParsedType::getFromOpaquePtr(TypeOrExpr),
+ 0);
+ }
+
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation NameLoc = Tok.getLocation();
+ ParsedType ReceiverType;
+ switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
+ Name == Ident_super,
+ NextToken().is(tok::period),
+ ReceiverType)) {
+ case Sema::ObjCSuperMessage:
+ return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
+ ParsedType(), 0);
+
+ case Sema::ObjCClassMessage:
+ if (!ReceiverType) {
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ ConsumeToken(); // the type name
+
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ReceiverType, 0);
+
+ case Sema::ObjCInstanceMessage:
+ // Fall through to parse an expression.
+ break;
+ }
+ }
+
+ // Otherwise, an arbitrary expression can be the receiver of a send.
+ ExprResult Res(ParseExpression());
+ if (Res.isInvalid()) {
+ SkipUntil(tok::r_square);
+ return move(Res);
+ }
+
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ParsedType(), Res.take());
+}
+
+/// \brief Parse the remainder of an Objective-C message following the
+/// '[' objc-receiver.
+///
+/// This routine handles sends to super, class messages (sent to a
+/// class name), and instance messages (sent to an object), and the
+/// target is represented by \p SuperLoc, \p ReceiverType, or \p
+/// ReceiverExpr, respectively. Only one of these parameters may have
+/// a valid value.
+///
+/// \param LBracLoc The location of the opening '['.
+///
+/// \param SuperLoc If this is a send to 'super', the location of the
+/// 'super' keyword that indicates a send to the superclass.
+///
+/// \param ReceiverType If this is a class message, the type of the
+/// class we are sending a message to.
+///
+/// \param ReceiverExpr If this is an instance message, the expression
+/// used to compute the receiver object.
+///
+/// objc-message-args:
+/// objc-selector
+/// objc-keywordarg-list
+///
+/// objc-keywordarg-list:
+/// objc-keywordarg
+/// objc-keywordarg-list objc-keywordarg
+///
+/// objc-keywordarg:
+/// selector-name[opt] ':' objc-keywordexpr
+///
+/// objc-keywordexpr:
+/// nonempty-expr-list
+///
+/// nonempty-expr-list:
+/// assignment-expression
+/// nonempty-expr-list , assignment-expression
+///
+ExprResult
+Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ ParsedType ReceiverType,
+ ExprArg ReceiverExpr) {
+ InMessageExpressionRAIIObject InMessage(*this, true);
+
+ if (Tok.is(tok::code_completion)) {
+ if (SuperLoc.isValid())
+ Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, 0, 0,
+ false);
+ else if (ReceiverType)
+ Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, 0, 0,
+ false);
+ else
+ Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
+ 0, 0, false);
+ ConsumeCodeCompletionToken();
+ }
+
+ // Parse objc-selector
+ SourceLocation Loc;
+ IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
+
+ SourceLocation SelectorLoc = Loc;
+
+ llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+ ExprVector KeyExprs(Actions);
+
+ if (Tok.is(tok::colon)) {
+ while (1) {
+ // Each iteration parses a single keyword argument.
+ KeyIdents.push_back(selIdent);
+
+ if (Tok.isNot(tok::colon)) {
+ Diag(Tok, diag::err_expected_colon);
+ // We must manually skip to a ']', otherwise the expression skipper will
+ // stop at the ']' when it skips to the ';'. We want it to skip beyond
+ // the enclosing expression.
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ ConsumeToken(); // Eat the ':'.
+ /// Parse the expression after ':'
+
+ if (Tok.is(tok::code_completion)) {
+ if (SuperLoc.isValid())
+ Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/true);
+ else if (ReceiverType)
+ Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/true);
+ else
+ Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/true);
+
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ ExprResult Res(ParseAssignmentExpression());
+ if (Res.isInvalid()) {
+ // We must manually skip to a ']', otherwise the expression skipper will
+ // stop at the ']' when it skips to the ';'. We want it to skip beyond
+ // the enclosing expression.
+ SkipUntil(tok::r_square);
+ return move(Res);
+ }
+
+ // We have a valid expression.
+ KeyExprs.push_back(Res.release());
+
+ // Code completion after each argument.
+ if (Tok.is(tok::code_completion)) {
+ if (SuperLoc.isValid())
+ Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/false);
+ else if (ReceiverType)
+ Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/false);
+ else
+ Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
+ KeyIdents.data(),
+ KeyIdents.size(),
+ /*AtArgumentEpression=*/false);
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ // Check for another keyword selector.
+ selIdent = ParseObjCSelectorPiece(Loc);
+ if (!selIdent && Tok.isNot(tok::colon))
+ break;
+ // We have a selector or a colon, continue parsing.
+ }
+ // Parse the, optional, argument list, comma separated.
+ while (Tok.is(tok::comma)) {
+ ConsumeToken(); // Eat the ','.
+ /// Parse the expression after ','
+ ExprResult Res(ParseAssignmentExpression());
+ if (Res.isInvalid()) {
+ // We must manually skip to a ']', otherwise the expression skipper will
+ // stop at the ']' when it skips to the ';'. We want it to skip beyond
+ // the enclosing expression.
+ SkipUntil(tok::r_square);
+ return move(Res);
+ }
+
+ // We have a valid expression.
+ KeyExprs.push_back(Res.release());
+ }
+ } else if (!selIdent) {
+ Diag(Tok, diag::err_expected_ident); // missing selector name.
+
+ // We must manually skip to a ']', otherwise the expression skipper will
+ // stop at the ']' when it skips to the ';'. We want it to skip beyond
+ // the enclosing expression.
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ if (Tok.isNot(tok::r_square)) {
+ if (Tok.is(tok::identifier))
+ Diag(Tok, diag::err_expected_colon);
+ else
+ Diag(Tok, diag::err_expected_rsquare);
+ // We must manually skip to a ']', otherwise the expression skipper will
+ // stop at the ']' when it skips to the ';'. We want it to skip beyond
+ // the enclosing expression.
+ SkipUntil(tok::r_square);
+ return ExprError();
+ }
+
+ SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
+
+ unsigned nKeys = KeyIdents.size();
+ if (nKeys == 0)
+ KeyIdents.push_back(selIdent);
+ Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
+
+ if (SuperLoc.isValid())
+ return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
+ LBracLoc, SelectorLoc, RBracLoc,
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
+ else if (ReceiverType)
+ return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
+ LBracLoc, SelectorLoc, RBracLoc,
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
+ return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
+ LBracLoc, SelectorLoc, RBracLoc,
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
+}
+
+ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
+ ExprResult Res(ParseStringLiteralExpression());
+ if (Res.isInvalid()) return move(Res);
+
+ // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string
+ // expressions. At this point, we know that the only valid thing that starts
+ // with '@' is an @"".
+ llvm::SmallVector<SourceLocation, 4> AtLocs;
+ ExprVector AtStrings(Actions);
+ AtLocs.push_back(AtLoc);
+ AtStrings.push_back(Res.release());
+
+ while (Tok.is(tok::at)) {
+ AtLocs.push_back(ConsumeToken()); // eat the @.
+
+ // Invalid unless there is a string literal.
+ if (!isTokenStringLiteral())
+ return ExprError(Diag(Tok, diag::err_objc_concat_string));
+
+ ExprResult Lit(ParseStringLiteralExpression());
+ if (Lit.isInvalid())
+ return move(Lit);
+
+ AtStrings.push_back(Lit.release());
+ }
+
+ return Owned(Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
+ AtStrings.size()));
+}
+
+/// objc-encode-expression:
+/// @encode ( type-name )
+ExprResult
+Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
+ assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
+
+ SourceLocation EncLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_paren))
+ return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
+
+ SourceLocation LParenLoc = ConsumeParen();
+
+ TypeResult Ty = ParseTypeName();
+
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
+ Ty.get(), RParenLoc));
+}
+
+/// objc-protocol-expression
+/// @protocol ( protocol-name )
+ExprResult
+Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
+ SourceLocation ProtoLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_paren))
+ return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
+
+ SourceLocation LParenLoc = ConsumeParen();
+
+ if (Tok.isNot(tok::identifier))
+ return ExprError(Diag(Tok, diag::err_expected_ident));
+
+ IdentifierInfo *protocolId = Tok.getIdentifierInfo();
+ ConsumeToken();
+
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
+ LParenLoc, RParenLoc));
+}
+
+/// objc-selector-expression
+/// @selector '(' objc-keyword-selector ')'
+ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
+ SourceLocation SelectorLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_paren))
+ return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
+
+ llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
+ SourceLocation LParenLoc = ConsumeParen();
+ SourceLocation sLoc;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(),
+ KeyIdents.size());
+ ConsumeCodeCompletionToken();
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return ExprError();
+ }
+
+ IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
+ if (!SelIdent && // missing selector name.
+ Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
+ return ExprError(Diag(Tok, diag::err_expected_ident));
+
+ KeyIdents.push_back(SelIdent);
+ unsigned nColons = 0;
+ if (Tok.isNot(tok::r_paren)) {
+ while (1) {
+ if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
+ ++nColons;
+ KeyIdents.push_back(0);
+ } else if (Tok.isNot(tok::colon))
+ return ExprError(Diag(Tok, diag::err_expected_colon));
+
+ ++nColons;
+ ConsumeToken(); // Eat the ':'.
+ if (Tok.is(tok::r_paren))
+ break;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(),
+ KeyIdents.size());
+ ConsumeCodeCompletionToken();
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return ExprError();
+ }
+
+ // Check for another keyword selector.
+ SourceLocation Loc;
+ SelIdent = ParseObjCSelectorPiece(Loc);
+ KeyIdents.push_back(SelIdent);
+ if (!SelIdent && Tok.isNot(tok::colon))
+ break;
+ }
+ }
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
+ return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
+ LParenLoc, RParenLoc));
+ }
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
new file mode 100644
index 0000000..dfd0da0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -0,0 +1,434 @@
+//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the language specific #pragma handlers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ParsePragma.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+/// \brief Handle the annotation token produced for #pragma unused(...)
+///
+/// Each annot_pragma_unused is followed by the argument token so e.g.
+/// "#pragma unused(x,y)" becomes:
+/// annot_pragma_unused 'x' annot_pragma_unused 'y'
+void Parser::HandlePragmaUnused() {
+ assert(Tok.is(tok::annot_pragma_unused));
+ SourceLocation UnusedLoc = ConsumeToken();
+ Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
+ ConsumeToken(); // The argument token.
+}
+
+// #pragma GCC visibility comes in two variants:
+// 'push' '(' [visibility] ')'
+// 'pop'
+void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &VisTok) {
+ SourceLocation VisLoc = VisTok.getLocation();
+
+ Token Tok;
+ PP.Lex(Tok);
+
+ const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
+
+ bool IsPush;
+ const IdentifierInfo *VisType;
+ if (PushPop && PushPop->isStr("pop")) {
+ IsPush = false;
+ VisType = 0;
+ } else if (PushPop && PushPop->isStr("push")) {
+ IsPush = true;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ VisType = Tok.getIdentifierInfo();
+ if (!VisType) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
+ << "visibility";
+ return;
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "visibility";
+ return;
+ }
+
+ Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
+}
+
+// #pragma pack(...) comes in the following delicious flavors:
+// pack '(' [integer] ')'
+// pack '(' 'show' ')'
+// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
+void PragmaPackHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &PackTok) {
+ SourceLocation PackLoc = PackTok.getLocation();
+
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
+ return;
+ }
+
+ Sema::PragmaPackKind Kind = Sema::PPK_Default;
+ IdentifierInfo *Name = 0;
+ ExprResult Alignment;
+ SourceLocation LParenLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.is(tok::numeric_constant)) {
+ Alignment = Actions.ActOnNumericConstant(Tok);
+ if (Alignment.isInvalid())
+ return;
+
+ PP.Lex(Tok);
+ } else if (Tok.is(tok::identifier)) {
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("show")) {
+ Kind = Sema::PPK_Show;
+ PP.Lex(Tok);
+ } else {
+ if (II->isStr("push")) {
+ Kind = Sema::PPK_Push;
+ } else if (II->isStr("pop")) {
+ Kind = Sema::PPK_Pop;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+
+ if (Tok.is(tok::numeric_constant)) {
+ Alignment = Actions.ActOnNumericConstant(Tok);
+ if (Alignment.isInvalid())
+ return;
+
+ PP.Lex(Tok);
+ } else if (Tok.is(tok::identifier)) {
+ Name = Tok.getIdentifierInfo();
+ PP.Lex(Tok);
+
+ if (Tok.is(tok::comma)) {
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::numeric_constant)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
+ return;
+ }
+
+ Alignment = Actions.ActOnNumericConstant(Tok);
+ if (Alignment.isInvalid())
+ return;
+
+ PP.Lex(Tok);
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
+ return;
+ }
+ }
+ }
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
+ return;
+ }
+
+ SourceLocation RParenLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
+ return;
+ }
+
+ Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
+ LParenLoc, RParenLoc);
+}
+
+// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
+// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
+static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
+ bool IsOptions) {
+ Token Tok;
+
+ if (IsOptions) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier) ||
+ !Tok.getIdentifierInfo()->isStr("align")) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
+ return;
+ }
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::equal)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
+ << IsOptions;
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << (IsOptions ? "options" : "align");
+ return;
+ }
+
+ Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (II->isStr("native"))
+ Kind = Sema::POAK_Native;
+ else if (II->isStr("natural"))
+ Kind = Sema::POAK_Natural;
+ else if (II->isStr("packed"))
+ Kind = Sema::POAK_Packed;
+ else if (II->isStr("power"))
+ Kind = Sema::POAK_Power;
+ else if (II->isStr("mac68k"))
+ Kind = Sema::POAK_Mac68k;
+ else if (II->isStr("reset"))
+ Kind = Sema::POAK_Reset;
+ else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
+ << IsOptions;
+ return;
+ }
+
+ SourceLocation KindLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << (IsOptions ? "options" : "align");
+ return;
+ }
+
+ Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
+}
+
+void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &AlignTok) {
+ ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
+}
+
+void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &OptionsTok) {
+ ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
+}
+
+// #pragma unused(identifier)
+void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &UnusedTok) {
+ // FIXME: Should we be expanding macros here? My guess is no.
+ SourceLocation UnusedLoc = UnusedTok.getLocation();
+
+ // Lex the left '('.
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
+ return;
+ }
+ SourceLocation LParenLoc = Tok.getLocation();
+
+ // Lex the declaration reference(s).
+ llvm::SmallVector<Token, 5> Identifiers;
+ SourceLocation RParenLoc;
+ bool LexID = true;
+
+ while (true) {
+ PP.Lex(Tok);
+
+ if (LexID) {
+ if (Tok.is(tok::identifier)) {
+ Identifiers.push_back(Tok);
+ LexID = false;
+ continue;
+ }
+
+ // Illegal token!
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
+ return;
+ }
+
+ // We are execting a ')' or a ','.
+ if (Tok.is(tok::comma)) {
+ LexID = true;
+ continue;
+ }
+
+ if (Tok.is(tok::r_paren)) {
+ RParenLoc = Tok.getLocation();
+ break;
+ }
+
+ // Illegal token!
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
+ "unused";
+ return;
+ }
+
+ // Verify that we have a location for the right parenthesis.
+ assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
+ assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
+
+ // For each identifier token, insert into the token stream a
+ // annot_pragma_unused token followed by the identifier token.
+ // This allows us to cache a "#pragma unused" that occurs inside an inline
+ // C++ member function.
+
+ Token *Toks = new Token[2*Identifiers.size()];
+ for (unsigned i=0; i != Identifiers.size(); i++) {
+ Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
+ pragmaUnusedTok.startToken();
+ pragmaUnusedTok.setKind(tok::annot_pragma_unused);
+ pragmaUnusedTok.setLocation(UnusedLoc);
+ idTok = Identifiers[i];
+ }
+ PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
+}
+
+// #pragma weak identifier
+// #pragma weak identifier '=' identifier
+void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &WeakTok) {
+ // FIXME: Should we be expanding macros here? My guess is no.
+ SourceLocation WeakLoc = WeakTok.getLocation();
+
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
+ return;
+ }
+
+ IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
+ SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
+
+ PP.Lex(Tok);
+ if (Tok.is(tok::equal)) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "weak";
+ return;
+ }
+ AliasName = Tok.getIdentifierInfo();
+ AliasNameLoc = Tok.getLocation();
+ PP.Lex(Tok);
+ }
+
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
+ return;
+ }
+
+ if (AliasName) {
+ Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
+ AliasNameLoc);
+ } else {
+ Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
+ }
+}
+
+void
+PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ tok::OnOffSwitch OOS;
+ if (PP.LexOnOffSwitch(OOS))
+ return;
+
+ Actions.ActOnPragmaFPContract(OOS);
+}
+
+void
+PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
+ "OPENCL";
+ return;
+ }
+ IdentifierInfo *ename = Tok.getIdentifierInfo();
+ SourceLocation NameLoc = Tok.getLocation();
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::colon)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
+ return;
+ }
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+ return;
+ }
+ IdentifierInfo *op = Tok.getIdentifierInfo();
+
+ unsigned state;
+ if (op->isStr("enable")) {
+ state = 1;
+ } else if (op->isStr("disable")) {
+ state = 0;
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+ return;
+ }
+
+ OpenCLOptions &f = Actions.getOpenCLOptions();
+ if (ename->isStr("all")) {
+#define OPENCLEXT(nm) f.nm = state;
+#include "clang/Basic/OpenCLExtensions.def"
+ }
+#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
+#include "clang/Basic/OpenCLExtensions.def"
+ else {
+ PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
+ return;
+ }
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h
new file mode 100644
index 0000000..bee6af3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h
@@ -0,0 +1,107 @@
+//===---- ParserPragmas.h - Language specific pragmas -----------*- 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 #pragma handlers for language specific pragmas.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H
+#define LLVM_CLANG_PARSE_PARSEPRAGMA_H
+
+#include "clang/Lex/Pragma.h"
+
+namespace clang {
+ class Sema;
+ class Parser;
+
+class PragmaAlignHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaAlignHandler(Sema &A) : PragmaHandler("align"), Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaGCCVisibilityHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaGCCVisibilityHandler(Sema &A) : PragmaHandler("visibility"),
+ Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaOptionsHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaOptionsHandler(Sema &A) : PragmaHandler("options"),
+ Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaPackHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaPackHandler(Sema &A) : PragmaHandler("pack"),
+ Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaUnusedHandler : public PragmaHandler {
+ Sema &Actions;
+ Parser &parser;
+public:
+ PragmaUnusedHandler(Sema &A, Parser& p)
+ : PragmaHandler("unused"), Actions(A), parser(p) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaWeakHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaWeakHandler(Sema &A)
+ : PragmaHandler("weak"), Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+class PragmaOpenCLExtensionHandler : public PragmaHandler {
+ Sema &Actions;
+ Parser &parser;
+public:
+ PragmaOpenCLExtensionHandler(Sema &S, Parser& p) :
+ PragmaHandler("EXTENSION"), Actions(S), parser(p) {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+
+class PragmaFPContractHandler : public PragmaHandler {
+ Sema &Actions;
+ Parser &parser;
+public:
+ PragmaFPContractHandler(Sema &S, Parser& p) :
+ PragmaHandler("FP_CONTRACT"), Actions(S), parser(p) {}
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken);
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
new file mode 100644
index 0000000..2d97583
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -0,0 +1,1704 @@
+//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Statement and Block portions of the Parser
+// interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// C99 6.8: Statements and Blocks.
+//===----------------------------------------------------------------------===//
+
+/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
+/// StatementOrDeclaration:
+/// statement
+/// declaration
+///
+/// statement:
+/// labeled-statement
+/// compound-statement
+/// expression-statement
+/// selection-statement
+/// iteration-statement
+/// jump-statement
+/// [C++] declaration-statement
+/// [C++] try-block
+/// [OBC] objc-throw-statement
+/// [OBC] objc-try-catch-statement
+/// [OBC] objc-synchronized-statement
+/// [GNU] asm-statement
+/// [OMP] openmp-construct [TODO]
+///
+/// labeled-statement:
+/// identifier ':' statement
+/// 'case' constant-expression ':' statement
+/// 'default' ':' statement
+///
+/// selection-statement:
+/// if-statement
+/// switch-statement
+///
+/// iteration-statement:
+/// while-statement
+/// do-statement
+/// for-statement
+///
+/// expression-statement:
+/// expression[opt] ';'
+///
+/// jump-statement:
+/// 'goto' identifier ';'
+/// 'continue' ';'
+/// 'break' ';'
+/// 'return' expression[opt] ';'
+/// [GNU] 'goto' '*' expression ';'
+///
+/// [OBC] objc-throw-statement:
+/// [OBC] '@' 'throw' expression ';'
+/// [OBC] '@' 'throw' ';'
+///
+StmtResult
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
+ const char *SemiError = 0;
+ StmtResult Res;
+
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ // Cases in this switch statement should fall through if the parser expects
+ // the token to end in a semicolon (in which case SemiError should be set),
+ // or they directly 'return;' if not.
+ tok::TokenKind Kind = Tok.getKind();
+ SourceLocation AtLoc;
+ switch (Kind) {
+ case tok::at: // May be a @try or @throw statement
+ {
+ AtLoc = ConsumeToken(); // consume @
+ return ParseObjCAtStatement(AtLoc);
+ }
+
+ case tok::code_completion:
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
+ ConsumeCodeCompletionToken();
+ return ParseStatementOrDeclaration(Stmts, OnlyStatement);
+
+ case tok::identifier:
+ if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
+ // identifier ':' statement
+ return ParseLabeledStatement(attrs);
+ }
+ // PASS THROUGH.
+
+ default: {
+ if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
+ SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+ DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,
+ DeclEnd, attrs);
+ return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
+ }
+
+ if (Tok.is(tok::r_brace)) {
+ Diag(Tok, diag::err_expected_statement);
+ return StmtError();
+ }
+
+ // FIXME: Use the attributes
+ // expression[opt] ';'
+ ExprResult Expr(ParseExpression());
+ if (Expr.isInvalid()) {
+ // If the expression is invalid, skip ahead to the next semicolon or '}'.
+ // Not doing this opens us up to the possibility of infinite loops if
+ // ParseExpression does not consume any tokens.
+ SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return StmtError();
+ }
+ // Otherwise, eat the semicolon.
+ ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+ return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));
+ }
+
+ case tok::kw_case: // C99 6.8.1: labeled-statement
+ return ParseCaseStatement(attrs);
+ case tok::kw_default: // C99 6.8.1: labeled-statement
+ return ParseDefaultStatement(attrs);
+
+ case tok::l_brace: // C99 6.8.2: compound-statement
+ return ParseCompoundStatement(attrs);
+ case tok::semi: { // C99 6.8.3p3: expression[opt] ';'
+ bool LeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
+ return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacro);
+ }
+
+ case tok::kw_if: // C99 6.8.4.1: if-statement
+ return ParseIfStatement(attrs);
+ case tok::kw_switch: // C99 6.8.4.2: switch-statement
+ return ParseSwitchStatement(attrs);
+
+ case tok::kw_while: // C99 6.8.5.1: while-statement
+ return ParseWhileStatement(attrs);
+ case tok::kw_do: // C99 6.8.5.2: do-statement
+ Res = ParseDoStatement(attrs);
+ SemiError = "do/while";
+ break;
+ case tok::kw_for: // C99 6.8.5.3: for-statement
+ return ParseForStatement(attrs);
+
+ case tok::kw_goto: // C99 6.8.6.1: goto-statement
+ Res = ParseGotoStatement(attrs);
+ SemiError = "goto";
+ break;
+ case tok::kw_continue: // C99 6.8.6.2: continue-statement
+ Res = ParseContinueStatement(attrs);
+ SemiError = "continue";
+ break;
+ case tok::kw_break: // C99 6.8.6.3: break-statement
+ Res = ParseBreakStatement(attrs);
+ SemiError = "break";
+ break;
+ case tok::kw_return: // C99 6.8.6.4: return-statement
+ Res = ParseReturnStatement(attrs);
+ SemiError = "return";
+ break;
+
+ case tok::kw_asm: {
+ ProhibitAttributes(attrs);
+ bool msAsm = false;
+ Res = ParseAsmStatement(msAsm);
+ Res = Actions.ActOnFinishFullStmt(Res.get());
+ if (msAsm) return move(Res);
+ SemiError = "asm";
+ break;
+ }
+
+ case tok::kw_try: // C++ 15: try-block
+ return ParseCXXTryBlock(attrs);
+ }
+
+ // If we reached this code, the statement must end in a semicolon.
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ } else if (!Res.isInvalid()) {
+ // If the result was valid, then we do want to diagnose this. Use
+ // ExpectAndConsume to emit the diagnostic, even though we know it won't
+ // succeed.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
+ // Skip until we see a } or ;, but don't eat it.
+ SkipUntil(tok::r_brace, true, true);
+ }
+
+ return move(Res);
+}
+
+/// ParseLabeledStatement - We have an identifier and a ':' after it.
+///
+/// labeled-statement:
+/// identifier ':' statement
+/// [GNU] identifier ':' attributes[opt] statement
+///
+StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
+ assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
+ "Not an identifier!");
+
+ Token IdentTok = Tok; // Save the whole token.
+ ConsumeToken(); // eat the identifier.
+
+ assert(Tok.is(tok::colon) && "Not a label!");
+
+ // identifier ':' statement
+ SourceLocation ColonLoc = ConsumeToken();
+
+ // Read label attributes, if present.
+ MaybeParseGNUAttributes(attrs);
+
+ StmtResult SubStmt(ParseStatement());
+
+ // Broken substmt shouldn't prevent the label from being added to the AST.
+ if (SubStmt.isInvalid())
+ SubStmt = Actions.ActOnNullStmt(ColonLoc);
+
+ LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
+ IdentTok.getLocation());
+ if (AttributeList *Attrs = attrs.getList())
+ Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
+
+ return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
+ SubStmt.get());
+}
+
+/// ParseCaseStatement
+/// labeled-statement:
+/// 'case' constant-expression ':' statement
+/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
+///
+StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs) {
+ assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+ // FIXME: Use attributes?
+
+ // It is very very common for code to contain many case statements recursively
+ // nested, as in (but usually without indentation):
+ // case 1:
+ // case 2:
+ // case 3:
+ // case 4:
+ // case 5: etc.
+ //
+ // Parsing this naively works, but is both inefficient and can cause us to run
+ // out of stack space in our recursive descent parser. As a special case,
+ // flatten this recursion into an iterative loop. This is complex and gross,
+ // but all the grossness is constrained to ParseCaseStatement (and some
+ // wierdness in the actions), so this is just local grossness :).
+
+ // TopLevelCase - This is the highest level we have parsed. 'case 1' in the
+ // example above.
+ StmtResult TopLevelCase(true);
+
+ // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
+ // gets updated each time a new case is parsed, and whose body is unset so
+ // far. When parsing 'case 4', this is the 'case 3' node.
+ StmtTy *DeepestParsedCaseStmt = 0;
+
+ // While we have case statements, eat and stack them.
+ do {
+ SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteCase(getCurScope());
+ ConsumeCodeCompletionToken();
+ }
+
+ /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
+ /// Disable this form of error recovery while we're parsing the case
+ /// expression.
+ ColonProtectionRAIIObject ColonProtection(*this);
+
+ ExprResult LHS(ParseConstantExpression());
+ if (LHS.isInvalid()) {
+ SkipUntil(tok::colon);
+ return StmtError();
+ }
+
+ // GNU case range extension.
+ SourceLocation DotDotDotLoc;
+ ExprResult RHS;
+ if (Tok.is(tok::ellipsis)) {
+ Diag(Tok, diag::ext_gnu_case_range);
+ DotDotDotLoc = ConsumeToken();
+
+ RHS = ParseConstantExpression();
+ if (RHS.isInvalid()) {
+ SkipUntil(tok::colon);
+ return StmtError();
+ }
+ }
+
+ ColonProtection.restore();
+
+ SourceLocation ColonLoc;
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+
+ // Treat "case blah;" as a typo for "case blah:".
+ } else if (Tok.is(tok::semi)) {
+ ColonLoc = ConsumeToken();
+ Diag(ColonLoc, diag::err_expected_colon_after) << "'case'"
+ << FixItHint::CreateReplacement(ColonLoc, ":");
+ } else {
+ SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
+ Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'"
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ ColonLoc = ExpectedLoc;
+ }
+
+ StmtResult Case =
+ Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc,
+ RHS.get(), ColonLoc);
+
+ // If we had a sema error parsing this case, then just ignore it and
+ // continue parsing the sub-stmt.
+ if (Case.isInvalid()) {
+ if (TopLevelCase.isInvalid()) // No parsed case stmts.
+ return ParseStatement();
+ // Otherwise, just don't add it as a nested case.
+ } else {
+ // If this is the first case statement we parsed, it becomes TopLevelCase.
+ // Otherwise we link it into the current chain.
+ Stmt *NextDeepest = Case.get();
+ if (TopLevelCase.isInvalid())
+ TopLevelCase = move(Case);
+ else
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
+ DeepestParsedCaseStmt = NextDeepest;
+ }
+
+ // Handle all case statements.
+ } while (Tok.is(tok::kw_case));
+
+ assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
+
+ // If we found a non-case statement, start by parsing it.
+ StmtResult SubStmt;
+
+ if (Tok.isNot(tok::r_brace)) {
+ SubStmt = ParseStatement();
+ } else {
+ // Nicely diagnose the common error "switch (X) { case 4: }", which is
+ // not valid.
+ // FIXME: add insertion hint.
+ Diag(Tok, diag::err_label_end_of_compound_statement);
+ SubStmt = true;
+ }
+
+ // Broken sub-stmt shouldn't prevent forming the case statement properly.
+ if (SubStmt.isInvalid())
+ SubStmt = Actions.ActOnNullStmt(SourceLocation());
+
+ // Install the body into the most deeply-nested case.
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
+
+ // Return the top level parsed statement tree.
+ return move(TopLevelCase);
+}
+
+/// ParseDefaultStatement
+/// labeled-statement:
+/// 'default' ':' statement
+/// Note that this does not parse the 'statement' at the end.
+///
+StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
+ //FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_default) && "Not a default stmt!");
+ SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
+
+ SourceLocation ColonLoc;
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+
+ // Treat "default;" as a typo for "default:".
+ } else if (Tok.is(tok::semi)) {
+ ColonLoc = ConsumeToken();
+ Diag(ColonLoc, diag::err_expected_colon_after) << "'default'"
+ << FixItHint::CreateReplacement(ColonLoc, ":");
+ } else {
+ SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
+ Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'"
+ << FixItHint::CreateInsertion(ExpectedLoc, ":");
+ ColonLoc = ExpectedLoc;
+ }
+
+ // Diagnose the common error "switch (X) {... default: }", which is not valid.
+ if (Tok.is(tok::r_brace)) {
+ Diag(Tok, diag::err_label_end_of_compound_statement);
+ return StmtError();
+ }
+
+ StmtResult SubStmt(ParseStatement());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
+ SubStmt.get(), getCurScope());
+}
+
+
+/// ParseCompoundStatement - Parse a "{}" block.
+///
+/// compound-statement: [C99 6.8.2]
+/// { block-item-list[opt] }
+/// [GNU] { label-declarations block-item-list } [TODO]
+///
+/// block-item-list:
+/// block-item
+/// block-item-list block-item
+///
+/// block-item:
+/// declaration
+/// [GNU] '__extension__' declaration
+/// statement
+/// [OMP] openmp-directive [TODO]
+///
+/// [GNU] label-declarations:
+/// [GNU] label-declaration
+/// [GNU] label-declarations label-declaration
+///
+/// [GNU] label-declaration:
+/// [GNU] '__label__' identifier-list ';'
+///
+/// [OMP] openmp-directive: [TODO]
+/// [OMP] barrier-directive
+/// [OMP] flush-directive
+///
+StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs,
+ bool isStmtExpr) {
+ //FIXME: Use attributes?
+
+ assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
+
+ // Enter a scope to hold everything within the compound stmt. Compound
+ // statements can always hold declarations.
+ ParseScope CompoundScope(this, Scope::DeclScope);
+
+ // Parse the statements in the body.
+ return ParseCompoundStatementBody(isStmtExpr);
+}
+
+
+/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
+/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
+/// consume the '}' at the end of the block. It does not manipulate the scope
+/// stack.
+StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
+ PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
+ Tok.getLocation(),
+ "in compound statement ('{}')");
+ InMessageExpressionRAIIObject InMessage(*this, false);
+
+ SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
+
+ StmtVector Stmts(Actions);
+
+ // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
+ // only allowed at the start of a compound stmt regardless of the language.
+ while (Tok.is(tok::kw___label__)) {
+ SourceLocation LabelLoc = ConsumeToken();
+ Diag(LabelLoc, diag::ext_gnu_local_label);
+
+ llvm::SmallVector<Decl *, 8> DeclsInGroup;
+ while (1) {
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ break;
+ }
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+ DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, true));
+
+ if (!Tok.is(tok::comma))
+ break;
+ ConsumeToken();
+ }
+
+ DeclSpec DS;
+ DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS,
+ DeclsInGroup.data(), DeclsInGroup.size());
+ StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
+
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+ if (R.isUsable())
+ Stmts.push_back(R.release());
+ }
+
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ if (Tok.is(tok::annot_pragma_unused)) {
+ HandlePragmaUnused();
+ continue;
+ }
+
+ StmtResult R;
+ if (Tok.isNot(tok::kw___extension__)) {
+ R = ParseStatementOrDeclaration(Stmts, false);
+ } else {
+ // __extension__ can start declarations and it can also be a unary
+ // operator for expressions. Consume multiple __extension__ markers here
+ // until we can determine which is which.
+ // FIXME: This loses extension expressions in the AST!
+ SourceLocation ExtLoc = ConsumeToken();
+ while (Tok.is(tok::kw___extension__))
+ ConsumeToken();
+
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ // If this is the start of a declaration, parse it as such.
+ if (isDeclarationStatement()) {
+ // __extension__ silences extension warnings in the subdeclaration.
+ // FIXME: Save the __extension__ on the decl as a node somehow?
+ ExtensionRAIIObject O(Diags);
+
+ SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+ DeclGroupPtrTy Res = ParseDeclaration(Stmts,
+ Declarator::BlockContext, DeclEnd,
+ attrs);
+ R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
+ } else {
+ // Otherwise this was a unary __extension__ marker.
+ ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
+
+ if (Res.isInvalid()) {
+ SkipUntil(tok::semi);
+ continue;
+ }
+
+ // FIXME: Use attributes?
+ // Eat the semicolon at the end of stmt and convert the expr into a
+ // statement.
+ ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+ R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.get()));
+ }
+ }
+
+ if (R.isUsable())
+ Stmts.push_back(R.release());
+ }
+
+ // We broke out of the while loop because we found a '}' or EOF.
+ if (Tok.isNot(tok::r_brace)) {
+ Diag(Tok, diag::err_expected_rbrace);
+ Diag(LBraceLoc, diag::note_matching) << "{";
+ return StmtError();
+ }
+
+ SourceLocation RBraceLoc = ConsumeBrace();
+ return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
+ isStmtExpr);
+}
+
+/// ParseParenExprOrCondition:
+/// [C ] '(' expression ')'
+/// [C++] '(' condition ')' [not allowed if OnlyAllowCondition=true]
+///
+/// This function parses and performs error recovery on the specified condition
+/// or expression (depending on whether we're in C++ or C mode). This function
+/// goes out of its way to recover well. It returns true if there was a parser
+/// error (the right paren couldn't be found), which indicates that the caller
+/// should try to recover harder. It returns false if the condition is
+/// successfully parsed. Note that a successful parse can still have semantic
+/// errors in the condition.
+bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
+ SourceLocation Loc,
+ bool ConvertToBoolean) {
+ SourceLocation LParenLoc = ConsumeParen();
+ if (getLang().CPlusPlus)
+ ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
+ else {
+ ExprResult = ParseExpression();
+ DeclResult = 0;
+
+ // If required, convert to a boolean value.
+ if (!ExprResult.isInvalid() && ConvertToBoolean)
+ ExprResult
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get());
+ }
+
+ // If the parser was confused by the condition and we don't have a ')', try to
+ // recover by skipping ahead to a semi and bailing out. If condexp is
+ // semantically invalid but we have well formed code, keep going.
+ if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) {
+ SkipUntil(tok::semi);
+ // Skipping may have stopped if it found the containing ')'. If so, we can
+ // continue parsing the if statement.
+ if (Tok.isNot(tok::r_paren))
+ return true;
+ }
+
+ // Otherwise the condition is valid or the rparen is present.
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return false;
+}
+
+
+/// ParseIfStatement
+/// if-statement: [C99 6.8.4.1]
+/// 'if' '(' expression ')' statement
+/// 'if' '(' expression ')' statement 'else' statement
+/// [C++] 'if' '(' condition ')' statement
+/// [C++] 'if' '(' condition ')' statement 'else' statement
+///
+StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_if) && "Not an if stmt!");
+ SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "if";
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+
+ bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+ // C99 6.8.4p3 - In C99, the if statement is a block. This is not
+ // the case for C90.
+ //
+ // C++ 6.4p3:
+ // A name introduced by a declaration in a condition is in scope from its
+ // point of declaration until the end of the substatements controlled by the
+ // condition.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement).
+ //
+ ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
+
+ // Parse the condition.
+ ExprResult CondExp;
+ Decl *CondVar = 0;
+ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
+ return StmtError();
+
+ FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get()));
+
+ // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do this
+ // if the body isn't a compound statement to avoid push/pop in common cases.
+ //
+ // C++ 6.4p1:
+ // The substatement in a selection-statement (each substatement, in the else
+ // form of the if statement) implicitly defines a local scope.
+ //
+ // For C++ we create a scope for the condition and a new scope for
+ // substatements because:
+ // -When the 'then' scope exits, we want the condition declaration to still be
+ // active for the 'else' scope too.
+ // -Sema will detect name clashes by considering declarations of a
+ // 'ControlScope' as part of its direct subscope.
+ // -If we wanted the condition and substatement to be in the same scope, we
+ // would have to notify ParseStatement not to create a new scope. It's
+ // simpler to let it create a new scope.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ C99orCXX && Tok.isNot(tok::l_brace));
+
+ // Read the 'then' stmt.
+ SourceLocation ThenStmtLoc = Tok.getLocation();
+ StmtResult ThenStmt(ParseStatement());
+
+ // Pop the 'if' scope if needed.
+ InnerScope.Exit();
+
+ // If it has an else, parse it.
+ SourceLocation ElseLoc;
+ SourceLocation ElseStmtLoc;
+ StmtResult ElseStmt;
+
+ if (Tok.is(tok::kw_else)) {
+ ElseLoc = ConsumeToken();
+ ElseStmtLoc = Tok.getLocation();
+
+ // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do
+ // this if the body isn't a compound statement to avoid push/pop in common
+ // cases.
+ //
+ // C++ 6.4p1:
+ // The substatement in a selection-statement (each substatement, in the else
+ // form of the if statement) implicitly defines a local scope.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ C99orCXX && Tok.isNot(tok::l_brace));
+
+ ElseStmt = ParseStatement();
+
+ // Pop the 'else' scope if needed.
+ InnerScope.Exit();
+ }
+
+ IfScope.Exit();
+
+ // If the condition was invalid, discard the if statement. We could recover
+ // better by replacing it with a valid expr, but don't do that yet.
+ if (CondExp.isInvalid() && !CondVar)
+ return StmtError();
+
+ // If the then or else stmt is invalid and the other is valid (and present),
+ // make turn the invalid one into a null stmt to avoid dropping the other
+ // part. If both are invalid, return error.
+ if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
+ (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
+ (ThenStmt.get() == 0 && ElseStmt.isInvalid())) {
+ // Both invalid, or one is invalid and other is non-present: return error.
+ return StmtError();
+ }
+
+ // Now if either are invalid, replace with a ';'.
+ if (ThenStmt.isInvalid())
+ ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
+ if (ElseStmt.isInvalid())
+ ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
+
+ return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),
+ ElseLoc, ElseStmt.get());
+}
+
+/// ParseSwitchStatement
+/// switch-statement:
+/// 'switch' '(' expression ')' statement
+/// [C++] 'switch' '(' condition ')' statement
+StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
+ SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "switch";
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+
+ bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+ // C99 6.8.4p3 - In C99, the switch statement is a block. This is
+ // not the case for C90. Start the switch scope.
+ //
+ // C++ 6.4p3:
+ // A name introduced by a declaration in a condition is in scope from its
+ // point of declaration until the end of the substatements controlled by the
+ // condition.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement).
+ //
+ unsigned ScopeFlags = Scope::BreakScope;
+ if (C99orCXX)
+ ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
+ ParseScope SwitchScope(this, ScopeFlags);
+
+ // Parse the condition.
+ ExprResult Cond;
+ Decl *CondVar = 0;
+ if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
+ return StmtError();
+
+ StmtResult Switch
+ = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar);
+
+ if (Switch.isInvalid()) {
+ // Skip the switch body.
+ // FIXME: This is not optimal recovery, but parsing the body is more
+ // dangerous due to the presence of case and default statements, which
+ // will have no place to connect back with the switch.
+ if (Tok.is(tok::l_brace)) {
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, false, false);
+ } else
+ SkipUntil(tok::semi);
+ return move(Switch);
+ }
+
+ // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do this
+ // if the body isn't a compound statement to avoid push/pop in common cases.
+ //
+ // C++ 6.4p1:
+ // The substatement in a selection-statement (each substatement, in the else
+ // form of the if statement) implicitly defines a local scope.
+ //
+ // See comments in ParseIfStatement for why we create a scope for the
+ // condition and a new scope for substatement in C++.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ C99orCXX && Tok.isNot(tok::l_brace));
+
+ // Read the body statement.
+ StmtResult Body(ParseStatement());
+
+ // Pop the scopes.
+ InnerScope.Exit();
+ SwitchScope.Exit();
+
+ if (Body.isInvalid())
+ // FIXME: Remove the case statement list from the Switch statement.
+ Body = Actions.ActOnNullStmt(Tok.getLocation());
+
+ return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
+}
+
+/// ParseWhileStatement
+/// while-statement: [C99 6.8.5.1]
+/// 'while' '(' expression ')' statement
+/// [C++] 'while' '(' condition ')' statement
+StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_while) && "Not a while stmt!");
+ SourceLocation WhileLoc = Tok.getLocation();
+ ConsumeToken(); // eat the 'while'.
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "while";
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+
+ bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
+
+ // C99 6.8.5p5 - In C99, the while statement is a block. This is not
+ // the case for C90. Start the loop scope.
+ //
+ // C++ 6.4p3:
+ // A name introduced by a declaration in a condition is in scope from its
+ // point of declaration until the end of the substatements controlled by the
+ // condition.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement).
+ //
+ unsigned ScopeFlags;
+ if (C99orCXX)
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
+ Scope::DeclScope | Scope::ControlScope;
+ else
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+ ParseScope WhileScope(this, ScopeFlags);
+
+ // Parse the condition.
+ ExprResult Cond;
+ Decl *CondVar = 0;
+ if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
+ return StmtError();
+
+ FullExprArg FullCond(Actions.MakeFullExpr(Cond.get()));
+
+ // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do this
+ // if the body isn't a compound statement to avoid push/pop in common cases.
+ //
+ // C++ 6.5p2:
+ // The substatement in an iteration-statement implicitly defines a local scope
+ // which is entered and exited each time through the loop.
+ //
+ // See comments in ParseIfStatement for why we create a scope for the
+ // condition and a new scope for substatement in C++.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ C99orCXX && Tok.isNot(tok::l_brace));
+
+ // Read the body statement.
+ StmtResult Body(ParseStatement());
+
+ // Pop the body scope if needed.
+ InnerScope.Exit();
+ WhileScope.Exit();
+
+ if ((Cond.isInvalid() && !CondVar) || Body.isInvalid())
+ return StmtError();
+
+ return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get());
+}
+
+/// ParseDoStatement
+/// do-statement: [C99 6.8.5.2]
+/// 'do' statement 'while' '(' expression ')' ';'
+/// Note: this lets the caller parse the end ';'.
+StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_do) && "Not a do stmt!");
+ SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
+
+ // C99 6.8.5p5 - In C99, the do statement is a block. This is not
+ // the case for C90. Start the loop scope.
+ unsigned ScopeFlags;
+ if (getLang().C99)
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
+ else
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+
+ ParseScope DoScope(this, ScopeFlags);
+
+ // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do this
+ // if the body isn't a compound statement to avoid push/pop in common cases.
+ //
+ // C++ 6.5p2:
+ // The substatement in an iteration-statement implicitly defines a local scope
+ // which is entered and exited each time through the loop.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ (getLang().C99 || getLang().CPlusPlus) &&
+ Tok.isNot(tok::l_brace));
+
+ // Read the body statement.
+ StmtResult Body(ParseStatement());
+
+ // Pop the body scope if needed.
+ InnerScope.Exit();
+
+ if (Tok.isNot(tok::kw_while)) {
+ if (!Body.isInvalid()) {
+ Diag(Tok, diag::err_expected_while);
+ Diag(DoLoc, diag::note_matching) << "do";
+ SkipUntil(tok::semi, false, true);
+ }
+ return StmtError();
+ }
+ SourceLocation WhileLoc = ConsumeToken();
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "do/while";
+ SkipUntil(tok::semi, false, true);
+ return StmtError();
+ }
+
+ // Parse the parenthesized condition.
+ SourceLocation LPLoc = ConsumeParen();
+ ExprResult Cond = ParseExpression();
+ SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
+ DoScope.Exit();
+
+ if (Cond.isInvalid() || Body.isInvalid())
+ return StmtError();
+
+ return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc,
+ Cond.get(), RPLoc);
+}
+
+/// ParseForStatement
+/// for-statement: [C99 6.8.5.3]
+/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
+/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
+/// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
+/// [C++] statement
+/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
+/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
+///
+/// [C++] for-init-statement:
+/// [C++] expression-statement
+/// [C++] simple-declaration
+///
+StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_for) && "Not a for stmt!");
+ SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "for";
+ SkipUntil(tok::semi);
+ return StmtError();
+ }
+
+ bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
+
+ // C99 6.8.5p5 - In C99, the for statement is a block. This is not
+ // the case for C90. Start the loop scope.
+ //
+ // C++ 6.4p3:
+ // A name introduced by a declaration in a condition is in scope from its
+ // point of declaration until the end of the substatements controlled by the
+ // condition.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement).
+ // C++ 6.5.3p1:
+ // Names declared in the for-init-statement are in the same declarative-region
+ // as those declared in the condition.
+ //
+ unsigned ScopeFlags;
+ if (C99orCXXorObjC)
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
+ Scope::DeclScope | Scope::ControlScope;
+ else
+ ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
+
+ ParseScope ForScope(this, ScopeFlags);
+
+ SourceLocation LParenLoc = ConsumeParen();
+ ExprResult Value;
+
+ bool ForEach = false;
+ StmtResult FirstPart;
+ bool SecondPartIsInvalid = false;
+ FullExprArg SecondPart(Actions);
+ ExprResult Collection;
+ FullExprArg ThirdPart(Actions);
+ Decl *SecondVar = 0;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
+ C99orCXXorObjC? Sema::PCC_ForInit
+ : Sema::PCC_Expression);
+ ConsumeCodeCompletionToken();
+ }
+
+ // Parse the first part of the for specifier.
+ if (Tok.is(tok::semi)) { // for (;
+ // no first part, eat the ';'.
+ ConsumeToken();
+ } else if (isSimpleDeclaration()) { // for (int X = 4;
+ // Parse declaration, which eats the ';'.
+ if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
+ Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+
+ SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+ StmtVector Stmts(Actions);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext,
+ DeclEnd, attrs, false);
+ FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+
+ if (Tok.is(tok::semi)) { // for (int x = 4;
+ ConsumeToken();
+ } else if ((ForEach = isTokIdentifier_in())) {
+ Actions.ActOnForEachDeclStmt(DG);
+ // ObjC: for (id x in expr)
+ ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
+ ConsumeCodeCompletionToken();
+ }
+ Collection = ParseExpression();
+ } else {
+ Diag(Tok, diag::err_expected_semi_for);
+ }
+ } else {
+ Value = ParseExpression();
+
+ ForEach = isTokIdentifier_in();
+
+ // Turn the expression into a stmt.
+ if (!Value.isInvalid()) {
+ if (ForEach)
+ FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
+ else
+ FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value.get()));
+ }
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ } else if (ForEach) {
+ ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy());
+ ConsumeCodeCompletionToken();
+ }
+ Collection = ParseExpression();
+ } else {
+ if (!Value.isInvalid()) {
+ Diag(Tok, diag::err_expected_semi_for);
+ } else {
+ // Skip until semicolon or rparen, don't consume it.
+ SkipUntil(tok::r_paren, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+ }
+ }
+ if (!ForEach) {
+ assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
+ // Parse the second part of the for specifier.
+ if (Tok.is(tok::semi)) { // for (...;;
+ // no second part.
+ } else if (Tok.is(tok::r_paren)) {
+ // missing both semicolons.
+ } else {
+ ExprResult Second;
+ if (getLang().CPlusPlus)
+ ParseCXXCondition(Second, SecondVar, ForLoc, true);
+ else {
+ Second = ParseExpression();
+ if (!Second.isInvalid())
+ Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc,
+ Second.get());
+ }
+ SecondPartIsInvalid = Second.isInvalid();
+ SecondPart = Actions.MakeFullExpr(Second.get());
+ }
+
+ if (Tok.isNot(tok::semi)) {
+ if (!SecondPartIsInvalid || SecondVar)
+ Diag(Tok, diag::err_expected_semi_for);
+ else
+ // Skip until semicolon or rparen, don't consume it.
+ SkipUntil(tok::r_paren, true, true);
+ }
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ }
+
+ // Parse the third part of the for specifier.
+ if (Tok.isNot(tok::r_paren)) { // for (...;...;)
+ ExprResult Third = ParseExpression();
+ ThirdPart = Actions.MakeFullExpr(Third.take());
+ }
+ }
+ // Match the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
+ // there is no compound stmt. C90 does not have this clause. We only do this
+ // if the body isn't a compound statement to avoid push/pop in common cases.
+ //
+ // C++ 6.5p2:
+ // The substatement in an iteration-statement implicitly defines a local scope
+ // which is entered and exited each time through the loop.
+ //
+ // See comments in ParseIfStatement for why we create a scope for
+ // for-init-statement/condition and a new scope for substatement in C++.
+ //
+ ParseScope InnerScope(this, Scope::DeclScope,
+ C99orCXXorObjC && Tok.isNot(tok::l_brace));
+
+ // Read the body statement.
+ StmtResult Body(ParseStatement());
+
+ // Pop the body scope if needed.
+ InnerScope.Exit();
+
+ // Leave the for-scope.
+ ForScope.Exit();
+
+ if (Body.isInvalid())
+ return StmtError();
+
+ if (!ForEach)
+ return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart,
+ SecondVar, ThirdPart, RParenLoc, Body.take());
+
+ // FIXME: It isn't clear how to communicate the late destruction of
+ // C++ temporaries used to create the collection.
+ return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, FirstPart.take(),
+ Collection.take(), RParenLoc,
+ Body.take());
+}
+
+/// ParseGotoStatement
+/// jump-statement:
+/// 'goto' identifier ';'
+/// [GNU] 'goto' '*' expression ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
+ SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
+
+ StmtResult Res;
+ if (Tok.is(tok::identifier)) {
+ LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
+ Tok.getLocation());
+ Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
+ ConsumeToken();
+ } else if (Tok.is(tok::star)) {
+ // GNU indirect goto extension.
+ Diag(Tok, diag::ext_gnu_indirect_goto);
+ SourceLocation StarLoc = ConsumeToken();
+ ExprResult R(ParseExpression());
+ if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
+ SkipUntil(tok::semi, false, true);
+ return StmtError();
+ }
+ Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
+ } else {
+ Diag(Tok, diag::err_expected_ident);
+ return StmtError();
+ }
+
+ return move(Res);
+}
+
+/// ParseContinueStatement
+/// jump-statement:
+/// 'continue' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
+ return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
+}
+
+/// ParseBreakStatement
+/// jump-statement:
+/// 'break' ';'
+///
+/// Note: this lets the caller parse the end ';'.
+///
+StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
+ return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
+}
+
+/// ParseReturnStatement
+/// jump-statement:
+/// 'return' expression[opt] ';'
+StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) {
+ // FIXME: Use attributes?
+
+ assert(Tok.is(tok::kw_return) && "Not a return stmt!");
+ SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
+
+ ExprResult R;
+ if (Tok.isNot(tok::semi)) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteReturn(getCurScope());
+ ConsumeCodeCompletionToken();
+ SkipUntil(tok::semi, false, true);
+ return StmtError();
+ }
+
+ R = ParseExpression();
+ if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
+ SkipUntil(tok::semi, false, true);
+ return StmtError();
+ }
+ }
+ return Actions.ActOnReturnStmt(ReturnLoc, R.take());
+}
+
+/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
+/// routine is called to skip/ignore tokens that comprise the MS asm statement.
+StmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
+ SourceLocation EndLoc;
+ if (Tok.is(tok::l_brace)) {
+ unsigned short savedBraceCount = BraceCount;
+ do {
+ EndLoc = Tok.getLocation();
+ ConsumeAnyToken();
+ } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
+ } else {
+ // From the MS website: If used without braces, the __asm keyword means
+ // that the rest of the line is an assembly-language statement.
+ SourceManager &SrcMgr = PP.getSourceManager();
+ SourceLocation TokLoc = Tok.getLocation();
+ unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
+ do {
+ EndLoc = TokLoc;
+ ConsumeAnyToken();
+ TokLoc = Tok.getLocation();
+ } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
+ Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
+ Tok.isNot(tok::eof));
+ }
+ Token t;
+ t.setKind(tok::string_literal);
+ t.setLiteralData("\"/*FIXME: not done*/\"");
+ t.clearFlag(Token::NeedsCleaning);
+ t.setLength(21);
+ ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
+ ExprVector Constraints(Actions);
+ ExprVector Exprs(Actions);
+ ExprVector Clobbers(Actions);
+ return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0,
+ move_arg(Constraints), move_arg(Exprs),
+ AsmString.take(), move_arg(Clobbers),
+ EndLoc, true);
+}
+
+/// ParseAsmStatement - Parse a GNU extended asm statement.
+/// asm-statement:
+/// gnu-asm-statement
+/// ms-asm-statement
+///
+/// [GNU] gnu-asm-statement:
+/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
+///
+/// [GNU] asm-argument:
+/// asm-string-literal
+/// asm-string-literal ':' asm-operands[opt]
+/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
+/// ':' asm-clobbers
+///
+/// [GNU] asm-clobbers:
+/// asm-string-literal
+/// asm-clobbers ',' asm-string-literal
+///
+/// [MS] ms-asm-statement:
+/// '__asm' assembly-instruction ';'[opt]
+/// '__asm' '{' assembly-instruction-list '}' ';'[opt]
+///
+/// [MS] assembly-instruction-list:
+/// assembly-instruction ';'[opt]
+/// assembly-instruction-list ';' assembly-instruction ';'[opt]
+///
+StmtResult Parser::ParseAsmStatement(bool &msAsm) {
+ assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
+ SourceLocation AsmLoc = ConsumeToken();
+
+ if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
+ msAsm = true;
+ return FuzzyParseMicrosoftAsmStatement(AsmLoc);
+ }
+ DeclSpec DS;
+ SourceLocation Loc = Tok.getLocation();
+ ParseTypeQualifierListOpt(DS, true, false);
+
+ // GNU asms accept, but warn, about type-qualifiers other than volatile.
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
+ Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
+ Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
+
+ // Remember if this was a volatile asm.
+ bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "asm";
+ SkipUntil(tok::r_paren);
+ return StmtError();
+ }
+ Loc = ConsumeParen();
+
+ ExprResult AsmString(ParseAsmStringLiteral());
+ if (AsmString.isInvalid())
+ return StmtError();
+
+ llvm::SmallVector<IdentifierInfo *, 4> Names;
+ ExprVector Constraints(Actions);
+ ExprVector Exprs(Actions);
+ ExprVector Clobbers(Actions);
+
+ if (Tok.is(tok::r_paren)) {
+ // We have a simple asm expression like 'asm("foo")'.
+ SourceLocation RParenLoc = ConsumeParen();
+ return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
+ /*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
+ move_arg(Constraints), move_arg(Exprs),
+ AsmString.take(), move_arg(Clobbers),
+ RParenLoc);
+ }
+
+ // Parse Outputs, if present.
+ bool AteExtraColon = false;
+ if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+ // In C++ mode, parse "::" like ": :".
+ AteExtraColon = Tok.is(tok::coloncolon);
+ ConsumeToken();
+
+ if (!AteExtraColon &&
+ ParseAsmOperandsOpt(Names, Constraints, Exprs))
+ return StmtError();
+ }
+
+ unsigned NumOutputs = Names.size();
+
+ // Parse Inputs, if present.
+ if (AteExtraColon ||
+ Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
+ // In C++ mode, parse "::" like ": :".
+ if (AteExtraColon)
+ AteExtraColon = false;
+ else {
+ AteExtraColon = Tok.is(tok::coloncolon);
+ ConsumeToken();
+ }
+
+ if (!AteExtraColon &&
+ ParseAsmOperandsOpt(Names, Constraints, Exprs))
+ return StmtError();
+ }
+
+ assert(Names.size() == Constraints.size() &&
+ Constraints.size() == Exprs.size() &&
+ "Input operand size mismatch!");
+
+ unsigned NumInputs = Names.size() - NumOutputs;
+
+ // Parse the clobbers, if present.
+ if (AteExtraColon || Tok.is(tok::colon)) {
+ if (!AteExtraColon)
+ ConsumeToken();
+
+ // Parse the asm-string list for clobbers if present.
+ if (Tok.isNot(tok::r_paren)) {
+ while (1) {
+ ExprResult Clobber(ParseAsmStringLiteral());
+
+ if (Clobber.isInvalid())
+ break;
+
+ Clobbers.push_back(Clobber.release());
+
+ if (Tok.isNot(tok::comma)) break;
+ ConsumeToken();
+ }
+ }
+ }
+
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
+ return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
+ NumOutputs, NumInputs, Names.data(),
+ move_arg(Constraints), move_arg(Exprs),
+ AsmString.take(), move_arg(Clobbers),
+ RParenLoc);
+}
+
+/// ParseAsmOperands - Parse the asm-operands production as used by
+/// asm-statement, assuming the leading ':' token was eaten.
+///
+/// [GNU] asm-operands:
+/// asm-operand
+/// asm-operands ',' asm-operand
+///
+/// [GNU] asm-operand:
+/// asm-string-literal '(' expression ')'
+/// '[' identifier ']' asm-string-literal '(' expression ')'
+///
+//
+// FIXME: Avoid unnecessary std::string trashing.
+bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
+ llvm::SmallVectorImpl<ExprTy *> &Constraints,
+ llvm::SmallVectorImpl<ExprTy *> &Exprs) {
+ // 'asm-operands' isn't present?
+ if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
+ return false;
+
+ while (1) {
+ // Read the [id] if present.
+ if (Tok.is(tok::l_square)) {
+ SourceLocation Loc = ConsumeBracket();
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ ConsumeToken();
+
+ Names.push_back(II);
+ MatchRHSPunctuation(tok::r_square, Loc);
+ } else
+ Names.push_back(0);
+
+ ExprResult Constraint(ParseAsmStringLiteral());
+ if (Constraint.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+ Constraints.push_back(Constraint.release());
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+
+ // Read the parenthesized expression.
+ SourceLocation OpenLoc = ConsumeParen();
+ ExprResult Res(ParseExpression());
+ MatchRHSPunctuation(tok::r_paren, OpenLoc);
+ if (Res.isInvalid()) {
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+ Exprs.push_back(Res.release());
+ // Eat the comma and continue parsing if it exists.
+ if (Tok.isNot(tok::comma)) return false;
+ ConsumeToken();
+ }
+
+ return true;
+}
+
+Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
+ assert(Tok.is(tok::l_brace));
+ SourceLocation LBraceLoc = Tok.getLocation();
+
+ if (PP.isCodeCompletionEnabled())
+ if (trySkippingFunctionBodyForCodeCompletion())
+ return Actions.ActOnFinishFunctionBody(Decl, 0);
+
+ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
+ "parsing function body");
+
+ // Do not enter a scope for the brace, as the arguments are in the same scope
+ // (the function body) as the body itself. Instead, just read the statement
+ // list and put it into a CompoundStmt for safe keeping.
+ StmtResult FnBody(ParseCompoundStatementBody());
+
+ // If the function body could not be parsed, make a bogus compoundstmt.
+ if (FnBody.isInvalid())
+ FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
+ MultiStmtArg(Actions), false);
+
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
+}
+
+/// ParseFunctionTryBlock - Parse a C++ function-try-block.
+///
+/// function-try-block:
+/// 'try' ctor-initializer[opt] compound-statement handler-seq
+///
+Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
+ assert(Tok.is(tok::kw_try) && "Expected 'try'");
+ SourceLocation TryLoc = ConsumeToken();
+
+ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc,
+ "parsing function try block");
+
+ // Constructor initializer list?
+ if (Tok.is(tok::colon))
+ ParseConstructorInitializer(Decl);
+
+ if (PP.isCodeCompletionEnabled())
+ if (trySkippingFunctionBodyForCodeCompletion())
+ return Actions.ActOnFinishFunctionBody(Decl, 0);
+
+ SourceLocation LBraceLoc = Tok.getLocation();
+ StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
+ // If we failed to parse the try-catch, we just give the function an empty
+ // compound statement as the body.
+ if (FnBody.isInvalid())
+ FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
+ MultiStmtArg(Actions), false);
+
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
+}
+
+bool Parser::trySkippingFunctionBodyForCodeCompletion() {
+ assert(Tok.is(tok::l_brace));
+ assert(PP.isCodeCompletionEnabled() &&
+ "Should only be called when in code-completion mode");
+
+ // We're in code-completion mode. Skip parsing for all function bodies unless
+ // the body contains the code-completion point.
+ TentativeParsingAction PA(*this);
+ ConsumeBrace();
+ if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false,
+ /*StopAtCodeCompletion=*/true)) {
+ PA.Commit();
+ return true;
+ }
+
+ PA.Revert();
+ return false;
+}
+
+/// ParseCXXTryBlock - Parse a C++ try-block.
+///
+/// try-block:
+/// 'try' compound-statement handler-seq
+///
+StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) {
+ // FIXME: Add attributes?
+
+ assert(Tok.is(tok::kw_try) && "Expected 'try'");
+
+ SourceLocation TryLoc = ConsumeToken();
+ return ParseCXXTryBlockCommon(TryLoc);
+}
+
+/// ParseCXXTryBlockCommon - Parse the common part of try-block and
+/// function-try-block.
+///
+/// try-block:
+/// 'try' compound-statement handler-seq
+///
+/// function-try-block:
+/// 'try' ctor-initializer[opt] compound-statement handler-seq
+///
+/// handler-seq:
+/// handler handler-seq[opt]
+///
+StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected_lbrace));
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ ParsedAttributesWithRange attrs;
+ StmtResult TryBlock(ParseCompoundStatement(attrs));
+ if (TryBlock.isInvalid())
+ return move(TryBlock);
+
+ StmtVector Handlers(Actions);
+ MaybeParseCXX0XAttributes(attrs);
+ ProhibitAttributes(attrs);
+
+ if (Tok.isNot(tok::kw_catch))
+ return StmtError(Diag(Tok, diag::err_expected_catch));
+ while (Tok.is(tok::kw_catch)) {
+ StmtResult Handler(ParseCXXCatchBlock());
+ if (!Handler.isInvalid())
+ Handlers.push_back(Handler.release());
+ }
+ // Don't bother creating the full statement if we don't have any usable
+ // handlers.
+ if (Handlers.empty())
+ return StmtError();
+
+ return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers));
+}
+
+/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
+///
+/// handler:
+/// 'catch' '(' exception-declaration ')' compound-statement
+///
+/// exception-declaration:
+/// type-specifier-seq declarator
+/// type-specifier-seq abstract-declarator
+/// type-specifier-seq
+/// '...'
+///
+StmtResult Parser::ParseCXXCatchBlock() {
+ assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
+
+ SourceLocation CatchLoc = ConsumeToken();
+
+ SourceLocation LParenLoc = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return StmtError();
+
+ // C++ 3.3.2p3:
+ // The name in a catch exception-declaration is local to the handler and
+ // shall not be redeclared in the outermost block of the handler.
+ ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
+
+ // exception-declaration is equivalent to '...' or a parameter-declaration
+ // without default arguments.
+ Decl *ExceptionDecl = 0;
+ if (Tok.isNot(tok::ellipsis)) {
+ DeclSpec DS;
+ if (ParseCXXTypeSpecifierSeq(DS))
+ return StmtError();
+ Declarator ExDecl(DS, Declarator::CXXCatchContext);
+ ParseDeclarator(ExDecl);
+ ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
+ } else
+ ConsumeToken();
+
+ if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
+ return StmtError();
+
+ if (Tok.isNot(tok::l_brace))
+ return StmtError(Diag(Tok, diag::err_expected_lbrace));
+
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ ParsedAttributes attrs;
+ StmtResult Block(ParseCompoundStatement(attrs));
+ if (Block.isInvalid())
+ return move(Block);
+
+ return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take());
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
new file mode 100644
index 0000000..8387c88
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -0,0 +1,1124 @@
+//===--- ParseTemplate.cpp - Template Parsing -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements parsing of C++ templates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "RAIIObjectsForParser.h"
+using namespace clang;
+
+/// \brief Parse a template declaration, explicit instantiation, or
+/// explicit specialization.
+Decl *
+Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
+ if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less))
+ return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
+ DeclEnd);
+
+ return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
+}
+
+/// \brief RAII class that manages the template parameter depth.
+namespace {
+ class TemplateParameterDepthCounter {
+ unsigned &Depth;
+ unsigned AddedLevels;
+
+ public:
+ explicit TemplateParameterDepthCounter(unsigned &Depth)
+ : Depth(Depth), AddedLevels(0) { }
+
+ ~TemplateParameterDepthCounter() {
+ Depth -= AddedLevels;
+ }
+
+ void operator++() {
+ ++Depth;
+ ++AddedLevels;
+ }
+
+ operator unsigned() const { return Depth; }
+ };
+}
+
+/// \brief Parse a template declaration or an explicit specialization.
+///
+/// Template declarations include one or more template parameter lists
+/// and either the function or class template declaration. Explicit
+/// specializations contain one or more 'template < >' prefixes
+/// followed by a (possibly templated) declaration. Since the
+/// syntactic form of both features is nearly identical, we parse all
+/// of the template headers together and let semantic analysis sort
+/// the declarations from the explicit specializations.
+///
+/// template-declaration: [C++ temp]
+/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration
+///
+/// explicit-specialization: [ C++ temp.expl.spec]
+/// 'template' '<' '>' declaration
+Decl *
+Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
+ assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
+ "Token does not start a template declaration.");
+
+ // Enter template-parameter scope.
+ ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+
+ // Tell the action that names should be checked in the context of
+ // the declaration to come.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
+ // Parse multiple levels of template headers within this template
+ // parameter scope, e.g.,
+ //
+ // template<typename T>
+ // template<typename U>
+ // class A<T>::B { ... };
+ //
+ // We parse multiple levels non-recursively so that we can build a
+ // single data structure containing all of the template parameter
+ // lists to easily differentiate between the case above and:
+ //
+ // template<typename T>
+ // class A {
+ // template<typename U> class B;
+ // };
+ //
+ // In the first case, the action for declaring A<T>::B receives
+ // both template parameter lists. In the second case, the action for
+ // defining A<T>::B receives just the inner template parameter list
+ // (and retrieves the outer template parameter list from its
+ // context).
+ bool isSpecialization = true;
+ bool LastParamListWasEmpty = false;
+ TemplateParameterLists ParamLists;
+ TemplateParameterDepthCounter Depth(TemplateParameterDepth);
+ do {
+ // Consume the 'export', if any.
+ SourceLocation ExportLoc;
+ if (Tok.is(tok::kw_export)) {
+ ExportLoc = ConsumeToken();
+ }
+
+ // Consume the 'template', which should be here.
+ SourceLocation TemplateLoc;
+ if (Tok.is(tok::kw_template)) {
+ TemplateLoc = ConsumeToken();
+ } else {
+ Diag(Tok.getLocation(), diag::err_expected_template);
+ return 0;
+ }
+
+ // Parse the '<' template-parameter-list '>'
+ SourceLocation LAngleLoc, RAngleLoc;
+ llvm::SmallVector<Decl*, 4> TemplateParams;
+ if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
+ // Skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return 0;
+ }
+
+ ParamLists.push_back(
+ Actions.ActOnTemplateParameterList(Depth, ExportLoc,
+ TemplateLoc, LAngleLoc,
+ TemplateParams.data(),
+ TemplateParams.size(), RAngleLoc));
+
+ if (!TemplateParams.empty()) {
+ isSpecialization = false;
+ ++Depth;
+ } else {
+ LastParamListWasEmpty = true;
+ }
+ } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
+
+ // Parse the actual template declaration.
+ return ParseSingleDeclarationAfterTemplate(Context,
+ ParsedTemplateInfo(&ParamLists,
+ isSpecialization,
+ LastParamListWasEmpty),
+ ParsingTemplateParams,
+ DeclEnd, AS);
+}
+
+/// \brief Parse a single declaration that declares a template,
+/// template specialization, or explicit instantiation of a template.
+///
+/// \param TemplateParams if non-NULL, the template parameter lists
+/// that preceded this declaration. In this case, the declaration is a
+/// template declaration, out-of-line definition of a template, or an
+/// explicit template specialization. When NULL, the declaration is an
+/// explicit template instantiation.
+///
+/// \param TemplateLoc when TemplateParams is NULL, the location of
+/// the 'template' keyword that indicates that we have an explicit
+/// template instantiation.
+///
+/// \param DeclEnd will receive the source location of the last token
+/// within this declaration.
+///
+/// \param AS the access specifier associated with this
+/// declaration. Will be AS_none for namespace-scope declarations.
+///
+/// \returns the new declaration.
+Decl *
+Parser::ParseSingleDeclarationAfterTemplate(
+ unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromTParams,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
+ assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
+ "Template information required");
+
+ if (Context == Declarator::MemberContext) {
+ // We are parsing a member template.
+ ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams);
+ return 0;
+ }
+
+ ParsedAttributesWithRange prefixAttrs;
+ MaybeParseCXX0XAttributes(prefixAttrs);
+
+ if (Tok.is(tok::kw_using))
+ return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
+ prefixAttrs);
+
+ // Parse the declaration specifiers, stealing the accumulated
+ // diagnostics from the template parameters.
+ ParsingDeclSpec DS(DiagsFromTParams);
+
+ DS.takeAttributesFrom(prefixAttrs);
+
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
+ getDeclSpecContextFromDeclaratorContext(Context));
+
+ if (Tok.is(tok::semi)) {
+ DeclEnd = ConsumeToken();
+ Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DS.complete(Decl);
+ return Decl;
+ }
+
+ // Parse the declarator.
+ ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
+ ParseDeclarator(DeclaratorInfo);
+ // Error parsing the declarator?
+ if (!DeclaratorInfo.hasName()) {
+ // If so, skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return 0;
+ }
+
+ // If we have a declaration or declarator list, handle it.
+ if (isDeclarationAfterDeclarator()) {
+ // Parse this declaration.
+ Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
+ TemplateInfo);
+
+ if (Tok.is(tok::comma)) {
+ Diag(Tok, diag::err_multiple_template_declarators)
+ << (int)TemplateInfo.Kind;
+ SkipUntil(tok::semi, true, false);
+ return ThisDecl;
+ }
+
+ // Eat the semi colon after the declaration.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+ DeclaratorInfo.complete(ThisDecl);
+ return ThisDecl;
+ }
+
+ if (DeclaratorInfo.isFunctionDeclarator() &&
+ isStartOfFunctionDefinition(DeclaratorInfo)) {
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
+
+ if (Tok.is(tok::l_brace)) {
+ // This recovery skips the entire function body. It would be nice
+ // to simply call ParseFunctionDefinition() below, however Sema
+ // assumes the declarator represents a function, not a typedef.
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, true);
+ } else {
+ SkipUntil(tok::semi);
+ }
+ return 0;
+ }
+ return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo);
+ }
+
+ if (DeclaratorInfo.isFunctionDeclarator())
+ Diag(Tok, diag::err_expected_fn_body);
+ else
+ Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
+ SkipUntil(tok::semi);
+ return 0;
+}
+
+/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
+/// angle brackets. Depth is the depth of this template-parameter-list, which
+/// is the number of template headers directly enclosing this template header.
+/// TemplateParams is the current list of template parameters we're building.
+/// The template parameter we parse will be added to this list. LAngleLoc and
+/// RAngleLoc will receive the positions of the '<' and '>', respectively,
+/// that enclose this template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
+bool Parser::ParseTemplateParameters(unsigned Depth,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc) {
+ // Get the template parameter list.
+ if (!Tok.is(tok::less)) {
+ Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
+ return true;
+ }
+ LAngleLoc = ConsumeToken();
+
+ // Try to parse the template parameter list.
+ if (Tok.is(tok::greater))
+ RAngleLoc = ConsumeToken();
+ else if (ParseTemplateParameterList(Depth, TemplateParams)) {
+ if (!Tok.is(tok::greater)) {
+ Diag(Tok.getLocation(), diag::err_expected_greater);
+ return true;
+ }
+ RAngleLoc = ConsumeToken();
+ }
+ return false;
+}
+
+/// ParseTemplateParameterList - Parse a template parameter list. If
+/// the parsing fails badly (i.e., closing bracket was left out), this
+/// will try to put the token stream in a reasonable position (closing
+/// a statement, etc.) and return false.
+///
+/// template-parameter-list: [C++ temp]
+/// template-parameter
+/// template-parameter-list ',' template-parameter
+bool
+Parser::ParseTemplateParameterList(unsigned Depth,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams) {
+ while (1) {
+ if (Decl *TmpParam
+ = ParseTemplateParameter(Depth, TemplateParams.size())) {
+ TemplateParams.push_back(TmpParam);
+ } else {
+ // If we failed to parse a template parameter, skip until we find
+ // a comma or closing brace.
+ SkipUntil(tok::comma, tok::greater, true, true);
+ }
+
+ // Did we find a comma or the end of the template parmeter list?
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ } else if (Tok.is(tok::greater)) {
+ // Don't consume this... that's done by template parser.
+ break;
+ } else {
+ // Somebody probably forgot to close the template. Skip ahead and
+ // try to get out of the expression. This error is currently
+ // subsumed by whatever goes on in ParseTemplateParameter.
+ // TODO: This could match >>, and it would be nice to avoid those
+ // silly errors with template <vec<T>>.
+ Diag(Tok.getLocation(), diag::err_expected_comma_greater);
+ SkipUntil(tok::greater, true, true);
+ return false;
+ }
+ }
+ return true;
+}
+
+/// \brief Determine whether the parser is at the start of a template
+/// type parameter.
+bool Parser::isStartOfTemplateTypeParameter() {
+ if (Tok.is(tok::kw_class)) {
+ // "class" may be the start of an elaborated-type-specifier or a
+ // type-parameter. Per C++ [temp.param]p3, we prefer the type-parameter.
+ switch (NextToken().getKind()) {
+ case tok::equal:
+ case tok::comma:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::ellipsis:
+ return true;
+
+ case tok::identifier:
+ // This may be either a type-parameter or an elaborated-type-specifier.
+ // We have to look further.
+ break;
+
+ default:
+ return false;
+ }
+
+ switch (GetLookAheadToken(2).getKind()) {
+ case tok::equal:
+ case tok::comma:
+ case tok::greater:
+ case tok::greatergreater:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ if (Tok.isNot(tok::kw_typename))
+ return false;
+
+ // C++ [temp.param]p2:
+ // There is no semantic difference between class and typename in a
+ // template-parameter. typename followed by an unqualified-id
+ // names a template type parameter. typename followed by a
+ // qualified-id denotes the type in a non-type
+ // parameter-declaration.
+ Token Next = NextToken();
+
+ // If we have an identifier, skip over it.
+ if (Next.getKind() == tok::identifier)
+ Next = GetLookAheadToken(2);
+
+ switch (Next.getKind()) {
+ case tok::equal:
+ case tok::comma:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::ellipsis:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
+///
+/// template-parameter: [C++ temp.param]
+/// type-parameter
+/// parameter-declaration
+///
+/// type-parameter: (see below)
+/// 'class' ...[opt] identifier[opt]
+/// 'class' identifier[opt] '=' type-id
+/// 'typename' ...[opt] identifier[opt]
+/// 'typename' identifier[opt] '=' type-id
+/// 'template' '<' template-parameter-list '>'
+/// 'class' ...[opt] identifier[opt]
+/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
+/// = id-expression
+Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
+ if (isStartOfTemplateTypeParameter())
+ return ParseTypeParameter(Depth, Position);
+
+ if (Tok.is(tok::kw_template))
+ return ParseTemplateTemplateParameter(Depth, Position);
+
+ // If it's none of the above, then it must be a parameter declaration.
+ // NOTE: This will pick up errors in the closure of the template parameter
+ // list (e.g., template < ; Check here to implement >> style closures.
+ return ParseNonTypeTemplateParameter(Depth, Position);
+}
+
+/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).
+/// Other kinds of template parameters are parsed in
+/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.
+///
+/// type-parameter: [C++ temp.param]
+/// 'class' ...[opt][C++0x] identifier[opt]
+/// 'class' identifier[opt] '=' type-id
+/// 'typename' ...[opt][C++0x] identifier[opt]
+/// 'typename' identifier[opt] '=' type-id
+Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
+ assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
+ "A type-parameter starts with 'class' or 'typename'");
+
+ // Consume the 'class' or 'typename' keyword.
+ bool TypenameKeyword = Tok.is(tok::kw_typename);
+ SourceLocation KeyLoc = ConsumeToken();
+
+ // Grab the ellipsis (if given).
+ bool Ellipsis = false;
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis)) {
+ Ellipsis = true;
+ EllipsisLoc = ConsumeToken();
+
+ if (!getLang().CPlusPlus0x)
+ Diag(EllipsisLoc, diag::ext_variadic_templates);
+ }
+
+ // Grab the template parameter name (if given)
+ SourceLocation NameLoc;
+ IdentifierInfo* ParamName = 0;
+ if (Tok.is(tok::identifier)) {
+ ParamName = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+ } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
+ Tok.is(tok::greater)) {
+ // Unnamed template parameter. Don't have to do anything here, just
+ // don't consume this token.
+ } else {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ return 0;
+ }
+
+ // Grab a default argument (if available).
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the type parameter into the local scope.
+ SourceLocation EqualLoc;
+ ParsedType DefaultArg;
+ if (Tok.is(tok::equal)) {
+ EqualLoc = ConsumeToken();
+ DefaultArg = ParseTypeName().get();
+ }
+
+ return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
+ EllipsisLoc, KeyLoc, ParamName, NameLoc,
+ Depth, Position, EqualLoc, DefaultArg);
+}
+
+/// ParseTemplateTemplateParameter - Handle the parsing of template
+/// template parameters.
+///
+/// type-parameter: [C++ temp.param]
+/// 'template' '<' template-parameter-list '>' 'class'
+/// ...[opt] identifier[opt]
+/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
+/// = id-expression
+Decl *
+Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
+ assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
+
+ // Handle the template <...> part.
+ SourceLocation TemplateLoc = ConsumeToken();
+ llvm::SmallVector<Decl*,8> TemplateParams;
+ SourceLocation LAngleLoc, RAngleLoc;
+ {
+ ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+ if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
+ return 0;
+ }
+ }
+
+ // Generate a meaningful error if the user forgot to put class before the
+ // identifier, comma, or greater.
+ if (!Tok.is(tok::kw_class)) {
+ Diag(Tok.getLocation(), diag::err_expected_class_before)
+ << PP.getSpelling(Tok);
+ return 0;
+ }
+ ConsumeToken();
+
+ // Parse the ellipsis, if given.
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis)) {
+ EllipsisLoc = ConsumeToken();
+
+ if (!getLang().CPlusPlus0x)
+ Diag(EllipsisLoc, diag::ext_variadic_templates);
+ }
+
+ // Get the identifier, if given.
+ SourceLocation NameLoc;
+ IdentifierInfo* ParamName = 0;
+ if (Tok.is(tok::identifier)) {
+ ParamName = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
+ } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
+ // Unnamed template parameter. Don't have to do anything here, just
+ // don't consume this token.
+ } else {
+ Diag(Tok.getLocation(), diag::err_expected_ident);
+ return 0;
+ }
+
+ TemplateParamsTy *ParamList =
+ Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
+ TemplateLoc, LAngleLoc,
+ TemplateParams.data(),
+ TemplateParams.size(),
+ RAngleLoc);
+
+ // Grab a default argument (if available).
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the template parameter into the local scope.
+ SourceLocation EqualLoc;
+ ParsedTemplateArgument DefaultArg;
+ if (Tok.is(tok::equal)) {
+ EqualLoc = ConsumeToken();
+ DefaultArg = ParseTemplateTemplateArgument();
+ if (DefaultArg.isInvalid()) {
+ Diag(Tok.getLocation(),
+ diag::err_default_template_template_parameter_not_template);
+ static const tok::TokenKind EndToks[] = {
+ tok::comma, tok::greater, tok::greatergreater
+ };
+ SkipUntil(EndToks, 3, true, true);
+ }
+ }
+
+ return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc,
+ ParamList, EllipsisLoc,
+ ParamName, NameLoc, Depth,
+ Position, EqualLoc, DefaultArg);
+}
+
+/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
+/// template parameters (e.g., in "template<int Size> class array;").
+///
+/// template-parameter:
+/// ...
+/// parameter-declaration
+Decl *
+Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
+ // Parse the declaration-specifiers (i.e., the type).
+ // FIXME: The type should probably be restricted in some way... Not all
+ // declarators (parts of declarators?) are accepted for parameters.
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
+
+ // Parse this as a typename.
+ Declarator ParamDecl(DS, Declarator::TemplateParamContext);
+ ParseDeclarator(ParamDecl);
+ if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+ // This probably shouldn't happen - and it's more of a Sema thing, but
+ // basically we didn't parse the type name because we couldn't associate
+ // it with an AST node. we should just skip to the comma or greater.
+ // TODO: This is currently a placeholder for some kind of Sema Error.
+ Diag(Tok.getLocation(), diag::err_parse_error);
+ SkipUntil(tok::comma, tok::greater, true, true);
+ return 0;
+ }
+
+ // If there is a default value, parse it.
+ // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
+ // we introduce the template parameter into the local scope.
+ SourceLocation EqualLoc;
+ ExprResult DefaultArg;
+ if (Tok.is(tok::equal)) {
+ EqualLoc = ConsumeToken();
+
+ // C++ [temp.param]p15:
+ // When parsing a default template-argument for a non-type
+ // template-parameter, the first non-nested > is taken as the
+ // end of the template-parameter-list rather than a greater-than
+ // operator.
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+
+ DefaultArg = ParseAssignmentExpression();
+ if (DefaultArg.isInvalid())
+ SkipUntil(tok::comma, tok::greater, true, true);
+ }
+
+ // Create the parameter.
+ return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
+ Depth, Position, EqualLoc,
+ DefaultArg.take());
+}
+
+/// \brief Parses a template-id that after the template name has
+/// already been parsed.
+///
+/// This routine takes care of parsing the enclosed template argument
+/// list ('<' template-parameter-list [opt] '>') and placing the
+/// results into a form that can be transferred to semantic analysis.
+///
+/// \param Template the template declaration produced by isTemplateName
+///
+/// \param TemplateNameLoc the source location of the template name
+///
+/// \param SS if non-NULL, the nested-name-specifier preceding the
+/// template name.
+///
+/// \param ConsumeLastToken if true, then we will consume the last
+/// token that forms the template-id. Otherwise, we will leave the
+/// last token in the stream (e.g., so that it can be replaced with an
+/// annotation token).
+bool
+Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ const CXXScopeSpec *SS,
+ bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ SourceLocation &RAngleLoc) {
+ assert(Tok.is(tok::less) && "Must have already parsed the template-name");
+
+ // Consume the '<'.
+ LAngleLoc = ConsumeToken();
+
+ // Parse the optional template-argument-list.
+ bool Invalid = false;
+ {
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+ if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater))
+ Invalid = ParseTemplateArgumentList(TemplateArgs);
+
+ if (Invalid) {
+ // Try to find the closing '>'.
+ SkipUntil(tok::greater, true, !ConsumeLastToken);
+
+ return true;
+ }
+ }
+
+ if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) {
+ Diag(Tok.getLocation(), diag::err_expected_greater);
+ return true;
+ }
+
+ // Determine the location of the '>' or '>>'. Only consume this
+ // token if the caller asked us to.
+ RAngleLoc = Tok.getLocation();
+
+ if (Tok.is(tok::greatergreater)) {
+ if (!getLang().CPlusPlus0x) {
+ const char *ReplaceStr = "> >";
+ if (NextToken().is(tok::greater) || NextToken().is(tok::greatergreater))
+ ReplaceStr = "> > ";
+
+ Diag(Tok.getLocation(), diag::err_two_right_angle_brackets_need_space)
+ << FixItHint::CreateReplacement(
+ SourceRange(Tok.getLocation()), ReplaceStr);
+ }
+
+ Tok.setKind(tok::greater);
+ if (!ConsumeLastToken) {
+ // Since we're not supposed to consume the '>>' token, we need
+ // to insert a second '>' token after the first.
+ PP.EnterToken(Tok);
+ }
+ } else if (ConsumeLastToken)
+ ConsumeToken();
+
+ return false;
+}
+
+/// \brief Replace the tokens that form a simple-template-id with an
+/// annotation token containing the complete template-id.
+///
+/// The first token in the stream must be the name of a template that
+/// is followed by a '<'. This routine will parse the complete
+/// simple-template-id and replace the tokens with a single annotation
+/// token with one of two different kinds: if the template-id names a
+/// type (and \p AllowTypeAnnotation is true), the annotation token is
+/// a type annotation that includes the optional nested-name-specifier
+/// (\p SS). Otherwise, the annotation token is a template-id
+/// annotation that does not include the optional
+/// nested-name-specifier.
+///
+/// \param Template the declaration of the template named by the first
+/// token (an identifier), as returned from \c Action::isTemplateName().
+///
+/// \param TemplateNameKind the kind of template that \p Template
+/// refers to, as returned from \c Action::isTemplateName().
+///
+/// \param SS if non-NULL, the nested-name-specifier that precedes
+/// this template name.
+///
+/// \param TemplateKWLoc if valid, specifies that this template-id
+/// annotation was preceded by the 'template' keyword and gives the
+/// location of that keyword. If invalid (the default), then this
+/// template-id was not preceded by a 'template' keyword.
+///
+/// \param AllowTypeAnnotation if true (the default), then a
+/// simple-template-id that refers to a class template, template
+/// template parameter, or other template that produces a type will be
+/// replaced with a type annotation token. Otherwise, the
+/// simple-template-id is always replaced with a template-id
+/// annotation token.
+///
+/// If an unrecoverable parse error occurs and no annotation token can be
+/// formed, this function returns true.
+///
+bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+ const CXXScopeSpec *SS,
+ UnqualifiedId &TemplateName,
+ SourceLocation TemplateKWLoc,
+ bool AllowTypeAnnotation) {
+ assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
+ assert(Template && Tok.is(tok::less) &&
+ "Parser isn't at the beginning of a template-id");
+
+ // Consume the template-name.
+ SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();
+
+ // Parse the enclosed template argument list.
+ SourceLocation LAngleLoc, RAngleLoc;
+ TemplateArgList TemplateArgs;
+ bool Invalid = ParseTemplateIdAfterTemplateName(Template,
+ TemplateNameLoc,
+ SS, false, LAngleLoc,
+ TemplateArgs,
+ RAngleLoc);
+
+ if (Invalid) {
+ // If we failed to parse the template ID but skipped ahead to a >, we're not
+ // going to be able to form a token annotation. Eat the '>' if present.
+ if (Tok.is(tok::greater))
+ ConsumeToken();
+ return true;
+ }
+
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+ TemplateArgs.size());
+
+ // Build the annotation token.
+ if (TNK == TNK_Type_template && AllowTypeAnnotation) {
+ TypeResult Type
+ = Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
+ LAngleLoc, TemplateArgsPtr,
+ RAngleLoc);
+ if (Type.isInvalid()) {
+ // If we failed to parse the template ID but skipped ahead to a >, we're not
+ // going to be able to form a token annotation. Eat the '>' if present.
+ if (Tok.is(tok::greater))
+ ConsumeToken();
+ return true;
+ }
+
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Type.get());
+ if (SS && SS->isNotEmpty())
+ Tok.setLocation(SS->getBeginLoc());
+ else if (TemplateKWLoc.isValid())
+ Tok.setLocation(TemplateKWLoc);
+ else
+ Tok.setLocation(TemplateNameLoc);
+ } else {
+ // Build a template-id annotation token that can be processed
+ // later.
+ Tok.setKind(tok::annot_template_id);
+ TemplateIdAnnotation *TemplateId
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+ TemplateId->TemplateNameLoc = TemplateNameLoc;
+ if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
+ TemplateId->Name = TemplateName.Identifier;
+ TemplateId->Operator = OO_None;
+ } else {
+ TemplateId->Name = 0;
+ TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
+ }
+ TemplateId->Template = Template;
+ TemplateId->Kind = TNK;
+ TemplateId->LAngleLoc = LAngleLoc;
+ TemplateId->RAngleLoc = RAngleLoc;
+ ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
+ for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
+ Args[Arg] = TemplateArgs[Arg];
+ Tok.setAnnotationValue(TemplateId);
+ if (TemplateKWLoc.isValid())
+ Tok.setLocation(TemplateKWLoc);
+ else
+ Tok.setLocation(TemplateNameLoc);
+
+ TemplateArgsPtr.release();
+ }
+
+ // Common fields for the annotation token
+ Tok.setAnnotationEndLoc(RAngleLoc);
+
+ // In case the tokens were cached, have Preprocessor replace them with the
+ // annotation token.
+ PP.AnnotateCachedTokens(Tok);
+ return false;
+}
+
+/// \brief Replaces a template-id annotation token with a type
+/// annotation token.
+///
+/// If there was a failure when forming the type from the template-id,
+/// a type annotation token will still be created, but will have a
+/// NULL type pointer to signify an error.
+void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
+ assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
+
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ assert((TemplateId->Kind == TNK_Type_template ||
+ TemplateId->Kind == TNK_Dependent_template_name) &&
+ "Only works for type and dependent templates");
+
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+
+ TypeResult Type
+ = Actions.ActOnTemplateIdType(TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+ // Create the new "type" annotation token.
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Type.isInvalid() ? ParsedType() : Type.get());
+ if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
+ Tok.setLocation(SS->getBeginLoc());
+ // End location stays the same
+
+ // Replace the template-id annotation token, and possible the scope-specifier
+ // that precedes it, with the typename annotation token.
+ PP.AnnotateCachedTokens(Tok);
+ TemplateId->Destroy();
+}
+
+/// \brief Determine whether the given token can end a template argument.
+static bool isEndOfTemplateArgument(Token Tok) {
+ return Tok.is(tok::comma) || Tok.is(tok::greater) ||
+ Tok.is(tok::greatergreater);
+}
+
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+ if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+ !Tok.is(tok::annot_cxxscope))
+ return ParsedTemplateArgument();
+
+ // C++0x [temp.arg.template]p1:
+ // A template-argument for a template template-parameter shall be the name
+ // of a class template or a template alias, expressed as id-expression.
+ //
+ // We parse an id-expression that refers to a class template or template
+ // alias. The grammar we parse is:
+ //
+ // nested-name-specifier[opt] template[opt] identifier ...[opt]
+ //
+ // followed by a token that terminates a template argument, such as ',',
+ // '>', or (in some cases) '>>'.
+ CXXScopeSpec SS; // nested-name-specifier, if present
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ /*EnteringContext=*/false);
+
+ ParsedTemplateArgument Result;
+ SourceLocation EllipsisLoc;
+ if (SS.isSet() && Tok.is(tok::kw_template)) {
+ // Parse the optional 'template' keyword following the
+ // nested-name-specifier.
+ SourceLocation TemplateLoc = ConsumeToken();
+
+ if (Tok.is(tok::identifier)) {
+ // We appear to have a dependent template name.
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ // Parse the ellipsis.
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
+ // If the next token signals the end of a template argument,
+ // then we have a dependent template name that could be a template
+ // template argument.
+ TemplateTy Template;
+ if (isEndOfTemplateArgument(Tok) &&
+ Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc,
+ SS, Name,
+ /*ObjectType=*/ ParsedType(),
+ /*EnteringContext=*/false,
+ Template))
+ Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ } else if (Tok.is(tok::identifier)) {
+ // We may have a (non-dependent) template name.
+ TemplateTy Template;
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ // Parse the ellipsis.
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
+ if (isEndOfTemplateArgument(Tok)) {
+ bool MemberOfUnknownSpecialization;
+ TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false,
+ Name,
+ /*ObjectType=*/ ParsedType(),
+ /*EnteringContext=*/false,
+ Template,
+ MemberOfUnknownSpecialization);
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ // We have an id-expression that refers to a class template or
+ // (C++0x) template alias.
+ Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
+ }
+ }
+
+ // If this is a pack expansion, build it as such.
+ if (EllipsisLoc.isValid() && !Result.isInvalid())
+ Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);
+
+ return Result;
+}
+
+/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
+///
+/// template-argument: [C++ 14.2]
+/// constant-expression
+/// type-id
+/// id-expression
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
+ // C++ [temp.arg]p2:
+ // In a template-argument, an ambiguity between a type-id and an
+ // expression is resolved to a type-id, regardless of the form of
+ // the corresponding template-parameter.
+ //
+ // Therefore, we initially try to parse a type-id.
+ if (isCXXTypeId(TypeIdAsTemplateArgument)) {
+ SourceLocation Loc = Tok.getLocation();
+ TypeResult TypeArg = ParseTypeName(/*Range=*/0,
+ Declarator::TemplateTypeArgContext);
+ if (TypeArg.isInvalid())
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type,
+ TypeArg.get().getAsOpaquePtr(),
+ Loc);
+ }
+
+ // Try to parse a template template argument.
+ {
+ TentativeParsingAction TPA(*this);
+
+ ParsedTemplateArgument TemplateTemplateArgument
+ = ParseTemplateTemplateArgument();
+ if (!TemplateTemplateArgument.isInvalid()) {
+ TPA.Commit();
+ return TemplateTemplateArgument;
+ }
+
+ // Revert this tentative parse to parse a non-type template argument.
+ TPA.Revert();
+ }
+
+ // Parse a non-type template argument.
+ SourceLocation Loc = Tok.getLocation();
+ ExprResult ExprArg = ParseConstantExpression();
+ if (ExprArg.isInvalid() || !ExprArg.get())
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(ParsedTemplateArgument::NonType,
+ ExprArg.release(), Loc);
+}
+
+/// \brief Determine whether the current tokens can only be parsed as a
+/// template argument list (starting with the '<') and never as a '<'
+/// expression.
+bool Parser::IsTemplateArgumentList(unsigned Skip) {
+ struct AlwaysRevertAction : TentativeParsingAction {
+ AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
+ ~AlwaysRevertAction() { Revert(); }
+ } Tentative(*this);
+
+ while (Skip) {
+ ConsumeToken();
+ --Skip;
+ }
+
+ // '<'
+ if (!Tok.is(tok::less))
+ return false;
+ ConsumeToken();
+
+ // An empty template argument list.
+ if (Tok.is(tok::greater))
+ return true;
+
+ // See whether we have declaration specifiers, which indicate a type.
+ while (isCXXDeclarationSpecifier() == TPResult::True())
+ ConsumeToken();
+
+ // If we have a '>' or a ',' then this is a template argument list.
+ return Tok.is(tok::greater) || Tok.is(tok::comma);
+}
+
+/// ParseTemplateArgumentList - Parse a C++ template-argument-list
+/// (C++ [temp.names]). Returns true if there was an error.
+///
+/// template-argument-list: [C++ 14.2]
+/// template-argument
+/// template-argument-list ',' template-argument
+bool
+Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+ while (true) {
+ ParsedTemplateArgument Arg = ParseTemplateArgument();
+ if (Tok.is(tok::ellipsis)) {
+ SourceLocation EllipsisLoc = ConsumeToken();
+ Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
+ }
+
+ if (Arg.isInvalid()) {
+ SkipUntil(tok::comma, tok::greater, true, true);
+ return true;
+ }
+
+ // Save this template argument.
+ TemplateArgs.push_back(Arg);
+
+ // If the next token is a comma, consume it and keep reading
+ // arguments.
+ if (Tok.isNot(tok::comma)) break;
+
+ // Consume the comma.
+ ConsumeToken();
+ }
+
+ return false;
+}
+
+/// \brief Parse a C++ explicit template instantiation
+/// (C++ [temp.explicit]).
+///
+/// explicit-instantiation:
+/// 'extern' [opt] 'template' declaration
+///
+/// Note that the 'extern' is a GNU extension and C++0x feature.
+Decl *Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd) {
+ // This isn't really required here.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
+ return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
+ ParsedTemplateInfo(ExternLoc,
+ TemplateLoc),
+ ParsingTemplateParams,
+ DeclEnd, AS_none);
+}
+
+SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {
+ if (TemplateParams)
+ return getTemplateParamsRange(TemplateParams->data(),
+ TemplateParams->size());
+
+ SourceRange R(TemplateLoc);
+ if (ExternLoc.isValid())
+ R.setBegin(ExternLoc);
+ return R;
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
new file mode 100644
index 0000000..a603c37
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -0,0 +1,1253 @@
+//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the tentative parsing portions of the Parser
+// interfaces, for ambiguity resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/ParsedTemplate.h"
+using namespace clang;
+
+/// isCXXDeclarationStatement - C++-specialized function that disambiguates
+/// between a declaration or an expression statement, when parsing function
+/// bodies. Returns true for declaration, false for expression.
+///
+/// declaration-statement:
+/// block-declaration
+///
+/// block-declaration:
+/// simple-declaration
+/// asm-definition
+/// namespace-alias-definition
+/// using-declaration
+/// using-directive
+/// [C++0x] static_assert-declaration
+///
+/// asm-definition:
+/// 'asm' '(' string-literal ')' ';'
+///
+/// namespace-alias-definition:
+/// 'namespace' identifier = qualified-namespace-specifier ';'
+///
+/// using-declaration:
+/// 'using' typename[opt] '::'[opt] nested-name-specifier
+/// unqualified-id ';'
+/// 'using' '::' unqualified-id ;
+///
+/// using-directive:
+/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt]
+/// namespace-name ';'
+///
+bool Parser::isCXXDeclarationStatement() {
+ switch (Tok.getKind()) {
+ // asm-definition
+ case tok::kw_asm:
+ // namespace-alias-definition
+ case tok::kw_namespace:
+ // using-declaration
+ // using-directive
+ case tok::kw_using:
+ // static_assert-declaration
+ case tok::kw_static_assert:
+ return true;
+ // simple-declaration
+ default:
+ return isCXXSimpleDeclaration();
+ }
+}
+
+/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+/// between a simple-declaration or an expression-statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+/// Returns false if the statement is disambiguated as expression.
+///
+/// simple-declaration:
+/// decl-specifier-seq init-declarator-list[opt] ';'
+///
+bool Parser::isCXXSimpleDeclaration() {
+ // C++ 6.8p1:
+ // There is an ambiguity in the grammar involving expression-statements and
+ // declarations: An expression-statement with a function-style explicit type
+ // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
+ // from a declaration where the first declarator starts with a '('. In those
+ // cases the statement is a declaration. [Note: To disambiguate, the whole
+ // statement might have to be examined to determine if it is an
+ // expression-statement or a declaration].
+
+ // C++ 6.8p3:
+ // The disambiguation is purely syntactic; that is, the meaning of the names
+ // occurring in such a statement, beyond whether they are type-names or not,
+ // is not generally used in or changed by the disambiguation. Class
+ // templates are instantiated as necessary to determine if a qualified name
+ // is a type-name. Disambiguation precedes parsing, and a statement
+ // disambiguated as a declaration may be an ill-formed declaration.
+
+ // We don't have to parse all of the decl-specifier-seq part. There's only
+ // an ambiguity if the first decl-specifier is
+ // simple-type-specifier/typename-specifier followed by a '(', which may
+ // indicate a function-style cast expression.
+ // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
+ // a case.
+
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+ // We need tentative parsing...
+
+ TentativeParsingAction PA(*this);
+ TPR = TryParseSimpleDeclaration();
+ PA.Revert();
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ return true;
+
+ // Declarations take precedence over expressions.
+ if (TPR == TPResult::Ambiguous())
+ TPR = TPResult::True();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+/// simple-declaration:
+/// decl-specifier-seq init-declarator-list[opt] ';'
+///
+Parser::TPResult Parser::TryParseSimpleDeclaration() {
+ // We know that we have a simple-type-specifier/typename-specifier followed
+ // by a '('.
+ assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
+
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+
+ TPResult TPR = TryParseInitDeclaratorList();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ if (Tok.isNot(tok::semi))
+ return TPResult::False();
+
+ return TPResult::Ambiguous();
+}
+
+/// init-declarator-list:
+/// init-declarator
+/// init-declarator-list ',' init-declarator
+///
+/// init-declarator:
+/// declarator initializer[opt]
+/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
+///
+/// initializer:
+/// '=' initializer-clause
+/// '(' expression-list ')'
+///
+/// initializer-clause:
+/// assignment-expression
+/// '{' initializer-list ','[opt] '}'
+/// '{' '}'
+///
+Parser::TPResult Parser::TryParseInitDeclaratorList() {
+ while (1) {
+ // declarator
+ TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // [GNU] simple-asm-expr[opt] attributes[opt]
+ if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ return TPResult::True();
+
+ // initializer[opt]
+ if (Tok.is(tok::l_paren)) {
+ // Parse through the parens.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+ } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
+ // MSVC and g++ won't examine the rest of declarators if '=' is
+ // encountered; they just conclude that we have a declaration.
+ // EDG parses the initializer completely, which is the proper behavior
+ // for this case.
+ //
+ // At present, Clang follows MSVC and g++, since the parser does not have
+ // the ability to parse an expression fully without recording the
+ // results of that parse.
+ // Also allow 'in' after on objective-c declaration as in:
+ // for (int (^b)(void) in array). Ideally this should be done in the
+ // context of parsing for-init-statement of a foreach statement only. But,
+ // in any other context 'in' is invalid after a declaration and parser
+ // issues the error regardless of outcome of this decision.
+ // FIXME. Change if above assumption does not hold.
+ return TPResult::True();
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // the comma.
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// isCXXConditionDeclaration - Disambiguates between a declaration or an
+/// expression for a condition of a if/switch/while/for statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// condition:
+/// expression
+/// type-specifier-seq declarator '=' assignment-expression
+/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+/// '=' assignment-expression
+///
+bool Parser::isCXXConditionDeclaration() {
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+ // We need tentative parsing...
+
+ TentativeParsingAction PA(*this);
+
+ // type-specifier-seq
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+
+ // declarator
+ TPR = TryParseDeclarator(false/*mayBeAbstract*/);
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ TPR = TPResult::True();
+
+ if (TPR == TPResult::Ambiguous()) {
+ // '='
+ // [GNU] simple-asm-expr[opt] attributes[opt]
+ if (Tok.is(tok::equal) ||
+ Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+ TPR = TPResult::True();
+ else
+ TPR = TPResult::False();
+ }
+
+ PA.Revert();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+ /// \brief Determine whether the next set of tokens contains a type-id.
+ ///
+ /// The context parameter states what context we're parsing right
+ /// now, which affects how this routine copes with the token
+ /// following the type-id. If the context is TypeIdInParens, we have
+ /// already parsed the '(' and we will cease lookahead when we hit
+ /// the corresponding ')'. If the context is
+ /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
+ /// before this template argument, and will cease lookahead when we
+ /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
+ /// and false for an expression. If during the disambiguation
+ /// process a parsing error is encountered, the function returns
+ /// true to let the declaration parsing code handle it.
+ ///
+ /// type-id:
+ /// type-specifier-seq abstract-declarator[opt]
+ ///
+bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
+
+ isAmbiguous = false;
+
+ // C++ 8.2p2:
+ // The ambiguity arising from the similarity between a function-style cast and
+ // a type-id can occur in different contexts. The ambiguity appears as a
+ // choice between a function-style cast expression and a declaration of a
+ // type. The resolution is that any construct that could possibly be a type-id
+ // in its syntactic context shall be considered a type-id.
+
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR != TPResult::False(); // Returns true for TPResult::True() or
+ // TPResult::Error().
+
+ // FIXME: Add statistics about the number of ambiguous statements encountered
+ // and how they were resolved (number of declarations+number of expressions).
+
+ // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+ // We need tentative parsing...
+
+ TentativeParsingAction PA(*this);
+
+ // type-specifier-seq
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+
+ // declarator
+ TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ TPR = TPResult::True();
+
+ if (TPR == TPResult::Ambiguous()) {
+ // We are supposed to be inside parens, so if after the abstract declarator
+ // we encounter a ')' this is a type-id, otherwise it's an expression.
+ if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
+ TPR = TPResult::True();
+ isAmbiguous = true;
+
+ // We are supposed to be inside a template argument, so if after
+ // the abstract declarator we encounter a '>', '>>' (in C++0x), or
+ // ',', this is a type-id. Otherwise, it's an expression.
+ } else if (Context == TypeIdAsTemplateArgument &&
+ (Tok.is(tok::greater) || Tok.is(tok::comma) ||
+ (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
+ TPR = TPResult::True();
+ isAmbiguous = true;
+
+ } else
+ TPR = TPResult::False();
+ }
+
+ PA.Revert();
+
+ assert(TPR == TPResult::True() || TPR == TPResult::False());
+ return TPR == TPResult::True();
+}
+
+/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
+/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
+/// performed that will simply return true if a [[ is seen. Currently C++ has no
+/// syntactical ambiguities from this check, but it may inhibit error recovery.
+/// If CheckClosing is true, a check is made for closing ]] brackets.
+///
+/// If given, After is set to the token after the attribute-specifier so that
+/// appropriate parsing decisions can be made; it is left untouched if false is
+/// returned.
+///
+/// FIXME: If an error is in the closing ]] brackets, the program assumes
+/// the absence of an attribute-specifier, which can cause very yucky errors
+/// to occur.
+///
+/// [C++0x] attribute-specifier:
+/// '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+/// attribute[opt]
+/// attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+/// attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+/// identifier
+/// attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+/// attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+/// identifier
+///
+/// [C++0x] attribute-argument-clause:
+/// '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+/// balanced-token
+/// balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+/// '(' balanced-token-seq ')'
+/// '[' balanced-token-seq ']'
+/// '{' balanced-token-seq '}'
+/// any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
+ tok::TokenKind *After) {
+ if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+ return false;
+
+ // No tentative parsing if we don't need to look for ]]
+ if (!CheckClosing && !getLang().ObjC1)
+ return true;
+
+ struct TentativeReverter {
+ TentativeParsingAction PA;
+
+ TentativeReverter (Parser& P)
+ : PA(P)
+ {}
+ ~TentativeReverter () {
+ PA.Revert();
+ }
+ } R(*this);
+
+ // Opening brackets were checked for above.
+ ConsumeBracket();
+ ConsumeBracket();
+
+ // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
+ SkipUntil(tok::r_square, false);
+
+ if (Tok.isNot(tok::r_square))
+ return false;
+ ConsumeBracket();
+
+ if (After)
+ *After = Tok.getKind();
+
+ return true;
+}
+
+/// declarator:
+/// direct-declarator
+/// ptr-operator declarator
+///
+/// direct-declarator:
+/// declarator-id
+/// direct-declarator '(' parameter-declaration-clause ')'
+/// cv-qualifier-seq[opt] exception-specification[opt]
+/// direct-declarator '[' constant-expression[opt] ']'
+/// '(' declarator ')'
+/// [GNU] '(' attributes declarator ')'
+///
+/// abstract-declarator:
+/// ptr-operator abstract-declarator[opt]
+/// direct-abstract-declarator
+/// ...
+///
+/// direct-abstract-declarator:
+/// direct-abstract-declarator[opt]
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+/// '(' abstract-declarator ')'
+///
+/// ptr-operator:
+/// '*' cv-qualifier-seq[opt]
+/// '&'
+/// [C++0x] '&&' [TODO]
+/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
+///
+/// cv-qualifier-seq:
+/// cv-qualifier cv-qualifier-seq[opt]
+///
+/// cv-qualifier:
+/// 'const'
+/// 'volatile'
+///
+/// declarator-id:
+/// '...'[opt] id-expression
+///
+/// id-expression:
+/// unqualified-id
+/// qualified-id [TODO]
+///
+/// unqualified-id:
+/// identifier
+/// operator-function-id [TODO]
+/// conversion-function-id [TODO]
+/// '~' class-name [TODO]
+/// template-id [TODO]
+///
+Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
+ bool mayHaveIdentifier) {
+ // declarator:
+ // direct-declarator
+ // ptr-operator declarator
+
+ while (1) {
+ if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
+ if (TryAnnotateCXXScopeToken(true))
+ return TPResult::Error();
+
+ if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
+ Tok.is(tok::ampamp) ||
+ (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
+ // ptr-operator
+ ConsumeToken();
+ while (Tok.is(tok::kw_const) ||
+ Tok.is(tok::kw_volatile) ||
+ Tok.is(tok::kw_restrict))
+ ConsumeToken();
+ } else {
+ break;
+ }
+ }
+
+ // direct-declarator:
+ // direct-abstract-declarator:
+ if (Tok.is(tok::ellipsis))
+ ConsumeToken();
+
+ if ((Tok.is(tok::identifier) ||
+ (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
+ mayHaveIdentifier) {
+ // declarator-id
+ if (Tok.is(tok::annot_cxxscope))
+ ConsumeToken();
+ ConsumeToken();
+ } else if (Tok.is(tok::l_paren)) {
+ ConsumeParen();
+ if (mayBeAbstract &&
+ (Tok.is(tok::r_paren) || // 'int()' is a function.
+ Tok.is(tok::ellipsis) || // 'int(...)' is a function.
+ isDeclarationSpecifier())) { // 'int(int)' is a function.
+ // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+ // exception-specification[opt]
+ TPResult TPR = TryParseFunctionDeclarator();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ } else {
+ // '(' declarator ')'
+ // '(' attributes declarator ')'
+ // '(' abstract-declarator ')'
+ if (Tok.is(tok::kw___attribute) ||
+ Tok.is(tok::kw___declspec) ||
+ Tok.is(tok::kw___cdecl) ||
+ Tok.is(tok::kw___stdcall) ||
+ Tok.is(tok::kw___fastcall) ||
+ Tok.is(tok::kw___thiscall))
+ return TPResult::True(); // attributes indicate declaration
+ TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ if (Tok.isNot(tok::r_paren))
+ return TPResult::False();
+ ConsumeParen();
+ }
+ } else if (!mayBeAbstract) {
+ return TPResult::False();
+ }
+
+ while (1) {
+ TPResult TPR(TPResult::Ambiguous());
+
+ // abstract-declarator: ...
+ if (Tok.is(tok::ellipsis))
+ ConsumeToken();
+
+ if (Tok.is(tok::l_paren)) {
+ // Check whether we have a function declarator or a possible ctor-style
+ // initializer that follows the declarator. Note that ctor-style
+ // initializers are not possible in contexts where abstract declarators
+ // are allowed.
+ if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/))
+ break;
+
+ // direct-declarator '(' parameter-declaration-clause ')'
+ // cv-qualifier-seq[opt] exception-specification[opt]
+ ConsumeParen();
+ TPR = TryParseFunctionDeclarator();
+ } else if (Tok.is(tok::l_square)) {
+ // direct-declarator '[' constant-expression[opt] ']'
+ // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
+ TPR = TryParseBracketDeclarator();
+ } else {
+ break;
+ }
+
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+ }
+
+ return TPResult::Ambiguous();
+}
+
+Parser::TPResult
+Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
+ switch (Kind) {
+ // Obviously starts an expression.
+ case tok::numeric_constant:
+ case tok::char_constant:
+ case tok::string_literal:
+ case tok::wide_string_literal:
+ case tok::l_square:
+ case tok::l_paren:
+ case tok::amp:
+ case tok::ampamp:
+ case tok::star:
+ case tok::plus:
+ case tok::plusplus:
+ case tok::minus:
+ case tok::minusminus:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::kw_sizeof:
+ case tok::kw___func__:
+ case tok::kw_const_cast:
+ case tok::kw_delete:
+ case tok::kw_dynamic_cast:
+ case tok::kw_false:
+ case tok::kw_new:
+ case tok::kw_operator:
+ case tok::kw_reinterpret_cast:
+ case tok::kw_static_cast:
+ case tok::kw_this:
+ case tok::kw_throw:
+ case tok::kw_true:
+ case tok::kw_typeid:
+ case tok::kw_alignof:
+ case tok::kw_noexcept:
+ case tok::kw_nullptr:
+ case tok::kw___null:
+ case tok::kw___alignof:
+ case tok::kw___builtin_choose_expr:
+ case tok::kw___builtin_offsetof:
+ case tok::kw___builtin_types_compatible_p:
+ case tok::kw___builtin_va_arg:
+ case tok::kw___imag:
+ case tok::kw___real:
+ case tok::kw___FUNCTION__:
+ case tok::kw___PRETTY_FUNCTION__:
+ case tok::kw___has_nothrow_assign:
+ case tok::kw___has_nothrow_copy:
+ case tok::kw___has_nothrow_constructor:
+ case tok::kw___has_trivial_assign:
+ case tok::kw___has_trivial_copy:
+ case tok::kw___has_trivial_constructor:
+ case tok::kw___has_trivial_destructor:
+ case tok::kw___has_virtual_destructor:
+ case tok::kw___is_abstract:
+ case tok::kw___is_base_of:
+ case tok::kw___is_class:
+ case tok::kw___is_convertible_to:
+ case tok::kw___is_empty:
+ case tok::kw___is_enum:
+ case tok::kw___is_pod:
+ case tok::kw___is_polymorphic:
+ case tok::kw___is_union:
+ case tok::kw___is_literal:
+ case tok::kw___uuidof:
+ return TPResult::True();
+
+ // Obviously starts a type-specifier-seq:
+ case tok::kw_char:
+ case tok::kw_const:
+ case tok::kw_double:
+ case tok::kw_enum:
+ case tok::kw_float:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw_restrict:
+ case tok::kw_short:
+ case tok::kw_signed:
+ case tok::kw_struct:
+ case tok::kw_union:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_volatile:
+ case tok::kw__Bool:
+ case tok::kw__Complex:
+ case tok::kw_class:
+ case tok::kw_typename:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_decltype:
+ case tok::kw_thread_local:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___thread:
+ case tok::kw_typeof:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___vector:
+ case tok::kw___pixel:
+ return TPResult::False();
+
+ default:
+ break;
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
+/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
+/// be either a decl-specifier or a function-style cast, and TPResult::Error()
+/// if a parsing error was found and reported.
+///
+/// decl-specifier:
+/// storage-class-specifier
+/// type-specifier
+/// function-specifier
+/// 'friend'
+/// 'typedef'
+/// [C++0x] 'constexpr'
+/// [GNU] attributes declaration-specifiers[opt]
+///
+/// storage-class-specifier:
+/// 'register'
+/// 'static'
+/// 'extern'
+/// 'mutable'
+/// 'auto'
+/// [GNU] '__thread'
+///
+/// function-specifier:
+/// 'inline'
+/// 'virtual'
+/// 'explicit'
+///
+/// typedef-name:
+/// identifier
+///
+/// type-specifier:
+/// simple-type-specifier
+/// class-specifier
+/// enum-specifier
+/// elaborated-type-specifier
+/// typename-specifier
+/// cv-qualifier
+///
+/// simple-type-specifier:
+/// '::'[opt] nested-name-specifier[opt] type-name
+/// '::'[opt] nested-name-specifier 'template'
+/// simple-template-id [TODO]
+/// 'char'
+/// 'wchar_t'
+/// 'bool'
+/// 'short'
+/// 'int'
+/// 'long'
+/// 'signed'
+/// 'unsigned'
+/// 'float'
+/// 'double'
+/// 'void'
+/// [GNU] typeof-specifier
+/// [GNU] '_Complex'
+/// [C++0x] 'auto' [TODO]
+/// [C++0x] 'decltype' ( expression )
+///
+/// type-name:
+/// class-name
+/// enum-name
+/// typedef-name
+///
+/// elaborated-type-specifier:
+/// class-key '::'[opt] nested-name-specifier[opt] identifier
+/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
+/// simple-template-id
+/// 'enum' '::'[opt] nested-name-specifier[opt] identifier
+///
+/// enum-name:
+/// identifier
+///
+/// enum-specifier:
+/// 'enum' identifier[opt] '{' enumerator-list[opt] '}'
+/// 'enum' identifier[opt] '{' enumerator-list ',' '}'
+///
+/// class-specifier:
+/// class-head '{' member-specification[opt] '}'
+///
+/// class-head:
+/// class-key identifier[opt] base-clause[opt]
+/// class-key nested-name-specifier identifier base-clause[opt]
+/// class-key nested-name-specifier[opt] simple-template-id
+/// base-clause[opt]
+///
+/// class-key:
+/// 'class'
+/// 'struct'
+/// 'union'
+///
+/// cv-qualifier:
+/// 'const'
+/// 'volatile'
+/// [GNU] restrict
+///
+Parser::TPResult Parser::isCXXDeclarationSpecifier() {
+ switch (Tok.getKind()) {
+ case tok::identifier: // foo::bar
+ // Check for need to substitute AltiVec __vector keyword
+ // for "vector" identifier.
+ if (TryAltiVecVectorToken())
+ return TPResult::True();
+ // Fall through.
+ case tok::kw_typename: // typename T::type
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ if (Tok.is(tok::identifier))
+ return TPResult::False();
+ return isCXXDeclarationSpecifier();
+
+ case tok::coloncolon: { // ::foo::bar
+ const Token &Next = NextToken();
+ if (Next.is(tok::kw_new) || // ::new
+ Next.is(tok::kw_delete)) // ::delete
+ return TPResult::False();
+
+ // Annotate typenames and C++ scope specifiers. If we get one, just
+ // recurse to handle whatever we get.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ return isCXXDeclarationSpecifier();
+ }
+
+ // decl-specifier:
+ // storage-class-specifier
+ // type-specifier
+ // function-specifier
+ // 'friend'
+ // 'typedef'
+ // 'constexpr'
+ case tok::kw_friend:
+ case tok::kw_typedef:
+ case tok::kw_constexpr:
+ // storage-class-specifier
+ case tok::kw_register:
+ case tok::kw_static:
+ case tok::kw_extern:
+ case tok::kw_mutable:
+ case tok::kw_auto:
+ case tok::kw___thread:
+ // function-specifier
+ case tok::kw_inline:
+ case tok::kw_virtual:
+ case tok::kw_explicit:
+
+ // type-specifier:
+ // simple-type-specifier
+ // class-specifier
+ // enum-specifier
+ // elaborated-type-specifier
+ // typename-specifier
+ // cv-qualifier
+
+ // class-specifier
+ // elaborated-type-specifier
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+ // cv-qualifier
+ case tok::kw_const:
+ case tok::kw_volatile:
+
+ // GNU
+ case tok::kw_restrict:
+ case tok::kw__Complex:
+ case tok::kw___attribute:
+ return TPResult::True();
+
+ // Microsoft
+ case tok::kw___declspec:
+ case tok::kw___cdecl:
+ case tok::kw___stdcall:
+ case tok::kw___fastcall:
+ case tok::kw___thiscall:
+ case tok::kw___w64:
+ case tok::kw___ptr64:
+ case tok::kw___forceinline:
+ return TPResult::True();
+
+ // Borland
+ case tok::kw___pascal:
+ return TPResult::True();
+
+ // AltiVec
+ case tok::kw___vector:
+ return TPResult::True();
+
+ case tok::annot_template_id: {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind != TNK_Type_template)
+ return TPResult::False();
+ CXXScopeSpec SS;
+ AnnotateTemplateIdTokenAsType(&SS);
+ assert(Tok.is(tok::annot_typename));
+ goto case_typename;
+ }
+
+ case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
+ // We've already annotated a scope; try to annotate a type.
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ if (!Tok.is(tok::annot_typename))
+ return TPResult::False();
+ // If that succeeded, fallthrough into the generic simple-type-id case.
+
+ // The ambiguity resides in a simple-type-specifier/typename-specifier
+ // followed by a '('. The '(' could either be the start of:
+ //
+ // direct-declarator:
+ // '(' declarator ')'
+ //
+ // direct-abstract-declarator:
+ // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+ // exception-specification[opt]
+ // '(' abstract-declarator ')'
+ //
+ // or part of a function-style cast expression:
+ //
+ // simple-type-specifier '(' expression-list[opt] ')'
+ //
+
+ // simple-type-specifier:
+
+ case tok::annot_typename:
+ case_typename:
+ // In Objective-C, we might have a protocol-qualified type.
+ if (getLang().ObjC1 && NextToken().is(tok::less)) {
+ // Tentatively parse the
+ TentativeParsingAction PA(*this);
+ ConsumeToken(); // The type token
+
+ TPResult TPR = TryParseProtocolQualifiers();
+ bool isFollowedByParen = Tok.is(tok::l_paren);
+
+ PA.Revert();
+
+ if (TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (isFollowedByParen)
+ return TPResult::Ambiguous();
+
+ return TPResult::True();
+ }
+
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_bool:
+ case tok::kw_short:
+ case tok::kw_int:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_void:
+ if (NextToken().is(tok::l_paren))
+ return TPResult::Ambiguous();
+
+ if (isStartOfObjCClassMessageMissingOpenBracket())
+ return TPResult::False();
+
+ return TPResult::True();
+
+ // GNU typeof support.
+ case tok::kw_typeof: {
+ if (NextToken().isNot(tok::l_paren))
+ return TPResult::True();
+
+ TentativeParsingAction PA(*this);
+
+ TPResult TPR = TryParseTypeofSpecifier();
+ bool isFollowedByParen = Tok.is(tok::l_paren);
+
+ PA.Revert();
+
+ if (TPR == TPResult::Error())
+ return TPResult::Error();
+
+ if (isFollowedByParen)
+ return TPResult::Ambiguous();
+
+ return TPResult::True();
+ }
+
+ // C++0x decltype support.
+ case tok::kw_decltype:
+ return TPResult::True();
+
+ default:
+ return TPResult::False();
+ }
+}
+
+/// [GNU] typeof-specifier:
+/// 'typeof' '(' expressions ')'
+/// 'typeof' '(' type-name ')'
+///
+Parser::TPResult Parser::TryParseTypeofSpecifier() {
+ assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
+ ConsumeToken();
+
+ assert(Tok.is(tok::l_paren) && "Expected '('");
+ // Parse through the parens after 'typeof'.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+
+ return TPResult::Ambiguous();
+}
+
+/// [ObjC] protocol-qualifiers:
+//// '<' identifier-list '>'
+Parser::TPResult Parser::TryParseProtocolQualifiers() {
+ assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
+ ConsumeToken();
+ do {
+ if (Tok.isNot(tok::identifier))
+ return TPResult::Error();
+ ConsumeToken();
+
+ if (Tok.is(tok::comma)) {
+ ConsumeToken();
+ continue;
+ }
+
+ if (Tok.is(tok::greater)) {
+ ConsumeToken();
+ return TPResult::Ambiguous();
+ }
+ } while (false);
+
+ return TPResult::Error();
+}
+
+Parser::TPResult Parser::TryParseDeclarationSpecifier() {
+ TPResult TPR = isCXXDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ if (Tok.is(tok::kw_typeof))
+ TryParseTypeofSpecifier();
+ else {
+ ConsumeToken();
+
+ if (getLang().ObjC1 && Tok.is(tok::less))
+ TryParseProtocolQualifiers();
+ }
+
+ assert(Tok.is(tok::l_paren) && "Expected '('!");
+ return TPResult::Ambiguous();
+}
+
+/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+/// a constructor-style initializer, when parsing declaration statements.
+/// Returns true for function declarator and false for constructor-style
+/// initializer.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+///
+bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) {
+
+ // C++ 8.2p1:
+ // The ambiguity arising from the similarity between a function-style cast and
+ // a declaration mentioned in 6.8 can also occur in the context of a
+ // declaration. In that context, the choice is between a function declaration
+ // with a redundant set of parentheses around a parameter name and an object
+ // declaration with a function-style cast as the initializer. Just as for the
+ // ambiguities mentioned in 6.8, the resolution is to consider any construct
+ // that could possibly be a declaration a declaration.
+
+ TentativeParsingAction PA(*this);
+
+ ConsumeParen();
+ TPResult TPR = TryParseParameterDeclarationClause();
+ if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+ TPR = TPResult::False();
+
+ SourceLocation TPLoc = Tok.getLocation();
+ PA.Revert();
+
+ // In case of an error, let the declaration parsing code handle it.
+ if (TPR == TPResult::Error())
+ return true;
+
+ if (TPR == TPResult::Ambiguous()) {
+ // Function declarator has precedence over constructor-style initializer.
+ // Emit a warning just in case the author intended a variable definition.
+ if (warnIfAmbiguous)
+ Diag(Tok, diag::warn_parens_disambiguated_as_function_decl)
+ << SourceRange(Tok.getLocation(), TPLoc);
+ return true;
+ }
+
+ return TPR == TPResult::True();
+}
+
+/// parameter-declaration-clause:
+/// parameter-declaration-list[opt] '...'[opt]
+/// parameter-declaration-list ',' '...'
+///
+/// parameter-declaration-list:
+/// parameter-declaration
+/// parameter-declaration-list ',' parameter-declaration
+///
+/// parameter-declaration:
+/// decl-specifier-seq declarator attributes[opt]
+/// decl-specifier-seq declarator attributes[opt] '=' assignment-expression
+/// decl-specifier-seq abstract-declarator[opt] attributes[opt]
+/// decl-specifier-seq abstract-declarator[opt] attributes[opt]
+/// '=' assignment-expression
+///
+Parser::TPResult Parser::TryParseParameterDeclarationClause() {
+
+ if (Tok.is(tok::r_paren))
+ return TPResult::True();
+
+ // parameter-declaration-list[opt] '...'[opt]
+ // parameter-declaration-list ',' '...'
+ //
+ // parameter-declaration-list:
+ // parameter-declaration
+ // parameter-declaration-list ',' parameter-declaration
+ //
+ while (1) {
+ // '...'[opt]
+ if (Tok.is(tok::ellipsis)) {
+ ConsumeToken();
+ return TPResult::True(); // '...' is a sign of a function declarator.
+ }
+
+ ParsedAttributes attrs;
+ MaybeParseMicrosoftAttributes(attrs);
+
+ // decl-specifier-seq
+ TPResult TPR = TryParseDeclarationSpecifier();
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // declarator
+ // abstract-declarator[opt]
+ TPR = TryParseDeclarator(true/*mayBeAbstract*/);
+ if (TPR != TPResult::Ambiguous())
+ return TPR;
+
+ // [GNU] attributes[opt]
+ if (Tok.is(tok::kw___attribute))
+ return TPResult::True();
+
+ if (Tok.is(tok::equal)) {
+ // '=' assignment-expression
+ // Parse through assignment-expression.
+ tok::TokenKind StopToks[2] ={ tok::comma, tok::r_paren };
+ if (!SkipUntil(StopToks, 2, true/*StopAtSemi*/, true/*DontConsume*/))
+ return TPResult::Error();
+ }
+
+ if (Tok.is(tok::ellipsis)) {
+ ConsumeToken();
+ return TPResult::True(); // '...' is a sign of a function declarator.
+ }
+
+ if (Tok.isNot(tok::comma))
+ break;
+ ConsumeToken(); // the comma.
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
+/// parsing as a function declarator.
+/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
+/// return TPResult::Ambiguous(), otherwise it will return either False() or
+/// Error().
+///
+/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
+/// exception-specification[opt]
+///
+/// exception-specification:
+/// 'throw' '(' type-id-list[opt] ')'
+///
+Parser::TPResult Parser::TryParseFunctionDeclarator() {
+
+ // The '(' is already parsed.
+
+ TPResult TPR = TryParseParameterDeclarationClause();
+ if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
+ TPR = TPResult::False();
+
+ if (TPR == TPResult::False() || TPR == TPResult::Error())
+ return TPR;
+
+ // Parse through the parens.
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+
+ // cv-qualifier-seq
+ while (Tok.is(tok::kw_const) ||
+ Tok.is(tok::kw_volatile) ||
+ Tok.is(tok::kw_restrict) )
+ ConsumeToken();
+
+ // ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+ ConsumeToken();
+
+ // exception-specification
+ if (Tok.is(tok::kw_throw)) {
+ ConsumeToken();
+ if (Tok.isNot(tok::l_paren))
+ return TPResult::Error();
+
+ // Parse through the parens after 'throw'.
+ ConsumeParen();
+ if (!SkipUntil(tok::r_paren))
+ return TPResult::Error();
+ }
+
+ return TPResult::Ambiguous();
+}
+
+/// '[' constant-expression[opt] ']'
+///
+Parser::TPResult Parser::TryParseBracketDeclarator() {
+ ConsumeBracket();
+ if (!SkipUntil(tok::r_square))
+ return TPResult::Error();
+
+ return TPResult::Ambiguous();
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
new file mode 100644
index 0000000..a50763a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -0,0 +1,1272 @@
+//===--- Parser.cpp - C Language Family Parser ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Parser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "llvm/Support/raw_ostream.h"
+#include "RAIIObjectsForParser.h"
+#include "ParsePragma.h"
+using namespace clang;
+
+Parser::Parser(Preprocessor &pp, Sema &actions)
+ : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
+ GreaterThanIsOperator(true), ColonIsSacred(false),
+ InMessageExpression(false), TemplateParameterDepth(0) {
+ Tok.setKind(tok::eof);
+ Actions.CurScope = 0;
+ NumCachedScopes = 0;
+ ParenCount = BracketCount = BraceCount = 0;
+ ObjCImpDecl = 0;
+
+ // Add #pragma handlers. These are removed and destroyed in the
+ // destructor.
+ AlignHandler.reset(new PragmaAlignHandler(actions));
+ PP.AddPragmaHandler(AlignHandler.get());
+
+ GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions));
+ PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
+
+ OptionsHandler.reset(new PragmaOptionsHandler(actions));
+ PP.AddPragmaHandler(OptionsHandler.get());
+
+ PackHandler.reset(new PragmaPackHandler(actions));
+ PP.AddPragmaHandler(PackHandler.get());
+
+ UnusedHandler.reset(new PragmaUnusedHandler(actions, *this));
+ PP.AddPragmaHandler(UnusedHandler.get());
+
+ WeakHandler.reset(new PragmaWeakHandler(actions));
+ PP.AddPragmaHandler(WeakHandler.get());
+
+ FPContractHandler.reset(new PragmaFPContractHandler(actions, *this));
+ PP.AddPragmaHandler("STDC", FPContractHandler.get());
+
+ if (getLang().OpenCL) {
+ OpenCLExtensionHandler.reset(
+ new PragmaOpenCLExtensionHandler(actions, *this));
+ PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+
+ PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
+ }
+
+ PP.setCodeCompletionHandler(*this);
+}
+
+/// If a crash happens while the parser is active, print out a line indicating
+/// what the current token is.
+void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
+ const Token &Tok = P.getCurToken();
+ if (Tok.is(tok::eof)) {
+ OS << "<eof> parser at end of file\n";
+ return;
+ }
+
+ if (Tok.getLocation().isInvalid()) {
+ OS << "<unknown> parser at unknown location\n";
+ return;
+ }
+
+ const Preprocessor &PP = P.getPreprocessor();
+ Tok.getLocation().print(OS, PP.getSourceManager());
+ if (Tok.isAnnotation())
+ OS << ": at annotation token \n";
+ else
+ OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";
+}
+
+
+DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+}
+
+DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {
+ return Diag(Tok.getLocation(), DiagID);
+}
+
+/// \brief Emits a diagnostic suggesting parentheses surrounding a
+/// given range.
+///
+/// \param Loc The location where we'll emit the diagnostic.
+/// \param Loc The kind of diagnostic to emit.
+/// \param ParenRange Source range enclosing code that should be parenthesized.
+void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
+ SourceRange ParenRange) {
+ SourceLocation EndLoc = PP.getLocForEndOfToken(ParenRange.getEnd());
+ if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just dig the
+ // warning/error and return.
+ Diag(Loc, DK);
+ return;
+ }
+
+ Diag(Loc, DK)
+ << FixItHint::CreateInsertion(ParenRange.getBegin(), "(")
+ << FixItHint::CreateInsertion(EndLoc, ")");
+}
+
+/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
+/// this helper function matches and consumes the specified RHS token if
+/// present. If not present, it emits the specified diagnostic indicating
+/// that the parser failed to match the RHS of the token at LHSLoc. LHSName
+/// should be the name of the unmatched LHS token.
+SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
+ SourceLocation LHSLoc) {
+
+ if (Tok.is(RHSTok))
+ return ConsumeAnyToken();
+
+ SourceLocation R = Tok.getLocation();
+ const char *LHSName = "unknown";
+ diag::kind DID = diag::err_parse_error;
+ switch (RHSTok) {
+ default: break;
+ case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
+ case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
+ case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
+ case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
+ case tok::greatergreatergreater:
+ LHSName = "<<<"; DID = diag::err_expected_ggg; break;
+ }
+ Diag(Tok, DID);
+ Diag(LHSLoc, diag::note_matching) << LHSName;
+ SkipUntil(RHSTok);
+ return R;
+}
+
+static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
+ switch (ExpectedTok) {
+ case tok::semi: return Tok.is(tok::colon); // : for ;
+ default: return false;
+ }
+}
+
+/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+/// input. If so, it is consumed and false is returned.
+///
+/// If the input is malformed, this emits the specified diagnostic. Next, if
+/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
+/// returned.
+bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
+ const char *Msg, tok::TokenKind SkipToTok) {
+ if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
+ ConsumeAnyToken();
+ return false;
+ }
+
+ // Detect common single-character typos and resume.
+ if (IsCommonTypo(ExpectedTok, Tok)) {
+ SourceLocation Loc = Tok.getLocation();
+ Diag(Loc, DiagID)
+ << Msg
+ << FixItHint::CreateReplacement(SourceRange(Loc),
+ getTokenSimpleSpelling(ExpectedTok));
+ ConsumeAnyToken();
+
+ // Pretend there wasn't a problem.
+ return false;
+ }
+
+ const char *Spelling = 0;
+ SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
+ if (EndLoc.isValid() &&
+ (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
+ // Show what code to insert to fix this problem.
+ Diag(EndLoc, DiagID)
+ << Msg
+ << FixItHint::CreateInsertion(EndLoc, Spelling);
+ } else
+ Diag(Tok, DiagID) << Msg;
+
+ if (SkipToTok != tok::unknown)
+ SkipUntil(SkipToTok);
+ return true;
+}
+
+bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
+ if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) {
+ ConsumeAnyToken();
+ return false;
+ }
+
+ if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) &&
+ NextToken().is(tok::semi)) {
+ Diag(Tok, diag::err_extraneous_token_before_semi)
+ << PP.getSpelling(Tok)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+ ConsumeAnyToken(); // The ')' or ']'.
+ ConsumeToken(); // The ';'.
+ return false;
+ }
+
+ return ExpectAndConsume(tok::semi, DiagID);
+}
+
+//===----------------------------------------------------------------------===//
+// Error recovery.
+//===----------------------------------------------------------------------===//
+
+/// SkipUntil - Read tokens until we get to the specified token, then consume
+/// it (unless DontConsume is true). Because we cannot guarantee that the
+/// token will ever occur, this skips to the next token, or to some likely
+/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
+/// character.
+///
+/// If SkipUntil finds the specified token, it returns true, otherwise it
+/// returns false.
+bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
+ bool StopAtSemi, bool DontConsume,
+ bool StopAtCodeCompletion) {
+ // We always want this function to skip at least one token if the first token
+ // isn't T and if not at EOF.
+ bool isFirstTokenSkipped = true;
+ while (1) {
+ // If we found one of the tokens, stop and return true.
+ for (unsigned i = 0; i != NumToks; ++i) {
+ if (Tok.is(Toks[i])) {
+ if (DontConsume) {
+ // Noop, don't consume the token.
+ } else {
+ ConsumeAnyToken();
+ }
+ return true;
+ }
+ }
+
+ switch (Tok.getKind()) {
+ case tok::eof:
+ // Ran out of tokens.
+ return false;
+
+ case tok::code_completion:
+ if (!StopAtCodeCompletion)
+ ConsumeToken();
+ return false;
+
+ case tok::l_paren:
+ // Recursively skip properly-nested parens.
+ ConsumeParen();
+ SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion);
+ break;
+ case tok::l_square:
+ // Recursively skip properly-nested square brackets.
+ ConsumeBracket();
+ SkipUntil(tok::r_square, false, false, StopAtCodeCompletion);
+ break;
+ case tok::l_brace:
+ // Recursively skip properly-nested braces.
+ ConsumeBrace();
+ SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion);
+ break;
+
+ // Okay, we found a ']' or '}' or ')', which we think should be balanced.
+ // Since the user wasn't looking for this token (if they were, it would
+ // already be handled), this isn't balanced. If there is a LHS token at a
+ // higher level, we will assume that this matches the unbalanced token
+ // and return it. Otherwise, this is a spurious RHS token, which we skip.
+ case tok::r_paren:
+ if (ParenCount && !isFirstTokenSkipped)
+ return false; // Matches something.
+ ConsumeParen();
+ break;
+ case tok::r_square:
+ if (BracketCount && !isFirstTokenSkipped)
+ return false; // Matches something.
+ ConsumeBracket();
+ break;
+ case tok::r_brace:
+ if (BraceCount && !isFirstTokenSkipped)
+ return false; // Matches something.
+ ConsumeBrace();
+ break;
+
+ case tok::string_literal:
+ case tok::wide_string_literal:
+ ConsumeStringToken();
+ break;
+ case tok::semi:
+ if (StopAtSemi)
+ return false;
+ // FALL THROUGH.
+ default:
+ // Skip this token.
+ ConsumeToken();
+ break;
+ }
+ isFirstTokenSkipped = false;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Scope manipulation
+//===----------------------------------------------------------------------===//
+
+/// EnterScope - Start a new scope.
+void Parser::EnterScope(unsigned ScopeFlags) {
+ if (NumCachedScopes) {
+ Scope *N = ScopeCache[--NumCachedScopes];
+ N->Init(getCurScope(), ScopeFlags);
+ Actions.CurScope = N;
+ } else {
+ Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags);
+ }
+}
+
+/// ExitScope - Pop a scope off the scope stack.
+void Parser::ExitScope() {
+ assert(getCurScope() && "Scope imbalance!");
+
+ // Inform the actions module that this scope is going away if there are any
+ // decls in it.
+ if (!getCurScope()->decl_empty())
+ Actions.ActOnPopScope(Tok.getLocation(), getCurScope());
+
+ Scope *OldScope = getCurScope();
+ Actions.CurScope = OldScope->getParent();
+
+ if (NumCachedScopes == ScopeCacheSize)
+ delete OldScope;
+ else
+ ScopeCache[NumCachedScopes++] = OldScope;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// C99 6.9: External Definitions.
+//===----------------------------------------------------------------------===//
+
+Parser::~Parser() {
+ // If we still have scopes active, delete the scope tree.
+ delete getCurScope();
+ Actions.CurScope = 0;
+
+ // Free the scope cache.
+ for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
+ delete ScopeCache[i];
+
+ // Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(AlignHandler.get());
+ AlignHandler.reset();
+ PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
+ GCCVisibilityHandler.reset();
+ PP.RemovePragmaHandler(OptionsHandler.get());
+ OptionsHandler.reset();
+ PP.RemovePragmaHandler(PackHandler.get());
+ PackHandler.reset();
+ PP.RemovePragmaHandler(UnusedHandler.get());
+ UnusedHandler.reset();
+ PP.RemovePragmaHandler(WeakHandler.get());
+ WeakHandler.reset();
+
+ if (getLang().OpenCL) {
+ PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
+ OpenCLExtensionHandler.reset();
+ PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
+ }
+
+ PP.RemovePragmaHandler("STDC", FPContractHandler.get());
+ FPContractHandler.reset();
+ PP.clearCodeCompletionHandler();
+}
+
+/// Initialize - Warm up the parser.
+///
+void Parser::Initialize() {
+ // Create the translation unit scope. Install it as the current scope.
+ assert(getCurScope() == 0 && "A scope is already active?");
+ EnterScope(Scope::DeclScope);
+ Actions.ActOnTranslationUnitScope(getCurScope());
+
+ // Prime the lexer look-ahead.
+ ConsumeToken();
+
+ if (Tok.is(tok::eof) &&
+ !getLang().CPlusPlus) // Empty source file is an extension in C
+ Diag(Tok, diag::ext_empty_source_file);
+
+ // Initialization for Objective-C context sensitive keywords recognition.
+ // Referenced in Parser::ParseObjCTypeQualifierList.
+ if (getLang().ObjC1) {
+ ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in");
+ ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out");
+ ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout");
+ ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");
+ ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
+ ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
+ }
+
+ Ident_final = 0;
+ Ident_override = 0;
+
+ Ident_super = &PP.getIdentifierTable().get("super");
+
+ if (getLang().AltiVec) {
+ Ident_vector = &PP.getIdentifierTable().get("vector");
+ Ident_pixel = &PP.getIdentifierTable().get("pixel");
+ }
+}
+
+/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
+/// action tells us to. This returns true if the EOF was encountered.
+bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+
+ while (Tok.is(tok::annot_pragma_unused))
+ HandlePragmaUnused();
+
+ Result = DeclGroupPtrTy();
+ if (Tok.is(tok::eof)) {
+ Actions.ActOnEndOfTranslationUnit();
+ return true;
+ }
+
+ ParsedAttributesWithRange attrs;
+ MaybeParseCXX0XAttributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+
+ Result = ParseExternalDeclaration(attrs);
+ return false;
+}
+
+/// ParseTranslationUnit:
+/// translation-unit: [C99 6.9]
+/// external-declaration
+/// translation-unit external-declaration
+void Parser::ParseTranslationUnit() {
+ Initialize();
+
+ DeclGroupPtrTy Res;
+ while (!ParseTopLevelDecl(Res))
+ /*parse them all*/;
+
+ ExitScope();
+ assert(getCurScope() == 0 && "Scope imbalance!");
+}
+
+/// ParseExternalDeclaration:
+///
+/// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl]
+/// function-definition
+/// declaration
+/// [C++0x] empty-declaration
+/// [GNU] asm-definition
+/// [GNU] __extension__ external-declaration
+/// [OBJC] objc-class-definition
+/// [OBJC] objc-class-declaration
+/// [OBJC] objc-alias-declaration
+/// [OBJC] objc-protocol-definition
+/// [OBJC] objc-method-definition
+/// [OBJC] @end
+/// [C++] linkage-specification
+/// [GNU] asm-definition:
+/// simple-asm-expr ';'
+///
+/// [C++0x] empty-declaration:
+/// ';'
+///
+/// [C++0x/GNU] 'extern' 'template' declaration
+Parser::DeclGroupPtrTy
+Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS) {
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+
+ Decl *SingleDecl = 0;
+ switch (Tok.getKind()) {
+ case tok::semi:
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_top_level_semi)
+ << FixItHint::CreateRemoval(Tok.getLocation());
+
+ ConsumeToken();
+ // TODO: Invoke action for top-level semicolon.
+ return DeclGroupPtrTy();
+ case tok::r_brace:
+ Diag(Tok, diag::err_expected_external_declaration);
+ ConsumeBrace();
+ return DeclGroupPtrTy();
+ case tok::eof:
+ Diag(Tok, diag::err_expected_external_declaration);
+ return DeclGroupPtrTy();
+ case tok::kw___extension__: {
+ // __extension__ silences extension warnings in the subexpression.
+ ExtensionRAIIObject O(Diags); // Use RAII to do this.
+ ConsumeToken();
+ return ParseExternalDeclaration(attrs);
+ }
+ case tok::kw_asm: {
+ ProhibitAttributes(attrs);
+
+ ExprResult Result(ParseSimpleAsm());
+
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ "top-level asm block");
+
+ if (Result.isInvalid())
+ return DeclGroupPtrTy();
+ SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), Result.get());
+ break;
+ }
+ case tok::at:
+ // @ is not a legal token unless objc is enabled, no need to check for ObjC.
+ /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like
+ /// @class foo, bar;
+ SingleDecl = ParseObjCAtDirectives();
+ break;
+ case tok::minus:
+ case tok::plus:
+ if (!getLang().ObjC1) {
+ Diag(Tok, diag::err_expected_external_declaration);
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
+ SingleDecl = ParseObjCMethodDefinition();
+ break;
+ case tok::code_completion:
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
+ ObjCImpDecl? Sema::PCC_ObjCImplementation
+ : Sema::PCC_Namespace);
+ ConsumeCodeCompletionToken();
+ return ParseExternalDeclaration(attrs);
+ case tok::kw_using:
+ case tok::kw_namespace:
+ case tok::kw_typedef:
+ case tok::kw_template:
+ case tok::kw_export: // As in 'export template'
+ case tok::kw_static_assert:
+ // A function definition cannot start with a these keywords.
+ {
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+
+ case tok::kw_static:
+ // Parse (then ignore) 'static' prior to a template instantiation. This is
+ // a GCC extension that we intentionally do not support.
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
+ Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
+ << 0;
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+ goto dont_know;
+
+ case tok::kw_inline:
+ if (getLang().CPlusPlus) {
+ tok::TokenKind NextKind = NextToken().getKind();
+
+ // Inline namespaces. Allowed as an extension even in C++03.
+ if (NextKind == tok::kw_namespace) {
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+
+ // Parse (then ignore) 'inline' prior to a template instantiation. This is
+ // a GCC extension that we intentionally do not support.
+ if (NextKind == tok::kw_template) {
+ Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored)
+ << 1;
+ SourceLocation DeclEnd;
+ StmtVector Stmts(Actions);
+ return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs);
+ }
+ }
+ goto dont_know;
+
+ case tok::kw_extern:
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
+ // Extern templates
+ SourceLocation ExternLoc = ConsumeToken();
+ SourceLocation TemplateLoc = ConsumeToken();
+ SourceLocation DeclEnd;
+ return Actions.ConvertDeclToDeclGroup(
+ ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
+ }
+ // FIXME: Detect C++ linkage specifications here?
+ goto dont_know;
+
+ default:
+ dont_know:
+ // We can't tell whether this is a function-definition or declaration yet.
+ if (DS) {
+ DS->takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(*DS);
+ } else {
+ return ParseDeclarationOrFunctionDefinition(attrs);
+ }
+ }
+
+ // This routine returns a DeclGroup, if the thing we parsed only contains a
+ // single decl, convert it now.
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
+}
+
+/// \brief Determine whether the current token, if it occurs after a
+/// declarator, continues a declaration or declaration list.
+bool Parser::isDeclarationAfterDeclarator() const {
+ return Tok.is(tok::equal) || // int X()= -> not a function def
+ Tok.is(tok::comma) || // int X(), -> not a function def
+ Tok.is(tok::semi) || // int X(); -> not a function def
+ Tok.is(tok::kw_asm) || // int X() __asm__ -> not a function def
+ Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def
+ (getLang().CPlusPlus &&
+ Tok.is(tok::l_paren)); // int X(0) -> not a function def [C++]
+}
+
+/// \brief Determine whether the current token, if it occurs after a
+/// declarator, indicates the start of a function definition.
+bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
+ assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator");
+ if (Tok.is(tok::l_brace)) // int X() {}
+ return true;
+
+ // Handle K&R C argument lists: int X(f) int f; {}
+ if (!getLang().CPlusPlus &&
+ Declarator.getFunctionTypeInfo().isKNRPrototype())
+ return isDeclarationSpecifier();
+
+ return Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
+ Tok.is(tok::kw_try); // X() try { ... }
+}
+
+/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
+/// a declaration. We can't tell which we have until we read up to the
+/// compound-statement in function-definition. TemplateParams, if
+/// non-NULL, provides the template parameters when we're parsing a
+/// C++ template-declaration.
+///
+/// function-definition: [C99 6.9.1]
+/// decl-specs declarator declaration-list[opt] compound-statement
+/// [C90] function-definition: [C99 6.7.1] - implicit int result
+/// [C90] decl-specs[opt] declarator declaration-list[opt] compound-statement
+///
+/// declaration: [C99 6.7]
+/// declaration-specifiers init-declarator-list[opt] ';'
+/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
+/// [OMP] threadprivate-directive [TODO]
+///
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
+ AccessSpecifier AS) {
+ // Parse the common declaration-specifiers piece.
+ ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
+
+ // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
+ // declaration-specifiers init-declarator-list[opt] ';'
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DS.complete(TheDecl);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
+
+ // ObjC2 allows prefix attributes on class interfaces and protocols.
+ // FIXME: This still needs better diagnostics. We should only accept
+ // attributes here, no types, etc.
+ if (getLang().ObjC2 && Tok.is(tok::at)) {
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+ if (!Tok.isObjCAtKeyword(tok::objc_interface) &&
+ !Tok.isObjCAtKeyword(tok::objc_protocol)) {
+ Diag(Tok, diag::err_objc_unexpected_attr);
+ SkipUntil(tok::semi); // FIXME: better skip?
+ return DeclGroupPtrTy();
+ }
+
+ DS.abort();
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
+ Diag(AtLoc, DiagID) << PrevSpec;
+
+ Decl *TheDecl = 0;
+ if (Tok.isObjCAtKeyword(tok::objc_protocol))
+ TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
+ else
+ TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
+
+ // If the declspec consisted only of 'extern' and we have a string
+ // literal following it, this must be a C++ linkage specifier like
+ // 'extern "C"'.
+ if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
+ DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+ Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ }
+
+ return ParseDeclGroup(DS, Declarator::FileContext, true);
+}
+
+Parser::DeclGroupPtrTy
+Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
+ AccessSpecifier AS) {
+ ParsingDeclSpec DS(*this);
+ DS.takeAttributesFrom(attrs);
+ return ParseDeclarationOrFunctionDefinition(DS, AS);
+}
+
+/// ParseFunctionDefinition - We parsed and verified that the specified
+/// Declarator is well formed. If this is a K&R-style function, read the
+/// parameters declaration-list, then start the compound-statement.
+///
+/// function-definition: [C99 6.9.1]
+/// decl-specs declarator declaration-list[opt] compound-statement
+/// [C90] function-definition: [C99 6.7.1] - implicit int result
+/// [C90] decl-specs[opt] declarator declaration-list[opt] compound-statement
+/// [C++] function-definition: [C++ 8.4]
+/// decl-specifier-seq[opt] declarator ctor-initializer[opt]
+/// function-body
+/// [C++] function-definition: [C++ 8.4]
+/// decl-specifier-seq[opt] declarator function-try-block
+///
+Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+ // If this is C90 and the declspecs were completely missing, fudge in an
+ // implicit int. We do this here because this is the only place where
+ // declaration-specifiers are completely optional in the grammar.
+ if (getLang().ImplicitInt && D.getDeclSpec().isEmpty()) {
+ const char *PrevSpec;
+ unsigned DiagID;
+ D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int,
+ D.getIdentifierLoc(),
+ PrevSpec, DiagID);
+ D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin());
+ }
+
+ // If this declaration was formed with a K&R-style identifier list for the
+ // arguments, parse declarations for all of the args next.
+ // int foo(a,b) int a; float b; {}
+ if (FTI.isKNRPrototype())
+ ParseKNRParamDeclarations(D);
+
+ // We should have either an opening brace or, in a C++ constructor,
+ // we may have a colon.
+ if (Tok.isNot(tok::l_brace) &&
+ (!getLang().CPlusPlus ||
+ (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) {
+ Diag(Tok, diag::err_expected_fn_body);
+
+ // Skip over garbage, until we get to '{'. Don't eat the '{'.
+ SkipUntil(tok::l_brace, true, true);
+
+ // If we didn't find the '{', bail out.
+ if (Tok.isNot(tok::l_brace))
+ return 0;
+ }
+
+ // Enter a scope for the function body.
+ ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+
+ // Tell the actions module that we have entered a function definition with the
+ // specified Declarator for the function.
+ Decl *Res = TemplateInfo.TemplateParams?
+ Actions.ActOnStartOfFunctionTemplateDef(getCurScope(),
+ MultiTemplateParamsArg(Actions,
+ TemplateInfo.TemplateParams->data(),
+ TemplateInfo.TemplateParams->size()),
+ D)
+ : Actions.ActOnStartOfFunctionDef(getCurScope(), D);
+
+ // Break out of the ParsingDeclarator context before we parse the body.
+ D.complete(Res);
+
+ // Break out of the ParsingDeclSpec context, too. This const_cast is
+ // safe because we're always the sole owner.
+ D.getMutableDeclSpec().abort();
+
+ if (Tok.is(tok::kw_try))
+ return ParseFunctionTryBlock(Res);
+
+ // If we have a colon, then we're probably parsing a C++
+ // ctor-initializer.
+ if (Tok.is(tok::colon)) {
+ ParseConstructorInitializer(Res);
+
+ // Recover from error.
+ if (!Tok.is(tok::l_brace)) {
+ Actions.ActOnFinishFunctionBody(Res, 0);
+ return Res;
+ }
+ } else
+ Actions.ActOnDefaultCtorInitializers(Res);
+
+ return ParseFunctionStatementBody(Res);
+}
+
+/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
+/// types for a function with a K&R-style identifier list for arguments.
+void Parser::ParseKNRParamDeclarations(Declarator &D) {
+ // We know that the top-level of this declarator is a function.
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+ // Enter function-declaration scope, limiting any declarators to the
+ // function prototype scope, including parameter declarators.
+ ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope);
+
+ // Read all the argument declarations.
+ while (isDeclarationSpecifier()) {
+ SourceLocation DSStart = Tok.getLocation();
+
+ // Parse the common declaration-specifiers piece.
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
+
+ // C99 6.9.1p6: 'each declaration in the declaration list shall have at
+ // least one declarator'.
+ // NOTE: GCC just makes this an ext-warn. It's not clear what it does with
+ // the declarations though. It's trivial to ignore them, really hard to do
+ // anything else with them.
+ if (Tok.is(tok::semi)) {
+ Diag(DSStart, diag::err_declaration_does_not_declare_param);
+ ConsumeToken();
+ continue;
+ }
+
+ // C99 6.9.1p6: Declarations shall contain no storage-class specifiers other
+ // than register.
+ if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_register) {
+ Diag(DS.getStorageClassSpecLoc(),
+ diag::err_invalid_storage_class_in_func_decl);
+ DS.ClearStorageClassSpecs();
+ }
+ if (DS.isThreadSpecified()) {
+ Diag(DS.getThreadSpecLoc(),
+ diag::err_invalid_storage_class_in_func_decl);
+ DS.ClearStorageClassSpecs();
+ }
+
+ // Parse the first declarator attached to this declspec.
+ Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
+ ParseDeclarator(ParmDeclarator);
+
+ // Handle the full declarator list.
+ while (1) {
+ // If attributes are present, parse them.
+ MaybeParseGNUAttributes(ParmDeclarator);
+
+ // Ask the actions module to compute the type for this declarator.
+ Decl *Param =
+ Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
+
+ if (Param &&
+ // A missing identifier has already been diagnosed.
+ ParmDeclarator.getIdentifier()) {
+
+ // Scan the argument list looking for the correct param to apply this
+ // type.
+ for (unsigned i = 0; ; ++i) {
+ // C99 6.9.1p6: those declarators shall declare only identifiers from
+ // the identifier list.
+ if (i == FTI.NumArgs) {
+ Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param)
+ << ParmDeclarator.getIdentifier();
+ break;
+ }
+
+ if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
+ // Reject redefinitions of parameters.
+ if (FTI.ArgInfo[i].Param) {
+ Diag(ParmDeclarator.getIdentifierLoc(),
+ diag::err_param_redefinition)
+ << ParmDeclarator.getIdentifier();
+ } else {
+ FTI.ArgInfo[i].Param = Param;
+ }
+ break;
+ }
+ }
+ }
+
+ // If we don't have a comma, it is either the end of the list (a ';') or
+ // an error, bail out.
+ if (Tok.isNot(tok::comma))
+ break;
+
+ // Consume the comma.
+ ConsumeToken();
+
+ // Parse the next declarator.
+ ParmDeclarator.clear();
+ ParseDeclarator(ParmDeclarator);
+ }
+
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_parse_error);
+ // Skip to end of block or statement
+ SkipUntil(tok::semi, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+ }
+
+ // The actions module must verify that all arguments were declared.
+ Actions.ActOnFinishKNRParamDeclarations(getCurScope(), D, Tok.getLocation());
+}
+
+
+/// ParseAsmStringLiteral - This is just a normal string-literal, but is not
+/// allowed to be a wide string, and is not subject to character translation.
+///
+/// [GNU] asm-string-literal:
+/// string-literal
+///
+Parser::ExprResult Parser::ParseAsmStringLiteral() {
+ if (!isTokenStringLiteral()) {
+ Diag(Tok, diag::err_expected_string_literal);
+ return ExprError();
+ }
+
+ ExprResult Res(ParseStringLiteralExpression());
+ if (Res.isInvalid()) return move(Res);
+
+ // TODO: Diagnose: wide string literal in 'asm'
+
+ return move(Res);
+}
+
+/// ParseSimpleAsm
+///
+/// [GNU] simple-asm-expr:
+/// 'asm' '(' asm-string-literal ')'
+///
+Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
+ assert(Tok.is(tok::kw_asm) && "Not an asm!");
+ SourceLocation Loc = ConsumeToken();
+
+ if (Tok.is(tok::kw_volatile)) {
+ // Remove from the end of 'asm' to the end of 'volatile'.
+ SourceRange RemovalRange(PP.getLocForEndOfToken(Loc),
+ PP.getLocForEndOfToken(Tok.getLocation()));
+
+ Diag(Tok, diag::warn_file_asm_volatile)
+ << FixItHint::CreateRemoval(RemovalRange);
+ ConsumeToken();
+ }
+
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected_lparen_after) << "asm";
+ return ExprError();
+ }
+
+ Loc = ConsumeParen();
+
+ ExprResult Result(ParseAsmStringLiteral());
+
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren, true, true);
+ if (EndLoc)
+ *EndLoc = Tok.getLocation();
+ ConsumeAnyToken();
+ } else {
+ Loc = MatchRHSPunctuation(tok::r_paren, Loc);
+ if (EndLoc)
+ *EndLoc = Loc;
+ }
+
+ return move(Result);
+}
+
+/// TryAnnotateTypeOrScopeToken - If the current token position is on a
+/// typename (possibly qualified in C++) or a C++ scope specifier not followed
+/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
+/// with a single annotation token representing the typename or C++ scope
+/// respectively.
+/// This simplifies handling of C++ scope specifiers and allows efficient
+/// backtracking without the need to re-parse and resolve nested-names and
+/// typenames.
+/// It will mainly be called when we expect to treat identifiers as typenames
+/// (if they are typenames). For example, in C we do not expect identifiers
+/// inside expressions to be treated as typenames so it will not be called
+/// for expressions in C.
+/// The benefit for C/ObjC is that a typename will be annotated and
+/// Actions.getTypeName will not be needed to be called again (e.g. getTypeName
+/// will not be called twice, once to check whether we have a declaration
+/// specifier, and another one to get the actual type inside
+/// ParseDeclarationSpecifiers).
+///
+/// This returns true if an error occurred.
+///
+/// Note that this routine emits an error if you call it with ::new or ::delete
+/// as the current tokens, so only call it in contexts where these are invalid.
+bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
+ assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
+ || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) &&
+ "Cannot be a type or scope token!");
+
+ if (Tok.is(tok::kw_typename)) {
+ // Parse a C++ typename-specifier, e.g., "typename T::type".
+ //
+ // typename-specifier:
+ // 'typename' '::' [opt] nested-name-specifier identifier
+ // 'typename' '::' [opt] nested-name-specifier template [opt]
+ // simple-template-id
+ SourceLocation TypenameLoc = ConsumeToken();
+ CXXScopeSpec SS;
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false))
+ return true;
+ if (!SS.isSet()) {
+ Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
+ return true;
+ }
+
+ TypeResult Ty;
+ if (Tok.is(tok::identifier)) {
+ // FIXME: check whether the next token is '<', first!
+ Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
+ *Tok.getIdentifierInfo(),
+ Tok.getLocation());
+ } else if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Function_template) {
+ Diag(Tok, diag::err_typename_refers_to_non_type_template)
+ << Tok.getAnnotationRange();
+ return true;
+ }
+
+ AnnotateTemplateIdTokenAsType(0);
+ assert(Tok.is(tok::annot_typename) &&
+ "AnnotateTemplateIdTokenAsType isn't working properly");
+ if (Tok.getAnnotationValue())
+ Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
+ SourceLocation(),
+ getTypeAnnotation(Tok));
+ else
+ Ty = true;
+ } else {
+ Diag(Tok, diag::err_expected_type_name_after_typename)
+ << SS.getRange();
+ return true;
+ }
+
+ SourceLocation EndLoc = Tok.getLastLoc();
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Ty.isInvalid() ? ParsedType() : Ty.get());
+ Tok.setAnnotationEndLoc(EndLoc);
+ Tok.setLocation(TypenameLoc);
+ PP.AnnotateCachedTokens(Tok);
+ return false;
+ }
+
+ // Remembers whether the token was originally a scope annotation.
+ bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope);
+
+ CXXScopeSpec SS;
+ if (getLang().CPlusPlus)
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
+ return true;
+
+ if (Tok.is(tok::identifier)) {
+ // Determine whether the identifier is a type name.
+ if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), getCurScope(),
+ &SS, false,
+ NextToken().is(tok::period))) {
+ // This is a typename. Replace the current token in-place with an
+ // annotation type token.
+ Tok.setKind(tok::annot_typename);
+ setTypeAnnotation(Tok, Ty);
+ Tok.setAnnotationEndLoc(Tok.getLocation());
+ if (SS.isNotEmpty()) // it was a C++ qualified type name.
+ Tok.setLocation(SS.getBeginLoc());
+
+ // In case the tokens were cached, have Preprocessor replace
+ // them with the annotation token.
+ PP.AnnotateCachedTokens(Tok);
+ return false;
+ }
+
+ if (!getLang().CPlusPlus) {
+ // If we're in C, we can't have :: tokens at all (the lexer won't return
+ // them). If the identifier is not a type, then it can't be scope either,
+ // just early exit.
+ return false;
+ }
+
+ // If this is a template-id, annotate with a template-id or type token.
+ if (NextToken().is(tok::less)) {
+ TemplateTy Template;
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ bool MemberOfUnknownSpecialization;
+ if (TemplateNameKind TNK
+ = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false, TemplateName,
+ /*ObjectType=*/ ParsedType(),
+ EnteringContext,
+ Template, MemberOfUnknownSpecialization)) {
+ // Consume the identifier.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
+ // If an unrecoverable error occurred, we need to return true here,
+ // because the token stream is in a damaged state. We may not return
+ // a valid identifier.
+ return true;
+ }
+ }
+ }
+
+ // The current token, which is either an identifier or a
+ // template-id, is not part of the annotation. Fall through to
+ // push that token back into the stream and complete the C++ scope
+ // specifier annotation.
+ }
+
+ if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (TemplateId->Kind == TNK_Type_template) {
+ // A template-id that refers to a type was parsed into a
+ // template-id annotation in a context where we weren't allowed
+ // to produce a type annotation token. Update the template-id
+ // annotation token to a type annotation token now.
+ AnnotateTemplateIdTokenAsType(&SS);
+ return false;
+ }
+ }
+
+ if (SS.isEmpty())
+ return false;
+
+ // A C++ scope specifier that isn't followed by a typename.
+ // Push the current token back into the token stream (or revert it if it is
+ // cached) and use an annotation scope token for current token.
+ if (PP.isBacktrackEnabled())
+ PP.RevertCachedTokens(1);
+ else
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::annot_cxxscope);
+ Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationRange(SS.getRange());
+
+ // In case the tokens were cached, have Preprocessor replace them
+ // with the annotation token. We don't need to do this if we've
+ // just reverted back to the state we were in before being called.
+ if (!wasScopeAnnotation)
+ PP.AnnotateCachedTokens(Tok);
+ return false;
+}
+
+/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
+/// annotates C++ scope specifiers and template-ids. This returns
+/// true if the token was annotated or there was an error that could not be
+/// recovered from.
+///
+/// Note that this routine emits an error if you call it with ::new or ::delete
+/// as the current tokens, so only call it in contexts where these are invalid.
+bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
+ assert(getLang().CPlusPlus &&
+ "Call sites of this function should be guarded by checking for C++");
+ assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+ "Cannot be a type or scope token!");
+
+ CXXScopeSpec SS;
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
+ return true;
+ if (SS.isEmpty())
+ return false;
+
+ // Push the current token back into the token stream (or revert it if it is
+ // cached) and use an annotation scope token for current token.
+ if (PP.isBacktrackEnabled())
+ PP.RevertCachedTokens(1);
+ else
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::annot_cxxscope);
+ Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationRange(SS.getRange());
+
+ // In case the tokens were cached, have Preprocessor replace them with the
+ // annotation token.
+ PP.AnnotateCachedTokens(Tok);
+ return false;
+}
+
+bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) {
+ if (Tok.is(tok::equalequal)) {
+ // We have '==' in a context that we would expect a '='.
+ // The user probably made a typo, intending to type '='. Emit diagnostic,
+ // fixit hint to turn '==' -> '=' and continue as if the user typed '='.
+ Diag(Tok, DiagID)
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()),
+ getTokenSimpleSpelling(tok::equal));
+ return true;
+ }
+
+ return Tok.is(tok::equal);
+}
+
+void Parser::CodeCompletionRecovery() {
+ for (Scope *S = getCurScope(); S; S = S->getParent()) {
+ if (S->getFlags() & Scope::FnScope) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_RecoveryInFunction);
+ return;
+ }
+
+ if (S->getFlags() & Scope::ClassScope) {
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class);
+ return;
+ }
+ }
+
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace);
+}
+
+// Anchor the Parser::FieldCallback vtable to this translation unit.
+// We use a spurious method instead of the destructor because
+// destroying FieldCallbacks can actually be slightly
+// performance-sensitive.
+void Parser::FieldCallback::_anchor() {
+}
+
+// Code-completion pass-through functions
+
+void Parser::CodeCompleteDirective(bool InConditional) {
+ Actions.CodeCompletePreprocessorDirective(InConditional);
+}
+
+void Parser::CodeCompleteInConditionalExclusion() {
+ Actions.CodeCompleteInPreprocessorConditionalExclusion(getCurScope());
+}
+
+void Parser::CodeCompleteMacroName(bool IsDefinition) {
+ Actions.CodeCompletePreprocessorMacroName(IsDefinition);
+}
+
+void Parser::CodeCompletePreprocessorExpression() {
+ Actions.CodeCompletePreprocessorExpression();
+}
+
+void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) {
+ Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo,
+ ArgumentIndex);
+}
+
+void Parser::CodeCompleteNaturalLanguage() {
+ Actions.CodeCompleteNaturalLanguage();
+}
diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
new file mode 100644
index 0000000..583f184
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h
@@ -0,0 +1,118 @@
+//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- 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 and implements the some simple RAII objects that are used
+// by the parser to manage bits in recursion.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
+
+#include "clang/Parse/ParseDiagnostic.h"
+
+namespace clang {
+ // TODO: move ParsingDeclRAIIObject here.
+ // TODO: move ParsingClassDefinition here.
+ // TODO: move TentativeParsingAction here.
+
+
+ /// ExtensionRAIIObject - This saves the state of extension warnings when
+ /// constructed and disables them. When destructed, it restores them back to
+ /// the way they used to be. This is used to handle __extension__ in the
+ /// parser.
+ class ExtensionRAIIObject {
+ void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT
+ ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
+ Diagnostic &Diags;
+ public:
+ ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
+ Diags.IncrementAllExtensionsSilenced();
+ }
+
+ ~ExtensionRAIIObject() {
+ Diags.DecrementAllExtensionsSilenced();
+ }
+ };
+
+ /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
+ /// restores it when destroyed. This says that "foo:" should not be
+ /// considered a possible typo for "foo::" for error recovery purposes.
+ class ColonProtectionRAIIObject {
+ Parser &P;
+ bool OldVal;
+ public:
+ ColonProtectionRAIIObject(Parser &p, bool Value = true)
+ : P(p), OldVal(P.ColonIsSacred) {
+ P.ColonIsSacred = Value;
+ }
+
+ /// restore - This can be used to restore the state early, before the dtor
+ /// is run.
+ void restore() {
+ P.ColonIsSacred = OldVal;
+ }
+
+ ~ColonProtectionRAIIObject() {
+ restore();
+ }
+ };
+
+ /// \brief RAII object that makes '>' behave either as an operator
+ /// or as the closing angle bracket for a template argument list.
+ class GreaterThanIsOperatorScope {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+ public:
+ GreaterThanIsOperatorScope(bool &GTIO, bool Val)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GreaterThanIsOperator = Val;
+ }
+
+ ~GreaterThanIsOperatorScope() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
+ class InMessageExpressionRAIIObject {
+ bool &InMessageExpression;
+ bool OldValue;
+
+ public:
+ InMessageExpressionRAIIObject(Parser &P, bool Value)
+ : InMessageExpression(P.InMessageExpression),
+ OldValue(P.InMessageExpression) {
+ InMessageExpression = Value;
+ }
+
+ ~InMessageExpressionRAIIObject() {
+ InMessageExpression = OldValue;
+ }
+ };
+
+ /// \brief RAII object that makes sure paren/bracket/brace count is correct
+ /// after declaration/statement parsing, even when there's a parsing error.
+ class ParenBraceBracketBalancer {
+ Parser &P;
+ unsigned short ParenCount, BracketCount, BraceCount;
+ public:
+ ParenBraceBracketBalancer(Parser &p)
+ : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
+ BraceCount(p.BraceCount) { }
+
+ ~ParenBraceBracketBalancer() {
+ P.ParenCount = ParenCount;
+ P.BracketCount = BracketCount;
+ P.BraceCount = BraceCount;
+ }
+ };
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp b/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp
new file mode 100644
index 0000000..085dfd8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/DeltaTree.cpp
@@ -0,0 +1,469 @@
+//===--- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DeltaTree and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/DeltaTree.h"
+#include "llvm/Support/Casting.h"
+#include <cstring>
+#include <cstdio>
+using namespace clang;
+using llvm::cast;
+using llvm::dyn_cast;
+
+/// The DeltaTree class is a multiway search tree (BTree) structure with some
+/// fancy features. B-Trees are generally more memory and cache efficient
+/// than binary trees, because they store multiple keys/values in each node.
+///
+/// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
+/// fast lookup by FileIndex. However, an added (important) bonus is that it
+/// can also efficiently tell us the full accumulated delta for a specific
+/// file offset as well, without traversing the whole tree.
+///
+/// The nodes of the tree are made up of instances of two classes:
+/// DeltaTreeNode and DeltaTreeInteriorNode. The later subclasses the
+/// former and adds children pointers. Each node knows the full delta of all
+/// entries (recursively) contained inside of it, which allows us to get the
+/// full delta implied by a whole subtree in constant time.
+
+namespace {
+ /// SourceDelta - As code in the original input buffer is added and deleted,
+ /// SourceDelta records are used to keep track of how the input SourceLocation
+ /// object is mapped into the output buffer.
+ struct SourceDelta {
+ unsigned FileLoc;
+ int Delta;
+
+ static SourceDelta get(unsigned Loc, int D) {
+ SourceDelta Delta;
+ Delta.FileLoc = Loc;
+ Delta.Delta = D;
+ return Delta;
+ }
+ };
+
+ /// DeltaTreeNode - The common part of all nodes.
+ ///
+ class DeltaTreeNode {
+ public:
+ struct InsertResult {
+ DeltaTreeNode *LHS, *RHS;
+ SourceDelta Split;
+ };
+
+ private:
+ friend class DeltaTreeInteriorNode;
+
+ /// WidthFactor - This controls the number of K/V slots held in the BTree:
+ /// how wide it is. Each level of the BTree is guaranteed to have at least
+ /// WidthFactor-1 K/V pairs (except the root) and may have at most
+ /// 2*WidthFactor-1 K/V pairs.
+ enum { WidthFactor = 8 };
+
+ /// Values - This tracks the SourceDelta's currently in this node.
+ ///
+ SourceDelta Values[2*WidthFactor-1];
+
+ /// NumValuesUsed - This tracks the number of values this node currently
+ /// holds.
+ unsigned char NumValuesUsed;
+
+ /// IsLeaf - This is true if this is a leaf of the btree. If false, this is
+ /// an interior node, and is actually an instance of DeltaTreeInteriorNode.
+ bool IsLeaf;
+
+ /// FullDelta - This is the full delta of all the values in this node and
+ /// all children nodes.
+ int FullDelta;
+ public:
+ DeltaTreeNode(bool isLeaf = true)
+ : NumValuesUsed(0), IsLeaf(isLeaf), FullDelta(0) {}
+
+ bool isLeaf() const { return IsLeaf; }
+ int getFullDelta() const { return FullDelta; }
+ bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
+
+ unsigned getNumValuesUsed() const { return NumValuesUsed; }
+ const SourceDelta &getValue(unsigned i) const {
+ assert(i < NumValuesUsed && "Invalid value #");
+ return Values[i];
+ }
+ SourceDelta &getValue(unsigned i) {
+ assert(i < NumValuesUsed && "Invalid value #");
+ return Values[i];
+ }
+
+ /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
+ /// this node. If insertion is easy, do it and return false. Otherwise,
+ /// split the node, populate InsertRes with info about the split, and return
+ /// true.
+ bool DoInsertion(unsigned FileIndex, int Delta, InsertResult *InsertRes);
+
+ void DoSplit(InsertResult &InsertRes);
+
+
+ /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
+ /// local walk over our contained deltas.
+ void RecomputeFullDeltaLocally();
+
+ void Destroy();
+
+ //static inline bool classof(const DeltaTreeNode *) { return true; }
+ };
+} // end anonymous namespace
+
+namespace {
+ /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
+ /// This class tracks them.
+ class DeltaTreeInteriorNode : public DeltaTreeNode {
+ DeltaTreeNode *Children[2*WidthFactor];
+ ~DeltaTreeInteriorNode() {
+ for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
+ Children[i]->Destroy();
+ }
+ friend class DeltaTreeNode;
+ public:
+ DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
+
+ DeltaTreeInteriorNode(const InsertResult &IR)
+ : DeltaTreeNode(false /*nonleaf*/) {
+ Children[0] = IR.LHS;
+ Children[1] = IR.RHS;
+ Values[0] = IR.Split;
+ FullDelta = IR.LHS->getFullDelta()+IR.RHS->getFullDelta()+IR.Split.Delta;
+ NumValuesUsed = 1;
+ }
+
+ const DeltaTreeNode *getChild(unsigned i) const {
+ assert(i < getNumValuesUsed()+1 && "Invalid child");
+ return Children[i];
+ }
+ DeltaTreeNode *getChild(unsigned i) {
+ assert(i < getNumValuesUsed()+1 && "Invalid child");
+ return Children[i];
+ }
+
+ //static inline bool classof(const DeltaTreeInteriorNode *) { return true; }
+ static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
+ };
+}
+
+
+/// Destroy - A 'virtual' destructor.
+void DeltaTreeNode::Destroy() {
+ if (isLeaf())
+ delete this;
+ else
+ delete cast<DeltaTreeInteriorNode>(this);
+}
+
+/// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
+/// local walk over our contained deltas.
+void DeltaTreeNode::RecomputeFullDeltaLocally() {
+ int NewFullDelta = 0;
+ for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
+ NewFullDelta += Values[i].Delta;
+ if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this))
+ for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
+ NewFullDelta += IN->getChild(i)->getFullDelta();
+ FullDelta = NewFullDelta;
+}
+
+/// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
+/// this node. If insertion is easy, do it and return false. Otherwise,
+/// split the node, populate InsertRes with info about the split, and return
+/// true.
+bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta,
+ InsertResult *InsertRes) {
+ // Maintain full delta for this node.
+ FullDelta += Delta;
+
+ // Find the insertion point, the first delta whose index is >= FileIndex.
+ unsigned i = 0, e = getNumValuesUsed();
+ while (i != e && FileIndex > getValue(i).FileLoc)
+ ++i;
+
+ // If we found an a record for exactly this file index, just merge this
+ // value into the pre-existing record and finish early.
+ if (i != e && getValue(i).FileLoc == FileIndex) {
+ // NOTE: Delta could drop to zero here. This means that the delta entry is
+ // useless and could be removed. Supporting erases is more complex than
+ // leaving an entry with Delta=0, so we just leave an entry with Delta=0 in
+ // the tree.
+ Values[i].Delta += Delta;
+ return false;
+ }
+
+ // Otherwise, we found an insertion point, and we know that the value at the
+ // specified index is > FileIndex. Handle the leaf case first.
+ if (isLeaf()) {
+ if (!isFull()) {
+ // For an insertion into a non-full leaf node, just insert the value in
+ // its sorted position. This requires moving later values over.
+ if (i != e)
+ memmove(&Values[i+1], &Values[i], sizeof(Values[0])*(e-i));
+ Values[i] = SourceDelta::get(FileIndex, Delta);
+ ++NumValuesUsed;
+ return false;
+ }
+
+ // Otherwise, if this is leaf is full, split the node at its median, insert
+ // the value into one of the children, and return the result.
+ assert(InsertRes && "No result location specified");
+ DoSplit(*InsertRes);
+
+ if (InsertRes->Split.FileLoc > FileIndex)
+ InsertRes->LHS->DoInsertion(FileIndex, Delta, 0 /*can't fail*/);
+ else
+ InsertRes->RHS->DoInsertion(FileIndex, Delta, 0 /*can't fail*/);
+ return true;
+ }
+
+ // Otherwise, this is an interior node. Send the request down the tree.
+ DeltaTreeInteriorNode *IN = cast<DeltaTreeInteriorNode>(this);
+ if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
+ return false; // If there was space in the child, just return.
+
+ // Okay, this split the subtree, producing a new value and two children to
+ // insert here. If this node is non-full, we can just insert it directly.
+ if (!isFull()) {
+ // Now that we have two nodes and a new element, insert the perclated value
+ // into ourself by moving all the later values/children down, then inserting
+ // the new one.
+ if (i != e)
+ memmove(&IN->Children[i+2], &IN->Children[i+1],
+ (e-i)*sizeof(IN->Children[0]));
+ IN->Children[i] = InsertRes->LHS;
+ IN->Children[i+1] = InsertRes->RHS;
+
+ if (e != i)
+ memmove(&Values[i+1], &Values[i], (e-i)*sizeof(Values[0]));
+ Values[i] = InsertRes->Split;
+ ++NumValuesUsed;
+ return false;
+ }
+
+ // Finally, if this interior node was full and a node is percolated up, split
+ // ourself and return that up the chain. Start by saving all our info to
+ // avoid having the split clobber it.
+ IN->Children[i] = InsertRes->LHS;
+ DeltaTreeNode *SubRHS = InsertRes->RHS;
+ SourceDelta SubSplit = InsertRes->Split;
+
+ // Do the split.
+ DoSplit(*InsertRes);
+
+ // Figure out where to insert SubRHS/NewSplit.
+ DeltaTreeInteriorNode *InsertSide;
+ if (SubSplit.FileLoc < InsertRes->Split.FileLoc)
+ InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS);
+ else
+ InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS);
+
+ // We now have a non-empty interior node 'InsertSide' to insert
+ // SubRHS/SubSplit into. Find out where to insert SubSplit.
+
+ // Find the insertion point, the first delta whose index is >SubSplit.FileLoc.
+ i = 0; e = InsertSide->getNumValuesUsed();
+ while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc)
+ ++i;
+
+ // Now we know that i is the place to insert the split value into. Insert it
+ // and the child right after it.
+ if (i != e)
+ memmove(&InsertSide->Children[i+2], &InsertSide->Children[i+1],
+ (e-i)*sizeof(IN->Children[0]));
+ InsertSide->Children[i+1] = SubRHS;
+
+ if (e != i)
+ memmove(&InsertSide->Values[i+1], &InsertSide->Values[i],
+ (e-i)*sizeof(Values[0]));
+ InsertSide->Values[i] = SubSplit;
+ ++InsertSide->NumValuesUsed;
+ InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta();
+ return true;
+}
+
+/// DoSplit - Split the currently full node (which has 2*WidthFactor-1 values)
+/// into two subtrees each with "WidthFactor-1" values and a pivot value.
+/// Return the pieces in InsertRes.
+void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
+ assert(isFull() && "Why split a non-full node?");
+
+ // Since this node is full, it contains 2*WidthFactor-1 values. We move
+ // the first 'WidthFactor-1' values to the LHS child (which we leave in this
+ // node), propagate one value up, and move the last 'WidthFactor-1' values
+ // into the RHS child.
+
+ // Create the new child node.
+ DeltaTreeNode *NewNode;
+ if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
+ // If this is an interior node, also move over 'WidthFactor' children
+ // into the new node.
+ DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
+ memcpy(&New->Children[0], &IN->Children[WidthFactor],
+ WidthFactor*sizeof(IN->Children[0]));
+ NewNode = New;
+ } else {
+ // Just create the new leaf node.
+ NewNode = new DeltaTreeNode();
+ }
+
+ // Move over the last 'WidthFactor-1' values from here to NewNode.
+ memcpy(&NewNode->Values[0], &Values[WidthFactor],
+ (WidthFactor-1)*sizeof(Values[0]));
+
+ // Decrease the number of values in the two nodes.
+ NewNode->NumValuesUsed = NumValuesUsed = WidthFactor-1;
+
+ // Recompute the two nodes' full delta.
+ NewNode->RecomputeFullDeltaLocally();
+ RecomputeFullDeltaLocally();
+
+ InsertRes.LHS = this;
+ InsertRes.RHS = NewNode;
+ InsertRes.Split = Values[WidthFactor-1];
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// DeltaTree Implementation
+//===----------------------------------------------------------------------===//
+
+//#define VERIFY_TREE
+
+#ifdef VERIFY_TREE
+/// VerifyTree - Walk the btree performing assertions on various properties to
+/// verify consistency. This is useful for debugging new changes to the tree.
+static void VerifyTree(const DeltaTreeNode *N) {
+ const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(N);
+ if (IN == 0) {
+ // Verify leaves, just ensure that FullDelta matches up and the elements
+ // are in proper order.
+ int FullDelta = 0;
+ for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
+ if (i)
+ assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
+ FullDelta += N->getValue(i).Delta;
+ }
+ assert(FullDelta == N->getFullDelta());
+ return;
+ }
+
+ // Verify interior nodes: Ensure that FullDelta matches up and the
+ // elements are in proper order and the children are in proper order.
+ int FullDelta = 0;
+ for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
+ const SourceDelta &IVal = N->getValue(i);
+ const DeltaTreeNode *IChild = IN->getChild(i);
+ if (i)
+ assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
+ FullDelta += IVal.Delta;
+ FullDelta += IChild->getFullDelta();
+
+ // The largest value in child #i should be smaller than FileLoc.
+ assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
+ IVal.FileLoc);
+
+ // The smallest value in child #i+1 should be larger than FileLoc.
+ assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
+ VerifyTree(IChild);
+ }
+
+ FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
+
+ assert(FullDelta == N->getFullDelta());
+}
+#endif // VERIFY_TREE
+
+static DeltaTreeNode *getRoot(void *Root) {
+ return (DeltaTreeNode*)Root;
+}
+
+DeltaTree::DeltaTree() {
+ Root = new DeltaTreeNode();
+}
+DeltaTree::DeltaTree(const DeltaTree &RHS) {
+ // Currently we only support copying when the RHS is empty.
+ assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
+ "Can only copy empty tree");
+ Root = new DeltaTreeNode();
+}
+
+DeltaTree::~DeltaTree() {
+ getRoot(Root)->Destroy();
+}
+
+/// getDeltaAt - Return the accumulated delta at the specified file offset.
+/// This includes all insertions or delections that occurred *before* the
+/// specified file index.
+int DeltaTree::getDeltaAt(unsigned FileIndex) const {
+ const DeltaTreeNode *Node = getRoot(Root);
+
+ int Result = 0;
+
+ // Walk down the tree.
+ while (1) {
+ // For all nodes, include any local deltas before the specified file
+ // index by summing them up directly. Keep track of how many were
+ // included.
+ unsigned NumValsGreater = 0;
+ for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e;
+ ++NumValsGreater) {
+ const SourceDelta &Val = Node->getValue(NumValsGreater);
+
+ if (Val.FileLoc >= FileIndex)
+ break;
+ Result += Val.Delta;
+ }
+
+ // If we have an interior node, include information about children and
+ // recurse. Otherwise, if we have a leaf, we're done.
+ const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
+ if (!IN) return Result;
+
+ // Include any children to the left of the values we skipped, all of
+ // their deltas should be included as well.
+ for (unsigned i = 0; i != NumValsGreater; ++i)
+ Result += IN->getChild(i)->getFullDelta();
+
+ // If we found exactly the value we were looking for, break off the
+ // search early. There is no need to search the RHS of the value for
+ // partial results.
+ if (NumValsGreater != Node->getNumValuesUsed() &&
+ Node->getValue(NumValsGreater).FileLoc == FileIndex)
+ return Result+IN->getChild(NumValsGreater)->getFullDelta();
+
+ // Otherwise, traverse down the tree. The selected subtree may be
+ // partially included in the range.
+ Node = IN->getChild(NumValsGreater);
+ }
+ // NOT REACHED.
+}
+
+/// AddDelta - When a change is made that shifts around the text buffer,
+/// this method is used to record that info. It inserts a delta of 'Delta'
+/// into the current DeltaTree at offset FileIndex.
+void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
+ assert(Delta && "Adding a noop?");
+ DeltaTreeNode *MyRoot = getRoot(Root);
+
+ DeltaTreeNode::InsertResult InsertRes;
+ if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
+ Root = MyRoot = new DeltaTreeInteriorNode(InsertRes);
+ }
+
+#ifdef VERIFY_TREE
+ VerifyTree(MyRoot);
+#endif
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp
new file mode 100644
index 0000000..8dcc5dc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp
@@ -0,0 +1,159 @@
+//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a diagnostic client adaptor that performs rewrites as
+// suggested by code modification hints attached to diagnostics. It
+// then forwards any diagnostics to the adapted diagnostic client.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/FixItRewriter.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cstdio>
+
+using namespace clang;
+
+FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
+ const LangOptions &LangOpts,
+ FixItOptions *FixItOpts)
+ : Diags(Diags),
+ Rewrite(SourceMgr, LangOpts),
+ FixItOpts(FixItOpts),
+ NumFailures(0) {
+ Client = Diags.takeClient();
+ Diags.setClient(this);
+}
+
+FixItRewriter::~FixItRewriter() {
+ Diags.takeClient();
+ Diags.setClient(Client);
+}
+
+bool FixItRewriter::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) {
+ const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID);
+ if (!RewriteBuf) return true;
+ RewriteBuf->write(OS);
+ OS.flush();
+ return false;
+}
+
+bool FixItRewriter::WriteFixedFiles() {
+ if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
+ Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
+ return true;
+ }
+
+ for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
+ const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
+ std::string Filename = FixItOpts->RewriteFilename(Entry->getName());
+ std::string Err;
+ llvm::raw_fd_ostream OS(Filename.c_str(), Err,
+ llvm::raw_fd_ostream::F_Binary);
+ if (!Err.empty()) {
+ Diags.Report(clang::diag::err_fe_unable_to_open_output)
+ << Filename << Err;
+ continue;
+ }
+ RewriteBuffer &RewriteBuf = I->second;
+ RewriteBuf.write(OS);
+ OS.flush();
+ }
+
+ return false;
+}
+
+bool FixItRewriter::IncludeInDiagnosticCounts() const {
+ return Client ? Client->IncludeInDiagnosticCounts() : true;
+}
+
+void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticClient::HandleDiagnostic(DiagLevel, Info);
+
+ Client->HandleDiagnostic(DiagLevel, Info);
+
+ // Skip over any diagnostics that are ignored or notes.
+ if (DiagLevel <= Diagnostic::Note)
+ return;
+
+ // Make sure that we can perform all of the modifications we
+ // in this diagnostic.
+ bool CanRewrite = Info.getNumFixItHints() > 0;
+ for (unsigned Idx = 0, Last = Info.getNumFixItHints();
+ Idx < Last; ++Idx) {
+ const FixItHint &Hint = Info.getFixItHint(Idx);
+ if (Hint.RemoveRange.isValid() &&
+ Rewrite.getRangeSize(Hint.RemoveRange) == -1) {
+ CanRewrite = false;
+ break;
+ }
+ }
+
+ if (!CanRewrite) {
+ if (Info.getNumFixItHints() > 0)
+ Diag(Info.getLocation(), diag::note_fixit_in_macro);
+
+ // If this was an error, refuse to perform any rewriting.
+ if (DiagLevel == Diagnostic::Error || DiagLevel == Diagnostic::Fatal) {
+ if (++NumFailures == 1)
+ Diag(Info.getLocation(), diag::note_fixit_unfixed_error);
+ }
+ return;
+ }
+
+ bool Failed = false;
+ for (unsigned Idx = 0, Last = Info.getNumFixItHints();
+ Idx < Last; ++Idx) {
+ const FixItHint &Hint = Info.getFixItHint(Idx);
+
+ if (Hint.CodeToInsert.empty()) {
+ // We're removing code.
+ if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
+ Rewrite.getRangeSize(Hint.RemoveRange)))
+ Failed = true;
+ continue;
+ }
+
+ // We're replacing code.
+ if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(),
+ Rewrite.getRangeSize(Hint.RemoveRange),
+ Hint.CodeToInsert))
+ Failed = true;
+ }
+
+ if (Failed) {
+ ++NumFailures;
+ Diag(Info.getLocation(), diag::note_fixit_failed);
+ return;
+ }
+
+ Diag(Info.getLocation(), diag::note_fixit_applied);
+}
+
+/// \brief Emit a diagnostic via the adapted diagnostic client.
+void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
+ // When producing this diagnostic, we temporarily bypass ourselves,
+ // clear out any current diagnostic, and let the downstream client
+ // format the diagnostic.
+ Diags.takeClient();
+ Diags.setClient(Client);
+ Diags.Clear();
+ Diags.Report(Loc, DiagID);
+ Diags.takeClient();
+ Diags.setClient(this);
+}
+
+FixItOptions::~FixItOptions() {}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Rewrite/FrontendActions.cpp
new file mode 100644
index 0000000..33e79ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/FrontendActions.cpp
@@ -0,0 +1,116 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Rewrite/ASTConsumers.h"
+#include "clang/Rewrite/FixItRewriter.h"
+#include "clang/Rewrite/Rewriters.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+ return CreateHTMLPrinter(OS, CI.getPreprocessor());
+ return 0;
+}
+
+FixItAction::FixItAction() {}
+FixItAction::~FixItAction() {}
+
+ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+namespace {
+class FixItRewriteInPlace : public FixItOptions {
+public:
+ std::string RewriteFilename(const std::string &Filename) { return Filename; }
+};
+
+class FixItActionSuffixInserter : public FixItOptions {
+ std::string NewSuffix;
+
+public:
+ FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
+ : NewSuffix(NewSuffix) {
+ this->FixWhatYouCan = FixWhatYouCan;
+ }
+
+ std::string RewriteFilename(const std::string &Filename) {
+ llvm::SmallString<128> Path(Filename);
+ llvm::sys::path::replace_extension(Path,
+ NewSuffix + llvm::sys::path::extension(Path));
+ return Path.str();
+ }
+};
+} // end anonymous namespace
+
+bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
+ if (!FEOpts.FixItSuffix.empty()) {
+ FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
+ FEOpts.FixWhatYouCan));
+ } else {
+ FixItOpts.reset(new FixItRewriteInPlace);
+ FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
+ }
+ Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
+ CI.getLangOpts(), FixItOpts.get()));
+ return true;
+}
+
+void FixItAction::EndSourceFileAction() {
+ // Otherwise rewrite all files.
+ Rewriter->WriteFixedFiles();
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
+ return CreateObjCRewriter(InFile, OS,
+ CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getDiagnosticOpts().NoRewriteMacros);
+ return 0;
+}
+
+void RewriteMacrosAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS) return;
+
+ RewriteMacrosInInput(CI.getPreprocessor(), OS);
+}
+
+void RewriteTestAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ if (!OS) return;
+
+ DoRewriteTest(CI.getPreprocessor(), OS);
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/HTMLPrint.cpp b/contrib/llvm/tools/clang/lib/Rewrite/HTMLPrint.cpp
new file mode 100644
index 0000000..f66bfcb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/HTMLPrint.cpp
@@ -0,0 +1,94 @@
+//===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Pretty-printing of source code to HTML.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/ASTConsumers.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Functional HTML pretty-printing.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class HTMLPrinter : public ASTConsumer {
+ Rewriter R;
+ llvm::raw_ostream *Out;
+ Preprocessor &PP;
+ bool SyntaxHighlight, HighlightMacros;
+
+ public:
+ HTMLPrinter(llvm::raw_ostream *OS, Preprocessor &pp,
+ bool _SyntaxHighlight, bool _HighlightMacros)
+ : Out(OS), PP(pp), SyntaxHighlight(_SyntaxHighlight),
+ HighlightMacros(_HighlightMacros) {}
+
+ void Initialize(ASTContext &context);
+ void HandleTranslationUnit(ASTContext &Ctx);
+ };
+}
+
+ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS,
+ Preprocessor &PP,
+ bool SyntaxHighlight,
+ bool HighlightMacros) {
+ return new HTMLPrinter(OS, PP, SyntaxHighlight, HighlightMacros);
+}
+
+void HTMLPrinter::Initialize(ASTContext &context) {
+ R.setSourceMgr(context.getSourceManager(), context.getLangOptions());
+}
+
+void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
+ if (PP.getDiagnostics().hasErrorOccurred())
+ return;
+
+ // Format the file.
+ FileID FID = R.getSourceMgr().getMainFileID();
+ const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
+ const char* Name;
+ // In some cases, in particular the case where the input is from stdin,
+ // there is no entry. Fall back to the memory buffer for a name in those
+ // cases.
+ if (Entry)
+ Name = Entry->getName();
+ else
+ Name = R.getSourceMgr().getBuffer(FID)->getBufferIdentifier();
+
+ html::AddLineNumbers(R, FID);
+ html::AddHeaderFooterInternalBuiltinCSS(R, FID, Name);
+
+ // If we have a preprocessor, relex the file and syntax highlight.
+ // We might not have a preprocessor if we come from a deserialized AST file,
+ // for example.
+
+ if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
+ if (HighlightMacros) html::HighlightMacros(R, FID, PP);
+ html::EscapeText(R, FID, false, true);
+
+ // Emit the HTML.
+ const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
+ char *Buffer = (char*)malloc(RewriteBuf.size());
+ std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
+ Out->write(Buffer, RewriteBuf.size());
+ free(Buffer);
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
new file mode 100644
index 0000000..df08cd7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/HTMLRewrite.cpp
@@ -0,0 +1,580 @@
+//== HTMLRewrite.cpp - Translate source code into prettified HTML --*- 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 HTMLRewriter clas, which is used to translate the
+// text of a source file into prettified HTML.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Lex/TokenConcatenation.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+
+/// HighlightRange - Highlight a range in the source code with the specified
+/// start/end tags. B/E must be in the same file. This ensures that
+/// start/end tags are placed at the start/end of each line if the range is
+/// multiline.
+void html::HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
+ const char *StartTag, const char *EndTag) {
+ SourceManager &SM = R.getSourceMgr();
+ B = SM.getInstantiationLoc(B);
+ E = SM.getInstantiationLoc(E);
+ FileID FID = SM.getFileID(B);
+ assert(SM.getFileID(E) == FID && "B/E not in the same file!");
+
+ unsigned BOffset = SM.getFileOffset(B);
+ unsigned EOffset = SM.getFileOffset(E);
+
+ // Include the whole end token in the range.
+ EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
+
+ bool Invalid = false;
+ const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
+ if (Invalid)
+ return;
+
+ HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
+ BufferStart, StartTag, EndTag);
+}
+
+/// HighlightRange - This is the same as the above method, but takes
+/// decomposed file locations.
+void html::HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E,
+ const char *BufferStart,
+ const char *StartTag, const char *EndTag) {
+ // Insert the tag at the absolute start/end of the range.
+ RB.InsertTextAfter(B, StartTag);
+ RB.InsertTextBefore(E, EndTag);
+
+ // Scan the range to see if there is a \r or \n. If so, and if the line is
+ // not blank, insert tags on that line as well.
+ bool HadOpenTag = true;
+
+ unsigned LastNonWhiteSpace = B;
+ for (unsigned i = B; i != E; ++i) {
+ switch (BufferStart[i]) {
+ case '\r':
+ case '\n':
+ // Okay, we found a newline in the range. If we have an open tag, we need
+ // to insert a close tag at the first non-whitespace before the newline.
+ if (HadOpenTag)
+ RB.InsertTextBefore(LastNonWhiteSpace+1, EndTag);
+
+ // Instead of inserting an open tag immediately after the newline, we
+ // wait until we see a non-whitespace character. This prevents us from
+ // inserting tags around blank lines, and also allows the open tag to
+ // be put *after* whitespace on a non-blank line.
+ HadOpenTag = false;
+ break;
+ case '\0':
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\v':
+ // Ignore whitespace.
+ break;
+
+ default:
+ // If there is no tag open, do it now.
+ if (!HadOpenTag) {
+ RB.InsertTextAfter(i, StartTag);
+ HadOpenTag = true;
+ }
+
+ // Remember this character.
+ LastNonWhiteSpace = i;
+ break;
+ }
+ }
+}
+
+void html::EscapeText(Rewriter &R, FileID FID,
+ bool EscapeSpaces, bool ReplaceTabs) {
+
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
+ const char* C = Buf->getBufferStart();
+ const char* FileEnd = Buf->getBufferEnd();
+
+ assert (C <= FileEnd);
+
+ RewriteBuffer &RB = R.getEditBuffer(FID);
+
+ unsigned ColNo = 0;
+ for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) {
+ switch (*C) {
+ default: ++ColNo; break;
+ case '\n':
+ case '\r':
+ ColNo = 0;
+ break;
+
+ case ' ':
+ if (EscapeSpaces)
+ RB.ReplaceText(FilePos, 1, "&nbsp;");
+ ++ColNo;
+ break;
+ case '\f':
+ RB.ReplaceText(FilePos, 1, "<hr>");
+ ColNo = 0;
+ break;
+
+ case '\t': {
+ if (!ReplaceTabs)
+ break;
+ unsigned NumSpaces = 8-(ColNo&7);
+ if (EscapeSpaces)
+ RB.ReplaceText(FilePos, 1,
+ llvm::StringRef("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
+ "&nbsp;&nbsp;&nbsp;", 6*NumSpaces));
+ else
+ RB.ReplaceText(FilePos, 1, llvm::StringRef(" ", NumSpaces));
+ ColNo += NumSpaces;
+ break;
+ }
+ case '<':
+ RB.ReplaceText(FilePos, 1, "&lt;");
+ ++ColNo;
+ break;
+
+ case '>':
+ RB.ReplaceText(FilePos, 1, "&gt;");
+ ++ColNo;
+ break;
+
+ case '&':
+ RB.ReplaceText(FilePos, 1, "&amp;");
+ ++ColNo;
+ break;
+ }
+ }
+}
+
+std::string html::EscapeText(const std::string& s, bool EscapeSpaces,
+ bool ReplaceTabs) {
+
+ unsigned len = s.size();
+ std::string Str;
+ llvm::raw_string_ostream os(Str);
+
+ for (unsigned i = 0 ; i < len; ++i) {
+
+ char c = s[i];
+ switch (c) {
+ default:
+ os << c; break;
+
+ case ' ':
+ if (EscapeSpaces) os << "&nbsp;";
+ else os << ' ';
+ break;
+
+ case '\t':
+ if (ReplaceTabs) {
+ if (EscapeSpaces)
+ for (unsigned i = 0; i < 4; ++i)
+ os << "&nbsp;";
+ else
+ for (unsigned i = 0; i < 4; ++i)
+ os << " ";
+ }
+ else
+ os << c;
+
+ break;
+
+ case '<': os << "&lt;"; break;
+ case '>': os << "&gt;"; break;
+ case '&': os << "&amp;"; break;
+ }
+ }
+
+ return os.str();
+}
+
+static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo,
+ unsigned B, unsigned E) {
+ llvm::SmallString<256> Str;
+ llvm::raw_svector_ostream OS(Str);
+
+ OS << "<tr><td class=\"num\" id=\"LN"
+ << LineNo << "\">"
+ << LineNo << "</td><td class=\"line\">";
+
+ if (B == E) { // Handle empty lines.
+ OS << " </td></tr>";
+ RB.InsertTextBefore(B, OS.str());
+ } else {
+ RB.InsertTextBefore(B, OS.str());
+ RB.InsertTextBefore(E, "</td></tr>");
+ }
+}
+
+void html::AddLineNumbers(Rewriter& R, FileID FID) {
+
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
+ const char* FileBeg = Buf->getBufferStart();
+ const char* FileEnd = Buf->getBufferEnd();
+ const char* C = FileBeg;
+ RewriteBuffer &RB = R.getEditBuffer(FID);
+
+ assert (C <= FileEnd);
+
+ unsigned LineNo = 0;
+ unsigned FilePos = 0;
+
+ while (C != FileEnd) {
+
+ ++LineNo;
+ unsigned LineStartPos = FilePos;
+ unsigned LineEndPos = FileEnd - FileBeg;
+
+ assert (FilePos <= LineEndPos);
+ assert (C < FileEnd);
+
+ // Scan until the newline (or end-of-file).
+
+ while (C != FileEnd) {
+ char c = *C;
+ ++C;
+
+ if (c == '\n') {
+ LineEndPos = FilePos++;
+ break;
+ }
+
+ ++FilePos;
+ }
+
+ AddLineNumber(RB, LineNo, LineStartPos, LineEndPos);
+ }
+
+ // Add one big table tag that surrounds all of the code.
+ RB.InsertTextBefore(0, "<table class=\"code\">\n");
+ RB.InsertTextAfter(FileEnd - FileBeg, "</table>");
+}
+
+void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
+ const char *title) {
+
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
+ const char* FileStart = Buf->getBufferStart();
+ const char* FileEnd = Buf->getBufferEnd();
+
+ SourceLocation StartLoc = R.getSourceMgr().getLocForStartOfFile(FID);
+ SourceLocation EndLoc = StartLoc.getFileLocWithOffset(FileEnd-FileStart);
+
+ std::string s;
+ llvm::raw_string_ostream os(s);
+ os << "<!doctype html>\n" // Use HTML 5 doctype
+ "<html>\n<head>\n";
+
+ if (title)
+ os << "<title>" << html::EscapeText(title) << "</title>\n";
+
+ os << "<style type=\"text/css\">\n"
+ " body { color:#000000; background-color:#ffffff }\n"
+ " body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
+ " h1 { font-size:14pt }\n"
+ " .code { border-collapse:collapse; width:100%; }\n"
+ " .code { font-family: \"Andale Mono\", monospace; font-size:10pt }\n"
+ " .code { line-height: 1.2em }\n"
+ " .comment { color: green; font-style: oblique }\n"
+ " .keyword { color: blue }\n"
+ " .string_literal { color: red }\n"
+ " .directive { color: darkmagenta }\n"
+ // Macro expansions.
+ " .expansion { display: none; }\n"
+ " .macro:hover .expansion { display: block; border: 2px solid #FF0000; "
+ "padding: 2px; background-color:#FFF0F0; font-weight: normal; "
+ " -webkit-border-radius:5px; -webkit-box-shadow:1px 1px 7px #000; "
+ "position: absolute; top: -1em; left:10em; z-index: 1 } \n"
+ " .macro { color: darkmagenta; background-color:LemonChiffon;"
+ // Macros are position: relative to provide base for expansions.
+ " position: relative }\n"
+ " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n"
+ " .num { text-align:right; font-size:8pt }\n"
+ " .num { color:#444444 }\n"
+ " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n"
+ " .line { white-space: pre }\n"
+ " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n"
+ " .msg { -webkit-border-radius:5px }\n"
+ " .msg { font-family:Helvetica, sans-serif; font-size:8pt }\n"
+ " .msg { float:left }\n"
+ " .msg { padding:0.25em 1ex 0.25em 1ex }\n"
+ " .msg { margin-top:10px; margin-bottom:10px }\n"
+ " .msg { font-weight:bold }\n"
+ " .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }\n"
+ " .msgT { padding:0x; spacing:0x }\n"
+ " .msgEvent { background-color:#fff8b4; color:#000000 }\n"
+ " .msgControl { background-color:#bbbbbb; color:#000000 }\n"
+ " .mrange { background-color:#dfddf3 }\n"
+ " .mrange { border-bottom:1px solid #6F9DBE }\n"
+ " .PathIndex { font-weight: bold; padding:0px 5px 0px 5px; "
+ "margin-right:5px; }\n"
+ " .PathIndex { -webkit-border-radius:8px }\n"
+ " .PathIndexEvent { background-color:#bfba87 }\n"
+ " .PathIndexControl { background-color:#8c8c8c }\n"
+ " .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n"
+ " .CodeRemovalHint { background-color:#de1010 }\n"
+ " .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n"
+ " table.simpletable {\n"
+ " padding: 5px;\n"
+ " font-size:12pt;\n"
+ " margin:20px;\n"
+ " border-collapse: collapse; border-spacing: 0px;\n"
+ " }\n"
+ " td.rowname {\n"
+ " text-align:right; font-weight:bold; color:#444444;\n"
+ " padding-right:2ex; }\n"
+ "</style>\n</head>\n<body>";
+
+ // Generate header
+ R.InsertTextBefore(StartLoc, os.str());
+ // Generate footer
+
+ R.InsertTextAfter(EndLoc, "</body></html>\n");
+}
+
+/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
+/// information about keywords, macro expansions etc. This uses the macro
+/// table state from the end of the file, so it won't be perfectly perfect,
+/// but it will be reasonably close.
+void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
+ RewriteBuffer &RB = R.getEditBuffer(FID);
+
+ const SourceManager &SM = PP.getSourceManager();
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+ Lexer L(FID, FromFile, SM, PP.getLangOptions());
+ const char *BufferStart = L.getBufferStart();
+
+ // Inform the preprocessor that we want to retain comments as tokens, so we
+ // can highlight them.
+ L.SetCommentRetentionState(true);
+
+ // Lex all the tokens in raw mode, to avoid entering #includes or expanding
+ // macros.
+ Token Tok;
+ L.LexFromRawLexer(Tok);
+
+ while (Tok.isNot(tok::eof)) {
+ // Since we are lexing unexpanded tokens, all tokens are from the main
+ // FileID.
+ unsigned TokOffs = SM.getFileOffset(Tok.getLocation());
+ unsigned TokLen = Tok.getLength();
+ switch (Tok.getKind()) {
+ default: break;
+ case tok::identifier:
+ llvm_unreachable("tok::identifier in raw lexing mode!");
+ break;
+ case tok::raw_identifier: {
+ // Fill in Result.IdentifierInfo and update the token kind,
+ // looking up the identifier in the identifier table.
+ PP.LookUpIdentifierInfo(Tok);
+
+ // If this is a pp-identifier, for a keyword, highlight it as such.
+ if (Tok.isNot(tok::identifier))
+ HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
+ "<span class='keyword'>", "</span>");
+ break;
+ }
+ case tok::comment:
+ HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
+ "<span class='comment'>", "</span>");
+ break;
+ case tok::wide_string_literal:
+ // Chop off the L prefix
+ ++TokOffs;
+ --TokLen;
+ // FALL THROUGH.
+ case tok::string_literal:
+ HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
+ "<span class='string_literal'>", "</span>");
+ break;
+ case tok::hash: {
+ // If this is a preprocessor directive, all tokens to end of line are too.
+ if (!Tok.isAtStartOfLine())
+ break;
+
+ // Eat all of the tokens until we get to the next one at the start of
+ // line.
+ unsigned TokEnd = TokOffs+TokLen;
+ L.LexFromRawLexer(Tok);
+ while (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
+ TokEnd = SM.getFileOffset(Tok.getLocation())+Tok.getLength();
+ L.LexFromRawLexer(Tok);
+ }
+
+ // Find end of line. This is a hack.
+ HighlightRange(RB, TokOffs, TokEnd, BufferStart,
+ "<span class='directive'>", "</span>");
+
+ // Don't skip the next token.
+ continue;
+ }
+ }
+
+ L.LexFromRawLexer(Tok);
+ }
+}
+
+namespace {
+/// IgnoringDiagClient - This is a diagnostic client that just ignores all
+/// diags.
+class IgnoringDiagClient : public DiagnosticClient {
+ void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Just ignore it.
+ }
+};
+}
+
+/// HighlightMacros - This uses the macro table state from the end of the
+/// file, to re-expand macros and insert (into the HTML) information about the
+/// macro expansions. This won't be perfectly perfect, but it will be
+/// reasonably close.
+void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
+ // Re-lex the raw token stream into a token buffer.
+ const SourceManager &SM = PP.getSourceManager();
+ std::vector<Token> TokenStream;
+
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+ Lexer L(FID, FromFile, SM, PP.getLangOptions());
+
+ // Lex all the tokens in raw mode, to avoid entering #includes or expanding
+ // macros.
+ while (1) {
+ Token Tok;
+ L.LexFromRawLexer(Tok);
+
+ // If this is a # at the start of a line, discard it from the token stream.
+ // We don't want the re-preprocess step to see #defines, #includes or other
+ // preprocessor directives.
+ if (Tok.is(tok::hash) && Tok.isAtStartOfLine())
+ continue;
+
+ // If this is a ## token, change its kind to unknown so that repreprocessing
+ // it will not produce an error.
+ if (Tok.is(tok::hashhash))
+ Tok.setKind(tok::unknown);
+
+ // If this raw token is an identifier, the raw lexer won't have looked up
+ // the corresponding identifier info for it. Do this now so that it will be
+ // macro expanded when we re-preprocess it.
+ if (Tok.is(tok::raw_identifier))
+ PP.LookUpIdentifierInfo(Tok);
+
+ TokenStream.push_back(Tok);
+
+ if (Tok.is(tok::eof)) break;
+ }
+
+ // Temporarily change the diagnostics object so that we ignore any generated
+ // diagnostics from this pass.
+ Diagnostic TmpDiags(PP.getDiagnostics().getDiagnosticIDs(),
+ new IgnoringDiagClient);
+
+ // FIXME: This is a huge hack; we reuse the input preprocessor because we want
+ // its state, but we aren't actually changing it (we hope). This should really
+ // construct a copy of the preprocessor.
+ Preprocessor &TmpPP = const_cast<Preprocessor&>(PP);
+ Diagnostic *OldDiags = &TmpPP.getDiagnostics();
+ TmpPP.setDiagnostics(TmpDiags);
+
+ // Inform the preprocessor that we don't want comments.
+ TmpPP.SetCommentRetentionState(false, false);
+
+ // Enter the tokens we just lexed. This will cause them to be macro expanded
+ // but won't enter sub-files (because we removed #'s).
+ TmpPP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
+
+ TokenConcatenation ConcatInfo(TmpPP);
+
+ // Lex all the tokens.
+ Token Tok;
+ TmpPP.Lex(Tok);
+ while (Tok.isNot(tok::eof)) {
+ // Ignore non-macro tokens.
+ if (!Tok.getLocation().isMacroID()) {
+ TmpPP.Lex(Tok);
+ continue;
+ }
+
+ // Okay, we have the first token of a macro expansion: highlight the
+ // instantiation by inserting a start tag before the macro instantiation and
+ // end tag after it.
+ std::pair<SourceLocation, SourceLocation> LLoc =
+ SM.getInstantiationRange(Tok.getLocation());
+
+ // Ignore tokens whose instantiation location was not the main file.
+ if (SM.getFileID(LLoc.first) != FID) {
+ TmpPP.Lex(Tok);
+ continue;
+ }
+
+ assert(SM.getFileID(LLoc.second) == FID &&
+ "Start and end of expansion must be in the same ultimate file!");
+
+ std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
+ unsigned LineLen = Expansion.size();
+
+ Token PrevPrevTok;
+ Token PrevTok = Tok;
+ // Okay, eat this token, getting the next one.
+ TmpPP.Lex(Tok);
+
+ // Skip all the rest of the tokens that are part of this macro
+ // instantiation. It would be really nice to pop up a window with all the
+ // spelling of the tokens or something.
+ while (!Tok.is(tok::eof) &&
+ SM.getInstantiationLoc(Tok.getLocation()) == LLoc.first) {
+ // Insert a newline if the macro expansion is getting large.
+ if (LineLen > 60) {
+ Expansion += "<br>";
+ LineLen = 0;
+ }
+
+ LineLen -= Expansion.size();
+
+ // If the tokens were already space separated, or if they must be to avoid
+ // them being implicitly pasted, add a space between them.
+ if (Tok.hasLeadingSpace() ||
+ ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok))
+ Expansion += ' ';
+
+ // Escape any special characters in the token text.
+ Expansion += EscapeText(TmpPP.getSpelling(Tok));
+ LineLen += Expansion.size();
+
+ PrevPrevTok = PrevTok;
+ PrevTok = Tok;
+ TmpPP.Lex(Tok);
+ }
+
+
+ // Insert the expansion as the end tag, so that multi-line macros all get
+ // highlighted.
+ Expansion = "<span class='expansion'>" + Expansion + "</span></span>";
+
+ HighlightRange(R, LLoc.first, LLoc.second,
+ "<span class='macro'>", Expansion.c_str());
+ }
+
+ // Restore diagnostics object back to its own thing.
+ TmpPP.setDiagnostics(*OldDiags);
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteMacros.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteMacros.cpp
new file mode 100644
index 0000000..0453098
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteMacros.cpp
@@ -0,0 +1,217 @@
+//===--- RewriteMacros.cpp - Rewrite macros into their expansions ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This code rewrites macro invocations into their expansions. This gives you
+// a macro expanded file that retains comments and #includes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/Rewriters.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <cstdio>
+
+using namespace clang;
+
+/// isSameToken - Return true if the two specified tokens start have the same
+/// content.
+static bool isSameToken(Token &RawTok, Token &PPTok) {
+ // If two tokens have the same kind and the same identifier info, they are
+ // obviously the same.
+ if (PPTok.getKind() == RawTok.getKind() &&
+ PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
+ return true;
+
+ // Otherwise, if they are different but have the same identifier info, they
+ // are also considered to be the same. This allows keywords and raw lexed
+ // identifiers with the same name to be treated the same.
+ if (PPTok.getIdentifierInfo() &&
+ PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
+ return true;
+
+ return false;
+}
+
+
+/// GetNextRawTok - Return the next raw token in the stream, skipping over
+/// comments if ReturnComment is false.
+static const Token &GetNextRawTok(const std::vector<Token> &RawTokens,
+ unsigned &CurTok, bool ReturnComment) {
+ assert(CurTok < RawTokens.size() && "Overran eof!");
+
+ // If the client doesn't want comments and we have one, skip it.
+ if (!ReturnComment && RawTokens[CurTok].is(tok::comment))
+ ++CurTok;
+
+ return RawTokens[CurTok++];
+}
+
+
+/// LexRawTokensFromMainFile - Lets all the raw tokens from the main file into
+/// the specified vector.
+static void LexRawTokensFromMainFile(Preprocessor &PP,
+ std::vector<Token> &RawTokens) {
+ SourceManager &SM = PP.getSourceManager();
+
+ // Create a lexer to lex all the tokens of the main file in raw mode. Even
+ // though it is in raw mode, it will not return comments.
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
+ Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
+
+ // Switch on comment lexing because we really do want them.
+ RawLex.SetCommentRetentionState(true);
+
+ Token RawTok;
+ do {
+ RawLex.LexFromRawLexer(RawTok);
+
+ // If we have an identifier with no identifier info for our raw token, look
+ // up the indentifier info. This is important for equality comparison of
+ // identifier tokens.
+ if (RawTok.is(tok::raw_identifier))
+ PP.LookUpIdentifierInfo(RawTok);
+
+ RawTokens.push_back(RawTok);
+ } while (RawTok.isNot(tok::eof));
+}
+
+
+/// RewriteMacrosInInput - Implement -rewrite-macros mode.
+void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) {
+ SourceManager &SM = PP.getSourceManager();
+
+ Rewriter Rewrite;
+ Rewrite.setSourceMgr(SM, PP.getLangOptions());
+ RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID());
+
+ std::vector<Token> RawTokens;
+ LexRawTokensFromMainFile(PP, RawTokens);
+ unsigned CurRawTok = 0;
+ Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+
+
+ // Get the first preprocessing token.
+ PP.EnterMainSourceFile();
+ Token PPTok;
+ PP.Lex(PPTok);
+
+ // Preprocess the input file in parallel with raw lexing the main file. Ignore
+ // all tokens that are preprocessed from a file other than the main file (e.g.
+ // a header). If we see tokens that are in the preprocessed file but not the
+ // lexed file, we have a macro expansion. If we see tokens in the lexed file
+ // that aren't in the preprocessed view, we have macros that expand to no
+ // tokens, or macro arguments etc.
+ while (RawTok.isNot(tok::eof) || PPTok.isNot(tok::eof)) {
+ SourceLocation PPLoc = SM.getInstantiationLoc(PPTok.getLocation());
+
+ // If PPTok is from a different source file, ignore it.
+ if (!SM.isFromMainFile(PPLoc)) {
+ PP.Lex(PPTok);
+ continue;
+ }
+
+ // If the raw file hits a preprocessor directive, they will be extra tokens
+ // in the raw file that don't exist in the preprocsesed file. However, we
+ // choose to preserve them in the output file and otherwise handle them
+ // specially.
+ if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) {
+ // If this is a #warning directive or #pragma mark (GNU extensions),
+ // comment the line out.
+ if (RawTokens[CurRawTok].is(tok::identifier)) {
+ const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo();
+ if (II->getName() == "warning") {
+ // Comment out #warning.
+ RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
+ } else if (II->getName() == "pragma" &&
+ RawTokens[CurRawTok+1].is(tok::identifier) &&
+ (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() ==
+ "mark")) {
+ // Comment out #pragma mark.
+ RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
+ }
+ }
+
+ // Otherwise, if this is a #include or some other directive, just leave it
+ // in the file by skipping over the line.
+ RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+ while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof))
+ RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+ continue;
+ }
+
+ // Okay, both tokens are from the same file. Get their offsets from the
+ // start of the file.
+ unsigned PPOffs = SM.getFileOffset(PPLoc);
+ unsigned RawOffs = SM.getFileOffset(RawTok.getLocation());
+
+ // If the offsets are the same and the token kind is the same, ignore them.
+ if (PPOffs == RawOffs && isSameToken(RawTok, PPTok)) {
+ RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+ PP.Lex(PPTok);
+ continue;
+ }
+
+ // If the PP token is farther along than the raw token, something was
+ // deleted. Comment out the raw token.
+ if (RawOffs <= PPOffs) {
+ // Comment out a whole run of tokens instead of bracketing each one with
+ // comments. Add a leading space if RawTok didn't have one.
+ bool HasSpace = RawTok.hasLeadingSpace();
+ RB.InsertTextAfter(RawOffs, " /*"+HasSpace);
+ unsigned EndPos;
+
+ do {
+ EndPos = RawOffs+RawTok.getLength();
+
+ RawTok = GetNextRawTok(RawTokens, CurRawTok, true);
+ RawOffs = SM.getFileOffset(RawTok.getLocation());
+
+ if (RawTok.is(tok::comment)) {
+ // Skip past the comment.
+ RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
+ break;
+ }
+
+ } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() &&
+ (PPOffs != RawOffs || !isSameToken(RawTok, PPTok)));
+
+ RB.InsertTextBefore(EndPos, "*/");
+ continue;
+ }
+
+ // Otherwise, there was a replacement an expansion. Insert the new token
+ // in the output buffer. Insert the whole run of new tokens at once to get
+ // them in the right order.
+ unsigned InsertPos = PPOffs;
+ std::string Expansion;
+ while (PPOffs < RawOffs) {
+ Expansion += ' ' + PP.getSpelling(PPTok);
+ PP.Lex(PPTok);
+ PPLoc = SM.getInstantiationLoc(PPTok.getLocation());
+ PPOffs = SM.getFileOffset(PPLoc);
+ }
+ Expansion += ' ';
+ RB.InsertTextBefore(InsertPos, Expansion);
+ }
+
+ // Get the buffer corresponding to MainFileID. If we haven't changed it, then
+ // we are done.
+ if (const RewriteBuffer *RewriteBuf =
+ Rewrite.getRewriteBufferFor(SM.getMainFileID())) {
+ //printf("Changed:\n");
+ *OS << std::string(RewriteBuf->begin(), RewriteBuf->end());
+ } else {
+ fprintf(stderr, "No changes\n");
+ }
+ OS->flush();
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
new file mode 100644
index 0000000..875a0c7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
@@ -0,0 +1,5928 @@
+//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hacks and fun related to the code rewriter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/ASTConsumers.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace clang;
+using llvm::utostr;
+
+namespace {
+ class RewriteObjC : public ASTConsumer {
+ enum {
+ BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
+ block, ... */
+ BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
+ BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
+ __block variable */
+ BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
+ helpers */
+ BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
+ support routines */
+ BLOCK_BYREF_CURRENT_MAX = 256
+ };
+
+ enum {
+ BLOCK_NEEDS_FREE = (1 << 24),
+ BLOCK_HAS_COPY_DISPOSE = (1 << 25),
+ BLOCK_HAS_CXX_OBJ = (1 << 26),
+ BLOCK_IS_GC = (1 << 27),
+ BLOCK_IS_GLOBAL = (1 << 28),
+ BLOCK_HAS_DESCRIPTOR = (1 << 29)
+ };
+
+ Rewriter Rewrite;
+ Diagnostic &Diags;
+ const LangOptions &LangOpts;
+ unsigned RewriteFailedDiag;
+ unsigned TryFinallyContainsReturnDiag;
+
+ ASTContext *Context;
+ SourceManager *SM;
+ TranslationUnitDecl *TUDecl;
+ FileID MainFileID;
+ const char *MainFileStart, *MainFileEnd;
+ SourceLocation LastIncLoc;
+
+ llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
+ llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
+ llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
+ llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
+ llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
+ llvm::SmallVector<Stmt *, 32> Stmts;
+ llvm::SmallVector<int, 8> ObjCBcLabelNo;
+ // Remember all the @protocol(<expr>) expressions.
+ llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
+
+ llvm::DenseSet<uint64_t> CopyDestroyCache;
+
+ unsigned NumObjCStringLiterals;
+
+ FunctionDecl *MsgSendFunctionDecl;
+ FunctionDecl *MsgSendSuperFunctionDecl;
+ FunctionDecl *MsgSendStretFunctionDecl;
+ FunctionDecl *MsgSendSuperStretFunctionDecl;
+ FunctionDecl *MsgSendFpretFunctionDecl;
+ FunctionDecl *GetClassFunctionDecl;
+ FunctionDecl *GetMetaClassFunctionDecl;
+ FunctionDecl *GetSuperClassFunctionDecl;
+ FunctionDecl *SelGetUidFunctionDecl;
+ FunctionDecl *CFStringFunctionDecl;
+ FunctionDecl *SuperContructorFunctionDecl;
+
+ // ObjC string constant support.
+ VarDecl *ConstantStringClassReference;
+ RecordDecl *NSStringRecord;
+
+ // ObjC foreach break/continue generation support.
+ int BcLabelCount;
+
+ // Needed for super.
+ ObjCMethodDecl *CurMethodDef;
+ RecordDecl *SuperStructDecl;
+ RecordDecl *ConstantStringDecl;
+
+ TypeDecl *ProtocolTypeDecl;
+ QualType getProtocolType();
+
+ // Needed for header files being rewritten
+ bool IsHeader;
+
+ std::string InFileName;
+ llvm::raw_ostream* OutFile;
+
+ bool SilenceRewriteMacroWarning;
+ bool objc_impl_method;
+
+ std::string Preamble;
+
+ // Block expressions.
+ llvm::SmallVector<BlockExpr *, 32> Blocks;
+ llvm::SmallVector<int, 32> InnerDeclRefsCount;
+ llvm::SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs;
+
+ llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
+
+ // Block related declarations.
+ llvm::SmallVector<ValueDecl *, 8> BlockByCopyDecls;
+ llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
+ llvm::SmallVector<ValueDecl *, 8> BlockByRefDecls;
+ llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
+ llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
+ llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
+ llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
+
+ llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
+
+ // This maps a property to it's assignment statement.
+ llvm::DenseMap<Expr *, BinaryOperator *> PropSetters;
+ // This maps a property to it's synthesied message expression.
+ // This allows us to rewrite chained getters (e.g. o.a.b.c).
+ llvm::DenseMap<Expr *, Stmt *> PropGetters;
+
+ // This maps an original source AST to it's rewritten form. This allows
+ // us to avoid rewriting the same node twice (which is very uncommon).
+ // This is needed to support some of the exotic property rewriting.
+ llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
+
+ FunctionDecl *CurFunctionDef;
+ FunctionDecl *CurFunctionDeclToDeclareForBlock;
+ VarDecl *GlobalVarDecl;
+
+ bool DisableReplaceStmt;
+
+ static const int OBJC_ABI_VERSION = 7;
+ public:
+ virtual void Initialize(ASTContext &context);
+
+ // Top Level Driver code.
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
+ void HandleDeclInMainFile(Decl *D);
+ RewriteObjC(std::string inFile, llvm::raw_ostream *OS,
+ Diagnostic &D, const LangOptions &LOpts,
+ bool silenceMacroWarn);
+
+ ~RewriteObjC() {}
+
+ virtual void HandleTranslationUnit(ASTContext &C);
+
+ void ReplaceStmt(Stmt *Old, Stmt *New) {
+ Stmt *ReplacingStmt = ReplacedNodes[Old];
+
+ if (ReplacingStmt)
+ return; // We can't rewrite the same node twice.
+
+ if (DisableReplaceStmt)
+ return; // Used when rewriting the assignment of a property setter.
+
+ // If replacement succeeded or warning disabled return with no warning.
+ if (!Rewrite.ReplaceStmt(Old, New)) {
+ ReplacedNodes[Old] = New;
+ return;
+ }
+ if (SilenceRewriteMacroWarning)
+ return;
+ Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+ << Old->getSourceRange();
+ }
+
+ void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
+ // Measure the old text.
+ int Size = Rewrite.getRangeSize(SrcRange);
+ if (Size == -1) {
+ Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+ << Old->getSourceRange();
+ return;
+ }
+ // Get the new text.
+ std::string SStr;
+ llvm::raw_string_ostream S(SStr);
+ New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
+ const std::string &Str = S.str();
+
+ // If replacement succeeded or warning disabled return with no warning.
+ if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
+ ReplacedNodes[Old] = New;
+ return;
+ }
+ if (SilenceRewriteMacroWarning)
+ return;
+ Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+ << Old->getSourceRange();
+ }
+
+ void InsertText(SourceLocation Loc, llvm::StringRef Str,
+ bool InsertAfter = true) {
+ // If insertion succeeded or warning disabled return with no warning.
+ if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
+ SilenceRewriteMacroWarning)
+ return;
+
+ Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
+ }
+
+ void ReplaceText(SourceLocation Start, unsigned OrigLength,
+ llvm::StringRef Str) {
+ // If removal succeeded or warning disabled return with no warning.
+ if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
+ SilenceRewriteMacroWarning)
+ return;
+
+ Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
+ }
+
+ // Syntactic Rewriting.
+ void RewriteInclude();
+ void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
+ void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
+ ObjCImplementationDecl *IMD,
+ ObjCCategoryImplDecl *CID);
+ void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
+ void RewriteImplementationDecl(Decl *Dcl);
+ void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
+ ObjCMethodDecl *MDecl, std::string &ResultStr);
+ void RewriteTypeIntoString(QualType T, std::string &ResultStr,
+ const FunctionType *&FPRetType);
+ void RewriteByRefString(std::string &ResultStr, const std::string &Name,
+ ValueDecl *VD, bool def=false);
+ void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
+ void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
+ void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
+ void RewriteMethodDeclaration(ObjCMethodDecl *Method);
+ void RewriteProperty(ObjCPropertyDecl *prop);
+ void RewriteFunctionDecl(FunctionDecl *FD);
+ void RewriteBlockPointerType(std::string& Str, QualType Type);
+ void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
+ void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
+ void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
+ void RewriteTypeOfDecl(VarDecl *VD);
+ void RewriteObjCQualifiedInterfaceTypes(Expr *E);
+ bool needToScanForQualifiers(QualType T);
+ QualType getSuperStructType();
+ QualType getConstantStringStructType();
+ QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
+ bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
+
+ // Expression Rewriting.
+ Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
+ void CollectPropertySetters(Stmt *S);
+
+ Stmt *CurrentBody;
+ ParentMap *PropParentMap; // created lazily.
+
+ Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
+ Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
+ bool &replaced);
+ Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
+ Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr);
+ Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
+ SourceRange SrcRange);
+ Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
+ Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
+ Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
+ Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
+ void WarnAboutReturnGotoStmts(Stmt *S);
+ void HasReturnStmts(Stmt *S, bool &hasReturns);
+ void RewriteTryReturnStmts(Stmt *S);
+ void RewriteSyncReturnStmts(Stmt *S, std::string buf);
+ Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
+ Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
+ Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
+ Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
+ SourceLocation OrigEnd);
+ CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
+ Expr **args, unsigned nargs,
+ SourceLocation StartLoc=SourceLocation(),
+ SourceLocation EndLoc=SourceLocation());
+ Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
+ SourceLocation StartLoc=SourceLocation(),
+ SourceLocation EndLoc=SourceLocation());
+ Stmt *RewriteBreakStmt(BreakStmt *S);
+ Stmt *RewriteContinueStmt(ContinueStmt *S);
+ void SynthCountByEnumWithState(std::string &buf);
+
+ void SynthMsgSendFunctionDecl();
+ void SynthMsgSendSuperFunctionDecl();
+ void SynthMsgSendStretFunctionDecl();
+ void SynthMsgSendFpretFunctionDecl();
+ void SynthMsgSendSuperStretFunctionDecl();
+ void SynthGetClassFunctionDecl();
+ void SynthGetMetaClassFunctionDecl();
+ void SynthGetSuperClassFunctionDecl();
+ void SynthSelGetUidFunctionDecl();
+ void SynthSuperContructorFunctionDecl();
+
+ // Metadata emission.
+ void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+ std::string &Result);
+
+ void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
+ std::string &Result);
+
+ template<typename MethodIterator>
+ void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+ MethodIterator MethodEnd,
+ bool IsInstanceMethod,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
+ std::string &Result);
+
+ void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
+ std::string &Result);
+ void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
+ std::string &Result);
+ void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
+ std::string &Result);
+ void SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar,
+ std::string &Result);
+ void RewriteImplementations();
+ void SynthesizeMetaDataIntoBuffer(std::string &Result);
+
+ // Block rewriting.
+ void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
+ void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
+
+ void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
+ void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
+
+ // Block specific rewrite rules.
+ void RewriteBlockPointerDecl(NamedDecl *VD);
+ void RewriteByRefVar(VarDecl *VD);
+ std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
+ Stmt *RewriteBlockDeclRefExpr(Expr *VD);
+ Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
+ void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
+
+ std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+ llvm::StringRef funcName, std::string Tag);
+ std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
+ llvm::StringRef funcName, std::string Tag);
+ std::string SynthesizeBlockImpl(BlockExpr *CE,
+ std::string Tag, std::string Desc);
+ std::string SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag,
+ int i, llvm::StringRef funcName,
+ unsigned hasCopy);
+ Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
+ void SynthesizeBlockLiterals(SourceLocation FunLocStart,
+ llvm::StringRef FunName);
+ void RewriteRecordBody(RecordDecl *RD);
+
+ void CollectBlockDeclRefInfo(BlockExpr *Exp);
+ void GetBlockDeclRefExprs(Stmt *S);
+ void GetInnerBlockDeclRefExprs(Stmt *S,
+ llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
+ llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
+
+ // We avoid calling Type::isBlockPointerType(), since it operates on the
+ // canonical type. We only care if the top-level type is a closure pointer.
+ bool isTopLevelBlockPointerType(QualType T) {
+ return isa<BlockPointerType>(T);
+ }
+
+ /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
+ /// to a function pointer type and upon success, returns true; false
+ /// otherwise.
+ bool convertBlockPointerToFunctionPointer(QualType &T) {
+ if (isTopLevelBlockPointerType(T)) {
+ const BlockPointerType *BPT = T->getAs<BlockPointerType>();
+ T = Context->getPointerType(BPT->getPointeeType());
+ return true;
+ }
+ return false;
+ }
+
+ void convertToUnqualifiedObjCType(QualType &T) {
+ if (T->isObjCQualifiedIdType())
+ T = Context->getObjCIdType();
+ else if (T->isObjCQualifiedClassType())
+ T = Context->getObjCClassType();
+ else if (T->isObjCObjectPointerType() &&
+ T->getPointeeType()->isObjCQualifiedInterfaceType())
+ T = Context->getObjCIdType();
+ }
+
+ // FIXME: This predicate seems like it would be useful to add to ASTContext.
+ bool isObjCType(QualType T) {
+ if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
+ return false;
+
+ QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
+
+ if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
+ OCT == Context->getCanonicalType(Context->getObjCClassType()))
+ return true;
+
+ if (const PointerType *PT = OCT->getAs<PointerType>()) {
+ if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
+ PT->getPointeeType()->isObjCQualifiedIdType())
+ return true;
+ }
+ return false;
+ }
+ bool PointerTypeTakesAnyBlockArguments(QualType QT);
+ bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
+ void GetExtentOfArgList(const char *Name, const char *&LParen,
+ const char *&RParen);
+ void RewriteCastExpr(CStyleCastExpr *CE);
+
+ FunctionDecl *SynthBlockInitFunctionDecl(llvm::StringRef name);
+ Stmt *SynthBlockInitExpr(BlockExpr *Exp,
+ const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs);
+
+ void QuoteDoublequotes(std::string &From, std::string &To) {
+ for (unsigned i = 0; i < From.length(); i++) {
+ if (From[i] == '"')
+ To += "\\\"";
+ else
+ To += From[i];
+ }
+ }
+
+ QualType getSimpleFunctionType(QualType result,
+ const QualType *args,
+ unsigned numArgs,
+ bool variadic = false) {
+ FunctionProtoType::ExtProtoInfo fpi;
+ fpi.Variadic = variadic;
+ return Context->getFunctionType(result, args, numArgs, fpi);
+ }
+ };
+
+ // Helper function: create a CStyleCastExpr with trivial type source info.
+ CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
+ CastKind Kind, Expr *E) {
+ TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
+ return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo,
+ SourceLocation(), SourceLocation());
+ }
+}
+
+void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
+ NamedDecl *D) {
+ if (const FunctionProtoType *fproto
+ = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
+ for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
+ E = fproto->arg_type_end(); I && (I != E); ++I)
+ if (isTopLevelBlockPointerType(*I)) {
+ // All the args are checked/rewritten. Don't call twice!
+ RewriteBlockPointerDecl(D);
+ break;
+ }
+ }
+}
+
+void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
+ const PointerType *PT = funcType->getAs<PointerType>();
+ if (PT && PointerTypeTakesAnyBlockArguments(funcType))
+ RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
+}
+
+static bool IsHeaderFile(const std::string &Filename) {
+ std::string::size_type DotPos = Filename.rfind('.');
+
+ if (DotPos == std::string::npos) {
+ // no file extension
+ return false;
+ }
+
+ std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
+ // C header: .h
+ // C++ header: .hh or .H;
+ return Ext == "h" || Ext == "hh" || Ext == "H";
+}
+
+RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS,
+ Diagnostic &D, const LangOptions &LOpts,
+ bool silenceMacroWarn)
+ : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
+ SilenceRewriteMacroWarning(silenceMacroWarn) {
+ IsHeader = IsHeaderFile(inFile);
+ RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
+ "rewriting sub-expression within a macro (may not be correct)");
+ TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning,
+ "rewriter doesn't support user-specified control flow semantics "
+ "for @try/@finally (code may not execute properly)");
+}
+
+ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
+ llvm::raw_ostream* OS,
+ Diagnostic &Diags,
+ const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning) {
+ return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+}
+
+void RewriteObjC::Initialize(ASTContext &context) {
+ Context = &context;
+ SM = &Context->getSourceManager();
+ TUDecl = Context->getTranslationUnitDecl();
+ MsgSendFunctionDecl = 0;
+ MsgSendSuperFunctionDecl = 0;
+ MsgSendStretFunctionDecl = 0;
+ MsgSendSuperStretFunctionDecl = 0;
+ MsgSendFpretFunctionDecl = 0;
+ GetClassFunctionDecl = 0;
+ GetMetaClassFunctionDecl = 0;
+ GetSuperClassFunctionDecl = 0;
+ SelGetUidFunctionDecl = 0;
+ CFStringFunctionDecl = 0;
+ ConstantStringClassReference = 0;
+ NSStringRecord = 0;
+ CurMethodDef = 0;
+ CurFunctionDef = 0;
+ CurFunctionDeclToDeclareForBlock = 0;
+ GlobalVarDecl = 0;
+ SuperStructDecl = 0;
+ ProtocolTypeDecl = 0;
+ ConstantStringDecl = 0;
+ BcLabelCount = 0;
+ SuperContructorFunctionDecl = 0;
+ NumObjCStringLiterals = 0;
+ PropParentMap = 0;
+ CurrentBody = 0;
+ DisableReplaceStmt = false;
+ objc_impl_method = false;
+
+ // Get the ID and start/end of the main file.
+ MainFileID = SM->getMainFileID();
+ const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
+ MainFileStart = MainBuf->getBufferStart();
+ MainFileEnd = MainBuf->getBufferEnd();
+
+ Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
+
+ // declaring objc_selector outside the parameter list removes a silly
+ // scope related warning...
+ if (IsHeader)
+ Preamble = "#pragma once\n";
+ Preamble += "struct objc_selector; struct objc_class;\n";
+ Preamble += "struct __rw_objc_super { struct objc_object *object; ";
+ Preamble += "struct objc_object *superClass; ";
+ if (LangOpts.Microsoft) {
+ // Add a constructor for creating temporary objects.
+ Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
+ ": ";
+ Preamble += "object(o), superClass(s) {} ";
+ }
+ Preamble += "};\n";
+ Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
+ Preamble += "typedef struct objc_object Protocol;\n";
+ Preamble += "#define _REWRITER_typedef_Protocol\n";
+ Preamble += "#endif\n";
+ if (LangOpts.Microsoft) {
+ Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
+ Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
+ } else
+ Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
+ Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
+ Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret";
+ Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret";
+ Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
+ Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
+ Preamble += "(const char *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
+ Preamble += "(struct objc_class *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
+ Preamble += "(const char *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
+ Preamble += "(struct objc_class *, struct objc_object *);\n";
+ // @synchronized hooks.
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
+ Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
+ Preamble += "struct __objcFastEnumerationState {\n\t";
+ Preamble += "unsigned long state;\n\t";
+ Preamble += "void **itemsPtr;\n\t";
+ Preamble += "unsigned long *mutationsPtr;\n\t";
+ Preamble += "unsigned long extra[5];\n};\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
+ Preamble += "#define __FASTENUMERATIONSTATE\n";
+ Preamble += "#endif\n";
+ Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
+ Preamble += "struct __NSConstantStringImpl {\n";
+ Preamble += " int *isa;\n";
+ Preamble += " int flags;\n";
+ Preamble += " char *str;\n";
+ Preamble += " long length;\n";
+ Preamble += "};\n";
+ Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
+ Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
+ Preamble += "#else\n";
+ Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
+ Preamble += "#endif\n";
+ Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
+ Preamble += "#endif\n";
+ // Blocks preamble.
+ Preamble += "#ifndef BLOCK_IMPL\n";
+ Preamble += "#define BLOCK_IMPL\n";
+ Preamble += "struct __block_impl {\n";
+ Preamble += " void *isa;\n";
+ Preamble += " int Flags;\n";
+ Preamble += " int Reserved;\n";
+ Preamble += " void *FuncPtr;\n";
+ Preamble += "};\n";
+ Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
+ Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
+ Preamble += "extern \"C\" __declspec(dllexport) "
+ "void _Block_object_assign(void *, const void *, const int);\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
+ Preamble += "#else\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
+ Preamble += "#endif\n";
+ Preamble += "#endif\n";
+ if (LangOpts.Microsoft) {
+ Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
+ Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
+ Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
+ Preamble += "#define __attribute__(X)\n";
+ Preamble += "#endif\n";
+ Preamble += "#define __weak\n";
+ }
+ else {
+ Preamble += "#define __block\n";
+ Preamble += "#define __weak\n";
+ }
+ // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
+ // as this avoids warning in any 64bit/32bit compilation model.
+ Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Top Level Driver Code
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ // Two cases: either the decl could be in the main file, or it could be in a
+ // #included file. If the former, rewrite it now. If the later, check to see
+ // if we rewrote the #include/#import.
+ SourceLocation Loc = D->getLocation();
+ Loc = SM->getInstantiationLoc(Loc);
+
+ // If this is for a builtin, ignore it.
+ if (Loc.isInvalid()) return;
+
+ // Look for built-in declarations that we need to refer during the rewrite.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ RewriteFunctionDecl(FD);
+ } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
+ // declared in <Foundation/NSString.h>
+ if (FVD->getName() == "_NSConstantStringClassReference") {
+ ConstantStringClassReference = FVD;
+ return;
+ }
+ } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
+ RewriteInterfaceDecl(MD);
+ } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
+ RewriteCategoryDecl(CD);
+ } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+ RewriteProtocolDecl(PD);
+ } else if (ObjCForwardProtocolDecl *FP =
+ dyn_cast<ObjCForwardProtocolDecl>(D)){
+ RewriteForwardProtocolDecl(FP);
+ } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
+ // Recurse into linkage specifications
+ for (DeclContext::decl_iterator DI = LSD->decls_begin(),
+ DIEnd = LSD->decls_end();
+ DI != DIEnd; ++DI)
+ HandleTopLevelSingleDecl(*DI);
+ }
+ // If we have a decl in the main file, see if we should rewrite it.
+ if (SM->isFromMainFile(Loc))
+ return HandleDeclInMainFile(D);
+}
+
+//===----------------------------------------------------------------------===//
+// Syntactic (non-AST) Rewriting Code
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::RewriteInclude() {
+ SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
+ llvm::StringRef MainBuf = SM->getBufferData(MainFileID);
+ const char *MainBufStart = MainBuf.begin();
+ const char *MainBufEnd = MainBuf.end();
+ size_t ImportLen = strlen("import");
+
+ // Loop over the whole file, looking for includes.
+ for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
+ if (*BufPtr == '#') {
+ if (++BufPtr == MainBufEnd)
+ return;
+ while (*BufPtr == ' ' || *BufPtr == '\t')
+ if (++BufPtr == MainBufEnd)
+ return;
+ if (!strncmp(BufPtr, "import", ImportLen)) {
+ // replace import with include
+ SourceLocation ImportLoc =
+ LocStart.getFileLocWithOffset(BufPtr-MainBufStart);
+ ReplaceText(ImportLoc, ImportLen, "include");
+ BufPtr += ImportLen;
+ }
+ }
+ }
+}
+
+static std::string getIvarAccessString(ObjCIvarDecl *OID) {
+ const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
+ std::string S;
+ S = "((struct ";
+ S += ClassDecl->getIdentifier()->getName();
+ S += "_IMPL *)self)->";
+ S += OID->getName();
+ return S;
+}
+
+void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
+ ObjCImplementationDecl *IMD,
+ ObjCCategoryImplDecl *CID) {
+ static bool objcGetPropertyDefined = false;
+ static bool objcSetPropertyDefined = false;
+ SourceLocation startLoc = PID->getLocStart();
+ InsertText(startLoc, "// ");
+ const char *startBuf = SM->getCharacterData(startLoc);
+ assert((*startBuf == '@') && "bogus @synthesize location");
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "@synthesize: can't find ';'");
+ SourceLocation onePastSemiLoc =
+ startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ return; // FIXME: is this correct?
+
+ // Generate the 'getter' function.
+ ObjCPropertyDecl *PD = PID->getPropertyDecl();
+ ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
+
+ if (!OID)
+ return;
+ unsigned Attributes = PD->getPropertyAttributes();
+ if (!PD->getGetterMethodDecl()->isDefined()) {
+ bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
+ (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy));
+ std::string Getr;
+ if (GenGetProperty && !objcGetPropertyDefined) {
+ objcGetPropertyDefined = true;
+ // FIXME. Is this attribute correct in all cases?
+ Getr = "\nextern \"C\" __declspec(dllimport) "
+ "id objc_getProperty(id, SEL, long, bool);\n";
+ }
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
+ PD->getGetterMethodDecl(), Getr);
+ Getr += "{ ";
+ // Synthesize an explicit cast to gain access to the ivar.
+ // See objc-act.c:objc_synthesize_new_getter() for details.
+ if (GenGetProperty) {
+ // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
+ Getr += "typedef ";
+ const FunctionType *FPRetType = 0;
+ RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr,
+ FPRetType);
+ Getr += " _TYPE";
+ if (FPRetType) {
+ Getr += ")"; // close the precedence "scope" for "*".
+
+ // Now, emit the argument types (if any).
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
+ Getr += "(";
+ for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+ if (i) Getr += ", ";
+ std::string ParamStr = FT->getArgType(i).getAsString(
+ Context->PrintingPolicy);
+ Getr += ParamStr;
+ }
+ if (FT->isVariadic()) {
+ if (FT->getNumArgs()) Getr += ", ";
+ Getr += "...";
+ }
+ Getr += ")";
+ } else
+ Getr += "()";
+ }
+ Getr += ";\n";
+ Getr += "return (_TYPE)";
+ Getr += "objc_getProperty(self, _cmd, ";
+ SynthesizeIvarOffsetComputation(OID, Getr);
+ Getr += ", 1)";
+ }
+ else
+ Getr += "return " + getIvarAccessString(OID);
+ Getr += "; }";
+ InsertText(onePastSemiLoc, Getr);
+ }
+
+ if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
+ return;
+
+ // Generate the 'setter' function.
+ std::string Setr;
+ bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy);
+ if (GenSetProperty && !objcSetPropertyDefined) {
+ objcSetPropertyDefined = true;
+ // FIXME. Is this attribute correct in all cases?
+ Setr = "\nextern \"C\" __declspec(dllimport) "
+ "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
+ }
+
+ RewriteObjCMethodDecl(OID->getContainingInterface(),
+ PD->getSetterMethodDecl(), Setr);
+ Setr += "{ ";
+ // Synthesize an explicit cast to initialize the ivar.
+ // See objc-act.c:objc_synthesize_new_setter() for details.
+ if (GenSetProperty) {
+ Setr += "objc_setProperty (self, _cmd, ";
+ SynthesizeIvarOffsetComputation(OID, Setr);
+ Setr += ", (id)";
+ Setr += PD->getName();
+ Setr += ", ";
+ if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ Setr += "0, ";
+ else
+ Setr += "1, ";
+ if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
+ Setr += "1)";
+ else
+ Setr += "0)";
+ }
+ else {
+ Setr += getIvarAccessString(OID) + " = ";
+ Setr += PD->getName();
+ }
+ Setr += "; }";
+ InsertText(onePastSemiLoc, Setr);
+}
+
+void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
+ // Get the start location and compute the semi location.
+ SourceLocation startLoc = ClassDecl->getLocation();
+ const char *startBuf = SM->getCharacterData(startLoc);
+ const char *semiPtr = strchr(startBuf, ';');
+
+ // Translate to typedef's that forward reference structs with the same name
+ // as the class. As a convenience, we include the original declaration
+ // as a comment.
+ std::string typedefString;
+ typedefString += "// @class ";
+ for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
+ I != E; ++I) {
+ ObjCInterfaceDecl *ForwardDecl = I->getInterface();
+ typedefString += ForwardDecl->getNameAsString();
+ if (I+1 != E)
+ typedefString += ", ";
+ else
+ typedefString += ";\n";
+ }
+
+ for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
+ I != E; ++I) {
+ ObjCInterfaceDecl *ForwardDecl = I->getInterface();
+ typedefString += "#ifndef _REWRITER_typedef_";
+ typedefString += ForwardDecl->getNameAsString();
+ typedefString += "\n";
+ typedefString += "#define _REWRITER_typedef_";
+ typedefString += ForwardDecl->getNameAsString();
+ typedefString += "\n";
+ typedefString += "typedef struct objc_object ";
+ typedefString += ForwardDecl->getNameAsString();
+ typedefString += ";\n#endif\n";
+ }
+
+ // Replace the @class with typedefs corresponding to the classes.
+ ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
+}
+
+void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
+ // When method is a synthesized one, such as a getter/setter there is
+ // nothing to rewrite.
+ if (Method->isSynthesized())
+ return;
+ SourceLocation LocStart = Method->getLocStart();
+ SourceLocation LocEnd = Method->getLocEnd();
+
+ if (SM->getInstantiationLineNumber(LocEnd) >
+ SM->getInstantiationLineNumber(LocStart)) {
+ InsertText(LocStart, "#if 0\n");
+ ReplaceText(LocEnd, 1, ";\n#endif\n");
+ } else {
+ InsertText(LocStart, "// ");
+ }
+}
+
+void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
+ SourceLocation Loc = prop->getAtLoc();
+
+ ReplaceText(Loc, 0, "// ");
+ // FIXME: handle properties that are declared across multiple lines.
+}
+
+void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
+ SourceLocation LocStart = CatDecl->getLocStart();
+
+ // FIXME: handle category headers that are declared across multiple lines.
+ ReplaceText(LocStart, 0, "// ");
+
+ for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
+ E = CatDecl->prop_end(); I != E; ++I)
+ RewriteProperty(*I);
+
+ for (ObjCCategoryDecl::instmeth_iterator
+ I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+ for (ObjCCategoryDecl::classmeth_iterator
+ I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+
+ // Lastly, comment out the @end.
+ ReplaceText(CatDecl->getAtEndRange().getBegin(),
+ strlen("@end"), "/* @end */");
+}
+
+void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
+ SourceLocation LocStart = PDecl->getLocStart();
+
+ // FIXME: handle protocol headers that are declared across multiple lines.
+ ReplaceText(LocStart, 0, "// ");
+
+ for (ObjCProtocolDecl::instmeth_iterator
+ I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+ for (ObjCProtocolDecl::classmeth_iterator
+ I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+
+ for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(),
+ E = PDecl->prop_end(); I != E; ++I)
+ RewriteProperty(*I);
+
+ // Lastly, comment out the @end.
+ SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
+ ReplaceText(LocEnd, strlen("@end"), "/* @end */");
+
+ // Must comment out @optional/@required
+ const char *startBuf = SM->getCharacterData(LocStart);
+ const char *endBuf = SM->getCharacterData(LocEnd);
+ for (const char *p = startBuf; p < endBuf; p++) {
+ if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
+ SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
+ ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
+
+ }
+ else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
+ SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
+ ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
+
+ }
+ }
+}
+
+void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
+ SourceLocation LocStart = PDecl->getLocation();
+ if (LocStart.isInvalid())
+ assert(false && "Invalid SourceLocation");
+ // FIXME: handle forward protocol that are declared across multiple lines.
+ ReplaceText(LocStart, 0, "// ");
+}
+
+void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
+ const FunctionType *&FPRetType) {
+ if (T->isObjCQualifiedIdType())
+ ResultStr += "id";
+ else if (T->isFunctionPointerType() ||
+ T->isBlockPointerType()) {
+ // needs special handling, since pointer-to-functions have special
+ // syntax (where a decaration models use).
+ QualType retType = T;
+ QualType PointeeTy;
+ if (const PointerType* PT = retType->getAs<PointerType>())
+ PointeeTy = PT->getPointeeType();
+ else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
+ PointeeTy = BPT->getPointeeType();
+ if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
+ ResultStr += FPRetType->getResultType().getAsString(
+ Context->PrintingPolicy);
+ ResultStr += "(*";
+ }
+ } else
+ ResultStr += T.getAsString(Context->PrintingPolicy);
+}
+
+void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
+ ObjCMethodDecl *OMD,
+ std::string &ResultStr) {
+ //fprintf(stderr,"In RewriteObjCMethodDecl\n");
+ const FunctionType *FPRetType = 0;
+ ResultStr += "\nstatic ";
+ RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType);
+ ResultStr += " ";
+
+ // Unique method name
+ std::string NameStr;
+
+ if (OMD->isInstanceMethod())
+ NameStr += "_I_";
+ else
+ NameStr += "_C_";
+
+ NameStr += IDecl->getNameAsString();
+ NameStr += "_";
+
+ if (ObjCCategoryImplDecl *CID =
+ dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+ NameStr += CID->getNameAsString();
+ NameStr += "_";
+ }
+ // Append selector names, replacing ':' with '_'
+ {
+ std::string selString = OMD->getSelector().getAsString();
+ int len = selString.size();
+ for (int i = 0; i < len; i++)
+ if (selString[i] == ':')
+ selString[i] = '_';
+ NameStr += selString;
+ }
+ // Remember this name for metadata emission
+ MethodInternalNames[OMD] = NameStr;
+ ResultStr += NameStr;
+
+ // Rewrite arguments
+ ResultStr += "(";
+
+ // invisible arguments
+ if (OMD->isInstanceMethod()) {
+ QualType selfTy = Context->getObjCInterfaceType(IDecl);
+ selfTy = Context->getPointerType(selfTy);
+ if (!LangOpts.Microsoft) {
+ if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
+ ResultStr += "struct ";
+ }
+ // When rewriting for Microsoft, explicitly omit the structure name.
+ ResultStr += IDecl->getNameAsString();
+ ResultStr += " *";
+ }
+ else
+ ResultStr += Context->getObjCClassType().getAsString(
+ Context->PrintingPolicy);
+
+ ResultStr += " self, ";
+ ResultStr += Context->getObjCSelType().getAsString(Context->PrintingPolicy);
+ ResultStr += " _cmd";
+
+ // Method arguments.
+ for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+ E = OMD->param_end(); PI != E; ++PI) {
+ ParmVarDecl *PDecl = *PI;
+ ResultStr += ", ";
+ if (PDecl->getType()->isObjCQualifiedIdType()) {
+ ResultStr += "id ";
+ ResultStr += PDecl->getNameAsString();
+ } else {
+ std::string Name = PDecl->getNameAsString();
+ QualType QT = PDecl->getType();
+ // Make sure we convert "t (^)(...)" to "t (*)(...)".
+ if (convertBlockPointerToFunctionPointer(QT))
+ QT.getAsStringInternal(Name, Context->PrintingPolicy);
+ else
+ PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy);
+ ResultStr += Name;
+ }
+ }
+ if (OMD->isVariadic())
+ ResultStr += ", ...";
+ ResultStr += ") ";
+
+ if (FPRetType) {
+ ResultStr += ")"; // close the precedence "scope" for "*".
+
+ // Now, emit the argument types (if any).
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
+ ResultStr += "(";
+ for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
+ if (i) ResultStr += ", ";
+ std::string ParamStr = FT->getArgType(i).getAsString(
+ Context->PrintingPolicy);
+ ResultStr += ParamStr;
+ }
+ if (FT->isVariadic()) {
+ if (FT->getNumArgs()) ResultStr += ", ";
+ ResultStr += "...";
+ }
+ ResultStr += ")";
+ } else {
+ ResultStr += "()";
+ }
+ }
+}
+void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
+ ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
+ ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
+
+ InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// ");
+
+ for (ObjCCategoryImplDecl::instmeth_iterator
+ I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
+ E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
+ I != E; ++I) {
+ std::string ResultStr;
+ ObjCMethodDecl *OMD = *I;
+ RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
+ SourceLocation LocStart = OMD->getLocStart();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+
+ const char *startBuf = SM->getCharacterData(LocStart);
+ const char *endBuf = SM->getCharacterData(LocEnd);
+ ReplaceText(LocStart, endBuf-startBuf, ResultStr);
+ }
+
+ for (ObjCCategoryImplDecl::classmeth_iterator
+ I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
+ E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
+ I != E; ++I) {
+ std::string ResultStr;
+ ObjCMethodDecl *OMD = *I;
+ RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
+ SourceLocation LocStart = OMD->getLocStart();
+ SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
+
+ const char *startBuf = SM->getCharacterData(LocStart);
+ const char *endBuf = SM->getCharacterData(LocEnd);
+ ReplaceText(LocStart, endBuf-startBuf, ResultStr);
+ }
+ for (ObjCCategoryImplDecl::propimpl_iterator
+ I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
+ E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
+ I != E; ++I) {
+ RewritePropertyImplDecl(*I, IMD, CID);
+ }
+
+ InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
+}
+
+void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
+ std::string ResultStr;
+ if (!ObjCForwardDecls.count(ClassDecl)) {
+ // we haven't seen a forward decl - generate a typedef.
+ ResultStr = "#ifndef _REWRITER_typedef_";
+ ResultStr += ClassDecl->getNameAsString();
+ ResultStr += "\n";
+ ResultStr += "#define _REWRITER_typedef_";
+ ResultStr += ClassDecl->getNameAsString();
+ ResultStr += "\n";
+ ResultStr += "typedef struct objc_object ";
+ ResultStr += ClassDecl->getNameAsString();
+ ResultStr += ";\n#endif\n";
+ // Mark this typedef as having been generated.
+ ObjCForwardDecls.insert(ClassDecl);
+ }
+ SynthesizeObjCInternalStruct(ClassDecl, ResultStr);
+
+ for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
+ E = ClassDecl->prop_end(); I != E; ++I)
+ RewriteProperty(*I);
+ for (ObjCInterfaceDecl::instmeth_iterator
+ I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+ for (ObjCInterfaceDecl::classmeth_iterator
+ I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
+ I != E; ++I)
+ RewriteMethodDeclaration(*I);
+
+ // Lastly, comment out the @end.
+ ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
+ "/* @end */");
+}
+
+Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt,
+ SourceRange SrcRange) {
+ ObjCMethodDecl *OMD = 0;
+ QualType Ty;
+ Selector Sel;
+ Stmt *Receiver = 0;
+ bool Super = false;
+ QualType SuperTy;
+ SourceLocation SuperLocation;
+ SourceLocation SelectorLoc;
+ // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ObjCImplicitSetterGetterRefExpr.
+ // This allows us to reuse all the fun and games in SynthMessageExpr().
+ if (ObjCPropertyRefExpr *PropRefExpr =
+ dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) {
+ SelectorLoc = PropRefExpr->getLocation();
+ if (PropRefExpr->isExplicitProperty()) {
+ ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();
+ OMD = PDecl->getSetterMethodDecl();
+ Ty = PDecl->getType();
+ Sel = PDecl->getSetterName();
+ } else {
+ OMD = PropRefExpr->getImplicitPropertySetter();
+ Sel = OMD->getSelector();
+ Ty = PropRefExpr->getType();
+ }
+ Super = PropRefExpr->isSuperReceiver();
+ if (!Super) {
+ Receiver = PropRefExpr->getBase();
+ } else {
+ SuperTy = PropRefExpr->getSuperReceiverType();
+ SuperLocation = PropRefExpr->getReceiverLocation();
+ }
+ }
+
+ assert(OMD && "RewritePropertyOrImplicitSetter - null OMD");
+ llvm::SmallVector<Expr *, 1> ExprVec;
+ ExprVec.push_back(newStmt);
+
+ ObjCMessageExpr *MsgExpr;
+ if (Super)
+ MsgExpr = ObjCMessageExpr::Create(*Context,
+ Ty.getNonReferenceType(),
+ Expr::getValueKindForType(Ty),
+ /*FIXME?*/SourceLocation(),
+ SuperLocation,
+ /*IsInstanceSuper=*/true,
+ SuperTy,
+ Sel, SelectorLoc, OMD,
+ &ExprVec[0], 1,
+ /*FIXME:*/SourceLocation());
+ else {
+ // FIXME. Refactor this into common code with that in
+ // RewritePropertyOrImplicitGetter
+ assert(Receiver && "RewritePropertyOrImplicitSetter - null Receiver");
+ if (Expr *Exp = dyn_cast<Expr>(Receiver))
+ if (PropGetters[Exp])
+ // This allows us to handle chain/nested property/implicit getters.
+ Receiver = PropGetters[Exp];
+
+ MsgExpr = ObjCMessageExpr::Create(*Context,
+ Ty.getNonReferenceType(),
+ Expr::getValueKindForType(Ty),
+ /*FIXME: */SourceLocation(),
+ cast<Expr>(Receiver),
+ Sel, SelectorLoc, OMD,
+ &ExprVec[0], 1,
+ /*FIXME:*/SourceLocation());
+ }
+ Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+
+ // Now do the actual rewrite.
+ ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
+ //delete BinOp;
+ // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+ // to things that stay around.
+ Context->Deallocate(MsgExpr);
+ return ReplacingStmt;
+}
+
+Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
+ // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter.
+ // This allows us to reuse all the fun and games in SynthMessageExpr().
+ Stmt *Receiver = 0;
+ ObjCMethodDecl *OMD = 0;
+ QualType Ty;
+ Selector Sel;
+ bool Super = false;
+ QualType SuperTy;
+ SourceLocation SuperLocation;
+ SourceLocation SelectorLoc;
+ if (ObjCPropertyRefExpr *PropRefExpr =
+ dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) {
+ SelectorLoc = PropRefExpr->getLocation();
+ if (PropRefExpr->isExplicitProperty()) {
+ ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty();
+ OMD = PDecl->getGetterMethodDecl();
+ Ty = PDecl->getType();
+ Sel = PDecl->getGetterName();
+ } else {
+ OMD = PropRefExpr->getImplicitPropertyGetter();
+ Sel = OMD->getSelector();
+ Ty = PropRefExpr->getType();
+ }
+ Super = PropRefExpr->isSuperReceiver();
+ if (!Super)
+ Receiver = PropRefExpr->getBase();
+ else {
+ SuperTy = PropRefExpr->getSuperReceiverType();
+ SuperLocation = PropRefExpr->getReceiverLocation();
+ }
+ }
+
+ assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null");
+
+ ObjCMessageExpr *MsgExpr;
+ if (Super)
+ MsgExpr = ObjCMessageExpr::Create(*Context,
+ Ty.getNonReferenceType(),
+ Expr::getValueKindForType(Ty),
+ /*FIXME?*/SourceLocation(),
+ SuperLocation,
+ /*IsInstanceSuper=*/true,
+ SuperTy,
+ Sel, SelectorLoc, OMD,
+ 0, 0,
+ /*FIXME:*/SourceLocation());
+ else {
+ assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null");
+ if (Expr *Exp = dyn_cast<Expr>(Receiver))
+ if (PropGetters[Exp])
+ // This allows us to handle chain/nested property/implicit getters.
+ Receiver = PropGetters[Exp];
+ MsgExpr = ObjCMessageExpr::Create(*Context,
+ Ty.getNonReferenceType(),
+ Expr::getValueKindForType(Ty),
+ /*FIXME:*/SourceLocation(),
+ cast<Expr>(Receiver),
+ Sel, SelectorLoc, OMD,
+ 0, 0,
+ /*FIXME:*/SourceLocation());
+ }
+
+ Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+
+ if (!PropParentMap)
+ PropParentMap = new ParentMap(CurrentBody);
+ bool NestedPropertyRef = false;
+ Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr);
+ ImplicitCastExpr*ICE=0;
+ if (Parent)
+ if ((ICE = dyn_cast<ImplicitCastExpr>(Parent))) {
+ assert((ICE->getCastKind() == CK_GetObjCProperty)
+ && "RewritePropertyOrImplicitGetter");
+ Parent = PropParentMap->getParent(Parent);
+ NestedPropertyRef = (Parent && isa<ObjCPropertyRefExpr>(Parent));
+ }
+ if (NestedPropertyRef) {
+ // We stash away the ReplacingStmt since actually doing the
+ // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
+ PropGetters[ICE] = ReplacingStmt;
+ // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+ // to things that stay around.
+ Context->Deallocate(MsgExpr);
+ return PropOrGetterRefExpr; // return the original...
+ } else {
+ ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt);
+ // delete PropRefExpr; elsewhere...
+ // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
+ // to things that stay around.
+ Context->Deallocate(MsgExpr);
+ return ReplacingStmt;
+ }
+}
+
+Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
+ SourceLocation OrigStart,
+ bool &replaced) {
+ ObjCIvarDecl *D = IV->getDecl();
+ const Expr *BaseExpr = IV->getBase();
+ if (CurMethodDef) {
+ if (BaseExpr->getType()->isObjCObjectPointerType()) {
+ const ObjCInterfaceType *iFaceDecl =
+ dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+ assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
+ // lookup which class implements the instance variable.
+ ObjCInterfaceDecl *clsDeclared = 0;
+ iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+ clsDeclared);
+ assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+
+ // Synthesize an explicit cast to gain access to the ivar.
+ std::string RecName = clsDeclared->getIdentifier()->getName();
+ RecName += "_IMPL";
+ IdentifierInfo *II = &Context->Idents.get(RecName);
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(), II);
+ assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+ QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+ CK_BitCast,
+ IV->getBase());
+ // Don't forget the parens to enforce the proper binding.
+ ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
+ IV->getBase()->getLocEnd(),
+ castExpr);
+ replaced = true;
+ if (IV->isFreeIvar() &&
+ CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
+ MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
+ IV->getLocation(),
+ D->getType(),
+ VK_LValue, OK_Ordinary);
+ // delete IV; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return ME;
+ }
+ // Get the new text
+ // Cannot delete IV->getBase(), since PE points to it.
+ // Replace the old base with the cast. This is important when doing
+ // embedded rewrites. For example, [newInv->_container addObject:0].
+ IV->setBase(PE);
+ return IV;
+ }
+ } else { // we are outside a method.
+ assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
+
+ // Explicit ivar refs need to have a cast inserted.
+ // FIXME: consider sharing some of this code with the code above.
+ if (BaseExpr->getType()->isObjCObjectPointerType()) {
+ const ObjCInterfaceType *iFaceDecl =
+ dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
+ // lookup which class implements the instance variable.
+ ObjCInterfaceDecl *clsDeclared = 0;
+ iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
+ clsDeclared);
+ assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
+
+ // Synthesize an explicit cast to gain access to the ivar.
+ std::string RecName = clsDeclared->getIdentifier()->getName();
+ RecName += "_IMPL";
+ IdentifierInfo *II = &Context->Idents.get(RecName);
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(), II);
+ assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
+ QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
+ CK_BitCast,
+ IV->getBase());
+ // Don't forget the parens to enforce the proper binding.
+ ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
+ IV->getBase()->getLocEnd(), castExpr);
+ replaced = true;
+ // Cannot delete IV->getBase(), since PE points to it.
+ // Replace the old base with the cast. This is important when doing
+ // embedded rewrites. For example, [newInv->_container addObject:0].
+ IV->setBase(PE);
+ return IV;
+ }
+ }
+ return IV;
+}
+
+Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
+ if (*CI) {
+ Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
+ if (newStmt)
+ *CI = newStmt;
+ }
+ }
+ if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
+ SourceRange OrigStmtRange = S->getSourceRange();
+ Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(),
+ replaced);
+ return newStmt;
+ }
+ if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {
+ Stmt *newStmt = SynthMessageExpr(MsgRefExpr);
+ return newStmt;
+ }
+ return S;
+}
+
+/// SynthCountByEnumWithState - To print:
+/// ((unsigned int (*)
+/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+/// (void *)objc_msgSend)((id)l_collection,
+/// sel_registerName(
+/// "countByEnumeratingWithState:objects:count:"),
+/// &enumState,
+/// (id *)items, (unsigned int)16)
+///
+void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
+ buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
+ "id *, unsigned int))(void *)objc_msgSend)";
+ buf += "\n\t\t";
+ buf += "((id)l_collection,\n\t\t";
+ buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
+ buf += "\n\t\t";
+ buf += "&enumState, "
+ "(id *)items, (unsigned int)16)";
+}
+
+/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
+/// statement to exit to its outer synthesized loop.
+///
+Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
+ if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ return S;
+ // replace break with goto __break_label
+ std::string buf;
+
+ SourceLocation startLoc = S->getLocStart();
+ buf = "goto __break_label_";
+ buf += utostr(ObjCBcLabelNo.back());
+ ReplaceText(startLoc, strlen("break"), buf);
+
+ return 0;
+}
+
+/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
+/// statement to continue with its inner synthesized loop.
+///
+Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
+ if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ return S;
+ // replace continue with goto __continue_label
+ std::string buf;
+
+ SourceLocation startLoc = S->getLocStart();
+ buf = "goto __continue_label_";
+ buf += utostr(ObjCBcLabelNo.back());
+ ReplaceText(startLoc, strlen("continue"), buf);
+
+ return 0;
+}
+
+/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
+/// It rewrites:
+/// for ( type elem in collection) { stmts; }
+
+/// Into:
+/// {
+/// type elem;
+/// struct __objcFastEnumerationState enumState = { 0 };
+/// id items[16];
+/// id l_collection = (id)collection;
+/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
+/// objects:items count:16];
+/// if (limit) {
+/// unsigned long startMutations = *enumState.mutationsPtr;
+/// do {
+/// unsigned long counter = 0;
+/// do {
+/// if (startMutations != *enumState.mutationsPtr)
+/// objc_enumerationMutation(l_collection);
+/// elem = (type)enumState.itemsPtr[counter++];
+/// stmts;
+/// __continue_label: ;
+/// } while (counter < limit);
+/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
+/// objects:items count:16]);
+/// elem = nil;
+/// __break_label: ;
+/// }
+/// else
+/// elem = nil;
+/// }
+///
+Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
+ SourceLocation OrigEnd) {
+ assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
+ assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
+ "ObjCForCollectionStmt Statement stack mismatch");
+ assert(!ObjCBcLabelNo.empty() &&
+ "ObjCForCollectionStmt - Label No stack empty");
+
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+ llvm::StringRef elementName;
+ std::string elementTypeAsString;
+ std::string buf;
+ buf = "\n{\n\t";
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
+ // type elem;
+ NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
+ QualType ElementType = cast<ValueDecl>(D)->getType();
+ if (ElementType->isObjCQualifiedIdType() ||
+ ElementType->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = ElementType.getAsString(Context->PrintingPolicy);
+ buf += elementTypeAsString;
+ buf += " ";
+ elementName = D->getName();
+ buf += elementName;
+ buf += ";\n\t";
+ }
+ else {
+ DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
+ elementName = DR->getDecl()->getName();
+ ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+ if (VD->getType()->isObjCQualifiedIdType() ||
+ VD->getType()->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = VD->getType().getAsString(Context->PrintingPolicy);
+ }
+
+ // struct __objcFastEnumerationState enumState = { 0 };
+ buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
+ // id items[16];
+ buf += "id items[16];\n\t";
+ // id l_collection = (id)
+ buf += "id l_collection = (id)";
+ // Find start location of 'collection' the hard way!
+ const char *startCollectionBuf = startBuf;
+ startCollectionBuf += 3; // skip 'for'
+ startCollectionBuf = strchr(startCollectionBuf, '(');
+ startCollectionBuf++; // skip '('
+ // find 'in' and skip it.
+ while (*startCollectionBuf != ' ' ||
+ *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
+ (*(startCollectionBuf+3) != ' ' &&
+ *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
+ startCollectionBuf++;
+ startCollectionBuf += 3;
+
+ // Replace: "for (type element in" with string constructed thus far.
+ ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
+ // Replace ')' in for '(' type elem in collection ')' with ';'
+ SourceLocation rightParenLoc = S->getRParenLoc();
+ const char *rparenBuf = SM->getCharacterData(rightParenLoc);
+ SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf);
+ buf = ";\n\t";
+
+ // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
+ // objects:items count:16];
+ // which is synthesized into:
+ // unsigned int limit =
+ // ((unsigned int (*)
+ // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+ // (void *)objc_msgSend)((id)l_collection,
+ // sel_registerName(
+ // "countByEnumeratingWithState:objects:count:"),
+ // (struct __objcFastEnumerationState *)&state,
+ // (id *)items, (unsigned int)16);
+ buf += "unsigned long limit =\n\t\t";
+ SynthCountByEnumWithState(buf);
+ buf += ";\n\t";
+ /// if (limit) {
+ /// unsigned long startMutations = *enumState.mutationsPtr;
+ /// do {
+ /// unsigned long counter = 0;
+ /// do {
+ /// if (startMutations != *enumState.mutationsPtr)
+ /// objc_enumerationMutation(l_collection);
+ /// elem = (type)enumState.itemsPtr[counter++];
+ buf += "if (limit) {\n\t";
+ buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
+ buf += "do {\n\t\t";
+ buf += "unsigned long counter = 0;\n\t\t";
+ buf += "do {\n\t\t\t";
+ buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
+ buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
+ buf += elementName;
+ buf += " = (";
+ buf += elementTypeAsString;
+ buf += ")enumState.itemsPtr[counter++];";
+ // Replace ')' in for '(' type elem in collection ')' with all of these.
+ ReplaceText(lparenLoc, 1, buf);
+
+ /// __continue_label: ;
+ /// } while (counter < limit);
+ /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
+ /// objects:items count:16]);
+ /// elem = nil;
+ /// __break_label: ;
+ /// }
+ /// else
+ /// elem = nil;
+ /// }
+ ///
+ buf = ";\n\t";
+ buf += "__continue_label_";
+ buf += utostr(ObjCBcLabelNo.back());
+ buf += ": ;";
+ buf += "\n\t\t";
+ buf += "} while (counter < limit);\n\t";
+ buf += "} while (limit = ";
+ SynthCountByEnumWithState(buf);
+ buf += ");\n\t";
+ buf += elementName;
+ buf += " = ((";
+ buf += elementTypeAsString;
+ buf += ")0);\n\t";
+ buf += "__break_label_";
+ buf += utostr(ObjCBcLabelNo.back());
+ buf += ": ;\n\t";
+ buf += "}\n\t";
+ buf += "else\n\t\t";
+ buf += elementName;
+ buf += " = ((";
+ buf += elementTypeAsString;
+ buf += ")0);\n\t";
+ buf += "}\n";
+
+ // Insert all these *after* the statement body.
+ // FIXME: If this should support Obj-C++, support CXXTryStmt
+ if (isa<CompoundStmt>(S->getBody())) {
+ SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
+ InsertText(endBodyLoc, buf);
+ } else {
+ /* Need to treat single statements specially. For example:
+ *
+ * for (A *a in b) if (stuff()) break;
+ * for (A *a in b) xxxyy;
+ *
+ * The following code simply scans ahead to the semi to find the actual end.
+ */
+ const char *stmtBuf = SM->getCharacterData(OrigEnd);
+ const char *semiBuf = strchr(stmtBuf, ';');
+ assert(semiBuf && "Can't find ';'");
+ SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1);
+ InsertText(endBodyLoc, buf);
+ }
+ Stmts.pop_back();
+ ObjCBcLabelNo.pop_back();
+ return 0;
+}
+
+/// RewriteObjCSynchronizedStmt -
+/// This routine rewrites @synchronized(expr) stmt;
+/// into:
+/// objc_sync_enter(expr);
+/// @try stmt @finally { objc_sync_exit(expr); }
+///
+Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+ // Get the start location and compute the semi location.
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '@') && "bogus @synchronized location");
+
+ std::string buf;
+ buf = "objc_sync_enter((id)";
+ const char *lparenBuf = startBuf;
+ while (*lparenBuf != '(') lparenBuf++;
+ ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
+ // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
+ // the sync expression is typically a message expression that's already
+ // been rewritten! (which implies the SourceLocation's are invalid).
+ SourceLocation endLoc = S->getSynchBody()->getLocStart();
+ const char *endBuf = SM->getCharacterData(endLoc);
+ while (*endBuf != ')') endBuf--;
+ SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf);
+ buf = ");\n";
+ // declare a new scope with two variables, _stack and _rethrow.
+ buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
+ buf += "int buf[18/*32-bit i386*/];\n";
+ buf += "char *pointers[4];} _stack;\n";
+ buf += "id volatile _rethrow = 0;\n";
+ buf += "objc_exception_try_enter(&_stack);\n";
+ buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
+ ReplaceText(rparenLoc, 1, buf);
+ startLoc = S->getSynchBody()->getLocEnd();
+ startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '}') && "bogus @synchronized block");
+ SourceLocation lastCurlyLoc = startLoc;
+ buf = "}\nelse {\n";
+ buf += " _rethrow = objc_exception_extract(&_stack);\n";
+ buf += "}\n";
+ buf += "{ /* implicit finally clause */\n";
+ buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
+
+ std::string syncBuf;
+ syncBuf += " objc_sync_exit(";
+ Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast,
+ S->getSynchExpr());
+ std::string syncExprBufS;
+ llvm::raw_string_ostream syncExprBuf(syncExprBufS);
+ syncExpr->printPretty(syncExprBuf, *Context, 0,
+ PrintingPolicy(LangOpts));
+ syncBuf += syncExprBuf.str();
+ syncBuf += ");";
+
+ buf += syncBuf;
+ buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
+ buf += "}\n";
+ buf += "}";
+
+ ReplaceText(lastCurlyLoc, 1, buf);
+
+ bool hasReturns = false;
+ HasReturnStmts(S->getSynchBody(), hasReturns);
+ if (hasReturns)
+ RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
+
+ return 0;
+}
+
+void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
+{
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI)
+ WarnAboutReturnGotoStmts(*CI);
+
+ if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
+ Diags.Report(Context->getFullLoc(S->getLocStart()),
+ TryFinallyContainsReturnDiag);
+ }
+ return;
+}
+
+void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
+{
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI)
+ HasReturnStmts(*CI, hasReturns);
+
+ if (isa<ReturnStmt>(S))
+ hasReturns = true;
+ return;
+}
+
+void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI) {
+ RewriteTryReturnStmts(*CI);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack); return";
+
+ ReplaceText(startLoc, 6, buf);
+ InsertText(onePastSemiLoc, "}");
+ }
+ return;
+}
+
+void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI) {
+ RewriteSyncReturnStmts(*CI, syncExitBuf);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack);";
+ buf += syncExitBuf;
+ buf += " return";
+
+ ReplaceText(startLoc, 6, buf);
+ InsertText(onePastSemiLoc, "}");
+ }
+ return;
+}
+
+Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
+ // Get the start location and compute the semi location.
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '@') && "bogus @try location");
+
+ std::string buf;
+ // declare a new scope with two variables, _stack and _rethrow.
+ buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
+ buf += "int buf[18/*32-bit i386*/];\n";
+ buf += "char *pointers[4];} _stack;\n";
+ buf += "id volatile _rethrow = 0;\n";
+ buf += "objc_exception_try_enter(&_stack);\n";
+ buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
+
+ ReplaceText(startLoc, 4, buf);
+
+ startLoc = S->getTryBody()->getLocEnd();
+ startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '}') && "bogus @try block");
+
+ SourceLocation lastCurlyLoc = startLoc;
+ if (S->getNumCatchStmts()) {
+ startLoc = startLoc.getFileLocWithOffset(1);
+ buf = " /* @catch begin */ else {\n";
+ buf += " id _caught = objc_exception_extract(&_stack);\n";
+ buf += " objc_exception_try_enter (&_stack);\n";
+ buf += " if (_setjmp(_stack.buf))\n";
+ buf += " _rethrow = objc_exception_extract(&_stack);\n";
+ buf += " else { /* @catch continue */";
+
+ InsertText(startLoc, buf);
+ } else { /* no catch list */
+ buf = "}\nelse {\n";
+ buf += " _rethrow = objc_exception_extract(&_stack);\n";
+ buf += "}";
+ ReplaceText(lastCurlyLoc, 1, buf);
+ }
+ Stmt *lastCatchBody = 0;
+ for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
+ ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
+ VarDecl *catchDecl = Catch->getCatchParamDecl();
+
+ if (I == 0)
+ buf = "if ("; // we are generating code for the first catch clause
+ else
+ buf = "else if (";
+ startLoc = Catch->getLocStart();
+ startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '@') && "bogus @catch location");
+
+ const char *lParenLoc = strchr(startBuf, '(');
+
+ if (Catch->hasEllipsis()) {
+ // Now rewrite the body...
+ lastCatchBody = Catch->getCatchBody();
+ SourceLocation bodyLoc = lastCatchBody->getLocStart();
+ const char *bodyBuf = SM->getCharacterData(bodyLoc);
+ assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&
+ "bogus @catch paren location");
+ assert((*bodyBuf == '{') && "bogus @catch body location");
+
+ buf += "1) { id _tmp = _caught;";
+ Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
+ } else if (catchDecl) {
+ QualType t = catchDecl->getType();
+ if (t == Context->getObjCIdType()) {
+ buf += "1) { ";
+ ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
+ } else if (const ObjCObjectPointerType *Ptr =
+ t->getAs<ObjCObjectPointerType>()) {
+ // Should be a pointer to a class.
+ ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
+ if (IDecl) {
+ buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
+ buf += IDecl->getNameAsString();
+ buf += "\"), (struct objc_object *)_caught)) { ";
+ ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
+ }
+ }
+ // Now rewrite the body...
+ lastCatchBody = Catch->getCatchBody();
+ SourceLocation rParenLoc = Catch->getRParenLoc();
+ SourceLocation bodyLoc = lastCatchBody->getLocStart();
+ const char *bodyBuf = SM->getCharacterData(bodyLoc);
+ const char *rParenBuf = SM->getCharacterData(rParenLoc);
+ assert((*rParenBuf == ')') && "bogus @catch paren location");
+ assert((*bodyBuf == '{') && "bogus @catch body location");
+
+ // Here we replace ") {" with "= _caught;" (which initializes and
+ // declares the @catch parameter).
+ ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");
+ } else {
+ assert(false && "@catch rewrite bug");
+ }
+ }
+ // Complete the catch list...
+ if (lastCatchBody) {
+ SourceLocation bodyLoc = lastCatchBody->getLocEnd();
+ assert(*SM->getCharacterData(bodyLoc) == '}' &&
+ "bogus @catch body location");
+
+ // Insert the last (implicit) else clause *before* the right curly brace.
+ bodyLoc = bodyLoc.getFileLocWithOffset(-1);
+ buf = "} /* last catch end */\n";
+ buf += "else {\n";
+ buf += " _rethrow = _caught;\n";
+ buf += " objc_exception_try_exit(&_stack);\n";
+ buf += "} } /* @catch end */\n";
+ if (!S->getFinallyStmt())
+ buf += "}\n";
+ InsertText(bodyLoc, buf);
+
+ // Set lastCurlyLoc
+ lastCurlyLoc = lastCatchBody->getLocEnd();
+ }
+ if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
+ startLoc = finalStmt->getLocStart();
+ startBuf = SM->getCharacterData(startLoc);
+ assert((*startBuf == '@') && "bogus @finally start");
+
+ ReplaceText(startLoc, 8, "/* @finally */");
+
+ Stmt *body = finalStmt->getFinallyBody();
+ SourceLocation startLoc = body->getLocStart();
+ SourceLocation endLoc = body->getLocEnd();
+ assert(*SM->getCharacterData(startLoc) == '{' &&
+ "bogus @finally body location");
+ assert(*SM->getCharacterData(endLoc) == '}' &&
+ "bogus @finally body location");
+
+ startLoc = startLoc.getFileLocWithOffset(1);
+ InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");
+ endLoc = endLoc.getFileLocWithOffset(-1);
+ InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");
+
+ // Set lastCurlyLoc
+ lastCurlyLoc = body->getLocEnd();
+
+ // Now check for any return/continue/go statements within the @try.
+ WarnAboutReturnGotoStmts(S->getTryBody());
+ } else { /* no finally clause - make sure we synthesize an implicit one */
+ buf = "{ /* implicit finally clause */\n";
+ buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
+ buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
+ buf += "}";
+ ReplaceText(lastCurlyLoc, 1, buf);
+
+ // Now check for any return/continue/go statements within the @try.
+ // The implicit finally clause won't called if the @try contains any
+ // jump statements.
+ bool hasReturns = false;
+ HasReturnStmts(S->getTryBody(), hasReturns);
+ if (hasReturns)
+ RewriteTryReturnStmts(S->getTryBody());
+ }
+ // Now emit the final closing curly brace...
+ lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
+ InsertText(lastCurlyLoc, " } /* @try scope end */\n");
+ return 0;
+}
+
+// This can't be done with ReplaceStmt(S, ThrowExpr), since
+// the throw expression is typically a message expression that's already
+// been rewritten! (which implies the SourceLocation's are invalid).
+Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
+ // Get the start location and compute the semi location.
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ assert((*startBuf == '@') && "bogus @throw location");
+
+ std::string buf;
+ /* void objc_exception_throw(id) __attribute__((noreturn)); */
+ if (S->getThrowExpr())
+ buf = "objc_exception_throw(";
+ else // add an implicit argument
+ buf = "objc_exception_throw(_caught";
+
+ // handle "@ throw" correctly.
+ const char *wBuf = strchr(startBuf, 'w');
+ assert((*wBuf == 'w') && "@throw: can't find 'w'");
+ ReplaceText(startLoc, wBuf-startBuf+1, buf);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "@throw: can't find ';'");
+ SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
+ ReplaceText(semiLoc, 1, ");");
+ return 0;
+}
+
+Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
+ // Create a new string expression.
+ QualType StrType = Context->getPointerType(Context->CharTy);
+ std::string StrEncoding;
+ Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
+ Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(),
+ StrEncoding.length(), false,StrType,
+ SourceLocation());
+ ReplaceStmt(Exp, Replacement);
+
+ // Replace this subexpr in the parent.
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return Replacement;
+}
+
+Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
+ if (!SelGetUidFunctionDecl)
+ SynthSelGetUidFunctionDecl();
+ assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
+ // Create a call to sel_registerName("selName").
+ llvm::SmallVector<Expr*, 8> SelExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ SelExprs.push_back(StringLiteral::Create(*Context,
+ Exp->getSelector().getAsString().c_str(),
+ Exp->getSelector().getAsString().size(),
+ false, argType, SourceLocation()));
+ CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
+ &SelExprs[0], SelExprs.size());
+ ReplaceStmt(Exp, SelExp);
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return SelExp;
+}
+
+CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
+ FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ // Get the type, we will need to reference it in a couple spots.
+ QualType msgSendType = FD->getType();
+
+ // Create a reference to the objc_msgSend() declaration.
+ DeclRefExpr *DRE =
+ new (Context) DeclRefExpr(FD, msgSendType, VK_LValue, SourceLocation());
+
+ // Now, we cast the reference to a pointer to the objc_msgSend type.
+ QualType pToFunc = Context->getPointerType(msgSendType);
+ ImplicitCastExpr *ICE =
+ ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
+ DRE, 0, VK_RValue);
+
+ const FunctionType *FT = msgSendType->getAs<FunctionType>();
+
+ CallExpr *Exp =
+ new (Context) CallExpr(*Context, ICE, args, nargs,
+ FT->getCallResultType(*Context),
+ VK_RValue, EndLoc);
+ return Exp;
+}
+
+static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
+ const char *&startRef, const char *&endRef) {
+ while (startBuf < endBuf) {
+ if (*startBuf == '<')
+ startRef = startBuf; // mark the start.
+ if (*startBuf == '>') {
+ if (startRef && *startRef == '<') {
+ endRef = startBuf; // mark the end.
+ return true;
+ }
+ return false;
+ }
+ startBuf++;
+ }
+ return false;
+}
+
+static void scanToNextArgument(const char *&argRef) {
+ int angle = 0;
+ while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
+ if (*argRef == '<')
+ angle++;
+ else if (*argRef == '>')
+ angle--;
+ argRef++;
+ }
+ assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
+}
+
+bool RewriteObjC::needToScanForQualifiers(QualType T) {
+ if (T->isObjCQualifiedIdType())
+ return true;
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ if (PT->getPointeeType()->isObjCQualifiedIdType())
+ return true;
+ }
+ if (T->isObjCObjectPointerType()) {
+ T = T->getPointeeType();
+ return T->isObjCQualifiedInterfaceType();
+ }
+ if (T->isArrayType()) {
+ QualType ElemTy = Context->getBaseElementType(T);
+ return needToScanForQualifiers(ElemTy);
+ }
+ return false;
+}
+
+void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
+ QualType Type = E->getType();
+ if (needToScanForQualifiers(Type)) {
+ SourceLocation Loc, EndLoc;
+
+ if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
+ Loc = ECE->getLParenLoc();
+ EndLoc = ECE->getRParenLoc();
+ } else {
+ Loc = E->getLocStart();
+ EndLoc = E->getLocEnd();
+ }
+ // This will defend against trying to rewrite synthesized expressions.
+ if (Loc.isInvalid() || EndLoc.isInvalid())
+ return;
+
+ const char *startBuf = SM->getCharacterData(Loc);
+ const char *endBuf = SM->getCharacterData(EndLoc);
+ const char *startRef = 0, *endRef = 0;
+ if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+ // Get the locations of the startRef, endRef.
+ SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
+ SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
+ // Comment out the protocol references.
+ InsertText(LessLoc, "/*");
+ InsertText(GreaterLoc, "*/");
+ }
+ }
+}
+
+void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
+ SourceLocation Loc;
+ QualType Type;
+ const FunctionProtoType *proto = 0;
+ if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
+ Loc = VD->getLocation();
+ Type = VD->getType();
+ }
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
+ Loc = FD->getLocation();
+ // Check for ObjC 'id' and class types that have been adorned with protocol
+ // information (id<p>, C<p>*). The protocol references need to be rewritten!
+ const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
+ assert(funcType && "missing function type");
+ proto = dyn_cast<FunctionProtoType>(funcType);
+ if (!proto)
+ return;
+ Type = proto->getResultType();
+ }
+ else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
+ Loc = FD->getLocation();
+ Type = FD->getType();
+ }
+ else
+ return;
+
+ if (needToScanForQualifiers(Type)) {
+ // Since types are unique, we need to scan the buffer.
+
+ const char *endBuf = SM->getCharacterData(Loc);
+ const char *startBuf = endBuf;
+ while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
+ startBuf--; // scan backward (from the decl location) for return type.
+ const char *startRef = 0, *endRef = 0;
+ if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+ // Get the locations of the startRef, endRef.
+ SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
+ SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
+ // Comment out the protocol references.
+ InsertText(LessLoc, "/*");
+ InsertText(GreaterLoc, "*/");
+ }
+ }
+ if (!proto)
+ return; // most likely, was a variable
+ // Now check arguments.
+ const char *startBuf = SM->getCharacterData(Loc);
+ const char *startFuncBuf = startBuf;
+ for (unsigned i = 0; i < proto->getNumArgs(); i++) {
+ if (needToScanForQualifiers(proto->getArgType(i))) {
+ // Since types are unique, we need to scan the buffer.
+
+ const char *endBuf = startBuf;
+ // scan forward (from the decl location) for argument types.
+ scanToNextArgument(endBuf);
+ const char *startRef = 0, *endRef = 0;
+ if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
+ // Get the locations of the startRef, endRef.
+ SourceLocation LessLoc =
+ Loc.getFileLocWithOffset(startRef-startFuncBuf);
+ SourceLocation GreaterLoc =
+ Loc.getFileLocWithOffset(endRef-startFuncBuf+1);
+ // Comment out the protocol references.
+ InsertText(LessLoc, "/*");
+ InsertText(GreaterLoc, "*/");
+ }
+ startBuf = ++endBuf;
+ }
+ else {
+ // If the function name is derived from a macro expansion, then the
+ // argument buffer will not follow the name. Need to speak with Chris.
+ while (*startBuf && *startBuf != ')' && *startBuf != ',')
+ startBuf++; // scan forward (from the decl location) for argument types.
+ startBuf++;
+ }
+ }
+}
+
+void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {
+ QualType QT = ND->getType();
+ const Type* TypePtr = QT->getAs<Type>();
+ if (!isa<TypeOfExprType>(TypePtr))
+ return;
+ while (isa<TypeOfExprType>(TypePtr)) {
+ const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
+ QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
+ TypePtr = QT->getAs<Type>();
+ }
+ // FIXME. This will not work for multiple declarators; as in:
+ // __typeof__(a) b,c,d;
+ std::string TypeAsString(QT.getAsString(Context->PrintingPolicy));
+ SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
+ const char *startBuf = SM->getCharacterData(DeclLoc);
+ if (ND->getInit()) {
+ std::string Name(ND->getNameAsString());
+ TypeAsString += " " + Name + " = ";
+ Expr *E = ND->getInit();
+ SourceLocation startLoc;
+ if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
+ startLoc = ECE->getLParenLoc();
+ else
+ startLoc = E->getLocStart();
+ startLoc = SM->getInstantiationLoc(startLoc);
+ const char *endBuf = SM->getCharacterData(startLoc);
+ ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
+ }
+ else {
+ SourceLocation X = ND->getLocEnd();
+ X = SM->getInstantiationLoc(X);
+ const char *endBuf = SM->getCharacterData(X);
+ ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
+ }
+}
+
+// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
+void RewriteObjC::SynthSelGetUidFunctionDecl() {
+ IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+ QualType getFuncType =
+ getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size());
+ SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ SelGetUidIdent, getFuncType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
+ // declared in <objc/objc.h>
+ if (FD->getIdentifier() &&
+ FD->getName() == "sel_registerName") {
+ SelGetUidFunctionDecl = FD;
+ return;
+ }
+ RewriteObjCQualifiedInterfaceTypes(FD);
+}
+
+void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
+ std::string TypeString(Type.getAsString(Context->PrintingPolicy));
+ const char *argPtr = TypeString.c_str();
+ if (!strchr(argPtr, '^')) {
+ Str += TypeString;
+ return;
+ }
+ while (*argPtr) {
+ Str += (*argPtr == '^' ? '*' : *argPtr);
+ argPtr++;
+ }
+}
+
+// FIXME. Consolidate this routine with RewriteBlockPointerType.
+void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
+ ValueDecl *VD) {
+ QualType Type = VD->getType();
+ std::string TypeString(Type.getAsString(Context->PrintingPolicy));
+ const char *argPtr = TypeString.c_str();
+ int paren = 0;
+ while (*argPtr) {
+ switch (*argPtr) {
+ case '(':
+ Str += *argPtr;
+ paren++;
+ break;
+ case ')':
+ Str += *argPtr;
+ paren--;
+ break;
+ case '^':
+ Str += '*';
+ if (paren == 1)
+ Str += VD->getNameAsString();
+ break;
+ default:
+ Str += *argPtr;
+ break;
+ }
+ argPtr++;
+ }
+}
+
+
+void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
+ SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+ const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
+ const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
+ if (!proto)
+ return;
+ QualType Type = proto->getResultType();
+ std::string FdStr = Type.getAsString(Context->PrintingPolicy);
+ FdStr += " ";
+ FdStr += FD->getName();
+ FdStr += "(";
+ unsigned numArgs = proto->getNumArgs();
+ for (unsigned i = 0; i < numArgs; i++) {
+ QualType ArgType = proto->getArgType(i);
+ RewriteBlockPointerType(FdStr, ArgType);
+ if (i+1 < numArgs)
+ FdStr += ", ";
+ }
+ FdStr += ");\n";
+ InsertText(FunLocStart, FdStr);
+ CurFunctionDeclToDeclareForBlock = 0;
+}
+
+// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
+void RewriteObjC::SynthSuperContructorFunctionDecl() {
+ if (SuperContructorFunctionDecl)
+ return;
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ QualType argT = Context->getObjCIdType();
+ assert(!argT.isNull() && "Can't find 'id' type");
+ ArgTys.push_back(argT);
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size());
+ SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendFunctionDecl() {
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ QualType argT = Context->getObjCIdType();
+ assert(!argT.isNull() && "Can't find 'id' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjCSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
+void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("objc_super"));
+ QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+ assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjCSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendStretFunctionDecl() {
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ QualType argT = Context->getObjCIdType();
+ assert(!argT.isNull() && "Can't find 'id' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjCSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthMsgSendSuperStretFunctionDecl -
+// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
+void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
+ IdentifierInfo *msgSendIdent =
+ &Context->Idents.get("objc_msgSendSuper_stret");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("objc_super"));
+ QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+ assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjCSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
+void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ QualType argT = Context->getObjCIdType();
+ assert(!argT.isNull() && "Can't find 'id' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjCSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ msgSendIdent, msgSendType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
+void RewriteObjC::SynthGetClassFunctionDecl() {
+ IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+ QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size());
+ GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ getClassIdent, getClassType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
+void RewriteObjC::SynthGetSuperClassFunctionDecl() {
+ IdentifierInfo *getSuperClassIdent =
+ &Context->Idents.get("class_getSuperclass");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.push_back(Context->getObjCClassType());
+ QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
+ &ArgTys[0], ArgTys.size());
+ GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ getSuperClassIdent,
+ getClassType, 0,
+ SC_Extern,
+ SC_None,
+ false);
+}
+
+// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
+void RewriteObjC::SynthGetMetaClassFunctionDecl() {
+ IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
+ QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
+ &ArgTys[0], ArgTys.size());
+ GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ getClassIdent, getClassType, 0,
+ SC_Extern,
+ SC_None, false);
+}
+
+Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
+ QualType strType = getConstantStringStructType();
+
+ std::string S = "__NSConstantStringImpl_";
+
+ std::string tmpName = InFileName;
+ unsigned i;
+ for (i=0; i < tmpName.length(); i++) {
+ char c = tmpName.at(i);
+ // replace any non alphanumeric characters with '_'.
+ if (!isalpha(c) && (c < '0' || c > '9'))
+ tmpName[i] = '_';
+ }
+ S += tmpName;
+ S += "_";
+ S += utostr(NumObjCStringLiterals++);
+
+ Preamble += "static __NSConstantStringImpl " + S;
+ Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
+ Preamble += "0x000007c8,"; // utf8_str
+ // The pretty printer for StringLiteral handles escape characters properly.
+ std::string prettyBufS;
+ llvm::raw_string_ostream prettyBuf(prettyBufS);
+ Exp->getString()->printPretty(prettyBuf, *Context, 0,
+ PrintingPolicy(LangOpts));
+ Preamble += prettyBuf.str();
+ Preamble += ",";
+ Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
+
+ VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+ &Context->Idents.get(S), strType, 0,
+ SC_Static, SC_None);
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue,
+ SourceLocation());
+ Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
+ Context->getPointerType(DRE->getType()),
+ VK_RValue, OK_Ordinary,
+ SourceLocation());
+ // cast to NSConstantString *
+ CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
+ CK_BitCast, Unop);
+ ReplaceStmt(Exp, cast);
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return cast;
+}
+
+// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
+QualType RewriteObjC::getSuperStructType() {
+ if (!SuperStructDecl) {
+ SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("objc_super"));
+ QualType FieldTypes[2];
+
+ // struct objc_object *receiver;
+ FieldTypes[0] = Context->getObjCIdType();
+ // struct objc_class *super;
+ FieldTypes[1] = Context->getObjCClassType();
+
+ // Create fields
+ for (unsigned i = 0; i < 2; ++i) {
+ SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], 0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false));
+ }
+
+ SuperStructDecl->completeDefinition();
+ }
+ return Context->getTagDeclType(SuperStructDecl);
+}
+
+QualType RewriteObjC::getConstantStringStructType() {
+ if (!ConstantStringDecl) {
+ ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("__NSConstantStringImpl"));
+ QualType FieldTypes[4];
+
+ // struct objc_object *receiver;
+ FieldTypes[0] = Context->getObjCIdType();
+ // int flags;
+ FieldTypes[1] = Context->IntTy;
+ // char *str;
+ FieldTypes[2] = Context->getPointerType(Context->CharTy);
+ // long length;
+ FieldTypes[3] = Context->LongTy;
+
+ // Create fields
+ for (unsigned i = 0; i < 4; ++i) {
+ ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
+ ConstantStringDecl,
+ SourceLocation(), 0,
+ FieldTypes[i], 0,
+ /*BitWidth=*/0,
+ /*Mutable=*/true));
+ }
+
+ ConstantStringDecl->completeDefinition();
+ }
+ return Context->getTagDeclType(ConstantStringDecl);
+}
+
+Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!SelGetUidFunctionDecl)
+ SynthSelGetUidFunctionDecl();
+ if (!MsgSendFunctionDecl)
+ SynthMsgSendFunctionDecl();
+ if (!MsgSendSuperFunctionDecl)
+ SynthMsgSendSuperFunctionDecl();
+ if (!MsgSendStretFunctionDecl)
+ SynthMsgSendStretFunctionDecl();
+ if (!MsgSendSuperStretFunctionDecl)
+ SynthMsgSendSuperStretFunctionDecl();
+ if (!MsgSendFpretFunctionDecl)
+ SynthMsgSendFpretFunctionDecl();
+ if (!GetClassFunctionDecl)
+ SynthGetClassFunctionDecl();
+ if (!GetSuperClassFunctionDecl)
+ SynthGetSuperClassFunctionDecl();
+ if (!GetMetaClassFunctionDecl)
+ SynthGetMetaClassFunctionDecl();
+
+ // default to objc_msgSend().
+ FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
+ // May need to use objc_msgSend_stret() as well.
+ FunctionDecl *MsgSendStretFlavor = 0;
+ if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
+ QualType resultType = mDecl->getResultType();
+ if (resultType->isRecordType())
+ MsgSendStretFlavor = MsgSendStretFunctionDecl;
+ else if (resultType->isRealFloatingType())
+ MsgSendFlavor = MsgSendFpretFunctionDecl;
+ }
+
+ // Synthesize a call to objc_msgSend().
+ llvm::SmallVector<Expr*, 8> MsgExprs;
+ switch (Exp->getReceiverKind()) {
+ case ObjCMessageExpr::SuperClass: {
+ MsgSendFlavor = MsgSendSuperFunctionDecl;
+ if (MsgSendStretFlavor)
+ MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
+ assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+
+ ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
+
+ llvm::SmallVector<Expr*, 4> InitExprs;
+
+ // set the receiver to self, the first argument to all methods.
+ InitExprs.push_back(
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast,
+ new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ Context->getObjCIdType(),
+ VK_RValue,
+ SourceLocation()))
+ ); // set the 'receiver'.
+
+ // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
+ llvm::SmallVector<Expr*, 8> ClsExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ ClsExprs.push_back(StringLiteral::Create(*Context,
+ ClassDecl->getIdentifier()->getNameStart(),
+ ClassDecl->getIdentifier()->getLength(),
+ false, argType, SourceLocation()));
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
+ &ClsExprs[0],
+ ClsExprs.size(),
+ StartLoc,
+ EndLoc);
+ // (Class)objc_getClass("CurrentClass")
+ CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
+ Context->getObjCClassType(),
+ CK_BitCast, Cls);
+ ClsExprs.clear();
+ ClsExprs.push_back(ArgExpr);
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
+ &ClsExprs[0], ClsExprs.size(),
+ StartLoc, EndLoc);
+
+ // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
+ // To turn off a warning, type-cast to 'id'
+ InitExprs.push_back( // set 'super class', using class_getSuperclass().
+ NoTypeInfoCStyleCastExpr(Context,
+ Context->getObjCIdType(),
+ CK_BitCast, Cls));
+ // struct objc_super
+ QualType superType = getSuperStructType();
+ Expr *SuperRep;
+
+ if (LangOpts.Microsoft) {
+ SynthSuperContructorFunctionDecl();
+ // Simulate a contructor call...
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
+ superType, VK_LValue,
+ SourceLocation());
+ SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
+ InitExprs.size(),
+ superType, VK_LValue,
+ SourceLocation());
+ // The code for super is a little tricky to prevent collision with
+ // the structure definition in the header. The rewriter has it's own
+ // internal definition (__rw_objc_super) that is uses. This is why
+ // we need the cast below. For example:
+ // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+ //
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+ Context->getPointerType(SuperRep->getType()),
+ VK_RValue, OK_Ordinary,
+ SourceLocation());
+ SuperRep = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(superType),
+ CK_BitCast, SuperRep);
+ } else {
+ // (struct objc_super) { <exprs from above> }
+ InitListExpr *ILE =
+ new (Context) InitListExpr(*Context, SourceLocation(),
+ &InitExprs[0], InitExprs.size(),
+ SourceLocation());
+ TypeSourceInfo *superTInfo
+ = Context->getTrivialTypeSourceInfo(superType);
+ SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+ superType, VK_LValue,
+ ILE, false);
+ // struct objc_super *
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+ Context->getPointerType(SuperRep->getType()),
+ VK_RValue, OK_Ordinary,
+ SourceLocation());
+ }
+ MsgExprs.push_back(SuperRep);
+ break;
+ }
+
+ case ObjCMessageExpr::Class: {
+ llvm::SmallVector<Expr*, 8> ClsExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ ObjCInterfaceDecl *Class
+ = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
+ IdentifierInfo *clsName = Class->getIdentifier();
+ ClsExprs.push_back(StringLiteral::Create(*Context,
+ clsName->getNameStart(),
+ clsName->getLength(),
+ false, argType,
+ SourceLocation()));
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+ &ClsExprs[0],
+ ClsExprs.size(),
+ StartLoc, EndLoc);
+ MsgExprs.push_back(Cls);
+ break;
+ }
+
+ case ObjCMessageExpr::SuperInstance:{
+ MsgSendFlavor = MsgSendSuperFunctionDecl;
+ if (MsgSendStretFlavor)
+ MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
+ assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+ ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
+ llvm::SmallVector<Expr*, 4> InitExprs;
+
+ InitExprs.push_back(
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast,
+ new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
+ Context->getObjCIdType(),
+ VK_RValue, SourceLocation()))
+ ); // set the 'receiver'.
+
+ // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
+ llvm::SmallVector<Expr*, 8> ClsExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ ClsExprs.push_back(StringLiteral::Create(*Context,
+ ClassDecl->getIdentifier()->getNameStart(),
+ ClassDecl->getIdentifier()->getLength(),
+ false, argType, SourceLocation()));
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+ &ClsExprs[0],
+ ClsExprs.size(),
+ StartLoc, EndLoc);
+ // (Class)objc_getClass("CurrentClass")
+ CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
+ Context->getObjCClassType(),
+ CK_BitCast, Cls);
+ ClsExprs.clear();
+ ClsExprs.push_back(ArgExpr);
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
+ &ClsExprs[0], ClsExprs.size(),
+ StartLoc, EndLoc);
+
+ // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
+ // To turn off a warning, type-cast to 'id'
+ InitExprs.push_back(
+ // set 'super class', using class_getSuperclass().
+ NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast, Cls));
+ // struct objc_super
+ QualType superType = getSuperStructType();
+ Expr *SuperRep;
+
+ if (LangOpts.Microsoft) {
+ SynthSuperContructorFunctionDecl();
+ // Simulate a contructor call...
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
+ superType, VK_LValue,
+ SourceLocation());
+ SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
+ InitExprs.size(),
+ superType, VK_LValue, SourceLocation());
+ // The code for super is a little tricky to prevent collision with
+ // the structure definition in the header. The rewriter has it's own
+ // internal definition (__rw_objc_super) that is uses. This is why
+ // we need the cast below. For example:
+ // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+ //
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
+ Context->getPointerType(SuperRep->getType()),
+ VK_RValue, OK_Ordinary,
+ SourceLocation());
+ SuperRep = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(superType),
+ CK_BitCast, SuperRep);
+ } else {
+ // (struct objc_super) { <exprs from above> }
+ InitListExpr *ILE =
+ new (Context) InitListExpr(*Context, SourceLocation(),
+ &InitExprs[0], InitExprs.size(),
+ SourceLocation());
+ TypeSourceInfo *superTInfo
+ = Context->getTrivialTypeSourceInfo(superType);
+ SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
+ superType, VK_RValue, ILE,
+ false);
+ }
+ MsgExprs.push_back(SuperRep);
+ break;
+ }
+
+ case ObjCMessageExpr::Instance: {
+ // Remove all type-casts because it may contain objc-style types; e.g.
+ // Foo<Proto> *.
+ Expr *recExpr = Exp->getInstanceReceiver();
+ while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
+ recExpr = CE->getSubExpr();
+ recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast, recExpr);
+ MsgExprs.push_back(recExpr);
+ break;
+ }
+ }
+
+ // Create a call to sel_registerName("selName"), it will be the 2nd argument.
+ llvm::SmallVector<Expr*, 8> SelExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ SelExprs.push_back(StringLiteral::Create(*Context,
+ Exp->getSelector().getAsString().c_str(),
+ Exp->getSelector().getAsString().size(),
+ false, argType, SourceLocation()));
+ CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
+ &SelExprs[0], SelExprs.size(),
+ StartLoc,
+ EndLoc);
+ MsgExprs.push_back(SelExp);
+
+ // Now push any user supplied arguments.
+ for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
+ Expr *userExpr = Exp->getArg(i);
+ // Make all implicit casts explicit...ICE comes in handy:-)
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
+ // Reuse the ICE type, it is exactly what the doctor ordered.
+ QualType type = ICE->getType()->isObjCQualifiedIdType()
+ ? Context->getObjCIdType()
+ : ICE->getType();
+ // Make sure we convert "type (^)(...)" to "type (*)(...)".
+ (void)convertBlockPointerToFunctionPointer(type);
+ userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK_BitCast,
+ userExpr);
+ }
+ // Make id<P...> cast into an 'id' cast.
+ else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
+ if (CE->getType()->isObjCQualifiedIdType()) {
+ while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
+ userExpr = CE->getSubExpr();
+ userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
+ CK_BitCast, userExpr);
+ }
+ }
+ MsgExprs.push_back(userExpr);
+ // We've transferred the ownership to MsgExprs. For now, we *don't* null
+ // out the argument in the original expression (since we aren't deleting
+ // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
+ //Exp->setArg(i, 0);
+ }
+ // Generate the funky cast.
+ CastExpr *cast;
+ llvm::SmallVector<QualType, 8> ArgTypes;
+ QualType returnType;
+
+ // Push 'id' and 'SEL', the 2 implicit arguments.
+ if (MsgSendFlavor == MsgSendSuperFunctionDecl)
+ ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
+ else
+ ArgTypes.push_back(Context->getObjCIdType());
+ ArgTypes.push_back(Context->getObjCSelType());
+ if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
+ // Push any user argument types.
+ for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
+ E = OMD->param_end(); PI != E; ++PI) {
+ QualType t = (*PI)->getType()->isObjCQualifiedIdType()
+ ? Context->getObjCIdType()
+ : (*PI)->getType();
+ // Make sure we convert "t (^)(...)" to "t (*)(...)".
+ (void)convertBlockPointerToFunctionPointer(t);
+ ArgTypes.push_back(t);
+ }
+ returnType = OMD->getResultType()->isObjCQualifiedIdType()
+ ? Context->getObjCIdType() : OMD->getResultType();
+ (void)convertBlockPointerToFunctionPointer(returnType);
+ } else {
+ returnType = Context->getObjCIdType();
+ }
+ // Get the type, we will need to reference it in a couple spots.
+ QualType msgSendType = MsgSendFlavor->getType();
+
+ // Create a reference to the objc_msgSend() declaration.
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType,
+ VK_LValue, SourceLocation());
+
+ // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
+ // If we don't do this cast, we get the following bizarre warning/note:
+ // xx.m:13: warning: function called through a non-compatible type
+ // xx.m:13: note: if this code is reached, the program will abort
+ cast = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidTy),
+ CK_BitCast, DRE);
+
+ // Now do the "normal" pointer to function cast.
+ QualType castType =
+ getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
+ // If we don't have a method decl, force a variadic cast.
+ Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true);
+ castType = Context->getPointerType(castType);
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
+ cast);
+
+ // Don't forget the parens to enforce the proper binding.
+ ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
+
+ const FunctionType *FT = msgSendType->getAs<FunctionType>();
+ CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
+ MsgExprs.size(),
+ FT->getResultType(), VK_RValue,
+ EndLoc);
+ Stmt *ReplacingStmt = CE;
+ if (MsgSendStretFlavor) {
+ // We have the method which returns a struct/union. Must also generate
+ // call to objc_msgSend_stret and hang both varieties on a conditional
+ // expression which dictate which one to envoke depending on size of
+ // method's return type.
+
+ // Create a reference to the objc_msgSend_stret() declaration.
+ DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
+ VK_LValue, SourceLocation());
+ // Need to cast objc_msgSend_stret to "void *" (see above comment).
+ cast = NoTypeInfoCStyleCastExpr(Context,
+ Context->getPointerType(Context->VoidTy),
+ CK_BitCast, STDRE);
+ // Now do the "normal" pointer to function cast.
+ castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
+ Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
+ castType = Context->getPointerType(castType);
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
+ cast);
+
+ // Don't forget the parens to enforce the proper binding.
+ PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
+
+ FT = msgSendType->getAs<FunctionType>();
+ CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
+ MsgExprs.size(),
+ FT->getResultType(), VK_RValue,
+ SourceLocation());
+
+ // Build sizeof(returnType)
+ SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
+ Context->getTrivialTypeSourceInfo(returnType),
+ Context->getSizeType(),
+ SourceLocation(), SourceLocation());
+ // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+ // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
+ // For X86 it is more complicated and some kind of target specific routine
+ // is needed to decide what to do.
+ unsigned IntSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+ IntegerLiteral *limit = IntegerLiteral::Create(*Context,
+ llvm::APInt(IntSize, 8),
+ Context->IntTy,
+ SourceLocation());
+ BinaryOperator *lessThanExpr =
+ new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
+ VK_RValue, OK_Ordinary, SourceLocation());
+ // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
+ ConditionalOperator *CondExpr =
+ new (Context) ConditionalOperator(lessThanExpr,
+ SourceLocation(), CE,
+ SourceLocation(), STCE,
+ returnType, VK_RValue, OK_Ordinary);
+ ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ CondExpr);
+ }
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return ReplacingStmt;
+}
+
+Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
+ Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
+ Exp->getLocEnd());
+
+ // Now do the actual rewrite.
+ ReplaceStmt(Exp, ReplacingStmt);
+
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return ReplacingStmt;
+}
+
+// typedef struct objc_object Protocol;
+QualType RewriteObjC::getProtocolType() {
+ if (!ProtocolTypeDecl) {
+ TypeSourceInfo *TInfo
+ = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
+ ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("Protocol"),
+ TInfo);
+ }
+ return Context->getTypeDeclType(ProtocolTypeDecl);
+}
+
+/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
+/// a synthesized/forward data reference (to the protocol's metadata).
+/// The forward references (and metadata) are generated in
+/// RewriteObjC::HandleTranslationUnit().
+Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
+ std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
+ IdentifierInfo *ID = &Context->Idents.get(Name);
+ VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+ ID, getProtocolType(), 0,
+ SC_Extern, SC_None);
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue,
+ SourceLocation());
+ Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
+ Context->getPointerType(DRE->getType()),
+ VK_RValue, OK_Ordinary, SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
+ CK_BitCast,
+ DerefExpr);
+ ReplaceStmt(Exp, castExpr);
+ ProtocolExprDecls.insert(Exp->getProtocol());
+ // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
+ return castExpr;
+
+}
+
+bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
+ const char *endBuf) {
+ while (startBuf < endBuf) {
+ if (*startBuf == '#') {
+ // Skip whitespace.
+ for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
+ ;
+ if (!strncmp(startBuf, "if", strlen("if")) ||
+ !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
+ !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
+ !strncmp(startBuf, "define", strlen("define")) ||
+ !strncmp(startBuf, "undef", strlen("undef")) ||
+ !strncmp(startBuf, "else", strlen("else")) ||
+ !strncmp(startBuf, "elif", strlen("elif")) ||
+ !strncmp(startBuf, "endif", strlen("endif")) ||
+ !strncmp(startBuf, "pragma", strlen("pragma")) ||
+ !strncmp(startBuf, "include", strlen("include")) ||
+ !strncmp(startBuf, "import", strlen("import")) ||
+ !strncmp(startBuf, "include_next", strlen("include_next")))
+ return true;
+ }
+ startBuf++;
+ }
+ return false;
+}
+
+/// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
+/// an objective-c class with ivars.
+void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
+ std::string &Result) {
+ assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
+ assert(CDecl->getName() != "" &&
+ "Name missing in SynthesizeObjCInternalStruct");
+ // Do not synthesize more than once.
+ if (ObjCSynthesizedStructs.count(CDecl))
+ return;
+ ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
+ int NumIvars = CDecl->ivar_size();
+ SourceLocation LocStart = CDecl->getLocStart();
+ SourceLocation LocEnd = CDecl->getLocEnd();
+
+ const char *startBuf = SM->getCharacterData(LocStart);
+ const char *endBuf = SM->getCharacterData(LocEnd);
+
+ // If no ivars and no root or if its root, directly or indirectly,
+ // have no ivars (thus not synthesized) then no need to synthesize this class.
+ if ((CDecl->isForwardDecl() || NumIvars == 0) &&
+ (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
+ endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
+ ReplaceText(LocStart, endBuf-startBuf, Result);
+ return;
+ }
+
+ // FIXME: This has potential of causing problem. If
+ // SynthesizeObjCInternalStruct is ever called recursively.
+ Result += "\nstruct ";
+ Result += CDecl->getNameAsString();
+ if (LangOpts.Microsoft)
+ Result += "_IMPL";
+
+ if (NumIvars > 0) {
+ const char *cursor = strchr(startBuf, '{');
+ assert((cursor && endBuf)
+ && "SynthesizeObjCInternalStruct - malformed @interface");
+ // If the buffer contains preprocessor directives, we do more fine-grained
+ // rewrites. This is intended to fix code that looks like (which occurs in
+ // NSURL.h, for example):
+ //
+ // #ifdef XYZ
+ // @interface Foo : NSObject
+ // #else
+ // @interface FooBar : NSObject
+ // #endif
+ // {
+ // int i;
+ // }
+ // @end
+ //
+ // This clause is segregated to avoid breaking the common case.
+ if (BufferContainsPPDirectives(startBuf, cursor)) {
+ SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
+ CDecl->getClassLoc();
+ const char *endHeader = SM->getCharacterData(L);
+ endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
+
+ if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+ // advance to the end of the referenced protocols.
+ while (endHeader < cursor && *endHeader != '>') endHeader++;
+ endHeader++;
+ }
+ // rewrite the original header
+ ReplaceText(LocStart, endHeader-startBuf, Result);
+ } else {
+ // rewrite the original header *without* disturbing the '{'
+ ReplaceText(LocStart, cursor-startBuf, Result);
+ }
+ if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
+ Result = "\n struct ";
+ Result += RCDecl->getNameAsString();
+ Result += "_IMPL ";
+ Result += RCDecl->getNameAsString();
+ Result += "_IVARS;\n";
+
+ // insert the super class structure definition.
+ SourceLocation OnePastCurly =
+ LocStart.getFileLocWithOffset(cursor-startBuf+1);
+ InsertText(OnePastCurly, Result);
+ }
+ cursor++; // past '{'
+
+ // Now comment out any visibility specifiers.
+ while (cursor < endBuf) {
+ if (*cursor == '@') {
+ SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+ // Skip whitespace.
+ for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
+ /*scan*/;
+
+ // FIXME: presence of @public, etc. inside comment results in
+ // this transformation as well, which is still correct c-code.
+ if (!strncmp(cursor, "public", strlen("public")) ||
+ !strncmp(cursor, "private", strlen("private")) ||
+ !strncmp(cursor, "package", strlen("package")) ||
+ !strncmp(cursor, "protected", strlen("protected")))
+ InsertText(atLoc, "// ");
+ }
+ // FIXME: If there are cases where '<' is used in ivar declaration part
+ // of user code, then scan the ivar list and use needToScanForQualifiers
+ // for type checking.
+ else if (*cursor == '<') {
+ SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+ InsertText(atLoc, "/* ");
+ cursor = strchr(cursor, '>');
+ cursor++;
+ atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+ InsertText(atLoc, " */");
+ } else if (*cursor == '^') { // rewrite block specifier.
+ SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
+ ReplaceText(caretLoc, 1, "*");
+ }
+ cursor++;
+ }
+ // Don't forget to add a ';'!!
+ InsertText(LocEnd.getFileLocWithOffset(1), ";");
+ } else { // we don't have any instance variables - insert super struct.
+ endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
+ Result += " {\n struct ";
+ Result += RCDecl->getNameAsString();
+ Result += "_IMPL ";
+ Result += RCDecl->getNameAsString();
+ Result += "_IVARS;\n};\n";
+ ReplaceText(LocStart, endBuf-startBuf, Result);
+ }
+ // Mark this struct as having been generated.
+ if (!ObjCSynthesizedStructs.insert(CDecl))
+ assert(false && "struct already synthesize- SynthesizeObjCInternalStruct");
+}
+
+// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
+/// class methods.
+template<typename MethodIterator>
+void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
+ MethodIterator MethodEnd,
+ bool IsInstanceMethod,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
+ std::string &Result) {
+ if (MethodBegin == MethodEnd) return;
+
+ if (!objc_impl_method) {
+ /* struct _objc_method {
+ SEL _cmd;
+ char *method_types;
+ void *_imp;
+ }
+ */
+ Result += "\nstruct _objc_method {\n";
+ Result += "\tSEL _cmd;\n";
+ Result += "\tchar *method_types;\n";
+ Result += "\tvoid *_imp;\n";
+ Result += "};\n";
+
+ objc_impl_method = true;
+ }
+
+ // Build _objc_method_list for class's methods if needed
+
+ /* struct {
+ struct _objc_method_list *next_method;
+ int method_count;
+ struct _objc_method method_list[];
+ }
+ */
+ unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
+ Result += "\nstatic struct {\n";
+ Result += "\tstruct _objc_method_list *next_method;\n";
+ Result += "\tint method_count;\n";
+ Result += "\tstruct _objc_method method_list[";
+ Result += utostr(NumMethods);
+ Result += "];\n} _OBJC_";
+ Result += prefix;
+ Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
+ Result += "_METHODS_";
+ Result += ClassName;
+ Result += " __attribute__ ((used, section (\"__OBJC, __";
+ Result += IsInstanceMethod ? "inst" : "cls";
+ Result += "_meth\")))= ";
+ Result += "{\n\t0, " + utostr(NumMethods) + "\n";
+
+ Result += "\t,{{(SEL)\"";
+ Result += (*MethodBegin)->getSelector().getAsString().c_str();
+ std::string MethodTypeString;
+ Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+ Result += "\", \"";
+ Result += MethodTypeString;
+ Result += "\", (void *)";
+ Result += MethodInternalNames[*MethodBegin];
+ Result += "}\n";
+ for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
+ Result += "\t ,{(SEL)\"";
+ Result += (*MethodBegin)->getSelector().getAsString().c_str();
+ std::string MethodTypeString;
+ Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+ Result += "\", \"";
+ Result += MethodTypeString;
+ Result += "\", (void *)";
+ Result += MethodInternalNames[*MethodBegin];
+ Result += "}\n";
+ }
+ Result += "\t }\n};\n";
+}
+
+/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
+void RewriteObjC::
+RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, llvm::StringRef prefix,
+ llvm::StringRef ClassName, std::string &Result) {
+ static bool objc_protocol_methods = false;
+
+ // Output struct protocol_methods holder of method selector and type.
+ if (!objc_protocol_methods && !PDecl->isForwardDecl()) {
+ /* struct protocol_methods {
+ SEL _cmd;
+ char *method_types;
+ }
+ */
+ Result += "\nstruct _protocol_methods {\n";
+ Result += "\tstruct objc_selector *_cmd;\n";
+ Result += "\tchar *method_types;\n";
+ Result += "};\n";
+
+ objc_protocol_methods = true;
+ }
+ // Do not synthesize the protocol more than once.
+ if (ObjCSynthesizedProtocols.count(PDecl))
+ return;
+
+ if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+ unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
+ PDecl->instmeth_end());
+ /* struct _objc_protocol_method_list {
+ int protocol_method_count;
+ struct protocol_methods protocols[];
+ }
+ */
+ Result += "\nstatic struct {\n";
+ Result += "\tint protocol_method_count;\n";
+ Result += "\tstruct _protocol_methods protocol_methods[";
+ Result += utostr(NumMethods);
+ Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
+ Result += PDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
+ "{\n\t" + utostr(NumMethods) + "\n";
+
+ // Output instance methods declared in this protocol.
+ for (ObjCProtocolDecl::instmeth_iterator
+ I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
+ I != E; ++I) {
+ if (I == PDecl->instmeth_begin())
+ Result += "\t ,{{(struct objc_selector *)\"";
+ else
+ Result += "\t ,{(struct objc_selector *)\"";
+ Result += (*I)->getSelector().getAsString();
+ std::string MethodTypeString;
+ Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+ Result += "\", \"";
+ Result += MethodTypeString;
+ Result += "\"}\n";
+ }
+ Result += "\t }\n};\n";
+ }
+
+ // Output class methods declared in this protocol.
+ unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
+ PDecl->classmeth_end());
+ if (NumMethods > 0) {
+ /* struct _objc_protocol_method_list {
+ int protocol_method_count;
+ struct protocol_methods protocols[];
+ }
+ */
+ Result += "\nstatic struct {\n";
+ Result += "\tint protocol_method_count;\n";
+ Result += "\tstruct _protocol_methods protocol_methods[";
+ Result += utostr(NumMethods);
+ Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
+ Result += PDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+ "{\n\t";
+ Result += utostr(NumMethods);
+ Result += "\n";
+
+ // Output instance methods declared in this protocol.
+ for (ObjCProtocolDecl::classmeth_iterator
+ I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+ I != E; ++I) {
+ if (I == PDecl->classmeth_begin())
+ Result += "\t ,{{(struct objc_selector *)\"";
+ else
+ Result += "\t ,{(struct objc_selector *)\"";
+ Result += (*I)->getSelector().getAsString();
+ std::string MethodTypeString;
+ Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+ Result += "\", \"";
+ Result += MethodTypeString;
+ Result += "\"}\n";
+ }
+ Result += "\t }\n};\n";
+ }
+
+ // Output:
+ /* struct _objc_protocol {
+ // Objective-C 1.0 extensions
+ struct _objc_protocol_extension *isa;
+ char *protocol_name;
+ struct _objc_protocol **protocol_list;
+ struct _objc_protocol_method_list *instance_methods;
+ struct _objc_protocol_method_list *class_methods;
+ };
+ */
+ static bool objc_protocol = false;
+ if (!objc_protocol) {
+ Result += "\nstruct _objc_protocol {\n";
+ Result += "\tstruct _objc_protocol_extension *isa;\n";
+ Result += "\tchar *protocol_name;\n";
+ Result += "\tstruct _objc_protocol **protocol_list;\n";
+ Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
+ Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
+ Result += "};\n";
+
+ objc_protocol = true;
+ }
+
+ Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
+ Result += PDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
+ "{\n\t0, \"";
+ Result += PDecl->getNameAsString();
+ Result += "\", 0, ";
+ if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
+ Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
+ Result += PDecl->getNameAsString();
+ Result += ", ";
+ }
+ else
+ Result += "0, ";
+ if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
+ Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
+ Result += PDecl->getNameAsString();
+ Result += "\n";
+ }
+ else
+ Result += "0\n";
+ Result += "};\n";
+
+ // Mark this protocol as having been generated.
+ if (!ObjCSynthesizedProtocols.insert(PDecl))
+ assert(false && "protocol already synthesized");
+
+}
+
+void RewriteObjC::
+RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols,
+ llvm::StringRef prefix, llvm::StringRef ClassName,
+ std::string &Result) {
+ if (Protocols.empty()) return;
+
+ for (unsigned i = 0; i != Protocols.size(); i++)
+ RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
+
+ // Output the top lovel protocol meta-data for the class.
+ /* struct _objc_protocol_list {
+ struct _objc_protocol_list *next;
+ int protocol_count;
+ struct _objc_protocol *class_protocols[];
+ }
+ */
+ Result += "\nstatic struct {\n";
+ Result += "\tstruct _objc_protocol_list *next;\n";
+ Result += "\tint protocol_count;\n";
+ Result += "\tstruct _objc_protocol *class_protocols[";
+ Result += utostr(Protocols.size());
+ Result += "];\n} _OBJC_";
+ Result += prefix;
+ Result += "_PROTOCOLS_";
+ Result += ClassName;
+ Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
+ "{\n\t0, ";
+ Result += utostr(Protocols.size());
+ Result += "\n";
+
+ Result += "\t,{&_OBJC_PROTOCOL_";
+ Result += Protocols[0]->getNameAsString();
+ Result += " \n";
+
+ for (unsigned i = 1; i != Protocols.size(); i++) {
+ Result += "\t ,&_OBJC_PROTOCOL_";
+ Result += Protocols[i]->getNameAsString();
+ Result += "\n";
+ }
+ Result += "\t }\n};\n";
+}
+
+
+/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
+/// implementation.
+void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
+ std::string &Result) {
+ ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
+ // Find category declaration for this implementation.
+ ObjCCategoryDecl *CDecl;
+ for (CDecl = ClassDecl->getCategoryList(); CDecl;
+ CDecl = CDecl->getNextClassCategory())
+ if (CDecl->getIdentifier() == IDecl->getIdentifier())
+ break;
+
+ std::string FullCategoryName = ClassDecl->getNameAsString();
+ FullCategoryName += '_';
+ FullCategoryName += IDecl->getNameAsString();
+
+ // Build _objc_method_list for class's instance methods if needed
+ llvm::SmallVector<ObjCMethodDecl *, 32>
+ InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+
+ // If any of our property implementations have associated getters or
+ // setters, produce metadata for them as well.
+ for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+ PropEnd = IDecl->propimpl_end();
+ Prop != PropEnd; ++Prop) {
+ if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ continue;
+ if (!(*Prop)->getPropertyIvarDecl())
+ continue;
+ ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+ if (!PD)
+ continue;
+ if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ InstanceMethods.push_back(Getter);
+ if (PD->isReadOnly())
+ continue;
+ if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ InstanceMethods.push_back(Setter);
+ }
+ RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+ true, "CATEGORY_", FullCategoryName.c_str(),
+ Result);
+
+ // Build _objc_method_list for class's class methods if needed
+ RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+ false, "CATEGORY_", FullCategoryName.c_str(),
+ Result);
+
+ // Protocols referenced in class declaration?
+ // Null CDecl is case of a category implementation with no category interface
+ if (CDecl)
+ RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
+ FullCategoryName, Result);
+ /* struct _objc_category {
+ char *category_name;
+ char *class_name;
+ struct _objc_method_list *instance_methods;
+ struct _objc_method_list *class_methods;
+ struct _objc_protocol_list *protocols;
+ // Objective-C 1.0 extensions
+ uint32_t size; // sizeof (struct _objc_category)
+ struct _objc_property_list *instance_properties; // category's own
+ // @property decl.
+ };
+ */
+
+ static bool objc_category = false;
+ if (!objc_category) {
+ Result += "\nstruct _objc_category {\n";
+ Result += "\tchar *category_name;\n";
+ Result += "\tchar *class_name;\n";
+ Result += "\tstruct _objc_method_list *instance_methods;\n";
+ Result += "\tstruct _objc_method_list *class_methods;\n";
+ Result += "\tstruct _objc_protocol_list *protocols;\n";
+ Result += "\tunsigned int size;\n";
+ Result += "\tstruct _objc_property_list *instance_properties;\n";
+ Result += "};\n";
+ objc_category = true;
+ }
+ Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
+ Result += FullCategoryName;
+ Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
+ Result += IDecl->getNameAsString();
+ Result += "\"\n\t, \"";
+ Result += ClassDecl->getNameAsString();
+ Result += "\"\n";
+
+ if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+ Result += "\t, (struct _objc_method_list *)"
+ "&_OBJC_CATEGORY_INSTANCE_METHODS_";
+ Result += FullCategoryName;
+ Result += "\n";
+ }
+ else
+ Result += "\t, 0\n";
+ if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+ Result += "\t, (struct _objc_method_list *)"
+ "&_OBJC_CATEGORY_CLASS_METHODS_";
+ Result += FullCategoryName;
+ Result += "\n";
+ }
+ else
+ Result += "\t, 0\n";
+
+ if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
+ Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
+ Result += FullCategoryName;
+ Result += "\n";
+ }
+ else
+ Result += "\t, 0\n";
+ Result += "\t, sizeof(struct _objc_category), 0\n};\n";
+}
+
+/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
+/// ivar offset.
+void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar,
+ std::string &Result) {
+ if (ivar->isBitField()) {
+ // FIXME: The hack below doesn't work for bitfields. For now, we simply
+ // place all bitfields at offset 0.
+ Result += "0";
+ } else {
+ Result += "__OFFSETOFIVAR__(struct ";
+ Result += ivar->getContainingInterface()->getNameAsString();
+ if (LangOpts.Microsoft)
+ Result += "_IMPL";
+ Result += ", ";
+ Result += ivar->getNameAsString();
+ Result += ")";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Meta Data Emission
+//===----------------------------------------------------------------------===//
+
+void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
+ std::string &Result) {
+ ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
+
+ // Explictly declared @interface's are already synthesized.
+ if (CDecl->isImplicitInterfaceDecl()) {
+ // FIXME: Implementation of a class with no @interface (legacy) doese not
+ // produce correct synthesis as yet.
+ SynthesizeObjCInternalStruct(CDecl, Result);
+ }
+
+ // Build _objc_ivar_list metadata for classes ivars if needed
+ unsigned NumIvars = !IDecl->ivar_empty()
+ ? IDecl->ivar_size()
+ : (CDecl ? CDecl->ivar_size() : 0);
+ if (NumIvars > 0) {
+ static bool objc_ivar = false;
+ if (!objc_ivar) {
+ /* struct _objc_ivar {
+ char *ivar_name;
+ char *ivar_type;
+ int ivar_offset;
+ };
+ */
+ Result += "\nstruct _objc_ivar {\n";
+ Result += "\tchar *ivar_name;\n";
+ Result += "\tchar *ivar_type;\n";
+ Result += "\tint ivar_offset;\n";
+ Result += "};\n";
+
+ objc_ivar = true;
+ }
+
+ /* struct {
+ int ivar_count;
+ struct _objc_ivar ivar_list[nIvars];
+ };
+ */
+ Result += "\nstatic struct {\n";
+ Result += "\tint ivar_count;\n";
+ Result += "\tstruct _objc_ivar ivar_list[";
+ Result += utostr(NumIvars);
+ Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
+ Result += IDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
+ "{\n\t";
+ Result += utostr(NumIvars);
+ Result += "\n";
+
+ ObjCInterfaceDecl::ivar_iterator IVI, IVE;
+ llvm::SmallVector<ObjCIvarDecl *, 8> IVars;
+ if (!IDecl->ivar_empty()) {
+ for (ObjCInterfaceDecl::ivar_iterator
+ IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
+ IV != IVEnd; ++IV)
+ IVars.push_back(*IV);
+ IVI = IDecl->ivar_begin();
+ IVE = IDecl->ivar_end();
+ } else {
+ IVI = CDecl->ivar_begin();
+ IVE = CDecl->ivar_end();
+ }
+ Result += "\t,{{\"";
+ Result += (*IVI)->getNameAsString();
+ Result += "\", \"";
+ std::string TmpString, StrEncoding;
+ Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+ QuoteDoublequotes(TmpString, StrEncoding);
+ Result += StrEncoding;
+ Result += "\", ";
+ SynthesizeIvarOffsetComputation(*IVI, Result);
+ Result += "}\n";
+ for (++IVI; IVI != IVE; ++IVI) {
+ Result += "\t ,{\"";
+ Result += (*IVI)->getNameAsString();
+ Result += "\", \"";
+ std::string TmpString, StrEncoding;
+ Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
+ QuoteDoublequotes(TmpString, StrEncoding);
+ Result += StrEncoding;
+ Result += "\", ";
+ SynthesizeIvarOffsetComputation((*IVI), Result);
+ Result += "}\n";
+ }
+
+ Result += "\t }\n};\n";
+ }
+
+ // Build _objc_method_list for class's instance methods if needed
+ llvm::SmallVector<ObjCMethodDecl *, 32>
+ InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
+
+ // If any of our property implementations have associated getters or
+ // setters, produce metadata for them as well.
+ for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
+ PropEnd = IDecl->propimpl_end();
+ Prop != PropEnd; ++Prop) {
+ if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ continue;
+ if (!(*Prop)->getPropertyIvarDecl())
+ continue;
+ ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
+ if (!PD)
+ continue;
+ if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ if (!Getter->isDefined())
+ InstanceMethods.push_back(Getter);
+ if (PD->isReadOnly())
+ continue;
+ if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ if (!Setter->isDefined())
+ InstanceMethods.push_back(Setter);
+ }
+ RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
+ true, "", IDecl->getName(), Result);
+
+ // Build _objc_method_list for class's class methods if needed
+ RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
+ false, "", IDecl->getName(), Result);
+
+ // Protocols referenced in class declaration?
+ RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
+ "CLASS", CDecl->getName(), Result);
+
+ // Declaration of class/meta-class metadata
+ /* struct _objc_class {
+ struct _objc_class *isa; // or const char *root_class_name when metadata
+ const char *super_class_name;
+ char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct _objc_ivar_list *ivars;
+ struct _objc_method_list *methods;
+ struct objc_cache *cache;
+ struct objc_protocol_list *protocols;
+ const char *ivar_layout;
+ struct _objc_class_ext *ext;
+ };
+ */
+ static bool objc_class = false;
+ if (!objc_class) {
+ Result += "\nstruct _objc_class {\n";
+ Result += "\tstruct _objc_class *isa;\n";
+ Result += "\tconst char *super_class_name;\n";
+ Result += "\tchar *name;\n";
+ Result += "\tlong version;\n";
+ Result += "\tlong info;\n";
+ Result += "\tlong instance_size;\n";
+ Result += "\tstruct _objc_ivar_list *ivars;\n";
+ Result += "\tstruct _objc_method_list *methods;\n";
+ Result += "\tstruct objc_cache *cache;\n";
+ Result += "\tstruct _objc_protocol_list *protocols;\n";
+ Result += "\tconst char *ivar_layout;\n";
+ Result += "\tstruct _objc_class_ext *ext;\n";
+ Result += "};\n";
+ objc_class = true;
+ }
+
+ // Meta-class metadata generation.
+ ObjCInterfaceDecl *RootClass = 0;
+ ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
+ while (SuperClass) {
+ RootClass = SuperClass;
+ SuperClass = SuperClass->getSuperClass();
+ }
+ SuperClass = CDecl->getSuperClass();
+
+ Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
+ Result += CDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
+ "{\n\t(struct _objc_class *)\"";
+ Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
+ Result += "\"";
+
+ if (SuperClass) {
+ Result += ", \"";
+ Result += SuperClass->getNameAsString();
+ Result += "\", \"";
+ Result += CDecl->getNameAsString();
+ Result += "\"";
+ }
+ else {
+ Result += ", 0, \"";
+ Result += CDecl->getNameAsString();
+ Result += "\"";
+ }
+ // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
+ // 'info' field is initialized to CLS_META(2) for metaclass
+ Result += ", 0,2, sizeof(struct _objc_class), 0";
+ if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
+ Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
+ Result += IDecl->getNameAsString();
+ Result += "\n";
+ }
+ else
+ Result += ", 0\n";
+ if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+ Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
+ Result += CDecl->getNameAsString();
+ Result += ",0,0\n";
+ }
+ else
+ Result += "\t,0,0,0,0\n";
+ Result += "};\n";
+
+ // class metadata generation.
+ Result += "\nstatic struct _objc_class _OBJC_CLASS_";
+ Result += CDecl->getNameAsString();
+ Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
+ "{\n\t&_OBJC_METACLASS_";
+ Result += CDecl->getNameAsString();
+ if (SuperClass) {
+ Result += ", \"";
+ Result += SuperClass->getNameAsString();
+ Result += "\", \"";
+ Result += CDecl->getNameAsString();
+ Result += "\"";
+ }
+ else {
+ Result += ", 0, \"";
+ Result += CDecl->getNameAsString();
+ Result += "\"";
+ }
+ // 'info' field is initialized to CLS_CLASS(1) for class
+ Result += ", 0,1";
+ if (!ObjCSynthesizedStructs.count(CDecl))
+ Result += ",0";
+ else {
+ // class has size. Must synthesize its size.
+ Result += ",sizeof(struct ";
+ Result += CDecl->getNameAsString();
+ if (LangOpts.Microsoft)
+ Result += "_IMPL";
+ Result += ")";
+ }
+ if (NumIvars > 0) {
+ Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
+ Result += CDecl->getNameAsString();
+ Result += "\n\t";
+ }
+ else
+ Result += ",0";
+ if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
+ Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
+ Result += CDecl->getNameAsString();
+ Result += ", 0\n\t";
+ }
+ else
+ Result += ",0,0";
+ if (CDecl->protocol_begin() != CDecl->protocol_end()) {
+ Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
+ Result += CDecl->getNameAsString();
+ Result += ", 0,0\n";
+ }
+ else
+ Result += ",0,0,0\n";
+ Result += "};\n";
+}
+
+/// RewriteImplementations - This routine rewrites all method implementations
+/// and emits meta-data.
+
+void RewriteObjC::RewriteImplementations() {
+ int ClsDefCount = ClassImplementation.size();
+ int CatDefCount = CategoryImplementation.size();
+
+ // Rewrite implemented methods
+ for (int i = 0; i < ClsDefCount; i++)
+ RewriteImplementationDecl(ClassImplementation[i]);
+
+ for (int i = 0; i < CatDefCount; i++)
+ RewriteImplementationDecl(CategoryImplementation[i]);
+}
+
+void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) {
+ int ClsDefCount = ClassImplementation.size();
+ int CatDefCount = CategoryImplementation.size();
+
+ // For each implemented class, write out all its meta data.
+ for (int i = 0; i < ClsDefCount; i++)
+ RewriteObjCClassMetaData(ClassImplementation[i], Result);
+
+ // For each implemented category, write out all its meta data.
+ for (int i = 0; i < CatDefCount; i++)
+ RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
+
+ // Write objc_symtab metadata
+ /*
+ struct _objc_symtab
+ {
+ long sel_ref_cnt;
+ SEL *refs;
+ short cls_def_cnt;
+ short cat_def_cnt;
+ void *defs[cls_def_cnt + cat_def_cnt];
+ };
+ */
+
+ Result += "\nstruct _objc_symtab {\n";
+ Result += "\tlong sel_ref_cnt;\n";
+ Result += "\tSEL *refs;\n";
+ Result += "\tshort cls_def_cnt;\n";
+ Result += "\tshort cat_def_cnt;\n";
+ Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
+ Result += "};\n\n";
+
+ Result += "static struct _objc_symtab "
+ "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
+ Result += "\t0, 0, " + utostr(ClsDefCount)
+ + ", " + utostr(CatDefCount) + "\n";
+ for (int i = 0; i < ClsDefCount; i++) {
+ Result += "\t,&_OBJC_CLASS_";
+ Result += ClassImplementation[i]->getNameAsString();
+ Result += "\n";
+ }
+
+ for (int i = 0; i < CatDefCount; i++) {
+ Result += "\t,&_OBJC_CATEGORY_";
+ Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
+ Result += "_";
+ Result += CategoryImplementation[i]->getNameAsString();
+ Result += "\n";
+ }
+
+ Result += "};\n\n";
+
+ // Write objc_module metadata
+
+ /*
+ struct _objc_module {
+ long version;
+ long size;
+ const char *name;
+ struct _objc_symtab *symtab;
+ }
+ */
+
+ Result += "\nstruct _objc_module {\n";
+ Result += "\tlong version;\n";
+ Result += "\tlong size;\n";
+ Result += "\tconst char *name;\n";
+ Result += "\tstruct _objc_symtab *symtab;\n";
+ Result += "};\n\n";
+ Result += "static struct _objc_module "
+ "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
+ Result += "\t" + utostr(OBJC_ABI_VERSION) +
+ ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
+ Result += "};\n\n";
+
+ if (LangOpts.Microsoft) {
+ if (ProtocolExprDecls.size()) {
+ Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
+ Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
+ for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+ E = ProtocolExprDecls.end(); I != E; ++I) {
+ Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
+ Result += (*I)->getNameAsString();
+ Result += " = &_OBJC_PROTOCOL_";
+ Result += (*I)->getNameAsString();
+ Result += ";\n";
+ }
+ Result += "#pragma data_seg(pop)\n\n";
+ }
+ Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
+ Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
+ Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
+ Result += "&_OBJC_MODULES;\n";
+ Result += "#pragma data_seg(pop)\n\n";
+ }
+}
+
+void RewriteObjC::RewriteByRefString(std::string &ResultStr,
+ const std::string &Name,
+ ValueDecl *VD, bool def) {
+ assert(BlockByRefDeclNo.count(VD) &&
+ "RewriteByRefString: ByRef decl missing");
+ if (def)
+ ResultStr += "struct ";
+ ResultStr += "__Block_byref_" + Name +
+ "_" + utostr(BlockByRefDeclNo[VD]) ;
+}
+
+static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+ return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
+ return false;
+}
+
+std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
+ llvm::StringRef funcName,
+ std::string Tag) {
+ const FunctionType *AFT = CE->getFunctionType();
+ QualType RT = AFT->getResultType();
+ std::string StructRef = "struct " + Tag;
+ std::string S = "static " + RT.getAsString(Context->PrintingPolicy) + " __" +
+ funcName.str() + "_" + "block_func_" + utostr(i);
+
+ BlockDecl *BD = CE->getBlockDecl();
+
+ if (isa<FunctionNoProtoType>(AFT)) {
+ // No user-supplied arguments. Still need to pass in a pointer to the
+ // block (to reference imported block decl refs).
+ S += "(" + StructRef + " *__cself)";
+ } else if (BD->param_empty()) {
+ S += "(" + StructRef + " *__cself)";
+ } else {
+ const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
+ assert(FT && "SynthesizeBlockFunc: No function proto");
+ S += '(';
+ // first add the implicit argument.
+ S += StructRef + " *__cself, ";
+ std::string ParamStr;
+ for (BlockDecl::param_iterator AI = BD->param_begin(),
+ E = BD->param_end(); AI != E; ++AI) {
+ if (AI != BD->param_begin()) S += ", ";
+ ParamStr = (*AI)->getNameAsString();
+ QualType QT = (*AI)->getType();
+ if (convertBlockPointerToFunctionPointer(QT))
+ QT.getAsStringInternal(ParamStr, Context->PrintingPolicy);
+ else
+ QT.getAsStringInternal(ParamStr, Context->PrintingPolicy);
+ S += ParamStr;
+ }
+ if (FT->isVariadic()) {
+ if (!BD->param_empty()) S += ", ";
+ S += "...";
+ }
+ S += ')';
+ }
+ S += " {\n";
+
+ // Create local declarations to avoid rewriting all closure decl ref exprs.
+ // First, emit a declaration for all "by ref" decls.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+ E = BlockByRefDecls.end(); I != E; ++I) {
+ S += " ";
+ std::string Name = (*I)->getNameAsString();
+ std::string TypeString;
+ RewriteByRefString(TypeString, Name, (*I));
+ TypeString += " *";
+ Name = TypeString + Name;
+ S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
+ }
+ // Next, emit a declaration for all "by copy" declarations.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+ E = BlockByCopyDecls.end(); I != E; ++I) {
+ S += " ";
+ // Handle nested closure invocation. For example:
+ //
+ // void (^myImportedClosure)(void);
+ // myImportedClosure = ^(void) { setGlobalInt(x + y); };
+ //
+ // void (^anotherClosure)(void);
+ // anotherClosure = ^(void) {
+ // myImportedClosure(); // import and invoke the closure
+ // };
+ //
+ if (isTopLevelBlockPointerType((*I)->getType())) {
+ RewriteBlockPointerTypeVariable(S, (*I));
+ S += " = (";
+ RewriteBlockPointerType(S, (*I)->getType());
+ S += ")";
+ S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
+ }
+ else {
+ std::string Name = (*I)->getNameAsString();
+ QualType QT = (*I)->getType();
+ if (HasLocalVariableExternalStorage(*I))
+ QT = Context->getPointerType(QT);
+ QT.getAsStringInternal(Name, Context->PrintingPolicy);
+ S += Name + " = __cself->" +
+ (*I)->getNameAsString() + "; // bound by copy\n";
+ }
+ }
+ std::string RewrittenStr = RewrittenBlockExprs[CE];
+ const char *cstr = RewrittenStr.c_str();
+ while (*cstr++ != '{') ;
+ S += cstr;
+ S += "\n";
+ return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+ llvm::StringRef funcName,
+ std::string Tag) {
+ std::string StructRef = "struct " + Tag;
+ std::string S = "static void __";
+
+ S += funcName;
+ S += "_block_copy_" + utostr(i);
+ S += "(" + StructRef;
+ S += "*dst, " + StructRef;
+ S += "*src) {";
+ for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+ E = ImportedBlockDecls.end(); I != E; ++I) {
+ S += "_Block_object_assign((void*)&dst->";
+ S += (*I)->getNameAsString();
+ S += ", (void*)src->";
+ S += (*I)->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count((*I)))
+ S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+ else
+ S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
+ }
+ S += "}\n";
+
+ S += "\nstatic void __";
+ S += funcName;
+ S += "_block_dispose_" + utostr(i);
+ S += "(" + StructRef;
+ S += "*src) {";
+ for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
+ E = ImportedBlockDecls.end(); I != E; ++I) {
+ S += "_Block_object_dispose((void*)src->";
+ S += (*I)->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count((*I)))
+ S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
+ else
+ S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
+ }
+ S += "}\n";
+ return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
+ std::string Desc) {
+ std::string S = "\nstruct " + Tag;
+ std::string Constructor = " " + Tag;
+
+ S += " {\n struct __block_impl impl;\n";
+ S += " struct " + Desc;
+ S += "* Desc;\n";
+
+ Constructor += "(void *fp, "; // Invoke function pointer.
+ Constructor += "struct " + Desc; // Descriptor pointer.
+ Constructor += " *desc";
+
+ if (BlockDeclRefs.size()) {
+ // Output all "by copy" declarations.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+ E = BlockByCopyDecls.end(); I != E; ++I) {
+ S += " ";
+ std::string FieldName = (*I)->getNameAsString();
+ std::string ArgName = "_" + FieldName;
+ // Handle nested closure invocation. For example:
+ //
+ // void (^myImportedBlock)(void);
+ // myImportedBlock = ^(void) { setGlobalInt(x + y); };
+ //
+ // void (^anotherBlock)(void);
+ // anotherBlock = ^(void) {
+ // myImportedBlock(); // import and invoke the closure
+ // };
+ //
+ if (isTopLevelBlockPointerType((*I)->getType())) {
+ S += "struct __block_impl *";
+ Constructor += ", void *" + ArgName;
+ } else {
+ QualType QT = (*I)->getType();
+ if (HasLocalVariableExternalStorage(*I))
+ QT = Context->getPointerType(QT);
+ QT.getAsStringInternal(FieldName, Context->PrintingPolicy);
+ QT.getAsStringInternal(ArgName, Context->PrintingPolicy);
+ Constructor += ", " + ArgName;
+ }
+ S += FieldName + ";\n";
+ }
+ // Output all "by ref" declarations.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+ E = BlockByRefDecls.end(); I != E; ++I) {
+ S += " ";
+ std::string FieldName = (*I)->getNameAsString();
+ std::string ArgName = "_" + FieldName;
+ // Handle nested closure invocation. For example:
+ //
+ // void (^myImportedBlock)(void);
+ // myImportedBlock = ^(void) { setGlobalInt(x + y); };
+ //
+ // void (^anotherBlock)(void);
+ // anotherBlock = ^(void) {
+ // myImportedBlock(); // import and invoke the closure
+ // };
+ //
+ if (isTopLevelBlockPointerType((*I)->getType())) {
+ S += "struct __block_impl *";
+ Constructor += ", void *" + ArgName;
+ } else {
+ std::string TypeString;
+ RewriteByRefString(TypeString, FieldName, (*I));
+ TypeString += " *";
+ FieldName = TypeString + FieldName;
+ ArgName = TypeString + ArgName;
+ Constructor += ", " + ArgName;
+ }
+ S += FieldName + "; // by ref\n";
+ }
+ // Finish writing the constructor.
+ Constructor += ", int flags=0)";
+ // Initialize all "by copy" arguments.
+ bool firsTime = true;
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+ E = BlockByCopyDecls.end(); I != E; ++I) {
+ std::string Name = (*I)->getNameAsString();
+ if (firsTime) {
+ Constructor += " : ";
+ firsTime = false;
+ }
+ else
+ Constructor += ", ";
+ if (isTopLevelBlockPointerType((*I)->getType()))
+ Constructor += Name + "((struct __block_impl *)_" + Name + ")";
+ else
+ Constructor += Name + "(_" + Name + ")";
+ }
+ // Initialize all "by ref" arguments.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+ E = BlockByRefDecls.end(); I != E; ++I) {
+ std::string Name = (*I)->getNameAsString();
+ if (firsTime) {
+ Constructor += " : ";
+ firsTime = false;
+ }
+ else
+ Constructor += ", ";
+ if (isTopLevelBlockPointerType((*I)->getType()))
+ Constructor += Name + "((struct __block_impl *)_"
+ + Name + "->__forwarding)";
+ else
+ Constructor += Name + "(_" + Name + "->__forwarding)";
+ }
+
+ Constructor += " {\n";
+ if (GlobalVarDecl)
+ Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
+ else
+ Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+
+ Constructor += " Desc = desc;\n";
+ } else {
+ // Finish writing the constructor.
+ Constructor += ", int flags=0) {\n";
+ if (GlobalVarDecl)
+ Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
+ else
+ Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+ Constructor += " Desc = desc;\n";
+ }
+ Constructor += " ";
+ Constructor += "}\n";
+ S += Constructor;
+ S += "};\n";
+ return S;
+}
+
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag, int i,
+ llvm::StringRef FunName,
+ unsigned hasCopy) {
+ std::string S = "\nstatic struct " + DescTag;
+
+ S += " {\n unsigned long reserved;\n";
+ S += " unsigned long Block_size;\n";
+ if (hasCopy) {
+ S += " void (*copy)(struct ";
+ S += ImplTag; S += "*, struct ";
+ S += ImplTag; S += "*);\n";
+
+ S += " void (*dispose)(struct ";
+ S += ImplTag; S += "*);\n";
+ }
+ S += "} ";
+
+ S += DescTag + "_DATA = { 0, sizeof(struct ";
+ S += ImplTag + ")";
+ if (hasCopy) {
+ S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
+ S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
+ }
+ S += "};\n";
+ return S;
+}
+
+void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
+ llvm::StringRef FunName) {
+ // Insert declaration for the function in which block literal is used.
+ if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
+ RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+ bool RewriteSC = (GlobalVarDecl &&
+ !Blocks.empty() &&
+ GlobalVarDecl->getStorageClass() == SC_Static &&
+ GlobalVarDecl->getType().getCVRQualifiers());
+ if (RewriteSC) {
+ std::string SC(" void __");
+ SC += GlobalVarDecl->getNameAsString();
+ SC += "() {}";
+ InsertText(FunLocStart, SC);
+ }
+
+ // Insert closures that were part of the function.
+ for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
+ CollectBlockDeclRefInfo(Blocks[i]);
+ // Need to copy-in the inner copied-in variables not actually used in this
+ // block.
+ for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
+ BlockDeclRefExpr *Exp = InnerDeclRefs[count++];
+ ValueDecl *VD = Exp->getDecl();
+ BlockDeclRefs.push_back(Exp);
+ if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
+ BlockByCopyDeclsPtrSet.insert(VD);
+ BlockByCopyDecls.push_back(VD);
+ }
+ if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
+ BlockByRefDeclsPtrSet.insert(VD);
+ BlockByRefDecls.push_back(VD);
+ }
+ // imported objects in the inner blocks not used in the outer
+ // blocks must be copied/disposed in the outer block as well.
+ if (Exp->isByRef() ||
+ VD->getType()->isObjCObjectPointerType() ||
+ VD->getType()->isBlockPointerType())
+ ImportedBlockDecls.insert(VD);
+ }
+
+ std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
+ std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
+
+ std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
+
+ InsertText(FunLocStart, CI);
+
+ std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
+
+ InsertText(FunLocStart, CF);
+
+ if (ImportedBlockDecls.size()) {
+ std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
+ InsertText(FunLocStart, HF);
+ }
+ std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
+ ImportedBlockDecls.size() > 0);
+ InsertText(FunLocStart, BD);
+
+ BlockDeclRefs.clear();
+ BlockByRefDecls.clear();
+ BlockByRefDeclsPtrSet.clear();
+ BlockByCopyDecls.clear();
+ BlockByCopyDeclsPtrSet.clear();
+ ImportedBlockDecls.clear();
+ }
+ if (RewriteSC) {
+ // Must insert any 'const/volatile/static here. Since it has been
+ // removed as result of rewriting of block literals.
+ std::string SC;
+ if (GlobalVarDecl->getStorageClass() == SC_Static)
+ SC = "static ";
+ if (GlobalVarDecl->getType().isConstQualified())
+ SC += "const ";
+ if (GlobalVarDecl->getType().isVolatileQualified())
+ SC += "volatile ";
+ if (GlobalVarDecl->getType().isRestrictQualified())
+ SC += "restrict ";
+ InsertText(FunLocStart, SC);
+ }
+
+ Blocks.clear();
+ InnerDeclRefsCount.clear();
+ InnerDeclRefs.clear();
+ RewrittenBlockExprs.clear();
+}
+
+void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
+ SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+ llvm::StringRef FuncName = FD->getName();
+
+ SynthesizeBlockLiterals(FunLocStart, FuncName);
+}
+
+static void BuildUniqueMethodName(std::string &Name,
+ ObjCMethodDecl *MD) {
+ ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ Name = IFace->getName();
+ Name += "__" + MD->getSelector().getAsString();
+ // Convert colons to underscores.
+ std::string::size_type loc = 0;
+ while ((loc = Name.find(":", loc)) != std::string::npos)
+ Name.replace(loc, 1, "_");
+}
+
+void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
+ //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
+ //SourceLocation FunLocStart = MD->getLocStart();
+ SourceLocation FunLocStart = MD->getLocStart();
+ std::string FuncName;
+ BuildUniqueMethodName(FuncName, MD);
+ SynthesizeBlockLiterals(FunLocStart, FuncName);
+}
+
+void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+ GetBlockDeclRefExprs(CBE->getBody());
+ else
+ GetBlockDeclRefExprs(*CI);
+ }
+ // Handle specific things.
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+ // FIXME: Handle enums.
+ if (!isa<FunctionDecl>(CDRE->getDecl()))
+ BlockDeclRefs.push_back(CDRE);
+ }
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
+ if (HasLocalVariableExternalStorage(DRE->getDecl())) {
+ BlockDeclRefExpr *BDRE =
+ new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()),
+ DRE->getType(),
+ VK_LValue, DRE->getLocation(), false);
+ BlockDeclRefs.push_back(BDRE);
+ }
+
+ return;
+}
+
+void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
+ llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
+ llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI) {
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+ InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
+ GetInnerBlockDeclRefExprs(CBE->getBody(),
+ InnerBlockDeclRefs,
+ InnerContexts);
+ }
+ else
+ GetInnerBlockDeclRefExprs(*CI,
+ InnerBlockDeclRefs,
+ InnerContexts);
+
+ }
+ // Handle specific things.
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+ if (!isa<FunctionDecl>(CDRE->getDecl()) &&
+ !InnerContexts.count(CDRE->getDecl()->getDeclContext()))
+ InnerBlockDeclRefs.push_back(CDRE);
+ }
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (Var->isFunctionOrMethodVarDecl())
+ ImportedLocalExternalDecls.insert(Var);
+ }
+
+ return;
+}
+
+/// convertFunctionTypeOfBlocks - This routine converts a function type
+/// whose result type may be a block pointer or whose argument type(s)
+/// might be block pointers to an equivalent funtion type replacing
+/// all block pointers to function pointers.
+QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
+ const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
+ // FTP will be null for closures that don't take arguments.
+ // Generate a funky cast.
+ llvm::SmallVector<QualType, 8> ArgTypes;
+ QualType Res = FT->getResultType();
+ bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
+
+ if (FTP) {
+ for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+ E = FTP->arg_type_end(); I && (I != E); ++I) {
+ QualType t = *I;
+ // Make sure we convert "t (^)(...)" to "t (*)(...)".
+ if (convertBlockPointerToFunctionPointer(t))
+ HasBlockType = true;
+ ArgTypes.push_back(t);
+ }
+ }
+ QualType FuncType;
+ // FIXME. Does this work if block takes no argument but has a return type
+ // which is of block type?
+ if (HasBlockType)
+ FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size());
+ else FuncType = QualType(FT, 0);
+ return FuncType;
+}
+
+Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
+ // Navigate to relevant type information.
+ const BlockPointerType *CPT = 0;
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
+ CPT = DRE->getType()->getAs<BlockPointerType>();
+ } else if (const BlockDeclRefExpr *CDRE =
+ dyn_cast<BlockDeclRefExpr>(BlockExp)) {
+ CPT = CDRE->getType()->getAs<BlockPointerType>();
+ } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
+ CPT = MExpr->getType()->getAs<BlockPointerType>();
+ }
+ else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
+ return SynthesizeBlockCall(Exp, PRE->getSubExpr());
+ }
+ else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
+ CPT = IEXPR->getType()->getAs<BlockPointerType>();
+ else if (const ConditionalOperator *CEXPR =
+ dyn_cast<ConditionalOperator>(BlockExp)) {
+ Expr *LHSExp = CEXPR->getLHS();
+ Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
+ Expr *RHSExp = CEXPR->getRHS();
+ Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
+ Expr *CONDExp = CEXPR->getCond();
+ ConditionalOperator *CondExpr =
+ new (Context) ConditionalOperator(CONDExp,
+ SourceLocation(), cast<Expr>(LHSStmt),
+ SourceLocation(), cast<Expr>(RHSStmt),
+ Exp->getType(), VK_RValue, OK_Ordinary);
+ return CondExpr;
+ } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
+ CPT = IRE->getType()->getAs<BlockPointerType>();
+ } else {
+ assert(1 && "RewriteBlockClass: Bad type");
+ }
+ assert(CPT && "RewriteBlockClass: Bad type");
+ const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
+ assert(FT && "RewriteBlockClass: Bad type");
+ const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
+ // FTP will be null for closures that don't take arguments.
+
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(),
+ &Context->Idents.get("__block_impl"));
+ QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
+
+ // Generate a funky cast.
+ llvm::SmallVector<QualType, 8> ArgTypes;
+
+ // Push the block argument type.
+ ArgTypes.push_back(PtrBlock);
+ if (FTP) {
+ for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+ E = FTP->arg_type_end(); I && (I != E); ++I) {
+ QualType t = *I;
+ // Make sure we convert "t (^)(...)" to "t (*)(...)".
+ if (!convertBlockPointerToFunctionPointer(t))
+ convertToUnqualifiedObjCType(t);
+ ArgTypes.push_back(t);
+ }
+ }
+ // Now do the pointer to function cast.
+ QualType PtrToFuncCastType
+ = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size());
+
+ PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
+
+ CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
+ CK_BitCast,
+ const_cast<Expr*>(BlockExp));
+ // Don't forget the parens to enforce the proper binding.
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ BlkCast);
+ //PE->dump();
+
+ FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, 0,
+ /*BitWidth=*/0, /*Mutable=*/true);
+ MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
+ FD->getType(), VK_LValue,
+ OK_Ordinary);
+
+
+ CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
+ CK_BitCast, ME);
+ PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+
+ llvm::SmallVector<Expr*, 8> BlkExprs;
+ // Add the implicit argument.
+ BlkExprs.push_back(BlkCast);
+ // Add the user arguments.
+ for (CallExpr::arg_iterator I = Exp->arg_begin(),
+ E = Exp->arg_end(); I != E; ++I) {
+ BlkExprs.push_back(*I);
+ }
+ CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
+ BlkExprs.size(),
+ Exp->getType(), VK_RValue,
+ SourceLocation());
+ return CE;
+}
+
+// We need to return the rewritten expression to handle cases where the
+// BlockDeclRefExpr is embedded in another expression being rewritten.
+// For example:
+//
+// int main() {
+// __block Foo *f;
+// __block int i;
+//
+// void (^myblock)() = ^() {
+// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
+// i = 77;
+// };
+//}
+Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
+ // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
+ // for each DeclRefExp where BYREFVAR is name of the variable.
+ ValueDecl *VD;
+ bool isArrow = true;
+ if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp))
+ VD = BDRE->getDecl();
+ else {
+ VD = cast<DeclRefExpr>(DeclRefExp)->getDecl();
+ isArrow = false;
+ }
+
+ FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ &Context->Idents.get("__forwarding"),
+ Context->VoidPtrTy, 0,
+ /*BitWidth=*/0, /*Mutable=*/true);
+ MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
+ FD, SourceLocation(),
+ FD->getType(), VK_LValue,
+ OK_Ordinary);
+
+ llvm::StringRef Name = VD->getName();
+ FD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ &Context->Idents.get(Name),
+ Context->VoidPtrTy, 0,
+ /*BitWidth=*/0, /*Mutable=*/true);
+ ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
+ DeclRefExp->getType(), VK_LValue, OK_Ordinary);
+
+
+
+ // Need parens to enforce precedence.
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ ME);
+ ReplaceStmt(DeclRefExp, PE);
+ return PE;
+}
+
+// Rewrites the imported local variable V with external storage
+// (static, extern, etc.) as *V
+//
+Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
+ ValueDecl *VD = DRE->getDecl();
+ if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+ if (!ImportedLocalExternalDecls.count(Var))
+ return DRE;
+ Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
+ VK_LValue, OK_Ordinary,
+ DRE->getLocation());
+ // Need parens to enforce precedence.
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ Exp);
+ ReplaceStmt(DRE, PE);
+ return PE;
+}
+
+void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
+ SourceLocation LocStart = CE->getLParenLoc();
+ SourceLocation LocEnd = CE->getRParenLoc();
+
+ // Need to avoid trying to rewrite synthesized casts.
+ if (LocStart.isInvalid())
+ return;
+ // Need to avoid trying to rewrite casts contained in macros.
+ if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
+ return;
+
+ const char *startBuf = SM->getCharacterData(LocStart);
+ const char *endBuf = SM->getCharacterData(LocEnd);
+ QualType QT = CE->getType();
+ const Type* TypePtr = QT->getAs<Type>();
+ if (isa<TypeOfExprType>(TypePtr)) {
+ const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
+ QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
+ std::string TypeAsString = "(";
+ RewriteBlockPointerType(TypeAsString, QT);
+ TypeAsString += ")";
+ ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
+ return;
+ }
+ // advance the location to startArgList.
+ const char *argPtr = startBuf;
+
+ while (*argPtr++ && (argPtr < endBuf)) {
+ switch (*argPtr) {
+ case '^':
+ // Replace the '^' with '*'.
+ LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
+ ReplaceText(LocStart, 1, "*");
+ break;
+ }
+ }
+ return;
+}
+
+void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
+ SourceLocation DeclLoc = FD->getLocation();
+ unsigned parenCount = 0;
+
+ // We have 1 or more arguments that have closure pointers.
+ const char *startBuf = SM->getCharacterData(DeclLoc);
+ const char *startArgList = strchr(startBuf, '(');
+
+ assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
+
+ parenCount++;
+ // advance the location to startArgList.
+ DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf);
+ assert((DeclLoc.isValid()) && "Invalid DeclLoc");
+
+ const char *argPtr = startArgList;
+
+ while (*argPtr++ && parenCount) {
+ switch (*argPtr) {
+ case '^':
+ // Replace the '^' with '*'.
+ DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
+ ReplaceText(DeclLoc, 1, "*");
+ break;
+ case '(':
+ parenCount++;
+ break;
+ case ')':
+ parenCount--;
+ break;
+ }
+ }
+ return;
+}
+
+bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
+ const FunctionProtoType *FTP;
+ const PointerType *PT = QT->getAs<PointerType>();
+ if (PT) {
+ FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
+ } else {
+ const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
+ assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+ FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
+ }
+ if (FTP) {
+ for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+ E = FTP->arg_type_end(); I != E; ++I)
+ if (isTopLevelBlockPointerType(*I))
+ return true;
+ }
+ return false;
+}
+
+bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
+ const FunctionProtoType *FTP;
+ const PointerType *PT = QT->getAs<PointerType>();
+ if (PT) {
+ FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
+ } else {
+ const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
+ assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+ FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
+ }
+ if (FTP) {
+ for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
+ E = FTP->arg_type_end(); I != E; ++I) {
+ if ((*I)->isObjCQualifiedIdType())
+ return true;
+ if ((*I)->isObjCObjectPointerType() &&
+ (*I)->getPointeeType()->isObjCQualifiedInterfaceType())
+ return true;
+ }
+
+ }
+ return false;
+}
+
+void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
+ const char *&RParen) {
+ const char *argPtr = strchr(Name, '(');
+ assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
+
+ LParen = argPtr; // output the start.
+ argPtr++; // skip past the left paren.
+ unsigned parenCount = 1;
+
+ while (*argPtr && parenCount) {
+ switch (*argPtr) {
+ case '(': parenCount++; break;
+ case ')': parenCount--; break;
+ default: break;
+ }
+ if (parenCount) argPtr++;
+ }
+ assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
+ RParen = argPtr; // output the end
+}
+
+void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ RewriteBlockPointerFunctionArgs(FD);
+ return;
+ }
+ // Handle Variables and Typedefs.
+ SourceLocation DeclLoc = ND->getLocation();
+ QualType DeclT;
+ if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+ DeclT = VD->getType();
+ else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
+ DeclT = TDD->getUnderlyingType();
+ else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
+ DeclT = FD->getType();
+ else
+ assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
+
+ const char *startBuf = SM->getCharacterData(DeclLoc);
+ const char *endBuf = startBuf;
+ // scan backward (from the decl location) for the end of the previous decl.
+ while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
+ startBuf--;
+ SourceLocation Start = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
+ std::string buf;
+ unsigned OrigLength=0;
+ // *startBuf != '^' if we are dealing with a pointer to function that
+ // may take block argument types (which will be handled below).
+ if (*startBuf == '^') {
+ // Replace the '^' with '*', computing a negative offset.
+ buf = '*';
+ startBuf++;
+ OrigLength++;
+ }
+ while (*startBuf != ')') {
+ buf += *startBuf;
+ startBuf++;
+ OrigLength++;
+ }
+ buf += ')';
+ OrigLength++;
+
+ if (PointerTypeTakesAnyBlockArguments(DeclT) ||
+ PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
+ // Replace the '^' with '*' for arguments.
+ // Replace id<P> with id/*<>*/
+ DeclLoc = ND->getLocation();
+ startBuf = SM->getCharacterData(DeclLoc);
+ const char *argListBegin, *argListEnd;
+ GetExtentOfArgList(startBuf, argListBegin, argListEnd);
+ while (argListBegin < argListEnd) {
+ if (*argListBegin == '^')
+ buf += '*';
+ else if (*argListBegin == '<') {
+ buf += "/*";
+ buf += *argListBegin++;
+ OrigLength++;;
+ while (*argListBegin != '>') {
+ buf += *argListBegin++;
+ OrigLength++;
+ }
+ buf += *argListBegin;
+ buf += "*/";
+ }
+ else
+ buf += *argListBegin;
+ argListBegin++;
+ OrigLength++;
+ }
+ buf += ')';
+ OrigLength++;
+ }
+ ReplaceText(Start, OrigLength, buf);
+
+ return;
+}
+
+
+/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
+/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
+/// struct Block_byref_id_object *src) {
+/// _Block_object_assign (&_dest->object, _src->object,
+/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+/// [|BLOCK_FIELD_IS_WEAK]) // object
+/// _Block_object_assign(&_dest->object, _src->object,
+/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+/// [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+/// And:
+/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
+/// _Block_object_dispose(_src->object,
+/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
+/// [|BLOCK_FIELD_IS_WEAK]) // object
+/// _Block_object_dispose(_src->object,
+/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
+/// [|BLOCK_FIELD_IS_WEAK]) // block
+/// }
+
+std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
+ int flag) {
+ std::string S;
+ if (CopyDestroyCache.count(flag))
+ return S;
+ CopyDestroyCache.insert(flag);
+ S = "static void __Block_byref_id_object_copy_";
+ S += utostr(flag);
+ S += "(void *dst, void *src) {\n";
+
+ // offset into the object pointer is computed as:
+ // void * + void* + int + int + void* + void *
+ unsigned IntSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+ unsigned VoidPtrSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
+
+ unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/8;
+ S += " _Block_object_assign((char*)dst + ";
+ S += utostr(offset);
+ S += ", *(void * *) ((char*)src + ";
+ S += utostr(offset);
+ S += "), ";
+ S += utostr(flag);
+ S += ");\n}\n";
+
+ S += "static void __Block_byref_id_object_dispose_";
+ S += utostr(flag);
+ S += "(void *src) {\n";
+ S += " _Block_object_dispose(*(void * *) ((char*)src + ";
+ S += utostr(offset);
+ S += "), ";
+ S += utostr(flag);
+ S += ");\n}\n";
+ return S;
+}
+
+/// RewriteByRefVar - For each __block typex ND variable this routine transforms
+/// the declaration into:
+/// struct __Block_byref_ND {
+/// void *__isa; // NULL for everything except __weak pointers
+/// struct __Block_byref_ND *__forwarding;
+/// int32_t __flags;
+/// int32_t __size;
+/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
+/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
+/// typex ND;
+/// };
+///
+/// It then replaces declaration of ND variable with:
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
+/// __size=sizeof(struct __Block_byref_ND),
+/// ND=initializer-if-any};
+///
+///
+void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
+ // Insert declaration for the function in which block literal is
+ // used.
+ if (CurFunctionDeclToDeclareForBlock)
+ RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
+ int flag = 0;
+ int isa = 0;
+ SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
+ if (DeclLoc.isInvalid())
+ // If type location is missing, it is because of missing type (a warning).
+ // Use variable's location which is good for this case.
+ DeclLoc = ND->getLocation();
+ const char *startBuf = SM->getCharacterData(DeclLoc);
+ SourceLocation X = ND->getLocEnd();
+ X = SM->getInstantiationLoc(X);
+ const char *endBuf = SM->getCharacterData(X);
+ std::string Name(ND->getNameAsString());
+ std::string ByrefType;
+ RewriteByRefString(ByrefType, Name, ND, true);
+ ByrefType += " {\n";
+ ByrefType += " void *__isa;\n";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += " *__forwarding;\n";
+ ByrefType += " int __flags;\n";
+ ByrefType += " int __size;\n";
+ // Add void *__Block_byref_id_object_copy;
+ // void *__Block_byref_id_object_dispose; if needed.
+ QualType Ty = ND->getType();
+ bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
+ if (HasCopyAndDispose) {
+ ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
+ ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
+ }
+
+ Ty.getAsStringInternal(Name, Context->PrintingPolicy);
+ ByrefType += " " + Name + ";\n";
+ ByrefType += "};\n";
+ // Insert this type in global scope. It is needed by helper function.
+ SourceLocation FunLocStart;
+ if (CurFunctionDef)
+ FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+ else {
+ assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
+ FunLocStart = CurMethodDef->getLocStart();
+ }
+ InsertText(FunLocStart, ByrefType);
+ if (Ty.isObjCGCWeak()) {
+ flag |= BLOCK_FIELD_IS_WEAK;
+ isa = 1;
+ }
+
+ if (HasCopyAndDispose) {
+ flag = BLOCK_BYREF_CALLER;
+ QualType Ty = ND->getType();
+ // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
+ if (Ty->isBlockPointerType())
+ flag |= BLOCK_FIELD_IS_BLOCK;
+ else
+ flag |= BLOCK_FIELD_IS_OBJECT;
+ std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
+ if (!HF.empty())
+ InsertText(FunLocStart, HF);
+ }
+
+ // struct __Block_byref_ND ND =
+ // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
+ // initializer-if-any};
+ bool hasInit = (ND->getInit() != 0);
+ unsigned flags = 0;
+ if (HasCopyAndDispose)
+ flags |= BLOCK_HAS_COPY_DISPOSE;
+ Name = ND->getNameAsString();
+ ByrefType.clear();
+ RewriteByRefString(ByrefType, Name, ND);
+ std::string ForwardingCastType("(");
+ ForwardingCastType += ByrefType + " *)";
+ if (!hasInit) {
+ ByrefType += " " + Name + " = {(void*)";
+ ByrefType += utostr(isa);
+ ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
+ ByrefType += utostr(flags);
+ ByrefType += ", ";
+ ByrefType += "sizeof(";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += ")";
+ if (HasCopyAndDispose) {
+ ByrefType += ", __Block_byref_id_object_copy_";
+ ByrefType += utostr(flag);
+ ByrefType += ", __Block_byref_id_object_dispose_";
+ ByrefType += utostr(flag);
+ }
+ ByrefType += "};\n";
+ ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType);
+ }
+ else {
+ SourceLocation startLoc;
+ Expr *E = ND->getInit();
+ if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
+ startLoc = ECE->getLParenLoc();
+ else
+ startLoc = E->getLocStart();
+ startLoc = SM->getInstantiationLoc(startLoc);
+ endBuf = SM->getCharacterData(startLoc);
+ ByrefType += " " + Name;
+ ByrefType += " = {(void*)";
+ ByrefType += utostr(isa);
+ ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
+ ByrefType += utostr(flags);
+ ByrefType += ", ";
+ ByrefType += "sizeof(";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += "), ";
+ if (HasCopyAndDispose) {
+ ByrefType += "__Block_byref_id_object_copy_";
+ ByrefType += utostr(flag);
+ ByrefType += ", __Block_byref_id_object_dispose_";
+ ByrefType += utostr(flag);
+ ByrefType += ", ";
+ }
+ ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
+
+ // Complete the newly synthesized compound expression by inserting a right
+ // curly brace before the end of the declaration.
+ // FIXME: This approach avoids rewriting the initializer expression. It
+ // also assumes there is only one declarator. For example, the following
+ // isn't currently supported by this routine (in general):
+ //
+ // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
+ //
+ const char *startInitializerBuf = SM->getCharacterData(startLoc);
+ const char *semiBuf = strchr(startInitializerBuf, ';');
+ assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
+ SourceLocation semiLoc =
+ startLoc.getFileLocWithOffset(semiBuf-startInitializerBuf);
+
+ InsertText(semiLoc, "}");
+ }
+ return;
+}
+
+void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
+ // Add initializers for any closure decl refs.
+ GetBlockDeclRefExprs(Exp->getBody());
+ if (BlockDeclRefs.size()) {
+ // Unique all "by copy" declarations.
+ for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+ if (!BlockDeclRefs[i]->isByRef()) {
+ if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
+ BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
+ BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
+ }
+ }
+ // Unique all "by ref" declarations.
+ for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+ if (BlockDeclRefs[i]->isByRef()) {
+ if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
+ BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
+ BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
+ }
+ }
+ // Find any imported blocks...they will need special attention.
+ for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
+ if (BlockDeclRefs[i]->isByRef() ||
+ BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ BlockDeclRefs[i]->getType()->isBlockPointerType())
+ ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
+ }
+}
+
+FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(llvm::StringRef name) {
+ IdentifierInfo *ID = &Context->Idents.get(name);
+ QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
+ return FunctionDecl::Create(*Context, TUDecl,SourceLocation(),
+ ID, FType, 0, SC_Extern,
+ SC_None, false, false);
+}
+
+Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
+ const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) {
+ const BlockDecl *block = Exp->getBlockDecl();
+ Blocks.push_back(Exp);
+
+ CollectBlockDeclRefInfo(Exp);
+
+ // Add inner imported variables now used in current block.
+ int countOfInnerDecls = 0;
+ if (!InnerBlockDeclRefs.empty()) {
+ for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
+ BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i];
+ ValueDecl *VD = Exp->getDecl();
+ if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
+ // We need to save the copied-in variables in nested
+ // blocks because it is needed at the end for some of the API generations.
+ // See SynthesizeBlockLiterals routine.
+ InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
+ BlockDeclRefs.push_back(Exp);
+ BlockByCopyDeclsPtrSet.insert(VD);
+ BlockByCopyDecls.push_back(VD);
+ }
+ if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
+ InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
+ BlockDeclRefs.push_back(Exp);
+ BlockByRefDeclsPtrSet.insert(VD);
+ BlockByRefDecls.push_back(VD);
+ }
+ }
+ // Find any imported blocks...they will need special attention.
+ for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
+ if (InnerBlockDeclRefs[i]->isByRef() ||
+ InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
+ InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
+ ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
+ }
+ InnerDeclRefsCount.push_back(countOfInnerDecls);
+
+ std::string FuncName;
+
+ if (CurFunctionDef)
+ FuncName = CurFunctionDef->getNameAsString();
+ else if (CurMethodDef)
+ BuildUniqueMethodName(FuncName, CurMethodDef);
+ else if (GlobalVarDecl)
+ FuncName = std::string(GlobalVarDecl->getNameAsString());
+
+ std::string BlockNumber = utostr(Blocks.size()-1);
+
+ std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
+ std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
+
+ // Get a pointer to the function type so we can cast appropriately.
+ QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
+ QualType FType = Context->getPointerType(BFT);
+
+ FunctionDecl *FD;
+ Expr *NewRep;
+
+ // Simulate a contructor call...
+ FD = SynthBlockInitFunctionDecl(Tag);
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue,
+ SourceLocation());
+
+ llvm::SmallVector<Expr*, 4> InitExprs;
+
+ // Initialize the block function.
+ FD = SynthBlockInitFunctionDecl(Func);
+ DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+ SourceLocation());
+ CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+ CK_BitCast, Arg);
+ InitExprs.push_back(castExpr);
+
+ // Initialize the block descriptor.
+ std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
+
+ VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+ &Context->Idents.get(DescData.c_str()),
+ Context->VoidPtrTy, 0,
+ SC_Static, SC_None);
+ UnaryOperator *DescRefExpr =
+ new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD,
+ Context->VoidPtrTy,
+ VK_LValue,
+ SourceLocation()),
+ UO_AddrOf,
+ Context->getPointerType(Context->VoidPtrTy),
+ VK_RValue, OK_Ordinary,
+ SourceLocation());
+ InitExprs.push_back(DescRefExpr);
+
+ // Add initializers for any closure decl refs.
+ if (BlockDeclRefs.size()) {
+ Expr *Exp;
+ // Output all "by copy" declarations.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
+ E = BlockByCopyDecls.end(); I != E; ++I) {
+ if (isObjCType((*I)->getType())) {
+ // FIXME: Conform to ABI ([[obj retain] autorelease]).
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
+ Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+ SourceLocation());
+ if (HasLocalVariableExternalStorage(*I)) {
+ QualType QT = (*I)->getType();
+ QT = Context->getPointerType(QT);
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+ OK_Ordinary, SourceLocation());
+ }
+ } else if (isTopLevelBlockPointerType((*I)->getType())) {
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
+ Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+ SourceLocation());
+ Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
+ CK_BitCast, Arg);
+ } else {
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
+ Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+ SourceLocation());
+ if (HasLocalVariableExternalStorage(*I)) {
+ QualType QT = (*I)->getType();
+ QT = Context->getPointerType(QT);
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
+ OK_Ordinary, SourceLocation());
+ }
+
+ }
+ InitExprs.push_back(Exp);
+ }
+ // Output all "by ref" declarations.
+ for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
+ E = BlockByRefDecls.end(); I != E; ++I) {
+ ValueDecl *ND = (*I);
+ std::string Name(ND->getNameAsString());
+ std::string RecName;
+ RewriteByRefString(RecName, Name, ND, true);
+ IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
+ + sizeof("struct"));
+ RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
+ SourceLocation(), II);
+ assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
+ QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
+
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
+ Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
+ SourceLocation());
+ bool isNestedCapturedVar = false;
+ if (block)
+ for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
+ ce = block->capture_end(); ci != ce; ++ci) {
+ const VarDecl *variable = ci->getVariable();
+ if (variable == ND && ci->isNested()) {
+ assert (ci->isByRef() &&
+ "SynthBlockInitExpr - captured block variable is not byref");
+ isNestedCapturedVar = true;
+ break;
+ }
+ }
+ // captured nested byref variable has its address passed. Do not take
+ // its address again.
+ if (!isNestedCapturedVar)
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
+ Context->getPointerType(Exp->getType()),
+ VK_RValue, OK_Ordinary, SourceLocation());
+ Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
+ InitExprs.push_back(Exp);
+ }
+ }
+ if (ImportedBlockDecls.size()) {
+ // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
+ int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
+ unsigned IntSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+ Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
+ Context->IntTy, SourceLocation());
+ InitExprs.push_back(FlagExp);
+ }
+ NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
+ FType, VK_LValue, SourceLocation());
+ NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
+ Context->getPointerType(NewRep->getType()),
+ VK_RValue, OK_Ordinary, SourceLocation());
+ NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
+ NewRep);
+ BlockDeclRefs.clear();
+ BlockByRefDecls.clear();
+ BlockByRefDeclsPtrSet.clear();
+ BlockByCopyDecls.clear();
+ BlockByCopyDeclsPtrSet.clear();
+ ImportedBlockDecls.clear();
+ return NewRep;
+}
+
+//===----------------------------------------------------------------------===//
+// Function Body / Expression rewriting
+//===----------------------------------------------------------------------===//
+
+// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer().
+// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with
+// their respective BinaryOperator. Without this knowledge, we'd need to rewrite
+// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter).
+// Since the rewriter isn't capable of rewriting rewritten code, it's important
+// we get this right.
+void RewriteObjC::CollectPropertySetters(Stmt *S) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI)
+ CollectPropertySetters(*CI);
+
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+ if (BinOp->isAssignmentOp()) {
+ if (isa<ObjCPropertyRefExpr>(BinOp->getLHS()))
+ PropSetters[BinOp->getLHS()] = BinOp;
+ }
+ }
+}
+
+Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
+ if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+ isa<DoStmt>(S) || isa<ForStmt>(S))
+ Stmts.push_back(S);
+ else if (isa<ObjCForCollectionStmt>(S)) {
+ Stmts.push_back(S);
+ ObjCBcLabelNo.push_back(++BcLabelCount);
+ }
+
+ SourceRange OrigStmtRange = S->getSourceRange();
+
+ // Perform a bottom up rewrite of all children.
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
+ if (*CI) {
+ Stmt *newStmt;
+ Stmt *S = (*CI);
+ if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
+ Expr *OldBase = IvarRefExpr->getBase();
+ bool replaced = false;
+ newStmt = RewriteObjCNestedIvarRefExpr(S, replaced);
+ if (replaced) {
+ if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt))
+ ReplaceStmt(OldBase, IRE->getBase());
+ else
+ ReplaceStmt(S, newStmt);
+ }
+ }
+ else
+ newStmt = RewriteFunctionBodyOrGlobalInitializer(S);
+ if (newStmt)
+ *CI = newStmt;
+ // If dealing with an assignment with LHS being a property reference
+ // expression, the entire assignment tree is rewritten into a property
+ // setter messaging. This involvs the RHS too. Do not attempt to rewrite
+ // RHS again.
+ if (Expr *Exp = dyn_cast<Expr>(S))
+ if (isa<ObjCPropertyRefExpr>(Exp)) {
+ if (PropSetters[Exp]) {
+ ++CI;
+ continue;
+ }
+ }
+ }
+
+ if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+ llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
+ llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
+ InnerContexts.insert(BE->getBlockDecl());
+ ImportedLocalExternalDecls.clear();
+ GetInnerBlockDeclRefExprs(BE->getBody(),
+ InnerBlockDeclRefs, InnerContexts);
+ // Rewrite the block body in place.
+ Stmt *SaveCurrentBody = CurrentBody;
+ CurrentBody = BE->getBody();
+ PropParentMap = 0;
+ RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
+ CurrentBody = SaveCurrentBody;
+ PropParentMap = 0;
+ ImportedLocalExternalDecls.clear();
+ // Now we snarf the rewritten text and stash it away for later use.
+ std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
+ RewrittenBlockExprs[BE] = Str;
+
+ Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
+
+ //blockTranscribed->dump();
+ ReplaceStmt(S, blockTranscribed);
+ return blockTranscribed;
+ }
+ // Handle specific things.
+ if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
+ return RewriteAtEncode(AtEncode);
+
+ if (isa<ObjCPropertyRefExpr>(S)) {
+ Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S);
+ assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null");
+
+ BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr];
+ if (BinOp) {
+ // Because the rewriter doesn't allow us to rewrite rewritten code,
+ // we need to rewrite the right hand side prior to rewriting the setter.
+ DisableReplaceStmt = true;
+ // Save the source range. Even if we disable the replacement, the
+ // rewritten node will have been inserted into the tree. If the synthesized
+ // node is at the 'end', the rewriter will fail. Consider this:
+ // self.errorHandler = handler ? handler :
+ // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };
+ SourceRange SrcRange = BinOp->getSourceRange();
+ Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
+ // Need to rewrite the ivar access expression if need be.
+ if (isa<ObjCIvarRefExpr>(newStmt)) {
+ bool replaced = false;
+ newStmt = RewriteObjCNestedIvarRefExpr(newStmt, replaced);
+ }
+
+ DisableReplaceStmt = false;
+ //
+ // Unlike the main iterator, we explicily avoid changing 'BinOp'. If
+ // we changed the RHS of BinOp, the rewriter would fail (since it needs
+ // to see the original expression). Consider this example:
+ //
+ // Foo *obj1, *obj2;
+ //
+ // obj1.i = [obj2 rrrr];
+ //
+ // 'BinOp' for the previous expression looks like:
+ //
+ // (BinaryOperator 0x231ccf0 'int' '='
+ // (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i"
+ // (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0))
+ // (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr
+ // (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0)))
+ //
+ // 'newStmt' represents the rewritten message expression. For example:
+ //
+ // (CallExpr 0x231d300 'id':'struct objc_object *'
+ // (ParenExpr 0x231d2e0 'int (*)(id, SEL)'
+ // (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)'
+ // (CStyleCastExpr 0x231d220 'void *'
+ // (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0))))
+ //
+ // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter so that it
+ // can be used as the setter argument. ReplaceStmt() will still 'see'
+ // the original RHS (since we haven't altered BinOp).
+ //
+ // This implies the Rewrite* routines can no longer delete the original
+ // node. As a result, we now leak the original AST nodes.
+ //
+ return RewritePropertyOrImplicitSetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
+ } else {
+ return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr);
+ }
+ }
+
+ if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
+ return RewriteAtSelector(AtSelector);
+
+ if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
+ return RewriteObjCStringLiteral(AtString);
+
+ if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
+#if 0
+ // Before we rewrite it, put the original message expression in a comment.
+ SourceLocation startLoc = MessExpr->getLocStart();
+ SourceLocation endLoc = MessExpr->getLocEnd();
+
+ const char *startBuf = SM->getCharacterData(startLoc);
+ const char *endBuf = SM->getCharacterData(endLoc);
+
+ std::string messString;
+ messString += "// ";
+ messString.append(startBuf, endBuf-startBuf+1);
+ messString += "\n";
+
+ // FIXME: Missing definition of
+ // InsertText(clang::SourceLocation, char const*, unsigned int).
+ // InsertText(startLoc, messString.c_str(), messString.size());
+ // Tried this, but it didn't work either...
+ // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
+#endif
+ return RewriteMessageExpr(MessExpr);
+ }
+
+ if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
+ return RewriteObjCTryStmt(StmtTry);
+
+ if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
+ return RewriteObjCSynchronizedStmt(StmtTry);
+
+ if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
+ return RewriteObjCThrowStmt(StmtThrow);
+
+ if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
+ return RewriteObjCProtocolExpr(ProtocolExp);
+
+ if (ObjCForCollectionStmt *StmtForCollection =
+ dyn_cast<ObjCForCollectionStmt>(S))
+ return RewriteObjCForCollectionStmt(StmtForCollection,
+ OrigStmtRange.getEnd());
+ if (BreakStmt *StmtBreakStmt =
+ dyn_cast<BreakStmt>(S))
+ return RewriteBreakStmt(StmtBreakStmt);
+ if (ContinueStmt *StmtContinueStmt =
+ dyn_cast<ContinueStmt>(S))
+ return RewriteContinueStmt(StmtContinueStmt);
+
+ // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
+ // and cast exprs.
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+ // FIXME: What we're doing here is modifying the type-specifier that
+ // precedes the first Decl. In the future the DeclGroup should have
+ // a separate type-specifier that we can rewrite.
+ // NOTE: We need to avoid rewriting the DeclStmt if it is within
+ // the context of an ObjCForCollectionStmt. For example:
+ // NSArray *someArray;
+ // for (id <FooProtocol> index in someArray) ;
+ // This is because RewriteObjCForCollectionStmt() does textual rewriting
+ // and it depends on the original text locations/positions.
+ if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
+
+ // Blocks rewrite rules.
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI) {
+ Decl *SD = *DI;
+ if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
+ if (isTopLevelBlockPointerType(ND->getType()))
+ RewriteBlockPointerDecl(ND);
+ else if (ND->getType()->isFunctionPointerType())
+ CheckFunctionPointerDecl(ND->getType(), ND);
+ if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
+ if (VD->hasAttr<BlocksAttr>()) {
+ static unsigned uniqueByrefDeclCount = 0;
+ assert(!BlockByRefDeclNo.count(ND) &&
+ "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
+ BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
+ RewriteByRefVar(VD);
+ }
+ else
+ RewriteTypeOfDecl(VD);
+ }
+ }
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+ if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+ RewriteBlockPointerDecl(TD);
+ else if (TD->getUnderlyingType()->isFunctionPointerType())
+ CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+ }
+ }
+ }
+
+ if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
+ RewriteObjCQualifiedInterfaceTypes(CE);
+
+ if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
+ isa<DoStmt>(S) || isa<ForStmt>(S)) {
+ assert(!Stmts.empty() && "Statement stack is empty");
+ assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
+ isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
+ && "Statement stack mismatch");
+ Stmts.pop_back();
+ }
+ // Handle blocks rewriting.
+ if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
+ if (BDRE->isByRef())
+ return RewriteBlockDeclRefExpr(BDRE);
+ }
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+ ValueDecl *VD = DRE->getDecl();
+ if (VD->hasAttr<BlocksAttr>())
+ return RewriteBlockDeclRefExpr(DRE);
+ if (HasLocalVariableExternalStorage(VD))
+ return RewriteLocalVariableExternalStorage(DRE);
+ }
+
+ if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ if (CE->getCallee()->getType()->isBlockPointerType()) {
+ Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
+ ReplaceStmt(S, BlockCall);
+ return BlockCall;
+ }
+ }
+ if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
+ RewriteCastExpr(CE);
+ }
+#if 0
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+ CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
+ ICE->getSubExpr(),
+ SourceLocation());
+ // Get the new text.
+ std::string SStr;
+ llvm::raw_string_ostream Buf(SStr);
+ Replacement->printPretty(Buf, *Context);
+ const std::string &Str = Buf.str();
+
+ printf("CAST = %s\n", &Str[0]);
+ InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+ delete S;
+ return Replacement;
+ }
+#endif
+ // Return this stmt unmodified.
+ return S;
+}
+
+void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
+ for (RecordDecl::field_iterator i = RD->field_begin(),
+ e = RD->field_end(); i != e; ++i) {
+ FieldDecl *FD = *i;
+ if (isTopLevelBlockPointerType(FD->getType()))
+ RewriteBlockPointerDecl(FD);
+ if (FD->getType()->isObjCQualifiedIdType() ||
+ FD->getType()->isObjCQualifiedInterfaceType())
+ RewriteObjCQualifiedInterfaceTypes(FD);
+ }
+}
+
+/// HandleDeclInMainFile - This is called for each top-level decl defined in the
+/// main file of the input.
+void RewriteObjC::HandleDeclInMainFile(Decl *D) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isOverloadedOperator())
+ return;
+
+ // Since function prototypes don't have ParmDecl's, we check the function
+ // prototype. This enables us to rewrite function declarations and
+ // definitions using the same code.
+ RewriteBlocksInFunctionProtoType(FD->getType(), FD);
+
+ // FIXME: If this should support Obj-C++, support CXXTryStmt
+ if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
+ CurFunctionDef = FD;
+ CurFunctionDeclToDeclareForBlock = FD;
+ CollectPropertySetters(Body);
+ CurrentBody = Body;
+ Body =
+ cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+ FD->setBody(Body);
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
+ // This synthesizes and inserts the block "impl" struct, invoke function,
+ // and any copy/dispose helper functions.
+ InsertBlockLiteralsWithinFunction(FD);
+ CurFunctionDef = 0;
+ CurFunctionDeclToDeclareForBlock = 0;
+ }
+ return;
+ }
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (CompoundStmt *Body = MD->getCompoundBody()) {
+ CurMethodDef = MD;
+ CollectPropertySetters(Body);
+ CurrentBody = Body;
+ Body =
+ cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
+ MD->setBody(Body);
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
+ InsertBlockLiteralsWithinMethod(MD);
+ CurMethodDef = 0;
+ }
+ }
+ if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D))
+ ClassImplementation.push_back(CI);
+ else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D))
+ CategoryImplementation.push_back(CI);
+ else if (ObjCClassDecl *CD = dyn_cast<ObjCClassDecl>(D))
+ RewriteForwardClassDecl(CD);
+ else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ RewriteObjCQualifiedInterfaceTypes(VD);
+ if (isTopLevelBlockPointerType(VD->getType()))
+ RewriteBlockPointerDecl(VD);
+ else if (VD->getType()->isFunctionPointerType()) {
+ CheckFunctionPointerDecl(VD->getType(), VD);
+ if (VD->getInit()) {
+ if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+ RewriteCastExpr(CE);
+ }
+ }
+ } else if (VD->getType()->isRecordType()) {
+ RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
+ }
+ if (VD->getInit()) {
+ GlobalVarDecl = VD;
+ CollectPropertySetters(VD->getInit());
+ CurrentBody = VD->getInit();
+ RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
+ SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
+ VD->getName());
+ GlobalVarDecl = 0;
+
+ // This is needed for blocks.
+ if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
+ RewriteCastExpr(CE);
+ }
+ }
+ return;
+ }
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
+ RewriteBlockPointerDecl(TD);
+ else if (TD->getUnderlyingType()->isFunctionPointerType())
+ CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+ return;
+ }
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
+ return;
+ }
+ // Nothing yet.
+}
+
+void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ RewriteInclude();
+
+ // Here's a great place to add any extra declarations that may be needed.
+ // Write out meta data for each @protocol(<expr>).
+ for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
+ E = ProtocolExprDecls.end(); I != E; ++I)
+ RewriteObjCProtocolMetaData(*I, "", "", Preamble);
+
+ InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
+ if (ClassImplementation.size() || CategoryImplementation.size())
+ RewriteImplementations();
+
+ // Get the buffer corresponding to MainFileID. If we haven't changed it, then
+ // we are done.
+ if (const RewriteBuffer *RewriteBuf =
+ Rewrite.getRewriteBufferFor(MainFileID)) {
+ //printf("Changed:\n");
+ *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
+ } else {
+ llvm::errs() << "No changes\n";
+ }
+
+ if (ClassImplementation.size() || CategoryImplementation.size() ||
+ ProtocolExprDecls.size()) {
+ // Rewrite Objective-c meta data*
+ std::string ResultStr;
+ SynthesizeMetaDataIntoBuffer(ResultStr);
+ // Emit metadata.
+ *OutFile << ResultStr;
+ }
+ OutFile->flush();
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
new file mode 100644
index 0000000..cfedd4b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteRope.cpp
@@ -0,0 +1,808 @@
+//===--- RewriteRope.cpp - Rope specialized for rewriter --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the RewriteRope class, which is a powerful string.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/RewriteRope.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+using namespace clang;
+using llvm::dyn_cast;
+using llvm::cast;
+
+/// RewriteRope is a "strong" string class, designed to make insertions and
+/// deletions in the middle of the string nearly constant time (really, they are
+/// O(log N), but with a very low constant factor).
+///
+/// The implementation of this datastructure is a conceptual linear sequence of
+/// RopePiece elements. Each RopePiece represents a view on a separately
+/// allocated and reference counted string. This means that splitting a very
+/// long string can be done in constant time by splitting a RopePiece that
+/// references the whole string into two rope pieces that reference each half.
+/// Once split, another string can be inserted in between the two halves by
+/// inserting a RopePiece in between the two others. All of this is very
+/// inexpensive: it takes time proportional to the number of RopePieces, not the
+/// length of the strings they represent.
+///
+/// While a linear sequences of RopePieces is the conceptual model, the actual
+/// implementation captures them in an adapted B+ Tree. Using a B+ tree (which
+/// is a tree that keeps the values in the leaves and has where each node
+/// contains a reasonable number of pointers to children/values) allows us to
+/// maintain efficient operation when the RewriteRope contains a *huge* number
+/// of RopePieces. The basic idea of the B+ Tree is that it allows us to find
+/// the RopePiece corresponding to some offset very efficiently, and it
+/// automatically balances itself on insertions of RopePieces (which can happen
+/// for both insertions and erases of string ranges).
+///
+/// The one wrinkle on the theory is that we don't attempt to keep the tree
+/// properly balanced when erases happen. Erases of string data can both insert
+/// new RopePieces (e.g. when the middle of some other rope piece is deleted,
+/// which results in two rope pieces, which is just like an insert) or it can
+/// reduce the number of RopePieces maintained by the B+Tree. In the case when
+/// the number of RopePieces is reduced, we don't attempt to maintain the
+/// standard 'invariant' that each node in the tree contains at least
+/// 'WidthFactor' children/values. For our use cases, this doesn't seem to
+/// matter.
+///
+/// The implementation below is primarily implemented in terms of three classes:
+/// RopePieceBTreeNode - Common base class for:
+///
+/// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
+/// nodes. This directly represents a chunk of the string with those
+/// RopePieces contatenated.
+/// RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
+/// up to '2*WidthFactor' other nodes in the tree.
+
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTreeNode Class
+//===----------------------------------------------------------------------===//
+
+namespace {
+ /// RopePieceBTreeNode - Common base class of RopePieceBTreeLeaf and
+ /// RopePieceBTreeInterior. This provides some 'virtual' dispatching methods
+ /// and a flag that determines which subclass the instance is. Also
+ /// important, this node knows the full extend of the node, including any
+ /// children that it has. This allows efficient skipping over entire subtrees
+ /// when looking for an offset in the BTree.
+ class RopePieceBTreeNode {
+ protected:
+ /// WidthFactor - This controls the number of K/V slots held in the BTree:
+ /// how wide it is. Each level of the BTree is guaranteed to have at least
+ /// 'WidthFactor' elements in it (either ropepieces or children), (except
+ /// the root, which may have less) and may have at most 2*WidthFactor
+ /// elements.
+ enum { WidthFactor = 8 };
+
+ /// Size - This is the number of bytes of file this node (including any
+ /// potential children) covers.
+ unsigned Size;
+
+ /// IsLeaf - True if this is an instance of RopePieceBTreeLeaf, false if it
+ /// is an instance of RopePieceBTreeInterior.
+ bool IsLeaf;
+
+ RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
+ ~RopePieceBTreeNode() {}
+ public:
+
+ bool isLeaf() const { return IsLeaf; }
+ unsigned size() const { return Size; }
+
+ void Destroy();
+
+ /// split - Split the range containing the specified offset so that we are
+ /// guaranteed that there is a place to do an insertion at the specified
+ /// offset. The offset is relative, so "0" is the start of the node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *split(unsigned Offset);
+
+ /// insert - Insert the specified ropepiece into this tree node at the
+ /// specified offset. The offset is relative, so "0" is the start of the
+ /// node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
+
+ /// erase - Remove NumBytes from this node at the specified offset. We are
+ /// guaranteed that there is a split at Offset.
+ void erase(unsigned Offset, unsigned NumBytes);
+
+ //static inline bool classof(const RopePieceBTreeNode *) { return true; }
+
+ };
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTreeLeaf Class
+//===----------------------------------------------------------------------===//
+
+namespace {
+ /// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
+ /// nodes. This directly represents a chunk of the string with those
+ /// RopePieces contatenated. Since this is a B+Tree, all values (in this case
+ /// instances of RopePiece) are stored in leaves like this. To make iteration
+ /// over the leaves efficient, they maintain a singly linked list through the
+ /// NextLeaf field. This allows the B+Tree forward iterator to be constant
+ /// time for all increments.
+ class RopePieceBTreeLeaf : public RopePieceBTreeNode {
+ /// NumPieces - This holds the number of rope pieces currently active in the
+ /// Pieces array.
+ unsigned char NumPieces;
+
+ /// Pieces - This tracks the file chunks currently in this leaf.
+ ///
+ RopePiece Pieces[2*WidthFactor];
+
+ /// NextLeaf - This is a pointer to the next leaf in the tree, allowing
+ /// efficient in-order forward iteration of the tree without traversal.
+ RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
+ public:
+ RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
+ PrevLeaf(0), NextLeaf(0) {}
+ ~RopePieceBTreeLeaf() {
+ if (PrevLeaf || NextLeaf)
+ removeFromLeafInOrder();
+ clear();
+ }
+
+ bool isFull() const { return NumPieces == 2*WidthFactor; }
+
+ /// clear - Remove all rope pieces from this leaf.
+ void clear() {
+ while (NumPieces)
+ Pieces[--NumPieces] = RopePiece();
+ Size = 0;
+ }
+
+ unsigned getNumPieces() const { return NumPieces; }
+
+ const RopePiece &getPiece(unsigned i) const {
+ assert(i < getNumPieces() && "Invalid piece ID");
+ return Pieces[i];
+ }
+
+ const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
+ void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
+ assert(PrevLeaf == 0 && NextLeaf == 0 && "Already in ordering");
+
+ NextLeaf = Node->NextLeaf;
+ if (NextLeaf)
+ NextLeaf->PrevLeaf = &NextLeaf;
+ PrevLeaf = &Node->NextLeaf;
+ Node->NextLeaf = this;
+ }
+
+ void removeFromLeafInOrder() {
+ if (PrevLeaf) {
+ *PrevLeaf = NextLeaf;
+ if (NextLeaf)
+ NextLeaf->PrevLeaf = PrevLeaf;
+ } else if (NextLeaf) {
+ NextLeaf->PrevLeaf = 0;
+ }
+ }
+
+ /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
+ /// summing the size of all RopePieces.
+ void FullRecomputeSizeLocally() {
+ Size = 0;
+ for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
+ Size += getPiece(i).size();
+ }
+
+ /// split - Split the range containing the specified offset so that we are
+ /// guaranteed that there is a place to do an insertion at the specified
+ /// offset. The offset is relative, so "0" is the start of the node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *split(unsigned Offset);
+
+ /// insert - Insert the specified ropepiece into this tree node at the
+ /// specified offset. The offset is relative, so "0" is the start of the
+ /// node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
+
+
+ /// erase - Remove NumBytes from this node at the specified offset. We are
+ /// guaranteed that there is a split at Offset.
+ void erase(unsigned Offset, unsigned NumBytes);
+
+ //static inline bool classof(const RopePieceBTreeLeaf *) { return true; }
+ static inline bool classof(const RopePieceBTreeNode *N) {
+ return N->isLeaf();
+ }
+ };
+} // end anonymous namespace
+
+/// split - Split the range containing the specified offset so that we are
+/// guaranteed that there is a place to do an insertion at the specified
+/// offset. The offset is relative, so "0" is the start of the node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
+ // Find the insertion point. We are guaranteed that there is a split at the
+ // specified offset so find it.
+ if (Offset == 0 || Offset == size()) {
+ // Fastpath for a common case. There is already a splitpoint at the end.
+ return 0;
+ }
+
+ // Find the piece that this offset lands in.
+ unsigned PieceOffs = 0;
+ unsigned i = 0;
+ while (Offset >= PieceOffs+Pieces[i].size()) {
+ PieceOffs += Pieces[i].size();
+ ++i;
+ }
+
+ // If there is already a split point at the specified offset, just return
+ // success.
+ if (PieceOffs == Offset)
+ return 0;
+
+ // Otherwise, we need to split piece 'i' at Offset-PieceOffs. Convert Offset
+ // to being Piece relative.
+ unsigned IntraPieceOffset = Offset-PieceOffs;
+
+ // We do this by shrinking the RopePiece and then doing an insert of the tail.
+ RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset,
+ Pieces[i].EndOffs);
+ Size -= Pieces[i].size();
+ Pieces[i].EndOffs = Pieces[i].StartOffs+IntraPieceOffset;
+ Size += Pieces[i].size();
+
+ return insert(Offset, Tail);
+}
+
+
+/// insert - Insert the specified RopePiece into this tree node at the
+/// specified offset. The offset is relative, so "0" is the start of the node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
+ const RopePiece &R) {
+ // If this node is not full, insert the piece.
+ if (!isFull()) {
+ // Find the insertion point. We are guaranteed that there is a split at the
+ // specified offset so find it.
+ unsigned i = 0, e = getNumPieces();
+ if (Offset == size()) {
+ // Fastpath for a common case.
+ i = e;
+ } else {
+ unsigned SlotOffs = 0;
+ for (; Offset > SlotOffs; ++i)
+ SlotOffs += getPiece(i).size();
+ assert(SlotOffs == Offset && "Split didn't occur before insertion!");
+ }
+
+ // For an insertion into a non-full leaf node, just insert the value in
+ // its sorted position. This requires moving later values over.
+ for (; i != e; --e)
+ Pieces[e] = Pieces[e-1];
+ Pieces[i] = R;
+ ++NumPieces;
+ Size += R.size();
+ return 0;
+ }
+
+ // Otherwise, if this is leaf is full, split it in two halves. Since this
+ // node is full, it contains 2*WidthFactor values. We move the first
+ // 'WidthFactor' values to the LHS child (which we leave in this node) and
+ // move the last 'WidthFactor' values into the RHS child.
+
+ // Create the new node.
+ RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
+
+ // Move over the last 'WidthFactor' values from here to NewNode.
+ std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
+ &NewNode->Pieces[0]);
+ // Replace old pieces with null RopePieces to drop refcounts.
+ std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor], RopePiece());
+
+ // Decrease the number of values in the two nodes.
+ NewNode->NumPieces = NumPieces = WidthFactor;
+
+ // Recompute the two nodes' size.
+ NewNode->FullRecomputeSizeLocally();
+ FullRecomputeSizeLocally();
+
+ // Update the list of leaves.
+ NewNode->insertAfterLeafInOrder(this);
+
+ // These insertions can't fail.
+ if (this->size() >= Offset)
+ this->insert(Offset, R);
+ else
+ NewNode->insert(Offset - this->size(), R);
+ return NewNode;
+}
+
+/// erase - Remove NumBytes from this node at the specified offset. We are
+/// guaranteed that there is a split at Offset.
+void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
+ // Since we are guaranteed that there is a split at Offset, we start by
+ // finding the Piece that starts there.
+ unsigned PieceOffs = 0;
+ unsigned i = 0;
+ for (; Offset > PieceOffs; ++i)
+ PieceOffs += getPiece(i).size();
+ assert(PieceOffs == Offset && "Split didn't occur before erase!");
+
+ unsigned StartPiece = i;
+
+ // Figure out how many pieces completely cover 'NumBytes'. We want to remove
+ // all of them.
+ for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i)
+ PieceOffs += getPiece(i).size();
+
+ // If we exactly include the last one, include it in the region to delete.
+ if (Offset+NumBytes == PieceOffs+getPiece(i).size())
+ PieceOffs += getPiece(i).size(), ++i;
+
+ // If we completely cover some RopePieces, erase them now.
+ if (i != StartPiece) {
+ unsigned NumDeleted = i-StartPiece;
+ for (; i != getNumPieces(); ++i)
+ Pieces[i-NumDeleted] = Pieces[i];
+
+ // Drop references to dead rope pieces.
+ std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()],
+ RopePiece());
+ NumPieces -= NumDeleted;
+
+ unsigned CoverBytes = PieceOffs-Offset;
+ NumBytes -= CoverBytes;
+ Size -= CoverBytes;
+ }
+
+ // If we completely removed some stuff, we could be done.
+ if (NumBytes == 0) return;
+
+ // Okay, now might be erasing part of some Piece. If this is the case, then
+ // move the start point of the piece.
+ assert(getPiece(StartPiece).size() > NumBytes);
+ Pieces[StartPiece].StartOffs += NumBytes;
+
+ // The size of this node just shrunk by NumBytes.
+ Size -= NumBytes;
+}
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTreeInterior Class
+//===----------------------------------------------------------------------===//
+
+namespace {
+ /// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
+ /// which holds up to 2*WidthFactor pointers to child nodes.
+ class RopePieceBTreeInterior : public RopePieceBTreeNode {
+ /// NumChildren - This holds the number of children currently active in the
+ /// Children array.
+ unsigned char NumChildren;
+ RopePieceBTreeNode *Children[2*WidthFactor];
+ public:
+ RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
+
+ RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
+ : RopePieceBTreeNode(false) {
+ Children[0] = LHS;
+ Children[1] = RHS;
+ NumChildren = 2;
+ Size = LHS->size() + RHS->size();
+ }
+
+ bool isFull() const { return NumChildren == 2*WidthFactor; }
+
+ unsigned getNumChildren() const { return NumChildren; }
+ const RopePieceBTreeNode *getChild(unsigned i) const {
+ assert(i < NumChildren && "invalid child #");
+ return Children[i];
+ }
+ RopePieceBTreeNode *getChild(unsigned i) {
+ assert(i < NumChildren && "invalid child #");
+ return Children[i];
+ }
+
+ /// FullRecomputeSizeLocally - Recompute the Size field of this node by
+ /// summing up the sizes of the child nodes.
+ void FullRecomputeSizeLocally() {
+ Size = 0;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ Size += getChild(i)->size();
+ }
+
+
+ /// split - Split the range containing the specified offset so that we are
+ /// guaranteed that there is a place to do an insertion at the specified
+ /// offset. The offset is relative, so "0" is the start of the node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *split(unsigned Offset);
+
+
+ /// insert - Insert the specified ropepiece into this tree node at the
+ /// specified offset. The offset is relative, so "0" is the start of the
+ /// node.
+ ///
+ /// If there is no space in this subtree for the extra piece, the extra tree
+ /// node is returned and must be inserted into a parent.
+ RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
+
+ /// HandleChildPiece - A child propagated an insertion result up to us.
+ /// Insert the new child, and/or propagate the result further up the tree.
+ RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
+
+ /// erase - Remove NumBytes from this node at the specified offset. We are
+ /// guaranteed that there is a split at Offset.
+ void erase(unsigned Offset, unsigned NumBytes);
+
+ //static inline bool classof(const RopePieceBTreeInterior *) { return true; }
+ static inline bool classof(const RopePieceBTreeNode *N) {
+ return !N->isLeaf();
+ }
+ };
+} // end anonymous namespace
+
+/// split - Split the range containing the specified offset so that we are
+/// guaranteed that there is a place to do an insertion at the specified
+/// offset. The offset is relative, so "0" is the start of the node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
+ // Figure out which child to split.
+ if (Offset == 0 || Offset == size())
+ return 0; // If we have an exact offset, we're already split.
+
+ unsigned ChildOffset = 0;
+ unsigned i = 0;
+ for (; Offset >= ChildOffset+getChild(i)->size(); ++i)
+ ChildOffset += getChild(i)->size();
+
+ // If already split there, we're done.
+ if (ChildOffset == Offset)
+ return 0;
+
+ // Otherwise, recursively split the child.
+ if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
+ return HandleChildPiece(i, RHS);
+ return 0; // Done!
+}
+
+/// insert - Insert the specified ropepiece into this tree node at the
+/// specified offset. The offset is relative, so "0" is the start of the
+/// node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset,
+ const RopePiece &R) {
+ // Find the insertion point. We are guaranteed that there is a split at the
+ // specified offset so find it.
+ unsigned i = 0, e = getNumChildren();
+
+ unsigned ChildOffs = 0;
+ if (Offset == size()) {
+ // Fastpath for a common case. Insert at end of last child.
+ i = e-1;
+ ChildOffs = size()-getChild(i)->size();
+ } else {
+ for (; Offset > ChildOffs+getChild(i)->size(); ++i)
+ ChildOffs += getChild(i)->size();
+ }
+
+ Size += R.size();
+
+ // Insert at the end of this child.
+ if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R))
+ return HandleChildPiece(i, RHS);
+
+ return 0;
+}
+
+/// HandleChildPiece - A child propagated an insertion result up to us.
+/// Insert the new child, and/or propagate the result further up the tree.
+RopePieceBTreeNode *
+RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) {
+ // Otherwise the child propagated a subtree up to us as a new child. See if
+ // we have space for it here.
+ if (!isFull()) {
+ // Insert RHS after child 'i'.
+ if (i + 1 != getNumChildren())
+ memmove(&Children[i+2], &Children[i+1],
+ (getNumChildren()-i-1)*sizeof(Children[0]));
+ Children[i+1] = RHS;
+ ++NumChildren;
+ return 0;
+ }
+
+ // Okay, this node is full. Split it in half, moving WidthFactor children to
+ // a newly allocated interior node.
+
+ // Create the new node.
+ RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior();
+
+ // Move over the last 'WidthFactor' values from here to NewNode.
+ memcpy(&NewNode->Children[0], &Children[WidthFactor],
+ WidthFactor*sizeof(Children[0]));
+
+ // Decrease the number of values in the two nodes.
+ NewNode->NumChildren = NumChildren = WidthFactor;
+
+ // Finally, insert the two new children in the side the can (now) hold them.
+ // These insertions can't fail.
+ if (i < WidthFactor)
+ this->HandleChildPiece(i, RHS);
+ else
+ NewNode->HandleChildPiece(i-WidthFactor, RHS);
+
+ // Recompute the two nodes' size.
+ NewNode->FullRecomputeSizeLocally();
+ FullRecomputeSizeLocally();
+ return NewNode;
+}
+
+/// erase - Remove NumBytes from this node at the specified offset. We are
+/// guaranteed that there is a split at Offset.
+void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
+ // This will shrink this node by NumBytes.
+ Size -= NumBytes;
+
+ // Find the first child that overlaps with Offset.
+ unsigned i = 0;
+ for (; Offset >= getChild(i)->size(); ++i)
+ Offset -= getChild(i)->size();
+
+ // Propagate the delete request into overlapping children, or completely
+ // delete the children as appropriate.
+ while (NumBytes) {
+ RopePieceBTreeNode *CurChild = getChild(i);
+
+ // If we are deleting something contained entirely in the child, pass on the
+ // request.
+ if (Offset+NumBytes < CurChild->size()) {
+ CurChild->erase(Offset, NumBytes);
+ return;
+ }
+
+ // If this deletion request starts somewhere in the middle of the child, it
+ // must be deleting to the end of the child.
+ if (Offset) {
+ unsigned BytesFromChild = CurChild->size()-Offset;
+ CurChild->erase(Offset, BytesFromChild);
+ NumBytes -= BytesFromChild;
+ // Start at the beginning of the next child.
+ Offset = 0;
+ ++i;
+ continue;
+ }
+
+ // If the deletion request completely covers the child, delete it and move
+ // the rest down.
+ NumBytes -= CurChild->size();
+ CurChild->Destroy();
+ --NumChildren;
+ if (i != getNumChildren())
+ memmove(&Children[i], &Children[i+1],
+ (getNumChildren()-i)*sizeof(Children[0]));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTreeNode Implementation
+//===----------------------------------------------------------------------===//
+
+void RopePieceBTreeNode::Destroy() {
+ if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ delete Leaf;
+ else
+ delete cast<RopePieceBTreeInterior>(this);
+}
+
+/// split - Split the range containing the specified offset so that we are
+/// guaranteed that there is a place to do an insertion at the specified
+/// offset. The offset is relative, so "0" is the start of the node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
+ assert(Offset <= size() && "Invalid offset to split!");
+ if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ return Leaf->split(Offset);
+ return cast<RopePieceBTreeInterior>(this)->split(Offset);
+}
+
+/// insert - Insert the specified ropepiece into this tree node at the
+/// specified offset. The offset is relative, so "0" is the start of the
+/// node.
+///
+/// If there is no space in this subtree for the extra piece, the extra tree
+/// node is returned and must be inserted into a parent.
+RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
+ const RopePiece &R) {
+ assert(Offset <= size() && "Invalid offset to insert!");
+ if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ return Leaf->insert(Offset, R);
+ return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
+}
+
+/// erase - Remove NumBytes from this node at the specified offset. We are
+/// guaranteed that there is a split at Offset.
+void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
+ assert(Offset+NumBytes <= size() && "Invalid offset to erase!");
+ if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
+ return Leaf->erase(Offset, NumBytes);
+ return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
+}
+
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTreeIterator Implementation
+//===----------------------------------------------------------------------===//
+
+static const RopePieceBTreeLeaf *getCN(const void *P) {
+ return static_cast<const RopePieceBTreeLeaf*>(P);
+}
+
+// begin iterator.
+RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
+ const RopePieceBTreeNode *N = static_cast<const RopePieceBTreeNode*>(n);
+
+ // Walk down the left side of the tree until we get to a leaf.
+ while (const RopePieceBTreeInterior *IN = dyn_cast<RopePieceBTreeInterior>(N))
+ N = IN->getChild(0);
+
+ // We must have at least one leaf.
+ CurNode = cast<RopePieceBTreeLeaf>(N);
+
+ // If we found a leaf that happens to be empty, skip over it until we get
+ // to something full.
+ while (CurNode && getCN(CurNode)->getNumPieces() == 0)
+ CurNode = getCN(CurNode)->getNextLeafInOrder();
+
+ if (CurNode != 0)
+ CurPiece = &getCN(CurNode)->getPiece(0);
+ else // Empty tree, this is an end() iterator.
+ CurPiece = 0;
+ CurChar = 0;
+}
+
+void RopePieceBTreeIterator::MoveToNextPiece() {
+ if (CurPiece != &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces()-1)) {
+ CurChar = 0;
+ ++CurPiece;
+ return;
+ }
+
+ // Find the next non-empty leaf node.
+ do
+ CurNode = getCN(CurNode)->getNextLeafInOrder();
+ while (CurNode && getCN(CurNode)->getNumPieces() == 0);
+
+ if (CurNode != 0)
+ CurPiece = &getCN(CurNode)->getPiece(0);
+ else // Hit end().
+ CurPiece = 0;
+ CurChar = 0;
+}
+
+//===----------------------------------------------------------------------===//
+// RopePieceBTree Implementation
+//===----------------------------------------------------------------------===//
+
+static RopePieceBTreeNode *getRoot(void *P) {
+ return static_cast<RopePieceBTreeNode*>(P);
+}
+
+RopePieceBTree::RopePieceBTree() {
+ Root = new RopePieceBTreeLeaf();
+}
+RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
+ assert(RHS.empty() && "Can't copy non-empty tree yet");
+ Root = new RopePieceBTreeLeaf();
+}
+RopePieceBTree::~RopePieceBTree() {
+ getRoot(Root)->Destroy();
+}
+
+unsigned RopePieceBTree::size() const {
+ return getRoot(Root)->size();
+}
+
+void RopePieceBTree::clear() {
+ if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
+ Leaf->clear();
+ else {
+ getRoot(Root)->Destroy();
+ Root = new RopePieceBTreeLeaf();
+ }
+}
+
+void RopePieceBTree::insert(unsigned Offset, const RopePiece &R) {
+ // #1. Split at Offset.
+ if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
+ Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
+
+ // #2. Do the insertion.
+ if (RopePieceBTreeNode *RHS = getRoot(Root)->insert(Offset, R))
+ Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
+}
+
+void RopePieceBTree::erase(unsigned Offset, unsigned NumBytes) {
+ // #1. Split at Offset.
+ if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
+ Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
+
+ // #2. Do the erasing.
+ getRoot(Root)->erase(Offset, NumBytes);
+}
+
+//===----------------------------------------------------------------------===//
+// RewriteRope Implementation
+//===----------------------------------------------------------------------===//
+
+/// MakeRopeString - This copies the specified byte range into some instance of
+/// RopeRefCountString, and return a RopePiece that represents it. This uses
+/// the AllocBuffer object to aggregate requests for small strings into one
+/// allocation instead of doing tons of tiny allocations.
+RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
+ unsigned Len = End-Start;
+ assert(Len && "Zero length RopePiece is invalid!");
+
+ // If we have space for this string in the current alloc buffer, use it.
+ if (AllocOffs+Len <= AllocChunkSize) {
+ memcpy(AllocBuffer->Data+AllocOffs, Start, Len);
+ AllocOffs += Len;
+ return RopePiece(AllocBuffer, AllocOffs-Len, AllocOffs);
+ }
+
+ // If we don't have enough room because this specific allocation is huge,
+ // just allocate a new rope piece for it alone.
+ if (Len > AllocChunkSize) {
+ unsigned Size = End-Start+sizeof(RopeRefCountString)-1;
+ RopeRefCountString *Res =
+ reinterpret_cast<RopeRefCountString *>(new char[Size]);
+ Res->RefCount = 0;
+ memcpy(Res->Data, Start, End-Start);
+ return RopePiece(Res, 0, End-Start);
+ }
+
+ // Otherwise, this was a small request but we just don't have space for it
+ // Make a new chunk and share it with later allocations.
+
+ // If we had an old allocation, drop our reference to it.
+ if (AllocBuffer && --AllocBuffer->RefCount == 0)
+ delete [] (char*)AllocBuffer;
+
+ unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
+ AllocBuffer = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
+ AllocBuffer->RefCount = 0;
+ memcpy(AllocBuffer->Data, Start, Len);
+ AllocOffs = Len;
+
+ // Start out the new allocation with a refcount of 1, since we have an
+ // internal reference to it.
+ AllocBuffer->addRef();
+ return RopePiece(AllocBuffer, 0, Len);
+}
+
+
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteTest.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteTest.cpp
new file mode 100644
index 0000000..3620700
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteTest.cpp
@@ -0,0 +1,39 @@
+//===--- RewriteTest.cpp - Rewriter playground ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a testbed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/Rewriters.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/TokenRewriter.h"
+#include "llvm/Support/raw_ostream.h"
+
+void clang::DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS) {
+ SourceManager &SM = PP.getSourceManager();
+ const LangOptions &LangOpts = PP.getLangOptions();
+
+ TokenRewriter Rewriter(SM.getMainFileID(), SM, LangOpts);
+
+ // Throw <i> </i> tags around comments.
+ for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
+ E = Rewriter.token_end(); I != E; ++I) {
+ if (I->isNot(tok::comment)) continue;
+
+ Rewriter.AddTokenBefore(I, "<i>");
+ Rewriter.AddTokenAfter(I, "</i>");
+ }
+
+
+ // Print out the output.
+ for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
+ E = Rewriter.token_end(); I != E; ++I)
+ *OS << PP.getSpelling(*I);
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
new file mode 100644
index 0000000..92e2b03
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
@@ -0,0 +1,236 @@
+//===--- Rewriter.cpp - Code rewriting interface --------------------------===//
+//
+// 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 Rewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Decl.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+llvm::raw_ostream &RewriteBuffer::write(llvm::raw_ostream &os) const {
+ // FIXME: eliminate the copy by writing out each chunk at a time
+ os << std::string(begin(), end());
+ return os;
+}
+
+void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size) {
+ // Nothing to remove, exit early.
+ if (Size == 0) return;
+
+ unsigned RealOffset = getMappedOffset(OrigOffset, true);
+ assert(RealOffset+Size < Buffer.size() && "Invalid location");
+
+ // Remove the dead characters.
+ Buffer.erase(RealOffset, Size);
+
+ // Add a delta so that future changes are offset correctly.
+ AddReplaceDelta(OrigOffset, -Size);
+}
+
+void RewriteBuffer::InsertText(unsigned OrigOffset, llvm::StringRef Str,
+ bool InsertAfter) {
+
+ // Nothing to insert, exit early.
+ if (Str.empty()) return;
+
+ unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
+ Buffer.insert(RealOffset, Str.begin(), Str.end());
+
+ // Add a delta so that future changes are offset correctly.
+ AddInsertDelta(OrigOffset, Str.size());
+}
+
+/// ReplaceText - This method replaces a range of characters in the input
+/// buffer with a new string. This is effectively a combined "remove+insert"
+/// operation.
+void RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
+ llvm::StringRef NewStr) {
+ unsigned RealOffset = getMappedOffset(OrigOffset, true);
+ Buffer.erase(RealOffset, OrigLength);
+ Buffer.insert(RealOffset, NewStr.begin(), NewStr.end());
+ if (OrigLength != NewStr.size())
+ AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Rewriter class
+//===----------------------------------------------------------------------===//
+
+/// getRangeSize - Return the size in bytes of the specified range if they
+/// are in the same file. If not, this returns -1.
+int Rewriter::getRangeSize(const CharSourceRange &Range) const {
+ if (!isRewritable(Range.getBegin()) ||
+ !isRewritable(Range.getEnd())) return -1;
+
+ FileID StartFileID, EndFileID;
+ unsigned StartOff, EndOff;
+
+ StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
+ EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
+
+ if (StartFileID != EndFileID)
+ return -1;
+
+ // If edits have been made to this buffer, the delta between the range may
+ // have changed.
+ std::map<FileID, RewriteBuffer>::const_iterator I =
+ RewriteBuffers.find(StartFileID);
+ if (I != RewriteBuffers.end()) {
+ const RewriteBuffer &RB = I->second;
+ EndOff = RB.getMappedOffset(EndOff, true);
+ StartOff = RB.getMappedOffset(StartOff);
+ }
+
+
+ // Adjust the end offset to the end of the last token, instead of being the
+ // start of the last token if this is a token range.
+ if (Range.isTokenRange())
+ EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
+
+ return EndOff-StartOff;
+}
+
+int Rewriter::getRangeSize(SourceRange Range) const {
+ return getRangeSize(CharSourceRange::getTokenRange(Range));
+}
+
+
+/// getRewrittenText - Return the rewritten form of the text in the specified
+/// range. If the start or end of the range was unrewritable or if they are
+/// in different buffers, this returns an empty string.
+///
+/// Note that this method is not particularly efficient.
+///
+std::string Rewriter::getRewrittenText(SourceRange Range) const {
+ if (!isRewritable(Range.getBegin()) ||
+ !isRewritable(Range.getEnd()))
+ return "";
+
+ FileID StartFileID, EndFileID;
+ unsigned StartOff, EndOff;
+ StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
+ EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
+
+ if (StartFileID != EndFileID)
+ return ""; // Start and end in different buffers.
+
+ // If edits have been made to this buffer, the delta between the range may
+ // have changed.
+ std::map<FileID, RewriteBuffer>::const_iterator I =
+ RewriteBuffers.find(StartFileID);
+ if (I == RewriteBuffers.end()) {
+ // If the buffer hasn't been rewritten, just return the text from the input.
+ const char *Ptr = SourceMgr->getCharacterData(Range.getBegin());
+
+ // Adjust the end offset to the end of the last token, instead of being the
+ // start of the last token.
+ EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
+ return std::string(Ptr, Ptr+EndOff-StartOff);
+ }
+
+ const RewriteBuffer &RB = I->second;
+ EndOff = RB.getMappedOffset(EndOff, true);
+ StartOff = RB.getMappedOffset(StartOff);
+
+ // Adjust the end offset to the end of the last token, instead of being the
+ // start of the last token.
+ EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
+
+ // Advance the iterators to the right spot, yay for linear time algorithms.
+ RewriteBuffer::iterator Start = RB.begin();
+ std::advance(Start, StartOff);
+ RewriteBuffer::iterator End = Start;
+ std::advance(End, EndOff-StartOff);
+
+ return std::string(Start, End);
+}
+
+unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
+ FileID &FID) const {
+ assert(Loc.isValid() && "Invalid location");
+ std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc);
+ FID = V.first;
+ return V.second;
+}
+
+
+/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
+///
+RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
+ std::map<FileID, RewriteBuffer>::iterator I =
+ RewriteBuffers.lower_bound(FID);
+ if (I != RewriteBuffers.end() && I->first == FID)
+ return I->second;
+ I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
+
+ llvm::StringRef MB = SourceMgr->getBufferData(FID);
+ I->second.Initialize(MB.begin(), MB.end());
+
+ return I->second;
+}
+
+/// InsertText - Insert the specified string at the specified location in the
+/// original buffer.
+bool Rewriter::InsertText(SourceLocation Loc, llvm::StringRef Str,
+ bool InsertAfter) {
+ if (!isRewritable(Loc)) return true;
+ FileID FID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
+ getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter);
+ return false;
+}
+
+/// RemoveText - Remove the specified text region.
+bool Rewriter::RemoveText(SourceLocation Start, unsigned Length) {
+ if (!isRewritable(Start)) return true;
+ FileID FID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
+ getEditBuffer(FID).RemoveText(StartOffs, Length);
+ return false;
+}
+
+/// ReplaceText - This method replaces a range of characters in the input
+/// buffer with a new string. This is effectively a combined "remove/insert"
+/// operation.
+bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
+ llvm::StringRef NewStr) {
+ if (!isRewritable(Start)) return true;
+ FileID StartFileID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
+
+ getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr);
+ return false;
+}
+
+/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
+/// printer to generate the replacement code. This returns true if the input
+/// could not be rewritten, or false if successful.
+bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) {
+ // Measaure the old text.
+ int Size = getRangeSize(From->getSourceRange());
+ if (Size == -1)
+ return true;
+
+ // Get the new text.
+ std::string SStr;
+ llvm::raw_string_ostream S(SStr);
+ To->printPretty(S, 0, PrintingPolicy(*LangOpts));
+ const std::string &Str = S.str();
+
+ ReplaceText(From->getLocStart(), Size, Str);
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp
new file mode 100644
index 0000000..03ce63e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Rewrite/TokenRewriter.cpp
@@ -0,0 +1,99 @@
+//===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TokenRewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Rewrite/TokenRewriter.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/ScratchBuffer.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
+ const LangOptions &LangOpts) {
+ ScratchBuf.reset(new ScratchBuffer(SM));
+
+ // Create a lexer to lex all the tokens of the main file in raw mode.
+ const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
+ Lexer RawLex(FID, FromFile, SM, LangOpts);
+
+ // Return all comments and whitespace as tokens.
+ RawLex.SetKeepWhitespaceMode(true);
+
+ // Lex the file, populating our datastructures.
+ Token RawTok;
+ RawLex.LexFromRawLexer(RawTok);
+ while (RawTok.isNot(tok::eof)) {
+#if 0
+ if (Tok.is(tok::raw_identifier)) {
+ // Look up the identifier info for the token. This should use
+ // IdentifierTable directly instead of PP.
+ PP.LookUpIdentifierInfo(Tok);
+ }
+#endif
+
+ AddToken(RawTok, TokenList.end());
+ RawLex.LexFromRawLexer(RawTok);
+ }
+}
+
+TokenRewriter::~TokenRewriter() {
+}
+
+
+/// RemapIterator - Convert from token_iterator (a const iterator) to
+/// TokenRefTy (a non-const iterator).
+TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) {
+ if (I == token_end()) return TokenList.end();
+
+ // FIXME: This is horrible, we should use our own list or something to avoid
+ // this.
+ std::map<SourceLocation, TokenRefTy>::iterator MapIt =
+ TokenAtLoc.find(I->getLocation());
+ assert(MapIt != TokenAtLoc.end() && "iterator not in rewriter?");
+ return MapIt->second;
+}
+
+
+/// AddToken - Add the specified token into the Rewriter before the other
+/// position.
+TokenRewriter::TokenRefTy
+TokenRewriter::AddToken(const Token &T, TokenRefTy Where) {
+ Where = TokenList.insert(Where, T);
+
+ bool InsertSuccess = TokenAtLoc.insert(std::make_pair(T.getLocation(),
+ Where)).second;
+ assert(InsertSuccess && "Token location already in rewriter!");
+ (void)InsertSuccess;
+ return Where;
+}
+
+
+TokenRewriter::token_iterator
+TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) {
+ unsigned Len = strlen(Val);
+
+ // Plop the string into the scratch buffer, then create a token for this
+ // string.
+ Token Tok;
+ Tok.startToken();
+ const char *Spelling;
+ Tok.setLocation(ScratchBuf->getToken(Val, Len, Spelling));
+ Tok.setLength(Len);
+
+ // TODO: Form a whole lexer around this and relex the token! For now, just
+ // set kind to tok::unknown.
+ Tok.setKind(tok::unknown);
+
+ return AddToken(Tok, RemapIterator(I));
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
new file mode 100644
index 0000000..63f561d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -0,0 +1,570 @@
+//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- 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 analysis_warnings::[Policy,Executor].
+// Together they are used by Sema to issue warnings based on inexpensive
+// static analysis algorithms in libAnalysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Support/Casting.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Unreachable code analysis.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class UnreachableCodeHandler : public reachable_code::Callback {
+ Sema &S;
+ public:
+ UnreachableCodeHandler(Sema &s) : S(s) {}
+
+ void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
+ S.Diag(L, diag::warn_unreachable) << R1 << R2;
+ }
+ };
+}
+
+/// CheckUnreachable - Check for unreachable code.
+static void CheckUnreachable(Sema &S, AnalysisContext &AC) {
+ UnreachableCodeHandler UC(S);
+ reachable_code::FindUnreachableCode(AC, UC);
+}
+
+//===----------------------------------------------------------------------===//
+// Check for missing return value.
+//===----------------------------------------------------------------------===//
+
+enum ControlFlowKind {
+ UnknownFallThrough,
+ NeverFallThrough,
+ MaybeFallThrough,
+ AlwaysFallThrough,
+ NeverFallThroughOrReturn
+};
+
+/// CheckFallThrough - Check that we don't fall off the end of a
+/// Statement that should return a value.
+///
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end,
+/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
+/// return. We assume NeverFallThrough iff we never fall off the end of the
+/// statement but we may return. We assume that functions not marked noreturn
+/// will return.
+static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
+ CFG *cfg = AC.getCFG();
+ if (cfg == 0) return UnknownFallThrough;
+
+ // The CFG leaves in dead things, and we don't want the dead code paths to
+ // confuse us, so we mark all live things first.
+ llvm::BitVector live(cfg->getNumBlockIDs());
+ unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
+ live);
+
+ bool AddEHEdges = AC.getAddEHEdges();
+ if (!AddEHEdges && count != cfg->getNumBlockIDs())
+ // When there are things remaining dead, and we didn't add EH edges
+ // from CallExprs to the catch clauses, we have to go back and
+ // mark them as live.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!live[b.getBlockID()]) {
+ if (b.pred_begin() == b.pred_end()) {
+ if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
+ // When not adding EH edges from calls, catch clauses
+ // can otherwise seem dead. Avoid noting them as dead.
+ count += reachable_code::ScanReachableFromBlock(b, live);
+ continue;
+ }
+ }
+ }
+
+ // Now we know what is live, we check the live precessors of the exit block
+ // and look for fall through paths, being careful to ignore normal returns,
+ // and exceptional paths.
+ bool HasLiveReturn = false;
+ bool HasFakeEdge = false;
+ bool HasPlainEdge = false;
+ bool HasAbnormalEdge = false;
+
+ // Ignore default cases that aren't likely to be reachable because all
+ // enums in a switch(X) have explicit case statements.
+ CFGBlock::FilterOptions FO;
+ FO.IgnoreDefaultsWithCoveredEnums = 1;
+
+ for (CFGBlock::filtered_pred_iterator
+ I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
+ const CFGBlock& B = **I;
+ if (!live[B.getBlockID()])
+ continue;
+
+ // Destructors can appear after the 'return' in the CFG. This is
+ // normal. We need to look pass the destructors for the return
+ // statement (if it exists).
+ CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
+ for ( ; ri != re ; ++ri) {
+ CFGElement CE = *ri;
+ if (isa<CFGStmt>(CE))
+ break;
+ }
+
+ // No more CFGElements in the block?
+ if (ri == re) {
+ if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+ // A labeled empty statement, or the entry block...
+ HasPlainEdge = true;
+ continue;
+ }
+
+ CFGStmt CS = cast<CFGStmt>(*ri);
+ Stmt *S = CS.getStmt();
+ if (isa<ReturnStmt>(S)) {
+ HasLiveReturn = true;
+ continue;
+ }
+ if (isa<ObjCAtThrowStmt>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ if (isa<CXXThrowExpr>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
+ if (AS->isMSAsm()) {
+ HasFakeEdge = true;
+ HasLiveReturn = true;
+ continue;
+ }
+ }
+ if (isa<CXXTryStmt>(S)) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+
+ bool NoReturnEdge = false;
+ if (CallExpr *C = dyn_cast<CallExpr>(S)) {
+ if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
+ == B.succ_end()) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+ Expr *CEE = C->getCallee()->IgnoreParenCasts();
+ if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
+ NoReturnEdge = true;
+ HasFakeEdge = true;
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
+ ValueDecl *VD = DRE->getDecl();
+ if (VD->hasAttr<NoReturnAttr>()) {
+ NoReturnEdge = true;
+ HasFakeEdge = true;
+ }
+ }
+ }
+ // FIXME: Add noreturn message sends.
+ if (NoReturnEdge == false)
+ HasPlainEdge = true;
+ }
+ if (!HasPlainEdge) {
+ if (HasLiveReturn)
+ return NeverFallThrough;
+ return NeverFallThroughOrReturn;
+ }
+ if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
+ return MaybeFallThrough;
+ // This says AlwaysFallThrough for calls to functions that are not marked
+ // noreturn, that don't return. If people would like this warning to be more
+ // accurate, such functions should be marked as noreturn.
+ return AlwaysFallThrough;
+}
+
+namespace {
+
+struct CheckFallThroughDiagnostics {
+ unsigned diag_MaybeFallThrough_HasNoReturn;
+ unsigned diag_MaybeFallThrough_ReturnsNonVoid;
+ unsigned diag_AlwaysFallThrough_HasNoReturn;
+ unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
+ unsigned diag_NeverFallThroughOrReturn;
+ bool funMode;
+ SourceLocation FuncLoc;
+
+ static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
+ CheckFallThroughDiagnostics D;
+ D.FuncLoc = Func->getLocation();
+ D.diag_MaybeFallThrough_HasNoReturn =
+ diag::warn_falloff_noreturn_function;
+ D.diag_MaybeFallThrough_ReturnsNonVoid =
+ diag::warn_maybe_falloff_nonvoid_function;
+ D.diag_AlwaysFallThrough_HasNoReturn =
+ diag::warn_falloff_noreturn_function;
+ D.diag_AlwaysFallThrough_ReturnsNonVoid =
+ diag::warn_falloff_nonvoid_function;
+
+ // Don't suggest that virtual functions be marked "noreturn", since they
+ // might be overridden by non-noreturn functions.
+ bool isVirtualMethod = false;
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
+ isVirtualMethod = Method->isVirtual();
+
+ if (!isVirtualMethod)
+ D.diag_NeverFallThroughOrReturn =
+ diag::warn_suggest_noreturn_function;
+ else
+ D.diag_NeverFallThroughOrReturn = 0;
+
+ D.funMode = true;
+ return D;
+ }
+
+ static CheckFallThroughDiagnostics MakeForBlock() {
+ CheckFallThroughDiagnostics D;
+ D.diag_MaybeFallThrough_HasNoReturn =
+ diag::err_noreturn_block_has_return_expr;
+ D.diag_MaybeFallThrough_ReturnsNonVoid =
+ diag::err_maybe_falloff_nonvoid_block;
+ D.diag_AlwaysFallThrough_HasNoReturn =
+ diag::err_noreturn_block_has_return_expr;
+ D.diag_AlwaysFallThrough_ReturnsNonVoid =
+ diag::err_falloff_nonvoid_block;
+ D.diag_NeverFallThroughOrReturn =
+ diag::warn_suggest_noreturn_block;
+ D.funMode = false;
+ return D;
+ }
+
+ bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
+ bool HasNoReturn) const {
+ if (funMode) {
+ return (ReturnsVoid ||
+ D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
+ FuncLoc) == Diagnostic::Ignored)
+ && (!HasNoReturn ||
+ D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
+ FuncLoc) == Diagnostic::Ignored)
+ && (!ReturnsVoid ||
+ D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
+ == Diagnostic::Ignored);
+ }
+
+ // For blocks.
+ return ReturnsVoid && !HasNoReturn
+ && (!ReturnsVoid ||
+ D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
+ == Diagnostic::Ignored);
+ }
+};
+
+}
+
+/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// function that should return a value. Check that we don't fall off the end
+/// of a noreturn function. We assume that functions and blocks not marked
+/// noreturn will return.
+static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
+ QualType BlockTy,
+ const CheckFallThroughDiagnostics& CD,
+ AnalysisContext &AC) {
+
+ bool ReturnsVoid = false;
+ bool HasNoReturn = false;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ ReturnsVoid = FD->getResultType()->isVoidType();
+ HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
+ }
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ ReturnsVoid = MD->getResultType()->isVoidType();
+ HasNoReturn = MD->hasAttr<NoReturnAttr>();
+ }
+ else if (isa<BlockDecl>(D)) {
+ if (const FunctionType *FT =
+ BlockTy->getPointeeType()->getAs<FunctionType>()) {
+ if (FT->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (FT->getNoReturnAttr())
+ HasNoReturn = true;
+ }
+ }
+
+ Diagnostic &Diags = S.getDiagnostics();
+
+ // Short circuit for compilation speed.
+ if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
+ return;
+
+ // FIXME: Function try block
+ if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+ switch (CheckFallThrough(AC)) {
+ case UnknownFallThrough:
+ break;
+
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ S.Diag(Compound->getRBracLoc(),
+ CD.diag_MaybeFallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(Compound->getRBracLoc(),
+ CD.diag_MaybeFallThrough_ReturnsNonVoid);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ S.Diag(Compound->getRBracLoc(),
+ CD.diag_AlwaysFallThrough_HasNoReturn);
+ else if (!ReturnsVoid)
+ S.Diag(Compound->getRBracLoc(),
+ CD.diag_AlwaysFallThrough_ReturnsNonVoid);
+ break;
+ case NeverFallThroughOrReturn:
+ if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
+ S.Diag(Compound->getLBracLoc(),
+ CD.diag_NeverFallThroughOrReturn);
+ break;
+ case NeverFallThrough:
+ break;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// -Wuninitialized
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct SLocSort {
+ bool operator()(const Expr *a, const Expr *b) {
+ SourceLocation aLoc = a->getLocStart();
+ SourceLocation bLoc = b->getLocStart();
+ return aLoc.getRawEncoding() < bLoc.getRawEncoding();
+ }
+};
+
+class UninitValsDiagReporter : public UninitVariablesHandler {
+ Sema &S;
+ typedef llvm::SmallVector<const Expr *, 2> UsesVec;
+ typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
+ UsesMap *uses;
+
+public:
+ UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
+ ~UninitValsDiagReporter() {
+ flushDiagnostics();
+ }
+
+ void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) {
+ if (!uses)
+ uses = new UsesMap();
+
+ UsesVec *&vec = (*uses)[vd];
+ if (!vec)
+ vec = new UsesVec();
+
+ vec->push_back(ex);
+ }
+
+ void flushDiagnostics() {
+ if (!uses)
+ return;
+
+ for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
+ const VarDecl *vd = i->first;
+ UsesVec *vec = i->second;
+
+ bool fixitIssued = false;
+
+ // Sort the uses by their SourceLocations. While not strictly
+ // guaranteed to produce them in line/column order, this will provide
+ // a stable ordering.
+ std::sort(vec->begin(), vec->end(), SLocSort());
+
+ for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
+ {
+ if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(*vi)) {
+ S.Diag(dr->getLocStart(), diag::warn_uninit_var)
+ << vd->getDeclName() << dr->getSourceRange();
+ }
+ else {
+ const BlockExpr *be = cast<BlockExpr>(*vi);
+ S.Diag(be->getLocStart(), diag::warn_uninit_var_captured_by_block)
+ << vd->getDeclName();
+ }
+
+ // Report where the variable was declared.
+ S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
+ << vd->getDeclName();
+
+ // Only report the fixit once.
+ if (fixitIssued)
+ continue;
+
+ fixitIssued = true;
+
+ // Suggest possible initialization (if any).
+ const char *initialization = 0;
+ QualType vdTy = vd->getType().getCanonicalType();
+
+ if (vdTy->getAs<ObjCObjectPointerType>()) {
+ // Check if 'nil' is defined.
+ if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
+ initialization = " = nil";
+ else
+ initialization = " = 0";
+ }
+ else if (vdTy->isRealFloatingType())
+ initialization = " = 0.0";
+ else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
+ initialization = " = false";
+ else if (vdTy->isEnumeralType())
+ continue;
+ else if (vdTy->isScalarType())
+ initialization = " = 0";
+
+ if (initialization) {
+ SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd());
+ S.Diag(loc, diag::note_var_fixit_add_initialization)
+ << FixItHint::CreateInsertion(loc, initialization);
+ }
+ }
+ delete vec;
+ }
+ delete uses;
+ }
+};
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
+// warnings on a function, method, or block.
+//===----------------------------------------------------------------------===//
+
+clang::sema::AnalysisBasedWarnings::Policy::Policy() {
+ enableCheckFallThrough = 1;
+ enableCheckUnreachable = 0;
+}
+
+clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
+ Diagnostic &D = S.getDiagnostics();
+ DefaultPolicy.enableCheckUnreachable = (unsigned)
+ (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
+ Diagnostic::Ignored);
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const Decl *D, QualType BlockTy) {
+
+ assert(BlockTy.isNull() || isa<BlockDecl>(D));
+
+ // We avoid doing analysis-based warnings when there are errors for
+ // two reasons:
+ // (1) The CFGs often can't be constructed (if the body is invalid), so
+ // don't bother trying.
+ // (2) The code already has problems; running the analysis just takes more
+ // time.
+ Diagnostic &Diags = S.getDiagnostics();
+
+ if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
+ return;
+
+ // Do not do any analysis for declarations in system headers if we are
+ // going to just ignore them.
+ if (Diags.getSuppressSystemWarnings() &&
+ S.SourceMgr.isInSystemHeader(D->getLocation()))
+ return;
+
+ // For code in dependent contexts, we'll do this at instantiation time.
+ if (cast<DeclContext>(D)->isDependentContext())
+ return;
+
+ const Stmt *Body = D->getBody();
+ assert(Body);
+
+ // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
+ // explosion for destrutors that can result and the compile time hit.
+ AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false,
+ /*addImplicitDtors=*/true, /*addInitializers=*/true);
+
+ // Warning: check missing 'return'
+ if (P.enableCheckFallThrough) {
+ const CheckFallThroughDiagnostics &CD =
+ (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
+ : CheckFallThroughDiagnostics::MakeForFunction(D));
+ CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
+ }
+
+ // Warning: check for unreachable code
+ if (P.enableCheckUnreachable)
+ CheckUnreachable(S, AC);
+
+ if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
+ != Diagnostic::Ignored) {
+ ASTContext &ctx = D->getASTContext();
+ llvm::OwningPtr<CFG> tmpCFG;
+ bool useAlternateCFG = false;
+ if (ctx.getLangOptions().CPlusPlus) {
+ // Temporary workaround: implicit dtors in the CFG can confuse
+ // the path-sensitivity in the uninitialized values analysis.
+ // For now create (if necessary) a separate CFG without implicit dtors.
+ // FIXME: We should not need to do this, as it results in multiple
+ // CFGs getting constructed.
+ CFG::BuildOptions B;
+ B.AddEHEdges = false;
+ B.AddImplicitDtors = false;
+ B.AddInitializers = true;
+ tmpCFG.reset(CFG::buildCFG(D, AC.getBody(), &ctx, B));
+ useAlternateCFG = true;
+ }
+ CFG *cfg = useAlternateCFG ? tmpCFG.get() : AC.getCFG();
+ if (cfg) {
+ UninitValsDiagReporter reporter(S);
+ runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
+ reporter);
+ }
+ }
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const BlockExpr *E) {
+ return IssueWarnings(P, E->getBlockDecl(), E->getType());
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const ObjCMethodDecl *D) {
+ return IssueWarnings(P, D, QualType());
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const FunctionDecl *D) {
+ return IssueWarnings(P, D, QualType());
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
new file mode 100644
index 0000000..c0a3053
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -0,0 +1,141 @@
+//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeList class implementation
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/AttributeList.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+AttributeList::AttributeList(llvm::BumpPtrAllocator &Alloc,
+ IdentifierInfo *aName, SourceLocation aLoc,
+ IdentifierInfo *sName, SourceLocation sLoc,
+ IdentifierInfo *pName, SourceLocation pLoc,
+ Expr **ExprList, unsigned numArgs,
+ bool declspec, bool cxx0x)
+ : AttrName(aName), AttrLoc(aLoc), ScopeName(sName),
+ ScopeLoc(sLoc),
+ ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(0),
+ DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false) {
+
+ if (numArgs == 0)
+ Args = 0;
+ else {
+ // Allocate the Args array using the BumpPtrAllocator.
+ Args = Alloc.Allocate<Expr*>(numArgs);
+ memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
+ }
+}
+
+AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
+ llvm::StringRef AttrName = Name->getName();
+
+ // Normalize the attribute name, __foo__ becomes foo.
+ if (AttrName.startswith("__") && AttrName.endswith("__"))
+ AttrName = AttrName.substr(2, AttrName.size() - 4);
+
+ return llvm::StringSwitch<AttributeList::Kind>(AttrName)
+ .Case("weak", AT_weak)
+ .Case("weakref", AT_weakref)
+ .Case("pure", AT_pure)
+ .Case("mode", AT_mode)
+ .Case("used", AT_used)
+ .Case("alias", AT_alias)
+ .Case("align", AT_aligned)
+ .Case("cdecl", AT_cdecl)
+ .Case("const", AT_const)
+ .Case("__const", AT_const) // some GCC headers do contain this spelling
+ .Case("blocks", AT_blocks)
+ .Case("format", AT_format)
+ .Case("malloc", AT_malloc)
+ .Case("packed", AT_packed)
+ .Case("unused", AT_unused)
+ .Case("aligned", AT_aligned)
+ .Case("cleanup", AT_cleanup)
+ .Case("naked", AT_naked)
+ .Case("nodebug", AT_nodebug)
+ .Case("nonnull", AT_nonnull)
+ .Case("nothrow", AT_nothrow)
+ .Case("objc_gc", AT_objc_gc)
+ .Case("regparm", AT_regparm)
+ .Case("section", AT_section)
+ .Case("stdcall", AT_stdcall)
+ .Case("annotate", AT_annotate)
+ .Case("fastcall", AT_fastcall)
+ .Case("ibaction", AT_IBAction)
+ .Case("iboutlet", AT_IBOutlet)
+ .Case("iboutletcollection", AT_IBOutletCollection)
+ .Case("noreturn", AT_noreturn)
+ .Case("noinline", AT_noinline)
+ .Case("sentinel", AT_sentinel)
+ .Case("NSObject", AT_nsobject)
+ .Case("dllimport", AT_dllimport)
+ .Case("dllexport", AT_dllexport)
+ .Case("may_alias", AT_may_alias)
+ .Case("base_check", AT_base_check)
+ .Case("deprecated", AT_deprecated)
+ .Case("visibility", AT_visibility)
+ .Case("destructor", AT_destructor)
+ .Case("format_arg", AT_format_arg)
+ .Case("gnu_inline", AT_gnu_inline)
+ .Case("weak_import", AT_weak_import)
+ .Case("vecreturn", AT_vecreturn)
+ .Case("vector_size", AT_vector_size)
+ .Case("constructor", AT_constructor)
+ .Case("unavailable", AT_unavailable)
+ .Case("overloadable", AT_overloadable)
+ .Case("address_space", AT_address_space)
+ .Case("always_inline", AT_always_inline)
+ .Case("returns_twice", IgnoredAttribute)
+ .Case("vec_type_hint", IgnoredAttribute)
+ .Case("objc_exception", AT_objc_exception)
+ .Case("ext_vector_type", AT_ext_vector_type)
+ .Case("neon_vector_type", AT_neon_vector_type)
+ .Case("neon_polyvector_type", AT_neon_polyvector_type)
+ .Case("transparent_union", AT_transparent_union)
+ .Case("analyzer_noreturn", AT_analyzer_noreturn)
+ .Case("warn_unused_result", AT_warn_unused_result)
+ .Case("carries_dependency", AT_carries_dependency)
+ .Case("ns_consumed", AT_ns_consumed)
+ .Case("ns_consumes_self", AT_ns_consumes_self)
+ .Case("ns_returns_autoreleased", AT_ns_returns_autoreleased)
+ .Case("ns_returns_not_retained", AT_ns_returns_not_retained)
+ .Case("ns_returns_retained", AT_ns_returns_retained)
+ .Case("cf_consumed", AT_cf_consumed)
+ .Case("cf_returns_not_retained", AT_cf_returns_not_retained)
+ .Case("cf_returns_retained", AT_cf_returns_retained)
+ .Case("ownership_returns", AT_ownership_returns)
+ .Case("ownership_holds", AT_ownership_holds)
+ .Case("ownership_takes", AT_ownership_takes)
+ .Case("reqd_work_group_size", AT_reqd_wg_size)
+ .Case("init_priority", AT_init_priority)
+ .Case("no_instrument_function", AT_no_instrument_function)
+ .Case("thiscall", AT_thiscall)
+ .Case("bounded", IgnoredAttribute) // OpenBSD
+ .Case("pascal", AT_pascal)
+ .Case("__cdecl", AT_cdecl)
+ .Case("__stdcall", AT_stdcall)
+ .Case("__fastcall", AT_fastcall)
+ .Case("__thiscall", AT_thiscall)
+ .Case("__pascal", AT_pascal)
+ .Case("constant", AT_constant)
+ .Case("device", AT_device)
+ .Case("global", AT_global)
+ .Case("host", AT_host)
+ .Case("shared", AT_shared)
+ .Case("launch_bounds", AT_launch_bounds)
+ .Case("common", AT_common)
+ .Case("nocommon", AT_nocommon)
+ .Case("opencl_kernel_function", AT_opencl_kernel_function)
+ .Case("uuid", AT_uuid)
+ .Default(UnknownAttribute);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
new file mode 100644
index 0000000..b7037ce
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -0,0 +1,460 @@
+//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeCompleteConsumer class.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang-c/Index.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+
+using namespace clang;
+using llvm::StringRef;
+
+//===----------------------------------------------------------------------===//
+// Code completion context implementation
+//===----------------------------------------------------------------------===//
+
+bool CodeCompletionContext::wantConstructorResults() const {
+ switch (Kind) {
+ case CCC_Recovery:
+ case CCC_Statement:
+ case CCC_Expression:
+ case CCC_ObjCMessageReceiver:
+ case CCC_ParenthesizedExpression:
+ return true;
+
+ case CCC_TopLevel:
+ case CCC_ObjCInterface:
+ case CCC_ObjCImplementation:
+ case CCC_ObjCIvarList:
+ case CCC_ClassStructUnion:
+ case CCC_MemberAccess:
+ case CCC_EnumTag:
+ case CCC_UnionTag:
+ case CCC_ClassOrStructTag:
+ case CCC_ObjCProtocolName:
+ case CCC_Namespace:
+ case CCC_Type:
+ case CCC_Name:
+ case CCC_PotentiallyQualifiedName:
+ case CCC_MacroName:
+ case CCC_MacroNameUse:
+ case CCC_PreprocessorExpression:
+ case CCC_PreprocessorDirective:
+ case CCC_NaturalLanguage:
+ case CCC_SelectorName:
+ case CCC_TypeQualifiers:
+ case CCC_Other:
+ case CCC_OtherWithMacros:
+ return false;
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion string implementation
+//===----------------------------------------------------------------------===//
+CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
+ : Kind(Kind), Text("")
+{
+ switch (Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_ResultType:
+ case CK_CurrentParameter:
+ this->Text = Text;
+ break;
+
+ case CK_Optional:
+ llvm_unreachable("Optional strings cannot be created from text");
+ break;
+
+ case CK_LeftParen:
+ this->Text = "(";
+ break;
+
+ case CK_RightParen:
+ this->Text = ")";
+ break;
+
+ case CK_LeftBracket:
+ this->Text = "[";
+ break;
+
+ case CK_RightBracket:
+ this->Text = "]";
+ break;
+
+ case CK_LeftBrace:
+ this->Text = "{";
+ break;
+
+ case CK_RightBrace:
+ this->Text = "}";
+ break;
+
+ case CK_LeftAngle:
+ this->Text = "<";
+ break;
+
+ case CK_RightAngle:
+ this->Text = ">";
+ break;
+
+ case CK_Comma:
+ this->Text = ", ";
+ break;
+
+ case CK_Colon:
+ this->Text = ":";
+ break;
+
+ case CK_SemiColon:
+ this->Text = ";";
+ break;
+
+ case CK_Equal:
+ this->Text = " = ";
+ break;
+
+ case CK_HorizontalSpace:
+ this->Text = " ";
+ break;
+
+ case CK_VerticalSpace:
+ this->Text = "\n";
+ break;
+ }
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateText(const char *Text) {
+ return Chunk(CK_Text, Text);
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
+ Chunk Result;
+ Result.Kind = CK_Optional;
+ Result.Optional = Optional;
+ return Result;
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
+ return Chunk(CK_Placeholder, Placeholder);
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
+ return Chunk(CK_Informative, Informative);
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
+ return Chunk(CK_ResultType, ResultType);
+}
+
+CodeCompletionString::Chunk
+CodeCompletionString::Chunk::CreateCurrentParameter(
+ const char *CurrentParameter) {
+ return Chunk(CK_CurrentParameter, CurrentParameter);
+}
+
+CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
+ unsigned NumChunks,
+ unsigned Priority,
+ CXAvailabilityKind Availability)
+ : NumChunks(NumChunks), Priority(Priority), Availability(Availability)
+{
+ Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
+ for (unsigned I = 0; I != NumChunks; ++I)
+ StoredChunks[I] = Chunks[I];
+}
+
+std::string CodeCompletionString::getAsString() const {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+ switch (C->Kind) {
+ case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
+ case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
+
+ case CK_Informative:
+ case CK_ResultType:
+ OS << "[#" << C->Text << "#]";
+ break;
+
+ case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
+ default: OS << C->Text; break;
+ }
+ }
+ return OS.str();
+}
+
+const char *CodeCompletionString::getTypedText() const {
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+ if (C->Kind == CK_TypedText)
+ return C->Text;
+
+ return 0;
+}
+
+const char *CodeCompletionAllocator::CopyString(llvm::StringRef String) {
+ char *Mem = (char *)Allocate(String.size() + 1, 1);
+ std::copy(String.begin(), String.end(), Mem);
+ Mem[String.size()] = 0;
+ return Mem;
+}
+
+const char *CodeCompletionAllocator::CopyString(llvm::Twine String) {
+ // FIXME: It would be more efficient to teach Twine to tell us its size and
+ // then add a routine there to fill in an allocated char* with the contents
+ // of the string.
+ llvm::SmallString<128> Data;
+ return CopyString(String.toStringRef(Data));
+}
+
+CodeCompletionString *CodeCompletionBuilder::TakeString() {
+ void *Mem = Allocator.Allocate(
+ sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size(),
+ llvm::alignOf<CodeCompletionString>());
+ CodeCompletionString *Result
+ = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
+ Priority, Availability);
+ Chunks.clear();
+ return Result;
+}
+
+unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
+ if (!ND)
+ return CCP_Unlikely;
+
+ // Context-based decisions.
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+ if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
+ // _cmd is relatively rare
+ if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
+ if (ImplicitParam->getIdentifier() &&
+ ImplicitParam->getIdentifier()->isStr("_cmd"))
+ return CCP_ObjC_cmd;
+
+ return CCP_LocalDeclaration;
+ }
+ if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
+ return CCP_MemberDeclaration;
+
+ // Content-based decisions.
+ if (isa<EnumConstantDecl>(ND))
+ return CCP_Constant;
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+ return CCP_Type;
+
+ return CCP_Declaration;
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion overload candidate implementation
+//===----------------------------------------------------------------------===//
+FunctionDecl *
+CodeCompleteConsumer::OverloadCandidate::getFunction() const {
+ if (getKind() == CK_Function)
+ return Function;
+ else if (getKind() == CK_FunctionTemplate)
+ return FunctionTemplate->getTemplatedDecl();
+ else
+ return 0;
+}
+
+const FunctionType *
+CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
+ switch (Kind) {
+ case CK_Function:
+ return Function->getType()->getAs<FunctionType>();
+
+ case CK_FunctionTemplate:
+ return FunctionTemplate->getTemplatedDecl()->getType()
+ ->getAs<FunctionType>();
+
+ case CK_FunctionType:
+ return Type;
+ }
+
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Code completion consumer implementation
+//===----------------------------------------------------------------------===//
+
+CodeCompleteConsumer::~CodeCompleteConsumer() { }
+
+void
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
+ std::stable_sort(Results, Results + NumResults);
+
+ // Print the results.
+ for (unsigned I = 0; I != NumResults; ++I) {
+ OS << "COMPLETION: ";
+ switch (Results[I].Kind) {
+ case CodeCompletionResult::RK_Declaration:
+ OS << Results[I].Declaration;
+ if (Results[I].Hidden)
+ OS << " (Hidden)";
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
+ OS << " : " << CCS->getAsString();
+ }
+
+ OS << '\n';
+ break;
+
+ case CodeCompletionResult::RK_Keyword:
+ OS << Results[I].Keyword << '\n';
+ break;
+
+ case CodeCompletionResult::RK_Macro: {
+ OS << Results[I].Macro->getName();
+ if (CodeCompletionString *CCS
+ = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
+ OS << " : " << CCS->getAsString();
+ }
+ OS << '\n';
+ break;
+ }
+
+ case CodeCompletionResult::RK_Pattern: {
+ OS << "Pattern : "
+ << Results[I].Pattern->getAsString() << '\n';
+ break;
+ }
+ }
+ }
+}
+
+void
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+ unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) {
+ for (unsigned I = 0; I != NumCandidates; ++I) {
+ if (CodeCompletionString *CCS
+ = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
+ Allocator)) {
+ OS << "OVERLOAD: " << CCS->getAsString() << "\n";
+ }
+ }
+}
+
+void CodeCompletionResult::computeCursorKindAndAvailability() {
+ switch (Kind) {
+ case RK_Declaration:
+ // Set the availability based on attributes.
+ Availability = CXAvailability_Available;
+ if (Declaration->getAttr<UnavailableAttr>())
+ Availability = CXAvailability_NotAvailable;
+ else if (Declaration->getAttr<DeprecatedAttr>())
+ Availability = CXAvailability_Deprecated;
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
+ if (Function->isDeleted())
+ Availability = CXAvailability_NotAvailable;
+
+ CursorKind = getCursorKindForDecl(Declaration);
+ if (CursorKind == CXCursor_UnexposedDecl)
+ CursorKind = CXCursor_NotImplemented;
+ break;
+
+ case RK_Macro:
+ Availability = CXAvailability_Available;
+ CursorKind = CXCursor_MacroDefinition;
+ break;
+
+ case RK_Keyword:
+ Availability = CXAvailability_Available;
+ CursorKind = CXCursor_NotImplemented;
+ break;
+
+ case RK_Pattern:
+ // Do nothing: Patterns can come with cursor kinds!
+ break;
+ }
+}
+
+/// \brief Retrieve the name that should be used to order a result.
+///
+/// If the name needs to be constructed as a string, that string will be
+/// saved into Saved and the returned StringRef will refer to it.
+static llvm::StringRef getOrderedName(const CodeCompletionResult &R,
+ std::string &Saved) {
+ switch (R.Kind) {
+ case CodeCompletionResult::RK_Keyword:
+ return R.Keyword;
+
+ case CodeCompletionResult::RK_Pattern:
+ return R.Pattern->getTypedText();
+
+ case CodeCompletionResult::RK_Macro:
+ return R.Macro->getName();
+
+ case CodeCompletionResult::RK_Declaration:
+ // Handle declarations below.
+ break;
+ }
+
+ DeclarationName Name = R.Declaration->getDeclName();
+
+ // If the name is a simple identifier (by far the common case), or a
+ // zero-argument selector, just return a reference to that identifier.
+ if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
+ return Id->getName();
+ if (Name.isObjCZeroArgSelector())
+ if (IdentifierInfo *Id
+ = Name.getObjCSelector().getIdentifierInfoForSlot(0))
+ return Id->getName();
+
+ Saved = Name.getAsString();
+ return Saved;
+}
+
+bool clang::operator<(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ std::string XSaved, YSaved;
+ llvm::StringRef XStr = getOrderedName(X, XSaved);
+ llvm::StringRef YStr = getOrderedName(Y, YSaved);
+ int cmp = XStr.compare_lower(YStr);
+ if (cmp)
+ return cmp < 0;
+
+ // If case-insensitive comparison fails, try case-sensitive comparison.
+ cmp = XStr.compare(YStr);
+ if (cmp)
+ return cmp < 0;
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
new file mode 100644
index 0000000..bc289ec
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -0,0 +1,747 @@
+//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for declaration specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstring>
+using namespace clang;
+
+
+static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
+ unsigned DiagID) {
+ return D.Report(Loc, DiagID);
+}
+
+
+void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_TemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+}
+
+void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id annotation?");
+ Kind = IK_ConstructorTemplateId;
+ this->TemplateId = TemplateId;
+ StartLocation = TemplateId->TemplateNameLoc;
+ EndLocation = TemplateId->RAngleLoc;
+}
+
+/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+/// "TheDeclarator" is the declarator that this will be added to.
+DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
+ bool hasProto, bool isVariadic,
+ SourceLocation EllipsisLoc,
+ ParamInfo *ArgInfo,
+ unsigned NumArgs,
+ unsigned TypeQuals,
+ bool RefQualifierIsLvalueRef,
+ SourceLocation RefQualifierLoc,
+ bool hasExceptionSpec,
+ SourceLocation ThrowLoc,
+ bool hasAnyExceptionSpec,
+ ParsedType *Exceptions,
+ SourceRange *ExceptionRanges,
+ unsigned NumExceptions,
+ SourceLocation LPLoc,
+ SourceLocation RPLoc,
+ Declarator &TheDeclarator,
+ ParsedType TrailingReturnType) {
+ DeclaratorChunk I;
+ I.Kind = Function;
+ I.Loc = LPLoc;
+ I.EndLoc = RPLoc;
+ I.Fun.AttrList = attrs.getList();
+ I.Fun.hasPrototype = hasProto;
+ I.Fun.isVariadic = isVariadic;
+ I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ I.Fun.DeleteArgInfo = false;
+ I.Fun.TypeQuals = TypeQuals;
+ I.Fun.NumArgs = NumArgs;
+ I.Fun.ArgInfo = 0;
+ I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
+ I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
+ I.Fun.hasExceptionSpec = hasExceptionSpec;
+ I.Fun.ThrowLoc = ThrowLoc.getRawEncoding();
+ I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
+ I.Fun.NumExceptions = NumExceptions;
+ I.Fun.Exceptions = 0;
+ I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr();
+
+ // new[] an argument array if needed.
+ if (NumArgs) {
+ // If the 'InlineParams' in Declarator is unused and big enough, put our
+ // parameter list there (in an effort to avoid new/delete traffic). If it
+ // is already used (consider a function returning a function pointer) or too
+ // small (function taking too many arguments), go to the heap.
+ if (!TheDeclarator.InlineParamsUsed &&
+ NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
+ I.Fun.ArgInfo = TheDeclarator.InlineParams;
+ I.Fun.DeleteArgInfo = false;
+ TheDeclarator.InlineParamsUsed = true;
+ } else {
+ I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
+ I.Fun.DeleteArgInfo = true;
+ }
+ memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
+ }
+ // new[] an exception array if needed
+ if (NumExceptions) {
+ I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
+ for (unsigned i = 0; i != NumExceptions; ++i) {
+ I.Fun.Exceptions[i].Ty = Exceptions[i];
+ I.Fun.Exceptions[i].Range = ExceptionRanges[i];
+ }
+ }
+ return I;
+}
+
+/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+/// declaration specifier includes.
+///
+unsigned DeclSpec::getParsedSpecifiers() const {
+ unsigned Res = 0;
+ if (StorageClassSpec != SCS_unspecified ||
+ SCS_thread_specified)
+ Res |= PQ_StorageClassSpecifier;
+
+ if (TypeQualifiers != TQ_unspecified)
+ Res |= PQ_TypeQualifier;
+
+ if (hasTypeSpecifier())
+ Res |= PQ_TypeSpecifier;
+
+ if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
+ Res |= PQ_FunctionSpecifier;
+ return Res;
+}
+
+template <class T> static bool BadSpecifier(T TNew, T TPrev,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ PrevSpec = DeclSpec::getSpecifierName(TPrev);
+ DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
+ : diag::err_invalid_decl_spec_combination);
+ return true;
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
+ switch (S) {
+ case DeclSpec::SCS_unspecified: return "unspecified";
+ case DeclSpec::SCS_typedef: return "typedef";
+ case DeclSpec::SCS_extern: return "extern";
+ case DeclSpec::SCS_static: return "static";
+ case DeclSpec::SCS_auto: return "auto";
+ case DeclSpec::SCS_register: return "register";
+ case DeclSpec::SCS_private_extern: return "__private_extern__";
+ case DeclSpec::SCS_mutable: return "mutable";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSW W) {
+ switch (W) {
+ case TSW_unspecified: return "unspecified";
+ case TSW_short: return "short";
+ case TSW_long: return "long";
+ case TSW_longlong: return "long long";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TSC C) {
+ switch (C) {
+ case TSC_unspecified: return "unspecified";
+ case TSC_imaginary: return "imaginary";
+ case TSC_complex: return "complex";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+
+const char *DeclSpec::getSpecifierName(TSS S) {
+ switch (S) {
+ case TSS_unspecified: return "unspecified";
+ case TSS_signed: return "signed";
+ case TSS_unsigned: return "unsigned";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
+ switch (T) {
+ case DeclSpec::TST_unspecified: return "unspecified";
+ case DeclSpec::TST_void: return "void";
+ case DeclSpec::TST_char: return "char";
+ case DeclSpec::TST_wchar: return "wchar_t";
+ case DeclSpec::TST_char16: return "char16_t";
+ case DeclSpec::TST_char32: return "char32_t";
+ case DeclSpec::TST_int: return "int";
+ case DeclSpec::TST_float: return "float";
+ case DeclSpec::TST_double: return "double";
+ case DeclSpec::TST_bool: return "_Bool";
+ case DeclSpec::TST_decimal32: return "_Decimal32";
+ case DeclSpec::TST_decimal64: return "_Decimal64";
+ case DeclSpec::TST_decimal128: return "_Decimal128";
+ case DeclSpec::TST_enum: return "enum";
+ case DeclSpec::TST_class: return "class";
+ case DeclSpec::TST_union: return "union";
+ case DeclSpec::TST_struct: return "struct";
+ case DeclSpec::TST_typename: return "type-name";
+ case DeclSpec::TST_typeofType:
+ case DeclSpec::TST_typeofExpr: return "typeof";
+ case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_decltype: return "(decltype)";
+ case DeclSpec::TST_error: return "(error)";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+const char *DeclSpec::getSpecifierName(TQ T) {
+ switch (T) {
+ case DeclSpec::TQ_unspecified: return "unspecified";
+ case DeclSpec::TQ_const: return "const";
+ case DeclSpec::TQ_restrict: return "restrict";
+ case DeclSpec::TQ_volatile: return "volatile";
+ }
+ llvm_unreachable("Unknown typespec!");
+}
+
+bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ const LangOptions &Lang) {
+ // OpenCL prohibits extern, auto, register, and static
+ // It seems sensible to prohibit private_extern too
+ if (Lang.OpenCL) {
+ switch (S) {
+ case SCS_extern:
+ case SCS_private_extern:
+ case SCS_auto:
+ case SCS_register:
+ case SCS_static:
+ DiagID = diag::err_not_opencl_storage_class_specifier;
+ PrevSpec = getSpecifierName(S);
+ return true;
+ default:
+ break;
+ }
+ }
+
+ if (StorageClassSpec != SCS_unspecified) {
+ // Changing storage class is allowed only if the previous one
+ // was the 'extern' that is part of a linkage specification and
+ // the new storage class is 'typedef'.
+ if (!(SCS_extern_in_linkage_spec &&
+ StorageClassSpec == SCS_extern &&
+ S == SCS_typedef))
+ return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+ }
+ StorageClassSpec = S;
+ StorageClassSpecLoc = Loc;
+ assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
+ return false;
+}
+
+bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (SCS_thread_specified) {
+ PrevSpec = "__thread";
+ DiagID = diag::ext_duplicate_declspec;
+ return true;
+ }
+ SCS_thread_specified = true;
+ SCS_threadLoc = Loc;
+ return false;
+}
+
+/// These methods set the specified attribute of the DeclSpec, but return true
+/// and ignore the request if invalid (e.g. "extern" then "auto" is
+/// specified).
+bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (TypeSpecWidth != TSW_unspecified &&
+ // Allow turning long -> long long.
+ (W != TSW_longlong || TypeSpecWidth != TSW_long))
+ return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
+ TypeSpecWidth = W;
+ TSWLoc = Loc;
+ if (TypeAltiVecVector && !TypeAltiVecBool &&
+ ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::warn_vector_long_decl_spec_combination;
+ return true;
+ }
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (TypeSpecComplex != TSC_unspecified)
+ return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
+ TypeSpecComplex = C;
+ TSCLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (TypeSpecSign != TSS_unspecified)
+ return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
+ TypeSpecSign = S;
+ TSSLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ ParsedType Rep) {
+ assert(isTypeRep(T) && "T does not store a type");
+ assert(Rep && "no type provided!");
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ TypeRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = false;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ Expr *Rep) {
+ assert(isExprRep(T) && "T does not store an expr");
+ assert(Rep && "no expression provided!");
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ ExprRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = false;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ Decl *Rep, bool Owned) {
+ assert(isDeclRep(T) && "T does not store a decl");
+ // Unlike the other cases, we don't assert that we actually get a decl.
+
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ DeclRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = Owned;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
+ "rep required for these type-spec kinds!");
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
+ TypeAltiVecBool = true;
+ TSTLoc = Loc;
+ return false;
+ }
+ TypeSpecType = T;
+ TSTLoc = Loc;
+ TypeSpecOwned = false;
+ if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_vector_decl_spec;
+ return true;
+ }
+ return false;
+}
+
+bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID) {
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_vector_decl_spec_combination;
+ return true;
+ }
+ TypeAltiVecVector = isAltiVecVector;
+ AltiVecLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID) {
+ if (!TypeAltiVecVector || TypeAltiVecPixel ||
+ (TypeSpecType != TST_unspecified)) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_pixel_decl_spec_combination;
+ return true;
+ }
+ TypeAltiVecPixel = isAltiVecPixel;
+ TSTLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecError() {
+ TypeSpecType = TST_error;
+ TypeSpecOwned = false;
+ TSTLoc = SourceLocation();
+ return false;
+}
+
+bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const LangOptions &Lang) {
+ // Duplicates turn into warnings pre-C99.
+ if ((TypeQualifiers & T) && !Lang.C99)
+ return BadSpecifier(T, T, PrevSpec, DiagID);
+ TypeQualifiers |= T;
+
+ switch (T) {
+ default: assert(0 && "Unknown type qualifier!");
+ case TQ_const: TQ_constLoc = Loc; break;
+ case TQ_restrict: TQ_restrictLoc = Loc; break;
+ case TQ_volatile: TQ_volatileLoc = Loc; break;
+ }
+ return false;
+}
+
+bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'inline inline' is ok.
+ FS_inline_specified = true;
+ FS_inlineLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'virtual virtual' is ok.
+ FS_virtual_specified = true;
+ FS_virtualLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'explicit explicit' is ok.
+ FS_explicit_specified = true;
+ FS_explicitLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ if (Friend_specified) {
+ PrevSpec = "friend";
+ DiagID = diag::ext_duplicate_declspec;
+ return true;
+ }
+
+ Friend_specified = true;
+ FriendLoc = Loc;
+ return false;
+}
+
+bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
+ // 'constexpr constexpr' is ok.
+ Constexpr_specified = true;
+ ConstexprLoc = Loc;
+ return false;
+}
+
+void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
+ unsigned NP,
+ SourceLocation *ProtoLocs,
+ SourceLocation LAngleLoc) {
+ if (NP == 0) return;
+ ProtocolQualifiers = new Decl*[NP];
+ ProtocolLocs = new SourceLocation[NP];
+ memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP);
+ memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
+ NumProtocolQualifiers = NP;
+ ProtocolLAngleLoc = LAngleLoc;
+}
+
+void DeclSpec::SaveWrittenBuiltinSpecs() {
+ writtenBS.Sign = getTypeSpecSign();
+ writtenBS.Width = getTypeSpecWidth();
+ writtenBS.Type = getTypeSpecType();
+ // Search the list of attributes for the presence of a mode attribute.
+ writtenBS.ModeAttr = false;
+ AttributeList* attrs = getAttributes().getList();
+ while (attrs) {
+ if (attrs->getKind() == AttributeList::AT_mode) {
+ writtenBS.ModeAttr = true;
+ break;
+ }
+ attrs = attrs->getNext();
+ }
+}
+
+void DeclSpec::SaveStorageSpecifierAsWritten() {
+ if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
+ // If 'extern' is part of a linkage specification,
+ // then it is not a storage class "as written".
+ StorageClassSpecAsWritten = SCS_unspecified;
+ else
+ StorageClassSpecAsWritten = StorageClassSpec;
+}
+
+/// Finish - This does final analysis of the declspec, rejecting things like
+/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
+/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
+/// DeclSpec is guaranteed self-consistent, even if an error occurred.
+void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
+ // Before possibly changing their values, save specs as written.
+ SaveWrittenBuiltinSpecs();
+ SaveStorageSpecifierAsWritten();
+
+ // Check the type specifier components first.
+
+ // Validate and finalize AltiVec vector declspec.
+ if (TypeAltiVecVector) {
+ if (TypeAltiVecBool) {
+ // Sign specifiers are not allowed with vector bool. (PIM 2.1)
+ if (TypeSpecSign != TSS_unspecified) {
+ Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
+ << getSpecifierName((TSS)TypeSpecSign);
+ }
+
+ // Only char/int are valid with vector bool. (PIM 2.1)
+ if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
+ (TypeSpecType != TST_int)) || TypeAltiVecPixel) {
+ Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
+ << (TypeAltiVecPixel ? "__pixel" :
+ getSpecifierName((TST)TypeSpecType));
+ }
+
+ // Only 'short' is valid with vector bool. (PIM 2.1)
+ if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
+ Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
+ << getSpecifierName((TSW)TypeSpecWidth);
+
+ // Elements of vector bool are interpreted as unsigned. (PIM 2.1)
+ if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
+ (TypeSpecWidth != TSW_unspecified))
+ TypeSpecSign = TSS_unsigned;
+ }
+
+ if (TypeAltiVecPixel) {
+ //TODO: perform validation
+ TypeSpecType = TST_int;
+ TypeSpecSign = TSS_unsigned;
+ TypeSpecWidth = TSW_short;
+ TypeSpecOwned = false;
+ }
+ }
+
+ // signed/unsigned are only valid with int/char/wchar_t.
+ if (TypeSpecSign != TSS_unspecified) {
+ if (TypeSpecType == TST_unspecified)
+ TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
+ else if (TypeSpecType != TST_int &&
+ TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
+ Diag(D, TSSLoc, diag::err_invalid_sign_spec)
+ << getSpecifierName((TST)TypeSpecType);
+ // signed double -> double.
+ TypeSpecSign = TSS_unspecified;
+ }
+ }
+
+ // Validate the width of the type.
+ switch (TypeSpecWidth) {
+ case TSW_unspecified: break;
+ case TSW_short: // short int
+ case TSW_longlong: // long long int
+ if (TypeSpecType == TST_unspecified)
+ TypeSpecType = TST_int; // short -> short int, long long -> long long int.
+ else if (TypeSpecType != TST_int) {
+ Diag(D, TSWLoc,
+ TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
+ : diag::err_invalid_longlong_spec)
+ << getSpecifierName((TST)TypeSpecType);
+ TypeSpecType = TST_int;
+ TypeSpecOwned = false;
+ }
+ break;
+ case TSW_long: // long double, long int
+ if (TypeSpecType == TST_unspecified)
+ TypeSpecType = TST_int; // long -> long int.
+ else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
+ Diag(D, TSWLoc, diag::err_invalid_long_spec)
+ << getSpecifierName((TST)TypeSpecType);
+ TypeSpecType = TST_int;
+ TypeSpecOwned = false;
+ }
+ break;
+ }
+
+ // TODO: if the implementation does not implement _Complex or _Imaginary,
+ // disallow their use. Need information about the backend.
+ if (TypeSpecComplex != TSC_unspecified) {
+ if (TypeSpecType == TST_unspecified) {
+ Diag(D, TSCLoc, diag::ext_plain_complex)
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
+ " double");
+ TypeSpecType = TST_double; // _Complex -> _Complex double.
+ } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
+ // Note that this intentionally doesn't include _Complex _Bool.
+ Diag(D, TSTLoc, diag::ext_integer_complex);
+ } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
+ Diag(D, TSCLoc, diag::err_invalid_complex_spec)
+ << getSpecifierName((TST)TypeSpecType);
+ TypeSpecComplex = TSC_unspecified;
+ }
+ }
+
+ // C++ [class.friend]p6:
+ // No storage-class-specifier shall appear in the decl-specifier-seq
+ // of a friend declaration.
+ if (isFriendSpecified() && getStorageClassSpec()) {
+ DeclSpec::SCS SC = getStorageClassSpec();
+ const char *SpecName = getSpecifierName(SC);
+
+ SourceLocation SCLoc = getStorageClassSpecLoc();
+ SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
+
+ Diag(D, SCLoc, diag::err_friend_storage_spec)
+ << SpecName
+ << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
+
+ ClearStorageClassSpecs();
+ }
+
+ assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
+
+ // Okay, now we can infer the real type.
+
+ // TODO: return "auto function" and other bad things based on the real type.
+
+ // 'data definition has no type or storage class'?
+}
+
+bool DeclSpec::isMissingDeclaratorOk() {
+ TST tst = getTypeSpecType();
+ return isDeclRep(tst) && getRepAsDecl() != 0 &&
+ StorageClassSpec != DeclSpec::SCS_typedef;
+}
+
+void UnqualifiedId::clear() {
+ if (Kind == IK_TemplateId)
+ TemplateId->Destroy();
+
+ Kind = IK_Identifier;
+ Identifier = 0;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]) {
+ Kind = IK_OperatorFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = OperatorLoc;
+ OperatorFunctionId.Operator = Op;
+ for (unsigned I = 0; I != 3; ++I) {
+ OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+
+ if (SymbolLocations[I].isValid())
+ EndLocation = SymbolLocations[I];
+ }
+}
+
+bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
+ const char *&PrevSpec) {
+ if (Specifiers & VS) {
+ PrevSpec = getSpecifierName(VS);
+ return true;
+ }
+
+ Specifiers |= VS;
+
+ switch (VS) {
+ default: assert(0 && "Unknown specifier!");
+ case VS_Override: VS_overrideLoc = Loc; break;
+ case VS_Final: VS_finalLoc = Loc; break;
+ case VS_New: VS_newLoc = Loc; break;
+ }
+
+ return false;
+}
+
+const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
+ switch (VS) {
+ default: assert(0 && "Unknown specifier");
+ case VS_Override: return "override";
+ case VS_Final: return "final";
+ case VS_New: return "new";
+ }
+}
+
+bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc,
+ const char *&PrevSpec) {
+ if (Specifiers & CVS) {
+ PrevSpec = getSpecifierName(CVS);
+ return true;
+ }
+
+ Specifiers |= CVS;
+
+ switch (CVS) {
+ default: assert(0 && "Unknown specifier!");
+ case CVS_Final: CVS_finalLoc = Loc; break;
+ case CVS_Explicit: CVS_explicitLoc = Loc; break;
+ }
+
+ return false;
+}
+
+const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) {
+ switch (CVS) {
+ default: assert(0 && "Unknown specifier");
+ case CVS_Final: return "final";
+ case CVS_Explicit: return "explicit";
+ }
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
new file mode 100644
index 0000000..3f16ed7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp
@@ -0,0 +1,288 @@
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap class
+//===----------------------------------------------------------------------===//
+
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
+/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
+/// individual IdDeclInfo to heap.
+class IdentifierResolver::IdDeclInfoMap {
+ static const unsigned int POOL_SIZE = 512;
+
+ /// We use our own linked-list implementation because it is sadly
+ /// impossible to add something to a pre-C++0x STL container without
+ /// a completely unnecessary copy.
+ struct IdDeclInfoPool {
+ IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
+
+ IdDeclInfoPool *Next;
+ IdDeclInfo Pool[POOL_SIZE];
+ };
+
+ IdDeclInfoPool *CurPool;
+ unsigned int CurIndex;
+
+public:
+ IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+
+ ~IdDeclInfoMap() {
+ IdDeclInfoPool *Cur = CurPool;
+ while (IdDeclInfoPool *P = Cur) {
+ Cur = Cur->Next;
+ delete P;
+ }
+ }
+
+ /// Returns the IdDeclInfo associated to the DeclarationName.
+ /// It creates a new IdDeclInfo if one was not created before for this id.
+ IdDeclInfo &operator[](DeclarationName Name);
+};
+
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfo Implementation
+//===----------------------------------------------------------------------===//
+
+/// RemoveDecl - Remove the decl from the scope chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (D == *(I-1)) {
+ Decls.erase(I-1);
+ return;
+ }
+ }
+
+ assert(0 && "Didn't find this decl on its identifier's chain!");
+}
+
+bool
+IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (Old == *(I-1)) {
+ *(I - 1) = New;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// IdentifierResolver Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
+ : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
+}
+IdentifierResolver::~IdentifierResolver() {
+ delete IdDeclInfos;
+}
+
+/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+/// true if 'D' belongs to the given declaration context.
+bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
+ ASTContext &Context, Scope *S) const {
+ Ctx = Ctx->getRedeclContext();
+
+ if (Ctx->isFunctionOrMethod()) {
+ // Ignore the scopes associated within transparent declaration contexts.
+ while (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext())
+ S = S->getParent();
+
+ if (S->isDeclScope(D))
+ return true;
+ if (LangOpt.CPlusPlus) {
+ // C++ 3.3.2p3:
+ // The name declared in a catch exception-declaration is local to the
+ // handler and shall not be redeclared in the outermost block of the
+ // handler.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement), and shall not be
+ // redeclared in a subsequent condition of that statement nor in the
+ // outermost block (or, for the if statement, any of the outermost blocks)
+ // of the controlled statement.
+ //
+ assert(S->getParent() && "No TUScope?");
+ if (S->getParent()->getFlags() & Scope::ControlScope)
+ return S->getParent()->isDeclScope(D);
+ }
+ return false;
+ }
+
+ return D->getDeclContext()->getRedeclContext()->Equals(Ctx);
+}
+
+/// AddDecl - Link the decl to its shadowed decl chain.
+void IdentifierResolver::AddDecl(NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr) {
+ Name.setFETokenInfo(D);
+ return;
+ }
+
+ IdDeclInfo *IDI;
+
+ if (isDeclPtr(Ptr)) {
+ Name.setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[Name];
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ IDI->AddDecl(PrevD);
+ } else
+ IDI = toIdDeclInfo(Ptr);
+
+ IDI->AddDecl(D);
+}
+
+/// RemoveDecl - Unlink the decl from its shadowed decl chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::RemoveDecl(NamedDecl *D) {
+ assert(D && "null param passed");
+ DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ assert(Ptr && "Didn't find this decl on its identifier's chain!");
+
+ if (isDeclPtr(Ptr)) {
+ assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
+ Name.setFETokenInfo(NULL);
+ return;
+ }
+
+ return toIdDeclInfo(Ptr)->RemoveDecl(D);
+}
+
+bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+ assert(Old->getDeclName() == New->getDeclName() &&
+ "Cannot replace a decl with another decl of a different name");
+
+ DeclarationName Name = Old->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr)
+ return false;
+
+ if (isDeclPtr(Ptr)) {
+ if (Ptr == Old) {
+ Name.setFETokenInfo(New);
+ return true;
+ }
+ return false;
+ }
+
+ return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
+}
+
+/// begin - Returns an iterator for decls with name 'Name'.
+IdentifierResolver::iterator
+IdentifierResolver::begin(DeclarationName Name) {
+ void *Ptr = Name.getFETokenInfo<void>();
+ if (!Ptr) return end();
+
+ if (isDeclPtr(Ptr))
+ return iterator(static_cast<NamedDecl*>(Ptr));
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+
+ IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
+ if (I != IDI->decls_begin())
+ return iterator(I-1);
+ // No decls found.
+ return end();
+}
+
+void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II,
+ NamedDecl *D) {
+ II->setIsFromAST(false);
+ void *Ptr = II->getFETokenInfo<void>();
+
+ if (!Ptr) {
+ II->setFETokenInfo(D);
+ return;
+ }
+
+ IdDeclInfo *IDI;
+
+ if (isDeclPtr(Ptr)) {
+ II->setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[II];
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ IDI->AddDecl(PrevD);
+ } else
+ IDI = toIdDeclInfo(Ptr);
+
+ IDI->AddDecl(D);
+}
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap Implementation
+//===----------------------------------------------------------------------===//
+
+/// Returns the IdDeclInfo associated to the DeclarationName.
+/// It creates a new IdDeclInfo if one was not created before for this id.
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (Ptr) return *toIdDeclInfo(Ptr);
+
+ if (CurIndex == POOL_SIZE) {
+ CurPool = new IdDeclInfoPool(CurPool);
+ CurIndex = 0;
+ }
+ IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
+ Name.setFETokenInfo(reinterpret_cast<void*>(
+ reinterpret_cast<uintptr_t>(IDI) | 0x1)
+ );
+ ++CurIndex;
+ return *IDI;
+}
+
+void IdentifierResolver::iterator::incrementSlowCase() {
+ NamedDecl *D = **this;
+ void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+ assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+ IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+
+ BaseIter I = getIterator();
+ if (I != Info->decls_begin())
+ *this = iterator(I-1);
+ else // No more decls.
+ *this = iterator();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
new file mode 100644
index 0000000..b73f0e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -0,0 +1,570 @@
+//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the JumpScopeChecker class, which is used to diagnose
+// jumps that enter a VLA scope in an invalid way.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "llvm/ADT/BitVector.h"
+using namespace clang;
+
+namespace {
+
+/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
+/// into VLA and other protected scopes. For example, this rejects:
+/// goto L;
+/// int a[n];
+/// L:
+///
+class JumpScopeChecker {
+ Sema &S;
+
+ /// GotoScope - This is a record that we use to keep track of all of the
+ /// scopes that are introduced by VLAs and other things that scope jumps like
+ /// gotos. This scope tree has nothing to do with the source scope tree,
+ /// because you can have multiple VLA scopes per compound statement, and most
+ /// compound statements don't introduce any scopes.
+ struct GotoScope {
+ /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for
+ /// the parent scope is the function body.
+ unsigned ParentScope;
+
+ /// InDiag - The diagnostic to emit if there is a jump into this scope.
+ unsigned InDiag;
+
+ /// OutDiag - The diagnostic to emit if there is an indirect jump out
+ /// of this scope. Direct jumps always clean up their current scope
+ /// in an orderly way.
+ unsigned OutDiag;
+
+ /// Loc - Location to emit the diagnostic.
+ SourceLocation Loc;
+
+ GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag,
+ SourceLocation L)
+ : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {}
+ };
+
+ llvm::SmallVector<GotoScope, 48> Scopes;
+ llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
+ llvm::SmallVector<Stmt*, 16> Jumps;
+
+ llvm::SmallVector<IndirectGotoStmt*, 4> IndirectJumps;
+ llvm::SmallVector<LabelDecl*, 4> IndirectJumpTargets;
+public:
+ JumpScopeChecker(Stmt *Body, Sema &S);
+private:
+ void BuildScopeInformation(Decl *D, unsigned &ParentScope);
+ void BuildScopeInformation(Stmt *S, unsigned ParentScope);
+ void VerifyJumps();
+ void VerifyIndirectJumps();
+ void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope,
+ LabelDecl *Target, unsigned TargetScope);
+ void CheckJump(Stmt *From, Stmt *To,
+ SourceLocation DiagLoc, unsigned JumpDiag);
+
+ unsigned GetDeepestCommonScope(unsigned A, unsigned B);
+};
+} // end anonymous namespace
+
+
+JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
+ // Add a scope entry for function scope.
+ Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
+
+ // Build information for the top level compound statement, so that we have a
+ // defined scope record for every "goto" and label.
+ BuildScopeInformation(Body, 0);
+
+ // Check that all jumps we saw are kosher.
+ VerifyJumps();
+ VerifyIndirectJumps();
+}
+
+/// GetDeepestCommonScope - Finds the innermost scope enclosing the
+/// two scopes.
+unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) {
+ while (A != B) {
+ // Inner scopes are created after outer scopes and therefore have
+ // higher indices.
+ if (A < B) {
+ assert(Scopes[B].ParentScope < B);
+ B = Scopes[B].ParentScope;
+ } else {
+ assert(Scopes[A].ParentScope < A);
+ A = Scopes[A].ParentScope;
+ }
+ }
+ return A;
+}
+
+/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
+/// diagnostic that should be emitted if control goes over it. If not, return 0.
+static std::pair<unsigned,unsigned>
+ GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ unsigned InDiag = 0, OutDiag = 0;
+ if (VD->getType()->isVariablyModifiedType())
+ InDiag = diag::note_protected_by_vla;
+
+ if (VD->hasAttr<BlocksAttr>()) {
+ InDiag = diag::note_protected_by___block;
+ OutDiag = diag::note_exits___block;
+ } else if (VD->hasAttr<CleanupAttr>()) {
+ InDiag = diag::note_protected_by_cleanup;
+ OutDiag = diag::note_exits_cleanup;
+ } else if (isCPlusPlus) {
+ // FIXME: In C++0x, we have to check more conditions than "did we
+ // just give it an initializer?". See 6.7p3.
+ if (VD->hasLocalStorage() && VD->hasInit())
+ InDiag = diag::note_protected_by_variable_init;
+
+ CanQualType T = VD->getType()->getCanonicalTypeUnqualified();
+ if (!T->isDependentType()) {
+ while (CanQual<ArrayType> AT = T->getAs<ArrayType>())
+ T = AT->getElementType();
+ if (CanQual<RecordType> RT = T->getAs<RecordType>())
+ if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
+ OutDiag = diag::note_exits_dtor;
+ }
+ }
+
+ return std::make_pair(InDiag, OutDiag);
+ }
+
+ if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ if (TD->getUnderlyingType()->isVariablyModifiedType())
+ return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0);
+ }
+
+ return std::make_pair(0U, 0U);
+}
+
+/// \brief Build scope information for a declaration that is part of a DeclStmt.
+void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
+ bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;
+
+ // If this decl causes a new scope, push and switch to it.
+ std::pair<unsigned,unsigned> Diags
+ = GetDiagForGotoScopeDecl(D, isCPlusPlus);
+ if (Diags.first || Diags.second) {
+ Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
+ D->getLocation()));
+ ParentScope = Scopes.size()-1;
+ }
+
+ // If the decl has an initializer, walk it with the potentially new
+ // scope we just installed.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (Expr *Init = VD->getInit())
+ BuildScopeInformation(Init, ParentScope);
+}
+
+/// BuildScopeInformation - The statements from CI to CE are known to form a
+/// coherent VLA scope with a specified parent node. Walk through the
+/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
+/// walking the AST as needed.
+void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
+ bool SkipFirstSubStmt = false;
+
+ // If we found a label, remember that it is in ParentScope scope.
+ switch (S->getStmtClass()) {
+ case Stmt::AddrLabelExprClass:
+ IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
+ break;
+
+ case Stmt::IndirectGotoStmtClass:
+ // "goto *&&lbl;" is a special case which we treat as equivalent
+ // to a normal goto. In addition, we don't calculate scope in the
+ // operand (to avoid recording the address-of-label use), which
+ // works only because of the restricted set of expressions which
+ // we detect as constant targets.
+ if (cast<IndirectGotoStmt>(S)->getConstantTarget()) {
+ LabelAndGotoScopes[S] = ParentScope;
+ Jumps.push_back(S);
+ return;
+ }
+
+ LabelAndGotoScopes[S] = ParentScope;
+ IndirectJumps.push_back(cast<IndirectGotoStmt>(S));
+ break;
+
+ case Stmt::SwitchStmtClass:
+ // Evaluate the condition variable before entering the scope of the switch
+ // statement.
+ if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
+ BuildScopeInformation(Var, ParentScope);
+ SkipFirstSubStmt = true;
+ }
+ // Fall through
+
+ case Stmt::GotoStmtClass:
+ // Remember both what scope a goto is in as well as the fact that we have
+ // it. This makes the second scan not have to walk the AST again.
+ LabelAndGotoScopes[S] = ParentScope;
+ Jumps.push_back(S);
+ break;
+
+ default:
+ break;
+ }
+
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
+ if (SkipFirstSubStmt) {
+ SkipFirstSubStmt = false;
+ continue;
+ }
+
+ Stmt *SubStmt = *CI;
+ if (SubStmt == 0) continue;
+
+ // Cases, labels, and defaults aren't "scope parents". It's also
+ // important to handle these iteratively instead of recursively in
+ // order to avoid blowing out the stack.
+ while (true) {
+ Stmt *Next;
+ if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt))
+ Next = CS->getSubStmt();
+ else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt))
+ Next = DS->getSubStmt();
+ else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
+ Next = LS->getSubStmt();
+ else
+ break;
+
+ LabelAndGotoScopes[SubStmt] = ParentScope;
+ SubStmt = Next;
+ }
+
+ // If this is a declstmt with a VLA definition, it defines a scope from here
+ // to the end of the containing context.
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
+ // The decl statement creates a scope if any of the decls in it are VLAs
+ // or have the cleanup attribute.
+ for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+ I != E; ++I)
+ BuildScopeInformation(*I, ParentScope);
+ continue;
+ }
+
+ // Disallow jumps into any part of an @try statement by pushing a scope and
+ // walking all sub-stmts in that scope.
+ if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
+ // Recursively walk the AST for the @try part.
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_objc_try,
+ diag::note_exits_objc_try,
+ AT->getAtTryLoc()));
+ if (Stmt *TryPart = AT->getTryBody())
+ BuildScopeInformation(TryPart, Scopes.size()-1);
+
+ // Jump from the catch to the finally or try is not valid.
+ for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) {
+ ObjCAtCatchStmt *AC = AT->getCatchStmt(I);
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_objc_catch,
+ diag::note_exits_objc_catch,
+ AC->getAtCatchLoc()));
+ // @catches are nested and it isn't
+ BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1);
+ }
+
+ // Jump from the finally to the try or catch is not valid.
+ if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_objc_finally,
+ diag::note_exits_objc_finally,
+ AF->getAtFinallyLoc()));
+ BuildScopeInformation(AF, Scopes.size()-1);
+ }
+
+ continue;
+ }
+
+ // Disallow jumps into the protected statement of an @synchronized, but
+ // allow jumps into the object expression it protects.
+ if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
+ // Recursively walk the AST for the @synchronized object expr, it is
+ // evaluated in the normal scope.
+ BuildScopeInformation(AS->getSynchExpr(), ParentScope);
+
+ // Recursively walk the AST for the @synchronized part, protected by a new
+ // scope.
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_objc_synchronized,
+ diag::note_exits_objc_synchronized,
+ AS->getAtSynchronizedLoc()));
+ BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1);
+ continue;
+ }
+
+ // Disallow jumps into any part of a C++ try statement. This is pretty
+ // much the same as for Obj-C.
+ if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) {
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_cxx_try,
+ diag::note_exits_cxx_try,
+ TS->getSourceRange().getBegin()));
+ if (Stmt *TryBlock = TS->getTryBlock())
+ BuildScopeInformation(TryBlock, Scopes.size()-1);
+
+ // Jump from the catch into the try is not allowed either.
+ for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
+ CXXCatchStmt *CS = TS->getHandler(I);
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_protected_by_cxx_catch,
+ diag::note_exits_cxx_catch,
+ CS->getSourceRange().getBegin()));
+ BuildScopeInformation(CS->getHandlerBlock(), Scopes.size()-1);
+ }
+
+ continue;
+ }
+
+ // Recursively walk the AST.
+ BuildScopeInformation(SubStmt, ParentScope);
+ }
+}
+
+/// VerifyJumps - Verify each element of the Jumps array to see if they are
+/// valid, emitting diagnostics if not.
+void JumpScopeChecker::VerifyJumps() {
+ while (!Jumps.empty()) {
+ Stmt *Jump = Jumps.pop_back_val();
+
+ // With a goto,
+ if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
+ CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
+ diag::err_goto_into_protected_scope);
+ continue;
+ }
+
+ // We only get indirect gotos here when they have a constant target.
+ if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
+ LabelDecl *Target = IGS->getConstantTarget();
+ CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
+ diag::err_goto_into_protected_scope);
+ continue;
+ }
+
+ SwitchStmt *SS = cast<SwitchStmt>(Jump);
+ for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
+ CheckJump(SS, SC, SC->getLocStart(),
+ diag::err_switch_into_protected_scope);
+ }
+ }
+}
+
+/// VerifyIndirectJumps - Verify whether any possible indirect jump
+/// might cross a protection boundary. Unlike direct jumps, indirect
+/// jumps count cleanups as protection boundaries: since there's no
+/// way to know where the jump is going, we can't implicitly run the
+/// right cleanups the way we can with direct jumps.
+///
+/// Thus, an indirect jump is "trivial" if it bypasses no
+/// initializations and no teardowns. More formally, an indirect jump
+/// from A to B is trivial if the path out from A to DCA(A,B) is
+/// trivial and the path in from DCA(A,B) to B is trivial, where
+/// DCA(A,B) is the deepest common ancestor of A and B.
+/// Jump-triviality is transitive but asymmetric.
+///
+/// A path in is trivial if none of the entered scopes have an InDiag.
+/// A path out is trivial is none of the exited scopes have an OutDiag.
+///
+/// Under these definitions, this function checks that the indirect
+/// jump between A and B is trivial for every indirect goto statement A
+/// and every label B whose address was taken in the function.
+void JumpScopeChecker::VerifyIndirectJumps() {
+ if (IndirectJumps.empty()) return;
+
+ // If there aren't any address-of-label expressions in this function,
+ // complain about the first indirect goto.
+ if (IndirectJumpTargets.empty()) {
+ S.Diag(IndirectJumps[0]->getGotoLoc(),
+ diag::err_indirect_goto_without_addrlabel);
+ return;
+ }
+
+ // Collect a single representative of every scope containing an
+ // indirect goto. For most code bases, this substantially cuts
+ // down on the number of jump sites we'll have to consider later.
+ typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope;
+ llvm::SmallVector<JumpScope, 32> JumpScopes;
+ {
+ llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap;
+ for (llvm::SmallVectorImpl<IndirectGotoStmt*>::iterator
+ I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
+ IndirectGotoStmt *IG = *I;
+ assert(LabelAndGotoScopes.count(IG) &&
+ "indirect jump didn't get added to scopes?");
+ unsigned IGScope = LabelAndGotoScopes[IG];
+ IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
+ if (!Entry) Entry = IG;
+ }
+ JumpScopes.reserve(JumpScopesMap.size());
+ for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator
+ I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I)
+ JumpScopes.push_back(*I);
+ }
+
+ // Collect a single representative of every scope containing a
+ // label whose address was taken somewhere in the function.
+ // For most code bases, there will be only one such scope.
+ llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;
+ for (llvm::SmallVectorImpl<LabelDecl*>::iterator
+ I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
+ I != E; ++I) {
+ LabelDecl *TheLabel = *I;
+ assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
+ "Referenced label didn't get added to scopes?");
+ unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
+ LabelDecl *&Target = TargetScopes[LabelScope];
+ if (!Target) Target = TheLabel;
+ }
+
+ // For each target scope, make sure it's trivially reachable from
+ // every scope containing a jump site.
+ //
+ // A path between scopes always consists of exitting zero or more
+ // scopes, then entering zero or more scopes. We build a set of
+ // of scopes S from which the target scope can be trivially
+ // entered, then verify that every jump scope can be trivially
+ // exitted to reach a scope in S.
+ llvm::BitVector Reachable(Scopes.size(), false);
+ for (llvm::DenseMap<unsigned,LabelDecl*>::iterator
+ TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) {
+ unsigned TargetScope = TI->first;
+ LabelDecl *TargetLabel = TI->second;
+
+ Reachable.reset();
+
+ // Mark all the enclosing scopes from which you can safely jump
+ // into the target scope. 'Min' will end up being the index of
+ // the shallowest such scope.
+ unsigned Min = TargetScope;
+ while (true) {
+ Reachable.set(Min);
+
+ // Don't go beyond the outermost scope.
+ if (Min == 0) break;
+
+ // Stop if we can't trivially enter the current scope.
+ if (Scopes[Min].InDiag) break;
+
+ Min = Scopes[Min].ParentScope;
+ }
+
+ // Walk through all the jump sites, checking that they can trivially
+ // reach this label scope.
+ for (llvm::SmallVectorImpl<JumpScope>::iterator
+ I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) {
+ unsigned Scope = I->first;
+
+ // Walk out the "scope chain" for this scope, looking for a scope
+ // we've marked reachable. For well-formed code this amortizes
+ // to O(JumpScopes.size() / Scopes.size()): we only iterate
+ // when we see something unmarked, and in well-formed code we
+ // mark everything we iterate past.
+ bool IsReachable = false;
+ while (true) {
+ if (Reachable.test(Scope)) {
+ // If we find something reachable, mark all the scopes we just
+ // walked through as reachable.
+ for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope)
+ Reachable.set(S);
+ IsReachable = true;
+ break;
+ }
+
+ // Don't walk out if we've reached the top-level scope or we've
+ // gotten shallower than the shallowest reachable scope.
+ if (Scope == 0 || Scope < Min) break;
+
+ // Don't walk out through an out-diagnostic.
+ if (Scopes[Scope].OutDiag) break;
+
+ Scope = Scopes[Scope].ParentScope;
+ }
+
+ // Only diagnose if we didn't find something.
+ if (IsReachable) continue;
+
+ DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope);
+ }
+ }
+}
+
+/// Diagnose an indirect jump which is known to cross scopes.
+void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
+ unsigned JumpScope,
+ LabelDecl *Target,
+ unsigned TargetScope) {
+ assert(JumpScope != TargetScope);
+
+ S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
+ S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
+
+ unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
+
+ // Walk out the scope chain until we reach the common ancestor.
+ for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope)
+ if (Scopes[I].OutDiag)
+ S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);
+
+ // Now walk into the scopes containing the label whose address was taken.
+ for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope)
+ if (Scopes[I].InDiag)
+ S.Diag(Scopes[I].Loc, Scopes[I].InDiag);
+}
+
+/// CheckJump - Validate that the specified jump statement is valid: that it is
+/// jumping within or out of its current scope, not into a deeper one.
+void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
+ SourceLocation DiagLoc, unsigned JumpDiag) {
+ assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
+ unsigned FromScope = LabelAndGotoScopes[From];
+
+ assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
+ unsigned ToScope = LabelAndGotoScopes[To];
+
+ // Common case: exactly the same scope, which is fine.
+ if (FromScope == ToScope) return;
+
+ unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);
+
+ // It's okay to jump out from a nested scope.
+ if (CommonScope == ToScope) return;
+
+ // Pull out (and reverse) any scopes we might need to diagnose skipping.
+ llvm::SmallVector<unsigned, 10> ToScopes;
+ for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope)
+ if (Scopes[I].InDiag)
+ ToScopes.push_back(I);
+
+ // If the only scopes present are cleanup scopes, we're okay.
+ if (ToScopes.empty()) return;
+
+ S.Diag(DiagLoc, JumpDiag);
+
+ // Emit diagnostics for whatever is left in ToScopes.
+ for (unsigned i = 0, e = ToScopes.size(); i != e; ++i)
+ S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].InDiag);
+}
+
+void Sema::DiagnoseInvalidJumps(Stmt *Body) {
+ (void)JumpScopeChecker(Body, *this);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
new file mode 100644
index 0000000..23a3c24
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -0,0 +1,672 @@
+//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the actions class which performs semantic analysis and
+// builds an AST out of a parse stream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "TargetAttributesSema.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/APFloat.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+using namespace clang;
+using namespace sema;
+
+FunctionScopeInfo::~FunctionScopeInfo() { }
+
+void FunctionScopeInfo::Clear() {
+ HasBranchProtectedScope = false;
+ HasBranchIntoScope = false;
+ HasIndirectGoto = false;
+
+ SwitchStack.clear();
+ Returns.clear();
+ ErrorTrap.reset();
+}
+
+BlockScopeInfo::~BlockScopeInfo() { }
+
+void Sema::ActOnTranslationUnitScope(Scope *S) {
+ TUScope = S;
+ PushDeclContext(S, Context.getTranslationUnitDecl());
+
+ VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+
+ if (!Context.isInt128Installed() && // May be set by ASTReader.
+ PP.getTargetInfo().getPointerWidth(0) >= 64) {
+ TypeSourceInfo *TInfo;
+
+ // Install [u]int128_t for 64-bit targets.
+ TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty);
+ PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
+ SourceLocation(),
+ &Context.Idents.get("__int128_t"),
+ TInfo), TUScope);
+
+ TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty);
+ PushOnScopeChains(TypedefDecl::Create(Context, CurContext,
+ SourceLocation(),
+ &Context.Idents.get("__uint128_t"),
+ TInfo), TUScope);
+ Context.setInt128Installed();
+ }
+
+
+ if (!PP.getLangOptions().ObjC1) return;
+
+ // Built-in ObjC types may already be set by ASTReader (hence isNull checks).
+ if (Context.getObjCSelType().isNull()) {
+ // Create the built-in typedef for 'SEL'.
+ QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy);
+ TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT);
+ TypedefDecl *SelTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("SEL"), SelInfo);
+ PushOnScopeChains(SelTypedef, TUScope);
+ Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
+ Context.ObjCSelRedefinitionType = Context.getObjCSelType();
+ }
+
+ // Synthesize "@class Protocol;
+ if (Context.getObjCProtoType().isNull()) {
+ ObjCInterfaceDecl *ProtocolDecl =
+ ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("Protocol"),
+ SourceLocation(), true);
+ Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
+ PushOnScopeChains(ProtocolDecl, TUScope, false);
+ }
+ // Create the built-in typedef for 'id'.
+ if (Context.getObjCIdType().isNull()) {
+ QualType T = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 0, 0);
+ T = Context.getObjCObjectPointerType(T);
+ TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T);
+ TypedefDecl *IdTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("id"), IdInfo);
+ PushOnScopeChains(IdTypedef, TUScope);
+ Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
+ Context.ObjCIdRedefinitionType = Context.getObjCIdType();
+ }
+ // Create the built-in typedef for 'Class'.
+ if (Context.getObjCClassType().isNull()) {
+ QualType T = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, 0, 0);
+ T = Context.getObjCObjectPointerType(T);
+ TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T);
+ TypedefDecl *ClassTypedef
+ = TypedefDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("Class"), ClassInfo);
+ PushOnScopeChains(ClassTypedef, TUScope);
+ Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+ Context.ObjCClassRedefinitionType = Context.getObjCClassType();
+ }
+}
+
+Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+ bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CodeCompleter)
+ : TheTargetAttributesSema(0), FPFeatures(pp.getLangOptions()),
+ LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
+ Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
+ ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
+ PackContext(0), VisContext(0),
+ IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
+ GlobalNewDeleteDeclared(false),
+ CompleteTranslationUnit(CompleteTranslationUnit),
+ NumSFINAEErrors(0), SuppressAccessChecking(false),
+ AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
+ NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+ CurrentInstantiationScope(0), TyposCorrected(0),
+ AnalysisWarnings(*this)
+{
+ TUScope = 0;
+ if (getLangOptions().CPlusPlus)
+ FieldCollector.reset(new CXXFieldCollector());
+
+ // Tell diagnostics how to render things from the AST library.
+ PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+ &Context);
+
+ ExprEvalContexts.push_back(
+ ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
+
+ FunctionScopes.push_back(new FunctionScopeInfo(Diags));
+}
+
+void Sema::Initialize() {
+ // Tell the AST consumer about this Sema object.
+ Consumer.Initialize(Context);
+
+ // FIXME: Isn't this redundant with the initialization above?
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+ SC->InitializeSema(*this);
+
+ // Tell the external Sema source about this Sema object.
+ if (ExternalSemaSource *ExternalSema
+ = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+ ExternalSema->InitializeSema(*this);
+}
+
+Sema::~Sema() {
+ if (PackContext) FreePackedContext();
+ if (VisContext) FreeVisContext();
+ delete TheTargetAttributesSema;
+
+ // Kill all the active scopes.
+ for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
+ delete FunctionScopes[I];
+ if (FunctionScopes.size() == 1)
+ delete FunctionScopes[0];
+
+ // Tell the SemaConsumer to forget about us; we're going out of scope.
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+ SC->ForgetSema();
+
+ // Detach from the external Sema source.
+ if (ExternalSemaSource *ExternalSema
+ = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+ ExternalSema->ForgetSema();
+}
+
+/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
+/// If there is already an implicit cast, merge into the existing one.
+/// The result is of the given category.
+void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
+ CastKind Kind, ExprValueKind VK,
+ const CXXCastPath *BasePath) {
+ QualType ExprTy = Context.getCanonicalType(Expr->getType());
+ QualType TypeTy = Context.getCanonicalType(Ty);
+
+ if (ExprTy == TypeTy)
+ return;
+
+ // If this is a derived-to-base cast to a through a virtual base, we
+ // need a vtable.
+ if (Kind == CK_DerivedToBase &&
+ BasePathInvolvesVirtualBase(*BasePath)) {
+ QualType T = Expr->getType();
+ if (const PointerType *Pointer = T->getAs<PointerType>())
+ T = Pointer->getPointeeType();
+ if (const RecordType *RecordTy = T->getAs<RecordType>())
+ MarkVTableUsed(Expr->getLocStart(),
+ cast<CXXRecordDecl>(RecordTy->getDecl()));
+ }
+
+ if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
+ if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
+ ImpCast->setType(Ty);
+ ImpCast->setValueKind(VK);
+ return;
+ }
+ }
+
+ Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK);
+}
+
+ExprValueKind Sema::CastCategory(Expr *E) {
+ Expr::Classification Classification = E->Classify(Context);
+ return Classification.isRValue() ? VK_RValue :
+ (Classification.isLValue() ? VK_LValue : VK_XValue);
+}
+
+/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
+ if (D->isUsed())
+ return true;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // UnusedFileScopedDecls stores the first declaration.
+ // The declaration may have become definition so check again.
+ const FunctionDecl *DeclToCheck;
+ if (FD->hasBody(DeclToCheck))
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+ // Later redecls may add new information resulting in not having to warn,
+ // so check again.
+ DeclToCheck = FD->getMostRecentDeclaration();
+ if (DeclToCheck != FD)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // UnusedFileScopedDecls stores the first declaration.
+ // The declaration may have become definition so check again.
+ const VarDecl *DeclToCheck = VD->getDefinition();
+ if (DeclToCheck)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+ // Later redecls may add new information resulting in not having to warn,
+ // so check again.
+ DeclToCheck = VD->getMostRecentDeclaration();
+ if (DeclToCheck != VD)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+ }
+
+ return false;
+}
+
+namespace {
+ struct UndefinedInternal {
+ NamedDecl *decl;
+ FullSourceLoc useLoc;
+
+ UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc)
+ : decl(decl), useLoc(useLoc) {}
+ };
+
+ bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) {
+ return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc);
+ }
+}
+
+/// checkUndefinedInternals - Check for undefined objects with internal linkage.
+static void checkUndefinedInternals(Sema &S) {
+ if (S.UndefinedInternals.empty()) return;
+
+ // Collect all the still-undefined entities with internal linkage.
+ llvm::SmallVector<UndefinedInternal, 16> undefined;
+ for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator
+ i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end();
+ i != e; ++i) {
+ NamedDecl *decl = i->first;
+
+ // Ignore attributes that have become invalid.
+ if (decl->isInvalidDecl()) continue;
+
+ // __attribute__((weakref)) is basically a definition.
+ if (decl->hasAttr<WeakRefAttr>()) continue;
+
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ if (fn->isPure() || fn->hasBody())
+ continue;
+ } else {
+ if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly)
+ continue;
+ }
+
+ // We build a FullSourceLoc so that we can sort with array_pod_sort.
+ FullSourceLoc loc(i->second, S.Context.getSourceManager());
+ undefined.push_back(UndefinedInternal(decl, loc));
+ }
+
+ if (undefined.empty()) return;
+
+ // Sort (in order of use site) so that we're not (as) dependent on
+ // the iteration order through an llvm::DenseMap.
+ llvm::array_pod_sort(undefined.begin(), undefined.end());
+
+ for (llvm::SmallVectorImpl<UndefinedInternal>::iterator
+ i = undefined.begin(), e = undefined.end(); i != e; ++i) {
+ NamedDecl *decl = i->decl;
+ S.Diag(decl->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(decl) << decl;
+ S.Diag(i->useLoc, diag::note_used_here);
+ }
+}
+
+/// ActOnEndOfTranslationUnit - This is called at the very end of the
+/// translation unit when EOF is reached and all but the top-level scope is
+/// popped.
+void Sema::ActOnEndOfTranslationUnit() {
+ // At PCH writing, implicit instantiations and VTable handling info are
+ // stored and performed when the PCH is included.
+ if (CompleteTranslationUnit) {
+ // If any dynamic classes have their key function defined within
+ // this translation unit, then those vtables are considered "used" and must
+ // be emitted.
+ for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
+ assert(!DynamicClasses[I]->isDependentType() &&
+ "Should not see dependent types here!");
+ if (const CXXMethodDecl *KeyFunction
+ = Context.getKeyFunction(DynamicClasses[I])) {
+ const FunctionDecl *Definition = 0;
+ if (KeyFunction->hasBody(Definition))
+ MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true);
+ }
+ }
+
+ // If DefinedUsedVTables ends up marking any virtual member functions it
+ // might lead to more pending template instantiations, which we then need
+ // to instantiate.
+ DefineUsedVTables();
+
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not
+ // carefully keep track of the point of instantiation (C++ [temp.point]).
+ // This means that name lookup that occurs within the template
+ // instantiation will always happen at the end of the translation unit,
+ // so it will find some names that should not be found. Although this is
+ // common behavior for C++ compilers, it is technically wrong. In the
+ // future, we either need to be able to filter the results of name lookup
+ // or we need to perform template instantiations earlier.
+ PerformPendingInstantiations();
+ }
+
+ // Remove file scoped decls that turned out to be used.
+ UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(),
+ UnusedFileScopedDecls.end(),
+ std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
+ this)),
+ UnusedFileScopedDecls.end());
+
+ if (!CompleteTranslationUnit) {
+ TUScope = 0;
+ return;
+ }
+
+ // Check for #pragma weak identifiers that were never declared
+ // FIXME: This will cause diagnostics to be emitted in a non-determinstic
+ // order! Iterating over a densemap like this is bad.
+ for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
+ I = WeakUndeclaredIdentifiers.begin(),
+ E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ if (I->second.getUsed()) continue;
+
+ Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
+ << I->first;
+ }
+
+ // C99 6.9.2p2:
+ // A declaration of an identifier for an object that has file
+ // scope without an initializer, and without a storage-class
+ // specifier or with the storage-class specifier static,
+ // constitutes a tentative definition. If a translation unit
+ // contains one or more tentative definitions for an identifier,
+ // and the translation unit contains no external definition for
+ // that identifier, then the behavior is exactly as if the
+ // translation unit contains a file scope declaration of that
+ // identifier, with the composite type as of the end of the
+ // translation unit, with an initializer equal to 0.
+ llvm::SmallSet<VarDecl *, 32> Seen;
+ for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) {
+ VarDecl *VD = TentativeDefinitions[i]->getActingDefinition();
+
+ // If the tentative definition was completed, getActingDefinition() returns
+ // null. If we've already seen this variable before, insert()'s second
+ // return value is false.
+ if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
+ continue;
+
+ if (const IncompleteArrayType *ArrayT
+ = Context.getAsIncompleteArrayType(VD->getType())) {
+ if (RequireCompleteType(VD->getLocation(),
+ ArrayT->getElementType(),
+ diag::err_tentative_def_incomplete_type_arr)) {
+ VD->setInvalidDecl();
+ continue;
+ }
+
+ // Set the length of the array to 1 (C99 6.9.2p5).
+ Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
+ llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
+ QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
+ One, ArrayType::Normal, 0);
+ VD->setType(T);
+ } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
+ diag::err_tentative_def_incomplete_type))
+ VD->setInvalidDecl();
+
+ // Notify the consumer that we've completed a tentative definition.
+ if (!VD->isInvalidDecl())
+ Consumer.CompleteTentativeDefinition(VD);
+
+ }
+
+ // If there were errors, disable 'unused' warnings since they will mostly be
+ // noise.
+ if (!Diags.hasErrorOccurred()) {
+ // Output warning for unused file scoped decls.
+ for (llvm::SmallVectorImpl<const DeclaratorDecl*>::iterator
+ I = UnusedFileScopedDecls.begin(),
+ E = UnusedFileScopedDecls.end(); I != E; ++I) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ const FunctionDecl *DiagD;
+ if (!FD->hasBody(DiagD))
+ DiagD = FD;
+ Diag(DiagD->getLocation(),
+ isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
+ : diag::warn_unused_function)
+ << DiagD->getDeclName();
+ } else {
+ const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
+ if (!DiagD)
+ DiagD = cast<VarDecl>(*I);
+ Diag(DiagD->getLocation(), diag::warn_unused_variable)
+ << DiagD->getDeclName();
+ }
+ }
+
+ checkUndefinedInternals(*this);
+ }
+
+ TUScope = 0;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Helper functions.
+//===----------------------------------------------------------------------===//
+
+DeclContext *Sema::getFunctionLevelDeclContext() {
+ DeclContext *DC = CurContext;
+
+ while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
+ DC = DC->getParent();
+
+ return DC;
+}
+
+/// getCurFunctionDecl - If inside of a function body, this returns a pointer
+/// to the function decl for the function being parsed. If we're currently
+/// in a 'block', this returns the containing context.
+FunctionDecl *Sema::getCurFunctionDecl() {
+ DeclContext *DC = getFunctionLevelDeclContext();
+ return dyn_cast<FunctionDecl>(DC);
+}
+
+ObjCMethodDecl *Sema::getCurMethodDecl() {
+ DeclContext *DC = getFunctionLevelDeclContext();
+ return dyn_cast<ObjCMethodDecl>(DC);
+}
+
+NamedDecl *Sema::getCurFunctionOrMethodDecl() {
+ DeclContext *DC = getFunctionLevelDeclContext();
+ if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
+ return cast<NamedDecl>(DC);
+ return 0;
+}
+
+Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
+ if (!isActive())
+ return;
+
+ if (llvm::Optional<TemplateDeductionInfo*> Info = SemaRef.isSFINAEContext()) {
+ switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) {
+ case DiagnosticIDs::SFINAE_Report:
+ // Fall through; we'll report the diagnostic below.
+ break;
+
+ case DiagnosticIDs::SFINAE_AccessControl:
+ // Unless access checking is specifically called out as a SFINAE
+ // error, report this diagnostic.
+ if (!SemaRef.AccessCheckingSFINAE)
+ break;
+
+ case DiagnosticIDs::SFINAE_SubstitutionFailure:
+ // Count this failure so that we know that template argument deduction
+ // has failed.
+ ++SemaRef.NumSFINAEErrors;
+ SemaRef.Diags.setLastDiagnosticIgnored();
+ SemaRef.Diags.Clear();
+ Clear();
+ return;
+
+ case DiagnosticIDs::SFINAE_Suppress:
+ // Make a copy of this suppressed diagnostic and store it with the
+ // template-deduction information;
+ FlushCounts();
+ DiagnosticInfo DiagInfo(&SemaRef.Diags);
+
+ if (*Info)
+ (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo,
+ SemaRef.Context.getDiagAllocator()));
+
+ // Suppress this diagnostic.
+ SemaRef.Diags.setLastDiagnosticIgnored();
+ SemaRef.Diags.Clear();
+ Clear();
+ return;
+ }
+ }
+
+ // Emit the diagnostic.
+ if (!this->Emit())
+ return;
+
+ // If this is not a note, and we're in a template instantiation
+ // that is different from the last template instantiation where
+ // we emitted an error, print a template instantiation
+ // backtrace.
+ if (!DiagnosticIDs::isBuiltinNote(DiagID) &&
+ !SemaRef.ActiveTemplateInstantiations.empty() &&
+ SemaRef.ActiveTemplateInstantiations.back()
+ != SemaRef.LastTemplateInstantiationErrorContext) {
+ SemaRef.PrintInstantiationStack();
+ SemaRef.LastTemplateInstantiationErrorContext
+ = SemaRef.ActiveTemplateInstantiations.back();
+ }
+}
+
+Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) {
+ DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
+ return SemaDiagnosticBuilder(DB, *this, DiagID);
+}
+
+Sema::SemaDiagnosticBuilder
+Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
+ SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID()));
+ PD.Emit(Builder);
+
+ return Builder;
+}
+
+/// \brief Determines the active Scope associated with the given declaration
+/// context.
+///
+/// This routine maps a declaration context to the active Scope object that
+/// represents that declaration context in the parser. It is typically used
+/// from "scope-less" code (e.g., template instantiation, lazy creation of
+/// declarations) that injects a name for name-lookup purposes and, therefore,
+/// must update the Scope.
+///
+/// \returns The scope corresponding to the given declaraion context, or NULL
+/// if no such scope is open.
+Scope *Sema::getScopeForContext(DeclContext *Ctx) {
+
+ if (!Ctx)
+ return 0;
+
+ Ctx = Ctx->getPrimaryContext();
+ for (Scope *S = getCurScope(); S; S = S->getParent()) {
+ // Ignore scopes that cannot have declarations. This is important for
+ // out-of-line definitions of static class members.
+ if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
+ if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity()))
+ if (Ctx == Entity->getPrimaryContext())
+ return S;
+ }
+
+ return 0;
+}
+
+/// \brief Enter a new function scope
+void Sema::PushFunctionScope() {
+ if (FunctionScopes.size() == 1) {
+ // Use the "top" function scope rather than having to allocate
+ // memory for a new scope.
+ FunctionScopes.back()->Clear();
+ FunctionScopes.push_back(FunctionScopes.back());
+ return;
+ }
+
+ FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
+}
+
+void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
+ FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
+ BlockScope, Block));
+}
+
+void Sema::PopFunctionOrBlockScope() {
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+ assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ if (FunctionScopes.back() != Scope)
+ delete Scope;
+}
+
+/// \brief Determine whether any errors occurred within this function/method/
+/// block.
+bool Sema::hasAnyErrorsInThisFunction() const {
+ return getCurFunction()->ErrorTrap.hasErrorOccurred();
+}
+
+BlockScopeInfo *Sema::getCurBlock() {
+ if (FunctionScopes.empty())
+ return 0;
+
+ return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+}
+
+// Pin this vtable to this file.
+ExternalSemaSource::~ExternalSemaSource() {}
+
+std::pair<ObjCMethodList, ObjCMethodList>
+ExternalSemaSource::ReadMethodPool(Selector Sel) {
+ return std::pair<ObjCMethodList, ObjCMethodList>();
+}
+
+void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const {
+ SourceLocation Loc = this->Loc;
+ if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+ if (Loc.isValid()) {
+ Loc.print(OS, S.getSourceManager());
+ OS << ": ";
+ }
+ OS << Message;
+
+ if (TheDecl && isa<NamedDecl>(TheDecl)) {
+ std::string Name = cast<NamedDecl>(TheDecl)->getNameAsString();
+ if (!Name.empty())
+ OS << " '" << Name << '\'';
+ }
+
+ OS << '\n';
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
new file mode 100644
index 0000000..4f9bf1c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -0,0 +1,1594 @@
+//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ access control semantics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DependentDiagnostic.h"
+#include "clang/AST/ExprCXX.h"
+
+using namespace clang;
+using namespace sema;
+
+/// A copy of Sema's enum without AR_delayed.
+enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent
+};
+
+/// SetMemberAccessSpecifier - Set the access specifier of a member.
+/// Returns true on error (when the previous member decl access specifier
+/// is different from the new member decl access specifier).
+bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+ NamedDecl *PrevMemberDecl,
+ AccessSpecifier LexicalAS) {
+ if (!PrevMemberDecl) {
+ // Use the lexical access specifier.
+ MemberDecl->setAccess(LexicalAS);
+ return false;
+ }
+
+ // C++ [class.access.spec]p3: When a member is redeclared its access
+ // specifier must be same as its initial declaration.
+ if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
+ Diag(MemberDecl->getLocation(),
+ diag::err_class_redeclared_with_different_access)
+ << MemberDecl << LexicalAS;
+ Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
+ << PrevMemberDecl << PrevMemberDecl->getAccess();
+
+ MemberDecl->setAccess(LexicalAS);
+ return true;
+ }
+
+ MemberDecl->setAccess(PrevMemberDecl->getAccess());
+ return false;
+}
+
+static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
+ DeclContext *DC = D->getDeclContext();
+
+ // This can only happen at top: enum decls only "publish" their
+ // immediate members.
+ if (isa<EnumDecl>(DC))
+ DC = cast<EnumDecl>(DC)->getDeclContext();
+
+ CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
+ while (DeclaringClass->isAnonymousStructOrUnion())
+ DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
+ return DeclaringClass;
+}
+
+namespace {
+struct EffectiveContext {
+ EffectiveContext() : Inner(0), Dependent(false) {}
+
+ explicit EffectiveContext(DeclContext *DC)
+ : Inner(DC),
+ Dependent(DC->isDependentContext()) {
+
+ // C++ [class.access.nest]p1:
+ // A nested class is a member and as such has the same access
+ // rights as any other member.
+ // C++ [class.access]p2:
+ // A member of a class can also access all the names to which
+ // the class has access. A local class of a member function
+ // may access the same names that the member function itself
+ // may access.
+ // This almost implies that the privileges of nesting are transitive.
+ // Technically it says nothing about the local classes of non-member
+ // functions (which can gain privileges through friendship), but we
+ // take that as an oversight.
+ while (true) {
+ if (isa<CXXRecordDecl>(DC)) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+ Records.push_back(Record);
+ DC = Record->getDeclContext();
+ } else if (isa<FunctionDecl>(DC)) {
+ FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
+ Functions.push_back(Function);
+ DC = Function->getDeclContext();
+ } else if (DC->isFileContext()) {
+ break;
+ } else {
+ DC = DC->getParent();
+ }
+ }
+ }
+
+ bool isDependent() const { return Dependent; }
+
+ bool includesClass(const CXXRecordDecl *R) const {
+ R = R->getCanonicalDecl();
+ return std::find(Records.begin(), Records.end(), R)
+ != Records.end();
+ }
+
+ /// Retrieves the innermost "useful" context. Can be null if we're
+ /// doing access-control without privileges.
+ DeclContext *getInnerContext() const {
+ return Inner;
+ }
+
+ typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
+
+ DeclContext *Inner;
+ llvm::SmallVector<FunctionDecl*, 4> Functions;
+ llvm::SmallVector<CXXRecordDecl*, 4> Records;
+ bool Dependent;
+};
+
+/// Like sema::AccessedEntity, but kindly lets us scribble all over
+/// it.
+struct AccessTarget : public AccessedEntity {
+ AccessTarget(const AccessedEntity &Entity)
+ : AccessedEntity(Entity) {
+ initialize();
+ }
+
+ AccessTarget(ASTContext &Context,
+ MemberNonce _,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl,
+ QualType BaseObjectType)
+ : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
+ initialize();
+ }
+
+ AccessTarget(ASTContext &Context,
+ BaseNonce _,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access)
+ : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) {
+ initialize();
+ }
+
+ bool hasInstanceContext() const {
+ return HasInstanceContext;
+ }
+
+ class SavedInstanceContext {
+ public:
+ ~SavedInstanceContext() {
+ Target.HasInstanceContext = Has;
+ }
+
+ private:
+ friend struct AccessTarget;
+ explicit SavedInstanceContext(AccessTarget &Target)
+ : Target(Target), Has(Target.HasInstanceContext) {}
+ AccessTarget &Target;
+ bool Has;
+ };
+
+ SavedInstanceContext saveInstanceContext() {
+ return SavedInstanceContext(*this);
+ }
+
+ void suppressInstanceContext() {
+ HasInstanceContext = false;
+ }
+
+ const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
+ assert(HasInstanceContext);
+ if (CalculatedInstanceContext)
+ return InstanceContext;
+
+ CalculatedInstanceContext = true;
+ DeclContext *IC = S.computeDeclContext(getBaseObjectType());
+ InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
+ return InstanceContext;
+ }
+
+ const CXXRecordDecl *getDeclaringClass() const {
+ return DeclaringClass;
+ }
+
+private:
+ void initialize() {
+ HasInstanceContext = (isMemberAccess() &&
+ !getBaseObjectType().isNull() &&
+ getTargetDecl()->isCXXInstanceMember());
+ CalculatedInstanceContext = false;
+ InstanceContext = 0;
+
+ if (isMemberAccess())
+ DeclaringClass = FindDeclaringClass(getTargetDecl());
+ else
+ DeclaringClass = getBaseClass();
+ DeclaringClass = DeclaringClass->getCanonicalDecl();
+ }
+
+ bool HasInstanceContext : 1;
+ mutable bool CalculatedInstanceContext : 1;
+ mutable const CXXRecordDecl *InstanceContext;
+ const CXXRecordDecl *DeclaringClass;
+};
+
+}
+
+/// Checks whether one class might instantiate to the other.
+static bool MightInstantiateTo(const CXXRecordDecl *From,
+ const CXXRecordDecl *To) {
+ // Declaration names are always preserved by instantiation.
+ if (From->getDeclName() != To->getDeclName())
+ return false;
+
+ const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
+ const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
+ if (FromDC == ToDC) return true;
+ if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
+
+ // Be conservative.
+ return true;
+}
+
+/// Checks whether one class is derived from another, inclusively.
+/// Properly indicates when it couldn't be determined due to
+/// dependence.
+///
+/// This should probably be donated to AST or at least Sema.
+static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
+ const CXXRecordDecl *Target) {
+ assert(Derived->getCanonicalDecl() == Derived);
+ assert(Target->getCanonicalDecl() == Target);
+
+ if (Derived == Target) return AR_accessible;
+
+ bool CheckDependent = Derived->isDependentContext();
+ if (CheckDependent && MightInstantiateTo(Derived, Target))
+ return AR_dependent;
+
+ AccessResult OnFailure = AR_inaccessible;
+ llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
+
+ while (true) {
+ for (CXXRecordDecl::base_class_const_iterator
+ I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
+
+ const CXXRecordDecl *RD;
+
+ QualType T = I->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ RD = cast<CXXRecordDecl>(RT->getDecl());
+ } else if (const InjectedClassNameType *IT
+ = T->getAs<InjectedClassNameType>()) {
+ RD = IT->getDecl();
+ } else {
+ assert(T->isDependentType() && "non-dependent base wasn't a record?");
+ OnFailure = AR_dependent;
+ continue;
+ }
+
+ RD = RD->getCanonicalDecl();
+ if (RD == Target) return AR_accessible;
+ if (CheckDependent && MightInstantiateTo(RD, Target))
+ OnFailure = AR_dependent;
+
+ Queue.push_back(RD);
+ }
+
+ if (Queue.empty()) break;
+
+ Derived = Queue.back();
+ Queue.pop_back();
+ }
+
+ return OnFailure;
+}
+
+
+static bool MightInstantiateTo(Sema &S, DeclContext *Context,
+ DeclContext *Friend) {
+ if (Friend == Context)
+ return true;
+
+ assert(!Friend->isDependentContext() &&
+ "can't handle friends with dependent contexts here");
+
+ if (!Context->isDependentContext())
+ return false;
+
+ if (Friend->isFileContext())
+ return false;
+
+ // TODO: this is very conservative
+ return true;
+}
+
+// Asks whether the type in 'context' can ever instantiate to the type
+// in 'friend'.
+static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
+ if (Friend == Context)
+ return true;
+
+ if (!Friend->isDependentType() && !Context->isDependentType())
+ return false;
+
+ // TODO: this is very conservative.
+ return true;
+}
+
+static bool MightInstantiateTo(Sema &S,
+ FunctionDecl *Context,
+ FunctionDecl *Friend) {
+ if (Context->getDeclName() != Friend->getDeclName())
+ return false;
+
+ if (!MightInstantiateTo(S,
+ Context->getDeclContext(),
+ Friend->getDeclContext()))
+ return false;
+
+ CanQual<FunctionProtoType> FriendTy
+ = S.Context.getCanonicalType(Friend->getType())
+ ->getAs<FunctionProtoType>();
+ CanQual<FunctionProtoType> ContextTy
+ = S.Context.getCanonicalType(Context->getType())
+ ->getAs<FunctionProtoType>();
+
+ // There isn't any way that I know of to add qualifiers
+ // during instantiation.
+ if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
+ return false;
+
+ if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
+ return false;
+
+ if (!MightInstantiateTo(S,
+ ContextTy->getResultType(),
+ FriendTy->getResultType()))
+ return false;
+
+ for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
+ if (!MightInstantiateTo(S,
+ ContextTy->getArgType(I),
+ FriendTy->getArgType(I)))
+ return false;
+
+ return true;
+}
+
+static bool MightInstantiateTo(Sema &S,
+ FunctionTemplateDecl *Context,
+ FunctionTemplateDecl *Friend) {
+ return MightInstantiateTo(S,
+ Context->getTemplatedDecl(),
+ Friend->getTemplatedDecl());
+}
+
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ const CXXRecordDecl *Friend) {
+ if (EC.includesClass(Friend))
+ return AR_accessible;
+
+ if (EC.isDependent()) {
+ CanQualType FriendTy
+ = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
+
+ for (EffectiveContext::record_iterator
+ I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+ CanQualType ContextTy
+ = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
+ if (MightInstantiateTo(S, ContextTy, FriendTy))
+ return AR_dependent;
+ }
+ }
+
+ return AR_inaccessible;
+}
+
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ CanQualType Friend) {
+ if (const RecordType *RT = Friend->getAs<RecordType>())
+ return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
+
+ // TODO: we can do better than this
+ if (Friend->isDependentType())
+ return AR_dependent;
+
+ return AR_inaccessible;
+}
+
+/// Determines whether the given friend class template matches
+/// anything in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ ClassTemplateDecl *Friend) {
+ AccessResult OnFailure = AR_inaccessible;
+
+ // Check whether the friend is the template of a class in the
+ // context chain.
+ for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
+ I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+ CXXRecordDecl *Record = *I;
+
+ // Figure out whether the current class has a template:
+ ClassTemplateDecl *CTD;
+
+ // A specialization of the template...
+ if (isa<ClassTemplateSpecializationDecl>(Record)) {
+ CTD = cast<ClassTemplateSpecializationDecl>(Record)
+ ->getSpecializedTemplate();
+
+ // ... or the template pattern itself.
+ } else {
+ CTD = Record->getDescribedClassTemplate();
+ if (!CTD) continue;
+ }
+
+ // It's a match.
+ if (Friend == CTD->getCanonicalDecl())
+ return AR_accessible;
+
+ // If the context isn't dependent, it can't be a dependent match.
+ if (!EC.isDependent())
+ continue;
+
+ // If the template names don't match, it can't be a dependent
+ // match. This isn't true in C++0x because of template aliases.
+ if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
+ continue;
+
+ // If the class's context can't instantiate to the friend's
+ // context, it can't be a dependent match.
+ if (!MightInstantiateTo(S, CTD->getDeclContext(),
+ Friend->getDeclContext()))
+ continue;
+
+ // Otherwise, it's a dependent match.
+ OnFailure = AR_dependent;
+ }
+
+ return OnFailure;
+}
+
+/// Determines whether the given friend function matches anything in
+/// the effective context.
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ FunctionDecl *Friend) {
+ AccessResult OnFailure = AR_inaccessible;
+
+ for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
+ I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
+ if (Friend == *I)
+ return AR_accessible;
+
+ if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
+ OnFailure = AR_dependent;
+ }
+
+ return OnFailure;
+}
+
+/// Determines whether the given friend function template matches
+/// anything in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ FunctionTemplateDecl *Friend) {
+ if (EC.Functions.empty()) return AR_inaccessible;
+
+ AccessResult OnFailure = AR_inaccessible;
+
+ for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
+ I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
+
+ FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
+ if (!FTD)
+ FTD = (*I)->getDescribedFunctionTemplate();
+ if (!FTD)
+ continue;
+
+ FTD = FTD->getCanonicalDecl();
+
+ if (Friend == FTD)
+ return AR_accessible;
+
+ if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
+ OnFailure = AR_dependent;
+ }
+
+ return OnFailure;
+}
+
+/// Determines whether the given friend declaration matches anything
+/// in the effective context.
+static AccessResult MatchesFriend(Sema &S,
+ const EffectiveContext &EC,
+ FriendDecl *FriendD) {
+ // Whitelist accesses if there's an invalid or unsupported friend
+ // declaration.
+ if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
+ return AR_accessible;
+
+ if (TypeSourceInfo *T = FriendD->getFriendType())
+ return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
+
+ NamedDecl *Friend
+ = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
+
+ // FIXME: declarations with dependent or templated scope.
+
+ if (isa<ClassTemplateDecl>(Friend))
+ return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
+
+ if (isa<FunctionTemplateDecl>(Friend))
+ return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
+
+ if (isa<CXXRecordDecl>(Friend))
+ return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
+
+ assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
+ return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
+}
+
+static AccessResult GetFriendKind(Sema &S,
+ const EffectiveContext &EC,
+ const CXXRecordDecl *Class) {
+ AccessResult OnFailure = AR_inaccessible;
+
+ // Okay, check friends.
+ for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
+ E = Class->friend_end(); I != E; ++I) {
+ FriendDecl *Friend = *I;
+
+ switch (MatchesFriend(S, EC, Friend)) {
+ case AR_accessible:
+ return AR_accessible;
+
+ case AR_inaccessible:
+ continue;
+
+ case AR_dependent:
+ OnFailure = AR_dependent;
+ break;
+ }
+ }
+
+ // That's it, give up.
+ return OnFailure;
+}
+
+namespace {
+
+/// A helper class for checking for a friend which will grant access
+/// to a protected instance member.
+struct ProtectedFriendContext {
+ Sema &S;
+ const EffectiveContext &EC;
+ const CXXRecordDecl *NamingClass;
+ bool CheckDependent;
+ bool EverDependent;
+
+ /// The path down to the current base class.
+ llvm::SmallVector<const CXXRecordDecl*, 20> CurPath;
+
+ ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
+ const CXXRecordDecl *InstanceContext,
+ const CXXRecordDecl *NamingClass)
+ : S(S), EC(EC), NamingClass(NamingClass),
+ CheckDependent(InstanceContext->isDependentContext() ||
+ NamingClass->isDependentContext()),
+ EverDependent(false) {}
+
+ /// Check classes in the current path for friendship, starting at
+ /// the given index.
+ bool checkFriendshipAlongPath(unsigned I) {
+ assert(I < CurPath.size());
+ for (unsigned E = CurPath.size(); I != E; ++I) {
+ switch (GetFriendKind(S, EC, CurPath[I])) {
+ case AR_accessible: return true;
+ case AR_inaccessible: continue;
+ case AR_dependent: EverDependent = true; continue;
+ }
+ }
+ return false;
+ }
+
+ /// Perform a search starting at the given class.
+ ///
+ /// PrivateDepth is the index of the last (least derived) class
+ /// along the current path such that a notional public member of
+ /// the final class in the path would have access in that class.
+ bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
+ // If we ever reach the naming class, check the current path for
+ // friendship. We can also stop recursing because we obviously
+ // won't find the naming class there again.
+ if (Cur == NamingClass)
+ return checkFriendshipAlongPath(PrivateDepth);
+
+ if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
+ EverDependent = true;
+
+ // Recurse into the base classes.
+ for (CXXRecordDecl::base_class_const_iterator
+ I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
+
+ // If this is private inheritance, then a public member of the
+ // base will not have any access in classes derived from Cur.
+ unsigned BasePrivateDepth = PrivateDepth;
+ if (I->getAccessSpecifier() == AS_private)
+ BasePrivateDepth = CurPath.size() - 1;
+
+ const CXXRecordDecl *RD;
+
+ QualType T = I->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ RD = cast<CXXRecordDecl>(RT->getDecl());
+ } else if (const InjectedClassNameType *IT
+ = T->getAs<InjectedClassNameType>()) {
+ RD = IT->getDecl();
+ } else {
+ assert(T->isDependentType() && "non-dependent base wasn't a record?");
+ EverDependent = true;
+ continue;
+ }
+
+ // Recurse. We don't need to clean up if this returns true.
+ CurPath.push_back(RD);
+ if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
+ return true;
+ CurPath.pop_back();
+ }
+
+ return false;
+ }
+
+ bool findFriendship(const CXXRecordDecl *Cur) {
+ assert(CurPath.empty());
+ CurPath.push_back(Cur);
+ return findFriendship(Cur, 0);
+ }
+};
+}
+
+/// Search for a class P that EC is a friend of, under the constraint
+/// InstanceContext <= P <= NamingClass
+/// and with the additional restriction that a protected member of
+/// NamingClass would have some natural access in P.
+///
+/// That second condition isn't actually quite right: the condition in
+/// the standard is whether the target would have some natural access
+/// in P. The difference is that the target might be more accessible
+/// along some path not passing through NamingClass. Allowing that
+/// introduces two problems:
+/// - It breaks encapsulation because you can suddenly access a
+/// forbidden base class's members by subclassing it elsewhere.
+/// - It makes access substantially harder to compute because it
+/// breaks the hill-climbing algorithm: knowing that the target is
+/// accessible in some base class would no longer let you change
+/// the question solely to whether the base class is accessible,
+/// because the original target might have been more accessible
+/// because of crazy subclassing.
+/// So we don't implement that.
+static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
+ const CXXRecordDecl *InstanceContext,
+ const CXXRecordDecl *NamingClass) {
+ assert(InstanceContext->getCanonicalDecl() == InstanceContext);
+ assert(NamingClass->getCanonicalDecl() == NamingClass);
+
+ ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
+ if (PRC.findFriendship(InstanceContext)) return AR_accessible;
+ if (PRC.EverDependent) return AR_dependent;
+ return AR_inaccessible;
+}
+
+static AccessResult HasAccess(Sema &S,
+ const EffectiveContext &EC,
+ const CXXRecordDecl *NamingClass,
+ AccessSpecifier Access,
+ const AccessTarget &Target) {
+ assert(NamingClass->getCanonicalDecl() == NamingClass &&
+ "declaration should be canonicalized before being passed here");
+
+ if (Access == AS_public) return AR_accessible;
+ assert(Access == AS_private || Access == AS_protected);
+
+ AccessResult OnFailure = AR_inaccessible;
+
+ for (EffectiveContext::record_iterator
+ I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+ // All the declarations in EC have been canonicalized, so pointer
+ // equality from this point on will work fine.
+ const CXXRecordDecl *ECRecord = *I;
+
+ // [B2] and [M2]
+ if (Access == AS_private) {
+ if (ECRecord == NamingClass)
+ return AR_accessible;
+
+ if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
+ OnFailure = AR_dependent;
+
+ // [B3] and [M3]
+ } else {
+ assert(Access == AS_protected);
+ switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
+ case AR_accessible: break;
+ case AR_inaccessible: continue;
+ case AR_dependent: OnFailure = AR_dependent; continue;
+ }
+
+ if (!Target.hasInstanceContext())
+ return AR_accessible;
+
+ const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+ if (!InstanceContext) {
+ OnFailure = AR_dependent;
+ continue;
+ }
+
+ // C++ [class.protected]p1:
+ // An additional access check beyond those described earlier in
+ // [class.access] is applied when a non-static data member or
+ // non-static member function is a protected member of its naming
+ // class. As described earlier, access to a protected member is
+ // granted because the reference occurs in a friend or member of
+ // some class C. If the access is to form a pointer to member,
+ // the nested-name-specifier shall name C or a class derived from
+ // C. All other accesses involve a (possibly implicit) object
+ // expression. In this case, the class of the object expression
+ // shall be C or a class derived from C.
+ //
+ // We interpret this as a restriction on [M3]. Most of the
+ // conditions are encoded by not having any instance context.
+ switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
+ case AR_accessible: return AR_accessible;
+ case AR_inaccessible: continue;
+ case AR_dependent: OnFailure = AR_dependent; continue;
+ }
+ }
+ }
+
+ // [M3] and [B3] say that, if the target is protected in N, we grant
+ // access if the access occurs in a friend or member of some class P
+ // that's a subclass of N and where the target has some natural
+ // access in P. The 'member' aspect is easy to handle because P
+ // would necessarily be one of the effective-context records, and we
+ // address that above. The 'friend' aspect is completely ridiculous
+ // to implement because there are no restrictions at all on P
+ // *unless* the [class.protected] restriction applies. If it does,
+ // however, we should ignore whether the naming class is a friend,
+ // and instead rely on whether any potential P is a friend.
+ if (Access == AS_protected && Target.hasInstanceContext()) {
+ const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+ if (!InstanceContext) return AR_dependent;
+ switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
+ case AR_accessible: return AR_accessible;
+ case AR_inaccessible: return OnFailure;
+ case AR_dependent: return AR_dependent;
+ }
+ llvm_unreachable("impossible friendship kind");
+ }
+
+ switch (GetFriendKind(S, EC, NamingClass)) {
+ case AR_accessible: return AR_accessible;
+ case AR_inaccessible: return OnFailure;
+ case AR_dependent: return AR_dependent;
+ }
+
+ // Silence bogus warnings
+ llvm_unreachable("impossible friendship kind");
+ return OnFailure;
+}
+
+/// Finds the best path from the naming class to the declaring class,
+/// taking friend declarations into account.
+///
+/// C++0x [class.access.base]p5:
+/// A member m is accessible at the point R when named in class N if
+/// [M1] m as a member of N is public, or
+/// [M2] m as a member of N is private, and R occurs in a member or
+/// friend of class N, or
+/// [M3] m as a member of N is protected, and R occurs in a member or
+/// friend of class N, or in a member or friend of a class P
+/// derived from N, where m as a member of P is public, private,
+/// or protected, or
+/// [M4] there exists a base class B of N that is accessible at R, and
+/// m is accessible at R when named in class B.
+///
+/// C++0x [class.access.base]p4:
+/// A base class B of N is accessible at R, if
+/// [B1] an invented public member of B would be a public member of N, or
+/// [B2] R occurs in a member or friend of class N, and an invented public
+/// member of B would be a private or protected member of N, or
+/// [B3] R occurs in a member or friend of a class P derived from N, and an
+/// invented public member of B would be a private or protected member
+/// of P, or
+/// [B4] there exists a class S such that B is a base class of S accessible
+/// at R and S is a base class of N accessible at R.
+///
+/// Along a single inheritance path we can restate both of these
+/// iteratively:
+///
+/// First, we note that M1-4 are equivalent to B1-4 if the member is
+/// treated as a notional base of its declaring class with inheritance
+/// access equivalent to the member's access. Therefore we need only
+/// ask whether a class B is accessible from a class N in context R.
+///
+/// Let B_1 .. B_n be the inheritance path in question (i.e. where
+/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
+/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the
+/// closest accessible base in the path:
+/// Access(a, b) = (* access on the base specifier from a to b *)
+/// Merge(a, forbidden) = forbidden
+/// Merge(a, private) = forbidden
+/// Merge(a, b) = min(a,b)
+/// Accessible(c, forbidden) = false
+/// Accessible(c, private) = (R is c) || IsFriend(c, R)
+/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
+/// Accessible(c, public) = true
+/// ACAB(n) = public
+/// ACAB(i) =
+/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
+/// if Accessible(B_i, AccessToBase) then public else AccessToBase
+///
+/// B is an accessible base of N at R iff ACAB(1) = public.
+///
+/// \param FinalAccess the access of the "final step", or AS_public if
+/// there is no final step.
+/// \return null if friendship is dependent
+static CXXBasePath *FindBestPath(Sema &S,
+ const EffectiveContext &EC,
+ AccessTarget &Target,
+ AccessSpecifier FinalAccess,
+ CXXBasePaths &Paths) {
+ // Derive the paths to the desired base.
+ const CXXRecordDecl *Derived = Target.getNamingClass();
+ const CXXRecordDecl *Base = Target.getDeclaringClass();
+
+ // FIXME: fail correctly when there are dependent paths.
+ bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
+ Paths);
+ assert(isDerived && "derived class not actually derived from base");
+ (void) isDerived;
+
+ CXXBasePath *BestPath = 0;
+
+ assert(FinalAccess != AS_none && "forbidden access after declaring class");
+
+ bool AnyDependent = false;
+
+ // Derive the friend-modified access along each path.
+ for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+ PI != PE; ++PI) {
+ AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
+
+ // Walk through the path backwards.
+ AccessSpecifier PathAccess = FinalAccess;
+ CXXBasePath::iterator I = PI->end(), E = PI->begin();
+ while (I != E) {
+ --I;
+
+ assert(PathAccess != AS_none);
+
+ // If the declaration is a private member of a base class, there
+ // is no level of friendship in derived classes that can make it
+ // accessible.
+ if (PathAccess == AS_private) {
+ PathAccess = AS_none;
+ break;
+ }
+
+ const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
+
+ AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
+ PathAccess = std::max(PathAccess, BaseAccess);
+
+ switch (HasAccess(S, EC, NC, PathAccess, Target)) {
+ case AR_inaccessible: break;
+ case AR_accessible:
+ PathAccess = AS_public;
+
+ // Future tests are not against members and so do not have
+ // instance context.
+ Target.suppressInstanceContext();
+ break;
+ case AR_dependent:
+ AnyDependent = true;
+ goto Next;
+ }
+ }
+
+ // Note that we modify the path's Access field to the
+ // friend-modified access.
+ if (BestPath == 0 || PathAccess < BestPath->Access) {
+ BestPath = &*PI;
+ BestPath->Access = PathAccess;
+
+ // Short-circuit if we found a public path.
+ if (BestPath->Access == AS_public)
+ return BestPath;
+ }
+
+ Next: ;
+ }
+
+ assert((!BestPath || BestPath->Access != AS_public) &&
+ "fell out of loop with public path");
+
+ // We didn't find a public path, but at least one path was subject
+ // to dependent friendship, so delay the check.
+ if (AnyDependent)
+ return 0;
+
+ return BestPath;
+}
+
+/// Given that an entity has protected natural access, check whether
+/// access might be denied because of the protected member access
+/// restriction.
+///
+/// \return true if a note was emitted
+static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
+ AccessTarget &Target) {
+ // Only applies to instance accesses.
+ if (!Target.hasInstanceContext())
+ return false;
+ assert(Target.isMemberAccess());
+ NamedDecl *D = Target.getTargetDecl();
+
+ const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass();
+ DeclaringClass = DeclaringClass->getCanonicalDecl();
+
+ for (EffectiveContext::record_iterator
+ I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+ const CXXRecordDecl *ECRecord = *I;
+ switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) {
+ case AR_accessible: break;
+ case AR_inaccessible: continue;
+ case AR_dependent: continue;
+ }
+
+ // The effective context is a subclass of the declaring class.
+ // If that class isn't a superclass of the instance context,
+ // then the [class.protected] restriction applies.
+
+ // To get this exactly right, this might need to be checked more
+ // holistically; it's not necessarily the case that gaining
+ // access here would grant us access overall.
+
+ const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+ assert(InstanceContext && "diagnosing dependent access");
+
+ switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
+ case AR_accessible: continue;
+ case AR_dependent: continue;
+ case AR_inaccessible:
+ S.Diag(D->getLocation(), diag::note_access_protected_restricted)
+ << (InstanceContext != Target.getNamingClass()->getCanonicalDecl())
+ << S.Context.getTypeDeclType(InstanceContext)
+ << S.Context.getTypeDeclType(ECRecord);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// Diagnose the path which caused the given declaration or base class
+/// to become inaccessible.
+static void DiagnoseAccessPath(Sema &S,
+ const EffectiveContext &EC,
+ AccessTarget &Entity) {
+ AccessSpecifier Access = Entity.getAccess();
+ const CXXRecordDecl *NamingClass = Entity.getNamingClass();
+ NamingClass = NamingClass->getCanonicalDecl();
+
+ NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+ const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+
+ // Easy case: the decl's natural access determined its path access.
+ // We have to check against AS_private here in case Access is AS_none,
+ // indicating a non-public member of a private base class.
+ if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
+ switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
+ case AR_inaccessible: {
+ if (Access == AS_protected &&
+ TryDiagnoseProtectedAccess(S, EC, Entity))
+ return;
+
+ // Find an original declaration.
+ while (D->isOutOfLine()) {
+ NamedDecl *PrevDecl = 0;
+ if (isa<VarDecl>(D))
+ PrevDecl = cast<VarDecl>(D)->getPreviousDeclaration();
+ else if (isa<FunctionDecl>(D))
+ PrevDecl = cast<FunctionDecl>(D)->getPreviousDeclaration();
+ else if (isa<TypedefDecl>(D))
+ PrevDecl = cast<TypedefDecl>(D)->getPreviousDeclaration();
+ else if (isa<TagDecl>(D)) {
+ if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
+ break;
+ PrevDecl = cast<TagDecl>(D)->getPreviousDeclaration();
+ }
+ if (!PrevDecl) break;
+ D = PrevDecl;
+ }
+
+ CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+ Decl *ImmediateChild;
+ if (D->getDeclContext() == DeclaringClass)
+ ImmediateChild = D;
+ else {
+ DeclContext *DC = D->getDeclContext();
+ while (DC->getParent() != DeclaringClass)
+ DC = DC->getParent();
+ ImmediateChild = cast<Decl>(DC);
+ }
+
+ // Check whether there's an AccessSpecDecl preceding this in the
+ // chain of the DeclContext.
+ bool Implicit = true;
+ for (CXXRecordDecl::decl_iterator
+ I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
+ I != E; ++I) {
+ if (*I == ImmediateChild) break;
+ if (isa<AccessSpecDecl>(*I)) {
+ Implicit = false;
+ break;
+ }
+ }
+
+ S.Diag(D->getLocation(), diag::note_access_natural)
+ << (unsigned) (Access == AS_protected)
+ << Implicit;
+ return;
+ }
+
+ case AR_accessible: break;
+
+ case AR_dependent:
+ llvm_unreachable("can't diagnose dependent access failures");
+ return;
+ }
+ }
+
+ CXXBasePaths Paths;
+ CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
+
+ CXXBasePath::iterator I = Path.end(), E = Path.begin();
+ while (I != E) {
+ --I;
+
+ const CXXBaseSpecifier *BS = I->Base;
+ AccessSpecifier BaseAccess = BS->getAccessSpecifier();
+
+ // If this is public inheritance, or the derived class is a friend,
+ // skip this step.
+ if (BaseAccess == AS_public)
+ continue;
+
+ switch (GetFriendKind(S, EC, I->Class)) {
+ case AR_accessible: continue;
+ case AR_inaccessible: break;
+ case AR_dependent:
+ llvm_unreachable("can't diagnose dependent access failures");
+ }
+
+ // Check whether this base specifier is the tighest point
+ // constraining access. We have to check against AS_private for
+ // the same reasons as above.
+ if (BaseAccess == AS_private || BaseAccess >= Access) {
+
+ // We're constrained by inheritance, but we want to say
+ // "declared private here" if we're diagnosing a hierarchy
+ // conversion and this is the final step.
+ unsigned diagnostic;
+ if (D) diagnostic = diag::note_access_constrained_by_path;
+ else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
+ else diagnostic = diag::note_access_constrained_by_path;
+
+ S.Diag(BS->getSourceRange().getBegin(), diagnostic)
+ << BS->getSourceRange()
+ << (BaseAccess == AS_protected)
+ << (BS->getAccessSpecifierAsWritten() == AS_none);
+
+ if (D)
+ S.Diag(D->getLocation(), diag::note_field_decl);
+
+ return;
+ }
+ }
+
+ llvm_unreachable("access not apparently constrained by path");
+}
+
+static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
+ const EffectiveContext &EC,
+ AccessTarget &Entity) {
+ const CXXRecordDecl *NamingClass = Entity.getNamingClass();
+ const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+ NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
+
+ S.Diag(Loc, Entity.getDiag())
+ << (Entity.getAccess() == AS_protected)
+ << (D ? D->getDeclName() : DeclarationName())
+ << S.Context.getTypeDeclType(NamingClass)
+ << S.Context.getTypeDeclType(DeclaringClass);
+ DiagnoseAccessPath(S, EC, Entity);
+}
+
+/// Determines whether the accessed entity is accessible. Public members
+/// have been weeded out by this point.
+static AccessResult IsAccessible(Sema &S,
+ const EffectiveContext &EC,
+ AccessTarget &Entity) {
+ // Determine the actual naming class.
+ CXXRecordDecl *NamingClass = Entity.getNamingClass();
+ while (NamingClass->isAnonymousStructOrUnion())
+ NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
+ NamingClass = NamingClass->getCanonicalDecl();
+
+ AccessSpecifier UnprivilegedAccess = Entity.getAccess();
+ assert(UnprivilegedAccess != AS_public && "public access not weeded out");
+
+ // Before we try to recalculate access paths, try to white-list
+ // accesses which just trade in on the final step, i.e. accesses
+ // which don't require [M4] or [B4]. These are by far the most
+ // common forms of privileged access.
+ if (UnprivilegedAccess != AS_none) {
+ switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
+ case AR_dependent:
+ // This is actually an interesting policy decision. We don't
+ // *have* to delay immediately here: we can do the full access
+ // calculation in the hope that friendship on some intermediate
+ // class will make the declaration accessible non-dependently.
+ // But that's not cheap, and odds are very good (note: assertion
+ // made without data) that the friend declaration will determine
+ // access.
+ return AR_dependent;
+
+ case AR_accessible: return AR_accessible;
+ case AR_inaccessible: break;
+ }
+ }
+
+ AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
+
+ // We lower member accesses to base accesses by pretending that the
+ // member is a base class of its declaring class.
+ AccessSpecifier FinalAccess;
+
+ if (Entity.isMemberAccess()) {
+ // Determine if the declaration is accessible from EC when named
+ // in its declaring class.
+ NamedDecl *Target = Entity.getTargetDecl();
+ const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
+
+ FinalAccess = Target->getAccess();
+ switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
+ case AR_accessible:
+ FinalAccess = AS_public;
+ break;
+ case AR_inaccessible: break;
+ case AR_dependent: return AR_dependent; // see above
+ }
+
+ if (DeclaringClass == NamingClass)
+ return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
+
+ Entity.suppressInstanceContext();
+ } else {
+ FinalAccess = AS_public;
+ }
+
+ assert(Entity.getDeclaringClass() != NamingClass);
+
+ // Append the declaration's access if applicable.
+ CXXBasePaths Paths;
+ CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
+ if (!Path)
+ return AR_dependent;
+
+ assert(Path->Access <= UnprivilegedAccess &&
+ "access along best path worse than direct?");
+ if (Path->Access == AS_public)
+ return AR_accessible;
+ return AR_inaccessible;
+}
+
+static void DelayDependentAccess(Sema &S,
+ const EffectiveContext &EC,
+ SourceLocation Loc,
+ const AccessTarget &Entity) {
+ assert(EC.isDependent() && "delaying non-dependent access");
+ DeclContext *DC = EC.getInnerContext();
+ assert(DC->isDependentContext() && "delaying non-dependent access");
+ DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
+ Loc,
+ Entity.isMemberAccess(),
+ Entity.getAccess(),
+ Entity.getTargetDecl(),
+ Entity.getNamingClass(),
+ Entity.getBaseObjectType(),
+ Entity.getDiag());
+}
+
+/// Checks access to an entity from the given effective context.
+static AccessResult CheckEffectiveAccess(Sema &S,
+ const EffectiveContext &EC,
+ SourceLocation Loc,
+ AccessTarget &Entity) {
+ assert(Entity.getAccess() != AS_public && "called for public access!");
+
+ switch (IsAccessible(S, EC, Entity)) {
+ case AR_dependent:
+ DelayDependentAccess(S, EC, Loc, Entity);
+ return AR_dependent;
+
+ case AR_inaccessible:
+ if (!Entity.isQuiet())
+ DiagnoseBadAccess(S, Loc, EC, Entity);
+ return AR_inaccessible;
+
+ case AR_accessible:
+ return AR_accessible;
+ }
+
+ // silence unnecessary warning
+ llvm_unreachable("invalid access result");
+ return AR_accessible;
+}
+
+static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
+ AccessTarget &Entity) {
+ // If the access path is public, it's accessible everywhere.
+ if (Entity.getAccess() == AS_public)
+ return Sema::AR_accessible;
+
+ if (S.SuppressAccessChecking)
+ return Sema::AR_accessible;
+
+ // If we're currently parsing a declaration, we may need to delay
+ // access control checking, because our effective context might be
+ // different based on what the declaration comes out as.
+ //
+ // For example, we might be parsing a declaration with a scope
+ // specifier, like this:
+ // A::private_type A::foo() { ... }
+ //
+ // Or we might be parsing something that will turn out to be a friend:
+ // void foo(A::private_type);
+ // void B::foo(A::private_type);
+ if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
+ S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
+ return Sema::AR_delayed;
+ }
+
+ EffectiveContext EC(S.CurContext);
+ switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
+ case AR_accessible: return Sema::AR_accessible;
+ case AR_inaccessible: return Sema::AR_inaccessible;
+ case AR_dependent: return Sema::AR_dependent;
+ }
+ llvm_unreachable("falling off end");
+ return Sema::AR_accessible;
+}
+
+void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
+ // Access control for names used in the declarations of functions
+ // and function templates should normally be evaluated in the context
+ // of the declaration, just in case it's a friend of something.
+ // However, this does not apply to local extern declarations.
+
+ DeclContext *DC = decl->getDeclContext();
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+ if (!DC->isFunctionOrMethod()) DC = fn;
+ } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
+ // Never a local declaration.
+ DC = fnt->getTemplatedDecl();
+ }
+
+ EffectiveContext EC(DC);
+
+ AccessTarget Target(DD.getAccessData());
+
+ if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
+ DD.Triggered = true;
+}
+
+void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ SourceLocation Loc = DD.getAccessLoc();
+ AccessSpecifier Access = DD.getAccess();
+
+ Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
+ TemplateArgs);
+ if (!NamingD) return;
+ Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
+ TemplateArgs);
+ if (!TargetD) return;
+
+ if (DD.isAccessToMember()) {
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
+ NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
+ QualType BaseObjectType = DD.getAccessBaseObjectType();
+ if (!BaseObjectType.isNull()) {
+ BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
+ DeclarationName());
+ if (BaseObjectType.isNull()) return;
+ }
+
+ AccessTarget Entity(Context,
+ AccessTarget::Member,
+ NamingClass,
+ DeclAccessPair::make(TargetDecl, Access),
+ BaseObjectType);
+ Entity.setDiag(DD.getDiagnostic());
+ CheckAccess(*this, Loc, Entity);
+ } else {
+ AccessTarget Entity(Context,
+ AccessTarget::Base,
+ cast<CXXRecordDecl>(TargetD),
+ cast<CXXRecordDecl>(NamingD),
+ Access);
+ Entity.setDiag(DD.getDiagnostic());
+ CheckAccess(*this, Loc, Entity);
+ }
+}
+
+Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ !E->getNamingClass() ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
+ Found, QualType());
+ Entity.setDiag(diag::err_access) << E->getSourceRange();
+
+ return CheckAccess(*this, E->getNameLoc(), Entity);
+}
+
+/// Perform access-control checking on a previously-unresolved member
+/// access which has now been resolved to a member.
+Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ QualType BaseType = E->getBaseType();
+ if (E->isArrow())
+ BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+
+ AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
+ Found, BaseType);
+ Entity.setDiag(diag::err_access) << E->getSourceRange();
+
+ return CheckAccess(*this, E->getMemberLoc(), Entity);
+}
+
+Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
+ CXXDestructorDecl *Dtor,
+ const PartialDiagnostic &PDiag) {
+ if (!getLangOptions().AccessControl)
+ return AR_accessible;
+
+ // There's never a path involved when checking implicit destructor access.
+ AccessSpecifier Access = Dtor->getAccess();
+ if (Access == AS_public)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = Dtor->getParent();
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
+ DeclAccessPair::make(Dtor, Access),
+ QualType());
+ Entity.setDiag(PDiag); // TODO: avoid copy
+
+ return CheckAccess(*this, Loc, Entity);
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp) {
+ if (!getLangOptions().AccessControl ||
+ Access == AS_public)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = Constructor->getParent();
+ AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
+ DeclAccessPair::make(Constructor, Access),
+ QualType());
+ switch (Entity.getKind()) {
+ default:
+ AccessEntity.setDiag(IsCopyBindingRefToTemp
+ ? diag::ext_rvalue_to_reference_access_ctor
+ : diag::err_access_ctor);
+ break;
+
+ case InitializedEntity::EK_Base:
+ AccessEntity.setDiag(PDiag(diag::err_access_base)
+ << Entity.isInheritedVirtualBase()
+ << Entity.getBaseSpecifier()->getType()
+ << getSpecialMember(Constructor));
+ break;
+
+ case InitializedEntity::EK_Member: {
+ const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
+ AccessEntity.setDiag(PDiag(diag::err_access_field)
+ << Field->getType()
+ << getSpecialMember(Constructor));
+ break;
+ }
+
+ }
+
+ return CheckAccess(*this, UseLoc, AccessEntity);
+}
+
+/// Checks direct (i.e. non-inherited) access to an arbitrary class
+/// member.
+Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
+ NamedDecl *Target,
+ const PartialDiagnostic &Diag) {
+ AccessSpecifier Access = Target->getAccess();
+ if (!getLangOptions().AccessControl ||
+ Access == AS_public)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
+ DeclAccessPair::make(Target, Access),
+ QualType());
+ Entity.setDiag(Diag);
+ return CheckAccess(*this, UseLoc, Entity);
+}
+
+
+/// Checks access to an overloaded operator new or delete.
+Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
+ SourceRange PlacementRange,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ !NamingClass ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+ QualType());
+ Entity.setDiag(diag::err_access)
+ << PlacementRange;
+
+ return CheckAccess(*this, OpLoc, Entity);
+}
+
+/// Checks access to an overloaded member operator, including
+/// conversion operators.
+Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
+ Expr *ObjectExpr,
+ Expr *ArgExpr,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
+ assert(RT && "found member operator but object expr not of record type");
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+ ObjectExpr->getType());
+ Entity.setDiag(diag::err_access)
+ << ObjectExpr->getSourceRange()
+ << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
+
+ return CheckAccess(*this, OpLoc, Entity);
+}
+
+Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ Found.getAccess() == AS_none ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
+ CXXRecordDecl *NamingClass = Ovl->getNamingClass();
+
+ AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
+ Context.getTypeDeclType(NamingClass));
+ Entity.setDiag(diag::err_access)
+ << Ovl->getSourceRange();
+
+ return CheckAccess(*this, Ovl->getNameLoc(), Entity);
+}
+
+/// Checks access for a hierarchy conversion.
+///
+/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
+/// or a derived-to-base conversion (false)
+/// \param ForceCheck true if this check should be performed even if access
+/// control is disabled; some things rely on this for semantics
+/// \param ForceUnprivileged true if this check should proceed as if the
+/// context had no special privileges
+/// \param ADK controls the kind of diagnostics that are used
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+ QualType Base,
+ QualType Derived,
+ const CXXBasePath &Path,
+ unsigned DiagID,
+ bool ForceCheck,
+ bool ForceUnprivileged) {
+ if (!ForceCheck && !getLangOptions().AccessControl)
+ return AR_accessible;
+
+ if (Path.Access == AS_public)
+ return AR_accessible;
+
+ CXXRecordDecl *BaseD, *DerivedD;
+ BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
+ DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
+
+ AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
+ Path.Access);
+ if (DiagID)
+ Entity.setDiag(DiagID) << Derived << Base;
+
+ if (ForceUnprivileged) {
+ switch (CheckEffectiveAccess(*this, EffectiveContext(),
+ AccessLoc, Entity)) {
+ case ::AR_accessible: return Sema::AR_accessible;
+ case ::AR_inaccessible: return Sema::AR_inaccessible;
+ case ::AR_dependent: return Sema::AR_dependent;
+ }
+ llvm_unreachable("unexpected result from CheckEffectiveAccess");
+ }
+ return CheckAccess(*this, AccessLoc, Entity);
+}
+
+/// Checks access to all the declarations in the given result set.
+void Sema::CheckLookupAccess(const LookupResult &R) {
+ assert(getLangOptions().AccessControl
+ && "performing access check without access control");
+ assert(R.getNamingClass() && "performing access check without naming class");
+
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ if (I.getAccess() != AS_public) {
+ AccessTarget Entity(Context, AccessedEntity::Member,
+ R.getNamingClass(), I.getPair(),
+ R.getBaseObjectType());
+ Entity.setDiag(diag::err_access);
+
+ CheckAccess(*this, R.getNameLoc(), Entity);
+ }
+ }
+}
+
+void Sema::ActOnStartSuppressingAccessChecks() {
+ assert(!SuppressAccessChecking &&
+ "Tried to start access check suppression when already started.");
+ SuppressAccessChecking = true;
+}
+
+void Sema::ActOnStopSuppressingAccessChecks() {
+ assert(SuppressAccessChecking &&
+ "Tried to stop access check suprression when already stopped.");
+ SuppressAccessChecking = false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
new file mode 100644
index 0000000..794b0b1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp
@@ -0,0 +1,386 @@
+//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for non-trivial attributes and
+// pragmas.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Pragma 'pack' and 'options align'
+//===----------------------------------------------------------------------===//
+
+namespace {
+ struct PackStackEntry {
+ // We just use a sentinel to represent when the stack is set to mac68k
+ // alignment.
+ static const unsigned kMac68kAlignmentSentinel = ~0U;
+
+ unsigned Alignment;
+ IdentifierInfo *Name;
+ };
+
+ /// PragmaPackStack - Simple class to wrap the stack used by #pragma
+ /// pack.
+ class PragmaPackStack {
+ typedef std::vector<PackStackEntry> stack_ty;
+
+ /// Alignment - The current user specified alignment.
+ unsigned Alignment;
+
+ /// Stack - Entries in the #pragma pack stack, consisting of saved
+ /// alignments and optional names.
+ stack_ty Stack;
+
+ public:
+ PragmaPackStack() : Alignment(0) {}
+
+ void setAlignment(unsigned A) { Alignment = A; }
+ unsigned getAlignment() { return Alignment; }
+
+ /// push - Push the current alignment onto the stack, optionally
+ /// using the given \arg Name for the record, if non-zero.
+ void push(IdentifierInfo *Name) {
+ PackStackEntry PSE = { Alignment, Name };
+ Stack.push_back(PSE);
+ }
+
+ /// pop - Pop a record from the stack and restore the current
+ /// alignment to the previous value. If \arg Name is non-zero then
+ /// the first such named record is popped, otherwise the top record
+ /// is popped. Returns true if the pop succeeded.
+ bool pop(IdentifierInfo *Name, bool IsReset);
+ };
+} // end anonymous namespace.
+
+bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
+ // If name is empty just pop top.
+ if (!Name) {
+ // An empty stack is a special case...
+ if (Stack.empty()) {
+ // If this isn't a reset, it is always an error.
+ if (!IsReset)
+ return false;
+
+ // Otherwise, it is an error only if some alignment has been set.
+ if (!Alignment)
+ return false;
+
+ // Otherwise, reset to the default alignment.
+ Alignment = 0;
+ } else {
+ Alignment = Stack.back().Alignment;
+ Stack.pop_back();
+ }
+
+ return true;
+ }
+
+ // Otherwise, find the named record.
+ for (unsigned i = Stack.size(); i != 0; ) {
+ --i;
+ if (Stack[i].Name == Name) {
+ // Found it, pop up to and including this record.
+ Alignment = Stack[i].Alignment;
+ Stack.erase(Stack.begin() + i, Stack.end());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/// FreePackedContext - Deallocate and null out PackContext.
+void Sema::FreePackedContext() {
+ delete static_cast<PragmaPackStack*>(PackContext);
+ PackContext = 0;
+}
+
+void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
+ // If there is no pack context, we don't need any attributes.
+ if (!PackContext)
+ return;
+
+ PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
+
+ // Otherwise, check to see if we need a max field alignment attribute.
+ if (unsigned Alignment = Stack->getAlignment()) {
+ if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
+ RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
+ else
+ RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
+ Context,
+ Alignment * 8));
+ }
+}
+
+void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+ SourceLocation PragmaLoc,
+ SourceLocation KindLoc) {
+ if (PackContext == 0)
+ PackContext = new PragmaPackStack();
+
+ PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+
+ // Reset just pops the top of the stack, or resets the current alignment to
+ // default.
+ if (Kind == Sema::POAK_Reset) {
+ if (!Context->pop(0, /*IsReset=*/true)) {
+ Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
+ << "stack empty";
+ }
+ return;
+ }
+
+ switch (Kind) {
+ // For all targets we support native and natural are the same.
+ //
+ // FIXME: This is not true on Darwin/PPC.
+ case POAK_Native:
+ case POAK_Power:
+ case POAK_Natural:
+ Context->push(0);
+ Context->setAlignment(0);
+ break;
+
+ // Note that '#pragma options align=packed' is not equivalent to attribute
+ // packed, it has a different precedence relative to attribute aligned.
+ case POAK_Packed:
+ Context->push(0);
+ Context->setAlignment(1);
+ break;
+
+ case POAK_Mac68k:
+ // Check if the target supports this.
+ if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
+ Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
+ return;
+ }
+ Context->push(0);
+ Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
+ break;
+
+ default:
+ Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
+ << KindLoc;
+ break;
+ }
+}
+
+void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
+ ExprTy *alignment, SourceLocation PragmaLoc,
+ SourceLocation LParenLoc, SourceLocation RParenLoc) {
+ Expr *Alignment = static_cast<Expr *>(alignment);
+
+ // If specified then alignment must be a "small" power of two.
+ unsigned AlignmentVal = 0;
+ if (Alignment) {
+ llvm::APSInt Val;
+
+ // pack(0) is like pack(), which just works out since that is what
+ // we use 0 for in PackAttr.
+ if (Alignment->isTypeDependent() ||
+ Alignment->isValueDependent() ||
+ !Alignment->isIntegerConstantExpr(Val, Context) ||
+ !(Val == 0 || Val.isPowerOf2()) ||
+ Val.getZExtValue() > 16) {
+ Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
+ return; // Ignore
+ }
+
+ AlignmentVal = (unsigned) Val.getZExtValue();
+ }
+
+ if (PackContext == 0)
+ PackContext = new PragmaPackStack();
+
+ PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+
+ switch (Kind) {
+ case Sema::PPK_Default: // pack([n])
+ Context->setAlignment(AlignmentVal);
+ break;
+
+ case Sema::PPK_Show: // pack(show)
+ // Show the current alignment, making sure to show the right value
+ // for the default.
+ AlignmentVal = Context->getAlignment();
+ // FIXME: This should come from the target.
+ if (AlignmentVal == 0)
+ AlignmentVal = 8;
+ if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
+ Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
+ else
+ Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
+ break;
+
+ case Sema::PPK_Push: // pack(push [, id] [, [n])
+ Context->push(Name);
+ // Set the new alignment if specified.
+ if (Alignment)
+ Context->setAlignment(AlignmentVal);
+ break;
+
+ case Sema::PPK_Pop: // pack(pop [, id] [, n])
+ // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
+ // "#pragma pack(pop, identifier, n) is undefined"
+ if (Alignment && Name)
+ Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
+
+ // Do the pop.
+ if (!Context->pop(Name, /*IsReset=*/false)) {
+ // If a name was specified then failure indicates the name
+ // wasn't found. Otherwise failure indicates the stack was
+ // empty.
+ Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
+ << (Name ? "no record matching name" : "stack empty");
+
+ // FIXME: Warn about popping named records as MSVC does.
+ } else {
+ // Pop succeeded, set the new alignment if specified.
+ if (Alignment)
+ Context->setAlignment(AlignmentVal);
+ }
+ break;
+
+ default:
+ assert(0 && "Invalid #pragma pack kind.");
+ }
+}
+
+void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
+ SourceLocation PragmaLoc) {
+
+ IdentifierInfo *Name = IdTok.getIdentifierInfo();
+ LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
+ LookupParsedName(Lookup, curScope, NULL, true);
+
+ if (Lookup.empty()) {
+ Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
+ << Name << SourceRange(IdTok.getLocation());
+ return;
+ }
+
+ VarDecl *VD = Lookup.getAsSingle<VarDecl>();
+ if (!VD) {
+ Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
+ << Name << SourceRange(IdTok.getLocation());
+ return;
+ }
+
+ // Warn if this was used before being marked unused.
+ if (VD->isUsed())
+ Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
+
+ VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
+}
+
+typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
+enum { NoVisibility = (unsigned) -1 };
+
+void Sema::AddPushedVisibilityAttribute(Decl *D) {
+ if (!VisContext)
+ return;
+
+ if (D->hasAttr<VisibilityAttr>())
+ return;
+
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+ unsigned rawType = Stack->back().first;
+ if (rawType == NoVisibility) return;
+
+ VisibilityAttr::VisibilityType type
+ = (VisibilityAttr::VisibilityType) rawType;
+ SourceLocation loc = Stack->back().second;
+
+ D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
+}
+
+/// FreeVisContext - Deallocate and null out VisContext.
+void Sema::FreeVisContext() {
+ delete static_cast<VisStack*>(VisContext);
+ VisContext = 0;
+}
+
+static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
+ // Put visibility on stack.
+ if (!S.VisContext)
+ S.VisContext = new VisStack;
+
+ VisStack *Stack = static_cast<VisStack*>(S.VisContext);
+ Stack->push_back(std::make_pair(type, loc));
+}
+
+void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc) {
+ if (IsPush) {
+ // Compute visibility to use.
+ VisibilityAttr::VisibilityType type;
+ if (VisType->isStr("default"))
+ type = VisibilityAttr::Default;
+ else if (VisType->isStr("hidden"))
+ type = VisibilityAttr::Hidden;
+ else if (VisType->isStr("internal"))
+ type = VisibilityAttr::Hidden; // FIXME
+ else if (VisType->isStr("protected"))
+ type = VisibilityAttr::Protected;
+ else {
+ Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
+ VisType->getName();
+ return;
+ }
+ PushPragmaVisibility(*this, type, PragmaLoc);
+ } else {
+ PopPragmaVisibility();
+ }
+}
+
+void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
+ switch (OOS) {
+ case tok::OOS_ON:
+ FPFeatures.fp_contract = 1;
+ break;
+ case tok::OOS_OFF:
+ FPFeatures.fp_contract = 0;
+ break;
+ case tok::OOS_DEFAULT:
+ FPFeatures.fp_contract = getLangOptions().DefaultFPContract;
+ break;
+ }
+}
+
+void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) {
+ // Visibility calculations will consider the namespace's visibility.
+ // Here we just want to note that we're in a visibility context
+ // which overrides any enclosing #pragma context, but doesn't itself
+ // contribute visibility.
+ PushPragmaVisibility(*this, NoVisibility, SourceLocation());
+}
+
+void Sema::PopPragmaVisibility() {
+ // Pop visibility from stack, if there is one on the stack.
+ if (VisContext) {
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+
+ Stack->pop_back();
+ // To simplify the implementation, never keep around an empty stack.
+ if (Stack->empty())
+ FreeVisContext();
+ }
+ // FIXME: Add diag for pop without push.
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp
new file mode 100644
index 0000000..506d261
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp
@@ -0,0 +1,1625 @@
+//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ named casts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+#include <set>
+using namespace clang;
+
+
+
+enum TryCastResult {
+ TC_NotApplicable, ///< The cast method is not applicable.
+ TC_Success, ///< The cast method is appropriate and successful.
+ TC_Failed ///< The cast method is appropriate, but failed. A
+ ///< diagnostic has been emitted.
+};
+
+enum CastType {
+ CT_Const, ///< const_cast
+ CT_Static, ///< static_cast
+ CT_Reinterpret, ///< reinterpret_cast
+ CT_Dynamic, ///< dynamic_cast
+ CT_CStyle, ///< (Type)expr
+ CT_Functional ///< Type(expr)
+};
+
+
+
+
+static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
+ const SourceRange &OpRange,
+ const SourceRange &DestRange);
+static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
+ const SourceRange &OpRange,
+ const SourceRange &DestRange,
+ CastKind &Kind);
+static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
+ const SourceRange &OpRange,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
+ const SourceRange &OpRange,
+ const SourceRange &DestRange,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+
+static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
+
+// The Try functions attempt a specific way of casting. If they succeed, they
+// return TC_Success. If their way of casting is not appropriate for the given
+// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic
+// to emit if no other way succeeds. If their way of casting is appropriate but
+// fails, they return TC_Failed and *must* set diag; they can set it to 0 if
+// they emit a specialized diagnostic.
+// All diagnostics returned by these functions must expect the same three
+// arguments:
+// %0: Cast Type (a value from the CastType enumeration)
+// %1: Source Type
+// %2: Destination Type
+static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+ QualType DestType, bool CStyle,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
+ unsigned &msg);
+static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
+ CanQualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ QualType OrigSrcType,
+ QualType OrigDestType, unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
+ QualType SrcType,
+ QualType DestType,bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+
+static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind);
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath);
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+ bool CStyle, unsigned &msg);
+static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind);
+
+
+static ExprResult
+ResolveAndFixSingleFunctionTemplateSpecialization(
+ Sema &Self, Expr *SrcExpr,
+ bool DoFunctionPointerConverion = false,
+ bool Complain = false,
+ const SourceRange& OpRangeForComplaining = SourceRange(),
+ QualType DestTypeForComplaining = QualType(),
+ unsigned DiagIDForComplaining = 0);
+
+
+
+/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ExprResult
+Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc, ParsedType Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc, Expr *E,
+ SourceLocation RParenLoc) {
+
+ TypeSourceInfo *DestTInfo;
+ QualType DestType = GetTypeFromParser(Ty, &DestTInfo);
+ if (!DestTInfo)
+ DestTInfo = Context.getTrivialTypeSourceInfo(DestType, SourceLocation());
+
+ return BuildCXXNamedCast(OpLoc, Kind, DestTInfo, move(E),
+ SourceRange(LAngleBracketLoc, RAngleBracketLoc),
+ SourceRange(LParenLoc, RParenLoc));
+}
+
+ExprResult
+Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ TypeSourceInfo *DestTInfo, Expr *Ex,
+ SourceRange AngleBrackets, SourceRange Parens) {
+ QualType DestType = DestTInfo->getType();
+
+ SourceRange OpRange(OpLoc, Parens.getEnd());
+ SourceRange DestRange = AngleBrackets;
+
+ // If the type is dependent, we won't do the semantic analysis now.
+ // FIXME: should we check this in a more fine-grained manner?
+ bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();
+
+ if (Ex->isBoundMemberFunction(Context))
+ Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+ << Ex->getSourceRange();
+
+ ExprValueKind VK = VK_RValue;
+ if (TypeDependent)
+ VK = Expr::getValueKindForType(DestType);
+
+ switch (Kind) {
+ default: llvm_unreachable("Unknown C++ cast!");
+
+ case tok::kw_const_cast:
+ if (!TypeDependent)
+ CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
+ return Owned(CXXConstCastExpr::Create(Context,
+ DestType.getNonLValueExprType(Context),
+ VK, Ex, DestTInfo, OpLoc,
+ Parens.getEnd()));
+
+ case tok::kw_dynamic_cast: {
+ CastKind Kind = CK_Dependent;
+ CXXCastPath BasePath;
+ if (!TypeDependent)
+ CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
+ Kind, BasePath);
+ return Owned(CXXDynamicCastExpr::Create(Context,
+ DestType.getNonLValueExprType(Context),
+ VK, Kind, Ex, &BasePath, DestTInfo,
+ OpLoc, Parens.getEnd()));
+ }
+ case tok::kw_reinterpret_cast: {
+ CastKind Kind = CK_Dependent;
+ if (!TypeDependent)
+ CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
+ return Owned(CXXReinterpretCastExpr::Create(Context,
+ DestType.getNonLValueExprType(Context),
+ VK, Kind, Ex, 0,
+ DestTInfo, OpLoc, Parens.getEnd()));
+ }
+ case tok::kw_static_cast: {
+ CastKind Kind = CK_Dependent;
+ CXXCastPath BasePath;
+ if (!TypeDependent)
+ CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
+
+ return Owned(CXXStaticCastExpr::Create(Context,
+ DestType.getNonLValueExprType(Context),
+ VK, Kind, Ex, &BasePath,
+ DestTInfo, OpLoc, Parens.getEnd()));
+ }
+ }
+
+ return ExprError();
+}
+
+/// Try to diagnose a failed overloaded cast. Returns true if
+/// diagnostics were emitted.
+static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
+ SourceRange range, Expr *src,
+ QualType destType) {
+ switch (CT) {
+ // These cast kinds don't consider user-defined conversions.
+ case CT_Const:
+ case CT_Reinterpret:
+ case CT_Dynamic:
+ return false;
+
+ // These do.
+ case CT_Static:
+ case CT_CStyle:
+ case CT_Functional:
+ break;
+ }
+
+ QualType srcType = src->getType();
+ if (!destType->isRecordType() && !srcType->isRecordType())
+ return false;
+
+ InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
+ InitializationKind initKind
+ = InitializationKind::CreateCast(/*type range?*/ range,
+ (CT == CT_CStyle || CT == CT_Functional));
+ InitializationSequence sequence(S, entity, initKind, &src, 1);
+
+ assert(sequence.getKind() == InitializationSequence::FailedSequence &&
+ "initialization succeeded on second try?");
+ switch (sequence.getFailureKind()) {
+ default: return false;
+
+ case InitializationSequence::FK_ConstructorOverloadFailed:
+ case InitializationSequence::FK_UserConversionOverloadFailed:
+ break;
+ }
+
+ OverloadCandidateSet &candidates = sequence.getFailedCandidateSet();
+
+ unsigned msg = 0;
+ OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates;
+
+ switch (sequence.getFailedOverloadResult()) {
+ case OR_Success: llvm_unreachable("successful failed overload");
+ return false;
+ case OR_No_Viable_Function:
+ if (candidates.empty())
+ msg = diag::err_ovl_no_conversion_in_cast;
+ else
+ msg = diag::err_ovl_no_viable_conversion_in_cast;
+ howManyCandidates = OCD_AllCandidates;
+ break;
+
+ case OR_Ambiguous:
+ msg = diag::err_ovl_ambiguous_conversion_in_cast;
+ howManyCandidates = OCD_ViableCandidates;
+ break;
+
+ case OR_Deleted:
+ msg = diag::err_ovl_deleted_conversion_in_cast;
+ howManyCandidates = OCD_ViableCandidates;
+ break;
+ }
+
+ S.Diag(range.getBegin(), msg)
+ << CT << srcType << destType
+ << range << src->getSourceRange();
+
+ candidates.NoteCandidates(S, howManyCandidates, &src, 1);
+
+ return true;
+}
+
+/// Diagnose a failed cast.
+static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
+ SourceRange opRange, Expr *src, QualType destType) {
+ if (msg == diag::err_bad_cxx_cast_generic &&
+ tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
+ return;
+
+ S.Diag(opRange.getBegin(), msg) << castType
+ << src->getType() << destType << opRange << src->getSourceRange();
+}
+
+/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
+/// this removes one level of indirection from both types, provided that they're
+/// the same kind of pointer (plain or to-member). Unlike the Sema function,
+/// this one doesn't care if the two pointers-to-member don't point into the
+/// same class. This is because CastsAwayConstness doesn't care.
+static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
+ const PointerType *T1PtrType = T1->getAs<PointerType>(),
+ *T2PtrType = T2->getAs<PointerType>();
+ if (T1PtrType && T2PtrType) {
+ T1 = T1PtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+ const ObjCObjectPointerType *T1ObjCPtrType =
+ T1->getAs<ObjCObjectPointerType>(),
+ *T2ObjCPtrType =
+ T2->getAs<ObjCObjectPointerType>();
+ if (T1ObjCPtrType) {
+ if (T2ObjCPtrType) {
+ T1 = T1ObjCPtrType->getPointeeType();
+ T2 = T2ObjCPtrType->getPointeeType();
+ return true;
+ }
+ else if (T2PtrType) {
+ T1 = T1ObjCPtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+ }
+ else if (T2ObjCPtrType) {
+ if (T1PtrType) {
+ T2 = T2ObjCPtrType->getPointeeType();
+ T1 = T1PtrType->getPointeeType();
+ return true;
+ }
+ }
+
+ const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
+ *T2MPType = T2->getAs<MemberPointerType>();
+ if (T1MPType && T2MPType) {
+ T1 = T1MPType->getPointeeType();
+ T2 = T2MPType->getPointeeType();
+ return true;
+ }
+
+ const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
+ *T2BPType = T2->getAs<BlockPointerType>();
+ if (T1BPType && T2BPType) {
+ T1 = T1BPType->getPointeeType();
+ T2 = T2BPType->getPointeeType();
+ return true;
+ }
+
+ return false;
+}
+
+/// CastsAwayConstness - Check if the pointer conversion from SrcType to
+/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
+/// the cast checkers. Both arguments must denote pointer (possibly to member)
+/// types.
+static bool
+CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
+ // Casting away constness is defined in C++ 5.2.11p8 with reference to
+ // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
+ // the rules are non-trivial. So first we construct Tcv *...cv* as described
+ // in C++ 5.2.11p8.
+ assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
+ SrcType->isBlockPointerType()) &&
+ "Source type is not pointer or pointer to member.");
+ assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
+ DestType->isBlockPointerType()) &&
+ "Destination type is not pointer or pointer to member.");
+
+ QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
+ UnwrappedDestType = Self.Context.getCanonicalType(DestType);
+ llvm::SmallVector<Qualifiers, 8> cv1, cv2;
+
+ // Find the qualifications.
+ while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
+ Qualifiers SrcQuals;
+ Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
+ cv1.push_back(SrcQuals);
+
+ Qualifiers DestQuals;
+ Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
+ cv2.push_back(DestQuals);
+ }
+ if (cv1.empty())
+ return false;
+
+ // Construct void pointers with those qualifiers (in reverse order of
+ // unwrapping, of course).
+ QualType SrcConstruct = Self.Context.VoidTy;
+ QualType DestConstruct = Self.Context.VoidTy;
+ ASTContext &Context = Self.Context;
+ for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+ i2 = cv2.rbegin();
+ i1 != cv1.rend(); ++i1, ++i2) {
+ SrcConstruct
+ = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+ DestConstruct
+ = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
+ }
+
+ // Test if they're compatible.
+ return SrcConstruct != DestConstruct &&
+ !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false);
+}
+
+/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
+/// checked downcasts in class hierarchies.
+static void
+CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK, const SourceRange &OpRange,
+ const SourceRange &DestRange, CastKind &Kind,
+ CXXCastPath &BasePath) {
+ QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
+ DestType = Self.Context.getCanonicalType(DestType);
+
+ // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
+ // or "pointer to cv void".
+
+ QualType DestPointee;
+ const PointerType *DestPointer = DestType->getAs<PointerType>();
+ const ReferenceType *DestReference = 0;
+ if (DestPointer) {
+ DestPointee = DestPointer->getPointeeType();
+ } else if ((DestReference = DestType->getAs<ReferenceType>())) {
+ DestPointee = DestReference->getPointeeType();
+ VK = isa<LValueReferenceType>(DestReference) ? VK_LValue
+ : isa<RValueReferenceType>(DestReference) ? VK_XValue
+ : VK_RValue;
+ } else {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
+ << OrigDestType << DestRange;
+ return;
+ }
+
+ const RecordType *DestRecord = DestPointee->getAs<RecordType>();
+ if (DestPointee->isVoidType()) {
+ assert(DestPointer && "Reference to void is not possible");
+ } else if (DestRecord) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
+ Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
+ << DestRange))
+ return;
+ } else {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+ << DestPointee.getUnqualifiedType() << DestRange;
+ return;
+ }
+
+ // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
+ // complete class type, [...]. If T is an lvalue reference type, v shall be
+ // an lvalue of a complete class type, [...]. If T is an rvalue reference
+ // type, v shall be an expression having a complete class type, [...]
+ QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
+ QualType SrcPointee;
+ if (DestPointer) {
+ if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+ SrcPointee = SrcPointer->getPointeeType();
+ } else {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
+ << OrigSrcType << SrcExpr->getSourceRange();
+ return;
+ }
+ } else if (DestReference->isLValueReferenceType()) {
+ if (!SrcExpr->isLValue()) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
+ << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+ }
+ SrcPointee = SrcType;
+ } else {
+ SrcPointee = SrcType;
+ }
+
+ const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
+ if (SrcRecord) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
+ Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
+ << SrcExpr->getSourceRange()))
+ return;
+ } else {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
+ << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+ return;
+ }
+
+ assert((DestPointer || DestReference) &&
+ "Bad destination non-ptr/ref slipped through.");
+ assert((DestRecord || DestPointee->isVoidType()) &&
+ "Bad destination pointee slipped through.");
+ assert(SrcRecord && "Bad source pointee slipped through.");
+
+ // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
+ if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away)
+ << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+ return;
+ }
+
+ // C++ 5.2.7p3: If the type of v is the same as the required result type,
+ // [except for cv].
+ if (DestRecord == SrcRecord) {
+ Kind = CK_NoOp;
+ return;
+ }
+
+ // C++ 5.2.7p5
+ // Upcasts are resolved statically.
+ if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
+ if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
+ OpRange.getBegin(), OpRange,
+ &BasePath))
+ return;
+
+ Kind = CK_DerivedToBase;
+
+ // If we are casting to or through a virtual base class, we need a
+ // vtable.
+ if (Self.BasePathInvolvesVirtualBase(BasePath))
+ Self.MarkVTableUsed(OpRange.getBegin(),
+ cast<CXXRecordDecl>(SrcRecord->getDecl()));
+ return;
+ }
+
+ // C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
+ const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition();
+ assert(SrcDecl && "Definition missing");
+ if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
+ << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
+ }
+ Self.MarkVTableUsed(OpRange.getBegin(),
+ cast<CXXRecordDecl>(SrcRecord->getDecl()));
+
+ // Done. Everything else is run-time checks.
+ Kind = CK_Dynamic;
+}
+
+/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.11 for details. const_cast is typically used in code
+/// like this:
+/// const char *str = "literal";
+/// legacy_function(const_cast\<char*\>(str));
+void
+CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK,
+ const SourceRange &OpRange, const SourceRange &DestRange) {
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue)
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+ unsigned msg = diag::err_bad_cxx_cast_generic;
+ if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
+ && msg != 0)
+ Self.Diag(OpRange.getBegin(), msg) << CT_Const
+ << SrcExpr->getType() << DestType << OpRange;
+}
+
+/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
+/// valid.
+/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
+/// like this:
+/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
+void
+CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK, const SourceRange &OpRange,
+ const SourceRange &DestRange, CastKind &Kind) {
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue)
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+ unsigned msg = diag::err_bad_cxx_cast_generic;
+ if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
+ msg, Kind)
+ != TC_Success && msg != 0)
+ {
+ if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ //FIXME: &f<int>; is overloaded and resolvable
+ Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
+ << OverloadExpr::find(SrcExpr).Expression->getName()
+ << DestType << OpRange;
+ Self.NoteAllOverloadCandidates(SrcExpr);
+
+ } else {
+ diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType);
+ }
+ }
+}
+
+
+/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
+/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
+/// implicit conversions explicit and getting rid of data loss warnings.
+void
+CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK, const SourceRange &OpRange,
+ CastKind &Kind, CXXCastPath &BasePath) {
+ // This test is outside everything else because it's the only case where
+ // a non-lvalue-reference target type does not lead to decay.
+ // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+ if (DestType->isVoidType()) {
+ Self.IgnoredValueConversions(SrcExpr);
+ if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ ExprResult SingleFunctionExpression =
+ ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
+ false, // Decay Function to ptr
+ true, // Complain
+ OpRange, DestType, diag::err_bad_static_cast_overload);
+ if (SingleFunctionExpression.isUsable())
+ {
+ SrcExpr = SingleFunctionExpression.release();
+ Kind = CK_ToVoid;
+ }
+ }
+ else
+ Kind = CK_ToVoid;
+ return;
+ }
+
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue && !DestType->isRecordType())
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
+
+ unsigned msg = diag::err_bad_cxx_cast_generic;
+ if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
+ Kind, BasePath) != TC_Success && msg != 0) {
+ if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
+ Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
+ << oe->getName() << DestType << OpRange << oe->getQualifierRange();
+ Self.NoteAllOverloadCandidates(SrcExpr);
+ } else {
+ diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType);
+ }
+ }
+ else if (Kind == CK_BitCast)
+ Self.CheckCastAlign(SrcExpr, DestType, OpRange);
+}
+
+/// TryStaticCast - Check if a static cast can be performed, and do so if
+/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
+/// and casting away constness.
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange, unsigned &msg,
+ CastKind &Kind,
+ CXXCastPath &BasePath) {
+ // The order the tests is not entirely arbitrary. There is one conversion
+ // that can be handled in two different ways. Given:
+ // struct A {};
+ // struct B : public A {
+ // B(); B(const A&);
+ // };
+ // const A &a = B();
+ // the cast static_cast<const B&>(a) could be seen as either a static
+ // reference downcast, or an explicit invocation of the user-defined
+ // conversion using B's conversion constructor.
+ // DR 427 specifies that the downcast is to be applied here.
+
+ // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+ // Done outside this function.
+
+ TryCastResult tcr;
+
+ // C++ 5.2.9p5, reference downcast.
+ // See the function for details.
+ // DR 427 specifies that this is to be applied before paragraph 2.
+ tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange,
+ msg, Kind, BasePath);
+ if (tcr != TC_NotApplicable)
+ return tcr;
+
+ // C++0x [expr.static.cast]p3:
+ // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
+ // T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+ tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, CStyle, Kind, BasePath,
+ msg);
+ if (tcr != TC_NotApplicable)
+ return tcr;
+
+ // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
+ // [...] if the declaration "T t(e);" is well-formed, [...].
+ tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
+ Kind);
+ if (tcr != TC_NotApplicable)
+ return tcr;
+
+ // C++ 5.2.9p6: May apply the reverse of any standard conversion, except
+ // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
+ // conversions, subject to further restrictions.
+ // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal
+ // of qualification conversions impossible.
+ // In the CStyle case, the earlier attempt to const_cast should have taken
+ // care of reverse qualification conversions.
+
+ QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType());
+
+ // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
+ // converted to an integral type. [...] A value of a scoped enumeration type
+ // can also be explicitly converted to a floating-point type [...].
+ if (const EnumType *Enum = SrcType->getAs<EnumType>()) {
+ if (Enum->getDecl()->isScoped()) {
+ if (DestType->isBooleanType()) {
+ Kind = CK_IntegralToBoolean;
+ return TC_Success;
+ } else if (DestType->isIntegralType(Self.Context)) {
+ Kind = CK_IntegralCast;
+ return TC_Success;
+ } else if (DestType->isRealFloatingType()) {
+ Kind = CK_IntegralToFloating;
+ return TC_Success;
+ }
+ }
+ }
+
+ // Reverse integral promotion/conversion. All such conversions are themselves
+ // again integral promotions or conversions and are thus already handled by
+ // p2 (TryDirectInitialization above).
+ // (Note: any data loss warnings should be suppressed.)
+ // The exception is the reverse of enum->integer, i.e. integer->enum (and
+ // enum->enum). See also C++ 5.2.9p7.
+ // The same goes for reverse floating point promotion/conversion and
+ // floating-integral conversions. Again, only floating->enum is relevant.
+ if (DestType->isEnumeralType()) {
+ if (SrcType->isComplexType() || SrcType->isVectorType()) {
+ // Fall through - these cannot be converted.
+ } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) {
+ Kind = CK_IntegralCast;
+ return TC_Success;
+ }
+ }
+
+ // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
+ // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
+ tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
+ Kind, BasePath);
+ if (tcr != TC_NotApplicable)
+ return tcr;
+
+ // Reverse member pointer conversion. C++ 4.11 specifies member pointer
+ // conversion. C++ 5.2.9p9 has additional information.
+ // DR54's access restrictions apply here also.
+ tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle,
+ OpRange, msg, Kind, BasePath);
+ if (tcr != TC_NotApplicable)
+ return tcr;
+
+ // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to
+ // void*. C++ 5.2.9p10 specifies additional restrictions, which really is
+ // just the usual constness stuff.
+ if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
+ QualType SrcPointee = SrcPointer->getPointeeType();
+ if (SrcPointee->isVoidType()) {
+ if (const PointerType *DestPointer = DestType->getAs<PointerType>()) {
+ QualType DestPointee = DestPointer->getPointeeType();
+ if (DestPointee->isIncompleteOrObjectType()) {
+ // This is definitely the intended conversion, but it might fail due
+ // to a const violation.
+ if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
+ msg = diag::err_bad_cxx_cast_const_away;
+ return TC_Failed;
+ }
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+ }
+ else if (DestType->isObjCObjectPointerType()) {
+ // allow both c-style cast and static_cast of objective-c pointers as
+ // they are pervasive.
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return TC_Success;
+ }
+ else if (CStyle && DestType->isBlockPointerType()) {
+ // allow c-style cast of void * to block pointers.
+ Kind = CK_AnyPointerToBlockPointerCast;
+ return TC_Success;
+ }
+ }
+ }
+ // Allow arbitray objective-c pointer conversion with static casts.
+ if (SrcType->isObjCObjectPointerType() &&
+ DestType->isObjCObjectPointerType()) {
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+
+ // We tried everything. Everything! Nothing works! :-(
+ return TC_NotApplicable;
+}
+
+/// Tests whether a conversion according to N2844 is valid.
+TryCastResult
+TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+ bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
+ unsigned &msg) {
+ // C++0x [expr.static.cast]p3:
+ // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
+ // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+ const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
+ if (!R)
+ return TC_NotApplicable;
+
+ if (!SrcExpr->isGLValue())
+ return TC_NotApplicable;
+
+ // Because we try the reference downcast before this function, from now on
+ // this is the only cast possibility, so we issue an error if we fail now.
+ // FIXME: Should allow casting away constness if CStyle.
+ bool DerivedToBase;
+ bool ObjCConversion;
+ QualType FromType = SrcExpr->getType();
+ QualType ToType = R->getPointeeType();
+ if (CStyle) {
+ FromType = FromType.getUnqualifiedType();
+ ToType = ToType.getUnqualifiedType();
+ }
+
+ if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
+ ToType, FromType,
+ DerivedToBase, ObjCConversion) <
+ Sema::Ref_Compatible_With_Added_Qualification) {
+ msg = diag::err_bad_lvalue_to_rvalue_cast;
+ return TC_Failed;
+ }
+
+ if (DerivedToBase) {
+ Kind = CK_DerivedToBase;
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/true);
+ if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
+ return TC_NotApplicable;
+
+ Self.BuildBasePathArray(Paths, BasePath);
+ } else
+ Kind = CK_NoOp;
+
+ return TC_Success;
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
+TryCastResult
+TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
+ bool CStyle, const SourceRange &OpRange,
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
+ // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
+ // cast to type "reference to cv2 D", where D is a class derived from B,
+ // if a valid standard conversion from "pointer to D" to "pointer to B"
+ // exists, cv2 >= cv1, and B is not a virtual base class of D.
+ // In addition, DR54 clarifies that the base must be accessible in the
+ // current context. Although the wording of DR54 only applies to the pointer
+ // variant of this rule, the intent is clearly for it to apply to the this
+ // conversion as well.
+
+ const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+ if (!DestReference) {
+ return TC_NotApplicable;
+ }
+ bool RValueRef = DestReference->isRValueReferenceType();
+ if (!RValueRef && !SrcExpr->isLValue()) {
+ // We know the left side is an lvalue reference, so we can suggest a reason.
+ msg = diag::err_bad_cxx_cast_rvalue;
+ return TC_NotApplicable;
+ }
+
+ QualType DestPointee = DestReference->getPointeeType();
+
+ return TryStaticDowncast(Self,
+ Self.Context.getCanonicalType(SrcExpr->getType()),
+ Self.Context.getCanonicalType(DestPointee), CStyle,
+ OpRange, SrcExpr->getType(), DestType, msg, Kind,
+ BasePath);
+}
+
+/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
+TryCastResult
+TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
+ bool CStyle, const SourceRange &OpRange,
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
+ // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
+ // type, can be converted to an rvalue of type "pointer to cv2 D", where D
+ // is a class derived from B, if a valid standard conversion from "pointer
+ // to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base
+ // class of D.
+ // In addition, DR54 clarifies that the base must be accessible in the
+ // current context.
+
+ const PointerType *DestPointer = DestType->getAs<PointerType>();
+ if (!DestPointer) {
+ return TC_NotApplicable;
+ }
+
+ const PointerType *SrcPointer = SrcType->getAs<PointerType>();
+ if (!SrcPointer) {
+ msg = diag::err_bad_static_cast_pointer_nonpointer;
+ return TC_NotApplicable;
+ }
+
+ return TryStaticDowncast(Self,
+ Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
+ Self.Context.getCanonicalType(DestPointer->getPointeeType()),
+ CStyle, OpRange, SrcType, DestType, msg, Kind,
+ BasePath);
+}
+
+/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
+/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
+/// DestType is possible and allowed.
+TryCastResult
+TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
+ bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
+ QualType OrigDestType, unsigned &msg,
+ CastKind &Kind, CXXCastPath &BasePath) {
+ // We can only work with complete types. But don't complain if it doesn't work
+ if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) ||
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
+ return TC_NotApplicable;
+
+ // Downcast can only happen in class hierarchies, so we need classes.
+ if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) {
+ return TC_NotApplicable;
+ }
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/true);
+ if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
+ return TC_NotApplicable;
+ }
+
+ // Target type does derive from source type. Now we're serious. If an error
+ // appears now, it's not ignored.
+ // This may not be entirely in line with the standard. Take for example:
+ // struct A {};
+ // struct B : virtual A {
+ // B(A&);
+ // };
+ //
+ // void f()
+ // {
+ // (void)static_cast<const B&>(*((A*)0));
+ // }
+ // As far as the standard is concerned, p5 does not apply (A is virtual), so
+ // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid.
+ // However, both GCC and Comeau reject this example, and accepting it would
+ // mean more complex code if we're to preserve the nice error message.
+ // FIXME: Being 100% compliant here would be nice to have.
+
+ // Must preserve cv, as always, unless we're in C-style mode.
+ if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) {
+ msg = diag::err_bad_cxx_cast_const_away;
+ return TC_Failed;
+ }
+
+ if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) {
+ // This code is analoguous to that in CheckDerivedToBaseConversion, except
+ // that it builds the paths in reverse order.
+ // To sum up: record all paths to the base and build a nice string from
+ // them. Use it to spice up the error message.
+ if (!Paths.isRecordingPaths()) {
+ Paths.clear();
+ Paths.setRecordingPaths(true);
+ Self.IsDerivedFrom(DestType, SrcType, Paths);
+ }
+ std::string PathDisplayStr;
+ std::set<unsigned> DisplayedPaths;
+ for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+ PI != PE; ++PI) {
+ if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) {
+ // We haven't displayed a path to this particular base
+ // class subobject yet.
+ PathDisplayStr += "\n ";
+ for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(),
+ EE = PI->rend();
+ EI != EE; ++EI)
+ PathDisplayStr += EI->Base->getType().getAsString() + " -> ";
+ PathDisplayStr += QualType(DestType).getAsString();
+ }
+ }
+
+ Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
+ << QualType(SrcType).getUnqualifiedType()
+ << QualType(DestType).getUnqualifiedType()
+ << PathDisplayStr << OpRange;
+ msg = 0;
+ return TC_Failed;
+ }
+
+ if (Paths.getDetectedVirtual() != 0) {
+ QualType VirtualBase(Paths.getDetectedVirtual(), 0);
+ Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
+ << OrigSrcType << OrigDestType << VirtualBase << OpRange;
+ msg = 0;
+ return TC_Failed;
+ }
+
+ if (!CStyle) {
+ switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
+ SrcType, DestType,
+ Paths.front(),
+ diag::err_downcast_from_inaccessible_base)) {
+ case Sema::AR_accessible:
+ case Sema::AR_delayed: // be optimistic
+ case Sema::AR_dependent: // be optimistic
+ break;
+
+ case Sema::AR_inaccessible:
+ msg = 0;
+ return TC_Failed;
+ }
+ }
+
+ Self.BuildBasePathArray(Paths, BasePath);
+ Kind = CK_BaseToDerived;
+ return TC_Success;
+}
+
+/// TryStaticMemberPointerUpcast - Tests whether a conversion according to
+/// C++ 5.2.9p9 is valid:
+///
+/// An rvalue of type "pointer to member of D of type cv1 T" can be
+/// converted to an rvalue of type "pointer to member of B of type cv2 T",
+/// where B is a base class of D [...].
+///
+TryCastResult
+TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
+ const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
+ if (!DestMemPtr)
+ return TC_NotApplicable;
+
+ bool WasOverloadedFunction = false;
+ DeclAccessPair FoundOverload;
+ if (SrcExpr->getType() == Self.Context.OverloadTy) {
+ if (FunctionDecl *Fn
+ = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+ FoundOverload)) {
+ CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+ SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+ Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
+ WasOverloadedFunction = true;
+ }
+ }
+
+ const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+ if (!SrcMemPtr) {
+ msg = diag::err_bad_static_cast_member_pointer_nonmp;
+ return TC_NotApplicable;
+ }
+
+ // T == T, modulo cv
+ if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
+ DestMemPtr->getPointeeType()))
+ return TC_NotApplicable;
+
+ // B base of D
+ QualType SrcClass(SrcMemPtr->getClass(), 0);
+ QualType DestClass(DestMemPtr->getClass(), 0);
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/true);
+ if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+ return TC_NotApplicable;
+ }
+
+ // B is a base of D. But is it an allowed base? If not, it's a hard error.
+ if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) {
+ Paths.clear();
+ Paths.setRecordingPaths(true);
+ bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
+ assert(StillOkay);
+ (void)StillOkay;
+ std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
+ Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv)
+ << 1 << SrcClass << DestClass << PathDisplayStr << OpRange;
+ msg = 0;
+ return TC_Failed;
+ }
+
+ if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+ Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual)
+ << SrcClass << DestClass << QualType(VBase, 0) << OpRange;
+ msg = 0;
+ return TC_Failed;
+ }
+
+ if (!CStyle) {
+ switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
+ DestClass, SrcClass,
+ Paths.front(),
+ diag::err_upcast_to_inaccessible_base)) {
+ case Sema::AR_accessible:
+ case Sema::AR_delayed:
+ case Sema::AR_dependent:
+ // Optimistically assume that the delayed and dependent cases
+ // will work out.
+ break;
+
+ case Sema::AR_inaccessible:
+ msg = 0;
+ return TC_Failed;
+ }
+ }
+
+ if (WasOverloadedFunction) {
+ // Resolve the address of the overloaded function again, this time
+ // allowing complaints if something goes wrong.
+ FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr,
+ DestType,
+ true,
+ FoundOverload);
+ if (!Fn) {
+ msg = 0;
+ return TC_Failed;
+ }
+
+ SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
+ if (!SrcExpr) {
+ msg = 0;
+ return TC_Failed;
+ }
+ }
+
+ Self.BuildBasePathArray(Paths, BasePath);
+ Kind = CK_DerivedToBaseMemberPointer;
+ return TC_Success;
+}
+
+/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
+/// is valid:
+///
+/// An expression e can be explicitly converted to a type T using a
+/// @c static_cast if the declaration "T t(e);" is well-formed [...].
+TryCastResult
+TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ bool CStyle, const SourceRange &OpRange, unsigned &msg,
+ CastKind &Kind) {
+ if (DestType->isRecordType()) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
+ diag::err_bad_dynamic_cast_incomplete)) {
+ msg = 0;
+ return TC_Failed;
+ }
+ }
+
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
+ InitializationKind InitKind
+ = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle);
+ InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1);
+
+ // At this point of CheckStaticCast, if the destination is a reference,
+ // or the expression is an overload expression this has to work.
+ // There is no other way that works.
+ // On the other hand, if we're checking a C-style cast, we've still got
+ // the reinterpret_cast way.
+
+ if (InitSeq.getKind() == InitializationSequence::FailedSequence &&
+ (CStyle || !DestType->isReferenceType()))
+ return TC_NotApplicable;
+
+ ExprResult Result
+ = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1));
+ if (Result.isInvalid()) {
+ msg = 0;
+ return TC_Failed;
+ }
+
+ if (InitSeq.isConstructorInitialization())
+ Kind = CK_ConstructorConversion;
+ else
+ Kind = CK_NoOp;
+
+ SrcExpr = Result.takeAs<Expr>();
+ return TC_Success;
+}
+
+/// TryConstCast - See if a const_cast from source to destination is allowed,
+/// and perform it if it is.
+static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+ bool CStyle, unsigned &msg) {
+ DestType = Self.Context.getCanonicalType(DestType);
+ QualType SrcType = SrcExpr->getType();
+ if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
+ if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) {
+ // Cannot const_cast non-lvalue to lvalue reference type. But if this
+ // is C-style, static_cast might find a way, so we simply suggest a
+ // message and tell the parent to keep searching.
+ msg = diag::err_bad_cxx_cast_rvalue;
+ return TC_NotApplicable;
+ }
+
+ // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
+ // [...] if a pointer to T1 can be [cast] to the type pointer to T2.
+ DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+ SrcType = Self.Context.getPointerType(SrcType);
+ }
+
+ // C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
+ // the rules for const_cast are the same as those used for pointers.
+
+ if (!DestType->isPointerType() &&
+ !DestType->isMemberPointerType() &&
+ !DestType->isObjCObjectPointerType()) {
+ // Cannot cast to non-pointer, non-reference type. Note that, if DestType
+ // was a reference type, we converted it to a pointer above.
+ // The status of rvalue references isn't entirely clear, but it looks like
+ // conversion to them is simply invalid.
+ // C++ 5.2.11p3: For two pointer types [...]
+ if (!CStyle)
+ msg = diag::err_bad_const_cast_dest;
+ return TC_NotApplicable;
+ }
+ if (DestType->isFunctionPointerType() ||
+ DestType->isMemberFunctionPointerType()) {
+ // Cannot cast direct function pointers.
+ // C++ 5.2.11p2: [...] where T is any object type or the void type [...]
+ // T is the ultimate pointee of source and target type.
+ if (!CStyle)
+ msg = diag::err_bad_const_cast_dest;
+ return TC_NotApplicable;
+ }
+ SrcType = Self.Context.getCanonicalType(SrcType);
+
+ // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
+ // completely equal.
+ // FIXME: const_cast should probably not be able to convert between pointers
+ // to different address spaces.
+ // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
+ // in multi-level pointers may change, but the level count must be the same,
+ // as must be the final pointee type.
+ while (SrcType != DestType &&
+ Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
+ Qualifiers Quals;
+ SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals);
+ DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals);
+ }
+
+ // Since we're dealing in canonical types, the remainder must be the same.
+ if (SrcType != DestType)
+ return TC_NotApplicable;
+
+ return TC_Success;
+}
+
+// A helper function to resolve and fix an overloaded expression that
+// can be resolved because it identifies a single function
+// template specialization
+// Last three arguments should only be supplied if Complain = true
+static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
+ Sema &Self, Expr *SrcExpr,
+ bool DoFunctionPointerConverion,
+ bool Complain,
+ const SourceRange& OpRangeForComplaining,
+ QualType DestTypeForComplaining,
+ unsigned DiagIDForComplaining) {
+ assert(SrcExpr->getType() == Self.Context.OverloadTy);
+ DeclAccessPair Found;
+ Expr* SingleFunctionExpression = 0;
+ if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization(
+ SrcExpr, false, // false -> Complain
+ &Found)) {
+ if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
+ // mark the expression as resolved to Fn
+ SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr,
+ Found, Fn);
+
+ if (DoFunctionPointerConverion)
+ Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression);
+ }
+ }
+ if (!SingleFunctionExpression && Complain) {
+ OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
+ Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+ << oe->getName() << DestTypeForComplaining << OpRangeForComplaining
+ << oe->getQualifierRange();
+ Self.NoteAllOverloadCandidates(SrcExpr);
+ }
+ return SingleFunctionExpression;
+}
+
+static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
+ QualType DestType, bool CStyle,
+ const SourceRange &OpRange,
+ unsigned &msg,
+ CastKind &Kind) {
+ bool IsLValueCast = false;
+
+ DestType = Self.Context.getCanonicalType(DestType);
+ QualType SrcType = SrcExpr->getType();
+
+ // Is the source an overloaded name? (i.e. &foo)
+ // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
+ if (SrcType == Self.Context.OverloadTy) {
+ // ... unless foo<int> resolves to an lvalue unambiguously
+ ExprResult SingleFunctionExpr =
+ ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
+ Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
+ );
+ if (SingleFunctionExpr.isUsable()) {
+ SrcExpr = SingleFunctionExpr.release();
+ SrcType = SrcExpr->getType();
+ }
+ else
+ return TC_NotApplicable;
+ }
+
+ if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
+ bool LValue = DestTypeTmp->isLValueReferenceType();
+ if (LValue && !SrcExpr->isLValue()) {
+ // Cannot cast non-lvalue to lvalue reference type. See the similar
+ // comment in const_cast.
+ msg = diag::err_bad_cxx_cast_rvalue;
+ return TC_NotApplicable;
+ }
+
+ // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
+ // same effect as the conversion *reinterpret_cast<T*>(&x) with the
+ // built-in & and * operators.
+ // This code does this transformation for the checked types.
+ DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+ SrcType = Self.Context.getPointerType(SrcType);
+
+ IsLValueCast = true;
+ }
+
+ // Canonicalize source for comparison.
+ SrcType = Self.Context.getCanonicalType(SrcType);
+
+ const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(),
+ *SrcMemPtr = SrcType->getAs<MemberPointerType>();
+ if (DestMemPtr && SrcMemPtr) {
+ // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1"
+ // can be explicitly converted to an rvalue of type "pointer to member
+ // of Y of type T2" if T1 and T2 are both function types or both object
+ // types.
+ if (DestMemPtr->getPointeeType()->isFunctionType() !=
+ SrcMemPtr->getPointeeType()->isFunctionType())
+ return TC_NotApplicable;
+
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
+ // constness.
+ // A reinterpret_cast followed by a const_cast can, though, so in C-style,
+ // we accept it.
+ if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+ msg = diag::err_bad_cxx_cast_const_away;
+ return TC_Failed;
+ }
+
+ // Don't allow casting between member pointers of different sizes.
+ if (Self.Context.getTypeSize(DestMemPtr) !=
+ Self.Context.getTypeSize(SrcMemPtr)) {
+ msg = diag::err_bad_cxx_cast_member_pointer_size;
+ return TC_Failed;
+ }
+
+ // A valid member pointer cast.
+ Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast;
+ return TC_Success;
+ }
+
+ // See below for the enumeral issue.
+ if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) {
+ // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
+ // type large enough to hold it. A value of std::nullptr_t can be
+ // converted to an integral type; the conversion has the same meaning
+ // and validity as a conversion of (void*)0 to the integral type.
+ if (Self.Context.getTypeSize(SrcType) >
+ Self.Context.getTypeSize(DestType)) {
+ msg = diag::err_bad_reinterpret_cast_small_int;
+ return TC_Failed;
+ }
+ Kind = CK_PointerToIntegral;
+ return TC_Success;
+ }
+
+ bool destIsVector = DestType->isVectorType();
+ bool srcIsVector = SrcType->isVectorType();
+ if (srcIsVector || destIsVector) {
+ // FIXME: Should this also apply to floating point types?
+ bool srcIsScalar = SrcType->isIntegralType(Self.Context);
+ bool destIsScalar = DestType->isIntegralType(Self.Context);
+
+ // Check if this is a cast between a vector and something else.
+ if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
+ !(srcIsVector && destIsVector))
+ return TC_NotApplicable;
+
+ // If both types have the same size, we can successfully cast.
+ if (Self.Context.getTypeSize(SrcType)
+ == Self.Context.getTypeSize(DestType)) {
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+
+ if (destIsScalar)
+ msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
+ else if (srcIsScalar)
+ msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
+ else
+ msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
+
+ return TC_Failed;
+ }
+
+ bool destIsPtr = DestType->isAnyPointerType() ||
+ DestType->isBlockPointerType();
+ bool srcIsPtr = SrcType->isAnyPointerType() ||
+ SrcType->isBlockPointerType();
+ if (!destIsPtr && !srcIsPtr) {
+ // Except for std::nullptr_t->integer and lvalue->reference, which are
+ // handled above, at least one of the two arguments must be a pointer.
+ return TC_NotApplicable;
+ }
+
+ if (SrcType == DestType) {
+ // C++ 5.2.10p2 has a note that mentions that, subject to all other
+ // restrictions, a cast to the same type is allowed. The intent is not
+ // entirely clear here, since all other paragraphs explicitly forbid casts
+ // to the same type. However, the behavior of compilers is pretty consistent
+ // on this point: allow same-type conversion if the involved types are
+ // pointers, disallow otherwise.
+ Kind = CK_NoOp;
+ return TC_Success;
+ }
+
+ if (DestType->isIntegralType(Self.Context)) {
+ assert(srcIsPtr && "One type must be a pointer");
+ // C++ 5.2.10p4: A pointer can be explicitly converted to any integral
+ // type large enough to hold it.
+ if (Self.Context.getTypeSize(SrcType) >
+ Self.Context.getTypeSize(DestType)) {
+ msg = diag::err_bad_reinterpret_cast_small_int;
+ return TC_Failed;
+ }
+ Kind = CK_PointerToIntegral;
+ return TC_Success;
+ }
+
+ if (SrcType->isIntegralOrEnumerationType()) {
+ assert(destIsPtr && "One type must be a pointer");
+ // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
+ // converted to a pointer.
+ // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not
+ // necessarily converted to a null pointer value.]
+ Kind = CK_IntegralToPointer;
+ return TC_Success;
+ }
+
+ if (!destIsPtr || !srcIsPtr) {
+ // With the valid non-pointer conversions out of the way, we can be even
+ // more stringent.
+ return TC_NotApplicable;
+ }
+
+ // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
+ // The C-style cast operator can.
+ if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+ msg = diag::err_bad_cxx_cast_const_away;
+ return TC_Failed;
+ }
+
+ // Cannot convert between block pointers and Objective-C object pointers.
+ if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
+ (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
+ return TC_NotApplicable;
+
+ // Any pointer can be cast to an Objective-C pointer type with a C-style
+ // cast.
+ if (CStyle && DestType->isObjCObjectPointerType()) {
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return TC_Success;
+ }
+
+ // Not casting away constness, so the only remaining check is for compatible
+ // pointer categories.
+ Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast;
+
+ if (SrcType->isFunctionPointerType()) {
+ if (DestType->isFunctionPointerType()) {
+ // C++ 5.2.10p6: A pointer to a function can be explicitly converted to
+ // a pointer to a function of a different type.
+ return TC_Success;
+ }
+
+ // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
+ // an object type or vice versa is conditionally-supported.
+ // Compilers support it in C++03 too, though, because it's necessary for
+ // casting the return value of dlsym() and GetProcAddress().
+ // FIXME: Conditionally-supported behavior should be configurable in the
+ // TargetInfo or similar.
+ if (!Self.getLangOptions().CPlusPlus0x)
+ Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange;
+ return TC_Success;
+ }
+
+ if (DestType->isFunctionPointerType()) {
+ // See above.
+ if (!Self.getLangOptions().CPlusPlus0x)
+ Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange;
+ return TC_Success;
+ }
+
+ // C++ 5.2.10p7: A pointer to an object can be explicitly converted to
+ // a pointer to an object of different type.
+ // Void pointers are not specified, but supported by every compiler out there.
+ // So we finish by allowing everything that remains - it's got to be two
+ // object pointers.
+ return TC_Success;
+}
+
+bool
+Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
+ Expr *&CastExpr, CastKind &Kind,
+ CXXCastPath &BasePath,
+ bool FunctionalStyle) {
+ if (CastExpr->isBoundMemberFunction(Context))
+ return Diag(CastExpr->getLocStart(),
+ diag::err_invalid_use_of_bound_member_func)
+ << CastExpr->getSourceRange();
+
+ // This test is outside everything else because it's the only case where
+ // a non-lvalue-reference target type does not lead to decay.
+ // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
+ if (CastTy->isVoidType()) {
+ IgnoredValueConversions(CastExpr);
+ bool ret = false; // false is 'able to convert'
+ if (CastExpr->getType() == Context.OverloadTy) {
+ ExprResult SingleFunctionExpr =
+ ResolveAndFixSingleFunctionTemplateSpecialization(*this,
+ CastExpr,
+ /* Decay Function to ptr */ false,
+ /* Complain */ true,
+ R, CastTy, diag::err_bad_cstyle_cast_overload);
+ if (SingleFunctionExpr.isUsable()) {
+ CastExpr = SingleFunctionExpr.release();
+ Kind = CK_ToVoid;
+ }
+ else
+ ret = true;
+ }
+ else
+ Kind = CK_ToVoid;
+ return ret;
+ }
+
+ // Make sure we determine the value kind before we bail out for
+ // dependent types.
+ VK = Expr::getValueKindForType(CastTy);
+
+ // If the type is dependent, we won't do any other semantic analysis now.
+ if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
+ Kind = CK_Dependent;
+ return false;
+ }
+
+ if (VK == VK_RValue && !CastTy->isRecordType())
+ DefaultFunctionArrayLvalueConversion(CastExpr);
+
+ // C++ [expr.cast]p5: The conversions performed by
+ // - a const_cast,
+ // - a static_cast,
+ // - a static_cast followed by a const_cast,
+ // - a reinterpret_cast, or
+ // - a reinterpret_cast followed by a const_cast,
+ // can be performed using the cast notation of explicit type conversion.
+ // [...] If a conversion can be interpreted in more than one of the ways
+ // listed above, the interpretation that appears first in the list is used,
+ // even if a cast resulting from that interpretation is ill-formed.
+ // In plain language, this means trying a const_cast ...
+ unsigned msg = diag::err_bad_cxx_cast_generic;
+ TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
+ msg);
+ if (tcr == TC_Success)
+ Kind = CK_NoOp;
+
+ if (tcr == TC_NotApplicable) {
+ // ... or if that is not possible, a static_cast, ignoring const, ...
+ tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, Kind,
+ BasePath);
+ if (tcr == TC_NotApplicable) {
+ // ... and finally a reinterpret_cast, ignoring const.
+ tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
+ Kind);
+ }
+ }
+
+ if (tcr != TC_Success && msg != 0) {
+ if (CastExpr->getType() == Context.OverloadTy) {
+ DeclAccessPair Found;
+ FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr,
+ CastTy,
+ /* Complain */ true,
+ Found);
+
+ assert(!Fn
+ && "cast failed but able to resolve overload expression!!");
+ (void)Fn;
+
+ } else {
+ diagnoseBadCast(*this, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
+ R, CastExpr, CastTy);
+ }
+ }
+ else if (Kind == CK_BitCast)
+ CheckCastAlign(CastExpr, CastTy, R);
+
+ return tcr != TC_Success;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
new file mode 100644
index 0000000..aa0efcd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -0,0 +1,694 @@
+//===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements C++ semantic analysis for scope specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+/// \brief Find the current instantiation that associated with the given type.
+static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
+ DeclContext *CurContext) {
+ if (T.isNull())
+ return 0;
+
+ const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!T->isDependentType())
+ return Record;
+
+ // This may be a member of a class template or class template partial
+ // specialization. If it's part of the current semantic context, then it's
+ // an injected-class-name;
+ for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
+ if (CurContext->Equals(Record))
+ return Record;
+
+ return 0;
+ } else if (isa<InjectedClassNameType>(Ty))
+ return cast<InjectedClassNameType>(Ty)->getDecl();
+ else
+ return 0;
+}
+
+/// \brief Compute the DeclContext that is associated with the given type.
+///
+/// \param T the type for which we are attempting to find a DeclContext.
+///
+/// \returns the declaration context represented by the type T,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(QualType T) {
+ if (!T->isDependentType())
+ if (const TagType *Tag = T->getAs<TagType>())
+ return Tag->getDecl();
+
+ return ::getCurrentInstantiationOf(T, CurContext);
+}
+
+/// \brief Compute the DeclContext that is associated with the given
+/// scope specifier.
+///
+/// \param SS the C++ scope specifier as it appears in the source
+///
+/// \param EnteringContext when true, we will be entering the context of
+/// this scope specifier, so we can retrieve the declaration context of a
+/// class template or class template partial specialization even if it is
+/// not the current instantiation.
+///
+/// \returns the declaration context represented by the scope specifier @p SS,
+/// or NULL if the declaration context cannot be computed (e.g., because it is
+/// dependent and not the current instantiation).
+DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
+ bool EnteringContext) {
+ if (!SS.isSet() || SS.isInvalid())
+ return 0;
+
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (NNS->isDependent()) {
+ // If this nested-name-specifier refers to the current
+ // instantiation, return its DeclContext.
+ if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS))
+ return Record;
+
+ if (EnteringContext) {
+ const Type *NNSType = NNS->getAsType();
+ if (!NNSType) {
+ // do nothing, fall out
+ } else if (const TemplateSpecializationType *SpecType
+ = NNSType->getAs<TemplateSpecializationType>()) {
+ // We are entering the context of the nested name specifier, so try to
+ // match the nested name specifier to either a primary class template
+ // or a class template partial specialization.
+ if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(
+ SpecType->getTemplateName().getAsTemplateDecl())) {
+ QualType ContextType
+ = Context.getCanonicalType(QualType(SpecType, 0));
+
+ // If the type of the nested name specifier is the same as the
+ // injected class name of the named class template, we're entering
+ // into that class template definition.
+ QualType Injected
+ = ClassTemplate->getInjectedClassNameSpecialization();
+ if (Context.hasSameType(Injected, ContextType))
+ return ClassTemplate->getTemplatedDecl();
+
+ // If the type of the nested name specifier is the same as the
+ // type of one of the class template's class template partial
+ // specializations, we're entering into the definition of that
+ // class template partial specialization.
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = ClassTemplate->findPartialSpecialization(ContextType))
+ return PartialSpec;
+ }
+ } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
+ // The nested name specifier refers to a member of a class template.
+ return RecordT->getDecl();
+ }
+ }
+
+ return 0;
+ }
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ assert(false && "Dependent nested-name-specifier has no DeclContext");
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ return NNS->getAsNamespace();
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ const TagType *Tag = NNS->getAsType()->getAs<TagType>();
+ assert(Tag && "Non-tag type in nested-name-specifier");
+ return Tag->getDecl();
+ } break;
+
+ case NestedNameSpecifier::Global:
+ return Context.getTranslationUnitDecl();
+ }
+
+ // Required to silence a GCC warning.
+ return 0;
+}
+
+bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
+ if (!SS.isSet() || SS.isInvalid())
+ return false;
+
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ return NNS->isDependent();
+}
+
+// \brief Determine whether this C++ scope specifier refers to an
+// unknown specialization, i.e., a dependent type that is not the
+// current instantiation.
+bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) {
+ if (!isDependentScopeSpecifier(SS))
+ return false;
+
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ return getCurrentInstantiationOf(NNS) == 0;
+}
+
+/// \brief If the given nested name specifier refers to the current
+/// instantiation, return the declaration that corresponds to that
+/// current instantiation (C++0x [temp.dep.type]p1).
+///
+/// \param NNS a dependent nested name specifier.
+CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) {
+ assert(getLangOptions().CPlusPlus && "Only callable in C++");
+ assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed");
+
+ if (!NNS->getAsType())
+ return 0;
+
+ QualType T = QualType(NNS->getAsType(), 0);
+ return ::getCurrentInstantiationOf(T, CurContext);
+}
+
+/// \brief Require that the context specified by SS be complete.
+///
+/// If SS refers to a type, this routine checks whether the type is
+/// complete enough (or can be made complete enough) for name lookup
+/// into the DeclContext. A type that is not yet completed can be
+/// considered "complete enough" if it is a class/struct/union/enum
+/// that is currently being defined. Or, if we have a type that names
+/// a class template specialization that is not a complete type, we
+/// will attempt to instantiate that class template.
+bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
+ DeclContext *DC) {
+ assert(DC != 0 && "given null context");
+
+ if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ // If this is a dependent type, then we consider it complete.
+ if (Tag->isDependentContext())
+ return false;
+
+ // If we're currently defining this type, then lookup into the
+ // type is okay: don't complain that it isn't complete yet.
+ const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>();
+ if (TagT && TagT->isBeingDefined())
+ return false;
+
+ // The type must be complete.
+ if (RequireCompleteType(SS.getRange().getBegin(),
+ Context.getTypeDeclType(Tag),
+ PDiag(diag::err_incomplete_nested_name_spec)
+ << SS.getRange())) {
+ SS.setScopeRep(0); // Mark the ScopeSpec invalid.
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+/// global scope ('::').
+Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
+ SourceLocation CCLoc) {
+ return NestedNameSpecifier::GlobalSpecifier(Context);
+}
+
+/// \brief Determines whether the given declaration is an valid acceptable
+/// result for name lookup of a nested-name-specifier.
+bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
+ if (!SD)
+ return false;
+
+ // Namespace and namespace aliases are fine.
+ if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
+ return true;
+
+ if (!isa<TypeDecl>(SD))
+ return false;
+
+ // Determine whether we have a class (or, in C++0x, an enum) or
+ // a typedef thereof. If so, build the nested-name-specifier.
+ QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+ if (T->isDependentType())
+ return true;
+ else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+ if (TD->getUnderlyingType()->isRecordType() ||
+ (Context.getLangOptions().CPlusPlus0x &&
+ TD->getUnderlyingType()->isEnumeralType()))
+ return true;
+ } else if (isa<RecordDecl>(SD) ||
+ (Context.getLangOptions().CPlusPlus0x && isa<EnumDecl>(SD)))
+ return true;
+
+ return false;
+}
+
+/// \brief If the given nested-name-specifier begins with a bare identifier
+/// (e.g., Base::), perform name lookup for that identifier as a
+/// nested-name-specifier within the given scope, and return the result of that
+/// name lookup.
+NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
+ if (!S || !NNS)
+ return 0;
+
+ while (NNS->getPrefix())
+ NNS = NNS->getPrefix();
+
+ if (NNS->getKind() != NestedNameSpecifier::Identifier)
+ return 0;
+
+ LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
+ LookupNestedNameSpecifierName);
+ LookupName(Found, S);
+ assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
+
+ if (!Found.isSingleResult())
+ return 0;
+
+ NamedDecl *Result = Found.getFoundDecl();
+ if (isAcceptableNestedNameSpecifier(Result))
+ return Result;
+
+ return 0;
+}
+
+bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectTypePtr) {
+ QualType ObjectType = GetTypeFromParser(ObjectTypePtr);
+ LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+
+ // Determine where to perform name lookup
+ DeclContext *LookupCtx = 0;
+ bool isDependent = false;
+ if (!ObjectType.isNull()) {
+ // This nested-name-specifier occurs in a member access expression, e.g.,
+ // x->B::f, and we are looking into the type of the object.
+ assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+ LookupCtx = computeDeclContext(ObjectType);
+ isDependent = ObjectType->isDependentType();
+ } else if (SS.isSet()) {
+ // This nested-name-specifier occurs after another nested-name-specifier,
+ // so long into the context associated with the prior nested-name-specifier.
+ LookupCtx = computeDeclContext(SS, false);
+ isDependent = isDependentScopeSpecifier(SS);
+ Found.setContextRange(SS.getRange());
+ }
+
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+
+ // The declaration context must be complete.
+ if (!LookupCtx->isDependentContext() &&
+ RequireCompleteDeclContext(SS, LookupCtx))
+ return false;
+
+ LookupQualifiedName(Found, LookupCtx);
+ } else if (isDependent) {
+ return false;
+ } else {
+ LookupName(Found, S);
+ }
+ Found.suppressDiagnostics();
+
+ if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+ return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+
+ return false;
+}
+
+/// \brief Build a new nested-name-specifier for "identifier::", as described
+/// by ActOnCXXNestedNameSpecifier.
+///
+/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
+/// that it contains an extra parameter \p ScopeLookupResult, which provides
+/// the result of name lookup within the scope of the nested-name-specifier
+/// that was computed at template definition time.
+///
+/// If ErrorRecoveryLookup is true, then this call is used to improve error
+/// recovery. This means that it should not emit diagnostics, it should
+/// just return null on failure. It also means it should only return a valid
+/// scope if it *knows* that the result is correct. It should not return in a
+/// dependent context, for example.
+Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *ScopeLookupResult,
+ bool EnteringContext,
+ bool ErrorRecoveryLookup) {
+ NestedNameSpecifier *Prefix
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+ LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+
+ // Determine where to perform name lookup
+ DeclContext *LookupCtx = 0;
+ bool isDependent = false;
+ if (!ObjectType.isNull()) {
+ // This nested-name-specifier occurs in a member access expression, e.g.,
+ // x->B::f, and we are looking into the type of the object.
+ assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+ LookupCtx = computeDeclContext(ObjectType);
+ isDependent = ObjectType->isDependentType();
+ } else if (SS.isSet()) {
+ // This nested-name-specifier occurs after another nested-name-specifier,
+ // so long into the context associated with the prior nested-name-specifier.
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(SS);
+ Found.setContextRange(SS.getRange());
+ }
+
+
+ bool ObjectTypeSearchedInScope = false;
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+
+ // The declaration context must be complete.
+ if (!LookupCtx->isDependentContext() &&
+ RequireCompleteDeclContext(SS, LookupCtx))
+ return 0;
+
+ LookupQualifiedName(Found, LookupCtx);
+
+ if (!ObjectType.isNull() && Found.empty()) {
+ // C++ [basic.lookup.classref]p4:
+ // If the id-expression in a class member access is a qualified-id of
+ // the form
+ //
+ // class-name-or-namespace-name::...
+ //
+ // the class-name-or-namespace-name following the . or -> operator is
+ // looked up both in the context of the entire postfix-expression and in
+ // the scope of the class of the object expression. If the name is found
+ // only in the scope of the class of the object expression, the name
+ // shall refer to a class-name. If the name is found only in the
+ // context of the entire postfix-expression, the name shall refer to a
+ // class-name or namespace-name. [...]
+ //
+ // Qualified name lookup into a class will not find a namespace-name,
+ // so we do not need to diagnoste that case specifically. However,
+ // this qualified name lookup may find nothing. In that case, perform
+ // unqualified name lookup in the given scope (if available) or
+ // reconstruct the result from when name lookup was performed at template
+ // definition time.
+ if (S)
+ LookupName(Found, S);
+ else if (ScopeLookupResult)
+ Found.addDecl(ScopeLookupResult);
+
+ ObjectTypeSearchedInScope = true;
+ }
+ } else if (!isDependent) {
+ // Perform unqualified name lookup in the current scope.
+ LookupName(Found, S);
+ }
+
+ // If we performed lookup into a dependent context and did not find anything,
+ // that's fine: just build a dependent nested-name-specifier.
+ if (Found.empty() && isDependent &&
+ !(LookupCtx && LookupCtx->isRecord() &&
+ (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
+ !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
+ // Don't speculate if we're just trying to improve error recovery.
+ if (ErrorRecoveryLookup)
+ return 0;
+
+ // We were not able to compute the declaration context for a dependent
+ // base object type or prior nested-name-specifier, so this
+ // nested-name-specifier refers to an unknown specialization. Just build
+ // a dependent nested-name-specifier.
+ if (!Prefix)
+ return NestedNameSpecifier::Create(Context, &II);
+
+ return NestedNameSpecifier::Create(Context, Prefix, &II);
+ }
+
+ // FIXME: Deal with ambiguities cleanly.
+
+ if (Found.empty() && !ErrorRecoveryLookup) {
+ // We haven't found anything, and we're not recovering from a
+ // different kind of error, so look for typos.
+ DeclarationName Name = Found.getLookupName();
+ if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext,
+ CTC_NoKeywords) &&
+ Found.isSingleResult() &&
+ isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {
+ if (LookupCtx)
+ Diag(Found.getNameLoc(), diag::err_no_member_suggest)
+ << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+ << FixItHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ else
+ Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
+ << Name << Found.getLookupName()
+ << FixItHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+
+ if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_previous_decl)
+ << ND->getDeclName();
+ } else {
+ Found.clear();
+ Found.setLookupName(&II);
+ }
+ }
+
+ NamedDecl *SD = Found.getAsSingle<NamedDecl>();
+ if (isAcceptableNestedNameSpecifier(SD)) {
+ if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+ // C++ [basic.lookup.classref]p4:
+ // [...] If the name is found in both contexts, the
+ // class-name-or-namespace-name shall refer to the same entity.
+ //
+ // We already found the name in the scope of the object. Now, look
+ // into the current scope (the scope of the postfix-expression) to
+ // see if we can find the same name there. As above, if there is no
+ // scope, reconstruct the result from the template instantiation itself.
+ NamedDecl *OuterDecl;
+ if (S) {
+ LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+ LookupName(FoundOuter, S);
+ OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
+ } else
+ OuterDecl = ScopeLookupResult;
+
+ if (isAcceptableNestedNameSpecifier(OuterDecl) &&
+ OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
+ (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
+ !Context.hasSameType(
+ Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
+ Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
+ if (ErrorRecoveryLookup)
+ return 0;
+
+ Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
+ << &II;
+ Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+ << ObjectType;
+ Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+ // Fall through so that we'll pick the name we found in the object
+ // type, since that's probably what the user wanted anyway.
+ }
+ }
+
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
+ return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+
+ // FIXME: It would be nice to maintain the namespace alias name, then
+ // see through that alias when resolving the nested-name-specifier down to
+ // a declaration context.
+ if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD))
+ return NestedNameSpecifier::Create(Context, Prefix,
+ Alias->getNamespace());
+
+ QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+ return NestedNameSpecifier::Create(Context, Prefix, false,
+ T.getTypePtr());
+ }
+
+ // Otherwise, we have an error case. If we don't want diagnostics, just
+ // return an error now.
+ if (ErrorRecoveryLookup)
+ return 0;
+
+ // If we didn't find anything during our lookup, try again with
+ // ordinary name lookup, which can help us produce better error
+ // messages.
+ if (Found.empty()) {
+ Found.clear(LookupOrdinaryName);
+ LookupName(Found, S);
+ }
+
+ unsigned DiagID;
+ if (!Found.empty())
+ DiagID = diag::err_expected_class_or_namespace;
+ else if (SS.isSet()) {
+ Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
+ return 0;
+ } else
+ DiagID = diag::err_undeclared_var_use;
+
+ if (SS.isSet())
+ Diag(IdLoc, DiagID) << &II << SS.getRange();
+ else
+ Diag(IdLoc, DiagID) << &II;
+
+ return 0;
+}
+
+/// ActOnCXXNestedNameSpecifier - Called during parsing of a
+/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
+/// we want to resolve "bar::". 'SS' is empty or the previously parsed
+/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
+/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
+/// Returns a CXXScopeTy* object representing the C++ scope.
+Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectTypePtr,
+ bool EnteringContext) {
+ return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
+ GetTypeFromParser(ObjectTypePtr),
+ /*ScopeLookupResult=*/0, EnteringContext,
+ false);
+}
+
+/// IsInvalidUnlessNestedName - This method is used for error recovery
+/// purposes to determine whether the specified identifier is only valid as
+/// a nested name specifier, for example a namespace name. It is
+/// conservatively correct to always return false from this method.
+///
+/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
+bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo &II, ParsedType ObjectType,
+ bool EnteringContext) {
+ return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
+ II, GetTypeFromParser(ObjectType),
+ /*ScopeLookupResult=*/0, EnteringContext,
+ true);
+}
+
+Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ ParsedType Ty,
+ SourceRange TypeRange,
+ SourceLocation CCLoc) {
+ NestedNameSpecifier *Prefix = SS.getScopeRep();
+ QualType T = GetTypeFromParser(Ty);
+ return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
+ T.getTypePtr());
+}
+
+bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+ NestedNameSpecifier *Qualifier =
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+ // There are only two places a well-formed program may qualify a
+ // declarator: first, when defining a namespace or class member
+ // out-of-line, and second, when naming an explicitly-qualified
+ // friend function. The latter case is governed by
+ // C++03 [basic.lookup.unqual]p10:
+ // In a friend declaration naming a member function, a name used
+ // in the function declarator and not part of a template-argument
+ // in a template-id is first looked up in the scope of the member
+ // function's class. If it is not found, or if the name is part of
+ // a template-argument in a template-id, the look up is as
+ // described for unqualified names in the definition of the class
+ // granting friendship.
+ // i.e. we don't push a scope unless it's a class member.
+
+ switch (Qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Namespace:
+ // These are always namespace scopes. We never want to enter a
+ // namespace scope from anything but a file context.
+ return CurContext->getRedeclContext()->isFileContext();
+
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ // These are never namespace scopes.
+ return true;
+ }
+
+ // Silence bogus warning.
+ return false;
+}
+
+/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+/// scope or nested-name-specifier) is parsed, part of a declarator-id.
+/// After this method is called, according to [C++ 3.4.3p3], names should be
+/// looked up in the declarator-id's scope, until the declarator is parsed and
+/// ActOnCXXExitDeclaratorScope is called.
+/// The 'SS' should be a non-empty valid CXXScopeSpec.
+bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) {
+ assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+ if (SS.isInvalid()) return true;
+
+ DeclContext *DC = computeDeclContext(SS, true);
+ if (!DC) return true;
+
+ // Before we enter a declarator's context, we need to make sure that
+ // it is a complete declaration context.
+ if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC))
+ return true;
+
+ EnterDeclaratorContext(S, DC);
+
+ // Rebuild the nested name specifier for the new scope.
+ if (DC->isDependentContext())
+ RebuildNestedNameSpecifierInCurrentInstantiation(SS);
+
+ return false;
+}
+
+/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+/// Used to indicate that names should revert to being looked up in the
+/// defining scope.
+void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+ if (SS.isInvalid())
+ return;
+ assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+ "exiting declarator scope we never really entered");
+ ExitDeclaratorContext(S);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
new file mode 100644
index 0000000..24cdaef
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -0,0 +1,3179 @@
+//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements extra semantic analysis beyond what is enforced
+// by the C type system.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/ConvertUTF.h"
+#include <limits>
+using namespace clang;
+using namespace sema;
+
+SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const {
+ return SL->getLocationOfByte(ByteNo, PP.getSourceManager(),
+ PP.getLangOptions(), PP.getTargetInfo());
+}
+
+
+/// CheckablePrintfAttr - does a function call have a "printf" attribute
+/// and arguments that merit checking?
+bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
+ if (Format->getType() == "printf") return true;
+ if (Format->getType() == "printf0") {
+ // printf0 allows null "format" string; if so don't check format/args
+ unsigned format_idx = Format->getFormatIdx() - 1;
+ // Does the index refer to the implicit object argument?
+ if (isa<CXXMemberCallExpr>(TheCall)) {
+ if (format_idx == 0)
+ return false;
+ --format_idx;
+ }
+ if (format_idx < TheCall->getNumArgs()) {
+ Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
+ if (!Format->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull))
+ return true;
+ }
+ }
+ return false;
+}
+
+ExprResult
+Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ ExprResult TheCallResult(Owned(TheCall));
+
+ // Find out if any arguments are required to be integer constant expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ if (Error != ASTContext::GE_None)
+ ICEArguments = 0; // Don't diagnose previously diagnosed errors.
+
+ // If any arguments are required to be ICE's, check and diagnose.
+ for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
+ // Skip arguments not required to be ICE's.
+ if ((ICEArguments & (1 << ArgNo)) == 0) continue;
+
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+ return true;
+ ICEArguments &= ~(1 << ArgNo);
+ }
+
+ switch (BuiltinID) {
+ case Builtin::BI__builtin___CFStringMakeConstantString:
+ assert(TheCall->getNumArgs() == 1 &&
+ "Wrong # arguments to builtin CFStringMakeConstantString");
+ if (CheckObjCString(TheCall->getArg(0)))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_stdarg_start:
+ case Builtin::BI__builtin_va_start:
+ if (SemaBuiltinVAStart(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered:
+ if (SemaBuiltinUnorderedCompare(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_fpclassify:
+ if (SemaBuiltinFPClassification(TheCall, 6))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_isfinite:
+ case Builtin::BI__builtin_isinf:
+ case Builtin::BI__builtin_isinf_sign:
+ case Builtin::BI__builtin_isnan:
+ case Builtin::BI__builtin_isnormal:
+ if (SemaBuiltinFPClassification(TheCall, 1))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_shufflevector:
+ return SemaBuiltinShuffleVector(TheCall);
+ // TheCall will be freed by the smart pointer here, but that's fine, since
+ // SemaBuiltinShuffleVector guts it, but then doesn't release it.
+ case Builtin::BI__builtin_prefetch:
+ if (SemaBuiltinPrefetch(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_object_size:
+ if (SemaBuiltinObjectSize(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_longjmp:
+ if (SemaBuiltinLongjmp(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_constant_p:
+ if (TheCall->getNumArgs() == 0)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 /*function call*/ << 1 << 0 << TheCall->getSourceRange();
+ if (TheCall->getNumArgs() > 1)
+ return Diag(TheCall->getArg(1)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << 1 << TheCall->getNumArgs()
+ << TheCall->getArg(1)->getSourceRange();
+ break;
+ case Builtin::BI__sync_fetch_and_add:
+ case Builtin::BI__sync_fetch_and_sub:
+ case Builtin::BI__sync_fetch_and_or:
+ case Builtin::BI__sync_fetch_and_and:
+ case Builtin::BI__sync_fetch_and_xor:
+ case Builtin::BI__sync_add_and_fetch:
+ case Builtin::BI__sync_sub_and_fetch:
+ case Builtin::BI__sync_and_and_fetch:
+ case Builtin::BI__sync_or_and_fetch:
+ case Builtin::BI__sync_xor_and_fetch:
+ case Builtin::BI__sync_val_compare_and_swap:
+ case Builtin::BI__sync_bool_compare_and_swap:
+ case Builtin::BI__sync_lock_test_and_set:
+ case Builtin::BI__sync_lock_release:
+ return SemaBuiltinAtomicOverloaded(move(TheCallResult));
+ }
+
+ // Since the target specific builtins for each arch overlap, only check those
+ // of the arch we are compiling for.
+ if (BuiltinID >= Builtin::FirstTSBuiltin) {
+ switch (Context.Target.getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return move(TheCallResult);
+}
+
+// Get the valid immediate range for the specified NEON type code.
+static unsigned RFT(unsigned t, bool shift = false) {
+ bool quad = t & 0x10;
+
+ switch (t & 0x7) {
+ case 0: // i8
+ return shift ? 7 : (8 << (int)quad) - 1;
+ case 1: // i16
+ return shift ? 15 : (4 << (int)quad) - 1;
+ case 2: // i32
+ return shift ? 31 : (2 << (int)quad) - 1;
+ case 3: // i64
+ return shift ? 63 : (1 << (int)quad) - 1;
+ case 4: // f32
+ assert(!shift && "cannot shift float types!");
+ return (2 << (int)quad) - 1;
+ case 5: // poly8
+ return shift ? 7 : (8 << (int)quad) - 1;
+ case 6: // poly16
+ return shift ? 15 : (4 << (int)quad) - 1;
+ case 7: // float16
+ assert(!shift && "cannot shift float types!");
+ return (4 << (int)quad) - 1;
+ }
+ return 0;
+}
+
+bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ llvm::APSInt Result;
+
+ unsigned mask = 0;
+ unsigned TV = 0;
+ switch (BuiltinID) {
+#define GET_NEON_OVERLOAD_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_OVERLOAD_CHECK
+ }
+
+ // For NEON intrinsics which are overloaded on vector element type, validate
+ // the immediate which specifies which variant to emit.
+ if (mask) {
+ unsigned ArgNo = TheCall->getNumArgs()-1;
+ if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+ return true;
+
+ TV = Result.getLimitedValue(32);
+ if ((TV > 31) || (mask & (1 << TV)) == 0)
+ return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
+ << TheCall->getArg(ArgNo)->getSourceRange();
+ }
+
+ // For NEON intrinsics which take an immediate value as part of the
+ // instruction, range check them here.
+ unsigned i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default: return false;
+ case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break;
+ case ARM::BI__builtin_arm_usat: i = 1; u = 31; break;
+ case ARM::BI__builtin_arm_vcvtr_f:
+ case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
+#define GET_NEON_IMMEDIATE_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_IMMEDIATE_CHECK
+ };
+
+ // Check that the immediate argument is actually a constant.
+ if (SemaBuiltinConstantArg(TheCall, i, Result))
+ return true;
+
+ // Range check against the upper/lower values for this isntruction.
+ unsigned Val = Result.getZExtValue();
+ if (Val < l || Val > (u + l))
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << l << u+l << TheCall->getArg(i)->getSourceRange();
+
+ // FIXME: VFP Intrinsics should error if VFP not present.
+ return false;
+}
+
+/// CheckFunctionCall - Check a direct function call for various correctness
+/// and safety properties not strictly enforced by the C type system.
+bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
+ // Get the IdentifierInfo* for the called function.
+ IdentifierInfo *FnInfo = FDecl->getIdentifier();
+
+ // None of the checks below are needed for functions that don't have
+ // simple names (e.g., C++ conversion functions).
+ if (!FnInfo)
+ return false;
+
+ // FIXME: This mechanism should be abstracted to be less fragile and
+ // more efficient. For example, just map function ids to custom
+ // handlers.
+
+ // Printf and scanf checking.
+ for (specific_attr_iterator<FormatAttr>
+ i = FDecl->specific_attr_begin<FormatAttr>(),
+ e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+ const FormatAttr *Format = *i;
+ const bool b = Format->getType() == "scanf";
+ if (b || CheckablePrintfAttr(Format, TheCall)) {
+ bool HasVAListArg = Format->getFirstArg() == 0;
+ CheckPrintfScanfArguments(TheCall, HasVAListArg,
+ Format->getFormatIdx() - 1,
+ HasVAListArg ? 0 : Format->getFirstArg() - 1,
+ !b);
+ }
+ }
+
+ for (specific_attr_iterator<NonNullAttr>
+ i = FDecl->specific_attr_begin<NonNullAttr>(),
+ e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ CheckNonNullArguments(*i, TheCall);
+ }
+
+ return false;
+}
+
+bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
+ // Printf checking.
+ const FormatAttr *Format = NDecl->getAttr<FormatAttr>();
+ if (!Format)
+ return false;
+
+ const VarDecl *V = dyn_cast<VarDecl>(NDecl);
+ if (!V)
+ return false;
+
+ QualType Ty = V->getType();
+ if (!Ty->isBlockPointerType())
+ return false;
+
+ const bool b = Format->getType() == "scanf";
+ if (!b && !CheckablePrintfAttr(Format, TheCall))
+ return false;
+
+ bool HasVAListArg = Format->getFirstArg() == 0;
+ CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
+ HasVAListArg ? 0 : Format->getFirstArg() - 1, !b);
+
+ return false;
+}
+
+/// SemaBuiltinAtomicOverloaded - We have a call to a function like
+/// __sync_fetch_and_add, which is an overloaded function based on the pointer
+/// type of its first argument. The main ActOnCallExpr routines have already
+/// promoted the types of arguments because all of these calls are prototyped as
+/// void(...).
+///
+/// This function goes through and does final semantic checking for these
+/// builtins,
+ExprResult
+Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
+ CallExpr *TheCall = (CallExpr *)TheCallResult.get();
+ DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+
+ // Ensure that we have at least one argument to do type inference from.
+ if (TheCall->getNumArgs() < 1) {
+ Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return ExprError();
+ }
+
+ // Inspect the first argument of the atomic builtin. This should always be
+ // a pointer type, whose element is an integral scalar or pointer type.
+ // Because it is a pointer type, we don't have to worry about any implicit
+ // casts here.
+ // FIXME: We don't allow floating point scalars as input.
+ Expr *FirstArg = TheCall->getArg(0);
+ if (!FirstArg->getType()->isPointerType()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
+
+ QualType ValType =
+ FirstArg->getType()->getAs<PointerType>()->getPointeeType();
+ if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
+ !ValType->isBlockPointerType()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
+
+ // The majority of builtins return a value, but a few have special return
+ // types, so allow them to override appropriately below.
+ QualType ResultType = ValType;
+
+ // We need to figure out which concrete builtin this maps onto. For example,
+ // __sync_fetch_and_add with a 2 byte object turns into
+ // __sync_fetch_and_add_2.
+#define BUILTIN_ROW(x) \
+ { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
+ Builtin::BI##x##_8, Builtin::BI##x##_16 }
+
+ static const unsigned BuiltinIndices[][5] = {
+ BUILTIN_ROW(__sync_fetch_and_add),
+ BUILTIN_ROW(__sync_fetch_and_sub),
+ BUILTIN_ROW(__sync_fetch_and_or),
+ BUILTIN_ROW(__sync_fetch_and_and),
+ BUILTIN_ROW(__sync_fetch_and_xor),
+
+ BUILTIN_ROW(__sync_add_and_fetch),
+ BUILTIN_ROW(__sync_sub_and_fetch),
+ BUILTIN_ROW(__sync_and_and_fetch),
+ BUILTIN_ROW(__sync_or_and_fetch),
+ BUILTIN_ROW(__sync_xor_and_fetch),
+
+ BUILTIN_ROW(__sync_val_compare_and_swap),
+ BUILTIN_ROW(__sync_bool_compare_and_swap),
+ BUILTIN_ROW(__sync_lock_test_and_set),
+ BUILTIN_ROW(__sync_lock_release)
+ };
+#undef BUILTIN_ROW
+
+ // Determine the index of the size.
+ unsigned SizeIndex;
+ switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
+ case 1: SizeIndex = 0; break;
+ case 2: SizeIndex = 1; break;
+ case 4: SizeIndex = 2; break;
+ case 8: SizeIndex = 3; break;
+ case 16: SizeIndex = 4; break;
+ default:
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
+
+ // Each of these builtins has one pointer argument, followed by some number of
+ // values (0, 1 or 2) followed by a potentially empty varags list of stuff
+ // that we ignore. Find out which row of BuiltinIndices to read from as well
+ // as the number of fixed args.
+ unsigned BuiltinID = FDecl->getBuiltinID();
+ unsigned BuiltinIndex, NumFixed = 1;
+ switch (BuiltinID) {
+ default: assert(0 && "Unknown overloaded atomic builtin!");
+ case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break;
+ case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break;
+ case Builtin::BI__sync_fetch_and_or: BuiltinIndex = 2; break;
+ case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break;
+ case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break;
+
+ case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 5; break;
+ case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 6; break;
+ case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 7; break;
+ case Builtin::BI__sync_or_and_fetch: BuiltinIndex = 8; break;
+ case Builtin::BI__sync_xor_and_fetch: BuiltinIndex = 9; break;
+
+ case Builtin::BI__sync_val_compare_and_swap:
+ BuiltinIndex = 10;
+ NumFixed = 2;
+ break;
+ case Builtin::BI__sync_bool_compare_and_swap:
+ BuiltinIndex = 11;
+ NumFixed = 2;
+ ResultType = Context.BoolTy;
+ break;
+ case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break;
+ case Builtin::BI__sync_lock_release:
+ BuiltinIndex = 13;
+ NumFixed = 0;
+ ResultType = Context.VoidTy;
+ break;
+ }
+
+ // Now that we know how many fixed arguments we expect, first check that we
+ // have at least that many.
+ if (TheCall->getNumArgs() < 1+NumFixed) {
+ Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1+NumFixed << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return ExprError();
+ }
+
+ // Get the decl for the concrete builtin from this, we can tell what the
+ // concrete integer type we should convert to is.
+ unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
+ const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+ IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
+ FunctionDecl *NewBuiltinDecl =
+ cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
+ TUScope, false, DRE->getLocStart()));
+
+ // The first argument --- the pointer --- has a fixed type; we
+ // deduce the types of the rest of the arguments accordingly. Walk
+ // the remaining arguments, converting them to the deduced value type.
+ for (unsigned i = 0; i != NumFixed; ++i) {
+ Expr *Arg = TheCall->getArg(i+1);
+
+ // If the argument is an implicit cast, then there was a promotion due to
+ // "...", just remove it now.
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ Arg = ICE->getSubExpr();
+ ICE->setSubExpr(0);
+ TheCall->setArg(i+1, Arg);
+ }
+
+ // GCC does an implicit conversion to the pointer or integer ValType. This
+ // can fail in some cases (1i -> int**), check for this error case now.
+ CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
+ CXXCastPath BasePath;
+ if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath))
+ return ExprError();
+
+ // Okay, we have something that *can* be converted to the right type. Check
+ // to see if there is a potentially weird extension going on here. This can
+ // happen when you do an atomic operation on something like an char* and
+ // pass in 42. The 42 gets converted to char. This is even more strange
+ // for things like 45.123 -> char, etc.
+ // FIXME: Do this check.
+ ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath);
+ TheCall->setArg(i+1, Arg);
+ }
+
+ // Switch the DeclRefExpr to refer to the new decl.
+ DRE->setDecl(NewBuiltinDecl);
+ DRE->setType(NewBuiltinDecl->getType());
+
+ // Set the callee in the CallExpr.
+ // FIXME: This leaks the original parens and implicit casts.
+ Expr *PromotedCall = DRE;
+ UsualUnaryConversions(PromotedCall);
+ TheCall->setCallee(PromotedCall);
+
+ // Change the result type of the call to match the original value type. This
+ // is arbitrary, but the codegen for these builtins ins design to handle it
+ // gracefully.
+ TheCall->setType(ResultType);
+
+ return move(TheCallResult);
+}
+
+
+/// CheckObjCString - Checks that the argument to the builtin
+/// CFString constructor is correct
+/// Note: It might also make sense to do the UTF-16 conversion here (would
+/// simplify the backend).
+bool Sema::CheckObjCString(Expr *Arg) {
+ Arg = Arg->IgnoreParenCasts();
+ StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+
+ if (!Literal || Literal->isWide()) {
+ Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+ << Arg->getSourceRange();
+ return true;
+ }
+
+ size_t NulPos = Literal->getString().find('\0');
+ if (NulPos != llvm::StringRef::npos) {
+ Diag(getLocationOfStringLiteralByte(Literal, NulPos),
+ diag::warn_cfstring_literal_contains_nul_character)
+ << Arg->getSourceRange();
+ }
+ if (Literal->containsNonAsciiOrNull()) {
+ llvm::StringRef String = Literal->getString();
+ unsigned NumBytes = String.size();
+ llvm::SmallVector<UTF16, 128> ToBuf(NumBytes);
+ const UTF8 *FromPtr = (UTF8 *)String.data();
+ UTF16 *ToPtr = &ToBuf[0];
+
+ ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
+ &ToPtr, ToPtr + NumBytes,
+ strictConversion);
+ // Check for conversion failure.
+ if (Result != conversionOK)
+ Diag(Arg->getLocStart(),
+ diag::warn_cfstring_truncated) << Arg->getSourceRange();
+ }
+ return false;
+}
+
+/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
+/// Emit an error and return true on failure, return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+ Expr *Fn = TheCall->getCallee();
+ if (TheCall->getNumArgs() > 2) {
+ Diag(TheCall->getArg(2)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << Fn->getSourceRange()
+ << SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+ return true;
+ }
+
+ if (TheCall->getNumArgs() < 2) {
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs();
+ }
+
+ // Determine whether the current function is variadic or not.
+ BlockScopeInfo *CurBlock = getCurBlock();
+ bool isVariadic;
+ if (CurBlock)
+ isVariadic = CurBlock->TheDecl->isVariadic();
+ else if (FunctionDecl *FD = getCurFunctionDecl())
+ isVariadic = FD->isVariadic();
+ else
+ isVariadic = getCurMethodDecl()->isVariadic();
+
+ if (!isVariadic) {
+ Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function);
+ return true;
+ }
+
+ // Verify that the second argument to the builtin is the last argument of the
+ // current function or method.
+ bool SecondArgIsLastNamedArgument = false;
+ const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
+ if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
+ // FIXME: This isn't correct for methods (results in bogus warning).
+ // Get the last formal in the current function.
+ const ParmVarDecl *LastArg;
+ if (CurBlock)
+ LastArg = *(CurBlock->TheDecl->param_end()-1);
+ else if (FunctionDecl *FD = getCurFunctionDecl())
+ LastArg = *(FD->param_end()-1);
+ else
+ LastArg = *(getCurMethodDecl()->param_end()-1);
+ SecondArgIsLastNamedArgument = PV == LastArg;
+ }
+ }
+
+ if (!SecondArgIsLastNamedArgument)
+ Diag(TheCall->getArg(1)->getLocStart(),
+ diag::warn_second_parameter_of_va_start_not_last_named_argument);
+ return false;
+}
+
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
+/// friends. This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() < 2)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 << 2 << TheCall->getNumArgs()/*function call*/;
+ if (TheCall->getNumArgs() > 2)
+ return Diag(TheCall->getArg(2)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+
+ Expr *OrigArg0 = TheCall->getArg(0);
+ Expr *OrigArg1 = TheCall->getArg(1);
+
+ // Do standard promotions between the two arguments, returning their common
+ // type.
+ QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
+
+ // Make sure any conversions are pushed back into the call; this is
+ // type safe since unordered compare builtins are declared as "_Bool
+ // foo(...)".
+ TheCall->setArg(0, OrigArg0);
+ TheCall->setArg(1, OrigArg1);
+
+ if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent())
+ return false;
+
+ // If the common type isn't a real floating type, then the arguments were
+ // invalid for this operation.
+ if (!Res->isRealFloatingType())
+ return Diag(OrigArg0->getLocStart(),
+ diag::err_typecheck_call_invalid_ordered_compare)
+ << OrigArg0->getType() << OrigArg1->getType()
+ << SourceRange(OrigArg0->getLocStart(), OrigArg1->getLocEnd());
+
+ return false;
+}
+
+/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like
+/// __builtin_isnan and friends. This is declared to take (...), so we have
+/// to check everything. We expect the last argument to be a floating point
+/// value.
+bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
+ if (TheCall->getNumArgs() < NumArgs)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 << NumArgs << TheCall->getNumArgs()/*function call*/;
+ if (TheCall->getNumArgs() > NumArgs)
+ return Diag(TheCall->getArg(NumArgs)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(NumArgs)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+
+ Expr *OrigArg = TheCall->getArg(NumArgs-1);
+
+ if (OrigArg->isTypeDependent())
+ return false;
+
+ // This operation requires a non-_Complex floating-point number.
+ if (!OrigArg->getType()->isRealFloatingType())
+ return Diag(OrigArg->getLocStart(),
+ diag::err_typecheck_call_invalid_unary_fp)
+ << OrigArg->getType() << OrigArg->getSourceRange();
+
+ // If this is an implicit conversion from float -> double, remove it.
+ if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
+ Expr *CastArg = Cast->getSubExpr();
+ if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
+ assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
+ "promotion from float to double is the only expected cast here");
+ Cast->setSubExpr(0);
+ TheCall->setArg(NumArgs-1, CastArg);
+ OrigArg = CastArg;
+ }
+ }
+
+ return false;
+}
+
+/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
+// This is declared to take (...), so we have to check everything.
+ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() < 2)
+ return ExprError(Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << TheCall->getSourceRange());
+
+ // Determine which of the following types of shufflevector we're checking:
+ // 1) unary, vector mask: (lhs, mask)
+ // 2) binary, vector mask: (lhs, rhs, mask)
+ // 3) binary, scalar mask: (lhs, rhs, index, ..., index)
+ QualType resType = TheCall->getArg(0)->getType();
+ unsigned numElements = 0;
+
+ if (!TheCall->getArg(0)->isTypeDependent() &&
+ !TheCall->getArg(1)->isTypeDependent()) {
+ QualType LHSType = TheCall->getArg(0)->getType();
+ QualType RHSType = TheCall->getArg(1)->getType();
+
+ if (!LHSType->isVectorType() || !RHSType->isVectorType()) {
+ Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ return ExprError();
+ }
+
+ numElements = LHSType->getAs<VectorType>()->getNumElements();
+ unsigned numResElements = TheCall->getNumArgs() - 2;
+
+ // Check to see if we have a call with 2 vector arguments, the unary shuffle
+ // with mask. If so, verify that RHS is an integer vector type with the
+ // same number of elts as lhs.
+ if (TheCall->getNumArgs() == 2) {
+ if (!RHSType->hasIntegerRepresentation() ||
+ RHSType->getAs<VectorType>()->getNumElements() != numElements)
+ Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+ << SourceRange(TheCall->getArg(1)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ numResElements = numElements;
+ }
+ else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
+ Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ return ExprError();
+ } else if (numElements != numResElements) {
+ QualType eltType = LHSType->getAs<VectorType>()->getElementType();
+ resType = Context.getVectorType(eltType, numResElements,
+ VectorType::GenericVector);
+ }
+ }
+
+ for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
+ if (TheCall->getArg(i)->isTypeDependent() ||
+ TheCall->getArg(i)->isValueDependent())
+ continue;
+
+ llvm::APSInt Result(32);
+ if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_nonconstant_argument)
+ << TheCall->getArg(i)->getSourceRange());
+
+ if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_argument_too_large)
+ << TheCall->getArg(i)->getSourceRange());
+ }
+
+ llvm::SmallVector<Expr*, 32> exprs;
+
+ for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
+ exprs.push_back(TheCall->getArg(i));
+ TheCall->setArg(i, 0);
+ }
+
+ return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(),
+ exprs.size(), resType,
+ TheCall->getCallee()->getLocStart(),
+ TheCall->getRParenLoc()));
+}
+
+/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
+// This is declared to take (const void*, ...) and can take two
+// optional constant int args.
+bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
+ unsigned NumArgs = TheCall->getNumArgs();
+
+ if (NumArgs > 3)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs
+ << TheCall->getSourceRange();
+
+ // Argument 0 is checked for us and the remaining arguments must be
+ // constant integers.
+ for (unsigned i = 1; i != NumArgs; ++i) {
+ Expr *Arg = TheCall->getArg(i);
+
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, i, Result))
+ return true;
+
+ // FIXME: gcc issues a warning and rewrites these to 0. These
+ // seems especially odd for the third argument since the default
+ // is 3.
+ if (i == 1) {
+ if (Result.getLimitedValue() > 1)
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << "0" << "1" << Arg->getSourceRange();
+ } else {
+ if (Result.getLimitedValue() > 3)
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << "0" << "3" << Arg->getSourceRange();
+ }
+ }
+
+ return false;
+}
+
+/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
+/// TheCall is a constant expression.
+bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+ llvm::APSInt &Result) {
+ Expr *Arg = TheCall->getArg(ArgNum);
+ DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;
+
+ if (!Arg->isIntegerConstantExpr(Result, Context))
+ return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type)
+ << FDecl->getDeclName() << Arg->getSourceRange();
+
+ return false;
+}
+
+/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr,
+/// int type). This simply type checks that type is one of the defined
+/// constants (0-3).
+// For compatability check 0-3, llvm only handles 0 and 2.
+bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
+ llvm::APSInt Result;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ return true;
+
+ Expr *Arg = TheCall->getArg(1);
+ if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) {
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+ }
+
+ return false;
+}
+
+/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
+/// This checks that val is a constant 1.
+bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(1);
+ llvm::APSInt Result;
+
+ // TODO: This is less than ideal. Overload this to take a value.
+ if (SemaBuiltinConstantArg(TheCall, 1, Result))
+ return true;
+
+ if (Result != 1)
+ return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val)
+ << SourceRange(Arg->getLocStart(), Arg->getLocEnd());
+
+ return false;
+}
+
+// Handle i > 1 ? "x" : "y", recursivelly
+bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+ bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+ tryAgain:
+ if (E->isTypeDependent() || E->isValueDependent())
+ return false;
+
+ switch (E->getStmtClass()) {
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: {
+ const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E);
+ return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg,
+ format_idx, firstDataArg, isPrintf)
+ && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg,
+ format_idx, firstDataArg, isPrintf);
+ }
+
+ case Stmt::IntegerLiteralClass:
+ // Technically -Wformat-nonliteral does not warn about this case.
+ // The behavior of printf and friends in this case is implementation
+ // dependent. Ideally if the format string cannot be null then
+ // it should have a 'nonnull' attribute in the function prototype.
+ return true;
+
+ case Stmt::ImplicitCastExprClass: {
+ E = cast<ImplicitCastExpr>(E)->getSubExpr();
+ goto tryAgain;
+ }
+
+ case Stmt::ParenExprClass: {
+ E = cast<ParenExpr>(E)->getSubExpr();
+ goto tryAgain;
+ }
+
+ case Stmt::OpaqueValueExprClass:
+ if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
+ E = src;
+ goto tryAgain;
+ }
+ return false;
+
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+ // As an exception, do not flag errors for variables binding to
+ // const string literals.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ bool isConstant = false;
+ QualType T = DR->getType();
+
+ if (const ArrayType *AT = Context.getAsArrayType(T)) {
+ isConstant = AT->getElementType().isConstant(Context);
+ } else if (const PointerType *PT = T->getAs<PointerType>()) {
+ isConstant = T.isConstant(Context) &&
+ PT->getPointeeType().isConstant(Context);
+ }
+
+ if (isConstant) {
+ if (const Expr *Init = VD->getAnyInitializer())
+ return SemaCheckStringLiteral(Init, TheCall,
+ HasVAListArg, format_idx, firstDataArg,
+ isPrintf);
+ }
+
+ // For vprintf* functions (i.e., HasVAListArg==true), we add a
+ // special check to see if the format string is a function parameter
+ // of the function calling the printf function. If the function
+ // has an attribute indicating it is a printf-like function, then we
+ // should suppress warnings concerning non-literals being used in a call
+ // to a vprintf function. For example:
+ //
+ // void
+ // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){
+ // va_list ap;
+ // va_start(ap, fmt);
+ // vprintf(fmt, ap); // Do NOT emit a warning about "fmt".
+ // ...
+ //
+ //
+ // FIXME: We don't have full attribute support yet, so just check to see
+ // if the argument is a DeclRefExpr that references a parameter. We'll
+ // add proper support for checking the attribute later.
+ if (HasVAListArg)
+ if (isa<ParmVarDecl>(VD))
+ return true;
+ }
+
+ return false;
+ }
+
+ case Stmt::CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ if (const ImplicitCastExpr *ICE
+ = dyn_cast<ImplicitCastExpr>(CE->getCallee())) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+ if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) {
+ unsigned ArgIndex = FA->getFormatIdx();
+ const Expr *Arg = CE->getArg(ArgIndex - 1);
+
+ return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
+ format_idx, firstDataArg, isPrintf);
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::StringLiteralClass: {
+ const StringLiteral *StrE = NULL;
+
+ if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
+ StrE = ObjCFExpr->getString();
+ else
+ StrE = cast<StringLiteral>(E);
+
+ if (StrE) {
+ CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx,
+ firstDataArg, isPrintf);
+ return true;
+ }
+
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+void
+Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
+ const CallExpr *TheCall) {
+ for (NonNullAttr::args_iterator i = NonNull->args_begin(),
+ e = NonNull->args_end();
+ i != e; ++i) {
+ const Expr *ArgExpr = TheCall->getArg(*i);
+ if (ArgExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull))
+ Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg)
+ << ArgExpr->getSourceRange();
+ }
+}
+
+/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
+/// functions) for correct use of format strings.
+void
+Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+
+ const Expr *Fn = TheCall->getCallee();
+
+ // The way the format attribute works in GCC, the implicit this argument
+ // of member functions is counted. However, it doesn't appear in our own
+ // lists, so decrement format_idx in that case.
+ if (isa<CXXMemberCallExpr>(TheCall)) {
+ const CXXMethodDecl *method_decl =
+ dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl());
+ if (method_decl && method_decl->isInstance()) {
+ // Catch a format attribute mistakenly referring to the object argument.
+ if (format_idx == 0)
+ return;
+ --format_idx;
+ if(firstDataArg != 0)
+ --firstDataArg;
+ }
+ }
+
+ // CHECK: printf/scanf-like function is called with no format string.
+ if (format_idx >= TheCall->getNumArgs()) {
+ Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string)
+ << Fn->getSourceRange();
+ return;
+ }
+
+ const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
+
+ // CHECK: format string is not a string literal.
+ //
+ // Dynamically generated format strings are difficult to
+ // automatically vet at compile time. Requiring that format strings
+ // are string literals: (1) permits the checking of format strings by
+ // the compiler and thereby (2) can practically remove the source of
+ // many format string exploits.
+
+ // Format string can be either ObjC string (e.g. @"%d") or
+ // C string (e.g. "%d")
+ // ObjC string uses the same format specifiers as C string, so we can use
+ // the same format string checking logic for both ObjC and C strings.
+ if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx,
+ firstDataArg, isPrintf))
+ return; // Literal format string found, check done!
+
+ // If there are no arguments specified, warn with -Wformat-security, otherwise
+ // warn only with -Wformat-nonliteral.
+ if (TheCall->getNumArgs() == format_idx+1)
+ Diag(TheCall->getArg(format_idx)->getLocStart(),
+ diag::warn_format_nonliteral_noargs)
+ << OrigFormatExpr->getSourceRange();
+ else
+ Diag(TheCall->getArg(format_idx)->getLocStart(),
+ diag::warn_format_nonliteral)
+ << OrigFormatExpr->getSourceRange();
+}
+
+namespace {
+class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
+protected:
+ Sema &S;
+ const StringLiteral *FExpr;
+ const Expr *OrigFormatExpr;
+ const unsigned FirstDataArg;
+ const unsigned NumDataArgs;
+ const bool IsObjCLiteral;
+ const char *Beg; // Start of format string.
+ const bool HasVAListArg;
+ const CallExpr *TheCall;
+ unsigned FormatIdx;
+ llvm::BitVector CoveredArgs;
+ bool usesPositionalArgs;
+ bool atFirstArg;
+public:
+ CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+ FirstDataArg(firstDataArg),
+ NumDataArgs(numDataArgs),
+ IsObjCLiteral(isObjCLiteral), Beg(beg),
+ HasVAListArg(hasVAListArg),
+ TheCall(theCall), FormatIdx(formatIdx),
+ usesPositionalArgs(false), atFirstArg(true) {
+ CoveredArgs.resize(numDataArgs);
+ CoveredArgs.reset();
+ }
+
+ void DoneProcessing();
+
+ void HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen);
+
+ virtual void HandleInvalidPosition(const char *startSpecifier,
+ unsigned specifierLen,
+ analyze_format_string::PositionContext p);
+
+ virtual void HandleZeroPosition(const char *startPos, unsigned posLen);
+
+ void HandleNullChar(const char *nullCharacter);
+
+protected:
+ bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
+ const char *startSpec,
+ unsigned specifierLen,
+ const char *csStart, unsigned csLen);
+
+ SourceRange getFormatStringRange();
+ CharSourceRange getSpecifierRange(const char *startSpecifier,
+ unsigned specifierLen);
+ SourceLocation getLocationOfByte(const char *x);
+
+ const Expr *getDataArg(unsigned i) const;
+
+ bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen,
+ unsigned argIndex);
+};
+}
+
+SourceRange CheckFormatHandler::getFormatStringRange() {
+ return OrigFormatExpr->getSourceRange();
+}
+
+CharSourceRange CheckFormatHandler::
+getSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
+ SourceLocation Start = getLocationOfByte(startSpecifier);
+ SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1);
+
+ // Advance the end SourceLocation by one due to half-open ranges.
+ End = End.getFileLocWithOffset(1);
+
+ return CharSourceRange::getCharRange(Start, End);
+}
+
+SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) {
+ return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
+}
+
+void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen){
+ SourceLocation Loc = getLocationOfByte(startSpecifier);
+ S.Diag(Loc, diag::warn_printf_incomplete_specifier)
+ << getSpecifierRange(startSpecifier, specifierLen);
+}
+
+void
+CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen,
+ analyze_format_string::PositionContext p) {
+ SourceLocation Loc = getLocationOfByte(startPos);
+ S.Diag(Loc, diag::warn_format_invalid_positional_specifier)
+ << (unsigned) p << getSpecifierRange(startPos, posLen);
+}
+
+void CheckFormatHandler::HandleZeroPosition(const char *startPos,
+ unsigned posLen) {
+ SourceLocation Loc = getLocationOfByte(startPos);
+ S.Diag(Loc, diag::warn_format_zero_positional_specifier)
+ << getSpecifierRange(startPos, posLen);
+}
+
+void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
+ // The presence of a null character is likely an error.
+ S.Diag(getLocationOfByte(nullCharacter),
+ diag::warn_printf_format_string_contains_null_char)
+ << getFormatStringRange();
+}
+
+const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
+ return TheCall->getArg(FirstDataArg + i);
+}
+
+void CheckFormatHandler::DoneProcessing() {
+ // Does the number of data arguments exceed the number of
+ // format conversions in the format string?
+ if (!HasVAListArg) {
+ // Find any arguments that weren't covered.
+ CoveredArgs.flip();
+ signed notCoveredArg = CoveredArgs.find_first();
+ if (notCoveredArg >= 0) {
+ assert((unsigned)notCoveredArg < NumDataArgs);
+ S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(),
+ diag::warn_printf_data_arg_not_used)
+ << getFormatStringRange();
+ }
+ }
+}
+
+bool
+CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
+ SourceLocation Loc,
+ const char *startSpec,
+ unsigned specifierLen,
+ const char *csStart,
+ unsigned csLen) {
+
+ bool keepGoing = true;
+ if (argIndex < NumDataArgs) {
+ // Consider the argument coverered, even though the specifier doesn't
+ // make sense.
+ CoveredArgs.set(argIndex);
+ }
+ else {
+ // If argIndex exceeds the number of data arguments we
+ // don't issue a warning because that is just a cascade of warnings (and
+ // they may have intended '%%' anyway). We don't want to continue processing
+ // the format string after this point, however, as we will like just get
+ // gibberish when trying to match arguments.
+ keepGoing = false;
+ }
+
+ S.Diag(Loc, diag::warn_format_invalid_conversion)
+ << llvm::StringRef(csStart, csLen)
+ << getSpecifierRange(startSpec, specifierLen);
+
+ return keepGoing;
+}
+
+bool
+CheckFormatHandler::CheckNumArgs(
+ const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen, unsigned argIndex) {
+
+ if (argIndex >= NumDataArgs) {
+ if (FS.usesPositionalArg()) {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_positional_arg_exceeds_data_args)
+ << (argIndex+1) << NumDataArgs
+ << getSpecifierRange(startSpecifier, specifierLen);
+ }
+ else {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_insufficient_data_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ }
+
+ return false;
+ }
+ return true;
+}
+
+//===--- CHECK: Printf format string checking ------------------------------===//
+
+namespace {
+class CheckPrintfHandler : public CheckFormatHandler {
+public:
+ CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, isObjCLiteral, beg, hasVAListArg,
+ theCall, formatIdx) {}
+
+
+ bool HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalAmount &Amt,
+ unsigned type,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleFlag(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &ignoredFlag,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
+};
+}
+
+bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+
+ return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+ getLocationOfByte(CS.getStart()),
+ startSpecifier, specifierLen,
+ CS.getStart(), CS.getLength());
+}
+
+bool CheckPrintfHandler::HandleAmount(
+ const analyze_format_string::OptionalAmount &Amt,
+ unsigned k, const char *startSpecifier,
+ unsigned specifierLen) {
+
+ if (Amt.hasDataArgument()) {
+ if (!HasVAListArg) {
+ unsigned argIndex = Amt.getArgIndex();
+ if (argIndex >= NumDataArgs) {
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_asterisk_missing_arg)
+ << k << getSpecifierRange(startSpecifier, specifierLen);
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
+ }
+
+ // Type check the data argument. It should be an 'int'.
+ // Although not in conformance with C99, we also allow the argument to be
+ // an 'unsigned int' as that is a reasonably safe case. GCC also
+ // doesn't emit a warning for that case.
+ CoveredArgs.set(argIndex);
+ const Expr *Arg = getDataArg(argIndex);
+ QualType T = Arg->getType();
+
+ const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context);
+ assert(ATR.isValid());
+
+ if (!ATR.matchesType(S.Context, T)) {
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_asterisk_wrong_type)
+ << k
+ << ATR.getRepresentativeType(S.Context) << T
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Arg->getSourceRange();
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void CheckPrintfHandler::HandleInvalidAmount(
+ const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalAmount &Amt,
+ unsigned type,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+ switch (Amt.getHowSpecified()) {
+ case analyze_printf::OptionalAmount::Constant:
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_nonsensical_optional_amount)
+ << type
+ << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(),
+ Amt.getConstantLength()));
+ break;
+
+ default:
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_nonsensical_optional_amount)
+ << type
+ << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen);
+ break;
+ }
+}
+
+void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ // Warn about pointless flag with a fixit removal.
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+ S.Diag(getLocationOfByte(flag.getPosition()),
+ diag::warn_printf_nonsensical_flag)
+ << flag.toString() << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(flag.getPosition(), 1));
+}
+
+void CheckPrintfHandler::HandleIgnoredFlag(
+ const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &ignoredFlag,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ // Warn about ignored flag with a fixit removal.
+ S.Diag(getLocationOfByte(ignoredFlag.getPosition()),
+ diag::warn_printf_ignored_flag)
+ << ignoredFlag.toString() << flag.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(
+ ignoredFlag.getPosition(), 1));
+}
+
+bool
+CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
+ &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ using namespace analyze_format_string;
+ using namespace analyze_printf;
+ const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();
+
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
+ }
+
+ // First check if the field width, precision, and conversion specifier
+ // have matching data arguments.
+ if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0,
+ startSpecifier, specifierLen)) {
+ return false;
+ }
+
+ if (!HandleAmount(FS.getPrecision(), /* precision */ 1,
+ startSpecifier, specifierLen)) {
+ return false;
+ }
+
+ if (!CS.consumesDataArgument()) {
+ // FIXME: Technically specifying a precision or field width here
+ // makes no sense. Worth issuing a warning at some point.
+ return true;
+ }
+
+ // Consume the argument.
+ unsigned argIndex = FS.getArgIndex();
+ if (argIndex < NumDataArgs) {
+ // The check to see if the argIndex is valid will come later.
+ // We set the bit here because we may exit early from this
+ // function if we encounter some other error.
+ CoveredArgs.set(argIndex);
+ }
+
+ // FreeBSD extensions
+ if (CS.getKind() == ConversionSpecifier::bArg || CS.getKind() == ConversionSpecifier::DArg) {
+ // claim the second argument
+ CoveredArgs.set(argIndex + 1);
+
+ // Now type check the data expression that matches the
+ // format specifier.
+ const Expr *Ex = getDataArg(argIndex);
+ const analyze_printf::ArgTypeResult &ATR =
+ (CS.getKind() == ConversionSpecifier::bArg) ?
+ ArgTypeResult(S.Context.IntTy) : ArgTypeResult::CStrTy;
+ if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType()))
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+
+ // Now type check the data expression that matches the
+ // format specifier.
+ Ex = getDataArg(argIndex + 1);
+ const analyze_printf::ArgTypeResult &ATR2 = ArgTypeResult::CStrTy;
+ if (ATR2.isValid() && !ATR2.matchesType(S.Context, Ex->getType()))
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR2.getRepresentativeType(S.Context) << Ex->getType()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+
+ return true;
+ }
+ // END OF FREEBSD EXTENSIONS
+
+ // Check for using an Objective-C specific conversion specifier
+ // in a non-ObjC literal.
+ if (!IsObjCLiteral && CS.isObjCArg()) {
+ return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
+ specifierLen);
+ }
+
+ // Check for invalid use of field width
+ if (!FS.hasValidFieldWidth()) {
+ HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
+ startSpecifier, specifierLen);
+ }
+
+ // Check for invalid use of precision
+ if (!FS.hasValidPrecision()) {
+ HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1,
+ startSpecifier, specifierLen);
+ }
+
+ // Check each flag does not conflict with any other component.
+ if (!FS.hasValidThousandsGroupingPrefix())
+ HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
+ if (!FS.hasValidLeadingZeros())
+ HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
+ if (!FS.hasValidPlusPrefix())
+ HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen);
+ if (!FS.hasValidSpacePrefix())
+ HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen);
+ if (!FS.hasValidAlternativeForm())
+ HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen);
+ if (!FS.hasValidLeftJustified())
+ HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen);
+
+ // Check that flags are not ignored by another flag
+ if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+'
+ HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(),
+ startSpecifier, specifierLen);
+ if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-'
+ HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(),
+ startSpecifier, specifierLen);
+
+ // Check the length modifier is valid with the given conversion specifier.
+ const LengthModifier &LM = FS.getLengthModifier();
+ if (!FS.hasValidLengthModifier())
+ S.Diag(getLocationOfByte(LM.getStart()),
+ diag::warn_format_nonsensical_length)
+ << LM.toString() << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(),
+ LM.getLength()));
+
+ // Are we using '%n'?
+ if (CS.getKind() == ConversionSpecifier::nArg) {
+ // Issue a warning about this being a possible security issue.
+ S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ // Continue checking the other format specifiers.
+ return true;
+ }
+
+ // The remaining checks depend on the data arguments.
+ if (HasVAListArg)
+ return true;
+
+ if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
+ return false;
+
+ // Now type check the data expression that matches the
+ // format specifier.
+ const Expr *Ex = getDataArg(argIndex);
+ const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
+ if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
+ // Check if we didn't match because of an implicit cast from a 'char'
+ // or 'short' to an 'int'. This is done because printf is a varargs
+ // function.
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+ if (ICE->getType() == S.Context.IntTy) {
+ // All further checking is done on the subexpression.
+ Ex = ICE->getSubExpr();
+ if (ATR.matchesType(S.Context, Ex->getType()))
+ return true;
+ }
+
+ // We may be able to offer a FixItHint if it is a supported type.
+ PrintfSpecifier fixedFS = FS;
+ bool success = fixedFS.fixType(Ex->getType());
+
+ if (success) {
+ // Get the fix string from the fixed format specifier
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+ fixedFS.toString(os);
+
+ // FIXME: getRepresentativeType() perhaps should return a string
+ // instead of a QualType to better handle when the representative
+ // type is 'wint_t' (which is defined in the system headers).
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange()
+ << FixItHint::CreateReplacement(
+ getSpecifierRange(startSpecifier, specifierLen),
+ os.str());
+ }
+ else {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+ }
+ }
+
+ return true;
+}
+
+//===--- CHECK: Scanf format string checking ------------------------------===//
+
+namespace {
+class CheckScanfHandler : public CheckFormatHandler {
+public:
+ CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, isObjCLiteral, beg, hasVAListArg,
+ theCall, formatIdx) {}
+
+ bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ void HandleIncompleteScanList(const char *start, const char *end);
+};
+}
+
+void CheckScanfHandler::HandleIncompleteScanList(const char *start,
+ const char *end) {
+ S.Diag(getLocationOfByte(end), diag::warn_scanf_scanlist_incomplete)
+ << getSpecifierRange(start, end - start);
+}
+
+bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ const analyze_scanf::ScanfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+
+ return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+ getLocationOfByte(CS.getStart()),
+ startSpecifier, specifierLen,
+ CS.getStart(), CS.getLength());
+}
+
+bool CheckScanfHandler::HandleScanfSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ using namespace analyze_scanf;
+ using namespace analyze_format_string;
+
+ const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();
+
+ // Handle case where '%' and '*' don't consume an argument. These shouldn't
+ // be used to decide if we are using positional arguments consistently.
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
+ }
+
+ // Check if the field with is non-zero.
+ const OptionalAmount &Amt = FS.getFieldWidth();
+ if (Amt.getHowSpecified() == OptionalAmount::Constant) {
+ if (Amt.getConstantAmount() == 0) {
+ const CharSourceRange &R = getSpecifierRange(Amt.getStart(),
+ Amt.getConstantLength());
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_scanf_nonzero_width)
+ << R << FixItHint::CreateRemoval(R);
+ }
+ }
+
+ if (!FS.consumesDataArgument()) {
+ // FIXME: Technically specifying a precision or field width here
+ // makes no sense. Worth issuing a warning at some point.
+ return true;
+ }
+
+ // Consume the argument.
+ unsigned argIndex = FS.getArgIndex();
+ if (argIndex < NumDataArgs) {
+ // The check to see if the argIndex is valid will come later.
+ // We set the bit here because we may exit early from this
+ // function if we encounter some other error.
+ CoveredArgs.set(argIndex);
+ }
+
+ // Check the length modifier is valid with the given conversion specifier.
+ const LengthModifier &LM = FS.getLengthModifier();
+ if (!FS.hasValidLengthModifier()) {
+ S.Diag(getLocationOfByte(LM.getStart()),
+ diag::warn_format_nonsensical_length)
+ << LM.toString() << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(),
+ LM.getLength()));
+ }
+
+ // The remaining checks depend on the data arguments.
+ if (HasVAListArg)
+ return true;
+
+ if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
+ return false;
+
+ // FIXME: Check that the argument type matches the format specifier.
+
+ return true;
+}
+
+void Sema::CheckFormatString(const StringLiteral *FExpr,
+ const Expr *OrigFormatExpr,
+ const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+
+ // CHECK: is the format string a wide literal?
+ if (FExpr->isWide()) {
+ Diag(FExpr->getLocStart(),
+ diag::warn_format_string_is_wide_literal)
+ << OrigFormatExpr->getSourceRange();
+ return;
+ }
+
+ // Str - The format string. NOTE: this is NOT null-terminated!
+ llvm::StringRef StrRef = FExpr->getString();
+ const char *Str = StrRef.data();
+ unsigned StrLen = StrRef.size();
+
+ // CHECK: empty format string?
+ if (StrLen == 0) {
+ Diag(FExpr->getLocStart(), diag::warn_empty_format_string)
+ << OrigFormatExpr->getSourceRange();
+ return;
+ }
+
+ if (isPrintf) {
+ CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
+
+ bool FormatExtensions = getLangOptions().FormatExtensions;
+ if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
+ FormatExtensions))
+ H.DoneProcessing();
+ }
+ else {
+ CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
+
+ if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen))
+ H.DoneProcessing();
+ }
+}
+
+//===--- CHECK: Return Address of Stack Variable --------------------------===//
+
+static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars);
+static Expr *EvalAddr(Expr* E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars);
+
+/// CheckReturnStackAddr - Check if a return statement returns the address
+/// of a stack variable.
+void
+Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc) {
+
+ Expr *stackE = 0;
+ llvm::SmallVector<DeclRefExpr *, 8> refVars;
+
+ // Perform checking for returned stack addresses, local blocks,
+ // label addresses or references to temporaries.
+ if (lhsType->isPointerType() || lhsType->isBlockPointerType()) {
+ stackE = EvalAddr(RetValExp, refVars);
+ } else if (lhsType->isReferenceType()) {
+ stackE = EvalVal(RetValExp, refVars);
+ }
+
+ if (stackE == 0)
+ return; // Nothing suspicious was found.
+
+ SourceLocation diagLoc;
+ SourceRange diagRange;
+ if (refVars.empty()) {
+ diagLoc = stackE->getLocStart();
+ diagRange = stackE->getSourceRange();
+ } else {
+ // We followed through a reference variable. 'stackE' contains the
+ // problematic expression but we will warn at the return statement pointing
+ // at the reference variable. We will later display the "trail" of
+ // reference variables using notes.
+ diagLoc = refVars[0]->getLocStart();
+ diagRange = refVars[0]->getSourceRange();
+ }
+
+ if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
+ Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
+ : diag::warn_ret_stack_addr)
+ << DR->getDecl()->getDeclName() << diagRange;
+ } else if (isa<BlockExpr>(stackE)) { // local block.
+ Diag(diagLoc, diag::err_ret_local_block) << diagRange;
+ } else if (isa<AddrLabelExpr>(stackE)) { // address of label.
+ Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
+ } else { // local temporary.
+ Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
+ : diag::warn_ret_local_temp_addr)
+ << diagRange;
+ }
+
+ // Display the "trail" of reference variables that we followed until we
+ // found the problematic expression using notes.
+ for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
+ VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
+ // If this var binds to another reference var, show the range of the next
+ // var, otherwise the var binds to the problematic expression, in which case
+ // show the range of the expression.
+ SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
+ : stackE->getSourceRange();
+ Diag(VD->getLocation(), diag::note_ref_var_local_bind)
+ << VD->getDeclName() << range;
+ }
+}
+
+/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that
+/// check if the expression in a return statement evaluates to an address
+/// to a location on the stack, a local block, an address of a label, or a
+/// reference to local temporary. The recursion is used to traverse the
+/// AST of the return expression, with recursion backtracking when we
+/// encounter a subexpression that (1) clearly does not lead to one of the
+/// above problematic expressions (2) is something we cannot determine leads to
+/// a problematic expression based on such local checking.
+///
+/// Both EvalAddr and EvalVal follow through reference variables to evaluate
+/// the expression that they point to. Such variables are added to the
+/// 'refVars' vector so that we know what the reference variable "trail" was.
+///
+/// EvalAddr processes expressions that are pointers that are used as
+/// references (and not L-values). EvalVal handles all other values.
+/// At the base case of the recursion is a check for the above problematic
+/// expressions.
+///
+/// This implementation handles:
+///
+/// * pointer-to-pointer casts
+/// * implicit conversions from array references to pointers
+/// * taking the address of fields
+/// * arbitrary interplay between "&" and "*" operators
+/// * pointer arithmetic from an address of a stack variable
+/// * taking the address of an array element where the array is on the stack
+static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) {
+ if (E->isTypeDependent())
+ return NULL;
+
+ // We should only be called for evaluating pointer expressions.
+ assert((E->getType()->isAnyPointerType() ||
+ E->getType()->isBlockPointerType() ||
+ E->getType()->isObjCQualifiedIdType()) &&
+ "EvalAddr only works on pointers");
+
+ // Our "symbolic interpreter" is just a dispatch off the currently
+ // viewed AST node. We then recursively traverse the AST by calling
+ // EvalAddr and EvalVal appropriately.
+ switch (E->getStmtClass()) {
+ case Stmt::ParenExprClass:
+ // Ignore parentheses.
+ return EvalAddr(cast<ParenExpr>(E)->getSubExpr(), refVars);
+
+ case Stmt::DeclRefExprClass: {
+ DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+ if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+ // If this is a reference variable, follow through to the expression that
+ // it points to.
+ if (V->hasLocalStorage() &&
+ V->getType()->isReferenceType() && V->hasInit()) {
+ // Add the reference variable to the "trail".
+ refVars.push_back(DR);
+ return EvalAddr(V->getInit(), refVars);
+ }
+
+ return NULL;
+ }
+
+ case Stmt::UnaryOperatorClass: {
+ // The only unary operator that make sense to handle here
+ // is AddrOf. All others don't make sense as pointers.
+ UnaryOperator *U = cast<UnaryOperator>(E);
+
+ if (U->getOpcode() == UO_AddrOf)
+ return EvalVal(U->getSubExpr(), refVars);
+ else
+ return NULL;
+ }
+
+ case Stmt::BinaryOperatorClass: {
+ // Handle pointer arithmetic. All other binary operators are not valid
+ // in this context.
+ BinaryOperator *B = cast<BinaryOperator>(E);
+ BinaryOperatorKind op = B->getOpcode();
+
+ if (op != BO_Add && op != BO_Sub)
+ return NULL;
+
+ Expr *Base = B->getLHS();
+
+ // Determine which argument is the real pointer base. It could be
+ // the RHS argument instead of the LHS.
+ if (!Base->getType()->isPointerType()) Base = B->getRHS();
+
+ assert (Base->getType()->isPointerType());
+ return EvalAddr(Base, refVars);
+ }
+
+ // For conditional operators we need to see if either the LHS or RHS are
+ // valid DeclRefExpr*s. If one of them is valid, we return it.
+ case Stmt::ConditionalOperatorClass: {
+ ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+ // Handle the GNU extension for missing LHS.
+ if (Expr *lhsExpr = C->getLHS()) {
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (!lhsExpr->getType()->isVoidType())
+ if (Expr* LHS = EvalAddr(lhsExpr, refVars))
+ return LHS;
+ }
+
+ // In C++, we can have a throw-expression, which has 'void' type.
+ if (C->getRHS()->getType()->isVoidType())
+ return NULL;
+
+ return EvalAddr(C->getRHS(), refVars);
+ }
+
+ case Stmt::BlockExprClass:
+ if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures())
+ return E; // local block.
+ return NULL;
+
+ case Stmt::AddrLabelExprClass:
+ return E; // address of label.
+
+ // For casts, we need to handle conversions from arrays to
+ // pointer values, and pointer-to-pointer conversions.
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass: {
+ Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
+ QualType T = SubExpr->getType();
+
+ if (SubExpr->getType()->isPointerType() ||
+ SubExpr->getType()->isBlockPointerType() ||
+ SubExpr->getType()->isObjCQualifiedIdType())
+ return EvalAddr(SubExpr, refVars);
+ else if (T->isArrayType())
+ return EvalVal(SubExpr, refVars);
+ else
+ return 0;
+ }
+
+ // C++ casts. For dynamic casts, static casts, and const casts, we
+ // are always converting from a pointer-to-pointer, so we just blow
+ // through the cast. In the case the dynamic cast doesn't fail (and
+ // return NULL), we take the conservative route and report cases
+ // where we return the address of a stack variable. For Reinterpre
+ // FIXME: The comment about is wrong; we're not always converting
+ // from pointer to pointer. I'm guessing that this code should also
+ // handle references to objects.
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass: {
+ Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr();
+ if (S->getType()->isPointerType() || S->getType()->isBlockPointerType())
+ return EvalAddr(S, refVars);
+ else
+ return NULL;
+ }
+
+ // Everything else: we simply don't reason about them.
+ default:
+ return NULL;
+ }
+}
+
+
+/// EvalVal - This function is complements EvalAddr in the mutual recursion.
+/// See the comments for EvalAddr for more details.
+static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) {
+do {
+ // We should only be called for evaluating non-pointer expressions, or
+ // expressions with a pointer type that are not used as references but instead
+ // are l-values (e.g., DeclRefExpr with a pointer type).
+
+ // Our "symbolic interpreter" is just a dispatch off the currently
+ // viewed AST node. We then recursively traverse the AST by calling
+ // EvalAddr and EvalVal appropriately.
+ switch (E->getStmtClass()) {
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
+ if (IE->getValueKind() == VK_LValue) {
+ E = IE->getSubExpr();
+ continue;
+ }
+ return NULL;
+ }
+
+ case Stmt::DeclRefExprClass: {
+ // When we hit a DeclRefExpr we are looking at code that refers to a
+ // variable's name. If it's not a reference variable we check if it has
+ // local storage within the function, and if so, return the expression.
+ DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+ if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
+ if (V->hasLocalStorage()) {
+ if (!V->getType()->isReferenceType())
+ return DR;
+
+ // Reference variable, follow through to the expression that
+ // it points to.
+ if (V->hasInit()) {
+ // Add the reference variable to the "trail".
+ refVars.push_back(DR);
+ return EvalVal(V->getInit(), refVars);
+ }
+ }
+
+ return NULL;
+ }
+
+ case Stmt::ParenExprClass: {
+ // Ignore parentheses.
+ E = cast<ParenExpr>(E)->getSubExpr();
+ continue;
+ }
+
+ case Stmt::UnaryOperatorClass: {
+ // The only unary operator that make sense to handle here
+ // is Deref. All others don't resolve to a "name." This includes
+ // handling all sorts of rvalues passed to a unary operator.
+ UnaryOperator *U = cast<UnaryOperator>(E);
+
+ if (U->getOpcode() == UO_Deref)
+ return EvalAddr(U->getSubExpr(), refVars);
+
+ return NULL;
+ }
+
+ case Stmt::ArraySubscriptExprClass: {
+ // Array subscripts are potential references to data on the stack. We
+ // retrieve the DeclRefExpr* for the array variable if it indeed
+ // has local storage.
+ return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars);
+ }
+
+ case Stmt::ConditionalOperatorClass: {
+ // For conditional operators we need to see if either the LHS or RHS are
+ // non-NULL Expr's. If one is non-NULL, we return it.
+ ConditionalOperator *C = cast<ConditionalOperator>(E);
+
+ // Handle the GNU extension for missing LHS.
+ if (Expr *lhsExpr = C->getLHS())
+ if (Expr *LHS = EvalVal(lhsExpr, refVars))
+ return LHS;
+
+ return EvalVal(C->getRHS(), refVars);
+ }
+
+ // Accesses to members are potential references to data on the stack.
+ case Stmt::MemberExprClass: {
+ MemberExpr *M = cast<MemberExpr>(E);
+
+ // Check for indirect access. We only want direct field accesses.
+ if (M->isArrow())
+ return NULL;
+
+ // Check whether the member type is itself a reference, in which case
+ // we're not going to refer to the member, but to what the member refers to.
+ if (M->getMemberDecl()->getType()->isReferenceType())
+ return NULL;
+
+ return EvalVal(M->getBase(), refVars);
+ }
+
+ default:
+ // Check that we don't return or take the address of a reference to a
+ // temporary. This is only useful in C++.
+ if (!E->isTypeDependent() && E->isRValue())
+ return E;
+
+ // Everything else: we simply don't reason about them.
+ return NULL;
+ }
+} while (true);
+}
+
+//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
+
+/// Check for comparisons of floating point operands using != and ==.
+/// Issue a warning if these are no self-comparisons, as they are not likely
+/// to do what the programmer intended.
+void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) {
+ bool EmitWarning = true;
+
+ Expr* LeftExprSansParen = lex->IgnoreParenImpCasts();
+ Expr* RightExprSansParen = rex->IgnoreParenImpCasts();
+
+ // Special case: check for x == x (which is OK).
+ // Do not emit warnings for such cases.
+ if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
+ if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
+ if (DRL->getDecl() == DRR->getDecl())
+ EmitWarning = false;
+
+
+ // Special case: check for comparisons against literals that can be exactly
+ // represented by APFloat. In such cases, do not emit a warning. This
+ // is a heuristic: often comparison against such literals are used to
+ // detect if a value in a variable has not changed. This clearly can
+ // lead to false negatives.
+ if (EmitWarning) {
+ if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
+ if (FLL->isExact())
+ EmitWarning = false;
+ } else
+ if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){
+ if (FLR->isExact())
+ EmitWarning = false;
+ }
+ }
+
+ // Check for comparisons with builtin types.
+ if (EmitWarning)
+ if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen))
+ if (CL->isBuiltinCall(Context))
+ EmitWarning = false;
+
+ if (EmitWarning)
+ if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen))
+ if (CR->isBuiltinCall(Context))
+ EmitWarning = false;
+
+ // Emit the diagnostic.
+ if (EmitWarning)
+ Diag(loc, diag::warn_floatingpoint_eq)
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
+//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===//
+//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===//
+
+namespace {
+
+/// Structure recording the 'active' range of an integer-valued
+/// expression.
+struct IntRange {
+ /// The number of bits active in the int.
+ unsigned Width;
+
+ /// True if the int is known not to have negative values.
+ bool NonNegative;
+
+ IntRange(unsigned Width, bool NonNegative)
+ : Width(Width), NonNegative(NonNegative)
+ {}
+
+ /// Returns the range of the bool type.
+ static IntRange forBoolType() {
+ return IntRange(1, true);
+ }
+
+ /// Returns the range of an opaque value of the given integral type.
+ static IntRange forValueOfType(ASTContext &C, QualType T) {
+ return forValueOfCanonicalType(C,
+ T->getCanonicalTypeInternal().getTypePtr());
+ }
+
+ /// Returns the range of an opaque value of a canonical integral type.
+ static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) {
+ assert(T->isCanonicalUnqualified());
+
+ if (const VectorType *VT = dyn_cast<VectorType>(T))
+ T = VT->getElementType().getTypePtr();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+ T = CT->getElementType().getTypePtr();
+
+ // For enum types, use the known bit width of the enumerators.
+ if (const EnumType *ET = dyn_cast<EnumType>(T)) {
+ EnumDecl *Enum = ET->getDecl();
+ if (!Enum->isDefinition())
+ return IntRange(C.getIntWidth(QualType(T, 0)), false);
+
+ unsigned NumPositive = Enum->getNumPositiveBits();
+ unsigned NumNegative = Enum->getNumNegativeBits();
+
+ return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0);
+ }
+
+ const BuiltinType *BT = cast<BuiltinType>(T);
+ assert(BT->isInteger());
+
+ return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+ }
+
+ /// Returns the "target" range of a canonical integral type, i.e.
+ /// the range of values expressible in the type.
+ ///
+ /// This matches forValueOfCanonicalType except that enums have the
+ /// full range of their type, not the range of their enumerators.
+ static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) {
+ assert(T->isCanonicalUnqualified());
+
+ if (const VectorType *VT = dyn_cast<VectorType>(T))
+ T = VT->getElementType().getTypePtr();
+ if (const ComplexType *CT = dyn_cast<ComplexType>(T))
+ T = CT->getElementType().getTypePtr();
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ T = ET->getDecl()->getIntegerType().getTypePtr();
+
+ const BuiltinType *BT = cast<BuiltinType>(T);
+ assert(BT->isInteger());
+
+ return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
+ }
+
+ /// Returns the supremum of two ranges: i.e. their conservative merge.
+ static IntRange join(IntRange L, IntRange R) {
+ return IntRange(std::max(L.Width, R.Width),
+ L.NonNegative && R.NonNegative);
+ }
+
+ /// Returns the infinum of two ranges: i.e. their aggressive merge.
+ static IntRange meet(IntRange L, IntRange R) {
+ return IntRange(std::min(L.Width, R.Width),
+ L.NonNegative || R.NonNegative);
+ }
+};
+
+IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) {
+ if (value.isSigned() && value.isNegative())
+ return IntRange(value.getMinSignedBits(), false);
+
+ if (value.getBitWidth() > MaxWidth)
+ value = value.trunc(MaxWidth);
+
+ // isNonNegative() just checks the sign bit without considering
+ // signedness.
+ return IntRange(value.getActiveBits(), true);
+}
+
+IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty,
+ unsigned MaxWidth) {
+ if (result.isInt())
+ return GetValueRange(C, result.getInt(), MaxWidth);
+
+ if (result.isVector()) {
+ IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth);
+ for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) {
+ IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth);
+ R = IntRange::join(R, El);
+ }
+ return R;
+ }
+
+ if (result.isComplexInt()) {
+ IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth);
+ IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth);
+ return IntRange::join(R, I);
+ }
+
+ // This can happen with lossless casts to intptr_t of "based" lvalues.
+ // Assume it might use arbitrary bits.
+ // FIXME: The only reason we need to pass the type in here is to get
+ // the sign right on this one case. It would be nice if APValue
+ // preserved this.
+ assert(result.isLValue());
+ return IntRange(MaxWidth, Ty->isUnsignedIntegerType());
+}
+
+/// Pseudo-evaluate the given integer expression, estimating the
+/// range of values it might take.
+///
+/// \param MaxWidth - the width to which the value will be truncated
+IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
+ E = E->IgnoreParens();
+
+ // Try a full evaluation first.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, C))
+ return GetValueRange(C, result.Val, E->getType(), MaxWidth);
+
+ // I think we only want to look through implicit casts here; if the
+ // user has an explicit widening cast, we should treat the value as
+ // being of the new, wider type.
+ if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (CE->getCastKind() == CK_NoOp)
+ return GetExprRange(C, CE->getSubExpr(), MaxWidth);
+
+ IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType());
+
+ bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
+
+ // Assume that non-integer casts can span the full range of the type.
+ if (!isIntegerCast)
+ return OutputTypeRange;
+
+ IntRange SubRange
+ = GetExprRange(C, CE->getSubExpr(),
+ std::min(MaxWidth, OutputTypeRange.Width));
+
+ // Bail out if the subexpr's range is as wide as the cast type.
+ if (SubRange.Width >= OutputTypeRange.Width)
+ return OutputTypeRange;
+
+ // Otherwise, we take the smaller width, and we're non-negative if
+ // either the output type or the subexpr is.
+ return IntRange(SubRange.Width,
+ SubRange.NonNegative || OutputTypeRange.NonNegative);
+ }
+
+ if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+ // If we can fold the condition, just take that operand.
+ bool CondResult;
+ if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
+ return GetExprRange(C, CondResult ? CO->getTrueExpr()
+ : CO->getFalseExpr(),
+ MaxWidth);
+
+ // Otherwise, conservatively merge.
+ IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth);
+ IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth);
+ return IntRange::join(L, R);
+ }
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ switch (BO->getOpcode()) {
+
+ // Boolean-valued operations are single-bit and positive.
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ return IntRange::forBoolType();
+
+ // The type of these compound assignments is the type of the LHS,
+ // so the RHS is not necessarily an integer.
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ return IntRange::forValueOfType(C, E->getType());
+
+ // Operations with opaque sources are black-listed.
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ return IntRange::forValueOfType(C, E->getType());
+
+ // Bitwise-and uses the *infinum* of the two source ranges.
+ case BO_And:
+ case BO_AndAssign:
+ return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth),
+ GetExprRange(C, BO->getRHS(), MaxWidth));
+
+ // Left shift gets black-listed based on a judgement call.
+ case BO_Shl:
+ // ...except that we want to treat '1 << (blah)' as logically
+ // positive. It's an important idiom.
+ if (IntegerLiteral *I
+ = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
+ if (I->getValue() == 1) {
+ IntRange R = IntRange::forValueOfType(C, E->getType());
+ return IntRange(R.Width, /*NonNegative*/ true);
+ }
+ }
+ // fallthrough
+
+ case BO_ShlAssign:
+ return IntRange::forValueOfType(C, E->getType());
+
+ // Right shift by a constant can narrow its left argument.
+ case BO_Shr:
+ case BO_ShrAssign: {
+ IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+
+ // If the shift amount is a positive constant, drop the width by
+ // that much.
+ llvm::APSInt shift;
+ if (BO->getRHS()->isIntegerConstantExpr(shift, C) &&
+ shift.isNonNegative()) {
+ unsigned zext = shift.getZExtValue();
+ if (zext >= L.Width)
+ L.Width = (L.NonNegative ? 0 : 1);
+ else
+ L.Width -= zext;
+ }
+
+ return L;
+ }
+
+ // Comma acts as its right operand.
+ case BO_Comma:
+ return GetExprRange(C, BO->getRHS(), MaxWidth);
+
+ // Black-list pointer subtractions.
+ case BO_Sub:
+ if (BO->getLHS()->getType()->isPointerType())
+ return IntRange::forValueOfType(C, E->getType());
+ // fallthrough
+
+ default:
+ break;
+ }
+
+ // Treat every other operator as if it were closed on the
+ // narrowest type that encompasses both operands.
+ IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
+ IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth);
+ return IntRange::join(L, R);
+ }
+
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ switch (UO->getOpcode()) {
+ // Boolean-valued operations are white-listed.
+ case UO_LNot:
+ return IntRange::forBoolType();
+
+ // Operations with opaque sources are black-listed.
+ case UO_Deref:
+ case UO_AddrOf: // should be impossible
+ return IntRange::forValueOfType(C, E->getType());
+
+ default:
+ return GetExprRange(C, UO->getSubExpr(), MaxWidth);
+ }
+ }
+
+ if (dyn_cast<OffsetOfExpr>(E)) {
+ IntRange::forValueOfType(C, E->getType());
+ }
+
+ FieldDecl *BitField = E->getBitField();
+ if (BitField) {
+ llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C);
+ unsigned BitWidth = BitWidthAP.getZExtValue();
+
+ return IntRange(BitWidth, BitField->getType()->isUnsignedIntegerType());
+ }
+
+ return IntRange::forValueOfType(C, E->getType());
+}
+
+IntRange GetExprRange(ASTContext &C, Expr *E) {
+ return GetExprRange(C, E, C.getIntWidth(E->getType()));
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+bool IsSameFloatAfterCast(const llvm::APFloat &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ llvm::APFloat truncated = value;
+
+ bool ignored;
+ truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
+ truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);
+
+ return truncated.bitwiseIsEqual(value);
+}
+
+/// Checks whether the given value, which currently has the given
+/// source semantics, has the same value when coerced through the
+/// target semantics.
+///
+/// The value might be a vector of floats (or a complex number).
+bool IsSameFloatAfterCast(const APValue &value,
+ const llvm::fltSemantics &Src,
+ const llvm::fltSemantics &Tgt) {
+ if (value.isFloat())
+ return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);
+
+ if (value.isVector()) {
+ for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
+ if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
+ return false;
+ return true;
+ }
+
+ assert(value.isComplexFloat());
+ return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
+ IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
+}
+
+void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC);
+
+static bool IsZero(Sema &S, Expr *E) {
+ // Suppress cases where we are comparing against an enum constant.
+ if (const DeclRefExpr *DR =
+ dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
+ if (isa<EnumConstantDecl>(DR->getDecl()))
+ return false;
+
+ // Suppress cases where the '0' value is expanded from a macro.
+ if (E->getLocStart().isMacroID())
+ return false;
+
+ llvm::APSInt Value;
+ return E->isIntegerConstantExpr(Value, S.Context) && Value == 0;
+}
+
+static bool HasEnumType(Expr *E) {
+ // Strip off implicit integral promotions.
+ while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() != CK_IntegralCast &&
+ ICE->getCastKind() != CK_NoOp)
+ break;
+ E = ICE->getSubExpr();
+ }
+
+ return E->getType()->isEnumeralType();
+}
+
+void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
+ BinaryOperatorKind op = E->getOpcode();
+ if (E->isValueDependent())
+ return;
+
+ if (op == BO_LT && IsZero(S, E->getRHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+ << "< 0" << "false" << HasEnumType(E->getLHS())
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BO_GE && IsZero(S, E->getRHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
+ << ">= 0" << "true" << HasEnumType(E->getLHS())
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BO_GT && IsZero(S, E->getLHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+ << "0 >" << "false" << HasEnumType(E->getRHS())
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ } else if (op == BO_LE && IsZero(S, E->getLHS())) {
+ S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
+ << "0 <=" << "true" << HasEnumType(E->getRHS())
+ << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
+ }
+}
+
+/// Analyze the operands of the given comparison. Implements the
+/// fallback case from AnalyzeComparison.
+void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
+ AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+}
+
+/// \brief Implements -Wsign-compare.
+///
+/// \param lex the left-hand expression
+/// \param rex the right-hand expression
+/// \param OpLoc the location of the joining operator
+/// \param BinOpc binary opcode or 0
+void AnalyzeComparison(Sema &S, BinaryOperator *E) {
+ // The type the comparison is being performed in.
+ QualType T = E->getLHS()->getType();
+ assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType())
+ && "comparison with mismatched types");
+
+ // We don't do anything special if this isn't an unsigned integral
+ // comparison: we're only interested in integral comparisons, and
+ // signed comparisons only happen in cases we don't care to warn about.
+ //
+ // We also don't care about value-dependent expressions or expressions
+ // whose result is a constant.
+ if (!T->hasUnsignedIntegerRepresentation()
+ || E->isValueDependent() || E->isIntegerConstantExpr(S.Context))
+ return AnalyzeImpConvsInComparison(S, E);
+
+ Expr *lex = E->getLHS()->IgnoreParenImpCasts();
+ Expr *rex = E->getRHS()->IgnoreParenImpCasts();
+
+ // Check to see if one of the (unmodified) operands is of different
+ // signedness.
+ Expr *signedOperand, *unsignedOperand;
+ if (lex->getType()->hasSignedIntegerRepresentation()) {
+ assert(!rex->getType()->hasSignedIntegerRepresentation() &&
+ "unsigned comparison between two signed integer expressions?");
+ signedOperand = lex;
+ unsignedOperand = rex;
+ } else if (rex->getType()->hasSignedIntegerRepresentation()) {
+ signedOperand = rex;
+ unsignedOperand = lex;
+ } else {
+ CheckTrivialUnsignedComparison(S, E);
+ return AnalyzeImpConvsInComparison(S, E);
+ }
+
+ // Otherwise, calculate the effective range of the signed operand.
+ IntRange signedRange = GetExprRange(S.Context, signedOperand);
+
+ // Go ahead and analyze implicit conversions in the operands. Note
+ // that we skip the implicit conversions on both sides.
+ AnalyzeImplicitConversions(S, lex, E->getOperatorLoc());
+ AnalyzeImplicitConversions(S, rex, E->getOperatorLoc());
+
+ // If the signed range is non-negative, -Wsign-compare won't fire,
+ // but we should still check for comparisons which are always true
+ // or false.
+ if (signedRange.NonNegative)
+ return CheckTrivialUnsignedComparison(S, E);
+
+ // For (in)equality comparisons, if the unsigned operand is a
+ // constant which cannot collide with a overflowed signed operand,
+ // then reinterpreting the signed operand as unsigned will not
+ // change the result of the comparison.
+ if (E->isEqualityOp()) {
+ unsigned comparisonWidth = S.Context.getIntWidth(T);
+ IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand);
+
+ // We should never be unable to prove that the unsigned operand is
+ // non-negative.
+ assert(unsignedRange.NonNegative && "unsigned range includes negative?");
+
+ if (unsignedRange.Width < comparisonWidth)
+ return;
+ }
+
+ S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
+/// Analyzes an attempt to assign the given value to a bitfield.
+///
+/// Returns true if there was something fishy about the attempt.
+bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
+ SourceLocation InitLoc) {
+ assert(Bitfield->isBitField());
+ if (Bitfield->isInvalidDecl())
+ return false;
+
+ // White-list bool bitfields.
+ if (Bitfield->getType()->isBooleanType())
+ return false;
+
+ // Ignore value- or type-dependent expressions.
+ if (Bitfield->getBitWidth()->isValueDependent() ||
+ Bitfield->getBitWidth()->isTypeDependent() ||
+ Init->isValueDependent() ||
+ Init->isTypeDependent())
+ return false;
+
+ Expr *OriginalInit = Init->IgnoreParenImpCasts();
+
+ llvm::APSInt Width(32);
+ Expr::EvalResult InitValue;
+ if (!Bitfield->getBitWidth()->isIntegerConstantExpr(Width, S.Context) ||
+ !OriginalInit->Evaluate(InitValue, S.Context) ||
+ !InitValue.Val.isInt())
+ return false;
+
+ const llvm::APSInt &Value = InitValue.Val.getInt();
+ unsigned OriginalWidth = Value.getBitWidth();
+ unsigned FieldWidth = Width.getZExtValue();
+
+ if (OriginalWidth <= FieldWidth)
+ return false;
+
+ llvm::APSInt TruncatedValue = Value.trunc(FieldWidth);
+
+ // It's fairly common to write values into signed bitfields
+ // that, if sign-extended, would end up becoming a different
+ // value. We don't want to warn about that.
+ if (Value.isSigned() && Value.isNegative())
+ TruncatedValue = TruncatedValue.sext(OriginalWidth);
+ else
+ TruncatedValue = TruncatedValue.zext(OriginalWidth);
+
+ if (Value == TruncatedValue)
+ return false;
+
+ std::string PrettyValue = Value.toString(10);
+ std::string PrettyTrunc = TruncatedValue.toString(10);
+
+ S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant)
+ << PrettyValue << PrettyTrunc << OriginalInit->getType()
+ << Init->getSourceRange();
+
+ return true;
+}
+
+/// Analyze the given simple or compound assignment for warning-worthy
+/// operations.
+void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
+ // Just recurse on the LHS.
+ AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
+
+ // We want to recurse on the RHS as normal unless we're assigning to
+ // a bitfield.
+ if (FieldDecl *Bitfield = E->getLHS()->getBitField()) {
+ if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(),
+ E->getOperatorLoc())) {
+ // Recurse, ignoring any implicit conversions on the RHS.
+ return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(),
+ E->getOperatorLoc());
+ }
+ }
+
+ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
+}
+
+/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
+void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext,
+ unsigned diag) {
+ S.Diag(E->getExprLoc(), diag)
+ << E->getType() << T << E->getSourceRange() << SourceRange(CContext);
+}
+
+std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
+ if (!Range.Width) return "0";
+
+ llvm::APSInt ValueInRange = Value;
+ ValueInRange.setIsSigned(!Range.NonNegative);
+ ValueInRange = ValueInRange.trunc(Range.Width);
+ return ValueInRange.toString(10);
+}
+
+void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
+ SourceLocation CC, bool *ICContext = 0) {
+ if (E->isTypeDependent() || E->isValueDependent()) return;
+
+ const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+ const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+ if (Source == Target) return;
+ if (Target->isDependentType()) return;
+
+ // If the conversion context location is invalid or instantiated
+ // from a system macro, don't complain.
+ if (CC.isInvalid() ||
+ (CC.isMacroID() && S.Context.getSourceManager().isInSystemHeader(
+ S.Context.getSourceManager().getSpellingLoc(CC))))
+ return;
+
+ // Never diagnose implicit casts to bool.
+ if (Target->isSpecificBuiltinType(BuiltinType::Bool))
+ return;
+
+ // Strip vector types.
+ if (isa<VectorType>(Source)) {
+ if (!isa<VectorType>(Target))
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar);
+
+ Source = cast<VectorType>(Source)->getElementType().getTypePtr();
+ Target = cast<VectorType>(Target)->getElementType().getTypePtr();
+ }
+
+ // Strip complex types.
+ if (isa<ComplexType>(Source)) {
+ if (!isa<ComplexType>(Target))
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
+
+ Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
+ Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
+ }
+
+ const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
+ const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);
+
+ // If the source is floating point...
+ if (SourceBT && SourceBT->isFloatingPoint()) {
+ // ...and the target is floating point...
+ if (TargetBT && TargetBT->isFloatingPoint()) {
+ // ...then warn if we're dropping FP rank.
+
+ // Builtin FP kinds are ordered by increasing FP rank.
+ if (SourceBT->getKind() > TargetBT->getKind()) {
+ // Don't warn about float constants that are precisely
+ // representable in the target type.
+ Expr::EvalResult result;
+ if (E->Evaluate(result, S.Context)) {
+ // Value might be a float, a float vector, or a float complex.
+ if (IsSameFloatAfterCast(result.Val,
+ S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
+ S.Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
+ return;
+ }
+
+ DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
+ }
+ return;
+ }
+
+ // If the target is integral, always warn.
+ if ((TargetBT && TargetBT->isInteger())) {
+ Expr *InnerE = E->IgnoreParenImpCasts();
+ if (FloatingLiteral *LiteralExpr = dyn_cast<FloatingLiteral>(InnerE)) {
+ DiagnoseImpCast(S, LiteralExpr, T, CC,
+ diag::warn_impcast_literal_float_to_integer);
+ } else {
+ DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer);
+ }
+ }
+
+ return;
+ }
+
+ if (!Source->isIntegerType() || !Target->isIntegerType())
+ return;
+
+ IntRange SourceRange = GetExprRange(S.Context, E);
+ IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
+
+ if (SourceRange.Width > TargetRange.Width) {
+ // If the source is a constant, use a default-on diagnostic.
+ // TODO: this should happen for bitfield stores, too.
+ llvm::APSInt Value(32);
+ if (E->isIntegerConstantExpr(Value, S.Context)) {
+ std::string PrettySourceValue = Value.toString(10);
+ std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
+
+ S.Diag(E->getExprLoc(), diag::warn_impcast_integer_precision_constant)
+ << PrettySourceValue << PrettyTargetValue
+ << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC);
+ return;
+ }
+
+ // People want to build with -Wshorten-64-to-32 and not -Wconversion
+ // and by god we'll let them.
+ if (SourceRange.Width == 64 && TargetRange.Width == 32)
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32);
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
+ }
+
+ if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
+ (!TargetRange.NonNegative && SourceRange.NonNegative &&
+ SourceRange.Width == TargetRange.Width)) {
+ unsigned DiagID = diag::warn_impcast_integer_sign;
+
+ // Traditionally, gcc has warned about this under -Wsign-compare.
+ // We also want to warn about it in -Wconversion.
+ // So if -Wconversion is off, use a completely identical diagnostic
+ // in the sign-compare group.
+ // The conditional-checking code will
+ if (ICContext) {
+ DiagID = diag::warn_impcast_integer_sign_conditional;
+ *ICContext = true;
+ }
+
+ return DiagnoseImpCast(S, E, T, CC, DiagID);
+ }
+
+ return;
+}
+
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T);
+
+void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
+ SourceLocation CC, bool &ICContext) {
+ E = E->IgnoreParenImpCasts();
+
+ if (isa<ConditionalOperator>(E))
+ return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T);
+
+ AnalyzeImplicitConversions(S, E, CC);
+ if (E->getType() != T)
+ return CheckImplicitConversion(S, E, T, CC, &ICContext);
+ return;
+}
+
+void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) {
+ SourceLocation CC = E->getQuestionLoc();
+
+ AnalyzeImplicitConversions(S, E->getCond(), CC);
+
+ bool Suspicious = false;
+ CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
+ CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
+
+ // If -Wconversion would have warned about either of the candidates
+ // for a signedness conversion to the context type...
+ if (!Suspicious) return;
+
+ // ...but it's currently ignored...
+ if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional,
+ CC))
+ return;
+
+ // ...and -Wsign-compare isn't...
+ if (!S.Diags.getDiagnosticLevel(diag::warn_mixed_sign_conditional, CC))
+ return;
+
+ // ...then check whether it would have warned about either of the
+ // candidates for a signedness conversion to the condition type.
+ if (E->getType() != T) {
+ Suspicious = false;
+ CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(),
+ E->getType(), CC, &Suspicious);
+ if (!Suspicious)
+ CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(),
+ E->getType(), CC, &Suspicious);
+ if (!Suspicious)
+ return;
+ }
+
+ // If so, emit a diagnostic under -Wsign-compare.
+ Expr *lex = E->getTrueExpr()->IgnoreParenImpCasts();
+ Expr *rex = E->getFalseExpr()->IgnoreParenImpCasts();
+ S.Diag(E->getQuestionLoc(), diag::warn_mixed_sign_conditional)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+}
+
+/// AnalyzeImplicitConversions - Find and report any interesting
+/// implicit conversions in the given expression. There are a couple
+/// of competing diagnostics here, -Wconversion and -Wsign-compare.
+void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
+ QualType T = OrigE->getType();
+ Expr *E = OrigE->IgnoreParenImpCasts();
+
+ // For conditional operators, we analyze the arguments as if they
+ // were being fed directly into the output.
+ if (isa<ConditionalOperator>(E)) {
+ ConditionalOperator *CO = cast<ConditionalOperator>(E);
+ CheckConditionalOperator(S, CO, T);
+ return;
+ }
+
+ // Go ahead and check any implicit conversions we might have skipped.
+ // The non-canonical typecheck is just an optimization;
+ // CheckImplicitConversion will filter out dead implicit conversions.
+ if (E->getType() != T)
+ CheckImplicitConversion(S, E, T, CC);
+
+ // Now continue drilling into this expression.
+
+ // Skip past explicit casts.
+ if (isa<ExplicitCastExpr>(E)) {
+ E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
+ return AnalyzeImplicitConversions(S, E, CC);
+ }
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ // Do a somewhat different check with comparison operators.
+ if (BO->isComparisonOp())
+ return AnalyzeComparison(S, BO);
+
+ // And with assignments and compound assignments.
+ if (BO->isAssignmentOp())
+ return AnalyzeAssignment(S, BO);
+ }
+
+ // These break the otherwise-useful invariant below. Fortunately,
+ // we don't really need to recurse into them, because any internal
+ // expressions should have been analyzed already when they were
+ // built into statements.
+ if (isa<StmtExpr>(E)) return;
+
+ // Don't descend into unevaluated contexts.
+ if (isa<SizeOfAlignOfExpr>(E)) return;
+
+ // Now just recurse over the expression's children.
+ CC = E->getExprLoc();
+ for (Stmt::child_range I = E->children(); I; ++I)
+ AnalyzeImplicitConversions(S, cast<Expr>(*I), CC);
+}
+
+} // end anonymous namespace
+
+/// Diagnoses "dangerous" implicit conversions within the given
+/// expression (which is a full expression). Implements -Wconversion
+/// and -Wsign-compare.
+///
+/// \param CC the "context" location of the implicit conversion, i.e.
+/// the most location of the syntactic entity requiring the implicit
+/// conversion
+void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
+ // Don't diagnose in unevaluated contexts.
+ if (ExprEvalContexts.back().Context == Sema::Unevaluated)
+ return;
+
+ // Don't diagnose for value- or type-dependent expressions.
+ if (E->isTypeDependent() || E->isValueDependent())
+ return;
+
+ // This is not the right CC for (e.g.) a variable initialization.
+ AnalyzeImplicitConversions(*this, E, CC);
+}
+
+void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
+ FieldDecl *BitField,
+ Expr *Init) {
+ (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
+}
+
+/// CheckParmsForFunctionDef - Check that the parameters of the given
+/// function are appropriate for the definition of a function. This
+/// takes care of any checks that cannot be performed on the
+/// declaration itself, e.g., that the types of each of the function
+/// parameters are complete.
+bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
+ bool CheckParameterNames) {
+ bool HasInvalidParm = false;
+ for (; P != PEnd; ++P) {
+ ParmVarDecl *Param = *P;
+
+ // C99 6.7.5.3p4: the parameters in a parameter type list in a
+ // function declarator that is part of a function definition of
+ // that function shall not have incomplete type.
+ //
+ // This is also C++ [dcl.fct]p6.
+ if (!Param->isInvalidDecl() &&
+ RequireCompleteType(Param->getLocation(), Param->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Param->setInvalidDecl();
+ HasInvalidParm = true;
+ }
+
+ // C99 6.9.1p5: If the declarator includes a parameter type list, the
+ // declaration of each parameter shall include an identifier.
+ if (CheckParameterNames &&
+ Param->getIdentifier() == 0 &&
+ !Param->isImplicit() &&
+ !getLangOptions().CPlusPlus)
+ Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+
+ // C99 6.7.5.3p12:
+ // If the function declarator is not part of a definition of that
+ // function, parameters may have incomplete type and may use the [*]
+ // notation in their sequences of declarator specifiers to specify
+ // variable length array types.
+ QualType PType = Param->getOriginalType();
+ if (const ArrayType *AT = Context.getAsArrayType(PType)) {
+ if (AT->getSizeModifier() == ArrayType::Star) {
+ // FIXME: This diagnosic should point the the '[*]' if source-location
+ // information is added for it.
+ Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
+ }
+ }
+ }
+
+ return HasInvalidParm;
+}
+
+/// CheckCastAlign - Implements -Wcast-align, which warns when a
+/// pointer cast increases the alignment requirements.
+void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
+ // This is actually a lot of work to potentially be doing on every
+ // cast; don't do it if we're ignoring -Wcast_align (as is the default).
+ if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align,
+ TRange.getBegin())
+ == Diagnostic::Ignored)
+ return;
+
+ // Ignore dependent types.
+ if (T->isDependentType() || Op->getType()->isDependentType())
+ return;
+
+ // Require that the destination be a pointer type.
+ const PointerType *DestPtr = T->getAs<PointerType>();
+ if (!DestPtr) return;
+
+ // If the destination has alignment 1, we're done.
+ QualType DestPointee = DestPtr->getPointeeType();
+ if (DestPointee->isIncompleteType()) return;
+ CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee);
+ if (DestAlign.isOne()) return;
+
+ // Require that the source be a pointer type.
+ const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
+ if (!SrcPtr) return;
+ QualType SrcPointee = SrcPtr->getPointeeType();
+
+ // Whitelist casts from cv void*. We already implicitly
+ // whitelisted casts to cv void*, since they have alignment 1.
+ // Also whitelist casts involving incomplete types, which implicitly
+ // includes 'void'.
+ if (SrcPointee->isIncompleteType()) return;
+
+ CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+ if (SrcAlign >= DestAlign) return;
+
+ Diag(TRange.getBegin(), diag::warn_cast_align)
+ << Op->getType() << T
+ << static_cast<unsigned>(SrcAlign.getQuantity())
+ << static_cast<unsigned>(DestAlign.getQuantity())
+ << TRange << Op->getSourceRange();
+}
+
+void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
+ const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts();
+ const ConstantArrayType *ArrayTy =
+ Context.getAsConstantArrayType(BaseExpr->getType());
+ if (!ArrayTy)
+ return;
+
+ const Expr *IndexExpr = E->getIdx();
+ if (IndexExpr->isValueDependent())
+ return;
+ llvm::APSInt index;
+ if (!IndexExpr->isIntegerConstantExpr(index, Context))
+ return;
+
+ if (!index.isNegative()) {
+ llvm::APInt size = ArrayTy->getSize();
+ if (!size.isStrictlyPositive())
+ return;
+ if (size.getBitWidth() > index.getBitWidth())
+ index = index.sext(size.getBitWidth());
+ else if (size.getBitWidth() < index.getBitWidth())
+ size = size.sext(index.getBitWidth());
+
+ if (index.slt(size))
+ return;
+
+ Diag(E->getBase()->getLocStart(), diag::warn_array_index_exceeds_bounds)
+ << index.toString(10, true) << size.toString(10, true)
+ << IndexExpr->getSourceRange();
+ } else {
+ Diag(E->getBase()->getLocStart(), diag::warn_array_index_precedes_bounds)
+ << index.toString(10, true) << IndexExpr->getSourceRange();
+ }
+
+ const NamedDecl *ND = NULL;
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ ND = dyn_cast<NamedDecl>(DRE->getDecl());
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+ ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+ if (ND)
+ Diag(ND->getLocStart(), diag::note_array_index_out_of_bounds)
+ << ND->getDeclName();
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
new file mode 100644
index 0000000..bab665a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -0,0 +1,6522 @@
+//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the code-completion semantic actions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include <list>
+#include <map>
+#include <vector>
+
+using namespace clang;
+using namespace sema;
+
+namespace {
+ /// \brief A container of code-completion results.
+ class ResultBuilder {
+ public:
+ /// \brief The type of a name-lookup filter, which can be provided to the
+ /// name-lookup routines to specify which declarations should be included in
+ /// the result set (when it returns true) and which declarations should be
+ /// filtered out (returns false).
+ typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
+
+ typedef CodeCompletionResult Result;
+
+ private:
+ /// \brief The actual results we have found.
+ std::vector<Result> Results;
+
+ /// \brief A record of all of the declarations we have found and placed
+ /// into the result set, used to ensure that no declaration ever gets into
+ /// the result set twice.
+ llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
+
+ typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
+
+ /// \brief An entry in the shadow map, which is optimized to store
+ /// a single (declaration, index) mapping (the common case) but
+ /// can also store a list of (declaration, index) mappings.
+ class ShadowMapEntry {
+ typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
+
+ /// \brief Contains either the solitary NamedDecl * or a vector
+ /// of (declaration, index) pairs.
+ llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+
+ /// \brief When the entry contains a single declaration, this is
+ /// the index associated with that entry.
+ unsigned SingleDeclIndex;
+
+ public:
+ ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
+
+ void Add(NamedDecl *ND, unsigned Index) {
+ if (DeclOrVector.isNull()) {
+ // 0 - > 1 elements: just set the single element information.
+ DeclOrVector = ND;
+ SingleDeclIndex = Index;
+ return;
+ }
+
+ if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+ // 1 -> 2 elements: create the vector of results and push in the
+ // existing declaration.
+ DeclIndexPairVector *Vec = new DeclIndexPairVector;
+ Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
+ DeclOrVector = Vec;
+ }
+
+ // Add the new element to the end of the vector.
+ DeclOrVector.get<DeclIndexPairVector*>()->push_back(
+ DeclIndexPair(ND, Index));
+ }
+
+ void Destroy() {
+ if (DeclIndexPairVector *Vec
+ = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
+ delete Vec;
+ DeclOrVector = ((NamedDecl *)0);
+ }
+ }
+
+ // Iteration.
+ class iterator;
+ iterator begin() const;
+ iterator end() const;
+ };
+
+ /// \brief A mapping from declaration names to the declarations that have
+ /// this name within a particular scope and their index within the list of
+ /// results.
+ typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+
+ /// \brief The semantic analysis object for which results are being
+ /// produced.
+ Sema &SemaRef;
+
+ /// \brief The allocator used to allocate new code-completion strings.
+ CodeCompletionAllocator &Allocator;
+
+ /// \brief If non-NULL, a filter function used to remove any code-completion
+ /// results that are not desirable.
+ LookupFilter Filter;
+
+ /// \brief Whether we should allow declarations as
+ /// nested-name-specifiers that would otherwise be filtered out.
+ bool AllowNestedNameSpecifiers;
+
+ /// \brief If set, the type that we would prefer our resulting value
+ /// declarations to have.
+ ///
+ /// Closely matching the preferred type gives a boost to a result's
+ /// priority.
+ CanQualType PreferredType;
+
+ /// \brief A list of shadow maps, which is used to model name hiding at
+ /// different levels of, e.g., the inheritance hierarchy.
+ std::list<ShadowMap> ShadowMaps;
+
+ /// \brief If we're potentially referring to a C++ member function, the set
+ /// of qualifiers applied to the object type.
+ Qualifiers ObjectTypeQualifiers;
+
+ /// \brief Whether the \p ObjectTypeQualifiers field is active.
+ bool HasObjectTypeQualifiers;
+
+ /// \brief The selector that we prefer.
+ Selector PreferredSelector;
+
+ /// \brief The completion context in which we are gathering results.
+ CodeCompletionContext CompletionContext;
+
+ /// \brief If we are in an instance method definition, the @implementation
+ /// object.
+ ObjCImplementationDecl *ObjCImplementation;
+
+ void AdjustResultPriorityForDecl(Result &R);
+
+ void MaybeAddConstructorResults(Result R);
+
+ public:
+ explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
+ const CodeCompletionContext &CompletionContext,
+ LookupFilter Filter = 0)
+ : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
+ AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
+ CompletionContext(CompletionContext),
+ ObjCImplementation(0)
+ {
+ // If this is an Objective-C instance method definition, dig out the
+ // corresponding implementation.
+ switch (CompletionContext.getKind()) {
+ case CodeCompletionContext::CCC_Expression:
+ case CodeCompletionContext::CCC_ObjCMessageReceiver:
+ case CodeCompletionContext::CCC_ParenthesizedExpression:
+ case CodeCompletionContext::CCC_Statement:
+ case CodeCompletionContext::CCC_Recovery:
+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+ if (Method->isInstanceMethod())
+ if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
+ ObjCImplementation = Interface->getImplementation();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /// \brief Whether we should include code patterns in the completion
+ /// results.
+ bool includeCodePatterns() const {
+ return SemaRef.CodeCompleter &&
+ SemaRef.CodeCompleter->includeCodePatterns();
+ }
+
+ /// \brief Set the filter used for code-completion results.
+ void setFilter(LookupFilter Filter) {
+ this->Filter = Filter;
+ }
+
+ Result *data() { return Results.empty()? 0 : &Results.front(); }
+ unsigned size() const { return Results.size(); }
+ bool empty() const { return Results.empty(); }
+
+ /// \brief Specify the preferred type.
+ void setPreferredType(QualType T) {
+ PreferredType = SemaRef.Context.getCanonicalType(T);
+ }
+
+ /// \brief Set the cv-qualifiers on the object type, for us in filtering
+ /// calls to member functions.
+ ///
+ /// When there are qualifiers in this set, they will be used to filter
+ /// out member functions that aren't available (because there will be a
+ /// cv-qualifier mismatch) or prefer functions with an exact qualifier
+ /// match.
+ void setObjectTypeQualifiers(Qualifiers Quals) {
+ ObjectTypeQualifiers = Quals;
+ HasObjectTypeQualifiers = true;
+ }
+
+ /// \brief Set the preferred selector.
+ ///
+ /// When an Objective-C method declaration result is added, and that
+ /// method's selector matches this preferred selector, we give that method
+ /// a slight priority boost.
+ void setPreferredSelector(Selector Sel) {
+ PreferredSelector = Sel;
+ }
+
+ /// \brief Retrieve the code-completion context for which results are
+ /// being collected.
+ const CodeCompletionContext &getCompletionContext() const {
+ return CompletionContext;
+ }
+
+ /// \brief Specify whether nested-name-specifiers are allowed.
+ void allowNestedNameSpecifiers(bool Allow = true) {
+ AllowNestedNameSpecifiers = Allow;
+ }
+
+ /// \brief Return the semantic analysis object for which we are collecting
+ /// code completion results.
+ Sema &getSema() const { return SemaRef; }
+
+ /// \brief Retrieve the allocator used to allocate code completion strings.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ /// \brief Determine whether the given declaration is at all interesting
+ /// as a code-completion result.
+ ///
+ /// \param ND the declaration that we are inspecting.
+ ///
+ /// \param AsNestedNameSpecifier will be set true if this declaration is
+ /// only interesting when it is a nested-name-specifier.
+ bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
+
+ /// \brief Check whether the result is hidden by the Hiding declaration.
+ ///
+ /// \returns true if the result is hidden and cannot be found, false if
+ /// the hidden result could still be found. When false, \p R may be
+ /// modified to describe how the result can be found (e.g., via extra
+ /// qualification).
+ bool CheckHiddenResult(Result &R, DeclContext *CurContext,
+ NamedDecl *Hiding);
+
+ /// \brief Add a new result to this result set (if it isn't already in one
+ /// of the shadow maps), or replace an existing result (for, e.g., a
+ /// redeclaration).
+ ///
+ /// \param CurContext the result to add (if it is unique).
+ ///
+ /// \param R the context in which this result will be named.
+ void MaybeAddResult(Result R, DeclContext *CurContext = 0);
+
+ /// \brief Add a new result to this result set, where we already know
+ /// the hiding declation (if any).
+ ///
+ /// \param R the result to add (if it is unique).
+ ///
+ /// \param CurContext the context in which this result will be named.
+ ///
+ /// \param Hiding the declaration that hides the result.
+ ///
+ /// \param InBaseClass whether the result was found in a base
+ /// class of the searched context.
+ void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
+ bool InBaseClass);
+
+ /// \brief Add a new non-declaration result to this result set.
+ void AddResult(Result R);
+
+ /// \brief Enter into a new scope.
+ void EnterNewScope();
+
+ /// \brief Exit from the current scope.
+ void ExitScope();
+
+ /// \brief Ignore this declaration, if it is seen again.
+ void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
+
+ /// \name Name lookup predicates
+ ///
+ /// These predicates can be passed to the name lookup functions to filter the
+ /// results of name lookup. All of the predicates have the same type, so that
+ ///
+ //@{
+ bool IsOrdinaryName(NamedDecl *ND) const;
+ bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
+ bool IsIntegralConstantValue(NamedDecl *ND) const;
+ bool IsOrdinaryNonValueName(NamedDecl *ND) const;
+ bool IsNestedNameSpecifier(NamedDecl *ND) const;
+ bool IsEnum(NamedDecl *ND) const;
+ bool IsClassOrStruct(NamedDecl *ND) const;
+ bool IsUnion(NamedDecl *ND) const;
+ bool IsNamespace(NamedDecl *ND) const;
+ bool IsNamespaceOrAlias(NamedDecl *ND) const;
+ bool IsType(NamedDecl *ND) const;
+ bool IsMember(NamedDecl *ND) const;
+ bool IsObjCIvar(NamedDecl *ND) const;
+ bool IsObjCMessageReceiver(NamedDecl *ND) const;
+ bool IsObjCCollection(NamedDecl *ND) const;
+ bool IsImpossibleToSatisfy(NamedDecl *ND) const;
+ //@}
+ };
+}
+
+class ResultBuilder::ShadowMapEntry::iterator {
+ llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
+ unsigned SingleDeclIndex;
+
+public:
+ typedef DeclIndexPair value_type;
+ typedef value_type reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ class pointer {
+ DeclIndexPair Value;
+
+ public:
+ pointer(const DeclIndexPair &Value) : Value(Value) { }
+
+ const DeclIndexPair *operator->() const {
+ return &Value;
+ }
+ };
+
+ iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+ iterator(NamedDecl *SingleDecl, unsigned Index)
+ : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
+
+ iterator(const DeclIndexPair *Iterator)
+ : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
+
+ iterator &operator++() {
+ if (DeclOrIterator.is<NamedDecl *>()) {
+ DeclOrIterator = (NamedDecl *)0;
+ SingleDeclIndex = 0;
+ return *this;
+ }
+
+ const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
+ ++I;
+ DeclOrIterator = I;
+ return *this;
+ }
+
+ /*iterator operator++(int) {
+ iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }*/
+
+ reference operator*() const {
+ if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
+ return reference(ND, SingleDeclIndex);
+
+ return *DeclOrIterator.get<const DeclIndexPair*>();
+ }
+
+ pointer operator->() const {
+ return pointer(**this);
+ }
+
+ friend bool operator==(const iterator &X, const iterator &Y) {
+ return X.DeclOrIterator.getOpaqueValue()
+ == Y.DeclOrIterator.getOpaqueValue() &&
+ X.SingleDeclIndex == Y.SingleDeclIndex;
+ }
+
+ friend bool operator!=(const iterator &X, const iterator &Y) {
+ return !(X == Y);
+ }
+};
+
+ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::begin() const {
+ if (DeclOrVector.isNull())
+ return iterator();
+
+ if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
+ return iterator(ND, SingleDeclIndex);
+
+ return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
+}
+
+ResultBuilder::ShadowMapEntry::iterator
+ResultBuilder::ShadowMapEntry::end() const {
+ if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
+ return iterator();
+
+ return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
+}
+
+/// \brief Compute the qualification required to get from the current context
+/// (\p CurContext) to the target context (\p TargetContext).
+///
+/// \param Context the AST context in which the qualification will be used.
+///
+/// \param CurContext the context where an entity is being named, which is
+/// typically based on the current scope.
+///
+/// \param TargetContext the context in which the named entity actually
+/// resides.
+///
+/// \returns a nested name specifier that refers into the target context, or
+/// NULL if no qualification is needed.
+static NestedNameSpecifier *
+getRequiredQualification(ASTContext &Context,
+ DeclContext *CurContext,
+ DeclContext *TargetContext) {
+ llvm::SmallVector<DeclContext *, 4> TargetParents;
+
+ for (DeclContext *CommonAncestor = TargetContext;
+ CommonAncestor && !CommonAncestor->Encloses(CurContext);
+ CommonAncestor = CommonAncestor->getLookupParent()) {
+ if (CommonAncestor->isTransparentContext() ||
+ CommonAncestor->isFunctionOrMethod())
+ continue;
+
+ TargetParents.push_back(CommonAncestor);
+ }
+
+ NestedNameSpecifier *Result = 0;
+ while (!TargetParents.empty()) {
+ DeclContext *Parent = TargetParents.back();
+ TargetParents.pop_back();
+
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+ if (!Namespace->getIdentifier())
+ continue;
+
+ Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+ }
+ else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
+ Result = NestedNameSpecifier::Create(Context, Result,
+ false,
+ Context.getTypeDeclType(TD).getTypePtr());
+ }
+ return Result;
+}
+
+bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
+ bool &AsNestedNameSpecifier) const {
+ AsNestedNameSpecifier = false;
+
+ ND = ND->getUnderlyingDecl();
+ unsigned IDNS = ND->getIdentifierNamespace();
+
+ // Skip unnamed entities.
+ if (!ND->getDeclName())
+ return false;
+
+ // Friend declarations and declarations introduced due to friends are never
+ // added as results.
+ if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
+ return false;
+
+ // Class template (partial) specializations are never added as results.
+ if (isa<ClassTemplateSpecializationDecl>(ND) ||
+ isa<ClassTemplatePartialSpecializationDecl>(ND))
+ return false;
+
+ // Using declarations themselves are never added as results.
+ if (isa<UsingDecl>(ND))
+ return false;
+
+ // Some declarations have reserved names that we don't want to ever show.
+ if (const IdentifierInfo *Id = ND->getIdentifier()) {
+ // __va_list_tag is a freak of nature. Find it and skip it.
+ if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
+ return false;
+
+ // Filter out names reserved for the implementation (C99 7.1.3,
+ // C++ [lib.global.names]) if they come from a system header.
+ //
+ // FIXME: Add predicate for this.
+ if (Id->getLength() >= 2) {
+ const char *Name = Id->getNameStart();
+ if (Name[0] == '_' &&
+ (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
+ (ND->getLocation().isInvalid() ||
+ SemaRef.SourceMgr.isInSystemHeader(
+ SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
+ return false;
+ }
+ }
+
+ // Skip out-of-line declarations and definitions.
+ // NOTE: Unless it's an Objective-C property, method, or ivar, where
+ // the contexts can be messy.
+ if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
+ !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
+ isa<ObjCMethodDecl>(ND)))
+ return false;
+
+ if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
+ ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+ Filter != &ResultBuilder::IsNamespace &&
+ Filter != &ResultBuilder::IsNamespaceOrAlias &&
+ Filter != 0))
+ AsNestedNameSpecifier = true;
+
+ // Filter out any unwanted results.
+ if (Filter && !(this->*Filter)(ND)) {
+ // Check whether it is interesting as a nested-name-specifier.
+ if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
+ IsNestedNameSpecifier(ND) &&
+ (Filter != &ResultBuilder::IsMember ||
+ (isa<CXXRecordDecl>(ND) &&
+ cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
+ AsNestedNameSpecifier = true;
+ return true;
+ }
+
+ return false;
+ }
+ // ... then it must be interesting!
+ return true;
+}
+
+bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
+ NamedDecl *Hiding) {
+ // In C, there is no way to refer to a hidden name.
+ // FIXME: This isn't true; we can find a tag name hidden by an ordinary
+ // name if we introduce the tag type.
+ if (!SemaRef.getLangOptions().CPlusPlus)
+ return true;
+
+ DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
+
+ // There is no way to qualify a name declared in a function or method.
+ if (HiddenCtx->isFunctionOrMethod())
+ return true;
+
+ if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
+ return true;
+
+ // We can refer to the result with the appropriate qualification. Do it.
+ R.Hidden = true;
+ R.QualifierIsInformative = false;
+
+ if (!R.Qualifier)
+ R.Qualifier = getRequiredQualification(SemaRef.Context,
+ CurContext,
+ R.Declaration->getDeclContext());
+ return false;
+}
+
+/// \brief A simplified classification of types used to determine whether two
+/// types are "similar enough" when adjusting priorities.
+SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
+ switch (T->getTypeClass()) {
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ case BuiltinType::Void:
+ return STC_Void;
+
+ case BuiltinType::NullPtr:
+ return STC_Pointer;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ return STC_Other;
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return STC_ObjectiveC;
+
+ default:
+ return STC_Arithmetic;
+ }
+ return STC_Other;
+
+ case Type::Complex:
+ return STC_Arithmetic;
+
+ case Type::Pointer:
+ return STC_Pointer;
+
+ case Type::BlockPointer:
+ return STC_Block;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ return STC_Array;
+
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ return STC_Arithmetic;
+
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ return STC_Function;
+
+ case Type::Record:
+ return STC_Record;
+
+ case Type::Enum:
+ return STC_Arithmetic;
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ return STC_ObjectiveC;
+
+ default:
+ return STC_Other;
+ }
+}
+
+/// \brief Get the type that a given expression will have if this declaration
+/// is used as an expression in its "typical" code-completion form.
+QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ return C.getTypeDeclType(Type);
+ if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+ return C.getObjCInterfaceType(Iface);
+
+ QualType T;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ T = Function->getCallResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ T = Method->getSendResultType();
+ else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ T = FunTmpl->getTemplatedDecl()->getCallResultType();
+ else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+ else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ T = Property->getType();
+ else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ T = Value->getType();
+ else
+ return QualType();
+
+ return T.getNonReferenceType();
+}
+
+void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
+ // If this is an Objective-C method declaration whose selector matches our
+ // preferred selector, give it a priority boost.
+ if (!PreferredSelector.isNull())
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+ if (PreferredSelector == Method->getSelector())
+ R.Priority += CCD_SelectorMatch;
+
+ // If we have a preferred type, adjust the priority for results with exactly-
+ // matching or nearly-matching types.
+ if (!PreferredType.isNull()) {
+ QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
+ if (!T.isNull()) {
+ CanQualType TC = SemaRef.Context.getCanonicalType(T);
+ // Check for exactly-matching types (modulo qualifiers).
+ if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
+ R.Priority /= CCF_ExactTypeMatch;
+ // Check for nearly-matching types, based on classification of each.
+ else if ((getSimplifiedTypeClass(PreferredType)
+ == getSimplifiedTypeClass(TC)) &&
+ !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
+ R.Priority /= CCF_SimilarTypeMatch;
+ }
+ }
+}
+
+void ResultBuilder::MaybeAddConstructorResults(Result R) {
+ if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
+ !CompletionContext.wantConstructorResults())
+ return;
+
+ ASTContext &Context = SemaRef.Context;
+ NamedDecl *D = R.Declaration;
+ CXXRecordDecl *Record = 0;
+ if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
+ Record = ClassTemplate->getTemplatedDecl();
+ else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
+ // Skip specializations and partial specializations.
+ if (isa<ClassTemplateSpecializationDecl>(Record))
+ return;
+ } else {
+ // There are no constructors here.
+ return;
+ }
+
+ Record = Record->getDefinition();
+ if (!Record)
+ return;
+
+
+ QualType RecordTy = Context.getTypeDeclType(Record);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(RecordTy));
+ for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
+ Ctors.first != Ctors.second; ++Ctors.first) {
+ R.Declaration = *Ctors.first;
+ R.CursorKind = getCursorKindForDecl(R.Declaration);
+ Results.push_back(R);
+ }
+}
+
+void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
+ assert(!ShadowMaps.empty() && "Must enter into a results scope");
+
+ if (R.Kind != Result::RK_Declaration) {
+ // For non-declaration results, just add the result.
+ Results.push_back(R);
+ return;
+ }
+
+ // Look through using declarations.
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
+ return;
+ }
+
+ Decl *CanonDecl = R.Declaration->getCanonicalDecl();
+ unsigned IDNS = CanonDecl->getIdentifierNamespace();
+
+ bool AsNestedNameSpecifier = false;
+ if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+ return;
+
+ // C++ constructors are never found by name lookup.
+ if (isa<CXXConstructorDecl>(R.Declaration))
+ return;
+
+ ShadowMap &SMap = ShadowMaps.back();
+ ShadowMapEntry::iterator I, IEnd;
+ ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
+ if (NamePos != SMap.end()) {
+ I = NamePos->second.begin();
+ IEnd = NamePos->second.end();
+ }
+
+ for (; I != IEnd; ++I) {
+ NamedDecl *ND = I->first;
+ unsigned Index = I->second;
+ if (ND->getCanonicalDecl() == CanonDecl) {
+ // This is a redeclaration. Always pick the newer declaration.
+ Results[Index].Declaration = R.Declaration;
+
+ // We're done.
+ return;
+ }
+ }
+
+ // This is a new declaration in this scope. However, check whether this
+ // declaration name is hidden by a similarly-named declaration in an outer
+ // scope.
+ std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
+ --SMEnd;
+ for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
+ ShadowMapEntry::iterator I, IEnd;
+ ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
+ if (NamePos != SM->end()) {
+ I = NamePos->second.begin();
+ IEnd = NamePos->second.end();
+ }
+ for (; I != IEnd; ++I) {
+ // A tag declaration does not hide a non-tag declaration.
+ if (I->first->hasTagIdentifierNamespace() &&
+ (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
+ Decl::IDNS_ObjCProtocol)))
+ continue;
+
+ // Protocols are in distinct namespaces from everything else.
+ if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+ || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+ I->first->getIdentifierNamespace() != IDNS)
+ continue;
+
+ // The newly-added result is hidden by an entry in the shadow map.
+ if (CheckHiddenResult(R, CurContext, I->first))
+ return;
+
+ break;
+ }
+ }
+
+ // Make sure that any given declaration only shows up in the result set once.
+ if (!AllDeclsFound.insert(CanonDecl))
+ return;
+
+ // If the filter is for nested-name-specifiers, then this result starts a
+ // nested-name-specifier.
+ if (AsNestedNameSpecifier) {
+ R.StartsNestedNameSpecifier = true;
+ R.Priority = CCP_NestedNameSpecifier;
+ } else
+ AdjustResultPriorityForDecl(R);
+
+ // If this result is supposed to have an informative qualifier, add one.
+ if (R.QualifierIsInformative && !R.Qualifier &&
+ !R.StartsNestedNameSpecifier) {
+ DeclContext *Ctx = R.Declaration->getDeclContext();
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ else
+ R.QualifierIsInformative = false;
+ }
+
+ // Insert this result into the set of results and into the current shadow
+ // map.
+ SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
+ Results.push_back(R);
+
+ if (!AsNestedNameSpecifier)
+ MaybeAddConstructorResults(R);
+}
+
+void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
+ NamedDecl *Hiding, bool InBaseClass = false) {
+ if (R.Kind != Result::RK_Declaration) {
+ // For non-declaration results, just add the result.
+ Results.push_back(R);
+ return;
+ }
+
+ // Look through using declarations.
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
+ AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
+ return;
+ }
+
+ bool AsNestedNameSpecifier = false;
+ if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
+ return;
+
+ // C++ constructors are never found by name lookup.
+ if (isa<CXXConstructorDecl>(R.Declaration))
+ return;
+
+ if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
+ return;
+
+ // Make sure that any given declaration only shows up in the result set once.
+ if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
+ return;
+
+ // If the filter is for nested-name-specifiers, then this result starts a
+ // nested-name-specifier.
+ if (AsNestedNameSpecifier) {
+ R.StartsNestedNameSpecifier = true;
+ R.Priority = CCP_NestedNameSpecifier;
+ }
+ else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
+ isa<CXXRecordDecl>(R.Declaration->getDeclContext()
+ ->getRedeclContext()))
+ R.QualifierIsInformative = true;
+
+ // If this result is supposed to have an informative qualifier, add one.
+ if (R.QualifierIsInformative && !R.Qualifier &&
+ !R.StartsNestedNameSpecifier) {
+ DeclContext *Ctx = R.Declaration->getDeclContext();
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
+ else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
+ R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ else
+ R.QualifierIsInformative = false;
+ }
+
+ // Adjust the priority if this result comes from a base class.
+ if (InBaseClass)
+ R.Priority += CCD_InBaseClass;
+
+ AdjustResultPriorityForDecl(R);
+
+ if (HasObjectTypeQualifiers)
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+ if (Method->isInstance()) {
+ Qualifiers MethodQuals
+ = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+ if (ObjectTypeQualifiers == MethodQuals)
+ R.Priority += CCD_ObjectQualifierMatch;
+ else if (ObjectTypeQualifiers - MethodQuals) {
+ // The method cannot be invoked, because doing so would drop
+ // qualifiers.
+ return;
+ }
+ }
+
+ // Insert this result into the set of results.
+ Results.push_back(R);
+
+ if (!AsNestedNameSpecifier)
+ MaybeAddConstructorResults(R);
+}
+
+void ResultBuilder::AddResult(Result R) {
+ assert(R.Kind != Result::RK_Declaration &&
+ "Declaration results need more context");
+ Results.push_back(R);
+}
+
+/// \brief Enter into a new scope.
+void ResultBuilder::EnterNewScope() {
+ ShadowMaps.push_back(ShadowMap());
+}
+
+/// \brief Exit from the current scope.
+void ResultBuilder::ExitScope() {
+ for (ShadowMap::iterator E = ShadowMaps.back().begin(),
+ EEnd = ShadowMaps.back().end();
+ E != EEnd;
+ ++E)
+ E->second.Destroy();
+
+ ShadowMaps.pop_back();
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ if (SemaRef.getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
+ else if (SemaRef.getLangOptions().ObjC1) {
+ if (isa<ObjCIvarDecl>(ND))
+ return true;
+ if (isa<ObjCPropertyDecl>(ND) &&
+ SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
+ return true;
+ }
+
+ return ND->getIdentifierNamespace() & IDNS;
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup but is not a type name.
+bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+ return false;
+
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ if (SemaRef.getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
+ else if (SemaRef.getLangOptions().ObjC1) {
+ if (isa<ObjCIvarDecl>(ND))
+ return true;
+ if (isa<ObjCPropertyDecl>(ND) &&
+ SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
+ return true;
+ }
+
+ return ND->getIdentifierNamespace() & IDNS;
+}
+
+bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
+ if (!IsOrdinaryNonTypeName(ND))
+ return 0;
+
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
+ if (VD->getType()->isIntegralOrEnumerationType())
+ return true;
+
+ return false;
+}
+
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ if (SemaRef.getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
+
+ return (ND->getIdentifierNamespace() & IDNS) &&
+ !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
+ !isa<ObjCPropertyDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is suitable as the
+/// start of a C++ nested-name-specifier, e.g., a class or namespace.
+bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
+ // Allow us to find class templates, too.
+ if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ ND = ClassTemplate->getTemplatedDecl();
+
+ return SemaRef.isAcceptableNestedNameSpecifier(ND);
+}
+
+/// \brief Determines whether the given declaration is an enumeration.
+bool ResultBuilder::IsEnum(NamedDecl *ND) const {
+ return isa<EnumDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a class or struct.
+bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
+ // Allow us to find class templates, too.
+ if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ ND = ClassTemplate->getTemplatedDecl();
+
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+ return RD->getTagKind() == TTK_Class ||
+ RD->getTagKind() == TTK_Struct;
+
+ return false;
+}
+
+/// \brief Determines whether the given declaration is a union.
+bool ResultBuilder::IsUnion(NamedDecl *ND) const {
+ // Allow us to find class templates, too.
+ if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
+ ND = ClassTemplate->getTemplatedDecl();
+
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
+ return RD->getTagKind() == TTK_Union;
+
+ return false;
+}
+
+/// \brief Determines whether the given declaration is a namespace.
+bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
+ return isa<NamespaceDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a namespace or
+/// namespace alias.
+bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
+ return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+}
+
+/// \brief Determines whether the given declaration is a type.
+bool ResultBuilder::IsType(NamedDecl *ND) const {
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+ ND = Using->getTargetDecl();
+
+ return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+}
+
+/// \brief Determines which members of a class should be visible via
+/// "." or "->". Only value declarations, nested name specifiers, and
+/// using declarations thereof should show up.
+bool ResultBuilder::IsMember(NamedDecl *ND) const {
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+ ND = Using->getTargetDecl();
+
+ return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
+ isa<ObjCPropertyDecl>(ND);
+}
+
+static bool isObjCReceiverType(ASTContext &C, QualType T) {
+ T = C.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ return true;
+
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+
+ default:
+ break;
+ }
+
+ if (!C.getLangOptions().CPlusPlus)
+ return false;
+
+ // FIXME: We could perform more analysis here to determine whether a
+ // particular class type has any conversions to Objective-C types. For now,
+ // just accept all class types.
+ return T->isDependentType() || T->isRecordType();
+}
+
+bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return isObjCReceiverType(SemaRef.Context, T);
+}
+
+bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+ if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
+ (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
+ return false;
+
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
+ T->isObjCIdType() ||
+ (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
+}
+
+bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
+ return false;
+}
+
+/// \rief Determines whether the given declaration is an Objective-C
+/// instance variable.
+bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
+ return isa<ObjCIvarDecl>(ND);
+}
+
+namespace {
+ /// \brief Visible declaration consumer that adds a code-completion result
+ /// for each visible declaration.
+ class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
+ ResultBuilder &Results;
+ DeclContext *CurContext;
+
+ public:
+ CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
+ : Results(Results), CurContext(CurContext) { }
+
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
+ Results.AddResult(ND, CurContext, Hiding, InBaseClass);
+ }
+ };
+}
+
+/// \brief Add type specifiers for the current language as keyword results.
+static void AddTypeSpecifierResults(const LangOptions &LangOpts,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+ Results.AddResult(Result("short", CCP_Type));
+ Results.AddResult(Result("long", CCP_Type));
+ Results.AddResult(Result("signed", CCP_Type));
+ Results.AddResult(Result("unsigned", CCP_Type));
+ Results.AddResult(Result("void", CCP_Type));
+ Results.AddResult(Result("char", CCP_Type));
+ Results.AddResult(Result("int", CCP_Type));
+ Results.AddResult(Result("float", CCP_Type));
+ Results.AddResult(Result("double", CCP_Type));
+ Results.AddResult(Result("enum", CCP_Type));
+ Results.AddResult(Result("struct", CCP_Type));
+ Results.AddResult(Result("union", CCP_Type));
+ Results.AddResult(Result("const", CCP_Type));
+ Results.AddResult(Result("volatile", CCP_Type));
+
+ if (LangOpts.C99) {
+ // C99-specific
+ Results.AddResult(Result("_Complex", CCP_Type));
+ Results.AddResult(Result("_Imaginary", CCP_Type));
+ Results.AddResult(Result("_Bool", CCP_Type));
+ Results.AddResult(Result("restrict", CCP_Type));
+ }
+
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ if (LangOpts.CPlusPlus) {
+ // C++-specific
+ Results.AddResult(Result("bool", CCP_Type +
+ (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
+ Results.AddResult(Result("class", CCP_Type));
+ Results.AddResult(Result("wchar_t", CCP_Type));
+
+ // typename qualified-id
+ Builder.AddTypedTextChunk("typename");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ if (LangOpts.CPlusPlus0x) {
+ Results.AddResult(Result("auto", CCP_Type));
+ Results.AddResult(Result("char16_t", CCP_Type));
+ Results.AddResult(Result("char32_t", CCP_Type));
+
+ Builder.AddTypedTextChunk("decltype");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+ }
+
+ // GNU extensions
+ if (LangOpts.GNUMode) {
+ // FIXME: Enable when we actually support decimal floating point.
+ // Results.AddResult(Result("_Decimal32"));
+ // Results.AddResult(Result("_Decimal64"));
+ // Results.AddResult(Result("_Decimal128"));
+
+ Builder.AddTypedTextChunk("typeof");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ Builder.AddTypedTextChunk("typeof");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+}
+
+static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
+ const LangOptions &LangOpts,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+ // Note: we don't suggest either "auto" or "register", because both
+ // are pointless as storage specifiers. Elsewhere, we suggest "auto"
+ // in C++0x as a type specifier.
+ Results.AddResult(Result("extern"));
+ Results.AddResult(Result("static"));
+}
+
+static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
+ const LangOptions &LangOpts,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+ switch (CCC) {
+ case Sema::PCC_Class:
+ case Sema::PCC_MemberTemplate:
+ if (LangOpts.CPlusPlus) {
+ Results.AddResult(Result("explicit"));
+ Results.AddResult(Result("friend"));
+ Results.AddResult(Result("mutable"));
+ Results.AddResult(Result("virtual"));
+ }
+ // Fall through
+
+ case Sema::PCC_ObjCInterface:
+ case Sema::PCC_ObjCImplementation:
+ case Sema::PCC_Namespace:
+ case Sema::PCC_Template:
+ if (LangOpts.CPlusPlus || LangOpts.C99)
+ Results.AddResult(Result("inline"));
+ break;
+
+ case Sema::PCC_ObjCInstanceVariableList:
+ case Sema::PCC_Expression:
+ case Sema::PCC_Statement:
+ case Sema::PCC_ForInit:
+ case Sema::PCC_Condition:
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Type:
+ case Sema::PCC_ParenthesizedExpression:
+ case Sema::PCC_LocalDeclarationSpecifiers:
+ break;
+ }
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt);
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt);
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt);
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
+
+static void AddTypedefResult(ResultBuilder &Results) {
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Builder.AddTypedTextChunk("typedef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+}
+
+static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
+ const LangOptions &LangOpts) {
+ switch (CCC) {
+ case Sema::PCC_Namespace:
+ case Sema::PCC_Class:
+ case Sema::PCC_ObjCInstanceVariableList:
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
+ case Sema::PCC_Statement:
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Type:
+ case Sema::PCC_ParenthesizedExpression:
+ case Sema::PCC_LocalDeclarationSpecifiers:
+ return true;
+
+ case Sema::PCC_Expression:
+ case Sema::PCC_Condition:
+ return LangOpts.CPlusPlus;
+
+ case Sema::PCC_ObjCInterface:
+ case Sema::PCC_ObjCImplementation:
+ return false;
+
+ case Sema::PCC_ForInit:
+ return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
+ }
+
+ return false;
+}
+
+/// \brief Add language constructs that show up for "ordinary" names.
+static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
+ Scope *S,
+ Sema &SemaRef,
+ ResultBuilder &Results) {
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ typedef CodeCompletionResult Result;
+ switch (CCC) {
+ case Sema::PCC_Namespace:
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ if (Results.includeCodePatterns()) {
+ // namespace <identifier> { declarations }
+ Builder.AddTypedTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("identifier");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("declarations");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // namespace identifier = identifier ;
+ Builder.AddTypedTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("name");
+ Builder.AddChunk(CodeCompletionString::CK_Equal);
+ Builder.AddPlaceholderChunk("namespace");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // Using directives
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("identifier");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // asm(string-literal)
+ Builder.AddTypedTextChunk("asm");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("string-literal");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ if (Results.includeCodePatterns()) {
+ // Explicit template instantiation
+ Builder.AddTypedTextChunk("template");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("declaration");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+ }
+
+ if (SemaRef.getLangOptions().ObjC1)
+ AddObjCTopLevelResults(Results, true);
+
+ AddTypedefResult(Results);
+ // Fall through
+
+ case Sema::PCC_Class:
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ // Using declaration
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // using typename qualifier::name (only in a dependent context)
+ if (SemaRef.CurContext->isDependentContext()) {
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("typename");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ if (CCC == Sema::PCC_Class) {
+ AddTypedefResult(Results);
+
+ // public:
+ Builder.AddTypedTextChunk("public");
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // protected:
+ Builder.AddTypedTextChunk("protected");
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // private:
+ Builder.AddTypedTextChunk("private");
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+ }
+ // Fall through
+
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
+ if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
+ // template < parameters >
+ Builder.AddTypedTextChunk("template");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("parameters");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ break;
+
+ case Sema::PCC_ObjCInterface:
+ AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
+ AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ break;
+
+ case Sema::PCC_ObjCImplementation:
+ AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
+ AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ break;
+
+ case Sema::PCC_ObjCInstanceVariableList:
+ AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
+ break;
+
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Statement: {
+ AddTypedefResult(Results);
+
+ if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
+ Builder.AddTypedTextChunk("try");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Builder.AddTextChunk("catch");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("declaration");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+ if (SemaRef.getLangOptions().ObjC1)
+ AddObjCStatementResults(Results, true);
+
+ if (Results.includeCodePatterns()) {
+ // if (condition) { statements }
+ Builder.AddTypedTextChunk("if");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (SemaRef.getLangOptions().CPlusPlus)
+ Builder.AddPlaceholderChunk("condition");
+ else
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // switch (condition) { }
+ Builder.AddTypedTextChunk("switch");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (SemaRef.getLangOptions().CPlusPlus)
+ Builder.AddPlaceholderChunk("condition");
+ else
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // Switch-specific statements.
+ if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
+ // case expression:
+ Builder.AddTypedTextChunk("case");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // default:
+ Builder.AddTypedTextChunk("default");
+ Builder.AddChunk(CodeCompletionString::CK_Colon);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ if (Results.includeCodePatterns()) {
+ /// while (condition) { statements }
+ Builder.AddTypedTextChunk("while");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (SemaRef.getLangOptions().CPlusPlus)
+ Builder.AddPlaceholderChunk("condition");
+ else
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // do { statements } while ( expression );
+ Builder.AddTypedTextChunk("do");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Builder.AddTextChunk("while");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // for ( for-init-statement ; condition ; expression ) { statements }
+ Builder.AddTypedTextChunk("for");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
+ Builder.AddPlaceholderChunk("init-statement");
+ else
+ Builder.AddPlaceholderChunk("init-expression");
+ Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+ Builder.AddPlaceholderChunk("condition");
+ Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+ Builder.AddPlaceholderChunk("inc-expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ if (S->getContinueParent()) {
+ // continue ;
+ Builder.AddTypedTextChunk("continue");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ if (S->getBreakParent()) {
+ // break ;
+ Builder.AddTypedTextChunk("break");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // "return expression ;" or "return ;", depending on whether we
+ // know the function is void or not.
+ bool isVoid = false;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
+ isVoid = Function->getResultType()->isVoidType();
+ else if (ObjCMethodDecl *Method
+ = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
+ isVoid = Method->getResultType()->isVoidType();
+ else if (SemaRef.getCurBlock() &&
+ !SemaRef.getCurBlock()->ReturnType.isNull())
+ isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
+ Builder.AddTypedTextChunk("return");
+ if (!isVoid) {
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ }
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // goto identifier ;
+ Builder.AddTypedTextChunk("goto");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("label");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // Using directives
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("identifier");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // Fall through (for statement expressions).
+ case Sema::PCC_ForInit:
+ case Sema::PCC_Condition:
+ AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
+ // Fall through: conditions and statements can have expressions.
+
+ case Sema::PCC_ParenthesizedExpression:
+ case Sema::PCC_Expression: {
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ // 'this', if we're in a non-static member function.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
+ if (!Method->isStatic())
+ Results.AddResult(Result("this"));
+
+ // true, false
+ Results.AddResult(Result("true"));
+ Results.AddResult(Result("false"));
+
+ // dynamic_cast < type-id > ( expression )
+ Builder.AddTypedTextChunk("dynamic_cast");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // static_cast < type-id > ( expression )
+ Builder.AddTypedTextChunk("static_cast");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // reinterpret_cast < type-id > ( expression )
+ Builder.AddTypedTextChunk("reinterpret_cast");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // const_cast < type-id > ( expression )
+ Builder.AddTypedTextChunk("const_cast");
+ Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightAngle);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // typeid ( expression-or-type )
+ Builder.AddTypedTextChunk("typeid");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression-or-type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // new T ( ... )
+ Builder.AddTypedTextChunk("new");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expressions");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // new T [ ] ( ... )
+ Builder.AddTypedTextChunk("new");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
+ Builder.AddPlaceholderChunk("size");
+ Builder.AddChunk(CodeCompletionString::CK_RightBracket);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expressions");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // delete expression
+ Builder.AddTypedTextChunk("delete");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // delete [] expression
+ Builder.AddTypedTextChunk("delete");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
+ Builder.AddChunk(CodeCompletionString::CK_RightBracket);
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // throw expression
+ Builder.AddTypedTextChunk("throw");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // FIXME: Rethrow?
+ }
+
+ if (SemaRef.getLangOptions().ObjC1) {
+ // Add "super", if we're in an Objective-C class with a superclass.
+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
+ // The interface can be NULL.
+ if (ObjCInterfaceDecl *ID = Method->getClassInterface())
+ if (ID->getSuperClass())
+ Results.AddResult(Result("super"));
+ }
+
+ AddObjCExpressionResults(Results, true);
+ }
+
+ // sizeof expression
+ Builder.AddTypedTextChunk("sizeof");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression-or-type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+ break;
+ }
+
+ case Sema::PCC_Type:
+ case Sema::PCC_LocalDeclarationSpecifiers:
+ break;
+ }
+
+ if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
+ AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
+
+ if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
+ Results.AddResult(Result("operator"));
+}
+
+/// \brief Retrieve the string representation of the given type as a string
+/// that has the appropriate lifetime for code completion.
+///
+/// This routine provides a fast path where we provide constant strings for
+/// common type names.
+const char *GetCompletionTypeString(QualType T,
+ ASTContext &Context,
+ CodeCompletionAllocator &Allocator) {
+ PrintingPolicy Policy(Context.PrintingPolicy);
+ Policy.AnonymousTagLocations = false;
+
+ if (!T.getLocalQualifiers()) {
+ // Built-in type names are constant strings.
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
+ return BT->getName(Context.getLangOptions());
+
+ // Anonymous tag types are constant strings.
+ if (const TagType *TagT = dyn_cast<TagType>(T))
+ if (TagDecl *Tag = TagT->getDecl())
+ if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
+ switch (Tag->getTagKind()) {
+ case TTK_Struct: return "struct <anonymous>";
+ case TTK_Class: return "class <anonymous>";
+ case TTK_Union: return "union <anonymous>";
+ case TTK_Enum: return "enum <anonymous>";
+ }
+ }
+ }
+
+ // Slow path: format the type as a string.
+ std::string Result;
+ T.getAsStringInternal(Result, Policy);
+ return Allocator.CopyString(Result);
+}
+
+/// \brief If the given declaration has an associated type, add it as a result
+/// type chunk.
+static void AddResultTypeChunk(ASTContext &Context,
+ NamedDecl *ND,
+ CodeCompletionBuilder &Result) {
+ if (!ND)
+ return;
+
+ // Skip constructors and conversion functions, which have their return types
+ // built into their names.
+ if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
+ return;
+
+ // Determine the type of the declaration (if it has a type).
+ QualType T;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ T = Function->getResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ T = Method->getResultType();
+ else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ T = FunTmpl->getTemplatedDecl()->getResultType();
+ else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
+ else if (isa<UnresolvedUsingValueDecl>(ND)) {
+ /* Do nothing: ignore unresolved using declarations*/
+ } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ T = Value->getType();
+ else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ T = Property->getType();
+
+ if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
+ return;
+
+ Result.AddResultTypeChunk(GetCompletionTypeString(T, Context,
+ Result.getAllocator()));
+}
+
+static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
+ CodeCompletionBuilder &Result) {
+ if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
+ if (Sentinel->getSentinel() == 0) {
+ if (Context.getLangOptions().ObjC1 &&
+ Context.Idents.get("nil").hasMacroDefinition())
+ Result.AddTextChunk(", nil");
+ else if (Context.Idents.get("NULL").hasMacroDefinition())
+ Result.AddTextChunk(", NULL");
+ else
+ Result.AddTextChunk(", (void*)0");
+ }
+}
+
+static std::string FormatFunctionParameter(ASTContext &Context,
+ ParmVarDecl *Param,
+ bool SuppressName = false) {
+ bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
+ if (Param->getType()->isDependentType() ||
+ !Param->getType()->isBlockPointerType()) {
+ // The argument for a dependent or non-block parameter is a placeholder
+ // containing that parameter's type.
+ std::string Result;
+
+ if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
+ Result = Param->getIdentifier()->getName();
+
+ Param->getType().getAsStringInternal(Result,
+ Context.PrintingPolicy);
+
+ if (ObjCMethodParam) {
+ Result = "(" + Result;
+ Result += ")";
+ if (Param->getIdentifier() && !SuppressName)
+ Result += Param->getIdentifier()->getName();
+ }
+ return Result;
+ }
+
+ // The argument for a block pointer parameter is a block literal with
+ // the appropriate type.
+ FunctionTypeLoc *Block = 0;
+ FunctionProtoTypeLoc *BlockProto = 0;
+ TypeLoc TL;
+ if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
+ TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+ while (true) {
+ // Look through typedefs.
+ if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
+ if (TypeSourceInfo *InnerTSInfo
+ = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
+ TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ }
+
+ // Look through qualified types
+ if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+ TL = QualifiedTL->getUnqualifiedLoc();
+ continue;
+ }
+
+ // Try to get the function prototype behind the block pointer type,
+ // then we're done.
+ if (BlockPointerTypeLoc *BlockPtr
+ = dyn_cast<BlockPointerTypeLoc>(&TL)) {
+ TL = BlockPtr->getPointeeLoc().IgnoreParens();
+ Block = dyn_cast<FunctionTypeLoc>(&TL);
+ BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ }
+ break;
+ }
+ }
+
+ if (!Block) {
+ // We were unable to find a FunctionProtoTypeLoc with parameter names
+ // for the block; just use the parameter type as a placeholder.
+ std::string Result;
+ Param->getType().getUnqualifiedType().
+ getAsStringInternal(Result, Context.PrintingPolicy);
+
+ if (ObjCMethodParam) {
+ Result = "(" + Result;
+ Result += ")";
+ if (Param->getIdentifier())
+ Result += Param->getIdentifier()->getName();
+ }
+
+ return Result;
+ }
+
+ // We have the function prototype behind the block pointer type, as it was
+ // written in the source.
+ std::string Result;
+ QualType ResultType = Block->getTypePtr()->getResultType();
+ if (!ResultType->isVoidType())
+ ResultType.getAsStringInternal(Result, Context.PrintingPolicy);
+
+ Result = '^' + Result;
+ if (!BlockProto || Block->getNumArgs() == 0) {
+ if (BlockProto && BlockProto->getTypePtr()->isVariadic())
+ Result += "(...)";
+ else
+ Result += "(void)";
+ } else {
+ Result += "(";
+ for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
+ if (I)
+ Result += ", ";
+ Result += FormatFunctionParameter(Context, Block->getArg(I));
+
+ if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
+ Result += ", ...";
+ }
+ Result += ")";
+ }
+
+ if (Param->getIdentifier())
+ Result += Param->getIdentifier()->getName();
+
+ return Result;
+}
+
+/// \brief Add function parameter chunks to the given code completion string.
+static void AddFunctionParameterChunks(ASTContext &Context,
+ FunctionDecl *Function,
+ CodeCompletionBuilder &Result,
+ unsigned Start = 0,
+ bool InOptional = false) {
+ typedef CodeCompletionString::Chunk Chunk;
+ bool FirstParameter = true;
+
+ for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
+ ParmVarDecl *Param = Function->getParamDecl(P);
+
+ if (Param->hasDefaultArg() && !InOptional) {
+ // When we see an optional default argument, put that argument and
+ // the remaining default arguments into a new, optional string.
+ CodeCompletionBuilder Opt(Result.getAllocator());
+ if (!FirstParameter)
+ Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+ AddFunctionParameterChunks(Context, Function, Opt, P, true);
+ Result.AddOptionalChunk(Opt.TakeString());
+ break;
+ }
+
+ if (FirstParameter)
+ FirstParameter = false;
+ else
+ Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+
+ InOptional = false;
+
+ // Format the placeholder string.
+ std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
+
+ if (Function->isVariadic() && P == N - 1)
+ PlaceholderStr += ", ...";
+
+ // Add the placeholder string.
+ Result.AddPlaceholderChunk(
+ Result.getAllocator().CopyString(PlaceholderStr));
+ }
+
+ if (const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>())
+ if (Proto->isVariadic()) {
+ if (Proto->getNumArgs() == 0)
+ Result.AddPlaceholderChunk("...");
+
+ MaybeAddSentinel(Context, Function, Result);
+ }
+}
+
+/// \brief Add template parameter chunks to the given code completion string.
+static void AddTemplateParameterChunks(ASTContext &Context,
+ TemplateDecl *Template,
+ CodeCompletionBuilder &Result,
+ unsigned MaxParameters = 0,
+ unsigned Start = 0,
+ bool InDefaultArg = false) {
+ typedef CodeCompletionString::Chunk Chunk;
+ bool FirstParameter = true;
+
+ TemplateParameterList *Params = Template->getTemplateParameters();
+ TemplateParameterList::iterator PEnd = Params->end();
+ if (MaxParameters)
+ PEnd = Params->begin() + MaxParameters;
+ for (TemplateParameterList::iterator P = Params->begin() + Start;
+ P != PEnd; ++P) {
+ bool HasDefaultArg = false;
+ std::string PlaceholderStr;
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
+ if (TTP->wasDeclaredWithTypename())
+ PlaceholderStr = "typename";
+ else
+ PlaceholderStr = "class";
+
+ if (TTP->getIdentifier()) {
+ PlaceholderStr += ' ';
+ PlaceholderStr += TTP->getIdentifier()->getName();
+ }
+
+ HasDefaultArg = TTP->hasDefaultArgument();
+ } else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ if (NTTP->getIdentifier())
+ PlaceholderStr = NTTP->getIdentifier()->getName();
+ NTTP->getType().getAsStringInternal(PlaceholderStr,
+ Context.PrintingPolicy);
+ HasDefaultArg = NTTP->hasDefaultArgument();
+ } else {
+ assert(isa<TemplateTemplateParmDecl>(*P));
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+
+ // Since putting the template argument list into the placeholder would
+ // be very, very long, we just use an abbreviation.
+ PlaceholderStr = "template<...> class";
+ if (TTP->getIdentifier()) {
+ PlaceholderStr += ' ';
+ PlaceholderStr += TTP->getIdentifier()->getName();
+ }
+
+ HasDefaultArg = TTP->hasDefaultArgument();
+ }
+
+ if (HasDefaultArg && !InDefaultArg) {
+ // When we see an optional default argument, put that argument and
+ // the remaining default arguments into a new, optional string.
+ CodeCompletionBuilder Opt(Result.getAllocator());
+ if (!FirstParameter)
+ Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+ AddTemplateParameterChunks(Context, Template, Opt, MaxParameters,
+ P - Params->begin(), true);
+ Result.AddOptionalChunk(Opt.TakeString());
+ break;
+ }
+
+ InDefaultArg = false;
+
+ if (FirstParameter)
+ FirstParameter = false;
+ else
+ Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+
+ // Add the placeholder string.
+ Result.AddPlaceholderChunk(
+ Result.getAllocator().CopyString(PlaceholderStr));
+ }
+}
+
+/// \brief Add a qualifier to the given code-completion string, if the
+/// provided nested-name-specifier is non-NULL.
+static void
+AddQualifierToCompletionString(CodeCompletionBuilder &Result,
+ NestedNameSpecifier *Qualifier,
+ bool QualifierIsInformative,
+ ASTContext &Context) {
+ if (!Qualifier)
+ return;
+
+ std::string PrintedNNS;
+ {
+ llvm::raw_string_ostream OS(PrintedNNS);
+ Qualifier->print(OS, Context.PrintingPolicy);
+ }
+ if (QualifierIsInformative)
+ Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
+ else
+ Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
+}
+
+static void
+AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
+ FunctionDecl *Function) {
+ const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>();
+ if (!Proto || !Proto->getTypeQuals())
+ return;
+
+ // FIXME: Add ref-qualifier!
+
+ // Handle single qualifiers without copying
+ if (Proto->getTypeQuals() == Qualifiers::Const) {
+ Result.AddInformativeChunk(" const");
+ return;
+ }
+
+ if (Proto->getTypeQuals() == Qualifiers::Volatile) {
+ Result.AddInformativeChunk(" volatile");
+ return;
+ }
+
+ if (Proto->getTypeQuals() == Qualifiers::Restrict) {
+ Result.AddInformativeChunk(" restrict");
+ return;
+ }
+
+ // Handle multiple qualifiers.
+ std::string QualsStr;
+ if (Proto->getTypeQuals() & Qualifiers::Const)
+ QualsStr += " const";
+ if (Proto->getTypeQuals() & Qualifiers::Volatile)
+ QualsStr += " volatile";
+ if (Proto->getTypeQuals() & Qualifiers::Restrict)
+ QualsStr += " restrict";
+ Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+}
+
+/// \brief Add the name of the given declaration
+static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND,
+ CodeCompletionBuilder &Result) {
+ typedef CodeCompletionString::Chunk Chunk;
+
+ DeclarationName Name = ND->getDeclName();
+ if (!Name)
+ return;
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXOperatorName: {
+ const char *OperatorName = 0;
+ switch (Name.getCXXOverloadedOperator()) {
+ case OO_None:
+ case OO_Conditional:
+ case NUM_OVERLOADED_OPERATORS:
+ OperatorName = "operator";
+ break;
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name: OperatorName = "operator" Spelling; break;
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+
+ case OO_New: OperatorName = "operator new"; break;
+ case OO_Delete: OperatorName = "operator delete"; break;
+ case OO_Array_New: OperatorName = "operator new[]"; break;
+ case OO_Array_Delete: OperatorName = "operator delete[]"; break;
+ case OO_Call: OperatorName = "operator()"; break;
+ case OO_Subscript: OperatorName = "operator[]"; break;
+ }
+ Result.AddTypedTextChunk(OperatorName);
+ break;
+ }
+
+ case DeclarationName::Identifier:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(ND->getNameAsString()));
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ break;
+
+ case DeclarationName::CXXConstructorName: {
+ CXXRecordDecl *Record = 0;
+ QualType Ty = Name.getCXXNameType();
+ if (const RecordType *RecordTy = Ty->getAs<RecordType>())
+ Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ else if (const InjectedClassNameType *InjectedTy
+ = Ty->getAs<InjectedClassNameType>())
+ Record = InjectedTy->getDecl();
+ else {
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(ND->getNameAsString()));
+ break;
+ }
+
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(Record->getNameAsString()));
+ if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
+ AddTemplateParameterChunks(Context, Template, Result);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
+ }
+ break;
+ }
+ }
+}
+
+/// \brief If possible, create a new code completion string for the given
+/// result.
+///
+/// \returns Either a new, heap-allocated code completion string describing
+/// how to use this result, or NULL to indicate that the string or name of the
+/// result is all that is needed.
+CodeCompletionString *
+CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+ CodeCompletionAllocator &Allocator) {
+ typedef CodeCompletionString::Chunk Chunk;
+ CodeCompletionBuilder Result(Allocator, Priority, Availability);
+
+ if (Kind == RK_Pattern) {
+ Pattern->Priority = Priority;
+ Pattern->Availability = Availability;
+ return Pattern;
+ }
+
+ if (Kind == RK_Keyword) {
+ Result.AddTypedTextChunk(Keyword);
+ return Result.TakeString();
+ }
+
+ if (Kind == RK_Macro) {
+ MacroInfo *MI = S.PP.getMacroInfo(Macro);
+ assert(MI && "Not a macro?");
+
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(Macro->getName()));
+
+ if (!MI->isFunctionLike())
+ return Result.TakeString();
+
+ // Format a function-like macro with placeholders for the arguments.
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
+ A != AEnd; ++A) {
+ if (A != MI->arg_begin())
+ Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+
+ if (!MI->isVariadic() || A != AEnd - 1) {
+ // Non-variadic argument.
+ Result.AddPlaceholderChunk(
+ Result.getAllocator().CopyString((*A)->getName()));
+ continue;
+ }
+
+ // Variadic argument; cope with the different between GNU and C99
+ // variadic macros, providing a single placeholder for the rest of the
+ // arguments.
+ if ((*A)->isStr("__VA_ARGS__"))
+ Result.AddPlaceholderChunk("...");
+ else {
+ std::string Arg = (*A)->getName();
+ Arg += "...";
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+ }
+ }
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ return Result.TakeString();
+ }
+
+ assert(Kind == RK_Declaration && "Missed a result kind?");
+ NamedDecl *ND = Declaration;
+
+ if (StartsNestedNameSpecifier) {
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(ND->getNameAsString()));
+ Result.AddTextChunk("::");
+ return Result.TakeString();
+ }
+
+ AddResultTypeChunk(S.Context, ND, Result);
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ S.Context);
+ AddTypedNameChunk(S.Context, ND, Result);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ AddFunctionParameterChunks(S.Context, Function, Result);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ AddFunctionTypeQualsToCompletionString(Result, Function);
+ return Result.TakeString();
+ }
+
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ S.Context);
+ FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+ AddTypedNameChunk(S.Context, Function, Result);
+
+ // Figure out which template parameters are deduced (or have default
+ // arguments).
+ llvm::SmallVector<bool, 16> Deduced;
+ S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
+ unsigned LastDeducibleArgument;
+ for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
+ --LastDeducibleArgument) {
+ if (!Deduced[LastDeducibleArgument - 1]) {
+ // C++0x: Figure out if the template argument has a default. If so,
+ // the user doesn't need to type this argument.
+ // FIXME: We need to abstract template parameters better!
+ bool HasDefaultArg = false;
+ NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
+ LastDeducibleArgument - 1);
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ HasDefaultArg = TTP->hasDefaultArgument();
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ HasDefaultArg = NTTP->hasDefaultArgument();
+ else {
+ assert(isa<TemplateTemplateParmDecl>(Param));
+ HasDefaultArg
+ = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
+ }
+
+ if (!HasDefaultArg)
+ break;
+ }
+ }
+
+ if (LastDeducibleArgument) {
+ // Some of the function template arguments cannot be deduced from a
+ // function call, so we introduce an explicit template argument list
+ // containing all of the arguments up to the first deducible argument.
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
+ AddTemplateParameterChunks(S.Context, FunTmpl, Result,
+ LastDeducibleArgument);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
+ }
+
+ // Add the function parameters
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ AddFunctionParameterChunks(S.Context, Function, Result);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ AddFunctionTypeQualsToCompletionString(Result, Function);
+ return Result.TakeString();
+ }
+
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ S.Context);
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(Template->getNameAsString()));
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
+ AddTemplateParameterChunks(S.Context, Template, Result);
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
+ return Result.TakeString();
+ }
+
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
+ Selector Sel = Method->getSelector();
+ if (Sel.isUnarySelector()) {
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(
+ Sel.getNameForSlot(0)));
+ return Result.TakeString();
+ }
+
+ std::string SelName = Sel.getNameForSlot(0).str();
+ SelName += ':';
+ if (StartParameter == 0)
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
+ else {
+ Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
+
+ // If there is only one parameter, and we're past it, add an empty
+ // typed-text chunk since there is nothing to type.
+ if (Method->param_size() == 1)
+ Result.AddTypedTextChunk("");
+ }
+ unsigned Idx = 0;
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; (void)++P, ++Idx) {
+ if (Idx > 0) {
+ std::string Keyword;
+ if (Idx > StartParameter)
+ Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
+ Keyword += II->getName().str();
+ Keyword += ":";
+ if (Idx < StartParameter || AllParametersAreInformative)
+ Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
+ else
+ Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
+ }
+
+ // If we're before the starting parameter, skip the placeholder.
+ if (Idx < StartParameter)
+ continue;
+
+ std::string Arg;
+
+ if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
+ Arg = FormatFunctionParameter(S.Context, *P, true);
+ else {
+ (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
+ Arg = "(" + Arg + ")";
+ if (IdentifierInfo *II = (*P)->getIdentifier())
+ if (DeclaringEntity || AllParametersAreInformative)
+ Arg += II->getName().str();
+ }
+
+ if (Method->isVariadic() && (P + 1) == PEnd)
+ Arg += ", ...";
+
+ if (DeclaringEntity)
+ Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
+ else if (AllParametersAreInformative)
+ Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
+ else
+ Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
+ }
+
+ if (Method->isVariadic()) {
+ if (Method->param_size() == 0) {
+ if (DeclaringEntity)
+ Result.AddTextChunk(", ...");
+ else if (AllParametersAreInformative)
+ Result.AddInformativeChunk(", ...");
+ else
+ Result.AddPlaceholderChunk(", ...");
+ }
+
+ MaybeAddSentinel(S.Context, Method, Result);
+ }
+
+ return Result.TakeString();
+ }
+
+ if (Qualifier)
+ AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
+ S.Context);
+
+ Result.AddTypedTextChunk(
+ Result.getAllocator().CopyString(ND->getNameAsString()));
+ return Result.TakeString();
+}
+
+CodeCompletionString *
+CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
+ unsigned CurrentArg,
+ Sema &S,
+ CodeCompletionAllocator &Allocator) const {
+ typedef CodeCompletionString::Chunk Chunk;
+
+ // FIXME: Set priority, availability appropriately.
+ CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
+ FunctionDecl *FDecl = getFunction();
+ AddResultTypeChunk(S.Context, FDecl, Result);
+ const FunctionProtoType *Proto
+ = dyn_cast<FunctionProtoType>(getFunctionType());
+ if (!FDecl && !Proto) {
+ // Function without a prototype. Just give the return type and a
+ // highlighted ellipsis.
+ const FunctionType *FT = getFunctionType();
+ Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
+ S.Context,
+ Result.getAllocator()));
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ return Result.TakeString();
+ }
+
+ if (FDecl)
+ Result.AddTextChunk(
+ Result.getAllocator().CopyString(FDecl->getNameAsString()));
+ else
+ Result.AddTextChunk(
+ Result.getAllocator().CopyString(
+ Proto->getResultType().getAsString(S.Context.PrintingPolicy)));
+
+ Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
+ for (unsigned I = 0; I != NumParams; ++I) {
+ if (I)
+ Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+
+ std::string ArgString;
+ QualType ArgType;
+
+ if (FDecl) {
+ ArgString = FDecl->getParamDecl(I)->getNameAsString();
+ ArgType = FDecl->getParamDecl(I)->getOriginalType();
+ } else {
+ ArgType = Proto->getArgType(I);
+ }
+
+ ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
+
+ if (I == CurrentArg)
+ Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
+ Result.getAllocator().CopyString(ArgString)));
+ else
+ Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
+ }
+
+ if (Proto && Proto->isVariadic()) {
+ Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
+ if (CurrentArg < NumParams)
+ Result.AddTextChunk("...");
+ else
+ Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
+ }
+ Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+
+ return Result.TakeString();
+}
+
+unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
+ const LangOptions &LangOpts,
+ bool PreferredTypeIsPointer) {
+ unsigned Priority = CCP_Macro;
+
+ // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
+ if (MacroName.equals("nil") || MacroName.equals("NULL") ||
+ MacroName.equals("Nil")) {
+ Priority = CCP_Constant;
+ if (PreferredTypeIsPointer)
+ Priority = Priority / CCF_SimilarTypeMatch;
+ }
+ // Treat "YES", "NO", "true", and "false" as constants.
+ else if (MacroName.equals("YES") || MacroName.equals("NO") ||
+ MacroName.equals("true") || MacroName.equals("false"))
+ Priority = CCP_Constant;
+ // Treat "bool" as a type.
+ else if (MacroName.equals("bool"))
+ Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
+
+
+ return Priority;
+}
+
+CXCursorKind clang::getCursorKindForDecl(Decl *D) {
+ if (!D)
+ return CXCursor_UnexposedDecl;
+
+ switch (D->getKind()) {
+ case Decl::Enum: return CXCursor_EnumDecl;
+ case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
+ case Decl::Field: return CXCursor_FieldDecl;
+ case Decl::Function:
+ return CXCursor_FunctionDecl;
+ case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
+ case Decl::ObjCClass:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCForwardProtocol:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
+ case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCMethod:
+ return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+ case Decl::CXXMethod: return CXCursor_CXXMethod;
+ case Decl::CXXConstructor: return CXCursor_Constructor;
+ case Decl::CXXDestructor: return CXCursor_Destructor;
+ case Decl::CXXConversion: return CXCursor_ConversionFunction;
+ case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
+ case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
+ case Decl::ParmVar: return CXCursor_ParmDecl;
+ case Decl::Typedef: return CXCursor_TypedefDecl;
+ case Decl::Var: return CXCursor_VarDecl;
+ case Decl::Namespace: return CXCursor_Namespace;
+ case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
+ case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
+ case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
+ case Decl::ClassTemplate: return CXCursor_ClassTemplate;
+ case Decl::ClassTemplatePartialSpecialization:
+ return CXCursor_ClassTemplatePartialSpecialization;
+ case Decl::UsingDirective: return CXCursor_UsingDirective;
+
+ case Decl::Using:
+ case Decl::UnresolvedUsingValue:
+ case Decl::UnresolvedUsingTypename:
+ return CXCursor_UsingDeclaration;
+
+ default:
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TTK_Struct: return CXCursor_StructDecl;
+ case TTK_Class: return CXCursor_ClassDecl;
+ case TTK_Union: return CXCursor_UnionDecl;
+ case TTK_Enum: return CXCursor_EnumDecl;
+ }
+ }
+ }
+
+ return CXCursor_UnexposedDecl;
+}
+
+static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
+ bool TargetTypeIsPointer = false) {
+ typedef CodeCompletionResult Result;
+
+ Results.EnterNewScope();
+
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ MEnd = PP.macro_end();
+ M != MEnd; ++M) {
+ Results.AddResult(Result(M->first,
+ getMacroUsagePriority(M->first->getName(),
+ PP.getLangOptions(),
+ TargetTypeIsPointer)));
+ }
+
+ Results.ExitScope();
+
+}
+
+static void AddPrettyFunctionResults(const LangOptions &LangOpts,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+
+ Results.EnterNewScope();
+
+ Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
+ Results.AddResult(Result("__FUNCTION__", CCP_Constant));
+ if (LangOpts.C99 || LangOpts.CPlusPlus0x)
+ Results.AddResult(Result("__func__", CCP_Constant));
+ Results.ExitScope();
+}
+
+static void HandleCodeCompleteResults(Sema *S,
+ CodeCompleteConsumer *CodeCompleter,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
+ if (CodeCompleter)
+ CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
+}
+
+static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
+ Sema::ParserCompletionContext PCC) {
+ switch (PCC) {
+ case Sema::PCC_Namespace:
+ return CodeCompletionContext::CCC_TopLevel;
+
+ case Sema::PCC_Class:
+ return CodeCompletionContext::CCC_ClassStructUnion;
+
+ case Sema::PCC_ObjCInterface:
+ return CodeCompletionContext::CCC_ObjCInterface;
+
+ case Sema::PCC_ObjCImplementation:
+ return CodeCompletionContext::CCC_ObjCImplementation;
+
+ case Sema::PCC_ObjCInstanceVariableList:
+ return CodeCompletionContext::CCC_ObjCIvarList;
+
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
+ if (S.CurContext->isFileContext())
+ return CodeCompletionContext::CCC_TopLevel;
+ else if (S.CurContext->isRecord())
+ return CodeCompletionContext::CCC_ClassStructUnion;
+ else
+ return CodeCompletionContext::CCC_Other;
+
+ case Sema::PCC_RecoveryInFunction:
+ return CodeCompletionContext::CCC_Recovery;
+
+ case Sema::PCC_ForInit:
+ if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
+ S.getLangOptions().ObjC1)
+ return CodeCompletionContext::CCC_ParenthesizedExpression;
+ else
+ return CodeCompletionContext::CCC_Expression;
+
+ case Sema::PCC_Expression:
+ case Sema::PCC_Condition:
+ return CodeCompletionContext::CCC_Expression;
+
+ case Sema::PCC_Statement:
+ return CodeCompletionContext::CCC_Statement;
+
+ case Sema::PCC_Type:
+ return CodeCompletionContext::CCC_Type;
+
+ case Sema::PCC_ParenthesizedExpression:
+ return CodeCompletionContext::CCC_ParenthesizedExpression;
+
+ case Sema::PCC_LocalDeclarationSpecifiers:
+ return CodeCompletionContext::CCC_Type;
+ }
+
+ return CodeCompletionContext::CCC_Other;
+}
+
+/// \brief If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the
+/// overridden function as well as adding new functionality.
+///
+/// \param S The semantic analysis object for which we are generating results.
+///
+/// \param InContext This context in which the nested-name-specifier preceding
+/// the code-completion point
+static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
+ ResultBuilder &Results) {
+ // Look through blocks.
+ DeclContext *CurContext = S.CurContext;
+ while (isa<BlockDecl>(CurContext))
+ CurContext = CurContext->getParent();
+
+
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
+ if (!Method || !Method->isVirtual())
+ return;
+
+ // We need to have names for all of the parameters, if we're going to
+ // generate a forwarding call.
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd;
+ ++P) {
+ if (!(*P)->getDeclName())
+ return;
+ }
+
+ for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
+ MEnd = Method->end_overridden_methods();
+ M != MEnd; ++M) {
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
+ if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
+ continue;
+
+ // If we need a nested-name-specifier, add one now.
+ if (!InContext) {
+ NestedNameSpecifier *NNS
+ = getRequiredQualification(S.Context, CurContext,
+ Overridden->getDeclContext());
+ if (NNS) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ NNS->print(OS, S.Context.PrintingPolicy);
+ Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
+ }
+ } else if (!InContext->Equals(Overridden->getDeclContext()))
+ continue;
+
+ Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
+ Overridden->getNameAsString()));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ bool FirstParam = true;
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P) {
+ if (FirstParam)
+ FirstParam = false;
+ else
+ Builder.AddChunk(CodeCompletionString::CK_Comma);
+
+ Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
+ (*P)->getIdentifier()->getName()));
+ }
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ CCP_SuperCompletion,
+ CXCursor_CXXMethod));
+ Results.Ignore(Overridden);
+ }
+}
+
+void Sema::CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ mapCodeCompletionContext(*this, CompletionContext));
+ Results.EnterNewScope();
+
+ // Determine how to filter results, e.g., so that the names of
+ // values (functions, enumerators, function templates, etc.) are
+ // only allowed where we can have an expression.
+ switch (CompletionContext) {
+ case PCC_Namespace:
+ case PCC_Class:
+ case PCC_ObjCInterface:
+ case PCC_ObjCImplementation:
+ case PCC_ObjCInstanceVariableList:
+ case PCC_Template:
+ case PCC_MemberTemplate:
+ case PCC_Type:
+ case PCC_LocalDeclarationSpecifiers:
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+ break;
+
+ case PCC_Statement:
+ case PCC_ParenthesizedExpression:
+ case PCC_Expression:
+ case PCC_ForInit:
+ case PCC_Condition:
+ if (WantTypesInContext(CompletionContext, getLangOptions()))
+ Results.setFilter(&ResultBuilder::IsOrdinaryName);
+ else
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+
+ if (getLangOptions().CPlusPlus)
+ MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
+ break;
+
+ case PCC_RecoveryInFunction:
+ // Unfiltered
+ break;
+ }
+
+ // If we are in a C++ non-static member function, check the qualifiers on
+ // the member function to filter/prioritize the results list.
+ if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
+ if (CurMethod->isInstance())
+ Results.setObjectTypeQualifiers(
+ Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
+
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ AddOrdinaryNameResults(CompletionContext, S, *this, Results);
+ Results.ExitScope();
+
+ switch (CompletionContext) {
+ case PCC_ParenthesizedExpression:
+ case PCC_Expression:
+ case PCC_Statement:
+ case PCC_RecoveryInFunction:
+ if (S->getFnParent())
+ AddPrettyFunctionResults(PP.getLangOptions(), Results);
+ break;
+
+ case PCC_Namespace:
+ case PCC_Class:
+ case PCC_ObjCInterface:
+ case PCC_ObjCImplementation:
+ case PCC_ObjCInstanceVariableList:
+ case PCC_Template:
+ case PCC_MemberTemplate:
+ case PCC_ForInit:
+ case PCC_Condition:
+ case PCC_Type:
+ case PCC_LocalDeclarationSpecifiers:
+ break;
+ }
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(),Results.size());
+}
+
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+ ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper,
+ ResultBuilder &Results);
+
+void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ AllowNestedNameSpecifiers
+ ? CodeCompletionContext::CCC_PotentiallyQualifiedName
+ : CodeCompletionContext::CCC_Name);
+ Results.EnterNewScope();
+
+ // Type qualifiers can come after names.
+ Results.AddResult(Result("const"));
+ Results.AddResult(Result("volatile"));
+ if (getLangOptions().C99)
+ Results.AddResult(Result("restrict"));
+
+ if (getLangOptions().CPlusPlus) {
+ if (AllowNonIdentifiers) {
+ Results.AddResult(Result("operator"));
+ }
+
+ // Add nested-name-specifiers.
+ if (AllowNestedNameSpecifiers) {
+ Results.allowNestedNameSpecifiers();
+ Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
+ CodeCompleter->includeGlobals());
+ Results.setFilter(0);
+ }
+ }
+ Results.ExitScope();
+
+ // If we're in a context where we might have an expression (rather than a
+ // declaration), and what we've seen so far is an Objective-C type that could
+ // be a receiver of a class message, this may be a class message send with
+ // the initial opening bracket '[' missing. Add appropriate completions.
+ if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
+ DS.getTypeSpecType() == DeclSpec::TST_typename &&
+ DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
+ !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
+ DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
+ DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ DS.getTypeQualifiers() == 0 &&
+ S &&
+ (S->getFlags() & Scope::DeclScope) != 0 &&
+ (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
+ Scope::FunctionPrototypeScope |
+ Scope::AtCatchScope)) == 0) {
+ ParsedType T = DS.getRepAsType();
+ if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
+ AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
+ }
+
+ // Note that we intentionally suppress macro results here, since we do not
+ // encourage using macros to produce the names of entities.
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
+struct Sema::CodeCompleteExpressionData {
+ CodeCompleteExpressionData(QualType PreferredType = QualType())
+ : PreferredType(PreferredType), IntegralConstantExpression(false),
+ ObjCCollection(false) { }
+
+ QualType PreferredType;
+ bool IntegralConstantExpression;
+ bool ObjCCollection;
+ llvm::SmallVector<Decl *, 4> IgnoreDecls;
+};
+
+/// \brief Perform code-completion in an expression context when we know what
+/// type we're looking for.
+///
+/// \param IntegralConstantExpression Only permit integral constant
+/// expressions.
+void Sema::CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Expression);
+ if (Data.ObjCCollection)
+ Results.setFilter(&ResultBuilder::IsObjCCollection);
+ else if (Data.IntegralConstantExpression)
+ Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
+ else if (WantTypesInContext(PCC_Expression, getLangOptions()))
+ Results.setFilter(&ResultBuilder::IsOrdinaryName);
+ else
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+
+ if (!Data.PreferredType.isNull())
+ Results.setPreferredType(Data.PreferredType.getNonReferenceType());
+
+ // Ignore any declarations that we were told that we don't care about.
+ for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
+ Results.Ignore(Data.IgnoreDecls[I]);
+
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ Results.EnterNewScope();
+ AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
+ Results.ExitScope();
+
+ bool PreferredTypeIsPointer = false;
+ if (!Data.PreferredType.isNull())
+ PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
+ || Data.PreferredType->isMemberPointerType()
+ || Data.PreferredType->isBlockPointerType();
+
+ if (S->getFnParent() &&
+ !Data.ObjCCollection &&
+ !Data.IntegralConstantExpression)
+ AddPrettyFunctionResults(PP.getLangOptions(), Results);
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results, PreferredTypeIsPointer);
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ Data.PreferredType),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
+ if (E.isInvalid())
+ CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
+ else if (getLangOptions().ObjC1)
+ CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
+}
+
+/// \brief The set of properties that have already been added, referenced by
+/// property name.
+typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
+
+static void AddObjCProperties(ObjCContainerDecl *Container,
+ bool AllowCategories,
+ DeclContext *CurContext,
+ AddedPropertiesSet &AddedProperties,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+
+ // Add properties in this container.
+ for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
+ PEnd = Container->prop_end();
+ P != PEnd;
+ ++P) {
+ if (AddedProperties.insert(P->getIdentifier()))
+ Results.MaybeAddResult(Result(*P, 0), CurContext);
+ }
+
+ // Add properties in referenced protocols.
+ if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+ for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
+ PEnd = Protocol->protocol_end();
+ P != PEnd; ++P)
+ AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
+ Results);
+ } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+ if (AllowCategories) {
+ // Look through categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ AddObjCProperties(Category, AllowCategories, CurContext,
+ AddedProperties, Results);
+ }
+
+ // Look through protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I)
+ AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties,
+ Results);
+
+ // Look in the superclass.
+ if (IFace->getSuperClass())
+ AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
+ AddedProperties, Results);
+ } else if (const ObjCCategoryDecl *Category
+ = dyn_cast<ObjCCategoryDecl>(Container)) {
+ // Look through protocols.
+ for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
+ P != PEnd; ++P)
+ AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
+ Results);
+ }
+}
+
+void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
+ SourceLocation OpLoc,
+ bool IsArrow) {
+ if (!BaseE || !CodeCompleter)
+ return;
+
+ typedef CodeCompletionResult Result;
+
+ Expr *Base = static_cast<Expr *>(BaseE);
+ QualType BaseType = Base->getType();
+
+ if (IsArrow) {
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ else if (BaseType->isObjCObjectPointerType())
+ /*Do nothing*/ ;
+ else
+ return;
+ }
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
+ BaseType),
+ &ResultBuilder::IsMember);
+ Results.EnterNewScope();
+ if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+ // Indicate that we are performing a member access, and the cv-qualifiers
+ // for the base object type.
+ Results.setObjectTypeQualifiers(BaseType.getQualifiers());
+
+ // Access to a C/C++ class, struct, or union.
+ Results.allowNestedNameSpecifiers();
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ if (getLangOptions().CPlusPlus) {
+ if (!Results.empty()) {
+ // The "template" keyword can follow "->" or "." in the grammar.
+ // However, we only want to suggest the template keyword if something
+ // is dependent.
+ bool IsDependent = BaseType->isDependentType();
+ if (!IsDependent) {
+ for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+ if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+ IsDependent = Ctx->isDependentContext();
+ break;
+ }
+ }
+
+ if (IsDependent)
+ Results.AddResult(Result("template"));
+ }
+ }
+ } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+ // Objective-C property reference.
+ AddedPropertiesSet AddedProperties;
+
+ // Add property results based on our interface.
+ const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAsObjCInterfacePointerType();
+ assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+ AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,
+ AddedProperties, Results);
+
+ // Add properties from the protocols in a qualified interface.
+ for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
+ E = ObjCPtr->qual_end();
+ I != E; ++I)
+ AddObjCProperties(*I, true, CurContext, AddedProperties, Results);
+ } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCObjectType())) {
+ // Objective-C instance variable access.
+ ObjCInterfaceDecl *Class = 0;
+ if (const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAs<ObjCObjectPointerType>())
+ Class = ObjCPtr->getInterfaceDecl();
+ else
+ Class = BaseType->getAs<ObjCObjectType>()->getInterface();
+
+ // Add all ivars from this class and its superclasses.
+ if (Class) {
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.setFilter(&ResultBuilder::IsObjCIvar);
+ LookupVisibleDecls(Class, LookupMemberName, Consumer,
+ CodeCompleter->includeGlobals());
+ }
+ }
+
+ // FIXME: How do we cope with isa?
+
+ Results.ExitScope();
+
+ // Hand off the results found for code completion.
+ HandleCodeCompleteResults(this, CodeCompleter,
+ Results.getCompletionContext(),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
+ if (!CodeCompleter)
+ return;
+
+ typedef CodeCompletionResult Result;
+ ResultBuilder::LookupFilter Filter = 0;
+ enum CodeCompletionContext::Kind ContextKind
+ = CodeCompletionContext::CCC_Other;
+ switch ((DeclSpec::TST)TagSpec) {
+ case DeclSpec::TST_enum:
+ Filter = &ResultBuilder::IsEnum;
+ ContextKind = CodeCompletionContext::CCC_EnumTag;
+ break;
+
+ case DeclSpec::TST_union:
+ Filter = &ResultBuilder::IsUnion;
+ ContextKind = CodeCompletionContext::CCC_UnionTag;
+ break;
+
+ case DeclSpec::TST_struct:
+ case DeclSpec::TST_class:
+ Filter = &ResultBuilder::IsClassOrStruct;
+ ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
+ break;
+
+ default:
+ assert(false && "Unknown type specifier kind in CodeCompleteTag");
+ return;
+ }
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+
+ // First pass: look for tags.
+ Results.setFilter(Filter);
+ LookupVisibleDecls(S, LookupTagName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ if (CodeCompleter->includeGlobals()) {
+ // Second pass: look for nested name specifiers.
+ Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_TypeQualifiers);
+ Results.EnterNewScope();
+ if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
+ Results.AddResult("const");
+ if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
+ Results.AddResult("volatile");
+ if (getLangOptions().C99 &&
+ !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
+ Results.AddResult("restrict");
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteCase(Scope *S) {
+ if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
+ return;
+
+ SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+ if (!Switch->getCond()->getType()->isEnumeralType()) {
+ CodeCompleteExpressionData Data(Switch->getCond()->getType());
+ Data.IntegralConstantExpression = true;
+ CodeCompleteExpression(S, Data);
+ return;
+ }
+
+ // Code-complete the cases of a switch statement over an enumeration type
+ // by providing the list of
+ EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
+
+ // Determine which enumerators we have already seen in the switch statement.
+ // FIXME: Ideally, we would also be able to look *past* the code-completion
+ // token, in case we are code-completing in the middle of the switch and not
+ // at the end. However, we aren't able to do so at the moment.
+ llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
+ NestedNameSpecifier *Qualifier = 0;
+ for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ CaseStmt *Case = dyn_cast<CaseStmt>(SC);
+ if (!Case)
+ continue;
+
+ Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
+ if (EnumConstantDecl *Enumerator
+ = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+ // We look into the AST of the case statement to determine which
+ // enumerator was named. Alternatively, we could compute the value of
+ // the integral constant expression, then compare it against the
+ // values of each enumerator. However, value-based approach would not
+ // work as well with C++ templates where enumerators declared within a
+ // template are type- and value-dependent.
+ EnumeratorsSeen.insert(Enumerator);
+
+ // If this is a qualified-id, keep track of the nested-name-specifier
+ // so that we can reproduce it as part of code completion, e.g.,
+ //
+ // switch (TagD.getKind()) {
+ // case TagDecl::TK_enum:
+ // break;
+ // case XXX
+ //
+ // At the XXX, our completions are TagDecl::TK_union,
+ // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
+ // TK_struct, and TK_class.
+ Qualifier = DRE->getQualifier();
+ }
+ }
+
+ if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
+ // If there are no prior enumerators in C++, check whether we have to
+ // qualify the names of the enumerators that we suggest, because they
+ // may not be visible in this scope.
+ Qualifier = getRequiredQualification(Context, CurContext,
+ Enum->getDeclContext());
+
+ // FIXME: Scoped enums need to start with "EnumDecl" as the context!
+ }
+
+ // Add any enumerators that have not yet been mentioned.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Expression);
+ Results.EnterNewScope();
+ for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
+ EEnd = Enum->enumerator_end();
+ E != EEnd; ++E) {
+ if (EnumeratorsSeen.count(*E))
+ continue;
+
+ CodeCompletionResult R(*E, Qualifier);
+ R.Priority = CCP_EnumInCase;
+ Results.AddResult(R, CurContext, 0, false);
+ }
+ Results.ExitScope();
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_OtherWithMacros,
+ Results.data(),Results.size());
+}
+
+namespace {
+ struct IsBetterOverloadCandidate {
+ Sema &S;
+ SourceLocation Loc;
+
+ public:
+ explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
+ : S(S), Loc(Loc) { }
+
+ bool
+ operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
+ return isBetterOverloadCandidate(S, X, Y, Loc);
+ }
+ };
+}
+
+static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
+ if (NumArgs && !Args)
+ return true;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (!Args[I])
+ return true;
+
+ return false;
+}
+
+void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
+ ExprTy **ArgsIn, unsigned NumArgs) {
+ if (!CodeCompleter)
+ return;
+
+ // When we're code-completing for a call, we fall back to ordinary
+ // name code-completion whenever we can't produce specific
+ // results. We may want to revisit this strategy in the future,
+ // e.g., by merging the two kinds of results.
+
+ Expr *Fn = (Expr *)FnIn;
+ Expr **Args = (Expr **)ArgsIn;
+
+ // Ignore type-dependent call expressions entirely.
+ if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
+ Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ return;
+ }
+
+ // Build an overload candidate set based on the functions we find.
+ SourceLocation Loc = Fn->getExprLoc();
+ OverloadCandidateSet CandidateSet(Loc);
+
+ // FIXME: What if we're calling something that isn't a function declaration?
+ // FIXME: What if we're calling a pseudo-destructor?
+ // FIXME: What if we're calling a member function?
+
+ typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+ llvm::SmallVector<ResultCandidate, 8> Results;
+
+ Expr *NakedFn = Fn->IgnoreParenCasts();
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
+ AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
+ /*PartialOverloading=*/ true);
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FDecl) {
+ if (!getLangOptions().CPlusPlus ||
+ !FDecl->getType()->getAs<FunctionProtoType>())
+ Results.push_back(ResultCandidate(FDecl));
+ else
+ // FIXME: access?
+ AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
+ Args, NumArgs, CandidateSet,
+ false, /*PartialOverloading*/true);
+ }
+ }
+
+ QualType ParamType;
+
+ if (!CandidateSet.empty()) {
+ // Sort the overload candidate set by placing the best overloads first.
+ std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
+ IsBetterOverloadCandidate(*this, Loc));
+
+ // Add the remaining viable overload candidates as code-completion reslults.
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+ CandEnd = CandidateSet.end();
+ Cand != CandEnd; ++Cand) {
+ if (Cand->Viable)
+ Results.push_back(ResultCandidate(Cand->Function));
+ }
+
+ // From the viable candidates, try to determine the type of this parameter.
+ for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+ if (const FunctionType *FType = Results[I].getFunctionType())
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
+ if (NumArgs < Proto->getNumArgs()) {
+ if (ParamType.isNull())
+ ParamType = Proto->getArgType(NumArgs);
+ else if (!Context.hasSameUnqualifiedType(
+ ParamType.getNonReferenceType(),
+ Proto->getArgType(NumArgs).getNonReferenceType())) {
+ ParamType = QualType();
+ break;
+ }
+ }
+ }
+ } else {
+ // Try to determine the parameter type from the type of the expression
+ // being called.
+ QualType FunctionType = Fn->getType();
+ if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
+ FunctionType = Ptr->getPointeeType();
+ else if (const BlockPointerType *BlockPtr
+ = FunctionType->getAs<BlockPointerType>())
+ FunctionType = BlockPtr->getPointeeType();
+ else if (const MemberPointerType *MemPtr
+ = FunctionType->getAs<MemberPointerType>())
+ FunctionType = MemPtr->getPointeeType();
+
+ if (const FunctionProtoType *Proto
+ = FunctionType->getAs<FunctionProtoType>()) {
+ if (NumArgs < Proto->getNumArgs())
+ ParamType = Proto->getArgType(NumArgs);
+ }
+ }
+
+ if (ParamType.isNull())
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ else
+ CodeCompleteExpression(S, ParamType);
+
+ if (!Results.empty())
+ CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
+ Results.size());
+}
+
+void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
+ ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
+ if (!VD) {
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ return;
+ }
+
+ CodeCompleteExpression(S, VD->getType());
+}
+
+void Sema::CodeCompleteReturn(Scope *S) {
+ QualType ResultType;
+ if (isa<BlockDecl>(CurContext)) {
+ if (BlockScopeInfo *BSI = getCurBlock())
+ ResultType = BSI->ReturnType;
+ } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
+ ResultType = Function->getResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
+ ResultType = Method->getResultType();
+
+ if (ResultType.isNull())
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ else
+ CodeCompleteExpression(S, ResultType);
+}
+
+void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
+ if (LHS)
+ CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
+ else
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+}
+
+void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext) {
+ if (!SS.getScopeRep() || !CodeCompleter)
+ return;
+
+ DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
+ if (!Ctx)
+ return;
+
+ // Try to instantiate any non-dependent declaration contexts before
+ // we look in them.
+ if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
+ return;
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Name);
+ Results.EnterNewScope();
+
+ // The "template" keyword can follow "::" in the grammar, but only
+ // put it into the grammar if the nested-name-specifier is dependent.
+ NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ if (!Results.empty() && NNS->isDependent())
+ Results.AddResult("template");
+
+ // Add calls to overridden virtual functions, if there are any.
+ //
+ // FIXME: This isn't wonderful, because we don't know whether we're actually
+ // in a context that permits expressions. This is a general issue with
+ // qualified-id completions.
+ if (!EnteringContext)
+ MaybeAddOverrideCalls(*this, Ctx, Results);
+ Results.ExitScope();
+
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Name,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsing(Scope *S) {
+ if (!CodeCompleter)
+ return;
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_PotentiallyQualifiedName,
+ &ResultBuilder::IsNestedNameSpecifier);
+ Results.EnterNewScope();
+
+ // If we aren't in class scope, we could see the "namespace" keyword.
+ if (!S->isClassScope())
+ Results.AddResult(CodeCompletionResult("namespace"));
+
+ // After "using", we can see anything that would start a
+ // nested-name-specifier.
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_PotentiallyQualifiedName,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteUsingDirective(Scope *S) {
+ if (!CodeCompleter)
+ return;
+
+ // After "using namespace", we expect to see a namespace name or namespace
+ // alias.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Namespace,
+ &ResultBuilder::IsNamespaceOrAlias);
+ Results.EnterNewScope();
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Namespace,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceDecl(Scope *S) {
+ if (!CodeCompleter)
+ return;
+
+ DeclContext *Ctx = (DeclContext *)S->getEntity();
+ if (!S->getParent())
+ Ctx = Context.getTranslationUnitDecl();
+
+ bool SuppressedGlobalResults
+ = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ SuppressedGlobalResults
+ ? CodeCompletionContext::CCC_Namespace
+ : CodeCompletionContext::CCC_Other,
+ &ResultBuilder::IsNamespace);
+
+ if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
+ // We only want to see those namespaces that have already been defined
+ // within this scope, because its likely that the user is creating an
+ // extended namespace declaration. Keep track of the most recent
+ // definition of each namespace.
+ std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
+ for (DeclContext::specific_decl_iterator<NamespaceDecl>
+ NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
+ NS != NSEnd; ++NS)
+ OrigToLatest[NS->getOriginalNamespace()] = *NS;
+
+ // Add the most recent definition (or extended definition) of each
+ // namespace to the list of results.
+ Results.EnterNewScope();
+ for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
+ NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
+ NS != NSEnd; ++NS)
+ Results.AddResult(CodeCompletionResult(NS->second, 0),
+ CurContext, 0, false);
+ Results.ExitScope();
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ Results.getCompletionContext(),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
+ if (!CodeCompleter)
+ return;
+
+ // After "namespace", we expect to see a namespace or alias.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Namespace,
+ &ResultBuilder::IsNamespaceOrAlias);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ Results.getCompletionContext(),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteOperatorName(Scope *S) {
+ if (!CodeCompleter)
+ return;
+
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Type,
+ &ResultBuilder::IsType);
+ Results.EnterNewScope();
+
+ // Add the names of overloadable operators.
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ if (std::strcmp(Spelling, "?")) \
+ Results.AddResult(Result(Spelling));
+#include "clang/Basic/OperatorKinds.def"
+
+ // Add any type names visible from the current scope
+ Results.allowNestedNameSpecifiers();
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ // Add any type specifiers
+ AddTypeSpecifierResults(getLangOptions(), Results);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Type,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
+ CXXCtorInitializer** Initializers,
+ unsigned NumInitializers) {
+ CXXConstructorDecl *Constructor
+ = static_cast<CXXConstructorDecl *>(ConstructorD);
+ if (!Constructor)
+ return;
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_PotentiallyQualifiedName);
+ Results.EnterNewScope();
+
+ // Fill in any already-initialized fields or base classes.
+ llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
+ llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
+ for (unsigned I = 0; I != NumInitializers; ++I) {
+ if (Initializers[I]->isBaseInitializer())
+ InitializedBases.insert(
+ Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
+ else
+ InitializedFields.insert(cast<FieldDecl>(
+ Initializers[I]->getAnyMember()));
+ }
+
+ // Add completions for base classes.
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ bool SawLastInitializer = (NumInitializers == 0);
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd; ++Base) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(Base->getType(),
+ QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ continue;
+ }
+
+ Builder.AddTypedTextChunk(
+ Results.getAllocator().CopyString(
+ Base->getType().getAsString(Context.PrintingPolicy)));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("args");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration));
+ SawLastInitializer = false;
+ }
+
+ // Add completions for virtual base classes.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ Base != BaseEnd; ++Base) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(Base->getType(),
+ QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ continue;
+ }
+
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(
+ Base->getType().getAsString(Context.PrintingPolicy)));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("args");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration));
+ SawLastInitializer = false;
+ }
+
+ // Add completions for members.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
+ Initializers[NumInitializers - 1]->getAnyMember() == *Field;
+ continue;
+ }
+
+ if (!Field->getDeclName())
+ continue;
+
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ Field->getIdentifier()->getName()));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("args");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(),
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration,
+ CXCursor_MemberRef));
+ SawLastInitializer = false;
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
+// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
+// true or false.
+#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
+static void AddObjCImplementationResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt) {
+ typedef CodeCompletionResult Result;
+ // Since we have an implementation, we can end it.
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ if (LangOpts.ObjC2) {
+ // @dynamic
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("property");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // @synthesize
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("property");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+}
+
+static void AddObjCInterfaceResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt) {
+ typedef CodeCompletionResult Result;
+
+ // Since we have an interface or protocol, we can end it.
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
+
+ if (LangOpts.ObjC2) {
+ // @property
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
+
+ // @required
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
+
+ // @optional
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
+ }
+}
+
+static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
+ typedef CodeCompletionResult Result;
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ // @class name ;
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ if (Results.includeCodePatterns()) {
+ // @interface name
+ // FIXME: Could introduce the whole pattern, including superclasses and
+ // such.
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("class");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // @protocol name
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("protocol");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // @implementation name
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("class");
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // @compatibility_alias name
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("alias");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("class");
+ Results.AddResult(Result(Builder.TakeString()));
+}
+
+void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
+ bool InInterface) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ if (ObjCImpDecl)
+ AddObjCImplementationResults(getLangOptions(), Results, false);
+ else if (InInterface)
+ AddObjCInterfaceResults(getLangOptions(), Results, false);
+ else
+ AddObjCTopLevelResults(Results, false);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
+ typedef CodeCompletionResult Result;
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ // @encode ( type-name )
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("type-name");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // @protocol ( protocol-name )
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("protocol-name");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+
+ // @selector ( selector )
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("selector");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
+}
+
+static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
+ typedef CodeCompletionResult Result;
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ if (Results.includeCodePatterns()) {
+ // @try { statements } @catch ( declaration ) { statements } @finally
+ // { statements }
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Builder.AddTextChunk("@catch");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("parameter");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Builder.AddTextChunk("@finally");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+
+ // @throw
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
+
+ if (Results.includeCodePatterns()) {
+ // @synchronized ( expression ) { statements }
+ Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("statements");
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
+ }
+}
+
+static void AddObjCVisibilityResults(const LangOptions &LangOpts,
+ ResultBuilder &Results,
+ bool NeedAt) {
+ typedef CodeCompletionResult Result;
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
+ if (LangOpts.ObjC2)
+ Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
+}
+
+void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ AddObjCVisibilityResults(getLangOptions(), Results, false);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtStatement(Scope *S) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ AddObjCStatementResults(Results, false);
+ AddObjCExpressionResults(Results, false);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCAtExpression(Scope *S) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ AddObjCExpressionResults(Results, false);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+/// \brief Determine whether the addition of the given flag to an Objective-C
+/// property's attributes will cause a conflict.
+static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
+ // Check if we've already added this flag.
+ if (Attributes & NewFlag)
+ return true;
+
+ Attributes |= NewFlag;
+
+ // Check for collisions with "readonly".
+ if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+ ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain)))
+ return true;
+
+ // Check for more than one of { assign, copy, retain }.
+ unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain);
+ if (AssignCopyRetMask &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
+ AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
+ return true;
+
+ return false;
+}
+
+void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
+ if (!CodeCompleter)
+ return;
+
+ unsigned Attributes = ODS.getPropertyAttributes();
+
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
+ Results.AddResult(CodeCompletionResult("readonly"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
+ Results.AddResult(CodeCompletionResult("assign"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
+ Results.AddResult(CodeCompletionResult("readwrite"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
+ Results.AddResult(CodeCompletionResult("retain"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
+ Results.AddResult(CodeCompletionResult("copy"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
+ Results.AddResult(CodeCompletionResult("nonatomic"));
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
+ CodeCompletionBuilder Setter(Results.getAllocator());
+ Setter.AddTypedTextChunk("setter");
+ Setter.AddTextChunk(" = ");
+ Setter.AddPlaceholderChunk("method");
+ Results.AddResult(CodeCompletionResult(Setter.TakeString()));
+ }
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
+ CodeCompletionBuilder Getter(Results.getAllocator());
+ Getter.AddTypedTextChunk("getter");
+ Getter.AddTextChunk(" = ");
+ Getter.AddPlaceholderChunk("method");
+ Results.AddResult(CodeCompletionResult(Getter.TakeString()));
+ }
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+/// \brief Descripts the kind of Objective-C method that we want to find
+/// via code completion.
+enum ObjCMethodKind {
+ MK_Any, //< Any kind of method, provided it means other specified criteria.
+ MK_ZeroArgSelector, //< Zero-argument (unary) selector.
+ MK_OneArgSelector //< One-argument selector.
+};
+
+static bool isAcceptableObjCSelector(Selector Sel,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AllowSameLength = true) {
+ if (NumSelIdents > Sel.getNumArgs())
+ return false;
+
+ switch (WantKind) {
+ case MK_Any: break;
+ case MK_ZeroArgSelector: return Sel.isUnarySelector();
+ case MK_OneArgSelector: return Sel.getNumArgs() == 1;
+ }
+
+ if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
+ return false;
+
+ for (unsigned I = 0; I != NumSelIdents; ++I)
+ if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
+ return false;
+
+ return true;
+}
+
+static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AllowSameLength = true) {
+ return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
+ NumSelIdents, AllowSameLength);
+}
+
+namespace {
+ /// \brief A set of selectors, which is used to avoid introducing multiple
+ /// completions with the same selector into the result set.
+ typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
+}
+
+/// \brief Add all of the Objective-C methods in the given Objective-C
+/// container to the set of results.
+///
+/// The container will be a class, protocol, category, or implementation of
+/// any of the above. This mether will recurse to include methods from
+/// the superclasses of classes along with their categories, protocols, and
+/// implementations.
+///
+/// \param Container the container in which we'll look to find methods.
+///
+/// \param WantInstance whether to add instance methods (only); if false, this
+/// routine will add factory methods (only).
+///
+/// \param CurContext the context in which we're performing the lookup that
+/// finds methods.
+///
+/// \param AllowSameLength Whether we allow a method to be added to the list
+/// when it has the same number of parameters as we have selector identifiers.
+///
+/// \param Results the structure into which we'll add results.
+static void AddObjCMethods(ObjCContainerDecl *Container,
+ bool WantInstanceMethods,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ DeclContext *CurContext,
+ VisitedSelectorSet &Selectors,
+ bool AllowSameLength,
+ ResultBuilder &Results,
+ bool InOriginalClass = true) {
+ typedef CodeCompletionResult Result;
+ for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+ MEnd = Container->meth_end();
+ M != MEnd; ++M) {
+ if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+ // Check whether the selector identifiers we've been given are a
+ // subset of the identifiers for this particular method.
+ if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
+ AllowSameLength))
+ continue;
+
+ if (!Selectors.insert((*M)->getSelector()))
+ continue;
+
+ Result R = Result(*M, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = (WantKind != MK_Any);
+ if (!InOriginalClass)
+ R.Priority += CCD_InBaseClass;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+
+ // Visit the protocols of protocols.
+ if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = Protocol->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
+ CurContext, Selectors, AllowSameLength, Results, false);
+ }
+
+ ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+ if (!IFace)
+ return;
+
+ // Add methods in protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
+ CurContext, Selectors, AllowSameLength, Results, false);
+
+ // Add methods in categories.
+ for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
+ CatDecl = CatDecl->getNextClassCategory()) {
+ AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Selectors, AllowSameLength,
+ Results, InOriginalClass);
+
+ // Add a categories protocol methods.
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Selectors, AllowSameLength,
+ Results, false);
+
+ // Add methods in category implementations.
+ if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
+ AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Selectors, AllowSameLength,
+ Results, InOriginalClass);
+ }
+
+ // Add methods in superclass.
+ if (IFace->getSuperClass())
+ AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
+ SelIdents, NumSelIdents, CurContext, Selectors,
+ AllowSameLength, Results, false);
+
+ // Add methods in our implementation, if any.
+ if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+ AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
+ NumSelIdents, CurContext, Selectors, AllowSameLength,
+ Results, InOriginalClass);
+}
+
+
+void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
+ typedef CodeCompletionResult Result;
+
+ // Try to find the interface where getters might live.
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
+ if (!Class) {
+ if (ObjCCategoryDecl *Category
+ = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
+ Class = Category->getClassInterface();
+
+ if (!Class)
+ return;
+ }
+
+ // Find all of the potential getters.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ VisitedSelectorSet Selectors;
+ AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
+ /*AllowSameLength=*/true, Results);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
+ typedef CodeCompletionResult Result;
+
+ // Try to find the interface where setters might live.
+ ObjCInterfaceDecl *Class
+ = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
+ if (!Class) {
+ if (ObjCCategoryDecl *Category
+ = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
+ Class = Category->getClassInterface();
+
+ if (!Class)
+ return;
+ }
+
+ // Find all of the potential getters.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ VisitedSelectorSet Selectors;
+ AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
+ Selectors, /*AllowSameLength=*/true, Results);
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+ bool IsParameter) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Type);
+ Results.EnterNewScope();
+
+ // Add context-sensitive, Objective-C parameter-passing keywords.
+ bool AddedInOut = false;
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
+ Results.AddResult("in");
+ Results.AddResult("inout");
+ AddedInOut = true;
+ }
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
+ Results.AddResult("out");
+ if (!AddedInOut)
+ Results.AddResult("inout");
+ }
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
+ ObjCDeclSpec::DQ_Oneway)) == 0) {
+ Results.AddResult("bycopy");
+ Results.AddResult("byref");
+ Results.AddResult("oneway");
+ }
+
+ // If we're completing the return type of an Objective-C method and the
+ // identifier IBAction refers to a macro, provide a completion item for
+ // an action, e.g.,
+ // IBAction)<#selector#>:(id)sender
+ if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
+ Context.Idents.get("IBAction").hasMacroDefinition()) {
+ typedef CodeCompletionString::Chunk Chunk;
+ CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
+ CXAvailability_Available);
+ Builder.AddTypedTextChunk("IBAction");
+ Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ Builder.AddPlaceholderChunk("selector");
+ Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
+ Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
+ Builder.AddTextChunk("id");
+ Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
+ Builder.AddTextChunk("sender");
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
+ }
+
+ // Add various builtin type names and specifiers.
+ AddOrdinaryNameResults(PCC_Type, S, *this, Results);
+ Results.ExitScope();
+
+ // Add the various type names
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Type,
+ Results.data(), Results.size());
+}
+
+/// \brief When we have an expression with type "id", we may assume
+/// that it has some more-specific class type based on knowledge of
+/// common uses of Objective-C. This routine returns that class type,
+/// or NULL if no better result could be determined.
+static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
+ ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
+ if (!Msg)
+ return 0;
+
+ Selector Sel = Msg->getSelector();
+ if (Sel.isNull())
+ return 0;
+
+ IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
+ if (!Id)
+ return 0;
+
+ ObjCMethodDecl *Method = Msg->getMethodDecl();
+ if (!Method)
+ return 0;
+
+ // Determine the class that we're sending the message to.
+ ObjCInterfaceDecl *IFace = 0;
+ switch (Msg->getReceiverKind()) {
+ case ObjCMessageExpr::Class:
+ if (const ObjCObjectType *ObjType
+ = Msg->getClassReceiver()->getAs<ObjCObjectType>())
+ IFace = ObjType->getInterface();
+ break;
+
+ case ObjCMessageExpr::Instance: {
+ QualType T = Msg->getInstanceReceiver()->getType();
+ if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
+ IFace = Ptr->getInterfaceDecl();
+ break;
+ }
+
+ case ObjCMessageExpr::SuperInstance:
+ case ObjCMessageExpr::SuperClass:
+ break;
+ }
+
+ if (!IFace)
+ return 0;
+
+ ObjCInterfaceDecl *Super = IFace->getSuperClass();
+ if (Method->isInstanceMethod())
+ return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
+ .Case("retain", IFace)
+ .Case("autorelease", IFace)
+ .Case("copy", IFace)
+ .Case("copyWithZone", IFace)
+ .Case("mutableCopy", IFace)
+ .Case("mutableCopyWithZone", IFace)
+ .Case("awakeFromCoder", IFace)
+ .Case("replacementObjectFromCoder", IFace)
+ .Case("class", IFace)
+ .Case("classForCoder", IFace)
+ .Case("superclass", Super)
+ .Default(0);
+
+ return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
+ .Case("new", IFace)
+ .Case("alloc", IFace)
+ .Case("allocWithZone", IFace)
+ .Case("class", IFace)
+ .Case("superclass", Super)
+ .Default(0);
+}
+
+// Add a special completion for a message send to "super", which fills in the
+// most likely case of forwarding all of our arguments to the superclass
+// function.
+///
+/// \param S The semantic analysis object.
+///
+/// \param S NeedSuperKeyword Whether we need to prefix this completion with
+/// the "super" keyword. Otherwise, we just need to provide the arguments.
+///
+/// \param SelIdents The identifiers in the selector that have already been
+/// provided as arguments for a send to "super".
+///
+/// \param NumSelIdents The number of identifiers in \p SelIdents.
+///
+/// \param Results The set of results to augment.
+///
+/// \returns the Objective-C method declaration that would be invoked by
+/// this "super" completion. If NULL, no completion was added.
+static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ ResultBuilder &Results) {
+ ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
+ if (!CurMethod)
+ return 0;
+
+ ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
+ if (!Class)
+ return 0;
+
+ // Try to find a superclass method with the same selector.
+ ObjCMethodDecl *SuperMethod = 0;
+ while ((Class = Class->getSuperClass()) && !SuperMethod) {
+ // Check in the class
+ SuperMethod = Class->getMethod(CurMethod->getSelector(),
+ CurMethod->isInstanceMethod());
+
+ // Check in categories or class extensions.
+ if (!SuperMethod) {
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
+ CurMethod->isInstanceMethod())))
+ break;
+ }
+ }
+
+ if (!SuperMethod)
+ return 0;
+
+ // Check whether the superclass method has the same signature.
+ if (CurMethod->param_size() != SuperMethod->param_size() ||
+ CurMethod->isVariadic() != SuperMethod->isVariadic())
+ return 0;
+
+ for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
+ CurPEnd = CurMethod->param_end(),
+ SuperP = SuperMethod->param_begin();
+ CurP != CurPEnd; ++CurP, ++SuperP) {
+ // Make sure the parameter types are compatible.
+ if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
+ (*SuperP)->getType()))
+ return 0;
+
+ // Make sure we have a parameter name to forward!
+ if (!(*CurP)->getIdentifier())
+ return 0;
+ }
+
+ // We have a superclass method. Now, form the send-to-super completion.
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ // Give this completion a return type.
+ AddResultTypeChunk(S.Context, SuperMethod, Builder);
+
+ // If we need the "super" keyword, add it (plus some spacing).
+ if (NeedSuperKeyword) {
+ Builder.AddTypedTextChunk("super");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ }
+
+ Selector Sel = CurMethod->getSelector();
+ if (Sel.isUnarySelector()) {
+ if (NeedSuperKeyword)
+ Builder.AddTextChunk(Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(0)));
+ else
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(0)));
+ } else {
+ ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
+ for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
+ if (I > NumSelIdents)
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+
+ if (I < NumSelIdents)
+ Builder.AddInformativeChunk(
+ Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(I) + ":"));
+ else if (NeedSuperKeyword || I > NumSelIdents) {
+ Builder.AddTextChunk(
+ Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(I) + ":"));
+ Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
+ (*CurP)->getIdentifier()->getName()));
+ } else {
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(I) + ":"));
+ Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
+ (*CurP)->getIdentifier()->getName()));
+ }
+ }
+ }
+
+ Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
+ SuperMethod->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl
+ : CXCursor_ObjCClassMethodDecl));
+ return SuperMethod;
+}
+
+void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_ObjCMessageReceiver,
+ &ResultBuilder::IsObjCMessageReceiver);
+
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.EnterNewScope();
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ // If we are in an Objective-C method inside a class that has a superclass,
+ // add "super" as an option.
+ if (ObjCMethodDecl *Method = getCurMethodDecl())
+ if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
+ if (Iface->getSuperClass()) {
+ Results.AddResult(Result("super"));
+
+ AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
+ }
+
+ Results.ExitScope();
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+
+}
+
+void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression) {
+ ObjCInterfaceDecl *CDecl = 0;
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+ // Figure out which interface we're in.
+ CDecl = CurMethod->getClassInterface();
+ if (!CDecl)
+ return;
+
+ // Find the superclass of this class.
+ CDecl = CDecl->getSuperClass();
+ if (!CDecl)
+ return;
+
+ if (CurMethod->isInstanceMethod()) {
+ // We are inside an instance method, which means that the message
+ // send [super ...] is actually calling an instance method on the
+ // current object.
+ return CodeCompleteObjCInstanceMessage(S, 0,
+ SelIdents, NumSelIdents,
+ AtArgumentExpression,
+ CDecl);
+ }
+
+ // Fall through to send to the superclass in CDecl.
+ } else {
+ // "super" may be the name of a type or variable. Figure out which
+ // it is.
+ IdentifierInfo *Super = &Context.Idents.get("super");
+ NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
+ LookupOrdinaryName);
+ if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
+ // "super" names an interface. Use it.
+ } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
+ if (const ObjCObjectType *Iface
+ = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
+ CDecl = Iface->getInterface();
+ } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
+ // "super" names an unresolved type; we can't be more specific.
+ } else {
+ // Assume that "super" names some kind of value and parse that way.
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(Super, SuperLoc);
+ ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
+ return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
+ SelIdents, NumSelIdents,
+ AtArgumentExpression);
+ }
+
+ // Fall through
+ }
+
+ ParsedType Receiver;
+ if (CDecl)
+ Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
+ return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
+ NumSelIdents, AtArgumentExpression,
+ /*IsSuper=*/true);
+}
+
+/// \brief Given a set of code-completion results for the argument of a message
+/// send, determine the preferred type (if any) for that argument expression.
+static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
+ unsigned NumSelIdents) {
+ typedef CodeCompletionResult Result;
+ ASTContext &Context = Results.getSema().Context;
+
+ QualType PreferredType;
+ unsigned BestPriority = CCP_Unlikely * 2;
+ Result *ResultsData = Results.data();
+ for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+ Result &R = ResultsData[I];
+ if (R.Kind == Result::RK_Declaration &&
+ isa<ObjCMethodDecl>(R.Declaration)) {
+ if (R.Priority <= BestPriority) {
+ ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
+ if (NumSelIdents <= Method->param_size()) {
+ QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
+ ->getType();
+ if (R.Priority < BestPriority || PreferredType.isNull()) {
+ BestPriority = R.Priority;
+ PreferredType = MyPreferredType;
+ } else if (!Context.hasSameUnqualifiedType(PreferredType,
+ MyPreferredType)) {
+ PreferredType = QualType();
+ }
+ }
+ }
+ }
+ }
+
+ return PreferredType;
+}
+
+static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
+ ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+ ObjCInterfaceDecl *CDecl = 0;
+
+ // If the given name refers to an interface type, retrieve the
+ // corresponding declaration.
+ if (Receiver) {
+ QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
+ if (!T.isNull())
+ if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
+ CDecl = Interface->getInterface();
+ }
+
+ // Add all of the factory methods in this Objective-C class, its protocols,
+ // superclasses, categories, implementation, etc.
+ Results.EnterNewScope();
+
+ // If this is a send-to-super, try to add the special "super" send
+ // completion.
+ if (IsSuper) {
+ if (ObjCMethodDecl *SuperMethod
+ = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
+ Results))
+ Results.Ignore(SuperMethod);
+ }
+
+ // If we're inside an Objective-C method definition, prefer its selector to
+ // others.
+ if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
+ Results.setPreferredSelector(CurMethod->getSelector());
+
+ VisitedSelectorSet Selectors;
+ if (CDecl)
+ AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
+ SemaRef.CurContext, Selectors, AtArgumentExpression,
+ Results);
+ else {
+ // We're messaging "id" as a type; provide all class/factory methods.
+
+ // If we have an external source, load the entire class method
+ // pool from the AST file.
+ if (SemaRef.ExternalSource) {
+ for (uint32_t I = 0,
+ N = SemaRef.ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
+ continue;
+
+ SemaRef.ReadMethodPool(Sel);
+ }
+ }
+
+ for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
+ MEnd = SemaRef.MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = &M->second.second;
+ MethList && MethList->Method;
+ MethList = MethList->Next) {
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
+ NumSelIdents))
+ continue;
+
+ Result R(MethList->Method, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = false;
+ Results.MaybeAddResult(R, SemaRef.CurContext);
+ }
+ }
+ }
+
+ Results.ExitScope();
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
+ AtArgumentExpression, IsSuper, Results);
+
+ // If we're actually at the argument expression (rather than prior to the
+ // selector), we're actually performing code completion for an expression.
+ // Determine whether we have a single, best method. If so, we can
+ // code-complete the expression using the corresponding parameter type as
+ // our preferred type, improving completion results.
+ if (AtArgumentExpression) {
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
+ NumSelIdents);
+ if (PreferredType.isNull())
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ else
+ CodeCompleteExpression(S, PreferredType);
+ return;
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool AtArgumentExpression,
+ ObjCInterfaceDecl *Super) {
+ typedef CodeCompletionResult Result;
+
+ Expr *RecExpr = static_cast<Expr *>(Receiver);
+
+ // If necessary, apply function/array conversion to the receiver.
+ // C99 6.7.5.3p[7,8].
+ if (RecExpr)
+ DefaultFunctionArrayLvalueConversion(RecExpr);
+ QualType ReceiverType = RecExpr? RecExpr->getType()
+ : Super? Context.getObjCObjectPointerType(
+ Context.getObjCInterfaceType(Super))
+ : Context.getObjCIdType();
+
+ // If we're messaging an expression with type "id" or "Class", check
+ // whether we know something special about the receiver that allows
+ // us to assume a more-specific receiver type.
+ if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
+ if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
+ if (ReceiverType->isObjCClassType())
+ return CodeCompleteObjCClassMessage(S,
+ ParsedType::make(Context.getObjCInterfaceType(IFace)),
+ SelIdents, NumSelIdents,
+ AtArgumentExpression, Super);
+
+ ReceiverType = Context.getObjCObjectPointerType(
+ Context.getObjCInterfaceType(IFace));
+ }
+
+ // Build the set of methods we can see.
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ // If this is a send-to-super, try to add the special "super" send
+ // completion.
+ if (Super) {
+ if (ObjCMethodDecl *SuperMethod
+ = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
+ Results))
+ Results.Ignore(SuperMethod);
+ }
+
+ // If we're inside an Objective-C method definition, prefer its selector to
+ // others.
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+ Results.setPreferredSelector(CurMethod->getSelector());
+
+ // Keep track of the selectors we've already added.
+ VisitedSelectorSet Selectors;
+
+ // Handle messages to Class. This really isn't a message to an instance
+ // method, so we treat it the same way we would treat a message send to a
+ // class method.
+ if (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType()) {
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
+ AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
+ CurContext, Selectors, AtArgumentExpression, Results);
+ }
+ }
+ // Handle messages to a qualified ID ("id<foo>").
+ else if (const ObjCObjectPointerType *QualID
+ = ReceiverType->getAsObjCQualifiedIdType()) {
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
+ E = QualID->qual_end();
+ I != E; ++I)
+ AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ Selectors, AtArgumentExpression, Results);
+ }
+ // Handle messages to a pointer to interface type.
+ else if (const ObjCObjectPointerType *IFacePtr
+ = ReceiverType->getAsObjCInterfacePointerType()) {
+ // Search the class, its superclasses, etc., for instance methods.
+ AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
+ NumSelIdents, CurContext, Selectors, AtArgumentExpression,
+ Results);
+
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
+ E = IFacePtr->qual_end();
+ I != E; ++I)
+ AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
+ Selectors, AtArgumentExpression, Results);
+ }
+ // Handle messages to "id".
+ else if (ReceiverType->isObjCIdType()) {
+ // We're messaging "id", so provide all instance methods we know
+ // about as code-completion results.
+
+ // If we have an external source, load the entire class method
+ // pool from the AST file.
+ if (ExternalSource) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || MethodPool.count(Sel))
+ continue;
+
+ ReadMethodPool(Sel);
+ }
+ }
+
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = &M->second.first;
+ MethList && MethList->Method;
+ MethList = MethList->Next) {
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
+ NumSelIdents))
+ continue;
+
+ if (!Selectors.insert(MethList->Method->getSelector()))
+ continue;
+
+ Result R(MethList->Method, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = false;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+ }
+ Results.ExitScope();
+
+
+ // If we're actually at the argument expression (rather than prior to the
+ // selector), we're actually performing code completion for an expression.
+ // Determine whether we have a single, best method. If so, we can
+ // code-complete the expression using the corresponding parameter type as
+ // our preferred type, improving completion results.
+ if (AtArgumentExpression) {
+ QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
+ NumSelIdents);
+ if (PreferredType.isNull())
+ CodeCompleteOrdinaryName(S, PCC_Expression);
+ else
+ CodeCompleteExpression(S, PreferredType);
+ return;
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar) {
+ CodeCompleteExpressionData Data;
+ Data.ObjCCollection = true;
+
+ if (IterationVar.getAsOpaquePtr()) {
+ DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+ for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
+ if (*I)
+ Data.IgnoreDecls.push_back(*I);
+ }
+ }
+
+ CodeCompleteExpression(S, Data);
+}
+
+void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ // If we have an external source, load the entire class method
+ // pool from the AST file.
+ if (ExternalSource) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || MethodPool.count(Sel))
+ continue;
+
+ ReadMethodPool(Sel);
+ }
+ }
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_SelectorName);
+ Results.EnterNewScope();
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+
+ Selector Sel = M->first;
+ if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
+ continue;
+
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ if (Sel.isUnarySelector()) {
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(0)));
+ Results.AddResult(Builder.TakeString());
+ continue;
+ }
+
+ std::string Accumulator;
+ for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
+ if (I == NumSelIdents) {
+ if (!Accumulator.empty()) {
+ Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
+ Accumulator));
+ Accumulator.clear();
+ }
+ }
+
+ Accumulator += Sel.getNameForSlot(I).str();
+ Accumulator += ':';
+ }
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
+ Results.AddResult(Builder.TakeString());
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_SelectorName,
+ Results.data(), Results.size());
+}
+
+/// \brief Add all of the protocol declarations that we find in the given
+/// (translation unit) context.
+static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
+ bool OnlyForwardDeclarations,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+
+ for (DeclContext::decl_iterator D = Ctx->decls_begin(),
+ DEnd = Ctx->decls_end();
+ D != DEnd; ++D) {
+ // Record any protocols we find.
+ if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
+ if (!OnlyForwardDeclarations || Proto->isForwardDecl())
+ Results.AddResult(Result(Proto, 0), CurContext, 0, false);
+
+ // Record any forward-declared protocols we find.
+ if (ObjCForwardProtocolDecl *Forward
+ = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
+ for (ObjCForwardProtocolDecl::protocol_iterator
+ P = Forward->protocol_begin(),
+ PEnd = Forward->protocol_end();
+ P != PEnd; ++P)
+ if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
+ Results.AddResult(Result(*P, 0), CurContext, 0, false);
+ }
+ }
+}
+
+void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_ObjCProtocolName);
+
+ if (CodeCompleter && CodeCompleter->includeGlobals()) {
+ Results.EnterNewScope();
+
+ // Tell the result set to ignore all of the protocols we have
+ // already seen.
+ // FIXME: This doesn't work when caching code-completion results.
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
+ Protocols[I].second))
+ Results.Ignore(Protocol);
+
+ // Add all protocols.
+ AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
+ Results);
+
+ Results.ExitScope();
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_ObjCProtocolName,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_ObjCProtocolName);
+
+ if (CodeCompleter && CodeCompleter->includeGlobals()) {
+ Results.EnterNewScope();
+
+ // Add all protocols.
+ AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
+ Results);
+
+ Results.ExitScope();
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_ObjCProtocolName,
+ Results.data(),Results.size());
+}
+
+/// \brief Add all of the Objective-C interface declarations that we find in
+/// the given (translation unit) context.
+static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
+ bool OnlyForwardDeclarations,
+ bool OnlyUnimplemented,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+
+ for (DeclContext::decl_iterator D = Ctx->decls_begin(),
+ DEnd = Ctx->decls_end();
+ D != DEnd; ++D) {
+ // Record any interfaces we find.
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
+ if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
+ (!OnlyUnimplemented || !Class->getImplementation()))
+ Results.AddResult(Result(Class, 0), CurContext, 0, false);
+
+ // Record any forward-declared interfaces we find.
+ if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
+ for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
+ C != CEnd; ++C)
+ if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
+ (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
+ Results.AddResult(Result(C->getInterface(), 0), CurContext,
+ 0, false);
+ }
+ }
+}
+
+void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ // Add all classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
+ false, Results);
+
+ Results.ExitScope();
+ // FIXME: Add a special context for this, use cached global completion
+ // results.
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ // Make sure that we ignore the class we're currently defining.
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
+ Results.Ignore(CurClass);
+
+ // Add all classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+ false, Results);
+
+ Results.ExitScope();
+ // FIXME: Add a special context for this, use cached global completion
+ // results.
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+
+ // Add all unimplemented classes.
+ AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+ true, Results);
+
+ Results.ExitScope();
+ // FIXME: Add a special context for this, use cached global completion
+ // results.
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc) {
+ typedef CodeCompletionResult Result;
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+
+ // Ignore any categories we find that have already been implemented by this
+ // interface.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ CategoryNames.insert(Category->getIdentifier());
+
+ // Add all of the categories we know about.
+ Results.EnterNewScope();
+ TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ for (DeclContext::decl_iterator D = TU->decls_begin(),
+ DEnd = TU->decls_end();
+ D != DEnd; ++D)
+ if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+ if (CategoryNames.insert(Category->getIdentifier()))
+ Results.AddResult(Result(Category, 0), CurContext, 0, false);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc) {
+ typedef CodeCompletionResult Result;
+
+ // Find the corresponding interface. If we couldn't find the interface, the
+ // program itself is ill-formed. However, we'll try to be helpful still by
+ // providing the list of all of the categories we know about.
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
+ if (!Class)
+ return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
+
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+
+ // Add all of the categories that have have corresponding interface
+ // declarations in this class and any of its superclasses, except for
+ // already-implemented categories in the class itself.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ Results.EnterNewScope();
+ bool IgnoreImplemented = true;
+ while (Class) {
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ if ((!IgnoreImplemented || !Category->getImplementation()) &&
+ CategoryNames.insert(Category->getIdentifier()))
+ Results.AddResult(Result(Category, 0), CurContext, 0, false);
+
+ Class = Class->getSuperClass();
+ IgnoreImplemented = false;
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Ignore any properties that have already been implemented.
+ for (DeclContext::decl_iterator D = Container->decls_begin(),
+ DEnd = Container->decls_end();
+ D != DEnd; ++D)
+ if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+ Results.Ignore(PropertyImpl->getPropertyDecl());
+
+ // Add any properties that we find.
+ AddedPropertiesSet AddedProperties;
+ Results.EnterNewScope();
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
+ AddedProperties, Results);
+ else
+ AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+ false, CurContext, AddedProperties, Results);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ Decl *ObjCImpDecl) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Figure out which interface we're looking into.
+ ObjCInterfaceDecl *Class = 0;
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ Class = ClassImpl->getClassInterface();
+ else
+ Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
+ ->getClassInterface();
+
+ // Add all of the instance variables in this class and its superclasses.
+ Results.EnterNewScope();
+ for(; Class; Class = Class->getSuperClass()) {
+ // FIXME: We could screen the type of each ivar for compatibility with
+ // the property, but is that being too paternal?
+ for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+ IVarEnd = Class->ivar_end();
+ IVar != IVarEnd; ++IVar)
+ Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+// Mapping from selectors to the methods that implement that selector, along
+// with the "in original class" flag.
+typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
+ KnownMethodsMap;
+
+/// \brief Find all of the methods that reside in the given container
+/// (and its superclasses, protocols, etc.) that meet the given
+/// criteria. Insert those methods into the map of known methods,
+/// indexed by selector so they can be easily found.
+static void FindImplementableMethods(ASTContext &Context,
+ ObjCContainerDecl *Container,
+ bool WantInstanceMethods,
+ QualType ReturnType,
+ KnownMethodsMap &KnownMethods,
+ bool InOriginalClass = true) {
+ if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
+ // Recurse into protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = IFace->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+ KnownMethods, InOriginalClass);
+
+ // Add methods from any class extensions and categories.
+ for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
+ Cat = Cat->getNextClassCategory())
+ FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
+ WantInstanceMethods, ReturnType,
+ KnownMethods, false);
+
+ // Visit the superclass.
+ if (IFace->getSuperClass())
+ FindImplementableMethods(Context, IFace->getSuperClass(),
+ WantInstanceMethods, ReturnType,
+ KnownMethods, false);
+ }
+
+ if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+ // Recurse into protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = Category->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+ KnownMethods, InOriginalClass);
+
+ // If this category is the original class, jump to the interface.
+ if (InOriginalClass && Category->getClassInterface())
+ FindImplementableMethods(Context, Category->getClassInterface(),
+ WantInstanceMethods, ReturnType, KnownMethods,
+ false);
+ }
+
+ if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+ // Recurse into protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols
+ = Protocol->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end();
+ I != E; ++I)
+ FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+ KnownMethods, false);
+ }
+
+ // Add methods in this container. This operation occurs last because
+ // we want the methods from this container to override any methods
+ // we've previously seen with the same selector.
+ for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+ MEnd = Container->meth_end();
+ M != MEnd; ++M) {
+ if ((*M)->isInstanceMethod() == WantInstanceMethods) {
+ if (!ReturnType.isNull() &&
+ !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
+ continue;
+
+ KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
+ }
+ }
+}
+
+/// \brief Add the parenthesized return or parameter type chunk to a code
+/// completion string.
+static void AddObjCPassingTypeChunk(QualType Type,
+ ASTContext &Context,
+ CodeCompletionBuilder &Builder) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk(GetCompletionTypeString(Type, Context,
+ Builder.getAllocator()));
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+}
+
+/// \brief Determine whether the given class is or inherits from a class by
+/// the given name.
+static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
+ llvm::StringRef Name) {
+ if (!Class)
+ return false;
+
+ if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
+ return true;
+
+ return InheritsFromClassNamed(Class->getSuperClass(), Name);
+}
+
+/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
+/// Key-Value Observing (KVO).
+static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
+ bool IsInstanceMethod,
+ QualType ReturnType,
+ ASTContext &Context,
+ const KnownMethodsMap &KnownMethods,
+ ResultBuilder &Results) {
+ IdentifierInfo *PropName = Property->getIdentifier();
+ if (!PropName || PropName->getLength() == 0)
+ return;
+
+
+ // Builder that will create each code completion.
+ typedef CodeCompletionResult Result;
+ CodeCompletionAllocator &Allocator = Results.getAllocator();
+ CodeCompletionBuilder Builder(Allocator);
+
+ // The selector table.
+ SelectorTable &Selectors = Context.Selectors;
+
+ // The property name, copied into the code completion allocation region
+ // on demand.
+ struct KeyHolder {
+ CodeCompletionAllocator &Allocator;
+ llvm::StringRef Key;
+ const char *CopiedKey;
+
+ KeyHolder(CodeCompletionAllocator &Allocator, llvm::StringRef Key)
+ : Allocator(Allocator), Key(Key), CopiedKey(0) { }
+
+ operator const char *() {
+ if (CopiedKey)
+ return CopiedKey;
+
+ return CopiedKey = Allocator.CopyString(Key);
+ }
+ } Key(Allocator, PropName->getName());
+
+ // The uppercased name of the property name.
+ std::string UpperKey = PropName->getName();
+ if (!UpperKey.empty())
+ UpperKey[0] = toupper(UpperKey[0]);
+
+ bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
+ Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
+ Property->getType());
+ bool ReturnTypeMatchesVoid
+ = ReturnType.isNull() || ReturnType->isVoidType();
+
+ // Add the normal accessor -(type)key.
+ if (IsInstanceMethod &&
+ !KnownMethods.count(Selectors.getNullarySelector(PropName)) &&
+ ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
+ if (ReturnType.isNull())
+ AddObjCPassingTypeChunk(Property->getType(), Context, Builder);
+
+ Builder.AddTypedTextChunk(Key);
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+
+ // If we have an integral or boolean property (or the user has provided
+ // an integral or boolean return type), add the accessor -(type)isKey.
+ if (IsInstanceMethod &&
+ ((!ReturnType.isNull() &&
+ (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
+ (ReturnType.isNull() &&
+ (Property->getType()->isIntegerType() ||
+ Property->getType()->isBooleanType())))) {
+ std::string SelectorName = (llvm::Twine("is") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("BOOL");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(
+ Allocator.CopyString(SelectorId->getName()));
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Add the normal mutator.
+ if (IsInstanceMethod && ReturnTypeMatchesVoid &&
+ !Property->getSetterMethodDecl()) {
+ std::string SelectorName = (llvm::Twine("set") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(
+ Allocator.CopyString(SelectorId->getName()));
+ Builder.AddTypedTextChunk(":");
+ AddObjCPassingTypeChunk(Property->getType(), Context, Builder);
+ Builder.AddTextChunk(Key);
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Indexed and unordered accessors
+ unsigned IndexedGetterPriority = CCP_CodePattern;
+ unsigned IndexedSetterPriority = CCP_CodePattern;
+ unsigned UnorderedGetterPriority = CCP_CodePattern;
+ unsigned UnorderedSetterPriority = CCP_CodePattern;
+ if (const ObjCObjectPointerType *ObjCPointer
+ = Property->getType()->getAs<ObjCObjectPointerType>()) {
+ if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
+ // If this interface type is not provably derived from a known
+ // collection, penalize the corresponding completions.
+ if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
+ IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
+ if (!InheritsFromClassNamed(IFace, "NSArray"))
+ IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
+ }
+
+ if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
+ UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
+ if (!InheritsFromClassNamed(IFace, "NSSet"))
+ UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
+ }
+ }
+ } else {
+ IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
+ IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
+ UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
+ UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
+ }
+
+ // Add -(NSUInteger)countOf<key>
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() || ReturnType->isIntegerType())) {
+ std::string SelectorName = (llvm::Twine("countOf") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSUInteger");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(
+ Allocator.CopyString(SelectorId->getName()));
+ Results.AddResult(Result(Builder.TakeString(),
+ std::min(IndexedGetterPriority,
+ UnorderedGetterPriority),
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Indexed getters
+ // Add -(id)objectInKeyAtIndex:(NSUInteger)index
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
+ std::string SelectorName
+ = (llvm::Twine("objectIn") + UpperKey + "AtIndex").str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("id");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSUInteger");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("index");
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() ||
+ (ReturnType->isObjCObjectPointerType() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+ ->getName() == "NSArray"))) {
+ std::string SelectorName
+ = (llvm::Twine(Property->getName()) + "AtIndexes").str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSArray *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSIndexSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("indexes");
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("get") + UpperKey).str();
+ IdentifierInfo *SelectorIds[2] = {
+ &Context.Idents.get(SelectorName),
+ &Context.Idents.get("range")
+ };
+
+ if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" **");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("buffer");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk("range:");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSRange");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("inRange");
+ Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Mutable indexed accessors
+
+ // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("in") + UpperKey + "AtIndex").str();
+ IdentifierInfo *SelectorIds[2] = {
+ &Context.Idents.get("insertObject"),
+ &Context.Idents.get(SelectorName)
+ };
+
+ if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk("insertObject:");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("object");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("NSUInteger");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("index");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("insert") + UpperKey).str();
+ IdentifierInfo *SelectorIds[2] = {
+ &Context.Idents.get(SelectorName),
+ &Context.Idents.get("atIndexes")
+ };
+
+ if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSArray *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("array");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk("atIndexes:");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("NSIndexSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("indexes");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName
+ = (llvm::Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSUInteger");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("index");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName
+ = (llvm::Twine("remove") + UpperKey + "AtIndexes").str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSIndexSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("indexes");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName
+ = (llvm::Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
+ IdentifierInfo *SelectorIds[2] = {
+ &Context.Idents.get(SelectorName),
+ &Context.Idents.get("withObject")
+ };
+
+ if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("NSUInteger");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("index");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk("withObject:");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("id");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("object");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName1
+ = (llvm::Twine("replace") + UpperKey + "AtIndexes").str();
+ std::string SelectorName2 = (llvm::Twine("with") + UpperKey).str();
+ IdentifierInfo *SelectorIds[2] = {
+ &Context.Idents.get(SelectorName1),
+ &Context.Idents.get(SelectorName2)
+ };
+
+ if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("NSIndexSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("indexes");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSArray *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("array");
+ Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Unordered getters
+ // - (NSEnumerator *)enumeratorOfKey
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() ||
+ (ReturnType->isObjCObjectPointerType() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+ ->getName() == "NSEnumerator"))) {
+ std::string SelectorName = (llvm::Twine("enumeratorOf") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSEnumerator *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (type *)memberOfKey:(type *)object
+ if (IsInstanceMethod &&
+ (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
+ std::string SelectorName = (llvm::Twine("memberOf") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ if (ReturnType.isNull()) {
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" *");
+ } else {
+ Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
+ Builder.getAllocator()));
+ }
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("object");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Mutable unordered accessors
+ // - (void)addKeyObject:(type *)object
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName
+ = (llvm::Twine("add") + UpperKey + llvm::Twine("Object")).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("object");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)addKey:(NSSet *)objects
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("add") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("objects");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)removeKeyObject:(type *)object
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName
+ = (llvm::Twine("remove") + UpperKey + llvm::Twine("Object")).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("object-type");
+ Builder.AddTextChunk(" *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("object");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)removeKey:(NSSet *)objects
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("remove") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("objects");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // - (void)intersectKey:(NSSet *)objects
+ if (IsInstanceMethod && ReturnTypeMatchesVoid) {
+ std::string SelectorName = (llvm::Twine("intersect") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("void");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Builder.AddTextChunk("objects");
+ Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+
+ // Key-Value Observing
+ // + (NSSet *)keyPathsForValuesAffectingKey
+ if (!IsInstanceMethod &&
+ (ReturnType.isNull() ||
+ (ReturnType->isObjCObjectPointerType() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
+ ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
+ ->getName() == "NSSet"))) {
+ std::string SelectorName
+ = (llvm::Twine("keyPathsForValuesAffecting") + UpperKey).str();
+ IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
+ if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
+ if (ReturnType.isNull()) {
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddTextChunk("NSSet *");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ }
+
+ Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
+ Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
+ CXCursor_ObjCInstanceMethodDecl));
+ }
+ }
+}
+
+void Sema::CodeCompleteObjCMethodDecl(Scope *S,
+ bool IsInstanceMethod,
+ ParsedType ReturnTy,
+ Decl *IDecl) {
+ // Determine the return type of the method we're declaring, if
+ // provided.
+ QualType ReturnType = GetTypeFromParser(ReturnTy);
+
+ // Determine where we should start searching for methods.
+ ObjCContainerDecl *SearchDecl = 0;
+ bool IsInImplementation = false;
+ if (Decl *D = IDecl) {
+ if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
+ SearchDecl = Impl->getClassInterface();
+ IsInImplementation = true;
+ } else if (ObjCCategoryImplDecl *CatImpl
+ = dyn_cast<ObjCCategoryImplDecl>(D)) {
+ SearchDecl = CatImpl->getCategoryDecl();
+ IsInImplementation = true;
+ } else
+ SearchDecl = dyn_cast<ObjCContainerDecl>(D);
+ }
+
+ if (!SearchDecl && S) {
+ if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
+ SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
+ }
+
+ if (!SearchDecl) {
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ 0, 0);
+ return;
+ }
+
+ // Find all of the methods that we could declare/implement here.
+ KnownMethodsMap KnownMethods;
+ FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
+ ReturnType, KnownMethods);
+
+ // Add declarations or definitions for each of the known methods.
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+ Results.EnterNewScope();
+ PrintingPolicy Policy(Context.PrintingPolicy);
+ Policy.AnonymousTagLocations = false;
+ for (KnownMethodsMap::iterator M = KnownMethods.begin(),
+ MEnd = KnownMethods.end();
+ M != MEnd; ++M) {
+ ObjCMethodDecl *Method = M->second.first;
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
+ // If the result type was not already provided, add it to the
+ // pattern as (type).
+ if (ReturnType.isNull())
+ AddObjCPassingTypeChunk(Method->getResultType(), Context, Builder);
+
+ Selector Sel = Method->getSelector();
+
+ // Add the first part of the selector to the pattern.
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ Sel.getNameForSlot(0)));
+
+ // Add parameters to the pattern.
+ unsigned I = 0;
+ for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; (void)++P, ++I) {
+ // Add the part of the selector name.
+ if (I == 0)
+ Builder.AddTypedTextChunk(":");
+ else if (I < Sel.getNumArgs()) {
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTypedTextChunk(
+ Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
+ } else
+ break;
+
+ // Add the parameter type.
+ AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Builder);
+
+ if (IdentifierInfo *Id = (*P)->getIdentifier())
+ Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
+ }
+
+ if (Method->isVariadic()) {
+ if (Method->param_size() > 0)
+ Builder.AddChunk(CodeCompletionString::CK_Comma);
+ Builder.AddTextChunk("...");
+ }
+
+ if (IsInImplementation && Results.includeCodePatterns()) {
+ // We will be defining the method here, so add a compound statement.
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ if (!Method->getResultType()->isVoidType()) {
+ // If the result type is not void, add a return clause.
+ Builder.AddTextChunk("return");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_SemiColon);
+ } else
+ Builder.AddPlaceholderChunk("statements");
+
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ }
+
+ unsigned Priority = CCP_CodePattern;
+ if (!M->second.second)
+ Priority += CCD_InBaseClass;
+
+ Results.AddResult(Result(Builder.TakeString(), Priority,
+ Method->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl
+ : CXCursor_ObjCClassMethodDecl));
+ }
+
+ // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
+ // the properties in this class and its categories.
+ if (Context.getLangOptions().ObjC2) {
+ llvm::SmallVector<ObjCContainerDecl *, 4> Containers;
+ Containers.push_back(SearchDecl);
+
+ ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
+ if (!IFace)
+ if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
+ IFace = Category->getClassInterface();
+
+ if (IFace) {
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ Containers.push_back(Category);
+ }
+
+ for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
+ for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
+ PEnd = Containers[I]->prop_end();
+ P != PEnd; ++P) {
+ AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
+ KnownMethods, Results);
+ }
+ }
+ }
+
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnTy,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ // If we have an external source, load the entire class method
+ // pool from the AST file.
+ if (ExternalSource) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || MethodPool.count(Sel))
+ continue;
+
+ ReadMethodPool(Sel);
+ }
+ }
+
+ // Build the set of methods we can see.
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_Other);
+
+ if (ReturnTy)
+ Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
+
+ Results.EnterNewScope();
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
+ &M->second.second;
+ MethList && MethList->Method;
+ MethList = MethList->Next) {
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
+ NumSelIdents))
+ continue;
+
+ if (AtParameterName) {
+ // Suggest parameter names we've seen before.
+ if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
+ ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
+ if (Param->getIdentifier()) {
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ Param->getIdentifier()->getName()));
+ Results.AddResult(Builder.TakeString());
+ }
+ }
+
+ continue;
+ }
+
+ Result R(MethList->Method, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = false;
+ R.DeclaringEntity = true;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_PreprocessorDirective);
+ Results.EnterNewScope();
+
+ // #if <condition>
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Builder.AddTypedTextChunk("if");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("condition");
+ Results.AddResult(Builder.TakeString());
+
+ // #ifdef <macro>
+ Builder.AddTypedTextChunk("ifdef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
+ // #ifndef <macro>
+ Builder.AddTypedTextChunk("ifndef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
+ if (InConditional) {
+ // #elif <condition>
+ Builder.AddTypedTextChunk("elif");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("condition");
+ Results.AddResult(Builder.TakeString());
+
+ // #else
+ Builder.AddTypedTextChunk("else");
+ Results.AddResult(Builder.TakeString());
+
+ // #endif
+ Builder.AddTypedTextChunk("endif");
+ Results.AddResult(Builder.TakeString());
+ }
+
+ // #include "header"
+ Builder.AddTypedTextChunk("include");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("\"");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk("\"");
+ Results.AddResult(Builder.TakeString());
+
+ // #include <header>
+ Builder.AddTypedTextChunk("include");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("<");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk(">");
+ Results.AddResult(Builder.TakeString());
+
+ // #define <macro>
+ Builder.AddTypedTextChunk("define");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
+ // #define <macro>(<args>)
+ Builder.AddTypedTextChunk("define");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("args");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Builder.TakeString());
+
+ // #undef <macro>
+ Builder.AddTypedTextChunk("undef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
+ // #line <number>
+ Builder.AddTypedTextChunk("line");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("number");
+ Results.AddResult(Builder.TakeString());
+
+ // #line <number> "filename"
+ Builder.AddTypedTextChunk("line");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("number");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("\"");
+ Builder.AddPlaceholderChunk("filename");
+ Builder.AddTextChunk("\"");
+ Results.AddResult(Builder.TakeString());
+
+ // #error <message>
+ Builder.AddTypedTextChunk("error");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("message");
+ Results.AddResult(Builder.TakeString());
+
+ // #pragma <arguments>
+ Builder.AddTypedTextChunk("pragma");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("arguments");
+ Results.AddResult(Builder.TakeString());
+
+ if (getLangOptions().ObjC1) {
+ // #import "header"
+ Builder.AddTypedTextChunk("import");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("\"");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk("\"");
+ Results.AddResult(Builder.TakeString());
+
+ // #import <header>
+ Builder.AddTypedTextChunk("import");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("<");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk(">");
+ Results.AddResult(Builder.TakeString());
+ }
+
+ // #include_next "header"
+ Builder.AddTypedTextChunk("include_next");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("\"");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk("\"");
+ Results.AddResult(Builder.TakeString());
+
+ // #include_next <header>
+ Builder.AddTypedTextChunk("include_next");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("<");
+ Builder.AddPlaceholderChunk("header");
+ Builder.AddTextChunk(">");
+ Results.AddResult(Builder.TakeString());
+
+ // #warning <message>
+ Builder.AddTypedTextChunk("warning");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("message");
+ Results.AddResult(Builder.TakeString());
+
+ // Note: #ident and #sccs are such crazy anachronisms that we don't provide
+ // completions for them. And __include_macros is a Clang-internal extension
+ // that we don't want to encourage anyone to use.
+
+ // FIXME: we don't support #assert or #unassert, so don't suggest them.
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_PreprocessorDirective,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
+ CodeCompleteOrdinaryName(S,
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
+ : Sema::PCC_Namespace);
+}
+
+void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ IsDefinition? CodeCompletionContext::CCC_MacroName
+ : CodeCompletionContext::CCC_MacroNameUse);
+ if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
+ // Add just the names of macros, not their arguments.
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Results.EnterNewScope();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ MEnd = PP.macro_end();
+ M != MEnd; ++M) {
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
+ M->first->getName()));
+ Results.AddResult(Builder.TakeString());
+ }
+ Results.ExitScope();
+ } else if (IsDefinition) {
+ // FIXME: Can we detect when the user just wrote an include guard above?
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompletePreprocessorExpression() {
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompletionContext::CCC_PreprocessorExpression);
+
+ if (!CodeCompleter || CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+
+ // defined (<macro>)
+ Results.EnterNewScope();
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Builder.AddTypedTextChunk("defined");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("macro");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Builder.TakeString());
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_PreprocessorExpression,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
+ IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned Argument) {
+ // FIXME: In the future, we could provide "overload" results, much like we
+ // do for function calls.
+
+ CodeCompleteOrdinaryName(S,
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
+ : Sema::PCC_Namespace);
+}
+
+void Sema::CodeCompleteNaturalLanguage() {
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_NaturalLanguage,
+ 0, 0);
+}
+
+void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
+ llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
+ ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
+ if (!CodeCompleter || CodeCompleter->includeGlobals()) {
+ CodeCompletionDeclConsumer Consumer(Builder,
+ Context.getTranslationUnitDecl());
+ LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
+ Consumer);
+ }
+
+ if (!CodeCompleter || CodeCompleter->includeMacros())
+ AddMacroResults(PP, Builder);
+
+ Results.clear();
+ Results.insert(Results.end(),
+ Builder.data(), Builder.data() + Builder.size());
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
new file mode 100644
index 0000000..dd30c12
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -0,0 +1,7985 @@
+//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/Triple.h"
+#include <algorithm>
+#include <cstring>
+#include <functional>
+using namespace clang;
+using namespace sema;
+
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) {
+ return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
+}
+
+/// \brief If the identifier refers to a type name within this scope,
+/// return the declaration of that type.
+///
+/// This routine performs ordinary name lookup of the identifier II
+/// within the given scope, with optional C++ scope specifier SS, to
+/// determine whether the name refers to a type. If so, returns an
+/// opaque pointer (actually a QualType) corresponding to that
+/// type. Otherwise, returns NULL.
+///
+/// If name lookup results in an ambiguity, this routine will complain
+/// and then return NULL.
+ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS,
+ bool isClassName, bool HasTrailingDot,
+ ParsedType ObjectTypePtr) {
+ // Determine where we will perform name lookup.
+ DeclContext *LookupCtx = 0;
+ if (ObjectTypePtr) {
+ QualType ObjectType = ObjectTypePtr.get();
+ if (ObjectType->isRecordType())
+ LookupCtx = computeDeclContext(ObjectType);
+ } else if (SS && SS->isNotEmpty()) {
+ LookupCtx = computeDeclContext(*SS, false);
+
+ if (!LookupCtx) {
+ if (isDependentScopeSpecifier(*SS)) {
+ // C++ [temp.res]p3:
+ // A qualified-id that refers to a type and in which the
+ // nested-name-specifier depends on a template-parameter (14.6.2)
+ // shall be prefixed by the keyword typename to indicate that the
+ // qualified-id denotes a type, forming an
+ // elaborated-type-specifier (7.1.5.3).
+ //
+ // We therefore do not perform any name lookup if the result would
+ // refer to a member of an unknown specialization.
+ if (!isClassName)
+ return ParsedType();
+
+ // We know from the grammar that this name refers to a type,
+ // so build a dependent node to describe the type.
+ QualType T =
+ CheckTypenameType(ETK_None, SS->getScopeRep(), II,
+ SourceLocation(), SS->getRange(), NameLoc);
+ return ParsedType::make(T);
+ }
+
+ return ParsedType();
+ }
+
+ if (!LookupCtx->isDependentContext() &&
+ RequireCompleteDeclContext(*SS, LookupCtx))
+ return ParsedType();
+ }
+
+ // FIXME: LookupNestedNameSpecifierName isn't the right kind of
+ // lookup for class-names.
+ LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
+ LookupOrdinaryName;
+ LookupResult Result(*this, &II, NameLoc, Kind);
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+ LookupQualifiedName(Result, LookupCtx);
+
+ if (ObjectTypePtr && Result.empty()) {
+ // C++ [basic.lookup.classref]p3:
+ // If the unqualified-id is ~type-name, the type-name is looked up
+ // in the context of the entire postfix-expression. If the type T of
+ // the object expression is of a class type C, the type-name is also
+ // looked up in the scope of class C. At least one of the lookups shall
+ // find a name that refers to (possibly cv-qualified) T.
+ LookupName(Result, S);
+ }
+ } else {
+ // Perform unqualified name lookup.
+ LookupName(Result, S);
+ }
+
+ NamedDecl *IIDecl = 0;
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ Result.suppressDiagnostics();
+ return ParsedType();
+
+ case LookupResult::Ambiguous:
+ // Recover from type-hiding ambiguities by hiding the type. We'll
+ // do the lookup again when looking for an object, and we can
+ // diagnose the error then. If we don't do this, then the error
+ // about hiding the type will be immediately followed by an error
+ // that only makes sense if the identifier was treated like a type.
+ if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
+ Result.suppressDiagnostics();
+ return ParsedType();
+ }
+
+ // Look to see if we have a type anywhere in the list of results.
+ for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
+ Res != ResEnd; ++Res) {
+ if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
+ if (!IIDecl ||
+ (*Res)->getLocation().getRawEncoding() <
+ IIDecl->getLocation().getRawEncoding())
+ IIDecl = *Res;
+ }
+ }
+
+ if (!IIDecl) {
+ // None of the entities we found is a type, so there is no way
+ // to even assume that the result is a type. In this case, don't
+ // complain about the ambiguity. The parser will either try to
+ // perform this lookup again (e.g., as an object name), which
+ // will produce the ambiguity, or will complain that it expected
+ // a type name.
+ Result.suppressDiagnostics();
+ return ParsedType();
+ }
+
+ // We found a type within the ambiguous lookup; diagnose the
+ // ambiguity and then return that type. This might be the right
+ // answer, or it might not be, but it suppresses any attempt to
+ // perform the name lookup again.
+ break;
+
+ case LookupResult::Found:
+ IIDecl = Result.getFoundDecl();
+ break;
+ }
+
+ assert(IIDecl && "Didn't find decl");
+
+ QualType T;
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
+ DiagnoseUseOfDecl(IIDecl, NameLoc);
+
+ if (T.isNull())
+ T = Context.getTypeDeclType(TD);
+
+ if (SS)
+ T = getElaboratedType(ETK_None, *SS, T);
+
+ } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ if (!HasTrailingDot)
+ T = Context.getObjCInterfaceType(IDecl);
+ }
+
+ if (T.isNull()) {
+ // If it's not plausibly a type, suppress diagnostics.
+ Result.suppressDiagnostics();
+ return ParsedType();
+ }
+ return ParsedType::make(T);
+}
+
+/// isTagName() - This method is called *for error recovery purposes only*
+/// to determine if the specified name is a valid tag name ("struct foo"). If
+/// so, this returns the TST for the tag corresponding to it (TST_enum,
+/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C
+/// where the user forgot to specify the tag.
+DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
+ // Do a tag name lookup in this scope.
+ LookupResult R(*this, &II, SourceLocation(), LookupTagName);
+ LookupName(R, S, false);
+ R.suppressDiagnostics();
+ if (R.getResultKind() == LookupResult::Found)
+ if (const TagDecl *TD = R.getAsSingle<TagDecl>()) {
+ switch (TD->getTagKind()) {
+ default: return DeclSpec::TST_unspecified;
+ case TTK_Struct: return DeclSpec::TST_struct;
+ case TTK_Union: return DeclSpec::TST_union;
+ case TTK_Class: return DeclSpec::TST_class;
+ case TTK_Enum: return DeclSpec::TST_enum;
+ }
+ }
+
+ return DeclSpec::TST_unspecified;
+}
+
+bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ CXXScopeSpec *SS,
+ ParsedType &SuggestedType) {
+ // We don't have anything to suggest (yet).
+ SuggestedType = ParsedType();
+
+ // There may have been a typo in the name of the type. Look up typo
+ // results, in case we have something that we can suggest.
+ LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName,
+ NotForRedeclaration);
+
+ if (DeclarationName Corrected = CorrectTypo(Lookup, S, SS, 0, 0, CTC_Type)) {
+ if (NamedDecl *Result = Lookup.getAsSingle<NamedDecl>()) {
+ if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
+ !Result->isInvalidDecl()) {
+ // We found a similarly-named type or interface; suggest that.
+ if (!SS || !SS->isSet())
+ Diag(IILoc, diag::err_unknown_typename_suggest)
+ << &II << Lookup.getLookupName()
+ << FixItHint::CreateReplacement(SourceRange(IILoc),
+ Result->getNameAsString());
+ else if (DeclContext *DC = computeDeclContext(*SS, false))
+ Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+ << &II << DC << Lookup.getLookupName() << SS->getRange()
+ << FixItHint::CreateReplacement(SourceRange(IILoc),
+ Result->getNameAsString());
+ else
+ llvm_unreachable("could not have corrected a typo here");
+
+ Diag(Result->getLocation(), diag::note_previous_decl)
+ << Result->getDeclName();
+
+ SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS);
+ return true;
+ }
+ } else if (Lookup.empty()) {
+ // We corrected to a keyword.
+ // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
+ Diag(IILoc, diag::err_unknown_typename_suggest)
+ << &II << Corrected;
+ return true;
+ }
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ // See if II is a class template that the user forgot to pass arguments to.
+ UnqualifiedId Name;
+ Name.setIdentifier(&II, IILoc);
+ CXXScopeSpec EmptySS;
+ TemplateTy TemplateResult;
+ bool MemberOfUnknownSpecialization;
+ if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
+ Name, ParsedType(), true, TemplateResult,
+ MemberOfUnknownSpecialization) == TNK_Type_template) {
+ TemplateName TplName = TemplateResult.getAsVal<TemplateName>();
+ Diag(IILoc, diag::err_template_missing_args) << TplName;
+ if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) {
+ Diag(TplDecl->getLocation(), diag::note_template_decl_here)
+ << TplDecl->getTemplateParameters()->getSourceRange();
+ }
+ return true;
+ }
+ }
+
+ // FIXME: Should we move the logic that tries to recover from a missing tag
+ // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
+
+ if (!SS || (!SS->isSet() && !SS->isInvalid()))
+ Diag(IILoc, diag::err_unknown_typename) << &II;
+ else if (DeclContext *DC = computeDeclContext(*SS, false))
+ Diag(IILoc, diag::err_typename_nested_not_found)
+ << &II << DC << SS->getRange();
+ else if (isDependentScopeSpecifier(*SS)) {
+ Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+ << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+ << SourceRange(SS->getRange().getBegin(), IILoc)
+ << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
+ SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get();
+ } else {
+ assert(SS && SS->isInvalid() &&
+ "Invalid scope specifier has already been diagnosed");
+ }
+
+ return true;
+}
+
+// Determines the context to return to after temporarily entering a
+// context. This depends in an unnecessarily complicated way on the
+// exact ordering of callbacks from the parser.
+DeclContext *Sema::getContainingDC(DeclContext *DC) {
+
+ // Functions defined inline within classes aren't parsed until we've
+ // finished parsing the top-level class, so the top-level class is
+ // the context we'll need to return to.
+ if (isa<FunctionDecl>(DC)) {
+ DC = DC->getLexicalParent();
+
+ // A function not defined within a class will always return to its
+ // lexical context.
+ if (!isa<CXXRecordDecl>(DC))
+ return DC;
+
+ // A C++ inline method/friend is parsed *after* the topmost class
+ // it was declared in is fully parsed ("complete"); the topmost
+ // class is the context we need to return to.
+ while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
+ DC = RD;
+
+ // Return the declaration context of the topmost class the inline method is
+ // declared in.
+ return DC;
+ }
+
+ // ObjCMethodDecls are parsed (for some reason) outside the context
+ // of the class.
+ if (isa<ObjCMethodDecl>(DC))
+ return DC->getLexicalParent()->getLexicalParent();
+
+ return DC->getLexicalParent();
+}
+
+void Sema::PushDeclContext(Scope *S, DeclContext *DC) {
+ assert(getContainingDC(DC) == CurContext &&
+ "The next DeclContext should be lexically contained in the current one.");
+ CurContext = DC;
+ S->setEntity(DC);
+}
+
+void Sema::PopDeclContext() {
+ assert(CurContext && "DeclContext imbalance!");
+
+ CurContext = getContainingDC(CurContext);
+ assert(CurContext && "Popped translation unit!");
+}
+
+/// EnterDeclaratorContext - Used when we must lookup names in the context
+/// of a declarator's nested name specifier.
+///
+void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
+ // C++0x [basic.lookup.unqual]p13:
+ // A name used in the definition of a static data member of class
+ // X (after the qualified-id of the static member) is looked up as
+ // if the name was used in a member function of X.
+ // C++0x [basic.lookup.unqual]p14:
+ // If a variable member of a namespace is defined outside of the
+ // scope of its namespace then any name used in the definition of
+ // the variable member (after the declarator-id) is looked up as
+ // if the definition of the variable member occurred in its
+ // namespace.
+ // Both of these imply that we should push a scope whose context
+ // is the semantic context of the declaration. We can't use
+ // PushDeclContext here because that context is not necessarily
+ // lexically contained in the current context. Fortunately,
+ // the containing scope should have the appropriate information.
+
+ assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
+ CurContext = DC;
+ S->setEntity(DC);
+}
+
+void Sema::ExitDeclaratorContext(Scope *S) {
+ assert(S->getEntity() == CurContext && "Context imbalance!");
+
+ // Switch back to the lexical context. The safety of this is
+ // enforced by an assert in EnterDeclaratorContext.
+ Scope *Ancestor = S->getParent();
+ while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+ CurContext = (DeclContext*) Ancestor->getEntity();
+
+ // We don't need to do anything with the scope, which is going to
+ // disappear.
+}
+
+/// \brief Determine whether we allow overloading of the function
+/// PrevDecl with another declaration.
+///
+/// This routine determines whether overloading is possible, not
+/// whether some new function is actually an overload. It will return
+/// true in C++ (where we can always provide overloads) or, as an
+/// extension, in C when the previous function is already an
+/// overloaded function declaration or has the "overloadable"
+/// attribute.
+static bool AllowOverloadingOfFunction(LookupResult &Previous,
+ ASTContext &Context) {
+ if (Context.getLangOptions().CPlusPlus)
+ return true;
+
+ if (Previous.getResultKind() == LookupResult::FoundOverloaded)
+ return true;
+
+ return (Previous.getResultKind() == LookupResult::Found
+ && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
+}
+
+/// Add this decl to the scope shadowed decl chains.
+void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
+ // Move up the scope chain until we find the nearest enclosing
+ // non-transparent context. The declaration will be introduced into this
+ // scope.
+ while (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext())
+ S = S->getParent();
+
+ // Add scoped declarations into their context, so that they can be
+ // found later. Declarations without a context won't be inserted
+ // into any context.
+ if (AddToContext)
+ CurContext->addDecl(D);
+
+ // Out-of-line definitions shouldn't be pushed into scope in C++.
+ // Out-of-line variable and function definitions shouldn't even in C.
+ if ((getLangOptions().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) &&
+ D->isOutOfLine())
+ return;
+
+ // Template instantiations should also not be pushed into scope.
+ if (isa<FunctionDecl>(D) &&
+ cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
+ return;
+
+ // If this replaces anything in the current scope,
+ IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
+ IEnd = IdResolver.end();
+ for (; I != IEnd; ++I) {
+ if (S->isDeclScope(*I) && D->declarationReplaces(*I)) {
+ S->RemoveDecl(*I);
+ IdResolver.RemoveDecl(*I);
+
+ // Should only need to replace one decl.
+ break;
+ }
+ }
+
+ S->AddDecl(D);
+ IdResolver.AddDecl(D);
+}
+
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
+ return IdResolver.isDeclInScope(D, Ctx, Context, S);
+}
+
+Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
+ DeclContext *TargetDC = DC->getPrimaryContext();
+ do {
+ if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
+ if (ScopeDC->getPrimaryContext() == TargetDC)
+ return S;
+ } while ((S = S->getParent()));
+
+ return 0;
+}
+
+static bool isOutOfScopePreviousDeclaration(NamedDecl *,
+ DeclContext*,
+ ASTContext&);
+
+/// Filters out lookup results that don't fall within the given scope
+/// as determined by isDeclInScope.
+static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
+ DeclContext *Ctx, Scope *S,
+ bool ConsiderLinkage) {
+ LookupResult::Filter F = R.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+
+ if (SemaRef.isDeclInScope(D, Ctx, S))
+ continue;
+
+ if (ConsiderLinkage &&
+ isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context))
+ continue;
+
+ F.erase();
+ }
+
+ F.done();
+}
+
+static bool isUsingDecl(NamedDecl *D) {
+ return isa<UsingShadowDecl>(D) ||
+ isa<UnresolvedUsingTypenameDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D);
+}
+
+/// Removes using shadow declarations from the lookup results.
+static void RemoveUsingDecls(LookupResult &R) {
+ LookupResult::Filter F = R.makeFilter();
+ while (F.hasNext())
+ if (isUsingDecl(F.next()))
+ F.erase();
+
+ F.done();
+}
+
+/// \brief Check for this common pattern:
+/// @code
+/// class S {
+/// S(const S&); // DO NOT IMPLEMENT
+/// void operator=(const S&); // DO NOT IMPLEMENT
+/// };
+/// @endcode
+static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
+ // FIXME: Should check for private access too but access is set after we get
+ // the decl here.
+ if (D->isThisDeclarationADefinition())
+ return false;
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
+ return CD->isCopyConstructor();
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ return Method->isCopyAssignmentOperator();
+ return false;
+}
+
+bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
+ assert(D);
+
+ if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
+ return false;
+
+ // Ignore class templates.
+ if (D->getDeclContext()->isDependentContext() ||
+ D->getLexicalDeclContext()->isDependentContext())
+ return false;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return false;
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
+ return false;
+ } else {
+ // 'static inline' functions are used in headers; don't warn.
+ if (FD->getStorageClass() == SC_Static &&
+ FD->isInlineSpecified())
+ return false;
+ }
+
+ if (FD->isThisDeclarationADefinition() &&
+ Context.DeclMustBeEmitted(FD))
+ return false;
+
+ } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!VD->isFileVarDecl() ||
+ VD->getType().isConstant(Context) ||
+ Context.DeclMustBeEmitted(VD))
+ return false;
+
+ if (VD->isStaticDataMember() &&
+ VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return false;
+
+ } else {
+ return false;
+ }
+
+ // Only warn for unused decls internal to the translation unit.
+ if (D->getLinkage() == ExternalLinkage)
+ return false;
+
+ return true;
+}
+
+void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
+ if (!D)
+ return;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ const FunctionDecl *First = FD->getFirstDeclaration();
+ if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+ return; // First should already be in the vector.
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ const VarDecl *First = VD->getFirstDeclaration();
+ if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+ return; // First should already be in the vector.
+ }
+
+ if (ShouldWarnIfUnusedFileScopedDecl(D))
+ UnusedFileScopedDecls.push_back(D);
+ }
+
+static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+ if (D->isInvalidDecl())
+ return false;
+
+ if (D->isUsed() || D->hasAttr<UnusedAttr>())
+ return false;
+
+ if (isa<LabelDecl>(D))
+ return true;
+
+ // White-list anything that isn't a local variable.
+ if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
+ !D->getDeclContext()->isFunctionOrMethod())
+ return false;
+
+ // Types of valid local variables should be complete, so this should succeed.
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+
+ // White-list anything with an __attribute__((unused)) type.
+ QualType Ty = VD->getType();
+
+ // Only look at the outermost level of typedef.
+ if (const TypedefType *TT = dyn_cast<TypedefType>(Ty)) {
+ if (TT->getDecl()->hasAttr<UnusedAttr>())
+ return false;
+ }
+
+ // If we failed to complete the type for some reason, or if the type is
+ // dependent, don't diagnose the variable.
+ if (Ty->isIncompleteType() || Ty->isDependentType())
+ return false;
+
+ if (const TagType *TT = Ty->getAs<TagType>()) {
+ const TagDecl *Tag = TT->getDecl();
+ if (Tag->hasAttr<UnusedAttr>())
+ return false;
+
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
+ // FIXME: Checking for the presence of a user-declared constructor
+ // isn't completely accurate; we'd prefer to check that the initializer
+ // has no side effects.
+ if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor())
+ return false;
+ }
+ }
+
+ // TODO: __attribute__((unused)) templates?
+ }
+
+ return true;
+}
+
+/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
+/// unless they are marked attr(unused).
+void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
+ if (!ShouldDiagnoseUnusedDecl(D))
+ return;
+
+ unsigned DiagID;
+ if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable())
+ DiagID = diag::warn_unused_exception_param;
+ else if (isa<LabelDecl>(D))
+ DiagID = diag::warn_unused_label;
+ else
+ DiagID = diag::warn_unused_variable;
+
+ Diag(D->getLocation(), DiagID) << D->getDeclName();
+}
+
+static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
+ // Verify that we have no forward references left. If so, there was a goto
+ // or address of a label taken, but no definition of it. Label fwd
+ // definitions are indicated with a null substmt.
+ if (L->getStmt() == 0)
+ S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
+}
+
+void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
+ if (S->decl_empty()) return;
+ assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
+ "Scope shouldn't contain decls!");
+
+ for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ Decl *TmpD = (*I);
+ assert(TmpD && "This decl didn't get pushed??");
+
+ assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
+ NamedDecl *D = cast<NamedDecl>(TmpD);
+
+ if (!D->getDeclName()) continue;
+
+ // Diagnose unused variables in this scope.
+ if (!S->hasErrorOccurred())
+ DiagnoseUnusedDecl(D);
+
+ // If this was a forward reference to a label, verify it was defined.
+ if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
+ CheckPoppedLabel(LD, *this);
+
+ // Remove this name from our lexical scope.
+ IdResolver.RemoveDecl(D);
+ }
+}
+
+/// \brief Look for an Objective-C class in the translation unit.
+///
+/// \param Id The name of the Objective-C class we're looking for. If
+/// typo-correction fixes this name, the Id will be updated
+/// to the fixed name.
+///
+/// \param IdLoc The location of the name in the translation unit.
+///
+/// \param TypoCorrection If true, this routine will attempt typo correction
+/// if there is no class with the given name.
+///
+/// \returns The declaration of the named Objective-C class, or NULL if the
+/// class could not be found.
+ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection) {
+ // The third "scope" argument is 0 since we aren't enabling lazy built-in
+ // creation from this context.
+ NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);
+
+ if (!IDecl && TypoCorrection) {
+ // Perform typo correction at the given location, but only if we
+ // find an Objective-C class name.
+ LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);
+ if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
+ (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+ Diag(IdLoc, diag::err_undef_interface_suggest)
+ << Id << IDecl->getDeclName()
+ << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
+ Diag(IDecl->getLocation(), diag::note_previous_decl)
+ << IDecl->getDeclName();
+
+ Id = IDecl->getIdentifier();
+ }
+ }
+
+ return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
+}
+
+/// getNonFieldDeclScope - Retrieves the innermost scope, starting
+/// from S, where a non-field would be declared. This routine copes
+/// with the difference between C and C++ scoping rules in structs and
+/// unions. For example, the following code is well-formed in C but
+/// ill-formed in C++:
+/// @code
+/// struct S6 {
+/// enum { BAR } e;
+/// };
+///
+/// void test_S6() {
+/// struct S6 a;
+/// a.e = BAR;
+/// }
+/// @endcode
+/// For the declaration of BAR, this routine will return a different
+/// scope. The scope S will be the scope of the unnamed enumeration
+/// within S6. In C++, this routine will return the scope associated
+/// with S6, because the enumeration's scope is a transparent
+/// context but structures can contain non-field names. In C, this
+/// routine will return the translation unit scope, since the
+/// enumeration's scope is a transparent context and structures cannot
+/// contain non-field names.
+Scope *Sema::getNonFieldDeclScope(Scope *S) {
+ while (((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+ (S->isClassScope() && !getLangOptions().CPlusPlus))
+ S = S->getParent();
+ return S;
+}
+
+/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
+/// file scope. lazily create a decl for it. ForRedeclaration is true
+/// if we're creating this built-in in anticipation of redeclaring the
+/// built-in.
+NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
+ Scope *S, bool ForRedeclaration,
+ SourceLocation Loc) {
+ Builtin::ID BID = (Builtin::ID)bid;
+
+ ASTContext::GetBuiltinTypeError Error;
+ QualType R = Context.GetBuiltinType(BID, Error);
+ switch (Error) {
+ case ASTContext::GE_None:
+ // Okay
+ break;
+
+ case ASTContext::GE_Missing_stdio:
+ if (ForRedeclaration)
+ Diag(Loc, diag::warn_implicit_decl_requires_stdio)
+ << Context.BuiltinInfo.GetName(BID);
+ return 0;
+
+ case ASTContext::GE_Missing_setjmp:
+ if (ForRedeclaration)
+ Diag(Loc, diag::warn_implicit_decl_requires_setjmp)
+ << Context.BuiltinInfo.GetName(BID);
+ return 0;
+ }
+
+ if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
+ Diag(Loc, diag::ext_implicit_lib_function_decl)
+ << Context.BuiltinInfo.GetName(BID)
+ << R;
+ if (Context.BuiltinInfo.getHeaderName(BID) &&
+ Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc)
+ != Diagnostic::Ignored)
+ Diag(Loc, diag::note_please_include_header)
+ << Context.BuiltinInfo.getHeaderName(BID)
+ << Context.BuiltinInfo.GetName(BID);
+ }
+
+ FunctionDecl *New = FunctionDecl::Create(Context,
+ Context.getTranslationUnitDecl(),
+ Loc, II, R, /*TInfo=*/0,
+ SC_Extern,
+ SC_None, false,
+ /*hasPrototype=*/true);
+ New->setImplicit();
+
+ // Create Decl objects for each parameter, adding them to the
+ // FunctionDecl.
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+ for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
+ Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
+ FT->getArgType(i), /*TInfo=*/0,
+ SC_None, SC_None, 0));
+ New->setParams(Params.data(), Params.size());
+ }
+
+ AddKnownFunctionAttributes(New);
+
+ // TUScope is the translation-unit scope to insert this function into.
+ // FIXME: This is hideous. We need to teach PushOnScopeChains to
+ // relate Scopes to DeclContexts, and probably eliminate CurContext
+ // entirely, but we're not there yet.
+ DeclContext *SavedContext = CurContext;
+ CurContext = Context.getTranslationUnitDecl();
+ PushOnScopeChains(New, TUScope);
+ CurContext = SavedContext;
+ return New;
+}
+
+/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the
+/// same name and scope as a previous declaration 'Old'. Figure out
+/// how to resolve this situation, merging decls or emitting
+/// diagnostics as appropriate. If there was an error, set New to be invalid.
+///
+void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
+ // If the new decl is known invalid already, don't bother doing any
+ // merging checks.
+ if (New->isInvalidDecl()) return;
+
+ // Allow multiple definitions for ObjC built-in typedefs.
+ // FIXME: Verify the underlying types are equivalent!
+ if (getLangOptions().ObjC1) {
+ const IdentifierInfo *TypeID = New->getIdentifier();
+ switch (TypeID->getLength()) {
+ default: break;
+ case 2:
+ if (!TypeID->isStr("id"))
+ break;
+ Context.ObjCIdRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'id', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+ return;
+ case 5:
+ if (!TypeID->isStr("Class"))
+ break;
+ Context.ObjCClassRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'Class', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
+ return;
+ case 3:
+ if (!TypeID->isStr("SEL"))
+ break;
+ Context.ObjCSelRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'SEL', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCSelType().getTypePtr());
+ return;
+ case 8:
+ if (!TypeID->isStr("Protocol"))
+ break;
+ Context.setObjCProtoType(New->getUnderlyingType());
+ return;
+ }
+ // Fall through - the typedef name was not a builtin type.
+ }
+
+ // Verify the old decl was also a type.
+ TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
+ if (!Old) {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ << New->getDeclName();
+
+ NamedDecl *OldD = OldDecls.getRepresentativeDecl();
+ if (OldD->getLocation().isValid())
+ Diag(OldD->getLocation(), diag::note_previous_definition);
+
+ return New->setInvalidDecl();
+ }
+
+ // If the old declaration is invalid, just give up here.
+ if (Old->isInvalidDecl())
+ return New->setInvalidDecl();
+
+ // Determine the "old" type we'll use for checking and diagnostics.
+ QualType OldType;
+ if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
+ OldType = OldTypedef->getUnderlyingType();
+ else
+ OldType = Context.getTypeDeclType(Old);
+
+ // If the typedef types are not identical, reject them in all languages and
+ // with any extensions enabled.
+
+ if (OldType != New->getUnderlyingType() &&
+ Context.getCanonicalType(OldType) !=
+ Context.getCanonicalType(New->getUnderlyingType())) {
+ Diag(New->getLocation(), diag::err_redefinition_different_typedef)
+ << New->getUnderlyingType() << OldType;
+ if (Old->getLocation().isValid())
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ // The types match. Link up the redeclaration chain if the old
+ // declaration was a typedef.
+ // FIXME: this is a potential source of wierdness if the type
+ // spellings don't match exactly.
+ if (isa<TypedefDecl>(Old))
+ New->setPreviousDeclaration(cast<TypedefDecl>(Old));
+
+ if (getLangOptions().Microsoft)
+ return;
+
+ if (getLangOptions().CPlusPlus) {
+ // C++ [dcl.typedef]p2:
+ // In a given non-class scope, a typedef specifier can be used to
+ // redefine the name of any type declared in that scope to refer
+ // to the type to which it already refers.
+ if (!isa<CXXRecordDecl>(CurContext))
+ return;
+
+ // C++0x [dcl.typedef]p4:
+ // In a given class scope, a typedef specifier can be used to redefine
+ // any class-name declared in that scope that is not also a typedef-name
+ // to refer to the type to which it already refers.
+ //
+ // This wording came in via DR424, which was a correction to the
+ // wording in DR56, which accidentally banned code like:
+ //
+ // struct S {
+ // typedef struct A { } A;
+ // };
+ //
+ // in the C++03 standard. We implement the C++0x semantics, which
+ // allow the above but disallow
+ //
+ // struct S {
+ // typedef int I;
+ // typedef int I;
+ // };
+ //
+ // since that was the intent of DR56.
+ if (!isa<TypedefDecl >(Old))
+ return;
+
+ Diag(New->getLocation(), diag::err_redefinition)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ // If we have a redefinition of a typedef in C, emit a warning. This warning
+ // is normally mapped to an error, but can be controlled with
+ // -Wtypedef-redefinition. If either the original or the redefinition is
+ // in a system header, don't emit this for compatibility with GCC.
+ if (getDiagnostics().getSuppressSystemWarnings() &&
+ (Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
+ Context.getSourceManager().isInSystemHeader(New->getLocation())))
+ return;
+
+ Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return;
+}
+
+/// DeclhasAttr - returns true if decl Declaration already has the target
+/// attribute.
+static bool
+DeclHasAttr(const Decl *D, const Attr *A) {
+ const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
+ for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
+ if ((*i)->getKind() == A->getKind()) {
+ // FIXME: Don't hardcode this check
+ if (OA && isa<OwnershipAttr>(*i))
+ return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
+ return true;
+ }
+
+ return false;
+}
+
+/// MergeDeclAttributes - append attributes from the Old decl to the New one.
+static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
+ if (!Old->hasAttrs())
+ return;
+ // Ensure that any moving of objects within the allocated map is done before
+ // we process them.
+ if (!New->hasAttrs())
+ New->setAttrs(AttrVec());
+ for (specific_attr_iterator<InheritableAttr>
+ i = Old->specific_attr_begin<InheritableAttr>(),
+ e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) {
+ if (!DeclHasAttr(New, *i)) {
+ InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C));
+ NewAttr->setInherited(true);
+ New->addAttr(NewAttr);
+ }
+ }
+}
+
+namespace {
+
+/// Used in MergeFunctionDecl to keep track of function parameters in
+/// C.
+struct GNUCompatibleParamWarning {
+ ParmVarDecl *OldParm;
+ ParmVarDecl *NewParm;
+ QualType PromotedType;
+};
+
+}
+
+/// getSpecialMember - get the special member enum for a method.
+Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
+ if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+ if (Ctor->isCopyConstructor())
+ return Sema::CXXCopyConstructor;
+
+ return Sema::CXXConstructor;
+ }
+
+ if (isa<CXXDestructorDecl>(MD))
+ return Sema::CXXDestructor;
+
+ assert(MD->isCopyAssignmentOperator() &&
+ "Must have copy assignment operator");
+ return Sema::CXXCopyAssignment;
+}
+
+/// canRedefineFunction - checks if a function can be redefined. Currently,
+/// only extern inline functions can be redefined, and even then only in
+/// GNU89 mode.
+static bool canRedefineFunction(const FunctionDecl *FD,
+ const LangOptions& LangOpts) {
+ return (LangOpts.GNUMode && !LangOpts.C99 && !LangOpts.CPlusPlus &&
+ FD->isInlineSpecified() &&
+ FD->getStorageClass() == SC_Extern);
+}
+
+/// MergeFunctionDecl - We just parsed a function 'New' from
+/// declarator D which has the same name and scope as a previous
+/// declaration 'Old'. Figure out how to resolve this situation,
+/// merging decls or emitting diagnostics as appropriate.
+///
+/// In C++, New and Old must be declarations that are not
+/// overloaded. Use IsOverload to determine whether New and Old are
+/// overloaded, and to select the Old declaration that New should be
+/// merged with.
+///
+/// Returns true if there was an error, false otherwise.
+bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
+ // Verify the old decl was also a function.
+ FunctionDecl *Old = 0;
+ if (FunctionTemplateDecl *OldFunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(OldD))
+ Old = OldFunctionTemplate->getTemplatedDecl();
+ else
+ Old = dyn_cast<FunctionDecl>(OldD);
+ if (!Old) {
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+ Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(),
+ diag::note_using_decl) << 0;
+ return true;
+ }
+
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ << New->getDeclName();
+ Diag(OldD->getLocation(), diag::note_previous_definition);
+ return true;
+ }
+
+ // Determine whether the previous declaration was a definition,
+ // implicit declaration, or a declaration.
+ diag::kind PrevDiag;
+ if (Old->isThisDeclarationADefinition())
+ PrevDiag = diag::note_previous_definition;
+ else if (Old->isImplicit())
+ PrevDiag = diag::note_previous_implicit_declaration;
+ else
+ PrevDiag = diag::note_previous_declaration;
+
+ QualType OldQType = Context.getCanonicalType(Old->getType());
+ QualType NewQType = Context.getCanonicalType(New->getType());
+
+ // Don't complain about this if we're in GNU89 mode and the old function
+ // is an extern inline function.
+ if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
+ New->getStorageClass() == SC_Static &&
+ Old->getStorageClass() != SC_Static &&
+ !canRedefineFunction(Old, getLangOptions())) {
+ Diag(New->getLocation(), diag::err_static_non_static)
+ << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
+
+ // If a function is first declared with a calling convention, but is
+ // later declared or defined without one, the second decl assumes the
+ // calling convention of the first.
+ //
+ // For the new decl, we have to look at the NON-canonical type to tell the
+ // difference between a function that really doesn't have a calling
+ // convention and one that is declared cdecl. That's because in
+ // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+ // because it is the default calling convention.
+ //
+ // Note also that we DO NOT return at this point, because we still have
+ // other tests to run.
+ const FunctionType *OldType = cast<FunctionType>(OldQType);
+ const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+ FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
+ FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+ bool RequiresAdjustment = false;
+ if (OldTypeInfo.getCC() != CC_Default &&
+ NewTypeInfo.getCC() == CC_Default) {
+ NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+ RequiresAdjustment = true;
+ } else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
+ NewTypeInfo.getCC())) {
+ // Calling conventions really aren't compatible, so complain.
+ Diag(New->getLocation(), diag::err_cconv_change)
+ << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
+ << (OldTypeInfo.getCC() == CC_Default)
+ << (OldTypeInfo.getCC() == CC_Default ? "" :
+ FunctionType::getNameForCallConv(OldTypeInfo.getCC()));
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ // FIXME: diagnose the other way around?
+ if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) {
+ NewTypeInfo = NewTypeInfo.withNoReturn(true);
+ RequiresAdjustment = true;
+ }
+
+ // Merge regparm attribute.
+ if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
+ if (NewTypeInfo.getRegParm()) {
+ Diag(New->getLocation(), diag::err_regparm_mismatch)
+ << NewType->getRegParmType()
+ << OldType->getRegParmType();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm());
+ RequiresAdjustment = true;
+ }
+
+ if (RequiresAdjustment) {
+ NewType = Context.adjustFunctionType(NewType, NewTypeInfo);
+ New->setType(QualType(NewType, 0));
+ NewQType = Context.getCanonicalType(New->getType());
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ // (C++98 13.1p2):
+ // Certain function declarations cannot be overloaded:
+ // -- Function declarations that differ only in the return type
+ // cannot be overloaded.
+ QualType OldReturnType = OldType->getResultType();
+ QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType();
+ QualType ResQT;
+ if (OldReturnType != NewReturnType) {
+ if (NewReturnType->isObjCObjectPointerType()
+ && OldReturnType->isObjCObjectPointerType())
+ ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
+ if (ResQT.isNull()) {
+ if (New->isCXXClassMember() && New->isOutOfLine())
+ Diag(New->getLocation(),
+ diag::err_member_def_does_not_match_ret_type) << New;
+ else
+ Diag(New->getLocation(), diag::err_ovl_diff_return_type);
+ Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ return true;
+ }
+ else
+ NewQType = ResQT;
+ }
+
+ const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+ CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+ if (OldMethod && NewMethod) {
+ // Preserve triviality.
+ NewMethod->setTrivial(OldMethod->isTrivial());
+
+ bool isFriend = NewMethod->getFriendObjectKind();
+
+ if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) {
+ // -- Member function declarations with the same name and the
+ // same parameter types cannot be overloaded if any of them
+ // is a static member function declaration.
+ if (OldMethod->isStatic() || NewMethod->isStatic()) {
+ Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+ Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ return true;
+ }
+
+ // C++ [class.mem]p1:
+ // [...] A member shall not be declared twice in the
+ // member-specification, except that a nested class or member
+ // class template can be declared and then later defined.
+ unsigned NewDiag;
+ if (isa<CXXConstructorDecl>(OldMethod))
+ NewDiag = diag::err_constructor_redeclared;
+ else if (isa<CXXDestructorDecl>(NewMethod))
+ NewDiag = diag::err_destructor_redeclared;
+ else if (isa<CXXConversionDecl>(NewMethod))
+ NewDiag = diag::err_conv_function_redeclared;
+ else
+ NewDiag = diag::err_member_redeclared;
+
+ Diag(New->getLocation(), NewDiag);
+ Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+
+ // Complain if this is an explicit declaration of a special
+ // member that was initially declared implicitly.
+ //
+ // As an exception, it's okay to befriend such methods in order
+ // to permit the implicit constructor/destructor/operator calls.
+ } else if (OldMethod->isImplicit()) {
+ if (isFriend) {
+ NewMethod->setImplicit();
+ } else {
+ Diag(NewMethod->getLocation(),
+ diag::err_definition_of_implicitly_declared_member)
+ << New << getSpecialMember(OldMethod);
+ return true;
+ }
+ }
+ }
+
+ // (C++98 8.3.5p3):
+ // All declarations for a function shall agree exactly in both the
+ // return type and the parameter-type-list.
+ // We also want to respect all the extended bits except noreturn.
+
+ // noreturn should now match unless the old type info didn't have it.
+ QualType OldQTypeForComparison = OldQType;
+ if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) {
+ assert(OldQType == QualType(OldType, 0));
+ const FunctionType *OldTypeForComparison
+ = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true));
+ OldQTypeForComparison = QualType(OldTypeForComparison, 0);
+ assert(OldQTypeForComparison.isCanonical());
+ }
+
+ if (OldQTypeForComparison == NewQType)
+ return MergeCompatibleFunctionDecls(New, Old);
+
+ // Fall through for conflicting redeclarations and redefinitions.
+ }
+
+ // C: Function types need to be compatible, not identical. This handles
+ // duplicate function decls like "void f(int); void f(enum X);" properly.
+ if (!getLangOptions().CPlusPlus &&
+ Context.typesAreCompatible(OldQType, NewQType)) {
+ const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
+ const FunctionProtoType *OldProto = 0;
+ if (isa<FunctionNoProtoType>(NewFuncType) &&
+ (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
+ // The old declaration provided a function prototype, but the
+ // new declaration does not. Merge in the prototype.
+ assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
+ llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
+ OldProto->arg_type_end());
+ NewQType = Context.getFunctionType(NewFuncType->getResultType(),
+ ParamTypes.data(), ParamTypes.size(),
+ OldProto->getExtProtoInfo());
+ New->setType(NewQType);
+ New->setHasInheritedPrototype();
+
+ // Synthesize a parameter for each argument type.
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+ for (FunctionProtoType::arg_type_iterator
+ ParamType = OldProto->arg_type_begin(),
+ ParamEnd = OldProto->arg_type_end();
+ ParamType != ParamEnd; ++ParamType) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
+ SourceLocation(), 0,
+ *ParamType, /*TInfo=*/0,
+ SC_None, SC_None,
+ 0);
+ Param->setImplicit();
+ Params.push_back(Param);
+ }
+
+ New->setParams(Params.data(), Params.size());
+ }
+
+ return MergeCompatibleFunctionDecls(New, Old);
+ }
+
+ // GNU C permits a K&R definition to follow a prototype declaration
+ // if the declared types of the parameters in the K&R definition
+ // match the types in the prototype declaration, even when the
+ // promoted types of the parameters from the K&R definition differ
+ // from the types in the prototype. GCC then keeps the types from
+ // the prototype.
+ //
+ // If a variadic prototype is followed by a non-variadic K&R definition,
+ // the K&R definition becomes variadic. This is sort of an edge case, but
+ // it's legal per the standard depending on how you read C99 6.7.5.3p15 and
+ // C99 6.9.1p8.
+ if (!getLangOptions().CPlusPlus &&
+ Old->hasPrototype() && !New->hasPrototype() &&
+ New->getType()->getAs<FunctionProtoType>() &&
+ Old->getNumParams() == New->getNumParams()) {
+ llvm::SmallVector<QualType, 16> ArgTypes;
+ llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings;
+ const FunctionProtoType *OldProto
+ = Old->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+
+ // Determine whether this is the GNU C extension.
+ QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
+ NewProto->getResultType());
+ bool LooseCompatible = !MergedReturn.isNull();
+ for (unsigned Idx = 0, End = Old->getNumParams();
+ LooseCompatible && Idx != End; ++Idx) {
+ ParmVarDecl *OldParm = Old->getParamDecl(Idx);
+ ParmVarDecl *NewParm = New->getParamDecl(Idx);
+ if (Context.typesAreCompatible(OldParm->getType(),
+ NewProto->getArgType(Idx))) {
+ ArgTypes.push_back(NewParm->getType());
+ } else if (Context.typesAreCompatible(OldParm->getType(),
+ NewParm->getType(),
+ /*CompareUnqualified=*/true)) {
+ GNUCompatibleParamWarning Warn
+ = { OldParm, NewParm, NewProto->getArgType(Idx) };
+ Warnings.push_back(Warn);
+ ArgTypes.push_back(NewParm->getType());
+ } else
+ LooseCompatible = false;
+ }
+
+ if (LooseCompatible) {
+ for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) {
+ Diag(Warnings[Warn].NewParm->getLocation(),
+ diag::ext_param_promoted_not_compatible_with_prototype)
+ << Warnings[Warn].PromotedType
+ << Warnings[Warn].OldParm->getType();
+ if (Warnings[Warn].OldParm->getLocation().isValid())
+ Diag(Warnings[Warn].OldParm->getLocation(),
+ diag::note_previous_declaration);
+ }
+
+ New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
+ ArgTypes.size(),
+ OldProto->getExtProtoInfo()));
+ return MergeCompatibleFunctionDecls(New, Old);
+ }
+
+ // Fall through to diagnose conflicting types.
+ }
+
+ // A function that has already been declared has been redeclared or defined
+ // with a different type- show appropriate diagnostic
+ if (unsigned BuiltinID = Old->getBuiltinID()) {
+ // The user has declared a builtin function with an incompatible
+ // signature.
+ if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+ // The function the user is redeclaring is a library-defined
+ // function like 'malloc' or 'printf'. Warn about the
+ // redeclaration, then pretend that we don't know about this
+ // library built-in.
+ Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
+ Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+ << Old << Old->getType();
+ New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+ Old->setInvalidDecl();
+ return false;
+ }
+
+ PrevDiag = diag::note_previous_builtin_declaration;
+ }
+
+ Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName();
+ Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+ return true;
+}
+
+/// \brief Completes the merge of two function declarations that are
+/// known to be compatible.
+///
+/// This routine handles the merging of attributes and other
+/// properties of function declarations form the old declaration to
+/// the new declaration, once we know that New is in fact a
+/// redeclaration of Old.
+///
+/// \returns false
+bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
+ // Merge the attributes
+ MergeDeclAttributes(New, Old, Context);
+
+ // Merge the storage class.
+ if (Old->getStorageClass() != SC_Extern &&
+ Old->getStorageClass() != SC_None)
+ New->setStorageClass(Old->getStorageClass());
+
+ // Merge "pure" flag.
+ if (Old->isPure())
+ New->setPure();
+
+ // Merge the "deleted" flag.
+ if (Old->isDeleted())
+ New->setDeleted();
+
+ if (getLangOptions().CPlusPlus)
+ return MergeCXXFunctionDecl(New, Old);
+
+ return false;
+}
+
+/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope
+/// as a previous declaration 'Old'. Figure out how to merge their types,
+/// emitting diagnostics as appropriate.
+///
+/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
+/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't
+/// check them before the initializer is attached.
+///
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
+ if (New->isInvalidDecl() || Old->isInvalidDecl())
+ return;
+
+ QualType MergedT;
+ if (getLangOptions().CPlusPlus) {
+ AutoType *AT = New->getType()->getContainedAutoType();
+ if (AT && !AT->isDeduced()) {
+ // We don't know what the new type is until the initializer is attached.
+ return;
+ } else if (Context.hasSameType(New->getType(), Old->getType()))
+ return;
+ // C++ [basic.link]p10:
+ // [...] the types specified by all declarations referring to a given
+ // object or function shall be identical, except that declarations for an
+ // array object can specify array types that differ by the presence or
+ // absence of a major array bound (8.3.4).
+ else if (Old->getType()->isIncompleteArrayType() &&
+ New->getType()->isArrayType()) {
+ CanQual<ArrayType> OldArray
+ = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+ CanQual<ArrayType> NewArray
+ = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+ if (OldArray->getElementType() == NewArray->getElementType())
+ MergedT = New->getType();
+ } else if (Old->getType()->isArrayType() &&
+ New->getType()->isIncompleteArrayType()) {
+ CanQual<ArrayType> OldArray
+ = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+ CanQual<ArrayType> NewArray
+ = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+ if (OldArray->getElementType() == NewArray->getElementType())
+ MergedT = Old->getType();
+ } else if (New->getType()->isObjCObjectPointerType()
+ && Old->getType()->isObjCObjectPointerType()) {
+ MergedT = Context.mergeObjCGCQualifiers(New->getType(),
+ Old->getType());
+ }
+ } else {
+ MergedT = Context.mergeTypes(New->getType(), Old->getType());
+ }
+ if (MergedT.isNull()) {
+ Diag(New->getLocation(), diag::err_redefinition_different_type)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+ New->setType(MergedT);
+}
+
+/// MergeVarDecl - We just parsed a variable 'New' which has the same name
+/// and scope as a previous declaration 'Old'. Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+/// Tentative definition rules (C99 6.9.2p2) are checked by
+/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
+/// definitions here, since the initializer hasn't been attached.
+///
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+ // If the new decl is already invalid, don't do any other checking.
+ if (New->isInvalidDecl())
+ return;
+
+ // Verify the old decl was also a variable.
+ VarDecl *Old = 0;
+ if (!Previous.isSingleResult() ||
+ !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ << New->getDeclName();
+ Diag(Previous.getRepresentativeDecl()->getLocation(),
+ diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ // C++ [class.mem]p1:
+ // A member shall not be declared twice in the member-specification [...]
+ //
+ // Here, we need only consider static data members.
+ if (Old->isStaticDataMember() && !New->isOutOfLine()) {
+ Diag(New->getLocation(), diag::err_duplicate_member)
+ << New->getIdentifier();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->setInvalidDecl();
+ }
+
+ MergeDeclAttributes(New, Old, Context);
+
+ // Merge the types.
+ MergeVarDeclTypes(New, Old);
+ if (New->isInvalidDecl())
+ return;
+
+ // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+ if (New->getStorageClass() == SC_Static &&
+ (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) {
+ Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+ // C99 6.2.2p4:
+ // For an identifier declared with the storage-class specifier
+ // extern in a scope in which a prior declaration of that
+ // identifier is visible,23) if the prior declaration specifies
+ // internal or external linkage, the linkage of the identifier at
+ // the later declaration is the same as the linkage specified at
+ // the prior declaration. If no prior declaration is visible, or
+ // if the prior declaration specifies no linkage, then the
+ // identifier has external linkage.
+ if (New->hasExternalStorage() && Old->hasLinkage())
+ /* Okay */;
+ else if (New->getStorageClass() != SC_Static &&
+ Old->getStorageClass() == SC_Static) {
+ Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ // Check if extern is followed by non-extern and vice-versa.
+ if (New->hasExternalStorage() &&
+ !Old->hasLinkage() && Old->isLocalVarDecl()) {
+ Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+ if (Old->hasExternalStorage() &&
+ !New->hasLinkage() && New->isLocalVarDecl()) {
+ Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ // Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
+
+ // FIXME: The test for external storage here seems wrong? We still
+ // need to check for mismatches.
+ if (!New->hasExternalStorage() && !New->isFileVarDecl() &&
+ // Don't complain about out-of-line definitions of static members.
+ !(Old->getLexicalDeclContext()->isRecord() &&
+ !New->getLexicalDeclContext()->isRecord())) {
+ Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ return New->setInvalidDecl();
+ }
+
+ if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
+ Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) {
+ Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ }
+
+ // C++ doesn't have tentative definitions, so go right ahead and check here.
+ const VarDecl *Def;
+ if (getLangOptions().CPlusPlus &&
+ New->isThisDeclarationADefinition() == VarDecl::Definition &&
+ (Def = Old->getDefinition())) {
+ Diag(New->getLocation(), diag::err_redefinition)
+ << New->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
+ // c99 6.2.2 P4.
+ // For an identifier declared with the storage-class specifier extern in a
+ // scope in which a prior declaration of that identifier is visible, if
+ // the prior declaration specifies internal or external linkage, the linkage
+ // of the identifier at the later declaration is the same as the linkage
+ // specified at the prior declaration.
+ // FIXME. revisit this code.
+ if (New->hasExternalStorage() &&
+ Old->getLinkage() == InternalLinkage &&
+ New->getDeclContext() == Old->getDeclContext())
+ New->setStorageClass(Old->getStorageClass());
+
+ // Keep a chain of previous declarations.
+ New->setPreviousDeclaration(Old);
+
+ // Inherit access appropriately.
+ New->setAccess(Old->getAccess());
+}
+
+/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+/// no declarator (e.g. "struct foo;") is parsed.
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS) {
+ // FIXME: Error on inline/virtual/explicit
+ // FIXME: Warn on useless __thread
+ // FIXME: Warn on useless const/volatile
+ // FIXME: Warn on useless static/extern/typedef/private_extern/mutable
+ // FIXME: Warn on useless attributes
+ Decl *TagD = 0;
+ TagDecl *Tag = 0;
+ if (DS.getTypeSpecType() == DeclSpec::TST_class ||
+ DS.getTypeSpecType() == DeclSpec::TST_struct ||
+ DS.getTypeSpecType() == DeclSpec::TST_union ||
+ DS.getTypeSpecType() == DeclSpec::TST_enum) {
+ TagD = DS.getRepAsDecl();
+
+ if (!TagD) // We probably had an error
+ return 0;
+
+ // Note that the above type specs guarantee that the
+ // type rep is a Decl, whereas in many of the others
+ // it's a Type.
+ Tag = dyn_cast<TagDecl>(TagD);
+ }
+
+ if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+ // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+ // or incomplete types shall not be restrict-qualified."
+ if (TypeQuals & DeclSpec::TQ_restrict)
+ Diag(DS.getRestrictSpecLoc(),
+ diag::err_typecheck_invalid_restrict_not_pointer_noarg)
+ << DS.getSourceRange();
+ }
+
+ if (DS.isFriendSpecified()) {
+ // If we're dealing with a decl but not a TagDecl, assume that
+ // whatever routines created it handled the friendship aspect.
+ if (TagD && !Tag)
+ return 0;
+ return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
+ }
+
+ if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+ ProcessDeclAttributeList(S, Record, DS.getAttributes().getList());
+
+ if (!Record->getDeclName() && Record->isDefinition() &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
+ if (getLangOptions().CPlusPlus ||
+ Record->getDeclContext()->isRecord())
+ return BuildAnonymousStructOrUnion(S, DS, AS, Record);
+
+ Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
+ << DS.getSourceRange();
+ }
+ }
+
+ // Check for Microsoft C extension: anonymous struct.
+ if (getLangOptions().Microsoft && !getLangOptions().CPlusPlus &&
+ CurContext->isRecord() &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
+ // Handle 2 kinds of anonymous struct:
+ // struct STRUCT;
+ // and
+ // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct.
+ RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag);
+ if ((Record && Record->getDeclName() && !Record->isDefinition()) ||
+ (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+ DS.getRepAsType().get()->isStructureType())) {
+ Diag(DS.getSourceRange().getBegin(), diag::ext_ms_anonymous_struct)
+ << DS.getSourceRange();
+ return BuildMicrosoftCAnonymousStruct(S, DS, Record);
+ }
+ }
+
+ if (getLangOptions().CPlusPlus &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
+ if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
+ if (Enum->enumerator_begin() == Enum->enumerator_end() &&
+ !Enum->getIdentifier() && !Enum->isInvalidDecl())
+ Diag(Enum->getLocation(), diag::ext_no_declarators)
+ << DS.getSourceRange();
+
+ if (!DS.isMissingDeclaratorOk() &&
+ DS.getTypeSpecType() != DeclSpec::TST_error) {
+ // Warn about typedefs of enums without names, since this is an
+ // extension in both Microsoft and GNU.
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
+ Tag && isa<EnumDecl>(Tag)) {
+ Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name)
+ << DS.getSourceRange();
+ return Tag;
+ }
+
+ Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
+ << DS.getSourceRange();
+ }
+
+ return TagD;
+}
+
+/// ActOnVlaStmt - This rouine if finds a vla expression in a decl spec.
+/// builds a statement for it and returns it so it is evaluated.
+StmtResult Sema::ActOnVlaStmt(const DeclSpec &DS) {
+ StmtResult R;
+ if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr) {
+ Expr *Exp = DS.getRepAsExpr();
+ QualType Ty = Exp->getType();
+ if (Ty->isPointerType()) {
+ do
+ Ty = Ty->getAs<PointerType>()->getPointeeType();
+ while (Ty->isPointerType());
+ }
+ if (Ty->isVariableArrayType()) {
+ R = ActOnExprStmt(MakeFullExpr(Exp));
+ }
+ }
+ return R;
+}
+
+/// We are trying to inject an anonymous member into the given scope;
+/// check if there's an existing declaration that can't be overloaded.
+///
+/// \return true if this is a forbidden redeclaration
+static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
+ Scope *S,
+ DeclContext *Owner,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ unsigned diagnostic) {
+ LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
+ Sema::ForRedeclaration);
+ if (!SemaRef.LookupName(R, S)) return false;
+
+ if (R.getAsSingle<TagDecl>())
+ return false;
+
+ // Pick a representative declaration.
+ NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
+ assert(PrevDecl && "Expected a non-null Decl");
+
+ if (!SemaRef.isDeclInScope(PrevDecl, Owner, S))
+ return false;
+
+ SemaRef.Diag(NameLoc, diagnostic) << Name;
+ SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+ return true;
+}
+
+/// InjectAnonymousStructOrUnionMembers - Inject the members of the
+/// anonymous struct or union AnonRecord into the owning context Owner
+/// and scope S. This routine will be invoked just after we realize
+/// that an unnamed union or struct is actually an anonymous union or
+/// struct, e.g.,
+///
+/// @code
+/// union {
+/// int i;
+/// float f;
+/// }; // InjectAnonymousStructOrUnionMembers called here to inject i and
+/// // f into the surrounding scope.x
+/// @endcode
+///
+/// This routine is recursive, injecting the names of nested anonymous
+/// structs/unions into the owning context and scope as well.
+static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
+ DeclContext *Owner,
+ RecordDecl *AnonRecord,
+ AccessSpecifier AS,
+ llvm::SmallVector<NamedDecl*, 2> &Chaining,
+ bool MSAnonStruct) {
+ unsigned diagKind
+ = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
+ : diag::err_anonymous_struct_member_redecl;
+
+ bool Invalid = false;
+
+ // Look every FieldDecl and IndirectFieldDecl with a name.
+ for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(),
+ DEnd = AnonRecord->decls_end();
+ D != DEnd; ++D) {
+ if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) &&
+ cast<NamedDecl>(*D)->getDeclName()) {
+ ValueDecl *VD = cast<ValueDecl>(*D);
+ if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
+ VD->getLocation(), diagKind)) {
+ // C++ [class.union]p2:
+ // The names of the members of an anonymous union shall be
+ // distinct from the names of any other entity in the
+ // scope in which the anonymous union is declared.
+ Invalid = true;
+ } else {
+ // C++ [class.union]p2:
+ // For the purpose of name lookup, after the anonymous union
+ // definition, the members of the anonymous union are
+ // considered to have been defined in the scope in which the
+ // anonymous union is declared.
+ unsigned OldChainingSize = Chaining.size();
+ if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
+ for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(),
+ PE = IF->chain_end(); PI != PE; ++PI)
+ Chaining.push_back(*PI);
+ else
+ Chaining.push_back(VD);
+
+ assert(Chaining.size() >= 2);
+ NamedDecl **NamedChain =
+ new (SemaRef.Context)NamedDecl*[Chaining.size()];
+ for (unsigned i = 0; i < Chaining.size(); i++)
+ NamedChain[i] = Chaining[i];
+
+ IndirectFieldDecl* IndirectField =
+ IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(),
+ VD->getIdentifier(), VD->getType(),
+ NamedChain, Chaining.size());
+
+ IndirectField->setAccess(AS);
+ IndirectField->setImplicit();
+ SemaRef.PushOnScopeChains(IndirectField, S);
+
+ // That includes picking up the appropriate access specifier.
+ if (AS != AS_none) IndirectField->setAccess(AS);
+
+ Chaining.resize(OldChainingSize);
+ }
+ }
+ }
+
+ return Invalid;
+}
+
+/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
+/// a VarDecl::StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+ switch (StorageClassSpec) {
+ case DeclSpec::SCS_unspecified: return SC_None;
+ case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_static: return SC_Static;
+ case DeclSpec::SCS_auto: return SC_Auto;
+ case DeclSpec::SCS_register: return SC_Register;
+ case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
+ // Illegal SCSs map to None: error reporting is up to the caller.
+ case DeclSpec::SCS_mutable: // Fall through.
+ case DeclSpec::SCS_typedef: return SC_None;
+ }
+ llvm_unreachable("unknown storage class specifier");
+}
+
+/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
+/// a StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
+ switch (StorageClassSpec) {
+ case DeclSpec::SCS_unspecified: return SC_None;
+ case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_static: return SC_Static;
+ case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
+ // Illegal SCSs map to None: error reporting is up to the caller.
+ case DeclSpec::SCS_auto: // Fall through.
+ case DeclSpec::SCS_mutable: // Fall through.
+ case DeclSpec::SCS_register: // Fall through.
+ case DeclSpec::SCS_typedef: return SC_None;
+ }
+ llvm_unreachable("unknown storage class specifier");
+}
+
+/// BuildAnonymousStructOrUnion - Handle the declaration of an
+/// anonymous structure or union. Anonymous unions are a C++ feature
+/// (C++ [class.union]) and a GNU C extension; anonymous structures
+/// are a GNU C and GNU C++ extension.
+Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record) {
+ DeclContext *Owner = Record->getDeclContext();
+
+ // Diagnose whether this anonymous struct/union is an extension.
+ if (Record->isUnion() && !getLangOptions().CPlusPlus)
+ Diag(Record->getLocation(), diag::ext_anonymous_union);
+ else if (!Record->isUnion())
+ Diag(Record->getLocation(), diag::ext_anonymous_struct);
+
+ // C and C++ require different kinds of checks for anonymous
+ // structs/unions.
+ bool Invalid = false;
+ if (getLangOptions().CPlusPlus) {
+ const char* PrevSpec = 0;
+ unsigned DiagID;
+ // C++ [class.union]p3:
+ // Anonymous unions declared in a named namespace or in the
+ // global namespace shall be declared static.
+ if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
+ (isa<TranslationUnitDecl>(Owner) ||
+ (isa<NamespaceDecl>(Owner) &&
+ cast<NamespaceDecl>(Owner)->getDeclName()))) {
+ Diag(Record->getLocation(), diag::err_anonymous_union_not_static);
+ Invalid = true;
+
+ // Recover by adding 'static'.
+ DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(),
+ PrevSpec, DiagID, getLangOptions());
+ }
+ // C++ [class.union]p3:
+ // A storage class is not allowed in a declaration of an
+ // anonymous union in a class scope.
+ else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+ isa<RecordDecl>(Owner)) {
+ Diag(DS.getStorageClassSpecLoc(),
+ diag::err_anonymous_union_with_storage_spec);
+ Invalid = true;
+
+ // Recover by removing the storage specifier.
+ DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(),
+ PrevSpec, DiagID, getLangOptions());
+ }
+
+ // C++ [class.union]p2:
+ // The member-specification of an anonymous union shall only
+ // define non-static data members. [Note: nested types and
+ // functions cannot be declared within an anonymous union. ]
+ for (DeclContext::decl_iterator Mem = Record->decls_begin(),
+ MemEnd = Record->decls_end();
+ Mem != MemEnd; ++Mem) {
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) {
+ // C++ [class.union]p3:
+ // An anonymous union shall not have private or protected
+ // members (clause 11).
+ assert(FD->getAccess() != AS_none);
+ if (FD->getAccess() != AS_public) {
+ Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
+ << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
+ Invalid = true;
+ }
+
+ if (CheckNontrivialField(FD))
+ Invalid = true;
+ } else if ((*Mem)->isImplicit()) {
+ // Any implicit members are fine.
+ } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+ // This is a type that showed up in an
+ // elaborated-type-specifier inside the anonymous struct or
+ // union, but which actually declares a type outside of the
+ // anonymous struct or union. It's okay.
+ } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
+ if (!MemRecord->isAnonymousStructOrUnion() &&
+ MemRecord->getDeclName()) {
+ // Visual C++ allows type definition in anonymous struct or union.
+ if (getLangOptions().Microsoft)
+ Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
+ << (int)Record->isUnion();
+ else {
+ // This is a nested type declaration.
+ Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
+ << (int)Record->isUnion();
+ Invalid = true;
+ }
+ }
+ } else if (isa<AccessSpecDecl>(*Mem)) {
+ // Any access specifier is fine.
+ } else {
+ // We have something that isn't a non-static data
+ // member. Complain about it.
+ unsigned DK = diag::err_anonymous_record_bad_member;
+ if (isa<TypeDecl>(*Mem))
+ DK = diag::err_anonymous_record_with_type;
+ else if (isa<FunctionDecl>(*Mem))
+ DK = diag::err_anonymous_record_with_function;
+ else if (isa<VarDecl>(*Mem))
+ DK = diag::err_anonymous_record_with_static;
+
+ // Visual C++ allows type definition in anonymous struct or union.
+ if (getLangOptions().Microsoft &&
+ DK == diag::err_anonymous_record_with_type)
+ Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
+ << (int)Record->isUnion();
+ else {
+ Diag((*Mem)->getLocation(), DK)
+ << (int)Record->isUnion();
+ Invalid = true;
+ }
+ }
+ }
+ }
+
+ if (!Record->isUnion() && !Owner->isRecord()) {
+ Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
+ << (int)getLangOptions().CPlusPlus;
+ Invalid = true;
+ }
+
+ // Mock up a declarator.
+ Declarator Dc(DS, Declarator::TypeNameContext);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
+ assert(TInfo && "couldn't build declarator info for anonymous struct/union");
+
+ // Create a declaration for this anonymous struct/union.
+ NamedDecl *Anon = 0;
+ if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
+ Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),
+ /*IdentifierInfo=*/0,
+ Context.getTypeDeclType(Record),
+ TInfo,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ Anon->setAccess(AS);
+ if (getLangOptions().CPlusPlus)
+ FieldCollector->Add(cast<FieldDecl>(Anon));
+ } else {
+ DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
+ assert(SCSpec != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class VarDecl.");
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ if (SCSpec == DeclSpec::SCS_mutable) {
+ // mutable can only appear on non-static class members, so it's always
+ // an error here
+ Diag(Record->getLocation(), diag::err_mutable_nonmember);
+ Invalid = true;
+ SC = SC_None;
+ }
+ SCSpec = DS.getStorageClassSpecAsWritten();
+ VarDecl::StorageClass SCAsWritten
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+ Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
+ /*IdentifierInfo=*/0,
+ Context.getTypeDeclType(Record),
+ TInfo, SC, SCAsWritten);
+ }
+ Anon->setImplicit();
+
+ // Add the anonymous struct/union object to the current
+ // context. We'll be referencing this object when we refer to one of
+ // its members.
+ Owner->addDecl(Anon);
+
+ // Inject the members of the anonymous struct/union into the owning
+ // context and into the identifier resolver chain for name lookup
+ // purposes.
+ llvm::SmallVector<NamedDecl*, 2> Chain;
+ Chain.push_back(Anon);
+
+ if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS,
+ Chain, false))
+ Invalid = true;
+
+ // Mark this as an anonymous struct/union type. Note that we do not
+ // do this until after we have already checked and injected the
+ // members of this anonymous struct/union type, because otherwise
+ // the members could be injected twice: once by DeclContext when it
+ // builds its lookup table, and once by
+ // InjectAnonymousStructOrUnionMembers.
+ Record->setAnonymousStructOrUnion(true);
+
+ if (Invalid)
+ Anon->setInvalidDecl();
+
+ return Anon;
+}
+
+/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an
+/// Microsoft C anonymous structure.
+/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
+/// Example:
+///
+/// struct A { int a; };
+/// struct B { struct A; int b; };
+///
+/// void foo() {
+/// B var;
+/// var.a = 3;
+/// }
+///
+Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+ RecordDecl *Record) {
+
+ // If there is no Record, get the record via the typedef.
+ if (!Record)
+ Record = DS.getRepAsType().get()->getAsStructureType()->getDecl();
+
+ // Mock up a declarator.
+ Declarator Dc(DS, Declarator::TypeNameContext);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
+ assert(TInfo && "couldn't build declarator info for anonymous struct");
+
+ // Create a declaration for this anonymous struct.
+ NamedDecl* Anon = FieldDecl::Create(Context,
+ cast<RecordDecl>(CurContext),
+ DS.getSourceRange().getBegin(),
+ /*IdentifierInfo=*/0,
+ Context.getTypeDeclType(Record),
+ TInfo,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ Anon->setImplicit();
+
+ // Add the anonymous struct object to the current context.
+ CurContext->addDecl(Anon);
+
+ // Inject the members of the anonymous struct into the current
+ // context and into the identifier resolver chain for name lookup
+ // purposes.
+ llvm::SmallVector<NamedDecl*, 2> Chain;
+ Chain.push_back(Anon);
+
+ if (InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
+ Record->getDefinition(),
+ AS_none, Chain, true))
+ Anon->setInvalidDecl();
+
+ return Anon;
+}
+
+/// GetNameForDeclarator - Determine the full declaration name for the
+/// given Declarator.
+DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
+ return GetNameFromUnqualifiedId(D.getName());
+}
+
+/// \brief Retrieves the declaration name from a parsed unqualified-id.
+DeclarationNameInfo
+Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
+ DeclarationNameInfo NameInfo;
+ NameInfo.setLoc(Name.StartLocation);
+
+ switch (Name.getKind()) {
+
+ case UnqualifiedId::IK_Identifier:
+ NameInfo.setName(Name.Identifier);
+ NameInfo.setLoc(Name.StartLocation);
+ return NameInfo;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
+ = Name.OperatorFunctionId.SymbolLocations[0];
+ NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
+ = Name.EndLocation.getRawEncoding();
+ return NameInfo;
+
+ case UnqualifiedId::IK_LiteralOperatorId:
+ NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
+ Name.Identifier));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
+ return NameInfo;
+
+ case UnqualifiedId::IK_ConversionFunctionId: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_ConstructorName: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_ConstructorTemplateId: {
+ // In well-formed code, we can only have a constructor
+ // template-id that refers to the current context, so go there
+ // to find the actual type being constructed.
+ CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
+ if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
+ return DeclarationNameInfo();
+
+ // Determine the type of the class being constructed.
+ QualType CurClassType = Context.getTypeDeclType(CurClass);
+
+ // FIXME: Check two things: that the template-id names the same type as
+ // CurClassType, and that the template-id does not occur when the name
+ // was qualified.
+
+ NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(CurClassType)));
+ NameInfo.setLoc(Name.StartLocation);
+ // FIXME: should we retrieve TypeSourceInfo?
+ NameInfo.setNamedTypeInfo(0);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_TemplateId: {
+ TemplateName TName = Name.TemplateId->Template.get();
+ SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
+ return Context.getNameForTemplate(TName, TNameLoc);
+ }
+
+ } // switch (Name.getKind())
+
+ assert(false && "Unknown name kind");
+ return DeclarationNameInfo();
+}
+
+/// isNearlyMatchingFunction - Determine whether the C++ functions
+/// Declaration and Definition are "nearly" matching. This heuristic
+/// is used to improve diagnostics in the case where an out-of-line
+/// function definition doesn't match any declaration within
+/// the class or namespace.
+static bool isNearlyMatchingFunction(ASTContext &Context,
+ FunctionDecl *Declaration,
+ FunctionDecl *Definition) {
+ if (Declaration->param_size() != Definition->param_size())
+ return false;
+ for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
+ QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType();
+ QualType DefParamTy = Definition->getParamDecl(Idx)->getType();
+
+ if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(),
+ DefParamTy.getNonReferenceType()))
+ return false;
+ }
+
+ return true;
+}
+
+/// NeedsRebuildingInCurrentInstantiation - Checks whether the given
+/// declarator needs to be rebuilt in the current instantiation.
+/// Any bits of declarator which appear before the name are valid for
+/// consideration here. That's specifically the type in the decl spec
+/// and the base type in any member-pointer chunks.
+static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
+ DeclarationName Name) {
+ // The types we specifically need to rebuild are:
+ // - typenames, typeofs, and decltypes
+ // - types which will become injected class names
+ // Of course, we also need to rebuild any type referencing such a
+ // type. It's safest to just say "dependent", but we call out a
+ // few cases here.
+
+ DeclSpec &DS = D.getMutableDeclSpec();
+ switch (DS.getTypeSpecType()) {
+ case DeclSpec::TST_typename:
+ case DeclSpec::TST_typeofType:
+ case DeclSpec::TST_decltype: {
+ // Grab the type from the parser.
+ TypeSourceInfo *TSI = 0;
+ QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
+ if (T.isNull() || !T->isDependentType()) break;
+
+ // Make sure there's a type source info. This isn't really much
+ // of a waste; most dependent types should have type source info
+ // attached already.
+ if (!TSI)
+ TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc());
+
+ // Rebuild the type in the current instantiation.
+ TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name);
+ if (!TSI) return true;
+
+ // Store the new type back in the decl spec.
+ ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI);
+ DS.UpdateTypeRep(LocType);
+ break;
+ }
+
+ case DeclSpec::TST_typeofExpr: {
+ Expr *E = DS.getRepAsExpr();
+ ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
+ if (Result.isInvalid()) return true;
+ DS.UpdateExprRep(Result.get());
+ break;
+ }
+
+ default:
+ // Nothing to do for these decl specs.
+ break;
+ }
+
+ // It doesn't matter what order we do this in.
+ for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
+ DeclaratorChunk &Chunk = D.getTypeObject(I);
+
+ // The only type information in the declarator which can come
+ // before the declaration name is the base type of a member
+ // pointer.
+ if (Chunk.Kind != DeclaratorChunk::MemberPointer)
+ continue;
+
+ // Rebuild the scope specifier in-place.
+ CXXScopeSpec &SS = Chunk.Mem.Scope();
+ if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS))
+ return true;
+ }
+
+ return false;
+}
+
+Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
+ return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
+}
+
+Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition) {
+ // TODO: consider using NameInfo for diagnostic.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+
+ // All of these full declarators require an identifier. If it doesn't have
+ // one, the ParsedFreeStandingDeclSpec action should be used.
+ if (!Name) {
+ if (!D.isInvalidType()) // Reject this if we think it is valid.
+ Diag(D.getDeclSpec().getSourceRange().getBegin(),
+ diag::err_declarator_need_ident)
+ << D.getDeclSpec().getSourceRange() << D.getSourceRange();
+ return 0;
+ } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
+ return 0;
+
+ // The scope passed in may not be a decl scope. Zip up the scope tree until
+ // we find one that is.
+ while ((S->getFlags() & Scope::DeclScope) == 0 ||
+ (S->getFlags() & Scope::TemplateParamScope) != 0)
+ S = S->getParent();
+
+ DeclContext *DC = CurContext;
+ if (D.getCXXScopeSpec().isInvalid())
+ D.setInvalidType();
+ else if (D.getCXXScopeSpec().isSet()) {
+ if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(),
+ UPPC_DeclarationQualifier))
+ return 0;
+
+ bool EnteringContext = !D.getDeclSpec().isFriendSpecified();
+ DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext);
+ if (!DC) {
+ // If we could not compute the declaration context, it's because the
+ // declaration context is dependent but does not refer to a class,
+ // class template, or class template partial specialization. Complain
+ // and return early, to avoid the coming semantic disaster.
+ Diag(D.getIdentifierLoc(),
+ diag::err_template_qualified_declarator_no_match)
+ << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+ << D.getCXXScopeSpec().getRange();
+ return 0;
+ }
+
+ bool IsDependentContext = DC->isDependentContext();
+
+ if (!IsDependentContext &&
+ RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
+ return 0;
+
+ if (isa<CXXRecordDecl>(DC)) {
+ if (!cast<CXXRecordDecl>(DC)->hasDefinition()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_member_def_undefined_record)
+ << Name << DC << D.getCXXScopeSpec().getRange();
+ D.setInvalidType();
+ } else if (isa<CXXRecordDecl>(CurContext) &&
+ !D.getDeclSpec().isFriendSpecified()) {
+ // The user provided a superfluous scope specifier inside a class
+ // definition:
+ //
+ // class X {
+ // void X::f();
+ // };
+ if (CurContext->Equals(DC))
+ Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
+ << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
+ else
+ Diag(D.getIdentifierLoc(), diag::err_member_qualification)
+ << Name << D.getCXXScopeSpec().getRange();
+
+ // Pretend that this qualifier was not here.
+ D.getCXXScopeSpec().clear();
+ }
+ }
+
+ // Check whether we need to rebuild the type of the given
+ // declaration in the current instantiation.
+ if (EnteringContext && IsDependentContext &&
+ TemplateParamLists.size() != 0) {
+ ContextRAII SavedContext(*this, DC);
+ if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name))
+ D.setInvalidType();
+ }
+ }
+
+ // C++ [class.mem]p13:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // - every static data member of class T;
+ // - every member function of class T
+ // - every member of class T that is itself a type;
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getIdentifier() && Record->getDeclName() == Name) {
+ Diag(D.getIdentifierLoc(), diag::err_member_name_of_class)
+ << Name;
+
+ // If this is a typedef, we'll end up spewing multiple diagnostics.
+ // Just return early; it's safer.
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return 0;
+ }
+
+ NamedDecl *New;
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType R = TInfo->getType();
+
+ if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_DeclarationType))
+ D.setInvalidType();
+
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForRedeclaration);
+
+ // See if this is a redefinition of a variable in the same scope.
+ if (!D.getCXXScopeSpec().isSet()) {
+ bool IsLinkageLookup = false;
+
+ // If the declaration we're planning to build will be a function
+ // or object with linkage, then look for another declaration with
+ // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6).
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ /* Do nothing*/;
+ else if (R->isFunctionType()) {
+ if (CurContext->isFunctionOrMethod() ||
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+ IsLinkageLookup = true;
+ } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
+ IsLinkageLookup = true;
+ else if (CurContext->getRedeclContext()->isTranslationUnit() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+ IsLinkageLookup = true;
+
+ if (IsLinkageLookup)
+ Previous.clear(LookupRedeclarationWithLinkage);
+
+ LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
+ } else { // Something like "int foo::x;"
+ LookupQualifiedName(Previous, DC);
+
+ // Don't consider using declarations as previous declarations for
+ // out-of-line members.
+ RemoveUsingDecls(Previous);
+
+ // C++ 7.3.1.2p2:
+ // Members (including explicit specializations of templates) of a named
+ // namespace can also be defined outside that namespace by explicit
+ // qualification of the name being defined, provided that the entity being
+ // defined was already declared in the namespace and the definition appears
+ // after the point of declaration in a namespace that encloses the
+ // declarations namespace.
+ //
+ // Note that we only check the context at this point. We don't yet
+ // have enough information to make sure that PrevDecl is actually
+ // the declaration we want to match. For example, given:
+ //
+ // class X {
+ // void f();
+ // void f(float);
+ // };
+ //
+ // void X::f(int) { } // ill-formed
+ //
+ // In this case, PrevDecl will point to the overload set
+ // containing the two f's declared in X, but neither of them
+ // matches.
+
+ // First check whether we named the global scope.
+ if (isa<TranslationUnitDecl>(DC)) {
+ Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
+ << Name << D.getCXXScopeSpec().getRange();
+ } else {
+ DeclContext *Cur = CurContext;
+ while (isa<LinkageSpecDecl>(Cur))
+ Cur = Cur->getParent();
+ if (!Cur->Encloses(DC)) {
+ // The qualifying scope doesn't enclose the original declaration.
+ // Emit diagnostic based on current scope.
+ SourceLocation L = D.getIdentifierLoc();
+ SourceRange R = D.getCXXScopeSpec().getRange();
+ if (isa<FunctionDecl>(Cur))
+ Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
+ else
+ Diag(L, diag::err_invalid_declarator_scope)
+ << Name << cast<NamedDecl>(DC) << R;
+ D.setInvalidType();
+ }
+ }
+ }
+
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ if (!D.isInvalidType())
+ if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+ Previous.getFoundDecl()))
+ D.setInvalidType();
+
+ // Just pretend that we didn't see the previous declaration.
+ Previous.clear();
+ }
+
+ // In C++, the previous declaration we find might be a tag type
+ // (class or enum). In this case, the new declaration will hide the
+ // tag type. Note that this does does not apply if we're declaring a
+ // typedef (C++ [dcl.typedef]p4).
+ if (Previous.isSingleTagDecl() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
+ Previous.clear();
+
+ bool Redeclaration = false;
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ if (TemplateParamLists.size()) {
+ Diag(D.getIdentifierLoc(), diag::err_template_typedef);
+ return 0;
+ }
+
+ New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration);
+ } else if (R->isFunctionType()) {
+ New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
+ move(TemplateParamLists),
+ IsFunctionDefinition, Redeclaration);
+ } else {
+ New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
+ move(TemplateParamLists),
+ Redeclaration);
+ }
+
+ if (New == 0)
+ return 0;
+
+ // If this has an identifier and is not an invalid redeclaration or
+ // function template specialization, add it to the scope stack.
+ if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl()))
+ PushOnScopeChains(New, S);
+
+ return New;
+}
+
+/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
+/// types into constant array types in certain situations which would otherwise
+/// be errors (for GCC compatibility).
+static QualType TryToFixInvalidVariablyModifiedType(QualType T,
+ ASTContext &Context,
+ bool &SizeIsNegative,
+ llvm::APSInt &Oversized) {
+ // This method tries to turn a variable array into a constant
+ // array even when the size isn't an ICE. This is necessary
+ // for compatibility with code that depends on gcc's buggy
+ // constant expression folding, like struct {char x[(int)(char*)2];}
+ SizeIsNegative = false;
+ Oversized = 0;
+
+ if (T->isDependentType())
+ return QualType();
+
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
+ if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
+ QualType Pointee = PTy->getPointeeType();
+ QualType FixedType =
+ TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative,
+ Oversized);
+ if (FixedType.isNull()) return FixedType;
+ FixedType = Context.getPointerType(FixedType);
+ return Qs.apply(Context, FixedType);
+ }
+ if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) {
+ QualType Inner = PTy->getInnerType();
+ QualType FixedType =
+ TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative,
+ Oversized);
+ if (FixedType.isNull()) return FixedType;
+ FixedType = Context.getParenType(FixedType);
+ return Qs.apply(Context, FixedType);
+ }
+
+ const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
+ if (!VLATy)
+ return QualType();
+ // FIXME: We should probably handle this case
+ if (VLATy->getElementType()->isVariablyModifiedType())
+ return QualType();
+
+ Expr::EvalResult EvalResult;
+ if (!VLATy->getSizeExpr() ||
+ !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) ||
+ !EvalResult.Val.isInt())
+ return QualType();
+
+ // Check whether the array size is negative.
+ llvm::APSInt &Res = EvalResult.Val.getInt();
+ if (Res.isSigned() && Res.isNegative()) {
+ SizeIsNegative = true;
+ return QualType();
+ }
+
+ // Check whether the array is too large to be addressed.
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
+ Res);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ Oversized = Res;
+ return QualType();
+ }
+
+ return Context.getConstantArrayType(VLATy->getElementType(),
+ Res, ArrayType::Normal, 0);
+}
+
+/// \brief Register the given locally-scoped external C declaration so
+/// that it can be found later for redeclarations
+void
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+ const LookupResult &Previous,
+ Scope *S) {
+ assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
+ "Decl is not a locally-scoped decl!");
+ // Note that we have a locally-scoped external with this name.
+ LocallyScopedExternalDecls[ND->getDeclName()] = ND;
+
+ if (!Previous.isSingleResult())
+ return;
+
+ NamedDecl *PrevDecl = Previous.getFoundDecl();
+
+ // If there was a previous declaration of this variable, it may be
+ // in our identifier chain. Update the identifier chain with the new
+ // declaration.
+ if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
+ // The previous declaration was found on the identifer resolver
+ // chain, so remove it from its scope.
+ while (S && !S->isDeclScope(PrevDecl))
+ S = S->getParent();
+
+ if (S)
+ S->RemoveDecl(PrevDecl);
+ }
+}
+
+/// \brief Diagnose function specifiers on a declaration of an identifier that
+/// does not identify a function.
+void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+ // FIXME: We should probably indicate the identifier in question to avoid
+ // confusion for constructs like "inline int a(), b;"
+ if (D.getDeclSpec().isInlineSpecified())
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_inline_non_function);
+
+ if (D.getDeclSpec().isVirtualSpecified())
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ diag::err_virtual_non_function);
+
+ if (D.getDeclSpec().isExplicitSpecified())
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_non_function);
+}
+
+NamedDecl*
+Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous, bool &Redeclaration) {
+ // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
+ if (D.getCXXScopeSpec().isSet()) {
+ Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
+ << D.getCXXScopeSpec().getRange();
+ D.setInvalidType();
+ // Pretend we didn't see the scope specifier.
+ DC = CurContext;
+ Previous.clear();
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ // Check that there are no default arguments (C++ only).
+ CheckExtraCXXDefaultArguments(D);
+ }
+
+ DiagnoseFunctionSpecifiers(D);
+
+ if (D.getDeclSpec().isThreadSpecified())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+ if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
+ Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
+ << D.getName().getSourceRange();
+ return 0;
+ }
+
+ TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo);
+ if (!NewTD) return 0;
+
+ // Handle attributes prior to checking for duplicates in MergeVarDecl
+ ProcessDeclAttributes(S, NewTD, D);
+
+ // C99 6.7.7p2: If a typedef name specifies a variably modified type
+ // then it shall have block scope.
+ // Note that variably modified types must be fixed before merging the decl so
+ // that redeclarations will match.
+ QualType T = NewTD->getUnderlyingType();
+ if (T->isVariablyModifiedType()) {
+ getCurFunction()->setHasBranchProtectedScope();
+
+ if (S->getFnParent() == 0) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ QualType FixedTy =
+ TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
+ if (!FixedTy.isNull()) {
+ Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
+ NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
+ } else {
+ if (SizeIsNegative)
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
+ else if (T->isVariableArrayType())
+ Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
+ else if (Oversized.getBoolValue())
+ Diag(D.getIdentifierLoc(), diag::err_array_too_large)
+ << Oversized.toString(10);
+ else
+ Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
+ NewTD->setInvalidDecl();
+ }
+ }
+ }
+
+ // Merge the decl with the existing one if appropriate. If the decl is
+ // in an outer scope, it isn't the same thing.
+ FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+ if (!Previous.empty()) {
+ Redeclaration = true;
+ MergeTypeDefDecl(NewTD, Previous);
+ }
+
+ // If this is the C FILE type, notify the AST context.
+ if (IdentifierInfo *II = NewTD->getIdentifier())
+ if (!NewTD->isInvalidDecl() &&
+ NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+ if (II->isStr("FILE"))
+ Context.setFILEDecl(NewTD);
+ else if (II->isStr("jmp_buf"))
+ Context.setjmp_bufDecl(NewTD);
+ else if (II->isStr("sigjmp_buf"))
+ Context.setsigjmp_bufDecl(NewTD);
+ else if (II->isStr("__builtin_va_list"))
+ Context.setBuiltinVaListType(Context.getTypedefType(NewTD));
+ }
+
+ return NewTD;
+}
+
+/// \brief Determines whether the given declaration is an out-of-scope
+/// previous declaration.
+///
+/// This routine should be invoked when name lookup has found a
+/// previous declaration (PrevDecl) that is not in the scope where a
+/// new declaration by the same name is being introduced. If the new
+/// declaration occurs in a local scope, previous declarations with
+/// linkage may still be considered previous declarations (C99
+/// 6.2.2p4-5, C++ [basic.link]p6).
+///
+/// \param PrevDecl the previous declaration found by name
+/// lookup
+///
+/// \param DC the context in which the new declaration is being
+/// declared.
+///
+/// \returns true if PrevDecl is an out-of-scope previous declaration
+/// for a new delcaration with the same name.
+static bool
+isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
+ ASTContext &Context) {
+ if (!PrevDecl)
+ return false;
+
+ if (!PrevDecl->hasLinkage())
+ return false;
+
+ if (Context.getLangOptions().CPlusPlus) {
+ // C++ [basic.link]p6:
+ // If there is a visible declaration of an entity with linkage
+ // having the same name and type, ignoring entities declared
+ // outside the innermost enclosing namespace scope, the block
+ // scope declaration declares that same entity and receives the
+ // linkage of the previous declaration.
+ DeclContext *OuterContext = DC->getRedeclContext();
+ if (!OuterContext->isFunctionOrMethod())
+ // This rule only applies to block-scope declarations.
+ return false;
+
+ DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
+ if (PrevOuterContext->isRecord())
+ // We found a member function: ignore it.
+ return false;
+
+ // Find the innermost enclosing namespace for the new and
+ // previous declarations.
+ OuterContext = OuterContext->getEnclosingNamespaceContext();
+ PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext();
+
+ // The previous declaration is in a different namespace, so it
+ // isn't the same function.
+ if (!OuterContext->Equals(PrevOuterContext))
+ return false;
+ }
+
+ return true;
+}
+
+static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
+ CXXScopeSpec &SS = D.getCXXScopeSpec();
+ if (!SS.isSet()) return;
+ DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getRange());
+}
+
+NamedDecl*
+Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &Redeclaration) {
+ DeclarationName Name = GetNameForDeclarator(D).getName();
+
+ // Check that there are no default arguments (C++ only).
+ if (getLangOptions().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
+ assert(SCSpec != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class VarDecl.");
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+ if (SCSpec == DeclSpec::SCS_mutable) {
+ // mutable can only appear on non-static class members, so it's always
+ // an error here
+ Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
+ D.setInvalidType();
+ SC = SC_None;
+ }
+ SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+ VarDecl::StorageClass SCAsWritten
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ if (!II) {
+ Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
+ << Name.getAsString();
+ return 0;
+ }
+
+ DiagnoseFunctionSpecifiers(D);
+
+ if (!DC->isRecord() && S->getFnParent() == 0) {
+ // C99 6.9p2: The storage-class specifiers auto and register shall not
+ // appear in the declaration specifiers in an external declaration.
+ if (SC == SC_Auto || SC == SC_Register) {
+
+ // If this is a register variable with an asm label specified, then this
+ // is a GNU extension.
+ if (SC == SC_Register && D.getAsmLabel())
+ Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
+ else
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
+ D.setInvalidType();
+ }
+ }
+
+ bool isExplicitSpecialization = false;
+ VarDecl *NewVD;
+ if (!getLangOptions().CPlusPlus) {
+ NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, TInfo, SC, SCAsWritten);
+
+ if (D.isInvalidType())
+ NewVD->setInvalidDecl();
+ } else {
+ if (DC->isRecord() && !CurContext->isRecord()) {
+ // This is an out-of-line definition of a static data member.
+ if (SC == SC_Static) {
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_static_out_of_line)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ } else if (SC == SC_None)
+ SC = SC_Static;
+ }
+ if (SC == SC_Static) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ if (RD->isLocalClass())
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_local_class)
+ << Name << RD->getDeclName();
+
+ // C++ [class.union]p1: If a union contains a static data member,
+ // the program is ill-formed.
+ //
+ // We also disallow static data members in anonymous structs.
+ if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName()))
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_union_or_anon_struct)
+ << Name << RD->isUnion();
+ }
+ }
+
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+ bool Invalid = false;
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ D.getCXXScopeSpec(),
+ TemplateParamLists.get(),
+ TemplateParamLists.size(),
+ /*never a friend*/ false,
+ isExplicitSpecialization,
+ Invalid)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams->size() > 0) {
+ // There is no such thing as a variable template.
+ Diag(D.getIdentifierLoc(), diag::err_template_variable)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ return 0;
+ } else {
+ // There is an extraneous 'template<>' for this variable. Complain
+ // about it, but allow the declaration of the variable.
+ Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_variable_noparams)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+
+ isExplicitSpecialization = true;
+ }
+ }
+
+ NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, TInfo, SC, SCAsWritten);
+
+ // If this decl has an auto type in need of deduction, mark the VarDecl so
+ // we can diagnose uses of it in its own initializer.
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) {
+ NewVD->setParsingAutoInit(R->getContainedAutoType());
+ }
+
+ if (D.isInvalidType() || Invalid)
+ NewVD->setInvalidDecl();
+
+ SetNestedNameSpecifier(NewVD, D);
+
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+ NewVD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ TemplateParamLists.release());
+ }
+ }
+
+ if (D.getDeclSpec().isThreadSpecified()) {
+ if (NewVD->hasLocalStorage())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
+ else if (!Context.Target.isTLSSupported())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported);
+ else
+ NewVD->setThreadSpecified(true);
+ }
+
+ // Set the lexical context. If the declarator has a C++ scope specifier, the
+ // lexical context will be different from the semantic context.
+ NewVD->setLexicalDeclContext(CurContext);
+
+ // Handle attributes prior to checking for duplicates in MergeVarDecl
+ ProcessDeclAttributes(S, NewVD, D);
+
+ // Handle GNU asm-label extension (encoded as an attribute).
+ if (Expr *E = (Expr*)D.getAsmLabel()) {
+ // The parser guarantees this is a string.
+ StringLiteral *SE = cast<StringLiteral>(E);
+ llvm::StringRef Label = SE->getString();
+ if (S->getFnParent() != 0) {
+ switch (SC) {
+ case SC_None:
+ case SC_Auto:
+ Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label;
+ break;
+ case SC_Register:
+ if (!Context.Target.isValidGCCRegisterName(Label))
+ Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ break;
+ case SC_Static:
+ case SC_Extern:
+ case SC_PrivateExtern:
+ break;
+ }
+ }
+
+ NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
+ Context, Label));
+ }
+
+ // Diagnose shadowed variables before filtering for scope.
+ if (!D.getCXXScopeSpec().isSet())
+ CheckShadow(S, NewVD, Previous);
+
+ // Don't consider existing declarations that are in a different
+ // scope and are out-of-semantic-context declarations (if the new
+ // declaration has linkage).
+ FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
+
+ if (!getLangOptions().CPlusPlus)
+ CheckVariableDeclaration(NewVD, Previous, Redeclaration);
+ else {
+ // Merge the decl with the existing one if appropriate.
+ if (!Previous.empty()) {
+ if (Previous.isSingleResult() &&
+ isa<FieldDecl>(Previous.getFoundDecl()) &&
+ D.getCXXScopeSpec().isSet()) {
+ // The user tried to define a non-static data member
+ // out-of-line (C++ [dcl.meaning]p1).
+ Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
+ << D.getCXXScopeSpec().getRange();
+ Previous.clear();
+ NewVD->setInvalidDecl();
+ }
+ } else if (D.getCXXScopeSpec().isSet()) {
+ // No previous declaration in the qualifying scope.
+ Diag(D.getIdentifierLoc(), diag::err_no_member)
+ << Name << computeDeclContext(D.getCXXScopeSpec(), true)
+ << D.getCXXScopeSpec().getRange();
+ NewVD->setInvalidDecl();
+ }
+
+ CheckVariableDeclaration(NewVD, Previous, Redeclaration);
+
+ // This is an explicit specialization of a static data member. Check it.
+ if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ CheckMemberSpecialization(NewVD, Previous))
+ NewVD->setInvalidDecl();
+ }
+
+ // attributes declared post-definition are currently ignored
+ // FIXME: This should be handled in attribute merging, not
+ // here.
+ if (Previous.isSingleResult()) {
+ VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
+ if (Def && (Def = Def->getDefinition()) &&
+ Def != NewVD && D.hasAttributes()) {
+ Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ }
+ }
+
+ // If this is a locally-scoped extern C variable, update the map of
+ // such variables.
+ if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
+ !NewVD->isInvalidDecl())
+ RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
+
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this variable.
+ if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ AddPushedVisibilityAttribute(NewVD);
+
+ MarkUnusedFileScopedDecl(NewVD);
+
+ return NewVD;
+}
+
+/// \brief Diagnose variable or built-in function shadowing. Implements
+/// -Wshadow.
+///
+/// This method is called whenever a VarDecl is added to a "useful"
+/// scope.
+///
+/// \param S the scope in which the shadowing name is being declared
+/// \param R the lookup of the name
+///
+void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
+ // Return if warning is ignored.
+ if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) ==
+ Diagnostic::Ignored)
+ return;
+
+ // Don't diagnose declarations at file scope.
+ DeclContext *NewDC = D->getDeclContext();
+ if (NewDC->isFileContext())
+ return;
+
+ // Only diagnose if we're shadowing an unambiguous field or variable.
+ if (R.getResultKind() != LookupResult::Found)
+ return;
+
+ NamedDecl* ShadowedDecl = R.getFoundDecl();
+ if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
+ return;
+
+ // Fields are not shadowed by variables in C++ static methods.
+ if (isa<FieldDecl>(ShadowedDecl))
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
+ if (MD->isStatic())
+ return;
+
+ if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl))
+ if (shadowedVar->isExternC()) {
+ // Don't warn for this case:
+ //
+ // @code
+ // extern int bob;
+ // void f() {
+ // extern int bob;
+ // }
+ // @endcode
+ if (D->isExternC())
+ return;
+
+ // For shadowing external vars, make sure that we point to the global
+ // declaration, not a locally scoped extern declaration.
+ for (VarDecl::redecl_iterator
+ I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end();
+ I != E; ++I)
+ if (I->isFileVarDecl()) {
+ ShadowedDecl = *I;
+ break;
+ }
+ }
+
+ DeclContext *OldDC = ShadowedDecl->getDeclContext();
+
+ // Only warn about certain kinds of shadowing for class members.
+ if (NewDC && NewDC->isRecord()) {
+ // In particular, don't warn about shadowing non-class members.
+ if (!OldDC->isRecord())
+ return;
+
+ // TODO: should we warn about static data members shadowing
+ // static data members from base classes?
+
+ // TODO: don't diagnose for inaccessible shadowed members.
+ // This is hard to do perfectly because we might friend the
+ // shadowing context, but that's just a false negative.
+ }
+
+ // Determine what kind of declaration we're shadowing.
+ unsigned Kind;
+ if (isa<RecordDecl>(OldDC)) {
+ if (isa<FieldDecl>(ShadowedDecl))
+ Kind = 3; // field
+ else
+ Kind = 2; // static data member
+ } else if (OldDC->isFileContext())
+ Kind = 1; // global
+ else
+ Kind = 0; // local
+
+ DeclarationName Name = R.getLookupName();
+
+ // Emit warning and note.
+ Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
+ Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
+}
+
+/// \brief Check -Wshadow without the advantage of a previous lookup.
+void Sema::CheckShadow(Scope *S, VarDecl *D) {
+ if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) ==
+ Diagnostic::Ignored)
+ return;
+
+ LookupResult R(*this, D->getDeclName(), D->getLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ LookupName(R, S);
+ CheckShadow(S, D, R);
+}
+
+/// \brief Perform semantic checking on a newly-created variable
+/// declaration.
+///
+/// This routine performs all of the type-checking required for a
+/// variable declaration once it has been built. It is used both to
+/// check variables after they have been parsed and their declarators
+/// have been translated into a declaration, and to check variables
+/// that have been instantiated from a template.
+///
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+void Sema::CheckVariableDeclaration(VarDecl *NewVD,
+ LookupResult &Previous,
+ bool &Redeclaration) {
+ // If the decl is already known invalid, don't check it.
+ if (NewVD->isInvalidDecl())
+ return;
+
+ QualType T = NewVD->getType();
+
+ if (T->isObjCObjectType()) {
+ Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
+ return NewVD->setInvalidDecl();
+ }
+
+ // Emit an error if an address space was applied to decl with local storage.
+ // This includes arrays of objects with address space qualifiers, but not
+ // automatic variables that point to other address spaces.
+ // ISO/IEC TR 18037 S5.1.2
+ if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+ Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
+ return NewVD->setInvalidDecl();
+ }
+
+ if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
+ && !NewVD->hasAttr<BlocksAttr>())
+ Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
+
+ bool isVM = T->isVariablyModifiedType();
+ if (isVM || NewVD->hasAttr<CleanupAttr>() ||
+ NewVD->hasAttr<BlocksAttr>())
+ getCurFunction()->setHasBranchProtectedScope();
+
+ if ((isVM && NewVD->hasLinkage()) ||
+ (T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ QualType FixedTy =
+ TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
+
+ if (FixedTy.isNull() && T->isVariableArrayType()) {
+ const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
+ // FIXME: This won't give the correct result for
+ // int a[10][n];
+ SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
+
+ if (NewVD->isFileVarDecl())
+ Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
+ << SizeRange;
+ else if (NewVD->getStorageClass() == SC_Static)
+ Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
+ << SizeRange;
+ else
+ Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
+ << SizeRange;
+ return NewVD->setInvalidDecl();
+ }
+
+ if (FixedTy.isNull()) {
+ if (NewVD->isFileVarDecl())
+ Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
+ else
+ Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
+ return NewVD->setInvalidDecl();
+ }
+
+ Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
+ NewVD->setType(FixedTy);
+ }
+
+ if (Previous.empty() && NewVD->isExternC()) {
+ // Since we did not find anything by this name and we're declaring
+ // an extern "C" variable, look for a non-visible extern "C"
+ // declaration with the same name.
+ llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+ = LocallyScopedExternalDecls.find(NewVD->getDeclName());
+ if (Pos != LocallyScopedExternalDecls.end())
+ Previous.addDecl(Pos->second);
+ }
+
+ if (T->isVoidType() && !NewVD->hasExternalStorage()) {
+ Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
+ << T;
+ return NewVD->setInvalidDecl();
+ }
+
+ if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+ Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
+ return NewVD->setInvalidDecl();
+ }
+
+ if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+ Diag(NewVD->getLocation(), diag::err_block_on_vm);
+ return NewVD->setInvalidDecl();
+ }
+
+ // Function pointers and references cannot have qualified function type, only
+ // function pointer-to-members can do that.
+ QualType Pointee;
+ unsigned PtrOrRef = 0;
+ if (const PointerType *Ptr = T->getAs<PointerType>())
+ Pointee = Ptr->getPointeeType();
+ else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
+ Pointee = Ref->getPointeeType();
+ PtrOrRef = 1;
+ }
+ if (!Pointee.isNull() && Pointee->isFunctionProtoType() &&
+ Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) {
+ Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer)
+ << PtrOrRef;
+ return NewVD->setInvalidDecl();
+ }
+
+ if (!Previous.empty()) {
+ Redeclaration = true;
+ MergeVarDecl(NewVD, Previous);
+ }
+}
+
+/// \brief Data used with FindOverriddenMethod
+struct FindOverriddenMethodData {
+ Sema *S;
+ CXXMethodDecl *Method;
+};
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overrides a method in a base class, to be used with
+/// CXXRecordDecl::lookupInBases().
+static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ FindOverriddenMethodData *Data
+ = reinterpret_cast<FindOverriddenMethodData*>(UserData);
+
+ DeclarationName Name = Data->Method->getDeclName();
+
+ // FIXME: Do we care about other names here too?
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // We really want to find the base class destructor here.
+ QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = Data->S->Context.getCanonicalType(T);
+
+ Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
+ }
+
+ for (Path.Decls = BaseRecord->lookup(Name);
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ NamedDecl *D = *Path.Decls.first;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+ // Look for virtual methods in base classes that this method might override.
+ CXXBasePaths Paths;
+ FindOverriddenMethodData Data;
+ Data.Method = MD;
+ Data.S = this;
+ bool AddedAny = false;
+ if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
+ E = Paths.found_decls_end(); I != E; ++I) {
+ if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+ if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+ !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
+ MD->addOverriddenMethod(OldMD->getCanonicalDecl());
+ AddedAny = true;
+ }
+ }
+ }
+ }
+
+ return AddedAny;
+}
+
+static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD) {
+ LookupResult Prev(S, NewFD->getDeclName(), NewFD->getLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ S.LookupQualifiedName(Prev, NewFD->getDeclContext());
+ assert(!Prev.isAmbiguous() &&
+ "Cannot have an ambiguity in previous-declaration lookup");
+ for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+ Func != FuncEnd; ++Func) {
+ if (isa<FunctionDecl>(*Func) &&
+ isNearlyMatchingFunction(S.Context, cast<FunctionDecl>(*Func), NewFD))
+ S.Diag((*Func)->getLocation(), diag::note_member_def_close_match);
+ }
+}
+
+NamedDecl*
+Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ QualType R, TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition, bool &Redeclaration) {
+ assert(R.getTypePtr()->isFunctionType());
+
+ // TODO: consider using NameInfo for diagnostic.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ FunctionDecl::StorageClass SC = SC_None;
+ switch (D.getDeclSpec().getStorageClassSpec()) {
+ default: assert(0 && "Unknown storage class!");
+ case DeclSpec::SCS_auto:
+ case DeclSpec::SCS_register:
+ case DeclSpec::SCS_mutable:
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_typecheck_sclass_func);
+ D.setInvalidType();
+ break;
+ case DeclSpec::SCS_unspecified: SC = SC_None; break;
+ case DeclSpec::SCS_extern: SC = SC_Extern; break;
+ case DeclSpec::SCS_static: {
+ if (CurContext->getRedeclContext()->isFunctionOrMethod()) {
+ // C99 6.7.1p5:
+ // The declaration of an identifier for a function that has
+ // block scope shall have no explicit storage-class specifier
+ // other than extern
+ // See also (C++ [dcl.stc]p4).
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_static_block_func);
+ SC = SC_None;
+ } else
+ SC = SC_Static;
+ break;
+ }
+ case DeclSpec::SCS_private_extern: SC = SC_PrivateExtern; break;
+ }
+
+ if (D.getDeclSpec().isThreadSpecified())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+ // Do not allow returning a objc interface by-value.
+ if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_object_cannot_be_passed_returned_by_value) << 0
+ << R->getAs<FunctionType>()->getResultType();
+ D.setInvalidType();
+ }
+
+ FunctionDecl *NewFD;
+ bool isInline = D.getDeclSpec().isInlineSpecified();
+ bool isFriend = false;
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+ FunctionDecl::StorageClass SCAsWritten
+ = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
+ FunctionTemplateDecl *FunctionTemplate = 0;
+ bool isExplicitSpecialization = false;
+ bool isFunctionTemplateSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = 0;
+
+ if (!getLangOptions().CPlusPlus) {
+ // Determine whether the function was written with a
+ // prototype. This true when:
+ // - there is a prototype in the declarator, or
+ // - the type R of the function is some kind of typedef or other reference
+ // to a type name (which eventually refers to a function type).
+ bool HasPrototype =
+ (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) ||
+ (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+
+ NewFD = FunctionDecl::Create(Context, DC,
+ NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+ HasPrototype);
+ if (D.isInvalidType())
+ NewFD->setInvalidDecl();
+
+ // Set the lexical context.
+ NewFD->setLexicalDeclContext(CurContext);
+ // Filter out previous declarations that don't match the scope.
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+ } else {
+ isFriend = D.getDeclSpec().isFriendSpecified();
+ bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+ bool isExplicit = D.getDeclSpec().isExplicitSpecified();
+ bool isVirtualOkay = false;
+
+ // Check that the return type is not an abstract class type.
+ // For record types, this is done by the AbstractClassUsageDiagnoser once
+ // the class has been completely parsed.
+ if (!DC->isRecord() &&
+ RequireNonAbstractType(D.getIdentifierLoc(),
+ R->getAs<FunctionType>()->getResultType(),
+ diag::err_abstract_type_in_decl,
+ AbstractReturnType))
+ D.setInvalidType();
+
+
+ if (isFriend) {
+ // C++ [class.friend]p5
+ // A function can be defined in a friend declaration of a
+ // class . . . . Such a function is implicitly inline.
+ isInline |= IsFunctionDefinition;
+ }
+
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
+ // This is a C++ constructor declaration.
+ assert(DC->isRecord() &&
+ "Constructors can only be declared in a member context");
+
+ R = CheckConstructorDeclarator(D, R, SC);
+
+ // Create the new declaration
+ NewFD = CXXConstructorDecl::Create(Context,
+ cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isExplicit, isInline,
+ /*isImplicitlyDeclared=*/false);
+ } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // This is a C++ destructor declaration.
+ if (DC->isRecord()) {
+ R = CheckDestructorDeclarator(D, R, SC);
+
+ NewFD = CXXDestructorDecl::Create(Context,
+ cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isInline,
+ /*isImplicitlyDeclared=*/false);
+ isVirtualOkay = true;
+ } else {
+ Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
+
+ // Create a FunctionDecl to satisfy the function definition parsing
+ // code path.
+ NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
+ Name, R, TInfo, SC, SCAsWritten, isInline,
+ /*hasPrototype=*/true);
+ D.setInvalidType();
+ }
+ } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ if (!DC->isRecord()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_conv_function_not_member);
+ return 0;
+ }
+
+ CheckConversionDeclarator(D, R, SC);
+ NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isInline, isExplicit);
+
+ isVirtualOkay = true;
+ } else if (DC->isRecord()) {
+ // If the of the function is the same as the name of the record, then this
+ // must be an invalid constructor that has a return type.
+ // (The parser checks for a return type and makes the declarator a
+ // constructor if it has no return type).
+ // must have an invalid constructor that has a return type
+ if (Name.getAsIdentifierInfo() &&
+ Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
+ Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
+ << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(D.getIdentifierLoc());
+ return 0;
+ }
+
+ bool isStatic = SC == SC_Static;
+
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_New ||
+ Name.getCXXOverloadedOperator() == OO_Array_New)
+ isStatic = true;
+
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_Delete ||
+ Name.getCXXOverloadedOperator() == OO_Array_Delete)
+ isStatic = true;
+
+ // This is a C++ method declaration.
+ NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isStatic, SCAsWritten, isInline);
+
+ isVirtualOkay = !isStatic;
+ } else {
+ // Determine whether the function was written with a
+ // prototype. This true when:
+ // - we're in C++ (where every function has a prototype),
+ NewFD = FunctionDecl::Create(Context, DC,
+ NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+ true/*HasPrototype*/);
+ }
+ SetNestedNameSpecifier(NewFD, D);
+ isExplicitSpecialization = false;
+ isFunctionTemplateSpecialization = false;
+ NumMatchedTemplateParamLists = TemplateParamLists.size();
+ if (D.isInvalidType())
+ NewFD->setInvalidDecl();
+
+ // Set the lexical context. If the declarator has a C++
+ // scope specifier, or is the object of a friend declaration, the
+ // lexical context will be different from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ bool Invalid = false;
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ D.getCXXScopeSpec(),
+ TemplateParamLists.get(),
+ TemplateParamLists.size(),
+ isFriend,
+ isExplicitSpecialization,
+ Invalid)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams->size() > 0) {
+ // This is a function template
+
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return 0;
+
+ FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+ NewFD->getLocation(),
+ Name, TemplateParams,
+ NewFD);
+ FunctionTemplate->setLexicalDeclContext(CurContext);
+ NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+ } else {
+ // This is a function template specialization.
+ isFunctionTemplateSpecialization = true;
+
+ // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
+ if (isFriend && isFunctionTemplateSpecialization) {
+ // We want to remove the "template<>", found here.
+ SourceRange RemoveRange = TemplateParams->getSourceRange();
+
+ // If we remove the template<> and the name is not a
+ // template-id, we're actually silently creating a problem:
+ // the friend declaration will refer to an untemplated decl,
+ // and clearly the user wants a template specialization. So
+ // we need to insert '<>' after the name.
+ SourceLocation InsertLoc;
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ InsertLoc = D.getName().getSourceRange().getEnd();
+ InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ }
+
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+ << Name << RemoveRange
+ << FixItHint::CreateRemoval(RemoveRange)
+ << FixItHint::CreateInsertion(InsertLoc, "<>");
+ }
+ }
+ }
+
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+ NewFD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ TemplateParamLists.release());
+ }
+
+ if (Invalid) {
+ NewFD->setInvalidDecl();
+ if (FunctionTemplate)
+ FunctionTemplate->setInvalidDecl();
+ }
+
+ // C++ [dcl.fct.spec]p5:
+ // The virtual specifier shall only be used in declarations of
+ // nonstatic class member functions that appear within a
+ // member-specification of a class declaration; see 10.3.
+ //
+ if (isVirtual && !NewFD->isInvalidDecl()) {
+ if (!isVirtualOkay) {
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ diag::err_virtual_non_function);
+ } else if (!CurContext->isRecord()) {
+ // 'virtual' was specified outside of the class.
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ diag::err_virtual_out_of_class)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
+ } else if (NewFD->getDescribedFunctionTemplate()) {
+ // C++ [temp.mem]p3:
+ // A member function template shall not be virtual.
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ diag::err_virtual_member_function_template)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
+ } else {
+ // Okay: Add virtual to the method.
+ NewFD->setVirtualAsWritten(true);
+ }
+ }
+
+ // C++ [dcl.fct.spec]p3:
+ // The inline specifier shall not appear on a block scope function declaration.
+ if (isInline && !NewFD->isInvalidDecl()) {
+ if (CurContext->isFunctionOrMethod()) {
+ // 'inline' is not allowed on block scope function declaration.
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_inline_declaration_block_scope) << Name
+ << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+ }
+ }
+
+ // C++ [dcl.fct.spec]p6:
+ // The explicit specifier shall be used only in the declaration of a
+ // constructor or conversion function within its class definition; see 12.3.1
+ // and 12.3.2.
+ if (isExplicit && !NewFD->isInvalidDecl()) {
+ if (!CurContext->isRecord()) {
+ // 'explicit' was specified outside of the class.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_out_of_class)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+ } else if (!isa<CXXConstructorDecl>(NewFD) &&
+ !isa<CXXConversionDecl>(NewFD)) {
+ // 'explicit' was specified on a function that wasn't a constructor
+ // or conversion function.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_non_ctor_or_conv_function)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+ }
+ }
+
+ // Filter out previous declarations that don't match the scope.
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+
+ if (isFriend) {
+ // For now, claim that the objects have no previous declaration.
+ if (FunctionTemplate) {
+ FunctionTemplate->setObjectOfFriendDecl(false);
+ FunctionTemplate->setAccess(AS_public);
+ }
+ NewFD->setObjectOfFriendDecl(false);
+ NewFD->setAccess(AS_public);
+ }
+
+ if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && IsFunctionDefinition) {
+ // A method is implicitly inline if it's defined in its class
+ // definition.
+ NewFD->setImplicitlyInline();
+ }
+
+ if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
+ !CurContext->isRecord()) {
+ // C++ [class.static]p1:
+ // A data or function member of a class may be declared static
+ // in a class definition, in which case it is a static member of
+ // the class.
+
+ // Complain about the 'static' specifier if it's on an out-of-line
+ // member function definition.
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_static_out_of_line)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ }
+ }
+
+ // Handle GNU asm-label extension (encoded as an attribute).
+ if (Expr *E = (Expr*) D.getAsmLabel()) {
+ // The parser guarantees this is a string.
+ StringLiteral *SE = cast<StringLiteral>(E);
+ NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
+ SE->getString()));
+ }
+
+ // Copy the parameter declarations from the declarator D to the function
+ // declaration NewFD, if they are available. First scavenge them into Params.
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+ if (D.isFunctionDeclarator()) {
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+ // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
+ // function that takes no arguments, not a function that takes a
+ // single void argument.
+ // We let through "const void" here because Sema::GetTypeForDeclarator
+ // already checks for that case.
+ if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+ FTI.ArgInfo[0].Param &&
+ cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
+ // Empty arg list, don't push any params.
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[0].Param);
+
+ // In C++, the empty parameter-type-list must be spelled "void"; a
+ // typedef of void is not permitted.
+ if (getLangOptions().CPlusPlus &&
+ Param->getType().getUnqualifiedType() != Context.VoidTy)
+ Diag(Param->getLocation(), diag::err_param_typedef_of_void);
+ } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
+ for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ assert(Param->getDeclContext() != NewFD && "Was set before ?");
+ Param->setDeclContext(NewFD);
+ Params.push_back(Param);
+
+ if (Param->isInvalidDecl())
+ NewFD->setInvalidDecl();
+ }
+ }
+
+ } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
+ // When we're declaring a function with a typedef, typeof, etc as in the
+ // following example, we'll need to synthesize (unnamed)
+ // parameters for use in the declaration.
+ //
+ // @code
+ // typedef void fn(int);
+ // fn f;
+ // @endcode
+
+ // Synthesize a parameter for each argument type.
+ for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
+ AE = FT->arg_type_end(); AI != AE; ++AI) {
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
+ Params.push_back(Param);
+ }
+ } else {
+ assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 &&
+ "Should not need args for typedef of non-prototype fn");
+ }
+ // Finally, we know we have the right number of parameters, install them.
+ NewFD->setParams(Params.data(), Params.size());
+
+ // Process the non-inheritable attributes on this declaration.
+ ProcessDeclAttributes(S, NewFD, D,
+ /*NonInheritable=*/true, /*Inheritable=*/false);
+
+ if (!getLangOptions().CPlusPlus) {
+ // Perform semantic checking on the function declaration.
+ bool isExplctSpecialization=false;
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplctSpecialization,
+ Redeclaration);
+ assert((NewFD->isInvalidDecl() || !Redeclaration ||
+ Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+ "previous declaration set still overloaded");
+ } else {
+ // If the declarator is a template-id, translate the parser's template
+ // argument list into our AST format.
+ bool HasExplicitTemplateArgs = false;
+ TemplateArgumentListInfo TemplateArgs;
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+ TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr,
+ TemplateArgs);
+ TemplateArgsPtr.release();
+
+ HasExplicitTemplateArgs = true;
+
+ if (FunctionTemplate) {
+ // Function template with explicit template arguments.
+ Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
+ << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
+
+ HasExplicitTemplateArgs = false;
+ } else if (!isFunctionTemplateSpecialization &&
+ !D.getDeclSpec().isFriendSpecified()) {
+ // We have encountered something that the user meant to be a
+ // specialization (because it has explicitly-specified template
+ // arguments) but that was not introduced with a "template<>" (or had
+ // too few of them).
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+ << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+ << FixItHint::CreateInsertion(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ "template<> ");
+ isFunctionTemplateSpecialization = true;
+ } else {
+ // "friend void foo<>(int);" is an implicit specialization decl.
+ isFunctionTemplateSpecialization = true;
+ }
+ } else if (isFriend && isFunctionTemplateSpecialization) {
+ // This combination is only possible in a recovery case; the user
+ // wrote something like:
+ // template <> friend void foo(int);
+ // which we're recovering from as if the user had written:
+ // friend void foo<>(int);
+ // Go ahead and fake up a template id.
+ HasExplicitTemplateArgs = true;
+ TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
+ TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
+ }
+
+ // If it's a friend (and only if it's a friend), it's possible
+ // that either the specialized function type or the specialized
+ // template is dependent, and therefore matching will fail. In
+ // this case, don't check the specialization yet.
+ if (isFunctionTemplateSpecialization && isFriend &&
+ (NewFD->getType()->isDependentType() || DC->isDependentContext())) {
+ assert(HasExplicitTemplateArgs &&
+ "friend function specialization without template args");
+ if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
+ Previous))
+ NewFD->setInvalidDecl();
+ } else if (isFunctionTemplateSpecialization) {
+ if (CheckFunctionTemplateSpecialization(NewFD,
+ (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ Previous))
+ NewFD->setInvalidDecl();
+ } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
+ if (CheckMemberSpecialization(NewFD, Previous))
+ NewFD->setInvalidDecl();
+ }
+
+ // Perform semantic checking on the function declaration.
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
+ Redeclaration);
+
+ assert((NewFD->isInvalidDecl() || !Redeclaration ||
+ Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+ "previous declaration set still overloaded");
+
+ NamedDecl *PrincipalDecl = (FunctionTemplate
+ ? cast<NamedDecl>(FunctionTemplate)
+ : NewFD);
+
+ if (isFriend && Redeclaration) {
+ AccessSpecifier Access = AS_public;
+ if (!NewFD->isInvalidDecl())
+ Access = NewFD->getPreviousDeclaration()->getAccess();
+
+ NewFD->setAccess(Access);
+ if (FunctionTemplate) FunctionTemplate->setAccess(Access);
+
+ PrincipalDecl->setObjectOfFriendDecl(true);
+ }
+
+ if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
+ PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ PrincipalDecl->setNonMemberOperator();
+
+ // If we have a function template, check the template parameter
+ // list. This will check and merge default template arguments.
+ if (FunctionTemplate) {
+ FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration();
+ CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
+ PrevTemplate? PrevTemplate->getTemplateParameters() : 0,
+ D.getDeclSpec().isFriendSpecified()
+ ? (IsFunctionDefinition
+ ? TPC_FriendFunctionTemplateDefinition
+ : TPC_FriendFunctionTemplate)
+ : (D.getCXXScopeSpec().isSet() &&
+ DC && DC->isRecord() &&
+ DC->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TPC_FunctionTemplate);
+ }
+
+ if (NewFD->isInvalidDecl()) {
+ // Ignore all the rest of this.
+ } else if (!Redeclaration) {
+ // Fake up an access specifier if it's supposed to be a class member.
+ if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+ NewFD->setAccess(AS_public);
+
+ // Qualified decls generally require a previous declaration.
+ if (D.getCXXScopeSpec().isSet()) {
+ // ...with the major exception of templated-scope or
+ // dependent-scope friend declarations.
+
+ // TODO: we currently also suppress this check in dependent
+ // contexts because (1) the parameter depth will be off when
+ // matching friend templates and (2) we might actually be
+ // selecting a friend based on a dependent factor. But there
+ // are situations where these conditions don't apply and we
+ // can actually do this check immediately.
+ if (isFriend &&
+ (NumMatchedTemplateParamLists ||
+ D.getCXXScopeSpec().getScopeRep()->isDependent() ||
+ CurContext->isDependentContext())) {
+ // ignore these
+ } else {
+ // The user tried to provide an out-of-line definition for a
+ // function that is a member of a class or namespace, but there
+ // was no such member function declared (C++ [class.mfct]p2,
+ // C++ [namespace.memdef]p2). For example:
+ //
+ // class X {
+ // void f() const;
+ // };
+ //
+ // void X::f() { } // ill-formed
+ //
+ // Complain about this problem, and attempt to suggest close
+ // matches (e.g., those that differ only in cv-qualifiers and
+ // whether the parameter types are references).
+ Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
+ << Name << DC << D.getCXXScopeSpec().getRange();
+ NewFD->setInvalidDecl();
+
+ DiagnoseInvalidRedeclaration(*this, NewFD);
+ }
+
+ // Unqualified local friend declarations are required to resolve
+ // to something.
+ } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
+ Diag(D.getIdentifierLoc(), diag::err_no_matching_local_friend);
+ NewFD->setInvalidDecl();
+ DiagnoseInvalidRedeclaration(*this, NewFD);
+ }
+
+ } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
+ !isFriend && !isFunctionTemplateSpecialization &&
+ !isExplicitSpecialization) {
+ // An out-of-line member function declaration must also be a
+ // definition (C++ [dcl.meaning]p1).
+ // Note that this is not the case for explicit specializations of
+ // function templates or member functions of class templates, per
+ // C++ [temp.expl.spec]p2. We also allow these declarations as an extension
+ // for compatibility with old SWIG code which likes to generate them.
+ Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
+ << D.getCXXScopeSpec().getRange();
+ }
+ }
+
+
+ // Handle attributes. We need to have merged decls when handling attributes
+ // (for example to check for conflicts, etc).
+ // FIXME: This needs to happen before we merge declarations. Then,
+ // let attribute merging cope with attribute conflicts.
+ ProcessDeclAttributes(S, NewFD, D,
+ /*NonInheritable=*/false, /*Inheritable=*/true);
+
+ // attributes declared post-definition are currently ignored
+ // FIXME: This should happen during attribute merging
+ if (Redeclaration && Previous.isSingleResult()) {
+ const FunctionDecl *Def;
+ FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
+ if (PrevFD && PrevFD->hasBody(Def) && D.hasAttributes()) {
+ Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ }
+ }
+
+ AddKnownFunctionAttributes(NewFD);
+
+ if (NewFD->hasAttr<OverloadableAttr>() &&
+ !NewFD->getType()->getAs<FunctionProtoType>()) {
+ Diag(NewFD->getLocation(),
+ diag::err_attribute_overloadable_no_prototype)
+ << NewFD;
+
+ // Turn this into a variadic function with no parameters.
+ const FunctionType *FT = NewFD->getType()->getAs<FunctionType>();
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = true;
+ EPI.ExtInfo = FT->getExtInfo();
+
+ QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI);
+ NewFD->setType(R);
+ }
+
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this function.
+ if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ AddPushedVisibilityAttribute(NewFD);
+
+ // If this is a locally-scoped extern C function, update the
+ // map of such names.
+ if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
+ && !NewFD->isInvalidDecl())
+ RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
+
+ // Set this FunctionDecl's range up to the right paren.
+ NewFD->setLocEnd(D.getSourceRange().getEnd());
+
+ if (getLangOptions().CPlusPlus) {
+ if (FunctionTemplate) {
+ if (NewFD->isInvalidDecl())
+ FunctionTemplate->setInvalidDecl();
+ return FunctionTemplate;
+ }
+ }
+
+ MarkUnusedFileScopedDecl(NewFD);
+
+ if (getLangOptions().CUDA)
+ if (IdentifierInfo *II = NewFD->getIdentifier())
+ if (!NewFD->isInvalidDecl() &&
+ NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+ if (II->isStr("cudaConfigureCall")) {
+ if (!R->getAs<FunctionType>()->getResultType()->isScalarType())
+ Diag(NewFD->getLocation(), diag::err_config_scalar_return);
+
+ Context.setcudaConfigureCallDecl(NewFD);
+ }
+ }
+
+ return NewFD;
+}
+
+/// \brief Perform semantic checking of a new function declaration.
+///
+/// Performs semantic analysis of the new function declaration
+/// NewFD. This routine performs all semantic checking that does not
+/// require the actual declarator involved in the declaration, and is
+/// used both for the declaration of functions as they are parsed
+/// (called via ActOnDeclarator) and for the declaration of functions
+/// that have been instantiated via C++ template instantiation (called
+/// via InstantiateDecl).
+///
+/// \param IsExplicitSpecialiation whether this new function declaration is
+/// an explicit specialization of the previous declaration.
+///
+/// This sets NewFD->isInvalidDecl() to true if there was an error.
+void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
+ LookupResult &Previous,
+ bool IsExplicitSpecialization,
+ bool &Redeclaration) {
+ // If NewFD is already known erroneous, don't do any of this checking.
+ if (NewFD->isInvalidDecl()) {
+ // If this is a class member, mark the class invalid immediately.
+ // This avoids some consistency errors later.
+ if (isa<CXXMethodDecl>(NewFD))
+ cast<CXXMethodDecl>(NewFD)->getParent()->setInvalidDecl();
+
+ return;
+ }
+
+ if (NewFD->getResultType()->isVariablyModifiedType()) {
+ // Functions returning a variably modified type violate C99 6.7.5.2p2
+ // because all functions have linkage.
+ Diag(NewFD->getLocation(), diag::err_vm_func_decl);
+ return NewFD->setInvalidDecl();
+ }
+
+ if (NewFD->isMain())
+ CheckMain(NewFD);
+
+ // Check for a previous declaration of this name.
+ if (Previous.empty() && NewFD->isExternC()) {
+ // Since we did not find anything by this name and we're declaring
+ // an extern "C" function, look for a non-visible extern "C"
+ // declaration with the same name.
+ llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+ = LocallyScopedExternalDecls.find(NewFD->getDeclName());
+ if (Pos != LocallyScopedExternalDecls.end())
+ Previous.addDecl(Pos->second);
+ }
+
+ // Merge or overload the declaration with an existing declaration of
+ // the same name, if appropriate.
+ if (!Previous.empty()) {
+ // Determine whether NewFD is an overload of PrevDecl or
+ // a declaration that requires merging. If it's an overload,
+ // there's no more work to do here; we'll just add the new
+ // function to the scope.
+
+ NamedDecl *OldDecl = 0;
+ if (!AllowOverloadingOfFunction(Previous, Context)) {
+ Redeclaration = true;
+ OldDecl = Previous.getFoundDecl();
+ } else {
+ switch (CheckOverload(S, NewFD, Previous, OldDecl,
+ /*NewIsUsingDecl*/ false)) {
+ case Ovl_Match:
+ Redeclaration = true;
+ break;
+
+ case Ovl_NonFunction:
+ Redeclaration = true;
+ break;
+
+ case Ovl_Overload:
+ Redeclaration = false;
+ break;
+ }
+
+ if (!getLangOptions().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
+ // If a function name is overloadable in C, then every function
+ // with that name must be marked "overloadable".
+ Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
+ << Redeclaration << NewFD;
+ NamedDecl *OverloadedDecl = 0;
+ if (Redeclaration)
+ OverloadedDecl = OldDecl;
+ else if (!Previous.empty())
+ OverloadedDecl = Previous.getRepresentativeDecl();
+ if (OverloadedDecl)
+ Diag(OverloadedDecl->getLocation(),
+ diag::note_attribute_overloadable_prev_overload);
+ NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
+ Context));
+ }
+ }
+
+ if (Redeclaration) {
+ // NewFD and OldDecl represent declarations that need to be
+ // merged.
+ if (MergeFunctionDecl(NewFD, OldDecl))
+ return NewFD->setInvalidDecl();
+
+ Previous.clear();
+ Previous.addDecl(OldDecl);
+
+ if (FunctionTemplateDecl *OldTemplateDecl
+ = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+ NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ FunctionTemplateDecl *NewTemplateDecl
+ = NewFD->getDescribedFunctionTemplate();
+ assert(NewTemplateDecl && "Template/non-template mismatch");
+ if (CXXMethodDecl *Method
+ = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+ Method->setAccess(OldTemplateDecl->getAccess());
+ NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+ }
+
+ // If this is an explicit specialization of a member that is a function
+ // template, mark it as a member specialization.
+ if (IsExplicitSpecialization &&
+ NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+ NewTemplateDecl->setMemberSpecialization();
+ assert(OldTemplateDecl->isMemberSpecialization());
+ }
+ } else {
+ if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
+ NewFD->setAccess(OldDecl->getAccess());
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+ }
+ }
+ }
+
+ // Semantic checking for this function declaration (in isolation).
+ if (getLangOptions().CPlusPlus) {
+ // C++-specific checks.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+ CheckConstructor(Constructor);
+ } else if (CXXDestructorDecl *Destructor =
+ dyn_cast<CXXDestructorDecl>(NewFD)) {
+ CXXRecordDecl *Record = Destructor->getParent();
+ QualType ClassType = Context.getTypeDeclType(Record);
+
+ // FIXME: Shouldn't we be able to perform this check even when the class
+ // type is dependent? Both gcc and edg can handle that.
+ if (!ClassType->isDependentType()) {
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(ClassType));
+ if (NewFD->getDeclName() != Name) {
+ Diag(NewFD->getLocation(), diag::err_destructor_name);
+ return NewFD->setInvalidDecl();
+ }
+ }
+ } else if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>(NewFD)) {
+ ActOnConversionDeclarator(Conversion);
+ }
+
+ // Find any virtual functions that this function overrides.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
+ if (!Method->isFunctionTemplateSpecialization() &&
+ !Method->getDescribedFunctionTemplate()) {
+ if (AddOverriddenMethods(Method->getParent(), Method)) {
+ // If the function was marked as "static", we have a problem.
+ if (NewFD->getStorageClass() == SC_Static) {
+ Diag(NewFD->getLocation(), diag::err_static_overrides_virtual)
+ << NewFD->getDeclName();
+ for (CXXMethodDecl::method_iterator
+ Overridden = Method->begin_overridden_methods(),
+ OverriddenEnd = Method->end_overridden_methods();
+ Overridden != OverriddenEnd;
+ ++Overridden) {
+ Diag((*Overridden)->getLocation(),
+ diag::note_overridden_virtual_function);
+ }
+ }
+ }
+ }
+ }
+
+ // Extra checking for C++ overloaded operators (C++ [over.oper]).
+ if (NewFD->isOverloadedOperator() &&
+ CheckOverloadedOperatorDeclaration(NewFD))
+ return NewFD->setInvalidDecl();
+
+ // Extra checking for C++0x literal operators (C++0x [over.literal]).
+ if (NewFD->getLiteralIdentifier() &&
+ CheckLiteralOperatorDeclaration(NewFD))
+ return NewFD->setInvalidDecl();
+
+ // In C++, check default arguments now that we have merged decls. Unless
+ // the lexical context is the class, because in this case this is done
+ // during delayed parsing anyway.
+ if (!CurContext->isRecord())
+ CheckCXXDefaultArguments(NewFD);
+
+ // If this function declares a builtin function, check the type of this
+ // declaration against the expected type for the builtin.
+ if (unsigned BuiltinID = NewFD->getBuiltinID()) {
+ ASTContext::GetBuiltinTypeError Error;
+ QualType T = Context.GetBuiltinType(BuiltinID, Error);
+ if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
+ // The type of this function differs from the type of the builtin,
+ // so forget about the builtin entirely.
+ Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
+ }
+ }
+ }
+}
+
+void Sema::CheckMain(FunctionDecl* FD) {
+ // C++ [basic.start.main]p3: A program that declares main to be inline
+ // or static is ill-formed.
+ // C99 6.7.4p4: In a hosted environment, the inline function specifier
+ // shall not appear in a declaration of main.
+ // static main is not an error under C99, but we should warn about it.
+ bool isInline = FD->isInlineSpecified();
+ bool isStatic = FD->getStorageClass() == SC_Static;
+ if (isInline || isStatic) {
+ unsigned diagID = diag::warn_unusual_main_decl;
+ if (isInline || getLangOptions().CPlusPlus)
+ diagID = diag::err_unusual_main_decl;
+
+ int which = isStatic + (isInline << 1) - 1;
+ Diag(FD->getLocation(), diagID) << which;
+ }
+
+ QualType T = FD->getType();
+ assert(T->isFunctionType() && "function decl is not of function type");
+ const FunctionType* FT = T->getAs<FunctionType>();
+
+ if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+ FD->setInvalidDecl(true);
+ }
+
+ // Treat protoless main() as nullary.
+ if (isa<FunctionNoProtoType>(FT)) return;
+
+ const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
+ unsigned nparams = FTP->getNumArgs();
+ assert(FD->getNumParams() == nparams);
+
+ bool HasExtraParameters = (nparams > 3);
+
+ // Darwin passes an undocumented fourth argument of type char**. If
+ // other platforms start sprouting these, the logic below will start
+ // getting shifty.
+ if (nparams == 4 &&
+ Context.Target.getTriple().getOS() == llvm::Triple::Darwin)
+ HasExtraParameters = false;
+
+ if (HasExtraParameters) {
+ Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
+ FD->setInvalidDecl(true);
+ nparams = 3;
+ }
+
+ // FIXME: a lot of the following diagnostics would be improved
+ // if we had some location information about types.
+
+ QualType CharPP =
+ Context.getPointerType(Context.getPointerType(Context.CharTy));
+ QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP };
+
+ for (unsigned i = 0; i < nparams; ++i) {
+ QualType AT = FTP->getArgType(i);
+
+ bool mismatch = true;
+
+ if (Context.hasSameUnqualifiedType(AT, Expected[i]))
+ mismatch = false;
+ else if (Expected[i] == CharPP) {
+ // As an extension, the following forms are okay:
+ // char const **
+ // char const * const *
+ // char * const *
+
+ QualifierCollector qs;
+ const PointerType* PT;
+ if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
+ (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
+ (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+ qs.removeConst();
+ mismatch = !qs.empty();
+ }
+ }
+
+ if (mismatch) {
+ Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
+ // TODO: suggest replacing given type with expected type
+ FD->setInvalidDecl(true);
+ }
+ }
+
+ if (nparams == 1 && !FD->isInvalidDecl()) {
+ Diag(FD->getLocation(), diag::warn_main_one_arg);
+ }
+
+ if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
+ Diag(FD->getLocation(), diag::err_main_template_decl);
+ FD->setInvalidDecl();
+ }
+}
+
+bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
+ // FIXME: Need strict checking. In C89, we need to check for
+ // any assignment, increment, decrement, function-calls, or
+ // commas outside of a sizeof. In C99, it's the same list,
+ // except that the aforementioned are allowed in unevaluated
+ // expressions. Everything else falls under the
+ // "may accept other forms of constant expressions" exception.
+ // (We never end up here for C++, so the constant expression
+ // rules there don't matter.)
+ if (Init->isConstantInitializer(Context, false))
+ return false;
+ Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
+ << Init->getSourceRange();
+ return true;
+}
+
+/// AddInitializerToDecl - Adds the initializer Init to the
+/// declaration dcl. If DirectInit is true, this is C++ direct
+/// initialization rather than copy initialization.
+void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
+ bool DirectInit, bool TypeMayContainAuto) {
+ // If there is no declaration, there was an error parsing it. Just ignore
+ // the initializer.
+ if (RealDecl == 0 || RealDecl->isInvalidDecl())
+ return;
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
+ // With declarators parsed the way they are, the parser cannot
+ // distinguish between a normal initializer and a pure-specifier.
+ // Thus this grotesque test.
+ IntegerLiteral *IL;
+ if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
+ Context.getCanonicalType(IL->getType()) == Context.IntTy)
+ CheckPureMethod(Method, Init->getSourceRange());
+ else {
+ Diag(Method->getLocation(), diag::err_member_function_initialization)
+ << Method->getDeclName() << Init->getSourceRange();
+ Method->setInvalidDecl();
+ }
+ return;
+ }
+
+ VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+ if (!VDecl) {
+ if (getLangOptions().CPlusPlus &&
+ RealDecl->getLexicalDeclContext()->isRecord() &&
+ isa<NamedDecl>(RealDecl))
+ Diag(RealDecl->getLocation(), diag::err_member_initialization);
+ else
+ Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
+ // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+ VDecl->setParsingAutoInit(false);
+
+ QualType DeducedType;
+ if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+ Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+ << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+ << Init->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ }
+ VDecl->setType(DeducedType);
+
+ // If this is a redeclaration, check that the type we just deduced matches
+ // the previously declared type.
+ if (VarDecl *Old = VDecl->getPreviousDeclaration())
+ MergeVarDeclTypes(VDecl, Old);
+ }
+
+
+ // A definition must end up with a complete type, which means it must be
+ // complete with the restriction that an array type might be completed by the
+ // initializer; note that later code assumes this restriction.
+ QualType BaseDeclType = VDecl->getType();
+ if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+ BaseDeclType = Array->getElementType();
+ if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
+ diag::err_typecheck_decl_incomplete_type)) {
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
+
+ const VarDecl *Def;
+ if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+ Diag(VDecl->getLocation(), diag::err_redefinition)
+ << VDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ const VarDecl* PrevInit = 0;
+ if (getLangOptions().CPlusPlus) {
+ // C++ [class.static.data]p4
+ // If a static data member is of const integral or const
+ // enumeration type, its declaration in the class definition can
+ // specify a constant-initializer which shall be an integral
+ // constant expression (5.19). In that case, the member can appear
+ // in integral constant expressions. The member shall still be
+ // defined in a namespace scope if it is used in the program and the
+ // namespace scope definition shall not contain an initializer.
+ //
+ // We already performed a redefinition check above, but for static
+ // data members we also need to check whether there was an in-class
+ // declaration with an initializer.
+ if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName();
+ Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ return;
+ }
+
+ if (VDecl->hasLocalStorage())
+ getCurFunction()->setHasBranchProtectedScope();
+
+ if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+ }
+
+ // Capture the variable that is being initialized and the style of
+ // initialization.
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+ Init->getLocStart(),
+ Init->getLocEnd())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ Init->getLocStart());
+
+ // Get the decls type and save a reference for later, since
+ // CheckInitializerTypes may change it.
+ QualType DclT = VDecl->getType(), SavT = DclT;
+ if (VDecl->isLocalVarDecl()) {
+ if (VDecl->hasExternalStorage()) { // C99 6.7.8p5
+ Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
+ VDecl->setInvalidDecl();
+ } else if (!VDecl->isInvalidDecl()) {
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+
+ // C++ 3.6.2p2, allow dynamic initialization of static initializers.
+ // Don't check invalid declarations to avoid emitting useless diagnostics.
+ if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
+ if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4.
+ CheckForConstantInitializer(Init, DclT);
+ }
+ }
+ } else if (VDecl->isStaticDataMember() &&
+ VDecl->getLexicalDeclContext()->isRecord()) {
+ // This is an in-class initialization for a static data member, e.g.,
+ //
+ // struct S {
+ // static const int value = 17;
+ // };
+
+ // Try to perform the initialization regardless.
+ if (!VDecl->isInvalidDecl()) {
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ }
+
+ // C++ [class.mem]p4:
+ // A member-declarator can contain a constant-initializer only
+ // if it declares a static member (9.4) of const integral or
+ // const enumeration type, see 9.4.2.
+ QualType T = VDecl->getType();
+
+ // Do nothing on dependent types.
+ if (T->isDependentType()) {
+
+ // Require constness.
+ } else if (!T.isConstQualified()) {
+ Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+
+ // We allow integer constant expressions in all cases.
+ } else if (T->isIntegralOrEnumerationType()) {
+ if (!Init->isValueDependent()) {
+ // Check whether the expression is a constant expression.
+ llvm::APSInt Value;
+ SourceLocation Loc;
+ if (!Init->isIntegerConstantExpr(Value, Context, &Loc)) {
+ Diag(Loc, diag::err_in_class_initializer_non_constant)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+ }
+ }
+
+ // We allow floating-point constants as an extension in C++03, and
+ // C++0x has far more complicated rules that we don't really
+ // implement fully.
+ } else {
+ bool Allowed = false;
+ if (getLangOptions().CPlusPlus0x) {
+ Allowed = T->isLiteralType();
+ } else if (T->isFloatingType()) { // also permits complex, which is ok
+ Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
+ << T << Init->getSourceRange();
+ Allowed = true;
+ }
+
+ if (!Allowed) {
+ Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)
+ << T << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+
+ // TODO: there are probably expressions that pass here that shouldn't.
+ } else if (!Init->isValueDependent() &&
+ !Init->isConstantInitializer(Context, false)) {
+ Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+ }
+ }
+ } else if (VDecl->isFileVarDecl()) {
+ if (VDecl->getStorageClassAsWritten() == SC_Extern &&
+ (!getLangOptions().CPlusPlus ||
+ !Context.getBaseElementType(VDecl->getType()).isConstQualified()))
+ Diag(VDecl->getLocation(), diag::warn_extern_init);
+ if (!VDecl->isInvalidDecl()) {
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ }
+
+ // C++ 3.6.2p2, allow dynamic initialization of static initializers.
+ // Don't check invalid declarations to avoid emitting useless diagnostics.
+ if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
+ // C99 6.7.8p4. All file scoped initializers need to be constant.
+ CheckForConstantInitializer(Init, DclT);
+ }
+ }
+ // If the type changed, it means we had an incomplete type that was
+ // completed by the initializer. For example:
+ // int ary[] = { 1, 3, 5 };
+ // "ary" transitions from a VariableArrayType to a ConstantArrayType.
+ if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
+ VDecl->setType(DclT);
+ Init->setType(DclT);
+ }
+
+
+ // If this variable is a local declaration with record type, make sure it
+ // doesn't have a flexible member initialization. We only support this as a
+ // global/static definition.
+ if (VDecl->hasLocalStorage())
+ if (const RecordType *RT = VDecl->getType()->getAs<RecordType>())
+ if (RT->getDecl()->hasFlexibleArrayMember()) {
+ // Check whether the initializer tries to initialize the flexible
+ // array member itself to anything other than an empty initializer list.
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ unsigned Index = std::distance(RT->getDecl()->field_begin(),
+ RT->getDecl()->field_end()) - 1;
+ if (Index < ILE->getNumInits() &&
+ !(isa<InitListExpr>(ILE->getInit(Index)) &&
+ cast<InitListExpr>(ILE->getInit(Index))->getNumInits() == 0)) {
+ Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable);
+ VDecl->setInvalidDecl();
+ }
+ }
+ }
+
+ // Check any implicit conversions within the expression.
+ CheckImplicitConversions(Init, VDecl->getLocation());
+
+ Init = MaybeCreateExprWithCleanups(Init);
+ // Attach the initializer to the decl.
+ VDecl->setInit(Init);
+
+ CheckCompleteVariableDeclaration(VDecl);
+}
+
+/// ActOnInitializerError - Given that there was an error parsing an
+/// initializer for the given declaration, try to return to some form
+/// of sanity.
+void Sema::ActOnInitializerError(Decl *D) {
+ // Our main concern here is re-establishing invariants like "a
+ // variable's type is either dependent or complete".
+ if (!D || D->isInvalidDecl()) return;
+
+ VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (!VD) return;
+
+ // Auto types are meaningless if we can't make sense of the initializer.
+ if (VD->isParsingAutoInit()) {
+ VD->setParsingAutoInit(false);
+ VD->setInvalidDecl();
+ return;
+ }
+
+ QualType Ty = VD->getType();
+ if (Ty->isDependentType()) return;
+
+ // Require a complete type.
+ if (RequireCompleteType(VD->getLocation(),
+ Context.getBaseElementType(Ty),
+ diag::err_typecheck_decl_incomplete_type)) {
+ VD->setInvalidDecl();
+ return;
+ }
+
+ // Require an abstract type.
+ if (RequireNonAbstractType(VD->getLocation(), Ty,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType)) {
+ VD->setInvalidDecl();
+ return;
+ }
+
+ // Don't bother complaining about constructors or destructors,
+ // though.
+}
+
+void Sema::ActOnUninitializedDecl(Decl *RealDecl,
+ bool TypeMayContainAuto) {
+ // If there is no declaration, there was an error parsing it. Just ignore it.
+ if (RealDecl == 0)
+ return;
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
+ QualType Type = Var->getType();
+
+ // C++0x [dcl.spec.auto]p3
+ if (TypeMayContainAuto && Type->getContainedAutoType()) {
+ Var->setParsingAutoInit(false);
+
+ Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+ << Var->getDeclName() << Type;
+ Var->setInvalidDecl();
+ return;
+ }
+
+ switch (Var->isThisDeclarationADefinition()) {
+ case VarDecl::Definition:
+ if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
+ break;
+
+ // We have an out-of-line definition of a static data member
+ // that has an in-class initializer, so we type-check this like
+ // a declaration.
+ //
+ // Fall through
+
+ case VarDecl::DeclarationOnly:
+ // It's only a declaration.
+
+ // Block scope. C99 6.7p7: If an identifier for an object is
+ // declared with no linkage (C99 6.2.2p6), the type for the
+ // object shall be complete.
+ if (!Type->isDependentType() && Var->isLocalVarDecl() &&
+ !Var->getLinkage() && !Var->isInvalidDecl() &&
+ RequireCompleteType(Var->getLocation(), Type,
+ diag::err_typecheck_decl_incomplete_type))
+ Var->setInvalidDecl();
+
+ // Make sure that the type is not abstract.
+ if (!Type->isDependentType() && !Var->isInvalidDecl() &&
+ RequireNonAbstractType(Var->getLocation(), Type,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ Var->setInvalidDecl();
+ return;
+
+ case VarDecl::TentativeDefinition:
+ // File scope. C99 6.9.2p2: A declaration of an identifier for an
+ // object that has file scope without an initializer, and without a
+ // storage-class specifier or with the storage-class specifier "static",
+ // constitutes a tentative definition. Note: A tentative definition with
+ // external linkage is valid (C99 6.2.2p5).
+ if (!Var->isInvalidDecl()) {
+ if (const IncompleteArrayType *ArrayT
+ = Context.getAsIncompleteArrayType(Type)) {
+ if (RequireCompleteType(Var->getLocation(),
+ ArrayT->getElementType(),
+ diag::err_illegal_decl_array_incomplete_type))
+ Var->setInvalidDecl();
+ } else if (Var->getStorageClass() == SC_Static) {
+ // C99 6.9.2p3: If the declaration of an identifier for an object is
+ // a tentative definition and has internal linkage (C99 6.2.2p3), the
+ // declared type shall not be an incomplete type.
+ // NOTE: code such as the following
+ // static struct s;
+ // struct s { int a; };
+ // is accepted by gcc. Hence here we issue a warning instead of
+ // an error and we do not invalidate the static declaration.
+ // NOTE: to avoid multiple warnings, only check the first declaration.
+ if (Var->getPreviousDeclaration() == 0)
+ RequireCompleteType(Var->getLocation(), Type,
+ diag::ext_typecheck_decl_incomplete_type);
+ }
+ }
+
+ // Record the tentative definition; we're done.
+ if (!Var->isInvalidDecl())
+ TentativeDefinitions.push_back(Var);
+ return;
+ }
+
+ // Provide a specific diagnostic for uninitialized variable
+ // definitions with incomplete array type.
+ if (Type->isIncompleteArrayType()) {
+ Diag(Var->getLocation(),
+ diag::err_typecheck_incomplete_array_needs_initializer);
+ Var->setInvalidDecl();
+ return;
+ }
+
+ // Provide a specific diagnostic for uninitialized variable
+ // definitions with reference type.
+ if (Type->isReferenceType()) {
+ Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+ << Var->getDeclName()
+ << SourceRange(Var->getLocation(), Var->getLocation());
+ Var->setInvalidDecl();
+ return;
+ }
+
+ // Do not attempt to type-check the default initializer for a
+ // variable with dependent type.
+ if (Type->isDependentType())
+ return;
+
+ if (Var->isInvalidDecl())
+ return;
+
+ if (RequireCompleteType(Var->getLocation(),
+ Context.getBaseElementType(Type),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Var->setInvalidDecl();
+ return;
+ }
+
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(Var->getLocation(), Type,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType)) {
+ Var->setInvalidDecl();
+ return;
+ }
+
+ const RecordType *Record
+ = Context.getBaseElementType(Type)->getAs<RecordType>();
+ if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x &&
+ cast<CXXRecordDecl>(Record->getDecl())->isPOD()) {
+ // C++03 [dcl.init]p9:
+ // If no initializer is specified for an object, and the
+ // object is of (possibly cv-qualified) non-POD class type (or
+ // array thereof), the object shall be default-initialized; if
+ // the object is of const-qualified type, the underlying class
+ // type shall have a user-declared default
+ // constructor. Otherwise, if no initializer is specified for
+ // a non- static object, the object and its subobjects, if
+ // any, have an indeterminate initial value); if the object
+ // or any of its subobjects are of const-qualified type, the
+ // program is ill-formed.
+ // FIXME: DPG thinks it is very fishy that C++0x disables this.
+ } else {
+ // Check for jumps past the implicit initializer. C++0x
+ // clarifies that this applies to a "variable with automatic
+ // storage duration", not a "local variable".
+ if (getLangOptions().CPlusPlus && Var->hasLocalStorage())
+ getCurFunction()->setHasBranchProtectedScope();
+
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+ InitializationKind Kind
+ = InitializationKind::CreateDefault(Var->getLocation());
+
+ InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+ ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, 0, 0));
+ if (Init.isInvalid())
+ Var->setInvalidDecl();
+ else if (Init.get())
+ Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
+ }
+
+ CheckCompleteVariableDeclaration(Var);
+ }
+}
+
+void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
+ if (var->isInvalidDecl()) return;
+
+ // All the following checks are C++ only.
+ if (!getLangOptions().CPlusPlus) return;
+
+ QualType baseType = Context.getBaseElementType(var->getType());
+ if (baseType->isDependentType()) return;
+
+ // __block variables might require us to capture a copy-initializer.
+ if (var->hasAttr<BlocksAttr>()) {
+ // It's currently invalid to ever have a __block variable with an
+ // array type; should we diagnose that here?
+
+ // Regardless, we don't want to ignore array nesting when
+ // constructing this copy.
+ QualType type = var->getType();
+
+ if (type->isStructureOrClassType()) {
+ SourceLocation poi = var->getLocation();
+ Expr *varRef = new (Context) DeclRefExpr(var, type, VK_LValue, poi);
+ ExprResult result =
+ PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(poi, type, false),
+ poi, Owned(varRef));
+ if (!result.isInvalid()) {
+ result = MaybeCreateExprWithCleanups(result);
+ Expr *init = result.takeAs<Expr>();
+ Context.setBlockVarCopyInits(var, init);
+ }
+ }
+ }
+
+ // Check for global constructors.
+ if (!var->getDeclContext()->isDependentContext() &&
+ var->hasGlobalStorage() &&
+ !var->isStaticLocal() &&
+ var->getInit() &&
+ !var->getInit()->isConstantInitializer(Context,
+ baseType->isReferenceType()))
+ Diag(var->getLocation(), diag::warn_global_constructor)
+ << var->getInit()->getSourceRange();
+
+ // Require the destructor.
+ if (const RecordType *recordType = baseType->getAs<RecordType>())
+ FinalizeVarWithDestructor(var, recordType);
+}
+
+Sema::DeclGroupPtrTy
+Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ Decl **Group, unsigned NumDecls) {
+ llvm::SmallVector<Decl*, 8> Decls;
+
+ if (DS.isTypeSpecOwned())
+ Decls.push_back(DS.getRepAsDecl());
+
+ // C++0x [dcl.spec.auto]p7:
+ // If the type deduced for the template parameter U is not the same in each
+ // deduction, the program is ill-formed.
+ // FIXME: When initializer-list support is added, a distinction is needed
+ // between the deduced type U and the deduced type which 'auto' stands for.
+ // auto a = 0, b = { 1, 2, 3 };
+ // is legal because the deduced type U is 'int' in both cases.
+ bool TypeContainsAuto = DS.getTypeSpecType() == DeclSpec::TST_auto;
+ if (TypeContainsAuto && NumDecls > 1) {
+ QualType Deduced;
+ CanQualType DeducedCanon;
+ VarDecl *DeducedDecl = 0;
+ for (unsigned i = 0; i != NumDecls; ++i) {
+ if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
+ AutoType *AT = D->getType()->getContainedAutoType();
+ if (AT && AT->isDeduced()) {
+ QualType U = AT->getDeducedType();
+ CanQualType UCanon = Context.getCanonicalType(U);
+ if (Deduced.isNull()) {
+ Deduced = U;
+ DeducedCanon = UCanon;
+ DeducedDecl = D;
+ } else if (DeducedCanon != UCanon) {
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_auto_different_deductions)
+ << Deduced << DeducedDecl->getDeclName()
+ << U << D->getDeclName()
+ << DeducedDecl->getInit()->getSourceRange()
+ << D->getInit()->getSourceRange();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (unsigned i = 0; i != NumDecls; ++i)
+ if (Decl *D = Group[i])
+ Decls.push_back(D);
+
+ return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
+ Decls.data(), Decls.size()));
+}
+
+
+/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
+/// to introduce parameters into function prototype scope.
+Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
+ const DeclSpec &DS = D.getDeclSpec();
+
+ // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+ VarDecl::StorageClass StorageClass = SC_None;
+ VarDecl::StorageClass StorageClassAsWritten = SC_None;
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
+ StorageClass = SC_Register;
+ StorageClassAsWritten = SC_Register;
+ } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
+ Diag(DS.getStorageClassSpecLoc(),
+ diag::err_invalid_storage_class_in_func_decl);
+ D.getMutableDeclSpec().ClearStorageClassSpecs();
+ }
+
+ if (D.getDeclSpec().isThreadSpecified())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+ DiagnoseFunctionSpecifiers(D);
+
+ TagDecl *OwnedDecl = 0;
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl);
+ QualType parmDeclType = TInfo->getType();
+
+ if (getLangOptions().CPlusPlus) {
+ // Check that there are no default arguments inside the type of this
+ // parameter.
+ CheckExtraCXXDefaultArguments(D);
+
+ if (OwnedDecl && OwnedDecl->isDefinition()) {
+ // C++ [dcl.fct]p6:
+ // Types shall not be defined in return or parameter types.
+ Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
+ << Context.getTypeDeclType(OwnedDecl);
+ }
+
+ // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+ if (D.getCXXScopeSpec().isSet()) {
+ Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
+ << D.getCXXScopeSpec().getRange();
+ D.getCXXScopeSpec().clear();
+ }
+ }
+
+ // Ensure we have a valid name
+ IdentifierInfo *II = 0;
+ if (D.hasName()) {
+ II = D.getIdentifier();
+ if (!II) {
+ Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name)
+ << GetNameForDeclarator(D).getName().getAsString();
+ D.setInvalidType(true);
+ }
+ }
+
+ // Check for redeclaration of parameters, e.g. int foo(int x, int x);
+ if (II) {
+ LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName,
+ ForRedeclaration);
+ LookupName(R, S);
+ if (R.isSingleResult()) {
+ NamedDecl *PrevDecl = R.getFoundDecl();
+ if (PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ } else if (S->isDeclScope(PrevDecl)) {
+ Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
+ Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+ // Recover by removing the name
+ II = 0;
+ D.SetIdentifier(0, D.getIdentifierLoc());
+ D.setInvalidType(true);
+ }
+ }
+ }
+
+ // Temporarily put parameter variables in the translation unit, not
+ // the enclosing context. This prevents them from accidentally
+ // looking like class members in C++.
+ ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(),
+ TInfo, parmDeclType, II,
+ D.getIdentifierLoc(),
+ StorageClass, StorageClassAsWritten);
+
+ if (D.isInvalidType())
+ New->setInvalidDecl();
+
+ // Add the parameter declaration into this scope.
+ S->AddDecl(New);
+ if (II)
+ IdResolver.AddDecl(New);
+
+ ProcessDeclAttributes(S, New, D);
+
+ if (New->hasAttr<BlocksAttr>()) {
+ Diag(New->getLocation(), diag::err_block_on_nonlocal);
+ }
+ return New;
+}
+
+/// \brief Synthesizes a variable for a parameter arising from a
+/// typedef.
+ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0,
+ T, Context.getTrivialTypeSourceInfo(T, Loc),
+ SC_None, SC_None, 0);
+ Param->setImplicit();
+ return Param;
+}
+
+void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param,
+ ParmVarDecl * const *ParamEnd) {
+ // Don't diagnose unused-parameter errors in template instantiations; we
+ // will already have done so in the template itself.
+ if (!ActiveTemplateInstantiations.empty())
+ return;
+
+ for (; Param != ParamEnd; ++Param) {
+ if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+ !(*Param)->hasAttr<UnusedAttr>()) {
+ Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+ << (*Param)->getDeclName();
+ }
+ }
+}
+
+void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
+ ParmVarDecl * const *ParamEnd,
+ QualType ReturnTy,
+ NamedDecl *D) {
+ if (LangOpts.NumLargeByValueCopy == 0) // No check.
+ return;
+
+ // Warn if the return value is pass-by-value and larger than the specified
+ // threshold.
+ if (ReturnTy->isPODType()) {
+ unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
+ if (Size > LangOpts.NumLargeByValueCopy)
+ Diag(D->getLocation(), diag::warn_return_value_size)
+ << D->getDeclName() << Size;
+ }
+
+ // Warn if any parameter is pass-by-value and larger than the specified
+ // threshold.
+ for (; Param != ParamEnd; ++Param) {
+ QualType T = (*Param)->getType();
+ if (!T->isPODType())
+ continue;
+ unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
+ if (Size > LangOpts.NumLargeByValueCopy)
+ Diag((*Param)->getLocation(), diag::warn_parameter_size)
+ << (*Param)->getDeclName() << Size;
+ }
+}
+
+ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
+ TypeSourceInfo *TSInfo, QualType T,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ VarDecl::StorageClass StorageClass,
+ VarDecl::StorageClass StorageClassAsWritten) {
+ ParmVarDecl *New = ParmVarDecl::Create(Context, DC, NameLoc, Name,
+ adjustParameterType(T), TSInfo,
+ StorageClass, StorageClassAsWritten,
+ 0);
+
+ // Parameters can not be abstract class types.
+ // For record types, this is done by the AbstractClassUsageDiagnoser once
+ // the class has been completely parsed.
+ if (!CurContext->isRecord() &&
+ RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl,
+ AbstractParamType))
+ New->setInvalidDecl();
+
+ // Parameter declarators cannot be interface types. All ObjC objects are
+ // passed by reference.
+ if (T->isObjCObjectType()) {
+ Diag(NameLoc,
+ diag::err_object_cannot_be_passed_returned_by_value) << 1 << T;
+ New->setInvalidDecl();
+ }
+
+ // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
+ // duration shall not be qualified by an address-space qualifier."
+ // Since all parameters have automatic store duration, they can not have
+ // an address space.
+ if (T.getAddressSpace() != 0) {
+ Diag(NameLoc, diag::err_arg_with_address_space);
+ New->setInvalidDecl();
+ }
+
+ return New;
+}
+
+void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls) {
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+ // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared'
+ // for a K&R function.
+ if (!FTI.hasPrototype) {
+ for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
+ --i;
+ if (FTI.ArgInfo[i].Param == 0) {
+ llvm::SmallString<256> Code;
+ llvm::raw_svector_ostream(Code) << " int "
+ << FTI.ArgInfo[i].Ident->getName()
+ << ";\n";
+ Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
+ << FTI.ArgInfo[i].Ident
+ << FixItHint::CreateInsertion(LocAfterDecls, Code.str());
+
+ // Implicitly declare the argument as type 'int' for lack of a better
+ // type.
+ DeclSpec DS;
+ const char* PrevSpec; // unused
+ unsigned DiagID; // unused
+ DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
+ PrevSpec, DiagID);
+ Declarator ParamD(DS, Declarator::KNRTypeListContext);
+ ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
+ FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
+ }
+ }
+ }
+}
+
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
+ Declarator &D) {
+ assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(D.isFunctionDeclarator() && "Not a function declarator!");
+ Scope *ParentScope = FnBodyScope->getParent();
+
+ Decl *DP = HandleDeclarator(ParentScope, D,
+ MultiTemplateParamsArg(*this),
+ /*IsFunctionDefinition=*/true);
+ return ActOnStartOfFunctionDef(FnBodyScope, DP);
+}
+
+static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
+ // Don't warn about invalid declarations.
+ if (FD->isInvalidDecl())
+ return false;
+
+ // Or declarations that aren't global.
+ if (!FD->isGlobal())
+ return false;
+
+ // Don't warn about C++ member functions.
+ if (isa<CXXMethodDecl>(FD))
+ return false;
+
+ // Don't warn about 'main'.
+ if (FD->isMain())
+ return false;
+
+ // Don't warn about inline functions.
+ if (FD->isInlineSpecified())
+ return false;
+
+ // Don't warn about function templates.
+ if (FD->getDescribedFunctionTemplate())
+ return false;
+
+ // Don't warn about function template specializations.
+ if (FD->isFunctionTemplateSpecialization())
+ return false;
+
+ bool MissingPrototype = true;
+ for (const FunctionDecl *Prev = FD->getPreviousDeclaration();
+ Prev; Prev = Prev->getPreviousDeclaration()) {
+ // Ignore any declarations that occur in function or method
+ // scope, because they aren't visible from the header.
+ if (Prev->getDeclContext()->isFunctionOrMethod())
+ continue;
+
+ MissingPrototype = !Prev->getType()->isFunctionProtoType();
+ break;
+ }
+
+ return MissingPrototype;
+}
+
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
+ // Clear the last template instantiation error context.
+ LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
+
+ if (!D)
+ return D;
+ FunctionDecl *FD = 0;
+
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+ FD = FunTmpl->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D);
+
+ // Enter a new function scope
+ PushFunctionScope();
+
+ // See if this is a redefinition.
+ // But don't complain if we're in GNU89 mode and the previous definition
+ // was an extern inline function.
+ const FunctionDecl *Definition;
+ if (FD->hasBody(Definition) &&
+ !canRedefineFunction(Definition, getLangOptions())) {
+ if (getLangOptions().GNUMode && Definition->isInlineSpecified() &&
+ Definition->getStorageClass() == SC_Extern)
+ Diag(FD->getLocation(), diag::err_redefinition_extern_inline)
+ << FD->getDeclName() << getLangOptions().CPlusPlus;
+ else
+ Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
+ Diag(Definition->getLocation(), diag::note_previous_definition);
+ }
+
+ // Builtin functions cannot be defined.
+ if (unsigned BuiltinID = FD->getBuiltinID()) {
+ if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
+ Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
+ FD->setInvalidDecl();
+ }
+ }
+
+ // The return type of a function definition must be complete
+ // (C99 6.9.1p3, C++ [dcl.fct]p6).
+ QualType ResultType = FD->getResultType();
+ if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
+ !FD->isInvalidDecl() &&
+ RequireCompleteType(FD->getLocation(), ResultType,
+ diag::err_func_def_incomplete_result))
+ FD->setInvalidDecl();
+
+ // GNU warning -Wmissing-prototypes:
+ // Warn if a global function is defined without a previous
+ // prototype declaration. This warning is issued even if the
+ // definition itself provides a prototype. The aim is to detect
+ // global functions that fail to be declared in header files.
+ if (ShouldWarnAboutMissingPrototype(FD))
+ Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+ if (FnBodyScope)
+ PushDeclContext(FnBodyScope, FD);
+
+ // Check the validity of our function parameters
+ CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(),
+ /*CheckParameterNames=*/true);
+
+ // Introduce our parameters into the function scope
+ for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) {
+ ParmVarDecl *Param = FD->getParamDecl(p);
+ Param->setOwningFunction(FD);
+
+ // If this has an identifier, add it to the scope stack.
+ if (Param->getIdentifier() && FnBodyScope) {
+ CheckShadow(FnBodyScope, Param);
+
+ PushOnScopeChains(Param, FnBodyScope);
+ }
+ }
+
+ // Checking attributes of current function definition
+ // dllimport attribute.
+ DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
+ if (DA && (!FD->getAttr<DLLExportAttr>())) {
+ // dllimport attribute cannot be directly applied to definition.
+ if (!DA->isInherited()) {
+ Diag(FD->getLocation(),
+ diag::err_attribute_can_be_applied_only_to_symbol_declaration)
+ << "dllimport";
+ FD->setInvalidDecl();
+ return FD;
+ }
+
+ // Visual C++ appears to not think this is an issue, so only issue
+ // a warning when Microsoft extensions are disabled.
+ if (!LangOpts.Microsoft) {
+ // If a symbol previously declared dllimport is later defined, the
+ // attribute is ignored in subsequent references, and a warning is
+ // emitted.
+ Diag(FD->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << FD->getName() << "dllimport";
+ }
+ }
+ return FD;
+}
+
+/// \brief Given the set of return statements within a function body,
+/// compute the variables that are subject to the named return value
+/// optimization.
+///
+/// Each of the variables that is subject to the named return value
+/// optimization will be marked as NRVO variables in the AST, and any
+/// return statement that has a marked NRVO variable as its NRVO candidate can
+/// use the named return value optimization.
+///
+/// This function applies a very simplistic algorithm for NRVO: if every return
+/// statement in the function has the same NRVO candidate, that candidate is
+/// the NRVO variable.
+///
+/// FIXME: Employ a smarter algorithm that accounts for multiple return
+/// statements and the lifetimes of the NRVO candidates. We should be able to
+/// find a maximal set of NRVO variables.
+static void ComputeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
+ ReturnStmt **Returns = Scope->Returns.data();
+
+ const VarDecl *NRVOCandidate = 0;
+ for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
+ if (!Returns[I]->getNRVOCandidate())
+ return;
+
+ if (!NRVOCandidate)
+ NRVOCandidate = Returns[I]->getNRVOCandidate();
+ else if (NRVOCandidate != Returns[I]->getNRVOCandidate())
+ return;
+ }
+
+ if (NRVOCandidate)
+ const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
+}
+
+Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
+ return ActOnFinishFunctionBody(D, move(BodyArg), false);
+}
+
+Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
+ bool IsInstantiation) {
+ FunctionDecl *FD = 0;
+ FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
+ if (FunTmpl)
+ FD = FunTmpl->getTemplatedDecl();
+ else
+ FD = dyn_cast_or_null<FunctionDecl>(dcl);
+
+ sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
+
+ if (FD) {
+ FD->setBody(Body);
+ if (FD->isMain()) {
+ // C and C++ allow for main to automagically return 0.
+ // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3.
+ FD->setHasImplicitReturnZero(true);
+ WP.disableCheckFallThrough();
+ }
+
+ if (!FD->isInvalidDecl()) {
+ DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+ DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
+ FD->getResultType(), FD);
+
+ // If this is a constructor, we need a vtable.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
+ MarkVTableUsed(FD->getLocation(), Constructor->getParent());
+
+ ComputeNRVO(Body, getCurFunction());
+ }
+
+ assert(FD == getCurFunctionDecl() && "Function parsing confused");
+ } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
+ assert(MD == getCurMethodDecl() && "Method parsing confused");
+ MD->setBody(Body);
+ if (Body)
+ MD->setEndLoc(Body->getLocEnd());
+ if (!MD->isInvalidDecl()) {
+ DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
+ DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
+ MD->getResultType(), MD);
+ }
+ } else {
+ return 0;
+ }
+
+ // Verify and clean out per-function state.
+ if (Body) {
+ // C++ constructors that have function-try-blocks can't have return
+ // statements in the handlers of that block. (C++ [except.handle]p14)
+ // Verify this.
+ if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
+ DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+
+ // Verify that that gotos and switch cases don't jump into scopes illegally.
+ // Verify that that gotos and switch cases don't jump into scopes illegally.
+ if (getCurFunction()->NeedsScopeChecking() &&
+ !dcl->isInvalidDecl() &&
+ !hasAnyErrorsInThisFunction())
+ DiagnoseInvalidJumps(Body);
+
+ if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
+ if (!Destructor->getParent()->isDependentType())
+ CheckDestructor(Destructor);
+
+ MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
+ Destructor->getParent());
+ }
+
+ // If any errors have occurred, clear out any temporaries that may have
+ // been leftover. This ensures that these temporaries won't be picked up for
+ // deletion in some later function.
+ if (PP.getDiagnostics().hasErrorOccurred())
+ ExprTemporaries.clear();
+ else if (!isa<FunctionTemplateDecl>(dcl)) {
+ // Since the body is valid, issue any analysis-based warnings that are
+ // enabled.
+ QualType ResultType;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) {
+ AnalysisWarnings.IssueWarnings(WP, FD);
+ } else {
+ ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl);
+ AnalysisWarnings.IssueWarnings(WP, MD);
+ }
+ }
+
+ assert(ExprTemporaries.empty() && "Leftover temporaries in function");
+ }
+
+ if (!IsInstantiation)
+ PopDeclContext();
+
+ PopFunctionOrBlockScope();
+
+ // If any errors have occurred, clear out any temporaries that may have
+ // been leftover. This ensures that these temporaries won't be picked up for
+ // deletion in some later function.
+ if (getDiagnostics().hasErrorOccurred())
+ ExprTemporaries.clear();
+
+ return dcl;
+}
+
+/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
+/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
+NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
+ IdentifierInfo &II, Scope *S) {
+ // Before we produce a declaration for an implicitly defined
+ // function, see whether there was a locally-scoped declaration of
+ // this name as a function or variable. If so, use that
+ // (non-visible) declaration, and complain about it.
+ llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
+ = LocallyScopedExternalDecls.find(&II);
+ if (Pos != LocallyScopedExternalDecls.end()) {
+ Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
+ Diag(Pos->second->getLocation(), diag::note_previous_declaration);
+ return Pos->second;
+ }
+
+ // Extension in C99. Legal in C90, but warn about it.
+ if (II.getName().startswith("__builtin_"))
+ Diag(Loc, diag::warn_builtin_unknown) << &II;
+ else if (getLangOptions().C99)
+ Diag(Loc, diag::ext_implicit_function_decl) << &II;
+ else
+ Diag(Loc, diag::warn_implicit_function_decl) << &II;
+
+ // Set a Declarator for the implicit definition: int foo();
+ const char *Dummy;
+ DeclSpec DS;
+ unsigned DiagID;
+ bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
+ (void)Error; // Silence warning.
+ assert(!Error && "Error setting up implicit decl!");
+ Declarator D(DS, Declarator::BlockContext);
+ D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
+ false, false, SourceLocation(), 0,
+ 0, 0, true, SourceLocation(),
+ false, SourceLocation(),
+ false, 0,0,0, Loc, Loc, D),
+ SourceLocation());
+ D.SetIdentifier(&II, Loc);
+
+ // Insert this function into translation-unit scope.
+
+ DeclContext *PrevDC = CurContext;
+ CurContext = Context.getTranslationUnitDecl();
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+ FD->setImplicit();
+
+ CurContext = PrevDC;
+
+ AddKnownFunctionAttributes(FD);
+
+ return FD;
+}
+
+/// \brief Adds any function attributes that we know a priori based on
+/// the declaration of this function.
+///
+/// These attributes can apply both to implicitly-declared builtins
+/// (like __builtin___printf_chk) or to library-declared functions
+/// like NSLog or printf.
+void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
+ if (FD->isInvalidDecl())
+ return;
+
+ // If this is a built-in function, map its builtin attributes to
+ // actual attributes.
+ if (unsigned BuiltinID = FD->getBuiltinID()) {
+ // Handle printf-formatting attributes.
+ unsigned FormatIdx;
+ bool HasVAListArg;
+ if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
+ if (!FD->getAttr<FormatAttr>())
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", FormatIdx+1,
+ HasVAListArg ? 0 : FormatIdx+2));
+ }
+ if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
+ HasVAListArg)) {
+ if (!FD->getAttr<FormatAttr>())
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "scanf", FormatIdx+1,
+ HasVAListArg ? 0 : FormatIdx+2));
+ }
+
+ // Mark const if we don't care about errno and that is the only
+ // thing preventing the function from being const. This allows
+ // IRgen to use LLVM intrinsics for such functions.
+ if (!getLangOptions().MathErrno &&
+ Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
+ if (!FD->getAttr<ConstAttr>())
+ FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ }
+
+ if (Context.BuiltinInfo.isNoThrow(BuiltinID))
+ FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
+ if (Context.BuiltinInfo.isConst(BuiltinID))
+ FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
+ }
+
+ IdentifierInfo *Name = FD->getIdentifier();
+ if (!Name)
+ return;
+ if ((!getLangOptions().CPlusPlus &&
+ FD->getDeclContext()->isTranslationUnit()) ||
+ (isa<LinkageSpecDecl>(FD->getDeclContext()) &&
+ cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
+ LinkageSpecDecl::lang_c)) {
+ // Okay: this could be a libc/libm/Objective-C function we know
+ // about.
+ } else
+ return;
+
+ if (Name->isStr("NSLog") || Name->isStr("NSLogv")) {
+ // FIXME: NSLog and NSLogv should be target specific
+ if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) {
+ // FIXME: We known better than our headers.
+ const_cast<FormatAttr *>(Format)->setType(Context, "printf");
+ } else
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", 1,
+ Name->isStr("NSLogv") ? 0 : 2));
+ } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
+ // FIXME: asprintf and vasprintf aren't C99 functions. Should they be
+ // target-specific builtins, perhaps?
+ if (!FD->getAttr<FormatAttr>())
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", 2,
+ Name->isStr("vasprintf") ? 0 : 3));
+ }
+}
+
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ TypeSourceInfo *TInfo) {
+ assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
+ assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
+
+ if (!TInfo) {
+ assert(D.isInvalidType() && "no declarator info for valid type");
+ TInfo = Context.getTrivialTypeSourceInfo(T);
+ }
+
+ // Scope manipulation handled by caller.
+ TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
+ D.getIdentifierLoc(),
+ D.getIdentifier(),
+ TInfo);
+
+ // Bail out immediately if we have an invalid declaration.
+ if (D.isInvalidType()) {
+ NewTD->setInvalidDecl();
+ return NewTD;
+ }
+
+ // C++ [dcl.typedef]p8:
+ // If the typedef declaration defines an unnamed class (or
+ // enum), the first typedef-name declared by the declaration
+ // to be that class type (or enum type) is used to denote the
+ // class type (or enum type) for linkage purposes only.
+ // We need to check whether the type was declared in the declaration.
+ switch (D.getDeclSpec().getTypeSpecType()) {
+ case TST_enum:
+ case TST_struct:
+ case TST_union:
+ case TST_class: {
+ TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+
+ // Do nothing if the tag is not anonymous or already has an
+ // associated typedef (from an earlier typedef in this decl group).
+ if (tagFromDeclSpec->getIdentifier()) break;
+ if (tagFromDeclSpec->getTypedefForAnonDecl()) break;
+
+ // A well-formed anonymous tag must always be a TUK_Definition.
+ assert(tagFromDeclSpec->isThisDeclarationADefinition());
+
+ // The type must match the tag exactly; no qualifiers allowed.
+ if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec)))
+ break;
+
+ // Otherwise, set this is the anon-decl typedef for the tag.
+ tagFromDeclSpec->setTypedefForAnonDecl(NewTD);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return NewTD;
+}
+
+
+/// \brief Determine whether a tag with a given kind is acceptable
+/// as a redeclaration of the given tag declaration.
+///
+/// \returns true if the new tag kind is acceptable, false otherwise.
+bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
+ TagTypeKind NewTag,
+ SourceLocation NewTagLoc,
+ const IdentifierInfo &Name) {
+ // C++ [dcl.type.elab]p3:
+ // The class-key or enum keyword present in the
+ // elaborated-type-specifier shall agree in kind with the
+ // declaration to which the name in the elaborated-type-specifier
+ // refers. This rule also applies to the form of
+ // elaborated-type-specifier that declares a class-name or
+ // friend class since it can be construed as referring to the
+ // definition of the class. Thus, in any
+ // elaborated-type-specifier, the enum keyword shall be used to
+ // refer to an enumeration (7.2), the union class-key shall be
+ // used to refer to a union (clause 9), and either the class or
+ // struct class-key shall be used to refer to a class (clause 9)
+ // declared using the class or struct class-key.
+ TagTypeKind OldTag = Previous->getTagKind();
+ if (OldTag == NewTag)
+ return true;
+
+ if ((OldTag == TTK_Struct || OldTag == TTK_Class) &&
+ (NewTag == TTK_Struct || NewTag == TTK_Class)) {
+ // Warn about the struct/class tag mismatch.
+ bool isTemplate = false;
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous))
+ isTemplate = Record->getDescribedClassTemplate();
+
+ Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch)
+ << (NewTag == TTK_Class)
+ << isTemplate << &Name
+ << FixItHint::CreateReplacement(SourceRange(NewTagLoc),
+ OldTag == TTK_Class? "class" : "struct");
+ Diag(Previous->getLocation(), diag::note_previous_use);
+ return true;
+ }
+ return false;
+}
+
+/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the
+/// former case, Name will be non-null. In the later case, Name will be null.
+/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
+/// reference/declaration/definition of a tag.
+Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent,
+ bool ScopedEnum, bool ScopedEnumUsesClassTag,
+ TypeResult UnderlyingType) {
+ // If this is not a definition, it must have a name.
+ assert((Name != 0 || TUK == TUK_Definition) &&
+ "Nameless record must be a definition!");
+ assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference);
+
+ OwnedDecl = false;
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+ // FIXME: Check explicit specializations more carefully.
+ bool isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+ bool Invalid = false;
+
+ // We only need to do this matching if we have template parameters
+ // or a scope specifier, which also conveniently avoids this work
+ // for non-C++ cases.
+ if (NumMatchedTemplateParamLists ||
+ (SS.isNotEmpty() && TUK != TUK_Reference)) {
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
+ TemplateParameterLists.get(),
+ TemplateParameterLists.size(),
+ TUK == TUK_Friend,
+ isExplicitSpecialization,
+ Invalid)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams->size() > 0) {
+ // This is a declaration or definition of a class template (which may
+ // be a member of another template).
+ if (Invalid)
+ return 0;
+
+ OwnedDecl = false;
+ DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
+ SS, Name, NameLoc, Attr,
+ TemplateParams,
+ AS);
+ TemplateParameterLists.release();
+ return Result.get();
+ } else {
+ // The "template<>" header is extraneous.
+ Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+ << TypeWithKeyword::getTagTypeKindName(Kind) << Name;
+ isExplicitSpecialization = true;
+ }
+ }
+ }
+
+ // Figure out the underlying type if this a enum declaration. We need to do
+ // this early, because it's needed to detect if this is an incompatible
+ // redeclaration.
+ llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+
+ if (Kind == TTK_Enum) {
+ if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
+ // No underlying type explicitly specified, or we failed to parse the
+ // type, default to int.
+ EnumUnderlying = Context.IntTy.getTypePtr();
+ else if (UnderlyingType.get()) {
+ // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
+ // integral type; any cv-qualification is ignored.
+ TypeSourceInfo *TI = 0;
+ QualType T = GetTypeFromParser(UnderlyingType.get(), &TI);
+ EnumUnderlying = TI;
+
+ SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
+
+ if (!T->isDependentType() && !T->isIntegralType(Context)) {
+ Diag(UnderlyingLoc, diag::err_enum_invalid_underlying)
+ << T;
+ // Recover by falling back to int.
+ EnumUnderlying = Context.IntTy.getTypePtr();
+ }
+
+ if (DiagnoseUnexpandedParameterPack(UnderlyingLoc, TI,
+ UPPC_FixedUnderlyingType))
+ EnumUnderlying = Context.IntTy.getTypePtr();
+
+ } else if (getLangOptions().Microsoft)
+ // Microsoft enums are always of int type.
+ EnumUnderlying = Context.IntTy.getTypePtr();
+ }
+
+ DeclContext *SearchDC = CurContext;
+ DeclContext *DC = CurContext;
+ bool isStdBadAlloc = false;
+
+ RedeclarationKind Redecl = ForRedeclaration;
+ if (TUK == TUK_Friend || TUK == TUK_Reference)
+ Redecl = NotForRedeclaration;
+
+ LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
+
+ if (Name && SS.isNotEmpty()) {
+ // We have a nested-name tag ('struct foo::bar').
+
+ // Check for invalid 'foo::'.
+ if (SS.isInvalid()) {
+ Name = 0;
+ goto CreateNewDecl;
+ }
+
+ // If this is a friend or a reference to a class in a dependent
+ // context, don't try to make a decl for it.
+ if (TUK == TUK_Friend || TUK == TUK_Reference) {
+ DC = computeDeclContext(SS, false);
+ if (!DC) {
+ IsDependent = true;
+ return 0;
+ }
+ } else {
+ DC = computeDeclContext(SS, true);
+ if (!DC) {
+ Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
+ << SS.getRange();
+ return 0;
+ }
+ }
+
+ if (RequireCompleteDeclContext(SS, DC))
+ return 0;
+
+ SearchDC = DC;
+ // Look-up name inside 'foo::'.
+ LookupQualifiedName(Previous, DC);
+
+ if (Previous.isAmbiguous())
+ return 0;
+
+ if (Previous.empty()) {
+ // Name lookup did not find anything. However, if the
+ // nested-name-specifier refers to the current instantiation,
+ // and that current instantiation has any dependent base
+ // classes, we might find something at instantiation time: treat
+ // this as a dependent elaborated-type-specifier.
+ // But this only makes any sense for reference-like lookups.
+ if (Previous.wasNotFoundInCurrentInstantiation() &&
+ (TUK == TUK_Reference || TUK == TUK_Friend)) {
+ IsDependent = true;
+ return 0;
+ }
+
+ // A tag 'foo::bar' must already exist.
+ Diag(NameLoc, diag::err_not_tag_in_scope)
+ << Kind << Name << DC << SS.getRange();
+ Name = 0;
+ Invalid = true;
+ goto CreateNewDecl;
+ }
+ } else if (Name) {
+ // If this is a named struct, check to see if there was a previous forward
+ // declaration or definition.
+ // FIXME: We're looking into outer scopes here, even when we
+ // shouldn't be. Doing so can result in ambiguities that we
+ // shouldn't be diagnosing.
+ LookupName(Previous, S);
+
+ // Note: there used to be some attempt at recovery here.
+ if (Previous.isAmbiguous())
+ return 0;
+
+ if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
+ // FIXME: This makes sure that we ignore the contexts associated
+ // with C structs, unions, and enums when looking for a matching
+ // tag declaration or definition. See the similar lookup tweak
+ // in Sema::LookupName; is there a better way to deal with this?
+ while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
+ SearchDC = SearchDC->getParent();
+ }
+ } else if (S->isFunctionPrototypeScope()) {
+ // If this is an enum declaration in function prototype scope, set its
+ // initial context to the translation unit.
+ SearchDC = Context.getTranslationUnitDecl();
+ }
+
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
+ // Just pretend that we didn't see the previous declaration.
+ Previous.clear();
+ }
+
+ if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
+ DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
+ // This is a declaration of or a reference to "std::bad_alloc".
+ isStdBadAlloc = true;
+
+ if (Previous.empty() && StdBadAlloc) {
+ // std::bad_alloc has been implicitly declared (but made invisible to
+ // name lookup). Fill in this implicit declaration as the previous
+ // declaration, so that the declarations get chained appropriately.
+ Previous.addDecl(getStdBadAlloc());
+ }
+ }
+
+ // If we didn't find a previous declaration, and this is a reference
+ // (or friend reference), move to the correct scope. In C++, we
+ // also need to do a redeclaration lookup there, just in case
+ // there's a shadow friend decl.
+ if (Name && Previous.empty() &&
+ (TUK == TUK_Reference || TUK == TUK_Friend)) {
+ if (Invalid) goto CreateNewDecl;
+ assert(SS.isEmpty());
+
+ if (TUK == TUK_Reference) {
+ // C++ [basic.scope.pdecl]p5:
+ // -- for an elaborated-type-specifier of the form
+ //
+ // class-key identifier
+ //
+ // if the elaborated-type-specifier is used in the
+ // decl-specifier-seq or parameter-declaration-clause of a
+ // function defined in namespace scope, the identifier is
+ // declared as a class-name in the namespace that contains
+ // the declaration; otherwise, except as a friend
+ // declaration, the identifier is declared in the smallest
+ // non-class, non-function-prototype scope that contains the
+ // declaration.
+ //
+ // C99 6.7.2.3p8 has a similar (but not identical!) provision for
+ // C structs and unions.
+ //
+ // It is an error in C++ to declare (rather than define) an enum
+ // type, including via an elaborated type specifier. We'll
+ // diagnose that later; for now, declare the enum in the same
+ // scope as we would have picked for any other tag type.
+ //
+ // GNU C also supports this behavior as part of its incomplete
+ // enum types extension, while GNU C++ does not.
+ //
+ // Find the context where we'll be declaring the tag.
+ // FIXME: We would like to maintain the current DeclContext as the
+ // lexical context,
+ while (SearchDC->isRecord() || SearchDC->isTransparentContext())
+ SearchDC = SearchDC->getParent();
+
+ // Find the scope where we'll be declaring the tag.
+ while (S->isClassScope() ||
+ (getLangOptions().CPlusPlus &&
+ S->isFunctionPrototypeScope()) ||
+ ((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext()))
+ S = S->getParent();
+ } else {
+ assert(TUK == TUK_Friend);
+ // C++ [namespace.memdef]p3:
+ // If a friend declaration in a non-local class first declares a
+ // class or function, the friend class or function is a member of
+ // the innermost enclosing namespace.
+ SearchDC = SearchDC->getEnclosingNamespaceContext();
+ }
+
+ // In C++, we need to do a redeclaration lookup to properly
+ // diagnose some problems.
+ if (getLangOptions().CPlusPlus) {
+ Previous.setRedeclarationKind(ForRedeclaration);
+ LookupQualifiedName(Previous, SearchDC);
+ }
+ }
+
+ if (!Previous.empty()) {
+ NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+ // It's okay to have a tag decl in the same scope as a typedef
+ // which hides a tag decl in the same scope. Finding this
+ // insanity with a redeclaration lookup can only actually happen
+ // in C++.
+ //
+ // This is also okay for elaborated-type-specifiers, which is
+ // technically forbidden by the current standard but which is
+ // okay according to the likely resolution of an open issue;
+ // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
+ if (getLangOptions().CPlusPlus) {
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) {
+ if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+ TagDecl *Tag = TT->getDecl();
+ if (Tag->getDeclName() == Name &&
+ Tag->getDeclContext()->getRedeclContext()
+ ->Equals(TD->getDeclContext()->getRedeclContext())) {
+ PrevDecl = Tag;
+ Previous.clear();
+ Previous.addDecl(Tag);
+ Previous.resolveKind();
+ }
+ }
+ }
+ }
+
+ if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
+ // If this is a use of a previous tag, or if the tag is already declared
+ // in the same scope (so that the definition/declaration completes or
+ // rementions the tag), reuse the decl.
+ if (TUK == TUK_Reference || TUK == TUK_Friend ||
+ isDeclInScope(PrevDecl, SearchDC, S)) {
+ // Make sure that this wasn't declared as an enum and now used as a
+ // struct or something similar.
+ if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) {
+ bool SafeToContinue
+ = (PrevTagDecl->getTagKind() != TTK_Enum &&
+ Kind != TTK_Enum);
+ if (SafeToContinue)
+ Diag(KWLoc, diag::err_use_with_wrong_tag)
+ << Name
+ << FixItHint::CreateReplacement(SourceRange(KWLoc),
+ PrevTagDecl->getKindName());
+ else
+ Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+
+ if (SafeToContinue)
+ Kind = PrevTagDecl->getTagKind();
+ else {
+ // Recover by making this an anonymous redefinition.
+ Name = 0;
+ Previous.clear();
+ Invalid = true;
+ }
+ }
+
+ if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
+ const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
+
+ // All conflicts with previous declarations are recovered by
+ // returning the previous declaration.
+ if (ScopedEnum != PrevEnum->isScoped()) {
+ Diag(KWLoc, diag::err_enum_redeclare_scoped_mismatch)
+ << PrevEnum->isScoped();
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+ return PrevTagDecl;
+ }
+ else if (EnumUnderlying && PrevEnum->isFixed()) {
+ QualType T;
+ if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
+ T = TI->getType();
+ else
+ T = QualType(EnumUnderlying.get<const Type*>(), 0);
+
+ if (!Context.hasSameUnqualifiedType(T, PrevEnum->getIntegerType())) {
+ Diag(NameLoc.isValid() ? NameLoc : KWLoc,
+ diag::err_enum_redeclare_type_mismatch)
+ << T
+ << PrevEnum->getIntegerType();
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+ return PrevTagDecl;
+ }
+ }
+ else if (!EnumUnderlying.isNull() != PrevEnum->isFixed()) {
+ Diag(KWLoc, diag::err_enum_redeclare_fixed_mismatch)
+ << PrevEnum->isFixed();
+ Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
+ return PrevTagDecl;
+ }
+ }
+
+ if (!Invalid) {
+ // If this is a use, just return the declaration we found.
+
+ // FIXME: In the future, return a variant or some other clue
+ // for the consumer of this Decl to know it doesn't own it.
+ // For our current ASTs this shouldn't be a problem, but will
+ // need to be changed with DeclGroups.
+ if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) ||
+ TUK == TUK_Friend)
+ return PrevTagDecl;
+
+ // Diagnose attempts to redefine a tag.
+ if (TUK == TUK_Definition) {
+ if (TagDecl *Def = PrevTagDecl->getDefinition()) {
+ // If we're defining a specialization and the previous definition
+ // is from an implicit instantiation, don't emit an error
+ // here; we'll catch this in the general case below.
+ if (!isExplicitSpecialization ||
+ !isa<CXXRecordDecl>(Def) ||
+ cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization) {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // If this is a redefinition, recover by making this
+ // struct be anonymous, which will make any later
+ // references get the previous definition.
+ Name = 0;
+ Previous.clear();
+ Invalid = true;
+ }
+ } else {
+ // If the type is currently being defined, complain
+ // about a nested redefinition.
+ const TagType *Tag
+ = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
+ if (Tag->isBeingDefined()) {
+ Diag(NameLoc, diag::err_nested_redefinition) << Name;
+ Diag(PrevTagDecl->getLocation(),
+ diag::note_previous_definition);
+ Name = 0;
+ Previous.clear();
+ Invalid = true;
+ }
+ }
+
+ // Okay, this is definition of a previously declared or referenced
+ // tag PrevDecl. We're going to create a new Decl for it.
+ }
+ }
+ // If we get here we have (another) forward declaration or we
+ // have a definition. Just create a new decl.
+
+ } else {
+ // If we get here, this is a definition of a new tag type in a nested
+ // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
+ // new decl/type. We set PrevDecl to NULL so that the entities
+ // have distinct types.
+ Previous.clear();
+ }
+ // If we get here, we're going to create a new Decl. If PrevDecl
+ // is non-NULL, it's a definition of the tag declared by
+ // PrevDecl. If it's NULL, we have a new definition.
+
+
+ // Otherwise, PrevDecl is not a tag, but was found with tag
+ // lookup. This is only actually possible in C++, where a few
+ // things like templates still live in the tag namespace.
+ } else {
+ assert(getLangOptions().CPlusPlus);
+
+ // Use a better diagnostic if an elaborated-type-specifier
+ // found the wrong kind of type on the first
+ // (non-redeclaration) lookup.
+ if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
+ !Previous.isForRedeclaration()) {
+ unsigned Kind = 0;
+ if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+ else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+ Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
+ Diag(PrevDecl->getLocation(), diag::note_declared_at);
+ Invalid = true;
+
+ // Otherwise, only diagnose if the declaration is in scope.
+ } else if (!isDeclInScope(PrevDecl, SearchDC, S)) {
+ // do nothing
+
+ // Diagnose implicit declarations introduced by elaborated types.
+ } else if (TUK == TUK_Reference || TUK == TUK_Friend) {
+ unsigned Kind = 0;
+ if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
+ else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
+ Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
+ Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+ Invalid = true;
+
+ // Otherwise it's a declaration. Call out a particularly common
+ // case here.
+ } else if (isa<TypedefDecl>(PrevDecl)) {
+ Diag(NameLoc, diag::err_tag_definition_of_typedef)
+ << Name
+ << cast<TypedefDecl>(PrevDecl)->getUnderlyingType();
+ Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
+ Invalid = true;
+
+ // Otherwise, diagnose.
+ } else {
+ // The tag name clashes with something else in the target scope,
+ // issue an error and recover by making this tag be anonymous.
+ Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Name = 0;
+ Invalid = true;
+ }
+
+ // The existing declaration isn't relevant to us; we're in a
+ // new scope, so clear out the previous declaration.
+ Previous.clear();
+ }
+ }
+
+CreateNewDecl:
+
+ TagDecl *PrevDecl = 0;
+ if (Previous.isSingleResult())
+ PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
+
+ // If there is an identifier, use the location of the identifier as the
+ // location of the decl, otherwise use the location of the struct/union
+ // keyword.
+ SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
+
+ // Otherwise, create a new declaration. If there is a previous
+ // declaration of the same entity, the two will be linked via
+ // PrevDecl.
+ TagDecl *New;
+
+ bool IsForwardReference = false;
+ if (Kind == TTK_Enum) {
+ // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+ // enum X { A, B, C } D; D should chain to X.
+ New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
+ cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
+ ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
+ // If this is an undefined enum, warn.
+ if (TUK != TUK_Definition && !Invalid) {
+ TagDecl *Def;
+ if (getLangOptions().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) {
+ // C++0x: 7.2p2: opaque-enum-declaration.
+ // Conflicts are diagnosed above. Do nothing.
+ }
+ else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
+ Diag(Loc, diag::ext_forward_ref_enum_def)
+ << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ } else {
+ unsigned DiagID = diag::ext_forward_ref_enum;
+ if (getLangOptions().Microsoft)
+ DiagID = diag::ext_ms_forward_ref_enum;
+ else if (getLangOptions().CPlusPlus)
+ DiagID = diag::err_forward_ref_enum;
+ Diag(Loc, DiagID);
+
+ // If this is a forward-declared reference to an enumeration, make a
+ // note of it; we won't actually be introducing the declaration into
+ // the declaration context.
+ if (TUK == TUK_Reference)
+ IsForwardReference = true;
+ }
+ }
+
+ if (EnumUnderlying) {
+ EnumDecl *ED = cast<EnumDecl>(New);
+ if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
+ ED->setIntegerTypeSourceInfo(TI);
+ else
+ ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
+ ED->setPromotionType(ED->getIntegerType());
+ }
+
+ } else {
+ // struct/union/class
+
+ // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+ // struct X { int A; } D; D should chain to X.
+ if (getLangOptions().CPlusPlus) {
+ // FIXME: Look for a way to use RecordDecl for simple structs.
+ New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+ cast_or_null<CXXRecordDecl>(PrevDecl));
+
+ if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
+ StdBadAlloc = cast<CXXRecordDecl>(New);
+ } else
+ New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
+ cast_or_null<RecordDecl>(PrevDecl));
+ }
+
+ // Maybe add qualifier info.
+ if (SS.isNotEmpty()) {
+ if (SS.isSet()) {
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ New->setQualifierInfo(NNS, SS.getRange());
+ if (NumMatchedTemplateParamLists > 0) {
+ New->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
+ }
+ else
+ Invalid = true;
+ }
+
+ if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) {
+ // Add alignment attributes if necessary; these attributes are checked when
+ // the ASTContext lays out the structure.
+ //
+ // It is important for implementing the correct semantics that this
+ // happen here (in act on tag decl). The #pragma pack stack is
+ // maintained as a result of parser callbacks which can occur at
+ // many points during the parsing of a struct declaration (because
+ // the #pragma tokens are effectively skipped over during the
+ // parsing of the struct).
+ AddAlignmentAttributesForRecord(RD);
+ }
+
+ // If this is a specialization of a member class (of a class template),
+ // check the specialization.
+ if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
+ Invalid = true;
+
+ if (Invalid)
+ New->setInvalidDecl();
+
+ if (Attr)
+ ProcessDeclAttributeList(S, New, Attr);
+
+ // If we're declaring or defining a tag in function prototype scope
+ // in C, note that this type can only be used within the function.
+ if (Name && S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus)
+ Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+
+ // Set the lexical context. If the tag has a C++ scope specifier, the
+ // lexical context will be different from the semantic context.
+ New->setLexicalDeclContext(CurContext);
+
+ // Mark this as a friend decl if applicable.
+ if (TUK == TUK_Friend)
+ New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty());
+
+ // Set the access specifier.
+ if (!Invalid && SearchDC->isRecord())
+ SetMemberAccessSpecifier(New, PrevDecl, AS);
+
+ if (TUK == TUK_Definition)
+ New->startDefinition();
+
+ // If this has an identifier, add it to the scope stack.
+ if (TUK == TUK_Friend) {
+ // We might be replacing an existing declaration in the lookup tables;
+ // if so, borrow its access specifier.
+ if (PrevDecl)
+ New->setAccess(PrevDecl->getAccess());
+
+ DeclContext *DC = New->getDeclContext()->getRedeclContext();
+ DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+ if (Name) // can be null along some error paths
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+ } else if (Name) {
+ S = getNonFieldDeclScope(S);
+ PushOnScopeChains(New, S, !IsForwardReference);
+ if (IsForwardReference)
+ SearchDC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+
+ } else {
+ CurContext->addDecl(New);
+ }
+
+ // If this is the C FILE type, notify the AST context.
+ if (IdentifierInfo *II = New->getIdentifier())
+ if (!New->isInvalidDecl() &&
+ New->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
+ II->isStr("FILE"))
+ Context.setFILEDecl(New);
+
+ OwnedDecl = true;
+ return New;
+}
+
+void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
+ AdjustDeclIfTemplate(TagD);
+ TagDecl *Tag = cast<TagDecl>(TagD);
+
+ // Enter the tag context.
+ PushDeclContext(S, Tag);
+}
+
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
+ ClassVirtSpecifiers &CVS,
+ SourceLocation LBraceLoc) {
+ AdjustDeclIfTemplate(TagD);
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
+
+ FieldCollector->StartClass();
+
+ if (!Record->getIdentifier())
+ return;
+
+ if (CVS.isFinalSpecified())
+ Record->addAttr(new (Context) FinalAttr(CVS.getFinalLoc(), Context));
+ if (CVS.isExplicitSpecified())
+ Record->addAttr(new (Context) ExplicitAttr(CVS.getExplicitLoc(), Context));
+
+ // C++ [class]p2:
+ // [...] The class-name is also inserted into the scope of the
+ // class itself; this is known as the injected-class-name. For
+ // purposes of access checking, the injected-class-name is treated
+ // as if it were a public member name.
+ CXXRecordDecl *InjectedClassName
+ = CXXRecordDecl::Create(Context, Record->getTagKind(),
+ CurContext, Record->getLocation(),
+ Record->getIdentifier(),
+ Record->getTagKeywordLoc(),
+ /*PrevDecl=*/0,
+ /*DelayTypeCreation=*/true);
+ Context.getTypeDeclType(InjectedClassName, Record);
+ InjectedClassName->setImplicit();
+ InjectedClassName->setAccess(AS_public);
+ if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
+ InjectedClassName->setDescribedClassTemplate(Template);
+ PushOnScopeChains(InjectedClassName, S);
+ assert(InjectedClassName->isInjectedClassName() &&
+ "Broken injected-class-name");
+}
+
+void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
+ SourceLocation RBraceLoc) {
+ AdjustDeclIfTemplate(TagD);
+ TagDecl *Tag = cast<TagDecl>(TagD);
+ Tag->setRBraceLoc(RBraceLoc);
+
+ if (isa<CXXRecordDecl>(Tag))
+ FieldCollector->FinishClass();
+
+ // Exit this scope of this tag's definition.
+ PopDeclContext();
+
+ // Notify the consumer that we've defined a tag.
+ Consumer.HandleTagDeclDefinition(Tag);
+}
+
+void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
+ AdjustDeclIfTemplate(TagD);
+ TagDecl *Tag = cast<TagDecl>(TagD);
+ Tag->setInvalidDecl();
+
+ // We're undoing ActOnTagStartDefinition here, not
+ // ActOnStartCXXMemberDeclarations, so we don't have to mess with
+ // the FieldCollector.
+
+ PopDeclContext();
+}
+
+// Note that FieldName may be null for anonymous bitfields.
+bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, const Expr *BitWidth,
+ bool *ZeroWidth) {
+ // Default to true; that shouldn't confuse checks for emptiness
+ if (ZeroWidth)
+ *ZeroWidth = true;
+
+ // C99 6.7.2.1p4 - verify the field type.
+ // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+ if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) {
+ // Handle incomplete types with specific error.
+ if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
+ return true;
+ if (FieldName)
+ return Diag(FieldLoc, diag::err_not_integral_type_bitfield)
+ << FieldName << FieldTy << BitWidth->getSourceRange();
+ return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield)
+ << FieldTy << BitWidth->getSourceRange();
+ } else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth),
+ UPPC_BitFieldWidth))
+ return true;
+
+ // If the bit-width is type- or value-dependent, don't try to check
+ // it now.
+ if (BitWidth->isValueDependent() || BitWidth->isTypeDependent())
+ return false;
+
+ llvm::APSInt Value;
+ if (VerifyIntegerConstantExpression(BitWidth, &Value))
+ return true;
+
+ if (Value != 0 && ZeroWidth)
+ *ZeroWidth = false;
+
+ // Zero-width bitfield is ok for anonymous field.
+ if (Value == 0 && FieldName)
+ return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
+
+ if (Value.isSigned() && Value.isNegative()) {
+ if (FieldName)
+ return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
+ << FieldName << Value.toString(10);
+ return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
+ << Value.toString(10);
+ }
+
+ if (!FieldTy->isDependentType()) {
+ uint64_t TypeSize = Context.getTypeSize(FieldTy);
+ if (Value.getZExtValue() > TypeSize) {
+ if (!getLangOptions().CPlusPlus) {
+ if (FieldName)
+ return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << (unsigned)TypeSize;
+
+ return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
+ << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
+ }
+
+ if (FieldName)
+ Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << (unsigned)TypeSize;
+ else
+ Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
+ << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
+ }
+ }
+
+ return false;
+}
+
+/// ActOnField - Each field of a struct/union/class is passed into this in order
+/// to create a FieldDecl object for it.
+Decl *Sema::ActOnField(Scope *S, Decl *TagD,
+ SourceLocation DeclStart,
+ Declarator &D, ExprTy *BitfieldWidth) {
+ FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
+ DeclStart, D, static_cast<Expr*>(BitfieldWidth),
+ AS_public);
+ return Res;
+}
+
+/// HandleField - Analyze a field of a C struct or a C++ data member.
+///
+FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
+ SourceLocation DeclStart,
+ Declarator &D, Expr *BitWidth,
+ AccessSpecifier AS) {
+ IdentifierInfo *II = D.getIdentifier();
+ SourceLocation Loc = DeclStart;
+ if (II) Loc = D.getIdentifierLoc();
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
+ if (getLangOptions().CPlusPlus) {
+ CheckExtraCXXDefaultArguments(D);
+
+ if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_DataMemberType)) {
+ D.setInvalidType();
+ T = Context.IntTy;
+ TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+ }
+ }
+
+ DiagnoseFunctionSpecifiers(D);
+
+ if (D.getDeclSpec().isThreadSpecified())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+ // Check to see if this name was declared as a member previously
+ LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+ LookupName(Previous, S);
+ assert((Previous.empty() || Previous.isOverloadedResult() ||
+ Previous.isSingleResult())
+ && "Lookup of member name should be either overloaded, single or null");
+
+ // If the name is overloaded then get any declaration else get the single result
+ NamedDecl *PrevDecl = Previous.isOverloadedResult() ?
+ Previous.getRepresentativeDecl() : Previous.getAsSingle<NamedDecl>();
+
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
+ if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
+ PrevDecl = 0;
+
+ bool Mutable
+ = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
+ SourceLocation TSSL = D.getSourceRange().getBegin();
+ FieldDecl *NewFD
+ = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, TSSL,
+ AS, PrevDecl, &D);
+
+ if (NewFD->isInvalidDecl())
+ Record->setInvalidDecl();
+
+ if (NewFD->isInvalidDecl() && PrevDecl) {
+ // Don't introduce NewFD into scope; there's already something
+ // with the same name in the same scope.
+ } else if (II) {
+ PushOnScopeChains(NewFD, S);
+ } else
+ Record->addDecl(NewFD);
+
+ return NewFD;
+}
+
+/// \brief Build a new FieldDecl and check its well-formedness.
+///
+/// This routine builds a new FieldDecl given the fields name, type,
+/// record, etc. \p PrevDecl should refer to any previous declaration
+/// with the same name and in the same scope as the field to be
+/// created.
+///
+/// \returns a new FieldDecl.
+///
+/// \todo The Declarator argument is a hack. It will be removed once
+FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
+ TypeSourceInfo *TInfo,
+ RecordDecl *Record, SourceLocation Loc,
+ bool Mutable, Expr *BitWidth,
+ SourceLocation TSSL,
+ AccessSpecifier AS, NamedDecl *PrevDecl,
+ Declarator *D) {
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ bool InvalidDecl = false;
+ if (D) InvalidDecl = D->isInvalidType();
+
+ // If we receive a broken type, recover by assuming 'int' and
+ // marking this declaration as invalid.
+ if (T.isNull()) {
+ InvalidDecl = true;
+ T = Context.IntTy;
+ }
+
+ QualType EltTy = Context.getBaseElementType(T);
+ if (!EltTy->isDependentType() &&
+ RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
+ // Fields of incomplete type force their record to be invalid.
+ Record->setInvalidDecl();
+ InvalidDecl = true;
+ }
+
+ // C99 6.7.2.1p8: A member of a structure or union may have any type other
+ // than a variably modified type.
+ if (!InvalidDecl && T->isVariablyModifiedType()) {
+ bool SizeIsNegative;
+ llvm::APSInt Oversized;
+ QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
+ SizeIsNegative,
+ Oversized);
+ if (!FixedTy.isNull()) {
+ Diag(Loc, diag::warn_illegal_constant_array_size);
+ T = FixedTy;
+ } else {
+ if (SizeIsNegative)
+ Diag(Loc, diag::err_typecheck_negative_array_size);
+ else if (Oversized.getBoolValue())
+ Diag(Loc, diag::err_array_too_large)
+ << Oversized.toString(10);
+ else
+ Diag(Loc, diag::err_typecheck_field_variable_size);
+ InvalidDecl = true;
+ }
+ }
+
+ // Fields can not have abstract class types
+ if (!InvalidDecl && RequireNonAbstractType(Loc, T,
+ diag::err_abstract_type_in_decl,
+ AbstractFieldType))
+ InvalidDecl = true;
+
+ bool ZeroWidth = false;
+ // If this is declared as a bit-field, check the bit-field.
+ if (!InvalidDecl && BitWidth &&
+ VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
+ InvalidDecl = true;
+ BitWidth = 0;
+ ZeroWidth = false;
+ }
+
+ // Check that 'mutable' is consistent with the type of the declaration.
+ if (!InvalidDecl && Mutable) {
+ unsigned DiagID = 0;
+ if (T->isReferenceType())
+ DiagID = diag::err_mutable_reference;
+ else if (T.isConstQualified())
+ DiagID = diag::err_mutable_const;
+
+ if (DiagID) {
+ SourceLocation ErrLoc = Loc;
+ if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid())
+ ErrLoc = D->getDeclSpec().getStorageClassSpecLoc();
+ Diag(ErrLoc, DiagID);
+ Mutable = false;
+ InvalidDecl = true;
+ }
+ }
+
+ FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo,
+ BitWidth, Mutable);
+ if (InvalidDecl)
+ NewFD->setInvalidDecl();
+
+ if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
+ Diag(Loc, diag::err_duplicate_member) << II;
+ Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ }
+
+ if (!InvalidDecl && getLangOptions().CPlusPlus) {
+ if (Record->isUnion()) {
+ if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (RDecl->getDefinition()) {
+ // C++ [class.union]p1: An object of a class with a non-trivial
+ // constructor, a non-trivial copy constructor, a non-trivial
+ // destructor, or a non-trivial copy assignment operator
+ // cannot be a member of a union, nor can an array of such
+ // objects.
+ // TODO: C++0x alters this restriction significantly.
+ if (CheckNontrivialField(NewFD))
+ NewFD->setInvalidDecl();
+ }
+ }
+
+ // C++ [class.union]p1: If a union contains a member of reference type,
+ // the program is ill-formed.
+ if (EltTy->isReferenceType()) {
+ Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type)
+ << NewFD->getDeclName() << EltTy;
+ NewFD->setInvalidDecl();
+ }
+ }
+ }
+
+ // FIXME: We need to pass in the attributes given an AST
+ // representation, not a parser representation.
+ if (D)
+ // FIXME: What to pass instead of TUScope?
+ ProcessDeclAttributes(TUScope, NewFD, *D);
+
+ if (T.isObjCGCWeak())
+ Diag(Loc, diag::warn_attribute_weak_on_field);
+
+ NewFD->setAccess(AS);
+ return NewFD;
+}
+
+bool Sema::CheckNontrivialField(FieldDecl *FD) {
+ assert(FD);
+ assert(getLangOptions().CPlusPlus && "valid check only for C++");
+
+ if (FD->isInvalidDecl())
+ return true;
+
+ QualType EltTy = Context.getBaseElementType(FD->getType());
+ if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (RDecl->getDefinition()) {
+ // We check for copy constructors before constructors
+ // because otherwise we'll never get complaints about
+ // copy constructors.
+
+ CXXSpecialMember member = CXXInvalid;
+ if (!RDecl->hasTrivialCopyConstructor())
+ member = CXXCopyConstructor;
+ else if (!RDecl->hasTrivialConstructor())
+ member = CXXConstructor;
+ else if (!RDecl->hasTrivialCopyAssignment())
+ member = CXXCopyAssignment;
+ else if (!RDecl->hasTrivialDestructor())
+ member = CXXDestructor;
+
+ if (member != CXXInvalid) {
+ Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member)
+ << (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
+ DiagnoseNontrivial(RT, member);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/// DiagnoseNontrivial - Given that a class has a non-trivial
+/// special member, figure out why.
+void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
+ QualType QT(T, 0U);
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl());
+
+ // Check whether the member was user-declared.
+ switch (member) {
+ case CXXInvalid:
+ break;
+
+ case CXXConstructor:
+ if (RD->hasUserDeclaredConstructor()) {
+ typedef CXXRecordDecl::ctor_iterator ctor_iter;
+ for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
+ const FunctionDecl *body = 0;
+ ci->hasBody(body);
+ if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) {
+ SourceLocation CtorLoc = ci->getLocation();
+ Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ }
+
+ assert(0 && "found no user-declared constructors");
+ return;
+ }
+ break;
+
+ case CXXCopyConstructor:
+ if (RD->hasUserDeclaredCopyConstructor()) {
+ SourceLocation CtorLoc =
+ RD->getCopyConstructor(Context, 0)->getLocation();
+ Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+
+ case CXXCopyAssignment:
+ if (RD->hasUserDeclaredCopyAssignment()) {
+ // FIXME: this should use the location of the copy
+ // assignment, not the type.
+ SourceLocation TyLoc = RD->getSourceRange().getBegin();
+ Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+
+ case CXXDestructor:
+ if (RD->hasUserDeclaredDestructor()) {
+ SourceLocation DtorLoc = LookupDestructor(RD)->getLocation();
+ Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+ }
+
+ typedef CXXRecordDecl::base_class_iterator base_iter;
+
+ // Virtual bases and members inhibit trivial copying/construction,
+ // but not trivial destruction.
+ if (member != CXXDestructor) {
+ // Check for virtual bases. vbases includes indirect virtual bases,
+ // so we just iterate through the direct bases.
+ for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi)
+ if (bi->isVirtual()) {
+ SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+ Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1;
+ return;
+ }
+
+ // Check for virtual methods.
+ typedef CXXRecordDecl::method_iterator meth_iter;
+ for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
+ ++mi) {
+ if (mi->isVirtual()) {
+ SourceLocation MLoc = mi->getSourceRange().getBegin();
+ Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
+ return;
+ }
+ }
+ }
+
+ bool (CXXRecordDecl::*hasTrivial)() const;
+ switch (member) {
+ case CXXConstructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break;
+ case CXXCopyConstructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
+ case CXXCopyAssignment:
+ hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
+ case CXXDestructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
+ default:
+ assert(0 && "unexpected special member"); return;
+ }
+
+ // Check for nontrivial bases (and recurse).
+ for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
+ const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
+ assert(BaseRT && "Don't know how to handle dependent bases");
+ CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
+ if (!(BaseRecTy->*hasTrivial)()) {
+ SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+ Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member;
+ DiagnoseNontrivial(BaseRT, member);
+ return;
+ }
+ }
+
+ // Check for nontrivial members (and recurse).
+ typedef RecordDecl::field_iterator field_iter;
+ for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
+ ++fi) {
+ QualType EltTy = Context.getBaseElementType((*fi)->getType());
+ if (const RecordType *EltRT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
+
+ if (!(EltRD->*hasTrivial)()) {
+ SourceLocation FLoc = (*fi)->getLocation();
+ Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member;
+ DiagnoseNontrivial(EltRT, member);
+ return;
+ }
+ }
+ }
+
+ assert(0 && "found no explanation for non-trivial member");
+}
+
+/// TranslateIvarVisibility - Translate visibility from a token ID to an
+/// AST enum value.
+static ObjCIvarDecl::AccessControl
+TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
+ switch (ivarVisibility) {
+ default: assert(0 && "Unknown visitibility kind");
+ case tok::objc_private: return ObjCIvarDecl::Private;
+ case tok::objc_public: return ObjCIvarDecl::Public;
+ case tok::objc_protected: return ObjCIvarDecl::Protected;
+ case tok::objc_package: return ObjCIvarDecl::Package;
+ }
+}
+
+/// ActOnIvar - Each ivar field of an objective-c class is passed into this
+/// in order to create an IvarDecl object for it.
+Decl *Sema::ActOnIvar(Scope *S,
+ SourceLocation DeclStart,
+ Decl *IntfDecl,
+ Declarator &D, ExprTy *BitfieldWidth,
+ tok::ObjCKeywordKind Visibility) {
+
+ IdentifierInfo *II = D.getIdentifier();
+ Expr *BitWidth = (Expr*)BitfieldWidth;
+ SourceLocation Loc = DeclStart;
+ if (II) Loc = D.getIdentifierLoc();
+
+ // FIXME: Unnamed fields can be handled in various different ways, for
+ // example, unnamed unions inject all members into the struct namespace!
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
+
+ if (BitWidth) {
+ // 6.7.2.1p3, 6.7.2.1p4
+ if (VerifyBitField(Loc, II, T, BitWidth)) {
+ D.setInvalidType();
+ BitWidth = 0;
+ }
+ } else {
+ // Not a bitfield.
+
+ // validate II.
+
+ }
+ if (T->isReferenceType()) {
+ Diag(Loc, diag::err_ivar_reference_type);
+ D.setInvalidType();
+ }
+ // C99 6.7.2.1p8: A member of a structure or union may have any type other
+ // than a variably modified type.
+ else if (T->isVariablyModifiedType()) {
+ Diag(Loc, diag::err_typecheck_ivar_variable_size);
+ D.setInvalidType();
+ }
+
+ // Get the visibility (access control) for this ivar.
+ ObjCIvarDecl::AccessControl ac =
+ Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
+ : ObjCIvarDecl::None;
+ // Must set ivar's DeclContext to its enclosing interface.
+ ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl);
+ ObjCContainerDecl *EnclosingContext;
+ if (ObjCImplementationDecl *IMPDecl =
+ dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+ if (!LangOpts.ObjCNonFragileABI2) {
+ // Case of ivar declared in an implementation. Context is that of its class.
+ EnclosingContext = IMPDecl->getClassInterface();
+ assert(EnclosingContext && "Implementation has no class interface!");
+ }
+ else
+ EnclosingContext = EnclosingDecl;
+ } else {
+ if (ObjCCategoryDecl *CDecl =
+ dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+ if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) {
+ Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
+ return 0;
+ }
+ }
+ EnclosingContext = EnclosingDecl;
+ }
+
+ // Construct the decl.
+ ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
+ EnclosingContext, Loc, II, T,
+ TInfo, ac, (Expr *)BitfieldWidth);
+
+ if (II) {
+ NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
+ ForRedeclaration);
+ if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
+ && !isa<TagDecl>(PrevDecl)) {
+ Diag(Loc, diag::err_duplicate_member) << II;
+ Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+ NewID->setInvalidDecl();
+ }
+ }
+
+ // Process attributes attached to the ivar.
+ ProcessDeclAttributes(S, NewID, D);
+
+ if (D.isInvalidType())
+ NewID->setInvalidDecl();
+
+ if (II) {
+ // FIXME: When interfaces are DeclContexts, we'll need to add
+ // these to the interface.
+ S->AddDecl(NewID);
+ IdResolver.AddDecl(NewID);
+ }
+
+ return NewID;
+}
+
+/// ActOnLastBitfield - This routine handles synthesized bitfields rules for
+/// class and class extensions. For every class @interface and class
+/// extension @interface, if the last ivar is a bitfield of any type,
+/// then add an implicit `char :0` ivar to the end of that interface.
+void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls) {
+ if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty())
+ return;
+
+ Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
+ ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
+
+ if (!Ivar->isBitField())
+ return;
+ uint64_t BitFieldSize =
+ Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ if (BitFieldSize == 0)
+ return;
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl);
+ if (!ID) {
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+ if (!CD->IsClassExtension())
+ return;
+ }
+ // No need to add this to end of @implementation.
+ else
+ return;
+ }
+ // All conditions are met. Add a new bitfield to the tail end of ivars.
+ llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0);
+ Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc);
+
+ Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl),
+ DeclLoc, 0,
+ Context.CharTy,
+ Context.CreateTypeSourceInfo(Context.CharTy),
+ ObjCIvarDecl::Private, BW,
+ true);
+ AllIvarDecls.push_back(Ivar);
+}
+
+void Sema::ActOnFields(Scope* S,
+ SourceLocation RecLoc, Decl *EnclosingDecl,
+ Decl **Fields, unsigned NumFields,
+ SourceLocation LBrac, SourceLocation RBrac,
+ AttributeList *Attr) {
+ assert(EnclosingDecl && "missing record or interface decl");
+
+ // If the decl this is being inserted into is invalid, then it may be a
+ // redeclaration or some other bogus case. Don't try to add fields to it.
+ if (EnclosingDecl->isInvalidDecl()) {
+ // FIXME: Deallocate fields?
+ return;
+ }
+
+
+ // Verify that all the fields are okay.
+ unsigned NumNamedMembers = 0;
+ llvm::SmallVector<FieldDecl*, 32> RecFields;
+
+ RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
+ for (unsigned i = 0; i != NumFields; ++i) {
+ FieldDecl *FD = cast<FieldDecl>(Fields[i]);
+
+ // Get the type for the field.
+ const Type *FDTy = FD->getType().getTypePtr();
+
+ if (!FD->isAnonymousStructOrUnion()) {
+ // Remember all fields written by the user.
+ RecFields.push_back(FD);
+ }
+
+ // If the field is already invalid for some reason, don't emit more
+ // diagnostics about it.
+ if (FD->isInvalidDecl()) {
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ }
+
+ // C99 6.7.2.1p2:
+ // A structure or union shall not contain a member with
+ // incomplete or function type (hence, a structure shall not
+ // contain an instance of itself, but may contain a pointer to
+ // an instance of itself), except that the last member of a
+ // structure with more than one named member may have incomplete
+ // array type; such a structure (and any union containing,
+ // possibly recursively, a member that is such a structure)
+ // shall not be a member of a structure or an element of an
+ // array.
+ if (FDTy->isFunctionType()) {
+ // Field declared as a function.
+ Diag(FD->getLocation(), diag::err_field_declared_as_function)
+ << FD->getDeclName();
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ } else if (FDTy->isIncompleteArrayType() && Record &&
+ ((i == NumFields - 1 && !Record->isUnion()) ||
+ (getLangOptions().Microsoft &&
+ (i == NumFields - 1 || Record->isUnion())))) {
+ // Flexible array member.
+ // Microsoft is more permissive regarding flexible array.
+ // It will accept flexible array in union and also
+ // as the sole element of a struct/class.
+ if (getLangOptions().Microsoft) {
+ if (Record->isUnion())
+ Diag(FD->getLocation(), diag::ext_flexible_array_union)
+ << FD->getDeclName();
+ else if (NumFields == 1)
+ Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate)
+ << FD->getDeclName() << Record->getTagKind();
+ } else if (NumNamedMembers < 1) {
+ Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
+ << FD->getDeclName();
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ }
+ if (!FD->getType()->isDependentType() &&
+ !Context.getBaseElementType(FD->getType())->isPODType()) {
+ Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type)
+ << FD->getDeclName() << FD->getType();
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ }
+ // Okay, we have a legal flexible array member at the end of the struct.
+ if (Record)
+ Record->setHasFlexibleArrayMember(true);
+ } else if (!FDTy->isDependentType() &&
+ RequireCompleteType(FD->getLocation(), FD->getType(),
+ diag::err_field_incomplete)) {
+ // Incomplete type
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
+ if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+ // If this is a member of a union, then entire union becomes "flexible".
+ if (Record && Record->isUnion()) {
+ Record->setHasFlexibleArrayMember(true);
+ } else {
+ // If this is a struct/class and this is not the last element, reject
+ // it. Note that GCC supports variable sized arrays in the middle of
+ // structures.
+ if (i != NumFields-1)
+ Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct)
+ << FD->getDeclName() << FD->getType();
+ else {
+ // We support flexible arrays at the end of structs in
+ // other structs as an extension.
+ Diag(FD->getLocation(), diag::ext_flexible_array_in_struct)
+ << FD->getDeclName();
+ if (Record)
+ Record->setHasFlexibleArrayMember(true);
+ }
+ }
+ }
+ if (Record && FDTTy->getDecl()->hasObjectMember())
+ Record->setHasObjectMember(true);
+ } else if (FDTy->isObjCObjectType()) {
+ /// A field cannot be an Objective-c object
+ Diag(FD->getLocation(), diag::err_statically_allocated_object);
+ FD->setInvalidDecl();
+ EnclosingDecl->setInvalidDecl();
+ continue;
+ } else if (getLangOptions().ObjC1 &&
+ getLangOptions().getGCMode() != LangOptions::NonGC &&
+ Record &&
+ (FD->getType()->isObjCObjectPointerType() ||
+ FD->getType().isObjCGCStrong()))
+ Record->setHasObjectMember(true);
+ else if (Context.getAsArrayType(FD->getType())) {
+ QualType BaseType = Context.getBaseElementType(FD->getType());
+ if (Record && BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
+ Record->setHasObjectMember(true);
+ }
+ // Keep track of the number of named members.
+ if (FD->getIdentifier())
+ ++NumNamedMembers;
+ }
+
+ // Okay, we successfully defined 'Record'.
+ if (Record) {
+ bool Completed = false;
+ if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
+ if (!CXXRecord->isInvalidDecl()) {
+ // Set access bits correctly on the directly-declared conversions.
+ UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions();
+ for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end();
+ I != E; ++I)
+ Convs->setAccess(I, (*I)->getAccess());
+
+ if (!CXXRecord->isDependentType()) {
+ // Add any implicitly-declared members to this class.
+ AddImplicitlyDeclaredMembersToClass(CXXRecord);
+
+ // If we have virtual base classes, we may end up finding multiple
+ // final overriders for a given virtual function. Check for this
+ // problem now.
+ if (CXXRecord->getNumVBases()) {
+ CXXFinalOverriderMap FinalOverriders;
+ CXXRecord->getFinalOverriders(FinalOverriders);
+
+ for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
+ MEnd = FinalOverriders.end();
+ M != MEnd; ++M) {
+ for (OverridingMethods::iterator SO = M->second.begin(),
+ SOEnd = M->second.end();
+ SO != SOEnd; ++SO) {
+ assert(SO->second.size() > 0 &&
+ "Virtual function without overridding functions?");
+ if (SO->second.size() == 1)
+ continue;
+
+ // C++ [class.virtual]p2:
+ // In a derived class, if a virtual member function of a base
+ // class subobject has more than one final overrider the
+ // program is ill-formed.
+ Diag(Record->getLocation(), diag::err_multiple_final_overriders)
+ << (NamedDecl *)M->first << Record;
+ Diag(M->first->getLocation(),
+ diag::note_overridden_virtual_function);
+ for (OverridingMethods::overriding_iterator
+ OM = SO->second.begin(),
+ OMEnd = SO->second.end();
+ OM != OMEnd; ++OM)
+ Diag(OM->Method->getLocation(), diag::note_final_overrider)
+ << (NamedDecl *)M->first << OM->Method->getParent();
+
+ Record->setInvalidDecl();
+ }
+ }
+ CXXRecord->completeDefinition(&FinalOverriders);
+ Completed = true;
+ }
+ }
+ }
+ }
+
+ if (!Completed)
+ Record->completeDefinition();
+ } else {
+ ObjCIvarDecl **ClsFields =
+ reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
+ ID->setLocEnd(RBrac);
+ // Add ivar's to class's DeclContext.
+ for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+ ClsFields[i]->setLexicalDeclContext(ID);
+ ID->addDecl(ClsFields[i]);
+ }
+ // Must enforce the rule that ivars in the base classes may not be
+ // duplicates.
+ if (ID->getSuperClass())
+ DiagnoseDuplicateIvars(ID, ID->getSuperClass());
+ } else if (ObjCImplementationDecl *IMPDecl =
+ dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+ assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
+ for (unsigned I = 0, N = RecFields.size(); I != N; ++I)
+ // Ivar declared in @implementation never belongs to the implementation.
+ // Only it is in implementation's lexical context.
+ ClsFields[I]->setLexicalDeclContext(IMPDecl);
+ CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
+ } else if (ObjCCategoryDecl *CDecl =
+ dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+ // case of ivars in class extension; all other cases have been
+ // reported as errors elsewhere.
+ // FIXME. Class extension does not have a LocEnd field.
+ // CDecl->setLocEnd(RBrac);
+ // Add ivar's to class extension's DeclContext.
+ for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
+ ClsFields[i]->setLexicalDeclContext(CDecl);
+ CDecl->addDecl(ClsFields[i]);
+ }
+ }
+ }
+
+ if (Attr)
+ ProcessDeclAttributeList(S, Record, Attr);
+
+ // If there's a #pragma GCC visibility in scope, and this isn't a subclass,
+ // set the visibility of this record.
+ if (Record && !Record->getDeclContext()->isRecord())
+ AddPushedVisibilityAttribute(Record);
+}
+
+/// \brief Determine whether the given integral value is representable within
+/// the given type T.
+static bool isRepresentableIntegerValue(ASTContext &Context,
+ llvm::APSInt &Value,
+ QualType T) {
+ assert(T->isIntegralType(Context) && "Integral type required!");
+ unsigned BitWidth = Context.getIntWidth(T);
+
+ if (Value.isUnsigned() || Value.isNonNegative()) {
+ if (T->isSignedIntegerType())
+ --BitWidth;
+ return Value.getActiveBits() <= BitWidth;
+ }
+ return Value.getMinSignedBits() <= BitWidth;
+}
+
+// \brief Given an integral type, return the next larger integral type
+// (or a NULL type of no such type exists).
+static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
+ // FIXME: Int128/UInt128 support, which also needs to be introduced into
+ // enum checking below.
+ assert(T->isIntegralType(Context) && "Integral type required!");
+ const unsigned NumTypes = 4;
+ QualType SignedIntegralTypes[NumTypes] = {
+ Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
+ };
+ QualType UnsignedIntegralTypes[NumTypes] = {
+ Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy,
+ Context.UnsignedLongLongTy
+ };
+
+ unsigned BitWidth = Context.getTypeSize(T);
+ QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes
+ : UnsignedIntegralTypes;
+ for (unsigned I = 0; I != NumTypes; ++I)
+ if (Context.getTypeSize(Types[I]) > BitWidth)
+ return Types[I];
+
+ return QualType();
+}
+
+EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ Expr *Val) {
+ unsigned IntWidth = Context.Target.getIntWidth();
+ llvm::APSInt EnumVal(IntWidth);
+ QualType EltTy;
+
+ if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue))
+ Val = 0;
+
+ if (Val) {
+ if (Enum->isDependentType() || Val->isTypeDependent())
+ EltTy = Context.DependentTy;
+ else {
+ // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+ SourceLocation ExpLoc;
+ if (!Val->isValueDependent() &&
+ VerifyIntegerConstantExpression(Val, &EnumVal)) {
+ Val = 0;
+ } else {
+ if (!getLangOptions().CPlusPlus) {
+ // C99 6.7.2.2p2:
+ // The expression that defines the value of an enumeration constant
+ // shall be an integer constant expression that has a value
+ // representable as an int.
+
+ // Complain if the value is not representable in an int.
+ if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
+ Diag(IdLoc, diag::ext_enum_value_not_int)
+ << EnumVal.toString(10) << Val->getSourceRange()
+ << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
+ else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
+ // Force the type of the expression to 'int'.
+ ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast);
+ }
+ }
+
+ if (Enum->isFixed()) {
+ EltTy = Enum->getIntegerType();
+
+ // C++0x [dcl.enum]p5:
+ // ... if the initializing value of an enumerator cannot be
+ // represented by the underlying type, the program is ill-formed.
+ if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+ if (getLangOptions().Microsoft) {
+ Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
+ ImpCastExprToType(Val, EltTy, CK_IntegralCast);
+ } else
+ Diag(IdLoc, diag::err_enumerator_too_large)
+ << EltTy;
+ } else
+ ImpCastExprToType(Val, EltTy, CK_IntegralCast);
+ }
+ else {
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ // - If an initializer is specified for an enumerator, the
+ // initializing value has the same type as the expression.
+ EltTy = Val->getType();
+ }
+ }
+ }
+ }
+
+ if (!Val) {
+ if (Enum->isDependentType())
+ EltTy = Context.DependentTy;
+ else if (!LastEnumConst) {
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ // - If no initializer is specified for the first enumerator, the
+ // initializing value has an unspecified integral type.
+ //
+ // GCC uses 'int' for its unspecified integral type, as does
+ // C99 6.7.2.2p3.
+ if (Enum->isFixed()) {
+ EltTy = Enum->getIntegerType();
+ }
+ else {
+ EltTy = Context.IntTy;
+ }
+ } else {
+ // Assign the last value + 1.
+ EnumVal = LastEnumConst->getInitVal();
+ ++EnumVal;
+ EltTy = LastEnumConst->getType();
+
+ // Check for overflow on increment.
+ if (EnumVal < LastEnumConst->getInitVal()) {
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ //
+ // - Otherwise the type of the initializing value is the same as
+ // the type of the initializing value of the preceding enumerator
+ // unless the incremented value is not representable in that type,
+ // in which case the type is an unspecified integral type
+ // sufficient to contain the incremented value. If no such type
+ // exists, the program is ill-formed.
+ QualType T = getNextLargerIntegralType(Context, EltTy);
+ if (T.isNull() || Enum->isFixed()) {
+ // There is no integral type larger enough to represent this
+ // value. Complain, then allow the value to wrap around.
+ EnumVal = LastEnumConst->getInitVal();
+ EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2);
+ ++EnumVal;
+ if (Enum->isFixed())
+ // When the underlying type is fixed, this is ill-formed.
+ Diag(IdLoc, diag::err_enumerator_wrapped)
+ << EnumVal.toString(10)
+ << EltTy;
+ else
+ Diag(IdLoc, diag::warn_enumerator_too_large)
+ << EnumVal.toString(10);
+ } else {
+ EltTy = T;
+ }
+
+ // Retrieve the last enumerator's value, extent that type to the
+ // type that is supposed to be large enough to represent the incremented
+ // value, then increment.
+ EnumVal = LastEnumConst->getInitVal();
+ EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+ EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
+ ++EnumVal;
+
+ // If we're not in C++, diagnose the overflow of enumerator values,
+ // which in C99 means that the enumerator value is not representable in
+ // an int (C99 6.7.2.2p2). However, we support GCC's extension that
+ // permits enumerator values that are representable in some larger
+ // integral type.
+ if (!getLangOptions().CPlusPlus && !T.isNull())
+ Diag(IdLoc, diag::warn_enum_value_overflow);
+ } else if (!getLangOptions().CPlusPlus &&
+ !isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+ // Enforce C99 6.7.2.2p2 even when we compute the next value.
+ Diag(IdLoc, diag::ext_enum_value_not_int)
+ << EnumVal.toString(10) << 1;
+ }
+ }
+ }
+
+ if (!EltTy->isDependentType()) {
+ // Make the enumerator value match the signedness and size of the
+ // enumerator's type.
+ EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy));
+ EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+ }
+
+ return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
+ Val, EnumVal);
+}
+
+
+Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ AttributeList *Attr,
+ SourceLocation EqualLoc, ExprTy *val) {
+ EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
+ EnumConstantDecl *LastEnumConst =
+ cast_or_null<EnumConstantDecl>(lastEnumConst);
+ Expr *Val = static_cast<Expr*>(val);
+
+ // The scope passed in may not be a decl scope. Zip up the scope tree until
+ // we find one that is.
+ S = getNonFieldDeclScope(S);
+
+ // Verify that there isn't already something declared with this name in this
+ // scope.
+ NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
+ if (PrevDecl) {
+ // When in C++, we may get a TagDecl with the same name; in this case the
+ // enum constant will 'hide' the tag.
+ assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
+ "Received TagDecl when not in C++!");
+ if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
+ if (isa<EnumConstantDecl>(PrevDecl))
+ Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
+ else
+ Diag(IdLoc, diag::err_redefinition) << Id;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ return 0;
+ }
+ }
+
+ // C++ [class.mem]p13:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // - every enumerator of every member of class T that is an enumerated
+ // type
+ if (CXXRecordDecl *Record
+ = dyn_cast<CXXRecordDecl>(
+ TheEnumDecl->getDeclContext()->getRedeclContext()))
+ if (Record->getIdentifier() && Record->getIdentifier() == Id)
+ Diag(IdLoc, diag::err_member_name_of_class) << Id;
+
+ EnumConstantDecl *New =
+ CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
+
+ if (New) {
+ // Process attributes.
+ if (Attr) ProcessDeclAttributeList(S, New, Attr);
+
+ // Register this decl in the current scope stack.
+ New->setAccess(TheEnumDecl->getAccess());
+ PushOnScopeChains(New, S);
+ }
+
+ return New;
+}
+
+void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc, Decl *EnumDeclX,
+ Decl **Elements, unsigned NumElements,
+ Scope *S, AttributeList *Attr) {
+ EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
+ QualType EnumType = Context.getTypeDeclType(Enum);
+
+ if (Attr)
+ ProcessDeclAttributeList(S, Enum, Attr);
+
+ if (Enum->isDependentType()) {
+ for (unsigned i = 0; i != NumElements; ++i) {
+ EnumConstantDecl *ECD =
+ cast_or_null<EnumConstantDecl>(Elements[i]);
+ if (!ECD) continue;
+
+ ECD->setType(EnumType);
+ }
+
+ Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0);
+ return;
+ }
+
+ // TODO: If the result value doesn't fit in an int, it must be a long or long
+ // long value. ISO C does not support this, but GCC does as an extension,
+ // emit a warning.
+ unsigned IntWidth = Context.Target.getIntWidth();
+ unsigned CharWidth = Context.Target.getCharWidth();
+ unsigned ShortWidth = Context.Target.getShortWidth();
+
+ // Verify that all the values are okay, compute the size of the values, and
+ // reverse the list.
+ unsigned NumNegativeBits = 0;
+ unsigned NumPositiveBits = 0;
+
+ // Keep track of whether all elements have type int.
+ bool AllElementsInt = true;
+
+ for (unsigned i = 0; i != NumElements; ++i) {
+ EnumConstantDecl *ECD =
+ cast_or_null<EnumConstantDecl>(Elements[i]);
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ const llvm::APSInt &InitVal = ECD->getInitVal();
+
+ // Keep track of the size of positive and negative values.
+ if (InitVal.isUnsigned() || InitVal.isNonNegative())
+ NumPositiveBits = std::max(NumPositiveBits,
+ (unsigned)InitVal.getActiveBits());
+ else
+ NumNegativeBits = std::max(NumNegativeBits,
+ (unsigned)InitVal.getMinSignedBits());
+
+ // Keep track of whether every enum element has type int (very commmon).
+ if (AllElementsInt)
+ AllElementsInt = ECD->getType() == Context.IntTy;
+ }
+
+ // Figure out the type that should be used for this enum.
+ QualType BestType;
+ unsigned BestWidth;
+
+ // C++0x N3000 [conv.prom]p3:
+ // An rvalue of an unscoped enumeration type whose underlying
+ // type is not fixed can be converted to an rvalue of the first
+ // of the following types that can represent all the values of
+ // the enumeration: int, unsigned int, long int, unsigned long
+ // int, long long int, or unsigned long long int.
+ // C99 6.4.4.3p2:
+ // An identifier declared as an enumeration constant has type int.
+ // The C99 rule is modified by a gcc extension
+ QualType BestPromotionType;
+
+ bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+ // -fshort-enums is the equivalent to specifying the packed attribute on all
+ // enum definitions.
+ if (LangOpts.ShortEnums)
+ Packed = true;
+
+ if (Enum->isFixed()) {
+ BestType = BestPromotionType = Enum->getIntegerType();
+ // We don't need to set BestWidth, because BestType is going to be the type
+ // of the enumerators, but we do anyway because otherwise some compilers
+ // warn that it might be used uninitialized.
+ BestWidth = CharWidth;
+ }
+ else if (NumNegativeBits) {
+ // If there is a negative value, figure out the smallest integer type (of
+ // int/long/longlong) that fits.
+ // If it's packed, check also if it fits a char or a short.
+ if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
+ BestType = Context.SignedCharTy;
+ BestWidth = CharWidth;
+ } else if (Packed && NumNegativeBits <= ShortWidth &&
+ NumPositiveBits < ShortWidth) {
+ BestType = Context.ShortTy;
+ BestWidth = ShortWidth;
+ } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+ BestType = Context.IntTy;
+ BestWidth = IntWidth;
+ } else {
+ BestWidth = Context.Target.getLongWidth();
+
+ if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
+ BestType = Context.LongTy;
+ } else {
+ BestWidth = Context.Target.getLongLongWidth();
+
+ if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
+ Diag(Enum->getLocation(), diag::warn_enum_too_large);
+ BestType = Context.LongLongTy;
+ }
+ }
+ BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
+ } else {
+ // If there is no negative value, figure out the smallest type that fits
+ // all of the enumerator values.
+ // If it's packed, check also if it fits a char or a short.
+ if (Packed && NumPositiveBits <= CharWidth) {
+ BestType = Context.UnsignedCharTy;
+ BestPromotionType = Context.IntTy;
+ BestWidth = CharWidth;
+ } else if (Packed && NumPositiveBits <= ShortWidth) {
+ BestType = Context.UnsignedShortTy;
+ BestPromotionType = Context.IntTy;
+ BestWidth = ShortWidth;
+ } else if (NumPositiveBits <= IntWidth) {
+ BestType = Context.UnsignedIntTy;
+ BestWidth = IntWidth;
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedIntTy : Context.IntTy;
+ } else if (NumPositiveBits <=
+ (BestWidth = Context.Target.getLongWidth())) {
+ BestType = Context.UnsignedLongTy;
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedLongTy : Context.LongTy;
+ } else {
+ BestWidth = Context.Target.getLongLongWidth();
+ assert(NumPositiveBits <= BestWidth &&
+ "How could an initializer get larger than ULL?");
+ BestType = Context.UnsignedLongLongTy;
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedLongLongTy : Context.LongLongTy;
+ }
+ }
+
+ // Loop over all of the enumerator constants, changing their types to match
+ // the type of the enum if needed.
+ for (unsigned i = 0; i != NumElements; ++i) {
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ // Standard C says the enumerators have int type, but we allow, as an
+ // extension, the enumerators to be larger than int size. If each
+ // enumerator value fits in an int, type it as an int, otherwise type it the
+ // same as the enumerator decl itself. This means that in "enum { X = 1U }"
+ // that X has type 'int', not 'unsigned'.
+
+ // Determine whether the value fits into an int.
+ llvm::APSInt InitVal = ECD->getInitVal();
+
+ // If it fits into an integer type, force it. Otherwise force it to match
+ // the enum decl type.
+ QualType NewTy;
+ unsigned NewWidth;
+ bool NewSign;
+ if (!getLangOptions().CPlusPlus &&
+ isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
+ NewTy = Context.IntTy;
+ NewWidth = IntWidth;
+ NewSign = true;
+ } else if (ECD->getType() == BestType) {
+ // Already the right type!
+ if (getLangOptions().CPlusPlus)
+ // C++ [dcl.enum]p4: Following the closing brace of an
+ // enum-specifier, each enumerator has the type of its
+ // enumeration.
+ ECD->setType(EnumType);
+ continue;
+ } else {
+ NewTy = BestType;
+ NewWidth = BestWidth;
+ NewSign = BestType->isSignedIntegerType();
+ }
+
+ // Adjust the APSInt value.
+ InitVal = InitVal.extOrTrunc(NewWidth);
+ InitVal.setIsSigned(NewSign);
+ ECD->setInitVal(InitVal);
+
+ // Adjust the Expr initializer and type.
+ if (ECD->getInitExpr() &&
+ !Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
+ ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
+ CK_IntegralCast,
+ ECD->getInitExpr(),
+ /*base paths*/ 0,
+ VK_RValue));
+ if (getLangOptions().CPlusPlus)
+ // C++ [dcl.enum]p4: Following the closing brace of an
+ // enum-specifier, each enumerator has the type of its
+ // enumeration.
+ ECD->setType(EnumType);
+ else
+ ECD->setType(NewTy);
+ }
+
+ Enum->completeDefinition(BestType, BestPromotionType,
+ NumPositiveBits, NumNegativeBits);
+}
+
+Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) {
+ StringLiteral *AsmString = cast<StringLiteral>(expr);
+
+ FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
+ Loc, AsmString);
+ CurContext->addDecl(New);
+ return New;
+}
+
+void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
+ SourceLocation PragmaLoc,
+ SourceLocation NameLoc) {
+ Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
+
+ if (PrevDecl) {
+ PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
+ } else {
+ (void)WeakUndeclaredIdentifiers.insert(
+ std::pair<IdentifierInfo*,WeakInfo>
+ (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
+ }
+}
+
+void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
+ IdentifierInfo* AliasName,
+ SourceLocation PragmaLoc,
+ SourceLocation NameLoc,
+ SourceLocation AliasNameLoc) {
+ Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc,
+ LookupOrdinaryName);
+ WeakInfo W = WeakInfo(Name, NameLoc);
+
+ if (PrevDecl) {
+ if (!PrevDecl->hasAttr<AliasAttr>())
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
+ DeclApplyPragmaWeak(TUScope, ND, W);
+ } else {
+ (void)WeakUndeclaredIdentifiers.insert(
+ std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
new file mode 100644
index 0000000..cbc940f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -0,0 +1,3044 @@
+//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements decl-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+//===----------------------------------------------------------------------===//
+// Helper functions
+//===----------------------------------------------------------------------===//
+
+static const FunctionType *getFunctionType(const Decl *d,
+ bool blocksToo = true) {
+ QualType Ty;
+ if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
+ Ty = decl->getType();
+ else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
+ Ty = decl->getType();
+ else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
+ Ty = decl->getUnderlyingType();
+ else
+ return 0;
+
+ if (Ty->isFunctionPointerType())
+ Ty = Ty->getAs<PointerType>()->getPointeeType();
+ else if (blocksToo && Ty->isBlockPointerType())
+ Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
+
+ return Ty->getAs<FunctionType>();
+}
+
+// FIXME: We should provide an abstraction around a method or function
+// to provide the following bits of information.
+
+/// isFunction - Return true if the given decl has function
+/// type (function or function-typed variable).
+static bool isFunction(const Decl *d) {
+ return getFunctionType(d, false) != NULL;
+}
+
+/// isFunctionOrMethod - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method.
+static bool isFunctionOrMethod(const Decl *d) {
+ return isFunction(d)|| isa<ObjCMethodDecl>(d);
+}
+
+/// isFunctionOrMethodOrBlock - Return true if the given decl has function
+/// type (function or function-typed variable) or an Objective-C
+/// method or a block.
+static bool isFunctionOrMethodOrBlock(const Decl *d) {
+ if (isFunctionOrMethod(d))
+ return true;
+ // check for block is more involved.
+ if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
+ QualType Ty = V->getType();
+ return Ty->isBlockPointerType();
+ }
+ return isa<BlockDecl>(d);
+}
+
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+static bool hasDeclarator(const Decl *d) {
+ // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+ return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefDecl>(d);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
+static bool hasFunctionProto(const Decl *d) {
+ if (const FunctionType *FnTy = getFunctionType(d))
+ return isa<FunctionProtoType>(FnTy);
+ else {
+ assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d));
+ return true;
+ }
+}
+
+/// getFunctionOrMethodNumArgs - Return number of function or method
+/// arguments. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
+ if (const FunctionType *FnTy = getFunctionType(d))
+ return cast<FunctionProtoType>(FnTy)->getNumArgs();
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+ return BD->getNumParams();
+ return cast<ObjCMethodDecl>(d)->param_size();
+}
+
+static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
+ if (const FunctionType *FnTy = getFunctionType(d))
+ return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+ return BD->getParamDecl(Idx)->getType();
+
+ return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
+}
+
+static QualType getFunctionOrMethodResultType(const Decl *d) {
+ if (const FunctionType *FnTy = getFunctionType(d))
+ return cast<FunctionProtoType>(FnTy)->getResultType();
+ return cast<ObjCMethodDecl>(d)->getResultType();
+}
+
+static bool isFunctionOrMethodVariadic(const Decl *d) {
+ if (const FunctionType *FnTy = getFunctionType(d)) {
+ const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
+ return proto->isVariadic();
+ } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
+ return BD->isVariadic();
+ else {
+ return cast<ObjCMethodDecl>(d)->isVariadic();
+ }
+}
+
+static bool isInstanceMethod(const Decl *d) {
+ if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(d))
+ return MethodDecl->isInstance();
+ return false;
+}
+
+static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+ const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+ if (!PT)
+ return false;
+
+ ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
+ if (!Cls)
+ return false;
+
+ IdentifierInfo* ClsName = Cls->getIdentifier();
+
+ // FIXME: Should we walk the chain of classes?
+ return ClsName == &Ctx.Idents.get("NSString") ||
+ ClsName == &Ctx.Idents.get("NSMutableString");
+}
+
+static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
+ const PointerType *PT = T->getAs<PointerType>();
+ if (!PT)
+ return false;
+
+ const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ const RecordDecl *RD = RT->getDecl();
+ if (RD->getTagKind() != TTK_Struct)
+ return false;
+
+ return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute Implementations
+//===----------------------------------------------------------------------===//
+
+// FIXME: All this manual attribute parsing code is gross. At the
+// least add some helper functions to check most argument patterns (#
+// and types of args).
+
+static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
+ const AttributeList &Attr, Sema &S) {
+ TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
+ if (tDecl == 0) {
+ S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
+ return;
+ }
+
+ QualType curType = tDecl->getUnderlyingType();
+
+ Expr *sizeExpr;
+
+ // Special case where the argument is a template id.
+ if (Attr.getParameterName()) {
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+ sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
+ } else {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ sizeExpr = Attr.getArg(0);
+ }
+
+ // Instantiate/Install the vector type, and let Sema build the type for us.
+ // This will run the reguired checks.
+ QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
+ if (!T.isNull()) {
+ // FIXME: preserve the old source info.
+ tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
+
+ // Remember this typedef decl, we will need it later for diagnostics.
+ S.ExtVectorDecls.push_back(tDecl);
+ }
+}
+
+static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (TagDecl *TD = dyn_cast<TagDecl>(d))
+ TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
+ else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
+ // If the alignment is less than or equal to 8 bits, the packed attribute
+ // has no effect.
+ if (!FD->getType()->isIncompleteType() &&
+ S.Context.getTypeAlign(FD->getType()) <= 8)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
+ << Attr.getName() << FD->getType();
+ else
+ FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
+ } else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+}
+
+static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // The IBAction attributes only apply to instance methods.
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
+ if (MD->isInstanceMethod()) {
+ d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
+ return;
+ }
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
+}
+
+static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // The IBOutlet attributes only apply to instance variables of
+ // Objective-C classes.
+ if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
+ d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
+ return;
+ }
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
+}
+
+static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+
+ // The iboutletcollection attribute can have zero or one arguments.
+ if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // The IBOutletCollection attributes only apply to instance variables of
+ // Objective-C classes.
+ if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
+ return;
+ }
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(d))
+ if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
+ << VD->getType() << 0;
+ return;
+ }
+ if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d))
+ if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
+ << PD->getType() << 1;
+ return;
+ }
+
+ IdentifierInfo *II = Attr.getParameterName();
+ if (!II)
+ II = &S.Context.Idents.get("id");
+
+ ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),
+ S.getScopeForContext(d->getDeclContext()->getParent()));
+ if (!TypeRep) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+ return;
+ }
+ QualType QT = TypeRep.get();
+ // Diagnose use of non-object type in iboutletcollection attribute.
+ // FIXME. Gnu attribute extension ignores use of builtin types in
+ // attributes. So, __attribute__((iboutletcollection(char))) will be
+ // treated as __attribute__((iboutletcollection())).
+ if (!QT->isObjCIdType() && !QT->isObjCClassType() &&
+ !QT->isObjCObjectType()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+ return;
+ }
+ d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
+ QT));
+}
+
+static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // GCC ignores the nonnull attribute on K&R style function prototypes, so we
+ // ignore it as well
+ if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ // In C++ the implicit 'this' function parameter also counts, and they are
+ // counted from one.
+ bool HasImplicitThisParam = isInstanceMethod(d);
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
+
+ // The nonnull attribute only applies to pointers.
+ llvm::SmallVector<unsigned, 10> NonNullArgs;
+
+ for (AttributeList::arg_iterator I=Attr.arg_begin(),
+ E=Attr.arg_end(); I!=E; ++I) {
+
+
+ // The argument must be an integer constant expression.
+ Expr *Ex = *I;
+ llvm::APSInt ArgNum(32);
+ if (Ex->isTypeDependent() || Ex->isValueDependent() ||
+ !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "nonnull" << Ex->getSourceRange();
+ return;
+ }
+
+ unsigned x = (unsigned) ArgNum.getZExtValue();
+
+ if (x < 1 || x > NumArgs) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "nonnull" << I.getArgNum() << Ex->getSourceRange();
+ return;
+ }
+
+ --x;
+ if (HasImplicitThisParam) {
+ if (x == 0) {
+ S.Diag(Attr.getLoc(),
+ diag::err_attribute_invalid_implicit_this_argument)
+ << "nonnull" << Ex->getSourceRange();
+ return;
+ }
+ --x;
+ }
+
+ // Is the function argument a pointer type?
+ QualType T = getFunctionOrMethodArgType(d, x).getNonReferenceType();
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ // FIXME: Should also highlight argument in decl.
+ S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
+ << "nonnull" << Ex->getSourceRange();
+ continue;
+ }
+
+ NonNullArgs.push_back(x);
+ }
+
+ // If no arguments were specified to __attribute__((nonnull)) then all pointer
+ // arguments have a nonnull attribute.
+ if (NonNullArgs.empty()) {
+ for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
+ QualType T = getFunctionOrMethodArgType(d, I).getNonReferenceType();
+ if (T->isAnyPointerType() || T->isBlockPointerType())
+ NonNullArgs.push_back(I);
+ else if (const RecordType *UT = T->getAsUnionType()) {
+ if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
+ RecordDecl *UD = UT->getDecl();
+ for (RecordDecl::field_iterator it = UD->field_begin(),
+ itend = UD->field_end(); it != itend; ++it) {
+ T = it->getType();
+ if (T->isAnyPointerType() || T->isBlockPointerType()) {
+ NonNullArgs.push_back(I);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // No pointer arguments?
+ if (NonNullArgs.empty()) {
+ // Warn the trivial case only if attribute is not coming from a
+ // macro instantiation.
+ if (Attr.getLoc().isFileID())
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+ return;
+ }
+ }
+
+ unsigned* start = &NonNullArgs[0];
+ unsigned size = NonNullArgs.size();
+ llvm::array_pod_sort(start, start + size);
+ d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
+ size));
+}
+
+static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
+ // This attribute must be applied to a function declaration.
+ // The first argument to the attribute must be a string,
+ // the name of the resource, for example "malloc".
+ // The following arguments must be argument indexes, the arguments must be
+ // of integer type for Returns, otherwise of pointer type.
+ // The difference between Holds and Takes is that a pointer may still be used
+ // after being held. free() should be __attribute((ownership_takes)), whereas
+ // a list append function may well be __attribute((ownership_holds)).
+
+ if (!AL.getParameterName()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
+ << AL.getName()->getName() << 1;
+ return;
+ }
+ // Figure out our Kind, and check arguments while we're at it.
+ OwnershipAttr::OwnershipKind K;
+ switch (AL.getKind()) {
+ case AttributeList::AT_ownership_takes:
+ K = OwnershipAttr::Takes;
+ if (AL.getNumArgs() < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+ break;
+ case AttributeList::AT_ownership_holds:
+ K = OwnershipAttr::Holds;
+ if (AL.getNumArgs() < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+ break;
+ case AttributeList::AT_ownership_returns:
+ K = OwnershipAttr::Returns;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getNumArgs() + 1;
+ return;
+ }
+ break;
+ default:
+ // This should never happen given how we are called.
+ llvm_unreachable("Unknown ownership attribute");
+ }
+
+ if (!isFunction(d) || !hasFunctionProto(d)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName()
+ << 0 /*function*/;
+ return;
+ }
+
+ // In C++ the implicit 'this' function parameter also counts, and they are
+ // counted from one.
+ bool HasImplicitThisParam = isInstanceMethod(d);
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
+
+ llvm::StringRef Module = AL.getParameterName()->getName();
+
+ // Normalize the argument, __foo__ becomes foo.
+ if (Module.startswith("__") && Module.endswith("__"))
+ Module = Module.substr(2, Module.size() - 4);
+
+ llvm::SmallVector<unsigned, 10> OwnershipArgs;
+
+ for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
+ ++I) {
+
+ Expr *IdxExpr = *I;
+ llvm::APSInt ArgNum(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+ || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
+ << AL.getName()->getName() << IdxExpr->getSourceRange();
+ continue;
+ }
+
+ unsigned x = (unsigned) ArgNum.getZExtValue();
+
+ if (x > NumArgs || x < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName()->getName() << x << IdxExpr->getSourceRange();
+ continue;
+ }
+ --x;
+ if (HasImplicitThisParam) {
+ if (x == 0) {
+ S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
+ << "ownership" << IdxExpr->getSourceRange();
+ return;
+ }
+ --x;
+ }
+
+ switch (K) {
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds: {
+ // Is the function argument a pointer type?
+ QualType T = getFunctionOrMethodArgType(d, x);
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ // FIXME: Should also highlight argument in decl.
+ S.Diag(AL.getLoc(), diag::err_ownership_type)
+ << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
+ << "pointer"
+ << IdxExpr->getSourceRange();
+ continue;
+ }
+ break;
+ }
+ case OwnershipAttr::Returns: {
+ if (AL.getNumArgs() > 1) {
+ // Is the function argument an integer type?
+ Expr *IdxExpr = AL.getArg(0);
+ llvm::APSInt ArgNum(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+ || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(AL.getLoc(), diag::err_ownership_type)
+ << "ownership_returns" << "integer"
+ << IdxExpr->getSourceRange();
+ return;
+ }
+ }
+ break;
+ }
+ default:
+ llvm_unreachable("Unknown ownership attribute");
+ } // switch
+
+ // Check we don't have a conflict with another ownership attribute.
+ for (specific_attr_iterator<OwnershipAttr>
+ i = d->specific_attr_begin<OwnershipAttr>(),
+ e = d->specific_attr_end<OwnershipAttr>();
+ i != e; ++i) {
+ if ((*i)->getOwnKind() != K) {
+ for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
+ I!=E; ++I) {
+ if (x == *I) {
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL.getName()->getName() << "ownership_*";
+ }
+ }
+ }
+ }
+ OwnershipArgs.push_back(x);
+ }
+
+ unsigned* start = OwnershipArgs.data();
+ unsigned size = OwnershipArgs.size();
+ llvm::array_pod_sort(start, start + size);
+
+ if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
+ start, size));
+}
+
+/// Whether this declaration has internal linkage for the purposes of
+/// things that want to complain about things not have internal linkage.
+static bool hasEffectivelyInternalLinkage(NamedDecl *D) {
+ switch (D->getLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ return true;
+
+ // Template instantiations that go from external to unique-external
+ // shouldn't get diagnosed.
+ case UniqueExternalLinkage:
+ return true;
+
+ case ExternalLinkage:
+ return false;
+ }
+ llvm_unreachable("unknown linkage kind!");
+ return false;
+}
+
+static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variables and functions*/;
+ return;
+ }
+
+ NamedDecl *nd = cast<NamedDecl>(d);
+
+ // gcc rejects
+ // class c {
+ // static int a __attribute__((weakref ("v2")));
+ // static int b() __attribute__((weakref ("f3")));
+ // };
+ // and ignores the attributes of
+ // void f(void) {
+ // static int a __attribute__((weakref ("v2")));
+ // }
+ // we reject them
+ const DeclContext *Ctx = d->getDeclContext()->getRedeclContext();
+ if (!Ctx->isFileContext()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
+ nd->getNameAsString();
+ return;
+ }
+
+ // The GCC manual says
+ //
+ // At present, a declaration to which `weakref' is attached can only
+ // be `static'.
+ //
+ // It also says
+ //
+ // Without a TARGET,
+ // given as an argument to `weakref' or to `alias', `weakref' is
+ // equivalent to `weak'.
+ //
+ // gcc 4.4.1 will accept
+ // int a7 __attribute__((weakref));
+ // as
+ // int a7 __attribute__((weak));
+ // This looks like a bug in gcc. We reject that for now. We should revisit
+ // it if this behaviour is actually used.
+
+ if (!hasEffectivelyInternalLinkage(nd)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static);
+ return;
+ }
+
+ // GCC rejects
+ // static ((alias ("y"), weakref)).
+ // Should we? How to check that weakref is before or after alias?
+
+ if (Attr.getNumArgs() == 1) {
+ Expr *Arg = Attr.getArg(0);
+ Arg = Arg->IgnoreParenCasts();
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "weakref" << 1;
+ return;
+ }
+ // GCC will accept anything as the argument of weakref. Should we
+ // check for an existing decl?
+ d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context,
+ Str->getString()));
+ }
+
+ d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ Expr *Arg = Attr.getArg(0);
+ Arg = Arg->IgnoreParenCasts();
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "alias" << 1;
+ return;
+ }
+
+ if (S.Context.Target.getTriple().getOS() == llvm::Triple::Darwin) {
+ S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
+ return;
+ }
+
+ // FIXME: check if target symbol exists in current file
+
+ d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context,
+ Str->getString()));
+}
+
+static void HandleNakedAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NakedAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
+ QualType RetTy = FD->getResultType();
+ if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
+ d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
+ return;
+ }
+ }
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
+}
+
+static void HandleMayAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) MayAliasAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ assert(Attr.isInvalid() == false);
+ if (isa<VarDecl>(d))
+ d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context));
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 12 /* variable */;
+}
+
+static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ assert(Attr.isInvalid() == false);
+ if (isa<VarDecl>(d))
+ d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context));
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 12 /* variable */;
+}
+
+static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ if (hasDeclarator(d)) return;
+
+ if (S.CheckNoReturnAttr(attr)) return;
+
+ if (!isa<ObjCMethodDecl>(d)) {
+ S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context));
+}
+
+bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
+ if (attr.getNumArgs() != 0) {
+ Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ attr.setInvalid();
+ return true;
+ }
+
+ return false;
+}
+
+static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+
+ // The checking path for 'noreturn' and 'analyzer_noreturn' are different
+ // because 'analyzer_noreturn' does not impact the type.
+
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
+ ValueDecl *VD = dyn_cast<ValueDecl>(d);
+ if (VD == 0 || (!VD->getType()->isBlockPointerType()
+ && !VD->getType()->isFunctionPointerType())) {
+ S.Diag(Attr.getLoc(),
+ Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+ }
+
+ d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
+}
+
+// PS3 PPU-specific.
+static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+/*
+ Returning a Vector Class in Registers
+
+ According to the PPU ABI specifications, a class with a single member of
+ vector type is returned in memory when used as the return value of a function.
+ This results in inefficient code when implementing vector classes. To return
+ the value in a single vector register, add the vecreturn attribute to the
+ class definition. This attribute is also applicable to struct types.
+
+ Example:
+
+ struct Vector
+ {
+ __vector float xyzw;
+ } __attribute__((vecreturn));
+
+ Vector Add(Vector lhs, Vector rhs)
+ {
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will be returned in a register
+ }
+*/
+ if (!isa<RecordDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 9 /*class*/;
+ return;
+ }
+
+ if (d->getAttr<VecReturnAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+ return;
+ }
+
+ RecordDecl *record = cast<RecordDecl>(d);
+ int count = 0;
+
+ if (!isa<CXXRecordDecl>(record)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ return;
+ }
+
+ if (!cast<CXXRecordDecl>(record)->isPOD()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
+ return;
+ }
+
+ for (RecordDecl::field_iterator iter = record->field_begin();
+ iter != record->field_end(); iter++) {
+ if ((count == 1) || !iter->getType()->isVectorType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
+ return;
+ }
+ count++;
+ }
+
+ d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 8 /*function, method, or parameter*/;
+ return;
+ }
+ // FIXME: Actually store the attribute on the declaration
+}
+
+static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) &&
+ !isa<TypeDecl>(d) && !isa<LabelDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 14 /*variable, function, labels*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(d)) {
+ if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
+ return;
+ }
+ } else if (!isFunctionOrMethod(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << "0 or 1";
+ return;
+ }
+
+ int priority = 65535; // FIXME: Do not hardcode such constants.
+ if (Attr.getNumArgs() > 0) {
+ Expr *E = Attr.getArg(0);
+ llvm::APSInt Idx(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "constructor" << 1 << E->getSourceRange();
+ return;
+ }
+ priority = Idx.getZExtValue();
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context,
+ priority));
+}
+
+static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << "0 or 1";
+ return;
+ }
+
+ int priority = 65535; // FIXME: Do not hardcode such constants.
+ if (Attr.getNumArgs() > 0) {
+ Expr *E = Attr.getArg(0);
+ llvm::APSInt Idx(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "destructor" << 1 << E->getSourceRange();
+ return;
+ }
+ priority = Idx.getZExtValue();
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context,
+ priority));
+}
+
+static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ int noArgs = Attr.getNumArgs();
+ if (noArgs > 1) {
+ S.Diag(Attr.getLoc(),
+ diag::err_attribute_wrong_number_arguments) << "0 or 1";
+ return;
+ }
+ // Handle the case where deprecated attribute has a text message.
+ StringLiteral *SE;
+ if (noArgs == 1) {
+ Expr *ArgExpr = Attr.getArg(0);
+ SE = dyn_cast<StringLiteral>(ArgExpr);
+ if (!SE) {
+ S.Diag(ArgExpr->getLocStart(),
+ diag::err_attribute_not_string) << "deprecated";
+ return;
+ }
+ }
+ else
+ SE = StringLiteral::CreateEmpty(S.Context, 1);
+
+ d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context,
+ SE->getString()));
+}
+
+static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ int noArgs = Attr.getNumArgs();
+ if (noArgs > 1) {
+ S.Diag(Attr.getLoc(),
+ diag::err_attribute_wrong_number_arguments) << "0 or 1";
+ return;
+ }
+ // Handle the case where unavailable attribute has a text message.
+ StringLiteral *SE;
+ if (noArgs == 1) {
+ Expr *ArgExpr = Attr.getArg(0);
+ SE = dyn_cast<StringLiteral>(ArgExpr);
+ if (!SE) {
+ S.Diag(ArgExpr->getLocStart(),
+ diag::err_attribute_not_string) << "unavailable";
+ return;
+ }
+ }
+ else
+ SE = StringLiteral::CreateEmpty(S.Context, 1);
+ d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context,
+ SE->getString()));
+}
+
+static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ Expr *Arg = Attr.getArg(0);
+ Arg = Arg->IgnoreParenCasts();
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "visibility" << 1;
+ return;
+ }
+
+ llvm::StringRef TypeStr = Str->getString();
+ VisibilityAttr::VisibilityType type;
+
+ if (TypeStr == "default")
+ type = VisibilityAttr::Default;
+ else if (TypeStr == "hidden")
+ type = VisibilityAttr::Hidden;
+ else if (TypeStr == "internal")
+ type = VisibilityAttr::Hidden; // FIXME
+ else if (TypeStr == "protected")
+ type = VisibilityAttr::Protected;
+ else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
+}
+
+static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
+ Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
+ if (OCI == 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ QualType T = TD->getUnderlyingType();
+ if (!T->isPointerType() ||
+ !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
+ S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
+ return;
+ }
+ }
+ D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
+}
+
+static void
+HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (!Attr.getParameterName()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "blocks" << 1;
+ return;
+ }
+
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ BlocksAttr::BlockType type;
+ if (Attr.getParameterName()->isStr("byref"))
+ type = BlocksAttr::ByRef;
+ else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << "blocks" << Attr.getParameterName();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
+}
+
+static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 2) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << "0, 1 or 2";
+ return;
+ }
+
+ int sentinel = 0;
+ if (Attr.getNumArgs() > 0) {
+ Expr *E = Attr.getArg(0);
+ llvm::APSInt Idx(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "sentinel" << 1 << E->getSourceRange();
+ return;
+ }
+ sentinel = Idx.getZExtValue();
+
+ if (sentinel < 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
+ << E->getSourceRange();
+ return;
+ }
+ }
+
+ int nullPos = 0;
+ if (Attr.getNumArgs() > 1) {
+ Expr *E = Attr.getArg(1);
+ llvm::APSInt Idx(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "sentinel" << 2 << E->getSourceRange();
+ return;
+ }
+ nullPos = Idx.getZExtValue();
+
+ if (nullPos > 1 || nullPos < 0) {
+ // FIXME: This error message could be improved, it would be nice
+ // to say what the bounds actually are.
+ S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
+ << E->getSourceRange();
+ return;
+ }
+ }
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
+ const FunctionType *FT = FD->getType()->getAs<FunctionType>();
+ assert(FT && "FunctionDecl has non-function type?");
+
+ if (isa<FunctionNoProtoType>(FT)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
+ return;
+ }
+
+ if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ return;
+ }
+ } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
+ if (!MD->isVariadic()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
+ return;
+ }
+ } else if (isa<BlockDecl>(d)) {
+ // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
+ // caller.
+ ;
+ } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
+ QualType Ty = V->getType();
+ if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
+ const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d)
+ : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+ if (!cast<FunctionProtoType>(FT)->isVariadic()) {
+ int m = Ty->isFunctionPointerType() ? 0 : 1;
+ S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 6 /*function, method or block */;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 6 /*function, method or block */;
+ return;
+ }
+ d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel,
+ nullPos));
+}
+
+static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
+ << Attr.getName() << 0;
+ return;
+ }
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ if (MD->getResultType()->isVoidType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ // check the attribute arguments.
+ if (attr.getNumArgs() != 0) {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
+ S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attr.getName() << 2 /*variables and functions*/;
+ return;
+ }
+
+ NamedDecl *nd = cast<NamedDecl>(d);
+
+ // 'weak' only applies to declarations with external linkage.
+ if (hasEffectivelyInternalLinkage(nd)) {
+ S.Diag(attr.getLoc(), diag::err_attribute_weak_static);
+ return;
+ }
+
+ nd->addAttr(::new (S.Context) WeakAttr(attr.getLoc(), S.Context));
+}
+
+static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // weak_import only applies to variable & function declarations.
+ bool isDef = false;
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ isDef = (!VD->hasExternalStorage() || VD->getInit());
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ isDef = FD->hasBody();
+ } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ // We ignore weak import on properties and methods
+ return;
+ } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
+ // Don't issue the warning for darwin as target; yet, ignore the attribute.
+ if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
+ !isa<ObjCInterfaceDecl>(D))
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Merge should handle any subsequent violations.
+ if (isDef) {
+ S.Diag(Attr.getLoc(),
+ diag::warn_attribute_weak_import_invalid_on_definition)
+ << "weak_import" << 2 /*variable and function*/;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
+ Sema &S) {
+ // Attribute has 3 arguments.
+ if (Attr.getNumArgs() != 3) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ unsigned WGSize[3];
+ for (unsigned i = 0; i < 3; ++i) {
+ Expr *E = Attr.getArg(i);
+ llvm::APSInt ArgNum(32);
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ !E->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "reqd_work_group_size" << E->getSourceRange();
+ return;
+ }
+ WGSize[i] = (unsigned) ArgNum.getZExtValue();
+ }
+ D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
+ WGSize[0], WGSize[1],
+ WGSize[2]));
+}
+
+static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // Attribute has no arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // Make sure that there is a string literal as the sections's single
+ // argument.
+ Expr *ArgExpr = Attr.getArg(0);
+ StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+ if (!SE) {
+ S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
+ return;
+ }
+
+ // If the target wants to validate the section specifier, make it happen.
+ std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString());
+ if (!Error.empty()) {
+ S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
+ << Error;
+ return;
+ }
+
+ // This attribute cannot be applied to local variables.
+ if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
+ S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context,
+ SE->getString()));
+}
+
+
+static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (!Attr.getParameterName()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ VarDecl *VD = dyn_cast<VarDecl>(d);
+
+ if (!VD || !VD->hasLocalStorage()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
+ return;
+ }
+
+ // Look up the function
+ // FIXME: Lookup probably isn't looking in the right place
+ NamedDecl *CleanupDecl
+ = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
+ Attr.getParameterLoc(), Sema::LookupOrdinaryName);
+ if (!CleanupDecl) {
+ S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) <<
+ Attr.getParameterName();
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
+ if (!FD) {
+ S.Diag(Attr.getParameterLoc(),
+ diag::err_attribute_cleanup_arg_not_function)
+ << Attr.getParameterName();
+ return;
+ }
+
+ if (FD->getNumParams() != 1) {
+ S.Diag(Attr.getParameterLoc(),
+ diag::err_attribute_cleanup_func_must_take_one_arg)
+ << Attr.getParameterName();
+ return;
+ }
+
+ // We're currently more strict than GCC about what function types we accept.
+ // If this ever proves to be a problem it should be easy to fix.
+ QualType Ty = S.Context.getPointerType(VD->getType());
+ QualType ParamTy = FD->getParamDecl(0)->getType();
+ if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
+ ParamTy, Ty) != Sema::Compatible) {
+ S.Diag(Attr.getParameterLoc(),
+ diag::err_attribute_cleanup_func_arg_incompatible_type) <<
+ Attr.getParameterName() << ParamTy << Ty;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
+ S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD);
+}
+
+/// Handle __attribute__((format_arg((idx)))) attribute based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ // In C++ the implicit 'this' function parameter also counts, and they are
+ // counted from one.
+ bool HasImplicitThisParam = isInstanceMethod(d);
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
+ unsigned FirstIdx = 1;
+
+ // checks for the 2nd argument
+ Expr *IdxExpr = Attr.getArg(0);
+ llvm::APSInt Idx(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
+ !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "format" << 2 << IdxExpr->getSourceRange();
+ return;
+ }
+
+ if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "format" << 2 << IdxExpr->getSourceRange();
+ return;
+ }
+
+ unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+ if (HasImplicitThisParam) {
+ if (ArgIdx == 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
+ << "format_arg" << IdxExpr->getSourceRange();
+ return;
+ }
+ ArgIdx--;
+ }
+
+ // make sure the format string is really a string
+ QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
+
+ bool not_nsstring_type = !isNSStringType(Ty, S.Context);
+ if (not_nsstring_type &&
+ !isCFStringType(Ty, S.Context) &&
+ (!Ty->isPointerType() ||
+ !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+ // FIXME: Should highlight the actual expression that has the wrong type.
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ << (not_nsstring_type ? "a string type" : "an NSString")
+ << IdxExpr->getSourceRange();
+ return;
+ }
+ Ty = getFunctionOrMethodResultType(d);
+ if (!isNSStringType(Ty, S.Context) &&
+ !isCFStringType(Ty, S.Context) &&
+ (!Ty->isPointerType() ||
+ !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
+ // FIXME: Should highlight the actual expression that has the wrong type.
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
+ << (not_nsstring_type ? "string type" : "NSString")
+ << IdxExpr->getSourceRange();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context,
+ Idx.getZExtValue()));
+}
+
+enum FormatAttrKind {
+ CFStringFormat,
+ NSStringFormat,
+ StrftimeFormat,
+ SupportedFormat,
+ IgnoredFormat,
+ InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
+ // Check for formats that get handled specially.
+ if (Format == "NSString")
+ return NSStringFormat;
+ if (Format == "CFString")
+ return CFStringFormat;
+ if (Format == "strftime")
+ return StrftimeFormat;
+
+ // Otherwise, check for supported formats.
+ if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+ Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
+ Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
+ Format == "zcmn_err" ||
+ Format == "kprintf") // OpenBSD.
+ return SupportedFormat;
+
+ if (Format == "gcc_diag" || Format == "gcc_cdiag" ||
+ Format == "gcc_cxxdiag" || Format == "gcc_tdiag")
+ return IgnoredFormat;
+
+ return InvalidFormat;
+}
+
+/// Handle __attribute__((init_priority(priority))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
+static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ if (!S.getLangOptions().CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) {
+ S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+ Attr.setInvalid();
+ return;
+ }
+ QualType T = dyn_cast<VarDecl>(d)->getType();
+ if (S.Context.getAsArrayType(T))
+ T = S.Context.getBaseElementType(T);
+ if (!T->getAs<RecordType>()) {
+ S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+ Attr.setInvalid();
+ return;
+ }
+
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *priorityExpr = Attr.getArg(0);
+
+ llvm::APSInt priority(32);
+ if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
+ !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "init_priority" << priorityExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ unsigned prioritynum = priority.getZExtValue();
+ if (prioritynum < 101 || prioritynum > 65535) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
+ << priorityExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context,
+ prioritynum));
+}
+
+/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+
+ if (!Attr.getParameterName()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "format" << 1;
+ return;
+ }
+
+ if (Attr.getNumArgs() != 2) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
+ return;
+ }
+
+ if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ // In C++ the implicit 'this' function parameter also counts, and they are
+ // counted from one.
+ bool HasImplicitThisParam = isInstanceMethod(d);
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
+ unsigned FirstIdx = 1;
+
+ llvm::StringRef Format = Attr.getParameterName()->getName();
+
+ // Normalize the argument, __foo__ becomes foo.
+ if (Format.startswith("__") && Format.endswith("__"))
+ Format = Format.substr(2, Format.size() - 4);
+
+ // Check for supported formats.
+ FormatAttrKind Kind = getFormatAttrKind(Format);
+
+ if (Kind == IgnoredFormat)
+ return;
+
+ if (Kind == InvalidFormat) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << "format" << Attr.getParameterName()->getName();
+ return;
+ }
+
+ // checks for the 2nd argument
+ Expr *IdxExpr = Attr.getArg(0);
+ llvm::APSInt Idx(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
+ !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "format" << 2 << IdxExpr->getSourceRange();
+ return;
+ }
+
+ if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "format" << 2 << IdxExpr->getSourceRange();
+ return;
+ }
+
+ // FIXME: Do we need to bounds check?
+ unsigned ArgIdx = Idx.getZExtValue() - 1;
+
+ if (HasImplicitThisParam) {
+ if (ArgIdx == 0) {
+ S.Diag(Attr.getLoc(),
+ diag::err_format_attribute_implicit_this_format_string)
+ << IdxExpr->getSourceRange();
+ return;
+ }
+ ArgIdx--;
+ }
+
+ // make sure the format string is really a string
+ QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
+
+ if (Kind == CFStringFormat) {
+ if (!isCFStringType(Ty, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ << "a CFString" << IdxExpr->getSourceRange();
+ return;
+ }
+ } else if (Kind == NSStringFormat) {
+ // FIXME: do we need to check if the type is NSString*? What are the
+ // semantics?
+ if (!isNSStringType(Ty, S.Context)) {
+ // FIXME: Should highlight the actual expression that has the wrong type.
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ << "an NSString" << IdxExpr->getSourceRange();
+ return;
+ }
+ } else if (!Ty->isPointerType() ||
+ !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
+ // FIXME: Should highlight the actual expression that has the wrong type.
+ S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+ << "a string type" << IdxExpr->getSourceRange();
+ return;
+ }
+
+ // check the 3rd argument
+ Expr *FirstArgExpr = Attr.getArg(1);
+ llvm::APSInt FirstArg(32);
+ if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
+ !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "format" << 3 << FirstArgExpr->getSourceRange();
+ return;
+ }
+
+ // check if the function is variadic if the 3rd argument non-zero
+ if (FirstArg != 0) {
+ if (isFunctionOrMethodVariadic(d)) {
+ ++NumArgs; // +1 for ...
+ } else {
+ S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
+ return;
+ }
+ }
+
+ // strftime requires FirstArg to be 0 because it doesn't read from any
+ // variable the input is just the current time + the format string.
+ if (Kind == StrftimeFormat) {
+ if (FirstArg != 0) {
+ S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
+ << FirstArgExpr->getSourceRange();
+ return;
+ }
+ // if 0 it disables parameter checking (to use with e.g. va_list)
+ } else if (FirstArg != 0 && FirstArg != NumArgs) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "format" << 3 << FirstArgExpr->getSourceRange();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
+ Idx.getZExtValue(),
+ FirstArg.getZExtValue()));
+}
+
+static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // Try to find the underlying union declaration.
+ RecordDecl *RD = 0;
+ TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
+ if (TD && TD->getUnderlyingType()->isUnionType())
+ RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
+ else
+ RD = dyn_cast<RecordDecl>(d);
+
+ if (!RD || !RD->isUnion()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 1 /*union*/;
+ return;
+ }
+
+ if (!RD->isDefinition()) {
+ S.Diag(Attr.getLoc(),
+ diag::warn_transparent_union_attribute_not_definition);
+ return;
+ }
+
+ RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ if (Field == FieldEnd) {
+ S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
+ return;
+ }
+
+ FieldDecl *FirstField = *Field;
+ QualType FirstType = FirstField->getType();
+ if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
+ S.Diag(FirstField->getLocation(),
+ diag::warn_transparent_union_attribute_floating)
+ << FirstType->isVectorType() << FirstType;
+ return;
+ }
+
+ uint64_t FirstSize = S.Context.getTypeSize(FirstType);
+ uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
+ for (; Field != FieldEnd; ++Field) {
+ QualType FieldType = Field->getType();
+ if (S.Context.getTypeSize(FieldType) != FirstSize ||
+ S.Context.getTypeAlign(FieldType) != FirstAlign) {
+ // Warn if we drop the attribute.
+ bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
+ unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
+ : S.Context.getTypeAlign(FieldType);
+ S.Diag(Field->getLocation(),
+ diag::warn_transparent_union_attribute_field_size_align)
+ << isSize << Field->getDeclName() << FieldBits;
+ unsigned FirstBits = isSize? FirstSize : FirstAlign;
+ S.Diag(FirstField->getLocation(),
+ diag::note_transparent_union_first_field_size_align)
+ << isSize << FirstBits;
+ return;
+ }
+ }
+
+ RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ Expr *ArgExpr = Attr.getArg(0);
+ StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
+
+ // Make sure that there is a string literal as the annotation's single
+ // argument.
+ if (!SE) {
+ S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
+ return;
+ }
+ d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context,
+ SE->getString()));
+}
+
+static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ //FIXME: The C++0x version of this attribute has more limited applicabilty
+ // than GNU's, and should error out when it is used to specify a
+ // weaker alignment, rather than being silently ignored.
+
+ if (Attr.getNumArgs() == 0) {
+ D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
+ return;
+ }
+
+ S.AddAlignedAttr(Attr.getLoc(), D, Attr.getArg(0));
+}
+
+void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
+ if (E->isTypeDependent() || E->isValueDependent()) {
+ // Save dependent expressions in the AST to be instantiated.
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
+ return;
+ }
+
+ // FIXME: Cache the number on the Attr object?
+ llvm::APSInt Alignment(32);
+ if (!E->isIntegerConstantExpr(Alignment, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_not_int)
+ << "aligned" << E->getSourceRange();
+ return;
+ }
+ if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
+ << E->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
+}
+
+void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
+ // FIXME: Cache the number on the Attr object if non-dependent?
+ // FIXME: Perform checking of type validity
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
+ return;
+}
+
+/// HandleModeAttr - This attribute modifies the width of a decl with primitive
+/// type.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute, not a
+/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
+/// HImode, not an intermediate pointer.
+static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // This attribute isn't documented, but glibc uses it. It changes
+ // the width of an int or unsigned int to the specified size.
+
+ // Check that there aren't any arguments
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ IdentifierInfo *Name = Attr.getParameterName();
+ if (!Name) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
+ return;
+ }
+
+ llvm::StringRef Str = Attr.getParameterName()->getName();
+
+ // Normalize the attribute name, __foo__ becomes foo.
+ if (Str.startswith("__") && Str.endswith("__"))
+ Str = Str.substr(2, Str.size() - 4);
+
+ unsigned DestWidth = 0;
+ bool IntegerMode = true;
+ bool ComplexMode = false;
+ switch (Str.size()) {
+ case 2:
+ switch (Str[0]) {
+ case 'Q': DestWidth = 8; break;
+ case 'H': DestWidth = 16; break;
+ case 'S': DestWidth = 32; break;
+ case 'D': DestWidth = 64; break;
+ case 'X': DestWidth = 96; break;
+ case 'T': DestWidth = 128; break;
+ }
+ if (Str[1] == 'F') {
+ IntegerMode = false;
+ } else if (Str[1] == 'C') {
+ IntegerMode = false;
+ ComplexMode = true;
+ } else if (Str[1] != 'I') {
+ DestWidth = 0;
+ }
+ break;
+ case 4:
+ // FIXME: glibc uses 'word' to define register_t; this is narrower than a
+ // pointer on PIC16 and other embedded platforms.
+ if (Str == "word")
+ DestWidth = S.Context.Target.getPointerWidth(0);
+ else if (Str == "byte")
+ DestWidth = S.Context.Target.getCharWidth();
+ break;
+ case 7:
+ if (Str == "pointer")
+ DestWidth = S.Context.Target.getPointerWidth(0);
+ break;
+ }
+
+ QualType OldTy;
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+ OldTy = TD->getUnderlyingType();
+ else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+ OldTy = VD->getType();
+ else {
+ S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
+ << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
+ return;
+ }
+
+ if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
+ S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+ else if (IntegerMode) {
+ if (!OldTy->isIntegralOrEnumerationType())
+ S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ } else if (ComplexMode) {
+ if (!OldTy->isComplexType())
+ S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ } else {
+ if (!OldTy->isFloatingType())
+ S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+ }
+
+ // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+ // and friends, at least with glibc.
+ // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
+ // width on unusual platforms.
+ // FIXME: Make sure floating-point mappings are accurate
+ // FIXME: Support XF and TF types
+ QualType NewTy;
+ switch (DestWidth) {
+ case 0:
+ S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
+ return;
+ default:
+ S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ return;
+ case 8:
+ if (!IntegerMode) {
+ S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ return;
+ }
+ if (OldTy->isSignedIntegerType())
+ NewTy = S.Context.SignedCharTy;
+ else
+ NewTy = S.Context.UnsignedCharTy;
+ break;
+ case 16:
+ if (!IntegerMode) {
+ S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ return;
+ }
+ if (OldTy->isSignedIntegerType())
+ NewTy = S.Context.ShortTy;
+ else
+ NewTy = S.Context.UnsignedShortTy;
+ break;
+ case 32:
+ if (!IntegerMode)
+ NewTy = S.Context.FloatTy;
+ else if (OldTy->isSignedIntegerType())
+ NewTy = S.Context.IntTy;
+ else
+ NewTy = S.Context.UnsignedIntTy;
+ break;
+ case 64:
+ if (!IntegerMode)
+ NewTy = S.Context.DoubleTy;
+ else if (OldTy->isSignedIntegerType())
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.LongTy;
+ else
+ NewTy = S.Context.LongLongTy;
+ else
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.UnsignedLongTy;
+ else
+ NewTy = S.Context.UnsignedLongLongTy;
+ break;
+ case 96:
+ NewTy = S.Context.LongDoubleTy;
+ break;
+ case 128:
+ if (!IntegerMode) {
+ S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
+ return;
+ }
+ if (OldTy->isSignedIntegerType())
+ NewTy = S.Context.Int128Ty;
+ else
+ NewTy = S.Context.UnsignedInt128Ty;
+ break;
+ }
+
+ if (ComplexMode) {
+ NewTy = S.Context.getComplexType(NewTy);
+ }
+
+ // Install the new type.
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+ // FIXME: preserve existing source info.
+ TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
+ } else
+ cast<ValueDecl>(D)->setType(NewTy);
+}
+
+static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isFunctionOrMethod(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(),
+ S.Context));
+}
+
+static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<VarDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 12 /*variable*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getLoc(), S.Context));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
+ }
+}
+
+static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getLoc(), S.Context));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
+ }
+}
+
+static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ FunctionDecl *FD = cast<FunctionDecl>(d);
+ if (!FD->getResultType()->isVoidType()) {
+ TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
+ if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType()
+ << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(),
+ "void");
+ } else {
+ S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
+ << FD->getType();
+ }
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getLoc(), S.Context));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
+ }
+}
+
+static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CUDAHostAttr(Attr.getLoc(), S.Context));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
+ }
+}
+
+static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<VarDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 12 /*variable*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) CUDASharedAttr(Attr.getLoc(), S.Context));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
+ }
+}
+
+static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
+ if (Fn == 0) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ if (!Fn->isInlineSpecified()) {
+ S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
+ return;
+ }
+
+ d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ if (hasDeclarator(d)) return;
+
+ // Diagnostic is emitted elsewhere: here we store the (valid) attr
+ // in the Decl node for syntactic reasoning, e.g., pretty-printing.
+ CallingConv CC;
+ if (S.CheckCallingConvAttr(attr, CC))
+ return;
+
+ if (!isa<ObjCMethodDecl>(d)) {
+ S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ switch (attr.getKind()) {
+ case AttributeList::AT_fastcall:
+ d->addAttr(::new (S.Context) FastCallAttr(attr.getLoc(), S.Context));
+ return;
+ case AttributeList::AT_stdcall:
+ d->addAttr(::new (S.Context) StdCallAttr(attr.getLoc(), S.Context));
+ return;
+ case AttributeList::AT_thiscall:
+ d->addAttr(::new (S.Context) ThisCallAttr(attr.getLoc(), S.Context));
+ return;
+ case AttributeList::AT_cdecl:
+ d->addAttr(::new (S.Context) CDeclAttr(attr.getLoc(), S.Context));
+ return;
+ case AttributeList::AT_pascal:
+ d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context));
+ return;
+ default:
+ llvm_unreachable("unexpected attribute kind");
+ return;
+ }
+}
+
+static void HandleOpenCLKernelAttr(Decl *d, const AttributeList &Attr, Sema &S){
+ assert(Attr.isInvalid() == false);
+ d->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getLoc(), S.Context));
+}
+
+bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
+ if (attr.isInvalid())
+ return true;
+
+ if (attr.getNumArgs() != 0) {
+ Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ attr.setInvalid();
+ return true;
+ }
+
+ // TODO: diagnose uses of these conventions on the wrong target.
+ switch (attr.getKind()) {
+ case AttributeList::AT_cdecl: CC = CC_C; break;
+ case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+ case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+ case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+ case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
+ default: llvm_unreachable("unexpected attribute kind"); return true;
+ }
+
+ return false;
+}
+
+static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ if (hasDeclarator(d)) return;
+
+ unsigned numParams;
+ if (S.CheckRegparmAttr(attr, numParams))
+ return;
+
+ if (!isa<ObjCMethodDecl>(d)) {
+ S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) RegparmAttr(attr.getLoc(), S.Context, numParams));
+}
+
+/// Checks a regparm attribute, returning true if it is ill-formed and
+/// otherwise setting numParams to the appropriate value.
+bool Sema::CheckRegparmAttr(const AttributeList &attr, unsigned &numParams) {
+ if (attr.isInvalid())
+ return true;
+
+ if (attr.getNumArgs() != 1) {
+ Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ attr.setInvalid();
+ return true;
+ }
+
+ Expr *NumParamsExpr = attr.getArg(0);
+ llvm::APSInt NumParams(32);
+ if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
+ !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
+ Diag(attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "regparm" << NumParamsExpr->getSourceRange();
+ attr.setInvalid();
+ return true;
+ }
+
+ if (Context.Target.getRegParmMax() == 0) {
+ Diag(attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
+ << NumParamsExpr->getSourceRange();
+ attr.setInvalid();
+ return true;
+ }
+
+ numParams = NumParams.getZExtValue();
+ if (numParams > Context.Target.getRegParmMax()) {
+ Diag(attr.getLoc(), diag::err_attribute_regparm_invalid_number)
+ << Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
+ attr.setInvalid();
+ return true;
+ }
+
+ return false;
+}
+
+static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){
+ if (S.LangOpts.CUDA) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << "1 or 2";
+ return;
+ }
+
+ if (!isFunctionOrMethod(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ Expr *MaxThreadsExpr = Attr.getArg(0);
+ llvm::APSInt MaxThreads(32);
+ if (MaxThreadsExpr->isTypeDependent() ||
+ MaxThreadsExpr->isValueDependent() ||
+ !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange();
+ return;
+ }
+
+ llvm::APSInt MinBlocks(32);
+ if (Attr.getNumArgs() > 1) {
+ Expr *MinBlocksExpr = Attr.getArg(1);
+ if (MinBlocksExpr->isTypeDependent() ||
+ MinBlocksExpr->isValueDependent() ||
+ !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
+ << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange();
+ return;
+ }
+ }
+
+ d->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getLoc(), S.Context,
+ MaxThreads.getZExtValue(),
+ MinBlocks.getZExtValue()));
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Checker-specific attribute handlers.
+//===----------------------------------------------------------------------===//
+
+static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
+ return type->isObjCObjectPointerType() || S.Context.isObjCNSObjectType(type);
+}
+static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
+ return type->isPointerType() || isValidSubjectOfNSAttribute(S, type);
+}
+
+static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) {
+ ParmVarDecl *param = dyn_cast<ParmVarDecl>(d);
+ if (!param) {
+ S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << 4 /*parameter*/;
+ return;
+ }
+
+ bool typeOK, cf;
+ if (attr.getKind() == AttributeList::AT_ns_consumed) {
+ typeOK = isValidSubjectOfNSAttribute(S, param->getType());
+ cf = false;
+ } else {
+ typeOK = isValidSubjectOfCFAttribute(S, param->getType());
+ cf = true;
+ }
+
+ if (!typeOK) {
+ S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << cf;
+ return;
+ }
+
+ if (cf)
+ param->addAttr(::new (S.Context) CFConsumedAttr(attr.getLoc(), S.Context));
+ else
+ param->addAttr(::new (S.Context) NSConsumedAttr(attr.getLoc(), S.Context));
+}
+
+static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr,
+ Sema &S) {
+ if (!isa<ObjCMethodDecl>(d)) {
+ S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+ << SourceRange(attr.getLoc()) << attr.getName() << 13 /*method*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NSConsumesSelfAttr(attr.getLoc(), S.Context));
+}
+
+static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr,
+ Sema &S) {
+
+ QualType returnType;
+
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
+ returnType = MD->getResultType();
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
+ returnType = FD->getResultType();
+ else {
+ S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
+ << SourceRange(attr.getLoc()) << attr.getName()
+ << 3 /* function or method */;
+ return;
+ }
+
+ bool typeOK;
+ bool cf;
+ switch (attr.getKind()) {
+ default: llvm_unreachable("invalid ownership attribute"); return;
+ case AttributeList::AT_ns_returns_autoreleased:
+ case AttributeList::AT_ns_returns_retained:
+ case AttributeList::AT_ns_returns_not_retained:
+ typeOK = isValidSubjectOfNSAttribute(S, returnType);
+ cf = false;
+ break;
+
+ case AttributeList::AT_cf_returns_retained:
+ case AttributeList::AT_cf_returns_not_retained:
+ typeOK = isValidSubjectOfCFAttribute(S, returnType);
+ cf = true;
+ break;
+ }
+
+ if (!typeOK) {
+ S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+ << SourceRange(attr.getLoc())
+ << attr.getName() << isa<ObjCMethodDecl>(d) << cf;
+ return;
+ }
+
+ switch (attr.getKind()) {
+ default:
+ assert(0 && "invalid ownership attribute");
+ return;
+ case AttributeList::AT_ns_returns_autoreleased:
+ d->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(attr.getLoc(),
+ S.Context));
+ return;
+ case AttributeList::AT_cf_returns_not_retained:
+ d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(attr.getLoc(),
+ S.Context));
+ return;
+ case AttributeList::AT_ns_returns_not_retained:
+ d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(attr.getLoc(),
+ S.Context));
+ return;
+ case AttributeList::AT_cf_returns_retained:
+ d->addAttr(::new (S.Context) CFReturnsRetainedAttr(attr.getLoc(),
+ S.Context));
+ return;
+ case AttributeList::AT_ns_returns_retained:
+ d->addAttr(::new (S.Context) NSReturnsRetainedAttr(attr.getLoc(),
+ S.Context));
+ return;
+ };
+}
+
+static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
+ return Attr.getKind() == AttributeList::AT_dllimport ||
+ Attr.getKind() == AttributeList::AT_dllexport ||
+ Attr.getKind() == AttributeList::AT_uuid;
+}
+
+//===----------------------------------------------------------------------===//
+// Microsoft specific attribute handlers.
+//===----------------------------------------------------------------------===//
+
+static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ if (S.LangOpts.Microsoft || S.LangOpts.Borland) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ Expr *Arg = Attr.getArg(0);
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "uuid" << 1;
+ return;
+ }
+
+ llvm::StringRef StrRef = Str->getString();
+
+ bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' &&
+ StrRef.back() == '}';
+
+ // Validate GUID length.
+ if (IsCurly && StrRef.size() != 38) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ if (!IsCurly && StrRef.size() != 36) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+
+ // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
+ // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+ llvm::StringRef::iterator I = StrRef.begin();
+ if (IsCurly) // Skip the optional '{'
+ ++I;
+
+ for (int i = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (*I != '-') {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ } else if (!isxdigit(*I)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ I++;
+ }
+
+ d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context,
+ Str->getString()));
+ } else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
+}
+
+//===----------------------------------------------------------------------===//
+// Top Level Sema Entry Points
+//===----------------------------------------------------------------------===//
+
+static void ProcessNonInheritableDeclAttr(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) {
+ switch (Attr.getKind()) {
+ case AttributeList::AT_device: HandleDeviceAttr (D, Attr, S); break;
+ case AttributeList::AT_host: HandleHostAttr (D, Attr, S); break;
+ case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
+ default:
+ break;
+ }
+}
+
+static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) {
+ switch (Attr.getKind()) {
+ case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break;
+ case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break;
+ case AttributeList::AT_IBOutletCollection:
+ HandleIBOutletCollection(D, Attr, S); break;
+ case AttributeList::AT_address_space:
+ case AttributeList::AT_objc_gc:
+ case AttributeList::AT_vector_size:
+ case AttributeList::AT_neon_vector_type:
+ case AttributeList::AT_neon_polyvector_type:
+ // Ignore these, these are type attributes, handled by
+ // ProcessTypeAttributes.
+ break;
+ case AttributeList::AT_device:
+ case AttributeList::AT_host:
+ case AttributeList::AT_overloadable:
+ // Ignore, this is a non-inheritable attribute, handled
+ // by ProcessNonInheritableDeclAttr.
+ break;
+ case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
+ case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
+ case AttributeList::AT_always_inline:
+ HandleAlwaysInlineAttr (D, Attr, S); break;
+ case AttributeList::AT_analyzer_noreturn:
+ HandleAnalyzerNoReturnAttr (D, Attr, S); break;
+ case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
+ case AttributeList::AT_carries_dependency:
+ HandleDependencyAttr (D, Attr, S); break;
+ case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break;
+ case AttributeList::AT_constant: HandleConstantAttr (D, Attr, S); break;
+ case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
+ case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
+ case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
+ case AttributeList::AT_ext_vector_type:
+ HandleExtVectorTypeAttr(scope, D, Attr, S);
+ break;
+ case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
+ case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
+ case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break;
+ case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
+ case AttributeList::AT_launch_bounds:
+ HandleLaunchBoundsAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
+ case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
+ case AttributeList::AT_may_alias: HandleMayAliasAttr (D, Attr, S); break;
+ case AttributeList::AT_nocommon: HandleNoCommonAttr (D, Attr, S); break;
+ case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
+ case AttributeList::AT_ownership_returns:
+ case AttributeList::AT_ownership_takes:
+ case AttributeList::AT_ownership_holds:
+ HandleOwnershipAttr (D, Attr, S); break;
+ case AttributeList::AT_naked: HandleNakedAttr (D, Attr, S); break;
+ case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
+ case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
+ case AttributeList::AT_shared: HandleSharedAttr (D, Attr, S); break;
+ case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
+
+ // Checker-specific.
+ case AttributeList::AT_cf_consumed:
+ case AttributeList::AT_ns_consumed: HandleNSConsumedAttr (D, Attr, S); break;
+ case AttributeList::AT_ns_consumes_self:
+ HandleNSConsumesSelfAttr(D, Attr, S); break;
+
+ case AttributeList::AT_ns_returns_autoreleased:
+ case AttributeList::AT_ns_returns_not_retained:
+ case AttributeList::AT_cf_returns_not_retained:
+ case AttributeList::AT_ns_returns_retained:
+ case AttributeList::AT_cf_returns_retained:
+ HandleNSReturnsRetainedAttr(D, Attr, S); break;
+
+ case AttributeList::AT_reqd_wg_size:
+ HandleReqdWorkGroupSize(D, Attr, S); break;
+
+ case AttributeList::AT_init_priority:
+ HandleInitPriorityAttr(D, Attr, S); break;
+
+ case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
+ case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
+ case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
+ case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
+ case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
+ case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break;
+ case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
+ break;
+ case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
+ case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break;
+ case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break;
+ case AttributeList::AT_transparent_union:
+ HandleTransparentUnionAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_objc_exception:
+ HandleObjCExceptionAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
+ case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
+ case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
+ case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
+ case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
+ case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
+ case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break;
+ case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
+ case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
+ case AttributeList::IgnoredAttribute:
+ // Just ignore
+ break;
+ case AttributeList::AT_no_instrument_function: // Interacts with -pg.
+ HandleNoInstrumentFunctionAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_stdcall:
+ case AttributeList::AT_cdecl:
+ case AttributeList::AT_fastcall:
+ case AttributeList::AT_thiscall:
+ case AttributeList::AT_pascal:
+ HandleCallConvAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_opencl_kernel_function:
+ HandleOpenCLKernelAttr(D, Attr, S);
+ break;
+ case AttributeList::AT_uuid:
+ HandleUuidAttr(D, Attr, S);
+ break;
+ default:
+ // Ask target about the attribute.
+ const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
+ if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+ S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
+ << Attr.getName();
+ break;
+ }
+}
+
+/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
+/// the attribute applies to decls. If the attribute is a type attribute, just
+/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
+/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
+static void ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S,
+ bool NonInheritable, bool Inheritable) {
+ if (Attr.isInvalid())
+ return;
+
+ if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
+ // FIXME: Try to deal with other __declspec attributes!
+ return;
+
+ if (NonInheritable)
+ ProcessNonInheritableDeclAttr(scope, D, Attr, S);
+
+ if (Inheritable)
+ ProcessInheritableDeclAttr(scope, D, Attr, S);
+}
+
+/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
+/// attribute list to the specified decl, ignoring any type attributes.
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
+ const AttributeList *AttrList,
+ bool NonInheritable, bool Inheritable) {
+ for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+ ProcessDeclAttribute(S, D, *l, *this, NonInheritable, Inheritable);
+ }
+
+ // GCC accepts
+ // static int a9 __attribute__((weakref));
+ // but that looks really pointless. We reject it.
+ if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
+ Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
+ dyn_cast<NamedDecl>(D)->getNameAsString();
+ return;
+ }
+}
+
+/// DeclClonePragmaWeak - clone existing decl (maybe definition),
+/// #pragma weak needs a non-definition decl and source may not have one
+NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
+ assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
+ NamedDecl *NewD = 0;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
+ NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
+ FD->getLocation(), DeclarationName(II),
+ FD->getType(), FD->getTypeSourceInfo());
+ if (FD->getQualifier()) {
+ FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
+ NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange());
+ }
+ } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
+ VD->getLocation(), II,
+ VD->getType(), VD->getTypeSourceInfo(),
+ VD->getStorageClass(),
+ VD->getStorageClassAsWritten());
+ if (VD->getQualifier()) {
+ VarDecl *NewVD = cast<VarDecl>(NewD);
+ NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
+ }
+ }
+ return NewD;
+}
+
+/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
+/// applied to it, possibly with an alias.
+void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
+ if (W.getUsed()) return; // only do this once
+ W.setUsed(true);
+ if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
+ IdentifierInfo *NDId = ND->getIdentifier();
+ NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
+ NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
+ NDId->getName()));
+ NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ WeakTopLevelDecl.push_back(NewD);
+ // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
+ // to insert Decl at TU scope, sorry.
+ DeclContext *SavedContext = CurContext;
+ CurContext = Context.getTranslationUnitDecl();
+ PushOnScopeChains(NewD, S);
+ CurContext = SavedContext;
+ } else { // just add weak to existing
+ ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
+ }
+}
+
+/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
+/// it, apply them to D. This is a bit tricky because PD can have attributes
+/// specified in many different places, and we need to find and apply them all.
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
+ bool NonInheritable, bool Inheritable) {
+ // It's valid to "forward-declare" #pragma weak, in which case we
+ // have to do this.
+ if (Inheritable && !WeakUndeclaredIdentifiers.empty()) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ if (IdentifierInfo *Id = ND->getIdentifier()) {
+ llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
+ = WeakUndeclaredIdentifiers.find(Id);
+ if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) {
+ WeakInfo W = I->second;
+ DeclApplyPragmaWeak(S, ND, W);
+ WeakUndeclaredIdentifiers[Id] = W;
+ }
+ }
+ }
+ }
+
+ // Apply decl attributes from the DeclSpec if present.
+ if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
+ ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+
+ // Walk the declarator structure, applying decl attributes that were in a type
+ // position to the decl itself. This handles cases like:
+ // int *__attr__(x)** D;
+ // when X is a decl attribute.
+ for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
+ if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
+ ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+
+ // Finally, apply any attributes on the decl itself.
+ if (const AttributeList *Attrs = PD.getAttributes())
+ ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
+}
+
+// This duplicates a vector push_back but hides the need to know the
+// size of the type.
+void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) {
+ assert(StackSize <= StackCapacity);
+
+ // Grow the stack if necessary.
+ if (StackSize == StackCapacity) {
+ unsigned newCapacity = 2 * StackCapacity + 2;
+ char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)];
+ const char *oldBuffer = (const char*) Stack;
+
+ if (StackCapacity)
+ memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic));
+
+ delete[] oldBuffer;
+ Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer);
+ StackCapacity = newCapacity;
+ }
+
+ assert(StackSize < StackCapacity);
+ new (&Stack[StackSize++]) DelayedDiagnostic(diag);
+}
+
+void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
+ Decl *decl) {
+ DelayedDiagnostics &DD = S.DelayedDiagnostics;
+
+ // Check the invariants.
+ assert(DD.StackSize >= state.SavedStackSize);
+ assert(state.SavedStackSize >= DD.ActiveStackBase);
+ assert(DD.ParsingDepth > 0);
+
+ // Drop the parsing depth.
+ DD.ParsingDepth--;
+
+ // If there are no active diagnostics, we're done.
+ if (DD.StackSize == DD.ActiveStackBase)
+ return;
+
+ // We only want to actually emit delayed diagnostics when we
+ // successfully parsed a decl.
+ if (decl) {
+ // We emit all the active diagnostics, not just those starting
+ // from the saved state. The idea is this: we get one push for a
+ // decl spec and another for each declarator; in a decl group like:
+ // deprecated_typedef foo, *bar, baz();
+ // only the declarator pops will be passed decls. This is correct;
+ // we really do need to consider delayed diagnostics from the decl spec
+ // for each of the different declarations.
+ for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) {
+ DelayedDiagnostic &diag = DD.Stack[i];
+ if (diag.Triggered)
+ continue;
+
+ switch (diag.Kind) {
+ case DelayedDiagnostic::Deprecation:
+ S.HandleDelayedDeprecationCheck(diag, decl);
+ break;
+
+ case DelayedDiagnostic::Access:
+ S.HandleDelayedAccessCheck(diag, decl);
+ break;
+ }
+ }
+ }
+
+ // Destroy all the delayed diagnostics we're about to pop off.
+ for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i)
+ DD.Stack[i].destroy();
+
+ DD.StackSize = state.SavedStackSize;
+}
+
+static bool isDeclDeprecated(Decl *D) {
+ do {
+ if (D->hasAttr<DeprecatedAttr>())
+ return true;
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
+void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
+ Decl *Ctx) {
+ if (isDeclDeprecated(Ctx))
+ return;
+
+ DD.Triggered = true;
+ if (!DD.getDeprecationMessage().empty())
+ Diag(DD.Loc, diag::warn_deprecated_message)
+ << DD.getDeprecationDecl()->getDeclName()
+ << DD.getDeprecationMessage();
+ else
+ Diag(DD.Loc, diag::warn_deprecated)
+ << DD.getDeprecationDecl()->getDeclName();
+}
+
+void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
+ SourceLocation Loc,
+ bool UnknownObjCClass) {
+ // Delay if we're currently parsing a declaration.
+ if (DelayedDiagnostics.shouldDelayDiagnostics()) {
+ DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message));
+ return;
+ }
+
+ // Otherwise, don't warn if our current context is deprecated.
+ if (isDeclDeprecated(cast<Decl>(CurContext)))
+ return;
+ if (!Message.empty())
+ Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
+ << Message;
+ else {
+ if (!UnknownObjCClass)
+ Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+ else
+ Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName();
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
new file mode 100644
index 0000000..e8abab8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -0,0 +1,7624 @@
+//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include <map>
+#include <set>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// CheckDefaultArgumentVisitor
+//===----------------------------------------------------------------------===//
+
+namespace {
+ /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses
+ /// the default argument of a parameter to determine whether it
+ /// contains any ill-formed subexpressions. For example, this will
+ /// diagnose the use of local variables or parameters within the
+ /// default argument expression.
+ class CheckDefaultArgumentVisitor
+ : public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
+ Expr *DefaultArg;
+ Sema *S;
+
+ public:
+ CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
+ : DefaultArg(defarg), S(s) {}
+
+ bool VisitExpr(Expr *Node);
+ bool VisitDeclRefExpr(DeclRefExpr *DRE);
+ bool VisitCXXThisExpr(CXXThisExpr *ThisE);
+ };
+
+ /// VisitExpr - Visit all of the children of this expression.
+ bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
+ bool IsInvalid = false;
+ for (Stmt::child_range I = Node->children(); I; ++I)
+ IsInvalid |= Visit(*I);
+ return IsInvalid;
+ }
+
+ /// VisitDeclRefExpr - Visit a reference to a declaration, to
+ /// determine whether this declaration can be used in the default
+ /// argument expression.
+ bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
+ NamedDecl *Decl = DRE->getDecl();
+ if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
+ // C++ [dcl.fct.default]p9
+ // Default arguments are evaluated each time the function is
+ // called. The order of evaluation of function arguments is
+ // unspecified. Consequently, parameters of a function shall not
+ // be used in default argument expressions, even if they are not
+ // evaluated. Parameters of a function declared before a default
+ // argument expression are in scope and can hide namespace and
+ // class member names.
+ return S->Diag(DRE->getSourceRange().getBegin(),
+ diag::err_param_default_argument_references_param)
+ << Param->getDeclName() << DefaultArg->getSourceRange();
+ } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
+ // C++ [dcl.fct.default]p7
+ // Local variables shall not be used in default argument
+ // expressions.
+ if (VDecl->isLocalVarDecl())
+ return S->Diag(DRE->getSourceRange().getBegin(),
+ diag::err_param_default_argument_references_local)
+ << VDecl->getDeclName() << DefaultArg->getSourceRange();
+ }
+
+ return false;
+ }
+
+ /// VisitCXXThisExpr - Visit a C++ "this" expression.
+ bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
+ // C++ [dcl.fct.default]p8:
+ // The keyword this shall not be used in a default argument of a
+ // member function.
+ return S->Diag(ThisE->getSourceRange().getBegin(),
+ diag::err_param_default_argument_references_this)
+ << ThisE->getSourceRange();
+ }
+}
+
+bool
+Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
+ SourceLocation EqualLoc) {
+ if (RequireCompleteType(Param->getLocation(), Param->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ Param->setInvalidDecl();
+ return true;
+ }
+
+ // C++ [dcl.fct.default]p5
+ // A default argument expression is implicitly converted (clause
+ // 4) to the parameter type. The default argument expression has
+ // the same semantic constraints as the initializer expression in
+ // a declaration of a variable of the parameter type, using the
+ // copy-initialization semantics (8.5).
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+ Param);
+ InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
+ EqualLoc);
+ InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Arg, 1));
+ if (Result.isInvalid())
+ return true;
+ Arg = Result.takeAs<Expr>();
+
+ CheckImplicitConversions(Arg, EqualLoc);
+ Arg = MaybeCreateExprWithCleanups(Arg);
+
+ // Okay: add the default argument to the parameter
+ Param->setDefaultArg(Arg);
+
+ // We have already instantiated this parameter; provide each of the
+ // instantiations with the uninstantiated default argument.
+ UnparsedDefaultArgInstantiationsMap::iterator InstPos
+ = UnparsedDefaultArgInstantiations.find(Param);
+ if (InstPos != UnparsedDefaultArgInstantiations.end()) {
+ for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
+ InstPos->second[I]->setUninstantiatedDefaultArg(Arg);
+
+ // We're done tracking this parameter's instantiations.
+ UnparsedDefaultArgInstantiations.erase(InstPos);
+ }
+
+ return false;
+}
+
+/// ActOnParamDefaultArgument - Check whether the default argument
+/// provided for a function parameter is well-formed. If so, attach it
+/// to the parameter declaration.
+void
+Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
+ Expr *DefaultArg) {
+ if (!param || !DefaultArg)
+ return;
+
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
+ UnparsedDefaultArgLocs.erase(Param);
+
+ // Default arguments are only permitted in C++
+ if (!getLangOptions().CPlusPlus) {
+ Diag(EqualLoc, diag::err_param_default_argument)
+ << DefaultArg->getSourceRange();
+ Param->setInvalidDecl();
+ return;
+ }
+
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
+ Param->setInvalidDecl();
+ return;
+ }
+
+ // Check that the default argument is well-formed
+ CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
+ if (DefaultArgChecker.Visit(DefaultArg)) {
+ Param->setInvalidDecl();
+ return;
+ }
+
+ SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
+}
+
+/// ActOnParamUnparsedDefaultArgument - We've seen a default
+/// argument for a function parameter, but we can't parse it yet
+/// because we're inside a class definition. Note that this default
+/// argument will be parsed later.
+void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ SourceLocation ArgLoc) {
+ if (!param)
+ return;
+
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
+ if (Param)
+ Param->setUnparsedDefaultArg();
+
+ UnparsedDefaultArgLocs[Param] = ArgLoc;
+}
+
+/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
+/// the default argument for the parameter param failed.
+void Sema::ActOnParamDefaultArgumentError(Decl *param) {
+ if (!param)
+ return;
+
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
+
+ Param->setInvalidDecl();
+
+ UnparsedDefaultArgLocs.erase(Param);
+}
+
+/// CheckExtraCXXDefaultArguments - Check for any extra default
+/// arguments in the declarator, which is not a function declaration
+/// or definition and therefore is not permitted to have default
+/// arguments. This routine should be invoked for every declarator
+/// that is not a function declaration or definition.
+void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
+ // C++ [dcl.fct.default]p3
+ // A default argument expression shall be specified only in the
+ // parameter-declaration-clause of a function declaration or in a
+ // template-parameter (14.1). It shall not be specified for a
+ // parameter pack. If it is specified in a
+ // parameter-declaration-clause, it shall not occur within a
+ // declarator or abstract-declarator of a parameter-declaration.
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &chunk = D.getTypeObject(i);
+ if (chunk.Kind == DeclaratorChunk::Function) {
+ for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
+ ParmVarDecl *Param =
+ cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
+ if (Param->hasUnparsedDefaultArg()) {
+ CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
+ Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+ << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation());
+ delete Toks;
+ chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0;
+ } else if (Param->getDefaultArg()) {
+ Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
+ << Param->getDefaultArg()->getSourceRange();
+ Param->setDefaultArg(0);
+ }
+ }
+ }
+ }
+}
+
+// MergeCXXFunctionDecl - Merge two declarations of the same C++
+// function, once we already know that they have the same
+// type. Subroutine of MergeFunctionDecl. Returns true if there was an
+// error, false otherwise.
+bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
+ bool Invalid = false;
+
+ // C++ [dcl.fct.default]p4:
+ // For non-template functions, default arguments can be added in
+ // later declarations of a function in the same
+ // scope. Declarations in different scopes have completely
+ // distinct sets of default arguments. That is, declarations in
+ // inner scopes do not acquire default arguments from
+ // declarations in outer scopes, and vice versa. In a given
+ // function declaration, all parameters subsequent to a
+ // parameter with a default argument shall have default
+ // arguments supplied in this or previous declarations. A
+ // default argument shall not be redefined by a later
+ // declaration (not even to the same value).
+ //
+ // C++ [dcl.fct.default]p6:
+ // Except for member functions of class templates, the default arguments
+ // in a member function definition that appears outside of the class
+ // definition are added to the set of default arguments provided by the
+ // member function declaration in the class definition.
+ for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
+ ParmVarDecl *OldParam = Old->getParamDecl(p);
+ ParmVarDecl *NewParam = New->getParamDecl(p);
+
+ if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
+ // FIXME: If we knew where the '=' was, we could easily provide a fix-it
+ // hint here. Alternatively, we could walk the type-source information
+ // for NewParam to find the last source location in the type... but it
+ // isn't worth the effort right now. This is the kind of test case that
+ // is hard to get right:
+
+ // int f(int);
+ // void g(int (*fp)(int) = f);
+ // void g(int (*fp)(int) = &f);
+ Diag(NewParam->getLocation(),
+ diag::err_param_default_argument_redefinition)
+ << NewParam->getDefaultArgRange();
+
+ // Look for the function declaration where the default argument was
+ // actually written, which may be a declaration prior to Old.
+ for (FunctionDecl *Older = Old->getPreviousDeclaration();
+ Older; Older = Older->getPreviousDeclaration()) {
+ if (!Older->getParamDecl(p)->hasDefaultArg())
+ break;
+
+ OldParam = Older->getParamDecl(p);
+ }
+
+ Diag(OldParam->getLocation(), diag::note_previous_definition)
+ << OldParam->getDefaultArgRange();
+ Invalid = true;
+ } else if (OldParam->hasDefaultArg()) {
+ // Merge the old default argument into the new parameter.
+ // It's important to use getInit() here; getDefaultArg()
+ // strips off any top-level ExprWithCleanups.
+ NewParam->setHasInheritedDefaultArg();
+ if (OldParam->hasUninstantiatedDefaultArg())
+ NewParam->setUninstantiatedDefaultArg(
+ OldParam->getUninstantiatedDefaultArg());
+ else
+ NewParam->setDefaultArg(OldParam->getInit());
+ } else if (NewParam->hasDefaultArg()) {
+ if (New->getDescribedFunctionTemplate()) {
+ // Paragraph 4, quoted above, only applies to non-template functions.
+ Diag(NewParam->getLocation(),
+ diag::err_param_default_argument_template_redecl)
+ << NewParam->getDefaultArgRange();
+ Diag(Old->getLocation(), diag::note_template_prev_declaration)
+ << false;
+ } else if (New->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation &&
+ New->getTemplateSpecializationKind() != TSK_Undeclared) {
+ // C++ [temp.expr.spec]p21:
+ // Default function arguments shall not be specified in a declaration
+ // or a definition for one of the following explicit specializations:
+ // - the explicit specialization of a function template;
+ // - the explicit specialization of a member function template;
+ // - the explicit specialization of a member function of a class
+ // template where the class template specialization to which the
+ // member function specialization belongs is implicitly
+ // instantiated.
+ Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
+ << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
+ << New->getDeclName()
+ << NewParam->getDefaultArgRange();
+ } else if (New->getDeclContext()->isDependentContext()) {
+ // C++ [dcl.fct.default]p6 (DR217):
+ // Default arguments for a member function of a class template shall
+ // be specified on the initial declaration of the member function
+ // within the class template.
+ //
+ // Reading the tea leaves a bit in DR217 and its reference to DR205
+ // leads me to the conclusion that one cannot add default function
+ // arguments for an out-of-line definition of a member function of a
+ // dependent type.
+ int WhichKind = 2;
+ if (CXXRecordDecl *Record
+ = dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
+ if (Record->getDescribedClassTemplate())
+ WhichKind = 0;
+ else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
+ WhichKind = 1;
+ else
+ WhichKind = 2;
+ }
+
+ Diag(NewParam->getLocation(),
+ diag::err_param_default_argument_member_template_redecl)
+ << WhichKind
+ << NewParam->getDefaultArgRange();
+ }
+ }
+ }
+
+ if (CheckEquivalentExceptionSpec(Old, New))
+ Invalid = true;
+
+ return Invalid;
+}
+
+/// CheckCXXDefaultArguments - Verify that the default arguments for a
+/// function declaration are well-formed according to C++
+/// [dcl.fct.default].
+void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
+ unsigned NumParams = FD->getNumParams();
+ unsigned p;
+
+ // Find first parameter with a default argument
+ for (p = 0; p < NumParams; ++p) {
+ ParmVarDecl *Param = FD->getParamDecl(p);
+ if (Param->hasDefaultArg())
+ break;
+ }
+
+ // C++ [dcl.fct.default]p4:
+ // In a given function declaration, all parameters
+ // subsequent to a parameter with a default argument shall
+ // have default arguments supplied in this or previous
+ // declarations. A default argument shall not be redefined
+ // by a later declaration (not even to the same value).
+ unsigned LastMissingDefaultArg = 0;
+ for (; p < NumParams; ++p) {
+ ParmVarDecl *Param = FD->getParamDecl(p);
+ if (!Param->hasDefaultArg()) {
+ if (Param->isInvalidDecl())
+ /* We already complained about this parameter. */;
+ else if (Param->getIdentifier())
+ Diag(Param->getLocation(),
+ diag::err_param_default_argument_missing_name)
+ << Param->getIdentifier();
+ else
+ Diag(Param->getLocation(),
+ diag::err_param_default_argument_missing);
+
+ LastMissingDefaultArg = p;
+ }
+ }
+
+ if (LastMissingDefaultArg > 0) {
+ // Some default arguments were missing. Clear out all of the
+ // default arguments up to (and including) the last missing
+ // default argument, so that we leave the function parameters
+ // in a semantically valid state.
+ for (p = 0; p <= LastMissingDefaultArg; ++p) {
+ ParmVarDecl *Param = FD->getParamDecl(p);
+ if (Param->hasDefaultArg()) {
+ Param->setDefaultArg(0);
+ }
+ }
+ }
+}
+
+/// isCurrentClassName - Determine whether the identifier II is the
+/// name of the class type currently being defined. In the case of
+/// nested classes, this will only return true if II is the name of
+/// the innermost class.
+bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
+ const CXXScopeSpec *SS) {
+ assert(getLangOptions().CPlusPlus && "No class names in C!");
+
+ CXXRecordDecl *CurDecl;
+ if (SS && SS->isSet() && !SS->isInvalid()) {
+ DeclContext *DC = computeDeclContext(*SS, true);
+ CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
+ } else
+ CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
+
+ if (CurDecl && CurDecl->getIdentifier())
+ return &II == CurDecl->getIdentifier();
+ else
+ return false;
+}
+
+/// \brief Check the validity of a C++ base class specifier.
+///
+/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
+/// and returns NULL otherwise.
+CXXBaseSpecifier *
+Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc) {
+ QualType BaseType = TInfo->getType();
+
+ // C++ [class.union]p1:
+ // A union shall not have base classes.
+ if (Class->isUnion()) {
+ Diag(Class->getLocation(), diag::err_base_clause_on_union)
+ << SpecifierRange;
+ return 0;
+ }
+
+ if (EllipsisLoc.isValid() &&
+ !TInfo->getType()->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << TInfo->getTypeLoc().getSourceRange();
+ EllipsisLoc = SourceLocation();
+ }
+
+ if (BaseType->isDependentType())
+ return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+ Class->getTagKind() == TTK_Class,
+ Access, TInfo, EllipsisLoc);
+
+ SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
+
+ // Base specifiers must be record types.
+ if (!BaseType->isRecordType()) {
+ Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
+ return 0;
+ }
+
+ // C++ [class.union]p1:
+ // A union shall not be used as a base class.
+ if (BaseType->isUnionType()) {
+ Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
+ return 0;
+ }
+
+ // C++ [class.derived]p2:
+ // The class-name in a base-specifier shall not be an incompletely
+ // defined class.
+ if (RequireCompleteType(BaseLoc, BaseType,
+ PDiag(diag::err_incomplete_base_class)
+ << SpecifierRange)) {
+ Class->setInvalidDecl();
+ return 0;
+ }
+
+ // If the base class is polymorphic or isn't empty, the new one is/isn't, too.
+ RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
+ assert(BaseDecl && "Record type has no declaration");
+ BaseDecl = BaseDecl->getDefinition();
+ assert(BaseDecl && "Base type is not incomplete, but has no definition");
+ CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
+ assert(CXXBaseDecl && "Base type is not a C++ type");
+
+ // C++ [class.derived]p2:
+ // If a class is marked with the class-virt-specifier final and it appears
+ // as a base-type-specifier in a base-clause (10 class.derived), the program
+ // is ill-formed.
+ if (CXXBaseDecl->hasAttr<FinalAttr>()) {
+ Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
+ << CXXBaseDecl->getDeclName();
+ Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl)
+ << CXXBaseDecl->getDeclName();
+ return 0;
+ }
+
+ if (BaseDecl->isInvalidDecl())
+ Class->setInvalidDecl();
+
+ // Create the base specifier.
+ return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
+ Class->getTagKind() == TTK_Class,
+ Access, TInfo, EllipsisLoc);
+}
+
+/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
+/// one entry in the base class list of a class specifier, for
+/// example:
+/// class foo : public bar, virtual private baz {
+/// 'public bar' and 'virtual private baz' are each base-specifiers.
+BaseResult
+Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ ParsedType basetype, SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc) {
+ if (!classdecl)
+ return true;
+
+ AdjustDeclIfTemplate(classdecl);
+ CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl);
+ if (!Class)
+ return true;
+
+ TypeSourceInfo *TInfo = 0;
+ GetTypeFromParser(basetype, &TInfo);
+
+ if (EllipsisLoc.isInvalid() &&
+ DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
+ UPPC_BaseType))
+ return true;
+
+ if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
+ Virtual, Access, TInfo,
+ EllipsisLoc))
+ return BaseSpec;
+
+ return true;
+}
+
+/// \brief Performs the actual work of attaching the given base class
+/// specifiers to a C++ class.
+bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
+ unsigned NumBases) {
+ if (NumBases == 0)
+ return false;
+
+ // Used to keep track of which base types we have already seen, so
+ // that we can properly diagnose redundant direct base types. Note
+ // that the key is always the unqualified canonical type of the base
+ // class.
+ std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
+
+ // Copy non-redundant base specifiers into permanent storage.
+ unsigned NumGoodBases = 0;
+ bool Invalid = false;
+ for (unsigned idx = 0; idx < NumBases; ++idx) {
+ QualType NewBaseType
+ = Context.getCanonicalType(Bases[idx]->getType());
+ NewBaseType = NewBaseType.getLocalUnqualifiedType();
+ if (!Class->hasObjectMember()) {
+ if (const RecordType *FDTTy =
+ NewBaseType.getTypePtr()->getAs<RecordType>())
+ if (FDTTy->getDecl()->hasObjectMember())
+ Class->setHasObjectMember(true);
+ }
+
+ if (KnownBaseTypes[NewBaseType]) {
+ // C++ [class.mi]p3:
+ // A class shall not be specified as a direct base class of a
+ // derived class more than once.
+ Diag(Bases[idx]->getSourceRange().getBegin(),
+ diag::err_duplicate_base_class)
+ << KnownBaseTypes[NewBaseType]->getType()
+ << Bases[idx]->getSourceRange();
+
+ // Delete the duplicate base class specifier; we're going to
+ // overwrite its pointer later.
+ Context.Deallocate(Bases[idx]);
+
+ Invalid = true;
+ } else {
+ // Okay, add this new base class.
+ KnownBaseTypes[NewBaseType] = Bases[idx];
+ Bases[NumGoodBases++] = Bases[idx];
+ }
+ }
+
+ // Attach the remaining base class specifiers to the derived class.
+ Class->setBases(Bases, NumGoodBases);
+
+ // Delete the remaining (good) base class specifiers, since their
+ // data has been copied into the CXXRecordDecl.
+ for (unsigned idx = 0; idx < NumGoodBases; ++idx)
+ Context.Deallocate(Bases[idx]);
+
+ return Invalid;
+}
+
+/// ActOnBaseSpecifiers - Attach the given base specifiers to the
+/// class, after checking whether there are any duplicate base
+/// classes.
+void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases,
+ unsigned NumBases) {
+ if (!ClassDecl || !Bases || !NumBases)
+ return;
+
+ AdjustDeclIfTemplate(ClassDecl);
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl),
+ (CXXBaseSpecifier**)(Bases), NumBases);
+}
+
+static CXXRecordDecl *GetClassForType(QualType T) {
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return cast<CXXRecordDecl>(RT->getDecl());
+ else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>())
+ return ICT->getDecl();
+ else
+ return 0;
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
+ if (!getLangOptions().CPlusPlus)
+ return false;
+
+ CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+ if (!DerivedRD)
+ return false;
+
+ CXXRecordDecl *BaseRD = GetClassForType(Base);
+ if (!BaseRD)
+ return false;
+
+ // FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
+ return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
+}
+
+/// \brief Determine whether the type \p Derived is a C++ class that is
+/// derived from the type \p Base.
+bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
+ if (!getLangOptions().CPlusPlus)
+ return false;
+
+ CXXRecordDecl *DerivedRD = GetClassForType(Derived);
+ if (!DerivedRD)
+ return false;
+
+ CXXRecordDecl *BaseRD = GetClassForType(Base);
+ if (!BaseRD)
+ return false;
+
+ return DerivedRD->isDerivedFrom(BaseRD, Paths);
+}
+
+void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
+ CXXCastPath &BasePathArray) {
+ assert(BasePathArray.empty() && "Base path array must be empty!");
+ assert(Paths.isRecordingPaths() && "Must record paths!");
+
+ const CXXBasePath &Path = Paths.front();
+
+ // We first go backward and check if we have a virtual base.
+ // FIXME: It would be better if CXXBasePath had the base specifier for
+ // the nearest virtual base.
+ unsigned Start = 0;
+ for (unsigned I = Path.size(); I != 0; --I) {
+ if (Path[I - 1].Base->isVirtual()) {
+ Start = I - 1;
+ break;
+ }
+ }
+
+ // Now add all bases.
+ for (unsigned I = Start, E = Path.size(); I != E; ++I)
+ BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
+}
+
+/// \brief Determine whether the given base path includes a virtual
+/// base class.
+bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) {
+ for (CXXCastPath::const_iterator B = BasePath.begin(),
+ BEnd = BasePath.end();
+ B != BEnd; ++B)
+ if ((*B)->isVirtual())
+ return true;
+
+ return false;
+}
+
+/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
+/// conversion (where Derived and Base are class types) is
+/// well-formed, meaning that the conversion is unambiguous (and
+/// that all of the base classes are accessible). Returns true
+/// and emits a diagnostic if the code is ill-formed, returns false
+/// otherwise. Loc is the location where this routine should point to
+/// if there is an error, and Range is the source range to highlight
+/// if there is an error.
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ unsigned InaccessibleBaseID,
+ unsigned AmbigiousBaseConvID,
+ SourceLocation Loc, SourceRange Range,
+ DeclarationName Name,
+ CXXCastPath *BasePath) {
+ // First, determine whether the path from Derived to Base is
+ // ambiguous. This is slightly more expensive than checking whether
+ // the Derived to Base conversion exists, because here we need to
+ // explore multiple paths to determine if there is an ambiguity.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
+ assert(DerivationOkay &&
+ "Can only be used with a derived-to-base conversion");
+ (void)DerivationOkay;
+
+ if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
+ if (InaccessibleBaseID) {
+ // Check that the base class can be accessed.
+ switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(),
+ InaccessibleBaseID)) {
+ case AR_inaccessible:
+ return true;
+ case AR_accessible:
+ case AR_dependent:
+ case AR_delayed:
+ break;
+ }
+ }
+
+ // Build a base path if necessary.
+ if (BasePath)
+ BuildBasePathArray(Paths, *BasePath);
+ return false;
+ }
+
+ // We know that the derived-to-base conversion is ambiguous, and
+ // we're going to produce a diagnostic. Perform the derived-to-base
+ // search just one more time to compute all of the possible paths so
+ // that we can print them out. This is more expensive than any of
+ // the previous derived-to-base checks we've done, but at this point
+ // performance isn't as much of an issue.
+ Paths.clear();
+ Paths.setRecordingPaths(true);
+ bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+ assert(StillOkay && "Can only be used with a derived-to-base conversion");
+ (void)StillOkay;
+
+ // Build up a textual representation of the ambiguous paths, e.g.,
+ // D -> B -> A, that will be used to illustrate the ambiguous
+ // conversions in the diagnostic. We only print one of the paths
+ // to each base class subobject.
+ std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+
+ Diag(Loc, AmbigiousBaseConvID)
+ << Derived << Base << PathDisplayStr << Range << Name;
+ return true;
+}
+
+bool
+Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ SourceLocation Loc, SourceRange Range,
+ CXXCastPath *BasePath,
+ bool IgnoreAccess) {
+ return CheckDerivedToBaseConversion(Derived, Base,
+ IgnoreAccess ? 0
+ : diag::err_upcast_to_inaccessible_base,
+ diag::err_ambiguous_derived_to_base_conv,
+ Loc, Range, DeclarationName(),
+ BasePath);
+}
+
+
+/// @brief Builds a string representing ambiguous paths from a
+/// specific derived class to different subobjects of the same base
+/// class.
+///
+/// This function builds a string that can be used in error messages
+/// to show the different paths that one can take through the
+/// inheritance hierarchy to go from the derived class to different
+/// subobjects of a base class. The result looks something like this:
+/// @code
+/// struct D -> struct B -> struct A
+/// struct D -> struct C -> struct A
+/// @endcode
+std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
+ std::string PathDisplayStr;
+ std::set<unsigned> DisplayedPaths;
+ for (CXXBasePaths::paths_iterator Path = Paths.begin();
+ Path != Paths.end(); ++Path) {
+ if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
+ // We haven't displayed a path to this particular base
+ // class subobject yet.
+ PathDisplayStr += "\n ";
+ PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
+ for (CXXBasePath::const_iterator Element = Path->begin();
+ Element != Path->end(); ++Element)
+ PathDisplayStr += " -> " + Element->Base->getType().getAsString();
+ }
+ }
+
+ return PathDisplayStr;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ class member Handling
+//===----------------------------------------------------------------------===//
+
+/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
+Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc) {
+ assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
+ AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
+ ASLoc, ColonLoc);
+ CurContext->addHiddenDecl(ASDecl);
+ return ASDecl;
+}
+
+/// CheckOverrideControl - Check C++0x override control semantics.
+void Sema::CheckOverrideControl(const Decl *D) {
+ const CXXMethodDecl *MD = llvm::dyn_cast<CXXMethodDecl>(D);
+ if (!MD || !MD->isVirtual())
+ return;
+
+ if (MD->isDependentContext())
+ return;
+
+ // C++0x [class.virtual]p3:
+ // If a virtual function is marked with the virt-specifier override and does
+ // not override a member function of a base class,
+ // the program is ill-formed.
+ bool HasOverriddenMethods =
+ MD->begin_overridden_methods() != MD->end_overridden_methods();
+ if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) {
+ Diag(MD->getLocation(),
+ diag::err_function_marked_override_not_overriding)
+ << MD->getDeclName();
+ return;
+ }
+
+ // C++0x [class.derived]p8:
+ // In a class definition marked with the class-virt-specifier explicit,
+ // if a virtual member function that is neither implicitly-declared nor a
+ // destructor overrides a member function of a base class and it is not
+ // marked with the virt-specifier override, the program is ill-formed.
+ if (MD->getParent()->hasAttr<ExplicitAttr>() && !isa<CXXDestructorDecl>(MD) &&
+ HasOverriddenMethods && !MD->hasAttr<OverrideAttr>()) {
+ llvm::SmallVector<const CXXMethodDecl*, 4>
+ OverriddenMethods(MD->begin_overridden_methods(),
+ MD->end_overridden_methods());
+
+ Diag(MD->getLocation(), diag::err_function_overriding_without_override)
+ << MD->getDeclName()
+ << (unsigned)OverriddenMethods.size();
+
+ for (unsigned I = 0; I != OverriddenMethods.size(); ++I)
+ Diag(OverriddenMethods[I]->getLocation(),
+ diag::note_overridden_virtual_function);
+ }
+}
+
+/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
+/// function overrides a virtual member function marked 'final', according to
+/// C++0x [class.virtual]p3.
+bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old) {
+ if (!Old->hasAttr<FinalAttr>())
+ return false;
+
+ Diag(New->getLocation(), diag::err_final_function_overridden)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+}
+
+/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
+/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
+/// bitfield width if there is one and 'InitExpr' specifies the initializer if
+/// any.
+Decl *
+Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ ExprTy *BW, const VirtSpecifiers &VS,
+ ExprTy *InitExpr, bool IsDefinition,
+ bool Deleted) {
+ const DeclSpec &DS = D.getDeclSpec();
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ SourceLocation Loc = NameInfo.getLoc();
+
+ // For anonymous bitfields, the location should point to the type.
+ if (Loc.isInvalid())
+ Loc = D.getSourceRange().getBegin();
+
+ Expr *BitWidth = static_cast<Expr*>(BW);
+ Expr *Init = static_cast<Expr*>(InitExpr);
+
+ assert(isa<CXXRecordDecl>(CurContext));
+ assert(!DS.isFriendSpecified());
+
+ bool isFunc = false;
+ if (D.isFunctionDeclarator())
+ isFunc = true;
+ else if (D.getNumTypeObjects() == 0 &&
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) {
+ QualType TDType = GetTypeFromParser(DS.getRepAsType());
+ isFunc = TDType->isFunctionType();
+ }
+
+ // C++ 9.2p6: A member shall not be declared to have automatic storage
+ // duration (auto, register) or with the extern storage-class-specifier.
+ // C++ 7.1.1p8: The mutable specifier can be applied only to names of class
+ // data members and cannot be applied to names declared const or static,
+ // and cannot be applied to reference members.
+ switch (DS.getStorageClassSpec()) {
+ case DeclSpec::SCS_unspecified:
+ case DeclSpec::SCS_typedef:
+ case DeclSpec::SCS_static:
+ // FALL THROUGH.
+ break;
+ case DeclSpec::SCS_mutable:
+ if (isFunc) {
+ if (DS.getStorageClassSpecLoc().isValid())
+ Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
+ else
+ Diag(DS.getThreadSpecLoc(), diag::err_mutable_function);
+
+ // FIXME: It would be nicer if the keyword was ignored only for this
+ // declarator. Otherwise we could get follow-up errors.
+ D.getMutableDeclSpec().ClearStorageClassSpecs();
+ }
+ break;
+ default:
+ if (DS.getStorageClassSpecLoc().isValid())
+ Diag(DS.getStorageClassSpecLoc(),
+ diag::err_storageclass_invalid_for_member);
+ else
+ Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member);
+ D.getMutableDeclSpec().ClearStorageClassSpecs();
+ }
+
+ bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
+ DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
+ !isFunc);
+
+ Decl *Member;
+ if (isInstField) {
+ CXXScopeSpec &SS = D.getCXXScopeSpec();
+
+
+ if (SS.isSet() && !SS.isInvalid()) {
+ // The user provided a superfluous scope specifier inside a class
+ // definition:
+ //
+ // class X {
+ // int X::member;
+ // };
+ DeclContext *DC = 0;
+ if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext))
+ Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
+ << Name << FixItHint::CreateRemoval(SS.getRange());
+ else
+ Diag(D.getIdentifierLoc(), diag::err_member_qualification)
+ << Name << SS.getRange();
+
+ SS.clear();
+ }
+
+ // FIXME: Check for template parameters!
+ // FIXME: Check that the name is an identifier!
+ Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
+ AS);
+ assert(Member && "HandleField never returns null");
+ } else {
+ Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
+ if (!Member) {
+ return 0;
+ }
+
+ // Non-instance-fields can't have a bitfield.
+ if (BitWidth) {
+ if (Member->isInvalidDecl()) {
+ // don't emit another diagnostic.
+ } else if (isa<VarDecl>(Member)) {
+ // C++ 9.6p3: A bit-field shall not be a static member.
+ // "static member 'A' cannot be a bit-field"
+ Diag(Loc, diag::err_static_not_bitfield)
+ << Name << BitWidth->getSourceRange();
+ } else if (isa<TypedefDecl>(Member)) {
+ // "typedef member 'x' cannot be a bit-field"
+ Diag(Loc, diag::err_typedef_not_bitfield)
+ << Name << BitWidth->getSourceRange();
+ } else {
+ // A function typedef ("typedef int f(); f a;").
+ // C++ 9.6p3: A bit-field shall have integral or enumeration type.
+ Diag(Loc, diag::err_not_integral_type_bitfield)
+ << Name << cast<ValueDecl>(Member)->getType()
+ << BitWidth->getSourceRange();
+ }
+
+ BitWidth = 0;
+ Member->setInvalidDecl();
+ }
+
+ Member->setAccess(AS);
+
+ // If we have declared a member function template, set the access of the
+ // templated declaration as well.
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+ FunTmpl->getTemplatedDecl()->setAccess(AS);
+ }
+
+ if (VS.isOverrideSpecified()) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
+ if (!MD || !MD->isVirtual()) {
+ Diag(Member->getLocStart(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc());
+ } else
+ MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context));
+ }
+ if (VS.isFinalSpecified()) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
+ if (!MD || !MD->isVirtual()) {
+ Diag(Member->getLocStart(),
+ diag::override_keyword_only_allowed_on_virtual_member_functions)
+ << "final" << FixItHint::CreateRemoval(VS.getFinalLoc());
+ } else
+ MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
+ }
+
+ CheckOverrideControl(Member);
+
+ assert((Name || isInstField) && "No identifier for non-field ?");
+
+ if (Init)
+ AddInitializerToDecl(Member, Init, false,
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+ if (Deleted) // FIXME: Source location is not very good.
+ SetDeclDeleted(Member, D.getSourceRange().getBegin());
+
+ if (isInstField)
+ FieldCollector->Add(cast<FieldDecl>(Member));
+ return Member;
+}
+
+/// \brief Find the direct and/or virtual base specifiers that
+/// correspond to the given base type, for use in base initialization
+/// within a constructor.
+static bool FindBaseInitializer(Sema &SemaRef,
+ CXXRecordDecl *ClassDecl,
+ QualType BaseType,
+ const CXXBaseSpecifier *&DirectBaseSpec,
+ const CXXBaseSpecifier *&VirtualBaseSpec) {
+ // First, check for a direct base class.
+ DirectBaseSpec = 0;
+ for (CXXRecordDecl::base_class_const_iterator Base
+ = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+ // We found a direct base of this type. That's what we're
+ // initializing.
+ DirectBaseSpec = &*Base;
+ break;
+ }
+ }
+
+ // Check for a virtual base class.
+ // FIXME: We might be able to short-circuit this if we know in advance that
+ // there are no virtual bases.
+ VirtualBaseSpec = 0;
+ if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
+ // We haven't found a base yet; search the class hierarchy for a
+ // virtual base class.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl),
+ BaseType, Paths)) {
+ for (CXXBasePaths::paths_iterator Path = Paths.begin();
+ Path != Paths.end(); ++Path) {
+ if (Path->back().Base->isVirtual()) {
+ VirtualBaseSpec = Path->back().Base;
+ break;
+ }
+ }
+ }
+ }
+
+ return DirectBaseSpec || VirtualBaseSpec;
+}
+
+/// ActOnMemInitializer - Handle a C++ member initializer.
+MemInitResult
+Sema::ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ ExprTy **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ SourceLocation EllipsisLoc) {
+ if (!ConstructorD)
+ return true;
+
+ AdjustDeclIfTemplate(ConstructorD);
+
+ CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(ConstructorD);
+ if (!Constructor) {
+ // The user wrote a constructor initializer on a function that is
+ // not a C++ constructor. Ignore the error for now, because we may
+ // have more member initializers coming; we'll diagnose it just
+ // once in ActOnMemInitializers.
+ return true;
+ }
+
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+ // C++ [class.base.init]p2:
+ // Names in a mem-initializer-id are looked up in the scope of the
+ // constructor's class and, if not found in that scope, are looked
+ // up in the scope containing the constructor's definition.
+ // [Note: if the constructor's class contains a member with the
+ // same name as a direct or virtual base class of the class, a
+ // mem-initializer-id naming the member or base class and composed
+ // of a single identifier refers to the class member. A
+ // mem-initializer-id for the hidden base class may be specified
+ // using a qualified name. ]
+ if (!SS.getScopeRep() && !TemplateTypeTy) {
+ // Look for a member, first.
+ FieldDecl *Member = 0;
+ DeclContext::lookup_result Result
+ = ClassDecl->lookup(MemberOrBase);
+ if (Result.first != Result.second) {
+ Member = dyn_cast<FieldDecl>(*Result.first);
+
+ if (Member) {
+ if (EllipsisLoc.isValid())
+ Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+ << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+
+ return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+ LParenLoc, RParenLoc);
+ }
+
+ // Handle anonymous union case.
+ if (IndirectFieldDecl* IndirectField
+ = dyn_cast<IndirectFieldDecl>(*Result.first)) {
+ if (EllipsisLoc.isValid())
+ Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+ << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+
+ return BuildMemberInitializer(IndirectField, (Expr**)Args,
+ NumArgs, IdLoc,
+ LParenLoc, RParenLoc);
+ }
+ }
+ }
+ // It didn't name a member, so see if it names a class.
+ QualType BaseType;
+ TypeSourceInfo *TInfo = 0;
+
+ if (TemplateTypeTy) {
+ BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
+ } else {
+ LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
+ LookupParsedName(R, S, &SS);
+
+ TypeDecl *TyD = R.getAsSingle<TypeDecl>();
+ if (!TyD) {
+ if (R.isAmbiguous()) return true;
+
+ // We don't want access-control diagnostics here.
+ R.suppressDiagnostics();
+
+ if (SS.isSet() && isDependentScopeSpecifier(SS)) {
+ bool NotUnknownSpecialization = false;
+ DeclContext *DC = computeDeclContext(SS, false);
+ if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
+ NotUnknownSpecialization = !Record->hasAnyDependentBases();
+
+ if (!NotUnknownSpecialization) {
+ // When the scope specifier can refer to a member of an unknown
+ // specialization, we take it as a type name.
+ BaseType = CheckTypenameType(ETK_None,
+ (NestedNameSpecifier *)SS.getScopeRep(),
+ *MemberOrBase, SourceLocation(),
+ SS.getRange(), IdLoc);
+ if (BaseType.isNull())
+ return true;
+
+ R.clear();
+ R.setLookupName(MemberOrBase);
+ }
+ }
+
+ // If no results were found, try to correct typos.
+ if (R.empty() && BaseType.isNull() &&
+ CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) &&
+ R.isSingleResult()) {
+ if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
+ if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
+ // We have found a non-static data member with a similar
+ // name to what was typed; complain and initialize that
+ // member.
+ Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << true << R.getLookupName()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ Diag(Member->getLocation(), diag::note_previous_decl)
+ << Member->getDeclName();
+
+ return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+ LParenLoc, RParenLoc);
+ }
+ } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {
+ const CXXBaseSpecifier *DirectBaseSpec;
+ const CXXBaseSpecifier *VirtualBaseSpec;
+ if (FindBaseInitializer(*this, ClassDecl,
+ Context.getTypeDeclType(Type),
+ DirectBaseSpec, VirtualBaseSpec)) {
+ // We have found a direct or virtual base class with a
+ // similar name to what was typed; complain and initialize
+ // that base class.
+ Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+ << MemberOrBase << false << R.getLookupName()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+
+ const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec
+ : VirtualBaseSpec;
+ Diag(BaseSpec->getSourceRange().getBegin(),
+ diag::note_base_class_specified_here)
+ << BaseSpec->getType()
+ << BaseSpec->getSourceRange();
+
+ TyD = Type;
+ }
+ }
+ }
+
+ if (!TyD && BaseType.isNull()) {
+ Diag(IdLoc, diag::err_mem_init_not_member_or_class)
+ << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ return true;
+ }
+ }
+
+ if (BaseType.isNull()) {
+ BaseType = Context.getTypeDeclType(TyD);
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier =
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+ // FIXME: preserve source range information
+ BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType);
+ }
+ }
+ }
+
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
+
+ return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs,
+ LParenLoc, RParenLoc, ClassDecl, EllipsisLoc);
+}
+
+/// Checks an initializer expression for use of uninitialized fields, such as
+/// containing the field that is being initialized. Returns true if there is an
+/// uninitialized field was used an updates the SourceLocation parameter; false
+/// otherwise.
+static bool InitExprContainsUninitializedFields(const Stmt *S,
+ const ValueDecl *LhsField,
+ SourceLocation *L) {
+ assert(isa<FieldDecl>(LhsField) || isa<IndirectFieldDecl>(LhsField));
+
+ if (isa<CallExpr>(S)) {
+ // Do not descend into function calls or constructors, as the use
+ // of an uninitialized field may be valid. One would have to inspect
+ // the contents of the function/ctor to determine if it is safe or not.
+ // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+ // may be safe, depending on what the function/ctor does.
+ return false;
+ }
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
+ const NamedDecl *RhsField = ME->getMemberDecl();
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(RhsField)) {
+ // The member expression points to a static data member.
+ assert(VD->isStaticDataMember() &&
+ "Member points to non-static data member!");
+ (void)VD;
+ return false;
+ }
+
+ if (isa<EnumConstantDecl>(RhsField)) {
+ // The member expression points to an enum.
+ return false;
+ }
+
+ if (RhsField == LhsField) {
+ // Initializing a field with itself. Throw a warning.
+ // But wait; there are exceptions!
+ // Exception #1: The field may not belong to this record.
+ // e.g. Foo(const Foo& rhs) : A(rhs.A) {}
+ const Expr *base = ME->getBase();
+ if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
+ // Even though the field matches, it does not belong to this record.
+ return false;
+ }
+ // None of the exceptions triggered; return true to indicate an
+ // uninitialized field was used.
+ *L = ME->getMemberLoc();
+ return true;
+ }
+ } else if (isa<SizeOfAlignOfExpr>(S)) {
+ // sizeof/alignof doesn't reference contents, do not warn.
+ return false;
+ } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) {
+ // address-of doesn't reference contents (the pointer may be dereferenced
+ // in the same expression but it would be rare; and weird).
+ if (UOE->getOpcode() == UO_AddrOf)
+ return false;
+ }
+ for (Stmt::const_child_range it = S->children(); it; ++it) {
+ if (!*it) {
+ // An expression such as 'member(arg ?: "")' may trigger this.
+ continue;
+ }
+ if (InitExprContainsUninitializedFields(*it, LhsField, L))
+ return true;
+ }
+ return false;
+}
+
+MemInitResult
+Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
+ unsigned NumArgs, SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
+ IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
+ assert((DirectMember || IndirectMember) &&
+ "Member must be a FieldDecl or IndirectFieldDecl");
+
+ if (Member->isInvalidDecl())
+ return true;
+
+ // Diagnose value-uses of fields to initialize themselves, e.g.
+ // foo(foo)
+ // where foo is not also a parameter to the constructor.
+ // TODO: implement -Wuninitialized and fold this into that framework.
+ for (unsigned i = 0; i < NumArgs; ++i) {
+ SourceLocation L;
+ if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+ // FIXME: Return true in the case when other fields are used before being
+ // uninitialized. For example, let this field be the i'th field. When
+ // initializing the i'th field, throw a warning if any of the >= i'th
+ // fields are used, as they are not yet initialized.
+ // Right now we are only handling the case where the i'th field uses
+ // itself in its initializer.
+ Diag(L, diag::warn_field_is_uninit);
+ }
+ }
+
+ bool HasDependentArg = false;
+ for (unsigned i = 0; i < NumArgs; i++)
+ HasDependentArg |= Args[i]->isTypeDependent();
+
+ Expr *Init;
+ if (Member->getType()->isDependentType() || HasDependentArg) {
+ // Can't check initialization for a member of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+ } else {
+ // Initialize the member.
+ InitializedEntity MemberEntity =
+ DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
+ : InitializedEntity::InitializeMember(IndirectMember, 0);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+
+ ExprResult MemberInit =
+ InitSeq.Perform(*this, MemberEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs), 0);
+ if (MemberInit.isInvalid())
+ return true;
+
+ CheckImplicitConversions(MemberInit.get(), LParenLoc);
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ MemberInit = MaybeCreateExprWithCleanups(MemberInit);
+ if (MemberInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the member
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext())
+ Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
+ else
+ Init = MemberInit.get();
+ }
+
+ if (DirectMember) {
+ return new (Context) CXXCtorInitializer(Context, DirectMember,
+ IdLoc, LParenLoc, Init,
+ RParenLoc);
+ } else {
+ return new (Context) CXXCtorInitializer(Context, IndirectMember,
+ IdLoc, LParenLoc, Init,
+ RParenLoc);
+ }
+}
+
+MemInitResult
+Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc) {
+ SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
+ if (!LangOpts.CPlusPlus0x)
+ return Diag(Loc, diag::err_delegation_0x_only)
+ << TInfo->getTypeLoc().getLocalSourceRange();
+
+ return Diag(Loc, diag::err_delegation_unimplemented)
+ << TInfo->getTypeLoc().getLocalSourceRange();
+}
+
+MemInitResult
+Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation LParenLoc, SourceLocation RParenLoc,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc) {
+ bool HasDependentArg = false;
+ for (unsigned i = 0; i < NumArgs; i++)
+ HasDependentArg |= Args[i]->isTypeDependent();
+
+ SourceLocation BaseLoc
+ = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
+
+ if (!BaseType->isDependentType() && !BaseType->isRecordType())
+ return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+ << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
+
+ // C++ [class.base.init]p2:
+ // [...] Unless the mem-initializer-id names a nonstatic data
+ // member of the constructor's class or a direct or virtual base
+ // of that class, the mem-initializer is ill-formed. A
+ // mem-initializer-list can initialize a base class using any
+ // name that denotes that base class type.
+ bool Dependent = BaseType->isDependentType() || HasDependentArg;
+
+ if (EllipsisLoc.isValid()) {
+ // This is a pack expansion.
+ if (!BaseType->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << SourceRange(BaseLoc, RParenLoc);
+
+ EllipsisLoc = SourceLocation();
+ }
+ } else {
+ // Check for any unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
+ return true;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (DiagnoseUnexpandedParameterPack(Args[I]))
+ return true;
+ }
+
+ // Check for direct and virtual base classes.
+ const CXXBaseSpecifier *DirectBaseSpec = 0;
+ const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ if (!Dependent) {
+ if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
+ BaseType))
+ return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs,
+ LParenLoc, RParenLoc, ClassDecl,
+ EllipsisLoc);
+
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ VirtualBaseSpec);
+
+ // C++ [base.class.init]p2:
+ // Unless the mem-initializer-id names a nonstatic data member of the
+ // constructor's class or a direct or virtual base of that class, the
+ // mem-initializer is ill-formed.
+ if (!DirectBaseSpec && !VirtualBaseSpec) {
+ // If the class has any dependent bases, then it's possible that
+ // one of those types will resolve to the same type as
+ // BaseType. Therefore, just treat this as a dependent base
+ // class initialization. FIXME: Should we try to check the
+ // initialization anyway? It seems odd.
+ if (ClassDecl->hasAnyDependentBases())
+ Dependent = true;
+ else
+ return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+ << BaseType << Context.getTypeDeclType(ClassDecl)
+ << BaseTInfo->getTypeLoc().getLocalSourceRange();
+ }
+ }
+
+ if (Dependent) {
+ // Can't check initialization for a base of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ ExprResult BaseInit
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+
+ return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+ /*IsVirtual=*/false,
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc,
+ EllipsisLoc);
+ }
+
+ // C++ [base.class.init]p2:
+ // If a mem-initializer-id is ambiguous because it designates both
+ // a direct non-virtual base class and an inherited virtual base
+ // class, the mem-initializer is ill-formed.
+ if (DirectBaseSpec && VirtualBaseSpec)
+ return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+ << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
+
+ CXXBaseSpecifier *BaseSpec
+ = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ if (!BaseSpec)
+ BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+ // Initialize the base.
+ InitializedEntity BaseEntity =
+ InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+
+ ExprResult BaseInit =
+ InitSeq.Perform(*this, BaseEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs), 0);
+ if (BaseInit.isInvalid())
+ return true;
+
+ CheckImplicitConversions(BaseInit.get(), LParenLoc);
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ BaseInit = MaybeCreateExprWithCleanups(BaseInit);
+ if (BaseInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the base
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ ExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+ return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+ BaseSpec->isVirtual(),
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc,
+ EllipsisLoc);
+ }
+
+ return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+ BaseSpec->isVirtual(),
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc,
+ EllipsisLoc);
+}
+
+/// ImplicitInitializerKind - How an implicit base or member initializer should
+/// initialize its base or member.
+enum ImplicitInitializerKind {
+ IIK_Default,
+ IIK_Copy,
+ IIK_Move
+};
+
+static bool
+BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
+ ImplicitInitializerKind ImplicitInitKind,
+ CXXBaseSpecifier *BaseSpec,
+ bool IsInheritedVirtualBase,
+ CXXCtorInitializer *&CXXBaseInit) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
+ IsInheritedVirtualBase);
+
+ ExprResult BaseInit;
+
+ switch (ImplicitInitKind) {
+ case IIK_Default: {
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
+ BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
+ MultiExprArg(SemaRef, 0, 0));
+ break;
+ }
+
+ case IIK_Copy: {
+ ParmVarDecl *Param = Constructor->getParamDecl(0);
+ QualType ParamType = Param->getType().getNonReferenceType();
+
+ Expr *CopyCtorArg =
+ DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
+ Constructor->getLocation(), ParamType,
+ VK_LValue, 0);
+
+ // Cast to the base class to avoid ambiguities.
+ QualType ArgTy =
+ SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
+ ParamType.getQualifiers());
+
+ CXXCastPath BasePath;
+ BasePath.push_back(BaseSpec);
+ SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
+
+ InitializationKind InitKind
+ = InitializationKind::CreateDirect(Constructor->getLocation(),
+ SourceLocation(), SourceLocation());
+ InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,
+ &CopyCtorArg, 1);
+ BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
+ MultiExprArg(&CopyCtorArg, 1));
+ break;
+ }
+
+ case IIK_Move:
+ assert(false && "Unhandled initializer kind!");
+ }
+
+ BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit);
+ if (BaseInit.isInvalid())
+ return true;
+
+ CXXBaseInit =
+ new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
+ SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(),
+ SourceLocation()),
+ BaseSpec->isVirtual(),
+ SourceLocation(),
+ BaseInit.takeAs<Expr>(),
+ SourceLocation(),
+ SourceLocation());
+
+ return false;
+}
+
+static bool
+BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
+ ImplicitInitializerKind ImplicitInitKind,
+ FieldDecl *Field,
+ CXXCtorInitializer *&CXXMemberInit) {
+ if (Field->isInvalidDecl())
+ return true;
+
+ SourceLocation Loc = Constructor->getLocation();
+
+ if (ImplicitInitKind == IIK_Copy) {
+ ParmVarDecl *Param = Constructor->getParamDecl(0);
+ QualType ParamType = Param->getType().getNonReferenceType();
+
+ Expr *MemberExprBase =
+ DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
+ Loc, ParamType, VK_LValue, 0);
+
+ // Build a reference to this field within the parameter.
+ CXXScopeSpec SS;
+ LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
+ Sema::LookupMemberName);
+ MemberLookup.addDecl(Field, AS_public);
+ MemberLookup.resolveKind();
+ ExprResult CopyCtorArg
+ = SemaRef.BuildMemberReferenceExpr(MemberExprBase,
+ ParamType, Loc,
+ /*IsArrow=*/false,
+ SS,
+ /*FirstQualifierInScope=*/0,
+ MemberLookup,
+ /*TemplateArgs=*/0);
+ if (CopyCtorArg.isInvalid())
+ return true;
+
+ // When the field we are copying is an array, create index variables for
+ // each dimension of the array. We use these index variables to subscript
+ // the source array, and other clients (e.g., CodeGen) will perform the
+ // necessary iteration with these index variables.
+ llvm::SmallVector<VarDecl *, 4> IndexVariables;
+ QualType BaseType = Field->getType();
+ QualType SizeType = SemaRef.Context.getSizeType();
+ while (const ConstantArrayType *Array
+ = SemaRef.Context.getAsConstantArrayType(BaseType)) {
+ // Create the iteration variable for this array index.
+ IdentifierInfo *IterationVarName = 0;
+ {
+ llvm::SmallString<8> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "__i" << IndexVariables.size();
+ IterationVarName = &SemaRef.Context.Idents.get(OS.str());
+ }
+ VarDecl *IterationVar
+ = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc,
+ IterationVarName, SizeType,
+ SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+ SC_None, SC_None);
+ IndexVariables.push_back(IterationVar);
+
+ // Create a reference to the iteration variable.
+ ExprResult IterationVarRef
+ = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc);
+ assert(!IterationVarRef.isInvalid() &&
+ "Reference to invented variable cannot fail!");
+
+ // Subscript the array with this iteration variable.
+ CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CopyCtorArg.take(),
+ Loc,
+ IterationVarRef.take(),
+ Loc);
+ if (CopyCtorArg.isInvalid())
+ return true;
+
+ BaseType = Array->getElementType();
+ }
+
+ // Construct the entity that we will be initializing. For an array, this
+ // will be first element in the array, which may require several levels
+ // of array-subscript entities.
+ llvm::SmallVector<InitializedEntity, 4> Entities;
+ Entities.reserve(1 + IndexVariables.size());
+ Entities.push_back(InitializedEntity::InitializeMember(Field));
+ for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+ Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
+ 0,
+ Entities.back()));
+
+ // Direct-initialize to use the copy constructor.
+ InitializationKind InitKind =
+ InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
+
+ Expr *CopyCtorArgE = CopyCtorArg.takeAs<Expr>();
+ InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
+ &CopyCtorArgE, 1);
+
+ ExprResult MemberInit
+ = InitSeq.Perform(SemaRef, Entities.back(), InitKind,
+ MultiExprArg(&CopyCtorArgE, 1));
+ MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
+ if (MemberInit.isInvalid())
+ return true;
+
+ CXXMemberInit
+ = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, Loc,
+ MemberInit.takeAs<Expr>(), Loc,
+ IndexVariables.data(),
+ IndexVariables.size());
+ return false;
+ }
+
+ assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!");
+
+ QualType FieldBaseElementType =
+ SemaRef.Context.getBaseElementType(Field->getType());
+
+ if (FieldBaseElementType->isRecordType()) {
+ InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+ InitializationKind InitKind =
+ InitializationKind::CreateDefault(Loc);
+
+ InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
+ ExprResult MemberInit =
+ InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg());
+
+ MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
+ if (MemberInit.isInvalid())
+ return true;
+
+ CXXMemberInit =
+ new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
+ Field, Loc, Loc,
+ MemberInit.get(),
+ Loc);
+ return false;
+ }
+
+ if (FieldBaseElementType->isReferenceType()) {
+ SemaRef.Diag(Constructor->getLocation(),
+ diag::err_uninitialized_member_in_ctor)
+ << (int)Constructor->isImplicit()
+ << SemaRef.Context.getTagDeclType(Constructor->getParent())
+ << 0 << Field->getDeclName();
+ SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ if (FieldBaseElementType.isConstQualified()) {
+ SemaRef.Diag(Constructor->getLocation(),
+ diag::err_uninitialized_member_in_ctor)
+ << (int)Constructor->isImplicit()
+ << SemaRef.Context.getTagDeclType(Constructor->getParent())
+ << 1 << Field->getDeclName();
+ SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // Nothing to initialize.
+ CXXMemberInit = 0;
+ return false;
+}
+
+namespace {
+struct BaseAndFieldInfo {
+ Sema &S;
+ CXXConstructorDecl *Ctor;
+ bool AnyErrorsInInits;
+ ImplicitInitializerKind IIK;
+ llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
+ llvm::SmallVector<CXXCtorInitializer*, 8> AllToInit;
+
+ BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
+ : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
+ // FIXME: Handle implicit move constructors.
+ if (Ctor->isImplicit() && Ctor->isCopyConstructor())
+ IIK = IIK_Copy;
+ else
+ IIK = IIK_Default;
+ }
+};
+}
+
+static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
+ FieldDecl *Top, FieldDecl *Field) {
+
+ // Overwhelmingly common case: we have a direct initializer for this field.
+ if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) {
+ Info.AllToInit.push_back(Init);
+ return false;
+ }
+
+ if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
+ const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
+ assert(FieldClassType && "anonymous struct/union without record type");
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+
+ // Even though union members never have non-trivial default
+ // constructions in C++03, we still build member initializers for aggregate
+ // record types which can be union members, and C++0x allows non-trivial
+ // default constructors for union members, so we ensure that only one
+ // member is initialized for these.
+ if (FieldClassDecl->isUnion()) {
+ // First check for an explicit initializer for one field.
+ for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+ EA = FieldClassDecl->field_end(); FA != EA; FA++) {
+ if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(*FA)) {
+ Info.AllToInit.push_back(Init);
+
+ // Once we've initialized a field of an anonymous union, the union
+ // field in the class is also initialized, so exit immediately.
+ return false;
+ } else if ((*FA)->isAnonymousStructOrUnion()) {
+ if (CollectFieldInitializer(Info, Top, *FA))
+ return true;
+ }
+ }
+
+ // Fallthrough and construct a default initializer for the union as
+ // a whole, which can call its default constructor if such a thing exists
+ // (C++0x perhaps). FIXME: It's not clear that this is the correct
+ // behavior going forward with C++0x, when anonymous unions there are
+ // finalized, we should revisit this.
+ } else {
+ // For structs, we simply descend through to initialize all members where
+ // necessary.
+ for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+ EA = FieldClassDecl->field_end(); FA != EA; FA++) {
+ if (CollectFieldInitializer(Info, Top, *FA))
+ return true;
+ }
+ }
+ }
+
+ // Don't try to build an implicit initializer if there were semantic
+ // errors in any of the initializers (and therefore we might be
+ // missing some that the user actually wrote).
+ if (Info.AnyErrorsInInits)
+ return false;
+
+ CXXCtorInitializer *Init = 0;
+ if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init))
+ return true;
+
+ if (Init)
+ Info.AllToInit.push_back(Init);
+
+ return false;
+}
+
+bool
+Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer **Initializers,
+ unsigned NumInitializers,
+ bool AnyErrors) {
+ if (Constructor->getDeclContext()->isDependentContext()) {
+ // Just store the initializers as written, they will be checked during
+ // instantiation.
+ if (NumInitializers > 0) {
+ Constructor->setNumCtorInitializers(NumInitializers);
+ CXXCtorInitializer **baseOrMemberInitializers =
+ new (Context) CXXCtorInitializer*[NumInitializers];
+ memcpy(baseOrMemberInitializers, Initializers,
+ NumInitializers * sizeof(CXXCtorInitializer*));
+ Constructor->setCtorInitializers(baseOrMemberInitializers);
+ }
+
+ return false;
+ }
+
+ BaseAndFieldInfo Info(*this, Constructor, AnyErrors);
+
+ // We need to build the initializer AST according to order of construction
+ // and not what user specified in the Initializers list.
+ CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
+ if (!ClassDecl)
+ return true;
+
+ bool HadError = false;
+
+ for (unsigned i = 0; i < NumInitializers; i++) {
+ CXXCtorInitializer *Member = Initializers[i];
+
+ if (Member->isBaseInitializer())
+ Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
+ else
+ Info.AllBaseFields[Member->getAnyMember()] = Member;
+ }
+
+ // Keep track of the direct virtual bases.
+ llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
+ for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ DirectVBases.insert(I);
+ }
+
+ // Push virtual bases before others.
+ for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+
+ if (CXXCtorInitializer *Value
+ = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ Info.AllToInit.push_back(Value);
+ } else if (!AnyErrors) {
+ bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
+ CXXCtorInitializer *CXXBaseInit;
+ if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
+ VBase, IsInheritedVirtualBase,
+ CXXBaseInit)) {
+ HadError = true;
+ continue;
+ }
+
+ Info.AllToInit.push_back(CXXBaseInit);
+ }
+ }
+
+ // Non-virtual bases.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // Virtuals are in the virtual base list and already constructed.
+ if (Base->isVirtual())
+ continue;
+
+ if (CXXCtorInitializer *Value
+ = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
+ Info.AllToInit.push_back(Value);
+ } else if (!AnyErrors) {
+ CXXCtorInitializer *CXXBaseInit;
+ if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
+ Base, /*IsInheritedVirtualBase=*/false,
+ CXXBaseInit)) {
+ HadError = true;
+ continue;
+ }
+
+ Info.AllToInit.push_back(CXXBaseInit);
+ }
+ }
+
+ // Fields.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field) {
+ if ((*Field)->getType()->isIncompleteArrayType()) {
+ assert(ClassDecl->hasFlexibleArrayMember() &&
+ "Incomplete array type is not valid");
+ continue;
+ }
+ if (CollectFieldInitializer(Info, *Field, *Field))
+ HadError = true;
+ }
+
+ NumInitializers = Info.AllToInit.size();
+ if (NumInitializers > 0) {
+ Constructor->setNumCtorInitializers(NumInitializers);
+ CXXCtorInitializer **baseOrMemberInitializers =
+ new (Context) CXXCtorInitializer*[NumInitializers];
+ memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
+ NumInitializers * sizeof(CXXCtorInitializer*));
+ Constructor->setCtorInitializers(baseOrMemberInitializers);
+
+ // Constructors implicitly reference the base and member
+ // destructors.
+ MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
+ Constructor->getParent());
+ }
+
+ return HadError;
+}
+
+static void *GetKeyForTopLevelField(FieldDecl *Field) {
+ // For anonymous unions, use the class declaration as the key.
+ if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
+ if (RT->getDecl()->isAnonymousStructOrUnion())
+ return static_cast<void *>(RT->getDecl());
+ }
+ return static_cast<void *>(Field);
+}
+
+static void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
+ return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr());
+}
+
+static void *GetKeyForMember(ASTContext &Context,
+ CXXCtorInitializer *Member) {
+ if (!Member->isAnyMemberInitializer())
+ return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
+
+ // For fields injected into the class via declaration of an anonymous union,
+ // use its anonymous union class declaration as the unique key.
+ FieldDecl *Field = Member->getAnyMember();
+
+ // If the field is a member of an anonymous struct or union, our key
+ // is the anonymous record decl that's a direct child of the class.
+ RecordDecl *RD = Field->getParent();
+ if (RD->isAnonymousStructOrUnion()) {
+ while (true) {
+ RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext());
+ if (Parent->isAnonymousStructOrUnion())
+ RD = Parent;
+ else
+ break;
+ }
+
+ return static_cast<void *>(RD);
+ }
+
+ return static_cast<void *>(Field);
+}
+
+static void
+DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
+ const CXXConstructorDecl *Constructor,
+ CXXCtorInitializer **Inits,
+ unsigned NumInits) {
+ if (Constructor->getDeclContext()->isDependentContext())
+ return;
+
+ // Don't check initializers order unless the warning is enabled at the
+ // location of at least one initializer.
+ bool ShouldCheckOrder = false;
+ for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+ CXXCtorInitializer *Init = Inits[InitIndex];
+ if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order,
+ Init->getSourceLocation())
+ != Diagnostic::Ignored) {
+ ShouldCheckOrder = true;
+ break;
+ }
+ }
+ if (!ShouldCheckOrder)
+ return;
+
+ // Build the list of bases and members in the order that they'll
+ // actually be initialized. The explicit initializers should be in
+ // this same order but may be missing things.
+ llvm::SmallVector<const void*, 32> IdealInitKeys;
+
+ const CXXRecordDecl *ClassDecl = Constructor->getParent();
+
+ // 1. Virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator VBase =
+ ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase)
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType()));
+
+ // 2. Non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
+ if (Base->isVirtual())
+ continue;
+ IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType()));
+ }
+
+ // 3. Direct fields.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field)
+ IdealInitKeys.push_back(GetKeyForTopLevelField(*Field));
+
+ unsigned NumIdealInits = IdealInitKeys.size();
+ unsigned IdealIndex = 0;
+
+ CXXCtorInitializer *PrevInit = 0;
+ for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+ CXXCtorInitializer *Init = Inits[InitIndex];
+ void *InitKey = GetKeyForMember(SemaRef.Context, Init);
+
+ // Scan forward to try to find this initializer in the idealized
+ // initializers list.
+ for (; IdealIndex != NumIdealInits; ++IdealIndex)
+ if (InitKey == IdealInitKeys[IdealIndex])
+ break;
+
+ // If we didn't find this initializer, it must be because we
+ // scanned past it on a previous iteration. That can only
+ // happen if we're out of order; emit a warning.
+ if (IdealIndex == NumIdealInits && PrevInit) {
+ Sema::SemaDiagnosticBuilder D =
+ SemaRef.Diag(PrevInit->getSourceLocation(),
+ diag::warn_initializer_out_of_order);
+
+ if (PrevInit->isAnyMemberInitializer())
+ D << 0 << PrevInit->getAnyMember()->getDeclName();
+ else
+ D << 1 << PrevInit->getBaseClassInfo()->getType();
+
+ if (Init->isAnyMemberInitializer())
+ D << 0 << Init->getAnyMember()->getDeclName();
+ else
+ D << 1 << Init->getBaseClassInfo()->getType();
+
+ // Move back to the initializer's location in the ideal list.
+ for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
+ if (InitKey == IdealInitKeys[IdealIndex])
+ break;
+
+ assert(IdealIndex != NumIdealInits &&
+ "initializer not found in initializer list");
+ }
+
+ PrevInit = Init;
+ }
+}
+
+namespace {
+bool CheckRedundantInit(Sema &S,
+ CXXCtorInitializer *Init,
+ CXXCtorInitializer *&PrevInit) {
+ if (!PrevInit) {
+ PrevInit = Init;
+ return false;
+ }
+
+ if (FieldDecl *Field = Init->getMember())
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_mem_initialization)
+ << Field->getDeclName()
+ << Init->getSourceRange();
+ else {
+ const Type *BaseClass = Init->getBaseClass();
+ assert(BaseClass && "neither field nor base");
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_base_initialization)
+ << QualType(BaseClass, 0)
+ << Init->getSourceRange();
+ }
+ S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer)
+ << 0 << PrevInit->getSourceRange();
+
+ return true;
+}
+
+typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry;
+typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap;
+
+bool CheckRedundantUnionInit(Sema &S,
+ CXXCtorInitializer *Init,
+ RedundantUnionMap &Unions) {
+ FieldDecl *Field = Init->getAnyMember();
+ RecordDecl *Parent = Field->getParent();
+ if (!Parent->isAnonymousStructOrUnion())
+ return false;
+
+ NamedDecl *Child = Field;
+ do {
+ if (Parent->isUnion()) {
+ UnionEntry &En = Unions[Parent];
+ if (En.first && En.first != Child) {
+ S.Diag(Init->getSourceLocation(),
+ diag::err_multiple_mem_union_initialization)
+ << Field->getDeclName()
+ << Init->getSourceRange();
+ S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
+ << 0 << En.second->getSourceRange();
+ return true;
+ } else if (!En.first) {
+ En.first = Child;
+ En.second = Init;
+ }
+ }
+
+ Child = Parent;
+ Parent = cast<RecordDecl>(Parent->getDeclContext());
+ } while (Parent->isAnonymousStructOrUnion());
+
+ return false;
+}
+}
+
+/// ActOnMemInitializers - Handle the member initializers for a constructor.
+void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ MemInitTy **meminits, unsigned NumMemInits,
+ bool AnyErrors) {
+ if (!ConstructorDecl)
+ return;
+
+ AdjustDeclIfTemplate(ConstructorDecl);
+
+ CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(ConstructorDecl);
+
+ if (!Constructor) {
+ Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
+ return;
+ }
+
+ CXXCtorInitializer **MemInits =
+ reinterpret_cast<CXXCtorInitializer **>(meminits);
+
+ // Mapping for the duplicate initializers check.
+ // For member initializers, this is keyed with a FieldDecl*.
+ // For base initializers, this is keyed with a Type*.
+ llvm::DenseMap<void*, CXXCtorInitializer *> Members;
+
+ // Mapping for the inconsistent anonymous-union initializers check.
+ RedundantUnionMap MemberUnions;
+
+ bool HadError = false;
+ for (unsigned i = 0; i < NumMemInits; i++) {
+ CXXCtorInitializer *Init = MemInits[i];
+
+ // Set the source order index.
+ Init->setSourceOrder(i);
+
+ if (Init->isAnyMemberInitializer()) {
+ FieldDecl *Field = Init->getAnyMember();
+ if (CheckRedundantInit(*this, Init, Members[Field]) ||
+ CheckRedundantUnionInit(*this, Init, MemberUnions))
+ HadError = true;
+ } else {
+ void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0));
+ if (CheckRedundantInit(*this, Init, Members[Key]))
+ HadError = true;
+ }
+ }
+
+ if (HadError)
+ return;
+
+ DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits);
+
+ SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors);
+}
+
+void
+Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
+ CXXRecordDecl *ClassDecl) {
+ // Ignore dependent contexts.
+ if (ClassDecl->isDependentContext())
+ return;
+
+ // FIXME: all the access-control diagnostics are positioned on the
+ // field/base declaration. That's probably good; that said, the
+ // user might reasonably want to know why the destructor is being
+ // emitted, and we currently don't say.
+
+ // Non-static data members.
+ for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); I != E; ++I) {
+ FieldDecl *Field = *I;
+ if (Field->isInvalidDecl())
+ continue;
+ QualType FieldType = Context.getBaseElementType(Field->getType());
+
+ const RecordType* RT = FieldType->getAs<RecordType>();
+ if (!RT)
+ continue;
+
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
+ continue;
+
+ CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+ CheckDestructorAccess(Field->getLocation(), Dtor,
+ PDiag(diag::err_access_dtor_field)
+ << Field->getDeclName()
+ << FieldType);
+
+ MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ }
+
+ llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
+
+ // Bases.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // Bases are always records in a well-formed non-dependent class.
+ const RecordType *RT = Base->getType()->getAs<RecordType>();
+
+ // Remember direct virtual bases.
+ if (Base->isVirtual())
+ DirectVirtualBases.insert(RT);
+
+ // Ignore trivial destructors.
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+
+ // FIXME: caret should be on the start of the class name
+ CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor,
+ PDiag(diag::err_access_dtor_base)
+ << Base->getType()
+ << Base->getSourceRange());
+
+ MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ }
+
+ // Virtual bases.
+ for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); VBase != E; ++VBase) {
+
+ // Bases are always records in a well-formed non-dependent class.
+ const RecordType *RT = VBase->getType()->getAs<RecordType>();
+
+ // Ignore direct virtual bases.
+ if (DirectVirtualBases.count(RT))
+ continue;
+
+ // Ignore trivial destructors.
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
+ CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
+ PDiag(diag::err_access_dtor_vbase)
+ << VBase->getType());
+
+ MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ }
+}
+
+void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
+ if (!CDtorDecl)
+ return;
+
+ if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(CDtorDecl))
+ SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false);
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+ unsigned DiagID, AbstractDiagSelID SelID) {
+ if (SelID == -1)
+ return RequireNonAbstractType(Loc, T, PDiag(DiagID));
+ else
+ return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID);
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD) {
+ if (!getLangOptions().CPlusPlus)
+ return false;
+
+ if (const ArrayType *AT = Context.getAsArrayType(T))
+ return RequireNonAbstractType(Loc, AT->getElementType(), PD);
+
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ // Find the innermost pointer type.
+ while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
+ PT = T;
+
+ if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
+ return RequireNonAbstractType(Loc, AT->getElementType(), PD);
+ }
+
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ // We can't answer whether something is abstract until it has a
+ // definition. If it's currently being defined, we'll walk back
+ // over all the declarations when we have a full definition.
+ const CXXRecordDecl *Def = RD->getDefinition();
+ if (!Def || Def->isBeingDefined())
+ return false;
+
+ if (!RD->isAbstract())
+ return false;
+
+ Diag(Loc, PD) << RD->getDeclName();
+ DiagnoseAbstractType(RD);
+
+ return true;
+}
+
+void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
+ // Check if we've already emitted the list of pure virtual functions
+ // for this class.
+ if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
+ return;
+
+ CXXFinalOverriderMap FinalOverriders;
+ RD->getFinalOverriders(FinalOverriders);
+
+ // Keep a set of seen pure methods so we won't diagnose the same method
+ // more than once.
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;
+
+ for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
+ MEnd = FinalOverriders.end();
+ M != MEnd;
+ ++M) {
+ for (OverridingMethods::iterator SO = M->second.begin(),
+ SOEnd = M->second.end();
+ SO != SOEnd; ++SO) {
+ // 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.size() != 1)
+ continue;
+
+ if (!SO->second.front().Method->isPure())
+ continue;
+
+ if (!SeenPureMethods.insert(SO->second.front().Method))
+ continue;
+
+ Diag(SO->second.front().Method->getLocation(),
+ diag::note_pure_virtual_function)
+ << SO->second.front().Method->getDeclName() << RD->getDeclName();
+ }
+ }
+
+ if (!PureVirtualClassDiagSet)
+ PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
+ PureVirtualClassDiagSet->insert(RD);
+}
+
+namespace {
+struct AbstractUsageInfo {
+ Sema &S;
+ CXXRecordDecl *Record;
+ CanQualType AbstractType;
+ bool Invalid;
+
+ AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
+ : S(S), Record(Record),
+ AbstractType(S.Context.getCanonicalType(
+ S.Context.getTypeDeclType(Record))),
+ Invalid(false) {}
+
+ void DiagnoseAbstractType() {
+ if (Invalid) return;
+ S.DiagnoseAbstractType(Record);
+ Invalid = true;
+ }
+
+ void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel);
+};
+
+struct CheckAbstractUsage {
+ AbstractUsageInfo &Info;
+ const NamedDecl *Ctx;
+
+ CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx)
+ : Info(Info), Ctx(Ctx) {}
+
+ void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break;
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+
+ void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ Visit(TL.getResultLoc(), Sema::AbstractReturnType);
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
+ if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
+ }
+ }
+
+ void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ Visit(TL.getElementLoc(), Sema::AbstractArrayType);
+ }
+
+ void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ // Visit the type parameters from a permissive context.
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TemplateArgumentLoc TAL = TL.getArgLoc(I);
+ if (TAL.getArgument().getKind() == TemplateArgument::Type)
+ if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo())
+ Visit(TSI->getTypeLoc(), Sema::AbstractNone);
+ // TODO: other template argument types?
+ }
+ }
+
+ // Visit pointee types from a permissive context.
+#define CheckPolymorphic(Type) \
+ void Check(Type TL, Sema::AbstractDiagSelID Sel) { \
+ Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \
+ }
+ CheckPolymorphic(PointerTypeLoc)
+ CheckPolymorphic(ReferenceTypeLoc)
+ CheckPolymorphic(MemberPointerTypeLoc)
+ CheckPolymorphic(BlockPointerTypeLoc)
+
+ /// Handle all the types we haven't given a more specific
+ /// implementation for above.
+ void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ // Every other kind of type that we haven't called out already
+ // that has an inner type is either (1) sugar or (2) contains that
+ // inner type in some way as a subobject.
+ if (TypeLoc Next = TL.getNextTypeLoc())
+ return Visit(Next, Sel);
+
+ // If there's no inner type and we're in a permissive context,
+ // don't diagnose.
+ if (Sel == Sema::AbstractNone) return;
+
+ // Check whether the type matches the abstract type.
+ QualType T = TL.getType();
+ if (T->isArrayType()) {
+ Sel = Sema::AbstractArrayType;
+ T = Info.S.Context.getBaseElementType(T);
+ }
+ CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType();
+ if (CT != Info.AbstractType) return;
+
+ // It matched; do some magic.
+ if (Sel == Sema::AbstractArrayType) {
+ Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type)
+ << T << TL.getSourceRange();
+ } else {
+ Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl)
+ << Sel << T << TL.getSourceRange();
+ }
+ Info.DiagnoseAbstractType();
+ }
+};
+
+void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL,
+ Sema::AbstractDiagSelID Sel) {
+ CheckAbstractUsage(*this, D).Visit(TL, Sel);
+}
+
+}
+
+/// Check for invalid uses of an abstract type in a method declaration.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+ CXXMethodDecl *MD) {
+ // No need to do the check on definitions, which require that
+ // the return/param types be complete.
+ if (MD->isThisDeclarationADefinition())
+ return;
+
+ // For safety's sake, just ignore it if we don't have type source
+ // information. This should never happen for non-implicit methods,
+ // but...
+ if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
+ Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone);
+}
+
+/// Check for invalid uses of an abstract type within a class definition.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+ CXXRecordDecl *RD) {
+ for (CXXRecordDecl::decl_iterator
+ I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) {
+ Decl *D = *I;
+ if (D->isImplicit()) continue;
+
+ // Methods and method templates.
+ if (isa<CXXMethodDecl>(D)) {
+ CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D));
+ } else if (isa<FunctionTemplateDecl>(D)) {
+ FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
+ CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD));
+
+ // Fields and static variables.
+ } else if (isa<FieldDecl>(D)) {
+ FieldDecl *FD = cast<FieldDecl>(D);
+ if (TypeSourceInfo *TSI = FD->getTypeSourceInfo())
+ Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType);
+ } else if (isa<VarDecl>(D)) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (TypeSourceInfo *TSI = VD->getTypeSourceInfo())
+ Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType);
+
+ // Nested classes and class templates.
+ } else if (isa<CXXRecordDecl>(D)) {
+ CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D));
+ } else if (isa<ClassTemplateDecl>(D)) {
+ CheckAbstractClassUsage(Info,
+ cast<ClassTemplateDecl>(D)->getTemplatedDecl());
+ }
+ }
+}
+
+/// \brief Perform semantic checks on a class definition that has been
+/// completing, introducing implicitly-declared members, checking for
+/// abstract types, etc.
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
+ if (!Record)
+ return;
+
+ if (Record->isAbstract() && !Record->isInvalidDecl()) {
+ AbstractUsageInfo Info(*this, Record);
+ CheckAbstractClassUsage(Info, Record);
+ }
+
+ // If this is not an aggregate type and has no user-declared constructor,
+ // complain about any non-static data members of reference or const scalar
+ // type, since they will never get initializers.
+ if (!Record->isInvalidDecl() && !Record->isDependentType() &&
+ !Record->isAggregate() && !Record->hasUserDeclaredConstructor()) {
+ bool Complained = false;
+ for (RecordDecl::field_iterator F = Record->field_begin(),
+ FEnd = Record->field_end();
+ F != FEnd; ++F) {
+ if (F->getType()->isReferenceType() ||
+ (F->getType().isConstQualified() && F->getType()->isScalarType())) {
+ if (!Complained) {
+ Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst)
+ << Record->getTagKind() << Record;
+ Complained = true;
+ }
+
+ Diag(F->getLocation(), diag::note_refconst_member_not_initialized)
+ << F->getType()->isReferenceType()
+ << F->getDeclName();
+ }
+ }
+ }
+
+ if (Record->isDynamicClass() && !Record->isDependentType())
+ DynamicClasses.push_back(Record);
+
+ if (Record->getIdentifier()) {
+ // C++ [class.mem]p13:
+ // If T is the name of a class, then each of the following shall have a
+ // name different from T:
+ // - every member of every anonymous union that is a member of class T.
+ //
+ // C++ [class.mem]p14:
+ // In addition, if class T has a user-declared constructor (12.1), every
+ // non-static data member of class T shall have a name different from T.
+ for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
+ R.first != R.second; ++R.first) {
+ NamedDecl *D = *R.first;
+ if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
+ isa<IndirectFieldDecl>(D)) {
+ Diag(D->getLocation(), diag::err_member_name_of_class)
+ << D->getDeclName();
+ break;
+ }
+ }
+ }
+
+ // Warn if the class has virtual methods but non-virtual public destructor.
+ if (Record->isPolymorphic() && !Record->isDependentType()) {
+ CXXDestructorDecl *dtor = Record->getDestructor();
+ if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public))
+ Diag(dtor ? dtor->getLocation() : Record->getLocation(),
+ diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
+ }
+
+ // See if a method overloads virtual methods in a base
+ /// class without overriding any.
+ if (!Record->isDependentType()) {
+ for (CXXRecordDecl::method_iterator M = Record->method_begin(),
+ MEnd = Record->method_end();
+ M != MEnd; ++M) {
+ DiagnoseHiddenVirtualMethods(Record, *M);
+ }
+ }
+
+ // Declare inherited constructors. We do this eagerly here because:
+ // - The standard requires an eager diagnostic for conflicting inherited
+ // constructors from different classes.
+ // - The lazy declaration of the other implicit constructors is so as to not
+ // waste space and performance on classes that are not meant to be
+ // instantiated (e.g. meta-functions). This doesn't apply to classes that
+ // have inherited constructors.
+ DeclareInheritedConstructors(Record);
+}
+
+/// \brief Data used with FindHiddenVirtualMethod
+struct FindHiddenVirtualMethodData {
+ Sema *S;
+ CXXMethodDecl *Method;
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+ llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
+};
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overloads virtual methods in a base class without overriding any,
+/// to be used with CXXRecordDecl::lookupInBases().
+static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ FindHiddenVirtualMethodData &Data
+ = *static_cast<FindHiddenVirtualMethodData*>(UserData);
+
+ DeclarationName Name = Data.Method->getDeclName();
+ assert(Name.getNameKind() == DeclarationName::Identifier);
+
+ bool foundSameNameMethod = false;
+ llvm::SmallVector<CXXMethodDecl *, 8> overloadedMethods;
+ for (Path.Decls = BaseRecord->lookup(Name);
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ NamedDecl *D = *Path.Decls.first;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ MD = MD->getCanonicalDecl();
+ foundSameNameMethod = true;
+ // Interested only in hidden virtual methods.
+ if (!MD->isVirtual())
+ continue;
+ // If the method we are checking overrides a method from its base
+ // don't warn about the other overloaded methods.
+ if (!Data.S->IsOverload(Data.Method, MD, false))
+ return true;
+ // Collect the overload only if its hidden.
+ if (!Data.OverridenAndUsingBaseMethods.count(MD))
+ overloadedMethods.push_back(MD);
+ }
+ }
+
+ if (foundSameNameMethod)
+ Data.OverloadedMethods.append(overloadedMethods.begin(),
+ overloadedMethods.end());
+ return foundSameNameMethod;
+}
+
+/// \brief See if a method overloads virtual methods in a base class without
+/// overriding any.
+void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+ if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual,
+ MD->getLocation()) == Diagnostic::Ignored)
+ return;
+ if (MD->getDeclName().getNameKind() != DeclarationName::Identifier)
+ return;
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
+ /*bool RecordPaths=*/false,
+ /*bool DetectVirtual=*/false);
+ FindHiddenVirtualMethodData Data;
+ Data.Method = MD;
+ Data.S = this;
+
+ // Keep the base methods that were overriden or introduced in the subclass
+ // by 'using' in a set. A base method not in this set is hidden.
+ for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName());
+ res.first != res.second; ++res.first) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*res.first))
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I)
+ Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl());
+ if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first))
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(shad->getTargetDecl()))
+ Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl());
+ }
+
+ if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) &&
+ !Data.OverloadedMethods.empty()) {
+ Diag(MD->getLocation(), diag::warn_overloaded_virtual)
+ << MD << (Data.OverloadedMethods.size() > 1);
+
+ for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) {
+ CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i];
+ Diag(overloadedMD->getLocation(),
+ diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
+ }
+ }
+}
+
+void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ Decl *TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac,
+ AttributeList *AttrList) {
+ if (!TagDecl)
+ return;
+
+ AdjustDeclIfTemplate(TagDecl);
+
+ ActOnFields(S, RLoc, TagDecl,
+ // strict aliasing violation!
+ reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
+ FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList);
+
+ CheckCompletedCXXClass(
+ dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+}
+
+namespace {
+ /// \brief Helper class that collects exception specifications for
+ /// implicitly-declared special member functions.
+ class ImplicitExceptionSpecification {
+ ASTContext &Context;
+ bool AllowsAllExceptions;
+ llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
+ llvm::SmallVector<QualType, 4> Exceptions;
+
+ public:
+ explicit ImplicitExceptionSpecification(ASTContext &Context)
+ : Context(Context), AllowsAllExceptions(false) { }
+
+ /// \brief Whether the special member function should have any
+ /// exception specification at all.
+ bool hasExceptionSpecification() const {
+ return !AllowsAllExceptions;
+ }
+
+ /// \brief Whether the special member function should have a
+ /// throw(...) exception specification (a Microsoft extension).
+ bool hasAnyExceptionSpecification() const {
+ return false;
+ }
+
+ /// \brief The number of exceptions in the exception specification.
+ unsigned size() const { return Exceptions.size(); }
+
+ /// \brief The set of exceptions in the exception specification.
+ const QualType *data() const { return Exceptions.data(); }
+
+ /// \brief Note that
+ void CalledDecl(CXXMethodDecl *Method) {
+ // If we already know that we allow all exceptions, do nothing.
+ if (AllowsAllExceptions || !Method)
+ return;
+
+ const FunctionProtoType *Proto
+ = Method->getType()->getAs<FunctionProtoType>();
+
+ // If this function can throw any exceptions, make a note of that.
+ if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) {
+ AllowsAllExceptions = true;
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ return;
+ }
+
+ // Record the exceptions in this function's exception specification.
+ for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+ EEnd = Proto->exception_end();
+ E != EEnd; ++E)
+ if (ExceptionsSeen.insert(Context.getCanonicalType(*E)))
+ Exceptions.push_back(*E);
+ }
+ };
+}
+
+
+/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
+/// special functions, such as the default constructor, copy
+/// constructor, or destructor, to the given C++ class (C++
+/// [special]p1). This routine can only be executed just before the
+/// definition of the class is complete.
+void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+ if (!ClassDecl->hasUserDeclaredConstructor())
+ ++ASTContext::NumImplicitDefaultConstructors;
+
+ if (!ClassDecl->hasUserDeclaredCopyConstructor())
+ ++ASTContext::NumImplicitCopyConstructors;
+
+ if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
+ ++ASTContext::NumImplicitCopyAssignmentOperators;
+
+ // If we have a dynamic class, then the copy assignment operator may be
+ // virtual, so we have to declare it immediately. This ensures that, e.g.,
+ // it shows up in the right place in the vtable and that we diagnose
+ // problems with the implicit exception specification.
+ if (ClassDecl->isDynamicClass())
+ DeclareImplicitCopyAssignment(ClassDecl);
+ }
+
+ if (!ClassDecl->hasUserDeclaredDestructor()) {
+ ++ASTContext::NumImplicitDestructors;
+
+ // If we have a dynamic class, then the destructor may be virtual, so we
+ // have to declare the destructor immediately. This ensures that, e.g., it
+ // shows up in the right place in the vtable and that we diagnose problems
+ // with the implicit exception specification.
+ if (ClassDecl->isDynamicClass())
+ DeclareImplicitDestructor(ClassDecl);
+ }
+}
+
+void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
+ if (!D)
+ return;
+
+ TemplateParameterList *Params = 0;
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
+ Params = Template->getTemplateParameters();
+ else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+ Params = PartialSpec->getTemplateParameters();
+ else
+ return;
+
+ for (TemplateParameterList::iterator Param = Params->begin(),
+ ParamEnd = Params->end();
+ Param != ParamEnd; ++Param) {
+ NamedDecl *Named = cast<NamedDecl>(*Param);
+ if (Named->getDeclName()) {
+ S->AddDecl(Named);
+ IdResolver.AddDecl(Named);
+ }
+ }
+}
+
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
+ if (!RecordD) return;
+ AdjustDeclIfTemplate(RecordD);
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD);
+ PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
+ if (!RecordD) return;
+ PopDeclContext();
+}
+
+/// ActOnStartDelayedCXXMethodDeclaration - We have completed
+/// parsing a top-level (non-nested) C++ class, and we are now
+/// parsing those parts of the given Method declaration that could
+/// not be parsed earlier (C++ [class.mem]p2), such as default
+/// arguments. This action should enter the scope of the given
+/// Method declaration as if we had just parsed the qualified method
+/// name. However, it should not bring the parameters into scope;
+/// that will be performed by ActOnDelayedCXXMethodParameter.
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
+}
+
+/// ActOnDelayedCXXMethodParameter - We've already started a delayed
+/// C++ method declaration. We're (re-)introducing the given
+/// function parameter into scope for use in parsing later parts of
+/// the method declaration. For example, we could see an
+/// ActOnParamDefaultArgument event for this parameter.
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
+ if (!ParamD)
+ return;
+
+ ParmVarDecl *Param = cast<ParmVarDecl>(ParamD);
+
+ // If this parameter has an unparsed default argument, clear it out
+ // to make way for the parsed default argument.
+ if (Param->hasUnparsedDefaultArg())
+ Param->setDefaultArg(0);
+
+ S->AddDecl(Param);
+ if (Param->getDeclName())
+ IdResolver.AddDecl(Param);
+}
+
+/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
+/// processing the delayed method declaration for Method. The method
+/// declaration is now considered finished. There may be a separate
+/// ActOnStartOfFunctionDef action later (not necessarily
+/// immediately!) for this method, if it was also defined inside the
+/// class body.
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
+ if (!MethodD)
+ return;
+
+ AdjustDeclIfTemplate(MethodD);
+
+ FunctionDecl *Method = cast<FunctionDecl>(MethodD);
+
+ // Now that we have our default arguments, check the constructor
+ // again. It could produce additional diagnostics or affect whether
+ // the class has implicitly-declared destructors, among other
+ // things.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
+ CheckConstructor(Constructor);
+
+ // Check the default arguments, which we may have added.
+ if (!Method->isInvalidDecl())
+ CheckCXXDefaultArguments(Method);
+}
+
+/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formedness of the constructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the invalid bit to true. In any case, the type
+/// will be updated to reflect a well-formed type for the constructor and
+/// returned.
+QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
+ StorageClass &SC) {
+ bool isVirtual = D.getDeclSpec().isVirtualSpecified();
+
+ // C++ [class.ctor]p3:
+ // A constructor shall not be virtual (10.3) or static (9.4). A
+ // constructor can be invoked for a const, volatile or const
+ // volatile object. A constructor shall not be declared const,
+ // volatile, or const volatile (9.3.2).
+ if (isVirtual) {
+ if (!D.isInvalidType())
+ Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+ << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
+ << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ }
+ if (SC == SC_Static) {
+ if (!D.isInvalidType())
+ Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
+ << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+ << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ SC = SC_None;
+ }
+
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+ if (FTI.TypeQuals != 0) {
+ if (FTI.TypeQuals & Qualifiers::Const)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+ << "const" << SourceRange(D.getIdentifierLoc());
+ if (FTI.TypeQuals & Qualifiers::Volatile)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+ << "volatile" << SourceRange(D.getIdentifierLoc());
+ if (FTI.TypeQuals & Qualifiers::Restrict)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
+ << "restrict" << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ }
+
+ // C++0x [class.ctor]p4:
+ // A constructor shall not be declared with a ref-qualifier.
+ if (FTI.hasRefQualifier()) {
+ Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
+ << FTI.RefQualifierIsLValueRef
+ << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+ D.setInvalidType();
+ }
+
+ // Rebuild the function type "R" without any type qualifiers (in
+ // case any of the errors above fired) and with "void" as the
+ // return type, since constructors don't have return types.
+ const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+ if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType())
+ return R;
+
+ FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ EPI.TypeQuals = 0;
+ EPI.RefQualifier = RQ_None;
+
+ return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
+ Proto->getNumArgs(), EPI);
+}
+
+/// CheckConstructor - Checks a fully-formed constructor for
+/// well-formedness, issuing any diagnostics required. Returns true if
+/// the constructor declarator is invalid.
+void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
+ CXXRecordDecl *ClassDecl
+ = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
+ if (!ClassDecl)
+ return Constructor->setInvalidDecl();
+
+ // C++ [class.copy]p3:
+ // A declaration of a constructor for a class X is ill-formed if
+ // its first parameter is of type (optionally cv-qualified) X and
+ // either there are no other parameters or else all other
+ // parameters have default arguments.
+ if (!Constructor->isInvalidDecl() &&
+ ((Constructor->getNumParams() == 1) ||
+ (Constructor->getNumParams() > 1 &&
+ Constructor->getParamDecl(1)->hasDefaultArg())) &&
+ Constructor->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation) {
+ QualType ParamType = Constructor->getParamDecl(0)->getType();
+ QualType ClassTy = Context.getTagDeclType(ClassDecl);
+ if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
+ SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
+ const char *ConstRef
+ = Constructor->getParamDecl(0)->getIdentifier() ? "const &"
+ : " const &";
+ Diag(ParamLoc, diag::err_constructor_byvalue_arg)
+ << FixItHint::CreateInsertion(ParamLoc, ConstRef);
+
+ // FIXME: Rather that making the constructor invalid, we should endeavor
+ // to fix the type.
+ Constructor->setInvalidDecl();
+ }
+ }
+}
+
+/// CheckDestructor - Checks a fully-formed destructor definition for
+/// well-formedness, issuing any diagnostics required. Returns true
+/// on error.
+bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
+ CXXRecordDecl *RD = Destructor->getParent();
+
+ if (Destructor->isVirtual()) {
+ SourceLocation Loc;
+
+ if (!Destructor->isImplicit())
+ Loc = Destructor->getLocation();
+ else
+ Loc = RD->getLocation();
+
+ // If we have a virtual destructor, look up the deallocation function
+ FunctionDecl *OperatorDelete = 0;
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+ if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+ return true;
+
+ MarkDeclarationReferenced(Loc, OperatorDelete);
+
+ Destructor->setOperatorDelete(OperatorDelete);
+ }
+
+ return false;
+}
+
+static inline bool
+FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
+ return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
+ FTI.ArgInfo[0].Param &&
+ cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType());
+}
+
+/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
+/// the well-formednes of the destructor declarator @p D with type @p
+/// R. If there are any errors in the declarator, this routine will
+/// emit diagnostics and set the declarator to invalid. Even if this happens,
+/// will be updated to reflect a well-formed type for the destructor and
+/// returned.
+QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
+ StorageClass& SC) {
+ // C++ [class.dtor]p1:
+ // [...] A typedef-name that names a class is a class-name
+ // (7.1.3); however, a typedef-name that names a class shall not
+ // be used as the identifier in the declarator for a destructor
+ // declaration.
+ QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
+ if (isa<TypedefType>(DeclaratorType))
+ Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
+ << DeclaratorType;
+
+ // C++ [class.dtor]p2:
+ // A destructor is used to destroy objects of its class type. A
+ // destructor takes no parameters, and no return type can be
+ // specified for it (not even void). The address of a destructor
+ // shall not be taken. A destructor shall not be static. A
+ // destructor can be invoked for a const, volatile or const
+ // volatile object. A destructor shall not be declared const,
+ // volatile or const volatile (9.3.2).
+ if (SC == SC_Static) {
+ if (!D.isInvalidType())
+ Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
+ << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+ << SourceRange(D.getIdentifierLoc())
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+
+ SC = SC_None;
+ }
+ if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ // Destructors don't have return types, but the parser will
+ // happily parse something like:
+ //
+ // class X {
+ // float ~X();
+ // };
+ //
+ // The return type will be eliminated later.
+ Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
+ << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(D.getIdentifierLoc());
+ }
+
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+ if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
+ if (FTI.TypeQuals & Qualifiers::Const)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+ << "const" << SourceRange(D.getIdentifierLoc());
+ if (FTI.TypeQuals & Qualifiers::Volatile)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+ << "volatile" << SourceRange(D.getIdentifierLoc());
+ if (FTI.TypeQuals & Qualifiers::Restrict)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
+ << "restrict" << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ }
+
+ // C++0x [class.dtor]p2:
+ // A destructor shall not be declared with a ref-qualifier.
+ if (FTI.hasRefQualifier()) {
+ Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
+ << FTI.RefQualifierIsLValueRef
+ << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+ D.setInvalidType();
+ }
+
+ // Make sure we don't have any parameters.
+ if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
+ Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
+
+ // Delete the parameters.
+ FTI.freeArgs();
+ D.setInvalidType();
+ }
+
+ // Make sure the destructor isn't variadic.
+ if (FTI.isVariadic) {
+ Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
+ D.setInvalidType();
+ }
+
+ // Rebuild the function type "R" without any type qualifiers or
+ // parameters (in case any of the errors above fired) and with
+ // "void" as the return type, since destructors don't have return
+ // types.
+ if (!D.isInvalidType())
+ return R;
+
+ const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ EPI.Variadic = false;
+ EPI.TypeQuals = 0;
+ EPI.RefQualifier = RQ_None;
+ return Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
+}
+
+/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
+/// well-formednes of the conversion function declarator @p D with
+/// type @p R. If there are any errors in the declarator, this routine
+/// will emit diagnostics and return true. Otherwise, it will return
+/// false. Either way, the type @p R will be updated to reflect a
+/// well-formed type for the conversion operator.
+void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
+ StorageClass& SC) {
+ // C++ [class.conv.fct]p1:
+ // Neither parameter types nor return type can be specified. The
+ // type of a conversion function (8.3.5) is "function taking no
+ // parameter returning conversion-type-id."
+ if (SC == SC_Static) {
+ if (!D.isInvalidType())
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
+ << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
+ << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ SC = SC_None;
+ }
+
+ QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
+
+ if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
+ // Conversion functions don't have return types, but the parser will
+ // happily parse something like:
+ //
+ // class X {
+ // float operator bool();
+ // };
+ //
+ // The return type will be changed later anyway.
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
+ << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(D.getIdentifierLoc());
+ D.setInvalidType();
+ }
+
+ const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+
+ // Make sure we don't have any parameters.
+ if (Proto->getNumArgs() > 0) {
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
+
+ // Delete the parameters.
+ D.getFunctionTypeInfo().freeArgs();
+ D.setInvalidType();
+ } else if (Proto->isVariadic()) {
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
+ D.setInvalidType();
+ }
+
+ // Diagnose "&operator bool()" and other such nonsense. This
+ // is actually a gcc extension which we don't support.
+ if (Proto->getResultType() != ConvType) {
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
+ << Proto->getResultType();
+ D.setInvalidType();
+ ConvType = Proto->getResultType();
+ }
+
+ // C++ [class.conv.fct]p4:
+ // The conversion-type-id shall not represent a function type nor
+ // an array type.
+ if (ConvType->isArrayType()) {
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
+ ConvType = Context.getPointerType(ConvType);
+ D.setInvalidType();
+ } else if (ConvType->isFunctionType()) {
+ Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
+ ConvType = Context.getPointerType(ConvType);
+ D.setInvalidType();
+ }
+
+ // Rebuild the function type "R" without any parameters (in case any
+ // of the errors above fired) and with the conversion type as the
+ // return type.
+ if (D.isInvalidType())
+ R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo());
+
+ // C++0x explicit conversion operators.
+ if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x)
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::warn_explicit_conversion_functions)
+ << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
+}
+
+/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
+/// the declaration of the given C++ conversion function. This routine
+/// is responsible for recording the conversion function in the C++
+/// class, if possible.
+Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
+ assert(Conversion && "Expected to receive a conversion function declaration");
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
+
+ // Make sure we aren't redeclaring the conversion function.
+ QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
+
+ // C++ [class.conv.fct]p1:
+ // [...] A conversion function is never used to convert a
+ // (possibly cv-qualified) object to the (possibly cv-qualified)
+ // same object type (or a reference to it), to a (possibly
+ // cv-qualified) base class of that type (or a reference to it),
+ // or to (possibly cv-qualified) void.
+ // FIXME: Suppress this warning if the conversion function ends up being a
+ // virtual function that overrides a virtual function in a base class.
+ QualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
+ ConvType = ConvTypeRef->getPointeeType();
+ if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
+ Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ /* Suppress diagnostics for instantiations. */;
+ else if (ConvType->isRecordType()) {
+ ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
+ if (ConvType == ClassType)
+ Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
+ << ClassType;
+ else if (IsDerivedFrom(ClassType, ConvType))
+ Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
+ << ClassType << ConvType;
+ } else if (ConvType->isVoidType()) {
+ Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
+ << ClassType << ConvType;
+ }
+
+ if (FunctionTemplateDecl *ConversionTemplate
+ = Conversion->getDescribedFunctionTemplate())
+ return ConversionTemplate;
+
+ return Conversion;
+}
+
+//===----------------------------------------------------------------------===//
+// Namespace Handling
+//===----------------------------------------------------------------------===//
+
+
+
+/// ActOnStartNamespaceDef - This is called at the start of a namespace
+/// definition.
+Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+ SourceLocation InlineLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation LBrace,
+ AttributeList *AttrList) {
+ // anonymous namespace starts at its left brace
+ NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext,
+ (II ? IdentLoc : LBrace) , II);
+ Namespc->setLBracLoc(LBrace);
+ Namespc->setInline(InlineLoc.isValid());
+
+ Scope *DeclRegionScope = NamespcScope->getParent();
+
+ ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
+
+ if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
+ PushNamespaceVisibilityAttr(Attr);
+
+ if (II) {
+ // C++ [namespace.def]p2:
+ // The identifier in an original-namespace-definition shall not
+ // have been previously defined in the declarative region in
+ // which the original-namespace-definition appears. The
+ // identifier in an original-namespace-definition is the name of
+ // the namespace. Subsequently in that declarative region, it is
+ // treated as an original-namespace-name.
+ //
+ // Since namespace names are unique in their scope, and we don't
+ // look through using directives, just
+ DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II);
+ NamedDecl *PrevDecl = R.first == R.second? 0 : *R.first;
+
+ if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
+ // This is an extended namespace definition.
+ if (Namespc->isInline() != OrigNS->isInline()) {
+ // inline-ness must match
+ Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+ << Namespc->isInline();
+ Diag(OrigNS->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Recover by ignoring the new namespace's inline status.
+ Namespc->setInline(OrigNS->isInline());
+ }
+
+ // Attach this namespace decl to the chain of extended namespace
+ // definitions.
+ OrigNS->setNextNamespace(Namespc);
+ Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
+
+ // Remove the previous declaration from the scope.
+ if (DeclRegionScope->isDeclScope(OrigNS)) {
+ IdResolver.RemoveDecl(OrigNS);
+ DeclRegionScope->RemoveDecl(OrigNS);
+ }
+ } else if (PrevDecl) {
+ // This is an invalid name redefinition.
+ Diag(Namespc->getLocation(), diag::err_redefinition_different_kind)
+ << Namespc->getDeclName();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Continue on to push Namespc as current DeclContext and return it.
+ } else if (II->isStr("std") &&
+ CurContext->getRedeclContext()->isTranslationUnit()) {
+ // This is the first "real" definition of the namespace "std", so update
+ // our cache of the "std" namespace to point at this definition.
+ if (NamespaceDecl *StdNS = getStdNamespace()) {
+ // We had already defined a dummy namespace "std". Link this new
+ // namespace definition to the dummy namespace "std".
+ StdNS->setNextNamespace(Namespc);
+ StdNS->setLocation(IdentLoc);
+ Namespc->setOriginalNamespace(StdNS->getOriginalNamespace());
+ }
+
+ // Make our StdNamespace cache point at the first real definition of the
+ // "std" namespace.
+ StdNamespace = Namespc;
+ }
+
+ PushOnScopeChains(Namespc, DeclRegionScope);
+ } else {
+ // Anonymous namespaces.
+ assert(Namespc->isAnonymousNamespace());
+
+ // Link the anonymous namespace into its parent.
+ NamespaceDecl *PrevDecl;
+ DeclContext *Parent = CurContext->getRedeclContext();
+ if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+ PrevDecl = TU->getAnonymousNamespace();
+ TU->setAnonymousNamespace(Namespc);
+ } else {
+ NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
+ PrevDecl = ND->getAnonymousNamespace();
+ ND->setAnonymousNamespace(Namespc);
+ }
+
+ // Link the anonymous namespace with its previous declaration.
+ if (PrevDecl) {
+ assert(PrevDecl->isAnonymousNamespace());
+ assert(!PrevDecl->getNextNamespace());
+ Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
+ PrevDecl->setNextNamespace(Namespc);
+
+ if (Namespc->isInline() != PrevDecl->isInline()) {
+ // inline-ness must match
+ Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+ << Namespc->isInline();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Recover by ignoring the new namespace's inline status.
+ Namespc->setInline(PrevDecl->isInline());
+ }
+ }
+
+ CurContext->addDecl(Namespc);
+
+ // C++ [namespace.unnamed]p1. An unnamed-namespace-definition
+ // behaves as if it were replaced by
+ // namespace unique { /* empty body */ }
+ // using namespace unique;
+ // namespace unique { namespace-body }
+ // where all occurrences of 'unique' in a translation unit are
+ // replaced by the same identifier and this identifier differs
+ // from all other identifiers in the entire program.
+
+ // We just create the namespace with an empty name and then add an
+ // implicit using declaration, just like the standard suggests.
+ //
+ // CodeGen enforces the "universally unique" aspect by giving all
+ // declarations semantically contained within an anonymous
+ // namespace internal linkage.
+
+ if (!PrevDecl) {
+ UsingDirectiveDecl* UD
+ = UsingDirectiveDecl::Create(Context, CurContext,
+ /* 'using' */ LBrace,
+ /* 'namespace' */ SourceLocation(),
+ /* qualifier */ SourceRange(),
+ /* NNS */ NULL,
+ /* identifier */ SourceLocation(),
+ Namespc,
+ /* Ancestor */ CurContext);
+ UD->setImplicit();
+ CurContext->addDecl(UD);
+ }
+ }
+
+ // Although we could have an invalid decl (i.e. the namespace name is a
+ // redefinition), push it as current DeclContext and try to continue parsing.
+ // FIXME: We should be able to push Namespc here, so that the each DeclContext
+ // for the namespace has the declarations that showed up in that particular
+ // namespace definition.
+ PushDeclContext(NamespcScope, Namespc);
+ return Namespc;
+}
+
+/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
+/// is a namespace alias, returns the namespace it points to.
+static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
+ if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
+ return AD->getNamespace();
+ return dyn_cast_or_null<NamespaceDecl>(D);
+}
+
+/// ActOnFinishNamespaceDef - This callback is called after a namespace is
+/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
+ NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
+ assert(Namespc && "Invalid parameter, expected NamespaceDecl");
+ Namespc->setRBracLoc(RBrace);
+ PopDeclContext();
+ if (Namespc->hasAttr<VisibilityAttr>())
+ PopPragmaVisibility();
+}
+
+CXXRecordDecl *Sema::getStdBadAlloc() const {
+ return cast_or_null<CXXRecordDecl>(
+ StdBadAlloc.get(Context.getExternalSource()));
+}
+
+NamespaceDecl *Sema::getStdNamespace() const {
+ return cast_or_null<NamespaceDecl>(
+ StdNamespace.get(Context.getExternalSource()));
+}
+
+/// \brief Retrieve the special "std" namespace, which may require us to
+/// implicitly define the namespace.
+NamespaceDecl *Sema::getOrCreateStdNamespace() {
+ if (!StdNamespace) {
+ // The "std" namespace has not yet been defined, so build one implicitly.
+ StdNamespace = NamespaceDecl::Create(Context,
+ Context.getTranslationUnitDecl(),
+ SourceLocation(),
+ &PP.getIdentifierTable().get("std"));
+ getStdNamespace()->setImplicit(true);
+ }
+
+ return getStdNamespace();
+}
+
+Decl *Sema::ActOnUsingDirective(Scope *S,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList) {
+ assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ assert(NamespcName && "Invalid NamespcName.");
+ assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+
+ // This can only happen along a recovery path.
+ while (S->getFlags() & Scope::TemplateParamScope)
+ S = S->getParent();
+ assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+ UsingDirectiveDecl *UDir = 0;
+ NestedNameSpecifier *Qualifier = 0;
+ if (SS.isSet())
+ Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+ // Lookup namespace name.
+ LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
+ LookupParsedName(R, S, &SS);
+ if (R.isAmbiguous())
+ return 0;
+
+ if (R.empty()) {
+ // Allow "using namespace std;" or "using namespace ::std;" even if
+ // "std" hasn't been defined yet, for GCC compatibility.
+ if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
+ NamespcName->isStr("std")) {
+ Diag(IdentLoc, diag::ext_using_undefined_std);
+ R.addDecl(getOrCreateStdNamespace());
+ R.resolveKind();
+ }
+ // Otherwise, attempt typo correction.
+ else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
+ CTC_NoKeywords, 0)) {
+ if (R.getAsSingle<NamespaceDecl>() ||
+ R.getAsSingle<NamespaceAliasDecl>()) {
+ if (DeclContext *DC = computeDeclContext(SS, false))
+ Diag(IdentLoc, diag::err_using_directive_member_suggest)
+ << NamespcName << DC << Corrected << SS.getRange()
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ else
+ Diag(IdentLoc, diag::err_using_directive_suggest)
+ << NamespcName << Corrected
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
+ << Corrected;
+
+ NamespcName = Corrected.getAsIdentifierInfo();
+ } else {
+ R.clear();
+ R.setLookupName(NamespcName);
+ }
+ }
+ }
+
+ if (!R.empty()) {
+ NamedDecl *Named = R.getFoundDecl();
+ assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
+ && "expected namespace decl");
+ // C++ [namespace.udir]p1:
+ // A using-directive specifies that the names in the nominated
+ // namespace can be used in the scope in which the
+ // using-directive appears after the using-directive. During
+ // unqualified name lookup (3.4.1), the names appear as if they
+ // were declared in the nearest enclosing namespace which
+ // contains both the using-directive and the nominated
+ // namespace. [Note: in this context, "contains" means "contains
+ // directly or indirectly". ]
+
+ // Find enclosing context containing both using-directive and
+ // nominated namespace.
+ NamespaceDecl *NS = getNamespaceDecl(Named);
+ DeclContext *CommonAncestor = cast<DeclContext>(NS);
+ while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
+ CommonAncestor = CommonAncestor->getParent();
+
+ UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
+ SS.getRange(),
+ (NestedNameSpecifier *)SS.getScopeRep(),
+ IdentLoc, Named, CommonAncestor);
+ PushUsingDirective(S, UDir);
+ } else {
+ Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
+ }
+
+ // FIXME: We ignore attributes for now.
+ return UDir;
+}
+
+void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
+ // If scope has associated entity, then using directive is at namespace
+ // or translation unit scope. We add UsingDirectiveDecls, into
+ // it's lookup structure.
+ if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+ Ctx->addDecl(UDir);
+ else
+ // Otherwise it is block-sope. using-directives will affect lookup
+ // only to the end of scope.
+ S->PushUsingDirective(UDir);
+}
+
+
+Decl *Sema::ActOnUsingDeclaration(Scope *S,
+ AccessSpecifier AS,
+ bool HasUsingKeyword,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
+ assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedId::IK_ConversionFunctionId:
+ break;
+
+ case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedId::IK_ConstructorTemplateId:
+ // C++0x inherited constructors.
+ if (getLangOptions().CPlusPlus0x) break;
+
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
+ << SS.getRange();
+ return 0;
+
+ case UnqualifiedId::IK_DestructorName:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
+ << SS.getRange();
+ return 0;
+
+ case UnqualifiedId::IK_TemplateId:
+ Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
+ << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+ return 0;
+ }
+
+ DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+ DeclarationName TargetName = TargetNameInfo.getName();
+ if (!TargetName)
+ return 0;
+
+ // Warn about using declarations.
+ // TODO: store that the declaration was written without 'using' and
+ // talk about access decls instead of using decls in the
+ // diagnostics.
+ if (!HasUsingKeyword) {
+ UsingLoc = Name.getSourceRange().getBegin();
+
+ Diag(UsingLoc, diag::warn_access_decl_deprecated)
+ << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
+ }
+
+ if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
+ DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
+ return 0;
+
+ NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
+ TargetNameInfo, AttrList,
+ /* IsInstantiation */ false,
+ IsTypeName, TypenameLoc);
+ if (UD)
+ PushOnScopeChains(UD, S, /*AddToContext*/ false);
+
+ return UD;
+}
+
+/// \brief Determine whether a using declaration considers the given
+/// declarations as "equivalent", e.g., if they are redeclarations of
+/// the same entity or are both typedefs of the same type.
+static bool
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
+ bool &SuppressRedeclaration) {
+ if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
+ SuppressRedeclaration = false;
+ return true;
+ }
+
+ if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1))
+ if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) {
+ SuppressRedeclaration = true;
+ return Context.hasSameType(TD1->getUnderlyingType(),
+ TD2->getUnderlyingType());
+ }
+
+ return false;
+}
+
+
+/// Determines whether to create a using shadow decl for a particular
+/// decl, given the set of decls existing prior to this using lookup.
+bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+ const LookupResult &Previous) {
+ // Diagnose finding a decl which is not from a base class of the
+ // current class. We do this now because there are cases where this
+ // function will silently decide not to build a shadow decl, which
+ // will pre-empt further diagnostics.
+ //
+ // We don't need to do this in C++0x because we do the check once on
+ // the qualifier.
+ //
+ // FIXME: diagnose the following if we care enough:
+ // struct A { int foo; };
+ // struct B : A { using A::foo; };
+ // template <class T> struct C : A {};
+ // template <class T> struct D : C<T> { using B::foo; } // <---
+ // This is invalid (during instantiation) in C++03 because B::foo
+ // resolves to the using decl in B, which is not a base class of D<T>.
+ // We can't diagnose it immediately because C<T> is an unknown
+ // specialization. The UsingShadowDecl in D<T> then points directly
+ // to A::foo, which will look well-formed when we instantiate.
+ // The right solution is to not collapse the shadow-decl chain.
+ if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) {
+ DeclContext *OrigDC = Orig->getDeclContext();
+
+ // Handle enums and anonymous structs.
+ if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
+ CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+ while (OrigRec->isAnonymousStructOrUnion())
+ OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+ if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+ if (OrigDC == CurContext) {
+ Diag(Using->getLocation(),
+ diag::err_using_decl_nested_name_specifier_is_current_class)
+ << Using->getNestedNameRange();
+ Diag(Orig->getLocation(), diag::note_using_decl_target);
+ return true;
+ }
+
+ Diag(Using->getNestedNameRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_base_class)
+ << Using->getTargetNestedNameDecl()
+ << cast<CXXRecordDecl>(CurContext)
+ << Using->getNestedNameRange();
+ Diag(Orig->getLocation(), diag::note_using_decl_target);
+ return true;
+ }
+ }
+
+ if (Previous.empty()) return false;
+
+ NamedDecl *Target = Orig;
+ if (isa<UsingShadowDecl>(Target))
+ Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+
+ // If the target happens to be one of the previous declarations, we
+ // don't have a conflict.
+ //
+ // FIXME: but we might be increasing its access, in which case we
+ // should redeclare it.
+ NamedDecl *NonTag = 0, *Tag = 0;
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ bool Result;
+ if (IsEquivalentForUsingDecl(Context, D, Target, Result))
+ return Result;
+
+ (isa<TagDecl>(D) ? Tag : NonTag) = D;
+ }
+
+ if (Target->isFunctionOrFunctionTemplate()) {
+ FunctionDecl *FD;
+ if (isa<FunctionTemplateDecl>(Target))
+ FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(Target);
+
+ NamedDecl *OldDecl = 0;
+ switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
+ case Ovl_Overload:
+ return false;
+
+ case Ovl_NonFunction:
+ Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ break;
+
+ // We found a decl with the exact signature.
+ case Ovl_Match:
+ // If we're in a record, we want to hide the target, so we
+ // return true (without a diagnostic) to tell the caller not to
+ // build a shadow decl.
+ if (CurContext->isRecord())
+ return true;
+
+ // If we're not in a record, this is an error.
+ Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ break;
+ }
+
+ Diag(Target->getLocation(), diag::note_using_decl_target);
+ Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
+ return true;
+ }
+
+ // Target is not a function.
+
+ if (isa<TagDecl>(Target)) {
+ // No conflict between a tag and a non-tag.
+ if (!Tag) return false;
+
+ Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(Target->getLocation(), diag::note_using_decl_target);
+ Diag(Tag->getLocation(), diag::note_using_decl_conflict);
+ return true;
+ }
+
+ // No conflict between a tag and a non-tag.
+ if (!NonTag) return false;
+
+ Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(Target->getLocation(), diag::note_using_decl_target);
+ Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
+ return true;
+}
+
+/// Builds a shadow declaration corresponding to a 'using' declaration.
+UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
+ UsingDecl *UD,
+ NamedDecl *Orig) {
+
+ // If we resolved to another shadow declaration, just coalesce them.
+ NamedDecl *Target = Orig;
+ if (isa<UsingShadowDecl>(Target)) {
+ Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+ assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
+ }
+
+ UsingShadowDecl *Shadow
+ = UsingShadowDecl::Create(Context, CurContext,
+ UD->getLocation(), UD, Target);
+ UD->addShadowDecl(Shadow);
+
+ Shadow->setAccess(UD->getAccess());
+ if (Orig->isInvalidDecl() || UD->isInvalidDecl())
+ Shadow->setInvalidDecl();
+
+ if (S)
+ PushOnScopeChains(Shadow, S);
+ else
+ CurContext->addDecl(Shadow);
+
+
+ return Shadow;
+}
+
+/// Hides a using shadow declaration. This is required by the current
+/// using-decl implementation when a resolvable using declaration in a
+/// class is followed by a declaration which would hide or override
+/// one or more of the using decl's targets; for example:
+///
+/// struct Base { void foo(int); };
+/// struct Derived : Base {
+/// using Base::foo;
+/// void foo(int);
+/// };
+///
+/// The governing language is C++03 [namespace.udecl]p12:
+///
+/// When a using-declaration brings names from a base class into a
+/// derived class scope, member functions in the derived class
+/// override and/or hide member functions with the same name and
+/// parameter types in a base class (rather than conflicting).
+///
+/// There are two ways to implement this:
+/// (1) optimistically create shadow decls when they're not hidden
+/// by existing declarations, or
+/// (2) don't create any shadow decls (or at least don't make them
+/// visible) until we've fully parsed/instantiated the class.
+/// The problem with (1) is that we might have to retroactively remove
+/// a shadow decl, which requires several O(n) operations because the
+/// decl structures are (very reasonably) not designed for removal.
+/// (2) avoids this but is very fiddly and phase-dependent.
+void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
+ if (Shadow->getDeclName().getNameKind() ==
+ DeclarationName::CXXConversionFunctionName)
+ cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow);
+
+ // Remove it from the DeclContext...
+ Shadow->getDeclContext()->removeDecl(Shadow);
+
+ // ...and the scope, if applicable...
+ if (S) {
+ S->RemoveDecl(Shadow);
+ IdResolver.RemoveDecl(Shadow);
+ }
+
+ // ...and the using decl.
+ Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+
+ // TODO: complain somehow if Shadow was used. It shouldn't
+ // be possible for this to happen, because...?
+}
+
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+/// instantiation of an unresolved using declaration. We treat
+/// the lookup differently for these declarations.
+NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ AttributeList *AttrList,
+ bool IsInstantiation,
+ bool IsTypeName,
+ SourceLocation TypenameLoc) {
+ assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ SourceLocation IdentLoc = NameInfo.getLoc();
+ assert(IdentLoc.isValid() && "Invalid TargetName location.");
+
+ // FIXME: We ignore attributes for now.
+
+ if (SS.isEmpty()) {
+ Diag(IdentLoc, diag::err_using_requires_qualname);
+ return 0;
+ }
+
+ // Do the redeclaration lookup in the current scope.
+ LookupResult Previous(*this, NameInfo, LookupUsingDeclName,
+ ForRedeclaration);
+ Previous.setHideTags(false);
+ if (S) {
+ LookupName(Previous, S);
+
+ // It is really dumb that we have to do this.
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (!isDeclInScope(D, CurContext, S))
+ F.erase();
+ }
+ F.done();
+ } else {
+ assert(IsInstantiation && "no scope in non-instantiation");
+ assert(CurContext->isRecord() && "scope not record in instantiation");
+ LookupQualifiedName(Previous, CurContext);
+ }
+
+ NestedNameSpecifier *NNS = SS.getScopeRep();
+
+ // Check for invalid redeclarations.
+ if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+ return 0;
+
+ // Check for bad qualifiers.
+ if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+ return 0;
+
+ DeclContext *LookupContext = computeDeclContext(SS);
+ NamedDecl *D;
+ if (!LookupContext) {
+ if (IsTypeName) {
+ // FIXME: not all declaration name kinds are legal here
+ D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+ UsingLoc, TypenameLoc,
+ SS.getRange(), NNS,
+ IdentLoc, NameInfo.getName());
+ } else {
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext,
+ UsingLoc, SS.getRange(),
+ NNS, NameInfo);
+ }
+ } else {
+ D = UsingDecl::Create(Context, CurContext,
+ SS.getRange(), UsingLoc, NNS, NameInfo,
+ IsTypeName);
+ }
+ D->setAccess(AS);
+ CurContext->addDecl(D);
+
+ if (!LookupContext) return D;
+ UsingDecl *UD = cast<UsingDecl>(D);
+
+ if (RequireCompleteDeclContext(SS, LookupContext)) {
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ // Constructor inheriting using decls get special treatment.
+ if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
+ if (CheckInheritedConstructorUsingDecl(UD))
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ // Otherwise, look up the target name.
+
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+
+ // Unlike most lookups, we don't always want to hide tag
+ // declarations: tag names are visible through the using declaration
+ // even if hidden by ordinary names, *except* in a dependent context
+ // where it's important for the sanity of two-phase lookup.
+ if (!IsInstantiation)
+ R.setHideTags(false);
+
+ LookupQualifiedName(R, LookupContext);
+
+ if (R.empty()) {
+ Diag(IdentLoc, diag::err_no_member)
+ << NameInfo.getName() << LookupContext << SS.getRange();
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ if (R.isAmbiguous()) {
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ if (IsTypeName) {
+ // If we asked for a typename and got a non-type decl, error out.
+ if (!R.getAsSingle<TypeDecl>()) {
+ Diag(IdentLoc, diag::err_using_typename_non_type);
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ Diag((*I)->getUnderlyingDecl()->getLocation(),
+ diag::note_using_decl_target);
+ UD->setInvalidDecl();
+ return UD;
+ }
+ } else {
+ // If we asked for a non-typename and we got a type, error out,
+ // but only if this is an instantiation of an unresolved using
+ // decl. Otherwise just silently find the type name.
+ if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
+ Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+ Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+ UD->setInvalidDecl();
+ return UD;
+ }
+ }
+
+ // C++0x N2914 [namespace.udecl]p6:
+ // A using-declaration shall not name a namespace.
+ if (R.getAsSingle<NamespaceDecl>()) {
+ Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
+ << SS.getRange();
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ if (!CheckUsingShadowDecl(UD, *I, Previous))
+ BuildUsingShadowDecl(S, UD, *I);
+ }
+
+ return UD;
+}
+
+/// Additional checks for a using declaration referring to a constructor name.
+bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
+ if (UD->isTypeName()) {
+ // FIXME: Cannot specify typename when specifying constructor
+ return true;
+ }
+
+ const Type *SourceType = UD->getTargetNestedNameDecl()->getAsType();
+ assert(SourceType &&
+ "Using decl naming constructor doesn't have type in scope spec.");
+ CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
+
+ // Check whether the named type is a direct base class.
+ CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified();
+ CXXRecordDecl::base_class_iterator BaseIt, BaseE;
+ for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end();
+ BaseIt != BaseE; ++BaseIt) {
+ CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified();
+ if (CanonicalSourceType == BaseType)
+ break;
+ }
+
+ if (BaseIt == BaseE) {
+ // Did not find SourceType in the bases.
+ Diag(UD->getUsingLocation(),
+ diag::err_using_decl_constructor_not_in_direct_base)
+ << UD->getNameInfo().getSourceRange()
+ << QualType(SourceType, 0) << TargetClass;
+ return true;
+ }
+
+ BaseIt->setInheritConstructors();
+
+ return false;
+}
+
+/// Checks that the given using declaration is not an invalid
+/// redeclaration. Note that this is checking only for the using decl
+/// itself, not for any ill-formedness among the UsingShadowDecls.
+bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+ bool isTypeName,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ const LookupResult &Prev) {
+ // C++03 [namespace.udecl]p8:
+ // C++0x [namespace.udecl]p10:
+ // A using-declaration is a declaration and can therefore be used
+ // repeatedly where (and only where) multiple declarations are
+ // allowed.
+ //
+ // That's in non-member contexts.
+ if (!CurContext->getRedeclContext()->isRecord())
+ return false;
+
+ NestedNameSpecifier *Qual
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+ for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
+ NamedDecl *D = *I;
+
+ bool DTypename;
+ NestedNameSpecifier *DQual;
+ if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
+ DTypename = UD->isTypeName();
+ DQual = UD->getTargetNestedNameDecl();
+ } else if (UnresolvedUsingValueDecl *UD
+ = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+ DTypename = false;
+ DQual = UD->getTargetNestedNameSpecifier();
+ } else if (UnresolvedUsingTypenameDecl *UD
+ = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+ DTypename = true;
+ DQual = UD->getTargetNestedNameSpecifier();
+ } else continue;
+
+ // using decls differ if one says 'typename' and the other doesn't.
+ // FIXME: non-dependent using decls?
+ if (isTypeName != DTypename) continue;
+
+ // using decls differ if they name different scopes (but note that
+ // template instantiation can cause this check to trigger when it
+ // didn't before instantiation).
+ if (Context.getCanonicalNestedNameSpecifier(Qual) !=
+ Context.getCanonicalNestedNameSpecifier(DQual))
+ continue;
+
+ Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
+ Diag(D->getLocation(), diag::note_using_decl) << 1;
+ return true;
+ }
+
+ return false;
+}
+
+
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope. If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc) {
+ DeclContext *NamedContext = computeDeclContext(SS);
+
+ if (!CurContext->isRecord()) {
+ // C++03 [namespace.udecl]p3:
+ // C++0x [namespace.udecl]p8:
+ // A using-declaration for a class member shall be a member-declaration.
+
+ // If we weren't able to compute a valid scope, it must be a
+ // dependent class scope.
+ if (!NamedContext || NamedContext->isRecord()) {
+ Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
+ << SS.getRange();
+ return true;
+ }
+
+ // Otherwise, everything is known to be fine.
+ return false;
+ }
+
+ // The current scope is a record.
+
+ // If the named context is dependent, we can't decide much.
+ if (!NamedContext) {
+ // FIXME: in C++0x, we can diagnose if we can prove that the
+ // nested-name-specifier does not refer to a base class, which is
+ // still possible in some cases.
+
+ // Otherwise we have to conservatively report that things might be
+ // okay.
+ return false;
+ }
+
+ if (!NamedContext->isRecord()) {
+ // Ideally this would point at the last name in the specifier,
+ // but we don't have that level of source info.
+ Diag(SS.getRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_class)
+ << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange();
+ return true;
+ }
+
+ if (!NamedContext->isDependentContext() &&
+ RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext))
+ return true;
+
+ if (getLangOptions().CPlusPlus0x) {
+ // C++0x [namespace.udecl]p3:
+ // In a using-declaration used as a member-declaration, the
+ // nested-name-specifier shall name a base class of the class
+ // being defined.
+
+ if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
+ cast<CXXRecordDecl>(NamedContext))) {
+ if (CurContext == NamedContext) {
+ Diag(NameLoc,
+ diag::err_using_decl_nested_name_specifier_is_current_class)
+ << SS.getRange();
+ return true;
+ }
+
+ Diag(SS.getRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_base_class)
+ << (NestedNameSpecifier*) SS.getScopeRep()
+ << cast<CXXRecordDecl>(CurContext)
+ << SS.getRange();
+ return true;
+ }
+
+ return false;
+ }
+
+ // C++03 [namespace.udecl]p4:
+ // A using-declaration used as a member-declaration shall refer
+ // to a member of a base class of the class being defined [etc.].
+
+ // Salient point: SS doesn't have to name a base class as long as
+ // lookup only finds members from base classes. Therefore we can
+ // diagnose here only if we can prove that that can't happen,
+ // i.e. if the class hierarchies provably don't intersect.
+
+ // TODO: it would be nice if "definitely valid" results were cached
+ // in the UsingDecl and UsingShadowDecl so that these checks didn't
+ // need to be repeated.
+
+ struct UserData {
+ llvm::DenseSet<const CXXRecordDecl*> Bases;
+
+ static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
+ UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+ Data->Bases.insert(Base);
+ return true;
+ }
+
+ bool hasDependentBases(const CXXRecordDecl *Class) {
+ return !Class->forallBases(collect, this);
+ }
+
+ /// Returns true if the base is dependent or is one of the
+ /// accumulated base classes.
+ static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
+ UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
+ return !Data->Bases.count(Base);
+ }
+
+ bool mightShareBases(const CXXRecordDecl *Class) {
+ return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
+ }
+ };
+
+ UserData Data;
+
+ // Returns false if we find a dependent base.
+ if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+ return false;
+
+ // Returns false if the class has a dependent base or if it or one
+ // of its bases is present in the base set of the current context.
+ if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+ return false;
+
+ Diag(SS.getRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_base_class)
+ << (NestedNameSpecifier*) SS.getScopeRep()
+ << cast<CXXRecordDecl>(CurContext)
+ << SS.getRange();
+
+ return true;
+}
+
+Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident) {
+
+ // Lookup the namespace name.
+ LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
+ LookupParsedName(R, S, &SS);
+
+ // Check if we have a previous declaration with the same name.
+ NamedDecl *PrevDecl
+ = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
+ PrevDecl = 0;
+
+ if (PrevDecl) {
+ if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
+ // We already have an alias with the same name that points to the same
+ // namespace, so don't create a new one.
+ // FIXME: At some point, we'll want to create the (redundant)
+ // declaration to maintain better source information.
+ if (!R.isAmbiguous() && !R.empty() &&
+ AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
+ return 0;
+ }
+
+ unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
+ diag::err_redefinition_different_kind;
+ Diag(AliasLoc, DiagID) << Alias;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ return 0;
+ }
+
+ if (R.isAmbiguous())
+ return 0;
+
+ if (R.empty()) {
+ if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
+ CTC_NoKeywords, 0)) {
+ if (R.getAsSingle<NamespaceDecl>() ||
+ R.getAsSingle<NamespaceAliasDecl>()) {
+ if (DeclContext *DC = computeDeclContext(SS, false))
+ Diag(IdentLoc, diag::err_using_directive_member_suggest)
+ << Ident << DC << Corrected << SS.getRange()
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ else
+ Diag(IdentLoc, diag::err_using_directive_suggest)
+ << Ident << Corrected
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+
+ Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
+ << Corrected;
+
+ Ident = Corrected.getAsIdentifierInfo();
+ } else {
+ R.clear();
+ R.setLookupName(Ident);
+ }
+ }
+
+ if (R.empty()) {
+ Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
+ return 0;
+ }
+ }
+
+ NamespaceAliasDecl *AliasDecl =
+ NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
+ Alias, SS.getRange(),
+ (NestedNameSpecifier *)SS.getScopeRep(),
+ IdentLoc, R.getFoundDecl());
+
+ PushOnScopeChains(AliasDecl, S);
+ return AliasDecl;
+}
+
+namespace {
+ /// \brief Scoped object used to handle the state changes required in Sema
+ /// to implicitly define the body of a C++ member function;
+ class ImplicitlyDefinedFunctionScope {
+ Sema &S;
+ Sema::ContextRAII SavedContext;
+
+ public:
+ ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method)
+ : S(S), SavedContext(S, Method)
+ {
+ S.PushFunctionScope();
+ S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+ }
+
+ ~ImplicitlyDefinedFunctionScope() {
+ S.PopExpressionEvaluationContext();
+ S.PopFunctionOrBlockScope();
+ }
+ };
+}
+
+static CXXConstructorDecl *getDefaultConstructorUnsafe(Sema &Self,
+ CXXRecordDecl *D) {
+ ASTContext &Context = Self.Context;
+ QualType ClassType = Context.getTypeDeclType(D);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // FIXME: In C++0x, a constructor template can be a default constructor.
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
+
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isDefaultConstructor())
+ return Constructor;
+ }
+ return 0;
+}
+
+CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
+ CXXRecordDecl *ClassDecl) {
+ // C++ [class.ctor]p5:
+ // A default constructor for a class X is a constructor of class X
+ // that can be called without an argument. If there is no
+ // user-declared constructor for class X, a default constructor is
+ // implicitly declared. An implicitly-declared default constructor
+ // is an inline public member of its class.
+ assert(!ClassDecl->hasUserDeclaredConstructor() &&
+ "Should not build implicit default constructor!");
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+
+ // Direct base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+ BEnd = ClassDecl->bases_end();
+ B != BEnd; ++B) {
+ if (B->isVirtual()) // Handled below.
+ continue;
+
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = getDefaultConstructorUnsafe(*this, BaseClassDecl))
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+ // Virtual base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+ BEnd = ClassDecl->vbases_end();
+ B != BEnd; ++B) {
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = getDefaultConstructorUnsafe(*this, BaseClassDecl))
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+ // Field destructors.
+ for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+ FEnd = ClassDecl->field_end();
+ F != FEnd; ++F) {
+ if (const RecordType *RecordTy
+ = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(
+ DeclareImplicitDefaultConstructor(FieldClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = getDefaultConstructorUnsafe(*this, FieldClassDecl))
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
+ EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.NumExceptions = ExceptSpec.size();
+ EPI.Exceptions = ExceptSpec.data();
+
+ // Create the actual constructor declaration.
+ CanQualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXConstructorName(ClassType);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ CXXConstructorDecl *DefaultCon
+ = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
+ Context.getFunctionType(Context.VoidTy,
+ 0, 0, EPI),
+ /*TInfo=*/0,
+ /*isExplicit=*/false,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ DefaultCon->setAccess(AS_public);
+ DefaultCon->setImplicit();
+ DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+
+ // Note that we have declared this constructor.
+ ++ASTContext::NumImplicitDefaultConstructorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(DefaultCon, S, false);
+ ClassDecl->addDecl(DefaultCon);
+
+ return DefaultCon;
+}
+
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor) {
+ assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+ !Constructor->isUsed(false)) &&
+ "DefineImplicitDefaultConstructor - call it for implicit default ctor");
+
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
+
+ ImplicitlyDefinedFunctionScope Scope(*this, Constructor);
+ DiagnosticErrorTrap Trap(Diags);
+ if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) ||
+ Trap.hasErrorOccurred()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXConstructor << Context.getTagDeclType(ClassDecl);
+ Constructor->setInvalidDecl();
+ return;
+ }
+
+ SourceLocation Loc = Constructor->getLocation();
+ Constructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc));
+
+ Constructor->setUsed();
+ MarkVTableUsed(CurrentLocation, ClassDecl);
+}
+
+void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
+ // We start with an initial pass over the base classes to collect those that
+ // inherit constructors from. If there are none, we can forgo all further
+ // processing.
+ typedef llvm::SmallVector<const RecordType *, 4> BasesVector;
+ BasesVector BasesToInheritFrom;
+ for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(),
+ BaseE = ClassDecl->bases_end();
+ BaseIt != BaseE; ++BaseIt) {
+ if (BaseIt->getInheritConstructors()) {
+ QualType Base = BaseIt->getType();
+ if (Base->isDependentType()) {
+ // If we inherit constructors from anything that is dependent, just
+ // abort processing altogether. We'll get another chance for the
+ // instantiations.
+ return;
+ }
+ BasesToInheritFrom.push_back(Base->castAs<RecordType>());
+ }
+ }
+ if (BasesToInheritFrom.empty())
+ return;
+
+ // Now collect the constructors that we already have in the current class.
+ // Those take precedence over inherited constructors.
+ // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...]
+ // unless there is a user-declared constructor with the same signature in
+ // the class where the using-declaration appears.
+ llvm::SmallSet<const Type *, 8> ExistingConstructors;
+ for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(),
+ CtorE = ClassDecl->ctor_end();
+ CtorIt != CtorE; ++CtorIt) {
+ ExistingConstructors.insert(
+ Context.getCanonicalType(CtorIt->getType()).getTypePtr());
+ }
+
+ Scope *S = getScopeForContext(ClassDecl);
+ DeclarationName CreatedCtorName =
+ Context.DeclarationNames.getCXXConstructorName(
+ ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified());
+
+ // Now comes the true work.
+ // First, we keep a map from constructor types to the base that introduced
+ // them. Needed for finding conflicting constructors. We also keep the
+ // actually inserted declarations in there, for pretty diagnostics.
+ typedef std::pair<CanQualType, CXXConstructorDecl *> ConstructorInfo;
+ typedef llvm::DenseMap<const Type *, ConstructorInfo> ConstructorToSourceMap;
+ ConstructorToSourceMap InheritedConstructors;
+ for (BasesVector::iterator BaseIt = BasesToInheritFrom.begin(),
+ BaseE = BasesToInheritFrom.end();
+ BaseIt != BaseE; ++BaseIt) {
+ const RecordType *Base = *BaseIt;
+ CanQualType CanonicalBase = Base->getCanonicalTypeUnqualified();
+ CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getDecl());
+ for (CXXRecordDecl::ctor_iterator CtorIt = BaseDecl->ctor_begin(),
+ CtorE = BaseDecl->ctor_end();
+ CtorIt != CtorE; ++CtorIt) {
+ // Find the using declaration for inheriting this base's constructors.
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXConstructorName(CanonicalBase);
+ UsingDecl *UD = dyn_cast_or_null<UsingDecl>(
+ LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName));
+ SourceLocation UsingLoc = UD ? UD->getLocation() :
+ ClassDecl->getLocation();
+
+ // C++0x [class.inhctor]p1: The candidate set of inherited constructors
+ // from the class X named in the using-declaration consists of actual
+ // constructors and notional constructors that result from the
+ // transformation of defaulted parameters as follows:
+ // - all non-template default constructors of X, and
+ // - for each non-template constructor of X that has at least one
+ // parameter with a default argument, the set of constructors that
+ // results from omitting any ellipsis parameter specification and
+ // successively omitting parameters with a default argument from the
+ // end of the parameter-type-list.
+ CXXConstructorDecl *BaseCtor = *CtorIt;
+ bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor();
+ const FunctionProtoType *BaseCtorType =
+ BaseCtor->getType()->getAs<FunctionProtoType>();
+
+ for (unsigned params = BaseCtor->getMinRequiredArguments(),
+ maxParams = BaseCtor->getNumParams();
+ params <= maxParams; ++params) {
+ // Skip default constructors. They're never inherited.
+ if (params == 0)
+ continue;
+ // Skip copy and move constructors for the same reason.
+ if (CanBeCopyOrMove && params == 1)
+ continue;
+
+ // Build up a function type for this particular constructor.
+ // FIXME: The working paper does not consider that the exception spec
+ // for the inheriting constructor might be larger than that of the
+ // source. This code doesn't yet, either.
+ const Type *NewCtorType;
+ if (params == maxParams)
+ NewCtorType = BaseCtorType;
+ else {
+ llvm::SmallVector<QualType, 16> Args;
+ for (unsigned i = 0; i < params; ++i) {
+ Args.push_back(BaseCtorType->getArgType(i));
+ }
+ FunctionProtoType::ExtProtoInfo ExtInfo =
+ BaseCtorType->getExtProtoInfo();
+ ExtInfo.Variadic = false;
+ NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(),
+ Args.data(), params, ExtInfo)
+ .getTypePtr();
+ }
+ const Type *CanonicalNewCtorType =
+ Context.getCanonicalType(NewCtorType);
+
+ // Now that we have the type, first check if the class already has a
+ // constructor with this signature.
+ if (ExistingConstructors.count(CanonicalNewCtorType))
+ continue;
+
+ // Then we check if we have already declared an inherited constructor
+ // with this signature.
+ std::pair<ConstructorToSourceMap::iterator, bool> result =
+ InheritedConstructors.insert(std::make_pair(
+ CanonicalNewCtorType,
+ std::make_pair(CanonicalBase, (CXXConstructorDecl*)0)));
+ if (!result.second) {
+ // Already in the map. If it came from a different class, that's an
+ // error. Not if it's from the same.
+ CanQualType PreviousBase = result.first->second.first;
+ if (CanonicalBase != PreviousBase) {
+ const CXXConstructorDecl *PrevCtor = result.first->second.second;
+ const CXXConstructorDecl *PrevBaseCtor =
+ PrevCtor->getInheritedConstructor();
+ assert(PrevBaseCtor && "Conflicting constructor was not inherited");
+
+ Diag(UsingLoc, diag::err_using_decl_constructor_conflict);
+ Diag(BaseCtor->getLocation(),
+ diag::note_using_decl_constructor_conflict_current_ctor);
+ Diag(PrevBaseCtor->getLocation(),
+ diag::note_using_decl_constructor_conflict_previous_ctor);
+ Diag(PrevCtor->getLocation(),
+ diag::note_using_decl_constructor_conflict_previous_using);
+ }
+ continue;
+ }
+
+ // OK, we're there, now add the constructor.
+ // C++0x [class.inhctor]p8: [...] that would be performed by a
+ // user-writtern inline constructor [...]
+ DeclarationNameInfo DNI(CreatedCtorName, UsingLoc);
+ CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create(
+ Context, ClassDecl, DNI, QualType(NewCtorType, 0), /*TInfo=*/0,
+ BaseCtor->isExplicit(), /*Inline=*/true,
+ /*ImplicitlyDeclared=*/true);
+ NewCtor->setAccess(BaseCtor->getAccess());
+
+ // Build up the parameter decls and add them.
+ llvm::SmallVector<ParmVarDecl *, 16> ParamDecls;
+ for (unsigned i = 0; i < params; ++i) {
+ ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, UsingLoc,
+ /*IdentifierInfo=*/0,
+ BaseCtorType->getArgType(i),
+ /*TInfo=*/0, SC_None,
+ SC_None, /*DefaultArg=*/0));
+ }
+ NewCtor->setParams(ParamDecls.data(), ParamDecls.size());
+ NewCtor->setInheritedConstructor(BaseCtor);
+
+ PushOnScopeChains(NewCtor, S, false);
+ ClassDecl->addDecl(NewCtor);
+ result.first->second.second = NewCtor;
+ }
+ }
+ }
+}
+
+CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
+ // C++ [class.dtor]p2:
+ // If a class has no user-declared destructor, a destructor is
+ // declared implicitly. An implicitly-declared destructor is an
+ // inline public member of its class.
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have
+ // an exception-specification.
+ ImplicitExceptionSpecification ExceptSpec(Context);
+
+ // Direct base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+ BEnd = ClassDecl->bases_end();
+ B != BEnd; ++B) {
+ if (B->isVirtual()) // Handled below.
+ continue;
+
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+ }
+
+ // Virtual base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+ BEnd = ClassDecl->vbases_end();
+ B != BEnd; ++B) {
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+ }
+
+ // Field destructors.
+ for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+ FEnd = ClassDecl->field_end();
+ F != FEnd; ++F) {
+ if (const RecordType *RecordTy
+ = Context.getBaseElementType(F->getType())->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
+ }
+
+ // Create the actual destructor declaration.
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
+ EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.NumExceptions = ExceptSpec.size();
+ EPI.Exceptions = ExceptSpec.data();
+ QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
+
+ CanQualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXDestructorName(ClassType);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ CXXDestructorDecl *Destructor
+ = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty, 0,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ Destructor->setAccess(AS_public);
+ Destructor->setImplicit();
+ Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+
+ // Note that we have declared this destructor.
+ ++ASTContext::NumImplicitDestructorsDeclared;
+
+ // Introduce this destructor into its scope.
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(Destructor, S, false);
+ ClassDecl->addDecl(Destructor);
+
+ // This could be uniqued if it ever proves significant.
+ Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
+
+ AddOverriddenMethods(ClassDecl, Destructor);
+
+ return Destructor;
+}
+
+void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor) {
+ assert((Destructor->isImplicit() && !Destructor->isUsed(false)) &&
+ "DefineImplicitDestructor - call it for implicit default dtor");
+ CXXRecordDecl *ClassDecl = Destructor->getParent();
+ assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+ if (Destructor->isInvalidDecl())
+ return;
+
+ ImplicitlyDefinedFunctionScope Scope(*this, Destructor);
+
+ DiagnosticErrorTrap Trap(Diags);
+ MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
+ Destructor->getParent());
+
+ if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXDestructor << Context.getTagDeclType(ClassDecl);
+
+ Destructor->setInvalidDecl();
+ return;
+ }
+
+ SourceLocation Loc = Destructor->getLocation();
+ Destructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc));
+
+ Destructor->setUsed();
+ MarkVTableUsed(CurrentLocation, ClassDecl);
+}
+
+/// \brief Builds a statement that copies the given entity from \p From to
+/// \c To.
+///
+/// This routine is used to copy the members of a class with an
+/// implicitly-declared copy assignment operator. When the entities being
+/// copied are arrays, this routine builds for loops to copy them.
+///
+/// \param S The Sema object used for type-checking.
+///
+/// \param Loc The location where the implicit copy is being generated.
+///
+/// \param T The type of the expressions being copied. Both expressions must
+/// have this type.
+///
+/// \param To The expression we are copying to.
+///
+/// \param From The expression we are copying from.
+///
+/// \param CopyingBaseSubobject Whether we're copying a base subobject.
+/// Otherwise, it's a non-static member subobject.
+///
+/// \param Depth Internal parameter recording the depth of the recursion.
+///
+/// \returns A statement or a loop that copies the expressions.
+static StmtResult
+BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
+ Expr *To, Expr *From,
+ bool CopyingBaseSubobject, unsigned Depth = 0) {
+ // C++0x [class.copy]p30:
+ // Each subobject is assigned in the manner appropriate to its type:
+ //
+ // - if the subobject is of class type, the copy assignment operator
+ // for the class is used (as if by explicit qualification; that is,
+ // ignoring any possible virtual overriding functions in more derived
+ // classes);
+ if (const RecordType *RecordTy = T->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+
+ // Look for operator=.
+ DeclarationName Name
+ = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(OpLookup, ClassDecl, false);
+
+ // Filter out any result that isn't a copy-assignment operator.
+ LookupResult::Filter F = OpLookup.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ if (Method->isCopyAssignmentOperator())
+ continue;
+
+ F.erase();
+ }
+ F.done();
+
+ // Suppress the protected check (C++ [class.protected]) for each of the
+ // assignment operators we found. This strange dance is required when
+ // we're assigning via a base classes's copy-assignment operator. To
+ // ensure that we're getting the right base class subobject (without
+ // ambiguities), we need to cast "this" to that subobject type; to
+ // ensure that we don't go through the virtual call mechanism, we need
+ // to qualify the operator= name with the base class (see below). However,
+ // this means that if the base class has a protected copy assignment
+ // operator, the protected member access check will fail. So, we
+ // rewrite "protected" access to "public" access in this case, since we
+ // know by construction that we're calling from a derived class.
+ if (CopyingBaseSubobject) {
+ for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end();
+ L != LEnd; ++L) {
+ if (L.getAccess() == AS_protected)
+ L.setAccess(AS_public);
+ }
+ }
+
+ // Create the nested-name-specifier that will be used to qualify the
+ // reference to operator=; this is required to suppress the virtual
+ // call mechanism.
+ CXXScopeSpec SS;
+ SS.setRange(Loc);
+ SS.setScopeRep(NestedNameSpecifier::Create(S.Context, 0, false,
+ T.getTypePtr()));
+
+ // Create the reference to operator=.
+ ExprResult OpEqualRef
+ = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
+ /*FirstQualifierInScope=*/0, OpLookup,
+ /*TemplateArgs=*/0,
+ /*SuppressQualifierCheck=*/true);
+ if (OpEqualRef.isInvalid())
+ return StmtError();
+
+ // Build the call to the assignment operator.
+
+ ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
+ OpEqualRef.takeAs<Expr>(),
+ Loc, &From, 1, Loc);
+ if (Call.isInvalid())
+ return StmtError();
+
+ return S.Owned(Call.takeAs<Stmt>());
+ }
+
+ // - if the subobject is of scalar type, the built-in assignment
+ // operator is used.
+ const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
+ if (!ArrayTy) {
+ ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
+ if (Assignment.isInvalid())
+ return StmtError();
+
+ return S.Owned(Assignment.takeAs<Stmt>());
+ }
+
+ // - if the subobject is an array, each element is assigned, in the
+ // manner appropriate to the element type;
+
+ // Construct a loop over the array bounds, e.g.,
+ //
+ // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
+ //
+ // that will copy each of the array elements.
+ QualType SizeType = S.Context.getSizeType();
+
+ // Create the iteration variable.
+ IdentifierInfo *IterationVarName = 0;
+ {
+ llvm::SmallString<8> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "__i" << Depth;
+ IterationVarName = &S.Context.Idents.get(OS.str());
+ }
+ VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc,
+ IterationVarName, SizeType,
+ S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+ SC_None, SC_None);
+
+ // Initialize the iteration variable to zero.
+ llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
+ IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
+
+ // Create a reference to the iteration variable; we'll use this several
+ // times throughout.
+ Expr *IterationVarRef
+ = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take();
+ assert(IterationVarRef && "Reference to invented variable cannot fail!");
+
+ // Create the DeclStmt that holds the iteration variable.
+ Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
+
+ // Create the comparison against the array bound.
+ llvm::APInt Upper
+ = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
+ Expr *Comparison
+ = new (S.Context) BinaryOperator(IterationVarRef,
+ IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
+ BO_NE, S.Context.BoolTy,
+ VK_RValue, OK_Ordinary, Loc);
+
+ // Create the pre-increment of the iteration variable.
+ Expr *Increment
+ = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
+ VK_LValue, OK_Ordinary, Loc);
+
+ // Subscript the "from" and "to" expressions with the iteration variable.
+ From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
+ IterationVarRef, Loc));
+ To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
+ IterationVarRef, Loc));
+
+ // Build the copy for an individual element of the array.
+ StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(),
+ To, From, CopyingBaseSubobject,
+ Depth + 1);
+ if (Copy.isInvalid())
+ return StmtError();
+
+ // Construct the loop that copies all elements of this array.
+ return S.ActOnForStmt(Loc, Loc, InitStmt,
+ S.MakeFullExpr(Comparison),
+ 0, S.MakeFullExpr(Increment),
+ Loc, Copy.take());
+}
+
+/// \brief Determine whether the given class has a copy assignment operator
+/// that accepts a const-qualified argument.
+static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) {
+ CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(CClass);
+
+ if (!Class->hasDeclaredCopyAssignment())
+ S.DeclareImplicitCopyAssignment(Class);
+
+ QualType ClassType = S.Context.getCanonicalType(S.Context.getTypeDeclType(Class));
+ DeclarationName OpName
+ = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = Class->lookup(OpName); Op != OpEnd; ++Op) {
+ // C++ [class.copy]p9:
+ // A user-declared copy assignment operator is a non-static non-template
+ // member function of class X with exactly one parameter of type X, X&,
+ // const X&, volatile X& or const volatile X&.
+ const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
+ if (!Method)
+ continue;
+
+ if (Method->isStatic())
+ continue;
+ if (Method->getPrimaryTemplate())
+ continue;
+ const FunctionProtoType *FnType =
+ Method->getType()->getAs<FunctionProtoType>();
+ assert(FnType && "Overloaded operator has no prototype.");
+ // Don't assert on this; an invalid decl might have been left in the AST.
+ if (FnType->getNumArgs() != 1 || FnType->isVariadic())
+ continue;
+ bool AcceptsConst = true;
+ QualType ArgType = FnType->getArgType(0);
+ if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()){
+ ArgType = Ref->getPointeeType();
+ // Is it a non-const lvalue reference?
+ if (!ArgType.isConstQualified())
+ AcceptsConst = false;
+ }
+ if (!S.Context.hasSameUnqualifiedType(ArgType, ClassType))
+ continue;
+
+ // We have a single argument of type cv X or cv X&, i.e. we've found the
+ // copy assignment operator. Return whether it accepts const arguments.
+ return AcceptsConst;
+ }
+ assert(Class->isInvalidDecl() &&
+ "No copy assignment operator declared in valid code.");
+ return false;
+}
+
+CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
+ // Note: The following rules are largely analoguous to the copy
+ // constructor rules. Note that virtual bases are not taken into account
+ // for determining the argument type of the operator. Note also that
+ // operators taking an object instead of a reference are allowed.
+
+
+ // C++ [class.copy]p10:
+ // If the class definition does not explicitly declare a copy
+ // assignment operator, one is declared implicitly.
+ // The implicitly-defined copy assignment operator for a class X
+ // will have the form
+ //
+ // X& X::operator=(const X&)
+ //
+ // if
+ bool HasConstCopyAssignment = true;
+
+ // -- each direct base class B of X has a copy assignment operator
+ // whose parameter is of type const B&, const volatile B& or B,
+ // and
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ HasConstCopyAssignment && Base != BaseEnd; ++Base) {
+ assert(!Base->getType()->isDependentType() &&
+ "Cannot generate implicit members for class with dependent bases.");
+ const CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ HasConstCopyAssignment = hasConstCopyAssignment(*this, BaseClassDecl);
+ }
+
+ // -- for all the nonstatic data members of X that are of a class
+ // type M (or array thereof), each such class type has a copy
+ // assignment operator whose parameter is of type const M&,
+ // const volatile M& or M.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ HasConstCopyAssignment && Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ const CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ HasConstCopyAssignment = hasConstCopyAssignment(*this, FieldClassDecl);
+ }
+ }
+
+ // Otherwise, the implicitly declared copy assignment operator will
+ // have the form
+ //
+ // X& X::operator=(X&)
+ QualType ArgType = Context.getTypeDeclType(ClassDecl);
+ QualType RetType = Context.getLValueReferenceType(ArgType);
+ if (HasConstCopyAssignment)
+ ArgType = ArgType.withConst();
+ ArgType = Context.getLValueReferenceType(ArgType);
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd; ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (!BaseClassDecl->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(BaseClassDecl);
+
+ if (CXXMethodDecl *CopyAssign
+ = BaseClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))
+ ExceptSpec.CalledDecl(CopyAssign);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+
+ if (!FieldClassDecl->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(FieldClassDecl);
+
+ if (CXXMethodDecl *CopyAssign
+ = FieldClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))
+ ExceptSpec.CalledDecl(CopyAssign);
+ }
+ }
+
+ // An implicitly-declared copy assignment operator is an inline public
+ // member of its class.
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
+ EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.NumExceptions = ExceptSpec.size();
+ EPI.Exceptions = ExceptSpec.data();
+ DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ CXXMethodDecl *CopyAssignment
+ = CXXMethodDecl::Create(Context, ClassDecl, NameInfo,
+ Context.getFunctionType(RetType, &ArgType, 1, EPI),
+ /*TInfo=*/0, /*isStatic=*/false,
+ /*StorageClassAsWritten=*/SC_None,
+ /*isInline=*/true);
+ CopyAssignment->setAccess(AS_public);
+ CopyAssignment->setImplicit();
+ CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
+
+ // Add the parameter to the operator.
+ ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
+ ClassDecl->getLocation(),
+ /*Id=*/0,
+ ArgType, /*TInfo=*/0,
+ SC_None,
+ SC_None, 0);
+ CopyAssignment->setParams(&FromParam, 1);
+
+ // Note that we have added this copy-assignment operator.
+ ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyAssignment, S, false);
+ ClassDecl->addDecl(CopyAssignment);
+
+ AddOverriddenMethods(ClassDecl, CopyAssignment);
+ return CopyAssignment;
+}
+
+void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *CopyAssignOperator) {
+ assert((CopyAssignOperator->isImplicit() &&
+ CopyAssignOperator->isOverloadedOperator() &&
+ CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
+ !CopyAssignOperator->isUsed(false)) &&
+ "DefineImplicitCopyAssignment called for wrong function");
+
+ CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
+
+ if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) {
+ CopyAssignOperator->setInvalidDecl();
+ return;
+ }
+
+ CopyAssignOperator->setUsed();
+
+ ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator);
+ DiagnosticErrorTrap Trap(Diags);
+
+ // C++0x [class.copy]p30:
+ // The implicitly-defined or explicitly-defaulted copy assignment operator
+ // for a non-union class X performs memberwise copy assignment of its
+ // subobjects. The direct base classes of X are assigned first, in the
+ // order of their declaration in the base-specifier-list, and then the
+ // immediate non-static data members of X are assigned, in the order in
+ // which they were declared in the class definition.
+
+ // The statements that form the synthesized function body.
+ ASTOwningVector<Stmt*> Statements(*this);
+
+ // The parameter for the "other" object, which we are copying from.
+ ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
+ Qualifiers OtherQuals = Other->getType().getQualifiers();
+ QualType OtherRefType = Other->getType();
+ if (const LValueReferenceType *OtherRef
+ = OtherRefType->getAs<LValueReferenceType>()) {
+ OtherRefType = OtherRef->getPointeeType();
+ OtherQuals = OtherRefType.getQualifiers();
+ }
+
+ // Our location for everything implicitly-generated.
+ SourceLocation Loc = CopyAssignOperator->getLocation();
+
+ // Construct a reference to the "other" object. We'll be using this
+ // throughout the generated ASTs.
+ Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
+ assert(OtherRef && "Reference to parameter cannot fail!");
+
+ // Construct the "this" pointer. We'll be using this throughout the generated
+ // ASTs.
+ Expr *This = ActOnCXXThis(Loc).takeAs<Expr>();
+ assert(This && "Reference to this cannot fail!");
+
+ // Assign base classes.
+ bool Invalid = false;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
+ // Form the assignment:
+ // static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
+ QualType BaseType = Base->getType().getUnqualifiedType();
+ if (!BaseType->isRecordType()) {
+ Invalid = true;
+ continue;
+ }
+
+ CXXCastPath BasePath;
+ BasePath.push_back(Base);
+
+ // Construct the "from" expression, which is an implicit cast to the
+ // appropriately-qualified base type.
+ Expr *From = OtherRef;
+ ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
+
+ // Dereference "this".
+ ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+
+ // Implicitly cast "this" to the appropriately-qualified base type.
+ Expr *ToE = To.takeAs<Expr>();
+ ImpCastExprToType(ToE,
+ Context.getCVRQualifiedType(BaseType,
+ CopyAssignOperator->getTypeQualifiers()),
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
+ To = Owned(ToE);
+
+ // Build the copy.
+ StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
+ To.get(), From,
+ /*CopyingBaseSubobject=*/true);
+ if (Copy.isInvalid()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+ CopyAssignOperator->setInvalidDecl();
+ return;
+ }
+
+ // Success! Record the copy.
+ Statements.push_back(Copy.takeAs<Expr>());
+ }
+
+ // \brief Reference to the __builtin_memcpy function.
+ Expr *BuiltinMemCpyRef = 0;
+ // \brief Reference to the __builtin_objc_memmove_collectable function.
+ Expr *CollectableMemCpyRef = 0;
+
+ // Assign non-static members.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ // Check for members of reference type; we can't copy those.
+ if (Field->getType()->isReferenceType()) {
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+ << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
+ Diag(Field->getLocation(), diag::note_declared_at);
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+ Invalid = true;
+ continue;
+ }
+
+ // Check for members of const-qualified, non-class type.
+ QualType BaseType = Context.getBaseElementType(Field->getType());
+ if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+ << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
+ Diag(Field->getLocation(), diag::note_declared_at);
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+ Invalid = true;
+ continue;
+ }
+
+ QualType FieldType = Field->getType().getNonReferenceType();
+ if (FieldType->isIncompleteArrayType()) {
+ assert(ClassDecl->hasFlexibleArrayMember() &&
+ "Incomplete array type is not valid");
+ continue;
+ }
+
+ // Build references to the field in the object we're copying from and to.
+ CXXScopeSpec SS; // Intentionally empty
+ LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
+ LookupMemberName);
+ MemberLookup.addDecl(*Field);
+ MemberLookup.resolveKind();
+ ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
+ Loc, /*IsArrow=*/false,
+ SS, 0, MemberLookup, 0);
+ ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
+ Loc, /*IsArrow=*/true,
+ SS, 0, MemberLookup, 0);
+ assert(!From.isInvalid() && "Implicit field reference cannot fail");
+ assert(!To.isInvalid() && "Implicit field reference cannot fail");
+
+ // If the field should be copied with __builtin_memcpy rather than via
+ // explicit assignments, do so. This optimization only applies for arrays
+ // of scalars and arrays of class type with trivial copy-assignment
+ // operators.
+ if (FieldType->isArrayType() &&
+ (!BaseType->isRecordType() ||
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl())
+ ->hasTrivialCopyAssignment())) {
+ // Compute the size of the memory buffer to be copied.
+ QualType SizeType = Context.getSizeType();
+ llvm::APInt Size(Context.getTypeSize(SizeType),
+ Context.getTypeSizeInChars(BaseType).getQuantity());
+ for (const ConstantArrayType *Array
+ = Context.getAsConstantArrayType(FieldType);
+ Array;
+ Array = Context.getAsConstantArrayType(Array->getElementType())) {
+ llvm::APInt ArraySize
+ = Array->getSize().zextOrTrunc(Size.getBitWidth());
+ Size *= ArraySize;
+ }
+
+ // Take the address of the field references for "from" and "to".
+ From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get());
+ To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get());
+
+ bool NeedsCollectableMemCpy =
+ (BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+
+ if (NeedsCollectableMemCpy) {
+ if (!CollectableMemCpyRef) {
+ // Create a reference to the __builtin_objc_memmove_collectable function.
+ LookupResult R(*this,
+ &Context.Idents.get("__builtin_objc_memmove_collectable"),
+ Loc, LookupOrdinaryName);
+ LookupName(R, TUScope, true);
+
+ FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
+ if (!CollectableMemCpy) {
+ // Something went horribly wrong earlier, and we will have
+ // complained about it.
+ Invalid = true;
+ continue;
+ }
+
+ CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
+ CollectableMemCpy->getType(),
+ VK_LValue, Loc, 0).take();
+ assert(CollectableMemCpyRef && "Builtin reference cannot fail");
+ }
+ }
+ // Create a reference to the __builtin_memcpy builtin function.
+ else if (!BuiltinMemCpyRef) {
+ LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
+ LookupOrdinaryName);
+ LookupName(R, TUScope, true);
+
+ FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>();
+ if (!BuiltinMemCpy) {
+ // Something went horribly wrong earlier, and we will have complained
+ // about it.
+ Invalid = true;
+ continue;
+ }
+
+ BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
+ BuiltinMemCpy->getType(),
+ VK_LValue, Loc, 0).take();
+ assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
+ }
+
+ ASTOwningVector<Expr*> CallArgs(*this);
+ CallArgs.push_back(To.takeAs<Expr>());
+ CallArgs.push_back(From.takeAs<Expr>());
+ CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
+ ExprResult Call = ExprError();
+ if (NeedsCollectableMemCpy)
+ Call = ActOnCallExpr(/*Scope=*/0,
+ CollectableMemCpyRef,
+ Loc, move_arg(CallArgs),
+ Loc);
+ else
+ Call = ActOnCallExpr(/*Scope=*/0,
+ BuiltinMemCpyRef,
+ Loc, move_arg(CallArgs),
+ Loc);
+
+ assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
+ Statements.push_back(Call.takeAs<Expr>());
+ continue;
+ }
+
+ // Build the copy of this field.
+ StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType,
+ To.get(), From.get(),
+ /*CopyingBaseSubobject=*/false);
+ if (Copy.isInvalid()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+ CopyAssignOperator->setInvalidDecl();
+ return;
+ }
+
+ // Success! Record the copy.
+ Statements.push_back(Copy.takeAs<Stmt>());
+ }
+
+ if (!Invalid) {
+ // Add a "return *this;"
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
+
+ StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
+ if (Return.isInvalid())
+ Invalid = true;
+ else {
+ Statements.push_back(Return.takeAs<Stmt>());
+
+ if (Trap.hasErrorOccurred()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
+ Invalid = true;
+ }
+ }
+ }
+
+ if (Invalid) {
+ CopyAssignOperator->setInvalidDecl();
+ return;
+ }
+
+ StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements),
+ /*isStmtExpr=*/false);
+ assert(!Body.isInvalid() && "Compound statement creation cannot fail");
+ CopyAssignOperator->setBody(Body.takeAs<Stmt>());
+}
+
+CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
+ CXXRecordDecl *ClassDecl) {
+ // C++ [class.copy]p4:
+ // If the class definition does not explicitly declare a copy
+ // constructor, one is declared implicitly.
+
+ // C++ [class.copy]p5:
+ // The implicitly-declared copy constructor for a class X will
+ // have the form
+ //
+ // X::X(const X&)
+ //
+ // if
+ bool HasConstCopyConstructor = true;
+
+ // -- each direct or virtual base class B of X has a copy
+ // constructor whose first parameter is of type const B& or
+ // const volatile B&, and
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ HasConstCopyConstructor && Base != BaseEnd;
+ ++Base) {
+ // Virtual bases are handled below.
+ if (Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ HasConstCopyConstructor
+ = BaseClassDecl->hasConstCopyConstructor(Context);
+ }
+
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ HasConstCopyConstructor && Base != BaseEnd;
+ ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ HasConstCopyConstructor
+ = BaseClassDecl->hasConstCopyConstructor(Context);
+ }
+
+ // -- for all the nonstatic data members of X that are of a
+ // class type M (or array thereof), each such class type
+ // has a copy constructor whose first parameter is of type
+ // const M& or const volatile M&.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ HasConstCopyConstructor && Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
+ HasConstCopyConstructor
+ = FieldClassDecl->hasConstCopyConstructor(Context);
+ }
+ }
+
+ // Otherwise, the implicitly declared copy constructor will have
+ // the form
+ //
+ // X::X(X&)
+ QualType ClassType = Context.getTypeDeclType(ClassDecl);
+ QualType ArgType = ClassType;
+ if (HasConstCopyConstructor)
+ ArgType = ArgType.withConst();
+ ArgType = Context.getLValueReferenceType(ArgType);
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+ unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd;
+ ++Base) {
+ // Virtual bases are handled below.
+ if (Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = BaseClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ Base != BaseEnd;
+ ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = BaseClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = FieldClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ }
+
+ // An implicitly-declared copy constructor is an inline public
+ // member of its class.
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.HasExceptionSpec = ExceptSpec.hasExceptionSpecification();
+ EPI.HasAnyExceptionSpec = ExceptSpec.hasAnyExceptionSpecification();
+ EPI.NumExceptions = ExceptSpec.size();
+ EPI.Exceptions = ExceptSpec.data();
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType));
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
+ CXXConstructorDecl *CopyConstructor
+ = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
+ Context.getFunctionType(Context.VoidTy,
+ &ArgType, 1, EPI),
+ /*TInfo=*/0,
+ /*isExplicit=*/false,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ CopyConstructor->setAccess(AS_public);
+ CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
+
+ // Note that we have declared this constructor.
+ ++ASTContext::NumImplicitCopyConstructorsDeclared;
+
+ // Add the parameter to the constructor.
+ ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
+ ClassDecl->getLocation(),
+ /*IdentifierInfo=*/0,
+ ArgType, /*TInfo=*/0,
+ SC_None,
+ SC_None, 0);
+ CopyConstructor->setParams(&FromParam, 1);
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyConstructor, S, false);
+ ClassDecl->addDecl(CopyConstructor);
+
+ return CopyConstructor;
+}
+
+void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *CopyConstructor,
+ unsigned TypeQuals) {
+ assert((CopyConstructor->isImplicit() &&
+ CopyConstructor->isCopyConstructor(TypeQuals) &&
+ !CopyConstructor->isUsed(false)) &&
+ "DefineImplicitCopyConstructor - call it for implicit copy ctor");
+
+ CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
+ assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+ ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor);
+ DiagnosticErrorTrap Trap(Diags);
+
+ if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) ||
+ Trap.hasErrorOccurred()) {
+ Diag(CurrentLocation, diag::note_member_synthesized_at)
+ << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
+ CopyConstructor->setInvalidDecl();
+ } else {
+ CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(),
+ CopyConstructor->getLocation(),
+ MultiStmtArg(*this, 0, 0),
+ /*isStmtExpr=*/false)
+ .takeAs<Stmt>());
+ }
+
+ CopyConstructor->setUsed();
+}
+
+ExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor,
+ MultiExprArg ExprArgs,
+ bool RequiresZeroInit,
+ unsigned ConstructKind,
+ SourceRange ParenRange) {
+ bool Elidable = false;
+
+ // C++0x [class.copy]p34:
+ // When certain criteria are met, an implementation is allowed to
+ // omit the copy/move construction of a class object, even if the
+ // copy/move constructor and/or destructor for the object have
+ // side effects. [...]
+ // - when a temporary class object that has not been bound to a
+ // reference (12.2) would be copied/moved to a class object
+ // with the same cv-unqualified type, the copy/move operation
+ // can be omitted by constructing the temporary object
+ // directly into the target of the omitted copy/move
+ if (ConstructKind == CXXConstructExpr::CK_Complete &&
+ Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) {
+ Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
+ Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent());
+ }
+
+ return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
+ Elidable, move(ExprArgs), RequiresZeroInit,
+ ConstructKind, ParenRange);
+}
+
+/// BuildCXXConstructExpr - Creates a complete call to a constructor,
+/// including handling of its default argument expressions.
+ExprResult
+Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
+ CXXConstructorDecl *Constructor, bool Elidable,
+ MultiExprArg ExprArgs,
+ bool RequiresZeroInit,
+ unsigned ConstructKind,
+ SourceRange ParenRange) {
+ unsigned NumExprs = ExprArgs.size();
+ Expr **Exprs = (Expr **)ExprArgs.release();
+
+ MarkDeclarationReferenced(ConstructLoc, Constructor);
+ return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
+ Constructor, Elidable, Exprs, NumExprs,
+ RequiresZeroInit,
+ static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
+ ParenRange));
+}
+
+bool Sema::InitializeVarWithConstructor(VarDecl *VD,
+ CXXConstructorDecl *Constructor,
+ MultiExprArg Exprs) {
+ // FIXME: Provide the correct paren SourceRange when available.
+ ExprResult TempResult =
+ BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
+ move(Exprs), false, CXXConstructExpr::CK_Complete,
+ SourceRange());
+ if (TempResult.isInvalid())
+ return true;
+
+ Expr *Temp = TempResult.takeAs<Expr>();
+ CheckImplicitConversions(Temp, VD->getLocation());
+ MarkDeclarationReferenced(VD->getLocation(), Constructor);
+ Temp = MaybeCreateExprWithCleanups(Temp);
+ VD->setInit(Temp);
+
+ return false;
+}
+
+void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
+ if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() &&
+ !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) {
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
+ MarkDeclarationReferenced(VD->getLocation(), Destructor);
+ CheckDestructorAccess(VD->getLocation(), Destructor,
+ PDiag(diag::err_access_dtor_var)
+ << VD->getDeclName()
+ << VD->getType());
+
+ // TODO: this should be re-enabled for static locals by !CXAAtExit
+ if (!VD->isInvalidDecl() && VD->hasGlobalStorage() && !VD->isStaticLocal())
+ Diag(VD->getLocation(), diag::warn_global_destructor);
+ }
+}
+
+/// AddCXXDirectInitializerToDecl - This action is called immediately after
+/// ActOnDeclarator, when a C++ direct initializer is present.
+/// e.g: "int x(1);"
+void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc,
+ bool TypeMayContainAuto) {
+ assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
+
+ // If there is no declaration, there was an error parsing it. Just ignore
+ // the initializer.
+ if (RealDecl == 0)
+ return;
+
+ VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
+ if (!VDecl) {
+ Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
+ // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+ VDecl->setParsingAutoInit(false);
+
+ // FIXME: n3225 doesn't actually seem to indicate this is ill-formed
+ if (Exprs.size() > 1) {
+ Diag(Exprs.get()[1]->getSourceRange().getBegin(),
+ diag::err_auto_var_init_multiple_expressions)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ }
+
+ Expr *Init = Exprs.get()[0];
+ QualType DeducedType;
+ if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+ Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+ << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+ << Init->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ }
+ VDecl->setType(DeducedType);
+
+ // If this is a redeclaration, check that the type we just deduced matches
+ // the previously declared type.
+ if (VarDecl *Old = VDecl->getPreviousDeclaration())
+ MergeVarDeclTypes(VDecl, Old);
+ }
+
+ // We will represent direct-initialization similarly to copy-initialization:
+ // int x(1); -as-> int x = 1;
+ // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
+ //
+ // Clients that want to distinguish between the two forms, can check for
+ // direct initializer using VarDecl::hasCXXDirectInitializer().
+ // A major benefit is that clients that don't particularly care about which
+ // exactly form was it (like the CodeGen) can handle both cases without
+ // special case code.
+
+ // C++ 8.5p11:
+ // The form of initialization (using parentheses or '=') is generally
+ // insignificant, but does matter when the entity being initialized has a
+ // class type.
+
+ if (!VDecl->getType()->isDependentType() &&
+ RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_typecheck_decl_incomplete_type)) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
+
+ const VarDecl *Def;
+ if ((Def = VDecl->getDefinition()) && Def != VDecl) {
+ Diag(VDecl->getLocation(), diag::err_redefinition)
+ << VDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ // C++ [class.static.data]p4
+ // If a static data member is of const integral or const
+ // enumeration type, its declaration in the class definition can
+ // specify a constant-initializer which shall be an integral
+ // constant expression (5.19). In that case, the member can appear
+ // in integral constant expressions. The member shall still be
+ // defined in a namespace scope if it is used in the program and the
+ // namespace scope definition shall not contain an initializer.
+ //
+ // We already performed a redefinition check above, but for static
+ // data members we also need to check whether there was an in-class
+ // declaration with an initializer.
+ const VarDecl* PrevInit = 0;
+ if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName();
+ Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ return;
+ }
+
+ bool IsDependent = false;
+ for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
+ if (DiagnoseUnexpandedParameterPack(Exprs.get()[I], UPPC_Expression)) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ if (Exprs.get()[I]->isTypeDependent())
+ IsDependent = true;
+ }
+
+ // If either the declaration has a dependent type or if any of the
+ // expressions is type-dependent, we represent the initialization
+ // via a ParenListExpr for later use during template instantiation.
+ if (VDecl->getType()->isDependentType() || IsDependent) {
+ // Let clients know that initialization was done with a direct initializer.
+ VDecl->setCXXDirectInitializer(true);
+
+ // Store the initialization expressions as a ParenListExpr.
+ unsigned NumExprs = Exprs.size();
+ VDecl->setInit(new (Context) ParenListExpr(Context, LParenLoc,
+ (Expr **)Exprs.release(),
+ NumExprs, RParenLoc));
+ return;
+ }
+
+ // Capture the variable that is being initialized and the style of
+ // initialization.
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = InitializationKind::CreateDirect(VDecl->getLocation(),
+ LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, Entity, Kind,
+ Exprs.get(), Exprs.size());
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs));
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ CheckImplicitConversions(Result.get(), LParenLoc);
+
+ Result = MaybeCreateExprWithCleanups(Result);
+ VDecl->setInit(Result.takeAs<Expr>());
+ VDecl->setCXXDirectInitializer(true);
+
+ CheckCompleteVariableDeclaration(VDecl);
+}
+
+/// \brief Given a constructor and the set of arguments provided for the
+/// constructor, convert the arguments and add any required default arguments
+/// to form a proper call to this constructor.
+///
+/// \returns true if an error occurred, false otherwise.
+bool
+Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ ASTOwningVector<Expr*> &ConvertedArgs) {
+ // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
+ unsigned NumArgs = ArgsPtr.size();
+ Expr **Args = (Expr **)ArgsPtr.get();
+
+ const FunctionProtoType *Proto
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ assert(Proto && "Constructor without a prototype?");
+ unsigned NumArgsInProto = Proto->getNumArgs();
+
+ // If too few arguments are available, we'll fill in the rest with defaults.
+ if (NumArgs < NumArgsInProto)
+ ConvertedArgs.reserve(NumArgsInProto);
+ else
+ ConvertedArgs.reserve(NumArgs);
+
+ VariadicCallType CallType =
+ Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+ llvm::SmallVector<Expr *, 8> AllArgs;
+ bool Invalid = GatherArgumentsForCall(Loc, Constructor,
+ Proto, 0, Args, NumArgs, AllArgs,
+ CallType);
+ for (unsigned i =0, size = AllArgs.size(); i < size; i++)
+ ConvertedArgs.push_back(AllArgs[i]);
+ return Invalid;
+}
+
+static inline bool
+CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
+ const FunctionDecl *FnDecl) {
+ const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
+ if (isa<NamespaceDecl>(DC)) {
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_declared_in_namespace)
+ << FnDecl->getDeclName();
+ }
+
+ if (isa<TranslationUnitDecl>(DC) &&
+ FnDecl->getStorageClass() == SC_Static) {
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_declared_static)
+ << FnDecl->getDeclName();
+ }
+
+ return false;
+}
+
+static inline bool
+CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
+ CanQualType ExpectedResultType,
+ CanQualType ExpectedFirstParamType,
+ unsigned DependentParamTypeDiag,
+ unsigned InvalidParamTypeDiag) {
+ QualType ResultType =
+ FnDecl->getType()->getAs<FunctionType>()->getResultType();
+
+ // Check that the result type is not dependent.
+ if (ResultType->isDependentType())
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_dependent_result_type)
+ << FnDecl->getDeclName() << ExpectedResultType;
+
+ // Check that the result type is what we expect.
+ if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_invalid_result_type)
+ << FnDecl->getDeclName() << ExpectedResultType;
+
+ // A function template must have at least 2 parameters.
+ if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_template_too_few_parameters)
+ << FnDecl->getDeclName();
+
+ // The function decl must have at least 1 parameter.
+ if (FnDecl->getNumParams() == 0)
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_delete_too_few_parameters)
+ << FnDecl->getDeclName();
+
+ // Check the the first parameter type is not dependent.
+ QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
+ if (FirstParamType->isDependentType())
+ return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
+ << FnDecl->getDeclName() << ExpectedFirstParamType;
+
+ // Check that the first parameter type is what we expect.
+ if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
+ ExpectedFirstParamType)
+ return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
+ << FnDecl->getDeclName() << ExpectedFirstParamType;
+
+ return false;
+}
+
+static bool
+CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+ // C++ [basic.stc.dynamic.allocation]p1:
+ // A program is ill-formed if an allocation function is declared in a
+ // namespace scope other than global scope or declared static in global
+ // scope.
+ if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+ return true;
+
+ CanQualType SizeTy =
+ SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
+
+ // C++ [basic.stc.dynamic.allocation]p1:
+ // The return type shall be void*. The first parameter shall have type
+ // std::size_t.
+ if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy,
+ SizeTy,
+ diag::err_operator_new_dependent_param_type,
+ diag::err_operator_new_param_type))
+ return true;
+
+ // C++ [basic.stc.dynamic.allocation]p1:
+ // The first parameter shall not have an associated default argument.
+ if (FnDecl->getParamDecl(0)->hasDefaultArg())
+ return SemaRef.Diag(FnDecl->getLocation(),
+ diag::err_operator_new_default_arg)
+ << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();
+
+ return false;
+}
+
+static bool
+CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+ // C++ [basic.stc.dynamic.deallocation]p1:
+ // A program is ill-formed if deallocation functions are declared in a
+ // namespace scope other than global scope or declared static in global
+ // scope.
+ if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+ return true;
+
+ // C++ [basic.stc.dynamic.deallocation]p2:
+ // Each deallocation function shall return void and its first parameter
+ // shall be void*.
+ if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy,
+ SemaRef.Context.VoidPtrTy,
+ diag::err_operator_delete_dependent_param_type,
+ diag::err_operator_delete_param_type))
+ return true;
+
+ return false;
+}
+
+/// CheckOverloadedOperatorDeclaration - Check whether the declaration
+/// of this overloaded operator is well-formed. If so, returns false;
+/// otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
+ assert(FnDecl && FnDecl->isOverloadedOperator() &&
+ "Expected an overloaded operator declaration");
+
+ OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
+
+ // C++ [over.oper]p5:
+ // The allocation and deallocation functions, operator new,
+ // operator new[], operator delete and operator delete[], are
+ // described completely in 3.7.3. The attributes and restrictions
+ // found in the rest of this subclause do not apply to them unless
+ // explicitly stated in 3.7.3.
+ if (Op == OO_Delete || Op == OO_Array_Delete)
+ return CheckOperatorDeleteDeclaration(*this, FnDecl);
+
+ if (Op == OO_New || Op == OO_Array_New)
+ return CheckOperatorNewDeclaration(*this, FnDecl);
+
+ // C++ [over.oper]p6:
+ // An operator function shall either be a non-static member
+ // function or be a non-member function and have at least one
+ // parameter whose type is a class, a reference to a class, an
+ // enumeration, or a reference to an enumeration.
+ if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ if (MethodDecl->isStatic())
+ return Diag(FnDecl->getLocation(),
+ diag::err_operator_overload_static) << FnDecl->getDeclName();
+ } else {
+ bool ClassOrEnumParam = false;
+ for (FunctionDecl::param_iterator Param = FnDecl->param_begin(),
+ ParamEnd = FnDecl->param_end();
+ Param != ParamEnd; ++Param) {
+ QualType ParamType = (*Param)->getType().getNonReferenceType();
+ if (ParamType->isDependentType() || ParamType->isRecordType() ||
+ ParamType->isEnumeralType()) {
+ ClassOrEnumParam = true;
+ break;
+ }
+ }
+
+ if (!ClassOrEnumParam)
+ return Diag(FnDecl->getLocation(),
+ diag::err_operator_overload_needs_class_or_enum)
+ << FnDecl->getDeclName();
+ }
+
+ // C++ [over.oper]p8:
+ // An operator function cannot have default arguments (8.3.6),
+ // except where explicitly stated below.
+ //
+ // Only the function-call operator allows default arguments
+ // (C++ [over.call]p1).
+ if (Op != OO_Call) {
+ for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
+ Param != FnDecl->param_end(); ++Param) {
+ if ((*Param)->hasDefaultArg())
+ return Diag((*Param)->getLocation(),
+ diag::err_operator_overload_default_arg)
+ << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
+ }
+ }
+
+ static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
+ { false, false, false }
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ , { Unary, Binary, MemberOnly }
+#include "clang/Basic/OperatorKinds.def"
+ };
+
+ bool CanBeUnaryOperator = OperatorUses[Op][0];
+ bool CanBeBinaryOperator = OperatorUses[Op][1];
+ bool MustBeMemberOperator = OperatorUses[Op][2];
+
+ // C++ [over.oper]p8:
+ // [...] Operator functions cannot have more or fewer parameters
+ // than the number required for the corresponding operator, as
+ // described in the rest of this subclause.
+ unsigned NumParams = FnDecl->getNumParams()
+ + (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
+ if (Op != OO_Call &&
+ ((NumParams == 1 && !CanBeUnaryOperator) ||
+ (NumParams == 2 && !CanBeBinaryOperator) ||
+ (NumParams < 1) || (NumParams > 2))) {
+ // We have the wrong number of parameters.
+ unsigned ErrorKind;
+ if (CanBeUnaryOperator && CanBeBinaryOperator) {
+ ErrorKind = 2; // 2 -> unary or binary.
+ } else if (CanBeUnaryOperator) {
+ ErrorKind = 0; // 0 -> unary
+ } else {
+ assert(CanBeBinaryOperator &&
+ "All non-call overloaded operators are unary or binary!");
+ ErrorKind = 1; // 1 -> binary
+ }
+
+ return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
+ << FnDecl->getDeclName() << NumParams << ErrorKind;
+ }
+
+ // Overloaded operators other than operator() cannot be variadic.
+ if (Op != OO_Call &&
+ FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) {
+ return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
+ << FnDecl->getDeclName();
+ }
+
+ // Some operators must be non-static member functions.
+ if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
+ return Diag(FnDecl->getLocation(),
+ diag::err_operator_overload_must_be_member)
+ << FnDecl->getDeclName();
+ }
+
+ // C++ [over.inc]p1:
+ // The user-defined function called operator++ implements the
+ // prefix and postfix ++ operator. If this function is a member
+ // function with no parameters, or a non-member function with one
+ // parameter of class or enumeration type, it defines the prefix
+ // increment operator ++ for objects of that type. If the function
+ // is a member function with one parameter (which shall be of type
+ // int) or a non-member function with two parameters (the second
+ // of which shall be of type int), it defines the postfix
+ // increment operator ++ for objects of that type.
+ if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
+ ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
+ bool ParamIsInt = false;
+ if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>())
+ ParamIsInt = BT->getKind() == BuiltinType::Int;
+
+ if (!ParamIsInt)
+ return Diag(LastParam->getLocation(),
+ diag::err_operator_overload_post_incdec_must_be_int)
+ << LastParam->getType() << (Op == OO_MinusMinus);
+ }
+
+ return false;
+}
+
+/// CheckLiteralOperatorDeclaration - Check whether the declaration
+/// of this literal operator function is well-formed. If so, returns
+/// false; otherwise, emits appropriate diagnostics and returns true.
+bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
+ DeclContext *DC = FnDecl->getDeclContext();
+ Decl::Kind Kind = DC->getDeclKind();
+ if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace &&
+ Kind != Decl::LinkageSpec) {
+ Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace)
+ << FnDecl->getDeclName();
+ return true;
+ }
+
+ bool Valid = false;
+
+ // template <char...> type operator "" name() is the only valid template
+ // signature, and the only valid signature with no parameters.
+ if (FnDecl->param_size() == 0) {
+ if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) {
+ // Must have only one template parameter
+ TemplateParameterList *Params = TpDecl->getTemplateParameters();
+ if (Params->size() == 1) {
+ NonTypeTemplateParmDecl *PmDecl =
+ cast<NonTypeTemplateParmDecl>(Params->getParam(0));
+
+ // The template parameter must be a char parameter pack.
+ if (PmDecl && PmDecl->isTemplateParameterPack() &&
+ Context.hasSameType(PmDecl->getType(), Context.CharTy))
+ Valid = true;
+ }
+ }
+ } else {
+ // Check the first parameter
+ FunctionDecl::param_iterator Param = FnDecl->param_begin();
+
+ QualType T = (*Param)->getType();
+
+ // unsigned long long int, long double, and any character type are allowed
+ // as the only parameters.
+ if (Context.hasSameType(T, Context.UnsignedLongLongTy) ||
+ Context.hasSameType(T, Context.LongDoubleTy) ||
+ Context.hasSameType(T, Context.CharTy) ||
+ Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.Char16Ty) ||
+ Context.hasSameType(T, Context.Char32Ty)) {
+ if (++Param == FnDecl->param_end())
+ Valid = true;
+ goto FinishedParams;
+ }
+
+ // Otherwise it must be a pointer to const; let's strip those qualifiers.
+ const PointerType *PT = T->getAs<PointerType>();
+ if (!PT)
+ goto FinishedParams;
+ T = PT->getPointeeType();
+ if (!T.isConstQualified())
+ goto FinishedParams;
+ T = T.getUnqualifiedType();
+
+ // Move on to the second parameter;
+ ++Param;
+
+ // If there is no second parameter, the first must be a const char *
+ if (Param == FnDecl->param_end()) {
+ if (Context.hasSameType(T, Context.CharTy))
+ Valid = true;
+ goto FinishedParams;
+ }
+
+ // const char *, const wchar_t*, const char16_t*, and const char32_t*
+ // are allowed as the first parameter to a two-parameter function
+ if (!(Context.hasSameType(T, Context.CharTy) ||
+ Context.hasSameType(T, Context.WCharTy) ||
+ Context.hasSameType(T, Context.Char16Ty) ||
+ Context.hasSameType(T, Context.Char32Ty)))
+ goto FinishedParams;
+
+ // The second and final parameter must be an std::size_t
+ T = (*Param)->getType().getUnqualifiedType();
+ if (Context.hasSameType(T, Context.getSizeType()) &&
+ ++Param == FnDecl->param_end())
+ Valid = true;
+ }
+
+ // FIXME: This diagnostic is absolutely terrible.
+FinishedParams:
+ if (!Valid) {
+ Diag(FnDecl->getLocation(), diag::err_literal_operator_params)
+ << FnDecl->getDeclName();
+ return true;
+ }
+
+ return false;
+}
+
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ llvm::StringRef Lang,
+ SourceLocation LBraceLoc) {
+ LinkageSpecDecl::LanguageIDs Language;
+ if (Lang == "\"C\"")
+ Language = LinkageSpecDecl::lang_c;
+ else if (Lang == "\"C++\"")
+ Language = LinkageSpecDecl::lang_cxx;
+ else {
+ Diag(LangLoc, diag::err_bad_language);
+ return 0;
+ }
+
+ // FIXME: Add all the various semantics of linkage specifications
+
+ LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+ LangLoc, Language,
+ LBraceLoc.isValid());
+ CurContext->addDecl(D);
+ PushDeclContext(S, D);
+ return D;
+}
+
+/// ActOnFinishLinkageSpecification - Complete the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc) {
+ if (LinkageSpec)
+ PopDeclContext();
+ return LinkageSpec;
+}
+
+/// \brief Perform semantic analysis for the variable declaration that
+/// occurs within a C++ catch clause, returning the newly-created
+/// variable.
+VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
+ TypeSourceInfo *TInfo,
+ IdentifierInfo *Name,
+ SourceLocation Loc) {
+ bool Invalid = false;
+ QualType ExDeclType = TInfo->getType();
+
+ // Arrays and functions decay.
+ if (ExDeclType->isArrayType())
+ ExDeclType = Context.getArrayDecayedType(ExDeclType);
+ else if (ExDeclType->isFunctionType())
+ ExDeclType = Context.getPointerType(ExDeclType);
+
+ // C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
+ // The exception-declaration shall not denote a pointer or reference to an
+ // incomplete type, other than [cv] void*.
+ // N2844 forbids rvalue references.
+ if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
+ Diag(Loc, diag::err_catch_rvalue_ref);
+ Invalid = true;
+ }
+
+ // GCC allows catching pointers and references to incomplete types
+ // as an extension; so do we, but we warn by default.
+
+ QualType BaseType = ExDeclType;
+ int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
+ unsigned DK = diag::err_catch_incomplete;
+ bool IncompleteCatchIsInvalid = true;
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ BaseType = Ptr->getPointeeType();
+ Mode = 1;
+ DK = diag::ext_catch_incomplete_ptr;
+ IncompleteCatchIsInvalid = false;
+ } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
+ // For the purpose of error recovery, we treat rvalue refs like lvalue refs.
+ BaseType = Ref->getPointeeType();
+ Mode = 2;
+ DK = diag::ext_catch_incomplete_ref;
+ IncompleteCatchIsInvalid = false;
+ }
+ if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
+ !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK) &&
+ IncompleteCatchIsInvalid)
+ Invalid = true;
+
+ if (!Invalid && !ExDeclType->isDependentType() &&
+ RequireNonAbstractType(Loc, ExDeclType,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ Invalid = true;
+
+ // Only the non-fragile NeXT runtime currently supports C++ catches
+ // of ObjC types, and no runtime supports catching ObjC types by value.
+ if (!Invalid && getLangOptions().ObjC1) {
+ QualType T = ExDeclType;
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType();
+
+ if (T->isObjCObjectType()) {
+ Diag(Loc, diag::err_objc_object_catch);
+ Invalid = true;
+ } else if (T->isObjCObjectPointerType()) {
+ if (!getLangOptions().NeXTRuntime) {
+ Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu);
+ Invalid = true;
+ } else if (!getLangOptions().ObjCNonFragileABI) {
+ Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile);
+ Invalid = true;
+ }
+ }
+ }
+
+ VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
+ Name, ExDeclType, TInfo, SC_None,
+ SC_None);
+ ExDecl->setExceptionVariable(true);
+
+ if (!Invalid) {
+ if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
+ // C++ [except.handle]p16:
+ // The object declared in an exception-declaration or, if the
+ // exception-declaration does not specify a name, a temporary (12.2) is
+ // copy-initialized (8.5) from the exception object. [...]
+ // The object is destroyed when the handler exits, after the destruction
+ // of any automatic objects initialized within the handler.
+ //
+ // We just pretend to initialize the object with itself, then make sure
+ // it can be destroyed later.
+ QualType initType = ExDeclType;
+
+ InitializedEntity entity =
+ InitializedEntity::InitializeVariable(ExDecl);
+ InitializationKind initKind =
+ InitializationKind::CreateCopy(Loc, SourceLocation());
+
+ Expr *opaqueValue =
+ new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary);
+ InitializationSequence sequence(*this, entity, initKind, &opaqueValue, 1);
+ ExprResult result = sequence.Perform(*this, entity, initKind,
+ MultiExprArg(&opaqueValue, 1));
+ if (result.isInvalid())
+ Invalid = true;
+ else {
+ // If the constructor used was non-trivial, set this as the
+ // "initializer".
+ CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take());
+ if (!construct->getConstructor()->isTrivial()) {
+ Expr *init = MaybeCreateExprWithCleanups(construct);
+ ExDecl->setInit(init);
+ }
+
+ // And make sure it's destructable.
+ FinalizeVarWithDestructor(ExDecl, recordType);
+ }
+ }
+ }
+
+ if (Invalid)
+ ExDecl->setInvalidDecl();
+
+ return ExDecl;
+}
+
+/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
+/// handler.
+Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ bool Invalid = D.isInvalidType();
+
+ // Check for unexpanded parameter packs.
+ if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_ExceptionType)) {
+ TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
+ D.getIdentifierLoc());
+ Invalid = true;
+ }
+
+ IdentifierInfo *II = D.getIdentifier();
+ if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
+ LookupOrdinaryName,
+ ForRedeclaration)) {
+ // The scope should be freshly made just for us. There is just no way
+ // it contains any previous declaration.
+ assert(!S->isDeclScope(PrevDecl));
+ if (PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ }
+ }
+
+ if (D.getCXXScopeSpec().isSet() && !Invalid) {
+ Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
+ << D.getCXXScopeSpec().getRange();
+ Invalid = true;
+ }
+
+ VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo,
+ D.getIdentifier(),
+ D.getIdentifierLoc());
+
+ if (Invalid)
+ ExDecl->setInvalidDecl();
+
+ // Add the exception declaration into this scope.
+ if (II)
+ PushOnScopeChains(ExDecl, S);
+ else
+ CurContext->addDecl(ExDecl);
+
+ ProcessDeclAttributes(S, ExDecl, D);
+ return ExDecl;
+}
+
+Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr_) {
+ StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_);
+
+ if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
+ llvm::APSInt Value(32);
+ if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
+ Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
+ AssertExpr->getSourceRange();
+ return 0;
+ }
+
+ if (Value == 0) {
+ Diag(AssertLoc, diag::err_static_assert_failed)
+ << AssertMessage->getString() << AssertExpr->getSourceRange();
+ }
+ }
+
+ if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
+ return 0;
+
+ Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
+ AssertExpr, AssertMessage);
+
+ CurContext->addDecl(Decl);
+ return Decl;
+}
+
+/// \brief Perform semantic analysis of the given friend type declaration.
+///
+/// \returns A friend declaration that.
+FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc,
+ TypeSourceInfo *TSInfo) {
+ assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
+
+ QualType T = TSInfo->getType();
+ SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();
+
+ if (!getLangOptions().CPlusPlus0x) {
+ // C++03 [class.friend]p2:
+ // An elaborated-type-specifier shall be used in a friend declaration
+ // for a class.*
+ //
+ // * The class-key of the elaborated-type-specifier is required.
+ if (!ActiveTemplateInstantiations.empty()) {
+ // Do not complain about the form of friend template types during
+ // template instantiation; we will already have complained when the
+ // template was declared.
+ } else if (!T->isElaboratedTypeSpecifier()) {
+ // If we evaluated the type to a record type, suggest putting
+ // a tag in front.
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ RecordDecl *RD = RT->getDecl();
+
+ std::string InsertionText = std::string(" ") + RD->getKindName();
+
+ Diag(TypeRange.getBegin(), diag::ext_unelaborated_friend_type)
+ << (unsigned) RD->getTagKind()
+ << T
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
+ InsertionText);
+ } else {
+ Diag(FriendLoc, diag::ext_nonclass_type_friend)
+ << T
+ << SourceRange(FriendLoc, TypeRange.getEnd());
+ }
+ } else if (T->getAs<EnumType>()) {
+ Diag(FriendLoc, diag::ext_enum_friend)
+ << T
+ << SourceRange(FriendLoc, TypeRange.getEnd());
+ }
+ }
+
+ // C++0x [class.friend]p3:
+ // If the type specifier in a friend declaration designates a (possibly
+ // cv-qualified) class type, that class is declared as a friend; otherwise,
+ // the friend declaration is ignored.
+
+ // FIXME: C++0x has some syntactic restrictions on friend type declarations
+ // in [class.friend]p3 that we do not implement.
+
+ return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc);
+}
+
+/// Handle a friend tag declaration where the scope specifier was
+/// templated.
+Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+ unsigned TagSpec, SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TempParamLists) {
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+ bool isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TempParamLists.size();
+ bool Invalid = false;
+
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(TagLoc, SS,
+ TempParamLists.get(),
+ TempParamLists.size(),
+ /*friend*/ true,
+ isExplicitSpecialization,
+ Invalid)) {
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams->size() > 0) {
+ // This is a declaration of a class template.
+ if (Invalid)
+ return 0;
+
+ return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
+ SS, Name, NameLoc, Attr,
+ TemplateParams, AS_public).take();
+ } else {
+ // The "template<>" header is extraneous.
+ Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+ << TypeWithKeyword::getTagTypeKindName(Kind) << Name;
+ isExplicitSpecialization = true;
+ }
+ }
+
+ if (Invalid) return 0;
+
+ assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
+
+ bool isAllExplicitSpecializations = true;
+ for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) {
+ if (TempParamLists.get()[I]->size()) {
+ isAllExplicitSpecializations = false;
+ break;
+ }
+ }
+
+ // FIXME: don't ignore attributes.
+
+ // If it's explicit specializations all the way down, just forget
+ // about the template header and build an appropriate non-templated
+ // friend. TODO: for source fidelity, remember the headers.
+ if (isAllExplicitSpecializations) {
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+ QualType T = CheckTypenameType(Keyword, SS.getScopeRep(), *Name,
+ TagLoc, SS.getRange(), NameLoc);
+ if (T.isNull())
+ return 0;
+
+ TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+ if (isa<DependentNameType>(T)) {
+ DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ TL.setKeywordLoc(TagLoc);
+ TL.setQualifierRange(SS.getRange());
+ TL.setNameLoc(NameLoc);
+ } else {
+ ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+ TL.setKeywordLoc(TagLoc);
+ TL.setQualifierRange(SS.getRange());
+ cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc);
+ }
+
+ FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
+ TSI, FriendLoc);
+ Friend->setAccess(AS_public);
+ CurContext->addDecl(Friend);
+ return Friend;
+ }
+
+ // Handle the case of a templated-scope friend class. e.g.
+ // template <class T> class A<T>::B;
+ // FIXME: we don't support these right now.
+ ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+ QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
+ TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+ DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ TL.setKeywordLoc(TagLoc);
+ TL.setQualifierRange(SS.getRange());
+ TL.setNameLoc(NameLoc);
+
+ FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
+ TSI, FriendLoc);
+ Friend->setAccess(AS_public);
+ Friend->setUnsupportedFriend(true);
+ CurContext->addDecl(Friend);
+ return Friend;
+}
+
+
+/// Handle a friend type declaration. This works in tandem with
+/// ActOnTag.
+///
+/// Notes on friend class templates:
+///
+/// We generally treat friend class declarations as if they were
+/// declaring a class. So, for example, the elaborated type specifier
+/// in a friend declaration is required to obey the restrictions of a
+/// class-head (i.e. no typedefs in the scope chain), template
+/// parameters are required to match up with simple template-ids, &c.
+/// However, unlike when declaring a template specialization, it's
+/// okay to refer to a template specialization without an empty
+/// template parameter declaration, e.g.
+/// friend class A<T>::B<unsigned>;
+/// We permit this as a special case; if there are any template
+/// parameters present at all, require proper matching, i.e.
+/// template <> template <class T> friend class A<int>::B;
+Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TempParams) {
+ SourceLocation Loc = DS.getSourceRange().getBegin();
+
+ assert(DS.isFriendSpecified());
+ assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+ // Try to convert the decl specifier to a type. This works for
+ // friend templates because ActOnTag never produces a ClassTemplateDecl
+ // for a TUK_Friend.
+ Declarator TheDeclarator(DS, Declarator::MemberContext);
+ TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
+ QualType T = TSI->getType();
+ if (TheDeclarator.isInvalidType())
+ return 0;
+
+ if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
+ return 0;
+
+ // This is definitely an error in C++98. It's probably meant to
+ // be forbidden in C++0x, too, but the specification is just
+ // poorly written.
+ //
+ // The problem is with declarations like the following:
+ // template <T> friend A<T>::foo;
+ // where deciding whether a class C is a friend or not now hinges
+ // on whether there exists an instantiation of A that causes
+ // 'foo' to equal C. There are restrictions on class-heads
+ // (which we declare (by fiat) elaborated friend declarations to
+ // be) that makes this tractable.
+ //
+ // FIXME: handle "template <> friend class A<T>;", which
+ // is possibly well-formed? Who even knows?
+ if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
+ Diag(Loc, diag::err_tagless_friend_type_template)
+ << DS.getSourceRange();
+ return 0;
+ }
+
+ // C++98 [class.friend]p1: A friend of a class is a function
+ // or class that is not a member of the class . . .
+ // This is fixed in DR77, which just barely didn't make the C++03
+ // deadline. It's also a very silly restriction that seriously
+ // affects inner classes and which nobody else seems to implement;
+ // thus we never diagnose it, not even in -pedantic.
+ //
+ // But note that we could warn about it: it's always useless to
+ // friend one of your own members (it's not, however, worthless to
+ // friend a member of an arbitrary specialization of your template).
+
+ Decl *D;
+ if (unsigned NumTempParamLists = TempParams.size())
+ D = FriendTemplateDecl::Create(Context, CurContext, Loc,
+ NumTempParamLists,
+ TempParams.release(),
+ TSI,
+ DS.getFriendSpecLoc());
+ else
+ D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI);
+
+ if (!D)
+ return 0;
+
+ D->setAccess(AS_public);
+ CurContext->addDecl(D);
+
+ return D;
+}
+
+Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
+ MultiTemplateParamsArg TemplateParams) {
+ const DeclSpec &DS = D.getDeclSpec();
+
+ assert(DS.isFriendSpecified());
+ assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+
+ SourceLocation Loc = D.getIdentifierLoc();
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
+
+ // C++ [class.friend]p1
+ // A friend of a class is a function or class....
+ // Note that this sees through typedefs, which is intended.
+ // It *doesn't* see through dependent types, which is correct
+ // according to [temp.arg.type]p3:
+ // If a declaration acquires a function type through a
+ // type dependent on a template-parameter and this causes
+ // a declaration that does not use the syntactic form of a
+ // function declarator to have a function type, the program
+ // is ill-formed.
+ if (!T->isFunctionType()) {
+ Diag(Loc, diag::err_unexpected_friend);
+
+ // It might be worthwhile to try to recover by creating an
+ // appropriate declaration.
+ return 0;
+ }
+
+ // C++ [namespace.memdef]p3
+ // - If a friend declaration in a non-local class first declares a
+ // class or function, the friend class or function is a member
+ // of the innermost enclosing namespace.
+ // - The name of the friend is not found by simple name lookup
+ // until a matching declaration is provided in that namespace
+ // scope (either before or after the class declaration granting
+ // friendship).
+ // - If a friend function is called, its name may be found by the
+ // name lookup that considers functions from namespaces and
+ // classes associated with the types of the function arguments.
+ // - When looking for a prior declaration of a class or a function
+ // declared as a friend, scopes outside the innermost enclosing
+ // namespace scope are not considered.
+
+ CXXScopeSpec &SS = D.getCXXScopeSpec();
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ assert(Name);
+
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
+ DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
+ DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
+ return 0;
+
+ // The context we found the declaration in, or in which we should
+ // create the declaration.
+ DeclContext *DC;
+ Scope *DCScope = S;
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForRedeclaration);
+
+ // FIXME: there are different rules in local classes
+
+ // There are four cases here.
+ // - There's no scope specifier, in which case we just go to the
+ // appropriate scope and look for a function or function template
+ // there as appropriate.
+ // Recover from invalid scope qualifiers as if they just weren't there.
+ if (SS.isInvalid() || !SS.isSet()) {
+ // C++0x [namespace.memdef]p3:
+ // If the name in a friend declaration is neither qualified nor
+ // a template-id and the declaration is a function or an
+ // elaborated-type-specifier, the lookup to determine whether
+ // the entity has been previously declared shall not consider
+ // any scopes outside the innermost enclosing namespace.
+ // C++0x [class.friend]p11:
+ // If a friend declaration appears in a local class and the name
+ // specified is an unqualified name, a prior declaration is
+ // looked up without considering scopes that are outside the
+ // innermost enclosing non-class scope. For a friend function
+ // declaration, if there is no prior declaration, the program is
+ // ill-formed.
+ bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass();
+ bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId;
+
+ // Find the appropriate context according to the above.
+ DC = CurContext;
+ while (true) {
+ // Skip class contexts. If someone can cite chapter and verse
+ // for this behavior, that would be nice --- it's what GCC and
+ // EDG do, and it seems like a reasonable intent, but the spec
+ // really only says that checks for unqualified existing
+ // declarations should stop at the nearest enclosing namespace,
+ // not that they should only consider the nearest enclosing
+ // namespace.
+ while (DC->isRecord())
+ DC = DC->getParent();
+
+ LookupQualifiedName(Previous, DC);
+
+ // TODO: decide what we think about using declarations.
+ if (isLocal || !Previous.empty())
+ break;
+
+ if (isTemplateId) {
+ if (isa<TranslationUnitDecl>(DC)) break;
+ } else {
+ if (DC->isFileContext()) break;
+ }
+ DC = DC->getParent();
+ }
+
+ // C++ [class.friend]p1: A friend of a class is a function or
+ // class that is not a member of the class . . .
+ // C++0x changes this for both friend types and functions.
+ // Most C++ 98 compilers do seem to give an error here, so
+ // we do, too.
+ if (!Previous.empty() && DC->Equals(CurContext)
+ && !getLangOptions().CPlusPlus0x)
+ Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+
+ DCScope = getScopeForDeclContext(S, DC);
+
+ // - There's a non-dependent scope specifier, in which case we
+ // compute it and do a previous lookup there for a function
+ // or function template.
+ } else if (!SS.getScopeRep()->isDependent()) {
+ DC = computeDeclContext(SS);
+ if (!DC) return 0;
+
+ if (RequireCompleteDeclContext(SS, DC)) return 0;
+
+ LookupQualifiedName(Previous, DC);
+
+ // Ignore things found implicitly in the wrong scope.
+ // TODO: better diagnostics for this case. Suggesting the right
+ // qualified scope would be nice...
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (!DC->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
+ F.erase();
+ }
+ F.done();
+
+ if (Previous.empty()) {
+ D.setInvalidType();
+ Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
+ return 0;
+ }
+
+ // C++ [class.friend]p1: A friend of a class is a function or
+ // class that is not a member of the class . . .
+ if (DC->Equals(CurContext))
+ Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+
+ // - There's a scope specifier that does not match any template
+ // parameter lists, in which case we use some arbitrary context,
+ // create a method or method template, and wait for instantiation.
+ // - There's a scope specifier that does match some template
+ // parameter lists, which we don't handle right now.
+ } else {
+ DC = CurContext;
+ assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
+ }
+
+ if (!DC->isRecord()) {
+ // This implies that it has to be an operator or function.
+ if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+ D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
+ Diag(Loc, diag::err_introducing_special_friend) <<
+ (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+ D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+ return 0;
+ }
+ }
+
+ bool Redeclaration = false;
+ NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, T, TInfo, Previous,
+ move(TemplateParams),
+ IsDefinition,
+ Redeclaration);
+ if (!ND) return 0;
+
+ assert(ND->getDeclContext() == DC);
+ assert(ND->getLexicalDeclContext() == CurContext);
+
+ // Add the function declaration to the appropriate lookup tables,
+ // adjusting the redeclarations list as necessary. We don't
+ // want to do this yet if the friending class is dependent.
+ //
+ // Also update the scope-based lookup if the target context's
+ // lookup context is in lexical scope.
+ if (!CurContext->isDependentContext()) {
+ DC = DC->getRedeclContext();
+ DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
+ }
+
+ FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
+ D.getIdentifierLoc(), ND,
+ DS.getFriendSpecLoc());
+ FrD->setAccess(AS_public);
+ CurContext->addDecl(FrD);
+
+ if (ND->isInvalidDecl())
+ FrD->setInvalidDecl();
+ else {
+ FunctionDecl *FD;
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ FD = FTD->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(ND);
+
+ // Mark templated-scope function declarations as unsupported.
+ if (FD->getNumTemplateParameterLists())
+ FrD->setUnsupportedFriend(true);
+ }
+
+ return ND;
+}
+
+void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
+ AdjustDeclIfTemplate(Dcl);
+
+ FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
+ if (!Fn) {
+ Diag(DelLoc, diag::err_deleted_non_function);
+ return;
+ }
+ if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) {
+ Diag(DelLoc, diag::err_deleted_decl_not_first);
+ Diag(Prev->getLocation(), diag::note_previous_declaration);
+ // If the declaration wasn't the first, we delete the function anyway for
+ // recovery.
+ }
+ Fn->setDeleted();
+}
+
+static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
+ Stmt *SubStmt = *CI;
+ if (!SubStmt)
+ continue;
+ if (isa<ReturnStmt>(SubStmt))
+ Self.Diag(SubStmt->getSourceRange().getBegin(),
+ diag::err_return_in_constructor_handler);
+ if (!isa<Expr>(SubStmt))
+ SearchForReturnInStmt(Self, SubStmt);
+ }
+}
+
+void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
+ for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
+ CXXCatchStmt *Handler = TryBlock->getHandler(I);
+ SearchForReturnInStmt(*this, Handler);
+ }
+}
+
+bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old) {
+ QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
+ QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
+
+ if (Context.hasSameType(NewTy, OldTy) ||
+ NewTy->isDependentType() || OldTy->isDependentType())
+ return false;
+
+ // Check if the return types are covariant
+ QualType NewClassTy, OldClassTy;
+
+ /// Both types must be pointers or references to classes.
+ if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
+ if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
+ NewClassTy = NewPT->getPointeeType();
+ OldClassTy = OldPT->getPointeeType();
+ }
+ } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
+ if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
+ if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
+ NewClassTy = NewRT->getPointeeType();
+ OldClassTy = OldRT->getPointeeType();
+ }
+ }
+ }
+
+ // The return types aren't either both pointers or references to a class type.
+ if (NewClassTy.isNull()) {
+ Diag(New->getLocation(),
+ diag::err_different_return_type_for_overriding_virtual_function)
+ << New->getDeclName() << NewTy << OldTy;
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+
+ return true;
+ }
+
+ // C++ [class.virtual]p6:
+ // If the return type of D::f differs from the return type of B::f, the
+ // class type in the return type of D::f shall be complete at the point of
+ // declaration of D::f or shall be the class type D.
+ if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
+ if (!RT->isBeingDefined() &&
+ RequireCompleteType(New->getLocation(), NewClassTy,
+ PDiag(diag::err_covariant_return_incomplete)
+ << New->getDeclName()))
+ return true;
+ }
+
+ if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
+ // Check if the new class derives from the old class.
+ if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
+ Diag(New->getLocation(),
+ diag::err_covariant_return_not_derived)
+ << New->getDeclName() << NewTy << OldTy;
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ }
+
+ // Check if we the conversion from derived to base is valid.
+ if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy,
+ diag::err_covariant_return_inaccessible_base,
+ diag::err_covariant_return_ambiguous_derived_to_base_conv,
+ // FIXME: Should this point to the return type?
+ New->getLocation(), SourceRange(), New->getDeclName(), 0)) {
+ // FIXME: this note won't trigger for delayed access control
+ // diagnostics, and it's impossible to get an undelayed error
+ // here from access control during the original parse because
+ // the ParsingDeclSpec/ParsingDeclarator are still in scope.
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ }
+ }
+
+ // The qualifiers of the return types must be the same.
+ if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
+ Diag(New->getLocation(),
+ diag::err_covariant_return_type_different_qualifications)
+ << New->getDeclName() << NewTy << OldTy;
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ };
+
+
+ // The new class type must have the same or less qualifiers as the old type.
+ if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
+ Diag(New->getLocation(),
+ diag::err_covariant_return_type_class_type_more_qualified)
+ << New->getDeclName() << NewTy << OldTy;
+ Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+ return true;
+ };
+
+ return false;
+}
+
+/// \brief Mark the given method pure.
+///
+/// \param Method the method to be marked pure.
+///
+/// \param InitRange the source range that covers the "0" initializer.
+bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
+ if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
+ Method->setPure();
+ return false;
+ }
+
+ if (!Method->isInvalidDecl())
+ Diag(Method->getLocation(), diag::err_non_virtual_pure)
+ << Method->getDeclName() << InitRange;
+ return true;
+}
+
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
+/// an initializer for the out-of-line declaration 'Dcl'. The scope
+/// is a fresh scope pushed for just this purpose.
+///
+/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+/// static data member of class X, names should be looked up in the scope of
+/// class X.
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0) return;
+
+ // We should only get called for declarations with scope specifiers, like:
+ // int foo::bar;
+ assert(D->isOutOfLine());
+ EnterDeclaratorContext(S, D->getDeclContext());
+}
+
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the out-of-line declaration 'D'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0) return;
+
+ assert(D->isOutOfLine());
+ ExitDeclaratorContext(S);
+}
+
+/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
+/// C++ if/switch/while/for statement.
+/// e.g: "if (int x = f()) {...}"
+DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+ // C++ 6.4p2:
+ // The declarator shall not specify a function or an array.
+ // The type-specifier-seq shall not contain typedef and shall not declare a
+ // new class or enumeration.
+ assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ "Parser allowed 'typedef' as storage class of condition decl.");
+
+ TagDecl *OwnedTag = 0;
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag);
+ QualType Ty = TInfo->getType();
+
+ if (Ty->isFunctionType()) { // The declarator shall not specify a function...
+ // We exit without creating a CXXConditionDeclExpr because a FunctionDecl
+ // would be created and CXXConditionDeclExpr wants a VarDecl.
+ Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type)
+ << D.getSourceRange();
+ return DeclResult();
+ } else if (OwnedTag && OwnedTag->isDefinition()) {
+ // The type-specifier-seq shall not declare a new class or enumeration.
+ Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition);
+ }
+
+ Decl *Dcl = ActOnDeclarator(S, D);
+ if (!Dcl)
+ return DeclResult();
+
+ return Dcl;
+}
+
+void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired) {
+ // Ignore any vtable uses in unevaluated operands or for classes that do
+ // not have a vtable.
+ if (!Class->isDynamicClass() || Class->isDependentContext() ||
+ CurContext->isDependentContext() ||
+ ExprEvalContexts.back().Context == Unevaluated)
+ return;
+
+ // Try to insert this class into the map.
+ Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
+ Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
+ if (!Pos.second) {
+ // If we already had an entry, check to see if we are promoting this vtable
+ // to required a definition. If so, we need to reappend to the VTableUses
+ // list, since we may have already processed the first entry.
+ if (DefinitionRequired && !Pos.first->second) {
+ Pos.first->second = true;
+ } else {
+ // Otherwise, we can early exit.
+ return;
+ }
+ }
+
+ // Local classes need to have their virtual members marked
+ // immediately. For all other classes, we mark their virtual members
+ // at the end of the translation unit.
+ if (Class->isLocalClass())
+ MarkVirtualMembersReferenced(Loc, Class);
+ else
+ VTableUses.push_back(std::make_pair(Class, Loc));
+}
+
+bool Sema::DefineUsedVTables() {
+ if (VTableUses.empty())
+ return false;
+
+ // Note: The VTableUses vector could grow as a result of marking
+ // the members of a class as "used", so we check the size each
+ // time through the loop and prefer indices (with are stable) to
+ // iterators (which are not).
+ for (unsigned I = 0; I != VTableUses.size(); ++I) {
+ CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
+ if (!Class)
+ continue;
+
+ SourceLocation Loc = VTableUses[I].second;
+
+ // If this class has a key function, but that key function is
+ // defined in another translation unit, we don't need to emit the
+ // vtable even though we're using it.
+ const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
+ if (KeyFunction && !KeyFunction->hasBody()) {
+ switch (KeyFunction->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ // The key function is in another translation unit.
+ continue;
+
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ImplicitInstantiation:
+ // We will be instantiating the key function.
+ break;
+ }
+ } else if (!KeyFunction) {
+ // If we have a class with no key function that is the subject
+ // of an explicit instantiation declaration, suppress the
+ // vtable; it will live with the explicit instantiation
+ // definition.
+ bool IsExplicitInstantiationDeclaration
+ = Class->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration;
+ for (TagDecl::redecl_iterator R = Class->redecls_begin(),
+ REnd = Class->redecls_end();
+ R != REnd; ++R) {
+ TemplateSpecializationKind TSK
+ = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind();
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ IsExplicitInstantiationDeclaration = true;
+ else if (TSK == TSK_ExplicitInstantiationDefinition) {
+ IsExplicitInstantiationDeclaration = false;
+ break;
+ }
+ }
+
+ if (IsExplicitInstantiationDeclaration)
+ continue;
+ }
+
+ // Mark all of the virtual members of this class as referenced, so
+ // that we can build a vtable. Then, tell the AST consumer that a
+ // vtable for this class is required.
+ MarkVirtualMembersReferenced(Loc, Class);
+ CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl());
+ Consumer.HandleVTable(Class, VTablesUsed[Canonical]);
+
+ // Optionally warn if we're emitting a weak vtable.
+ if (Class->getLinkage() == ExternalLinkage &&
+ Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ if (!KeyFunction || (KeyFunction->hasBody() && KeyFunction->isInlined()))
+ Diag(Class->getLocation(), diag::warn_weak_vtable) << Class;
+ }
+ }
+ VTableUses.clear();
+
+ return true;
+}
+
+void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
+ const CXXRecordDecl *RD) {
+ for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+ e = RD->method_end(); i != e; ++i) {
+ CXXMethodDecl *MD = *i;
+
+ // C++ [basic.def.odr]p2:
+ // [...] A virtual member function is used if it is not pure. [...]
+ if (MD->isVirtual() && !MD->isPure())
+ MarkDeclarationReferenced(Loc, MD);
+ }
+
+ // Only classes that have virtual bases need a VTT.
+ if (RD->getNumVBases() == 0)
+ return;
+
+ for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
+ e = RD->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ if (Base->getNumVBases() == 0)
+ continue;
+ MarkVirtualMembersReferenced(Loc, Base);
+ }
+}
+
+/// SetIvarInitializers - This routine builds initialization ASTs for the
+/// Objective-C implementation whose ivars need be initialized.
+void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
+ if (!getLangOptions().CPlusPlus)
+ return;
+ if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
+ llvm::SmallVector<ObjCIvarDecl*, 8> ivars;
+ CollectIvarsToConstructOrDestruct(OID, ivars);
+ if (ivars.empty())
+ return;
+ llvm::SmallVector<CXXCtorInitializer*, 32> AllToInit;
+ for (unsigned i = 0; i < ivars.size(); i++) {
+ FieldDecl *Field = ivars[i];
+ if (Field->isInvalidDecl())
+ continue;
+
+ CXXCtorInitializer *Member;
+ InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+ InitializationKind InitKind =
+ InitializationKind::CreateDefault(ObjCImplementation->getLocation());
+
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ ExprResult MemberInit =
+ InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg());
+ MemberInit = MaybeCreateExprWithCleanups(MemberInit);
+ // Note, MemberInit could actually come back empty if no initialization
+ // is required (e.g., because it would call a trivial default constructor)
+ if (!MemberInit.get() || MemberInit.isInvalid())
+ continue;
+
+ Member =
+ new (Context) CXXCtorInitializer(Context, Field, SourceLocation(),
+ SourceLocation(),
+ MemberInit.takeAs<Expr>(),
+ SourceLocation());
+ AllToInit.push_back(Member);
+
+ // Be sure that the destructor is accessible and is marked as referenced.
+ if (const RecordType *RecordTy
+ = Context.getBaseElementType(Field->getType())
+ ->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
+ MarkDeclarationReferenced(Field->getLocation(), Destructor);
+ CheckDestructorAccess(Field->getLocation(), Destructor,
+ PDiag(diag::err_access_dtor_ivar)
+ << Context.getBaseElementType(Field->getType()));
+ }
+ }
+ }
+ ObjCImplementation->setIvarInitializers(Context,
+ AllToInit.data(), AllToInit.size());
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
new file mode 100644
index 0000000..66f6f2b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -0,0 +1,2059 @@
+//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for Objective C declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace clang;
+
+static void DiagnoseObjCImplementedDeprecations(Sema &S,
+ NamedDecl *ND,
+ SourceLocation ImplLoc,
+ int select) {
+ if (ND && ND->getAttr<DeprecatedAttr>()) {
+ S.Diag(ImplLoc, diag::warn_deprecated_def) << select;
+ if (select == 0)
+ S.Diag(ND->getLocation(), diag::note_method_declared_at);
+ else
+ S.Diag(ND->getLocation(), diag::note_previous_decl) << "class";
+ }
+}
+
+/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
+/// and user declared, in the method definition's AST.
+void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
+ assert(getCurMethodDecl() == 0 && "Method parsing confused");
+ ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
+
+ // If we don't have a valid method decl, simply return.
+ if (!MDecl)
+ return;
+
+ // Allow the rest of sema to find private method decl implementations.
+ if (MDecl->isInstanceMethod())
+ AddInstanceMethodToGlobalPool(MDecl, true);
+ else
+ AddFactoryMethodToGlobalPool(MDecl, true);
+
+ // Allow all of Sema to see that we are entering a method definition.
+ PushDeclContext(FnBodyScope, MDecl);
+ PushFunctionScope();
+
+ // Create Decl objects for each parameter, entrring them in the scope for
+ // binding to their use.
+
+ // Insert the invisible arguments, self and _cmd!
+ MDecl->createImplicitParams(Context, MDecl->getClassInterface());
+
+ PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
+ PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);
+
+ // Introduce all of the other parameters into this scope.
+ for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(),
+ E = MDecl->param_end(); PI != E; ++PI) {
+ ParmVarDecl *Param = (*PI);
+ if (!Param->isInvalidDecl() &&
+ RequireCompleteType(Param->getLocation(), Param->getType(),
+ diag::err_typecheck_decl_incomplete_type))
+ Param->setInvalidDecl();
+ if ((*PI)->getIdentifier())
+ PushOnScopeChains(*PI, FnBodyScope);
+ }
+ // Warn on implementating deprecated methods under
+ // -Wdeprecated-implementations flag.
+ if (ObjCInterfaceDecl *IC = MDecl->getClassInterface())
+ if (ObjCMethodDecl *IMD =
+ IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()))
+ DiagnoseObjCImplementedDeprecations(*this,
+ dyn_cast<NamedDecl>(IMD),
+ MDecl->getLocation(), 0);
+}
+
+Decl *Sema::
+ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ Decl * const *ProtoRefs, unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc, AttributeList *AttrList) {
+ assert(ClassName && "Missing class identifier");
+
+ // Check for another declaration kind with the same name.
+ NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
+ LookupOrdinaryName, ForRedeclaration);
+
+ if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+ Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ }
+
+ ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (IDecl) {
+ // Class already seen. Is it a forward declaration?
+ if (!IDecl->isForwardDecl()) {
+ IDecl->setInvalidDecl();
+ Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
+ Diag(IDecl->getLocation(), diag::note_previous_definition);
+
+ // Return the previous class interface.
+ // FIXME: don't leak the objects passed in!
+ return IDecl;
+ } else {
+ IDecl->setLocation(AtInterfaceLoc);
+ IDecl->setForwardDecl(false);
+ IDecl->setClassLoc(ClassLoc);
+ // If the forward decl was in a PCH, we need to write it again in a
+ // dependent AST file.
+ IDecl->setChangedSinceDeserialization(true);
+
+ // Since this ObjCInterfaceDecl was created by a forward declaration,
+ // we now add it to the DeclContext since it wasn't added before
+ // (see ActOnForwardClassDeclaration).
+ IDecl->setLexicalDeclContext(CurContext);
+ CurContext->addDecl(IDecl);
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+ }
+ } else {
+ IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassName, ClassLoc);
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
+
+ PushOnScopeChains(IDecl, TUScope);
+ }
+
+ if (SuperName) {
+ // Check if a different kind of symbol declared in this scope.
+ PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
+ LookupOrdinaryName);
+
+ if (!PrevDecl) {
+ // Try to correct for a typo in the superclass name.
+ LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName);
+ if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
+ (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+ Diag(SuperLoc, diag::err_undef_superclass_suggest)
+ << SuperName << ClassName << PrevDecl->getDeclName();
+ Diag(PrevDecl->getLocation(), diag::note_previous_decl)
+ << PrevDecl->getDeclName();
+ }
+ }
+
+ if (PrevDecl == IDecl) {
+ Diag(SuperLoc, diag::err_recursive_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ IDecl->setLocEnd(ClassLoc);
+ } else {
+ ObjCInterfaceDecl *SuperClassDecl =
+ dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+
+ // Diagnose classes that inherit from deprecated classes.
+ if (SuperClassDecl)
+ (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
+
+ if (PrevDecl && SuperClassDecl == 0) {
+ // The previous declaration was not a class decl. Check if we have a
+ // typedef. If we do, get the underlying class type.
+ if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+ QualType T = TDecl->getUnderlyingType();
+ if (T->isObjCObjectType()) {
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
+ SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
+ }
+ }
+
+ // This handles the following case:
+ //
+ // typedef int SuperClass;
+ // @interface MyClass : SuperClass {} @end
+ //
+ if (!SuperClassDecl) {
+ Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ }
+ }
+
+ if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
+ if (!SuperClassDecl)
+ Diag(SuperLoc, diag::err_undef_superclass)
+ << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
+ else if (SuperClassDecl->isForwardDecl())
+ Diag(SuperLoc, diag::err_undef_superclass)
+ << SuperClassDecl->getDeclName() << ClassName
+ << SourceRange(AtInterfaceLoc, ClassLoc);
+ }
+ IDecl->setSuperClass(SuperClassDecl);
+ IDecl->setSuperClassLoc(SuperLoc);
+ IDecl->setLocEnd(SuperLoc);
+ }
+ } else { // we have a root class.
+ IDecl->setLocEnd(ClassLoc);
+ }
+
+ // Check then save referenced protocols.
+ if (NumProtoRefs) {
+ IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+ ProtoLocs, Context);
+ IDecl->setLocEnd(EndProtoLoc);
+ }
+
+ CheckObjCDeclScope(IDecl);
+ return IDecl;
+}
+
+/// ActOnCompatiblityAlias - this action is called after complete parsing of
+/// @compatibility_alias declaration. It sets up the alias relationships.
+Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
+ IdentifierInfo *AliasName,
+ SourceLocation AliasLocation,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLocation) {
+ // Look for previous declaration of alias name
+ NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
+ LookupOrdinaryName, ForRedeclaration);
+ if (ADecl) {
+ if (isa<ObjCCompatibleAliasDecl>(ADecl))
+ Diag(AliasLocation, diag::warn_previous_alias_decl);
+ else
+ Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
+ Diag(ADecl->getLocation(), diag::note_previous_declaration);
+ return 0;
+ }
+ // Check for class declaration
+ NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
+ LookupOrdinaryName, ForRedeclaration);
+ if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
+ QualType T = TDecl->getUnderlyingType();
+ if (T->isObjCObjectType()) {
+ if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
+ ClassName = IDecl->getIdentifier();
+ CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
+ LookupOrdinaryName, ForRedeclaration);
+ }
+ }
+ }
+ ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
+ if (CDecl == 0) {
+ Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
+ if (CDeclU)
+ Diag(CDeclU->getLocation(), diag::note_previous_declaration);
+ return 0;
+ }
+
+ // Everything checked out, instantiate a new alias declaration AST.
+ ObjCCompatibleAliasDecl *AliasDecl =
+ ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl);
+
+ if (!CheckObjCDeclScope(AliasDecl))
+ PushOnScopeChains(AliasDecl, TUScope);
+
+ return AliasDecl;
+}
+
+void Sema::CheckForwardProtocolDeclarationForCircularDependency(
+ IdentifierInfo *PName,
+ SourceLocation &Ploc, SourceLocation PrevLoc,
+ const ObjCList<ObjCProtocolDecl> &PList) {
+ for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
+ E = PList.end(); I != E; ++I) {
+
+ if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(),
+ Ploc)) {
+ if (PDecl->getIdentifier() == PName) {
+ Diag(Ploc, diag::err_protocol_has_circular_dependency);
+ Diag(PrevLoc, diag::note_previous_definition);
+ }
+ CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
+ PDecl->getLocation(), PDecl->getReferencedProtocols());
+ }
+ }
+}
+
+Decl *
+Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
+ IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList) {
+ // FIXME: Deal with AttrList.
+ assert(ProtocolName && "Missing protocol identifier");
+ ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc);
+ if (PDecl) {
+ // Protocol already seen. Better be a forward protocol declaration
+ if (!PDecl->isForwardDecl()) {
+ Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
+ Diag(PDecl->getLocation(), diag::note_previous_definition);
+ // Just return the protocol we already had.
+ // FIXME: don't leak the objects passed in!
+ return PDecl;
+ }
+ ObjCList<ObjCProtocolDecl> PList;
+ PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
+ CheckForwardProtocolDeclarationForCircularDependency(
+ ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
+
+ // Make sure the cached decl gets a valid start location.
+ PDecl->setLocation(AtProtoInterfaceLoc);
+ PDecl->setForwardDecl(false);
+ CurContext->addDecl(PDecl);
+ // Repeat in dependent AST files.
+ PDecl->setChangedSinceDeserialization(true);
+ } else {
+ PDecl = ObjCProtocolDecl::Create(Context, CurContext,
+ AtProtoInterfaceLoc,ProtocolName);
+ PushOnScopeChains(PDecl, TUScope);
+ PDecl->setForwardDecl(false);
+ }
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
+ if (NumProtoRefs) {
+ /// Check then save referenced protocols.
+ PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+ ProtoLocs, Context);
+ PDecl->setLocEnd(EndProtoLoc);
+ }
+
+ CheckObjCDeclScope(PDecl);
+ return PDecl;
+}
+
+/// FindProtocolDeclaration - This routine looks up protocols and
+/// issues an error if they are not declared. It returns list of
+/// protocol declarations in its 'Protocols' argument.
+void
+Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
+ const IdentifierLocPair *ProtocolId,
+ unsigned NumProtocols,
+ llvm::SmallVectorImpl<Decl *> &Protocols) {
+ for (unsigned i = 0; i != NumProtocols; ++i) {
+ ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
+ ProtocolId[i].second);
+ if (!PDecl) {
+ LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second,
+ LookupObjCProtocolName);
+ if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
+ (PDecl = R.getAsSingle<ObjCProtocolDecl>())) {
+ Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)
+ << ProtocolId[i].first << R.getLookupName();
+ Diag(PDecl->getLocation(), diag::note_previous_decl)
+ << PDecl->getDeclName();
+ }
+ }
+
+ if (!PDecl) {
+ Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
+ << ProtocolId[i].first;
+ continue;
+ }
+
+ (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+
+ // If this is a forward declaration and we are supposed to warn in this
+ // case, do it.
+ if (WarnOnDeclarations && PDecl->isForwardDecl())
+ Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
+ << ProtocolId[i].first;
+ Protocols.push_back(PDecl);
+ }
+}
+
+/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
+/// a class method in its extension.
+///
+void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID) {
+ if (!ID)
+ return; // Possibly due to previous error
+
+ llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
+ for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(),
+ e = ID->meth_end(); i != e; ++i) {
+ ObjCMethodDecl *MD = *i;
+ MethodMap[MD->getSelector()] = MD;
+ }
+
+ if (MethodMap.empty())
+ return;
+ for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(),
+ e = CAT->meth_end(); i != e; ++i) {
+ ObjCMethodDecl *Method = *i;
+ const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
+ if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+ Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+ << Method->getDeclName();
+ Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ }
+ }
+}
+
+/// ActOnForwardProtocolDeclaration - Handle @protocol foo;
+Decl *
+Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
+ const IdentifierLocPair *IdentList,
+ unsigned NumElts,
+ AttributeList *attrList) {
+ llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
+ llvm::SmallVector<SourceLocation, 8> ProtoLocs;
+
+ for (unsigned i = 0; i != NumElts; ++i) {
+ IdentifierInfo *Ident = IdentList[i].first;
+ ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second);
+ bool isNew = false;
+ if (PDecl == 0) { // Not already seen?
+ PDecl = ObjCProtocolDecl::Create(Context, CurContext,
+ IdentList[i].second, Ident);
+ PushOnScopeChains(PDecl, TUScope, false);
+ isNew = true;
+ }
+ if (attrList) {
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
+ if (!isNew)
+ PDecl->setChangedSinceDeserialization(true);
+ }
+ Protocols.push_back(PDecl);
+ ProtoLocs.push_back(IdentList[i].second);
+ }
+
+ ObjCForwardProtocolDecl *PDecl =
+ ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc,
+ Protocols.data(), Protocols.size(),
+ ProtoLocs.data());
+ CurContext->addDecl(PDecl);
+ CheckObjCDeclScope(PDecl);
+ return PDecl;
+}
+
+Decl *Sema::
+ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *CategoryName,
+ SourceLocation CategoryLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc) {
+ ObjCCategoryDecl *CDecl;
+ ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
+
+ /// Check that class of this category is already completely declared.
+ if (!IDecl || IDecl->isForwardDecl()) {
+ // Create an invalid ObjCCategoryDecl to serve as context for
+ // the enclosing method declarations. We mark the decl invalid
+ // to make it clear that this isn't a valid AST.
+ CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassLoc, CategoryLoc, CategoryName);
+ CDecl->setInvalidDecl();
+ Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+ return CDecl;
+ }
+
+ if (!CategoryName && IDecl->getImplementation()) {
+ Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
+ Diag(IDecl->getImplementation()->getLocation(),
+ diag::note_implementation_declared);
+ }
+
+ CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassLoc, CategoryLoc, CategoryName);
+ // FIXME: PushOnScopeChains?
+ CurContext->addDecl(CDecl);
+
+ CDecl->setClassInterface(IDecl);
+ // Insert class extension to the list of class's categories.
+ if (!CategoryName)
+ CDecl->insertNextClassCategory();
+
+ // If the interface is deprecated, warn about it.
+ (void)DiagnoseUseOfDecl(IDecl, ClassLoc);
+
+ if (CategoryName) {
+ /// Check for duplicate interface declaration for this category
+ ObjCCategoryDecl *CDeclChain;
+ for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
+ CDeclChain = CDeclChain->getNextClassCategory()) {
+ if (CDeclChain->getIdentifier() == CategoryName) {
+ // Class extensions can be declared multiple times.
+ Diag(CategoryLoc, diag::warn_dup_category_def)
+ << ClassName << CategoryName;
+ Diag(CDeclChain->getLocation(), diag::note_previous_definition);
+ break;
+ }
+ }
+ if (!CDeclChain)
+ CDecl->insertNextClassCategory();
+ }
+
+ if (NumProtoRefs) {
+ CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+ ProtoLocs, Context);
+ // Protocols in the class extension belong to the class.
+ if (CDecl->IsClassExtension())
+ IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
+ NumProtoRefs, Context);
+ }
+
+ CheckObjCDeclScope(CDecl);
+ return CDecl;
+}
+
+/// ActOnStartCategoryImplementation - Perform semantic checks on the
+/// category implementation declaration and build an ObjCCategoryImplDecl
+/// object.
+Decl *Sema::ActOnStartCategoryImplementation(
+ SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *CatName, SourceLocation CatLoc) {
+ ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
+ ObjCCategoryDecl *CatIDecl = 0;
+ if (IDecl) {
+ CatIDecl = IDecl->FindCategoryDeclaration(CatName);
+ if (!CatIDecl) {
+ // Category @implementation with no corresponding @interface.
+ // Create and install one.
+ CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ CatName);
+ CatIDecl->setClassInterface(IDecl);
+ CatIDecl->insertNextClassCategory();
+ }
+ }
+
+ ObjCCategoryImplDecl *CDecl =
+ ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName,
+ IDecl);
+ /// Check that class of this category is already completely declared.
+ if (!IDecl || IDecl->isForwardDecl())
+ Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+
+ // FIXME: PushOnScopeChains?
+ CurContext->addDecl(CDecl);
+
+ /// Check that CatName, category name, is not used in another implementation.
+ if (CatIDecl) {
+ if (CatIDecl->getImplementation()) {
+ Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
+ << CatName;
+ Diag(CatIDecl->getImplementation()->getLocation(),
+ diag::note_previous_definition);
+ } else {
+ CatIDecl->setImplementation(CDecl);
+ // Warn on implementating category of deprecated class under
+ // -Wdeprecated-implementations flag.
+ DiagnoseObjCImplementedDeprecations(*this,
+ dyn_cast<NamedDecl>(IDecl),
+ CDecl->getLocation(), 2);
+ }
+ }
+
+ CheckObjCDeclScope(CDecl);
+ return CDecl;
+}
+
+Decl *Sema::ActOnStartClassImplementation(
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc) {
+ ObjCInterfaceDecl* IDecl = 0;
+ // Check for another declaration kind with the same name.
+ NamedDecl *PrevDecl
+ = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+ Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+ // If this is a forward declaration of an interface, warn.
+ if (IDecl->isForwardDecl()) {
+ Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+ IDecl = 0;
+ }
+ } else {
+ // We did not find anything with the name ClassName; try to correct for
+ // typos in the class name.
+ LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName);
+ if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&
+ (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
+ // Suggest the (potentially) correct interface name. However, put the
+ // fix-it hint itself in a separate note, since changing the name in
+ // the warning would make the fix-it change semantics.However, don't
+ // provide a code-modification hint or use the typo name for recovery,
+ // because this is just a warning. The program may actually be correct.
+ Diag(ClassLoc, diag::warn_undef_interface_suggest)
+ << ClassName << R.getLookupName();
+ Diag(IDecl->getLocation(), diag::note_previous_decl)
+ << R.getLookupName()
+ << FixItHint::CreateReplacement(ClassLoc,
+ R.getLookupName().getAsString());
+ IDecl = 0;
+ } else {
+ Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
+ }
+ }
+
+ // Check that super class name is valid class name
+ ObjCInterfaceDecl* SDecl = 0;
+ if (SuperClassname) {
+ // Check if a different kind of symbol declared in this scope.
+ PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc,
+ LookupOrdinaryName);
+ if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+ Diag(SuperClassLoc, diag::err_redefinition_different_kind)
+ << SuperClassname;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ } else {
+ SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (!SDecl)
+ Diag(SuperClassLoc, diag::err_undef_superclass)
+ << SuperClassname << ClassName;
+ else if (IDecl && IDecl->getSuperClass() != SDecl) {
+ // This implementation and its interface do not have the same
+ // super class.
+ Diag(SuperClassLoc, diag::err_conflicting_super_class)
+ << SDecl->getDeclName();
+ Diag(SDecl->getLocation(), diag::note_previous_definition);
+ }
+ }
+ }
+
+ if (!IDecl) {
+ // Legacy case of @implementation with no corresponding @interface.
+ // Build, chain & install the interface decl into the identifier.
+
+ // FIXME: Do we support attributes on the @implementation? If so we should
+ // copy them over.
+ IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
+ ClassName, ClassLoc, false, true);
+ IDecl->setSuperClass(SDecl);
+ IDecl->setLocEnd(ClassLoc);
+
+ PushOnScopeChains(IDecl, TUScope);
+ } else {
+ // Mark the interface as being completed, even if it was just as
+ // @class ....;
+ // declaration; the user cannot reopen it.
+ IDecl->setForwardDecl(false);
+ }
+
+ ObjCImplementationDecl* IMPDecl =
+ ObjCImplementationDecl::Create(Context, CurContext, AtClassImplLoc,
+ IDecl, SDecl);
+
+ if (CheckObjCDeclScope(IMPDecl))
+ return IMPDecl;
+
+ // Check that there is no duplicate implementation of this class.
+ if (IDecl->getImplementation()) {
+ // FIXME: Don't leak everything!
+ Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
+ Diag(IDecl->getImplementation()->getLocation(),
+ diag::note_previous_definition);
+ } else { // add it to the list.
+ IDecl->setImplementation(IMPDecl);
+ PushOnScopeChains(IMPDecl, TUScope);
+ // Warn on implementating deprecated class under
+ // -Wdeprecated-implementations flag.
+ DiagnoseObjCImplementedDeprecations(*this,
+ dyn_cast<NamedDecl>(IDecl),
+ IMPDecl->getLocation(), 1);
+ }
+ return IMPDecl;
+}
+
+void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+ ObjCIvarDecl **ivars, unsigned numIvars,
+ SourceLocation RBrace) {
+ assert(ImpDecl && "missing implementation decl");
+ ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();
+ if (!IDecl)
+ return;
+ /// Check case of non-existing @interface decl.
+ /// (legacy objective-c @implementation decl without an @interface decl).
+ /// Add implementations's ivar to the synthesize class's ivar list.
+ if (IDecl->isImplicitInterfaceDecl()) {
+ IDecl->setLocEnd(RBrace);
+ // Add ivar's to class's DeclContext.
+ for (unsigned i = 0, e = numIvars; i != e; ++i) {
+ ivars[i]->setLexicalDeclContext(ImpDecl);
+ IDecl->makeDeclVisibleInContext(ivars[i], false);
+ ImpDecl->addDecl(ivars[i]);
+ }
+
+ return;
+ }
+ // If implementation has empty ivar list, just return.
+ if (numIvars == 0)
+ return;
+
+ assert(ivars && "missing @implementation ivars");
+ if (LangOpts.ObjCNonFragileABI2) {
+ if (ImpDecl->getSuperClass())
+ Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);
+ for (unsigned i = 0; i < numIvars; i++) {
+ ObjCIvarDecl* ImplIvar = ivars[i];
+ if (const ObjCIvarDecl *ClsIvar =
+ IDecl->getIvarDecl(ImplIvar->getIdentifier())) {
+ Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
+ Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+ continue;
+ }
+ // Instance ivar to Implementation's DeclContext.
+ ImplIvar->setLexicalDeclContext(ImpDecl);
+ IDecl->makeDeclVisibleInContext(ImplIvar, false);
+ ImpDecl->addDecl(ImplIvar);
+ }
+ return;
+ }
+ // Check interface's Ivar list against those in the implementation.
+ // names and types must match.
+ //
+ unsigned j = 0;
+ ObjCInterfaceDecl::ivar_iterator
+ IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
+ for (; numIvars > 0 && IVI != IVE; ++IVI) {
+ ObjCIvarDecl* ImplIvar = ivars[j++];
+ ObjCIvarDecl* ClsIvar = *IVI;
+ assert (ImplIvar && "missing implementation ivar");
+ assert (ClsIvar && "missing class ivar");
+
+ // First, make sure the types match.
+ if (Context.getCanonicalType(ImplIvar->getType()) !=
+ Context.getCanonicalType(ClsIvar->getType())) {
+ Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)
+ << ImplIvar->getIdentifier()
+ << ImplIvar->getType() << ClsIvar->getType();
+ Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+ } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) {
+ Expr *ImplBitWidth = ImplIvar->getBitWidth();
+ Expr *ClsBitWidth = ClsIvar->getBitWidth();
+ if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() !=
+ ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) {
+ Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth)
+ << ImplIvar->getIdentifier();
+ Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition);
+ }
+ }
+ // Make sure the names are identical.
+ if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
+ Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)
+ << ImplIvar->getIdentifier() << ClsIvar->getIdentifier();
+ Diag(ClsIvar->getLocation(), diag::note_previous_definition);
+ }
+ --numIvars;
+ }
+
+ if (numIvars > 0)
+ Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count);
+ else if (IVI != IVE)
+ Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count);
+}
+
+void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
+ bool &IncompleteImpl, unsigned DiagID) {
+ if (!IncompleteImpl) {
+ Diag(ImpLoc, diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ if (DiagID == diag::warn_unimplemented_protocol_method)
+ Diag(ImpLoc, DiagID) << method->getDeclName();
+ else
+ Diag(method->getLocation(), DiagID) << method->getDeclName();
+}
+
+/// Determines if type B can be substituted for type A. Returns true if we can
+/// guarantee that anything that the user will do to an object of type A can
+/// also be done to an object of type B. This is trivially true if the two
+/// types are the same, or if B is a subclass of A. It becomes more complex
+/// in cases where protocols are involved.
+///
+/// Object types in Objective-C describe the minimum requirements for an
+/// object, rather than providing a complete description of a type. For
+/// example, if A is a subclass of B, then B* may refer to an instance of A.
+/// The principle of substitutability means that we may use an instance of A
+/// anywhere that we may use an instance of B - it will implement all of the
+/// ivars of B and all of the methods of B.
+///
+/// This substitutability is important when type checking methods, because
+/// the implementation may have stricter type definitions than the interface.
+/// The interface specifies minimum requirements, but the implementation may
+/// have more accurate ones. For example, a method may privately accept
+/// instances of B, but only publish that it accepts instances of A. Any
+/// object passed to it will be type checked against B, and so will implicitly
+/// by a valid A*. Similarly, a method may return a subclass of the class that
+/// it is declared as returning.
+///
+/// This is most important when considering subclassing. A method in a
+/// subclass must accept any object as an argument that its superclass's
+/// implementation accepts. It may, however, accept a more general type
+/// without breaking substitutability (i.e. you can still use the subclass
+/// anywhere that you can use the superclass, but not vice versa). The
+/// converse requirement applies to return types: the return type for a
+/// subclass method must be a valid object of the kind that the superclass
+/// advertises, but it may be specified more accurately. This avoids the need
+/// for explicit down-casting by callers.
+///
+/// Note: This is a stricter requirement than for assignment.
+static bool isObjCTypeSubstitutable(ASTContext &Context,
+ const ObjCObjectPointerType *A,
+ const ObjCObjectPointerType *B,
+ bool rejectId) {
+ // Reject a protocol-unqualified id.
+ if (rejectId && B->isObjCIdType()) return false;
+
+ // If B is a qualified id, then A must also be a qualified id and it must
+ // implement all of the protocols in B. It may not be a qualified class.
+ // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a
+ // stricter definition so it is not substitutable for id<A>.
+ if (B->isObjCQualifiedIdType()) {
+ return A->isObjCQualifiedIdType() &&
+ Context.ObjCQualifiedIdTypesAreCompatible(QualType(A, 0),
+ QualType(B,0),
+ false);
+ }
+
+ /*
+ // id is a special type that bypasses type checking completely. We want a
+ // warning when it is used in one place but not another.
+ if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false;
+
+
+ // If B is a qualified id, then A must also be a qualified id (which it isn't
+ // if we've got this far)
+ if (B->isObjCQualifiedIdType()) return false;
+ */
+
+ // Now we know that A and B are (potentially-qualified) class types. The
+ // normal rules for assignment apply.
+ return Context.canAssignObjCInterfaces(A, B);
+}
+
+static SourceRange getTypeRange(TypeSourceInfo *TSI) {
+ return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());
+}
+
+static void CheckMethodOverrideReturn(Sema &S,
+ ObjCMethodDecl *MethodImpl,
+ ObjCMethodDecl *MethodIface) {
+ if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
+ MethodIface->getResultType()))
+ return;
+
+ unsigned DiagID = diag::warn_conflicting_ret_types;
+
+ // Mismatches between ObjC pointers go into a different warning
+ // category, and sometimes they're even completely whitelisted.
+ if (const ObjCObjectPointerType *ImplPtrTy =
+ MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *IfacePtrTy =
+ MethodIface->getResultType()->getAs<ObjCObjectPointerType>()) {
+ // Allow non-matching return types as long as they don't violate
+ // the principle of substitutability. Specifically, we permit
+ // return types that are subclasses of the declared return type,
+ // or that are more-qualified versions of the declared type.
+ if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
+ return;
+
+ DiagID = diag::warn_non_covariant_ret_types;
+ }
+ }
+
+ S.Diag(MethodImpl->getLocation(), DiagID)
+ << MethodImpl->getDeclName()
+ << MethodIface->getResultType()
+ << MethodImpl->getResultType()
+ << getTypeRange(MethodImpl->getResultTypeSourceInfo());
+ S.Diag(MethodIface->getLocation(), diag::note_previous_definition)
+ << getTypeRange(MethodIface->getResultTypeSourceInfo());
+}
+
+static void CheckMethodOverrideParam(Sema &S,
+ ObjCMethodDecl *MethodImpl,
+ ObjCMethodDecl *MethodIface,
+ ParmVarDecl *ImplVar,
+ ParmVarDecl *IfaceVar) {
+ QualType ImplTy = ImplVar->getType();
+ QualType IfaceTy = IfaceVar->getType();
+ if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
+ return;
+
+ unsigned DiagID = diag::warn_conflicting_param_types;
+
+ // Mismatches between ObjC pointers go into a different warning
+ // category, and sometimes they're even completely whitelisted.
+ if (const ObjCObjectPointerType *ImplPtrTy =
+ ImplTy->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *IfacePtrTy =
+ IfaceTy->getAs<ObjCObjectPointerType>()) {
+ // Allow non-matching argument types as long as they don't
+ // violate the principle of substitutability. Specifically, the
+ // implementation must accept any objects that the superclass
+ // accepts, however it may also accept others.
+ if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
+ return;
+
+ DiagID = diag::warn_non_contravariant_param_types;
+ }
+ }
+
+ S.Diag(ImplVar->getLocation(), DiagID)
+ << getTypeRange(ImplVar->getTypeSourceInfo())
+ << MethodImpl->getDeclName() << IfaceTy << ImplTy;
+ S.Diag(IfaceVar->getLocation(), diag::note_previous_definition)
+ << getTypeRange(IfaceVar->getTypeSourceInfo());
+}
+
+
+void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
+ ObjCMethodDecl *IntfMethodDecl) {
+ CheckMethodOverrideReturn(*this, ImpMethodDecl, IntfMethodDecl);
+
+ for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
+ IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+ IM != EM; ++IM, ++IF)
+ CheckMethodOverrideParam(*this, ImpMethodDecl, IntfMethodDecl, *IM, *IF);
+
+ if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) {
+ Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
+ Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration);
+ }
+}
+
+/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely
+/// improve the efficiency of selector lookups and type checking by associating
+/// with each protocol / interface / category the flattened instance tables. If
+/// we used an immutable set to keep the table then it wouldn't add significant
+/// memory cost and it would be handy for lookups.
+
+/// CheckProtocolMethodDefs - This routine checks unimplemented methods
+/// Declared in protocol, and those referenced by it.
+void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
+ bool& IncompleteImpl,
+ const llvm::DenseSet<Selector> &InsMap,
+ const llvm::DenseSet<Selector> &ClsMap,
+ ObjCContainerDecl *CDecl) {
+ ObjCInterfaceDecl *IDecl;
+ if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl))
+ IDecl = C->getClassInterface();
+ else
+ IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
+ assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
+
+ ObjCInterfaceDecl *Super = IDecl->getSuperClass();
+ ObjCInterfaceDecl *NSIDecl = 0;
+ if (getLangOptions().NeXTRuntime) {
+ // check to see if class implements forwardInvocation method and objects
+ // of this class are derived from 'NSProxy' so that to forward requests
+ // from one object to another.
+ // Under such conditions, which means that every method possible is
+ // implemented in the class, we should not issue "Method definition not
+ // found" warnings.
+ // FIXME: Use a general GetUnarySelector method for this.
+ IdentifierInfo* II = &Context.Idents.get("forwardInvocation");
+ Selector fISelector = Context.Selectors.getSelector(1, &II);
+ if (InsMap.count(fISelector))
+ // Is IDecl derived from 'NSProxy'? If so, no instance methods
+ // need be implemented in the implementation.
+ NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy"));
+ }
+
+ // If a method lookup fails locally we still need to look and see if
+ // the method was implemented by a base class or an inherited
+ // protocol. This lookup is slow, but occurs rarely in correct code
+ // and otherwise would terminate in a warning.
+
+ // check unimplemented instance methods.
+ if (!NSIDecl)
+ for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
+ E = PDecl->instmeth_end(); I != E; ++I) {
+ ObjCMethodDecl *method = *I;
+ if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+ !method->isSynthesized() && !InsMap.count(method->getSelector()) &&
+ (!Super ||
+ !Super->lookupInstanceMethod(method->getSelector()))) {
+ // Ugly, but necessary. Method declared in protcol might have
+ // have been synthesized due to a property declared in the class which
+ // uses the protocol.
+ ObjCMethodDecl *MethodInClass =
+ IDecl->lookupInstanceMethod(method->getSelector());
+ if (!MethodInClass || !MethodInClass->isSynthesized()) {
+ unsigned DIAG = diag::warn_unimplemented_protocol_method;
+ if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
+ != Diagnostic::Ignored) {
+ WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
+ Diag(method->getLocation(), diag::note_method_declared_at);
+ Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
+ << PDecl->getDeclName();
+ }
+ }
+ }
+ }
+ // check unimplemented class methods
+ for (ObjCProtocolDecl::classmeth_iterator
+ I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
+ I != E; ++I) {
+ ObjCMethodDecl *method = *I;
+ if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
+ !ClsMap.count(method->getSelector()) &&
+ (!Super || !Super->lookupClassMethod(method->getSelector()))) {
+ unsigned DIAG = diag::warn_unimplemented_protocol_method;
+ if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != Diagnostic::Ignored) {
+ WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
+ Diag(method->getLocation(), diag::note_method_declared_at);
+ Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) <<
+ PDecl->getDeclName();
+ }
+ }
+ }
+ // Check on this protocols's referenced protocols, recursively.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI)
+ CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
+}
+
+/// MatchAllMethodDeclarations - Check methods declaraed in interface or
+/// or protocol against those declared in their implementations.
+///
+void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+ const llvm::DenseSet<Selector> &ClsMap,
+ llvm::DenseSet<Selector> &InsMapSeen,
+ llvm::DenseSet<Selector> &ClsMapSeen,
+ ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* CDecl,
+ bool &IncompleteImpl,
+ bool ImmediateClass) {
+ // Check and see if instance methods in class interface have been
+ // implemented in the implementation class. If so, their types match.
+ for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
+ E = CDecl->instmeth_end(); I != E; ++I) {
+ if (InsMapSeen.count((*I)->getSelector()))
+ continue;
+ InsMapSeen.insert((*I)->getSelector());
+ if (!(*I)->isSynthesized() &&
+ !InsMap.count((*I)->getSelector())) {
+ if (ImmediateClass)
+ WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ diag::note_undef_method_impl);
+ continue;
+ } else {
+ ObjCMethodDecl *ImpMethodDecl =
+ IMPDecl->getInstanceMethod((*I)->getSelector());
+ ObjCMethodDecl *IntfMethodDecl =
+ CDecl->getInstanceMethod((*I)->getSelector());
+ assert(IntfMethodDecl &&
+ "IntfMethodDecl is null in ImplMethodsVsClassMethods");
+ // ImpMethodDecl may be null as in a @dynamic property.
+ if (ImpMethodDecl)
+ WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ }
+ }
+
+ // Check and see if class methods in class interface have been
+ // implemented in the implementation class. If so, their types match.
+ for (ObjCInterfaceDecl::classmeth_iterator
+ I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) {
+ if (ClsMapSeen.count((*I)->getSelector()))
+ continue;
+ ClsMapSeen.insert((*I)->getSelector());
+ if (!ClsMap.count((*I)->getSelector())) {
+ if (ImmediateClass)
+ WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl,
+ diag::note_undef_method_impl);
+ } else {
+ ObjCMethodDecl *ImpMethodDecl =
+ IMPDecl->getClassMethod((*I)->getSelector());
+ ObjCMethodDecl *IntfMethodDecl =
+ CDecl->getClassMethod((*I)->getSelector());
+ WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ }
+ }
+
+ if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+ // Also methods in class extensions need be looked at next.
+ for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension();
+ ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension())
+ MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+ IMPDecl,
+ const_cast<ObjCCategoryDecl *>(ClsExtDecl),
+ IncompleteImpl, false);
+
+ // Check for any implementation of a methods declared in protocol.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
+ MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+ IMPDecl,
+ (*PI), IncompleteImpl, false);
+ if (I->getSuperClass())
+ MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+ IMPDecl,
+ I->getSuperClass(), IncompleteImpl, false);
+ }
+}
+
+void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* CDecl,
+ bool IncompleteImpl) {
+ llvm::DenseSet<Selector> InsMap;
+ // Check and see if instance methods in class interface have been
+ // implemented in the implementation class.
+ for (ObjCImplementationDecl::instmeth_iterator
+ I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
+ InsMap.insert((*I)->getSelector());
+
+ // Check and see if properties declared in the interface have either 1)
+ // an implementation or 2) there is a @synthesize/@dynamic implementation
+ // of the property in the @implementation.
+ if (isa<ObjCInterfaceDecl>(CDecl) &&
+ !(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2))
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
+
+ llvm::DenseSet<Selector> ClsMap;
+ for (ObjCImplementationDecl::classmeth_iterator
+ I = IMPDecl->classmeth_begin(),
+ E = IMPDecl->classmeth_end(); I != E; ++I)
+ ClsMap.insert((*I)->getSelector());
+
+ // Check for type conflict of methods declared in a class/protocol and
+ // its implementation; if any.
+ llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
+ MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+ IMPDecl, CDecl,
+ IncompleteImpl, true);
+
+ // Check the protocol list for unimplemented methods in the @implementation
+ // class.
+ // Check and see if class methods in class interface have been
+ // implemented in the implementation class.
+
+ if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
+ CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+ InsMap, ClsMap, I);
+ // Check class extensions (unnamed categories)
+ for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension();
+ Categories; Categories = Categories->getNextClassExtension())
+ ImplMethodsVsClassMethods(S, IMPDecl,
+ const_cast<ObjCCategoryDecl*>(Categories),
+ IncompleteImpl);
+ } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ // For extended class, unimplemented methods in its protocols will
+ // be reported in the primary class.
+ if (!C->IsClassExtension()) {
+ for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
+ E = C->protocol_end(); PI != E; ++PI)
+ CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
+ InsMap, ClsMap, CDecl);
+ // Report unimplemented properties in the category as well.
+ // When reporting on missing setter/getters, do not report when
+ // setter/getter is implemented in category's primary class
+ // implementation.
+ if (ObjCInterfaceDecl *ID = C->getClassInterface())
+ if (ObjCImplDecl *IMP = ID->getImplementation()) {
+ for (ObjCImplementationDecl::instmeth_iterator
+ I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
+ InsMap.insert((*I)->getSelector());
+ }
+ DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
+ }
+ } else
+ assert(false && "invalid ObjCContainerDecl type.");
+}
+
+/// ActOnForwardClassDeclaration -
+Decl *
+Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts) {
+ llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces;
+
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // Check for another declaration kind with the same name.
+ NamedDecl *PrevDecl
+ = LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
+ LookupOrdinaryName, ForRedeclaration);
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
+ if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
+ // GCC apparently allows the following idiom:
+ //
+ // typedef NSObject < XCElementTogglerP > XCElementToggler;
+ // @class XCElementToggler;
+ //
+ // FIXME: Make an extension?
+ TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl);
+ if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
+ Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ } else {
+ // a forward class declaration matching a typedef name of a class refers
+ // to the underlying class.
+ if (const ObjCObjectType *OI =
+ TDD->getUnderlyingType()->getAs<ObjCObjectType>())
+ PrevDecl = OI->getInterface();
+ }
+ }
+ ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+ if (!IDecl) { // Not already seen? Make a forward decl.
+ IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
+ IdentList[i], IdentLocs[i], true);
+
+ // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to
+ // the current DeclContext. This prevents clients that walk DeclContext
+ // from seeing the imaginary ObjCInterfaceDecl until it is actually
+ // declared later (if at all). We also take care to explicitly make
+ // sure this declaration is visible for name lookup.
+ PushOnScopeChains(IDecl, TUScope, false);
+ CurContext->makeDeclVisibleInContext(IDecl, true);
+ }
+
+ Interfaces.push_back(IDecl);
+ }
+
+ assert(Interfaces.size() == NumElts);
+ ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc,
+ Interfaces.data(), IdentLocs,
+ Interfaces.size());
+ CurContext->addDecl(CDecl);
+ CheckObjCDeclScope(CDecl);
+ return CDecl;
+}
+
+
+/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
+/// returns true, or false, accordingly.
+/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
+bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+ const ObjCMethodDecl *PrevMethod,
+ bool matchBasedOnSizeAndAlignment,
+ bool matchBasedOnStrictEqulity) {
+ QualType T1 = Context.getCanonicalType(Method->getResultType());
+ QualType T2 = Context.getCanonicalType(PrevMethod->getResultType());
+
+ if (T1 != T2) {
+ // The result types are different.
+ if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity)
+ return false;
+ // Incomplete types don't have a size and alignment.
+ if (T1->isIncompleteType() || T2->isIncompleteType())
+ return false;
+ // Check is based on size and alignment.
+ if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
+ return false;
+ }
+
+ ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+ E = Method->param_end();
+ ObjCMethodDecl::param_iterator PrevI = PrevMethod->param_begin();
+
+ for (; ParamI != E; ++ParamI, ++PrevI) {
+ assert(PrevI != PrevMethod->param_end() && "Param mismatch");
+ T1 = Context.getCanonicalType((*ParamI)->getType());
+ T2 = Context.getCanonicalType((*PrevI)->getType());
+ if (T1 != T2) {
+ // The result types are different.
+ if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity)
+ return false;
+ // Incomplete types don't have a size and alignment.
+ if (T1->isIncompleteType() || T2->isIncompleteType())
+ return false;
+ // Check is based on size and alignment.
+ if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
+ return false;
+ }
+ }
+ return true;
+}
+
+/// \brief Read the contents of the method pool for a given selector from
+/// external storage.
+///
+/// This routine should only be called once, when the method pool has no entry
+/// for this selector.
+Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) {
+ assert(ExternalSource && "We need an external AST source");
+ assert(MethodPool.find(Sel) == MethodPool.end() &&
+ "Selector data already loaded into the method pool");
+
+ // Read the method list from the external source.
+ GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel);
+
+ return MethodPool.insert(std::make_pair(Sel, Methods)).first;
+}
+
+void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
+ bool instance) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector());
+ if (Pos == MethodPool.end()) {
+ if (ExternalSource)
+ Pos = ReadMethodPool(Method->getSelector());
+ else
+ Pos = MethodPool.insert(std::make_pair(Method->getSelector(),
+ GlobalMethods())).first;
+ }
+ Method->setDefined(impl);
+ ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
+ if (Entry.Method == 0) {
+ // Haven't seen a method with this selector name yet - add it.
+ Entry.Method = Method;
+ Entry.Next = 0;
+ return;
+ }
+
+ // We've seen a method with this name, see if we have already seen this type
+ // signature.
+ for (ObjCMethodList *List = &Entry; List; List = List->Next)
+ if (MatchTwoMethodDeclarations(Method, List->Method)) {
+ ObjCMethodDecl *PrevObjCMethod = List->Method;
+ PrevObjCMethod->setDefined(impl);
+ // If a method is deprecated, push it in the global pool.
+ // This is used for better diagnostics.
+ if (Method->getAttr<DeprecatedAttr>()) {
+ if (!PrevObjCMethod->getAttr<DeprecatedAttr>())
+ List->Method = Method;
+ }
+ // If new method is unavailable, push it into global pool
+ // unless previous one is deprecated.
+ if (Method->getAttr<UnavailableAttr>()) {
+ if (!PrevObjCMethod->getAttr<UnavailableAttr>() &&
+ !PrevObjCMethod->getAttr<DeprecatedAttr>())
+ List->Method = Method;
+ }
+ return;
+ }
+
+ // We have a new signature for an existing method - add it.
+ // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+ ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+ Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next);
+}
+
+ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass,
+ bool warn, bool instance) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ if (Pos == MethodPool.end()) {
+ if (ExternalSource)
+ Pos = ReadMethodPool(Sel);
+ else
+ return 0;
+ }
+
+ ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+
+ bool strictSelectorMatch = receiverIdOrClass && warn &&
+ (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl,
+ R.getBegin()) !=
+ Diagnostic::Ignored);
+ if (warn && MethList.Method && MethList.Next) {
+ bool issueWarning = false;
+ if (strictSelectorMatch)
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+ // This checks if the methods differ in type mismatch.
+ if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, false, true))
+ issueWarning = true;
+ }
+
+ if (!issueWarning)
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+ // This checks if the methods differ by size & alignment.
+ if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
+ issueWarning = true;
+ }
+
+ if (issueWarning) {
+ if (strictSelectorMatch)
+ Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
+ else
+ Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+ Diag(MethList.Method->getLocStart(), diag::note_using)
+ << MethList.Method->getSourceRange();
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+ Diag(Next->Method->getLocStart(), diag::note_also_found)
+ << Next->Method->getSourceRange();
+ }
+ }
+ return MethList.Method;
+}
+
+ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ if (Pos == MethodPool.end())
+ return 0;
+
+ GlobalMethods &Methods = Pos->second;
+
+ if (Methods.first.Method && Methods.first.Method->isDefined())
+ return Methods.first.Method;
+ if (Methods.second.Method && Methods.second.Method->isDefined())
+ return Methods.second.Method;
+ return 0;
+}
+
+/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
+/// identical selector names in current and its super classes and issues
+/// a warning if any of their argument types are incompatible.
+void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
+ ObjCMethodDecl *Method,
+ bool IsInstance) {
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
+ if (ID == 0) return;
+
+ while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
+ ObjCMethodDecl *SuperMethodDecl =
+ SD->lookupMethod(Method->getSelector(), IsInstance);
+ if (SuperMethodDecl == 0) {
+ ID = SD;
+ continue;
+ }
+ ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+ E = Method->param_end();
+ ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin();
+ for (; ParamI != E; ++ParamI, ++PrevI) {
+ // Number of parameters are the same and is guaranteed by selector match.
+ assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
+ QualType T1 = Context.getCanonicalType((*ParamI)->getType());
+ QualType T2 = Context.getCanonicalType((*PrevI)->getType());
+ // If type of arguement of method in this class does not match its
+ // respective argument type in the super class method, issue warning;
+ if (!Context.typesAreCompatible(T1, T2)) {
+ Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
+ << T1 << T2;
+ Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration);
+ return;
+ }
+ }
+ ID = SD;
+ }
+}
+
+/// DiagnoseDuplicateIvars -
+/// Check for duplicate ivars in the entire class at the start of
+/// @implementation. This becomes necesssary because class extension can
+/// add ivars to a class in random order which will not be known until
+/// class's @implementation is seen.
+void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
+ ObjCInterfaceDecl *SID) {
+ for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
+ IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
+ ObjCIvarDecl* Ivar = (*IVI);
+ if (Ivar->isInvalidDecl())
+ continue;
+ if (IdentifierInfo *II = Ivar->getIdentifier()) {
+ ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II);
+ if (prevIvar) {
+ Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
+ Diag(prevIvar->getLocation(), diag::note_previous_declaration);
+ Ivar->setInvalidDecl();
+ }
+ }
+ }
+}
+
+// Note: For class/category implemenations, allMethods/allProperties is
+// always null.
+void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
+ Decl *ClassDecl,
+ Decl **allMethods, unsigned allNum,
+ Decl **allProperties, unsigned pNum,
+ DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
+ // FIXME: If we don't have a ClassDecl, we have an error. We should consider
+ // always passing in a decl. If the decl has an error, isInvalidDecl()
+ // should be true.
+ if (!ClassDecl)
+ return;
+
+ bool isInterfaceDeclKind =
+ isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
+ || isa<ObjCProtocolDecl>(ClassDecl);
+ bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
+
+ if (!isInterfaceDeclKind && AtEnd.isInvalid()) {
+ // FIXME: This is wrong. We shouldn't be pretending that there is
+ // an '@end' in the declaration.
+ SourceLocation L = ClassDecl->getLocation();
+ AtEnd.setBegin(L);
+ AtEnd.setEnd(L);
+ Diag(L, diag::warn_missing_atend);
+ }
+
+ // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
+ llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
+ llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
+
+ for (unsigned i = 0; i < allNum; i++ ) {
+ ObjCMethodDecl *Method =
+ cast_or_null<ObjCMethodDecl>(allMethods[i]);
+
+ if (!Method) continue; // Already issued a diagnostic.
+ if (Method->isInstanceMethod()) {
+ /// Check for instance method of the same name with incompatible types
+ const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
+ bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+ : false;
+ if ((isInterfaceDeclKind && PrevMethod && !match)
+ || (checkIdenticalMethods && match)) {
+ Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+ << Method->getDeclName();
+ Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ Method->setInvalidDecl();
+ } else {
+ InsMap[Method->getSelector()] = Method;
+ /// The following allows us to typecheck messages to "id".
+ AddInstanceMethodToGlobalPool(Method);
+ // verify that the instance method conforms to the same definition of
+ // parent methods if it shadows one.
+ CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
+ }
+ } else {
+ /// Check for class method of the same name with incompatible types
+ const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
+ bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
+ : false;
+ if ((isInterfaceDeclKind && PrevMethod && !match)
+ || (checkIdenticalMethods && match)) {
+ Diag(Method->getLocation(), diag::err_duplicate_method_decl)
+ << Method->getDeclName();
+ Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ Method->setInvalidDecl();
+ } else {
+ ClsMap[Method->getSelector()] = Method;
+ /// The following allows us to typecheck messages to "Class".
+ AddFactoryMethodToGlobalPool(Method);
+ // verify that the class method conforms to the same definition of
+ // parent methods if it shadows one.
+ CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
+ }
+ }
+ }
+ if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+ // Compares properties declared in this class to those of its
+ // super class.
+ ComparePropertiesInBaseAndSuper(I);
+ CompareProperties(I, I);
+ } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+ // Categories are used to extend the class by declaring new methods.
+ // By the same token, they are also used to add new properties. No
+ // need to compare the added property to those in the class.
+
+ // Compare protocol properties with those in category
+ CompareProperties(C, C);
+ if (C->IsClassExtension()) {
+ ObjCInterfaceDecl *CCPrimary = C->getClassInterface();
+ DiagnoseClassExtensionDupMethods(C, CCPrimary);
+ }
+ }
+ if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
+ if (CDecl->getIdentifier())
+ // ProcessPropertyDecl is responsible for diagnosing conflicts with any
+ // user-defined setter/getter. It also synthesizes setter/getter methods
+ // and adds them to the DeclContext and global method pools.
+ for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
+ E = CDecl->prop_end();
+ I != E; ++I)
+ ProcessPropertyDecl(*I, CDecl);
+ CDecl->setAtEndRange(AtEnd);
+ }
+ if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
+ IC->setAtEndRange(AtEnd);
+ if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
+ // Any property declared in a class extension might have user
+ // declared setter or getter in current class extension or one
+ // of the other class extensions. Mark them as synthesized as
+ // property will be synthesized when property with same name is
+ // seen in the @implementation.
+ for (const ObjCCategoryDecl *ClsExtDecl =
+ IDecl->getFirstClassExtension();
+ ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+ for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(),
+ E = ClsExtDecl->prop_end(); I != E; ++I) {
+ ObjCPropertyDecl *Property = (*I);
+ // Skip over properties declared @dynamic
+ if (const ObjCPropertyImplDecl *PIDecl
+ = IC->FindPropertyImplDecl(Property->getIdentifier()))
+ if (PIDecl->getPropertyImplementation()
+ == ObjCPropertyImplDecl::Dynamic)
+ continue;
+
+ for (const ObjCCategoryDecl *CExtDecl =
+ IDecl->getFirstClassExtension();
+ CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) {
+ if (ObjCMethodDecl *GetterMethod =
+ CExtDecl->getInstanceMethod(Property->getGetterName()))
+ GetterMethod->setSynthesized(true);
+ if (!Property->isReadOnly())
+ if (ObjCMethodDecl *SetterMethod =
+ CExtDecl->getInstanceMethod(Property->getSetterName()))
+ SetterMethod->setSynthesized(true);
+ }
+ }
+ }
+
+ if (LangOpts.ObjCDefaultSynthProperties &&
+ LangOpts.ObjCNonFragileABI2)
+ DefaultSynthesizeProperties(S, IC, IDecl);
+ ImplMethodsVsClassMethods(S, IC, IDecl);
+ AtomicPropertySetterGetterRules(IC, IDecl);
+
+ if (LangOpts.ObjCNonFragileABI2)
+ while (IDecl->getSuperClass()) {
+ DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
+ IDecl = IDecl->getSuperClass();
+ }
+ }
+ SetIvarInitializers(IC);
+ } else if (ObjCCategoryImplDecl* CatImplClass =
+ dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
+ CatImplClass->setAtEndRange(AtEnd);
+
+ // Find category interface decl and then check that all methods declared
+ // in this interface are implemented in the category @implementation.
+ if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {
+ for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
+ Categories; Categories = Categories->getNextClassCategory()) {
+ if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
+ ImplMethodsVsClassMethods(S, CatImplClass, Categories);
+ break;
+ }
+ }
+ }
+ }
+ if (isInterfaceDeclKind) {
+ // Reject invalid vardecls.
+ for (unsigned i = 0; i != tuvNum; i++) {
+ DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>();
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
+ if (!VDecl->hasExternalStorage())
+ Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);
+ }
+ }
+ }
+}
+
+
+/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
+/// objective-c's type qualifier from the parser version of the same info.
+static Decl::ObjCDeclQualifier
+CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
+ Decl::ObjCDeclQualifier ret = Decl::OBJC_TQ_None;
+ if (PQTVal & ObjCDeclSpec::DQ_In)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_In);
+ if (PQTVal & ObjCDeclSpec::DQ_Inout)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Inout);
+ if (PQTVal & ObjCDeclSpec::DQ_Out)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Out);
+ if (PQTVal & ObjCDeclSpec::DQ_Bycopy)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Bycopy);
+ if (PQTVal & ObjCDeclSpec::DQ_Byref)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Byref);
+ if (PQTVal & ObjCDeclSpec::DQ_Oneway)
+ ret = (Decl::ObjCDeclQualifier)(ret | Decl::OBJC_TQ_Oneway);
+
+ return ret;
+}
+
+static inline
+bool containsInvalidMethodImplAttribute(const AttrVec &A) {
+ // The 'ibaction' attribute is allowed on method definitions because of
+ // how the IBAction macro is used on both method declarations and definitions.
+ // If the method definitions contains any other attributes, return true.
+ for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
+ if ((*i)->getKind() != attr::IBAction)
+ return true;
+ return false;
+}
+
+Decl *Sema::ActOnMethodDeclaration(
+ Scope *S,
+ SourceLocation MethodLoc, SourceLocation EndLoc,
+ tok::TokenKind MethodType, Decl *ClassDecl,
+ ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ Selector Sel,
+ // optional arguments. The number of types/arguments is obtained
+ // from the Sel.getNumArgs().
+ ObjCArgInfo *ArgInfo,
+ DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
+ AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
+ bool isVariadic) {
+ // Make sure we can establish a context for the method.
+ if (!ClassDecl) {
+ Diag(MethodLoc, diag::error_missing_method_context);
+ return 0;
+ }
+ QualType resultDeclType;
+
+ TypeSourceInfo *ResultTInfo = 0;
+ if (ReturnType) {
+ resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo);
+
+ // Methods cannot return interface types. All ObjC objects are
+ // passed by reference.
+ if (resultDeclType->isObjCObjectType()) {
+ Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
+ << 0 << resultDeclType;
+ return 0;
+ }
+ } else // get the type for "id".
+ resultDeclType = Context.getObjCIdType();
+
+ ObjCMethodDecl* ObjCMethod =
+ ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType,
+ ResultTInfo,
+ cast<DeclContext>(ClassDecl),
+ MethodType == tok::minus, isVariadic,
+ false, false,
+ MethodDeclKind == tok::objc_optional ?
+ ObjCMethodDecl::Optional :
+ ObjCMethodDecl::Required);
+
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+
+ for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {
+ QualType ArgType;
+ TypeSourceInfo *DI;
+
+ if (ArgInfo[i].Type == 0) {
+ ArgType = Context.getObjCIdType();
+ DI = 0;
+ } else {
+ ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI);
+ // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
+ ArgType = adjustParameterType(ArgType);
+ }
+
+ LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
+ LookupOrdinaryName, ForRedeclaration);
+ LookupName(R, S);
+ if (R.isSingleResult()) {
+ NamedDecl *PrevDecl = R.getFoundDecl();
+ if (S->isDeclScope(PrevDecl)) {
+ // FIXME. This should be an error; but will break projects.
+ Diag(ArgInfo[i].NameLoc, diag::warn_method_param_redefinition)
+ << ArgInfo[i].Name;
+ Diag(PrevDecl->getLocation(),
+ diag::note_previous_declaration);
+ }
+ }
+
+ ParmVarDecl* Param
+ = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
+ ArgInfo[i].Name, ArgType, DI,
+ SC_None, SC_None, 0);
+
+ if (ArgType->isObjCObjectType()) {
+ Diag(ArgInfo[i].NameLoc,
+ diag::err_object_cannot_be_passed_returned_by_value)
+ << 1 << ArgType;
+ Param->setInvalidDecl();
+ }
+
+ Param->setObjCDeclQualifier(
+ CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
+
+ // Apply the attributes to the parameter.
+ ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
+
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
+
+ Params.push_back(Param);
+ }
+
+ for (unsigned i = 0, e = CNumArgs; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);
+ QualType ArgType = Param->getType();
+ if (ArgType.isNull())
+ ArgType = Context.getObjCIdType();
+ else
+ // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
+ ArgType = adjustParameterType(ArgType);
+ if (ArgType->isObjCObjectType()) {
+ Diag(Param->getLocation(),
+ diag::err_object_cannot_be_passed_returned_by_value)
+ << 1 << ArgType;
+ Param->setInvalidDecl();
+ }
+ Param->setDeclContext(ObjCMethod);
+
+ Params.push_back(Param);
+ }
+
+ ObjCMethod->setMethodParams(Context, Params.data(), Params.size(),
+ Sel.getNumArgs());
+ ObjCMethod->setObjCDeclQualifier(
+ CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));
+ const ObjCMethodDecl *PrevMethod = 0;
+
+ if (AttrList)
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
+
+ const ObjCMethodDecl *InterfaceMD = 0;
+
+ // Add the method now.
+ if (ObjCImplementationDecl *ImpDecl =
+ dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
+ if (MethodType == tok::minus) {
+ PrevMethod = ImpDecl->getInstanceMethod(Sel);
+ ImpDecl->addInstanceMethod(ObjCMethod);
+ } else {
+ PrevMethod = ImpDecl->getClassMethod(Sel);
+ ImpDecl->addClassMethod(ObjCMethod);
+ }
+ InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
+ MethodType == tok::minus);
+ if (ObjCMethod->hasAttrs() &&
+ containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
+ Diag(EndLoc, diag::warn_attribute_method_def);
+ } else if (ObjCCategoryImplDecl *CatImpDecl =
+ dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
+ if (MethodType == tok::minus) {
+ PrevMethod = CatImpDecl->getInstanceMethod(Sel);
+ CatImpDecl->addInstanceMethod(ObjCMethod);
+ } else {
+ PrevMethod = CatImpDecl->getClassMethod(Sel);
+ CatImpDecl->addClassMethod(ObjCMethod);
+ }
+ if (ObjCMethod->hasAttrs() &&
+ containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
+ Diag(EndLoc, diag::warn_attribute_method_def);
+ } else {
+ cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
+ }
+ if (PrevMethod) {
+ // You can never have two method definitions with the same name.
+ Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
+ << ObjCMethod->getDeclName();
+ Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
+ }
+
+ // If the interface declared this method, and it was deprecated there,
+ // mark it deprecated here.
+ if (InterfaceMD)
+ if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
+ StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
+ ObjCMethod->addAttr(::new (Context)
+ DeprecatedAttr(DA->getLocation(),
+ Context,
+ SE->getString()));
+ }
+
+ return ObjCMethod;
+}
+
+bool Sema::CheckObjCDeclScope(Decl *D) {
+ if (isa<TranslationUnitDecl>(CurContext->getRedeclContext()))
+ return false;
+
+ Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
+ D->setInvalidDecl();
+
+ return true;
+}
+
+/// Called whenever @defs(ClassName) is encountered in the source. Inserts the
+/// instance variables of ClassName into Decls.
+void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ llvm::SmallVectorImpl<Decl*> &Decls) {
+ // Check that ClassName is a valid class
+ ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);
+ if (!Class) {
+ Diag(DeclStart, diag::err_undef_interface) << ClassName;
+ return;
+ }
+ if (LangOpts.ObjCNonFragileABI) {
+ Diag(DeclStart, diag::err_atdef_nonfragile_interface);
+ return;
+ }
+
+ // Collect the instance variables
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ Context.DeepCollectObjCIvars(Class, true, Ivars);
+ // For each ivar, create a fresh ObjCAtDefsFieldDecl.
+ for (unsigned i = 0; i < Ivars.size(); i++) {
+ FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
+ RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
+ Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(),
+ ID->getIdentifier(), ID->getType(),
+ ID->getBitWidth());
+ Decls.push_back(FD);
+ }
+
+ // Introduce all of these fields into the appropriate scope.
+ for (llvm::SmallVectorImpl<Decl*>::iterator D = Decls.begin();
+ D != Decls.end(); ++D) {
+ FieldDecl *FD = cast<FieldDecl>(*D);
+ if (getLangOptions().CPlusPlus)
+ PushOnScopeChains(cast<FieldDecl>(FD), S);
+ else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
+ Record->addDecl(FD);
+ }
+}
+
+/// \brief Build a type-check a new Objective-C exception variable declaration.
+VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
+ QualType T,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool Invalid) {
+ // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
+ // duration shall not be qualified by an address-space qualifier."
+ // Since all parameters have automatic store duration, they can not have
+ // an address space.
+ if (T.getAddressSpace() != 0) {
+ Diag(NameLoc, diag::err_arg_with_address_space);
+ Invalid = true;
+ }
+
+ // An @catch parameter must be an unqualified object pointer type;
+ // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
+ if (Invalid) {
+ // Don't do any further checking.
+ } else if (T->isDependentType()) {
+ // Okay: we don't know what this type will instantiate to.
+ } else if (!T->isObjCObjectPointerType()) {
+ Invalid = true;
+ Diag(NameLoc ,diag::err_catch_param_not_objc_type);
+ } else if (T->isObjCQualifiedIdType()) {
+ Invalid = true;
+ Diag(NameLoc, diag::err_illegal_qualifiers_on_catch_parm);
+ }
+
+ VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo,
+ SC_None, SC_None);
+ New->setExceptionVariable(true);
+
+ if (Invalid)
+ New->setInvalidDecl();
+ return New;
+}
+
+Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
+ const DeclSpec &DS = D.getDeclSpec();
+
+ // We allow the "register" storage class on exception variables because
+ // GCC did, but we drop it completely. Any other storage class is an error.
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
+ Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)
+ << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));
+ } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
+ Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)
+ << DS.getStorageClassSpec();
+ }
+ if (D.getDeclSpec().isThreadSpecified())
+ Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+ D.getMutableDeclSpec().ClearStorageClassSpecs();
+
+ DiagnoseFunctionSpecifiers(D);
+
+ // Check that there are no default arguments inside the type of this
+ // exception object (C++ only).
+ if (getLangOptions().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
+ TagDecl *OwnedDecl = 0;
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl);
+ QualType ExceptionType = TInfo->getType();
+
+ if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
+ // Objective-C++: Types shall not be defined in exception types.
+ Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type)
+ << Context.getTypeDeclType(OwnedDecl);
+ }
+
+ VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, D.getIdentifier(),
+ D.getIdentifierLoc(),
+ D.isInvalidType());
+
+ // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
+ if (D.getCXXScopeSpec().isSet()) {
+ Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)
+ << D.getCXXScopeSpec().getRange();
+ New->setInvalidDecl();
+ }
+
+ // Add the parameter declaration into this scope.
+ S->AddDecl(New);
+ if (D.getIdentifier())
+ IdResolver.AddDecl(New);
+
+ ProcessDeclAttributes(S, New, D);
+
+ if (New->hasAttr<BlocksAttr>())
+ Diag(New->getLocation(), diag::err_block_on_nonlocal);
+ return New;
+}
+
+/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+/// initialization.
+void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
+ for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar()) {
+ QualType QT = Context.getBaseElementType(Iv->getType());
+ if (QT->isRecordType())
+ Ivars.push_back(Iv);
+ }
+}
+
+void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
+ CXXCtorInitializer ** initializers,
+ unsigned numInitializers) {
+ if (numInitializers > 0) {
+ NumIvarInitializers = numInitializers;
+ CXXCtorInitializer **ivarInitializers =
+ new (C) CXXCtorInitializer*[NumIvarInitializers];
+ memcpy(ivarInitializers, initializers,
+ numInitializers * sizeof(CXXCtorInitializer*));
+ IvarInitializers = ivarInitializers;
+ }
+}
+
+void Sema::DiagnoseUseOfUnimplementedSelectors() {
+ // Warning will be issued only when selector table is
+ // generated (which means there is at lease one implementation
+ // in the TU). This is to match gcc's behavior.
+ if (ReferencedSelectors.empty() ||
+ !Context.AnyObjCImplementation())
+ return;
+ for (llvm::DenseMap<Selector, SourceLocation>::iterator S =
+ ReferencedSelectors.begin(),
+ E = ReferencedSelectors.end(); S != E; ++S) {
+ Selector Sel = (*S).first;
+ if (!LookupImplementedMethodInGlobalPool(Sel))
+ Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
+ }
+ return;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
new file mode 100644
index 0000000..5d7993b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -0,0 +1,522 @@
+//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ exception specification testing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+static const FunctionProtoType *GetUnderlyingFunction(QualType T)
+{
+ if (const PointerType *PtrTy = T->getAs<PointerType>())
+ T = PtrTy->getPointeeType();
+ else if (const ReferenceType *RefTy = T->getAs<ReferenceType>())
+ T = RefTy->getPointeeType();
+ else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
+ T = MPTy->getPointeeType();
+ return T->getAs<FunctionProtoType>();
+}
+
+/// CheckSpecifiedExceptionType - Check if the given type is valid in an
+/// exception specification. Incomplete types, or pointers to incomplete types
+/// other than void are not allowed.
+bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
+
+ // This check (and the similar one below) deals with issue 437, that changes
+ // C++ 9.2p2 this way:
+ // Within the class member-specification, the class is regarded as complete
+ // within function bodies, default arguments, exception-specifications, and
+ // constructor ctor-initializers (including such things in nested classes).
+ if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+ return false;
+
+ // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+ // an incomplete type.
+ if (RequireCompleteType(Range.getBegin(), T,
+ PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range))
+ return true;
+
+ // C++ 15.4p2: A type denoted in an exception-specification shall not denote
+ // an incomplete type a pointer or reference to an incomplete type, other
+ // than (cv) void*.
+ int kind;
+ if (const PointerType* IT = T->getAs<PointerType>()) {
+ T = IT->getPointeeType();
+ kind = 1;
+ } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) {
+ T = IT->getPointeeType();
+ kind = 2;
+ } else
+ return false;
+
+ // Again as before
+ if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
+ return false;
+
+ if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T,
+ PDiag(diag::err_incomplete_in_exception_spec) << kind << Range))
+ return true;
+
+ return false;
+}
+
+/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
+/// to member to a function with an exception specification. This means that
+/// it is invalid to add another level of indirection.
+bool Sema::CheckDistantExceptionSpec(QualType T) {
+ if (const PointerType *PT = T->getAs<PointerType>())
+ T = PT->getPointeeType();
+ else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
+ T = PT->getPointeeType();
+ else
+ return false;
+
+ const FunctionProtoType *FnT = T->getAs<FunctionProtoType>();
+ if (!FnT)
+ return false;
+
+ return FnT->hasExceptionSpec();
+}
+
+bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ bool MissingExceptionSpecification = false;
+ bool MissingEmptyExceptionSpecification = false;
+ if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
+ PDiag(diag::note_previous_declaration),
+ Old->getType()->getAs<FunctionProtoType>(),
+ Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(),
+ New->getLocation(),
+ &MissingExceptionSpecification,
+ &MissingEmptyExceptionSpecification))
+ return false;
+
+ // The failure was something other than an empty exception
+ // specification; return an error.
+ if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
+ return true;
+
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+
+ // The new function declaration is only missing an empty exception
+ // specification "throw()". If the throw() specification came from a
+ // function in a system header that has C linkage, just add an empty
+ // exception specification to the "new" declaration. This is an
+ // egregious workaround for glibc, which adds throw() specifications
+ // to many libc functions as an optimization. Unfortunately, that
+ // optimization isn't permitted by the C++ standard, so we're forced
+ // to work around it here.
+ if (MissingEmptyExceptionSpecification && NewProto &&
+ (Old->getLocation().isInvalid() ||
+ Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
+ Old->isExternC()) {
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ EPI.HasExceptionSpec = true;
+ EPI.HasAnyExceptionSpec = false;
+ EPI.NumExceptions = 0;
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI);
+ New->setType(NewType);
+ return false;
+ }
+
+ if (MissingExceptionSpecification && NewProto) {
+ const FunctionProtoType *OldProto
+ = Old->getType()->getAs<FunctionProtoType>();
+
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ EPI.HasExceptionSpec = OldProto->hasExceptionSpec();
+ EPI.HasAnyExceptionSpec = OldProto->hasAnyExceptionSpec();
+ EPI.NumExceptions = OldProto->getNumExceptions();
+ EPI.Exceptions = OldProto->exception_begin();
+
+ // Update the type of the function with the appropriate exception
+ // specification.
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI);
+ New->setType(NewType);
+
+ // If exceptions are disabled, suppress the warning about missing
+ // exception specifications for new and delete operators.
+ if (!getLangOptions().Exceptions) {
+ switch (New->getDeclName().getCXXOverloadedOperator()) {
+ case OO_New:
+ case OO_Array_New:
+ case OO_Delete:
+ case OO_Array_Delete:
+ if (New->getDeclContext()->isTranslationUnit())
+ return false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Warn about the lack of exception specification.
+ llvm::SmallString<128> ExceptionSpecString;
+ llvm::raw_svector_ostream OS(ExceptionSpecString);
+ OS << "throw(";
+ bool OnFirstException = true;
+ for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
+ EEnd = OldProto->exception_end();
+ E != EEnd;
+ ++E) {
+ if (OnFirstException)
+ OnFirstException = false;
+ else
+ OS << ", ";
+
+ OS << E->getAsString(Context.PrintingPolicy);
+ }
+ OS << ")";
+ OS.flush();
+
+ SourceLocation AfterParenLoc;
+ if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
+ TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
+ if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
+ AfterParenLoc = PP.getLocForEndOfToken(FTLoc->getRParenLoc());
+ }
+
+ if (AfterParenLoc.isInvalid())
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str();
+ else {
+ // FIXME: This will get more complicated with C++0x
+ // late-specified return types.
+ Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ << New << OS.str()
+ << FixItHint::CreateInsertion(AfterParenLoc, " " + OS.str().str());
+ }
+
+ if (!Old->getLocation().isInvalid())
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+
+ return false;
+ }
+
+ Diag(New->getLocation(), diag::err_mismatched_exception_spec);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
+/// exception specifications. Exception specifications are equivalent if
+/// they allow exactly the same set of exception types. It does not matter how
+/// that is achieved. See C++ [except.spec]p2.
+bool Sema::CheckEquivalentExceptionSpec(
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc) {
+ return CheckEquivalentExceptionSpec(
+ PDiag(diag::err_mismatched_exception_spec),
+ PDiag(diag::note_previous_declaration),
+ Old, OldLoc, New, NewLoc);
+}
+
+/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
+/// exception specifications. Exception specifications are equivalent if
+/// they allow exactly the same set of exception types. It does not matter how
+/// that is achieved. See C++ [except.spec]p2.
+bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Old,
+ SourceLocation OldLoc,
+ const FunctionProtoType *New,
+ SourceLocation NewLoc,
+ bool *MissingExceptionSpecification,
+ bool *MissingEmptyExceptionSpecification) {
+ // Just completely ignore this under -fno-exceptions.
+ if (!getLangOptions().Exceptions)
+ return false;
+
+ if (MissingExceptionSpecification)
+ *MissingExceptionSpecification = false;
+
+ if (MissingEmptyExceptionSpecification)
+ *MissingEmptyExceptionSpecification = false;
+
+ bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
+ bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
+ if (getLangOptions().Microsoft) {
+ // Treat throw(whatever) as throw(...) to be compatible with MS headers.
+ if (New->hasExceptionSpec() && New->getNumExceptions() > 0)
+ NewAny = true;
+ if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0)
+ OldAny = true;
+ }
+
+ if (OldAny && NewAny)
+ return false;
+ if (OldAny || NewAny) {
+ if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
+ !New->hasExceptionSpec()) {
+ // The old type has an exception specification of some sort, but
+ // the new type does not.
+ *MissingExceptionSpecification = true;
+
+ if (MissingEmptyExceptionSpecification &&
+ !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0) {
+ // The old type has a throw() exception specification and the
+ // new type has no exception specification, and the caller asked
+ // to handle this itself.
+ *MissingEmptyExceptionSpecification = true;
+ }
+
+ return true;
+ }
+
+ Diag(NewLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(OldLoc, NoteID);
+ return true;
+ }
+
+ bool Success = true;
+ // Both have a definite exception spec. Collect the first set, then compare
+ // to the second.
+ llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
+ for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
+ E = Old->exception_end(); I != E; ++I)
+ OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());
+
+ for (FunctionProtoType::exception_iterator I = New->exception_begin(),
+ E = New->exception_end(); I != E && Success; ++I) {
+ CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
+ if(OldTypes.count(TypePtr))
+ NewTypes.insert(TypePtr);
+ else
+ Success = false;
+ }
+
+ Success = Success && OldTypes.size() == NewTypes.size();
+
+ if (Success) {
+ return false;
+ }
+ Diag(NewLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(OldLoc, NoteID);
+ return true;
+}
+
+/// CheckExceptionSpecSubset - Check whether the second function type's
+/// exception specification is a subset (or equivalent) of the first function
+/// type. This is used by override and pointer assignment checks.
+bool Sema::CheckExceptionSpecSubset(
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Superset, SourceLocation SuperLoc,
+ const FunctionProtoType *Subset, SourceLocation SubLoc) {
+
+ // Just auto-succeed under -fno-exceptions.
+ if (!getLangOptions().Exceptions)
+ return false;
+
+ // FIXME: As usual, we could be more specific in our error messages, but
+ // that better waits until we've got types with source locations.
+
+ if (!SubLoc.isValid())
+ SubLoc = SuperLoc;
+
+ // If superset contains everything, we're done.
+ if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
+ return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+
+ // It does not. If the subset contains everything, we've failed.
+ if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
+ Diag(SubLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+
+ // Neither contains everything. Do a proper comparison.
+ for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
+ SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
+ // Take one type from the subset.
+ QualType CanonicalSubT = Context.getCanonicalType(*SubI);
+ // Unwrap pointers and references so that we can do checks within a class
+ // hierarchy. Don't unwrap member pointers; they don't have hierarchy
+ // conversions on the pointee.
+ bool SubIsPointer = false;
+ if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
+ CanonicalSubT = RefTy->getPointeeType();
+ if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
+ CanonicalSubT = PtrTy->getPointeeType();
+ SubIsPointer = true;
+ }
+ bool SubIsClass = CanonicalSubT->isRecordType();
+ CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+
+ bool Contained = false;
+ // Make sure it's in the superset.
+ for (FunctionProtoType::exception_iterator SuperI =
+ Superset->exception_begin(), SuperE = Superset->exception_end();
+ SuperI != SuperE; ++SuperI) {
+ QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
+ // SubT must be SuperT or derived from it, or pointer or reference to
+ // such types.
+ if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
+ CanonicalSuperT = RefTy->getPointeeType();
+ if (SubIsPointer) {
+ if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
+ CanonicalSuperT = PtrTy->getPointeeType();
+ else {
+ continue;
+ }
+ }
+ CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
+ // If the types are the same, move on to the next type in the subset.
+ if (CanonicalSubT == CanonicalSuperT) {
+ Contained = true;
+ break;
+ }
+
+ // Otherwise we need to check the inheritance.
+ if (!SubIsClass || !CanonicalSuperT->isRecordType())
+ continue;
+
+ Paths.clear();
+ if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+ continue;
+
+ if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
+ continue;
+
+ // Do this check from a context without privileges.
+ switch (CheckBaseClassAccess(SourceLocation(),
+ CanonicalSuperT, CanonicalSubT,
+ Paths.front(),
+ /*Diagnostic*/ 0,
+ /*ForceCheck*/ true,
+ /*ForceUnprivileged*/ true)) {
+ case AR_accessible: break;
+ case AR_inaccessible: continue;
+ case AR_dependent:
+ llvm_unreachable("access check dependent for unprivileged context");
+ break;
+ case AR_delayed:
+ llvm_unreachable("access check delayed in non-declaration");
+ break;
+ }
+
+ Contained = true;
+ break;
+ }
+ if (!Contained) {
+ Diag(SubLoc, DiagID);
+ if (NoteID.getDiagID() != 0)
+ Diag(SuperLoc, NoteID);
+ return true;
+ }
+ }
+ // We've run half the gauntlet.
+ return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+}
+
+static bool CheckSpecForTypesEquivalent(Sema &S,
+ const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
+ QualType Target, SourceLocation TargetLoc,
+ QualType Source, SourceLocation SourceLoc)
+{
+ const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
+ if (!TFunc)
+ return false;
+ const FunctionProtoType *SFunc = GetUnderlyingFunction(Source);
+ if (!SFunc)
+ return false;
+
+ return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc,
+ SFunc, SourceLoc);
+}
+
+/// CheckParamExceptionSpec - Check if the parameter and return types of the
+/// two functions have equivalent exception specs. This is part of the
+/// assignment and override compatibility check. We do not check the parameters
+/// of parameter function pointers recursively, as no sane programmer would
+/// even be able to write such a function type.
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+ const FunctionProtoType *Target, SourceLocation TargetLoc,
+ const FunctionProtoType *Source, SourceLocation SourceLoc)
+{
+ if (CheckSpecForTypesEquivalent(*this,
+ PDiag(diag::err_deep_exception_specs_differ) << 0,
+ PDiag(),
+ Target->getResultType(), TargetLoc,
+ Source->getResultType(), SourceLoc))
+ return true;
+
+ // We shouldn't even be testing this unless the arguments are otherwise
+ // compatible.
+ assert(Target->getNumArgs() == Source->getNumArgs() &&
+ "Functions have different argument counts.");
+ for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) {
+ if (CheckSpecForTypesEquivalent(*this,
+ PDiag(diag::err_deep_exception_specs_differ) << 1,
+ PDiag(),
+ Target->getArgType(i), TargetLoc,
+ Source->getArgType(i), SourceLoc))
+ return true;
+ }
+ return false;
+}
+
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
+ // First we check for applicability.
+ // Target type must be a function, function pointer or function reference.
+ const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
+ if (!ToFunc)
+ return false;
+
+ // SourceType must be a function or function pointer.
+ const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
+ if (!FromFunc)
+ return false;
+
+ // Now we've got the correct types on both sides, check their compatibility.
+ // This means that the source of the conversion can only throw a subset of
+ // the exceptions of the target, and any exception specs on arguments or
+ // return types must be equivalent.
+ return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
+ PDiag(), ToFunc,
+ From->getSourceRange().getBegin(),
+ FromFunc, SourceLocation());
+}
+
+bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old) {
+ return CheckExceptionSpecSubset(PDiag(diag::err_override_exception_spec),
+ PDiag(diag::note_overridden_virtual_function),
+ Old->getType()->getAs<FunctionProtoType>(),
+ Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(),
+ New->getLocation());
+}
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
new file mode 100644
index 0000000..65b57c3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -0,0 +1,9669 @@
+//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Template.h"
+using namespace clang;
+using namespace sema;
+
+
+/// \brief Determine whether the use of this declaration is valid, and
+/// emit any corresponding diagnostics.
+///
+/// This routine diagnoses various problems with referencing
+/// declarations that can occur when using a declaration. For example,
+/// it might warn if a deprecated or unavailable declaration is being
+/// used, or produce an error (and return true) if a C++0x deleted
+/// function is being used.
+///
+/// If IgnoreDeprecated is set to true, this should not warn about deprecated
+/// decls.
+///
+/// \returns true if there was an error (this declaration cannot be
+/// referenced), false otherwise.
+///
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool UnknownObjCClass) {
+ if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
+ // If there were any diagnostics suppressed by template argument deduction,
+ // emit them now.
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+ Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+ if (Pos != SuppressedDiagnostics.end()) {
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
+ for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
+ Diag(Suppressed[I].first, Suppressed[I].second);
+
+ // Clear out the list of suppressed diagnostics, so that we don't emit
+ // them again for this specialization. However, we don't remove this
+ // entry from the table, because we want to avoid ever emitting these
+ // diagnostics again.
+ Suppressed.clear();
+ }
+ }
+
+ // See if this is an auto-typed variable whose initializer we are parsing.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->isParsingAutoInit()) {
+ Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ return true;
+ }
+ }
+
+ // See if the decl is deprecated.
+ if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
+ EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass);
+
+ // See if the decl is unavailable
+ if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
+ if (UA->getMessage().empty()) {
+ if (!UnknownObjCClass)
+ Diag(Loc, diag::err_unavailable) << D->getDeclName();
+ else
+ Diag(Loc, diag::warn_unavailable_fwdclass_message)
+ << D->getDeclName();
+ }
+ else
+ Diag(Loc, diag::err_unavailable_message)
+ << D->getDeclName() << UA->getMessage();
+ Diag(D->getLocation(), diag::note_unavailable_here) << 0;
+ }
+
+ // See if this is a deleted function.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isDeleted()) {
+ Diag(Loc, diag::err_deleted_function_use);
+ Diag(D->getLocation(), diag::note_unavailable_here) << true;
+ return true;
+ }
+ }
+
+ // Warn if this is used but marked unused.
+ if (D->hasAttr<UnusedAttr>())
+ Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
+
+ return false;
+}
+
+/// DiagnoseSentinelCalls - This routine checks on method dispatch calls
+/// (and other functions in future), which have been declared with sentinel
+/// attribute. It warns if call does not have the sentinel argument.
+///
+void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+ Expr **Args, unsigned NumArgs) {
+ const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+ if (!attr)
+ return;
+
+ // FIXME: In C++0x, if any of the arguments are parameter pack
+ // expansions, we can't check for the sentinel now.
+ int sentinelPos = attr->getSentinel();
+ int nullPos = attr->getNullPos();
+
+ // FIXME. ObjCMethodDecl and FunctionDecl need be derived from the same common
+ // base class. Then we won't be needing two versions of the same code.
+ unsigned int i = 0;
+ bool warnNotEnoughArgs = false;
+ int isMethod = 0;
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ // skip over named parameters.
+ ObjCMethodDecl::param_iterator P, E = MD->param_end();
+ for (P = MD->param_begin(); (P != E && i < NumArgs); ++P) {
+ if (nullPos)
+ --nullPos;
+ else
+ ++i;
+ }
+ warnNotEnoughArgs = (P != E || i >= NumArgs);
+ isMethod = 1;
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // skip over named parameters.
+ ObjCMethodDecl::param_iterator P, E = FD->param_end();
+ for (P = FD->param_begin(); (P != E && i < NumArgs); ++P) {
+ if (nullPos)
+ --nullPos;
+ else
+ ++i;
+ }
+ warnNotEnoughArgs = (P != E || i >= NumArgs);
+ } else if (VarDecl *V = dyn_cast<VarDecl>(D)) {
+ // block or function pointer call.
+ QualType Ty = V->getType();
+ if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
+ const FunctionType *FT = Ty->isFunctionPointerType()
+ ? Ty->getAs<PointerType>()->getPointeeType()->getAs<FunctionType>()
+ : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) {
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned k;
+ for (k = 0; (k != NumArgsInProto && i < NumArgs); k++) {
+ if (nullPos)
+ --nullPos;
+ else
+ ++i;
+ }
+ warnNotEnoughArgs = (k != NumArgsInProto || i >= NumArgs);
+ }
+ if (Ty->isBlockPointerType())
+ isMethod = 2;
+ } else
+ return;
+ } else
+ return;
+
+ if (warnNotEnoughArgs) {
+ Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+ Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+ return;
+ }
+ int sentinel = i;
+ while (sentinelPos > 0 && i < NumArgs-1) {
+ --sentinelPos;
+ ++i;
+ }
+ if (sentinelPos > 0) {
+ Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+ Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+ return;
+ }
+ while (i < NumArgs-1) {
+ ++i;
+ ++sentinel;
+ }
+ Expr *sentinelExpr = Args[sentinel];
+ if (!sentinelExpr) return;
+ if (sentinelExpr->isTypeDependent()) return;
+ if (sentinelExpr->isValueDependent()) return;
+
+ // nullptr_t is always treated as null.
+ if (sentinelExpr->getType()->isNullPtrType()) return;
+
+ if (sentinelExpr->getType()->isAnyPointerType() &&
+ sentinelExpr->IgnoreParenCasts()->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull))
+ return;
+
+ // Unfortunately, __null has type 'int'.
+ if (isa<GNUNullExpr>(sentinelExpr)) return;
+
+ Diag(Loc, diag::warn_missing_sentinel) << isMethod;
+ Diag(D->getLocation(), diag::note_sentinel_here) << isMethod;
+}
+
+SourceRange Sema::getExprRange(ExprTy *E) const {
+ Expr *Ex = (Expr *)E;
+ return Ex? Ex->getSourceRange() : SourceRange();
+}
+
+//===----------------------------------------------------------------------===//
+// Standard Promotions and Conversions
+//===----------------------------------------------------------------------===//
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+void Sema::DefaultFunctionArrayConversion(Expr *&E) {
+ QualType Ty = E->getType();
+ assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
+
+ if (Ty->isFunctionType())
+ ImpCastExprToType(E, Context.getPointerType(Ty),
+ CK_FunctionToPointerDecay);
+ else if (Ty->isArrayType()) {
+ // In C90 mode, arrays only promote to pointers if the array expression is
+ // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
+ // type 'array of type' is converted to an expression that has type 'pointer
+ // to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression
+ // that has type 'array of type' ...". The relevant change is "an lvalue"
+ // (C90) to "an expression" (C99).
+ //
+ // C++ 4.2p1:
+ // An lvalue or rvalue of type "array of N T" or "array of unknown bound of
+ // T" can be converted to an rvalue of type "pointer to T".
+ //
+ if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue())
+ ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
+ CK_ArrayToPointerDecay);
+ }
+}
+
+void Sema::DefaultLvalueConversion(Expr *&E) {
+ // C++ [conv.lval]p1:
+ // A glvalue of a non-function, non-array type T can be
+ // converted to a prvalue.
+ if (!E->isGLValue()) return;
+
+ QualType T = E->getType();
+ assert(!T.isNull() && "r-value conversion on typeless expression?");
+
+ // Create a load out of an ObjCProperty l-value, if necessary.
+ if (E->getObjectKind() == OK_ObjCProperty) {
+ ConvertPropertyForRValue(E);
+ if (!E->isGLValue())
+ return;
+ }
+
+ // We don't want to throw lvalue-to-rvalue casts on top of
+ // expressions of certain types in C++.
+ if (getLangOptions().CPlusPlus &&
+ (E->getType() == Context.OverloadTy ||
+ T->isDependentType() ||
+ T->isRecordType()))
+ return;
+
+ // The C standard is actually really unclear on this point, and
+ // DR106 tells us what the result should be but not why. It's
+ // generally best to say that void types just doesn't undergo
+ // lvalue-to-rvalue at all. Note that expressions of unqualified
+ // 'void' type are never l-values, but qualified void can be.
+ if (T->isVoidType())
+ return;
+
+ // C++ [conv.lval]p1:
+ // [...] If T is a non-class type, the type of the prvalue is the
+ // cv-unqualified version of T. Otherwise, the type of the
+ // rvalue is T.
+ //
+ // C99 6.3.2.1p2:
+ // If the lvalue has qualified type, the value has the unqualified
+ // version of the type of the lvalue; otherwise, the value has the
+ // type of the lvalue.
+ if (T.hasQualifiers())
+ T = T.getUnqualifiedType();
+
+ if (const ArraySubscriptExpr *ae = dyn_cast<ArraySubscriptExpr>(E))
+ CheckArrayAccess(ae);
+
+ E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
+ E, 0, VK_RValue);
+}
+
+void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
+ DefaultFunctionArrayConversion(E);
+ DefaultLvalueConversion(E);
+}
+
+
+/// UsualUnaryConversions - Performs various conversions that are common to most
+/// operators (C99 6.3). The conversions of array and function types are
+/// sometimes surpressed. For example, the array->pointer conversion doesn't
+/// apply if the array is an argument to the sizeof or address (&) operators.
+/// In these instances, this routine should *not* be called.
+Expr *Sema::UsualUnaryConversions(Expr *&E) {
+ // First, convert to an r-value.
+ DefaultFunctionArrayLvalueConversion(E);
+
+ QualType Ty = E->getType();
+ assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
+
+ // Try to perform integral promotions if the object has a theoretically
+ // promotable type.
+ if (Ty->isIntegralOrUnscopedEnumerationType()) {
+ // C99 6.3.1.1p2:
+ //
+ // The following may be used in an expression wherever an int or
+ // unsigned int may be used:
+ // - an object or expression with an integer type whose integer
+ // conversion rank is less than or equal to the rank of int
+ // and unsigned int.
+ // - A bit-field of type _Bool, int, signed int, or unsigned int.
+ //
+ // If an int can represent all values of the original type, the
+ // value is converted to an int; otherwise, it is converted to an
+ // unsigned int. These are called the integer promotions. All
+ // other types are unchanged by the integer promotions.
+
+ QualType PTy = Context.isPromotableBitField(E);
+ if (!PTy.isNull()) {
+ ImpCastExprToType(E, PTy, CK_IntegralCast);
+ return E;
+ }
+ if (Ty->isPromotableIntegerType()) {
+ QualType PT = Context.getPromotedIntegerType(Ty);
+ ImpCastExprToType(E, PT, CK_IntegralCast);
+ return E;
+ }
+ }
+
+ return E;
+}
+
+/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+/// do not have a prototype. Arguments that have type float are promoted to
+/// double. All other argument types are converted by UsualUnaryConversions().
+void Sema::DefaultArgumentPromotion(Expr *&Expr) {
+ QualType Ty = Expr->getType();
+ assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
+
+ UsualUnaryConversions(Expr);
+
+ // If this is a 'float' (CVR qualified or typedef) promote to double.
+ if (Ty->isSpecificBuiltinType(BuiltinType::Float))
+ return ImpCastExprToType(Expr, Context.DoubleTy, CK_FloatingCast);
+}
+
+/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+/// will warn if the resulting type is not a POD type, and rejects ObjC
+/// interfaces passed by value. This returns true if the argument type is
+/// completely illegal.
+bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
+ FunctionDecl *FDecl) {
+ DefaultArgumentPromotion(Expr);
+
+ // __builtin_va_start takes the second argument as a "varargs" argument, but
+ // it doesn't actually do anything with it. It doesn't need to be non-pod
+ // etc.
+ if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start)
+ return false;
+
+ if (Expr->getType()->isObjCObjectType() &&
+ DiagRuntimeBehavior(Expr->getLocStart(),
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << Expr->getType() << CT))
+ return true;
+
+ if (!Expr->getType()->isPODType() &&
+ DiagRuntimeBehavior(Expr->getLocStart(),
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << Expr->getType() << CT))
+ return true;
+
+ return false;
+}
+
+/// UsualArithmeticConversions - Performs various conversions that are common to
+/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+/// routine returns the first non-arithmetic type found. The client is
+/// responsible for emitting appropriate error diagnostics.
+/// FIXME: verify the conversion rules for "complex int" are consistent with
+/// GCC.
+QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
+ bool isCompAssign) {
+ if (!isCompAssign)
+ UsualUnaryConversions(lhsExpr);
+
+ UsualUnaryConversions(rhsExpr);
+
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType lhs =
+ Context.getCanonicalType(lhsExpr->getType()).getUnqualifiedType();
+ QualType rhs =
+ Context.getCanonicalType(rhsExpr->getType()).getUnqualifiedType();
+
+ // If both types are identical, no conversion is needed.
+ if (lhs == rhs)
+ return lhs;
+
+ // 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;
+
+ // Apply unary and bitfield promotions to the LHS's type.
+ QualType lhs_unpromoted = lhs;
+ if (lhs->isPromotableIntegerType())
+ lhs = Context.getPromotedIntegerType(lhs);
+ QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr);
+ if (!LHSBitfieldPromoteTy.isNull())
+ lhs = LHSBitfieldPromoteTy;
+ if (lhs != lhs_unpromoted && !isCompAssign)
+ ImpCastExprToType(lhsExpr, lhs, CK_IntegralCast);
+
+ // If both types are identical, no conversion is needed.
+ if (lhs == rhs)
+ return lhs;
+
+ // At this point, we have two different arithmetic types.
+
+ // Handle complex types first (C99 6.3.1.8p1).
+ bool LHSComplexFloat = lhs->isComplexType();
+ bool RHSComplexFloat = rhs->isComplexType();
+ if (LHSComplexFloat || RHSComplexFloat) {
+ // if we have an integer operand, the result is the complex type.
+
+ if (!RHSComplexFloat && !rhs->isRealFloatingType()) {
+ if (rhs->isIntegerType()) {
+ QualType fp = cast<ComplexType>(lhs)->getElementType();
+ ImpCastExprToType(rhsExpr, fp, CK_IntegralToFloating);
+ ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
+ } else {
+ assert(rhs->isComplexIntegerType());
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex);
+ }
+ return lhs;
+ }
+
+ if (!LHSComplexFloat && !lhs->isRealFloatingType()) {
+ if (!isCompAssign) {
+ // int -> float -> _Complex float
+ if (lhs->isIntegerType()) {
+ QualType fp = cast<ComplexType>(rhs)->getElementType();
+ ImpCastExprToType(lhsExpr, fp, CK_IntegralToFloating);
+ ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+ } else {
+ assert(lhs->isComplexIntegerType());
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex);
+ }
+ }
+ 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 order = Context.getFloatingTypeOrder(lhs, rhs);
+
+ // If both are complex, just cast to the more precise type.
+ if (LHSComplexFloat && RHSComplexFloat) {
+ if (order > 0) {
+ // _Complex float -> _Complex double
+ ImpCastExprToType(rhsExpr, lhs, CK_FloatingComplexCast);
+ return lhs;
+
+ } else if (order < 0) {
+ // _Complex float -> _Complex double
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_FloatingComplexCast);
+ return rhs;
+ }
+ return lhs;
+ }
+
+ // If just the LHS is complex, the RHS needs to be converted,
+ // and the LHS might need to be promoted.
+ if (LHSComplexFloat) {
+ if (order > 0) { // LHS is wider
+ // float -> _Complex double
+ QualType fp = cast<ComplexType>(lhs)->getElementType();
+ ImpCastExprToType(rhsExpr, fp, CK_FloatingCast);
+ ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);
+ return lhs;
+ }
+
+ // RHS is at least as wide. Find its corresponding complex type.
+ QualType result = (order == 0 ? lhs : Context.getComplexType(rhs));
+
+ // double -> _Complex double
+ ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
+
+ // _Complex float -> _Complex double
+ if (!isCompAssign && order < 0)
+ ImpCastExprToType(lhsExpr, result, CK_FloatingComplexCast);
+
+ return result;
+ }
+
+ // Just the RHS is complex, so the LHS needs to be converted
+ // and the RHS might need to be promoted.
+ assert(RHSComplexFloat);
+
+ if (order < 0) { // RHS is wider
+ // float -> _Complex double
+ if (!isCompAssign) {
+ QualType fp = cast<ComplexType>(rhs)->getElementType();
+ ImpCastExprToType(lhsExpr, fp, CK_FloatingCast);
+ ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);
+ }
+ return rhs;
+ }
+
+ // LHS is at least as wide. Find its corresponding complex type.
+ QualType result = (order == 0 ? rhs : Context.getComplexType(lhs));
+
+ // double -> _Complex double
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
+
+ // _Complex float -> _Complex double
+ if (order > 0)
+ ImpCastExprToType(rhsExpr, result, CK_FloatingComplexCast);
+
+ return result;
+ }
+
+ // Now handle "real" floating types (i.e. float, double, long double).
+ bool LHSFloat = lhs->isRealFloatingType();
+ bool RHSFloat = rhs->isRealFloatingType();
+ if (LHSFloat || RHSFloat) {
+ // If we have two real floating types, convert the smaller operand
+ // to the bigger result.
+ if (LHSFloat && RHSFloat) {
+ int order = Context.getFloatingTypeOrder(lhs, rhs);
+ if (order > 0) {
+ ImpCastExprToType(rhsExpr, lhs, CK_FloatingCast);
+ return lhs;
+ }
+
+ assert(order < 0 && "illegal float comparison");
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_FloatingCast);
+ return rhs;
+ }
+
+ // If we have an integer operand, the result is the real floating type.
+ if (LHSFloat) {
+ if (rhs->isIntegerType()) {
+ // Convert rhs to the lhs floating point type.
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloating);
+ return lhs;
+ }
+
+ // Convert both sides to the appropriate complex float.
+ assert(rhs->isComplexIntegerType());
+ QualType result = Context.getComplexType(lhs);
+
+ // _Complex int -> _Complex float
+ ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex);
+
+ // float -> _Complex float
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_FloatingRealToComplex);
+
+ return result;
+ }
+
+ assert(RHSFloat);
+ if (lhs->isIntegerType()) {
+ // Convert lhs to the rhs floating point type.
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloating);
+ return rhs;
+ }
+
+ // Convert both sides to the appropriate complex float.
+ assert(lhs->isComplexIntegerType());
+ QualType result = Context.getComplexType(rhs);
+
+ // _Complex int -> _Complex float
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex);
+
+ // float -> _Complex float
+ ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex);
+
+ return result;
+ }
+
+ // Handle GCC complex int extension.
+ // FIXME: if the operands are (int, _Complex long), we currently
+ // don't promote the complex. Also, signedness?
+ const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType();
+ const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType();
+ if (lhsComplexInt && rhsComplexInt) {
+ int order = Context.getIntegerTypeOrder(lhsComplexInt->getElementType(),
+ rhsComplexInt->getElementType());
+ assert(order && "inequal types with equal element ordering");
+ if (order > 0) {
+ // _Complex int -> _Complex long
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexCast);
+ return lhs;
+ }
+
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexCast);
+ return rhs;
+ } else if (lhsComplexInt) {
+ // int -> _Complex int
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralRealToComplex);
+ return lhs;
+ } else if (rhsComplexInt) {
+ // int -> _Complex int
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralRealToComplex);
+ return rhs;
+ }
+
+ // Finally, we have two differing integer types.
+ // The rules for this case are in C99 6.3.1.8
+ int compare = Context.getIntegerTypeOrder(lhs, rhs);
+ bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
+ rhsSigned = rhs->hasSignedIntegerRepresentation();
+ if (lhsSigned == rhsSigned) {
+ // Same signedness; use the higher-ranked type
+ if (compare >= 0) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return 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
+ if (rhsSigned) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return rhs;
+ } else if (Context.getIntWidth(lhs) != Context.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.
+ if (lhsSigned) {
+ ImpCastExprToType(rhsExpr, lhs, CK_IntegralCast);
+ return lhs;
+ } else if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, rhs, CK_IntegralCast);
+ return 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.
+ QualType result =
+ Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs);
+ ImpCastExprToType(rhsExpr, result, CK_IntegralCast);
+ if (!isCompAssign)
+ ImpCastExprToType(lhsExpr, result, CK_IntegralCast);
+ return result;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Semantic Analysis for various Expression Types
+//===----------------------------------------------------------------------===//
+
+
+/// ActOnStringLiteral - The specified tokens were lexed as pasted string
+/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
+/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
+/// multiple tokens. However, the common case is that StringToks points to one
+/// string.
+///
+ExprResult
+Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
+ assert(NumStringToks && "Must have at least one string!");
+
+ StringLiteralParser Literal(StringToks, NumStringToks, PP);
+ if (Literal.hadError)
+ return ExprError();
+
+ llvm::SmallVector<SourceLocation, 4> StringTokLocs;
+ for (unsigned i = 0; i != NumStringToks; ++i)
+ StringTokLocs.push_back(StringToks[i].getLocation());
+
+ QualType StrTy = Context.CharTy;
+ if (Literal.AnyWide) StrTy = Context.getWCharType();
+ if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
+
+ // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+ if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings)
+ StrTy.addConst();
+
+ // Get an array type for the string, according to C99 6.4.5. This includes
+ // the nul terminator character as well as the string length for pascal
+ // strings.
+ StrTy = Context.getConstantArrayType(StrTy,
+ llvm::APInt(32, Literal.GetNumStringChars()+1),
+ ArrayType::Normal, 0);
+
+ // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
+ return Owned(StringLiteral::Create(Context, Literal.GetString(),
+ Literal.GetStringLength(),
+ Literal.AnyWide, StrTy,
+ &StringTokLocs[0],
+ StringTokLocs.size()));
+}
+
+enum CaptureResult {
+ /// No capture is required.
+ CR_NoCapture,
+
+ /// A capture is required.
+ CR_Capture,
+
+ /// A by-ref capture is required.
+ CR_CaptureByRef,
+
+ /// An error occurred when trying to capture the given variable.
+ CR_Error
+};
+
+/// Diagnose an uncapturable value reference.
+///
+/// \param var - the variable referenced
+/// \param DC - the context which we couldn't capture through
+static CaptureResult
+diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
+ VarDecl *var, DeclContext *DC) {
+ switch (S.ExprEvalContexts.back().Context) {
+ case Sema::Unevaluated:
+ // The argument will never be evaluated, so don't complain.
+ return CR_NoCapture;
+
+ case Sema::PotentiallyEvaluated:
+ case Sema::PotentiallyEvaluatedIfUsed:
+ break;
+
+ case Sema::PotentiallyPotentiallyEvaluated:
+ // FIXME: delay these!
+ break;
+ }
+
+ // Don't diagnose about capture if we're not actually in code right
+ // now; in general, there are more appropriate places that will
+ // diagnose this.
+ if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture;
+
+ // This particular madness can happen in ill-formed default
+ // arguments; claim it's okay and let downstream code handle it.
+ if (isa<ParmVarDecl>(var) &&
+ S.CurContext == var->getDeclContext()->getParent())
+ return CR_NoCapture;
+
+ DeclarationName functionName;
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext()))
+ functionName = fn->getDeclName();
+ // FIXME: variable from enclosing block that we couldn't capture from!
+
+ S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function)
+ << var->getIdentifier() << functionName;
+ S.Diag(var->getLocation(), diag::note_local_variable_declared_here)
+ << var->getIdentifier();
+
+ return CR_Error;
+}
+
+/// There is a well-formed capture at a particular scope level;
+/// propagate it through all the nested blocks.
+static CaptureResult propagateCapture(Sema &S, unsigned validScopeIndex,
+ const BlockDecl::Capture &capture) {
+ VarDecl *var = capture.getVariable();
+
+ // Update all the inner blocks with the capture information.
+ for (unsigned i = validScopeIndex + 1, e = S.FunctionScopes.size();
+ i != e; ++i) {
+ BlockScopeInfo *innerBlock = cast<BlockScopeInfo>(S.FunctionScopes[i]);
+ innerBlock->Captures.push_back(
+ BlockDecl::Capture(capture.getVariable(), capture.isByRef(),
+ /*nested*/ true, capture.getCopyExpr()));
+ innerBlock->CaptureMap[var] = innerBlock->Captures.size(); // +1
+ }
+
+ return capture.isByRef() ? CR_CaptureByRef : CR_Capture;
+}
+
+/// shouldCaptureValueReference - Determine if a reference to the
+/// given value in the current context requires a variable capture.
+///
+/// This also keeps the captures set in the BlockScopeInfo records
+/// up-to-date.
+static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc,
+ ValueDecl *value) {
+ // Only variables ever require capture.
+ VarDecl *var = dyn_cast<VarDecl>(value);
+ if (!var) return CR_NoCapture;
+
+ // Fast path: variables from the current context never require capture.
+ DeclContext *DC = S.CurContext;
+ if (var->getDeclContext() == DC) return CR_NoCapture;
+
+ // Only variables with local storage require capture.
+ // FIXME: What about 'const' variables in C++?
+ if (!var->hasLocalStorage()) return CR_NoCapture;
+
+ // Otherwise, we need to capture.
+
+ unsigned functionScopesIndex = S.FunctionScopes.size() - 1;
+ do {
+ // Only blocks (and eventually C++0x closures) can capture; other
+ // scopes don't work.
+ if (!isa<BlockDecl>(DC))
+ return diagnoseUncapturableValueReference(S, loc, var, DC);
+
+ BlockScopeInfo *blockScope =
+ cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]);
+ assert(blockScope->TheDecl == static_cast<BlockDecl*>(DC));
+
+ // Check whether we've already captured it in this block. If so,
+ // we're done.
+ if (unsigned indexPlus1 = blockScope->CaptureMap[var])
+ return propagateCapture(S, functionScopesIndex,
+ blockScope->Captures[indexPlus1 - 1]);
+
+ functionScopesIndex--;
+ DC = cast<BlockDecl>(DC)->getDeclContext();
+ } while (var->getDeclContext() != DC);
+
+ // Okay, we descended all the way to the block that defines the variable.
+ // Actually try to capture it.
+ QualType type = var->getType();
+
+ // Prohibit variably-modified types.
+ if (type->isVariablyModifiedType()) {
+ S.Diag(loc, diag::err_ref_vm_type);
+ S.Diag(var->getLocation(), diag::note_declared_at);
+ return CR_Error;
+ }
+
+ // Prohibit arrays, even in __block variables, but not references to
+ // them.
+ if (type->isArrayType()) {
+ S.Diag(loc, diag::err_ref_array_type);
+ S.Diag(var->getLocation(), diag::note_declared_at);
+ return CR_Error;
+ }
+
+ S.MarkDeclarationReferenced(loc, var);
+
+ // The BlocksAttr indicates the variable is bound by-reference.
+ bool byRef = var->hasAttr<BlocksAttr>();
+
+ // Build a copy expression.
+ Expr *copyExpr = 0;
+ if (!byRef && S.getLangOptions().CPlusPlus &&
+ !type->isDependentType() && type->isStructureOrClassType()) {
+ // According to the blocks spec, the capture of a variable from
+ // the stack requires a const copy constructor. This is not true
+ // of the copy/move done to move a __block variable to the heap.
+ type.addConst();
+
+ Expr *declRef = new (S.Context) DeclRefExpr(var, type, VK_LValue, loc);
+ ExprResult result =
+ S.PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(var->getLocation(),
+ type, false),
+ loc, S.Owned(declRef));
+
+ // Build a full-expression copy expression if initialization
+ // succeeded and used a non-trivial constructor. Recover from
+ // errors by pretending that the copy isn't necessary.
+ if (!result.isInvalid() &&
+ !cast<CXXConstructExpr>(result.get())->getConstructor()->isTrivial()) {
+ result = S.MaybeCreateExprWithCleanups(result);
+ copyExpr = result.take();
+ }
+ }
+
+ // We're currently at the declarer; go back to the closure.
+ functionScopesIndex++;
+ BlockScopeInfo *blockScope =
+ cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]);
+
+ // Build a valid capture in this scope.
+ blockScope->Captures.push_back(
+ BlockDecl::Capture(var, byRef, /*nested*/ false, copyExpr));
+ blockScope->CaptureMap[var] = blockScope->Captures.size(); // +1
+
+ // Propagate that to inner captures if necessary.
+ return propagateCapture(S, functionScopesIndex,
+ blockScope->Captures.back());
+}
+
+static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *vd,
+ const DeclarationNameInfo &NameInfo,
+ bool byRef) {
+ assert(isa<VarDecl>(vd) && "capturing non-variable");
+
+ VarDecl *var = cast<VarDecl>(vd);
+ assert(var->hasLocalStorage() && "capturing non-local");
+ assert(byRef == var->hasAttr<BlocksAttr>() && "byref set wrong");
+
+ QualType exprType = var->getType().getNonReferenceType();
+
+ BlockDeclRefExpr *BDRE;
+ if (!byRef) {
+ // The variable will be bound by copy; make it const within the
+ // closure, but record that this was done in the expression.
+ bool constAdded = !exprType.isConstQualified();
+ exprType.addConst();
+
+ BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue,
+ NameInfo.getLoc(), false,
+ constAdded);
+ } else {
+ BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue,
+ NameInfo.getLoc(), true);
+ }
+
+ return S.Owned(BDRE);
+}
+
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS) {
+ DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
+ return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
+}
+
+/// BuildDeclRefExpr - Build an expression that references a
+/// declaration that does not require a closure capture.
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS) {
+ MarkDeclarationReferenced(NameInfo.getLoc(), D);
+
+ Expr *E = DeclRefExpr::Create(Context,
+ SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
+ SS? SS->getRange() : SourceRange(),
+ D, NameInfo, Ty, VK);
+
+ // Just in case we're building an illegal pointer-to-member.
+ if (isa<FieldDecl>(D) && cast<FieldDecl>(D)->getBitWidth())
+ E->setObjectKind(OK_BitField);
+
+ return Owned(E);
+}
+
+static ExprResult
+BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+ const CXXScopeSpec &SS, FieldDecl *Field,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo);
+
+ExprResult
+Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
+ SourceLocation loc,
+ IndirectFieldDecl *indirectField,
+ Expr *baseObjectExpr,
+ SourceLocation opLoc) {
+ // First, build the expression that refers to the base object.
+
+ bool baseObjectIsPointer = false;
+ Qualifiers baseQuals;
+
+ // Case 1: the base of the indirect field is not a field.
+ VarDecl *baseVariable = indirectField->getVarDecl();
+ CXXScopeSpec EmptySS;
+ if (baseVariable) {
+ assert(baseVariable->getType()->isRecordType());
+
+ // In principle we could have a member access expression that
+ // accesses an anonymous struct/union that's a static member of
+ // the base object's class. However, under the current standard,
+ // static data members cannot be anonymous structs or unions.
+ // Supporting this is as easy as building a MemberExpr here.
+ assert(!baseObjectExpr && "anonymous struct/union is static data member?");
+
+ DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
+
+ ExprResult result =
+ BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
+ if (result.isInvalid()) return ExprError();
+
+ baseObjectExpr = result.take();
+ baseObjectIsPointer = false;
+ baseQuals = baseObjectExpr->getType().getQualifiers();
+
+ // Case 2: the base of the indirect field is a field and the user
+ // wrote a member expression.
+ } else if (baseObjectExpr) {
+ // The caller provided the base object expression. Determine
+ // whether its a pointer and whether it adds any qualifiers to the
+ // anonymous struct/union fields we're looking into.
+ QualType objectType = baseObjectExpr->getType();
+
+ if (const PointerType *ptr = objectType->getAs<PointerType>()) {
+ baseObjectIsPointer = true;
+ objectType = ptr->getPointeeType();
+ } else {
+ baseObjectIsPointer = false;
+ }
+ baseQuals = objectType.getQualifiers();
+
+ // Case 3: the base of the indirect field is a field and we should
+ // build an implicit member access.
+ } else {
+ // We've found a member of an anonymous struct/union that is
+ // inside a non-anonymous struct/union, so in a well-formed
+ // program our base object expression is "this".
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ if (!method) {
+ Diag(loc, diag::err_invalid_member_use_in_static_method)
+ << indirectField->getDeclName();
+ return ExprError();
+ }
+
+ // Our base object expression is "this".
+ baseObjectExpr =
+ new (Context) CXXThisExpr(loc, method->getThisType(Context),
+ /*isImplicit=*/ true);
+ baseObjectIsPointer = true;
+ baseQuals = Qualifiers::fromCVRMask(method->getTypeQualifiers());
+ }
+
+ // Build the implicit member references to the field of the
+ // anonymous struct/union.
+ Expr *result = baseObjectExpr;
+ IndirectFieldDecl::chain_iterator
+ FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
+
+ // Build the first member access in the chain with full information.
+ if (!baseVariable) {
+ FieldDecl *field = cast<FieldDecl>(*FI);
+
+ // FIXME: use the real found-decl info!
+ DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+
+ // Make a nameInfo that properly uses the anonymous name.
+ DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+
+ result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
+ EmptySS, field, foundDecl,
+ memberNameInfo).take();
+ baseObjectIsPointer = false;
+
+ // FIXME: check qualified member access
+ }
+
+ // In all cases, we should now skip the first declaration in the chain.
+ ++FI;
+
+ while (FI != FEnd) {
+ FieldDecl *field = cast<FieldDecl>(*FI++);
+
+ // FIXME: these are somewhat meaningless
+ DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
+ DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+
+ result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
+ (FI == FEnd? SS : EmptySS), field,
+ foundDecl, memberNameInfo)
+ .take();
+ }
+
+ return Owned(result);
+}
+
+/// Decomposes the given name into a DeclarationNameInfo, its location, and
+/// possibly a list of template arguments.
+///
+/// If this produces template arguments, it is permitted to call
+/// DecomposeTemplateName.
+///
+/// This actually loses a lot of source location information for
+/// non-standard name kinds; we should consider preserving that in
+/// some way.
+static void DecomposeUnqualifiedId(Sema &SemaRef,
+ const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs) {
+ if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+ Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
+ Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
+ ASTTemplateArgsPtr TemplateArgsPtr(SemaRef,
+ Id.TemplateId->getTemplateArgs(),
+ Id.TemplateId->NumArgs);
+ SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer);
+ TemplateArgsPtr.release();
+
+ TemplateName TName = Id.TemplateId->Template.get();
+ SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc;
+ NameInfo = SemaRef.Context.getNameForTemplate(TName, TNameLoc);
+ TemplateArgs = &Buffer;
+ } else {
+ NameInfo = SemaRef.GetNameFromUnqualifiedId(Id);
+ TemplateArgs = 0;
+ }
+}
+
+/// Determines if the given class is provably not derived from all of
+/// the prospective base classes.
+static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
+ CXXRecordDecl *Record,
+ const llvm::SmallPtrSet<CXXRecordDecl*, 4> &Bases) {
+ if (Bases.count(Record->getCanonicalDecl()))
+ return false;
+
+ RecordDecl *RD = Record->getDefinition();
+ if (!RD) return false;
+ Record = cast<CXXRecordDecl>(RD);
+
+ for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
+ E = Record->bases_end(); I != E; ++I) {
+ CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
+ CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
+ if (!BaseRT) return false;
+
+ CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+ if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases))
+ return false;
+ }
+
+ return true;
+}
+
+enum IMAKind {
+ /// The reference is definitely not an instance member access.
+ IMA_Static,
+
+ /// The reference may be an implicit instance member access.
+ IMA_Mixed,
+
+ /// The reference may be to an instance member, but it is invalid if
+ /// so, because the context is not an instance method.
+ IMA_Mixed_StaticContext,
+
+ /// The reference may be to an instance member, but it is invalid if
+ /// so, because the context is from an unrelated class.
+ IMA_Mixed_Unrelated,
+
+ /// The reference is definitely an implicit instance member access.
+ IMA_Instance,
+
+ /// The reference may be to an unresolved using declaration.
+ IMA_Unresolved,
+
+ /// The reference may be to an unresolved using declaration and the
+ /// context is not an instance method.
+ IMA_Unresolved_StaticContext,
+
+ /// All possible referrents are instance members and the current
+ /// context is not an instance method.
+ IMA_Error_StaticContext,
+
+ /// All possible referrents are instance members of an unrelated
+ /// class.
+ IMA_Error_Unrelated
+};
+
+/// The given lookup names class member(s) and is not being used for
+/// an address-of-member expression. Classify the type of access
+/// according to whether it's possible that this reference names an
+/// instance member. This is best-effort; it is okay to
+/// conservatively answer "yes", in which case some errors will simply
+/// not be caught until template-instantiation.
+static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
+ const LookupResult &R) {
+ assert(!R.empty() && (*R.begin())->isCXXClassMember());
+
+ DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
+ bool isStaticContext =
+ (!isa<CXXMethodDecl>(DC) ||
+ cast<CXXMethodDecl>(DC)->isStatic());
+
+ if (R.isUnresolvableResult())
+ return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
+
+ // Collect all the declaring classes of instance members we find.
+ bool hasNonInstance = false;
+ bool hasField = false;
+ llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ NamedDecl *D = *I;
+
+ if (D->isCXXInstanceMember()) {
+ if (dyn_cast<FieldDecl>(D))
+ hasField = true;
+
+ CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
+ Classes.insert(R->getCanonicalDecl());
+ }
+ else
+ hasNonInstance = true;
+ }
+
+ // If we didn't find any instance members, it can't be an implicit
+ // member reference.
+ if (Classes.empty())
+ return IMA_Static;
+
+ // If the current context is not an instance method, it can't be
+ // an implicit member reference.
+ if (isStaticContext) {
+ if (hasNonInstance)
+ return IMA_Mixed_StaticContext;
+
+ if (SemaRef.getLangOptions().CPlusPlus0x && hasField) {
+ // C++0x [expr.prim.general]p10:
+ // An id-expression that denotes a non-static data member or non-static
+ // member function of a class can only be used:
+ // (...)
+ // - if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
+ const Sema::ExpressionEvaluationContextRecord& record = SemaRef.ExprEvalContexts.back();
+ bool isUnevaluatedExpression = record.Context == Sema::Unevaluated;
+ if (isUnevaluatedExpression)
+ return IMA_Mixed_StaticContext;
+ }
+
+ return IMA_Error_StaticContext;
+ }
+
+ // If we can prove that the current context is unrelated to all the
+ // declaring classes, it can't be an implicit member reference (in
+ // which case it's an error if any of those members are selected).
+ if (IsProvablyNotDerivedFrom(SemaRef,
+ cast<CXXMethodDecl>(DC)->getParent(),
+ Classes))
+ return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated);
+
+ return (hasNonInstance ? IMA_Mixed : IMA_Instance);
+}
+
+/// Diagnose a reference to a field with no object available.
+static void DiagnoseInstanceReference(Sema &SemaRef,
+ const CXXScopeSpec &SS,
+ NamedDecl *rep,
+ const DeclarationNameInfo &nameInfo) {
+ SourceLocation Loc = nameInfo.getLoc();
+ SourceRange Range(Loc);
+ if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
+
+ if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
+ if (MD->isStatic()) {
+ // "invalid use of member 'x' in static member function"
+ SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
+ << Range << nameInfo.getName();
+ return;
+ }
+ }
+
+ SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
+ << nameInfo.getName() << Range;
+ return;
+ }
+
+ SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
+}
+
+/// Diagnose an empty lookup.
+///
+/// \return false if new lookup candidates were found
+bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectTypoContext CTC) {
+ DeclarationName Name = R.getLookupName();
+
+ unsigned diagnostic = diag::err_undeclared_var_use;
+ unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
+ if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
+ Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ diagnostic = diag::err_undeclared_use;
+ diagnostic_suggest = diag::err_undeclared_use_suggest;
+ }
+
+ // If the original lookup was an unqualified lookup, fake an
+ // unqualified lookup. This is useful when (for example) the
+ // original lookup would not have found something because it was a
+ // dependent name.
+ for (DeclContext *DC = SS.isEmpty() ? CurContext : 0;
+ DC; DC = DC->getParent()) {
+ if (isa<CXXRecordDecl>(DC)) {
+ LookupQualifiedName(R, DC);
+
+ if (!R.empty()) {
+ // Don't give errors about ambiguities in this lookup.
+ R.suppressDiagnostics();
+
+ CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
+ bool isInstance = CurMethod &&
+ CurMethod->isInstance() &&
+ DC == CurMethod->getParent();
+
+ // Give a code modification hint to insert 'this->'.
+ // TODO: fixit for inserting 'Base<T>::' in the other cases.
+ // Actually quite difficult!
+ if (isInstance) {
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
+ CallsUndergoingInstantiation.back()->getCallee());
+ CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>(
+ CurMethod->getInstantiatedFromMemberFunction());
+ if (DepMethod) {
+ Diag(R.getNameLoc(), diagnostic) << Name
+ << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
+ QualType DepThisType = DepMethod->getThisType(Context);
+ CXXThisExpr *DepThis = new (Context) CXXThisExpr(
+ R.getNameLoc(), DepThisType, false);
+ TemplateArgumentListInfo TList;
+ if (ULE->hasExplicitTemplateArgs())
+ ULE->copyTemplateArgumentsInto(TList);
+ CXXDependentScopeMemberExpr *DepExpr =
+ CXXDependentScopeMemberExpr::Create(
+ Context, DepThis, DepThisType, true, SourceLocation(),
+ ULE->getQualifier(), ULE->getQualifierRange(), NULL,
+ R.getLookupNameInfo(), &TList);
+ CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+ } else {
+ // FIXME: we should be able to handle this case too. It is correct
+ // to add this-> here. This is a workaround for PR7947.
+ Diag(R.getNameLoc(), diagnostic) << Name;
+ }
+ } else {
+ Diag(R.getNameLoc(), diagnostic) << Name;
+ }
+
+ // Do we really want to note all of these?
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+ Diag((*I)->getLocation(), diag::note_dependent_var_use);
+
+ // Tell the callee to try to recover.
+ return false;
+ }
+
+ R.clear();
+ }
+ }
+
+ // We didn't find anything, so try to correct for a typo.
+ DeclarationName Corrected;
+ if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) {
+ if (!R.empty()) {
+ if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << R.getLookupName()
+ << SS.getRange()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ Diag(ND->getLocation(), diag::note_previous_decl)
+ << ND->getDeclName();
+
+ // Tell the callee to try to recover.
+ return false;
+ }
+
+ if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) {
+ // FIXME: If we ended up with a typo for a type name or
+ // Objective-C class name, we're in trouble because the parser
+ // is in the wrong place to recover. Suggest the typo
+ // correction, but don't make it a fix-it since we're not going
+ // to recover well anyway.
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << R.getLookupName()
+ << SS.getRange();
+
+ // Don't try to recover; it won't work.
+ return true;
+ }
+ } else {
+ // FIXME: We found a keyword. Suggest it, but don't provide a fix-it
+ // because we aren't able to recover.
+ if (SS.isEmpty())
+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected;
+ else
+ Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << computeDeclContext(SS, false) << Corrected
+ << SS.getRange();
+ return true;
+ }
+ R.clear();
+ }
+
+ // Emit a special diagnostic for failed member lookups.
+ // FIXME: computing the declaration context might fail here (?)
+ if (!SS.isEmpty()) {
+ Diag(R.getNameLoc(), diag::err_no_member)
+ << Name << computeDeclContext(SS, false)
+ << SS.getRange();
+ return true;
+ }
+
+ // Give up, we can't recover.
+ Diag(R.getNameLoc(), diagnostic) << Name;
+ return true;
+}
+
+ObjCPropertyDecl *Sema::canSynthesizeProvisionalIvar(IdentifierInfo *II) {
+ ObjCMethodDecl *CurMeth = getCurMethodDecl();
+ ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+ if (!IDecl)
+ return 0;
+ ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+ if (!ClassImpDecl)
+ return 0;
+ ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II);
+ if (!property)
+ return 0;
+ if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II))
+ if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic ||
+ PIDecl->getPropertyIvarDecl())
+ return 0;
+ return property;
+}
+
+bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) {
+ ObjCMethodDecl *CurMeth = getCurMethodDecl();
+ ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+ if (!IDecl)
+ return false;
+ ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+ if (!ClassImpDecl)
+ return false;
+ if (ObjCPropertyImplDecl *PIDecl
+ = ClassImpDecl->FindPropertyImplDecl(Property->getIdentifier()))
+ if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic ||
+ PIDecl->getPropertyIvarDecl())
+ return false;
+
+ return true;
+}
+
+static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
+ LookupResult &Lookup,
+ IdentifierInfo *II,
+ SourceLocation NameLoc) {
+ ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl();
+ bool LookForIvars;
+ if (Lookup.empty())
+ LookForIvars = true;
+ else if (CurMeth->isClassMethod())
+ LookForIvars = false;
+ else
+ LookForIvars = (Lookup.isSingleResult() &&
+ Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod() &&
+ (Lookup.getAsSingle<VarDecl>() != 0));
+ if (!LookForIvars)
+ return 0;
+
+ ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+ if (!IDecl)
+ return 0;
+ ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+ if (!ClassImpDecl)
+ return 0;
+ bool DynamicImplSeen = false;
+ ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II);
+ if (!property)
+ return 0;
+ if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) {
+ DynamicImplSeen =
+ (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
+ // property implementation has a designated ivar. No need to assume a new
+ // one.
+ if (!DynamicImplSeen && PIDecl->getPropertyIvarDecl())
+ return 0;
+ }
+ if (!DynamicImplSeen) {
+ QualType PropType = SemaRef.Context.getCanonicalType(property->getType());
+ ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl,
+ NameLoc,
+ II, PropType, /*Dinfo=*/0,
+ ObjCIvarDecl::Private,
+ (Expr *)0, true);
+ ClassImpDecl->addDecl(Ivar);
+ IDecl->makeDeclVisibleInContext(Ivar, false);
+ property->setPropertyIvarDecl(Ivar);
+ return Ivar;
+ }
+ return 0;
+}
+
+ExprResult Sema::ActOnIdExpression(Scope *S,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Id,
+ bool HasTrailingLParen,
+ bool isAddressOfOperand) {
+ assert(!(isAddressOfOperand && HasTrailingLParen) &&
+ "cannot be direct & operand and have a trailing lparen");
+
+ if (SS.isInvalid())
+ return ExprError();
+
+ TemplateArgumentListInfo TemplateArgsBuffer;
+
+ // Decompose the UnqualifiedId into the following data.
+ DeclarationNameInfo NameInfo;
+ const TemplateArgumentListInfo *TemplateArgs;
+ DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, NameInfo, TemplateArgs);
+
+ DeclarationName Name = NameInfo.getName();
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ SourceLocation NameLoc = NameInfo.getLoc();
+
+ // C++ [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains:
+ // -- an identifier that was declared with a dependent type,
+ // (note: handled after lookup)
+ // -- a template-id that is dependent,
+ // (note: handled in BuildTemplateIdExpr)
+ // -- a conversion-function-id that specifies a dependent type,
+ // -- a nested-name-specifier that contains a class-name that
+ // names a dependent type.
+ // Determine whether this is a member of an unknown specialization;
+ // we need to handle these differently.
+ bool DependentID = false;
+ if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+ Name.getCXXNameType()->isDependentType()) {
+ DependentID = true;
+ } else if (SS.isSet()) {
+ if (DeclContext *DC = computeDeclContext(SS, false)) {
+ if (RequireCompleteDeclContext(SS, DC))
+ return ExprError();
+ } else {
+ DependentID = true;
+ }
+ }
+
+ if (DependentID)
+ return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+ TemplateArgs);
+
+ bool IvarLookupFollowUp = false;
+ // Perform the required lookup.
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ if (TemplateArgs) {
+ // Lookup the template name again to correctly establish the context in
+ // which it was found. This is really unfortunate as we already did the
+ // lookup to determine that it was a template name in the first place. If
+ // this becomes a performance hit, we can work harder to preserve those
+ // results until we get here but it's likely not worth it.
+ bool MemberOfUnknownSpecialization;
+ LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
+ MemberOfUnknownSpecialization);
+
+ if (MemberOfUnknownSpecialization ||
+ (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
+ return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+ TemplateArgs);
+ } else {
+ IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
+ LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
+
+ // If the result might be in a dependent base class, this is a dependent
+ // id-expression.
+ if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
+ return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+ TemplateArgs);
+
+ // If this reference is in an Objective-C method, then we need to do
+ // some special Objective-C lookup, too.
+ if (IvarLookupFollowUp) {
+ ExprResult E(LookupInObjCMethod(R, S, II, true));
+ if (E.isInvalid())
+ return ExprError();
+
+ if (Expr *Ex = E.takeAs<Expr>())
+ return Owned(Ex);
+
+ // Synthesize ivars lazily.
+ if (getLangOptions().ObjCDefaultSynthProperties &&
+ getLangOptions().ObjCNonFragileABI2) {
+ if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) {
+ if (const ObjCPropertyDecl *Property =
+ canSynthesizeProvisionalIvar(II)) {
+ Diag(NameLoc, diag::warn_synthesized_ivar_access) << II;
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+ return ActOnIdExpression(S, SS, Id, HasTrailingLParen,
+ isAddressOfOperand);
+ }
+ }
+ // for further use, this must be set to false if in class method.
+ IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod();
+ }
+ }
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ // Determine whether this name might be a candidate for
+ // argument-dependent lookup.
+ bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
+
+ if (R.empty() && !ADL) {
+ // Otherwise, this could be an implicitly declared function reference (legal
+ // in C90, extension in C99, forbidden in C++).
+ if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) {
+ NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+ if (D) R.addDecl(D);
+ }
+
+ // If this name wasn't predeclared and if this is not a function
+ // call, diagnose the problem.
+ if (R.empty()) {
+ if (DiagnoseEmptyLookup(S, SS, R, CTC_Unknown))
+ return ExprError();
+
+ assert(!R.empty() &&
+ "DiagnoseEmptyLookup returned false but added no results");
+
+ // If we found an Objective-C instance variable, let
+ // LookupInObjCMethod build the appropriate expression to
+ // reference the ivar.
+ if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
+ R.clear();
+ ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
+ assert(E.isInvalid() || E.get());
+ return move(E);
+ }
+ }
+ }
+
+ // This is guaranteed from this point on.
+ assert(!R.empty() || ADL);
+
+ if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
+ if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
+ !(getLangOptions().ObjCDefaultSynthProperties &&
+ getLangOptions().ObjCNonFragileABI2) &&
+ Var->isFileVarDecl()) {
+ ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II);
+ if (Property) {
+ Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
+ Diag(Property->getLocation(), diag::note_property_declare);
+ Diag(Var->getLocation(), diag::note_global_declared_at);
+ }
+ }
+ }
+
+ // Check whether this might be a C++ implicit instance member access.
+ // C++ [class.mfct.non-static]p3:
+ // When an id-expression that is not part of a class member access
+ // syntax and not used to form a pointer to member is used in the
+ // body of a non-static member function of class X, if name lookup
+ // resolves the name in the id-expression to a non-static non-type
+ // member of some class C, the id-expression is transformed into a
+ // class member access expression using (*this) as the
+ // postfix-expression to the left of the . operator.
+ //
+ // But we don't actually need to do this for '&' operands if R
+ // resolved to a function or overloaded function set, because the
+ // expression is ill-formed if it actually works out to be a
+ // non-static member function:
+ //
+ // C++ [expr.ref]p4:
+ // Otherwise, if E1.E2 refers to a non-static member function. . .
+ // [t]he expression can be used only as the left-hand operand of a
+ // member function call.
+ //
+ // There are other safeguards against such uses, but it's important
+ // to get this right here so that we don't end up making a
+ // spuriously dependent expression if we're inside a dependent
+ // instance method.
+ if (!R.empty() && (*R.begin())->isCXXClassMember()) {
+ bool MightBeImplicitMember;
+ if (!isAddressOfOperand)
+ MightBeImplicitMember = true;
+ else if (!SS.isEmpty())
+ MightBeImplicitMember = false;
+ else if (R.isOverloadedResult())
+ MightBeImplicitMember = false;
+ else if (R.isUnresolvableResult())
+ MightBeImplicitMember = true;
+ else
+ MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
+ isa<IndirectFieldDecl>(R.getFoundDecl());
+
+ if (MightBeImplicitMember)
+ return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs);
+ }
+
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs);
+
+ return BuildDeclarationNameExpr(SS, R, ADL);
+}
+
+/// Builds an expression which might be an implicit member expression.
+ExprResult
+Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ switch (ClassifyImplicitMemberAccess(*this, R)) {
+ case IMA_Instance:
+ return BuildImplicitMemberExpr(SS, R, TemplateArgs, true);
+
+ case IMA_Mixed:
+ case IMA_Mixed_Unrelated:
+ case IMA_Unresolved:
+ return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
+
+ case IMA_Static:
+ case IMA_Mixed_StaticContext:
+ case IMA_Unresolved_StaticContext:
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
+ return BuildDeclarationNameExpr(SS, R, false);
+
+ case IMA_Error_StaticContext:
+ case IMA_Error_Unrelated:
+ DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
+ R.getLookupNameInfo());
+ return ExprError();
+ }
+
+ llvm_unreachable("unexpected instance member access kind");
+ return ExprError();
+}
+
+/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
+/// declaration name, generally during template instantiation.
+/// There's a large number of things which don't need to be done along
+/// this path.
+ExprResult
+Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo) {
+ DeclContext *DC;
+ if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext())
+ return BuildDependentDeclRefExpr(SS, NameInfo, 0);
+
+ if (RequireCompleteDeclContext(SS, DC))
+ return ExprError();
+
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ LookupQualifiedName(R, DC);
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ Diag(NameInfo.getLoc(), diag::err_no_member)
+ << NameInfo.getName() << DC << SS.getRange();
+ return ExprError();
+ }
+
+ return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
+}
+
+/// LookupInObjCMethod - The parser has read a name in, and Sema has
+/// detected that we're currently inside an ObjC method. Perform some
+/// additional lookup.
+///
+/// Ideally, most of this would be done by lookup, but there's
+/// actually quite a lot of extra work involved.
+///
+/// Returns a null sentinel to indicate trivial success.
+ExprResult
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
+ IdentifierInfo *II, bool AllowBuiltinCreation) {
+ SourceLocation Loc = Lookup.getNameLoc();
+ ObjCMethodDecl *CurMethod = getCurMethodDecl();
+
+ // There are two cases to handle here. 1) scoped lookup could have failed,
+ // in which case we should look for an ivar. 2) scoped lookup could have
+ // found a decl, but that decl is outside the current instance method (i.e.
+ // a global variable). In these two cases, we do a lookup for an ivar with
+ // this name, if the lookup sucedes, we replace it our current decl.
+
+ // If we're in a class method, we don't normally want to look for
+ // ivars. But if we don't find anything else, and there's an
+ // ivar, that's an error.
+ bool IsClassMethod = CurMethod->isClassMethod();
+
+ bool LookForIvars;
+ if (Lookup.empty())
+ LookForIvars = true;
+ else if (IsClassMethod)
+ LookForIvars = false;
+ else
+ LookForIvars = (Lookup.isSingleResult() &&
+ Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+ ObjCInterfaceDecl *IFace = 0;
+ if (LookForIvars) {
+ IFace = CurMethod->getClassInterface();
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+ // Diagnose using an ivar in a class method.
+ if (IsClassMethod)
+ return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+ << IV->getDeclName());
+
+ // If we're referencing an invalid decl, just return this as a silent
+ // error node. The error diagnostic was already emitted on the decl.
+ if (IV->isInvalidDecl())
+ return ExprError();
+
+ // Check if referencing a field with __attribute__((deprecated)).
+ if (DiagnoseUseOfDecl(IV, Loc))
+ return ExprError();
+
+ // Diagnose the use of an ivar outside of the declaring class.
+ if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+ ClassDeclared != IFace)
+ Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+ // FIXME: This should use a new expr for a direct reference, don't
+ // turn this into Self->ivar, just return a BareIVarExpr or something.
+ IdentifierInfo &II = Context.Idents.get("self");
+ UnqualifiedId SelfName;
+ SelfName.setIdentifier(&II, SourceLocation());
+ CXXScopeSpec SelfScopeSpec;
+ ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ SelfName, false, false);
+ if (SelfExpr.isInvalid())
+ return ExprError();
+
+ Expr *SelfE = SelfExpr.take();
+ DefaultLvalueConversion(SelfE);
+
+ MarkDeclarationReferenced(Loc, IV);
+ return Owned(new (Context)
+ ObjCIvarRefExpr(IV, IV->getType(), Loc,
+ SelfE, true, true));
+ }
+ } else if (CurMethod->isInstanceMethod()) {
+ // We should warn if a local variable hides an ivar.
+ ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+ if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+ IFace == ClassDeclared)
+ Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
+ }
+ }
+
+ if (Lookup.empty() && II && AllowBuiltinCreation) {
+ // FIXME. Consolidate this with similar code in LookupName.
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ if (!(getLangOptions().CPlusPlus &&
+ Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) {
+ NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+ S, Lookup.isForRedeclaration(),
+ Lookup.getNameLoc());
+ if (D) Lookup.addDecl(D);
+ }
+ }
+ }
+ // Sentinel value saying that we didn't do anything special.
+ return Owned((Expr*) 0);
+}
+
+/// \brief Cast a base object to a member's actual type.
+///
+/// Logically this happens in three phases:
+///
+/// * First we cast from the base type to the naming class.
+/// The naming class is the class into which we were looking
+/// when we found the member; it's the qualifier type if a
+/// qualifier was provided, and otherwise it's the base type.
+///
+/// * Next we cast from the naming class to the declaring class.
+/// If the member we found was brought into a class's scope by
+/// a using declaration, this is that class; otherwise it's
+/// the class declaring the member.
+///
+/// * Finally we cast from the declaring class to the "true"
+/// declaring class of the member. This conversion does not
+/// obey access control.
+bool
+Sema::PerformObjectMemberConversion(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member) {
+ CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
+ if (!RD)
+ return false;
+
+ QualType DestRecordType;
+ QualType DestType;
+ QualType FromRecordType;
+ QualType FromType = From->getType();
+ bool PointerConversions = false;
+ if (isa<FieldDecl>(Member)) {
+ DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD));
+
+ if (FromType->getAs<PointerType>()) {
+ DestType = Context.getPointerType(DestRecordType);
+ FromRecordType = FromType->getPointeeType();
+ PointerConversions = true;
+ } else {
+ DestType = DestRecordType;
+ FromRecordType = FromType;
+ }
+ } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
+ if (Method->isStatic())
+ return false;
+
+ DestType = Method->getThisType(Context);
+ DestRecordType = DestType->getPointeeType();
+
+ if (FromType->getAs<PointerType>()) {
+ FromRecordType = FromType->getPointeeType();
+ PointerConversions = true;
+ } else {
+ FromRecordType = FromType;
+ DestType = DestRecordType;
+ }
+ } else {
+ // No conversion necessary.
+ return false;
+ }
+
+ if (DestType->isDependentType() || FromType->isDependentType())
+ return false;
+
+ // If the unqualified types are the same, no conversion is necessary.
+ if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+ return false;
+
+ SourceRange FromRange = From->getSourceRange();
+ SourceLocation FromLoc = FromRange.getBegin();
+
+ ExprValueKind VK = CastCategory(From);
+
+ // C++ [class.member.lookup]p8:
+ // [...] Ambiguities can often be resolved by qualifying a name with its
+ // class name.
+ //
+ // If the member was a qualified name and the qualified referred to a
+ // specific base subobject type, we'll cast to that intermediate type
+ // first and then to the object in which the member is declared. That allows
+ // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as:
+ //
+ // class Base { public: int x; };
+ // class Derived1 : public Base { };
+ // class Derived2 : public Base { };
+ // class VeryDerived : public Derived1, public Derived2 { void f(); };
+ //
+ // void VeryDerived::f() {
+ // x = 17; // error: ambiguous base subobjects
+ // Derived1::x = 17; // okay, pick the Base subobject of Derived1
+ // }
+ if (Qualifier) {
+ QualType QType = QualType(Qualifier->getAsType(), 0);
+ assert(!QType.isNull() && "lookup done with dependent qualifier?");
+ assert(QType->isRecordType() && "lookup done with non-record type");
+
+ QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
+
+ // In C++98, the qualifier type doesn't actually have to be a base
+ // type of the object type, in which case we just ignore it.
+ // Otherwise build the appropriate casts.
+ if (IsDerivedFrom(FromRecordType, QRecordType)) {
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
+ FromLoc, FromRange, &BasePath))
+ return true;
+
+ if (PointerConversions)
+ QType = Context.getPointerType(QType);
+ ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
+
+ FromType = QType;
+ FromRecordType = QRecordType;
+
+ // If the qualifier type was the same as the destination type,
+ // we're done.
+ if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+ return false;
+ }
+ }
+
+ bool IgnoreAccess = false;
+
+ // If we actually found the member through a using declaration, cast
+ // down to the using declaration's type.
+ //
+ // Pointer equality is fine here because only one declaration of a
+ // class ever has member declarations.
+ if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
+ assert(isa<UsingShadowDecl>(FoundDecl));
+ QualType URecordType = Context.getTypeDeclType(
+ cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
+
+ // We only need to do this if the naming-class to declaring-class
+ // conversion is non-trivial.
+ if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
+ assert(IsDerivedFrom(FromRecordType, URecordType));
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
+ FromLoc, FromRange, &BasePath))
+ return true;
+
+ QualType UType = URecordType;
+ if (PointerConversions)
+ UType = Context.getPointerType(UType);
+ ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
+ FromType = UType;
+ FromRecordType = URecordType;
+ }
+
+ // We don't do access control for the conversion from the
+ // declaring class to the true declaring class.
+ IgnoreAccess = true;
+ }
+
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
+ FromLoc, FromRange, &BasePath,
+ IgnoreAccess))
+ return true;
+
+ ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
+ return false;
+}
+
+/// \brief Build a MemberExpr AST node.
+static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
+ const CXXScopeSpec &SS, ValueDecl *Member,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo,
+ QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = 0) {
+ NestedNameSpecifier *Qualifier = 0;
+ SourceRange QualifierRange;
+ if (SS.isSet()) {
+ Qualifier = (NestedNameSpecifier *) SS.getScopeRep();
+ QualifierRange = SS.getRange();
+ }
+
+ return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
+ Member, FoundDecl, MemberNameInfo,
+ TemplateArgs, Ty, VK, OK);
+}
+
+static ExprResult
+BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
+ const CXXScopeSpec &SS, FieldDecl *Field,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo) {
+ // x.a is an l-value if 'a' has a reference type. Otherwise:
+ // x.a is an l-value/x-value/pr-value if the base is (and note
+ // that *x is always an l-value), except that if the base isn't
+ // an ordinary object then we must have an rvalue.
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
+ if (!IsArrow) {
+ if (BaseExpr->getObjectKind() == OK_Ordinary)
+ VK = BaseExpr->getValueKind();
+ else
+ VK = VK_RValue;
+ }
+ if (VK != VK_RValue && Field->isBitField())
+ OK = OK_BitField;
+
+ // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
+ QualType MemberType = Field->getType();
+ if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
+ MemberType = Ref->getPointeeType();
+ VK = VK_LValue;
+ } else {
+ QualType BaseType = BaseExpr->getType();
+ if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+
+ // GC attributes are never picked up by members.
+ BaseQuals.removeObjCGCAttr();
+
+ // CVR attributes from the base are picked up by members,
+ // except that 'mutable' members don't pick up 'const'.
+ if (Field->isMutable()) BaseQuals.removeConst();
+
+ Qualifiers MemberQuals
+ = S.Context.getCanonicalType(MemberType).getQualifiers();
+
+ // TR 18037 does not allow fields to be declared with address spaces.
+ assert(!MemberQuals.hasAddressSpace());
+
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ MemberType = S.Context.getQualifiedType(MemberType, Combined);
+ }
+
+ S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field);
+ if (S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
+ FoundDecl, Field))
+ return ExprError();
+ return S.Owned(BuildMemberExpr(S.Context, BaseExpr, IsArrow, SS,
+ Field, FoundDecl, MemberNameInfo,
+ MemberType, VK, OK));
+}
+
+/// Builds an implicit member access expression. The current context
+/// is known to be an instance method, and the given unqualified lookup
+/// set is known to contain only instance members, at least one of which
+/// is from an appropriate type.
+ExprResult
+Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool IsKnownInstance) {
+ assert(!R.empty() && !R.isAmbiguous());
+
+ SourceLocation loc = R.getNameLoc();
+
+ // We may have found a field within an anonymous union or struct
+ // (C++ [class.union]).
+ // FIXME: template-ids inside anonymous structs?
+ if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
+ return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
+
+ // If this is known to be an instance access, go ahead and build an
+ // implicit 'this' expression now.
+ // 'this' expression now.
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ assert(method && "didn't correctly pre-flight capture of 'this'");
+
+ QualType thisType = method->getThisType(Context);
+ Expr *baseExpr = 0; // null signifies implicit access
+ if (IsKnownInstance) {
+ SourceLocation Loc = R.getNameLoc();
+ if (SS.getRange().isValid())
+ Loc = SS.getRange().getBegin();
+ baseExpr = new (Context) CXXThisExpr(loc, thisType, /*isImplicit=*/true);
+ }
+
+ return BuildMemberReferenceExpr(baseExpr, thisType,
+ /*OpLoc*/ SourceLocation(),
+ /*IsArrow*/ true,
+ SS,
+ /*FirstQualifierInScope*/ 0,
+ R, TemplateArgs);
+}
+
+bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
+ const LookupResult &R,
+ bool HasTrailingLParen) {
+ // Only when used directly as the postfix-expression of a call.
+ if (!HasTrailingLParen)
+ return false;
+
+ // Never if a scope specifier was provided.
+ if (SS.isSet())
+ return false;
+
+ // Only in C++ or ObjC++.
+ if (!getLangOptions().CPlusPlus)
+ return false;
+
+ // Turn off ADL when we find certain kinds of declarations during
+ // normal lookup:
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ NamedDecl *D = *I;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a declaration of a class member
+ // Since using decls preserve this property, we check this on the
+ // original decl.
+ if (D->isCXXClassMember())
+ return false;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a block-scope function declaration that is not a
+ // using-declaration
+ // NOTE: we also trigger this for function templates (in fact, we
+ // don't check the decl type at all, since all other decl types
+ // turn off ADL anyway).
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ else if (D->getDeclContext()->isFunctionOrMethod())
+ return false;
+
+ // C++0x [basic.lookup.argdep]p3:
+ // -- a declaration that is neither a function or a function
+ // template
+ // And also for builtin functions.
+ if (isa<FunctionDecl>(D)) {
+ FunctionDecl *FDecl = cast<FunctionDecl>(D);
+
+ // But also builtin functions.
+ if (FDecl->getBuiltinID() && FDecl->isImplicit())
+ return false;
+ } else if (!isa<FunctionTemplateDecl>(D))
+ return false;
+ }
+
+ return true;
+}
+
+
+/// Diagnoses obvious problems with the use of the given declaration
+/// as an expression. This is only actually called for lookups that
+/// were not overloaded, and it doesn't promise that the declaration
+/// will in fact be used.
+static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
+ if (isa<TypedefDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
+ return true;
+ }
+
+ if (isa<ObjCInterfaceDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName();
+ return true;
+ }
+
+ if (isa<NamespaceDecl>(D)) {
+ S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName();
+ return true;
+ }
+
+ return false;
+}
+
+ExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool NeedsADL) {
+ // If this is a single, fully-resolved result and we don't need ADL,
+ // just build an ordinary singleton decl ref.
+ if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
+ return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(),
+ R.getFoundDecl());
+
+ // We only need to check the declaration if there's exactly one
+ // result, because in the overloaded case the results can only be
+ // functions and function templates.
+ if (R.isSingleResult() &&
+ CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
+ return ExprError();
+
+ // Otherwise, just build an unresolved lookup expression. Suppress
+ // any lookup-related diagnostics; we'll hash these out later, when
+ // we've picked a target.
+ R.suppressDiagnostics();
+
+ UnresolvedLookupExpr *ULE
+ = UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
+ (NestedNameSpecifier*) SS.getScopeRep(),
+ SS.getRange(), R.getLookupNameInfo(),
+ NeedsADL, R.isOverloadedResult(),
+ R.begin(), R.end());
+
+ return Owned(ULE);
+}
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+ExprResult
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *D) {
+ assert(D && "Cannot refer to a NULL declaration");
+ assert(!isa<FunctionTemplateDecl>(D) &&
+ "Cannot refer unambiguously to a function template");
+
+ SourceLocation Loc = NameInfo.getLoc();
+ if (CheckDeclInExpr(*this, Loc, D))
+ return ExprError();
+
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
+ // Specifically diagnose references to class templates that are missing
+ // a template argument list.
+ Diag(Loc, diag::err_template_decl_ref)
+ << Template << SS.getRange();
+ Diag(Template->getLocation(), diag::note_template_decl_here);
+ return ExprError();
+ }
+
+ // Make sure that we're referring to a value.
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (!VD) {
+ Diag(Loc, diag::err_ref_non_value)
+ << D << SS.getRange();
+ Diag(D->getLocation(), diag::note_declared_at);
+ return ExprError();
+ }
+
+ // Check whether this declaration can be used. Note that we suppress
+ // this check when we're going to perform argument-dependent lookup
+ // on this function name, because this might not be the function
+ // that overload resolution actually selects.
+ if (DiagnoseUseOfDecl(VD, Loc))
+ return ExprError();
+
+ // Only create DeclRefExpr's for valid Decl's.
+ if (VD->isInvalidDecl())
+ return ExprError();
+
+ // Handle members of anonymous structs and unions. If we got here,
+ // and the reference is to a class member indirect field, then this
+ // must be the subject of a pointer-to-member expression.
+ if (IndirectFieldDecl *indirectField = dyn_cast<IndirectFieldDecl>(VD))
+ if (!indirectField->isCXXClassMember())
+ return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(),
+ indirectField);
+
+ // If the identifier reference is inside a block, and it refers to a value
+ // that is outside the block, create a BlockDeclRefExpr instead of a
+ // DeclRefExpr. This ensures the value is treated as a copy-in snapshot when
+ // the block is formed.
+ //
+ // We do not do this for things like enum constants, global variables, etc,
+ // as they do not get snapshotted.
+ //
+ switch (shouldCaptureValueReference(*this, NameInfo.getLoc(), VD)) {
+ case CR_Error:
+ return ExprError();
+
+ case CR_Capture:
+ assert(!SS.isSet() && "referenced local variable with scope specifier?");
+ return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ false);
+
+ case CR_CaptureByRef:
+ assert(!SS.isSet() && "referenced local variable with scope specifier?");
+ return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ true);
+
+ case CR_NoCapture: {
+ // If this reference is not in a block or if the referenced
+ // variable is within the block, create a normal DeclRefExpr.
+
+ QualType type = VD->getType();
+ ExprValueKind valueKind = VK_RValue;
+
+ switch (D->getKind()) {
+ // Ignore all the non-ValueDecl kinds.
+#define ABSTRACT_DECL(kind)
+#define VALUE(type, base)
+#define DECL(type, base) \
+ case Decl::type:
+#include "clang/AST/DeclNodes.inc"
+ llvm_unreachable("invalid value decl kind");
+ return ExprError();
+
+ // These shouldn't make it here.
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCIvar:
+ llvm_unreachable("forming non-member reference to ivar?");
+ return ExprError();
+
+ // Enum constants are always r-values and never references.
+ // Unresolved using declarations are dependent.
+ case Decl::EnumConstant:
+ case Decl::UnresolvedUsingValue:
+ valueKind = VK_RValue;
+ break;
+
+ // Fields and indirect fields that got here must be for
+ // pointer-to-member expressions; we just call them l-values for
+ // internal consistency, because this subexpression doesn't really
+ // exist in the high-level semantics.
+ case Decl::Field:
+ case Decl::IndirectField:
+ assert(getLangOptions().CPlusPlus &&
+ "building reference to field in C?");
+
+ // These can't have reference type in well-formed programs, but
+ // for internal consistency we do this anyway.
+ type = type.getNonReferenceType();
+ valueKind = VK_LValue;
+ break;
+
+ // Non-type template parameters are either l-values or r-values
+ // depending on the type.
+ case Decl::NonTypeTemplateParm: {
+ if (const ReferenceType *reftype = type->getAs<ReferenceType>()) {
+ type = reftype->getPointeeType();
+ valueKind = VK_LValue; // even if the parameter is an r-value reference
+ break;
+ }
+
+ // For non-references, we need to strip qualifiers just in case
+ // the template parameter was declared as 'const int' or whatever.
+ valueKind = VK_RValue;
+ type = type.getUnqualifiedType();
+ break;
+ }
+
+ case Decl::Var:
+ // In C, "extern void blah;" is valid and is an r-value.
+ if (!getLangOptions().CPlusPlus &&
+ !type.hasQualifiers() &&
+ type->isVoidType()) {
+ valueKind = VK_RValue;
+ break;
+ }
+ // fallthrough
+
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ // These are always l-values.
+ valueKind = VK_LValue;
+ type = type.getNonReferenceType();
+ break;
+
+ case Decl::Function: {
+ // Functions are l-values in C++.
+ if (getLangOptions().CPlusPlus) {
+ valueKind = VK_LValue;
+ break;
+ }
+
+ // C99 DR 316 says that, if a function type comes from a
+ // function definition (without a prototype), that type is only
+ // used for checking compatibility. Therefore, when referencing
+ // the function, we pretend that we don't have the full function
+ // type.
+ if (!cast<FunctionDecl>(VD)->hasPrototype())
+ if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
+ type = Context.getFunctionNoProtoType(proto->getResultType(),
+ proto->getExtInfo());
+
+ // Functions are r-values in C.
+ valueKind = VK_RValue;
+ break;
+ }
+
+ case Decl::CXXMethod:
+ // C++ methods are l-values if static, r-values if non-static.
+ if (cast<CXXMethodDecl>(VD)->isStatic()) {
+ valueKind = VK_LValue;
+ break;
+ }
+ // fallthrough
+
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXConstructor:
+ valueKind = VK_RValue;
+ break;
+ }
+
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
+ }
+
+ }
+
+ llvm_unreachable("unknown capture result");
+ return ExprError();
+}
+
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
+ tok::TokenKind Kind) {
+ PredefinedExpr::IdentType IT;
+
+ switch (Kind) {
+ default: assert(0 && "Unknown simple primary expr!");
+ case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
+ case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+ case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
+ }
+
+ // Pre-defined identifiers are of type char[x], where x is the length of the
+ // string.
+
+ Decl *currentDecl = getCurFunctionOrMethodDecl();
+ if (!currentDecl && getCurBlock())
+ currentDecl = getCurBlock()->TheDecl;
+ if (!currentDecl) {
+ Diag(Loc, diag::ext_predef_outside_function);
+ currentDecl = Context.getTranslationUnitDecl();
+ }
+
+ QualType ResTy;
+ if (cast<DeclContext>(currentDecl)->isDependentContext()) {
+ ResTy = Context.DependentTy;
+ } else {
+ unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+
+ llvm::APInt LengthI(32, Length + 1);
+ ResTy = Context.CharTy.withConst();
+ ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
+ }
+ return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
+}
+
+ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
+ llvm::SmallString<16> CharBuffer;
+ bool Invalid = false;
+ llvm::StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid);
+ if (Invalid)
+ return ExprError();
+
+ CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(),
+ PP);
+ if (Literal.hadError())
+ return ExprError();
+
+ QualType Ty;
+ if (!getLangOptions().CPlusPlus)
+ Ty = Context.IntTy; // 'x' and L'x' -> int in C.
+ else if (Literal.isWide())
+ Ty = Context.WCharTy; // L'x' -> wchar_t in C++.
+ else if (Literal.isMultiChar())
+ Ty = Context.IntTy; // 'wxyz' -> int in C++.
+ else
+ Ty = Context.CharTy; // 'x' -> char in C++
+
+ return Owned(new (Context) CharacterLiteral(Literal.getValue(),
+ Literal.isWide(),
+ Ty, Tok.getLocation()));
+}
+
+ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
+ // Fast path for a single digit (which is quite common). A single digit
+ // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
+ if (Tok.getLength() == 1) {
+ const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
+ unsigned IntSize = Context.Target.getIntWidth();
+ return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'),
+ Context.IntTy, Tok.getLocation()));
+ }
+
+ llvm::SmallString<512> IntegerBuffer;
+ // Add padding so that NumericLiteralParser can overread by one character.
+ IntegerBuffer.resize(Tok.getLength()+1);
+ const char *ThisTokBegin = &IntegerBuffer[0];
+
+ // Get the spelling of the token, which eliminates trigraphs, etc.
+ bool Invalid = false;
+ unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
+ if (Invalid)
+ return ExprError();
+
+ NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
+ Tok.getLocation(), PP);
+ if (Literal.hadError)
+ return ExprError();
+
+ Expr *Res;
+
+ if (Literal.isFloatingLiteral()) {
+ QualType Ty;
+ if (Literal.isFloat)
+ Ty = Context.FloatTy;
+ else if (!Literal.isLong)
+ Ty = Context.DoubleTy;
+ else
+ Ty = Context.LongDoubleTy;
+
+ const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty);
+
+ using llvm::APFloat;
+ APFloat Val(Format);
+
+ APFloat::opStatus result = Literal.GetFloatValue(Val);
+
+ // Overflow is always an error, but underflow is only an error if
+ // we underflowed to zero (APFloat reports denormals as underflow).
+ if ((result & APFloat::opOverflow) ||
+ ((result & APFloat::opUnderflow) && Val.isZero())) {
+ unsigned diagnostic;
+ llvm::SmallString<20> buffer;
+ if (result & APFloat::opOverflow) {
+ diagnostic = diag::warn_float_overflow;
+ APFloat::getLargest(Format).toString(buffer);
+ } else {
+ diagnostic = diag::warn_float_underflow;
+ APFloat::getSmallest(Format).toString(buffer);
+ }
+
+ Diag(Tok.getLocation(), diagnostic)
+ << Ty
+ << llvm::StringRef(buffer.data(), buffer.size());
+ }
+
+ bool isExact = (result == APFloat::opOK);
+ Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation());
+
+ if (getLangOptions().SinglePrecisionConstants && Ty == Context.DoubleTy)
+ ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast);
+
+ } else if (!Literal.isIntegerLiteral()) {
+ return ExprError();
+ } else {
+ QualType Ty;
+
+ // long long is a C99 feature.
+ if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
+ Literal.isLongLong)
+ Diag(Tok.getLocation(), diag::ext_longlong);
+
+ // Get the value in the widest-possible width.
+ llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0);
+
+ if (Literal.GetIntegerValue(ResultVal)) {
+ // If this value didn't fit into uintmax_t, warn and force to ull.
+ Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ Ty = Context.UnsignedLongLongTy;
+ assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
+ "long long is not intmax_t?");
+ } else {
+ // If this value fits into a ULL, try to figure out what else it fits into
+ // according to the rules of C99 6.4.4.1p5.
+
+ // Octal, Hexadecimal, and integers with a U suffix are allowed to
+ // be an unsigned int.
+ bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+ // Check from smallest to largest, picking the smallest type we can.
+ unsigned Width = 0;
+ if (!Literal.isLong && !Literal.isLongLong) {
+ // Are int/unsigned possibilities?
+ unsigned IntSize = Context.Target.getIntWidth();
+
+ // Does it fit in a unsigned int?
+ if (ResultVal.isIntN(IntSize)) {
+ // Does it fit in a signed int?
+ if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+ Ty = Context.IntTy;
+ else if (AllowUnsigned)
+ Ty = Context.UnsignedIntTy;
+ Width = IntSize;
+ }
+ }
+
+ // Are long/unsigned long possibilities?
+ if (Ty.isNull() && !Literal.isLongLong) {
+ unsigned LongSize = Context.Target.getLongWidth();
+
+ // Does it fit in a unsigned long?
+ if (ResultVal.isIntN(LongSize)) {
+ // Does it fit in a signed long?
+ if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+ Ty = Context.LongTy;
+ else if (AllowUnsigned)
+ Ty = Context.UnsignedLongTy;
+ Width = LongSize;
+ }
+ }
+
+ // Finally, check long long if needed.
+ if (Ty.isNull()) {
+ unsigned LongLongSize = Context.Target.getLongLongWidth();
+
+ // Does it fit in a unsigned long long?
+ if (ResultVal.isIntN(LongLongSize)) {
+ // Does it fit in a signed long long?
+ // To be compatible with MSVC, hex integer literals ending with the
+ // LL or i64 suffix are always signed in Microsoft mode.
+ if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 ||
+ (getLangOptions().Microsoft && Literal.isLongLong)))
+ Ty = Context.LongLongTy;
+ else if (AllowUnsigned)
+ Ty = Context.UnsignedLongLongTy;
+ Width = LongLongSize;
+ }
+ }
+
+ // If we still couldn't decide a type, we probably have something that
+ // does not fit in a signed long long, but has no U suffix.
+ if (Ty.isNull()) {
+ Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+ Ty = Context.UnsignedLongLongTy;
+ Width = Context.Target.getLongLongWidth();
+ }
+
+ if (ResultVal.getBitWidth() != Width)
+ ResultVal = ResultVal.trunc(Width);
+ }
+ Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
+ }
+
+ // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
+ if (Literal.isImaginary)
+ Res = new (Context) ImaginaryLiteral(Res,
+ Context.getComplexType(Res->getType()));
+
+ return Owned(Res);
+}
+
+ExprResult Sema::ActOnParenExpr(SourceLocation L,
+ SourceLocation R, Expr *E) {
+ assert((E != 0) && "ActOnParenExpr() missing expr");
+ return Owned(new (Context) ParenExpr(L, R, E));
+}
+
+/// The UsualUnaryConversions() function is *not* called by this routine.
+/// See C99 6.3.2.1p[2-4] for more details.
+bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
+ SourceLocation OpLoc,
+ SourceRange ExprRange,
+ bool isSizeof) {
+ if (exprType->isDependentType())
+ return false;
+
+ // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
+ // the result is the size of the referenced type."
+ // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
+ // result shall be the alignment of the referenced type."
+ if (const ReferenceType *Ref = exprType->getAs<ReferenceType>())
+ exprType = Ref->getPointeeType();
+
+ // C99 6.5.3.4p1:
+ if (exprType->isFunctionType()) {
+ // alignof(function) is allowed as an extension.
+ if (isSizeof)
+ Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange;
+ return false;
+ }
+
+ // Allow sizeof(void)/alignof(void) as an extension.
+ if (exprType->isVoidType()) {
+ Diag(OpLoc, diag::ext_sizeof_void_type)
+ << (isSizeof ? "sizeof" : "__alignof") << ExprRange;
+ return false;
+ }
+
+ if (RequireCompleteType(OpLoc, exprType,
+ PDiag(diag::err_sizeof_alignof_incomplete_type)
+ << int(!isSizeof) << ExprRange))
+ return true;
+
+ // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode.
+ if (LangOpts.ObjCNonFragileABI && exprType->isObjCObjectType()) {
+ Diag(OpLoc, diag::err_sizeof_nonfragile_interface)
+ << exprType << isSizeof << ExprRange;
+ return true;
+ }
+
+ return false;
+}
+
+static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,
+ SourceRange ExprRange) {
+ E = E->IgnoreParens();
+
+ // alignof decl is always ok.
+ if (isa<DeclRefExpr>(E))
+ return false;
+
+ // Cannot know anything else if the expression is dependent.
+ if (E->isTypeDependent())
+ return false;
+
+ if (E->getBitField()) {
+ S. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange;
+ return true;
+ }
+
+ // Alignment of a field access is always okay, so long as it isn't a
+ // bit-field.
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ if (isa<FieldDecl>(ME->getMemberDecl()))
+ return false;
+
+ return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
+}
+
+/// \brief Build a sizeof or alignof expression given a type operand.
+ExprResult
+Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
+ SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ if (!TInfo)
+ return ExprError();
+
+ QualType T = TInfo->getType();
+
+ if (!T->isDependentType() &&
+ CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
+ return ExprError();
+
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, TInfo,
+ Context.getSizeType(), OpLoc,
+ R.getEnd()));
+}
+
+/// \brief Build a sizeof or alignof expression given an expression
+/// operand.
+ExprResult
+Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ // Verify that the operand is valid.
+ bool isInvalid = false;
+ if (E->isTypeDependent()) {
+ // Delay type-checking for type-dependent expressions.
+ } else if (!isSizeOf) {
+ isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R);
+ } else if (E->getBitField()) { // C99 6.5.3.4p1.
+ Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
+ isInvalid = true;
+ } else if (E->getType()->isPlaceholderType()) {
+ ExprResult PE = CheckPlaceholderExpr(E, OpLoc);
+ if (PE.isInvalid()) return ExprError();
+ return CreateSizeOfAlignOfExpr(PE.take(), OpLoc, isSizeOf, R);
+ } else {
+ isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
+ }
+
+ if (isInvalid)
+ return ExprError();
+
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
+ Context.getSizeType(), OpLoc,
+ R.getEnd()));
+}
+
+/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
+/// the same for @c alignof and @c __alignof
+/// Note that the ArgRange is invalid if isType is false.
+ExprResult
+Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+ void *TyOrEx, const SourceRange &ArgRange) {
+ // If error parsing type, ignore.
+ if (TyOrEx == 0) return ExprError();
+
+ if (isType) {
+ TypeSourceInfo *TInfo;
+ (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
+ return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange);
+ }
+
+ Expr *ArgEx = (Expr *)TyOrEx;
+ ExprResult Result
+ = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
+
+ return move(Result);
+}
+
+static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc,
+ bool isReal) {
+ if (V->isTypeDependent())
+ return S.Context.DependentTy;
+
+ // _Real and _Imag are only l-values for normal l-values.
+ if (V->getObjectKind() != OK_Ordinary)
+ S.DefaultLvalueConversion(V);
+
+ // These operators return the element type of a complex type.
+ if (const ComplexType *CT = V->getType()->getAs<ComplexType>())
+ return CT->getElementType();
+
+ // Otherwise they pass through real integer and floating point types here.
+ if (V->getType()->isArithmeticType())
+ return V->getType();
+
+ // Test for placeholders.
+ ExprResult PR = S.CheckPlaceholderExpr(V, Loc);
+ if (PR.isInvalid()) return QualType();
+ if (PR.take() != V) {
+ V = PR.take();
+ return CheckRealImagOperand(S, V, Loc, isReal);
+ }
+
+ // Reject anything else.
+ S.Diag(Loc, diag::err_realimag_invalid_type) << V->getType()
+ << (isReal ? "__real" : "__imag");
+ return QualType();
+}
+
+
+
+ExprResult
+Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input) {
+ UnaryOperatorKind Opc;
+ switch (Kind) {
+ default: assert(0 && "Unknown unary op!");
+ case tok::plusplus: Opc = UO_PostInc; break;
+ case tok::minusminus: Opc = UO_PostDec; break;
+ }
+
+ return BuildUnaryOp(S, OpLoc, Opc, Input);
+}
+
+/// Expressions of certain arbitrary types are forbidden by C from
+/// having l-value type. These are:
+/// - 'void', but not qualified void
+/// - function types
+///
+/// The exact rule here is C99 6.3.2.1:
+/// An lvalue is an expression with an object type or an incomplete
+/// type other than void.
+static bool IsCForbiddenLValueType(ASTContext &C, QualType T) {
+ return ((T->isVoidType() && !T.hasQualifiers()) ||
+ T->isFunctionType());
+}
+
+ExprResult
+Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc) {
+ // Since this might be a postfix expression, get rid of ParenListExprs.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.take();
+
+ Expr *LHSExp = Base, *RHSExp = Idx;
+
+ if (getLangOptions().CPlusPlus &&
+ (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
+ return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+ Context.DependentTy,
+ VK_LValue, OK_Ordinary,
+ RLoc));
+ }
+
+ if (getLangOptions().CPlusPlus &&
+ (LHSExp->getType()->isRecordType() ||
+ LHSExp->getType()->isEnumeralType() ||
+ RHSExp->getType()->isRecordType() ||
+ RHSExp->getType()->isEnumeralType())) {
+ return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);
+ }
+
+ return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);
+}
+
+
+ExprResult
+Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc) {
+ Expr *LHSExp = Base;
+ Expr *RHSExp = Idx;
+
+ // Perform default conversions.
+ if (!LHSExp->getType()->getAs<VectorType>())
+ DefaultFunctionArrayLvalueConversion(LHSExp);
+ DefaultFunctionArrayLvalueConversion(RHSExp);
+
+ QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
+
+ // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
+ // to the expression *((e1)+(e2)). This means the array "Base" may actually be
+ // in the subscript position. As a result, we need to derive the array base
+ // and index from the expression types.
+ Expr *BaseExpr, *IndexExpr;
+ QualType ResultType;
+ if (LHSTy->isDependentType() || RHSTy->isDependentType()) {
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ ResultType = Context.DependentTy;
+ } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) {
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ ResultType = PTy->getPointeeType();
+ } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
+ // Handle the uncommon case of "123[Ptr]".
+ BaseExpr = RHSExp;
+ IndexExpr = LHSExp;
+ ResultType = PTy->getPointeeType();
+ } else if (const ObjCObjectPointerType *PTy =
+ LHSTy->getAs<ObjCObjectPointerType>()) {
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ ResultType = PTy->getPointeeType();
+ } else if (const ObjCObjectPointerType *PTy =
+ RHSTy->getAs<ObjCObjectPointerType>()) {
+ // Handle the uncommon case of "123[Ptr]".
+ BaseExpr = RHSExp;
+ IndexExpr = LHSExp;
+ ResultType = PTy->getPointeeType();
+ } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
+ BaseExpr = LHSExp; // vectors: V[123]
+ IndexExpr = RHSExp;
+ VK = LHSExp->getValueKind();
+ if (VK != VK_RValue)
+ OK = OK_VectorComponent;
+
+ // FIXME: need to deal with const...
+ ResultType = VTy->getElementType();
+ } else if (LHSTy->isArrayType()) {
+ // If we see an array that wasn't promoted by
+ // DefaultFunctionArrayLvalueConversion, it must be an array that
+ // wasn't promoted because of the C90 rule that doesn't
+ // allow promoting non-lvalue arrays. Warn, then
+ // force the promotion here.
+ Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+ LHSExp->getSourceRange();
+ ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
+ CK_ArrayToPointerDecay);
+ LHSTy = LHSExp->getType();
+
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
+ } else if (RHSTy->isArrayType()) {
+ // Same as previous, except for 123[f().a] case
+ Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
+ RHSExp->getSourceRange();
+ ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
+ CK_ArrayToPointerDecay);
+ RHSTy = RHSExp->getType();
+
+ BaseExpr = RHSExp;
+ IndexExpr = LHSExp;
+ ResultType = RHSTy->getAs<PointerType>()->getPointeeType();
+ } else {
+ return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
+ << LHSExp->getSourceRange() << RHSExp->getSourceRange());
+ }
+ // C99 6.5.2.1p1
+ if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
+ return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
+ << IndexExpr->getSourceRange());
+
+ if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ && !IndexExpr->isTypeDependent())
+ Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
+
+ // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+ // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
+ // type. Note that Functions are not objects, and that (in C99 parlance)
+ // incomplete types are not object types.
+ if (ResultType->isFunctionType()) {
+ Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
+ << ResultType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+
+ if (ResultType->isVoidType() && !getLangOptions().CPlusPlus) {
+ // GNU extension: subscripting on pointer to void
+ Diag(LLoc, diag::ext_gnu_void_ptr)
+ << BaseExpr->getSourceRange();
+
+ // C forbids expressions of unqualified void type from being l-values.
+ // See IsCForbiddenLValueType.
+ if (!ResultType.hasQualifiers()) VK = VK_RValue;
+ } else if (!ResultType->isDependentType() &&
+ RequireCompleteType(LLoc, ResultType,
+ PDiag(diag::err_subscript_incomplete_type)
+ << BaseExpr->getSourceRange()))
+ return ExprError();
+
+ // Diagnose bad cases where we step over interface counts.
+ if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
+ Diag(LLoc, diag::err_subscript_nonfragile_interface)
+ << ResultType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+
+ assert(VK == VK_RValue || LangOpts.CPlusPlus ||
+ !IsCForbiddenLValueType(Context, ResultType));
+
+ return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+ ResultType, VK, OK, RLoc));
+}
+
+/// Check an ext-vector component access expression.
+///
+/// VK should be set in advance to the value kind of the base
+/// expression.
+static QualType
+CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
+ SourceLocation OpLoc, const IdentifierInfo *CompName,
+ SourceLocation CompLoc) {
+ // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
+ // see FIXME there.
+ //
+ // FIXME: This logic can be greatly simplified by splitting it along
+ // halving/not halving and reworking the component checking.
+ const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
+
+ // The vector accessor can't exceed the number of elements.
+ const char *compStr = CompName->getNameStart();
+
+ // This flag determines whether or not the component is one of the four
+ // special names that indicate a subset of exactly half the elements are
+ // to be selected.
+ bool HalvingSwizzle = false;
+
+ // This flag determines whether or not CompName has an 's' char prefix,
+ // indicating that it is a string of hex values to be used as vector indices.
+ bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+
+ bool HasRepeated = false;
+ bool HasIndex[16] = {};
+
+ int Idx;
+
+ // Check that we've found one of the special components, or that the component
+ // names must come from the same set.
+ if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
+ !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
+ HalvingSwizzle = true;
+ } else if (!HexSwizzle &&
+ (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
+ do {
+ if (HasIndex[Idx]) HasRepeated = true;
+ HasIndex[Idx] = true;
+ compStr++;
+ } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
+ } else {
+ if (HexSwizzle) compStr++;
+ while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
+ if (HasIndex[Idx]) HasRepeated = true;
+ HasIndex[Idx] = true;
+ compStr++;
+ }
+ }
+
+ if (!HalvingSwizzle && *compStr) {
+ // We didn't get to the end of the string. This means the component names
+ // didn't come from the same set *or* we encountered an illegal name.
+ S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
+ << llvm::StringRef(compStr, 1) << SourceRange(CompLoc);
+ return QualType();
+ }
+
+ // Ensure no component accessor exceeds the width of the vector type it
+ // operates on.
+ if (!HalvingSwizzle) {
+ compStr = CompName->getNameStart();
+
+ if (HexSwizzle)
+ compStr++;
+
+ while (*compStr) {
+ if (!vecType->isAccessorWithinNumElements(*compStr++)) {
+ S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
+ << baseType << SourceRange(CompLoc);
+ return QualType();
+ }
+ }
+ }
+
+ // The component accessor looks fine - now we need to compute the actual type.
+ // The vector type is implied by the component accessor. For example,
+ // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
+ // vec4.s0 is a float, vec4.s23 is a vec3, etc.
+ // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
+ unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
+ : CompName->getLength();
+ if (HexSwizzle)
+ CompSize--;
+
+ if (CompSize == 1)
+ return vecType->getElementType();
+
+ if (HasRepeated) VK = VK_RValue;
+
+ QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
+ // Now look up the TypeDefDecl from the vector type. Without this,
+ // diagostics look bad. We want extended vector types to appear built-in.
+ for (unsigned i = 0, E = S.ExtVectorDecls.size(); i != E; ++i) {
+ if (S.ExtVectorDecls[i]->getUnderlyingType() == VT)
+ return S.Context.getTypedefType(S.ExtVectorDecls[i]);
+ }
+ return VT; // should never get here (a typedef type should always be found).
+}
+
+static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
+ IdentifierInfo *Member,
+ const Selector &Sel,
+ ASTContext &Context) {
+ if (Member)
+ if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member))
+ return PD;
+ if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
+ return OMD;
+
+ for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); I != E; ++I) {
+ if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ Context))
+ return D;
+ }
+ return 0;
+}
+
+static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
+ IdentifierInfo *Member,
+ const Selector &Sel,
+ ASTContext &Context) {
+ // Check protocols on qualified interfaces.
+ Decl *GDecl = 0;
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+ E = QIdTy->qual_end(); I != E; ++I) {
+ if (Member)
+ if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ GDecl = PD;
+ break;
+ }
+ // Also must look for a getter or setter name which uses property syntax.
+ if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) {
+ GDecl = OMD;
+ break;
+ }
+ }
+ if (!GDecl) {
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+ E = QIdTy->qual_end(); I != E; ++I) {
+ // Search in the protocol-qualifier list of current protocol.
+ GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel,
+ Context);
+ if (GDecl)
+ return GDecl;
+ }
+ }
+ return GDecl;
+}
+
+ExprResult
+Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ // Even in dependent contexts, try to diagnose base expressions with
+ // obviously wrong types, e.g.:
+ //
+ // T* t;
+ // t.f;
+ //
+ // In Obj-C++, however, the above expression is valid, since it could be
+ // accessing the 'f' property if T is an Obj-C interface. The extra check
+ // allows this, while still reporting an error if T is a struct pointer.
+ if (!IsArrow) {
+ const PointerType *PT = BaseType->getAs<PointerType>();
+ if (PT && (!getLangOptions().ObjC1 ||
+ PT->getPointeeType()->isRecordType())) {
+ assert(BaseExpr && "cannot happen with implicit member accesses");
+ Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union)
+ << BaseType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+ }
+
+ assert(BaseType->isDependentType() ||
+ NameInfo.getName().isDependentName() ||
+ isDependentScopeSpecifier(SS));
+
+ // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
+ // must have pointer type, and the accessed type is the pointee.
+ return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
+ IsArrow, OpLoc,
+ SS.getScopeRep(),
+ SS.getRange(),
+ FirstQualifierInScope,
+ NameInfo, TemplateArgs));
+}
+
+/// We know that the given qualified member reference points only to
+/// declarations which do not belong to the static type of the base
+/// expression. Diagnose the problem.
+static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
+ Expr *BaseExpr,
+ QualType BaseType,
+ const CXXScopeSpec &SS,
+ NamedDecl *rep,
+ const DeclarationNameInfo &nameInfo) {
+ // If this is an implicit member access, use a different set of
+ // diagnostics.
+ if (!BaseExpr)
+ return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
+
+ SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
+ << SS.getRange() << rep << BaseType;
+}
+
+// Check whether the declarations we found through a nested-name
+// specifier in a member expression are actually members of the base
+// type. The restriction here is:
+//
+// C++ [expr.ref]p2:
+// ... In these cases, the id-expression shall name a
+// member of the class or of one of its base classes.
+//
+// So it's perfectly legitimate for the nested-name specifier to name
+// an unrelated class, and for us to find an overload set including
+// decls from classes which are not superclasses, as long as the decl
+// we actually pick through overload resolution is from a superclass.
+bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
+ QualType BaseType,
+ const CXXScopeSpec &SS,
+ const LookupResult &R) {
+ const RecordType *BaseRT = BaseType->getAs<RecordType>();
+ if (!BaseRT) {
+ // We can't check this yet because the base type is still
+ // dependent.
+ assert(BaseType->isDependentType());
+ return false;
+ }
+ CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
+
+ for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+ // If this is an implicit member reference and we find a
+ // non-instance member, it's not an error.
+ if (!BaseExpr && !(*I)->isCXXInstanceMember())
+ return false;
+
+ // Note that we use the DC of the decl, not the underlying decl.
+ DeclContext *DC = (*I)->getDeclContext();
+ while (DC->isTransparentContext())
+ DC = DC->getParent();
+
+ if (!DC->isRecord())
+ continue;
+
+ llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord;
+ MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl());
+
+ if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord))
+ return false;
+ }
+
+ DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,
+ R.getRepresentativeDecl(),
+ R.getLookupNameInfo());
+ return true;
+}
+
+static bool
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+ SourceRange BaseRange, const RecordType *RTy,
+ SourceLocation OpLoc, CXXScopeSpec &SS,
+ bool HasTemplateArgs) {
+ RecordDecl *RDecl = RTy->getDecl();
+ if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+ SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
+ << BaseRange))
+ return true;
+
+ if (HasTemplateArgs) {
+ // LookupTemplateName doesn't expect these both to exist simultaneously.
+ QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
+
+ bool MOUS;
+ SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS);
+ return false;
+ }
+
+ DeclContext *DC = RDecl;
+ if (SS.isSet()) {
+ // If the member name was a qualified-id, look into the
+ // nested-name-specifier.
+ DC = SemaRef.computeDeclContext(SS, false);
+
+ if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
+ SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
+ << SS.getRange() << DC;
+ return true;
+ }
+
+ assert(DC && "Cannot handle non-computable dependent contexts in lookup");
+
+ if (!isa<TypeDecl>(DC)) {
+ SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
+ << DC << SS.getRange();
+ return true;
+ }
+ }
+
+ // The record definition is complete, now look up the member.
+ SemaRef.LookupQualifiedName(R, DC);
+
+ if (!R.empty())
+ return false;
+
+ // We didn't find anything with the given name, so try to correct
+ // for typos.
+ DeclarationName Name = R.getLookupName();
+ if (SemaRef.CorrectTypo(R, 0, &SS, DC, false, Sema::CTC_MemberLookup) &&
+ !R.empty() &&
+ (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
+ SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
+ << Name << DC << R.getLookupName() << SS.getRange()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ R.getLookupName().getAsString());
+ if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
+ SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
+ << ND->getDeclName();
+ return false;
+ } else {
+ R.clear();
+ R.setLookupName(Name);
+ }
+
+ return false;
+}
+
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ if (BaseType->isDependentType() ||
+ (SS.isSet() && isDependentScopeSpecifier(SS)))
+ return ActOnDependentMemberExpr(Base, BaseType,
+ IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ NameInfo, TemplateArgs);
+
+ LookupResult R(*this, NameInfo, LookupMemberName);
+
+ // Implicit member accesses.
+ if (!Base) {
+ QualType RecordTy = BaseType;
+ if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
+ if (LookupMemberExprInRecord(*this, R, SourceRange(),
+ RecordTy->getAs<RecordType>(),
+ OpLoc, SS, TemplateArgs != 0))
+ return ExprError();
+
+ // Explicit member accesses.
+ } else {
+ ExprResult Result =
+ LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
+
+ if (Result.isInvalid()) {
+ Owned(Base);
+ return ExprError();
+ }
+
+ if (Result.get())
+ return move(Result);
+
+ // LookupMemberExpr can modify Base, and thus change BaseType
+ BaseType = Base->getType();
+ }
+
+ return BuildMemberReferenceExpr(Base, BaseType,
+ OpLoc, IsArrow, SS, FirstQualifierInScope,
+ R, TemplateArgs);
+}
+
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool SuppressQualifierCheck) {
+ QualType BaseType = BaseExprType;
+ if (IsArrow) {
+ assert(BaseType->isPointerType());
+ BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+ }
+ R.setBaseObjectType(BaseType);
+
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
+ DeclarationName MemberName = MemberNameInfo.getName();
+ SourceLocation MemberLoc = MemberNameInfo.getLoc();
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ // Rederive where we looked up.
+ DeclContext *DC = (SS.isSet()
+ ? computeDeclContext(SS, false)
+ : BaseType->getAs<RecordType>()->getDecl());
+
+ Diag(R.getNameLoc(), diag::err_no_member)
+ << MemberName << DC
+ << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
+ return ExprError();
+ }
+
+ // Diagnose lookups that find only declarations from a non-base
+ // type. This is possible for either qualified lookups (which may
+ // have been qualified with an unrelated type) or implicit member
+ // expressions (which were found with unqualified lookup and thus
+ // may have come from an enclosing scope). Note that it's okay for
+ // lookup to find declarations from a non-base type as long as those
+ // aren't the ones picked by overload resolution.
+ if ((SS.isSet() || !BaseExpr ||
+ (isa<CXXThisExpr>(BaseExpr) &&
+ cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+ !SuppressQualifierCheck &&
+ CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
+ return ExprError();
+
+ // Construct an unresolved result if we in fact got an unresolved
+ // result.
+ if (R.isOverloadedResult() || R.isUnresolvableResult()) {
+ // Suppress any lookup-related diagnostics; we'll do these when we
+ // pick a member.
+ R.suppressDiagnostics();
+
+ UnresolvedMemberExpr *MemExpr
+ = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),
+ BaseExpr, BaseExprType,
+ IsArrow, OpLoc,
+ Qualifier, SS.getRange(),
+ MemberNameInfo,
+ TemplateArgs, R.begin(), R.end());
+
+ return Owned(MemExpr);
+ }
+
+ assert(R.isSingleResult());
+ DeclAccessPair FoundDecl = R.begin().getPair();
+ NamedDecl *MemberDecl = R.getFoundDecl();
+
+ // FIXME: diagnose the presence of template arguments now.
+
+ // If the decl being referenced had an error, return an error for this
+ // sub-expr without emitting another error, in order to avoid cascading
+ // error cases.
+ if (MemberDecl->isInvalidDecl())
+ return ExprError();
+
+ // Handle the implicit-member-access case.
+ if (!BaseExpr) {
+ // If this is not an instance member, convert to a non-member access.
+ if (!MemberDecl->isCXXInstanceMember())
+ return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl);
+
+ SourceLocation Loc = R.getNameLoc();
+ if (SS.getRange().isValid())
+ Loc = SS.getRange().getBegin();
+ BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
+ }
+
+ bool ShouldCheckUse = true;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+ // Don't diagnose the use of a virtual member function unless it's
+ // explicitly qualified.
+ if (MD->isVirtual() && !SS.isSet())
+ ShouldCheckUse = false;
+ }
+
+ // Check the use of this member.
+ if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) {
+ Owned(BaseExpr);
+ return ExprError();
+ }
+
+ // Perform a property load on the base regardless of whether we
+ // actually need it for the declaration.
+ if (BaseExpr->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(BaseExpr);
+
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
+ return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow,
+ SS, FD, FoundDecl, MemberNameInfo);
+
+ if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
+ // We may have found a field within an anonymous union or struct
+ // (C++ [class.union]).
+ return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
+ BaseExpr, OpLoc);
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, Var);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ Var, FoundDecl, MemberNameInfo,
+ Var->getType().getNonReferenceType(),
+ VK_LValue, OK_Ordinary));
+ }
+
+ if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ MemberFn, FoundDecl, MemberNameInfo,
+ MemberFn->getType(),
+ MemberFn->isInstance() ? VK_RValue : VK_LValue,
+ OK_Ordinary));
+ }
+ assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
+
+ if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
+ return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
+ Enum, FoundDecl, MemberNameInfo,
+ Enum->getType(), VK_RValue, OK_Ordinary));
+ }
+
+ Owned(BaseExpr);
+
+ // We found something that we didn't expect. Complain.
+ if (isa<TypeDecl>(MemberDecl))
+ Diag(MemberLoc, diag::err_typecheck_member_reference_type)
+ << MemberName << BaseType << int(IsArrow);
+ else
+ Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
+ << MemberName << BaseType << int(IsArrow);
+
+ Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
+ << MemberName;
+ R.suppressDiagnostics();
+ return ExprError();
+}
+
+/// Given that normal member access failed on the given expression,
+/// and given that the expression's type involves builtin-id or
+/// builtin-Class, decide whether substituting in the redefinition
+/// types would be profitable. The redefinition type is whatever
+/// this translation unit tried to typedef to id/Class; we store
+/// it to the side and then re-use it in places like this.
+static bool ShouldTryAgainWithRedefinitionType(Sema &S, Expr *&base) {
+ const ObjCObjectPointerType *opty
+ = base->getType()->getAs<ObjCObjectPointerType>();
+ if (!opty) return false;
+
+ const ObjCObjectType *ty = opty->getObjectType();
+
+ QualType redef;
+ if (ty->isObjCId()) {
+ redef = S.Context.ObjCIdRedefinitionType;
+ } else if (ty->isObjCClass()) {
+ redef = S.Context.ObjCClassRedefinitionType;
+ } else {
+ return false;
+ }
+
+ // Do the substitution as long as the redefinition type isn't just a
+ // possibly-qualified pointer to builtin-id or builtin-Class again.
+ opty = redef->getAs<ObjCObjectPointerType>();
+ if (opty && !opty->getObjectType()->getInterface() != 0)
+ return false;
+
+ S.ImpCastExprToType(base, redef, CK_BitCast);
+ return true;
+}
+
+/// Look up the given member of the given non-type-dependent
+/// expression. This can return in one of two ways:
+/// * If it returns a sentinel null-but-valid result, the caller will
+/// assume that lookup was performed and the results written into
+/// the provided structure. It will take over from there.
+/// * Otherwise, the returned expression will be produced in place of
+/// an ordinary member expression.
+///
+/// The ObjCImpDecl bit is a gross hack that will need to be properly
+/// fixed for ObjC++.
+ExprResult
+Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
+ bool &IsArrow, SourceLocation OpLoc,
+ CXXScopeSpec &SS,
+ Decl *ObjCImpDecl, bool HasTemplateArgs) {
+ assert(BaseExpr && "no base expression");
+
+ // Perform default conversions.
+ DefaultFunctionArrayConversion(BaseExpr);
+ if (IsArrow) DefaultLvalueConversion(BaseExpr);
+
+ QualType BaseType = BaseExpr->getType();
+ assert(!BaseType->isDependentType());
+
+ DeclarationName MemberName = R.getLookupName();
+ SourceLocation MemberLoc = R.getNameLoc();
+
+ // For later type-checking purposes, turn arrow accesses into dot
+ // accesses. The only access type we support that doesn't follow
+ // the C equivalence "a->b === (*a).b" is ObjC property accesses,
+ // and those never use arrows, so this is unaffected.
+ if (IsArrow) {
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ else if (const ObjCObjectPointerType *Ptr
+ = BaseType->getAs<ObjCObjectPointerType>())
+ BaseType = Ptr->getPointeeType();
+ else if (BaseType->isRecordType()) {
+ // Recover from arrow accesses to records, e.g.:
+ // struct MyRecord foo;
+ // foo->bar
+ // This is actually well-formed in C++ if MyRecord has an
+ // overloaded operator->, but that should have been dealt with
+ // by now.
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ IsArrow = false;
+ } else {
+ Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
+ << BaseType << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+ }
+
+ // Handle field access to simple records.
+ if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
+ if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(),
+ RTy, OpLoc, SS, HasTemplateArgs))
+ return ExprError();
+
+ // Returning valid-but-null is how we indicate to the caller that
+ // the lookup result was filled in.
+ return Owned((Expr*) 0);
+ }
+
+ // Handle ivar access to Objective-C objects.
+ if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+ // There are three cases for the base type:
+ // - builtin id (qualified or unqualified)
+ // - builtin Class (qualified or unqualified)
+ // - an interface
+ ObjCInterfaceDecl *IDecl = OTy->getInterface();
+ if (!IDecl) {
+ // There's an implicit 'isa' ivar on all objects.
+ // But we only actually find it this way on objects of type 'id',
+ // apparently.
+ if (OTy->isObjCId() && Member->isStr("isa"))
+ return Owned(new (Context) ObjCIsaExpr(BaseExpr, IsArrow, MemberLoc,
+ Context.getObjCClassType()));
+
+ if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ goto fail;
+ }
+
+ ObjCInterfaceDecl *ClassDeclared;
+ ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
+
+ if (!IV) {
+ // Attempt to correct for typos in ivar names.
+ LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),
+ LookupMemberName);
+ if (CorrectTypo(Res, 0, 0, IDecl, false,
+ IsArrow ? CTC_ObjCIvarLookup
+ : CTC_ObjCPropertyLookup) &&
+ (IV = Res.getAsSingle<ObjCIvarDecl>())) {
+ Diag(R.getNameLoc(),
+ diag::err_typecheck_member_reference_ivar_suggest)
+ << IDecl->getDeclName() << MemberName << IV->getDeclName()
+ << FixItHint::CreateReplacement(R.getNameLoc(),
+ IV->getNameAsString());
+ Diag(IV->getLocation(), diag::note_previous_decl)
+ << IV->getDeclName();
+ } else {
+ Res.clear();
+ Res.setLookupName(Member);
+
+ Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
+ << IDecl->getDeclName() << MemberName
+ << BaseExpr->getSourceRange();
+ return ExprError();
+ }
+ }
+
+ // If the decl being referenced had an error, return an error for this
+ // sub-expr without emitting another error, in order to avoid cascading
+ // error cases.
+ if (IV->isInvalidDecl())
+ return ExprError();
+
+ // Check whether we can reference this field.
+ if (DiagnoseUseOfDecl(IV, MemberLoc))
+ return ExprError();
+ if (IV->getAccessControl() != ObjCIvarDecl::Public &&
+ IV->getAccessControl() != ObjCIvarDecl::Package) {
+ ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+ if (ObjCMethodDecl *MD = getCurMethodDecl())
+ ClassOfMethodDecl = MD->getClassInterface();
+ else if (ObjCImpDecl && getCurFunctionDecl()) {
+ // Case of a c-function declared inside an objc implementation.
+ // FIXME: For a c-style function nested inside an objc implementation
+ // class, there is no implementation context available, so we pass
+ // down the context as argument to this routine. Ideally, this context
+ // need be passed down in the AST node and somehow calculated from the
+ // AST for a function decl.
+ if (ObjCImplementationDecl *IMPD =
+ dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
+ ClassOfMethodDecl = IMPD->getClassInterface();
+ else if (ObjCCategoryImplDecl* CatImplClass =
+ dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
+ ClassOfMethodDecl = CatImplClass->getClassInterface();
+ }
+
+ if (IV->getAccessControl() == ObjCIvarDecl::Private) {
+ if (ClassDeclared != IDecl ||
+ ClassOfMethodDecl != ClassDeclared)
+ Diag(MemberLoc, diag::error_private_ivar_access)
+ << IV->getDeclName();
+ } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
+ // @protected
+ Diag(MemberLoc, diag::error_protected_ivar_access)
+ << IV->getDeclName();
+ }
+
+ return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+ MemberLoc, BaseExpr,
+ IsArrow));
+ }
+
+ // Objective-C property access.
+ const ObjCObjectPointerType *OPT;
+ if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
+ // This actually uses the base as an r-value.
+ DefaultLvalueConversion(BaseExpr);
+ assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType()));
+
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+ const ObjCObjectType *OT = OPT->getObjectType();
+
+ // id, with and without qualifiers.
+ if (OT->isObjCId()) {
+ // Check protocols on qualified interfaces.
+ Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+ if (Decl *PMDecl = FindGetterSetterNameDecl(OPT, Member, Sel, Context)) {
+ if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
+ // Check the use of this declaration
+ if (DiagnoseUseOfDecl(PD, MemberLoc))
+ return ExprError();
+
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ VK_LValue,
+ OK_ObjCProperty,
+ MemberLoc,
+ BaseExpr));
+ }
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
+ // Check the use of this method.
+ if (DiagnoseUseOfDecl(OMD, MemberLoc))
+ return ExprError();
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), Member);
+ ObjCMethodDecl *SMD = 0;
+ if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
+ SetterSel, Context))
+ SMD = dyn_cast<ObjCMethodDecl>(SDecl);
+ QualType PType = OMD->getSendResultType();
+
+ ExprValueKind VK = VK_LValue;
+ if (!getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(Context, PType))
+ VK = VK_RValue;
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
+ return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType,
+ VK, OK,
+ MemberLoc, BaseExpr));
+ }
+ }
+
+ if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+
+ return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ << MemberName << BaseType);
+ }
+
+ // 'Class', unqualified only.
+ if (OT->isObjCClass()) {
+ // Only works in a method declaration (??!).
+ ObjCMethodDecl *MD = getCurMethodDecl();
+ if (!MD) {
+ if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+
+ goto fail;
+ }
+
+ // Also must look for a getter name which uses property syntax.
+ Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+ ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ ObjCMethodDecl *Getter;
+ if ((Getter = IFace->lookupClassMethod(Sel))) {
+ // Check the use of this method.
+ if (DiagnoseUseOfDecl(Getter, MemberLoc))
+ return ExprError();
+ } else
+ Getter = IFace->lookupPrivateMethod(Sel, false);
+ // If we found a getter then this may be a valid dot-reference, we
+ // will look for the matching setter, in case it is needed.
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), Member);
+ ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ Setter = IFace->lookupPrivateMethod(SetterSel, false);
+ }
+ // Look through local category implementations associated with the class.
+ if (!Setter)
+ Setter = IFace->getCategoryClassMethod(SetterSel);
+
+ if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+ return ExprError();
+
+ if (Getter || Setter) {
+ QualType PType;
+
+ ExprValueKind VK = VK_LValue;
+ if (Getter) {
+ PType = Getter->getSendResultType();
+ if (!getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(Context, PType))
+ VK = VK_RValue;
+ } else {
+ // Get the expression type from Setter's incoming parameter.
+ PType = (*(Setter->param_end() -1))->getType();
+ }
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
+ // FIXME: we must check that the setter has property type.
+ return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+ PType, VK, OK,
+ MemberLoc, BaseExpr));
+ }
+
+ if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+
+ return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ << MemberName << BaseType);
+ }
+
+ // Normal property access.
+ return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc,
+ SourceLocation(), QualType(), false);
+ }
+
+ // Handle 'field access' to vectors, such as 'V.xx'.
+ if (BaseType->isExtVectorType()) {
+ // FIXME: this expr should store IsArrow.
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+ ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr->getValueKind());
+ QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc,
+ Member, MemberLoc);
+ if (ret.isNull())
+ return ExprError();
+
+ return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr,
+ *Member, MemberLoc));
+ }
+
+ // Adjust builtin-sel to the appropriate redefinition type if that's
+ // not just a pointer to builtin-sel again.
+ if (IsArrow &&
+ BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
+ !Context.ObjCSelRedefinitionType->isObjCSelType()) {
+ ImpCastExprToType(BaseExpr, Context.ObjCSelRedefinitionType, CK_BitCast);
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+
+ // Failure cases.
+ fail:
+
+ // There's a possible road to recovery for function types.
+ const FunctionType *Fun = 0;
+ SourceLocation ParenInsertionLoc =
+ PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
+ // fall out, handled below.
+
+ // Recover from dot accesses to pointers, e.g.:
+ // type *foo;
+ // foo.bar
+ // This is actually well-formed in two cases:
+ // - 'type' is an Objective C type
+ // - 'bar' is a pseudo-destructor name which happens to refer to
+ // the appropriate pointer type
+ } else if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
+ MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, "->");
+
+ // Recurse as an -> access.
+ IsArrow = true;
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+ } else {
+ Fun = BaseType->getAs<FunctionType>();
+ }
+
+ // If the user is trying to apply -> or . to a function pointer
+ // type, it's probably because they forgot parentheses to call that
+ // function. Suggest the addition of those parentheses, build the
+ // call, and continue on.
+ if (Fun || BaseType == Context.OverloadTy) {
+ bool TryCall;
+ if (BaseType == Context.OverloadTy) {
+ // Plunder the overload set for something that would make the member
+ // expression valid.
+ const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
+ UnresolvedSet<4> CandidateOverloads;
+ bool HasZeroArgCandidateOverload = false;
+ for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
+ DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
+ const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ CandidateOverloads.addDecl(*it);
+ if (OverloadDecl->getNumParams() == 0) {
+ HasZeroArgCandidateOverload = true;
+ }
+ }
+ }
+ if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) {
+ // We have one reasonable overload, and there's only one way to call it,
+ // so emit a fixit and try to recover
+ Diag(ParenInsertionLoc, diag::err_member_reference_needs_call)
+ << 1
+ << BaseExpr->getSourceRange()
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ TryCall = true;
+ } else {
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << 0
+ << BaseExpr->getSourceRange();
+ int CandidateOverloadCount = CandidateOverloads.size();
+ int I;
+ for (I = 0; I < CandidateOverloadCount; ++I) {
+ // FIXME: Magic number for max shown overloads stolen from
+ // OverloadCandidateSet::NoteCandidates.
+ if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
+ break;
+ }
+ Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(),
+ diag::note_member_ref_possible_intended_overload);
+ }
+ if (I != CandidateOverloadCount) {
+ Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ << int(CandidateOverloadCount - I);
+ }
+ return ExprError();
+ }
+ } else {
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
+ TryCall = (FPT->getNumArgs() == 0);
+ } else {
+ TryCall = true;
+ }
+
+ if (TryCall) {
+ QualType ResultTy = Fun->getResultType();
+ TryCall = (!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getAs<PointerType>()->getPointeeType()->isRecordType());
+ }
+ }
+
+
+ if (TryCall) {
+ if (Fun) {
+ Diag(BaseExpr->getExprLoc(),
+ diag::err_member_reference_needs_call_zero_arg)
+ << QualType(Fun, 0)
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ }
+
+ ExprResult NewBase
+ = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ MultiExprArg(*this, 0, 0), ParenInsertionLoc);
+ if (NewBase.isInvalid())
+ return ExprError();
+ BaseExpr = NewBase.takeAs<Expr>();
+
+
+ DefaultFunctionArrayConversion(BaseExpr);
+ BaseType = BaseExpr->getType();
+
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+ }
+
+ Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
+ << BaseType << BaseExpr->getSourceRange();
+
+ return ExprError();
+}
+
+/// The main callback when the parser finds something like
+/// expression . [nested-name-specifier] identifier
+/// expression -> [nested-name-specifier] identifier
+/// where 'identifier' encompasses a fairly broad spectrum of
+/// possibilities, including destructor and operator references.
+///
+/// \param OpKind either tok::arrow or tok::period
+/// \param HasTrailingLParen whether the next token is '(', which
+/// is used to diagnose mis-uses of special members that can
+/// only be called
+/// \param ObjCImpDecl the current ObjC @implementation decl;
+/// this is an ugly hack around the fact that ObjC @implementations
+/// aren't properly put in the context chain
+ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Id,
+ Decl *ObjCImpDecl,
+ bool HasTrailingLParen) {
+ if (SS.isSet() && SS.isInvalid())
+ return ExprError();
+
+ // Warn about the explicit constructor calls Microsoft extension.
+ if (getLangOptions().Microsoft &&
+ Id.getKind() == UnqualifiedId::IK_ConstructorName)
+ Diag(Id.getSourceRange().getBegin(),
+ diag::ext_ms_explicit_constructor_call);
+
+ TemplateArgumentListInfo TemplateArgsBuffer;
+
+ // Decompose the name into its component parts.
+ DeclarationNameInfo NameInfo;
+ const TemplateArgumentListInfo *TemplateArgs;
+ DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
+ NameInfo, TemplateArgs);
+
+ DeclarationName Name = NameInfo.getName();
+ bool IsArrow = (OpKind == tok::arrow);
+
+ NamedDecl *FirstQualifierInScope
+ = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S,
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
+
+ // This is a postfix expression, so get rid of ParenListExprs.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.take();
+
+ if (Base->getType()->isDependentType() || Name.isDependentName() ||
+ isDependentScopeSpecifier(SS)) {
+ Result = ActOnDependentMemberExpr(Base, Base->getType(),
+ IsArrow, OpLoc,
+ SS, FirstQualifierInScope,
+ NameInfo, TemplateArgs);
+ } else {
+ LookupResult R(*this, NameInfo, LookupMemberName);
+ Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ SS, ObjCImpDecl, TemplateArgs != 0);
+
+ if (Result.isInvalid()) {
+ Owned(Base);
+ return ExprError();
+ }
+
+ if (Result.get()) {
+ // The only way a reference to a destructor can be used is to
+ // immediately call it, which falls into this case. If the
+ // next token is not a '(', produce a diagnostic and build the
+ // call now.
+ if (!HasTrailingLParen &&
+ Id.getKind() == UnqualifiedId::IK_DestructorName)
+ return DiagnoseDtorReference(NameInfo.getLoc(), Result.get());
+
+ return move(Result);
+ }
+
+ Result = BuildMemberReferenceExpr(Base, Base->getType(),
+ OpLoc, IsArrow, SS, FirstQualifierInScope,
+ R, TemplateArgs);
+ }
+
+ return move(Result);
+}
+
+ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD,
+ ParmVarDecl *Param) {
+ if (Param->hasUnparsedDefaultArg()) {
+ Diag(CallLoc,
+ diag::err_use_of_default_argument_to_function_declared_later) <<
+ FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
+ Diag(UnparsedDefaultArgLocs[Param],
+ diag::note_default_argument_declared_here);
+ return ExprError();
+ }
+
+ if (Param->hasUninstantiatedDefaultArg()) {
+ Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+
+ // Instantiate the expression.
+ MultiLevelTemplateArgumentList ArgList
+ = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
+
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = ArgList.getInnermost();
+ InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
+ Innermost.second);
+
+ ExprResult Result;
+ {
+ // C++ [dcl.fct.default]p5:
+ // The names in the [default argument] expression are bound, and
+ // the semantic constraints are checked, at the point where the
+ // default argument expression appears.
+ ContextRAII SavedContext(*this, FD);
+ Result = SubstExpr(UninstExpr, ArgList);
+ }
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Check the expression as an initializer for the parameter.
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Context, Param);
+ InitializationKind Kind
+ = InitializationKind::CreateCopy(Param->getLocation(),
+ /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin());
+ Expr *ResultE = Result.takeAs<Expr>();
+
+ InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1);
+ Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &ResultE, 1));
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Build the default argument expression.
+ return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param,
+ Result.takeAs<Expr>()));
+ }
+
+ // If the default expression creates temporaries, we need to
+ // push them to the current stack of expression temporaries so they'll
+ // be properly destroyed.
+ // FIXME: We should really be rebuilding the default argument with new
+ // bound temporaries; see the comment in PR5810.
+ for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) {
+ CXXTemporary *Temporary = Param->getDefaultArgTemporary(i);
+ MarkDeclarationReferenced(Param->getDefaultArg()->getLocStart(),
+ const_cast<CXXDestructorDecl*>(Temporary->getDestructor()));
+ ExprTemporaries.push_back(Temporary);
+ }
+
+ // We already type-checked the argument, so we know it works.
+ // Just mark all of the declarations in this potentially-evaluated expression
+ // as being "referenced".
+ MarkDeclarationsReferencedInExpr(Param->getDefaultArg());
+ return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
+}
+
+/// ConvertArgumentsForCall - Converts the arguments specified in
+/// Args/NumArgs to the parameter types of the function FDecl with
+/// function prototype Proto. Call is the call expression itself, and
+/// Fn is the function expression. For a C++ member function, this
+/// routine does not attempt to convert the object argument. Returns
+/// true if the call is ill-formed.
+bool
+Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
+ // assignment, to the types of the corresponding parameter, ...
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ bool Invalid = false;
+
+ // If too few arguments are available (and we don't have default
+ // arguments for the remaining parameters), don't make the call.
+ if (NumArgs < NumArgsInProto) {
+ if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
+ << Fn->getType()->isBlockPointerType()
+ << NumArgsInProto << NumArgs << Fn->getSourceRange();
+ Call->setNumArgs(Context, NumArgsInProto);
+ }
+
+ // If too many are passed and not variadic, error on the extras and drop
+ // them.
+ if (NumArgs > NumArgsInProto) {
+ if (!Proto->isVariadic()) {
+ Diag(Args[NumArgsInProto]->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << Fn->getType()->isBlockPointerType()
+ << NumArgsInProto << NumArgs << Fn->getSourceRange()
+ << SourceRange(Args[NumArgsInProto]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd());
+ // This deletes the extra arguments.
+ Call->setNumArgs(Context, NumArgsInProto);
+ return true;
+ }
+ }
+ llvm::SmallVector<Expr *, 8> AllArgs;
+ VariadicCallType CallType =
+ Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+ if (Fn->getType()->isBlockPointerType())
+ CallType = VariadicBlock; // Block
+ else if (isa<MemberExpr>(Fn))
+ CallType = VariadicMethod;
+ Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl,
+ Proto, 0, Args, NumArgs, AllArgs, CallType);
+ if (Invalid)
+ return true;
+ unsigned TotalNumArgs = AllArgs.size();
+ for (unsigned i = 0; i < TotalNumArgs; ++i)
+ Call->setArg(i, AllArgs[i]);
+
+ return false;
+}
+
+bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ unsigned FirstProtoArg,
+ Expr **Args, unsigned NumArgs,
+ llvm::SmallVector<Expr *, 8> &AllArgs,
+ VariadicCallType CallType) {
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumArgsToCheck = NumArgs;
+ bool Invalid = false;
+ if (NumArgs != NumArgsInProto)
+ // Use default arguments for missing arguments
+ NumArgsToCheck = NumArgsInProto;
+ unsigned ArgIx = 0;
+ // Continue to check argument types (even if we have too few/many args).
+ for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) {
+ QualType ProtoArgType = Proto->getArgType(i);
+
+ Expr *Arg;
+ if (ArgIx < NumArgs) {
+ Arg = Args[ArgIx++];
+
+ if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+ ProtoArgType,
+ PDiag(diag::err_call_incomplete_argument)
+ << Arg->getSourceRange()))
+ return true;
+
+ // Pass the argument
+ ParmVarDecl *Param = 0;
+ if (FDecl && i < FDecl->getNumParams())
+ Param = FDecl->getParamDecl(i);
+
+ InitializedEntity Entity =
+ Param? InitializedEntity::InitializeParameter(Context, Param)
+ : InitializedEntity::InitializeParameter(Context, ProtoArgType);
+ ExprResult ArgE = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(Arg));
+ if (ArgE.isInvalid())
+ return true;
+
+ Arg = ArgE.takeAs<Expr>();
+ } else {
+ ParmVarDecl *Param = FDecl->getParamDecl(i);
+
+ ExprResult ArgExpr =
+ BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
+ if (ArgExpr.isInvalid())
+ return true;
+
+ Arg = ArgExpr.takeAs<Expr>();
+ }
+ AllArgs.push_back(Arg);
+ }
+
+ // If this is a variadic call, handle args passed through "...".
+ if (CallType != VariadicDoesNotApply) {
+ // Promote the arguments (C99 6.5.2.2p7).
+ for (unsigned i = ArgIx; i != NumArgs; ++i) {
+ Expr *Arg = Args[i];
+ Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType, FDecl);
+ AllArgs.push_back(Arg);
+ }
+ }
+ return Invalid;
+}
+
+/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+/// This provides the location of the left/right parens and a list of comma
+/// locations.
+ExprResult
+Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+ MultiExprArg args, SourceLocation RParenLoc,
+ Expr *ExecConfig) {
+ unsigned NumArgs = args.size();
+
+ // Since this might be a postfix expression, get rid of ParenListExprs.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn);
+ if (Result.isInvalid()) return ExprError();
+ Fn = Result.take();
+
+ Expr **Args = args.release();
+
+ if (getLangOptions().CPlusPlus) {
+ // If this is a pseudo-destructor expression, build the call immediately.
+ if (isa<CXXPseudoDestructorExpr>(Fn)) {
+ if (NumArgs > 0) {
+ // Pseudo-destructor calls should not have any arguments.
+ Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
+ << FixItHint::CreateRemoval(
+ SourceRange(Args[0]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd()));
+
+ NumArgs = 0;
+ }
+
+ return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
+ VK_RValue, RParenLoc));
+ }
+
+ // Determine whether this is a dependent call inside a C++ template,
+ // in which case we won't do any semantic analysis now.
+ // FIXME: Will need to cache the results of name lookup (including ADL) in
+ // Fn.
+ bool Dependent = false;
+ if (Fn->isTypeDependent())
+ Dependent = true;
+ else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs))
+ Dependent = true;
+
+ if (Dependent) {
+ if (ExecConfig) {
+ return Owned(new (Context) CUDAKernelCallExpr(
+ Context, Fn, cast<CallExpr>(ExecConfig), Args, NumArgs,
+ Context.DependentTy, VK_RValue, RParenLoc));
+ } else {
+ return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs,
+ Context.DependentTy, VK_RValue,
+ RParenLoc));
+ }
+ }
+
+ // Determine whether this is a call to an object (C++ [over.call.object]).
+ if (Fn->getType()->isRecordType())
+ return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ Expr *NakedFn = Fn->IgnoreParens();
+
+ // Determine whether this is a call to an unresolved member function.
+ if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
+ // If lookup was unresolved but not dependent (i.e. didn't find
+ // an unresolved using declaration), it has to be an overloaded
+ // function set, which means it must contain either multiple
+ // declarations (all methods or method templates) or a single
+ // method template.
+ assert((MemE->getNumDecls() > 1) ||
+ isa<FunctionTemplateDecl>(
+ (*MemE->decls_begin())->getUnderlyingDecl()));
+ (void)MemE;
+
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+ RParenLoc);
+ }
+
+ // Determine whether this is a call to a member function.
+ if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
+ NamedDecl *MemDecl = MemExpr->getMemberDecl();
+ if (isa<CXXMethodDecl>(MemDecl))
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+ RParenLoc);
+ }
+
+ // Determine whether this is a call to a pointer-to-member function.
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
+ if (BO->getOpcode() == BO_PtrMemD ||
+ BO->getOpcode() == BO_PtrMemI) {
+ if (const FunctionProtoType *FPT
+ = BO->getType()->getAs<FunctionProtoType>()) {
+ QualType ResultTy = FPT->getCallResultType(Context);
+ ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
+
+ // Check that the object type isn't more qualified than the
+ // member function we're calling.
+ Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals());
+ Qualifiers ObjectQuals
+ = BO->getOpcode() == BO_PtrMemD
+ ? BO->getLHS()->getType().getQualifiers()
+ : BO->getLHS()->getType()->getAs<PointerType>()
+ ->getPointeeType().getQualifiers();
+
+ Qualifiers Difference = ObjectQuals - FuncQuals;
+ Difference.removeObjCGCAttr();
+ Difference.removeAddressSpace();
+ if (Difference) {
+ std::string QualsString = Difference.getAsString();
+ Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+ << BO->getType().getUnqualifiedType()
+ << QualsString
+ << (QualsString.find(' ') == std::string::npos? 1 : 2);
+ }
+
+ CXXMemberCallExpr *TheCall
+ = new (Context) CXXMemberCallExpr(Context, Fn, Args,
+ NumArgs, ResultTy, VK,
+ RParenLoc);
+
+ if (CheckCallReturnType(FPT->getResultType(),
+ BO->getRHS()->getSourceRange().getBegin(),
+ TheCall, 0))
+ return ExprError();
+
+ if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
+ RParenLoc))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall);
+ }
+ return ExprError(Diag(Fn->getLocStart(),
+ diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
+ }
+
+ // If we're directly calling a function, get the appropriate declaration.
+ // Also, in C++, keep track of whether we should perform argument-dependent
+ // lookup and whether there were any explicitly-specified template arguments.
+
+ Expr *NakedFn = Fn->IgnoreParens();
+ if (isa<UnresolvedLookupExpr>(NakedFn)) {
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+ RParenLoc, ExecConfig);
+ }
+
+ NamedDecl *NDecl = 0;
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
+ if (UnOp->getOpcode() == UO_AddrOf)
+ NakedFn = UnOp->getSubExpr()->IgnoreParens();
+
+ if (isa<DeclRefExpr>(NakedFn))
+ NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+
+ return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
+ ExecConfig);
+}
+
+ExprResult
+Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg execConfig, SourceLocation GGGLoc) {
+ FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl();
+ if (!ConfigDecl)
+ return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
+ << "cudaConfigureCall");
+ QualType ConfigQTy = ConfigDecl->getType();
+
+ DeclRefExpr *ConfigDR = new (Context) DeclRefExpr(
+ ConfigDecl, ConfigQTy, VK_LValue, LLLLoc);
+
+ return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0);
+}
+
+/// BuildResolvedCallExpr - Build a call to a resolved expression,
+/// i.e. an expression not of \p OverloadTy. The expression should
+/// unary-convert to an expression of function-pointer or
+/// block-pointer type.
+///
+/// \param NDecl the declaration being called, if available
+ExprResult
+Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ Expr *Config) {
+ FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
+
+ // Promote the function operand.
+ UsualUnaryConversions(Fn);
+
+ // Make the call expr early, before semantic checks. This guarantees cleanup
+ // of arguments and function on error.
+ CallExpr *TheCall;
+ if (Config) {
+ TheCall = new (Context) CUDAKernelCallExpr(Context, Fn,
+ cast<CallExpr>(Config),
+ Args, NumArgs,
+ Context.BoolTy,
+ VK_RValue,
+ RParenLoc);
+ } else {
+ TheCall = new (Context) CallExpr(Context, Fn,
+ Args, NumArgs,
+ Context.BoolTy,
+ VK_RValue,
+ RParenLoc);
+ }
+
+ const FunctionType *FuncT;
+ if (!Fn->getType()->isBlockPointerType()) {
+ // C99 6.5.2.2p1 - "The expression that denotes the called function shall
+ // have type pointer to function".
+ const PointerType *PT = Fn->getType()->getAs<PointerType>();
+ if (PT == 0)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ FuncT = PT->getPointeeType()->getAs<FunctionType>();
+ } else { // This is a block call.
+ FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
+ getAs<FunctionType>();
+ }
+ if (FuncT == 0)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+
+ // Check for a valid return type
+ if (CheckCallReturnType(FuncT->getResultType(),
+ Fn->getSourceRange().getBegin(), TheCall,
+ FDecl))
+ return ExprError();
+
+ // We know the result type of the call, set it.
+ TheCall->setType(FuncT->getCallResultType(Context));
+ TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
+
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
+ if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
+ RParenLoc))
+ return ExprError();
+ } else {
+ assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
+
+ if (FDecl) {
+ // Check if we have too few/too many template arguments, based
+ // on our knowledge of the function definition.
+ const FunctionDecl *Def = 0;
+ if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
+ const FunctionProtoType *Proto
+ = Def->getType()->getAs<FunctionProtoType>();
+ if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
+ Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
+ << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
+ }
+
+ // If the function we're calling isn't a function prototype, but we have
+ // a function prototype from a prior declaratiom, use that prototype.
+ if (!FDecl->hasPrototype())
+ Proto = FDecl->getType()->getAs<FunctionProtoType>();
+ }
+
+ // Promote the arguments (C99 6.5.2.2p6).
+ for (unsigned i = 0; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+
+ if (Proto && i < Proto->getNumArgs()) {
+ InitializedEntity Entity
+ = InitializedEntity::InitializeParameter(Context,
+ Proto->getArgType(i));
+ ExprResult ArgE = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(Arg));
+ if (ArgE.isInvalid())
+ return true;
+
+ Arg = ArgE.takeAs<Expr>();
+
+ } else {
+ DefaultArgumentPromotion(Arg);
+ }
+
+ if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+ Arg->getType(),
+ PDiag(diag::err_call_incomplete_argument)
+ << Arg->getSourceRange()))
+ return ExprError();
+
+ TheCall->setArg(i, Arg);
+ }
+ }
+
+ if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
+ if (!Method->isStatic())
+ return ExprError(Diag(LParenLoc, diag::err_member_call_without_object)
+ << Fn->getSourceRange());
+
+ // Check for sentinels
+ if (NDecl)
+ DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs);
+
+ // Do special checking on direct calls to functions.
+ if (FDecl) {
+ if (CheckFunctionCall(FDecl, TheCall))
+ return ExprError();
+
+ if (unsigned BuiltinID = FDecl->getBuiltinID())
+ return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+ } else if (NDecl) {
+ if (CheckBlockCall(NDecl, TheCall))
+ return ExprError();
+ }
+
+ return MaybeBindToTemporary(TheCall);
+}
+
+ExprResult
+Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *InitExpr) {
+ assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
+ // FIXME: put back this assert when initializers are worked out.
+ //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+
+ TypeSourceInfo *TInfo;
+ QualType literalType = GetTypeFromParser(Ty, &TInfo);
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(literalType);
+
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr);
+}
+
+ExprResult
+Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc, Expr *literalExpr) {
+ QualType literalType = TInfo->getType();
+
+ if (literalType->isArrayType()) {
+ if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType),
+ PDiag(diag::err_illegal_decl_array_incomplete_type)
+ << SourceRange(LParenLoc,
+ literalExpr->getSourceRange().getEnd())))
+ return ExprError();
+ if (literalType->isVariableArrayType())
+ return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
+ << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd()));
+ } else if (!literalType->isDependentType() &&
+ RequireCompleteType(LParenLoc, literalType,
+ PDiag(diag::err_typecheck_decl_incomplete_type)
+ << SourceRange(LParenLoc,
+ literalExpr->getSourceRange().getEnd())))
+ return ExprError();
+
+ InitializedEntity Entity
+ = InitializedEntity::InitializeTemporary(literalType);
+ InitializationKind Kind
+ = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc),
+ /*IsCStyleCast=*/true);
+ InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &literalExpr, 1),
+ &literalType);
+ if (Result.isInvalid())
+ return ExprError();
+ literalExpr = Result.get();
+
+ bool isFileScope = getCurFunctionOrMethodDecl() == 0;
+ if (isFileScope) { // 6.5.2.5p3
+ if (CheckForConstantInitializer(literalExpr, literalType))
+ return ExprError();
+ }
+
+ // In C, compound literals are l-values for some reason.
+ ExprValueKind VK = getLangOptions().CPlusPlus ? VK_RValue : VK_LValue;
+
+ return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+ VK, literalExpr, isFileScope));
+}
+
+ExprResult
+Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
+ SourceLocation RBraceLoc) {
+ unsigned NumInit = initlist.size();
+ Expr **InitList = initlist.release();
+
+ // Semantic analysis for initializers is done by ActOnDeclarator() and
+ // CheckInitializer() - it requires knowledge of the object being intialized.
+
+ InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList,
+ NumInit, RBraceLoc);
+ E->setType(Context.VoidTy); // FIXME: just a place holder for now.
+ return Owned(E);
+}
+
+/// Prepares for a scalar cast, performing all the necessary stages
+/// except the final cast and returning the kind required.
+static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
+ // Both Src and Dest are scalar types, i.e. arithmetic or pointer.
+ // Also, callers should have filtered out the invalid cases with
+ // pointers. Everything else should be possible.
+
+ QualType SrcTy = Src->getType();
+ if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))
+ return CK_NoOp;
+
+ switch (SrcTy->getScalarTypeKind()) {
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+
+ case Type::STK_Pointer:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Pointer:
+ return DestTy->isObjCObjectPointerType() ?
+ CK_AnyPointerToObjCPointerCast :
+ CK_BitCast;
+ case Type::STK_Bool:
+ return CK_PointerToBoolean;
+ case Type::STK_Integral:
+ return CK_PointerToIntegral;
+ case Type::STK_Floating:
+ case Type::STK_FloatingComplex:
+ case Type::STK_IntegralComplex:
+ case Type::STK_MemberPointer:
+ llvm_unreachable("illegal cast from pointer");
+ }
+ break;
+
+ case Type::STK_Bool: // casting from bool is like casting from an integer
+ case Type::STK_Integral:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Pointer:
+ if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
+ return CK_NullToPointer;
+ return CK_IntegralToPointer;
+ case Type::STK_Bool:
+ return CK_IntegralToBoolean;
+ case Type::STK_Integral:
+ return CK_IntegralCast;
+ case Type::STK_Floating:
+ return CK_IntegralToFloating;
+ case Type::STK_IntegralComplex:
+ S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralCast);
+ return CK_IntegralRealToComplex;
+ case Type::STK_FloatingComplex:
+ S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralToFloating);
+ return CK_FloatingRealToComplex;
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+ }
+ break;
+
+ case Type::STK_Floating:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Floating:
+ return CK_FloatingCast;
+ case Type::STK_Bool:
+ return CK_FloatingToBoolean;
+ case Type::STK_Integral:
+ return CK_FloatingToIntegral;
+ case Type::STK_FloatingComplex:
+ S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingCast);
+ return CK_FloatingRealToComplex;
+ case Type::STK_IntegralComplex:
+ S.ImpCastExprToType(Src, DestTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingToIntegral);
+ return CK_IntegralRealToComplex;
+ case Type::STK_Pointer:
+ llvm_unreachable("valid float->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+ }
+ break;
+
+ case Type::STK_FloatingComplex:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_FloatingComplex:
+ return CK_FloatingComplexCast;
+ case Type::STK_IntegralComplex:
+ return CK_FloatingComplexToIntegralComplex;
+ case Type::STK_Floating: {
+ QualType ET = SrcTy->getAs<ComplexType>()->getElementType();
+ if (S.Context.hasSameType(ET, DestTy))
+ return CK_FloatingComplexToReal;
+ S.ImpCastExprToType(Src, ET, CK_FloatingComplexToReal);
+ return CK_FloatingCast;
+ }
+ case Type::STK_Bool:
+ return CK_FloatingComplexToBoolean;
+ case Type::STK_Integral:
+ S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(),
+ CK_FloatingComplexToReal);
+ return CK_FloatingToIntegral;
+ case Type::STK_Pointer:
+ llvm_unreachable("valid complex float->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+ }
+ break;
+
+ case Type::STK_IntegralComplex:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_FloatingComplex:
+ return CK_IntegralComplexToFloatingComplex;
+ case Type::STK_IntegralComplex:
+ return CK_IntegralComplexCast;
+ case Type::STK_Integral: {
+ QualType ET = SrcTy->getAs<ComplexType>()->getElementType();
+ if (S.Context.hasSameType(ET, DestTy))
+ return CK_IntegralComplexToReal;
+ S.ImpCastExprToType(Src, ET, CK_IntegralComplexToReal);
+ return CK_IntegralCast;
+ }
+ case Type::STK_Bool:
+ return CK_IntegralComplexToBoolean;
+ case Type::STK_Floating:
+ S.ImpCastExprToType(Src, SrcTy->getAs<ComplexType>()->getElementType(),
+ CK_IntegralComplexToReal);
+ return CK_IntegralToFloating;
+ case Type::STK_Pointer:
+ llvm_unreachable("valid complex int->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+ }
+ break;
+ }
+
+ llvm_unreachable("Unhandled scalar cast");
+ return CK_BitCast;
+}
+
+/// CheckCastTypes - Check type constraints for casting between types.
+bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
+ Expr *&castExpr, CastKind& Kind, ExprValueKind &VK,
+ CXXCastPath &BasePath, bool FunctionalStyle) {
+ if (getLangOptions().CPlusPlus)
+ return CXXCheckCStyleCast(SourceRange(TyR.getBegin(),
+ castExpr->getLocEnd()),
+ castType, VK, castExpr, Kind, BasePath,
+ FunctionalStyle);
+
+ // We only support r-value casts in C.
+ VK = VK_RValue;
+
+ // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
+ // type needs to be scalar.
+ if (castType->isVoidType()) {
+ // We don't necessarily do lvalue-to-rvalue conversions on this.
+ IgnoredValueConversions(castExpr);
+
+ // Cast to void allows any expr type.
+ Kind = CK_ToVoid;
+ return false;
+ }
+
+ DefaultFunctionArrayLvalueConversion(castExpr);
+
+ if (RequireCompleteType(TyR.getBegin(), castType,
+ diag::err_typecheck_cast_to_incomplete))
+ return true;
+
+ if (!castType->isScalarType() && !castType->isVectorType()) {
+ if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) &&
+ (castType->isStructureType() || castType->isUnionType())) {
+ // GCC struct/union extension: allow cast to self.
+ // FIXME: Check that the cast destination type is complete.
+ Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
+ << castType << castExpr->getSourceRange();
+ Kind = CK_NoOp;
+ return false;
+ }
+
+ if (castType->isUnionType()) {
+ // GCC cast to union extension
+ RecordDecl *RD = castType->getAs<RecordType>()->getDecl();
+ RecordDecl::field_iterator Field, FieldEnd;
+ for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Context.hasSameUnqualifiedType(Field->getType(),
+ castExpr->getType()) &&
+ !Field->isUnnamedBitfield()) {
+ Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union)
+ << castExpr->getSourceRange();
+ break;
+ }
+ }
+ if (Field == FieldEnd)
+ return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+ << castExpr->getType() << castExpr->getSourceRange();
+ Kind = CK_ToUnion;
+ return false;
+ }
+
+ // Reject any other conversions to non-scalar types.
+ return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
+ << castType << castExpr->getSourceRange();
+ }
+
+ // The type we're casting to is known to be a scalar or vector.
+
+ // Require the operand to be a scalar or vector.
+ if (!castExpr->getType()->isScalarType() &&
+ !castExpr->getType()->isVectorType()) {
+ return Diag(castExpr->getLocStart(),
+ diag::err_typecheck_expect_scalar_operand)
+ << castExpr->getType() << castExpr->getSourceRange();
+ }
+
+ if (castType->isExtVectorType())
+ return CheckExtVectorCast(TyR, castType, castExpr, Kind);
+
+ if (castType->isVectorType())
+ return CheckVectorCast(TyR, castType, castExpr->getType(), Kind);
+ if (castExpr->getType()->isVectorType())
+ return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
+
+ // The source and target types are both scalars, i.e.
+ // - arithmetic types (fundamental, enum, and complex)
+ // - all kinds of pointers
+ // Note that member pointers were filtered out with C++, above.
+
+ if (isa<ObjCSelectorExpr>(castExpr))
+ return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+
+ // If either type is a pointer, the other type has to be either an
+ // integer or a pointer.
+ if (!castType->isArithmeticType()) {
+ QualType castExprType = castExpr->getType();
+ if (!castExprType->isIntegralType(Context) &&
+ castExprType->isArithmeticType())
+ return Diag(castExpr->getLocStart(),
+ diag::err_cast_pointer_from_non_pointer_int)
+ << castExprType << castExpr->getSourceRange();
+ } else if (!castExpr->getType()->isArithmeticType()) {
+ if (!castType->isIntegralType(Context) && castType->isArithmeticType())
+ return Diag(castExpr->getLocStart(),
+ diag::err_cast_pointer_to_non_pointer_int)
+ << castType << castExpr->getSourceRange();
+ }
+
+ Kind = PrepareScalarCast(*this, castExpr, castType);
+
+ if (Kind == CK_BitCast)
+ CheckCastAlign(castExpr, castType, TyR);
+
+ return false;
+}
+
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+ CastKind &Kind) {
+ assert(VectorTy->isVectorType() && "Not a vector type!");
+
+ if (Ty->isVectorType() || Ty->isIntegerType()) {
+ if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty))
+ return Diag(R.getBegin(),
+ Ty->isVectorType() ?
+ diag::err_invalid_conversion_between_vectors :
+ diag::err_invalid_conversion_between_vector_and_integer)
+ << VectorTy << Ty << R;
+ } else
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_vector_and_scalar)
+ << VectorTy << Ty << R;
+
+ Kind = CK_BitCast;
+ return false;
+}
+
+bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
+ CastKind &Kind) {
+ assert(DestTy->isExtVectorType() && "Not an extended vector type!");
+
+ QualType SrcTy = CastExpr->getType();
+
+ // If SrcTy is a VectorType, the total size must match to explicitly cast to
+ // an ExtVectorType.
+ if (SrcTy->isVectorType()) {
+ if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
+ return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
+ Kind = CK_BitCast;
+ return false;
+ }
+
+ // All non-pointer scalars can be cast to ExtVector type. The appropriate
+ // conversion will take place first from scalar to elt type, and then
+ // splat from elt type to vector.
+ if (SrcTy->isPointerType())
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_vector_and_scalar)
+ << DestTy << SrcTy << R;
+
+ QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
+ ImpCastExprToType(CastExpr, DestElemTy,
+ PrepareScalarCast(*this, CastExpr, DestElemTy));
+
+ Kind = CK_VectorSplat;
+ return false;
+}
+
+ExprResult
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *castExpr) {
+ assert((Ty != 0) && (castExpr != 0) &&
+ "ActOnCastExpr(): missing type or expr");
+
+ TypeSourceInfo *castTInfo;
+ QualType castType = GetTypeFromParser(Ty, &castTInfo);
+ if (!castTInfo)
+ castTInfo = Context.getTrivialTypeSourceInfo(castType);
+
+ // If the Expr being casted is a ParenListExpr, handle it specially.
+ if (isa<ParenListExpr>(castExpr))
+ return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, castExpr,
+ castTInfo);
+
+ return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, castExpr);
+}
+
+ExprResult
+Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+ SourceLocation RParenLoc, Expr *castExpr) {
+ CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
+ CXXCastPath BasePath;
+ if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
+ Kind, VK, BasePath))
+ return ExprError();
+
+ return Owned(CStyleCastExpr::Create(Context,
+ Ty->getType().getNonLValueExprType(Context),
+ VK, Kind, castExpr, &BasePath, Ty,
+ LParenLoc, RParenLoc));
+}
+
+/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
+/// of comma binary operators.
+ExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *expr) {
+ ParenListExpr *E = dyn_cast<ParenListExpr>(expr);
+ if (!E)
+ return Owned(expr);
+
+ ExprResult Result(E->getExpr(0));
+
+ for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
+ Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(),
+ E->getExpr(i));
+
+ if (Result.isInvalid()) return ExprError();
+
+ return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
+}
+
+ExprResult
+Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *Op,
+ TypeSourceInfo *TInfo) {
+ ParenListExpr *PE = cast<ParenListExpr>(Op);
+ QualType Ty = TInfo->getType();
+ bool isAltiVecLiteral = false;
+
+ // Check for an altivec literal,
+ // i.e. all the elements are integer constants.
+ if (getLangOptions().AltiVec && Ty->isVectorType()) {
+ if (PE->getNumExprs() == 0) {
+ Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer);
+ return ExprError();
+ }
+ if (PE->getNumExprs() == 1) {
+ if (!PE->getExpr(0)->getType()->isVectorType())
+ isAltiVecLiteral = true;
+ }
+ else
+ isAltiVecLiteral = true;
+ }
+
+ // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
+ // then handle it as such.
+ if (isAltiVecLiteral) {
+ llvm::SmallVector<Expr *, 8> initExprs;
+ for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
+ initExprs.push_back(PE->getExpr(i));
+
+ // FIXME: This means that pretty-printing the final AST will produce curly
+ // braces instead of the original commas.
+ InitListExpr *E = new (Context) InitListExpr(Context, LParenLoc,
+ &initExprs[0],
+ initExprs.size(), RParenLoc);
+ E->setType(Ty);
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, E);
+ } else {
+ // This is not an AltiVec-style cast, so turn the ParenListExpr into a
+ // sequence of BinOp comma operators.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Op);
+ if (Result.isInvalid()) return ExprError();
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Result.take());
+ }
+}
+
+ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val,
+ ParsedType TypeOfCast) {
+ unsigned nexprs = Val.size();
+ Expr **exprs = reinterpret_cast<Expr**>(Val.release());
+ assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list");
+ Expr *expr;
+ if (nexprs == 1 && TypeOfCast && !TypeIsVectorType(TypeOfCast))
+ expr = new (Context) ParenExpr(L, R, exprs[0]);
+ else
+ expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R);
+ return Owned(expr);
+}
+
+/// \brief Emit a specialized diagnostic when one expression is a null pointer
+/// constant and the other is not a pointer.
+bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS,
+ SourceLocation QuestionLoc) {
+ Expr *NullExpr = LHS;
+ Expr *NonPointerExpr = RHS;
+ Expr::NullPointerConstantKind NullKind =
+ NullExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull);
+
+ if (NullKind == Expr::NPCK_NotNull) {
+ NullExpr = RHS;
+ NonPointerExpr = LHS;
+ NullKind =
+ NullExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull);
+ }
+
+ if (NullKind == Expr::NPCK_NotNull)
+ return false;
+
+ if (NullKind == Expr::NPCK_ZeroInteger) {
+ // In this case, check to make sure that we got here from a "NULL"
+ // string in the source code.
+ NullExpr = NullExpr->IgnoreParenImpCasts();
+ SourceManager& SM = Context.getSourceManager();
+ SourceLocation Loc = SM.getInstantiationLoc(NullExpr->getExprLoc());
+ unsigned Len =
+ Lexer::MeasureTokenLength(Loc, SM, Context.getLangOptions());
+ if (Len != 4 || memcmp(SM.getCharacterData(Loc), "NULL", 4))
+ return false;
+ }
+
+ int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr);
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null)
+ << NonPointerExpr->getType() << DiagType
+ << NonPointerExpr->getSourceRange();
+ return true;
+}
+
+/// Note that lhs is not null here, even if this is the gnu "x ?: y" extension.
+/// In that case, lhs = cond.
+/// C99 6.5.15
+QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+ ExprValueKind &VK, ExprObjectKind &OK,
+ SourceLocation QuestionLoc) {
+ // If both LHS and RHS are overloaded functions, try to resolve them.
+ if (Context.hasSameType(LHS->getType(), RHS->getType()) &&
+ LHS->getType()->isSpecificBuiltinType(BuiltinType::Overload)) {
+ ExprResult LHSResult = CheckPlaceholderExpr(LHS, QuestionLoc);
+ if (LHSResult.isInvalid())
+ return QualType();
+
+ ExprResult RHSResult = CheckPlaceholderExpr(RHS, QuestionLoc);
+ if (RHSResult.isInvalid())
+ return QualType();
+
+ LHS = LHSResult.take();
+ RHS = RHSResult.take();
+ }
+
+ // C++ is sufficiently different to merit its own checker.
+ if (getLangOptions().CPlusPlus)
+ return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
+
+ VK = VK_RValue;
+ OK = OK_Ordinary;
+
+ UsualUnaryConversions(Cond);
+ UsualUnaryConversions(LHS);
+ UsualUnaryConversions(RHS);
+ QualType CondTy = Cond->getType();
+ QualType LHSTy = LHS->getType();
+ QualType RHSTy = RHS->getType();
+
+ // first, check the condition.
+ if (!CondTy->isScalarType()) { // C99 6.5.15p2
+ // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar.
+ // Throw an error if its not either.
+ if (getLangOptions().OpenCL) {
+ if (!CondTy->isVectorType()) {
+ Diag(Cond->getLocStart(),
+ diag::err_typecheck_cond_expect_scalar_or_vector)
+ << CondTy;
+ return QualType();
+ }
+ }
+ else {
+ Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy;
+ return QualType();
+ }
+ }
+
+ // Now check the two expressions.
+ if (LHSTy->isVectorType() || RHSTy->isVectorType())
+ return CheckVectorOperands(QuestionLoc, LHS, RHS);
+
+ // OpenCL: If the condition is a vector, and both operands are scalar,
+ // attempt to implicity convert them to the vector type to act like the
+ // built in select.
+ if (getLangOptions().OpenCL && CondTy->isVectorType()) {
+ // Both operands should be of scalar type.
+ if (!LHSTy->isScalarType()) {
+ Diag(LHS->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy;
+ return QualType();
+ }
+ if (!RHSTy->isScalarType()) {
+ Diag(RHS->getLocStart(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy;
+ return QualType();
+ }
+ // Implicity convert these scalars to the type of the condition.
+ ImpCastExprToType(LHS, CondTy, CK_IntegralCast);
+ ImpCastExprToType(RHS, CondTy, CK_IntegralCast);
+ }
+
+ // If both operands have arithmetic type, do the usual arithmetic conversions
+ // to find a common type: C99 6.5.15p3,5.
+ if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
+ UsualArithmeticConversions(LHS, RHS);
+ return LHS->getType();
+ }
+
+ // If both operands are the same structure or union type, the result is that
+ // type.
+ if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3
+ if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
+ if (LHSRT->getDecl() == RHSRT->getDecl())
+ // "If both the operands have structure or union type, the result has
+ // that type." This implies that CV qualifiers are dropped.
+ return LHSTy.getUnqualifiedType();
+ // FIXME: Type of conditional expression must be complete in C mode.
+ }
+
+ // C99 6.5.15p5: "If both operands have void type, the result has void type."
+ // The following || allows only one side to be void (a GCC-ism).
+ if (LHSTy->isVoidType() || RHSTy->isVoidType()) {
+ if (!LHSTy->isVoidType())
+ Diag(RHS->getLocStart(), diag::ext_typecheck_cond_one_void)
+ << RHS->getSourceRange();
+ if (!RHSTy->isVoidType())
+ Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)
+ << LHS->getSourceRange();
+ ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid);
+ ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid);
+ return Context.VoidTy;
+ }
+ // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
+ // the type of the other operand."
+ if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
+ RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ // promote the null to a pointer.
+ ImpCastExprToType(RHS, LHSTy, CK_NullToPointer);
+ return LHSTy;
+ }
+ if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
+ LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ ImpCastExprToType(LHS, RHSTy, CK_NullToPointer);
+ return RHSTy;
+ }
+
+ // All objective-c pointer type analysis is done here.
+ QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
+ QuestionLoc);
+ if (!compositeType.isNull())
+ return compositeType;
+
+
+ // Handle block pointer types.
+ if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
+ if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
+ if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
+ QualType destType = Context.getPointerType(Context.VoidTy);
+ ImpCastExprToType(LHS, destType, CK_BitCast);
+ ImpCastExprToType(RHS, destType, CK_BitCast);
+ return destType;
+ }
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ return QualType();
+ }
+ // We have 2 block pointer types.
+ if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+ // Two identical block pointer types are always compatible.
+ return LHSTy;
+ }
+ // The block pointer types aren't identical, continue checking.
+ QualType lhptee = LHSTy->getAs<BlockPointerType>()->getPointeeType();
+ QualType rhptee = RHSTy->getAs<BlockPointerType>()->getPointeeType();
+
+ if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType())) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ // In this situation, we assume void* type. No especially good
+ // reason, but this is what gcc does, and we do have to pick
+ // to get a consistent AST.
+ QualType incompatTy = Context.getPointerType(Context.VoidTy);
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ return incompatTy;
+ }
+ // The block pointer types are compatible.
+ ImpCastExprToType(LHS, LHSTy, CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ return LHSTy;
+ }
+
+ // Check constraints for C object pointers types (C99 6.5.15p3,6).
+ if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
+ // get the "pointed to" types
+ QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+ QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+
+ // ignore qualifiers on void (C99 6.5.15p3, clause 6)
+ if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
+ // Figure out necessary qualifiers (C99 6.5.15p6)
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ // Add qualifiers if necessary.
+ ImpCastExprToType(LHS, destType, CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(RHS, destType, CK_BitCast);
+ return destType;
+ }
+ if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ // Add qualifiers if necessary.
+ ImpCastExprToType(RHS, destType, CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(LHS, destType, CK_BitCast);
+ return destType;
+ }
+
+ if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+ // Two identical pointer types are always compatible.
+ return LHSTy;
+ }
+ if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
+ rhptee.getUnqualifiedType())) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ // In this situation, we assume void* type. No especially good
+ // reason, but this is what gcc does, and we do have to pick
+ // to get a consistent AST.
+ QualType incompatTy = Context.getPointerType(Context.VoidTy);
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ return incompatTy;
+ }
+ // The pointer types are compatible.
+ // C99 6.5.15p6: If both operands are pointers to compatible types *or* to
+ // differently qualified versions of compatible types, the result type is
+ // a pointer to an appropriately qualified version of the *composite*
+ // type.
+ // FIXME: Need to calculate the composite type.
+ // FIXME: Need to add qualifiers
+ ImpCastExprToType(LHS, LHSTy, CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ return LHSTy;
+ }
+
+ // GCC compatibility: soften pointer/integer mismatch. Note that
+ // null pointers have been filtered out by this point.
+ if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer);
+ return RHSTy;
+ }
+ if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer);
+ return LHSTy;
+ }
+
+ // Emit a better diagnostic if one of the expressions is a null pointer
+ // constant and the other is not a pointer type. In this case, the user most
+ // likely forgot to take the address of the other expression.
+ if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ return QualType();
+
+ // Otherwise, the operands are not compatible.
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ return QualType();
+}
+
+/// FindCompositeObjCPointerType - Helper method to find composite type of
+/// two objective-c pointer types of the two input expressions.
+QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
+ SourceLocation QuestionLoc) {
+ QualType LHSTy = LHS->getType();
+ QualType RHSTy = RHS->getType();
+
+ // Handle things like Class and struct objc_class*. Here we case the result
+ // to the pseudo-builtin, because that will be implicitly cast back to the
+ // redefinition type if an attempt is made to access its fields.
+ if (LHSTy->isObjCClassType() &&
+ (Context.hasSameType(RHSTy, Context.ObjCClassRedefinitionType))) {
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ return LHSTy;
+ }
+ if (RHSTy->isObjCClassType() &&
+ (Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) {
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ return RHSTy;
+ }
+ // And the same for struct objc_object* / id
+ if (LHSTy->isObjCIdType() &&
+ (Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) {
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ return LHSTy;
+ }
+ if (RHSTy->isObjCIdType() &&
+ (Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) {
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ return RHSTy;
+ }
+ // And the same for struct objc_selector* / SEL
+ if (Context.isObjCSelType(LHSTy) &&
+ (Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) {
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
+ return LHSTy;
+ }
+ if (Context.isObjCSelType(RHSTy) &&
+ (Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) {
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
+ return RHSTy;
+ }
+ // Check constraints for Objective-C object pointers types.
+ if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
+
+ if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
+ // Two identical object pointer types are always compatible.
+ return LHSTy;
+ }
+ const ObjCObjectPointerType *LHSOPT = LHSTy->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *RHSOPT = RHSTy->getAs<ObjCObjectPointerType>();
+ QualType compositeType = LHSTy;
+
+ // If both operands are interfaces and either operand can be
+ // assigned to the other, use that type as the composite
+ // type. This allows
+ // xxx ? (A*) a : (B*) b
+ // where B is a subclass of A.
+ //
+ // Additionally, as for assignment, if either type is 'id'
+ // allow silent coercion. Finally, if the types are
+ // incompatible then make sure to use 'id' as the composite
+ // type so the result is acceptable for sending messages to.
+
+ // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
+ // It could return the composite type.
+ if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
+ compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
+ } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
+ compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
+ } else if ((LHSTy->isObjCQualifiedIdType() ||
+ RHSTy->isObjCQualifiedIdType()) &&
+ Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
+ // Need to handle "id<xx>" explicitly.
+ // GCC allows qualified id and any Objective-C type to devolve to
+ // id. Currently localizing to here until clear this should be
+ // part of ObjCQualifiedIdTypesAreCompatible.
+ compositeType = Context.getObjCIdType();
+ } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
+ compositeType = Context.getObjCIdType();
+ } else if (!(compositeType =
+ Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull())
+ ;
+ else {
+ Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
+ << LHSTy << RHSTy
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ QualType incompatTy = Context.getObjCIdType();
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
+ return incompatTy;
+ }
+ // The object pointer types are compatible.
+ ImpCastExprToType(LHS, compositeType, CK_BitCast);
+ ImpCastExprToType(RHS, compositeType, CK_BitCast);
+ return compositeType;
+ }
+ // Check Objective-C object pointer types and 'void *'
+ if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
+ QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
+ QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ // Add qualifiers if necessary.
+ ImpCastExprToType(LHS, destType, CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(RHS, destType, CK_BitCast);
+ return destType;
+ }
+ if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
+ QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+ QualType destType = Context.getPointerType(destPointee);
+ // Add qualifiers if necessary.
+ ImpCastExprToType(RHS, destType, CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(LHS, destType, CK_BitCast);
+ return destType;
+ }
+ return QualType();
+}
+
+/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
+/// in the case of a the GNU conditional expr extension.
+ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr) {
+ // If this is the gnu "x ?: y" extension, analyze the types as though the LHS
+ // was the condition.
+ OpaqueValueExpr *opaqueValue = 0;
+ Expr *commonExpr = 0;
+ if (LHSExpr == 0) {
+ commonExpr = CondExpr;
+
+ // We usually want to apply unary conversions *before* saving, except
+ // in the special case of a C++ l-value conditional.
+ if (!(getLangOptions().CPlusPlus
+ && !commonExpr->isTypeDependent()
+ && commonExpr->getValueKind() == RHSExpr->getValueKind()
+ && commonExpr->isGLValue()
+ && commonExpr->isOrdinaryOrBitFieldObject()
+ && RHSExpr->isOrdinaryOrBitFieldObject()
+ && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
+ UsualUnaryConversions(commonExpr);
+ }
+
+ opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
+ commonExpr->getType(),
+ commonExpr->getValueKind(),
+ commonExpr->getObjectKind());
+ LHSExpr = CondExpr = opaqueValue;
+ }
+
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+ QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr,
+ VK, OK, QuestionLoc);
+ if (result.isNull())
+ return ExprError();
+
+ if (!commonExpr)
+ return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
+ LHSExpr, ColonLoc,
+ RHSExpr, result, VK, OK));
+
+ return Owned(new (Context)
+ BinaryConditionalOperator(commonExpr, opaqueValue, CondExpr, LHSExpr,
+ RHSExpr, QuestionLoc, ColonLoc, result, VK, OK));
+}
+
+// checkPointerTypesForAssignment - This is a very tricky routine (despite
+// being closely modeled after the C99 spec:-). The odd characteristic of this
+// routine is it effectively iqnores the qualifiers on the top level pointee.
+// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
+// FIXME: add a couple examples in this comment.
+static Sema::AssignConvertType
+checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
+ assert(lhsType.isCanonical() && "LHS not canonicalized!");
+ assert(rhsType.isCanonical() && "RHS not canonicalized!");
+
+ // get the "pointed to" type (ignoring qualifiers at the top level)
+ const Type *lhptee, *rhptee;
+ Qualifiers lhq, rhq;
+ llvm::tie(lhptee, lhq) = cast<PointerType>(lhsType)->getPointeeType().split();
+ llvm::tie(rhptee, rhq) = cast<PointerType>(rhsType)->getPointeeType().split();
+
+ Sema::AssignConvertType ConvTy = Sema::Compatible;
+
+ // C99 6.5.16.1p1: This following citation is common to constraints
+ // 3 & 4 (below). ...and the type *pointed to* by the left has all the
+ // qualifiers of the type *pointed to* by the right;
+ Qualifiers lq;
+
+ if (!lhq.compatiblyIncludes(rhq)) {
+ // Treat address-space mismatches as fatal. TODO: address subspaces
+ if (lhq.getAddressSpace() != rhq.getAddressSpace())
+ ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
+
+ // For GCC compatibility, other qualifier mismatches are treated
+ // as still compatible in C.
+ else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
+ }
+
+ // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
+ // incomplete type and the other is a pointer to a qualified or unqualified
+ // version of void...
+ if (lhptee->isVoidType()) {
+ if (rhptee->isIncompleteOrObjectType())
+ return ConvTy;
+
+ // As an extension, we allow cast to/from void* to function pointer.
+ assert(rhptee->isFunctionType());
+ return Sema::FunctionVoidPointer;
+ }
+
+ if (rhptee->isVoidType()) {
+ if (lhptee->isIncompleteOrObjectType())
+ return ConvTy;
+
+ // As an extension, we allow cast to/from void* to function pointer.
+ assert(lhptee->isFunctionType());
+ return Sema::FunctionVoidPointer;
+ }
+
+ // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
+ // unqualified versions of compatible types, ...
+ QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0);
+ if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
+ // Check if the pointee types are compatible ignoring the sign.
+ // We explicitly check for char so that we catch "char" vs
+ // "unsigned char" on systems where "char" is unsigned.
+ if (lhptee->isCharType())
+ ltrans = S.Context.UnsignedCharTy;
+ else if (lhptee->hasSignedIntegerRepresentation())
+ ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
+
+ if (rhptee->isCharType())
+ rtrans = S.Context.UnsignedCharTy;
+ else if (rhptee->hasSignedIntegerRepresentation())
+ rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
+
+ if (ltrans == rtrans) {
+ // Types are compatible ignoring the sign. Qualifier incompatibility
+ // takes priority over sign incompatibility because the sign
+ // warning can be disabled.
+ if (ConvTy != Sema::Compatible)
+ return ConvTy;
+
+ return Sema::IncompatiblePointerSign;
+ }
+
+ // If we are a multi-level pointer, it's possible that our issue is simply
+ // one of qualification - e.g. char ** -> const char ** is not allowed. If
+ // the eventual target type is the same and the pointers have the same
+ // level of indirection, this must be the issue.
+ if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
+ do {
+ lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr();
+ rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr();
+ } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
+
+ if (lhptee == rhptee)
+ return Sema::IncompatibleNestedPointerQualifiers;
+ }
+
+ // General pointer incompatibility takes priority over qualifiers.
+ return Sema::IncompatiblePointer;
+ }
+ return ConvTy;
+}
+
+/// checkBlockPointerTypesForAssignment - This routine determines whether two
+/// block pointer types are compatible or whether a block and normal pointer
+/// are compatible. It is more restrict than comparing two function pointer
+// types.
+static Sema::AssignConvertType
+checkBlockPointerTypesForAssignment(Sema &S, QualType lhsType,
+ QualType rhsType) {
+ assert(lhsType.isCanonical() && "LHS not canonicalized!");
+ assert(rhsType.isCanonical() && "RHS not canonicalized!");
+
+ QualType lhptee, rhptee;
+
+ // get the "pointed to" type (ignoring qualifiers at the top level)
+ lhptee = cast<BlockPointerType>(lhsType)->getPointeeType();
+ rhptee = cast<BlockPointerType>(rhsType)->getPointeeType();
+
+ // In C++, the types have to match exactly.
+ if (S.getLangOptions().CPlusPlus)
+ return Sema::IncompatibleBlockPointer;
+
+ Sema::AssignConvertType ConvTy = Sema::Compatible;
+
+ // For blocks we enforce that qualifiers are identical.
+ if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers())
+ ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
+
+ if (!S.Context.typesAreBlockPointerCompatible(lhsType, rhsType))
+ return Sema::IncompatibleBlockPointer;
+
+ return ConvTy;
+}
+
+/// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types
+/// for assignment compatibility.
+static Sema::AssignConvertType
+checkObjCPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) {
+ assert(lhsType.isCanonical() && "LHS was not canonicalized!");
+ assert(rhsType.isCanonical() && "RHS was not canonicalized!");
+
+ if (lhsType->isObjCBuiltinType()) {
+ // Class is not compatible with ObjC object pointers.
+ if (lhsType->isObjCClassType() && !rhsType->isObjCBuiltinType() &&
+ !rhsType->isObjCQualifiedClassType())
+ return Sema::IncompatiblePointer;
+ return Sema::Compatible;
+ }
+ if (rhsType->isObjCBuiltinType()) {
+ // Class is not compatible with ObjC object pointers.
+ if (rhsType->isObjCClassType() && !lhsType->isObjCBuiltinType() &&
+ !lhsType->isObjCQualifiedClassType())
+ return Sema::IncompatiblePointer;
+ return Sema::Compatible;
+ }
+ QualType lhptee =
+ lhsType->getAs<ObjCObjectPointerType>()->getPointeeType();
+ QualType rhptee =
+ rhsType->getAs<ObjCObjectPointerType>()->getPointeeType();
+
+ if (!lhptee.isAtLeastAsQualifiedAs(rhptee))
+ return Sema::CompatiblePointerDiscardsQualifiers;
+
+ if (S.Context.typesAreCompatible(lhsType, rhsType))
+ return Sema::Compatible;
+ if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType())
+ return Sema::IncompatibleObjCQualifiedId;
+ return Sema::IncompatiblePointer;
+}
+
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(SourceLocation Loc,
+ QualType lhsType, QualType rhsType) {
+ // Fake up an opaque expression. We don't actually care about what
+ // cast operations are required, so if CheckAssignmentConstraints
+ // adds casts to this they'll be wasted, but fortunately that doesn't
+ // usually happen on valid code.
+ OpaqueValueExpr rhs(Loc, rhsType, VK_RValue);
+ Expr *rhsPtr = &rhs;
+ CastKind K = CK_Invalid;
+
+ return CheckAssignmentConstraints(lhsType, rhsPtr, K);
+}
+
+/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
+/// has code to accommodate several GCC extensions when type checking
+/// pointers. Here are some objectionable examples that GCC considers warnings:
+///
+/// int a, *pint;
+/// short *pshort;
+/// struct foo *pfoo;
+///
+/// pint = pshort; // warning: assignment from incompatible pointer type
+/// a = pint; // warning: assignment makes integer from pointer without a cast
+/// pint = a; // warning: assignment makes pointer from integer without a cast
+/// pint = pfoo; // warning: assignment from incompatible pointer type
+///
+/// As a result, the code for dealing with pointers is more complex than the
+/// C99 spec dictates.
+///
+/// Sets 'Kind' for any result kind except Incompatible.
+Sema::AssignConvertType
+Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs,
+ CastKind &Kind) {
+ QualType rhsType = rhs->getType();
+
+ // Get canonical types. We're not formatting these types, just comparing
+ // them.
+ lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType();
+ rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType();
+
+ // Common case: no conversion required.
+ if (lhsType == rhsType) {
+ Kind = CK_NoOp;
+ return Compatible;
+ }
+
+ // If the left-hand side is a reference type, then we are in a
+ // (rare!) case where we've allowed the use of references in C,
+ // e.g., as a parameter type in a built-in function. In this case,
+ // just make sure that the type referenced is compatible with the
+ // right-hand side type. The caller is responsible for adjusting
+ // lhsType so that the resulting expression does not have reference
+ // type.
+ if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) {
+ if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType)) {
+ Kind = CK_LValueBitCast;
+ return Compatible;
+ }
+ return Incompatible;
+ }
+
+ // Allow scalar to ExtVector assignments, and assignments of an ExtVector type
+ // to the same ExtVector type.
+ if (lhsType->isExtVectorType()) {
+ if (rhsType->isExtVectorType())
+ return Incompatible;
+ if (rhsType->isArithmeticType()) {
+ // CK_VectorSplat does T -> vector T, so first cast to the
+ // element type.
+ QualType elType = cast<ExtVectorType>(lhsType)->getElementType();
+ if (elType != rhsType) {
+ Kind = PrepareScalarCast(*this, rhs, elType);
+ ImpCastExprToType(rhs, elType, Kind);
+ }
+ Kind = CK_VectorSplat;
+ return Compatible;
+ }
+ }
+
+ // Conversions to or from vector type.
+ if (lhsType->isVectorType() || rhsType->isVectorType()) {
+ if (lhsType->isVectorType() && rhsType->isVectorType()) {
+ // Allow assignments of an AltiVec vector type to an equivalent GCC
+ // vector type and vice versa
+ if (Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
+
+ // If we are allowing lax vector conversions, and LHS and RHS are both
+ // vectors, the total size only needs to be the same. This is a bitcast;
+ // no bits are changed but the result type is different.
+ if (getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))) {
+ Kind = CK_BitCast;
+ return IncompatibleVectors;
+ }
+ }
+ return Incompatible;
+ }
+
+ // Arithmetic conversions.
+ if (lhsType->isArithmeticType() && rhsType->isArithmeticType() &&
+ !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) {
+ Kind = PrepareScalarCast(*this, rhs, lhsType);
+ return Compatible;
+ }
+
+ // Conversions to normal pointers.
+ if (const PointerType *lhsPointer = dyn_cast<PointerType>(lhsType)) {
+ // U* -> T*
+ if (isa<PointerType>(rhsType)) {
+ Kind = CK_BitCast;
+ return checkPointerTypesForAssignment(*this, lhsType, rhsType);
+ }
+
+ // int -> T*
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null?
+ return IntToPointer;
+ }
+
+ // C pointers are not compatible with ObjC object pointers,
+ // with two exceptions:
+ if (isa<ObjCObjectPointerType>(rhsType)) {
+ // - conversions to void*
+ if (lhsPointer->getPointeeType()->isVoidType()) {
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return Compatible;
+ }
+
+ // - conversions from 'Class' to the redefinition type
+ if (rhsType->isObjCClassType() &&
+ Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
+
+ Kind = CK_BitCast;
+ return IncompatiblePointer;
+ }
+
+ // U^ -> void*
+ if (rhsType->getAs<BlockPointerType>()) {
+ if (lhsPointer->getPointeeType()->isVoidType()) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
+ }
+
+ return Incompatible;
+ }
+
+ // Conversions to block pointers.
+ if (isa<BlockPointerType>(lhsType)) {
+ // U^ -> T^
+ if (rhsType->isBlockPointerType()) {
+ Kind = CK_AnyPointerToBlockPointerCast;
+ return checkBlockPointerTypesForAssignment(*this, lhsType, rhsType);
+ }
+
+ // int or null -> T^
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null
+ return IntToBlockPointer;
+ }
+
+ // id -> T^
+ if (getLangOptions().ObjC1 && rhsType->isObjCIdType()) {
+ Kind = CK_AnyPointerToBlockPointerCast;
+ return Compatible;
+ }
+
+ // void* -> T^
+ if (const PointerType *RHSPT = rhsType->getAs<PointerType>())
+ if (RHSPT->getPointeeType()->isVoidType()) {
+ Kind = CK_AnyPointerToBlockPointerCast;
+ return Compatible;
+ }
+
+ return Incompatible;
+ }
+
+ // Conversions to Objective-C pointers.
+ if (isa<ObjCObjectPointerType>(lhsType)) {
+ // A* -> B*
+ if (rhsType->isObjCObjectPointerType()) {
+ Kind = CK_BitCast;
+ return checkObjCPointerTypesForAssignment(*this, lhsType, rhsType);
+ }
+
+ // int or null -> A*
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null
+ return IntToPointer;
+ }
+
+ // In general, C pointers are not compatible with ObjC object pointers,
+ // with two exceptions:
+ if (isa<PointerType>(rhsType)) {
+ // - conversions from 'void*'
+ if (rhsType->isVoidPointerType()) {
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return Compatible;
+ }
+
+ // - conversions to 'Class' from its redefinition type
+ if (lhsType->isObjCClassType() &&
+ Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType)) {
+ Kind = CK_BitCast;
+ return Compatible;
+ }
+
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return IncompatiblePointer;
+ }
+
+ // T^ -> A*
+ if (rhsType->isBlockPointerType()) {
+ Kind = CK_AnyPointerToObjCPointerCast;
+ return Compatible;
+ }
+
+ return Incompatible;
+ }
+
+ // Conversions from pointers that are not covered by the above.
+ if (isa<PointerType>(rhsType)) {
+ // T* -> _Bool
+ if (lhsType == Context.BoolTy) {
+ Kind = CK_PointerToBoolean;
+ return Compatible;
+ }
+
+ // T* -> int
+ if (lhsType->isIntegerType()) {
+ Kind = CK_PointerToIntegral;
+ return PointerToInt;
+ }
+
+ return Incompatible;
+ }
+
+ // Conversions from Objective-C pointers that are not covered by the above.
+ if (isa<ObjCObjectPointerType>(rhsType)) {
+ // T* -> _Bool
+ if (lhsType == Context.BoolTy) {
+ Kind = CK_PointerToBoolean;
+ return Compatible;
+ }
+
+ // T* -> int
+ if (lhsType->isIntegerType()) {
+ Kind = CK_PointerToIntegral;
+ return PointerToInt;
+ }
+
+ return Incompatible;
+ }
+
+ // struct A -> struct B
+ if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
+ if (Context.typesAreCompatible(lhsType, rhsType)) {
+ Kind = CK_NoOp;
+ return Compatible;
+ }
+ }
+
+ return Incompatible;
+}
+
+/// \brief Constructs a transparent union from an expression that is
+/// used to initialize the transparent union.
+static void ConstructTransparentUnion(ASTContext &C, Expr *&E,
+ QualType UnionType, FieldDecl *Field) {
+ // Build an initializer list that designates the appropriate member
+ // of the transparent union.
+ InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
+ &E, 1,
+ SourceLocation());
+ Initializer->setType(UnionType);
+ Initializer->setInitializedFieldInUnion(Field);
+
+ // Build a compound literal constructing a value of the transparent
+ // union type from this initializer list.
+ TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
+ E = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
+ VK_RValue, Initializer, false);
+}
+
+Sema::AssignConvertType
+Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
+ QualType FromType = rExpr->getType();
+
+ // If the ArgType is a Union type, we want to handle a potential
+ // transparent_union GCC extension.
+ const RecordType *UT = ArgType->getAsUnionType();
+ if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ return Incompatible;
+
+ // The field to initialize within the transparent union.
+ RecordDecl *UD = UT->getDecl();
+ FieldDecl *InitField = 0;
+ // It's compatible if the expression matches any of the fields.
+ for (RecordDecl::field_iterator it = UD->field_begin(),
+ itend = UD->field_end();
+ it != itend; ++it) {
+ if (it->getType()->isPointerType()) {
+ // If the transparent union contains a pointer type, we allow:
+ // 1) void pointer
+ // 2) null pointer constant
+ if (FromType->isPointerType())
+ if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+ ImpCastExprToType(rExpr, it->getType(), CK_BitCast);
+ InitField = *it;
+ break;
+ }
+
+ if (rExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ ImpCastExprToType(rExpr, it->getType(), CK_NullToPointer);
+ InitField = *it;
+ break;
+ }
+ }
+
+ Expr *rhs = rExpr;
+ CastKind Kind = CK_Invalid;
+ if (CheckAssignmentConstraints(it->getType(), rhs, Kind)
+ == Compatible) {
+ ImpCastExprToType(rhs, it->getType(), Kind);
+ rExpr = rhs;
+ InitField = *it;
+ break;
+ }
+ }
+
+ if (!InitField)
+ return Incompatible;
+
+ ConstructTransparentUnion(Context, rExpr, ArgType, InitField);
+ return Compatible;
+}
+
+Sema::AssignConvertType
+Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
+ if (getLangOptions().CPlusPlus) {
+ if (!lhsType->isRecordType()) {
+ // C++ 5.17p3: If the left operand is not of class type, the
+ // expression is implicitly converted (C++ 4) to the
+ // cv-unqualified type of the left operand.
+ if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(),
+ AA_Assigning))
+ return Incompatible;
+ return Compatible;
+ }
+
+ // FIXME: Currently, we fall through and treat C++ classes like C
+ // structures.
+ }
+
+ // C99 6.5.16.1p1: the left operand is a pointer and the right is
+ // a null pointer constant.
+ if ((lhsType->isPointerType() ||
+ lhsType->isObjCObjectPointerType() ||
+ lhsType->isBlockPointerType())
+ && rExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ ImpCastExprToType(rExpr, lhsType, CK_NullToPointer);
+ return Compatible;
+ }
+
+ // This check seems unnatural, however it is necessary to ensure the proper
+ // conversion of functions/arrays. If the conversion were done for all
+ // DeclExpr's (created by ActOnIdExpression), it would mess up the unary
+ // expressions that suppress this implicit conversion (&, sizeof).
+ //
+ // Suppress this for references: C++ 8.5.3p5.
+ if (!lhsType->isReferenceType())
+ DefaultFunctionArrayLvalueConversion(rExpr);
+
+ CastKind Kind = CK_Invalid;
+ Sema::AssignConvertType result =
+ CheckAssignmentConstraints(lhsType, rExpr, Kind);
+
+ // C99 6.5.16.1p2: The value of the right operand is converted to the
+ // type of the assignment expression.
+ // CheckAssignmentConstraints allows the left-hand side to be a reference,
+ // so that we can use references in built-in functions even in C.
+ // The getNonReferenceType() call makes sure that the resulting expression
+ // does not have reference type.
+ if (result != Incompatible && rExpr->getType() != lhsType)
+ ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind);
+ return result;
+}
+
+QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+ Diag(Loc, diag::err_typecheck_invalid_operands)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+}
+
+QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType lhsType =
+ Context.getCanonicalType(lex->getType()).getUnqualifiedType();
+ QualType rhsType =
+ Context.getCanonicalType(rex->getType()).getUnqualifiedType();
+
+ // If the vector types are identical, return.
+ if (lhsType == rhsType)
+ return lhsType;
+
+ // Handle the case of a vector & extvector type of the same size and element
+ // type. It would be nice if we only had one vector type someday.
+ if (getLangOptions().LaxVectorConversions) {
+ if (const VectorType *LV = lhsType->getAs<VectorType>()) {
+ if (const VectorType *RV = rhsType->getAs<VectorType>()) {
+ if (LV->getElementType() == RV->getElementType() &&
+ LV->getNumElements() == RV->getNumElements()) {
+ if (lhsType->isExtVectorType()) {
+ ImpCastExprToType(rex, lhsType, CK_BitCast);
+ return lhsType;
+ }
+
+ ImpCastExprToType(lex, rhsType, CK_BitCast);
+ return rhsType;
+ } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){
+ // If we are allowing lax vector conversions, and LHS and RHS are both
+ // vectors, the total size only needs to be the same. This is a
+ // bitcast; no bits are changed but the result type is different.
+ ImpCastExprToType(rex, lhsType, CK_BitCast);
+ return lhsType;
+ }
+ }
+ }
+ }
+
+ // Handle the case of equivalent AltiVec and GCC vector types
+ if (lhsType->isVectorType() && rhsType->isVectorType() &&
+ Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+ ImpCastExprToType(lex, rhsType, CK_BitCast);
+ return rhsType;
+ }
+
+ // Canonicalize the ExtVector to the LHS, remember if we swapped so we can
+ // swap back (so that we don't reverse the inputs to a subtract, for instance.
+ bool swapped = false;
+ if (rhsType->isExtVectorType()) {
+ swapped = true;
+ std::swap(rex, lex);
+ std::swap(rhsType, lhsType);
+ }
+
+ // Handle the case of an ext vector and scalar.
+ if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) {
+ QualType EltTy = LV->getElementType();
+ if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
+ int order = Context.getIntegerTypeOrder(EltTy, rhsType);
+ if (order > 0)
+ ImpCastExprToType(rex, EltTy, CK_IntegralCast);
+ if (order >= 0) {
+ ImpCastExprToType(rex, lhsType, CK_VectorSplat);
+ if (swapped) std::swap(rex, lex);
+ return lhsType;
+ }
+ }
+ if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
+ rhsType->isRealFloatingType()) {
+ int order = Context.getFloatingTypeOrder(EltTy, rhsType);
+ if (order > 0)
+ ImpCastExprToType(rex, EltTy, CK_FloatingCast);
+ if (order >= 0) {
+ ImpCastExprToType(rex, lhsType, CK_VectorSplat);
+ if (swapped) std::swap(rex, lex);
+ return lhsType;
+ }
+ }
+ }
+
+ // Vectors of different size or scalar and non-ext-vector are errors.
+ Diag(Loc, diag::err_typecheck_vector_not_convertable)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+}
+
+QualType Sema::CheckMultiplyDivideOperands(
+ Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign, bool isDiv) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(Loc, lex, rex);
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (!lex->getType()->isArithmeticType() ||
+ !rex->getType()->isArithmeticType())
+ return InvalidOperands(Loc, lex, rex);
+
+ // Check for division by zero.
+ if (isDiv &&
+ rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero)
+ << rex->getSourceRange());
+
+ return compType;
+}
+
+QualType Sema::CheckRemainderOperands(
+ Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
+ return CheckVectorOperands(Loc, lex, rex);
+ return InvalidOperands(Loc, lex, rex);
+ }
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+ return InvalidOperands(Loc, lex, rex);
+
+ // Check for remainder by zero.
+ if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero)
+ << rex->getSourceRange());
+
+ return compType;
+}
+
+QualType Sema::CheckAdditionOperands( // C99 6.5.6
+ Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ QualType compType = CheckVectorOperands(Loc, lex, rex);
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
+
+ QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+
+ // handle the common case first (both operands are arithmetic).
+ if (lex->getType()->isArithmeticType() &&
+ rex->getType()->isArithmeticType()) {
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
+
+ // Put any potential pointer into PExp
+ Expr* PExp = lex, *IExp = rex;
+ if (IExp->getType()->isAnyPointerType())
+ std::swap(PExp, IExp);
+
+ if (PExp->getType()->isAnyPointerType()) {
+
+ if (IExp->getType()->isIntegerType()) {
+ QualType PointeeTy = PExp->getType()->getPointeeType();
+
+ // Check for arithmetic on pointers to incomplete types.
+ if (PointeeTy->isVoidType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ }
+
+ // GNU extension: arithmetic on pointer to void
+ Diag(Loc, diag::ext_gnu_void_ptr)
+ << lex->getSourceRange() << rex->getSourceRange();
+ } else if (PointeeTy->isFunctionType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+ << lex->getType() << lex->getSourceRange();
+ return QualType();
+ }
+
+ // GNU extension: arithmetic on pointer to function
+ Diag(Loc, diag::ext_gnu_ptr_func_arith)
+ << lex->getType() << lex->getSourceRange();
+ } else {
+ // Check if we require a complete type.
+ if (((PExp->getType()->isPointerType() &&
+ !PExp->getType()->isDependentType()) ||
+ PExp->getType()->isObjCObjectPointerType()) &&
+ RequireCompleteType(Loc, PointeeTy,
+ PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+ << PExp->getSourceRange()
+ << PExp->getType()))
+ return QualType();
+ }
+ // Diagnose bad cases where we step over interface counts.
+ if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
+ Diag(Loc, diag::err_arithmetic_nonfragile_interface)
+ << PointeeTy << PExp->getSourceRange();
+ return QualType();
+ }
+
+ if (CompLHSTy) {
+ QualType LHSTy = Context.isPromotableBitField(lex);
+ if (LHSTy.isNull()) {
+ LHSTy = lex->getType();
+ if (LHSTy->isPromotableIntegerType())
+ LHSTy = Context.getPromotedIntegerType(LHSTy);
+ }
+ *CompLHSTy = LHSTy;
+ }
+ return PExp->getType();
+ }
+ }
+
+ return InvalidOperands(Loc, lex, rex);
+}
+
+// C99 6.5.6
+QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
+ SourceLocation Loc, QualType* CompLHSTy) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ QualType compType = CheckVectorOperands(Loc, lex, rex);
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
+
+ QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
+
+ // Enforce type constraints: C99 6.5.6p3.
+
+ // Handle the common case first (both operands are arithmetic).
+ if (lex->getType()->isArithmeticType()
+ && rex->getType()->isArithmeticType()) {
+ if (CompLHSTy) *CompLHSTy = compType;
+ return compType;
+ }
+
+ // Either ptr - int or ptr - ptr.
+ if (lex->getType()->isAnyPointerType()) {
+ QualType lpointee = lex->getType()->getPointeeType();
+
+ // The LHS must be an completely-defined object type.
+
+ bool ComplainAboutVoid = false;
+ Expr *ComplainAboutFunc = 0;
+ if (lpointee->isVoidType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ }
+
+ // GNU C extension: arithmetic on pointer to void
+ ComplainAboutVoid = true;
+ } else if (lpointee->isFunctionType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+ << lex->getType() << lex->getSourceRange();
+ return QualType();
+ }
+
+ // GNU C extension: arithmetic on pointer to function
+ ComplainAboutFunc = lex;
+ } else if (!lpointee->isDependentType() &&
+ RequireCompleteType(Loc, lpointee,
+ PDiag(diag::err_typecheck_sub_ptr_object)
+ << lex->getSourceRange()
+ << lex->getType()))
+ return QualType();
+
+ // Diagnose bad cases where we step over interface counts.
+ if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
+ Diag(Loc, diag::err_arithmetic_nonfragile_interface)
+ << lpointee << lex->getSourceRange();
+ return QualType();
+ }
+
+ // The result type of a pointer-int computation is the pointer type.
+ if (rex->getType()->isIntegerType()) {
+ if (ComplainAboutVoid)
+ Diag(Loc, diag::ext_gnu_void_ptr)
+ << lex->getSourceRange() << rex->getSourceRange();
+ if (ComplainAboutFunc)
+ Diag(Loc, diag::ext_gnu_ptr_func_arith)
+ << ComplainAboutFunc->getType()
+ << ComplainAboutFunc->getSourceRange();
+
+ if (CompLHSTy) *CompLHSTy = lex->getType();
+ return lex->getType();
+ }
+
+ // Handle pointer-pointer subtractions.
+ if (const PointerType *RHSPTy = rex->getType()->getAs<PointerType>()) {
+ QualType rpointee = RHSPTy->getPointeeType();
+
+ // RHS must be a completely-type object type.
+ // Handle the GNU void* extension.
+ if (rpointee->isVoidType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ }
+
+ ComplainAboutVoid = true;
+ } else if (rpointee->isFunctionType()) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
+ << rex->getType() << rex->getSourceRange();
+ return QualType();
+ }
+
+ // GNU extension: arithmetic on pointer to function
+ if (!ComplainAboutFunc)
+ ComplainAboutFunc = rex;
+ } else if (!rpointee->isDependentType() &&
+ RequireCompleteType(Loc, rpointee,
+ PDiag(diag::err_typecheck_sub_ptr_object)
+ << rex->getSourceRange()
+ << rex->getType()))
+ return QualType();
+
+ if (getLangOptions().CPlusPlus) {
+ // Pointee types must be the same: C++ [expr.add]
+ if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
+ Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ }
+ } else {
+ // Pointee types must be compatible C99 6.5.6p3
+ if (!Context.typesAreCompatible(
+ Context.getCanonicalType(lpointee).getUnqualifiedType(),
+ Context.getCanonicalType(rpointee).getUnqualifiedType())) {
+ Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
+ << lex->getType() << rex->getType()
+ << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ }
+ }
+
+ if (ComplainAboutVoid)
+ Diag(Loc, diag::ext_gnu_void_ptr)
+ << lex->getSourceRange() << rex->getSourceRange();
+ if (ComplainAboutFunc)
+ Diag(Loc, diag::ext_gnu_ptr_func_arith)
+ << ComplainAboutFunc->getType()
+ << ComplainAboutFunc->getSourceRange();
+
+ if (CompLHSTy) *CompLHSTy = lex->getType();
+ return Context.getPointerDiffType();
+ }
+ }
+
+ return InvalidOperands(Loc, lex, rex);
+}
+
+static bool isScopedEnumerationType(QualType T) {
+ if (const EnumType *ET = dyn_cast<EnumType>(T))
+ return ET->getDecl()->isScoped();
+ return false;
+}
+
+// C99 6.5.7
+QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+ bool isCompAssign) {
+ // C99 6.5.7p2: Each of the operands shall have integer type.
+ if (!lex->getType()->hasIntegerRepresentation() ||
+ !rex->getType()->hasIntegerRepresentation())
+ return InvalidOperands(Loc, lex, rex);
+
+ // C++0x: Don't allow scoped enums. FIXME: Use something better than
+ // hasIntegerRepresentation() above instead of this.
+ if (isScopedEnumerationType(lex->getType()) ||
+ isScopedEnumerationType(rex->getType())) {
+ return InvalidOperands(Loc, lex, rex);
+ }
+
+ // Vector shifts promote their scalar inputs to vector type.
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorOperands(Loc, lex, rex);
+
+ // Shifts don't perform usual arithmetic conversions, they just do integer
+ // promotions on each operand. C99 6.5.7p3
+
+ // For the LHS, do usual unary conversions, but then reset them away
+ // if this is a compound assignment.
+ Expr *old_lex = lex;
+ UsualUnaryConversions(lex);
+ QualType LHSTy = lex->getType();
+ if (isCompAssign) lex = old_lex;
+
+ // The RHS is simpler.
+ UsualUnaryConversions(rex);
+
+ // Sanity-check shift operands
+ llvm::APSInt Right;
+ // Check right/shifter operand
+ if (!rex->isValueDependent() &&
+ rex->isIntegerConstantExpr(Right, Context)) {
+ if (Right.isNegative())
+ Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+ else {
+ llvm::APInt LeftBits(Right.getBitWidth(),
+ Context.getTypeSize(lex->getType()));
+ if (Right.uge(LeftBits))
+ Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+ }
+ }
+
+ // "The type of the result is that of the promoted left operand."
+ return LHSTy;
+}
+
+static bool IsWithinTemplateSpecialization(Decl *D) {
+ if (DeclContext *DC = D->getDeclContext()) {
+ if (isa<ClassTemplateSpecializationDecl>(DC))
+ return true;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+ return FD->isFunctionTemplateSpecialization();
+ }
+ return false;
+}
+
+// C99 6.5.8, C++ [expr.rel]
+QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
+ unsigned OpaqueOpc, bool isRelational) {
+ BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
+
+ // Handle vector comparisons separately.
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
+ return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
+
+ QualType lType = lex->getType();
+ QualType rType = rex->getType();
+
+ Expr *LHSStripped = lex->IgnoreParenImpCasts();
+ Expr *RHSStripped = rex->IgnoreParenImpCasts();
+ QualType LHSStrippedType = LHSStripped->getType();
+ QualType RHSStrippedType = RHSStripped->getType();
+
+ // Two different enums will raise a warning when compared.
+ if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) {
+ if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) {
+ if (LHSEnumType->getDecl()->getIdentifier() &&
+ RHSEnumType->getDecl()->getIdentifier() &&
+ !Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
+ Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
+ << LHSStrippedType << RHSStrippedType
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+ }
+ }
+
+ if (!lType->hasFloatingRepresentation() &&
+ !(lType->isBlockPointerType() && isRelational) &&
+ !lex->getLocStart().isMacroID() &&
+ !rex->getLocStart().isMacroID()) {
+ // For non-floating point types, check for self-comparisons of the form
+ // x == x, x != x, x < x, etc. These always evaluate to a constant, and
+ // often indicate logic errors in the program.
+ //
+ // NOTE: Don't warn about comparison expressions resulting from macro
+ // expansion. Also don't warn about comparisons which are only self
+ // comparisons within a template specialization. The warnings should catch
+ // obvious cases in the definition of the template anyways. The idea is to
+ // warn when the typed comparison operator will always evaluate to the same
+ // result.
+ if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
+ if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
+ if (DRL->getDecl() == DRR->getDecl() &&
+ !IsWithinTemplateSpecialization(DRL->getDecl())) {
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << (Opc == BO_EQ
+ || Opc == BO_LE
+ || Opc == BO_GE));
+ } else if (lType->isArrayType() && rType->isArrayType() &&
+ !DRL->getDecl()->getType()->isReferenceType() &&
+ !DRR->getDecl()->getType()->isReferenceType()) {
+ // what is it always going to eval to?
+ char always_evals_to;
+ switch(Opc) {
+ case BO_EQ: // e.g. array1 == array2
+ always_evals_to = 0; // false
+ break;
+ case BO_NE: // e.g. array1 != array2
+ always_evals_to = 1; // true
+ break;
+ default:
+ // best we can say is 'a constant'
+ always_evals_to = 2; // e.g. array1 <= array2
+ break;
+ }
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << always_evals_to);
+ }
+ }
+ }
+
+ if (isa<CastExpr>(LHSStripped))
+ LHSStripped = LHSStripped->IgnoreParenCasts();
+ if (isa<CastExpr>(RHSStripped))
+ RHSStripped = RHSStripped->IgnoreParenCasts();
+
+ // Warn about comparisons against a string constant (unless the other
+ // operand is null), the user probably wants strcmp.
+ Expr *literalString = 0;
+ Expr *literalStringStripped = 0;
+ if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+ !RHSStripped->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ literalString = lex;
+ literalStringStripped = LHSStripped;
+ } else if ((isa<StringLiteral>(RHSStripped) ||
+ isa<ObjCEncodeExpr>(RHSStripped)) &&
+ !LHSStripped->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull)) {
+ literalString = rex;
+ literalStringStripped = RHSStripped;
+ }
+
+ if (literalString) {
+ std::string resultComparison;
+ switch (Opc) {
+ case BO_LT: resultComparison = ") < 0"; break;
+ case BO_GT: resultComparison = ") > 0"; break;
+ case BO_LE: resultComparison = ") <= 0"; break;
+ case BO_GE: resultComparison = ") >= 0"; break;
+ case BO_EQ: resultComparison = ") == 0"; break;
+ case BO_NE: resultComparison = ") != 0"; break;
+ default: assert(false && "Invalid comparison operator");
+ }
+
+ DiagRuntimeBehavior(Loc,
+ PDiag(diag::warn_stringcompare)
+ << isa<ObjCEncodeExpr>(literalStringStripped)
+ << literalString->getSourceRange());
+ }
+ }
+
+ // C99 6.5.8p3 / C99 6.5.9p4
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ UsualArithmeticConversions(lex, rex);
+ else {
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+ }
+
+ lType = lex->getType();
+ rType = rex->getType();
+
+ // The result of comparisons is 'bool' in C++, 'int' in C.
+ QualType ResultTy = Context.getLogicalOperationType();
+
+ if (isRelational) {
+ if (lType->isRealType() && rType->isRealType())
+ return ResultTy;
+ } else {
+ // Check for comparisons of floating point operands using != and ==.
+ if (lType->hasFloatingRepresentation())
+ CheckFloatComparison(Loc,lex,rex);
+
+ if (lType->isArithmeticType() && rType->isArithmeticType())
+ return ResultTy;
+ }
+
+ bool LHSIsNull = lex->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull);
+ bool RHSIsNull = rex->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull);
+
+ // All of the following pointer-related warnings are GCC extensions, except
+ // when handling null pointer constants.
+ if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
+ QualType LCanPointeeTy =
+ Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType());
+ QualType RCanPointeeTy =
+ Context.getCanonicalType(rType->getAs<PointerType>()->getPointeeType());
+
+ if (getLangOptions().CPlusPlus) {
+ if (LCanPointeeTy == RCanPointeeTy)
+ return ResultTy;
+ if (!isRelational &&
+ (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+ // Valid unless comparison between non-null pointer and function pointer
+ // This is a gcc extension compatibility comparison.
+ // In a SFINAE context, we treat this as a hard error to maintain
+ // conformance with the C++ standard.
+ if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+ && !LHSIsNull && !RHSIsNull) {
+ Diag(Loc,
+ isSFINAEContext()?
+ diag::err_typecheck_comparison_of_fptr_to_void
+ : diag::ext_typecheck_comparison_of_fptr_to_void)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+
+ if (isSFINAEContext())
+ return QualType();
+
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+ }
+
+ // C++ [expr.rel]p2:
+ // [...] Pointer conversions (4.10) and qualification
+ // conversions (4.4) are performed on pointer operands (or on
+ // a pointer operand and a null pointer constant) to bring
+ // them to their composite pointer type. [...]
+ //
+ // C++ [expr.eq]p1 uses the same notion for (in)equality
+ // comparisons of pointers.
+ bool NonStandardCompositeType = false;
+ QualType T = FindCompositePointerType(Loc, lex, rex,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
+ if (T.isNull()) {
+ Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ } else if (NonStandardCompositeType) {
+ Diag(Loc,
+ diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
+ << lType << rType << T
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+
+ ImpCastExprToType(lex, T, CK_BitCast);
+ ImpCastExprToType(rex, T, CK_BitCast);
+ return ResultTy;
+ }
+ // C99 6.5.9p2 and C99 6.5.8p2
+ if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
+ RCanPointeeTy.getUnqualifiedType())) {
+ // Valid unless a relational comparison of function pointers
+ if (isRelational && LCanPointeeTy->isFunctionType()) {
+ Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ } else if (!isRelational &&
+ (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+ // Valid unless comparison between non-null pointer and function pointer
+ if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+ && !LHSIsNull && !RHSIsNull) {
+ Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ } else {
+ // Invalid
+ Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ if (LCanPointeeTy != RCanPointeeTy)
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ // Comparison of nullptr_t with itself.
+ if (lType->isNullPtrType() && rType->isNullPtrType())
+ return ResultTy;
+
+ // Comparison of pointers with null pointer constants and equality
+ // comparisons of member pointers to null pointer constants.
+ if (RHSIsNull &&
+ ((lType->isPointerType() || lType->isNullPtrType()) ||
+ (!isRelational && lType->isMemberPointerType()))) {
+ ImpCastExprToType(rex, lType,
+ lType->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_NullToPointer);
+ return ResultTy;
+ }
+ if (LHSIsNull &&
+ ((rType->isPointerType() || rType->isNullPtrType()) ||
+ (!isRelational && rType->isMemberPointerType()))) {
+ ImpCastExprToType(lex, rType,
+ rType->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_NullToPointer);
+ return ResultTy;
+ }
+
+ // Comparison of member pointers.
+ if (!isRelational &&
+ lType->isMemberPointerType() && rType->isMemberPointerType()) {
+ // C++ [expr.eq]p2:
+ // In addition, pointers to members can be compared, or a pointer to
+ // member and a null pointer constant. Pointer to member conversions
+ // (4.11) and qualification conversions (4.4) are performed to bring
+ // them to a common type. If one operand is a null pointer constant,
+ // the common type is the type of the other operand. Otherwise, the
+ // common type is a pointer to member type similar (4.4) to the type
+ // of one of the operands, with a cv-qualification signature (4.4)
+ // that is the union of the cv-qualification signatures of the operand
+ // types.
+ bool NonStandardCompositeType = false;
+ QualType T = FindCompositePointerType(Loc, lex, rex,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
+ if (T.isNull()) {
+ Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ return QualType();
+ } else if (NonStandardCompositeType) {
+ Diag(Loc,
+ diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
+ << lType << rType << T
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+
+ ImpCastExprToType(lex, T, CK_BitCast);
+ ImpCastExprToType(rex, T, CK_BitCast);
+ return ResultTy;
+ }
+ }
+
+ // Handle block pointer types.
+ if (!isRelational && lType->isBlockPointerType() && rType->isBlockPointerType()) {
+ QualType lpointee = lType->getAs<BlockPointerType>()->getPointeeType();
+ QualType rpointee = rType->getAs<BlockPointerType>()->getPointeeType();
+
+ if (!LHSIsNull && !RHSIsNull &&
+ !Context.typesAreCompatible(lpointee, rpointee)) {
+ Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+ // Allow block pointers to be compared with null pointer constants.
+ if (!isRelational
+ && ((lType->isBlockPointerType() && rType->isPointerType())
+ || (lType->isPointerType() && rType->isBlockPointerType()))) {
+ if (!LHSIsNull && !RHSIsNull) {
+ if (!((rType->isPointerType() && rType->getAs<PointerType>()
+ ->getPointeeType()->isVoidType())
+ || (lType->isPointerType() && lType->getAs<PointerType>()
+ ->getPointeeType()->isVoidType())))
+ Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+
+ if ((lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType())) {
+ if (lType->isPointerType() || rType->isPointerType()) {
+ const PointerType *LPT = lType->getAs<PointerType>();
+ const PointerType *RPT = rType->getAs<PointerType>();
+ bool LPtrToVoid = LPT ?
+ Context.getCanonicalType(LPT->getPointeeType())->isVoidType() : false;
+ bool RPtrToVoid = RPT ?
+ Context.getCanonicalType(RPT->getPointeeType())->isVoidType() : false;
+
+ if (!LPtrToVoid && !RPtrToVoid &&
+ !Context.typesAreCompatible(lType, rType)) {
+ Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ }
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+ if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {
+ if (!Context.areComparableObjCPointerTypes(lType, rType))
+ Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ ImpCastExprToType(rex, lType, CK_BitCast);
+ return ResultTy;
+ }
+ }
+ if ((lType->isAnyPointerType() && rType->isIntegerType()) ||
+ (lType->isIntegerType() && rType->isAnyPointerType())) {
+ unsigned DiagID = 0;
+ bool isError = false;
+ if ((LHSIsNull && lType->isIntegerType()) ||
+ (RHSIsNull && rType->isIntegerType())) {
+ if (isRelational && !getLangOptions().CPlusPlus)
+ DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+ } else if (isRelational && !getLangOptions().CPlusPlus)
+ DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+ else if (getLangOptions().CPlusPlus) {
+ DiagID = diag::err_typecheck_comparison_of_pointer_integer;
+ isError = true;
+ } else
+ DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
+
+ if (DiagID) {
+ Diag(Loc, DiagID)
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ if (isError)
+ return QualType();
+ }
+
+ if (lType->isIntegerType())
+ ImpCastExprToType(lex, rType,
+ LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
+ else
+ ImpCastExprToType(rex, lType,
+ RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
+ return ResultTy;
+ }
+
+ // Handle block pointers.
+ if (!isRelational && RHSIsNull
+ && lType->isBlockPointerType() && rType->isIntegerType()) {
+ ImpCastExprToType(rex, lType, CK_NullToPointer);
+ return ResultTy;
+ }
+ if (!isRelational && LHSIsNull
+ && lType->isIntegerType() && rType->isBlockPointerType()) {
+ ImpCastExprToType(lex, rType, CK_NullToPointer);
+ return ResultTy;
+ }
+ return InvalidOperands(Loc, lex, rex);
+}
+
+/// CheckVectorCompareOperands - vector comparisons are a clang extension that
+/// operates on extended vector types. Instead of producing an IntTy result,
+/// like a scalar comparison, a vector comparison produces a vector of integer
+/// types.
+QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
+ SourceLocation Loc,
+ bool isRelational) {
+ // Check to make sure we're operating on vectors of the same type and width,
+ // Allowing one side to be a scalar of element type.
+ QualType vType = CheckVectorOperands(Loc, lex, rex);
+ if (vType.isNull())
+ return vType;
+
+ // If AltiVec, the comparison results in a numeric type, i.e.
+ // bool for C++, int for C
+ if (getLangOptions().AltiVec)
+ return Context.getLogicalOperationType();
+
+ QualType lType = lex->getType();
+ QualType rType = rex->getType();
+
+ // For non-floating point types, check for self-comparisons of the form
+ // x == x, x != x, x < x, etc. These always evaluate to a constant, and
+ // often indicate logic errors in the program.
+ if (!lType->hasFloatingRepresentation()) {
+ if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
+ if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
+ if (DRL->getDecl() == DRR->getDecl())
+ DiagRuntimeBehavior(Loc,
+ PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << 2 // "a constant"
+ );
+ }
+
+ // Check for comparisons of floating point operands using != and ==.
+ if (!isRelational && lType->hasFloatingRepresentation()) {
+ assert (rType->hasFloatingRepresentation());
+ CheckFloatComparison(Loc,lex,rex);
+ }
+
+ // Return the type for the comparison, which is the same as vector type for
+ // integer vectors, or an integer type of identical size and number of
+ // elements for floating point vectors.
+ if (lType->hasIntegerRepresentation())
+ return lType;
+
+ const VectorType *VTy = lType->getAs<VectorType>();
+ unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
+ if (TypeSize == Context.getTypeSize(Context.IntTy))
+ return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
+ if (TypeSize == Context.getTypeSize(Context.LongTy))
+ return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
+
+ assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
+ "Unhandled vector element size in vector compare");
+ return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
+}
+
+inline QualType Sema::CheckBitwiseOperands(
+ Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
+ return CheckVectorOperands(Loc, lex, rex);
+
+ return InvalidOperands(Loc, lex, rex);
+ }
+
+ QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+
+ if (lex->getType()->isIntegralOrUnscopedEnumerationType() &&
+ rex->getType()->isIntegralOrUnscopedEnumerationType())
+ return compType;
+ return InvalidOperands(Loc, lex, rex);
+}
+
+inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
+ Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned Opc) {
+
+ // Diagnose cases where the user write a logical and/or but probably meant a
+ // bitwise one. We do this when the LHS is a non-bool integer and the RHS
+ // is a constant.
+ if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() &&
+ rex->getType()->isIntegerType() && !rex->isValueDependent() &&
+ // Don't warn in macros.
+ !Loc.isMacroID()) {
+ // If the RHS can be constant folded, and if it constant folds to something
+ // that isn't 0 or 1 (which indicate a potential logical operation that
+ // happened to fold to true/false) then warn.
+ Expr::EvalResult Result;
+ if (rex->Evaluate(Result, Context) && !Result.HasSideEffects &&
+ Result.Val.getInt() != 0 && Result.Val.getInt() != 1) {
+ Diag(Loc, diag::warn_logical_instead_of_bitwise)
+ << rex->getSourceRange()
+ << (Opc == BO_LAnd ? "&&" : "||")
+ << (Opc == BO_LAnd ? "&" : "|");
+ }
+ }
+
+ if (!Context.getLangOptions().CPlusPlus) {
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+
+ if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType())
+ return InvalidOperands(Loc, lex, rex);
+
+ return Context.IntTy;
+ }
+
+ // The following is safe because we only use this method for
+ // non-overloadable operands.
+
+ // C++ [expr.log.and]p1
+ // C++ [expr.log.or]p1
+ // The operands are both contextually converted to type bool.
+ if (PerformContextuallyConvertToBool(lex) ||
+ PerformContextuallyConvertToBool(rex))
+ return InvalidOperands(Loc, lex, rex);
+
+ // C++ [expr.log.and]p2
+ // C++ [expr.log.or]p2
+ // The result is a bool.
+ return Context.BoolTy;
+}
+
+/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
+/// is a read-only property; return true if so. A readonly property expression
+/// depends on various declarations and thus must be treated specially.
+///
+static bool IsReadonlyProperty(Expr *E, Sema &S) {
+ if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
+ const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
+ if (PropExpr->isImplicitProperty()) return false;
+
+ ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
+ QualType BaseType = PropExpr->isSuperReceiver() ?
+ PropExpr->getSuperReceiverType() :
+ PropExpr->getBase()->getType();
+
+ if (const ObjCObjectPointerType *OPT =
+ BaseType->getAsObjCInterfacePointerType())
+ if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
+ if (S.isPropertyReadonly(PDecl, IFace))
+ return true;
+ }
+ return false;
+}
+
+/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
+/// emit an error and return true. If so, return false.
+static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
+ SourceLocation OrigLoc = Loc;
+ Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
+ &Loc);
+ if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
+ IsLV = Expr::MLV_ReadonlyProperty;
+ if (IsLV == Expr::MLV_Valid)
+ return false;
+
+ unsigned Diag = 0;
+ bool NeedType = false;
+ switch (IsLV) { // C99 6.5.16p2
+ case Expr::MLV_ConstQualified: Diag = diag::err_typecheck_assign_const; break;
+ case Expr::MLV_ArrayType:
+ Diag = diag::err_typecheck_array_not_modifiable_lvalue;
+ NeedType = true;
+ break;
+ case Expr::MLV_NotObjectType:
+ Diag = diag::err_typecheck_non_object_not_modifiable_lvalue;
+ NeedType = true;
+ break;
+ case Expr::MLV_LValueCast:
+ Diag = diag::err_typecheck_lvalue_casts_not_supported;
+ break;
+ case Expr::MLV_Valid:
+ llvm_unreachable("did not take early return for MLV_Valid");
+ case Expr::MLV_InvalidExpression:
+ case Expr::MLV_MemberFunction:
+ case Expr::MLV_ClassTemporary:
+ Diag = diag::err_typecheck_expression_not_modifiable_lvalue;
+ break;
+ case Expr::MLV_IncompleteType:
+ case Expr::MLV_IncompleteVoidType:
+ return S.RequireCompleteType(Loc, E->getType(),
+ S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
+ << E->getSourceRange());
+ case Expr::MLV_DuplicateVectorComponents:
+ Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
+ break;
+ case Expr::MLV_NotBlockQualified:
+ Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
+ break;
+ case Expr::MLV_ReadonlyProperty:
+ Diag = diag::error_readonly_property_assignment;
+ break;
+ case Expr::MLV_NoSetterProperty:
+ Diag = diag::error_nosetter_property_assignment;
+ break;
+ case Expr::MLV_SubObjCPropertySetting:
+ Diag = diag::error_no_subobject_property_setting;
+ break;
+ }
+
+ SourceRange Assign;
+ if (Loc != OrigLoc)
+ Assign = SourceRange(OrigLoc, OrigLoc);
+ if (NeedType)
+ S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign;
+ else
+ S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
+ return true;
+}
+
+
+
+// C99 6.5.16.1
+QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
+ SourceLocation Loc,
+ QualType CompoundType) {
+ // Verify that LHS is a modifiable lvalue, and emit error if not.
+ if (CheckForModifiableLvalue(LHS, Loc, *this))
+ return QualType();
+
+ QualType LHSType = LHS->getType();
+ QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType;
+ AssignConvertType ConvTy;
+ if (CompoundType.isNull()) {
+ QualType LHSTy(LHSType);
+ // Simple assignment "x = y".
+ if (LHS->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForLValue(LHS, RHS, LHSTy);
+ ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+ // Special case of NSObject attributes on c-style pointer types.
+ if (ConvTy == IncompatiblePointer &&
+ ((Context.isObjCNSObjectType(LHSType) &&
+ RHSType->isObjCObjectPointerType()) ||
+ (Context.isObjCNSObjectType(RHSType) &&
+ LHSType->isObjCObjectPointerType())))
+ ConvTy = Compatible;
+
+ if (ConvTy == Compatible &&
+ getLangOptions().ObjCNonFragileABI &&
+ LHSType->isObjCObjectType())
+ Diag(Loc, diag::err_assignment_requires_nonfragile_object)
+ << LHSType;
+
+ // If the RHS is a unary plus or minus, check to see if they = and + are
+ // right next to each other. If so, the user may have typo'd "x =+ 4"
+ // instead of "x += 4".
+ Expr *RHSCheck = RHS;
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
+ RHSCheck = ICE->getSubExpr();
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
+ if ((UO->getOpcode() == UO_Plus ||
+ UO->getOpcode() == UO_Minus) &&
+ Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
+ // Only if the two operators are exactly adjacent.
+ Loc.getFileLocWithOffset(1) == UO->getOperatorLoc() &&
+ // And there is a space or other character before the subexpr of the
+ // unary +/-. We don't want to warn on "x=-1".
+ Loc.getFileLocWithOffset(2) != UO->getSubExpr()->getLocStart() &&
+ UO->getSubExpr()->getLocStart().isFileID()) {
+ Diag(Loc, diag::warn_not_compound_assign)
+ << (UO->getOpcode() == UO_Plus ? "+" : "-")
+ << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
+ }
+ }
+ } else {
+ // Compound assignment "x += y"
+ ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType);
+ }
+
+ if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
+ RHS, AA_Assigning))
+ return QualType();
+
+
+ // Check to see if the destination operand is a dereferenced null pointer. If
+ // so, and if not volatile-qualified, this is undefined behavior that the
+ // optimizer will delete, so warn about it. People sometimes try to use this
+ // to get a deterministic trap and are surprised by clang's behavior. This
+ // only handles the pattern "*null = whatever", which is a very syntactic
+ // check.
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts()))
+ if (UO->getOpcode() == UO_Deref &&
+ UO->getSubExpr()->IgnoreParenCasts()->
+ isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
+ !UO->getType().isVolatileQualified()) {
+ Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange();
+ Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
+ }
+
+ // Check for trivial buffer overflows.
+ if (const ArraySubscriptExpr *ae
+ = dyn_cast<ArraySubscriptExpr>(LHS->IgnoreParenCasts()))
+ CheckArrayAccess(ae);
+
+ // C99 6.5.16p3: The type of an assignment expression is the type of the
+ // left operand unless the left operand has qualified type, in which case
+ // it is the unqualified version of the type of the left operand.
+ // C99 6.5.16.1p2: In simple assignment, the value of the right operand
+ // is converted to the type of the assignment expression (above).
+ // C++ 5.17p1: the type of the assignment expression is that of its left
+ // operand.
+ return (getLangOptions().CPlusPlus
+ ? LHSType : LHSType.getUnqualifiedType());
+}
+
+// C99 6.5.17
+static QualType CheckCommaOperands(Sema &S, Expr *&LHS, Expr *&RHS,
+ SourceLocation Loc) {
+ S.DiagnoseUnusedExprResult(LHS);
+
+ ExprResult LHSResult = S.CheckPlaceholderExpr(LHS, Loc);
+ if (LHSResult.isInvalid())
+ return QualType();
+
+ ExprResult RHSResult = S.CheckPlaceholderExpr(RHS, Loc);
+ if (RHSResult.isInvalid())
+ return QualType();
+ RHS = RHSResult.take();
+
+ // C's comma performs lvalue conversion (C99 6.3.2.1) on both its
+ // operands, but not unary promotions.
+ // C++'s comma does not do any conversions at all (C++ [expr.comma]p1).
+
+ // So we treat the LHS as a ignored value, and in C++ we allow the
+ // containing site to determine what should be done with the RHS.
+ S.IgnoredValueConversions(LHS);
+
+ if (!S.getLangOptions().CPlusPlus) {
+ S.DefaultFunctionArrayLvalueConversion(RHS);
+ if (!RHS->getType()->isVoidType())
+ S.RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type);
+ }
+
+ return RHS->getType();
+}
+
+/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
+/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
+static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
+ ExprValueKind &VK,
+ SourceLocation OpLoc,
+ bool isInc, bool isPrefix) {
+ if (Op->isTypeDependent())
+ return S.Context.DependentTy;
+
+ QualType ResType = Op->getType();
+ assert(!ResType.isNull() && "no type for increment/decrement expression");
+
+ if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) {
+ // Decrement of bool is not allowed.
+ if (!isInc) {
+ S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
+ return QualType();
+ }
+ // Increment of bool sets it to true, but is deprecated.
+ S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ } else if (ResType->isRealType()) {
+ // OK!
+ } else if (ResType->isAnyPointerType()) {
+ QualType PointeeTy = ResType->getPointeeType();
+
+ // C99 6.5.2.4p2, 6.5.6p2
+ if (PointeeTy->isVoidType()) {
+ if (S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
+ << Op->getSourceRange();
+ return QualType();
+ }
+
+ // Pointer to void is a GNU extension in C.
+ S.Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
+ } else if (PointeeTy->isFunctionType()) {
+ if (S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
+ << Op->getType() << Op->getSourceRange();
+ return QualType();
+ }
+
+ S.Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
+ << ResType << Op->getSourceRange();
+ } else if (S.RequireCompleteType(OpLoc, PointeeTy,
+ S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+ << Op->getSourceRange()
+ << ResType))
+ return QualType();
+ // Diagnose bad cases where we step over interface counts.
+ else if (PointeeTy->isObjCObjectType() && S.LangOpts.ObjCNonFragileABI) {
+ S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
+ << PointeeTy << Op->getSourceRange();
+ return QualType();
+ }
+ } else if (ResType->isAnyComplexType()) {
+ // C99 does not support ++/-- on complex types, we allow as an extension.
+ S.Diag(OpLoc, diag::ext_integer_increment_complex)
+ << ResType << Op->getSourceRange();
+ } else if (ResType->isPlaceholderType()) {
+ ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
+ if (PR.isInvalid()) return QualType();
+ return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
+ isInc, isPrefix);
+ } else if (S.getLangOptions().AltiVec && ResType->isVectorType()) {
+ // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
+ } else {
+ S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
+ << ResType << int(isInc) << Op->getSourceRange();
+ return QualType();
+ }
+ // At this point, we know we have a real, complex or pointer type.
+ // Now make sure the operand is a modifiable lvalue.
+ if (CheckForModifiableLvalue(Op, OpLoc, S))
+ return QualType();
+ // In C++, a prefix increment is the same type as the operand. Otherwise
+ // (in C or with postfix), the increment is the unqualified type of the
+ // operand.
+ if (isPrefix && S.getLangOptions().CPlusPlus) {
+ VK = VK_LValue;
+ return ResType;
+ } else {
+ VK = VK_RValue;
+ return ResType.getUnqualifiedType();
+ }
+}
+
+void Sema::ConvertPropertyForRValue(Expr *&E) {
+ assert(E->getValueKind() == VK_LValue &&
+ E->getObjectKind() == OK_ObjCProperty);
+ const ObjCPropertyRefExpr *PRE = E->getObjCProperty();
+
+ ExprValueKind VK = VK_RValue;
+ if (PRE->isImplicitProperty()) {
+ if (const ObjCMethodDecl *GetterMethod =
+ PRE->getImplicitPropertyGetter()) {
+ QualType Result = GetterMethod->getResultType();
+ VK = Expr::getValueKindForType(Result);
+ }
+ else {
+ Diag(PRE->getLocation(), diag::err_getter_not_found)
+ << PRE->getBase()->getType();
+ }
+ }
+
+ E = ImplicitCastExpr::Create(Context, E->getType(), CK_GetObjCProperty,
+ E, 0, VK);
+
+ ExprResult Result = MaybeBindToTemporary(E);
+ if (!Result.isInvalid())
+ E = Result.take();
+}
+
+void Sema::ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType &LHSTy) {
+ assert(LHS->getValueKind() == VK_LValue &&
+ LHS->getObjectKind() == OK_ObjCProperty);
+ const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
+
+ if (PRE->isImplicitProperty()) {
+ // If using property-dot syntax notation for assignment, and there is a
+ // setter, RHS expression is being passed to the setter argument. So,
+ // type conversion (and comparison) is RHS to setter's argument type.
+ if (const ObjCMethodDecl *SetterMD = PRE->getImplicitPropertySetter()) {
+ ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
+ LHSTy = (*P)->getType();
+
+ // Otherwise, if the getter returns an l-value, just call that.
+ } else {
+ QualType Result = PRE->getImplicitPropertyGetter()->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(Result);
+ if (VK == VK_LValue) {
+ LHS = ImplicitCastExpr::Create(Context, LHS->getType(),
+ CK_GetObjCProperty, LHS, 0, VK);
+ return;
+ }
+ }
+ }
+
+ if (getLangOptions().CPlusPlus && LHSTy->isRecordType()) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(Context, LHSTy);
+ Expr *Arg = RHS;
+ ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(),
+ Owned(Arg));
+ if (!ArgE.isInvalid())
+ RHS = ArgE.takeAs<Expr>();
+ }
+}
+
+
+/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
+/// This routine allows us to typecheck complex/recursive expressions
+/// where the declaration is needed for type checking. We only need to
+/// handle cases when the expression references a function designator
+/// or is an lvalue. Here are some examples:
+/// - &(x) => x
+/// - &*****f => f for f a function designator.
+/// - &s.xx => s
+/// - &s.zz[1].yy -> s, if zz is an array
+/// - *(x + 1) -> x, if x is an array
+/// - &"123"[2] -> 0
+/// - & __real__ x -> x
+static ValueDecl *getPrimaryDecl(Expr *E) {
+ switch (E->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(E)->getDecl();
+ case Stmt::MemberExprClass:
+ // If this is an arrow operator, the address is an offset from
+ // the base's value, so the object the base refers to is
+ // irrelevant.
+ if (cast<MemberExpr>(E)->isArrow())
+ return 0;
+ // Otherwise, the expression refers to a part of the base
+ return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
+ case Stmt::ArraySubscriptExprClass: {
+ // FIXME: This code shouldn't be necessary! We should catch the implicit
+ // promotion of register arrays earlier.
+ Expr* Base = cast<ArraySubscriptExpr>(E)->getBase();
+ if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
+ if (ICE->getSubExpr()->getType()->isArrayType())
+ return getPrimaryDecl(ICE->getSubExpr());
+ }
+ return 0;
+ }
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator *UO = cast<UnaryOperator>(E);
+
+ switch(UO->getOpcode()) {
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
+ return getPrimaryDecl(UO->getSubExpr());
+ default:
+ return 0;
+ }
+ }
+ case Stmt::ParenExprClass:
+ return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
+ case Stmt::ImplicitCastExprClass:
+ // If the result of an implicit cast is an l-value, we care about
+ // the sub-expression; otherwise, the result here doesn't matter.
+ return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
+ default:
+ return 0;
+ }
+}
+
+/// CheckAddressOfOperand - The operand of & must be either a function
+/// designator or an lvalue designating an object. If it is an lvalue, the
+/// object cannot be declared with storage class register or be a bit field.
+/// Note: The usual conversions are *not* applied to the operand of the &
+/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
+/// In C++, the operand might be an overloaded function name, in which case
+/// we allow the '&' but retain the overloaded-function type.
+static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
+ SourceLocation OpLoc) {
+ if (OrigOp->isTypeDependent())
+ return S.Context.DependentTy;
+ if (OrigOp->getType() == S.Context.OverloadTy)
+ return S.Context.OverloadTy;
+
+ ExprResult PR = S.CheckPlaceholderExpr(OrigOp, OpLoc);
+ if (PR.isInvalid()) return QualType();
+ OrigOp = PR.take();
+
+ // Make sure to ignore parentheses in subsequent checks
+ Expr *op = OrigOp->IgnoreParens();
+
+ if (S.getLangOptions().C99) {
+ // Implement C99-only parts of addressof rules.
+ if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
+ if (uOp->getOpcode() == UO_Deref)
+ // Per C99 6.5.3.2, the address of a deref always returns a valid result
+ // (assuming the deref expression is valid).
+ return uOp->getSubExpr()->getType();
+ }
+ // Technically, there should be a check for array subscript
+ // expressions here, but the result of one is always an lvalue anyway.
+ }
+ ValueDecl *dcl = getPrimaryDecl(op);
+ Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
+
+ if (lval == Expr::LV_ClassTemporary) {
+ bool sfinae = S.isSFINAEContext();
+ S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
+ : diag::ext_typecheck_addrof_class_temporary)
+ << op->getType() << op->getSourceRange();
+ if (sfinae)
+ return QualType();
+ } else if (isa<ObjCSelectorExpr>(op)) {
+ return S.Context.getPointerType(op->getType());
+ } else if (lval == Expr::LV_MemberFunction) {
+ // If it's an instance method, make a member pointer.
+ // The expression must have exactly the form &A::foo.
+
+ // If the underlying expression isn't a decl ref, give up.
+ if (!isa<DeclRefExpr>(op)) {
+ S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp->getSourceRange();
+ return QualType();
+ }
+ DeclRefExpr *DRE = cast<DeclRefExpr>(op);
+ CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
+
+ // The id-expression was parenthesized.
+ if (OrigOp != DRE) {
+ S.Diag(OpLoc, diag::err_parens_pointer_member_function)
+ << OrigOp->getSourceRange();
+
+ // The method was named without a qualifier.
+ } else if (!DRE->getQualifier()) {
+ S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ << op->getSourceRange();
+ }
+
+ return S.Context.getMemberPointerType(op->getType(),
+ S.Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
+ // C99 6.5.3.2p1
+ // The operand must be either an l-value or a function designator
+ if (!op->getType()->isFunctionType()) {
+ // FIXME: emit more specific diag...
+ S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+ << op->getSourceRange();
+ return QualType();
+ }
+ } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1
+ // The operand cannot be a bit-field
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
+ << "bit-field" << op->getSourceRange();
+ return QualType();
+ } else if (op->getObjectKind() == OK_VectorComponent) {
+ // The operand cannot be an element of a vector
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
+ << "vector element" << op->getSourceRange();
+ return QualType();
+ } else if (op->getObjectKind() == OK_ObjCProperty) {
+ // cannot take address of a property expression.
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
+ << "property expression" << op->getSourceRange();
+ return QualType();
+ } else if (dcl) { // C99 6.5.3.2p1
+ // We have an lvalue with a decl. Make sure the decl is not declared
+ // with the register storage-class specifier.
+ if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
+ // in C++ it is not error to take address of a register
+ // variable (c++03 7.1.1P3)
+ if (vd->getStorageClass() == SC_Register &&
+ !S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
+ << "register variable" << op->getSourceRange();
+ return QualType();
+ }
+ } else if (isa<FunctionTemplateDecl>(dcl)) {
+ return S.Context.OverloadTy;
+ } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
+ // Okay: we can take the address of a field.
+ // Could be a pointer to member, though, if there is an explicit
+ // scope qualifier for the class.
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
+ DeclContext *Ctx = dcl->getDeclContext();
+ if (Ctx && Ctx->isRecord()) {
+ if (dcl->getType()->isReferenceType()) {
+ S.Diag(OpLoc,
+ diag::err_cannot_form_pointer_to_member_of_reference_type)
+ << dcl->getDeclName() << dcl->getType();
+ return QualType();
+ }
+
+ while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
+ Ctx = Ctx->getParent();
+ return S.Context.getMemberPointerType(op->getType(),
+ S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ }
+ }
+ } else if (!isa<FunctionDecl>(dcl))
+ assert(0 && "Unknown/unexpected decl type");
+ }
+
+ if (lval == Expr::LV_IncompleteVoidType) {
+ // Taking the address of a void variable is technically illegal, but we
+ // allow it in cases which are otherwise valid.
+ // Example: "extern void x; void* y = &x;".
+ S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+ }
+
+ // If the operand has type "type", the result has type "pointer to type".
+ if (op->getType()->isObjCObjectType())
+ return S.Context.getObjCObjectPointerType(op->getType());
+ return S.Context.getPointerType(op->getType());
+}
+
+/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
+static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
+ SourceLocation OpLoc) {
+ if (Op->isTypeDependent())
+ return S.Context.DependentTy;
+
+ S.UsualUnaryConversions(Op);
+ QualType OpTy = Op->getType();
+ QualType Result;
+
+ // Note that per both C89 and C99, indirection is always legal, even if OpTy
+ // is an incomplete type or void. It would be possible to warn about
+ // dereferencing a void pointer, but it's completely well-defined, and such a
+ // warning is unlikely to catch any mistakes.
+ if (const PointerType *PT = OpTy->getAs<PointerType>())
+ Result = PT->getPointeeType();
+ else if (const ObjCObjectPointerType *OPT =
+ OpTy->getAs<ObjCObjectPointerType>())
+ Result = OPT->getPointeeType();
+ else {
+ ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
+ if (PR.isInvalid()) return QualType();
+ if (PR.take() != Op)
+ return CheckIndirectionOperand(S, PR.take(), VK, OpLoc);
+ }
+
+ if (Result.isNull()) {
+ S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
+ << OpTy << Op->getSourceRange();
+ return QualType();
+ }
+
+ // Dereferences are usually l-values...
+ VK = VK_LValue;
+
+ // ...except that certain expressions are never l-values in C.
+ if (!S.getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(S.Context, Result))
+ VK = VK_RValue;
+
+ return Result;
+}
+
+static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode(
+ tok::TokenKind Kind) {
+ BinaryOperatorKind Opc;
+ switch (Kind) {
+ default: assert(0 && "Unknown binop!");
+ case tok::periodstar: Opc = BO_PtrMemD; break;
+ case tok::arrowstar: Opc = BO_PtrMemI; break;
+ case tok::star: Opc = BO_Mul; break;
+ case tok::slash: Opc = BO_Div; break;
+ case tok::percent: Opc = BO_Rem; break;
+ case tok::plus: Opc = BO_Add; break;
+ case tok::minus: Opc = BO_Sub; break;
+ case tok::lessless: Opc = BO_Shl; break;
+ case tok::greatergreater: Opc = BO_Shr; break;
+ case tok::lessequal: Opc = BO_LE; break;
+ case tok::less: Opc = BO_LT; break;
+ case tok::greaterequal: Opc = BO_GE; break;
+ case tok::greater: Opc = BO_GT; break;
+ case tok::exclaimequal: Opc = BO_NE; break;
+ case tok::equalequal: Opc = BO_EQ; break;
+ case tok::amp: Opc = BO_And; break;
+ case tok::caret: Opc = BO_Xor; break;
+ case tok::pipe: Opc = BO_Or; break;
+ case tok::ampamp: Opc = BO_LAnd; break;
+ case tok::pipepipe: Opc = BO_LOr; break;
+ case tok::equal: Opc = BO_Assign; break;
+ case tok::starequal: Opc = BO_MulAssign; break;
+ case tok::slashequal: Opc = BO_DivAssign; break;
+ case tok::percentequal: Opc = BO_RemAssign; break;
+ case tok::plusequal: Opc = BO_AddAssign; break;
+ case tok::minusequal: Opc = BO_SubAssign; break;
+ case tok::lesslessequal: Opc = BO_ShlAssign; break;
+ case tok::greatergreaterequal: Opc = BO_ShrAssign; break;
+ case tok::ampequal: Opc = BO_AndAssign; break;
+ case tok::caretequal: Opc = BO_XorAssign; break;
+ case tok::pipeequal: Opc = BO_OrAssign; break;
+ case tok::comma: Opc = BO_Comma; break;
+ }
+ return Opc;
+}
+
+static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
+ tok::TokenKind Kind) {
+ UnaryOperatorKind Opc;
+ switch (Kind) {
+ default: assert(0 && "Unknown unary op!");
+ case tok::plusplus: Opc = UO_PreInc; break;
+ case tok::minusminus: Opc = UO_PreDec; break;
+ case tok::amp: Opc = UO_AddrOf; break;
+ case tok::star: Opc = UO_Deref; break;
+ case tok::plus: Opc = UO_Plus; break;
+ case tok::minus: Opc = UO_Minus; break;
+ case tok::tilde: Opc = UO_Not; break;
+ case tok::exclaim: Opc = UO_LNot; break;
+ case tok::kw___real: Opc = UO_Real; break;
+ case tok::kw___imag: Opc = UO_Imag; break;
+ case tok::kw___extension__: Opc = UO_Extension; break;
+ }
+ return Opc;
+}
+
+/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
+/// This warning is only emitted for builtin assignment operations. It is also
+/// suppressed in the event of macro expansions.
+static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs,
+ SourceLocation OpLoc) {
+ if (!S.ActiveTemplateInstantiations.empty())
+ return;
+ if (OpLoc.isInvalid() || OpLoc.isMacroID())
+ return;
+ lhs = lhs->IgnoreParenImpCasts();
+ rhs = rhs->IgnoreParenImpCasts();
+ const DeclRefExpr *LeftDeclRef = dyn_cast<DeclRefExpr>(lhs);
+ const DeclRefExpr *RightDeclRef = dyn_cast<DeclRefExpr>(rhs);
+ if (!LeftDeclRef || !RightDeclRef ||
+ LeftDeclRef->getLocation().isMacroID() ||
+ RightDeclRef->getLocation().isMacroID())
+ return;
+ const ValueDecl *LeftDecl =
+ cast<ValueDecl>(LeftDeclRef->getDecl()->getCanonicalDecl());
+ const ValueDecl *RightDecl =
+ cast<ValueDecl>(RightDeclRef->getDecl()->getCanonicalDecl());
+ if (LeftDecl != RightDecl)
+ return;
+ if (LeftDecl->getType().isVolatileQualified())
+ return;
+ if (const ReferenceType *RefTy = LeftDecl->getType()->getAs<ReferenceType>())
+ if (RefTy->getPointeeType().isVolatileQualified())
+ return;
+
+ S.Diag(OpLoc, diag::warn_self_assignment)
+ << LeftDeclRef->getType()
+ << lhs->getSourceRange() << rhs->getSourceRange();
+}
+
+/// CreateBuiltinBinOp - Creates a new built-in binary operation with
+/// operator @p Opc at location @c TokLoc. This routine only supports
+/// built-in operations; ActOnBinOp handles overloaded operators.
+ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ Expr *lhs, Expr *rhs) {
+ QualType ResultTy; // Result type of the binary operator.
+ // The following two variables are used for compound assignment operators
+ QualType CompLHSTy; // Type of LHS after promotions for computation
+ QualType CompResultTy; // Type of computation result
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+
+ switch (Opc) {
+ case BO_Assign:
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
+ if (getLangOptions().CPlusPlus &&
+ lhs->getObjectKind() != OK_ObjCProperty) {
+ VK = lhs->getValueKind();
+ OK = lhs->getObjectKind();
+ }
+ if (!ResultTy.isNull())
+ DiagnoseSelfAssignment(*this, lhs, rhs, OpLoc);
+ break;
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ ResultTy = CheckPointerToMemberOperands(lhs, rhs, VK, OpLoc,
+ Opc == BO_PtrMemI);
+ break;
+ case BO_Mul:
+ case BO_Div:
+ ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false,
+ Opc == BO_Div);
+ break;
+ case BO_Rem:
+ ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc);
+ break;
+ case BO_Add:
+ ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc);
+ break;
+ case BO_Sub:
+ ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc);
+ break;
+ case BO_Shl:
+ case BO_Shr:
+ ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
+ break;
+ case BO_LE:
+ case BO_LT:
+ case BO_GE:
+ case BO_GT:
+ ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, true);
+ break;
+ case BO_EQ:
+ case BO_NE:
+ ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, false);
+ break;
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc);
+ break;
+ case BO_LAnd:
+ case BO_LOr:
+ ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc, Opc);
+ break;
+ case BO_MulAssign:
+ case BO_DivAssign:
+ CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
+ Opc == BO_DivAssign);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_RemAssign:
+ CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_AddAssign:
+ CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_SubAssign:
+ CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
+ CompLHSTy = CompResultTy;
+ if (!CompResultTy.isNull())
+ ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
+ break;
+ case BO_Comma:
+ ResultTy = CheckCommaOperands(*this, lhs, rhs, OpLoc);
+ if (getLangOptions().CPlusPlus) {
+ VK = rhs->getValueKind();
+ OK = rhs->getObjectKind();
+ }
+ break;
+ }
+ if (ResultTy.isNull())
+ return ExprError();
+ if (CompResultTy.isNull())
+ return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy,
+ VK, OK, OpLoc));
+
+ if (getLangOptions().CPlusPlus && lhs->getObjectKind() != OK_ObjCProperty) {
+ VK = VK_LValue;
+ OK = lhs->getObjectKind();
+ }
+ return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
+ VK, OK, CompLHSTy,
+ CompResultTy, OpLoc));
+}
+
+/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps
+/// ParenRange in parentheses.
+static void SuggestParentheses(Sema &Self, SourceLocation Loc,
+ const PartialDiagnostic &PD,
+ const PartialDiagnostic &FirstNote,
+ SourceRange FirstParenRange,
+ const PartialDiagnostic &SecondNote,
+ SourceRange SecondParenRange) {
+ Self.Diag(Loc, PD);
+
+ if (!FirstNote.getDiagID())
+ return;
+
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(FirstParenRange.getEnd());
+ if (!FirstParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just return.
+ return;
+ }
+
+ Self.Diag(Loc, FirstNote)
+ << FixItHint::CreateInsertion(FirstParenRange.getBegin(), "(")
+ << FixItHint::CreateInsertion(EndLoc, ")");
+
+ if (!SecondNote.getDiagID())
+ return;
+
+ EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd());
+ if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
+ // We can't display the parentheses, so just dig the
+ // warning/error and return.
+ Self.Diag(Loc, SecondNote);
+ return;
+ }
+
+ Self.Diag(Loc, SecondNote)
+ << FixItHint::CreateInsertion(SecondParenRange.getBegin(), "(")
+ << FixItHint::CreateInsertion(EndLoc, ")");
+}
+
+/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
+/// operators are mixed in a way that suggests that the programmer forgot that
+/// comparison operators have higher precedence. The most typical example of
+/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
+ SourceLocation OpLoc,Expr *lhs,Expr *rhs){
+ typedef BinaryOperator BinOp;
+ BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1),
+ rhsopc = static_cast<BinOp::Opcode>(-1);
+ if (BinOp *BO = dyn_cast<BinOp>(lhs))
+ lhsopc = BO->getOpcode();
+ if (BinOp *BO = dyn_cast<BinOp>(rhs))
+ rhsopc = BO->getOpcode();
+
+ // Subs are not binary operators.
+ if (lhsopc == -1 && rhsopc == -1)
+ return;
+
+ // Bitwise operations are sometimes used as eager logical ops.
+ // Don't diagnose this.
+ if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) &&
+ (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc)))
+ return;
+
+ if (BinOp::isComparisonOp(lhsopc))
+ SuggestParentheses(Self, OpLoc,
+ Self.PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(lhs->getLocStart(), OpLoc)
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
+ Self.PDiag(diag::note_precedence_bitwise_first)
+ << BinOp::getOpcodeStr(Opc),
+ SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()),
+ Self.PDiag(diag::note_precedence_bitwise_silence)
+ << BinOp::getOpcodeStr(lhsopc),
+ lhs->getSourceRange());
+ else if (BinOp::isComparisonOp(rhsopc))
+ SuggestParentheses(Self, OpLoc,
+ Self.PDiag(diag::warn_precedence_bitwise_rel)
+ << SourceRange(OpLoc, rhs->getLocEnd())
+ << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
+ Self.PDiag(diag::note_precedence_bitwise_first)
+ << BinOp::getOpcodeStr(Opc),
+ SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()),
+ Self.PDiag(diag::note_precedence_bitwise_silence)
+ << BinOp::getOpcodeStr(rhsopc),
+ rhs->getSourceRange());
+}
+
+/// \brief It accepts a '&&' expr that is inside a '||' one.
+/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
+/// in parentheses.
+static void
+EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
+ Expr *E) {
+ assert(isa<BinaryOperator>(E) &&
+ cast<BinaryOperator>(E)->getOpcode() == BO_LAnd);
+ SuggestParentheses(Self, OpLoc,
+ Self.PDiag(diag::warn_logical_and_in_logical_or)
+ << E->getSourceRange(),
+ Self.PDiag(diag::note_logical_and_in_logical_or_silence),
+ E->getSourceRange(),
+ Self.PDiag(0), SourceRange());
+}
+
+/// \brief Returns true if the given expression can be evaluated as a constant
+/// 'true'.
+static bool EvaluatesAsTrue(Sema &S, Expr *E) {
+ bool Res;
+ return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
+}
+
+/// \brief Returns true if the given expression can be evaluated as a constant
+/// 'false'.
+static bool EvaluatesAsFalse(Sema &S, Expr *E) {
+ bool Res;
+ return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
+}
+
+/// \brief Look for '&&' in the left hand of a '||' expr.
+static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
+ Expr *OrLHS, Expr *OrRHS) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrLHS)) {
+ if (Bop->getOpcode() == BO_LAnd) {
+ // If it's "a && b || 0" don't warn since the precedence doesn't matter.
+ if (EvaluatesAsFalse(S, OrRHS))
+ return;
+ // If it's "1 && a || b" don't warn since the precedence doesn't matter.
+ if (!EvaluatesAsTrue(S, Bop->getLHS()))
+ return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
+ } else if (Bop->getOpcode() == BO_LOr) {
+ if (BinaryOperator *RBop = dyn_cast<BinaryOperator>(Bop->getRHS())) {
+ // If it's "a || b && 1 || c" we didn't warn earlier for
+ // "a || b && 1", but warn now.
+ if (RBop->getOpcode() == BO_LAnd && EvaluatesAsTrue(S, RBop->getRHS()))
+ return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, RBop);
+ }
+ }
+ }
+}
+
+/// \brief Look for '&&' in the right hand of a '||' expr.
+static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
+ Expr *OrLHS, Expr *OrRHS) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrRHS)) {
+ if (Bop->getOpcode() == BO_LAnd) {
+ // If it's "0 || a && b" don't warn since the precedence doesn't matter.
+ if (EvaluatesAsFalse(S, OrLHS))
+ return;
+ // If it's "a || b && 1" don't warn since the precedence doesn't matter.
+ if (!EvaluatesAsTrue(S, Bop->getRHS()))
+ return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
+ }
+ }
+}
+
+/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
+/// precedence.
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
+ SourceLocation OpLoc, Expr *lhs, Expr *rhs){
+ // Diagnose "arg1 'bitwise' arg2 'eq' arg3".
+ if (BinaryOperator::isBitwiseOp(Opc))
+ return DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs);
+
+ // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
+ // We don't warn for 'assert(a || b && "bad")' since this is safe.
+ if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) {
+ DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs, rhs);
+ DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, lhs, rhs);
+ }
+}
+
+// Binary Operators. 'Tok' is the token for the operator.
+ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind,
+ Expr *lhs, Expr *rhs) {
+ BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
+ assert((lhs != 0) && "ActOnBinOp(): missing left expression");
+ assert((rhs != 0) && "ActOnBinOp(): missing right expression");
+
+ // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
+ DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
+
+ return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
+}
+
+ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ Expr *lhs, Expr *rhs) {
+ if (getLangOptions().CPlusPlus) {
+ bool UseBuiltinOperator;
+
+ if (lhs->isTypeDependent() || rhs->isTypeDependent()) {
+ UseBuiltinOperator = false;
+ } else if (Opc == BO_Assign && lhs->getObjectKind() == OK_ObjCProperty) {
+ UseBuiltinOperator = true;
+ } else {
+ UseBuiltinOperator = !lhs->getType()->isOverloadableType() &&
+ !rhs->getType()->isOverloadableType();
+ }
+
+ if (!UseBuiltinOperator) {
+ // Find all of the overloaded operators visible from this
+ // point. We perform both an operator-name lookup from the local
+ // scope and an argument-dependent lookup based on the types of
+ // the arguments.
+ UnresolvedSet<16> Functions;
+ OverloadedOperatorKind OverOp
+ = BinaryOperator::getOverloadedOperator(Opc);
+ if (S && OverOp != OO_None)
+ LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+ Functions);
+
+ // Build the (potentially-overloaded, potentially-dependent)
+ // binary operation.
+ return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
+ }
+ }
+
+ // Build a built-in binary operation.
+ return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
+}
+
+ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ Expr *Input) {
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+ QualType resultType;
+ switch (Opc) {
+ case UO_PreInc:
+ case UO_PreDec:
+ case UO_PostInc:
+ case UO_PostDec:
+ resultType = CheckIncrementDecrementOperand(*this, Input, VK, OpLoc,
+ Opc == UO_PreInc ||
+ Opc == UO_PostInc,
+ Opc == UO_PreInc ||
+ Opc == UO_PreDec);
+ break;
+ case UO_AddrOf:
+ resultType = CheckAddressOfOperand(*this, Input, OpLoc);
+ break;
+ case UO_Deref:
+ DefaultFunctionArrayLvalueConversion(Input);
+ resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc);
+ break;
+ case UO_Plus:
+ case UO_Minus:
+ UsualUnaryConversions(Input);
+ resultType = Input->getType();
+ if (resultType->isDependentType())
+ break;
+ if (resultType->isArithmeticType() || // C99 6.5.3.3p1
+ resultType->isVectorType())
+ break;
+ else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7
+ resultType->isEnumeralType())
+ break;
+ else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6
+ Opc == UO_Plus &&
+ resultType->isPointerType())
+ break;
+ else if (resultType->isPlaceholderType()) {
+ ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
+ if (PR.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ }
+
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input->getSourceRange());
+ case UO_Not: // bitwise complement
+ UsualUnaryConversions(Input);
+ resultType = Input->getType();
+ if (resultType->isDependentType())
+ break;
+ // C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
+ if (resultType->isComplexType() || resultType->isComplexIntegerType())
+ // C99 does not support '~' for complex conjugation.
+ Diag(OpLoc, diag::ext_integer_complement_complex)
+ << resultType << Input->getSourceRange();
+ else if (resultType->hasIntegerRepresentation())
+ break;
+ else if (resultType->isPlaceholderType()) {
+ ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
+ if (PR.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ } else {
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input->getSourceRange());
+ }
+ break;
+ case UO_LNot: // logical negation
+ // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
+ DefaultFunctionArrayLvalueConversion(Input);
+ resultType = Input->getType();
+ if (resultType->isDependentType())
+ break;
+ if (resultType->isScalarType()) { // C99 6.5.3.3p1
+ // ok, fallthrough
+ } else if (resultType->isPlaceholderType()) {
+ ExprResult PR = CheckPlaceholderExpr(Input, OpLoc);
+ if (PR.isInvalid()) return ExprError();
+ return CreateBuiltinUnaryOp(OpLoc, Opc, PR.take());
+ } else {
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input->getSourceRange());
+ }
+
+ // LNot always has type int. C99 6.5.3.3p5.
+ // In C++, it's bool. C++ 5.3.1p8
+ resultType = Context.getLogicalOperationType();
+ break;
+ case UO_Real:
+ case UO_Imag:
+ resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real);
+ // _Real and _Imag map ordinary l-values into ordinary l-values.
+ if (Input->getValueKind() != VK_RValue &&
+ Input->getObjectKind() == OK_Ordinary)
+ VK = Input->getValueKind();
+ break;
+ case UO_Extension:
+ resultType = Input->getType();
+ VK = Input->getValueKind();
+ OK = Input->getObjectKind();
+ break;
+ }
+ if (resultType.isNull())
+ return ExprError();
+
+ return Owned(new (Context) UnaryOperator(Input, Opc, resultType,
+ VK, OK, OpLoc));
+}
+
+ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ Expr *Input) {
+ if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
+ UnaryOperator::getOverloadedOperator(Opc) != OO_None) {
+ // Find all of the overloaded operators visible from this
+ // point. We perform both an operator-name lookup from the local
+ // scope and an argument-dependent lookup based on the types of
+ // the arguments.
+ UnresolvedSet<16> Functions;
+ OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
+ if (S && OverOp != OO_None)
+ LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+ Functions);
+
+ return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input);
+ }
+
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+}
+
+// Unary Operators. 'Tok' is the token for the operator.
+ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input) {
+ return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input);
+}
+
+/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *TheDecl) {
+ TheDecl->setUsed();
+ // Create the AST node. The address of a label always has type 'void*'.
+ return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
+ Context.getPointerType(Context.VoidTy)));
+}
+
+ExprResult
+Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc) { // "({..})"
+ assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
+ CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
+
+ bool isFileScope
+ = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0);
+ if (isFileScope)
+ return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope));
+
+ // FIXME: there are a variety of strange constraints to enforce here, for
+ // example, it is not possible to goto into a stmt expression apparently.
+ // More semantic analysis is needed.
+
+ // If there are sub stmts in the compound stmt, take the type of the last one
+ // as the type of the stmtexpr.
+ QualType Ty = Context.VoidTy;
+ bool StmtExprMayBindToTemp = false;
+ if (!Compound->body_empty()) {
+ Stmt *LastStmt = Compound->body_back();
+ LabelStmt *LastLabelStmt = 0;
+ // If LastStmt is a label, skip down through into the body.
+ while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
+ LastLabelStmt = Label;
+ LastStmt = Label->getSubStmt();
+ }
+ if (Expr *LastExpr = dyn_cast<Expr>(LastStmt)) {
+ // Do function/array conversion on the last expression, but not
+ // lvalue-to-rvalue. However, initialize an unqualified type.
+ DefaultFunctionArrayConversion(LastExpr);
+ Ty = LastExpr->getType().getUnqualifiedType();
+
+ if (!Ty->isDependentType() && !LastExpr->isTypeDependent()) {
+ ExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(LPLoc,
+ Ty,
+ false),
+ SourceLocation(),
+ Owned(LastExpr));
+ if (Res.isInvalid())
+ return ExprError();
+ if ((LastExpr = Res.takeAs<Expr>())) {
+ if (!LastLabelStmt)
+ Compound->setLastStmt(LastExpr);
+ else
+ LastLabelStmt->setSubStmt(LastExpr);
+ StmtExprMayBindToTemp = true;
+ }
+ }
+ }
+ }
+
+ // FIXME: Check that expression type is complete/non-abstract; statement
+ // expressions are not lvalues.
+ Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
+ if (StmtExprMayBindToTemp)
+ return MaybeBindToTemporary(ResStmtExpr);
+ return Owned(ResStmtExpr);
+}
+
+ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc) {
+ QualType ArgTy = TInfo->getType();
+ bool Dependent = ArgTy->isDependentType();
+ SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange();
+
+ // We must have at least one component that refers to the type, and the first
+ // one is known to be a field designator. Verify that the ArgTy represents
+ // a struct/union/class.
+ if (!Dependent && !ArgTy->isRecordType())
+ return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
+ << ArgTy << TypeRange);
+
+ // Type must be complete per C99 7.17p3 because a declaring a variable
+ // with an incomplete type would be ill-formed.
+ if (!Dependent
+ && RequireCompleteType(BuiltinLoc, ArgTy,
+ PDiag(diag::err_offsetof_incomplete_type)
+ << TypeRange))
+ return ExprError();
+
+ // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
+ // GCC extension, diagnose them.
+ // FIXME: This diagnostic isn't actually visible because the location is in
+ // a system header!
+ if (NumComponents != 1)
+ Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
+ << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+
+ bool DidWarnAboutNonPOD = false;
+ QualType CurrentType = ArgTy;
+ typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
+ llvm::SmallVector<OffsetOfNode, 4> Comps;
+ llvm::SmallVector<Expr*, 4> Exprs;
+ for (unsigned i = 0; i != NumComponents; ++i) {
+ const OffsetOfComponent &OC = CompPtr[i];
+ if (OC.isBrackets) {
+ // Offset of an array sub-field. TODO: Should we allow vector elements?
+ if (!CurrentType->isDependentType()) {
+ const ArrayType *AT = Context.getAsArrayType(CurrentType);
+ if(!AT)
+ return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
+ << CurrentType);
+ CurrentType = AT->getElementType();
+ } else
+ CurrentType = Context.DependentTy;
+
+ // The expression must be an integral expression.
+ // FIXME: An integral constant expression?
+ Expr *Idx = static_cast<Expr*>(OC.U.E);
+ if (!Idx->isTypeDependent() && !Idx->isValueDependent() &&
+ !Idx->getType()->isIntegerType())
+ return ExprError(Diag(Idx->getLocStart(),
+ diag::err_typecheck_subscript_not_integer)
+ << Idx->getSourceRange());
+
+ // Record this array index.
+ Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd));
+ Exprs.push_back(Idx);
+ continue;
+ }
+
+ // Offset of a field.
+ if (CurrentType->isDependentType()) {
+ // We have the offset of a field, but we can't look into the dependent
+ // type. Just record the identifier of the field.
+ Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd));
+ CurrentType = Context.DependentTy;
+ continue;
+ }
+
+ // We need to have a complete type to look into.
+ if (RequireCompleteType(OC.LocStart, CurrentType,
+ diag::err_offsetof_incomplete_type))
+ return ExprError();
+
+ // Look for the designated field.
+ const RecordType *RC = CurrentType->getAs<RecordType>();
+ if (!RC)
+ return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
+ << CurrentType);
+ RecordDecl *RD = RC->getDecl();
+
+ // C++ [lib.support.types]p5:
+ // The macro offsetof accepts a restricted set of type arguments in this
+ // International Standard. type shall be a POD structure or a POD union
+ // (clause 9).
+ if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
+ DiagRuntimeBehavior(BuiltinLoc,
+ PDiag(diag::warn_offsetof_non_pod_type)
+ << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << CurrentType))
+ DidWarnAboutNonPOD = true;
+ }
+
+ // Look for the field.
+ LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
+ LookupQualifiedName(R, RD);
+ FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
+ IndirectFieldDecl *IndirectMemberDecl = 0;
+ if (!MemberDecl) {
+ if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()))
+ MemberDecl = IndirectMemberDecl->getAnonField();
+ }
+
+ if (!MemberDecl)
+ return ExprError(Diag(BuiltinLoc, diag::err_no_member)
+ << OC.U.IdentInfo << RD << SourceRange(OC.LocStart,
+ OC.LocEnd));
+
+ // C99 7.17p3:
+ // (If the specified member is a bit-field, the behavior is undefined.)
+ //
+ // We diagnose this as an error.
+ if (MemberDecl->getBitWidth()) {
+ Diag(OC.LocEnd, diag::err_offsetof_bitfield)
+ << MemberDecl->getDeclName()
+ << SourceRange(BuiltinLoc, RParenLoc);
+ Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
+ return ExprError();
+ }
+
+ RecordDecl *Parent = MemberDecl->getParent();
+ if (IndirectMemberDecl)
+ Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext());
+
+ // If the member was found in a base class, introduce OffsetOfNodes for
+ // the base class indirections.
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+ CXXBasePath &Path = Paths.front();
+ for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
+ B != BEnd; ++B)
+ Comps.push_back(OffsetOfNode(B->Base));
+ }
+
+ if (IndirectMemberDecl) {
+ for (IndirectFieldDecl::chain_iterator FI =
+ IndirectMemberDecl->chain_begin(),
+ FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) {
+ assert(isa<FieldDecl>(*FI));
+ Comps.push_back(OffsetOfNode(OC.LocStart,
+ cast<FieldDecl>(*FI), OC.LocEnd));
+ }
+ } else
+ Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
+
+ CurrentType = MemberDecl->getType().getNonReferenceType();
+ }
+
+ return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc,
+ TInfo, Comps.data(), Comps.size(),
+ Exprs.data(), Exprs.size(), RParenLoc));
+}
+
+ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType argty,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RPLoc) {
+
+ TypeSourceInfo *ArgTInfo;
+ QualType ArgTy = GetTypeFromParser(argty, &ArgTInfo);
+ if (ArgTy.isNull())
+ return ExprError();
+
+ if (!ArgTInfo)
+ ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
+
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
+ RPLoc);
+}
+
+
+ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *CondExpr,
+ Expr *LHSExpr, Expr *RHSExpr,
+ SourceLocation RPLoc) {
+ assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
+
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+ QualType resType;
+ bool ValueDependent = false;
+ if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
+ resType = Context.DependentTy;
+ ValueDependent = true;
+ } else {
+ // The conditional expression is required to be a constant expression.
+ llvm::APSInt condEval(32);
+ SourceLocation ExpLoc;
+ if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc))
+ return ExprError(Diag(ExpLoc,
+ diag::err_typecheck_choose_expr_requires_constant)
+ << CondExpr->getSourceRange());
+
+ // If the condition is > zero, then the AST type is the same as the LSHExpr.
+ Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr;
+
+ resType = ActiveExpr->getType();
+ ValueDependent = ActiveExpr->isValueDependent();
+ VK = ActiveExpr->getValueKind();
+ OK = ActiveExpr->getObjectKind();
+ }
+
+ return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
+ resType, VK, OK, RPLoc,
+ resType->isDependentType(),
+ ValueDependent));
+}
+
+//===----------------------------------------------------------------------===//
+// Clang Extensions.
+//===----------------------------------------------------------------------===//
+
+/// ActOnBlockStart - This callback is invoked when a block literal is started.
+void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
+ BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
+ PushBlockScope(BlockScope, Block);
+ CurContext->addDecl(Block);
+ if (BlockScope)
+ PushDeclContext(BlockScope, Block);
+ else
+ CurContext = Block;
+}
+
+void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
+ assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
+ assert(ParamInfo.getContext() == Declarator::BlockLiteralContext);
+ BlockScopeInfo *CurBlock = getCurBlock();
+
+ TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
+ QualType T = Sig->getType();
+
+ // GetTypeForDeclarator always produces a function type for a block
+ // literal signature. Furthermore, it is always a FunctionProtoType
+ // unless the function was written with a typedef.
+ assert(T->isFunctionType() &&
+ "GetTypeForDeclarator made a non-function block signature");
+
+ // Look for an explicit signature in that function type.
+ FunctionProtoTypeLoc ExplicitSignature;
+
+ TypeLoc tmp = Sig->getTypeLoc().IgnoreParens();
+ if (isa<FunctionProtoTypeLoc>(tmp)) {
+ ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp);
+
+ // Check whether that explicit signature was synthesized by
+ // GetTypeForDeclarator. If so, don't save that as part of the
+ // written signature.
+ if (ExplicitSignature.getLParenLoc() ==
+ ExplicitSignature.getRParenLoc()) {
+ // This would be much cheaper if we stored TypeLocs instead of
+ // TypeSourceInfos.
+ TypeLoc Result = ExplicitSignature.getResultLoc();
+ unsigned Size = Result.getFullDataSize();
+ Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
+ Sig->getTypeLoc().initializeFullCopy(Result, Size);
+
+ ExplicitSignature = FunctionProtoTypeLoc();
+ }
+ }
+
+ CurBlock->TheDecl->setSignatureAsWritten(Sig);
+ CurBlock->FunctionType = T;
+
+ const FunctionType *Fn = T->getAs<FunctionType>();
+ QualType RetTy = Fn->getResultType();
+ bool isVariadic =
+ (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
+
+ CurBlock->TheDecl->setIsVariadic(isVariadic);
+
+ // Don't allow returning a objc interface by value.
+ if (RetTy->isObjCObjectType()) {
+ Diag(ParamInfo.getSourceRange().getBegin(),
+ diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
+ return;
+ }
+
+ // Context.DependentTy is used as a placeholder for a missing block
+ // return type. TODO: what should we do with declarators like:
+ // ^ * { ... }
+ // If the answer is "apply template argument deduction"....
+ if (RetTy != Context.DependentTy)
+ CurBlock->ReturnType = RetTy;
+
+ // Push block parameters from the declarator if we had them.
+ llvm::SmallVector<ParmVarDecl*, 8> Params;
+ if (ExplicitSignature) {
+ for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) {
+ ParmVarDecl *Param = ExplicitSignature.getArg(I);
+ if (Param->getIdentifier() == 0 &&
+ !Param->isImplicit() &&
+ !Param->isInvalidDecl() &&
+ !getLangOptions().CPlusPlus)
+ Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+ Params.push_back(Param);
+ }
+
+ // Fake up parameter variables if we have a typedef, like
+ // ^ fntype { ... }
+ } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
+ for (FunctionProtoType::arg_type_iterator
+ I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(CurBlock->TheDecl,
+ ParamInfo.getSourceRange().getBegin(),
+ *I);
+ Params.push_back(Param);
+ }
+ }
+
+ // Set the parameters on the block decl.
+ if (!Params.empty()) {
+ CurBlock->TheDecl->setParams(Params.data(), Params.size());
+ CheckParmsForFunctionDef(CurBlock->TheDecl->param_begin(),
+ CurBlock->TheDecl->param_end(),
+ /*CheckParameterNames=*/false);
+ }
+
+ // Finally we can process decl attributes.
+ ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+
+ if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ Diag(ParamInfo.getAttributes()->getLoc(),
+ diag::warn_attribute_sentinel_not_variadic) << 1;
+ // FIXME: remove the attribute.
+ }
+
+ // Put the parameter variables in scope. We can bail out immediately
+ // if we don't have any.
+ if (Params.empty())
+ return;
+
+ for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
+ E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
+ (*AI)->setOwningFunction(CurBlock->TheDecl);
+
+ // If this has an identifier, add it to the scope stack.
+ if ((*AI)->getIdentifier()) {
+ CheckShadow(CurBlock->TheScope, *AI);
+
+ PushOnScopeChains(*AI, CurBlock->TheScope);
+ }
+ }
+}
+
+/// ActOnBlockError - If there is an error parsing a block, this callback
+/// is invoked to pop the information about the block from the action impl.
+void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
+ // Pop off CurBlock, handle nested blocks.
+ PopDeclContext();
+ PopFunctionOrBlockScope();
+}
+
+/// ActOnBlockStmtExpr - This is called when the body of a block statement
+/// literal was successfully completed. ^(int x){...}
+ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope) {
+ // If blocks are disabled, emit an error.
+ if (!LangOpts.Blocks)
+ Diag(CaretLoc, diag::err_blocks_disable);
+
+ BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
+
+ PopDeclContext();
+
+ QualType RetTy = Context.VoidTy;
+ if (!BSI->ReturnType.isNull())
+ RetTy = BSI->ReturnType;
+
+ bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
+ QualType BlockTy;
+
+ // Set the captured variables on the block.
+ BSI->TheDecl->setCaptures(Context, BSI->Captures.begin(), BSI->Captures.end(),
+ BSI->CapturesCXXThis);
+
+ // If the user wrote a function type in some form, try to use that.
+ if (!BSI->FunctionType.isNull()) {
+ const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>();
+
+ FunctionType::ExtInfo Ext = FTy->getExtInfo();
+ if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
+
+ // Turn protoless block types into nullary block types.
+ if (isa<FunctionNoProtoType>(FTy)) {
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = Ext;
+ BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+
+ // Otherwise, if we don't need to change anything about the function type,
+ // preserve its sugar structure.
+ } else if (FTy->getResultType() == RetTy &&
+ (!NoReturn || FTy->getNoReturnAttr())) {
+ BlockTy = BSI->FunctionType;
+
+ // Otherwise, make the minimal modifications to the function type.
+ } else {
+ const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.TypeQuals = 0; // FIXME: silently?
+ EPI.ExtInfo = Ext;
+ BlockTy = Context.getFunctionType(RetTy,
+ FPT->arg_type_begin(),
+ FPT->getNumArgs(),
+ EPI);
+ }
+
+ // If we don't have a function type, just build one from nothing.
+ } else {
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default);
+ BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
+ }
+
+ DiagnoseUnusedParameters(BSI->TheDecl->param_begin(),
+ BSI->TheDecl->param_end());
+ BlockTy = Context.getBlockPointerType(BlockTy);
+
+ // If needed, diagnose invalid gotos and switches in the block.
+ if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction())
+ DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
+
+ BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
+
+ BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
+
+ // Issue any analysis-based warnings.
+ const sema::AnalysisBasedWarnings::Policy &WP =
+ AnalysisWarnings.getDefaultPolicy();
+ AnalysisWarnings.IssueWarnings(WP, Result);
+
+ PopFunctionOrBlockScope();
+ return Owned(Result);
+}
+
+ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+ Expr *expr, ParsedType type,
+ SourceLocation RPLoc) {
+ TypeSourceInfo *TInfo;
+ GetTypeFromParser(type, &TInfo);
+ return BuildVAArgExpr(BuiltinLoc, expr, TInfo, RPLoc);
+}
+
+ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc) {
+ Expr *OrigExpr = E;
+
+ // Get the va_list type
+ QualType VaListType = Context.getBuiltinVaListType();
+ if (VaListType->isArrayType()) {
+ // Deal with implicit array decay; for example, on x86-64,
+ // va_list is an array, but it's supposed to decay to
+ // a pointer for va_arg.
+ VaListType = Context.getArrayDecayedType(VaListType);
+ // Make sure the input expression also decays appropriately.
+ UsualUnaryConversions(E);
+ } else {
+ // Otherwise, the va_list argument must be an l-value because
+ // it is modified by va_arg.
+ if (!E->isTypeDependent() &&
+ CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ }
+
+ if (!E->isTypeDependent() &&
+ !Context.hasSameType(VaListType, E->getType())) {
+ return ExprError(Diag(E->getLocStart(),
+ diag::err_first_argument_to_va_arg_not_of_type_va_list)
+ << OrigExpr->getType() << E->getSourceRange());
+ }
+
+ // FIXME: Check that type is complete/non-abstract
+ // FIXME: Warn if a non-POD type is passed in.
+
+ QualType T = TInfo->getType().getNonLValueExprType(Context);
+ return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T));
+}
+
+ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
+ // The type of __null will be int or long, depending on the size of
+ // pointers on the target.
+ QualType Ty;
+ unsigned pw = Context.Target.getPointerWidth(0);
+ if (pw == Context.Target.getIntWidth())
+ Ty = Context.IntTy;
+ else if (pw == Context.Target.getLongWidth())
+ Ty = Context.LongTy;
+ else if (pw == Context.Target.getLongLongWidth())
+ Ty = Context.LongLongTy;
+ else {
+ assert(!"I don't know size of pointer!");
+ Ty = Context.IntTy;
+ }
+
+ return Owned(new (Context) GNUNullExpr(Ty, TokenLoc));
+}
+
+static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
+ Expr *SrcExpr, FixItHint &Hint) {
+ if (!SemaRef.getLangOptions().ObjC1)
+ return;
+
+ const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
+ if (!PT)
+ return;
+
+ // Check if the destination is of type 'id'.
+ if (!PT->isObjCIdType()) {
+ // Check if the destination is the 'NSString' interface.
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+ if (!ID || !ID->getIdentifier()->isStr("NSString"))
+ return;
+ }
+
+ // Strip off any parens and casts.
+ StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts());
+ if (!SL || SL->isWide())
+ return;
+
+ Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@");
+}
+
+bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
+ SourceLocation Loc,
+ QualType DstType, QualType SrcType,
+ Expr *SrcExpr, AssignmentAction Action,
+ bool *Complained) {
+ if (Complained)
+ *Complained = false;
+
+ // Decode the result (notice that AST's are still created for extensions).
+ bool isInvalid = false;
+ unsigned DiagKind;
+ FixItHint Hint;
+
+ switch (ConvTy) {
+ default: assert(0 && "Unknown conversion type");
+ case Compatible: return false;
+ case PointerToInt:
+ DiagKind = diag::ext_typecheck_convert_pointer_int;
+ break;
+ case IntToPointer:
+ DiagKind = diag::ext_typecheck_convert_int_pointer;
+ break;
+ case IncompatiblePointer:
+ MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint);
+ DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+ break;
+ case IncompatiblePointerSign:
+ DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+ break;
+ case FunctionVoidPointer:
+ DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+ break;
+ case IncompatiblePointerDiscardsQualifiers: {
+ // Perform array-to-pointer decay if necessary.
+ if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType);
+
+ Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
+ Qualifiers rhq = DstType->getPointeeType().getQualifiers();
+ if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
+ DiagKind = diag::err_typecheck_incompatible_address_space;
+ break;
+ }
+
+ llvm_unreachable("unknown error case for discarding qualifiers!");
+ // fallthrough
+ }
+ case CompatiblePointerDiscardsQualifiers:
+ // If the qualifiers lost were because we were applying the
+ // (deprecated) C++ conversion from a string literal to a char*
+ // (or wchar_t*), then there was no error (C++ 4.2p2). FIXME:
+ // Ideally, this check would be performed in
+ // checkPointerTypesForAssignment. However, that would require a
+ // bit of refactoring (so that the second argument is an
+ // expression, rather than a type), which should be done as part
+ // of a larger effort to fix checkPointerTypesForAssignment for
+ // C++ semantics.
+ if (getLangOptions().CPlusPlus &&
+ IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
+ return false;
+ DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+ break;
+ case IncompatibleNestedPointerQualifiers:
+ DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+ break;
+ case IntToBlockPointer:
+ DiagKind = diag::err_int_to_block_pointer;
+ break;
+ case IncompatibleBlockPointer:
+ DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
+ break;
+ case IncompatibleObjCQualifiedId:
+ // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
+ // it can give a more specific diagnostic.
+ DiagKind = diag::warn_incompatible_qualified_id;
+ break;
+ case IncompatibleVectors:
+ DiagKind = diag::warn_incompatible_vectors;
+ break;
+ case Incompatible:
+ DiagKind = diag::err_typecheck_convert_incompatible;
+ isInvalid = true;
+ break;
+ }
+
+ QualType FirstType, SecondType;
+ switch (Action) {
+ case AA_Assigning:
+ case AA_Initializing:
+ // The destination type comes first.
+ FirstType = DstType;
+ SecondType = SrcType;
+ break;
+
+ case AA_Returning:
+ case AA_Passing:
+ case AA_Converting:
+ case AA_Sending:
+ case AA_Casting:
+ // The source type comes first.
+ FirstType = SrcType;
+ SecondType = DstType;
+ break;
+ }
+
+ Diag(Loc, DiagKind) << FirstType << SecondType << Action
+ << SrcExpr->getSourceRange() << Hint;
+ if (Complained)
+ *Complained = true;
+ return isInvalid;
+}
+
+bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
+ llvm::APSInt ICEResult;
+ if (E->isIntegerConstantExpr(ICEResult, Context)) {
+ if (Result)
+ *Result = ICEResult;
+ return false;
+ }
+
+ Expr::EvalResult EvalResult;
+
+ if (!E->Evaluate(EvalResult, Context) || !EvalResult.Val.isInt() ||
+ EvalResult.HasSideEffects) {
+ Diag(E->getExprLoc(), diag::err_expr_not_ice) << E->getSourceRange();
+
+ if (EvalResult.Diag) {
+ // We only show the note if it's not the usual "invalid subexpression"
+ // or if it's actually in a subexpression.
+ if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice ||
+ E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens())
+ Diag(EvalResult.DiagLoc, EvalResult.Diag);
+ }
+
+ return true;
+ }
+
+ Diag(E->getExprLoc(), diag::ext_expr_not_ice) <<
+ E->getSourceRange();
+
+ if (EvalResult.Diag &&
+ Diags.getDiagnosticLevel(diag::ext_expr_not_ice, EvalResult.DiagLoc)
+ != Diagnostic::Ignored)
+ Diag(EvalResult.DiagLoc, EvalResult.Diag);
+
+ if (Result)
+ *Result = EvalResult.Val.getInt();
+ return false;
+}
+
+void
+Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
+ ExprEvalContexts.push_back(
+ ExpressionEvaluationContextRecord(NewContext, ExprTemporaries.size()));
+}
+
+void
+Sema::PopExpressionEvaluationContext() {
+ // Pop the current expression evaluation context off the stack.
+ ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back();
+ ExprEvalContexts.pop_back();
+
+ if (Rec.Context == PotentiallyPotentiallyEvaluated) {
+ if (Rec.PotentiallyReferenced) {
+ // Mark any remaining declarations in the current position of the stack
+ // as "referenced". If they were not meant to be referenced, semantic
+ // analysis would have eliminated them (e.g., in ActOnCXXTypeId).
+ for (PotentiallyReferencedDecls::iterator
+ I = Rec.PotentiallyReferenced->begin(),
+ IEnd = Rec.PotentiallyReferenced->end();
+ I != IEnd; ++I)
+ MarkDeclarationReferenced(I->first, I->second);
+ }
+
+ if (Rec.PotentiallyDiagnosed) {
+ // Emit any pending diagnostics.
+ for (PotentiallyEmittedDiagnostics::iterator
+ I = Rec.PotentiallyDiagnosed->begin(),
+ IEnd = Rec.PotentiallyDiagnosed->end();
+ I != IEnd; ++I)
+ Diag(I->first, I->second);
+ }
+ }
+
+ // When are coming out of an unevaluated context, clear out any
+ // temporaries that we may have created as part of the evaluation of
+ // the expression in that context: they aren't relevant because they
+ // will never be constructed.
+ if (Rec.Context == Unevaluated &&
+ ExprTemporaries.size() > Rec.NumTemporaries)
+ ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries,
+ ExprTemporaries.end());
+
+ // Destroy the popped expression evaluation record.
+ Rec.Destroy();
+}
+
+/// \brief Note that the given declaration was referenced in the source code.
+///
+/// This routine should be invoke whenever a given declaration is referenced
+/// in the source code, and where that reference occurred. If this declaration
+/// reference means that the the declaration is used (C++ [basic.def.odr]p2,
+/// C99 6.9p3), then the declaration will be marked as used.
+///
+/// \param Loc the location where the declaration was referenced.
+///
+/// \param D the declaration that has been referenced by the source code.
+void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
+ assert(D && "No declaration?");
+
+ if (D->isUsed(false))
+ return;
+
+ // Mark a parameter or variable declaration "used", regardless of whether we're in a
+ // template or not. The reason for this is that unevaluated expressions
+ // (e.g. (void)sizeof()) constitute a use for warning purposes (-Wunused-variables and
+ // -Wunused-parameters)
+ if (isa<ParmVarDecl>(D) ||
+ (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) {
+ D->setUsed();
+ return;
+ }
+
+ if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D))
+ return;
+
+ // Do not mark anything as "used" within a dependent context; wait for
+ // an instantiation.
+ if (CurContext->isDependentContext())
+ return;
+
+ switch (ExprEvalContexts.back().Context) {
+ case Unevaluated:
+ // We are in an expression that is not potentially evaluated; do nothing.
+ return;
+
+ case PotentiallyEvaluated:
+ // We are in a potentially-evaluated expression, so this declaration is
+ // "used"; handle this below.
+ break;
+
+ case PotentiallyPotentiallyEvaluated:
+ // We are in an expression that may be potentially evaluated; queue this
+ // declaration reference until we know whether the expression is
+ // potentially evaluated.
+ ExprEvalContexts.back().addReferencedDecl(Loc, D);
+ return;
+
+ case PotentiallyEvaluatedIfUsed:
+ // Referenced declarations will only be used if the construct in the
+ // containing expression is used.
+ return;
+ }
+
+ // Note that this declaration has been used.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ unsigned TypeQuals;
+ if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
+ if (Constructor->getParent()->hasTrivialConstructor())
+ return;
+ if (!Constructor->isUsed(false))
+ DefineImplicitDefaultConstructor(Loc, Constructor);
+ } else if (Constructor->isImplicit() &&
+ Constructor->isCopyConstructor(TypeQuals)) {
+ if (!Constructor->isUsed(false))
+ DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
+ }
+
+ MarkVTableUsed(Loc, Constructor->getParent());
+ } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+ if (Destructor->isImplicit() && !Destructor->isUsed(false))
+ DefineImplicitDestructor(Loc, Destructor);
+ if (Destructor->isVirtual())
+ MarkVTableUsed(Loc, Destructor->getParent());
+ } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
+ if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
+ MethodDecl->getOverloadedOperator() == OO_Equal) {
+ if (!MethodDecl->isUsed(false))
+ DefineImplicitCopyAssignment(Loc, MethodDecl);
+ } else if (MethodDecl->isVirtual())
+ MarkVTableUsed(Loc, MethodDecl->getParent());
+ }
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // Recursive functions should be marked when used from another function.
+ if (CurContext == Function) return;
+
+ // Implicit instantiation of function templates and member functions of
+ // class templates.
+ if (Function->isImplicitlyInstantiable()) {
+ bool AlreadyInstantiated = false;
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = Function->getTemplateSpecializationInfo()) {
+ if (SpecInfo->getPointOfInstantiation().isInvalid())
+ SpecInfo->setPointOfInstantiation(Loc);
+ else if (SpecInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
+ AlreadyInstantiated = true;
+ } else if (MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->setPointOfInstantiation(Loc);
+ else if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
+ AlreadyInstantiated = true;
+ }
+
+ if (!AlreadyInstantiated) {
+ if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
+ cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
+ PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
+ Loc));
+ else
+ PendingInstantiations.push_back(std::make_pair(Function, Loc));
+ }
+ } else {
+ // Walk redefinitions, as some of them may be instantiable.
+ for (FunctionDecl::redecl_iterator i(Function->redecls_begin()),
+ e(Function->redecls_end()); i != e; ++i) {
+ if (!i->isUsed(false) && i->isImplicitlyInstantiable())
+ MarkDeclarationReferenced(Loc, *i);
+ }
+ }
+
+ // Keep track of used but undefined functions.
+ if (!Function->isPure() && !Function->hasBody() &&
+ Function->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+
+ Function->setUsed(true);
+ return;
+ }
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ // Implicit instantiation of static data members of class templates.
+ if (Var->isStaticDataMember() &&
+ Var->getInstantiatedFromStaticDataMember()) {
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ if (MSInfo->getPointOfInstantiation().isInvalid() &&
+ MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
+ MSInfo->setPointOfInstantiation(Loc);
+ PendingInstantiations.push_back(std::make_pair(Var, Loc));
+ }
+ }
+
+ // Keep track of used but undefined variables.
+ if (Var->hasDefinition() == VarDecl::DeclarationOnly
+ && Var->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+
+ D->setUsed(true);
+ return;
+ }
+}
+
+namespace {
+ // Mark all of the declarations referenced
+ // FIXME: Not fully implemented yet! We need to have a better understanding
+ // of when we're entering
+ class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
+ Sema &S;
+ SourceLocation Loc;
+
+ public:
+ typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
+
+ MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
+
+ bool TraverseTemplateArgument(const TemplateArgument &Arg);
+ bool TraverseRecordType(RecordType *T);
+ };
+}
+
+bool MarkReferencedDecls::TraverseTemplateArgument(
+ const TemplateArgument &Arg) {
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ S.MarkDeclarationReferenced(Loc, Arg.getAsDecl());
+ }
+
+ return Inherited::TraverseTemplateArgument(Arg);
+}
+
+bool MarkReferencedDecls::TraverseRecordType(RecordType *T) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
+ const TemplateArgumentList &Args = Spec->getTemplateArgs();
+ return TraverseTemplateArguments(Args.data(), Args.size());
+ }
+
+ return true;
+}
+
+void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
+ MarkReferencedDecls Marker(*this, Loc);
+ Marker.TraverseType(Context.getCanonicalType(T));
+}
+
+namespace {
+ /// \brief Helper class that marks all of the declarations referenced by
+ /// potentially-evaluated subexpressions as "referenced".
+ class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
+ Sema &S;
+
+ public:
+ typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited;
+
+ explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { }
+
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ S.MarkDeclarationReferenced(E->getLocation(), E->getDecl());
+ }
+
+ void VisitMemberExpr(MemberExpr *E) {
+ S.MarkDeclarationReferenced(E->getMemberLoc(), E->getMemberDecl());
+ Inherited::VisitMemberExpr(E);
+ }
+
+ void VisitCXXNewExpr(CXXNewExpr *E) {
+ if (E->getConstructor())
+ S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor());
+ if (E->getOperatorNew())
+ S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorNew());
+ if (E->getOperatorDelete())
+ S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete());
+ Inherited::VisitCXXNewExpr(E);
+ }
+
+ void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ if (E->getOperatorDelete())
+ S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete());
+ QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ S.MarkDeclarationReferenced(E->getLocStart(),
+ S.LookupDestructor(Record));
+ }
+
+ Inherited::VisitCXXDeleteExpr(E);
+ }
+
+ void VisitCXXConstructExpr(CXXConstructExpr *E) {
+ S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor());
+ Inherited::VisitCXXConstructExpr(E);
+ }
+
+ void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ S.MarkDeclarationReferenced(E->getLocation(), E->getDecl());
+ }
+
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ Visit(E->getExpr());
+ }
+ };
+}
+
+/// \brief Mark any declarations that appear within this expression or any
+/// potentially-evaluated subexpressions as "referenced".
+void Sema::MarkDeclarationsReferencedInExpr(Expr *E) {
+ EvaluatedExprMarker(*this).Visit(E);
+}
+
+/// \brief Emit a diagnostic that describes an effect on the run-time behavior
+/// of the program being compiled.
+///
+/// This routine emits the given diagnostic when the code currently being
+/// type-checked is "potentially evaluated", meaning that there is a
+/// possibility that the code will actually be executable. Code in sizeof()
+/// expressions, code used only during overload resolution, etc., are not
+/// potentially evaluated. This routine will suppress such diagnostics or,
+/// in the absolutely nutty case of potentially potentially evaluated
+/// expressions (C++ typeid), queue the diagnostic to potentially emit it
+/// later.
+///
+/// This routine should be used for all diagnostics that describe the run-time
+/// behavior of a program, such as passing a non-POD value through an ellipsis.
+/// Failure to do so will likely result in spurious diagnostics or failures
+/// during overload resolution or within sizeof/alignof/typeof/typeid.
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
+ const PartialDiagnostic &PD) {
+ switch (ExprEvalContexts.back().Context ) {
+ case Unevaluated:
+ // The argument will never be evaluated, so don't complain.
+ break;
+
+ case PotentiallyEvaluated:
+ case PotentiallyEvaluatedIfUsed:
+ Diag(Loc, PD);
+ return true;
+
+ case PotentiallyPotentiallyEvaluated:
+ ExprEvalContexts.back().addDiagnostic(Loc, PD);
+ break;
+ }
+
+ return false;
+}
+
+bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+ CallExpr *CE, FunctionDecl *FD) {
+ if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())
+ return false;
+
+ PartialDiagnostic Note =
+ FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here)
+ << FD->getDeclName() : PDiag();
+ SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation();
+
+ if (RequireCompleteType(Loc, ReturnType,
+ FD ?
+ PDiag(diag::err_call_function_incomplete_return)
+ << CE->getSourceRange() << FD->getDeclName() :
+ PDiag(diag::err_call_incomplete_return)
+ << CE->getSourceRange(),
+ std::make_pair(NoteLoc, Note)))
+ return true;
+
+ return false;
+}
+
+// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses
+// will prevent this condition from triggering, which is what we want.
+void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
+ SourceLocation Loc;
+
+ unsigned diagnostic = diag::warn_condition_is_assignment;
+ bool IsOrAssign = false;
+
+ if (isa<BinaryOperator>(E)) {
+ BinaryOperator *Op = cast<BinaryOperator>(E);
+ if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign)
+ return;
+
+ IsOrAssign = Op->getOpcode() == BO_OrAssign;
+
+ // Greylist some idioms by putting them into a warning subcategory.
+ if (ObjCMessageExpr *ME
+ = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+ Selector Sel = ME->getSelector();
+
+ // self = [<foo> init...]
+ if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init"))
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+
+ // <foo> = [<bar> nextObject]
+ else if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "nextObject")
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+ }
+
+ Loc = Op->getOperatorLoc();
+ } else if (isa<CXXOperatorCallExpr>(E)) {
+ CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E);
+ if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual)
+ return;
+
+ IsOrAssign = Op->getOperator() == OO_PipeEqual;
+ Loc = Op->getOperatorLoc();
+ } else {
+ // Not an assignment.
+ return;
+ }
+
+ SourceLocation Open = E->getSourceRange().getBegin();
+ SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
+
+ Diag(Loc, diagnostic) << E->getSourceRange();
+
+ if (IsOrAssign)
+ Diag(Loc, diag::note_condition_or_assign_to_comparison)
+ << FixItHint::CreateReplacement(Loc, "!=");
+ else
+ Diag(Loc, diag::note_condition_assign_to_comparison)
+ << FixItHint::CreateReplacement(Loc, "==");
+
+ Diag(Loc, diag::note_condition_assign_silence)
+ << FixItHint::CreateInsertion(Open, "(")
+ << FixItHint::CreateInsertion(Close, ")");
+}
+
+/// \brief Redundant parentheses over an equality comparison can indicate
+/// that the user intended an assignment used as condition.
+void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) {
+ // Don't warn if the parens came from a macro.
+ SourceLocation parenLoc = parenE->getLocStart();
+ if (parenLoc.isInvalid() || parenLoc.isMacroID())
+ return;
+
+ Expr *E = parenE->IgnoreParens();
+
+ if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E))
+ if (opE->getOpcode() == BO_EQ &&
+ opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context)
+ == Expr::MLV_Valid) {
+ SourceLocation Loc = opE->getOperatorLoc();
+
+ Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
+ Diag(Loc, diag::note_equality_comparison_to_assign)
+ << FixItHint::CreateReplacement(Loc, "=");
+ Diag(Loc, diag::note_equality_comparison_silence)
+ << FixItHint::CreateRemoval(parenE->getSourceRange().getBegin())
+ << FixItHint::CreateRemoval(parenE->getSourceRange().getEnd());
+ }
+}
+
+bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
+ DiagnoseAssignmentAsCondition(E);
+ if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
+ DiagnoseEqualityWithExtraParens(parenE);
+
+ if (!E->isTypeDependent()) {
+ if (E->isBoundMemberFunction(Context))
+ return Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+ << E->getSourceRange();
+
+ if (getLangOptions().CPlusPlus)
+ return CheckCXXBooleanCondition(E); // C++ 6.4p4
+
+ DefaultFunctionArrayLvalueConversion(E);
+
+ QualType T = E->getType();
+ if (!T->isScalarType()) // C99 6.8.4.1p1
+ return Diag(Loc, diag::err_typecheck_statement_requires_scalar)
+ << T << E->getSourceRange();
+ }
+
+ return false;
+}
+
+ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+ Expr *Sub) {
+ if (!Sub)
+ return ExprError();
+
+ if (CheckBooleanCondition(Sub, Loc))
+ return ExprError();
+
+ return Owned(Sub);
+}
+
+/// Check for operands with placeholder types and complain if found.
+/// Returns true if there was an error and no recovery was possible.
+ExprResult Sema::CheckPlaceholderExpr(Expr *E, SourceLocation Loc) {
+ const BuiltinType *BT = E->getType()->getAs<BuiltinType>();
+ if (!BT || !BT->isPlaceholderType()) return Owned(E);
+
+ // If this is overload, check for a single overload.
+ assert(BT->getKind() == BuiltinType::Overload);
+
+ if (FunctionDecl *Specialization
+ = ResolveSingleFunctionTemplateSpecialization(E)) {
+ // The access doesn't really matter in this case.
+ DeclAccessPair Found = DeclAccessPair::make(Specialization,
+ Specialization->getAccess());
+ E = FixOverloadedFunctionReference(E, Found, Specialization);
+ if (!E) return ExprError();
+ return Owned(E);
+ }
+
+ Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange();
+ return ExprError();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
new file mode 100644
index 0000000..f9c2c9a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -0,0 +1,3911 @@
+//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace clang;
+using namespace sema;
+
+ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II,
+ SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectTypePtr,
+ bool EnteringContext) {
+ // Determine where to perform name lookup.
+
+ // FIXME: This area of the standard is very messy, and the current
+ // wording is rather unclear about which scopes we search for the
+ // destructor name; see core issues 399 and 555. Issue 399 in
+ // particular shows where the current description of destructor name
+ // lookup is completely out of line with existing practice, e.g.,
+ // this appears to be ill-formed:
+ //
+ // namespace N {
+ // template <typename T> struct S {
+ // ~S();
+ // };
+ // }
+ //
+ // void f(N::S<int>* s) {
+ // s->N::S<int>::~S();
+ // }
+ //
+ // See also PR6358 and PR6359.
+ // For this reason, we're currently only doing the C++03 version of this
+ // code; the C++0x version has to wait until we get a proper spec.
+ QualType SearchType;
+ DeclContext *LookupCtx = 0;
+ bool isDependent = false;
+ bool LookInScope = false;
+
+ // If we have an object type, it's because we are in a
+ // pseudo-destructor-expression or a member access expression, and
+ // we know what type we're looking for.
+ if (ObjectTypePtr)
+ SearchType = GetTypeFromParser(ObjectTypePtr);
+
+ if (SS.isSet()) {
+ NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+
+ bool AlreadySearched = false;
+ bool LookAtPrefix = true;
+ // C++ [basic.lookup.qual]p6:
+ // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
+ // the type-names are looked up as types in the scope designated by the
+ // nested-name-specifier. In a qualified-id of the form:
+ //
+ // ::[opt] nested-name-specifier ~ class-name
+ //
+ // where the nested-name-specifier designates a namespace scope, and in
+ // a qualified-id of the form:
+ //
+ // ::opt nested-name-specifier class-name :: ~ class-name
+ //
+ // the class-names are looked up as types in the scope designated by
+ // the nested-name-specifier.
+ //
+ // Here, we check the first case (completely) and determine whether the
+ // code below is permitted to look at the prefix of the
+ // nested-name-specifier.
+ DeclContext *DC = computeDeclContext(SS, EnteringContext);
+ if (DC && DC->isFileContext()) {
+ AlreadySearched = true;
+ LookupCtx = DC;
+ isDependent = false;
+ } else if (DC && isa<CXXRecordDecl>(DC))
+ LookAtPrefix = false;
+
+ // The second case from the C++03 rules quoted further above.
+ NestedNameSpecifier *Prefix = 0;
+ if (AlreadySearched) {
+ // Nothing left to do.
+ } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
+ CXXScopeSpec PrefixSS;
+ PrefixSS.setScopeRep(Prefix);
+ LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(PrefixSS);
+ } else if (ObjectTypePtr) {
+ LookupCtx = computeDeclContext(SearchType);
+ isDependent = SearchType->isDependentType();
+ } else {
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = LookupCtx && LookupCtx->isDependentContext();
+ }
+
+ LookInScope = false;
+ } else if (ObjectTypePtr) {
+ // C++ [basic.lookup.classref]p3:
+ // If the unqualified-id is ~type-name, the type-name is looked up
+ // in the context of the entire postfix-expression. If the type T
+ // of the object expression is of a class type C, the type-name is
+ // also looked up in the scope of class C. At least one of the
+ // lookups shall find a name that refers to (possibly
+ // cv-qualified) T.
+ LookupCtx = computeDeclContext(SearchType);
+ isDependent = SearchType->isDependentType();
+ assert((isDependent || !SearchType->isIncompleteType()) &&
+ "Caller should have completed object type");
+
+ LookInScope = true;
+ } else {
+ // Perform lookup into the current scope (only).
+ LookInScope = true;
+ }
+
+ LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
+ for (unsigned Step = 0; Step != 2; ++Step) {
+ // Look for the name first in the computed lookup context (if we
+ // have one) and, if that fails to find a match, in the sope (if
+ // we're allowed to look there).
+ Found.clear();
+ if (Step == 0 && LookupCtx)
+ LookupQualifiedName(Found, LookupCtx);
+ else if (Step == 1 && LookInScope && S)
+ LookupName(Found, S);
+ else
+ continue;
+
+ // FIXME: Should we be suppressing ambiguities here?
+ if (Found.isAmbiguous())
+ return ParsedType();
+
+ if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
+ QualType T = Context.getTypeDeclType(Type);
+
+ if (SearchType.isNull() || SearchType->isDependentType() ||
+ Context.hasSameUnqualifiedType(T, SearchType)) {
+ // We found our type!
+
+ return ParsedType::make(T);
+ }
+ }
+
+ // If the name that we found is a class template name, and it is
+ // the same name as the template name in the last part of the
+ // nested-name-specifier (if present) or the object type, then
+ // this is the destructor for that class.
+ // FIXME: This is a workaround until we get real drafting for core
+ // issue 399, for which there isn't even an obvious direction.
+ if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) {
+ QualType MemberOfType;
+ if (SS.isSet()) {
+ if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
+ // Figure out the type of the context, if it has one.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx))
+ MemberOfType = Context.getTypeDeclType(Record);
+ }
+ }
+ if (MemberOfType.isNull())
+ MemberOfType = SearchType;
+
+ if (MemberOfType.isNull())
+ continue;
+
+ // We're referring into a class template specialization. If the
+ // class template we found is the same as the template being
+ // specialized, we found what we are looking for.
+ if (const RecordType *Record = MemberOfType->getAs<RecordType>()) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+ if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
+ Template->getCanonicalDecl())
+ return ParsedType::make(MemberOfType);
+ }
+
+ continue;
+ }
+
+ // We're referring to an unresolved class template
+ // specialization. Determine whether we class template we found
+ // is the same as the template being specialized or, if we don't
+ // know which template is being specialized, that it at least
+ // has the same name.
+ if (const TemplateSpecializationType *SpecType
+ = MemberOfType->getAs<TemplateSpecializationType>()) {
+ TemplateName SpecName = SpecType->getTemplateName();
+
+ // The class template we found is the same template being
+ // specialized.
+ if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
+ if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
+ return ParsedType::make(MemberOfType);
+
+ continue;
+ }
+
+ // The class template we found has the same name as the
+ // (dependent) template name being specialized.
+ if (DependentTemplateName *DepTemplate
+ = SpecName.getAsDependentTemplateName()) {
+ if (DepTemplate->isIdentifier() &&
+ DepTemplate->getIdentifier() == Template->getIdentifier())
+ return ParsedType::make(MemberOfType);
+
+ continue;
+ }
+ }
+ }
+ }
+
+ if (isDependent) {
+ // We didn't find our type, but that's okay: it's dependent
+ // anyway.
+ NestedNameSpecifier *NNS = 0;
+ SourceRange Range;
+ if (SS.isSet()) {
+ NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ Range = SourceRange(SS.getRange().getBegin(), NameLoc);
+ } else {
+ NNS = NestedNameSpecifier::Create(Context, &II);
+ Range = SourceRange(NameLoc);
+ }
+
+ QualType T = CheckTypenameType(ETK_None, NNS, II,
+ SourceLocation(),
+ Range, NameLoc);
+ return ParsedType::make(T);
+ }
+
+ if (ObjectTypePtr)
+ Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << &II;
+ else
+ Diag(NameLoc, diag::err_destructor_class_name);
+
+ return ParsedType();
+}
+
+/// \brief Build a C++ typeid expression with a type operand.
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc) {
+ // C++ [expr.typeid]p4:
+ // The top-level cv-qualifiers of the lvalue expression or the type-id
+ // that is the operand of typeid are always ignored.
+ // If the type of the type-id is a class type or a reference to a class
+ // type, the class shall be completely-defined.
+ Qualifiers Quals;
+ QualType T
+ = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(),
+ Quals);
+ if (T->getAs<RecordType>() &&
+ RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
+ return ExprError();
+
+ return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
+ Operand,
+ SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// \brief Build a C++ typeid expression with an expression operand.
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *E,
+ SourceLocation RParenLoc) {
+ bool isUnevaluatedOperand = true;
+ if (E && !E->isTypeDependent()) {
+ QualType T = E->getType();
+ if (const RecordType *RecordT = T->getAs<RecordType>()) {
+ CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
+ // C++ [expr.typeid]p3:
+ // [...] If the type of the expression is a class type, the class
+ // shall be completely-defined.
+ if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
+ return ExprError();
+
+ // C++ [expr.typeid]p3:
+ // When typeid is applied to an expression other than an glvalue of a
+ // polymorphic class type [...] [the] expression is an unevaluated
+ // operand. [...]
+ if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
+ isUnevaluatedOperand = false;
+
+ // We require a vtable to query the type at run time.
+ MarkVTableUsed(TypeidLoc, RecordD);
+ }
+ }
+
+ // C++ [expr.typeid]p4:
+ // [...] If the type of the type-id is a reference to a possibly
+ // cv-qualified type, the result of the typeid expression refers to a
+ // std::type_info object representing the cv-unqualified referenced
+ // type.
+ Qualifiers Quals;
+ QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
+ if (!Context.hasSameType(T, UnqualT)) {
+ T = UnqualT;
+ ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E));
+ }
+ }
+
+ // If this is an unevaluated operand, clear out the set of
+ // declaration references we have been computing and eliminate any
+ // temporaries introduced in its computation.
+ if (isUnevaluatedOperand)
+ ExprEvalContexts.back().Context = Unevaluated;
+
+ return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
+ E,
+ SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression);
+ExprResult
+Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+ bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+ // Find the std::type_info type.
+ if (!StdNamespace)
+ return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+
+ if (!CXXTypeInfoDecl) {
+ IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
+ LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
+ LookupQualifiedName(R, getStdNamespace());
+ CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
+ if (!CXXTypeInfoDecl)
+ return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
+ }
+
+ QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl);
+
+ if (isType) {
+ // The operand is a type; handle it as such.
+ TypeSourceInfo *TInfo = 0;
+ QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
+ &TInfo);
+ if (T.isNull())
+ return ExprError();
+
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
+
+ return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc);
+ }
+
+ // The operand is an expression.
+ return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
+}
+
+/// Retrieve the UuidAttr associated with QT.
+static UuidAttr *GetUuidAttrOfType(QualType QT) {
+ // Optionally remove one level of pointer, reference or array indirection.
+ const Type *Ty = QT.getTypePtr();;
+ if (QT->isPointerType() || QT->isReferenceType())
+ Ty = QT->getPointeeType().getTypePtr();
+ else if (QT->isArrayType())
+ Ty = cast<ArrayType>(QT)->getElementType().getTypePtr();
+
+ // Loop all class definition and declaration looking for an uuid attribute.
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ while (RD) {
+ if (UuidAttr *Uuid = RD->getAttr<UuidAttr>())
+ return Uuid;
+ RD = RD->getPreviousDeclaration();
+ }
+ return 0;
+}
+
+/// \brief Build a Microsoft __uuidof expression with a type operand.
+ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc) {
+ if (!Operand->getType()->isDependentType()) {
+ if (!GetUuidAttrOfType(Operand->getType()))
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ }
+
+ // FIXME: add __uuidof semantic analysis for type operand.
+ return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
+ Operand,
+ SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// \brief Build a Microsoft __uuidof expression with an expression operand.
+ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *E,
+ SourceLocation RParenLoc) {
+ if (!E->getType()->isDependentType()) {
+ if (!GetUuidAttrOfType(E->getType()) &&
+ !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
+ }
+ // FIXME: add __uuidof semantic analysis for type operand.
+ return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
+ E,
+ SourceRange(TypeidLoc, RParenLoc)));
+}
+
+/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression);
+ExprResult
+Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+ bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+ // If MSVCGuidDecl has not been cached, do the lookup.
+ if (!MSVCGuidDecl) {
+ IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID");
+ LookupResult R(*this, GuidII, SourceLocation(), LookupTagName);
+ LookupQualifiedName(R, Context.getTranslationUnitDecl());
+ MSVCGuidDecl = R.getAsSingle<RecordDecl>();
+ if (!MSVCGuidDecl)
+ return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof));
+ }
+
+ QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl);
+
+ if (isType) {
+ // The operand is a type; handle it as such.
+ TypeSourceInfo *TInfo = 0;
+ QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
+ &TInfo);
+ if (T.isNull())
+ return ExprError();
+
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
+
+ return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc);
+ }
+
+ // The operand is an expression.
+ return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
+}
+
+/// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ExprResult
+Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
+ assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
+ "Unknown C++ Boolean value!");
+ return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true,
+ Context.BoolTy, OpLoc));
+}
+
+/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ExprResult
+Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
+ return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
+}
+
+/// ActOnCXXThrow - Parse throw expressions.
+ExprResult
+Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) {
+ if (!getLangOptions().Exceptions)
+ Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
+
+ if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
+ return ExprError();
+ return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc));
+}
+
+/// CheckCXXThrowOperand - Validate the operand of a throw.
+bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
+ // C++ [except.throw]p3:
+ // A throw-expression initializes a temporary object, called the exception
+ // object, the type of which is determined by removing any top-level
+ // cv-qualifiers from the static type of the operand of throw and adjusting
+ // the type from "array of T" or "function returning T" to "pointer to T"
+ // or "pointer to function returning T", [...]
+ if (E->getType().hasQualifiers())
+ ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
+ CastCategory(E));
+
+ DefaultFunctionArrayConversion(E);
+
+ // If the type of the exception would be an incomplete type or a pointer
+ // to an incomplete type other than (cv) void the program is ill-formed.
+ QualType Ty = E->getType();
+ bool isPointer = false;
+ if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
+ Ty = Ptr->getPointeeType();
+ isPointer = true;
+ }
+ if (!isPointer || !Ty->isVoidType()) {
+ if (RequireCompleteType(ThrowLoc, Ty,
+ PDiag(isPointer ? diag::err_throw_incomplete_ptr
+ : diag::err_throw_incomplete)
+ << E->getSourceRange()))
+ return true;
+
+ if (RequireNonAbstractType(ThrowLoc, E->getType(),
+ PDiag(diag::err_throw_abstract_type)
+ << E->getSourceRange()))
+ return true;
+ }
+
+ // Initialize the exception result. This implicitly weeds out
+ // abstract types or types with inaccessible copy constructors.
+ const VarDecl *NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
+
+ // FIXME: Determine whether we can elide this copy per C++0x [class.copy]p32.
+ InitializedEntity Entity =
+ InitializedEntity::InitializeException(ThrowLoc, E->getType(),
+ /*NRVO=*/false);
+ ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
+ QualType(), E);
+ if (Res.isInvalid())
+ return true;
+ E = Res.takeAs<Expr>();
+
+ // If the exception has class type, we need additional handling.
+ const RecordType *RecordTy = Ty->getAs<RecordType>();
+ if (!RecordTy)
+ return false;
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+
+ // If we are throwing a polymorphic class type or pointer thereof,
+ // exception handling will make use of the vtable.
+ MarkVTableUsed(ThrowLoc, RD);
+
+ // If a pointer is thrown, the referenced object will not be destroyed.
+ if (isPointer)
+ return false;
+
+ // If the class has a non-trivial destructor, we must be able to call it.
+ if (RD->hasTrivialDestructor())
+ return false;
+
+ CXXDestructorDecl *Destructor
+ = const_cast<CXXDestructorDecl*>(LookupDestructor(RD));
+ if (!Destructor)
+ return false;
+
+ MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+ CheckDestructorAccess(E->getExprLoc(), Destructor,
+ PDiag(diag::err_access_dtor_exception) << Ty);
+ return false;
+}
+
+CXXMethodDecl *Sema::tryCaptureCXXThis() {
+ // Ignore block scopes: we can capture through them.
+ // Ignore nested enum scopes: we'll diagnose non-constant expressions
+ // where they're invalid, and other uses are legitimate.
+ // Don't ignore nested class scopes: you can't use 'this' in a local class.
+ DeclContext *DC = CurContext;
+ while (true) {
+ if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
+ else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext();
+ else break;
+ }
+
+ // If we're not in an instance method, error out.
+ CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC);
+ if (!method || !method->isInstance())
+ return 0;
+
+ // Mark that we're closing on 'this' in all the block scopes, if applicable.
+ for (unsigned idx = FunctionScopes.size() - 1;
+ isa<BlockScopeInfo>(FunctionScopes[idx]);
+ --idx)
+ cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true;
+
+ return method;
+}
+
+ExprResult Sema::ActOnCXXThis(SourceLocation loc) {
+ /// C++ 9.3.2: In the body of a non-static member function, the keyword this
+ /// is a non-lvalue expression whose value is the address of the object for
+ /// which the function is called.
+
+ CXXMethodDecl *method = tryCaptureCXXThis();
+ if (!method) return Diag(loc, diag::err_invalid_this_use);
+
+ return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context),
+ /*isImplicit=*/false));
+}
+
+ExprResult
+Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg exprs,
+ SourceLocation RParenLoc) {
+ if (!TypeRep)
+ return ExprError();
+
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
+
+ return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
+}
+
+/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+/// Can be interpreted either as function-style casting ("int(x)")
+/// or class type construction ("ClassType(x,y,z)")
+/// or creation of a value-initialized type ("int()").
+ExprResult
+Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
+ SourceLocation LParenLoc,
+ MultiExprArg exprs,
+ SourceLocation RParenLoc) {
+ QualType Ty = TInfo->getType();
+ unsigned NumExprs = exprs.size();
+ Expr **Exprs = (Expr**)exprs.get();
+ SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
+ SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
+
+ if (Ty->isDependentType() ||
+ CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
+ exprs.release();
+
+ return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo,
+ LParenLoc,
+ Exprs, NumExprs,
+ RParenLoc));
+ }
+
+ if (Ty->isArrayType())
+ return ExprError(Diag(TyBeginLoc,
+ diag::err_value_init_for_array_type) << FullRange);
+ if (!Ty->isVoidType() &&
+ RequireCompleteType(TyBeginLoc, Ty,
+ PDiag(diag::err_invalid_incomplete_type_use)
+ << FullRange))
+ return ExprError();
+
+ if (RequireNonAbstractType(TyBeginLoc, Ty,
+ diag::err_allocation_of_abstract_type))
+ return ExprError();
+
+
+ // C++ [expr.type.conv]p1:
+ // If the expression list is a single expression, the type conversion
+ // expression is equivalent (in definedness, and if defined in meaning) to the
+ // corresponding cast expression.
+ //
+ if (NumExprs == 1) {
+ CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
+ CXXCastPath BasePath;
+ if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
+ Kind, VK, BasePath,
+ /*FunctionalStyle=*/true))
+ return ExprError();
+
+ exprs.release();
+
+ return Owned(CXXFunctionalCastExpr::Create(Context,
+ Ty.getNonLValueExprType(Context),
+ VK, TInfo, TyBeginLoc, Kind,
+ Exprs[0], &BasePath,
+ RParenLoc));
+ }
+
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
+ InitializationKind Kind
+ = NumExprs ? InitializationKind::CreateDirect(TyBeginLoc,
+ LParenLoc, RParenLoc)
+ : InitializationKind::CreateValue(TyBeginLoc,
+ LParenLoc, RParenLoc);
+ InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));
+
+ // FIXME: Improve AST representation?
+ return move(Result);
+}
+
+/// doesUsualArrayDeleteWantSize - Answers whether the usual
+/// operator delete[] for the given type has a size_t parameter.
+static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
+ QualType allocType) {
+ const RecordType *record =
+ allocType->getBaseElementTypeUnsafe()->getAs<RecordType>();
+ if (!record) return false;
+
+ // Try to find an operator delete[] in class scope.
+
+ DeclarationName deleteName =
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
+ LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(ops, record->getDecl());
+
+ // We're just doing this for information.
+ ops.suppressDiagnostics();
+
+ // Very likely: there's no operator delete[].
+ if (ops.empty()) return false;
+
+ // If it's ambiguous, it should be illegal to call operator delete[]
+ // on this thing, so it doesn't matter if we allocate extra space or not.
+ if (ops.isAmbiguous()) return false;
+
+ LookupResult::Filter filter = ops.makeFilter();
+ while (filter.hasNext()) {
+ NamedDecl *del = filter.next()->getUnderlyingDecl();
+
+ // C++0x [basic.stc.dynamic.deallocation]p2:
+ // A template instance is never a usual deallocation function,
+ // regardless of its signature.
+ if (isa<FunctionTemplateDecl>(del)) {
+ filter.erase();
+ continue;
+ }
+
+ // C++0x [basic.stc.dynamic.deallocation]p2:
+ // If class T does not declare [an operator delete[] with one
+ // parameter] but does declare a member deallocation function
+ // named operator delete[] with exactly two parameters, the
+ // second of which has type std::size_t, then this function
+ // is a usual deallocation function.
+ if (!cast<CXXMethodDecl>(del)->isUsualDeallocationFunction()) {
+ filter.erase();
+ continue;
+ }
+ }
+ filter.done();
+
+ if (!ops.isSingleResult()) return false;
+
+ const FunctionDecl *del = cast<FunctionDecl>(ops.getFoundDecl());
+ return (del->getNumParams() == 2);
+}
+
+/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
+/// @code new (memory) int[size][4] @endcode
+/// or
+/// @code ::new Foo(23, "hello") @endcode
+/// For the interpretation of this heap of arguments, consult the base version.
+ExprResult
+Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen, SourceRange TypeIdParens,
+ Declarator &D, SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen) {
+ bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
+ Expr *ArraySize = 0;
+ // If the specified type is an array, unwrap it and save the expression.
+ if (D.getNumTypeObjects() > 0 &&
+ D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
+ DeclaratorChunk &Chunk = D.getTypeObject(0);
+ if (TypeContainsAuto)
+ return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto)
+ << D.getSourceRange());
+ if (Chunk.Arr.hasStatic)
+ return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
+ << D.getSourceRange());
+ if (!Chunk.Arr.NumElts)
+ return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
+ << D.getSourceRange());
+
+ ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
+ D.DropFirstTypeObject();
+ }
+
+ // Every dimension shall be of constant size.
+ if (ArraySize) {
+ for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) {
+ if (D.getTypeObject(I).Kind != DeclaratorChunk::Array)
+ break;
+
+ DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr;
+ if (Expr *NumElts = (Expr *)Array.NumElts) {
+ if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
+ !NumElts->isIntegerConstantExpr(Context)) {
+ Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst)
+ << NumElts->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+ }
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0, /*OwnedDecl=*/0,
+ /*AllowAuto=*/true);
+ QualType AllocType = TInfo->getType();
+ if (D.isInvalidType())
+ return ExprError();
+
+ return BuildCXXNew(StartLoc, UseGlobal,
+ PlacementLParen,
+ move(PlacementArgs),
+ PlacementRParen,
+ TypeIdParens,
+ AllocType,
+ TInfo,
+ ArraySize,
+ ConstructorLParen,
+ move(ConstructorArgs),
+ ConstructorRParen,
+ TypeContainsAuto);
+}
+
+ExprResult
+Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocType,
+ TypeSourceInfo *AllocTypeInfo,
+ Expr *ArraySize,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen,
+ bool TypeMayContainAuto) {
+ SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
+
+ // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+ if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
+ if (ConstructorArgs.size() == 0)
+ return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
+ << AllocType << TypeRange);
+ if (ConstructorArgs.size() != 1) {
+ Expr *FirstBad = ConstructorArgs.get()[1];
+ return ExprError(Diag(FirstBad->getSourceRange().getBegin(),
+ diag::err_auto_new_ctor_multiple_expressions)
+ << AllocType << TypeRange);
+ }
+ QualType DeducedType;
+ if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType))
+ return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
+ << AllocType
+ << ConstructorArgs.get()[0]->getType()
+ << TypeRange
+ << ConstructorArgs.get()[0]->getSourceRange());
+
+ AllocType = DeducedType;
+ AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc);
+ }
+
+ // Per C++0x [expr.new]p5, the type being constructed may be a
+ // typedef of an array type.
+ if (!ArraySize) {
+ if (const ConstantArrayType *Array
+ = Context.getAsConstantArrayType(AllocType)) {
+ ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
+ Context.getSizeType(),
+ TypeRange.getEnd());
+ AllocType = Array->getElementType();
+ }
+ }
+
+ if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
+ return ExprError();
+
+ QualType ResultType = Context.getPointerType(AllocType);
+
+ // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
+ // or enumeration type with a non-negative value."
+ if (ArraySize && !ArraySize->isTypeDependent()) {
+
+ QualType SizeType = ArraySize->getType();
+
+ ExprResult ConvertedSize
+ = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize,
+ PDiag(diag::err_array_size_not_integral),
+ PDiag(diag::err_array_size_incomplete_type)
+ << ArraySize->getSourceRange(),
+ PDiag(diag::err_array_size_explicit_conversion),
+ PDiag(diag::note_array_size_conversion),
+ PDiag(diag::err_array_size_ambiguous_conversion),
+ PDiag(diag::note_array_size_conversion),
+ PDiag(getLangOptions().CPlusPlus0x? 0
+ : diag::ext_array_size_conversion));
+ if (ConvertedSize.isInvalid())
+ return ExprError();
+
+ ArraySize = ConvertedSize.take();
+ SizeType = ArraySize->getType();
+ if (!SizeType->isIntegralOrUnscopedEnumerationType())
+ return ExprError();
+
+ // Let's see if this is a constant < 0. If so, we reject it out of hand.
+ // We don't care about special rules, so we tell the machinery it's not
+ // evaluated - it gives us a result in more cases.
+ if (!ArraySize->isValueDependent()) {
+ llvm::APSInt Value;
+ if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+ if (Value < llvm::APSInt(
+ llvm::APInt::getNullValue(Value.getBitWidth()),
+ Value.isUnsigned()))
+ return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange());
+
+ if (!AllocType->isDependentType()) {
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_array_too_large)
+ << Value.toString(10)
+ << ArraySize->getSourceRange();
+ return ExprError();
+ }
+ }
+ } else if (TypeIdParens.isValid()) {
+ // Can't have dynamic array size when the type-id is in parentheses.
+ Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
+ << ArraySize->getSourceRange()
+ << FixItHint::CreateRemoval(TypeIdParens.getBegin())
+ << FixItHint::CreateRemoval(TypeIdParens.getEnd());
+
+ TypeIdParens = SourceRange();
+ }
+ }
+
+ ImpCastExprToType(ArraySize, Context.getSizeType(),
+ CK_IntegralCast);
+ }
+
+ FunctionDecl *OperatorNew = 0;
+ FunctionDecl *OperatorDelete = 0;
+ Expr **PlaceArgs = (Expr**)PlacementArgs.get();
+ unsigned NumPlaceArgs = PlacementArgs.size();
+
+ if (!AllocType->isDependentType() &&
+ !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&
+ FindAllocationFunctions(StartLoc,
+ SourceRange(PlacementLParen, PlacementRParen),
+ UseGlobal, AllocType, ArraySize, PlaceArgs,
+ NumPlaceArgs, OperatorNew, OperatorDelete))
+ return ExprError();
+
+ // If this is an array allocation, compute whether the usual array
+ // deallocation function for the type has a size_t parameter.
+ bool UsualArrayDeleteWantsSize = false;
+ if (ArraySize && !AllocType->isDependentType())
+ UsualArrayDeleteWantsSize
+ = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType);
+
+ llvm::SmallVector<Expr *, 8> AllPlaceArgs;
+ if (OperatorNew) {
+ // Add default arguments, if any.
+ const FunctionProtoType *Proto =
+ OperatorNew->getType()->getAs<FunctionProtoType>();
+ VariadicCallType CallType =
+ Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+
+ if (GatherArgumentsForCall(PlacementLParen, OperatorNew,
+ Proto, 1, PlaceArgs, NumPlaceArgs,
+ AllPlaceArgs, CallType))
+ return ExprError();
+
+ NumPlaceArgs = AllPlaceArgs.size();
+ if (NumPlaceArgs > 0)
+ PlaceArgs = &AllPlaceArgs[0];
+ }
+
+ bool Init = ConstructorLParen.isValid();
+ // --- Choosing a constructor ---
+ CXXConstructorDecl *Constructor = 0;
+ Expr **ConsArgs = (Expr**)ConstructorArgs.get();
+ unsigned NumConsArgs = ConstructorArgs.size();
+ ASTOwningVector<Expr*> ConvertedConstructorArgs(*this);
+
+ // Array 'new' can't have any initializers.
+ if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) {
+ SourceRange InitRange(ConsArgs[0]->getLocStart(),
+ ConsArgs[NumConsArgs - 1]->getLocEnd());
+
+ Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
+ return ExprError();
+ }
+
+ if (!AllocType->isDependentType() &&
+ !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
+ // C++0x [expr.new]p15:
+ // A new-expression that creates an object of type T initializes that
+ // object as follows:
+ InitializationKind Kind
+ // - If the new-initializer is omitted, the object is default-
+ // initialized (8.5); if no initialization is performed,
+ // the object has indeterminate value
+ = !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
+ // - Otherwise, the new-initializer is interpreted according to the
+ // initialization rules of 8.5 for direct-initialization.
+ : InitializationKind::CreateDirect(TypeRange.getBegin(),
+ ConstructorLParen,
+ ConstructorRParen);
+
+ InitializedEntity Entity
+ = InitializedEntity::InitializeNew(StartLoc, AllocType);
+ InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
+ ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
+ move(ConstructorArgs));
+ if (FullInit.isInvalid())
+ return ExprError();
+
+ // FullInit is our initializer; walk through it to determine if it's a
+ // constructor call, which CXXNewExpr handles directly.
+ if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
+ if (CXXBindTemporaryExpr *Binder
+ = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
+ FullInitExpr = Binder->getSubExpr();
+ if (CXXConstructExpr *Construct
+ = dyn_cast<CXXConstructExpr>(FullInitExpr)) {
+ Constructor = Construct->getConstructor();
+ for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
+ AEnd = Construct->arg_end();
+ A != AEnd; ++A)
+ ConvertedConstructorArgs.push_back(*A);
+ } else {
+ // Take the converted initializer.
+ ConvertedConstructorArgs.push_back(FullInit.release());
+ }
+ } else {
+ // No initialization required.
+ }
+
+ // Take the converted arguments and use them for the new expression.
+ NumConsArgs = ConvertedConstructorArgs.size();
+ ConsArgs = (Expr **)ConvertedConstructorArgs.take();
+ }
+
+ // Mark the new and delete operators as referenced.
+ if (OperatorNew)
+ MarkDeclarationReferenced(StartLoc, OperatorNew);
+ if (OperatorDelete)
+ MarkDeclarationReferenced(StartLoc, OperatorDelete);
+
+ // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
+
+ PlacementArgs.release();
+ ConstructorArgs.release();
+
+ return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
+ PlaceArgs, NumPlaceArgs, TypeIdParens,
+ ArraySize, Constructor, Init,
+ ConsArgs, NumConsArgs, OperatorDelete,
+ UsualArrayDeleteWantsSize,
+ ResultType, AllocTypeInfo,
+ StartLoc,
+ Init ? ConstructorRParen :
+ TypeRange.getEnd(),
+ ConstructorLParen, ConstructorRParen));
+}
+
+/// CheckAllocatedType - Checks that a type is suitable as the allocated type
+/// in a new-expression.
+/// dimension off and stores the size expression in ArraySize.
+bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R) {
+ // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
+ // abstract class type or array thereof.
+ if (AllocType->isFunctionType())
+ return Diag(Loc, diag::err_bad_new_type)
+ << AllocType << 0 << R;
+ else if (AllocType->isReferenceType())
+ return Diag(Loc, diag::err_bad_new_type)
+ << AllocType << 1 << R;
+ else if (!AllocType->isDependentType() &&
+ RequireCompleteType(Loc, AllocType,
+ PDiag(diag::err_new_incomplete_type)
+ << R))
+ return true;
+ else if (RequireNonAbstractType(Loc, AllocType,
+ diag::err_allocation_of_abstract_type))
+ return true;
+ else if (AllocType->isVariablyModifiedType())
+ return Diag(Loc, diag::err_variably_modified_new_type)
+ << AllocType;
+
+ return false;
+}
+
+/// \brief Determine whether the given function is a non-placement
+/// deallocation function.
+static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) {
+ if (FD->isInvalidDecl())
+ return false;
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+ return Method->isUsualDeallocationFunction();
+
+ return ((FD->getOverloadedOperator() == OO_Delete ||
+ FD->getOverloadedOperator() == OO_Array_Delete) &&
+ FD->getNumParams() == 1);
+}
+
+/// FindAllocationFunctions - Finds the overloads of operator new and delete
+/// that are appropriate for the allocation.
+bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType,
+ bool IsArray, Expr **PlaceArgs,
+ unsigned NumPlaceArgs,
+ FunctionDecl *&OperatorNew,
+ FunctionDecl *&OperatorDelete) {
+ // --- Choosing an allocation function ---
+ // C++ 5.3.4p8 - 14 & 18
+ // 1) If UseGlobal is true, only look in the global scope. Else, also look
+ // in the scope of the allocated class.
+ // 2) If an array size is given, look for operator new[], else look for
+ // operator new.
+ // 3) The first argument is always size_t. Append the arguments from the
+ // placement form.
+
+ llvm::SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs);
+ // We don't care about the actual value of this argument.
+ // FIXME: Should the Sema create the expression and embed it in the syntax
+ // tree? Or should the consumer just recalculate the value?
+ IntegerLiteral Size(Context, llvm::APInt::getNullValue(
+ Context.Target.getPointerWidth(0)),
+ Context.getSizeType(),
+ SourceLocation());
+ AllocArgs[0] = &Size;
+ std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1);
+
+ // C++ [expr.new]p8:
+ // If the allocated type is a non-array type, the allocation
+ // function's name is operator new and the deallocation function's
+ // name is operator delete. If the allocated type is an array
+ // type, the allocation function's name is operator new[] and the
+ // deallocation function's name is operator delete[].
+ DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
+ IsArray ? OO_Array_New : OO_New);
+ DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+ IsArray ? OO_Array_Delete : OO_Delete);
+
+ QualType AllocElemType = Context.getBaseElementType(AllocType);
+
+ if (AllocElemType->isRecordType() && !UseGlobal) {
+ CXXRecordDecl *Record
+ = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
+ if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+ AllocArgs.size(), Record, /*AllowMissing=*/true,
+ OperatorNew))
+ return true;
+ }
+ if (!OperatorNew) {
+ // Didn't find a member overload. Look for a global one.
+ DeclareGlobalNewDelete();
+ DeclContext *TUDecl = Context.getTranslationUnitDecl();
+ if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
+ AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
+ OperatorNew))
+ return true;
+ }
+
+ // We don't need an operator delete if we're running under
+ // -fno-exceptions.
+ if (!getLangOptions().Exceptions) {
+ OperatorDelete = 0;
+ return false;
+ }
+
+ // FindAllocationOverload can change the passed in arguments, so we need to
+ // copy them back.
+ if (NumPlaceArgs > 0)
+ std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs);
+
+ // C++ [expr.new]p19:
+ //
+ // If the new-expression begins with a unary :: operator, the
+ // deallocation function's name is looked up in the global
+ // scope. Otherwise, if the allocated type is a class type T or an
+ // array thereof, the deallocation function's name is looked up in
+ // the scope of T. If this lookup fails to find the name, or if
+ // the allocated type is not a class type or array thereof, the
+ // deallocation function's name is looked up in the global scope.
+ LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
+ if (AllocElemType->isRecordType() && !UseGlobal) {
+ CXXRecordDecl *RD
+ = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
+ LookupQualifiedName(FoundDelete, RD);
+ }
+ if (FoundDelete.isAmbiguous())
+ return true; // FIXME: clean up expressions?
+
+ if (FoundDelete.empty()) {
+ DeclareGlobalNewDelete();
+ LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
+ }
+
+ FoundDelete.suppressDiagnostics();
+
+ llvm::SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;
+
+ // Whether we're looking for a placement operator delete is dictated
+ // by whether we selected a placement operator new, not by whether
+ // we had explicit placement arguments. This matters for things like
+ // struct A { void *operator new(size_t, int = 0); ... };
+ // A *a = new A()
+ bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1);
+
+ if (isPlacementNew) {
+ // C++ [expr.new]p20:
+ // A declaration of a placement deallocation function matches the
+ // declaration of a placement allocation function if it has the
+ // same number of parameters and, after parameter transformations
+ // (8.3.5), all parameter types except the first are
+ // identical. [...]
+ //
+ // To perform this comparison, we compute the function type that
+ // the deallocation function should have, and use that type both
+ // for template argument deduction and for comparison purposes.
+ //
+ // FIXME: this comparison should ignore CC and the like.
+ QualType ExpectedFunctionType;
+ {
+ const FunctionProtoType *Proto
+ = OperatorNew->getType()->getAs<FunctionProtoType>();
+
+ llvm::SmallVector<QualType, 4> ArgTypes;
+ ArgTypes.push_back(Context.VoidPtrTy);
+ for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I)
+ ArgTypes.push_back(Proto->getArgType(I));
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = Proto->isVariadic();
+
+ ExpectedFunctionType
+ = Context.getFunctionType(Context.VoidTy, ArgTypes.data(),
+ ArgTypes.size(), EPI);
+ }
+
+ for (LookupResult::iterator D = FoundDelete.begin(),
+ DEnd = FoundDelete.end();
+ D != DEnd; ++D) {
+ FunctionDecl *Fn = 0;
+ if (FunctionTemplateDecl *FnTmpl
+ = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
+ // Perform template argument deduction to try to match the
+ // expected function type.
+ TemplateDeductionInfo Info(Context, StartLoc);
+ if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info))
+ continue;
+ } else
+ Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
+
+ if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
+ Matches.push_back(std::make_pair(D.getPair(), Fn));
+ }
+ } else {
+ // C++ [expr.new]p20:
+ // [...] Any non-placement deallocation function matches a
+ // non-placement allocation function. [...]
+ for (LookupResult::iterator D = FoundDelete.begin(),
+ DEnd = FoundDelete.end();
+ D != DEnd; ++D) {
+ if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
+ if (isNonPlacementDeallocationFunction(Fn))
+ Matches.push_back(std::make_pair(D.getPair(), Fn));
+ }
+ }
+
+ // C++ [expr.new]p20:
+ // [...] If the lookup finds a single matching deallocation
+ // function, that function will be called; otherwise, no
+ // deallocation function will be called.
+ if (Matches.size() == 1) {
+ OperatorDelete = Matches[0].second;
+
+ // C++0x [expr.new]p20:
+ // If the lookup finds the two-parameter form of a usual
+ // deallocation function (3.7.4.2) and that function, considered
+ // as a placement deallocation function, would have been
+ // selected as a match for the allocation function, the program
+ // is ill-formed.
+ if (NumPlaceArgs && getLangOptions().CPlusPlus0x &&
+ isNonPlacementDeallocationFunction(OperatorDelete)) {
+ Diag(StartLoc, diag::err_placement_new_non_placement_delete)
+ << SourceRange(PlaceArgs[0]->getLocStart(),
+ PlaceArgs[NumPlaceArgs - 1]->getLocEnd());
+ Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
+ << DeleteName;
+ } else {
+ CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
+ Matches[0].first);
+ }
+ }
+
+ return false;
+}
+
+/// FindAllocationOverload - Find an fitting overload for the allocation
+/// function in the specified scope.
+bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, Expr** Args,
+ unsigned NumArgs, DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator) {
+ LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, Ctx);
+ if (R.empty()) {
+ if (AllowMissing)
+ return false;
+ return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+ << Name << Range;
+ }
+
+ if (R.isAmbiguous())
+ return true;
+
+ R.suppressDiagnostics();
+
+ OverloadCandidateSet Candidates(StartLoc);
+ for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
+ Alloc != AllocEnd; ++Alloc) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ NamedDecl *D = (*Alloc)->getUnderlyingDecl();
+
+ if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+ AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
+ /*ExplicitTemplateArgs=*/0, Args, NumArgs,
+ Candidates,
+ /*SuppressUserConversions=*/false);
+ continue;
+ }
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (Candidates.BestViableFunction(*this, StartLoc, Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ // The first argument is size_t, and the first parameter must be size_t,
+ // too. This is checked on declaration and can be assumed. (It can't be
+ // asserted on, though, since invalid decls are left in there.)
+ // Watch out for variadic allocator function.
+ unsigned NumArgsInFnDecl = FnDecl->getNumParams();
+ for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
+ ExprResult Result
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ FnDecl->getParamDecl(i)),
+ SourceLocation(),
+ Owned(Args[i]));
+ if (Result.isInvalid())
+ return true;
+
+ Args[i] = Result.takeAs<Expr>();
+ }
+ Operator = FnDecl;
+ CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl);
+ return false;
+ }
+
+ case OR_No_Viable_Function:
+ Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+ << Name << Range;
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ return true;
+
+ case OR_Ambiguous:
+ Diag(StartLoc, diag::err_ovl_ambiguous_call)
+ << Name << Range;
+ Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
+ return true;
+
+ case OR_Deleted:
+ Diag(StartLoc, diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted()
+ << Name << Range;
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ return true;
+ }
+ assert(false && "Unreachable, bad result from BestViableFunction");
+ return true;
+}
+
+
+/// DeclareGlobalNewDelete - Declare the global forms of operator new and
+/// delete. These are:
+/// @code
+/// void* operator new(std::size_t) throw(std::bad_alloc);
+/// void* operator new[](std::size_t) throw(std::bad_alloc);
+/// void operator delete(void *) throw();
+/// void operator delete[](void *) throw();
+/// @endcode
+/// Note that the placement and nothrow forms of new are *not* implicitly
+/// declared. Their use requires including \<new\>.
+void Sema::DeclareGlobalNewDelete() {
+ if (GlobalNewDeleteDeclared)
+ return;
+
+ // C++ [basic.std.dynamic]p2:
+ // [...] The following allocation and deallocation functions (18.4) are
+ // implicitly declared in global scope in each translation unit of a
+ // program
+ //
+ // void* operator new(std::size_t) throw(std::bad_alloc);
+ // void* operator new[](std::size_t) throw(std::bad_alloc);
+ // void operator delete(void*) throw();
+ // void operator delete[](void*) throw();
+ //
+ // These implicit declarations introduce only the function names operator
+ // new, operator new[], operator delete, operator delete[].
+ //
+ // Here, we need to refer to std::bad_alloc, so we will implicitly declare
+ // "std" or "bad_alloc" as necessary to form the exception specification.
+ // However, we do not make these implicit declarations visible to name
+ // lookup.
+ if (!StdBadAlloc) {
+ // The "std::bad_alloc" class has not yet been declared, so build it
+ // implicitly.
+ StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
+ getOrCreateStdNamespace(),
+ SourceLocation(),
+ &PP.getIdentifierTable().get("bad_alloc"),
+ SourceLocation(), 0);
+ getStdBadAlloc()->setImplicit(true);
+ }
+
+ GlobalNewDeleteDeclared = true;
+
+ QualType VoidPtr = Context.getPointerType(Context.VoidTy);
+ QualType SizeT = Context.getSizeType();
+ bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew;
+
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_New),
+ VoidPtr, SizeT, AssumeSaneOperatorNew);
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
+ VoidPtr, SizeT, AssumeSaneOperatorNew);
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_Delete),
+ Context.VoidTy, VoidPtr);
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
+ Context.VoidTy, VoidPtr);
+}
+
+/// DeclareGlobalAllocationFunction - Declares a single implicit global
+/// allocation function if it doesn't already exist.
+void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
+ QualType Return, QualType Argument,
+ bool AddMallocAttr) {
+ DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
+
+ // Check if this function is already declared.
+ {
+ DeclContext::lookup_iterator Alloc, AllocEnd;
+ for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
+ Alloc != AllocEnd; ++Alloc) {
+ // Only look at non-template functions, as it is the predefined,
+ // non-templated allocation function we are trying to declare here.
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+ QualType InitialParamType =
+ Context.getCanonicalType(
+ Func->getParamDecl(0)->getType().getUnqualifiedType());
+ // FIXME: Do we need to check for default arguments here?
+ if (Func->getNumParams() == 1 && InitialParamType == Argument) {
+ if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
+ Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+ return;
+ }
+ }
+ }
+ }
+
+ QualType BadAllocType;
+ bool HasBadAllocExceptionSpec
+ = (Name.getCXXOverloadedOperator() == OO_New ||
+ Name.getCXXOverloadedOperator() == OO_Array_New);
+ if (HasBadAllocExceptionSpec) {
+ assert(StdBadAlloc && "Must have std::bad_alloc declared");
+ BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
+ }
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.HasExceptionSpec = true;
+ if (HasBadAllocExceptionSpec) {
+ EPI.NumExceptions = 1;
+ EPI.Exceptions = &BadAllocType;
+ }
+
+ QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);
+ FunctionDecl *Alloc =
+ FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
+ FnType, /*TInfo=*/0, SC_None,
+ SC_None, false, true);
+ Alloc->setImplicit();
+
+ if (AddMallocAttr)
+ Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
+
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
+ 0, Argument, /*TInfo=*/0,
+ SC_None,
+ SC_None, 0);
+ Alloc->setParams(&Param, 1);
+
+ // FIXME: Also add this declaration to the IdentifierResolver, but
+ // make sure it is at the end of the chain to coincide with the
+ // global scope.
+ Context.getTranslationUnitDecl()->addDecl(Alloc);
+}
+
+bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name,
+ FunctionDecl* &Operator) {
+ LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
+ // Try to find operator delete/operator delete[] in class scope.
+ LookupQualifiedName(Found, RD);
+
+ if (Found.isAmbiguous())
+ return true;
+
+ Found.suppressDiagnostics();
+
+ llvm::SmallVector<DeclAccessPair,4> Matches;
+ for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+ F != FEnd; ++F) {
+ NamedDecl *ND = (*F)->getUnderlyingDecl();
+
+ // Ignore template operator delete members from the check for a usual
+ // deallocation function.
+ if (isa<FunctionTemplateDecl>(ND))
+ continue;
+
+ if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction())
+ Matches.push_back(F.getPair());
+ }
+
+ // There's exactly one suitable operator; pick it.
+ if (Matches.size() == 1) {
+ Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
+ CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
+ Matches[0]);
+ return false;
+
+ // We found multiple suitable operators; complain about the ambiguity.
+ } else if (!Matches.empty()) {
+ Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
+ << Name << RD;
+
+ for (llvm::SmallVectorImpl<DeclAccessPair>::iterator
+ F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
+ Diag((*F)->getUnderlyingDecl()->getLocation(),
+ diag::note_member_declared_here) << Name;
+ return true;
+ }
+
+ // We did find operator delete/operator delete[] declarations, but
+ // none of them were suitable.
+ if (!Found.empty()) {
+ Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+ << Name << RD;
+
+ for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+ F != FEnd; ++F)
+ Diag((*F)->getUnderlyingDecl()->getLocation(),
+ diag::note_member_declared_here) << Name;
+
+ return true;
+ }
+
+ // Look for a global declaration.
+ DeclareGlobalNewDelete();
+ DeclContext *TUDecl = Context.getTranslationUnitDecl();
+
+ CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
+ Expr* DeallocArgs[1];
+ DeallocArgs[0] = &Null;
+ if (FindAllocationOverload(StartLoc, SourceRange(), Name,
+ DeallocArgs, 1, TUDecl, /*AllowMissing=*/false,
+ Operator))
+ return true;
+
+ assert(Operator && "Did not find a deallocation function!");
+ return false;
+}
+
+/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
+/// @code ::delete ptr; @endcode
+/// or
+/// @code delete [] ptr; @endcode
+ExprResult
+Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+ bool ArrayForm, Expr *Ex) {
+ // C++ [expr.delete]p1:
+ // The operand shall have a pointer type, or a class type having a single
+ // conversion function to a pointer type. The result has type void.
+ //
+ // DR599 amends "pointer type" to "pointer to object type" in both cases.
+
+ FunctionDecl *OperatorDelete = 0;
+ bool ArrayFormAsWritten = ArrayForm;
+ bool UsualArrayDeleteWantsSize = false;
+
+ if (!Ex->isTypeDependent()) {
+ QualType Type = Ex->getType();
+
+ if (const RecordType *Record = Type->getAs<RecordType>()) {
+ if (RequireCompleteType(StartLoc, Type,
+ PDiag(diag::err_delete_incomplete_class_type)))
+ return ExprError();
+
+ llvm::SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
+
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = I.getDecl();
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ // Skip over templated conversion functions; they aren't considered.
+ if (isa<FunctionTemplateDecl>(D))
+ continue;
+
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+
+ QualType ConvType = Conv->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
+ ObjectPtrConversions.push_back(Conv);
+ }
+ if (ObjectPtrConversions.size() == 1) {
+ // We have a single conversion to a pointer-to-object type. Perform
+ // that conversion.
+ // TODO: don't redo the conversion calculation.
+ if (!PerformImplicitConversion(Ex,
+ ObjectPtrConversions.front()->getConversionType(),
+ AA_Converting)) {
+ Type = Ex->getType();
+ }
+ }
+ else if (ObjectPtrConversions.size() > 1) {
+ Diag(StartLoc, diag::err_ambiguous_delete_operand)
+ << Type << Ex->getSourceRange();
+ for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)
+ NoteOverloadCandidate(ObjectPtrConversions[i]);
+ return ExprError();
+ }
+ }
+
+ if (!Type->isPointerType())
+ return ExprError(Diag(StartLoc, diag::err_delete_operand)
+ << Type << Ex->getSourceRange());
+
+ QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
+ if (Pointee->isVoidType() && !isSFINAEContext()) {
+ // The C++ standard bans deleting a pointer to a non-object type, which
+ // effectively bans deletion of "void*". However, most compilers support
+ // this, so we treat it as a warning unless we're in a SFINAE context.
+ Diag(StartLoc, diag::ext_delete_void_ptr_operand)
+ << Type << Ex->getSourceRange();
+ } else if (Pointee->isFunctionType() || Pointee->isVoidType())
+ return ExprError(Diag(StartLoc, diag::err_delete_operand)
+ << Type << Ex->getSourceRange());
+ else if (!Pointee->isDependentType() &&
+ RequireCompleteType(StartLoc, Pointee,
+ PDiag(diag::warn_delete_incomplete)
+ << Ex->getSourceRange()))
+ return ExprError();
+
+ // C++ [expr.delete]p2:
+ // [Note: a pointer to a const type can be the operand of a
+ // delete-expression; it is not necessary to cast away the constness
+ // (5.2.11) of the pointer expression before it is used as the operand
+ // of the delete-expression. ]
+ ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy),
+ CK_NoOp);
+
+ if (Pointee->isArrayType() && !ArrayForm) {
+ Diag(StartLoc, diag::warn_delete_array_type)
+ << Type << Ex->getSourceRange()
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+ ArrayForm = true;
+ }
+
+ DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+ ArrayForm ? OO_Array_Delete : OO_Delete);
+
+ QualType PointeeElem = Context.getBaseElementType(Pointee);
+ if (const RecordType *RT = PointeeElem->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ if (!UseGlobal &&
+ FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete))
+ return ExprError();
+
+ // If we're allocating an array of records, check whether the
+ // usual operator delete[] has a size_t parameter.
+ if (ArrayForm) {
+ // If the user specifically asked to use the global allocator,
+ // we'll need to do the lookup into the class.
+ if (UseGlobal)
+ UsualArrayDeleteWantsSize =
+ doesUsualArrayDeleteWantSize(*this, StartLoc, PointeeElem);
+
+ // Otherwise, the usual operator delete[] should be the
+ // function we just found.
+ else if (isa<CXXMethodDecl>(OperatorDelete))
+ UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
+ }
+
+ if (!RD->hasTrivialDestructor())
+ if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
+ MarkDeclarationReferenced(StartLoc,
+ const_cast<CXXDestructorDecl*>(Dtor));
+ DiagnoseUseOfDecl(Dtor, StartLoc);
+ }
+ }
+
+ if (!OperatorDelete) {
+ // Look for a global declaration.
+ DeclareGlobalNewDelete();
+ DeclContext *TUDecl = Context.getTranslationUnitDecl();
+ if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
+ &Ex, 1, TUDecl, /*AllowMissing=*/false,
+ OperatorDelete))
+ return ExprError();
+ }
+
+ MarkDeclarationReferenced(StartLoc, OperatorDelete);
+
+ // Check access and ambiguity of operator delete and destructor.
+ if (const RecordType *RT = PointeeElem->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
+ CheckDestructorAccess(Ex->getExprLoc(), Dtor,
+ PDiag(diag::err_access_dtor) << PointeeElem);
+ }
+ }
+
+ }
+
+ return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
+ ArrayFormAsWritten,
+ UsualArrayDeleteWantsSize,
+ OperatorDelete, Ex, StartLoc));
+}
+
+/// \brief Check the use of the given variable as a C++ condition in an if,
+/// while, do-while, or switch statement.
+ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
+ SourceLocation StmtLoc,
+ bool ConvertToBoolean) {
+ QualType T = ConditionVar->getType();
+
+ // C++ [stmt.select]p2:
+ // The declarator shall not specify a function or an array.
+ if (T->isFunctionType())
+ return ExprError(Diag(ConditionVar->getLocation(),
+ diag::err_invalid_use_of_function_type)
+ << ConditionVar->getSourceRange());
+ else if (T->isArrayType())
+ return ExprError(Diag(ConditionVar->getLocation(),
+ diag::err_invalid_use_of_array_type)
+ << ConditionVar->getSourceRange());
+
+ Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
+ ConditionVar->getLocation(),
+ ConditionVar->getType().getNonReferenceType(),
+ VK_LValue);
+ if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
+ return ExprError();
+
+ return Owned(Condition);
+}
+
+/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
+bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) {
+ // C++ 6.4p4:
+ // The value of a condition that is an initialized declaration in a statement
+ // other than a switch statement is the value of the declared variable
+ // implicitly converted to type bool. If that conversion is ill-formed, the
+ // program is ill-formed.
+ // The value of a condition that is an expression is the value of the
+ // expression, implicitly converted to bool.
+ //
+ return PerformContextuallyConvertToBool(CondExpr);
+}
+
+/// Helper function to determine whether this is the (deprecated) C++
+/// conversion from a string literal to a pointer to non-const char or
+/// non-const wchar_t (for narrow and wide string literals,
+/// respectively).
+bool
+Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
+ // Look inside the implicit cast, if it exists.
+ if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(From))
+ From = Cast->getSubExpr();
+
+ // A string literal (2.13.4) that is not a wide string literal can
+ // be converted to an rvalue of type "pointer to char"; a wide
+ // string literal can be converted to an rvalue of type "pointer
+ // to wchar_t" (C++ 4.2p2).
+ if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens()))
+ if (const PointerType *ToPtrType = ToType->getAs<PointerType>())
+ if (const BuiltinType *ToPointeeType
+ = ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
+ // This conversion is considered only when there is an
+ // explicit appropriate pointer target type (C++ 4.2p2).
+ if (!ToPtrType->getPointeeType().hasQualifiers() &&
+ ((StrLit->isWide() && ToPointeeType->isWideCharType()) ||
+ (!StrLit->isWide() &&
+ (ToPointeeType->getKind() == BuiltinType::Char_U ||
+ ToPointeeType->getKind() == BuiltinType::Char_S))))
+ return true;
+ }
+
+ return false;
+}
+
+static ExprResult BuildCXXCastArgument(Sema &S,
+ SourceLocation CastLoc,
+ QualType Ty,
+ CastKind Kind,
+ CXXMethodDecl *Method,
+ NamedDecl *FoundDecl,
+ Expr *From) {
+ switch (Kind) {
+ default: assert(0 && "Unhandled cast kind!");
+ case CK_ConstructorConversion: {
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+
+ if (S.CompleteConstructorCall(cast<CXXConstructorDecl>(Method),
+ MultiExprArg(&From, 1),
+ CastLoc, ConstructorArgs))
+ return ExprError();
+
+ ExprResult Result =
+ S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false, CXXConstructExpr::CK_Complete,
+ SourceRange());
+ if (Result.isInvalid())
+ return ExprError();
+
+ return S.MaybeBindToTemporary(Result.takeAs<Expr>());
+ }
+
+ case CK_UserDefinedConversion: {
+ assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
+
+ // Create an implicit call expr that calls it.
+ ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return S.MaybeBindToTemporary(Result.get());
+ }
+ }
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType using the pre-computed implicit
+/// conversion sequence ICS. Returns true if there was an error, false
+/// otherwise. The expression From is replaced with the converted
+/// expression. Action is the kind of conversion we're performing,
+/// used in the error message.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ const ImplicitConversionSequence &ICS,
+ AssignmentAction Action, bool CStyle) {
+ switch (ICS.getKind()) {
+ case ImplicitConversionSequence::StandardConversion:
+ if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
+ CStyle))
+ return true;
+ break;
+
+ case ImplicitConversionSequence::UserDefinedConversion: {
+
+ FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
+ CastKind CastKind;
+ QualType BeforeToType;
+ if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
+ CastKind = CK_UserDefinedConversion;
+
+ // If the user-defined conversion is specified by a conversion function,
+ // the initial standard conversion sequence converts the source type to
+ // the implicit object parameter of the conversion function.
+ BeforeToType = Context.getTagDeclType(Conv->getParent());
+ } else {
+ const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD);
+ CastKind = CK_ConstructorConversion;
+ // Do no conversion if dealing with ... for the first conversion.
+ if (!ICS.UserDefined.EllipsisConversion) {
+ // If the user-defined conversion is specified by a constructor, the
+ // initial standard conversion sequence converts the source type to the
+ // type required by the argument of the constructor
+ BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType();
+ }
+ }
+ // Watch out for elipsis conversion.
+ if (!ICS.UserDefined.EllipsisConversion) {
+ if (PerformImplicitConversion(From, BeforeToType,
+ ICS.UserDefined.Before, AA_Converting,
+ CStyle))
+ return true;
+ }
+
+ ExprResult CastArg
+ = BuildCXXCastArgument(*this,
+ From->getLocStart(),
+ ToType.getNonReferenceType(),
+ CastKind, cast<CXXMethodDecl>(FD),
+ ICS.UserDefined.FoundConversionFunction,
+ From);
+
+ if (CastArg.isInvalid())
+ return true;
+
+ From = CastArg.takeAs<Expr>();
+
+ return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
+ AA_Converting, CStyle);
+ }
+
+ case ImplicitConversionSequence::AmbiguousConversion:
+ ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
+ PDiag(diag::err_typecheck_ambiguous_condition)
+ << From->getSourceRange());
+ return true;
+
+ case ImplicitConversionSequence::EllipsisConversion:
+ assert(false && "Cannot perform an ellipsis conversion");
+ return false;
+
+ case ImplicitConversionSequence::BadConversion:
+ return true;
+ }
+
+ // Everything went well.
+ return false;
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType by following the standard
+/// conversion sequence SCS. Returns true if there was an error, false
+/// otherwise. The expression From is replaced with the converted
+/// expression. Flavor is the context in which we're performing this
+/// conversion, for use in error messages.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ const StandardConversionSequence& SCS,
+ AssignmentAction Action, bool CStyle) {
+ // Overall FIXME: we are recomputing too many types here and doing far too
+ // much extra work. What this means is that we need to keep track of more
+ // information that is computed when we try the implicit conversion initially,
+ // so that we don't need to recompute anything here.
+ QualType FromType = From->getType();
+
+ if (SCS.CopyConstructor) {
+ // FIXME: When can ToType be a reference type?
+ assert(!ToType->isReferenceType());
+ if (SCS.Second == ICK_Derived_To_Base) {
+ ASTOwningVector<Expr*> ConstructorArgs(*this);
+ if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
+ MultiExprArg(*this, &From, 1),
+ /*FIXME:ConstructLoc*/SourceLocation(),
+ ConstructorArgs))
+ return true;
+ ExprResult FromResult =
+ BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+ ToType, SCS.CopyConstructor,
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
+ if (FromResult.isInvalid())
+ return true;
+ From = FromResult.takeAs<Expr>();
+ return false;
+ }
+ ExprResult FromResult =
+ BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
+ ToType, SCS.CopyConstructor,
+ MultiExprArg(*this, &From, 1),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
+
+ if (FromResult.isInvalid())
+ return true;
+
+ From = FromResult.takeAs<Expr>();
+ return false;
+ }
+
+ // Resolve overloaded function references.
+ if (Context.hasSameType(FromType, Context.OverloadTy)) {
+ DeclAccessPair Found;
+ FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
+ true, Found);
+ if (!Fn)
+ return true;
+
+ if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
+ return true;
+
+ From = FixOverloadedFunctionReference(From, Found, Fn);
+ FromType = From->getType();
+ }
+
+ // Perform the first implicit conversion.
+ switch (SCS.First) {
+ case ICK_Identity:
+ // Nothing to do.
+ break;
+
+ case ICK_Lvalue_To_Rvalue:
+ // Should this get its own ICK?
+ if (From->getObjectKind() == OK_ObjCProperty) {
+ ConvertPropertyForRValue(From);
+ if (!From->isGLValue()) break;
+ }
+
+ // Check for trivial buffer overflows.
+ if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(From))
+ CheckArrayAccess(AE);
+
+ FromType = FromType.getUnqualifiedType();
+ From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue,
+ From, 0, VK_RValue);
+ break;
+
+ case ICK_Array_To_Pointer:
+ FromType = Context.getArrayDecayedType(FromType);
+ ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay);
+ break;
+
+ case ICK_Function_To_Pointer:
+ FromType = Context.getPointerType(FromType);
+ ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay);
+ break;
+
+ default:
+ assert(false && "Improper first standard conversion");
+ break;
+ }
+
+ // Perform the second implicit conversion
+ switch (SCS.Second) {
+ case ICK_Identity:
+ // If both sides are functions (or pointers/references to them), there could
+ // be incompatible exception declarations.
+ if (CheckExceptionSpecCompatibility(From, ToType))
+ return true;
+ // Nothing else to do.
+ break;
+
+ case ICK_NoReturn_Adjustment:
+ // If both sides are functions (or pointers/references to them), there could
+ // be incompatible exception declarations.
+ if (CheckExceptionSpecCompatibility(From, ToType))
+ return true;
+
+ ImpCastExprToType(From, ToType, CK_NoOp);
+ break;
+
+ case ICK_Integral_Promotion:
+ case ICK_Integral_Conversion:
+ ImpCastExprToType(From, ToType, CK_IntegralCast);
+ break;
+
+ case ICK_Floating_Promotion:
+ case ICK_Floating_Conversion:
+ ImpCastExprToType(From, ToType, CK_FloatingCast);
+ break;
+
+ case ICK_Complex_Promotion:
+ case ICK_Complex_Conversion: {
+ QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType();
+ QualType ToEl = ToType->getAs<ComplexType>()->getElementType();
+ CastKind CK;
+ if (FromEl->isRealFloatingType()) {
+ if (ToEl->isRealFloatingType())
+ CK = CK_FloatingComplexCast;
+ else
+ CK = CK_FloatingComplexToIntegralComplex;
+ } else if (ToEl->isRealFloatingType()) {
+ CK = CK_IntegralComplexToFloatingComplex;
+ } else {
+ CK = CK_IntegralComplexCast;
+ }
+ ImpCastExprToType(From, ToType, CK);
+ break;
+ }
+
+ case ICK_Floating_Integral:
+ if (ToType->isRealFloatingType())
+ ImpCastExprToType(From, ToType, CK_IntegralToFloating);
+ else
+ ImpCastExprToType(From, ToType, CK_FloatingToIntegral);
+ break;
+
+ case ICK_Compatible_Conversion:
+ ImpCastExprToType(From, ToType, CK_NoOp);
+ break;
+
+ case ICK_Pointer_Conversion: {
+ if (SCS.IncompatibleObjC && Action != AA_Casting) {
+ // Diagnose incompatible Objective-C conversions
+ Diag(From->getSourceRange().getBegin(),
+ diag::ext_typecheck_convert_incompatible_pointer)
+ << From->getType() << ToType << Action
+ << From->getSourceRange();
+ }
+
+ CastKind Kind = CK_Invalid;
+ CXXCastPath BasePath;
+ if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
+ return true;
+ ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
+ break;
+ }
+
+ case ICK_Pointer_Member: {
+ CastKind Kind = CK_Invalid;
+ CXXCastPath BasePath;
+ if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle))
+ return true;
+ if (CheckExceptionSpecCompatibility(From, ToType))
+ return true;
+ ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
+ break;
+ }
+ case ICK_Boolean_Conversion: {
+ CastKind Kind = CK_Invalid;
+ switch (FromType->getScalarTypeKind()) {
+ case Type::STK_Pointer: Kind = CK_PointerToBoolean; break;
+ case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break;
+ case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?");
+ case Type::STK_Integral: Kind = CK_IntegralToBoolean; break;
+ case Type::STK_Floating: Kind = CK_FloatingToBoolean; break;
+ case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break;
+ case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break;
+ }
+
+ ImpCastExprToType(From, Context.BoolTy, Kind);
+ break;
+ }
+
+ case ICK_Derived_To_Base: {
+ CXXCastPath BasePath;
+ if (CheckDerivedToBaseConversion(From->getType(),
+ ToType.getNonReferenceType(),
+ From->getLocStart(),
+ From->getSourceRange(),
+ &BasePath,
+ CStyle))
+ return true;
+
+ ImpCastExprToType(From, ToType.getNonReferenceType(),
+ CK_DerivedToBase, CastCategory(From),
+ &BasePath);
+ break;
+ }
+
+ case ICK_Vector_Conversion:
+ ImpCastExprToType(From, ToType, CK_BitCast);
+ break;
+
+ case ICK_Vector_Splat:
+ ImpCastExprToType(From, ToType, CK_VectorSplat);
+ break;
+
+ case ICK_Complex_Real:
+ // Case 1. x -> _Complex y
+ if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) {
+ QualType ElType = ToComplex->getElementType();
+ bool isFloatingComplex = ElType->isRealFloatingType();
+
+ // x -> y
+ if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
+ // do nothing
+ } else if (From->getType()->isRealFloatingType()) {
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral);
+ } else {
+ assert(From->getType()->isIntegerType());
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast);
+ }
+ // y -> _Complex y
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingRealToComplex
+ : CK_IntegralRealToComplex);
+
+ // Case 2. _Complex x -> y
+ } else {
+ const ComplexType *FromComplex = From->getType()->getAs<ComplexType>();
+ assert(FromComplex);
+
+ QualType ElType = FromComplex->getElementType();
+ bool isFloatingComplex = ElType->isRealFloatingType();
+
+ // _Complex x -> x
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_FloatingComplexToReal
+ : CK_IntegralComplexToReal);
+
+ // x -> y
+ if (Context.hasSameUnqualifiedType(ElType, ToType)) {
+ // do nothing
+ } else if (ToType->isRealFloatingType()) {
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating);
+ } else {
+ assert(ToType->isIntegerType());
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast);
+ }
+ }
+ break;
+
+ case ICK_Block_Pointer_Conversion: {
+ ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, VK_RValue);
+ break;
+ }
+
+ case ICK_Lvalue_To_Rvalue:
+ case ICK_Array_To_Pointer:
+ case ICK_Function_To_Pointer:
+ case ICK_Qualification:
+ case ICK_Num_Conversion_Kinds:
+ assert(false && "Improper second standard conversion");
+ break;
+ }
+
+ switch (SCS.Third) {
+ case ICK_Identity:
+ // Nothing to do.
+ break;
+
+ case ICK_Qualification: {
+ // The qualification keeps the category of the inner expression, unless the
+ // target type isn't a reference.
+ ExprValueKind VK = ToType->isReferenceType() ?
+ CastCategory(From) : VK_RValue;
+ ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
+ CK_NoOp, VK);
+
+ if (SCS.DeprecatedStringLiteralToCharPtr)
+ Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
+ << ToType.getNonReferenceType();
+
+ break;
+ }
+
+ default:
+ assert(false && "Improper third standard conversion");
+ break;
+ }
+
+ return false;
+}
+
+ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
+ SourceLocation KWLoc,
+ ParsedType Ty,
+ SourceLocation RParen) {
+ TypeSourceInfo *TSInfo;
+ QualType T = GetTypeFromParser(Ty, &TSInfo);
+
+ if (!TSInfo)
+ TSInfo = Context.getTrivialTypeSourceInfo(T);
+ return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen);
+}
+
+static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
+ SourceLocation KeyLoc) {
+ // FIXME: For many of these traits, we need a complete type before we can
+ // check these properties.
+ assert(!T->isDependentType() &&
+ "Cannot evaluate traits for dependent types.");
+ ASTContext &C = Self.Context;
+ switch(UTT) {
+ default: assert(false && "Unknown type trait or not implemented");
+ case UTT_IsPOD: return T->isPODType();
+ case UTT_IsLiteral: return T->isLiteralType();
+ case UTT_IsClass: // Fallthrough
+ case UTT_IsUnion:
+ if (const RecordType *Record = T->getAs<RecordType>()) {
+ bool Union = Record->getDecl()->isUnion();
+ return UTT == UTT_IsUnion ? Union : !Union;
+ }
+ return false;
+ case UTT_IsEnum: return T->isEnumeralType();
+ case UTT_IsPolymorphic:
+ if (const RecordType *Record = T->getAs<RecordType>()) {
+ // Type traits are only parsed in C++, so we've got CXXRecords.
+ return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic();
+ }
+ return false;
+ case UTT_IsAbstract:
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
+ return false;
+ case UTT_IsEmpty:
+ if (const RecordType *Record = T->getAs<RecordType>()) {
+ return !Record->getDecl()->isUnion()
+ && cast<CXXRecordDecl>(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 (T->isPODType())
+ return true;
+ if (const RecordType *RT =
+ C.getBaseElementType(T)->getAs<RecordType>())
+ return cast<CXXRecordDecl>(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 (T->isPODType() || T->isReferenceType())
+ return true;
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return cast<CXXRecordDecl>(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(T).isConstQualified())
+ return false;
+ if (T->isPODType())
+ return true;
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return cast<CXXRecordDecl>(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 (T->isPODType() || T->isReferenceType())
+ return true;
+ if (const RecordType *RT =
+ C.getBaseElementType(T)->getAs<RecordType>())
+ return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
+ return false;
+ // TODO: Propagate nothrowness for implicitly declared special members.
+ case UTT_HasNothrowAssign:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If type is const qualified or is a reference type then the
+ // trait is false. Otherwise if __has_trivial_assign (type)
+ // is true then the trait is true, else if type is a cv class
+ // or union type with copy assignment operators that are known
+ // not to throw an exception then the trait is true, else it is
+ // false.
+ if (C.getBaseElementType(T).isConstQualified())
+ return false;
+ if (T->isReferenceType())
+ return false;
+ if (T->isPODType())
+ return true;
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyAssignment())
+ return true;
+
+ bool FoundAssign = false;
+ bool AllNoThrow = true;
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+ LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc),
+ Sema::LookupOrdinaryName);
+ if (Self.LookupQualifiedName(Res, RD)) {
+ for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
+ Op != OpEnd; ++Op) {
+ CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+ if (Operator->isCopyAssignmentOperator()) {
+ FoundAssign = true;
+ const FunctionProtoType *CPT
+ = Operator->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+ }
+
+ return FoundAssign && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowCopy:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_copy (type) is true then the trait is true, else
+ // if type is a cv class or union type with copy constructors that are
+ // known not to throw an exception then the trait is true, else it is
+ // false.
+ if (T->isPODType() || T->isReferenceType())
+ return true;
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyConstructor())
+ return true;
+
+ bool FoundConstructor = false;
+ bool AllNoThrow = true;
+ unsigned FoundTQs;
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+ Con != ConEnd; ++Con) {
+ // A template constructor is never a copy constructor.
+ // FIXME: However, it may actually be selected at the actual overload
+ // resolution point.
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
+ FoundConstructor = true;
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ if (!CPT->hasEmptyExceptionSpec() || CPT->getNumArgs() > 1) {
+ 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 (T->isPODType())
+ return true;
+ if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialConstructor())
+ return true;
+
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD);
+ Con != ConEnd; ++Con) {
+ // FIXME: In C++0x, a constructor template can be a default constructor.
+ if (isa<FunctionTemplateDecl>(*Con))
+ continue;
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isDefaultConstructor()) {
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ return CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0;
+ }
+ }
+ }
+ 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 = T->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD))
+ return Destructor->isVirtual();
+ }
+ return false;
+ }
+}
+
+ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo,
+ SourceLocation RParen) {
+ QualType T = TSInfo->getType();
+
+ // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
+ // all traits except __is_class, __is_enum and __is_union require a the type
+ // to be complete, an array of unknown bound, or void.
+ if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion) {
+ QualType E = T;
+ if (T->isIncompleteArrayType())
+ E = Context.getAsArrayType(T)->getElementType();
+ if (!T->isVoidType() &&
+ RequireCompleteType(KWLoc, E,
+ diag::err_incomplete_type_used_in_type_trait_expr))
+ return ExprError();
+ }
+
+ bool Value = false;
+ if (!T->isDependentType())
+ Value = EvaluateUnaryTypeTrait(*this, UTT, T, KWLoc);
+
+ return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value,
+ RParen, Context.BoolTy));
+}
+
+ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ ParsedType RhsTy,
+ SourceLocation RParen) {
+ TypeSourceInfo *LhsTSInfo;
+ QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo);
+ if (!LhsTSInfo)
+ LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT);
+
+ TypeSourceInfo *RhsTSInfo;
+ QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo);
+ if (!RhsTSInfo)
+ RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT);
+
+ return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
+}
+
+static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
+ QualType LhsT, QualType RhsT,
+ SourceLocation KeyLoc) {
+ assert((!LhsT->isDependentType() || RhsT->isDependentType()) &&
+ "Cannot evaluate traits for dependent types.");
+
+ switch(BTT) {
+ case BTT_IsBaseOf: {
+ // C++0x [meta.rel]p2
+ // Base is a base class of Derived without regard to cv-qualifiers or
+ // Base and Derived are not unions and name the same class type without
+ // regard to cv-qualifiers.
+
+ const RecordType *lhsRecord = LhsT->getAs<RecordType>();
+ if (!lhsRecord) return false;
+
+ const RecordType *rhsRecord = RhsT->getAs<RecordType>();
+ if (!rhsRecord) return false;
+
+ assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
+ == (lhsRecord == rhsRecord));
+
+ if (lhsRecord == rhsRecord)
+ return !lhsRecord->getDecl()->isUnion();
+
+ // C++0x [meta.rel]p2:
+ // If Base and Derived are class types and are different types
+ // (ignoring possible cv-qualifiers) then Derived shall be a
+ // complete type.
+ if (Self.RequireCompleteType(KeyLoc, RhsT,
+ diag::err_incomplete_type_used_in_type_trait_expr))
+ return false;
+
+ return cast<CXXRecordDecl>(rhsRecord->getDecl())
+ ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
+ }
+
+ case BTT_TypeCompatible:
+ return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
+ RhsT.getUnqualifiedType());
+
+ case BTT_IsConvertibleTo: {
+ // C++0x [meta.rel]p4:
+ // Given the following function prototype:
+ //
+ // template <class T>
+ // typename add_rvalue_reference<T>::type create();
+ //
+ // the predicate condition for a template specialization
+ // is_convertible<From, To> shall be satisfied if and only if
+ // the return expression in the following code would be
+ // well-formed, including any implicit conversions to the return
+ // type of the function:
+ //
+ // To test() {
+ // return create<From>();
+ // }
+ //
+ // Access checking is performed as if in a context unrelated to To and
+ // From. Only the validity of the immediate context of the expression
+ // of the return-statement (including conversions to the return type)
+ // is considered.
+ //
+ // We model the initialization as a copy-initialization of a temporary
+ // of the appropriate type, which for this expression is identical to the
+ // return statement (since NRVO doesn't apply).
+ if (LhsT->isObjectType() || LhsT->isFunctionType())
+ LhsT = Self.Context.getRValueReferenceType(LhsT);
+
+ InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
+ OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
+ Expr::getValueKindForType(LhsT));
+ Expr *FromPtr = &From;
+ InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc,
+ SourceLocation()));
+
+ // Perform the initialization within a SFINAE trap at translation unit
+ // scope.
+ Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
+ Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
+ InitializationSequence Init(Self, To, Kind, &FromPtr, 1);
+ if (Init.getKind() == InitializationSequence::FailedSequence)
+ return false;
+
+ ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1));
+ return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
+ }
+ }
+ llvm_unreachable("Unknown type trait or not implemented");
+}
+
+ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *LhsTSInfo,
+ TypeSourceInfo *RhsTSInfo,
+ SourceLocation RParen) {
+ QualType LhsT = LhsTSInfo->getType();
+ QualType RhsT = RhsTSInfo->getType();
+
+ if (BTT == BTT_TypeCompatible) {
+ if (getLangOptions().CPlusPlus) {
+ Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
+ << SourceRange(KWLoc, RParen);
+ return ExprError();
+ }
+ }
+
+ bool Value = false;
+ if (!LhsT->isDependentType() && !RhsT->isDependentType())
+ Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc);
+
+ // Select trait result type.
+ QualType ResultType;
+ switch (BTT) {
+ case BTT_IsBaseOf: ResultType = Context.BoolTy; break;
+ case BTT_TypeCompatible: ResultType = Context.IntTy; break;
+ case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break;
+ }
+
+ return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo,
+ RhsTSInfo, Value, RParen,
+ ResultType));
+}
+
+QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
+ ExprValueKind &VK,
+ SourceLocation Loc,
+ bool isIndirect) {
+ const char *OpSpelling = isIndirect ? "->*" : ".*";
+ // C++ 5.5p2
+ // The binary operator .* [p3: ->*] binds its second operand, which shall
+ // be of type "pointer to member of T" (where T is a completely-defined
+ // class type) [...]
+ QualType RType = rex->getType();
+ const MemberPointerType *MemPtr = RType->getAs<MemberPointerType>();
+ if (!MemPtr) {
+ Diag(Loc, diag::err_bad_memptr_rhs)
+ << OpSpelling << RType << rex->getSourceRange();
+ return QualType();
+ }
+
+ QualType Class(MemPtr->getClass(), 0);
+
+ // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the
+ // member pointer points must be completely-defined. However, there is no
+ // reason for this semantic distinction, and the rule is not enforced by
+ // other compilers. Therefore, we do not check this property, as it is
+ // likely to be considered a defect.
+
+ // C++ 5.5p2
+ // [...] to its first operand, which shall be of class T or of a class of
+ // which T is an unambiguous and accessible base class. [p3: a pointer to
+ // such a class]
+ QualType LType = lex->getType();
+ if (isIndirect) {
+ if (const PointerType *Ptr = LType->getAs<PointerType>())
+ LType = Ptr->getPointeeType();
+ else {
+ Diag(Loc, diag::err_bad_memptr_lhs)
+ << OpSpelling << 1 << LType
+ << FixItHint::CreateReplacement(SourceRange(Loc), ".*");
+ return QualType();
+ }
+ }
+
+ if (!Context.hasSameUnqualifiedType(Class, LType)) {
+ // If we want to check the hierarchy, we need a complete type.
+ if (RequireCompleteType(Loc, LType, PDiag(diag::err_bad_memptr_lhs)
+ << OpSpelling << (int)isIndirect)) {
+ return QualType();
+ }
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ // FIXME: Would it be useful to print full ambiguity paths, or is that
+ // overkill?
+ if (!IsDerivedFrom(LType, Class, Paths) ||
+ Paths.isAmbiguous(Context.getCanonicalType(Class))) {
+ Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
+ << (int)isIndirect << lex->getType();
+ return QualType();
+ }
+ // Cast LHS to type of use.
+ QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
+ ExprValueKind VK =
+ isIndirect ? VK_RValue : CastCategory(lex);
+
+ CXXCastPath BasePath;
+ BuildBasePathArray(Paths, BasePath);
+ ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath);
+ }
+
+ if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) {
+ // Diagnose use of pointer-to-member type which when used as
+ // the functional cast in a pointer-to-member expression.
+ Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
+ return QualType();
+ }
+
+ // C++ 5.5p2
+ // The result is an object or a function of the type specified by the
+ // second operand.
+ // The cv qualifiers are the union of those in the pointer and the left side,
+ // in accordance with 5.5p5 and 5.2.5.
+ // FIXME: This returns a dereferenced member function pointer as a normal
+ // function type. However, the only operation valid on such functions is
+ // calling them. There's also a GCC extension to get a function pointer to the
+ // thing, which is another complication, because this type - unlike the type
+ // that is the result of this expression - takes the class as the first
+ // argument.
+ // We probably need a "MemberFunctionClosureType" or something like that.
+ QualType Result = MemPtr->getPointeeType();
+ Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
+
+ // C++0x [expr.mptr.oper]p6:
+ // In a .* expression whose object expression is an rvalue, the program is
+ // ill-formed if the second operand is a pointer to member function with
+ // ref-qualifier &. In a ->* expression or in a .* expression whose object
+ // expression is an lvalue, the program is ill-formed if the second operand
+ // is a pointer to member function with ref-qualifier &&.
+ if (const FunctionProtoType *Proto = Result->getAs<FunctionProtoType>()) {
+ switch (Proto->getRefQualifier()) {
+ case RQ_None:
+ // Do nothing
+ break;
+
+ case RQ_LValue:
+ if (!isIndirect && !lex->Classify(Context).isLValue())
+ Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+ << RType << 1 << lex->getSourceRange();
+ break;
+
+ case RQ_RValue:
+ if (isIndirect || !lex->Classify(Context).isRValue())
+ Diag(Loc, diag::err_pointer_to_member_oper_value_classify)
+ << RType << 0 << lex->getSourceRange();
+ break;
+ }
+ }
+
+ // C++ [expr.mptr.oper]p6:
+ // The result of a .* expression whose second operand is a pointer
+ // to a data member is of the same value category as its
+ // first operand. The result of a .* expression whose second
+ // operand is a pointer to a member function is a prvalue. The
+ // result of an ->* expression is an lvalue if its second operand
+ // is a pointer to data member and a prvalue otherwise.
+ if (Result->isFunctionType())
+ VK = VK_RValue;
+ else if (isIndirect)
+ VK = VK_LValue;
+ else
+ VK = lex->getValueKind();
+
+ return Result;
+}
+
+/// \brief Try to convert a type to another according to C++0x 5.16p3.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, the two operands are attempted to be
+/// converted to each other. This function does the conversion in one direction.
+/// It returns true if the program is ill-formed and has already been diagnosed
+/// as such.
+static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
+ SourceLocation QuestionLoc,
+ bool &HaveConversion,
+ QualType &ToType) {
+ HaveConversion = false;
+ ToType = To->getType();
+
+ InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(),
+ SourceLocation());
+ // C++0x 5.16p3
+ // The process for determining whether an operand expression E1 of type T1
+ // can be converted to match an operand expression E2 of type T2 is defined
+ // as follows:
+ // -- If E2 is an lvalue:
+ bool ToIsLvalue = To->isLValue();
+ if (ToIsLvalue) {
+ // E1 can be converted to match E2 if E1 can be implicitly converted to
+ // type "lvalue reference to T2", subject to the constraint that in the
+ // conversion the reference must bind directly to E1.
+ QualType T = Self.Context.getLValueReferenceType(ToType);
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
+
+ InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+ if (InitSeq.isDirectReferenceBinding()) {
+ ToType = T;
+ HaveConversion = true;
+ return false;
+ }
+
+ if (InitSeq.isAmbiguous())
+ return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+ }
+
+ // -- If E2 is an rvalue, or if the conversion above cannot be done:
+ // -- if E1 and E2 have class type, and the underlying class types are
+ // the same or one is a base class of the other:
+ QualType FTy = From->getType();
+ QualType TTy = To->getType();
+ const RecordType *FRec = FTy->getAs<RecordType>();
+ const RecordType *TRec = TTy->getAs<RecordType>();
+ bool FDerivedFromT = FRec && TRec && FRec != TRec &&
+ Self.IsDerivedFrom(FTy, TTy);
+ if (FRec && TRec &&
+ (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+ // E1 can be converted to match E2 if the class of T2 is the
+ // same type as, or a base class of, the class of T1, and
+ // [cv2 > cv1].
+ if (FRec == TRec || FDerivedFromT) {
+ if (TTy.isAtLeastAsQualifiedAs(FTy)) {
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
+ InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+ if (InitSeq.getKind() != InitializationSequence::FailedSequence) {
+ HaveConversion = true;
+ return false;
+ }
+
+ if (InitSeq.isAmbiguous())
+ return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+ }
+ }
+
+ return false;
+ }
+
+ // -- Otherwise: E1 can be converted to match E2 if E1 can be
+ // implicitly converted to the type that expression E2 would have
+ // if E2 were converted to an rvalue (or the type it has, if E2 is
+ // an rvalue).
+ //
+ // This actually refers very narrowly to the lvalue-to-rvalue conversion, not
+ // to the array-to-pointer or function-to-pointer conversions.
+ if (!TTy->getAs<TagType>())
+ TTy = TTy.getUnqualifiedType();
+
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
+ InitializationSequence InitSeq(Self, Entity, Kind, &From, 1);
+ HaveConversion = InitSeq.getKind() != InitializationSequence::FailedSequence;
+ ToType = TTy;
+ if (InitSeq.isAmbiguous())
+ return InitSeq.Diagnose(Self, Entity, Kind, &From, 1);
+
+ return false;
+}
+
+/// \brief Try to find a common type for two according to C++0x 5.16p5.
+///
+/// This is part of the parameter validation for the ? operator. If either
+/// value operand is a class type, overload resolution is used to find a
+/// conversion to a common type.
+static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
+ SourceLocation QuestionLoc) {
+ Expr *Args[2] = { LHS, RHS };
+ OverloadCandidateSet CandidateSet(QuestionLoc);
+ Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2,
+ CandidateSet);
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) {
+ case OR_Success:
+ // We found a match. Perform the conversions on the arguments and move on.
+ if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], Sema::AA_Converting) ||
+ Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], Sema::AA_Converting))
+ break;
+ return false;
+
+ case OR_No_Viable_Function:
+
+ // Emit a better diagnostic if one of the expressions is a null pointer
+ // constant and the other is a pointer type. In this case, the user most
+ // likely forgot to take the address of the other expression.
+ if (Self.DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ return true;
+
+ Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHS->getType() << RHS->getType()
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ return true;
+
+ case OR_Ambiguous:
+ Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl)
+ << LHS->getType() << RHS->getType()
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ // FIXME: Print the possible common types by printing the return types of
+ // the viable candidates.
+ break;
+
+ case OR_Deleted:
+ assert(false && "Conditional operator has only built-in overloads");
+ break;
+ }
+ return true;
+}
+
+/// \brief Perform an "extended" implicit conversion as returned by
+/// TryClassUnification.
+static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) {
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
+ InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(),
+ SourceLocation());
+ InitializationSequence InitSeq(Self, Entity, Kind, &E, 1);
+ ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1));
+ if (Result.isInvalid())
+ return true;
+
+ E = Result.takeAs<Expr>();
+ return false;
+}
+
+/// \brief Check the operands of ?: under C++ semantics.
+///
+/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
+/// extension. In this case, LHS == Cond. (But they're not aliases.)
+QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
+ ExprValueKind &VK, ExprObjectKind &OK,
+ SourceLocation QuestionLoc) {
+ // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
+ // interface pointers.
+
+ // C++0x 5.16p1
+ // The first expression is contextually converted to bool.
+ if (!Cond->isTypeDependent()) {
+ if (CheckCXXBooleanCondition(Cond))
+ return QualType();
+ }
+
+ // Assume r-value.
+ VK = VK_RValue;
+ OK = OK_Ordinary;
+
+ // Either of the arguments dependent?
+ if (LHS->isTypeDependent() || RHS->isTypeDependent())
+ return Context.DependentTy;
+
+ // C++0x 5.16p2
+ // If either the second or the third operand has type (cv) void, ...
+ QualType LTy = LHS->getType();
+ QualType RTy = RHS->getType();
+ bool LVoid = LTy->isVoidType();
+ bool RVoid = RTy->isVoidType();
+ if (LVoid || RVoid) {
+ // ... then the [l2r] conversions are performed on the second and third
+ // operands ...
+ DefaultFunctionArrayLvalueConversion(LHS);
+ DefaultFunctionArrayLvalueConversion(RHS);
+ LTy = LHS->getType();
+ RTy = RHS->getType();
+
+ // ... and one of the following shall hold:
+ // -- The second or the third operand (but not both) is a throw-
+ // expression; the result is of the type of the other and is an rvalue.
+ bool LThrow = isa<CXXThrowExpr>(LHS);
+ bool RThrow = isa<CXXThrowExpr>(RHS);
+ if (LThrow && !RThrow)
+ return RTy;
+ if (RThrow && !LThrow)
+ return LTy;
+
+ // -- Both the second and third operands have type void; the result is of
+ // type void and is an rvalue.
+ if (LVoid && RVoid)
+ return Context.VoidTy;
+
+ // Neither holds, error.
+ Diag(QuestionLoc, diag::err_conditional_void_nonvoid)
+ << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1)
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ return QualType();
+ }
+
+ // Neither is void.
+
+ // C++0x 5.16p3
+ // Otherwise, if the second and third operand have different types, and
+ // either has (cv) class type, and attempt is made to convert each of those
+ // operands to the other.
+ if (!Context.hasSameType(LTy, RTy) &&
+ (LTy->isRecordType() || RTy->isRecordType())) {
+ ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
+ // These return true if a single direction is already ambiguous.
+ QualType L2RType, R2LType;
+ bool HaveL2R, HaveR2L;
+ if (TryClassUnification(*this, LHS, RHS, QuestionLoc, HaveL2R, L2RType))
+ return QualType();
+ if (TryClassUnification(*this, RHS, LHS, QuestionLoc, HaveR2L, R2LType))
+ return QualType();
+
+ // If both can be converted, [...] the program is ill-formed.
+ if (HaveL2R && HaveR2L) {
+ Diag(QuestionLoc, diag::err_conditional_ambiguous)
+ << LTy << RTy << LHS->getSourceRange() << RHS->getSourceRange();
+ return QualType();
+ }
+
+ // If exactly one conversion is possible, that conversion is applied to
+ // the chosen operand and the converted operands are used in place of the
+ // original operands for the remainder of this section.
+ if (HaveL2R) {
+ if (ConvertForConditional(*this, LHS, L2RType))
+ return QualType();
+ LTy = LHS->getType();
+ } else if (HaveR2L) {
+ if (ConvertForConditional(*this, RHS, R2LType))
+ return QualType();
+ RTy = RHS->getType();
+ }
+ }
+
+ // C++0x 5.16p4
+ // If the second and third operands are glvalues of the same value
+ // category and have the same type, the result is of that type and
+ // value category and it is a bit-field if the second or the third
+ // operand is a bit-field, or if both are bit-fields.
+ // We only extend this to bitfields, not to the crazy other kinds of
+ // l-values.
+ bool Same = Context.hasSameType(LTy, RTy);
+ if (Same &&
+ LHS->isGLValue() &&
+ LHS->getValueKind() == RHS->getValueKind() &&
+ LHS->isOrdinaryOrBitFieldObject() &&
+ RHS->isOrdinaryOrBitFieldObject()) {
+ VK = LHS->getValueKind();
+ if (LHS->getObjectKind() == OK_BitField ||
+ RHS->getObjectKind() == OK_BitField)
+ OK = OK_BitField;
+ return LTy;
+ }
+
+ // C++0x 5.16p5
+ // Otherwise, the result is an rvalue. If the second and third operands
+ // do not have the same type, and either has (cv) class type, ...
+ if (!Same && (LTy->isRecordType() || RTy->isRecordType())) {
+ // ... overload resolution is used to determine the conversions (if any)
+ // to be applied to the operands. If the overload resolution fails, the
+ // program is ill-formed.
+ if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc))
+ return QualType();
+ }
+
+ // C++0x 5.16p6
+ // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
+ // conversions are performed on the second and third operands.
+ DefaultFunctionArrayLvalueConversion(LHS);
+ DefaultFunctionArrayLvalueConversion(RHS);
+ LTy = LHS->getType();
+ RTy = RHS->getType();
+
+ // After those conversions, one of the following shall hold:
+ // -- The second and third operands have the same type; the result
+ // is of that type. If the operands have class type, the result
+ // is a prvalue temporary of the result type, which is
+ // copy-initialized from either the second operand or the third
+ // operand depending on the value of the first operand.
+ if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
+ if (LTy->isRecordType()) {
+ // The operands have class type. Make a temporary copy.
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
+ ExprResult LHSCopy = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(LHS));
+ if (LHSCopy.isInvalid())
+ return QualType();
+
+ ExprResult RHSCopy = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(RHS));
+ if (RHSCopy.isInvalid())
+ return QualType();
+
+ LHS = LHSCopy.takeAs<Expr>();
+ RHS = RHSCopy.takeAs<Expr>();
+ }
+
+ return LTy;
+ }
+
+ // Extension: conditional operator involving vector types.
+ if (LTy->isVectorType() || RTy->isVectorType())
+ return CheckVectorOperands(QuestionLoc, LHS, RHS);
+
+ // -- The second and third operands have arithmetic or enumeration type;
+ // the usual arithmetic conversions are performed to bring them to a
+ // common type, and the result is of that type.
+ if (LTy->isArithmeticType() && RTy->isArithmeticType()) {
+ UsualArithmeticConversions(LHS, RHS);
+ return LHS->getType();
+ }
+
+ // -- The second and third operands have pointer type, or one has pointer
+ // type and the other is a null pointer constant; pointer conversions
+ // and qualification conversions are performed to bring them to their
+ // composite pointer type. The result is of the composite pointer type.
+ // -- The second and third operands have pointer to member type, or one has
+ // pointer to member type and the other is a null pointer constant;
+ // pointer to member conversions and qualification conversions are
+ // performed to bring them to a common type, whose cv-qualification
+ // shall match the cv-qualification of either the second or the third
+ // operand. The result is of the common type.
+ bool NonStandardCompositeType = false;
+ QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
+ if (!Composite.isNull()) {
+ if (NonStandardCompositeType)
+ Diag(QuestionLoc,
+ diag::ext_typecheck_cond_incompatible_operands_nonstandard)
+ << LTy << RTy << Composite
+ << LHS->getSourceRange() << RHS->getSourceRange();
+
+ return Composite;
+ }
+
+ // Similarly, attempt to find composite type of two objective-c pointers.
+ Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
+ if (!Composite.isNull())
+ return Composite;
+
+ // Check if we are using a null with a non-pointer type.
+ if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc))
+ return QualType();
+
+ Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
+ << LHS->getType() << RHS->getType()
+ << LHS->getSourceRange() << RHS->getSourceRange();
+ return QualType();
+}
+
+/// \brief Find a merged pointer type and convert the two expressions to it.
+///
+/// This finds the composite pointer type (or member pointer type) for @p E1
+/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this
+/// type and returns it.
+/// It does not emit diagnostics.
+///
+/// \param Loc The location of the operator requiring these two expressions to
+/// be converted to the composite pointer type.
+///
+/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find
+/// a non-standard (but still sane) composite type to which both expressions
+/// can be converted. When such a type is chosen, \c *NonStandardCompositeType
+/// will be set true.
+QualType Sema::FindCompositePointerType(SourceLocation Loc,
+ Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType) {
+ if (NonStandardCompositeType)
+ *NonStandardCompositeType = false;
+
+ assert(getLangOptions().CPlusPlus && "This function assumes C++");
+ QualType T1 = E1->getType(), T2 = E2->getType();
+
+ if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
+ !T2->isAnyPointerType() && !T2->isMemberPointerType())
+ return QualType();
+
+ // C++0x 5.9p2
+ // Pointer conversions and qualification conversions are performed on
+ // pointer operands to bring them to their composite pointer type. If
+ // one operand is a null pointer constant, the composite pointer type is
+ // the type of the other operand.
+ if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ if (T2->isMemberPointerType())
+ ImpCastExprToType(E1, T2, CK_NullToMemberPointer);
+ else
+ ImpCastExprToType(E1, T2, CK_NullToPointer);
+ return T2;
+ }
+ if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ if (T1->isMemberPointerType())
+ ImpCastExprToType(E2, T1, CK_NullToMemberPointer);
+ else
+ ImpCastExprToType(E2, T1, CK_NullToPointer);
+ return T1;
+ }
+
+ // Now both have to be pointers or member pointers.
+ if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
+ (!T2->isPointerType() && !T2->isMemberPointerType()))
+ return QualType();
+
+ // Otherwise, of one of the operands has type "pointer to cv1 void," then
+ // the other has type "pointer to cv2 T" and the composite pointer type is
+ // "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
+ // Otherwise, the composite pointer type is a pointer type similar to the
+ // type of one of the operands, with a cv-qualification signature that is
+ // the union of the cv-qualification signatures of the operand types.
+ // In practice, the first part here is redundant; it's subsumed by the second.
+ // What we do here is, we build the two possible composite types, and try the
+ // conversions in both directions. If only one works, or if the two composite
+ // types are the same, we have succeeded.
+ // FIXME: extended qualifiers?
+ typedef llvm::SmallVector<unsigned, 4> QualifierVector;
+ QualifierVector QualifierUnion;
+ typedef llvm::SmallVector<std::pair<const Type *, const Type *>, 4>
+ ContainingClassVector;
+ ContainingClassVector MemberOfClass;
+ QualType Composite1 = Context.getCanonicalType(T1),
+ Composite2 = Context.getCanonicalType(T2);
+ unsigned NeedConstBefore = 0;
+ do {
+ const PointerType *Ptr1, *Ptr2;
+ if ((Ptr1 = Composite1->getAs<PointerType>()) &&
+ (Ptr2 = Composite2->getAs<PointerType>())) {
+ Composite1 = Ptr1->getPointeeType();
+ Composite2 = Ptr2->getPointeeType();
+
+ // If we're allowed to create a non-standard composite type, keep track
+ // of where we need to fill in additional 'const' qualifiers.
+ if (NonStandardCompositeType &&
+ Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ NeedConstBefore = QualifierUnion.size();
+
+ QualifierUnion.push_back(
+ Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+ MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
+ continue;
+ }
+
+ const MemberPointerType *MemPtr1, *MemPtr2;
+ if ((MemPtr1 = Composite1->getAs<MemberPointerType>()) &&
+ (MemPtr2 = Composite2->getAs<MemberPointerType>())) {
+ Composite1 = MemPtr1->getPointeeType();
+ Composite2 = MemPtr2->getPointeeType();
+
+ // If we're allowed to create a non-standard composite type, keep track
+ // of where we need to fill in additional 'const' qualifiers.
+ if (NonStandardCompositeType &&
+ Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ NeedConstBefore = QualifierUnion.size();
+
+ QualifierUnion.push_back(
+ Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+ MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(),
+ MemPtr2->getClass()));
+ continue;
+ }
+
+ // FIXME: block pointer types?
+
+ // Cannot unwrap any more types.
+ break;
+ } while (true);
+
+ if (NeedConstBefore && NonStandardCompositeType) {
+ // Extension: Add 'const' to qualifiers that come before the first qualifier
+ // mismatch, so that our (non-standard!) composite type meets the
+ // requirements of C++ [conv.qual]p4 bullet 3.
+ for (unsigned I = 0; I != NeedConstBefore; ++I) {
+ if ((QualifierUnion[I] & Qualifiers::Const) == 0) {
+ QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const;
+ *NonStandardCompositeType = true;
+ }
+ }
+ }
+
+ // Rewrap the composites as pointers or member pointers with the union CVRs.
+ ContainingClassVector::reverse_iterator MOC
+ = MemberOfClass.rbegin();
+ for (QualifierVector::reverse_iterator
+ I = QualifierUnion.rbegin(),
+ E = QualifierUnion.rend();
+ I != E; (void)++I, ++MOC) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(*I);
+ if (MOC->first && MOC->second) {
+ // Rebuild member pointer type
+ Composite1 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite1, Quals),
+ MOC->first);
+ Composite2 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite2, Quals),
+ MOC->second);
+ } else {
+ // Rebuild pointer type
+ Composite1
+ = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+ Composite2
+ = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
+ }
+ }
+
+ // Try to convert to the first composite pointer type.
+ InitializedEntity Entity1
+ = InitializedEntity::InitializeTemporary(Composite1);
+ InitializationKind Kind
+ = InitializationKind::CreateCopy(Loc, SourceLocation());
+ InitializationSequence E1ToC1(*this, Entity1, Kind, &E1, 1);
+ InitializationSequence E2ToC1(*this, Entity1, Kind, &E2, 1);
+
+ if (E1ToC1 && E2ToC1) {
+ // Conversion to Composite1 is viable.
+ if (!Context.hasSameType(Composite1, Composite2)) {
+ // Composite2 is a different type from Composite1. Check whether
+ // Composite2 is also viable.
+ InitializedEntity Entity2
+ = InitializedEntity::InitializeTemporary(Composite2);
+ InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
+ InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
+ if (E1ToC2 && E2ToC2) {
+ // Both Composite1 and Composite2 are viable and are different;
+ // this is an ambiguity.
+ return QualType();
+ }
+ }
+
+ // Convert E1 to Composite1
+ ExprResult E1Result
+ = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1));
+ if (E1Result.isInvalid())
+ return QualType();
+ E1 = E1Result.takeAs<Expr>();
+
+ // Convert E2 to Composite1
+ ExprResult E2Result
+ = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1));
+ if (E2Result.isInvalid())
+ return QualType();
+ E2 = E2Result.takeAs<Expr>();
+
+ return Composite1;
+ }
+
+ // Check whether Composite2 is viable.
+ InitializedEntity Entity2
+ = InitializedEntity::InitializeTemporary(Composite2);
+ InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1);
+ InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1);
+ if (!E1ToC2 || !E2ToC2)
+ return QualType();
+
+ // Convert E1 to Composite2
+ ExprResult E1Result
+ = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1));
+ if (E1Result.isInvalid())
+ return QualType();
+ E1 = E1Result.takeAs<Expr>();
+
+ // Convert E2 to Composite2
+ ExprResult E2Result
+ = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1));
+ if (E2Result.isInvalid())
+ return QualType();
+ E2 = E2Result.takeAs<Expr>();
+
+ return Composite2;
+}
+
+ExprResult Sema::MaybeBindToTemporary(Expr *E) {
+ if (!E)
+ return ExprError();
+
+ if (!Context.getLangOptions().CPlusPlus)
+ return Owned(E);
+
+ assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");
+
+ const RecordType *RT = E->getType()->getAs<RecordType>();
+ if (!RT)
+ return Owned(E);
+
+ // If the result is a glvalue, we shouldn't bind it.
+ if (E->Classify(Context).isGLValue())
+ return Owned(E);
+
+ // That should be enough to guarantee that this type is complete.
+ // If it has a trivial destructor, we can avoid the extra copy.
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->isInvalidDecl() || RD->hasTrivialDestructor())
+ return Owned(E);
+
+ CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD));
+ ExprTemporaries.push_back(Temp);
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
+ MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+ CheckDestructorAccess(E->getExprLoc(), Destructor,
+ PDiag(diag::err_access_dtor_temp)
+ << E->getType());
+ }
+ // FIXME: Add the temporary to the temporaries vector.
+ return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
+}
+
+Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
+ assert(SubExpr && "sub expression can't be null!");
+
+ unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
+ assert(ExprTemporaries.size() >= FirstTemporary);
+ if (ExprTemporaries.size() == FirstTemporary)
+ return SubExpr;
+
+ Expr *E = ExprWithCleanups::Create(Context, SubExpr,
+ &ExprTemporaries[FirstTemporary],
+ ExprTemporaries.size() - FirstTemporary);
+ ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
+ ExprTemporaries.end());
+
+ return E;
+}
+
+ExprResult
+Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
+}
+
+Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
+ assert(SubStmt && "sub statement can't be null!");
+
+ unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
+ assert(ExprTemporaries.size() >= FirstTemporary);
+ if (ExprTemporaries.size() == FirstTemporary)
+ return SubStmt;
+
+ // FIXME: In order to attach the temporaries, wrap the statement into
+ // a StmtExpr; currently this is only used for asm statements.
+ // This is hacky, either create a new CXXStmtWithTemporaries statement or
+ // a new AsmStmtWithTemporaries.
+ CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1,
+ SourceLocation(),
+ SourceLocation());
+ Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
+ SourceLocation());
+ return MaybeCreateExprWithCleanups(E);
+}
+
+ExprResult
+Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind, ParsedType &ObjectType,
+ bool &MayBePseudoDestructor) {
+ // Since this might be a postfix expression, get rid of ParenListExprs.
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.get();
+
+ QualType BaseType = Base->getType();
+ MayBePseudoDestructor = false;
+ if (BaseType->isDependentType()) {
+ // If we have a pointer to a dependent type and are using the -> operator,
+ // the object type is the type that the pointer points to. We might still
+ // have enough information about that type to do something useful.
+ if (OpKind == tok::arrow)
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+
+ ObjectType = ParsedType::make(BaseType);
+ MayBePseudoDestructor = true;
+ return Owned(Base);
+ }
+
+ // C++ [over.match.oper]p8:
+ // [...] When operator->returns, the operator-> is applied to the value
+ // returned, with the original second operand.
+ if (OpKind == tok::arrow) {
+ // The set of types we've considered so far.
+ llvm::SmallPtrSet<CanQualType,8> CTypes;
+ llvm::SmallVector<SourceLocation, 8> Locations;
+ CTypes.insert(Context.getCanonicalType(BaseType));
+
+ while (BaseType->isRecordType()) {
+ Result = BuildOverloadedArrowExpr(S, Base, OpLoc);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
+ Locations.push_back(OpCall->getDirectCallee()->getLocation());
+ BaseType = Base->getType();
+ CanQualType CBaseType = Context.getCanonicalType(BaseType);
+ if (!CTypes.insert(CBaseType)) {
+ Diag(OpLoc, diag::err_operator_arrow_circular);
+ for (unsigned i = 0; i < Locations.size(); i++)
+ Diag(Locations[i], diag::note_declared_at);
+ return ExprError();
+ }
+ }
+
+ if (BaseType->isPointerType())
+ BaseType = BaseType->getPointeeType();
+ }
+
+ // We could end up with various non-record types here, such as extended
+ // vector types or Objective-C interfaces. Just return early and let
+ // ActOnMemberReferenceExpr do the work.
+ if (!BaseType->isRecordType()) {
+ // C++ [basic.lookup.classref]p2:
+ // [...] If the type of the object expression is of pointer to scalar
+ // type, the unqualified-id is looked up in the context of the complete
+ // postfix-expression.
+ //
+ // This also indicates that we should be parsing a
+ // pseudo-destructor-name.
+ ObjectType = ParsedType();
+ MayBePseudoDestructor = true;
+ return Owned(Base);
+ }
+
+ // The object type must be complete (or dependent).
+ if (!BaseType->isDependentType() &&
+ RequireCompleteType(OpLoc, BaseType,
+ PDiag(diag::err_incomplete_member_access)))
+ return ExprError();
+
+ // C++ [basic.lookup.classref]p2:
+ // If the id-expression in a class member access (5.2.5) is an
+ // unqualified-id, and the type of the object expression is of a class
+ // type C (or of pointer to a class type C), the unqualified-id is looked
+ // up in the scope of class C. [...]
+ ObjectType = ParsedType::make(BaseType);
+ return move(Base);
+}
+
+ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
+ Expr *MemExpr) {
+ SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc);
+ Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call)
+ << isa<CXXPseudoDestructorExpr>(MemExpr)
+ << FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
+
+ return ActOnCallExpr(/*Scope*/ 0,
+ MemExpr,
+ /*LPLoc*/ ExpectedLParenLoc,
+ MultiExprArg(),
+ /*RPLoc*/ ExpectedLParenLoc);
+}
+
+ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeTypeInfo,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage Destructed,
+ bool HasTrailingLParen) {
+ TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
+
+ // C++ [expr.pseudo]p2:
+ // The left-hand side of the dot operator shall be of scalar type. The
+ // left-hand side of the arrow operator shall be of pointer to scalar type.
+ // This scalar type is the object type.
+ QualType ObjectType = Base->getType();
+ if (OpKind == tok::arrow) {
+ if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
+ ObjectType = Ptr->getPointeeType();
+ } else if (!Base->isTypeDependent()) {
+ // The user wrote "p->" when she probably meant "p."; fix it.
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << ObjectType << true
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ if (isSFINAEContext())
+ return ExprError();
+
+ OpKind = tok::period;
+ }
+ }
+
+ if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) {
+ Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
+ << ObjectType << Base->getSourceRange();
+ return ExprError();
+ }
+
+ // C++ [expr.pseudo]p2:
+ // [...] The cv-unqualified versions of the object type and of the type
+ // designated by the pseudo-destructor-name shall be the same type.
+ if (DestructedTypeInfo) {
+ QualType DestructedType = DestructedTypeInfo->getType();
+ SourceLocation DestructedTypeStart
+ = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin();
+ if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+ Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+ << ObjectType << DestructedType << Base->getSourceRange()
+ << DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
+
+ // Recover by setting the destructed type to the object type.
+ DestructedType = ObjectType;
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+ DestructedTypeStart);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
+ }
+
+ // C++ [expr.pseudo]p2:
+ // [...] Furthermore, the two type-names in a pseudo-destructor-name of the
+ // form
+ //
+ // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name
+ //
+ // shall designate the same scalar type.
+ if (ScopeTypeInfo) {
+ QualType ScopeType = ScopeTypeInfo->getType();
+ if (!ScopeType->isDependentType() && !ObjectType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) {
+
+ Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(),
+ diag::err_pseudo_dtor_type_mismatch)
+ << ObjectType << ScopeType << Base->getSourceRange()
+ << ScopeTypeInfo->getTypeLoc().getLocalSourceRange();
+
+ ScopeType = QualType();
+ ScopeTypeInfo = 0;
+ }
+ }
+
+ Expr *Result
+ = new (Context) CXXPseudoDestructorExpr(Context, Base,
+ OpKind == tok::arrow, OpLoc,
+ SS.getScopeRep(), SS.getRange(),
+ ScopeTypeInfo,
+ CCLoc,
+ TildeLoc,
+ Destructed);
+
+ if (HasTrailingLParen)
+ return Owned(Result);
+
+ return DiagnoseDtorReference(Destructed.getLocation(), Result);
+}
+
+ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen) {
+ assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ "Invalid first type name in pseudo-destructor");
+ assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
+ "Invalid second type name in pseudo-destructor");
+
+ // C++ [expr.pseudo]p2:
+ // The left-hand side of the dot operator shall be of scalar type. The
+ // left-hand side of the arrow operator shall be of pointer to scalar type.
+ // This scalar type is the object type.
+ QualType ObjectType = Base->getType();
+ if (OpKind == tok::arrow) {
+ if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
+ ObjectType = Ptr->getPointeeType();
+ } else if (!ObjectType->isDependentType()) {
+ // The user wrote "p->" when she probably meant "p."; fix it.
+ Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+ << ObjectType << true
+ << FixItHint::CreateReplacement(OpLoc, ".");
+ if (isSFINAEContext())
+ return ExprError();
+
+ OpKind = tok::period;
+ }
+ }
+
+ // Compute the object type that we should use for name lookup purposes. Only
+ // record types and dependent types matter.
+ ParsedType ObjectTypePtrForLookup;
+ if (!SS.isSet()) {
+ if (const Type *T = ObjectType->getAs<RecordType>())
+ ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0));
+ else if (ObjectType->isDependentType())
+ ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
+ }
+
+ // Convert the name of the type being destructed (following the ~) into a
+ // type (with source-location information).
+ QualType DestructedType;
+ TypeSourceInfo *DestructedTypeInfo = 0;
+ PseudoDestructorTypeStorage Destructed;
+ if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ ParsedType T = getTypeName(*SecondTypeName.Identifier,
+ SecondTypeName.StartLocation,
+ S, &SS, true, false, ObjectTypePtrForLookup);
+ if (!T &&
+ ((SS.isSet() && !computeDeclContext(SS, false)) ||
+ (!SS.isSet() && ObjectType->isDependentType()))) {
+ // The name of the type being destroyed is a dependent name, and we
+ // couldn't find anything useful in scope. Just store the identifier and
+ // it's location, and we'll perform (qualified) name lookup again at
+ // template instantiation time.
+ Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
+ SecondTypeName.StartLocation);
+ } else if (!T) {
+ Diag(SecondTypeName.StartLocation,
+ diag::err_pseudo_dtor_destructor_non_type)
+ << SecondTypeName.Identifier << ObjectType;
+ if (isSFINAEContext())
+ return ExprError();
+
+ // Recover by assuming we had the right type all along.
+ DestructedType = ObjectType;
+ } else
+ DestructedType = GetTypeFromParser(T, &DestructedTypeInfo);
+ } else {
+ // Resolve the template-id to a type.
+ TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ TypeResult T = ActOnTemplateIdType(TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+ if (T.isInvalid() || !T.get()) {
+ // Recover by assuming we had the right type all along.
+ DestructedType = ObjectType;
+ } else
+ DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo);
+ }
+
+ // If we've performed some kind of recovery, (re-)build the type source
+ // information.
+ if (!DestructedType.isNull()) {
+ if (!DestructedTypeInfo)
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+ SecondTypeName.StartLocation);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
+
+ // Convert the name of the scope type (the type prior to '::') into a type.
+ TypeSourceInfo *ScopeTypeInfo = 0;
+ QualType ScopeType;
+ if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
+ FirstTypeName.Identifier) {
+ if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
+ ParsedType T = getTypeName(*FirstTypeName.Identifier,
+ FirstTypeName.StartLocation,
+ S, &SS, false, false, ObjectTypePtrForLookup);
+ if (!T) {
+ Diag(FirstTypeName.StartLocation,
+ diag::err_pseudo_dtor_destructor_non_type)
+ << FirstTypeName.Identifier << ObjectType;
+
+ if (isSFINAEContext())
+ return ExprError();
+
+ // Just drop this type. It's unnecessary anyway.
+ ScopeType = QualType();
+ } else
+ ScopeType = GetTypeFromParser(T, &ScopeTypeInfo);
+ } else {
+ // Resolve the template-id to a type.
+ TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ TypeResult T = ActOnTemplateIdType(TemplateId->Template,
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->RAngleLoc);
+ if (T.isInvalid() || !T.get()) {
+ // Recover by dropping this type.
+ ScopeType = QualType();
+ } else
+ ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo);
+ }
+ }
+
+ if (!ScopeType.isNull() && !ScopeTypeInfo)
+ ScopeTypeInfo = Context.getTrivialTypeSourceInfo(ScopeType,
+ FirstTypeName.StartLocation);
+
+
+ return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS,
+ ScopeTypeInfo, CCLoc, TildeLoc,
+ Destructed, HasTrailingLParen);
+}
+
+ExprResult Sema::BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXMethodDecl *Method) {
+ if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0,
+ FoundDecl, Method))
+ return true;
+
+ MemberExpr *ME =
+ new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
+ SourceLocation(), Method->getType(),
+ VK_RValue, OK_Ordinary);
+ QualType ResultType = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultType);
+ ResultType = ResultType.getNonLValueExprType(Context);
+
+ MarkDeclarationReferenced(Exp->getLocStart(), Method);
+ CXXMemberCallExpr *CE =
+ new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
+ Exp->getLocEnd());
+ return CE;
+}
+
+ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+ SourceLocation RParen) {
+ return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
+ Operand->CanThrow(Context),
+ KeyLoc, RParen));
+}
+
+ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
+ Expr *Operand, SourceLocation RParen) {
+ return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen);
+}
+
+/// Perform the conversions required for an expression used in a
+/// context that ignores the result.
+void Sema::IgnoredValueConversions(Expr *&E) {
+ // C99 6.3.2.1:
+ // [Except in specific positions,] an lvalue that does not have
+ // array type is converted to the value stored in the
+ // designated object (and is no longer an lvalue).
+ if (E->isRValue()) return;
+
+ // We always want to do this on ObjC property references.
+ if (E->getObjectKind() == OK_ObjCProperty) {
+ ConvertPropertyForRValue(E);
+ if (E->isRValue()) return;
+ }
+
+ // Otherwise, this rule does not apply in C++, at least not for the moment.
+ if (getLangOptions().CPlusPlus) return;
+
+ // GCC seems to also exclude expressions of incomplete enum type.
+ if (const EnumType *T = E->getType()->getAs<EnumType>()) {
+ if (!T->getDecl()->isComplete()) {
+ // FIXME: stupid workaround for a codegen bug!
+ ImpCastExprToType(E, Context.VoidTy, CK_ToVoid);
+ return;
+ }
+ }
+
+ DefaultFunctionArrayLvalueConversion(E);
+ if (!E->getType()->isVoidType())
+ RequireCompleteType(E->getExprLoc(), E->getType(),
+ diag::err_incomplete_type);
+}
+
+ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
+ if (!FullExpr)
+ return ExprError();
+
+ if (DiagnoseUnexpandedParameterPack(FullExpr))
+ return ExprError();
+
+ IgnoredValueConversions(FullExpr);
+ CheckImplicitConversions(FullExpr);
+ return MaybeCreateExprWithCleanups(FullExpr);
+}
+
+StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
+ if (!FullStmt) return StmtError();
+
+ return MaybeCreateStmtWithCleanups(FullStmt);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
new file mode 100644
index 0000000..4d03b06
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -0,0 +1,1210 @@
+//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for Objective-C expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallString.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+using namespace sema;
+
+ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
+ Expr **strings,
+ unsigned NumStrings) {
+ StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
+
+ // Most ObjC strings are formed out of a single piece. However, we *can*
+ // have strings formed out of multiple @ strings with multiple pptokens in
+ // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
+ // StringLiteral for ObjCStringLiteral to hold onto.
+ StringLiteral *S = Strings[0];
+
+ // If we have a multi-part string, merge it all together.
+ if (NumStrings != 1) {
+ // Concatenate objc strings.
+ llvm::SmallString<128> StrBuf;
+ llvm::SmallVector<SourceLocation, 8> StrLocs;
+
+ for (unsigned i = 0; i != NumStrings; ++i) {
+ S = Strings[i];
+
+ // ObjC strings can't be wide.
+ if (S->isWide()) {
+ Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
+ << S->getSourceRange();
+ return true;
+ }
+
+ // Append the string.
+ StrBuf += S->getString();
+
+ // Get the locations of the string tokens.
+ StrLocs.append(S->tokloc_begin(), S->tokloc_end());
+ }
+
+ // Create the aggregate string with the appropriate content and location
+ // information.
+ S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
+ Context.getPointerType(Context.CharTy),
+ &StrLocs[0], StrLocs.size());
+ }
+
+ // Verify that this composite string is acceptable for ObjC strings.
+ if (CheckObjCString(S))
+ return true;
+
+ // Initialize the constant string interface lazily. This assumes
+ // the NSString interface is seen in this translation unit. Note: We
+ // don't use NSConstantString, since the runtime team considers this
+ // interface private (even though it appears in the header files).
+ QualType Ty = Context.getObjCConstantStringInterface();
+ if (!Ty.isNull()) {
+ Ty = Context.getObjCObjectPointerType(Ty);
+ } else if (getLangOptions().NoConstantCFStrings) {
+ IdentifierInfo *NSIdent=0;
+ std::string StringClass(getLangOptions().ObjCConstantStringClass);
+
+ if (StringClass.empty())
+ NSIdent = &Context.Idents.get("NSConstantString");
+ else
+ NSIdent = &Context.Idents.get(StringClass);
+
+ NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0],
+ LookupOrdinaryName);
+ if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
+ Context.setObjCConstantStringInterface(StrIF);
+ Ty = Context.getObjCConstantStringInterface();
+ Ty = Context.getObjCObjectPointerType(Ty);
+ } else {
+ // If there is no NSConstantString interface defined then treat this
+ // as error and recover from it.
+ Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent
+ << S->getSourceRange();
+ Ty = Context.getObjCIdType();
+ }
+ } else {
+ IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
+ NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0],
+ LookupOrdinaryName);
+ if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
+ Context.setObjCConstantStringInterface(StrIF);
+ Ty = Context.getObjCConstantStringInterface();
+ Ty = Context.getObjCObjectPointerType(Ty);
+ } else {
+ // If there is no NSString interface defined then treat constant
+ // strings as untyped objects and let the runtime figure it out later.
+ Ty = Context.getObjCIdType();
+ }
+ }
+
+ return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
+}
+
+Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc) {
+ QualType EncodedType = EncodedTypeInfo->getType();
+ QualType StrTy;
+ if (EncodedType->isDependentType())
+ StrTy = Context.DependentTy;
+ else {
+ std::string Str;
+ Context.getObjCEncodingForType(EncodedType, Str);
+
+ // The type of @encode is the same as the type of the corresponding string,
+ // which is an array type.
+ StrTy = Context.CharTy;
+ // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
+ if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings)
+ StrTy.addConst();
+ StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
+ ArrayType::Normal, 0);
+ }
+
+ return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType ty,
+ SourceLocation RParenLoc) {
+ // FIXME: Preserve type source info ?
+ TypeSourceInfo *TInfo;
+ QualType EncodedType = GetTypeFromParser(ty, &TInfo);
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
+ PP.getLocForEndOfToken(LParenLoc));
+
+ return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc), false, false);
+ if (!Method)
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc));
+ if (!Method)
+ Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+
+ llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+ = ReferencedSelectors.find(Sel);
+ if (Pos == ReferencedSelectors.end())
+ ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+
+ QualType Ty = Context.getObjCSelType();
+ return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
+}
+
+ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc);
+ if (!PDecl) {
+ Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
+ return true;
+ }
+
+ QualType Ty = Context.getObjCProtoType();
+ if (Ty.isNull())
+ return true;
+ Ty = Context.getObjCObjectPointerType(Ty);
+ return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
+}
+
+/// Try to capture an implicit reference to 'self'.
+ObjCMethodDecl *Sema::tryCaptureObjCSelf() {
+ // Ignore block scopes: we can capture through them.
+ DeclContext *DC = CurContext;
+ while (true) {
+ if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext();
+ else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext();
+ else break;
+ }
+
+ // If we're not in an ObjC method, error out. Note that, unlike the
+ // C++ case, we don't require an instance method --- class methods
+ // still have a 'self', and we really do still need to capture it!
+ ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
+ if (!method)
+ return 0;
+
+ ImplicitParamDecl *self = method->getSelfDecl();
+ assert(self && "capturing 'self' in non-definition?");
+
+ // Mark that we're closing on 'this' in all the block scopes, if applicable.
+ for (unsigned idx = FunctionScopes.size() - 1;
+ isa<BlockScopeInfo>(FunctionScopes[idx]);
+ --idx) {
+ BlockScopeInfo *blockScope = cast<BlockScopeInfo>(FunctionScopes[idx]);
+ unsigned &captureIndex = blockScope->CaptureMap[self];
+ if (captureIndex) break;
+
+ bool nested = isa<BlockScopeInfo>(FunctionScopes[idx-1]);
+ blockScope->Captures.push_back(
+ BlockDecl::Capture(self, /*byref*/ false, nested, /*copy*/ 0));
+ captureIndex = blockScope->Captures.size(); // +1
+ }
+
+ return method;
+}
+
+
+bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
+ Selector Sel, ObjCMethodDecl *Method,
+ bool isClassMessage,
+ SourceLocation lbrac, SourceLocation rbrac,
+ QualType &ReturnType, ExprValueKind &VK) {
+ if (!Method) {
+ // Apply default argument promotion as for (C99 6.5.2.2p6).
+ for (unsigned i = 0; i != NumArgs; i++) {
+ if (Args[i]->isTypeDependent())
+ continue;
+
+ DefaultArgumentPromotion(Args[i]);
+ }
+
+ unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found :
+ diag::warn_inst_method_not_found;
+ Diag(lbrac, DiagID)
+ << Sel << isClassMessage << SourceRange(lbrac, rbrac);
+ ReturnType = Context.getObjCIdType();
+ VK = VK_RValue;
+ return false;
+ }
+
+ ReturnType = Method->getSendResultType();
+ VK = Expr::getValueKindForType(Method->getResultType());
+
+ unsigned NumNamedArgs = Sel.getNumArgs();
+ // Method might have more arguments than selector indicates. This is due
+ // to addition of c-style arguments in method.
+ if (Method->param_size() > Sel.getNumArgs())
+ NumNamedArgs = Method->param_size();
+ // FIXME. This need be cleaned up.
+ if (NumArgs < NumNamedArgs) {
+ Diag(lbrac, diag::err_typecheck_call_too_few_args)
+ << 2 << NumNamedArgs << NumArgs;
+ return false;
+ }
+
+ bool IsError = false;
+ for (unsigned i = 0; i < NumNamedArgs; i++) {
+ // We can't do any type-checking on a type-dependent argument.
+ if (Args[i]->isTypeDependent())
+ continue;
+
+ Expr *argExpr = Args[i];
+
+ ParmVarDecl *Param = Method->param_begin()[i];
+ assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+
+ if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
+ Param->getType(),
+ PDiag(diag::err_call_incomplete_argument)
+ << argExpr->getSourceRange()))
+ return true;
+
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+ Param);
+ ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr));
+ if (ArgE.isInvalid())
+ IsError = true;
+ else
+ Args[i] = ArgE.takeAs<Expr>();
+ }
+
+ // Promote additional arguments to variadic methods.
+ if (Method->isVariadic()) {
+ for (unsigned i = NumNamedArgs; i < NumArgs; ++i) {
+ if (Args[i]->isTypeDependent())
+ continue;
+
+ IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
+ }
+ } else {
+ // Check for extra arguments to non-variadic methods.
+ if (NumArgs != NumNamedArgs) {
+ Diag(Args[NumNamedArgs]->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 2 /*method*/ << NumNamedArgs << NumArgs
+ << Method->getSourceRange()
+ << SourceRange(Args[NumNamedArgs]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd());
+ }
+ }
+
+ DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
+ return IsError;
+}
+
+bool Sema::isSelfExpr(Expr *RExpr) {
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RExpr))
+ if (ICE->getCastKind() == CK_LValueToRValue)
+ RExpr = ICE->getSubExpr();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr))
+ if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
+ return true;
+ return false;
+}
+
+// Helper method for ActOnClassMethod/ActOnInstanceMethod.
+// Will search "local" class/category implementations for a method decl.
+// If failed, then we search in class's root for an instance method.
+// Returns 0 if no method is found.
+ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
+ ObjCInterfaceDecl *ClassDecl) {
+ ObjCMethodDecl *Method = 0;
+ // lookup in class and all superclasses
+ while (ClassDecl && !Method) {
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+ Method = ImpDecl->getClassMethod(Sel);
+
+ // Look through local category implementations associated with the class.
+ if (!Method)
+ Method = ClassDecl->getCategoryClassMethod(Sel);
+
+ // Before we give up, check if the selector is an instance method.
+ // But only in the root. This matches gcc's behaviour and what the
+ // runtime expects.
+ if (!Method && !ClassDecl->getSuperClass()) {
+ Method = ClassDecl->lookupInstanceMethod(Sel);
+ // Look through local category implementations associated
+ // with the root class.
+ if (!Method)
+ Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+ }
+
+ ClassDecl = ClassDecl->getSuperClass();
+ }
+ return Method;
+}
+
+ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
+ ObjCInterfaceDecl *ClassDecl) {
+ ObjCMethodDecl *Method = 0;
+ while (ClassDecl && !Method) {
+ // If we have implementations in scope, check "private" methods.
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+ Method = ImpDecl->getInstanceMethod(Sel);
+
+ // Look through local category implementations associated with the class.
+ if (!Method)
+ Method = ClassDecl->getCategoryInstanceMethod(Sel);
+ ClassDecl = ClassDecl->getSuperClass();
+ }
+ return Method;
+}
+
+/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
+/// objective C interface. This is a property reference expression.
+ExprResult Sema::
+HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr, DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc, QualType SuperType,
+ bool Super) {
+ const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
+ ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+ if (IFace->isForwardDecl()) {
+ Diag(MemberLoc, diag::err_property_not_found_forward_class)
+ << MemberName << QualType(OPT, 0);
+ Diag(IFace->getLocation(), diag::note_forward_class);
+ return ExprError();
+ }
+ // Search for a declared property first.
+ if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
+ // Check whether we can reference this property.
+ if (DiagnoseUseOfDecl(PD, MemberLoc))
+ return ExprError();
+ QualType ResTy = PD->getType();
+ Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+ ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+ if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
+ ResTy = Getter->getResultType();
+
+ if (Super)
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+ VK_LValue, OK_ObjCProperty,
+ MemberLoc,
+ SuperLoc, SuperType));
+ else
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+ VK_LValue, OK_ObjCProperty,
+ MemberLoc, BaseExpr));
+ }
+ // Check protocols on qualified interfaces.
+ for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I)
+ if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+ // Check whether we can reference this property.
+ if (DiagnoseUseOfDecl(PD, MemberLoc))
+ return ExprError();
+ if (Super)
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ VK_LValue,
+ OK_ObjCProperty,
+ MemberLoc,
+ SuperLoc, SuperType));
+ else
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ VK_LValue,
+ OK_ObjCProperty,
+ MemberLoc,
+ BaseExpr));
+ }
+ // If that failed, look for an "implicit" property by seeing if the nullary
+ // selector is implemented.
+
+ // FIXME: The logic for looking up nullary and unary selectors should be
+ // shared with the code in ActOnInstanceMessage.
+
+ Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+ ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+
+ // If this reference is in an @implementation, check for 'private' methods.
+ if (!Getter)
+ Getter = IFace->lookupPrivateMethod(Sel);
+
+ // Look through local category implementations associated with the class.
+ if (!Getter)
+ Getter = IFace->getCategoryInstanceMethod(Sel);
+ if (Getter) {
+ // Check if we can reference this property.
+ if (DiagnoseUseOfDecl(Getter, MemberLoc))
+ return ExprError();
+ }
+ // If we found a getter then this may be a valid dot-reference, we
+ // will look for the matching setter, in case it is needed.
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), Member);
+ ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ Setter = IFace->lookupPrivateMethod(SetterSel);
+ }
+ // Look through local category implementations associated with the class.
+ if (!Setter)
+ Setter = IFace->getCategoryInstanceMethod(SetterSel);
+
+ if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+ return ExprError();
+
+ if (Getter || Setter) {
+ QualType PType;
+ if (Getter)
+ PType = Getter->getSendResultType();
+ else {
+ ParmVarDecl *ArgDecl = *Setter->param_begin();
+ PType = ArgDecl->getType();
+ }
+
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_ObjCProperty;
+ if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() &&
+ PType->isVoidType())
+ VK = VK_RValue, OK = OK_Ordinary;
+
+ if (Super)
+ return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+ PType, VK, OK,
+ MemberLoc,
+ SuperLoc, SuperType));
+ else
+ return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+ PType, VK, OK,
+ MemberLoc, BaseExpr));
+
+ }
+
+ // Attempt to correct for typos in property names.
+ LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName);
+ if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) &&
+ Res.getAsSingle<ObjCPropertyDecl>()) {
+ DeclarationName TypoResult = Res.getLookupName();
+ Diag(MemberLoc, diag::err_property_not_found_suggest)
+ << MemberName << QualType(OPT, 0) << TypoResult
+ << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString());
+ ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
+ Diag(Property->getLocation(), diag::note_previous_decl)
+ << Property->getDeclName();
+ return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc,
+ SuperLoc, SuperType, Super);
+ }
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *Ivar =
+ IFace->lookupInstanceVariable(Member, ClassDeclared)) {
+ QualType T = Ivar->getType();
+ if (const ObjCObjectPointerType * OBJPT =
+ T->getAsObjCInterfacePointerType()) {
+ const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
+ if (ObjCInterfaceDecl *IFace = IFaceT->getDecl())
+ if (IFace->isForwardDecl()) {
+ Diag(MemberLoc, diag::err_property_not_as_forward_class)
+ << MemberName << IFace;
+ Diag(IFace->getLocation(), diag::note_forward_class);
+ return ExprError();
+ }
+ }
+ }
+
+ Diag(MemberLoc, diag::err_property_not_found)
+ << MemberName << QualType(OPT, 0);
+ if (Setter)
+ Diag(Setter->getLocation(), diag::note_getter_unavailable)
+ << MemberName << BaseExpr->getSourceRange();
+ return ExprError();
+}
+
+
+
+ExprResult Sema::
+ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc) {
+
+ IdentifierInfo *receiverNamePtr = &receiverName;
+ ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
+ receiverNameLoc);
+ if (IFace == 0) {
+ // If the "receiver" is 'super' in a method, handle it as an expression-like
+ // property reference.
+ if (receiverNamePtr->isStr("super")) {
+ if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) {
+ if (CurMethod->isInstanceMethod()) {
+ QualType T =
+ Context.getObjCInterfaceType(CurMethod->getClassInterface());
+ T = Context.getObjCObjectPointerType(T);
+
+ return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
+ /*BaseExpr*/0, &propertyName,
+ propertyNameLoc,
+ receiverNameLoc, T, true);
+ }
+
+ // Otherwise, if this is a class method, try dispatching to our
+ // superclass.
+ IFace = CurMethod->getClassInterface()->getSuperClass();
+ }
+ }
+
+ if (IFace == 0) {
+ Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
+ return ExprError();
+ }
+ }
+
+ // Search for a declared property first.
+ Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
+ ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
+
+ // If this reference is in an @implementation, check for 'private' methods.
+ if (!Getter)
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+ Getter = ImpDecl->getClassMethod(Sel);
+
+ if (Getter) {
+ // FIXME: refactor/share with ActOnMemberReference().
+ // Check if we can reference this property.
+ if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
+ return ExprError();
+ }
+
+ // Look for the matching setter, in case it is needed.
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), &propertyName);
+
+ ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
+ Setter = ImpDecl->getClassMethod(SetterSel);
+ }
+ // Look through local category implementations associated with the class.
+ if (!Setter)
+ Setter = IFace->getCategoryClassMethod(SetterSel);
+
+ if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
+ return ExprError();
+
+ if (Getter || Setter) {
+ QualType PType;
+
+ ExprValueKind VK = VK_LValue;
+ if (Getter) {
+ PType = Getter->getSendResultType();
+ if (!getLangOptions().CPlusPlus &&
+ !PType.hasQualifiers() && PType->isVoidType())
+ VK = VK_RValue;
+ } else {
+ for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
+ E = Setter->param_end(); PI != E; ++PI)
+ PType = (*PI)->getType();
+ VK = VK_LValue;
+ }
+
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
+ return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
+ PType, VK, OK,
+ propertyNameLoc,
+ receiverNameLoc, IFace));
+ }
+ return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
+ << &propertyName << Context.getObjCInterfaceType(IFace));
+}
+
+Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType) {
+ ReceiverType = ParsedType();
+
+ // If the identifier is "super" and there is no trailing dot, we're
+ // messaging super. If the identifier is "super" and there is a
+ // trailing dot, it's an instance message.
+ if (IsSuper && S->isInObjcMethodScope())
+ return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;
+
+ LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupName(Result, S);
+
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ // Normal name lookup didn't find anything. If we're in an
+ // Objective-C method, look for ivars. If we find one, we're done!
+ // FIXME: This is a hack. Ivar lookup should be part of normal
+ // lookup.
+ if (ObjCMethodDecl *Method = getCurMethodDecl()) {
+ ObjCInterfaceDecl *ClassDeclared;
+ if (Method->getClassInterface()->lookupInstanceVariable(Name,
+ ClassDeclared))
+ return ObjCInstanceMessage;
+ }
+
+ // Break out; we'll perform typo correction below.
+ break;
+
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ case LookupResult::Ambiguous:
+ Result.suppressDiagnostics();
+ return ObjCInstanceMessage;
+
+ case LookupResult::Found: {
+ // If the identifier is a class or not, and there is a trailing dot,
+ // it's an instance message.
+ if (HasTrailingDot)
+ return ObjCInstanceMessage;
+ // We found something. If it's a type, then we have a class
+ // message. Otherwise, it's an instance message.
+ NamedDecl *ND = Result.getFoundDecl();
+ QualType T;
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
+ T = Context.getObjCInterfaceType(Class);
+ else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ T = Context.getTypeDeclType(Type);
+ else
+ return ObjCInstanceMessage;
+
+ // We have a class message, and T is the type we're
+ // messaging. Build source-location information for it.
+ TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
+ ReceiverType = CreateParsedType(T, TSInfo);
+ return ObjCClassMessage;
+ }
+ }
+
+ // Determine our typo-correction context.
+ CorrectTypoContext CTC = CTC_Expression;
+ if (ObjCMethodDecl *Method = getCurMethodDecl())
+ if (Method->getClassInterface() &&
+ Method->getClassInterface()->getSuperClass())
+ CTC = CTC_ObjCMessageReceiver;
+
+ if (DeclarationName Corrected = CorrectTypo(Result, S, 0, 0, false, CTC)) {
+ if (Result.isSingleResult()) {
+ // If we found a declaration, correct when it refers to an Objective-C
+ // class.
+ NamedDecl *ND = Result.getFoundDecl();
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) {
+ Diag(NameLoc, diag::err_unknown_receiver_suggest)
+ << Name << Result.getLookupName()
+ << FixItHint::CreateReplacement(SourceRange(NameLoc),
+ ND->getNameAsString());
+ Diag(ND->getLocation(), diag::note_previous_decl)
+ << Corrected;
+
+ QualType T = Context.getObjCInterfaceType(Class);
+ TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
+ ReceiverType = CreateParsedType(T, TSInfo);
+ return ObjCClassMessage;
+ }
+ } else if (Result.empty() && Corrected.getAsIdentifierInfo() &&
+ Corrected.getAsIdentifierInfo()->isStr("super")) {
+ // If we've found the keyword "super", this is a send to super.
+ Diag(NameLoc, diag::err_unknown_receiver_suggest)
+ << Name << Corrected
+ << FixItHint::CreateReplacement(SourceRange(NameLoc), "super");
+ return ObjCSuperMessage;
+ }
+ }
+
+ // Fall back: let the parser try to parse it as an instance message.
+ return ObjCInstanceMessage;
+}
+
+ExprResult Sema::ActOnSuperMessage(Scope *S,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
+ // Determine whether we are inside a method or not.
+ ObjCMethodDecl *Method = tryCaptureObjCSelf();
+ if (!Method) {
+ Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
+ return ExprError();
+ }
+
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ if (!Class) {
+ Diag(SuperLoc, diag::error_no_super_class_message)
+ << Method->getDeclName();
+ return ExprError();
+ }
+
+ ObjCInterfaceDecl *Super = Class->getSuperClass();
+ if (!Super) {
+ // The current class does not have a superclass.
+ Diag(SuperLoc, diag::error_root_class_cannot_use_super)
+ << Class->getIdentifier();
+ return ExprError();
+ }
+
+ // We are in a method whose class has a superclass, so 'super'
+ // is acting as a keyword.
+ if (Method->isInstanceMethod()) {
+ // Since we are in an instance method, this is an instance
+ // message to the superclass instance.
+ QualType SuperTy = Context.getObjCInterfaceType(Super);
+ SuperTy = Context.getObjCObjectPointerType(SuperTy);
+ return BuildInstanceMessage(0, SuperTy, SuperLoc,
+ Sel, /*Method=*/0,
+ LBracLoc, SelectorLoc, RBracLoc, move(Args));
+ }
+
+ // Since we are in a class method, this is a class message to
+ // the superclass.
+ return BuildClassMessage(/*ReceiverTypeInfo=*/0,
+ Context.getObjCInterfaceType(Super),
+ SuperLoc, Sel, /*Method=*/0,
+ LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
+
+/// \brief Build an Objective-C class message expression.
+///
+/// This routine takes care of both normal class messages and
+/// class messages to the superclass.
+///
+/// \param ReceiverTypeInfo Type source information that describes the
+/// receiver of this message. This may be NULL, in which case we are
+/// sending to the superclass and \p SuperLoc must be a valid source
+/// location.
+
+/// \param ReceiverType The type of the object receiving the
+/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
+/// type as that refers to. For a superclass send, this is the type of
+/// the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param Method The method that this class message is invoking, if
+/// already known.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg ArgsIn) {
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc
+ : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
+ if (LBracLoc.isInvalid()) {
+ Diag(Loc, diag::err_missing_open_square_message_send)
+ << FixItHint::CreateInsertion(Loc, "[");
+ LBracLoc = Loc;
+ }
+
+ if (ReceiverType->isDependentType()) {
+ // If the receiver type is dependent, we can't type-check anything
+ // at this point. Build a dependent expression.
+ unsigned NumArgs = ArgsIn.size();
+ Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+ assert(SuperLoc.isInvalid() && "Message to super with dependent type");
+ return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
+ VK_RValue, LBracLoc, ReceiverTypeInfo,
+ Sel, SelectorLoc, /*Method=*/0,
+ Args, NumArgs, RBracLoc));
+ }
+
+ // Find the class to which we are sending this message.
+ ObjCInterfaceDecl *Class = 0;
+ const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
+ if (!ClassType || !(Class = ClassType->getInterface())) {
+ Diag(Loc, diag::err_invalid_receiver_class_message)
+ << ReceiverType;
+ return ExprError();
+ }
+ assert(Class && "We don't know which class we're messaging?");
+
+ // Find the method we are messaging.
+ if (!Method) {
+ if (Class->isForwardDecl()) {
+ // A forward class used in messaging is treated as a 'Class'
+ Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ if (Method)
+ Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+ << Method->getDeclName();
+ }
+ if (!Method)
+ Method = Class->lookupClassMethod(Sel);
+
+ // If we have an implementation in scope, check "private" methods.
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, Class);
+
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
+ }
+
+ // Check the argument types and determine the result type.
+ QualType ReturnType;
+ ExprValueKind VK = VK_RValue;
+
+ unsigned NumArgs = ArgsIn.size();
+ Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+ if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true,
+ LBracLoc, RBracLoc, ReturnType, VK))
+ return ExprError();
+
+ if (Method && !Method->getResultType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getResultType(),
+ diag::err_illegal_message_expr_incomplete_type))
+ return ExprError();
+
+ // Construct the appropriate ObjCMessageExpr.
+ Expr *Result;
+ if (SuperLoc.isValid())
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ SuperLoc, /*IsInstanceSuper=*/false,
+ ReceiverType, Sel, SelectorLoc,
+ Method, Args, NumArgs, RBracLoc);
+ else
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ ReceiverTypeInfo, Sel, SelectorLoc,
+ Method, Args, NumArgs, RBracLoc);
+ return MaybeBindToTemporary(Result);
+}
+
+// ActOnClassMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+ExprResult Sema::ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
+ TypeSourceInfo *ReceiverTypeInfo;
+ QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
+ if (ReceiverType.isNull())
+ return ExprError();
+
+
+ if (!ReceiverTypeInfo)
+ ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
+
+ return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
+ /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
+ LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
+
+/// \brief Build an Objective-C instance message expression.
+///
+/// This routine takes care of both normal instance messages and
+/// instance messages to the superclass instance.
+///
+/// \param Receiver The expression that computes the object that will
+/// receive this message. This may be empty, in which case we are
+/// sending to the superclass instance and \p SuperLoc must be a valid
+/// source location.
+///
+/// \param ReceiverType The (static) type of the object receiving the
+/// message. When a \p Receiver expression is provided, this is the
+/// same type as that expression. For a superclass instance send, this
+/// is a pointer to the type of the superclass.
+///
+/// \param SuperLoc The location of the "super" keyword in a
+/// superclass instance message.
+///
+/// \param Sel The selector to which the message is being sent.
+///
+/// \param Method The method that this instance message is invoking, if
+/// already known.
+///
+/// \param LBracLoc The location of the opening square bracket ']'.
+///
+/// \param RBrac The location of the closing square bracket ']'.
+///
+/// \param Args The message arguments.
+ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg ArgsIn) {
+ // The location of the receiver.
+ SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
+
+ if (LBracLoc.isInvalid()) {
+ Diag(Loc, diag::err_missing_open_square_message_send)
+ << FixItHint::CreateInsertion(Loc, "[");
+ LBracLoc = Loc;
+ }
+
+ // If we have a receiver expression, perform appropriate promotions
+ // and determine receiver type.
+ if (Receiver) {
+ if (Receiver->isTypeDependent()) {
+ // If the receiver is type-dependent, we can't type-check anything
+ // at this point. Build a dependent expression.
+ unsigned NumArgs = ArgsIn.size();
+ Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+ assert(SuperLoc.isInvalid() && "Message to super with dependent type");
+ return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
+ VK_RValue, LBracLoc, Receiver, Sel,
+ SelectorLoc, /*Method=*/0,
+ Args, NumArgs, RBracLoc));
+ }
+
+ // If necessary, apply function/array conversion to the receiver.
+ // C99 6.7.5.3p[7,8].
+ DefaultFunctionArrayLvalueConversion(Receiver);
+ ReceiverType = Receiver->getType();
+ }
+
+ if (!Method) {
+ // Handle messages to id.
+ bool receiverIsId = ReceiverType->isObjCIdType();
+ if (receiverIsId || ReceiverType->isBlockPointerType() ||
+ (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsId);
+ if (!Method)
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsId);
+ } else if (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType()) {
+ // Handle messages to Class.
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+ // First check the public methods in the class interface.
+ Method = ClassDecl->lookupClassMethod(Sel);
+
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, ClassDecl);
+
+ // FIXME: if we still haven't found a method, we need to look in
+ // protocols (if we have qualifiers).
+ }
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
+ }
+ if (!Method) {
+ // If not messaging 'self', look for any factory method named 'Sel'.
+ if (!Receiver || !isSelfExpr(Receiver)) {
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ if (!Method) {
+ // If no class (factory) method was found, check if an _instance_
+ // method of the same name exists in the root class only.
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc),
+ true);
+ if (Method)
+ if (const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+ if (ID->getSuperClass())
+ Diag(Loc, diag::warn_root_inst_method_not_found)
+ << Sel << SourceRange(LBracLoc, RBracLoc);
+ }
+ }
+ }
+ }
+ } else {
+ ObjCInterfaceDecl* ClassDecl = 0;
+
+ // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
+ // long as one of the protocols implements the selector (if not, warn).
+ if (const ObjCObjectPointerType *QIdTy
+ = ReceiverType->getAsObjCQualifiedIdType()) {
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+ E = QIdTy->qual_end(); I != E; ++I) {
+ ObjCProtocolDecl *PDecl = *I;
+ if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
+ break;
+ // Since we aren't supporting "Class<foo>", look for a class method.
+ if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
+ break;
+ }
+ } else if (const ObjCObjectPointerType *OCIType
+ = ReceiverType->getAsObjCInterfacePointerType()) {
+ // We allow sending a message to a pointer to an interface (an object).
+ ClassDecl = OCIType->getInterfaceDecl();
+ // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
+ // faster than the following method (which can do *many* linear searches).
+ // The idea is to add class info to MethodPool.
+ Method = ClassDecl->lookupInstanceMethod(Sel);
+
+ if (!Method) {
+ // Search protocol qualifiers.
+ for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
+ E = OCIType->qual_end(); QI != E; ++QI) {
+ if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+ break;
+ }
+ }
+ bool forwardClass = false;
+ if (!Method) {
+ // If we have implementations in scope, check "private" methods.
+ Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+
+ if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
+ // If we still haven't found a method, look in the global pool. This
+ // behavior isn't very desirable, however we need it for GCC
+ // compatibility. FIXME: should we deviate??
+ if (OCIType->qual_empty()) {
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ forwardClass = OCIType->getInterfaceDecl()->isForwardDecl();
+ if (Method && !forwardClass)
+ Diag(Loc, diag::warn_maynot_respond)
+ << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+ }
+ }
+ }
+ if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
+ return ExprError();
+ } else if (!Context.getObjCIdType().isNull() &&
+ (ReceiverType->isPointerType() ||
+ ReceiverType->isIntegerType())) {
+ // Implicitly convert integers and pointers to 'id' but emit a warning.
+ Diag(Loc, diag::warn_bad_receiver_type)
+ << ReceiverType
+ << Receiver->getSourceRange();
+ if (ReceiverType->isPointerType())
+ ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ CK_BitCast);
+ else {
+ // TODO: specialized warning on null receivers?
+ bool IsNull = Receiver->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull);
+ ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ IsNull ? CK_NullToPointer : CK_IntegralToPointer);
+ }
+ ReceiverType = Receiver->getType();
+ }
+ else if (getLangOptions().CPlusPlus &&
+ !PerformContextuallyConvertToObjCId(Receiver)) {
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) {
+ Receiver = ICE->getSubExpr();
+ ReceiverType = Receiver->getType();
+ }
+ return BuildInstanceMessage(Receiver,
+ ReceiverType,
+ SuperLoc,
+ Sel,
+ Method,
+ LBracLoc,
+ SelectorLoc,
+ RBracLoc,
+ move(ArgsIn));
+ } else {
+ // Reject other random receiver types (e.g. structs).
+ Diag(Loc, diag::err_bad_receiver_type)
+ << ReceiverType << Receiver->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
+ // Check the message arguments.
+ unsigned NumArgs = ArgsIn.size();
+ Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
+ QualType ReturnType;
+ ExprValueKind VK = VK_RValue;
+ bool ClassMessage = (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType());
+ if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, ClassMessage,
+ LBracLoc, RBracLoc, ReturnType, VK))
+ return ExprError();
+
+ if (Method && !Method->getResultType()->isVoidType() &&
+ RequireCompleteType(LBracLoc, Method->getResultType(),
+ diag::err_illegal_message_expr_incomplete_type))
+ return ExprError();
+
+ // Construct the appropriate ObjCMessageExpr instance.
+ Expr *Result;
+ if (SuperLoc.isValid())
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ SuperLoc, /*IsInstanceSuper=*/true,
+ ReceiverType, Sel, SelectorLoc, Method,
+ Args, NumArgs, RBracLoc);
+ else
+ Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
+ Receiver, Sel, SelectorLoc, Method,
+ Args, NumArgs, RBracLoc);
+ return MaybeBindToTemporary(Result);
+}
+
+// ActOnInstanceMessage - used for both unary and keyword messages.
+// ArgExprs is optional - if it is present, the number of expressions
+// is obtained from Sel.getNumArgs().
+ExprResult Sema::ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
+ if (!Receiver)
+ return ExprError();
+
+ return BuildInstanceMessage(Receiver, Receiver->getType(),
+ /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
+ LBracLoc, SelectorLoc, RBracLoc, move(Args));
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
new file mode 100644
index 0000000..b9a6a57
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -0,0 +1,4552 @@
+//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for initializers. The main entry
+// point is Sema::CheckInitList(), but all of the work is performed
+// within the InitListChecker class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <map>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Sema Initialization Checking
+//===----------------------------------------------------------------------===//
+
+static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
+ const ArrayType *AT = Context.getAsArrayType(DeclType);
+ if (!AT) return 0;
+
+ if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
+ return 0;
+
+ // See if this is a string literal or @encode.
+ Init = Init->IgnoreParens();
+
+ // Handle @encode, which is a narrow string.
+ if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
+ return Init;
+
+ // Otherwise we can only handle string literals.
+ StringLiteral *SL = dyn_cast<StringLiteral>(Init);
+ if (SL == 0) return 0;
+
+ QualType ElemTy = Context.getCanonicalType(AT->getElementType());
+ // char array can be initialized with a narrow string.
+ // Only allow char x[] = "foo"; not char x[] = L"foo";
+ if (!SL->isWide())
+ return ElemTy->isCharType() ? Init : 0;
+
+ // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
+ // correction from DR343): "An array with element type compatible with a
+ // qualified or unqualified version of wchar_t may be initialized by a wide
+ // string literal, optionally enclosed in braces."
+ if (Context.typesAreCompatible(Context.getWCharType(),
+ ElemTy.getUnqualifiedType()))
+ return Init;
+
+ return 0;
+}
+
+static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
+ // Get the length of the string as parsed.
+ uint64_t StrLength =
+ cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
+
+
+ const ArrayType *AT = S.Context.getAsArrayType(DeclT);
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
+ // C99 6.7.8p14. We have an array of character type with unknown size
+ // being initialized to a string literal.
+ llvm::APSInt ConstVal(32);
+ ConstVal = StrLength;
+ // Return a new array type (C99 6.7.8p22).
+ DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
+ ConstVal,
+ ArrayType::Normal, 0);
+ return;
+ }
+
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+
+ // C99 6.7.8p14. We have an array of character type with known size. However,
+ // the size may be smaller or larger than the string we are initializing.
+ // FIXME: Avoid truncation for 64-bit length strings.
+ if (StrLength-1 > CAT->getSize().getZExtValue())
+ S.Diag(Str->getSourceRange().getBegin(),
+ diag::warn_initializer_string_for_char_array_too_long)
+ << Str->getSourceRange();
+
+ // Set the type to the actual size that we are initializing. If we have
+ // something like:
+ // char x[1] = "foo";
+ // then this will set the string literal's type to char[1].
+ Str->setType(DeclT);
+}
+
+//===----------------------------------------------------------------------===//
+// Semantic checking for initializer lists.
+//===----------------------------------------------------------------------===//
+
+/// @brief Semantic checking for initializer lists.
+///
+/// The InitListChecker class contains a set of routines that each
+/// handle the initialization of a certain kind of entity, e.g.,
+/// arrays, vectors, struct/union types, scalars, etc. The
+/// InitListChecker itself performs a recursive walk of the subobject
+/// structure of the type to be initialized, while stepping through
+/// the initializer list one element at a time. The IList and Index
+/// parameters to each of the Check* routines contain the active
+/// (syntactic) initializer list and the index into that initializer
+/// list that represents the current initializer. Each routine is
+/// responsible for moving that Index forward as it consumes elements.
+///
+/// Each Check* routine also has a StructuredList/StructuredIndex
+/// arguments, which contains the current "structured" (semantic)
+/// initializer list and the index into that initializer list where we
+/// are copying initializers as we map them over to the semantic
+/// list. Once we have completed our recursive walk of the subobject
+/// structure, we will have constructed a full semantic initializer
+/// list.
+///
+/// C99 designators cause changes in the initializer list traversal,
+/// because they make the initialization "jump" into a specific
+/// subobject and then continue the initialization from that
+/// point. CheckDesignatedInitializer() recursively steps into the
+/// designated subobject and manages backing out the recursion to
+/// initialize the subobjects after the one designated.
+namespace {
+class InitListChecker {
+ Sema &SemaRef;
+ bool hadError;
+ std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
+ InitListExpr *FullyStructuredList;
+
+ void CheckImplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *ParentIList, QualType T,
+ unsigned &Index, InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
+ void CheckExplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &T,
+ unsigned &Index, InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
+ void CheckListElementTypes(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
+ bool SubobjectIsDesignatorContext,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
+ void CheckSubElementType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType ElemType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
+ void CheckScalarType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
+ void CheckReferenceType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
+ void CheckVectorType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType, unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
+ void CheckStructUnionTypes(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ RecordDecl::field_iterator Field,
+ bool SubobjectIsDesignatorContext, unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
+ void CheckArrayType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
+ llvm::APSInt elementIndex,
+ bool SubobjectIsDesignatorContext, unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
+ bool CheckDesignatedInitializer(const InitializedEntity &Entity,
+ InitListExpr *IList, DesignatedInitExpr *DIE,
+ unsigned DesigIdx,
+ QualType &CurrentObjectType,
+ RecordDecl::field_iterator *NextField,
+ llvm::APSInt *NextElementIndex,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool FinishSubobjectInit,
+ bool TopLevelObject);
+ InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+ QualType CurrentObjectType,
+ InitListExpr *StructuredList,
+ unsigned StructuredIndex,
+ SourceRange InitRange);
+ void UpdateStructuredListElement(InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ Expr *expr);
+ int numArrayElements(QualType DeclType);
+ int numStructUnionElements(QualType DeclType);
+
+ void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE, bool &RequiresSecondPass);
+ void FillInValueInitializations(const InitializedEntity &Entity,
+ InitListExpr *ILE, bool &RequiresSecondPass);
+public:
+ InitListChecker(Sema &S, const InitializedEntity &Entity,
+ InitListExpr *IL, QualType &T);
+ bool HadError() { return hadError; }
+
+ // @brief Retrieves the fully-structured initializer list used for
+ // semantic analysis and code generation.
+ InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
+};
+} // end anonymous namespace
+
+void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+ const InitializedEntity &ParentEntity,
+ InitListExpr *ILE,
+ bool &RequiresSecondPass) {
+ SourceLocation Loc = ILE->getSourceRange().getBegin();
+ unsigned NumInits = ILE->getNumInits();
+ InitializedEntity MemberEntity
+ = InitializedEntity::InitializeMember(Field, &ParentEntity);
+ if (Init >= NumInits || !ILE->getInit(Init)) {
+ // FIXME: We probably don't need to handle references
+ // specially here, since value-initialization of references is
+ // handled in InitializationSequence.
+ if (Field->getType()->isReferenceType()) {
+ // C++ [dcl.init.aggr]p9:
+ // If an incomplete or empty initializer-list leaves a
+ // member of reference type uninitialized, the program is
+ // ill-formed.
+ SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
+ << Field->getType()
+ << ILE->getSyntacticForm()->getSourceRange();
+ SemaRef.Diag(Field->getLocation(),
+ diag::note_uninit_reference_member);
+ hadError = true;
+ return;
+ }
+
+ InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+ true);
+ InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
+ if (!InitSeq) {
+ InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
+ hadError = true;
+ return;
+ }
+
+ ExprResult MemberInit
+ = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg());
+ if (MemberInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ if (hadError) {
+ // Do nothing
+ } else if (Init < NumInits) {
+ ILE->setInit(Init, MemberInit.takeAs<Expr>());
+ } else if (InitSeq.getKind()
+ == InitializationSequence::ConstructorInitialization) {
+ // Value-initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs<Expr>());
+ RequiresSecondPass = true;
+ }
+ } else if (InitListExpr *InnerILE
+ = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+ FillInValueInitializations(MemberEntity, InnerILE,
+ RequiresSecondPass);
+}
+
+/// Recursively replaces NULL values within the given initializer list
+/// with expressions that perform value-initialization of the
+/// appropriate type.
+void
+InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+ InitListExpr *ILE,
+ bool &RequiresSecondPass) {
+ assert((ILE->getType() != SemaRef.Context.VoidTy) &&
+ "Should not have void type");
+ SourceLocation Loc = ILE->getSourceRange().getBegin();
+ if (ILE->getSyntacticForm())
+ Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
+
+ if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
+ if (RType->getDecl()->isUnion() &&
+ ILE->getInitializedFieldInUnion())
+ FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+ Entity, ILE, RequiresSecondPass);
+ else {
+ unsigned Init = 0;
+ for (RecordDecl::field_iterator
+ Field = RType->getDecl()->field_begin(),
+ FieldEnd = RType->getDecl()->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ if (hadError)
+ return;
+
+ FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
+ if (hadError)
+ return;
+
+ ++Init;
+
+ // Only look at the first initialization of a union.
+ if (RType->getDecl()->isUnion())
+ break;
+ }
+ }
+
+ return;
+ }
+
+ QualType ElementType;
+
+ InitializedEntity ElementEntity = Entity;
+ unsigned NumInits = ILE->getNumInits();
+ unsigned NumElements = NumInits;
+ if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
+ ElementType = AType->getElementType();
+ if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
+ NumElements = CAType->getSize().getZExtValue();
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ 0, Entity);
+ } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
+ ElementType = VType->getElementType();
+ NumElements = VType->getNumElements();
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ 0, Entity);
+ } else
+ ElementType = ILE->getType();
+
+
+ for (unsigned Init = 0; Init != NumElements; ++Init) {
+ if (hadError)
+ return;
+
+ if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
+ ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
+ ElementEntity.setElementIndex(Init);
+
+ if (Init >= NumInits || !ILE->getInit(Init)) {
+ InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
+ true);
+ InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0);
+ if (!InitSeq) {
+ InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0);
+ hadError = true;
+ return;
+ }
+
+ ExprResult ElementInit
+ = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg());
+ if (ElementInit.isInvalid()) {
+ hadError = true;
+ return;
+ }
+
+ if (hadError) {
+ // Do nothing
+ } else if (Init < NumInits) {
+ ILE->setInit(Init, ElementInit.takeAs<Expr>());
+ } else if (InitSeq.getKind()
+ == InitializationSequence::ConstructorInitialization) {
+ // Value-initialization requires a constructor call, so
+ // extend the initializer list to include the constructor
+ // call and make a note that we'll need to take another pass
+ // through the initializer list.
+ ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
+ RequiresSecondPass = true;
+ }
+ } else if (InitListExpr *InnerILE
+ = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+ FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+ }
+}
+
+
+InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
+ InitListExpr *IL, QualType &T)
+ : SemaRef(S) {
+ hadError = false;
+
+ unsigned newIndex = 0;
+ unsigned newStructuredIndex = 0;
+ FullyStructuredList
+ = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
+ CheckExplicitInitList(Entity, IL, T, newIndex,
+ FullyStructuredList, newStructuredIndex,
+ /*TopLevelObject=*/true);
+
+ if (!hadError) {
+ bool RequiresSecondPass = false;
+ FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+ if (RequiresSecondPass && !hadError)
+ FillInValueInitializations(Entity, FullyStructuredList,
+ RequiresSecondPass);
+ }
+}
+
+int InitListChecker::numArrayElements(QualType DeclType) {
+ // FIXME: use a proper constant
+ int maxElements = 0x7FFFFFFF;
+ if (const ConstantArrayType *CAT =
+ SemaRef.Context.getAsConstantArrayType(DeclType)) {
+ maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+ }
+ return maxElements;
+}
+
+int InitListChecker::numStructUnionElements(QualType DeclType) {
+ RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
+ int InitializableMembers = 0;
+ for (RecordDecl::field_iterator
+ Field = structDecl->field_begin(),
+ FieldEnd = structDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ if ((*Field)->getIdentifier() || !(*Field)->isBitField())
+ ++InitializableMembers;
+ }
+ if (structDecl->isUnion())
+ return std::min(InitializableMembers, 1);
+ return InitializableMembers - structDecl->hasFlexibleArrayMember();
+}
+
+void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *ParentIList,
+ QualType T, unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
+ int maxElements = 0;
+
+ if (T->isArrayType())
+ maxElements = numArrayElements(T);
+ else if (T->isRecordType())
+ maxElements = numStructUnionElements(T);
+ else if (T->isVectorType())
+ maxElements = T->getAs<VectorType>()->getNumElements();
+ else
+ assert(0 && "CheckImplicitInitList(): Illegal type");
+
+ if (maxElements == 0) {
+ SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
+ diag::err_implicit_empty_initializer);
+ ++Index;
+ hadError = true;
+ return;
+ }
+
+ // Build a structured initializer list corresponding to this subobject.
+ InitListExpr *StructuredSubobjectInitList
+ = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
+ StructuredIndex,
+ SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(),
+ ParentIList->getSourceRange().getEnd()));
+ unsigned StructuredSubobjectInitIndex = 0;
+
+ // Check the element types and build the structural subobject.
+ unsigned StartIndex = Index;
+ CheckListElementTypes(Entity, ParentIList, T,
+ /*SubobjectIsDesignatorContext=*/false, Index,
+ StructuredSubobjectInitList,
+ StructuredSubobjectInitIndex,
+ TopLevelObject);
+ unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
+ StructuredSubobjectInitList->setType(T);
+
+ // Update the structured sub-object initializer so that it's ending
+ // range corresponds with the end of the last initializer it used.
+ if (EndIndex < ParentIList->getNumInits()) {
+ SourceLocation EndLoc
+ = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
+ StructuredSubobjectInitList->setRBraceLoc(EndLoc);
+ }
+
+ // Warn about missing braces.
+ if (T->isArrayType() || T->isRecordType()) {
+ SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
+ diag::warn_missing_braces)
+ << StructuredSubobjectInitList->getSourceRange()
+ << FixItHint::CreateInsertion(StructuredSubobjectInitList->getLocStart(),
+ "{")
+ << FixItHint::CreateInsertion(SemaRef.PP.getLocForEndOfToken(
+ StructuredSubobjectInitList->getLocEnd()),
+ "}");
+ }
+}
+
+void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &T,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
+ assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
+ SyntacticToSemantic[IList] = StructuredList;
+ StructuredList->setSyntacticForm(IList);
+ CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
+ Index, StructuredList, StructuredIndex, TopLevelObject);
+ QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
+ IList->setType(ExprTy);
+ StructuredList->setType(ExprTy);
+ if (hadError)
+ return;
+
+ if (Index < IList->getNumInits()) {
+ // We have leftover initializers
+ if (StructuredIndex == 1 &&
+ IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
+ unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ DK = diag::err_excess_initializers_in_char_array_initializer;
+ hadError = true;
+ }
+ // Special-case
+ SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+ << IList->getInit(Index)->getSourceRange();
+ } else if (!T->isIncompleteType()) {
+ // Don't complain for incomplete types, since we'll get an error
+ // elsewhere
+ QualType CurrentObjectType = StructuredList->getType();
+ int initKind =
+ CurrentObjectType->isArrayType()? 0 :
+ CurrentObjectType->isVectorType()? 1 :
+ CurrentObjectType->isScalarType()? 2 :
+ CurrentObjectType->isUnionType()? 3 :
+ 4;
+
+ unsigned DK = diag::warn_excess_initializers;
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ DK = diag::err_excess_initializers;
+ hadError = true;
+ }
+ if (SemaRef.getLangOptions().OpenCL && initKind == 1) {
+ DK = diag::err_excess_initializers;
+ hadError = true;
+ }
+
+ SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
+ << initKind << IList->getInit(Index)->getSourceRange();
+ }
+ }
+
+ if (T->isScalarType() && !TopLevelObject)
+ SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
+ << IList->getSourceRange()
+ << FixItHint::CreateRemoval(IList->getLocStart())
+ << FixItHint::CreateRemoval(IList->getLocEnd());
+}
+
+void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
+ InitListExpr *IList,
+ QualType &DeclType,
+ bool SubobjectIsDesignatorContext,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
+ if (DeclType->isScalarType()) {
+ CheckScalarType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
+ } else if (DeclType->isVectorType()) {
+ CheckVectorType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
+ } else if (DeclType->isAggregateType()) {
+ if (DeclType->isRecordType()) {
+ RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+ CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
+ SubobjectIsDesignatorContext, Index,
+ StructuredList, StructuredIndex,
+ TopLevelObject);
+ } else if (DeclType->isArrayType()) {
+ llvm::APSInt Zero(
+ SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
+ false);
+ CheckArrayType(Entity, IList, DeclType, Zero,
+ SubobjectIsDesignatorContext, Index,
+ StructuredList, StructuredIndex);
+ } else
+ assert(0 && "Aggregate that isn't a structure or array?!");
+ } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
+ // This type is invalid, issue a diagnostic.
+ ++Index;
+ SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+ << DeclType;
+ hadError = true;
+ } else if (DeclType->isRecordType()) {
+ // C++ [dcl.init]p14:
+ // [...] If the class is an aggregate (8.5.1), and the initializer
+ // is a brace-enclosed list, see 8.5.1.
+ //
+ // Note: 8.5.1 is handled below; here, we diagnose the case where
+ // we have an initializer list and a destination type that is not
+ // an aggregate.
+ // FIXME: In C++0x, this is yet another form of initialization.
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+ << DeclType << IList->getSourceRange();
+ hadError = true;
+ } else if (DeclType->isReferenceType()) {
+ CheckReferenceType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
+ } else if (DeclType->isObjCObjectType()) {
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
+ << DeclType;
+ hadError = true;
+ } else {
+ SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+ << DeclType;
+ hadError = true;
+ }
+}
+
+void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
+ InitListExpr *IList,
+ QualType ElemType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ Expr *expr = IList->getInit(Index);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newIndex = 0;
+ unsigned newStructuredIndex = 0;
+ InitListExpr *newStructuredList
+ = getStructuredSubobjectInit(IList, Index, ElemType,
+ StructuredList, StructuredIndex,
+ SubInitList->getSourceRange());
+ CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
+ newStructuredList, newStructuredIndex);
+ ++StructuredIndex;
+ ++Index;
+ } else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
+ CheckStringInit(Str, ElemType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ ++Index;
+ } else if (ElemType->isScalarType()) {
+ CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ } else if (ElemType->isReferenceType()) {
+ CheckReferenceType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ } else {
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ // C++ [dcl.init.aggr]p12:
+ // All implicit type conversions (clause 4) are considered when
+ // initializing the aggregate member with an ini- tializer from
+ // an initializer-list. If the initializer can initialize a
+ // member, the member is initialized. [...]
+
+ // FIXME: Better EqualLoc?
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+ InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+
+ if (Seq) {
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+ if (Result.isInvalid())
+ hadError = true;
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ Result.takeAs<Expr>());
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization
+ } else {
+ // C99 6.7.8p13:
+ //
+ // The initializer for a structure or union object that has
+ // automatic storage duration shall be either an initializer
+ // list as described below, or a single expression that has
+ // compatible structure or union type. In the latter case, the
+ // initial value of the object, including unnamed members, is
+ // that of the expression.
+ if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
+ == Sema::Compatible) {
+ SemaRef.DefaultFunctionArrayLvalueConversion(expr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization
+ }
+
+ // C++ [dcl.init.aggr]p12:
+ //
+ // [...] Otherwise, if the member is itself a non-empty
+ // subaggregate, brace elision is assumed and the initializer is
+ // considered for the initialization of the first member of
+ // the subaggregate.
+ if (ElemType->isAggregateType() || ElemType->isVectorType()) {
+ CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
+ StructuredIndex);
+ ++StructuredIndex;
+ } else {
+ // We cannot initialize this element, so let
+ // PerformCopyInitialization produce the appropriate diagnostic.
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.Owned(expr));
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ }
+ }
+}
+
+void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ if (Index >= IList->getNumInits()) {
+ SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
+ << IList->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ Expr *expr = IList->getInit(Index);
+ if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
+ SemaRef.Diag(SubIList->getLocStart(),
+ diag::warn_many_braces_around_scalar_init)
+ << SubIList->getSourceRange();
+
+ CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
+ StructuredIndex);
+ return;
+ } else if (isa<DesignatedInitExpr>(expr)) {
+ SemaRef.Diag(expr->getSourceRange().getBegin(),
+ diag::err_designator_for_scalar_init)
+ << DeclType << expr->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr));
+
+ Expr *ResultExpr = 0;
+
+ if (Result.isInvalid())
+ hadError = true; // types weren't compatible.
+ else {
+ ResultExpr = Result.takeAs<Expr>();
+
+ if (ResultExpr != expr) {
+ // The type was promoted, update initializer list.
+ IList->setInit(Index, ResultExpr);
+ }
+ }
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ ++Index;
+}
+
+void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ if (Index < IList->getNumInits()) {
+ Expr *expr = IList->getInit(Index);
+ if (isa<InitListExpr>(expr)) {
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+ << DeclType << IList->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr));
+
+ if (Result.isInvalid())
+ hadError = true;
+
+ expr = Result.takeAs<Expr>();
+ IList->setInit(Index, expr);
+
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ ++Index;
+ } else {
+ // FIXME: It would be wonderful if we could point at the actual member. In
+ // general, it would be useful to pass location information down the stack,
+ // so that we know the location (or decl) of the "current object" being
+ // initialized.
+ SemaRef.Diag(IList->getLocStart(),
+ diag::err_init_reference_member_uninitialized)
+ << DeclType
+ << IList->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+}
+
+void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ if (Index >= IList->getNumInits())
+ return;
+
+ const VectorType *VT = DeclType->getAs<VectorType>();
+ unsigned maxElements = VT->getNumElements();
+ unsigned numEltsInit = 0;
+ QualType elementType = VT->getElementType();
+
+ if (!SemaRef.getLangOptions().OpenCL) {
+ // If the initializing element is a vector, try to copy-initialize
+ // instead of breaking it apart (which is doomed to failure anyway).
+ Expr *Init = IList->getInit(Index);
+ if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
+ SemaRef.Owned(Init));
+
+ Expr *ResultExpr = 0;
+ if (Result.isInvalid())
+ hadError = true; // types weren't compatible.
+ else {
+ ResultExpr = Result.takeAs<Expr>();
+
+ if (ResultExpr != Init) {
+ // The type was promoted, update initializer list.
+ IList->setInit(Index, ResultExpr);
+ }
+ }
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ ++Index;
+ return;
+ }
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
+ // Don't attempt to go past the end of the init list
+ if (Index >= IList->getNumInits())
+ break;
+
+ ElementEntity.setElementIndex(Index);
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ }
+ return;
+ }
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ // OpenCL initializers allows vectors to be constructed from vectors.
+ for (unsigned i = 0; i < maxElements; ++i) {
+ // Don't attempt to go past the end of the init list
+ if (Index >= IList->getNumInits())
+ break;
+
+ ElementEntity.setElementIndex(Index);
+
+ QualType IType = IList->getInit(Index)->getType();
+ if (!IType->isVectorType()) {
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ ++numEltsInit;
+ } else {
+ QualType VecType;
+ const VectorType *IVT = IType->getAs<VectorType>();
+ unsigned numIElts = IVT->getNumElements();
+
+ if (IType->isExtVectorType())
+ VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
+ else
+ VecType = SemaRef.Context.getVectorType(elementType, numIElts,
+ IVT->getVectorKind());
+ CheckSubElementType(ElementEntity, IList, VecType, Index,
+ StructuredList, StructuredIndex);
+ numEltsInit += numIElts;
+ }
+ }
+
+ // OpenCL requires all elements to be initialized.
+ if (numEltsInit != maxElements)
+ if (SemaRef.getLangOptions().OpenCL)
+ SemaRef.Diag(IList->getSourceRange().getBegin(),
+ diag::err_vector_incorrect_num_initializers)
+ << (numEltsInit < maxElements) << maxElements << numEltsInit;
+}
+
+void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
+ llvm::APSInt elementIndex,
+ bool SubobjectIsDesignatorContext,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ // Check for the special-case of initializing an array with a string.
+ if (Index < IList->getNumInits()) {
+ if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
+ SemaRef.Context)) {
+ CheckStringInit(Str, DeclType, SemaRef);
+ // We place the string literal directly into the resulting
+ // initializer list. This is the only place where the structure
+ // of the structured initializer list doesn't match exactly,
+ // because doing so would involve allocating one character
+ // constant for each string.
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
+ ++Index;
+ return;
+ }
+ }
+ if (const VariableArrayType *VAT =
+ SemaRef.Context.getAsVariableArrayType(DeclType)) {
+ // Check for VLAs; in standard C it would be possible to check this
+ // earlier, but I don't know where clang accepts VLAs (gcc accepts
+ // them in all sorts of strange places).
+ SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
+ diag::err_variable_object_no_init)
+ << VAT->getSizeExpr()->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ // We might know the maximum number of elements in advance.
+ llvm::APSInt maxElements(elementIndex.getBitWidth(),
+ elementIndex.isUnsigned());
+ bool maxElementsKnown = false;
+ if (const ConstantArrayType *CAT =
+ SemaRef.Context.getAsConstantArrayType(DeclType)) {
+ maxElements = CAT->getSize();
+ elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
+ elementIndex.setIsUnsigned(maxElements.isUnsigned());
+ maxElementsKnown = true;
+ }
+
+ QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
+ ->getElementType();
+ while (Index < IList->getNumInits()) {
+ Expr *Init = IList->getInit(Index);
+ if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+ // If we're not the subobject that matches up with the '{' for
+ // the designator, we shouldn't be handling the
+ // designator. Return immediately.
+ if (!SubobjectIsDesignatorContext)
+ return;
+
+ // Handle this designated initializer. elementIndex will be
+ // updated to be the next array element we'll initialize.
+ if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+ DeclType, 0, &elementIndex, Index,
+ StructuredList, StructuredIndex, true,
+ false)) {
+ hadError = true;
+ continue;
+ }
+
+ if (elementIndex.getBitWidth() > maxElements.getBitWidth())
+ maxElements = maxElements.extend(elementIndex.getBitWidth());
+ else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
+ elementIndex = elementIndex.extend(maxElements.getBitWidth());
+ elementIndex.setIsUnsigned(maxElements.isUnsigned());
+
+ // If the array is of incomplete type, keep track of the number of
+ // elements in the initializer.
+ if (!maxElementsKnown && elementIndex > maxElements)
+ maxElements = elementIndex;
+
+ continue;
+ }
+
+ // If we know the maximum number of elements, and we've already
+ // hit it, stop consuming elements in the initializer list.
+ if (maxElementsKnown && elementIndex == maxElements)
+ break;
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
+ Entity);
+ // Check this element.
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ ++elementIndex;
+
+ // If the array is of incomplete type, keep track of the number of
+ // elements in the initializer.
+ if (!maxElementsKnown && elementIndex > maxElements)
+ maxElements = elementIndex;
+ }
+ if (!hadError && DeclType->isIncompleteArrayType()) {
+ // If this is an incomplete array type, the actual type needs to
+ // be calculated here.
+ llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
+ if (maxElements == Zero) {
+ // Sizing an array implicitly to zero is not allowed by ISO C,
+ // but is supported by GNU.
+ SemaRef.Diag(IList->getLocStart(),
+ diag::ext_typecheck_zero_array_size);
+ }
+
+ DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
+ ArrayType::Normal, 0);
+ }
+}
+
+void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
+ InitListExpr *IList,
+ QualType DeclType,
+ RecordDecl::field_iterator Field,
+ bool SubobjectIsDesignatorContext,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
+ RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
+
+ // If the record is invalid, some of it's members are invalid. To avoid
+ // confusion, we forgo checking the intializer for the entire record.
+ if (structDecl->isInvalidDecl()) {
+ hadError = true;
+ return;
+ }
+
+ if (DeclType->isUnionType() && IList->getNumInits() == 0) {
+ // Value-initialize the first named member of the union.
+ RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+ for (RecordDecl::field_iterator FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Field->getDeclName()) {
+ StructuredList->setInitializedFieldInUnion(*Field);
+ break;
+ }
+ }
+ return;
+ }
+
+ // If structDecl is a forward declaration, this loop won't do
+ // anything except look at designated initializers; That's okay,
+ // because an error should get printed out elsewhere. It might be
+ // worthwhile to skip over the rest of the initializer, though.
+ RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+ RecordDecl::field_iterator FieldEnd = RD->field_end();
+ bool InitializedSomething = false;
+ bool CheckForMissingFields = true;
+ while (Index < IList->getNumInits()) {
+ Expr *Init = IList->getInit(Index);
+
+ if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
+ // If we're not the subobject that matches up with the '{' for
+ // the designator, we shouldn't be handling the
+ // designator. Return immediately.
+ if (!SubobjectIsDesignatorContext)
+ return;
+
+ // Handle this designated initializer. Field will be updated to
+ // the next field that we'll be initializing.
+ if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
+ DeclType, &Field, 0, Index,
+ StructuredList, StructuredIndex,
+ true, TopLevelObject))
+ hadError = true;
+
+ InitializedSomething = true;
+
+ // Disable check for missing fields when designators are used.
+ // This matches gcc behaviour.
+ CheckForMissingFields = false;
+ continue;
+ }
+
+ if (Field == FieldEnd) {
+ // We've run out of fields. We're done.
+ break;
+ }
+
+ // We've already initialized a member of a union. We're done.
+ if (InitializedSomething && DeclType->isUnionType())
+ break;
+
+ // If we've hit the flexible array member at the end, we're done.
+ if (Field->getType()->isIncompleteArrayType())
+ break;
+
+ if (Field->isUnnamedBitfield()) {
+ // Don't initialize unnamed bitfields, e.g. "int : 20;"
+ ++Field;
+ continue;
+ }
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, StructuredIndex);
+ InitializedSomething = true;
+
+ if (DeclType->isUnionType()) {
+ // Initialize the first field within the union.
+ StructuredList->setInitializedFieldInUnion(*Field);
+ }
+
+ ++Field;
+ }
+
+ // Emit warnings for missing struct field initializers.
+ if (InitializedSomething && CheckForMissingFields && Field != FieldEnd &&
+ !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) {
+ // It is possible we have one or more unnamed bitfields remaining.
+ // Find first (if any) named field and emit warning.
+ for (RecordDecl::field_iterator it = Field, end = RD->field_end();
+ it != end; ++it) {
+ if (!it->isUnnamedBitfield()) {
+ SemaRef.Diag(IList->getSourceRange().getEnd(),
+ diag::warn_missing_field_initializers) << it->getName();
+ break;
+ }
+ }
+ }
+
+ if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
+ Index >= IList->getNumInits())
+ return;
+
+ // Handle GNU flexible array initializers.
+ if (!TopLevelObject &&
+ (!isa<InitListExpr>(IList->getInit(Index)) ||
+ cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) {
+ SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
+ diag::err_flexible_array_init_nonempty)
+ << IList->getInit(Index)->getSourceRange().getBegin();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ hadError = true;
+ ++Index;
+ return;
+ } else {
+ SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
+ diag::ext_flexible_array_init)
+ << IList->getInit(Index)->getSourceRange().getBegin();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ }
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+
+ if (isa<InitListExpr>(IList->getInit(Index)))
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, StructuredIndex);
+ else
+ CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, StructuredIndex);
+}
+
+/// \brief Expand a field designator that refers to a member of an
+/// anonymous struct or union into a series of field designators that
+/// refers to the field within the appropriate subobject.
+///
+static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
+ DesignatedInitExpr *DIE,
+ unsigned DesigIdx,
+ IndirectFieldDecl *IndirectField) {
+ typedef DesignatedInitExpr::Designator Designator;
+
+ // Build the replacement designators.
+ llvm::SmallVector<Designator, 4> Replacements;
+ for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
+ PE = IndirectField->chain_end(); PI != PE; ++PI) {
+ if (PI + 1 == PE)
+ Replacements.push_back(Designator((IdentifierInfo *)0,
+ DIE->getDesignator(DesigIdx)->getDotLoc(),
+ DIE->getDesignator(DesigIdx)->getFieldLoc()));
+ else
+ Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
+ SourceLocation()));
+ assert(isa<FieldDecl>(*PI));
+ Replacements.back().setField(cast<FieldDecl>(*PI));
+ }
+
+ // Expand the current designator into the set of replacement
+ // designators, so we have a full subobject path down to where the
+ // member of the anonymous struct/union is actually stored.
+ DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
+ &Replacements[0] + Replacements.size());
+}
+
+/// \brief Given an implicit anonymous field, search the IndirectField that
+/// corresponds to FieldName.
+static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
+ IdentifierInfo *FieldName) {
+ assert(AnonField->isAnonymousStructOrUnion());
+ Decl *NextDecl = AnonField->getNextDeclInContext();
+ while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) {
+ if (FieldName && FieldName == IF->getAnonField()->getIdentifier())
+ return IF;
+ NextDecl = NextDecl->getNextDeclInContext();
+ }
+ return 0;
+}
+
+/// @brief Check the well-formedness of a C99 designated initializer.
+///
+/// Determines whether the designated initializer @p DIE, which
+/// resides at the given @p Index within the initializer list @p
+/// IList, is well-formed for a current object of type @p DeclType
+/// (C99 6.7.8). The actual subobject that this designator refers to
+/// within the current subobject is returned in either
+/// @p NextField or @p NextElementIndex (whichever is appropriate).
+///
+/// @param IList The initializer list in which this designated
+/// initializer occurs.
+///
+/// @param DIE The designated initializer expression.
+///
+/// @param DesigIdx The index of the current designator.
+///
+/// @param DeclType The type of the "current object" (C99 6.7.8p17),
+/// into which the designation in @p DIE should refer.
+///
+/// @param NextField If non-NULL and the first designator in @p DIE is
+/// a field, this will be set to the field declaration corresponding
+/// to the field named by the designator.
+///
+/// @param NextElementIndex If non-NULL and the first designator in @p
+/// DIE is an array designator or GNU array-range designator, this
+/// will be set to the last index initialized by this designator.
+///
+/// @param Index Index into @p IList where the designated initializer
+/// @p DIE occurs.
+///
+/// @param StructuredList The initializer list expression that
+/// describes all of the subobject initializers in the order they'll
+/// actually be initialized.
+///
+/// @returns true if there was an error, false otherwise.
+bool
+InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
+ InitListExpr *IList,
+ DesignatedInitExpr *DIE,
+ unsigned DesigIdx,
+ QualType &CurrentObjectType,
+ RecordDecl::field_iterator *NextField,
+ llvm::APSInt *NextElementIndex,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ bool FinishSubobjectInit,
+ bool TopLevelObject) {
+ if (DesigIdx == DIE->size()) {
+ // Check the actual initialization for the designated object type.
+ bool prevHadError = hadError;
+
+ // Temporarily remove the designator expression from the
+ // initializer list that the child calls see, so that we don't try
+ // to re-process the designator.
+ unsigned OldIndex = Index;
+ IList->setInit(OldIndex, DIE->getInit());
+
+ CheckSubElementType(Entity, IList, CurrentObjectType, Index,
+ StructuredList, StructuredIndex);
+
+ // Restore the designated initializer expression in the syntactic
+ // form of the initializer list.
+ if (IList->getInit(OldIndex) != DIE->getInit())
+ DIE->setInit(IList->getInit(OldIndex));
+ IList->setInit(OldIndex, DIE);
+
+ return hadError && !prevHadError;
+ }
+
+ bool IsFirstDesignator = (DesigIdx == 0);
+ assert((IsFirstDesignator || StructuredList) &&
+ "Need a non-designated initializer list to start from");
+
+ DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
+ // Determine the structural initializer list that corresponds to the
+ // current subobject.
+ StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
+ : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+ StructuredList, StructuredIndex,
+ SourceRange(D->getStartLocation(),
+ DIE->getSourceRange().getEnd()));
+ assert(StructuredList && "Expected a structured initializer list");
+
+ if (D->isFieldDesignator()) {
+ // C99 6.7.8p7:
+ //
+ // If a designator has the form
+ //
+ // . identifier
+ //
+ // then the current object (defined below) shall have
+ // structure or union type and the identifier shall be the
+ // name of a member of that type.
+ const RecordType *RT = CurrentObjectType->getAs<RecordType>();
+ if (!RT) {
+ SourceLocation Loc = D->getDotLoc();
+ if (Loc.isInvalid())
+ Loc = D->getFieldLoc();
+ SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
+ << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
+ ++Index;
+ return true;
+ }
+
+ // Note: we perform a linear search of the fields here, despite
+ // the fact that we have a faster lookup method, because we always
+ // need to compute the field's index.
+ FieldDecl *KnownField = D->getField();
+ IdentifierInfo *FieldName = D->getFieldName();
+ unsigned FieldIndex = 0;
+ RecordDecl::field_iterator
+ Field = RT->getDecl()->field_begin(),
+ FieldEnd = RT->getDecl()->field_end();
+ for (; Field != FieldEnd; ++Field) {
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ // If we find a field representing an anonymous field, look in the
+ // IndirectFieldDecl that follow for the designated initializer.
+ if (!KnownField && Field->isAnonymousStructOrUnion()) {
+ if (IndirectFieldDecl *IF =
+ FindIndirectFieldDesignator(*Field, FieldName)) {
+ ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
+ D = DIE->getDesignator(DesigIdx);
+ break;
+ }
+ }
+ if (KnownField && KnownField == *Field)
+ break;
+ if (FieldName && FieldName == Field->getIdentifier())
+ break;
+
+ ++FieldIndex;
+ }
+
+ if (Field == FieldEnd) {
+ // There was no normal field in the struct with the designated
+ // name. Perform another lookup for this name, which may find
+ // something that we can't designate (e.g., a member function),
+ // may find nothing, or may find a member of an anonymous
+ // struct/union.
+ DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+ FieldDecl *ReplacementField = 0;
+ if (Lookup.first == Lookup.second) {
+ // Name lookup didn't find anything. Determine whether this
+ // was a typo for another field name.
+ LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
+ Sema::LookupMemberName);
+ if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
+ Sema::CTC_NoKeywords) &&
+ (ReplacementField = R.getAsSingle<FieldDecl>()) &&
+ ReplacementField->getDeclContext()->getRedeclContext()
+ ->Equals(RT->getDecl())) {
+ SemaRef.Diag(D->getFieldLoc(),
+ diag::err_field_designator_unknown_suggest)
+ << FieldName << CurrentObjectType << R.getLookupName()
+ << FixItHint::CreateReplacement(D->getFieldLoc(),
+ R.getLookupName().getAsString());
+ SemaRef.Diag(ReplacementField->getLocation(),
+ diag::note_previous_decl)
+ << ReplacementField->getDeclName();
+ } else {
+ SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
+ << FieldName << CurrentObjectType;
+ ++Index;
+ return true;
+ }
+ }
+
+ if (!ReplacementField) {
+ // Name lookup found something, but it wasn't a field.
+ SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
+ << FieldName;
+ SemaRef.Diag((*Lookup.first)->getLocation(),
+ diag::note_field_designator_found);
+ ++Index;
+ return true;
+ }
+
+ if (!KnownField) {
+ // The replacement field comes from typo correction; find it
+ // in the list of fields.
+ FieldIndex = 0;
+ Field = RT->getDecl()->field_begin();
+ for (; Field != FieldEnd; ++Field) {
+ if (Field->isUnnamedBitfield())
+ continue;
+
+ if (ReplacementField == *Field ||
+ Field->getIdentifier() == ReplacementField->getIdentifier())
+ break;
+
+ ++FieldIndex;
+ }
+ }
+ }
+
+ // All of the fields of a union are located at the same place in
+ // the initializer list.
+ if (RT->getDecl()->isUnion()) {
+ FieldIndex = 0;
+ StructuredList->setInitializedFieldInUnion(*Field);
+ }
+
+ // Update the designator with the field declaration.
+ D->setField(*Field);
+
+ // Make sure that our non-designated initializer list has space
+ // for a subobject corresponding to this field.
+ if (FieldIndex >= StructuredList->getNumInits())
+ StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
+
+ // This designator names a flexible array member.
+ if (Field->getType()->isIncompleteArrayType()) {
+ bool Invalid = false;
+ if ((DesigIdx + 1) != DIE->size()) {
+ // We can't designate an object within the flexible array
+ // member (because GCC doesn't allow it).
+ DesignatedInitExpr::Designator *NextD
+ = DIE->getDesignator(DesigIdx + 1);
+ SemaRef.Diag(NextD->getStartLocation(),
+ diag::err_designator_into_flexible_array_member)
+ << SourceRange(NextD->getStartLocation(),
+ DIE->getSourceRange().getEnd());
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ Invalid = true;
+ }
+
+ if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
+ !isa<StringLiteral>(DIE->getInit())) {
+ // The initializer is not an initializer list.
+ SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
+ diag::err_flexible_array_init_needs_braces)
+ << DIE->getInit()->getSourceRange();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ Invalid = true;
+ }
+
+ // Handle GNU flexible array initializers.
+ if (!Invalid && !TopLevelObject &&
+ cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) {
+ SemaRef.Diag(DIE->getSourceRange().getBegin(),
+ diag::err_flexible_array_init_nonempty)
+ << DIE->getSourceRange().getBegin();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ Invalid = true;
+ }
+
+ if (Invalid) {
+ ++Index;
+ return true;
+ }
+
+ // Initialize the array.
+ bool prevHadError = hadError;
+ unsigned newStructuredIndex = FieldIndex;
+ unsigned OldIndex = Index;
+ IList->setInit(Index, DIE->getInit());
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, newStructuredIndex);
+
+ IList->setInit(OldIndex, DIE);
+ if (hadError && !prevHadError) {
+ ++Field;
+ ++FieldIndex;
+ if (NextField)
+ *NextField = Field;
+ StructuredIndex = FieldIndex;
+ return true;
+ }
+ } else {
+ // Recurse to check later designated subobjects.
+ QualType FieldType = (*Field)->getType();
+ unsigned newStructuredIndex = FieldIndex;
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
+ FieldType, 0, 0, Index,
+ StructuredList, newStructuredIndex,
+ true, false))
+ return true;
+ }
+
+ // Find the position of the next field to be initialized in this
+ // subobject.
+ ++Field;
+ ++FieldIndex;
+
+ // If this the first designator, our caller will continue checking
+ // the rest of this struct/class/union subobject.
+ if (IsFirstDesignator) {
+ if (NextField)
+ *NextField = Field;
+ StructuredIndex = FieldIndex;
+ return false;
+ }
+
+ if (!FinishSubobjectInit)
+ return false;
+
+ // We've already initialized something in the union; we're done.
+ if (RT->getDecl()->isUnion())
+ return hadError;
+
+ // Check the remaining fields within this class/struct/union subobject.
+ bool prevHadError = hadError;
+
+ CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
+ StructuredList, FieldIndex);
+ return hadError && !prevHadError;
+ }
+
+ // C99 6.7.8p6:
+ //
+ // If a designator has the form
+ //
+ // [ constant-expression ]
+ //
+ // then the current object (defined below) shall have array
+ // type and the expression shall be an integer constant
+ // expression. If the array is of unknown size, any
+ // nonnegative value is valid.
+ //
+ // Additionally, cope with the GNU extension that permits
+ // designators of the form
+ //
+ // [ constant-expression ... constant-expression ]
+ const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
+ if (!AT) {
+ SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
+ << CurrentObjectType;
+ ++Index;
+ return true;
+ }
+
+ Expr *IndexExpr = 0;
+ llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
+ if (D->isArrayDesignator()) {
+ IndexExpr = DIE->getArrayIndex(*D);
+ DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context);
+ DesignatedEndIndex = DesignatedStartIndex;
+ } else {
+ assert(D->isArrayRangeDesignator() && "Need array-range designator");
+
+ DesignatedStartIndex =
+ DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context);
+ DesignatedEndIndex =
+ DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context);
+ IndexExpr = DIE->getArrayRangeEnd(*D);
+
+ // Codegen can't handle evaluating array range designators that have side
+ // effects, because we replicate the AST value for each initialized element.
+ // As such, set the sawArrayRangeDesignator() bit if we initialize multiple
+ // elements with something that has a side effect, so codegen can emit an
+ // "error unsupported" error instead of miscompiling the app.
+ if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&&
+ DIE->getInit()->HasSideEffects(SemaRef.Context))
+ FullyStructuredList->sawArrayRangeDesignator();
+ }
+
+ if (isa<ConstantArrayType>(AT)) {
+ llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
+ DesignatedStartIndex
+ = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
+ DesignatedEndIndex
+ = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
+ if (DesignatedEndIndex >= MaxElements) {
+ SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
+ diag::err_array_designator_too_large)
+ << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+ << IndexExpr->getSourceRange();
+ ++Index;
+ return true;
+ }
+ } else {
+ // Make sure the bit-widths and signedness match.
+ if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
+ DesignatedEndIndex
+ = DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+ else if (DesignatedStartIndex.getBitWidth() <
+ DesignatedEndIndex.getBitWidth())
+ DesignatedStartIndex
+ = DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+ DesignatedStartIndex.setIsUnsigned(true);
+ DesignatedEndIndex.setIsUnsigned(true);
+ }
+
+ // Make sure that our non-designated initializer list has space
+ // for a subobject corresponding to this array element.
+ if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+ StructuredList->resizeInits(SemaRef.Context,
+ DesignatedEndIndex.getZExtValue() + 1);
+
+ // Repeatedly perform subobject initializations in the range
+ // [DesignatedStartIndex, DesignatedEndIndex].
+
+ // Move to the next designator
+ unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
+ unsigned OldIndex = Index;
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ while (DesignatedStartIndex <= DesignatedEndIndex) {
+ // Recurse to check later designated subobjects.
+ QualType ElementType = AT->getElementType();
+ Index = OldIndex;
+
+ ElementEntity.setElementIndex(ElementIndex);
+ if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
+ ElementType, 0, 0, Index,
+ StructuredList, ElementIndex,
+ (DesignatedStartIndex == DesignatedEndIndex),
+ false))
+ return true;
+
+ // Move to the next index in the array that we'll be initializing.
+ ++DesignatedStartIndex;
+ ElementIndex = DesignatedStartIndex.getZExtValue();
+ }
+
+ // If this the first designator, our caller will continue checking
+ // the rest of this array subobject.
+ if (IsFirstDesignator) {
+ if (NextElementIndex)
+ *NextElementIndex = DesignatedStartIndex;
+ StructuredIndex = ElementIndex;
+ return false;
+ }
+
+ if (!FinishSubobjectInit)
+ return false;
+
+ // Check the remaining elements within this array subobject.
+ bool prevHadError = hadError;
+ CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
+ /*SubobjectIsDesignatorContext=*/false, Index,
+ StructuredList, ElementIndex);
+ return hadError && !prevHadError;
+}
+
+// Get the structured initializer list for a subobject of type
+// @p CurrentObjectType.
+InitListExpr *
+InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+ QualType CurrentObjectType,
+ InitListExpr *StructuredList,
+ unsigned StructuredIndex,
+ SourceRange InitRange) {
+ Expr *ExistingInit = 0;
+ if (!StructuredList)
+ ExistingInit = SyntacticToSemantic[IList];
+ else if (StructuredIndex < StructuredList->getNumInits())
+ ExistingInit = StructuredList->getInit(StructuredIndex);
+
+ if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
+ return Result;
+
+ if (ExistingInit) {
+ // We are creating an initializer list that initializes the
+ // subobjects of the current object, but there was already an
+ // initialization that completely initialized the current
+ // subobject, e.g., by a compound literal:
+ //
+ // struct X { int a, b; };
+ // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
+ //
+ // Here, xs[0].a == 0 and xs[0].b == 3, since the second,
+ // designated initializer re-initializes the whole
+ // subobject [0], overwriting previous initializers.
+ SemaRef.Diag(InitRange.getBegin(),
+ diag::warn_subobject_initializer_overrides)
+ << InitRange;
+ SemaRef.Diag(ExistingInit->getSourceRange().getBegin(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << ExistingInit->getSourceRange();
+ }
+
+ InitListExpr *Result
+ = new (SemaRef.Context) InitListExpr(SemaRef.Context,
+ InitRange.getBegin(), 0, 0,
+ InitRange.getEnd());
+
+ Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context));
+
+ // Pre-allocate storage for the structured initializer list.
+ unsigned NumElements = 0;
+ unsigned NumInits = 0;
+ if (!StructuredList)
+ NumInits = IList->getNumInits();
+ else if (Index < IList->getNumInits()) {
+ if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index)))
+ NumInits = SubList->getNumInits();
+ }
+
+ if (const ArrayType *AType
+ = SemaRef.Context.getAsArrayType(CurrentObjectType)) {
+ if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
+ NumElements = CAType->getSize().getZExtValue();
+ // Simple heuristic so that we don't allocate a very large
+ // initializer with many empty entries at the end.
+ if (NumInits && NumElements > NumInits)
+ NumElements = 0;
+ }
+ } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
+ NumElements = VType->getNumElements();
+ else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) {
+ RecordDecl *RDecl = RType->getDecl();
+ if (RDecl->isUnion())
+ NumElements = 1;
+ else
+ NumElements = std::distance(RDecl->field_begin(),
+ RDecl->field_end());
+ }
+
+ if (NumElements < NumInits)
+ NumElements = IList->getNumInits();
+
+ Result->reserveInits(SemaRef.Context, NumElements);
+
+ // Link this new initializer list into the structured initializer
+ // lists.
+ if (StructuredList)
+ StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result);
+ else {
+ Result->setSyntacticForm(IList);
+ SyntacticToSemantic[IList] = Result;
+ }
+
+ return Result;
+}
+
+/// Update the initializer at index @p StructuredIndex within the
+/// structured initializer list to the value @p expr.
+void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
+ Expr *expr) {
+ // No structured initializer list to update
+ if (!StructuredList)
+ return;
+
+ if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
+ StructuredIndex, expr)) {
+ // This initializer overwrites a previous initializer. Warn.
+ SemaRef.Diag(expr->getSourceRange().getBegin(),
+ diag::warn_initializer_overrides)
+ << expr->getSourceRange();
+ SemaRef.Diag(PrevInit->getSourceRange().getBegin(),
+ diag::note_previous_initializer)
+ << /*FIXME:has side effects=*/0
+ << PrevInit->getSourceRange();
+ }
+
+ ++StructuredIndex;
+}
+
+/// Check that the given Index expression is a valid array designator
+/// value. This is essentailly just a wrapper around
+/// VerifyIntegerConstantExpression that also checks for negative values
+/// and produces a reasonable diagnostic if there is a
+/// failure. Returns true if there was an error, false otherwise. If
+/// everything went okay, Value will receive the value of the constant
+/// expression.
+static bool
+CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
+ SourceLocation Loc = Index->getSourceRange().getBegin();
+
+ // Make sure this is an integer constant expression.
+ if (S.VerifyIntegerConstantExpression(Index, &Value))
+ return true;
+
+ if (Value.isSigned() && Value.isNegative())
+ return S.Diag(Loc, diag::err_array_designator_negative)
+ << Value.toString(10) << Index->getSourceRange();
+
+ Value.setIsUnsigned(true);
+ return false;
+}
+
+ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init) {
+ typedef DesignatedInitExpr::Designator ASTDesignator;
+
+ bool Invalid = false;
+ llvm::SmallVector<ASTDesignator, 32> Designators;
+ llvm::SmallVector<Expr *, 32> InitExpressions;
+
+ // Build designators and check array designator expressions.
+ for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
+ const Designator &D = Desig.getDesignator(Idx);
+ switch (D.getKind()) {
+ case Designator::FieldDesignator:
+ Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
+ D.getFieldLoc()));
+ break;
+
+ case Designator::ArrayDesignator: {
+ Expr *Index = static_cast<Expr *>(D.getArrayIndex());
+ llvm::APSInt IndexValue;
+ if (!Index->isTypeDependent() &&
+ !Index->isValueDependent() &&
+ CheckArrayDesignatorExpr(*this, Index, IndexValue))
+ Invalid = true;
+ else {
+ Designators.push_back(ASTDesignator(InitExpressions.size(),
+ D.getLBracketLoc(),
+ D.getRBracketLoc()));
+ InitExpressions.push_back(Index);
+ }
+ break;
+ }
+
+ case Designator::ArrayRangeDesignator: {
+ Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
+ Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
+ llvm::APSInt StartValue;
+ llvm::APSInt EndValue;
+ bool StartDependent = StartIndex->isTypeDependent() ||
+ StartIndex->isValueDependent();
+ bool EndDependent = EndIndex->isTypeDependent() ||
+ EndIndex->isValueDependent();
+ if ((!StartDependent &&
+ CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
+ (!EndDependent &&
+ CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
+ Invalid = true;
+ else {
+ // Make sure we're comparing values with the same bit width.
+ if (StartDependent || EndDependent) {
+ // Nothing to compute.
+ } else if (StartValue.getBitWidth() > EndValue.getBitWidth())
+ EndValue = EndValue.extend(StartValue.getBitWidth());
+ else if (StartValue.getBitWidth() < EndValue.getBitWidth())
+ StartValue = StartValue.extend(EndValue.getBitWidth());
+
+ if (!StartDependent && !EndDependent && EndValue < StartValue) {
+ Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
+ << StartValue.toString(10) << EndValue.toString(10)
+ << StartIndex->getSourceRange() << EndIndex->getSourceRange();
+ Invalid = true;
+ } else {
+ Designators.push_back(ASTDesignator(InitExpressions.size(),
+ D.getLBracketLoc(),
+ D.getEllipsisLoc(),
+ D.getRBracketLoc()));
+ InitExpressions.push_back(StartIndex);
+ InitExpressions.push_back(EndIndex);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (Invalid || Init.isInvalid())
+ return ExprError();
+
+ // Clear out the expressions within the designation.
+ Desig.ClearExprs(*this);
+
+ DesignatedInitExpr *DIE
+ = DesignatedInitExpr::Create(Context,
+ Designators.data(), Designators.size(),
+ InitExpressions.data(), InitExpressions.size(),
+ Loc, GNUSyntax, Init.takeAs<Expr>());
+
+ if (getLangOptions().CPlusPlus)
+ Diag(DIE->getLocStart(), diag::ext_designated_init)
+ << DIE->getSourceRange();
+
+ return Owned(DIE);
+}
+
+bool Sema::CheckInitList(const InitializedEntity &Entity,
+ InitListExpr *&InitList, QualType &DeclType) {
+ InitListChecker CheckInitList(*this, Entity, InitList, DeclType);
+ if (!CheckInitList.HadError())
+ InitList = CheckInitList.getFullyStructuredList();
+
+ return CheckInitList.HadError();
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization entity
+//===----------------------------------------------------------------------===//
+
+InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent)
+ : Parent(&Parent), Index(Index)
+{
+ if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
+ Kind = EK_ArrayElement;
+ Type = AT->getElementType();
+ } else {
+ Kind = EK_VectorElement;
+ Type = Parent.getType()->getAs<VectorType>()->getElementType();
+ }
+}
+
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase)
+{
+ InitializedEntity Result;
+ Result.Kind = EK_Base;
+ Result.Base = reinterpret_cast<uintptr_t>(Base);
+ if (IsInheritedVirtualBase)
+ Result.Base |= 0x01;
+
+ Result.Type = Base->getType();
+ return Result;
+}
+
+DeclarationName InitializedEntity::getName() const {
+ switch (getKind()) {
+ case EK_Parameter:
+ if (!VariableOrMember)
+ return DeclarationName();
+ // Fall through
+
+ case EK_Variable:
+ case EK_Member:
+ return VariableOrMember->getDeclName();
+
+ case EK_Result:
+ case EK_Exception:
+ case EK_New:
+ case EK_Temporary:
+ case EK_Base:
+ case EK_ArrayElement:
+ case EK_VectorElement:
+ case EK_BlockElement:
+ return DeclarationName();
+ }
+
+ // Silence GCC warning
+ return DeclarationName();
+}
+
+DeclaratorDecl *InitializedEntity::getDecl() const {
+ switch (getKind()) {
+ case EK_Variable:
+ case EK_Parameter:
+ case EK_Member:
+ return VariableOrMember;
+
+ case EK_Result:
+ case EK_Exception:
+ case EK_New:
+ case EK_Temporary:
+ case EK_Base:
+ case EK_ArrayElement:
+ case EK_VectorElement:
+ case EK_BlockElement:
+ return 0;
+ }
+
+ // Silence GCC warning
+ return 0;
+}
+
+bool InitializedEntity::allowsNRVO() const {
+ switch (getKind()) {
+ case EK_Result:
+ case EK_Exception:
+ return LocAndNRVO.NRVO;
+
+ case EK_Variable:
+ case EK_Parameter:
+ case EK_Member:
+ case EK_New:
+ case EK_Temporary:
+ case EK_Base:
+ case EK_ArrayElement:
+ case EK_VectorElement:
+ case EK_BlockElement:
+ break;
+ }
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization sequence
+//===----------------------------------------------------------------------===//
+
+void InitializationSequence::Step::Destroy() {
+ switch (Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
+ case SK_CastDerivedToBaseLValue:
+ case SK_BindReference:
+ case SK_BindReferenceToTemporary:
+ case SK_ExtraneousCopyToTemporary:
+ case SK_UserConversion:
+ case SK_QualificationConversionRValue:
+ case SK_QualificationConversionXValue:
+ case SK_QualificationConversionLValue:
+ case SK_ListInitialization:
+ case SK_ConstructorInitialization:
+ case SK_ZeroInitialization:
+ case SK_CAssignment:
+ case SK_StringInit:
+ case SK_ObjCObjectConversion:
+ break;
+
+ case SK_ConversionSequence:
+ delete ICS;
+ }
+}
+
+bool InitializationSequence::isDirectReferenceBinding() const {
+ return getKind() == ReferenceBinding && Steps.back().Kind == SK_BindReference;
+}
+
+bool InitializationSequence::isAmbiguous() const {
+ if (getKind() != FailedSequence)
+ return false;
+
+ switch (getFailureKind()) {
+ case FK_TooManyInitsForReference:
+ case FK_ArrayNeedsInitList:
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ case FK_AddressOfOverloadFailed: // FIXME: Could do better
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ case FK_RValueReferenceBindingToLValue:
+ case FK_ReferenceInitDropsQualifiers:
+ case FK_ReferenceInitFailed:
+ case FK_ConversionFailed:
+ case FK_TooManyInitsForScalar:
+ case FK_ReferenceBindingToInitList:
+ case FK_InitListBadDestinationType:
+ case FK_DefaultInitOfConst:
+ case FK_Incomplete:
+ return false;
+
+ case FK_ReferenceInitOverloadFailed:
+ case FK_UserConversionOverloadFailed:
+ case FK_ConstructorOverloadFailed:
+ return FailedOverloadResult == OR_Ambiguous;
+ }
+
+ return false;
+}
+
+bool InitializationSequence::isConstructorInitialization() const {
+ return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
+}
+
+void InitializationSequence::AddAddressOverloadResolutionStep(
+ FunctionDecl *Function,
+ DeclAccessPair Found) {
+ Step S;
+ S.Kind = SK_ResolveAddressOfOverloadedFunction;
+ S.Type = Function->getType();
+ S.Function.Function = Function;
+ S.Function.FoundDecl = Found;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
+ ExprValueKind VK) {
+ Step S;
+ switch (VK) {
+ case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
+ case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
+ case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
+ default: llvm_unreachable("No such category");
+ }
+ S.Type = BaseType;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddReferenceBindingStep(QualType T,
+ bool BindingTemporary) {
+ Step S;
+ S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) {
+ Step S;
+ S.Kind = SK_ExtraneousCopyToTemporary;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ QualType T) {
+ Step S;
+ S.Kind = SK_UserConversion;
+ S.Type = T;
+ S.Function.Function = Function;
+ S.Function.FoundDecl = FoundDecl;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddQualificationConversionStep(QualType Ty,
+ ExprValueKind VK) {
+ Step S;
+ S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
+ switch (VK) {
+ case VK_RValue:
+ S.Kind = SK_QualificationConversionRValue;
+ break;
+ case VK_XValue:
+ S.Kind = SK_QualificationConversionXValue;
+ break;
+ case VK_LValue:
+ S.Kind = SK_QualificationConversionLValue;
+ break;
+ }
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddConversionSequenceStep(
+ const ImplicitConversionSequence &ICS,
+ QualType T) {
+ Step S;
+ S.Kind = SK_ConversionSequence;
+ S.Type = T;
+ S.ICS = new ImplicitConversionSequence(ICS);
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddListInitializationStep(QualType T) {
+ Step S;
+ S.Kind = SK_ListInitialization;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void
+InitializationSequence::AddConstructorInitializationStep(
+ CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
+ QualType T) {
+ Step S;
+ S.Kind = SK_ConstructorInitialization;
+ S.Type = T;
+ S.Function.Function = Constructor;
+ S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddZeroInitializationStep(QualType T) {
+ Step S;
+ S.Kind = SK_ZeroInitialization;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddCAssignmentStep(QualType T) {
+ Step S;
+ S.Kind = SK_CAssignment;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddStringInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_StringInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
+ Step S;
+ S.Kind = SK_ObjCObjectConversion;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::SetOverloadFailure(FailureKind Failure,
+ OverloadingResult Result) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ this->FailedOverloadResult = Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Attempt initialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static void TryListInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitListExpr *InitList,
+ InitializationSequence &Sequence) {
+ // FIXME: We only perform rudimentary checking of list
+ // initializations at this point, then assume that any list
+ // initialization of an array, aggregate, or scalar will be
+ // well-formed. When we actually "perform" list initialization, we'll
+ // do all of the necessary checking. C++0x initializer lists will
+ // force us to perform more checking here.
+ Sequence.setSequenceKind(InitializationSequence::ListInitialization);
+
+ QualType DestType = Entity.getType();
+
+ // C++ [dcl.init]p13:
+ // If T is a scalar type, then a declaration of the form
+ //
+ // T x = { a };
+ //
+ // is equivalent to
+ //
+ // T x = a;
+ if (DestType->isScalarType()) {
+ if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
+ Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+ return;
+ }
+
+ // Assume scalar initialization from a single value works.
+ } else if (DestType->isAggregateType()) {
+ // Assume aggregate initialization works.
+ } else if (DestType->isVectorType()) {
+ // Assume vector initialization works.
+ } else if (DestType->isReferenceType()) {
+ // FIXME: C++0x defines behavior for this.
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+ return;
+ } else if (DestType->isRecordType()) {
+ // FIXME: C++0x defines behavior for this
+ Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+ }
+
+ // Add a general "list initialization" step.
+ Sequence.AddListInitializationStep(DestType);
+}
+
+/// \brief Try a reference initialization that involves calling a conversion
+/// function.
+static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ bool AllowRValues,
+ InitializationSequence &Sequence) {
+ QualType DestType = Entity.getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ QualType T1 = cv1T1.getUnqualifiedType();
+ QualType cv2T2 = Initializer->getType();
+ QualType T2 = cv2T2.getUnqualifiedType();
+
+ bool DerivedToBase;
+ bool ObjCConversion;
+ assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
+ T1, T2, DerivedToBase,
+ ObjCConversion) &&
+ "Must have incompatible references when binding via conversion");
+ (void)DerivedToBase;
+ (void)ObjCConversion;
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+
+ const RecordType *T1RecordType = 0;
+ if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
+ !S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if there is a suitable conversion.
+ CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
+ Con != ConEnd; ++Con) {
+ NamedDecl *D = *Con;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(D);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
+ else
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
+ }
+ }
+ }
+ if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
+
+ const RecordType *T2RecordType = 0;
+ if ((T2RecordType = T2->getAs<RecordType>()) &&
+ !S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
+ // The type we're converting from is a class type, enumerate its conversion
+ // functions.
+ CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+
+ const UnresolvedSetImpl *Conversions
+ = T2RecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion unless we're allowed to
+ // consider rvalues.
+ // FIXME: Do we need to make sure that we only consider conversion
+ // candidates with reference-compatible results? That might be needed to
+ // break recursion.
+ if ((AllowExplicit || !Conv->isExplicit()) &&
+ (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer,
+ DestType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+ Initializer, DestType, CandidateSet);
+ }
+ }
+ }
+ if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
+
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
+ return Result;
+
+ FunctionDecl *Function = Best->Function;
+
+ // Compute the returned type of the conversion.
+ if (isa<CXXConversionDecl>(Function))
+ T2 = Function->getResultType();
+ else
+ T2 = cv1T1;
+
+ // Add the user-defined conversion step.
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl,
+ T2.getNonLValueExprType(S.Context));
+
+ // Determine whether we need to perform derived-to-base or
+ // cv-qualification adjustments.
+ ExprValueKind VK = VK_RValue;
+ if (T2->isLValueReferenceType())
+ VK = VK_LValue;
+ else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
+ VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
+
+ bool NewDerivedToBase = false;
+ bool NewObjCConversion = false;
+ Sema::ReferenceCompareResult NewRefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, T1,
+ T2.getNonLValueExprType(S.Context),
+ NewDerivedToBase, NewObjCConversion);
+ if (NewRefRelationship == Sema::Ref_Incompatible) {
+ // If the type we've converted to is not reference-related to the
+ // type we're looking for, then there is another conversion step
+ // we need to perform to produce a temporary of the right type
+ // that we'll be binding to.
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard = Best->FinalConversion;
+ T2 = ICS.Standard.getToType(2);
+ Sequence.AddConversionSequenceStep(ICS, T2);
+ } else if (NewDerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1,
+ T2.getNonReferenceType().getQualifiers()),
+ VK);
+ else if (NewObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1,
+ T2.getNonReferenceType().getQualifiers()));
+
+ if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, VK);
+
+ Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
+ return OR_Success;
+}
+
+/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
+static void TryReferenceInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
+
+ QualType DestType = Entity.getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ Qualifiers T1Quals;
+ QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
+ QualType cv2T2 = Initializer->getType();
+ Qualifiers T2Quals;
+ QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // If the initializer is the address of an overloaded function, try
+ // to resolve the overloaded function. If all goes well, T2 is the
+ // type of the resulting function.
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+ DeclAccessPair Found;
+ if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
+ T1,
+ false,
+ Found)) {
+ Sequence.AddAddressOverloadResolutionStep(Fn, Found);
+ cv2T2 = Fn->getType();
+ T2 = cv2T2.getUnqualifiedType();
+ } else if (!T1->isRecordType()) {
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ return;
+ }
+ }
+
+ // Compute some basic properties of the types and the initializer.
+ bool isLValueRef = DestType->isLValueReferenceType();
+ bool isRValueRef = !isLValueRef;
+ bool DerivedToBase = false;
+ bool ObjCConversion = false;
+ Expr::Classification InitCategory = Initializer->Classify(S.Context);
+ Sema::ReferenceCompareResult RefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
+ ObjCConversion);
+
+ // C++0x [dcl.init.ref]p5:
+ // A reference to type "cv1 T1" is initialized by an expression of type
+ // "cv2 T2" as follows:
+ //
+ // - If the reference is an lvalue reference and the initializer
+ // expression
+ // Note the analogous bullet points for rvlaue refs to functions. Because
+ // there are no function rvalues in C++, rvalue refs to functions are treated
+ // like lvalue refs.
+ OverloadingResult ConvOvlResult = OR_Success;
+ bool T1Function = T1->isFunctionType();
+ if (isLValueRef || T1Function) {
+ if (InitCategory.isLValue() &&
+ (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ (Kind.isCStyleOrFunctionalCast() &&
+ RefRelationship == Sema::Ref_Related))) {
+ // - is an lvalue (but is not a bit-field), and "cv1 T1" is
+ // reference-compatible with "cv2 T2," or
+ //
+ // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
+ // bit-field when we're determining whether the reference initialization
+ // can occur. However, we do pay attention to whether it is a bit-field
+ // to decide whether we're actually binding to a temporary created from
+ // the bit-field.
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1, T2Quals),
+ VK_LValue);
+ else if (ObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1, T2Quals));
+
+ if (T1Quals != T2Quals)
+ Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);
+ bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+ (Initializer->getBitField() || Initializer->refersToVectorElement());
+ Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
+ return;
+ }
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
+ // with "cv3 T3" (this conversion is selected by enumerating the
+ // applicable conversion functions (13.3.1.6) and choosing the best
+ // one through overload resolution (13.3)),
+ // If we have an rvalue ref to function type here, the rhs must be
+ // an rvalue.
+ if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
+ (isLValueRef || InitCategory.isRValue())) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
+ Initializer,
+ /*AllowRValues=*/isRValueRef,
+ Sequence);
+ if (ConvOvlResult == OR_Success)
+ return;
+ if (ConvOvlResult != OR_No_Viable_Function) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ }
+ }
+ }
+
+ // - Otherwise, the reference shall be an lvalue reference to a
+ // non-volatile const type (i.e., cv1 shall be const), or the reference
+ // shall be an rvalue reference.
+ if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ else
+ Sequence.SetFailed(InitCategory.isLValue()
+ ? (RefRelationship == Sema::Ref_Related
+ ? InitializationSequence::FK_ReferenceInitDropsQualifiers
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+
+ return;
+ }
+
+ // - If the initializer expression
+ // - is an xvalue, class prvalue, array prvalue, or function lvalue and
+ // "cv1 T1" is reference-compatible with "cv2 T2"
+ // Note: functions are handled below.
+ if (!T1Function &&
+ (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ (Kind.isCStyleOrFunctionalCast() &&
+ RefRelationship == Sema::Ref_Related)) &&
+ (InitCategory.isXValue() ||
+ (InitCategory.isPRValue() && T2->isRecordType()) ||
+ (InitCategory.isPRValue() && T2->isArrayType()))) {
+ ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
+ if (InitCategory.isPRValue() && T2->isRecordType()) {
+ // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
+ // compiler the freedom to perform a copy here or bind to the
+ // object, while C++0x requires that we bind directly to the
+ // object. Hence, we always bind to the object without making an
+ // extra copy. However, in C++03 requires that we check for the
+ // presence of a suitable copy constructor:
+ //
+ // The constructor that would be used to make the copy shall
+ // be callable whether or not the copy is actually done.
+ if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().Microsoft)
+ Sequence.AddExtraneousCopyToTemporary(cv2T2);
+ }
+
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
+ ValueKind);
+ else if (ObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1, T2Quals));
+
+ if (T1Quals != T2Quals)
+ Sequence.AddQualificationConversionStep(cv1T1, ValueKind);
+ Sequence.AddReferenceBindingStep(cv1T1,
+ /*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType()));
+ return;
+ }
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // xvalue, class prvalue, or function lvalue of type "cv3 T3",
+ // where "cv1 T1" is reference-compatible with "cv3 T3",
+ if (T2->isRecordType()) {
+ if (RefRelationship == Sema::Ref_Incompatible) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
+ Kind, Initializer,
+ /*AllowRValues=*/true,
+ Sequence);
+ if (ConvOvlResult)
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+
+ return;
+ }
+
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+
+ // - Otherwise, a temporary of type "cv1 T1" is created and initialized
+ // from the initializer expression using the rules for a non-reference
+ // copy initialization (8.5). The reference is then bound to the
+ // temporary. [...]
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
+
+ InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+
+ if (S.TryImplicitConversion(Sequence, TempEntity, Initializer,
+ /*SuppressUserConversions*/ false,
+ AllowExplicit,
+ /*FIXME:InOverloadResolution=*/false,
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast())) {
+ // FIXME: Use the conversion function set stored in ICS to turn
+ // this into an overloading ambiguity diagnostic. However, we need
+ // to keep that set as an OverloadCandidateSet rather than as some
+ // other kind of set.
+ if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+ return;
+ }
+
+ // [...] If T1 is reference-related to T2, cv1 must be the
+ // same cv-qualification as, or greater cv-qualification
+ // than, cv2; otherwise, the program is ill-formed.
+ unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
+ unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
+ if (RefRelationship == Sema::Ref_Related &&
+ (T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+
+ // [...] If T1 is reference-related to T2 and the reference is an rvalue
+ // reference, the initializer expression shall not be an lvalue.
+ if (RefRelationship >= Sema::Ref_Related && !isLValueRef &&
+ InitCategory.isLValue()) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_RValueReferenceBindingToLValue);
+ return;
+ }
+
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ return;
+}
+
+/// \brief Attempt character array initialization from a string literal
+/// (C++ [dcl.init.string], C99 6.7.8).
+static void TryStringLiteralInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::StringInit);
+ Sequence.AddStringInitStep(Entity.getType());
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+static void TryConstructorInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs,
+ QualType DestType,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
+ Kind.getKind() == InitializationKind::IK_Value ||
+ Kind.getKind() == InitializationKind::IK_Default);
+
+ // The type we're constructing needs to be complete.
+ if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ Sequence.SetFailed(InitializationSequence::FK_Incomplete);
+ return;
+ }
+
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if one is suitable.
+ const RecordType *DestRecordType = DestType->getAs<RecordType>();
+ assert(DestRecordType && "Constructor initialization requires record type");
+ CXXRecordDecl *DestRecordDecl
+ = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
+ Con != ConEnd; ++Con) {
+ NamedDecl *D = *Con;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+ bool SuppressUserConversions = false;
+
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else {
+ Constructor = cast<CXXConstructorDecl>(D);
+
+ // If we're performing copy initialization using a copy constructor, we
+ // suppress user-defined conversions on the arguments.
+ // FIXME: Move constructors?
+ if (Kind.getKind() == InitializationKind::IK_Copy &&
+ Constructor->isCopyConstructor())
+ SuppressUserConversions = true;
+ }
+
+ if (!Constructor->isInvalidDecl() &&
+ (AllowExplicit || !Constructor->isExplicit())) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ else
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ }
+ }
+
+ SourceLocation DeclLoc = Kind.getLocation();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ConstructorOverloadFailed,
+ Result);
+ return;
+ }
+
+ // C++0x [dcl.init]p6:
+ // If a program calls for the default initialization of an object
+ // of a const-qualified type T, T shall be a class type with a
+ // user-provided default constructor.
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ Entity.getType().isConstQualified() &&
+ cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
+
+ // Add the constructor initialization step. Any cv-qualification conversion is
+ // subsumed by the initialization.
+ Sequence.AddConstructorInitializationStep(
+ cast<CXXConstructorDecl>(Best->Function),
+ Best->FoundDecl.getAccess(),
+ DestType);
+}
+
+/// \brief Attempt value initialization (C++ [dcl.init]p7).
+static void TryValueInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitializationSequence &Sequence) {
+ // C++ [dcl.init]p5:
+ //
+ // To value-initialize an object of type T means:
+ QualType T = Entity.getType();
+
+ // -- if T is an array type, then each element is value-initialized;
+ while (const ArrayType *AT = S.Context.getAsArrayType(T))
+ T = AT->getElementType();
+
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ // -- if T is a class type (clause 9) with a user-declared
+ // constructor (12.1), then the default constructor for T is
+ // called (and the initialization is ill-formed if T has no
+ // accessible default constructor);
+ //
+ // FIXME: we really want to refer to a single subobject of the array,
+ // but Entity doesn't have a way to capture that (yet).
+ if (ClassDecl->hasUserDeclaredConstructor())
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+
+ // -- if T is a (possibly cv-qualified) non-union class type
+ // without a user-provided constructor, then the object is
+ // zero-initialized and, if T's implicitly-declared default
+ // constructor is non-trivial, that constructor is called.
+ if ((ClassDecl->getTagKind() == TTK_Class ||
+ ClassDecl->getTagKind() == TTK_Struct)) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+ }
+ }
+ }
+
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ Sequence.setSequenceKind(InitializationSequence::ZeroInitialization);
+}
+
+/// \brief Attempt default initialization (C++ [dcl.init]p6).
+static void TryDefaultInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitializationSequence &Sequence) {
+ assert(Kind.getKind() == InitializationKind::IK_Default);
+
+ // C++ [dcl.init]p6:
+ // To default-initialize an object of type T means:
+ // - if T is an array type, each element is default-initialized;
+ QualType DestType = Entity.getType();
+ while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
+ DestType = Array->getElementType();
+
+ // - if T is a (possibly cv-qualified) class type (Clause 9), the default
+ // constructor for T is called (and the initialization is ill-formed if
+ // T has no accessible default constructor);
+ if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
+ TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
+ return;
+ }
+
+ // - otherwise, no initialization is performed.
+ Sequence.setSequenceKind(InitializationSequence::NoInitialization);
+
+ // If a program calls for the default initialization of an object of
+ // a const-qualified type T, T shall be a class type with a user-provided
+ // default constructor.
+ if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+}
+
+/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
+/// which enumerates all conversion functions and performs overload resolution
+/// to select the best.
+static void TryUserDefinedConversion(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
+
+ QualType DestType = Entity.getType();
+ assert(!DestType->isReferenceType() && "References are handled elsewhere");
+ QualType SourceType = Initializer->getType();
+ assert((DestType->isRecordType() || SourceType->isRecordType()) &&
+ "Must have a class type to perform a user-defined conversion");
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+
+ if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if there is a suitable conversion.
+ CXXRecordDecl *DestRecordDecl
+ = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+ // Try to complete the type we're converting to.
+ if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
+ Con != ConEnd; ++Con) {
+ NamedDecl *D = *Con;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl
+ = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(D);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
+ else
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
+ }
+ }
+ }
+ }
+
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
+ // The type we're converting from is a class type, enumerate its conversion
+ // functions.
+
+ // We can only enumerate the conversion functions for a complete type; if
+ // the type isn't complete, simply skip this step.
+ if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+ CXXRecordDecl *SourceRecordDecl
+ = cast<CXXRecordDecl>(SourceRecordType->getDecl());
+
+ const UnresolvedSetImpl *Conversions
+ = SourceRecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ if (AllowExplicit || !Conv->isExplicit()) {
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
+ ActingDC, Initializer, DestType,
+ CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
+ Initializer, DestType, CandidateSet);
+ }
+ }
+ }
+ }
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_UserConversionOverloadFailed,
+ Result);
+ return;
+ }
+
+ FunctionDecl *Function = Best->Function;
+
+ if (isa<CXXConstructorDecl>(Function)) {
+ // Add the user-defined conversion step. Any cv-qualification conversion is
+ // subsumed by the initialization.
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
+ return;
+ }
+
+ // Add the user-defined conversion step that calls the conversion function.
+ QualType ConvType = Function->getCallResultType();
+ if (ConvType->getAs<RecordType>()) {
+ // If we're converting to a class type, there may be an copy if
+ // the resulting temporary object (possible to create an object of
+ // a base class type). That copy is not a separate conversion, so
+ // we just make a note of the actual destination type (possibly a
+ // base class of the type returned by the conversion function) and
+ // let the user-defined conversion step handle the conversion.
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
+ return;
+ }
+
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
+
+ // If the conversion following the call to the conversion function
+ // is interesting, add it as a separate step.
+ if (Best->FinalConversion.First || Best->FinalConversion.Second ||
+ Best->FinalConversion.Third) {
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard = Best->FinalConversion;
+ Sequence.AddConversionSequenceStep(ICS, DestType);
+ }
+}
+
+InitializationSequence::InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args,
+ unsigned NumArgs)
+ : FailedCandidateSet(Kind.getLocation()) {
+ ASTContext &Context = S.Context;
+
+ // C++0x [dcl.init]p16:
+ // The semantics of initializers are as follows. The destination type is
+ // the type of the object or reference being initialized and the source
+ // type is the type of the initializer expression. The source type is not
+ // defined when the initializer is a braced-init-list or when it is a
+ // parenthesized list of expressions.
+ QualType DestType = Entity.getType();
+
+ if (DestType->isDependentType() ||
+ Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
+ SequenceKind = DependentSequence;
+ return;
+ }
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Args[I]->getObjectKind() == OK_ObjCProperty)
+ S.ConvertPropertyForRValue(Args[I]);
+
+ QualType SourceType;
+ Expr *Initializer = 0;
+ if (NumArgs == 1) {
+ Initializer = Args[0];
+ if (!isa<InitListExpr>(Initializer))
+ SourceType = Initializer->getType();
+ }
+
+ // - If the initializer is a braced-init-list, the object is
+ // list-initialized (8.5.4).
+ if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
+ TryListInitialization(S, Entity, Kind, InitList, *this);
+ return;
+ }
+
+ // - If the destination type is a reference type, see 8.5.3.
+ if (DestType->isReferenceType()) {
+ // C++0x [dcl.init.ref]p1:
+ // A variable declared to be a T& or T&&, that is, "reference to type T"
+ // (8.3.2), shall be initialized by an object, or function, of type T or
+ // by an object that can be converted into a T.
+ // (Therefore, multiple arguments are not permitted.)
+ if (NumArgs != 1)
+ SetFailed(FK_TooManyInitsForReference);
+ else
+ TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
+ return;
+ }
+
+ // - If the destination type is an array of characters, an array of
+ // char16_t, an array of char32_t, or an array of wchar_t, and the
+ // initializer is a string literal, see 8.5.2.
+ if (Initializer && IsStringInit(Initializer, DestType, Context)) {
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // - If the initializer is (), the object is value-initialized.
+ if (Kind.getKind() == InitializationKind::IK_Value ||
+ (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
+ TryValueInitialization(S, Entity, Kind, *this);
+ return;
+ }
+
+ // Handle default initialization.
+ if (Kind.getKind() == InitializationKind::IK_Default) {
+ TryDefaultInitialization(S, Entity, Kind, *this);
+ return;
+ }
+
+ // - Otherwise, if the destination type is an array, the program is
+ // ill-formed.
+ if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
+ if (AT->getElementType()->isAnyCharacterType())
+ SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
+ else
+ SetFailed(FK_ArrayNeedsInitList);
+
+ return;
+ }
+
+ // Handle initialization in C
+ if (!S.getLangOptions().CPlusPlus) {
+ setSequenceKind(CAssignment);
+ AddCAssignmentStep(DestType);
+ return;
+ }
+
+ // - If the destination type is a (possibly cv-qualified) class type:
+ if (DestType->isRecordType()) {
+ // - If the initialization is direct-initialization, or if it is
+ // copy-initialization where the cv-unqualified version of the
+ // source type is the same class as, or a derived class of, the
+ // class of the destination, constructors are considered. [...]
+ if (Kind.getKind() == InitializationKind::IK_Direct ||
+ (Kind.getKind() == InitializationKind::IK_Copy &&
+ (Context.hasSameUnqualifiedType(SourceType, DestType) ||
+ S.IsDerivedFrom(SourceType, DestType))))
+ TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
+ Entity.getType(), *this);
+ // - Otherwise (i.e., for the remaining copy-initialization cases),
+ // user-defined conversion sequences that can convert from the source
+ // type to the destination type or (when a conversion function is
+ // used) to a derived class thereof are enumerated as described in
+ // 13.3.1.4, and the best one is chosen through overload resolution
+ // (13.3).
+ else
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ if (NumArgs > 1) {
+ SetFailed(FK_TooManyInitsForScalar);
+ return;
+ }
+ assert(NumArgs == 1 && "Zero-argument case handled above");
+
+ // - Otherwise, if the source type is a (possibly cv-qualified) class
+ // type, conversion functions are considered.
+ if (!SourceType.isNull() && SourceType->isRecordType()) {
+ TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // - Otherwise, the initial value of the object being initialized is the
+ // (possibly converted) value of the initializer expression. Standard
+ // conversions (Clause 4) will be used, if necessary, to convert the
+ // initializer expression to the cv-unqualified version of the
+ // destination type; no user-defined conversions are considered.
+ if (S.TryImplicitConversion(*this, Entity, Initializer,
+ /*SuppressUserConversions*/ true,
+ /*AllowExplicitConversions*/ false,
+ /*InOverloadResolution*/ false,
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast()))
+ {
+ DeclAccessPair dap;
+ if (Initializer->getType() == Context.OverloadTy &&
+ !S.ResolveAddressOfOverloadedFunction(Initializer
+ , DestType, false, dap))
+ SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else
+ SetFailed(InitializationSequence::FK_ConversionFailed);
+ }
+ else
+ setSequenceKind(StandardConversion);
+}
+
+InitializationSequence::~InitializationSequence() {
+ for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+ StepEnd = Steps.end();
+ Step != StepEnd; ++Step)
+ Step->Destroy();
+}
+
+//===----------------------------------------------------------------------===//
+// Perform initialization
+//===----------------------------------------------------------------------===//
+static Sema::AssignmentAction
+getAssignmentAction(const InitializedEntity &Entity) {
+ switch(Entity.getKind()) {
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_Base:
+ return Sema::AA_Initializing;
+
+ case InitializedEntity::EK_Parameter:
+ if (Entity.getDecl() &&
+ isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
+ return Sema::AA_Sending;
+
+ return Sema::AA_Passing;
+
+ case InitializedEntity::EK_Result:
+ return Sema::AA_Returning;
+
+ case InitializedEntity::EK_Temporary:
+ // FIXME: Can we tell apart casting vs. converting?
+ return Sema::AA_Casting;
+
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
+ return Sema::AA_Initializing;
+ }
+
+ return Sema::AA_Converting;
+}
+
+/// \brief Whether we should binding a created object as a temporary when
+/// initializing the given entity.
+static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_BlockElement:
+ return false;
+
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Temporary:
+ return true;
+ }
+
+ llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief Whether the given entity, when initialized with an object
+/// created for that initialization, requires destruction.
+static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
+ return false;
+
+ case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Exception:
+ return true;
+ }
+
+ llvm_unreachable("missed an InitializedEntity kind?");
+}
+
+/// \brief Make a (potentially elidable) temporary copy of the object
+/// provided by the given initializer by calling the appropriate copy
+/// constructor.
+///
+/// \param S The Sema object used for type-checking.
+///
+/// \param T The type of the temporary object, which must either be
+/// the type of the initializer expression or a superclass thereof.
+///
+/// \param Enter The entity being initialized.
+///
+/// \param CurInit The initializer expression.
+///
+/// \param IsExtraneousCopy Whether this is an "extraneous" copy that
+/// is permitted in C++03 (but not C++0x) when binding a reference to
+/// an rvalue.
+///
+/// \returns An expression that copies the initializer expression into
+/// a temporary object, or an error expression if a copy could not be
+/// created.
+static ExprResult CopyObject(Sema &S,
+ QualType T,
+ const InitializedEntity &Entity,
+ ExprResult CurInit,
+ bool IsExtraneousCopy) {
+ // Determine which class type we're copying to.
+ Expr *CurInitExpr = (Expr *)CurInit.get();
+ CXXRecordDecl *Class = 0;
+ if (const RecordType *Record = T->getAs<RecordType>())
+ Class = cast<CXXRecordDecl>(Record->getDecl());
+ if (!Class)
+ return move(CurInit);
+
+ // C++0x [class.copy]p32:
+ // When certain criteria are met, an implementation is allowed to
+ // omit the copy/move construction of a class object, even if the
+ // copy/move constructor and/or destructor for the object have
+ // side effects. [...]
+ // - when a temporary class object that has not been bound to a
+ // reference (12.2) would be copied/moved to a class object
+ // with the same cv-unqualified type, the copy/move operation
+ // can be omitted by constructing the temporary object
+ // directly into the target of the omitted copy/move
+ //
+ // Note that the other three bullets are handled elsewhere. Copy
+ // elision for return statements and throw expressions are handled as part
+ // of constructor initialization, while copy elision for exception handlers
+ // is handled by the run-time.
+ bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class);
+ SourceLocation Loc;
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_Result:
+ Loc = Entity.getReturnLoc();
+ break;
+
+ case InitializedEntity::EK_Exception:
+ Loc = Entity.getThrowLoc();
+ break;
+
+ case InitializedEntity::EK_Variable:
+ Loc = Entity.getDecl()->getLocation();
+ break;
+
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_Parameter:
+ case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Base:
+ case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
+ Loc = CurInitExpr->getLocStart();
+ break;
+ }
+
+ // Make sure that the type we are copying is complete.
+ if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete)))
+ return move(CurInit);
+
+ // Perform overload resolution using the class's copy/move constructors.
+ DeclContext::lookup_iterator Con, ConEnd;
+ OverloadCandidateSet CandidateSet(Loc);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
+ Con != ConEnd; ++Con) {
+ // Only consider copy/move constructors and constructor templates. Per
+ // C++0x [dcl.init]p16, second bullet to class types, this
+ // initialization is direct-initialization.
+ CXXConstructorDecl *Constructor = 0;
+
+ if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
+ // Handle copy/moveconstructors, only.
+ if (!Constructor || Constructor->isInvalidDecl() ||
+ !Constructor->isCopyOrMoveConstructor() ||
+ !Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+ continue;
+
+ DeclAccessPair FoundDecl
+ = DeclAccessPair::make(Constructor, Constructor->getAccess());
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &CurInitExpr, 1, CandidateSet);
+ continue;
+ }
+
+ // Handle constructor templates.
+ FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl->isInvalidDecl())
+ continue;
+
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+ continue;
+
+ // FIXME: Do we need to limit this to copy-constructor-like
+ // candidates?
+ DeclAccessPair FoundDecl
+ = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+ &CurInitExpr, 1, CandidateSet, true);
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
+ case OR_Success:
+ break;
+
+ case OR_No_Viable_Function:
+ S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
+ ? diag::ext_rvalue_to_reference_temp_copy_no_viable
+ : diag::err_temp_copy_no_viable)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1);
+ if (!IsExtraneousCopy || S.isSFINAEContext())
+ return ExprError();
+ return move(CurInit);
+
+ case OR_Ambiguous:
+ S.Diag(Loc, diag::err_temp_copy_ambiguous)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1);
+ return ExprError();
+
+ case OR_Deleted:
+ S.Diag(Loc, diag::err_temp_copy_deleted)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ return ExprError();
+ }
+
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+ CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+ S.CheckConstructorAccess(Loc, Constructor, Entity,
+ Best->FoundDecl.getAccess(), IsExtraneousCopy);
+
+ if (IsExtraneousCopy) {
+ // If this is a totally extraneous copy for C++03 reference
+ // binding purposes, just return the original initialization
+ // expression. We don't generate an (elided) copy operation here
+ // because doing so would require us to pass down a flag to avoid
+ // infinite recursion, where each step adds another extraneous,
+ // elidable copy.
+
+ // Instantiate the default arguments of any extra parameters in
+ // the selected copy constructor, as if we were going to create a
+ // proper call to the copy constructor.
+ for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) {
+ ParmVarDecl *Parm = Constructor->getParamDecl(I);
+ if (S.RequireCompleteType(Loc, Parm->getType(),
+ S.PDiag(diag::err_call_incomplete_argument)))
+ break;
+
+ // Build the default argument expression; we don't actually care
+ // if this succeeds or not, because this routine will complain
+ // if there was a problem.
+ S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm);
+ }
+
+ return S.Owned(CurInitExpr);
+ }
+
+ // Determine the arguments required to actually perform the
+ // constructor call (we might have derived-to-base conversions, or
+ // the copy constructor may have default arguments).
+ if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1),
+ Loc, ConstructorArgs))
+ return ExprError();
+
+ // Actually perform the constructor call.
+ CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
+
+ // If we're supposed to bind temporaries, do so.
+ if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ return move(CurInit);
+}
+
+void InitializationSequence::PrintInitLocationNote(Sema &S,
+ const InitializedEntity &Entity) {
+ if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) {
+ if (Entity.getDecl()->getLocation().isInvalid())
+ return;
+
+ if (Entity.getDecl()->getDeclName())
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here)
+ << Entity.getDecl()->getDeclName();
+ else
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
+ }
+}
+
+ExprResult
+InitializationSequence::Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType) {
+ if (SequenceKind == FailedSequence) {
+ unsigned NumArgs = Args.size();
+ Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
+ return ExprError();
+ }
+
+ if (SequenceKind == DependentSequence) {
+ // If the declaration is a non-dependent, incomplete array type
+ // that has an initializer, then its type will be completed once
+ // the initializer is instantiated.
+ if (ResultType && !Entity.getType()->isDependentType() &&
+ Args.size() == 1) {
+ QualType DeclType = Entity.getType();
+ if (const IncompleteArrayType *ArrayT
+ = S.Context.getAsIncompleteArrayType(DeclType)) {
+ // FIXME: We don't currently have the ability to accurately
+ // compute the length of an initializer list without
+ // performing full type-checking of the initializer list
+ // (since we have to determine where braces are implicitly
+ // introduced and such). So, we fall back to making the array
+ // type a dependently-sized array type with no specified
+ // bound.
+ if (isa<InitListExpr>((Expr *)Args.get()[0])) {
+ SourceRange Brackets;
+
+ // Scavange the location of the brackets from the entity, if we can.
+ if (DeclaratorDecl *DD = Entity.getDecl()) {
+ if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
+ TypeLoc TL = TInfo->getTypeLoc();
+ if (IncompleteArrayTypeLoc *ArrayLoc
+ = dyn_cast<IncompleteArrayTypeLoc>(&TL))
+ Brackets = ArrayLoc->getBracketsRange();
+ }
+ }
+
+ *ResultType
+ = S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
+ /*NumElts=*/0,
+ ArrayT->getSizeModifier(),
+ ArrayT->getIndexTypeCVRQualifiers(),
+ Brackets);
+ }
+
+ }
+ }
+
+ if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
+ return ExprResult(Args.release()[0]);
+
+ if (Args.size() == 0)
+ return S.Owned((Expr *)0);
+
+ unsigned NumArgs = Args.size();
+ return S.Owned(new (S.Context) ParenListExpr(S.Context,
+ SourceLocation(),
+ (Expr **)Args.release(),
+ NumArgs,
+ SourceLocation()));
+ }
+
+ if (SequenceKind == NoInitialization)
+ return S.Owned((Expr *)0);
+
+ QualType DestType = Entity.getType().getNonReferenceType();
+ // FIXME: Ugly hack around the fact that Entity.getType() is not
+ // the same as Entity.getDecl()->getType() in cases involving type merging,
+ // and we want latter when it makes sense.
+ if (ResultType)
+ *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
+ Entity.getType();
+
+ ExprResult CurInit = S.Owned((Expr *)0);
+
+ assert(!Steps.empty() && "Cannot have an empty initialization sequence");
+
+ // For initialization steps that start with a single initializer,
+ // grab the only argument out the Args and place it into the "current"
+ // initializer.
+ switch (Steps.front().Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
+ case SK_CastDerivedToBaseLValue:
+ case SK_BindReference:
+ case SK_BindReferenceToTemporary:
+ case SK_ExtraneousCopyToTemporary:
+ case SK_UserConversion:
+ case SK_QualificationConversionLValue:
+ case SK_QualificationConversionXValue:
+ case SK_QualificationConversionRValue:
+ case SK_ConversionSequence:
+ case SK_ListInitialization:
+ case SK_CAssignment:
+ case SK_StringInit:
+ case SK_ObjCObjectConversion: {
+ assert(Args.size() == 1);
+ Expr *CurInitExpr = Args.get()[0];
+ if (!CurInitExpr) return ExprError();
+
+ // Read from a property when initializing something with it.
+ if (CurInitExpr->getObjectKind() == OK_ObjCProperty)
+ S.ConvertPropertyForRValue(CurInitExpr);
+
+ CurInit = ExprResult(CurInitExpr);
+ break;
+ }
+
+ case SK_ConstructorInitialization:
+ case SK_ZeroInitialization:
+ break;
+ }
+
+ // Walk through the computed steps for the initialization sequence,
+ // performing the specified conversions along the way.
+ bool ConstructorInitRequiresZeroInit = false;
+ for (step_iterator Step = step_begin(), StepEnd = step_end();
+ Step != StepEnd; ++Step) {
+ if (CurInit.isInvalid())
+ return ExprError();
+
+ Expr *CurInitExpr = CurInit.get();
+ QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
+
+ switch (Step->Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ // Overload resolution determined which function invoke; update the
+ // initializer to reflect that choice.
+ S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);
+ S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
+ CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+ Step->Function.FoundDecl,
+ Step->Function.Function);
+ break;
+
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
+ case SK_CastDerivedToBaseLValue: {
+ // We have a derived-to-base cast that produces either an rvalue or an
+ // lvalue. Perform that cast.
+
+ CXXCastPath BasePath;
+
+ // Casts to inaccessible base classes are allowed with C-style casts.
+ bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
+ if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
+ CurInitExpr->getLocStart(),
+ CurInitExpr->getSourceRange(),
+ &BasePath, IgnoreBaseAccess))
+ return ExprError();
+
+ if (S.BasePathInvolvesVirtualBase(BasePath)) {
+ QualType T = SourceType;
+ if (const PointerType *Pointer = T->getAs<PointerType>())
+ T = Pointer->getPointeeType();
+ if (const RecordType *RecordTy = T->getAs<RecordType>())
+ S.MarkVTableUsed(CurInitExpr->getLocStart(),
+ cast<CXXRecordDecl>(RecordTy->getDecl()));
+ }
+
+ ExprValueKind VK =
+ Step->Kind == SK_CastDerivedToBaseLValue ?
+ VK_LValue :
+ (Step->Kind == SK_CastDerivedToBaseXValue ?
+ VK_XValue :
+ VK_RValue);
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ Step->Type,
+ CK_DerivedToBase,
+ CurInit.get(),
+ &BasePath, VK));
+ break;
+ }
+
+ case SK_BindReference:
+ if (FieldDecl *BitField = CurInitExpr->getBitField()) {
+ // References cannot bind to bit fields (C++ [dcl.init.ref]p5).
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+ << Entity.getType().isVolatileQualified()
+ << BitField->getDeclName()
+ << CurInitExpr->getSourceRange();
+ S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+ return ExprError();
+ }
+
+ if (CurInitExpr->refersToVectorElement()) {
+ // References cannot bind to vector elements.
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+ << Entity.getType().isVolatileQualified()
+ << CurInitExpr->getSourceRange();
+ PrintInitLocationNote(S, Entity);
+ return ExprError();
+ }
+
+ // Reference binding does not have any corresponding ASTs.
+
+ // Check exception specifications
+ if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ return ExprError();
+
+ break;
+
+ case SK_BindReferenceToTemporary:
+ // Reference binding does not have any corresponding ASTs.
+
+ // Check exception specifications
+ if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
+ return ExprError();
+
+ break;
+
+ case SK_ExtraneousCopyToTemporary:
+ CurInit = CopyObject(S, Step->Type, Entity, move(CurInit),
+ /*IsExtraneousCopy=*/true);
+ break;
+
+ case SK_UserConversion: {
+ // We have a user-defined conversion that invokes either a constructor
+ // or a conversion function.
+ CastKind CastKind;
+ bool IsCopy = false;
+ FunctionDecl *Fn = Step->Function.Function;
+ DeclAccessPair FoundFn = Step->Function.FoundDecl;
+ bool CreatedObject = false;
+ bool IsLvalue = false;
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
+ // Build a call to the selected constructor.
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+ SourceLocation Loc = CurInitExpr->getLocStart();
+ CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+ // Determine the arguments required to actually perform the constructor
+ // call.
+ if (S.CompleteConstructorCall(Constructor,
+ MultiExprArg(&CurInitExpr, 1),
+ Loc, ConstructorArgs))
+ return ExprError();
+
+ // Build the an expression that constructs a temporary.
+ CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
+ if (CurInit.isInvalid())
+ return ExprError();
+
+ S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
+ FoundFn.getAccess());
+ S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
+
+ CastKind = CK_ConstructorConversion;
+ QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
+ if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
+ S.IsDerivedFrom(SourceType, Class))
+ IsCopy = true;
+
+ CreatedObject = true;
+ } else {
+ // Build a call to the conversion function.
+ CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
+ IsLvalue = Conversion->getResultType()->isLValueReferenceType();
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0,
+ FoundFn);
+ S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
+
+ // FIXME: Should we move this initialization into a separate
+ // derived-to-base conversion? I believe the answer is "no", because
+ // we don't want to turn off access control here for c-style casts.
+ if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
+ FoundFn, Conversion))
+ return ExprError();
+
+ // Do a little dance to make sure that CurInit has the proper
+ // pointer.
+ CurInit.release();
+
+ // Build the actual call to the conversion function.
+ CurInit = S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion);
+ if (CurInit.isInvalid() || !CurInit.get())
+ return ExprError();
+
+ CastKind = CK_UserDefinedConversion;
+
+ CreatedObject = Conversion->getResultType()->isRecordType();
+ }
+
+ bool RequiresCopy = !IsCopy &&
+ getKind() != InitializationSequence::ReferenceBinding;
+ if (RequiresCopy || shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ else if (CreatedObject && shouldDestroyTemporary(Entity)) {
+ CurInitExpr = static_cast<Expr *>(CurInit.get());
+ QualType T = CurInitExpr->getType();
+ if (const RecordType *Record = T->getAs<RecordType>()) {
+ CXXDestructorDecl *Destructor
+ = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
+ S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
+ S.PDiag(diag::err_access_dtor_temp) << T);
+ S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
+ S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart());
+ }
+ }
+
+ CurInitExpr = CurInit.takeAs<Expr>();
+ // FIXME: xvalues
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ CurInitExpr->getType(),
+ CastKind, CurInitExpr, 0,
+ IsLvalue ? VK_LValue : VK_RValue));
+
+ if (RequiresCopy)
+ CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
+ move(CurInit), /*IsExtraneousCopy=*/false);
+
+ break;
+ }
+
+ case SK_QualificationConversionLValue:
+ case SK_QualificationConversionXValue:
+ case SK_QualificationConversionRValue: {
+ // Perform a qualification conversion; these can never go wrong.
+ ExprValueKind VK =
+ Step->Kind == SK_QualificationConversionLValue ?
+ VK_LValue :
+ (Step->Kind == SK_QualificationConversionXValue ?
+ VK_XValue :
+ VK_RValue);
+ S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK);
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+
+ case SK_ConversionSequence: {
+ if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS,
+ getAssignmentAction(Entity),
+ Kind.isCStyleOrFunctionalCast()))
+ return ExprError();
+
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+
+ case SK_ListInitialization: {
+ InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
+ QualType Ty = Step->Type;
+ if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
+ return ExprError();
+
+ CurInit.release();
+ CurInit = S.Owned(InitList);
+ break;
+ }
+
+ case SK_ConstructorInitialization: {
+ unsigned NumArgs = Args.size();
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(Step->Function.Function);
+
+ // Build a call to the selected constructor.
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+ SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
+ ? Kind.getEqualLoc()
+ : Kind.getLocation();
+
+ if (Kind.getKind() == InitializationKind::IK_Default) {
+ // Force even a trivial, implicit default constructor to be
+ // semantically checked. We do this explicitly because we don't build
+ // the definition for completely trivial constructors.
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ assert(ClassDecl && "No parent class for constructor.");
+ if (Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+ ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false))
+ S.DefineImplicitDefaultConstructor(Loc, Constructor);
+ }
+
+ // Determine the arguments required to actually perform the constructor
+ // call.
+ if (S.CompleteConstructorCall(Constructor, move(Args),
+ Loc, ConstructorArgs))
+ return ExprError();
+
+
+ if (Entity.getKind() == InitializedEntity::EK_Temporary &&
+ NumArgs != 1 && // FIXME: Hack to work around cast weirdness
+ (Kind.getKind() == InitializationKind::IK_Direct ||
+ Kind.getKind() == InitializationKind::IK_Value)) {
+ // An explicitly-constructed temporary, e.g., X(1, 2).
+ unsigned NumExprs = ConstructorArgs.size();
+ Expr **Exprs = (Expr **)ConstructorArgs.take();
+ S.MarkDeclarationReferenced(Loc, Constructor);
+ S.DiagnoseUseOfDecl(Constructor, Loc);
+
+ TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+ if (!TSInfo)
+ TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
+
+ CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
+ Constructor,
+ TSInfo,
+ Exprs,
+ NumExprs,
+ Kind.getParenRange(),
+ ConstructorInitRequiresZeroInit));
+ } else {
+ CXXConstructExpr::ConstructionKind ConstructKind =
+ CXXConstructExpr::CK_Complete;
+
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
+ CXXConstructExpr::CK_VirtualBase :
+ CXXConstructExpr::CK_NonVirtualBase;
+ }
+
+ // Only get the parenthesis range if it is a direct construction.
+ SourceRange parenRange =
+ Kind.getKind() == InitializationKind::IK_Direct ?
+ Kind.getParenRange() : SourceRange();
+
+ // If the entity allows NRVO, mark the construction as elidable
+ // unconditionally.
+ if (Entity.allowsNRVO())
+ CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Constructor, /*Elidable=*/true,
+ move_arg(ConstructorArgs),
+ ConstructorInitRequiresZeroInit,
+ ConstructKind,
+ parenRange);
+ else
+ CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Constructor,
+ move_arg(ConstructorArgs),
+ ConstructorInitRequiresZeroInit,
+ ConstructKind,
+ parenRange);
+ }
+ if (CurInit.isInvalid())
+ return ExprError();
+
+ // Only check access if all of that succeeded.
+ S.CheckConstructorAccess(Loc, Constructor, Entity,
+ Step->Function.FoundDecl.getAccess());
+ S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc);
+
+ if (shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+ break;
+ }
+
+ case SK_ZeroInitialization: {
+ step_iterator NextStep = Step;
+ ++NextStep;
+ if (NextStep != StepEnd &&
+ NextStep->Kind == SK_ConstructorInitialization) {
+ // The need for zero-initialization is recorded directly into
+ // the call to the object's constructor within the next step.
+ ConstructorInitRequiresZeroInit = true;
+ } else if (Kind.getKind() == InitializationKind::IK_Value &&
+ S.getLangOptions().CPlusPlus &&
+ !Kind.isImplicitValueInit()) {
+ TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+ if (!TSInfo)
+ TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
+ Kind.getRange().getBegin());
+
+ CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(
+ TSInfo->getType().getNonLValueExprType(S.Context),
+ TSInfo,
+ Kind.getRange().getEnd()));
+ } else {
+ CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
+ }
+ break;
+ }
+
+ case SK_CAssignment: {
+ QualType SourceType = CurInitExpr->getType();
+ Sema::AssignConvertType ConvTy =
+ S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr);
+
+ // If this is a call, allow conversion to a transparent union.
+ if (ConvTy != Sema::Compatible &&
+ Entity.getKind() == InitializedEntity::EK_Parameter &&
+ S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr)
+ == Sema::Compatible)
+ ConvTy = Sema::Compatible;
+
+ bool Complained;
+ if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
+ Step->Type, SourceType,
+ CurInitExpr,
+ getAssignmentAction(Entity),
+ &Complained)) {
+ PrintInitLocationNote(S, Entity);
+ return ExprError();
+ } else if (Complained)
+ PrintInitLocationNote(S, Entity);
+
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+
+ case SK_StringInit: {
+ QualType Ty = Step->Type;
+ CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
+ break;
+ }
+
+ case SK_ObjCObjectConversion:
+ S.ImpCastExprToType(CurInitExpr, Step->Type,
+ CK_ObjCObjectLValueCast,
+ S.CastCategory(CurInitExpr));
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
+ }
+ }
+
+ // Diagnose non-fatal problems with the completed initialization.
+ if (Entity.getKind() == InitializedEntity::EK_Member &&
+ cast<FieldDecl>(Entity.getDecl())->isBitField())
+ S.CheckBitFieldInitialization(Kind.getLocation(),
+ cast<FieldDecl>(Entity.getDecl()),
+ CurInit.get());
+
+ return move(CurInit);
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnose initialization failures
+//===----------------------------------------------------------------------===//
+bool InitializationSequence::Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs) {
+ if (SequenceKind != FailedSequence)
+ return false;
+
+ QualType DestType = Entity.getType();
+ switch (Failure) {
+ case FK_TooManyInitsForReference:
+ // FIXME: Customize for the initialized entity?
+ if (NumArgs == 0)
+ S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+ << DestType.getNonReferenceType();
+ else // FIXME: diagnostic below could be better!
+ S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+ << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ break;
+
+ case FK_ArrayNeedsInitList:
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
+ << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
+ break;
+
+ case FK_AddressOfOverloadFailed: {
+ DeclAccessPair Found;
+ S.ResolveAddressOfOverloadedFunction(Args[0],
+ DestType.getNonReferenceType(),
+ true,
+ Found);
+ break;
+ }
+
+ case FK_ReferenceInitOverloadFailed:
+ case FK_UserConversionOverloadFailed:
+ switch (FailedOverloadResult) {
+ case OR_Ambiguous:
+ if (Failure == FK_UserConversionOverloadFailed)
+ S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
+ << Args[0]->getType() << DestType
+ << Args[0]->getSourceRange();
+ else
+ S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
+ << DestType << Args[0]->getType()
+ << Args[0]->getSourceRange();
+
+ FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs);
+ break;
+
+ case OR_No_Viable_Function:
+ S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+ << Args[0]->getType() << DestType.getNonReferenceType()
+ << Args[0]->getSourceRange();
+ FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
+ break;
+
+ case OR_Deleted: {
+ S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
+ << Args[0]->getType() << DestType.getNonReferenceType()
+ << Args[0]->getSourceRange();
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Ovl
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
+ true);
+ if (Ovl == OR_Deleted) {
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ } else {
+ llvm_unreachable("Inconsistent overload resolution?");
+ }
+ break;
+ }
+
+ case OR_Success:
+ llvm_unreachable("Conversion did not fail!");
+ break;
+ }
+ break;
+
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ S.Diag(Kind.getLocation(),
+ Failure == FK_NonConstLValueReferenceBindingToTemporary
+ ? diag::err_lvalue_reference_bind_to_temporary
+ : diag::err_lvalue_reference_bind_to_unrelated)
+ << DestType.getNonReferenceType().isVolatileQualified()
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_RValueReferenceBindingToLValue:
+ S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+ << DestType.getNonReferenceType() << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ReferenceInitDropsQualifiers:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ReferenceInitFailed:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
+ << DestType.getNonReferenceType()
+ << Args[0]->isLValue()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
+ case FK_ConversionFailed: {
+ QualType FromType = Args[0]->getType();
+ S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
+ << (int)Entity.getKind()
+ << DestType
+ << Args[0]->isLValue()
+ << FromType
+ << Args[0]->getSourceRange();
+ break;
+ }
+ case FK_TooManyInitsForScalar: {
+ SourceRange R;
+
+ if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
+ R = SourceRange(InitList->getInit(0)->getLocEnd(),
+ InitList->getLocEnd());
+ else
+ R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd());
+
+ R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
+ if (Kind.isCStyleOrFunctionalCast())
+ S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
+ << R;
+ else
+ S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+ << /*scalar=*/2 << R;
+ break;
+ }
+
+ case FK_ReferenceBindingToInitList:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
+ << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+ break;
+
+ case FK_InitListBadDestinationType:
+ S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
+ << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
+ break;
+
+ case FK_ConstructorOverloadFailed: {
+ SourceRange ArgsRange;
+ if (NumArgs)
+ ArgsRange = SourceRange(Args[0]->getLocStart(),
+ Args[NumArgs - 1]->getLocEnd());
+
+ // FIXME: Using "DestType" for the entity we're printing is probably
+ // bad.
+ switch (FailedOverloadResult) {
+ case OR_Ambiguous:
+ S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
+ << DestType << ArgsRange;
+ FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
+ Args, NumArgs);
+ break;
+
+ case OR_No_Viable_Function:
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ (Entity.getKind() == InitializedEntity::EK_Base ||
+ Entity.getKind() == InitializedEntity::EK_Member) &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default initialization of a member or
+ // base within a constructor. If no viable function was
+ // found, notify the user that she needs to explicitly
+ // initialize this base/member.
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(S.CurContext);
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*base=*/0
+ << Entity.getType();
+
+ RecordDecl *BaseDecl
+ = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+ ->getDecl();
+ S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+ << S.Context.getTagDeclType(BaseDecl);
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*member=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+ if (const RecordType *Record
+ = Entity.getType()->getAs<RecordType>())
+ S.Diag(Record->getDecl()->getLocation(),
+ diag::note_previous_decl)
+ << S.Context.getTagDeclType(Record->getDecl());
+ }
+ break;
+ }
+
+ S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
+ << DestType << ArgsRange;
+ FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
+ break;
+
+ case OR_Deleted: {
+ S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+ << true << DestType << ArgsRange;
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Ovl
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+ if (Ovl == OR_Deleted) {
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ } else {
+ llvm_unreachable("Inconsistent overload resolution?");
+ }
+ break;
+ }
+
+ case OR_Success:
+ llvm_unreachable("Conversion did not fail!");
+ break;
+ }
+ break;
+ }
+
+ case FK_DefaultInitOfConst:
+ if (Entity.getKind() == InitializedEntity::EK_Member &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default-initialization of a const member in
+ // a constructor. Complain that it needs to be explicitly
+ // initialized.
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+ S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*const=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+ << Entity.getName();
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_default_init_const)
+ << DestType << (bool)DestType->getAs<RecordType>();
+ }
+ break;
+
+ case FK_Incomplete:
+ S.RequireCompleteType(Kind.getLocation(), DestType,
+ diag::err_init_incomplete_type);
+ break;
+ }
+
+ PrintInitLocationNote(S, Entity);
+ return true;
+}
+
+void InitializationSequence::dump(llvm::raw_ostream &OS) const {
+ switch (SequenceKind) {
+ case FailedSequence: {
+ OS << "Failed sequence: ";
+ switch (Failure) {
+ case FK_TooManyInitsForReference:
+ OS << "too many initializers for reference";
+ break;
+
+ case FK_ArrayNeedsInitList:
+ OS << "array requires initializer list";
+ break;
+
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ OS << "array requires initializer list or string literal";
+ break;
+
+ case FK_AddressOfOverloadFailed:
+ OS << "address of overloaded function failed";
+ break;
+
+ case FK_ReferenceInitOverloadFailed:
+ OS << "overload resolution for reference initialization failed";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ OS << "non-const lvalue reference bound to temporary";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ OS << "non-const lvalue reference bound to unrelated type";
+ break;
+
+ case FK_RValueReferenceBindingToLValue:
+ OS << "rvalue reference bound to an lvalue";
+ break;
+
+ case FK_ReferenceInitDropsQualifiers:
+ OS << "reference initialization drops qualifiers";
+ break;
+
+ case FK_ReferenceInitFailed:
+ OS << "reference initialization failed";
+ break;
+
+ case FK_ConversionFailed:
+ OS << "conversion failed";
+ break;
+
+ case FK_TooManyInitsForScalar:
+ OS << "too many initializers for scalar";
+ break;
+
+ case FK_ReferenceBindingToInitList:
+ OS << "referencing binding to initializer list";
+ break;
+
+ case FK_InitListBadDestinationType:
+ OS << "initializer list for non-aggregate, non-scalar type";
+ break;
+
+ case FK_UserConversionOverloadFailed:
+ OS << "overloading failed for user-defined conversion";
+ break;
+
+ case FK_ConstructorOverloadFailed:
+ OS << "constructor overloading failed";
+ break;
+
+ case FK_DefaultInitOfConst:
+ OS << "default initialization of a const variable";
+ break;
+
+ case FK_Incomplete:
+ OS << "initialization of incomplete type";
+ break;
+ }
+ OS << '\n';
+ return;
+ }
+
+ case DependentSequence:
+ OS << "Dependent sequence: ";
+ return;
+
+ case UserDefinedConversion:
+ OS << "User-defined conversion sequence: ";
+ break;
+
+ case ConstructorInitialization:
+ OS << "Constructor initialization sequence: ";
+ break;
+
+ case ReferenceBinding:
+ OS << "Reference binding: ";
+ break;
+
+ case ListInitialization:
+ OS << "List initialization: ";
+ break;
+
+ case ZeroInitialization:
+ OS << "Zero initialization\n";
+ return;
+
+ case NoInitialization:
+ OS << "No initialization\n";
+ return;
+
+ case StandardConversion:
+ OS << "Standard conversion: ";
+ break;
+
+ case CAssignment:
+ OS << "C assignment: ";
+ break;
+
+ case StringInit:
+ OS << "String initialization: ";
+ break;
+ }
+
+ for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
+ if (S != step_begin()) {
+ OS << " -> ";
+ }
+
+ switch (S->Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ OS << "resolve address of overloaded function";
+ break;
+
+ case SK_CastDerivedToBaseRValue:
+ OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_CastDerivedToBaseXValue:
+ OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_CastDerivedToBaseLValue:
+ OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_BindReference:
+ OS << "bind reference to lvalue";
+ break;
+
+ case SK_BindReferenceToTemporary:
+ OS << "bind reference to a temporary";
+ break;
+
+ case SK_ExtraneousCopyToTemporary:
+ OS << "extraneous C++03 copy to temporary";
+ break;
+
+ case SK_UserConversion:
+ OS << "user-defined conversion via " << S->Function.Function;
+ break;
+
+ case SK_QualificationConversionRValue:
+ OS << "qualification conversion (rvalue)";
+
+ case SK_QualificationConversionXValue:
+ OS << "qualification conversion (xvalue)";
+
+ case SK_QualificationConversionLValue:
+ OS << "qualification conversion (lvalue)";
+ break;
+
+ case SK_ConversionSequence:
+ OS << "implicit conversion sequence (";
+ S->ICS->DebugPrint(); // FIXME: use OS
+ OS << ")";
+ break;
+
+ case SK_ListInitialization:
+ OS << "list initialization";
+ break;
+
+ case SK_ConstructorInitialization:
+ OS << "constructor initialization";
+ break;
+
+ case SK_ZeroInitialization:
+ OS << "zero initialization";
+ break;
+
+ case SK_CAssignment:
+ OS << "C assignment";
+ break;
+
+ case SK_StringInit:
+ OS << "string initialization";
+ break;
+
+ case SK_ObjCObjectConversion:
+ OS << "Objective-C object conversion";
+ break;
+ }
+ }
+}
+
+void InitializationSequence::dump() const {
+ dump(llvm::errs());
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization helper functions
+//===----------------------------------------------------------------------===//
+ExprResult
+Sema::PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init) {
+ if (Init.isInvalid())
+ return ExprError();
+
+ Expr *InitE = Init.get();
+ assert(InitE && "No initialization expression?");
+
+ if (EqualLoc.isInvalid())
+ EqualLoc = InitE->getLocStart();
+
+ InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
+ EqualLoc);
+ InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
+ Init.release();
+ return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
new file mode 100644
index 0000000..0fd0e08
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -0,0 +1,3379 @@
+//===--------------------- SemaLookup.cpp - Name Lookup ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements name lookup for C, C++, Objective-C, and
+// Objective-C++.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <limits>
+#include <list>
+#include <set>
+#include <vector>
+#include <iterator>
+#include <utility>
+#include <algorithm>
+
+using namespace clang;
+using namespace sema;
+
+namespace {
+ class UnqualUsingEntry {
+ const DeclContext *Nominated;
+ const DeclContext *CommonAncestor;
+
+ public:
+ UnqualUsingEntry(const DeclContext *Nominated,
+ const DeclContext *CommonAncestor)
+ : Nominated(Nominated), CommonAncestor(CommonAncestor) {
+ }
+
+ const DeclContext *getCommonAncestor() const {
+ return CommonAncestor;
+ }
+
+ const DeclContext *getNominatedNamespace() const {
+ return Nominated;
+ }
+
+ // Sort by the pointer value of the common ancestor.
+ struct Comparator {
+ bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) {
+ return L.getCommonAncestor() < R.getCommonAncestor();
+ }
+
+ bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) {
+ return E.getCommonAncestor() < DC;
+ }
+
+ bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) {
+ return DC < E.getCommonAncestor();
+ }
+ };
+ };
+
+ /// A collection of using directives, as used by C++ unqualified
+ /// lookup.
+ class UnqualUsingDirectiveSet {
+ typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy;
+
+ ListTy list;
+ llvm::SmallPtrSet<DeclContext*, 8> visited;
+
+ public:
+ UnqualUsingDirectiveSet() {}
+
+ void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
+ // C++ [namespace.udir]p1:
+ // During unqualified name lookup, the names appear as if they
+ // were declared in the nearest enclosing namespace which contains
+ // both the using-directive and the nominated namespace.
+ DeclContext *InnermostFileDC
+ = static_cast<DeclContext*>(InnermostFileScope->getEntity());
+ assert(InnermostFileDC && InnermostFileDC->isFileContext());
+
+ for (; S; S = S->getParent()) {
+ if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
+ DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
+ visit(Ctx, EffectiveDC);
+ } else {
+ Scope::udir_iterator I = S->using_directives_begin(),
+ End = S->using_directives_end();
+
+ for (; I != End; ++I)
+ visit(*I, InnermostFileDC);
+ }
+ }
+ }
+
+ // Visits a context and collect all of its using directives
+ // recursively. Treats all using directives as if they were
+ // declared in the context.
+ //
+ // A given context is only every visited once, so it is important
+ // that contexts be visited from the inside out in order to get
+ // the effective DCs right.
+ void visit(DeclContext *DC, DeclContext *EffectiveDC) {
+ if (!visited.insert(DC))
+ return;
+
+ addUsingDirectives(DC, EffectiveDC);
+ }
+
+ // Visits a using directive and collects all of its using
+ // directives recursively. Treats all using directives as if they
+ // were declared in the effective DC.
+ void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+ DeclContext *NS = UD->getNominatedNamespace();
+ if (!visited.insert(NS))
+ return;
+
+ addUsingDirective(UD, EffectiveDC);
+ addUsingDirectives(NS, EffectiveDC);
+ }
+
+ // Adds all the using directives in a context (and those nominated
+ // by its using directives, transitively) as if they appeared in
+ // the given effective context.
+ void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
+ llvm::SmallVector<DeclContext*,4> queue;
+ while (true) {
+ DeclContext::udir_iterator I, End;
+ for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
+ UsingDirectiveDecl *UD = *I;
+ DeclContext *NS = UD->getNominatedNamespace();
+ if (visited.insert(NS)) {
+ addUsingDirective(UD, EffectiveDC);
+ queue.push_back(NS);
+ }
+ }
+
+ if (queue.empty())
+ return;
+
+ DC = queue.back();
+ queue.pop_back();
+ }
+ }
+
+ // Add a using directive as if it had been declared in the given
+ // context. This helps implement C++ [namespace.udir]p3:
+ // The using-directive is transitive: if a scope contains a
+ // using-directive that nominates a second namespace that itself
+ // contains using-directives, the effect is as if the
+ // using-directives from the second namespace also appeared in
+ // the first.
+ void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
+ // Find the common ancestor between the effective context and
+ // the nominated namespace.
+ DeclContext *Common = UD->getNominatedNamespace();
+ while (!Common->Encloses(EffectiveDC))
+ Common = Common->getParent();
+ Common = Common->getPrimaryContext();
+
+ list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
+ }
+
+ void done() {
+ std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
+ }
+
+ typedef ListTy::const_iterator const_iterator;
+
+ const_iterator begin() const { return list.begin(); }
+ const_iterator end() const { return list.end(); }
+
+ std::pair<const_iterator,const_iterator>
+ getNamespacesFor(DeclContext *DC) const {
+ return std::equal_range(begin(), end(), DC->getPrimaryContext(),
+ UnqualUsingEntry::Comparator());
+ }
+ };
+}
+
+// Retrieve the set of identifier namespaces that correspond to a
+// specific kind of name lookup.
+static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
+ bool CPlusPlus,
+ bool Redeclaration) {
+ unsigned IDNS = 0;
+ switch (NameKind) {
+ case Sema::LookupOrdinaryName:
+ case Sema::LookupRedeclarationWithLinkage:
+ IDNS = Decl::IDNS_Ordinary;
+ if (CPlusPlus) {
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
+ if (Redeclaration)
+ IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+ }
+ break;
+
+ case Sema::LookupOperatorName:
+ // Operator lookup is its own crazy thing; it is not the same
+ // as (e.g.) looking up an operator name for redeclaration.
+ assert(!Redeclaration && "cannot do redeclaration operator lookup");
+ IDNS = Decl::IDNS_NonMemberOperator;
+ break;
+
+ case Sema::LookupTagName:
+ if (CPlusPlus) {
+ IDNS = Decl::IDNS_Type;
+
+ // When looking for a redeclaration of a tag name, we add:
+ // 1) TagFriend to find undeclared friend decls
+ // 2) Namespace because they can't "overload" with tag decls.
+ // 3) Tag because it includes class templates, which can't
+ // "overload" with tag decls.
+ if (Redeclaration)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace;
+ } else {
+ IDNS = Decl::IDNS_Tag;
+ }
+ break;
+ case Sema::LookupLabel:
+ IDNS = Decl::IDNS_Label;
+ break;
+
+ case Sema::LookupMemberName:
+ IDNS = Decl::IDNS_Member;
+ if (CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
+ break;
+
+ case Sema::LookupNestedNameSpecifierName:
+ IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace;
+ break;
+
+ case Sema::LookupNamespaceName:
+ IDNS = Decl::IDNS_Namespace;
+ break;
+
+ case Sema::LookupUsingDeclName:
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
+ | Decl::IDNS_Member | Decl::IDNS_Using;
+ break;
+
+ case Sema::LookupObjCProtocolName:
+ IDNS = Decl::IDNS_ObjCProtocol;
+ break;
+
+ case Sema::LookupAnyName:
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member
+ | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
+ | Decl::IDNS_Type;
+ break;
+ }
+ return IDNS;
+}
+
+void LookupResult::configure() {
+ IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus,
+ isForRedeclaration());
+
+ // If we're looking for one of the allocation or deallocation
+ // operators, make sure that the implicitly-declared new and delete
+ // operators can be found.
+ if (!isForRedeclaration()) {
+ switch (NameInfo.getName().getCXXOverloadedOperator()) {
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ SemaRef.DeclareGlobalNewDelete();
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void LookupResult::sanity() const {
+ assert(ResultKind != NotFound || Decls.size() == 0);
+ assert(ResultKind != Found || Decls.size() == 1);
+ assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
+ (Decls.size() == 1 &&
+ isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
+ assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
+ assert(ResultKind != Ambiguous || Decls.size() > 1 ||
+ (Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects ||
+ Ambiguity == AmbiguousBaseSubobjectTypes)));
+ assert((Paths != NULL) == (ResultKind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
+}
+
+// Necessary because CXXBasePaths is not complete in Sema.h
+void LookupResult::deletePaths(CXXBasePaths *Paths) {
+ delete Paths;
+}
+
+/// Resolves the result kind of this lookup.
+void LookupResult::resolveKind() {
+ unsigned N = Decls.size();
+
+ // Fast case: no possible ambiguity.
+ if (N == 0) {
+ assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
+ return;
+ }
+
+ // If there's a single decl, we need to examine it to decide what
+ // kind of lookup this is.
+ if (N == 1) {
+ NamedDecl *D = (*Decls.begin())->getUnderlyingDecl();
+ if (isa<FunctionTemplateDecl>(D))
+ ResultKind = FoundOverloaded;
+ else if (isa<UnresolvedUsingValueDecl>(D))
+ ResultKind = FoundUnresolvedValue;
+ return;
+ }
+
+ // Don't do any extra resolution if we've already resolved as ambiguous.
+ if (ResultKind == Ambiguous) return;
+
+ llvm::SmallPtrSet<NamedDecl*, 16> Unique;
+ llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+
+ bool Ambiguous = false;
+ bool HasTag = false, HasFunction = false, HasNonFunction = false;
+ bool HasFunctionTemplate = false, HasUnresolved = false;
+
+ unsigned UniqueTagIndex = 0;
+
+ unsigned I = 0;
+ while (I < N) {
+ NamedDecl *D = Decls[I]->getUnderlyingDecl();
+ D = cast<NamedDecl>(D->getCanonicalDecl());
+
+ // Redeclarations of types via typedef can occur both within a scope
+ // and, through using declarations and directives, across scopes. There is
+ // no ambiguity if they all refer to the same type, so unique based on the
+ // canonical type.
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+ if (!TD->getDeclContext()->isRecord()) {
+ QualType T = SemaRef.Context.getTypeDeclType(TD);
+ if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) {
+ // The type is not unique; pull something off the back and continue
+ // at this index.
+ Decls[I] = Decls[--N];
+ continue;
+ }
+ }
+ }
+
+ if (!Unique.insert(D)) {
+ // If it's not unique, pull something off the back (and
+ // continue at this index).
+ Decls[I] = Decls[--N];
+ continue;
+ }
+
+ // Otherwise, do some decl type analysis and then continue.
+
+ if (isa<UnresolvedUsingValueDecl>(D)) {
+ HasUnresolved = true;
+ } else if (isa<TagDecl>(D)) {
+ if (HasTag)
+ Ambiguous = true;
+ UniqueTagIndex = I;
+ HasTag = true;
+ } else if (isa<FunctionTemplateDecl>(D)) {
+ HasFunction = true;
+ HasFunctionTemplate = true;
+ } else if (isa<FunctionDecl>(D)) {
+ HasFunction = true;
+ } else {
+ if (HasNonFunction)
+ Ambiguous = true;
+ HasNonFunction = true;
+ }
+ I++;
+ }
+
+ // C++ [basic.scope.hiding]p2:
+ // A class name or enumeration name can be hidden by the name of
+ // an object, function, or enumerator declared in the same
+ // scope. If a class or enumeration name and an object, function,
+ // or enumerator are declared in the same scope (in any order)
+ // with the same name, the class or enumeration name is hidden
+ // wherever the object, function, or enumerator name is visible.
+ // But it's still an error if there are distinct tag types found,
+ // even if they're not visible. (ref?)
+ if (HideTags && HasTag && !Ambiguous &&
+ (HasFunction || HasNonFunction || HasUnresolved)) {
+ if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals(
+ Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext()))
+ Decls[UniqueTagIndex] = Decls[--N];
+ else
+ Ambiguous = true;
+ }
+
+ Decls.set_size(N);
+
+ if (HasNonFunction && (HasFunction || HasUnresolved))
+ Ambiguous = true;
+
+ if (Ambiguous)
+ setAmbiguous(LookupResult::AmbiguousReference);
+ else if (HasUnresolved)
+ ResultKind = LookupResult::FoundUnresolvedValue;
+ else if (N > 1 || HasFunctionTemplate)
+ ResultKind = LookupResult::FoundOverloaded;
+ else
+ ResultKind = LookupResult::Found;
+}
+
+void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
+ CXXBasePaths::const_paths_iterator I, E;
+ DeclContext::lookup_iterator DI, DE;
+ for (I = P.begin(), E = P.end(); I != E; ++I)
+ for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
+ addDecl(*DI);
+}
+
+void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
+ Paths = new CXXBasePaths;
+ Paths->swap(P);
+ addDeclsFromBasePaths(*Paths);
+ resolveKind();
+ setAmbiguous(AmbiguousBaseSubobjects);
+}
+
+void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
+ Paths = new CXXBasePaths;
+ Paths->swap(P);
+ addDeclsFromBasePaths(*Paths);
+ resolveKind();
+ setAmbiguous(AmbiguousBaseSubobjectTypes);
+}
+
+void LookupResult::print(llvm::raw_ostream &Out) {
+ Out << Decls.size() << " result(s)";
+ if (isAmbiguous()) Out << ", ambiguous";
+ if (Paths) Out << ", base paths present";
+
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ Out << "\n";
+ (*I)->print(Out, 2);
+ }
+}
+
+/// \brief Lookup a builtin function, when name lookup would otherwise
+/// fail.
+static bool LookupBuiltin(Sema &S, LookupResult &R) {
+ Sema::LookupNameKind NameKind = R.getLookupKind();
+
+ // If we didn't find a use of this identifier, and if the identifier
+ // corresponds to a compiler builtin, create the decl object for the builtin
+ // now, injecting it into translation unit scope, and return it.
+ if (NameKind == Sema::LookupOrdinaryName ||
+ NameKind == Sema::LookupRedeclarationWithLinkage) {
+ IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
+ if (II) {
+ // If this is a builtin on this (or all) targets, create the decl.
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ // In C++, we don't have any predefined library functions like
+ // 'malloc'. Instead, we'll just error.
+ if (S.getLangOptions().CPlusPlus &&
+ S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return false;
+
+ if (NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II,
+ BuiltinID, S.TUScope,
+ R.isForRedeclaration(),
+ R.getNameLoc())) {
+ R.addDecl(D);
+ return true;
+ }
+
+ if (R.isForRedeclaration()) {
+ // If we're redeclaring this function anyway, forget that
+ // this was a builtin at all.
+ S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents);
+ }
+
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
+/// \brief Determine whether we can declare a special member function within
+/// the class at this point.
+static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
+ const CXXRecordDecl *Class) {
+ // Don't do it if the class is invalid.
+ if (Class->isInvalidDecl())
+ return false;
+
+ // We need to have a definition for the class.
+ if (!Class->getDefinition() || Class->isDependentContext())
+ return false;
+
+ // We can't be in the middle of defining the class.
+ if (const RecordType *RecordTy
+ = Context.getTypeDeclType(Class)->getAs<RecordType>())
+ return !RecordTy->isBeingDefined();
+
+ return false;
+}
+
+void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+ if (!CanDeclareSpecialMemberFunction(Context, Class))
+ return;
+
+ // If the default constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
+
+ // If the copy constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+
+ // If the copy assignment operator has not yet been declared, do so now.
+ if (!Class->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(Class);
+
+ // If the destructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+}
+
+/// \brief Determine whether this is the name of an implicitly-declared
+/// special member function.
+static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ return true;
+
+ case DeclarationName::CXXOperatorName:
+ return Name.getCXXOverloadedOperator() == OO_Equal;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/// \brief If there are any implicit member functions with the given name
+/// that need to be declared in the given declaration context, do so.
+static void DeclareImplicitMemberFunctionsWithName(Sema &S,
+ DeclarationName Name,
+ const DeclContext *DC) {
+ if (!DC)
+ return;
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record)) {
+ if (!Record->hasDeclaredDefaultConstructor())
+ S.DeclareImplicitDefaultConstructor(
+ const_cast<CXXRecordDecl *>(Record));
+ if (!Record->hasDeclaredCopyConstructor())
+ S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+ }
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ if (Name.getCXXOverloadedOperator() != OO_Equal)
+ break;
+
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredCopyAssignment() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitCopyAssignment(const_cast<CXXRecordDecl *>(Record));
+ break;
+
+ default:
+ break;
+ }
+}
+
+// Adds all qualifying matches for a name within a decl context to the
+// given lookup result. Returns true if any matches were found.
+static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
+ bool Found = false;
+
+ // Lazily declare C++ special member functions.
+ if (S.getLangOptions().CPlusPlus)
+ DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
+
+ // Perform lookup into this declaration context.
+ DeclContext::lookup_const_iterator I, E;
+ for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
+ NamedDecl *D = *I;
+ if (R.isAcceptableDecl(D)) {
+ R.addDecl(D);
+ Found = true;
+ }
+ }
+
+ if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R))
+ return true;
+
+ if (R.getLookupName().getNameKind()
+ != DeclarationName::CXXConversionFunctionName ||
+ R.getLookupName().getCXXNameType()->isDependentType() ||
+ !isa<CXXRecordDecl>(DC))
+ return Found;
+
+ // C++ [temp.mem]p6:
+ // A specialization of a conversion function template is not found by
+ // name lookup. Instead, any conversion function templates visible in the
+ // context of the use are considered. [...]
+ const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+ if (!Record->isDefinition())
+ return Found;
+
+ const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+ for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
+ UEnd = Unresolved->end(); U != UEnd; ++U) {
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+ if (!ConvTemplate)
+ continue;
+
+ // When we're performing lookup for the purposes of redeclaration, just
+ // add the conversion function template. When we deduce template
+ // arguments for specializations, we'll end up unifying the return
+ // type of the new declaration with the type of the function template.
+ if (R.isForRedeclaration()) {
+ R.addDecl(ConvTemplate);
+ Found = true;
+ continue;
+ }
+
+ // C++ [temp.mem]p6:
+ // [...] For each such operator, if argument deduction succeeds
+ // (14.9.2.3), the resulting specialization is used as if found by
+ // name lookup.
+ //
+ // When referencing a conversion function for any purpose other than
+ // a redeclaration (such that we'll be building an expression with the
+ // result), perform template argument deduction and place the
+ // specialization into the result set. We do this to avoid forcing all
+ // callers to perform special deduction for conversion functions.
+ TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+ FunctionDecl *Specialization = 0;
+
+ const FunctionProtoType *ConvProto
+ = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
+ assert(ConvProto && "Nonsensical conversion function template type");
+
+ // Compute the type of the function that we would expect the conversion
+ // function to have, if it were to match the name given.
+ // FIXME: Calling convention!
+ FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default);
+ EPI.HasExceptionSpec = false;
+ EPI.HasAnyExceptionSpec = false;
+ EPI.NumExceptions = 0;
+ QualType ExpectedType
+ = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
+ 0, 0, EPI);
+
+ // Perform template argument deduction against the type that we would
+ // expect the function to have.
+ if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+ Specialization, Info)
+ == Sema::TDK_Success) {
+ R.addDecl(Specialization);
+ Found = true;
+ }
+ }
+
+ return Found;
+}
+
+// Performs C++ unqualified lookup into the given file context.
+static bool
+CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
+ DeclContext *NS, UnqualUsingDirectiveSet &UDirs) {
+
+ assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
+
+ // Perform direct name lookup into the LookupCtx.
+ bool Found = LookupDirect(S, R, NS);
+
+ // Perform direct name lookup into the namespaces nominated by the
+ // using directives whose common ancestor is this namespace.
+ UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+ llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
+
+ for (; UI != UEnd; ++UI)
+ if (LookupDirect(S, R, UI->getNominatedNamespace()))
+ Found = true;
+
+ R.resolveKind();
+
+ return Found;
+}
+
+static bool isNamespaceOrTranslationUnitScope(Scope *S) {
+ if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+ return Ctx->isFileContext();
+ return false;
+}
+
+// Find the next outer declaration context from this scope. This
+// routine actually returns the semantic outer context, which may
+// differ from the lexical context (encoded directly in the Scope
+// stack) when we are parsing a member of a class template. In this
+// case, the second element of the pair will be true, to indicate that
+// name lookup should continue searching in this semantic context when
+// it leaves the current template parameter scope.
+static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
+ DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
+ DeclContext *Lexical = 0;
+ for (Scope *OuterS = S->getParent(); OuterS;
+ OuterS = OuterS->getParent()) {
+ if (OuterS->getEntity()) {
+ Lexical = static_cast<DeclContext *>(OuterS->getEntity());
+ break;
+ }
+ }
+
+ // C++ [temp.local]p8:
+ // In the definition of a member of a class template that appears
+ // outside of the namespace containing the class template
+ // definition, the name of a template-parameter hides the name of
+ // a member of this namespace.
+ //
+ // Example:
+ //
+ // namespace N {
+ // class C { };
+ //
+ // template<class T> class B {
+ // void f(T);
+ // };
+ // }
+ //
+ // template<class C> void N::B<C>::f(C) {
+ // C b; // C is the template parameter, not N::C
+ // }
+ //
+ // In this example, the lexical context we return is the
+ // TranslationUnit, while the semantic context is the namespace N.
+ if (!Lexical || !DC || !S->getParent() ||
+ !S->getParent()->isTemplateParamScope())
+ return std::make_pair(Lexical, false);
+
+ // Find the outermost template parameter scope.
+ // For the example, this is the scope for the template parameters of
+ // template<class C>.
+ Scope *OutermostTemplateScope = S->getParent();
+ while (OutermostTemplateScope->getParent() &&
+ OutermostTemplateScope->getParent()->isTemplateParamScope())
+ OutermostTemplateScope = OutermostTemplateScope->getParent();
+
+ // Find the namespace context in which the original scope occurs. In
+ // the example, this is namespace N.
+ DeclContext *Semantic = DC;
+ while (!Semantic->isFileContext())
+ Semantic = Semantic->getParent();
+
+ // Find the declaration context just outside of the template
+ // parameter scope. This is the context in which the template is
+ // being lexically declaration (a namespace context). In the
+ // example, this is the global scope.
+ if (Lexical->isFileContext() && !Lexical->Equals(Semantic) &&
+ Lexical->Encloses(Semantic))
+ return std::make_pair(Semantic, true);
+
+ return std::make_pair(Lexical, false);
+}
+
+bool Sema::CppLookupName(LookupResult &R, Scope *S) {
+ assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup");
+
+ DeclarationName Name = R.getLookupName();
+
+ // If this is the name of an implicitly-declared special member function,
+ // go through the scope stack to implicitly declare
+ if (isImplicitlyDeclaredMemberFunctionName(Name)) {
+ for (Scope *PreS = S; PreS; PreS = PreS->getParent())
+ if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity()))
+ DeclareImplicitMemberFunctionsWithName(*this, Name, DC);
+ }
+
+ // Implicitly declare member functions with the name we're looking for, if in
+ // fact we are in a scope where it matters.
+
+ Scope *Initial = S;
+ IdentifierResolver::iterator
+ I = IdResolver.begin(Name),
+ IEnd = IdResolver.end();
+
+ // First we lookup local scope.
+ // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
+ // ...During unqualified name lookup (3.4.1), the names appear as if
+ // they were declared in the nearest enclosing namespace which contains
+ // both the using-directive and the nominated namespace.
+ // [Note: in this context, "contains" means "contains directly or
+ // indirectly".
+ //
+ // For example:
+ // namespace A { int i; }
+ // void foo() {
+ // int i;
+ // {
+ // using namespace A;
+ // ++i; // finds local 'i', A::i appears at global scope
+ // }
+ // }
+ //
+ DeclContext *OutsideOfTemplateParamDC = 0;
+ for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
+ DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
+
+ // Check whether the IdResolver has anything in this scope.
+ bool Found = false;
+ for (; I != IEnd && S->isDeclScope(*I); ++I) {
+ if (R.isAcceptableDecl(*I)) {
+ Found = true;
+ R.addDecl(*I);
+ }
+ }
+ if (Found) {
+ R.resolveKind();
+ if (S->isClassScope())
+ if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
+ R.setNamingClass(Record);
+ return true;
+ }
+
+ if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+ S->getParent() && !S->getParent()->isTemplateParamScope()) {
+ // We've just searched the last template parameter scope and
+ // found nothing, so look into the the contexts between the
+ // lexical and semantic declaration contexts returned by
+ // findOuterContext(). This implements the name lookup behavior
+ // of C++ [temp.local]p8.
+ Ctx = OutsideOfTemplateParamDC;
+ OutsideOfTemplateParamDC = 0;
+ }
+
+ if (Ctx) {
+ DeclContext *OuterCtx;
+ bool SearchAfterTemplateScope;
+ llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ if (SearchAfterTemplateScope)
+ OutsideOfTemplateParamDC = OuterCtx;
+
+ for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+ // We do not directly look into transparent contexts, since
+ // those entities will be found in the nearest enclosing
+ // non-transparent context.
+ if (Ctx->isTransparentContext())
+ continue;
+
+ // We do not look directly into function or method contexts,
+ // since all of the local variables and parameters of the
+ // function/method are present within the Scope.
+ if (Ctx->isFunctionOrMethod()) {
+ // If we have an Objective-C instance method, look for ivars
+ // in the corresponding interface.
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
+ if (Method->isInstanceMethod() && Name.getAsIdentifierInfo())
+ if (ObjCInterfaceDecl *Class = Method->getClassInterface()) {
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(
+ Name.getAsIdentifierInfo(),
+ ClassDeclared)) {
+ if (R.isAcceptableDecl(Ivar)) {
+ R.addDecl(Ivar);
+ R.resolveKind();
+ return true;
+ }
+ }
+ }
+ }
+
+ continue;
+ }
+
+ // Perform qualified name lookup into this context.
+ // FIXME: In some cases, we know that every name that could be found by
+ // this qualified name lookup will also be on the identifier chain. For
+ // example, inside a class without any base classes, we never need to
+ // perform qualified lookup because all of the members are on top of the
+ // identifier chain.
+ if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true))
+ return true;
+ }
+ }
+ }
+
+ // Stop if we ran out of scopes.
+ // FIXME: This really, really shouldn't be happening.
+ if (!S) return false;
+
+ // If we are looking for members, no need to look into global/namespace scope.
+ if (R.getLookupKind() == LookupMemberName)
+ return false;
+
+ // Collect UsingDirectiveDecls in all scopes, and recursively all
+ // nominated namespaces by those using-directives.
+ //
+ // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
+ // don't build it for each lookup!
+
+ UnqualUsingDirectiveSet UDirs;
+ UDirs.visitScopeChain(Initial, S);
+ UDirs.done();
+
+ // Lookup namespace scope, and global scope.
+ // Unqualified name lookup in C++ requires looking into scopes
+ // that aren't strictly lexical, and therefore we walk through the
+ // context as well as walking through the scopes.
+
+ for (; S; S = S->getParent()) {
+ // Check whether the IdResolver has anything in this scope.
+ bool Found = false;
+ for (; I != IEnd && S->isDeclScope(*I); ++I) {
+ if (R.isAcceptableDecl(*I)) {
+ // We found something. Look for anything else in our scope
+ // with this same name and in an acceptable identifier
+ // namespace, so that we can construct an overload set if we
+ // need to.
+ Found = true;
+ R.addDecl(*I);
+ }
+ }
+
+ if (Found && S->isTemplateParamScope()) {
+ R.resolveKind();
+ return true;
+ }
+
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+ S->getParent() && !S->getParent()->isTemplateParamScope()) {
+ // We've just searched the last template parameter scope and
+ // found nothing, so look into the the contexts between the
+ // lexical and semantic declaration contexts returned by
+ // findOuterContext(). This implements the name lookup behavior
+ // of C++ [temp.local]p8.
+ Ctx = OutsideOfTemplateParamDC;
+ OutsideOfTemplateParamDC = 0;
+ }
+
+ if (Ctx) {
+ DeclContext *OuterCtx;
+ bool SearchAfterTemplateScope;
+ llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+ if (SearchAfterTemplateScope)
+ OutsideOfTemplateParamDC = OuterCtx;
+
+ for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
+ // We do not directly look into transparent contexts, since
+ // those entities will be found in the nearest enclosing
+ // non-transparent context.
+ if (Ctx->isTransparentContext())
+ continue;
+
+ // If we have a context, and it's not a context stashed in the
+ // template parameter scope for an out-of-line definition, also
+ // look into that context.
+ if (!(Found && S && S->isTemplateParamScope())) {
+ assert(Ctx->isFileContext() &&
+ "We should have been looking only at file context here already.");
+
+ // Look into context considering using-directives.
+ if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+ Found = true;
+ }
+
+ if (Found) {
+ R.resolveKind();
+ return true;
+ }
+
+ if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+ return false;
+ }
+ }
+
+ if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
+ return false;
+ }
+
+ return !R.empty();
+}
+
+/// @brief Perform unqualified name lookup starting from a given
+/// scope.
+///
+/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
+/// used to find names within the current scope. For example, 'x' in
+/// @code
+/// int x;
+/// int f() {
+/// return x; // unqualified name look finds 'x' in the global scope
+/// }
+/// @endcode
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// @param S The scope from which unqualified name lookup will
+/// begin. If the lookup criteria permits, name lookup may also search
+/// in the parent scopes.
+///
+/// @param Name The name of the entity that we are searching for.
+///
+/// @param Loc If provided, the source location where we're performing
+/// name lookup. At present, this is only used to produce diagnostics when
+/// C library functions (like "malloc") are implicitly declared.
+///
+/// @returns The result of name lookup, which includes zero or more
+/// declarations and possibly additional information used to diagnose
+/// ambiguities.
+bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
+ DeclarationName Name = R.getLookupName();
+ if (!Name) return false;
+
+ LookupNameKind NameKind = R.getLookupKind();
+
+ if (!getLangOptions().CPlusPlus) {
+ // Unqualified name lookup in C/Objective-C is purely lexical, so
+ // search in the declarations attached to the name.
+ if (NameKind == Sema::LookupRedeclarationWithLinkage) {
+ // Find the nearest non-transparent declaration scope.
+ while (!(S->getFlags() & Scope::DeclScope) ||
+ (S->getEntity() &&
+ static_cast<DeclContext *>(S->getEntity())
+ ->isTransparentContext()))
+ S = S->getParent();
+ }
+
+ unsigned IDNS = R.getIdentifierNamespace();
+
+ // Scan up the scope chain looking for a decl that matches this
+ // identifier that is in the appropriate namespace. This search
+ // should not take long, as shadowing of names is uncommon, and
+ // deep shadowing is extremely uncommon.
+ bool LeftStartingScope = false;
+
+ for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+ IEnd = IdResolver.end();
+ I != IEnd; ++I)
+ if ((*I)->isInIdentifierNamespace(IDNS)) {
+ if (NameKind == LookupRedeclarationWithLinkage) {
+ // Determine whether this (or a previous) declaration is
+ // out-of-scope.
+ if (!LeftStartingScope && !S->isDeclScope(*I))
+ LeftStartingScope = true;
+
+ // If we found something outside of our starting scope that
+ // does not have linkage, skip it.
+ if (LeftStartingScope && !((*I)->hasLinkage()))
+ continue;
+ }
+
+ R.addDecl(*I);
+
+ if ((*I)->getAttr<OverloadableAttr>()) {
+ // If this declaration has the "overloadable" attribute, we
+ // might have a set of overloaded functions.
+
+ // Figure out what scope the identifier is in.
+ while (!(S->getFlags() & Scope::DeclScope) ||
+ !S->isDeclScope(*I))
+ S = S->getParent();
+
+ // Find the last declaration in this scope (with the same
+ // name, naturally).
+ IdentifierResolver::iterator LastI = I;
+ for (++LastI; LastI != IEnd; ++LastI) {
+ if (!S->isDeclScope(*LastI))
+ break;
+ R.addDecl(*LastI);
+ }
+ }
+
+ R.resolveKind();
+
+ return true;
+ }
+ } else {
+ // Perform C++ unqualified name lookup.
+ if (CppLookupName(R, S))
+ return true;
+ }
+
+ // If we didn't find a use of this identifier, and if the identifier
+ // corresponds to a compiler builtin, create the decl object for the builtin
+ // now, injecting it into translation unit scope, and return it.
+ if (AllowBuiltinCreation)
+ return LookupBuiltin(*this, R);
+
+ return false;
+}
+
+/// @brief Perform qualified name lookup in the namespaces nominated by
+/// using directives by the given context.
+///
+/// C++98 [namespace.qual]p2:
+/// Given X::m (where X is a user-declared namespace), or given ::m
+/// (where X is the global namespace), let S be the set of all
+/// declarations of m in X and in the transitive closure of all
+/// namespaces nominated by using-directives in X and its used
+/// namespaces, except that using-directives are ignored in any
+/// namespace, including X, directly containing one or more
+/// declarations of m. No namespace is searched more than once in
+/// the lookup of a name. If S is the empty set, the program is
+/// ill-formed. Otherwise, if S has exactly one member, or if the
+/// context of the reference is a using-declaration
+/// (namespace.udecl), S is the required set of declarations of
+/// m. Otherwise if the use of m is not one that allows a unique
+/// declaration to be chosen from S, the program is ill-formed.
+/// C++98 [namespace.qual]p5:
+/// During the lookup of a qualified namespace member name, if the
+/// lookup finds more than one declaration of the member, and if one
+/// declaration introduces a class name or enumeration name and the
+/// other declarations either introduce the same object, the same
+/// enumerator or a set of functions, the non-type name hides the
+/// class or enumeration name if and only if the declarations are
+/// from the same namespace; otherwise (the declarations are from
+/// different namespaces), the program is ill-formed.
+static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
+ DeclContext *StartDC) {
+ assert(StartDC->isFileContext() && "start context is not a file context");
+
+ DeclContext::udir_iterator I = StartDC->using_directives_begin();
+ DeclContext::udir_iterator E = StartDC->using_directives_end();
+
+ if (I == E) return false;
+
+ // We have at least added all these contexts to the queue.
+ llvm::DenseSet<DeclContext*> Visited;
+ Visited.insert(StartDC);
+
+ // We have not yet looked into these namespaces, much less added
+ // their "using-children" to the queue.
+ llvm::SmallVector<NamespaceDecl*, 8> Queue;
+
+ // We have already looked into the initial namespace; seed the queue
+ // with its using-children.
+ for (; I != E; ++I) {
+ NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
+ if (Visited.insert(ND).second)
+ Queue.push_back(ND);
+ }
+
+ // The easiest way to implement the restriction in [namespace.qual]p5
+ // is to check whether any of the individual results found a tag
+ // and, if so, to declare an ambiguity if the final result is not
+ // a tag.
+ bool FoundTag = false;
+ bool FoundNonTag = false;
+
+ LookupResult LocalR(LookupResult::Temporary, R);
+
+ bool Found = false;
+ while (!Queue.empty()) {
+ NamespaceDecl *ND = Queue.back();
+ Queue.pop_back();
+
+ // We go through some convolutions here to avoid copying results
+ // between LookupResults.
+ bool UseLocal = !R.empty();
+ LookupResult &DirectR = UseLocal ? LocalR : R;
+ bool FoundDirect = LookupDirect(S, DirectR, ND);
+
+ if (FoundDirect) {
+ // First do any local hiding.
+ DirectR.resolveKind();
+
+ // If the local result is a tag, remember that.
+ if (DirectR.isSingleTagDecl())
+ FoundTag = true;
+ else
+ FoundNonTag = true;
+
+ // Append the local results to the total results if necessary.
+ if (UseLocal) {
+ R.addAllDecls(LocalR);
+ LocalR.clear();
+ }
+ }
+
+ // If we find names in this namespace, ignore its using directives.
+ if (FoundDirect) {
+ Found = true;
+ continue;
+ }
+
+ for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
+ NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+ if (Visited.insert(Nom).second)
+ Queue.push_back(Nom);
+ }
+ }
+
+ if (Found) {
+ if (FoundTag && FoundNonTag)
+ R.setAmbiguousQualifiedTagHiding();
+ else
+ R.resolveKind();
+ }
+
+ return Found;
+}
+
+/// \brief Callback that looks for any member of a class with the given name.
+static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+ Path.Decls = BaseRecord->lookup(N);
+ return Path.Decls.first != Path.Decls.second;
+}
+
+/// \brief Determine whether the given set of member declarations contains only
+/// static members, nested types, and enumerators.
+template<typename InputIterator>
+static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) {
+ Decl *D = (*First)->getUnderlyingDecl();
+ if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D))
+ return true;
+
+ if (isa<CXXMethodDecl>(D)) {
+ // Determine whether all of the methods are static.
+ bool AllMethodsAreStatic = true;
+ for(; First != Last; ++First) {
+ D = (*First)->getUnderlyingDecl();
+
+ if (!isa<CXXMethodDecl>(D)) {
+ assert(isa<TagDecl>(D) && "Non-function must be a tag decl");
+ break;
+ }
+
+ if (!cast<CXXMethodDecl>(D)->isStatic()) {
+ AllMethodsAreStatic = false;
+ break;
+ }
+ }
+
+ if (AllMethodsAreStatic)
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Perform qualified name lookup into a given context.
+///
+/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
+/// names when the context of those names is explicit specified, e.g.,
+/// "std::vector" or "x->member", or as part of unqualified name lookup.
+///
+/// Different lookup criteria can find different names. For example, a
+/// particular scope can have both a struct and a function of the same
+/// name, and each can be found by certain lookup criteria. For more
+/// information about lookup criteria, see the documentation for the
+/// class LookupCriteria.
+///
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param LookupCtx The context in which qualified name lookup will
+/// search. If the lookup criteria permits, name lookup may also search
+/// in the parent contexts or (for C++ classes) base classes.
+///
+/// \param InUnqualifiedLookup true if this is qualified name lookup that
+/// occurs as part of unqualified name lookup.
+///
+/// \returns true if lookup succeeded, false if it failed.
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+ bool InUnqualifiedLookup) {
+ assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
+
+ if (!R.getLookupName())
+ return false;
+
+ // Make sure that the declaration context is complete.
+ assert((!isa<TagDecl>(LookupCtx) ||
+ LookupCtx->isDependentContext() ||
+ cast<TagDecl>(LookupCtx)->isDefinition() ||
+ Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>()
+ ->isBeingDefined()) &&
+ "Declaration context must already be complete!");
+
+ // Perform qualified name lookup into the LookupCtx.
+ if (LookupDirect(*this, R, LookupCtx)) {
+ R.resolveKind();
+ if (isa<CXXRecordDecl>(LookupCtx))
+ R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
+ return true;
+ }
+
+ // Don't descend into implied contexts for redeclarations.
+ // C++98 [namespace.qual]p6:
+ // In a declaration for a namespace member in which the
+ // declarator-id is a qualified-id, given that the qualified-id
+ // for the namespace member has the form
+ // nested-name-specifier unqualified-id
+ // the unqualified-id shall name a member of the namespace
+ // designated by the nested-name-specifier.
+ // See also [class.mfct]p5 and [class.static.data]p2.
+ if (R.isForRedeclaration())
+ return false;
+
+ // If this is a namespace, look it up in the implied namespaces.
+ if (LookupCtx->isFileContext())
+ return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx);
+
+ // If this isn't a C++ class, we aren't allowed to look into base
+ // classes, we're done.
+ CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
+ if (!LookupRec || !LookupRec->getDefinition())
+ return false;
+
+ // If we're performing qualified name lookup into a dependent class,
+ // then we are actually looking into a current instantiation. If we have any
+ // dependent base classes, then we either have to delay lookup until
+ // template instantiation time (at which point all bases will be available)
+ // or we have to fail.
+ if (!InUnqualifiedLookup && LookupRec->isDependentContext() &&
+ LookupRec->hasAnyDependentBases()) {
+ R.setNotFoundInCurrentInstantiation();
+ return false;
+ }
+
+ // Perform lookup into our base classes.
+ CXXBasePaths Paths;
+ Paths.setOrigin(LookupRec);
+
+ // Look for this member in our base classes
+ CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
+ switch (R.getLookupKind()) {
+ case LookupOrdinaryName:
+ case LookupMemberName:
+ case LookupRedeclarationWithLinkage:
+ BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
+ break;
+
+ case LookupTagName:
+ BaseCallback = &CXXRecordDecl::FindTagMember;
+ break;
+
+ case LookupAnyName:
+ BaseCallback = &LookupAnyMember;
+ break;
+
+ case LookupUsingDeclName:
+ // This lookup is for redeclarations only.
+
+ case LookupOperatorName:
+ case LookupNamespaceName:
+ case LookupObjCProtocolName:
+ case LookupLabel:
+ // These lookups will never find a member in a C++ class (or base class).
+ return false;
+
+ case LookupNestedNameSpecifierName:
+ BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember;
+ break;
+ }
+
+ if (!LookupRec->lookupInBases(BaseCallback,
+ R.getLookupName().getAsOpaquePtr(), Paths))
+ return false;
+
+ R.setNamingClass(LookupRec);
+
+ // C++ [class.member.lookup]p2:
+ // [...] If the resulting set of declarations are not all from
+ // sub-objects of the same type, or the set has a nonstatic member
+ // and includes members from distinct sub-objects, there is an
+ // ambiguity and the program is ill-formed. Otherwise that set is
+ // the result of the lookup.
+ QualType SubobjectType;
+ int SubobjectNumber = 0;
+ AccessSpecifier SubobjectAccess = AS_none;
+
+ for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
+ Path != PathEnd; ++Path) {
+ const CXXBasePathElement &PathElement = Path->back();
+
+ // Pick the best (i.e. most permissive i.e. numerically lowest) access
+ // across all paths.
+ SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+
+ // Determine whether we're looking at a distinct sub-object or not.
+ if (SubobjectType.isNull()) {
+ // This is the first subobject we've looked at. Record its type.
+ SubobjectType = Context.getCanonicalType(PathElement.Base->getType());
+ SubobjectNumber = PathElement.SubobjectNumber;
+ continue;
+ }
+
+ if (SubobjectType
+ != Context.getCanonicalType(PathElement.Base->getType())) {
+ // We found members of the given name in two subobjects of
+ // different types. If the declaration sets aren't the same, this
+ // this lookup is ambiguous.
+ if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) {
+ CXXBasePaths::paths_iterator FirstPath = Paths.begin();
+ DeclContext::lookup_iterator FirstD = FirstPath->Decls.first;
+ DeclContext::lookup_iterator CurrentD = Path->Decls.first;
+
+ while (FirstD != FirstPath->Decls.second &&
+ CurrentD != Path->Decls.second) {
+ if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() !=
+ (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl())
+ break;
+
+ ++FirstD;
+ ++CurrentD;
+ }
+
+ if (FirstD == FirstPath->Decls.second &&
+ CurrentD == Path->Decls.second)
+ continue;
+ }
+
+ R.setAmbiguousBaseSubobjectTypes(Paths);
+ return true;
+ }
+
+ if (SubobjectNumber != PathElement.SubobjectNumber) {
+ // We have a different subobject of the same type.
+
+ // C++ [class.member.lookup]p5:
+ // A static member, a nested type or an enumerator defined in
+ // a base class T can unambiguously be found even if an object
+ // has more than one base class subobject of type T.
+ if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second))
+ continue;
+
+ // We have found a nonstatic member name in multiple, distinct
+ // subobjects. Name lookup is ambiguous.
+ R.setAmbiguousBaseSubobjects(Paths);
+ return true;
+ }
+ }
+
+ // Lookup in a base class succeeded; return these results.
+
+ DeclContext::lookup_iterator I, E;
+ for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) {
+ NamedDecl *D = *I;
+ AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
+ D->getAccess());
+ R.addDecl(D, AS);
+ }
+ R.resolveKind();
+ return true;
+}
+
+/// @brief Performs name lookup for a name that was parsed in the
+/// source code, and may contain a C++ scope specifier.
+///
+/// This routine is a convenience routine meant to be called from
+/// contexts that receive a name and an optional C++ scope specifier
+/// (e.g., "N::M::x"). It will then perform either qualified or
+/// unqualified name lookup (with LookupQualifiedName or LookupName,
+/// respectively) on the given name and return those results.
+///
+/// @param S The scope from which unqualified name lookup will
+/// begin.
+///
+/// @param SS An optional C++ scope-specifier, e.g., "::N::M".
+///
+/// @param EnteringContext Indicates whether we are going to enter the
+/// context of the scope-specifier SS (if present).
+///
+/// @returns True if any decls were found (but possibly ambiguous)
+bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ bool AllowBuiltinCreation, bool EnteringContext) {
+ if (SS && SS->isInvalid()) {
+ // When the scope specifier is invalid, don't even look for
+ // anything.
+ return false;
+ }
+
+ if (SS && SS->isSet()) {
+ if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) {
+ // We have resolved the scope specifier to a particular declaration
+ // contex, and will perform name lookup in that context.
+ if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC))
+ return false;
+
+ R.setContextRange(SS->getRange());
+
+ return LookupQualifiedName(R, DC);
+ }
+
+ // We could not resolve the scope specified to a specific declaration
+ // context, which means that SS refers to an unknown specialization.
+ // Name lookup can't find anything in this case.
+ return false;
+ }
+
+ // Perform unqualified name lookup starting in the given scope.
+ return LookupName(R, S, AllowBuiltinCreation);
+}
+
+
+/// @brief Produce a diagnostic describing the ambiguity that resulted
+/// from name lookup.
+///
+/// @param Result The ambiguous name lookup result.
+///
+/// @param Name The name of the entity that name lookup was
+/// searching for.
+///
+/// @param NameLoc The location of the name within the source code.
+///
+/// @param LookupRange A source range that provides more
+/// source-location information concerning the lookup itself. For
+/// example, this range might highlight a nested-name-specifier that
+/// precedes the name.
+///
+/// @returns true
+bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
+ assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
+
+ DeclarationName Name = Result.getLookupName();
+ SourceLocation NameLoc = Result.getNameLoc();
+ SourceRange LookupRange = Result.getContextRange();
+
+ switch (Result.getAmbiguityKind()) {
+ case LookupResult::AmbiguousBaseSubobjects: {
+ CXXBasePaths *Paths = Result.getBasePaths();
+ QualType SubobjectType = Paths->front().back().Base->getType();
+ Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
+ << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
+ << LookupRange;
+
+ DeclContext::lookup_iterator Found = Paths->front().Decls.first;
+ while (isa<CXXMethodDecl>(*Found) &&
+ cast<CXXMethodDecl>(*Found)->isStatic())
+ ++Found;
+
+ Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
+
+ return true;
+ }
+
+ case LookupResult::AmbiguousBaseSubobjectTypes: {
+ Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
+ << Name << LookupRange;
+
+ CXXBasePaths *Paths = Result.getBasePaths();
+ std::set<Decl *> DeclsPrinted;
+ for (CXXBasePaths::paths_iterator Path = Paths->begin(),
+ PathEnd = Paths->end();
+ Path != PathEnd; ++Path) {
+ Decl *D = *Path->Decls.first;
+ if (DeclsPrinted.insert(D).second)
+ Diag(D->getLocation(), diag::note_ambiguous_member_found);
+ }
+
+ return true;
+ }
+
+ case LookupResult::AmbiguousTagHiding: {
+ Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
+
+ llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+
+ LookupResult::iterator DI, DE = Result.end();
+ for (DI = Result.begin(); DI != DE; ++DI)
+ if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
+ TagDecls.insert(TD);
+ Diag(TD->getLocation(), diag::note_hidden_tag);
+ }
+
+ for (DI = Result.begin(); DI != DE; ++DI)
+ if (!isa<TagDecl>(*DI))
+ Diag((*DI)->getLocation(), diag::note_hiding_object);
+
+ // For recovery purposes, go ahead and implement the hiding.
+ LookupResult::Filter F = Result.makeFilter();
+ while (F.hasNext()) {
+ if (TagDecls.count(F.next()))
+ F.erase();
+ }
+ F.done();
+
+ return true;
+ }
+
+ case LookupResult::AmbiguousReference: {
+ Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
+
+ LookupResult::iterator DI = Result.begin(), DE = Result.end();
+ for (; DI != DE; ++DI)
+ Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+
+ return true;
+ }
+ }
+
+ llvm_unreachable("unknown ambiguity kind");
+ return true;
+}
+
+namespace {
+ struct AssociatedLookup {
+ AssociatedLookup(Sema &S,
+ Sema::AssociatedNamespaceSet &Namespaces,
+ Sema::AssociatedClassSet &Classes)
+ : S(S), Namespaces(Namespaces), Classes(Classes) {
+ }
+
+ Sema &S;
+ Sema::AssociatedNamespaceSet &Namespaces;
+ Sema::AssociatedClassSet &Classes;
+ };
+}
+
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
+
+static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
+ DeclContext *Ctx) {
+ // Add the associated namespace for this class.
+
+ // We don't use DeclContext::getEnclosingNamespaceContext() as this may
+ // be a locally scoped record.
+
+ // We skip out of inline namespaces. The innermost non-inline namespace
+ // contains all names of all its nested inline namespaces anyway, so we can
+ // replace the entire inline namespace tree with its root.
+ while (Ctx->isRecord() || Ctx->isTransparentContext() ||
+ Ctx->isInlineNamespace())
+ Ctx = Ctx->getParent();
+
+ if (Ctx->isFileContext())
+ Namespaces.insert(Ctx->getPrimaryContext());
+}
+
+// \brief Add the associated classes and namespaces for argument-dependent
+// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+ const TemplateArgument &Arg) {
+ // C++ [basic.lookup.koenig]p2, last bullet:
+ // -- [...] ;
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Type:
+ // [...] the namespaces and classes associated with the types of the
+ // template arguments provided for template type parameters (excluding
+ // template template parameters)
+ addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
+ // [...] the namespaces in which any template template arguments are
+ // defined; and the classes in which any member templates used as
+ // template template arguments are defined.
+ TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
+ if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
+ DeclContext *Ctx = ClassTemplate->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.Classes.insert(EnclosingClass);
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
+ }
+ break;
+ }
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Expression:
+ // [Note: non-type template arguments do not contribute to the set of
+ // associated namespaces. ]
+ break;
+
+ case TemplateArgument::Pack:
+ for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
+ PEnd = Arg.pack_end();
+ P != PEnd; ++P)
+ addAssociatedClassesAndNamespaces(Result, *P);
+ break;
+ }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of class type
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+ CXXRecordDecl *Class) {
+
+ // Just silently ignore anything whose name is __va_list_tag.
+ if (Class->getDeclName() == Result.S.VAListTagName)
+ return;
+
+ // C++ [basic.lookup.koenig]p2:
+ // [...]
+ // -- If T is a class type (including unions), its associated
+ // classes are: the class itself; the class of which it is a
+ // member, if any; and its direct and indirect base
+ // classes. Its associated namespaces are the namespaces in
+ // which its associated classes are defined.
+
+ // Add the class of which it is a member, if any.
+ DeclContext *Ctx = Class->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.Classes.insert(EnclosingClass);
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+ // Add the class itself. If we've already seen this class, we don't
+ // need to visit base classes.
+ if (!Result.Classes.insert(Class))
+ return;
+
+ // -- If T is a template-id, its associated namespaces and classes are
+ // the namespace in which the template is defined; for member
+ // templates, the member template's class; the namespaces and classes
+ // associated with the types of the template arguments provided for
+ // template type parameters (excluding template template parameters); the
+ // namespaces in which any template template arguments are defined; and
+ // the classes in which any member templates used as template template
+ // arguments are defined. [Note: non-type template arguments do not
+ // contribute to the set of associated namespaces. ]
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
+ DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.Classes.insert(EnclosingClass);
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]);
+ }
+
+ // Only recurse into base classes for complete types.
+ if (!Class->hasDefinition()) {
+ // FIXME: we might need to instantiate templates here
+ return;
+ }
+
+ // Add direct and indirect base classes along with their associated
+ // namespaces.
+ llvm::SmallVector<CXXRecordDecl *, 32> Bases;
+ Bases.push_back(Class);
+ while (!Bases.empty()) {
+ // Pop this class off the stack.
+ Class = Bases.back();
+ Bases.pop_back();
+
+ // Visit the base classes.
+ for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
+ BaseEnd = Class->bases_end();
+ Base != BaseEnd; ++Base) {
+ const RecordType *BaseType = Base->getType()->getAs<RecordType>();
+ // In dependent contexts, we do ADL twice, and the first time around,
+ // the base type might be a dependent TemplateSpecializationType, or a
+ // TemplateTypeParmType. If that happens, simply ignore it.
+ // FIXME: If we want to support export, we probably need to add the
+ // namespace of the template in a TemplateSpecializationType, or even
+ // the classes and namespaces of known non-dependent arguments.
+ if (!BaseType)
+ continue;
+ CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (Result.Classes.insert(BaseDecl)) {
+ // Find the associated namespace for this base class.
+ DeclContext *BaseCtx = BaseDecl->getDeclContext();
+ CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
+
+ // Make sure we visit the bases of this base class.
+ if (BaseDecl->bases_begin() != BaseDecl->bases_end())
+ Bases.push_back(BaseDecl);
+ }
+ }
+ }
+}
+
+// \brief Add the associated classes and namespaces for
+// argument-dependent lookup with an argument of type T
+// (C++ [basic.lookup.koenig]p2).
+static void
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
+ // C++ [basic.lookup.koenig]p2:
+ //
+ // For each argument type T in the function call, there is a set
+ // of zero or more associated namespaces and a set of zero or more
+ // associated classes to be considered. The sets of namespaces and
+ // classes is determined entirely by the types of the function
+ // arguments (and the namespace of any template template
+ // argument). Typedef names and using-declarations used to specify
+ // the types do not contribute to this set. The sets of namespaces
+ // and classes are determined in the following way:
+
+ llvm::SmallVector<const Type *, 16> Queue;
+ const Type *T = Ty->getCanonicalTypeInternal().getTypePtr();
+
+ while (true) {
+ switch (T->getTypeClass()) {
+
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ // T is canonical. We can also ignore dependent types because
+ // we don't need to do ADL at the definition point, but if we
+ // wanted to implement template export (or if we find some other
+ // use for associated classes and namespaces...) this would be
+ // wrong.
+ break;
+
+ // -- If T is a pointer to U or an array of U, its associated
+ // namespaces and classes are those associated with U.
+ case Type::Pointer:
+ T = cast<PointerType>(T)->getPointeeType().getTypePtr();
+ continue;
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ T = cast<ArrayType>(T)->getElementType().getTypePtr();
+ continue;
+
+ // -- If T is a fundamental type, its associated sets of
+ // namespaces and classes are both empty.
+ case Type::Builtin:
+ break;
+
+ // -- If T is a class type (including unions), its associated
+ // classes are: the class itself; the class of which it is a
+ // member, if any; and its direct and indirect base
+ // classes. Its associated namespaces are the namespaces in
+ // which its associated classes are defined.
+ case Type::Record: {
+ CXXRecordDecl *Class
+ = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ addAssociatedClassesAndNamespaces(Result, Class);
+ break;
+ }
+
+ // -- If T is an enumeration type, its associated namespace is
+ // the namespace in which it is defined. If it is class
+ // member, its associated class is the member's class; else
+ // it has no associated class.
+ case Type::Enum: {
+ EnumDecl *Enum = cast<EnumType>(T)->getDecl();
+
+ DeclContext *Ctx = Enum->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.Classes.insert(EnclosingClass);
+
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
+
+ break;
+ }
+
+ // -- If T is a function type, its associated namespaces and
+ // classes are those associated with the function parameter
+ // types and those associated with the return type.
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ Queue.push_back(Arg->getTypePtr());
+ // fallthrough
+ }
+ case Type::FunctionNoProto: {
+ const FunctionType *FnType = cast<FunctionType>(T);
+ T = FnType->getResultType().getTypePtr();
+ continue;
+ }
+
+ // -- If T is a pointer to a member function of a class X, its
+ // associated namespaces and classes are those associated
+ // with the function parameter types and return type,
+ // together with those associated with X.
+ //
+ // -- If T is a pointer to a data member of class X, its
+ // associated namespaces and classes are those associated
+ // with the member type together with those associated with
+ // X.
+ case Type::MemberPointer: {
+ const MemberPointerType *MemberPtr = cast<MemberPointerType>(T);
+
+ // Queue up the class type into which this points.
+ Queue.push_back(MemberPtr->getClass());
+
+ // And directly continue with the pointee type.
+ T = MemberPtr->getPointeeType().getTypePtr();
+ continue;
+ }
+
+ // As an extension, treat this like a normal pointer.
+ case Type::BlockPointer:
+ T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr();
+ continue;
+
+ // References aren't covered by the standard, but that's such an
+ // obvious defect that we cover them anyway.
+ case Type::LValueReference:
+ case Type::RValueReference:
+ T = cast<ReferenceType>(T)->getPointeeType().getTypePtr();
+ continue;
+
+ // These are fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ break;
+
+ // These are ignored by ADL.
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ break;
+ }
+
+ if (Queue.empty()) break;
+ T = Queue.back();
+ Queue.pop_back();
+ }
+}
+
+/// \brief Find the associated classes and namespaces for
+/// argument-dependent lookup for a call with the given set of
+/// arguments.
+///
+/// This routine computes the sets of associated classes and associated
+/// namespaces searched by argument-dependent lookup
+/// (C++ [basic.lookup.argdep]) for a given set of arguments.
+void
+Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses) {
+ AssociatedNamespaces.clear();
+ AssociatedClasses.clear();
+
+ AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses);
+
+ // C++ [basic.lookup.koenig]p2:
+ // For each argument type T in the function call, there is a set
+ // of zero or more associated namespaces and a set of zero or more
+ // associated classes to be considered. The sets of namespaces and
+ // classes is determined entirely by the types of the function
+ // arguments (and the namespace of any template template
+ // argument).
+ for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) {
+ Expr *Arg = Args[ArgIdx];
+
+ if (Arg->getType() != Context.OverloadTy) {
+ addAssociatedClassesAndNamespaces(Result, Arg->getType());
+ continue;
+ }
+
+ // [...] In addition, if the argument is the name or address of a
+ // set of overloaded functions and/or function templates, its
+ // associated classes and namespaces are the union of those
+ // associated with each of the members of the set: the namespace
+ // in which the function or function template is defined and the
+ // classes and namespaces associated with its (non-dependent)
+ // parameter types and return type.
+ Arg = Arg->IgnoreParens();
+ if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
+ if (unaryOp->getOpcode() == UO_AddrOf)
+ Arg = unaryOp->getSubExpr();
+
+ UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
+ if (!ULE) continue;
+
+ for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
+ I != E; ++I) {
+ // Look through any using declarations to find the underlying function.
+ NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
+ if (!FDecl)
+ FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
+
+ // Add the classes and namespaces associated with the parameter
+ // types and return type of this function.
+ addAssociatedClassesAndNamespaces(Result, FDecl->getType());
+ }
+ }
+}
+
+/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
+/// an acceptable non-member overloaded operator for a call whose
+/// arguments have types T1 (and, if non-empty, T2). This routine
+/// implements the check in C++ [over.match.oper]p3b2 concerning
+/// enumeration types.
+static bool
+IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
+ QualType T1, QualType T2,
+ ASTContext &Context) {
+ if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+ return true;
+
+ if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
+ return true;
+
+ const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
+ if (Proto->getNumArgs() < 1)
+ return false;
+
+ if (T1->isEnumeralType()) {
+ QualType ArgType = Proto->getArgType(0).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T1, ArgType))
+ return true;
+ }
+
+ if (Proto->getNumArgs() < 2)
+ return false;
+
+ if (!T2.isNull() && T2->isEnumeralType()) {
+ QualType ArgType = Proto->getArgType(1).getNonReferenceType();
+ if (Context.hasSameUnqualifiedType(T2, ArgType))
+ return true;
+ }
+
+ return false;
+}
+
+NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
+ SourceLocation Loc,
+ LookupNameKind NameKind,
+ RedeclarationKind Redecl) {
+ LookupResult R(*this, Name, Loc, NameKind, Redecl);
+ LookupName(R, S);
+ return R.getAsSingle<NamedDecl>();
+}
+
+/// \brief Find the protocol with the given name, if any.
+ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II,
+ SourceLocation IdLoc) {
+ Decl *D = LookupSingleName(TUScope, II, IdLoc,
+ LookupObjCProtocolName);
+ return cast_or_null<ObjCProtocolDecl>(D);
+}
+
+void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+ QualType T1, QualType T2,
+ UnresolvedSetImpl &Functions) {
+ // C++ [over.match.oper]p3:
+ // -- The set of non-member candidates is the result of the
+ // unqualified lookup of operator@ in the context of the
+ // expression according to the usual rules for name lookup in
+ // unqualified function calls (3.4.2) except that all member
+ // functions are ignored. However, if no operand has a class
+ // type, only those non-member functions in the lookup set
+ // that have a first parameter of type T1 or "reference to
+ // (possibly cv-qualified) T1", when T1 is an enumeration
+ // type, or (if there is a right operand) a second parameter
+ // of type T2 or "reference to (possibly cv-qualified) T2",
+ // when T2 is an enumeration type, are candidate functions.
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+ LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
+ LookupName(Operators, S);
+
+ assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
+
+ if (Operators.empty())
+ return;
+
+ for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
+ Op != OpEnd; ++Op) {
+ NamedDecl *Found = (*Op)->getUnderlyingDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) {
+ if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
+ Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD
+ } else if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>(Found)) {
+ // FIXME: friend operators?
+ // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
+ // later?
+ if (!FunTmpl->getDeclContext()->isRecord())
+ Functions.addDecl(*Op, Op.getAccess());
+ }
+ }
+}
+
+/// \brief Look up the constructors for the given class.
+DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
+ // If the copy constructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class)) {
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+ }
+
+ CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
+ DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
+ return Class->lookup(Name);
+}
+
+/// \brief Look for the destructor of the given class.
+///
+/// During semantic analysis, this routine should be used in lieu of
+/// CXXRecordDecl::getDestructor().
+///
+/// \returns The destructor for this class.
+CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+ // If the destructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class) &&
+ !Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+
+ return Class->getDestructor();
+}
+
+void ADLResult::insert(NamedDecl *New) {
+ NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+ // If we haven't yet seen a decl for this key, or the last decl
+ // was exactly this one, we're done.
+ if (Old == 0 || Old == New) {
+ Old = New;
+ return;
+ }
+
+ // Otherwise, decide which is a more recent redeclaration.
+ FunctionDecl *OldFD, *NewFD;
+ if (isa<FunctionTemplateDecl>(New)) {
+ OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+ NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+ } else {
+ OldFD = cast<FunctionDecl>(Old);
+ NewFD = cast<FunctionDecl>(New);
+ }
+
+ FunctionDecl *Cursor = NewFD;
+ while (true) {
+ Cursor = Cursor->getPreviousDeclaration();
+
+ // If we got to the end without finding OldFD, OldFD is the newer
+ // declaration; leave things as they are.
+ if (!Cursor) return;
+
+ // If we do find OldFD, then NewFD is newer.
+ if (Cursor == OldFD) break;
+
+ // Otherwise, keep looking.
+ }
+
+ Old = New;
+}
+
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
+ Expr **Args, unsigned NumArgs,
+ ADLResult &Result) {
+ // Find all of the associated namespaces and classes based on the
+ // arguments we have.
+ AssociatedNamespaceSet AssociatedNamespaces;
+ AssociatedClassSet AssociatedClasses;
+ FindAssociatedClassesAndNamespaces(Args, NumArgs,
+ AssociatedNamespaces,
+ AssociatedClasses);
+
+ QualType T1, T2;
+ if (Operator) {
+ T1 = Args[0]->getType();
+ if (NumArgs >= 2)
+ T2 = Args[1]->getType();
+ }
+
+ // C++ [basic.lookup.argdep]p3:
+ // Let X be the lookup set produced by unqualified lookup (3.4.1)
+ // and let Y be the lookup set produced by argument dependent
+ // lookup (defined as follows). If X contains [...] then Y is
+ // empty. Otherwise Y is the set of declarations found in the
+ // namespaces associated with the argument types as described
+ // below. The set of declarations found by the lookup of the name
+ // is the union of X and Y.
+ //
+ // Here, we compute Y and add its members to the overloaded
+ // candidate set.
+ for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(),
+ NSEnd = AssociatedNamespaces.end();
+ NS != NSEnd; ++NS) {
+ // When considering an associated namespace, the lookup is the
+ // same as the lookup performed when the associated namespace is
+ // used as a qualifier (3.4.3.2) except that:
+ //
+ // -- Any using-directives in the associated namespace are
+ // ignored.
+ //
+ // -- Any namespace-scope friend functions declared in
+ // associated classes are visible within their respective
+ // namespaces even if they are not visible during an ordinary
+ // lookup (11.4).
+ DeclContext::lookup_iterator I, E;
+ for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
+ NamedDecl *D = *I;
+ // If the only declaration here is an ordinary friend, consider
+ // it only if it was declared in an associated classes.
+ if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
+ DeclContext *LexDC = D->getLexicalDeclContext();
+ if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
+ continue;
+ }
+
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ if (isa<FunctionDecl>(D)) {
+ if (Operator &&
+ !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
+ T1, T2, Context))
+ continue;
+ } else if (!isa<FunctionTemplateDecl>(D))
+ continue;
+
+ Result.insert(D);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// Search for all visible declarations.
+//----------------------------------------------------------------------------
+VisibleDeclConsumer::~VisibleDeclConsumer() { }
+
+namespace {
+
+class ShadowContextRAII;
+
+class VisibleDeclsRecord {
+public:
+ /// \brief An entry in the shadow map, which is optimized to store a
+ /// single declaration (the common case) but can also store a list
+ /// of declarations.
+ class ShadowMapEntry {
+ typedef llvm::SmallVector<NamedDecl *, 4> DeclVector;
+
+ /// \brief Contains either the solitary NamedDecl * or a vector
+ /// of declarations.
+ llvm::PointerUnion<NamedDecl *, DeclVector*> DeclOrVector;
+
+ public:
+ ShadowMapEntry() : DeclOrVector() { }
+
+ void Add(NamedDecl *ND);
+ void Destroy();
+
+ // Iteration.
+ typedef NamedDecl * const *iterator;
+ iterator begin();
+ iterator end();
+ };
+
+private:
+ /// \brief A mapping from declaration names to the declarations that have
+ /// this name within a particular scope.
+ typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
+
+ /// \brief A list of shadow maps, which is used to model name hiding.
+ std::list<ShadowMap> ShadowMaps;
+
+ /// \brief The declaration contexts we have already visited.
+ llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts;
+
+ friend class ShadowContextRAII;
+
+public:
+ /// \brief Determine whether we have already visited this context
+ /// (and, if not, note that we are going to visit that context now).
+ bool visitedContext(DeclContext *Ctx) {
+ return !VisitedContexts.insert(Ctx);
+ }
+
+ bool alreadyVisitedContext(DeclContext *Ctx) {
+ return VisitedContexts.count(Ctx);
+ }
+
+ /// \brief Determine whether the given declaration is hidden in the
+ /// current scope.
+ ///
+ /// \returns the declaration that hides the given declaration, or
+ /// NULL if no such declaration exists.
+ NamedDecl *checkHidden(NamedDecl *ND);
+
+ /// \brief Add a declaration to the current shadow map.
+ void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].Add(ND); }
+};
+
+/// \brief RAII object that records when we've entered a shadow context.
+class ShadowContextRAII {
+ VisibleDeclsRecord &Visible;
+
+ typedef VisibleDeclsRecord::ShadowMap ShadowMap;
+
+public:
+ ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) {
+ Visible.ShadowMaps.push_back(ShadowMap());
+ }
+
+ ~ShadowContextRAII() {
+ for (ShadowMap::iterator E = Visible.ShadowMaps.back().begin(),
+ EEnd = Visible.ShadowMaps.back().end();
+ E != EEnd;
+ ++E)
+ E->second.Destroy();
+
+ Visible.ShadowMaps.pop_back();
+ }
+};
+
+} // end anonymous namespace
+
+void VisibleDeclsRecord::ShadowMapEntry::Add(NamedDecl *ND) {
+ if (DeclOrVector.isNull()) {
+ // 0 - > 1 elements: just set the single element information.
+ DeclOrVector = ND;
+ return;
+ }
+
+ if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+ // 1 -> 2 elements: create the vector of results and push in the
+ // existing declaration.
+ DeclVector *Vec = new DeclVector;
+ Vec->push_back(PrevND);
+ DeclOrVector = Vec;
+ }
+
+ // Add the new element to the end of the vector.
+ DeclOrVector.get<DeclVector*>()->push_back(ND);
+}
+
+void VisibleDeclsRecord::ShadowMapEntry::Destroy() {
+ if (DeclVector *Vec = DeclOrVector.dyn_cast<DeclVector *>()) {
+ delete Vec;
+ DeclOrVector = ((NamedDecl *)0);
+ }
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator
+VisibleDeclsRecord::ShadowMapEntry::begin() {
+ if (DeclOrVector.isNull())
+ return 0;
+
+ if (DeclOrVector.is<NamedDecl *>())
+ return DeclOrVector.getAddrOf<NamedDecl *>();
+
+ return DeclOrVector.get<DeclVector *>()->begin();
+}
+
+VisibleDeclsRecord::ShadowMapEntry::iterator
+VisibleDeclsRecord::ShadowMapEntry::end() {
+ if (DeclOrVector.isNull())
+ return 0;
+
+ if (DeclOrVector.dyn_cast<NamedDecl *>())
+ return &reinterpret_cast<NamedDecl*&>(DeclOrVector) + 1;
+
+ return DeclOrVector.get<DeclVector *>()->end();
+}
+
+NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
+ // Look through using declarations.
+ ND = ND->getUnderlyingDecl();
+
+ unsigned IDNS = ND->getIdentifierNamespace();
+ std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
+ for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
+ SM != SMEnd; ++SM) {
+ ShadowMap::iterator Pos = SM->find(ND->getDeclName());
+ if (Pos == SM->end())
+ continue;
+
+ for (ShadowMapEntry::iterator I = Pos->second.begin(),
+ IEnd = Pos->second.end();
+ I != IEnd; ++I) {
+ // A tag declaration does not hide a non-tag declaration.
+ if ((*I)->hasTagIdentifierNamespace() &&
+ (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
+ Decl::IDNS_ObjCProtocol)))
+ continue;
+
+ // Protocols are in distinct namespaces from everything else.
+ if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+ || (IDNS & Decl::IDNS_ObjCProtocol)) &&
+ (*I)->getIdentifierNamespace() != IDNS)
+ continue;
+
+ // Functions and function templates in the same scope overload
+ // rather than hide. FIXME: Look for hiding based on function
+ // signatures!
+ if ((*I)->isFunctionOrFunctionTemplate() &&
+ ND->isFunctionOrFunctionTemplate() &&
+ SM == ShadowMaps.rbegin())
+ continue;
+
+ // We've found a declaration that hides this one.
+ return *I;
+ }
+ }
+
+ return 0;
+}
+
+static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
+ bool QualifiedNameLookup,
+ bool InBaseClass,
+ VisibleDeclConsumer &Consumer,
+ VisibleDeclsRecord &Visited) {
+ if (!Ctx)
+ return;
+
+ // Make sure we don't visit the same context twice.
+ if (Visited.visitedContext(Ctx->getPrimaryContext()))
+ return;
+
+ if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+
+ // Enumerate all of the results in this context.
+ for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
+ CurCtx = CurCtx->getNextContext()) {
+ for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
+ DEnd = CurCtx->decls_end();
+ D != DEnd; ++D) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
+ if (Result.isAcceptableDecl(ND)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
+ Visited.add(ND);
+ }
+ } else if (ObjCForwardProtocolDecl *ForwardProto
+ = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
+ for (ObjCForwardProtocolDecl::protocol_iterator
+ P = ForwardProto->protocol_begin(),
+ PEnd = ForwardProto->protocol_end();
+ P != PEnd;
+ ++P) {
+ if (Result.isAcceptableDecl(*P)) {
+ Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass);
+ Visited.add(*P);
+ }
+ }
+ } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
+ for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end();
+ I != IEnd; ++I) {
+ ObjCInterfaceDecl *IFace = I->getInterface();
+ if (Result.isAcceptableDecl(IFace)) {
+ Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass);
+ Visited.add(IFace);
+ }
+ }
+ }
+
+ // Visit transparent contexts and inline namespaces inside this context.
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
+ LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass,
+ Consumer, Visited);
+ }
+ }
+ }
+
+ // Traverse using directives for qualified name lookup.
+ if (QualifiedNameLookup) {
+ ShadowContextRAII Shadow(Visited);
+ DeclContext::udir_iterator I, E;
+ for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
+ LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
+ QualifiedNameLookup, InBaseClass, Consumer, Visited);
+ }
+ }
+
+ // Traverse the contexts of inherited C++ classes.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (!Record->hasDefinition())
+ return;
+
+ for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
+ BEnd = Record->bases_end();
+ B != BEnd; ++B) {
+ QualType BaseType = B->getType();
+
+ // Don't look into dependent bases, because name lookup can't look
+ // there anyway.
+ if (BaseType->isDependentType())
+ continue;
+
+ const RecordType *Record = BaseType->getAs<RecordType>();
+ if (!Record)
+ continue;
+
+ // FIXME: It would be nice to be able to determine whether referencing
+ // a particular member would be ambiguous. For example, given
+ //
+ // struct A { int member; };
+ // struct B { int member; };
+ // struct C : A, B { };
+ //
+ // void f(C *c) { c->### }
+ //
+ // accessing 'member' would result in an ambiguity. However, we
+ // could be smart enough to qualify the member with the base
+ // class, e.g.,
+ //
+ // c->B::member
+ //
+ // or
+ //
+ // c->A::member
+
+ // Find results in this base class (and its bases).
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup,
+ true, Consumer, Visited);
+ }
+ }
+
+ // Traverse the contexts of Objective-C classes.
+ if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) {
+ // Traverse categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory()) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(Category, Result, QualifiedNameLookup, false,
+ Consumer, Visited);
+ }
+
+ // Traverse protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ Visited);
+ }
+
+ // Traverse the superclass.
+ if (IFace->getSuperClass()) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
+ true, Consumer, Visited);
+ }
+
+ // If there is an implementation, traverse it. We do this to find
+ // synthesized ivars.
+ if (IFace->getImplementation()) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(IFace->getImplementation(), Result,
+ QualifiedNameLookup, true, Consumer, Visited);
+ }
+ } else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
+ for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
+ E = Protocol->protocol_end(); I != E; ++I) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ Visited);
+ }
+ } else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
+ for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
+ E = Category->protocol_end(); I != E; ++I) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
+ Visited);
+ }
+
+ // If there is an implementation, traverse it.
+ if (Category->getImplementation()) {
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(Category->getImplementation(), Result,
+ QualifiedNameLookup, true, Consumer, Visited);
+ }
+ }
+}
+
+static void LookupVisibleDecls(Scope *S, LookupResult &Result,
+ UnqualUsingDirectiveSet &UDirs,
+ VisibleDeclConsumer &Consumer,
+ VisibleDeclsRecord &Visited) {
+ if (!S)
+ return;
+
+ if (!S->getEntity() ||
+ (!S->getParent() &&
+ !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) ||
+ ((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
+ // Walk through the declarations in this Scope.
+ for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
+ if (Result.isAcceptableDecl(ND)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
+ Visited.add(ND);
+ }
+ }
+ }
+
+ // FIXME: C++ [temp.local]p8
+ DeclContext *Entity = 0;
+ if (S->getEntity()) {
+ // Look into this scope's declaration context, along with any of its
+ // parent lookup contexts (e.g., enclosing classes), up to the point
+ // where we hit the context stored in the next outer scope.
+ Entity = (DeclContext *)S->getEntity();
+ DeclContext *OuterCtx = findOuterContext(S).first; // FIXME
+
+ for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx);
+ Ctx = Ctx->getLookupParent()) {
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) {
+ if (Method->isInstanceMethod()) {
+ // For instance methods, look for ivars in the method's interface.
+ LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
+ Result.getNameLoc(), Sema::LookupMemberName);
+ if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
+ LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
+
+ // Look for properties from which we can synthesize ivars, if
+ // permitted.
+ if (Result.getSema().getLangOptions().ObjCNonFragileABI2 &&
+ IFace->getImplementation() &&
+ Result.getLookupKind() == Sema::LookupOrdinaryName) {
+ for (ObjCInterfaceDecl::prop_iterator
+ P = IFace->prop_begin(),
+ PEnd = IFace->prop_end();
+ P != PEnd; ++P) {
+ if (Result.getSema().canSynthesizeProvisionalIvar(*P) &&
+ !IFace->lookupInstanceVariable((*P)->getIdentifier())) {
+ Consumer.FoundDecl(*P, Visited.checkHidden(*P), false);
+ Visited.add(*P);
+ }
+ }
+ }
+ }
+ }
+
+ // We've already performed all of the name lookup that we need
+ // to for Objective-C methods; the next context will be the
+ // outer scope.
+ break;
+ }
+
+ if (Ctx->isFunctionOrMethod())
+ continue;
+
+ LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
+ }
+ } else if (!S->getParent()) {
+ // Look into the translation unit scope. We walk through the translation
+ // unit's declaration context, because the Scope itself won't have all of
+ // the declarations if we loaded a precompiled header.
+ // FIXME: We would like the translation unit's Scope object to point to the
+ // translation unit, so we don't need this special "if" branch. However,
+ // doing so would force the normal C++ name-lookup code to look into the
+ // translation unit decl when the IdentifierInfo chains would suffice.
+ // Once we fix that problem (which is part of a more general "don't look
+ // in DeclContexts unless we have to" optimization), we can eliminate this.
+ Entity = Result.getSema().Context.getTranslationUnitDecl();
+ LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
+ }
+
+ if (Entity) {
+ // Lookup visible declarations in any namespaces found by using
+ // directives.
+ UnqualUsingDirectiveSet::const_iterator UI, UEnd;
+ llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
+ for (; UI != UEnd; ++UI)
+ LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
+ Result, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
+ }
+
+ // Lookup names in the parent scope.
+ ShadowContextRAII Shadow(Visited);
+ LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope) {
+ // Determine the set of using directives available during
+ // unqualified name lookup.
+ Scope *Initial = S;
+ UnqualUsingDirectiveSet UDirs;
+ if (getLangOptions().CPlusPlus) {
+ // Find the first namespace or translation-unit scope.
+ while (S && !isNamespaceOrTranslationUnitScope(S))
+ S = S->getParent();
+
+ UDirs.visitScopeChain(Initial, S);
+ }
+ UDirs.done();
+
+ // Look for visible declarations.
+ LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ VisibleDeclsRecord Visited;
+ if (!IncludeGlobalScope)
+ Visited.visitedContext(Context.getTranslationUnitDecl());
+ ShadowContextRAII Shadow(Visited);
+ ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
+}
+
+void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope) {
+ LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+ VisibleDeclsRecord Visited;
+ if (!IncludeGlobalScope)
+ Visited.visitedContext(Context.getTranslationUnitDecl());
+ ShadowContextRAII Shadow(Visited);
+ ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
+ /*InBaseClass=*/false, Consumer, Visited);
+}
+
+/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
+/// If isLocalLabel is true, then this is a definition of an __label__ label
+/// name, otherwise it is a normal label definition or use.
+LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
+ bool isLocalLabel) {
+ // Do a lookup to see if we have a label with this name already.
+ NamedDecl *Res = 0;
+
+ // Local label definitions always shadow existing labels.
+ if (!isLocalLabel)
+ Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
+
+ // If we found a label, check to see if it is in the same context as us. When
+ // in a Block, we don't want to reuse a label in an enclosing function.
+ if (Res && Res->getDeclContext() != CurContext)
+ Res = 0;
+
+ if (Res == 0) {
+ // If not forward referenced or defined already, create the backing decl.
+ Res = LabelDecl::Create(Context, CurContext, Loc, II);
+ Scope *S = isLocalLabel ? CurScope : CurScope->getFnParent();
+ assert(S && "Not in a function?");
+ PushOnScopeChains(Res, S, true);
+ }
+
+ return cast<LabelDecl>(Res);
+}
+
+//===----------------------------------------------------------------------===//
+// Typo correction
+//===----------------------------------------------------------------------===//
+
+namespace {
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ /// \brief The name written that is a typo in the source.
+ llvm::StringRef Typo;
+
+ /// \brief The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ ///
+ /// The boolean value indicates whether there is a keyword with this name.
+ llvm::StringMap<bool, llvm::BumpPtrAllocator> BestResults;
+
+ /// \brief The best edit distance found so far.
+ unsigned BestEditDistance;
+
+public:
+ explicit TypoCorrectionConsumer(IdentifierInfo *Typo)
+ : Typo(Typo->getName()),
+ BestEditDistance((std::numeric_limits<unsigned>::max)()) { }
+
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
+ void FoundName(llvm::StringRef Name);
+ void addKeywordResult(ASTContext &Context, llvm::StringRef Keyword);
+
+ typedef llvm::StringMap<bool, llvm::BumpPtrAllocator>::iterator iterator;
+ iterator begin() { return BestResults.begin(); }
+ iterator end() { return BestResults.end(); }
+ void erase(iterator I) { BestResults.erase(I); }
+ unsigned size() const { return BestResults.size(); }
+ bool empty() const { return BestResults.empty(); }
+
+ bool &operator[](llvm::StringRef Name) {
+ return BestResults[Name];
+ }
+
+ unsigned getBestEditDistance() const { return BestEditDistance; }
+};
+
+}
+
+void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
+ bool InBaseClass) {
+ // Don't consider hidden names for typo correction.
+ if (Hiding)
+ return;
+
+ // Only consider entities with identifiers for names, ignoring
+ // special names (constructors, overloaded operators, selectors,
+ // etc.).
+ IdentifierInfo *Name = ND->getIdentifier();
+ if (!Name)
+ return;
+
+ FoundName(Name->getName());
+}
+
+void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) {
+ using namespace std;
+
+ // Use a simple length-based heuristic to determine the minimum possible
+ // edit distance. If the minimum isn't good enough, bail out early.
+ unsigned MinED = abs((int)Name.size() - (int)Typo.size());
+ if (MinED > BestEditDistance || (MinED && Typo.size() / MinED < 3))
+ return;
+
+ // Compute an upper bound on the allowable edit distance, so that the
+ // edit-distance algorithm can short-circuit.
+ unsigned UpperBound = min(unsigned((Typo.size() + 2) / 3), BestEditDistance);
+
+ // Compute the edit distance between the typo and the name of this
+ // entity. If this edit distance is not worse than the best edit
+ // distance we've seen so far, add it to the list of results.
+ unsigned ED = Typo.edit_distance(Name, true, UpperBound);
+ if (ED == 0)
+ return;
+
+ if (ED < BestEditDistance) {
+ // This result is better than any we've seen before; clear out
+ // the previous results.
+ BestResults.clear();
+ BestEditDistance = ED;
+ } else if (ED > BestEditDistance) {
+ // This result is worse than the best results we've seen so far;
+ // ignore it.
+ return;
+ }
+
+ // Add this name to the list of results. By not assigning a value, we
+ // keep the current value if we've seen this name before (either as a
+ // keyword or as a declaration), or get the default value (not a keyword)
+ // if we haven't seen it before.
+ (void)BestResults[Name];
+}
+
+void TypoCorrectionConsumer::addKeywordResult(ASTContext &Context,
+ llvm::StringRef Keyword) {
+ // Compute the edit distance between the typo and this keyword.
+ // If this edit distance is not worse than the best edit
+ // distance we've seen so far, add it to the list of results.
+ unsigned ED = Typo.edit_distance(Keyword);
+ if (ED < BestEditDistance) {
+ BestResults.clear();
+ BestEditDistance = ED;
+ } else if (ED > BestEditDistance) {
+ // This result is worse than the best results we've seen so far;
+ // ignore it.
+ return;
+ }
+
+ BestResults[Keyword] = true;
+}
+
+/// \brief Perform name lookup for a possible result for typo correction.
+static void LookupPotentialTypoResult(Sema &SemaRef,
+ LookupResult &Res,
+ IdentifierInfo *Name,
+ Scope *S, CXXScopeSpec *SS,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ Sema::CorrectTypoContext CTC) {
+ Res.suppressDiagnostics();
+ Res.clear();
+ Res.setLookupName(Name);
+ if (MemberContext) {
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
+ if (CTC == Sema::CTC_ObjCIvarLookup) {
+ if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) {
+ Res.addDecl(Ivar);
+ Res.resolveKind();
+ return;
+ }
+ }
+
+ if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) {
+ Res.addDecl(Prop);
+ Res.resolveKind();
+ return;
+ }
+ }
+
+ SemaRef.LookupQualifiedName(Res, MemberContext);
+ return;
+ }
+
+ SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false,
+ EnteringContext);
+
+ // Fake ivar lookup; this should really be part of
+ // LookupParsedName.
+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
+ if (Method->isInstanceMethod() && Method->getClassInterface() &&
+ (Res.empty() ||
+ (Res.isSingleResult() &&
+ Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) {
+ if (ObjCIvarDecl *IV
+ = Method->getClassInterface()->lookupInstanceVariable(Name)) {
+ Res.addDecl(IV);
+ Res.resolveKind();
+ }
+ }
+ }
+}
+
+/// \brief Try to "correct" a typo in the source code by finding
+/// visible declarations whose names are similar to the name that was
+/// present in the source code.
+///
+/// \param Res the \c LookupResult structure that contains the name
+/// that was present in the source code along with the name-lookup
+/// criteria used to search for the name. On success, this structure
+/// will contain the results of name lookup.
+///
+/// \param S the scope in which name lookup occurs.
+///
+/// \param SS the nested-name-specifier that precedes the name we're
+/// looking for, if present.
+///
+/// \param MemberContext if non-NULL, the context in which to look for
+/// a member access expression.
+///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
+/// \param CTC The context in which typo correction occurs, which impacts the
+/// set of keywords permitted.
+///
+/// \param OPT when non-NULL, the search for visible declarations will
+/// also walk the protocols in the qualified interfaces of \p OPT.
+///
+/// \returns the corrected name if the typo was corrected, otherwise returns an
+/// empty \c DeclarationName. When a typo was corrected, the result structure
+/// may contain the results of name lookup for the correct name or it may be
+/// empty.
+DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ CorrectTypoContext CTC,
+ const ObjCObjectPointerType *OPT) {
+ if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
+ return DeclarationName();
+
+ // We only attempt to correct typos for identifiers.
+ IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
+ if (!Typo)
+ return DeclarationName();
+
+ // If the scope specifier itself was invalid, don't try to correct
+ // typos.
+ if (SS && SS->isInvalid())
+ return DeclarationName();
+
+ // Never try to correct typos during template deduction or
+ // instantiation.
+ if (!ActiveTemplateInstantiations.empty())
+ return DeclarationName();
+
+ TypoCorrectionConsumer Consumer(Typo);
+
+ // Perform name lookup to find visible, similarly-named entities.
+ bool IsUnqualifiedLookup = false;
+ if (MemberContext) {
+ LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
+
+ // Look in qualified interfaces.
+ if (OPT) {
+ for (ObjCObjectPointerType::qual_iterator
+ I = OPT->qual_begin(), E = OPT->qual_end();
+ I != E; ++I)
+ LookupVisibleDecls(*I, Res.getLookupKind(), Consumer);
+ }
+ } else if (SS && SS->isSet()) {
+ DeclContext *DC = computeDeclContext(*SS, EnteringContext);
+ if (!DC)
+ return DeclarationName();
+
+ // Provide a stop gap for files that are just seriously broken. Trying
+ // to correct all typos can turn into a HUGE performance penalty, causing
+ // some files to take minutes to get rejected by the parser.
+ if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
+ return DeclarationName();
+ ++TyposCorrected;
+
+ LookupVisibleDecls(DC, Res.getLookupKind(), Consumer);
+ } else {
+ IsUnqualifiedLookup = true;
+ UnqualifiedTyposCorrectedMap::iterator Cached
+ = UnqualifiedTyposCorrected.find(Typo);
+ if (Cached == UnqualifiedTyposCorrected.end()) {
+ // Provide a stop gap for files that are just seriously broken. Trying
+ // to correct all typos can turn into a HUGE performance penalty, causing
+ // some files to take minutes to get rejected by the parser.
+ if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
+ return DeclarationName();
+
+ // For unqualified lookup, look through all of the names that we have
+ // seen in this translation unit.
+ for (IdentifierTable::iterator I = Context.Idents.begin(),
+ IEnd = Context.Idents.end();
+ I != IEnd; ++I)
+ Consumer.FoundName(I->getKey());
+
+ // Walk through identifiers in external identifier sources.
+ if (IdentifierInfoLookup *External
+ = Context.Idents.getExternalIdentifierLookup()) {
+ llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
+ do {
+ llvm::StringRef Name = Iter->Next();
+ if (Name.empty())
+ break;
+
+ Consumer.FoundName(Name);
+ } while (true);
+ }
+ } else {
+ // Use the cached value, unless it's a keyword. In the keyword case, we'll
+ // end up adding the keyword below.
+ if (Cached->second.first.empty())
+ return DeclarationName();
+
+ if (!Cached->second.second)
+ Consumer.FoundName(Cached->second.first);
+ }
+ }
+
+ // Add context-dependent keywords.
+ bool WantTypeSpecifiers = false;
+ bool WantExpressionKeywords = false;
+ bool WantCXXNamedCasts = false;
+ bool WantRemainingKeywords = false;
+ switch (CTC) {
+ case CTC_Unknown:
+ WantTypeSpecifiers = true;
+ WantExpressionKeywords = true;
+ WantCXXNamedCasts = true;
+ WantRemainingKeywords = true;
+
+ if (ObjCMethodDecl *Method = getCurMethodDecl())
+ if (Method->getClassInterface() &&
+ Method->getClassInterface()->getSuperClass())
+ Consumer.addKeywordResult(Context, "super");
+
+ break;
+
+ case CTC_NoKeywords:
+ break;
+
+ case CTC_Type:
+ WantTypeSpecifiers = true;
+ break;
+
+ case CTC_ObjCMessageReceiver:
+ Consumer.addKeywordResult(Context, "super");
+ // Fall through to handle message receivers like expressions.
+
+ case CTC_Expression:
+ if (getLangOptions().CPlusPlus)
+ WantTypeSpecifiers = true;
+ WantExpressionKeywords = true;
+ // Fall through to get C++ named casts.
+
+ case CTC_CXXCasts:
+ WantCXXNamedCasts = true;
+ break;
+
+ case CTC_ObjCPropertyLookup:
+ // FIXME: Add "isa"?
+ break;
+
+ case CTC_MemberLookup:
+ if (getLangOptions().CPlusPlus)
+ Consumer.addKeywordResult(Context, "template");
+ break;
+
+ case CTC_ObjCIvarLookup:
+ break;
+ }
+
+ if (WantTypeSpecifiers) {
+ // Add type-specifier keywords to the set of results.
+ const char *CTypeSpecs[] = {
+ "char", "const", "double", "enum", "float", "int", "long", "short",
+ "signed", "struct", "union", "unsigned", "void", "volatile", "_Bool",
+ "_Complex", "_Imaginary",
+ // storage-specifiers as well
+ "extern", "inline", "static", "typedef"
+ };
+
+ const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]);
+ for (unsigned I = 0; I != NumCTypeSpecs; ++I)
+ Consumer.addKeywordResult(Context, CTypeSpecs[I]);
+
+ if (getLangOptions().C99)
+ Consumer.addKeywordResult(Context, "restrict");
+ if (getLangOptions().Bool || getLangOptions().CPlusPlus)
+ Consumer.addKeywordResult(Context, "bool");
+
+ if (getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "class");
+ Consumer.addKeywordResult(Context, "typename");
+ Consumer.addKeywordResult(Context, "wchar_t");
+
+ if (getLangOptions().CPlusPlus0x) {
+ Consumer.addKeywordResult(Context, "char16_t");
+ Consumer.addKeywordResult(Context, "char32_t");
+ Consumer.addKeywordResult(Context, "constexpr");
+ Consumer.addKeywordResult(Context, "decltype");
+ Consumer.addKeywordResult(Context, "thread_local");
+ }
+ }
+
+ if (getLangOptions().GNUMode)
+ Consumer.addKeywordResult(Context, "typeof");
+ }
+
+ if (WantCXXNamedCasts && getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "const_cast");
+ Consumer.addKeywordResult(Context, "dynamic_cast");
+ Consumer.addKeywordResult(Context, "reinterpret_cast");
+ Consumer.addKeywordResult(Context, "static_cast");
+ }
+
+ if (WantExpressionKeywords) {
+ Consumer.addKeywordResult(Context, "sizeof");
+ if (getLangOptions().Bool || getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "false");
+ Consumer.addKeywordResult(Context, "true");
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ const char *CXXExprs[] = {
+ "delete", "new", "operator", "throw", "typeid"
+ };
+ const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]);
+ for (unsigned I = 0; I != NumCXXExprs; ++I)
+ Consumer.addKeywordResult(Context, CXXExprs[I]);
+
+ if (isa<CXXMethodDecl>(CurContext) &&
+ cast<CXXMethodDecl>(CurContext)->isInstance())
+ Consumer.addKeywordResult(Context, "this");
+
+ if (getLangOptions().CPlusPlus0x) {
+ Consumer.addKeywordResult(Context, "alignof");
+ Consumer.addKeywordResult(Context, "nullptr");
+ }
+ }
+ }
+
+ if (WantRemainingKeywords) {
+ if (getCurFunctionOrMethodDecl() || getCurBlock()) {
+ // Statements.
+ const char *CStmts[] = {
+ "do", "else", "for", "goto", "if", "return", "switch", "while" };
+ const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]);
+ for (unsigned I = 0; I != NumCStmts; ++I)
+ Consumer.addKeywordResult(Context, CStmts[I]);
+
+ if (getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "catch");
+ Consumer.addKeywordResult(Context, "try");
+ }
+
+ if (S && S->getBreakParent())
+ Consumer.addKeywordResult(Context, "break");
+
+ if (S && S->getContinueParent())
+ Consumer.addKeywordResult(Context, "continue");
+
+ if (!getCurFunction()->SwitchStack.empty()) {
+ Consumer.addKeywordResult(Context, "case");
+ Consumer.addKeywordResult(Context, "default");
+ }
+ } else {
+ if (getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "namespace");
+ Consumer.addKeywordResult(Context, "template");
+ }
+
+ if (S && S->isClassScope()) {
+ Consumer.addKeywordResult(Context, "explicit");
+ Consumer.addKeywordResult(Context, "friend");
+ Consumer.addKeywordResult(Context, "mutable");
+ Consumer.addKeywordResult(Context, "private");
+ Consumer.addKeywordResult(Context, "protected");
+ Consumer.addKeywordResult(Context, "public");
+ Consumer.addKeywordResult(Context, "virtual");
+ }
+ }
+
+ if (getLangOptions().CPlusPlus) {
+ Consumer.addKeywordResult(Context, "using");
+
+ if (getLangOptions().CPlusPlus0x)
+ Consumer.addKeywordResult(Context, "static_assert");
+ }
+ }
+
+ // If we haven't found anything, we're done.
+ if (Consumer.empty()) {
+ // If this was an unqualified lookup, note that no correction was found.
+ if (IsUnqualifiedLookup)
+ (void)UnqualifiedTyposCorrected[Typo];
+
+ return DeclarationName();
+ }
+
+ // Make sure that the user typed at least 3 characters for each correction
+ // made. Otherwise, we don't even both looking at the results.
+
+ // We also suppress exact matches; those should be handled by a
+ // different mechanism (e.g., one that introduces qualification in
+ // C++).
+ unsigned ED = Consumer.getBestEditDistance();
+ if (ED > 0 && Typo->getName().size() / ED < 3) {
+ // If this was an unqualified lookup, note that no correction was found.
+ if (IsUnqualifiedLookup)
+ (void)UnqualifiedTyposCorrected[Typo];
+
+ return DeclarationName();
+ }
+
+ // Weed out any names that could not be found by name lookup.
+ bool LastLookupWasAccepted = false;
+ for (TypoCorrectionConsumer::iterator I = Consumer.begin(),
+ IEnd = Consumer.end();
+ I != IEnd; /* Increment in loop. */) {
+ // Keywords are always found.
+ if (I->second) {
+ ++I;
+ continue;
+ }
+
+ // Perform name lookup on this name.
+ IdentifierInfo *Name = &Context.Idents.get(I->getKey());
+ LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,
+ EnteringContext, CTC);
+
+ switch (Res.getResultKind()) {
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ case LookupResult::Ambiguous:
+ // We didn't find this name in our scope, or didn't like what we found;
+ // ignore it.
+ Res.suppressDiagnostics();
+ {
+ TypoCorrectionConsumer::iterator Next = I;
+ ++Next;
+ Consumer.erase(I);
+ I = Next;
+ }
+ LastLookupWasAccepted = false;
+ break;
+
+ case LookupResult::Found:
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ ++I;
+ LastLookupWasAccepted = true;
+ break;
+ }
+
+ if (Res.isAmbiguous()) {
+ // We don't deal with ambiguities.
+ Res.suppressDiagnostics();
+ Res.clear();
+ return DeclarationName();
+ }
+ }
+
+ // If only a single name remains, return that result.
+ if (Consumer.size() == 1) {
+ IdentifierInfo *Name = &Context.Idents.get(Consumer.begin()->getKey());
+ if (Consumer.begin()->second) {
+ Res.suppressDiagnostics();
+ Res.clear();
+
+ // Don't correct to a keyword that's the same as the typo; the keyword
+ // wasn't actually in scope.
+ if (ED == 0) {
+ Res.setLookupName(Typo);
+ return DeclarationName();
+ }
+
+ } else if (!LastLookupWasAccepted) {
+ // Perform name lookup on this name.
+ LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,
+ EnteringContext, CTC);
+ }
+
+ // Record the correction for unqualified lookup.
+ if (IsUnqualifiedLookup)
+ UnqualifiedTyposCorrected[Typo]
+ = std::make_pair(Name->getName(), Consumer.begin()->second);
+
+ return &Context.Idents.get(Consumer.begin()->getKey());
+ }
+ else if (Consumer.size() > 1 && CTC == CTC_ObjCMessageReceiver
+ && Consumer["super"]) {
+ // Prefix 'super' when we're completing in a message-receiver
+ // context.
+ Res.suppressDiagnostics();
+ Res.clear();
+
+ // Don't correct to a keyword that's the same as the typo; the keyword
+ // wasn't actually in scope.
+ if (ED == 0) {
+ Res.setLookupName(Typo);
+ return DeclarationName();
+ }
+
+ // Record the correction for unqualified lookup.
+ if (IsUnqualifiedLookup)
+ UnqualifiedTyposCorrected[Typo]
+ = std::make_pair("super", Consumer.begin()->second);
+
+ return &Context.Idents.get("super");
+ }
+
+ Res.suppressDiagnostics();
+ Res.setLookupName(Typo);
+ Res.clear();
+ // Record the correction for unqualified lookup.
+ if (IsUnqualifiedLookup)
+ (void)UnqualifiedTyposCorrected[Typo];
+
+ return DeclarationName();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
new file mode 100644
index 0000000..b086ca7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -0,0 +1,1363 @@
+//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for Objective C @property and
+// @synthesize declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Grammar actions.
+//===----------------------------------------------------------------------===//
+
+Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ ObjCDeclSpec &ODS,
+ Selector GetterSel,
+ Selector SetterSel,
+ Decl *ClassCategory,
+ bool *isOverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC) {
+ unsigned Attributes = ODS.getPropertyAttributes();
+ bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
+ // default is readwrite!
+ !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
+ // property is defaulted to 'assign' if it is readwrite and is
+ // not retain or copy
+ bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
+ (isReadWrite &&
+ !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
+ !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
+
+ TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
+ QualType T = TSI->getType();
+ if (T->isReferenceType()) {
+ Diag(AtLoc, diag::error_reference_property);
+ return 0;
+ }
+ // Proceed with constructing the ObjCPropertDecls.
+ ObjCContainerDecl *ClassDecl =
+ cast<ObjCContainerDecl>(ClassCategory);
+
+ if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+ if (CDecl->IsClassExtension()) {
+ Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc,
+ FD, GetterSel, SetterSel,
+ isAssign, isReadWrite,
+ Attributes,
+ isOverridingProperty, TSI,
+ MethodImplKind);
+ if (Res)
+ CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
+ return Res;
+ }
+
+ Decl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
+ GetterSel, SetterSel,
+ isAssign, isReadWrite,
+ Attributes, TSI, MethodImplKind);
+ if (lexicalDC)
+ Res->setLexicalDeclContext(lexicalDC);
+
+ // Validate the attributes on the @property.
+ CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
+ return Res;
+}
+
+Decl *
+Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
+ SourceLocation AtLoc, FieldDeclarator &FD,
+ Selector GetterSel, Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ bool *isOverridingProperty,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind) {
+
+ // Diagnose if this property is already in continuation class.
+ DeclContext *DC = cast<DeclContext>(CDecl);
+ IdentifierInfo *PropertyId = FD.D.getIdentifier();
+ ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
+
+ if (CCPrimary)
+ // Check for duplicate declaration of this property in current and
+ // other class extensions.
+ for (const ObjCCategoryDecl *ClsExtDecl =
+ CCPrimary->getFirstClassExtension();
+ ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
+ if (ObjCPropertyDecl *prevDecl =
+ ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) {
+ Diag(AtLoc, diag::err_duplicate_property);
+ Diag(prevDecl->getLocation(), diag::note_property_declare);
+ return 0;
+ }
+ }
+
+ // Create a new ObjCPropertyDecl with the DeclContext being
+ // the class extension.
+ // FIXME. We should really be using CreatePropertyDecl for this.
+ ObjCPropertyDecl *PDecl =
+ ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
+ PropertyId, AtLoc, T);
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+ if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+ // Set setter/getter selector name. Needed later.
+ PDecl->setGetterName(GetterSel);
+ PDecl->setSetterName(SetterSel);
+ DC->addDecl(PDecl);
+
+ // We need to look in the @interface to see if the @property was
+ // already declared.
+ if (!CCPrimary) {
+ Diag(CDecl->getLocation(), diag::err_continuation_class);
+ *isOverridingProperty = true;
+ return 0;
+ }
+
+ // Find the property in continuation class's primary class only.
+ ObjCPropertyDecl *PIDecl =
+ CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
+
+ if (!PIDecl) {
+ // No matching property found in the primary class. Just fall thru
+ // and add property to continuation class's primary class.
+ ObjCPropertyDecl *PDecl =
+ CreatePropertyDecl(S, CCPrimary, AtLoc,
+ FD, GetterSel, SetterSel, isAssign, isReadWrite,
+ Attributes, T, MethodImplKind, DC);
+ // Mark written attribute as having no attribute because
+ // this is not a user-written property declaration in primary
+ // class.
+ PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr);
+
+ // A case of continuation class adding a new property in the class. This
+ // is not what it was meant for. However, gcc supports it and so should we.
+ // Make sure setter/getters are declared here.
+ ProcessPropertyDecl(PDecl, CCPrimary, /* redeclaredProperty = */ 0,
+ /* lexicalDC = */ CDecl);
+ return PDecl;
+ }
+
+ // The property 'PIDecl's readonly attribute will be over-ridden
+ // with continuation class's readwrite property attribute!
+ unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
+ if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+ unsigned retainCopyNonatomic =
+ (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if ((Attributes & retainCopyNonatomic) !=
+ (PIkind & retainCopyNonatomic)) {
+ Diag(AtLoc, diag::warn_property_attr_mismatch);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+ DeclContext *DC = cast<DeclContext>(CCPrimary);
+ if (!ObjCPropertyDecl::findPropertyDecl(DC,
+ PIDecl->getDeclName().getAsIdentifierInfo())) {
+ // Protocol is not in the primary class. Must build one for it.
+ ObjCDeclSpec ProtocolPropertyODS;
+ // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
+ // and ObjCPropertyDecl::PropertyAttributeKind have identical
+ // values. Should consolidate both into one enum type.
+ ProtocolPropertyODS.
+ setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
+ PIkind);
+
+ Decl *ProtocolPtrTy =
+ ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
+ PIDecl->getGetterName(),
+ PIDecl->getSetterName(),
+ CCPrimary, isOverridingProperty,
+ MethodImplKind,
+ /* lexicalDC = */ CDecl);
+ PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
+ }
+ PIDecl->makeitReadWriteAttribute();
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+ PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+ if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+ PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+ PIDecl->setSetterName(SetterSel);
+ } else {
+ // Tailor the diagnostics for the common case where a readwrite
+ // property is declared both in the @interface and the continuation.
+ // This is a common error where the user often intended the original
+ // declaration to be readonly.
+ unsigned diag =
+ (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
+ (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
+ ? diag::err_use_continuation_class_redeclaration_readwrite
+ : diag::err_use_continuation_class;
+ Diag(AtLoc, diag)
+ << CCPrimary->getDeclName();
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+ *isOverridingProperty = true;
+ // Make sure setter decl is synthesized, and added to primary class's list.
+ ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
+ return 0;
+}
+
+ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
+ ObjCContainerDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ TypeSourceInfo *TInfo,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC){
+ IdentifierInfo *PropertyId = FD.D.getIdentifier();
+ QualType T = TInfo->getType();
+
+ // Issue a warning if property is 'assign' as default and its object, which is
+ // gc'able conforms to NSCopying protocol
+ if (getLangOptions().getGCMode() != LangOptions::NonGC &&
+ isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+ if (const ObjCObjectPointerType *ObjPtrTy =
+ T->getAs<ObjCObjectPointerType>()) {
+ ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
+ if (IDecl)
+ if (ObjCProtocolDecl* PNSCopying =
+ LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
+ if (IDecl->ClassImplementsProtocol(PNSCopying, true))
+ Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
+ }
+ if (T->isObjCObjectType())
+ Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
+
+ DeclContext *DC = cast<DeclContext>(CDecl);
+ ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
+ FD.D.getIdentifierLoc(),
+ PropertyId, AtLoc, TInfo);
+
+ if (ObjCPropertyDecl *prevDecl =
+ ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
+ Diag(PDecl->getLocation(), diag::err_duplicate_property);
+ Diag(prevDecl->getLocation(), diag::note_property_declare);
+ PDecl->setInvalidDecl();
+ }
+ else {
+ DC->addDecl(PDecl);
+ if (lexicalDC)
+ PDecl->setLexicalDeclContext(lexicalDC);
+ }
+
+ if (T->isArrayType() || T->isFunctionType()) {
+ Diag(AtLoc, diag::err_property_type) << T;
+ PDecl->setInvalidDecl();
+ }
+
+ ProcessDeclAttributes(S, PDecl, FD.D);
+
+ // Regardless of setter/getter attribute, we save the default getter/setter
+ // selector names in anticipation of declaration of setter/getter methods.
+ PDecl->setGetterName(GetterSel);
+ PDecl->setSetterName(SetterSel);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_getter)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_setter)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
+
+ if (isReadWrite)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+
+ if (isAssign)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+
+ if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+ else if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
+ PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
+
+ PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes());
+
+ if (MethodImplKind == tok::objc_required)
+ PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
+ else if (MethodImplKind == tok::objc_optional)
+ PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
+
+ return PDecl;
+}
+
+
+/// ActOnPropertyImplDecl - This routine performs semantic checks and
+/// builds the AST node for a property implementation declaration; declared
+/// as @synthesize or @dynamic.
+///
+Decl *Sema::ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool Synthesize,
+ Decl *ClassCatImpDecl,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar,
+ SourceLocation PropertyIvarLoc) {
+ ObjCContainerDecl *ClassImpDecl =
+ cast_or_null<ObjCContainerDecl>(ClassCatImpDecl);
+ // Make sure we have a context for the property implementation declaration.
+ if (!ClassImpDecl) {
+ Diag(AtLoc, diag::error_missing_property_context);
+ return 0;
+ }
+ ObjCPropertyDecl *property = 0;
+ ObjCInterfaceDecl* IDecl = 0;
+ // Find the class or category class where this property must have
+ // a declaration.
+ ObjCImplementationDecl *IC = 0;
+ ObjCCategoryImplDecl* CatImplClass = 0;
+ if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
+ IDecl = IC->getClassInterface();
+ // We always synthesize an interface for an implementation
+ // without an interface decl. So, IDecl is always non-zero.
+ assert(IDecl &&
+ "ActOnPropertyImplDecl - @implementation without @interface");
+
+ // Look for this property declaration in the @implementation's @interface
+ property = IDecl->FindPropertyDeclaration(PropertyId);
+ if (!property) {
+ Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
+ return 0;
+ }
+ unsigned PIkind = property->getPropertyAttributesAsWritten();
+ if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
+ ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) {
+ if (AtLoc.isValid())
+ Diag(AtLoc, diag::warn_implicit_atomic_property);
+ else
+ Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
+ Diag(property->getLocation(), diag::note_property_declare);
+ }
+
+ if (const ObjCCategoryDecl *CD =
+ dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
+ if (!CD->IsClassExtension()) {
+ Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+ Diag(property->getLocation(), diag::note_property_declare);
+ return 0;
+ }
+ }
+ } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
+ if (Synthesize) {
+ Diag(AtLoc, diag::error_synthesize_category_decl);
+ return 0;
+ }
+ IDecl = CatImplClass->getClassInterface();
+ if (!IDecl) {
+ Diag(AtLoc, diag::error_missing_property_interface);
+ return 0;
+ }
+ ObjCCategoryDecl *Category =
+ IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
+
+ // If category for this implementation not found, it is an error which
+ // has already been reported eralier.
+ if (!Category)
+ return 0;
+ // Look for this property declaration in @implementation's category
+ property = Category->FindPropertyDeclaration(PropertyId);
+ if (!property) {
+ Diag(PropertyLoc, diag::error_bad_category_property_decl)
+ << Category->getDeclName();
+ return 0;
+ }
+ } else {
+ Diag(AtLoc, diag::error_bad_property_context);
+ return 0;
+ }
+ ObjCIvarDecl *Ivar = 0;
+ // Check that we have a valid, previously declared ivar for @synthesize
+ if (Synthesize) {
+ // @synthesize
+ if (!PropertyIvar)
+ PropertyIvar = PropertyId;
+ QualType PropType = Context.getCanonicalType(property->getType());
+ // Check that this is a previously declared 'ivar' in 'IDecl' interface
+ ObjCInterfaceDecl *ClassDeclared;
+ Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
+ if (!Ivar) {
+ Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc,
+ PropertyIvar, PropType, /*Dinfo=*/0,
+ ObjCIvarDecl::Private,
+ (Expr *)0, true);
+ ClassImpDecl->addDecl(Ivar);
+ IDecl->makeDeclVisibleInContext(Ivar, false);
+ property->setPropertyIvarDecl(Ivar);
+
+ if (!getLangOptions().ObjCNonFragileABI)
+ Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
+ // Note! I deliberately want it to fall thru so, we have a
+ // a property implementation and to avoid future warnings.
+ } else if (getLangOptions().ObjCNonFragileABI &&
+ ClassDeclared != IDecl) {
+ Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
+ << property->getDeclName() << Ivar->getDeclName()
+ << ClassDeclared->getDeclName();
+ Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
+ << Ivar << Ivar->getName();
+ // Note! I deliberately want it to fall thru so more errors are caught.
+ }
+ QualType IvarType = Context.getCanonicalType(Ivar->getType());
+
+ // Check that type of property and its ivar are type compatible.
+ if (PropType != IvarType) {
+ bool compat = false;
+ if (isa<ObjCObjectPointerType>(PropType)
+ && isa<ObjCObjectPointerType>(IvarType))
+ compat =
+ Context.canAssignObjCInterfaces(
+ PropType->getAs<ObjCObjectPointerType>(),
+ IvarType->getAs<ObjCObjectPointerType>());
+ else {
+ SourceLocation Loc = PropertyIvarLoc;
+ if (Loc.isInvalid())
+ Loc = PropertyLoc;
+ compat = (CheckAssignmentConstraints(Loc, PropType, IvarType)
+ == Compatible);
+ }
+ if (!compat) {
+ Diag(PropertyLoc, diag::error_property_ivar_type)
+ << property->getDeclName() << PropType
+ << Ivar->getDeclName() << IvarType;
+ Diag(Ivar->getLocation(), diag::note_ivar_decl);
+ // Note! I deliberately want it to fall thru so, we have a
+ // a property implementation and to avoid future warnings.
+ }
+
+ // FIXME! Rules for properties are somewhat different that those
+ // for assignments. Use a new routine to consolidate all cases;
+ // specifically for property redeclarations as well as for ivars.
+ QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
+ QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
+ if (lhsType != rhsType &&
+ lhsType->isArithmeticType()) {
+ Diag(PropertyLoc, diag::error_property_ivar_type)
+ << property->getDeclName() << PropType
+ << Ivar->getDeclName() << IvarType;
+ Diag(Ivar->getLocation(), diag::note_ivar_decl);
+ // Fall thru - see previous comment
+ }
+ // __weak is explicit. So it works on Canonical type.
+ if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
+ getLangOptions().getGCMode() != LangOptions::NonGC) {
+ Diag(PropertyLoc, diag::error_weak_property)
+ << property->getDeclName() << Ivar->getDeclName();
+ // Fall thru - see previous comment
+ }
+ if ((property->getType()->isObjCObjectPointerType() ||
+ PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
+ getLangOptions().getGCMode() != LangOptions::NonGC) {
+ Diag(PropertyLoc, diag::error_strong_property)
+ << property->getDeclName() << Ivar->getDeclName();
+ // Fall thru - see previous comment
+ }
+ }
+ } else if (PropertyIvar)
+ // @dynamic
+ Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
+ assert (property && "ActOnPropertyImplDecl - property declaration missing");
+ ObjCPropertyImplDecl *PIDecl =
+ ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
+ property,
+ (Synthesize ?
+ ObjCPropertyImplDecl::Synthesize
+ : ObjCPropertyImplDecl::Dynamic),
+ Ivar, PropertyIvarLoc);
+ if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
+ getterMethod->createImplicitParams(Context, IDecl);
+ if (getLangOptions().CPlusPlus && Synthesize &&
+ Ivar->getType()->isRecordType()) {
+ // For Objective-C++, need to synthesize the AST for the IVAR object to be
+ // returned by the getter as it must conform to C++'s copy-return rules.
+ // FIXME. Eventually we want to do this for Objective-C as well.
+ ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
+ DeclRefExpr *SelfExpr =
+ new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
+ VK_RValue, SourceLocation());
+ Expr *IvarRefExpr =
+ new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
+ SelfExpr, true, true);
+ ExprResult Res =
+ PerformCopyInitialization(InitializedEntity::InitializeResult(
+ SourceLocation(),
+ getterMethod->getResultType(),
+ /*NRVO=*/false),
+ SourceLocation(),
+ Owned(IvarRefExpr));
+ if (!Res.isInvalid()) {
+ Expr *ResExpr = Res.takeAs<Expr>();
+ if (ResExpr)
+ ResExpr = MaybeCreateExprWithCleanups(ResExpr);
+ PIDecl->setGetterCXXConstructor(ResExpr);
+ }
+ }
+ }
+ if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
+ setterMethod->createImplicitParams(Context, IDecl);
+ if (getLangOptions().CPlusPlus && Synthesize
+ && Ivar->getType()->isRecordType()) {
+ // FIXME. Eventually we want to do this for Objective-C as well.
+ ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
+ DeclRefExpr *SelfExpr =
+ new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
+ VK_RValue, SourceLocation());
+ Expr *lhs =
+ new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
+ SelfExpr, true, true);
+ ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
+ ParmVarDecl *Param = (*P);
+ Expr *rhs = new (Context) DeclRefExpr(Param, Param->getType(),
+ VK_LValue, SourceLocation());
+ ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
+ BO_Assign, lhs, rhs);
+ PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
+ }
+ }
+
+ if (IC) {
+ if (Synthesize)
+ if (ObjCPropertyImplDecl *PPIDecl =
+ IC->FindPropertyImplIvarDecl(PropertyIvar)) {
+ Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+ << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+ << PropertyIvar;
+ Diag(PPIDecl->getLocation(), diag::note_previous_use);
+ }
+
+ if (ObjCPropertyImplDecl *PPIDecl
+ = IC->FindPropertyImplDecl(PropertyId)) {
+ Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+ Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+ return 0;
+ }
+ IC->addPropertyImplementation(PIDecl);
+ if (getLangOptions().ObjCDefaultSynthProperties &&
+ getLangOptions().ObjCNonFragileABI2) {
+ // Diagnose if an ivar was lazily synthesdized due to a previous
+ // use and if 1) property is @dynamic or 2) property is synthesized
+ // but it requires an ivar of different name.
+ ObjCInterfaceDecl *ClassDeclared=0;
+ ObjCIvarDecl *Ivar = 0;
+ if (!Synthesize)
+ Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+ else {
+ if (PropertyIvar && PropertyIvar != PropertyId)
+ Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+ }
+ // Issue diagnostics only if Ivar belongs to current class.
+ if (Ivar && Ivar->getSynthesize() &&
+ IC->getClassInterface() == ClassDeclared) {
+ Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
+ << PropertyId;
+ Ivar->setInvalidDecl();
+ }
+ }
+ } else {
+ if (Synthesize)
+ if (ObjCPropertyImplDecl *PPIDecl =
+ CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
+ Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+ << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
+ << PropertyIvar;
+ Diag(PPIDecl->getLocation(), diag::note_previous_use);
+ }
+
+ if (ObjCPropertyImplDecl *PPIDecl =
+ CatImplClass->FindPropertyImplDecl(PropertyId)) {
+ Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+ Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
+ return 0;
+ }
+ CatImplClass->addPropertyImplementation(PIDecl);
+ }
+
+ return PIDecl;
+}
+
+//===----------------------------------------------------------------------===//
+// Helper methods.
+//===----------------------------------------------------------------------===//
+
+/// DiagnosePropertyMismatch - Compares two properties for their
+/// attributes and types and warns on a variety of inconsistencies.
+///
+void
+Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+ ObjCPropertyDecl *SuperProperty,
+ const IdentifierInfo *inheritedName) {
+ ObjCPropertyDecl::PropertyAttributeKind CAttr =
+ Property->getPropertyAttributes();
+ ObjCPropertyDecl::PropertyAttributeKind SAttr =
+ SuperProperty->getPropertyAttributes();
+ if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
+ && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
+ Diag(Property->getLocation(), diag::warn_readonly_property)
+ << Property->getDeclName() << inheritedName;
+ if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
+ != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "copy" << inheritedName;
+ else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain)
+ != (SAttr & ObjCPropertyDecl::OBJC_PR_retain))
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "retain" << inheritedName;
+
+ if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "atomic" << inheritedName;
+ if (Property->getSetterName() != SuperProperty->getSetterName())
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "setter" << inheritedName;
+ if (Property->getGetterName() != SuperProperty->getGetterName())
+ Diag(Property->getLocation(), diag::warn_property_attribute)
+ << Property->getDeclName() << "getter" << inheritedName;
+
+ QualType LHSType =
+ Context.getCanonicalType(SuperProperty->getType());
+ QualType RHSType =
+ Context.getCanonicalType(Property->getType());
+
+ if (!Context.typesAreCompatible(LHSType, RHSType)) {
+ // FIXME: Incorporate this test with typesAreCompatible.
+ if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType())
+ if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
+ return;
+ Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
+ << Property->getType() << SuperProperty->getType() << inheritedName;
+ }
+}
+
+bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
+ ObjCMethodDecl *GetterMethod,
+ SourceLocation Loc) {
+ if (GetterMethod &&
+ GetterMethod->getResultType() != property->getType()) {
+ AssignConvertType result = Incompatible;
+ if (property->getType()->isObjCObjectPointerType())
+ result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
+ property->getType());
+ if (result != Compatible) {
+ Diag(Loc, diag::warn_accessor_property_type_mismatch)
+ << property->getDeclName()
+ << GetterMethod->getSelector();
+ Diag(GetterMethod->getLocation(), diag::note_declared_at);
+ return true;
+ }
+ }
+ return false;
+}
+
+/// ComparePropertiesInBaseAndSuper - This routine compares property
+/// declarations in base and its super class, if any, and issues
+/// diagnostics in a variety of inconsistant situations.
+///
+void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
+ ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
+ if (!SDecl)
+ return;
+ // FIXME: O(N^2)
+ for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
+ E = SDecl->prop_end(); S != E; ++S) {
+ ObjCPropertyDecl *SuperPDecl = (*S);
+ // Does property in super class has declaration in current class?
+ for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
+ E = IDecl->prop_end(); I != E; ++I) {
+ ObjCPropertyDecl *PDecl = (*I);
+ if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
+ DiagnosePropertyMismatch(PDecl, SuperPDecl,
+ SDecl->getIdentifier());
+ }
+ }
+}
+
+/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
+/// of properties declared in a protocol and compares their attribute against
+/// the same property declared in the class or category.
+void
+Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
+ ObjCProtocolDecl *PDecl) {
+ ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+ if (!IDecl) {
+ // Category
+ ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+ assert (CatDecl && "MatchOneProtocolPropertiesInClass");
+ if (!CatDecl->IsClassExtension())
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Pr = (*P);
+ ObjCCategoryDecl::prop_iterator CP, CE;
+ // Is this property already in category's list of properties?
+ for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP)
+ if ((*CP)->getIdentifier() == Pr->getIdentifier())
+ break;
+ if (CP != CE)
+ // Property protocol already exist in class. Diagnose any mismatch.
+ DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+ }
+ return;
+ }
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Pr = (*P);
+ ObjCInterfaceDecl::prop_iterator CP, CE;
+ // Is this property already in class's list of properties?
+ for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
+ if ((*CP)->getIdentifier() == Pr->getIdentifier())
+ break;
+ if (CP != CE)
+ // Property protocol already exist in class. Diagnose any mismatch.
+ DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+ }
+}
+
+/// CompareProperties - This routine compares properties
+/// declared in 'ClassOrProtocol' objects (which can be a class or an
+/// inherited protocol with the list of properties for class/category 'CDecl'
+///
+void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
+ Decl *ClassDecl = ClassOrProtocol;
+ ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
+
+ if (!IDecl) {
+ // Category
+ ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
+ assert (CatDecl && "CompareProperties");
+ if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
+ for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
+ E = MDecl->protocol_end(); P != E; ++P)
+ // Match properties of category with those of protocol (*P)
+ MatchOneProtocolPropertiesInClass(CatDecl, *P);
+
+ // Go thru the list of protocols for this category and recursively match
+ // their properties with those in the category.
+ for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
+ E = CatDecl->protocol_end(); P != E; ++P)
+ CompareProperties(CatDecl, *P);
+ } else {
+ ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+ for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+ E = MD->protocol_end(); P != E; ++P)
+ MatchOneProtocolPropertiesInClass(CatDecl, *P);
+ }
+ return;
+ }
+
+ if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = MDecl->all_referenced_protocol_begin(),
+ E = MDecl->all_referenced_protocol_end(); P != E; ++P)
+ // Match properties of class IDecl with those of protocol (*P).
+ MatchOneProtocolPropertiesInClass(IDecl, *P);
+
+ // Go thru the list of protocols for this class and recursively match
+ // their properties with those declared in the class.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); P != E; ++P)
+ CompareProperties(IDecl, *P);
+ } else {
+ ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
+ for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
+ E = MD->protocol_end(); P != E; ++P)
+ MatchOneProtocolPropertiesInClass(IDecl, *P);
+ }
+}
+
+/// isPropertyReadonly - Return true if property is readonly, by searching
+/// for the property in the class and in its categories and implementations
+///
+bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
+ ObjCInterfaceDecl *IDecl) {
+ // by far the most common case.
+ if (!PDecl->isReadOnly())
+ return false;
+ // Even if property is ready only, if interface has a user defined setter,
+ // it is not considered read only.
+ if (IDecl->getInstanceMethod(PDecl->getSetterName()))
+ return false;
+
+ // Main class has the property as 'readonly'. Must search
+ // through the category list to see if the property's
+ // attribute has been over-ridden to 'readwrite'.
+ for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
+ Category; Category = Category->getNextClassCategory()) {
+ // Even if property is ready only, if a category has a user defined setter,
+ // it is not considered read only.
+ if (Category->getInstanceMethod(PDecl->getSetterName()))
+ return false;
+ ObjCPropertyDecl *P =
+ Category->FindPropertyDeclaration(PDecl->getIdentifier());
+ if (P && !P->isReadOnly())
+ return false;
+ }
+
+ // Also, check for definition of a setter method in the implementation if
+ // all else failed.
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
+ if (ObjCImplementationDecl *IMD =
+ dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
+ if (IMD->getInstanceMethod(PDecl->getSetterName()))
+ return false;
+ } else if (ObjCCategoryImplDecl *CIMD =
+ dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+ if (CIMD->getInstanceMethod(PDecl->getSetterName()))
+ return false;
+ }
+ }
+ // Lastly, look through the implementation (if one is in scope).
+ if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
+ if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
+ return false;
+ // If all fails, look at the super class.
+ if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
+ return isPropertyReadonly(PDecl, SIDecl);
+ return true;
+}
+
+/// CollectImmediateProperties - This routine collects all properties in
+/// the class and its conforming protocols; but not those it its super class.
+void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) {
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+ E = IDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ }
+ if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+ if (!CATDecl->IsClassExtension())
+ for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+ E = CATDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+ E = CATDecl->protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ }
+ else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
+ // Exclude property for protocols which conform to class's super-class,
+ // as super-class has to implement the property.
+ if (!PropertyFromSuper || PropertyFromSuper != Prop) {
+ ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
+ if (!PropEntry)
+ PropEntry = Prop;
+ }
+ }
+ // scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI)
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
+ }
+}
+
+/// CollectClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in the class. This includes, class's
+/// and its conforming protocols' properties.
+static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+ E = IDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
+ CollectClassPropertyImplementations((*PI), PropMap);
+ }
+ else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
+ // scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI)
+ CollectClassPropertyImplementations((*PI), PropMap);
+ }
+}
+
+/// CollectSuperClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in super class(s) and also coming from their
+/// conforming protocols.
+static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+ if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
+ while (SDecl) {
+ CollectClassPropertyImplementations(SDecl, PropMap);
+ SDecl = SDecl->getSuperClass();
+ }
+ }
+}
+
+/// LookupPropertyDecl - Looks up a property in the current class and all
+/// its protocols.
+ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+ IdentifierInfo *II) {
+ if (const ObjCInterfaceDecl *IDecl =
+ dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+ E = IDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ if (Prop->getIdentifier() == II)
+ return Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
+ ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+ if (Prop)
+ return Prop;
+ }
+ }
+ else if (const ObjCProtocolDecl *PDecl =
+ dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ if (Prop->getIdentifier() == II)
+ return Prop;
+ }
+ // scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI) {
+ ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+ if (Prop)
+ return Prop;
+ }
+ }
+ return 0;
+}
+
+/// DefaultSynthesizeProperties - This routine default synthesizes all
+/// properties which must be synthesized in class's @implementation.
+void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCInterfaceDecl *IDecl) {
+
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+ CollectClassPropertyImplementations(IDecl, PropMap);
+ if (PropMap.empty())
+ return;
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+ CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+
+ for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+ P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = P->second;
+ // If property to be implemented in the super class, ignore.
+ if (SuperPropMap[Prop->getIdentifier()])
+ continue;
+ // Is there a matching propery synthesize/dynamic?
+ if (Prop->isInvalidDecl() ||
+ Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+ IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier()))
+ continue;
+ // Property may have been synthesized by user.
+ if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
+ continue;
+ if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+ continue;
+ if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
+ continue;
+ }
+
+
+ // We use invalid SourceLocations for the synthesized ivars since they
+ // aren't really synthesized at a particular location; they just exist.
+ // Saying that they are located at the @implementation isn't really going
+ // to help users.
+ ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
+ true,IMPDecl,
+ Prop->getIdentifier(), Prop->getIdentifier(),
+ SourceLocation());
+ }
+}
+
+void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl *CDecl,
+ const llvm::DenseSet<Selector>& InsMap) {
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
+ CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+ CollectImmediateProperties(CDecl, PropMap, SuperPropMap);
+ if (PropMap.empty())
+ return;
+
+ llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
+ for (ObjCImplDecl::propimpl_iterator
+ I = IMPDecl->propimpl_begin(),
+ EI = IMPDecl->propimpl_end(); I != EI; ++I)
+ PropImplMap.insert((*I)->getPropertyDecl());
+
+ for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+ P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = P->second;
+ // Is there a matching propery synthesize/dynamic?
+ if (Prop->isInvalidDecl() ||
+ Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+ PropImplMap.count(Prop))
+ continue;
+ if (!InsMap.count(Prop->getGetterName())) {
+ Diag(Prop->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Prop->getGetterName();
+ Diag(IMPDecl->getLocation(),
+ diag::note_property_impl_required);
+ }
+
+ if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
+ Diag(Prop->getLocation(),
+ isa<ObjCCategoryDecl>(CDecl) ?
+ diag::warn_setter_getter_impl_required_in_category :
+ diag::warn_setter_getter_impl_required)
+ << Prop->getDeclName() << Prop->getSetterName();
+ Diag(IMPDecl->getLocation(),
+ diag::note_property_impl_required);
+ }
+ }
+}
+
+void
+Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
+ ObjCContainerDecl* IDecl) {
+ // Rules apply in non-GC mode only
+ if (getLangOptions().getGCMode() != LangOptions::NonGC)
+ return;
+ for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
+ E = IDecl->prop_end();
+ I != E; ++I) {
+ ObjCPropertyDecl *Property = (*I);
+ ObjCMethodDecl *GetterMethod = 0;
+ ObjCMethodDecl *SetterMethod = 0;
+ bool LookedUpGetterSetter = false;
+
+ unsigned Attributes = Property->getPropertyAttributes();
+ unsigned AttributesAsWrittern = Property->getPropertyAttributesAsWritten();
+
+ if (!(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_atomic) &&
+ !(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
+ GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
+ SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
+ LookedUpGetterSetter = true;
+ if (GetterMethod) {
+ Diag(GetterMethod->getLocation(),
+ diag::warn_default_atomic_custom_getter_setter)
+ << Property->getIdentifier() << 0;
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+ if (SetterMethod) {
+ Diag(SetterMethod->getLocation(),
+ diag::warn_default_atomic_custom_getter_setter)
+ << Property->getIdentifier() << 1;
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+ }
+
+ // We only care about readwrite atomic property.
+ if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
+ !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
+ continue;
+ if (const ObjCPropertyImplDecl *PIDecl
+ = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
+ if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ continue;
+ if (!LookedUpGetterSetter) {
+ GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
+ SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
+ LookedUpGetterSetter = true;
+ }
+ if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
+ SourceLocation MethodLoc =
+ (GetterMethod ? GetterMethod->getLocation()
+ : SetterMethod->getLocation());
+ Diag(MethodLoc, diag::warn_atomic_property_rule)
+ << Property->getIdentifier();
+ Diag(Property->getLocation(), diag::note_property_declare);
+ }
+ }
+ }
+}
+
+/// AddPropertyAttrs - Propagates attributes from a property to the
+/// implicitly-declared getter or setter for that property.
+static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
+ ObjCPropertyDecl *Property) {
+ // Should we just clone all attributes over?
+ if (DeprecatedAttr *A = Property->getAttr<DeprecatedAttr>())
+ PropertyMethod->addAttr(A->clone(S.Context));
+ if (UnavailableAttr *A = Property->getAttr<UnavailableAttr>())
+ PropertyMethod->addAttr(A->clone(S.Context));
+}
+
+/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
+/// have the property type and issue diagnostics if they don't.
+/// Also synthesize a getter/setter method if none exist (and update the
+/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
+/// methods is the "right" thing to do.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
+ ObjCContainerDecl *CD,
+ ObjCPropertyDecl *redeclaredProperty,
+ ObjCContainerDecl *lexicalDC) {
+
+ ObjCMethodDecl *GetterMethod, *SetterMethod;
+
+ GetterMethod = CD->getInstanceMethod(property->getGetterName());
+ SetterMethod = CD->getInstanceMethod(property->getSetterName());
+ DiagnosePropertyAccessorMismatch(property, GetterMethod,
+ property->getLocation());
+
+ if (SetterMethod) {
+ ObjCPropertyDecl::PropertyAttributeKind CAttr =
+ property->getPropertyAttributes();
+ if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
+ Context.getCanonicalType(SetterMethod->getResultType()) !=
+ Context.VoidTy)
+ Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
+ if (SetterMethod->param_size() != 1 ||
+ ((*SetterMethod->param_begin())->getType() != property->getType())) {
+ Diag(property->getLocation(),
+ diag::warn_accessor_property_type_mismatch)
+ << property->getDeclName()
+ << SetterMethod->getSelector();
+ Diag(SetterMethod->getLocation(), diag::note_declared_at);
+ }
+ }
+
+ // Synthesize getter/setter methods if none exist.
+ // Find the default getter and if one not found, add one.
+ // FIXME: The synthesized property we set here is misleading. We almost always
+ // synthesize these methods unless the user explicitly provided prototypes
+ // (which is odd, but allowed). Sema should be typechecking that the
+ // declarations jive in that situation (which it is not currently).
+ if (!GetterMethod) {
+ // No instance method of same name as property getter name was found.
+ // Declare a getter method and add it to the list of methods
+ // for this class.
+ SourceLocation Loc = redeclaredProperty ?
+ redeclaredProperty->getLocation() :
+ property->getLocation();
+
+ GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
+ property->getGetterName(),
+ property->getType(), 0, CD, true, false, true,
+ false,
+ (property->getPropertyImplementation() ==
+ ObjCPropertyDecl::Optional) ?
+ ObjCMethodDecl::Optional :
+ ObjCMethodDecl::Required);
+ CD->addDecl(GetterMethod);
+
+ AddPropertyAttrs(*this, GetterMethod, property);
+
+ // FIXME: Eventually this shouldn't be needed, as the lexical context
+ // and the real context should be the same.
+ if (lexicalDC)
+ GetterMethod->setLexicalDeclContext(lexicalDC);
+ } else
+ // A user declared getter will be synthesize when @synthesize of
+ // the property with the same name is seen in the @implementation
+ GetterMethod->setSynthesized(true);
+ property->setGetterMethodDecl(GetterMethod);
+
+ // Skip setter if property is read-only.
+ if (!property->isReadOnly()) {
+ // Find the default setter and if one not found, add one.
+ if (!SetterMethod) {
+ // No instance method of same name as property setter name was found.
+ // Declare a setter method and add it to the list of methods
+ // for this class.
+ SourceLocation Loc = redeclaredProperty ?
+ redeclaredProperty->getLocation() :
+ property->getLocation();
+
+ SetterMethod =
+ ObjCMethodDecl::Create(Context, Loc, Loc,
+ property->getSetterName(), Context.VoidTy, 0,
+ CD, true, false, true, false,
+ (property->getPropertyImplementation() ==
+ ObjCPropertyDecl::Optional) ?
+ ObjCMethodDecl::Optional :
+ ObjCMethodDecl::Required);
+
+ // Invent the arguments for the setter. We don't bother making a
+ // nice name for the argument.
+ ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, Loc,
+ property->getIdentifier(),
+ property->getType(),
+ /*TInfo=*/0,
+ SC_None,
+ SC_None,
+ 0);
+ SetterMethod->setMethodParams(Context, &Argument, 1, 1);
+
+ AddPropertyAttrs(*this, SetterMethod, property);
+
+ CD->addDecl(SetterMethod);
+ // FIXME: Eventually this shouldn't be needed, as the lexical context
+ // and the real context should be the same.
+ if (lexicalDC)
+ SetterMethod->setLexicalDeclContext(lexicalDC);
+ } else
+ // A user declared setter will be synthesize when @synthesize of
+ // the property with the same name is seen in the @implementation
+ SetterMethod->setSynthesized(true);
+ property->setSetterMethodDecl(SetterMethod);
+ }
+ // Add any synthesized methods to the global pool. This allows us to
+ // handle the following, which is supported by GCC (and part of the design).
+ //
+ // @interface Foo
+ // @property double bar;
+ // @end
+ //
+ // void thisIsUnfortunate() {
+ // id foo;
+ // double bar = [foo bar];
+ // }
+ //
+ if (GetterMethod)
+ AddInstanceMethodToGlobalPool(GetterMethod);
+ if (SetterMethod)
+ AddInstanceMethodToGlobalPool(SetterMethod);
+}
+
+void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
+ SourceLocation Loc,
+ unsigned &Attributes) {
+ // FIXME: Improve the reported location.
+ if (!PDecl)
+ return;
+
+ ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
+ QualType PropertyTy = PropertyDecl->getType();
+
+ // readonly and readwrite/assign/retain/copy conflict.
+ if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
+ ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain))) {
+ const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
+ "readwrite" :
+ (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
+ "assign" :
+ (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
+ "copy" : "retain";
+
+ Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
+ diag::err_objc_property_attr_mutually_exclusive :
+ diag::warn_objc_property_attr_mutually_exclusive)
+ << "readonly" << which;
+ }
+
+ // Check for copy or retain on non-object types.
+ if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) &&
+ !PropertyTy->isObjCObjectPointerType() &&
+ !PropertyTy->isBlockPointerType() &&
+ !Context.isObjCNSObjectType(PropertyTy) &&
+ !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
+ Diag(Loc, diag::err_objc_property_requires_object)
+ << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain");
+ Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain);
+ }
+
+ // Check for more than one of { assign, copy, retain }.
+ if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+ << "assign" << "copy";
+ Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
+ }
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+ << "assign" << "retain";
+ Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+ }
+ } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
+ Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+ << "copy" << "retain";
+ Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
+ }
+ }
+
+ // Warn if user supplied no assignment attribute, property is
+ // readwrite, and this is an object type.
+ if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
+ ObjCDeclSpec::DQ_PR_retain)) &&
+ !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+ PropertyTy->isObjCObjectPointerType()) {
+ // Skip this warning in gc-only mode.
+ if (getLangOptions().getGCMode() != LangOptions::GCOnly)
+ Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
+
+ // If non-gc code warn that this is likely inappropriate.
+ if (getLangOptions().getGCMode() == LangOptions::NonGC)
+ Diag(Loc, diag::warn_objc_property_default_assign_on_object);
+
+ // FIXME: Implement warning dependent on NSCopying being
+ // implemented. See also:
+ // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
+ // (please trim this list while you are at it).
+ }
+
+ if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
+ &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly)
+ && getLangOptions().getGCMode() == LangOptions::GCOnly
+ && PropertyTy->isBlockPointerType())
+ Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
new file mode 100644
index 0000000..6fb789c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -0,0 +1,8984 @@
+//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Sema routines for C++ overloading.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
+
+namespace clang {
+using namespace sema;
+
+/// A convenience routine for creating a decayed reference to a
+/// function.
+static Expr *
+CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn,
+ SourceLocation Loc = SourceLocation()) {
+ Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc);
+ S.DefaultFunctionArrayConversion(E);
+ return E;
+}
+
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS,
+ bool CStyle);
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+ UserDefinedConversionSequence& User,
+ OverloadCandidateSet& Conversions,
+ bool AllowExplicit);
+
+
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareQualificationConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareDerivedToBaseConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+
+
+/// GetConversionCategory - Retrieve the implicit conversion
+/// category corresponding to the given implicit conversion kind.
+ImplicitConversionCategory
+GetConversionCategory(ImplicitConversionKind Kind) {
+ static const ImplicitConversionCategory
+ Category[(int)ICK_Num_Conversion_Kinds] = {
+ ICC_Identity,
+ ICC_Lvalue_Transformation,
+ ICC_Lvalue_Transformation,
+ ICC_Lvalue_Transformation,
+ ICC_Identity,
+ ICC_Qualification_Adjustment,
+ ICC_Promotion,
+ ICC_Promotion,
+ ICC_Promotion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion,
+ ICC_Conversion
+ };
+ return Category[(int)Kind];
+}
+
+/// GetConversionRank - Retrieve the implicit conversion rank
+/// corresponding to the given implicit conversion kind.
+ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
+ static const ImplicitConversionRank
+ Rank[(int)ICK_Num_Conversion_Kinds] = {
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Exact_Match,
+ ICR_Promotion,
+ ICR_Promotion,
+ ICR_Promotion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Conversion,
+ ICR_Complex_Real_Conversion
+ };
+ return Rank[(int)Kind];
+}
+
+/// GetImplicitConversionName - Return the name of this kind of
+/// implicit conversion.
+const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
+ static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
+ "No conversion",
+ "Lvalue-to-rvalue",
+ "Array-to-pointer",
+ "Function-to-pointer",
+ "Noreturn adjustment",
+ "Qualification",
+ "Integral promotion",
+ "Floating point promotion",
+ "Complex promotion",
+ "Integral conversion",
+ "Floating conversion",
+ "Complex conversion",
+ "Floating-integral conversion",
+ "Pointer conversion",
+ "Pointer-to-member conversion",
+ "Boolean conversion",
+ "Compatible-types conversion",
+ "Derived-to-base conversion",
+ "Vector conversion",
+ "Vector splat",
+ "Complex-real conversion"
+ };
+ return Name[Kind];
+}
+
+/// StandardConversionSequence - Set the standard conversion
+/// sequence to the identity conversion.
+void StandardConversionSequence::setAsIdentityConversion() {
+ First = ICK_Identity;
+ Second = ICK_Identity;
+ Third = ICK_Identity;
+ DeprecatedStringLiteralToCharPtr = false;
+ ReferenceBinding = false;
+ DirectBinding = false;
+ IsLvalueReference = true;
+ BindsToFunctionLvalue = false;
+ BindsToRvalue = false;
+ BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ CopyConstructor = 0;
+}
+
+/// getRank - Retrieve the rank of this standard conversion sequence
+/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the
+/// implicit conversions.
+ImplicitConversionRank StandardConversionSequence::getRank() const {
+ ImplicitConversionRank Rank = ICR_Exact_Match;
+ if (GetConversionRank(First) > Rank)
+ Rank = GetConversionRank(First);
+ if (GetConversionRank(Second) > Rank)
+ Rank = GetConversionRank(Second);
+ if (GetConversionRank(Third) > Rank)
+ Rank = GetConversionRank(Third);
+ return Rank;
+}
+
+/// isPointerConversionToBool - Determines whether this conversion is
+/// a conversion of a pointer or pointer-to-member to bool. This is
+/// used as part of the ranking of standard conversion sequences
+/// (C++ 13.3.3.2p4).
+bool StandardConversionSequence::isPointerConversionToBool() const {
+ // Note that FromType has not necessarily been transformed by the
+ // array-to-pointer or function-to-pointer implicit conversions, so
+ // check for their presence as well as checking whether FromType is
+ // a pointer.
+ if (getToType(1)->isBooleanType() &&
+ (getFromType()->isPointerType() ||
+ getFromType()->isObjCObjectPointerType() ||
+ getFromType()->isBlockPointerType() ||
+ getFromType()->isNullPtrType() ||
+ First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
+ return true;
+
+ return false;
+}
+
+/// isPointerConversionToVoidPointer - Determines whether this
+/// conversion is a conversion of a pointer to a void pointer. This is
+/// used as part of the ranking of standard conversion sequences (C++
+/// 13.3.3.2p4).
+bool
+StandardConversionSequence::
+isPointerConversionToVoidPointer(ASTContext& Context) const {
+ QualType FromType = getFromType();
+ QualType ToType = getToType(1);
+
+ // Note that FromType has not necessarily been transformed by the
+ // array-to-pointer implicit conversion, so check for its presence
+ // and redo the conversion to get a pointer.
+ if (First == ICK_Array_To_Pointer)
+ FromType = Context.getArrayDecayedType(FromType);
+
+ if (Second == ICK_Pointer_Conversion && FromType->isPointerType())
+ if (const PointerType* ToPtrType = ToType->getAs<PointerType>())
+ return ToPtrType->getPointeeType()->isVoidType();
+
+ return false;
+}
+
+/// DebugPrint - Print this standard conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void StandardConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
+ bool PrintedSomething = false;
+ if (First != ICK_Identity) {
+ OS << GetImplicitConversionName(First);
+ PrintedSomething = true;
+ }
+
+ if (Second != ICK_Identity) {
+ if (PrintedSomething) {
+ OS << " -> ";
+ }
+ OS << GetImplicitConversionName(Second);
+
+ if (CopyConstructor) {
+ OS << " (by copy constructor)";
+ } else if (DirectBinding) {
+ OS << " (direct reference binding)";
+ } else if (ReferenceBinding) {
+ OS << " (reference binding)";
+ }
+ PrintedSomething = true;
+ }
+
+ if (Third != ICK_Identity) {
+ if (PrintedSomething) {
+ OS << " -> ";
+ }
+ OS << GetImplicitConversionName(Third);
+ PrintedSomething = true;
+ }
+
+ if (!PrintedSomething) {
+ OS << "No conversions required";
+ }
+}
+
+/// DebugPrint - Print this user-defined conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void UserDefinedConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
+ if (Before.First || Before.Second || Before.Third) {
+ Before.DebugPrint();
+ OS << " -> ";
+ }
+ OS << '\'' << ConversionFunction << '\'';
+ if (After.First || After.Second || After.Third) {
+ OS << " -> ";
+ After.DebugPrint();
+ }
+}
+
+/// DebugPrint - Print this implicit conversion sequence to standard
+/// error. Useful for debugging overloading issues.
+void ImplicitConversionSequence::DebugPrint() const {
+ llvm::raw_ostream &OS = llvm::errs();
+ switch (ConversionKind) {
+ case StandardConversion:
+ OS << "Standard conversion: ";
+ Standard.DebugPrint();
+ break;
+ case UserDefinedConversion:
+ OS << "User-defined conversion: ";
+ UserDefined.DebugPrint();
+ break;
+ case EllipsisConversion:
+ OS << "Ellipsis conversion";
+ break;
+ case AmbiguousConversion:
+ OS << "Ambiguous conversion";
+ break;
+ case BadConversion:
+ OS << "Bad conversion";
+ break;
+ }
+
+ OS << "\n";
+}
+
+void AmbiguousConversionSequence::construct() {
+ new (&conversions()) ConversionSet();
+}
+
+void AmbiguousConversionSequence::destruct() {
+ conversions().~ConversionSet();
+}
+
+void
+AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
+ FromTypePtr = O.FromTypePtr;
+ ToTypePtr = O.ToTypePtr;
+ new (&conversions()) ConversionSet(O.conversions());
+}
+
+namespace {
+ // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // template parameter and template argument information.
+ struct DFIParamWithArguments {
+ TemplateParameter Param;
+ TemplateArgument FirstArg;
+ TemplateArgument SecondArg;
+ };
+}
+
+/// \brief Convert from Sema's representation of template deduction information
+/// to the form used in overload-candidate information.
+OverloadCandidate::DeductionFailureInfo
+static MakeDeductionFailureInfo(ASTContext &Context,
+ Sema::TemplateDeductionResult TDK,
+ TemplateDeductionInfo &Info) {
+ OverloadCandidate::DeductionFailureInfo Result;
+ Result.Result = static_cast<unsigned>(TDK);
+ Result.Data = 0;
+ switch (TDK) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ break;
+
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_InvalidExplicitArguments:
+ Result.Data = Info.Param.getOpaqueValue();
+ break;
+
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified: {
+ // FIXME: Should allocate from normal heap so that we can free this later.
+ DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
+ Saved->Param = Info.Param;
+ Saved->FirstArg = Info.FirstArg;
+ Saved->SecondArg = Info.SecondArg;
+ Result.Data = Saved;
+ break;
+ }
+
+ case Sema::TDK_SubstitutionFailure:
+ Result.Data = Info.take();
+ break;
+
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+
+ return Result;
+}
+
+void OverloadCandidate::DeductionFailureInfo::Destroy() {
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_InvalidExplicitArguments:
+ break;
+
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ // FIXME: Destroy the data?
+ Data = 0;
+ break;
+
+ case Sema::TDK_SubstitutionFailure:
+ // FIXME: Destroy the template arugment list?
+ Data = 0;
+ break;
+
+ // Unhandled
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+}
+
+TemplateParameter
+OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_SubstitutionFailure:
+ return TemplateParameter();
+
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_InvalidExplicitArguments:
+ return TemplateParameter::getFromOpaqueValue(Data);
+
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ return static_cast<DFIParamWithArguments*>(Data)->Param;
+
+ // Unhandled
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+
+ return TemplateParameter();
+}
+
+TemplateArgumentList *
+OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ return 0;
+
+ case Sema::TDK_SubstitutionFailure:
+ return static_cast<TemplateArgumentList*>(Data);
+
+ // Unhandled
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+
+ return 0;
+}
+
+const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_SubstitutionFailure:
+ return 0;
+
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
+
+ // Unhandled
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+
+ return 0;
+}
+
+const TemplateArgument *
+OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+ switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+ case Sema::TDK_Success:
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_Incomplete:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_SubstitutionFailure:
+ return 0;
+
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_Underqualified:
+ return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
+
+ // Unhandled
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ break;
+ }
+
+ return 0;
+}
+
+void OverloadCandidateSet::clear() {
+ inherited::clear();
+ Functions.clear();
+}
+
+// IsOverload - Determine whether the given New declaration is an
+// overload of the declarations in Old. This routine returns false if
+// New and Old cannot be overloaded, e.g., if New has the same
+// signature as some function in Old (C++ 1.3.10) or if the Old
+// declarations aren't functions (or function templates) at all. When
+// it does return false, MatchedDecl will point to the decl that New
+// cannot be overloaded with. This decl may be a UsingShadowDecl on
+// top of the underlying declaration.
+//
+// Example: Given the following input:
+//
+// void f(int, float); // #1
+// void f(int, int); // #2
+// int f(int, int); // #3
+//
+// When we process #1, there is no previous declaration of "f",
+// so IsOverload will not be used.
+//
+// When we process #2, Old contains only the FunctionDecl for #1. By
+// comparing the parameter types, we see that #1 and #2 are overloaded
+// (since they have different signatures), so this routine returns
+// false; MatchedDecl is unchanged.
+//
+// When we process #3, Old is an overload set containing #1 and #2. We
+// compare the signatures of #3 to #1 (they're overloaded, so we do
+// nothing) and then #3 to #2. Since the signatures of #3 and #2 are
+// identical (return types of functions are not part of the
+// signature), IsOverload returns false and MatchedDecl will be set to
+// point to the FunctionDecl for #2.
+//
+// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced
+// into a class by a using declaration. The rules for whether to hide
+// shadow declarations ignore some properties which otherwise figure
+// into a function template's signature.
+Sema::OverloadKind
+Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
+ NamedDecl *&Match, bool NewIsUsingDecl) {
+ for (LookupResult::iterator I = Old.begin(), E = Old.end();
+ I != E; ++I) {
+ NamedDecl *OldD = *I;
+
+ bool OldIsUsingDecl = false;
+ if (isa<UsingShadowDecl>(OldD)) {
+ OldIsUsingDecl = true;
+
+ // We can always introduce two using declarations into the same
+ // context, even if they have identical signatures.
+ if (NewIsUsingDecl) continue;
+
+ OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
+ }
+
+ // If either declaration was introduced by a using declaration,
+ // we'll need to use slightly different rules for matching.
+ // Essentially, these rules are the normal rules, except that
+ // function templates hide function templates with different
+ // return types or template parameter lists.
+ bool UseMemberUsingDeclRules =
+ (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord();
+
+ if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
+ if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
+ if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+ HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+ continue;
+ }
+
+ Match = *I;
+ return Ovl_Match;
+ }
+ } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
+ if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
+ if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+ HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+ continue;
+ }
+
+ Match = *I;
+ return Ovl_Match;
+ }
+ } else if (isa<UsingDecl>(OldD)) {
+ // We can overload with these, which can show up when doing
+ // redeclaration checks for UsingDecls.
+ assert(Old.getLookupKind() == LookupUsingDeclName);
+ } else if (isa<TagDecl>(OldD)) {
+ // We can always overload with tags by hiding them.
+ } else if (isa<UnresolvedUsingValueDecl>(OldD)) {
+ // Optimistically assume that an unresolved using decl will
+ // overload; if it doesn't, we'll have to diagnose during
+ // template instantiation.
+ } else {
+ // (C++ 13p1):
+ // Only function declarations can be overloaded; object and type
+ // declarations cannot be overloaded.
+ Match = *I;
+ return Ovl_NonFunction;
+ }
+ }
+
+ return Ovl_Overload;
+}
+
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+ bool UseUsingDeclRules) {
+ // If both of the functions are extern "C", then they are not
+ // overloads.
+ if (Old->isExternC() && New->isExternC())
+ return false;
+
+ FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
+
+ // C++ [temp.fct]p2:
+ // A function template can be overloaded with other function templates
+ // and with normal (non-template) functions.
+ if ((OldTemplate == 0) != (NewTemplate == 0))
+ return true;
+
+ // Is the function New an overload of the function Old?
+ QualType OldQType = Context.getCanonicalType(Old->getType());
+ QualType NewQType = Context.getCanonicalType(New->getType());
+
+ // Compare the signatures (C++ 1.3.10) of the two functions to
+ // determine whether they are overloads. If we find any mismatch
+ // in the signature, they are overloads.
+
+ // If either of these functions is a K&R-style function (no
+ // prototype), then we consider them to have matching signatures.
+ if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
+ isa<FunctionNoProtoType>(NewQType.getTypePtr()))
+ return false;
+
+ const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+ const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+
+ // The signature of a function includes the types of its
+ // parameters (C++ 1.3.10), which includes the presence or absence
+ // of the ellipsis; see C++ DR 357).
+ if (OldQType != NewQType &&
+ (OldType->getNumArgs() != NewType->getNumArgs() ||
+ OldType->isVariadic() != NewType->isVariadic() ||
+ !FunctionArgTypesAreEqual(OldType, NewType)))
+ return true;
+
+ // C++ [temp.over.link]p4:
+ // The signature of a function template consists of its function
+ // signature, its return type and its template parameter list. The names
+ // of the template parameters are significant only for establishing the
+ // relationship between the template parameters and the rest of the
+ // signature.
+ //
+ // We check the return type and template parameter lists for function
+ // templates first; the remaining checks follow.
+ //
+ // However, we don't consider either of these when deciding whether
+ // a member introduced by a shadow declaration is hidden.
+ if (!UseUsingDeclRules && NewTemplate &&
+ (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ false, TPL_TemplateMatch) ||
+ OldType->getResultType() != NewType->getResultType()))
+ return true;
+
+ // If the function is a class member, its signature includes the
+ // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
+ //
+ // As part of this, also check whether one of the member functions
+ // is static, in which case they are not overloads (C++
+ // 13.1p2). While not part of the definition of the signature,
+ // this check is important to determine whether these functions
+ // can be overloaded.
+ CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+ CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+ if (OldMethod && NewMethod &&
+ !OldMethod->isStatic() && !NewMethod->isStatic() &&
+ (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() ||
+ OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) {
+ if (!UseUsingDeclRules &&
+ OldMethod->getRefQualifier() != NewMethod->getRefQualifier() &&
+ (OldMethod->getRefQualifier() == RQ_None ||
+ NewMethod->getRefQualifier() == RQ_None)) {
+ // C++0x [over.load]p2:
+ // - Member function declarations with the same name and the same
+ // parameter-type-list as well as member function template
+ // declarations with the same name, the same parameter-type-list, and
+ // the same template parameter lists cannot be overloaded if any of
+ // them, but not all, have a ref-qualifier (8.3.5).
+ Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
+ << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+ Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+ }
+
+ return true;
+ }
+
+ // The signatures match; this is not an overload.
+ return false;
+}
+
+/// TryImplicitConversion - Attempt to perform an implicit conversion
+/// from the given expression (Expr) to the given type (ToType). This
+/// function returns an implicit conversion sequence that can be used
+/// to perform the initialization. Given
+///
+/// void f(float f);
+/// void g(int i) { f(i); }
+///
+/// this routine would produce an implicit conversion sequence to
+/// describe the initialization of f from i, which will be a standard
+/// conversion sequence containing an lvalue-to-rvalue conversion (C++
+/// 4.1) followed by a floating-integral conversion (C++ 4.9).
+//
+/// Note that this routine only determines how the conversion can be
+/// performed; it does not actually perform the conversion. As such,
+/// it will not produce any diagnostics if no conversion is available,
+/// but will instead return an implicit conversion sequence of kind
+/// "BadConversion".
+///
+/// If @p SuppressUserConversions, then user-defined conversions are
+/// not permitted.
+/// If @p AllowExplicit, then explicit user-defined conversions are
+/// permitted.
+static ImplicitConversionSequence
+TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle) {
+ ImplicitConversionSequence ICS;
+ if (IsStandardConversion(S, From, ToType, InOverloadResolution,
+ ICS.Standard, CStyle)) {
+ ICS.setStandard();
+ return ICS;
+ }
+
+ if (!S.getLangOptions().CPlusPlus) {
+ ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+ return ICS;
+ }
+
+ // C++ [over.ics.user]p4:
+ // A conversion of an expression of class type to the same class
+ // type is given Exact Match rank, and a conversion of an
+ // expression of class type to a base class of that type is
+ // given Conversion rank, in spite of the fact that a copy/move
+ // constructor (i.e., a user-defined conversion function) is
+ // called for those cases.
+ QualType FromType = From->getType();
+ if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
+ (S.Context.hasSameUnqualifiedType(FromType, ToType) ||
+ S.IsDerivedFrom(FromType, ToType))) {
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.setFromType(FromType);
+ ICS.Standard.setAllToTypes(ToType);
+
+ // We don't actually check at this point whether there is a valid
+ // copy/move constructor, since overloading just assumes that it
+ // exists. When we actually perform initialization, we'll find the
+ // appropriate constructor to copy the returned object, if needed.
+ ICS.Standard.CopyConstructor = 0;
+
+ // Determine whether this is considered a derived-to-base conversion.
+ if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
+ ICS.Standard.Second = ICK_Derived_To_Base;
+
+ return ICS;
+ }
+
+ if (SuppressUserConversions) {
+ // We're not in the case above, so there is no conversion that
+ // we can perform.
+ ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+ return ICS;
+ }
+
+ // Attempt user-defined conversion.
+ OverloadCandidateSet Conversions(From->getExprLoc());
+ OverloadingResult UserDefResult
+ = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
+ AllowExplicit);
+
+ if (UserDefResult == OR_Success) {
+ ICS.setUserDefined();
+ // C++ [over.ics.user]p4:
+ // A conversion of an expression of class type to the same class
+ // type is given Exact Match rank, and a conversion of an
+ // expression of class type to a base class of that type is
+ // given Conversion rank, in spite of the fact that a copy
+ // constructor (i.e., a user-defined conversion function) is
+ // called for those cases.
+ if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
+ QualType FromCanon
+ = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+ QualType ToCanon
+ = S.Context.getCanonicalType(ToType).getUnqualifiedType();
+ if (Constructor->isCopyConstructor() &&
+ (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
+ // Turn this into a "standard" conversion sequence, so that it
+ // gets ranked with standard conversion sequences.
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.setFromType(From->getType());
+ ICS.Standard.setAllToTypes(ToType);
+ ICS.Standard.CopyConstructor = Constructor;
+ if (ToCanon != FromCanon)
+ ICS.Standard.Second = ICK_Derived_To_Base;
+ }
+ }
+
+ // C++ [over.best.ics]p4:
+ // However, when considering the argument of a user-defined
+ // conversion function that is a candidate by 13.3.1.3 when
+ // invoked for the copying of the temporary in the second step
+ // of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
+ // 13.3.1.6 in all cases, only standard conversion sequences and
+ // ellipsis conversion sequences are allowed.
+ if (SuppressUserConversions && ICS.isUserDefined()) {
+ ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
+ }
+ } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
+ ICS.setAmbiguous();
+ ICS.Ambiguous.setFromType(From->getType());
+ ICS.Ambiguous.setToType(ToType);
+ for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+ Cand != Conversions.end(); ++Cand)
+ if (Cand->Viable)
+ ICS.Ambiguous.addConversion(Cand->Function);
+ } else {
+ ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+ }
+
+ return ICS;
+}
+
+bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *Initializer,
+ bool SuppressUserConversions,
+ bool AllowExplicitConversions,
+ bool InOverloadResolution,
+ bool CStyle) {
+ ImplicitConversionSequence ICS
+ = clang::TryImplicitConversion(*this, Initializer, Entity.getType(),
+ SuppressUserConversions,
+ AllowExplicitConversions,
+ InOverloadResolution,
+ CStyle);
+ if (ICS.isBad()) return true;
+
+ // Perform the actual conversion.
+ Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+ return false;
+}
+
+/// PerformImplicitConversion - Perform an implicit conversion of the
+/// expression From to the type ToType. Returns true if there was an
+/// error, false otherwise. The expression From is replaced with the
+/// converted expression. Flavor is the kind of conversion we're
+/// performing, used in the error message. If @p AllowExplicit,
+/// explicit user-defined conversions are permitted.
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action, bool AllowExplicit) {
+ ImplicitConversionSequence ICS;
+ return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
+}
+
+bool
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ AssignmentAction Action, bool AllowExplicit,
+ ImplicitConversionSequence& ICS) {
+ ICS = clang::TryImplicitConversion(*this, From, ToType,
+ /*SuppressUserConversions=*/false,
+ AllowExplicit,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
+ return PerformImplicitConversion(From, ToType, ICS, Action);
+}
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// conversion that strips "noreturn" off the nested function type.
+static bool IsNoReturnConversion(ASTContext &Context, QualType FromType,
+ QualType ToType, QualType &ResultTy) {
+ if (Context.hasSameUnqualifiedType(FromType, ToType))
+ return false;
+
+ // Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+ // where F adds one of the following at most once:
+ // - a pointer
+ // - a member pointer
+ // - a block pointer
+ CanQualType CanTo = Context.getCanonicalType(ToType);
+ CanQualType CanFrom = Context.getCanonicalType(FromType);
+ Type::TypeClass TyClass = CanTo->getTypeClass();
+ if (TyClass != CanFrom->getTypeClass()) return false;
+ if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) {
+ if (TyClass == Type::Pointer) {
+ CanTo = CanTo.getAs<PointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<PointerType>()->getPointeeType();
+ } else if (TyClass == Type::BlockPointer) {
+ CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
+ } else if (TyClass == Type::MemberPointer) {
+ CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
+ } else {
+ return false;
+ }
+
+ TyClass = CanTo->getTypeClass();
+ if (TyClass != CanFrom->getTypeClass()) return false;
+ if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
+ return false;
+ }
+
+ const FunctionType *FromFn = cast<FunctionType>(CanFrom);
+ FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
+ if (!EInfo.getNoReturn()) return false;
+
+ FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
+ assert(QualType(FromFn, 0).isCanonical());
+ if (QualType(FromFn, 0) != CanTo) return false;
+
+ ResultTy = ToType;
+ return true;
+}
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid
+/// vector conversion.
+///
+/// \param ICK Will be set to the vector conversion kind, if this is a vector
+/// conversion.
+static bool IsVectorConversion(ASTContext &Context, QualType FromType,
+ QualType ToType, ImplicitConversionKind &ICK) {
+ // We need at least one of these types to be a vector type to have a vector
+ // conversion.
+ if (!ToType->isVectorType() && !FromType->isVectorType())
+ return false;
+
+ // Identical types require no conversions.
+ if (Context.hasSameUnqualifiedType(FromType, ToType))
+ return false;
+
+ // There are no conversions between extended vector types, only identity.
+ if (ToType->isExtVectorType()) {
+ // There are no conversions between extended vector types other than the
+ // identity conversion.
+ if (FromType->isExtVectorType())
+ return false;
+
+ // Vector splat from any arithmetic type to a vector.
+ if (FromType->isArithmeticType()) {
+ ICK = ICK_Vector_Splat;
+ return true;
+ }
+ }
+
+ // We can perform the conversion between vector types in the following cases:
+ // 1)vector types are equivalent AltiVec and GCC vector types
+ // 2)lax vector conversions are permitted and the vector types are of the
+ // same size
+ if (ToType->isVectorType() && FromType->isVectorType()) {
+ if (Context.areCompatibleVectorTypes(FromType, ToType) ||
+ (Context.getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) {
+ ICK = ICK_Vector_Conversion;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// IsStandardConversion - Determines whether there is a standard
+/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
+/// expression From to the type ToType. Standard conversion sequences
+/// only consider non-class types; for conversions that involve class
+/// types, use TryImplicitConversion. If a conversion exists, SCS will
+/// contain the standard conversion sequence required to perform this
+/// conversion and this routine will return true. Otherwise, this
+/// routine will return false and the value of SCS is unspecified.
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS,
+ bool CStyle) {
+ QualType FromType = From->getType();
+
+ // Standard conversions (C++ [conv])
+ SCS.setAsIdentityConversion();
+ SCS.DeprecatedStringLiteralToCharPtr = false;
+ SCS.IncompatibleObjC = false;
+ SCS.setFromType(FromType);
+ SCS.CopyConstructor = 0;
+
+ // There are no standard conversions for class types in C++, so
+ // abort early. When overloading in C, however, we do permit
+ if (FromType->isRecordType() || ToType->isRecordType()) {
+ if (S.getLangOptions().CPlusPlus)
+ return false;
+
+ // When we're overloading in C, we allow, as standard conversions,
+ }
+
+ // The first conversion can be an lvalue-to-rvalue conversion,
+ // array-to-pointer conversion, or function-to-pointer conversion
+ // (C++ 4p1).
+
+ if (FromType == S.Context.OverloadTy) {
+ DeclAccessPair AccessPair;
+ if (FunctionDecl *Fn
+ = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
+ AccessPair)) {
+ // We were able to resolve the address of the overloaded function,
+ // so we can convert to the type of that function.
+ FromType = Fn->getType();
+
+ // we can sometimes resolve &foo<int> regardless of ToType, so check
+ // if the type matches (identity) or we are converting to bool
+ if (!S.Context.hasSameUnqualifiedType(
+ S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
+ QualType resultTy;
+ // if the function type matches except for [[noreturn]], it's ok
+ if (!IsNoReturnConversion(S.Context, FromType,
+ S.ExtractUnqualifiedFunctionType(ToType), resultTy))
+ // otherwise, only a boolean conversion is standard
+ if (!ToType->isBooleanType())
+ return false;
+
+ }
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+ if (!Method->isStatic()) {
+ const Type *ClassType
+ = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FromType = S.Context.getMemberPointerType(FromType, ClassType);
+ }
+ }
+
+ // If the "from" expression takes the address of the overloaded
+ // function, update the type of the resulting expression accordingly.
+ if (FromType->getAs<FunctionType>())
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens()))
+ if (UnOp->getOpcode() == UO_AddrOf)
+ FromType = S.Context.getPointerType(FromType);
+
+ // Check that we've computed the proper type after overload resolution.
+ assert(S.Context.hasSameType(FromType,
+ S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
+ } else {
+ return false;
+ }
+ }
+ // Lvalue-to-rvalue conversion (C++ 4.1):
+ // An lvalue (3.10) of a non-function, non-array type T can be
+ // converted to an rvalue.
+ bool argIsLValue = From->isLValue();
+ if (argIsLValue &&
+ !FromType->isFunctionType() && !FromType->isArrayType() &&
+ S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
+ SCS.First = ICK_Lvalue_To_Rvalue;
+
+ // If T is a non-class type, the type of the rvalue is the
+ // cv-unqualified version of T. Otherwise, the type of the rvalue
+ // is T (C++ 4.1p1). C++ can't get here with class types; in C, we
+ // just strip the qualifiers because they don't matter.
+ FromType = FromType.getUnqualifiedType();
+ } else if (FromType->isArrayType()) {
+ // Array-to-pointer conversion (C++ 4.2)
+ SCS.First = ICK_Array_To_Pointer;
+
+ // An lvalue or rvalue of type "array of N T" or "array of unknown
+ // bound of T" can be converted to an rvalue of type "pointer to
+ // T" (C++ 4.2p1).
+ FromType = S.Context.getArrayDecayedType(FromType);
+
+ if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
+ // This conversion is deprecated. (C++ D.4).
+ SCS.DeprecatedStringLiteralToCharPtr = true;
+
+ // For the purpose of ranking in overload resolution
+ // (13.3.3.1.1), this conversion is considered an
+ // array-to-pointer conversion followed by a qualification
+ // conversion (4.4). (C++ 4.2p2)
+ SCS.Second = ICK_Identity;
+ SCS.Third = ICK_Qualification;
+ SCS.setAllToTypes(FromType);
+ return true;
+ }
+ } else if (FromType->isFunctionType() && argIsLValue) {
+ // Function-to-pointer conversion (C++ 4.3).
+ SCS.First = ICK_Function_To_Pointer;
+
+ // An lvalue of function type T can be converted to an rvalue of
+ // type "pointer to T." The result is a pointer to the
+ // function. (C++ 4.3p1).
+ FromType = S.Context.getPointerType(FromType);
+ } else {
+ // We don't require any conversions for the first step.
+ SCS.First = ICK_Identity;
+ }
+ SCS.setToType(0, FromType);
+
+ // The second conversion can be an integral promotion, floating
+ // point promotion, integral conversion, floating point conversion,
+ // floating-integral conversion, pointer conversion,
+ // pointer-to-member conversion, or boolean conversion (C++ 4p1).
+ // For overloading in C, this can also be a "compatible-type"
+ // conversion.
+ bool IncompatibleObjC = false;
+ ImplicitConversionKind SecondICK = ICK_Identity;
+ if (S.Context.hasSameUnqualifiedType(FromType, ToType)) {
+ // The unqualified versions of the types are the same: there's no
+ // conversion to do.
+ SCS.Second = ICK_Identity;
+ } else if (S.IsIntegralPromotion(From, FromType, ToType)) {
+ // Integral promotion (C++ 4.5).
+ SCS.Second = ICK_Integral_Promotion;
+ FromType = ToType.getUnqualifiedType();
+ } else if (S.IsFloatingPointPromotion(FromType, ToType)) {
+ // Floating point promotion (C++ 4.6).
+ SCS.Second = ICK_Floating_Promotion;
+ FromType = ToType.getUnqualifiedType();
+ } else if (S.IsComplexPromotion(FromType, ToType)) {
+ // Complex promotion (Clang extension)
+ SCS.Second = ICK_Complex_Promotion;
+ FromType = ToType.getUnqualifiedType();
+ } else if (ToType->isBooleanType() &&
+ (FromType->isArithmeticType() ||
+ FromType->isAnyPointerType() ||
+ FromType->isBlockPointerType() ||
+ FromType->isMemberPointerType() ||
+ FromType->isNullPtrType())) {
+ // Boolean conversions (C++ 4.12).
+ SCS.Second = ICK_Boolean_Conversion;
+ FromType = S.Context.BoolTy;
+ } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
+ ToType->isIntegralType(S.Context)) {
+ // Integral conversions (C++ 4.7).
+ SCS.Second = ICK_Integral_Conversion;
+ FromType = ToType.getUnqualifiedType();
+ } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
+ // Complex conversions (C99 6.3.1.6)
+ SCS.Second = ICK_Complex_Conversion;
+ FromType = ToType.getUnqualifiedType();
+ } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
+ (ToType->isAnyComplexType() && FromType->isArithmeticType())) {
+ // Complex-real conversions (C99 6.3.1.7)
+ SCS.Second = ICK_Complex_Real;
+ FromType = ToType.getUnqualifiedType();
+ } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
+ // Floating point conversions (C++ 4.8).
+ SCS.Second = ICK_Floating_Conversion;
+ FromType = ToType.getUnqualifiedType();
+ } else if ((FromType->isRealFloatingType() &&
+ ToType->isIntegralType(S.Context)) ||
+ (FromType->isIntegralOrUnscopedEnumerationType() &&
+ ToType->isRealFloatingType())) {
+ // Floating-integral conversions (C++ 4.9).
+ SCS.Second = ICK_Floating_Integral;
+ FromType = ToType.getUnqualifiedType();
+ } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) {
+ SCS.Second = ICK_Block_Pointer_Conversion;
+ } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
+ FromType, IncompatibleObjC)) {
+ // Pointer conversions (C++ 4.10).
+ SCS.Second = ICK_Pointer_Conversion;
+ SCS.IncompatibleObjC = IncompatibleObjC;
+ } else if (S.IsMemberPointerConversion(From, FromType, ToType,
+ InOverloadResolution, FromType)) {
+ // Pointer to member conversions (4.11).
+ SCS.Second = ICK_Pointer_Member;
+ } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
+ SCS.Second = SecondICK;
+ FromType = ToType.getUnqualifiedType();
+ } else if (!S.getLangOptions().CPlusPlus &&
+ S.Context.typesAreCompatible(ToType, FromType)) {
+ // Compatible conversions (Clang extension for C function overloading)
+ SCS.Second = ICK_Compatible_Conversion;
+ FromType = ToType.getUnqualifiedType();
+ } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) {
+ // Treat a conversion that strips "noreturn" as an identity conversion.
+ SCS.Second = ICK_NoReturn_Adjustment;
+ } else {
+ // No second conversion required.
+ SCS.Second = ICK_Identity;
+ }
+ SCS.setToType(1, FromType);
+
+ QualType CanonFrom;
+ QualType CanonTo;
+ // The third conversion can be a qualification conversion (C++ 4p1).
+ if (S.IsQualificationConversion(FromType, ToType, CStyle)) {
+ SCS.Third = ICK_Qualification;
+ FromType = ToType;
+ CanonFrom = S.Context.getCanonicalType(FromType);
+ CanonTo = S.Context.getCanonicalType(ToType);
+ } else {
+ // No conversion required
+ SCS.Third = ICK_Identity;
+
+ // C++ [over.best.ics]p6:
+ // [...] Any difference in top-level cv-qualification is
+ // subsumed by the initialization itself and does not constitute
+ // a conversion. [...]
+ CanonFrom = S.Context.getCanonicalType(FromType);
+ CanonTo = S.Context.getCanonicalType(ToType);
+ if (CanonFrom.getLocalUnqualifiedType()
+ == CanonTo.getLocalUnqualifiedType() &&
+ (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
+ || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr())) {
+ FromType = ToType;
+ CanonFrom = CanonTo;
+ }
+ }
+ SCS.setToType(2, FromType);
+
+ // If we have not converted the argument type to the parameter type,
+ // this is a bad conversion sequence.
+ if (CanonFrom != CanonTo)
+ return false;
+
+ return true;
+}
+
+/// IsIntegralPromotion - Determines whether the conversion from the
+/// expression From (whose potentially-adjusted type is FromType) to
+/// ToType is an integral promotion (C++ 4.5). If so, returns true and
+/// sets PromotedType to the promoted type.
+bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
+ const BuiltinType *To = ToType->getAs<BuiltinType>();
+ // All integers are built-in.
+ if (!To) {
+ return false;
+ }
+
+ // An rvalue of type char, signed char, unsigned char, short int, or
+ // unsigned short int can be converted to an rvalue of type int if
+ // int can represent all the values of the source type; otherwise,
+ // the source rvalue can be converted to an rvalue of type unsigned
+ // int (C++ 4.5p1).
+ if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
+ !FromType->isEnumeralType()) {
+ if (// We can promote any signed, promotable integer type to an int
+ (FromType->isSignedIntegerType() ||
+ // We can promote any unsigned integer type whose size is
+ // less than int to an int.
+ (!FromType->isSignedIntegerType() &&
+ Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) {
+ return To->getKind() == BuiltinType::Int;
+ }
+
+ return To->getKind() == BuiltinType::UInt;
+ }
+
+ // C++0x [conv.prom]p3:
+ // A prvalue of an unscoped enumeration type whose underlying type is not
+ // fixed (7.2) can be converted to an rvalue a prvalue of the first of the
+ // following types that can represent all the values of the enumeration
+ // (i.e., the values in the range bmin to bmax as described in 7.2): int,
+ // unsigned int, long int, unsigned long int, long long int, or unsigned
+ // long long int. If none of the types in that list can represent all the
+ // values of the enumeration, an rvalue a prvalue of an unscoped enumeration
+ // type can be converted to an rvalue a prvalue of the extended integer type
+ // with lowest integer conversion rank (4.13) greater than the rank of long
+ // long in which all the values of the enumeration can be represented. If
+ // there are two such extended types, the signed one is chosen.
+ if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
+ // C++0x 7.2p9: Note that this implicit enum to int conversion is not
+ // provided for a scoped enumeration.
+ if (FromEnumType->getDecl()->isScoped())
+ return false;
+
+ // We have already pre-calculated the promotion type, so this is trivial.
+ if (ToType->isIntegerType() &&
+ !RequireCompleteType(From->getLocStart(), FromType, PDiag()))
+ return Context.hasSameUnqualifiedType(ToType,
+ FromEnumType->getDecl()->getPromotionType());
+ }
+
+ // C++0x [conv.prom]p2:
+ // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted
+ // to an rvalue a prvalue of the first of the following types that can
+ // represent all the values of its underlying type: int, unsigned int,
+ // long int, unsigned long int, long long int, or unsigned long long int.
+ // If none of the types in that list can represent all the values of its
+ // underlying type, an rvalue a prvalue of type char16_t, char32_t,
+ // or wchar_t can be converted to an rvalue a prvalue of its underlying
+ // type.
+ if (FromType->isAnyCharacterType() && !FromType->isCharType() &&
+ ToType->isIntegerType()) {
+ // Determine whether the type we're converting from is signed or
+ // unsigned.
+ bool FromIsSigned;
+ uint64_t FromSize = Context.getTypeSize(FromType);
+
+ // FIXME: Is wchar_t signed or unsigned? We assume it's signed for now.
+ FromIsSigned = true;
+
+ // The types we'll try to promote to, in the appropriate
+ // order. Try each of these types.
+ QualType PromoteTypes[6] = {
+ Context.IntTy, Context.UnsignedIntTy,
+ Context.LongTy, Context.UnsignedLongTy ,
+ Context.LongLongTy, Context.UnsignedLongLongTy
+ };
+ for (int Idx = 0; Idx < 6; ++Idx) {
+ uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]);
+ if (FromSize < ToSize ||
+ (FromSize == ToSize &&
+ FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) {
+ // We found the type that we can promote to. If this is the
+ // type we wanted, we have a promotion. Otherwise, no
+ // promotion.
+ return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]);
+ }
+ }
+ }
+
+ // An rvalue for an integral bit-field (9.6) can be converted to an
+ // rvalue of type int if int can represent all the values of the
+ // bit-field; otherwise, it can be converted to unsigned int if
+ // unsigned int can represent all the values of the bit-field. If
+ // the bit-field is larger yet, no integral promotion applies to
+ // it. If the bit-field has an enumerated type, it is treated as any
+ // other value of that type for promotion purposes (C++ 4.5p3).
+ // FIXME: We should delay checking of bit-fields until we actually perform the
+ // conversion.
+ using llvm::APSInt;
+ if (From)
+ if (FieldDecl *MemberDecl = From->getBitField()) {
+ APSInt BitWidth;
+ if (FromType->isIntegralType(Context) &&
+ MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
+ APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
+ ToSize = Context.getTypeSize(ToType);
+
+ // Are we promoting to an int from a bitfield that fits in an int?
+ if (BitWidth < ToSize ||
+ (FromType->isSignedIntegerType() && BitWidth <= ToSize)) {
+ return To->getKind() == BuiltinType::Int;
+ }
+
+ // Are we promoting to an unsigned int from an unsigned bitfield
+ // that fits into an unsigned int?
+ if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) {
+ return To->getKind() == BuiltinType::UInt;
+ }
+
+ return false;
+ }
+ }
+
+ // An rvalue of type bool can be converted to an rvalue of type int,
+ // with false becoming zero and true becoming one (C++ 4.5p4).
+ if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) {
+ return true;
+ }
+
+ return false;
+}
+
+/// IsFloatingPointPromotion - Determines whether the conversion from
+/// FromType to ToType is a floating point promotion (C++ 4.6). If so,
+/// returns true and sets PromotedType to the promoted type.
+bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
+ /// An rvalue of type float can be converted to an rvalue of type
+ /// double. (C++ 4.6p1).
+ if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>())
+ if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) {
+ if (FromBuiltin->getKind() == BuiltinType::Float &&
+ ToBuiltin->getKind() == BuiltinType::Double)
+ return true;
+
+ // C99 6.3.1.5p1:
+ // When a float is promoted to double or long double, or a
+ // double is promoted to long double [...].
+ if (!getLangOptions().CPlusPlus &&
+ (FromBuiltin->getKind() == BuiltinType::Float ||
+ FromBuiltin->getKind() == BuiltinType::Double) &&
+ (ToBuiltin->getKind() == BuiltinType::LongDouble))
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Determine if a conversion is a complex promotion.
+///
+/// A complex promotion is defined as a complex -> complex conversion
+/// where the conversion between the underlying real types is a
+/// floating-point or integral promotion.
+bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
+ const ComplexType *FromComplex = FromType->getAs<ComplexType>();
+ if (!FromComplex)
+ return false;
+
+ const ComplexType *ToComplex = ToType->getAs<ComplexType>();
+ if (!ToComplex)
+ return false;
+
+ return IsFloatingPointPromotion(FromComplex->getElementType(),
+ ToComplex->getElementType()) ||
+ IsIntegralPromotion(0, FromComplex->getElementType(),
+ ToComplex->getElementType());
+}
+
+/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from
+/// the pointer type FromPtr to a pointer to type ToPointee, with the
+/// same type qualifiers as FromPtr has on its pointee type. ToType,
+/// if non-empty, will be a pointer to ToType that may or may not have
+/// the right set of qualifiers on its pointee.
+static QualType
+BuildSimilarlyQualifiedPointerType(const Type *FromPtr,
+ QualType ToPointee, QualType ToType,
+ ASTContext &Context) {
+ assert((FromPtr->getTypeClass() == Type::Pointer ||
+ FromPtr->getTypeClass() == Type::ObjCObjectPointer) &&
+ "Invalid similarly-qualified pointer type");
+
+ /// \brief Conversions to 'id' subsume cv-qualifier conversions.
+ if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType())
+ return ToType.getUnqualifiedType();
+
+ QualType CanonFromPointee
+ = Context.getCanonicalType(FromPtr->getPointeeType());
+ QualType CanonToPointee = Context.getCanonicalType(ToPointee);
+ Qualifiers Quals = CanonFromPointee.getQualifiers();
+
+ // Exact qualifier match -> return the pointer type we're converting to.
+ if (CanonToPointee.getLocalQualifiers() == Quals) {
+ // ToType is exactly what we need. Return it.
+ if (!ToType.isNull())
+ return ToType.getUnqualifiedType();
+
+ // Build a pointer to ToPointee. It has the right qualifiers
+ // already.
+ if (isa<ObjCObjectPointerType>(ToType))
+ return Context.getObjCObjectPointerType(ToPointee);
+ return Context.getPointerType(ToPointee);
+ }
+
+ // Just build a canonical type that has the right qualifiers.
+ QualType QualifiedCanonToPointee
+ = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals);
+
+ if (isa<ObjCObjectPointerType>(ToType))
+ return Context.getObjCObjectPointerType(QualifiedCanonToPointee);
+ return Context.getPointerType(QualifiedCanonToPointee);
+}
+
+static bool isNullPointerConstantForConversion(Expr *Expr,
+ bool InOverloadResolution,
+ ASTContext &Context) {
+ // Handle value-dependent integral null pointer constants correctly.
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
+ if (Expr->isValueDependent() && !Expr->isTypeDependent() &&
+ Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType())
+ return !InOverloadResolution;
+
+ return Expr->isNullPointerConstant(Context,
+ InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+ : Expr::NPC_ValueDependentIsNull);
+}
+
+/// IsPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType,
+/// can be converted to the type ToType via a pointer conversion (C++
+/// 4.10). If so, returns true and places the converted type (that
+/// might differ from ToType in its cv-qualifiers at some level) into
+/// ConvertedType.
+///
+/// This routine also supports conversions to and from block pointers
+/// and conversions with Objective-C's 'id', 'id<protocols...>', and
+/// pointers to interfaces. FIXME: Once we've determined the
+/// appropriate overloading rules for Objective-C, we may want to
+/// split the Objective-C checks into a different routine; however,
+/// GCC seems to consider all of these conversions to be pointer
+/// conversions, so for now they live here. IncompatibleObjC will be
+/// set if the conversion is an allowed Objective-C conversion that
+/// should result in a warning.
+bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+ bool InOverloadResolution,
+ QualType& ConvertedType,
+ bool &IncompatibleObjC) {
+ IncompatibleObjC = false;
+ if (isObjCPointerConversion(FromType, ToType, ConvertedType,
+ IncompatibleObjC))
+ return true;
+
+ // Conversion from a null pointer constant to any Objective-C pointer type.
+ if (ToType->isObjCObjectPointerType() &&
+ isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
+ // Blocks: Block pointers can be converted to void*.
+ if (FromType->isBlockPointerType() && ToType->isPointerType() &&
+ ToType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+ ConvertedType = ToType;
+ return true;
+ }
+ // Blocks: A null pointer constant can be converted to a block
+ // pointer type.
+ if (ToType->isBlockPointerType() &&
+ isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
+ // If the left-hand-side is nullptr_t, the right side can be a null
+ // pointer constant.
+ if (ToType->isNullPtrType() &&
+ isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
+ const PointerType* ToTypePtr = ToType->getAs<PointerType>();
+ if (!ToTypePtr)
+ return false;
+
+ // A null pointer constant can be converted to a pointer type (C++ 4.10p1).
+ if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
+ // Beyond this point, both types need to be pointers
+ // , including objective-c pointers.
+ QualType ToPointeeType = ToTypePtr->getPointeeType();
+ if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) {
+ ConvertedType = BuildSimilarlyQualifiedPointerType(
+ FromType->getAs<ObjCObjectPointerType>(),
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+ const PointerType *FromTypePtr = FromType->getAs<PointerType>();
+ if (!FromTypePtr)
+ return false;
+
+ QualType FromPointeeType = FromTypePtr->getPointeeType();
+
+ // If the unqualified pointee types are the same, this can't be a
+ // pointer conversion, so don't do all of the work below.
+ if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType))
+ return false;
+
+ // An rvalue of type "pointer to cv T," where T is an object type,
+ // can be converted to an rvalue of type "pointer to cv void" (C++
+ // 4.10p2).
+ if (FromPointeeType->isIncompleteOrObjectType() &&
+ ToPointeeType->isVoidType()) {
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+
+ // When we're overloading in C, we allow a special kind of pointer
+ // conversion for compatible-but-not-identical pointee types.
+ if (!getLangOptions().CPlusPlus &&
+ Context.typesAreCompatible(FromPointeeType, ToPointeeType)) {
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+
+ // C++ [conv.ptr]p3:
+ //
+ // An rvalue of type "pointer to cv D," where D is a class type,
+ // can be converted to an rvalue of type "pointer to cv B," where
+ // B is a base class (clause 10) of D. If B is an inaccessible
+ // (clause 11) or ambiguous (10.2) base class of D, a program that
+ // necessitates this conversion is ill-formed. The result of the
+ // conversion is a pointer to the base class sub-object of the
+ // derived class object. The null pointer value is converted to
+ // the null pointer value of the destination type.
+ //
+ // Note that we do not check for ambiguity or inaccessibility
+ // here. That is handled by CheckPointerConversion.
+ if (getLangOptions().CPlusPlus &&
+ FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+ !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
+ !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
+ IsDerivedFrom(FromPointeeType, ToPointeeType)) {
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+
+ return false;
+}
+
+/// isObjCPointerConversion - Determines whether this is an
+/// Objective-C pointer conversion. Subroutine of IsPointerConversion,
+/// with the same arguments and return values.
+bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType,
+ bool &IncompatibleObjC) {
+ if (!getLangOptions().ObjC1)
+ return false;
+
+ // First, we handle all conversions on ObjC object pointer types.
+ const ObjCObjectPointerType* ToObjCPtr =
+ ToType->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *FromObjCPtr =
+ FromType->getAs<ObjCObjectPointerType>();
+
+ if (ToObjCPtr && FromObjCPtr) {
+ // If the pointee types are the same (ignoring qualifications),
+ // then this is not a pointer conversion.
+ if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(),
+ FromObjCPtr->getPointeeType()))
+ return false;
+
+ // Objective C++: We're able to convert between "id" or "Class" and a
+ // pointer to any interface (in both directions).
+ if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
+ ConvertedType = ToType;
+ return true;
+ }
+ // Conversions with Objective-C's id<...>.
+ if ((FromObjCPtr->isObjCQualifiedIdType() ||
+ ToObjCPtr->isObjCQualifiedIdType()) &&
+ Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
+ /*compare=*/false)) {
+ ConvertedType = ToType;
+ return true;
+ }
+ // Objective C++: We're able to convert from a pointer to an
+ // interface to a pointer to a different interface.
+ if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
+ const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType();
+ const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType();
+ if (getLangOptions().CPlusPlus && LHS && RHS &&
+ !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs(
+ FromObjCPtr->getPointeeType()))
+ return false;
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+ ToObjCPtr->getPointeeType(),
+ ToType, Context);
+ return true;
+ }
+
+ if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) {
+ // Okay: this is some kind of implicit downcast of Objective-C
+ // interfaces, which is permitted. However, we're going to
+ // complain about it.
+ IncompatibleObjC = true;
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+ ToObjCPtr->getPointeeType(),
+ ToType, Context);
+ return true;
+ }
+ }
+ // Beyond this point, both types need to be C pointers or block pointers.
+ QualType ToPointeeType;
+ if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
+ ToPointeeType = ToCPtr->getPointeeType();
+ else if (const BlockPointerType *ToBlockPtr =
+ ToType->getAs<BlockPointerType>()) {
+ // Objective C++: We're able to convert from a pointer to any object
+ // to a block pointer type.
+ if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
+ ConvertedType = ToType;
+ return true;
+ }
+ ToPointeeType = ToBlockPtr->getPointeeType();
+ }
+ else if (FromType->getAs<BlockPointerType>() &&
+ ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
+ // Objective C++: We're able to convert from a block pointer type to a
+ // pointer to any object.
+ ConvertedType = ToType;
+ return true;
+ }
+ else
+ return false;
+
+ QualType FromPointeeType;
+ if (const PointerType *FromCPtr = FromType->getAs<PointerType>())
+ FromPointeeType = FromCPtr->getPointeeType();
+ else if (const BlockPointerType *FromBlockPtr =
+ FromType->getAs<BlockPointerType>())
+ FromPointeeType = FromBlockPtr->getPointeeType();
+ else
+ return false;
+
+ // If we have pointers to pointers, recursively check whether this
+ // is an Objective-C conversion.
+ if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() &&
+ isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+ IncompatibleObjC)) {
+ // We always complain about this conversion.
+ IncompatibleObjC = true;
+ ConvertedType = Context.getPointerType(ConvertedType);
+ return true;
+ }
+ // Allow conversion of pointee being objective-c pointer to another one;
+ // as in I* to id.
+ if (FromPointeeType->getAs<ObjCObjectPointerType>() &&
+ ToPointeeType->getAs<ObjCObjectPointerType>() &&
+ isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
+ IncompatibleObjC)) {
+ ConvertedType = Context.getPointerType(ConvertedType);
+ return true;
+ }
+
+ // If we have pointers to functions or blocks, check whether the only
+ // differences in the argument and result types are in Objective-C
+ // pointer conversions. If so, we permit the conversion (but
+ // complain about it).
+ const FunctionProtoType *FromFunctionType
+ = FromPointeeType->getAs<FunctionProtoType>();
+ const FunctionProtoType *ToFunctionType
+ = ToPointeeType->getAs<FunctionProtoType>();
+ if (FromFunctionType && ToFunctionType) {
+ // If the function types are exactly the same, this isn't an
+ // Objective-C pointer conversion.
+ if (Context.getCanonicalType(FromPointeeType)
+ == Context.getCanonicalType(ToPointeeType))
+ return false;
+
+ // Perform the quick checks that will tell us whether these
+ // function types are obviously different.
+ if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
+ FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals())
+ return false;
+
+ bool HasObjCConversion = false;
+ if (Context.getCanonicalType(FromFunctionType->getResultType())
+ == Context.getCanonicalType(ToFunctionType->getResultType())) {
+ // Okay, the types match exactly. Nothing to do.
+ } else if (isObjCPointerConversion(FromFunctionType->getResultType(),
+ ToFunctionType->getResultType(),
+ ConvertedType, IncompatibleObjC)) {
+ // Okay, we have an Objective-C pointer conversion.
+ HasObjCConversion = true;
+ } else {
+ // Function types are too different. Abort.
+ return false;
+ }
+
+ // Check argument types.
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ ArgIdx != NumArgs; ++ArgIdx) {
+ QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ if (Context.getCanonicalType(FromArgType)
+ == Context.getCanonicalType(ToArgType)) {
+ // Okay, the types match exactly. Nothing to do.
+ } else if (isObjCPointerConversion(FromArgType, ToArgType,
+ ConvertedType, IncompatibleObjC)) {
+ // Okay, we have an Objective-C pointer conversion.
+ HasObjCConversion = true;
+ } else {
+ // Argument types are too different. Abort.
+ return false;
+ }
+ }
+
+ if (HasObjCConversion) {
+ // We had an Objective-C conversion. Allow this pointer
+ // conversion, but complain about it.
+ ConvertedType = ToType;
+ IncompatibleObjC = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType) {
+ QualType ToPointeeType;
+ if (const BlockPointerType *ToBlockPtr =
+ ToType->getAs<BlockPointerType>())
+ ToPointeeType = ToBlockPtr->getPointeeType();
+ else
+ return false;
+
+ QualType FromPointeeType;
+ if (const BlockPointerType *FromBlockPtr =
+ FromType->getAs<BlockPointerType>())
+ FromPointeeType = FromBlockPtr->getPointeeType();
+ else
+ return false;
+ // We have pointer to blocks, check whether the only
+ // differences in the argument and result types are in Objective-C
+ // pointer conversions. If so, we permit the conversion.
+
+ const FunctionProtoType *FromFunctionType
+ = FromPointeeType->getAs<FunctionProtoType>();
+ const FunctionProtoType *ToFunctionType
+ = ToPointeeType->getAs<FunctionProtoType>();
+
+ if (!FromFunctionType || !ToFunctionType)
+ return false;
+
+ if (Context.hasSameType(FromPointeeType, ToPointeeType))
+ return true;
+
+ // Perform the quick checks that will tell us whether these
+ // function types are obviously different.
+ if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
+ return false;
+
+ FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo();
+ FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo();
+ if (FromEInfo != ToEInfo)
+ return false;
+
+ bool IncompatibleObjC = false;
+ if (Context.hasSameType(FromFunctionType->getResultType(),
+ ToFunctionType->getResultType())) {
+ // Okay, the types match exactly. Nothing to do.
+ } else {
+ QualType RHS = FromFunctionType->getResultType();
+ QualType LHS = ToFunctionType->getResultType();
+ if ((!getLangOptions().CPlusPlus || !RHS->isRecordType()) &&
+ !RHS.hasQualifiers() && LHS.hasQualifiers())
+ LHS = LHS.getUnqualifiedType();
+
+ if (Context.hasSameType(RHS,LHS)) {
+ // OK exact match.
+ } else if (isObjCPointerConversion(RHS, LHS,
+ ConvertedType, IncompatibleObjC)) {
+ if (IncompatibleObjC)
+ return false;
+ // Okay, we have an Objective-C pointer conversion.
+ }
+ else
+ return false;
+ }
+
+ // Check argument types.
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ ArgIdx != NumArgs; ++ArgIdx) {
+ IncompatibleObjC = false;
+ QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ if (Context.hasSameType(FromArgType, ToArgType)) {
+ // Okay, the types match exactly. Nothing to do.
+ } else if (isObjCPointerConversion(ToArgType, FromArgType,
+ ConvertedType, IncompatibleObjC)) {
+ if (IncompatibleObjC)
+ return false;
+ // Okay, we have an Objective-C pointer conversion.
+ } else
+ // Argument types are too different. Abort.
+ return false;
+ }
+ ConvertedType = ToType;
+ return true;
+}
+
+/// FunctionArgTypesAreEqual - This routine checks two function proto types
+/// for equlity of their argument types. Caller has already checked that
+/// they have same number of arguments. This routine assumes that Objective-C
+/// pointer types which only differ in their protocol qualifiers are equal.
+bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType) {
+ if (!getLangOptions().ObjC1)
+ return std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
+ NewType->arg_type_begin());
+
+ for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
+ N = NewType->arg_type_begin(),
+ E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
+ QualType ToType = (*O);
+ QualType FromType = (*N);
+ if (ToType != FromType) {
+ if (const PointerType *PTTo = ToType->getAs<PointerType>()) {
+ if (const PointerType *PTFr = FromType->getAs<PointerType>())
+ if ((PTTo->getPointeeType()->isObjCQualifiedIdType() &&
+ PTFr->getPointeeType()->isObjCQualifiedIdType()) ||
+ (PTTo->getPointeeType()->isObjCQualifiedClassType() &&
+ PTFr->getPointeeType()->isObjCQualifiedClassType()))
+ continue;
+ }
+ else if (const ObjCObjectPointerType *PTTo =
+ ToType->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *PTFr =
+ FromType->getAs<ObjCObjectPointerType>())
+ if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl())
+ continue;
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+/// CheckPointerConversion - Check the pointer conversion from the
+/// expression From to the type ToType. This routine checks for
+/// ambiguous or inaccessible derived-to-base pointer
+/// conversions for which IsPointerConversion has already returned
+/// true. It returns true and produces a diagnostic if there was an
+/// error, or returns false otherwise.
+bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath& BasePath,
+ bool IgnoreBaseAccess) {
+ QualType FromType = From->getType();
+ bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
+
+ Kind = CK_BitCast;
+
+ if (CXXBoolLiteralExpr* LitBool
+ = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
+ if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false)
+ Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false)
+ << ToType;
+
+ if (const PointerType *FromPtrType = FromType->getAs<PointerType>())
+ if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
+ QualType FromPointeeType = FromPtrType->getPointeeType(),
+ ToPointeeType = ToPtrType->getPointeeType();
+
+ if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
+ !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) {
+ // We must have a derived-to-base conversion. Check an
+ // ambiguous or inaccessible conversion.
+ if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType,
+ From->getExprLoc(),
+ From->getSourceRange(), &BasePath,
+ IgnoreBaseAccess))
+ return true;
+
+ // The conversion was successful.
+ Kind = CK_DerivedToBase;
+ }
+ }
+ if (const ObjCObjectPointerType *FromPtrType =
+ FromType->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *ToPtrType =
+ ToType->getAs<ObjCObjectPointerType>()) {
+ // Objective-C++ conversions are always okay.
+ // FIXME: We should have a different class of conversions for the
+ // Objective-C++ implicit conversions.
+ if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
+ return false;
+ }
+ }
+
+ // We shouldn't fall into this case unless it's valid for other
+ // reasons.
+ if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+ Kind = CK_NullToPointer;
+
+ return false;
+}
+
+/// IsMemberPointerConversion - Determines whether the conversion of the
+/// expression From, which has the (possibly adjusted) type FromType, can be
+/// converted to the type ToType via a member pointer conversion (C++ 4.11).
+/// If so, returns true and places the converted type (that might differ from
+/// ToType in its cv-qualifiers at some level) into ConvertedType.
+bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
+ QualType ToType,
+ bool InOverloadResolution,
+ QualType &ConvertedType) {
+ const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>();
+ if (!ToTypePtr)
+ return false;
+
+ // A null pointer constant can be converted to a member pointer (C++ 4.11p1)
+ if (From->isNullPointerConstant(Context,
+ InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
+ : Expr::NPC_ValueDependentIsNull)) {
+ ConvertedType = ToType;
+ return true;
+ }
+
+ // Otherwise, both types have to be member pointers.
+ const MemberPointerType *FromTypePtr = FromType->getAs<MemberPointerType>();
+ if (!FromTypePtr)
+ return false;
+
+ // A pointer to member of B can be converted to a pointer to member of D,
+ // where D is derived from B (C++ 4.11p2).
+ QualType FromClass(FromTypePtr->getClass(), 0);
+ QualType ToClass(ToTypePtr->getClass(), 0);
+
+ if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
+ !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) &&
+ IsDerivedFrom(ToClass, FromClass)) {
+ ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
+ ToClass.getTypePtr());
+ return true;
+ }
+
+ return false;
+}
+
+/// CheckMemberPointerConversion - Check the member pointer conversion from the
+/// expression From to the type ToType. This routine checks for ambiguous or
+/// virtual or inaccessible base-to-derived member pointer conversions
+/// for which IsMemberPointerConversion has already returned true. It returns
+/// true and produces a diagnostic if there was an error, or returns false
+/// otherwise.
+bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
+ bool IgnoreBaseAccess) {
+ QualType FromType = From->getType();
+ const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
+ if (!FromPtrType) {
+ // This must be a null pointer to member pointer conversion
+ assert(From->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNull) &&
+ "Expr must be null pointer constant!");
+ Kind = CK_NullToMemberPointer;
+ return false;
+ }
+
+ const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>();
+ assert(ToPtrType && "No member pointer cast has a target type "
+ "that is not a member pointer.");
+
+ QualType FromClass = QualType(FromPtrType->getClass(), 0);
+ QualType ToClass = QualType(ToPtrType->getClass(), 0);
+
+ // FIXME: What about dependent types?
+ assert(FromClass->isRecordType() && "Pointer into non-class.");
+ assert(ToClass->isRecordType() && "Pointer into non-class.");
+
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/true);
+ bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
+ assert(DerivationOkay &&
+ "Should not have been called if derivation isn't OK.");
+ (void)DerivationOkay;
+
+ if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
+ getUnqualifiedType())) {
+ std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
+ Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
+ << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
+ return true;
+ }
+
+ if (const RecordType *VBase = Paths.getDetectedVirtual()) {
+ Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual)
+ << FromClass << ToClass << QualType(VBase, 0)
+ << From->getSourceRange();
+ return true;
+ }
+
+ if (!IgnoreBaseAccess)
+ CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass,
+ Paths.front(),
+ diag::err_downcast_from_inaccessible_base);
+
+ // Must be a base to derived member conversion.
+ BuildBasePathArray(Paths, BasePath);
+ Kind = CK_BaseToDerivedMemberPointer;
+ return false;
+}
+
+/// IsQualificationConversion - Determines whether the conversion from
+/// an rvalue of type FromType to ToType is a qualification conversion
+/// (C++ 4.4).
+bool
+Sema::IsQualificationConversion(QualType FromType, QualType ToType,
+ bool CStyle) {
+ FromType = Context.getCanonicalType(FromType);
+ ToType = Context.getCanonicalType(ToType);
+
+ // If FromType and ToType are the same type, this is not a
+ // qualification conversion.
+ if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType())
+ return false;
+
+ // (C++ 4.4p4):
+ // A conversion can add cv-qualifiers at levels other than the first
+ // in multi-level pointers, subject to the following rules: [...]
+ bool PreviousToQualsIncludeConst = true;
+ bool UnwrappedAnyPointer = false;
+ while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
+ // Within each iteration of the loop, we check the qualifiers to
+ // determine if this still looks like a qualification
+ // conversion. Then, if all is well, we unwrap one more level of
+ // pointers or pointers-to-members and do it all again
+ // until there are no more pointers or pointers-to-members left to
+ // unwrap.
+ UnwrappedAnyPointer = true;
+
+ // -- for every j > 0, if const is in cv 1,j then const is in cv
+ // 2,j, and similarly for volatile.
+ if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType))
+ return false;
+
+ // -- if the cv 1,j and cv 2,j are different, then const is in
+ // every cv for 0 < k < j.
+ if (!CStyle && FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
+ && !PreviousToQualsIncludeConst)
+ return false;
+
+ // Keep track of whether all prior cv-qualifiers in the "to" type
+ // include const.
+ PreviousToQualsIncludeConst
+ = PreviousToQualsIncludeConst && ToType.isConstQualified();
+ }
+
+ // We are left with FromType and ToType being the pointee types
+ // after unwrapping the original FromType and ToType the same number
+ // of types. If we unwrapped any pointers, and if FromType and
+ // ToType have the same unqualified type (since we checked
+ // qualifiers above), then this is a qualification conversion.
+ return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
+}
+
+/// Determines whether there is a user-defined conversion sequence
+/// (C++ [over.ics.user]) that converts expression From to the type
+/// ToType. If such a conversion exists, User will contain the
+/// user-defined conversion sequence that performs such a conversion
+/// and this routine will return true. Otherwise, this routine returns
+/// false and User is unspecified.
+///
+/// \param AllowExplicit true if the conversion should consider C++0x
+/// "explicit" conversion functions as well as non-explicit conversion
+/// functions (C++0x [class.conv.fct]p2).
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+ UserDefinedConversionSequence& User,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowExplicit) {
+ // Whether we will only visit constructors.
+ bool ConstructorsOnly = false;
+
+ // If the type we are conversion to is a class type, enumerate its
+ // constructors.
+ if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
+ // C++ [over.match.ctor]p1:
+ // When objects of class type are direct-initialized (8.5), or
+ // copy-initialized from an expression of the same or a
+ // derived class type (8.5), overload resolution selects the
+ // constructor. [...] For copy-initialization, the candidate
+ // functions are all the converting constructors (12.3.1) of
+ // that class. The argument list is the expression-list within
+ // the parentheses of the initializer.
+ if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+ (From->getType()->getAs<RecordType>() &&
+ S.IsDerivedFrom(From->getType(), ToType)))
+ ConstructorsOnly = true;
+
+ if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) {
+ // We're not going to find any constructors.
+ } else if (CXXRecordDecl *ToRecordDecl
+ = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl);
+ Con != ConEnd; ++Con) {
+ NamedDecl *D = *Con;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl
+ = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConstructorTmpl)
+ Constructor
+ = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(D);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ &From, 1, CandidateSet,
+ /*SuppressUserConversions=*/
+ !ConstructorsOnly);
+ else
+ // Allow one user-defined conversion when user specifies a
+ // From->ToType conversion via an static cast (c-style, etc).
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &From, 1, CandidateSet,
+ /*SuppressUserConversions=*/
+ !ConstructorsOnly);
+ }
+ }
+ }
+ }
+
+ // Enumerate conversion functions, if we're allowed to.
+ if (ConstructorsOnly) {
+ } else if (S.RequireCompleteType(From->getLocStart(), From->getType(),
+ S.PDiag(0) << From->getSourceRange())) {
+ // No conversion functions from incomplete types.
+ } else if (const RecordType *FromRecordType
+ = From->getType()->getAs<RecordType>()) {
+ if (CXXRecordDecl *FromRecordDecl
+ = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
+ // Add all of the conversion functions as candidates.
+ const UnresolvedSetImpl *Conversions
+ = FromRecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ DeclAccessPair FoundDecl = I.getPair();
+ NamedDecl *D = FoundDecl.getDecl();
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D)))
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ if (AllowExplicit || !Conv->isExplicit()) {
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
+ ActingContext, From, ToType,
+ CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
+ From, ToType, CandidateSet);
+ }
+ }
+ }
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+ case OR_Success:
+ // Record the standard conversion we used and the conversion function.
+ if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(Best->Function)) {
+ // C++ [over.ics.user]p1:
+ // If the user-defined conversion is specified by a
+ // constructor (12.3.1), the initial standard conversion
+ // sequence converts the source type to the type required by
+ // the argument of the constructor.
+ //
+ QualType ThisType = Constructor->getThisType(S.Context);
+ if (Best->Conversions[0].isEllipsis())
+ User.EllipsisConversion = true;
+ else {
+ User.Before = Best->Conversions[0].Standard;
+ User.EllipsisConversion = false;
+ }
+ User.ConversionFunction = Constructor;
+ User.FoundConversionFunction = Best->FoundDecl.getDecl();
+ User.After.setAsIdentityConversion();
+ User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
+ User.After.setAllToTypes(ToType);
+ return OR_Success;
+ } else if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>(Best->Function)) {
+ // C++ [over.ics.user]p1:
+ //
+ // [...] If the user-defined conversion is specified by a
+ // conversion function (12.3.2), the initial standard
+ // conversion sequence converts the source type to the
+ // implicit object parameter of the conversion function.
+ User.Before = Best->Conversions[0].Standard;
+ User.ConversionFunction = Conversion;
+ User.FoundConversionFunction = Best->FoundDecl.getDecl();
+ User.EllipsisConversion = false;
+
+ // C++ [over.ics.user]p2:
+ // The second standard conversion sequence converts the
+ // result of the user-defined conversion to the target type
+ // for the sequence. Since an implicit conversion sequence
+ // is an initialization, the special rules for
+ // initialization by user-defined conversion apply when
+ // selecting the best user-defined conversion for a
+ // user-defined conversion sequence (see 13.3.3 and
+ // 13.3.3.1).
+ User.After = Best->FinalConversion;
+ return OR_Success;
+ } else {
+ llvm_unreachable("Not a constructor or conversion function?");
+ return OR_No_Viable_Function;
+ }
+
+ case OR_No_Viable_Function:
+ return OR_No_Viable_Function;
+ case OR_Deleted:
+ // No conversion here! We're done.
+ return OR_Deleted;
+
+ case OR_Ambiguous:
+ return OR_Ambiguous;
+ }
+
+ return OR_No_Viable_Function;
+}
+
+bool
+Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
+ ImplicitConversionSequence ICS;
+ OverloadCandidateSet CandidateSet(From->getExprLoc());
+ OverloadingResult OvResult =
+ IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
+ CandidateSet, false);
+ if (OvResult == OR_Ambiguous)
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_ambiguous_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty())
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_nonviable_condition)
+ << From->getType() << ToType << From->getSourceRange();
+ else
+ return false;
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1);
+ return true;
+}
+
+/// CompareImplicitConversionSequences - Compare two implicit
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2).
+static ImplicitConversionSequence::CompareKind
+CompareImplicitConversionSequences(Sema &S,
+ const ImplicitConversionSequence& ICS1,
+ const ImplicitConversionSequence& ICS2)
+{
+ // (C++ 13.3.3.2p2): When comparing the basic forms of implicit
+ // conversion sequences (as defined in 13.3.3.1)
+ // -- a standard conversion sequence (13.3.3.1.1) is a better
+ // conversion sequence than a user-defined conversion sequence or
+ // an ellipsis conversion sequence, and
+ // -- a user-defined conversion sequence (13.3.3.1.2) is a better
+ // conversion sequence than an ellipsis conversion sequence
+ // (13.3.3.1.3).
+ //
+ // C++0x [over.best.ics]p10:
+ // For the purpose of ranking implicit conversion sequences as
+ // described in 13.3.3.2, the ambiguous conversion sequence is
+ // treated as a user-defined sequence that is indistinguishable
+ // from any other user-defined conversion sequence.
+ if (ICS1.getKindRank() < ICS2.getKindRank())
+ return ImplicitConversionSequence::Better;
+ else if (ICS2.getKindRank() < ICS1.getKindRank())
+ return ImplicitConversionSequence::Worse;
+
+ // The following checks require both conversion sequences to be of
+ // the same kind.
+ if (ICS1.getKind() != ICS2.getKind())
+ return ImplicitConversionSequence::Indistinguishable;
+
+ // Two implicit conversion sequences of the same form are
+ // indistinguishable conversion sequences unless one of the
+ // following rules apply: (C++ 13.3.3.2p3):
+ if (ICS1.isStandard())
+ return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard);
+ else if (ICS1.isUserDefined()) {
+ // User-defined conversion sequence U1 is a better conversion
+ // sequence than another user-defined conversion sequence U2 if
+ // they contain the same user-defined conversion function or
+ // constructor and if the second standard conversion sequence of
+ // U1 is better than the second standard conversion sequence of
+ // U2 (C++ 13.3.3.2p3).
+ if (ICS1.UserDefined.ConversionFunction ==
+ ICS2.UserDefined.ConversionFunction)
+ return CompareStandardConversionSequences(S,
+ ICS1.UserDefined.After,
+ ICS2.UserDefined.After);
+ }
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
+static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
+ while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ Qualifiers Quals;
+ T1 = Context.getUnqualifiedArrayType(T1, Quals);
+ T2 = Context.getUnqualifiedArrayType(T2, Quals);
+ }
+
+ return Context.hasSameUnqualifiedType(T1, T2);
+}
+
+// Per 13.3.3.2p3, compare the given standard conversion sequences to
+// determine if one is a proper subset of the other.
+static ImplicitConversionSequence::CompareKind
+compareStandardConversionSubsets(ASTContext &Context,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
+ ImplicitConversionSequence::CompareKind Result
+ = ImplicitConversionSequence::Indistinguishable;
+
+ // the identity conversion sequence is considered to be a subsequence of
+ // any non-identity conversion sequence
+ if (SCS1.ReferenceBinding == SCS2.ReferenceBinding) {
+ if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion())
+ return ImplicitConversionSequence::Better;
+ else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion())
+ return ImplicitConversionSequence::Worse;
+ }
+
+ if (SCS1.Second != SCS2.Second) {
+ if (SCS1.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Better;
+ else if (SCS2.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Worse;
+ else
+ return ImplicitConversionSequence::Indistinguishable;
+ } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
+ return ImplicitConversionSequence::Indistinguishable;
+
+ if (SCS1.Third == SCS2.Third) {
+ return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
+ : ImplicitConversionSequence::Indistinguishable;
+ }
+
+ if (SCS1.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Worse
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Better;
+
+ if (SCS2.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Better
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Worse;
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// \brief Determine whether one of the given reference bindings is better
+/// than the other based on what kind of bindings they are.
+static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
+ const StandardConversionSequence &SCS2) {
+ // C++0x [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
+ // implicit object parameter of a non-static member function declared
+ // without a ref-qualifier, and *either* S1 binds an rvalue reference
+ // to an rvalue and S2 binds an lvalue reference *or S1 binds an
+ // lvalue reference to a function lvalue and S2 binds an rvalue
+ // reference*.
+ //
+ // FIXME: Rvalue references. We're going rogue with the above edits,
+ // because the semantics in the current C++0x working paper (N3225 at the
+ // time of this writing) break the standard definition of std::forward
+ // and std::reference_wrapper when dealing with references to functions.
+ // Proposed wording changes submitted to CWG for consideration.
+ if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier ||
+ SCS2.BindsImplicitObjectArgumentWithoutRefQualifier)
+ return false;
+
+ return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
+ SCS2.IsLvalueReference) ||
+ (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
+ !SCS2.IsLvalueReference);
+}
+
+/// CompareStandardConversionSequences - Compare two standard
+/// conversion sequences to determine whether one is better than the
+/// other or if they are indistinguishable (C++ 13.3.3.2p3).
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2)
+{
+ // Standard conversion sequence S1 is a better conversion sequence
+ // than standard conversion sequence S2 if (C++ 13.3.3.2p3):
+
+ // -- S1 is a proper subsequence of S2 (comparing the conversion
+ // sequences in the canonical form defined by 13.3.3.1.1,
+ // excluding any Lvalue Transformation; the identity conversion
+ // sequence is considered to be a subsequence of any
+ // non-identity conversion sequence) or, if not that,
+ if (ImplicitConversionSequence::CompareKind CK
+ = compareStandardConversionSubsets(S.Context, SCS1, SCS2))
+ return CK;
+
+ // -- the rank of S1 is better than the rank of S2 (by the rules
+ // defined below), or, if not that,
+ ImplicitConversionRank Rank1 = SCS1.getRank();
+ ImplicitConversionRank Rank2 = SCS2.getRank();
+ if (Rank1 < Rank2)
+ return ImplicitConversionSequence::Better;
+ else if (Rank2 < Rank1)
+ return ImplicitConversionSequence::Worse;
+
+ // (C++ 13.3.3.2p4): Two conversion sequences with the same rank
+ // are indistinguishable unless one of the following rules
+ // applies:
+
+ // A conversion that is not a conversion of a pointer, or
+ // pointer to member, to bool is better than another conversion
+ // that is such a conversion.
+ if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
+ return SCS2.isPointerConversionToBool()
+ ? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+
+ // C++ [over.ics.rank]p4b2:
+ //
+ // If class B is derived directly or indirectly from class A,
+ // conversion of B* to A* is better than conversion of B* to
+ // void*, and conversion of A* to void* is better than conversion
+ // of B* to void*.
+ bool SCS1ConvertsToVoid
+ = SCS1.isPointerConversionToVoidPointer(S.Context);
+ bool SCS2ConvertsToVoid
+ = SCS2.isPointerConversionToVoidPointer(S.Context);
+ if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
+ // Exactly one of the conversion sequences is a conversion to
+ // a void pointer; it's the worse conversion.
+ return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+ } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
+ // Neither conversion sequence converts to a void pointer; compare
+ // their derived-to-base conversions.
+ if (ImplicitConversionSequence::CompareKind DerivedCK
+ = CompareDerivedToBaseConversions(S, SCS1, SCS2))
+ return DerivedCK;
+ } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
+ // Both conversion sequences are conversions to void
+ // pointers. Compare the source types to determine if there's an
+ // inheritance relationship in their sources.
+ QualType FromType1 = SCS1.getFromType();
+ QualType FromType2 = SCS2.getFromType();
+
+ // Adjust the types we're converting from via the array-to-pointer
+ // conversion, if we need to.
+ if (SCS1.First == ICK_Array_To_Pointer)
+ FromType1 = S.Context.getArrayDecayedType(FromType1);
+ if (SCS2.First == ICK_Array_To_Pointer)
+ FromType2 = S.Context.getArrayDecayedType(FromType2);
+
+ QualType FromPointee1
+ = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+ QualType FromPointee2
+ = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+
+ if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Worse;
+
+ // Objective-C++: If one interface is more specific than the
+ // other, it is the better one.
+ const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
+ const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
+ if (FromIface1 && FromIface1) {
+ if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
+ return ImplicitConversionSequence::Better;
+ else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
+ // Compare based on qualification conversions (C++ 13.3.3.2p3,
+ // bullet 3).
+ if (ImplicitConversionSequence::CompareKind QualCK
+ = CompareQualificationConversions(S, SCS1, SCS2))
+ return QualCK;
+
+ if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
+ // Check for a better reference binding based on the kind of bindings.
+ if (isBetterReferenceBindingKind(SCS1, SCS2))
+ return ImplicitConversionSequence::Better;
+ else if (isBetterReferenceBindingKind(SCS2, SCS1))
+ return ImplicitConversionSequence::Worse;
+
+ // C++ [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3), and the types to
+ // which the references refer are the same type except for
+ // top-level cv-qualifiers, and the type to which the reference
+ // initialized by S2 refers is more cv-qualified than the type
+ // to which the reference initialized by S1 refers.
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
+ T1 = S.Context.getCanonicalType(T1);
+ T2 = S.Context.getCanonicalType(T2);
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
+ if (UnqualT1 == UnqualT2) {
+ // If the type is an array type, promote the element qualifiers to the
+ // type for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+ if (T2.isMoreQualifiedThan(T1))
+ return ImplicitConversionSequence::Better;
+ else if (T1.isMoreQualifiedThan(T2))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareQualificationConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
+ImplicitConversionSequence::CompareKind
+CompareQualificationConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
+ // C++ 13.3.3.2p3:
+ // -- S1 and S2 differ only in their qualification conversion and
+ // yield similar types T1 and T2 (C++ 4.4), respectively, and the
+ // cv-qualification signature of type T1 is a proper subset of
+ // the cv-qualification signature of type T2, and S1 is not the
+ // deprecated string literal array-to-pointer conversion (4.2).
+ if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second ||
+ SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification)
+ return ImplicitConversionSequence::Indistinguishable;
+
+ // FIXME: the example in the standard doesn't use a qualification
+ // conversion (!)
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
+ T1 = S.Context.getCanonicalType(T1);
+ T2 = S.Context.getCanonicalType(T2);
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
+
+ // If the types are the same, we won't learn anything by unwrapped
+ // them.
+ if (UnqualT1 == UnqualT2)
+ return ImplicitConversionSequence::Indistinguishable;
+
+ // If the type is an array type, promote the element qualifiers to the type
+ // for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+
+ ImplicitConversionSequence::CompareKind Result
+ = ImplicitConversionSequence::Indistinguishable;
+ while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ // Within each iteration of the loop, we check the qualifiers to
+ // determine if this still looks like a qualification
+ // conversion. Then, if all is well, we unwrap one more level of
+ // pointers or pointers-to-members and do it all again
+ // until there are no more pointers or pointers-to-members left
+ // to unwrap. This essentially mimics what
+ // IsQualificationConversion does, but here we're checking for a
+ // strict subset of qualifiers.
+ if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
+ // The qualifiers are the same, so this doesn't tell us anything
+ // about how the sequences rank.
+ ;
+ else if (T2.isMoreQualifiedThan(T1)) {
+ // T1 has fewer qualifiers, so it could be the better sequence.
+ if (Result == ImplicitConversionSequence::Worse)
+ // Neither has qualifiers that are a subset of the other's
+ // qualifiers.
+ return ImplicitConversionSequence::Indistinguishable;
+
+ Result = ImplicitConversionSequence::Better;
+ } else if (T1.isMoreQualifiedThan(T2)) {
+ // T2 has fewer qualifiers, so it could be the better sequence.
+ if (Result == ImplicitConversionSequence::Better)
+ // Neither has qualifiers that are a subset of the other's
+ // qualifiers.
+ return ImplicitConversionSequence::Indistinguishable;
+
+ Result = ImplicitConversionSequence::Worse;
+ } else {
+ // Qualifiers are disjoint.
+ return ImplicitConversionSequence::Indistinguishable;
+ }
+
+ // If the types after this point are equivalent, we're done.
+ if (S.Context.hasSameUnqualifiedType(T1, T2))
+ break;
+ }
+
+ // Check that the winning standard conversion sequence isn't using
+ // the deprecated string literal array to pointer conversion.
+ switch (Result) {
+ case ImplicitConversionSequence::Better:
+ if (SCS1.DeprecatedStringLiteralToCharPtr)
+ Result = ImplicitConversionSequence::Indistinguishable;
+ break;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ break;
+
+ case ImplicitConversionSequence::Worse:
+ if (SCS2.DeprecatedStringLiteralToCharPtr)
+ Result = ImplicitConversionSequence::Indistinguishable;
+ break;
+ }
+
+ return Result;
+}
+
+/// CompareDerivedToBaseConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// various kinds of derived-to-base conversions (C++
+/// [over.ics.rank]p4b3). As part of these checks, we also look at
+/// conversions between Objective-C interface types.
+ImplicitConversionSequence::CompareKind
+CompareDerivedToBaseConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
+ QualType FromType1 = SCS1.getFromType();
+ QualType ToType1 = SCS1.getToType(1);
+ QualType FromType2 = SCS2.getFromType();
+ QualType ToType2 = SCS2.getToType(1);
+
+ // Adjust the types we're converting from via the array-to-pointer
+ // conversion, if we need to.
+ if (SCS1.First == ICK_Array_To_Pointer)
+ FromType1 = S.Context.getArrayDecayedType(FromType1);
+ if (SCS2.First == ICK_Array_To_Pointer)
+ FromType2 = S.Context.getArrayDecayedType(FromType2);
+
+ // Canonicalize all of the types.
+ FromType1 = S.Context.getCanonicalType(FromType1);
+ ToType1 = S.Context.getCanonicalType(ToType1);
+ FromType2 = S.Context.getCanonicalType(FromType2);
+ ToType2 = S.Context.getCanonicalType(ToType2);
+
+ // C++ [over.ics.rank]p4b3:
+ //
+ // If class B is derived directly or indirectly from class A and
+ // class C is derived directly or indirectly from B,
+ //
+ // Compare based on pointer conversions.
+ if (SCS1.Second == ICK_Pointer_Conversion &&
+ SCS2.Second == ICK_Pointer_Conversion &&
+ /*FIXME: Remove if Objective-C id conversions get their own rank*/
+ FromType1->isPointerType() && FromType2->isPointerType() &&
+ ToType1->isPointerType() && ToType2->isPointerType()) {
+ QualType FromPointee1
+ = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+ QualType ToPointee1
+ = ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+ QualType FromPointee2
+ = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+ QualType ToPointee2
+ = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
+
+ // -- conversion of C* to B* is better than conversion of C* to A*,
+ if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+ if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ return ImplicitConversionSequence::Worse;
+ }
+
+ // -- conversion of B* to A* is better than conversion of C* to A*,
+ if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
+ if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Worse;
+ }
+ } else if (SCS1.Second == ICK_Pointer_Conversion &&
+ SCS2.Second == ICK_Pointer_Conversion) {
+ const ObjCObjectPointerType *FromPtr1
+ = FromType1->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *FromPtr2
+ = FromType2->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *ToPtr1
+ = ToType1->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *ToPtr2
+ = ToType2->getAs<ObjCObjectPointerType>();
+
+ if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) {
+ // Apply the same conversion ranking rules for Objective-C pointer types
+ // that we do for C++ pointers to class types. However, we employ the
+ // Objective-C pseudo-subtyping relationship used for assignment of
+ // Objective-C pointer types.
+ bool FromAssignLeft
+ = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2);
+ bool FromAssignRight
+ = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1);
+ bool ToAssignLeft
+ = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2);
+ bool ToAssignRight
+ = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1);
+
+ // A conversion to an a non-id object pointer type or qualified 'id'
+ // type is better than a conversion to 'id'.
+ if (ToPtr1->isObjCIdType() &&
+ (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl()))
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCIdType() &&
+ (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl()))
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to a non-id object pointer type is better than a
+ // conversion to a qualified 'id' type
+ if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl())
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl())
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to an a non-Class object pointer type or qualified 'Class'
+ // type is better than a conversion to 'Class'.
+ if (ToPtr1->isObjCClassType() &&
+ (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl()))
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCClassType() &&
+ (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl()))
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to a non-Class object pointer type is better than a
+ // conversion to a qualified 'Class' type.
+ if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl())
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl())
+ return ImplicitConversionSequence::Better;
+
+ // -- "conversion of C* to B* is better than conversion of C* to A*,"
+ if (S.Context.hasSameType(FromType1, FromType2) &&
+ !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() &&
+ (ToAssignLeft != ToAssignRight))
+ return ToAssignLeft? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
+
+ // -- "conversion of B* to A* is better than conversion of C* to A*,"
+ if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) &&
+ (FromAssignLeft != FromAssignRight))
+ return FromAssignLeft? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+ }
+ }
+
+ // Ranking of member-pointer types.
+ if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
+ FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
+ ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
+ const MemberPointerType * FromMemPointer1 =
+ FromType1->getAs<MemberPointerType>();
+ const MemberPointerType * ToMemPointer1 =
+ ToType1->getAs<MemberPointerType>();
+ const MemberPointerType * FromMemPointer2 =
+ FromType2->getAs<MemberPointerType>();
+ const MemberPointerType * ToMemPointer2 =
+ ToType2->getAs<MemberPointerType>();
+ const Type *FromPointeeType1 = FromMemPointer1->getClass();
+ const Type *ToPointeeType1 = ToMemPointer1->getClass();
+ const Type *FromPointeeType2 = FromMemPointer2->getClass();
+ const Type *ToPointeeType2 = ToMemPointer2->getClass();
+ QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType();
+ QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType();
+ QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType();
+ QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
+ // conversion of A::* to B::* is better than conversion of A::* to C::*,
+ if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+ if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ return ImplicitConversionSequence::Worse;
+ else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ return ImplicitConversionSequence::Better;
+ }
+ // conversion of B::* to C::* is better than conversion of A::* to C::*
+ if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
+ if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
+ if (SCS1.Second == ICK_Derived_To_Base) {
+ // -- conversion of C to B is better than conversion of C to A,
+ // -- binding of an expression of type C to a reference of type
+ // B& is better than binding an expression of type C to a
+ // reference of type A&,
+ if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+ if (S.IsDerivedFrom(ToType1, ToType2))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(ToType2, ToType1))
+ return ImplicitConversionSequence::Worse;
+ }
+
+ // -- conversion of B to A is better than conversion of C to A.
+ // -- binding of an expression of type B to a reference of type
+ // A& is better than binding an expression of type C to a
+ // reference of type A&,
+ if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+ if (S.IsDerivedFrom(FromType2, FromType1))
+ return ImplicitConversionSequence::Better;
+ else if (S.IsDerivedFrom(FromType1, FromType2))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareReferenceRelationship - Compare the two types T1 and T2 to
+/// determine whether they are reference-related,
+/// reference-compatible, reference-compatible with added
+/// qualification, or incompatible, for use in C++ initialization by
+/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
+/// type, and the first type (T1) is the pointee type of the reference
+/// type being initialized.
+Sema::ReferenceCompareResult
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+ QualType OrigT1, QualType OrigT2,
+ bool &DerivedToBase,
+ bool &ObjCConversion) {
+ assert(!OrigT1->isReferenceType() &&
+ "T1 must be the pointee type of the reference type");
+ assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
+
+ QualType T1 = Context.getCanonicalType(OrigT1);
+ QualType T2 = Context.getCanonicalType(OrigT2);
+ Qualifiers T1Quals, T2Quals;
+ QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+
+ // C++ [dcl.init.ref]p4:
+ // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
+ // reference-related to "cv2 T2" if T1 is the same type as T2, or
+ // T1 is a base class of T2.
+ DerivedToBase = false;
+ ObjCConversion = false;
+ if (UnqualT1 == UnqualT2) {
+ // Nothing to do.
+ } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
+ IsDerivedFrom(UnqualT2, UnqualT1))
+ DerivedToBase = true;
+ else if (UnqualT1->isObjCObjectOrInterfaceType() &&
+ UnqualT2->isObjCObjectOrInterfaceType() &&
+ Context.canBindObjCObjectType(UnqualT1, UnqualT2))
+ ObjCConversion = true;
+ else
+ return Ref_Incompatible;
+
+ // At this point, we know that T1 and T2 are reference-related (at
+ // least).
+
+ // If the type is an array type, promote the element qualifiers to the type
+ // for comparison.
+ if (isa<ArrayType>(T1) && T1Quals)
+ T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ if (isa<ArrayType>(T2) && T2Quals)
+ T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+ // C++ [dcl.init.ref]p4:
+ // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
+ // reference-related to T2 and cv1 is the same cv-qualification
+ // as, or greater cv-qualification than, cv2. For purposes of
+ // overload resolution, cases for which cv1 is greater
+ // cv-qualification than cv2 are identified as
+ // reference-compatible with added qualification (see 13.3.3.2).
+ if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
+ return Ref_Compatible;
+ else if (T1.isMoreQualifiedThan(T2))
+ return Ref_Compatible_With_Added_Qualification;
+ else
+ return Ref_Related;
+}
+
+/// \brief Look for a user-defined conversion to an value reference-compatible
+/// with DeclType. Return true if something definite is found.
+static bool
+FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
+ QualType DeclType, SourceLocation DeclLoc,
+ Expr *Init, QualType T2, bool AllowRvalues,
+ bool AllowExplicit) {
+ assert(T2->isRecordType() && "Can only find conversions of record types.");
+ CXXRecordDecl *T2RecordDecl
+ = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+
+ OverloadCandidateSet CandidateSet(DeclLoc);
+ const UnresolvedSetImpl *Conversions
+ = T2RecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate
+ = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ // If this is an explicit conversion, and we're not allowed to consider
+ // explicit conversions, skip it.
+ if (!AllowExplicit && Conv->isExplicit())
+ continue;
+
+ if (AllowRvalues) {
+ bool DerivedToBase = false;
+ bool ObjCConversion = false;
+ if (!ConvTemplate &&
+ S.CompareReferenceRelationship(
+ DeclLoc,
+ Conv->getConversionType().getNonReferenceType()
+ .getUnqualifiedType(),
+ DeclType.getNonReferenceType().getUnqualifiedType(),
+ DerivedToBase, ObjCConversion) ==
+ Sema::Ref_Incompatible)
+ continue;
+ } else {
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion. An rvalue reference
+ // is only acceptable if its referencee is a function type.
+
+ const ReferenceType *RefType =
+ Conv->getConversionType()->getAs<ReferenceType>();
+ if (!RefType ||
+ (!RefType->isLValueReferenceType() &&
+ !RefType->getPointeeType()->isFunctionType()))
+ continue;
+ }
+
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+ Init, DeclType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+ DeclType, CandidateSet);
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
+ case OR_Success:
+ // C++ [over.ics.ref]p1:
+ //
+ // [...] If the parameter binds directly to the result of
+ // applying a conversion function to the argument
+ // expression, the implicit conversion sequence is a
+ // user-defined conversion sequence (13.3.3.1.2), with the
+ // second standard conversion sequence either an identity
+ // conversion or, if the conversion function returns an
+ // entity of a type that is a derived class of the parameter
+ // type, a derived-to-base Conversion.
+ if (!Best->FinalConversion.DirectBinding)
+ return false;
+
+ ICS.setUserDefined();
+ ICS.UserDefined.Before = Best->Conversions[0].Standard;
+ ICS.UserDefined.After = Best->FinalConversion;
+ ICS.UserDefined.ConversionFunction = Best->Function;
+ ICS.UserDefined.FoundConversionFunction = Best->FoundDecl.getDecl();
+ ICS.UserDefined.EllipsisConversion = false;
+ assert(ICS.UserDefined.After.ReferenceBinding &&
+ ICS.UserDefined.After.DirectBinding &&
+ "Expected a direct reference binding!");
+ return true;
+
+ case OR_Ambiguous:
+ ICS.setAmbiguous();
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+ Cand != CandidateSet.end(); ++Cand)
+ if (Cand->Viable)
+ ICS.Ambiguous.addConversion(Cand->Function);
+ return true;
+
+ case OR_No_Viable_Function:
+ case OR_Deleted:
+ // There was no suitable conversion, or we found a deleted
+ // conversion; continue with other checks.
+ return false;
+ }
+
+ return false;
+}
+
+/// \brief Compute an implicit conversion sequence for reference
+/// initialization.
+static ImplicitConversionSequence
+TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
+ SourceLocation DeclLoc,
+ bool SuppressUserConversions,
+ bool AllowExplicit) {
+ assert(DeclType->isReferenceType() && "Reference init needs a reference");
+
+ // Most paths end in a failed conversion.
+ ImplicitConversionSequence ICS;
+ ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+ QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
+ QualType T2 = Init->getType();
+
+ // If the initializer is the address of an overloaded function, try
+ // to resolve the overloaded function. If all goes well, T2 is the
+ // type of the resulting function.
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+ DeclAccessPair Found;
+ if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType,
+ false, Found))
+ T2 = Fn->getType();
+ }
+
+ // Compute some basic properties of the types and the initializer.
+ bool isRValRef = DeclType->isRValueReferenceType();
+ bool DerivedToBase = false;
+ bool ObjCConversion = false;
+ Expr::Classification InitCategory = Init->Classify(S.Context);
+ Sema::ReferenceCompareResult RefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
+ ObjCConversion);
+
+
+ // C++0x [dcl.init.ref]p5:
+ // A reference to type "cv1 T1" is initialized by an expression
+ // of type "cv2 T2" as follows:
+
+ // -- If reference is an lvalue reference and the initializer expression
+ if (!isRValRef) {
+ // -- is an lvalue (but is not a bit-field), and "cv1 T1" is
+ // reference-compatible with "cv2 T2," or
+ //
+ // Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
+ if (InitCategory.isLValue() &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ // C++ [over.ics.ref]p1:
+ // When a parameter of reference type binds directly (8.5.3)
+ // to an argument expression, the implicit conversion sequence
+ // is the identity conversion, unless the argument expression
+ // has a type that is a derived class of the parameter type,
+ // in which case the implicit conversion sequence is a
+ // derived-to-base Conversion (13.3.3.1).
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+ : ObjCConversion? ICK_Compatible_Conversion
+ : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.DirectBinding = true;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = false;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ ICS.Standard.CopyConstructor = 0;
+
+ // Nothing more to do: the inaccessibility/ambiguity check for
+ // derived-to-base conversions is suppressed when we're
+ // computing the implicit conversion sequence (C++
+ // [over.best.ics]p2).
+ return ICS;
+ }
+
+ // -- has a class type (i.e., T2 is a class type), where T1 is
+ // not reference-related to T2, and can be implicitly
+ // converted to an lvalue of type "cv3 T3," where "cv1 T1"
+ // is reference-compatible with "cv3 T3" 92) (this
+ // conversion is selected by enumerating the applicable
+ // conversion functions (13.3.1.6) and choosing the best
+ // one through overload resolution (13.3)),
+ if (!SuppressUserConversions && T2->isRecordType() &&
+ !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ RefRelationship == Sema::Ref_Incompatible) {
+ if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+ Init, T2, /*AllowRvalues=*/false,
+ AllowExplicit))
+ return ICS;
+ }
+ }
+
+ // -- Otherwise, the reference shall be an lvalue reference to a
+ // non-volatile const type (i.e., cv1 shall be const), or the reference
+ // shall be an rvalue reference.
+ //
+ // We actually handle one oddity of C++ [over.ics.ref] at this
+ // point, which is that, due to p2 (which short-circuits reference
+ // binding by only attempting a simple conversion for non-direct
+ // bindings) and p3's strange wording, we allow a const volatile
+ // reference to bind to an rvalue. Hence the check for the presence
+ // of "const" rather than checking for "const" being the only
+ // qualifier.
+ // This is also the point where rvalue references and lvalue inits no longer
+ // go together.
+ if (!isRValRef && !T1.isConstQualified())
+ return ICS;
+
+ // -- If the initializer expression
+ //
+ // -- is an xvalue, class prvalue, array prvalue or function
+ // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or
+ if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
+ (InitCategory.isXValue() ||
+ (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+ (InitCategory.isLValue() && T2->isFunctionType()))) {
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+ : ObjCConversion? ICK_Compatible_Conversion
+ : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ // In C++0x, this is always a direct binding. In C++98/03, it's a direct
+ // binding unless we're binding to a class prvalue.
+ // Note: Although xvalues wouldn't normally show up in C++98/03 code, we
+ // allow the use of rvalue references in C++98/03 for the benefit of
+ // standard library implementors; therefore, we need the xvalue check here.
+ ICS.Standard.DirectBinding =
+ S.getLangOptions().CPlusPlus0x ||
+ (InitCategory.isPRValue() && !T2->isRecordType());
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = InitCategory.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ ICS.Standard.CopyConstructor = 0;
+ return ICS;
+ }
+
+ // -- has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to
+ // an xvalue, class prvalue, or function lvalue of type
+ // "cv3 T3", where "cv1 T1" is reference-compatible with
+ // "cv3 T3",
+ //
+ // then the reference is bound to the value of the initializer
+ // expression in the first case and to the result of the conversion
+ // in the second case (or, in either case, to an appropriate base
+ // class subobject).
+ if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+ T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+ Init, T2, /*AllowRvalues=*/true,
+ AllowExplicit)) {
+ // In the second case, if the reference is an rvalue reference
+ // and the second standard conversion sequence of the
+ // user-defined conversion sequence includes an lvalue-to-rvalue
+ // conversion, the program is ill-formed.
+ if (ICS.isUserDefined() && isRValRef &&
+ ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue)
+ ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+ return ICS;
+ }
+
+ // -- Otherwise, a temporary of type "cv1 T1" is created and
+ // initialized from the initializer expression using the
+ // rules for a non-reference copy initialization (8.5). The
+ // reference is then bound to the temporary. If T1 is
+ // reference-related to T2, cv1 must be the same
+ // cv-qualification as, or greater cv-qualification than,
+ // cv2; otherwise, the program is ill-formed.
+ if (RefRelationship == Sema::Ref_Related) {
+ // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
+ // we would be reference-compatible or reference-compatible with
+ // added qualification. But that wasn't the case, so the reference
+ // initialization fails.
+ return ICS;
+ }
+
+ // If at least one of the types is a class type, the types are not
+ // related, and we aren't allowed any user conversions, the
+ // reference binding fails. This case is important for breaking
+ // recursion, since TryImplicitConversion below will attempt to
+ // create a temporary through the use of a copy constructor.
+ if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+ (T1->isRecordType() || T2->isRecordType()))
+ return ICS;
+
+ // If T1 is reference-related to T2 and the reference is an rvalue
+ // reference, the initializer expression shall not be an lvalue.
+ if (RefRelationship >= Sema::Ref_Related &&
+ isRValRef && Init->Classify(S.Context).isLValue())
+ return ICS;
+
+ // C++ [over.ics.ref]p2:
+ // When a parameter of reference type is not bound directly to
+ // an argument expression, the conversion sequence is the one
+ // required to convert the argument expression to the
+ // underlying type of the reference according to
+ // 13.3.3.1. Conceptually, this conversion sequence corresponds
+ // to copy-initializing a temporary of the underlying type with
+ // the argument expression. Any difference in top-level
+ // cv-qualification is subsumed by the initialization itself
+ // and does not constitute a conversion.
+ ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
+ /*AllowExplicit=*/false,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
+
+ // Of course, that's still a reference binding.
+ if (ICS.isStandard()) {
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = true;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ } else if (ICS.isUserDefined()) {
+ ICS.UserDefined.After.ReferenceBinding = true;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = true;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ }
+
+ return ICS;
+}
+
+/// TryCopyInitialization - Try to copy-initialize a value of type
+/// ToType from the expression From. Return the implicit conversion
+/// sequence required to pass this argument, which may be a bad
+/// conversion sequence (meaning that the argument cannot be passed to
+/// a parameter of this type). If @p SuppressUserConversions, then we
+/// do not permit any user-defined conversion sequences.
+static ImplicitConversionSequence
+TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ bool InOverloadResolution) {
+ if (ToType->isReferenceType())
+ return TryReferenceInit(S, From, ToType,
+ /*FIXME:*/From->getLocStart(),
+ SuppressUserConversions,
+ /*AllowExplicit=*/false);
+
+ return TryImplicitConversion(S, From, ToType,
+ SuppressUserConversions,
+ /*AllowExplicit=*/false,
+ InOverloadResolution,
+ /*CStyle=*/false);
+}
+
+/// TryObjectArgumentInitialization - Try to initialize the object
+/// parameter of the given member function (@c Method) from the
+/// expression @p From.
+static ImplicitConversionSequence
+TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
+ Expr::Classification FromClassification,
+ CXXMethodDecl *Method,
+ CXXRecordDecl *ActingContext) {
+ QualType ClassType = S.Context.getTypeDeclType(ActingContext);
+ // [class.dtor]p2: A destructor can be invoked for a const, volatile or
+ // const volatile object.
+ unsigned Quals = isa<CXXDestructorDecl>(Method) ?
+ Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
+ QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals);
+
+ // Set up the conversion sequence as a "bad" conversion, to allow us
+ // to exit early.
+ ImplicitConversionSequence ICS;
+
+ // We need to have an object of class type.
+ QualType FromType = OrigFromType;
+ if (const PointerType *PT = FromType->getAs<PointerType>()) {
+ FromType = PT->getPointeeType();
+
+ // When we had a pointer, it's implicitly dereferenced, so we
+ // better have an lvalue.
+ assert(FromClassification.isLValue());
+ }
+
+ assert(FromType->isRecordType());
+
+ // C++0x [over.match.funcs]p4:
+ // For non-static member functions, the type of the implicit object
+ // parameter is
+ //
+ // - "lvalue reference to cv X" for functions declared without a
+ // ref-qualifier or with the & ref-qualifier
+ // - "rvalue reference to cv X" for functions declared with the &&
+ // ref-qualifier
+ //
+ // where X is the class of which the function is a member and cv is the
+ // cv-qualification on the member function declaration.
+ //
+ // However, when finding an implicit conversion sequence for the argument, we
+ // are not allowed to create temporaries or perform user-defined conversions
+ // (C++ [over.match.funcs]p5). We perform a simplified version of
+ // reference binding here, that allows class rvalues to bind to
+ // non-constant references.
+
+ // First check the qualifiers.
+ QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
+ if (ImplicitParamType.getCVRQualifiers()
+ != FromTypeCanon.getLocalCVRQualifiers() &&
+ !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
+ ICS.setBad(BadConversionSequence::bad_qualifiers,
+ OrigFromType, ImplicitParamType);
+ return ICS;
+ }
+
+ // Check that we have either the same type or a derived type. It
+ // affects the conversion rank.
+ QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
+ ImplicitConversionKind SecondKind;
+ if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
+ SecondKind = ICK_Identity;
+ } else if (S.IsDerivedFrom(FromType, ClassType))
+ SecondKind = ICK_Derived_To_Base;
+ else {
+ ICS.setBad(BadConversionSequence::unrelated_class,
+ FromType, ImplicitParamType);
+ return ICS;
+ }
+
+ // Check the ref-qualifier.
+ switch (Method->getRefQualifier()) {
+ case RQ_None:
+ // Do nothing; we don't care about lvalueness or rvalueness.
+ break;
+
+ case RQ_LValue:
+ if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
+ // non-const lvalue reference cannot bind to an rvalue
+ ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
+ ImplicitParamType);
+ return ICS;
+ }
+ break;
+
+ case RQ_RValue:
+ if (!FromClassification.isRValue()) {
+ // rvalue reference cannot bind to an lvalue
+ ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType,
+ ImplicitParamType);
+ return ICS;
+ }
+ break;
+ }
+
+ // Success. Mark this as a reference binding.
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.Second = SecondKind;
+ ICS.Standard.setFromType(FromType);
+ ICS.Standard.setAllToTypes(ImplicitParamType);
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.DirectBinding = true;
+ ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
+ ICS.Standard.BindsToFunctionLvalue = false;
+ ICS.Standard.BindsToRvalue = FromClassification.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier
+ = (Method->getRefQualifier() == RQ_None);
+ return ICS;
+}
+
+/// PerformObjectArgumentInitialization - Perform initialization of
+/// the implicit object parameter for the given Method with the given
+/// expression.
+bool
+Sema::PerformObjectArgumentInitialization(Expr *&From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method) {
+ QualType FromRecordType, DestType;
+ QualType ImplicitParamRecordType =
+ Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
+
+ Expr::Classification FromClassification;
+ if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
+ FromRecordType = PT->getPointeeType();
+ DestType = Method->getThisType(Context);
+ FromClassification = Expr::Classification::makeSimpleLValue();
+ } else {
+ FromRecordType = From->getType();
+ DestType = ImplicitParamRecordType;
+ FromClassification = From->Classify(Context);
+ }
+
+ // Note that we always use the true parent context when performing
+ // the actual argument initialization.
+ ImplicitConversionSequence ICS
+ = TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
+ Method, Method->getParent());
+ if (ICS.isBad()) {
+ if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+ Qualifiers FromQs = FromRecordType.getQualifiers();
+ Qualifiers ToQs = DestType.getQualifiers();
+ unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+ if (CVR) {
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_member_function_call_bad_cvr)
+ << Method->getDeclName() << FromRecordType << (CVR - 1)
+ << From->getSourceRange();
+ Diag(Method->getLocation(), diag::note_previous_decl)
+ << Method->getDeclName();
+ return true;
+ }
+ }
+
+ return Diag(From->getSourceRange().getBegin(),
+ diag::err_implicit_object_parameter_init)
+ << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
+ }
+
+ if (ICS.Standard.Second == ICK_Derived_To_Base)
+ return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
+
+ if (!Context.hasSameType(From->getType(), DestType))
+ ImpCastExprToType(From, DestType, CK_NoOp,
+ From->getType()->isPointerType() ? VK_RValue : VK_LValue);
+ return false;
+}
+
+/// TryContextuallyConvertToBool - Attempt to contextually convert the
+/// expression From to bool (C++0x [conv]p3).
+static ImplicitConversionSequence
+TryContextuallyConvertToBool(Sema &S, Expr *From) {
+ // FIXME: This is pretty broken.
+ return TryImplicitConversion(S, From, S.Context.BoolTy,
+ // FIXME: Are these flags correct?
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/true,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
+}
+
+/// PerformContextuallyConvertToBool - Perform a contextual conversion
+/// of the expression From to bool (C++0x [conv]p3).
+bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
+ ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
+ if (!ICS.isBad())
+ return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
+
+ if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
+ return Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_bool_condition)
+ << From->getType() << From->getSourceRange();
+ return true;
+}
+
+/// TryContextuallyConvertToObjCId - Attempt to contextually convert the
+/// expression From to 'id'.
+static ImplicitConversionSequence
+TryContextuallyConvertToObjCId(Sema &S, Expr *From) {
+ QualType Ty = S.Context.getObjCIdType();
+ return TryImplicitConversion(S, From, Ty,
+ // FIXME: Are these flags correct?
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/true,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
+}
+
+/// PerformContextuallyConvertToObjCId - Perform a contextual conversion
+/// of the expression From to 'id'.
+bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
+ QualType Ty = Context.getObjCIdType();
+ ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From);
+ if (!ICS.isBad())
+ return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
+ return true;
+}
+
+/// \brief Attempt to convert the given expression to an integral or
+/// enumeration type.
+///
+/// This routine will attempt to convert an expression of class type to an
+/// integral or enumeration type, if that class type only has a single
+/// conversion to an integral or enumeration type.
+///
+/// \param Loc The source location of the construct that requires the
+/// conversion.
+///
+/// \param FromE The expression we're converting from.
+///
+/// \param NotIntDiag The diagnostic to be emitted if the expression does not
+/// have integral or enumeration type.
+///
+/// \param IncompleteDiag The diagnostic to be emitted if the expression has
+/// incomplete class type.
+///
+/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an
+/// explicit conversion function (because no implicit conversion functions
+/// were available). This is a recovery mode.
+///
+/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag,
+/// showing which conversion was picked.
+///
+/// \param AmbigDiag The diagnostic to be emitted if there is more than one
+/// conversion function that could convert to integral or enumeration type.
+///
+/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
+/// usable conversion function.
+///
+/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
+/// function, which may be an extension in this case.
+///
+/// \returns The expression, converted to an integral or enumeration type if
+/// successful.
+ExprResult
+Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
+ const PartialDiagnostic &NotIntDiag,
+ const PartialDiagnostic &IncompleteDiag,
+ const PartialDiagnostic &ExplicitConvDiag,
+ const PartialDiagnostic &ExplicitConvNote,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &AmbigNote,
+ const PartialDiagnostic &ConvDiag) {
+ // We can't perform any more checking for type-dependent expressions.
+ if (From->isTypeDependent())
+ return Owned(From);
+
+ // If the expression already has integral or enumeration type, we're golden.
+ QualType T = From->getType();
+ if (T->isIntegralOrEnumerationType())
+ return Owned(From);
+
+ // FIXME: Check for missing '()' if T is a function type?
+
+ // If we don't have a class type in C++, there's no way we can get an
+ // expression of integral or enumeration type.
+ const RecordType *RecordTy = T->getAs<RecordType>();
+ if (!RecordTy || !getLangOptions().CPlusPlus) {
+ Diag(Loc, NotIntDiag)
+ << T << From->getSourceRange();
+ return Owned(From);
+ }
+
+ // We must have a complete class type.
+ if (RequireCompleteType(Loc, T, IncompleteDiag))
+ return Owned(From);
+
+ // Look for a conversion to an integral or enumeration type.
+ UnresolvedSet<4> ViableConversions;
+ UnresolvedSet<4> ExplicitConversions;
+ const UnresolvedSetImpl *Conversions
+ = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E;
+ ++I) {
+ if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
+ if (Conversion->getConversionType().getNonReferenceType()
+ ->isIntegralOrEnumerationType()) {
+ if (Conversion->isExplicit())
+ ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
+ else
+ ViableConversions.addDecl(I.getDecl(), I.getAccess());
+ }
+ }
+
+ switch (ViableConversions.size()) {
+ case 0:
+ if (ExplicitConversions.size() == 1) {
+ DeclAccessPair Found = ExplicitConversions[0];
+ CXXConversionDecl *Conversion
+ = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+
+ // The user probably meant to invoke the given explicit
+ // conversion; use it.
+ QualType ConvTy
+ = Conversion->getConversionType().getNonReferenceType();
+ std::string TypeStr;
+ ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy);
+
+ Diag(Loc, ExplicitConvDiag)
+ << T << ConvTy
+ << FixItHint::CreateInsertion(From->getLocStart(),
+ "static_cast<" + TypeStr + ">(")
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
+ ")");
+ Diag(Conversion->getLocation(), ExplicitConvNote)
+ << ConvTy->isEnumeralType() << ConvTy;
+
+ // If we aren't in a SFINAE context, build a call to the
+ // explicit conversion function.
+ if (isSFINAEContext())
+ return ExprError();
+
+ CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion);
+ if (Result.isInvalid())
+ return ExprError();
+
+ From = Result.get();
+ }
+
+ // We'll complain below about a non-integral condition type.
+ break;
+
+ case 1: {
+ // Apply this conversion.
+ DeclAccessPair Found = ViableConversions[0];
+ CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+
+ CXXConversionDecl *Conversion
+ = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+ QualType ConvTy
+ = Conversion->getConversionType().getNonReferenceType();
+ if (ConvDiag.getDiagID()) {
+ if (isSFINAEContext())
+ return ExprError();
+
+ Diag(Loc, ConvDiag)
+ << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
+ }
+
+ ExprResult Result = BuildCXXMemberCallExpr(From, Found,
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
+ if (Result.isInvalid())
+ return ExprError();
+
+ From = Result.get();
+ break;
+ }
+
+ default:
+ Diag(Loc, AmbigDiag)
+ << T << From->getSourceRange();
+ for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+ QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+ Diag(Conv->getLocation(), AmbigNote)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ return Owned(From);
+ }
+
+ if (!From->getType()->isIntegralOrEnumerationType())
+ Diag(Loc, NotIntDiag)
+ << From->getType() << From->getSourceRange();
+
+ return Owned(From);
+}
+
+/// AddOverloadCandidate - Adds the given function to the set of
+/// candidate functions, using the given function call arguments. If
+/// @p SuppressUserConversions, then don't allow user-defined
+/// conversions via constructors or conversion operators.
+///
+/// \para PartialOverloading true if we are performing "partial" overloading
+/// based on an incomplete set of function arguments. This feature is used by
+/// code completion.
+void
+Sema::AddOverloadCandidate(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions,
+ bool PartialOverloading) {
+ const FunctionProtoType* Proto
+ = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
+ assert(Proto && "Functions without a prototype cannot be overloaded");
+ assert(!Function->getDescribedFunctionTemplate() &&
+ "Use AddTemplateOverloadCandidate for function templates");
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+ if (!isa<CXXConstructorDecl>(Method)) {
+ // If we get here, it's because we're calling a member function
+ // that is named without a member access expression (e.g.,
+ // "this->f") that was either written explicitly or created
+ // implicitly. This can happen with a qualified call to a member
+ // function, e.g., X::f(). We use an empty type for the implied
+ // object argument (C++ [over.call.func]p3), and the acting context
+ // is irrelevant.
+ AddMethodCandidate(Method, FoundDecl, Method->getParent(),
+ QualType(), Expr::Classification::makeSimpleLValue(),
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ return;
+ }
+ // We treat a constructor like a non-member function, since its object
+ // argument doesn't participate in overload resolution.
+ }
+
+ if (!CandidateSet.isNewCandidate(Function))
+ return;
+
+ // Overload resolution is always an unevaluated context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+ // C++ [class.copy]p3:
+ // A member function template is never instantiated to perform the copy
+ // of a class object to an object of its class type.
+ QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+ if (NumArgs == 1 &&
+ Constructor->isSpecializationCopyingObject() &&
+ (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
+ IsDerivedFrom(Args[0]->getType(), ClassType)))
+ return;
+ }
+
+ // Add this candidate
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate& Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = Function;
+ Candidate.Viable = true;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
+
+ unsigned NumArgsInProto = Proto->getNumArgs();
+
+ // (C++ 13.3.2p2): A candidate function having fewer than m
+ // parameters is viable only if it has an ellipsis in its parameter
+ // list (8.3.5).
+ if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto &&
+ !Proto->isVariadic()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_many_arguments;
+ return;
+ }
+
+ // (C++ 13.3.2p2): A candidate function having more than m parameters
+ // is viable only if the (m+1)st parameter has a default argument
+ // (8.3.6). For the purposes of overload resolution, the
+ // parameter list is truncated on the right, so that there are
+ // exactly m parameters.
+ unsigned MinRequiredArgs = Function->getMinRequiredArguments();
+ if (NumArgs < MinRequiredArgs && !PartialOverloading) {
+ // Not enough arguments.
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_few_arguments;
+ return;
+ }
+
+ // Determine the implicit conversion sequences for each of the
+ // arguments.
+ Candidate.Conversions.resize(NumArgs);
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ if (ArgIdx < NumArgsInProto) {
+ // (C++ 13.3.2p3): for F to be a viable function, there shall
+ // exist for each argument an implicit conversion sequence
+ // (13.3.3.1) that converts that argument to the corresponding
+ // parameter of F.
+ QualType ParamType = Proto->getArgType(ArgIdx);
+ Candidate.Conversions[ArgIdx]
+ = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+ SuppressUserConversions,
+ /*InOverloadResolution=*/true);
+ if (Candidate.Conversions[ArgIdx].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ break;
+ }
+ } else {
+ // (C++ 13.3.2p2): For the purposes of overload resolution, any
+ // argument for which there is no corresponding parameter is
+ // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+ Candidate.Conversions[ArgIdx].setEllipsis();
+ }
+ }
+}
+
+/// \brief Add all of the function declarations in the given function set to
+/// the overload canddiate set.
+void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions) {
+ for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
+ NamedDecl *D = F.getDecl()->getUnderlyingDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+ cast<CXXMethodDecl>(FD)->getParent(),
+ Args[0]->getType(), Args[0]->Classify(Context),
+ Args + 1, NumArgs - 1,
+ CandidateSet, SuppressUserConversions);
+ else
+ AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ } else {
+ FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
+ if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
+ !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
+ AddMethodTemplateCandidate(FunTmpl, F.getPair(),
+ cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
+ /*FIXME: explicit args */ 0,
+ Args[0]->getType(),
+ Args[0]->Classify(Context),
+ Args + 1, NumArgs - 1,
+ CandidateSet,
+ SuppressUserConversions);
+ else
+ AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
+ /*FIXME: explicit args */ 0,
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ }
+ }
+}
+
+/// AddMethodCandidate - Adds a named decl (which is some kind of
+/// method) as a method candidate to the given overload set.
+void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions) {
+ NamedDecl *Decl = FoundDecl.getDecl();
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
+
+ if (isa<UsingShadowDecl>(Decl))
+ Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
+
+ if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
+ assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
+ "Expected a member function template");
+ AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
+ /*ExplicitArgs*/ 0,
+ ObjectType, ObjectClassification, Args, NumArgs,
+ CandidateSet,
+ SuppressUserConversions);
+ } else {
+ AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
+ ObjectType, ObjectClassification, Args, NumArgs,
+ CandidateSet, SuppressUserConversions);
+ }
+}
+
+/// AddMethodCandidate - Adds the given C++ member function to the set
+/// of candidate functions, using the given function call arguments
+/// and the object argument (@c Object). For example, in a call
+/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain
+/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
+/// allow user-defined conversions via constructors or conversion
+/// operators.
+void
+Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions) {
+ const FunctionProtoType* Proto
+ = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
+ assert(Proto && "Methods without a prototype cannot be overloaded");
+ assert(!isa<CXXConstructorDecl>(Method) &&
+ "Use AddOverloadCandidate for constructors");
+
+ if (!CandidateSet.isNewCandidate(Method))
+ return;
+
+ // Overload resolution is always an unevaluated context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+ // Add this candidate
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate& Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = Method;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
+
+ unsigned NumArgsInProto = Proto->getNumArgs();
+
+ // (C++ 13.3.2p2): A candidate function having fewer than m
+ // parameters is viable only if it has an ellipsis in its parameter
+ // list (8.3.5).
+ if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_many_arguments;
+ return;
+ }
+
+ // (C++ 13.3.2p2): A candidate function having more than m parameters
+ // is viable only if the (m+1)st parameter has a default argument
+ // (8.3.6). For the purposes of overload resolution, the
+ // parameter list is truncated on the right, so that there are
+ // exactly m parameters.
+ unsigned MinRequiredArgs = Method->getMinRequiredArguments();
+ if (NumArgs < MinRequiredArgs) {
+ // Not enough arguments.
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_few_arguments;
+ return;
+ }
+
+ Candidate.Viable = true;
+ Candidate.Conversions.resize(NumArgs + 1);
+
+ if (Method->isStatic() || ObjectType.isNull())
+ // The implicit object argument is ignored.
+ Candidate.IgnoreObjectArgument = true;
+ else {
+ // Determine the implicit conversion sequence for the object
+ // parameter.
+ Candidate.Conversions[0]
+ = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
+ Method, ActingContext);
+ if (Candidate.Conversions[0].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ return;
+ }
+ }
+
+ // Determine the implicit conversion sequences for each of the
+ // arguments.
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ if (ArgIdx < NumArgsInProto) {
+ // (C++ 13.3.2p3): for F to be a viable function, there shall
+ // exist for each argument an implicit conversion sequence
+ // (13.3.3.1) that converts that argument to the corresponding
+ // parameter of F.
+ QualType ParamType = Proto->getArgType(ArgIdx);
+ Candidate.Conversions[ArgIdx + 1]
+ = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+ SuppressUserConversions,
+ /*InOverloadResolution=*/true);
+ if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ break;
+ }
+ } else {
+ // (C++ 13.3.2p2): For the purposes of overload resolution, any
+ // argument for which there is no corresponding parameter is
+ // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+ Candidate.Conversions[ArgIdx + 1].setEllipsis();
+ }
+ }
+}
+
+/// \brief Add a C++ member function template as a candidate to the candidate
+/// set, using template argument deduction to produce an appropriate member
+/// function template specialization.
+void
+Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions) {
+ if (!CandidateSet.isNewCandidate(MethodTmpl))
+ return;
+
+ // C++ [over.match.funcs]p7:
+ // In each case where a candidate is a function template, candidate
+ // function template specializations are generated using template argument
+ // deduction (14.8.3, 14.8.2). Those candidates are then handled as
+ // candidate functions in the usual way.113) A given name can refer to one
+ // or more function templates and also to a set of overloaded non-template
+ // functions. In such a case, the candidate functions generated from each
+ // function template are combined with the set of non-template candidate
+ // functions.
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+ FunctionDecl *Specialization = 0;
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs,
+ Args, NumArgs, Specialization, Info)) {
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate &Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = MethodTmpl->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_deduction;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
+ return;
+ }
+
+ // Add the function template specialization produced by template argument
+ // deduction as a candidate.
+ assert(Specialization && "Missing member function template specialization?");
+ assert(isa<CXXMethodDecl>(Specialization) &&
+ "Specialization is not a member function?");
+ AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
+ ActingContext, ObjectType, ObjectClassification,
+ Args, NumArgs, CandidateSet, SuppressUserConversions);
+}
+
+/// \brief Add a C++ function template specialization as a candidate
+/// in the candidate set, using template argument deduction to produce
+/// an appropriate function template specialization.
+void
+Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions) {
+ if (!CandidateSet.isNewCandidate(FunctionTemplate))
+ return;
+
+ // C++ [over.match.funcs]p7:
+ // In each case where a candidate is a function template, candidate
+ // function template specializations are generated using template argument
+ // deduction (14.8.3, 14.8.2). Those candidates are then handled as
+ // candidate functions in the usual way.113) A given name can refer to one
+ // or more function templates and also to a set of overloaded non-template
+ // functions. In such a case, the candidate functions generated from each
+ // function template are combined with the set of non-template candidate
+ // functions.
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+ FunctionDecl *Specialization = 0;
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+ Args, NumArgs, Specialization, Info)) {
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate &Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_deduction;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
+ return;
+ }
+
+ // Add the function template specialization produced by template argument
+ // deduction as a candidate.
+ assert(Specialization && "Missing function template specialization?");
+ AddOverloadCandidate(Specialization, FoundDecl, Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+}
+
+/// AddConversionCandidate - Add a C++ conversion function as a
+/// candidate in the candidate set (C++ [over.match.conv],
+/// C++ [over.match.copy]). From is the expression we're converting from,
+/// and ToType is the type that we're eventually trying to convert to
+/// (which may or may not be the same type as the type that the
+/// conversion function produces).
+void
+Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet) {
+ assert(!Conversion->getDescribedFunctionTemplate() &&
+ "Conversion function templates use AddTemplateConversionCandidate");
+ QualType ConvType = Conversion->getConversionType().getNonReferenceType();
+ if (!CandidateSet.isNewCandidate(Conversion))
+ return;
+
+ // Overload resolution is always an unevaluated context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+ // Add this candidate
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate& Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = Conversion;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.FinalConversion.setAsIdentityConversion();
+ Candidate.FinalConversion.setFromType(ConvType);
+ Candidate.FinalConversion.setAllToTypes(ToType);
+ Candidate.Viable = true;
+ Candidate.Conversions.resize(1);
+ Candidate.ExplicitCallArguments = 1;
+
+ // C++ [over.match.funcs]p4:
+ // For conversion functions, the function is considered to be a member of
+ // the class of the implicit implied object argument for the purpose of
+ // defining the type of the implicit object parameter.
+ //
+ // Determine the implicit conversion sequence for the implicit
+ // object parameter.
+ QualType ImplicitParamType = From->getType();
+ if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
+ ImplicitParamType = FromPtrType->getPointeeType();
+ CXXRecordDecl *ConversionContext
+ = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
+
+ Candidate.Conversions[0]
+ = TryObjectArgumentInitialization(*this, From->getType(),
+ From->Classify(Context),
+ Conversion, ConversionContext);
+
+ if (Candidate.Conversions[0].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ return;
+ }
+
+ // We won't go through a user-define type conversion function to convert a
+ // derived to base as such conversions are given Conversion Rank. They only
+ // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
+ QualType FromCanon
+ = Context.getCanonicalType(From->getType().getUnqualifiedType());
+ QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+ if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_trivial_conversion;
+ return;
+ }
+
+ // To determine what the conversion from the result of calling the
+ // conversion function to the type we're eventually trying to
+ // convert to (ToType), we need to synthesize a call to the
+ // conversion function and attempt copy initialization from it. This
+ // makes sure that we get the right semantics with respect to
+ // lvalues/rvalues and the type. Fortunately, we can allocate this
+ // call on the stack and we don't need its arguments to be
+ // well-formed.
+ DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
+ VK_LValue, From->getLocStart());
+ ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
+ Context.getPointerType(Conversion->getType()),
+ CK_FunctionToPointerDecay,
+ &ConversionRef, VK_RValue);
+
+ QualType CallResultType
+ = Conversion->getConversionType().getNonLValueExprType(Context);
+ if (RequireCompleteType(From->getLocStart(), CallResultType, 0)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ return;
+ }
+
+ ExprValueKind VK = Expr::getValueKindForType(Conversion->getConversionType());
+
+ // Note that it is safe to allocate CallExpr on the stack here because
+ // there are 0 arguments (i.e., nothing is allocated using ASTContext's
+ // allocator).
+ CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK,
+ From->getLocStart());
+ ImplicitConversionSequence ICS =
+ TryCopyInitialization(*this, &Call, ToType,
+ /*SuppressUserConversions=*/true,
+ /*InOverloadResolution=*/false);
+
+ switch (ICS.getKind()) {
+ case ImplicitConversionSequence::StandardConversion:
+ Candidate.FinalConversion = ICS.Standard;
+
+ // C++ [over.ics.user]p3:
+ // If the user-defined conversion is specified by a specialization of a
+ // conversion function template, the second standard conversion sequence
+ // shall have exact match rank.
+ if (Conversion->getPrimaryTemplate() &&
+ GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
+ }
+
+ // C++0x [dcl.init.ref]p5:
+ // In the second case, if the reference is an rvalue reference and
+ // the second standard conversion sequence of the user-defined
+ // conversion sequence includes an lvalue-to-rvalue conversion, the
+ // program is ill-formed.
+ if (ToType->isRValueReferenceType() &&
+ ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ }
+ break;
+
+ case ImplicitConversionSequence::BadConversion:
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ break;
+
+ default:
+ assert(false &&
+ "Can only end up with a standard conversion sequence or failure");
+ }
+}
+
+/// \brief Adds a conversion function template specialization
+/// candidate to the overload set, using template argument deduction
+/// to deduce the template arguments of the conversion function
+/// template from the type that we are converting to (C++
+/// [temp.deduct.conv]).
+void
+Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingDC,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet) {
+ assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
+ "Only conversion function templates permitted here");
+
+ if (!CandidateSet.isNewCandidate(FunctionTemplate))
+ return;
+
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
+ CXXConversionDecl *Specialization = 0;
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, ToType,
+ Specialization, Info)) {
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate &Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_deduction;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = 1;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
+ return;
+ }
+
+ // Add the conversion function template specialization produced by
+ // template argument deduction as a candidate.
+ assert(Specialization && "Missing function template specialization?");
+ AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
+ CandidateSet);
+}
+
+/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
+/// converts the given @c Object to a function pointer via the
+/// conversion function @c Conversion, and then attempts to call it
+/// with the given arguments (C++ [over.call.object]p2-4). Proto is
+/// the type of function that we'll eventually be calling.
+void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const FunctionProtoType *Proto,
+ Expr *Object,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet) {
+ if (!CandidateSet.isNewCandidate(Conversion))
+ return;
+
+ // Overload resolution is always an unevaluated context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate& Candidate = CandidateSet.back();
+ Candidate.FoundDecl = FoundDecl;
+ Candidate.Function = 0;
+ Candidate.Surrogate = Conversion;
+ Candidate.Viable = true;
+ Candidate.IsSurrogate = true;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.Conversions.resize(NumArgs + 1);
+ Candidate.ExplicitCallArguments = NumArgs;
+
+ // Determine the implicit conversion sequence for the implicit
+ // object parameter.
+ ImplicitConversionSequence ObjectInit
+ = TryObjectArgumentInitialization(*this, Object->getType(),
+ Object->Classify(Context),
+ Conversion, ActingContext);
+ if (ObjectInit.isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ Candidate.Conversions[0] = ObjectInit;
+ return;
+ }
+
+ // The first conversion is actually a user-defined conversion whose
+ // first conversion is ObjectInit's standard conversion (which is
+ // effectively a reference binding). Record it as such.
+ Candidate.Conversions[0].setUserDefined();
+ Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
+ Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
+ Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
+ Candidate.Conversions[0].UserDefined.FoundConversionFunction
+ = FoundDecl.getDecl();
+ Candidate.Conversions[0].UserDefined.After
+ = Candidate.Conversions[0].UserDefined.Before;
+ Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
+
+ // Find the
+ unsigned NumArgsInProto = Proto->getNumArgs();
+
+ // (C++ 13.3.2p2): A candidate function having fewer than m
+ // parameters is viable only if it has an ellipsis in its parameter
+ // list (8.3.5).
+ if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_many_arguments;
+ return;
+ }
+
+ // Function types don't have any default arguments, so just check if
+ // we have enough arguments.
+ if (NumArgs < NumArgsInProto) {
+ // Not enough arguments.
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_too_few_arguments;
+ return;
+ }
+
+ // Determine the implicit conversion sequences for each of the
+ // arguments.
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ if (ArgIdx < NumArgsInProto) {
+ // (C++ 13.3.2p3): for F to be a viable function, there shall
+ // exist for each argument an implicit conversion sequence
+ // (13.3.3.1) that converts that argument to the corresponding
+ // parameter of F.
+ QualType ParamType = Proto->getArgType(ArgIdx);
+ Candidate.Conversions[ArgIdx + 1]
+ = TryCopyInitialization(*this, Args[ArgIdx], ParamType,
+ /*SuppressUserConversions=*/false,
+ /*InOverloadResolution=*/false);
+ if (Candidate.Conversions[ArgIdx + 1].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ break;
+ }
+ } else {
+ // (C++ 13.3.2p2): For the purposes of overload resolution, any
+ // argument for which there is no corresponding parameter is
+ // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
+ Candidate.Conversions[ArgIdx + 1].setEllipsis();
+ }
+ }
+}
+
+/// \brief Add overload candidates for overloaded operators that are
+/// member functions.
+///
+/// Add the overloaded operator candidates that are member functions
+/// for the operator Op that was used in an operator expression such
+/// as "x Op y". , Args/NumArgs provides the operator arguments, and
+/// CandidateSet will store the added overload candidates. (C++
+/// [over.match.oper]).
+void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ SourceRange OpRange) {
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+ // C++ [over.match.oper]p3:
+ // For a unary operator @ with an operand of a type whose
+ // cv-unqualified version is T1, and for a binary operator @ with
+ // a left operand of a type whose cv-unqualified version is T1 and
+ // a right operand of a type whose cv-unqualified version is T2,
+ // three sets of candidate functions, designated member
+ // candidates, non-member candidates and built-in candidates, are
+ // constructed as follows:
+ QualType T1 = Args[0]->getType();
+
+ // -- If T1 is a class type, the set of member candidates is the
+ // result of the qualified lookup of T1::operator@
+ // (13.3.1.1.1); otherwise, the set of member candidates is
+ // empty.
+ if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
+ // Complete the type if it can be completed. Otherwise, we're done.
+ if (RequireCompleteType(OpLoc, T1, PDiag()))
+ return;
+
+ LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
+ LookupQualifiedName(Operators, T1Rec->getDecl());
+ Operators.suppressDiagnostics();
+
+ for (LookupResult::iterator Oper = Operators.begin(),
+ OperEnd = Operators.end();
+ Oper != OperEnd;
+ ++Oper)
+ AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
+ Args[0]->Classify(Context), Args + 1, NumArgs - 1,
+ CandidateSet,
+ /* SuppressUserConversions = */ false);
+ }
+}
+
+/// AddBuiltinCandidate - Add a candidate for a built-in
+/// operator. ResultTy and ParamTys are the result and parameter types
+/// of the built-in candidate, respectively. Args and NumArgs are the
+/// arguments being passed to the candidate. IsAssignmentOperator
+/// should be true when this built-in candidate is an assignment
+/// operator. NumContextualBoolArguments is the number of arguments
+/// (at the beginning of the argument list) that will be contextually
+/// converted to bool.
+void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool IsAssignmentOperator,
+ unsigned NumContextualBoolArguments) {
+ // Overload resolution is always an unevaluated context.
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
+
+ // Add this candidate
+ CandidateSet.push_back(OverloadCandidate());
+ OverloadCandidate& Candidate = CandidateSet.back();
+ Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
+ Candidate.Function = 0;
+ Candidate.IsSurrogate = false;
+ Candidate.IgnoreObjectArgument = false;
+ Candidate.BuiltinTypes.ResultTy = ResultTy;
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+ Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx];
+
+ // Determine the implicit conversion sequences for each of the
+ // arguments.
+ Candidate.Viable = true;
+ Candidate.Conversions.resize(NumArgs);
+ Candidate.ExplicitCallArguments = NumArgs;
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ // C++ [over.match.oper]p4:
+ // For the built-in assignment operators, conversions of the
+ // left operand are restricted as follows:
+ // -- no temporaries are introduced to hold the left operand, and
+ // -- no user-defined conversions are applied to the left
+ // operand to achieve a type match with the left-most
+ // parameter of a built-in candidate.
+ //
+ // We block these conversions by turning off user-defined
+ // conversions, since that is the only way that initialization of
+ // a reference to a non-class type can occur from something that
+ // is not of the same type.
+ if (ArgIdx < NumContextualBoolArguments) {
+ assert(ParamTys[ArgIdx] == Context.BoolTy &&
+ "Contextual conversion to bool requires bool type");
+ Candidate.Conversions[ArgIdx]
+ = TryContextuallyConvertToBool(*this, Args[ArgIdx]);
+ } else {
+ Candidate.Conversions[ArgIdx]
+ = TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx],
+ ArgIdx == 0 && IsAssignmentOperator,
+ /*InOverloadResolution=*/false);
+ }
+ if (Candidate.Conversions[ArgIdx].isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ break;
+ }
+ }
+}
+
+/// BuiltinCandidateTypeSet - A set of types that will be used for the
+/// candidate operator functions for built-in operators (C++
+/// [over.built]). The types are separated into pointer types and
+/// enumeration types.
+class BuiltinCandidateTypeSet {
+ /// TypeSet - A set of types.
+ typedef llvm::SmallPtrSet<QualType, 8> TypeSet;
+
+ /// PointerTypes - The set of pointer types that will be used in the
+ /// built-in candidates.
+ TypeSet PointerTypes;
+
+ /// MemberPointerTypes - The set of member pointer types that will be
+ /// used in the built-in candidates.
+ TypeSet MemberPointerTypes;
+
+ /// EnumerationTypes - The set of enumeration types that will be
+ /// used in the built-in candidates.
+ TypeSet EnumerationTypes;
+
+ /// \brief The set of vector types that will be used in the built-in
+ /// candidates.
+ TypeSet VectorTypes;
+
+ /// \brief A flag indicating non-record types are viable candidates
+ bool HasNonRecordTypes;
+
+ /// \brief A flag indicating whether either arithmetic or enumeration types
+ /// were present in the candidate set.
+ bool HasArithmeticOrEnumeralTypes;
+
+ /// Sema - The semantic analysis instance where we are building the
+ /// candidate type set.
+ Sema &SemaRef;
+
+ /// Context - The AST context in which we will build the type sets.
+ ASTContext &Context;
+
+ bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+ const Qualifiers &VisibleQuals);
+ bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);
+
+public:
+ /// iterator - Iterates through the types that are part of the set.
+ typedef TypeSet::iterator iterator;
+
+ BuiltinCandidateTypeSet(Sema &SemaRef)
+ : HasNonRecordTypes(false),
+ HasArithmeticOrEnumeralTypes(false),
+ SemaRef(SemaRef),
+ Context(SemaRef.Context) { }
+
+ void AddTypesConvertedFrom(QualType Ty,
+ SourceLocation Loc,
+ bool AllowUserConversions,
+ bool AllowExplicitConversions,
+ const Qualifiers &VisibleTypeConversionsQuals);
+
+ /// pointer_begin - First pointer type found;
+ iterator pointer_begin() { return PointerTypes.begin(); }
+
+ /// pointer_end - Past the last pointer type found;
+ iterator pointer_end() { return PointerTypes.end(); }
+
+ /// member_pointer_begin - First member pointer type found;
+ iterator member_pointer_begin() { return MemberPointerTypes.begin(); }
+
+ /// member_pointer_end - Past the last member pointer type found;
+ iterator member_pointer_end() { return MemberPointerTypes.end(); }
+
+ /// enumeration_begin - First enumeration type found;
+ iterator enumeration_begin() { return EnumerationTypes.begin(); }
+
+ /// enumeration_end - Past the last enumeration type found;
+ iterator enumeration_end() { return EnumerationTypes.end(); }
+
+ iterator vector_begin() { return VectorTypes.begin(); }
+ iterator vector_end() { return VectorTypes.end(); }
+
+ bool hasNonRecordTypes() { return HasNonRecordTypes; }
+ bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; }
+};
+
+/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to
+/// the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+ const Qualifiers &VisibleQuals) {
+
+ // Insert this type.
+ if (!PointerTypes.insert(Ty))
+ return false;
+
+ QualType PointeeTy;
+ const PointerType *PointerTy = Ty->getAs<PointerType>();
+ bool buildObjCPtr = false;
+ if (!PointerTy) {
+ if (const ObjCObjectPointerType *PTy = Ty->getAs<ObjCObjectPointerType>()) {
+ PointeeTy = PTy->getPointeeType();
+ buildObjCPtr = true;
+ }
+ else
+ assert(false && "type was not a pointer type!");
+ }
+ else
+ PointeeTy = PointerTy->getPointeeType();
+
+ // Don't add qualified variants of arrays. For one, they're not allowed
+ // (the qualifier would sink to the element type), and for another, the
+ // only overload situation where it matters is subscript or pointer +- int,
+ // and those shouldn't have qualifier variants anyway.
+ if (PointeeTy->isArrayType())
+ return true;
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+ if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy))
+ BaseCVR = Array->getElementType().getCVRQualifiers();
+ bool hasVolatile = VisibleQuals.hasVolatile();
+ bool hasRestrict = VisibleQuals.hasRestrict();
+
+ // Iterate through all strict supersets of BaseCVR.
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+ // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere
+ // in the types.
+ if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
+ if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ if (!buildObjCPtr)
+ PointerTypes.insert(Context.getPointerType(QPointeeTy));
+ else
+ PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy));
+ }
+
+ return true;
+}
+
+/// AddMemberPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty
+/// to the set of pointer types along with any more-qualified variants of
+/// that type. For example, if @p Ty is "int const *", this routine
+/// will add "int const *", "int const volatile *", "int const
+/// restrict *", and "int const volatile restrict *" to the set of
+/// pointer types. Returns true if the add of @p Ty itself succeeded,
+/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
+bool
+BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
+ QualType Ty) {
+ // Insert this type.
+ if (!MemberPointerTypes.insert(Ty))
+ return false;
+
+ const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+ assert(PointerTy && "type was not a member pointer type!");
+
+ QualType PointeeTy = PointerTy->getPointeeType();
+ // Don't add qualified variants of arrays. For one, they're not allowed
+ // (the qualifier would sink to the element type), and for another, the
+ // only overload situation where it matters is subscript or pointer +- int,
+ // and those shouldn't have qualifier variants anyway.
+ if (PointeeTy->isArrayType())
+ return true;
+ const Type *ClassTy = PointerTy->getClass();
+
+ // Iterate through all strict supersets of the pointee type's CVR
+ // qualifiers.
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ MemberPointerTypes.insert(
+ Context.getMemberPointerType(QPointeeTy, ClassTy));
+ }
+
+ return true;
+}
+
+/// AddTypesConvertedFrom - Add each of the types to which the type @p
+/// Ty can be implicit converted to the given set of @p Types. We're
+/// primarily interested in pointer types and enumeration types. We also
+/// take member pointer types, for the conditional operator.
+/// AllowUserConversions is true if we should look at the conversion
+/// functions of a class type, and AllowExplicitConversions if we
+/// should also include the explicit conversion functions of a class
+/// type.
+void
+BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
+ SourceLocation Loc,
+ bool AllowUserConversions,
+ bool AllowExplicitConversions,
+ const Qualifiers &VisibleQuals) {
+ // Only deal with canonical types.
+ Ty = Context.getCanonicalType(Ty);
+
+ // Look through reference types; they aren't part of the type of an
+ // expression for the purposes of conversions.
+ if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>())
+ Ty = RefTy->getPointeeType();
+
+ // If we're dealing with an array type, decay to the pointer.
+ if (Ty->isArrayType())
+ Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
+ // Otherwise, we don't care about qualifiers on the type.
+ Ty = Ty.getLocalUnqualifiedType();
+
+ // Flag if we ever add a non-record type.
+ const RecordType *TyRec = Ty->getAs<RecordType>();
+ HasNonRecordTypes = HasNonRecordTypes || !TyRec;
+
+ // Flag if we encounter an arithmetic type.
+ HasArithmeticOrEnumeralTypes =
+ HasArithmeticOrEnumeralTypes || Ty->isArithmeticType();
+
+ if (Ty->isObjCIdType() || Ty->isObjCClassType())
+ PointerTypes.insert(Ty);
+ else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
+ // Insert our type, and its more-qualified variants, into the set
+ // of types.
+ if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
+ return;
+ } else if (Ty->isMemberPointerType()) {
+ // Member pointers are far easier, since the pointee can't be converted.
+ if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
+ return;
+ } else if (Ty->isEnumeralType()) {
+ HasArithmeticOrEnumeralTypes = true;
+ EnumerationTypes.insert(Ty);
+ } else if (Ty->isVectorType()) {
+ // We treat vector types as arithmetic types in many contexts as an
+ // extension.
+ HasArithmeticOrEnumeralTypes = true;
+ VectorTypes.insert(Ty);
+ } else if (AllowUserConversions && TyRec) {
+ // No conversion functions in incomplete types.
+ if (SemaRef.RequireCompleteType(Loc, Ty, 0))
+ return;
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ const UnresolvedSetImpl *Conversions
+ = ClassDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = I.getDecl();
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ // Skip conversion function templates; they don't tell us anything
+ // about which builtin types we can convert to.
+ if (isa<FunctionTemplateDecl>(D))
+ continue;
+
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+ if (AllowExplicitConversions || !Conv->isExplicit()) {
+ AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
+ VisibleQuals);
+ }
+ }
+ }
+}
+
+/// \brief Helper function for AddBuiltinOperatorCandidates() that adds
+/// the volatile- and non-volatile-qualified assignment operators for the
+/// given type to the candidate set.
+static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
+ QualType T,
+ Expr **Args,
+ unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet) {
+ QualType ParamTypes[2];
+
+ // T& operator=(T&, T)
+ ParamTypes[0] = S.Context.getLValueReferenceType(T);
+ ParamTypes[1] = T;
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssignmentOperator=*/true);
+
+ if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
+ // volatile T& operator=(volatile T&, T)
+ ParamTypes[0]
+ = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
+ ParamTypes[1] = T;
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssignmentOperator=*/true);
+ }
+}
+
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers,
+/// if any, found in visible type conversion functions found in ArgExpr's type.
+static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
+ Qualifiers VRQuals;
+ const RecordType *TyRec;
+ if (const MemberPointerType *RHSMPType =
+ ArgExpr->getType()->getAs<MemberPointerType>())
+ TyRec = RHSMPType->getClass()->getAs<RecordType>();
+ else
+ TyRec = ArgExpr->getType()->getAs<RecordType>();
+ if (!TyRec) {
+ // Just to be safe, assume the worst case.
+ VRQuals.addVolatile();
+ VRQuals.addRestrict();
+ return VRQuals;
+ }
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ if (!ClassDecl->hasDefinition())
+ return VRQuals;
+
+ const UnresolvedSetImpl *Conversions =
+ ClassDecl->getVisibleConversionFunctions();
+
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = I.getDecl();
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) {
+ QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
+ if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
+ CanTy = ResTypeRef->getPointeeType();
+ // Need to go down the pointer/mempointer chain and add qualifiers
+ // as see them.
+ bool done = false;
+ while (!done) {
+ if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
+ CanTy = ResTypePtr->getPointeeType();
+ else if (const MemberPointerType *ResTypeMPtr =
+ CanTy->getAs<MemberPointerType>())
+ CanTy = ResTypeMPtr->getPointeeType();
+ else
+ done = true;
+ if (CanTy.isVolatileQualified())
+ VRQuals.addVolatile();
+ if (CanTy.isRestrictQualified())
+ VRQuals.addRestrict();
+ if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
+ return VRQuals;
+ }
+ }
+ }
+ return VRQuals;
+}
+
+namespace {
+
+/// \brief Helper class to manage the addition of builtin operator overload
+/// candidates. It provides shared state and utility methods used throughout
+/// the process, as well as a helper method to add each group of builtin
+/// operator overloads from the standard to a candidate set.
+class BuiltinOperatorOverloadBuilder {
+ // Common instance state available to all overload candidate addition methods.
+ Sema &S;
+ Expr **Args;
+ unsigned NumArgs;
+ Qualifiers VisibleTypeConversionsQuals;
+ bool HasArithmeticOrEnumeralCandidateType;
+ llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
+ OverloadCandidateSet &CandidateSet;
+
+ // Define some constants used to index and iterate over the arithemetic types
+ // provided via the getArithmeticType() method below.
+ // The "promoted arithmetic types" are the arithmetic
+ // types are that preserved by promotion (C++ [over.built]p2).
+ static const unsigned FirstIntegralType = 3;
+ static const unsigned LastIntegralType = 18;
+ static const unsigned FirstPromotedIntegralType = 3,
+ LastPromotedIntegralType = 9;
+ static const unsigned FirstPromotedArithmeticType = 0,
+ LastPromotedArithmeticType = 9;
+ static const unsigned NumArithmeticTypes = 18;
+
+ /// \brief Get the canonical type for a given arithmetic type index.
+ CanQualType getArithmeticType(unsigned index) {
+ assert(index < NumArithmeticTypes);
+ static CanQualType ASTContext::* const
+ ArithmeticTypes[NumArithmeticTypes] = {
+ // Start of promoted types.
+ &ASTContext::FloatTy,
+ &ASTContext::DoubleTy,
+ &ASTContext::LongDoubleTy,
+
+ // Start of integral types.
+ &ASTContext::IntTy,
+ &ASTContext::LongTy,
+ &ASTContext::LongLongTy,
+ &ASTContext::UnsignedIntTy,
+ &ASTContext::UnsignedLongTy,
+ &ASTContext::UnsignedLongLongTy,
+ // End of promoted types.
+
+ &ASTContext::BoolTy,
+ &ASTContext::CharTy,
+ &ASTContext::WCharTy,
+ &ASTContext::Char16Ty,
+ &ASTContext::Char32Ty,
+ &ASTContext::SignedCharTy,
+ &ASTContext::ShortTy,
+ &ASTContext::UnsignedCharTy,
+ &ASTContext::UnsignedShortTy,
+ // End of integral types.
+ // FIXME: What about complex?
+ };
+ return S.Context.*ArithmeticTypes[index];
+ }
+
+ /// \brief Gets the canonical type resulting from the usual arithemetic
+ /// converions for the given arithmetic types.
+ CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
+ // Accelerator table for performing the usual arithmetic conversions.
+ // The rules are basically:
+ // - if either is floating-point, use the wider floating-point
+ // - if same signedness, use the higher rank
+ // - if same size, use unsigned of the higher rank
+ // - use the larger type
+ // These rules, together with the axiom that higher ranks are
+ // never smaller, are sufficient to precompute all of these results
+ // *except* when dealing with signed types of higher rank.
+ // (we could precompute SLL x UI for all known platforms, but it's
+ // better not to make any assumptions).
+ enum PromotedType {
+ Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1
+ };
+ static PromotedType ConversionsTable[LastPromotedArithmeticType]
+ [LastPromotedArithmeticType] = {
+ /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt },
+ /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl },
+ /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
+ /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL },
+ /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL },
+ /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL },
+ /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL },
+ /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL },
+ /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL },
+ };
+
+ assert(L < LastPromotedArithmeticType);
+ assert(R < LastPromotedArithmeticType);
+ int Idx = ConversionsTable[L][R];
+
+ // Fast path: the table gives us a concrete answer.
+ if (Idx != Dep) return getArithmeticType(Idx);
+
+ // Slow path: we need to compare widths.
+ // An invariant is that the signed type has higher rank.
+ CanQualType LT = getArithmeticType(L),
+ RT = getArithmeticType(R);
+ unsigned LW = S.Context.getIntWidth(LT),
+ RW = S.Context.getIntWidth(RT);
+
+ // If they're different widths, use the signed type.
+ if (LW > RW) return LT;
+ else if (LW < RW) return RT;
+
+ // Otherwise, use the unsigned type of the signed type's rank.
+ if (L == SL || R == SL) return S.Context.UnsignedLongTy;
+ assert(L == SLL || R == SLL);
+ return S.Context.UnsignedLongLongTy;
+ }
+
+ /// \brief Helper method to factor out the common pattern of adding overloads
+ /// for '++' and '--' builtin operators.
+ void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
+ bool HasVolatile) {
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(CandidateTy),
+ S.Context.IntTy
+ };
+
+ // Non-volatile version.
+ if (NumArgs == 1)
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+ else
+ S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+
+ // Use a heuristic to reduce number of builtin candidates in the set:
+ // add volatile version only if there are conversions to a volatile type.
+ if (HasVolatile) {
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(
+ S.Context.getVolatileType(CandidateTy));
+ if (NumArgs == 1)
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+ else
+ S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+
+public:
+ BuiltinOperatorOverloadBuilder(
+ Sema &S, Expr **Args, unsigned NumArgs,
+ Qualifiers VisibleTypeConversionsQuals,
+ bool HasArithmeticOrEnumeralCandidateType,
+ llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
+ OverloadCandidateSet &CandidateSet)
+ : S(S), Args(Args), NumArgs(NumArgs),
+ VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
+ HasArithmeticOrEnumeralCandidateType(
+ HasArithmeticOrEnumeralCandidateType),
+ CandidateTypes(CandidateTypes),
+ CandidateSet(CandidateSet) {
+ // Validate some of our static helper constants in debug builds.
+ assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
+ "Invalid first promoted integral type");
+ assert(getArithmeticType(LastPromotedIntegralType - 1)
+ == S.Context.UnsignedLongLongTy &&
+ "Invalid last promoted integral type");
+ assert(getArithmeticType(FirstPromotedArithmeticType)
+ == S.Context.FloatTy &&
+ "Invalid first promoted arithmetic type");
+ assert(getArithmeticType(LastPromotedArithmeticType - 1)
+ == S.Context.UnsignedLongLongTy &&
+ "Invalid last promoted arithmetic type");
+ }
+
+ // C++ [over.built]p3:
+ //
+ // For every pair (T, VQ), where T is an arithmetic type, and VQ
+ // is either volatile or empty, there exist candidate operator
+ // functions of the form
+ //
+ // VQ T& operator++(VQ T&);
+ // T operator++(VQ T&, int);
+ //
+ // C++ [over.built]p4:
+ //
+ // For every pair (T, VQ), where T is an arithmetic type other
+ // than bool, and VQ is either volatile or empty, there exist
+ // candidate operator functions of the form
+ //
+ // VQ T& operator--(VQ T&);
+ // T operator--(VQ T&, int);
+ void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
+ Arith < NumArithmeticTypes; ++Arith) {
+ addPlusPlusMinusMinusStyleOverloads(
+ getArithmeticType(Arith),
+ VisibleTypeConversionsQuals.hasVolatile());
+ }
+ }
+
+ // C++ [over.built]p5:
+ //
+ // For every pair (T, VQ), where T is a cv-qualified or
+ // cv-unqualified object type, and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // T*VQ& operator++(T*VQ&);
+ // T*VQ& operator--(T*VQ&);
+ // T* operator++(T*VQ&, int);
+ // T* operator--(T*VQ&, int);
+ void addPlusPlusMinusMinusPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // Skip pointer types that aren't pointers to object types.
+ if (!(*Ptr)->getPointeeType()->isObjectType())
+ continue;
+
+ addPlusPlusMinusMinusStyleOverloads(*Ptr,
+ (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()));
+ }
+ }
+
+ // C++ [over.built]p6:
+ // For every cv-qualified or cv-unqualified object type T, there
+ // exist candidate operator functions of the form
+ //
+ // T& operator*(T*);
+ //
+ // C++ [over.built]p7:
+ // For every function type T that does not have cv-qualifiers or a
+ // ref-qualifier, there exist candidate operator functions of the form
+ // T& operator*(T*);
+ void addUnaryStarPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTy = *Ptr;
+ QualType PointeeTy = ParamTy->getPointeeType();
+ if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
+ continue;
+
+ if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
+ if (Proto->getTypeQuals() || Proto->getRefQualifier())
+ continue;
+
+ S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
+ &ParamTy, Args, 1, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p9:
+ // For every promoted arithmetic type T, there exist candidate
+ // operator functions of the form
+ //
+ // T operator+(T);
+ // T operator-(T);
+ void addUnaryPlusOrMinusArithmeticOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Arith = FirstPromotedArithmeticType;
+ Arith < LastPromotedArithmeticType; ++Arith) {
+ QualType ArithTy = getArithmeticType(Arith);
+ S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet);
+ }
+
+ // Extension: We also add these operators for vector types.
+ for (BuiltinCandidateTypeSet::iterator
+ Vec = CandidateTypes[0].vector_begin(),
+ VecEnd = CandidateTypes[0].vector_end();
+ Vec != VecEnd; ++Vec) {
+ QualType VecTy = *Vec;
+ S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p8:
+ // For every type T, there exist candidate operator functions of
+ // the form
+ //
+ // T* operator+(T*);
+ void addUnaryPlusPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTy = *Ptr;
+ S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p10:
+ // For every promoted integral type T, there exist candidate
+ // operator functions of the form
+ //
+ // T operator~(T);
+ void addUnaryTildePromotedIntegralOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Int = FirstPromotedIntegralType;
+ Int < LastPromotedIntegralType; ++Int) {
+ QualType IntTy = getArithmeticType(Int);
+ S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet);
+ }
+
+ // Extension: We also add this operator for vector types.
+ for (BuiltinCandidateTypeSet::iterator
+ Vec = CandidateTypes[0].vector_begin(),
+ VecEnd = CandidateTypes[0].vector_end();
+ Vec != VecEnd; ++Vec) {
+ QualType VecTy = *Vec;
+ S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+ }
+ }
+
+ // C++ [over.match.oper]p16:
+ // For every pointer to member type T, there exist candidate operator
+ // functions of the form
+ //
+ // bool operator==(T,T);
+ // bool operator!=(T,T);
+ void addEqualEqualOrNotEqualMemberPointerOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd;
+ ++MemPtr) {
+ // Don't add the same builtin candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ continue;
+
+ QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p15:
+ //
+ // For every pointer or enumeration type T, there exist
+ // candidate operator functions of the form
+ //
+ // bool operator<(T, T);
+ // bool operator>(T, T);
+ // bool operator<=(T, T);
+ // bool operator>=(T, T);
+ // bool operator==(T, T);
+ // bool operator!=(T, T);
+ void addRelationalPointerOrEnumeralOverloads() {
+ // C++ [over.built]p1:
+ // If there is a user-written candidate with the same name and parameter
+ // types as a built-in candidate operator function, the built-in operator
+ // function is hidden and is not included in the set of candidate
+ // functions.
+ //
+ // The text is actually in a note, but if we don't implement it then we end
+ // up with ambiguities when the user provides an overloaded operator for
+ // an enumeration type. Note that only enumeration types have this problem,
+ // so we track which enumeration types we've seen operators for. Also, the
+ // only other overloaded operator with enumeration argumenst, operator=,
+ // cannot be overloaded for enumeration types, so this is the only place
+ // where we must suppress candidates like this.
+ llvm::DenseSet<std::pair<CanQualType, CanQualType> >
+ UserDefinedBinaryOperators;
+
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ if (CandidateTypes[ArgIdx].enumeration_begin() !=
+ CandidateTypes[ArgIdx].enumeration_end()) {
+ for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
+ CEnd = CandidateSet.end();
+ C != CEnd; ++C) {
+ if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
+ continue;
+
+ QualType FirstParamType =
+ C->Function->getParamDecl(0)->getType().getUnqualifiedType();
+ QualType SecondParamType =
+ C->Function->getParamDecl(1)->getType().getUnqualifiedType();
+
+ // Skip if either parameter isn't of enumeral type.
+ if (!FirstParamType->isEnumeralType() ||
+ !SecondParamType->isEnumeralType())
+ continue;
+
+ // Add this operator to the set of known user-defined operators.
+ UserDefinedBinaryOperators.insert(
+ std::make_pair(S.Context.getCanonicalType(FirstParamType),
+ S.Context.getCanonicalType(SecondParamType)));
+ }
+ }
+ }
+
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+ PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // Don't add the same builtin candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ for (BuiltinCandidateTypeSet::iterator
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ CanQualType CanonType = S.Context.getCanonicalType(*Enum);
+
+ // Don't add the same builtin candidate twice, or if a user defined
+ // candidate exists.
+ if (!AddedTypes.insert(CanonType) ||
+ UserDefinedBinaryOperators.count(std::make_pair(CanonType,
+ CanonType)))
+ continue;
+
+ QualType ParamTypes[2] = { *Enum, *Enum };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p13:
+ //
+ // For every cv-qualified or cv-unqualified object type T
+ // there exist candidate operator functions of the form
+ //
+ // T* operator+(T*, ptrdiff_t);
+ // T& operator[](T*, ptrdiff_t); [BELOW]
+ // T* operator-(T*, ptrdiff_t);
+ // T* operator+(ptrdiff_t, T*);
+ // T& operator[](ptrdiff_t, T*); [BELOW]
+ //
+ // C++ [over.built]p14:
+ //
+ // For every T, where T is a pointer to object type, there
+ // exist candidate operator functions of the form
+ //
+ // ptrdiff_t operator-(T, T);
+ void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (int Arg = 0; Arg < 2; ++Arg) {
+ QualType AsymetricParamTypes[2] = {
+ S.Context.getPointerDiffType(),
+ S.Context.getPointerDiffType(),
+ };
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[Arg].pointer_begin(),
+ PtrEnd = CandidateTypes[Arg].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType PointeeTy = (*Ptr)->getPointeeType();
+ if (!PointeeTy->isObjectType())
+ continue;
+
+ AsymetricParamTypes[Arg] = *Ptr;
+ if (Arg == 0 || Op == OO_Plus) {
+ // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
+ // T* operator+(ptrdiff_t, T*);
+ S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2,
+ CandidateSet);
+ }
+ if (Op == OO_Minus) {
+ // ptrdiff_t operator-(T, T);
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes,
+ Args, 2, CandidateSet);
+ }
+ }
+ }
+ }
+
+ // C++ [over.built]p12:
+ //
+ // For every pair of promoted arithmetic types L and R, there
+ // exist candidate operator functions of the form
+ //
+ // LR operator*(L, R);
+ // LR operator/(L, R);
+ // LR operator+(L, R);
+ // LR operator-(L, R);
+ // bool operator<(L, R);
+ // bool operator>(L, R);
+ // bool operator<=(L, R);
+ // bool operator>=(L, R);
+ // bool operator==(L, R);
+ // bool operator!=(L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ //
+ // C++ [over.built]p24:
+ //
+ // For every pair of promoted arithmetic types L and R, there exist
+ // candidate operator functions of the form
+ //
+ // LR operator?(bool, L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ // Our candidates ignore the first parameter.
+ void addGenericBinaryArithmeticOverloads(bool isComparison) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Left = FirstPromotedArithmeticType;
+ Left < LastPromotedArithmeticType; ++Left) {
+ for (unsigned Right = FirstPromotedArithmeticType;
+ Right < LastPromotedArithmeticType; ++Right) {
+ QualType LandR[2] = { getArithmeticType(Left),
+ getArithmeticType(Right) };
+ QualType Result =
+ isComparison ? S.Context.BoolTy
+ : getUsualArithmeticConversions(Left, Right);
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+ }
+ }
+
+ // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the
+ // conditional operator for vector types.
+ for (BuiltinCandidateTypeSet::iterator
+ Vec1 = CandidateTypes[0].vector_begin(),
+ Vec1End = CandidateTypes[0].vector_end();
+ Vec1 != Vec1End; ++Vec1) {
+ for (BuiltinCandidateTypeSet::iterator
+ Vec2 = CandidateTypes[1].vector_begin(),
+ Vec2End = CandidateTypes[1].vector_end();
+ Vec2 != Vec2End; ++Vec2) {
+ QualType LandR[2] = { *Vec1, *Vec2 };
+ QualType Result = S.Context.BoolTy;
+ if (!isComparison) {
+ if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType())
+ Result = *Vec1;
+ else
+ Result = *Vec2;
+ }
+
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p17:
+ //
+ // For every pair of promoted integral types L and R, there
+ // exist candidate operator functions of the form
+ //
+ // LR operator%(L, R);
+ // LR operator&(L, R);
+ // LR operator^(L, R);
+ // LR operator|(L, R);
+ // L operator<<(L, R);
+ // L operator>>(L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Left = FirstPromotedIntegralType;
+ Left < LastPromotedIntegralType; ++Left) {
+ for (unsigned Right = FirstPromotedIntegralType;
+ Right < LastPromotedIntegralType; ++Right) {
+ QualType LandR[2] = { getArithmeticType(Left),
+ getArithmeticType(Right) };
+ QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
+ ? LandR[0]
+ : getUsualArithmeticConversions(Left, Right);
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p20:
+ //
+ // For every pair (T, VQ), where T is an enumeration or
+ // pointer to member type and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // VQ T& operator=(VQ T&, T);
+ void addAssignmentMemberPointerOrEnumeralOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+ continue;
+
+ AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2,
+ CandidateSet);
+ }
+
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ continue;
+
+ AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p19:
+ //
+ // For every pair (T, VQ), where T is any type and VQ is either
+ // volatile or empty, there exist candidate operator functions
+ // of the form
+ //
+ // T*VQ& operator=(T*VQ&, T*);
+ //
+ // C++ [over.built]p21:
+ //
+ // For every pair (T, VQ), where T is a cv-qualified or
+ // cv-unqualified object type and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // T*VQ& operator+=(T*VQ&, ptrdiff_t);
+ // T*VQ& operator-=(T*VQ&, ptrdiff_t);
+ void addAssignmentPointerOverloads(bool isEqualOp) {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // If this is operator=, keep track of the builtin candidates we added.
+ if (isEqualOp)
+ AddedTypes.insert(S.Context.getCanonicalType(*Ptr));
+ else if (!(*Ptr)->getPointeeType()->isObjectType())
+ continue;
+
+ // non-volatile version
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(*Ptr),
+ isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
+ };
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/ isEqualOp);
+
+ if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()) {
+ // volatile version
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+ }
+ }
+
+ if (isEqualOp) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[1].pointer_begin(),
+ PtrEnd = CandidateTypes[1].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // Make sure we don't add the same candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(*Ptr),
+ *Ptr,
+ };
+
+ // non-volatile version
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/true);
+
+ if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()) {
+ // volatile version
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet, /*IsAssigmentOperator=*/true);
+ }
+ }
+ }
+ }
+
+ // C++ [over.built]p18:
+ //
+ // For every triple (L, VQ, R), where L is an arithmetic type,
+ // VQ is either volatile or empty, and R is a promoted
+ // arithmetic type, there exist candidate operator functions of
+ // the form
+ //
+ // VQ L& operator=(VQ L&, R);
+ // VQ L& operator*=(VQ L&, R);
+ // VQ L& operator/=(VQ L&, R);
+ // VQ L& operator+=(VQ L&, R);
+ // VQ L& operator-=(VQ L&, R);
+ void addAssignmentArithmeticOverloads(bool isEqualOp) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
+ for (unsigned Right = FirstPromotedArithmeticType;
+ Right < LastPromotedArithmeticType; ++Right) {
+ QualType ParamTypes[2];
+ ParamTypes[1] = getArithmeticType(Right);
+
+ // Add this built-in operator as a candidate (VQ is empty).
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+
+ // Add this built-in operator as a candidate (VQ is 'volatile').
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ ParamTypes[0] =
+ S.Context.getVolatileType(getArithmeticType(Left));
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+ }
+ }
+ }
+
+ // Extension: Add the binary operators =, +=, -=, *=, /= for vector types.
+ for (BuiltinCandidateTypeSet::iterator
+ Vec1 = CandidateTypes[0].vector_begin(),
+ Vec1End = CandidateTypes[0].vector_end();
+ Vec1 != Vec1End; ++Vec1) {
+ for (BuiltinCandidateTypeSet::iterator
+ Vec2 = CandidateTypes[1].vector_begin(),
+ Vec2End = CandidateTypes[1].vector_end();
+ Vec2 != Vec2End; ++Vec2) {
+ QualType ParamTypes[2];
+ ParamTypes[1] = *Vec2;
+ // Add this built-in operator as a candidate (VQ is empty).
+ ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+
+ // Add this built-in operator as a candidate (VQ is 'volatile').
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ ParamTypes[0] = S.Context.getVolatileType(*Vec1);
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+ }
+ }
+ }
+ }
+
+ // C++ [over.built]p22:
+ //
+ // For every triple (L, VQ, R), where L is an integral type, VQ
+ // is either volatile or empty, and R is a promoted integral
+ // type, there exist candidate operator functions of the form
+ //
+ // VQ L& operator%=(VQ L&, R);
+ // VQ L& operator<<=(VQ L&, R);
+ // VQ L& operator>>=(VQ L&, R);
+ // VQ L& operator&=(VQ L&, R);
+ // VQ L& operator^=(VQ L&, R);
+ // VQ L& operator|=(VQ L&, R);
+ void addAssignmentIntegralOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
+ for (unsigned Right = FirstPromotedIntegralType;
+ Right < LastPromotedIntegralType; ++Right) {
+ QualType ParamTypes[2];
+ ParamTypes[1] = getArithmeticType(Right);
+
+ // Add this built-in operator as a candidate (VQ is empty).
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ // Add this built-in operator as a candidate (VQ is 'volatile').
+ ParamTypes[0] = getArithmeticType(Left);
+ ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
+ }
+
+ // C++ [over.operator]p23:
+ //
+ // There also exist candidate operator functions of the form
+ //
+ // bool operator!(bool);
+ // bool operator&&(bool, bool);
+ // bool operator||(bool, bool);
+ void addExclaimOverload() {
+ QualType ParamTy = S.Context.BoolTy;
+ S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet,
+ /*IsAssignmentOperator=*/false,
+ /*NumContextualBoolArguments=*/1);
+ }
+ void addAmpAmpOrPipePipeOverload() {
+ QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet,
+ /*IsAssignmentOperator=*/false,
+ /*NumContextualBoolArguments=*/2);
+ }
+
+ // C++ [over.built]p13:
+ //
+ // For every cv-qualified or cv-unqualified object type T there
+ // exist candidate operator functions of the form
+ //
+ // T* operator+(T*, ptrdiff_t); [ABOVE]
+ // T& operator[](T*, ptrdiff_t);
+ // T* operator-(T*, ptrdiff_t); [ABOVE]
+ // T* operator+(ptrdiff_t, T*); [ABOVE]
+ // T& operator[](ptrdiff_t, T*);
+ void addSubscriptOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() };
+ QualType PointeeType = (*Ptr)->getPointeeType();
+ if (!PointeeType->isObjectType())
+ continue;
+
+ QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
+
+ // T& operator[](T*, ptrdiff_t)
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[1].pointer_begin(),
+ PtrEnd = CandidateTypes[1].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr };
+ QualType PointeeType = (*Ptr)->getPointeeType();
+ if (!PointeeType->isObjectType())
+ continue;
+
+ QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
+
+ // T& operator[](ptrdiff_t, T*)
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p11:
+ // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type,
+ // C1 is the same type as C2 or is a derived class of C2, T is an object
+ // type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
+ // there exist candidate operator functions of the form
+ //
+ // CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
+ //
+ // where CV12 is the union of CV1 and CV2.
+ void addArrowStarOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType C1Ty = (*Ptr);
+ QualType C1;
+ QualifierCollector Q1;
+ C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
+ if (!isa<RecordType>(C1))
+ continue;
+ // heuristic to reduce number of builtin candidates in the set.
+ // Add volatile/restrict version only if there are conversions to a
+ // volatile/restrict type.
+ if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+ continue;
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[1].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[1].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+ QualType C2 = QualType(mptr->getClass(), 0);
+ C2 = C2.getUnqualifiedType();
+ if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
+ break;
+ QualType ParamTypes[2] = { *Ptr, *MemPtr };
+ // build CV12 T&
+ QualType T = mptr->getPointeeType();
+ if (!VisibleTypeConversionsQuals.hasVolatile() &&
+ T.isVolatileQualified())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() &&
+ T.isRestrictQualified())
+ continue;
+ T = Q1.apply(S.Context, T);
+ QualType ResultTy = S.Context.getLValueReferenceType(T);
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+ }
+
+ // Note that we don't consider the first argument, since it has been
+ // contextually converted to bool long ago. The candidates below are
+ // therefore added as binary.
+ //
+ // C++ [over.built]p25:
+ // For every type T, where T is a pointer, pointer-to-member, or scoped
+ // enumeration type, there exist candidate operator functions of the form
+ //
+ // T operator?(bool, T, T);
+ //
+ void addConditionalOperatorOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+ PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+ }
+
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ continue;
+
+ QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet);
+ }
+
+ if (S.getLangOptions().CPlusPlus0x) {
+ for (BuiltinCandidateTypeSet::iterator
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
+ continue;
+
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+ continue;
+
+ QualType ParamTypes[2] = { *Enum, *Enum };
+ S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
+/// AddBuiltinOperatorCandidates - Add the appropriate built-in
+/// operator overloads to the candidate set (C++ [over.built]), based
+/// on the operator @p Op and the arguments given. For example, if the
+/// operator is a binary '+', this routine might add "int
+/// operator+(int, int)" to cover integer addition.
+void
+Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet) {
+ // Find all of the types that the arguments can convert to, but only
+ // if the operator we're looking at has built-in operator candidates
+ // that make use of these types. Also record whether we encounter non-record
+ // candidate types or either arithmetic or enumeral candidate types.
+ Qualifiers VisibleTypeConversionsQuals;
+ VisibleTypeConversionsQuals.addConst();
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+ VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+
+ bool HasNonRecordCandidateType = false;
+ bool HasArithmeticOrEnumeralCandidateType = false;
+ llvm::SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ CandidateTypes.push_back(BuiltinCandidateTypeSet(*this));
+ CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+ OpLoc,
+ true,
+ (Op == OO_Exclaim ||
+ Op == OO_AmpAmp ||
+ Op == OO_PipePipe),
+ VisibleTypeConversionsQuals);
+ HasNonRecordCandidateType = HasNonRecordCandidateType ||
+ CandidateTypes[ArgIdx].hasNonRecordTypes();
+ HasArithmeticOrEnumeralCandidateType =
+ HasArithmeticOrEnumeralCandidateType ||
+ CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes();
+ }
+
+ // Exit early when no non-record types have been added to the candidate set
+ // for any of the arguments to the operator.
+ if (!HasNonRecordCandidateType)
+ return;
+
+ // Setup an object to manage the common state for building overloads.
+ BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs,
+ VisibleTypeConversionsQuals,
+ HasArithmeticOrEnumeralCandidateType,
+ CandidateTypes, CandidateSet);
+
+ // Dispatch over the operation to add in only those overloads which apply.
+ switch (Op) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ assert(false && "Expected an overloaded operator");
+ break;
+
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ case OO_Call:
+ assert(false && "Special operators don't use AddBuiltinOperatorCandidates");
+ break;
+
+ case OO_Comma:
+ case OO_Arrow:
+ // C++ [over.match.oper]p3:
+ // -- For the operator ',', the unary operator '&', or the
+ // operator '->', the built-in candidates set is empty.
+ break;
+
+ case OO_Plus: // '+' is either unary or binary
+ if (NumArgs == 1)
+ OpBuilder.addUnaryPlusPointerOverloads();
+ // Fall through.
+
+ case OO_Minus: // '-' is either unary or binary
+ if (NumArgs == 1) {
+ OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
+ } else {
+ OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ }
+ break;
+
+ case OO_Star: // '*' is either unary or binary
+ if (NumArgs == 1)
+ OpBuilder.addUnaryStarPointerOverloads();
+ else
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
+
+ case OO_Slash:
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
+
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op);
+ OpBuilder.addPlusPlusMinusMinusPointerOverloads();
+ break;
+
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads();
+ // Fall through.
+
+ case OO_Less:
+ case OO_Greater:
+ case OO_LessEqual:
+ case OO_GreaterEqual:
+ OpBuilder.addRelationalPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true);
+ break;
+
+ case OO_Percent:
+ case OO_Caret:
+ case OO_Pipe:
+ case OO_LessLess:
+ case OO_GreaterGreater:
+ OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ break;
+
+ case OO_Amp: // '&' is either unary or binary
+ if (NumArgs == 1)
+ // C++ [over.match.oper]p3:
+ // -- For the operator ',', the unary operator '&', or the
+ // operator '->', the built-in candidates set is empty.
+ break;
+
+ OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ break;
+
+ case OO_Tilde:
+ OpBuilder.addUnaryTildePromotedIntegralOverloads();
+ break;
+
+ case OO_Equal:
+ OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
+ // Fall through.
+
+ case OO_PlusEqual:
+ case OO_MinusEqual:
+ OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
+ // Fall through.
+
+ case OO_StarEqual:
+ case OO_SlashEqual:
+ OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal);
+ break;
+
+ case OO_PercentEqual:
+ case OO_LessLessEqual:
+ case OO_GreaterGreaterEqual:
+ case OO_AmpEqual:
+ case OO_CaretEqual:
+ case OO_PipeEqual:
+ OpBuilder.addAssignmentIntegralOverloads();
+ break;
+
+ case OO_Exclaim:
+ OpBuilder.addExclaimOverload();
+ break;
+
+ case OO_AmpAmp:
+ case OO_PipePipe:
+ OpBuilder.addAmpAmpOrPipePipeOverload();
+ break;
+
+ case OO_Subscript:
+ OpBuilder.addSubscriptOverloads();
+ break;
+
+ case OO_ArrowStar:
+ OpBuilder.addArrowStarOverloads();
+ break;
+
+ case OO_Conditional:
+ OpBuilder.addConditionalOperatorOverloads();
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
+ }
+}
+
+/// \brief Add function candidates found via argument-dependent lookup
+/// to the set of overloading candidates.
+///
+/// This routine performs argument-dependent name lookup based on the
+/// given function name (which may also be an operator name) and adds
+/// all of the overload candidates found by ADL to the overload
+/// candidate set (C++ [basic.lookup.argdep]).
+void
+Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
+ bool Operator,
+ Expr **Args, unsigned NumArgs,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool PartialOverloading) {
+ ADLResult Fns;
+
+ // FIXME: This approach for uniquing ADL results (and removing
+ // redundant candidates from the set) relies on pointer-equality,
+ // which means we need to key off the canonical decl. However,
+ // always going back to the canonical decl might not get us the
+ // right set of default arguments. What default arguments are
+ // we supposed to consider on ADL candidates, anyway?
+
+ // FIXME: Pass in the explicit template arguments?
+ ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns);
+
+ // Erase all of the candidates we already knew about.
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+ CandEnd = CandidateSet.end();
+ Cand != CandEnd; ++Cand)
+ if (Cand->Function) {
+ Fns.erase(Cand->Function);
+ if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
+ Fns.erase(FunTmpl);
+ }
+
+ // For each of the ADL candidates we found, add it to the overload
+ // set.
+ for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+ DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ if (ExplicitTemplateArgs)
+ continue;
+
+ AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet,
+ false, PartialOverloading);
+ } else
+ AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
+ FoundDecl, ExplicitTemplateArgs,
+ Args, NumArgs, CandidateSet);
+ }
+}
+
+/// isBetterOverloadCandidate - Determines whether the first overload
+/// candidate is a better candidate than the second (C++ 13.3.3p1).
+bool
+isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2,
+ SourceLocation Loc,
+ bool UserDefinedConversion) {
+ // Define viable functions to be better candidates than non-viable
+ // functions.
+ if (!Cand2.Viable)
+ return Cand1.Viable;
+ else if (!Cand1.Viable)
+ return false;
+
+ // C++ [over.match.best]p1:
+ //
+ // -- if F is a static member function, ICS1(F) is defined such
+ // that ICS1(F) is neither better nor worse than ICS1(G) for
+ // any function G, and, symmetrically, ICS1(G) is neither
+ // better nor worse than ICS1(F).
+ unsigned StartArg = 0;
+ if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
+ StartArg = 1;
+
+ // C++ [over.match.best]p1:
+ // A viable function F1 is defined to be a better function than another
+ // viable function F2 if for all arguments i, ICSi(F1) is not a worse
+ // conversion sequence than ICSi(F2), and then...
+ unsigned NumArgs = Cand1.Conversions.size();
+ assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
+ bool HasBetterConversion = false;
+ for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
+ switch (CompareImplicitConversionSequences(S,
+ Cand1.Conversions[ArgIdx],
+ Cand2.Conversions[ArgIdx])) {
+ case ImplicitConversionSequence::Better:
+ // Cand1 has a better conversion sequence.
+ HasBetterConversion = true;
+ break;
+
+ case ImplicitConversionSequence::Worse:
+ // Cand1 can't be better than Cand2.
+ return false;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ // Do nothing.
+ break;
+ }
+ }
+
+ // -- for some argument j, ICSj(F1) is a better conversion sequence than
+ // ICSj(F2), or, if not that,
+ if (HasBetterConversion)
+ return true;
+
+ // - F1 is a non-template function and F2 is a function template
+ // specialization, or, if not that,
+ if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
+ Cand2.Function && Cand2.Function->getPrimaryTemplate())
+ return true;
+
+ // -- F1 and F2 are function template specializations, and the function
+ // template for F1 is more specialized than the template for F2
+ // according to the partial ordering rules described in 14.5.5.2, or,
+ // if not that,
+ if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
+ Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
+ if (FunctionTemplateDecl *BetterTemplate
+ = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+ Cand2.Function->getPrimaryTemplate(),
+ Loc,
+ isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
+ : TPOC_Call,
+ Cand1.ExplicitCallArguments))
+ return BetterTemplate == Cand1.Function->getPrimaryTemplate();
+ }
+
+ // -- the context is an initialization by user-defined conversion
+ // (see 8.5, 13.3.1.5) and the standard conversion sequence
+ // from the return type of F1 to the destination type (i.e.,
+ // the type of the entity being initialized) is a better
+ // conversion sequence than the standard conversion sequence
+ // from the return type of F2 to the destination type.
+ if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
+ isa<CXXConversionDecl>(Cand1.Function) &&
+ isa<CXXConversionDecl>(Cand2.Function)) {
+ switch (CompareStandardConversionSequences(S,
+ Cand1.FinalConversion,
+ Cand2.FinalConversion)) {
+ case ImplicitConversionSequence::Better:
+ // Cand1 has a better conversion sequence.
+ return true;
+
+ case ImplicitConversionSequence::Worse:
+ // Cand1 can't be better than Cand2.
+ return false;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ // Do nothing
+ break;
+ }
+ }
+
+ return false;
+}
+
+/// \brief Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param CandidateSet the set of candidate functions.
+///
+/// \param Loc the location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best f overload resolution was successful or found a deleted
+/// function, Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
+OverloadingResult
+OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
+ iterator &Best,
+ bool UserDefinedConversion) {
+ // Find the best viable function.
+ Best = end();
+ for (iterator Cand = begin(); Cand != end(); ++Cand) {
+ if (Cand->Viable)
+ if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
+ UserDefinedConversion))
+ Best = Cand;
+ }
+
+ // If we didn't find any viable functions, abort.
+ if (Best == end())
+ return OR_No_Viable_Function;
+
+ // Make sure that this function is better than every other viable
+ // function. If not, we have an ambiguity.
+ for (iterator Cand = begin(); Cand != end(); ++Cand) {
+ if (Cand->Viable &&
+ Cand != Best &&
+ !isBetterOverloadCandidate(S, *Best, *Cand, Loc,
+ UserDefinedConversion)) {
+ Best = end();
+ return OR_Ambiguous;
+ }
+ }
+
+ // Best is the best viable function.
+ if (Best->Function &&
+ (Best->Function->isDeleted() ||
+ Best->Function->getAttr<UnavailableAttr>()))
+ return OR_Deleted;
+
+ // C++ [basic.def.odr]p2:
+ // An overloaded function is used if it is selected by overload resolution
+ // when referred to from a potentially-evaluated expression. [Note: this
+ // covers calls to named functions (5.2.2), operator overloading
+ // (clause 13), user-defined conversions (12.3.2), allocation function for
+ // placement new (5.3.4), as well as non-default initialization (8.5).
+ if (Best->Function)
+ S.MarkDeclarationReferenced(Loc, Best->Function);
+
+ return OR_Success;
+}
+
+namespace {
+
+enum OverloadCandidateKind {
+ oc_function,
+ oc_method,
+ oc_constructor,
+ oc_function_template,
+ oc_method_template,
+ oc_constructor_template,
+ oc_implicit_default_constructor,
+ oc_implicit_copy_constructor,
+ oc_implicit_copy_assignment,
+ oc_implicit_inherited_constructor
+};
+
+OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
+ FunctionDecl *Fn,
+ std::string &Description) {
+ bool isTemplate = false;
+
+ if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
+ isTemplate = true;
+ Description = S.getTemplateArgumentBindingsText(
+ FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
+ }
+
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+ if (!Ctor->isImplicit())
+ return isTemplate ? oc_constructor_template : oc_constructor;
+
+ if (Ctor->getInheritedConstructor())
+ return oc_implicit_inherited_constructor;
+
+ return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor
+ : oc_implicit_default_constructor;
+ }
+
+ if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
+ // This actually gets spelled 'candidate function' for now, but
+ // it doesn't hurt to split it out.
+ if (!Meth->isImplicit())
+ return isTemplate ? oc_method_template : oc_method;
+
+ assert(Meth->isCopyAssignmentOperator()
+ && "implicit method is not copy assignment operator?");
+ return oc_implicit_copy_assignment;
+ }
+
+ return isTemplate ? oc_function_template : oc_function;
+}
+
+void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+ const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
+ if (!Ctor) return;
+
+ Ctor = Ctor->getInheritedConstructor();
+ if (!Ctor) return;
+
+ S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor);
+}
+
+} // end anonymous namespace
+
+// Notes the location of an overload candidate.
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
+ std::string FnDesc;
+ OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
+ Diag(Fn->getLocation(), diag::note_ovl_candidate)
+ << (unsigned) K << FnDesc;
+ MaybeEmitInheritedConstructorNote(*this, Fn);
+}
+
+//Notes the location of all overload candidates designated through
+// OverloadedExpr
+void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) {
+ assert(OverloadedExpr->getType() == Context.OverloadTy);
+
+ OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
+ OverloadExpr *OvlExpr = Ovl.Expression;
+
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ IEnd = OvlExpr->decls_end();
+ I != IEnd; ++I) {
+ if (FunctionTemplateDecl *FunTmpl =
+ dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
+ NoteOverloadCandidate(FunTmpl->getTemplatedDecl());
+ } else if (FunctionDecl *Fun
+ = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
+ NoteOverloadCandidate(Fun);
+ }
+ }
+}
+
+/// Diagnoses an ambiguous conversion. The partial diagnostic is the
+/// "lead" diagnostic; it will be given two arguments, the source and
+/// target types of the conversion.
+void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
+ Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const {
+ S.Diag(CaretLoc, PDiag)
+ << Ambiguous.getFromType() << Ambiguous.getToType();
+ for (AmbiguousConversionSequence::const_iterator
+ I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
+ S.NoteOverloadCandidate(*I);
+ }
+}
+
+namespace {
+
+void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
+ const ImplicitConversionSequence &Conv = Cand->Conversions[I];
+ assert(Conv.isBad());
+ assert(Cand->Function && "for now, candidate must be a function");
+ FunctionDecl *Fn = Cand->Function;
+
+ // There's a conversion slot for the object argument if this is a
+ // non-constructor method. Note that 'I' corresponds the
+ // conversion-slot index.
+ bool isObjectArgument = false;
+ if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) {
+ if (I == 0)
+ isObjectArgument = true;
+ else
+ I--;
+ }
+
+ std::string FnDesc;
+ OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+ Expr *FromExpr = Conv.Bad.FromExpr;
+ QualType FromTy = Conv.Bad.getFromType();
+ QualType ToTy = Conv.Bad.getToType();
+
+ if (FromTy == S.Context.OverloadTy) {
+ assert(FromExpr && "overload set argument came from implicit argument?");
+ Expr *E = FromExpr->IgnoreParens();
+ if (isa<UnaryOperator>(E))
+ E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ DeclarationName Name = cast<OverloadExpr>(E)->getName();
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << ToTy << Name << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // Do some hand-waving analysis to see if the non-viability is due
+ // to a qualifier mismatch.
+ CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
+ CanQualType CToTy = S.Context.getCanonicalType(ToTy);
+ if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
+ CToTy = RT->getPointeeType();
+ else {
+ // TODO: detect and diagnose the full richness of const mismatches.
+ if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
+ if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
+ CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+ }
+
+ if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
+ !CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
+ // It is dumb that we have to do this here.
+ while (isa<ArrayType>(CFromTy))
+ CFromTy = CFromTy->getAs<ArrayType>()->getElementType();
+ while (isa<ArrayType>(CToTy))
+ CToTy = CFromTy->getAs<ArrayType>()->getElementType();
+
+ Qualifiers FromQs = CFromTy.getQualifiers();
+ Qualifiers ToQs = CToTy.getQualifiers();
+
+ if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy
+ << FromQs.getAddressSpace() << ToQs.getAddressSpace()
+ << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+ assert(CVR && "unexpected qualifiers mismatch");
+
+ if (isObjectArgument) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << (CVR - 1);
+ } else {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << (CVR - 1) << I+1;
+ }
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // Diagnose references or pointers to incomplete types differently,
+ // since it's far from impossible that the incompleteness triggered
+ // the failure.
+ QualType TempFromTy = FromTy.getNonReferenceType();
+ if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
+ TempFromTy = PTy->getPointeeType();
+ if (TempFromTy->isIncompleteType()) {
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // Diagnose base -> derived pointer conversions.
+ unsigned BaseToDerivedConversion = 0;
+ if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) {
+ if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
+ if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+ FromPtrTy->getPointeeType()) &&
+ !FromPtrTy->getPointeeType()->isIncompleteType() &&
+ !ToPtrTy->getPointeeType()->isIncompleteType() &&
+ S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+ FromPtrTy->getPointeeType()))
+ BaseToDerivedConversion = 1;
+ }
+ } else if (const ObjCObjectPointerType *FromPtrTy
+ = FromTy->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *ToPtrTy
+ = ToTy->getAs<ObjCObjectPointerType>())
+ if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl())
+ if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl())
+ if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+ FromPtrTy->getPointeeType()) &&
+ FromIface->isSuperClassOf(ToIface))
+ BaseToDerivedConversion = 2;
+ } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) {
+ if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
+ !FromTy->isIncompleteType() &&
+ !ToRefTy->getPointeeType()->isIncompleteType() &&
+ S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy))
+ BaseToDerivedConversion = 3;
+ }
+
+ if (BaseToDerivedConversion) {
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_bad_base_to_derived_conv)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << (BaseToDerivedConversion - 1)
+ << FromTy << ToTy << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // TODO: specialize more based on the kind of mismatch
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+}
+
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumFormalArgs) {
+ // TODO: treat calls to a missing default constructor as a special case
+
+ FunctionDecl *Fn = Cand->Function;
+ const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+
+ unsigned MinParams = Fn->getMinRequiredArguments();
+
+ // at least / at most / exactly
+ unsigned mode, modeCount;
+ if (NumFormalArgs < MinParams) {
+ assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
+ (Cand->FailureKind == ovl_fail_bad_deduction &&
+ Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
+ if (MinParams != FnTy->getNumArgs() ||
+ FnTy->isVariadic() || FnTy->isTemplateVariadic())
+ mode = 0; // "at least"
+ else
+ mode = 2; // "exactly"
+ modeCount = MinParams;
+ } else {
+ assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
+ (Cand->FailureKind == ovl_fail_bad_deduction &&
+ Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
+ if (MinParams != FnTy->getNumArgs())
+ mode = 1; // "at most"
+ else
+ mode = 2; // "exactly"
+ modeCount = FnTy->getNumArgs();
+ }
+
+ std::string Description;
+ OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
+ << modeCount << NumFormalArgs;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+}
+
+/// Diagnose a failed template-argument deduction.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+ Expr **Args, unsigned NumArgs) {
+ FunctionDecl *Fn = Cand->Function; // pattern
+
+ TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
+ NamedDecl *ParamD;
+ (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+ (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+ (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+ switch (Cand->DeductionFailure.Result) {
+ case Sema::TDK_Success:
+ llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+ case Sema::TDK_Incomplete: {
+ assert(ParamD && "no parameter found for incomplete deduction result");
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
+ << ParamD->getDeclName();
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ case Sema::TDK_Underqualified: {
+ assert(ParamD && "no parameter found for bad qualifiers deduction result");
+ TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
+
+ QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+
+ // Param will have been canonicalized, but it should just be a
+ // qualified version of ParamD, so move the qualifiers to that.
+ QualifierCollector Qs;
+ Qs.strip(Param);
+ QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl());
+ assert(S.Context.hasSameType(Param, NonCanonParam));
+
+ // Arg has also been canonicalized, but there's nothing we can do
+ // about that. It also doesn't matter as much, because it won't
+ // have any template parameters in it (because deduction isn't
+ // done on dependent types).
+ QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
+ << ParamD->getDeclName() << Arg << NonCanonParam;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ case Sema::TDK_Inconsistent: {
+ assert(ParamD && "no parameter found for inconsistent deduction result");
+ int which = 0;
+ if (isa<TemplateTypeParmDecl>(ParamD))
+ which = 0;
+ else if (isa<NonTypeTemplateParmDecl>(ParamD))
+ which = 1;
+ else {
+ which = 2;
+ }
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
+ << which << ParamD->getDeclName()
+ << *Cand->DeductionFailure.getFirstArg()
+ << *Cand->DeductionFailure.getSecondArg();
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ case Sema::TDK_InvalidExplicitArguments:
+ assert(ParamD && "no parameter found for invalid explicit arguments");
+ if (ParamD->getDeclName())
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_explicit_arg_mismatch_named)
+ << ParamD->getDeclName();
+ else {
+ int index = 0;
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
+ index = TTP->getIndex();
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(ParamD))
+ index = NTTP->getIndex();
+ else
+ index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
+ << (index + 1);
+ }
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ DiagnoseArityMismatch(S, Cand, NumArgs);
+ return;
+
+ case Sema::TDK_InstantiationDepth:
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+
+ case Sema::TDK_SubstitutionFailure: {
+ std::string ArgString;
+ if (TemplateArgumentList *Args
+ = Cand->DeductionFailure.getTemplateArgumentList())
+ ArgString = S.getTemplateArgumentBindingsText(
+ Fn->getDescribedFunctionTemplate()->getTemplateParameters(),
+ *Args);
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
+ << ArgString;
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // TODO: diagnose these individually, then kill off
+ // note_ovl_candidate_bad_deduction, which is uselessly vague.
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_FailedOverloadResolution:
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+}
+
+/// Generates a 'note' diagnostic for an overload candidate. We've
+/// already generated a primary error at the call site.
+///
+/// It really does need to be a single diagnostic with its caret
+/// pointed at the candidate declaration. Yes, this creates some
+/// major challenges of technical writing. Yes, this makes pointing
+/// out problems with specific arguments quite awkward. It's still
+/// better than generating twenty screens of text for every failed
+/// overload.
+///
+/// It would be great to be able to express per-candidate problems
+/// more richly for those diagnostic clients that cared, but we'd
+/// still have to be just as careful with the default diagnostics.
+void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
+ Expr **Args, unsigned NumArgs) {
+ FunctionDecl *Fn = Cand->Function;
+
+ // Note deleted candidates, but only if they're viable.
+ if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+ std::string FnDesc;
+ OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
+ << FnKind << FnDesc << Fn->isDeleted();
+ MaybeEmitInheritedConstructorNote(S, Fn);
+ return;
+ }
+
+ // We don't really have anything else to say about viable candidates.
+ if (Cand->Viable) {
+ S.NoteOverloadCandidate(Fn);
+ return;
+ }
+
+ switch (Cand->FailureKind) {
+ case ovl_fail_too_many_arguments:
+ case ovl_fail_too_few_arguments:
+ return DiagnoseArityMismatch(S, Cand, NumArgs);
+
+ case ovl_fail_bad_deduction:
+ return DiagnoseBadDeduction(S, Cand, Args, NumArgs);
+
+ case ovl_fail_trivial_conversion:
+ case ovl_fail_bad_final_conversion:
+ case ovl_fail_final_conversion_not_exact:
+ return S.NoteOverloadCandidate(Fn);
+
+ case ovl_fail_bad_conversion: {
+ unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
+ for (unsigned N = Cand->Conversions.size(); I != N; ++I)
+ if (Cand->Conversions[I].isBad())
+ return DiagnoseBadConversion(S, Cand, I);
+
+ // FIXME: this currently happens when we're called from SemaInit
+ // when user-conversion overload fails. Figure out how to handle
+ // those conditions and diagnose them well.
+ return S.NoteOverloadCandidate(Fn);
+ }
+ }
+}
+
+void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+ // Desugar the type of the surrogate down to a function type,
+ // retaining as many typedefs as possible while still showing
+ // the function type (and, therefore, its parameter types).
+ QualType FnType = Cand->Surrogate->getConversionType();
+ bool isLValueReference = false;
+ bool isRValueReference = false;
+ bool isPointer = false;
+ if (const LValueReferenceType *FnTypeRef =
+ FnType->getAs<LValueReferenceType>()) {
+ FnType = FnTypeRef->getPointeeType();
+ isLValueReference = true;
+ } else if (const RValueReferenceType *FnTypeRef =
+ FnType->getAs<RValueReferenceType>()) {
+ FnType = FnTypeRef->getPointeeType();
+ isRValueReference = true;
+ }
+ if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
+ FnType = FnTypePtr->getPointeeType();
+ isPointer = true;
+ }
+ // Desugar down to a function type.
+ FnType = QualType(FnType->getAs<FunctionType>(), 0);
+ // Reconstruct the pointer/reference as appropriate.
+ if (isPointer) FnType = S.Context.getPointerType(FnType);
+ if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
+ if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
+
+ S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
+ << FnType;
+ MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
+}
+
+void NoteBuiltinOperatorCandidate(Sema &S,
+ const char *Opc,
+ SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
+ assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+ std::string TypeStr("operator");
+ TypeStr += Opc;
+ TypeStr += "(";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+ if (Cand->Conversions.size() == 1) {
+ TypeStr += ")";
+ S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
+ } else {
+ TypeStr += ", ";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+ TypeStr += ")";
+ S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
+ }
+}
+
+void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
+ unsigned NoOperands = Cand->Conversions.size();
+ for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+ const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
+ if (ICS.isBad()) break; // all meaningless after first invalid
+ if (!ICS.isAmbiguous()) continue;
+
+ ICS.DiagnoseAmbiguousConversion(S, OpLoc,
+ S.PDiag(diag::note_ambiguous_type_conversion));
+ }
+}
+
+SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+ if (Cand->Function)
+ return Cand->Function->getLocation();
+ if (Cand->IsSurrogate)
+ return Cand->Surrogate->getLocation();
+ return SourceLocation();
+}
+
+struct CompareOverloadCandidatesForDisplay {
+ Sema &S;
+ CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
+
+ bool operator()(const OverloadCandidate *L,
+ const OverloadCandidate *R) {
+ // Fast-path this check.
+ if (L == R) return false;
+
+ // Order first by viability.
+ if (L->Viable) {
+ if (!R->Viable) return true;
+
+ // TODO: introduce a tri-valued comparison for overload
+ // candidates. Would be more worthwhile if we had a sort
+ // that could exploit it.
+ if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true;
+ if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false;
+ } else if (R->Viable)
+ return false;
+
+ assert(L->Viable == R->Viable);
+
+ // Criteria by which we can sort non-viable candidates:
+ if (!L->Viable) {
+ // 1. Arity mismatches come after other candidates.
+ if (L->FailureKind == ovl_fail_too_many_arguments ||
+ L->FailureKind == ovl_fail_too_few_arguments)
+ return false;
+ if (R->FailureKind == ovl_fail_too_many_arguments ||
+ R->FailureKind == ovl_fail_too_few_arguments)
+ return true;
+
+ // 2. Bad conversions come first and are ordered by the number
+ // of bad conversions and quality of good conversions.
+ if (L->FailureKind == ovl_fail_bad_conversion) {
+ if (R->FailureKind != ovl_fail_bad_conversion)
+ return true;
+
+ // If there's any ordering between the defined conversions...
+ // FIXME: this might not be transitive.
+ assert(L->Conversions.size() == R->Conversions.size());
+
+ int leftBetter = 0;
+ unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
+ for (unsigned E = L->Conversions.size(); I != E; ++I) {
+ switch (CompareImplicitConversionSequences(S,
+ L->Conversions[I],
+ R->Conversions[I])) {
+ case ImplicitConversionSequence::Better:
+ leftBetter++;
+ break;
+
+ case ImplicitConversionSequence::Worse:
+ leftBetter--;
+ break;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ break;
+ }
+ }
+ if (leftBetter > 0) return true;
+ if (leftBetter < 0) return false;
+
+ } else if (R->FailureKind == ovl_fail_bad_conversion)
+ return false;
+
+ // TODO: others?
+ }
+
+ // Sort everything else by location.
+ SourceLocation LLoc = GetLocationForCandidate(L);
+ SourceLocation RLoc = GetLocationForCandidate(R);
+
+ // Put candidates without locations (e.g. builtins) at the end.
+ if (LLoc.isInvalid()) return false;
+ if (RLoc.isInvalid()) return true;
+
+ return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+ }
+};
+
+/// CompleteNonViableCandidate - Normally, overload resolution only
+/// computes up to the first
+void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
+ Expr **Args, unsigned NumArgs) {
+ assert(!Cand->Viable);
+
+ // Don't do anything on failures other than bad conversion.
+ if (Cand->FailureKind != ovl_fail_bad_conversion) return;
+
+ // Skip forward to the first bad conversion.
+ unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
+ unsigned ConvCount = Cand->Conversions.size();
+ while (true) {
+ assert(ConvIdx != ConvCount && "no bad conversion in candidate");
+ ConvIdx++;
+ if (Cand->Conversions[ConvIdx - 1].isBad())
+ break;
+ }
+
+ if (ConvIdx == ConvCount)
+ return;
+
+ assert(!Cand->Conversions[ConvIdx].isInitialized() &&
+ "remaining conversion is initialized?");
+
+ // FIXME: this should probably be preserved from the overload
+ // operation somehow.
+ bool SuppressUserConversions = false;
+
+ const FunctionProtoType* Proto;
+ unsigned ArgIdx = ConvIdx;
+
+ if (Cand->IsSurrogate) {
+ QualType ConvType
+ = Cand->Surrogate->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
+ Proto = ConvType->getAs<FunctionProtoType>();
+ ArgIdx--;
+ } else if (Cand->Function) {
+ Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
+ if (isa<CXXMethodDecl>(Cand->Function) &&
+ !isa<CXXConstructorDecl>(Cand->Function))
+ ArgIdx--;
+ } else {
+ // Builtin binary operator with a bad first conversion.
+ assert(ConvCount <= 3);
+ for (; ConvIdx != ConvCount; ++ConvIdx)
+ Cand->Conversions[ConvIdx]
+ = TryCopyInitialization(S, Args[ConvIdx],
+ Cand->BuiltinTypes.ParamTypes[ConvIdx],
+ SuppressUserConversions,
+ /*InOverloadResolution*/ true);
+ return;
+ }
+
+ // Fill in the rest of the conversions.
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
+ if (ArgIdx < NumArgsInProto)
+ Cand->Conversions[ConvIdx]
+ = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx),
+ SuppressUserConversions,
+ /*InOverloadResolution=*/true);
+ else
+ Cand->Conversions[ConvIdx].setEllipsis();
+ }
+}
+
+} // end anonymous namespace
+
+/// PrintOverloadCandidates - When overload resolution fails, prints
+/// diagnostic messages containing the candidates in the candidate
+/// set.
+void OverloadCandidateSet::NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ Expr **Args, unsigned NumArgs,
+ const char *Opc,
+ SourceLocation OpLoc) {
+ // Sort the candidates by viability and position. Sorting directly would
+ // be prohibitive, so we make a set of pointers and sort those.
+ llvm::SmallVector<OverloadCandidate*, 32> Cands;
+ if (OCD == OCD_AllCandidates) Cands.reserve(size());
+ for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+ if (Cand->Viable)
+ Cands.push_back(Cand);
+ else if (OCD == OCD_AllCandidates) {
+ CompleteNonViableCandidate(S, Cand, Args, NumArgs);
+ if (Cand->Function || Cand->IsSurrogate)
+ Cands.push_back(Cand);
+ // Otherwise, this a non-viable builtin candidate. We do not, in general,
+ // want to list every possible builtin candidate.
+ }
+ }
+
+ std::sort(Cands.begin(), Cands.end(),
+ CompareOverloadCandidatesForDisplay(S));
+
+ bool ReportedAmbiguousConversions = false;
+
+ llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
+ const Diagnostic::OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
+ unsigned CandsShown = 0;
+ for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+ OverloadCandidate *Cand = *I;
+
+ // Set an arbitrary limit on the number of candidate functions we'll spam
+ // the user with. FIXME: This limit should depend on details of the
+ // candidate list.
+ if (CandsShown >= 4 && ShowOverloads == Diagnostic::Ovl_Best) {
+ break;
+ }
+ ++CandsShown;
+
+ if (Cand->Function)
+ NoteFunctionCandidate(S, Cand, Args, NumArgs);
+ else if (Cand->IsSurrogate)
+ NoteSurrogateCandidate(S, Cand);
+ else {
+ assert(Cand->Viable &&
+ "Non-viable built-in candidates are not added to Cands.");
+ // Generally we only see ambiguities including viable builtin
+ // operators if overload resolution got screwed up by an
+ // ambiguous user-defined conversion.
+ //
+ // FIXME: It's quite possible for different conversions to see
+ // different ambiguities, though.
+ if (!ReportedAmbiguousConversions) {
+ NoteAmbiguousUserConversions(S, OpLoc, Cand);
+ ReportedAmbiguousConversions = true;
+ }
+
+ // If this is a viable builtin, print it.
+ NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand);
+ }
+ }
+
+ if (I != E)
+ S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
+}
+
+static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
+ if (isa<UnresolvedLookupExpr>(E))
+ return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D);
+
+ return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
+}
+
+
+
+
+// [PossiblyAFunctionType] --> [Return]
+// NonFunctionType --> NonFunctionType
+// R (A) --> R(A)
+// R (*)(A) --> R (A)
+// R (&)(A) --> R (A)
+// R (S::*)(A) --> R (A)
+QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
+ QualType Ret = PossiblyAFunctionType;
+ if (const PointerType *ToTypePtr =
+ PossiblyAFunctionType->getAs<PointerType>())
+ Ret = ToTypePtr->getPointeeType();
+ else if (const ReferenceType *ToTypeRef =
+ PossiblyAFunctionType->getAs<ReferenceType>())
+ Ret = ToTypeRef->getPointeeType();
+ else if (const MemberPointerType *MemTypePtr =
+ PossiblyAFunctionType->getAs<MemberPointerType>())
+ Ret = MemTypePtr->getPointeeType();
+ Ret =
+ Context.getCanonicalType(Ret).getUnqualifiedType();
+ return Ret;
+}
+
+// A helper class to help with address of function resolution
+// - allows us to avoid passing around all those ugly parameters
+class AddressOfFunctionResolver
+{
+ Sema& S;
+ Expr* SourceExpr;
+ const QualType& TargetType;
+ QualType TargetFunctionType; // Extracted function type from target type
+
+ bool Complain;
+ //DeclAccessPair& ResultFunctionAccessPair;
+ ASTContext& Context;
+
+ bool TargetTypeIsNonStaticMemberFunction;
+ bool FoundNonTemplateFunction;
+
+ OverloadExpr::FindResult OvlExprInfo;
+ OverloadExpr *OvlExpr;
+ TemplateArgumentListInfo OvlExplicitTemplateArgs;
+ llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+
+public:
+ AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
+ const QualType& TargetType, bool Complain)
+ : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
+ Complain(Complain), Context(S.getASTContext()),
+ TargetTypeIsNonStaticMemberFunction(
+ !!TargetType->getAs<MemberPointerType>()),
+ FoundNonTemplateFunction(false),
+ OvlExprInfo(OverloadExpr::find(SourceExpr)),
+ OvlExpr(OvlExprInfo.Expression)
+ {
+ ExtractUnqualifiedFunctionTypeFromTargetType();
+
+ if (!TargetFunctionType->isFunctionType()) {
+ if (OvlExpr->hasExplicitTemplateArgs()) {
+ DeclAccessPair dap;
+ if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+ OvlExpr, false, &dap) ) {
+ Matches.push_back(std::make_pair(dap,Fn));
+ }
+ }
+ return;
+ }
+
+ if (OvlExpr->hasExplicitTemplateArgs())
+ OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
+
+ if (FindAllFunctionsThatMatchTargetTypeExactly()) {
+ // C++ [over.over]p4:
+ // If more than one function is selected, [...]
+ if (Matches.size() > 1) {
+ if (FoundNonTemplateFunction)
+ EliminateAllTemplateMatches();
+ else
+ EliminateAllExceptMostSpecializedTemplate();
+ }
+ }
+ }
+
+private:
+ bool isTargetTypeAFunction() const {
+ return TargetFunctionType->isFunctionType();
+ }
+
+ // [ToType] [Return]
+
+ // R (*)(A) --> R (A), IsNonStaticMemberFunction = false
+ // R (&)(A) --> R (A), IsNonStaticMemberFunction = false
+ // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true
+ void inline ExtractUnqualifiedFunctionTypeFromTargetType() {
+ TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType);
+ }
+
+ // return true if any matching specializations were found
+ bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate,
+ const DeclAccessPair& CurAccessFunPair) {
+ if (CXXMethodDecl *Method
+ = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
+ // Skip non-static function templates when converting to pointer, and
+ // static when converting to member pointer.
+ if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+ return false;
+ }
+ else if (TargetTypeIsNonStaticMemberFunction)
+ return false;
+
+ // C++ [over.over]p2:
+ // If the name is a function template, template argument deduction is
+ // done (14.8.2.2), and if the argument deduction succeeds, the
+ // resulting template argument list is used to generate a single
+ // function template specialization, which is added to the set of
+ // overloaded functions considered.
+ FunctionDecl *Specialization = 0;
+ TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+ if (Sema::TemplateDeductionResult Result
+ = S.DeduceTemplateArguments(FunctionTemplate,
+ &OvlExplicitTemplateArgs,
+ TargetFunctionType, Specialization,
+ Info)) {
+ // FIXME: make a note of the failed deduction for diagnostics.
+ (void)Result;
+ return false;
+ }
+
+ // Template argument deduction ensures that we have an exact match.
+ // This function template specicalization works.
+ Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
+ assert(TargetFunctionType
+ == Context.getCanonicalType(Specialization->getType()));
+ Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
+ return true;
+ }
+
+ bool AddMatchingNonTemplateFunction(NamedDecl* Fn,
+ const DeclAccessPair& CurAccessFunPair) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+ // Skip non-static functions when converting to pointer, and static
+ // when converting to member pointer.
+ if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+ return false;
+ }
+ else if (TargetTypeIsNonStaticMemberFunction)
+ return false;
+
+ if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
+ QualType ResultTy;
+ if (Context.hasSameUnqualifiedType(TargetFunctionType,
+ FunDecl->getType()) ||
+ IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType,
+ ResultTy)) {
+ Matches.push_back(std::make_pair(CurAccessFunPair,
+ cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+ FoundNonTemplateFunction = true;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool FindAllFunctionsThatMatchTargetTypeExactly() {
+ bool Ret = false;
+
+ // If the overload expression doesn't have the form of a pointer to
+ // member, don't try to convert it to a pointer-to-member type.
+ if (IsInvalidFormOfPointerToMemberFunction())
+ return false;
+
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ E = OvlExpr->decls_end();
+ I != E; ++I) {
+ // Look through any using declarations to find the underlying function.
+ NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+ // C++ [over.over]p3:
+ // Non-member functions and static member functions match
+ // targets of type "pointer-to-function" or "reference-to-function."
+ // Nonstatic member functions match targets of
+ // type "pointer-to-member-function."
+ // Note that according to DR 247, the containing class does not matter.
+ if (FunctionTemplateDecl *FunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(Fn)) {
+ if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair()))
+ Ret = true;
+ }
+ // If we have explicit template arguments supplied, skip non-templates.
+ else if (!OvlExpr->hasExplicitTemplateArgs() &&
+ AddMatchingNonTemplateFunction(Fn, I.getPair()))
+ Ret = true;
+ }
+ assert(Ret || Matches.empty());
+ return Ret;
+ }
+
+ void EliminateAllExceptMostSpecializedTemplate() {
+ // [...] and any given function template specialization F1 is
+ // eliminated if the set contains a second function template
+ // specialization whose function template is more specialized
+ // than the function template of F1 according to the partial
+ // ordering rules of 14.5.5.2.
+
+ // The algorithm specified above is quadratic. We instead use a
+ // two-pass algorithm (similar to the one used to identify the
+ // best viable function in an overload set) that identifies the
+ // best function template (if it exists).
+
+ UnresolvedSet<4> MatchesCopy; // TODO: avoid!
+ for (unsigned I = 0, E = Matches.size(); I != E; ++I)
+ MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
+
+ UnresolvedSetIterator Result =
+ S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
+ TPOC_Other, 0, SourceExpr->getLocStart(),
+ S.PDiag(),
+ S.PDiag(diag::err_addr_ovl_ambiguous)
+ << Matches[0].second->getDeclName(),
+ S.PDiag(diag::note_ovl_candidate)
+ << (unsigned) oc_function_template,
+ Complain);
+
+ if (Result != MatchesCopy.end()) {
+ // Make it the first and only element
+ Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
+ Matches[0].second = cast<FunctionDecl>(*Result);
+ Matches.resize(1);
+ }
+ }
+
+ void EliminateAllTemplateMatches() {
+ // [...] any function template specializations in the set are
+ // eliminated if the set also contains a non-template function, [...]
+ for (unsigned I = 0, N = Matches.size(); I != N; ) {
+ if (Matches[I].second->getPrimaryTemplate() == 0)
+ ++I;
+ else {
+ Matches[I] = Matches[--N];
+ Matches.set_size(N);
+ }
+ }
+ }
+
+public:
+ void ComplainNoMatchesFound() const {
+ assert(Matches.empty());
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
+ << OvlExpr->getName() << TargetFunctionType
+ << OvlExpr->getSourceRange();
+ S.NoteAllOverloadCandidates(OvlExpr);
+ }
+
+ bool IsInvalidFormOfPointerToMemberFunction() const {
+ return TargetTypeIsNonStaticMemberFunction &&
+ !OvlExprInfo.HasFormOfMemberPointer;
+ }
+
+ void ComplainIsInvalidFormOfPointerToMemberFunction() const {
+ // TODO: Should we condition this on whether any functions might
+ // have matched, or is it more appropriate to do that in callers?
+ // TODO: a fixit wouldn't hurt.
+ S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
+ << TargetType << OvlExpr->getSourceRange();
+ }
+
+ void ComplainOfInvalidConversion() const {
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
+ << OvlExpr->getName() << TargetType;
+ }
+
+ void ComplainMultipleMatchesFound() const {
+ assert(Matches.size() > 1);
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
+ << OvlExpr->getName()
+ << OvlExpr->getSourceRange();
+ S.NoteAllOverloadCandidates(OvlExpr);
+ }
+
+ int getNumMatches() const { return Matches.size(); }
+
+ FunctionDecl* getMatchingFunctionDecl() const {
+ if (Matches.size() != 1) return 0;
+ return Matches[0].second;
+ }
+
+ const DeclAccessPair* getMatchingFunctionAccessPair() const {
+ if (Matches.size() != 1) return 0;
+ return &Matches[0].first;
+ }
+};
+
+/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
+/// an overloaded function (C++ [over.over]), where @p From is an
+/// expression with overloaded function type and @p ToType is the type
+/// we're trying to resolve to. For example:
+///
+/// @code
+/// int f(double);
+/// int f(int);
+///
+/// int (*pfd)(double) = f; // selects f(double)
+/// @endcode
+///
+/// This routine returns the resulting FunctionDecl if it could be
+/// resolved, and NULL otherwise. When @p Complain is true, this
+/// routine will emit diagnostics if there is an error.
+FunctionDecl *
+Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+ bool Complain,
+ DeclAccessPair &FoundResult) {
+
+ assert(AddressOfExpr->getType() == Context.OverloadTy);
+
+ AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, Complain);
+ int NumMatches = Resolver.getNumMatches();
+ FunctionDecl* Fn = 0;
+ if ( NumMatches == 0 && Complain) {
+ if (Resolver.IsInvalidFormOfPointerToMemberFunction())
+ Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
+ else
+ Resolver.ComplainNoMatchesFound();
+ }
+ else if (NumMatches > 1 && Complain)
+ Resolver.ComplainMultipleMatchesFound();
+ else if (NumMatches == 1) {
+ Fn = Resolver.getMatchingFunctionDecl();
+ assert(Fn);
+ FoundResult = *Resolver.getMatchingFunctionAccessPair();
+ MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn);
+ if (Complain)
+ CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+ }
+
+ return Fn;
+}
+
+/// \brief Given an expression that refers to an overloaded function, try to
+/// resolve that overloaded function expression down to a single function.
+///
+/// This routine can only resolve template-ids that refer to a single function
+/// template, where that template-id refers to a single template whose template
+/// arguments are either provided by the template-id or have defaults,
+/// as described in C++0x [temp.arg.explicit]p3.
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
+ bool Complain,
+ DeclAccessPair* FoundResult) {
+ // C++ [over.over]p1:
+ // [...] [Note: any redundant set of parentheses surrounding the
+ // overloaded function name is ignored (5.1). ]
+ // C++ [over.over]p1:
+ // [...] The overloaded function name can be preceded by the &
+ // operator.
+ if (From->getType() != Context.OverloadTy)
+ return 0;
+
+ OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
+
+ // If we didn't actually find any template-ids, we're done.
+ if (!OvlExpr->hasExplicitTemplateArgs())
+ return 0;
+
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+ OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+
+ // Look through all of the overloaded functions, searching for one
+ // whose type matches exactly.
+ FunctionDecl *Matched = 0;
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ E = OvlExpr->decls_end(); I != E; ++I) {
+ // C++0x [temp.arg.explicit]p3:
+ // [...] In contexts where deduction is done and fails, or in contexts
+ // where deduction is not done, if a template argument list is
+ // specified and it, along with any default template arguments,
+ // identifies a single function template specialization, then the
+ // template-id is an lvalue for the function template specialization.
+ FunctionTemplateDecl *FunctionTemplate
+ = cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
+
+ // C++ [over.over]p2:
+ // If the name is a function template, template argument deduction is
+ // done (14.8.2.2), and if the argument deduction succeeds, the
+ // resulting template argument list is used to generate a single
+ // function template specialization, which is added to the set of
+ // overloaded functions considered.
+ FunctionDecl *Specialization = 0;
+ TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
+ Specialization, Info)) {
+ // FIXME: make a note of the failed deduction for diagnostics.
+ (void)Result;
+ continue;
+ }
+
+ // Multiple matches; we can't resolve to a single declaration.
+ if (Matched) {
+ if (FoundResult)
+ *FoundResult = DeclAccessPair();
+
+ if (Complain) {
+ Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
+ << OvlExpr->getName();
+ NoteAllOverloadCandidates(OvlExpr);
+ }
+ return 0;
+ }
+
+ if ((Matched = Specialization) && FoundResult)
+ *FoundResult = I.getPair();
+ }
+
+ return Matched;
+}
+
+/// \brief Add a single candidate to the overload set.
+static void AddOverloadedCallCandidate(Sema &S,
+ DeclAccessPair FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading) {
+ NamedDecl *Callee = FoundDecl.getDecl();
+ if (isa<UsingShadowDecl>(Callee))
+ Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
+
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
+ assert(!ExplicitTemplateArgs && "Explicit template arguments?");
+ S.AddOverloadCandidate(Func, FoundDecl, Args, NumArgs, CandidateSet,
+ false, PartialOverloading);
+ return;
+ }
+
+ if (FunctionTemplateDecl *FuncTemplate
+ = dyn_cast<FunctionTemplateDecl>(Callee)) {
+ S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
+ ExplicitTemplateArgs,
+ Args, NumArgs, CandidateSet);
+ return;
+ }
+
+ assert(false && "unhandled case in overloaded call candidate");
+
+ // do nothing?
+}
+
+/// \brief Add the overload candidates named by callee and/or found by argument
+/// dependent lookup to the given overload set.
+void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading) {
+
+#ifndef NDEBUG
+ // Verify that ArgumentDependentLookup is consistent with the rules
+ // in C++0x [basic.lookup.argdep]p3:
+ //
+ // Let X be the lookup set produced by unqualified lookup (3.4.1)
+ // and let Y be the lookup set produced by argument dependent
+ // lookup (defined as follows). If X contains
+ //
+ // -- a declaration of a class member, or
+ //
+ // -- a block-scope function declaration that is not a
+ // using-declaration, or
+ //
+ // -- a declaration that is neither a function or a function
+ // template
+ //
+ // then Y is empty.
+
+ if (ULE->requiresADL()) {
+ for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+ E = ULE->decls_end(); I != E; ++I) {
+ assert(!(*I)->getDeclContext()->isRecord());
+ assert(isa<UsingShadowDecl>(*I) ||
+ !(*I)->getDeclContext()->isFunctionOrMethod());
+ assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
+ }
+ }
+#endif
+
+ // It would be nice to avoid this copy.
+ TemplateArgumentListInfo TABuffer;
+ const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ if (ULE->hasExplicitTemplateArgs()) {
+ ULE->copyTemplateArgumentsInto(TABuffer);
+ ExplicitTemplateArgs = &TABuffer;
+ }
+
+ for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
+ E = ULE->decls_end(); I != E; ++I)
+ AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs,
+ Args, NumArgs, CandidateSet,
+ PartialOverloading);
+
+ if (ULE->requiresADL())
+ AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
+ Args, NumArgs,
+ ExplicitTemplateArgs,
+ CandidateSet,
+ PartialOverloading);
+}
+
+/// Attempts to recover from a call where no functions were found.
+///
+/// Returns true if new candidates were found.
+static ExprResult
+BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc) {
+
+ CXXScopeSpec SS;
+ if (ULE->getQualifier()) {
+ SS.setScopeRep(ULE->getQualifier());
+ SS.setRange(ULE->getQualifierRange());
+ }
+
+ TemplateArgumentListInfo TABuffer;
+ const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
+ if (ULE->hasExplicitTemplateArgs()) {
+ ULE->copyTemplateArgumentsInto(TABuffer);
+ ExplicitTemplateArgs = &TABuffer;
+ }
+
+ LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
+ Sema::LookupOrdinaryName);
+ if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression))
+ return ExprError();
+
+ assert(!R.empty() && "lookup results empty despite recovery");
+
+ // Build an implicit member call if appropriate. Just drop the
+ // casts and such from the call, we don't really care.
+ ExprResult NewFn = ExprError();
+ if ((*R.begin())->isCXXClassMember())
+ NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R,
+ ExplicitTemplateArgs);
+ else if (ExplicitTemplateArgs)
+ NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs);
+ else
+ NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
+
+ if (NewFn.isInvalid())
+ return ExprError();
+
+ // This shouldn't cause an infinite loop because we're giving it
+ // an expression with non-empty lookup results, which should never
+ // end up here.
+ return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
+ MultiExprArg(Args, NumArgs), RParenLoc);
+}
+
+/// ResolveOverloadedCallFn - Given the call expression that calls Fn
+/// (which eventually refers to the declaration Func) and the call
+/// arguments Args/NumArgs, attempt to resolve the function call down
+/// to a specific function. If overload resolution succeeds, returns
+/// the function declaration produced by overload
+/// resolution. Otherwise, emits diagnostics, deletes all of the
+/// arguments and Fn, and returns NULL.
+ExprResult
+Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig) {
+#ifndef NDEBUG
+ if (ULE->requiresADL()) {
+ // To do ADL, we must have found an unqualified name.
+ assert(!ULE->getQualifier() && "qualified name with ADL");
+
+ // We don't perform ADL for implicit declarations of builtins.
+ // Verify that this was correctly set up.
+ FunctionDecl *F;
+ if (ULE->decls_begin() + 1 == ULE->decls_end() &&
+ (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
+ F->getBuiltinID() && F->isImplicit())
+ assert(0 && "performing ADL for builtin");
+
+ // We don't perform ADL in C.
+ assert(getLangOptions().CPlusPlus && "ADL enabled in C");
+ }
+#endif
+
+ OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+
+ // Add the functions denoted by the callee to the set of candidate
+ // functions, including those from argument-dependent lookup.
+ AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet);
+
+ // If we found nothing, try to recover.
+ // AddRecoveryCallCandidates diagnoses the error itself, so we just
+ // bailout out if it fails.
+ if (CandidateSet.empty())
+ return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs,
+ RParenLoc);
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
+ case OR_Success: {
+ FunctionDecl *FDecl = Best->Function;
+ CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
+ DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(),
+ ULE->getNameLoc());
+ Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
+ return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc,
+ ExecConfig);
+ }
+
+ case OR_No_Viable_Function:
+ Diag(Fn->getSourceRange().getBegin(),
+ diag::err_ovl_no_viable_function_in_call)
+ << ULE->getName() << Fn->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ break;
+
+ case OR_Ambiguous:
+ Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
+ << ULE->getName() << Fn->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
+ break;
+
+ case OR_Deleted:
+ Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted()
+ << ULE->getName()
+ << Fn->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ break;
+ }
+
+ // Overload resolution failed.
+ return ExprError();
+}
+
+static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
+ return Functions.size() > 1 ||
+ (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
+}
+
+/// \brief Create a unary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '*').
+///
+/// \param OpcIn The UnaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedUnaryOp().
+///
+/// \param input The input argument.
+ExprResult
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+ const UnresolvedSetImpl &Fns,
+ Expr *Input) {
+ UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
+
+ OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
+ assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+ // TODO: provide better source location info.
+ DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+
+ if (Input->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Input);
+
+ Expr *Args[2] = { Input, 0 };
+ unsigned NumArgs = 1;
+
+ // For post-increment and post-decrement, add the implicit '0' as
+ // the second argument, so that we know this is a post-increment or
+ // post-decrement.
+ if (Opc == UO_PostInc || Opc == UO_PostDec) {
+ llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
+ Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy,
+ SourceLocation());
+ NumArgs = 2;
+ }
+
+ if (Input->isTypeDependent()) {
+ if (Fns.empty())
+ return Owned(new (Context) UnaryOperator(Input,
+ Opc,
+ Context.DependentTy,
+ VK_RValue, OK_Ordinary,
+ OpLoc));
+
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, NamingClass,
+ 0, SourceRange(), OpNameInfo,
+ /*ADL*/ true, IsOverloaded(Fns),
+ Fns.begin(), Fns.end());
+ return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+ &Args[0], NumArgs,
+ Context.DependentTy,
+ VK_RValue,
+ OpLoc));
+ }
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet(OpLoc);
+
+ // Add the candidates from the given function set.
+ AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false);
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+ // Add candidates from ADL.
+ AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+ Args, NumArgs,
+ /*ExplicitTemplateArgs*/ 0,
+ CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ // Convert the arguments.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
+
+ if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+ Best->FoundDecl, Method))
+ return ExprError();
+ } else {
+ // Convert the arguments.
+ ExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ Input);
+ if (InputInit.isInvalid())
+ return ExprError();
+ Input = InputInit.take();
+ }
+
+ DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
+ // Build the actual expression node.
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl);
+
+ Args[0] = Input;
+ CallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+ Args, NumArgs, ResultTy, VK, OpLoc);
+
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall);
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function:
+ // No viable function; fall through to handling this as a
+ // built-in operator, which will produce an error message for us.
+ break;
+
+ case OR_Ambiguous:
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
+ << UnaryOperator::getOpcodeStr(Opc)
+ << Input->getType()
+ << Input->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+ Args, NumArgs,
+ UnaryOperator::getOpcodeStr(Opc), OpLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(OpLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted()
+ << UnaryOperator::getOpcodeStr(Opc)
+ << Input->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ return ExprError();
+ }
+
+ // Either we found no viable overloaded operator or we matched a
+ // built-in operator. In either case, fall through to trying to
+ // build a built-in operation.
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
+}
+
+/// \brief Create a binary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '+').
+///
+/// \param OpcIn The BinaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedBinOp().
+///
+/// \param LHS Left-hand argument.
+/// \param RHS Right-hand argument.
+ExprResult
+Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
+ unsigned OpcIn,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS) {
+ Expr *Args[2] = { LHS, RHS };
+ LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
+
+ BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
+ OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+ // If either side is type-dependent, create an appropriate dependent
+ // expression.
+ if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+ if (Fns.empty()) {
+ // If there are no functions to store, just build a dependent
+ // BinaryOperator or CompoundAssignment.
+ if (Opc <= BO_Assign || Opc > BO_OrAssign)
+ return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+ Context.DependentTy,
+ VK_RValue, OK_Ordinary,
+ OpLoc));
+
+ return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+ Context.DependentTy,
+ VK_LValue,
+ OK_Ordinary,
+ Context.DependentTy,
+ Context.DependentTy,
+ OpLoc));
+ }
+
+ // FIXME: save results of ADL from here?
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ // TODO: provide better source location info in DNLoc component.
+ DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(),
+ OpNameInfo, /*ADL*/ true, IsOverloaded(Fns),
+ Fns.begin(), Fns.end());
+ return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+ Args, 2,
+ Context.DependentTy,
+ VK_RValue,
+ OpLoc));
+ }
+
+ // Always do property rvalue conversions on the RHS.
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
+ // The LHS is more complicated.
+ if (Args[0]->getObjectKind() == OK_ObjCProperty) {
+
+ // There's a tension for assignment operators between primitive
+ // property assignment and the overloaded operators.
+ if (BinaryOperator::isAssignmentOp(Opc)) {
+ const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
+
+ // Is the property "logically" settable?
+ bool Settable = (PRE->isExplicitProperty() ||
+ PRE->getImplicitPropertySetter());
+
+ // To avoid gratuitously inventing semantics, use the primitive
+ // unless it isn't. Thoughts in case we ever really care:
+ // - If the property isn't logically settable, we have to
+ // load and hope.
+ // - If the property is settable and this is simple assignment,
+ // we really should use the primitive.
+ // - If the property is settable, then we could try overloading
+ // on a generic lvalue of the appropriate type; if it works
+ // out to a builtin candidate, we would do that same operation
+ // on the property, and otherwise just error.
+ if (Settable)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ }
+
+ ConvertPropertyForRValue(Args[0]);
+ }
+
+ // If this is the assignment operator, we only perform overload resolution
+ // if the left-hand side is a class or enumeration type. This is actually
+ // a hack. The standard requires that we do overload resolution between the
+ // various built-in candidates, but as DR507 points out, this can lead to
+ // problems. So we do it this way, which pretty much follows what GCC does.
+ // Note that we go the traditional code path for compound assignment forms.
+ if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+ // If this is the .* operator, which is not overloadable, just
+ // create a built-in binary operator.
+ if (Opc == BO_PtrMemD)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet(OpLoc);
+
+ // Add the candidates from the given function set.
+ AddFunctionCandidates(Fns, Args, 2, CandidateSet, false);
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+ // Add candidates from ADL.
+ AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+ Args, 2,
+ /*ExplicitTemplateArgs*/ 0,
+ CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ // Convert the arguments.
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ // Best->Access is only meaningful for class members.
+ CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
+
+ ExprResult Arg1 =
+ PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(), Owned(Args[1]));
+ if (Arg1.isInvalid())
+ return ExprError();
+
+ if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ Best->FoundDecl, Method))
+ return ExprError();
+
+ Args[1] = RHS = Arg1.takeAs<Expr>();
+ } else {
+ // Convert the arguments.
+ ExprResult Arg0 = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(), Owned(Args[0]));
+ if (Arg0.isInvalid())
+ return ExprError();
+
+ ExprResult Arg1 =
+ PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(1)),
+ SourceLocation(), Owned(Args[1]));
+ if (Arg1.isInvalid())
+ return ExprError();
+ Args[0] = LHS = Arg0.takeAs<Expr>();
+ Args[1] = RHS = Arg1.takeAs<Expr>();
+ }
+
+ DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
+ // Build the actual expression node.
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc);
+
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+ Args, 2, ResultTy, VK, OpLoc);
+
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall);
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing) ||
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], AA_Passing))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function: {
+ // C++ [over.match.oper]p9:
+ // If the operator is the operator , [...] and there are no
+ // viable functions, then the operator is assumed to be the
+ // built-in operator and interpreted according to clause 5.
+ if (Opc == BO_Comma)
+ break;
+
+ // For class as left operand for assignment or compound assigment
+ // operator do not fall through to handling in built-in, but report that
+ // no overloaded assignment operator found
+ ExprResult Result = ExprError();
+ if (Args[0]->getType()->isRecordType() &&
+ Opc >= BO_Assign && Opc <= BO_OrAssign) {
+ Diag(OpLoc, diag::err_ovl_no_viable_oper)
+ << BinaryOperator::getOpcodeStr(Opc)
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ } else {
+ // No viable function; try to create a built-in operation, which will
+ // produce an error. Then, show the non-viable candidates.
+ Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ }
+ assert(Result.isInvalid() &&
+ "C++ binary operator overloading is missing candidates!");
+ if (Result.isInvalid())
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
+ return move(Result);
+ }
+
+ case OR_Ambiguous:
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary)
+ << BinaryOperator::getOpcodeStr(Opc)
+ << Args[0]->getType() << Args[1]->getType()
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(OpLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted()
+ << BinaryOperator::getOpcodeStr(Opc)
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
+ return ExprError();
+ }
+
+ // We matched a built-in operator; build it.
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+}
+
+ExprResult
+Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ Expr *Base, Expr *Idx) {
+ Expr *Args[2] = { Base, Idx };
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
+
+ // If either side is type-dependent, create an appropriate dependent
+ // expression.
+ if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ // CHECKME: no 'operator' keyword?
+ DeclarationNameInfo OpNameInfo(OpName, LLoc);
+ OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
+ UnresolvedLookupExpr *Fn
+ = UnresolvedLookupExpr::Create(Context, NamingClass,
+ 0, SourceRange(), OpNameInfo,
+ /*ADL*/ true, /*Overloaded*/ false,
+ UnresolvedSetIterator(),
+ UnresolvedSetIterator());
+ // Can't add any actual overloads yet
+
+ return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
+ Args, 2,
+ Context.DependentTy,
+ VK_RValue,
+ RLoc));
+ }
+
+ if (Args[0]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[0]);
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
+ // Build an empty overload set.
+ OverloadCandidateSet CandidateSet(LLoc);
+
+ // Subscript can only be overloaded as a member function.
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Add builtin operator candidates.
+ AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet);
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) {
+ case OR_Success: {
+ // We found a built-in operator or an overloaded operator.
+ FunctionDecl *FnDecl = Best->Function;
+
+ if (FnDecl) {
+ // We matched an overloaded operator. Build a call to that
+ // operator.
+
+ CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
+ DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
+
+ // Convert the arguments.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+ if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ Best->FoundDecl, Method))
+ return ExprError();
+
+ // Convert the arguments.
+ ExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ Owned(Args[1]));
+ if (InputInit.isInvalid())
+ return ExprError();
+
+ Args[1] = InputInit.takeAs<Expr>();
+
+ // Determine the result type
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
+ // Build the actual expression node.
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc);
+
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+ FnExpr, Args, 2,
+ ResultTy, VK, RLoc);
+
+ if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
+ FnDecl))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall);
+ } else {
+ // We matched a built-in operator. Convert the arguments, then
+ // break out so that we will build the appropriate built-in
+ // operator node.
+ if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
+ Best->Conversions[0], AA_Passing) ||
+ PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
+ Best->Conversions[1], AA_Passing))
+ return ExprError();
+
+ break;
+ }
+ }
+
+ case OR_No_Viable_Function: {
+ if (CandidateSet.empty())
+ Diag(LLoc, diag::err_ovl_no_oper)
+ << Args[0]->getType() << /*subscript*/ 0
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ else
+ Diag(LLoc, diag::err_ovl_no_viable_subscript)
+ << Args[0]->getType()
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ "[]", LLoc);
+ return ExprError();
+ }
+
+ case OR_Ambiguous:
+ Diag(LLoc, diag::err_ovl_ambiguous_oper_binary)
+ << "[]"
+ << Args[0]->getType() << Args[1]->getType()
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
+ "[]", LLoc);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(LLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted() << "[]"
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ "[]", LLoc);
+ return ExprError();
+ }
+
+ // We matched a built-in operator; build it.
+ return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc);
+}
+
+/// BuildCallToMemberFunction - Build a call to a member
+/// function. MemExpr is the expression that refers to the member
+/// function (and includes the object parameter), Args/NumArgs are the
+/// arguments to the function call (not including the object
+/// parameter). The caller needs to validate that the member
+/// expression refers to a member function or an overloaded member
+/// function.
+ExprResult
+Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
+ SourceLocation LParenLoc, Expr **Args,
+ unsigned NumArgs, SourceLocation RParenLoc) {
+ // Dig out the member expression. This holds both the object
+ // argument and the member function we're referring to.
+ Expr *NakedMemExpr = MemExprE->IgnoreParens();
+
+ MemberExpr *MemExpr;
+ CXXMethodDecl *Method = 0;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
+ NestedNameSpecifier *Qualifier = 0;
+ if (isa<MemberExpr>(NakedMemExpr)) {
+ MemExpr = cast<MemberExpr>(NakedMemExpr);
+ Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+ FoundDecl = MemExpr->getFoundDecl();
+ Qualifier = MemExpr->getQualifier();
+ } else {
+ UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
+ Qualifier = UnresExpr->getQualifier();
+
+ QualType ObjectType = UnresExpr->getBaseType();
+ Expr::Classification ObjectClassification
+ = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue()
+ : UnresExpr->getBase()->Classify(Context);
+
+ // Add overload candidates
+ OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
+
+ // FIXME: avoid copy.
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ if (UnresExpr->hasExplicitTemplateArgs()) {
+ UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+ TemplateArgs = &TemplateArgsBuffer;
+ }
+
+ for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
+ E = UnresExpr->decls_end(); I != E; ++I) {
+
+ NamedDecl *Func = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext());
+ if (isa<UsingShadowDecl>(Func))
+ Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
+
+
+ // Microsoft supports direct constructor calls.
+ if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) {
+ AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs,
+ CandidateSet);
+ } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
+ // If explicit template arguments were provided, we can't call a
+ // non-template member function.
+ if (TemplateArgs)
+ continue;
+
+ AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
+ ObjectClassification,
+ Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions=*/false);
+ } else {
+ AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
+ I.getPair(), ActingDC, TemplateArgs,
+ ObjectType, ObjectClassification,
+ Args, NumArgs, CandidateSet,
+ /*SuppressUsedConversions=*/false);
+ }
+ }
+
+ DeclarationName DeclName = UnresExpr->getMemberName();
+
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
+ Best)) {
+ case OR_Success:
+ Method = cast<CXXMethodDecl>(Best->Function);
+ FoundDecl = Best->FoundDecl;
+ CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
+ DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
+ break;
+
+ case OR_No_Viable_Function:
+ Diag(UnresExpr->getMemberLoc(),
+ diag::err_ovl_no_viable_member_function_in_call)
+ << DeclName << MemExprE->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ // FIXME: Leaking incoming expressions!
+ return ExprError();
+
+ case OR_Ambiguous:
+ Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
+ << DeclName << MemExprE->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ // FIXME: Leaking incoming expressions!
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
+ << Best->Function->isDeleted()
+ << DeclName << MemExprE->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ // FIXME: Leaking incoming expressions!
+ return ExprError();
+ }
+
+ MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
+
+ // If overload resolution picked a static member, build a
+ // non-member call based on that function.
+ if (Method->isStatic()) {
+ return BuildResolvedCallExpr(MemExprE, Method, LParenLoc,
+ Args, NumArgs, RParenLoc);
+ }
+
+ MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
+ }
+
+ QualType ResultType = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultType);
+ ResultType = ResultType.getNonLValueExprType(Context);
+
+ assert(Method && "Member call to something that isn't a method?");
+ CXXMemberCallExpr *TheCall =
+ new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+ ResultType, VK, RParenLoc);
+
+ // Check for a valid return type.
+ if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
+ TheCall, Method))
+ return ExprError();
+
+ // Convert the object argument (for a non-static member function call).
+ // We only need to do this if there was actually an overload; otherwise
+ // it was done at lookup.
+ Expr *ObjectArg = MemExpr->getBase();
+ if (!Method->isStatic() &&
+ PerformObjectArgumentInitialization(ObjectArg, Qualifier,
+ FoundDecl, Method))
+ return ExprError();
+ MemExpr->setBase(ObjectArg);
+
+ // Convert the rest of the arguments
+ const FunctionProtoType *Proto =
+ Method->getType()->getAs<FunctionProtoType>();
+ if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs,
+ RParenLoc))
+ return ExprError();
+
+ if (CheckFunctionCall(Method, TheCall))
+ return ExprError();
+
+ return MaybeBindToTemporary(TheCall);
+}
+
+/// BuildCallToObjectOfClassType - Build a call to an object of class
+/// type (C++ [over.call.object]), which can end up invoking an
+/// overloaded function call operator (@c operator()) or performing a
+/// user-defined conversion on the object argument.
+ExprResult
+Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ if (Object->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Object);
+
+ assert(Object->getType()->isRecordType() && "Requires object type argument");
+ const RecordType *Record = Object->getType()->getAs<RecordType>();
+
+ // C++ [over.call.object]p1:
+ // If the primary-expression E in the function call syntax
+ // evaluates to a class object of type "cv T", then the set of
+ // candidate functions includes at least the function call
+ // operators of T. The function call operators of T are obtained by
+ // ordinary lookup of the name operator() in the context of
+ // (E).operator().
+ OverloadCandidateSet CandidateSet(LParenLoc);
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+
+ if (RequireCompleteType(LParenLoc, Object->getType(),
+ PDiag(diag::err_incomplete_object_call)
+ << Object->getSourceRange()))
+ return true;
+
+ LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, Record->getDecl());
+ R.suppressDiagnostics();
+
+ for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+ Oper != OperEnd; ++Oper) {
+ AddMethodCandidate(Oper.getPair(), Object->getType(),
+ Object->Classify(Context), Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions=*/ false);
+ }
+
+ // C++ [over.call.object]p2:
+ // In addition, for each conversion function declared in T of the
+ // form
+ //
+ // operator conversion-type-id () cv-qualifier;
+ //
+ // where cv-qualifier is the same cv-qualification as, or a
+ // greater cv-qualification than, cv, and where conversion-type-id
+ // denotes the type "pointer to function of (P1,...,Pn) returning
+ // R", or the type "reference to pointer to function of
+ // (P1,...,Pn) returning R", or the type "reference to function
+ // of (P1,...,Pn) returning R", a surrogate call function [...]
+ // is also considered as a candidate function. Similarly,
+ // surrogate call functions are added to the set of candidate
+ // functions for each conversion function declared in an
+ // accessible base class provided the function is not hidden
+ // within T by another intervening declaration.
+ const UnresolvedSetImpl *Conversions
+ = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ // Skip over templated conversion functions; they aren't
+ // surrogates.
+ if (isa<FunctionTemplateDecl>(D))
+ continue;
+
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+
+ // Strip the reference type (if any) and then the pointer type (if
+ // any) to get down to what might be a function type.
+ QualType ConvType = Conv->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
+
+ if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+ AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
+ Object, Args, NumArgs, CandidateSet);
+ }
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(),
+ Best)) {
+ case OR_Success:
+ // Overload resolution succeeded; we'll build the appropriate call
+ // below.
+ break;
+
+ case OR_No_Viable_Function:
+ if (CandidateSet.empty())
+ Diag(Object->getSourceRange().getBegin(), diag::err_ovl_no_oper)
+ << Object->getType() << /*call*/ 1
+ << Object->getSourceRange();
+ else
+ Diag(Object->getSourceRange().getBegin(),
+ diag::err_ovl_no_viable_object_call)
+ << Object->getType() << Object->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ break;
+
+ case OR_Ambiguous:
+ Diag(Object->getSourceRange().getBegin(),
+ diag::err_ovl_ambiguous_object_call)
+ << Object->getType() << Object->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
+ break;
+
+ case OR_Deleted:
+ Diag(Object->getSourceRange().getBegin(),
+ diag::err_ovl_deleted_object_call)
+ << Best->Function->isDeleted()
+ << Object->getType() << Object->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ break;
+ }
+
+ if (Best == CandidateSet.end())
+ return true;
+
+ if (Best->Function == 0) {
+ // Since there is no function declaration, this is one of the
+ // surrogate candidates. Dig out the conversion function.
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(
+ Best->Conversions[0].UserDefined.ConversionFunction);
+
+ CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
+ DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
+
+ // We selected one of the surrogate functions that converts the
+ // object parameter to a function pointer. Perform the conversion
+ // on the object argument, then let ActOnCallExpr finish the job.
+
+ // Create an implicit member expr to refer to the conversion operator.
+ // and then call it.
+ ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv);
+ if (Call.isInvalid())
+ return ExprError();
+
+ return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs),
+ RParenLoc);
+ }
+
+ CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
+ DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
+
+ // We found an overloaded operator(). Build a CXXOperatorCallExpr
+ // that calls this method, using Object for the implicit object
+ // parameter and passing along the remaining arguments.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+ const FunctionProtoType *Proto =
+ Method->getType()->getAs<FunctionProtoType>();
+
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumArgsToCheck = NumArgs;
+
+ // Build the full argument list for the method call (the
+ // implicit object parameter is placed at the beginning of the
+ // list).
+ Expr **MethodArgs;
+ if (NumArgs < NumArgsInProto) {
+ NumArgsToCheck = NumArgsInProto;
+ MethodArgs = new Expr*[NumArgsInProto + 1];
+ } else {
+ MethodArgs = new Expr*[NumArgs + 1];
+ }
+ MethodArgs[0] = Object;
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+ MethodArgs[ArgIdx + 1] = Args[ArgIdx];
+
+ Expr *NewFn = CreateFunctionRefExpr(*this, Method);
+
+ // Once we've built TheCall, all of the expressions are properly
+ // owned.
+ QualType ResultTy = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
+ MethodArgs, NumArgs + 1,
+ ResultTy, VK, RParenLoc);
+ delete [] MethodArgs;
+
+ if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
+ Method))
+ return true;
+
+ // We may have default arguments. If so, we need to allocate more
+ // slots in the call for them.
+ if (NumArgs < NumArgsInProto)
+ TheCall->setNumArgs(Context, NumArgsInProto + 1);
+ else if (NumArgs > NumArgsInProto)
+ NumArgsToCheck = NumArgsInProto;
+
+ bool IsError = false;
+
+ // Initialize the implicit object parameter.
+ IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,
+ Best->FoundDecl, Method);
+ TheCall->setArg(0, Object);
+
+
+ // Check the argument types.
+ for (unsigned i = 0; i != NumArgsToCheck; i++) {
+ Expr *Arg;
+ if (i < NumArgs) {
+ Arg = Args[i];
+
+ // Pass the argument.
+
+ ExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
+ Method->getParamDecl(i)),
+ SourceLocation(), Arg);
+
+ IsError |= InputInit.isInvalid();
+ Arg = InputInit.takeAs<Expr>();
+ } else {
+ ExprResult DefArg
+ = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
+ if (DefArg.isInvalid()) {
+ IsError = true;
+ break;
+ }
+
+ Arg = DefArg.takeAs<Expr>();
+ }
+
+ TheCall->setArg(i + 1, Arg);
+ }
+
+ // If this is a variadic call, handle args passed through "...".
+ if (Proto->isVariadic()) {
+ // Promote the arguments (C99 6.5.2.2p7).
+ for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod, 0);
+ TheCall->setArg(i + 1, Arg);
+ }
+ }
+
+ if (IsError) return true;
+
+ if (CheckFunctionCall(Method, TheCall))
+ return true;
+
+ return MaybeBindToTemporary(TheCall);
+}
+
+/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
+/// (if one exists), where @c Base is an expression of class type and
+/// @c Member is the name of the member we're trying to find.
+ExprResult
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
+ assert(Base->getType()->isRecordType() &&
+ "left-hand side must have class type");
+
+ if (Base->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Base);
+
+ SourceLocation Loc = Base->getExprLoc();
+
+ // C++ [over.ref]p1:
+ //
+ // [...] An expression x->m is interpreted as (x.operator->())->m
+ // for a class object x of type T if T::operator->() exists and if
+ // the operator is selected as the best match function by the
+ // overload resolution mechanism (13.3).
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
+ OverloadCandidateSet CandidateSet(Loc);
+ const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
+
+ if (RequireCompleteType(Loc, Base->getType(),
+ PDiag(diag::err_typecheck_incomplete_tag)
+ << Base->getSourceRange()))
+ return ExprError();
+
+ LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, BaseRecord->getDecl());
+ R.suppressDiagnostics();
+
+ for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
+ Oper != OperEnd; ++Oper) {
+ AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
+ 0, 0, CandidateSet, /*SuppressUserConversions=*/false);
+ }
+
+ // Perform overload resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
+ case OR_Success:
+ // Overload resolution succeeded; we'll build the call below.
+ break;
+
+ case OR_No_Viable_Function:
+ if (CandidateSet.empty())
+ Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
+ << Base->getType() << Base->getSourceRange();
+ else
+ Diag(OpLoc, diag::err_ovl_no_viable_oper)
+ << "operator->" << Base->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
+ return ExprError();
+
+ case OR_Ambiguous:
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
+ << "->" << Base->getType() << Base->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1);
+ return ExprError();
+
+ case OR_Deleted:
+ Diag(OpLoc, diag::err_ovl_deleted_oper)
+ << Best->Function->isDeleted()
+ << "->" << Base->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
+ return ExprError();
+ }
+
+ CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
+ DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
+
+ // Convert the object parameter.
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
+ if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+ Best->FoundDecl, Method))
+ return ExprError();
+
+ // Build the operator call.
+ Expr *FnExpr = CreateFunctionRefExpr(*this, Method);
+
+ QualType ResultTy = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
+ &Base, 1, ResultTy, VK, OpLoc);
+
+ if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
+ Method))
+ return ExprError();
+ return Owned(TheCall);
+}
+
+/// FixOverloadedFunctionReference - E is an expression that refers to
+/// a C++ overloaded function (possibly with some parentheses and
+/// perhaps a '&' around it). We have resolved the overloaded function
+/// to the function declaration Fn, so patch up the expression E to
+/// refer (possibly indirectly) to Fn. Returns the new expr.
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
+ FunctionDecl *Fn) {
+ if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
+ Found, Fn);
+ if (SubExpr == PE->getSubExpr())
+ return PE;
+
+ return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
+ }
+
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
+ Found, Fn);
+ assert(Context.hasSameType(ICE->getSubExpr()->getType(),
+ SubExpr->getType()) &&
+ "Implicit cast type cannot be determined from overload");
+ assert(ICE->path_empty() && "fixing up hierarchy conversion?");
+ if (SubExpr == ICE->getSubExpr())
+ return ICE;
+
+ return ImplicitCastExpr::Create(Context, ICE->getType(),
+ ICE->getCastKind(),
+ SubExpr, 0,
+ ICE->getValueKind());
+ }
+
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
+ assert(UnOp->getOpcode() == UO_AddrOf &&
+ "Can only take the address of an overloaded function");
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
+ if (Method->isStatic()) {
+ // Do nothing: static member functions aren't any different
+ // from non-member functions.
+ } else {
+ // Fix the sub expression, which really has to be an
+ // UnresolvedLookupExpr holding an overloaded member function
+ // or template.
+ Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+ Found, Fn);
+ if (SubExpr == UnOp->getSubExpr())
+ return UnOp;
+
+ assert(isa<DeclRefExpr>(SubExpr)
+ && "fixed to something other than a decl ref");
+ assert(cast<DeclRefExpr>(SubExpr)->getQualifier()
+ && "fixed to a member ref with no nested name qualifier");
+
+ // We have taken the address of a pointer to member
+ // function. Perform the computation here so that we get the
+ // appropriate pointer to member type.
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ QualType MemPtrType
+ = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
+
+ return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
+ VK_RValue, OK_Ordinary,
+ UnOp->getOperatorLoc());
+ }
+ }
+ Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+ Found, Fn);
+ if (SubExpr == UnOp->getSubExpr())
+ return UnOp;
+
+ return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
+ Context.getPointerType(SubExpr->getType()),
+ VK_RValue, OK_Ordinary,
+ UnOp->getOperatorLoc());
+ }
+
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
+ // FIXME: avoid copy.
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ if (ULE->hasExplicitTemplateArgs()) {
+ ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
+ TemplateArgs = &TemplateArgsBuffer;
+ }
+
+ return DeclRefExpr::Create(Context,
+ ULE->getQualifier(),
+ ULE->getQualifierRange(),
+ Fn,
+ ULE->getNameLoc(),
+ Fn->getType(),
+ VK_LValue,
+ TemplateArgs);
+ }
+
+ if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
+ // FIXME: avoid copy.
+ TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
+ if (MemExpr->hasExplicitTemplateArgs()) {
+ MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
+ TemplateArgs = &TemplateArgsBuffer;
+ }
+
+ Expr *Base;
+
+ // If we're filling in a static method where we used to have an
+ // implicit member access, rewrite to a simple decl ref.
+ if (MemExpr->isImplicitAccess()) {
+ if (cast<CXXMethodDecl>(Fn)->isStatic()) {
+ return DeclRefExpr::Create(Context,
+ MemExpr->getQualifier(),
+ MemExpr->getQualifierRange(),
+ Fn,
+ MemExpr->getMemberLoc(),
+ Fn->getType(),
+ VK_LValue,
+ TemplateArgs);
+ } else {
+ SourceLocation Loc = MemExpr->getMemberLoc();
+ if (MemExpr->getQualifier())
+ Loc = MemExpr->getQualifierRange().getBegin();
+ Base = new (Context) CXXThisExpr(Loc,
+ MemExpr->getBaseType(),
+ /*isImplicit=*/true);
+ }
+ } else
+ Base = MemExpr->getBase();
+
+ return MemberExpr::Create(Context, Base,
+ MemExpr->isArrow(),
+ MemExpr->getQualifier(),
+ MemExpr->getQualifierRange(),
+ Fn,
+ Found,
+ MemExpr->getMemberNameInfo(),
+ TemplateArgs,
+ Fn->getType(),
+ cast<CXXMethodDecl>(Fn)->isStatic()
+ ? VK_LValue : VK_RValue,
+ OK_Ordinary);
+ }
+
+ llvm_unreachable("Invalid reference to overloaded function");
+ return E;
+}
+
+ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
+ DeclAccessPair Found,
+ FunctionDecl *Fn) {
+ return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
+}
+
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
new file mode 100644
index 0000000..e995e8f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -0,0 +1,1806 @@
+//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for statements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+using namespace sema;
+
+StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
+ Expr *E = expr.get();
+ if (!E) // FIXME: FullExprArg has no error state?
+ return StmtError();
+
+ // C99 6.8.3p2: The expression in an expression statement is evaluated as a
+ // void expression for its side effects. Conversion to void allows any
+ // operand, even incomplete types.
+
+ // Same thing in for stmt first clause (when expr) and third clause.
+ return Owned(static_cast<Stmt*>(E));
+}
+
+
+StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool LeadingEmptyMacro) {
+ return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacro));
+}
+
+StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+ // If we have an invalid decl, just return an error.
+ if (DG.isNull()) return StmtError();
+
+ return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc));
+}
+
+void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
+ DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
+
+ // If we have an invalid decl, just return.
+ if (DG.isNull() || !DG.isSingleDecl()) return;
+ // suppress any potential 'unused variable' warning.
+ DG.getSingleDecl()->setUsed();
+}
+
+void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
+ if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
+ return DiagnoseUnusedExprResult(Label->getSubStmt());
+
+ const Expr *E = dyn_cast_or_null<Expr>(S);
+ if (!E)
+ return;
+
+ if (E->isBoundMemberFunction(Context)) {
+ Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+ << E->getSourceRange();
+ return;
+ }
+
+ SourceLocation Loc;
+ SourceRange R1, R2;
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
+ return;
+
+ // Okay, we have an unused result. Depending on what the base expression is,
+ // we might want to make a more specific diagnostic. Check for one of these
+ // cases now.
+ unsigned DiagID = diag::warn_unused_expr;
+ if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
+ E = Temps->getSubExpr();
+
+ E = E->IgnoreParenImpCasts();
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ if (E->getType()->isVoidType())
+ return;
+
+ // If the callee has attribute pure, const, or warn_unused_result, warn with
+ // a more specific message to make it clear what is happening.
+ if (const Decl *FD = CE->getCalleeDecl()) {
+ if (FD->getAttr<WarnUnusedResultAttr>()) {
+ Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
+ return;
+ }
+ if (FD->getAttr<PureAttr>()) {
+ Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
+ return;
+ }
+ if (FD->getAttr<ConstAttr>()) {
+ Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
+ return;
+ }
+ }
+ } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ const ObjCMethodDecl *MD = ME->getMethodDecl();
+ if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
+ Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
+ return;
+ }
+ } else if (isa<ObjCPropertyRefExpr>(E)) {
+ DiagID = diag::warn_unused_property_expr;
+ } else if (const CXXFunctionalCastExpr *FC
+ = dyn_cast<CXXFunctionalCastExpr>(E)) {
+ if (isa<CXXConstructExpr>(FC->getSubExpr()) ||
+ isa<CXXTemporaryObjectExpr>(FC->getSubExpr()))
+ return;
+ }
+ // Diagnose "(void*) blah" as a typo for "(void) blah".
+ else if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) {
+ TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
+ QualType T = TI->getType();
+
+ // We really do want to use the non-canonical type here.
+ if (T == Context.VoidPtrTy) {
+ PointerTypeLoc TL = cast<PointerTypeLoc>(TI->getTypeLoc());
+
+ Diag(Loc, diag::warn_unused_voidptr)
+ << FixItHint::CreateRemoval(TL.getStarLoc());
+ return;
+ }
+ }
+
+ DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2);
+}
+
+StmtResult
+Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ MultiStmtArg elts, bool isStmtExpr) {
+ unsigned NumElts = elts.size();
+ Stmt **Elts = reinterpret_cast<Stmt**>(elts.release());
+ // If we're in C89 mode, check that we don't have any decls after stmts. If
+ // so, emit an extension diagnostic.
+ if (!getLangOptions().C99 && !getLangOptions().CPlusPlus) {
+ // Note that __extension__ can be around a decl.
+ unsigned i = 0;
+ // Skip over all declarations.
+ for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
+ /*empty*/;
+
+ // We found the end of the list or a statement. Scan for another declstmt.
+ for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
+ /*empty*/;
+
+ if (i != NumElts) {
+ Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
+ Diag(D->getLocation(), diag::ext_mixed_decls_code);
+ }
+ }
+ // Warn about unused expressions in statements.
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // Ignore statements that are last in a statement expression.
+ if (isStmtExpr && i == NumElts - 1)
+ continue;
+
+ DiagnoseUnusedExprResult(Elts[i]);
+ }
+
+ return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R));
+}
+
+StmtResult
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+ SourceLocation DotDotDotLoc, Expr *RHSVal,
+ SourceLocation ColonLoc) {
+ assert((LHSVal != 0) && "missing expression in case statement");
+
+ // C99 6.8.4.2p3: The expression shall be an integer constant.
+ // However, GCC allows any evaluatable integer expression.
+ if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() &&
+ VerifyIntegerConstantExpression(LHSVal))
+ return StmtError();
+
+ // GCC extension: The expression shall be an integer constant.
+
+ if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
+ VerifyIntegerConstantExpression(RHSVal)) {
+ RHSVal = 0; // Recover by just forgetting about it.
+ }
+
+ if (getCurFunction()->SwitchStack.empty()) {
+ Diag(CaseLoc, diag::err_case_not_in_switch);
+ return StmtError();
+ }
+
+ CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
+ ColonLoc);
+ getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
+ return Owned(CS);
+}
+
+/// ActOnCaseStmtBody - This installs a statement as the body of a case.
+void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
+ CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
+ CS->setSubStmt(SubStmt);
+}
+
+StmtResult
+Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope) {
+ if (getCurFunction()->SwitchStack.empty()) {
+ Diag(DefaultLoc, diag::err_default_not_in_switch);
+ return Owned(SubStmt);
+ }
+
+ DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
+ getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
+ return Owned(DS);
+}
+
+StmtResult
+Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+ SourceLocation ColonLoc, Stmt *SubStmt) {
+
+ // If the label was multiply defined, reject it now.
+ if (TheDecl->getStmt()) {
+ Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
+ Diag(TheDecl->getLocation(), diag::note_previous_definition);
+ return Owned(SubStmt);
+ }
+
+ // Otherwise, things are good. Fill in the declaration and return it.
+ TheDecl->setLocation(IdentLoc);
+
+ LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
+ TheDecl->setStmt(LS);
+ TheDecl->setLocation(IdentLoc);
+ return Owned(LS);
+}
+
+StmtResult
+Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
+ Stmt *thenStmt, SourceLocation ElseLoc,
+ Stmt *elseStmt) {
+ ExprResult CondResult(CondVal.release());
+
+ VarDecl *ConditionVar = 0;
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
+ CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
+ if (CondResult.isInvalid())
+ return StmtError();
+ }
+ Expr *ConditionExpr = CondResult.takeAs<Expr>();
+ if (!ConditionExpr)
+ return StmtError();
+
+ DiagnoseUnusedExprResult(thenStmt);
+
+ // Warn if the if block has a null body without an else value.
+ // this helps prevent bugs due to typos, such as
+ // if (condition);
+ // do_stuff();
+ //
+ if (!elseStmt) {
+ if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt))
+ // But do not warn if the body is a macro that expands to nothing, e.g:
+ //
+ // #define CALL(x)
+ // if (condition)
+ // CALL(0);
+ //
+ if (!stmt->hasLeadingEmptyMacro())
+ Diag(stmt->getSemiLoc(), diag::warn_empty_if_body);
+ }
+
+ DiagnoseUnusedExprResult(elseStmt);
+
+ return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
+ thenStmt, ElseLoc, elseStmt));
+}
+
+/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+/// the specified width and sign. If an overflow occurs, detect it and emit
+/// the specified diagnostic.
+void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val,
+ unsigned NewWidth, bool NewSign,
+ SourceLocation Loc,
+ unsigned DiagID) {
+ // Perform a conversion to the promoted condition type if needed.
+ if (NewWidth > Val.getBitWidth()) {
+ // If this is an extension, just do it.
+ Val = Val.extend(NewWidth);
+ Val.setIsSigned(NewSign);
+
+ // If the input was signed and negative and the output is
+ // unsigned, don't bother to warn: this is implementation-defined
+ // behavior.
+ // FIXME: Introduce a second, default-ignored warning for this case?
+ } else if (NewWidth < Val.getBitWidth()) {
+ // If this is a truncation, check for overflow.
+ llvm::APSInt ConvVal(Val);
+ ConvVal = ConvVal.trunc(NewWidth);
+ ConvVal.setIsSigned(NewSign);
+ ConvVal = ConvVal.extend(Val.getBitWidth());
+ ConvVal.setIsSigned(Val.isSigned());
+ if (ConvVal != Val)
+ Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10);
+
+ // Regardless of whether a diagnostic was emitted, really do the
+ // truncation.
+ Val = Val.trunc(NewWidth);
+ Val.setIsSigned(NewSign);
+ } else if (NewSign != Val.isSigned()) {
+ // Convert the sign to match the sign of the condition. This can cause
+ // overflow as well: unsigned(INTMIN)
+ // We don't diagnose this overflow, because it is implementation-defined
+ // behavior.
+ // FIXME: Introduce a second, default-ignored warning for this case?
+ llvm::APSInt OldVal(Val);
+ Val.setIsSigned(NewSign);
+ }
+}
+
+namespace {
+ struct CaseCompareFunctor {
+ bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+ const llvm::APSInt &RHS) {
+ return LHS.first < RHS;
+ }
+ bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS,
+ const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+ return LHS.first < RHS.first;
+ }
+ bool operator()(const llvm::APSInt &LHS,
+ const std::pair<llvm::APSInt, CaseStmt*> &RHS) {
+ return LHS < RHS.first;
+ }
+ };
+}
+
+/// CmpCaseVals - Comparison predicate for sorting case values.
+///
+static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
+ const std::pair<llvm::APSInt, CaseStmt*>& rhs) {
+ if (lhs.first < rhs.first)
+ return true;
+
+ if (lhs.first == rhs.first &&
+ lhs.second->getCaseLoc().getRawEncoding()
+ < rhs.second->getCaseLoc().getRawEncoding())
+ return true;
+ return false;
+}
+
+/// CmpEnumVals - Comparison predicate for sorting enumeration values.
+///
+static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+ const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+/// EqEnumVals - Comparison preficate for uniqing enumeration values.
+///
+static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+ const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+ return lhs.first == rhs.first;
+}
+
+/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
+/// potentially integral-promoted expression @p expr.
+static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
+ if (const CastExpr *ImplicitCast = dyn_cast<ImplicitCastExpr>(expr)) {
+ const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr();
+ QualType TypeBeforePromotion = ExprBeforePromotion->getType();
+ if (TypeBeforePromotion->isIntegralOrEnumerationType()) {
+ return TypeBeforePromotion;
+ }
+ }
+ return expr->getType();
+}
+
+StmtResult
+Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
+ Decl *CondVar) {
+ ExprResult CondResult;
+
+ VarDecl *ConditionVar = 0;
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
+ CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);
+ if (CondResult.isInvalid())
+ return StmtError();
+
+ Cond = CondResult.release();
+ }
+
+ if (!Cond)
+ return StmtError();
+
+ CondResult
+ = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond,
+ PDiag(diag::err_typecheck_statement_requires_integer),
+ PDiag(diag::err_switch_incomplete_class_type)
+ << Cond->getSourceRange(),
+ PDiag(diag::err_switch_explicit_conversion),
+ PDiag(diag::note_switch_conversion),
+ PDiag(diag::err_switch_multiple_conversions),
+ PDiag(diag::note_switch_conversion),
+ PDiag(0));
+ if (CondResult.isInvalid()) return StmtError();
+ Cond = CondResult.take();
+
+ if (!CondVar) {
+ CheckImplicitConversions(Cond, SwitchLoc);
+ CondResult = MaybeCreateExprWithCleanups(Cond);
+ if (CondResult.isInvalid())
+ return StmtError();
+ Cond = CondResult.take();
+ }
+
+ getCurFunction()->setHasBranchIntoScope();
+
+ SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);
+ getCurFunction()->SwitchStack.push_back(SS);
+ return Owned(SS);
+}
+
+static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
+ if (Val.getBitWidth() < BitWidth)
+ Val = Val.extend(BitWidth);
+ else if (Val.getBitWidth() > BitWidth)
+ Val = Val.trunc(BitWidth);
+ Val.setIsSigned(IsSigned);
+}
+
+StmtResult
+Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+ Stmt *BodyStmt) {
+ SwitchStmt *SS = cast<SwitchStmt>(Switch);
+ assert(SS == getCurFunction()->SwitchStack.back() &&
+ "switch stack missing push/pop!");
+
+ SS->setBody(BodyStmt, SwitchLoc);
+ getCurFunction()->SwitchStack.pop_back();
+
+ if (SS->getCond() == 0)
+ return StmtError();
+
+ Expr *CondExpr = SS->getCond();
+ Expr *CondExprBeforePromotion = CondExpr;
+ QualType CondTypeBeforePromotion =
+ GetTypeBeforeIntegralPromotion(CondExpr);
+
+ // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
+ UsualUnaryConversions(CondExpr);
+ QualType CondType = CondExpr->getType();
+ SS->setCond(CondExpr);
+
+ // C++ 6.4.2.p2:
+ // Integral promotions are performed (on the switch condition).
+ //
+ // A case value unrepresentable by the original switch condition
+ // type (before the promotion) doesn't make sense, even when it can
+ // be represented by the promoted type. Therefore we need to find
+ // the pre-promotion type of the switch condition.
+ if (!CondExpr->isTypeDependent()) {
+ // We have already converted the expression to an integral or enumeration
+ // type, when we started the switch statement. If we don't have an
+ // appropriate type now, just return an error.
+ if (!CondType->isIntegralOrEnumerationType())
+ return StmtError();
+
+ if (CondExpr->isKnownToHaveBooleanValue()) {
+ // switch(bool_expr) {...} is often a programmer error, e.g.
+ // switch(n && mask) { ... } // Doh - should be "n & mask".
+ // One can always use an if statement instead of switch(bool_expr).
+ Diag(SwitchLoc, diag::warn_bool_switch_condition)
+ << CondExpr->getSourceRange();
+ }
+ }
+
+ // Get the bitwidth of the switched-on value before promotions. We must
+ // convert the integer case values to this width before comparison.
+ bool HasDependentValue
+ = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
+ unsigned CondWidth
+ = HasDependentValue? 0
+ : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+ bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
+
+ // Accumulate all of the case values in a vector so that we can sort them
+ // and detect duplicates. This vector contains the APInt for the case after
+ // it has been converted to the condition type.
+ typedef llvm::SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseValsTy;
+ CaseValsTy CaseVals;
+
+ // Keep track of any GNU case ranges we see. The APSInt is the low value.
+ typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
+ CaseRangesTy CaseRanges;
+
+ DefaultStmt *TheDefaultStmt = 0;
+
+ bool CaseListIsErroneous = false;
+
+ for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue;
+ SC = SC->getNextSwitchCase()) {
+
+ if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) {
+ if (TheDefaultStmt) {
+ Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined);
+ Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev);
+
+ // FIXME: Remove the default statement from the switch block so that
+ // we'll return a valid AST. This requires recursing down the AST and
+ // finding it, not something we are set up to do right now. For now,
+ // just lop the entire switch stmt out of the AST.
+ CaseListIsErroneous = true;
+ }
+ TheDefaultStmt = DS;
+
+ } else {
+ CaseStmt *CS = cast<CaseStmt>(SC);
+
+ // We already verified that the expression has a i-c-e value (C99
+ // 6.8.4.2p3) - get that value now.
+ Expr *Lo = CS->getLHS();
+
+ if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+ HasDependentValue = true;
+ break;
+ }
+
+ llvm::APSInt LoVal = Lo->EvaluateAsInt(Context);
+
+ // Convert the value to the same width/sign as the condition.
+ ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned,
+ Lo->getLocStart(),
+ diag::warn_case_value_overflow);
+
+ // If the LHS is not the same type as the condition, insert an implicit
+ // cast.
+ ImpCastExprToType(Lo, CondType, CK_IntegralCast);
+ CS->setLHS(Lo);
+
+ // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
+ if (CS->getRHS()) {
+ if (CS->getRHS()->isTypeDependent() ||
+ CS->getRHS()->isValueDependent()) {
+ HasDependentValue = true;
+ break;
+ }
+ CaseRanges.push_back(std::make_pair(LoVal, CS));
+ } else
+ CaseVals.push_back(std::make_pair(LoVal, CS));
+ }
+ }
+
+ if (!HasDependentValue) {
+ // If we don't have a default statement, check whether the
+ // condition is constant.
+ llvm::APSInt ConstantCondValue;
+ bool HasConstantCond = false;
+ bool ShouldCheckConstantCond = false;
+ if (!HasDependentValue && !TheDefaultStmt) {
+ Expr::EvalResult Result;
+ HasConstantCond = CondExprBeforePromotion->Evaluate(Result, Context);
+ if (HasConstantCond) {
+ assert(Result.Val.isInt() && "switch condition evaluated to non-int");
+ ConstantCondValue = Result.Val.getInt();
+ ShouldCheckConstantCond = true;
+
+ assert(ConstantCondValue.getBitWidth() == CondWidth &&
+ ConstantCondValue.isSigned() == CondIsSigned);
+ }
+ }
+
+ // Sort all the scalar case values so we can easily detect duplicates.
+ std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
+
+ if (!CaseVals.empty()) {
+ for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) {
+ if (ShouldCheckConstantCond &&
+ CaseVals[i].first == ConstantCondValue)
+ ShouldCheckConstantCond = false;
+
+ if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) {
+ // If we have a duplicate, report it.
+ Diag(CaseVals[i].second->getLHS()->getLocStart(),
+ diag::err_duplicate_case) << CaseVals[i].first.toString(10);
+ Diag(CaseVals[i-1].second->getLHS()->getLocStart(),
+ diag::note_duplicate_case_prev);
+ // FIXME: We really want to remove the bogus case stmt from the
+ // substmt, but we have no way to do this right now.
+ CaseListIsErroneous = true;
+ }
+ }
+ }
+
+ // Detect duplicate case ranges, which usually don't exist at all in
+ // the first place.
+ if (!CaseRanges.empty()) {
+ // Sort all the case ranges by their low value so we can easily detect
+ // overlaps between ranges.
+ std::stable_sort(CaseRanges.begin(), CaseRanges.end());
+
+ // Scan the ranges, computing the high values and removing empty ranges.
+ std::vector<llvm::APSInt> HiVals;
+ for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+ llvm::APSInt &LoVal = CaseRanges[i].first;
+ CaseStmt *CR = CaseRanges[i].second;
+ Expr *Hi = CR->getRHS();
+ llvm::APSInt HiVal = Hi->EvaluateAsInt(Context);
+
+ // Convert the value to the same width/sign as the condition.
+ ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
+ Hi->getLocStart(),
+ diag::warn_case_value_overflow);
+
+ // If the LHS is not the same type as the condition, insert an implicit
+ // cast.
+ ImpCastExprToType(Hi, CondType, CK_IntegralCast);
+ CR->setRHS(Hi);
+
+ // If the low value is bigger than the high value, the case is empty.
+ if (LoVal > HiVal) {
+ Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
+ << SourceRange(CR->getLHS()->getLocStart(),
+ Hi->getLocEnd());
+ CaseRanges.erase(CaseRanges.begin()+i);
+ --i, --e;
+ continue;
+ }
+
+ if (ShouldCheckConstantCond &&
+ LoVal <= ConstantCondValue &&
+ ConstantCondValue <= HiVal)
+ ShouldCheckConstantCond = false;
+
+ HiVals.push_back(HiVal);
+ }
+
+ // Rescan the ranges, looking for overlap with singleton values and other
+ // ranges. Since the range list is sorted, we only need to compare case
+ // ranges with their neighbors.
+ for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+ llvm::APSInt &CRLo = CaseRanges[i].first;
+ llvm::APSInt &CRHi = HiVals[i];
+ CaseStmt *CR = CaseRanges[i].second;
+
+ // Check to see whether the case range overlaps with any
+ // singleton cases.
+ CaseStmt *OverlapStmt = 0;
+ llvm::APSInt OverlapVal(32);
+
+ // Find the smallest value >= the lower bound. If I is in the
+ // case range, then we have overlap.
+ CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
+ CaseVals.end(), CRLo,
+ CaseCompareFunctor());
+ if (I != CaseVals.end() && I->first < CRHi) {
+ OverlapVal = I->first; // Found overlap with scalar.
+ OverlapStmt = I->second;
+ }
+
+ // Find the smallest value bigger than the upper bound.
+ I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
+ if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
+ OverlapVal = (I-1)->first; // Found overlap with scalar.
+ OverlapStmt = (I-1)->second;
+ }
+
+ // Check to see if this case stmt overlaps with the subsequent
+ // case range.
+ if (i && CRLo <= HiVals[i-1]) {
+ OverlapVal = HiVals[i-1]; // Found overlap with range.
+ OverlapStmt = CaseRanges[i-1].second;
+ }
+
+ if (OverlapStmt) {
+ // If we have a duplicate, report it.
+ Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
+ << OverlapVal.toString(10);
+ Diag(OverlapStmt->getLHS()->getLocStart(),
+ diag::note_duplicate_case_prev);
+ // FIXME: We really want to remove the bogus case stmt from the
+ // substmt, but we have no way to do this right now.
+ CaseListIsErroneous = true;
+ }
+ }
+ }
+
+ // Complain if we have a constant condition and we didn't find a match.
+ if (!CaseListIsErroneous && ShouldCheckConstantCond) {
+ // TODO: it would be nice if we printed enums as enums, chars as
+ // chars, etc.
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
+ << ConstantCondValue.toString(10)
+ << CondExpr->getSourceRange();
+ }
+
+ // Check to see if switch is over an Enum and handles all of its
+ // values. We only issue a warning if there is not 'default:', but
+ // we still do the analysis to preserve this information in the AST
+ // (which can be used by flow-based analyes).
+ //
+ const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>();
+
+ // If switch has default case, then ignore it.
+ if (!CaseListIsErroneous && !HasConstantCond && ET) {
+ const EnumDecl *ED = ET->getDecl();
+ typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
+ EnumValsTy EnumVals;
+
+ // Gather all enum values, set their type and sort them,
+ // allowing easier comparison with CaseVals.
+ for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin();
+ EDI != ED->enumerator_end(); ++EDI) {
+ llvm::APSInt Val = EDI->getInitVal();
+ AdjustAPSInt(Val, CondWidth, CondIsSigned);
+ EnumVals.push_back(std::make_pair(Val, *EDI));
+ }
+ std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+ EnumValsTy::iterator EIend =
+ std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+
+ // See which case values aren't in enum.
+ // TODO: we might want to check whether case values are out of the
+ // enum even if we don't want to check whether all cases are handled.
+ if (!TheDefaultStmt) {
+ EnumValsTy::const_iterator EI = EnumVals.begin();
+ for (CaseValsTy::const_iterator CI = CaseVals.begin();
+ CI != CaseVals.end(); CI++) {
+ while (EI != EIend && EI->first < CI->first)
+ EI++;
+ if (EI == EIend || EI->first > CI->first)
+ Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
+ << ED->getDeclName();
+ }
+ // See which of case ranges aren't in enum
+ EI = EnumVals.begin();
+ for (CaseRangesTy::const_iterator RI = CaseRanges.begin();
+ RI != CaseRanges.end() && EI != EIend; RI++) {
+ while (EI != EIend && EI->first < RI->first)
+ EI++;
+
+ if (EI == EIend || EI->first != RI->first) {
+ Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
+ << ED->getDeclName();
+ }
+
+ llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+ AdjustAPSInt(Hi, CondWidth, CondIsSigned);
+ while (EI != EIend && EI->first < Hi)
+ EI++;
+ if (EI == EIend || EI->first != Hi)
+ Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum)
+ << ED->getDeclName();
+ }
+ }
+
+ // Check which enum vals aren't in switch
+ CaseValsTy::const_iterator CI = CaseVals.begin();
+ CaseRangesTy::const_iterator RI = CaseRanges.begin();
+ bool hasCasesNotInSwitch = false;
+
+ llvm::SmallVector<DeclarationName,8> UnhandledNames;
+
+ for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){
+ // Drop unneeded case values
+ llvm::APSInt CIVal;
+ while (CI != CaseVals.end() && CI->first < EI->first)
+ CI++;
+
+ if (CI != CaseVals.end() && CI->first == EI->first)
+ continue;
+
+ // Drop unneeded case ranges
+ for (; RI != CaseRanges.end(); RI++) {
+ llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+ AdjustAPSInt(Hi, CondWidth, CondIsSigned);
+ if (EI->first <= Hi)
+ break;
+ }
+
+ if (RI == CaseRanges.end() || EI->first < RI->first) {
+ hasCasesNotInSwitch = true;
+ if (!TheDefaultStmt)
+ UnhandledNames.push_back(EI->second->getDeclName());
+ }
+ }
+
+ // Produce a nice diagnostic if multiple values aren't handled.
+ switch (UnhandledNames.size()) {
+ case 0: break;
+ case 1:
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_case1)
+ << UnhandledNames[0];
+ break;
+ case 2:
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_case2)
+ << UnhandledNames[0] << UnhandledNames[1];
+ break;
+ case 3:
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_case3)
+ << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+ break;
+ default:
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_cases)
+ << (unsigned)UnhandledNames.size()
+ << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+ break;
+ }
+
+ if (!hasCasesNotInSwitch)
+ SS->setAllEnumCasesCovered();
+ }
+ }
+
+ // FIXME: If the case list was broken is some way, we don't have a good system
+ // to patch it up. Instead, just return the whole substmt as broken.
+ if (CaseListIsErroneous)
+ return StmtError();
+
+ return Owned(SS);
+}
+
+StmtResult
+Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
+ Decl *CondVar, Stmt *Body) {
+ ExprResult CondResult(Cond.release());
+
+ VarDecl *ConditionVar = 0;
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
+ CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
+ if (CondResult.isInvalid())
+ return StmtError();
+ }
+ Expr *ConditionExpr = CondResult.take();
+ if (!ConditionExpr)
+ return StmtError();
+
+ DiagnoseUnusedExprResult(Body);
+
+ return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr,
+ Body, WhileLoc));
+}
+
+StmtResult
+Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+ SourceLocation WhileLoc, SourceLocation CondLParen,
+ Expr *Cond, SourceLocation CondRParen) {
+ assert(Cond && "ActOnDoStmt(): missing expression");
+
+ if (CheckBooleanCondition(Cond, DoLoc))
+ return StmtError();
+
+ CheckImplicitConversions(Cond, DoLoc);
+ ExprResult CondResult = MaybeCreateExprWithCleanups(Cond);
+ if (CondResult.isInvalid())
+ return StmtError();
+ Cond = CondResult.take();
+
+ DiagnoseUnusedExprResult(Body);
+
+ return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen));
+}
+
+StmtResult
+Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+ Stmt *First, FullExprArg second, Decl *secondVar,
+ FullExprArg third,
+ SourceLocation RParenLoc, Stmt *Body) {
+ if (!getLangOptions().CPlusPlus) {
+ if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+ // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+ // declare identifiers for objects having storage class 'auto' or
+ // 'register'.
+ for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+ DI!=DE; ++DI) {
+ VarDecl *VD = dyn_cast<VarDecl>(*DI);
+ if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
+ VD = 0;
+ if (VD == 0)
+ Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for);
+ // FIXME: mark decl erroneous!
+ }
+ }
+ }
+
+ ExprResult SecondResult(second.release());
+ VarDecl *ConditionVar = 0;
+ if (secondVar) {
+ ConditionVar = cast<VarDecl>(secondVar);
+ SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
+ if (SecondResult.isInvalid())
+ return StmtError();
+ }
+
+ Expr *Third = third.release().takeAs<Expr>();
+
+ DiagnoseUnusedExprResult(First);
+ DiagnoseUnusedExprResult(Third);
+ DiagnoseUnusedExprResult(Body);
+
+ return Owned(new (Context) ForStmt(Context, First,
+ SecondResult.take(), ConditionVar,
+ Third, Body, ForLoc, LParenLoc,
+ RParenLoc));
+}
+
+/// In an Objective C collection iteration statement:
+/// for (x in y)
+/// x can be an arbitrary l-value expression. Bind it up as a
+/// full-expression.
+StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
+ CheckImplicitConversions(E);
+ ExprResult Result = MaybeCreateExprWithCleanups(E);
+ if (Result.isInvalid()) return StmtError();
+ return Owned(static_cast<Stmt*>(Result.get()));
+}
+
+StmtResult
+Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, Expr *Second,
+ SourceLocation RParenLoc, Stmt *Body) {
+ if (First) {
+ QualType FirstType;
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
+ if (!DS->isSingleDecl())
+ return StmtError(Diag((*DS->decl_begin())->getLocation(),
+ diag::err_toomany_element_decls));
+
+ Decl *D = DS->getSingleDecl();
+ FirstType = cast<ValueDecl>(D)->getType();
+ // C99 6.8.5p3: The declaration part of a 'for' statement shall only
+ // declare identifiers for objects having storage class 'auto' or
+ // 'register'.
+ VarDecl *VD = cast<VarDecl>(D);
+ if (VD->isLocalVarDecl() && !VD->hasLocalStorage())
+ return StmtError(Diag(VD->getLocation(),
+ diag::err_non_variable_decl_in_for));
+ } else {
+ Expr *FirstE = cast<Expr>(First);
+ if (!FirstE->isTypeDependent() && !FirstE->isLValue())
+ return StmtError(Diag(First->getLocStart(),
+ diag::err_selector_element_not_lvalue)
+ << First->getSourceRange());
+
+ FirstType = static_cast<Expr*>(First)->getType();
+ }
+ if (!FirstType->isDependentType() &&
+ !FirstType->isObjCObjectPointerType() &&
+ !FirstType->isBlockPointerType())
+ Diag(ForLoc, diag::err_selector_element_type)
+ << FirstType << First->getSourceRange();
+ }
+ if (Second && !Second->isTypeDependent()) {
+ DefaultFunctionArrayLvalueConversion(Second);
+ QualType SecondType = Second->getType();
+ if (!SecondType->isObjCObjectPointerType())
+ Diag(ForLoc, diag::err_collection_expr_type)
+ << SecondType << Second->getSourceRange();
+ else if (const ObjCObjectPointerType *OPT =
+ SecondType->getAsObjCInterfacePointerType()) {
+ llvm::SmallVector<IdentifierInfo *, 4> KeyIdents;
+ IdentifierInfo* selIdent =
+ &Context.Idents.get("countByEnumeratingWithState");
+ KeyIdents.push_back(selIdent);
+ selIdent = &Context.Idents.get("objects");
+ KeyIdents.push_back(selIdent);
+ selIdent = &Context.Idents.get("count");
+ KeyIdents.push_back(selIdent);
+ Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]);
+ if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) {
+ if (!IDecl->isForwardDecl() &&
+ !IDecl->lookupInstanceMethod(CSelector)) {
+ // Must further look into private implementation methods.
+ if (!LookupPrivateInstanceMethod(CSelector, IDecl))
+ Diag(ForLoc, diag::warn_collection_expr_type)
+ << SecondType << CSelector << Second->getSourceRange();
+ }
+ }
+ }
+ }
+ return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body,
+ ForLoc, RParenLoc));
+}
+
+StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
+ SourceLocation LabelLoc,
+ LabelDecl *TheDecl) {
+ getCurFunction()->setHasBranchIntoScope();
+ TheDecl->setUsed();
+ return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc));
+}
+
+StmtResult
+Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
+ Expr *E) {
+ // Convert operand to void*
+ if (!E->isTypeDependent()) {
+ QualType ETy = E->getType();
+ QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
+ AssignConvertType ConvTy =
+ CheckSingleAssignmentConstraints(DestTy, E);
+ if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
+ return StmtError();
+ }
+
+ getCurFunction()->setHasIndirectGoto();
+
+ return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
+}
+
+StmtResult
+Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
+ Scope *S = CurScope->getContinueParent();
+ if (!S) {
+ // C99 6.8.6.2p1: A break shall appear only in or as a loop body.
+ return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
+ }
+
+ return Owned(new (Context) ContinueStmt(ContinueLoc));
+}
+
+StmtResult
+Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
+ Scope *S = CurScope->getBreakParent();
+ if (!S) {
+ // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body.
+ return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch));
+ }
+
+ return Owned(new (Context) BreakStmt(BreakLoc));
+}
+
+/// \brief Determine whether the given expression is a candidate for
+/// copy elision in either a return statement or a throw expression.
+///
+/// \param ReturnType If we're determining the copy elision candidate for
+/// a return statement, this is the return type of the function. If we're
+/// determining the copy elision candidate for a throw expression, this will
+/// be a NULL type.
+///
+/// \param E The expression being returned from the function or block, or
+/// being thrown.
+///
+/// \param AllowFunctionParameter
+///
+/// \returns The NRVO candidate variable, if the return statement may use the
+/// NRVO, or NULL if there is no such candidate.
+const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType,
+ Expr *E,
+ bool AllowFunctionParameter) {
+ QualType ExprType = E->getType();
+ // - in a return statement in a function with ...
+ // ... a class return type ...
+ if (!ReturnType.isNull()) {
+ if (!ReturnType->isRecordType())
+ return 0;
+ // ... the same cv-unqualified type as the function return type ...
+ if (!Context.hasSameUnqualifiedType(ReturnType, ExprType))
+ return 0;
+ }
+
+ // ... the expression is the name of a non-volatile automatic object
+ // (other than a function or catch-clause parameter)) ...
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
+ if (!DR)
+ return 0;
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return 0;
+
+ if (VD->hasLocalStorage() && !VD->isExceptionVariable() &&
+ !VD->getType()->isReferenceType() && !VD->hasAttr<BlocksAttr>() &&
+ !VD->getType().isVolatileQualified() &&
+ ((VD->getKind() == Decl::Var) ||
+ (AllowFunctionParameter && VD->getKind() == Decl::ParmVar)))
+ return VD;
+
+ return 0;
+}
+
+/// \brief Perform the initialization of a potentially-movable value, which
+/// is the result of return value.
+///
+/// This routine implements C++0x [class.copy]p33, which attempts to treat
+/// returned lvalues as rvalues in certain cases (to prefer move construction),
+/// then falls back to treating them as lvalues if that failed.
+ExprResult
+Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *Value) {
+ // C++0x [class.copy]p33:
+ // When the criteria for elision of a copy operation are met or would
+ // be met save for the fact that the source object is a function
+ // parameter, and the object to be copied is designated by an lvalue,
+ // overload resolution to select the constructor for the copy is first
+ // performed as if the object were designated by an rvalue.
+ ExprResult Res = ExprError();
+ if (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true)) {
+ ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack,
+ Value->getType(), CK_LValueToRValue,
+ Value, VK_XValue);
+
+ Expr *InitExpr = &AsRvalue;
+ InitializationKind Kind
+ = InitializationKind::CreateCopy(Value->getLocStart(),
+ Value->getLocStart());
+ InitializationSequence Seq(*this, Entity, Kind, &InitExpr, 1);
+
+ // [...] If overload resolution fails, or if the type of the first
+ // parameter of the selected constructor is not an rvalue reference
+ // to the object's type (possibly cv-qualified), overload resolution
+ // is performed again, considering the object as an lvalue.
+ if (Seq.getKind() != InitializationSequence::FailedSequence) {
+ for (InitializationSequence::step_iterator Step = Seq.step_begin(),
+ StepEnd = Seq.step_end();
+ Step != StepEnd; ++Step) {
+ if (Step->Kind
+ != InitializationSequence::SK_ConstructorInitialization)
+ continue;
+
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(Step->Function.Function);
+
+ const RValueReferenceType *RRefType
+ = Constructor->getParamDecl(0)->getType()
+ ->getAs<RValueReferenceType>();
+
+ // If we don't meet the criteria, break out now.
+ if (!RRefType ||
+ !Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+ Context.getTypeDeclType(Constructor->getParent())))
+ break;
+
+ // Promote "AsRvalue" to the heap, since we now need this
+ // expression node to persist.
+ Value = ImplicitCastExpr::Create(Context, Value->getType(),
+ CK_LValueToRValue, Value, 0,
+ VK_XValue);
+
+ // Complete type-checking the initialization of the return type
+ // using the constructor we found.
+ Res = Seq.Perform(*this, Entity, Kind, MultiExprArg(&Value, 1));
+ }
+ }
+ }
+
+ // Either we didn't meet the criteria for treating an lvalue as an rvalue,
+ // above, or overload resolution failed. Either way, we need to try
+ // (again) now with the return value expression as written.
+ if (Res.isInvalid())
+ Res = PerformCopyInitialization(Entity, SourceLocation(), Value);
+
+ return Res;
+}
+
+/// ActOnBlockReturnStmt - Utility routine to figure out block's return type.
+///
+StmtResult
+Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+ // If this is the first return we've seen in the block, infer the type of
+ // the block from it.
+ BlockScopeInfo *CurBlock = getCurBlock();
+ if (CurBlock->ReturnType.isNull()) {
+ if (RetValExp) {
+ // Don't call UsualUnaryConversions(), since we don't want to do
+ // integer promotions here.
+ DefaultFunctionArrayLvalueConversion(RetValExp);
+ CurBlock->ReturnType = RetValExp->getType();
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+ // We have to remove a 'const' added to copied-in variable which was
+ // part of the implementation spec. and not the actual qualifier for
+ // the variable.
+ if (CDRE->isConstQualAdded())
+ CurBlock->ReturnType.removeLocalConst(); // FIXME: local???
+ }
+ } else
+ CurBlock->ReturnType = Context.VoidTy;
+ }
+ QualType FnRetType = CurBlock->ReturnType;
+
+ if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) {
+ Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
+ << getCurFunctionOrMethodDecl()->getDeclName();
+ return StmtError();
+ }
+
+ // Otherwise, verify that this result type matches the previous one. We are
+ // pickier with blocks than for normal functions because we don't have GCC
+ // compatibility to worry about here.
+ ReturnStmt *Result = 0;
+ if (CurBlock->ReturnType->isVoidType()) {
+ if (RetValExp) {
+ Diag(ReturnLoc, diag::err_return_block_has_expr);
+ RetValExp = 0;
+ }
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
+ } else if (!RetValExp) {
+ return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr));
+ } else {
+ const VarDecl *NRVOCandidate = 0;
+
+ if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+ // we have a non-void block with an expression, continue checking
+
+ // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+ // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+ // function return.
+
+ // In C++ the return statement is handled via a copy initialization.
+ // the C version of which boils down to CheckSingleAssignmentConstraints.
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
+ FnRetType,
+ NRVOCandidate != 0);
+ ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
+ FnRetType, RetValExp);
+ if (Res.isInvalid()) {
+ // FIXME: Cleanup temporaries here, anyway?
+ return StmtError();
+ }
+
+ if (RetValExp) {
+ CheckImplicitConversions(RetValExp, ReturnLoc);
+ RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ }
+
+ RetValExp = Res.takeAs<Expr>();
+ if (RetValExp)
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ }
+
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
+ }
+
+ // If we need to check for the named return value optimization, save the
+ // return statement in our scope for later processing.
+ if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&
+ !CurContext->isDependentContext())
+ FunctionScopes.back()->Returns.push_back(Result);
+
+ return Owned(Result);
+}
+
+StmtResult
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+ if (getCurBlock())
+ return ActOnBlockReturnStmt(ReturnLoc, RetValExp);
+
+ QualType FnRetType;
+ if (const FunctionDecl *FD = getCurFunctionDecl()) {
+ FnRetType = FD->getResultType();
+ if (FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
+ Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
+ << getCurFunctionOrMethodDecl()->getDeclName();
+ } else if (ObjCMethodDecl *MD = getCurMethodDecl())
+ FnRetType = MD->getResultType();
+ else // If we don't have a function/method context, bail.
+ return StmtError();
+
+ ReturnStmt *Result = 0;
+ if (FnRetType->isVoidType()) {
+ if (RetValExp && !RetValExp->isTypeDependent()) {
+ // C99 6.8.6.4p1 (ext_ since GCC warns)
+ unsigned D = diag::ext_return_has_expr;
+ if (RetValExp->getType()->isVoidType())
+ D = diag::ext_return_has_void_expr;
+ else {
+ IgnoredValueConversions(RetValExp);
+ ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid);
+ }
+
+ // return (some void expression); is legal in C++.
+ if (D != diag::ext_return_has_void_expr ||
+ !getLangOptions().CPlusPlus) {
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ Diag(ReturnLoc, D)
+ << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl)
+ << RetValExp->getSourceRange();
+ }
+
+ CheckImplicitConversions(RetValExp, ReturnLoc);
+ RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ }
+
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
+ } else if (!RetValExp && !FnRetType->isDependentType()) {
+ unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4
+ // C99 6.8.6.4p1 (ext_ since GCC warns)
+ if (getLangOptions().C99) DiagID = diag::ext_return_missing_expr;
+
+ if (FunctionDecl *FD = getCurFunctionDecl())
+ Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/;
+ else
+ Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
+ Result = new (Context) ReturnStmt(ReturnLoc);
+ } else {
+ const VarDecl *NRVOCandidate = 0;
+ if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
+ // we have a non-void function with an expression, continue checking
+
+ // C99 6.8.6.4p3(136): The return statement is not an assignment. The
+ // overlap restriction of subclause 6.5.16.1 does not apply to the case of
+ // function return.
+
+ // In C++ the return statement is handled via a copy initialization.
+ // the C version of which boils down to CheckSingleAssignmentConstraints.
+ NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
+ InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
+ FnRetType,
+ NRVOCandidate != 0);
+ ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
+ FnRetType, RetValExp);
+ if (Res.isInvalid()) {
+ // FIXME: Cleanup temporaries here, anyway?
+ return StmtError();
+ }
+
+ RetValExp = Res.takeAs<Expr>();
+ if (RetValExp)
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ }
+
+ if (RetValExp) {
+ CheckImplicitConversions(RetValExp, ReturnLoc);
+ RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ }
+ Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate);
+ }
+
+ // If we need to check for the named return value optimization, save the
+ // return statement in our scope for later processing.
+ if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&
+ !CurContext->isDependentContext())
+ FunctionScopes.back()->Returns.push_back(Result);
+
+ return Owned(Result);
+}
+
+/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
+/// ignore "noop" casts in places where an lvalue is required by an inline asm.
+/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
+/// provide a strong guidance to not use it.
+///
+/// This method checks to see if the argument is an acceptable l-value and
+/// returns false if it is a case we can handle.
+static bool CheckAsmLValue(const Expr *E, Sema &S) {
+ // Type dependent expressions will be checked during instantiation.
+ if (E->isTypeDependent())
+ return false;
+
+ if (E->isLValue())
+ return false; // Cool, this is an lvalue.
+
+ // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
+ // are supposed to allow.
+ const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
+ if (E != E2 && E2->isLValue()) {
+ if (!S.getLangOptions().HeinousExtensions)
+ S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+ << E->getSourceRange();
+ else
+ S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+ << E->getSourceRange();
+ // Accept, even if we emitted an error diagnostic.
+ return false;
+ }
+
+ // None of the above, just randomly invalid non-lvalue.
+ return true;
+}
+
+
+StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple,
+ bool IsVolatile,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg constraints,
+ MultiExprArg exprs,
+ Expr *asmString,
+ MultiExprArg clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm) {
+ unsigned NumClobbers = clobbers.size();
+ StringLiteral **Constraints =
+ reinterpret_cast<StringLiteral**>(constraints.get());
+ Expr **Exprs = exprs.get();
+ StringLiteral *AsmString = cast<StringLiteral>(asmString);
+ StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
+
+ llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
+
+ // The parser verifies that there is a string literal here.
+ if (AsmString->isWide())
+ return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
+ << AsmString->getSourceRange());
+
+ for (unsigned i = 0; i != NumOutputs; i++) {
+ StringLiteral *Literal = Constraints[i];
+ if (Literal->isWide())
+ return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+ << Literal->getSourceRange());
+
+ llvm::StringRef OutputName;
+ if (Names[i])
+ OutputName = Names[i]->getName();
+
+ TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
+ if (!Context.Target.validateOutputConstraint(Info))
+ return StmtError(Diag(Literal->getLocStart(),
+ diag::err_asm_invalid_output_constraint)
+ << Info.getConstraintStr());
+
+ // Check that the output exprs are valid lvalues.
+ Expr *OutputExpr = Exprs[i];
+ if (CheckAsmLValue(OutputExpr, *this)) {
+ return StmtError(Diag(OutputExpr->getLocStart(),
+ diag::err_asm_invalid_lvalue_in_output)
+ << OutputExpr->getSourceRange());
+ }
+
+ OutputConstraintInfos.push_back(Info);
+ }
+
+ llvm::SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
+
+ for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
+ StringLiteral *Literal = Constraints[i];
+ if (Literal->isWide())
+ return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+ << Literal->getSourceRange());
+
+ llvm::StringRef InputName;
+ if (Names[i])
+ InputName = Names[i]->getName();
+
+ TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
+ if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(),
+ NumOutputs, Info)) {
+ return StmtError(Diag(Literal->getLocStart(),
+ diag::err_asm_invalid_input_constraint)
+ << Info.getConstraintStr());
+ }
+
+ Expr *InputExpr = Exprs[i];
+
+ // Only allow void types for memory constraints.
+ if (Info.allowsMemory() && !Info.allowsRegister()) {
+ if (CheckAsmLValue(InputExpr, *this))
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_asm_invalid_lvalue_in_input)
+ << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+ }
+
+ if (Info.allowsRegister()) {
+ if (InputExpr->getType()->isVoidType()) {
+ return StmtError(Diag(InputExpr->getLocStart(),
+ diag::err_asm_invalid_type_in_input)
+ << InputExpr->getType() << Info.getConstraintStr()
+ << InputExpr->getSourceRange());
+ }
+ }
+
+ DefaultFunctionArrayLvalueConversion(Exprs[i]);
+
+ InputConstraintInfos.push_back(Info);
+ }
+
+ // Check that the clobbers are valid.
+ for (unsigned i = 0; i != NumClobbers; i++) {
+ StringLiteral *Literal = Clobbers[i];
+ if (Literal->isWide())
+ return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
+ << Literal->getSourceRange());
+
+ llvm::StringRef Clobber = Literal->getString();
+
+ if (!Context.Target.isValidGCCRegisterName(Clobber))
+ return StmtError(Diag(Literal->getLocStart(),
+ diag::err_asm_unknown_register_name) << Clobber);
+ }
+
+ AsmStmt *NS =
+ new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
+ NumOutputs, NumInputs, Names, Constraints, Exprs,
+ AsmString, NumClobbers, Clobbers, RParenLoc);
+ // Validate the asm string, ensuring it makes sense given the operands we
+ // have.
+ llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
+ unsigned DiagOffs;
+ if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
+ Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
+ << AsmString->getSourceRange();
+ return StmtError();
+ }
+
+ // Validate tied input operands for type mismatches.
+ for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
+ TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+
+ // If this is a tied constraint, verify that the output and input have
+ // either exactly the same type, or that they are int/ptr operands with the
+ // same size (int/long, int*/long, are ok etc).
+ if (!Info.hasTiedOperand()) continue;
+
+ unsigned TiedTo = Info.getTiedOperand();
+ Expr *OutputExpr = Exprs[TiedTo];
+ Expr *InputExpr = Exprs[i+NumOutputs];
+ QualType InTy = InputExpr->getType();
+ QualType OutTy = OutputExpr->getType();
+ if (Context.hasSameType(InTy, OutTy))
+ continue; // All types can be tied to themselves.
+
+ // Decide if the input and output are in the same domain (integer/ptr or
+ // floating point.
+ enum AsmDomain {
+ AD_Int, AD_FP, AD_Other
+ } InputDomain, OutputDomain;
+
+ if (InTy->isIntegerType() || InTy->isPointerType())
+ InputDomain = AD_Int;
+ else if (InTy->isRealFloatingType())
+ InputDomain = AD_FP;
+ else
+ InputDomain = AD_Other;
+
+ if (OutTy->isIntegerType() || OutTy->isPointerType())
+ OutputDomain = AD_Int;
+ else if (OutTy->isRealFloatingType())
+ OutputDomain = AD_FP;
+ else
+ OutputDomain = AD_Other;
+
+ // They are ok if they are the same size and in the same domain. This
+ // allows tying things like:
+ // void* to int*
+ // void* to int if they are the same size.
+ // double to long double if they are the same size.
+ //
+ uint64_t OutSize = Context.getTypeSize(OutTy);
+ uint64_t InSize = Context.getTypeSize(InTy);
+ if (OutSize == InSize && InputDomain == OutputDomain &&
+ InputDomain != AD_Other)
+ continue;
+
+ // If the smaller input/output operand is not mentioned in the asm string,
+ // then we can promote it and the asm string won't notice. Check this
+ // case now.
+ bool SmallerValueMentioned = false;
+ for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
+ AsmStmt::AsmStringPiece &Piece = Pieces[p];
+ if (!Piece.isOperand()) continue;
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == i+NumOutputs) {
+ if (InSize < OutSize) {
+ SmallerValueMentioned = true;
+ break;
+ }
+ }
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == TiedTo) {
+ if (InSize > OutSize) {
+ SmallerValueMentioned = true;
+ break;
+ }
+ }
+ }
+
+ // If the smaller value wasn't mentioned in the asm string, and if the
+ // output was a register, just extend the shorter one to the size of the
+ // larger one.
+ if (!SmallerValueMentioned && InputDomain != AD_Other &&
+ OutputConstraintInfos[TiedTo].allowsRegister())
+ continue;
+
+ Diag(InputExpr->getLocStart(),
+ diag::err_asm_tying_incompatible_types)
+ << InTy << OutTy << OutputExpr->getSourceRange()
+ << InputExpr->getSourceRange();
+ return StmtError();
+ }
+
+ return Owned(NS);
+}
+
+StmtResult
+Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+ SourceLocation RParen, Decl *Parm,
+ Stmt *Body) {
+ VarDecl *Var = cast_or_null<VarDecl>(Parm);
+ if (Var && Var->isInvalidDecl())
+ return StmtError();
+
+ return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body));
+}
+
+StmtResult
+Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
+ return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body));
+}
+
+StmtResult
+Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg CatchStmts, Stmt *Finally) {
+ if (!getLangOptions().ObjCExceptions)
+ Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try";
+
+ getCurFunction()->setHasBranchProtectedScope();
+ unsigned NumCatchStmts = CatchStmts.size();
+ return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try,
+ CatchStmts.release(),
+ NumCatchStmts,
+ Finally));
+}
+
+StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
+ Expr *Throw) {
+ if (Throw) {
+ DefaultLvalueConversion(Throw);
+
+ QualType ThrowType = Throw->getType();
+ // Make sure the expression type is an ObjC pointer or "void *".
+ if (!ThrowType->isDependentType() &&
+ !ThrowType->isObjCObjectPointerType()) {
+ const PointerType *PT = ThrowType->getAs<PointerType>();
+ if (!PT || !PT->getPointeeType()->isVoidType())
+ return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object)
+ << Throw->getType() << Throw->getSourceRange());
+ }
+ }
+
+ return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw));
+}
+
+StmtResult
+Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+ Scope *CurScope) {
+ if (!getLangOptions().ObjCExceptions)
+ Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw";
+
+ if (!Throw) {
+ // @throw without an expression designates a rethrow (which much occur
+ // in the context of an @catch clause).
+ Scope *AtCatchParent = CurScope;
+ while (AtCatchParent && !AtCatchParent->isAtCatchScope())
+ AtCatchParent = AtCatchParent->getParent();
+ if (!AtCatchParent)
+ return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch));
+ }
+
+ return BuildObjCAtThrowStmt(AtLoc, Throw);
+}
+
+StmtResult
+Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
+ Stmt *SyncBody) {
+ getCurFunction()->setHasBranchProtectedScope();
+
+ DefaultLvalueConversion(SyncExpr);
+
+ // Make sure the expression type is an ObjC pointer or "void *".
+ if (!SyncExpr->getType()->isDependentType() &&
+ !SyncExpr->getType()->isObjCObjectPointerType()) {
+ const PointerType *PT = SyncExpr->getType()->getAs<PointerType>();
+ if (!PT || !PT->getPointeeType()->isVoidType())
+ return StmtError(Diag(AtLoc, diag::error_objc_synchronized_expects_object)
+ << SyncExpr->getType() << SyncExpr->getSourceRange());
+ }
+
+ return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody));
+}
+
+/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
+/// and creates a proper catch handler from them.
+StmtResult
+Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+ Stmt *HandlerBlock) {
+ // There's nothing to test that ActOnExceptionDecl didn't already test.
+ return Owned(new (Context) CXXCatchStmt(CatchLoc,
+ cast_or_null<VarDecl>(ExDecl),
+ HandlerBlock));
+}
+
+namespace {
+
+class TypeWithHandler {
+ QualType t;
+ CXXCatchStmt *stmt;
+public:
+ TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
+ : t(type), stmt(statement) {}
+
+ // An arbitrary order is fine as long as it places identical
+ // types next to each other.
+ bool operator<(const TypeWithHandler &y) const {
+ if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
+ return true;
+ if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
+ return false;
+ else
+ return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
+ }
+
+ bool operator==(const TypeWithHandler& other) const {
+ return t == other.t;
+ }
+
+ CXXCatchStmt *getCatchStmt() const { return stmt; }
+ SourceLocation getTypeSpecStartLoc() const {
+ return stmt->getExceptionDecl()->getTypeSpecStartLoc();
+ }
+};
+
+}
+
+/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
+/// handlers and creates a try statement from them.
+StmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ MultiStmtArg RawHandlers) {
+ if (!getLangOptions().Exceptions)
+ Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+
+ unsigned NumHandlers = RawHandlers.size();
+ assert(NumHandlers > 0 &&
+ "The parser shouldn't call this if there are no handlers.");
+ Stmt **Handlers = RawHandlers.get();
+
+ llvm::SmallVector<TypeWithHandler, 8> TypesWithHandlers;
+
+ for (unsigned i = 0; i < NumHandlers; ++i) {
+ CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]);
+ if (!Handler->getExceptionDecl()) {
+ if (i < NumHandlers - 1)
+ return StmtError(Diag(Handler->getLocStart(),
+ diag::err_early_catch_all));
+
+ continue;
+ }
+
+ const QualType CaughtType = Handler->getCaughtType();
+ const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType);
+ TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler));
+ }
+
+ // Detect handlers for the same type as an earlier one.
+ if (NumHandlers > 1) {
+ llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end());
+
+ TypeWithHandler prev = TypesWithHandlers[0];
+ for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) {
+ TypeWithHandler curr = TypesWithHandlers[i];
+
+ if (curr == prev) {
+ Diag(curr.getTypeSpecStartLoc(),
+ diag::warn_exception_caught_by_earlier_handler)
+ << curr.getCatchStmt()->getCaughtType().getAsString();
+ Diag(prev.getTypeSpecStartLoc(),
+ diag::note_previous_exception_handler)
+ << prev.getCatchStmt()->getCaughtType().getAsString();
+ }
+
+ prev = curr;
+ }
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ // FIXME: We should detect handlers that cannot catch anything because an
+ // earlier handler catches a superclass. Need to find a method that is not
+ // quadratic for this.
+ // Neither of these are explicitly forbidden, but every compiler detects them
+ // and warns.
+
+ return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
+ Handlers, NumHandlers));
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
new file mode 100644
index 0000000..f0a0103
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -0,0 +1,6223 @@
+//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements semantic analysis for C++ templates.
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "TreeTransform.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+// Exported for use by Parser.
+SourceRange
+clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
+ unsigned N) {
+ if (!N) return SourceRange();
+ return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
+}
+
+/// \brief Determine whether the declaration found is acceptable as the name
+/// of a template and, if so, return that template declaration. Otherwise,
+/// returns NULL.
+static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
+ NamedDecl *Orig) {
+ NamedDecl *D = Orig->getUnderlyingDecl();
+
+ if (isa<TemplateDecl>(D))
+ return Orig;
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+ // C++ [temp.local]p1:
+ // Like normal (non-template) classes, class templates have an
+ // injected-class-name (Clause 9). The injected-class-name
+ // can be used with or without a template-argument-list. When
+ // it is used without a template-argument-list, it is
+ // equivalent to the injected-class-name followed by the
+ // template-parameters of the class template enclosed in
+ // <>. When it is used with a template-argument-list, it
+ // refers to the specified class template specialization,
+ // which could be the current specialization or another
+ // specialization.
+ if (Record->isInjectedClassName()) {
+ Record = cast<CXXRecordDecl>(Record->getDeclContext());
+ if (Record->getDescribedClassTemplate())
+ return Record->getDescribedClassTemplate();
+
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Record))
+ return Spec->getSpecializedTemplate();
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+ // The set of class templates we've already seen.
+ llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
+ LookupResult::Filter filter = R.makeFilter();
+ while (filter.hasNext()) {
+ NamedDecl *Orig = filter.next();
+ NamedDecl *Repl = isAcceptableTemplateName(C, Orig);
+ if (!Repl)
+ filter.erase();
+ else if (Repl != Orig) {
+
+ // C++ [temp.local]p3:
+ // A lookup that finds an injected-class-name (10.2) can result in an
+ // ambiguity in certain cases (for example, if it is found in more than
+ // one base class). If all of the injected-class-names that are found
+ // refer to specializations of the same class template, and if the name
+ // is followed by a template-argument-list, the reference refers to the
+ // class template itself and not a specialization thereof, and is not
+ // ambiguous.
+ //
+ // FIXME: Will we eventually have to do the same for alias templates?
+ if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))
+ if (!ClassTemplates.insert(ClassTmpl)) {
+ filter.erase();
+ continue;
+ }
+
+ // FIXME: we promote access to public here as a workaround to
+ // the fact that LookupResult doesn't let us remember that we
+ // found this template through a particular injected class name,
+ // which means we end up doing nasty things to the invariants.
+ // Pretending that access is public is *much* safer.
+ filter.replace(Repl, AS_public);
+ }
+ }
+ filter.done();
+}
+
+TemplateNameKind Sema::isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ UnqualifiedId &Name,
+ ParsedType ObjectTypePtr,
+ bool EnteringContext,
+ TemplateTy &TemplateResult,
+ bool &MemberOfUnknownSpecialization) {
+ assert(getLangOptions().CPlusPlus && "No template names in C!");
+
+ DeclarationName TName;
+ MemberOfUnknownSpecialization = false;
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ TName = DeclarationName(Name.Identifier);
+ break;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ TName = Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator);
+ break;
+
+ case UnqualifiedId::IK_LiteralOperatorId:
+ TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
+ break;
+
+ default:
+ return TNK_Non_template;
+ }
+
+ QualType ObjectType = ObjectTypePtr.get();
+
+ LookupResult R(*this, TName, Name.getSourceRange().getBegin(),
+ LookupOrdinaryName);
+ LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
+ MemberOfUnknownSpecialization);
+ if (R.empty()) return TNK_Non_template;
+ if (R.isAmbiguous()) {
+ // Suppress diagnostics; we'll redo this lookup later.
+ R.suppressDiagnostics();
+
+ // FIXME: we might have ambiguous templates, in which case we
+ // should at least parse them properly!
+ return TNK_Non_template;
+ }
+
+ TemplateName Template;
+ TemplateNameKind TemplateKind;
+
+ unsigned ResultCount = R.end() - R.begin();
+ if (ResultCount > 1) {
+ // We assume that we'll preserve the qualifier from a function
+ // template name in other ways.
+ Template = Context.getOverloadedTemplateName(R.begin(), R.end());
+ TemplateKind = TNK_Function_template;
+
+ // We'll do this lookup again later.
+ R.suppressDiagnostics();
+ } else {
+ TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
+
+ if (SS.isSet() && !SS.isInvalid()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ Template = Context.getQualifiedTemplateName(Qualifier,
+ hasTemplateKeyword, TD);
+ } else {
+ Template = TemplateName(TD);
+ }
+
+ if (isa<FunctionTemplateDecl>(TD)) {
+ TemplateKind = TNK_Function_template;
+
+ // We'll do this lookup again later.
+ R.suppressDiagnostics();
+ } else {
+ assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD));
+ TemplateKind = TNK_Type_template;
+ }
+ }
+
+ TemplateResult = TemplateTy::make(Template);
+ return TemplateKind;
+}
+
+bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind) {
+ // We can't recover unless there's a dependent scope specifier preceding the
+ // template name.
+ // FIXME: Typo correction?
+ if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
+ computeDeclContext(*SS))
+ return false;
+
+ // The code is missing a 'template' keyword prior to the dependent template
+ // name.
+ NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep();
+ Diag(IILoc, diag::err_template_kw_missing)
+ << Qualifier << II.getName()
+ << FixItHint::CreateInsertion(IILoc, "template ");
+ SuggestedTemplate
+ = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
+ SuggestedKind = TNK_Dependent_template_name;
+ return true;
+}
+
+void Sema::LookupTemplateName(LookupResult &Found,
+ Scope *S, CXXScopeSpec &SS,
+ QualType ObjectType,
+ bool EnteringContext,
+ bool &MemberOfUnknownSpecialization) {
+ // Determine where to perform name lookup
+ MemberOfUnknownSpecialization = false;
+ DeclContext *LookupCtx = 0;
+ bool isDependent = false;
+ if (!ObjectType.isNull()) {
+ // This nested-name-specifier occurs in a member access expression, e.g.,
+ // x->B::f, and we are looking into the type of the object.
+ assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
+ LookupCtx = computeDeclContext(ObjectType);
+ isDependent = ObjectType->isDependentType();
+ assert((isDependent || !ObjectType->isIncompleteType()) &&
+ "Caller should have completed object type");
+ } else if (SS.isSet()) {
+ // This nested-name-specifier occurs after another nested-name-specifier,
+ // so long into the context associated with the prior nested-name-specifier.
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ isDependent = isDependentScopeSpecifier(SS);
+
+ // The declaration context must be complete.
+ if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
+ return;
+ }
+
+ bool ObjectTypeSearchedInScope = false;
+ if (LookupCtx) {
+ // Perform "qualified" name lookup into the declaration context we
+ // computed, which is either the type of the base of a member access
+ // expression or the declaration context associated with a prior
+ // nested-name-specifier.
+ LookupQualifiedName(Found, LookupCtx);
+
+ if (!ObjectType.isNull() && Found.empty()) {
+ // C++ [basic.lookup.classref]p1:
+ // In a class member access expression (5.2.5), if the . or -> token is
+ // immediately followed by an identifier followed by a <, the
+ // identifier must be looked up to determine whether the < is the
+ // beginning of a template argument list (14.2) or a less-than operator.
+ // The identifier is first looked up in the class of the object
+ // expression. If the identifier is not found, it is then looked up in
+ // the context of the entire postfix-expression and shall name a class
+ // or function template.
+ if (S) LookupName(Found, S);
+ ObjectTypeSearchedInScope = true;
+ }
+ } else if (isDependent && (!S || ObjectType.isNull())) {
+ // We cannot look into a dependent object type or nested nme
+ // specifier.
+ MemberOfUnknownSpecialization = true;
+ return;
+ } else {
+ // Perform unqualified name lookup in the current scope.
+ LookupName(Found, S);
+ }
+
+ if (Found.empty() && !isDependent) {
+ // If we did not find any names, attempt to correct any typos.
+ DeclarationName Name = Found.getLookupName();
+ if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
+ false, CTC_CXXCasts)) {
+ FilterAcceptableTemplateNames(Context, Found);
+ if (!Found.empty()) {
+ if (LookupCtx)
+ Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
+ << Name << LookupCtx << Found.getLookupName() << SS.getRange()
+ << FixItHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ else
+ Diag(Found.getNameLoc(), diag::err_no_template_suggest)
+ << Name << Found.getLookupName()
+ << FixItHint::CreateReplacement(Found.getNameLoc(),
+ Found.getLookupName().getAsString());
+ if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
+ Diag(Template->getLocation(), diag::note_previous_decl)
+ << Template->getDeclName();
+ }
+ } else {
+ Found.clear();
+ Found.setLookupName(Name);
+ }
+ }
+
+ FilterAcceptableTemplateNames(Context, Found);
+ if (Found.empty()) {
+ if (isDependent)
+ MemberOfUnknownSpecialization = true;
+ return;
+ }
+
+ if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
+ // C++ [basic.lookup.classref]p1:
+ // [...] If the lookup in the class of the object expression finds a
+ // template, the name is also looked up in the context of the entire
+ // postfix-expression and [...]
+ //
+ LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
+ LookupOrdinaryName);
+ LookupName(FoundOuter, S);
+ FilterAcceptableTemplateNames(Context, FoundOuter);
+
+ if (FoundOuter.empty()) {
+ // - if the name is not found, the name found in the class of the
+ // object expression is used, otherwise
+ } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) {
+ // - if the name is found in the context of the entire
+ // postfix-expression and does not name a class template, the name
+ // found in the class of the object expression is used, otherwise
+ } else if (!Found.isSuppressingDiagnostics()) {
+ // - if the name found is a class template, it must refer to the same
+ // entity as the one found in the class of the object expression,
+ // otherwise the program is ill-formed.
+ if (!Found.isSingleResult() ||
+ Found.getFoundDecl()->getCanonicalDecl()
+ != FoundOuter.getFoundDecl()->getCanonicalDecl()) {
+ Diag(Found.getNameLoc(),
+ diag::ext_nested_name_member_ref_lookup_ambiguous)
+ << Found.getLookupName()
+ << ObjectType;
+ Diag(Found.getRepresentativeDecl()->getLocation(),
+ diag::note_ambig_member_ref_object_type)
+ << ObjectType;
+ Diag(FoundOuter.getFoundDecl()->getLocation(),
+ diag::note_ambig_member_ref_scope);
+
+ // Recover by taking the template that we found in the object
+ // expression's type.
+ }
+ }
+ }
+}
+
+/// ActOnDependentIdExpression - Handle a dependent id-expression that
+/// was just parsed. This is only possible with an explicit scope
+/// specifier naming a dependent type.
+ExprResult
+Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+ DeclContext *DC = getFunctionLevelDeclContext();
+
+ if (!isAddressOfOperand &&
+ isa<CXXMethodDecl>(DC) &&
+ cast<CXXMethodDecl>(DC)->isInstance()) {
+ QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
+
+ // Since the 'this' expression is synthesized, we don't need to
+ // perform the double-lookup check.
+ NamedDecl *FirstQualifierInScope = 0;
+
+ return Owned(CXXDependentScopeMemberExpr::Create(Context,
+ /*This*/ 0, ThisType,
+ /*IsArrow*/ true,
+ /*Op*/ SourceLocation(),
+ Qualifier, SS.getRange(),
+ FirstQualifierInScope,
+ NameInfo,
+ TemplateArgs));
+ }
+
+ return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs);
+}
+
+ExprResult
+Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ return Owned(DependentScopeDeclRefExpr::Create(Context,
+ static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getRange(),
+ NameInfo,
+ TemplateArgs));
+}
+
+/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
+/// that the template parameter 'PrevDecl' is being shadowed by a new
+/// declaration at location Loc. Returns true to indicate that this is
+/// an error, and false otherwise.
+bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
+ assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
+
+ // Microsoft Visual C++ permits template parameters to be shadowed.
+ if (getLangOptions().Microsoft)
+ return false;
+
+ // C++ [temp.local]p4:
+ // A template-parameter shall not be redeclared within its
+ // scope (including nested scopes).
+ Diag(Loc, diag::err_template_param_shadow)
+ << cast<NamedDecl>(PrevDecl)->getDeclName();
+ Diag(PrevDecl->getLocation(), diag::note_template_param_here);
+ return true;
+}
+
+/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
+/// the parameter D to reference the templated declaration and return a pointer
+/// to the template declaration. Otherwise, do nothing to D and return null.
+TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
+ if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) {
+ D = Temp->getTemplatedDecl();
+ return Temp;
+ }
+ return 0;
+}
+
+ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const {
+ assert(Kind == Template &&
+ "Only template template arguments can be pack expansions here");
+ assert(getAsTemplate().get().containsUnexpandedParameterPack() &&
+ "Template template argument pack expansion without packs");
+ ParsedTemplateArgument Result(*this);
+ Result.EllipsisLoc = EllipsisLoc;
+ return Result;
+}
+
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+ const ParsedTemplateArgument &Arg) {
+
+ switch (Arg.getKind()) {
+ case ParsedTemplateArgument::Type: {
+ TypeSourceInfo *DI;
+ QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+ if (!DI)
+ DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
+ return TemplateArgumentLoc(TemplateArgument(T), DI);
+ }
+
+ case ParsedTemplateArgument::NonType: {
+ Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case ParsedTemplateArgument::Template: {
+ TemplateName Template = Arg.getAsTemplate().get();
+ TemplateArgument TArg;
+ if (Arg.getEllipsisLoc().isValid())
+ TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+ else
+ TArg = Template;
+ return TemplateArgumentLoc(TArg,
+ Arg.getScopeSpec().getRange(),
+ Arg.getLocation(),
+ Arg.getEllipsisLoc());
+ }
+ }
+
+ llvm_unreachable("Unhandled parsed template argument");
+ return TemplateArgumentLoc();
+}
+
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
+ TemplateArgumentListInfo &TemplateArgs) {
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+ TemplateArgs.addArgument(translateTemplateArgument(*this,
+ TemplateArgsIn[I]));
+}
+
+/// ActOnTypeParameter - Called when a C++ template type parameter
+/// (e.g., "typename T") has been parsed. Typename specifies whether
+/// the keyword "typename" was used to declare the type parameter
+/// (otherwise, "class" was used), and KeyLoc is the location of the
+/// "class" or "typename" keyword. ParamName is the name of the
+/// parameter (NULL indicates an unnamed template parameter) and
+/// ParamName is the location of the parameter name (if any).
+/// If the type parameter has a default argument, it will be added
+/// later via ActOnTypeParameterDefault.
+Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg) {
+ assert(S->isTemplateParamScope() &&
+ "Template type parameter not in template parameter scope!");
+ bool Invalid = false;
+
+ if (ParamName) {
+ NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc,
+ LookupOrdinaryName,
+ ForRedeclaration);
+ if (PrevDecl && PrevDecl->isTemplateParameter())
+ Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
+ PrevDecl);
+ }
+
+ SourceLocation Loc = ParamNameLoc;
+ if (!ParamName)
+ Loc = KeyLoc;
+
+ TemplateTypeParmDecl *Param
+ = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ Loc, Depth, Position, ParamName, Typename,
+ Ellipsis);
+ if (Invalid)
+ Param->setInvalidDecl();
+
+ if (ParamName) {
+ // Add the template parameter into the current scope.
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
+ }
+
+ // C++0x [temp.param]p9:
+ // A default template-argument may be specified for any kind of
+ // template-parameter that is not a template parameter pack.
+ if (DefaultArg && Ellipsis) {
+ Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+ DefaultArg = ParsedType();
+ }
+
+ // Handle the default argument, if provided.
+ if (DefaultArg) {
+ TypeSourceInfo *DefaultTInfo;
+ GetTypeFromParser(DefaultArg, &DefaultTInfo);
+
+ assert(DefaultTInfo && "expected source information for type");
+
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo,
+ UPPC_DefaultArgument))
+ return Param;
+
+ // Check the template argument itself.
+ if (CheckTemplateArgument(Param, DefaultTInfo)) {
+ Param->setInvalidDecl();
+ return Param;
+ }
+
+ Param->setDefaultArgument(DefaultTInfo, false);
+ }
+
+ return Param;
+}
+
+/// \brief Check that the type of a non-type template parameter is
+/// well-formed.
+///
+/// \returns the (possibly-promoted) parameter type if valid;
+/// otherwise, produces a diagnostic and returns a NULL type.
+QualType
+Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+ // We don't allow variably-modified types as the type of non-type template
+ // parameters.
+ if (T->isVariablyModifiedType()) {
+ Diag(Loc, diag::err_variably_modified_nontype_template_param)
+ << T;
+ return QualType();
+ }
+
+ // C++ [temp.param]p4:
+ //
+ // A non-type template-parameter shall have one of the following
+ // (optionally cv-qualified) types:
+ //
+ // -- integral or enumeration type,
+ if (T->isIntegralOrEnumerationType() ||
+ // -- pointer to object or pointer to function,
+ T->isPointerType() ||
+ // -- reference to object or reference to function,
+ T->isReferenceType() ||
+ // -- pointer to member.
+ T->isMemberPointerType() ||
+ // If T is a dependent type, we can't do the check now, so we
+ // assume that it is well-formed.
+ T->isDependentType())
+ return T;
+ // C++ [temp.param]p8:
+ //
+ // A non-type template-parameter of type "array of T" or
+ // "function returning T" is adjusted to be of type "pointer to
+ // T" or "pointer to function returning T", respectively.
+ else if (T->isArrayType())
+ // FIXME: Keep the type prior to promotion?
+ return Context.getArrayDecayedType(T);
+ else if (T->isFunctionType())
+ // FIXME: Keep the type prior to promotion?
+ return Context.getPointerType(T);
+
+ Diag(Loc, diag::err_template_nontype_parm_bad_type)
+ << T;
+
+ return QualType();
+}
+
+Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ Expr *Default) {
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
+
+ assert(S->isTemplateParamScope() &&
+ "Non-type template parameter not in template parameter scope!");
+ bool Invalid = false;
+
+ IdentifierInfo *ParamName = D.getIdentifier();
+ if (ParamName) {
+ NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(),
+ LookupOrdinaryName,
+ ForRedeclaration);
+ if (PrevDecl && PrevDecl->isTemplateParameter())
+ Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+ PrevDecl);
+ }
+
+ T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
+ if (T.isNull()) {
+ T = Context.IntTy; // Recover with an 'int' type.
+ Invalid = true;
+ }
+
+ bool IsParameterPack = D.hasEllipsis();
+ NonTypeTemplateParmDecl *Param
+ = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ D.getIdentifierLoc(),
+ Depth, Position, ParamName, T,
+ IsParameterPack, TInfo);
+ if (Invalid)
+ Param->setInvalidDecl();
+
+ if (D.getIdentifier()) {
+ // Add the template parameter into the current scope.
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
+ }
+
+ // C++0x [temp.param]p9:
+ // A default template-argument may be specified for any kind of
+ // template-parameter that is not a template parameter pack.
+ if (Default && IsParameterPack) {
+ Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+ Default = 0;
+ }
+
+ // Check the well-formedness of the default template argument, if provided.
+ if (Default) {
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
+ return Param;
+
+ TemplateArgument Converted;
+ if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
+ Param->setInvalidDecl();
+ return Param;
+ }
+
+ Param->setDefaultArgument(Default, false);
+ }
+
+ return Param;
+}
+
+/// ActOnTemplateTemplateParameter - Called when a C++ template template
+/// parameter (e.g. T in template <template <typename> class T> class array)
+/// has been parsed. S is the current scope.
+Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
+ SourceLocation EllipsisLoc,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedTemplateArgument Default) {
+ assert(S->isTemplateParamScope() &&
+ "Template template parameter not in template parameter scope!");
+
+ // Construct the parameter object.
+ bool IsParameterPack = EllipsisLoc.isValid();
+ // FIXME: Pack-ness is dropped
+ TemplateTemplateParmDecl *Param =
+ TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
+ NameLoc.isInvalid()? TmpLoc : NameLoc,
+ Depth, Position, IsParameterPack,
+ Name, Params);
+
+ // If the template template parameter has a name, then link the identifier
+ // into the scope and lookup mechanisms.
+ if (Name) {
+ S->AddDecl(Param);
+ IdResolver.AddDecl(Param);
+ }
+
+ if (Params->size() == 0) {
+ Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
+ << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
+ Param->setInvalidDecl();
+ }
+
+ // C++0x [temp.param]p9:
+ // A default template-argument may be specified for any kind of
+ // template-parameter that is not a template parameter pack.
+ if (IsParameterPack && !Default.isInvalid()) {
+ Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+ Default = ParsedTemplateArgument();
+ }
+
+ if (!Default.isInvalid()) {
+ // Check only that we have a template template argument. We don't want to
+ // try to check well-formedness now, because our template template parameter
+ // might have dependent types in its template parameters, which we wouldn't
+ // be able to match now.
+ //
+ // If none of the template template parameter's template arguments mention
+ // other template parameters, we could actually perform more checking here.
+ // However, it isn't worth doing.
+ TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+ if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+ Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+ << DefaultArg.getSourceRange();
+ return Param;
+ }
+
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(),
+ DefaultArg.getArgument().getAsTemplate(),
+ UPPC_DefaultArgument))
+ return Param;
+
+ Param->setDefaultArgument(DefaultArg, false);
+ }
+
+ return Param;
+}
+
+/// ActOnTemplateParameterList - Builds a TemplateParameterList that
+/// contains the template parameters in Params/NumParams.
+Sema::TemplateParamsTy *
+Sema::ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ Decl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc) {
+ if (ExportLoc.isValid())
+ Diag(ExportLoc, diag::warn_template_export_unsupported);
+
+ return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
+ (NamedDecl**)Params, NumParams,
+ RAngleLoc);
+}
+
+static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
+ if (SS.isSet())
+ T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getRange());
+}
+
+DeclResult
+Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ TemplateParameterList *TemplateParams,
+ AccessSpecifier AS) {
+ assert(TemplateParams && TemplateParams->size() > 0 &&
+ "No template parameters");
+ assert(TUK != TUK_Reference && "Can only declare or define class templates");
+ bool Invalid = false;
+
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return true;
+
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+ assert(Kind != TTK_Enum && "can't build template of enumerated type");
+
+ // There is no such thing as an unnamed class template.
+ if (!Name) {
+ Diag(KWLoc, diag::err_template_unnamed_class);
+ return true;
+ }
+
+ // Find any previous declaration with this name.
+ DeclContext *SemanticContext;
+ LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ if (SS.isNotEmpty() && !SS.isInvalid()) {
+ SemanticContext = computeDeclContext(SS, true);
+ if (!SemanticContext) {
+ // FIXME: Produce a reasonable diagnostic here
+ return true;
+ }
+
+ if (RequireCompleteDeclContext(SS, SemanticContext))
+ return true;
+
+ LookupQualifiedName(Previous, SemanticContext);
+ } else {
+ SemanticContext = CurContext;
+ LookupName(Previous, S);
+ }
+
+ if (Previous.isAmbiguous())
+ return true;
+
+ NamedDecl *PrevDecl = 0;
+ if (Previous.begin() != Previous.end())
+ PrevDecl = (*Previous.begin())->getUnderlyingDecl();
+
+ // If there is a previous declaration with the same name, check
+ // whether this is a valid redeclaration.
+ ClassTemplateDecl *PrevClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+ // We may have found the injected-class-name of a class template,
+ // class template partial specialization, or class template specialization.
+ // In these cases, grab the template that is being defined or specialized.
+ if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
+ cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+ PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+ PrevClassTemplate
+ = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+ if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+ PrevClassTemplate
+ = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+ ->getSpecializedTemplate();
+ }
+ }
+
+ if (TUK == TUK_Friend) {
+ // C++ [namespace.memdef]p3:
+ // [...] When looking for a prior declaration of a class or a function
+ // declared as a friend, and when the name of the friend class or
+ // function is neither a qualified name nor a template-id, scopes outside
+ // the innermost enclosing namespace scope are not considered.
+ if (!SS.isSet()) {
+ DeclContext *OutermostContext = CurContext;
+ while (!OutermostContext->isFileContext())
+ OutermostContext = OutermostContext->getLookupParent();
+
+ if (PrevDecl &&
+ (OutermostContext->Equals(PrevDecl->getDeclContext()) ||
+ OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
+ SemanticContext = PrevDecl->getDeclContext();
+ } else {
+ // Declarations in outer scopes don't matter. However, the outermost
+ // context we computed is the semantic context for our new
+ // declaration.
+ PrevDecl = PrevClassTemplate = 0;
+ SemanticContext = OutermostContext;
+ }
+ }
+
+ if (CurContext->isDependentContext()) {
+ // If this is a dependent context, we don't want to link the friend
+ // class template to the template in scope, because that would perform
+ // checking of the template parameter lists that can't be performed
+ // until the outer context is instantiated.
+ PrevDecl = PrevClassTemplate = 0;
+ }
+ } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
+ PrevDecl = PrevClassTemplate = 0;
+
+ if (PrevClassTemplate) {
+ // Ensure that the template parameter lists are compatible.
+ if (!TemplateParameterListsAreEqual(TemplateParams,
+ PrevClassTemplate->getTemplateParameters(),
+ /*Complain=*/true,
+ TPL_TemplateMatch))
+ return true;
+
+ // C++ [temp.class]p4:
+ // In a redeclaration, partial specialization, explicit
+ // specialization or explicit instantiation of a class template,
+ // the class-key shall agree in kind with the original class
+ // template declaration (7.1.5.3).
+ RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
+ if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, KWLoc, *Name)) {
+ Diag(KWLoc, diag::err_use_with_wrong_tag)
+ << Name
+ << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
+ Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
+ Kind = PrevRecordDecl->getTagKind();
+ }
+
+ // Check for redefinition of this class template.
+ if (TUK == TUK_Definition) {
+ if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // FIXME: Would it make sense to try to "forget" the previous
+ // definition, as part of error recovery?
+ return true;
+ }
+ }
+ } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ } else if (PrevDecl) {
+ // C++ [temp]p5:
+ // A class template shall not have the same name as any other
+ // template, class, function, object, enumeration, enumerator,
+ // namespace, or type in the same scope (3.3), except as specified
+ // in (14.5.4).
+ Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ return true;
+ }
+
+ // Check the template parameter list of this declaration, possibly
+ // merging in the template parameter list from the previous class
+ // template declaration.
+ if (CheckTemplateParameterList(TemplateParams,
+ PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
+ (SS.isSet() && SemanticContext &&
+ SemanticContext->isRecord() &&
+ SemanticContext->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TPC_ClassTemplate))
+ Invalid = true;
+
+ if (SS.isSet()) {
+ // If the name of the template was qualified, we must be defining the
+ // template out-of-line.
+ if (!SS.isInvalid() && !Invalid && !PrevClassTemplate &&
+ !(TUK == TUK_Friend && CurContext->isDependentContext()))
+ Diag(NameLoc, diag::err_member_def_does_not_match)
+ << Name << SemanticContext << SS.getRange();
+ }
+
+ CXXRecordDecl *NewClass =
+ CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc,
+ PrevClassTemplate?
+ PrevClassTemplate->getTemplatedDecl() : 0,
+ /*DelayTypeCreation=*/true);
+ SetNestedNameSpecifier(NewClass, SS);
+
+ ClassTemplateDecl *NewTemplate
+ = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
+ DeclarationName(Name), TemplateParams,
+ NewClass, PrevClassTemplate);
+ NewClass->setDescribedClassTemplate(NewTemplate);
+
+ // Build the type for the class template declaration now.
+ QualType T = NewTemplate->getInjectedClassNameSpecialization();
+ T = Context.getInjectedClassNameType(NewClass, T);
+ assert(T->isDependentType() && "Class template type is not dependent?");
+ (void)T;
+
+ // If we are providing an explicit specialization of a member that is a
+ // class template, make a note of that.
+ if (PrevClassTemplate &&
+ PrevClassTemplate->getInstantiatedFromMemberTemplate())
+ PrevClassTemplate->setMemberSpecialization();
+
+ // Set the access specifier.
+ if (!Invalid && TUK != TUK_Friend)
+ SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
+
+ // Set the lexical context of these templates
+ NewClass->setLexicalDeclContext(CurContext);
+ NewTemplate->setLexicalDeclContext(CurContext);
+
+ if (TUK == TUK_Definition)
+ NewClass->startDefinition();
+
+ if (Attr)
+ ProcessDeclAttributeList(S, NewClass, Attr);
+
+ if (TUK != TUK_Friend)
+ PushOnScopeChains(NewTemplate, S);
+ else {
+ if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
+ NewTemplate->setAccess(PrevClassTemplate->getAccess());
+ NewClass->setAccess(PrevClassTemplate->getAccess());
+ }
+
+ NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+ PrevClassTemplate != NULL);
+
+ // Friend templates are visible in fairly strange ways.
+ if (!CurContext->isDependentContext()) {
+ DeclContext *DC = SemanticContext->getRedeclContext();
+ DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(NewTemplate, EnclosingScope,
+ /* AddToContext = */ false);
+ }
+
+ FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+ NewClass->getLocation(),
+ NewTemplate,
+ /*FIXME:*/NewClass->getLocation());
+ Friend->setAccess(AS_public);
+ CurContext->addDecl(Friend);
+ }
+
+ if (Invalid) {
+ NewTemplate->setInvalidDecl();
+ NewClass->setInvalidDecl();
+ }
+ return NewTemplate;
+}
+
+/// \brief Diagnose the presence of a default template argument on a
+/// template parameter, which is ill-formed in certain contexts.
+///
+/// \returns true if the default template argument should be dropped.
+static bool DiagnoseDefaultTemplateArgument(Sema &S,
+ Sema::TemplateParamListContext TPC,
+ SourceLocation ParamLoc,
+ SourceRange DefArgRange) {
+ switch (TPC) {
+ case Sema::TPC_ClassTemplate:
+ return false;
+
+ case Sema::TPC_FunctionTemplate:
+ case Sema::TPC_FriendFunctionTemplateDefinition:
+ // C++ [temp.param]p9:
+ // A default template-argument shall not be specified in a
+ // function template declaration or a function template
+ // definition [...]
+ // If a friend function template declaration specifies a default
+ // template-argument, that declaration shall be a definition and shall be
+ // the only declaration of the function template in the translation unit.
+ // (C++98/03 doesn't have this wording; see DR226).
+ if (!S.getLangOptions().CPlusPlus0x)
+ S.Diag(ParamLoc,
+ diag::ext_template_parameter_default_in_function_template)
+ << DefArgRange;
+ return false;
+
+ case Sema::TPC_ClassTemplateMember:
+ // C++0x [temp.param]p9:
+ // A default template-argument shall not be specified in the
+ // template-parameter-lists of the definition of a member of a
+ // class template that appears outside of the member's class.
+ S.Diag(ParamLoc, diag::err_template_parameter_default_template_member)
+ << DefArgRange;
+ return true;
+
+ case Sema::TPC_FriendFunctionTemplate:
+ // C++ [temp.param]p9:
+ // A default template-argument shall not be specified in a
+ // friend template declaration.
+ S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template)
+ << DefArgRange;
+ return true;
+
+ // FIXME: C++0x [temp.param]p9 allows default template-arguments
+ // for friend function templates if there is only a single
+ // declaration (and it is a definition). Strange!
+ }
+
+ return false;
+}
+
+/// \brief Check for unexpanded parameter packs within the template parameters
+/// of a template template parameter, recursively.
+bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP){
+ TemplateParameterList *Params = TTP->getTemplateParameters();
+ for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+ NamedDecl *P = Params->getParam(I);
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
+ if (S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(),
+ NTTP->getTypeSourceInfo(),
+ Sema::UPPC_NonTypeTemplateParameterType))
+ return true;
+
+ continue;
+ }
+
+ if (TemplateTemplateParmDecl *InnerTTP
+ = dyn_cast<TemplateTemplateParmDecl>(P))
+ if (DiagnoseUnexpandedParameterPacks(S, InnerTTP))
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Checks the validity of a template parameter list, possibly
+/// considering the template parameter list from a previous
+/// declaration.
+///
+/// If an "old" template parameter list is provided, it must be
+/// equivalent (per TemplateParameterListsAreEqual) to the "new"
+/// template parameter list.
+///
+/// \param NewParams Template parameter list for a new template
+/// declaration. This template parameter list will be updated with any
+/// default arguments that are carried through from the previous
+/// template parameter list.
+///
+/// \param OldParams If provided, template parameter list from a
+/// previous declaration of the same template. Default template
+/// arguments will be merged from the old template parameter list to
+/// the new template parameter list.
+///
+/// \param TPC Describes the context in which we are checking the given
+/// template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
+bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
+ TemplateParameterList *OldParams,
+ TemplateParamListContext TPC) {
+ bool Invalid = false;
+
+ // C++ [temp.param]p10:
+ // The set of default template-arguments available for use with a
+ // template declaration or definition is obtained by merging the
+ // default arguments from the definition (if in scope) and all
+ // declarations in scope in the same way default function
+ // arguments are (8.3.6).
+ bool SawDefaultArgument = false;
+ SourceLocation PreviousDefaultArgLoc;
+
+ bool SawParameterPack = false;
+ SourceLocation ParameterPackLoc;
+
+ // Dummy initialization to avoid warnings.
+ TemplateParameterList::iterator OldParam = NewParams->end();
+ if (OldParams)
+ OldParam = OldParams->begin();
+
+ bool RemoveDefaultArguments = false;
+ for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+ NewParamEnd = NewParams->end();
+ NewParam != NewParamEnd; ++NewParam) {
+ // Variables used to diagnose redundant default arguments
+ bool RedundantDefaultArg = false;
+ SourceLocation OldDefaultLoc;
+ SourceLocation NewDefaultLoc;
+
+ // Variables used to diagnose missing default arguments
+ bool MissingDefaultArg = false;
+
+ // C++0x [temp.param]p11:
+ // If a template parameter of a primary class template is a template
+ // parameter pack, it shall be the last template parameter.
+ if (SawParameterPack && TPC == TPC_ClassTemplate) {
+ Diag(ParameterPackLoc,
+ diag::err_template_param_pack_must_be_last_template_parameter);
+ Invalid = true;
+ }
+
+ if (TemplateTypeParmDecl *NewTypeParm
+ = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
+ // Check the presence of a default argument here.
+ if (NewTypeParm->hasDefaultArgument() &&
+ DiagnoseDefaultTemplateArgument(*this, TPC,
+ NewTypeParm->getLocation(),
+ NewTypeParm->getDefaultArgumentInfo()->getTypeLoc()
+ .getSourceRange()))
+ NewTypeParm->removeDefaultArgument();
+
+ // Merge default arguments for template type parameters.
+ TemplateTypeParmDecl *OldTypeParm
+ = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
+
+ if (NewTypeParm->isParameterPack()) {
+ assert(!NewTypeParm->hasDefaultArgument() &&
+ "Parameter packs can't have a default argument!");
+ SawParameterPack = true;
+ ParameterPackLoc = NewTypeParm->getLocation();
+ } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
+ NewTypeParm->hasDefaultArgument()) {
+ OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
+ NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
+ SawDefaultArgument = true;
+ RedundantDefaultArg = true;
+ PreviousDefaultArgLoc = NewDefaultLoc;
+ } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
+ // Merge the default argument from the old declaration to the
+ // new declaration.
+ SawDefaultArgument = true;
+ NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
+ true);
+ PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
+ } else if (NewTypeParm->hasDefaultArgument()) {
+ SawDefaultArgument = true;
+ PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc();
+ } else if (SawDefaultArgument)
+ MissingDefaultArg = true;
+ } else if (NonTypeTemplateParmDecl *NewNonTypeParm
+ = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) {
+ // Check for unexpanded parameter packs.
+ if (DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(),
+ NewNonTypeParm->getTypeSourceInfo(),
+ UPPC_NonTypeTemplateParameterType)) {
+ Invalid = true;
+ continue;
+ }
+
+ // Check the presence of a default argument here.
+ if (NewNonTypeParm->hasDefaultArgument() &&
+ DiagnoseDefaultTemplateArgument(*this, TPC,
+ NewNonTypeParm->getLocation(),
+ NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
+ NewNonTypeParm->removeDefaultArgument();
+ }
+
+ // Merge default arguments for non-type template parameters
+ NonTypeTemplateParmDecl *OldNonTypeParm
+ = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
+ if (NewNonTypeParm->isParameterPack()) {
+ assert(!NewNonTypeParm->hasDefaultArgument() &&
+ "Parameter packs can't have a default argument!");
+ SawParameterPack = true;
+ ParameterPackLoc = NewNonTypeParm->getLocation();
+ } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
+ NewNonTypeParm->hasDefaultArgument()) {
+ OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
+ NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
+ SawDefaultArgument = true;
+ RedundantDefaultArg = true;
+ PreviousDefaultArgLoc = NewDefaultLoc;
+ } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
+ // Merge the default argument from the old declaration to the
+ // new declaration.
+ SawDefaultArgument = true;
+ // FIXME: We need to create a new kind of "default argument"
+ // expression that points to a previous non-type template
+ // parameter.
+ NewNonTypeParm->setDefaultArgument(
+ OldNonTypeParm->getDefaultArgument(),
+ /*Inherited=*/ true);
+ PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
+ } else if (NewNonTypeParm->hasDefaultArgument()) {
+ SawDefaultArgument = true;
+ PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc();
+ } else if (SawDefaultArgument)
+ MissingDefaultArg = true;
+ } else {
+ // Check the presence of a default argument here.
+ TemplateTemplateParmDecl *NewTemplateParm
+ = cast<TemplateTemplateParmDecl>(*NewParam);
+
+ // Check for unexpanded parameter packs, recursively.
+ if (DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
+ Invalid = true;
+ continue;
+ }
+
+ if (NewTemplateParm->hasDefaultArgument() &&
+ DiagnoseDefaultTemplateArgument(*this, TPC,
+ NewTemplateParm->getLocation(),
+ NewTemplateParm->getDefaultArgument().getSourceRange()))
+ NewTemplateParm->removeDefaultArgument();
+
+ // Merge default arguments for template template parameters
+ TemplateTemplateParmDecl *OldTemplateParm
+ = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
+ if (NewTemplateParm->isParameterPack()) {
+ assert(!NewTemplateParm->hasDefaultArgument() &&
+ "Parameter packs can't have a default argument!");
+ SawParameterPack = true;
+ ParameterPackLoc = NewTemplateParm->getLocation();
+ } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
+ NewTemplateParm->hasDefaultArgument()) {
+ OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+ NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
+ SawDefaultArgument = true;
+ RedundantDefaultArg = true;
+ PreviousDefaultArgLoc = NewDefaultLoc;
+ } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
+ // Merge the default argument from the old declaration to the
+ // new declaration.
+ SawDefaultArgument = true;
+ // FIXME: We need to create a new kind of "default argument" expression
+ // that points to a previous template template parameter.
+ NewTemplateParm->setDefaultArgument(
+ OldTemplateParm->getDefaultArgument(),
+ /*Inherited=*/ true);
+ PreviousDefaultArgLoc
+ = OldTemplateParm->getDefaultArgument().getLocation();
+ } else if (NewTemplateParm->hasDefaultArgument()) {
+ SawDefaultArgument = true;
+ PreviousDefaultArgLoc
+ = NewTemplateParm->getDefaultArgument().getLocation();
+ } else if (SawDefaultArgument)
+ MissingDefaultArg = true;
+ }
+
+ if (RedundantDefaultArg) {
+ // C++ [temp.param]p12:
+ // A template-parameter shall not be given default arguments
+ // by two different declarations in the same scope.
+ Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition);
+ Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg);
+ Invalid = true;
+ } else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) {
+ // C++ [temp.param]p11:
+ // If a template-parameter of a class template has a default
+ // template-argument, each subsequent template-parameter shall either
+ // have a default template-argument supplied or be a template parameter
+ // pack.
+ Diag((*NewParam)->getLocation(),
+ diag::err_template_param_default_arg_missing);
+ Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
+ Invalid = true;
+ RemoveDefaultArguments = true;
+ }
+
+ // If we have an old template parameter list that we're merging
+ // in, move on to the next parameter.
+ if (OldParams)
+ ++OldParam;
+ }
+
+ // We were missing some default arguments at the end of the list, so remove
+ // all of the default arguments.
+ if (RemoveDefaultArguments) {
+ for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+ NewParamEnd = NewParams->end();
+ NewParam != NewParamEnd; ++NewParam) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
+ TTP->removeDefaultArgument();
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
+ NTTP->removeDefaultArgument();
+ else
+ cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
+ }
+ }
+
+ return Invalid;
+}
+
+namespace {
+
+/// A class which looks for a use of a certain level of template
+/// parameter.
+struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
+ typedef RecursiveASTVisitor<DependencyChecker> super;
+
+ unsigned Depth;
+ bool Match;
+
+ DependencyChecker(TemplateParameterList *Params) : Match(false) {
+ NamedDecl *ND = Params->getParam(0);
+ if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
+ Depth = PD->getDepth();
+ } else if (NonTypeTemplateParmDecl *PD =
+ dyn_cast<NonTypeTemplateParmDecl>(ND)) {
+ Depth = PD->getDepth();
+ } else {
+ Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth();
+ }
+ }
+
+ bool Matches(unsigned ParmDepth) {
+ if (ParmDepth >= Depth) {
+ Match = true;
+ return true;
+ }
+ return false;
+ }
+
+ bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ return !Matches(T->getDepth());
+ }
+
+ bool TraverseTemplateName(TemplateName N) {
+ if (TemplateTemplateParmDecl *PD =
+ dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
+ if (Matches(PD->getDepth())) return false;
+ return super::TraverseTemplateName(N);
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (NonTypeTemplateParmDecl *PD =
+ dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+ if (PD->getDepth() == Depth) {
+ Match = true;
+ return false;
+ }
+ }
+ return super::VisitDeclRefExpr(E);
+ }
+};
+}
+
+/// Determines whether a template-id depends on the given parameter
+/// list.
+static bool
+DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId,
+ TemplateParameterList *Params) {
+ DependencyChecker Checker(Params);
+ Checker.TraverseType(QualType(TemplateId, 0));
+ return Checker.Match;
+}
+
+/// \brief Match the given template parameter lists to the given scope
+/// specifier, returning the template parameter list that applies to the
+/// name.
+///
+/// \param DeclStartLoc the start of the declaration that has a scope
+/// specifier or a template parameter list.
+///
+/// \param SS the scope specifier that will be matched to the given template
+/// parameter lists. This scope specifier precedes a qualified name that is
+/// being declared.
+///
+/// \param ParamLists the template parameter lists, from the outermost to the
+/// innermost template parameter lists.
+///
+/// \param NumParamLists the number of template parameter lists in ParamLists.
+///
+/// \param IsFriend Whether to apply the slightly different rules for
+/// matching template parameters to scope specifiers in friend
+/// declarations.
+///
+/// \param IsExplicitSpecialization will be set true if the entity being
+/// declared is an explicit specialization, false otherwise.
+///
+/// \returns the template parameter list, if any, that corresponds to the
+/// name that is preceded by the scope specifier @p SS. This template
+/// parameter list may be have template parameters (if we're declaring a
+/// template) or may have no template parameters (if we're declaring a
+/// template specialization), or may be NULL (if we were's declaring isn't
+/// itself a template).
+TemplateParameterList *
+Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
+ const CXXScopeSpec &SS,
+ TemplateParameterList **ParamLists,
+ unsigned NumParamLists,
+ bool IsFriend,
+ bool &IsExplicitSpecialization,
+ bool &Invalid) {
+ IsExplicitSpecialization = false;
+
+ // Find the template-ids that occur within the nested-name-specifier. These
+ // template-ids will match up with the template parameter lists.
+ llvm::SmallVector<const TemplateSpecializationType *, 4>
+ TemplateIdsInSpecifier;
+ llvm::SmallVector<ClassTemplateSpecializationDecl *, 4>
+ ExplicitSpecializationsInSpecifier;
+ for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NNS; NNS = NNS->getPrefix()) {
+ const Type *T = NNS->getAsType();
+ if (!T) break;
+
+ // C++0x [temp.expl.spec]p17:
+ // A member or a member template may be nested within many
+ // enclosing class templates. In an explicit specialization for
+ // such a member, the member declaration shall be preceded by a
+ // template<> for each enclosing class template that is
+ // explicitly specialized.
+ //
+ // Following the existing practice of GNU and EDG, we allow a typedef of a
+ // template specialization type.
+ while (const TypedefType *TT = dyn_cast<TypedefType>(T))
+ T = TT->getDecl()->getUnderlyingType().getTypePtr();
+
+ if (const TemplateSpecializationType *SpecType
+ = dyn_cast<TemplateSpecializationType>(T)) {
+ TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl();
+ if (!Template)
+ continue; // FIXME: should this be an error? probably...
+
+ if (const RecordType *Record = SpecType->getAs<RecordType>()) {
+ ClassTemplateSpecializationDecl *SpecDecl
+ = cast<ClassTemplateSpecializationDecl>(Record->getDecl());
+ // If the nested name specifier refers to an explicit specialization,
+ // we don't need a template<> header.
+ if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) {
+ ExplicitSpecializationsInSpecifier.push_back(SpecDecl);
+ continue;
+ }
+ }
+
+ TemplateIdsInSpecifier.push_back(SpecType);
+ }
+ }
+
+ // Reverse the list of template-ids in the scope specifier, so that we can
+ // more easily match up the template-ids and the template parameter lists.
+ std::reverse(TemplateIdsInSpecifier.begin(), TemplateIdsInSpecifier.end());
+
+ SourceLocation FirstTemplateLoc = DeclStartLoc;
+ if (NumParamLists)
+ FirstTemplateLoc = ParamLists[0]->getTemplateLoc();
+
+ // Match the template-ids found in the specifier to the template parameter
+ // lists.
+ unsigned ParamIdx = 0, TemplateIdx = 0;
+ for (unsigned NumTemplateIds = TemplateIdsInSpecifier.size();
+ TemplateIdx != NumTemplateIds; ++TemplateIdx) {
+ const TemplateSpecializationType *TemplateId
+ = TemplateIdsInSpecifier[TemplateIdx];
+ bool DependentTemplateId = TemplateId->isDependentType();
+
+ // In friend declarations we can have template-ids which don't
+ // depend on the corresponding template parameter lists. But
+ // assume that empty parameter lists are supposed to match this
+ // template-id.
+ if (IsFriend && ParamIdx < NumParamLists && ParamLists[ParamIdx]->size()) {
+ if (!DependentTemplateId ||
+ !DependsOnTemplateParameters(TemplateId, ParamLists[ParamIdx]))
+ continue;
+ }
+
+ if (ParamIdx >= NumParamLists) {
+ // We have a template-id without a corresponding template parameter
+ // list.
+
+ // ...which is fine if this is a friend declaration.
+ if (IsFriend) {
+ IsExplicitSpecialization = true;
+ break;
+ }
+
+ if (DependentTemplateId) {
+ // FIXME: the location information here isn't great.
+ Diag(SS.getRange().getBegin(),
+ diag::err_template_spec_needs_template_parameters)
+ << QualType(TemplateId, 0)
+ << SS.getRange();
+ Invalid = true;
+ } else {
+ Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header)
+ << SS.getRange()
+ << FixItHint::CreateInsertion(FirstTemplateLoc, "template<> ");
+ IsExplicitSpecialization = true;
+ }
+ return 0;
+ }
+
+ // Check the template parameter list against its corresponding template-id.
+ if (DependentTemplateId) {
+ TemplateParameterList *ExpectedTemplateParams = 0;
+
+ // Are there cases in (e.g.) friends where this won't match?
+ if (const InjectedClassNameType *Injected
+ = TemplateId->getAs<InjectedClassNameType>()) {
+ CXXRecordDecl *Record = Injected->getDecl();
+ if (ClassTemplatePartialSpecializationDecl *Partial =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
+ ExpectedTemplateParams = Partial->getTemplateParameters();
+ else
+ ExpectedTemplateParams = Record->getDescribedClassTemplate()
+ ->getTemplateParameters();
+ }
+
+ if (ExpectedTemplateParams)
+ TemplateParameterListsAreEqual(ParamLists[ParamIdx],
+ ExpectedTemplateParams,
+ true, TPL_TemplateMatch);
+
+ CheckTemplateParameterList(ParamLists[ParamIdx], 0,
+ TPC_ClassTemplateMember);
+ } else if (ParamLists[ParamIdx]->size() > 0)
+ Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+ diag::err_template_param_list_matches_nontemplate)
+ << TemplateId
+ << ParamLists[ParamIdx]->getSourceRange();
+ else
+ IsExplicitSpecialization = true;
+
+ ++ParamIdx;
+ }
+
+ // If there were at least as many template-ids as there were template
+ // parameter lists, then there are no template parameter lists remaining for
+ // the declaration itself.
+ if (ParamIdx >= NumParamLists)
+ return 0;
+
+ // If there were too many template parameter lists, complain about that now.
+ if (ParamIdx != NumParamLists - 1) {
+ while (ParamIdx < NumParamLists - 1) {
+ bool isExplicitSpecHeader = ParamLists[ParamIdx]->size() == 0;
+ Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+ isExplicitSpecHeader? diag::warn_template_spec_extra_headers
+ : diag::err_template_spec_extra_headers)
+ << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
+ ParamLists[ParamIdx]->getRAngleLoc());
+
+ if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) {
+ Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(),
+ diag::note_explicit_template_spec_does_not_need_header)
+ << ExplicitSpecializationsInSpecifier.back();
+ ExplicitSpecializationsInSpecifier.pop_back();
+ }
+
+ // We have a template parameter list with no corresponding scope, which
+ // means that the resulting template declaration can't be instantiated
+ // properly (we'll end up with dependent nodes when we shouldn't).
+ if (!isExplicitSpecHeader)
+ Invalid = true;
+
+ ++ParamIdx;
+ }
+ }
+
+ // Return the last template parameter list, which corresponds to the
+ // entity being declared.
+ return ParamLists[NumParamLists - 1];
+}
+
+QualType Sema::CheckTemplateIdType(TemplateName Name,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ if (!Template) {
+ // The template name does not resolve to a template, so we just
+ // build a dependent template-id type.
+ return Context.getTemplateSpecializationType(Name, TemplateArgs);
+ }
+
+ // Check that the template argument list is well-formed for this
+ // template.
+ llvm::SmallVector<TemplateArgument, 4> Converted;
+ if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
+ false, Converted))
+ return QualType();
+
+ assert((Converted.size() == Template->getTemplateParameters()->size()) &&
+ "Converted template argument list is too short!");
+
+ QualType CanonType;
+
+ if (Name.isDependent() ||
+ TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs)) {
+ // This class template specialization is a dependent
+ // type. Therefore, its canonical type is another class template
+ // specialization type that contains all of the converted
+ // arguments in canonical form. This ensures that, e.g., A<T> and
+ // A<T, T> have identical types when A is declared as:
+ //
+ // template<typename T, typename U = T> struct A;
+ TemplateName CanonName = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(CanonName,
+ Converted.data(),
+ Converted.size());
+
+ // FIXME: CanonType is not actually the canonical type, and unfortunately
+ // it is a TemplateSpecializationType that we will never use again.
+ // In the future, we need to teach getTemplateSpecializationType to only
+ // build the canonical type and return that to us.
+ CanonType = Context.getCanonicalType(CanonType);
+
+ // This might work out to be a current instantiation, in which
+ // case the canonical type needs to be the InjectedClassNameType.
+ //
+ // TODO: in theory this could be a simple hashtable lookup; most
+ // changes to CurContext don't change the set of current
+ // instantiations.
+ if (isa<ClassTemplateDecl>(Template)) {
+ for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
+ // If we get out to a namespace, we're done.
+ if (Ctx->isFileContext()) break;
+
+ // If this isn't a record, keep looking.
+ CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
+ if (!Record) continue;
+
+ // Look for one of the two cases with InjectedClassNameTypes
+ // and check whether it's the same template.
+ if (!isa<ClassTemplatePartialSpecializationDecl>(Record) &&
+ !Record->getDescribedClassTemplate())
+ continue;
+
+ // Fetch the injected class name type and check whether its
+ // injected type is equal to the type we just built.
+ QualType ICNT = Context.getTypeDeclType(Record);
+ QualType Injected = cast<InjectedClassNameType>(ICNT)
+ ->getInjectedSpecializationType();
+
+ if (CanonType != Injected->getCanonicalTypeInternal())
+ continue;
+
+ // If so, the canonical type of this TST is the injected
+ // class name type of the record we just found.
+ assert(ICNT.isCanonical());
+ CanonType = ICNT;
+ break;
+ }
+ }
+ } else if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast<ClassTemplateDecl>(Template)) {
+ // Find the class template specialization declaration that
+ // corresponds to these arguments.
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *Decl
+ = ClassTemplate->findSpecialization(Converted.data(), Converted.size(),
+ InsertPos);
+ if (!Decl) {
+ // This is the first time we have referenced this class template
+ // specialization. Create the canonical declaration and add it to
+ // the set of specializations.
+ Decl = ClassTemplateSpecializationDecl::Create(Context,
+ ClassTemplate->getTemplatedDecl()->getTagKind(),
+ ClassTemplate->getDeclContext(),
+ ClassTemplate->getLocation(),
+ ClassTemplate,
+ Converted.data(),
+ Converted.size(), 0);
+ ClassTemplate->AddSpecialization(Decl, InsertPos);
+ Decl->setLexicalDeclContext(CurContext);
+ }
+
+ CanonType = Context.getTypeDeclType(Decl);
+ assert(isa<RecordType>(CanonType) &&
+ "type of non-dependent specialization is not a RecordType");
+ }
+
+ // Build the fully-sugared type for this class template
+ // specialization, which refers back to the class template
+ // specialization we created or found.
+ return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+}
+
+TypeResult
+Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc) {
+ TemplateName Template = TemplateD.getAsVal<TemplateName>();
+
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+ TemplateArgsIn.release();
+
+ if (Result.isNull())
+ return true;
+
+ TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Result);
+ TemplateSpecializationTypeLoc TL
+ = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TL.setTemplateNameLoc(TemplateLoc);
+ TL.setLAngleLoc(LAngleLoc);
+ TL.setRAngleLoc(RAngleLoc);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+ return CreateParsedType(Result, DI);
+}
+
+TypeResult Sema::ActOnTagTemplateIdType(CXXScopeSpec &SS,
+ TypeResult TypeResult,
+ TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc) {
+ if (TypeResult.isInvalid())
+ return ::TypeResult();
+
+ TypeSourceInfo *DI;
+ QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
+
+ // Verify the tag specifier.
+ TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+ if (const RecordType *RT = Type->getAs<RecordType>()) {
+ RecordDecl *D = RT->getDecl();
+
+ IdentifierInfo *Id = D->getIdentifier();
+ assert(Id && "templated class must have an identifier");
+
+ if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) {
+ Diag(TagLoc, diag::err_use_with_wrong_tag)
+ << Type
+ << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
+ Diag(D->getLocation(), diag::note_previous_use);
+ }
+ }
+
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
+ QualType ElabType = Context.getElaboratedType(Keyword, /*NNS=*/0, Type);
+
+ TypeSourceInfo *ElabDI = Context.CreateTypeSourceInfo(ElabType);
+ ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(ElabDI->getTypeLoc());
+ TL.setKeywordLoc(TagLoc);
+ TL.setQualifierRange(SS.getRange());
+ TL.getNamedTypeLoc().initializeFullCopy(DI->getTypeLoc());
+ return CreateParsedType(ElabType, ElabDI);
+}
+
+ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ // FIXME: Can we do any checking at this point? I guess we could check the
+ // template arguments that we have against the template name, if the template
+ // name refers to a single template. That's not a terribly common case,
+ // though.
+ // foo<int> could identify a single function unambiguously
+ // This approach does NOT work, since f<int>(1);
+ // gets resolved prior to resorting to overload resolution
+ // i.e., template<class T> void f(double);
+ // vs template<class T, class U> void f(U);
+
+ // These should be filtered out by our callers.
+ assert(!R.empty() && "empty lookup results when building templateid");
+ assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
+
+ NestedNameSpecifier *Qualifier = 0;
+ SourceRange QualifierRange;
+ if (SS.isSet()) {
+ Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ QualifierRange = SS.getRange();
+ }
+
+ // We don't want lookup warnings at this point.
+ R.suppressDiagnostics();
+
+ UnresolvedLookupExpr *ULE
+ = UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
+ Qualifier, QualifierRange,
+ R.getLookupNameInfo(),
+ RequiresADL, TemplateArgs,
+ R.begin(), R.end());
+
+ return Owned(ULE);
+}
+
+// We actually only call this from template instantiation.
+ExprResult
+Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ DeclContext *DC;
+ if (!(DC = computeDeclContext(SS, false)) ||
+ DC->isDependentContext() ||
+ RequireCompleteDeclContext(SS, DC))
+ return BuildDependentDeclRefExpr(SS, NameInfo, &TemplateArgs);
+
+ bool MemberOfUnknownSpecialization;
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
+ LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false,
+ MemberOfUnknownSpecialization);
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template)
+ << NameInfo.getName() << SS.getRange();
+ return ExprError();
+ }
+
+ if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
+ Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
+ << (NestedNameSpecifier*) SS.getScopeRep()
+ << NameInfo.getName() << SS.getRange();
+ Diag(Temp->getLocation(), diag::note_referenced_class_template);
+ return ExprError();
+ }
+
+ return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs);
+}
+
+/// \brief Form a dependent template name.
+///
+/// This action forms a dependent template name given the template
+/// name and its (presumably dependent) scope specifier. For
+/// example, given "MetaFun::template apply", the scope specifier \p
+/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
+/// of the "template" keyword, and "apply" is the \p Name.
+TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Result) {
+ if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TemplateKWLoc, diag::ext_template_outside_of_template)
+ << FixItHint::CreateRemoval(TemplateKWLoc);
+
+ DeclContext *LookupCtx = 0;
+ if (SS.isSet())
+ LookupCtx = computeDeclContext(SS, EnteringContext);
+ if (!LookupCtx && ObjectType)
+ LookupCtx = computeDeclContext(ObjectType.get());
+ if (LookupCtx) {
+ // C++0x [temp.names]p5:
+ // If a name prefixed by the keyword template is not the name of
+ // a template, the program is ill-formed. [Note: the keyword
+ // template may not be applied to non-template members of class
+ // templates. -end note ] [ Note: as is the case with the
+ // typename prefix, the template prefix is allowed in cases
+ // where it is not strictly necessary; i.e., when the
+ // nested-name-specifier or the expression on the left of the ->
+ // or . is not dependent on a template-parameter, or the use
+ // does not appear in the scope of a template. -end note]
+ //
+ // Note: C++03 was more strict here, because it banned the use of
+ // the "template" keyword prior to a template-name that was not a
+ // dependent name. C++ DR468 relaxed this requirement (the
+ // "template" keyword is now permitted). We follow the C++0x
+ // rules, even in C++03 mode with a warning, retroactively applying the DR.
+ bool MemberOfUnknownSpecialization;
+ TemplateNameKind TNK = isTemplateName(0, SS, TemplateKWLoc.isValid(), Name,
+ ObjectType, EnteringContext, Result,
+ MemberOfUnknownSpecialization);
+ if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
+ isa<CXXRecordDecl>(LookupCtx) &&
+ cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
+ // This is a dependent template. Handle it below.
+ } else if (TNK == TNK_Non_template) {
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name).getName()
+ << Name.getSourceRange()
+ << TemplateKWLoc;
+ return TNK_Non_template;
+ } else {
+ // We found something; return it.
+ return TNK;
+ }
+ }
+
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
+ switch (Name.getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.Identifier));
+ return TNK_Dependent_template_name;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.OperatorFunctionId.Operator));
+ return TNK_Dependent_template_name;
+
+ case UnqualifiedId::IK_LiteralOperatorId:
+ assert(false && "We don't support these; Parse shouldn't have allowed propagation");
+
+ default:
+ break;
+ }
+
+ Diag(Name.getSourceRange().getBegin(),
+ diag::err_template_kw_refers_to_non_template)
+ << GetNameFromUnqualifiedId(Name).getName()
+ << Name.getSourceRange()
+ << TemplateKWLoc;
+ return TNK_Non_template;
+}
+
+bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+ const TemplateArgumentLoc &AL,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ const TemplateArgument &Arg = AL.getArgument();
+
+ // Check template type parameter.
+ switch(Arg.getKind()) {
+ case TemplateArgument::Type:
+ // C++ [temp.arg.type]p1:
+ // A template-argument for a template-parameter which is a
+ // type shall be a type-id.
+ break;
+ case TemplateArgument::Template: {
+ // We have a template type parameter but the template argument
+ // is a template without any arguments.
+ SourceRange SR = AL.getSourceRange();
+ TemplateName Name = Arg.getAsTemplate();
+ Diag(SR.getBegin(), diag::err_template_missing_args)
+ << Name << SR;
+ if (TemplateDecl *Decl = Name.getAsTemplateDecl())
+ Diag(Decl->getLocation(), diag::note_template_decl_here);
+
+ return true;
+ }
+ default: {
+ // We have a template type parameter but the template argument
+ // is not a type.
+ SourceRange SR = AL.getSourceRange();
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
+ Diag(Param->getLocation(), diag::note_template_param_here);
+
+ return true;
+ }
+ }
+
+ if (CheckTemplateArgument(Param, AL.getTypeSourceInfo()))
+ return true;
+
+ // Add the converted template type argument.
+ Converted.push_back(
+ TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
+ return false;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template type parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TypeSourceInfo *
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateTypeParmDecl *Param,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo();
+
+ // If the argument type is dependent, instantiate it now based
+ // on the previously-computed template arguments.
+ if (ArgType->getType()->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.data(),
+ Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
+ Param->getDefaultArgumentLoc(),
+ Param->getDeclName());
+ }
+
+ return ArgType;
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given non-type template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the non-type template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static ExprResult
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ NonTypeTemplateParmDecl *Param,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.data(),
+ Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
+}
+
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+ TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ TemplateTemplateParmDecl *Param,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+
+ MultiLevelTemplateArgumentList AllTemplateArgs
+ = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+
+ Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+ Template, Converted.data(),
+ Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ return SemaRef.SubstTemplateName(
+ Param->getDefaultArgument().getArgument().getAsTemplate(),
+ Param->getDefaultArgument().getTemplateNameLoc(),
+ AllTemplateArgs);
+}
+
+/// \brief If the given template parameter has a default template
+/// argument, substitute into that default template argument and
+/// return the corresponding template argument.
+TemplateArgumentLoc
+Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ Decl *Param,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (!TypeParm->hasDefaultArgument())
+ return TemplateArgumentLoc();
+
+ TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ TypeParm,
+ Converted);
+ if (DI)
+ return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+
+ return TemplateArgumentLoc();
+ }
+
+ if (NonTypeTemplateParmDecl *NonTypeParm
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ if (!NonTypeParm->hasDefaultArgument())
+ return TemplateArgumentLoc();
+
+ ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ NonTypeParm,
+ Converted);
+ if (Arg.isInvalid())
+ return TemplateArgumentLoc();
+
+ Expr *ArgE = Arg.takeAs<Expr>();
+ return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
+ }
+
+ TemplateTemplateParmDecl *TempTempParm
+ = cast<TemplateTemplateParmDecl>(Param);
+ if (!TempTempParm->hasDefaultArgument())
+ return TemplateArgumentLoc();
+
+ TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ TempTempParm,
+ Converted);
+ if (TName.isNull())
+ return TemplateArgumentLoc();
+
+ return TemplateArgumentLoc(TemplateArgument(TName),
+ TempTempParm->getDefaultArgument().getTemplateQualifierRange(),
+ TempTempParm->getDefaultArgument().getTemplateNameLoc());
+}
+
+/// \brief Check that the given template argument corresponds to the given
+/// template parameter.
+///
+/// \param Param The template parameter against which the argument will be
+/// checked.
+///
+/// \param Arg The template argument.
+///
+/// \param Template The template in which the template argument resides.
+///
+/// \param TemplateLoc The location of the template name for the template
+/// whose argument list we're matching.
+///
+/// \param RAngleLoc The location of the right angle bracket ('>') that closes
+/// the template argument list.
+///
+/// \param ArgumentPackIndex The index into the argument pack where this
+/// argument will be placed. Only valid if the parameter is a parameter pack.
+///
+/// \param Converted The checked, converted argument will be added to the
+/// end of this small vector.
+///
+/// \param CTAK Describes how we arrived at this particular template argument:
+/// explicitly written, deduced, etc.
+///
+/// \returns true on error, false otherwise.
+bool Sema::CheckTemplateArgument(NamedDecl *Param,
+ const TemplateArgumentLoc &Arg,
+ NamedDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ unsigned ArgumentPackIndex,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted,
+ CheckTemplateArgumentKind CTAK) {
+ // Check template type parameters.
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ return CheckTemplateTypeArgument(TTP, Arg, Converted);
+
+ // Check non-type template parameters.
+ if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ // Do substitution on the type of the non-type template parameter
+ // with the template arguments we've seen thus far. But if the
+ // template has a dependent context then we cannot substitute yet.
+ QualType NTTPType = NTTP->getType();
+ if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
+ NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+
+ if (NTTPType->isDependentType() &&
+ !isa<TemplateTemplateParmDecl>(Template) &&
+ !Template->getDeclContext()->isDependentContext()) {
+ // Do substitution on the type of the non-type template parameter.
+ InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+ NTTP, Converted.data(), Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+ NTTPType = SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ // If that worked, check the non-type template parameter type
+ // for validity.
+ if (!NTTPType.isNull())
+ NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
+ NTTP->getLocation());
+ if (NTTPType.isNull())
+ return true;
+ }
+
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Should never see a NULL template argument here");
+ return true;
+
+ case TemplateArgument::Expression: {
+ Expr *E = Arg.getArgument().getAsExpr();
+ TemplateArgument Result;
+ if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK))
+ return true;
+
+ Converted.push_back(Result);
+ break;
+ }
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ // We've already checked this template argument, so just copy
+ // it to the list of converted arguments.
+ Converted.push_back(Arg.getArgument());
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ // We were given a template template argument. It may not be ill-formed;
+ // see below.
+ if (DependentTemplateName *DTN
+ = Arg.getArgument().getAsTemplateOrTemplatePattern()
+ .getAsDependentTemplateName()) {
+ // We have a template argument such as \c T::template X, which we
+ // parsed as a template template argument. However, since we now
+ // know that we need a non-type template argument, convert this
+ // template name into an expression.
+
+ DeclarationNameInfo NameInfo(DTN->getIdentifier(),
+ Arg.getTemplateNameLoc());
+
+ Expr *E = DependentScopeDeclRefExpr::Create(Context,
+ DTN->getQualifier(),
+ Arg.getTemplateQualifierRange(),
+ NameInfo);
+
+ // If we parsed the template argument as a pack expansion, create a
+ // pack expansion expression.
+ if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+ ExprResult Expansion = ActOnPackExpansion(E,
+ Arg.getTemplateEllipsisLoc());
+ if (Expansion.isInvalid())
+ return true;
+
+ E = Expansion.get();
+ }
+
+ TemplateArgument Result;
+ if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+ return true;
+
+ Converted.push_back(Result);
+ break;
+ }
+
+ // We have a template argument that actually does refer to a class
+ // template, template alias, or template template parameter, and
+ // therefore cannot be a non-type template argument.
+ Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+ << Arg.getSourceRange();
+
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+
+ case TemplateArgument::Type: {
+ // We have a non-type template parameter but the template
+ // argument is a type.
+
+ // C++ [temp.arg]p2:
+ // In a template-argument, an ambiguity between a type-id and
+ // an expression is resolved to a type-id, regardless of the
+ // form of the corresponding template-parameter.
+ //
+ // We warn specifically about this case, since it can be rather
+ // confusing for users.
+ QualType T = Arg.getArgument().getAsType();
+ SourceRange SR = Arg.getSourceRange();
+ if (T->isFunctionType())
+ Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
+ else
+ Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ case TemplateArgument::Pack:
+ llvm_unreachable("Caller must expand template argument packs");
+ break;
+ }
+
+ return false;
+ }
+
+
+ // Check template template parameters.
+ TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
+
+ // Substitute into the template parameter list of the template
+ // template parameter, since previously-supplied template arguments
+ // may appear within the template template parameter.
+ {
+ // Set up a template instantiation context.
+ LocalInstantiationScope Scope(*this);
+ InstantiatingTemplate Inst(*this, TemplateLoc, Template,
+ TempParm, Converted.data(), Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Converted.data(), Converted.size());
+ TempParm = cast_or_null<TemplateTemplateParmDecl>(
+ SubstDecl(TempParm, CurContext,
+ MultiLevelTemplateArgumentList(TemplateArgs)));
+ if (!TempParm)
+ return true;
+ }
+
+ switch (Arg.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Should never see a NULL template argument here");
+ return true;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (CheckTemplateArgument(TempParm, Arg))
+ return true;
+
+ Converted.push_back(Arg.getArgument());
+ break;
+
+ case TemplateArgument::Expression:
+ case TemplateArgument::Type:
+ // We have a template template parameter but the template
+ // argument does not refer to a template.
+ Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
+ return true;
+
+ case TemplateArgument::Declaration:
+ llvm_unreachable(
+ "Declaration argument with template template parameter");
+ break;
+ case TemplateArgument::Integral:
+ llvm_unreachable(
+ "Integral argument with template template parameter");
+ break;
+
+ case TemplateArgument::Pack:
+ llvm_unreachable("Caller must expand template argument packs");
+ break;
+ }
+
+ return false;
+}
+
+/// \brief Check that the given template argument list is well-formed
+/// for specializing the given template.
+bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &TemplateArgs,
+ bool PartialTemplateArgs,
+ llvm::SmallVectorImpl<TemplateArgument> &Converted) {
+ TemplateParameterList *Params = Template->getTemplateParameters();
+ unsigned NumParams = Params->size();
+ unsigned NumArgs = TemplateArgs.size();
+ bool Invalid = false;
+
+ SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc();
+
+ bool HasParameterPack =
+ NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
+
+ if ((NumArgs > NumParams && !HasParameterPack) ||
+ (NumArgs < Params->getMinRequiredArguments() &&
+ !PartialTemplateArgs)) {
+ // FIXME: point at either the first arg beyond what we can handle,
+ // or the '>', depending on whether we have too many or too few
+ // arguments.
+ SourceRange Range;
+ if (NumArgs > NumParams)
+ Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc);
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << (NumArgs > NumParams)
+ << (isa<ClassTemplateDecl>(Template)? 0 :
+ isa<FunctionTemplateDecl>(Template)? 1 :
+ isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+ << Template << Range;
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ Invalid = true;
+ }
+
+ // C++ [temp.arg]p1:
+ // [...] The type and form of each template-argument specified in
+ // a template-id shall match the type and form specified for the
+ // corresponding parameter declared by the template in its
+ // template-parameter-list.
+ llvm::SmallVector<TemplateArgument, 2> ArgumentPack;
+ TemplateParameterList::iterator Param = Params->begin(),
+ ParamEnd = Params->end();
+ unsigned ArgIdx = 0;
+ LocalInstantiationScope InstScope(*this, true);
+ while (Param != ParamEnd) {
+ if (ArgIdx > NumArgs && PartialTemplateArgs)
+ break;
+
+ if (ArgIdx < NumArgs) {
+ // If we have an expanded parameter pack, make sure we don't have too
+ // many arguments.
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+ if (NTTP->isExpandedParameterPack() &&
+ ArgumentPack.size() >= NTTP->getNumExpansionTypes()) {
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << true
+ << (isa<ClassTemplateDecl>(Template)? 0 :
+ isa<FunctionTemplateDecl>(Template)? 1 :
+ isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+ << Template;
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+ }
+ }
+
+ // Check the template argument we were given.
+ if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
+ TemplateLoc, RAngleLoc,
+ ArgumentPack.size(), Converted))
+ return true;
+
+ if ((*Param)->isTemplateParameterPack()) {
+ // The template parameter was a template parameter pack, so take the
+ // deduced argument and place it on the argument pack. Note that we
+ // stay on the same template parameter so that we can deduce more
+ // arguments.
+ ArgumentPack.push_back(Converted.back());
+ Converted.pop_back();
+ } else {
+ // Move to the next template parameter.
+ ++Param;
+ }
+ ++ArgIdx;
+ continue;
+ }
+
+ // If we have a template parameter pack with no more corresponding
+ // arguments, just break out now and we'll fill in the argument pack below.
+ if ((*Param)->isTemplateParameterPack())
+ break;
+
+ // We have a default template argument that we will use.
+ TemplateArgumentLoc Arg;
+
+ // Retrieve the default template argument from the template
+ // parameter. For each kind of template parameter, we substitute the
+ // template arguments provided thus far and any "outer" template arguments
+ // (when the template parameter was part of a nested template) into
+ // the default argument.
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+ if (!TTP->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+ break;
+ }
+
+ TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
+ Template,
+ TemplateLoc,
+ RAngleLoc,
+ TTP,
+ Converted);
+ if (!ArgType)
+ return true;
+
+ Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
+ ArgType);
+ } else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+ if (!NTTP->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+ break;
+ }
+
+ ExprResult E = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ NTTP,
+ Converted);
+ if (E.isInvalid())
+ return true;
+
+ Expr *Ex = E.takeAs<Expr>();
+ Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
+ } else {
+ TemplateTemplateParmDecl *TempParm
+ = cast<TemplateTemplateParmDecl>(*Param);
+
+ if (!TempParm->hasDefaultArgument()) {
+ assert((Invalid || PartialTemplateArgs) && "Missing default argument");
+ break;
+ }
+
+ TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+ TemplateLoc,
+ RAngleLoc,
+ TempParm,
+ Converted);
+ if (Name.isNull())
+ return true;
+
+ Arg = TemplateArgumentLoc(TemplateArgument(Name),
+ TempParm->getDefaultArgument().getTemplateQualifierRange(),
+ TempParm->getDefaultArgument().getTemplateNameLoc());
+ }
+
+ // Introduce an instantiation record that describes where we are using
+ // the default template argument.
+ InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param,
+ Converted.data(), Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
+ // Check the default template argument.
+ if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
+ RAngleLoc, 0, Converted))
+ return true;
+
+ // Move to the next template parameter and argument.
+ ++Param;
+ ++ArgIdx;
+ }
+
+ // Form argument packs for each of the parameter packs remaining.
+ while (Param != ParamEnd) {
+ // If we're checking a partial list of template arguments, don't fill
+ // in arguments for non-template parameter packs.
+
+ if ((*Param)->isTemplateParameterPack()) {
+ if (PartialTemplateArgs && ArgumentPack.empty()) {
+ Converted.push_back(TemplateArgument());
+ } else if (ArgumentPack.empty())
+ Converted.push_back(TemplateArgument(0, 0));
+ else {
+ Converted.push_back(TemplateArgument::CreatePackCopy(Context,
+ ArgumentPack.data(),
+ ArgumentPack.size()));
+ ArgumentPack.clear();
+ }
+ }
+
+ ++Param;
+ }
+
+ return Invalid;
+}
+
+namespace {
+ class UnnamedLocalNoLinkageFinder
+ : public TypeVisitor<UnnamedLocalNoLinkageFinder, bool>
+ {
+ Sema &S;
+ SourceRange SR;
+
+ typedef TypeVisitor<UnnamedLocalNoLinkageFinder, bool> inherited;
+
+ public:
+ UnnamedLocalNoLinkageFinder(Sema &S, SourceRange SR) : S(S), SR(SR) { }
+
+ bool Visit(QualType T) {
+ return inherited::Visit(T.getTypePtr());
+ }
+
+#define TYPE(Class, Parent) \
+ bool Visit##Class##Type(const Class##Type *);
+#define ABSTRACT_TYPE(Class, Parent) \
+ bool Visit##Class##Type(const Class##Type *) { return false; }
+#define NON_CANONICAL_TYPE(Class, Parent) \
+ bool Visit##Class##Type(const Class##Type *) { return false; }
+#include "clang/AST/TypeNodes.def"
+
+ bool VisitTagDecl(const TagDecl *Tag);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
+ };
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitPointerType(const PointerType* T) {
+ return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitBlockPointerType(
+ const BlockPointerType* T) {
+ return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitLValueReferenceType(
+ const LValueReferenceType* T) {
+ return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
+ const RValueReferenceType* T) {
+ return Visit(T->getPointeeType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
+ const MemberPointerType* T) {
+ return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
+ const ConstantArrayType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitIncompleteArrayType(
+ const IncompleteArrayType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitVariableArrayType(
+ const VariableArrayType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentSizedArrayType(
+ const DependentSizedArrayType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
+ const DependentSizedExtVectorType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
+ return Visit(T->getElementType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
+ const FunctionProtoType* T) {
+ for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
+ AEnd = T->arg_type_end();
+ A != AEnd; ++A) {
+ if (Visit(*A))
+ return true;
+ }
+
+ return Visit(T->getResultType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
+ const FunctionNoProtoType* T) {
+ return Visit(T->getResultType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
+ const UnresolvedUsingType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) {
+ return Visit(T->getUnderlyingType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
+ return Visit(T->getDeducedType());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
+ return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) {
+ return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
+ const TemplateTypeParmType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
+ const SubstTemplateTypeParmPackType *) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
+ const TemplateSpecializationType*) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType(
+ const InjectedClassNameType* T) {
+ return VisitTagDecl(T->getDecl());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
+ const DependentNameType* T) {
+ return VisitNestedNameSpecifier(T->getQualifier());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
+ const DependentTemplateSpecializationType* T) {
+ return VisitNestedNameSpecifier(T->getQualifier());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
+ const PackExpansionType* T) {
+ return Visit(T->getPattern());
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCInterfaceType(
+ const ObjCInterfaceType *) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType(
+ const ObjCObjectPointerType *) {
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
+ if (Tag->getDeclContext()->isFunctionOrMethod()) {
+ S.Diag(SR.getBegin(), diag::ext_template_arg_local_type)
+ << S.Context.getTypeDeclType(Tag) << SR;
+ return true;
+ }
+
+ if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) {
+ S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
+ S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
+ return true;
+ }
+
+ return false;
+}
+
+bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
+ NestedNameSpecifier *NNS) {
+ if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
+ return true;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Global:
+ return false;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ return Visit(QualType(NNS->getAsType(), 0));
+ }
+ return false;
+}
+
+
+/// \brief Check a template argument against its corresponding
+/// template type parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.type]. It
+/// returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ TypeSourceInfo *ArgInfo) {
+ assert(ArgInfo && "invalid TypeSourceInfo");
+ QualType Arg = ArgInfo->getType();
+ SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
+
+ if (Arg->isVariablyModifiedType()) {
+ return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
+ } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
+ return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
+ }
+
+ // C++03 [temp.arg.type]p2:
+ // A local type, a type with no linkage, an unnamed type or a type
+ // compounded from any of these types shall not be used as a
+ // template-argument for a template type-parameter.
+ //
+ // C++0x allows these, and even in C++03 we allow them as an extension with
+ // a warning.
+ if (!LangOpts.CPlusPlus0x && Arg->hasUnnamedOrLocalType()) {
+ UnnamedLocalNoLinkageFinder Finder(*this, SR);
+ (void)Finder.Visit(Context.getCanonicalType(Arg));
+ }
+
+ return false;
+}
+
+/// \brief Checks whether the given template argument is the address
+/// of an object or function according to C++ [temp.arg.nontype]p1.
+static bool
+CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
+ NonTypeTemplateParmDecl *Param,
+ QualType ParamType,
+ Expr *ArgIn,
+ TemplateArgument &Converted) {
+ bool Invalid = false;
+ Expr *Arg = ArgIn;
+ QualType ArgType = Arg->getType();
+
+ // See through any implicit casts we added to fix the type.
+ while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = Cast->getSubExpr();
+
+ // C++ [temp.arg.nontype]p1:
+ //
+ // A template-argument for a non-type, non-template
+ // template-parameter shall be one of: [...]
+ //
+ // -- the address of an object or function with external
+ // linkage, including function templates and function
+ // template-ids but excluding non-static class members,
+ // expressed as & id-expression where the & is optional if
+ // the name refers to a function or array, or if the
+ // corresponding template-parameter is a reference; or
+ DeclRefExpr *DRE = 0;
+
+ // In C++98/03 mode, give an extension warning on any extra parentheses.
+ // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
+ bool ExtraParens = false;
+ while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+ if (!Invalid && !ExtraParens && !S.getLangOptions().CPlusPlus0x) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::ext_template_arg_extra_parens)
+ << Arg->getSourceRange();
+ ExtraParens = true;
+ }
+
+ Arg = Parens->getSubExpr();
+ }
+
+ bool AddressTaken = false;
+ SourceLocation AddrOpLoc;
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
+ DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+ AddressTaken = true;
+ AddrOpLoc = UnOp->getOperatorLoc();
+ }
+ } else
+ DRE = dyn_cast<DeclRefExpr>(Arg);
+
+ if (!DRE) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ // Stop checking the precise nature of the argument if it is value dependent,
+ // it should be checked when instantiated.
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(ArgIn);
+ return false;
+ }
+
+ if (!isa<ValueDecl>(DRE->getDecl())) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_object_or_func_form)
+ << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ NamedDecl *Entity = 0;
+
+ // Cannot refer to non-static data members
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) {
+ S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field)
+ << Field << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ // Cannot refer to non-static member functions
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl()))
+ if (!Method->isStatic()) {
+ S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method)
+ << Method << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ // Functions must have external linkage.
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+ if (!isExternalLinkage(Func->getLinkage())) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_function_not_extern)
+ << Func << Arg->getSourceRange();
+ S.Diag(Func->getLocation(), diag::note_template_arg_internal_object)
+ << true;
+ return true;
+ }
+
+ // Okay: we've named a function with external linkage.
+ Entity = Func;
+
+ // If the template parameter has pointer type, the function decays.
+ if (ParamType->isPointerType() && !AddressTaken)
+ ArgType = S.Context.getPointerType(Func->getType());
+ else if (AddressTaken && ParamType->isReferenceType()) {
+ // If we originally had an address-of operator, but the
+ // parameter has reference type, complain and (if things look
+ // like they will work) drop the address-of operator.
+ if (!S.Context.hasSameUnqualifiedType(Func->getType(),
+ ParamType.getNonReferenceType())) {
+ S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+ << ParamType;
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+ << ParamType
+ << FixItHint::CreateRemoval(AddrOpLoc);
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+
+ ArgType = Func->getType();
+ }
+ } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!isExternalLinkage(Var->getLinkage())) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_object_not_extern)
+ << Var << Arg->getSourceRange();
+ S.Diag(Var->getLocation(), diag::note_template_arg_internal_object)
+ << true;
+ return true;
+ }
+
+ // A value of reference type is not an object.
+ if (Var->getType()->isReferenceType()) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_reference_var)
+ << Var->getType() << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ // Okay: we've named an object with external linkage
+ Entity = Var;
+
+ // If the template parameter has pointer type, we must have taken
+ // the address of this object.
+ if (ParamType->isReferenceType()) {
+ if (AddressTaken) {
+ // If we originally had an address-of operator, but the
+ // parameter has reference type, complain and (if things look
+ // like they will work) drop the address-of operator.
+ if (!S.Context.hasSameUnqualifiedType(Var->getType(),
+ ParamType.getNonReferenceType())) {
+ S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+ << ParamType;
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
+ << ParamType
+ << FixItHint::CreateRemoval(AddrOpLoc);
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+
+ ArgType = Var->getType();
+ }
+ } else if (!AddressTaken && ParamType->isPointerType()) {
+ if (Var->getType()->isArrayType()) {
+ // Array-to-pointer decay.
+ ArgType = S.Context.getArrayDecayedType(Var->getType());
+ } else {
+ // If the template parameter has pointer type but the address of
+ // this object was not taken, complain and (possibly) recover by
+ // taking the address of the entity.
+ ArgType = S.Context.getPointerType(Var->getType());
+ if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
+ << ParamType;
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of)
+ << ParamType
+ << FixItHint::CreateInsertion(Arg->getLocStart(), "&");
+
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ }
+ }
+ } else {
+ // We found something else, but we don't know specifically what it is.
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_object_or_func)
+ << Arg->getSourceRange();
+ S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
+ return true;
+ }
+
+ if (ParamType->isPointerType() &&
+ !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
+ S.IsQualificationConversion(ArgType, ParamType, false)) {
+ // For pointer-to-object types, qualification conversions are
+ // permitted.
+ } else {
+ if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
+ if (!ParamRef->getPointeeType()->isFunctionType()) {
+ // C++ [temp.arg.nontype]p5b3:
+ // For a non-type template-parameter of type reference to
+ // object, no conversions apply. The type referred to by the
+ // reference may be more cv-qualified than the (otherwise
+ // identical) type of the template- argument. The
+ // template-parameter is bound directly to the
+ // template-argument, which shall be an lvalue.
+
+ // FIXME: Other qualifiers?
+ unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
+ unsigned ArgQuals = ArgType.getCVRQualifiers();
+
+ if ((ParamQuals | ArgQuals) != ParamQuals) {
+ S.Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_ref_bind_ignores_quals)
+ << ParamType << Arg->getType()
+ << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+ }
+
+ // At this point, the template argument refers to an object or
+ // function with external linkage. We now need to check whether the
+ // argument and parameter types are compatible.
+ if (!S.Context.hasSameUnqualifiedType(ArgType,
+ ParamType.getNonReferenceType())) {
+ // We can't perform this conversion or binding.
+ if (ParamType->isReferenceType())
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
+ << ParamType << Arg->getType() << Arg->getSourceRange();
+ else
+ S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
+ << Arg->getType() << ParamType << Arg->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+
+ // Create the template argument.
+ Converted = TemplateArgument(Entity->getCanonicalDecl());
+ S.MarkDeclarationReferenced(Arg->getLocStart(), Entity);
+ return false;
+}
+
+/// \brief Checks whether the given template argument is a pointer to
+/// member constant according to C++ [temp.arg.nontype]p1.
+bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
+ TemplateArgument &Converted) {
+ bool Invalid = false;
+
+ // See through any implicit casts we added to fix the type.
+ while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = Cast->getSubExpr();
+
+ // C++ [temp.arg.nontype]p1:
+ //
+ // A template-argument for a non-type, non-template
+ // template-parameter shall be one of: [...]
+ //
+ // -- a pointer to member expressed as described in 5.3.1.
+ DeclRefExpr *DRE = 0;
+
+ // In C++98/03 mode, give an extension warning on any extra parentheses.
+ // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
+ bool ExtraParens = false;
+ while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
+ if (!Invalid && !ExtraParens && !getLangOptions().CPlusPlus0x) {
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::ext_template_arg_extra_parens)
+ << Arg->getSourceRange();
+ ExtraParens = true;
+ }
+
+ Arg = Parens->getSubExpr();
+ }
+
+ // A pointer-to-member constant written &Class::member.
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
+ DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+ if (DRE && !DRE->getQualifier())
+ DRE = 0;
+ }
+ }
+ // A constant of pointer-to-member type.
+ else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
+ if (VD->getType()->isMemberPointerType()) {
+ if (isa<NonTypeTemplateParmDecl>(VD) ||
+ (isa<VarDecl>(VD) &&
+ Context.getCanonicalType(VD->getType()).isConstQualified())) {
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ Converted = TemplateArgument(Arg);
+ else
+ Converted = TemplateArgument(VD->getCanonicalDecl());
+ return Invalid;
+ }
+ }
+ }
+
+ DRE = 0;
+ }
+
+ if (!DRE)
+ return Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_pointer_to_member_form)
+ << Arg->getSourceRange();
+
+ if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) {
+ assert((isa<FieldDecl>(DRE->getDecl()) ||
+ !cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) &&
+ "Only non-static member pointers can make it here");
+
+ // Okay: this is the address of a non-static member, and therefore
+ // a member pointer constant.
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ Converted = TemplateArgument(Arg);
+ else
+ Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
+ return Invalid;
+ }
+
+ // We found something else, but we don't know specifically what it is.
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_pointer_to_member_form)
+ << Arg->getSourceRange();
+ Diag(DRE->getDecl()->getLocation(),
+ diag::note_template_arg_refers_here);
+ return true;
+}
+
+/// \brief Check a template argument against its corresponding
+/// non-type template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.nontype].
+/// It returns true if an error occurred, and false otherwise. \p
+/// InstantiatedParamType is the type of the non-type template
+/// parameter after it has been instantiated.
+///
+/// If no error was detected, Converted receives the converted template argument.
+bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *&Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK) {
+ SourceLocation StartLoc = Arg->getSourceRange().getBegin();
+
+ // If either the parameter has a dependent type or the argument is
+ // type-dependent, there's nothing we can check now.
+ if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
+ // FIXME: Produce a cloned, canonical expression?
+ Converted = TemplateArgument(Arg);
+ return false;
+ }
+
+ // C++ [temp.arg.nontype]p5:
+ // The following conversions are performed on each expression used
+ // as a non-type template-argument. If a non-type
+ // template-argument cannot be converted to the type of the
+ // corresponding template-parameter then the program is
+ // ill-formed.
+ //
+ // -- for a non-type template-parameter of integral or
+ // enumeration type, integral promotions (4.5) and integral
+ // conversions (4.7) are applied.
+ QualType ParamType = InstantiatedParamType;
+ QualType ArgType = Arg->getType();
+ if (ParamType->isIntegralOrEnumerationType()) {
+ // C++ [temp.arg.nontype]p1:
+ // A template-argument for a non-type, non-template
+ // template-parameter shall be one of:
+ //
+ // -- an integral constant-expression of integral or enumeration
+ // type; or
+ // -- the name of a non-type template-parameter; or
+ SourceLocation NonConstantLoc;
+ llvm::APSInt Value;
+ if (!ArgType->isIntegralOrEnumerationType()) {
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_integral_or_enumeral)
+ << ArgType << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ } else if (!Arg->isValueDependent() &&
+ !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) {
+ Diag(NonConstantLoc, diag::err_template_arg_not_ice)
+ << ArgType << Arg->getSourceRange();
+ return true;
+ }
+
+ // From here on out, all we care about are the unqualified forms
+ // of the parameter and argument types.
+ ParamType = ParamType.getUnqualifiedType();
+ ArgType = ArgType.getUnqualifiedType();
+
+ // Try to convert the argument to the parameter's type.
+ if (Context.hasSameType(ParamType, ArgType)) {
+ // Okay: no conversion necessary
+ } else if (CTAK == CTAK_Deduced) {
+ // C++ [temp.deduct.type]p17:
+ // If, in the declaration of a function template with a non-type
+ // template-parameter, the non-type template- parameter is used
+ // in an expression in the function parameter-list and, if the
+ // corresponding template-argument is deduced, the
+ // template-argument type shall match the type of the
+ // template-parameter exactly, except that a template-argument
+ // deduced from an array bound may be of any integral type.
+ Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
+ << ArgType << ParamType;
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ } else if (ParamType->isBooleanType()) {
+ // This is an integral-to-boolean conversion.
+ ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean);
+ } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
+ !ParamType->isEnumeralType()) {
+ // This is an integral promotion or conversion.
+ ImpCastExprToType(Arg, ParamType, CK_IntegralCast);
+ } else {
+ // We can't perform this conversion.
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_convertible)
+ << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ QualType IntegerType = Context.getCanonicalType(ParamType);
+ if (const EnumType *Enum = IntegerType->getAs<EnumType>())
+ IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
+
+ if (!Arg->isValueDependent()) {
+ llvm::APSInt OldValue = Value;
+
+ // Coerce the template argument's value to the value it will have
+ // based on the template parameter's type.
+ unsigned AllowedBits = Context.getTypeSize(IntegerType);
+ if (Value.getBitWidth() != AllowedBits)
+ Value = Value.extOrTrunc(AllowedBits);
+ Value.setIsSigned(IntegerType->isSignedIntegerType());
+
+ // Complain if an unsigned parameter received a negative value.
+ if (IntegerType->isUnsignedIntegerType()
+ && (OldValue.isSigned() && OldValue.isNegative())) {
+ Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative)
+ << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ }
+
+ // Complain if we overflowed the template parameter's type.
+ unsigned RequiredBits;
+ if (IntegerType->isUnsignedIntegerType())
+ RequiredBits = OldValue.getActiveBits();
+ else if (OldValue.isUnsigned())
+ RequiredBits = OldValue.getActiveBits() + 1;
+ else
+ RequiredBits = OldValue.getMinSignedBits();
+ if (RequiredBits > AllowedBits) {
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::warn_template_arg_too_large)
+ << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ }
+ }
+
+ // Add the value of this argument to the list of converted
+ // arguments. We use the bitwidth and signedness of the template
+ // parameter.
+ if (Arg->isValueDependent()) {
+ // The argument is value-dependent. Create a new
+ // TemplateArgument with the converted expression.
+ Converted = TemplateArgument(Arg);
+ return false;
+ }
+
+ Converted = TemplateArgument(Value,
+ ParamType->isEnumeralType() ? ParamType
+ : IntegerType);
+ return false;
+ }
+
+ DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
+
+ // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion
+ // from a template argument of type std::nullptr_t to a non-type
+ // template parameter of type pointer to object, pointer to
+ // function, or pointer-to-member, respectively.
+ if (ArgType->isNullPtrType() &&
+ (ParamType->isPointerType() || ParamType->isMemberPointerType())) {
+ Converted = TemplateArgument((NamedDecl *)0);
+ return false;
+ }
+
+ // Handle pointer-to-function, reference-to-function, and
+ // pointer-to-member-function all in (roughly) the same way.
+ if (// -- For a non-type template-parameter of type pointer to
+ // function, only the function-to-pointer conversion (4.3) is
+ // applied. If the template-argument represents a set of
+ // overloaded functions (or a pointer to such), the matching
+ // function is selected from the set (13.4).
+ (ParamType->isPointerType() &&
+ ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) ||
+ // -- For a non-type template-parameter of type reference to
+ // function, no conversions apply. If the template-argument
+ // represents a set of overloaded functions, the matching
+ // function is selected from the set (13.4).
+ (ParamType->isReferenceType() &&
+ ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) ||
+ // -- For a non-type template-parameter of type pointer to
+ // member function, no conversions apply. If the
+ // template-argument represents a set of overloaded member
+ // functions, the matching member function is selected from
+ // the set (13.4).
+ (ParamType->isMemberPointerType() &&
+ ParamType->getAs<MemberPointerType>()->getPointeeType()
+ ->isFunctionType())) {
+
+ if (Arg->getType() == Context.OverloadTy) {
+ if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
+ true,
+ FoundResult)) {
+ if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ return true;
+
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ ArgType = Arg->getType();
+ } else
+ return true;
+ }
+
+ if (!ParamType->isMemberPointerType())
+ return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted);
+
+ if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(),
+ false)) {
+ ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
+ } else if (!Context.hasSameUnqualifiedType(ArgType,
+ ParamType.getNonReferenceType())) {
+ // We can't perform this conversion.
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_convertible)
+ << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ return CheckTemplateArgumentPointerToMember(Arg, Converted);
+ }
+
+ if (ParamType->isPointerType()) {
+ // -- for a non-type template-parameter of type pointer to
+ // object, qualification conversions (4.4) and the
+ // array-to-pointer conversion (4.2) are applied.
+ // C++0x also allows a value of std::nullptr_t.
+ assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
+ "Only object pointers allowed here");
+
+ return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted);
+ }
+
+ if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
+ // -- For a non-type template-parameter of type reference to
+ // object, no conversions apply. The type referred to by the
+ // reference may be more cv-qualified than the (otherwise
+ // identical) type of the template-argument. The
+ // template-parameter is bound directly to the
+ // template-argument, which must be an lvalue.
+ assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() &&
+ "Only object references allowed here");
+
+ if (Arg->getType() == Context.OverloadTy) {
+ if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
+ ParamRefType->getPointeeType(),
+ true,
+ FoundResult)) {
+ if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+ return true;
+
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ ArgType = Arg->getType();
+ } else
+ return true;
+ }
+
+ return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
+ ParamType,
+ Arg, Converted);
+ }
+
+ // -- For a non-type template-parameter of type pointer to data
+ // member, qualification conversions (4.4) are applied.
+ assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
+
+ if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
+ // Types match exactly: nothing more to do here.
+ } else if (IsQualificationConversion(ArgType, ParamType, false)) {
+ ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
+ } else {
+ // We can't perform this conversion.
+ Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_convertible)
+ << Arg->getType() << InstantiatedParamType << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+
+ return CheckTemplateArgumentPointerToMember(Arg, Converted);
+}
+
+/// \brief Check a template argument against its corresponding
+/// template template parameter.
+///
+/// This routine implements the semantics of C++ [temp.arg.template].
+/// It returns true if an error occurred, and false otherwise.
+bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ const TemplateArgumentLoc &Arg) {
+ TemplateName Name = Arg.getArgument().getAsTemplate();
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ if (!Template) {
+ // Any dependent template name is fine.
+ assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+ return false;
+ }
+
+ // C++ [temp.arg.template]p1:
+ // A template-argument for a template template-parameter shall be
+ // the name of a class template, expressed as id-expression. Only
+ // primary class templates are considered when matching the
+ // template template argument with the corresponding parameter;
+ // partial specializations are not considered even if their
+ // parameter lists match that of the template template parameter.
+ //
+ // Note that we also allow template template parameters here, which
+ // will happen when we are dealing with, e.g., class template
+ // partial specializations.
+ if (!isa<ClassTemplateDecl>(Template) &&
+ !isa<TemplateTemplateParmDecl>(Template)) {
+ assert(isa<FunctionTemplateDecl>(Template) &&
+ "Only function templates are possible here");
+ Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
+ Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
+ << Template;
+ }
+
+ return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
+ Param->getTemplateParameters(),
+ true,
+ TPL_TemplateTemplateArgumentMatch,
+ Arg.getLocation());
+}
+
+/// \brief Given a non-type template argument that refers to a
+/// declaration and the type of its corresponding non-type template
+/// parameter, produce an expression that properly refers to that
+/// declaration.
+ExprResult
+Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+ QualType ParamType,
+ SourceLocation Loc) {
+ assert(Arg.getKind() == TemplateArgument::Declaration &&
+ "Only declaration template arguments permitted here");
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ if (VD->getDeclContext()->isRecord() &&
+ (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) {
+ // If the value is a class member, we might have a pointer-to-member.
+ // Determine whether the non-type template template parameter is of
+ // pointer-to-member type. If so, we need to build an appropriate
+ // expression for a pointer-to-member, since a "normal" DeclRefExpr
+ // would refer to the member itself.
+ if (ParamType->isMemberPointerType()) {
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier *Qualifier
+ = NestedNameSpecifier::Create(Context, 0, false,
+ ClassType.getTypePtr());
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+
+ // The actual value-ness of this is unimportant, but for
+ // internal consistency's sake, references to instance methods
+ // are r-values.
+ ExprValueKind VK = VK_LValue;
+ if (isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())
+ VK = VK_RValue;
+
+ ExprResult RefExpr = BuildDeclRefExpr(VD,
+ VD->getType().getNonReferenceType(),
+ VK,
+ Loc,
+ &SS);
+ if (RefExpr.isInvalid())
+ return ExprError();
+
+ RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
+
+ // We might need to perform a trailing qualification conversion, since
+ // the element type on the parameter could be more qualified than the
+ // element type in the expression we constructed.
+ if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
+ ParamType.getUnqualifiedType(), false)) {
+ Expr *RefE = RefExpr.takeAs<Expr>();
+ ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CK_NoOp);
+ RefExpr = Owned(RefE);
+ }
+
+ assert(!RefExpr.isInvalid() &&
+ Context.hasSameType(((Expr*) RefExpr.get())->getType(),
+ ParamType.getUnqualifiedType()));
+ return move(RefExpr);
+ }
+ }
+
+ QualType T = VD->getType().getNonReferenceType();
+ if (ParamType->isPointerType()) {
+ // When the non-type template parameter is a pointer, take the
+ // address of the declaration.
+ ExprResult RefExpr = BuildDeclRefExpr(VD, T, VK_LValue, Loc);
+ if (RefExpr.isInvalid())
+ return ExprError();
+
+ if (T->isFunctionType() || T->isArrayType()) {
+ // Decay functions and arrays.
+ Expr *RefE = (Expr *)RefExpr.get();
+ DefaultFunctionArrayConversion(RefE);
+ if (RefE != RefExpr.get()) {
+ RefExpr.release();
+ RefExpr = Owned(RefE);
+ }
+
+ return move(RefExpr);
+ }
+
+ // Take the address of everything else
+ return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
+ }
+
+ ExprValueKind VK = VK_RValue;
+
+ // If the non-type template parameter has reference type, qualify the
+ // resulting declaration reference with the extra qualifiers on the
+ // type that the reference refers to.
+ if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) {
+ VK = VK_LValue;
+ T = Context.getQualifiedType(T,
+ TargetRef->getPointeeType().getQualifiers());
+ }
+
+ return BuildDeclRefExpr(VD, T, VK, Loc);
+}
+
+/// \brief Construct a new expression that refers to the given
+/// integral template argument with the given source-location
+/// information.
+///
+/// This routine takes care of the mapping from an integral template
+/// argument (which may have any integral type) to the appropriate
+/// literal value.
+ExprResult
+Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc) {
+ assert(Arg.getKind() == TemplateArgument::Integral &&
+ "Operation is only valid for integral template arguments");
+ QualType T = Arg.getIntegralType();
+ if (T->isCharType() || T->isWideCharType())
+ return Owned(new (Context) CharacterLiteral(
+ Arg.getAsIntegral()->getZExtValue(),
+ T->isWideCharType(),
+ T,
+ Loc));
+ if (T->isBooleanType())
+ return Owned(new (Context) CXXBoolLiteralExpr(
+ Arg.getAsIntegral()->getBoolValue(),
+ T,
+ Loc));
+
+ QualType BT;
+ if (const EnumType *ET = T->getAs<EnumType>())
+ BT = ET->getDecl()->getPromotionType();
+ else
+ BT = T;
+
+ Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
+ if (T->isEnumeralType()) {
+ // FIXME: This is a hack. We need a better way to handle substituted
+ // non-type template parameters.
+ E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast,
+ E, 0,
+ Context.getTrivialTypeSourceInfo(T, Loc),
+ Loc, Loc);
+ }
+
+ return Owned(E);
+}
+
+/// \brief Match two template parameters within template parameter lists.
+static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
+ bool Complain,
+ Sema::TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc) {
+ // Check the actual kind (type, non-type, template).
+ if (Old->getKind() != New->getKind()) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_param_different_kind;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_different_kind;
+ }
+ S.Diag(New->getLocation(), NextDiag)
+ << (Kind != Sema::TPL_TemplateMatch);
+ S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
+ << (Kind != Sema::TPL_TemplateMatch);
+ }
+
+ return false;
+ }
+
+ // Check that both are parameter packs are neither are parameter packs.
+ // However, if we are matching a template template argument to a
+ // template template parameter, the template template parameter can have
+ // a parameter pack where the template template argument does not.
+ if (Old->isTemplateParameterPack() != New->isTemplateParameterPack() &&
+ !(Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
+ Old->isTemplateParameterPack())) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_parameter_pack_non_pack;
+ }
+
+ unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
+ : isa<NonTypeTemplateParmDecl>(New)? 1
+ : 2;
+ S.Diag(New->getLocation(), NextDiag)
+ << ParamKind << New->isParameterPack();
+ S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
+ << ParamKind << Old->isParameterPack();
+ }
+
+ return false;
+ }
+
+ // For non-type template parameters, check the type of the parameter.
+ if (NonTypeTemplateParmDecl *OldNTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Old)) {
+ NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);
+
+ // If we are matching a template template argument to a template
+ // template parameter and one of the non-type template parameter types
+ // is dependent, then we must wait until template instantiation time
+ // to actually compare the arguments.
+ if (Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
+ (OldNTTP->getType()->isDependentType() ||
+ NewNTTP->getType()->isDependentType()))
+ return true;
+
+ if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_nontype_parm_different_type;
+ }
+ S.Diag(NewNTTP->getLocation(), NextDiag)
+ << NewNTTP->getType()
+ << (Kind != Sema::TPL_TemplateMatch);
+ S.Diag(OldNTTP->getLocation(),
+ diag::note_template_nontype_parm_prev_declaration)
+ << OldNTTP->getType();
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ // For template template parameters, check the template parameter types.
+ // The template parameter lists of template template
+ // parameters must agree.
+ if (TemplateTemplateParmDecl *OldTTP
+ = dyn_cast<TemplateTemplateParmDecl>(Old)) {
+ TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);
+ return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
+ OldTTP->getTemplateParameters(),
+ Complain,
+ (Kind == Sema::TPL_TemplateMatch
+ ? Sema::TPL_TemplateTemplateParmMatch
+ : Kind),
+ TemplateArgLoc);
+ }
+
+ return true;
+}
+
+/// \brief Diagnose a known arity mismatch when comparing template argument
+/// lists.
+static
+void DiagnoseTemplateParameterListArityMismatch(Sema &S,
+ TemplateParameterList *New,
+ TemplateParameterList *Old,
+ Sema::TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc) {
+ unsigned NextDiag = diag::err_template_param_list_different_arity;
+ if (TemplateArgLoc.isValid()) {
+ S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_list_different_arity;
+ }
+ S.Diag(New->getTemplateLoc(), NextDiag)
+ << (New->size() > Old->size())
+ << (Kind != Sema::TPL_TemplateMatch)
+ << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
+ S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
+ << (Kind != Sema::TPL_TemplateMatch)
+ << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
+}
+
+/// \brief Determine whether the given template parameter lists are
+/// equivalent.
+///
+/// \param New The new template parameter list, typically written in the
+/// source code as part of a new template declaration.
+///
+/// \param Old The old template parameter list, typically found via
+/// name lookup of the template declared with this template parameter
+/// list.
+///
+/// \param Complain If true, this routine will produce a diagnostic if
+/// the template parameter lists are not equivalent.
+///
+/// \param Kind describes how we are to match the template parameter lists.
+///
+/// \param TemplateArgLoc If this source location is valid, then we
+/// are actually checking the template parameter list of a template
+/// argument (New) against the template parameter list of its
+/// corresponding template template parameter (Old). We produce
+/// slightly different diagnostics in this scenario.
+///
+/// \returns True if the template parameter lists are equal, false
+/// otherwise.
+bool
+Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
+ TemplateParameterList *Old,
+ bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc) {
+ if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) {
+ if (Complain)
+ DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+ TemplateArgLoc);
+
+ return false;
+ }
+
+ // C++0x [temp.arg.template]p3:
+ // A template-argument matches a template template-parameter (call it P)
+ // when each of the template parameters in the template-parameter-list of
+ // the template-argument's corresponding class template or template alias
+ // (call it A) matches the corresponding template parameter in the
+ // template-parameter-list of P. [...]
+ TemplateParameterList::iterator NewParm = New->begin();
+ TemplateParameterList::iterator NewParmEnd = New->end();
+ for (TemplateParameterList::iterator OldParm = Old->begin(),
+ OldParmEnd = Old->end();
+ OldParm != OldParmEnd; ++OldParm) {
+ if (Kind != TPL_TemplateTemplateArgumentMatch ||
+ !(*OldParm)->isTemplateParameterPack()) {
+ if (NewParm == NewParmEnd) {
+ if (Complain)
+ DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+ TemplateArgLoc);
+
+ return false;
+ }
+
+ if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+ Kind, TemplateArgLoc))
+ return false;
+
+ ++NewParm;
+ continue;
+ }
+
+ // C++0x [temp.arg.template]p3:
+ // [...] When P's template- parameter-list contains a template parameter
+ // pack (14.5.3), the template parameter pack will match zero or more
+ // template parameters or template parameter packs in the
+ // template-parameter-list of A with the same type and form as the
+ // template parameter pack in P (ignoring whether those template
+ // parameters are template parameter packs).
+ for (; NewParm != NewParmEnd; ++NewParm) {
+ if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+ Kind, TemplateArgLoc))
+ return false;
+ }
+ }
+
+ // Make sure we exhausted all of the arguments.
+ if (NewParm != NewParmEnd) {
+ if (Complain)
+ DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
+ TemplateArgLoc);
+
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Check whether a template can be declared within this scope.
+///
+/// If the template declaration is valid in this scope, returns
+/// false. Otherwise, issues a diagnostic and returns true.
+bool
+Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
+ // Find the nearest enclosing declaration scope.
+ while ((S->getFlags() & Scope::DeclScope) == 0 ||
+ (S->getFlags() & Scope::TemplateParamScope) != 0)
+ S = S->getParent();
+
+ // C++ [temp]p2:
+ // A template-declaration can appear only as a namespace scope or
+ // class scope declaration.
+ DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
+ if (Ctx && isa<LinkageSpecDecl>(Ctx) &&
+ cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx)
+ return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
+ << TemplateParams->getSourceRange();
+
+ while (Ctx && isa<LinkageSpecDecl>(Ctx))
+ Ctx = Ctx->getParent();
+
+ if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
+ return false;
+
+ return Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_outside_namespace_or_class_scope)
+ << TemplateParams->getSourceRange();
+}
+
+/// \brief Determine what kind of template specialization the given declaration
+/// is.
+static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) {
+ if (!D)
+ return TSK_Undeclared;
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
+ return Record->getTemplateSpecializationKind();
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+ return Function->getTemplateSpecializationKind();
+ if (VarDecl *Var = dyn_cast<VarDecl>(D))
+ return Var->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+/// \brief Check whether a specialization is well-formed in the current
+/// context.
+///
+/// This routine determines whether a template specialization can be declared
+/// in the current context (C++ [temp.expl.spec]p2).
+///
+/// \param S the semantic analysis object for which this check is being
+/// performed.
+///
+/// \param Specialized the entity being specialized or instantiated, which
+/// may be a kind of template (class template, function template, etc.) or
+/// a member of a class template (member function, static data member,
+/// member class).
+///
+/// \param PrevDecl the previous declaration of this entity, if any.
+///
+/// \param Loc the location of the explicit specialization or instantiation of
+/// this entity.
+///
+/// \param IsPartialSpecialization whether this is a partial specialization of
+/// a class template.
+///
+/// \returns true if there was an error that we cannot recover from, false
+/// otherwise.
+static bool CheckTemplateSpecializationScope(Sema &S,
+ NamedDecl *Specialized,
+ NamedDecl *PrevDecl,
+ SourceLocation Loc,
+ bool IsPartialSpecialization) {
+ // Keep these "kind" numbers in sync with the %select statements in the
+ // various diagnostics emitted by this routine.
+ int EntityKind = 0;
+ if (isa<ClassTemplateDecl>(Specialized))
+ EntityKind = IsPartialSpecialization? 1 : 0;
+ else if (isa<FunctionTemplateDecl>(Specialized))
+ EntityKind = 2;
+ else if (isa<CXXMethodDecl>(Specialized))
+ EntityKind = 3;
+ else if (isa<VarDecl>(Specialized))
+ EntityKind = 4;
+ else if (isa<RecordDecl>(Specialized))
+ EntityKind = 5;
+ else {
+ S.Diag(Loc, diag::err_template_spec_unknown_kind);
+ S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+ return true;
+ }
+
+ // C++ [temp.expl.spec]p2:
+ // An explicit specialization shall be declared in the namespace
+ // of which the template is a member, or, for member templates, in
+ // the namespace of which the enclosing class or enclosing class
+ // template is a member. An explicit specialization of a member
+ // function, member class or static data member of a class
+ // template shall be declared in the namespace of which the class
+ // template is a member. Such a declaration may also be a
+ // definition. If the declaration is not a definition, the
+ // specialization may be defined later in the name- space in which
+ // the explicit specialization was declared, or in a namespace
+ // that encloses the one in which the explicit specialization was
+ // declared.
+ if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
+ S.Diag(Loc, diag::err_template_spec_decl_function_scope)
+ << Specialized;
+ return true;
+ }
+
+ if (S.CurContext->isRecord() && !IsPartialSpecialization) {
+ S.Diag(Loc, diag::err_template_spec_decl_class_scope)
+ << Specialized;
+ return true;
+ }
+
+ // C++ [temp.class.spec]p6:
+ // A class template partial specialization may be declared or redeclared
+ // in any namespace scope in which its definition may be defined (14.5.1
+ // and 14.5.2).
+ bool ComplainedAboutScope = false;
+ DeclContext *SpecializedContext
+ = Specialized->getDeclContext()->getEnclosingNamespaceContext();
+ DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
+ if ((!PrevDecl ||
+ getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
+ getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
+ // C++ [temp.exp.spec]p2:
+ // An explicit specialization shall be declared in the namespace of which
+ // the template is a member, or, for member templates, in the namespace
+ // of which the enclosing class or enclosing class template is a member.
+ // An explicit specialization of a member function, member class or
+ // static data member of a class template shall be declared in the
+ // namespace of which the class template is a member.
+ //
+ // C++0x [temp.expl.spec]p2:
+ // An explicit specialization shall be declared in a namespace enclosing
+ // the specialized template.
+ if (!DC->InEnclosingNamespaceSetOf(SpecializedContext) &&
+ !(S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext))) {
+ bool IsCPlusPlus0xExtension
+ = !S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext);
+ if (isa<TranslationUnitDecl>(SpecializedContext))
+ S.Diag(Loc, IsCPlusPlus0xExtension
+ ? diag::ext_template_spec_decl_out_of_scope_global
+ : diag::err_template_spec_decl_out_of_scope_global)
+ << EntityKind << Specialized;
+ else if (isa<NamespaceDecl>(SpecializedContext))
+ S.Diag(Loc, IsCPlusPlus0xExtension
+ ? diag::ext_template_spec_decl_out_of_scope
+ : diag::err_template_spec_decl_out_of_scope)
+ << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+
+ S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+ ComplainedAboutScope = true;
+ }
+ }
+
+ // Make sure that this redeclaration (or definition) occurs in an enclosing
+ // namespace.
+ // Note that HandleDeclarator() performs this check for explicit
+ // specializations of function templates, static data members, and member
+ // functions, so we skip the check here for those kinds of entities.
+ // FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
+ // Should we refactor that check, so that it occurs later?
+ if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) &&
+ !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) ||
+ isa<FunctionDecl>(Specialized))) {
+ if (isa<TranslationUnitDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
+ << EntityKind << Specialized;
+ else if (isa<NamespaceDecl>(SpecializedContext))
+ S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope)
+ << EntityKind << Specialized
+ << cast<NamedDecl>(SpecializedContext);
+
+ S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
+ }
+
+ // FIXME: check for specialization-after-instantiation errors and such.
+
+ return false;
+}
+
+/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs
+/// that checks non-type template partial specialization arguments.
+static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ if (Args[I].getKind() == TemplateArgument::Pack) {
+ if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
+ Args[I].pack_begin(),
+ Args[I].pack_size()))
+ return true;
+
+ continue;
+ }
+
+ Expr *ArgExpr = Args[I].getAsExpr();
+ if (!ArgExpr) {
+ continue;
+ }
+
+ // We can have a pack expansion of any of the bullets below.
+ if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
+ ArgExpr = Expansion->getPattern();
+
+ // Strip off any implicit casts we added as part of type checking.
+ while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
+ ArgExpr = ICE->getSubExpr();
+
+ // C++ [temp.class.spec]p8:
+ // A non-type argument is non-specialized if it is the name of a
+ // non-type parameter. All other non-type arguments are
+ // specialized.
+ //
+ // Below, we check the two conditions that only apply to
+ // specialized non-type arguments, so skip any non-specialized
+ // arguments.
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
+ if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
+ continue;
+
+ // C++ [temp.class.spec]p9:
+ // Within the argument list of a class template partial
+ // specialization, the following restrictions apply:
+ // -- A partially specialized non-type argument expression
+ // shall not involve a template parameter of the partial
+ // specialization except when the argument expression is a
+ // simple identifier.
+ if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
+ S.Diag(ArgExpr->getLocStart(),
+ diag::err_dependent_non_type_arg_in_partial_spec)
+ << ArgExpr->getSourceRange();
+ return true;
+ }
+
+ // -- The type of a template parameter corresponding to a
+ // specialized non-type argument shall not be dependent on a
+ // parameter of the specialization.
+ if (Param->getType()->isDependentType()) {
+ S.Diag(ArgExpr->getLocStart(),
+ diag::err_dependent_typed_non_type_arg_in_partial_spec)
+ << Param->getType()
+ << ArgExpr->getSourceRange();
+ S.Diag(Param->getLocation(), diag::note_template_param_here);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// \brief Check the non-type template arguments of a class template
+/// partial specialization according to C++ [temp.class.spec]p9.
+///
+/// \param TemplateParams the template parameters of the primary class
+/// template.
+///
+/// \param TemplateArg the template arguments of the class template
+/// partial specialization.
+///
+/// \returns true if there was an error, false otherwise.
+static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
+ TemplateParameterList *TemplateParams,
+ llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) {
+ const TemplateArgument *ArgList = TemplateArgs.data();
+
+ for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+ NonTypeTemplateParmDecl *Param
+ = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
+ if (!Param)
+ continue;
+
+ if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
+ &ArgList[I], 1))
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Retrieve the previous declaration of the given declaration.
+static NamedDecl *getPreviousDecl(NamedDecl *ND) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(ND))
+ return VD->getPreviousDeclaration();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ return FD->getPreviousDeclaration();
+ if (TagDecl *TD = dyn_cast<TagDecl>(ND))
+ return TD->getPreviousDeclaration();
+ if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
+ return TD->getPreviousDeclaration();
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ return FTD->getPreviousDeclaration();
+ if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
+ return CTD->getPreviousDeclaration();
+ return 0;
+}
+
+DeclResult
+Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
+ TagUseKind TUK,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ TemplateTy TemplateD,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists) {
+ assert(TUK != TUK_Reference && "References are not specializations");
+
+ // Find the class template we're specializing
+ TemplateName Name = TemplateD.getAsVal<TemplateName>();
+ ClassTemplateDecl *ClassTemplate
+ = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+ if (!ClassTemplate) {
+ Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
+ << (Name.getAsTemplateDecl() &&
+ isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
+ return true;
+ }
+
+ bool isExplicitSpecialization = false;
+ bool isPartialSpecialization = false;
+
+ // Check the validity of the template headers that introduce this
+ // template.
+ // FIXME: We probably shouldn't complain about these headers for
+ // friend declarations.
+ bool Invalid = false;
+ TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
+ (TemplateParameterList**)TemplateParameterLists.get(),
+ TemplateParameterLists.size(),
+ TUK == TUK_Friend,
+ isExplicitSpecialization,
+ Invalid);
+ if (Invalid)
+ return true;
+
+ unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+ if (TemplateParams)
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams && TemplateParams->size() > 0) {
+ isPartialSpecialization = true;
+
+ if (TUK == TUK_Friend) {
+ Diag(KWLoc, diag::err_partial_specialization_friend)
+ << SourceRange(LAngleLoc, RAngleLoc);
+ return true;
+ }
+
+ // C++ [temp.class.spec]p10:
+ // The template parameter list of a specialization shall not
+ // contain default template argument values.
+ for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+ Decl *Param = TemplateParams->getParam(I);
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (TTP->hasDefaultArgument()) {
+ Diag(TTP->getDefaultArgumentLoc(),
+ diag::err_default_arg_in_partial_spec);
+ TTP->removeDefaultArgument();
+ }
+ } else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ if (Expr *DefArg = NTTP->getDefaultArgument()) {
+ Diag(NTTP->getDefaultArgumentLoc(),
+ diag::err_default_arg_in_partial_spec)
+ << DefArg->getSourceRange();
+ NTTP->removeDefaultArgument();
+ }
+ } else {
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
+ if (TTP->hasDefaultArgument()) {
+ Diag(TTP->getDefaultArgument().getLocation(),
+ diag::err_default_arg_in_partial_spec)
+ << TTP->getDefaultArgument().getSourceRange();
+ TTP->removeDefaultArgument();
+ }
+ }
+ }
+ } else if (TemplateParams) {
+ if (TUK == TUK_Friend)
+ Diag(KWLoc, diag::err_template_spec_friend)
+ << FixItHint::CreateRemoval(
+ SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc()))
+ << SourceRange(LAngleLoc, RAngleLoc);
+ else
+ isExplicitSpecialization = true;
+ } else if (TUK != TUK_Friend) {
+ Diag(KWLoc, diag::err_template_spec_needs_header)
+ << FixItHint::CreateInsertion(KWLoc, "template<> ");
+ isExplicitSpecialization = true;
+ }
+
+ // Check that the specialization uses the same tag kind as the
+ // original template.
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+ assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");
+ if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+ Kind, KWLoc,
+ *ClassTemplate->getIdentifier())) {
+ Diag(KWLoc, diag::err_use_with_wrong_tag)
+ << ClassTemplate
+ << FixItHint::CreateReplacement(KWLoc,
+ ClassTemplate->getTemplatedDecl()->getKindName());
+ Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+ diag::note_previous_use);
+ Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+ }
+
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs;
+ TemplateArgs.setLAngleLoc(LAngleLoc);
+ TemplateArgs.setRAngleLoc(RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ // Check for unexpanded parameter packs in any of the template arguments.
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
+ UPPC_PartialSpecialization))
+ return true;
+
+ // Check that the template argument list is well-formed for this
+ // template.
+ llvm::SmallVector<TemplateArgument, 4> Converted;
+ if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+ TemplateArgs, false, Converted))
+ return true;
+
+ assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) &&
+ "Converted template argument list is too short!");
+
+ // Find the class template (partial) specialization declaration that
+ // corresponds to these arguments.
+ if (isPartialSpecialization) {
+ if (CheckClassTemplatePartialSpecializationArgs(*this,
+ ClassTemplate->getTemplateParameters(),
+ Converted))
+ return true;
+
+ if (!Name.isDependent() &&
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs.getArgumentArray(),
+ TemplateArgs.size())) {
+ Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+ << ClassTemplate->getDeclName();
+ isPartialSpecialization = false;
+ }
+ }
+
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *PrevDecl = 0;
+
+ if (isPartialSpecialization)
+ // FIXME: Template parameter list matters, too
+ PrevDecl
+ = ClassTemplate->findPartialSpecialization(Converted.data(),
+ Converted.size(),
+ InsertPos);
+ else
+ PrevDecl
+ = ClassTemplate->findSpecialization(Converted.data(),
+ Converted.size(), InsertPos);
+
+ ClassTemplateSpecializationDecl *Specialization = 0;
+
+ // Check whether we can declare a class template specialization in
+ // the current scope.
+ if (TUK != TUK_Friend &&
+ CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
+ TemplateNameLoc,
+ isPartialSpecialization))
+ return true;
+
+ // The canonical type
+ QualType CanonType;
+ if (PrevDecl &&
+ (PrevDecl->getSpecializationKind() == TSK_Undeclared ||
+ TUK == TUK_Friend)) {
+ // Since the only prior class template specialization with these
+ // arguments was referenced but not declared, or we're only
+ // referencing this specialization as a friend, reuse that
+ // declaration node as our own, updating its source location to
+ // reflect our new declaration.
+ Specialization = PrevDecl;
+ Specialization->setLocation(TemplateNameLoc);
+ PrevDecl = 0;
+ CanonType = Context.getTypeDeclType(Specialization);
+ } else if (isPartialSpecialization) {
+ // Build the canonical type that describes the converted template
+ // arguments of the class template partial specialization.
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(CanonTemplate,
+ Converted.data(),
+ Converted.size());
+
+ if (Context.hasSameType(CanonType,
+ ClassTemplate->getInjectedClassNameSpecialization())) {
+ // C++ [temp.class.spec]p9b3:
+ //
+ // -- The argument list of the specialization shall not be identical
+ // to the implicit argument list of the primary template.
+ Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
+ << (TUK == TUK_Definition)
+ << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
+ return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
+ ClassTemplate->getIdentifier(),
+ TemplateNameLoc,
+ Attr,
+ TemplateParams,
+ AS_none);
+ }
+
+ // Create a new class template partial specialization declaration node.
+ ClassTemplatePartialSpecializationDecl *PrevPartial
+ = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
+ unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber()
+ : ClassTemplate->getNextPartialSpecSequenceNumber();
+ ClassTemplatePartialSpecializationDecl *Partial
+ = ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
+ ClassTemplate->getDeclContext(),
+ TemplateNameLoc,
+ TemplateParams,
+ ClassTemplate,
+ Converted.data(),
+ Converted.size(),
+ TemplateArgs,
+ CanonType,
+ PrevPartial,
+ SequenceNumber);
+ SetNestedNameSpecifier(Partial, SS);
+ if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+ Partial->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
+
+ if (!PrevPartial)
+ ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
+ Specialization = Partial;
+
+ // If we are providing an explicit specialization of a member class
+ // template specialization, make a note of that.
+ if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+ PrevPartial->setMemberSpecialization();
+
+ // Check that all of the template parameters of the class template
+ // partial specialization are deducible from the template
+ // arguments. If not, this class template partial specialization
+ // will never be used.
+ llvm::SmallVector<bool, 8> DeducibleParams;
+ DeducibleParams.resize(TemplateParams->size());
+ MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+ TemplateParams->getDepth(),
+ DeducibleParams);
+ unsigned NumNonDeducible = 0;
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I)
+ if (!DeducibleParams[I])
+ ++NumNonDeducible;
+
+ if (NumNonDeducible) {
+ Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
+ << (NumNonDeducible > 1)
+ << SourceRange(TemplateNameLoc, RAngleLoc);
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+ if (!DeducibleParams[I]) {
+ NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ if (Param->getDeclName())
+ Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << Param->getDeclName();
+ else
+ Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << "<anonymous>";
+ }
+ }
+ }
+ } else {
+ // Create a new class template specialization declaration node for
+ // this explicit specialization or friend declaration.
+ Specialization
+ = ClassTemplateSpecializationDecl::Create(Context, Kind,
+ ClassTemplate->getDeclContext(),
+ TemplateNameLoc,
+ ClassTemplate,
+ Converted.data(),
+ Converted.size(),
+ PrevDecl);
+ SetNestedNameSpecifier(Specialization, SS);
+ if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
+ Specialization->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
+
+ if (!PrevDecl)
+ ClassTemplate->AddSpecialization(Specialization, InsertPos);
+
+ CanonType = Context.getTypeDeclType(Specialization);
+ }
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that specialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+ bool Okay = false;
+ for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+ // Is there any previous explicit specialization declaration?
+ if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+ Okay = true;
+ break;
+ }
+ }
+
+ if (!Okay) {
+ SourceRange Range(TemplateNameLoc, RAngleLoc);
+ Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+ << Context.getTypeDeclType(Specialization) << Range;
+
+ Diag(PrevDecl->getPointOfInstantiation(),
+ diag::note_instantiation_required_here)
+ << (PrevDecl->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation);
+ return true;
+ }
+ }
+
+ // If this is not a friend, note that this is an explicit specialization.
+ if (TUK != TUK_Friend)
+ Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
+
+ // Check that this isn't a redefinition of this specialization.
+ if (TUK == TUK_Definition) {
+ if (RecordDecl *Def = Specialization->getDefinition()) {
+ SourceRange Range(TemplateNameLoc, RAngleLoc);
+ Diag(TemplateNameLoc, diag::err_redefinition)
+ << Context.getTypeDeclType(Specialization) << Range;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ Specialization->setInvalidDecl();
+ return true;
+ }
+ }
+
+ if (Attr)
+ ProcessDeclAttributeList(S, Specialization, Attr);
+
+ // Build the fully-sugared type for this class template
+ // specialization as the user wrote in the specialization
+ // itself. This means that we'll pretty-print the type retrieved
+ // from the specialization's declaration the way that the user
+ // actually wrote the specialization, rather than formatting the
+ // name based on the "canonical" representation used to store the
+ // template arguments in the specialization.
+ TypeSourceInfo *WrittenTy
+ = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+ TemplateArgs, CanonType);
+ if (TUK != TUK_Friend) {
+ Specialization->setTypeAsWritten(WrittenTy);
+ if (TemplateParams)
+ Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc());
+ }
+ TemplateArgsIn.release();
+
+ // C++ [temp.expl.spec]p9:
+ // A template explicit specialization is in the scope of the
+ // namespace in which the template was defined.
+ //
+ // We actually implement this paragraph where we set the semantic
+ // context (in the creation of the ClassTemplateSpecializationDecl),
+ // but we also maintain the lexical context where the actual
+ // definition occurs.
+ Specialization->setLexicalDeclContext(CurContext);
+
+ // We may be starting the definition of this specialization.
+ if (TUK == TUK_Definition)
+ Specialization->startDefinition();
+
+ if (TUK == TUK_Friend) {
+ FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
+ TemplateNameLoc,
+ WrittenTy,
+ /*FIXME:*/KWLoc);
+ Friend->setAccess(AS_public);
+ CurContext->addDecl(Friend);
+ } else {
+ // Add the specialization into its lexical context, so that it can
+ // be seen when iterating through the list of declarations in that
+ // context. However, specializations are not found by name lookup.
+ CurContext->addDecl(Specialization);
+ }
+ return Specialization;
+}
+
+Decl *Sema::ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D) {
+ return HandleDeclarator(S, D, move(TemplateParameterLists), false);
+}
+
+Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D) {
+ assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+
+ if (FTI.hasPrototype) {
+ // FIXME: Diagnose arguments without names in C.
+ }
+
+ Scope *ParentScope = FnBodyScope->getParent();
+
+ Decl *DP = HandleDeclarator(ParentScope, D,
+ move(TemplateParameterLists),
+ /*IsFunctionDefinition=*/true);
+ if (FunctionTemplateDecl *FunctionTemplate
+ = dyn_cast_or_null<FunctionTemplateDecl>(DP))
+ return ActOnStartOfFunctionDef(FnBodyScope,
+ FunctionTemplate->getTemplatedDecl());
+ if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP))
+ return ActOnStartOfFunctionDef(FnBodyScope, Function);
+ return 0;
+}
+
+/// \brief Strips various properties off an implicit instantiation
+/// that has just been explicitly specialized.
+static void StripImplicitInstantiation(NamedDecl *D) {
+ D->dropAttrs();
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ FD->setInlineSpecified(false);
+ }
+}
+
+/// \brief Diagnose cases where we have an explicit template specialization
+/// before/after an explicit template instantiation, producing diagnostics
+/// for those cases where they are required and determining whether the
+/// new specialization/instantiation will have any effect.
+///
+/// \param NewLoc the location of the new explicit specialization or
+/// instantiation.
+///
+/// \param NewTSK the kind of the new explicit specialization or instantiation.
+///
+/// \param PrevDecl the previous declaration of the entity.
+///
+/// \param PrevTSK the kind of the old explicit specialization or instantiatin.
+///
+/// \param PrevPointOfInstantiation if valid, indicates where the previus
+/// declaration was instantiated (either implicitly or explicitly).
+///
+/// \param HasNoEffect will be set to true to indicate that the new
+/// specialization or instantiation has no effect and should be ignored.
+///
+/// \returns true if there was an error that should prevent the introduction of
+/// the new declaration into the AST, false otherwise.
+bool
+Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &HasNoEffect) {
+ HasNoEffect = false;
+
+ switch (NewTSK) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ assert(false && "Don't check implicit instantiations here");
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ switch (PrevTSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ // Okay, we're just specializing something that is either already
+ // explicitly specialized or has merely been mentioned without any
+ // instantiation.
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ if (PrevPointOfInstantiation.isInvalid()) {
+ // The declaration itself has not actually been instantiated, so it is
+ // still okay to specialize it.
+ StripImplicitInstantiation(PrevDecl);
+ return false;
+ }
+ // Fall through
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ assert((PrevTSK == TSK_ImplicitInstantiation ||
+ PrevPointOfInstantiation.isValid()) &&
+ "Explicit instantiation without point of instantiation?");
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template
+ // is explicitly specialized then that specialization shall be declared
+ // before the first use of that specialization that would cause an
+ // implicit instantiation to take place, in every translation unit in
+ // which such a use occurs; no diagnostic is required.
+ for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+ // Is there any previous explicit specialization declaration?
+ if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
+ return false;
+ }
+
+ Diag(NewLoc, diag::err_specialization_after_instantiation)
+ << PrevDecl;
+ Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+ << (PrevTSK != TSK_ImplicitInstantiation);
+
+ return true;
+ }
+ break;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ switch (PrevTSK) {
+ case TSK_ExplicitInstantiationDeclaration:
+ // This explicit instantiation declaration is redundant (that's okay).
+ HasNoEffect = true;
+ return false;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We're explicitly instantiating something that may have already been
+ // implicitly instantiated; that's fine.
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ // C++0x [temp.explicit]p4:
+ // For a given set of template parameters, if an explicit instantiation
+ // of a template appears after a declaration of an explicit
+ // specialization for that template, the explicit instantiation has no
+ // effect.
+ HasNoEffect = true;
+ return false;
+
+ case TSK_ExplicitInstantiationDefinition:
+ // C++0x [temp.explicit]p10:
+ // If an entity is the subject of both an explicit instantiation
+ // declaration and an explicit instantiation definition in the same
+ // translation unit, the definition shall follow the declaration.
+ Diag(NewLoc,
+ diag::err_explicit_instantiation_declaration_after_definition);
+ Diag(PrevPointOfInstantiation,
+ diag::note_explicit_instantiation_definition_here);
+ assert(PrevPointOfInstantiation.isValid() &&
+ "Explicit instantiation without point of instantiation?");
+ HasNoEffect = true;
+ return false;
+ }
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ switch (PrevTSK) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We're explicitly instantiating something that may have already been
+ // implicitly instantiated; that's fine.
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ // C++ DR 259, C++0x [temp.explicit]p4:
+ // For a given set of template parameters, if an explicit
+ // instantiation of a template appears after a declaration of
+ // an explicit specialization for that template, the explicit
+ // instantiation has no effect.
+ //
+ // In C++98/03 mode, we only give an extension warning here, because it
+ // is not harmful to try to explicitly instantiate something that
+ // has been explicitly specialized.
+ if (!getLangOptions().CPlusPlus0x) {
+ Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
+ << PrevDecl;
+ Diag(PrevDecl->getLocation(),
+ diag::note_previous_template_specialization);
+ }
+ HasNoEffect = true;
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ // We're explicity instantiating a definition for something for which we
+ // were previously asked to suppress instantiations. That's fine.
+ return false;
+
+ case TSK_ExplicitInstantiationDefinition:
+ // C++0x [temp.spec]p5:
+ // For a given template and a given set of template-arguments,
+ // - an explicit instantiation definition shall appear at most once
+ // in a program,
+ Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+ << PrevDecl;
+ Diag(PrevPointOfInstantiation,
+ diag::note_previous_explicit_instantiation);
+ HasNoEffect = true;
+ return false;
+ }
+ break;
+ }
+
+ assert(false && "Missing specialization/instantiation case?");
+
+ return false;
+}
+
+/// \brief Perform semantic analysis for the given dependent function
+/// template specialization. The only possible way to get a dependent
+/// function template specialization is with a friend declaration,
+/// like so:
+///
+/// template <class T> void foo(T);
+/// template <class T> class A {
+/// friend void foo<>(T);
+/// };
+///
+/// There really isn't any useful analysis we can do here, so we
+/// just store the information.
+bool
+Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ LookupResult &Previous) {
+ // Remove anything from Previous that isn't a function template in
+ // the correct context.
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next()->getUnderlyingDecl();
+ if (!isa<FunctionTemplateDecl>(D) ||
+ !FDLookupContext->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
+ F.erase();
+ }
+ F.done();
+
+ // Should this be diagnosed here?
+ if (Previous.empty()) return true;
+
+ FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
+ ExplicitTemplateArgs);
+ return false;
+}
+
+/// \brief Perform semantic analysis for the given function template
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an
+/// explicit function template specialization. On successful completion,
+/// the function declaration \p FD will become a function template
+/// specialization.
+///
+/// \param FD the function declaration, which will be updated to become a
+/// function template specialization.
+///
+/// \param ExplicitTemplateArgs the explicitly-provided template arguments,
+/// if any. Note that this may be valid info even when 0 arguments are
+/// explicitly provided as in, e.g., \c void sort<>(char*, char*);
+/// as it anyway contains info on the angle brackets locations.
+///
+/// \param PrevDecl the set of declarations that may be specialized by
+/// this function specialization.
+bool
+Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous) {
+ // The set of function template specializations that could match this
+ // explicit function template specialization.
+ UnresolvedSet<8> Candidates;
+
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *Ovl = (*I)->getUnderlyingDecl();
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
+ // Only consider templates found within the same semantic lookup scope as
+ // FD.
+ if (!FDLookupContext->InEnclosingNamespaceSetOf(
+ Ovl->getDeclContext()->getRedeclContext()))
+ continue;
+
+ // C++ [temp.expl.spec]p11:
+ // A trailing template-argument can be left unspecified in the
+ // template-id naming an explicit function template specialization
+ // provided it can be deduced from the function argument type.
+ // Perform template argument deduction to determine whether we may be
+ // specializing this template.
+ // FIXME: It is somewhat wasteful to build
+ TemplateDeductionInfo Info(Context, FD->getLocation());
+ FunctionDecl *Specialization = 0;
+ if (TemplateDeductionResult TDK
+ = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
+ FD->getType(),
+ Specialization,
+ Info)) {
+ // FIXME: Template argument deduction failed; record why it failed, so
+ // that we can provide nifty diagnostics.
+ (void)TDK;
+ continue;
+ }
+
+ // Record this candidate.
+ Candidates.addDecl(Specialization, I.getAccess());
+ }
+ }
+
+ // Find the most specialized function template.
+ UnresolvedSetIterator Result
+ = getMostSpecialized(Candidates.begin(), Candidates.end(),
+ TPOC_Other, 0, FD->getLocation(),
+ PDiag(diag::err_function_template_spec_no_match)
+ << FD->getDeclName(),
+ PDiag(diag::err_function_template_spec_ambiguous)
+ << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+ PDiag(diag::note_function_template_spec_matched));
+ if (Result == Candidates.end())
+ return true;
+
+ // Ignore access information; it doesn't figure into redeclaration checking.
+ FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+ Specialization->setLocation(FD->getLocation());
+
+ // FIXME: Check if the prior specialization has a point of instantiation.
+ // If so, we have run afoul of .
+
+ // If this is a friend declaration, then we're not really declaring
+ // an explicit specialization.
+ bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);
+
+ // Check the scope of this explicit specialization.
+ if (!isFriend &&
+ CheckTemplateSpecializationScope(*this,
+ Specialization->getPrimaryTemplate(),
+ Specialization, FD->getLocation(),
+ false))
+ return true;
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that specialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ FunctionTemplateSpecializationInfo *SpecInfo
+ = Specialization->getTemplateSpecializationInfo();
+ assert(SpecInfo && "Function template specialization info missing?");
+
+ bool HasNoEffect = false;
+ if (!isFriend &&
+ CheckSpecializationInstantiationRedecl(FD->getLocation(),
+ TSK_ExplicitSpecialization,
+ Specialization,
+ SpecInfo->getTemplateSpecializationKind(),
+ SpecInfo->getPointOfInstantiation(),
+ HasNoEffect))
+ return true;
+
+ // Mark the prior declaration as an explicit specialization, so that later
+ // clients know that this is an explicit specialization.
+ if (!isFriend) {
+ SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(Specialization);
+ }
+
+ // Turn the given function declaration into a function template
+ // specialization, with the template arguments from the previous
+ // specialization.
+ // Take copies of (semantic and syntactic) template argument lists.
+ const TemplateArgumentList* TemplArgs = new (Context)
+ TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
+ const TemplateArgumentListInfo* TemplArgsAsWritten = ExplicitTemplateArgs
+ ? new (Context) TemplateArgumentListInfo(*ExplicitTemplateArgs) : 0;
+ FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
+ TemplArgs, /*InsertPos=*/0,
+ SpecInfo->getTemplateSpecializationKind(),
+ TemplArgsAsWritten);
+
+ // The "previous declaration" for this function template specialization is
+ // the prior function template specialization.
+ Previous.clear();
+ Previous.addDecl(Specialization);
+ return false;
+}
+
+/// \brief Perform semantic analysis for the given non-template member
+/// specialization.
+///
+/// This routine performs all of the semantic analysis required for an
+/// explicit member function specialization. On successful completion,
+/// the function declaration \p FD will become a member function
+/// specialization.
+///
+/// \param Member the member declaration, which will be updated to become a
+/// specialization.
+///
+/// \param Previous the set of declarations, one of which may be specialized
+/// by this function specialization; the set will be modified to contain the
+/// redeclared member.
+bool
+Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
+ assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
+
+ // Try to find the member we are instantiating.
+ NamedDecl *Instantiation = 0;
+ NamedDecl *InstantiatedFrom = 0;
+ MemberSpecializationInfo *MSInfo = 0;
+
+ if (Previous.empty()) {
+ // Nowhere to look anyway.
+ } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
+ for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+ I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Context.hasSameType(Function->getType(), Method->getType())) {
+ Instantiation = Method;
+ InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
+ MSInfo = Method->getMemberSpecializationInfo();
+ break;
+ }
+ }
+ }
+ } else if (isa<VarDecl>(Member)) {
+ VarDecl *PrevVar;
+ if (Previous.isSingleResult() &&
+ (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
+ if (PrevVar->isStaticDataMember()) {
+ Instantiation = PrevVar;
+ InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
+ MSInfo = PrevVar->getMemberSpecializationInfo();
+ }
+ } else if (isa<RecordDecl>(Member)) {
+ CXXRecordDecl *PrevRecord;
+ if (Previous.isSingleResult() &&
+ (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
+ Instantiation = PrevRecord;
+ InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
+ MSInfo = PrevRecord->getMemberSpecializationInfo();
+ }
+ }
+
+ if (!Instantiation) {
+ // There is no previous declaration that matches. Since member
+ // specializations are always out-of-line, the caller will complain about
+ // this mismatch later.
+ return false;
+ }
+
+ // If this is a friend, just bail out here before we start turning
+ // things into explicit specializations.
+ if (Member->getFriendObjectKind() != Decl::FOK_None) {
+ // Preserve instantiation information.
+ if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
+ cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
+ cast<CXXMethodDecl>(InstantiatedFrom),
+ cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
+ } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
+ cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+ cast<CXXRecordDecl>(InstantiatedFrom),
+ cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
+ }
+
+ Previous.clear();
+ Previous.addDecl(Instantiation);
+ return false;
+ }
+
+ // Make sure that this is a specialization of a member.
+ if (!InstantiatedFrom) {
+ Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
+ << Member;
+ Diag(Instantiation->getLocation(), diag::note_specialized_decl);
+ return true;
+ }
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that spe- cialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ assert(MSInfo && "Member specialization info missing?");
+
+ bool HasNoEffect = false;
+ if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
+ TSK_ExplicitSpecialization,
+ Instantiation,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ HasNoEffect))
+ return true;
+
+ // Check the scope of this explicit specialization.
+ if (CheckTemplateSpecializationScope(*this,
+ InstantiatedFrom,
+ Instantiation, Member->getLocation(),
+ false))
+ return true;
+
+ // Note that this is an explicit instantiation of a member.
+ // the original declaration to note that it is an explicit specialization
+ // (if it was previously an implicit instantiation). This latter step
+ // makes bookkeeping easier.
+ if (isa<FunctionDecl>(Member)) {
+ FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);
+ if (InstantiationFunction->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation) {
+ InstantiationFunction->setTemplateSpecializationKind(
+ TSK_ExplicitSpecialization);
+ InstantiationFunction->setLocation(Member->getLocation());
+ }
+
+ cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
+ cast<CXXMethodDecl>(InstantiatedFrom),
+ TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(InstantiationFunction);
+ } else if (isa<VarDecl>(Member)) {
+ VarDecl *InstantiationVar = cast<VarDecl>(Instantiation);
+ if (InstantiationVar->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation) {
+ InstantiationVar->setTemplateSpecializationKind(
+ TSK_ExplicitSpecialization);
+ InstantiationVar->setLocation(Member->getLocation());
+ }
+
+ Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
+ cast<VarDecl>(InstantiatedFrom),
+ TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(InstantiationVar);
+ } else {
+ assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
+ CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
+ if (InstantiationClass->getTemplateSpecializationKind() ==
+ TSK_ImplicitInstantiation) {
+ InstantiationClass->setTemplateSpecializationKind(
+ TSK_ExplicitSpecialization);
+ InstantiationClass->setLocation(Member->getLocation());
+ }
+
+ cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
+ cast<CXXRecordDecl>(InstantiatedFrom),
+ TSK_ExplicitSpecialization);
+ }
+
+ // Save the caller the trouble of having to figure out which declaration
+ // this specialization matches.
+ Previous.clear();
+ Previous.addDecl(Instantiation);
+ return false;
+}
+
+/// \brief Check the scope of an explicit instantiation.
+///
+/// \returns true if a serious error occurs, false otherwise.
+static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
+ SourceLocation InstLoc,
+ bool WasQualifiedName) {
+ DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
+ DeclContext *CurContext = S.CurContext->getRedeclContext();
+
+ if (CurContext->isRecord()) {
+ S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
+ << D;
+ return true;
+ }
+
+ // C++0x [temp.explicit]p2:
+ // An explicit instantiation shall appear in an enclosing namespace of its
+ // template.
+ //
+ // This is DR275, which we do not retroactively apply to C++98/03.
+ if (S.getLangOptions().CPlusPlus0x &&
+ !CurContext->Encloses(OrigContext)) {
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext))
+ S.Diag(InstLoc,
+ S.getLangOptions().CPlusPlus0x?
+ diag::err_explicit_instantiation_out_of_scope
+ : diag::warn_explicit_instantiation_out_of_scope_0x)
+ << D << NS;
+ else
+ S.Diag(InstLoc,
+ S.getLangOptions().CPlusPlus0x?
+ diag::err_explicit_instantiation_must_be_global
+ : diag::warn_explicit_instantiation_out_of_scope_0x)
+ << D;
+ S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+ return false;
+ }
+
+ // C++0x [temp.explicit]p2:
+ // If the name declared in the explicit instantiation is an unqualified
+ // name, the explicit instantiation shall appear in the namespace where
+ // its template is declared or, if that namespace is inline (7.3.1), any
+ // namespace from its enclosing namespace set.
+ if (WasQualifiedName)
+ return false;
+
+ if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
+ return false;
+
+ S.Diag(InstLoc,
+ S.getLangOptions().CPlusPlus0x?
+ diag::err_explicit_instantiation_unqualified_wrong_namespace
+ : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
+ << D << OrigContext;
+ S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+ return false;
+}
+
+/// \brief Determine whether the given scope specifier has a template-id in it.
+static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
+ if (!SS.isSet())
+ return false;
+
+ // C++0x [temp.explicit]p2:
+ // If the explicit instantiation is for a member function, a member class
+ // or a static data member of a class template specialization, the name of
+ // the class template specialization in the qualified-id for the member
+ // name shall be a simple-template-id.
+ //
+ // C++98 has the same restriction, just worded differently.
+ for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+ NNS; NNS = NNS->getPrefix())
+ if (const Type *T = NNS->getAsType())
+ if (isa<TemplateSpecializationType>(T))
+ return true;
+
+ return false;
+}
+
+// Explicit instantiation of a class template specialization
+DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ TemplateTy TemplateD,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr) {
+ // Find the class template we're specializing
+ TemplateName Name = TemplateD.getAsVal<TemplateName>();
+ ClassTemplateDecl *ClassTemplate
+ = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
+
+ // Check that the specialization uses the same tag kind as the
+ // original template.
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+ assert(Kind != TTK_Enum &&
+ "Invalid enum tag in class template explicit instantiation!");
+ if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
+ Kind, KWLoc,
+ *ClassTemplate->getIdentifier())) {
+ Diag(KWLoc, diag::err_use_with_wrong_tag)
+ << ClassTemplate
+ << FixItHint::CreateReplacement(KWLoc,
+ ClassTemplate->getTemplatedDecl()->getKindName());
+ Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
+ diag::note_previous_use);
+ Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
+ }
+
+ // C++0x [temp.explicit]p2:
+ // There are two forms of explicit instantiation: an explicit instantiation
+ // definition and an explicit instantiation declaration. An explicit
+ // instantiation declaration begins with the extern keyword. [...]
+ TemplateSpecializationKind TSK
+ = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ // Translate the parser's template argument list in our AST format.
+ TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
+ translateTemplateArguments(TemplateArgsIn, TemplateArgs);
+
+ // Check that the template argument list is well-formed for this
+ // template.
+ llvm::SmallVector<TemplateArgument, 4> Converted;
+ if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
+ TemplateArgs, false, Converted))
+ return true;
+
+ assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) &&
+ "Converted template argument list is too short!");
+
+ // Find the class template specialization declaration that
+ // corresponds to these arguments.
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *PrevDecl
+ = ClassTemplate->findSpecialization(Converted.data(),
+ Converted.size(), InsertPos);
+
+ TemplateSpecializationKind PrevDecl_TSK
+ = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
+
+ // C++0x [temp.explicit]p2:
+ // [...] An explicit instantiation shall appear in an enclosing
+ // namespace of its template. [...]
+ //
+ // This is C++ DR 275.
+ if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+ SS.isSet()))
+ return true;
+
+ ClassTemplateSpecializationDecl *Specialization = 0;
+
+ bool HasNoEffect = false;
+ if (PrevDecl) {
+ if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
+ PrevDecl, PrevDecl_TSK,
+ PrevDecl->getPointOfInstantiation(),
+ HasNoEffect))
+ return PrevDecl;
+
+ // Even though HasNoEffect == true means that this explicit instantiation
+ // has no effect on semantics, we go on to put its syntax in the AST.
+
+ if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
+ PrevDecl_TSK == TSK_Undeclared) {
+ // Since the only prior class template specialization with these
+ // arguments was referenced but not declared, reuse that
+ // declaration node as our own, updating the source location
+ // for the template name to reflect our new declaration.
+ // (Other source locations will be updated later.)
+ Specialization = PrevDecl;
+ Specialization->setLocation(TemplateNameLoc);
+ PrevDecl = 0;
+ }
+ }
+
+ if (!Specialization) {
+ // Create a new class template specialization declaration node for
+ // this explicit specialization.
+ Specialization
+ = ClassTemplateSpecializationDecl::Create(Context, Kind,
+ ClassTemplate->getDeclContext(),
+ TemplateNameLoc,
+ ClassTemplate,
+ Converted.data(),
+ Converted.size(),
+ PrevDecl);
+ SetNestedNameSpecifier(Specialization, SS);
+
+ if (!HasNoEffect && !PrevDecl) {
+ // Insert the new specialization.
+ ClassTemplate->AddSpecialization(Specialization, InsertPos);
+ }
+ }
+
+ // Build the fully-sugared type for this explicit instantiation as
+ // the user wrote in the explicit instantiation itself. This means
+ // that we'll pretty-print the type retrieved from the
+ // specialization's declaration the way that the user actually wrote
+ // the explicit instantiation, rather than formatting the name based
+ // on the "canonical" representation used to store the template
+ // arguments in the specialization.
+ TypeSourceInfo *WrittenTy
+ = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
+ TemplateArgs,
+ Context.getTypeDeclType(Specialization));
+ Specialization->setTypeAsWritten(WrittenTy);
+ TemplateArgsIn.release();
+
+ // Set source locations for keywords.
+ Specialization->setExternLoc(ExternLoc);
+ Specialization->setTemplateKeywordLoc(TemplateLoc);
+
+ // Add the explicit instantiation into its lexical context. However,
+ // since explicit instantiations are never found by name lookup, we
+ // just put it into the declaration context directly.
+ Specialization->setLexicalDeclContext(CurContext);
+ CurContext->addDecl(Specialization);
+
+ // Syntax is now OK, so return if it has no other effect on semantics.
+ if (HasNoEffect) {
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
+ return Specialization;
+ }
+
+ // C++ [temp.explicit]p3:
+ // A definition of a class template or class member template
+ // shall be in scope at the point of the explicit instantiation of
+ // the class template or class member template.
+ //
+ // This check comes when we actually try to perform the
+ // instantiation.
+ ClassTemplateSpecializationDecl *Def
+ = cast_or_null<ClassTemplateSpecializationDecl>(
+ Specialization->getDefinition());
+ if (!Def)
+ InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
+ else if (TSK == TSK_ExplicitInstantiationDefinition) {
+ MarkVTableUsed(TemplateNameLoc, Specialization, true);
+ Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
+ }
+
+ // Instantiate the members of this class template specialization.
+ Def = cast_or_null<ClassTemplateSpecializationDecl>(
+ Specialization->getDefinition());
+ if (Def) {
+ TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind();
+
+ // Fix a TSK_ExplicitInstantiationDeclaration followed by a
+ // TSK_ExplicitInstantiationDefinition
+ if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
+ TSK == TSK_ExplicitInstantiationDefinition)
+ Def->setTemplateSpecializationKind(TSK);
+
+ InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
+ }
+
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
+ return Specialization;
+}
+
+// Explicit instantiation of a member class of a class template.
+DeclResult
+Sema::ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ AttributeList *Attr) {
+
+ bool Owned = false;
+ bool IsDependent = false;
+ Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
+ KWLoc, SS, Name, NameLoc, Attr, AS_none,
+ MultiTemplateParamsArg(*this, 0, 0),
+ Owned, IsDependent, false, false,
+ TypeResult());
+ assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
+
+ if (!TagD)
+ return true;
+
+ TagDecl *Tag = cast<TagDecl>(TagD);
+ if (Tag->isEnum()) {
+ Diag(TemplateLoc, diag::err_explicit_instantiation_enum)
+ << Context.getTypeDeclType(Tag);
+ return true;
+ }
+
+ if (Tag->isInvalidDecl())
+ return true;
+
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
+ CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+ if (!Pattern) {
+ Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
+ << Context.getTypeDeclType(Record);
+ Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
+ return true;
+ }
+
+ // C++0x [temp.explicit]p2:
+ // If the explicit instantiation is for a class or member class, the
+ // elaborated-type-specifier in the declaration shall include a
+ // simple-template-id.
+ //
+ // C++98 has the same restriction, just worded differently.
+ if (!ScopeSpecifierHasTemplateId(SS))
+ Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id)
+ << Record << SS.getRange();
+
+ // C++0x [temp.explicit]p2:
+ // There are two forms of explicit instantiation: an explicit instantiation
+ // definition and an explicit instantiation declaration. An explicit
+ // instantiation declaration begins with the extern keyword. [...]
+ TemplateSpecializationKind TSK
+ = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ // C++0x [temp.explicit]p2:
+ // [...] An explicit instantiation shall appear in an enclosing
+ // namespace of its template. [...]
+ //
+ // This is C++ DR 275.
+ CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
+
+ // Verify that it is okay to explicitly instantiate here.
+ CXXRecordDecl *PrevDecl
+ = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+ if (!PrevDecl && Record->getDefinition())
+ PrevDecl = Record;
+ if (PrevDecl) {
+ MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
+ bool HasNoEffect = false;
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
+ PrevDecl,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ HasNoEffect))
+ return true;
+ if (HasNoEffect)
+ return TagD;
+ }
+
+ CXXRecordDecl *RecordDef
+ = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+ if (!RecordDef) {
+ // C++ [temp.explicit]p3:
+ // A definition of a member class of a class template shall be in scope
+ // at the point of an explicit instantiation of the member class.
+ CXXRecordDecl *Def
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
+ if (!Def) {
+ Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
+ << 0 << Record->getDeclName() << Record->getDeclContext();
+ Diag(Pattern->getLocation(), diag::note_forward_declaration)
+ << Pattern;
+ return true;
+ } else {
+ if (InstantiateClass(NameLoc, Record, Def,
+ getTemplateInstantiationArgs(Record),
+ TSK))
+ return true;
+
+ RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+ if (!RecordDef)
+ return true;
+ }
+ }
+
+ // Instantiate all of the members of the class.
+ InstantiateClassMembers(NameLoc, RecordDef,
+ getTemplateInstantiationArgs(Record), TSK);
+
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ MarkVTableUsed(NameLoc, RecordDef, true);
+
+ // FIXME: We don't have any representation for explicit instantiations of
+ // member classes. Such a representation is not needed for compilation, but it
+ // should be available for clients that want to see all of the declarations in
+ // the source code.
+ return TagD;
+}
+
+DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D) {
+ // Explicit instantiations always require a name.
+ // TODO: check if/when DNInfo should replace Name.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ if (!Name) {
+ if (!D.isInvalidType())
+ Diag(D.getDeclSpec().getSourceRange().getBegin(),
+ diag::err_explicit_instantiation_requires_name)
+ << D.getDeclSpec().getSourceRange()
+ << D.getSourceRange();
+
+ return true;
+ }
+
+ // The scope passed in may not be a decl scope. Zip up the scope tree until
+ // we find one that is.
+ while ((S->getFlags() & Scope::DeclScope) == 0 ||
+ (S->getFlags() & Scope::TemplateParamScope) != 0)
+ S = S->getParent();
+
+ // Determine the type of the declaration.
+ TypeSourceInfo *T = GetTypeForDeclarator(D, S);
+ QualType R = T->getType();
+ if (R.isNull())
+ return true;
+
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ // Cannot explicitly instantiate a typedef.
+ Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
+ << Name;
+ return true;
+ }
+
+ // C++0x [temp.explicit]p1:
+ // [...] An explicit instantiation of a function template shall not use the
+ // inline or constexpr specifiers.
+ // Presumably, this also applies to member functions of class templates as
+ // well.
+ if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_explicit_instantiation_inline)
+ <<FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+
+ // FIXME: check for constexpr specifier.
+
+ // C++0x [temp.explicit]p2:
+ // There are two forms of explicit instantiation: an explicit instantiation
+ // definition and an explicit instantiation declaration. An explicit
+ // instantiation declaration begins with the extern keyword. [...]
+ TemplateSpecializationKind TSK
+ = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
+ LookupParsedName(Previous, S, &D.getCXXScopeSpec());
+
+ if (!R->isFunctionType()) {
+ // C++ [temp.explicit]p1:
+ // A [...] static data member of a class template can be explicitly
+ // instantiated from the member definition associated with its class
+ // template.
+ if (Previous.isAmbiguous())
+ return true;
+
+ VarDecl *Prev = Previous.getAsSingle<VarDecl>();
+ if (!Prev || !Prev->isStaticDataMember()) {
+ // We expect to see a data data member here.
+ Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
+ << Name;
+ for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+ P != PEnd; ++P)
+ Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
+ return true;
+ }
+
+ if (!Prev->getInstantiatedFromStaticDataMember()) {
+ // FIXME: Check for explicit specialization?
+ Diag(D.getIdentifierLoc(),
+ diag::err_explicit_instantiation_data_member_not_instantiated)
+ << Prev;
+ Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
+ // FIXME: Can we provide a note showing where this was declared?
+ return true;
+ }
+
+ // C++0x [temp.explicit]p2:
+ // If the explicit instantiation is for a member function, a member class
+ // or a static data member of a class template specialization, the name of
+ // the class template specialization in the qualified-id for the member
+ // name shall be a simple-template-id.
+ //
+ // C++98 has the same restriction, just worded differently.
+ if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+ Diag(D.getIdentifierLoc(),
+ diag::ext_explicit_instantiation_without_qualified_id)
+ << Prev << D.getCXXScopeSpec().getRange();
+
+ // Check the scope of this explicit instantiation.
+ CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
+
+ // Verify that it is okay to explicitly instantiate here.
+ MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing static data member specialization info?");
+ bool HasNoEffect = false;
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ HasNoEffect))
+ return true;
+ if (HasNoEffect)
+ return (Decl*) 0;
+
+ // Instantiate static data member.
+ Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
+
+ // FIXME: Create an ExplicitInstantiation node?
+ return (Decl*) 0;
+ }
+
+ // If the declarator is a template-id, translate the parser's template
+ // argument list into our AST format.
+ bool HasExplicitTemplateArgs = false;
+ TemplateArgumentListInfo TemplateArgs;
+ if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
+ TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+ TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+ HasExplicitTemplateArgs = true;
+ TemplateArgsPtr.release();
+ }
+
+ // C++ [temp.explicit]p1:
+ // A [...] function [...] can be explicitly instantiated from its template.
+ // A member function [...] of a class template can be explicitly
+ // instantiated from the member definition associated with its class
+ // template.
+ UnresolvedSet<8> Matches;
+ for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
+ P != PEnd; ++P) {
+ NamedDecl *Prev = *P;
+ if (!HasExplicitTemplateArgs) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+ if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+ Matches.clear();
+
+ Matches.addDecl(Method, P.getAccess());
+ if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
+ break;
+ }
+ }
+ }
+
+ FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev);
+ if (!FunTmpl)
+ continue;
+
+ TemplateDeductionInfo Info(Context, D.getIdentifierLoc());
+ FunctionDecl *Specialization = 0;
+ if (TemplateDeductionResult TDK
+ = DeduceTemplateArguments(FunTmpl,
+ (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ R, Specialization, Info)) {
+ // FIXME: Keep track of almost-matches?
+ (void)TDK;
+ continue;
+ }
+
+ Matches.addDecl(Specialization, P.getAccess());
+ }
+
+ // Find the most specialized function template specialization.
+ UnresolvedSetIterator Result
+ = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0,
+ D.getIdentifierLoc(),
+ PDiag(diag::err_explicit_instantiation_not_known) << Name,
+ PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+ PDiag(diag::note_explicit_instantiation_candidate));
+
+ if (Result == Matches.end())
+ return true;
+
+ // Ignore access control bits, we don't need them for redeclaration checking.
+ FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+
+ if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_explicit_instantiation_member_function_not_instantiated)
+ << Specialization
+ << (Specialization->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization);
+ Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
+ return true;
+ }
+
+ FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+ if (!PrevDecl && Specialization->isThisDeclarationADefinition())
+ PrevDecl = Specialization;
+
+ if (PrevDecl) {
+ bool HasNoEffect = false;
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
+ PrevDecl,
+ PrevDecl->getTemplateSpecializationKind(),
+ PrevDecl->getPointOfInstantiation(),
+ HasNoEffect))
+ return true;
+
+ // FIXME: We may still want to build some representation of this
+ // explicit specialization.
+ if (HasNoEffect)
+ return (Decl*) 0;
+ }
+
+ Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
+
+ // C++0x [temp.explicit]p2:
+ // If the explicit instantiation is for a member function, a member class
+ // or a static data member of a class template specialization, the name of
+ // the class template specialization in the qualified-id for the member
+ // name shall be a simple-template-id.
+ //
+ // C++98 has the same restriction, just worded differently.
+ FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
+ D.getCXXScopeSpec().isSet() &&
+ !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
+ Diag(D.getIdentifierLoc(),
+ diag::ext_explicit_instantiation_without_qualified_id)
+ << Specialization << D.getCXXScopeSpec().getRange();
+
+ CheckExplicitInstantiationScope(*this,
+ FunTmpl? (NamedDecl *)FunTmpl
+ : Specialization->getInstantiatedFromMemberFunction(),
+ D.getIdentifierLoc(),
+ D.getCXXScopeSpec().isSet());
+
+ // FIXME: Create some kind of ExplicitInstantiationDecl here.
+ return (Decl*) 0;
+}
+
+TypeResult
+Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ const CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation TagLoc, SourceLocation NameLoc) {
+ // This has to hold, because SS is expected to be defined.
+ assert(Name && "Expected a name in a dependent tag");
+
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (!NNS)
+ return true;
+
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+
+ if (TUK == TUK_Declaration || TUK == TUK_Definition) {
+ Diag(NameLoc, diag::err_dependent_tag_decl)
+ << (TUK == TUK_Definition) << Kind << SS.getRange();
+ return true;
+ }
+
+ ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
+ return ParsedType::make(Context.getDependentNameType(Kwd, NNS, Name));
+}
+
+TypeResult
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc) {
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (!NNS)
+ return true;
+
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+ << FixItHint::CreateRemoval(TypenameLoc);
+
+ QualType T = CheckTypenameType(ETK_Typename, NNS, II,
+ TypenameLoc, SS.getRange(), IdLoc);
+ if (T.isNull())
+ return true;
+
+ TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+ if (isa<DependentNameType>(T)) {
+ DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+ TL.setNameLoc(IdLoc);
+ } else {
+ ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+ cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
+ }
+
+ return CreateParsedType(T, TSI);
+}
+
+TypeResult
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ ParsedType Ty) {
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+ << FixItHint::CreateRemoval(TypenameLoc);
+
+ TypeSourceInfo *InnerTSI = 0;
+ QualType T = GetTypeFromParser(Ty, &InnerTSI);
+
+ assert(isa<TemplateSpecializationType>(T) &&
+ "Expected a template specialization type");
+
+ if (computeDeclContext(SS, false)) {
+ // If we can compute a declaration context, then the "typename"
+ // keyword was superfluous. Just build an ElaboratedType to keep
+ // track of the nested-name-specifier.
+
+ // Push the inner type, preserving its source locations if possible.
+ TypeLocBuilder Builder;
+ if (InnerTSI)
+ Builder.pushFullCopy(InnerTSI->getTypeLoc());
+ else
+ Builder.push<TemplateSpecializationTypeLoc>(T).initialize(Context,
+ TemplateLoc);
+
+ /* Note: NNS already embedded in template specialization type T. */
+ T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T);
+ ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+
+ TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
+ return CreateParsedType(T, TSI);
+ }
+
+ // TODO: it's really silly that we make a template specialization
+ // type earlier only to drop it again here.
+ const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
+ DependentTemplateName *DTN =
+ TST->getTemplateName().getAsDependentTemplateName();
+ assert(DTN && "dependent template has non-dependent name?");
+ assert(DTN->getQualifier()
+ == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ T = Context.getDependentTemplateSpecializationType(ETK_Typename,
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
+ TST->getNumArgs(),
+ TST->getArgs());
+ TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
+ DependentTemplateSpecializationTypeLoc TL =
+ cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
+ if (InnerTSI) {
+ TemplateSpecializationTypeLoc TSTL =
+ cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc());
+ TL.setLAngleLoc(TSTL.getLAngleLoc());
+ TL.setRAngleLoc(TSTL.getRAngleLoc());
+ for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I)
+ TL.setArgLocInfo(I, TSTL.getArgLocInfo(I));
+ } else {
+ // FIXME: Poor source-location information here.
+ TL.initializeLocal(Context, TemplateLoc);
+ }
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+ return CreateParsedType(T, TSI);
+}
+
+/// \brief Build the type that describes a C++ typename specifier,
+/// e.g., "typename T::type".
+QualType
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, const IdentifierInfo &II,
+ SourceLocation KeywordLoc, SourceRange NNSRange,
+ SourceLocation IILoc) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(NNS);
+ SS.setRange(NNSRange);
+
+ DeclContext *Ctx = computeDeclContext(SS);
+ if (!Ctx) {
+ // If the nested-name-specifier is dependent and couldn't be
+ // resolved to a type, build a typename type.
+ assert(NNS->isDependent());
+ return Context.getDependentNameType(Keyword, NNS, &II);
+ }
+
+ // If the nested-name-specifier refers to the current instantiation,
+ // the "typename" keyword itself is superfluous. In C++03, the
+ // program is actually ill-formed. However, DR 382 (in C++0x CD1)
+ // allows such extraneous "typename" keywords, and we retroactively
+ // apply this DR to C++03 code with only a warning. In any case we continue.
+
+ if (RequireCompleteDeclContext(SS, Ctx))
+ return QualType();
+
+ DeclarationName Name(&II);
+ LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
+ LookupQualifiedName(Result, Ctx);
+ unsigned DiagID = 0;
+ Decl *Referenced = 0;
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ DiagID = diag::err_typename_nested_not_found;
+ break;
+
+ case LookupResult::FoundUnresolvedValue: {
+ // We found a using declaration that is a value. Most likely, the using
+ // declaration itself is meant to have the 'typename' keyword.
+ SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(),
+ IILoc);
+ Diag(IILoc, diag::err_typename_refers_to_using_value_decl)
+ << Name << Ctx << FullRange;
+ if (UnresolvedUsingValueDecl *Using
+ = dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
+ SourceLocation Loc = Using->getTargetNestedNameRange().getBegin();
+ Diag(Loc, diag::note_using_value_decl_missing_typename)
+ << FixItHint::CreateInsertion(Loc, "typename ");
+ }
+ }
+ // Fall through to create a dependent typename type, from which we can recover
+ // better.
+
+ case LookupResult::NotFoundInCurrentInstantiation:
+ // Okay, it's a member of an unknown instantiation.
+ return Context.getDependentNameType(Keyword, NNS, &II);
+
+ case LookupResult::Found:
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
+ // We found a type. Build an ElaboratedType, since the
+ // typename-specifier was just sugar.
+ return Context.getElaboratedType(ETK_Typename, NNS,
+ Context.getTypeDeclType(Type));
+ }
+
+ DiagID = diag::err_typename_nested_not_type;
+ Referenced = Result.getFoundDecl();
+ break;
+
+
+ llvm_unreachable("unresolved using decl in non-dependent context");
+ return QualType();
+
+ case LookupResult::FoundOverloaded:
+ DiagID = diag::err_typename_nested_not_type;
+ Referenced = *Result.begin();
+ break;
+
+ case LookupResult::Ambiguous:
+ return QualType();
+ }
+
+ // If we get here, it's because name lookup did not find a
+ // type. Emit an appropriate diagnostic and return an error.
+ SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(),
+ IILoc);
+ Diag(IILoc, DiagID) << FullRange << Name << Ctx;
+ if (Referenced)
+ Diag(Referenced->getLocation(), diag::note_typename_refers_here)
+ << Name;
+ return QualType();
+}
+
+namespace {
+ // See Sema::RebuildTypeInCurrentInstantiation
+ class CurrentInstantiationRebuilder
+ : public TreeTransform<CurrentInstantiationRebuilder> {
+ SourceLocation Loc;
+ DeclarationName Entity;
+
+ public:
+ typedef TreeTransform<CurrentInstantiationRebuilder> inherited;
+
+ CurrentInstantiationRebuilder(Sema &SemaRef,
+ SourceLocation Loc,
+ DeclarationName Entity)
+ : TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
+ Loc(Loc), Entity(Entity) { }
+
+ /// \brief Determine whether the given type \p T has already been
+ /// transformed.
+ ///
+ /// For the purposes of type reconstruction, a type has already been
+ /// transformed if it is NULL or if it is not dependent.
+ bool AlreadyTransformed(QualType T) {
+ return T.isNull() || !T->isDependentType();
+ }
+
+ /// \brief Returns the location of the entity whose type is being
+ /// rebuilt.
+ SourceLocation getBaseLocation() { return Loc; }
+
+ /// \brief Returns the name of the entity whose type is being rebuilt.
+ DeclarationName getBaseEntity() { return Entity; }
+
+ /// \brief Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) {
+ this->Loc = Loc;
+ this->Entity = Entity;
+ }
+ };
+}
+
+/// \brief Rebuilds a type within the context of the current instantiation.
+///
+/// The type \p T is part of the type of an out-of-line member definition of
+/// a class template (or class template partial specialization) that was parsed
+/// and constructed before we entered the scope of the class template (or
+/// partial specialization thereof). This routine will rebuild that type now
+/// that we have entered the declarator's scope, which may produce different
+/// canonical types, e.g.,
+///
+/// \code
+/// template<typename T>
+/// struct X {
+/// typedef T* pointer;
+/// pointer data();
+/// };
+///
+/// template<typename T>
+/// typename X<T>::pointer X<T>::data() { ... }
+/// \endcode
+///
+/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType,
+/// since we do not know that we can look into X<T> when we parsed the type.
+/// This function will rebuild the type, performing the lookup of "pointer"
+/// in X<T> and returning an ElaboratedType whose canonical type is the same
+/// as the canonical type of T*, allowing the return types of the out-of-line
+/// definition and the declaration to match.
+TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+ SourceLocation Loc,
+ DeclarationName Name) {
+ if (!T || !T->getType()->isDependentType())
+ return T;
+
+ CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
+ return Rebuilder.TransformType(T);
+}
+
+ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
+ CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(),
+ DeclarationName());
+ return Rebuilder.TransformExpr(E);
+}
+
+bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
+ if (SS.isInvalid()) return true;
+
+ NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
+ DeclarationName());
+ NestedNameSpecifier *Rebuilt =
+ Rebuilder.TransformNestedNameSpecifier(NNS, SS.getRange());
+ if (!Rebuilt) return true;
+
+ SS.setScopeRep(Rebuilt);
+ return false;
+}
+
+/// \brief Produces a formatted string that describes the binding of
+/// template parameters to template arguments.
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgumentList &Args) {
+ return getTemplateArgumentBindingsText(Params, Args.data(), Args.size());
+}
+
+std::string
+Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ llvm::SmallString<128> Str;
+ llvm::raw_svector_ostream Out(Str);
+
+ if (!Params || Params->size() == 0 || NumArgs == 0)
+ return std::string();
+
+ for (unsigned I = 0, N = Params->size(); I != N; ++I) {
+ if (I >= NumArgs)
+ break;
+
+ if (I == 0)
+ Out << "[with ";
+ else
+ Out << ", ";
+
+ if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
+ Out << Id->getName();
+ } else {
+ Out << '$' << I;
+ }
+
+ Out << " = ";
+ Args[I].print(Context.PrintingPolicy, Out);
+ }
+
+ Out << ']';
+ return Out.str();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
new file mode 100644
index 0000000..bd0a618
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -0,0 +1,3938 @@
+//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements C++ template argument deduction.
+//
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/SemaDiagnostic.h" // FIXME: temporary!
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/BitVector.h"
+#include "TreeTransform.h"
+#include <algorithm>
+
+namespace clang {
+ using namespace sema;
+
+ /// \brief Various flags that control template argument deduction.
+ ///
+ /// These flags can be bitwise-OR'd together.
+ enum TemplateDeductionFlags {
+ /// \brief No template argument deduction flags, which indicates the
+ /// strictest results for template argument deduction (as used for, e.g.,
+ /// matching class template partial specializations).
+ TDF_None = 0,
+ /// \brief Within template argument deduction from a function call, we are
+ /// matching with a parameter type for which the original parameter was
+ /// a reference.
+ TDF_ParamWithReferenceType = 0x1,
+ /// \brief Within template argument deduction from a function call, we
+ /// are matching in a case where we ignore cv-qualifiers.
+ TDF_IgnoreQualifiers = 0x02,
+ /// \brief Within template argument deduction from a function call,
+ /// we are matching in a case where we can perform template argument
+ /// deduction from a template-id of a derived class of the argument type.
+ TDF_DerivedClass = 0x04,
+ /// \brief Allow non-dependent types to differ, e.g., when performing
+ /// template argument deduction from a function call where conversions
+ /// may apply.
+ TDF_SkipNonDependent = 0x08,
+ /// \brief Whether we are performing template argument deduction for
+ /// parameters and arguments in a top-level template argument
+ TDF_TopLevelParameterTypeList = 0x10
+ };
+}
+
+using namespace clang;
+
+/// \brief Compare two APSInts, extending and switching the sign as
+/// necessary to compare their values regardless of underlying type.
+static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
+ if (Y.getBitWidth() > X.getBitWidth())
+ X = X.extend(Y.getBitWidth());
+ else if (Y.getBitWidth() < X.getBitWidth())
+ Y = Y.extend(X.getBitWidth());
+
+ // If there is a signedness mismatch, correct it.
+ if (X.isSigned() != Y.isSigned()) {
+ // If the signed value is negative, then the values cannot be the same.
+ if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative()))
+ return false;
+
+ Y.setIsSigned(true);
+ X.setIsSigned(true);
+ }
+
+ return X == Y;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument &Param,
+ TemplateArgument Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
+
+/// \brief Whether template argument deduction for two reference parameters
+/// resulted in the argument type, parameter type, or neither type being more
+/// qualified than the other.
+enum DeductionQualifierComparison {
+ NeitherMoreQualified = 0,
+ ParamMoreQualified,
+ ArgMoreQualified
+};
+
+/// \brief Stores the result of comparing two reference parameters while
+/// performing template argument deduction for partial ordering of function
+/// templates.
+struct RefParamPartialOrderingComparison {
+ /// \brief Whether the parameter type is an rvalue reference type.
+ bool ParamIsRvalueRef;
+ /// \brief Whether the argument type is an rvalue reference type.
+ bool ArgIsRvalueRef;
+
+ /// \brief Whether the parameter or argument (or neither) is more qualified.
+ DeductionQualifierComparison Qualifiers;
+};
+
+
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ QualType Param,
+ QualType Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF,
+ bool PartialOrdering = false,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0);
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument *Params, unsigned NumParams,
+ const TemplateArgument *Args, unsigned NumArgs,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ bool NumberOfArgumentsMustMatch = true);
+
+/// \brief If the given expression is of a form that permits the deduction
+/// of a non-type template parameter, return the declaration of that
+/// non-type template parameter.
+static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
+ if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
+ E = IC->getSubExpr();
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+
+ return 0;
+}
+
+/// \brief Determine whether two declaration pointers refer to the same
+/// declaration.
+static bool isSameDeclaration(Decl *X, Decl *Y) {
+ if (!X || !Y)
+ return !X && !Y;
+
+ if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
+ X = NX->getUnderlyingDecl();
+ if (NamedDecl *NY = dyn_cast<NamedDecl>(Y))
+ Y = NY->getUnderlyingDecl();
+
+ return X->getCanonicalDecl() == Y->getCanonicalDecl();
+}
+
+/// \brief Verify that the given, deduced template arguments are compatible.
+///
+/// \returns The deduced template argument, or a NULL template argument if
+/// the deduced template arguments were incompatible.
+static DeducedTemplateArgument
+checkDeducedTemplateArguments(ASTContext &Context,
+ const DeducedTemplateArgument &X,
+ const DeducedTemplateArgument &Y) {
+ // We have no deduction for one or both of the arguments; they're compatible.
+ if (X.isNull())
+ return Y;
+ if (Y.isNull())
+ return X;
+
+ switch (X.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Non-deduced template arguments handled above");
+
+ case TemplateArgument::Type:
+ // If two template type arguments have the same type, they're compatible.
+ if (Y.getKind() == TemplateArgument::Type &&
+ Context.hasSameType(X.getAsType(), Y.getAsType()))
+ return X;
+
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Integral:
+ // If we deduced a constant in one case and either a dependent expression or
+ // declaration in another case, keep the integral constant.
+ // If both are integral constants with the same value, keep that value.
+ if (Y.getKind() == TemplateArgument::Expression ||
+ Y.getKind() == TemplateArgument::Declaration ||
+ (Y.getKind() == TemplateArgument::Integral &&
+ hasSameExtendedValue(*X.getAsIntegral(), *Y.getAsIntegral())))
+ return DeducedTemplateArgument(X,
+ X.wasDeducedFromArrayBound() &&
+ Y.wasDeducedFromArrayBound());
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Template:
+ if (Y.getKind() == TemplateArgument::Template &&
+ Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::TemplateExpansion:
+ if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+ Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
+ Y.getAsTemplateOrTemplatePattern()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Expression:
+ // If we deduced a dependent expression in one case and either an integral
+ // constant or a declaration in another case, keep the integral constant
+ // or declaration.
+ if (Y.getKind() == TemplateArgument::Integral ||
+ Y.getKind() == TemplateArgument::Declaration)
+ return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
+ Y.wasDeducedFromArrayBound());
+
+ if (Y.getKind() == TemplateArgument::Expression) {
+ // Compare the expressions for equality
+ llvm::FoldingSetNodeID ID1, ID2;
+ X.getAsExpr()->Profile(ID1, Context, true);
+ Y.getAsExpr()->Profile(ID2, Context, true);
+ if (ID1 == ID2)
+ return X;
+ }
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Declaration:
+ // If we deduced a declaration and a dependent expression, keep the
+ // declaration.
+ if (Y.getKind() == TemplateArgument::Expression)
+ return X;
+
+ // If we deduced a declaration and an integral constant, keep the
+ // integral constant.
+ if (Y.getKind() == TemplateArgument::Integral)
+ return Y;
+
+ // If we deduced two declarations, make sure they they refer to the
+ // same declaration.
+ if (Y.getKind() == TemplateArgument::Declaration &&
+ isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::Pack:
+ if (Y.getKind() != TemplateArgument::Pack ||
+ X.pack_size() != Y.pack_size())
+ return DeducedTemplateArgument();
+
+ for (TemplateArgument::pack_iterator XA = X.pack_begin(),
+ XAEnd = X.pack_end(),
+ YA = Y.pack_begin();
+ XA != XAEnd; ++XA, ++YA) {
+ if (checkDeducedTemplateArguments(Context,
+ DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()),
+ DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound()))
+ .isNull())
+ return DeducedTemplateArgument();
+ }
+
+ return X;
+ }
+
+ return DeducedTemplateArgument();
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given constant.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+ NonTypeTemplateParmDecl *NTTP,
+ llvm::APSInt Value, QualType ValueType,
+ bool DeducedFromArrayBound,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument with depth > 0");
+
+ DeducedTemplateArgument NewDeduced(Value, ValueType, DeducedFromArrayBound);
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[NTTP->getIndex()],
+ NewDeduced);
+ if (Result.isNull()) {
+ Info.Param = NTTP;
+ Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.SecondArg = NewDeduced;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[NTTP->getIndex()] = Result;
+ return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given type- or value-dependent expression.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+ NonTypeTemplateParmDecl *NTTP,
+ Expr *Value,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument with depth > 0");
+ assert((Value->isTypeDependent() || Value->isValueDependent()) &&
+ "Expression template argument must be type- or value-dependent.");
+
+ DeducedTemplateArgument NewDeduced(Value);
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[NTTP->getIndex()],
+ NewDeduced);
+
+ if (Result.isNull()) {
+ Info.Param = NTTP;
+ Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.SecondArg = NewDeduced;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[NTTP->getIndex()] = Result;
+ return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given declaration.
+///
+/// \returns true if deduction succeeded, false otherwise.
+static Sema::TemplateDeductionResult
+DeduceNonTypeTemplateArgument(Sema &S,
+ NonTypeTemplateParmDecl *NTTP,
+ Decl *D,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument with depth > 0");
+
+ DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0);
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[NTTP->getIndex()],
+ NewDeduced);
+ if (Result.isNull()) {
+ Info.Param = NTTP;
+ Info.FirstArg = Deduced[NTTP->getIndex()];
+ Info.SecondArg = NewDeduced;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[NTTP->getIndex()] = Result;
+ return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ TemplateName Param,
+ TemplateName Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
+ if (!ParamDecl) {
+ // The parameter type is dependent and is not a template template parameter,
+ // so there is nothing that we can deduce.
+ return Sema::TDK_Success;
+ }
+
+ if (TemplateTemplateParmDecl *TempParam
+ = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+ DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg));
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[TempParam->getIndex()],
+ NewDeduced);
+ if (Result.isNull()) {
+ Info.Param = TempParam;
+ Info.FirstArg = Deduced[TempParam->getIndex()];
+ Info.SecondArg = NewDeduced;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[TempParam->getIndex()] = Result;
+ return Sema::TDK_Success;
+ }
+
+ // Verify that the two template names are equivalent.
+ if (S.Context.hasSameTemplateName(Param, Arg))
+ return Sema::TDK_Success;
+
+ // Mismatch of non-dependent template parameter to argument.
+ Info.FirstArg = TemplateArgument(Param);
+ Info.SecondArg = TemplateArgument(Arg);
+ return Sema::TDK_NonDeducedMismatch;
+}
+
+/// \brief Deduce the template arguments by comparing the template parameter
+/// type (which is a template-id) with the template argument type.
+///
+/// \param S the Sema
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param Param the parameter type
+///
+/// \param Arg the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateSpecializationType *Param,
+ QualType Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ assert(Arg.isCanonical() && "Argument type must be canonical");
+
+ // Check whether the template argument is a dependent template-id.
+ if (const TemplateSpecializationType *SpecArg
+ = dyn_cast<TemplateSpecializationType>(Arg)) {
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ Param->getTemplateName(),
+ SpecArg->getTemplateName(),
+ Info, Deduced))
+ return Result;
+
+
+ // Perform template argument deduction on each template
+ // argument. Ignore any missing/extra arguments, since they could be
+ // filled in by default arguments.
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->getArgs(), Param->getNumArgs(),
+ SpecArg->getArgs(), SpecArg->getNumArgs(),
+ Info, Deduced,
+ /*NumberOfArgumentsMustMatch=*/false);
+ }
+
+ // If the argument type is a class template specialization, we
+ // perform template argument deduction using its template
+ // arguments.
+ const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+ if (!RecordArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ ClassTemplateSpecializationDecl *SpecArg
+ = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
+ if (!SpecArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Perform template argument deduction for the template name.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S,
+ TemplateParams,
+ Param->getTemplateName(),
+ TemplateName(SpecArg->getSpecializedTemplate()),
+ Info, Deduced))
+ return Result;
+
+ // Perform template argument deduction for the template arguments.
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->getArgs(), Param->getNumArgs(),
+ SpecArg->getTemplateArgs().data(),
+ SpecArg->getTemplateArgs().size(),
+ Info, Deduced);
+}
+
+/// \brief Determines whether the given type is an opaque type that
+/// might be more qualified when instantiated.
+static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
+ switch (T->getTypeClass()) {
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::DependentName:
+ case Type::Decltype:
+ case Type::UnresolvedUsing:
+ case Type::TemplateTypeParm:
+ return true;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ return IsPossiblyOpaquelyQualifiedType(
+ cast<ArrayType>(T)->getElementType());
+
+ default:
+ return false;
+ }
+}
+
+/// \brief Retrieve the depth and index of a template parameter.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+ if (const TemplateTypeParmType *TTP
+ = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
+/// \brief Helper function to build a TemplateParameter when we don't
+/// know its type statically.
+static TemplateParameter makeTemplateParameter(Decl *D) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+ return TemplateParameter(TTP);
+ else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+ return TemplateParameter(NTTP);
+
+ return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
+}
+
+/// \brief Prepare to perform template argument deduction for all of the
+/// arguments in a set of argument packs.
+static void PrepareArgumentPackDeduction(Sema &S,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ const llvm::SmallVectorImpl<unsigned> &PackIndices,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ llvm::SmallVectorImpl<
+ llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) {
+ // Save the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ // Save the previously-deduced argument pack, then clear it out so that we
+ // can deduce a new argument pack.
+ SavedPacks[I] = Deduced[PackIndices[I]];
+ Deduced[PackIndices[I]] = TemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (NamedDecl *PartiallySubstitutedPack
+ = S.CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs,
+ &NumExplicitArgs)) {
+ if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+ NewlyDeducedPacks[I].append(ExplicitArgs,
+ ExplicitArgs + NumExplicitArgs);
+ }
+ }
+}
+
+/// \brief Finish template argument deduction for a set of argument packs,
+/// producing the argument packs and checking for consistency with prior
+/// deductions.
+static Sema::TemplateDeductionResult
+FinishArgumentPackDeduction(Sema &S,
+ TemplateParameterList *TemplateParams,
+ bool HasAnyArguments,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ const llvm::SmallVectorImpl<unsigned> &PackIndices,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks,
+ llvm::SmallVectorImpl<
+ llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks,
+ TemplateDeductionInfo &Info) {
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
+ // We were not able to deduce anything for this parameter pack,
+ // so just restore the saved argument pack.
+ Deduced[PackIndices[I]] = SavedPacks[I];
+ continue;
+ }
+
+ DeducedTemplateArgument NewPack;
+
+ if (NewlyDeducedPacks[I].empty()) {
+ // If we deduced an empty argument pack, create it now.
+ NewPack = DeducedTemplateArgument(TemplateArgument(0, 0));
+ } else {
+ TemplateArgument *ArgumentPack
+ = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
+ std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
+ ArgumentPack);
+ NewPack
+ = DeducedTemplateArgument(TemplateArgument(ArgumentPack,
+ NewlyDeducedPacks[I].size()),
+ NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
+ }
+
+ DeducedTemplateArgument Result
+ = checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack);
+ if (Result.isNull()) {
+ Info.Param
+ = makeTemplateParameter(TemplateParams->getParam(PackIndices[I]));
+ Info.FirstArg = SavedPacks[I];
+ Info.SecondArg = NewPack;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[PackIndices[I]] = Result;
+ }
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Deduce the template arguments by comparing the list of parameter
+/// types to the list of argument types, as in the parameter-type-lists of
+/// function types (C++ [temp.deduct.type]p10).
+///
+/// \param S The semantic analysis object within which we are deducing
+///
+/// \param TemplateParams The template parameters that we are deducing
+///
+/// \param Params The list of parameter types
+///
+/// \param NumParams The number of types in \c Params
+///
+/// \param Args The list of argument types
+///
+/// \param NumArgs The number of types in \c Args
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \param PartialOrdering If true, we are performing template argument
+/// deduction for during partial ordering for a call
+/// (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const QualType *Params, unsigned NumParams,
+ const QualType *Args, unsigned NumArgs,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF,
+ bool PartialOrdering = false,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0) {
+ // Fast-path check to see if we have too many/too few arguments.
+ if (NumParams != NumArgs &&
+ !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
+ !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1])))
+ return Sema::TDK_NonDeducedMismatch;
+
+ // C++0x [temp.deduct.type]p10:
+ // Similarly, if P has a form that contains (T), then each parameter type
+ // Pi of the respective parameter-type- list of P is compared with the
+ // corresponding parameter type Ai of the corresponding parameter-type-list
+ // of A. [...]
+ unsigned ArgIdx = 0, ParamIdx = 0;
+ for (; ParamIdx != NumParams; ++ParamIdx) {
+ // Check argument types.
+ const PackExpansionType *Expansion
+ = dyn_cast<PackExpansionType>(Params[ParamIdx]);
+ if (!Expansion) {
+ // Simple case: compare the parameter and argument types at this point.
+
+ // Make sure we have an argument.
+ if (ArgIdx >= NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ if (isa<PackExpansionType>(Args[ArgIdx])) {
+ // C++0x [temp.deduct.type]p22:
+ // If the original function parameter associated with A is a function
+ // parameter pack and the function parameter associated with P is not
+ // a function parameter pack, then template argument deduction fails.
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ Params[ParamIdx],
+ Args[ArgIdx],
+ Info, Deduced, TDF,
+ PartialOrdering,
+ RefParamComparisons))
+ return Result;
+
+ ++ArgIdx;
+ continue;
+ }
+
+ // C++0x [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // - A function parameter pack that does not occur at the end of the
+ // parameter-declaration-clause.
+ if (ParamIdx + 1 < NumParams)
+ return Sema::TDK_Success;
+
+ // C++0x [temp.deduct.type]p10:
+ // If the parameter-declaration corresponding to Pi is a function
+ // parameter pack, then the type of its declarator- id is compared with
+ // each remaining parameter type in the parameter-type-list of A. Each
+ // comparison deduces template arguments for subsequent positions in the
+ // template parameter packs expanded by the function parameter pack.
+
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ QualType Pattern = Expansion->getPattern();
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == 0 && !SawIndices[Index]) {
+ SawIndices[Index] = true;
+ PackIndices.push_back(Index);
+ }
+ }
+ }
+ assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+
+ bool HasAnyArguments = false;
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ HasAnyArguments = true;
+
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+ Info, Deduced, TDF, PartialOrdering,
+ RefParamComparisons))
+ return Result;
+
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+ if (!DeducedArg.isNull()) {
+ NewlyDeducedPacks[I].push_back(DeducedArg);
+ DeducedArg = DeducedTemplateArgument();
+ }
+ }
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ if (Sema::TemplateDeductionResult Result
+ = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
+ return Result;
+ }
+
+ // Make sure we don't have any extra arguments.
+ if (ArgIdx < NumArgs)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Deduce the template arguments by comparing the parameter type and
+/// the argument type (C++ [temp.deduct.type]).
+///
+/// \param S the semantic analysis object within which we are deducing
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \param PartialOrdering Whether we're performing template argument deduction
+/// in the context of partial ordering (C++0x [temp.deduct.partial]).
+///
+/// \param RefParamComparisons If we're performing template argument deduction
+/// in the context of partial ordering, the set of qualifier comparisons.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ QualType ParamIn, QualType ArgIn,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned TDF,
+ bool PartialOrdering,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
+ // We only want to look at the canonical types, since typedefs and
+ // sugar are not part of template argument deduction.
+ QualType Param = S.Context.getCanonicalType(ParamIn);
+ QualType Arg = S.Context.getCanonicalType(ArgIn);
+
+ // If the argument type is a pack expansion, look at its pattern.
+ // This isn't explicitly called out
+ if (const PackExpansionType *ArgExpansion
+ = dyn_cast<PackExpansionType>(Arg))
+ Arg = ArgExpansion->getPattern();
+
+ if (PartialOrdering) {
+ // C++0x [temp.deduct.partial]p5:
+ // Before the partial ordering is done, certain transformations are
+ // performed on the types used for partial ordering:
+ // - If P is a reference type, P is replaced by the type referred to.
+ const ReferenceType *ParamRef = Param->getAs<ReferenceType>();
+ if (ParamRef)
+ Param = ParamRef->getPointeeType();
+
+ // - If A is a reference type, A is replaced by the type referred to.
+ const ReferenceType *ArgRef = Arg->getAs<ReferenceType>();
+ if (ArgRef)
+ Arg = ArgRef->getPointeeType();
+
+ if (RefParamComparisons && ParamRef && ArgRef) {
+ // C++0x [temp.deduct.partial]p6:
+ // If both P and A were reference types (before being replaced with the
+ // type referred to above), determine which of the two types (if any) is
+ // more cv-qualified than the other; otherwise the types are considered
+ // to be equally cv-qualified for partial ordering purposes. The result
+ // of this determination will be used below.
+ //
+ // We save this information for later, using it only when deduction
+ // succeeds in both directions.
+ RefParamPartialOrderingComparison Comparison;
+ Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
+ Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
+ Comparison.Qualifiers = NeitherMoreQualified;
+ if (Param.isMoreQualifiedThan(Arg))
+ Comparison.Qualifiers = ParamMoreQualified;
+ else if (Arg.isMoreQualifiedThan(Param))
+ Comparison.Qualifiers = ArgMoreQualified;
+ RefParamComparisons->push_back(Comparison);
+ }
+
+ // C++0x [temp.deduct.partial]p7:
+ // Remove any top-level cv-qualifiers:
+ // - If P is a cv-qualified type, P is replaced by the cv-unqualified
+ // version of P.
+ Param = Param.getUnqualifiedType();
+ // - If A is a cv-qualified type, A is replaced by the cv-unqualified
+ // version of A.
+ Arg = Arg.getUnqualifiedType();
+ } else {
+ // C++0x [temp.deduct.call]p4 bullet 1:
+ // - If the original P is a reference type, the deduced A (i.e., the type
+ // referred to by the reference) can be more cv-qualified than the
+ // transformed A.
+ if (TDF & TDF_ParamWithReferenceType) {
+ Qualifiers Quals;
+ QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
+ Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
+ Arg.getCVRQualifiers());
+ Param = S.Context.getQualifiedType(UnqualParam, Quals);
+ }
+
+ if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) {
+ // C++0x [temp.deduct.type]p10:
+ // If P and A are function types that originated from deduction when
+ // taking the address of a function template (14.8.2.2) or when deducing
+ // template arguments from a function declaration (14.8.2.6) and Pi and
+ // Ai are parameters of the top-level parameter-type-list of P and A,
+ // respectively, Pi is adjusted if it is an rvalue reference to a
+ // cv-unqualified template parameter and Ai is an lvalue reference, in
+ // which case the type of Pi is changed to be the template parameter
+ // type (i.e., T&& is changed to simply T). [ Note: As a result, when
+ // Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be
+ // deduced as X&. - end note ]
+ TDF &= ~TDF_TopLevelParameterTypeList;
+
+ if (const RValueReferenceType *ParamRef
+ = Param->getAs<RValueReferenceType>()) {
+ if (isa<TemplateTypeParmType>(ParamRef->getPointeeType()) &&
+ !ParamRef->getPointeeType().getQualifiers())
+ if (Arg->isLValueReferenceType())
+ Param = ParamRef->getPointeeType();
+ }
+ }
+ }
+
+ // If the parameter type is not dependent, there is nothing to deduce.
+ if (!Param->isDependentType()) {
+ if (!(TDF & TDF_SkipNonDependent) && Param != Arg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return Sema::TDK_Success;
+ }
+
+ // C++ [temp.deduct.type]p9:
+ // A template type argument T, a template template argument TT or a
+ // template non-type argument i can be deduced if P and A have one of
+ // the following forms:
+ //
+ // T
+ // cv-list T
+ if (const TemplateTypeParmType *TemplateTypeParm
+ = Param->getAs<TemplateTypeParmType>()) {
+ unsigned Index = TemplateTypeParm->getIndex();
+ bool RecanonicalizeArg = false;
+
+ // If the argument type is an array type, move the qualifiers up to the
+ // top level, so they can be matched with the qualifiers on the parameter.
+ // FIXME: address spaces, ObjC GC qualifiers
+ if (isa<ArrayType>(Arg)) {
+ Qualifiers Quals;
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
+ if (Quals) {
+ Arg = S.Context.getQualifiedType(Arg, Quals);
+ RecanonicalizeArg = true;
+ }
+ }
+
+ // The argument type can not be less qualified than the parameter
+ // type.
+ if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
+ Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+ Info.FirstArg = TemplateArgument(Param);
+ Info.SecondArg = TemplateArgument(Arg);
+ return Sema::TDK_Underqualified;
+ }
+
+ assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
+ assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
+ QualType DeducedType = Arg;
+
+ // local manipulation is okay because it's canonical
+ DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers());
+ if (RecanonicalizeArg)
+ DeducedType = S.Context.getCanonicalType(DeducedType);
+
+ DeducedTemplateArgument NewDeduced(DeducedType);
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
+ Deduced[Index],
+ NewDeduced);
+ if (Result.isNull()) {
+ Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
+ Info.FirstArg = Deduced[Index];
+ Info.SecondArg = NewDeduced;
+ return Sema::TDK_Inconsistent;
+ }
+
+ Deduced[Index] = Result;
+ return Sema::TDK_Success;
+ }
+
+ // Set up the template argument deduction information for a failure.
+ Info.FirstArg = TemplateArgument(ParamIn);
+ Info.SecondArg = TemplateArgument(ArgIn);
+
+ // If the parameter is an already-substituted template parameter
+ // pack, do nothing: we don't know which of its arguments to look
+ // at, so we have to wait until all of the parameter packs in this
+ // expansion have arguments.
+ if (isa<SubstTemplateTypeParmPackType>(Param))
+ return Sema::TDK_Success;
+
+ // Check the cv-qualifiers on the parameter and argument types.
+ if (!(TDF & TDF_IgnoreQualifiers)) {
+ if (TDF & TDF_ParamWithReferenceType) {
+ if (Param.isMoreQualifiedThan(Arg))
+ return Sema::TDK_NonDeducedMismatch;
+ } else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
+ if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
+
+ switch (Param->getTypeClass()) {
+ // No deduction possible for these types
+ case Type::Builtin:
+ return Sema::TDK_NonDeducedMismatch;
+
+ // T *
+ case Type::Pointer: {
+ QualType PointeeType;
+ if (const PointerType *PointerArg = Arg->getAs<PointerType>()) {
+ PointeeType = PointerArg->getPointeeType();
+ } else if (const ObjCObjectPointerType *PointerArg
+ = Arg->getAs<ObjCObjectPointerType>()) {
+ PointeeType = PointerArg->getPointeeType();
+ } else {
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
+ return DeduceTemplateArguments(S, TemplateParams,
+ cast<PointerType>(Param)->getPointeeType(),
+ PointeeType,
+ Info, Deduced, SubTDF);
+ }
+
+ // T &
+ case Type::LValueReference: {
+ const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>();
+ if (!ReferenceArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return DeduceTemplateArguments(S, TemplateParams,
+ cast<LValueReferenceType>(Param)->getPointeeType(),
+ ReferenceArg->getPointeeType(),
+ Info, Deduced, 0);
+ }
+
+ // T && [C++0x]
+ case Type::RValueReference: {
+ const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>();
+ if (!ReferenceArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return DeduceTemplateArguments(S, TemplateParams,
+ cast<RValueReferenceType>(Param)->getPointeeType(),
+ ReferenceArg->getPointeeType(),
+ Info, Deduced, 0);
+ }
+
+ // T [] (implied, but not stated explicitly)
+ case Type::IncompleteArray: {
+ const IncompleteArrayType *IncompleteArrayArg =
+ S.Context.getAsIncompleteArrayType(Arg);
+ if (!IncompleteArrayArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+ return DeduceTemplateArguments(S, TemplateParams,
+ S.Context.getAsIncompleteArrayType(Param)->getElementType(),
+ IncompleteArrayArg->getElementType(),
+ Info, Deduced, SubTDF);
+ }
+
+ // T [integer-constant]
+ case Type::ConstantArray: {
+ const ConstantArrayType *ConstantArrayArg =
+ S.Context.getAsConstantArrayType(Arg);
+ if (!ConstantArrayArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ const ConstantArrayType *ConstantArrayParm =
+ S.Context.getAsConstantArrayType(Param);
+ if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
+ return Sema::TDK_NonDeducedMismatch;
+
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+ return DeduceTemplateArguments(S, TemplateParams,
+ ConstantArrayParm->getElementType(),
+ ConstantArrayArg->getElementType(),
+ Info, Deduced, SubTDF);
+ }
+
+ // type [i]
+ case Type::DependentSizedArray: {
+ const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
+ if (!ArrayArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+
+ // Check the element type of the arrays
+ const DependentSizedArrayType *DependentArrayParm
+ = S.Context.getAsDependentSizedArrayType(Param);
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ DependentArrayParm->getElementType(),
+ ArrayArg->getElementType(),
+ Info, Deduced, SubTDF))
+ return Result;
+
+ // Determine the array bound is something we can deduce.
+ NonTypeTemplateParmDecl *NTTP
+ = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
+ if (!NTTP)
+ return Sema::TDK_Success;
+
+ // We can perform template argument deduction for the given non-type
+ // template parameter.
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument at depth > 0");
+ if (const ConstantArrayType *ConstantArrayArg
+ = dyn_cast<ConstantArrayType>(ArrayArg)) {
+ llvm::APSInt Size(ConstantArrayArg->getSize());
+ return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+ S.Context.getSizeType(),
+ /*ArrayBound=*/true,
+ Info, Deduced);
+ }
+ if (const DependentSizedArrayType *DependentArrayArg
+ = dyn_cast<DependentSizedArrayType>(ArrayArg))
+ if (DependentArrayArg->getSizeExpr())
+ return DeduceNonTypeTemplateArgument(S, NTTP,
+ DependentArrayArg->getSizeExpr(),
+ Info, Deduced);
+
+ // Incomplete type does not match a dependently-sized array type
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ // type(*)(T)
+ // T(*)()
+ // T(*)(T)
+ case Type::FunctionProto: {
+ unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
+ const FunctionProtoType *FunctionProtoArg =
+ dyn_cast<FunctionProtoType>(Arg);
+ if (!FunctionProtoArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ const FunctionProtoType *FunctionProtoParam =
+ cast<FunctionProtoType>(Param);
+
+ if (FunctionProtoParam->getTypeQuals()
+ != FunctionProtoArg->getTypeQuals() ||
+ FunctionProtoParam->getRefQualifier()
+ != FunctionProtoArg->getRefQualifier() ||
+ FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+ return Sema::TDK_NonDeducedMismatch;
+
+ // Check return types.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ FunctionProtoParam->getResultType(),
+ FunctionProtoArg->getResultType(),
+ Info, Deduced, 0))
+ return Result;
+
+ return DeduceTemplateArguments(S, TemplateParams,
+ FunctionProtoParam->arg_type_begin(),
+ FunctionProtoParam->getNumArgs(),
+ FunctionProtoArg->arg_type_begin(),
+ FunctionProtoArg->getNumArgs(),
+ Info, Deduced, SubTDF);
+ }
+
+ case Type::InjectedClassName: {
+ // Treat a template's injected-class-name as if the template
+ // specialization type had been used.
+ Param = cast<InjectedClassNameType>(Param)
+ ->getInjectedSpecializationType();
+ assert(isa<TemplateSpecializationType>(Param) &&
+ "injected class name is not a template specialization type");
+ // fall through
+ }
+
+ // template-name<T> (where template-name refers to a class template)
+ // template-name<i>
+ // TT<T>
+ // TT<i>
+ // TT<>
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *SpecParam
+ = cast<TemplateSpecializationType>(Param);
+
+ // Try to deduce template arguments from the template-id.
+ Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
+ Info, Deduced);
+
+ if (Result && (TDF & TDF_DerivedClass)) {
+ // C++ [temp.deduct.call]p3b3:
+ // If P is a class, and P has the form template-id, then A can be a
+ // derived class of the deduced A. Likewise, if P is a pointer to a
+ // class of the form template-id, A can be a pointer to a derived
+ // class pointed to by the deduced A.
+ //
+ // More importantly:
+ // These alternatives are considered only if type deduction would
+ // otherwise fail.
+ if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
+ // We cannot inspect base classes as part of deduction when the type
+ // is incomplete, so either instantiate any templates necessary to
+ // complete the type, or skip over it if it cannot be completed.
+ if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+ return Result;
+
+ // Use data recursion to crawl through the list of base classes.
+ // Visited contains the set of nodes we have already visited, while
+ // ToVisit is our stack of records that we still need to visit.
+ llvm::SmallPtrSet<const RecordType *, 8> Visited;
+ llvm::SmallVector<const RecordType *, 8> ToVisit;
+ ToVisit.push_back(RecordT);
+ bool Successful = false;
+ llvm::SmallVectorImpl<DeducedTemplateArgument> DeducedOrig(0);
+ DeducedOrig = Deduced;
+ while (!ToVisit.empty()) {
+ // Retrieve the next class in the inheritance hierarchy.
+ const RecordType *NextT = ToVisit.back();
+ ToVisit.pop_back();
+
+ // If we have already seen this type, skip it.
+ if (!Visited.insert(NextT))
+ continue;
+
+ // If this is a base class, try to perform template argument
+ // deduction from it.
+ if (NextT != RecordT) {
+ Sema::TemplateDeductionResult BaseResult
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam,
+ QualType(NextT, 0), Info, Deduced);
+
+ // If template argument deduction for this base was successful,
+ // note that we had some success. Otherwise, ignore any deductions
+ // from this base class.
+ if (BaseResult == Sema::TDK_Success) {
+ Successful = true;
+ DeducedOrig = Deduced;
+ }
+ else
+ Deduced = DeducedOrig;
+ }
+
+ // Visit base classes
+ CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
+ for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(),
+ BaseEnd = Next->bases_end();
+ Base != BaseEnd; ++Base) {
+ assert(Base->getType()->isRecordType() &&
+ "Base class that isn't a record?");
+ ToVisit.push_back(Base->getType()->getAs<RecordType>());
+ }
+ }
+
+ if (Successful)
+ return Sema::TDK_Success;
+ }
+
+ }
+
+ return Result;
+ }
+
+ // T type::*
+ // T T::*
+ // T (type::*)()
+ // type (T::*)()
+ // type (type::*)(T)
+ // type (T::*)(T)
+ // T (type::*)(T)
+ // T (T::*)()
+ // T (T::*)(T)
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param);
+ const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg);
+ if (!MemPtrArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ MemPtrParam->getPointeeType(),
+ MemPtrArg->getPointeeType(),
+ Info, Deduced,
+ TDF & TDF_IgnoreQualifiers))
+ return Result;
+
+ return DeduceTemplateArguments(S, TemplateParams,
+ QualType(MemPtrParam->getClass(), 0),
+ QualType(MemPtrArg->getClass(), 0),
+ Info, Deduced, 0);
+ }
+
+ // (clang extension)
+ //
+ // type(^)(T)
+ // T(^)()
+ // T(^)(T)
+ case Type::BlockPointer: {
+ const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param);
+ const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg);
+
+ if (!BlockPtrArg)
+ return Sema::TDK_NonDeducedMismatch;
+
+ return DeduceTemplateArguments(S, TemplateParams,
+ BlockPtrParam->getPointeeType(),
+ BlockPtrArg->getPointeeType(), Info,
+ Deduced, 0);
+ }
+
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::DependentName:
+ // No template argument deduction for these types
+ return Sema::TDK_Success;
+
+ default:
+ break;
+ }
+
+ // FIXME: Many more cases to go (to go).
+ return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument &Param,
+ TemplateArgument Arg,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ // If the template argument is a pack expansion, perform template argument
+ // deduction against the pattern of that expansion. This only occurs during
+ // partial ordering.
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+
+ switch (Param.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Null template argument in parameter list");
+ break;
+
+ case TemplateArgument::Type:
+ if (Arg.getKind() == TemplateArgument::Type)
+ return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(),
+ Arg.getAsType(), Info, Deduced, 0);
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::Template:
+ if (Arg.getKind() == TemplateArgument::Template)
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param.getAsTemplate(),
+ Arg.getAsTemplate(), Info, Deduced);
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("caller should handle pack expansions");
+ break;
+
+ case TemplateArgument::Declaration:
+ if (Arg.getKind() == TemplateArgument::Declaration &&
+ Param.getAsDecl()->getCanonicalDecl() ==
+ Arg.getAsDecl()->getCanonicalDecl())
+ return Sema::TDK_Success;
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::Integral:
+ if (Arg.getKind() == TemplateArgument::Integral) {
+ if (hasSameExtendedValue(*Param.getAsIntegral(), *Arg.getAsIntegral()))
+ return Sema::TDK_Success;
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::Expression: {
+ if (NonTypeTemplateParmDecl *NTTP
+ = getDeducedParameterFromExpr(Param.getAsExpr())) {
+ if (Arg.getKind() == TemplateArgument::Integral)
+ return DeduceNonTypeTemplateArgument(S, NTTP,
+ *Arg.getAsIntegral(),
+ Arg.getIntegralType(),
+ /*ArrayBound=*/false,
+ Info, Deduced);
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
+ Info, Deduced);
+ if (Arg.getKind() == TemplateArgument::Declaration)
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+ Info, Deduced);
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ // Can't deduce anything, but that's okay.
+ return Sema::TDK_Success;
+ }
+ case TemplateArgument::Pack:
+ llvm_unreachable("Argument packs should be expanded by the caller!");
+ }
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Determine whether there is a template argument to be used for
+/// deduction.
+///
+/// This routine "expands" argument packs in-place, overriding its input
+/// parameters so that \c Args[ArgIdx] will be the available template argument.
+///
+/// \returns true if there is another template argument (which will be at
+/// \c Args[ArgIdx]), false otherwise.
+static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
+ unsigned &ArgIdx,
+ unsigned &NumArgs) {
+ if (ArgIdx == NumArgs)
+ return false;
+
+ const TemplateArgument &Arg = Args[ArgIdx];
+ if (Arg.getKind() != TemplateArgument::Pack)
+ return true;
+
+ assert(ArgIdx == NumArgs - 1 && "Pack not at the end of argument list?");
+ Args = Arg.pack_begin();
+ NumArgs = Arg.pack_size();
+ ArgIdx = 0;
+ return ArgIdx < NumArgs;
+}
+
+/// \brief Determine whether the given set of template arguments has a pack
+/// expansion that is not the last template argument.
+static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ unsigned ArgIdx = 0;
+ while (ArgIdx < NumArgs) {
+ const TemplateArgument &Arg = Args[ArgIdx];
+
+ // Unwrap argument packs.
+ if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
+ Args = Arg.pack_begin();
+ NumArgs = Arg.pack_size();
+ ArgIdx = 0;
+ continue;
+ }
+
+ ++ArgIdx;
+ if (ArgIdx == NumArgs)
+ return false;
+
+ if (Arg.isPackExpansion())
+ return true;
+ }
+
+ return false;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgument *Params, unsigned NumParams,
+ const TemplateArgument *Args, unsigned NumArgs,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ bool NumberOfArgumentsMustMatch) {
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (hasPackExpansionBeforeEnd(Params, NumParams))
+ return Sema::TDK_Success;
+
+ // C++0x [temp.deduct.type]p9:
+ // If P has a form that contains <T> or <i>, then each argument Pi of the
+ // respective template argument list P is compared with the corresponding
+ // argument Ai of the corresponding template argument list of A.
+ unsigned ArgIdx = 0, ParamIdx = 0;
+ for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
+ ++ParamIdx) {
+ if (!Params[ParamIdx].isPackExpansion()) {
+ // The simple case: deduce template arguments by matching Pi and Ai.
+
+ // Check whether we have enough arguments.
+ if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+ return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch
+ : Sema::TDK_Success;
+
+ if (Args[ArgIdx].isPackExpansion()) {
+ // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
+ // but applied to pack expansions that are template arguments.
+ return Sema::TDK_NonDeducedMismatch;
+ }
+
+ // Perform deduction for this Pi/Ai pair.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ Params[ParamIdx], Args[ArgIdx],
+ Info, Deduced))
+ return Result;
+
+ // Move to the next argument.
+ ++ArgIdx;
+ continue;
+ }
+
+ // The parameter is a pack expansion.
+
+ // C++0x [temp.deduct.type]p9:
+ // If Pi is a pack expansion, then the pattern of Pi is compared with
+ // each remaining argument in the template argument list of A. Each
+ // comparison deduces template arguments for subsequent positions in the
+ // template parameter packs expanded by Pi.
+ TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
+
+ // Compute the set of template parameter indices that correspond to
+ // parameter packs expanded by the pack expansion.
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == 0 && !SawIndices[Index]) {
+ SawIndices[Index] = true;
+ PackIndices.push_back(Index);
+ }
+ }
+ }
+ assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+ // FIXME: If there are no remaining arguments, we can bail out early
+ // and set any deduced parameter packs to an empty argument pack.
+ // The latter part of this is a (minor) correctness issue.
+
+ // Save the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ bool HasAnyArguments = false;
+ while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
+ HasAnyArguments = true;
+
+ // Deduce template arguments from the pattern.
+ if (Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+ Info, Deduced))
+ return Result;
+
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+ if (!DeducedArg.isNull()) {
+ NewlyDeducedPacks[I].push_back(DeducedArg);
+ DeducedArg = DeducedTemplateArgument();
+ }
+ }
+
+ ++ArgIdx;
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ if (Sema::TemplateDeductionResult Result
+ = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
+ return Result;
+ }
+
+ // If there is an argument remaining, then we had too many arguments.
+ if (NumberOfArgumentsMustMatch &&
+ hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+ return Sema::TDK_NonDeducedMismatch;
+
+ return Sema::TDK_Success;
+}
+
+static Sema::TemplateDeductionResult
+DeduceTemplateArguments(Sema &S,
+ TemplateParameterList *TemplateParams,
+ const TemplateArgumentList &ParamList,
+ const TemplateArgumentList &ArgList,
+ TemplateDeductionInfo &Info,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceTemplateArguments(S, TemplateParams,
+ ParamList.data(), ParamList.size(),
+ ArgList.data(), ArgList.size(),
+ Info, Deduced);
+}
+
+/// \brief Determine whether two template arguments are the same.
+static bool isSameTemplateArg(ASTContext &Context,
+ const TemplateArgument &X,
+ const TemplateArgument &Y) {
+ if (X.getKind() != Y.getKind())
+ return false;
+
+ switch (X.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Comparing NULL template argument");
+ break;
+
+ case TemplateArgument::Type:
+ return Context.getCanonicalType(X.getAsType()) ==
+ Context.getCanonicalType(Y.getAsType());
+
+ case TemplateArgument::Declaration:
+ return X.getAsDecl()->getCanonicalDecl() ==
+ Y.getAsDecl()->getCanonicalDecl();
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ return Context.getCanonicalTemplateName(
+ X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+ Context.getCanonicalTemplateName(
+ Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
+
+ case TemplateArgument::Integral:
+ return *X.getAsIntegral() == *Y.getAsIntegral();
+
+ case TemplateArgument::Expression: {
+ llvm::FoldingSetNodeID XID, YID;
+ X.getAsExpr()->Profile(XID, Context, true);
+ Y.getAsExpr()->Profile(YID, Context, true);
+ return XID == YID;
+ }
+
+ case TemplateArgument::Pack:
+ if (X.pack_size() != Y.pack_size())
+ return false;
+
+ for (TemplateArgument::pack_iterator XP = X.pack_begin(),
+ XPEnd = X.pack_end(),
+ YP = Y.pack_begin();
+ XP != XPEnd; ++XP, ++YP)
+ if (!isSameTemplateArg(Context, *XP, *YP))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// been initialized to the given location.
+///
+/// \param S The semantic analysis object.
+///
+/// \param The template argument we are producing template argument
+/// location information for.
+///
+/// \param NTTPType For a declaration template argument, the type of
+/// the non-type template parameter that corresponds to this template
+/// argument.
+///
+/// \param Loc The source location to use for the resulting template
+/// argument.
+static TemplateArgumentLoc
+getTrivialTemplateArgumentLoc(Sema &S,
+ const TemplateArgument &Arg,
+ QualType NTTPType,
+ SourceLocation Loc) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Can't get a NULL template argument here");
+ break;
+
+ case TemplateArgument::Type:
+ return TemplateArgumentLoc(Arg,
+ S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+
+ case TemplateArgument::Declaration: {
+ Expr *E
+ = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .takeAs<Expr>();
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case TemplateArgument::Integral: {
+ Expr *E
+ = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+ return TemplateArgumentLoc(TemplateArgument(E), E);
+ }
+
+ case TemplateArgument::Template:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
+ case TemplateArgument::Expression:
+ return TemplateArgumentLoc(Arg, Arg.getAsExpr());
+
+ case TemplateArgument::Pack:
+ return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+ }
+
+ return TemplateArgumentLoc();
+}
+
+
+/// \brief Convert the given deduced template argument and add it to the set of
+/// fully-converted template arguments.
+static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
+ DeducedTemplateArgument Arg,
+ NamedDecl *Template,
+ QualType NTTPType,
+ unsigned ArgumentPackIndex,
+ TemplateDeductionInfo &Info,
+ bool InFunctionTemplate,
+ llvm::SmallVectorImpl<TemplateArgument> &Output) {
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ // This is a template argument pack, so check each of its arguments against
+ // the template parameter.
+ llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+ for (TemplateArgument::pack_iterator PA = Arg.pack_begin(),
+ PAEnd = Arg.pack_end();
+ PA != PAEnd; ++PA) {
+ // When converting the deduced template argument, append it to the
+ // general output list. We need to do this so that the template argument
+ // checking logic has all of the prior template arguments available.
+ DeducedTemplateArgument InnerArg(*PA);
+ InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
+ if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template,
+ NTTPType, PackedArgsBuilder.size(),
+ Info, InFunctionTemplate, Output))
+ return true;
+
+ // Move the converted template argument into our argument pack.
+ PackedArgsBuilder.push_back(Output.back());
+ Output.pop_back();
+ }
+
+ // Create the resulting argument pack.
+ Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
+ PackedArgsBuilder.data(),
+ PackedArgsBuilder.size()));
+ return false;
+ }
+
+ // Convert the deduced template argument into a template
+ // argument that we can check, almost as if the user had written
+ // the template argument explicitly.
+ TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
+ Info.getLocation());
+
+ // Check the template argument, converting it as necessary.
+ return S.CheckTemplateArgument(Param, ArgLoc,
+ Template,
+ Template->getLocation(),
+ Template->getSourceRange().getEnd(),
+ ArgumentPackIndex,
+ Output,
+ InFunctionTemplate
+ ? (Arg.wasDeducedFromArrayBound()
+ ? Sema::CTAK_DeducedFromArrayBound
+ : Sema::CTAK_Deduced)
+ : Sema::CTAK_Specified);
+}
+
+/// Complete template argument deduction for a class template partial
+/// specialization.
+static Sema::TemplateDeductionResult
+FinishTemplateArgumentDeduction(Sema &S,
+ ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Trap errors.
+ Sema::SFINAETrap Trap(S);
+
+ Sema::ContextRAII SavedContext(S, Partial);
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ llvm::SmallVector<TemplateArgument, 4> Builder;
+ TemplateParameterList *PartialParams = Partial->getTemplateParameters();
+ for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
+ NamedDecl *Param = PartialParams->getParam(I);
+ if (Deduced[I].isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ return Sema::TDK_Incomplete;
+ }
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+
+ // First, for a non-type template parameter type that is
+ // initialized by a declaration, we need the type of the
+ // corresponding non-type template parameter.
+ QualType NTTPType;
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ NTTPType = NTTP->getType();
+ if (NTTPType->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Builder.data(), Builder.size());
+ NTTPType = S.SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context,
+ Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+ }
+
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
+ Partial, NTTPType, 0, Info, false,
+ Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size()));
+ return Sema::TDK_SubstitutionFailure;
+ }
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList
+ = TemplateArgumentList::CreateCopy(S.Context, Builder.data(),
+ Builder.size());
+
+ Info.reset(DeducedArgumentList);
+
+ // Substitute the deduced template arguments into the template
+ // arguments of the class template partial specialization, and
+ // verify that the instantiated template arguments are both valid
+ // and are equivalent to the template arguments originally provided
+ // to the class template.
+ LocalInstantiationScope InstScope(S);
+ ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
+ const TemplateArgumentLoc *PartialTemplateArgs
+ = Partial->getTemplateArgsAsWritten();
+
+ // Note that we don't provide the langle and rangle locations.
+ TemplateArgumentListInfo InstArgs;
+
+ if (S.Subst(PartialTemplateArgs,
+ Partial->getNumTemplateArgsAsWritten(),
+ InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+ unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
+ if (ParamIdx >= Partial->getTemplateParameters()->size())
+ ParamIdx = Partial->getTemplateParameters()->size() - 1;
+
+ Decl *Param
+ = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(ParamIdx));
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+ return Sema::TDK_SubstitutionFailure;
+ }
+
+ llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs;
+ if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+ InstArgs, false, ConvertedInstArgs))
+ return Sema::TDK_SubstitutionFailure;
+
+ TemplateParameterList *TemplateParams
+ = ClassTemplate->getTemplateParameters();
+ for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+ TemplateArgument InstArg = ConvertedInstArgs.data()[I];
+ if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return Sema::TDK_Success;
+}
+
+/// \brief Perform template argument deduction to determine whether
+/// the given template arguments match the given class template
+/// partial specialization per C++ [temp.class.spec.match].
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ TemplateDeductionInfo &Info) {
+ // C++ [temp.class.spec.match]p2:
+ // A partial specialization matches a given actual template
+ // argument list if the template arguments of the partial
+ // specialization can be deduced from the actual template argument
+ // list (14.8.2).
+ SFINAETrap Trap(*this);
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ Deduced.resize(Partial->getTemplateParameters()->size());
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this,
+ Partial->getTemplateParameters(),
+ Partial->getTemplateArgs(),
+ TemplateArgs, Info, Deduced))
+ return Result;
+
+ InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
+ Deduced.data(), Deduced.size(), Info);
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
+ Deduced, Info);
+}
+
+/// \brief Determine whether the given type T is a simple-template-id type.
+static bool isSimpleTemplateIdType(QualType T) {
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>())
+ return Spec->getTemplateName().getAsTemplateDecl() != 0;
+
+ return false;
+}
+
+/// \brief Substitute the explicitly-provided template arguments into the
+/// given function template according to C++ [temp.arg.explicit].
+///
+/// \param FunctionTemplate the function template into which the explicit
+/// template arguments will be substituted.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Deduced the deduced template arguments, which will be populated
+/// with the converted and checked explicit template arguments.
+///
+/// \param ParamTypes will be populated with the instantiated function
+/// parameters.
+///
+/// \param FunctionType if non-NULL, the result type of the function template
+/// will also be instantiated and the pointed-to value will be updated with
+/// the instantiated function type.
+///
+/// \param Info if substitution fails for any reason, this object will be
+/// populated with more information about the failure.
+///
+/// \returns TDK_Success if substitution was successful, or some failure
+/// condition.
+Sema::TemplateDeductionResult
+Sema::SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ QualType *FunctionType,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+
+ if (ExplicitTemplateArgs.size() == 0) {
+ // No arguments to substitute; just copy over the parameter types and
+ // fill in the function type.
+ for (FunctionDecl::param_iterator P = Function->param_begin(),
+ PEnd = Function->param_end();
+ P != PEnd;
+ ++P)
+ ParamTypes.push_back((*P)->getType());
+
+ if (FunctionType)
+ *FunctionType = Function->getType();
+ return TDK_Success;
+ }
+
+ // Substitution of the explicit template arguments into a function template
+ /// is a SFINAE context. Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // C++ [temp.arg.explicit]p3:
+ // Template arguments that are present shall be specified in the
+ // declaration order of their corresponding template-parameters. The
+ // template argument list shall not specify more template-arguments than
+ // there are corresponding template-parameters.
+ llvm::SmallVector<TemplateArgument, 4> Builder;
+
+ // Enter a new template instantiation context where we check the
+ // explicitly-specified template arguments against this function template,
+ // and then substitute them into the function parameter types.
+ InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
+ Info);
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ if (CheckTemplateArgumentList(FunctionTemplate,
+ SourceLocation(),
+ ExplicitTemplateArgs,
+ true,
+ Builder) || Trap.hasErrorOccurred()) {
+ unsigned Index = Builder.size();
+ if (Index >= TemplateParams->size())
+ Index = TemplateParams->size() - 1;
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(Index));
+ return TDK_InvalidExplicitArguments;
+ }
+
+ // Form the template argument list from the explicitly-specified
+ // template arguments.
+ TemplateArgumentList *ExplicitArgumentList
+ = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
+ Info.reset(ExplicitArgumentList);
+
+ // Template argument deduction and the final substitution should be
+ // done in the context of the templated declaration. Explicit
+ // argument substitution, on the other hand, needs to happen in the
+ // calling context.
+ ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
+ // If we deduced template arguments for a template parameter pack,
+ // note that the template argument pack is partially substituted and record
+ // the explicit template arguments. They'll be used as part of deduction
+ // for this template parameter pack.
+ for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
+ const TemplateArgument &Arg = Builder[I];
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ TemplateParams->getParam(I),
+ Arg.pack_begin(),
+ Arg.pack_size());
+ break;
+ }
+ }
+
+ // Instantiate the types of each of the function parameters given the
+ // explicitly-specified template arguments.
+ if (SubstParmTypes(Function->getLocation(),
+ Function->param_begin(), Function->getNumParams(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ ParamTypes))
+ return TDK_SubstitutionFailure;
+
+ // If the caller wants a full function type back, instantiate the return
+ // type and form that function type.
+ if (FunctionType) {
+ // FIXME: exception-specifications?
+ const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>();
+ assert(Proto && "Function template does not have a prototype?");
+
+ QualType ResultType
+ = SubstType(Proto->getResultType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(),
+ Function->getDeclName());
+ if (ResultType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+
+ *FunctionType = BuildFunctionType(ResultType,
+ ParamTypes.data(), ParamTypes.size(),
+ Proto->isVariadic(),
+ Proto->getTypeQuals(),
+ Proto->getRefQualifier(),
+ Function->getLocation(),
+ Function->getDeclName(),
+ Proto->getExtInfo());
+ if (FunctionType->isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+ }
+
+ // C++ [temp.arg.explicit]p2:
+ // Trailing template arguments that can be deduced (14.8.2) may be
+ // omitted from the list of explicit template-arguments. If all of the
+ // template arguments can be deduced, they may all be omitted; in this
+ // case, the empty template argument list <> itself may also be omitted.
+ //
+ // Take all of the explicitly-specified arguments and put them into
+ // the set of deduced template arguments. Explicitly-specified
+ // parameter packs, however, will be set to NULL since the deduction
+ // mechanisms handle explicitly-specified argument packs directly.
+ Deduced.reserve(TemplateParams->size());
+ for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
+ const TemplateArgument &Arg = ExplicitArgumentList->get(I);
+ if (Arg.getKind() == TemplateArgument::Pack)
+ Deduced.push_back(DeducedTemplateArgument());
+ else
+ Deduced.push_back(Arg);
+ }
+
+ return TDK_Success;
+}
+
+/// \brief Finish template argument deduction for a function template,
+/// checking the deduced template arguments for completeness and forming
+/// the function template specialization.
+Sema::TemplateDeductionResult
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // Enter a new template instantiation context while we instantiate the
+ // actual function declaration.
+ InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ Info);
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ llvm::SmallVector<TemplateArgument, 4> Builder;
+ for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+ NamedDecl *Param = TemplateParams->getParam(I);
+
+ if (!Deduced[I].isNull()) {
+ if (I < NumExplicitlySpecified) {
+ // We have already fully type-checked and converted this
+ // argument, because it was explicitly-specified. Just record the
+ // presence of this argument.
+ Builder.push_back(Deduced[I]);
+ continue;
+ }
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+
+ // First, for a non-type template parameter type that is
+ // initialized by a declaration, we need the type of the
+ // corresponding non-type template parameter.
+ QualType NTTPType;
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ NTTPType = NTTP->getType();
+ if (NTTPType->isDependentType()) {
+ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
+ Builder.data(), Builder.size());
+ NTTPType = SubstType(NTTPType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
+ NTTP->getLocation(),
+ NTTP->getDeclName());
+ if (NTTPType.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context,
+ Builder.data(),
+ Builder.size()));
+ return TDK_SubstitutionFailure;
+ }
+ }
+ }
+
+ if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
+ FunctionTemplate, NTTPType, 0, Info,
+ true, Builder)) {
+ Info.Param = makeTemplateParameter(Param);
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
+ return TDK_SubstitutionFailure;
+ }
+
+ continue;
+ }
+
+ // C++0x [temp.arg.explicit]p3:
+ // A trailing template parameter pack (14.5.3) not otherwise deduced will
+ // be deduced to an empty sequence of template arguments.
+ // FIXME: Where did the word "trailing" come from?
+ if (Param->isTemplateParameterPack()) {
+ // We may have had explicitly-specified template arguments for this
+ // template parameter pack. If so, our empty deduction extends the
+ // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
+ &NumExplicitArgs)
+ == Param)
+ Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ else
+ Builder.push_back(TemplateArgument(0, 0));
+
+ continue;
+ }
+
+ // Substitute into the default template argument, if available.
+ TemplateArgumentLoc DefArg
+ = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
+ FunctionTemplate->getLocation(),
+ FunctionTemplate->getSourceRange().getEnd(),
+ Param,
+ Builder);
+
+ // If there was no default argument, deduction is incomplete.
+ if (DefArg.getArgument().isNull()) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ return TDK_Incomplete;
+ }
+
+ // Check whether we can actually use the default argument.
+ if (CheckTemplateArgument(Param, DefArg,
+ FunctionTemplate,
+ FunctionTemplate->getLocation(),
+ FunctionTemplate->getSourceRange().getEnd(),
+ 0, Builder,
+ CTAK_Deduced)) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ // FIXME: These template arguments are temporary. Free them!
+ Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(),
+ Builder.size()));
+ return TDK_SubstitutionFailure;
+ }
+
+ // If we get here, we successfully used the default template argument.
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList
+ = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
+ Info.reset(DeducedArgumentList);
+
+ // Substitute the deduced template arguments into the function template
+ // declaration to produce the function template specialization.
+ DeclContext *Owner = FunctionTemplate->getDeclContext();
+ if (FunctionTemplate->getFriendObjectKind())
+ Owner = FunctionTemplate->getLexicalDeclContext();
+ Specialization = cast_or_null<FunctionDecl>(
+ SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
+ MultiLevelTemplateArgumentList(*DeducedArgumentList)));
+ if (!Specialization)
+ return TDK_SubstitutionFailure;
+
+ assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
+ FunctionTemplate->getCanonicalDecl());
+
+ // If the template argument list is owned by the function template
+ // specialization, release it.
+ if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
+ !Trap.hasErrorOccurred())
+ Info.take();
+
+ // There may have been an error that did not prevent us from constructing a
+ // declaration. Mark the declaration invalid and return with a substitution
+ // failure.
+ if (Trap.hasErrorOccurred()) {
+ Specialization->setInvalidDecl(true);
+ return TDK_SubstitutionFailure;
+ }
+
+ // If we suppressed any diagnostics while performing template argument
+ // deduction, and if we haven't already instantiated this declaration,
+ // keep track of these diagnostics. They'll be emitted if this specialization
+ // is actually used.
+ if (Info.diag_begin() != Info.diag_end()) {
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+ Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
+ if (Pos == SuppressedDiagnostics.end())
+ SuppressedDiagnostics[Specialization->getCanonicalDecl()]
+ .append(Info.diag_begin(), Info.diag_end());
+ }
+
+ return TDK_Success;
+}
+
+/// Gets the type of a function for template-argument-deducton
+/// purposes when it's considered as part of an overload set.
+static QualType GetTypeOfFunction(ASTContext &Context,
+ const OverloadExpr::FindResult &R,
+ FunctionDecl *Fn) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
+ if (Method->isInstance()) {
+ // An instance method that's referenced in a form that doesn't
+ // look like a member pointer is just invalid.
+ if (!R.HasFormOfMemberPointer) return QualType();
+
+ return Context.getMemberPointerType(Fn->getType(),
+ Context.getTypeDeclType(Method->getParent()).getTypePtr());
+ }
+
+ if (!R.IsAddressOfOperand) return Fn->getType();
+ return Context.getPointerType(Fn->getType());
+}
+
+/// Apply the deduction rules for overload sets.
+///
+/// \return the null type if this argument should be treated as an
+/// undeduced context
+static QualType
+ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
+ Expr *Arg, QualType ParamType,
+ bool ParamWasReference) {
+
+ OverloadExpr::FindResult R = OverloadExpr::find(Arg);
+
+ OverloadExpr *Ovl = R.Expression;
+
+ // C++0x [temp.deduct.call]p4
+ unsigned TDF = 0;
+ if (ParamWasReference)
+ TDF |= TDF_ParamWithReferenceType;
+ if (R.IsAddressOfOperand)
+ TDF |= TDF_IgnoreQualifiers;
+
+ // If there were explicit template arguments, we can only find
+ // something via C++ [temp.arg.explicit]p3, i.e. if the arguments
+ // unambiguously name a full specialization.
+ if (Ovl->hasExplicitTemplateArgs()) {
+ // But we can still look for an explicit specialization.
+ if (FunctionDecl *ExplicitSpec
+ = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+ return GetTypeOfFunction(S.Context, R, ExplicitSpec);
+ return QualType();
+ }
+
+ // C++0x [temp.deduct.call]p6:
+ // When P is a function type, pointer to function type, or pointer
+ // to member function type:
+
+ if (!ParamType->isFunctionType() &&
+ !ParamType->isFunctionPointerType() &&
+ !ParamType->isMemberFunctionPointerType())
+ return QualType();
+
+ QualType Match;
+ for (UnresolvedSetIterator I = Ovl->decls_begin(),
+ E = Ovl->decls_end(); I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+
+ // - If the argument is an overload set containing one or more
+ // function templates, the parameter is treated as a
+ // non-deduced context.
+ if (isa<FunctionTemplateDecl>(D))
+ return QualType();
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ QualType ArgType = GetTypeOfFunction(S.Context, R, Fn);
+ if (ArgType.isNull()) continue;
+
+ // Function-to-pointer conversion.
+ if (!ParamWasReference && ParamType->isPointerType() &&
+ ArgType->isFunctionType())
+ ArgType = S.Context.getPointerType(ArgType);
+
+ // - If the argument is an overload set (not containing function
+ // templates), trial argument deduction is attempted using each
+ // of the members of the set. If deduction succeeds for only one
+ // of the overload set members, that member is used as the
+ // argument value for the deduction. If deduction succeeds for
+ // more than one member of the overload set the parameter is
+ // treated as a non-deduced context.
+
+ // We do all of this in a fresh context per C++0x [temp.deduct.type]p2:
+ // Type deduction is done independently for each P/A pair, and
+ // the deduced template argument values are then combined.
+ // So we do not reject deductions which were made elsewhere.
+ llvm::SmallVector<DeducedTemplateArgument, 8>
+ Deduced(TemplateParams->size());
+ TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+ Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ ParamType, ArgType,
+ Info, Deduced, TDF);
+ if (Result) continue;
+ if (!Match.isNull()) return QualType();
+ Match = ArgType;
+ }
+
+ return Match;
+}
+
+/// \brief Perform the adjustments to the parameter and argument types
+/// described in C++ [temp.deduct.call].
+///
+/// \returns true if the caller should not attempt to perform any template
+/// argument deduction based on this P/A pair.
+static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
+ TemplateParameterList *TemplateParams,
+ QualType &ParamType,
+ QualType &ArgType,
+ Expr *Arg,
+ unsigned &TDF) {
+ // C++0x [temp.deduct.call]p3:
+ // If P is a cv-qualified type, the top level cv-qualifiers of P's type
+ // are ignored for type deduction.
+ if (ParamType.getCVRQualifiers())
+ ParamType = ParamType.getLocalUnqualifiedType();
+ const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+ if (ParamRefType) {
+ QualType PointeeType = ParamRefType->getPointeeType();
+
+ // [C++0x] If P is an rvalue reference to a cv-unqualified
+ // template parameter and the argument is an lvalue, the type
+ // "lvalue reference to A" is used in place of A for type
+ // deduction.
+ if (isa<RValueReferenceType>(ParamType)) {
+ if (!PointeeType.getQualifiers() &&
+ isa<TemplateTypeParmType>(PointeeType) &&
+ Arg->Classify(S.Context).isLValue())
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ }
+
+ // [...] If P is a reference type, the type referred to by P is used
+ // for type deduction.
+ ParamType = PointeeType;
+ }
+
+ // Overload sets usually make this parameter an undeduced
+ // context, but there are sometimes special circumstances.
+ if (ArgType == S.Context.OverloadTy) {
+ ArgType = ResolveOverloadForDeduction(S, TemplateParams,
+ Arg, ParamType,
+ ParamRefType != 0);
+ if (ArgType.isNull())
+ return true;
+ }
+
+ if (ParamRefType) {
+ // C++0x [temp.deduct.call]p3:
+ // [...] If P is of the form T&&, where T is a template parameter, and
+ // the argument is an lvalue, the type A& is used in place of A for
+ // type deduction.
+ if (ParamRefType->isRValueReferenceType() &&
+ ParamRefType->getAs<TemplateTypeParmType>() &&
+ Arg->isLValue())
+ ArgType = S.Context.getLValueReferenceType(ArgType);
+ } else {
+ // C++ [temp.deduct.call]p2:
+ // If P is not a reference type:
+ // - If A is an array type, the pointer type produced by the
+ // array-to-pointer standard conversion (4.2) is used in place of
+ // A for type deduction; otherwise,
+ if (ArgType->isArrayType())
+ ArgType = S.Context.getArrayDecayedType(ArgType);
+ // - If A is a function type, the pointer type produced by the
+ // function-to-pointer standard conversion (4.3) is used in place
+ // of A for type deduction; otherwise,
+ else if (ArgType->isFunctionType())
+ ArgType = S.Context.getPointerType(ArgType);
+ else {
+ // - If A is a cv-qualified type, the top level cv-qualifiers of A's
+ // type are ignored for type deduction.
+ if (ArgType.getCVRQualifiers())
+ ArgType = ArgType.getUnqualifiedType();
+ }
+ }
+
+ // C++0x [temp.deduct.call]p4:
+ // In general, the deduction process attempts to find template argument
+ // values that will make the deduced A identical to A (after the type A
+ // is transformed as described above). [...]
+ TDF = TDF_SkipNonDependent;
+
+ // - If the original P is a reference type, the deduced A (i.e., the
+ // type referred to by the reference) can be more cv-qualified than
+ // the transformed A.
+ if (ParamRefType)
+ TDF |= TDF_ParamWithReferenceType;
+ // - The transformed A can be another pointer or pointer to member
+ // type that can be converted to the deduced A via a qualification
+ // conversion (4.4).
+ if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
+ ArgType->isObjCObjectPointerType())
+ TDF |= TDF_IgnoreQualifiers;
+ // - If P is a class and P has the form simple-template-id, then the
+ // transformed A can be a derived class of the deduced A. Likewise,
+ // if P is a pointer to a class of the form simple-template-id, the
+ // transformed A can be a pointer to a derived class pointed to by
+ // the deduced A.
+ if (isSimpleTemplateIdType(ParamType) ||
+ (isa<PointerType>(ParamType) &&
+ isSimpleTemplateIdType(
+ ParamType->getAs<PointerType>()->getPointeeType())))
+ TDF |= TDF_DerivedClass;
+
+ return false;
+}
+
+/// \brief Perform template argument deduction from a function call
+/// (C++ [temp.deduct.call]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicit template arguments provided
+/// for this call.
+///
+/// \param Args the function call arguments
+///
+/// \param NumArgs the number of arguments in Args
+///
+/// \param Name the name of the function being called. This is only significant
+/// when the function template is a conversion function template, in which
+/// case this routine will also perform template argument deduction based on
+/// the function to which
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ Expr **Args, unsigned NumArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+
+ // C++ [temp.deduct.call]p1:
+ // Template argument deduction is done by comparing each function template
+ // parameter type (call it P) with the type of the corresponding argument
+ // of the call (call it A) as described below.
+ unsigned CheckArgs = NumArgs;
+ if (NumArgs < Function->getMinRequiredArguments())
+ return TDK_TooFewArguments;
+ else if (NumArgs > Function->getNumParams()) {
+ const FunctionProtoType *Proto
+ = Function->getType()->getAs<FunctionProtoType>();
+ if (Proto->isTemplateVariadic())
+ /* Do nothing */;
+ else if (Proto->isVariadic())
+ CheckArgs = Function->getNumParams();
+ else
+ return TDK_TooManyArguments;
+ }
+
+ // The types of the parameters from which we will perform template argument
+ // deduction.
+ LocalInstantiationScope InstScope(*this);
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ unsigned NumExplicitlySpecified = 0;
+ if (ExplicitTemplateArgs) {
+ TemplateDeductionResult Result =
+ SubstituteExplicitTemplateArguments(FunctionTemplate,
+ *ExplicitTemplateArgs,
+ Deduced,
+ ParamTypes,
+ 0,
+ Info);
+ if (Result)
+ return Result;
+
+ NumExplicitlySpecified = Deduced.size();
+ } else {
+ // Just fill in the parameter types from the function declaration.
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+ ParamTypes.push_back(Function->getParamDecl(I)->getType());
+ }
+
+ // Deduce template arguments from the function parameters.
+ Deduced.resize(TemplateParams->size());
+ unsigned ArgIdx = 0;
+ for (unsigned ParamIdx = 0, NumParams = ParamTypes.size();
+ ParamIdx != NumParams; ++ParamIdx) {
+ QualType ParamType = ParamTypes[ParamIdx];
+
+ const PackExpansionType *ParamExpansion
+ = dyn_cast<PackExpansionType>(ParamType);
+ if (!ParamExpansion) {
+ // Simple case: matching a function parameter to a function argument.
+ if (ArgIdx >= CheckArgs)
+ break;
+
+ Expr *Arg = Args[ArgIdx++];
+ QualType ArgType = Arg->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ ParamType, ArgType, Arg,
+ TDF))
+ continue;
+
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ ParamType, ArgType, Info, Deduced,
+ TDF))
+ return Result;
+
+ // FIXME: we need to check that the deduced A is the same as A,
+ // modulo the various allowed differences.
+ continue;
+ }
+
+ // C++0x [temp.deduct.call]p1:
+ // For a function parameter pack that occurs at the end of the
+ // parameter-declaration-list, the type A of each remaining argument of
+ // the call is compared with the type P of the declarator-id of the
+ // function parameter pack. Each comparison deduces template arguments
+ // for subsequent positions in the template parameter packs expanded by
+ // the function parameter pack. For a function parameter pack that does
+ // not occur at the end of the parameter-declaration-list, the type of
+ // the parameter pack is a non-deduced context.
+ if (ParamIdx + 1 < NumParams)
+ break;
+
+ QualType ParamPattern = ParamExpansion->getPattern();
+ llvm::SmallVector<unsigned, 2> PackIndices;
+ {
+ llvm::BitVector SawIndices(TemplateParams->size());
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(ParamPattern, Unexpanded);
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+ if (Depth == 0 && !SawIndices[Index]) {
+ SawIndices[Index] = true;
+ PackIndices.push_back(Index);
+ }
+ }
+ }
+ assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks);
+ bool HasAnyArguments = false;
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ HasAnyArguments = true;
+
+ ParamType = ParamPattern;
+ Expr *Arg = Args[ArgIdx];
+ QualType ArgType = Arg->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ ParamType, ArgType, Arg,
+ TDF)) {
+ // We can't actually perform any deduction for this argument, so stop
+ // deduction at this point.
+ ++ArgIdx;
+ break;
+ }
+
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ ParamType, ArgType, Info, Deduced,
+ TDF))
+ return Result;
+
+ // Capture the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, add them to the list of arguments we've deduced
+ // for that pack, then clear out the deduced argument.
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+ if (!DeducedArg.isNull()) {
+ NewlyDeducedPacks[I].push_back(DeducedArg);
+ DeducedArg = DeducedTemplateArgument();
+ }
+ }
+ }
+
+ // Build argument packs for each of the parameter packs expanded by this
+ // pack expansion.
+ if (Sema::TemplateDeductionResult Result
+ = FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments,
+ Deduced, PackIndices, SavedPacks,
+ NewlyDeducedPacks, Info))
+ return Result;
+
+ // After we've matching against a parameter pack, we're done.
+ break;
+ }
+
+ return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+ NumExplicitlySpecified,
+ Specialization, Info);
+}
+
+/// \brief Deduce template arguments when taking the address of a function
+/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
+/// a template.
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param ArgFunctionType the function type that will be used as the
+/// "argument" type (A) when performing template argument deduction from the
+/// function template's function type. This type may be NULL, if there is no
+/// argument type to compare against, in C++0x [temp.arg.explicit]p3.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ QualType FunctionType = Function->getType();
+
+ // Substitute any explicit template arguments.
+ LocalInstantiationScope InstScope(*this);
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ unsigned NumExplicitlySpecified = 0;
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ if (ExplicitTemplateArgs) {
+ if (TemplateDeductionResult Result
+ = SubstituteExplicitTemplateArguments(FunctionTemplate,
+ *ExplicitTemplateArgs,
+ Deduced, ParamTypes,
+ &FunctionType, Info))
+ return Result;
+
+ NumExplicitlySpecified = Deduced.size();
+ }
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ Deduced.resize(TemplateParams->size());
+
+ if (!ArgFunctionType.isNull()) {
+ // Deduce template arguments from the function type.
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ FunctionType, ArgFunctionType, Info,
+ Deduced, TDF_TopLevelParameterTypeList))
+ return Result;
+ }
+
+ if (TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
+ NumExplicitlySpecified,
+ Specialization, Info))
+ return Result;
+
+ // If the requested function type does not match the actual type of the
+ // specialization, template argument deduction fails.
+ if (!ArgFunctionType.isNull() &&
+ !Context.hasSameType(ArgFunctionType, Specialization->getType()))
+ return TDK_NonDeducedMismatch;
+
+ return TDK_Success;
+}
+
+/// \brief Deduce template arguments for a templated conversion
+/// function (C++ [temp.deduct.conv]) and, if successful, produce a
+/// conversion function template specialization.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl());
+ QualType FromType = Conv->getConversionType();
+
+ // Canonicalize the types for deduction.
+ QualType P = Context.getCanonicalType(FromType);
+ QualType A = Context.getCanonicalType(ToType);
+
+ // C++0x [temp.deduct.conv]p3:
+ // If P is a reference type, the type referred to by P is used for
+ // type deduction.
+ if (const ReferenceType *PRef = P->getAs<ReferenceType>())
+ P = PRef->getPointeeType();
+
+ // C++0x [temp.deduct.conv]p3:
+ // If A is a reference type, the type referred to by A is used
+ // for type deduction.
+ if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+ A = ARef->getPointeeType();
+ // C++ [temp.deduct.conv]p2:
+ //
+ // If A is not a reference type:
+ else {
+ assert(!A->isReferenceType() && "Reference types were handled above");
+
+ // - If P is an array type, the pointer type produced by the
+ // array-to-pointer standard conversion (4.2) is used in place
+ // of P for type deduction; otherwise,
+ if (P->isArrayType())
+ P = Context.getArrayDecayedType(P);
+ // - If P is a function type, the pointer type produced by the
+ // function-to-pointer standard conversion (4.3) is used in
+ // place of P for type deduction; otherwise,
+ else if (P->isFunctionType())
+ P = Context.getPointerType(P);
+ // - If P is a cv-qualified type, the top level cv-qualifiers of
+ // P's type are ignored for type deduction.
+ else
+ P = P.getUnqualifiedType();
+
+ // C++0x [temp.deduct.conv]p3:
+ // If A is a cv-qualified type, the top level cv-qualifiers of A's
+ // type are ignored for type deduction.
+ A = A.getUnqualifiedType();
+ }
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // C++ [temp.deduct.conv]p1:
+ // Template argument deduction is done by comparing the return
+ // type of the template conversion function (call it P) with the
+ // type that is required as the result of the conversion (call it
+ // A) as described in 14.8.2.4.
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ Deduced.resize(TemplateParams->size());
+
+ // C++0x [temp.deduct.conv]p4:
+ // In general, the deduction process attempts to find template
+ // argument values that will make the deduced A identical to
+ // A. However, there are two cases that allow a difference:
+ unsigned TDF = 0;
+ // - If the original A is a reference type, A can be more
+ // cv-qualified than the deduced A (i.e., the type referred to
+ // by the reference)
+ if (ToType->isReferenceType())
+ TDF |= TDF_ParamWithReferenceType;
+ // - The deduced A can be another pointer or pointer to member
+ // type that can be converted to A via a qualification
+ // conversion.
+ //
+ // (C++0x [temp.deduct.conv]p6 clarifies that this only happens when
+ // both P and A are pointers or member pointers. In this case, we
+ // just ignore cv-qualifiers completely).
+ if ((P->isPointerType() && A->isPointerType()) ||
+ (P->isMemberPointerType() && P->isMemberPointerType()))
+ TDF |= TDF_IgnoreQualifiers;
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(*this, TemplateParams,
+ P, A, Info, Deduced, TDF))
+ return Result;
+
+ // FIXME: we need to check that the deduced A is the same as A,
+ // modulo the various allowed differences.
+
+ // Finish template argument deduction.
+ LocalInstantiationScope InstScope(*this);
+ FunctionDecl *Spec = 0;
+ TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
+ Info);
+ Specialization = cast_or_null<CXXConversionDecl>(Spec);
+ return Result;
+}
+
+/// \brief Deduce template arguments for a function template when there is
+/// nothing to deduce against (C++0x [temp.arg.explicit]p3).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template
+/// arguments.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
+ QualType(), Specialization, Info);
+}
+
+namespace {
+ /// Substitute the 'auto' type specifier within a type for a given replacement
+ /// type.
+ class SubstituteAutoTransform :
+ public TreeTransform<SubstituteAutoTransform> {
+ QualType Replacement;
+ public:
+ SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) :
+ TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) {
+ }
+ QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
+ // If we're building the type pattern to deduce against, don't wrap the
+ // substituted type in an AutoType. Certain template deduction rules
+ // apply only when a template type parameter appears directly (and not if
+ // the parameter is found through desugaring). For instance:
+ // auto &&lref = lvalue;
+ // must transform into "rvalue reference to T" not "rvalue reference to
+ // auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
+ if (isa<TemplateTypeParmType>(Replacement)) {
+ QualType Result = Replacement;
+ TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+ } else {
+ QualType Result = RebuildAutoType(Replacement);
+ AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+ }
+ }
+ };
+}
+
+/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6)
+///
+/// \param Type the type pattern using the auto type-specifier.
+///
+/// \param Init the initializer for the variable whose type is to be deduced.
+///
+/// \param Result if type deduction was successful, this will be set to the
+/// deduced type. This may still contain undeduced autos if the type is
+/// dependent.
+///
+/// \returns true if deduction succeeded, false if it failed.
+bool
+Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
+ if (Init->isTypeDependent()) {
+ Result = Type;
+ return true;
+ }
+
+ SourceLocation Loc = Init->getExprLoc();
+
+ LocalInstantiationScope InstScope(*this);
+
+ // Build template<class TemplParam> void Func(FuncParam);
+ NamedDecl *TemplParam
+ = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
+ TemplateParameterList *TemplateParams
+ = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
+
+ QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+ QualType FuncParam =
+ SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+
+ // Deduce type of TemplParam in Func(Init)
+ llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
+ Deduced.resize(1);
+ QualType InitType = Init->getType();
+ unsigned TDF = 0;
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ FuncParam, InitType, Init,
+ TDF))
+ return false;
+
+ TemplateDeductionInfo Info(Context, Loc);
+ if (::DeduceTemplateArguments(*this, TemplateParams,
+ FuncParam, InitType, Info, Deduced,
+ TDF))
+ return false;
+
+ QualType DeducedType = Deduced[0].getAsType();
+ if (DeducedType.isNull())
+ return false;
+
+ Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
+ return true;
+}
+
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+ bool OnlyDeduced,
+ unsigned Level,
+ llvm::SmallVectorImpl<bool> &Deduced);
+
+/// \brief If this is a non-static member function,
+static void MaybeAddImplicitObjectParameterType(ASTContext &Context,
+ CXXMethodDecl *Method,
+ llvm::SmallVectorImpl<QualType> &ArgTypes) {
+ if (Method->isStatic())
+ return;
+
+ // C++ [over.match.funcs]p4:
+ //
+ // For non-static member functions, the type of the implicit
+ // object parameter is
+ // - "lvalue reference to cv X" for functions declared without a
+ // ref-qualifier or with the & ref-qualifier
+ // - "rvalue reference to cv X" for functions declared with the
+ // && ref-qualifier
+ //
+ // FIXME: We don't have ref-qualifiers yet, so we don't do that part.
+ QualType ArgTy = Context.getTypeDeclType(Method->getParent());
+ ArgTy = Context.getQualifiedType(ArgTy,
+ Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+ ArgTy = Context.getLValueReferenceType(ArgTy);
+ ArgTypes.push_back(ArgTy);
+}
+
+/// \brief Determine whether the function template \p FT1 is at least as
+/// specialized as \p FT2.
+static bool isAtLeastAsSpecializedAs(Sema &S,
+ SourceLocation Loc,
+ FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
+ FunctionDecl *FD1 = FT1->getTemplatedDecl();
+ FunctionDecl *FD2 = FT2->getTemplatedDecl();
+ const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
+
+ assert(Proto1 && Proto2 && "Function templates must have prototypes");
+ TemplateParameterList *TemplateParams = FT2->getTemplateParameters();
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ Deduced.resize(TemplateParams->size());
+
+ // C++0x [temp.deduct.partial]p3:
+ // The types used to determine the ordering depend on the context in which
+ // the partial ordering is done:
+ TemplateDeductionInfo Info(S.Context, Loc);
+ CXXMethodDecl *Method1 = 0;
+ CXXMethodDecl *Method2 = 0;
+ bool IsNonStatic2 = false;
+ bool IsNonStatic1 = false;
+ unsigned Skip2 = 0;
+ switch (TPOC) {
+ case TPOC_Call: {
+ // - In the context of a function call, the function parameter types are
+ // used.
+ Method1 = dyn_cast<CXXMethodDecl>(FD1);
+ Method2 = dyn_cast<CXXMethodDecl>(FD2);
+ IsNonStatic1 = Method1 && !Method1->isStatic();
+ IsNonStatic2 = Method2 && !Method2->isStatic();
+
+ // C++0x [temp.func.order]p3:
+ // [...] If only one of the function templates is a non-static
+ // member, that function template is considered to have a new
+ // first parameter inserted in its function parameter list. The
+ // new parameter is of type "reference to cv A," where cv are
+ // the cv-qualifiers of the function template (if any) and A is
+ // the class of which the function template is a member.
+ //
+ // C++98/03 doesn't have this provision, so instead we drop the
+ // first argument of the free function or static member, which
+ // seems to match existing practice.
+ llvm::SmallVector<QualType, 4> Args1;
+ unsigned Skip1 = !S.getLangOptions().CPlusPlus0x &&
+ IsNonStatic2 && !IsNonStatic1;
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2)
+ MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1);
+ Args1.insert(Args1.end(),
+ Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end());
+
+ llvm::SmallVector<QualType, 4> Args2;
+ Skip2 = !S.getLangOptions().CPlusPlus0x &&
+ IsNonStatic1 && !IsNonStatic2;
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+ MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2);
+ Args2.insert(Args2.end(),
+ Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end());
+
+ // C++ [temp.func.order]p5:
+ // The presence of unused ellipsis and default arguments has no effect on
+ // the partial ordering of function templates.
+ if (Args1.size() > NumCallArguments)
+ Args1.resize(NumCallArguments);
+ if (Args2.size() > NumCallArguments)
+ Args2.resize(NumCallArguments);
+ if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
+ Args1.data(), Args1.size(), Info, Deduced,
+ TDF_None, /*PartialOrdering=*/true,
+ RefParamComparisons))
+ return false;
+
+ break;
+ }
+
+ case TPOC_Conversion:
+ // - In the context of a call to a conversion operator, the return types
+ // of the conversion function templates are used.
+ if (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(),
+ Proto1->getResultType(), Info, Deduced,
+ TDF_None, /*PartialOrdering=*/true,
+ RefParamComparisons))
+ return false;
+ break;
+
+ case TPOC_Other:
+ // - In other contexts (14.6.6.2) the function template's function type
+ // is used.
+ // FIXME: Don't we actually want to perform the adjustments on the parameter
+ // types?
+ if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(),
+ FD1->getType(), Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true, RefParamComparisons))
+ return false;
+ break;
+ }
+
+ // C++0x [temp.deduct.partial]p11:
+ // In most cases, all template parameters must have values in order for
+ // deduction to succeed, but for partial ordering purposes a template
+ // parameter may remain without a value provided it is not used in the
+ // types being used for partial ordering. [ Note: a template parameter used
+ // in a non-deduced context is considered used. -end note]
+ unsigned ArgIdx = 0, NumArgs = Deduced.size();
+ for (; ArgIdx != NumArgs; ++ArgIdx)
+ if (Deduced[ArgIdx].isNull())
+ break;
+
+ if (ArgIdx == NumArgs) {
+ // All template arguments were deduced. FT1 is at least as specialized
+ // as FT2.
+ return true;
+ }
+
+ // Figure out which template parameters were used.
+ llvm::SmallVector<bool, 4> UsedParameters;
+ UsedParameters.resize(TemplateParams->size());
+ switch (TPOC) {
+ case TPOC_Call: {
+ unsigned NumParams = std::min(NumCallArguments,
+ std::min(Proto1->getNumArgs(),
+ Proto2->getNumArgs()));
+ if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1)
+ ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false,
+ TemplateParams->getDepth(), UsedParameters);
+ for (unsigned I = Skip2; I < NumParams; ++I)
+ ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false,
+ TemplateParams->getDepth(),
+ UsedParameters);
+ break;
+ }
+
+ case TPOC_Conversion:
+ ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false,
+ TemplateParams->getDepth(),
+ UsedParameters);
+ break;
+
+ case TPOC_Other:
+ ::MarkUsedTemplateParameters(S, FD2->getType(), false,
+ TemplateParams->getDepth(),
+ UsedParameters);
+ break;
+ }
+
+ for (; ArgIdx != NumArgs; ++ArgIdx)
+ // If this argument had no value deduced but was used in one of the types
+ // used for partial ordering, then deduction fails.
+ if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx])
+ return false;
+
+ return true;
+}
+
+/// \brief Determine whether this a function template whose parameter-type-list
+/// ends with a function parameter pack.
+static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) {
+ FunctionDecl *Function = FunTmpl->getTemplatedDecl();
+ unsigned NumParams = Function->getNumParams();
+ if (NumParams == 0)
+ return false;
+
+ ParmVarDecl *Last = Function->getParamDecl(NumParams - 1);
+ if (!Last->isParameterPack())
+ return false;
+
+ // Make sure that no previous parameter is a parameter pack.
+ while (--NumParams > 0) {
+ if (Function->getParamDecl(NumParams - 1)->isParameterPack())
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Returns the more specialized function template according
+/// to the rules of function template partial ordering (C++ [temp.func.order]).
+///
+/// \param FT1 the first function template
+///
+/// \param FT2 the second function template
+///
+/// \param TPOC the context in which we are performing partial ordering of
+/// function templates.
+///
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
+/// \returns the more specialized function template. If neither
+/// template is more specialized, returns NULL.
+FunctionTemplateDecl *
+Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments) {
+ llvm::SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
+ bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
+ NumCallArguments, 0);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
+ NumCallArguments,
+ &RefParamComparisons);
+
+ if (Better1 != Better2) // We have a clear winner
+ return Better1? FT1 : FT2;
+
+ if (!Better1 && !Better2) // Neither is better than the other
+ return 0;
+
+ // C++0x [temp.deduct.partial]p10:
+ // If for each type being considered a given template is at least as
+ // specialized for all types and more specialized for some set of types and
+ // the other template is not more specialized for any types or is not at
+ // least as specialized for any types, then the given template is more
+ // specialized than the other template. Otherwise, neither template is more
+ // specialized than the other.
+ Better1 = false;
+ Better2 = false;
+ for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) {
+ // C++0x [temp.deduct.partial]p9:
+ // If, for a given type, deduction succeeds in both directions (i.e., the
+ // types are identical after the transformations above) and both P and A
+ // were reference types (before being replaced with the type referred to
+ // above):
+
+ // -- if the type from the argument template was an lvalue reference
+ // and the type from the parameter template was not, the argument
+ // type is considered to be more specialized than the other;
+ // otherwise,
+ if (!RefParamComparisons[I].ArgIsRvalueRef &&
+ RefParamComparisons[I].ParamIsRvalueRef) {
+ Better2 = true;
+ if (Better1)
+ return 0;
+ continue;
+ } else if (!RefParamComparisons[I].ParamIsRvalueRef &&
+ RefParamComparisons[I].ArgIsRvalueRef) {
+ Better1 = true;
+ if (Better2)
+ return 0;
+ continue;
+ }
+
+ // -- if the type from the argument template is more cv-qualified than
+ // the type from the parameter template (as described above), the
+ // argument type is considered to be more specialized than the
+ // other; otherwise,
+ switch (RefParamComparisons[I].Qualifiers) {
+ case NeitherMoreQualified:
+ break;
+
+ case ParamMoreQualified:
+ Better1 = true;
+ if (Better2)
+ return 0;
+ continue;
+
+ case ArgMoreQualified:
+ Better2 = true;
+ if (Better1)
+ return 0;
+ continue;
+ }
+
+ // -- neither type is more specialized than the other.
+ }
+
+ assert(!(Better1 && Better2) && "Should have broken out in the loop above");
+ if (Better1)
+ return FT1;
+ else if (Better2)
+ return FT2;
+
+ // FIXME: This mimics what GCC implements, but doesn't match up with the
+ // proposed resolution for core issue 692. This area needs to be sorted out,
+ // but for now we attempt to maintain compatibility.
+ bool Variadic1 = isVariadicFunctionTemplate(FT1);
+ bool Variadic2 = isVariadicFunctionTemplate(FT2);
+ if (Variadic1 != Variadic2)
+ return Variadic1? FT2 : FT1;
+
+ return 0;
+}
+
+/// \brief Determine if the two templates are equivalent.
+static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
+ if (T1 == T2)
+ return true;
+
+ if (!T1 || !T2)
+ return false;
+
+ return T1->getCanonicalDecl() == T2->getCanonicalDecl();
+}
+
+/// \brief Retrieve the most specialized of the given function template
+/// specializations.
+///
+/// \param SpecBegin the start iterator of the function template
+/// specializations that we will be comparing.
+///
+/// \param SpecEnd the end iterator of the function template
+/// specializations, paired with \p SpecBegin.
+///
+/// \param TPOC the partial ordering context to use to compare the function
+/// template specializations.
+///
+/// \param NumCallArguments The number of arguments in a call, used only
+/// when \c TPOC is \c TPOC_Call.
+///
+/// \param Loc the location where the ambiguity or no-specializations
+/// diagnostic should occur.
+///
+/// \param NoneDiag partial diagnostic used to diagnose cases where there are
+/// no matching candidates.
+///
+/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one
+/// occurs.
+///
+/// \param CandidateDiag partial diagnostic used for each function template
+/// specialization that is a candidate in the ambiguous ordering. One parameter
+/// in this diagnostic should be unbound, which will correspond to the string
+/// describing the template arguments for the function template specialization.
+///
+/// \param Index if non-NULL and the result of this function is non-nULL,
+/// receives the index corresponding to the resulting function template
+/// specialization.
+///
+/// \returns the most specialized function template specialization, if
+/// found. Otherwise, returns SpecEnd.
+///
+/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
+/// template argument deduction.
+UnresolvedSetIterator
+Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
+ UnresolvedSetIterator SpecEnd,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain) {
+ if (SpecBegin == SpecEnd) {
+ if (Complain)
+ Diag(Loc, NoneDiag);
+ return SpecEnd;
+ }
+
+ if (SpecBegin + 1 == SpecEnd)
+ return SpecBegin;
+
+ // Find the function template that is better than all of the templates it
+ // has been compared to.
+ UnresolvedSetIterator Best = SpecBegin;
+ FunctionTemplateDecl *BestTemplate
+ = cast<FunctionDecl>(*Best)->getPrimaryTemplate();
+ assert(BestTemplate && "Not a function template specialization?");
+ for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
+ FunctionTemplateDecl *Challenger
+ = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+ assert(Challenger && "Not a function template specialization?");
+ if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC, NumCallArguments),
+ Challenger)) {
+ Best = I;
+ BestTemplate = Challenger;
+ }
+ }
+
+ // Make sure that the "best" function template is more specialized than all
+ // of the others.
+ bool Ambiguous = false;
+ for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+ FunctionTemplateDecl *Challenger
+ = cast<FunctionDecl>(*I)->getPrimaryTemplate();
+ if (I != Best &&
+ !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC, NumCallArguments),
+ BestTemplate)) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ if (!Ambiguous) {
+ // We found an answer. Return it.
+ return Best;
+ }
+
+ // Diagnose the ambiguity.
+ if (Complain)
+ Diag(Loc, AmbigDiag);
+
+ if (Complain)
+ // FIXME: Can we order the candidates in some sane way?
+ for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+ Diag((*I)->getLocation(), CandidateDiag)
+ << getTemplateArgumentBindingsText(
+ cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+ *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
+
+ return SpecEnd;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc) {
+ // C++ [temp.class.order]p1:
+ // For two class template partial specializations, the first is at least as
+ // specialized as the second if, given the following rewrite to two
+ // function templates, the first function template is at least as
+ // specialized as the second according to the ordering rules for function
+ // templates (14.6.6.2):
+ // - the first function template has the same template parameters as the
+ // first partial specialization and has a single function parameter
+ // whose type is a class template specialization with the template
+ // arguments of the first partial specialization, and
+ // - the second function template has the same template parameters as the
+ // second partial specialization and has a single function parameter
+ // whose type is a class template specialization with the template
+ // arguments of the second partial specialization.
+ //
+ // Rather than synthesize function templates, we merely perform the
+ // equivalent partial ordering by performing deduction directly on
+ // the template arguments of the class template partial
+ // specializations. This computation is slightly simpler than the
+ // general problem of function template partial ordering, because
+ // class template partial specializations are more constrained. We
+ // know that every template parameter is deducible from the class
+ // template partial specialization's template arguments, for
+ // example.
+ llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
+ TemplateDeductionInfo Info(Context, Loc);
+
+ QualType PT1 = PS1->getInjectedSpecializationType();
+ QualType PT2 = PS2->getInjectedSpecializationType();
+
+ // Determine whether PS1 is at least as specialized as PS2
+ Deduced.resize(PS2->getTemplateParameters()->size());
+ bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(),
+ PT2, PT1, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better1) {
+ InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
+ Deduced.data(), Deduced.size(), Info);
+ Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
+ PS1->getTemplateArgs(),
+ Deduced, Info);
+ }
+
+ // Determine whether PS2 is at least as specialized as PS1
+ Deduced.clear();
+ Deduced.resize(PS1->getTemplateParameters()->size());
+ bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(),
+ PT1, PT2, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true,
+ /*RefParamComparisons=*/0);
+ if (Better2) {
+ InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
+ Deduced.data(), Deduced.size(), Info);
+ Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
+ PS2->getTemplateArgs(),
+ Deduced, Info);
+ }
+
+ if (Better1 == Better2)
+ return 0;
+
+ return Better1? PS1 : PS2;
+}
+
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used);
+
+/// \brief Mark the template parameters that are used by the given
+/// expression.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const Expr *E,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ // We can deduce from a pack expansion.
+ if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
+ E = Expansion->getPattern();
+
+ // Skip through any implicit casts we added while type-checking.
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+ E = ICE->getSubExpr();
+
+ // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
+ // find other occurrences of template parameters.
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!DRE)
+ return;
+
+ const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ if (!NTTP)
+ return;
+
+ if (NTTP->getDepth() == Depth)
+ Used[NTTP->getIndex()] = true;
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// nested name specifier.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ NestedNameSpecifier *NNS,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (!NNS)
+ return;
+
+ MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth,
+ Used);
+ MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0),
+ OnlyDeduced, Depth, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// template name.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ TemplateName Name,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ }
+ return;
+ }
+
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+ MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced,
+ Depth, Used);
+ if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
+ MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced,
+ Depth, Used);
+}
+
+/// \brief Mark the template parameters that are used by the given
+/// type.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ if (T.isNull())
+ return;
+
+ // Non-dependent types have nothing deducible
+ if (!T->isDependentType())
+ return;
+
+ T = SemaRef.Context.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::Pointer:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<PointerType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Depth,
+ Used);
+ break;
+
+ case Type::BlockPointer:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<BlockPointerType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Depth,
+ Used);
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ReferenceType>(T)->getPointeeType(),
+ OnlyDeduced,
+ Depth,
+ Used);
+ break;
+
+ case Type::MemberPointer: {
+ const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
+ MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced,
+ Depth, Used);
+ MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0),
+ OnlyDeduced, Depth, Used);
+ break;
+ }
+
+ case Type::DependentSizedArray:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<DependentSizedArrayType>(T)->getSizeExpr(),
+ OnlyDeduced, Depth, Used);
+ // Fall through to check the element type
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ArrayType>(T)->getElementType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::Vector:
+ case Type::ExtVector:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<VectorType>(T)->getElementType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::DependentSizedExtVector: {
+ const DependentSizedExtVectorType *VecType
+ = cast<DependentSizedExtVectorType>(T);
+ MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced,
+ Depth, Used);
+ MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced,
+ Depth, Used);
+ break;
+ }
+
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced,
+ Depth, Used);
+ for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
+ MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced,
+ Depth, Used);
+ break;
+ }
+
+ case Type::TemplateTypeParm: {
+ const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T);
+ if (TTP->getDepth() == Depth)
+ Used[TTP->getIndex()] = true;
+ break;
+ }
+
+ case Type::SubstTemplateTypeParmPack: {
+ const SubstTemplateTypeParmPackType *Subst
+ = cast<SubstTemplateTypeParmPackType>(T);
+ MarkUsedTemplateParameters(SemaRef,
+ QualType(Subst->getReplacedParameter(), 0),
+ OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(SemaRef, Subst->getArgumentPack(),
+ OnlyDeduced, Depth, Used);
+ break;
+ }
+
+ case Type::InjectedClassName:
+ T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+ // fall through
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *Spec
+ = cast<TemplateSpecializationType>(T);
+ MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced,
+ Depth, Used);
+
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ break;
+
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
+
+ case Type::Complex:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<ComplexType>(T)->getElementType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::DependentName:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<DependentNameType>(T)->getQualifier(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *Spec
+ = cast<DependentTemplateSpecializationType>(T);
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(),
+ OnlyDeduced, Depth, Used);
+
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ break;
+
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
+
+ case Type::TypeOf:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<TypeOfType>(T)->getUnderlyingType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::TypeOfExpr:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<TypeOfExprType>(T)->getUnderlyingExpr(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::Decltype:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<DecltypeType>(T)->getUnderlyingExpr(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::PackExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<PackExpansionType>(T)->getPattern(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case Type::Auto:
+ MarkUsedTemplateParameters(SemaRef,
+ cast<AutoType>(T)->getDeducedType(),
+ OnlyDeduced, Depth, Used);
+
+ // None of these types have any template parameters in them.
+ case Type::Builtin:
+ case Type::VariableArray:
+ case Type::FunctionNoProto:
+ case Type::Record:
+ case Type::Enum:
+ case Type::ObjCInterface:
+ case Type::ObjCObject:
+ case Type::ObjCObjectPointer:
+ case Type::UnresolvedUsing:
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ break;
+ }
+}
+
+/// \brief Mark the template parameters that are used by this
+/// template argument.
+static void
+MarkUsedTemplateParameters(Sema &SemaRef,
+ const TemplateArgument &TemplateArg,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ switch (TemplateArg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ break;
+
+ case TemplateArgument::Type:
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced,
+ Depth, Used);
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ TemplateArg.getAsTemplateOrTemplatePattern(),
+ OnlyDeduced, Depth, Used);
+ break;
+
+ case TemplateArgument::Expression:
+ MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced,
+ Depth, Used);
+ break;
+
+ case TemplateArgument::Pack:
+ for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(),
+ PEnd = TemplateArg.pack_end();
+ P != PEnd; ++P)
+ MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used);
+ break;
+ }
+}
+
+/// \brief Mark the template parameters can be deduced by the given
+/// template argument list.
+///
+/// \param TemplateArgs the template argument list from which template
+/// parameters will be deduced.
+///
+/// \param Deduced a bit vector whose elements will be set to \c true
+/// to indicate when the corresponding template parameter will be
+/// deduced.
+void
+Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ bool OnlyDeduced, unsigned Depth,
+ llvm::SmallVectorImpl<bool> &Used) {
+ // C++0x [temp.deduct.type]p9:
+ // If the template argument list of P contains a pack expansion that is not
+ // the last template argument, the entire template argument list is a
+ // non-deduced context.
+ if (OnlyDeduced &&
+ hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
+ return;
+
+ for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
+ ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced,
+ Depth, Used);
+}
+
+/// \brief Marks all of the template parameters that will be deduced by a
+/// call to the given function template.
+void
+Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ Deduced.clear();
+ Deduced.resize(TemplateParams->size());
+
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I)
+ ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(),
+ true, TemplateParams->getDepth(), Deduced);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
new file mode 100644
index 0000000..44f5913
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -0,0 +1,2263 @@
+//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements C++ template instantiation.
+//
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/SemaInternal.h"
+#include "TreeTransform.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+using namespace sema;
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation Support
+//===----------------------------------------------------------------------===/
+
+/// \brief Retrieve the template argument list(s) that should be used to
+/// instantiate the definition of the given declaration.
+///
+/// \param D the declaration for which we are computing template instantiation
+/// arguments.
+///
+/// \param Innermost if non-NULL, the innermost template argument list.
+///
+/// \param RelativeToPrimary true if we should get the template
+/// arguments relative to the primary template, even when we're
+/// dealing with a specialization. This is only relevant for function
+/// template specializations.
+///
+/// \param Pattern If non-NULL, indicates the pattern from which we will be
+/// instantiating the definition of the given declaration, \p D. This is
+/// used to determine the proper set of template instantiation arguments for
+/// friend function template specializations.
+MultiLevelTemplateArgumentList
+Sema::getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost,
+ bool RelativeToPrimary,
+ const FunctionDecl *Pattern) {
+ // Accumulate the set of template argument lists in this structure.
+ MultiLevelTemplateArgumentList Result;
+
+ if (Innermost)
+ Result.addOuterTemplateArguments(Innermost);
+
+ DeclContext *Ctx = dyn_cast<DeclContext>(D);
+ if (!Ctx)
+ Ctx = D->getDeclContext();
+
+ while (!Ctx->isFileContext()) {
+ // Add template arguments from a class template instantiation.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+ // We're done when we hit an explicit specialization.
+ if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(Spec))
+ break;
+
+ Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+
+ // If this class template specialization was instantiated from a
+ // specialized member that is a class template, we're done.
+ assert(Spec->getSpecializedTemplate() && "No class template?");
+ if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+ break;
+ }
+ // Add template arguments from a function template specialization.
+ else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
+ if (!RelativeToPrimary &&
+ Function->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ break;
+
+ if (const TemplateArgumentList *TemplateArgs
+ = Function->getTemplateSpecializationArgs()) {
+ // Add the template arguments for this specialization.
+ Result.addOuterTemplateArguments(TemplateArgs);
+
+ // If this function was instantiated from a specialized member that is
+ // a function template, we're done.
+ assert(Function->getPrimaryTemplate() && "No function template?");
+ if (Function->getPrimaryTemplate()->isMemberSpecialization())
+ break;
+ }
+
+ // If this is a friend declaration and it declares an entity at
+ // namespace scope, take arguments from its lexical parent
+ // instead of its semantic parent, unless of course the pattern we're
+ // instantiating actually comes from the file's context!
+ if (Function->getFriendObjectKind() &&
+ Function->getDeclContext()->isFileContext() &&
+ (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
+ Ctx = Function->getLexicalDeclContext();
+ RelativeToPrimary = false;
+ continue;
+ }
+ } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
+ QualType T = ClassTemplate->getInjectedClassNameSpecialization();
+ const TemplateSpecializationType *TST
+ = cast<TemplateSpecializationType>(Context.getCanonicalType(T));
+ Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
+ if (ClassTemplate->isMemberSpecialization())
+ break;
+ }
+ }
+
+ Ctx = Ctx->getParent();
+ RelativeToPrimary = false;
+ }
+
+ return Result;
+}
+
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+ switch (Kind) {
+ case TemplateInstantiation:
+ case DefaultTemplateArgumentInstantiation:
+ case DefaultFunctionArgumentInstantiation:
+ return true;
+
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ return false;
+ }
+
+ return true;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ Decl *Entity,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.TemplateArgs = 0;
+ Inst.NumTemplateArgs = 0;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind
+ = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = Kind;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.DeductionInfo = &DeductionInfo;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ if (!Inst.isInstantiationRecord())
+ ++SemaRef.NonInstantiationEntries;
+ }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
+ ClassTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.DeductionInfo = &DeductionInfo;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
+ ParmVarDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind
+ = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = false;
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+void Sema::InstantiatingTemplate::Clear() {
+ if (!Invalid) {
+ if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+ assert(SemaRef.NonInstantiationEntries > 0);
+ --SemaRef.NonInstantiationEntries;
+ }
+ SemaRef.InNonInstantiationSFINAEContext
+ = SavedInNonInstantiationSFINAEContext;
+ SemaRef.ActiveTemplateInstantiations.pop_back();
+ Invalid = true;
+ }
+}
+
+bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
+ SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange) {
+ assert(SemaRef.NonInstantiationEntries <=
+ SemaRef.ActiveTemplateInstantiations.size());
+ if ((SemaRef.ActiveTemplateInstantiations.size() -
+ SemaRef.NonInstantiationEntries)
+ <= SemaRef.getLangOptions().InstantiationDepth)
+ return false;
+
+ SemaRef.Diag(PointOfInstantiation,
+ diag::err_template_recursion_depth_exceeded)
+ << SemaRef.getLangOptions().InstantiationDepth
+ << InstantiationRange;
+ SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+ << SemaRef.getLangOptions().InstantiationDepth;
+ return true;
+}
+
+/// \brief Prints the current instantiation stack through a series of
+/// notes.
+void Sema::PrintInstantiationStack() {
+ // Determine which template instantiations to skip, if any.
+ unsigned SkipStart = ActiveTemplateInstantiations.size(), SkipEnd = SkipStart;
+ unsigned Limit = Diags.getTemplateBacktraceLimit();
+ if (Limit && Limit < ActiveTemplateInstantiations.size()) {
+ SkipStart = Limit / 2 + Limit % 2;
+ SkipEnd = ActiveTemplateInstantiations.size() - Limit / 2;
+ }
+
+ // FIXME: In all of these cases, we need to show the template arguments
+ unsigned InstantiationIdx = 0;
+ for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
+ Active = ActiveTemplateInstantiations.rbegin(),
+ ActiveEnd = ActiveTemplateInstantiations.rend();
+ Active != ActiveEnd;
+ ++Active, ++InstantiationIdx) {
+ // Skip this instantiation?
+ if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
+ if (InstantiationIdx == SkipStart) {
+ // Note that we're skipping instantiations.
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_instantiation_contexts_suppressed)
+ << unsigned(ActiveTemplateInstantiations.size() - Limit);
+ }
+ continue;
+ }
+
+ switch (Active->Kind) {
+ case ActiveTemplateInstantiation::TemplateInstantiation: {
+ Decl *D = reinterpret_cast<Decl *>(Active->Entity);
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+ unsigned DiagID = diag::note_template_member_class_here;
+ if (isa<ClassTemplateSpecializationDecl>(Record))
+ DiagID = diag::note_template_class_instantiation_here;
+ Diags.Report(Active->PointOfInstantiation, DiagID)
+ << Context.getTypeDeclType(Record)
+ << Active->InstantiationRange;
+ } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ unsigned DiagID;
+ if (Function->getPrimaryTemplate())
+ DiagID = diag::note_function_template_spec_here;
+ else
+ DiagID = diag::note_template_member_function_here;
+ Diags.Report(Active->PointOfInstantiation, DiagID)
+ << Function
+ << Active->InstantiationRange;
+ } else {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_static_data_member_def_here)
+ << cast<VarDecl>(D)
+ << Active->InstantiationRange;
+ }
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
+ TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ Active->TemplateArgs,
+ Active->NumTemplateArgs,
+ Context.PrintingPolicy);
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_default_arg_instantiation_here)
+ << (Template->getNameAsString() + TemplateArgsStr)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
+ FunctionTemplateDecl *FnTmpl
+ = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_explicit_template_arg_substitution_here)
+ << FnTmpl
+ << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+ (Decl *)Active->Entity)) {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_partial_spec_deduct_instantiation_here)
+ << Context.getTypeDeclType(PartialSpec)
+ << getTemplateArgumentBindingsText(
+ PartialSpec->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ } else {
+ FunctionTemplateDecl *FnTmpl
+ = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_function_template_deduction_instantiation_here)
+ << FnTmpl
+ << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ }
+ break;
+
+ case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: {
+ ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity);
+ FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
+
+ std::string TemplateArgsStr
+ = TemplateSpecializationType::PrintTemplateArgumentList(
+ Active->TemplateArgs,
+ Active->NumTemplateArgs,
+ Context.PrintingPolicy);
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_default_function_arg_instantiation_here)
+ << (FD->getNameAsString() + TemplateArgsStr)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
+ NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+ std::string Name;
+ if (!Parm->getName().empty())
+ Name = std::string(" '") + Parm->getName().str() + "'";
+
+ TemplateParameterList *TemplateParams = 0;
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+ TemplateParams = Template->getTemplateParameters();
+ else
+ TemplateParams =
+ cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+ ->getTemplateParameters();
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_prior_template_arg_substitution)
+ << isa<TemplateTemplateParmDecl>(Parm)
+ << Name
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+ TemplateParameterList *TemplateParams = 0;
+ if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+ TemplateParams = Template->getTemplateParameters();
+ else
+ TemplateParams =
+ cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+ ->getTemplateParameters();
+
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_default_arg_checking)
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
+ }
+ }
+}
+
+llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
+ using llvm::SmallVector;
+ if (InNonInstantiationSFINAEContext)
+ return llvm::Optional<TemplateDeductionInfo *>(0);
+
+ for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
+ Active = ActiveTemplateInstantiations.rbegin(),
+ ActiveEnd = ActiveTemplateInstantiations.rend();
+ Active != ActiveEnd;
+ ++Active)
+ {
+ switch(Active->Kind) {
+ case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
+ case ActiveTemplateInstantiation::TemplateInstantiation:
+ // This is a template instantiation, so there is no SFINAE.
+ return llvm::Optional<TemplateDeductionInfo *>();
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
+ // A default template argument instantiation and substitution into
+ // template parameters with arguments for prior parameters may or may
+ // not be a SFINAE context; look further up the stack.
+ break;
+
+ case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
+ case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+ // We're either substitution explicitly-specified template arguments
+ // or deduced template arguments, so SFINAE applies.
+ assert(Active->DeductionInfo && "Missing deduction info pointer");
+ return Active->DeductionInfo;
+ }
+ }
+
+ return llvm::Optional<TemplateDeductionInfo *>();
+}
+
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation for Types
+//===----------------------------------------------------------------------===/
+namespace {
+ class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+ SourceLocation Loc;
+ DeclarationName Entity;
+
+ public:
+ typedef TreeTransform<TemplateInstantiator> inherited;
+
+ TemplateInstantiator(Sema &SemaRef,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity)
+ : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+ Entity(Entity) { }
+
+ /// \brief Determine whether the given type \p T has already been
+ /// transformed.
+ ///
+ /// For the purposes of template instantiation, a type has already been
+ /// transformed if it is NULL or if it is not dependent.
+ bool AlreadyTransformed(QualType T);
+
+ /// \brief Returns the location of the entity being instantiated, if known.
+ SourceLocation getBaseLocation() { return Loc; }
+
+ /// \brief Returns the name of the entity being instantiated, if any.
+ DeclarationName getBaseEntity() { return Entity; }
+
+ /// \brief Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) {
+ this->Loc = Loc;
+ this->Entity = Entity;
+ }
+
+ bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ llvm::Optional<unsigned> &NumExpansions) {
+ return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
+ PatternRange, Unexpanded,
+ NumUnexpanded,
+ TemplateArgs,
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions);
+ }
+
+ void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+ }
+
+ TemplateArgument ForgetPartiallySubstitutedPack() {
+ TemplateArgument Result;
+ if (NamedDecl *PartialPack
+ = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+ MultiLevelTemplateArgumentList &TemplateArgs
+ = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ Result = TemplateArgs(Depth, Index);
+ TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+ }
+ }
+
+ return Result;
+ }
+
+ void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+ if (Arg.isNull())
+ return;
+
+ if (NamedDecl *PartialPack
+ = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+ MultiLevelTemplateArgumentList &TemplateArgs
+ = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ TemplateArgs.setArgument(Depth, Index, Arg);
+ }
+ }
+
+ /// \brief Transform the given declaration by instantiating a reference to
+ /// this declaration.
+ Decl *TransformDecl(SourceLocation Loc, Decl *D);
+
+ /// \brief Transform the definition of the given declaration by
+ /// instantiating it.
+ Decl *TransformDefinition(SourceLocation Loc, Decl *D);
+
+ /// \bried Transform the first qualifier within a scope by instantiating the
+ /// declaration.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
+
+ /// \brief Rebuild the exception declaration and register the declaration
+ /// as an instantiated local.
+ VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *Declarator,
+ IdentifierInfo *Name,
+ SourceLocation Loc);
+
+ /// \brief Rebuild the Objective-C exception declaration and register the
+ /// declaration as an instantiated local.
+ VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *TSInfo, QualType T);
+
+ /// \brief Check for tag mismatches when instantiating an
+ /// elaborated type.
+ QualType RebuildElaboratedType(SourceLocation KeywordLoc,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, QualType T);
+
+ TemplateName TransformTemplateName(TemplateName Name,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
+
+ ExprResult TransformPredefinedExpr(PredefinedExpr *E);
+ ExprResult TransformDeclRefExpr(DeclRefExpr *E);
+ ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+ NonTypeTemplateParmDecl *D);
+ ExprResult TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
+
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL);
+ ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ llvm::Optional<unsigned> NumExpansions);
+
+ /// \brief Transforms a template type parameter type by performing
+ /// substitution of the corresponding template type argument.
+ QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL);
+
+ /// \brief Transforms an already-substituted template type parameter pack
+ /// into either itself (if we aren't substituting into its pack expansion)
+ /// or the appropriate substituted argument.
+ QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL);
+
+ ExprResult TransformCallExpr(CallExpr *CE) {
+ getSema().CallsUndergoingInstantiation.push_back(CE);
+ ExprResult Result =
+ TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
+ getSema().CallsUndergoingInstantiation.pop_back();
+ return move(Result);
+ }
+ };
+}
+
+bool TemplateInstantiator::AlreadyTransformed(QualType T) {
+ if (T.isNull())
+ return true;
+
+ if (T->isDependentType() || T->isVariablyModifiedType())
+ return false;
+
+ getSema().MarkDeclarationsReferencedInType(Loc, T);
+ return true;
+}
+
+Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
+ if (!D)
+ return 0;
+
+ if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return D;
+
+ TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+
+ if (TTP->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ assert(getSema().ArgumentPackSubstitutionIndex >= 0);
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ TemplateName Template = Arg.getAsTemplate();
+ assert(!Template.isNull() && Template.getAsTemplateDecl() &&
+ "Wrong kind of template template argument");
+ return Template.getAsTemplateDecl();
+ }
+
+ // Fall through to find the instantiated declaration for this template
+ // template parameter.
+ }
+
+ return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
+}
+
+Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
+ Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
+ if (!Inst)
+ return 0;
+
+ getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+ return Inst;
+}
+
+NamedDecl *
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
+ SourceLocation Loc) {
+ // If the first part of the nested-name-specifier was a template type
+ // parameter, instantiate that type parameter down to a tag type.
+ if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
+ const TemplateTypeParmType *TTP
+ = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
+
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // FIXME: This needs testing w/ member access expressions.
+ TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());
+
+ if (TTP->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ if (getSema().ArgumentPackSubstitutionIndex == -1)
+ return 0;
+
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ QualType T = Arg.getAsType();
+ if (T.isNull())
+ return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
+
+ if (const TagType *Tag = T->getAs<TagType>())
+ return Tag->getDecl();
+
+ // The resulting type is not a tag; complain.
+ getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
+ return 0;
+ }
+ }
+
+ return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
+}
+
+VarDecl *
+TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *Declarator,
+ IdentifierInfo *Name,
+ SourceLocation Loc) {
+ VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
+ Name, Loc);
+ if (Var)
+ getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
+ return Var;
+}
+
+VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *TSInfo,
+ QualType T) {
+ VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
+ if (Var)
+ getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
+ return Var;
+}
+
+QualType
+TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ QualType T) {
+ if (const TagType *TT = T->getAs<TagType>()) {
+ TagDecl* TD = TT->getDecl();
+
+ SourceLocation TagLocation = KeywordLoc;
+
+ // FIXME: type might be anonymous.
+ IdentifierInfo *Id = TD->getIdentifier();
+
+ // TODO: should we even warn on struct/class mismatches for this? Seems
+ // like it's likely to produce a lot of spurious errors.
+ if (Keyword != ETK_None && Keyword != ETK_Typename) {
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
+ if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, TagLocation, *Id)) {
+ SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
+ << Id
+ << FixItHint::CreateReplacement(SourceRange(TagLocation),
+ TD->getKindName());
+ SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
+ }
+ }
+ }
+
+ return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc,
+ Keyword,
+ NNS, T);
+}
+
+TemplateName TemplateInstantiator::TransformTemplateName(TemplateName Name,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return Name;
+
+ TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
+
+ if (TTP->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We have the template argument pack to substitute, but we're not
+ // actually expanding the enclosing pack expansion yet. So, just
+ // keep the entire argument pack.
+ return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
+ }
+
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ TemplateName Template = Arg.getAsTemplate();
+ assert(!Template.isNull() && Template.getAsTemplateDecl() &&
+ "Wrong kind of template template argument");
+ return Template;
+ }
+ }
+
+ if (SubstTemplateTemplateParmPackStorage *SubstPack
+ = Name.getAsSubstTemplateTemplateParmPack()) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1)
+ return Name;
+
+ const TemplateArgument &ArgPack = SubstPack->getArgumentPack();
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() &&
+ "Pack substitution index out-of-range");
+ return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex]
+ .getAsTemplate();
+ }
+
+ return inherited::TransformTemplateName(Name, ObjectType,
+ FirstQualifierInScope);
+}
+
+ExprResult
+TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
+ if (!E->isTypeDependent())
+ return SemaRef.Owned(E);
+
+ FunctionDecl *currentDecl = getSema().getCurFunctionDecl();
+ assert(currentDecl && "Must have current function declaration when "
+ "instantiating.");
+
+ PredefinedExpr::IdentType IT = E->getIdentType();
+
+ unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
+
+ llvm::APInt LengthI(32, Length + 1);
+ QualType ResTy = getSema().Context.CharTy.withConst();
+ ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI,
+ ArrayType::Normal, 0);
+ PredefinedExpr *PE =
+ new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT);
+ return getSema().Owned(PE);
+}
+
+ExprResult
+TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
+ NonTypeTemplateParmDecl *NTTP) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+ NTTP->getPosition()))
+ return SemaRef.Owned(E);
+
+ TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
+ if (NTTP->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We have an argument pack, but we can't select a particular argument
+ // out of it yet. Therefore, we'll build an expression to hold on to that
+ // argument pack.
+ QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+ E->getLocation(),
+ NTTP->getDeclName());
+ if (TargetType.isNull())
+ return ExprError();
+
+ return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType,
+ NTTP,
+ E->getLocation(),
+ Arg);
+ }
+
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ // The template argument itself might be an expression, in which
+ // case we just return that expression.
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr());
+
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ // Find the instantiation of the template argument. This is
+ // required for nested templates.
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(E->getLocation(),
+ VD, TemplateArgs));
+ if (!VD)
+ return ExprError();
+
+ // Derive the type we want the substituted decl to have. This had
+ // better be non-dependent, or these checks will have serious problems.
+ QualType TargetType;
+ if (NTTP->isExpandedParameterPack())
+ TargetType = NTTP->getExpansionType(
+ getSema().ArgumentPackSubstitutionIndex);
+ else if (NTTP->isParameterPack() &&
+ isa<PackExpansionType>(NTTP->getType())) {
+ TargetType = SemaRef.SubstType(
+ cast<PackExpansionType>(NTTP->getType())->getPattern(),
+ TemplateArgs, E->getLocation(),
+ NTTP->getDeclName());
+ } else
+ TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+ E->getLocation(), NTTP->getDeclName());
+ assert(!TargetType.isNull() && "type substitution failed for param type");
+ assert(!TargetType->isDependentType() && "param type still dependent");
+ return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
+ TargetType,
+ E->getLocation());
+ }
+
+ return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
+ E->getSourceRange().getBegin());
+}
+
+ExprResult
+TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We aren't expanding the parameter pack, so just return ourselves.
+ return getSema().Owned(E);
+ }
+
+ const TemplateArgument &ArgPack = E->getArgumentPack();
+ unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+ assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+
+ const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr());
+
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ // Find the instantiation of the template argument. This is
+ // required for nested templates.
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(E->getParameterPackLocation(),
+ VD, TemplateArgs));
+ if (!VD)
+ return ExprError();
+
+ QualType T;
+ NonTypeTemplateParmDecl *NTTP = E->getParameterPack();
+ if (NTTP->isExpandedParameterPack())
+ T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex);
+ else if (const PackExpansionType *Expansion
+ = dyn_cast<PackExpansionType>(NTTP->getType()))
+ T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs,
+ E->getParameterPackLocation(), NTTP->getDeclName());
+ else
+ T = E->getType();
+ return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T,
+ E->getParameterPackLocation());
+ }
+
+ return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
+ E->getParameterPackLocation());
+}
+
+ExprResult
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+ NamedDecl *D = E->getDecl();
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ if (NTTP->getDepth() < TemplateArgs.getNumLevels())
+ return TransformTemplateParmRefExpr(E, NTTP);
+
+ // We have a non-type template parameter that isn't fully substituted;
+ // FindInstantiatedDecl will find it in the local instantiation scope.
+ }
+
+ return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
+}
+
+ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+ CXXDefaultArgExpr *E) {
+ assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
+ getDescribedFunctionTemplate() &&
+ "Default arg expressions are never formed in dependent cases.");
+ return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
+ cast<FunctionDecl>(E->getParam()->getDeclContext()),
+ E->getParam());
+}
+
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL) {
+ // We need a local instantiation scope for this function prototype.
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return inherited::TransformFunctionProtoType(TLB, TL);
+}
+
+ParmVarDecl *
+TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ llvm::Optional<unsigned> NumExpansions) {
+ return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs,
+ NumExpansions);
+}
+
+QualType
+TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL) {
+ const TemplateTypeParmType *T = TL.getTypePtr();
+ if (T->getDepth() < TemplateArgs.getNumLevels()) {
+ // Replace the template type parameter with its corresponding
+ // template argument.
+
+ // If the corresponding template argument is NULL or doesn't exist, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template class, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
+ TemplateTypeParmTypeLoc NewTL
+ = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+ NewTL.setNameLoc(TL.getNameLoc());
+ return TL.getType();
+ }
+
+ TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
+
+ if (T->isParameterPack()) {
+ assert(Arg.getKind() == TemplateArgument::Pack &&
+ "Missing argument pack");
+
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We have the template argument pack, but we're not expanding the
+ // enclosing pack expansion yet. Just save the template argument
+ // pack for later substitution.
+ QualType Result
+ = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
+ SubstTemplateTypeParmPackTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+ }
+
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
+ Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
+ }
+
+ assert(Arg.getKind() == TemplateArgument::Type &&
+ "Template argument kind mismatch");
+
+ QualType Replacement = Arg.getAsType();
+
+ // TODO: only do this uniquing once, at the start of instantiation.
+ QualType Result
+ = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+ }
+
+ // The template type parameter comes from an inner template (e.g.,
+ // the template parameter list of a member template inside the
+ // template we are instantiating). Create a new template type
+ // parameter with the template "level" reduced by one.
+ QualType Result
+ = getSema().Context.getTemplateTypeParmType(T->getDepth()
+ - TemplateArgs.getNumLevels(),
+ T->getIndex(),
+ T->isParameterPack(),
+ T->getName());
+ TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+}
+
+QualType
+TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We aren't expanding the parameter pack, so just return ourselves.
+ SubstTemplateTypeParmPackTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
+ NewTL.setNameLoc(TL.getNameLoc());
+ return TL.getType();
+ }
+
+ const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack();
+ unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+ assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+
+ QualType Result = ArgPack.pack_begin()[Index].getAsType();
+ Result = getSema().Context.getSubstTemplateTypeParmType(
+ TL.getTypePtr()->getReplacedParameter(),
+ Result);
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+}
+
+/// \brief Perform substitution on the type T with a given set of template
+/// arguments.
+///
+/// This routine substitutes the given template arguments into the
+/// type T and produces the instantiated type.
+///
+/// \param T the type into which the template arguments will be
+/// substituted. If this type is not dependent, it will be returned
+/// immediately.
+///
+/// \param TemplateArgs the template arguments that will be
+/// substituted for the top-level template parameters within T.
+///
+/// \param Loc the location in the source code where this substitution
+/// is being performed. It will typically be the location of the
+/// declarator (if we're instantiating the type of some declaration)
+/// or the location of the type in the source code (if, e.g., we're
+/// instantiating the type of a cast expression).
+///
+/// \param Entity the name of the entity associated with a declaration
+/// being instantiated (if any). May be empty to indicate that there
+/// is no such entity (if, e.g., this is a type that occurs as part of
+/// a cast expression) or that the entity has no name (e.g., an
+/// unnamed function parameter).
+///
+/// \returns If the instantiation succeeds, the instantiated
+/// type. Otherwise, produces diagnostics and returns a NULL type.
+TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &Args,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ if (!T->getType()->isDependentType() &&
+ !T->getType()->isVariablyModifiedType())
+ return T;
+
+ TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+ return Instantiator.TransformType(T);
+}
+
+TypeSourceInfo *Sema::SubstType(TypeLoc TL,
+ const MultiLevelTemplateArgumentList &Args,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ if (TL.getType().isNull())
+ return 0;
+
+ if (!TL.getType()->isDependentType() &&
+ !TL.getType()->isVariablyModifiedType()) {
+ // FIXME: Make a copy of the TypeLoc data here, so that we can
+ // return a new TypeSourceInfo. Inefficient!
+ TypeLocBuilder TLB;
+ TLB.pushFullCopy(TL);
+ return TLB.getTypeSourceInfo(Context, TL.getType());
+ }
+
+ TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+ TypeLocBuilder TLB;
+ TLB.reserve(TL.getFullDataSize());
+ QualType Result = Instantiator.TransformType(TLB, TL);
+ if (Result.isNull())
+ return 0;
+
+ return TLB.getTypeSourceInfo(Context, Result);
+}
+
+/// Deprecated form of the above.
+QualType Sema::SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ // If T is not a dependent type or a variably-modified type, there
+ // is nothing to do.
+ if (!T->isDependentType() && !T->isVariablyModifiedType())
+ return T;
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
+ return Instantiator.TransformType(T);
+}
+
+static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
+ if (T->getType()->isDependentType() || T->getType()->isVariablyModifiedType())
+ return true;
+
+ TypeLoc TL = T->getTypeLoc().IgnoreParens();
+ if (!isa<FunctionProtoTypeLoc>(TL))
+ return false;
+
+ FunctionProtoTypeLoc FP = cast<FunctionProtoTypeLoc>(TL);
+ for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) {
+ ParmVarDecl *P = FP.getArg(I);
+
+ // TODO: currently we always rebuild expressions. When we
+ // properly get lazier about this, we should use the same
+ // logic to avoid rebuilding prototypes here.
+ if (P->hasDefaultArg())
+ return true;
+ }
+
+ return false;
+}
+
+/// A form of SubstType intended specifically for instantiating the
+/// type of a FunctionDecl. Its purpose is solely to force the
+/// instantiation of default-argument expressions.
+TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &Args,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ if (!NeedsInstantiationAsFunctionType(T))
+ return T;
+
+ TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+
+ TypeLocBuilder TLB;
+
+ TypeLoc TL = T->getTypeLoc();
+ TLB.reserve(TL.getFullDataSize());
+
+ QualType Result = Instantiator.TransformType(TLB, TL);
+ if (Result.isNull())
+ return 0;
+
+ return TLB.getTypeSourceInfo(Context, Result);
+}
+
+ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::Optional<unsigned> NumExpansions) {
+ TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
+ TypeSourceInfo *NewDI = 0;
+
+ TypeLoc OldTL = OldDI->getTypeLoc();
+ if (isa<PackExpansionTypeLoc>(OldTL)) {
+ PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+
+ // We have a function parameter pack. Substitute into the pattern of the
+ // expansion.
+ NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
+ OldParm->getLocation(), OldParm->getDeclName());
+ if (!NewDI)
+ return 0;
+
+ if (NewDI->getType()->containsUnexpandedParameterPack()) {
+ // We still have unexpanded parameter packs, which means that
+ // our function parameter is still a function parameter pack.
+ // Therefore, make its type a pack expansion type.
+ NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
+ NumExpansions);
+ }
+ } else {
+ NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
+ OldParm->getDeclName());
+ }
+
+ if (!NewDI)
+ return 0;
+
+ if (NewDI->getType()->isVoidType()) {
+ Diag(OldParm->getLocation(), diag::err_param_with_void_type);
+ return 0;
+ }
+
+ ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
+ NewDI, NewDI->getType(),
+ OldParm->getIdentifier(),
+ OldParm->getLocation(),
+ OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten());
+ if (!NewParm)
+ return 0;
+
+ // Mark the (new) default argument as uninstantiated (if any).
+ if (OldParm->hasUninstantiatedDefaultArg()) {
+ Expr *Arg = OldParm->getUninstantiatedDefaultArg();
+ NewParm->setUninstantiatedDefaultArg(Arg);
+ } else if (OldParm->hasUnparsedDefaultArg()) {
+ NewParm->setUnparsedDefaultArg();
+ UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
+ } else if (Expr *Arg = OldParm->getDefaultArg())
+ NewParm->setUninstantiatedDefaultArg(Arg);
+
+ NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
+
+ // FIXME: When OldParm is a parameter pack and NewParm is not a parameter
+ // pack, we actually have a set of instantiated locations. Maintain this set!
+ if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
+ // Add the new parameter to
+ CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
+ } else {
+ // Introduce an Old -> New mapping
+ CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
+ }
+
+ // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
+ // can be anything, is this right ?
+ NewParm->setDeclContext(CurContext);
+
+ return NewParm;
+}
+
+/// \brief Substitute the given template arguments into the given set of
+/// parameters, producing the set of parameter types that would be generated
+/// from such a substitution.
+bool Sema::SubstParmTypes(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<QualType> &ParamTypes,
+ llvm::SmallVectorImpl<ParmVarDecl *> *OutParams) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+ DeclarationName());
+ return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0,
+ ParamTypes, OutParams);
+}
+
+/// \brief Perform substitution on the base class specifiers of the
+/// given class template specialization.
+///
+/// Produces a diagnostic and returns true on error, returns false and
+/// attaches the instantiated base classes to the class template
+/// specialization if successful.
+bool
+Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ bool Invalid = false;
+ llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
+ for (ClassTemplateSpecializationDecl::base_class_iterator
+ Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
+ Base != BaseEnd; ++Base) {
+ if (!Base->getType()->isDependentType()) {
+ InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base));
+ continue;
+ }
+
+ SourceLocation EllipsisLoc;
+ if (Base->isPackExpansion()) {
+ // This is a pack expansion. See whether we should expand it now, or
+ // wait until later.
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+ Unexpanded);
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions;
+ if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
+ Base->getSourceRange(),
+ Unexpanded.data(), Unexpanded.size(),
+ TemplateArgs, ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
+ Invalid = true;
+ continue;
+ }
+
+ // If we should expand this pack expansion now, do so.
+ if (ShouldExpand) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (!BaseTypeLoc) {
+ Invalid = true;
+ continue;
+ }
+
+ if (CXXBaseSpecifier *InstantiatedBase
+ = CheckBaseSpecifier(Instantiation,
+ Base->getSourceRange(),
+ Base->isVirtual(),
+ Base->getAccessSpecifierAsWritten(),
+ BaseTypeLoc,
+ SourceLocation()))
+ InstantiatedBases.push_back(InstantiatedBase);
+ else
+ Invalid = true;
+ }
+
+ continue;
+ }
+
+ // The resulting base specifier will (still) be a pack expansion.
+ EllipsisLoc = Base->getEllipsisLoc();
+ }
+
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (!BaseTypeLoc) {
+ Invalid = true;
+ continue;
+ }
+
+ if (CXXBaseSpecifier *InstantiatedBase
+ = CheckBaseSpecifier(Instantiation,
+ Base->getSourceRange(),
+ Base->isVirtual(),
+ Base->getAccessSpecifierAsWritten(),
+ BaseTypeLoc,
+ EllipsisLoc))
+ InstantiatedBases.push_back(InstantiatedBase);
+ else
+ Invalid = true;
+ }
+
+ if (!Invalid &&
+ AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
+ InstantiatedBases.size()))
+ Invalid = true;
+
+ return Invalid;
+}
+
+/// \brief Instantiate the definition of a class from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+///
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be either a class template specialization
+/// or a member class of a class template specialization.
+///
+/// \param Pattern is the pattern from which the instantiation
+/// occurs. This will be either the declaration of a class template or
+/// the declaration of a member class of a class template.
+///
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+///
+/// \param TSK the kind of implicit or explicit instantiation to perform.
+///
+/// \param Complain whether to complain if the class cannot be instantiated due
+/// to the lack of a definition.
+///
+/// \returns true if an error occurred, false otherwise.
+bool
+Sema::InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK,
+ bool Complain) {
+ bool Invalid = false;
+
+ CXXRecordDecl *PatternDef
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
+ if (!PatternDef) {
+ if (!Complain) {
+ // Say nothing
+ } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
+ Diag(PointOfInstantiation,
+ diag::err_implicit_instantiate_member_undefined)
+ << Context.getTypeDeclType(Instantiation);
+ Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+ } else {
+ Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
+ << (TSK != TSK_ImplicitInstantiation)
+ << Context.getTypeDeclType(Instantiation);
+ Diag(Pattern->getLocation(), diag::note_template_decl_here);
+ }
+ return true;
+ }
+ Pattern = PatternDef;
+
+ // \brief Record the point of instantiation.
+ if (MemberSpecializationInfo *MSInfo
+ = Instantiation->getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+ Spec->setTemplateSpecializationKind(TSK);
+ Spec->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+ if (Inst)
+ return true;
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ ContextRAII SavedContext(*this, Instantiation);
+ EnterExpressionEvaluationContext EvalContext(*this,
+ Sema::PotentiallyEvaluated);
+
+ // If this is an instantiation of a local class, merge this local
+ // instantiation scope with the enclosing scope. Otherwise, every
+ // instantiation of a class has its own local instantiation scope.
+ bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
+ LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+ // Pull attributes from the pattern onto the instantiation.
+ InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
+
+ // Start the definition of this instantiation.
+ Instantiation->startDefinition();
+
+ Instantiation->setTagKind(Pattern->getTagKind());
+
+ // Do substitution on the base class specifiers.
+ if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
+ Invalid = true;
+
+ TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
+ llvm::SmallVector<Decl*, 4> Fields;
+ for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
+ MemberEnd = Pattern->decls_end();
+ Member != MemberEnd; ++Member) {
+ // Don't instantiate members not belonging in this semantic context.
+ // e.g. for:
+ // @code
+ // template <int i> class A {
+ // class B *g;
+ // };
+ // @endcode
+ // 'class B' has the template as lexical context but semantically it is
+ // introduced in namespace scope.
+ if ((*Member)->getDeclContext() != Pattern)
+ continue;
+
+ if ((*Member)->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
+ Decl *NewMember = Instantiator.Visit(*Member);
+ if (NewMember) {
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+ Fields.push_back(Field);
+ else if (NewMember->isInvalidDecl())
+ Invalid = true;
+ } else {
+ // FIXME: Eventually, a NULL return will mean that one of the
+ // instantiations was a semantic disaster, and we'll want to set Invalid =
+ // true. For now, we expect to skip some members that we can't yet handle.
+ }
+ }
+
+ // Finish checking fields.
+ ActOnFields(0, Instantiation->getLocation(), Instantiation,
+ Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
+ 0);
+ CheckCompletedCXXClass(Instantiation);
+ if (Instantiation->isInvalidDecl())
+ Invalid = true;
+ else {
+ // Instantiate any out-of-line class template partial
+ // specializations now.
+ for (TemplateDeclInstantiator::delayed_partial_spec_iterator
+ P = Instantiator.delayed_partial_spec_begin(),
+ PEnd = Instantiator.delayed_partial_spec_end();
+ P != PEnd; ++P) {
+ if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
+ P->first,
+ P->second)) {
+ Invalid = true;
+ break;
+ }
+ }
+ }
+
+ // Exit the scope of this instantiation.
+ SavedContext.pop();
+
+ if (!Invalid) {
+ Consumer.HandleTagDeclDefinition(Instantiation);
+
+ // Always emit the vtable for an explicit instantiation definition
+ // of a polymorphic class template specialization.
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ MarkVTableUsed(PointOfInstantiation, Instantiation, true);
+ }
+
+ return Invalid;
+}
+
+namespace {
+ /// \brief A partial specialization whose template arguments have matched
+ /// a given template-id.
+ struct PartialSpecMatchResult {
+ ClassTemplatePartialSpecializationDecl *Partial;
+ TemplateArgumentList *Args;
+ };
+}
+
+bool
+Sema::InstantiateClassTemplateSpecialization(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK,
+ bool Complain) {
+ // Perform the actual instantiation on the canonical declaration.
+ ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
+ ClassTemplateSpec->getCanonicalDecl());
+
+ // Check whether we have already instantiated or specialized this class
+ // template specialization.
+ if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) {
+ if (ClassTemplateSpec->getSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration &&
+ TSK == TSK_ExplicitInstantiationDefinition) {
+ // An explicit instantiation definition follows an explicit instantiation
+ // declaration (C++0x [temp.explicit]p10); go ahead and perform the
+ // explicit instantiation.
+ ClassTemplateSpec->setSpecializationKind(TSK);
+
+ // If this is an explicit instantiation definition, mark the
+ // vtable as used.
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
+
+ return false;
+ }
+
+ // We can only instantiate something that hasn't already been
+ // instantiated or specialized. Fail without any diagnostics: our
+ // caller will provide an error message.
+ return true;
+ }
+
+ if (ClassTemplateSpec->isInvalidDecl())
+ return true;
+
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+ CXXRecordDecl *Pattern = 0;
+
+ // C++ [temp.class.spec.match]p1:
+ // When a class template is used in a context that requires an
+ // instantiation of the class, it is necessary to determine
+ // whether the instantiation is to be generated using the primary
+ // template or one of the partial specializations. This is done by
+ // matching the template arguments of the class template
+ // specialization with the template argument lists of the partial
+ // specializations.
+ typedef PartialSpecMatchResult MatchResult;
+ llvm::SmallVector<MatchResult, 4> Matched;
+ llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ Template->getPartialSpecializations(PartialSpecs);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
+ TemplateDeductionInfo Info(Context, PointOfInstantiation);
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(Partial,
+ ClassTemplateSpec->getTemplateArgs(),
+ Info)) {
+ // FIXME: Store the failed-deduction information for use in
+ // diagnostics, later.
+ (void)Result;
+ } else {
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
+ }
+ }
+
+ // If we're dealing with a member template where the template parameters
+ // have been instantiated, this provides the original template parameters
+ // from which the member template's parameters were instantiated.
+ llvm::SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters;
+
+ if (Matched.size() >= 1) {
+ llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
+ if (Matched.size() == 1) {
+ // -- If exactly one matching specialization is found, the
+ // instantiation is generated from that specialization.
+ // We don't need to do anything for this.
+ } else {
+ // -- If more than one matching specialization is found, the
+ // partial order rules (14.5.4.2) are used to determine
+ // whether one of the specializations is more specialized
+ // than the others. If none of the specializations is more
+ // specialized than all of the other matching
+ // specializations, then the use of the class template is
+ // ambiguous and the program is ill-formed.
+ for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+ PointOfInstantiation)
+ == P->Partial)
+ Best = P;
+ }
+
+ // Determine if the best partial specialization is more specialized than
+ // the others.
+ bool Ambiguous = false;
+ for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P) {
+ if (P != Best &&
+ getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
+ PointOfInstantiation)
+ != Best->Partial) {
+ Ambiguous = true;
+ break;
+ }
+ }
+
+ if (Ambiguous) {
+ // Partial ordering did not produce a clear winner. Complain.
+ ClassTemplateSpec->setInvalidDecl();
+ Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
+ << ClassTemplateSpec;
+
+ // Print the matching partial specializations.
+ for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
+ PEnd = Matched.end();
+ P != PEnd; ++P)
+ Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(),
+ *P->Args);
+
+ return true;
+ }
+ }
+
+ // Instantiate using the best class template partial specialization.
+ ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
+ while (OrigPartialSpec->getInstantiatedFromMember()) {
+ // If we've found an explicit specialization of this class template,
+ // stop here and use that as the pattern.
+ if (OrigPartialSpec->isMemberSpecialization())
+ break;
+
+ OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember();
+ }
+
+ Pattern = OrigPartialSpec;
+ ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+ } else {
+ // -- If no matches are found, the instantiation is generated
+ // from the primary template.
+ ClassTemplateDecl *OrigTemplate = Template;
+ while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+ // If we've found an explicit specialization of this class template,
+ // stop here and use that as the pattern.
+ if (OrigTemplate->isMemberSpecialization())
+ break;
+
+ OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+ }
+
+ Pattern = OrigTemplate->getTemplatedDecl();
+ }
+
+ bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec,
+ Pattern,
+ getTemplateInstantiationArgs(ClassTemplateSpec),
+ TSK,
+ Complain);
+
+ return Result;
+}
+
+/// \brief Instantiates the definitions of all of the member
+/// of the given class, which is an instantiation of a class template
+/// or a member class of a template.
+void
+Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK) {
+ for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
+ DEnd = Instantiation->decls_end();
+ D != DEnd; ++D) {
+ bool SuppressNew = false;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
+ if (FunctionDecl *Pattern
+ = Function->getInstantiatedFromMemberFunction()) {
+ MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ continue;
+
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Function,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
+ continue;
+
+ if (Function->hasBody())
+ continue;
+
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Pattern->hasBody())
+ continue;
+
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+
+ InstantiateFunctionDefinition(PointOfInstantiation, Function);
+ } else {
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
+ }
+ } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+ if (Var->isStaticDataMember()) {
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ continue;
+
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Var,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
+ continue;
+
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Var->getInstantiatedFromStaticDataMember()
+ ->getOutOfLineDefinition())
+ continue;
+
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
+ } else {
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
+ }
+ } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
+ // Always skip the injected-class-name, along with any
+ // redeclarations of nested classes, since both would cause us
+ // to try to instantiate the members of a class twice.
+ if (Record->isInjectedClassName() || Record->getPreviousDeclaration())
+ continue;
+
+ MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+
+ if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ continue;
+
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Record,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
+ continue;
+
+ CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+ assert(Pattern && "Missing instantiated-from-template information");
+
+ if (!Record->getDefinition()) {
+ if (!Pattern->getDefinition()) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ continue;
+ }
+
+ InstantiateClass(PointOfInstantiation, Record, Pattern,
+ TemplateArgs,
+ TSK);
+ } else {
+ if (TSK == TSK_ExplicitInstantiationDefinition &&
+ Record->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration) {
+ Record->setTemplateSpecializationKind(TSK);
+ MarkVTableUsed(PointOfInstantiation, Record, true);
+ }
+ }
+
+ Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
+ if (Pattern)
+ InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
+ TSK);
+ }
+ }
+}
+
+/// \brief Instantiate the definitions of all of the members of the
+/// given class template specialization, which was named as part of an
+/// explicit instantiation.
+void
+Sema::InstantiateClassTemplateSpecializationMembers(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK) {
+ // C++0x [temp.explicit]p7:
+ // An explicit instantiation that names a class template
+ // specialization is an explicit instantion of the same kind
+ // (declaration or definition) of each of its members (not
+ // including members inherited from base classes) that has not
+ // been previously explicitly specialized in the translation unit
+ // containing the explicit instantiation, except as described
+ // below.
+ InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
+ getTemplateInstantiationArgs(ClassTemplateSpec),
+ TSK);
+}
+
+StmtResult
+Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (!S)
+ return Owned(S);
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformStmt(S);
+}
+
+ExprResult
+Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (!E)
+ return Owned(E);
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformExpr(E);
+}
+
+bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ llvm::SmallVectorImpl<Expr *> &Outputs) {
+ if (NumExprs == 0)
+ return false;
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
+}
+
+/// \brief Do template substitution on a nested-name-specifier.
+NestedNameSpecifier *
+Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
+ DeclarationName());
+ return Instantiator.TransformNestedNameSpecifier(NNS, Range);
+}
+
+/// \brief Do template substitution on declaration name info.
+DeclarationNameInfo
+Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
+ NameInfo.getName());
+ return Instantiator.TransformDeclarationNameInfo(NameInfo);
+}
+
+TemplateName
+Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+ DeclarationName());
+ return Instantiator.TransformTemplateName(Name);
+}
+
+bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ TemplateArgumentListInfo &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
+ DeclarationName());
+
+ return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
+}
+
+llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
+LocalInstantiationScope::findInstantiationOf(const Decl *D) {
+ for (LocalInstantiationScope *Current = this; Current;
+ Current = Current->Outer) {
+
+ // Check if we found something within this scope.
+ const Decl *CheckD = D;
+ do {
+ LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
+ if (Found != Current->LocalDecls.end())
+ return &Found->second;
+
+ // If this is a tag declaration, it's possible that we need to look for
+ // a previous declaration.
+ if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
+ CheckD = Tag->getPreviousDeclaration();
+ else
+ CheckD = 0;
+ } while (CheckD);
+
+ // If we aren't combined with our outer scope, we're done.
+ if (!Current->CombineWithOuterScope)
+ break;
+ }
+
+ // If we didn't find the decl, then we either have a sema bug, or we have a
+ // forward reference to a label declaration. Return null to indicate that
+ // we have an uninstantiated label.
+ assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
+ return 0;
+}
+
+void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
+ if (Stored.isNull())
+ Stored = Inst;
+ else if (Stored.is<Decl *>()) {
+ assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
+ Stored = Inst;
+ } else
+ LocalDecls[D].get<DeclArgumentPack *>()->push_back(Inst);
+}
+
+void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
+ Decl *Inst) {
+ DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
+ Pack->push_back(Inst);
+}
+
+void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
+ assert(Stored.isNull() && "Already instantiated this local");
+ DeclArgumentPack *Pack = new DeclArgumentPack;
+ Stored = Pack;
+ ArgumentPacks.push_back(Pack);
+}
+
+void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs) {
+ assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
+ "Already have a partially-substituted pack");
+ assert((!PartiallySubstitutedPack
+ || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
+ "Wrong number of arguments in partially-substituted pack");
+ PartiallySubstitutedPack = Pack;
+ ArgsInPartiallySubstitutedPack = ExplicitArgs;
+ NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
+}
+
+NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
+ const TemplateArgument **ExplicitArgs,
+ unsigned *NumExplicitArgs) const {
+ if (ExplicitArgs)
+ *ExplicitArgs = 0;
+ if (NumExplicitArgs)
+ *NumExplicitArgs = 0;
+
+ for (const LocalInstantiationScope *Current = this; Current;
+ Current = Current->Outer) {
+ if (Current->PartiallySubstitutedPack) {
+ if (ExplicitArgs)
+ *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
+ if (NumExplicitArgs)
+ *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
+
+ return Current->PartiallySubstitutedPack;
+ }
+
+ if (!Current->CombineWithOuterScope)
+ break;
+ }
+
+ return 0;
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
new file mode 100644
index 0000000..c0150c0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -0,0 +1,3105 @@
+//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements C++ template instantiation for declarations.
+//
+//===----------------------------------------------------------------------===/
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DependentDiagnostic.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl) {
+ NestedNameSpecifier *OldQual = OldDecl->getQualifier();
+ if (!OldQual) return false;
+
+ SourceRange QualRange = OldDecl->getQualifierRange();
+
+ NestedNameSpecifier *NewQual
+ = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
+ if (!NewQual)
+ return true;
+
+ NewDecl->setQualifierInfo(NewQual, QualRange);
+ return false;
+}
+
+bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl) {
+ NestedNameSpecifier *OldQual = OldDecl->getQualifier();
+ if (!OldQual) return false;
+
+ SourceRange QualRange = OldDecl->getQualifierRange();
+
+ NestedNameSpecifier *NewQual
+ = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
+ if (!NewQual)
+ return true;
+
+ NewDecl->setQualifierInfo(NewQual, QualRange);
+ return false;
+}
+
+// FIXME: Is this still too simple?
+void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ Decl *Tmpl, Decl *New) {
+ for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
+ i != e; ++i) {
+ const Attr *TmplAttr = *i;
+ // FIXME: This should be generalized to more than just the AlignedAttr.
+ if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
+ if (Aligned->isAlignmentDependent()) {
+ // The alignment expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(*this,
+ Sema::Unevaluated);
+
+ if (Aligned->isAlignmentExpr()) {
+ ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
+ TemplateArgs);
+ if (!Result.isInvalid())
+ AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
+ }
+ else {
+ TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
+ TemplateArgs,
+ Aligned->getLocation(),
+ DeclarationName());
+ if (Result)
+ AddAlignedAttr(Aligned->getLocation(), New, Result);
+ }
+ continue;
+ }
+ }
+
+ // FIXME: Is cloning correct for all attributes?
+ Attr *NewAttr = TmplAttr->clone(Context);
+ New->addAttr(NewAttr);
+ }
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ assert(false && "Translation units cannot be instantiated");
+ return D;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
+ LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getIdentifier());
+ Owner->addDecl(Inst);
+ return Inst;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
+ assert(false && "Namespaces cannot be instantiated");
+ return D;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ NamespaceAliasDecl *Inst
+ = NamespaceAliasDecl::Create(SemaRef.Context, Owner,
+ D->getNamespaceLoc(),
+ D->getAliasLoc(),
+ D->getNamespace()->getIdentifier(),
+ D->getQualifierRange(),
+ D->getQualifier(),
+ D->getTargetNameLoc(),
+ D->getNamespace());
+ Owner->addDecl(Inst);
+ return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+ bool Invalid = false;
+ TypeSourceInfo *DI = D->getTypeSourceInfo();
+ if (DI->getType()->isDependentType() ||
+ DI->getType()->isVariablyModifiedType()) {
+ DI = SemaRef.SubstType(DI, TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI) {
+ Invalid = true;
+ DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy);
+ }
+ } else {
+ SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+ }
+
+ // Create the new typedef
+ TypedefDecl *Typedef
+ = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getIdentifier(), DI);
+ if (Invalid)
+ Typedef->setInvalidDecl();
+
+ // If the old typedef was the name for linkage purposes of an anonymous
+ // tag decl, re-establish that relationship for the new typedef.
+ if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
+ TagDecl *oldTag = oldTagType->getDecl();
+ if (oldTag->getTypedefForAnonDecl() == D) {
+ TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
+ assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl());
+ newTag->setTypedefForAnonDecl(Typedef);
+ }
+ }
+
+ if (TypedefDecl *Prev = D->getPreviousDeclaration()) {
+ NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
+ TemplateArgs);
+ Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
+ }
+
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
+
+ Typedef->setAccess(D->getAccess());
+ Owner->addDecl(Typedef);
+
+ return Typedef;
+}
+
+/// \brief Instantiate an initializer, breaking it into separate
+/// initialization arguments.
+///
+/// \param S The semantic analysis object.
+///
+/// \param Init The initializer to instantiate.
+///
+/// \param TemplateArgs Template arguments to be substituted into the
+/// initializer.
+///
+/// \param NewArgs Will be filled in with the instantiation arguments.
+///
+/// \returns true if an error occurred, false otherwise
+static bool InstantiateInitializer(Sema &S, Expr *Init,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation &LParenLoc,
+ ASTOwningVector<Expr*> &NewArgs,
+ SourceLocation &RParenLoc) {
+ NewArgs.clear();
+ LParenLoc = SourceLocation();
+ RParenLoc = SourceLocation();
+
+ if (!Init)
+ return false;
+
+ if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
+ Init = ExprTemp->getSubExpr();
+
+ while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
+ Init = Binder->getSubExpr();
+
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
+ Init = ICE->getSubExprAsWritten();
+
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ LParenLoc = ParenList->getLParenLoc();
+ RParenLoc = ParenList->getRParenLoc();
+ return S.SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(),
+ true, TemplateArgs, NewArgs);
+ }
+
+ if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
+ if (!isa<CXXTemporaryObjectExpr>(Construct)) {
+ if (S.SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
+ TemplateArgs, NewArgs))
+ return true;
+
+ // FIXME: Fake locations!
+ LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart());
+ RParenLoc = LParenLoc;
+ return false;
+ }
+ }
+
+ ExprResult Result = S.SubstExpr(Init, TemplateArgs);
+ if (Result.isInvalid())
+ return true;
+
+ NewArgs.push_back(Result.takeAs<Expr>());
+ return false;
+}
+
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+ // If this is the variable for an anonymous struct or union,
+ // instantiate the anonymous struct/union type first.
+ if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
+ if (RecordTy->getDecl()->isAnonymousStructOrUnion())
+ if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
+ return 0;
+
+ // Do substitution on the type of the declaration
+ TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
+ TemplateArgs,
+ D->getTypeSpecStartLoc(),
+ D->getDeclName());
+ if (!DI)
+ return 0;
+
+ if (DI->getType()->isFunctionType()) {
+ SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
+ << D->isStaticDataMember() << DI->getType();
+ return 0;
+ }
+
+ // Build the instantiated declaration
+ VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(), D->getIdentifier(),
+ DI->getType(), DI,
+ D->getStorageClass(),
+ D->getStorageClassAsWritten());
+ Var->setThreadSpecified(D->isThreadSpecified());
+ Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
+
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(D, Var))
+ return 0;
+
+ // If we are instantiating a static data member defined
+ // out-of-line, the instantiation will have the same lexical
+ // context (which will be a namespace scope) as the template.
+ if (D->isOutOfLine())
+ Var->setLexicalDeclContext(D->getLexicalDeclContext());
+
+ Var->setAccess(D->getAccess());
+
+ if (!D->isStaticDataMember())
+ Var->setUsed(D->isUsed(false));
+
+ // FIXME: In theory, we could have a previous declaration for variables that
+ // are not static data members.
+ bool Redeclaration = false;
+ // FIXME: having to fake up a LookupResult is dumb.
+ LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ if (D->isStaticDataMember())
+ SemaRef.LookupQualifiedName(Previous, Owner, false);
+ SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
+
+ if (D->isOutOfLine()) {
+ if (!D->isStaticDataMember())
+ D->getLexicalDeclContext()->addDecl(Var);
+ Owner->makeDeclVisibleInContext(Var);
+ } else {
+ Owner->addDecl(Var);
+ if (Owner->isFunctionOrMethod())
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
+ }
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Var);
+
+ // Link instantiations of static data members back to the template from
+ // which they were instantiated.
+ if (Var->isStaticDataMember())
+ SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
+ TSK_ImplicitInstantiation);
+
+ if (Var->getAnyInitializer()) {
+ // We already have an initializer in the class.
+ } else if (D->getInit()) {
+ if (Var->isStaticDataMember() && !D->isOutOfLine())
+ SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated);
+ else
+ SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+
+ // Instantiate the initializer.
+ SourceLocation LParenLoc, RParenLoc;
+ ASTOwningVector<Expr*> InitArgs(SemaRef);
+ if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc,
+ InitArgs, RParenLoc)) {
+ bool TypeMayContainAuto = true;
+ // Attach the initializer to the declaration, if we have one.
+ if (InitArgs.size() == 0)
+ SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
+ else if (D->hasCXXDirectInitializer()) {
+ // Add the direct initializer to the declaration.
+ SemaRef.AddCXXDirectInitializerToDecl(Var,
+ LParenLoc,
+ move_arg(InitArgs),
+ RParenLoc,
+ TypeMayContainAuto);
+ } else {
+ assert(InitArgs.size() == 1);
+ Expr *Init = InitArgs.take()[0];
+ SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto);
+ }
+ } else {
+ // FIXME: Not too happy about invalidating the declaration
+ // because of a bogus initializer.
+ Var->setInvalidDecl();
+ }
+
+ SemaRef.PopExpressionEvaluationContext();
+ } else if (!Var->isStaticDataMember() || Var->isOutOfLine())
+ SemaRef.ActOnUninitializedDecl(Var, false);
+
+ // Diagnose unused local variables.
+ if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed())
+ SemaRef.DiagnoseUnusedDecl(Var);
+
+ return Var;
+}
+
+Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) {
+ AccessSpecDecl* AD
+ = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner,
+ D->getAccessSpecifierLoc(), D->getColonLoc());
+ Owner->addHiddenDecl(AD);
+ return AD;
+}
+
+Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
+ bool Invalid = false;
+ TypeSourceInfo *DI = D->getTypeSourceInfo();
+ if (DI->getType()->isDependentType() ||
+ DI->getType()->isVariablyModifiedType()) {
+ DI = SemaRef.SubstType(DI, TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI) {
+ DI = D->getTypeSourceInfo();
+ Invalid = true;
+ } else if (DI->getType()->isFunctionType()) {
+ // C++ [temp.arg.type]p3:
+ // If a declaration acquires a function type through a type
+ // dependent on a template-parameter and this causes a
+ // declaration that does not use the syntactic form of a
+ // function declarator to have function type, the program is
+ // ill-formed.
+ SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+ << DI->getType();
+ Invalid = true;
+ }
+ } else {
+ SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
+ }
+
+ Expr *BitWidth = D->getBitWidth();
+ if (Invalid)
+ BitWidth = 0;
+ else if (BitWidth) {
+ // The bit-width expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult InstantiatedBitWidth
+ = SemaRef.SubstExpr(BitWidth, TemplateArgs);
+ if (InstantiatedBitWidth.isInvalid()) {
+ Invalid = true;
+ BitWidth = 0;
+ } else
+ BitWidth = InstantiatedBitWidth.takeAs<Expr>();
+ }
+
+ FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
+ DI->getType(), DI,
+ cast<RecordDecl>(Owner),
+ D->getLocation(),
+ D->isMutable(),
+ BitWidth,
+ D->getTypeSpecStartLoc(),
+ D->getAccess(),
+ 0);
+ if (!Field) {
+ cast<Decl>(Owner)->setInvalidDecl();
+ return 0;
+ }
+
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Field);
+
+ if (Invalid)
+ Field->setInvalidDecl();
+
+ if (!Field->getDeclName()) {
+ // Keep track of where this decl came from.
+ SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D);
+ }
+ if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
+ if (Parent->isAnonymousStructOrUnion() &&
+ Parent->getRedeclContext()->isFunctionOrMethod())
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
+ }
+
+ Field->setImplicit(D->isImplicit());
+ Field->setAccess(D->getAccess());
+ Owner->addDecl(Field);
+
+ return Field;
+}
+
+Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
+ NamedDecl **NamedChain =
+ new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
+
+ int i = 0;
+ for (IndirectFieldDecl::chain_iterator PI =
+ D->chain_begin(), PE = D->chain_end();
+ PI != PE; ++PI)
+ NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(),
+ *PI, TemplateArgs));
+
+ QualType T = cast<FieldDecl>(NamedChain[i-1])->getType();
+ IndirectFieldDecl* IndirectField
+ = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getIdentifier(), T,
+ NamedChain, D->getChainingSize());
+
+
+ IndirectField->setImplicit(D->isImplicit());
+ IndirectField->setAccess(D->getAccess());
+ Owner->addDecl(IndirectField);
+ return IndirectField;
+}
+
+Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
+ // Handle friend type expressions by simply substituting template
+ // parameters into the pattern type and checking the result.
+ if (TypeSourceInfo *Ty = D->getFriendType()) {
+ TypeSourceInfo *InstTy =
+ SemaRef.SubstType(Ty, TemplateArgs,
+ D->getLocation(), DeclarationName());
+ if (!InstTy)
+ return 0;
+
+ FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy);
+ if (!FD)
+ return 0;
+
+ FD->setAccess(AS_public);
+ FD->setUnsupportedFriend(D->isUnsupportedFriend());
+ Owner->addDecl(FD);
+ return FD;
+ }
+
+ NamedDecl *ND = D->getFriendDecl();
+ assert(ND && "friend decl must be a decl or a type!");
+
+ // All of the Visit implementations for the various potential friend
+ // declarations have to be carefully written to work for friend
+ // objects, with the most important detail being that the target
+ // decl should almost certainly not be placed in Owner.
+ Decl *NewND = Visit(ND);
+ if (!NewND) return 0;
+
+ FriendDecl *FD =
+ FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ cast<NamedDecl>(NewND), D->getFriendLoc());
+ FD->setAccess(AS_public);
+ FD->setUnsupportedFriend(D->isUnsupportedFriend());
+ Owner->addDecl(FD);
+ return FD;
+}
+
+Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ Expr *AssertExpr = D->getAssertExpr();
+
+ // The expression in a static assertion is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult InstantiatedAssertExpr
+ = SemaRef.SubstExpr(AssertExpr, TemplateArgs);
+ if (InstantiatedAssertExpr.isInvalid())
+ return 0;
+
+ ExprResult Message(D->getMessage());
+ D->getMessage();
+ return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
+ InstantiatedAssertExpr.get(),
+ Message.get());
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
+ EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(), D->getIdentifier(),
+ D->getTagKeywordLoc(),
+ /*PrevDecl=*/0, D->isScoped(),
+ D->isScopedUsingClassTag(), D->isFixed());
+ if (D->isFixed()) {
+ if (TypeSourceInfo* TI = D->getIntegerTypeSourceInfo()) {
+ // If we have type source information for the underlying type, it means it
+ // has been explicitly set by the user. Perform substitution on it before
+ // moving on.
+ SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
+ Enum->setIntegerTypeSourceInfo(SemaRef.SubstType(TI,
+ TemplateArgs,
+ UnderlyingLoc,
+ DeclarationName()));
+
+ if (!Enum->getIntegerTypeSourceInfo())
+ Enum->setIntegerType(SemaRef.Context.IntTy);
+ }
+ else {
+ assert(!D->getIntegerType()->isDependentType()
+ && "Dependent type without type source info");
+ Enum->setIntegerType(D->getIntegerType());
+ }
+ }
+
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Enum);
+
+ Enum->setInstantiationOfMemberEnum(D);
+ Enum->setAccess(D->getAccess());
+ if (SubstQualifier(D, Enum)) return 0;
+ Owner->addDecl(Enum);
+ Enum->startDefinition();
+
+ if (D->getDeclContext()->isFunctionOrMethod())
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
+
+ llvm::SmallVector<Decl*, 4> Enumerators;
+
+ EnumConstantDecl *LastEnumConst = 0;
+ for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
+ ECEnd = D->enumerator_end();
+ EC != ECEnd; ++EC) {
+ // The specified value for the enumerator.
+ ExprResult Value = SemaRef.Owned((Expr *)0);
+ if (Expr *UninstValue = EC->getInitExpr()) {
+ // The enumerator's value expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Sema::Unevaluated);
+
+ Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
+ }
+
+ // Drop the initial value and continue.
+ bool isInvalid = false;
+ if (Value.isInvalid()) {
+ Value = SemaRef.Owned((Expr *)0);
+ isInvalid = true;
+ }
+
+ EnumConstantDecl *EnumConst
+ = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
+ EC->getLocation(), EC->getIdentifier(),
+ Value.get());
+
+ if (isInvalid) {
+ if (EnumConst)
+ EnumConst->setInvalidDecl();
+ Enum->setInvalidDecl();
+ }
+
+ if (EnumConst) {
+ SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
+
+ EnumConst->setAccess(Enum->getAccess());
+ Enum->addDecl(EnumConst);
+ Enumerators.push_back(EnumConst);
+ LastEnumConst = EnumConst;
+
+ if (D->getDeclContext()->isFunctionOrMethod()) {
+ // If the enumeration is within a function or method, record the enum
+ // constant as a local.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst);
+ }
+ }
+ }
+
+ // FIXME: Fixup LBraceLoc and RBraceLoc
+ // FIXME: Empty Scope and AttributeList (required to handle attribute packed).
+ SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(),
+ Enum,
+ Enumerators.data(), Enumerators.size(),
+ 0, 0);
+
+ return Enum;
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ assert(false && "EnumConstantDecls can only occur within EnumDecls.");
+ return 0;
+}
+
+Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+ // Create a local instantiation scope for this class template, which
+ // will contain the instantiations of the template parameters.
+ LocalInstantiationScope Scope(SemaRef);
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+
+ CXXRecordDecl *Pattern = D->getTemplatedDecl();
+
+ // Instantiate the qualifier. We have to do this first in case
+ // we're a friend declaration, because if we are then we need to put
+ // the new declaration in the appropriate context.
+ NestedNameSpecifier *Qualifier = Pattern->getQualifier();
+ if (Qualifier) {
+ Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
+ Pattern->getQualifierRange(),
+ TemplateArgs);
+ if (!Qualifier) return 0;
+ }
+
+ CXXRecordDecl *PrevDecl = 0;
+ ClassTemplateDecl *PrevClassTemplate = 0;
+
+ if (!isFriend && Pattern->getPreviousDeclaration()) {
+ DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
+ if (Found.first != Found.second) {
+ PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first);
+ if (PrevClassTemplate)
+ PrevDecl = PrevClassTemplate->getTemplatedDecl();
+ }
+ }
+
+ // If this isn't a friend, then it's a member template, in which
+ // case we just want to build the instantiation in the
+ // specialization. If it is a friend, we want to build it in
+ // the appropriate context.
+ DeclContext *DC = Owner;
+ if (isFriend) {
+ if (Qualifier) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(Pattern->getQualifierRange());
+ DC = SemaRef.computeDeclContext(SS);
+ if (!DC) return 0;
+ } else {
+ DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(),
+ Pattern->getDeclContext(),
+ TemplateArgs);
+ }
+
+ // Look for a previous declaration of the template in the owning
+ // context.
+ LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ SemaRef.LookupQualifiedName(R, DC);
+
+ if (R.isSingleResult()) {
+ PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>();
+ if (PrevClassTemplate)
+ PrevDecl = PrevClassTemplate->getTemplatedDecl();
+ }
+
+ if (!PrevClassTemplate && Qualifier) {
+ SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
+ << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
+ << Pattern->getQualifierRange();
+ return 0;
+ }
+
+ bool AdoptedPreviousTemplateParams = false;
+ if (PrevClassTemplate) {
+ bool Complain = true;
+
+ // HACK: libstdc++ 4.2.1 contains an ill-formed friend class
+ // template for struct std::tr1::__detail::_Map_base, where the
+ // template parameters of the friend declaration don't match the
+ // template parameters of the original declaration. In this one
+ // case, we don't complain about the ill-formed friend
+ // declaration.
+ if (isFriend && Pattern->getIdentifier() &&
+ Pattern->getIdentifier()->isStr("_Map_base") &&
+ DC->isNamespace() &&
+ cast<NamespaceDecl>(DC)->getIdentifier() &&
+ cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) {
+ DeclContext *DCParent = DC->getParent();
+ if (DCParent->isNamespace() &&
+ cast<NamespaceDecl>(DCParent)->getIdentifier() &&
+ cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
+ DeclContext *DCParent2 = DCParent->getParent();
+ if (DCParent2->isNamespace() &&
+ cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
+ cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
+ DCParent2->getParent()->isTranslationUnit())
+ Complain = false;
+ }
+ }
+
+ TemplateParameterList *PrevParams
+ = PrevClassTemplate->getTemplateParameters();
+
+ // Make sure the parameter lists match.
+ if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
+ Complain,
+ Sema::TPL_TemplateMatch)) {
+ if (Complain)
+ return 0;
+
+ AdoptedPreviousTemplateParams = true;
+ InstParams = PrevParams;
+ }
+
+ // Do some additional validation, then merge default arguments
+ // from the existing declarations.
+ if (!AdoptedPreviousTemplateParams &&
+ SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+ Sema::TPC_ClassTemplate))
+ return 0;
+ }
+ }
+
+ CXXRecordDecl *RecordInst
+ = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC,
+ Pattern->getLocation(), Pattern->getIdentifier(),
+ Pattern->getTagKeywordLoc(), PrevDecl,
+ /*DelayTypeCreation=*/true);
+
+ if (Qualifier)
+ RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange());
+
+ ClassTemplateDecl *Inst
+ = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
+ D->getIdentifier(), InstParams, RecordInst,
+ PrevClassTemplate);
+ RecordInst->setDescribedClassTemplate(Inst);
+
+ if (isFriend) {
+ if (PrevClassTemplate)
+ Inst->setAccess(PrevClassTemplate->getAccess());
+ else
+ Inst->setAccess(D->getAccess());
+
+ Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
+ // TODO: do we want to track the instantiation progeny of this
+ // friend target decl?
+ } else {
+ Inst->setAccess(D->getAccess());
+ if (!PrevClassTemplate)
+ Inst->setInstantiatedFromMemberTemplate(D);
+ }
+
+ // Trigger creation of the type for the instantiation.
+ SemaRef.Context.getInjectedClassNameType(RecordInst,
+ Inst->getInjectedClassNameSpecialization());
+
+ // Finish handling of friends.
+ if (isFriend) {
+ DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false);
+ return Inst;
+ }
+
+ Owner->addDecl(Inst);
+
+ if (!PrevClassTemplate) {
+ // Queue up any out-of-line partial specializations of this member
+ // class template; the client will force their instantiation once
+ // the enclosing class has been instantiated.
+ llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ D->getPartialSpecializations(PartialSpecs);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+ if (PartialSpecs[I]->isOutOfLine())
+ OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
+ }
+
+ return Inst;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+
+ // Lookup the already-instantiated declaration in the instantiation
+ // of the class template and return that.
+ DeclContext::lookup_result Found
+ = Owner->lookup(ClassTemplate->getDeclName());
+ if (Found.first == Found.second)
+ return 0;
+
+ ClassTemplateDecl *InstClassTemplate
+ = dyn_cast<ClassTemplateDecl>(*Found.first);
+ if (!InstClassTemplate)
+ return 0;
+
+ if (ClassTemplatePartialSpecializationDecl *Result
+ = InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
+ return Result;
+
+ return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
+}
+
+Decl *
+TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // Create a local instantiation scope for this function template, which
+ // will contain the instantiations of the template parameters and then get
+ // merged with the local instantiation scope for the function template
+ // itself.
+ LocalInstantiationScope Scope(SemaRef);
+
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+
+ FunctionDecl *Instantiated = 0;
+ if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
+ Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
+ InstParams));
+ else
+ Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl(
+ D->getTemplatedDecl(),
+ InstParams));
+
+ if (!Instantiated)
+ return 0;
+
+ Instantiated->setAccess(D->getAccess());
+
+ // Link the instantiated function template declaration to the function
+ // template from which it was instantiated.
+ FunctionTemplateDecl *InstTemplate
+ = Instantiated->getDescribedFunctionTemplate();
+ InstTemplate->setAccess(D->getAccess());
+ assert(InstTemplate &&
+ "VisitFunctionDecl/CXXMethodDecl didn't create a template!");
+
+ bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None);
+
+ // Link the instantiation back to the pattern *unless* this is a
+ // non-definition friend declaration.
+ if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
+ !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
+ InstTemplate->setInstantiatedFromMemberTemplate(D);
+
+ // Make declarations visible in the appropriate context.
+ if (!isFriend)
+ Owner->addDecl(InstTemplate);
+
+ return InstTemplate;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ CXXRecordDecl *PrevDecl = 0;
+ if (D->isInjectedClassName())
+ PrevDecl = cast<CXXRecordDecl>(Owner);
+ else if (D->getPreviousDeclaration()) {
+ NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
+ D->getPreviousDeclaration(),
+ TemplateArgs);
+ if (!Prev) return 0;
+ PrevDecl = cast<CXXRecordDecl>(Prev);
+ }
+
+ CXXRecordDecl *Record
+ = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
+ D->getLocation(), D->getIdentifier(),
+ D->getTagKeywordLoc(), PrevDecl);
+
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(D, Record))
+ return 0;
+
+ Record->setImplicit(D->isImplicit());
+ // FIXME: Check against AS_none is an ugly hack to work around the issue that
+ // the tag decls introduced by friend class declarations don't have an access
+ // specifier. Remove once this area of the code gets sorted out.
+ if (D->getAccess() != AS_none)
+ Record->setAccess(D->getAccess());
+ if (!D->isInjectedClassName())
+ Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
+
+ // If the original function was part of a friend declaration,
+ // inherit its namespace state.
+ if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+ Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
+
+ // Make sure that anonymous structs and unions are recorded.
+ if (D->isAnonymousStructOrUnion()) {
+ Record->setAnonymousStructOrUnion(true);
+ if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
+ }
+
+ Owner->addDecl(Record);
+ return Record;
+}
+
+/// Normal class members are of more specific types and therefore
+/// don't make it here. This function serves two purposes:
+/// 1) instantiating function templates
+/// 2) substituting friend declarations
+/// FIXME: preserve function definitions in case #2
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams) {
+ // Check whether there is already a function template specialization for
+ // this declaration.
+ FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+ void *InsertPos = 0;
+ if (FunctionTemplate && !TemplateParams) {
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+
+ FunctionDecl *SpecFunc
+ = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+ InsertPos);
+
+ // If we already have a function template specialization, return it.
+ if (SpecFunc)
+ return SpecFunc;
+ }
+
+ bool isFriend;
+ if (FunctionTemplate)
+ isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
+ else
+ isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+ bool MergeWithParentScope = (TemplateParams != 0) ||
+ Owner->isFunctionOrMethod() ||
+ !(isa<Decl>(Owner) &&
+ cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+ LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+ llvm::SmallVector<ParmVarDecl *, 4> Params;
+ TypeSourceInfo *TInfo = D->getTypeSourceInfo();
+ TInfo = SubstFunctionType(D, Params);
+ if (!TInfo)
+ return 0;
+ QualType T = TInfo->getType();
+
+ NestedNameSpecifier *Qualifier = D->getQualifier();
+ if (Qualifier) {
+ Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
+ D->getQualifierRange(),
+ TemplateArgs);
+ if (!Qualifier) return 0;
+ }
+
+ // If we're instantiating a local function declaration, put the result
+ // in the owner; otherwise we need to find the instantiated context.
+ DeclContext *DC;
+ if (D->getDeclContext()->isFunctionOrMethod())
+ DC = Owner;
+ else if (isFriend && Qualifier) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(D->getQualifierRange());
+ DC = SemaRef.computeDeclContext(SS);
+ if (!DC) return 0;
+ } else {
+ DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(),
+ TemplateArgs);
+ }
+
+ FunctionDecl *Function =
+ FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
+ D->getDeclName(), T, TInfo,
+ D->getStorageClass(), D->getStorageClassAsWritten(),
+ D->isInlineSpecified(), D->hasWrittenPrototype());
+
+ if (Qualifier)
+ Function->setQualifierInfo(Qualifier, D->getQualifierRange());
+
+ DeclContext *LexicalDC = Owner;
+ if (!isFriend && D->isOutOfLine()) {
+ assert(D->getDeclContext()->isFileContext());
+ LexicalDC = D->getDeclContext();
+ }
+
+ Function->setLexicalDeclContext(LexicalDC);
+
+ // Attach the parameters
+ for (unsigned P = 0; P < Params.size(); ++P)
+ if (Params[P])
+ Params[P]->setOwningFunction(Function);
+ Function->setParams(Params.data(), Params.size());
+
+ SourceLocation InstantiateAtPOI;
+ if (TemplateParams) {
+ // Our resulting instantiation is actually a function template, since we
+ // are substituting only the outer template parameters. For example, given
+ //
+ // template<typename T>
+ // struct X {
+ // template<typename U> friend void f(T, U);
+ // };
+ //
+ // X<int> x;
+ //
+ // We are instantiating the friend function template "f" within X<int>,
+ // which means substituting int for T, but leaving "f" as a friend function
+ // template.
+ // Build the function template itself.
+ FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC,
+ Function->getLocation(),
+ Function->getDeclName(),
+ TemplateParams, Function);
+ Function->setDescribedFunctionTemplate(FunctionTemplate);
+
+ FunctionTemplate->setLexicalDeclContext(LexicalDC);
+
+ if (isFriend && D->isThisDeclarationADefinition()) {
+ // TODO: should we remember this connection regardless of whether
+ // the friend declaration provided a body?
+ FunctionTemplate->setInstantiatedFromMemberTemplate(
+ D->getDescribedFunctionTemplate());
+ }
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+ Function->setFunctionTemplateSpecialization(FunctionTemplate,
+ TemplateArgumentList::CreateCopy(SemaRef.Context,
+ Innermost.first,
+ Innermost.second),
+ InsertPos);
+ } else if (isFriend && D->isThisDeclarationADefinition()) {
+ // TODO: should we remember this connection regardless of whether
+ // the friend declaration provided a body?
+ Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+ }
+
+ if (InitFunctionInstantiation(Function, D))
+ Function->setInvalidDecl();
+
+ bool Redeclaration = false;
+ bool isExplicitSpecialization = false;
+
+ LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
+ Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
+ if (DependentFunctionTemplateSpecializationInfo *Info
+ = D->getDependentSpecializationInfo()) {
+ assert(isFriend && "non-friend has dependent specialization info?");
+
+ // This needs to be set now for future sanity.
+ Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
+
+ // Instantiate the explicit template arguments.
+ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
+ Info->getRAngleLoc());
+ if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+ ExplicitArgs, TemplateArgs))
+ return 0;
+
+ // Map the candidate templates to their instantiations.
+ for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
+ Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
+ Info->getTemplate(I),
+ TemplateArgs);
+ if (!Temp) return 0;
+
+ Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
+ }
+
+ if (SemaRef.CheckFunctionTemplateSpecialization(Function,
+ &ExplicitArgs,
+ Previous))
+ Function->setInvalidDecl();
+
+ isExplicitSpecialization = true;
+
+ } else if (TemplateParams || !FunctionTemplate) {
+ // Look only into the namespace where the friend would be declared to
+ // find a previous declaration. This is the innermost enclosing namespace,
+ // as described in ActOnFriendFunctionDecl.
+ SemaRef.LookupQualifiedName(Previous, DC);
+
+ // In C++, the previous declaration we find might be a tag type
+ // (class or enum). In this case, the new declaration will hide the
+ // tag type. Note that this does does not apply if we're declaring a
+ // typedef (C++ [dcl.typedef]p4).
+ if (Previous.isSingleTagDecl())
+ Previous.clear();
+ }
+
+ SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+ isExplicitSpecialization, Redeclaration);
+
+ NamedDecl *PrincipalDecl = (TemplateParams
+ ? cast<NamedDecl>(FunctionTemplate)
+ : Function);
+
+ // If the original function was part of a friend declaration,
+ // inherit its namespace state and add it to the owner.
+ if (isFriend) {
+ NamedDecl *PrevDecl;
+ if (TemplateParams)
+ PrevDecl = FunctionTemplate->getPreviousDeclaration();
+ else
+ PrevDecl = Function->getPreviousDeclaration();
+
+ PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
+ DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
+
+ bool queuedInstantiation = false;
+
+ if (!SemaRef.getLangOptions().CPlusPlus0x &&
+ D->isThisDeclarationADefinition()) {
+ // Check for a function body.
+ const FunctionDecl *Definition = 0;
+ if (Function->hasBody(Definition) &&
+ Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
+ << Function->getDeclName();
+ SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
+ Function->setInvalidDecl();
+ }
+ // Check for redefinitions due to other instantiations of this or
+ // a similar friend function.
+ else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
+ REnd = Function->redecls_end();
+ R != REnd; ++R) {
+ if (*R == Function)
+ continue;
+ switch (R->getFriendObjectKind()) {
+ case Decl::FOK_None:
+ if (!queuedInstantiation && R->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = R->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
+ queuedInstantiation = true;
+ }
+ }
+ }
+ break;
+ default:
+ if (const FunctionDecl *RPattern
+ = R->getTemplateInstantiationPattern())
+ if (RPattern->hasBody(RPattern)) {
+ SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
+ << Function->getDeclName();
+ SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
+ Function->setInvalidDecl();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (Function->isOverloadedOperator() && !DC->isRecord() &&
+ PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
+ PrincipalDecl->setNonMemberOperator();
+
+ return Function;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams) {
+ FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+ void *InsertPos = 0;
+ if (FunctionTemplate && !TemplateParams) {
+ // We are creating a function template specialization from a function
+ // template. Check whether there is already a function template
+ // specialization for this particular set of template arguments.
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+
+ FunctionDecl *SpecFunc
+ = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+ InsertPos);
+
+ // If we already have a function template specialization, return it.
+ if (SpecFunc)
+ return SpecFunc;
+ }
+
+ bool isFriend;
+ if (FunctionTemplate)
+ isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
+ else
+ isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
+
+ bool MergeWithParentScope = (TemplateParams != 0) ||
+ !(isa<Decl>(Owner) &&
+ cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+ LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+
+ // Instantiate enclosing template arguments for friends.
+ llvm::SmallVector<TemplateParameterList *, 4> TempParamLists;
+ unsigned NumTempParamLists = 0;
+ if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
+ TempParamLists.set_size(NumTempParamLists);
+ for (unsigned I = 0; I != NumTempParamLists; ++I) {
+ TemplateParameterList *TempParams = D->getTemplateParameterList(I);
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+ TempParamLists[I] = InstParams;
+ }
+ }
+
+ llvm::SmallVector<ParmVarDecl *, 4> Params;
+ TypeSourceInfo *TInfo = D->getTypeSourceInfo();
+ TInfo = SubstFunctionType(D, Params);
+ if (!TInfo)
+ return 0;
+ QualType T = TInfo->getType();
+
+ // \brief If the type of this function, after ignoring parentheses,
+ // is not *directly* a function type, then we're instantiating a function
+ // that was declared via a typedef, e.g.,
+ //
+ // typedef int functype(int, int);
+ // functype func;
+ //
+ // In this case, we'll just go instantiate the ParmVarDecls that we
+ // synthesized in the method declaration.
+ if (!isa<FunctionProtoType>(T.IgnoreParens())) {
+ assert(!Params.size() && "Instantiating type could not yield parameters");
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
+ D->getNumParams(), TemplateArgs, ParamTypes,
+ &Params))
+ return 0;
+ }
+
+ NestedNameSpecifier *Qualifier = D->getQualifier();
+ if (Qualifier) {
+ Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
+ D->getQualifierRange(),
+ TemplateArgs);
+ if (!Qualifier) return 0;
+ }
+
+ DeclContext *DC = Owner;
+ if (isFriend) {
+ if (Qualifier) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(D->getQualifierRange());
+ DC = SemaRef.computeDeclContext(SS);
+
+ if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
+ return 0;
+ } else {
+ DC = SemaRef.FindInstantiatedContext(D->getLocation(),
+ D->getDeclContext(),
+ TemplateArgs);
+ }
+ if (!DC) return 0;
+ }
+
+ // Build the instantiated method declaration.
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+ CXXMethodDecl *Method = 0;
+
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
+ NameInfo, T, TInfo,
+ Constructor->isExplicit(),
+ Constructor->isInlineSpecified(),
+ false);
+ } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+ Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
+ NameInfo, T, TInfo,
+ Destructor->isInlineSpecified(),
+ false);
+ } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+ Method = CXXConversionDecl::Create(SemaRef.Context, Record,
+ NameInfo, T, TInfo,
+ Conversion->isInlineSpecified(),
+ Conversion->isExplicit());
+ } else {
+ Method = CXXMethodDecl::Create(SemaRef.Context, Record,
+ NameInfo, T, TInfo,
+ D->isStatic(),
+ D->getStorageClassAsWritten(),
+ D->isInlineSpecified());
+ }
+
+ if (Qualifier)
+ Method->setQualifierInfo(Qualifier, D->getQualifierRange());
+
+ if (TemplateParams) {
+ // Our resulting instantiation is actually a function template, since we
+ // are substituting only the outer template parameters. For example, given
+ //
+ // template<typename T>
+ // struct X {
+ // template<typename U> void f(T, U);
+ // };
+ //
+ // X<int> x;
+ //
+ // We are instantiating the member template "f" within X<int>, which means
+ // substituting int for T, but leaving "f" as a member function template.
+ // Build the function template itself.
+ FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record,
+ Method->getLocation(),
+ Method->getDeclName(),
+ TemplateParams, Method);
+ if (isFriend) {
+ FunctionTemplate->setLexicalDeclContext(Owner);
+ FunctionTemplate->setObjectOfFriendDecl(true);
+ } else if (D->isOutOfLine())
+ FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+ Method->setDescribedFunctionTemplate(FunctionTemplate);
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+ Method->setFunctionTemplateSpecialization(FunctionTemplate,
+ TemplateArgumentList::CreateCopy(SemaRef.Context,
+ Innermost.first,
+ Innermost.second),
+ InsertPos);
+ } else if (!isFriend) {
+ // Record that this is an instantiation of a member function.
+ Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+ }
+
+ // If we are instantiating a member function defined
+ // out-of-line, the instantiation will have the same lexical
+ // context (which will be a namespace scope) as the template.
+ if (isFriend) {
+ if (NumTempParamLists)
+ Method->setTemplateParameterListsInfo(SemaRef.Context,
+ NumTempParamLists,
+ TempParamLists.data());
+
+ Method->setLexicalDeclContext(Owner);
+ Method->setObjectOfFriendDecl(true);
+ } else if (D->isOutOfLine())
+ Method->setLexicalDeclContext(D->getLexicalDeclContext());
+
+ // Attach the parameters
+ for (unsigned P = 0; P < Params.size(); ++P)
+ Params[P]->setOwningFunction(Method);
+ Method->setParams(Params.data(), Params.size());
+
+ if (InitMethodInstantiation(Method, D))
+ Method->setInvalidDecl();
+
+ LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
+
+ if (!FunctionTemplate || TemplateParams || isFriend) {
+ SemaRef.LookupQualifiedName(Previous, Record);
+
+ // In C++, the previous declaration we find might be a tag type
+ // (class or enum). In this case, the new declaration will hide the
+ // tag type. Note that this does does not apply if we're declaring a
+ // typedef (C++ [dcl.typedef]p4).
+ if (Previous.isSingleTagDecl())
+ Previous.clear();
+ }
+
+ bool Redeclaration = false;
+ SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration);
+
+ if (D->isPure())
+ SemaRef.CheckPureMethod(Method, SourceRange());
+
+ Method->setAccess(D->getAccess());
+
+ SemaRef.CheckOverrideControl(Method);
+
+ if (FunctionTemplate) {
+ // If there's a function template, let our caller handle it.
+ } else if (Method->isInvalidDecl() && !Previous.empty()) {
+ // Don't hide a (potentially) valid declaration with an invalid one.
+ } else {
+ NamedDecl *DeclToAdd = (TemplateParams
+ ? cast<NamedDecl>(FunctionTemplate)
+ : Method);
+ if (isFriend)
+ Record->makeDeclVisibleInContext(DeclToAdd);
+ else
+ Owner->addDecl(DeclToAdd);
+ }
+
+ return Method;
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ return VisitCXXMethodDecl(D);
+}
+
+ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
+ return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>());
+}
+
+Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
+ TemplateTypeParmDecl *D) {
+ // TODO: don't always clone when decls are refcounted.
+ const Type* T = D->getTypeForDecl();
+ assert(T->isTemplateTypeParmType());
+ const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>();
+
+ TemplateTypeParmDecl *Inst =
+ TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ TTPT->getDepth() - TemplateArgs.getNumLevels(),
+ TTPT->getIndex(), D->getIdentifier(),
+ D->wasDeclaredWithTypename(),
+ D->isParameterPack());
+
+ if (D->hasDefaultArgument())
+ Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+
+ return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
+ NonTypeTemplateParmDecl *D) {
+ // Substitute into the type of the non-type template parameter.
+ TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
+ llvm::SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten;
+ llvm::SmallVector<QualType, 4> ExpandedParameterPackTypes;
+ bool IsExpandedParameterPack = false;
+ TypeSourceInfo *DI;
+ QualType T;
+ bool Invalid = false;
+
+ if (D->isExpandedParameterPack()) {
+ // The non-type template parameter pack is an already-expanded pack
+ // expansion of types. Substitute into each of the expanded types.
+ ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
+ ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
+ for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+ TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
+ TemplateArgs,
+ D->getLocation(),
+ D->getDeclName());
+ if (!NewDI)
+ return 0;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
+ QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
+ D->getLocation());
+ if (NewT.isNull())
+ return 0;
+ ExpandedParameterPackTypes.push_back(NewT);
+ }
+
+ IsExpandedParameterPack = true;
+ DI = D->getTypeSourceInfo();
+ T = DI->getType();
+ } else if (isa<PackExpansionTypeLoc>(TL)) {
+ // The non-type template parameter pack's type is a pack expansion of types.
+ // Determine whether we need to expand this parameter pack into separate
+ // types.
+ PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL);
+ TypeLoc Pattern = Expansion.getPatternLoc();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> OrigNumExpansions
+ = Expansion.getTypePtr()->getNumExpansions();
+ llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(),
+ Pattern.getSourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ TemplateArgs,
+ Expand, RetainExpansion,
+ NumExpansions))
+ return 0;
+
+ if (Expand) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
+ TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs,
+ D->getLocation(),
+ D->getDeclName());
+ if (!NewDI)
+ return 0;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
+ QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
+ NewDI->getType(),
+ D->getLocation());
+ if (NewT.isNull())
+ return 0;
+ ExpandedParameterPackTypes.push_back(NewT);
+ }
+
+ // Note that we have an expanded parameter pack. The "type" of this
+ // expanded parameter pack is the original expansion type, but callers
+ // will end up using the expanded parameter pack types for type-checking.
+ IsExpandedParameterPack = true;
+ DI = D->getTypeSourceInfo();
+ T = DI->getType();
+ } else {
+ // We cannot fully expand the pack expansion now, so substitute into the
+ // pattern and create a new pack expansion type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+ TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs,
+ D->getLocation(),
+ D->getDeclName());
+ if (!NewPattern)
+ return 0;
+
+ DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
+ NumExpansions);
+ if (!DI)
+ return 0;
+
+ T = DI->getType();
+ }
+ } else {
+ // Simple case: substitution into a parameter that is not a parameter pack.
+ DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI)
+ return 0;
+
+ // Check that this type is acceptable for a non-type template parameter.
+ bool Invalid = false;
+ T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
+ D->getLocation());
+ if (T.isNull()) {
+ T = SemaRef.Context.IntTy;
+ Invalid = true;
+ }
+ }
+
+ NonTypeTemplateParmDecl *Param;
+ if (IsExpandedParameterPack)
+ Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(),
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getPosition(),
+ D->getIdentifier(), T,
+ DI,
+ ExpandedParameterPackTypes.data(),
+ ExpandedParameterPackTypes.size(),
+ ExpandedParameterPackTypesAsWritten.data());
+ else
+ Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(),
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getPosition(),
+ D->getIdentifier(), T,
+ D->isParameterPack(), DI);
+
+ if (Invalid)
+ Param->setInvalidDecl();
+
+ Param->setDefaultArgument(D->getDefaultArgument(), false);
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+ return Param;
+}
+
+Decl *
+TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
+ TemplateTemplateParmDecl *D) {
+ // Instantiate the template parameter list of the template template parameter.
+ TemplateParameterList *TempParams = D->getTemplateParameters();
+ TemplateParameterList *InstParams;
+ {
+ // Perform the actual substitution of template parameters within a new,
+ // local instantiation scope.
+ LocalInstantiationScope Scope(SemaRef);
+ InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return NULL;
+ }
+
+ // Build the template template parameter.
+ TemplateTemplateParmDecl *Param
+ = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getPosition(), D->isParameterPack(),
+ D->getIdentifier(), InstParams);
+ Param->setDefaultArgument(D->getDefaultArgument(), false);
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
+
+ return Param;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Using directives are never dependent, so they require no explicit
+
+ UsingDirectiveDecl *Inst
+ = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getNamespaceKeyLocation(),
+ D->getQualifierRange(), D->getQualifier(),
+ D->getIdentLocation(),
+ D->getNominatedNamespace(),
+ D->getCommonAncestor());
+ Owner->addDecl(Inst);
+ return Inst;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+
+ // The nested name specifier may be dependent, for example
+ // template <typename T> struct t {
+ // struct s1 { T f1(); };
+ // struct s2 : s1 { using s1::f1; };
+ // };
+ // template struct t<int>;
+ // Here, in using s1::f1, s1 refers to t<T>::s1;
+ // we need to substitute for t<int>::s1.
+ NestedNameSpecifier *NNS =
+ SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(),
+ D->getNestedNameRange(),
+ TemplateArgs);
+ if (!NNS)
+ return 0;
+
+ // The name info is non-dependent, so no transformation
+ // is required.
+ DeclarationNameInfo NameInfo = D->getNameInfo();
+
+ // We only need to do redeclaration lookups if we're in a class
+ // scope (in fact, it's not really even possible in non-class
+ // scopes).
+ bool CheckRedeclaration = Owner->isRecord();
+
+ LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
+ Sema::ForRedeclaration);
+
+ UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+ D->getNestedNameRange(),
+ D->getUsingLocation(),
+ NNS,
+ NameInfo,
+ D->isTypeName());
+
+ CXXScopeSpec SS;
+ SS.setScopeRep(NNS);
+ SS.setRange(D->getNestedNameRange());
+
+ if (CheckRedeclaration) {
+ Prev.setHideTags(false);
+ SemaRef.LookupQualifiedName(Prev, Owner);
+
+ // Check for invalid redeclarations.
+ if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
+ D->isTypeName(), SS,
+ D->getLocation(), Prev))
+ NewUD->setInvalidDecl();
+
+ }
+
+ if (!NewUD->isInvalidDecl() &&
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+ D->getLocation()))
+ NewUD->setInvalidDecl();
+
+ SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+ NewUD->setAccess(D->getAccess());
+ Owner->addDecl(NewUD);
+
+ // Don't process the shadow decls for an invalid decl.
+ if (NewUD->isInvalidDecl())
+ return NewUD;
+
+ bool isFunctionScope = Owner->isFunctionOrMethod();
+
+ // Process the shadow decls.
+ for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
+ I != E; ++I) {
+ UsingShadowDecl *Shadow = *I;
+ NamedDecl *InstTarget =
+ cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getLocation(),
+ Shadow->getTargetDecl(),
+ TemplateArgs));
+
+ if (CheckRedeclaration &&
+ SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
+ continue;
+
+ UsingShadowDecl *InstShadow
+ = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+ SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+
+ if (isFunctionScope)
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
+ }
+
+ return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ // Ignore these; we handle them in bulk when processing the UsingDecl.
+ return 0;
+}
+
+Decl * TemplateDeclInstantiator
+ ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ NestedNameSpecifier *NNS =
+ SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+ D->getTargetNestedNameRange(),
+ TemplateArgs);
+ if (!NNS)
+ return 0;
+
+ CXXScopeSpec SS;
+ SS.setRange(D->getTargetNestedNameRange());
+ SS.setScopeRep(NNS);
+
+ // Since NameInfo refers to a typename, it cannot be a C++ special name.
+ // Hence, no tranformation is required for it.
+ DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
+ NamedDecl *UD =
+ SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, 0,
+ /*instantiation*/ true,
+ /*typename*/ true, D->getTypenameLoc());
+ if (UD)
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+ return UD;
+}
+
+Decl * TemplateDeclInstantiator
+ ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ NestedNameSpecifier *NNS =
+ SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+ D->getTargetNestedNameRange(),
+ TemplateArgs);
+ if (!NNS)
+ return 0;
+
+ CXXScopeSpec SS;
+ SS.setRange(D->getTargetNestedNameRange());
+ SS.setScopeRep(NNS);
+
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+
+ NamedDecl *UD =
+ SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+ D->getUsingLoc(), SS, NameInfo, 0,
+ /*instantiation*/ true,
+ /*typename*/ false, SourceLocation());
+ if (UD)
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
+ return UD;
+}
+
+Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
+ if (D->isInvalidDecl())
+ return 0;
+
+ return Instantiator.Visit(D);
+}
+
+/// \brief Instantiates a nested template parameter list in the current
+/// instantiation context.
+///
+/// \param L The parameter list to instantiate
+///
+/// \returns NULL if there was an error
+TemplateParameterList *
+TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
+ // Get errors for all the parameters before bailing out.
+ bool Invalid = false;
+
+ unsigned N = L->size();
+ typedef llvm::SmallVector<NamedDecl *, 8> ParamVector;
+ ParamVector Params;
+ Params.reserve(N);
+ for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
+ PI != PE; ++PI) {
+ NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
+ Params.push_back(D);
+ Invalid = Invalid || !D || D->isInvalidDecl();
+ }
+
+ // Clean up if we had an error.
+ if (Invalid)
+ return NULL;
+
+ TemplateParameterList *InstL
+ = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
+ L->getLAngleLoc(), &Params.front(), N,
+ L->getRAngleLoc());
+ return InstL;
+}
+
+/// \brief Instantiate the declaration of a class template partial
+/// specialization.
+///
+/// \param ClassTemplate the (instantiated) class template that is partially
+// specialized by the instantiation of \p PartialSpec.
+///
+/// \param PartialSpec the (uninstantiated) class template partial
+/// specialization that we are instantiating.
+///
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+ClassTemplatePartialSpecializationDecl *
+TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ // Create a local instantiation scope for this class template partial
+ // specialization, which will contain the instantiations of the template
+ // parameters.
+ LocalInstantiationScope Scope(SemaRef);
+
+ // Substitute into the template parameters of the class template partial
+ // specialization.
+ TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
+ TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ if (!InstParams)
+ return 0;
+
+ // Substitute into the template arguments of the class template partial
+ // specialization.
+ TemplateArgumentListInfo InstTemplateArgs; // no angle locations
+ if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(),
+ PartialSpec->getNumTemplateArgsAsWritten(),
+ InstTemplateArgs, TemplateArgs))
+ return 0;
+
+ // Check that the template argument list is well-formed for this
+ // class template.
+ llvm::SmallVector<TemplateArgument, 4> Converted;
+ if (SemaRef.CheckTemplateArgumentList(ClassTemplate,
+ PartialSpec->getLocation(),
+ InstTemplateArgs,
+ false,
+ Converted))
+ return 0;
+
+ // Figure out where to insert this class template partial specialization
+ // in the member template's set of class template partial specializations.
+ void *InsertPos = 0;
+ ClassTemplateSpecializationDecl *PrevDecl
+ = ClassTemplate->findPartialSpecialization(Converted.data(),
+ Converted.size(), InsertPos);
+
+ // Build the canonical type that describes the converted template
+ // arguments of the class template partial specialization.
+ QualType CanonType
+ = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
+ Converted.data(),
+ Converted.size());
+
+ // Build the fully-sugared type for this class template
+ // specialization as the user wrote in the specialization
+ // itself. This means that we'll pretty-print the type retrieved
+ // from the specialization's declaration the way that the user
+ // actually wrote the specialization, rather than formatting the
+ // name based on the "canonical" representation used to store the
+ // template arguments in the specialization.
+ TypeSourceInfo *WrittenTy
+ = SemaRef.Context.getTemplateSpecializationTypeInfo(
+ TemplateName(ClassTemplate),
+ PartialSpec->getLocation(),
+ InstTemplateArgs,
+ CanonType);
+
+ if (PrevDecl) {
+ // We've already seen a partial specialization with the same template
+ // parameters and template arguments. This can happen, for example, when
+ // substituting the outer template arguments ends up causing two
+ // class template partial specializations of a member class template
+ // to have identical forms, e.g.,
+ //
+ // template<typename T, typename U>
+ // struct Outer {
+ // template<typename X, typename Y> struct Inner;
+ // template<typename Y> struct Inner<T, Y>;
+ // template<typename Y> struct Inner<U, Y>;
+ // };
+ //
+ // Outer<int, int> outer; // error: the partial specializations of Inner
+ // // have the same signature.
+ SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
+ << WrittenTy->getType();
+ SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
+ << SemaRef.Context.getTypeDeclType(PrevDecl);
+ return 0;
+ }
+
+
+ // Create the class template partial specialization declaration.
+ ClassTemplatePartialSpecializationDecl *InstPartialSpec
+ = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context,
+ PartialSpec->getTagKind(),
+ Owner,
+ PartialSpec->getLocation(),
+ InstParams,
+ ClassTemplate,
+ Converted.data(),
+ Converted.size(),
+ InstTemplateArgs,
+ CanonType,
+ 0,
+ ClassTemplate->getNextPartialSpecSequenceNumber());
+ // Substitute the nested name specifier, if any.
+ if (SubstQualifier(PartialSpec, InstPartialSpec))
+ return 0;
+
+ InstPartialSpec->setInstantiatedFromMember(PartialSpec);
+ InstPartialSpec->setTypeAsWritten(WrittenTy);
+
+ // Add this partial specialization to the set of class template partial
+ // specializations.
+ ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
+ return InstPartialSpec;
+}
+
+TypeSourceInfo*
+TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
+ llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
+ TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
+ assert(OldTInfo && "substituting function without type source info");
+ assert(Params.empty() && "parameter vector is non-empty at start");
+ TypeSourceInfo *NewTInfo
+ = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
+ D->getTypeSpecStartLoc(),
+ D->getDeclName());
+ if (!NewTInfo)
+ return 0;
+
+ if (NewTInfo != OldTInfo) {
+ // Get parameters from the new type info.
+ TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
+ if (FunctionProtoTypeLoc *OldProtoLoc
+ = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
+ TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
+ FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
+ assert(NewProtoLoc && "Missing prototype?");
+ unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs();
+ for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs();
+ OldIdx != NumOldParams; ++OldIdx) {
+ ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
+ if (!OldParam->isParameterPack() ||
+ (NewIdx < NumNewParams &&
+ NewProtoLoc->getArg(NewIdx)->isParameterPack())) {
+ // Simple case: normal parameter, or a parameter pack that's
+ // instantiated to a (still-dependent) parameter pack.
+ ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ Params.push_back(NewParam);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam,
+ NewParam);
+ continue;
+ }
+
+ // Parameter pack: make the instantiation an argument pack.
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
+ OldParam);
+ unsigned NumArgumentsInExpansion
+ = SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
+ TemplateArgs);
+ while (NumArgumentsInExpansion--) {
+ ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ Params.push_back(NewParam);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam,
+ NewParam);
+ }
+ }
+ }
+ } else {
+ // The function type itself was not dependent and therefore no
+ // substitution occurred. However, we still need to instantiate
+ // the function parameters themselves.
+ TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
+ if (FunctionProtoTypeLoc *OldProtoLoc
+ = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
+ for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) {
+ ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc->getArg(i));
+ if (!Parm)
+ return 0;
+ Params.push_back(Parm);
+ }
+ }
+ }
+ return NewTInfo;
+}
+
+/// \brief Initializes the common fields of an instantiation function
+/// declaration (New) from the corresponding fields of its template (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
+ FunctionDecl *Tmpl) {
+ if (Tmpl->isDeleted())
+ New->setDeleted();
+
+ // If we are performing substituting explicitly-specified template arguments
+ // or deduced template arguments into a function template and we reach this
+ // point, we are now past the point where SFINAE applies and have committed
+ // to keeping the new function template specialization. We therefore
+ // convert the active template instantiation for the function template
+ // into a template instantiation for this specific function template
+ // specialization, which is not a SFINAE context, so that we diagnose any
+ // further errors in the declaration itself.
+ typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+ ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+ if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+ ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+ if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+ assert(FunTmpl->getTemplatedDecl() == Tmpl &&
+ "Deduction from the wrong function template?");
+ (void) FunTmpl;
+ ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+ ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+ --SemaRef.NonInstantiationEntries;
+ }
+ }
+
+ const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>();
+ assert(Proto && "Function template without prototype?");
+
+ if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() ||
+ Proto->getNoReturnAttr()) {
+ // The function has an exception specification or a "noreturn"
+ // attribute. Substitute into each of the exception types.
+ llvm::SmallVector<QualType, 4> Exceptions;
+ for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+ // FIXME: Poor location information!
+ if (const PackExpansionType *PackExpansion
+ = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+ // We have a pack expansion. Instantiate it.
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+ Unexpanded);
+ assert(!Unexpanded.empty() &&
+ "Pack expansion without parameter packs?");
+
+ bool Expand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions
+ = PackExpansion->getNumExpansions();
+ if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
+ SourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ TemplateArgs,
+ Expand,
+ RetainExpansion,
+ NumExpansions))
+ break;
+
+ if (!Expand) {
+ // We can't expand this pack expansion into separate arguments yet;
+ // just substitute into the pattern and create a new pack expansion
+ // type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull())
+ break;
+
+ T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
+ Exceptions.push_back(T);
+ continue;
+ }
+
+ // Substitute into the pack expansion pattern for each template
+ bool Invalid = false;
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull()) {
+ Invalid = true;
+ break;
+ }
+
+ Exceptions.push_back(T);
+ }
+
+ if (Invalid)
+ break;
+
+ continue;
+ }
+
+ QualType T
+ = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull() ||
+ SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+ continue;
+
+ Exceptions.push_back(T);
+ }
+
+ // Rebuild the function type
+
+ FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ EPI.HasExceptionSpec = Proto->hasExceptionSpec();
+ EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec();
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ EPI.ExtInfo = Proto->getExtInfo();
+
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+ assert(NewProto && "Template instantiation without function prototype?");
+ New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI));
+ }
+
+ SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New);
+
+ return false;
+}
+
+/// \brief Initializes common fields of an instantiated method
+/// declaration (New) from the corresponding fields of its template
+/// (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
+ CXXMethodDecl *Tmpl) {
+ if (InitFunctionInstantiation(New, Tmpl))
+ return true;
+
+ New->setAccess(Tmpl->getAccess());
+ if (Tmpl->isVirtualAsWritten())
+ New->setVirtualAsWritten(true);
+
+ // FIXME: attributes
+ // FIXME: New needs a pointer to Tmpl
+ return false;
+}
+
+/// \brief Instantiate the definition of the given function from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Function the already-instantiated declaration of a
+/// function template specialization or member function of a class template
+/// specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where the body of the function is required. Complain if
+/// there is no such body.
+void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function,
+ bool Recursive,
+ bool DefinitionRequired) {
+ if (Function->isInvalidDecl() || Function->hasBody())
+ return;
+
+ // Never instantiate an explicit specialization.
+ if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return;
+
+ // Find the function body that we'll be substituting.
+ const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
+ Stmt *Pattern = 0;
+ if (PatternDecl)
+ Pattern = PatternDecl->getBody(PatternDecl);
+
+ if (!Pattern) {
+ if (DefinitionRequired) {
+ if (Function->getPrimaryTemplate())
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_func_template)
+ << Function->getPrimaryTemplate();
+ else
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << 1 << Function->getDeclName() << Function->getDeclContext();
+
+ if (PatternDecl)
+ Diag(PatternDecl->getLocation(),
+ diag::note_explicit_instantiation_here);
+ Function->setInvalidDecl();
+ } else if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
+ }
+
+ return;
+ }
+
+ // C++0x [temp.explicit]p9:
+ // Except for inline functions, other explicit instantiation declarations
+ // have the effect of suppressing the implicit instantiation of the entity
+ // to which they refer.
+ if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration &&
+ !PatternDecl->isInlined())
+ return;
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
+ if (Inst)
+ return;
+
+ // If we're performing recursive template instantiation, create our own
+ // queue of pending implicit instantiations that we will instantiate later,
+ // while we're still within our own instantiation context.
+ llvm::SmallVector<VTableUse, 16> SavedVTableUses;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ if (Recursive) {
+ VTableUses.swap(SavedVTableUses);
+ PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+
+ EnterExpressionEvaluationContext EvalContext(*this,
+ Sema::PotentiallyEvaluated);
+ ActOnStartOfFunctionDef(0, Function);
+
+ // Introduce a new scope where local variable instantiations will be
+ // recorded, unless we're actually a member function within a local
+ // class, in which case we need to merge our results with the parent
+ // scope (of the enclosing function).
+ bool MergeWithParentScope = false;
+ if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
+ MergeWithParentScope = Rec->isLocalClass();
+
+ LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+ // Introduce the instantiated function parameters into the local
+ // instantiation scope, and set the parameter names to those used
+ // in the template.
+ unsigned FParamIdx = 0;
+ for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+ const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+ if (!PatternParam->isParameterPack()) {
+ // Simple case: not a parameter pack.
+ assert(FParamIdx < Function->getNumParams());
+ ParmVarDecl *FunctionParam = Function->getParamDecl(I);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ ++FParamIdx;
+ continue;
+ }
+
+ // Expand the parameter pack.
+ Scope.MakeInstantiatedLocalArgPack(PatternParam);
+ for (unsigned NumFParams = Function->getNumParams();
+ FParamIdx < NumFParams;
+ ++FParamIdx) {
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ }
+ }
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ Sema::ContextRAII savedContext(*this, Function);
+
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
+
+ // If this is a constructor, instantiate the member initializers.
+ if (const CXXConstructorDecl *Ctor =
+ dyn_cast<CXXConstructorDecl>(PatternDecl)) {
+ InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
+ TemplateArgs);
+ }
+
+ // Instantiate the function body.
+ StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+
+ if (Body.isInvalid())
+ Function->setInvalidDecl();
+
+ ActOnFinishFunctionBody(Function, Body.get(),
+ /*IsInstantiation=*/true);
+
+ PerformDependentDiagnostics(PatternDecl, TemplateArgs);
+
+ savedContext.pop();
+
+ DeclGroupRef DG(Function);
+ Consumer.HandleTopLevelDecl(DG);
+
+ // This class may have local implicit instantiations that need to be
+ // instantiation within this scope.
+ PerformPendingInstantiations(/*LocalOnly=*/true);
+ Scope.Exit();
+
+ if (Recursive) {
+ // Define any pending vtables.
+ DefineUsedVTables();
+
+ // Instantiate any pending implicit instantiations found during the
+ // instantiation of this template.
+ PerformPendingInstantiations();
+
+ // Restore the set of pending vtables.
+ VTableUses.swap(SavedVTableUses);
+
+ // Restore the set of pending implicit instantiations.
+ PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+}
+
+/// \brief Instantiate the definition of the given variable from its
+/// template.
+///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
+/// \param Var the already-instantiated declaration of a static member
+/// variable of a class template specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where an out-of-line definition of the member variable
+/// is required. Complain if there is no such definition.
+void Sema::InstantiateStaticDataMemberDefinition(
+ SourceLocation PointOfInstantiation,
+ VarDecl *Var,
+ bool Recursive,
+ bool DefinitionRequired) {
+ if (Var->isInvalidDecl())
+ return;
+
+ // Find the out-of-line definition of this static data member.
+ VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
+ assert(Def && "This data member was not instantiated from a template?");
+ assert(Def->isStaticDataMember() && "Not a static data member?");
+ Def = Def->getOutOfLineDefinition();
+
+ if (!Def) {
+ // We did not find an out-of-line definition of this static data member,
+ // so we won't perform any instantiation. Rather, we rely on the user to
+ // instantiate this definition (or provide a specialization for it) in
+ // another translation unit.
+ if (DefinitionRequired) {
+ Def = Var->getInstantiatedFromStaticDataMember();
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << 2 << Var->getDeclName() << Var->getDeclContext();
+ Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+ } else if (Var->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingInstantiations.push_back(
+ std::make_pair(Var, PointOfInstantiation));
+ }
+
+ return;
+ }
+
+ // Never instantiate an explicit specialization.
+ if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return;
+
+ // C++0x [temp.explicit]p9:
+ // Except for inline functions, other explicit instantiation declarations
+ // have the effect of suppressing the implicit instantiation of the entity
+ // to which they refer.
+ if (Var->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return;
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
+ if (Inst)
+ return;
+
+ // If we're performing recursive template instantiation, create our own
+ // queue of pending implicit instantiations that we will instantiate later,
+ // while we're still within our own instantiation context.
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ if (Recursive)
+ PendingInstantiations.swap(SavedPendingInstantiations);
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ ContextRAII previousContext(*this, Var->getDeclContext());
+
+ VarDecl *OldVar = Var;
+ Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
+ getTemplateInstantiationArgs(Var)));
+
+ previousContext.pop();
+
+ if (Var) {
+ MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation());
+ DeclGroupRef DG(Var);
+ Consumer.HandleTopLevelDecl(DG);
+ }
+
+ if (Recursive) {
+ // Instantiate any pending implicit instantiations found during the
+ // instantiation of this template.
+ PerformPendingInstantiations();
+
+ // Restore the set of pending implicit instantiations.
+ PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+}
+
+void
+Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
+ const CXXConstructorDecl *Tmpl,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+ llvm::SmallVector<MemInitTy*, 4> NewInits;
+ bool AnyErrors = false;
+
+ // Instantiate all the initializers.
+ for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
+ InitsEnd = Tmpl->init_end();
+ Inits != InitsEnd; ++Inits) {
+ CXXCtorInitializer *Init = *Inits;
+
+ // Only instantiate written initializers, let Sema re-construct implicit
+ // ones.
+ if (!Init->isWritten())
+ continue;
+
+ SourceLocation LParenLoc, RParenLoc;
+ ASTOwningVector<Expr*> NewArgs(*this);
+
+ SourceLocation EllipsisLoc;
+
+ if (Init->isPackExpansion()) {
+ // This is a pack expansion. We should expand it now.
+ TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(BaseTL, Unexpanded);
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions;
+ if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
+ BaseTL.getSourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ TemplateArgs, ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
+ AnyErrors = true;
+ New->setInvalidDecl();
+ continue;
+ }
+ assert(ShouldExpand && "Partial instantiation of base initializer?");
+
+ // Loop over all of the arguments in the argument pack(s),
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+ // Instantiate the initializer.
+ if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs,
+ LParenLoc, NewArgs, RParenLoc)) {
+ AnyErrors = true;
+ break;
+ }
+
+ // Instantiate the base type.
+ TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
+ TemplateArgs,
+ Init->getSourceLocation(),
+ New->getDeclName());
+ if (!BaseTInfo) {
+ AnyErrors = true;
+ break;
+ }
+
+ // Build the initializer.
+ MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
+ BaseTInfo,
+ (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getLParenLoc(),
+ Init->getRParenLoc(),
+ New->getParent(),
+ SourceLocation());
+ if (NewInit.isInvalid()) {
+ AnyErrors = true;
+ break;
+ }
+
+ NewInits.push_back(NewInit.get());
+ NewArgs.clear();
+ }
+
+ continue;
+ }
+
+ // Instantiate the initializer.
+ if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs,
+ LParenLoc, NewArgs, RParenLoc)) {
+ AnyErrors = true;
+ continue;
+ }
+
+ MemInitResult NewInit;
+ if (Init->isBaseInitializer()) {
+ TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
+ TemplateArgs,
+ Init->getSourceLocation(),
+ New->getDeclName());
+ if (!BaseTInfo) {
+ AnyErrors = true;
+ New->setInvalidDecl();
+ continue;
+ }
+
+ NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo,
+ (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getLParenLoc(),
+ Init->getRParenLoc(),
+ New->getParent(),
+ EllipsisLoc);
+ } else if (Init->isMemberInitializer()) {
+ FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl(
+ Init->getMemberLocation(),
+ Init->getMember(),
+ TemplateArgs));
+
+ NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getSourceLocation(),
+ Init->getLParenLoc(),
+ Init->getRParenLoc());
+ } else if (Init->isIndirectMemberInitializer()) {
+ IndirectFieldDecl *IndirectMember =
+ cast<IndirectFieldDecl>(FindInstantiatedDecl(
+ Init->getMemberLocation(),
+ Init->getIndirectMember(), TemplateArgs));
+
+ NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getSourceLocation(),
+ Init->getLParenLoc(),
+ Init->getRParenLoc());
+ }
+
+ if (NewInit.isInvalid()) {
+ AnyErrors = true;
+ New->setInvalidDecl();
+ } else {
+ // FIXME: It would be nice if ASTOwningVector had a release function.
+ NewArgs.take();
+
+ NewInits.push_back((MemInitTy *)NewInit.get());
+ }
+ }
+
+ // Assign all the initializers to the new constructor.
+ ActOnMemInitializers(New,
+ /*FIXME: ColonLoc */
+ SourceLocation(),
+ NewInits.data(), NewInits.size(),
+ AnyErrors);
+}
+
+// TODO: this could be templated if the various decl types used the
+// same method name.
+static bool isInstantiationOf(ClassTemplateDecl *Pattern,
+ ClassTemplateDecl *Instance) {
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromMemberTemplate();
+ } while (Instance);
+
+ return false;
+}
+
+static bool isInstantiationOf(FunctionTemplateDecl *Pattern,
+ FunctionTemplateDecl *Instance) {
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromMemberTemplate();
+ } while (Instance);
+
+ return false;
+}
+
+static bool
+isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern,
+ ClassTemplatePartialSpecializationDecl *Instance) {
+ Pattern
+ = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl());
+ do {
+ Instance = cast<ClassTemplatePartialSpecializationDecl>(
+ Instance->getCanonicalDecl());
+ if (Pattern == Instance)
+ return true;
+ Instance = Instance->getInstantiatedFromMember();
+ } while (Instance);
+
+ return false;
+}
+
+static bool isInstantiationOf(CXXRecordDecl *Pattern,
+ CXXRecordDecl *Instance) {
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromMemberClass();
+ } while (Instance);
+
+ return false;
+}
+
+static bool isInstantiationOf(FunctionDecl *Pattern,
+ FunctionDecl *Instance) {
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromMemberFunction();
+ } while (Instance);
+
+ return false;
+}
+
+static bool isInstantiationOf(EnumDecl *Pattern,
+ EnumDecl *Instance) {
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromMemberEnum();
+ } while (Instance);
+
+ return false;
+}
+
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+ UsingShadowDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
+ VarDecl *Instance) {
+ assert(Instance->isStaticDataMember());
+
+ Pattern = Pattern->getCanonicalDecl();
+
+ do {
+ Instance = Instance->getCanonicalDecl();
+ if (Pattern == Instance) return true;
+ Instance = Instance->getInstantiatedFromStaticDataMember();
+ } while (Instance);
+
+ return false;
+}
+
+// Other is the prospective instantiation
+// D is the prospective pattern
+static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
+ if (D->getKind() != Other->getKind()) {
+ if (UnresolvedUsingTypenameDecl *UUD
+ = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+ if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+ return isInstantiationOf(UUD, UD, Ctx);
+ }
+ }
+
+ if (UnresolvedUsingValueDecl *UUD
+ = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+ if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+ return isInstantiationOf(UUD, UD, Ctx);
+ }
+ }
+
+ return false;
+ }
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+ return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+ return isInstantiationOf(cast<FunctionDecl>(D), Function);
+
+ if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+ return isInstantiationOf(cast<EnumDecl>(D), Enum);
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(Other))
+ if (Var->isStaticDataMember())
+ return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
+
+ if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
+ return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
+
+ if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
+ return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
+
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
+ return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
+ PartialSpec);
+
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
+ if (!Field->getDeclName()) {
+ // This is an unnamed field.
+ return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) ==
+ cast<FieldDecl>(D);
+ }
+ }
+
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+ return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+ return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
+ return D->getDeclName() && isa<NamedDecl>(Other) &&
+ D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
+}
+
+template<typename ForwardIterator>
+static NamedDecl *findInstantiationOf(ASTContext &Ctx,
+ NamedDecl *D,
+ ForwardIterator first,
+ ForwardIterator last) {
+ for (; first != last; ++first)
+ if (isInstantiationOf(Ctx, D, *first))
+ return cast<NamedDecl>(*first);
+
+ return 0;
+}
+
+/// \brief Finds the instantiation of the given declaration context
+/// within the current instantiation.
+///
+/// \returns NULL if there was an error
+DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
+ Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs);
+ return cast_or_null<DeclContext>(ID);
+ } else return DC;
+}
+
+/// \brief Find the instantiation of the given declaration within the
+/// current instantiation.
+///
+/// This routine is intended to be used when \p D is a declaration
+/// referenced from within a template, that needs to mapped into the
+/// corresponding declaration within an instantiation. For example,
+/// given:
+///
+/// \code
+/// template<typename T>
+/// struct X {
+/// enum Kind {
+/// KnownValue = sizeof(T)
+/// };
+///
+/// bool getKind() const { return KnownValue; }
+/// };
+///
+/// template struct X<int>;
+/// \endcode
+///
+/// In the instantiation of X<int>::getKind(), we need to map the
+/// EnumConstantDecl for KnownValue (which refers to
+/// X<T>::<Kind>::KnownValue) to its instantiation
+/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
+/// this mapping from within the instantiation of X<int>.
+NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ DeclContext *ParentDC = D->getDeclContext();
+ if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
+ isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
+ (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) {
+ // D is a local of some kind. Look into the map of local
+ // declarations to their instantiations.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
+ = CurrentInstantiationScope->findInstantiationOf(D);
+
+ if (Found) {
+ if (Decl *FD = Found->dyn_cast<Decl *>())
+ return cast<NamedDecl>(FD);
+
+ unsigned PackIdx = ArgumentPackSubstitutionIndex;
+ return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
+ }
+
+ // If we didn't find the decl, then we must have a label decl that hasn't
+ // been found yet. Lazily instantiate it and return it now.
+ assert(isa<LabelDecl>(D));
+
+ Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
+ assert(Inst && "Failed to instantiate label??");
+
+ CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+ return cast<LabelDecl>(Inst);
+ }
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+ if (!Record->isDependentContext())
+ return D;
+
+ // If the RecordDecl is actually the injected-class-name or a
+ // "templated" declaration for a class template, class template
+ // partial specialization, or a member class of a class template,
+ // substitute into the injected-class-name of the class template
+ // or partial specialization to find the new DeclContext.
+ QualType T;
+ ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
+
+ if (ClassTemplate) {
+ T = ClassTemplate->getInjectedClassNameSpecialization();
+ } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+ ClassTemplate = PartialSpec->getSpecializedTemplate();
+
+ // If we call SubstType with an InjectedClassNameType here we
+ // can end up in an infinite loop.
+ T = Context.getTypeDeclType(Record);
+ assert(isa<InjectedClassNameType>(T) &&
+ "type of partial specialization is not an InjectedClassNameType");
+ T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+ }
+
+ if (!T.isNull()) {
+ // Substitute into the injected-class-name to get the type
+ // corresponding to the instantiation we want, which may also be
+ // the current instantiation (if we're in a template
+ // definition). This substitution should never fail, since we
+ // know we can instantiate the injected-class-name or we
+ // wouldn't have gotten to the injected-class-name!
+
+ // FIXME: Can we use the CurrentInstantiationScope to avoid this
+ // extra instantiation in the common case?
+ T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
+ assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
+
+ if (!T->isDependentType()) {
+ assert(T->isRecordType() && "Instantiation must produce a record type");
+ return T->getAs<RecordType>()->getDecl();
+ }
+
+ // We are performing "partial" template instantiation to create
+ // the member declarations for the members of a class template
+ // specialization. Therefore, D is actually referring to something
+ // in the current instantiation. Look through the current
+ // context, which contains actual instantiations, to find the
+ // instantiation of the "current instantiation" that D refers
+ // to.
+ bool SawNonDependentContext = false;
+ for (DeclContext *DC = CurContext; !DC->isFileContext();
+ DC = DC->getParent()) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+ if (isInstantiationOf(ClassTemplate,
+ Spec->getSpecializedTemplate()))
+ return Spec;
+
+ if (!DC->isDependentContext())
+ SawNonDependentContext = true;
+ }
+
+ // We're performing "instantiation" of a member of the current
+ // instantiation while we are type-checking the
+ // definition. Compute the declaration context and return that.
+ assert(!SawNonDependentContext &&
+ "No dependent context while instantiating record");
+ DeclContext *DC = computeDeclContext(T);
+ assert(DC &&
+ "Unable to find declaration for the current instantiation");
+ return cast<CXXRecordDecl>(DC);
+ }
+
+ // Fall through to deal with other dependent record types (e.g.,
+ // anonymous unions in class templates).
+ }
+
+ if (!ParentDC->isDependentContext())
+ return D;
+
+ ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
+ if (!ParentDC)
+ return 0;
+
+ if (ParentDC != D->getDeclContext()) {
+ // We performed some kind of instantiation in the parent context,
+ // so now we need to look into the instantiated parent context to
+ // find the instantiation of the declaration D.
+
+ // If our context used to be dependent, we may need to instantiate
+ // it before performing lookup into that context.
+ if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
+ if (!Spec->isDependentContext()) {
+ QualType T = Context.getTypeDeclType(Spec);
+ const RecordType *Tag = T->getAs<RecordType>();
+ assert(Tag && "type of non-dependent record is not a RecordType");
+ if (!Tag->isBeingDefined() &&
+ RequireCompleteType(Loc, T, diag::err_incomplete_type))
+ return 0;
+
+ ParentDC = Tag->getDecl();
+ }
+ }
+
+ NamedDecl *Result = 0;
+ if (D->getDeclName()) {
+ DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
+ Result = findInstantiationOf(Context, D, Found.first, Found.second);
+ } else {
+ // Since we don't have a name for the entity we're looking for,
+ // our only option is to walk through all of the declarations to
+ // find that name. This will occur in a few cases:
+ //
+ // - anonymous struct/union within a template
+ // - unnamed class/struct/union/enum within a template
+ //
+ // FIXME: Find a better way to find these instantiations!
+ Result = findInstantiationOf(Context, D,
+ ParentDC->decls_begin(),
+ ParentDC->decls_end());
+ }
+
+ // UsingShadowDecls can instantiate to nothing because of using hiding.
+ assert((Result || isa<UsingShadowDecl>(D) || D->isInvalidDecl() ||
+ cast<Decl>(ParentDC)->isInvalidDecl())
+ && "Unable to find instantiation of declaration!");
+
+ D = Result;
+ }
+
+ return D;
+}
+
+/// \brief Performs template instantiation for all implicit template
+/// instantiations we have seen until this point.
+void Sema::PerformPendingInstantiations(bool LocalOnly) {
+ while (!PendingLocalImplicitInstantiations.empty() ||
+ (!LocalOnly && !PendingInstantiations.empty())) {
+ PendingImplicitInstantiation Inst;
+
+ if (PendingLocalImplicitInstantiations.empty()) {
+ Inst = PendingInstantiations.front();
+ PendingInstantiations.pop_front();
+ } else {
+ Inst = PendingLocalImplicitInstantiations.front();
+ PendingLocalImplicitInstantiations.pop_front();
+ }
+
+ // Instantiate function definitions
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
+ PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+ "instantiating function definition");
+ bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
+ DefinitionRequired);
+ continue;
+ }
+
+ // Instantiate static data member definitions.
+ VarDecl *Var = cast<VarDecl>(Inst.first);
+ assert(Var->isStaticDataMember() && "Not a static data member?");
+
+ // Don't try to instantiate declarations if the most recent redeclaration
+ // is invalid.
+ if (Var->getMostRecentDeclaration()->isInvalidDecl())
+ continue;
+
+ // Check if the most recent declaration has changed the specialization kind
+ // and removed the need for implicit instantiation.
+ switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ assert(false && "Cannot instantitiate an undeclared specialization.");
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitSpecialization:
+ continue; // No longer need to instantiate this type.
+ case TSK_ExplicitInstantiationDefinition:
+ // We only need an instantiation if the pending instantiation *is* the
+ // explicit instantiation.
+ if (Var != Var->getMostRecentDeclaration()) continue;
+ case TSK_ImplicitInstantiation:
+ break;
+ }
+
+ PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
+ "instantiating static data member "
+ "definition");
+
+ bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
+ DefinitionRequired);
+ }
+}
+
+void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(),
+ E = Pattern->ddiag_end(); I != E; ++I) {
+ DependentDiagnostic *DD = *I;
+
+ switch (DD->getKind()) {
+ case DependentDiagnostic::Access:
+ HandleDependentAccessCheck(*DD, TemplateArgs);
+ break;
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
new file mode 100644
index 0000000..0da801c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -0,0 +1,748 @@
+//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements semantic analysis for C++0x variadic templates.
+//===----------------------------------------------------------------------===/
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TypeLoc.h"
+
+using namespace clang;
+
+//----------------------------------------------------------------------------
+// Visitor that collects unexpanded parameter packs
+//----------------------------------------------------------------------------
+
+namespace {
+ /// \brief A class that collects unexpanded parameter packs.
+ class CollectUnexpandedParameterPacksVisitor :
+ public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
+ {
+ typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor>
+ inherited;
+
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
+
+ public:
+ explicit CollectUnexpandedParameterPacksVisitor(
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
+ : Unexpanded(Unexpanded) { }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ //------------------------------------------------------------------------
+ // Recording occurrences of (unexpanded) parameter packs.
+ //------------------------------------------------------------------------
+
+ /// \brief Record occurrences of template type parameter packs.
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ if (TL.getTypePtr()->isParameterPack())
+ Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc()));
+ return true;
+ }
+
+ /// \brief Record occurrences of template type parameter packs
+ /// when we don't have proper source-location information for
+ /// them.
+ ///
+ /// Ideally, this routine would never be used.
+ bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+ if (T->isParameterPack())
+ Unexpanded.push_back(std::make_pair(T, SourceLocation()));
+
+ return true;
+ }
+
+ /// \brief Record occurrences of function and non-type template
+ /// parameter packs in an expression.
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ if (E->getDecl()->isParameterPack())
+ Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+
+ return true;
+ }
+
+ // \brief Record occurrences of function and non-type template parameter
+ // packs in a block-captured expression.
+ bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ if (E->getDecl()->isParameterPack())
+ Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
+
+ return true;
+ }
+
+ /// \brief Record occurrences of template template parameter packs.
+ bool TraverseTemplateName(TemplateName Template) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast_or_null<TemplateTemplateParmDecl>(
+ Template.getAsTemplateDecl()))
+ if (TTP->isParameterPack())
+ Unexpanded.push_back(std::make_pair(TTP, SourceLocation()));
+
+ return inherited::TraverseTemplateName(Template);
+ }
+
+ //------------------------------------------------------------------------
+ // Pruning the search for unexpanded parameter packs.
+ //------------------------------------------------------------------------
+
+ /// \brief Suppress traversal into statements and expressions that
+ /// do not contain unexpanded parameter packs.
+ bool TraverseStmt(Stmt *S) {
+ if (Expr *E = dyn_cast_or_null<Expr>(S))
+ if (E->containsUnexpandedParameterPack())
+ return inherited::TraverseStmt(E);
+
+ return true;
+ }
+
+ /// \brief Suppress traversal into types that do not contain
+ /// unexpanded parameter packs.
+ bool TraverseType(QualType T) {
+ if (!T.isNull() && T->containsUnexpandedParameterPack())
+ return inherited::TraverseType(T);
+
+ return true;
+ }
+
+ /// \brief Suppress traversel into types with location information
+ /// that do not contain unexpanded parameter packs.
+ bool TraverseTypeLoc(TypeLoc TL) {
+ if (!TL.getType().isNull() &&
+ TL.getType()->containsUnexpandedParameterPack())
+ return inherited::TraverseTypeLoc(TL);
+
+ return true;
+ }
+
+ /// \brief Suppress traversal of non-parameter declarations, since
+ /// they cannot contain unexpanded parameter packs.
+ bool TraverseDecl(Decl *D) {
+ if (D && isa<ParmVarDecl>(D))
+ return inherited::TraverseDecl(D);
+
+ return true;
+ }
+
+ /// \brief Suppress traversal of template argument pack expansions.
+ bool TraverseTemplateArgument(const TemplateArgument &Arg) {
+ if (Arg.isPackExpansion())
+ return true;
+
+ return inherited::TraverseTemplateArgument(Arg);
+ }
+
+ /// \brief Suppress traversal of template argument pack expansions.
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+ if (ArgLoc.getArgument().isPackExpansion())
+ return true;
+
+ return inherited::TraverseTemplateArgumentLoc(ArgLoc);
+ }
+ };
+}
+
+/// \brief Diagnose all of the unexpanded parameter packs in the given
+/// vector.
+static void
+DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc,
+ Sema::UnexpandedParameterPackContext UPPC,
+ const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ llvm::SmallVector<SourceLocation, 4> Locations;
+ llvm::SmallVector<IdentifierInfo *, 4> Names;
+ llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
+
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ IdentifierInfo *Name = 0;
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
+ Name = TTP->getName();
+ else
+ Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
+
+ if (Name && NamesKnown.insert(Name))
+ Names.push_back(Name);
+
+ if (Unexpanded[I].second.isValid())
+ Locations.push_back(Unexpanded[I].second);
+ }
+
+ DiagnosticBuilder DB
+ = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0)
+ << (int)UPPC
+ : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1)
+ << (int)UPPC << Names[0]
+ : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2)
+ << (int)UPPC << Names[0] << Names[1]
+ : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more)
+ << (int)UPPC << Names[0] << Names[1];
+
+ for (unsigned I = 0, N = Locations.size(); I != N; ++I)
+ DB << SourceRange(Locations[I]);
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+ TypeSourceInfo *T,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ if (!T->getType()->containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
+ T->getTypeLoc());
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ if (!E->containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ if (!SS.getScopeRep() ||
+ !SS.getScopeRep()->containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseNestedNameSpecifier(SS.getScopeRep());
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(),
+ UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+ UnexpandedParameterPackContext UPPC) {
+ // C++0x [temp.variadic]p5:
+ // An appearance of a name of a parameter pack that is not expanded is
+ // ill-formed.
+ switch (NameInfo.getName().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:
+ // FIXME: We shouldn't need this null check!
+ if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
+ return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
+
+ if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
+ return false;
+
+ break;
+ }
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseType(NameInfo.getName().getCXXNameType());
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+ TemplateName Template,
+ UnexpandedParameterPackContext UPPC) {
+
+ if (Template.isNull() || !Template.containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTemplateName(Template);
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded);
+ return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
+ UnexpandedParameterPackContext UPPC) {
+ if (Arg.getArgument().isNull() ||
+ !Arg.getArgument().containsUnexpandedParameterPack())
+ return false;
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTemplateArgumentLoc(Arg);
+ assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
+ DiagnoseUnexpandedParameterPacks(*this, Arg.getLocation(), UPPC, Unexpanded);
+ return true;
+}
+
+void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTemplateArgument(Arg);
+}
+
+void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded)
+ .TraverseTemplateArgumentLoc(Arg);
+}
+
+void Sema::collectUnexpandedParameterPacks(QualType T,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
+}
+
+void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
+}
+
+ParsedTemplateArgument
+Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+ SourceLocation EllipsisLoc) {
+ if (Arg.isInvalid())
+ return Arg;
+
+ switch (Arg.getKind()) {
+ case ParsedTemplateArgument::Type: {
+ TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
+ if (Result.isInvalid())
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
+ Arg.getLocation());
+ }
+
+ case ParsedTemplateArgument::NonType: {
+ ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
+ if (Result.isInvalid())
+ return ParsedTemplateArgument();
+
+ return ParsedTemplateArgument(Arg.getKind(), Result.get(),
+ Arg.getLocation());
+ }
+
+ case ParsedTemplateArgument::Template:
+ if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
+ SourceRange R(Arg.getLocation());
+ if (Arg.getScopeSpec().isValid())
+ R.setBegin(Arg.getScopeSpec().getBeginLoc());
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << R;
+ return ParsedTemplateArgument();
+ }
+
+ return Arg.getTemplatePackExpansion(EllipsisLoc);
+ }
+ llvm_unreachable("Unhandled template argument kind?");
+ return ParsedTemplateArgument();
+}
+
+TypeResult Sema::ActOnPackExpansion(ParsedType Type,
+ SourceLocation EllipsisLoc) {
+ TypeSourceInfo *TSInfo;
+ GetTypeFromParser(Type, &TSInfo);
+ if (!TSInfo)
+ return true;
+
+ TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc,
+ llvm::Optional<unsigned>());
+ if (!TSResult)
+ return true;
+
+ return CreateParsedType(TSResult->getType(), TSResult);
+}
+
+TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ // Create the pack expansion type and source-location information.
+ QualType Result = CheckPackExpansion(Pattern->getType(),
+ Pattern->getTypeLoc().getSourceRange(),
+ EllipsisLoc, NumExpansions);
+ if (Result.isNull())
+ return 0;
+
+ TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
+ PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
+ TL.setEllipsisLoc(EllipsisLoc);
+
+ // Copy over the source-location information from the type.
+ memcpy(TL.getNextTypeLoc().getOpaqueData(),
+ Pattern->getTypeLoc().getOpaqueData(),
+ Pattern->getTypeLoc().getFullDataSize());
+ return TSResult;
+}
+
+QualType Sema::CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ // C++0x [temp.variadic]p5:
+ // The pattern of a pack expansion shall name one or more
+ // parameter packs that are not expanded by a nested pack
+ // expansion.
+ if (!Pattern->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << PatternRange;
+ return QualType();
+ }
+
+ return Context.getPackExpansionType(Pattern, NumExpansions);
+}
+
+ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
+ return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>());
+}
+
+ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ if (!Pattern)
+ return ExprError();
+
+ // C++0x [temp.variadic]p5:
+ // The pattern of a pack expansion shall name one or more
+ // parameter packs that are not expanded by a nested pack
+ // expansion.
+ if (!Pattern->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << Pattern->getSourceRange();
+ return ExprError();
+ }
+
+ // Create the pack expansion expression and source-location information.
+ return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern,
+ EllipsisLoc, NumExpansions));
+}
+
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ llvm::Optional<unsigned> &NumExpansions) {
+ ShouldExpand = true;
+ RetainExpansion = false;
+ std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+ bool HaveFirstPack = false;
+
+ for (unsigned I = 0; I != NumUnexpanded; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth = 0, Index = 0;
+ IdentifierInfo *Name;
+ bool IsFunctionParameterPack = false;
+
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ Name = TTP->getName();
+ } else {
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+ if (isa<ParmVarDecl>(ND))
+ IsFunctionParameterPack = true;
+ else
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+
+ Name = ND->getIdentifier();
+ }
+
+ // Determine the size of this argument pack.
+ unsigned NewPackSize;
+ if (IsFunctionParameterPack) {
+ // Figure out whether we're instantiating to an argument pack or not.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+ = CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation->is<DeclArgumentPack *>()) {
+ // We could expand this function parameter pack.
+ NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
+ } else {
+ // We can't expand this function parameter pack, so we can't expand
+ // the pack expansion.
+ ShouldExpand = false;
+ continue;
+ }
+ } else {
+ // If we don't have a template argument at this depth/index, then we
+ // cannot expand the pack expansion. Make a note of this, but we still
+ // want to check any parameter packs we *do* have arguments for.
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ ShouldExpand = false;
+ continue;
+ }
+
+ // Determine the size of the argument pack.
+ NewPackSize = TemplateArgs(Depth, Index).pack_size();
+ }
+
+ // C++0x [temp.arg.explicit]p9:
+ // Template argument deduction can extend the sequence of template
+ // arguments corresponding to a template parameter pack, even when the
+ // sequence contains explicitly specified template arguments.
+ if (!IsFunctionParameterPack) {
+ if (NamedDecl *PartialPack
+ = CurrentInstantiationScope->getPartiallySubstitutedPack()){
+ unsigned PartialDepth, PartialIndex;
+ llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ if (PartialDepth == Depth && PartialIndex == Index)
+ RetainExpansion = true;
+ }
+ }
+
+ if (!NumExpansions) {
+ // The is the first pack we've seen for which we have an argument.
+ // Record it.
+ NumExpansions = NewPackSize;
+ FirstPack.first = Name;
+ FirstPack.second = Unexpanded[I].second;
+ HaveFirstPack = true;
+ continue;
+ }
+
+ if (NewPackSize != *NumExpansions) {
+ // C++0x [temp.variadic]p5:
+ // All of the parameter packs expanded by a pack expansion shall have
+ // the same number of arguments specified.
+ if (HaveFirstPack)
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+ << FirstPack.first << Name << *NumExpansions << NewPackSize
+ << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+ else
+ Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
+ << Name << *NumExpansions << NewPackSize
+ << SourceRange(Unexpanded[I].second);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+unsigned Sema::getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ QualType Pattern = cast<PackExpansionType>(T)->getPattern();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
+
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth;
+ unsigned Index;
+
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ } else {
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+ if (isa<ParmVarDecl>(ND)) {
+ // Function parameter pack.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+ = CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation->is<DeclArgumentPack *>())
+ return Instantiation->get<DeclArgumentPack *>()->size();
+
+ continue;
+ }
+
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+ }
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index))
+ continue;
+
+ // Determine the size of the argument pack.
+ return TemplateArgs(Depth, Index).pack_size();
+ }
+
+ llvm_unreachable("No unexpanded parameter packs in type expansion.");
+ return 0;
+}
+
+bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
+ const DeclSpec &DS = D.getDeclSpec();
+ switch (DS.getTypeSpecType()) {
+ case TST_typename:
+ case TST_typeofType: {
+ QualType T = DS.getRepAsType().get();
+ if (!T.isNull() && T->containsUnexpandedParameterPack())
+ return true;
+ break;
+ }
+
+ case TST_typeofExpr:
+ case TST_decltype:
+ if (DS.getRepAsExpr() &&
+ DS.getRepAsExpr()->containsUnexpandedParameterPack())
+ return true;
+ break;
+
+ case TST_unspecified:
+ case TST_void:
+ case TST_char:
+ case TST_wchar:
+ case TST_char16:
+ case TST_char32:
+ case TST_int:
+ case TST_float:
+ case TST_double:
+ case TST_bool:
+ case TST_decimal32:
+ case TST_decimal64:
+ case TST_decimal128:
+ case TST_enum:
+ case TST_union:
+ case TST_struct:
+ case TST_class:
+ case TST_auto:
+ case TST_error:
+ break;
+ }
+
+ for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
+ const DeclaratorChunk &Chunk = D.getTypeObject(I);
+ switch (Chunk.Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Paren:
+ // These declarator chunks cannot contain any parameter packs.
+ break;
+
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::BlockPointer:
+ // Syntactically, these kinds of declarator chunks all come after the
+ // declarator-id (conceptually), so the parser should not invoke this
+ // routine at this time.
+ llvm_unreachable("Could not have seen this kind of declarator chunk");
+ break;
+
+ case DeclaratorChunk::MemberPointer:
+ if (Chunk.Mem.Scope().getScopeRep() &&
+ Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
+ return true;
+ break;
+ }
+ }
+
+ return false;
+}
+
+/// \brief Called when an expression computing the size of a parameter pack
+/// is parsed.
+///
+/// \code
+/// template<typename ...Types> struct count {
+/// static const unsigned value = sizeof...(Types);
+/// };
+/// \endcode
+///
+//
+/// \param OpLoc The location of the "sizeof" keyword.
+/// \param Name The name of the parameter pack whose size will be determined.
+/// \param NameLoc The source location of the name of the parameter pack.
+/// \param RParenLoc The location of the closing parentheses.
+ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
+ SourceLocation OpLoc,
+ IdentifierInfo &Name,
+ SourceLocation NameLoc,
+ SourceLocation RParenLoc) {
+ // C++0x [expr.sizeof]p5:
+ // The identifier in a sizeof... expression shall name a parameter pack.
+ LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
+ LookupName(R, S);
+
+ NamedDecl *ParameterPack = 0;
+ switch (R.getResultKind()) {
+ case LookupResult::Found:
+ ParameterPack = R.getFoundDecl();
+ break;
+
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false,
+ CTC_NoKeywords)) {
+ if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>())
+ if (CorrectedResult->isParameterPack()) {
+ ParameterPack = CorrectedResult;
+ Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)
+ << &Name << CorrectedName
+ << FixItHint::CreateReplacement(NameLoc,
+ CorrectedName.getAsString());
+ Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)
+ << CorrectedName;
+ }
+ }
+
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ break;
+
+ case LookupResult::Ambiguous:
+ DiagnoseAmbiguousLookup(R);
+ return ExprError();
+ }
+
+ if (!ParameterPack || !ParameterPack->isParameterPack()) {
+ Diag(NameLoc, diag::err_sizeof_pack_no_pack_name)
+ << &Name;
+ return ExprError();
+ }
+
+ return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
+ ParameterPack, NameLoc, RParenLoc);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
new file mode 100644
index 0000000..c88baa5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -0,0 +1,3038 @@
+//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements type-related semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+/// \brief Perform adjustment on the parameter type of a function.
+///
+/// This routine adjusts the given parameter type @p T to the actual
+/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
+/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
+QualType Sema::adjustParameterType(QualType T) {
+ // C99 6.7.5.3p7:
+ // A declaration of a parameter as "array of type" shall be
+ // adjusted to "qualified pointer to type", where the type
+ // qualifiers (if any) are those specified within the [ and ] of
+ // the array type derivation.
+ if (T->isArrayType())
+ return Context.getArrayDecayedType(T);
+
+ // C99 6.7.5.3p8:
+ // A declaration of a parameter as "function returning type"
+ // shall be adjusted to "pointer to function returning type", as
+ // in 6.3.2.1.
+ if (T->isFunctionType())
+ return Context.getPointerType(T);
+
+ return T;
+}
+
+
+
+/// isOmittedBlockReturnType - Return true if this declarator is missing a
+/// return type because this is a omitted return type on a block literal.
+static bool isOmittedBlockReturnType(const Declarator &D) {
+ if (D.getContext() != Declarator::BlockLiteralContext ||
+ D.getDeclSpec().hasTypeSpecifier())
+ return false;
+
+ if (D.getNumTypeObjects() == 0)
+ return true; // ^{ ... }
+
+ if (D.getNumTypeObjects() == 1 &&
+ D.getTypeObject(0).Kind == DeclaratorChunk::Function)
+ return true; // ^(int X, float Y) { ... }
+
+ return false;
+}
+
+// objc_gc applies to Objective-C pointers or, otherwise, to the
+// smallest available pointer type (i.e. 'void*' in 'void**').
+#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_objc_gc
+
+// Function type attributes.
+#define FUNCTION_TYPE_ATTRS_CASELIST \
+ case AttributeList::AT_noreturn: \
+ case AttributeList::AT_cdecl: \
+ case AttributeList::AT_fastcall: \
+ case AttributeList::AT_stdcall: \
+ case AttributeList::AT_thiscall: \
+ case AttributeList::AT_pascal: \
+ case AttributeList::AT_regparm
+
+namespace {
+ /// An object which stores processing state for the entire
+ /// GetTypeForDeclarator process.
+ class TypeProcessingState {
+ Sema &sema;
+
+ /// The declarator being processed.
+ Declarator &declarator;
+
+ /// The index of the declarator chunk we're currently processing.
+ /// May be the total number of valid chunks, indicating the
+ /// DeclSpec.
+ unsigned chunkIndex;
+
+ /// Whether there are non-trivial modifications to the decl spec.
+ bool trivial;
+
+ /// The original set of attributes on the DeclSpec.
+ llvm::SmallVector<AttributeList*, 2> savedAttrs;
+
+ /// A list of attributes to diagnose the uselessness of when the
+ /// processing is complete.
+ llvm::SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+
+ public:
+ TypeProcessingState(Sema &sema, Declarator &declarator)
+ : sema(sema), declarator(declarator),
+ chunkIndex(declarator.getNumTypeObjects()),
+ trivial(true) {}
+
+ Sema &getSema() const {
+ return sema;
+ }
+
+ Declarator &getDeclarator() const {
+ return declarator;
+ }
+
+ unsigned getCurrentChunkIndex() const {
+ return chunkIndex;
+ }
+
+ void setCurrentChunkIndex(unsigned idx) {
+ assert(idx <= declarator.getNumTypeObjects());
+ chunkIndex = idx;
+ }
+
+ AttributeList *&getCurrentAttrListRef() const {
+ assert(chunkIndex <= declarator.getNumTypeObjects());
+ if (chunkIndex == declarator.getNumTypeObjects())
+ return getMutableDeclSpec().getAttributes().getListRef();
+ return declarator.getTypeObject(chunkIndex).getAttrListRef();
+ }
+
+ /// Save the current set of attributes on the DeclSpec.
+ void saveDeclSpecAttrs() {
+ // Don't try to save them multiple times.
+ if (!savedAttrs.empty()) return;
+
+ DeclSpec &spec = getMutableDeclSpec();
+ for (AttributeList *attr = spec.getAttributes().getList(); attr;
+ attr = attr->getNext())
+ savedAttrs.push_back(attr);
+ trivial &= savedAttrs.empty();
+ }
+
+ /// Record that we had nowhere to put the given type attribute.
+ /// We will diagnose such attributes later.
+ void addIgnoredTypeAttr(AttributeList &attr) {
+ ignoredTypeAttrs.push_back(&attr);
+ }
+
+ /// Diagnose all the ignored type attributes, given that the
+ /// declarator worked out to the given type.
+ void diagnoseIgnoredTypeAttrs(QualType type) const {
+ for (llvm::SmallVectorImpl<AttributeList*>::const_iterator
+ i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
+ i != e; ++i) {
+ AttributeList &attr = **i;
+ getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+ << attr.getName() << type;
+ }
+ }
+
+ ~TypeProcessingState() {
+ if (trivial) return;
+
+ restoreDeclSpecAttrs();
+ }
+
+ private:
+ DeclSpec &getMutableDeclSpec() const {
+ return const_cast<DeclSpec&>(declarator.getDeclSpec());
+ }
+
+ void restoreDeclSpecAttrs() {
+ assert(!savedAttrs.empty());
+ getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
+ for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
+ savedAttrs[i]->setNext(savedAttrs[i+1]);
+ savedAttrs.back()->setNext(0);
+ }
+ };
+
+ /// Basically std::pair except that we really want to avoid an
+ /// implicit operator= for safety concerns. It's also a minor
+ /// link-time optimization for this to be a private type.
+ struct AttrAndList {
+ /// The attribute.
+ AttributeList &first;
+
+ /// The head of the list the attribute is currently in.
+ AttributeList *&second;
+
+ AttrAndList(AttributeList &attr, AttributeList *&head)
+ : first(attr), second(head) {}
+ };
+}
+
+namespace llvm {
+ template <> struct isPodLike<AttrAndList> {
+ static const bool value = true;
+ };
+}
+
+static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
+ attr.setNext(head);
+ head = &attr;
+}
+
+static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
+ if (head == &attr) {
+ head = attr.getNext();
+ return;
+ }
+
+ AttributeList *cur = head;
+ while (true) {
+ assert(cur && cur->getNext() && "ran out of attrs?");
+ if (cur->getNext() == &attr) {
+ cur->setNext(attr.getNext());
+ return;
+ }
+ cur = cur->getNext();
+ }
+}
+
+static void moveAttrFromListToList(AttributeList &attr,
+ AttributeList *&fromList,
+ AttributeList *&toList) {
+ spliceAttrOutOfList(attr, fromList);
+ spliceAttrIntoList(attr, toList);
+}
+
+static void processTypeAttrs(TypeProcessingState &state,
+ QualType &type, bool isDeclSpec,
+ AttributeList *attrs);
+
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &type);
+
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+ AttributeList &attr, QualType &type);
+
+static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
+ AttributeList &attr, QualType &type) {
+ // Right now, we have exactly one of these attributes: objc_gc.
+ assert(attr.getKind() == AttributeList::AT_objc_gc);
+ return handleObjCGCTypeAttr(state, attr, type);
+}
+
+/// Given that an objc_gc attribute was written somewhere on a
+/// declaration *other* than on the declarator itself (for which, use
+/// distributeObjCPointerTypeAttrFromDeclarator), and given that it
+/// didn't apply in whatever position it was written in, try to move
+/// it to a more appropriate position.
+static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType type) {
+ Declarator &declarator = state.getDeclarator();
+ for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ chunk.getAttrListRef());
+ return;
+
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Array:
+ continue;
+
+ // Don't walk through these.
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::MemberPointer:
+ goto error;
+ }
+ }
+ error:
+
+ state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+ << attr.getName() << type;
+}
+
+/// Distribute an objc_gc type attribute that was written on the
+/// declarator.
+static void
+distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &declSpecType) {
+ Declarator &declarator = state.getDeclarator();
+
+ // objc_gc goes on the innermost pointer to something that's not a
+ // pointer.
+ unsigned innermost = -1U;
+ bool considerDeclSpec = true;
+ for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ innermost = i;
+ continue;
+
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Array:
+ continue;
+
+ case DeclaratorChunk::Function:
+ considerDeclSpec = false;
+ goto done;
+ }
+ }
+ done:
+
+ // That might actually be the decl spec if we weren't blocked by
+ // anything in the declarator.
+ if (considerDeclSpec) {
+ if (handleObjCPointerTypeAttr(state, attr, declSpecType))
+ return;
+ }
+
+ // Otherwise, if we found an appropriate chunk, splice the attribute
+ // into it.
+ if (innermost != -1U) {
+ moveAttrFromListToList(attr, declarator.getAttrListRef(),
+ declarator.getTypeObject(innermost).getAttrListRef());
+ return;
+ }
+
+ // Otherwise, diagnose when we're done building the type.
+ spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written somewhere in a declaration
+/// *other* than on the declarator itself or in the decl spec. Given
+/// that it didn't apply in whatever position it was written in, try
+/// to move it to a more appropriate position.
+static void distributeFunctionTypeAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType type) {
+ Declarator &declarator = state.getDeclarator();
+
+ // Try to push the attribute from the return type of a function to
+ // the function itself.
+ for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Function:
+ moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
+ chunk.getAttrListRef());
+ return;
+
+ case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ continue;
+ }
+ }
+
+ state.getSema().Diag(attr.getLoc(), diag::warn_function_attribute_wrong_type)
+ << attr.getName() << type;
+}
+
+/// Try to distribute a function type attribute to the innermost
+/// function chunk or type. Returns true if the attribute was
+/// distributed, false if no location was found.
+static bool
+distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
+ AttributeList &attr,
+ AttributeList *&attrList,
+ QualType &declSpecType) {
+ Declarator &declarator = state.getDeclarator();
+
+ // Put it on the innermost function chunk, if there is one.
+ for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &chunk = declarator.getTypeObject(i);
+ if (chunk.Kind != DeclaratorChunk::Function) continue;
+
+ moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
+ return true;
+ }
+
+ return handleFunctionTypeAttr(state, attr, declSpecType);
+}
+
+/// A function type attribute was written in the decl spec. Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &declSpecType) {
+ state.saveDeclSpecAttrs();
+
+ // Try to distribute to the innermost.
+ if (distributeFunctionTypeAttrToInnermost(state, attr,
+ state.getCurrentAttrListRef(),
+ declSpecType))
+ return;
+
+ // If that failed, diagnose the bad attribute when the declarator is
+ // fully built.
+ state.addIgnoredTypeAttr(attr);
+}
+
+/// A function type attribute was written on the declarator. Try to
+/// apply it somewhere.
+static void
+distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &declSpecType) {
+ Declarator &declarator = state.getDeclarator();
+
+ // Try to distribute to the innermost.
+ if (distributeFunctionTypeAttrToInnermost(state, attr,
+ declarator.getAttrListRef(),
+ declSpecType))
+ return;
+
+ // If that failed, diagnose the bad attribute when the declarator is
+ // fully built.
+ spliceAttrOutOfList(attr, declarator.getAttrListRef());
+ state.addIgnoredTypeAttr(attr);
+}
+
+/// \brief Given that there are attributes written on the declarator
+/// itself, try to distribute any type attributes to the appropriate
+/// declarator chunk.
+///
+/// These are attributes like the following:
+/// int f ATTR;
+/// int (f ATTR)();
+/// but not necessarily this:
+/// int f() ATTR;
+static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
+ QualType &declSpecType) {
+ // Collect all the type attributes from the declarator itself.
+ assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
+ AttributeList *attr = state.getDeclarator().getAttributes();
+ AttributeList *next;
+ do {
+ next = attr->getNext();
+
+ switch (attr->getKind()) {
+ OBJC_POINTER_TYPE_ATTRS_CASELIST:
+ distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
+ break;
+
+ FUNCTION_TYPE_ATTRS_CASELIST:
+ distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
+ break;
+
+ default:
+ break;
+ }
+ } while ((attr = next));
+}
+
+/// Add a synthetic '()' to a block-literal declarator if it is
+/// required, given the return type.
+static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
+ QualType declSpecType) {
+ Declarator &declarator = state.getDeclarator();
+
+ // First, check whether the declarator would produce a function,
+ // i.e. whether the innermost semantic chunk is a function.
+ if (declarator.isFunctionDeclarator()) {
+ // If so, make that declarator a prototyped declarator.
+ declarator.getFunctionTypeInfo().hasPrototype = true;
+ return;
+ }
+
+ // If there are any type objects, the type as written won't name a
+ // function, regardless of the decl spec type. This is because a
+ // block signature declarator is always an abstract-declarator, and
+ // abstract-declarators can't just be parentheses chunks. Therefore
+ // we need to build a function chunk unless there are no type
+ // objects and the decl spec type is a function.
+ if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
+ return;
+
+ // Note that there *are* cases with invalid declarators where
+ // declarators consist solely of parentheses. In general, these
+ // occur only in failed efforts to make function declarators, so
+ // faking up the function chunk is still the right thing to do.
+
+ // Otherwise, we need to fake up a function declarator.
+ SourceLocation loc = declarator.getSourceRange().getBegin();
+
+ // ...and *prepend* it to the declarator.
+ declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
+ ParsedAttributes(),
+ /*proto*/ true,
+ /*variadic*/ false, SourceLocation(),
+ /*args*/ 0, 0,
+ /*type quals*/ 0,
+ /*ref-qualifier*/true, SourceLocation(),
+ /*EH*/ false, SourceLocation(), false, 0, 0, 0,
+ /*parens*/ loc, loc,
+ declarator));
+
+ // For consistency, make sure the state still has us as processing
+ // the decl spec.
+ assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
+ state.setCurrentChunkIndex(declarator.getNumTypeObjects());
+}
+
+/// \brief Convert the specified declspec to the appropriate type
+/// object.
+/// \param D the declarator containing the declaration specifier.
+/// \returns The type described by the declaration specifiers. This function
+/// never returns null.
+static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
+ // FIXME: Should move the logic from DeclSpec::Finish to here for validity
+ // checking.
+
+ Declarator &declarator = state.getDeclarator();
+ const DeclSpec &DS = declarator.getDeclSpec();
+ SourceLocation DeclLoc = declarator.getIdentifierLoc();
+ if (DeclLoc.isInvalid())
+ DeclLoc = DS.getSourceRange().getBegin();
+
+ ASTContext &Context = S.Context;
+
+ QualType Result;
+ switch (DS.getTypeSpecType()) {
+ case DeclSpec::TST_void:
+ Result = Context.VoidTy;
+ break;
+ case DeclSpec::TST_char:
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+ Result = Context.CharTy;
+ else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
+ Result = Context.SignedCharTy;
+ else {
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+ "Unknown TSS value");
+ Result = Context.UnsignedCharTy;
+ }
+ break;
+ case DeclSpec::TST_wchar:
+ if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
+ Result = Context.WCharTy;
+ else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
+ S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+ << DS.getSpecifierName(DS.getTypeSpecType());
+ Result = Context.getSignedWCharType();
+ } else {
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
+ "Unknown TSS value");
+ S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
+ << DS.getSpecifierName(DS.getTypeSpecType());
+ Result = Context.getUnsignedWCharType();
+ }
+ break;
+ case DeclSpec::TST_char16:
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char16Ty;
+ break;
+ case DeclSpec::TST_char32:
+ assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
+ "Unknown TSS value");
+ Result = Context.Char32Ty;
+ break;
+ case DeclSpec::TST_unspecified:
+ // "<proto1,proto2>" is an objc qualified ID with a missing id.
+ if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+ Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+ (ObjCProtocolDecl**)PQ,
+ DS.getNumProtocolQualifiers());
+ Result = Context.getObjCObjectPointerType(Result);
+ break;
+ }
+
+ // If this is a missing declspec in a block literal return context, then it
+ // is inferred from the return statements inside the block.
+ if (isOmittedBlockReturnType(declarator)) {
+ Result = Context.DependentTy;
+ break;
+ }
+
+ // Unspecified typespec defaults to int in C90. However, the C90 grammar
+ // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
+ // type-qualifier, or storage-class-specifier. If not, emit an extwarn.
+ // Note that the one exception to this is function definitions, which are
+ // allowed to be completely missing a declspec. This is handled in the
+ // parser already though by it pretending to have seen an 'int' in this
+ // case.
+ if (S.getLangOptions().ImplicitInt) {
+ // In C89 mode, we only warn if there is a completely missing declspec
+ // when one is not allowed.
+ if (DS.isEmpty()) {
+ S.Diag(DeclLoc, diag::ext_missing_declspec)
+ << DS.getSourceRange()
+ << FixItHint::CreateInsertion(DS.getSourceRange().getBegin(), "int");
+ }
+ } else if (!DS.hasTypeSpecifier()) {
+ // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
+ // "At least one type specifier shall be given in the declaration
+ // specifiers in each declaration, and in the specifier-qualifier list in
+ // each struct declaration and type name."
+ // FIXME: Does Microsoft really have the implicit int extension in C++?
+ if (S.getLangOptions().CPlusPlus &&
+ !S.getLangOptions().Microsoft) {
+ S.Diag(DeclLoc, diag::err_missing_type_specifier)
+ << DS.getSourceRange();
+
+ // When this occurs in C++ code, often something is very broken with the
+ // value being declared, poison it as invalid so we don't get chains of
+ // errors.
+ declarator.setInvalidType(true);
+ } else {
+ S.Diag(DeclLoc, diag::ext_missing_type_specifier)
+ << DS.getSourceRange();
+ }
+ }
+
+ // FALL THROUGH.
+ case DeclSpec::TST_int: {
+ if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
+ case DeclSpec::TSW_short: Result = Context.ShortTy; break;
+ case DeclSpec::TSW_long: Result = Context.LongTy; break;
+ case DeclSpec::TSW_longlong:
+ Result = Context.LongLongTy;
+
+ // long long is a C99 feature.
+ if (!S.getLangOptions().C99 &&
+ !S.getLangOptions().CPlusPlus0x)
+ S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+ break;
+ }
+ } else {
+ switch (DS.getTypeSpecWidth()) {
+ case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
+ case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
+ case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
+ case DeclSpec::TSW_longlong:
+ Result = Context.UnsignedLongLongTy;
+
+ // long long is a C99 feature.
+ if (!S.getLangOptions().C99 &&
+ !S.getLangOptions().CPlusPlus0x)
+ S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong);
+ break;
+ }
+ }
+ break;
+ }
+ case DeclSpec::TST_float: Result = Context.FloatTy; break;
+ case DeclSpec::TST_double:
+ if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
+ Result = Context.LongDoubleTy;
+ else
+ Result = Context.DoubleTy;
+
+ if (S.getLangOptions().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64);
+ declarator.setInvalidType(true);
+ }
+ break;
+ case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
+ case DeclSpec::TST_decimal32: // _Decimal32
+ case DeclSpec::TST_decimal64: // _Decimal64
+ case DeclSpec::TST_decimal128: // _Decimal128
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ break;
+ case DeclSpec::TST_class:
+ case DeclSpec::TST_enum:
+ case DeclSpec::TST_union:
+ case DeclSpec::TST_struct: {
+ TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
+ if (!D) {
+ // This can happen in C++ with ambiguous lookups.
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ break;
+ }
+
+ // If the type is deprecated or unavailable, diagnose it.
+ S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc());
+
+ assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+ DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
+
+ // TypeQuals handled by caller.
+ Result = Context.getTypeDeclType(D);
+
+ // In C++, make an ElaboratedType.
+ if (S.getLangOptions().CPlusPlus) {
+ ElaboratedTypeKeyword Keyword
+ = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
+ Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
+ }
+ if (D->isInvalidDecl())
+ declarator.setInvalidType(true);
+ break;
+ }
+ case DeclSpec::TST_typename: {
+ assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
+ DS.getTypeSpecSign() == 0 &&
+ "Can't handle qualifiers on typedef names yet!");
+ Result = S.GetTypeFromParser(DS.getRepAsType());
+ if (Result.isNull())
+ declarator.setInvalidType(true);
+ else if (DeclSpec::ProtocolQualifierListTy PQ
+ = DS.getProtocolQualifiers()) {
+ if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
+ // Silently drop any existing protocol qualifiers.
+ // TODO: determine whether that's the right thing to do.
+ if (ObjT->getNumProtocols())
+ Result = ObjT->getBaseType();
+
+ if (DS.getNumProtocolQualifiers())
+ Result = Context.getObjCObjectType(Result,
+ (ObjCProtocolDecl**) PQ,
+ DS.getNumProtocolQualifiers());
+ } else if (Result->isObjCIdType()) {
+ // id<protocol-list>
+ Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+ (ObjCProtocolDecl**) PQ,
+ DS.getNumProtocolQualifiers());
+ Result = Context.getObjCObjectPointerType(Result);
+ } else if (Result->isObjCClassType()) {
+ // Class<protocol-list>
+ Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
+ (ObjCProtocolDecl**) PQ,
+ DS.getNumProtocolQualifiers());
+ Result = Context.getObjCObjectPointerType(Result);
+ } else {
+ S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
+ << DS.getSourceRange();
+ declarator.setInvalidType(true);
+ }
+ }
+
+ // TypeQuals handled by caller.
+ break;
+ }
+ case DeclSpec::TST_typeofType:
+ // FIXME: Preserve type source info.
+ Result = S.GetTypeFromParser(DS.getRepAsType());
+ assert(!Result.isNull() && "Didn't get a type for typeof?");
+ if (!Result->isDependentType())
+ if (const TagType *TT = Result->getAs<TagType>())
+ S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
+ // TypeQuals handled by caller.
+ Result = Context.getTypeOfType(Result);
+ break;
+ case DeclSpec::TST_typeofExpr: {
+ Expr *E = DS.getRepAsExpr();
+ assert(E && "Didn't get an expression for typeof?");
+ // TypeQuals handled by caller.
+ Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ }
+ break;
+ }
+ case DeclSpec::TST_decltype: {
+ Expr *E = DS.getRepAsExpr();
+ assert(E && "Didn't get an expression for decltype?");
+ // TypeQuals handled by caller.
+ Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ }
+ break;
+ }
+ case DeclSpec::TST_auto: {
+ // TypeQuals handled by caller.
+ Result = Context.getAutoType(QualType());
+ break;
+ }
+
+ case DeclSpec::TST_error:
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ break;
+ }
+
+ // Handle complex types.
+ if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
+ if (S.getLangOptions().Freestanding)
+ S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
+ Result = Context.getComplexType(Result);
+ } else if (DS.isTypeAltiVecVector()) {
+ unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
+ assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
+ VectorType::VectorKind VecKind = VectorType::AltiVecVector;
+ if (DS.isTypeAltiVecPixel())
+ VecKind = VectorType::AltiVecPixel;
+ else if (DS.isTypeAltiVecBool())
+ VecKind = VectorType::AltiVecBool;
+ Result = Context.getVectorType(Result, 128/typeSize, VecKind);
+ }
+
+ // FIXME: Imaginary.
+ if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
+ S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
+
+ // Before we process any type attributes, synthesize a block literal
+ // function declarator if necessary.
+ if (declarator.getContext() == Declarator::BlockLiteralContext)
+ maybeSynthesizeBlockSignature(state, Result);
+
+ // Apply any type attributes from the decl spec. This may cause the
+ // list of type attributes to be temporarily saved while the type
+ // attributes are pushed around.
+ if (AttributeList *attrs = DS.getAttributes().getList())
+ processTypeAttrs(state, Result, true, attrs);
+
+ // Apply const/volatile/restrict qualifiers to T.
+ if (unsigned TypeQuals = DS.getTypeQualifiers()) {
+
+ // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
+ // or incomplete types shall not be restrict-qualified." C++ also allows
+ // restrict-qualified references.
+ if (TypeQuals & DeclSpec::TQ_restrict) {
+ if (Result->isAnyPointerType() || Result->isReferenceType()) {
+ QualType EltTy;
+ if (Result->isObjCObjectPointerType())
+ EltTy = Result;
+ else
+ EltTy = Result->isPointerType() ?
+ Result->getAs<PointerType>()->getPointeeType() :
+ Result->getAs<ReferenceType>()->getPointeeType();
+
+ // If we have a pointer or reference, the pointee must have an object
+ // incomplete type.
+ if (!EltTy->isIncompleteOrObjectType()) {
+ S.Diag(DS.getRestrictSpecLoc(),
+ diag::err_typecheck_invalid_restrict_invalid_pointee)
+ << EltTy << DS.getSourceRange();
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+ }
+ } else {
+ S.Diag(DS.getRestrictSpecLoc(),
+ diag::err_typecheck_invalid_restrict_not_pointer)
+ << Result << DS.getSourceRange();
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
+ }
+ }
+
+ // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
+ // of a function type includes any type qualifiers, the behavior is
+ // undefined."
+ if (Result->isFunctionType() && TypeQuals) {
+ // Get some location to point at, either the C or V location.
+ SourceLocation Loc;
+ if (TypeQuals & DeclSpec::TQ_const)
+ Loc = DS.getConstSpecLoc();
+ else if (TypeQuals & DeclSpec::TQ_volatile)
+ Loc = DS.getVolatileSpecLoc();
+ else {
+ assert((TypeQuals & DeclSpec::TQ_restrict) &&
+ "Has CVR quals but not C, V, or R?");
+ Loc = DS.getRestrictSpecLoc();
+ }
+ S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
+ << Result << DS.getSourceRange();
+ }
+
+ // C++ [dcl.ref]p1:
+ // Cv-qualified references are ill-formed except when the
+ // cv-qualifiers are introduced through the use of a typedef
+ // (7.1.3) or of a template type argument (14.3), in which
+ // case the cv-qualifiers are ignored.
+ // FIXME: Shouldn't we be checking SCS_typedef here?
+ if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+ TypeQuals && Result->isReferenceType()) {
+ TypeQuals &= ~DeclSpec::TQ_const;
+ TypeQuals &= ~DeclSpec::TQ_volatile;
+ }
+
+ Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+ Result = Context.getQualifiedType(Result, Quals);
+ }
+
+ return Result;
+}
+
+static std::string getPrintableNameForEntity(DeclarationName Entity) {
+ if (Entity)
+ return Entity.getAsString();
+
+ return "type name";
+}
+
+QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
+ Qualifiers Qs) {
+ // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+ // object or incomplete types shall not be restrict-qualified."
+ if (Qs.hasRestrict()) {
+ unsigned DiagID = 0;
+ QualType ProblemTy;
+
+ const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+ if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
+ if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
+ }
+ } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+ if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ }
+ } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
+ if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ }
+ } else if (!Ty->isDependentType()) {
+ // FIXME: this deserves a proper diagnostic
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T;
+ }
+
+ if (DiagID) {
+ Diag(Loc, DiagID) << ProblemTy;
+ Qs.removeRestrict();
+ }
+ }
+
+ return Context.getQualifiedType(T, Qs);
+}
+
+/// \brief Build a paren type including \p T.
+QualType Sema::BuildParenType(QualType T) {
+ return Context.getParenType(T);
+}
+
+/// \brief Build a pointer type.
+///
+/// \param T The type to which we'll be building a pointer.
+///
+/// \param Loc The location of the entity whose type involves this
+/// pointer type or, if there is no such entity, the location of the
+/// type that will have pointer type.
+///
+/// \param Entity The name of the entity that involves the pointer
+/// type, if known.
+///
+/// \returns A suitable pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity) {
+ if (T->isReferenceType()) {
+ // C++ 8.3.2p4: There shall be no ... pointers to references ...
+ Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+ << getPrintableNameForEntity(Entity) << T;
+ return QualType();
+ }
+
+ assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
+
+ // Build the pointer type.
+ return Context.getPointerType(T);
+}
+
+/// \brief Build a reference type.
+///
+/// \param T The type to which we'll be building a reference.
+///
+/// \param Loc The location of the entity whose type involves this
+/// reference type or, if there is no such entity, the location of the
+/// type that will have reference type.
+///
+/// \param Entity The name of the entity that involves the reference
+/// type, if known.
+///
+/// \returns A suitable reference type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // C++0x [dcl.ref]p6:
+ // If a typedef (7.1.3), a type template-parameter (14.3.1), or a
+ // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
+ // type T, an attempt to create the type "lvalue reference to cv TR" creates
+ // the type "lvalue reference to T", while an attempt to create the type
+ // "rvalue reference to cv TR" creates the type TR.
+ bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
+
+ // C++ [dcl.ref]p4: There shall be no references to references.
+ //
+ // According to C++ DR 106, references to references are only
+ // diagnosed when they are written directly (e.g., "int & &"),
+ // but not when they happen via a typedef:
+ //
+ // typedef int& intref;
+ // typedef intref& intref2;
+ //
+ // Parser::ParseDeclaratorInternal diagnoses the case where
+ // references are written directly; here, we handle the
+ // collapsing of references-to-references as described in C++0x.
+ // DR 106 and 540 introduce reference-collapsing into C++98/03.
+
+ // C++ [dcl.ref]p1:
+ // A declarator that specifies the type "reference to cv void"
+ // is ill-formed.
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_reference_to_void);
+ return QualType();
+ }
+
+ // Handle restrict on references.
+ if (LValueRef)
+ return Context.getLValueReferenceType(T, SpelledAsLValue);
+ return Context.getRValueReferenceType(T);
+}
+
+/// \brief Build an array type.
+///
+/// \param T The type of each element in the array.
+///
+/// \param ASM C99 array size modifier (e.g., '*', 'static').
+///
+/// \param ArraySize Expression describing the size of the array.
+///
+/// \param Loc The location of the entity whose type involves this
+/// array type or, if there is no such entity, the location of the
+/// type that will have array type.
+///
+/// \param Entity The name of the entity that involves the array
+/// type, if known.
+///
+/// \returns A suitable array type, if there are no errors. Otherwise,
+/// returns a NULL type.
+QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
+ Expr *ArraySize, unsigned Quals,
+ SourceRange Brackets, DeclarationName Entity) {
+
+ SourceLocation Loc = Brackets.getBegin();
+ if (getLangOptions().CPlusPlus) {
+ // C++ [dcl.array]p1:
+ // T is called the array element type; this type shall not be a reference
+ // type, the (possibly cv-qualified) type void, a function type or an
+ // abstract class type.
+ //
+ // Note: function types are handled in the common path with C.
+ if (T->isReferenceType()) {
+ Diag(Loc, diag::err_illegal_decl_array_of_references)
+ << getPrintableNameForEntity(Entity) << T;
+ return QualType();
+ }
+
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+ return QualType();
+ }
+
+ if (RequireNonAbstractType(Brackets.getBegin(), T,
+ diag::err_array_of_abstract_type))
+ return QualType();
+
+ } else {
+ // C99 6.7.5.2p1: If the element type is an incomplete or function type,
+ // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
+ if (RequireCompleteType(Loc, T,
+ diag::err_illegal_decl_array_incomplete_type))
+ return QualType();
+ }
+
+ if (T->isFunctionType()) {
+ Diag(Loc, diag::err_illegal_decl_array_of_functions)
+ << getPrintableNameForEntity(Entity) << T;
+ return QualType();
+ }
+
+ if (T->getContainedAutoType()) {
+ Diag(Loc, diag::err_illegal_decl_array_of_auto)
+ << getPrintableNameForEntity(Entity) << T;
+ return QualType();
+ }
+
+ if (const RecordType *EltTy = T->getAs<RecordType>()) {
+ // If the element type is a struct or union that contains a variadic
+ // array, accept it as a GNU extension: C99 6.7.2.1p2.
+ if (EltTy->getDecl()->hasFlexibleArrayMember())
+ Diag(Loc, diag::ext_flexible_array_in_array) << T;
+ } else if (T->isObjCObjectType()) {
+ Diag(Loc, diag::err_objc_array_of_interfaces) << T;
+ return QualType();
+ }
+
+ // Do lvalue-to-rvalue conversions on the array size expression.
+ if (ArraySize && !ArraySize->isRValue())
+ DefaultLvalueConversion(ArraySize);
+
+ // C99 6.7.5.2p1: The size expression shall have integer type.
+ // TODO: in theory, if we were insane, we could allow contextual
+ // conversions to integer type here.
+ if (ArraySize && !ArraySize->isTypeDependent() &&
+ !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
+ Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+ << ArraySize->getType() << ArraySize->getSourceRange();
+ return QualType();
+ }
+ llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
+ if (!ArraySize) {
+ if (ASM == ArrayType::Star)
+ T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
+ else
+ T = Context.getIncompleteArrayType(T, ASM, Quals);
+ } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
+ T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
+ } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
+ (!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType())) {
+ // Per C99, a variable array is an array with either a non-constant
+ // size or an element type that has a non-constant-size
+ T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+ } else {
+ // C99 6.7.5.2p1: If the expression is a constant expression, it shall
+ // have a value greater than zero.
+ if (ConstVal.isSigned() && ConstVal.isNegative()) {
+ if (Entity)
+ Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
+ << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
+ else
+ Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+ if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays. We allow them when
+ // we're not in a SFINAE context.
+ Diag(ArraySize->getLocStart(),
+ isSFINAEContext()? diag::err_typecheck_zero_array_size
+ : diag::ext_typecheck_zero_array_size)
+ << ArraySize->getSourceRange();
+ } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
+ !T->isIncompleteType()) {
+ // Is the array too large?
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ Diag(ArraySize->getLocStart(), diag::err_array_too_large)
+ << ConstVal.toString(10)
+ << ArraySize->getSourceRange();
+ }
+
+ T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
+ }
+ // If this is not C99, extwarn about VLA's and C99 array size modifiers.
+ if (!getLangOptions().C99) {
+ if (T->isVariableArrayType()) {
+ // Prohibit the use of non-POD types in VLAs.
+ if (!T->isDependentType() &&
+ !Context.getBaseElementType(T)->isPODType()) {
+ Diag(Loc, diag::err_vla_non_pod)
+ << Context.getBaseElementType(T);
+ return QualType();
+ }
+ // Prohibit the use of VLAs during template argument deduction.
+ else if (isSFINAEContext()) {
+ Diag(Loc, diag::err_vla_in_sfinae);
+ return QualType();
+ }
+ // Just extwarn about VLAs.
+ else
+ Diag(Loc, diag::ext_vla);
+ } else if (ASM != ArrayType::Normal || Quals != 0)
+ Diag(Loc,
+ getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx
+ : diag::ext_c99_array_usage);
+ }
+
+ return T;
+}
+
+/// \brief Build an ext-vector type.
+///
+/// Run the required checks for the extended vector type.
+QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
+ SourceLocation AttrLoc) {
+ // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+ // in conjunction with complex types (pointers, arrays, functions, etc.).
+ if (!T->isDependentType() &&
+ !T->isIntegerType() && !T->isRealFloatingType()) {
+ Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
+ return QualType();
+ }
+
+ if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
+ llvm::APSInt vecSize(32);
+ if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_not_int)
+ << "ext_vector_type" << ArraySize->getSourceRange();
+ return QualType();
+ }
+
+ // unlike gcc's vector_size attribute, the size is specified as the
+ // number of elements, not the number of bytes.
+ unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+
+ if (vectorSize == 0) {
+ Diag(AttrLoc, diag::err_attribute_zero_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+
+ if (!T->isDependentType())
+ return Context.getExtVectorType(T, vectorSize);
+ }
+
+ return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
+}
+
+/// \brief Build a function type.
+///
+/// This routine checks the function type according to C++ rules and
+/// under the assumption that the result type and parameter types have
+/// just been instantiated from a template. It therefore duplicates
+/// some of the behavior of GetTypeForDeclarator, but in a much
+/// simpler form that is only suitable for this narrow use case.
+///
+/// \param T The return type of the function.
+///
+/// \param ParamTypes The parameter types of the function. This array
+/// will be modified to account for adjustments to the types of the
+/// function parameters.
+///
+/// \param NumParamTypes The number of parameter types in ParamTypes.
+///
+/// \param Variadic Whether this is a variadic function type.
+///
+/// \param Quals The cvr-qualifiers to be applied to the function type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// function type or, if there is no such entity, the location of the
+/// type that will have function type.
+///
+/// \param Entity The name of the entity that involves the function
+/// type, if known.
+///
+/// \returns A suitable function type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildFunctionType(QualType T,
+ QualType *ParamTypes,
+ unsigned NumParamTypes,
+ bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
+ SourceLocation Loc, DeclarationName Entity,
+ FunctionType::ExtInfo Info) {
+ if (T->isArrayType() || T->isFunctionType()) {
+ Diag(Loc, diag::err_func_returning_array_function)
+ << T->isFunctionType() << T;
+ return QualType();
+ }
+
+ bool Invalid = false;
+ for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
+ QualType ParamType = adjustParameterType(ParamTypes[Idx]);
+ if (ParamType->isVoidType()) {
+ Diag(Loc, diag::err_param_with_void_type);
+ Invalid = true;
+ }
+
+ ParamTypes[Idx] = ParamType;
+ }
+
+ if (Invalid)
+ return QualType();
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = Variadic;
+ EPI.TypeQuals = Quals;
+ EPI.RefQualifier = RefQualifier;
+ EPI.ExtInfo = Info;
+
+ return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
+}
+
+/// \brief Build a member pointer type \c T Class::*.
+///
+/// \param T the type to which the member pointer refers.
+/// \param Class the class type into which the member pointer points.
+/// \param CVR Qualifiers applied to the member pointer type
+/// \param Loc the location where this type begins
+/// \param Entity the name of the entity that will have this member pointer type
+///
+/// \returns a member pointer type, if successful, or a NULL type if there was
+/// an error.
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // Verify that we're not building a pointer to pointer to function with
+ // exception specification.
+ if (CheckDistantExceptionSpec(T)) {
+ Diag(Loc, diag::err_distant_exception_spec);
+
+ // FIXME: If we're doing this as part of template instantiation,
+ // we should return immediately.
+
+ // Build the type anyway, but use the canonical type so that the
+ // exception specifiers are stripped off.
+ T = Context.getCanonicalType(T);
+ }
+
+ // C++ 8.3.3p3: A pointer to member shall not point to ... a member
+ // with reference type, or "cv void."
+ if (T->isReferenceType()) {
+ Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
+ << (Entity? Entity.getAsString() : "type name") << T;
+ return QualType();
+ }
+
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
+ << (Entity? Entity.getAsString() : "type name");
+ return QualType();
+ }
+
+ if (!Class->isDependentType() && !Class->isRecordType()) {
+ Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+ return QualType();
+ }
+
+ // In the Microsoft ABI, the class is allowed to be an incomplete
+ // type. In such cases, the compiler makes a worst-case assumption.
+ // We make no such assumption right now, so emit an error if the
+ // class isn't a complete type.
+ if (Context.Target.getCXXABI() == CXXABI_Microsoft &&
+ RequireCompleteType(Loc, Class, diag::err_incomplete_type))
+ return QualType();
+
+ return Context.getMemberPointerType(T, Class.getTypePtr());
+}
+
+/// \brief Build a block pointer type.
+///
+/// \param T The type to which we'll be building a block pointer.
+///
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
+///
+/// \param Loc The location of the entity whose type involves this
+/// block pointer type or, if there is no such entity, the location of the
+/// type that will have block pointer type.
+///
+/// \param Entity The name of the entity that involves the block pointer
+/// type, if known.
+///
+/// \returns A suitable block pointer type, if there are no
+/// errors. Otherwise, returns a NULL type.
+QualType Sema::BuildBlockPointerType(QualType T,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ if (!T->isFunctionType()) {
+ Diag(Loc, diag::err_nonfunction_block_type);
+ return QualType();
+ }
+
+ return Context.getBlockPointerType(T);
+}
+
+QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
+ QualType QT = Ty.get();
+ if (QT.isNull()) {
+ if (TInfo) *TInfo = 0;
+ return QualType();
+ }
+
+ TypeSourceInfo *DI = 0;
+ if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
+ QT = LIT->getType();
+ DI = LIT->getTypeSourceInfo();
+ }
+
+ if (TInfo) *TInfo = DI;
+ return QT;
+}
+
+/// GetTypeForDeclarator - Convert the type for the specified
+/// declarator to Type instances.
+///
+/// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq
+/// owns the declaration of a type (e.g., the definition of a struct
+/// type), then *OwnedDecl will receive the owned declaration.
+///
+/// The result of this call will never be null, but the associated
+/// type may be a null type if there's an unrecoverable error.
+TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
+ TagDecl **OwnedDecl,
+ bool AutoAllowedInTypeName) {
+ // Determine the type of the declarator. Not all forms of declarator
+ // have a type.
+ QualType T;
+ TypeSourceInfo *ReturnTypeInfo = 0;
+
+ TypeProcessingState state(*this, D);
+
+ switch (D.getName().getKind()) {
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedId::IK_TemplateId:
+ T = ConvertDeclSpecToType(*this, state);
+
+ if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
+ TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+ // Owned is embedded if it was defined here, or if it is the
+ // very first (i.e., canonical) declaration of this tag type.
+ Owned->setEmbeddedInDeclarator(Owned->isDefinition() ||
+ Owned->isCanonicalDecl());
+ if (OwnedDecl) *OwnedDecl = Owned;
+ }
+ break;
+
+ case UnqualifiedId::IK_ConstructorName:
+ case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedId::IK_DestructorName:
+ // Constructors and destructors don't have return types. Use
+ // "void" instead.
+ T = Context.VoidTy;
+ break;
+
+ case UnqualifiedId::IK_ConversionFunctionId:
+ // The result type of a conversion function is the type that it
+ // converts to.
+ T = GetTypeFromParser(D.getName().ConversionFunctionId,
+ &ReturnTypeInfo);
+ break;
+ }
+
+ if (D.getAttributes())
+ distributeTypeAttrsFromDeclarator(state, T);
+
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ !D.isFunctionDeclarator()) {
+ int Error = -1;
+
+ switch (D.getContext()) {
+ case Declarator::KNRTypeListContext:
+ assert(0 && "K&R type lists aren't allowed in C++");
+ break;
+ case Declarator::PrototypeContext:
+ Error = 0; // Function prototype
+ break;
+ case Declarator::MemberContext:
+ switch (cast<TagDecl>(CurContext)->getTagKind()) {
+ case TTK_Enum: assert(0 && "unhandled tag kind"); break;
+ case TTK_Struct: Error = 1; /* Struct member */ break;
+ case TTK_Union: Error = 2; /* Union member */ break;
+ case TTK_Class: Error = 3; /* Class member */ break;
+ }
+ break;
+ case Declarator::CXXCatchContext:
+ Error = 4; // Exception declaration
+ break;
+ case Declarator::TemplateParamContext:
+ Error = 5; // Template parameter
+ break;
+ case Declarator::BlockLiteralContext:
+ Error = 6; // Block literal
+ break;
+ case Declarator::TemplateTypeArgContext:
+ Error = 7; // Template type argument
+ break;
+ case Declarator::TypeNameContext:
+ if (!AutoAllowedInTypeName)
+ Error = 8; // Generic
+ break;
+ case Declarator::FileContext:
+ case Declarator::BlockContext:
+ case Declarator::ForContext:
+ case Declarator::ConditionContext:
+ break;
+ }
+
+ if (Error != -1) {
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
+ << Error;
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
+ }
+
+ if (T.isNull())
+ return Context.getNullTypeSourceInfo();
+
+ // The name we're declaring, if any.
+ DeclarationName Name;
+ if (D.getIdentifier())
+ Name = D.getIdentifier();
+
+ // Walk the DeclTypeInfo, building the recursive type as we go.
+ // DeclTypeInfos are ordered from the identifier out, which is
+ // opposite of what we want :).
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ unsigned chunkIndex = e - i - 1;
+ state.setCurrentChunkIndex(chunkIndex);
+ DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ switch (DeclType.Kind) {
+ default: assert(0 && "Unknown decltype!");
+ case DeclaratorChunk::Paren:
+ T = BuildParenType(T);
+ break;
+ case DeclaratorChunk::BlockPointer:
+ // If blocks are disabled, emit an error.
+ if (!LangOpts.Blocks)
+ Diag(DeclType.Loc, diag::err_blocks_disable);
+
+ T = BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
+ if (DeclType.Cls.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
+ break;
+ case DeclaratorChunk::Pointer:
+ // Verify that we're not building a pointer to pointer to function with
+ // exception specification.
+ if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+ Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+ D.setInvalidType(true);
+ // Build the type anyway.
+ }
+ if (getLangOptions().ObjC1 && T->getAs<ObjCObjectType>()) {
+ T = Context.getObjCObjectPointerType(T);
+ if (DeclType.Ptr.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
+ break;
+ }
+ T = BuildPointerType(T, DeclType.Loc, Name);
+ if (DeclType.Ptr.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
+
+ break;
+ case DeclaratorChunk::Reference: {
+ // Verify that we're not building a reference to pointer to function with
+ // exception specification.
+ if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+ Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+ D.setInvalidType(true);
+ // Build the type anyway.
+ }
+ T = BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
+
+ Qualifiers Quals;
+ if (DeclType.Ref.HasRestrict)
+ T = BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
+ break;
+ }
+ case DeclaratorChunk::Array: {
+ // Verify that we're not building an array of pointers to function with
+ // exception specification.
+ if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
+ Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
+ D.setInvalidType(true);
+ // Build the type anyway.
+ }
+ DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
+ Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
+ ArrayType::ArraySizeModifier ASM;
+ if (ATI.isStar)
+ ASM = ArrayType::Star;
+ else if (ATI.hasStatic)
+ ASM = ArrayType::Static;
+ else
+ ASM = ArrayType::Normal;
+ if (ASM == ArrayType::Star &&
+ D.getContext() != Declarator::PrototypeContext) {
+ // FIXME: This check isn't quite right: it allows star in prototypes
+ // for function definitions, and disallows some edge cases detailed
+ // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
+ Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
+ ASM = ArrayType::Normal;
+ D.setInvalidType(true);
+ }
+ T = BuildArrayType(T, ASM, ArraySize,
+ Qualifiers::fromCVRMask(ATI.TypeQuals),
+ SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
+ break;
+ }
+ case DeclaratorChunk::Function: {
+ // If the function declarator has a prototype (i.e. it is not () and
+ // does not have a K&R-style identifier list), then the arguments are part
+ // of the type, otherwise the argument list is ().
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+
+ // C99 6.7.5.3p1: The return type may not be a function or array type.
+ // For conversion functions, we'll diagnose this particular error later.
+ if ((T->isArrayType() || T->isFunctionType()) &&
+ (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+ unsigned diagID = diag::err_func_returning_array_function;
+ // Last processing chunk in block context means this function chunk
+ // represents the block.
+ if (chunkIndex == 0 &&
+ D.getContext() == Declarator::BlockLiteralContext)
+ diagID = diag::err_block_returning_array_function;
+ Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
+
+ // Check for auto functions and trailing return type and adjust the
+ // return type accordingly.
+ if (!D.isInvalidType()) {
+ // trailing-return-type is only required if we're declaring a function,
+ // and not, for instance, a pointer to a function.
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ !FTI.TrailingReturnType && chunkIndex == 0) {
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ diag::err_auto_missing_trailing_return);
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ } else if (FTI.TrailingReturnType) {
+ if (T.hasQualifiers() || !isa<AutoType>(T)) {
+ // T must be exactly 'auto' at this point. See CWG issue 681.
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ diag::err_trailing_return_without_auto)
+ << T << D.getDeclSpec().getSourceRange();
+ D.setInvalidType(true);
+ }
+
+ T = GetTypeFromParser(
+ ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
+ &ReturnTypeInfo);
+ }
+ }
+
+ // cv-qualifiers on return types are pointless except when the type is a
+ // class type in C++.
+ if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+ (!getLangOptions().CPlusPlus ||
+ (!T->isDependentType() && !T->isRecordType()))) {
+ unsigned Quals = D.getDeclSpec().getTypeQualifiers();
+ std::string QualStr;
+ unsigned NumQuals = 0;
+ SourceLocation Loc;
+ if (Quals & Qualifiers::Const) {
+ Loc = D.getDeclSpec().getConstSpecLoc();
+ ++NumQuals;
+ QualStr = "const";
+ }
+ if (Quals & Qualifiers::Volatile) {
+ if (NumQuals == 0) {
+ Loc = D.getDeclSpec().getVolatileSpecLoc();
+ QualStr = "volatile";
+ } else
+ QualStr += " volatile";
+ ++NumQuals;
+ }
+ if (Quals & Qualifiers::Restrict) {
+ if (NumQuals == 0) {
+ Loc = D.getDeclSpec().getRestrictSpecLoc();
+ QualStr = "restrict";
+ } else
+ QualStr += " restrict";
+ ++NumQuals;
+ }
+ assert(NumQuals > 0 && "No known qualifiers?");
+
+ SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type);
+ DB << QualStr << NumQuals;
+ if (Quals & Qualifiers::Const)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc());
+ if (Quals & Qualifiers::Volatile)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc());
+ if (Quals & Qualifiers::Restrict)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc());
+ }
+
+ if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
+ // C++ [dcl.fct]p6:
+ // Types shall not be defined in return or parameter types.
+ TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
+ if (Tag->isDefinition())
+ Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
+ << Context.getTypeDeclType(Tag);
+ }
+
+ // Exception specs are not allowed in typedefs. Complain, but add it
+ // anyway.
+ if (FTI.hasExceptionSpec &&
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef);
+
+ if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) {
+ // Simple void foo(), where the incoming T is the result type.
+ T = Context.getFunctionNoProtoType(T);
+ } else {
+ // We allow a zero-parameter variadic function in C if the
+ // function is marked with the "overloadable" attribute. Scan
+ // for this attribute now.
+ if (!FTI.NumArgs && FTI.isVariadic && !getLangOptions().CPlusPlus) {
+ bool Overloadable = false;
+ for (const AttributeList *Attrs = D.getAttributes();
+ Attrs; Attrs = Attrs->getNext()) {
+ if (Attrs->getKind() == AttributeList::AT_overloadable) {
+ Overloadable = true;
+ break;
+ }
+ }
+
+ if (!Overloadable)
+ Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
+ }
+
+ if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
+ // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
+ // definition.
+ Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+ D.setInvalidType(true);
+ break;
+ }
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = FTI.isVariadic;
+ EPI.TypeQuals = FTI.TypeQuals;
+ EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
+ : FTI.RefQualifierIsLValueRef? RQ_LValue
+ : RQ_RValue;
+
+ // Otherwise, we have a function with an argument list that is
+ // potentially variadic.
+ llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.reserve(FTI.NumArgs);
+
+ for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ QualType ArgTy = Param->getType();
+ assert(!ArgTy.isNull() && "Couldn't parse type?");
+
+ // Adjust the parameter type.
+ assert((ArgTy == adjustParameterType(ArgTy)) && "Unadjusted type?");
+
+ // Look for 'void'. void is allowed only as a single argument to a
+ // function with no other parameters (C99 6.7.5.3p10). We record
+ // int(void) as a FunctionProtoType with an empty argument list.
+ if (ArgTy->isVoidType()) {
+ // If this is something like 'float(int, void)', reject it. 'void'
+ // is an incomplete type (C99 6.2.5p19) and function decls cannot
+ // have arguments of incomplete type.
+ if (FTI.NumArgs != 1 || FTI.isVariadic) {
+ Diag(DeclType.Loc, diag::err_void_only_param);
+ ArgTy = Context.IntTy;
+ Param->setType(ArgTy);
+ } else if (FTI.ArgInfo[i].Ident) {
+ // Reject, but continue to parse 'int(void abc)'.
+ Diag(FTI.ArgInfo[i].IdentLoc,
+ diag::err_param_with_void_type);
+ ArgTy = Context.IntTy;
+ Param->setType(ArgTy);
+ } else {
+ // Reject, but continue to parse 'float(const void)'.
+ if (ArgTy.hasQualifiers())
+ Diag(DeclType.Loc, diag::err_void_param_qualified);
+
+ // Do not add 'void' to the ArgTys list.
+ break;
+ }
+ } else if (!FTI.hasPrototype) {
+ if (ArgTy->isPromotableIntegerType()) {
+ ArgTy = Context.getPromotedIntegerType(ArgTy);
+ } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
+ if (BTy->getKind() == BuiltinType::Float)
+ ArgTy = Context.DoubleTy;
+ }
+ }
+
+ ArgTys.push_back(ArgTy);
+ }
+
+ llvm::SmallVector<QualType, 4> Exceptions;
+ if (FTI.hasExceptionSpec) {
+ EPI.HasExceptionSpec = FTI.hasExceptionSpec;
+ EPI.HasAnyExceptionSpec = FTI.hasAnyExceptionSpec;
+ Exceptions.reserve(FTI.NumExceptions);
+ for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
+ // FIXME: Preserve type source info.
+ QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty);
+ // Check that the type is valid for an exception spec, and
+ // drop it if not.
+ if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
+ Exceptions.push_back(ET);
+ }
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ }
+
+ T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
+ }
+
+ break;
+ }
+ case DeclaratorChunk::MemberPointer:
+ // The scope spec must refer to a class, or be dependent.
+ CXXScopeSpec &SS = DeclType.Mem.Scope();
+ QualType ClsType;
+ if (SS.isInvalid()) {
+ // Avoid emitting extra errors if we already errored on the scope.
+ D.setInvalidType(true);
+ } else if (isDependentScopeSpecifier(SS) ||
+ dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS))) {
+ NestedNameSpecifier *NNS
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
+ NNS->getAsIdentifier());
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::Global:
+ llvm_unreachable("Nested-name-specifier must name a type");
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ ClsType = QualType(NNS->getAsType(), 0);
+ // Note: if NNS is dependent, then its prefix (if any) is already
+ // included in ClsType; this does not hold if the NNS is
+ // nondependent: in this case (if there is indeed a prefix)
+ // ClsType needs to be wrapped into an elaborated type.
+ if (NNSPrefix && !NNS->isDependent())
+ ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
+ break;
+ }
+ } else {
+ Diag(DeclType.Mem.Scope().getBeginLoc(),
+ diag::err_illegal_decl_mempointer_in_nonclass)
+ << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+ << DeclType.Mem.Scope().getRange();
+ D.setInvalidType(true);
+ }
+
+ if (!ClsType.isNull())
+ T = BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
+ if (T.isNull()) {
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ } else if (DeclType.Mem.TypeQuals) {
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
+ }
+ break;
+ }
+
+ if (T.isNull()) {
+ D.setInvalidType(true);
+ T = Context.IntTy;
+ }
+
+ // See if there are any attributes on this declarator chunk.
+ if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
+ processTypeAttrs(state, T, false, attrs);
+ }
+
+ if (getLangOptions().CPlusPlus && T->isFunctionType()) {
+ const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
+ assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
+
+ // C++ 8.3.5p4:
+ // A cv-qualifier-seq shall only be part of the function type
+ // for a nonstatic member function, the function type to which a pointer
+ // to member refers, or the top-level function type of a function typedef
+ // declaration.
+ //
+ // Core issue 547 also allows cv-qualifiers on function types that are
+ // top-level template type arguments.
+ bool FreeFunction;
+ if (!D.getCXXScopeSpec().isSet()) {
+ FreeFunction = (D.getContext() != Declarator::MemberContext ||
+ D.getDeclSpec().isFriendSpecified());
+ } else {
+ DeclContext *DC = computeDeclContext(D.getCXXScopeSpec());
+ FreeFunction = (DC && !DC->isRecord());
+ }
+
+ // C++0x [dcl.fct]p6:
+ // A ref-qualifier shall only be part of the function type for a
+ // non-static member function, the function type to which a pointer to
+ // member refers, or the top-level function type of a function typedef
+ // declaration.
+ if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) &&
+ !(D.getContext() == Declarator::TemplateTypeArgContext &&
+ !D.isFunctionDeclarator()) &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ (FreeFunction ||
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
+ if (D.getContext() == Declarator::TemplateTypeArgContext) {
+ // Accept qualified function types as template type arguments as a GNU
+ // extension. This is also the subject of C++ core issue 547.
+ std::string Quals;
+ if (FnTy->getTypeQuals() != 0)
+ Quals = Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
+
+ switch (FnTy->getRefQualifier()) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += '&';
+ break;
+
+ case RQ_RValue:
+ if (!Quals.empty())
+ Quals += ' ';
+ Quals += "&&";
+ break;
+ }
+
+ Diag(D.getIdentifierLoc(),
+ diag::ext_qualified_function_type_template_arg)
+ << Quals;
+ } else {
+ if (FnTy->getTypeQuals() != 0) {
+ if (D.isFunctionDeclarator())
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_qualified_function_type);
+ else
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_qualified_typedef_function_type_use)
+ << FreeFunction;
+ }
+
+ if (FnTy->getRefQualifier()) {
+ if (D.isFunctionDeclarator()) {
+ SourceLocation Loc = D.getIdentifierLoc();
+ for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
+ const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
+ if (Chunk.Kind == DeclaratorChunk::Function &&
+ Chunk.Fun.hasRefQualifier()) {
+ Loc = Chunk.Fun.getRefQualifierLoc();
+ break;
+ }
+ }
+
+ Diag(Loc, diag::err_invalid_ref_qualifier_function_type)
+ << (FnTy->getRefQualifier() == RQ_LValue)
+ << FixItHint::CreateRemoval(Loc);
+ } else {
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_ref_qualifier_typedef_function_type_use)
+ << FreeFunction
+ << (FnTy->getRefQualifier() == RQ_LValue);
+ }
+ }
+
+ // Strip the cv-qualifiers and ref-qualifiers from the type.
+ FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
+ EPI.TypeQuals = 0;
+ EPI.RefQualifier = RQ_None;
+
+ T = Context.getFunctionType(FnTy->getResultType(),
+ FnTy->arg_type_begin(),
+ FnTy->getNumArgs(), EPI);
+ }
+ }
+ }
+
+ // Apply any undistributed attributes from the declarator.
+ if (!T.isNull())
+ if (AttributeList *attrs = D.getAttributes())
+ processTypeAttrs(state, T, false, attrs);
+
+ // Diagnose any ignored type attributes.
+ if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
+
+ // If there's a constexpr specifier, treat it as a top-level const.
+ if (D.getDeclSpec().isConstexprSpecified()) {
+ T.addConst();
+ }
+
+ // If there was an ellipsis in the declarator, the declaration declares a
+ // parameter pack whose type may be a pack expansion type.
+ if (D.hasEllipsis() && !T.isNull()) {
+ // C++0x [dcl.fct]p13:
+ // A declarator-id or abstract-declarator containing an ellipsis shall
+ // only be used in a parameter-declaration. Such a parameter-declaration
+ // is a parameter pack (14.5.3). [...]
+ switch (D.getContext()) {
+ case Declarator::PrototypeContext:
+ // C++0x [dcl.fct]p13:
+ // [...] When it is part of a parameter-declaration-clause, the
+ // parameter pack is a function parameter pack (14.5.3). The type T
+ // of the declarator-id of the function parameter pack shall contain
+ // a template parameter pack; each template parameter pack in T is
+ // expanded by the function parameter pack.
+ //
+ // We represent function parameter packs as function parameters whose
+ // type is a pack expansion.
+ if (!T->containsUnexpandedParameterPack()) {
+ Diag(D.getEllipsisLoc(),
+ diag::err_function_parameter_pack_without_parameter_packs)
+ << T << D.getSourceRange();
+ D.setEllipsisLoc(SourceLocation());
+ } else {
+ T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+ }
+ break;
+
+ case Declarator::TemplateParamContext:
+ // C++0x [temp.param]p15:
+ // If a template-parameter is a [...] is a parameter-declaration that
+ // declares a parameter pack (8.3.5), then the template-parameter is a
+ // template parameter pack (14.5.3).
+ //
+ // Note: core issue 778 clarifies that, if there are any unexpanded
+ // parameter packs in the type of the non-type template parameter, then
+ // it expands those parameter packs.
+ if (T->containsUnexpandedParameterPack())
+ T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
+ else if (!getLangOptions().CPlusPlus0x)
+ Diag(D.getEllipsisLoc(), diag::ext_variadic_templates);
+ break;
+
+ case Declarator::FileContext:
+ case Declarator::KNRTypeListContext:
+ case Declarator::TypeNameContext:
+ case Declarator::MemberContext:
+ case Declarator::BlockContext:
+ case Declarator::ForContext:
+ case Declarator::ConditionContext:
+ case Declarator::CXXCatchContext:
+ case Declarator::BlockLiteralContext:
+ case Declarator::TemplateTypeArgContext:
+ // FIXME: We may want to allow parameter packs in block-literal contexts
+ // in the future.
+ Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
+ D.setEllipsisLoc(SourceLocation());
+ break;
+ }
+ }
+
+ if (T.isNull())
+ return Context.getNullTypeSourceInfo();
+ else if (D.isInvalidType())
+ return Context.getTrivialTypeSourceInfo(T);
+ return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo);
+}
+
+namespace {
+ class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
+ ASTContext &Context;
+ const DeclSpec &DS;
+
+ public:
+ TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
+ : Context(Context), DS(DS) {}
+
+ void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ Visit(TL.getUnqualifiedLoc());
+ }
+ void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
+ void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
+ void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ // Handle the base type, which might not have been written explicitly.
+ if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+ TL.setHasBaseTypeAsWritten(false);
+ TL.getBaseLoc().initialize(Context, SourceLocation());
+ } else {
+ TL.setHasBaseTypeAsWritten(true);
+ Visit(TL.getBaseLoc());
+ }
+
+ // Protocol qualifiers.
+ if (DS.getProtocolQualifiers()) {
+ assert(TL.getNumProtocols() > 0);
+ assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+ TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+ TL.setRAngleLoc(DS.getSourceRange().getEnd());
+ for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+ TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
+ } else {
+ assert(TL.getNumProtocols() == 0);
+ TL.setLAngleLoc(SourceLocation());
+ TL.setRAngleLoc(SourceLocation());
+ }
+ }
+ void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ TL.setStarLoc(SourceLocation());
+ Visit(TL.getPointeeLoc());
+ }
+ void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+
+ // If we got no declarator info from previous Sema routines,
+ // just fill with the typespec loc.
+ if (!TInfo) {
+ TL.initialize(Context, DS.getTypeSpecTypeLoc());
+ return;
+ }
+
+ TypeLoc OldTL = TInfo->getTypeLoc();
+ if (TInfo->getType()->getAs<ElaboratedType>()) {
+ ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
+ TemplateSpecializationTypeLoc NamedTL =
+ cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
+ TL.copy(NamedTL);
+ }
+ else
+ TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
+ }
+ void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+ TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
+ }
+ void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+ TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
+ assert(DS.getRepAsType());
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ TL.setUnderlyingTInfo(TInfo);
+ }
+ void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ // By default, use the source location of the type specifier.
+ TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
+ if (TL.needsExtraLocalData()) {
+ // Set info for the written builtin specifiers.
+ TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
+ // Try to have a meaningful source location.
+ if (TL.getWrittenSignSpec() != TSS_unspecified)
+ // Sign spec loc overrides the others (e.g., 'unsigned long').
+ TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
+ else if (TL.getWrittenWidthSpec() != TSW_unspecified)
+ // Width spec loc overrides type spec loc (e.g., 'short int').
+ TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
+ }
+ }
+ void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
+ return;
+ }
+ }
+ TL.setKeywordLoc(Keyword != ETK_None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
+ const CXXScopeSpec& SS = DS.getTypeSpecScope();
+ TL.setQualifierRange(SS.isEmpty() ? SourceRange(): SS.getRange());
+ Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
+ }
+ void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+ if (DS.getTypeSpecType() == TST_typename) {
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
+ return;
+ }
+ }
+ TL.setKeywordLoc(Keyword != ETK_None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
+ const CXXScopeSpec& SS = DS.getTypeSpecScope();
+ TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
+ // FIXME: load appropriate source location.
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
+ void VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+ if (Keyword == ETK_Typename) {
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ if (TInfo) {
+ TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
+ TInfo->getTypeLoc()));
+ return;
+ }
+ }
+ TL.initializeLocal(Context, SourceLocation());
+ TL.setKeywordLoc(Keyword != ETK_None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
+ const CXXScopeSpec& SS = DS.getTypeSpecScope();
+ TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
+ // FIXME: load appropriate source location.
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
+
+ void VisitTypeLoc(TypeLoc TL) {
+ // FIXME: add other typespec types and change this to an assert.
+ TL.initialize(Context, DS.getTypeSpecTypeLoc());
+ }
+ };
+
+ class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+ const DeclaratorChunk &Chunk;
+
+ public:
+ DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {}
+
+ void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ llvm_unreachable("qualified type locs not expected here!");
+ }
+
+ void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
+ TL.setCaretLoc(Chunk.Loc);
+ }
+ void VisitPointerTypeLoc(PointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pointer);
+ TL.setStarLoc(Chunk.Loc);
+ }
+ void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pointer);
+ TL.setStarLoc(Chunk.Loc);
+ }
+ void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+ TL.setStarLoc(Chunk.Loc);
+ // FIXME: nested name specifier
+ }
+ void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Reference);
+ // 'Amp' is misleading: this might have been originally
+ /// spelled with AmpAmp.
+ TL.setAmpLoc(Chunk.Loc);
+ }
+ void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Reference);
+ assert(!Chunk.Ref.LValueRef);
+ TL.setAmpAmpLoc(Chunk.Loc);
+ }
+ void VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Array);
+ TL.setLBracketLoc(Chunk.Loc);
+ TL.setRBracketLoc(Chunk.EndLoc);
+ TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
+ }
+ void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Function);
+ TL.setLParenLoc(Chunk.Loc);
+ TL.setRParenLoc(Chunk.EndLoc);
+ TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
+
+ const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
+ for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
+ TL.setArg(tpi++, Param);
+ }
+ // FIXME: exception specs
+ }
+ void VisitParenTypeLoc(ParenTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Paren);
+ TL.setLParenLoc(Chunk.Loc);
+ TL.setRParenLoc(Chunk.EndLoc);
+ }
+
+ void VisitTypeLoc(TypeLoc TL) {
+ llvm_unreachable("unsupported TypeLoc kind in declarator!");
+ }
+ };
+}
+
+/// \brief Create and instantiate a TypeSourceInfo with type source information.
+///
+/// \param T QualType referring to the type as written in source code.
+///
+/// \param ReturnTypeInfo For declarators whose return type does not show
+/// up in the normal place in the declaration specifiers (such as a C++
+/// conversion function), this pointer will refer to a type source information
+/// for that return type.
+TypeSourceInfo *
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+ TypeSourceInfo *ReturnTypeInfo) {
+ TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
+ UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
+
+ // Handle parameter packs whose type is a pack expansion.
+ if (isa<PackExpansionType>(T)) {
+ cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
+ CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+ }
+
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+ CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+ }
+
+ // If we have different source information for the return type, use
+ // that. This really only applies to C++ conversion functions.
+ if (ReturnTypeInfo) {
+ TypeLoc TL = ReturnTypeInfo->getTypeLoc();
+ assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
+ memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
+ } else {
+ TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
+ }
+
+ return TInfo;
+}
+
+/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
+ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
+ // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
+ // and Sema during declaration parsing. Try deallocating/caching them when
+ // it's appropriate, instead of allocating them and keeping them around.
+ LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
+ TypeAlignment);
+ new (LocT) LocInfoType(T, TInfo);
+ assert(LocT->getTypeClass() != T->getTypeClass() &&
+ "LocInfoType's TypeClass conflicts with an existing Type class");
+ return ParsedType::make(QualType(LocT, 0));
+}
+
+void LocInfoType::getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const {
+ assert(false && "LocInfoType leaked into the type system; an opaque TypeTy*"
+ " was used directly instead of getting the QualType through"
+ " GetTypeFromParser");
+}
+
+TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
+ // C99 6.7.6: Type names have no identifier. This is already validated by
+ // the parser.
+ assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
+
+ TagDecl *OwnedTag = 0;
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag);
+ QualType T = TInfo->getType();
+ if (D.isInvalidType())
+ return true;
+
+ if (getLangOptions().CPlusPlus) {
+ // Check that there are no default arguments (C++ only).
+ CheckExtraCXXDefaultArguments(D);
+
+ // C++0x [dcl.type]p3:
+ // A type-specifier-seq shall not define a class or enumeration
+ // unless it appears in the type-id of an alias-declaration
+ // (7.1.3).
+ if (OwnedTag && OwnedTag->isDefinition())
+ Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier)
+ << Context.getTypeDeclType(OwnedTag);
+ }
+
+ return CreateParsedType(T, TInfo);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Type Attribute Processing
+//===----------------------------------------------------------------------===//
+
+/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
+/// specified type. The attribute contains 1 argument, the id of the address
+/// space for the type.
+static void HandleAddressSpaceTypeAttribute(QualType &Type,
+ const AttributeList &Attr, Sema &S){
+
+ // If this type is already address space qualified, reject it.
+ // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
+ // for two or more different address spaces."
+ if (Type.getAddressSpace()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+ Attr.setInvalid();
+ return;
+ }
+
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt addrSpace(32);
+ if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
+ !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
+ << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+
+ // Bounds checking.
+ if (addrSpace.isSigned()) {
+ if (addrSpace.isNegative()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
+ << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ addrSpace.setIsSigned(false);
+ }
+ llvm::APSInt max(addrSpace.getBitWidth());
+ max = Qualifiers::MaxAddressSpace;
+ if (addrSpace > max) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
+ << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+
+ unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
+ Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
+}
+
+/// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
+/// attribute on the specified type. Returns true to indicate that
+/// the attribute was handled, false to indicate that the type does
+/// not permit the attribute.
+static bool handleObjCGCTypeAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &type) {
+ Sema &S = state.getSema();
+
+ // Delay if this isn't some kind of pointer.
+ if (!type->isPointerType() &&
+ !type->isObjCObjectPointerType() &&
+ !type->isBlockPointerType())
+ return false;
+
+ if (type.getObjCGCAttr() != Qualifiers::GCNone) {
+ S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+ attr.setInvalid();
+ return true;
+ }
+
+ // Check the attribute arguments.
+ if (!attr.getParameterName()) {
+ S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "objc_gc" << 1;
+ attr.setInvalid();
+ return true;
+ }
+ Qualifiers::GC GCAttr;
+ if (attr.getNumArgs() != 0) {
+ S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ attr.setInvalid();
+ return true;
+ }
+ if (attr.getParameterName()->isStr("weak"))
+ GCAttr = Qualifiers::Weak;
+ else if (attr.getParameterName()->isStr("strong"))
+ GCAttr = Qualifiers::Strong;
+ else {
+ S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << "objc_gc" << attr.getParameterName();
+ attr.setInvalid();
+ return true;
+ }
+
+ type = S.Context.getObjCGCQualType(type, GCAttr);
+ return true;
+}
+
+namespace {
+ /// A helper class to unwrap a type down to a function for the
+ /// purposes of applying attributes there.
+ ///
+ /// Use:
+ /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
+ /// if (unwrapped.isFunctionType()) {
+ /// const FunctionType *fn = unwrapped.get();
+ /// // change fn somehow
+ /// T = unwrapped.wrap(fn);
+ /// }
+ struct FunctionTypeUnwrapper {
+ enum WrapKind {
+ Desugar,
+ Parens,
+ Pointer,
+ BlockPointer,
+ Reference,
+ MemberPointer
+ };
+
+ QualType Original;
+ const FunctionType *Fn;
+ llvm::SmallVector<unsigned char /*WrapKind*/, 8> Stack;
+
+ FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
+ while (true) {
+ const Type *Ty = T.getTypePtr();
+ if (isa<FunctionType>(Ty)) {
+ Fn = cast<FunctionType>(Ty);
+ return;
+ } else if (isa<ParenType>(Ty)) {
+ T = cast<ParenType>(Ty)->getInnerType();
+ Stack.push_back(Parens);
+ } else if (isa<PointerType>(Ty)) {
+ T = cast<PointerType>(Ty)->getPointeeType();
+ Stack.push_back(Pointer);
+ } else if (isa<BlockPointerType>(Ty)) {
+ T = cast<BlockPointerType>(Ty)->getPointeeType();
+ Stack.push_back(BlockPointer);
+ } else if (isa<MemberPointerType>(Ty)) {
+ T = cast<MemberPointerType>(Ty)->getPointeeType();
+ Stack.push_back(MemberPointer);
+ } else if (isa<ReferenceType>(Ty)) {
+ T = cast<ReferenceType>(Ty)->getPointeeType();
+ Stack.push_back(Reference);
+ } else {
+ const Type *DTy = Ty->getUnqualifiedDesugaredType();
+ if (Ty == DTy) {
+ Fn = 0;
+ return;
+ }
+
+ T = QualType(DTy, 0);
+ Stack.push_back(Desugar);
+ }
+ }
+ }
+
+ bool isFunctionType() const { return (Fn != 0); }
+ const FunctionType *get() const { return Fn; }
+
+ QualType wrap(Sema &S, const FunctionType *New) {
+ // If T wasn't modified from the unwrapped type, do nothing.
+ if (New == get()) return Original;
+
+ Fn = New;
+ return wrap(S.Context, Original, 0);
+ }
+
+ private:
+ QualType wrap(ASTContext &C, QualType Old, unsigned I) {
+ if (I == Stack.size())
+ return C.getQualifiedType(Fn, Old.getQualifiers());
+
+ // Build up the inner type, applying the qualifiers from the old
+ // type to the new type.
+ SplitQualType SplitOld = Old.split();
+
+ // As a special case, tail-recurse if there are no qualifiers.
+ if (SplitOld.second.empty())
+ return wrap(C, SplitOld.first, I);
+ return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second);
+ }
+
+ QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
+ if (I == Stack.size()) return QualType(Fn, 0);
+
+ switch (static_cast<WrapKind>(Stack[I++])) {
+ case Desugar:
+ // This is the point at which we potentially lose source
+ // information.
+ return wrap(C, Old->getUnqualifiedDesugaredType(), I);
+
+ case Parens: {
+ QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
+ return C.getParenType(New);
+ }
+
+ case Pointer: {
+ QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
+ return C.getPointerType(New);
+ }
+
+ case BlockPointer: {
+ QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
+ return C.getBlockPointerType(New);
+ }
+
+ case MemberPointer: {
+ const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
+ QualType New = wrap(C, OldMPT->getPointeeType(), I);
+ return C.getMemberPointerType(New, OldMPT->getClass());
+ }
+
+ case Reference: {
+ const ReferenceType *OldRef = cast<ReferenceType>(Old);
+ QualType New = wrap(C, OldRef->getPointeeType(), I);
+ if (isa<LValueReferenceType>(OldRef))
+ return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
+ else
+ return C.getRValueReferenceType(New);
+ }
+ }
+
+ llvm_unreachable("unknown wrapping kind");
+ return QualType();
+ }
+ };
+}
+
+/// Process an individual function attribute. Returns true to
+/// indicate that the attribute was handled, false if it wasn't.
+static bool handleFunctionTypeAttr(TypeProcessingState &state,
+ AttributeList &attr,
+ QualType &type) {
+ Sema &S = state.getSema();
+
+ FunctionTypeUnwrapper unwrapped(S, type);
+
+ if (attr.getKind() == AttributeList::AT_noreturn) {
+ if (S.CheckNoReturnAttr(attr))
+ return true;
+
+ // Delay if this is not a function type.
+ if (!unwrapped.isFunctionType())
+ return false;
+
+ // Otherwise we can process right away.
+ FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
+ if (attr.getKind() == AttributeList::AT_regparm) {
+ unsigned value;
+ if (S.CheckRegparmAttr(attr, value))
+ return true;
+
+ // Delay if this is not a function type.
+ if (!unwrapped.isFunctionType())
+ return false;
+
+ // Diagnose regparm with fastcall.
+ const FunctionType *fn = unwrapped.get();
+ CallingConv CC = fn->getCallConv();
+ if (CC == CC_X86FastCall) {
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << "regparm";
+ attr.setInvalid();
+ return true;
+ }
+
+ FunctionType::ExtInfo EI =
+ unwrapped.get()->getExtInfo().withRegParm(value);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
+ // Otherwise, a calling convention.
+ CallingConv CC;
+ if (S.CheckCallingConvAttr(attr, CC))
+ return true;
+
+ // Delay if the type didn't work out to a function.
+ if (!unwrapped.isFunctionType()) return false;
+
+ const FunctionType *fn = unwrapped.get();
+ CallingConv CCOld = fn->getCallConv();
+ if (S.Context.getCanonicalCallConv(CC) ==
+ S.Context.getCanonicalCallConv(CCOld)) {
+ FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+ }
+
+ if (CCOld != CC_Default) {
+ // Should we diagnose reapplications of the same convention?
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld);
+ attr.setInvalid();
+ return true;
+ }
+
+ // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
+ if (CC == CC_X86FastCall) {
+ if (isa<FunctionNoProtoType>(fn)) {
+ S.Diag(attr.getLoc(), diag::err_cconv_knr)
+ << FunctionType::getNameForCallConv(CC);
+ attr.setInvalid();
+ return true;
+ }
+
+ const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
+ if (FnP->isVariadic()) {
+ S.Diag(attr.getLoc(), diag::err_cconv_varargs)
+ << FunctionType::getNameForCallConv(CC);
+ attr.setInvalid();
+ return true;
+ }
+
+ // Also diagnose fastcall with regparm.
+ if (fn->getRegParmType()) {
+ S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "regparm"
+ << FunctionType::getNameForCallConv(CC);
+ attr.setInvalid();
+ return true;
+ }
+ }
+
+ FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
+ type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ return true;
+}
+
+/// HandleVectorSizeAttribute - this attribute is only applicable to integral
+/// and float scalars, although arrays, pointers, and function return values are
+/// allowed in conjunction with this construct. Aggregates with this attribute
+/// are invalid, even if they are of the same size as a corresponding scalar.
+/// The raw attribute should contain precisely 1 argument, the vector size for
+/// the variable, measured in bytes. If curType and rawAttr are well formed,
+/// this routine will return a new vector type.
+static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt vecSize(32);
+ if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
+ !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "vector_size" << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ // the base type must be integer or float, and can't already be a vector.
+ if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
+ Attr.setInvalid();
+ return;
+ }
+ unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
+ // vecSize is specified in bytes - convert to bits.
+ unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
+
+ // the vector size needs to be an integral multiple of the type size.
+ if (vectorSize % typeSize) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ if (vectorSize == 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
+ << sizeExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+
+ // Success! Instantiate the vector type, the number of elements is > 0, and
+ // not required to be a power of 2, unlike GCC.
+ CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
+ VectorType::GenericVector);
+}
+
+/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
+/// "neon_polyvector_type" attributes are used to create vector types that
+/// are mangled according to ARM's ABI. Otherwise, these types are identical
+/// to those created with the "vector_size" attribute. Unlike "vector_size"
+/// the argument to these Neon attributes is the number of vector elements,
+/// not the vector size in bytes. The vector width and element type must
+/// match one of the standard Neon vector types.
+static void HandleNeonVectorTypeAttr(QualType& CurType,
+ const AttributeList &Attr, Sema &S,
+ VectorType::VectorKind VecKind,
+ const char *AttrName) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ // The number of elements must be an ICE.
+ Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt numEltsInt(32);
+ if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
+ !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << AttrName << numEltsExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ // Only certain element types are supported for Neon vectors.
+ const BuiltinType* BTy = CurType->getAs<BuiltinType>();
+ if (!BTy ||
+ (VecKind == VectorType::NeonPolyVector &&
+ BTy->getKind() != BuiltinType::SChar &&
+ BTy->getKind() != BuiltinType::Short) ||
+ (BTy->getKind() != BuiltinType::SChar &&
+ BTy->getKind() != BuiltinType::UChar &&
+ BTy->getKind() != BuiltinType::Short &&
+ BTy->getKind() != BuiltinType::UShort &&
+ BTy->getKind() != BuiltinType::Int &&
+ BTy->getKind() != BuiltinType::UInt &&
+ BTy->getKind() != BuiltinType::LongLong &&
+ BTy->getKind() != BuiltinType::ULongLong &&
+ BTy->getKind() != BuiltinType::Float)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
+ Attr.setInvalid();
+ return;
+ }
+ // The total size of the vector must be 64 or 128 bits.
+ unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
+ unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
+ unsigned vecSize = typeSize * numElts;
+ if (vecSize != 64 && vecSize != 128) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
+ Attr.setInvalid();
+ return;
+ }
+
+ CurType = S.Context.getVectorType(CurType, numElts, VecKind);
+}
+
+static void processTypeAttrs(TypeProcessingState &state, QualType &type,
+ bool isDeclSpec, AttributeList *attrs) {
+ // Scan through and apply attributes to this type where it makes sense. Some
+ // attributes (such as __address_space__, __vector_size__, etc) apply to the
+ // type, but others can be present in the type specifiers even though they
+ // apply to the decl. Here we apply type attributes and ignore the rest.
+
+ AttributeList *next;
+ do {
+ AttributeList &attr = *attrs;
+ next = attr.getNext();
+
+ // Skip attributes that were marked to be invalid.
+ if (attr.isInvalid())
+ continue;
+
+ // If this is an attribute we can handle, do so now,
+ // otherwise, add it to the FnAttrs list for rechaining.
+ switch (attr.getKind()) {
+ default: break;
+
+ case AttributeList::AT_address_space:
+ HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+ break;
+ OBJC_POINTER_TYPE_ATTRS_CASELIST:
+ if (!handleObjCPointerTypeAttr(state, attr, type))
+ distributeObjCPointerTypeAttr(state, attr, type);
+ break;
+ case AttributeList::AT_vector_size:
+ HandleVectorSizeAttr(type, attr, state.getSema());
+ break;
+ case AttributeList::AT_neon_vector_type:
+ HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+ VectorType::NeonVector, "neon_vector_type");
+ break;
+ case AttributeList::AT_neon_polyvector_type:
+ HandleNeonVectorTypeAttr(type, attr, state.getSema(),
+ VectorType::NeonPolyVector,
+ "neon_polyvector_type");
+ break;
+
+ FUNCTION_TYPE_ATTRS_CASELIST:
+ // Never process function type attributes as part of the
+ // declaration-specifiers.
+ if (isDeclSpec)
+ distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
+
+ // Otherwise, handle the possible delays.
+ else if (!handleFunctionTypeAttr(state, attr, type))
+ distributeFunctionTypeAttr(state, attr, type);
+ break;
+ }
+ } while ((attrs = next));
+}
+
+/// @brief Ensure that the type T is a complete type.
+///
+/// This routine checks whether the type @p T is complete in any
+/// context where a complete type is required. If @p T is a complete
+/// type, returns false. If @p T is a class template specialization,
+/// this routine then attempts to perform class template
+/// instantiation. If instantiation fails, or if @p T is incomplete
+/// and cannot be completed, issues the diagnostic @p diag (giving it
+/// the type @p T) and returns true.
+///
+/// @param Loc The location in the source that the incomplete type
+/// diagnostic should refer to.
+///
+/// @param T The type that this routine is examining for completeness.
+///
+/// @param PD The partial diagnostic that will be printed out if T is not a
+/// complete type.
+///
+/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
+/// @c false otherwise.
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD,
+ std::pair<SourceLocation,
+ PartialDiagnostic> Note) {
+ unsigned diag = PD.getDiagID();
+
+ // FIXME: Add this assertion to make sure we always get instantiation points.
+ // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
+ // FIXME: Add this assertion to help us flush out problems with
+ // checking for dependent types and type-dependent expressions.
+ //
+ // assert(!T->isDependentType() &&
+ // "Can't ask whether a dependent type is complete");
+
+ // If we have a complete type, we're done.
+ if (!T->isIncompleteType())
+ return false;
+
+ // If we have a class template specialization or a class member of a
+ // class template specialization, or an array with known size of such,
+ // try to instantiate it.
+ QualType MaybeTemplate = T;
+ if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T))
+ MaybeTemplate = Array->getElementType();
+ if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+ if (ClassTemplateSpecializationDecl *ClassTemplateSpec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+ if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
+ return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
+ TSK_ImplicitInstantiation,
+ /*Complain=*/diag != 0);
+ } else if (CXXRecordDecl *Rec
+ = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
+ if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
+ MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ // This record was instantiated from a class within a template.
+ if (MSInfo->getTemplateSpecializationKind()
+ != TSK_ExplicitSpecialization)
+ return InstantiateClass(Loc, Rec, Pattern,
+ getTemplateInstantiationArgs(Rec),
+ TSK_ImplicitInstantiation,
+ /*Complain=*/diag != 0);
+ }
+ }
+ }
+
+ if (diag == 0)
+ return true;
+
+ const TagType *Tag = T->getAs<TagType>();
+
+ // Avoid diagnosing invalid decls as incomplete.
+ if (Tag && Tag->getDecl()->isInvalidDecl())
+ return true;
+
+ // Give the external AST source a chance to complete the type.
+ if (Tag && Tag->getDecl()->hasExternalLexicalStorage()) {
+ Context.getExternalSource()->CompleteType(Tag->getDecl());
+ if (!Tag->isIncompleteType())
+ return false;
+ }
+
+ // We have an incomplete type. Produce a diagnostic.
+ Diag(Loc, PD) << T;
+
+ // If we have a note, produce it.
+ if (!Note.first.isInvalid())
+ Diag(Note.first, Note.second);
+
+ // If the type was a forward declaration of a class/struct/union
+ // type, produce a note.
+ if (Tag && !Tag->getDecl()->isInvalidDecl())
+ Diag(Tag->getDecl()->getLocation(),
+ Tag->isBeingDefined() ? diag::note_type_being_defined
+ : diag::note_forward_declaration)
+ << QualType(Tag, 0);
+
+ return true;
+}
+
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD) {
+ return RequireCompleteType(Loc, T, PD,
+ std::make_pair(SourceLocation(), PDiag(0)));
+}
+
+bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID) {
+ return RequireCompleteType(Loc, T, PDiag(DiagID),
+ std::make_pair(SourceLocation(), PDiag(0)));
+}
+
+/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
+/// and qualified by the nested-name-specifier contained in SS.
+QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
+ const CXXScopeSpec &SS, QualType T) {
+ if (T.isNull())
+ return T;
+ NestedNameSpecifier *NNS;
+ if (SS.isValid())
+ NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ else {
+ if (Keyword == ETK_None)
+ return T;
+ NNS = 0;
+ }
+ return Context.getElaboratedType(Keyword, NNS, T);
+}
+
+QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
+ ExprResult ER = CheckPlaceholderExpr(E, Loc);
+ if (ER.isInvalid()) return QualType();
+ E = ER.take();
+
+ if (!E->isTypeDependent()) {
+ QualType T = E->getType();
+ if (const TagType *TT = T->getAs<TagType>())
+ DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
+ }
+ return Context.getTypeOfExprType(E);
+}
+
+QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
+ ExprResult ER = CheckPlaceholderExpr(E, Loc);
+ if (ER.isInvalid()) return QualType();
+ E = ER.take();
+
+ return Context.getDecltypeType(E);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
new file mode 100644
index 0000000..c3415cb
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp
@@ -0,0 +1,276 @@
+//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains semantic analysis implementation for target-specific
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetAttributesSema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+TargetAttributesSema::~TargetAttributesSema() {}
+bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ return false;
+}
+
+static void HandleMSP430InterruptAttr(Decl *d,
+ const AttributeList &Attr, Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt NumParams(32);
+ if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "interrupt" << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ unsigned Num = NumParams.getLimitedValue(255);
+ if ((Num & 1) || Num > 30) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "interrupt" << (int)NumParams.getSExtValue()
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+ }
+
+namespace {
+ class MSP430AttributesSema : public TargetAttributesSema {
+ public:
+ MSP430AttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ if (Attr.getName()->getName() == "interrupt") {
+ HandleMSP430InterruptAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
+static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(),
+ S.Context));
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(),
+ S.Context));
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
+}
+
+
+namespace {
+ class MBlazeAttributesSema : public TargetAttributesSema {
+ public:
+ MBlazeAttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
+ Sema &S) const {
+ if (Attr.getName()->getName() == "interrupt_handler") {
+ HandleMBlazeInterruptHandlerAttr(D, Attr, S);
+ return true;
+ } else if (Attr.getName()->getName() == "save_volatiles") {
+ HandleMBlazeSaveVolatilesAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
+static void HandleX86ForceAlignArgPointerAttr(Decl *D,
+ const AttributeList& Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either. It doesn't matter anyway, because there's nothing
+ // special about calling a force_align_arg_pointer function.
+ ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
+ // Also don't warn on function pointer typedefs.
+ TypedefDecl *TD = dyn_cast<TypedefDecl>(D);
+ if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
+ TD->getUnderlyingType()->isFunctionType()))
+ return;
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(D)) {
+ D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) {
+ // Apparently Visual C++ thinks it is okay to not emit a warning
+ // in this case, so only emit a warning when -fms-extensions is not
+ // specified.
+ if (!S.getLangOptions().Microsoft)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Currently, the dllimport attribute is ignored for inlined functions.
+ // Warning is emitted.
+ if (FD->isInlineSpecified()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
+ // The attribute is also overridden by a subsequent declaration as dllexport.
+ // Warning is emitted.
+ for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+ nextAttr = nextAttr->getNext()) {
+ if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+ }
+
+ if (D->getAttr<DLLExportAttr>()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(D)) {
+ D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Currently, the dllexport attribute is ignored for inlined functions, unless
+ // the -fkeep-inline-functions flag has been used. Warning is emitted;
+ if (FD->isInlineSpecified()) {
+ // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
+}
+
+namespace {
+ class X86AttributesSema : public TargetAttributesSema {
+ public:
+ X86AttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ const llvm::Triple &Triple(S.Context.Target.getTriple());
+ if (Triple.getOS() == llvm::Triple::Win32 ||
+ Triple.getOS() == llvm::Triple::MinGW32) {
+ switch (Attr.getKind()) {
+ case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S);
+ return true;
+ case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S);
+ return true;
+ default: break;
+ }
+ }
+ if (Attr.getName()->getName() == "force_align_arg_pointer" ||
+ Attr.getName()->getName() == "__force_align_arg_pointer__") {
+ HandleX86ForceAlignArgPointerAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
+const TargetAttributesSema &Sema::getTargetAttributesSema() const {
+ if (TheTargetAttributesSema)
+ return *TheTargetAttributesSema;
+
+ const llvm::Triple &Triple(Context.Target.getTriple());
+ switch (Triple.getArch()) {
+ default:
+ return *(TheTargetAttributesSema = new TargetAttributesSema);
+
+ case llvm::Triple::msp430:
+ return *(TheTargetAttributesSema = new MSP430AttributesSema);
+ case llvm::Triple::mblaze:
+ return *(TheTargetAttributesSema = new MBlazeAttributesSema);
+ case llvm::Triple::x86:
+ return *(TheTargetAttributesSema = new X86AttributesSema);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h
new file mode 100644
index 0000000..410c900
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h
@@ -0,0 +1,27 @@
+//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_SEMA_TARGETSEMA_H
+#define CLANG_SEMA_TARGETSEMA_H
+
+namespace clang {
+ class Scope;
+ class Decl;
+ class AttributeList;
+ class Sema;
+
+ class TargetAttributesSema {
+ public:
+ virtual ~TargetAttributesSema();
+ virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const;
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
new file mode 100644
index 0000000..944e6a1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -0,0 +1,7786 @@
+//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+//
+// This file implements a semantic tree transformation that takes a given
+// AST and rebuilds it, possibly transforming some nodes in the process.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
+#define LLVM_CLANG_SEMA_TREETRANSFORM_H
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "TypeLocBuilder.h"
+#include <algorithm>
+
+namespace clang {
+using namespace sema;
+
+/// \brief A semantic tree transformation that allows one to transform one
+/// abstract syntax tree into another.
+///
+/// A new tree transformation is defined by creating a new subclass \c X of
+/// \c TreeTransform<X> and then overriding certain operations to provide
+/// behavior specific to that transformation. For example, template
+/// instantiation is implemented as a tree transformation where the
+/// transformation of TemplateTypeParmType nodes involves substituting the
+/// template arguments for their corresponding template parameters; a similar
+/// transformation is performed for non-type template parameters and
+/// template template parameters.
+///
+/// This tree-transformation template uses static polymorphism to allow
+/// subclasses to customize any of its operations. Thus, a subclass can
+/// override any of the transformation or rebuild operators by providing an
+/// operation with the same signature as the default implementation. The
+/// overridding function should not be virtual.
+///
+/// Semantic tree transformations are split into two stages, either of which
+/// can be replaced by a subclass. The "transform" step transforms an AST node
+/// or the parts of an AST node using the various transformation functions,
+/// then passes the pieces on to the "rebuild" step, which constructs a new AST
+/// node of the appropriate kind from the pieces. The default transformation
+/// routines recursively transform the operands to composite AST nodes (e.g.,
+/// the pointee type of a PointerType node) and, if any of those operand nodes
+/// were changed by the transformation, invokes the rebuild operation to create
+/// a new AST node.
+///
+/// Subclasses can customize the transformation at various levels. The
+/// most coarse-grained transformations involve replacing TransformType(),
+/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
+/// TransformTemplateName(), or TransformTemplateArgument() with entirely
+/// new implementations.
+///
+/// For more fine-grained transformations, subclasses can replace any of the
+/// \c TransformXXX functions (where XXX is the name of an AST node, e.g.,
+/// PointerType, StmtExpr) to alter the transformation. As mentioned previously,
+/// replacing TransformTemplateTypeParmType() allows template instantiation
+/// to substitute template arguments for their corresponding template
+/// parameters. Additionally, subclasses can override the \c RebuildXXX
+/// functions to control how AST nodes are rebuilt when their operands change.
+/// By default, \c TreeTransform will invoke semantic analysis to rebuild
+/// AST nodes. However, certain other tree transformations (e.g, cloning) may
+/// be able to use more efficient rebuild steps.
+///
+/// There are a handful of other functions that can be overridden, allowing one
+/// to avoid traversing nodes that don't need any transformation
+/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their
+/// operands have not changed (\c AlwaysRebuild()), and customize the
+/// default locations and entity names used for type-checking
+/// (\c getBaseLocation(), \c getBaseEntity()).
+template<typename Derived>
+class TreeTransform {
+ /// \brief Private RAII object that helps us forget and then re-remember
+ /// the template argument corresponding to a partially-substituted parameter
+ /// pack.
+ class ForgetPartiallySubstitutedPackRAII {
+ Derived &Self;
+ TemplateArgument Old;
+
+ public:
+ ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) {
+ Old = Self.ForgetPartiallySubstitutedPack();
+ }
+
+ ~ForgetPartiallySubstitutedPackRAII() {
+ Self.RememberPartiallySubstitutedPack(Old);
+ }
+ };
+
+protected:
+ Sema &SemaRef;
+
+public:
+ /// \brief Initializes a new tree transformer.
+ TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+
+ /// \brief Retrieves a reference to the derived class.
+ Derived &getDerived() { return static_cast<Derived&>(*this); }
+
+ /// \brief Retrieves a reference to the derived class.
+ const Derived &getDerived() const {
+ return static_cast<const Derived&>(*this);
+ }
+
+ static inline ExprResult Owned(Expr *E) { return E; }
+ static inline StmtResult Owned(Stmt *S) { return S; }
+
+ /// \brief Retrieves a reference to the semantic analysis object used for
+ /// this tree transform.
+ Sema &getSema() const { return SemaRef; }
+
+ /// \brief Whether the transformation should always rebuild AST nodes, even
+ /// if none of the children have changed.
+ ///
+ /// Subclasses may override this function to specify when the transformation
+ /// should rebuild all AST nodes.
+ bool AlwaysRebuild() { return false; }
+
+ /// \brief Returns the location of the entity being transformed, if that
+ /// information was not available elsewhere in the AST.
+ ///
+ /// By default, returns no source-location information. Subclasses can
+ /// provide an alternative implementation that provides better location
+ /// information.
+ SourceLocation getBaseLocation() { return SourceLocation(); }
+
+ /// \brief Returns the name of the entity being transformed, if that
+ /// information was not available elsewhere in the AST.
+ ///
+ /// By default, returns an empty name. Subclasses can provide an alternative
+ /// implementation with a more precise name.
+ DeclarationName getBaseEntity() { return DeclarationName(); }
+
+ /// \brief Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ ///
+ /// By default, the source location and entity are ignored. Subclasses can
+ /// override this function to provide a customized implementation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) { }
+
+ /// \brief RAII object that temporarily sets the base location and entity
+ /// used for reporting diagnostics in types.
+ class TemporaryBase {
+ TreeTransform &Self;
+ SourceLocation OldLocation;
+ DeclarationName OldEntity;
+
+ public:
+ TemporaryBase(TreeTransform &Self, SourceLocation Location,
+ DeclarationName Entity) : Self(Self) {
+ OldLocation = Self.getDerived().getBaseLocation();
+ OldEntity = Self.getDerived().getBaseEntity();
+
+ if (Location.isValid())
+ Self.getDerived().setBase(Location, Entity);
+ }
+
+ ~TemporaryBase() {
+ Self.getDerived().setBase(OldLocation, OldEntity);
+ }
+ };
+
+ /// \brief Determine whether the given type \p T has already been
+ /// transformed.
+ ///
+ /// Subclasses can provide an alternative implementation of this routine
+ /// to short-circuit evaluation when it is known that a given type will
+ /// not change. For example, template instantiation need not traverse
+ /// non-dependent types.
+ bool AlreadyTransformed(QualType T) {
+ return T.isNull();
+ }
+
+ /// \brief Determine whether the given call argument should be dropped, e.g.,
+ /// because it is a default argument.
+ ///
+ /// Subclasses can provide an alternative implementation of this routine to
+ /// determine which kinds of call arguments get dropped. By default,
+ /// CXXDefaultArgument nodes are dropped (prior to transformation).
+ bool DropCallArgument(Expr *E) {
+ return E->isDefaultArgument();
+ }
+
+ /// \brief Determine whether we should expand a pack expansion with the
+ /// given set of parameter packs into separate arguments by repeatedly
+ /// transforming the pattern.
+ ///
+ /// By default, the transformer never tries to expand pack expansions.
+ /// Subclasses can override this routine to provide different behavior.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis that identifies the
+ /// pack expansion.
+ ///
+ /// \param PatternRange The source range that covers the entire pattern of
+ /// the pack expansion.
+ ///
+ /// \param Unexpanded The set of unexpanded parameter packs within the
+ /// pattern.
+ ///
+ /// \param NumUnexpanded The number of unexpanded parameter packs in
+ /// \p Unexpanded.
+ ///
+ /// \param ShouldExpand Will be set to \c true if the transformer should
+ /// expand the corresponding pack expansions into separate arguments. When
+ /// set, \c NumExpansions must also be set.
+ ///
+ /// \param RetainExpansion Whether the caller should add an unexpanded
+ /// pack expansion after all of the expanded arguments. This is used
+ /// when extending explicitly-specified template argument packs per
+ /// C++0x [temp.arg.explicit]p9.
+ ///
+ /// \param NumExpansions The number of separate arguments that will be in
+ /// the expanded form of the corresponding pack expansion. This is both an
+ /// input and an output parameter, which can be set by the caller if the
+ /// number of expansions is known a priori (e.g., due to a prior substitution)
+ /// and will be set by the callee when the number of expansions is known.
+ /// The callee must set this value when \c ShouldExpand is \c true; it may
+ /// set this value in other cases.
+ ///
+ /// \returns true if an error occurred (e.g., because the parameter packs
+ /// are to be instantiated with arguments of different lengths), false
+ /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
+ /// must be set.
+ bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ const UnexpandedParameterPack *Unexpanded,
+ unsigned NumUnexpanded,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ llvm::Optional<unsigned> &NumExpansions) {
+ ShouldExpand = false;
+ return false;
+ }
+
+ /// \brief "Forget" about the partially-substituted pack template argument,
+ /// when performing an instantiation that must preserve the parameter pack
+ /// use.
+ ///
+ /// This routine is meant to be overridden by the template instantiator.
+ TemplateArgument ForgetPartiallySubstitutedPack() {
+ return TemplateArgument();
+ }
+
+ /// \brief "Remember" the partially-substituted pack template argument
+ /// after performing an instantiation that must preserve the parameter pack
+ /// use.
+ ///
+ /// This routine is meant to be overridden by the template instantiator.
+ void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
+
+ /// \brief Note to the derived class when a function parameter pack is
+ /// being expanded.
+ void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
+
+ /// \brief Transforms the given type into another type.
+ ///
+ /// By default, this routine transforms a type by creating a
+ /// TypeSourceInfo for it and delegating to the appropriate
+ /// function. This is expensive, but we don't mind, because
+ /// this method is deprecated anyway; all users should be
+ /// switched to storing TypeSourceInfos.
+ ///
+ /// \returns the transformed type.
+ QualType TransformType(QualType T);
+
+ /// \brief Transforms the given type-with-location into a new
+ /// type-with-location.
+ ///
+ /// By default, this routine transforms a type by delegating to the
+ /// appropriate TransformXXXType to build a new type. Subclasses
+ /// may override this function (to take over all type
+ /// transformations) or some set of the TransformXXXType functions
+ /// to alter the transformation.
+ TypeSourceInfo *TransformType(TypeSourceInfo *DI);
+
+ /// \brief Transform the given type-with-location into a new
+ /// type, collecting location information in the given builder
+ /// as necessary.
+ ///
+ QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
+
+ /// \brief Transform the given statement.
+ ///
+ /// By default, this routine transforms a statement by delegating to the
+ /// appropriate TransformXXXStmt function to transform a specific kind of
+ /// statement or the TransformExpr() function to transform an expression.
+ /// Subclasses may override this function to transform statements using some
+ /// other mechanism.
+ ///
+ /// \returns the transformed statement.
+ StmtResult TransformStmt(Stmt *S);
+
+ /// \brief Transform the given expression.
+ ///
+ /// By default, this routine transforms an expression by delegating to the
+ /// appropriate TransformXXXExpr function to build a new expression.
+ /// Subclasses may override this function to transform expressions using some
+ /// other mechanism.
+ ///
+ /// \returns the transformed expression.
+ ExprResult TransformExpr(Expr *E);
+
+ /// \brief Transform the given list of expressions.
+ ///
+ /// This routine transforms a list of expressions by invoking
+ /// \c TransformExpr() for each subexpression. However, it also provides
+ /// support for variadic templates by expanding any pack expansions (if the
+ /// derived class permits such expansion) along the way. When pack expansions
+ /// are present, the number of outputs may not equal the number of inputs.
+ ///
+ /// \param Inputs The set of expressions to be transformed.
+ ///
+ /// \param NumInputs The number of expressions in \c Inputs.
+ ///
+ /// \param IsCall If \c true, then this transform is being performed on
+ /// function-call arguments, and any arguments that should be dropped, will
+ /// be.
+ ///
+ /// \param Outputs The transformed input expressions will be added to this
+ /// vector.
+ ///
+ /// \param ArgChanged If non-NULL, will be set \c true if any argument changed
+ /// due to transformation.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
+ llvm::SmallVectorImpl<Expr *> &Outputs,
+ bool *ArgChanged = 0);
+
+ /// \brief Transform the given declaration, which is referenced from a type
+ /// or expression.
+ ///
+ /// By default, acts as the identity function on declarations. Subclasses
+ /// may override this function to provide alternate behavior.
+ Decl *TransformDecl(SourceLocation Loc, Decl *D) { return D; }
+
+ /// \brief Transform the definition of the given declaration.
+ ///
+ /// By default, invokes TransformDecl() to transform the declaration.
+ /// Subclasses may override this function to provide alternate behavior.
+ Decl *TransformDefinition(SourceLocation Loc, Decl *D) {
+ return getDerived().TransformDecl(Loc, D);
+ }
+
+ /// \brief Transform the given declaration, which was the first part of a
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// This specific declaration transformation only applies to the first
+ /// identifier in a nested-name-specifier of a member access expression, e.g.,
+ /// the \c T in \c x->T::member
+ ///
+ /// By default, invokes TransformDecl() to transform the declaration.
+ /// Subclasses may override this function to provide alternate behavior.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) {
+ return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D));
+ }
+
+ /// \brief Transform the given nested-name-specifier.
+ ///
+ /// By default, transforms all of the types and declarations within the
+ /// nested-name-specifier. Subclasses may override this function to provide
+ /// alternate behavior.
+ NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
+
+ /// \brief Transform the given declaration name.
+ ///
+ /// By default, transforms the types of conversion function, constructor,
+ /// and destructor names and then (if needed) rebuilds the declaration name.
+ /// Identifiers and selectors are returned unmodified. Sublcasses may
+ /// override this function to provide alternate behavior.
+ DeclarationNameInfo
+ TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo);
+
+ /// \brief Transform the given template name.
+ ///
+ /// By default, transforms the template name by transforming the declarations
+ /// and nested-name-specifiers that occur within the template name.
+ /// Subclasses may override this function to provide alternate behavior.
+ TemplateName TransformTemplateName(TemplateName Name,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
+
+ /// \brief Transform the given template argument.
+ ///
+ /// By default, this operation transforms the type, expression, or
+ /// declaration stored within the template argument and constructs a
+ /// new template argument from the transformed result. Subclasses may
+ /// override this function to provide alternate behavior.
+ ///
+ /// Returns true if there was an error.
+ bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output);
+
+ /// \brief Transform the given set of template arguments.
+ ///
+ /// By default, this operation transforms all of the template arguments
+ /// in the input set using \c TransformTemplateArgument(), and appends
+ /// the transformed arguments to the output list.
+ ///
+ /// Note that this overload of \c TransformTemplateArguments() is merely
+ /// a convenience function. Subclasses that wish to override this behavior
+ /// should override the iterator-based member template version.
+ ///
+ /// \param Inputs The set of template arguments to be transformed.
+ ///
+ /// \param NumInputs The number of template arguments in \p Inputs.
+ ///
+ /// \param Outputs The set of transformed template arguments output by this
+ /// routine.
+ ///
+ /// Returns true if an error occurred.
+ bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs,
+ unsigned NumInputs,
+ TemplateArgumentListInfo &Outputs) {
+ return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs);
+ }
+
+ /// \brief Transform the given set of template arguments.
+ ///
+ /// By default, this operation transforms all of the template arguments
+ /// in the input set using \c TransformTemplateArgument(), and appends
+ /// the transformed arguments to the output list.
+ ///
+ /// \param First An iterator to the first template argument.
+ ///
+ /// \param Last An iterator one step past the last template argument.
+ ///
+ /// \param Outputs The set of transformed template arguments output by this
+ /// routine.
+ ///
+ /// Returns true if an error occurred.
+ template<typename InputIterator>
+ bool TransformTemplateArguments(InputIterator First,
+ InputIterator Last,
+ TemplateArgumentListInfo &Outputs);
+
+ /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+ void InventTemplateArgumentLoc(const TemplateArgument &Arg,
+ TemplateArgumentLoc &ArgLoc);
+
+ /// \brief Fakes up a TypeSourceInfo for a type.
+ TypeSourceInfo *InventTypeSourceInfo(QualType T) {
+ return SemaRef.Context.getTrivialTypeSourceInfo(T,
+ getDerived().getBaseLocation());
+ }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+#include "clang/AST/TypeLocNodes.def"
+
+ QualType
+ TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL,
+ TemplateName Template);
+
+ QualType
+ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ NestedNameSpecifier *Prefix);
+
+ /// \brief Transforms the parameters of a function type into the
+ /// given vectors.
+ ///
+ /// The result vectors should be kept in sync; null entries in the
+ /// variables vector are acceptable.
+ ///
+ /// Return true on error.
+ bool TransformFunctionTypeParams(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const QualType *ParamTypes,
+ llvm::SmallVectorImpl<QualType> &PTypes,
+ llvm::SmallVectorImpl<ParmVarDecl*> *PVars);
+
+ /// \brief Transforms a single function-type parameter. Return null
+ /// on error.
+ ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ llvm::Optional<unsigned> NumExpansions);
+
+ QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+
+ StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
+ ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
+
+#define STMT(Node, Parent) \
+ StmtResult Transform##Node(Node *S);
+#define EXPR(Node, Parent) \
+ ExprResult Transform##Node(Node *E);
+#define ABSTRACT_STMT(Stmt)
+#include "clang/AST/StmtNodes.inc"
+
+ /// \brief Build a new pointer type given its pointee type.
+ ///
+ /// By default, performs semantic analysis when building the pointer type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil);
+
+ /// \brief Build a new block pointer type given its pointee type.
+ ///
+ /// By default, performs semantic analysis when building the block pointer
+ /// type. Subclasses may override this routine to provide different behavior.
+ QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil);
+
+ /// \brief Build a new reference type given the type it references.
+ ///
+ /// By default, performs semantic analysis when building the
+ /// reference type. Subclasses may override this routine to provide
+ /// different behavior.
+ ///
+ /// \param LValue whether the type was written with an lvalue sigil
+ /// or an rvalue sigil.
+ QualType RebuildReferenceType(QualType ReferentType,
+ bool LValue,
+ SourceLocation Sigil);
+
+ /// \brief Build a new member pointer type given the pointee type and the
+ /// class type it refers into.
+ ///
+ /// By default, performs semantic analysis when building the member pointer
+ /// type. Subclasses may override this routine to provide different behavior.
+ QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+ SourceLocation Sigil);
+
+ /// \brief Build a new array type given the element type, size
+ /// modifier, size of the array (if known), size expression, and index type
+ /// qualifiers.
+ ///
+ /// By default, performs semantic analysis when building the array type.
+ /// Subclasses may override this routine to provide different behavior.
+ /// Also by default, all of the other Rebuild*Array
+ QualType RebuildArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ const llvm::APInt *Size,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
+
+ /// \brief Build a new constant array type given the element type, size
+ /// modifier, (known) size of the array, and index type qualifiers.
+ ///
+ /// By default, performs semantic analysis when building the array type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildConstantArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ const llvm::APInt &Size,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
+
+ /// \brief Build a new incomplete array type given the element type, size
+ /// modifier, and index type qualifiers.
+ ///
+ /// By default, performs semantic analysis when building the array type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildIncompleteArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
+
+ /// \brief Build a new variable-length array type given the element type,
+ /// size modifier, size expression, and index type qualifiers.
+ ///
+ /// By default, performs semantic analysis when building the array type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildVariableArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
+
+ /// \brief Build a new dependent-sized array type given the element type,
+ /// size modifier, size expression, and index type qualifiers.
+ ///
+ /// By default, performs semantic analysis when building the array type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildDependentSizedArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange);
+
+ /// \brief Build a new vector type given the element type and
+ /// number of elements.
+ ///
+ /// By default, performs semantic analysis when building the vector type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
+ VectorType::VectorKind VecKind);
+
+ /// \brief Build a new extended vector type given the element type and
+ /// number of elements.
+ ///
+ /// By default, performs semantic analysis when building the vector type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
+ SourceLocation AttributeLoc);
+
+ /// \brief Build a new potentially dependently-sized extended vector type
+ /// given the element type and number of elements.
+ ///
+ /// By default, performs semantic analysis when building the vector type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildDependentSizedExtVectorType(QualType ElementType,
+ Expr *SizeExpr,
+ SourceLocation AttributeLoc);
+
+ /// \brief Build a new function type.
+ ///
+ /// By default, performs semantic analysis when building the function type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildFunctionProtoType(QualType T,
+ QualType *ParamTypes,
+ unsigned NumParamTypes,
+ bool Variadic, unsigned Quals,
+ RefQualifierKind RefQualifier,
+ const FunctionType::ExtInfo &Info);
+
+ /// \brief Build a new unprototyped function type.
+ QualType RebuildFunctionNoProtoType(QualType ResultType);
+
+ /// \brief Rebuild an unresolved typename type, given the decl that
+ /// the UnresolvedUsingTypenameDecl was transformed to.
+ QualType RebuildUnresolvedUsingType(Decl *D);
+
+ /// \brief Build a new typedef type.
+ QualType RebuildTypedefType(TypedefDecl *Typedef) {
+ return SemaRef.Context.getTypeDeclType(Typedef);
+ }
+
+ /// \brief Build a new class/struct/union type.
+ QualType RebuildRecordType(RecordDecl *Record) {
+ return SemaRef.Context.getTypeDeclType(Record);
+ }
+
+ /// \brief Build a new Enum type.
+ QualType RebuildEnumType(EnumDecl *Enum) {
+ return SemaRef.Context.getTypeDeclType(Enum);
+ }
+
+ /// \brief Build a new typeof(expr) type.
+ ///
+ /// By default, performs semantic analysis when building the typeof type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
+
+ /// \brief Build a new typeof(type) type.
+ ///
+ /// By default, builds a new TypeOfType with the given underlying type.
+ QualType RebuildTypeOfType(QualType Underlying);
+
+ /// \brief Build a new C++0x decltype type.
+ ///
+ /// By default, performs semantic analysis when building the decltype type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
+
+ /// \brief Build a new C++0x auto type.
+ ///
+ /// By default, builds a new AutoType with the given deduced type.
+ QualType RebuildAutoType(QualType Deduced) {
+ return SemaRef.Context.getAutoType(Deduced);
+ }
+
+ /// \brief Build a new template specialization type.
+ ///
+ /// By default, performs semantic analysis when building the template
+ /// specialization type. Subclasses may override this routine to provide
+ /// different behavior.
+ QualType RebuildTemplateSpecializationType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo &Args);
+
+ /// \brief Build a new parenthesized type.
+ ///
+ /// By default, builds a new ParenType type from the inner type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildParenType(QualType InnerType) {
+ return SemaRef.Context.getParenType(InnerType);
+ }
+
+ /// \brief Build a new qualified name type.
+ ///
+ /// By default, builds a new ElaboratedType type from the keyword,
+ /// the nested-name-specifier and the named type.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildElaboratedType(SourceLocation KeywordLoc,
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS, QualType Named) {
+ return SemaRef.Context.getElaboratedType(Keyword, NNS, Named);
+ }
+
+ /// \brief Build a new typename type that refers to a template-id.
+ ///
+ /// By default, builds a new DependentNameType type from the
+ /// nested-name-specifier and the given type. Subclasses may override
+ /// this routine to provide different behavior.
+ QualType RebuildDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &Args) {
+ // Rebuild the template name.
+ // TODO: avoid TemplateName abstraction
+ TemplateName InstName =
+ getDerived().RebuildTemplateName(Qualifier, QualifierRange, *Name,
+ QualType(), 0);
+
+ if (InstName.isNull())
+ return QualType();
+
+ // If it's still dependent, make a dependent specialization.
+ if (InstName.getAsDependentTemplateName())
+ return SemaRef.Context.getDependentTemplateSpecializationType(
+ Keyword, Qualifier, Name, Args);
+
+ // Otherwise, make an elaborated type wrapping a non-dependent
+ // specialization.
+ QualType T =
+ getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
+ if (T.isNull()) return QualType();
+
+ // NOTE: NNS is already recorded in template specialization type T.
+ return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T);
+ }
+
+ /// \brief Build a new typename type that refers to an identifier.
+ ///
+ /// By default, performs semantic analysis when building the typename type
+ /// (or elaborated type). Subclasses may override this routine to provide
+ /// different behavior.
+ QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Id,
+ SourceLocation KeywordLoc,
+ SourceRange NNSRange,
+ SourceLocation IdLoc) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(NNS);
+ SS.setRange(NNSRange);
+
+ if (NNS->isDependent()) {
+ // If the name is still dependent, just build a new dependent name type.
+ if (!SemaRef.computeDeclContext(SS))
+ return SemaRef.Context.getDependentNameType(Keyword, NNS, Id);
+ }
+
+ if (Keyword == ETK_None || Keyword == ETK_Typename)
+ return SemaRef.CheckTypenameType(Keyword, NNS, *Id,
+ KeywordLoc, NNSRange, IdLoc);
+
+ TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
+
+ // We had a dependent elaborated-type-specifier that has been transformed
+ // into a non-dependent elaborated-type-specifier. Find the tag we're
+ // referring to.
+ LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName);
+ DeclContext *DC = SemaRef.computeDeclContext(SS, false);
+ if (!DC)
+ return QualType();
+
+ if (SemaRef.RequireCompleteDeclContext(SS, DC))
+ return QualType();
+
+ TagDecl *Tag = 0;
+ SemaRef.LookupQualifiedName(Result, DC);
+ switch (Result.getResultKind()) {
+ case LookupResult::NotFound:
+ case LookupResult::NotFoundInCurrentInstantiation:
+ break;
+
+ case LookupResult::Found:
+ Tag = Result.getAsSingle<TagDecl>();
+ break;
+
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue:
+ llvm_unreachable("Tag lookup cannot find non-tags");
+ return QualType();
+
+ case LookupResult::Ambiguous:
+ // Let the LookupResult structure handle ambiguities.
+ return QualType();
+ }
+
+ if (!Tag) {
+ // Check where the name exists but isn't a tag type and use that to emit
+ // better diagnostics.
+ LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName);
+ SemaRef.LookupQualifiedName(Result, DC);
+ switch (Result.getResultKind()) {
+ case LookupResult::Found:
+ case LookupResult::FoundOverloaded:
+ case LookupResult::FoundUnresolvedValue: {
+ NamedDecl *SomeDecl = Result.getRepresentativeDecl();
+ unsigned Kind = 0;
+ if (isa<TypedefDecl>(SomeDecl)) Kind = 1;
+ else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 2;
+ SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind;
+ SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at);
+ break;
+ }
+ default:
+ // FIXME: Would be nice to highlight just the source range.
+ SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope)
+ << Kind << Id << DC;
+ break;
+ }
+ return QualType();
+ }
+
+ if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, IdLoc, *Id)) {
+ SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;
+ SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);
+ return QualType();
+ }
+
+ // Build the elaborated-type-specifier type.
+ QualType T = SemaRef.Context.getTypeDeclType(Tag);
+ return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
+ }
+
+ /// \brief Build a new pack expansion type.
+ ///
+ /// By default, builds a new PackExpansionType type from the given pattern.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildPackExpansionType(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc,
+ NumExpansions);
+ }
+
+ /// \brief Build a new nested-name-specifier given the prefix and an
+ /// identifier that names the next step in the nested-name-specifier.
+ ///
+ /// By default, performs semantic analysis when building the new
+ /// nested-name-specifier. Subclasses may override this routine to provide
+ /// different behavior.
+ NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope);
+
+ /// \brief Build a new nested-name-specifier given the prefix and the
+ /// namespace named in the next step in the nested-name-specifier.
+ ///
+ /// By default, performs semantic analysis when building the new
+ /// nested-name-specifier. Subclasses may override this routine to provide
+ /// different behavior.
+ NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ NamespaceDecl *NS);
+
+ /// \brief Build a new nested-name-specifier given the prefix and the
+ /// type named in the next step in the nested-name-specifier.
+ ///
+ /// By default, performs semantic analysis when building the new
+ /// nested-name-specifier. Subclasses may override this routine to provide
+ /// different behavior.
+ NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ bool TemplateKW,
+ QualType T);
+
+ /// \brief Build a new template name given a nested name specifier, a flag
+ /// indicating whether the "template" keyword was provided, and the template
+ /// that the template name refers to.
+ ///
+ /// By default, builds the new template name directly. Subclasses may override
+ /// this routine to provide different behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ TemplateDecl *Template);
+
+ /// \brief Build a new template name given a nested name specifier and the
+ /// name that is referred to as a template.
+ ///
+ /// By default, performs semantic analysis to determine whether the name can
+ /// be resolved to a specific template, then builds the appropriate kind of
+ /// template name. Subclasses may override this routine to provide different
+ /// behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope);
+
+ /// \brief Build a new template name given a nested name specifier and the
+ /// overloaded operator name that is referred to as a template.
+ ///
+ /// By default, performs semantic analysis to determine whether the name can
+ /// be resolved to a specific template, then builds the appropriate kind of
+ /// template name. Subclasses may override this routine to provide different
+ /// behavior.
+ TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ QualType ObjectType);
+
+ /// \brief Build a new template name given a template template parameter pack
+ /// and the
+ ///
+ /// By default, performs semantic analysis to determine whether the name can
+ /// be resolved to a specific template, then builds the appropriate kind of
+ /// template name. Subclasses may override this routine to provide different
+ /// behavior.
+ TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param,
+ const TemplateArgument &ArgPack) {
+ return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
+ }
+
+ /// \brief Build a new compound statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCompoundStmt(SourceLocation LBraceLoc,
+ MultiStmtArg Statements,
+ SourceLocation RBraceLoc,
+ bool IsStmtExpr) {
+ return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, Statements,
+ IsStmtExpr);
+ }
+
+ /// \brief Build a new case statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCaseStmt(SourceLocation CaseLoc,
+ Expr *LHS,
+ SourceLocation EllipsisLoc,
+ Expr *RHS,
+ SourceLocation ColonLoc) {
+ return getSema().ActOnCaseStmt(CaseLoc, LHS, EllipsisLoc, RHS,
+ ColonLoc);
+ }
+
+ /// \brief Attach the body to a new case statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCaseStmtBody(Stmt *S, Stmt *Body) {
+ getSema().ActOnCaseStmtBody(S, Body);
+ return S;
+ }
+
+ /// \brief Build a new default statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt) {
+ return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt,
+ /*CurScope=*/0);
+ }
+
+ /// \brief Build a new label statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildLabelStmt(SourceLocation IdentLoc, LabelDecl *L,
+ SourceLocation ColonLoc, Stmt *SubStmt) {
+ return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
+ }
+
+ /// \brief Build a new "if" statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
+ VarDecl *CondVar, Stmt *Then,
+ SourceLocation ElseLoc, Stmt *Else) {
+ return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else);
+ }
+
+ /// \brief Start building a new switch statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
+ Expr *Cond, VarDecl *CondVar) {
+ return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond,
+ CondVar);
+ }
+
+ /// \brief Attach the body to the switch statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body) {
+ return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body);
+ }
+
+ /// \brief Build a new while statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond,
+ VarDecl *CondVar, Stmt *Body) {
+ return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body);
+ }
+
+ /// \brief Build a new do-while statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body,
+ SourceLocation WhileLoc, SourceLocation LParenLoc,
+ Expr *Cond, SourceLocation RParenLoc) {
+ return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc,
+ Cond, RParenLoc);
+ }
+
+ /// \brief Build a new for statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+ Stmt *Init, Sema::FullExprArg Cond,
+ VarDecl *CondVar, Sema::FullExprArg Inc,
+ SourceLocation RParenLoc, Stmt *Body) {
+ return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond,
+ CondVar, Inc, RParenLoc, Body);
+ }
+
+ /// \brief Build a new goto statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+ LabelDecl *Label) {
+ return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label);
+ }
+
+ /// \brief Build a new indirect goto statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
+ SourceLocation StarLoc,
+ Expr *Target) {
+ return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
+ }
+
+ /// \brief Build a new return statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) {
+ return getSema().ActOnReturnStmt(ReturnLoc, Result);
+ }
+
+ /// \brief Build a new declaration statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return getSema().Owned(
+ new (getSema().Context) DeclStmt(
+ DeclGroupRef::Create(getSema().Context,
+ Decls, NumDecls),
+ StartLoc, EndLoc));
+ }
+
+ /// \brief Build a new inline asm statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple,
+ bool IsVolatile,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ Expr *AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm) {
+ return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs,
+ NumInputs, Names, move(Constraints),
+ Exprs, AsmString, Clobbers,
+ RParenLoc, MSAsm);
+ }
+
+ /// \brief Build a new Objective-C @try statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCAtTryStmt(SourceLocation AtLoc,
+ Stmt *TryBody,
+ MultiStmtArg CatchStmts,
+ Stmt *Finally) {
+ return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, move(CatchStmts),
+ Finally);
+ }
+
+ /// \brief Rebuild an Objective-C exception declaration.
+ ///
+ /// By default, performs semantic analysis to build the new declaration.
+ /// Subclasses may override this routine to provide different behavior.
+ VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *TInfo, QualType T) {
+ return getSema().BuildObjCExceptionDecl(TInfo, T,
+ ExceptionDecl->getIdentifier(),
+ ExceptionDecl->getLocation());
+ }
+
+ /// \brief Build a new Objective-C @catch statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc,
+ SourceLocation RParenLoc,
+ VarDecl *Var,
+ Stmt *Body) {
+ return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc,
+ Var, Body);
+ }
+
+ /// \brief Build a new Objective-C @finally statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc,
+ Stmt *Body) {
+ return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
+ }
+
+ /// \brief Build a new Objective-C @throw statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc,
+ Expr *Operand) {
+ return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
+ }
+
+ /// \brief Build a new Objective-C @synchronized statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *Object,
+ Stmt *Body) {
+ return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object,
+ Body);
+ }
+
+ /// \brief Build a new Objective-C fast enumeration statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *Element,
+ Expr *Collection,
+ SourceLocation RParenLoc,
+ Stmt *Body) {
+ return getSema().ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+ Element,
+ Collection,
+ RParenLoc,
+ Body);
+ }
+
+ /// \brief Build a new C++ exception declaration.
+ ///
+ /// By default, performs semantic analysis to build the new decaration.
+ /// Subclasses may override this routine to provide different behavior.
+ VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *Declarator,
+ IdentifierInfo *Name,
+ SourceLocation Loc) {
+ return getSema().BuildExceptionDeclaration(0, Declarator, Name, Loc);
+ }
+
+ /// \brief Build a new C++ catch statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc,
+ VarDecl *ExceptionDecl,
+ Stmt *Handler) {
+ return Owned(new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl,
+ Handler));
+ }
+
+ /// \brief Build a new C++ try statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
+ Stmt *TryBlock,
+ MultiStmtArg Handlers) {
+ return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers));
+ }
+
+ /// \brief Build a new expression that references a declaration.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL) {
+ return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL);
+ }
+
+
+ /// \brief Build a new expression that references a declaration.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *VD,
+ const DeclarationNameInfo &NameInfo,
+ TemplateArgumentListInfo *TemplateArgs) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(QualifierRange);
+
+ // FIXME: loses template args.
+
+ return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD);
+ }
+
+ /// \brief Build a new expression in parentheses.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildParenExpr(Expr *SubExpr, SourceLocation LParen,
+ SourceLocation RParen) {
+ return getSema().ActOnParenExpr(LParen, RParen, SubExpr);
+ }
+
+ /// \brief Build a new pseudo-destructor expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base,
+ SourceLocation OperatorLoc,
+ bool isArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage Destroyed);
+
+ /// \brief Build a new unary operator expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildUnaryOperator(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ Expr *SubExpr) {
+ return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr);
+ }
+
+ /// \brief Build a new builtin offsetof expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
+ TypeSourceInfo *Type,
+ Sema::OffsetOfComponent *Components,
+ unsigned NumComponents,
+ SourceLocation RParenLoc) {
+ return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components,
+ NumComponents, RParenLoc);
+ }
+
+ /// \brief Build a new sizeof or alignof expression with a type argument.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
+ SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R);
+ }
+
+ /// \brief Build a new sizeof or alignof expression with an expression
+ /// argument.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ ExprResult Result
+ = getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return move(Result);
+ }
+
+ /// \brief Build a new array subscript expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildArraySubscriptExpr(Expr *LHS,
+ SourceLocation LBracketLoc,
+ Expr *RHS,
+ SourceLocation RBracketLoc) {
+ return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS,
+ LBracketLoc, RHS,
+ RBracketLoc);
+ }
+
+ /// \brief Build a new call expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig = 0) {
+ return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc,
+ move(Args), RParenLoc, ExecConfig);
+ }
+
+ /// \brief Build a new member access expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
+ bool isArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &MemberNameInfo,
+ ValueDecl *Member,
+ NamedDecl *FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ NamedDecl *FirstQualifierInScope) {
+ if (!Member->getDeclName()) {
+ // We have a reference to an unnamed field. This is always the
+ // base of an anonymous struct/union member access, i.e. the
+ // field is always of record type.
+ assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
+ assert(Member->getType()->isRecordType() &&
+ "unnamed member not of record type?");
+
+ if (getSema().PerformObjectMemberConversion(Base, Qualifier,
+ FoundDecl, Member))
+ return ExprError();
+
+ ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind();
+ MemberExpr *ME =
+ new (getSema().Context) MemberExpr(Base, isArrow,
+ Member, MemberNameInfo,
+ cast<FieldDecl>(Member)->getType(),
+ VK, OK_Ordinary);
+ return getSema().Owned(ME);
+ }
+
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ }
+
+ getSema().DefaultFunctionArrayConversion(Base);
+ QualType BaseType = Base->getType();
+
+ // FIXME: this involves duplicating earlier analysis in a lot of
+ // cases; we should avoid this when possible.
+ LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName);
+ R.addDecl(FoundDecl);
+ R.resolveKind();
+
+ return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
+ SS, FirstQualifierInScope,
+ R, ExplicitTemplateArgs);
+ }
+
+ /// \brief Build a new binary operator expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildBinaryOperator(SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ Expr *LHS, Expr *RHS) {
+ return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS);
+ }
+
+ /// \brief Build a new conditional operator expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildConditionalOperator(Expr *Cond,
+ SourceLocation QuestionLoc,
+ Expr *LHS,
+ SourceLocation ColonLoc,
+ Expr *RHS) {
+ return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, Cond,
+ LHS, RHS);
+ }
+
+ /// \brief Build a new C-style cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *SubExpr) {
+ return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc,
+ SubExpr);
+ }
+
+ /// \brief Build a new compound literal expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *Init) {
+ return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
+ Init);
+ }
+
+ /// \brief Build a new extended vector element access expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildExtVectorElementExpr(Expr *Base,
+ SourceLocation OpLoc,
+ SourceLocation AccessorLoc,
+ IdentifierInfo &Accessor) {
+
+ CXXScopeSpec SS;
+ DeclarationNameInfo NameInfo(&Accessor, AccessorLoc);
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ OpLoc, /*IsArrow*/ false,
+ SS, /*FirstQualifierInScope*/ 0,
+ NameInfo,
+ /* TemplateArgs */ 0);
+ }
+
+ /// \brief Build a new initializer list expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildInitList(SourceLocation LBraceLoc,
+ MultiExprArg Inits,
+ SourceLocation RBraceLoc,
+ QualType ResultTy) {
+ ExprResult Result
+ = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
+ if (Result.isInvalid() || ResultTy->isDependentType())
+ return move(Result);
+
+ // Patch in the result type we were given, which may have been computed
+ // when the initial InitListExpr was built.
+ InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get());
+ ILE->setType(ResultTy);
+ return move(Result);
+ }
+
+ /// \brief Build a new designated initializer expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildDesignatedInitExpr(Designation &Desig,
+ MultiExprArg ArrayExprs,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax,
+ Expr *Init) {
+ ExprResult Result
+ = SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax,
+ Init);
+ if (Result.isInvalid())
+ return ExprError();
+
+ ArrayExprs.release();
+ return move(Result);
+ }
+
+ /// \brief Build a new value-initialized expression.
+ ///
+ /// By default, builds the implicit value initialization without performing
+ /// any semantic analysis. Subclasses may override this routine to provide
+ /// different behavior.
+ ExprResult RebuildImplicitValueInitExpr(QualType T) {
+ return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T));
+ }
+
+ /// \brief Build a new \c va_arg expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *SubExpr, TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc) {
+ return getSema().BuildVAArgExpr(BuiltinLoc,
+ SubExpr, TInfo,
+ RParenLoc);
+ }
+
+ /// \brief Build a new expression list in parentheses.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildParenListExpr(SourceLocation LParenLoc,
+ MultiExprArg SubExprs,
+ SourceLocation RParenLoc) {
+ return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc,
+ move(SubExprs));
+ }
+
+ /// \brief Build a new address-of-label expression.
+ ///
+ /// By default, performs semantic analysis, using the name of the label
+ /// rather than attempting to map the label statement itself.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
+ SourceLocation LabelLoc, LabelDecl *Label) {
+ return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label);
+ }
+
+ /// \brief Build a new GNU statement expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildStmtExpr(SourceLocation LParenLoc,
+ Stmt *SubStmt,
+ SourceLocation RParenLoc) {
+ return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
+ }
+
+ /// \brief Build a new __builtin_choose_expr expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
+ Expr *Cond, Expr *LHS, Expr *RHS,
+ SourceLocation RParenLoc) {
+ return SemaRef.ActOnChooseExpr(BuiltinLoc,
+ Cond, LHS, RHS,
+ RParenLoc);
+ }
+
+ /// \brief Build a new overloaded operator call expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// The semantic analysis provides the behavior of template instantiation,
+ /// copying with transformations that turn what looks like an overloaded
+ /// operator call into a use of a builtin operator, performing
+ /// argument-dependent lookup, etc. Subclasses may override this routine to
+ /// provide different behavior.
+ ExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr *Callee,
+ Expr *First,
+ Expr *Second);
+
+ /// \brief Build a new C++ "named" cast expression, such as static_cast or
+ /// reinterpret_cast.
+ ///
+ /// By default, this routine dispatches to one of the more-specific routines
+ /// for a particular named case, e.g., RebuildCXXStaticCastExpr().
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
+ Stmt::StmtClass Class,
+ SourceLocation LAngleLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RAngleLoc,
+ SourceLocation LParenLoc,
+ Expr *SubExpr,
+ SourceLocation RParenLoc) {
+ switch (Class) {
+ case Stmt::CXXStaticCastExprClass:
+ return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo,
+ RAngleLoc, LParenLoc,
+ SubExpr, RParenLoc);
+
+ case Stmt::CXXDynamicCastExprClass:
+ return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo,
+ RAngleLoc, LParenLoc,
+ SubExpr, RParenLoc);
+
+ case Stmt::CXXReinterpretCastExprClass:
+ return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo,
+ RAngleLoc, LParenLoc,
+ SubExpr,
+ RParenLoc);
+
+ case Stmt::CXXConstCastExprClass:
+ return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo,
+ RAngleLoc, LParenLoc,
+ SubExpr, RParenLoc);
+
+ default:
+ assert(false && "Invalid C++ named cast");
+ break;
+ }
+
+ return ExprError();
+ }
+
+ /// \brief Build a new C++ static_cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
+ SourceLocation LAngleLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RAngleLoc,
+ SourceLocation LParenLoc,
+ Expr *SubExpr,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast,
+ TInfo, SubExpr,
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
+ }
+
+ /// \brief Build a new C++ dynamic_cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
+ SourceLocation LAngleLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RAngleLoc,
+ SourceLocation LParenLoc,
+ Expr *SubExpr,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
+ TInfo, SubExpr,
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
+ }
+
+ /// \brief Build a new C++ reinterpret_cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
+ SourceLocation LAngleLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RAngleLoc,
+ SourceLocation LParenLoc,
+ Expr *SubExpr,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
+ TInfo, SubExpr,
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
+ }
+
+ /// \brief Build a new C++ const_cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
+ SourceLocation LAngleLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RAngleLoc,
+ SourceLocation LParenLoc,
+ Expr *SubExpr,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast,
+ TInfo, SubExpr,
+ SourceRange(LAngleLoc, RAngleLoc),
+ SourceRange(LParenLoc, RParenLoc));
+ }
+
+ /// \brief Build a new C++ functional-style cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
+ SourceLocation LParenLoc,
+ Expr *Sub,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc,
+ MultiExprArg(&Sub, 1),
+ RParenLoc);
+ }
+
+ /// \brief Build a new C++ typeid(type) expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand,
+ RParenLoc);
+ }
+
+
+ /// \brief Build a new C++ typeid(expr) expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand,
+ RParenLoc);
+ }
+
+ /// \brief Build a new C++ __uuidof(type) expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand,
+ RParenLoc);
+ }
+
+ /// \brief Build a new C++ __uuidof(expr) expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand,
+ RParenLoc);
+ }
+
+ /// \brief Build a new C++ "this" expression.
+ ///
+ /// By default, builds a new "this" expression without performing any
+ /// semantic analysis. Subclasses may override this routine to provide
+ /// different behavior.
+ ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
+ QualType ThisType,
+ bool isImplicit) {
+ return getSema().Owned(
+ new (getSema().Context) CXXThisExpr(ThisLoc, ThisType,
+ isImplicit));
+ }
+
+ /// \brief Build a new C++ throw expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, Expr *Sub) {
+ return getSema().ActOnCXXThrow(ThrowLoc, Sub);
+ }
+
+ /// \brief Build a new C++ default-argument expression.
+ ///
+ /// By default, builds a new default-argument expression, which does not
+ /// require any semantic analysis. Subclasses may override this routine to
+ /// provide different behavior.
+ ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
+ ParmVarDecl *Param) {
+ return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
+ Param));
+ }
+
+ /// \brief Build a new C++ zero-initialization expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc,
+ MultiExprArg(getSema(), 0, 0),
+ RParenLoc);
+ }
+
+ /// \brief Build a new C++ "new" expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXNewExpr(SourceLocation StartLoc,
+ bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocatedType,
+ TypeSourceInfo *AllocatedTypeInfo,
+ Expr *ArraySize,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen) {
+ return getSema().BuildCXXNew(StartLoc, UseGlobal,
+ PlacementLParen,
+ move(PlacementArgs),
+ PlacementRParen,
+ TypeIdParens,
+ AllocatedType,
+ AllocatedTypeInfo,
+ ArraySize,
+ ConstructorLParen,
+ move(ConstructorArgs),
+ ConstructorRParen);
+ }
+
+ /// \brief Build a new C++ "delete" expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
+ bool IsGlobalDelete,
+ bool IsArrayForm,
+ Expr *Operand) {
+ return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm,
+ Operand);
+ }
+
+ /// \brief Build a new unary type trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
+ SourceLocation StartLoc,
+ TypeSourceInfo *T,
+ SourceLocation RParenLoc) {
+ return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
+ }
+
+ /// \brief Build a new binary type trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
+ SourceLocation StartLoc,
+ TypeSourceInfo *LhsT,
+ TypeSourceInfo *RhsT,
+ SourceLocation RParenLoc) {
+ return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
+ }
+
+ /// \brief Build a new (previously unresolved) declaration reference
+ /// expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(NNS);
+
+ if (TemplateArgs)
+ return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo,
+ *TemplateArgs);
+
+ return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo);
+ }
+
+ /// \brief Build a new template-id expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs);
+ }
+
+ /// \brief Build a new object-construction expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXConstructExpr(QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *Constructor,
+ bool IsElidable,
+ MultiExprArg Args,
+ bool RequiresZeroInit,
+ CXXConstructExpr::ConstructionKind ConstructKind,
+ SourceRange ParenRange) {
+ ASTOwningVector<Expr*> ConvertedArgs(SemaRef);
+ if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc,
+ ConvertedArgs))
+ return ExprError();
+
+ return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
+ move_arg(ConvertedArgs),
+ RequiresZeroInit, ConstructKind,
+ ParenRange);
+ }
+
+ /// \brief Build a new object-construction expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeConstructExpr(TSInfo,
+ LParenLoc,
+ move(Args),
+ RParenLoc);
+ }
+
+ /// \brief Build a new object-construction expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc) {
+ return getSema().BuildCXXTypeConstructExpr(TSInfo,
+ LParenLoc,
+ move(Args),
+ RParenLoc);
+ }
+
+ /// \brief Build a new member reference expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE,
+ QualType BaseType,
+ bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+
+ return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
+ OperatorLoc, IsArrow,
+ SS, FirstQualifierInScope,
+ MemberNameInfo,
+ TemplateArgs);
+ }
+
+ /// \brief Build a new member reference expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE,
+ QualType BaseType,
+ SourceLocation OperatorLoc,
+ bool IsArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ NamedDecl *FirstQualifierInScope,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+
+ return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
+ OperatorLoc, IsArrow,
+ SS, FirstQualifierInScope,
+ R, TemplateArgs);
+ }
+
+ /// \brief Build a new noexcept expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCXXNoexceptExpr(SourceRange Range, Expr *Arg) {
+ return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd());
+ }
+
+ /// \brief Build a new expression to compute the length of a parameter pack.
+ ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc,
+ SourceLocation RParenLoc,
+ unsigned Length) {
+ return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
+ OperatorLoc, Pack, PackLoc,
+ RParenLoc, Length);
+ }
+
+ /// \brief Build a new Objective-C @encode expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
+ TypeSourceInfo *EncodeTypeInfo,
+ SourceLocation RParenLoc) {
+ return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo,
+ RParenLoc));
+ }
+
+ /// \brief Build a new Objective-C class message.
+ ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
+ Selector Sel,
+ SourceLocation SelectorLoc,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ MultiExprArg Args,
+ SourceLocation RBracLoc) {
+ return SemaRef.BuildClassMessage(ReceiverTypeInfo,
+ ReceiverTypeInfo->getType(),
+ /*SuperLoc=*/SourceLocation(),
+ Sel, Method, LBracLoc, SelectorLoc,
+ RBracLoc, move(Args));
+ }
+
+ /// \brief Build a new Objective-C instance message.
+ ExprResult RebuildObjCMessageExpr(Expr *Receiver,
+ Selector Sel,
+ SourceLocation SelectorLoc,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ MultiExprArg Args,
+ SourceLocation RBracLoc) {
+ return SemaRef.BuildInstanceMessage(Receiver,
+ Receiver->getType(),
+ /*SuperLoc=*/SourceLocation(),
+ Sel, Method, LBracLoc, SelectorLoc,
+ RBracLoc, move(Args));
+ }
+
+ /// \brief Build a new Objective-C ivar reference expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildObjCIvarRefExpr(Expr *BaseArg, ObjCIvarDecl *Ivar,
+ SourceLocation IvarLoc,
+ bool IsArrow, bool IsFreeIvar) {
+ // FIXME: We lose track of the IsFreeIvar bit.
+ CXXScopeSpec SS;
+ Expr *Base = BaseArg;
+ LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
+ Sema::LookupMemberName);
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ /*FIME:*/IvarLoc,
+ SS, 0,
+ false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ if (Result.get())
+ return move(Result);
+
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ /*FIXME:*/IvarLoc, IsArrow, SS,
+ /*FirstQualifierInScope=*/0,
+ R,
+ /*TemplateArgs=*/0);
+ }
+
+ /// \brief Build a new Objective-C property reference expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg,
+ ObjCPropertyDecl *Property,
+ SourceLocation PropertyLoc) {
+ CXXScopeSpec SS;
+ Expr *Base = BaseArg;
+ LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
+ Sema::LookupMemberName);
+ bool IsArrow = false;
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ /*FIME:*/PropertyLoc,
+ SS, 0, false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ if (Result.get())
+ return move(Result);
+
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ /*FIXME:*/PropertyLoc, IsArrow,
+ SS,
+ /*FirstQualifierInScope=*/0,
+ R,
+ /*TemplateArgs=*/0);
+ }
+
+ /// \brief Build a new Objective-C property reference expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildObjCPropertyRefExpr(Expr *Base, QualType T,
+ ObjCMethodDecl *Getter,
+ ObjCMethodDecl *Setter,
+ SourceLocation PropertyLoc) {
+ // Since these expressions can only be value-dependent, we do not
+ // need to perform semantic analysis again.
+ return Owned(
+ new (getSema().Context) ObjCPropertyRefExpr(Getter, Setter, T,
+ VK_LValue, OK_ObjCProperty,
+ PropertyLoc, Base));
+ }
+
+ /// \brief Build a new Objective-C "isa" expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
+ bool IsArrow) {
+ CXXScopeSpec SS;
+ Expr *Base = BaseArg;
+ LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
+ Sema::LookupMemberName);
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ /*FIME:*/IsaLoc,
+ SS, 0, false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ if (Result.get())
+ return move(Result);
+
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
+ /*FIXME:*/IsaLoc, IsArrow, SS,
+ /*FirstQualifierInScope=*/0,
+ R,
+ /*TemplateArgs=*/0);
+ }
+
+ /// \brief Build a new shuffle vector expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
+ MultiExprArg SubExprs,
+ SourceLocation RParenLoc) {
+ // Find the declaration for __builtin_shufflevector
+ const IdentifierInfo &Name
+ = SemaRef.Context.Idents.get("__builtin_shufflevector");
+ TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl();
+ DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name));
+ assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?");
+
+ // Build a reference to the __builtin_shufflevector builtin
+ FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first);
+ Expr *Callee
+ = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(),
+ VK_LValue, BuiltinLoc);
+ SemaRef.UsualUnaryConversions(Callee);
+
+ // Build the CallExpr
+ unsigned NumSubExprs = SubExprs.size();
+ Expr **Subs = (Expr **)SubExprs.release();
+ CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
+ Subs, NumSubExprs,
+ Builtin->getCallResultType(),
+ Expr::getValueKindForType(Builtin->getResultType()),
+ RParenLoc);
+ ExprResult OwnedCall(SemaRef.Owned(TheCall));
+
+ // Type-check the __builtin_shufflevector expression.
+ ExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
+ if (Result.isInvalid())
+ return ExprError();
+
+ OwnedCall.release();
+ return move(Result);
+ }
+
+ /// \brief Build a new template argument pack expansion.
+ ///
+ /// By default, performs semantic analysis to build a new pack expansion
+ /// for a template argument. Subclasses may override this routine to provide
+ /// different behavior.
+ TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
+ SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ switch (Pattern.getArgument().getKind()) {
+ case TemplateArgument::Expression: {
+ ExprResult Result
+ = getSema().CheckPackExpansion(Pattern.getSourceExpression(),
+ EllipsisLoc, NumExpansions);
+ if (Result.isInvalid())
+ return TemplateArgumentLoc();
+
+ return TemplateArgumentLoc(Result.get(), Result.get());
+ }
+
+ case TemplateArgument::Template:
+ return TemplateArgumentLoc(TemplateArgument(
+ Pattern.getArgument().getAsTemplate(),
+ NumExpansions),
+ Pattern.getTemplateQualifierRange(),
+ Pattern.getTemplateNameLoc(),
+ EllipsisLoc);
+
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("Pack expansion pattern has no parameter packs");
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *Expansion
+ = getSema().CheckPackExpansion(Pattern.getTypeSourceInfo(),
+ EllipsisLoc,
+ NumExpansions))
+ return TemplateArgumentLoc(TemplateArgument(Expansion->getType()),
+ Expansion);
+ break;
+ }
+
+ return TemplateArgumentLoc();
+ }
+
+ /// \brief Build a new expression pack expansion.
+ ///
+ /// By default, performs semantic analysis to build a new pack expansion
+ /// for an expression. Subclasses may override this routine to provide
+ /// different behavior.
+ ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+ llvm::Optional<unsigned> NumExpansions) {
+ return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions);
+ }
+
+private:
+ QualType TransformTypeInObjectScope(QualType T,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ NestedNameSpecifier *Prefix);
+
+ TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *T,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ NestedNameSpecifier *Prefix);
+};
+
+template<typename Derived>
+StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
+ if (!S)
+ return SemaRef.Owned(S);
+
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass: break;
+
+ // Transform individual statement nodes
+#define STMT(Node, Parent) \
+ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S));
+#define ABSTRACT_STMT(Node)
+#define EXPR(Node, Parent)
+#include "clang/AST/StmtNodes.inc"
+
+ // Transform expressions by calling TransformExpr.
+#define STMT(Node, Parent)
+#define ABSTRACT_STMT(Stmt)
+#define EXPR(Node, Parent) case Stmt::Node##Class:
+#include "clang/AST/StmtNodes.inc"
+ {
+ ExprResult E = getDerived().TransformExpr(cast<Expr>(S));
+ if (E.isInvalid())
+ return StmtError();
+
+ return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take()));
+ }
+ }
+
+ return SemaRef.Owned(S);
+}
+
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
+ if (!E)
+ return SemaRef.Owned(E);
+
+ switch (E->getStmtClass()) {
+ case Stmt::NoStmtClass: break;
+#define STMT(Node, Parent) case Stmt::Node##Class: break;
+#define ABSTRACT_STMT(Stmt)
+#define EXPR(Node, Parent) \
+ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
+#include "clang/AST/StmtNodes.inc"
+ }
+
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
+ unsigned NumInputs,
+ bool IsCall,
+ llvm::SmallVectorImpl<Expr *> &Outputs,
+ bool *ArgChanged) {
+ for (unsigned I = 0; I != NumInputs; ++I) {
+ // If requested, drop call arguments that need to be dropped.
+ if (IsCall && getDerived().DropCallArgument(Inputs[I])) {
+ if (ArgChanged)
+ *ArgChanged = true;
+
+ break;
+ }
+
+ if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(Inputs[I])) {
+ Expr *Pattern = Expansion->getPattern();
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> OrigNumExpansions
+ = Expansion->getNumExpansions();
+ llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
+ Pattern->getSourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ Expand, RetainExpansion,
+ NumExpansions))
+ return true;
+
+ if (!Expand) {
+ // The transform has determined that we should perform a simple
+ // transformation on the pack expansion, producing another pack
+ // expansion.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ ExprResult OutPattern = getDerived().TransformExpr(Pattern);
+ if (OutPattern.isInvalid())
+ return true;
+
+ ExprResult Out = getDerived().RebuildPackExpansion(OutPattern.get(),
+ Expansion->getEllipsisLoc(),
+ NumExpansions);
+ if (Out.isInvalid())
+ return true;
+
+ if (ArgChanged)
+ *ArgChanged = true;
+ Outputs.push_back(Out.get());
+ continue;
+ }
+
+ // The transform has determined that we should perform an elementwise
+ // expansion of the pattern. Do so.
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+ ExprResult Out = getDerived().TransformExpr(Pattern);
+ if (Out.isInvalid())
+ return true;
+
+ if (Out.get()->containsUnexpandedParameterPack()) {
+ Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(),
+ OrigNumExpansions);
+ if (Out.isInvalid())
+ return true;
+ }
+
+ if (ArgChanged)
+ *ArgChanged = true;
+ Outputs.push_back(Out.get());
+ }
+
+ continue;
+ }
+
+ ExprResult Result = getDerived().TransformExpr(Inputs[I]);
+ if (Result.isInvalid())
+ return true;
+
+ if (Result.get() != Inputs[I] && ArgChanged)
+ *ArgChanged = true;
+
+ Outputs.push_back(Result.get());
+ }
+
+ return false;
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ NestedNameSpecifier *Prefix = NNS->getPrefix();
+
+ // Transform the prefix of this nested name specifier.
+ if (Prefix) {
+ Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
+ ObjectType,
+ FirstQualifierInScope);
+ if (!Prefix)
+ return 0;
+ }
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ if (Prefix) {
+ // The object type and qualifier-in-scope really apply to the
+ // leftmost entity.
+ ObjectType = QualType();
+ FirstQualifierInScope = 0;
+ }
+
+ assert((Prefix || !ObjectType.isNull()) &&
+ "Identifier nested-name-specifier with no prefix or object type");
+ if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix() &&
+ ObjectType.isNull())
+ return NNS;
+
+ return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
+ *NNS->getAsIdentifier(),
+ ObjectType,
+ FirstQualifierInScope);
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS
+ = cast_or_null<NamespaceDecl>(
+ getDerived().TransformDecl(Range.getBegin(),
+ NNS->getAsNamespace()));
+ if (!getDerived().AlwaysRebuild() &&
+ Prefix == NNS->getPrefix() &&
+ NS == NNS->getAsNamespace())
+ return NNS;
+
+ return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
+ }
+
+ case NestedNameSpecifier::Global:
+ // There is no meaningful transformation that one could perform on the
+ // global scope.
+ return NNS;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec: {
+ TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
+ QualType T = TransformTypeInObjectScope(QualType(NNS->getAsType(), 0),
+ ObjectType,
+ FirstQualifierInScope,
+ Prefix);
+ if (T.isNull())
+ return 0;
+
+ if (!getDerived().AlwaysRebuild() &&
+ Prefix == NNS->getPrefix() &&
+ T == QualType(NNS->getAsType(), 0))
+ return NNS;
+
+ return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
+ NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
+ T);
+ }
+ }
+
+ // Required to silence a GCC warning
+ return 0;
+}
+
+template<typename Derived>
+DeclarationNameInfo
+TreeTransform<Derived>
+::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
+ DeclarationName Name = NameInfo.getName();
+ if (!Name)
+ return DeclarationNameInfo();
+
+ 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 NameInfo;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName: {
+ TypeSourceInfo *NewTInfo;
+ CanQualType NewCanTy;
+ if (TypeSourceInfo *OldTInfo = NameInfo.getNamedTypeInfo()) {
+ NewTInfo = getDerived().TransformType(OldTInfo);
+ if (!NewTInfo)
+ return DeclarationNameInfo();
+ NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType());
+ }
+ else {
+ NewTInfo = 0;
+ TemporaryBase Rebase(*this, NameInfo.getLoc(), Name);
+ QualType NewT = getDerived().TransformType(Name.getCXXNameType());
+ if (NewT.isNull())
+ return DeclarationNameInfo();
+ NewCanTy = SemaRef.Context.getCanonicalType(NewT);
+ }
+
+ DeclarationName NewName
+ = SemaRef.Context.DeclarationNames.getCXXSpecialName(Name.getNameKind(),
+ NewCanTy);
+ DeclarationNameInfo NewNameInfo(NameInfo);
+ NewNameInfo.setName(NewName);
+ NewNameInfo.setNamedTypeInfo(NewTInfo);
+ return NewNameInfo;
+ }
+ }
+
+ assert(0 && "Unknown name kind.");
+ return DeclarationNameInfo();
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ SourceLocation Loc = getDerived().getBaseLocation();
+
+ if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
+ /*FIXME*/ SourceRange(Loc),
+ ObjectType,
+ FirstQualifierInScope);
+ if (!NNS)
+ return TemplateName();
+
+ if (TemplateDecl *Template = QTN->getTemplateDecl()) {
+ TemplateDecl *TransTemplate
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template));
+ if (!TransTemplate)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == QTN->getQualifier() &&
+ TransTemplate == Template)
+ return Name;
+
+ return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+ TransTemplate);
+ }
+
+ // These should be getting filtered out before they make it into the AST.
+ llvm_unreachable("overloaded template name survived to here");
+ }
+
+ if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ NestedNameSpecifier *NNS = DTN->getQualifier();
+ if (NNS) {
+ NNS = getDerived().TransformNestedNameSpecifier(NNS,
+ /*FIXME:*/SourceRange(Loc),
+ ObjectType,
+ FirstQualifierInScope);
+ if (!NNS) return TemplateName();
+
+ // These apply to the scope specifier, not the template.
+ ObjectType = QualType();
+ FirstQualifierInScope = 0;
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == DTN->getQualifier() &&
+ ObjectType.isNull())
+ return Name;
+
+ if (DTN->isIdentifier()) {
+ // FIXME: Bad range
+ SourceRange QualifierRange(getDerived().getBaseLocation());
+ return getDerived().RebuildTemplateName(NNS, QualifierRange,
+ *DTN->getIdentifier(),
+ ObjectType,
+ FirstQualifierInScope);
+ }
+
+ return getDerived().RebuildTemplateName(NNS, DTN->getOperator(),
+ ObjectType);
+ }
+
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ TemplateDecl *TransTemplate
+ = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Loc, Template));
+ if (!TransTemplate)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TransTemplate == Template)
+ return Name;
+
+ return TemplateName(TransTemplate);
+ }
+
+ if (SubstTemplateTemplateParmPackStorage *SubstPack
+ = Name.getAsSubstTemplateTemplateParmPack()) {
+ TemplateTemplateParmDecl *TransParam
+ = cast_or_null<TemplateTemplateParmDecl>(
+ getDerived().TransformDecl(Loc, SubstPack->getParameterPack()));
+ if (!TransParam)
+ return TemplateName();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TransParam == SubstPack->getParameterPack())
+ return Name;
+
+ return getDerived().RebuildTemplateName(TransParam,
+ SubstPack->getArgumentPack());
+ }
+
+ // These should be getting filtered out before they reach the AST.
+ llvm_unreachable("overloaded function decl survived to here");
+ return TemplateName();
+}
+
+template<typename Derived>
+void TreeTransform<Derived>::InventTemplateArgumentLoc(
+ const TemplateArgument &Arg,
+ TemplateArgumentLoc &Output) {
+ SourceLocation Loc = getDerived().getBaseLocation();
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("null template argument in TreeTransform");
+ break;
+
+ case TemplateArgument::Type:
+ Output = TemplateArgumentLoc(Arg,
+ SemaRef.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+
+ break;
+
+ case TemplateArgument::Template:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
+ break;
+
+ case TemplateArgument::TemplateExpansion:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+ break;
+
+ case TemplateArgument::Expression:
+ Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
+ break;
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+ break;
+ }
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformTemplateArgument(
+ const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output) {
+ const TemplateArgument &Arg = Input.getArgument();
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ Output = Input;
+ return false;
+
+ case TemplateArgument::Type: {
+ TypeSourceInfo *DI = Input.getTypeSourceInfo();
+ if (DI == NULL)
+ DI = InventTypeSourceInfo(Input.getArgument().getAsType());
+
+ DI = getDerived().TransformType(DI);
+ if (!DI) return true;
+
+ Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+ return false;
+ }
+
+ case TemplateArgument::Declaration: {
+ // FIXME: we should never have to transform one of these.
+ DeclarationName Name;
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
+ Name = ND->getDeclName();
+ TemporaryBase Rebase(*this, Input.getLocation(), Name);
+ Decl *D = getDerived().TransformDecl(Input.getLocation(), Arg.getAsDecl());
+ if (!D) return true;
+
+ Expr *SourceExpr = Input.getSourceDeclExpression();
+ if (SourceExpr) {
+ EnterExpressionEvaluationContext Unevaluated(getSema(),
+ Sema::Unevaluated);
+ ExprResult E = getDerived().TransformExpr(SourceExpr);
+ SourceExpr = (E.isInvalid() ? 0 : E.take());
+ }
+
+ Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr);
+ return false;
+ }
+
+ case TemplateArgument::Template: {
+ TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());
+ TemplateName Template
+ = getDerived().TransformTemplateName(Arg.getAsTemplate());
+ if (Template.isNull())
+ return true;
+
+ Output = TemplateArgumentLoc(TemplateArgument(Template),
+ Input.getTemplateQualifierRange(),
+ Input.getTemplateNameLoc());
+ return false;
+ }
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("Caller should expand pack expansions");
+
+ case TemplateArgument::Expression: {
+ // Template argument expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(getSema(),
+ Sema::Unevaluated);
+
+ Expr *InputExpr = Input.getSourceExpression();
+ if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+
+ ExprResult E
+ = getDerived().TransformExpr(InputExpr);
+ if (E.isInvalid()) return true;
+ Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
+ return false;
+ }
+
+ case TemplateArgument::Pack: {
+ llvm::SmallVector<TemplateArgument, 4> TransformedArgs;
+ TransformedArgs.reserve(Arg.pack_size());
+ for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
+ AEnd = Arg.pack_end();
+ A != AEnd; ++A) {
+
+ // FIXME: preserve source information here when we start
+ // caring about parameter packs.
+
+ TemplateArgumentLoc InputArg;
+ TemplateArgumentLoc OutputArg;
+ getDerived().InventTemplateArgumentLoc(*A, InputArg);
+ if (getDerived().TransformTemplateArgument(InputArg, OutputArg))
+ return true;
+
+ TransformedArgs.push_back(OutputArg.getArgument());
+ }
+
+ TemplateArgument *TransformedArgsPtr
+ = new (getSema().Context) TemplateArgument[TransformedArgs.size()];
+ std::copy(TransformedArgs.begin(), TransformedArgs.end(),
+ TransformedArgsPtr);
+ Output = TemplateArgumentLoc(TemplateArgument(TransformedArgsPtr,
+ TransformedArgs.size()),
+ Input.getLocInfo());
+ return false;
+ }
+ }
+
+ // Work around bogus GCC warning
+ return true;
+}
+
+/// \brief Iterator adaptor that invents template argument location information
+/// for each of the template arguments in its underlying iterator.
+template<typename Derived, typename InputIterator>
+class TemplateArgumentLocInventIterator {
+ TreeTransform<Derived> &Self;
+ InputIterator Iter;
+
+public:
+ typedef TemplateArgumentLoc value_type;
+ typedef TemplateArgumentLoc reference;
+ typedef typename std::iterator_traits<InputIterator>::difference_type
+ difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ class pointer {
+ TemplateArgumentLoc Arg;
+
+ public:
+ explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
+
+ const TemplateArgumentLoc *operator->() const { return &Arg; }
+ };
+
+ TemplateArgumentLocInventIterator() { }
+
+ explicit TemplateArgumentLocInventIterator(TreeTransform<Derived> &Self,
+ InputIterator Iter)
+ : Self(Self), Iter(Iter) { }
+
+ TemplateArgumentLocInventIterator &operator++() {
+ ++Iter;
+ return *this;
+ }
+
+ TemplateArgumentLocInventIterator operator++(int) {
+ TemplateArgumentLocInventIterator Old(*this);
+ ++(*this);
+ return Old;
+ }
+
+ reference operator*() const {
+ TemplateArgumentLoc Result;
+ Self.InventTemplateArgumentLoc(*Iter, Result);
+ return Result;
+ }
+
+ pointer operator->() const { return pointer(**this); }
+
+ friend bool operator==(const TemplateArgumentLocInventIterator &X,
+ const TemplateArgumentLocInventIterator &Y) {
+ return X.Iter == Y.Iter;
+ }
+
+ friend bool operator!=(const TemplateArgumentLocInventIterator &X,
+ const TemplateArgumentLocInventIterator &Y) {
+ return X.Iter != Y.Iter;
+ }
+};
+
+template<typename Derived>
+template<typename InputIterator>
+bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
+ InputIterator Last,
+ TemplateArgumentListInfo &Outputs) {
+ for (; First != Last; ++First) {
+ TemplateArgumentLoc Out;
+ TemplateArgumentLoc In = *First;
+
+ if (In.getArgument().getKind() == TemplateArgument::Pack) {
+ // Unpack argument packs, which we translate them into separate
+ // arguments.
+ // FIXME: We could do much better if we could guarantee that the
+ // TemplateArgumentLocInfo for the pack expansion would be usable for
+ // all of the template arguments in the argument pack.
+ typedef TemplateArgumentLocInventIterator<Derived,
+ TemplateArgument::pack_iterator>
+ PackLocIterator;
+ if (TransformTemplateArguments(PackLocIterator(*this,
+ In.getArgument().pack_begin()),
+ PackLocIterator(*this,
+ In.getArgument().pack_end()),
+ Outputs))
+ return true;
+
+ continue;
+ }
+
+ if (In.getArgument().isPackExpansion()) {
+ // We have a pack expansion, for which we will be substituting into
+ // the pattern.
+ SourceLocation Ellipsis;
+ llvm::Optional<unsigned> OrigNumExpansions;
+ TemplateArgumentLoc Pattern
+ = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions,
+ getSema().Context);
+
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+ assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
+
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+ if (getDerived().TryExpandParameterPacks(Ellipsis,
+ Pattern.getSourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ Expand,
+ RetainExpansion,
+ NumExpansions))
+ return true;
+
+ if (!Expand) {
+ // The transform has determined that we should perform a simple
+ // transformation on the pack expansion, producing another pack
+ // expansion.
+ TemplateArgumentLoc OutPattern;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
+ return true;
+
+ Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
+ NumExpansions);
+ if (Out.getArgument().isNull())
+ return true;
+
+ Outputs.addArgument(Out);
+ continue;
+ }
+
+ // The transform has determined that we should perform an elementwise
+ // expansion of the pattern. Do so.
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+
+ if (getDerived().TransformTemplateArgument(Pattern, Out))
+ return true;
+
+ if (Out.getArgument().containsUnexpandedParameterPack()) {
+ Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+ OrigNumExpansions);
+ if (Out.getArgument().isNull())
+ return true;
+ }
+
+ Outputs.addArgument(Out);
+ }
+
+ // If we're supposed to retain a pack expansion, do so by temporarily
+ // forgetting the partially-substituted parameter pack.
+ if (RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+ if (getDerived().TransformTemplateArgument(Pattern, Out))
+ return true;
+
+ Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
+ OrigNumExpansions);
+ if (Out.getArgument().isNull())
+ return true;
+
+ Outputs.addArgument(Out);
+ }
+
+ continue;
+ }
+
+ // The simple case:
+ if (getDerived().TransformTemplateArgument(In, Out))
+ return true;
+
+ Outputs.addArgument(Out);
+ }
+
+ return false;
+
+}
+
+//===----------------------------------------------------------------------===//
+// Type transformation
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformType(QualType T) {
+ if (getDerived().AlreadyTransformed(T))
+ return T;
+
+ // Temporary workaround. All of these transformations should
+ // eventually turn into transformations on TypeLocs.
+ TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T,
+ getDerived().getBaseLocation());
+
+ TypeSourceInfo *NewDI = getDerived().TransformType(DI);
+
+ if (!NewDI)
+ return QualType();
+
+ return NewDI->getType();
+}
+
+template<typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+ if (getDerived().AlreadyTransformed(DI->getType()))
+ return DI;
+
+ TypeLocBuilder TLB;
+
+ TypeLoc TL = DI->getTypeLoc();
+ TLB.reserve(TL.getFullDataSize());
+
+ QualType Result = getDerived().TransformType(TLB, TL);
+ if (Result.isNull())
+ return 0;
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+ switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: \
+ return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#include "clang/AST/TypeLocNodes.def"
+ }
+
+ llvm_unreachable("unhandled type loc!");
+ return QualType();
+}
+
+/// FIXME: By default, this routine adds type qualifiers only to types
+/// that can have qualifiers, and silently suppresses those qualifiers
+/// that are not permitted (e.g., qualifiers on reference or function
+/// types). This is the right thing for template instantiation, but
+/// probably not for other clients.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
+ QualifiedTypeLoc T) {
+ Qualifiers Quals = T.getType().getLocalQualifiers();
+
+ QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+ if (Result.isNull())
+ return QualType();
+
+ // Silently suppress qualifiers if the result type can't be qualified.
+ // FIXME: this is the right thing for template instantiation, but
+ // probably not for other clients.
+ if (Result->isFunctionType() || Result->isReferenceType())
+ return Result;
+
+ if (!Quals.empty()) {
+ Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals);
+ TLB.push<QualifiedTypeLoc>(Result);
+ // No location information to preserve.
+ }
+
+ return Result;
+}
+
+/// \brief Transforms a type that was written in a scope specifier,
+/// given an object type, the results of unqualified lookup, and
+/// an already-instantiated prefix.
+///
+/// The object type is provided iff the scope specifier qualifies the
+/// member of a dependent member-access expression. The prefix is
+/// provided iff the the scope specifier in which this appears has a
+/// prefix.
+///
+/// This is private to TreeTransform.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformTypeInObjectScope(QualType T,
+ QualType ObjectType,
+ NamedDecl *UnqualLookup,
+ NestedNameSpecifier *Prefix) {
+ if (getDerived().AlreadyTransformed(T))
+ return T;
+
+ TypeSourceInfo *TSI =
+ SemaRef.Context.getTrivialTypeSourceInfo(T, getDerived().getBaseLocation());
+
+ TSI = getDerived().TransformTypeInObjectScope(TSI, ObjectType,
+ UnqualLookup, Prefix);
+ if (!TSI) return QualType();
+ return TSI->getType();
+}
+
+template<typename Derived>
+TypeSourceInfo *
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
+ QualType ObjectType,
+ NamedDecl *UnqualLookup,
+ NestedNameSpecifier *Prefix) {
+ // TODO: in some cases, we might be some verification to do here.
+ if (ObjectType.isNull())
+ return getDerived().TransformType(TSI);
+
+ QualType T = TSI->getType();
+ if (getDerived().AlreadyTransformed(T))
+ return TSI;
+
+ TypeLocBuilder TLB;
+ QualType Result;
+
+ if (isa<TemplateSpecializationType>(T)) {
+ TemplateSpecializationTypeLoc TL
+ = cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
+
+ TemplateName Template =
+ getDerived().TransformTemplateName(TL.getTypePtr()->getTemplateName(),
+ ObjectType, UnqualLookup);
+ if (Template.isNull()) return 0;
+
+ Result = getDerived()
+ .TransformTemplateSpecializationType(TLB, TL, Template);
+ } else if (isa<DependentTemplateSpecializationType>(T)) {
+ DependentTemplateSpecializationTypeLoc TL
+ = cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
+
+ Result = getDerived()
+ .TransformDependentTemplateSpecializationType(TLB, TL, Prefix);
+ } else {
+ // Nothing special needs to be done for these.
+ Result = getDerived().TransformType(TLB, TSI->getTypeLoc());
+ }
+
+ if (Result.isNull()) return 0;
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result);
+}
+
+template <class TyLoc> static inline
+QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
+ TyLoc NewT = TLB.push<TyLoc>(T.getType());
+ NewT.setNameLoc(T.getNameLoc());
+ return T.getType();
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
+ BuiltinTypeLoc T) {
+ BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
+ NewT.setBuiltinLoc(T.getBuiltinLoc());
+ if (T.needsExtraLocalData())
+ NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs();
+ return T.getType();
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
+ ComplexTypeLoc T) {
+ // FIXME: recurse?
+ return TransformTypeSpecType(TLB, T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
+ PointerTypeLoc TL) {
+ QualType PointeeType
+ = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (PointeeType->getAs<ObjCObjectType>()) {
+ // A dependent pointer type 'T *' has is being transformed such
+ // that an Objective-C class type is being replaced for 'T'. The
+ // resulting pointer type is an ObjCObjectPointerType, not a
+ // PointerType.
+ Result = SemaRef.Context.getObjCObjectPointerType(PointeeType);
+
+ ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result);
+ NewT.setStarLoc(TL.getStarLoc());
+ return Result;
+ }
+
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != TL.getPointeeLoc().getType()) {
+ Result = getDerived().RebuildPointerType(PointeeType, TL.getSigilLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ PointerTypeLoc NewT = TLB.push<PointerTypeLoc>(Result);
+ NewT.setSigilLoc(TL.getSigilLoc());
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
+ BlockPointerTypeLoc TL) {
+ QualType PointeeType
+ = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != TL.getPointeeLoc().getType()) {
+ Result = getDerived().RebuildBlockPointerType(PointeeType,
+ TL.getSigilLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ BlockPointerTypeLoc NewT = TLB.push<BlockPointerTypeLoc>(Result);
+ NewT.setSigilLoc(TL.getSigilLoc());
+ return Result;
+}
+
+/// Transforms a reference type. Note that somewhat paradoxically we
+/// don't care whether the type itself is an l-value type or an r-value
+/// type; we only care if the type was *written* as an l-value type
+/// or an r-value type.
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
+ ReferenceTypeLoc TL) {
+ const ReferenceType *T = TL.getTypePtr();
+
+ // Note that this works with the pointee-as-written.
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeTypeAsWritten()) {
+ Result = getDerived().RebuildReferenceType(PointeeType,
+ T->isSpelledAsLValue(),
+ TL.getSigilLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // r-value references can be rebuilt as l-value references.
+ ReferenceTypeLoc NewTL;
+ if (isa<LValueReferenceType>(Result))
+ NewTL = TLB.push<LValueReferenceTypeLoc>(Result);
+ else
+ NewTL = TLB.push<RValueReferenceTypeLoc>(Result);
+ NewTL.setSigilLoc(TL.getSigilLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
+ LValueReferenceTypeLoc TL) {
+ return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
+ RValueReferenceTypeLoc TL) {
+ return TransformReferenceType(TLB, TL);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
+ MemberPointerTypeLoc TL) {
+ const MemberPointerType *T = TL.getTypePtr();
+
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
+
+ // TODO: preserve source information for this.
+ QualType ClassType
+ = getDerived().TransformType(QualType(T->getClass(), 0));
+ if (ClassType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeType() ||
+ ClassType != QualType(T->getClass(), 0)) {
+ Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType,
+ TL.getStarLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
+ NewTL.setSigilLoc(TL.getSigilLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
+ ConstantArrayTypeLoc TL) {
+ const ConstantArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+ if (ElementType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildConstantArrayType(ElementType,
+ T->getSizeModifier(),
+ T->getSize(),
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+
+ Expr *Size = TL.getSizeExpr();
+ if (Size) {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
+ }
+ NewTL.setSizeExpr(Size);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformIncompleteArrayType(
+ TypeLocBuilder &TLB,
+ IncompleteArrayTypeLoc TL) {
+ const IncompleteArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+ if (ElementType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildIncompleteArrayType(ElementType,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(0);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
+ VariableArrayTypeLoc TL) {
+ const VariableArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+ if (ElementType.isNull())
+ return QualType();
+
+ // Array bounds are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult SizeResult
+ = getDerived().TransformExpr(T->getSizeExpr());
+ if (SizeResult.isInvalid())
+ return QualType();
+
+ Expr *Size = SizeResult.take();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType() ||
+ Size != T->getSizeExpr()) {
+ Result = getDerived().RebuildVariableArrayType(ElementType,
+ T->getSizeModifier(),
+ Size,
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(Size);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
+ DependentSizedArrayTypeLoc TL) {
+ const DependentSizedArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
+ if (ElementType.isNull())
+ return QualType();
+
+ // Array bounds are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ // Prefer the expression from the TypeLoc; the other may have been uniqued.
+ Expr *origSize = TL.getSizeExpr();
+ if (!origSize) origSize = T->getSizeExpr();
+
+ ExprResult sizeResult
+ = getDerived().TransformExpr(origSize);
+ if (sizeResult.isInvalid())
+ return QualType();
+
+ Expr *size = sizeResult.get();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType() ||
+ size != origSize) {
+ Result = getDerived().RebuildDependentSizedArrayType(ElementType,
+ T->getSizeModifier(),
+ size,
+ T->getIndexTypeCVRQualifiers(),
+ TL.getBracketsRange());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // We might have any sort of array type now, but fortunately they
+ // all have the same location layout.
+ ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(size);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
+ TypeLocBuilder &TLB,
+ DependentSizedExtVectorTypeLoc TL) {
+ const DependentSizedExtVectorType *T = TL.getTypePtr();
+
+ // FIXME: ext vector locs should be nested
+ QualType ElementType = getDerived().TransformType(T->getElementType());
+ if (ElementType.isNull())
+ return QualType();
+
+ // Vector sizes are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ if (Size.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType() ||
+ Size.get() != T->getSizeExpr()) {
+ Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
+ Size.take(),
+ T->getAttributeLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // Result might be dependent or not.
+ if (isa<DependentSizedExtVectorType>(Result)) {
+ DependentSizedExtVectorTypeLoc NewTL
+ = TLB.push<DependentSizedExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ } else {
+ ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ }
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
+ VectorTypeLoc TL) {
+ const VectorType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(T->getElementType());
+ if (ElementType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
+ T->getVectorKind());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
+ ExtVectorTypeLoc TL) {
+ const VectorType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(T->getElementType());
+ if (ElementType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildExtVectorType(ElementType,
+ T->getNumElements(),
+ /*FIXME*/ SourceLocation());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+ParmVarDecl *
+TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ llvm::Optional<unsigned> NumExpansions) {
+ TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
+ TypeSourceInfo *NewDI = 0;
+
+ if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) {
+ // If we're substituting into a pack expansion type and we know the
+ TypeLoc OldTL = OldDI->getTypeLoc();
+ PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL);
+
+ TypeLocBuilder TLB;
+ TypeLoc NewTL = OldDI->getTypeLoc();
+ TLB.reserve(NewTL.getFullDataSize());
+
+ QualType Result = getDerived().TransformType(TLB,
+ OldExpansionTL.getPatternLoc());
+ if (Result.isNull())
+ return 0;
+
+ Result = RebuildPackExpansionType(Result,
+ OldExpansionTL.getPatternLoc().getSourceRange(),
+ OldExpansionTL.getEllipsisLoc(),
+ NumExpansions);
+ if (Result.isNull())
+ return 0;
+
+ PackExpansionTypeLoc NewExpansionTL
+ = TLB.push<PackExpansionTypeLoc>(Result);
+ NewExpansionTL.setEllipsisLoc(OldExpansionTL.getEllipsisLoc());
+ NewDI = TLB.getTypeSourceInfo(SemaRef.Context, Result);
+ } else
+ NewDI = getDerived().TransformType(OldDI);
+ if (!NewDI)
+ return 0;
+
+ if (NewDI == OldDI)
+ return OldParm;
+ else
+ return ParmVarDecl::Create(SemaRef.Context,
+ OldParm->getDeclContext(),
+ OldParm->getLocation(),
+ OldParm->getIdentifier(),
+ NewDI->getType(),
+ NewDI,
+ OldParm->getStorageClass(),
+ OldParm->getStorageClassAsWritten(),
+ /* DefArg */ NULL);
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::
+ TransformFunctionTypeParams(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const QualType *ParamTypes,
+ llvm::SmallVectorImpl<QualType> &OutParamTypes,
+ llvm::SmallVectorImpl<ParmVarDecl*> *PVars) {
+ for (unsigned i = 0; i != NumParams; ++i) {
+ if (ParmVarDecl *OldParm = Params[i]) {
+ llvm::Optional<unsigned> NumExpansions;
+ if (OldParm->isParameterPack()) {
+ // We have a function parameter pack that may need to be expanded.
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+
+ // Find the parameter packs that could be expanded.
+ TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
+ PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL);
+ TypeLoc Pattern = ExpansionTL.getPatternLoc();
+ SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+
+ // Determine whether we should expand the parameter packs.
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> OrigNumExpansions
+ = ExpansionTL.getTypePtr()->getNumExpansions();
+ NumExpansions = OrigNumExpansions;
+ if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
+ Pattern.getSourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
+ return true;
+ }
+
+ if (ShouldExpand) {
+ // Expand the function parameter pack into multiple, separate
+ // parameters.
+ getDerived().ExpandingFunctionParameterPack(OldParm);
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+ ParmVarDecl *NewParm
+ = getDerived().TransformFunctionTypeParam(OldParm,
+ OrigNumExpansions);
+ if (!NewParm)
+ return true;
+
+ OutParamTypes.push_back(NewParm->getType());
+ if (PVars)
+ PVars->push_back(NewParm);
+ }
+
+ // If we're supposed to retain a pack expansion, do so by temporarily
+ // forgetting the partially-substituted parameter pack.
+ if (RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+ ParmVarDecl *NewParm
+ = getDerived().TransformFunctionTypeParam(OldParm,
+ OrigNumExpansions);
+ if (!NewParm)
+ return true;
+
+ OutParamTypes.push_back(NewParm->getType());
+ if (PVars)
+ PVars->push_back(NewParm);
+ }
+
+ // We're done with the pack expansion.
+ continue;
+ }
+
+ // We'll substitute the parameter now without expanding the pack
+ // expansion.
+ }
+
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm,
+ NumExpansions);
+ if (!NewParm)
+ return true;
+
+ OutParamTypes.push_back(NewParm->getType());
+ if (PVars)
+ PVars->push_back(NewParm);
+ continue;
+ }
+
+ // Deal with the possibility that we don't have a parameter
+ // declaration for this parameter.
+ QualType OldType = ParamTypes[i];
+ bool IsPackExpansion = false;
+ llvm::Optional<unsigned> NumExpansions;
+ if (const PackExpansionType *Expansion
+ = dyn_cast<PackExpansionType>(OldType)) {
+ // We have a function parameter pack that may need to be expanded.
+ QualType Pattern = Expansion->getPattern();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);
+
+ // Determine whether we should expand the parameter packs.
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
+ Unexpanded.data(),
+ Unexpanded.size(),
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
+ return true;
+ }
+
+ if (ShouldExpand) {
+ // Expand the function parameter pack into multiple, separate
+ // parameters.
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+ QualType NewType = getDerived().TransformType(Pattern);
+ if (NewType.isNull())
+ return true;
+
+ OutParamTypes.push_back(NewType);
+ if (PVars)
+ PVars->push_back(0);
+ }
+
+ // We're done with the pack expansion.
+ continue;
+ }
+
+ // If we're supposed to retain a pack expansion, do so by temporarily
+ // forgetting the partially-substituted parameter pack.
+ if (RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+ QualType NewType = getDerived().TransformType(Pattern);
+ if (NewType.isNull())
+ return true;
+
+ OutParamTypes.push_back(NewType);
+ if (PVars)
+ PVars->push_back(0);
+ }
+
+ // We'll substitute the parameter now without expanding the pack
+ // expansion.
+ OldType = Expansion->getPattern();
+ IsPackExpansion = true;
+ }
+
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ QualType NewType = getDerived().TransformType(OldType);
+ if (NewType.isNull())
+ return true;
+
+ if (IsPackExpansion)
+ NewType = getSema().Context.getPackExpansionType(NewType,
+ NumExpansions);
+
+ OutParamTypes.push_back(NewType);
+ if (PVars)
+ PVars->push_back(0);
+ }
+
+ return false;
+ }
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL) {
+ // Transform the parameters and return type.
+ //
+ // We instantiate in source order, with the return type first followed by
+ // the parameters, because users tend to expect this (even if they shouldn't
+ // rely on it!).
+ //
+ // When the function has a trailing return type, we instantiate the
+ // parameters before the return type, since the return type can then refer
+ // to the parameters themselves (via decltype, sizeof, etc.).
+ //
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
+ const FunctionProtoType *T = TL.getTypePtr();
+
+ QualType ResultType;
+
+ if (TL.getTrailingReturn()) {
+ if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
+ TL.getParmArray(),
+ TL.getNumArgs(),
+ TL.getTypePtr()->arg_type_begin(),
+ ParamTypes, &ParamDecls))
+ return QualType();
+
+ ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+ }
+ else {
+ ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+
+ if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(),
+ TL.getParmArray(),
+ TL.getNumArgs(),
+ TL.getTypePtr()->arg_type_begin(),
+ ParamTypes, &ParamDecls))
+ return QualType();
+ }
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ResultType != T->getResultType() ||
+ T->getNumArgs() != ParamTypes.size() ||
+ !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+ Result = getDerived().RebuildFunctionProtoType(ResultType,
+ ParamTypes.data(),
+ ParamTypes.size(),
+ T->isVariadic(),
+ T->getTypeQuals(),
+ T->getRefQualifier(),
+ T->getExtInfo());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setTrailingReturn(TL.getTrailingReturn());
+ for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
+ NewTL.setArg(i, ParamDecls[i]);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
+ TypeLocBuilder &TLB,
+ FunctionNoProtoTypeLoc TL) {
+ const FunctionNoProtoType *T = TL.getTypePtr();
+ QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ResultType != T->getResultType())
+ Result = getDerived().RebuildFunctionNoProtoType(ResultType);
+
+ FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setTrailingReturn(false);
+
+ return Result;
+}
+
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+ UnresolvedUsingTypeLoc TL) {
+ const UnresolvedUsingType *T = TL.getTypePtr();
+ Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl());
+ if (!D)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+ Result = getDerived().RebuildUnresolvedUsingType(D);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // We might get an arbitrary type spec type back. We should at
+ // least always get a type spec type, though.
+ TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
+ TypedefTypeLoc TL) {
+ const TypedefType *T = TL.getTypePtr();
+ TypedefDecl *Typedef
+ = cast_or_null<TypedefDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+ T->getDecl()));
+ if (!Typedef)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Typedef != T->getDecl()) {
+ Result = getDerived().RebuildTypedefType(Typedef);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
+ TypeOfExprTypeLoc TL) {
+ // typeof expressions are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
+ if (E.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ E.get() != TL.getUnderlyingExpr()) {
+ Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+ else E.take();
+
+ TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
+ NewTL.setTypeofLoc(TL.getTypeofLoc());
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
+ TypeOfTypeLoc TL) {
+ TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
+ TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
+ if (!New_Under_TI)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) {
+ Result = getDerived().RebuildTypeOfType(New_Under_TI->getType());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
+ NewTL.setTypeofLoc(TL.getTypeofLoc());
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+ NewTL.setUnderlyingTInfo(New_Under_TI);
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
+ DecltypeTypeLoc TL) {
+ const DecltypeType *T = TL.getTypePtr();
+
+ // decltype expressions are not potentially evaluated contexts
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+ if (E.isInvalid())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ E.get() != T->getUnderlyingExpr()) {
+ Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+ else E.take();
+
+ DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
+ AutoTypeLoc TL) {
+ const AutoType *T = TL.getTypePtr();
+ QualType OldDeduced = T->getDeducedType();
+ QualType NewDeduced;
+ if (!OldDeduced.isNull()) {
+ NewDeduced = getDerived().TransformType(OldDeduced);
+ if (NewDeduced.isNull())
+ return QualType();
+ }
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced) {
+ Result = getDerived().RebuildAutoType(NewDeduced);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
+ RecordTypeLoc TL) {
+ const RecordType *T = TL.getTypePtr();
+ RecordDecl *Record
+ = cast_or_null<RecordDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+ T->getDecl()));
+ if (!Record)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Record != T->getDecl()) {
+ Result = getDerived().RebuildRecordType(Record);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
+ EnumTypeLoc TL) {
+ const EnumType *T = TL.getTypePtr();
+ EnumDecl *Enum
+ = cast_or_null<EnumDecl>(getDerived().TransformDecl(TL.getNameLoc(),
+ T->getDecl()));
+ if (!Enum)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Enum != T->getDecl()) {
+ Result = getDerived().RebuildEnumType(Enum);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformInjectedClassNameType(
+ TypeLocBuilder &TLB,
+ InjectedClassNameTypeLoc TL) {
+ Decl *D = getDerived().TransformDecl(TL.getNameLoc(),
+ TL.getTypePtr()->getDecl());
+ if (!D) return QualType();
+
+ QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D));
+ TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc());
+ return T;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
+ TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+ TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL) {
+ const TemplateSpecializationType *T = TL.getTypePtr();
+
+ TemplateName Template
+ = getDerived().TransformTemplateName(T->getTemplateName());
+ if (Template.isNull())
+ return QualType();
+
+ return getDerived().TransformTemplateSpecializationType(TLB, TL, Template);
+}
+
+namespace {
+ /// \brief Simple iterator that traverses the template arguments in a
+ /// container that provides a \c getArgLoc() member function.
+ ///
+ /// This iterator is intended to be used with the iterator form of
+ /// \c TreeTransform<Derived>::TransformTemplateArguments().
+ template<typename ArgLocContainer>
+ class TemplateArgumentLocContainerIterator {
+ ArgLocContainer *Container;
+ unsigned Index;
+
+ public:
+ typedef TemplateArgumentLoc value_type;
+ typedef TemplateArgumentLoc reference;
+ typedef int difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ class pointer {
+ TemplateArgumentLoc Arg;
+
+ public:
+ explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
+
+ const TemplateArgumentLoc *operator->() const {
+ return &Arg;
+ }
+ };
+
+
+ TemplateArgumentLocContainerIterator() {}
+
+ TemplateArgumentLocContainerIterator(ArgLocContainer &Container,
+ unsigned Index)
+ : Container(&Container), Index(Index) { }
+
+ TemplateArgumentLocContainerIterator &operator++() {
+ ++Index;
+ return *this;
+ }
+
+ TemplateArgumentLocContainerIterator operator++(int) {
+ TemplateArgumentLocContainerIterator Old(*this);
+ ++(*this);
+ return Old;
+ }
+
+ TemplateArgumentLoc operator*() const {
+ return Container->getArgLoc(Index);
+ }
+
+ pointer operator->() const {
+ return pointer(Container->getArgLoc(Index));
+ }
+
+ friend bool operator==(const TemplateArgumentLocContainerIterator &X,
+ const TemplateArgumentLocContainerIterator &Y) {
+ return X.Container == Y.Container && X.Index == Y.Index;
+ }
+
+ friend bool operator!=(const TemplateArgumentLocContainerIterator &X,
+ const TemplateArgumentLocContainerIterator &Y) {
+ return !(X == Y);
+ }
+ };
+}
+
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+ TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL,
+ TemplateName Template) {
+ TemplateArgumentListInfo NewTemplateArgs;
+ NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+ NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+ typedef TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>
+ ArgIterator;
+ if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
+ ArgIterator(TL, TL.getNumArgs()),
+ NewTemplateArgs))
+ return QualType();
+
+ // FIXME: maybe don't rebuild if all the template arguments are the same.
+
+ QualType Result =
+ getDerived().RebuildTemplateSpecializationType(Template,
+ TL.getTemplateNameLoc(),
+ NewTemplateArgs);
+
+ if (!Result.isNull()) {
+ TemplateSpecializationTypeLoc NewTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+ NewTL.setLAngleLoc(TL.getLAngleLoc());
+ NewTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+ NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
+ }
+
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
+ ElaboratedTypeLoc TL) {
+ const ElaboratedType *T = TL.getTypePtr();
+
+ NestedNameSpecifier *NNS = 0;
+ // NOTE: the qualifier in an ElaboratedType is optional.
+ if (T->getQualifier() != 0) {
+ NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+ TL.getQualifierRange());
+ if (!NNS)
+ return QualType();
+ }
+
+ QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
+ if (NamedT.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ NNS != T->getQualifier() ||
+ NamedT != T->getNamedType()) {
+ Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(),
+ T->getKeyword(), NNS, NamedT);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+ NewTL.setQualifierRange(TL.getQualifierRange());
+
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformAttributedType(
+ TypeLocBuilder &TLB,
+ AttributedTypeLoc TL) {
+ const AttributedType *oldType = TL.getTypePtr();
+ QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
+ if (modifiedType.isNull())
+ return QualType();
+
+ QualType result = TL.getType();
+
+ // FIXME: dependent operand expressions?
+ if (getDerived().AlwaysRebuild() ||
+ modifiedType != oldType->getModifiedType()) {
+ // TODO: this is really lame; we should really be rebuilding the
+ // equivalent type from first principles.
+ QualType equivalentType
+ = getDerived().TransformType(oldType->getEquivalentType());
+ if (equivalentType.isNull())
+ return QualType();
+ result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
+ modifiedType,
+ equivalentType);
+ }
+
+ AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
+ newTL.setAttrNameLoc(TL.getAttrNameLoc());
+ if (TL.hasAttrOperand())
+ newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
+ if (TL.hasAttrExprOperand())
+ newTL.setAttrExprOperand(TL.getAttrExprOperand());
+ else if (TL.hasAttrEnumOperand())
+ newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
+
+ return result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
+ ParenTypeLoc TL) {
+ QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc());
+ if (Inner.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Inner != TL.getInnerLoc().getType()) {
+ Result = getDerived().RebuildParenType(Inner);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result);
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
+ DependentNameTypeLoc TL) {
+ const DependentNameType *T = TL.getTypePtr();
+
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+ TL.getQualifierRange());
+ if (!NNS)
+ return QualType();
+
+ QualType Result
+ = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
+ T->getIdentifier(),
+ TL.getKeywordLoc(),
+ TL.getQualifierRange(),
+ TL.getNameLoc());
+ if (Result.isNull())
+ return QualType();
+
+ if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
+ QualType NamedT = ElabT->getNamedType();
+ TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
+
+ ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+ NewTL.setQualifierRange(TL.getQualifierRange());
+ } else {
+ DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+ NewTL.setQualifierRange(TL.getQualifierRange());
+ NewTL.setNameLoc(TL.getNameLoc());
+ }
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::
+ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL) {
+ const DependentTemplateSpecializationType *T = TL.getTypePtr();
+
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+ TL.getQualifierRange());
+ if (!NNS)
+ return QualType();
+
+ return getDerived()
+ .TransformDependentTemplateSpecializationType(TLB, TL, NNS);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::
+ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ NestedNameSpecifier *NNS) {
+ const DependentTemplateSpecializationType *T = TL.getTypePtr();
+
+ TemplateArgumentListInfo NewTemplateArgs;
+ NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+ NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+
+ typedef TemplateArgumentLocContainerIterator<
+ DependentTemplateSpecializationTypeLoc> ArgIterator;
+ if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
+ ArgIterator(TL, TL.getNumArgs()),
+ NewTemplateArgs))
+ return QualType();
+
+ QualType Result
+ = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(),
+ NNS,
+ TL.getQualifierRange(),
+ T->getIdentifier(),
+ TL.getNameLoc(),
+ NewTemplateArgs);
+ if (Result.isNull())
+ return QualType();
+
+ if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
+ QualType NamedT = ElabT->getNamedType();
+
+ // Copy information relevant to the template specialization.
+ TemplateSpecializationTypeLoc NamedTL
+ = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+ NamedTL.setLAngleLoc(TL.getLAngleLoc());
+ NamedTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I));
+
+ // Copy information relevant to the elaborated type.
+ ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+ NewTL.setQualifierRange(TL.getQualifierRange());
+ } else {
+ TypeLoc NewTL(Result, TL.getOpaqueData());
+ TLB.pushFullCopy(NewTL);
+ }
+ return Result;
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
+ PackExpansionTypeLoc TL) {
+ QualType Pattern
+ = getDerived().TransformType(TLB, TL.getPatternLoc());
+ if (Pattern.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Pattern != TL.getPatternLoc().getType()) {
+ Result = getDerived().RebuildPackExpansionType(Pattern,
+ TL.getPatternLoc().getSourceRange(),
+ TL.getEllipsisLoc(),
+ TL.getTypePtr()->getNumExpansions());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ PackExpansionTypeLoc NewT = TLB.push<PackExpansionTypeLoc>(Result);
+ NewT.setEllipsisLoc(TL.getEllipsisLoc());
+ return Result;
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
+ ObjCInterfaceTypeLoc TL) {
+ // ObjCInterfaceType is never dependent.
+ TLB.pushFullCopy(TL);
+ return TL.getType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
+ ObjCObjectTypeLoc TL) {
+ // ObjCObjectType is never dependent.
+ TLB.pushFullCopy(TL);
+ return TL.getType();
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
+ ObjCObjectPointerTypeLoc TL) {
+ // ObjCObjectPointerType is never dependent.
+ TLB.pushFullCopy(TL);
+ return TL.getType();
+}
+
+//===----------------------------------------------------------------------===//
+// Statement transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformNullStmt(NullStmt *S) {
+ return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) {
+ return getDerived().TransformCompoundStmt(S, false);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
+ bool IsStmtExpr) {
+ bool SubStmtInvalid = false;
+ bool SubStmtChanged = false;
+ ASTOwningVector<Stmt*> Statements(getSema());
+ for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
+ B != BEnd; ++B) {
+ StmtResult Result = getDerived().TransformStmt(*B);
+ if (Result.isInvalid()) {
+ // Immediately fail if this was a DeclStmt, since it's very
+ // likely that this will cause problems for future statements.
+ if (isa<DeclStmt>(*B))
+ return StmtError();
+
+ // Otherwise, just keep processing substatements and fail later.
+ SubStmtInvalid = true;
+ continue;
+ }
+
+ SubStmtChanged = SubStmtChanged || Result.get() != *B;
+ Statements.push_back(Result.takeAs<Stmt>());
+ }
+
+ if (SubStmtInvalid)
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ !SubStmtChanged)
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildCompoundStmt(S->getLBracLoc(),
+ move_arg(Statements),
+ S->getRBracLoc(),
+ IsStmtExpr);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
+ ExprResult LHS, RHS;
+ {
+ // The case value expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ // Transform the left-hand case value.
+ LHS = getDerived().TransformExpr(S->getLHS());
+ if (LHS.isInvalid())
+ return StmtError();
+
+ // Transform the right-hand case value (for the GNU case-range extension).
+ RHS = getDerived().TransformExpr(S->getRHS());
+ if (RHS.isInvalid())
+ return StmtError();
+ }
+
+ // Build the case statement.
+ // Case statements are always rebuilt so that they will attached to their
+ // transformed switch statement.
+ StmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(),
+ LHS.get(),
+ S->getEllipsisLoc(),
+ RHS.get(),
+ S->getColonLoc());
+ if (Case.isInvalid())
+ return StmtError();
+
+ // Transform the statement following the case
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ // Attach the body to the case statement
+ return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
+ // Transform the statement following the default case
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ // Default statements are always rebuilt
+ return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(),
+ SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ Decl *LD = getDerived().TransformDecl(S->getDecl()->getLocation(),
+ S->getDecl());
+ if (!LD)
+ return StmtError();
+
+
+ // FIXME: Pass the real colon location in.
+ return getDerived().RebuildLabelStmt(S->getIdentLoc(),
+ cast<LabelDecl>(LD), SourceLocation(),
+ SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
+ // Transform the condition
+ ExprResult Cond;
+ VarDecl *ConditionVar = 0;
+ if (S->getConditionVariable()) {
+ ConditionVar
+ = cast_or_null<VarDecl>(
+ getDerived().TransformDefinition(
+ S->getConditionVariable()->getLocation(),
+ S->getConditionVariable()));
+ if (!ConditionVar)
+ return StmtError();
+ } else {
+ Cond = getDerived().TransformExpr(S->getCond());
+
+ if (Cond.isInvalid())
+ return StmtError();
+
+ // Convert the condition to a boolean value.
+ if (S->getCond()) {
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(),
+ Cond.get());
+ if (CondE.isInvalid())
+ return StmtError();
+
+ Cond = CondE.get();
+ }
+ }
+
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
+
+ // Transform the "then" branch.
+ StmtResult Then = getDerived().TransformStmt(S->getThen());
+ if (Then.isInvalid())
+ return StmtError();
+
+ // Transform the "else" branch.
+ StmtResult Else = getDerived().TransformStmt(S->getElse());
+ if (Else.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ FullCond.get() == S->getCond() &&
+ ConditionVar == S->getConditionVariable() &&
+ Then.get() == S->getThen() &&
+ Else.get() == S->getElse())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
+ Then.get(),
+ S->getElseLoc(), Else.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
+ // Transform the condition.
+ ExprResult Cond;
+ VarDecl *ConditionVar = 0;
+ if (S->getConditionVariable()) {
+ ConditionVar
+ = cast_or_null<VarDecl>(
+ getDerived().TransformDefinition(
+ S->getConditionVariable()->getLocation(),
+ S->getConditionVariable()));
+ if (!ConditionVar)
+ return StmtError();
+ } else {
+ Cond = getDerived().TransformExpr(S->getCond());
+
+ if (Cond.isInvalid())
+ return StmtError();
+ }
+
+ // Rebuild the switch statement.
+ StmtResult Switch
+ = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(),
+ ConditionVar);
+ if (Switch.isInvalid())
+ return StmtError();
+
+ // Transform the body of the switch statement.
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // Complete the switch statement.
+ return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), Switch.get(),
+ Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
+ // Transform the condition
+ ExprResult Cond;
+ VarDecl *ConditionVar = 0;
+ if (S->getConditionVariable()) {
+ ConditionVar
+ = cast_or_null<VarDecl>(
+ getDerived().TransformDefinition(
+ S->getConditionVariable()->getLocation(),
+ S->getConditionVariable()));
+ if (!ConditionVar)
+ return StmtError();
+ } else {
+ Cond = getDerived().TransformExpr(S->getCond());
+
+ if (Cond.isInvalid())
+ return StmtError();
+
+ if (S->getCond()) {
+ // Convert the condition to a boolean value.
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(),
+ Cond.get());
+ if (CondE.isInvalid())
+ return StmtError();
+ Cond = CondE;
+ }
+ }
+
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
+
+ // Transform the body
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ FullCond.get() == S->getCond() &&
+ ConditionVar == S->getConditionVariable() &&
+ Body.get() == S->getBody())
+ return Owned(S);
+
+ return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond,
+ ConditionVar, Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
+ // Transform the body
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // Transform the condition
+ ExprResult Cond = getDerived().TransformExpr(S->getCond());
+ if (Cond.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Cond.get() == S->getCond() &&
+ Body.get() == S->getBody())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(),
+ /*FIXME:*/S->getWhileLoc(), Cond.get(),
+ S->getRParenLoc());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
+ // Transform the initialization statement
+ StmtResult Init = getDerived().TransformStmt(S->getInit());
+ if (Init.isInvalid())
+ return StmtError();
+
+ // Transform the condition
+ ExprResult Cond;
+ VarDecl *ConditionVar = 0;
+ if (S->getConditionVariable()) {
+ ConditionVar
+ = cast_or_null<VarDecl>(
+ getDerived().TransformDefinition(
+ S->getConditionVariable()->getLocation(),
+ S->getConditionVariable()));
+ if (!ConditionVar)
+ return StmtError();
+ } else {
+ Cond = getDerived().TransformExpr(S->getCond());
+
+ if (Cond.isInvalid())
+ return StmtError();
+
+ if (S->getCond()) {
+ // Convert the condition to a boolean value.
+ ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(),
+ Cond.get());
+ if (CondE.isInvalid())
+ return StmtError();
+
+ Cond = CondE.get();
+ }
+ }
+
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
+
+ // Transform the increment
+ ExprResult Inc = getDerived().TransformExpr(S->getInc());
+ if (Inc.isInvalid())
+ return StmtError();
+
+ Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get()));
+ if (S->getInc() && !FullInc.get())
+ return StmtError();
+
+ // Transform the body
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Init.get() == S->getInit() &&
+ FullCond.get() == S->getCond() &&
+ Inc.get() == S->getInc() &&
+ Body.get() == S->getBody())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
+ Init.get(), FullCond, ConditionVar,
+ FullInc, S->getRParenLoc(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
+ Decl *LD = getDerived().TransformDecl(S->getLabel()->getLocation(),
+ S->getLabel());
+ if (!LD)
+ return StmtError();
+
+ // Goto statements must always be rebuilt, to resolve the label.
+ return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
+ cast<LabelDecl>(LD));
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
+ ExprResult Target = getDerived().TransformExpr(S->getTarget());
+ if (Target.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Target.get() == S->getTarget())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
+ Target.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
+ return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
+ return SemaRef.Owned(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) {
+ ExprResult Result = getDerived().TransformExpr(S->getRetValue());
+ if (Result.isInvalid())
+ return StmtError();
+
+ // FIXME: We always rebuild the return statement because there is no way
+ // to tell whether the return type of the function has changed.
+ return getDerived().RebuildReturnStmt(S->getReturnLoc(), Result.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
+ bool DeclChanged = false;
+ llvm::SmallVector<Decl *, 4> Decls;
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(),
+ *D);
+ if (!Transformed)
+ return StmtError();
+
+ if (Transformed != *D)
+ DeclChanged = true;
+
+ Decls.push_back(Transformed);
+ }
+
+ if (!getDerived().AlwaysRebuild() && !DeclChanged)
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(),
+ S->getStartLoc(), S->getEndLoc());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
+
+ ASTOwningVector<Expr*> Constraints(getSema());
+ ASTOwningVector<Expr*> Exprs(getSema());
+ llvm::SmallVector<IdentifierInfo *, 4> Names;
+
+ ExprResult AsmString;
+ ASTOwningVector<Expr*> Clobbers(getSema());
+
+ bool ExprsChanged = false;
+
+ // Go through the outputs.
+ for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) {
+ Names.push_back(S->getOutputIdentifier(I));
+
+ // No need to transform the constraint literal.
+ Constraints.push_back(S->getOutputConstraintLiteral(I));
+
+ // Transform the output expr.
+ Expr *OutputExpr = S->getOutputExpr(I);
+ ExprResult Result = getDerived().TransformExpr(OutputExpr);
+ if (Result.isInvalid())
+ return StmtError();
+
+ ExprsChanged |= Result.get() != OutputExpr;
+
+ Exprs.push_back(Result.get());
+ }
+
+ // Go through the inputs.
+ for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) {
+ Names.push_back(S->getInputIdentifier(I));
+
+ // No need to transform the constraint literal.
+ Constraints.push_back(S->getInputConstraintLiteral(I));
+
+ // Transform the input expr.
+ Expr *InputExpr = S->getInputExpr(I);
+ ExprResult Result = getDerived().TransformExpr(InputExpr);
+ if (Result.isInvalid())
+ return StmtError();
+
+ ExprsChanged |= Result.get() != InputExpr;
+
+ Exprs.push_back(Result.get());
+ }
+
+ if (!getDerived().AlwaysRebuild() && !ExprsChanged)
+ return SemaRef.Owned(S);
+
+ // Go through the clobbers.
+ for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
+ Clobbers.push_back(S->getClobber(I));
+
+ // No need to transform the asm string literal.
+ AsmString = SemaRef.Owned(S->getAsmString());
+
+ return getDerived().RebuildAsmStmt(S->getAsmLoc(),
+ S->isSimple(),
+ S->isVolatile(),
+ S->getNumOutputs(),
+ S->getNumInputs(),
+ Names.data(),
+ move_arg(Constraints),
+ move_arg(Exprs),
+ AsmString.get(),
+ move_arg(Clobbers),
+ S->getRParenLoc(),
+ S->isMSAsm());
+}
+
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
+ // Transform the body of the @try.
+ StmtResult TryBody = getDerived().TransformStmt(S->getTryBody());
+ if (TryBody.isInvalid())
+ return StmtError();
+
+ // Transform the @catch statements (if present).
+ bool AnyCatchChanged = false;
+ ASTOwningVector<Stmt*> CatchStmts(SemaRef);
+ for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
+ StmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I));
+ if (Catch.isInvalid())
+ return StmtError();
+ if (Catch.get() != S->getCatchStmt(I))
+ AnyCatchChanged = true;
+ CatchStmts.push_back(Catch.release());
+ }
+
+ // Transform the @finally statement (if present).
+ StmtResult Finally;
+ if (S->getFinallyStmt()) {
+ Finally = getDerived().TransformStmt(S->getFinallyStmt());
+ if (Finally.isInvalid())
+ return StmtError();
+ }
+
+ // If nothing changed, just retain this statement.
+ if (!getDerived().AlwaysRebuild() &&
+ TryBody.get() == S->getTryBody() &&
+ !AnyCatchChanged &&
+ Finally.get() == S->getFinallyStmt())
+ return SemaRef.Owned(S);
+
+ // Build a new statement.
+ return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(),
+ move_arg(CatchStmts), Finally.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ // Transform the @catch parameter, if there is one.
+ VarDecl *Var = 0;
+ if (VarDecl *FromVar = S->getCatchParamDecl()) {
+ TypeSourceInfo *TSInfo = 0;
+ if (FromVar->getTypeSourceInfo()) {
+ TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
+ if (!TSInfo)
+ return StmtError();
+ }
+
+ QualType T;
+ if (TSInfo)
+ T = TSInfo->getType();
+ else {
+ T = getDerived().TransformType(FromVar->getType());
+ if (T.isNull())
+ return StmtError();
+ }
+
+ Var = getDerived().RebuildObjCExceptionDecl(FromVar, TSInfo, T);
+ if (!Var)
+ return StmtError();
+ }
+
+ StmtResult Body = getDerived().TransformStmt(S->getCatchBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ return getDerived().RebuildObjCAtCatchStmt(S->getAtCatchLoc(),
+ S->getRParenLoc(),
+ Var, Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ // Transform the body.
+ StmtResult Body = getDerived().TransformStmt(S->getFinallyBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // If nothing changed, just retain this statement.
+ if (!getDerived().AlwaysRebuild() &&
+ Body.get() == S->getFinallyBody())
+ return SemaRef.Owned(S);
+
+ // Build a new statement.
+ return getDerived().RebuildObjCAtFinallyStmt(S->getAtFinallyLoc(),
+ Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ ExprResult Operand;
+ if (S->getThrowExpr()) {
+ Operand = getDerived().TransformExpr(S->getThrowExpr());
+ if (Operand.isInvalid())
+ return StmtError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Operand.get() == S->getThrowExpr())
+ return getSema().Owned(S);
+
+ return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), Operand.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
+ ObjCAtSynchronizedStmt *S) {
+ // Transform the object we are locking.
+ ExprResult Object = getDerived().TransformExpr(S->getSynchExpr());
+ if (Object.isInvalid())
+ return StmtError();
+
+ // Transform the body.
+ StmtResult Body = getDerived().TransformStmt(S->getSynchBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // If nothing change, just retain the current statement.
+ if (!getDerived().AlwaysRebuild() &&
+ Object.get() == S->getSynchExpr() &&
+ Body.get() == S->getSynchBody())
+ return SemaRef.Owned(S);
+
+ // Build a new statement.
+ return getDerived().RebuildObjCAtSynchronizedStmt(S->getAtSynchronizedLoc(),
+ Object.get(), Body.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformObjCForCollectionStmt(
+ ObjCForCollectionStmt *S) {
+ // Transform the element statement.
+ StmtResult Element = getDerived().TransformStmt(S->getElement());
+ if (Element.isInvalid())
+ return StmtError();
+
+ // Transform the collection expression.
+ ExprResult Collection = getDerived().TransformExpr(S->getCollection());
+ if (Collection.isInvalid())
+ return StmtError();
+
+ // Transform the body.
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
+ if (Body.isInvalid())
+ return StmtError();
+
+ // If nothing changed, just retain this statement.
+ if (!getDerived().AlwaysRebuild() &&
+ Element.get() == S->getElement() &&
+ Collection.get() == S->getCollection() &&
+ Body.get() == S->getBody())
+ return SemaRef.Owned(S);
+
+ // Build a new statement.
+ return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(),
+ /*FIXME:*/S->getForLoc(),
+ Element.get(),
+ Collection.get(),
+ S->getRParenLoc(),
+ Body.get());
+}
+
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
+ // Transform the exception declaration, if any.
+ VarDecl *Var = 0;
+ if (S->getExceptionDecl()) {
+ VarDecl *ExceptionDecl = S->getExceptionDecl();
+ TypeSourceInfo *T = getDerived().TransformType(
+ ExceptionDecl->getTypeSourceInfo());
+ if (!T)
+ return StmtError();
+
+ Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T,
+ ExceptionDecl->getIdentifier(),
+ ExceptionDecl->getLocation());
+ if (!Var || Var->isInvalidDecl())
+ return StmtError();
+ }
+
+ // Transform the actual exception handler.
+ StmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock());
+ if (Handler.isInvalid())
+ return StmtError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ !Var &&
+ Handler.get() == S->getHandlerBlock())
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(),
+ Var,
+ Handler.get());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
+ // Transform the try block itself.
+ StmtResult TryBlock
+ = getDerived().TransformCompoundStmt(S->getTryBlock());
+ if (TryBlock.isInvalid())
+ return StmtError();
+
+ // Transform the handlers.
+ bool HandlerChanged = false;
+ ASTOwningVector<Stmt*> Handlers(SemaRef);
+ for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
+ StmtResult Handler
+ = getDerived().TransformCXXCatchStmt(S->getHandler(I));
+ if (Handler.isInvalid())
+ return StmtError();
+
+ HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I);
+ Handlers.push_back(Handler.takeAs<Stmt>());
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ TryBlock.get() == S->getTryBlock() &&
+ !HandlerChanged)
+ return SemaRef.Owned(S);
+
+ return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(),
+ move_arg(Handlers));
+}
+
+//===----------------------------------------------------------------------===//
+// Expression transformation
+//===----------------------------------------------------------------------===//
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return ExprError();
+ }
+
+ ValueDecl *ND
+ = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
+ E->getDecl()));
+ if (!ND)
+ return ExprError();
+
+ DeclarationNameInfo NameInfo = E->getNameInfo();
+ if (NameInfo.getName()) {
+ NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+ if (!NameInfo.getName())
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Qualifier == E->getQualifier() &&
+ ND == E->getDecl() &&
+ NameInfo.getName() == E->getDecl()->getDeclName() &&
+ !E->hasExplicitTemplateArgs()) {
+
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+
+ return SemaRef.Owned(E);
+ }
+
+ TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
+ if (E->hasExplicitTemplateArgs()) {
+ TemplateArgs = &TransArgs;
+ TransArgs.setLAngleLoc(E->getLAngleLoc());
+ TransArgs.setRAngleLoc(E->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+ E->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+ }
+
+ return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
+ ND, NameInfo, TemplateArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildParenExpr(SubExpr.get(), E->getLParen(),
+ E->getRParen());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
+ E->getOpcode(),
+ SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
+ // Transform the type.
+ TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo());
+ if (!Type)
+ return ExprError();
+
+ // Transform all of the components into components similar to what the
+ // parser uses.
+ // FIXME: It would be slightly more efficient in the non-dependent case to
+ // just map FieldDecls, rather than requiring the rebuilder to look for
+ // the fields again. However, __builtin_offsetof is rare enough in
+ // template code that we don't care.
+ bool ExprChanged = false;
+ typedef Sema::OffsetOfComponent Component;
+ typedef OffsetOfExpr::OffsetOfNode Node;
+ llvm::SmallVector<Component, 4> Components;
+ for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
+ const Node &ON = E->getComponent(I);
+ Component Comp;
+ Comp.isBrackets = true;
+ Comp.LocStart = ON.getRange().getBegin();
+ Comp.LocEnd = ON.getRange().getEnd();
+ switch (ON.getKind()) {
+ case Node::Array: {
+ Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
+ ExprResult Index = getDerived().TransformExpr(FromIndex);
+ if (Index.isInvalid())
+ return ExprError();
+
+ ExprChanged = ExprChanged || Index.get() != FromIndex;
+ Comp.isBrackets = true;
+ Comp.U.E = Index.get();
+ break;
+ }
+
+ case Node::Field:
+ case Node::Identifier:
+ Comp.isBrackets = false;
+ Comp.U.IdentInfo = ON.getFieldName();
+ if (!Comp.U.IdentInfo)
+ continue;
+
+ break;
+
+ case Node::Base:
+ // Will be recomputed during the rebuild.
+ continue;
+ }
+
+ Components.push_back(Comp);
+ }
+
+ // If nothing changed, retain the existing expression.
+ if (!getDerived().AlwaysRebuild() &&
+ Type == E->getTypeSourceInfo() &&
+ !ExprChanged)
+ return SemaRef.Owned(E);
+
+ // Build a new offsetof expression.
+ return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type,
+ Components.data(), Components.size(),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
+ assert(getDerived().AlreadyTransformed(E->getType()) &&
+ "opaque value expression requires transformation");
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ if (E->isArgumentType()) {
+ TypeSourceInfo *OldT = E->getArgumentTypeInfo();
+
+ TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+ if (!NewT)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && OldT == NewT)
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(),
+ E->isSizeOf(),
+ E->getSourceRange());
+ }
+
+ ExprResult SubExpr;
+ {
+ // C++0x [expr.sizeof]p1:
+ // The operand is either an expression, which is an unevaluated operand
+ // [...]
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(),
+ E->isSizeOf(),
+ E->getSourceRange());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ if (RHS.isInvalid())
+ return ExprError();
+
+
+ if (!getDerived().AlwaysRebuild() &&
+ LHS.get() == E->getLHS() &&
+ RHS.get() == E->getRHS())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildArraySubscriptExpr(LHS.get(),
+ /*FIXME:*/E->getLHS()->getLocStart(),
+ RHS.get(),
+ E->getRBracketLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
+ // Transform the callee.
+ ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+ if (Callee.isInvalid())
+ return ExprError();
+
+ // Transform arguments.
+ bool ArgChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Callee.get() == E->getCallee() &&
+ !ArgChanged)
+ return SemaRef.Owned(E);
+
+ // FIXME: Wrong source location information for the '('.
+ SourceLocation FakeLParenLoc
+ = ((Expr *)Callee.get())->getSourceRange().getBegin();
+ return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
+ move_arg(Args),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->hasQualifier()) {
+ Qualifier
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (Qualifier == 0)
+ return ExprError();
+ }
+
+ ValueDecl *Member
+ = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberLoc(),
+ E->getMemberDecl()));
+ if (!Member)
+ return ExprError();
+
+ NamedDecl *FoundDecl = E->getFoundDecl();
+ if (FoundDecl == E->getMemberDecl()) {
+ FoundDecl = Member;
+ } else {
+ FoundDecl = cast_or_null<NamedDecl>(
+ getDerived().TransformDecl(E->getMemberLoc(), FoundDecl));
+ if (!FoundDecl)
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase() &&
+ Qualifier == E->getQualifier() &&
+ Member == E->getMemberDecl() &&
+ FoundDecl == E->getFoundDecl() &&
+ !E->hasExplicitTemplateArgs()) {
+
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member);
+ return SemaRef.Owned(E);
+ }
+
+ TemplateArgumentListInfo TransArgs;
+ if (E->hasExplicitTemplateArgs()) {
+ TransArgs.setLAngleLoc(E->getLAngleLoc());
+ TransArgs.setRAngleLoc(E->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+ E->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+ }
+
+ // FIXME: Bogus source location for the operator
+ SourceLocation FakeOperatorLoc
+ = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+
+ // FIXME: to do this check properly, we will need to preserve the
+ // first-qualifier-in-scope here, just in case we had a dependent
+ // base (and therefore couldn't do the check) and a
+ // nested-name-qualifier (and therefore could do the lookup).
+ NamedDecl *FirstQualifierInScope = 0;
+
+ return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
+ E->isArrow(),
+ Qualifier,
+ E->getQualifierRange(),
+ E->getMemberNameInfo(),
+ Member,
+ FoundDecl,
+ (E->hasExplicitTemplateArgs()
+ ? &TransArgs : 0),
+ FirstQualifierInScope);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ if (RHS.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ LHS.get() == E->getLHS() &&
+ RHS.get() == E->getRHS())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
+ LHS.get(), RHS.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCompoundAssignOperator(
+ CompoundAssignOperator *E) {
+ return getDerived().TransformBinaryOperator(E);
+}
+
+template<typename Derived>
+ExprResult TreeTransform<Derived>::
+TransformBinaryConditionalOperator(BinaryConditionalOperator *e) {
+ // Just rebuild the common and RHS expressions and see whether we
+ // get any changes.
+
+ ExprResult commonExpr = getDerived().TransformExpr(e->getCommon());
+ if (commonExpr.isInvalid())
+ return ExprError();
+
+ ExprResult rhs = getDerived().TransformExpr(e->getFalseExpr());
+ if (rhs.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ commonExpr.get() == e->getCommon() &&
+ rhs.get() == e->getFalseExpr())
+ return SemaRef.Owned(e);
+
+ return getDerived().RebuildConditionalOperator(commonExpr.take(),
+ e->getQuestionLoc(),
+ 0,
+ e->getColonLoc(),
+ rhs.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
+ ExprResult Cond = getDerived().TransformExpr(E->getCond());
+ if (Cond.isInvalid())
+ return ExprError();
+
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ if (RHS.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Cond.get() == E->getCond() &&
+ LHS.get() == E->getLHS() &&
+ RHS.get() == E->getRHS())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildConditionalOperator(Cond.get(),
+ E->getQuestionLoc(),
+ LHS.get(),
+ E->getColonLoc(),
+ RHS.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
+ // Implicit casts are eliminated during transformation, since they
+ // will be recomputed by semantic analysis after transformation.
+ return getDerived().TransformExpr(E->getSubExprAsWritten());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
+ TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+ if (!Type)
+ return ExprError();
+
+ ExprResult SubExpr
+ = getDerived().TransformExpr(E->getSubExprAsWritten());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Type == E->getTypeInfoAsWritten() &&
+ SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
+ Type,
+ E->getRParenLoc(),
+ SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ TypeSourceInfo *OldT = E->getTypeSourceInfo();
+ TypeSourceInfo *NewT = getDerived().TransformType(OldT);
+ if (!NewT)
+ return ExprError();
+
+ ExprResult Init = getDerived().TransformExpr(E->getInitializer());
+ if (Init.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ OldT == NewT &&
+ Init.get() == E->getInitializer())
+ return SemaRef.Owned(E);
+
+ // Note: the expression type doesn't necessarily match the
+ // type-as-written, but that's okay, because it should always be
+ // derivable from the initializer.
+
+ return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
+ /*FIXME:*/E->getInitializer()->getLocEnd(),
+ Init.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase())
+ return SemaRef.Owned(E);
+
+ // FIXME: Bad source location
+ SourceLocation FakeOperatorLoc
+ = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
+ return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
+ E->getAccessorLoc(),
+ E->getAccessor());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
+ bool InitChanged = false;
+
+ ASTOwningVector<Expr*, 4> Inits(SemaRef);
+ if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false,
+ Inits, &InitChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && !InitChanged)
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits),
+ E->getRBraceLoc(), E->getType());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
+ Designation Desig;
+
+ // transform the initializer value
+ ExprResult Init = getDerived().TransformExpr(E->getInit());
+ if (Init.isInvalid())
+ return ExprError();
+
+ // transform the designators.
+ ASTOwningVector<Expr*, 4> ArrayExprs(SemaRef);
+ bool ExprChanged = false;
+ for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+ DEnd = E->designators_end();
+ D != DEnd; ++D) {
+ if (D->isFieldDesignator()) {
+ Desig.AddDesignator(Designator::getField(D->getFieldName(),
+ D->getDotLoc(),
+ D->getFieldLoc()));
+ continue;
+ }
+
+ if (D->isArrayDesignator()) {
+ ExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
+ if (Index.isInvalid())
+ return ExprError();
+
+ Desig.AddDesignator(Designator::getArray(Index.get(),
+ D->getLBracketLoc()));
+
+ ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(*D);
+ ArrayExprs.push_back(Index.release());
+ continue;
+ }
+
+ assert(D->isArrayRangeDesignator() && "New kind of designator?");
+ ExprResult Start
+ = getDerived().TransformExpr(E->getArrayRangeStart(*D));
+ if (Start.isInvalid())
+ return ExprError();
+
+ ExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
+ if (End.isInvalid())
+ return ExprError();
+
+ Desig.AddDesignator(Designator::getArrayRange(Start.get(),
+ End.get(),
+ D->getLBracketLoc(),
+ D->getEllipsisLoc()));
+
+ ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(*D) ||
+ End.get() != E->getArrayRangeEnd(*D);
+
+ ArrayExprs.push_back(Start.release());
+ ArrayExprs.push_back(End.release());
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Init.get() == E->getInit() &&
+ !ExprChanged)
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs),
+ E->getEqualOrColonLoc(),
+ E->usesGNUSyntax(), Init.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformImplicitValueInitExpr(
+ ImplicitValueInitExpr *E) {
+ TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
+
+ // FIXME: Will we ever have proper type location here? Will we actually
+ // need to transform the type?
+ QualType T = getDerived().TransformType(E->getType());
+ if (T.isNull())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getType())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildImplicitValueInitExpr(T);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
+ TypeSourceInfo *TInfo = getDerived().TransformType(E->getWrittenTypeInfo());
+ if (!TInfo)
+ return ExprError();
+
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TInfo == E->getWrittenTypeInfo() &&
+ SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), SubExpr.get(),
+ TInfo, E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*, 4> Inits(SemaRef);
+ if (TransformExprs(E->getExprs(), E->getNumExprs(), true, Inits,
+ &ArgumentChanged))
+ return ExprError();
+
+ return getDerived().RebuildParenListExpr(E->getLParenLoc(),
+ move_arg(Inits),
+ E->getRParenLoc());
+}
+
+/// \brief Transform an address-of-label expression.
+///
+/// By default, the transformation of an address-of-label expression always
+/// rebuilds the expression, so that the label identifier can be resolved to
+/// the corresponding label statement by semantic analysis.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) {
+ Decl *LD = getDerived().TransformDecl(E->getLabel()->getLocation(),
+ E->getLabel());
+ if (!LD)
+ return ExprError();
+
+ return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
+ cast<LabelDecl>(LD));
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
+ StmtResult SubStmt
+ = getDerived().TransformCompoundStmt(E->getSubStmt(), true);
+ if (SubStmt.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ SubStmt.get() == E->getSubStmt())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildStmtExpr(E->getLParenLoc(),
+ SubStmt.get(),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
+ ExprResult Cond = getDerived().TransformExpr(E->getCond());
+ if (Cond.isInvalid())
+ return ExprError();
+
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ if (RHS.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Cond.get() == E->getCond() &&
+ LHS.get() == E->getLHS() &&
+ RHS.get() == E->getRHS())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
+ Cond.get(), LHS.get(), RHS.get(),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ switch (E->getOperator()) {
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr");
+ return ExprError();
+
+ case OO_Call: {
+ // This is a call to an object's operator().
+ assert(E->getNumArgs() >= 1 && "Object call is missing arguments");
+
+ // Transform the object itself.
+ ExprResult Object = getDerived().TransformExpr(E->getArg(0));
+ if (Object.isInvalid())
+ return ExprError();
+
+ // FIXME: Poor location information
+ SourceLocation FakeLParenLoc
+ = SemaRef.PP.getLocForEndOfToken(
+ static_cast<Expr *>(Object.get())->getLocEnd());
+
+ // Transform the call arguments.
+ ASTOwningVector<Expr*> Args(SemaRef);
+ if (getDerived().TransformExprs(E->getArgs() + 1, E->getNumArgs() - 1, true,
+ Args))
+ return ExprError();
+
+ return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc,
+ move_arg(Args),
+ E->getLocEnd());
+ }
+
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ case OO_##Name:
+#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+#include "clang/Basic/OperatorKinds.def"
+ case OO_Subscript:
+ // Handled below.
+ break;
+
+ case OO_Conditional:
+ llvm_unreachable("conditional operator is not actually overloadable");
+ return ExprError();
+
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("not an overloaded operator?");
+ return ExprError();
+ }
+
+ ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+ if (Callee.isInvalid())
+ return ExprError();
+
+ ExprResult First = getDerived().TransformExpr(E->getArg(0));
+ if (First.isInvalid())
+ return ExprError();
+
+ ExprResult Second;
+ if (E->getNumArgs() == 2) {
+ Second = getDerived().TransformExpr(E->getArg(1));
+ if (Second.isInvalid())
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Callee.get() == E->getCallee() &&
+ First.get() == E->getArg(0) &&
+ (E->getNumArgs() != 2 || Second.get() == E->getArg(1)))
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
+ E->getOperatorLoc(),
+ Callee.get(),
+ First.get(),
+ Second.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
+ return getDerived().TransformCallExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
+ // Transform the callee.
+ ExprResult Callee = getDerived().TransformExpr(E->getCallee());
+ if (Callee.isInvalid())
+ return ExprError();
+
+ // Transform exec config.
+ ExprResult EC = getDerived().TransformCallExpr(E->getConfig());
+ if (EC.isInvalid())
+ return ExprError();
+
+ // Transform arguments.
+ bool ArgChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Callee.get() == E->getCallee() &&
+ !ArgChanged)
+ return SemaRef.Owned(E);
+
+ // FIXME: Wrong source location information for the '('.
+ SourceLocation FakeLParenLoc
+ = ((Expr *)Callee.get())->getSourceRange().getBegin();
+ return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
+ move_arg(Args),
+ E->getRParenLoc(), EC.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+ if (!Type)
+ return ExprError();
+
+ ExprResult SubExpr
+ = getDerived().TransformExpr(E->getSubExprAsWritten());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Type == E->getTypeInfoAsWritten() &&
+ SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ // FIXME: Poor source location information here.
+ SourceLocation FakeLAngleLoc
+ = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
+ SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
+ SourceLocation FakeRParenLoc
+ = SemaRef.PP.getLocForEndOfToken(
+ E->getSubExpr()->getSourceRange().getEnd());
+ return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(),
+ E->getStmtClass(),
+ FakeLAngleLoc,
+ Type,
+ FakeRAngleLoc,
+ FakeRAngleLoc,
+ SubExpr.get(),
+ FakeRParenLoc);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
+ return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+ return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
+ CXXReinterpretCastExpr *E) {
+ return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
+ return getDerived().TransformCXXNamedCastExpr(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
+ CXXFunctionalCastExpr *E) {
+ TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten());
+ if (!Type)
+ return ExprError();
+
+ ExprResult SubExpr
+ = getDerived().TransformExpr(E->getSubExprAsWritten());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Type == E->getTypeInfoAsWritten() &&
+ SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXFunctionalCastExpr(Type,
+ /*FIXME:*/E->getSubExpr()->getLocStart(),
+ SubExpr.get(),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
+ if (E->isTypeOperand()) {
+ TypeSourceInfo *TInfo
+ = getDerived().TransformType(E->getTypeOperandSourceInfo());
+ if (!TInfo)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TInfo == E->getTypeOperandSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXTypeidExpr(E->getType(),
+ E->getLocStart(),
+ TInfo,
+ E->getLocEnd());
+ }
+
+ // We don't know whether the expression is potentially evaluated until
+ // after we perform semantic analysis, so the expression is potentially
+ // potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Sema::PotentiallyPotentiallyEvaluated);
+
+ ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ SubExpr.get() == E->getExprOperand())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXTypeidExpr(E->getType(),
+ E->getLocStart(),
+ SubExpr.get(),
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) {
+ if (E->isTypeOperand()) {
+ TypeSourceInfo *TInfo
+ = getDerived().TransformType(E->getTypeOperandSourceInfo());
+ if (!TInfo)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ TInfo == E->getTypeOperandSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXTypeidExpr(E->getType(),
+ E->getLocStart(),
+ TInfo,
+ E->getLocEnd());
+ }
+
+ // We don't know whether the expression is potentially evaluated until
+ // after we perform semantic analysis, so the expression is potentially
+ // potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+
+ ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ SubExpr.get() == E->getExprOperand())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXUuidofExpr(E->getType(),
+ E->getLocStart(),
+ SubExpr.get(),
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
+ CXXNullPtrLiteralExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+ DeclContext *DC = getSema().getFunctionLevelDeclContext();
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC);
+ QualType T = MD->getThisType(getSema().Context);
+
+ if (!getDerived().AlwaysRebuild() && T == E->getType())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ SubExpr.get() == E->getSubExpr())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ ParmVarDecl *Param
+ = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(),
+ E->getParam()));
+ if (!Param)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ Param == E->getParam())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXScalarValueInitExpr(
+ CXXScalarValueInitExpr *E) {
+ TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+ if (!T)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getTypeSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXScalarValueInitExpr(T,
+ /*FIXME:*/T->getTypeLoc().getEndLoc(),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
+ // Transform the type that we're allocating
+ TypeSourceInfo *AllocTypeInfo
+ = getDerived().TransformType(E->getAllocatedTypeSourceInfo());
+ if (!AllocTypeInfo)
+ return ExprError();
+
+ // Transform the size of the array we're allocating (if any).
+ ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
+ if (ArraySize.isInvalid())
+ return ExprError();
+
+ // Transform the placement arguments (if any).
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*> PlacementArgs(SemaRef);
+ if (getDerived().TransformExprs(E->getPlacementArgs(),
+ E->getNumPlacementArgs(), true,
+ PlacementArgs, &ArgumentChanged))
+ return ExprError();
+
+ // transform the constructor arguments (if any).
+ ASTOwningVector<Expr*> ConstructorArgs(SemaRef);
+ if (TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true,
+ ConstructorArgs, &ArgumentChanged))
+ return ExprError();
+
+ // Transform constructor, new operator, and delete operator.
+ CXXConstructorDecl *Constructor = 0;
+ if (E->getConstructor()) {
+ Constructor = cast_or_null<CXXConstructorDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getConstructor()));
+ if (!Constructor)
+ return ExprError();
+ }
+
+ FunctionDecl *OperatorNew = 0;
+ if (E->getOperatorNew()) {
+ OperatorNew = cast_or_null<FunctionDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getOperatorNew()));
+ if (!OperatorNew)
+ return ExprError();
+ }
+
+ FunctionDecl *OperatorDelete = 0;
+ if (E->getOperatorDelete()) {
+ OperatorDelete = cast_or_null<FunctionDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getOperatorDelete()));
+ if (!OperatorDelete)
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ AllocTypeInfo == E->getAllocatedTypeSourceInfo() &&
+ ArraySize.get() == E->getArraySize() &&
+ Constructor == E->getConstructor() &&
+ OperatorNew == E->getOperatorNew() &&
+ OperatorDelete == E->getOperatorDelete() &&
+ !ArgumentChanged) {
+ // Mark any declarations we need as referenced.
+ // FIXME: instantiation-specific.
+ if (Constructor)
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ if (OperatorNew)
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew);
+ if (OperatorDelete)
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
+ return SemaRef.Owned(E);
+ }
+
+ QualType AllocType = AllocTypeInfo->getType();
+ if (!ArraySize.get()) {
+ // If no array size was specified, but the new expression was
+ // instantiated with an array type (e.g., "new T" where T is
+ // instantiated with "int[4]"), extract the outer bound from the
+ // array type as our array size. We do this with constant and
+ // dependently-sized array types.
+ const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType);
+ if (!ArrayT) {
+ // Do nothing
+ } else if (const ConstantArrayType *ConsArrayT
+ = dyn_cast<ConstantArrayType>(ArrayT)) {
+ ArraySize
+ = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context,
+ ConsArrayT->getSize(),
+ SemaRef.Context.getSizeType(),
+ /*FIXME:*/E->getLocStart()));
+ AllocType = ConsArrayT->getElementType();
+ } else if (const DependentSizedArrayType *DepArrayT
+ = dyn_cast<DependentSizedArrayType>(ArrayT)) {
+ if (DepArrayT->getSizeExpr()) {
+ ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr());
+ AllocType = DepArrayT->getElementType();
+ }
+ }
+ }
+
+ return getDerived().RebuildCXXNewExpr(E->getLocStart(),
+ E->isGlobalNew(),
+ /*FIXME:*/E->getLocStart(),
+ move_arg(PlacementArgs),
+ /*FIXME:*/E->getLocStart(),
+ E->getTypeIdParens(),
+ AllocType,
+ AllocTypeInfo,
+ ArraySize.get(),
+ /*FIXME:*/E->getLocStart(),
+ move_arg(ConstructorArgs),
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
+ ExprResult Operand = getDerived().TransformExpr(E->getArgument());
+ if (Operand.isInvalid())
+ return ExprError();
+
+ // Transform the delete operator, if known.
+ FunctionDecl *OperatorDelete = 0;
+ if (E->getOperatorDelete()) {
+ OperatorDelete = cast_or_null<FunctionDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getOperatorDelete()));
+ if (!OperatorDelete)
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Operand.get() == E->getArgument() &&
+ OperatorDelete == E->getOperatorDelete()) {
+ // Mark any declarations we need as referenced.
+ // FIXME: instantiation-specific.
+ if (OperatorDelete)
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
+
+ if (!E->getArgument()->isTypeDependent()) {
+ QualType Destroyed = SemaRef.Context.getBaseElementType(
+ E->getDestroyedType());
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(),
+ SemaRef.LookupDestructor(Record));
+ }
+ }
+
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
+ E->isGlobalDelete(),
+ E->isArrayForm(),
+ Operand.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
+ CXXPseudoDestructorExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ ParsedType ObjectTypePtr;
+ bool MayBePseudoDestructor = false;
+ Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ E->getOperatorLoc(),
+ E->isArrow()? tok::arrow : tok::period,
+ ObjectTypePtr,
+ MayBePseudoDestructor);
+ if (Base.isInvalid())
+ return ExprError();
+
+ QualType ObjectType = ObjectTypePtr.get();
+ NestedNameSpecifier *Qualifier = E->getQualifier();
+ if (Qualifier) {
+ Qualifier
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange(),
+ ObjectType);
+ if (!Qualifier)
+ return ExprError();
+ }
+
+ PseudoDestructorTypeStorage Destroyed;
+ if (E->getDestroyedTypeInfo()) {
+ TypeSourceInfo *DestroyedTypeInfo
+ = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
+ ObjectType, 0, Qualifier);
+ if (!DestroyedTypeInfo)
+ return ExprError();
+ Destroyed = DestroyedTypeInfo;
+ } else if (ObjectType->isDependentType()) {
+ // We aren't likely to be able to resolve the identifier down to a type
+ // now anyway, so just retain the identifier.
+ Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc());
+ } else {
+ // Look for a destructor known with the given name.
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setScopeRep(Qualifier);
+ SS.setRange(E->getQualifierRange());
+ }
+
+ ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
+ *E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc(),
+ /*Scope=*/0,
+ SS, ObjectTypePtr,
+ false);
+ if (!T)
+ return ExprError();
+
+ Destroyed
+ = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
+ E->getDestroyedTypeLoc());
+ }
+
+ TypeSourceInfo *ScopeTypeInfo = 0;
+ if (E->getScopeTypeInfo()) {
+ ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+ if (!ScopeTypeInfo)
+ return ExprError();
+ }
+
+ return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(),
+ E->getOperatorLoc(),
+ E->isArrow(),
+ Qualifier,
+ E->getQualifierRange(),
+ ScopeTypeInfo,
+ E->getColonColonLoc(),
+ E->getTildeLoc(),
+ Destroyed);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnresolvedLookupExpr(
+ UnresolvedLookupExpr *Old) {
+ TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName());
+
+ LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
+ Sema::LookupOrdinaryName);
+
+ // Transform all the decls.
+ for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
+ E = Old->decls_end(); I != E; ++I) {
+ NamedDecl *InstD = static_cast<NamedDecl*>(
+ getDerived().TransformDecl(Old->getNameLoc(),
+ *I));
+ if (!InstD) {
+ // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+ // This can happen because of dependent hiding.
+ if (isa<UsingShadowDecl>(*I))
+ continue;
+ else
+ return ExprError();
+ }
+
+ // Expand using declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+ for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+ E = UD->shadow_end(); I != E; ++I)
+ R.addDecl(*I);
+ continue;
+ }
+
+ R.addDecl(InstD);
+ }
+
+ // Resolve a kind, but don't do any further analysis. If it's
+ // ambiguous, the callee needs to deal with it.
+ R.resolveKind();
+
+ // Rebuild the nested-name qualifier, if present.
+ CXXScopeSpec SS;
+ NestedNameSpecifier *Qualifier = 0;
+ if (Old->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+ Old->getQualifierRange());
+ if (!Qualifier)
+ return ExprError();
+
+ SS.setScopeRep(Qualifier);
+ SS.setRange(Old->getQualifierRange());
+ }
+
+ if (Old->getNamingClass()) {
+ CXXRecordDecl *NamingClass
+ = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+ Old->getNameLoc(),
+ Old->getNamingClass()));
+ if (!NamingClass)
+ return ExprError();
+
+ R.setNamingClass(NamingClass);
+ }
+
+ // If we have no template arguments, it's a normal declaration name.
+ if (!Old->hasExplicitTemplateArgs())
+ return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+
+ // If we have template arguments, rebuild them, then rebuild the
+ // templateid expression.
+ TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
+ Old->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+
+ return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(),
+ TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
+ if (!T)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getQueriedTypeSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildUnaryTypeTrait(E->getTrait(),
+ E->getLocStart(),
+ T,
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo());
+ if (!LhsT)
+ return ExprError();
+
+ TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo());
+ if (!RhsT)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
+ E->getLocStart(),
+ LhsT, RhsT,
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *E) {
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!NNS)
+ return ExprError();
+
+ // TODO: If this is a conversion-function-id, verify that the
+ // destination type name (if present) resolves the same way after
+ // instantiation as it did in the local scope.
+
+ DeclarationNameInfo NameInfo
+ = getDerived().TransformDeclarationNameInfo(E->getNameInfo());
+ if (!NameInfo.getName())
+ return ExprError();
+
+ if (!E->hasExplicitTemplateArgs()) {
+ if (!getDerived().AlwaysRebuild() &&
+ NNS == E->getQualifier() &&
+ // Note: it is sufficient to compare the Name component of NameInfo:
+ // if name has not changed, DNLoc has not changed either.
+ NameInfo.getName() == E->getDeclName())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+ E->getQualifierRange(),
+ NameInfo,
+ /*TemplateArgs*/ 0);
+ }
+
+ TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+ E->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+
+ return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
+ E->getQualifierRange(),
+ NameInfo,
+ &TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
+ // CXXConstructExprs are always implicit, so when we have a
+ // 1-argument construction we just transform that argument.
+ if (E->getNumArgs() == 1 ||
+ (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1))))
+ return getDerived().TransformExpr(E->getArg(0));
+
+ TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
+
+ QualType T = getDerived().TransformType(E->getType());
+ if (T.isNull())
+ return ExprError();
+
+ CXXConstructorDecl *Constructor
+ = cast_or_null<CXXConstructorDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getConstructor()));
+ if (!Constructor)
+ return ExprError();
+
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getType() &&
+ Constructor == E->getConstructor() &&
+ !ArgumentChanged) {
+ // Mark the constructor as referenced.
+ // FIXME: Instantiation-specific
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
+ Constructor, E->isElidable(),
+ move_arg(Args),
+ E->requiresZeroInitialization(),
+ E->getConstructionKind(),
+ E->getParenRange());
+}
+
+/// \brief Transform a C++ temporary-binding expression.
+///
+/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ return getDerived().TransformExpr(E->getSubExpr());
+}
+
+/// \brief Transform a C++ expression that contains cleanups that should
+/// be run after the expression is evaluated.
+///
+/// Since ExprWithCleanups nodes are implicitly generated, we
+/// just transform the subexpression and return that.
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformExprWithCleanups(ExprWithCleanups *E) {
+ return getDerived().TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
+ CXXTemporaryObjectExpr *E) {
+ TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+ if (!T)
+ return ExprError();
+
+ CXXConstructorDecl *Constructor
+ = cast_or_null<CXXConstructorDecl>(
+ getDerived().TransformDecl(E->getLocStart(),
+ E->getConstructor()));
+ if (!Constructor)
+ return ExprError();
+
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ Args.reserve(E->getNumArgs());
+ if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getTypeSourceInfo() &&
+ Constructor == E->getConstructor() &&
+ !ArgumentChanged) {
+ // FIXME: Instantiation-specific
+ SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ return SemaRef.MaybeBindToTemporary(E);
+ }
+
+ return getDerived().RebuildCXXTemporaryObjectExpr(T,
+ /*FIXME:*/T->getTypeLoc().getEndLoc(),
+ move_arg(Args),
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
+ CXXUnresolvedConstructExpr *E) {
+ TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo());
+ if (!T)
+ return ExprError();
+
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ Args.reserve(E->arg_size());
+ if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args,
+ &ArgumentChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T == E->getTypeSourceInfo() &&
+ !ArgumentChanged)
+ return SemaRef.Owned(E);
+
+ // FIXME: we're faking the locations of the commas
+ return getDerived().RebuildCXXUnresolvedConstructExpr(T,
+ E->getLParenLoc(),
+ move_arg(Args),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
+ // Transform the base of the expression.
+ ExprResult Base((Expr*) 0);
+ Expr *OldBase;
+ QualType BaseType;
+ QualType ObjectType;
+ if (!E->isImplicitAccess()) {
+ OldBase = E->getBase();
+ Base = getDerived().TransformExpr(OldBase);
+ if (Base.isInvalid())
+ return ExprError();
+
+ // Start the member reference and compute the object's type.
+ ParsedType ObjectTy;
+ bool MayBePseudoDestructor = false;
+ Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
+ E->getOperatorLoc(),
+ E->isArrow()? tok::arrow : tok::period,
+ ObjectTy,
+ MayBePseudoDestructor);
+ if (Base.isInvalid())
+ return ExprError();
+
+ ObjectType = ObjectTy.get();
+ BaseType = ((Expr*) Base.get())->getType();
+ } else {
+ OldBase = 0;
+ BaseType = getDerived().TransformType(E->getBaseType());
+ ObjectType = BaseType->getAs<PointerType>()->getPointeeType();
+ }
+
+ // Transform the first part of the nested-name-specifier that qualifies
+ // the member name.
+ NamedDecl *FirstQualifierInScope
+ = getDerived().TransformFirstQualifierInScope(
+ E->getFirstQualifierFoundInScope(),
+ E->getQualifierRange().getBegin());
+
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange(),
+ ObjectType,
+ FirstQualifierInScope);
+ if (!Qualifier)
+ return ExprError();
+ }
+
+ // TODO: If this is a conversion-function-id, verify that the
+ // destination type name (if present) resolves the same way after
+ // instantiation as it did in the local scope.
+
+ DeclarationNameInfo NameInfo
+ = getDerived().TransformDeclarationNameInfo(E->getMemberNameInfo());
+ if (!NameInfo.getName())
+ return ExprError();
+
+ if (!E->hasExplicitTemplateArgs()) {
+ // This is a reference to a member without an explicitly-specified
+ // template argument list. Optimize for this common case.
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == OldBase &&
+ BaseType == E->getBaseType() &&
+ Qualifier == E->getQualifier() &&
+ NameInfo.getName() == E->getMember() &&
+ FirstQualifierInScope == E->getFirstQualifierFoundInScope())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
+ BaseType,
+ E->isArrow(),
+ E->getOperatorLoc(),
+ Qualifier,
+ E->getQualifierRange(),
+ FirstQualifierInScope,
+ NameInfo,
+ /*TemplateArgs*/ 0);
+ }
+
+ TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
+ E->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+
+ return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
+ BaseType,
+ E->isArrow(),
+ E->getOperatorLoc(),
+ Qualifier,
+ E->getQualifierRange(),
+ FirstQualifierInScope,
+ NameInfo,
+ &TransArgs);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
+ // Transform the base of the expression.
+ ExprResult Base((Expr*) 0);
+ QualType BaseType;
+ if (!Old->isImplicitAccess()) {
+ Base = getDerived().TransformExpr(Old->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+ BaseType = ((Expr*) Base.get())->getType();
+ } else {
+ BaseType = getDerived().TransformType(Old->getBaseType());
+ }
+
+ NestedNameSpecifier *Qualifier = 0;
+ if (Old->getQualifier()) {
+ Qualifier
+ = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
+ Old->getQualifierRange());
+ if (Qualifier == 0)
+ return ExprError();
+ }
+
+ LookupResult R(SemaRef, Old->getMemberNameInfo(),
+ Sema::LookupOrdinaryName);
+
+ // Transform all the decls.
+ for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
+ E = Old->decls_end(); I != E; ++I) {
+ NamedDecl *InstD = static_cast<NamedDecl*>(
+ getDerived().TransformDecl(Old->getMemberLoc(),
+ *I));
+ if (!InstD) {
+ // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+ // This can happen because of dependent hiding.
+ if (isa<UsingShadowDecl>(*I))
+ continue;
+ else
+ return ExprError();
+ }
+
+ // Expand using declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+ for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+ E = UD->shadow_end(); I != E; ++I)
+ R.addDecl(*I);
+ continue;
+ }
+
+ R.addDecl(InstD);
+ }
+
+ R.resolveKind();
+
+ // Determine the naming class.
+ if (Old->getNamingClass()) {
+ CXXRecordDecl *NamingClass
+ = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+ Old->getMemberLoc(),
+ Old->getNamingClass()));
+ if (!NamingClass)
+ return ExprError();
+
+ R.setNamingClass(NamingClass);
+ }
+
+ TemplateArgumentListInfo TransArgs;
+ if (Old->hasExplicitTemplateArgs()) {
+ TransArgs.setLAngleLoc(Old->getLAngleLoc());
+ TransArgs.setRAngleLoc(Old->getRAngleLoc());
+ if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
+ Old->getNumTemplateArgs(),
+ TransArgs))
+ return ExprError();
+ }
+
+ // FIXME: to do this check properly, we will need to preserve the
+ // first-qualifier-in-scope here, just in case we had a dependent
+ // base (and therefore couldn't do the check) and a
+ // nested-name-qualifier (and therefore could do the lookup).
+ NamedDecl *FirstQualifierInScope = 0;
+
+ return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
+ BaseType,
+ Old->getOperatorLoc(),
+ Old->isArrow(),
+ Qualifier,
+ Old->getQualifierRange(),
+ FirstQualifierInScope,
+ R,
+ (Old->hasExplicitTemplateArgs()
+ ? &TransArgs : 0));
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ ExprResult SubExpr = getDerived().TransformExpr(E->getOperand());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getOperand())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildCXXNoexceptExpr(E->getSourceRange(),SubExpr.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) {
+ ExprResult Pattern = getDerived().TransformExpr(E->getPattern());
+ if (Pattern.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && Pattern.get() == E->getPattern())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildPackExpansion(Pattern.get(), E->getEllipsisLoc(),
+ E->getNumExpansions());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
+ // If E is not value-dependent, then nothing will change when we transform it.
+ // Note: This is an instantiation-centric view.
+ if (!E->isValueDependent())
+ return SemaRef.Owned(E);
+
+ // Note: None of the implementations of TryExpandParameterPacks can ever
+ // produce a diagnostic when given only a single unexpanded parameter pack,
+ // so
+ UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions;
+ if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
+ &Unexpanded, 1,
+ ShouldExpand, RetainExpansion,
+ NumExpansions))
+ return ExprError();
+
+ if (!ShouldExpand || RetainExpansion)
+ return SemaRef.Owned(E);
+
+ // We now know the length of the parameter pack, so build a new expression
+ // that stores that length.
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
+ E->getPackLoc(), E->getRParenLoc(),
+ *NumExpansions);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ // Default behavior is to do nothing with this transformation.
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
+ TypeSourceInfo *EncodedTypeInfo
+ = getDerived().TransformType(E->getEncodedTypeSourceInfo());
+ if (!EncodedTypeInfo)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ EncodedTypeInfo == E->getEncodedTypeSourceInfo())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(),
+ EncodedTypeInfo,
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
+ // Transform arguments.
+ bool ArgChanged = false;
+ ASTOwningVector<Expr*> Args(SemaRef);
+ Args.reserve(E->getNumArgs());
+ if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), false, Args,
+ &ArgChanged))
+ return ExprError();
+
+ if (E->getReceiverKind() == ObjCMessageExpr::Class) {
+ // Class message: transform the receiver type.
+ TypeSourceInfo *ReceiverTypeInfo
+ = getDerived().TransformType(E->getClassReceiverTypeInfo());
+ if (!ReceiverTypeInfo)
+ return ExprError();
+
+ // If nothing changed, just retain the existing message send.
+ if (!getDerived().AlwaysRebuild() &&
+ ReceiverTypeInfo == E->getClassReceiverTypeInfo() && !ArgChanged)
+ return SemaRef.Owned(E);
+
+ // Build a new class message send.
+ return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo,
+ E->getSelector(),
+ E->getSelectorLoc(),
+ E->getMethodDecl(),
+ E->getLeftLoc(),
+ move_arg(Args),
+ E->getRightLoc());
+ }
+
+ // Instance message: transform the receiver
+ assert(E->getReceiverKind() == ObjCMessageExpr::Instance &&
+ "Only class and instance messages may be instantiated");
+ ExprResult Receiver
+ = getDerived().TransformExpr(E->getInstanceReceiver());
+ if (Receiver.isInvalid())
+ return ExprError();
+
+ // If nothing changed, just retain the existing message send.
+ if (!getDerived().AlwaysRebuild() &&
+ Receiver.get() == E->getInstanceReceiver() && !ArgChanged)
+ return SemaRef.Owned(E);
+
+ // Build a new instance message send.
+ return getDerived().RebuildObjCMessageExpr(Receiver.get(),
+ E->getSelector(),
+ E->getSelectorLoc(),
+ E->getMethodDecl(),
+ E->getLeftLoc(),
+ move_arg(Args),
+ E->getRightLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ // Transform the base expression.
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ // We don't need to transform the ivar; it will never change.
+
+ // If nothing changed, just retain the existing expression.
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(),
+ E->getLocation(),
+ E->isArrow(), E->isFreeIvar());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ // 'super' and types never change. Property never changes. Just
+ // retain the existing expression.
+ if (!E->isObjectReceiver())
+ return SemaRef.Owned(E);
+
+ // Transform the base expression.
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ // We don't need to transform the property; it will never change.
+
+ // If nothing changed, just retain the existing expression.
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase())
+ return SemaRef.Owned(E);
+
+ if (E->isExplicitProperty())
+ return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
+ E->getExplicitProperty(),
+ E->getLocation());
+
+ return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
+ E->getType(),
+ E->getImplicitPropertyGetter(),
+ E->getImplicitPropertySetter(),
+ E->getLocation());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
+ // Transform the base expression.
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ // If nothing changed, just retain the existing expression.
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase())
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(),
+ E->isArrow());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
+ bool ArgumentChanged = false;
+ ASTOwningVector<Expr*> SubExprs(SemaRef);
+ SubExprs.reserve(E->getNumSubExprs());
+ if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false,
+ SubExprs, &ArgumentChanged))
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ !ArgumentChanged)
+ return SemaRef.Owned(E);
+
+ return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(),
+ move_arg(SubExprs),
+ E->getRParenLoc());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
+ BlockDecl *oldBlock = E->getBlockDecl();
+
+ SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0);
+ BlockScopeInfo *blockScope = SemaRef.getCurBlock();
+
+ blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic());
+ llvm::SmallVector<ParmVarDecl*, 4> params;
+ llvm::SmallVector<QualType, 4> paramTypes;
+
+ // Parameter substitution.
+ if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(),
+ oldBlock->param_begin(),
+ oldBlock->param_size(),
+ 0, paramTypes, &params))
+ return true;
+
+ const FunctionType *exprFunctionType = E->getFunctionType();
+ QualType exprResultType = exprFunctionType->getResultType();
+ if (!exprResultType.isNull()) {
+ if (!exprResultType->isDependentType())
+ blockScope->ReturnType = exprResultType;
+ else if (exprResultType != getSema().Context.DependentTy)
+ blockScope->ReturnType = getDerived().TransformType(exprResultType);
+ }
+
+ // If the return type has not been determined yet, leave it as a dependent
+ // type; it'll get set when we process the body.
+ if (blockScope->ReturnType.isNull())
+ blockScope->ReturnType = getSema().Context.DependentTy;
+
+ // Don't allow returning a objc interface by value.
+ if (blockScope->ReturnType->isObjCObjectType()) {
+ getSema().Diag(E->getCaretLocation(),
+ diag::err_object_cannot_be_passed_returned_by_value)
+ << 0 << blockScope->ReturnType;
+ return ExprError();
+ }
+
+ QualType functionType = getDerived().RebuildFunctionProtoType(
+ blockScope->ReturnType,
+ paramTypes.data(),
+ paramTypes.size(),
+ oldBlock->isVariadic(),
+ 0, RQ_None,
+ exprFunctionType->getExtInfo());
+ blockScope->FunctionType = functionType;
+
+ // Set the parameters on the block decl.
+ if (!params.empty())
+ blockScope->TheDecl->setParams(params.data(), params.size());
+
+ // If the return type wasn't explicitly set, it will have been marked as a
+ // dependent type (DependentTy); clear out the return type setting so
+ // we will deduce the return type when type-checking the block's body.
+ if (blockScope->ReturnType == getSema().Context.DependentTy)
+ blockScope->ReturnType = QualType();
+
+ // Transform the body
+ StmtResult body = getDerived().TransformStmt(E->getBody());
+ if (body.isInvalid())
+ return ExprError();
+
+#ifndef NDEBUG
+ // In builds with assertions, make sure that we captured everything we
+ // captured before.
+
+ if (oldBlock->capturesCXXThis()) assert(blockScope->CapturesCXXThis);
+
+ for (BlockDecl::capture_iterator i = oldBlock->capture_begin(),
+ e = oldBlock->capture_end(); i != e; ++i) {
+ VarDecl *oldCapture = i->getVariable();
+
+ // Ignore parameter packs.
+ if (isa<ParmVarDecl>(oldCapture) &&
+ cast<ParmVarDecl>(oldCapture)->isParameterPack())
+ continue;
+
+ VarDecl *newCapture =
+ cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(),
+ oldCapture));
+ assert(blockScope->CaptureMap.count(newCapture));
+ }
+#endif
+
+ return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(),
+ /*Scope=*/0);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ NestedNameSpecifier *Qualifier = 0;
+
+ ValueDecl *ND
+ = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
+ E->getDecl()));
+ if (!ND)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ ND == E->getDecl()) {
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+
+ return SemaRef.Owned(E);
+ }
+
+ DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation());
+ return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(),
+ ND, NameInfo, 0);
+}
+
+//===----------------------------------------------------------------------===//
+// Type reconstruction
+//===----------------------------------------------------------------------===//
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildPointerType(PointeeType, Star,
+ getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
+ SourceLocation Star) {
+ return SemaRef.BuildBlockPointerType(PointeeType, Star,
+ getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
+ bool WrittenAsLValue,
+ SourceLocation Sigil) {
+ return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue,
+ Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+ QualType ClassType,
+ SourceLocation Sigil) {
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
+ Sigil, getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ const llvm::APInt *Size,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
+ if (SizeExpr || !Size)
+ return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
+ IndexTypeQuals, BracketsRange,
+ getDerived().getBaseEntity());
+
+ QualType Types[] = {
+ SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
+ SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
+ SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
+ };
+ const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
+ QualType SizeType;
+ for (unsigned I = 0; I != NumTypes; ++I)
+ if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
+ SizeType = Types[I];
+ break;
+ }
+
+ IntegerLiteral ArraySize(SemaRef.Context, *Size, SizeType,
+ /*FIXME*/BracketsRange.getBegin());
+ return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
+ IndexTypeQuals, BracketsRange,
+ getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ const llvm::APInt &Size,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
+ return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
+ IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
+ return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
+ IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
+ return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ SizeExpr,
+ IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
+ ArrayType::ArraySizeModifier SizeMod,
+ Expr *SizeExpr,
+ unsigned IndexTypeQuals,
+ SourceRange BracketsRange) {
+ return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
+ SizeExpr,
+ IndexTypeQuals, BracketsRange);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
+ unsigned NumElements,
+ VectorType::VectorKind VecKind) {
+ // FIXME: semantic checking!
+ return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
+ unsigned NumElements,
+ SourceLocation AttributeLoc) {
+ llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
+ NumElements, true);
+ IntegerLiteral *VectorSize
+ = IntegerLiteral::Create(SemaRef.Context, numElements, SemaRef.Context.IntTy,
+ AttributeLoc);
+ return SemaRef.BuildExtVectorType(ElementType, VectorSize, AttributeLoc);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
+ Expr *SizeExpr,
+ SourceLocation AttributeLoc) {
+ return SemaRef.BuildExtVectorType(ElementType, SizeExpr, AttributeLoc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
+ QualType *ParamTypes,
+ unsigned NumParamTypes,
+ bool Variadic,
+ unsigned Quals,
+ RefQualifierKind RefQualifier,
+ const FunctionType::ExtInfo &Info) {
+ return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
+ Quals, RefQualifier,
+ getDerived().getBaseLocation(),
+ getDerived().getBaseEntity(),
+ Info);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
+ return SemaRef.Context.getFunctionNoProtoType(T);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+ assert(D && "no decl found");
+ if (D->isInvalidDecl()) return QualType();
+
+ // FIXME: Doesn't account for ObjCInterfaceDecl!
+ TypeDecl *Ty;
+ if (isa<UsingDecl>(D)) {
+ UsingDecl *Using = cast<UsingDecl>(D);
+ assert(Using->isTypeName() &&
+ "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+ // A valid resolved using typename decl points to exactly one type decl.
+ assert(++Using->shadow_begin() == Using->shadow_end());
+ Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+
+ } else {
+ assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+ "UnresolvedUsingTypenameDecl transformed to non-using decl");
+ Ty = cast<UnresolvedUsingTypenameDecl>(D);
+ }
+
+ return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
+ SourceLocation Loc) {
+ return SemaRef.BuildTypeofExprType(E, Loc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
+ return SemaRef.Context.getTypeOfType(Underlying);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
+ SourceLocation Loc) {
+ return SemaRef.BuildDecltypeType(E, Loc);
+}
+
+template<typename Derived>
+QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
+ TemplateName Template,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs) {
+ return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ CXXScopeSpec SS;
+ // FIXME: The source location information is all wrong.
+ SS.setRange(Range);
+ SS.setScopeRep(Prefix);
+ return static_cast<NestedNameSpecifier *>(
+ SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
+ Range.getEnd(), II,
+ ObjectType,
+ FirstQualifierInScope,
+ false, false));
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ NamespaceDecl *NS) {
+ return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ bool TemplateKW,
+ QualType T) {
+ if (T->isDependentType() || T->isRecordType() ||
+ (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
+ assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here");
+ return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
+ T.getTypePtr());
+ }
+
+ SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
+ return 0;
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ bool TemplateKW,
+ TemplateDecl *Template) {
+ return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW,
+ Template);
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ const IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ UnqualifiedId Name;
+ Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
+ Sema::TemplateTy Template;
+ getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ /*FIXME:*/getDerived().getBaseLocation(),
+ SS,
+ Name,
+ ParsedType::make(ObjectType),
+ /*EnteringContext=*/false,
+ Template);
+ return Template.get();
+}
+
+template<typename Derived>
+TemplateName
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+ OverloadedOperatorKind Operator,
+ QualType ObjectType) {
+ CXXScopeSpec SS;
+ SS.setRange(SourceRange(getDerived().getBaseLocation()));
+ SS.setScopeRep(Qualifier);
+ UnqualifiedId Name;
+ SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
+ Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
+ Operator, SymbolLocations);
+ Sema::TemplateTy Template;
+ getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ /*FIXME:*/getDerived().getBaseLocation(),
+ SS,
+ Name,
+ ParsedType::make(ObjectType),
+ /*EnteringContext=*/false,
+ Template);
+ return Template.template getAsVal<TemplateName>();
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr *OrigCallee,
+ Expr *First,
+ Expr *Second) {
+ Expr *Callee = OrigCallee->IgnoreParenCasts();
+ bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+
+ // Determine whether this should be a builtin operation.
+ if (Op == OO_Subscript) {
+ if (!First->getType()->isOverloadableType() &&
+ !Second->getType()->isOverloadableType())
+ return getSema().CreateBuiltinArraySubscriptExpr(First,
+ Callee->getLocStart(),
+ Second, OpLoc);
+ } else if (Op == OO_Arrow) {
+ // -> is never a builtin operation.
+ return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc);
+ } else if (Second == 0 || isPostIncDec) {
+ if (!First->getType()->isOverloadableType()) {
+ // The argument is not of overloadable type, so try to create a
+ // built-in unary operation.
+ UnaryOperatorKind Opc
+ = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+
+ return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
+ }
+ } else {
+ if (!First->getType()->isOverloadableType() &&
+ !Second->getType()->isOverloadableType()) {
+ // Neither of the arguments is an overloadable type, so try to
+ // create a built-in binary operation.
+ BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+ ExprResult Result
+ = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return move(Result);
+ }
+ }
+
+ // Compute the transformed set of functions (and function templates) to be
+ // used during overload resolution.
+ UnresolvedSet<16> Functions;
+
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
+ assert(ULE->requiresADL());
+
+ // FIXME: Do we have to check
+ // IsAcceptableNonMemberOperatorCandidate for each of these?
+ Functions.append(ULE->decls_begin(), ULE->decls_end());
+ } else {
+ Functions.addDecl(cast<DeclRefExpr>(Callee)->getDecl());
+ }
+
+ // Add any functions found via argument-dependent lookup.
+ Expr *Args[2] = { First, Second };
+ unsigned NumArgs = 1 + (Second != 0);
+
+ // Create the overloaded operator invocation for unary operators.
+ if (NumArgs == 1 || isPostIncDec) {
+ UnaryOperatorKind Opc
+ = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
+ return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First);
+ }
+
+ if (Op == OO_Subscript)
+ return SemaRef.CreateOverloadedArraySubscriptExpr(Callee->getLocStart(),
+ OpLoc,
+ First,
+ Second);
+
+ // Create the overloaded operator invocation for binary operators.
+ BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+ ExprResult Result
+ = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return move(Result);
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
+ SourceLocation OperatorLoc,
+ bool isArrow,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage Destroyed) {
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ }
+
+ QualType BaseType = Base->getType();
+ if (Base->isTypeDependent() || Destroyed.getIdentifier() ||
+ (!isArrow && !BaseType->getAs<RecordType>()) ||
+ (isArrow && BaseType->getAs<PointerType>() &&
+ !BaseType->getAs<PointerType>()->getPointeeType()
+ ->template getAs<RecordType>())){
+ // This pseudo-destructor expression is still a pseudo-destructor.
+ return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc,
+ isArrow? tok::arrow : tok::period,
+ SS, ScopeType, CCLoc, TildeLoc,
+ Destroyed,
+ /*FIXME?*/true);
+ }
+
+ TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
+ DeclarationName Name(SemaRef.Context.DeclarationNames.getCXXDestructorName(
+ SemaRef.Context.getCanonicalType(DestroyedType->getType())));
+ DeclarationNameInfo NameInfo(Name, Destroyed.getLocation());
+ NameInfo.setNamedTypeInfo(DestroyedType);
+
+ // FIXME: the ScopeType should be tacked onto SS.
+
+ return getSema().BuildMemberReferenceExpr(Base, BaseType,
+ OperatorLoc, isArrow,
+ SS, /*FIXME: FirstQualifier*/ 0,
+ NameInfo,
+ /*TemplateArgs*/ 0);
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
new file mode 100644
index 0000000..3d20a52
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -0,0 +1,180 @@
+//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines TypeLocBuilder, a class for building TypeLocs
+// bottom-up.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
+#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
+
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+class TypeLocBuilder {
+ enum { InlineCapacity = 8 * sizeof(SourceLocation) };
+
+ /// The underlying location-data buffer. Data grows from the end
+ /// of the buffer backwards.
+ char *Buffer;
+
+ /// The capacity of the current buffer.
+ size_t Capacity;
+
+ /// The index of the first occupied byte in the buffer.
+ size_t Index;
+
+#ifndef NDEBUG
+ /// The last type pushed on this builder.
+ QualType LastTy;
+#endif
+
+ /// The inline buffer.
+ char InlineBuffer[InlineCapacity];
+
+ public:
+ TypeLocBuilder()
+ : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
+ {}
+
+ ~TypeLocBuilder() {
+ if (Buffer != InlineBuffer)
+ delete[] Buffer;
+ }
+
+ /// Ensures that this buffer has at least as much capacity as described.
+ void reserve(size_t Requested) {
+ if (Requested > Capacity)
+ // For now, match the request exactly.
+ grow(Requested);
+ }
+
+ /// Pushes a copy of the given TypeLoc onto this builder. The builder
+ /// must be empty for this to work.
+ void pushFullCopy(TypeLoc L) {
+ size_t Size = L.getFullDataSize();
+ TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
+ memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
+ }
+
+ /// Pushes uninitialized space for the given type. The builder must
+ /// be empty.
+ TypeLoc pushFullUninitialized(QualType T) {
+ return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
+ }
+
+ /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
+ /// previously retrieved from this builder.
+ TypeSpecTypeLoc pushTypeSpec(QualType T) {
+ size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
+ return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
+ }
+
+ /// Resets this builder to the newly-initialized state.
+ void clear() {
+#ifndef NDEBUG
+ LastTy = QualType();
+#endif
+ Index = Capacity;
+ }
+
+ /// Pushes space for a new TypeLoc of the given type. Invalidates
+ /// any TypeLocs previously retrieved from this builder.
+ template <class TyLocType> TyLocType push(QualType T) {
+ size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
+ return cast<TyLocType>(pushImpl(T, LocalSize));
+ }
+
+ /// Creates a TypeSourceInfo for the given type.
+ TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
+#ifndef NDEBUG
+ assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+ size_t FullDataSize = Capacity - Index;
+ TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
+ memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
+ return DI;
+ }
+
+private:
+ TypeLoc pushImpl(QualType T, size_t LocalSize) {
+#ifndef NDEBUG
+ QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
+ assert(TLast == LastTy &&
+ "mismatch between last type and new type's inner type");
+ LastTy = T;
+#endif
+
+ // If we need to grow, grow by a factor of 2.
+ if (LocalSize > Index) {
+ size_t RequiredCapacity = Capacity + (LocalSize - Index);
+ size_t NewCapacity = Capacity * 2;
+ while (RequiredCapacity > NewCapacity)
+ NewCapacity *= 2;
+ grow(NewCapacity);
+ }
+
+ Index -= LocalSize;
+
+ return getTypeLoc(T);
+ }
+
+ /// Grow to the given capacity.
+ void grow(size_t NewCapacity) {
+ assert(NewCapacity > Capacity);
+
+ // Allocate the new buffer and copy the old data into it.
+ char *NewBuffer = new char[NewCapacity];
+ unsigned NewIndex = Index + NewCapacity - Capacity;
+ memcpy(&NewBuffer[NewIndex],
+ &Buffer[Index],
+ Capacity - Index);
+
+ if (Buffer != InlineBuffer)
+ delete[] Buffer;
+
+ Buffer = NewBuffer;
+ Capacity = NewCapacity;
+ Index = NewIndex;
+ }
+
+ TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
+#ifndef NDEBUG
+ assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
+ LastTy = T;
+#endif
+ assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
+
+ reserve(Size);
+ Index -= Size;
+
+ return getTypeLoc(T);
+ }
+
+
+ // This is private because, when we kill off TypeSourceInfo in favor
+ // of TypeLoc, we'll want an interface that creates a TypeLoc given
+ // an ASTContext, and we don't want people to think they can just
+ // use this as an equivalent.
+ TypeLoc getTypeLoc(QualType T) {
+#ifndef NDEBUG
+ assert(LastTy == T && "type doesn't match last type pushed!");
+#endif
+ return TypeLoc(T, &Buffer[Index]);
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
new file mode 100644
index 0000000..5e94f59
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -0,0 +1,71 @@
+//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTCommon.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+
+// Give ASTDeserializationListener's VTable a home.
+ASTDeserializationListener::~ASTDeserializationListener() { }
+
+serialization::TypeIdx
+serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
+ unsigned ID = 0;
+ switch (BT->getKind()) {
+ case BuiltinType::Void: ID = PREDEF_TYPE_VOID_ID; break;
+ case BuiltinType::Bool: ID = PREDEF_TYPE_BOOL_ID; break;
+ case BuiltinType::Char_U: ID = PREDEF_TYPE_CHAR_U_ID; break;
+ case BuiltinType::UChar: ID = PREDEF_TYPE_UCHAR_ID; break;
+ case BuiltinType::UShort: ID = PREDEF_TYPE_USHORT_ID; break;
+ case BuiltinType::UInt: ID = PREDEF_TYPE_UINT_ID; break;
+ case BuiltinType::ULong: ID = PREDEF_TYPE_ULONG_ID; break;
+ case BuiltinType::ULongLong: ID = PREDEF_TYPE_ULONGLONG_ID; break;
+ case BuiltinType::UInt128: ID = PREDEF_TYPE_UINT128_ID; break;
+ case BuiltinType::Char_S: ID = PREDEF_TYPE_CHAR_S_ID; break;
+ case BuiltinType::SChar: ID = PREDEF_TYPE_SCHAR_ID; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: ID = PREDEF_TYPE_WCHAR_ID; break;
+ case BuiltinType::Short: ID = PREDEF_TYPE_SHORT_ID; break;
+ case BuiltinType::Int: ID = PREDEF_TYPE_INT_ID; break;
+ case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;
+ case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;
+ case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;
+ case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;
+ case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;
+ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
+ case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break;
+ case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break;
+ case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;
+ case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;
+ case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;
+ case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break;
+ case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break;
+ case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break;
+ }
+
+ return TypeIdx(ID);
+}
+
+unsigned serialization::ComputeHash(Selector Sel) {
+ unsigned N = Sel.getNumArgs();
+ if (N == 0)
+ ++N;
+ unsigned R = 5381;
+ for (unsigned I = 0; I != N; ++I)
+ if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+ R = llvm::HashString(II->getName(), R);
+ return R;
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
new file mode 100644
index 0000000..d416699
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
@@ -0,0 +1,56 @@
+//===- ASTCommon.h - Common stuff for ASTReader/ASTWriter -*- C++ -*-=========//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
+#define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+namespace serialization {
+
+enum DeclUpdateKind {
+ UPD_CXX_SET_DEFINITIONDATA,
+ UPD_CXX_ADDED_IMPLICIT_MEMBER,
+ UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION
+};
+
+TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
+
+template <typename IdxForTypeTy>
+TypeID MakeTypeID(QualType T, IdxForTypeTy IdxForType) {
+ if (T.isNull())
+ return PREDEF_TYPE_NULL_ID;
+
+ unsigned FastQuals = T.getLocalFastQualifiers();
+ T.removeLocalFastQualifiers();
+
+ if (T.hasLocalNonFastQualifiers())
+ return IdxForType(T).asTypeID(FastQuals);
+
+ assert(!T.hasLocalQualifiers());
+
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
+ return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);
+
+ return IdxForType(T).asTypeID(FastQuals);
+}
+
+unsigned ComputeHash(Selector Sel);
+
+} // namespace serialization
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
new file mode 100644
index 0000000..ce87b11
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -0,0 +1,4935 @@
+//===--- ASTReader.cpp - AST File Reader ------------------------*- 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 ASTReader class, which reads AST files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "ASTCommon.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <iterator>
+#include <cstdio>
+#include <sys/stat.h>
+
+using namespace clang;
+using namespace clang::serialization;
+
+//===----------------------------------------------------------------------===//
+// PCH validator implementation
+//===----------------------------------------------------------------------===//
+
+ASTReaderListener::~ASTReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+ const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
+ if (PPLangOpts.Option != LangOpts.Option) { \
+ Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
+ return true; \
+ }
+
+ PARSE_LANGOPT_BENIGN(Trigraphs);
+ PARSE_LANGOPT_BENIGN(BCPLComment);
+ PARSE_LANGOPT_BENIGN(DollarIdents);
+ PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+ PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+ PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords);
+ PARSE_LANGOPT_BENIGN(ImplicitInt);
+ PARSE_LANGOPT_BENIGN(Digraphs);
+ PARSE_LANGOPT_BENIGN(HexFloats);
+ PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+ PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+ PARSE_LANGOPT_BENIGN(MSCVersion);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+ PARSE_LANGOPT_BENIGN(CXXOperatorName);
+ PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+ PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+ PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+ PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2);
+ PARSE_LANGOPT_IMPORTANT(AppleKext, diag::warn_pch_apple_kext);
+ PARSE_LANGOPT_IMPORTANT(ObjCDefaultSynthProperties,
+ diag::warn_pch_objc_auto_properties);
+ PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings,
+ diag::warn_pch_no_constant_cfstrings);
+ PARSE_LANGOPT_BENIGN(PascalStrings);
+ PARSE_LANGOPT_BENIGN(WritableStrings);
+ PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
+ diag::warn_pch_lax_vector_conversions);
+ PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
+ PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+ PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions);
+ PARSE_LANGOPT_IMPORTANT(ObjCExceptions, diag::warn_pch_objc_exceptions);
+ PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields);
+ PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+ PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+ PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+ PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
+ diag::warn_pch_thread_safe_statics);
+ PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads);
+ PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+ PARSE_LANGOPT_BENIGN(EmitAllDecls);
+ PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+ PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior());
+ PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
+ diag::warn_pch_heinous_extensions);
+ // FIXME: Most of the options below are benign if the macro wasn't
+ // used. Unfortunately, this means that a PCH compiled without
+ // optimization can't be used with optimization turned on, even
+ // though the only thing that changes is whether __OPTIMIZE__ was
+ // defined... but if __OPTIMIZE__ never showed up in the header, it
+ // doesn't matter. We could consider making this some special kind
+ // of check.
+ PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+ PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+ PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+ PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+ PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+ PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
+ PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
+ PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
+ PARSE_LANGOPT_IMPORTANT(ShortEnums, diag::warn_pch_short_enums);
+ if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+ Reader.Diag(diag::warn_pch_gc_mode)
+ << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+ return true;
+ }
+ PARSE_LANGOPT_BENIGN(getVisibilityMode());
+ PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(),
+ diag::warn_pch_stack_protector);
+ PARSE_LANGOPT_BENIGN(InstantiationDepth);
+ PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
+ PARSE_LANGOPT_IMPORTANT(CUDA, diag::warn_pch_cuda);
+ PARSE_LANGOPT_BENIGN(CatchUndefined);
+ PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
+ PARSE_LANGOPT_BENIGN(SpellChecking);
+ PARSE_LANGOPT_BENIGN(DefaultFPContract);
+#undef PARSE_LANGOPT_IMPORTANT
+#undef PARSE_LANGOPT_BENIGN
+
+ return false;
+}
+
+bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
+ if (Triple == PP.getTargetInfo().getTriple().str())
+ return false;
+
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTriple().str();
+ return true;
+}
+
+namespace {
+ struct EmptyStringRef {
+ bool operator ()(llvm::StringRef r) const { return r.empty(); }
+ };
+ struct EmptyBlock {
+ bool operator ()(const PCHPredefinesBlock &r) const {return r.Data.empty();}
+ };
+}
+
+static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L,
+ PCHPredefinesBlocks R) {
+ // First, sum up the lengths.
+ unsigned LL = 0, RL = 0;
+ for (unsigned I = 0, N = L.size(); I != N; ++I) {
+ LL += L[I].size();
+ }
+ for (unsigned I = 0, N = R.size(); I != N; ++I) {
+ RL += R[I].Data.size();
+ }
+ if (LL != RL)
+ return false;
+ if (LL == 0 && RL == 0)
+ return true;
+
+ // Kick out empty parts, they confuse the algorithm below.
+ L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end());
+ R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end());
+
+ // Do it the hard way. At this point, both vectors must be non-empty.
+ llvm::StringRef LR = L[0], RR = R[0].Data;
+ unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size();
+ (void) RN;
+ for (;;) {
+ // Compare the current pieces.
+ if (LR.size() == RR.size()) {
+ // If they're the same length, it's pretty easy.
+ if (LR != RR)
+ return false;
+ // Both pieces are done, advance.
+ ++LI;
+ ++RI;
+ // If either string is done, they're both done, since they're the same
+ // length.
+ if (LI == LN) {
+ assert(RI == RN && "Strings not the same length after all?");
+ return true;
+ }
+ LR = L[LI];
+ RR = R[RI].Data;
+ } else if (LR.size() < RR.size()) {
+ // Right piece is longer.
+ if (!RR.startswith(LR))
+ return false;
+ ++LI;
+ assert(LI != LN && "Strings not the same length after all?");
+ RR = RR.substr(LR.size());
+ LR = L[LI];
+ } else {
+ // Left piece is longer.
+ if (!LR.startswith(RR))
+ return false;
+ ++RI;
+ assert(RI != RN && "Strings not the same length after all?");
+ LR = LR.substr(RR.size());
+ RR = R[RI].Data;
+ }
+ }
+}
+
+static std::pair<FileID, llvm::StringRef::size_type>
+FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) {
+ std::pair<FileID, llvm::StringRef::size_type> Res;
+ for (unsigned I = 0, N = Buffers.size(); I != N; ++I) {
+ Res.second = Buffers[I].Data.find(MacroDef);
+ if (Res.second != llvm::StringRef::npos) {
+ Res.first = Buffers[I].BufferID;
+ break;
+ }
+ }
+ return Res;
+}
+
+bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
+ llvm::StringRef OriginalFileName,
+ std::string &SuggestedPredefines) {
+ // We are in the context of an implicit include, so the predefines buffer will
+ // have a #include entry for the PCH file itself (as normalized by the
+ // preprocessor initialization). Find it and skip over it in the checking
+ // below.
+ llvm::SmallString<256> PCHInclude;
+ PCHInclude += "#include \"";
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += "\"\n";
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
+ llvm::StringRef Left = Split.first, Right = Split.second;
+ if (Left == PP.getPredefines()) {
+ Error("Missing PCH include entry!");
+ return true;
+ }
+
+ // If the concatenation of all the PCH buffers is equal to the adjusted
+ // command line, we're done.
+ llvm::SmallVector<llvm::StringRef, 2> CommandLine;
+ CommandLine.push_back(Left);
+ CommandLine.push_back(Right);
+ if (EqualConcatenations(CommandLine, Buffers))
+ return false;
+
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // The predefines buffers are different. Determine what the differences are,
+ // and whether they require us to reject the PCH file.
+ llvm::SmallVector<llvm::StringRef, 8> PCHLines;
+ for (unsigned I = 0, N = Buffers.size(); I != N; ++I)
+ Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
+ Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ // Pick out implicit #includes after the PCH and don't consider them for
+ // validation; we will insert them into SuggestedPredefines so that the
+ // preprocessor includes them.
+ std::string IncludesAfterPCH;
+ llvm::SmallVector<llvm::StringRef, 8> AfterPCHLines;
+ Right.split(AfterPCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (unsigned i = 0, e = AfterPCHLines.size(); i != e; ++i) {
+ if (AfterPCHLines[i].startswith("#include ")) {
+ IncludesAfterPCH += AfterPCHLines[i];
+ IncludesAfterPCH += '\n';
+ } else {
+ CmdLineLines.push_back(AfterPCHLines[i]);
+ }
+ }
+
+ // Make sure we add the includes last into SuggestedPredefines before we
+ // exit this function.
+ struct AddIncludesRAII {
+ std::string &SuggestedPredefines;
+ std::string &IncludesAfterPCH;
+
+ AddIncludesRAII(std::string &SuggestedPredefines,
+ std::string &IncludesAfterPCH)
+ : SuggestedPredefines(SuggestedPredefines),
+ IncludesAfterPCH(IncludesAfterPCH) { }
+ ~AddIncludesRAII() {
+ SuggestedPredefines += IncludesAfterPCH;
+ }
+ } AddIncludes(SuggestedPredefines, IncludesAfterPCH);
+
+ // Sort both sets of predefined buffer lines, since we allow some extra
+ // definitions and they may appear at any point in the output.
+ std::sort(CmdLineLines.begin(), CmdLineLines.end());
+ std::sort(PCHLines.begin(), PCHLines.end());
+
+ // Determine which predefines that were used to build the PCH file are missing
+ // from the command line.
+ std::vector<llvm::StringRef> MissingPredefines;
+ std::set_difference(PCHLines.begin(), PCHLines.end(),
+ CmdLineLines.begin(), CmdLineLines.end(),
+ std::back_inserter(MissingPredefines));
+
+ bool MissingDefines = false;
+ bool ConflictingDefines = false;
+ for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
+ llvm::StringRef Missing = MissingPredefines[I];
+ if (Missing.startswith("#include ")) {
+ // An -include was specified when generating the PCH; it is included in
+ // the PCH, just ignore it.
+ continue;
+ }
+ if (!Missing.startswith("#define ")) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is a macro definition. Determine the name of the macro we're
+ // defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Missing.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
+
+ // Determine whether this macro was given a different definition on the
+ // command line.
+ std::string MacroDefStart = "#define " + MacroName.str();
+ std::string::size_type MacroDefLen = MacroDefStart.size();
+ llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
+ = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+ MacroDefStart);
+ for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+ if (!ConflictPos->startswith(MacroDefStart)) {
+ // Different macro; we're done.
+ ConflictPos = CmdLineLines.end();
+ break;
+ }
+
+ assert(ConflictPos->size() > MacroDefLen &&
+ "Invalid #define in predefines buffer?");
+ if ((*ConflictPos)[MacroDefLen] != ' ' &&
+ (*ConflictPos)[MacroDefLen] != '(')
+ continue; // Longer macro name; keep trying.
+
+ // We found a conflicting macro definition.
+ break;
+ }
+
+ if (ConflictPos != CmdLineLines.end()) {
+ Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+ << MacroName;
+
+ // Show the definition of this macro within the PCH file.
+ std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
+ FindMacro(Buffers, Missing);
+ assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc =
+ SourceMgr.getLocForStartOfFile(MacroLoc.first)
+ .getFileLocWithOffset(MacroLoc.second);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
+
+ ConflictingDefines = true;
+ continue;
+ }
+
+ // If the macro doesn't conflict, then we'll just pick up the macro
+ // definition from the PCH file. Warn the user that they made a mistake.
+ if (ConflictingDefines)
+ continue; // Don't complain if there are already conflicting defs
+
+ if (!MissingDefines) {
+ Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+ MissingDefines = true;
+ }
+
+ // Show the definition of this macro within the PCH file.
+ std::pair<FileID, llvm::StringRef::size_type> MacroLoc =
+ FindMacro(Buffers, Missing);
+ assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc =
+ SourceMgr.getLocForStartOfFile(MacroLoc.first)
+ .getFileLocWithOffset(MacroLoc.second);
+ Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
+ }
+
+ if (ConflictingDefines)
+ return true;
+
+ // Determine what predefines were introduced based on command-line
+ // parameters that were not present when building the PCH
+ // file. Extra #defines are okay, so long as the identifiers being
+ // defined were not used within the precompiled header.
+ std::vector<llvm::StringRef> ExtraPredefines;
+ std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
+ PCHLines.begin(), PCHLines.end(),
+ std::back_inserter(ExtraPredefines));
+ for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
+ llvm::StringRef &Extra = ExtraPredefines[I];
+ if (!Extra.startswith("#define ")) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is an extra macro definition. Determine the name of the
+ // macro we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Extra.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
+
+ // Check whether this name was used somewhere in the PCH file. If
+ // so, defining it as a macro could change behavior, so we reject
+ // the PCH file.
+ if (IdentifierInfo *II = Reader.get(MacroName)) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
+ return true;
+ }
+
+ // Add this definition to the suggested predefines buffer.
+ SuggestedPredefines += Extra;
+ SuggestedPredefines += '\n';
+ }
+
+ // If we get here, it's because the predefines buffer had compatible
+ // contents. Accept the PCH file.
+ return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
+ unsigned ID) {
+ PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
+ ++NumHeaderInfos;
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+ PP.setCounterValue(Value);
+}
+
+//===----------------------------------------------------------------------===//
+// AST reader implementation
+//===----------------------------------------------------------------------===//
+
+void
+ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
+ DeserializationListener = Listener;
+}
+
+
+namespace {
+class ASTSelectorLookupTrait {
+ ASTReader &Reader;
+
+public:
+ struct data_type {
+ SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
+
+ typedef Selector external_key_type;
+ typedef external_key_type internal_key_type;
+
+ explicit ASTSelectorLookupTrait(ASTReader &Reader) : Reader(Reader) { }
+
+ static bool EqualKey(const internal_key_type& a,
+ const internal_key_type& b) {
+ return a == b;
+ }
+
+ static unsigned ComputeHash(Selector Sel) {
+ return serialization::ComputeHash(Sel);
+ }
+
+ // This hopefully will just get inlined and removed by the optimizer.
+ static const internal_key_type&
+ GetInternalKey(const external_key_type& x) { return x; }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ unsigned DataLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ internal_key_type ReadKey(const unsigned char* d, unsigned) {
+ using namespace clang::io;
+ SelectorTable &SelTable = Reader.getContext()->Selectors;
+ unsigned N = ReadUnalignedLE16(d);
+ IdentifierInfo *FirstII
+ = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+ if (N == 0)
+ return SelTable.getNullarySelector(FirstII);
+ else if (N == 1)
+ return SelTable.getUnarySelector(FirstII);
+
+ llvm::SmallVector<IdentifierInfo *, 16> Args;
+ Args.push_back(FirstII);
+ for (unsigned I = 1; I != N; ++I)
+ Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
+
+ return SelTable.getSelector(N, Args.data());
+ }
+
+ data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
+ using namespace clang::io;
+
+ data_type Result;
+
+ Result.ID = ReadUnalignedLE32(d);
+ unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+ unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
+ // Load instance methods
+ ObjCMethodList *Prev = 0;
+ for (unsigned I = 0; I != NumInstanceMethods; ++I) {
+ ObjCMethodDecl *Method
+ = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
+ if (!Result.Instance.Method) {
+ // This is the first method, which is the easy case.
+ Result.Instance.Method = Method;
+ Prev = &Result.Instance;
+ continue;
+ }
+
+ ObjCMethodList *Mem =
+ Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>();
+ Prev->Next = new (Mem) ObjCMethodList(Method, 0);
+ Prev = Prev->Next;
+ }
+
+ // Load factory methods
+ Prev = 0;
+ for (unsigned I = 0; I != NumFactoryMethods; ++I) {
+ ObjCMethodDecl *Method
+ = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
+ if (!Result.Factory.Method) {
+ // This is the first method, which is the easy case.
+ Result.Factory.Method = Method;
+ Prev = &Result.Factory;
+ continue;
+ }
+
+ ObjCMethodList *Mem =
+ Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>();
+ Prev->Next = new (Mem) ObjCMethodList(Method, 0);
+ Prev = Prev->Next;
+ }
+
+ return Result;
+ }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used for the global method pool.
+typedef OnDiskChainedHashTable<ASTSelectorLookupTrait>
+ ASTSelectorLookupTable;
+
+namespace clang {
+class ASTIdentifierLookupTrait {
+ ASTReader &Reader;
+ ASTReader::PerFileData &F;
+
+ // If we know the IdentifierInfo in advance, it is here and we will
+ // not build a new one. Used when deserializing information about an
+ // identifier that was constructed before the AST file was read.
+ IdentifierInfo *KnownII;
+
+public:
+ typedef IdentifierInfo * data_type;
+
+ typedef const std::pair<const char*, unsigned> external_key_type;
+
+ typedef external_key_type internal_key_type;
+
+ ASTIdentifierLookupTrait(ASTReader &Reader, ASTReader::PerFileData &F,
+ IdentifierInfo *II = 0)
+ : Reader(Reader), F(F), KnownII(II) { }
+
+ static bool EqualKey(const internal_key_type& a,
+ const internal_key_type& b) {
+ return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
+ : false;
+ }
+
+ static unsigned ComputeHash(const internal_key_type& a) {
+ return llvm::HashString(llvm::StringRef(a.first, a.second));
+ }
+
+ // This hopefully will just get inlined and removed by the optimizer.
+ static const internal_key_type&
+ GetInternalKey(const external_key_type& x) { return x; }
+
+ // This hopefully will just get inlined and removed by the optimizer.
+ static const external_key_type&
+ GetExternalKey(const internal_key_type& x) { return x; }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned DataLen = ReadUnalignedLE16(d);
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ static std::pair<const char*, unsigned>
+ ReadKey(const unsigned char* d, unsigned n) {
+ assert(n >= 2 && d[n-1] == '\0');
+ return std::make_pair((const char*) d, n-1);
+ }
+
+ IdentifierInfo *ReadData(const internal_key_type& k,
+ const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+ IdentID ID = ReadUnalignedLE32(d);
+ bool IsInteresting = ID & 0x01;
+
+ // Wipe out the "is interesting" bit.
+ ID = ID >> 1;
+
+ if (!IsInteresting) {
+ // For uninteresting identifiers, just build the IdentifierInfo
+ // and associate it with the persistent ID.
+ IdentifierInfo *II = KnownII;
+ if (!II)
+ II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
+ Reader.SetIdentifierInfo(ID, II);
+ II->setIsFromAST();
+ return II;
+ }
+
+ unsigned Bits = ReadUnalignedLE16(d);
+ bool CPlusPlusOperatorKeyword = Bits & 0x01;
+ Bits >>= 1;
+ bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
+ Bits >>= 1;
+ bool Poisoned = Bits & 0x01;
+ Bits >>= 1;
+ bool ExtensionToken = Bits & 0x01;
+ Bits >>= 1;
+ bool hasMacroDefinition = Bits & 0x01;
+ Bits >>= 1;
+ unsigned ObjCOrBuiltinID = Bits & 0x3FF;
+ Bits >>= 10;
+
+ assert(Bits == 0 && "Extra bits in the identifier?");
+ DataLen -= 6;
+
+ // Build the IdentifierInfo itself and link the identifier ID with
+ // the new IdentifierInfo.
+ IdentifierInfo *II = KnownII;
+ if (!II)
+ II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
+ Reader.SetIdentifierInfo(ID, II);
+
+ // Set or check the various bits in the IdentifierInfo structure.
+ // Token IDs are read-only.
+ if (HasRevertedTokenIDToIdentifier)
+ II->RevertTokenIDToIdentifier();
+ II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+ assert(II->isExtensionToken() == ExtensionToken &&
+ "Incorrect extension token flag");
+ (void)ExtensionToken;
+ II->setIsPoisoned(Poisoned);
+ assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+ "Incorrect C++ operator keyword flag");
+ (void)CPlusPlusOperatorKeyword;
+
+ // If this identifier is a macro, deserialize the macro
+ // definition.
+ if (hasMacroDefinition) {
+ uint32_t Offset = ReadUnalignedLE32(d);
+ Reader.SetIdentifierIsMacro(II, F, Offset);
+ DataLen -= 4;
+ }
+
+ // Read all of the declarations visible at global scope with this
+ // name.
+ if (Reader.getContext() == 0) return II;
+ if (DataLen > 0) {
+ llvm::SmallVector<uint32_t, 4> DeclIDs;
+ for (; DataLen > 0; DataLen -= 4)
+ DeclIDs.push_back(ReadUnalignedLE32(d));
+ Reader.SetGloballyVisibleDecls(II, DeclIDs);
+ }
+
+ II->setIsFromAST();
+ return II;
+ }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used to contain information about
+/// all of the identifiers in the program.
+typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
+ ASTIdentifierLookupTable;
+
+namespace {
+class ASTDeclContextNameLookupTrait {
+ ASTReader &Reader;
+
+public:
+ /// \brief Pair of begin/end iterators for DeclIDs.
+ typedef std::pair<DeclID *, DeclID *> data_type;
+
+ /// \brief Special internal key for declaration names.
+ /// The hash table creates keys for comparison; we do not create
+ /// a DeclarationName for the internal key to avoid deserializing types.
+ struct DeclNameKey {
+ DeclarationName::NameKind Kind;
+ uint64_t Data;
+ DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
+ };
+
+ typedef DeclarationName external_key_type;
+ typedef DeclNameKey internal_key_type;
+
+ explicit ASTDeclContextNameLookupTrait(ASTReader &Reader) : Reader(Reader) { }
+
+ static bool EqualKey(const internal_key_type& a,
+ const internal_key_type& b) {
+ return a.Kind == b.Kind && a.Data == b.Data;
+ }
+
+ unsigned ComputeHash(const DeclNameKey &Key) const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Key.Kind);
+
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ ID.AddInteger((TypeID)Key.Data);
+ break;
+ case DeclarationName::CXXOperatorName:
+ ID.AddInteger((OverloadedOperatorKind)Key.Data);
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return ID.ComputeHash();
+ }
+
+ internal_key_type GetInternalKey(const external_key_type& Name) const {
+ DeclNameKey Key;
+ Key.Kind = Name.getNameKind();
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Key.Data = Reader.GetTypeID(Name.getCXXNameType());
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = Name.getCXXOverloadedOperator();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return Key;
+ }
+
+ external_key_type GetExternalKey(const internal_key_type& Key) const {
+ ASTContext *Context = Reader.getContext();
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ return DeclarationName((IdentifierInfo*)Key.Data);
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return DeclarationName(Selector(Key.Data));
+
+ case DeclarationName::CXXConstructorName:
+ return Context->DeclarationNames.getCXXConstructorName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXDestructorName:
+ return Context->DeclarationNames.getCXXDestructorName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXConversionFunctionName:
+ return Context->DeclarationNames.getCXXConversionFunctionName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXOperatorName:
+ return Context->DeclarationNames.getCXXOperatorName(
+ (OverloadedOperatorKind)Key.Data);
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return Context->DeclarationNames.getCXXLiteralOperatorName(
+ (IdentifierInfo*)Key.Data);
+
+ case DeclarationName::CXXUsingDirective:
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ llvm_unreachable("Invalid Name Kind ?");
+ }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ unsigned DataLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ internal_key_type ReadKey(const unsigned char* d, unsigned) {
+ using namespace clang::io;
+
+ DeclNameKey Key;
+ Key.Kind = (DeclarationName::NameKind)*d++;
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data =
+ (uint64_t)Reader.DecodeSelector(ReadUnalignedLE32(d)).getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Key.Data = ReadUnalignedLE32(d); // TypeID
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = *d++; // OverloadedOperatorKind
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return Key;
+ }
+
+ data_type ReadData(internal_key_type, const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+ unsigned NumDecls = ReadUnalignedLE16(d);
+ DeclID *Start = (DeclID *)d;
+ return std::make_pair(Start, Start + NumDecls);
+ }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
+typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
+ ASTDeclContextNameLookupTable;
+
+bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info) {
+ SavedStreamPosition SavedPosition(Cursor);
+ // First the lexical decls.
+ if (Offsets.first != 0) {
+ Cursor.JumpToBit(Offsets.first);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_LEXICAL) {
+ Error("Expected lexical block");
+ return true;
+ }
+
+ Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob);
+ Info.NumLexicalDecls = BlobLen / sizeof(KindDeclIDPair);
+ } else {
+ Info.LexicalDecls = 0;
+ Info.NumLexicalDecls = 0;
+ }
+
+ // Now the lookup table.
+ if (Offsets.second != 0) {
+ Cursor.JumpToBit(Offsets.second);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_VISIBLE) {
+ Error("Expected visible lookup table block");
+ return true;
+ }
+ Info.NameLookupTableData
+ = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)Blob + Record[0],
+ (const unsigned char *)Blob,
+ ASTDeclContextNameLookupTrait(*this));
+ } else {
+ Info.NameLookupTableData = 0;
+ }
+
+ return false;
+}
+
+void ASTReader::Error(const char *Msg) {
+ Diag(diag::err_fe_pch_malformed) << Msg;
+}
+
+/// \brief Tell the AST listener about the predefines buffers in the chain.
+bool ASTReader::CheckPredefinesBuffers() {
+ if (Listener)
+ return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
+ ActualOriginalFileName,
+ SuggestedPredefines);
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Deserialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Read the line table in the source manager block.
+/// \returns true if there was an error.
+bool ASTReader::ParseLineTable(PerFileData &F,
+ llvm::SmallVectorImpl<uint64_t> &Record) {
+ unsigned Idx = 0;
+ LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+ // Parse the file names
+ std::map<int, int> FileIDs;
+ for (int I = 0, N = Record[Idx++]; I != N; ++I) {
+ // Extract the file name
+ unsigned FilenameLen = Record[Idx++];
+ std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
+ Idx += FilenameLen;
+ MaybeAddSystemRootToFilename(Filename);
+ FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
+ Filename.size());
+ }
+
+ // Parse the line entries
+ std::vector<LineEntry> Entries;
+ while (Idx < Record.size()) {
+ int FID = Record[Idx++];
+
+ // Extract the line entries
+ unsigned NumEntries = Record[Idx++];
+ assert(NumEntries && "Numentries is 00000");
+ Entries.clear();
+ Entries.reserve(NumEntries);
+ for (unsigned I = 0; I != NumEntries; ++I) {
+ unsigned FileOffset = Record[Idx++];
+ unsigned LineNo = Record[Idx++];
+ int FilenameID = FileIDs[Record[Idx++]];
+ SrcMgr::CharacteristicKind FileKind
+ = (SrcMgr::CharacteristicKind)Record[Idx++];
+ unsigned IncludeOffset = Record[Idx++];
+ Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
+ FileKind, IncludeOffset));
+ }
+ LineTable.AddEntry(FID, Entries);
+ }
+
+ return false;
+}
+
+namespace {
+
+class ASTStatData {
+public:
+ const ino_t ino;
+ const dev_t dev;
+ const mode_t mode;
+ const time_t mtime;
+ const off_t size;
+
+ ASTStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
+ : ino(i), dev(d), mode(mo), mtime(m), size(s) {}
+};
+
+class ASTStatLookupTrait {
+ public:
+ typedef const char *external_key_type;
+ typedef const char *internal_key_type;
+
+ typedef ASTStatData data_type;
+
+ static unsigned ComputeHash(const char *path) {
+ return llvm::HashString(path);
+ }
+
+ static internal_key_type GetInternalKey(const char *path) { return path; }
+
+ static bool EqualKey(internal_key_type a, internal_key_type b) {
+ return strcmp(a, b) == 0;
+ }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+ unsigned DataLen = (unsigned) *d++;
+ return std::make_pair(KeyLen + 1, DataLen);
+ }
+
+ static internal_key_type ReadKey(const unsigned char *d, unsigned) {
+ return (const char *)d;
+ }
+
+ static data_type ReadData(const internal_key_type, const unsigned char *d,
+ unsigned /*DataLen*/) {
+ using namespace clang::io;
+
+ ino_t ino = (ino_t) ReadUnalignedLE32(d);
+ dev_t dev = (dev_t) ReadUnalignedLE32(d);
+ mode_t mode = (mode_t) ReadUnalignedLE16(d);
+ time_t mtime = (time_t) ReadUnalignedLE64(d);
+ off_t size = (off_t) ReadUnalignedLE64(d);
+ return data_type(ino, dev, mode, mtime, size);
+ }
+};
+
+/// \brief stat() cache for precompiled headers.
+///
+/// This cache is very similar to the stat cache used by pretokenized
+/// headers.
+class ASTStatCache : public FileSystemStatCache {
+ typedef OnDiskChainedHashTable<ASTStatLookupTrait> CacheTy;
+ CacheTy *Cache;
+
+ unsigned &NumStatHits, &NumStatMisses;
+public:
+ ASTStatCache(const unsigned char *Buckets, const unsigned char *Base,
+ unsigned &NumStatHits, unsigned &NumStatMisses)
+ : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
+ Cache = CacheTy::Create(Buckets, Base);
+ }
+
+ ~ASTStatCache() { delete Cache; }
+
+ LookupResult getStat(const char *Path, struct stat &StatBuf,
+ int *FileDescriptor) {
+ // Do the lookup for the file's data in the AST file.
+ CacheTy::iterator I = Cache->find(Path);
+
+ // If we don't get a hit in the AST file just forward to 'stat'.
+ if (I == Cache->end()) {
+ ++NumStatMisses;
+ return statChained(Path, StatBuf, FileDescriptor);
+ }
+
+ ++NumStatHits;
+ ASTStatData Data = *I;
+
+ StatBuf.st_ino = Data.ino;
+ StatBuf.st_dev = Data.dev;
+ StatBuf.st_mtime = Data.mtime;
+ StatBuf.st_mode = Data.mode;
+ StatBuf.st_size = Data.size;
+ return CacheExists;
+ }
+};
+} // end anonymous namespace
+
+
+/// \brief Read a source manager block
+ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(PerFileData &F) {
+ using namespace SrcMgr;
+
+ llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
+
+ // Set the source-location entry cursor to the current position in
+ // the stream. This cursor will be used to read the contents of the
+ // source manager block initially, and then lazily read
+ // source-location entries as needed.
+ SLocEntryCursor = F.Stream;
+
+ // The stream itself is going to skip over the source manager block.
+ if (F.Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ // Enter the source manager block.
+ if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
+ Error("malformed source manager block record in AST file");
+ return Failure;
+ }
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = SLocEntryCursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (SLocEntryCursor.ReadBlockEnd()) {
+ Error("error at end of Source Manager block in AST file");
+ return Failure;
+ }
+ return Success;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ SLocEntryCursor.ReadSubBlockID();
+ if (SLocEntryCursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ SLocEntryCursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case SM_LINE_TABLE:
+ if (ParseLineTable(F, Record))
+ return Failure;
+ break;
+
+ case SM_SLOC_FILE_ENTRY:
+ case SM_SLOC_BUFFER_ENTRY:
+ case SM_SLOC_INSTANTIATION_ENTRY:
+ // Once we hit one of the source location entries, we're done.
+ return Success;
+ }
+ }
+}
+
+/// \brief If a header file is not found at the path that we expect it to be
+/// and the PCH file was moved from its original location, try to resolve the
+/// file by assuming that header+PCH were moved together and the header is in
+/// the same place relative to the PCH.
+static std::string
+resolveFileRelativeToOriginalDir(const std::string &Filename,
+ const std::string &OriginalDir,
+ const std::string &CurrDir) {
+ assert(OriginalDir != CurrDir &&
+ "No point trying to resolve the file if the PCH dir didn't change");
+ using namespace llvm::sys;
+ llvm::SmallString<128> filePath(Filename);
+ fs::make_absolute(filePath);
+ assert(path::is_absolute(OriginalDir));
+ llvm::SmallString<128> currPCHPath(CurrDir);
+
+ path::const_iterator fileDirI = path::begin(path::parent_path(filePath)),
+ fileDirE = path::end(path::parent_path(filePath));
+ path::const_iterator origDirI = path::begin(OriginalDir),
+ origDirE = path::end(OriginalDir);
+ // Skip the common path components from filePath and OriginalDir.
+ while (fileDirI != fileDirE && origDirI != origDirE &&
+ *fileDirI == *origDirI) {
+ ++fileDirI;
+ ++origDirI;
+ }
+ for (; origDirI != origDirE; ++origDirI)
+ path::append(currPCHPath, "..");
+ path::append(currPCHPath, fileDirI, fileDirE);
+ path::append(currPCHPath, path::filename(Filename));
+ return currPCHPath.str();
+}
+
+/// \brief Get a cursor that's correctly positioned for reading the source
+/// location entry with the given ID.
+ASTReader::PerFileData *ASTReader::SLocCursorForID(unsigned ID) {
+ assert(ID != 0 && ID <= TotalNumSLocEntries &&
+ "SLocCursorForID should only be called for real IDs.");
+
+ ID -= 1;
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (ID < F->LocalNumSLocEntries)
+ break;
+ ID -= F->LocalNumSLocEntries;
+ }
+ assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted");
+
+ F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]);
+ return F;
+}
+
+/// \brief Read in the source location entry with the given ID.
+ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) {
+ if (ID == 0)
+ return Success;
+
+ if (ID > TotalNumSLocEntries) {
+ Error("source location entry ID out-of-range for AST file");
+ return Failure;
+ }
+
+ PerFileData *F = SLocCursorForID(ID);
+ llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
+
+ ++NumSLocEntriesRead;
+ unsigned Code = SLocEntryCursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK ||
+ Code == llvm::bitc::ENTER_SUBBLOCK ||
+ Code == llvm::bitc::DEFINE_ABBREV) {
+ Error("incorrectly-formatted source location entry in AST file");
+ return Failure;
+ }
+
+ RecordData Record;
+ const char *BlobStart;
+ unsigned BlobLen;
+ switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default:
+ Error("incorrectly-formatted source location entry in AST file");
+ return Failure;
+
+ case SM_SLOC_FILE_ENTRY: {
+ std::string Filename(BlobStart, BlobStart + BlobLen);
+ MaybeAddSystemRootToFilename(Filename);
+ const FileEntry *File = FileMgr.getFile(Filename);
+ if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() &&
+ OriginalDir != CurrentDir) {
+ std::string resolved = resolveFileRelativeToOriginalDir(Filename,
+ OriginalDir,
+ CurrentDir);
+ if (!resolved.empty())
+ File = FileMgr.getFile(resolved);
+ }
+ if (File == 0)
+ File = FileMgr.getVirtualFile(Filename, (off_t)Record[4],
+ (time_t)Record[5]);
+ if (File == 0) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr += Filename;
+ ErrorStr += "' referenced by AST file";
+ Error(ErrorStr.c_str());
+ return Failure;
+ }
+
+ if (Record.size() < 6) {
+ Error("source location entry is incorrect");
+ return Failure;
+ }
+
+ if (!DisableValidation &&
+ ((off_t)Record[4] != File->getSize()
+#if !defined(LLVM_ON_WIN32)
+ // In our regression testing, the Windows file system seems to
+ // have inconsistent modification times that sometimes
+ // erroneously trigger this error-handling path.
+ || (time_t)Record[5] != File->getModificationTime()
+#endif
+ )) {
+ Diag(diag::err_fe_pch_file_modified)
+ << Filename;
+ return Failure;
+ }
+
+ FileID FID = SourceMgr.createFileID(File, ReadSourceLocation(*F, Record[1]),
+ (SrcMgr::CharacteristicKind)Record[2],
+ ID, Record[0]);
+ if (Record[3])
+ const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
+ .setHasLineDirectives();
+
+ break;
+ }
+
+ case SM_SLOC_BUFFER_ENTRY: {
+ const char *Name = BlobStart;
+ unsigned Offset = Record[0];
+ unsigned Code = SLocEntryCursor.ReadCode();
+ Record.clear();
+ unsigned RecCode
+ = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+
+ if (RecCode != SM_SLOC_BUFFER_BLOB) {
+ Error("AST record has invalid code");
+ return Failure;
+ }
+
+ llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1),
+ Name);
+ FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
+
+ if (strcmp(Name, "<built-in>") == 0) {
+ PCHPredefinesBlock Block = {
+ BufferID,
+ llvm::StringRef(BlobStart, BlobLen - 1)
+ };
+ PCHPredefinesBuffers.push_back(Block);
+ }
+
+ break;
+ }
+
+ case SM_SLOC_INSTANTIATION_ENTRY: {
+ SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]);
+ SourceMgr.createInstantiationLoc(SpellingLoc,
+ ReadSourceLocation(*F, Record[2]),
+ ReadSourceLocation(*F, Record[3]),
+ Record[4],
+ ID,
+ Record[0]);
+ break;
+ }
+ }
+
+ return Success;
+}
+
+/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+/// specified cursor. Read the abbreviations that are at the top of the block
+/// and then leave the cursor pointing into the block.
+bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
+ unsigned BlockID) {
+ if (Cursor.EnterSubBlock(BlockID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ while (true) {
+ uint64_t Offset = Cursor.GetCurrentBitNo();
+ unsigned Code = Cursor.ReadCode();
+
+ // We expect all abbrevs to be at the start of the block.
+ if (Code != llvm::bitc::DEFINE_ABBREV) {
+ Cursor.JumpToBit(Offset);
+ return false;
+ }
+ Cursor.ReadAbbrevRecord();
+ }
+}
+
+PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) {
+ assert(PP && "Forgot to set Preprocessor ?");
+ llvm::BitstreamCursor &Stream = F.MacroCursor;
+
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this macro.
+ SavedStreamPosition SavedPosition(Stream);
+
+ Stream.JumpToBit(Offset);
+ RecordData Record;
+ llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
+ MacroInfo *Macro = 0;
+
+ while (true) {
+ unsigned Code = Stream.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ return 0;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return 0;
+ }
+ continue;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+ default: break;
+ }
+
+ // Read a record.
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ Record.clear();
+ PreprocessorRecordTypes RecType =
+ (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record, BlobStart,
+ BlobLen);
+ switch (RecType) {
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE: {
+ // If we already have a macro, that means that we've hit the end
+ // of the definition of the macro we were looking for. We're
+ // done.
+ if (Macro)
+ return 0;
+
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
+ if (II == 0) {
+ Error("macro must have a name in AST file");
+ return 0;
+ }
+ SourceLocation Loc = ReadSourceLocation(F, Record[1]);
+ bool isUsed = Record[2];
+
+ MacroInfo *MI = PP->AllocateMacroInfo(Loc);
+ MI->setIsUsed(isUsed);
+ MI->setIsFromAST();
+
+ unsigned NextIndex = 3;
+ if (RecType == PP_MACRO_FUNCTION_LIKE) {
+ // Decode function-like macro info.
+ bool isC99VarArgs = Record[3];
+ bool isGNUVarArgs = Record[4];
+ MacroArgs.clear();
+ unsigned NumArgs = Record[5];
+ NextIndex = 6 + NumArgs;
+ for (unsigned i = 0; i != NumArgs; ++i)
+ MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
+
+ // Install function-like macro info.
+ MI->setIsFunctionLike();
+ if (isC99VarArgs) MI->setIsC99Varargs();
+ if (isGNUVarArgs) MI->setIsGNUVarargs();
+ MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
+ PP->getPreprocessorAllocator());
+ }
+
+ // Finally, install the macro.
+ PP->setMacroInfo(II, MI);
+
+ // Remember that we saw this macro last so that we add the tokens that
+ // form its body to it.
+ Macro = MI;
+
+ if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) {
+ // We have a macro definition. Load it now.
+ PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro,
+ getMacroDefinition(Record[NextIndex]));
+ }
+
+ ++NumMacrosRead;
+ break;
+ }
+
+ case PP_TOKEN: {
+ // If we see a TOKEN before a PP_MACRO_*, then the file is
+ // erroneous, just pretend we didn't see this.
+ if (Macro == 0) break;
+
+ Token Tok;
+ Tok.startToken();
+ Tok.setLocation(ReadSourceLocation(F, Record[0]));
+ Tok.setLength(Record[1]);
+ if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
+ Tok.setIdentifierInfo(II);
+ Tok.setKind((tok::TokenKind)Record[3]);
+ Tok.setFlag((Token::TokenFlags)Record[4]);
+ Macro->AddTokenToBody(Tok);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+PreprocessedEntity *ASTReader::LoadPreprocessedEntity(PerFileData &F) {
+ assert(PP && "Forgot to set Preprocessor ?");
+ unsigned Code = F.PreprocessorDetailCursor.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ return 0;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ Error("unexpected subblock record in preprocessor detail block");
+ return 0;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Error("unexpected abbrevation record in preprocessor detail block");
+ return 0;
+
+ default:
+ break;
+ }
+
+ if (!PP->getPreprocessingRecord()) {
+ Error("no preprocessing record");
+ return 0;
+ }
+
+ // Read the record.
+ PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ RecordData Record;
+ PreprocessorDetailRecordTypes RecType =
+ (PreprocessorDetailRecordTypes)F.PreprocessorDetailCursor.ReadRecord(
+ Code, Record, BlobStart, BlobLen);
+ switch (RecType) {
+ case PPD_MACRO_INSTANTIATION: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ MacroInstantiation *MI
+ = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]),
+ SourceRange(ReadSourceLocation(F, Record[1]),
+ ReadSourceLocation(F, Record[2])),
+ getMacroDefinition(Record[4]));
+ PPRec.SetPreallocatedEntity(Record[0], MI);
+ return MI;
+ }
+
+ case PPD_MACRO_DEFINITION: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ if (Record[1] > MacroDefinitionsLoaded.size()) {
+ Error("out-of-bounds macro definition record");
+ return 0;
+ }
+
+ // Decode the identifier info and then check again; if the macro is
+ // still defined and associated with the identifier,
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[4]);
+ if (!MacroDefinitionsLoaded[Record[1] - 1]) {
+ MacroDefinition *MD
+ = new (PPRec) MacroDefinition(II,
+ ReadSourceLocation(F, Record[5]),
+ SourceRange(
+ ReadSourceLocation(F, Record[2]),
+ ReadSourceLocation(F, Record[3])));
+
+ PPRec.SetPreallocatedEntity(Record[0], MD);
+ MacroDefinitionsLoaded[Record[1] - 1] = MD;
+
+ if (DeserializationListener)
+ DeserializationListener->MacroDefinitionRead(Record[1], MD);
+ }
+
+ return MacroDefinitionsLoaded[Record[1] - 1];
+ }
+
+ case PPD_INCLUSION_DIRECTIVE: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ const char *FullFileNameStart = BlobStart + Record[3];
+ const FileEntry *File
+ = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart,
+ BlobLen - Record[3]));
+
+ // FIXME: Stable encoding
+ InclusionDirective::InclusionKind Kind
+ = static_cast<InclusionDirective::InclusionKind>(Record[5]);
+ InclusionDirective *ID
+ = new (PPRec) InclusionDirective(PPRec, Kind,
+ llvm::StringRef(BlobStart, Record[3]),
+ Record[4],
+ File,
+ SourceRange(ReadSourceLocation(F, Record[1]),
+ ReadSourceLocation(F, Record[2])));
+ PPRec.SetPreallocatedEntity(Record[0], ID);
+ return ID;
+ }
+ }
+
+ Error("invalid offset in preprocessor detail block");
+ return 0;
+}
+
+namespace {
+ /// \brief Trait class used to search the on-disk hash table containing all of
+ /// the header search information.
+ ///
+ /// The on-disk hash table contains a mapping from each header path to
+ /// information about that header (how many times it has been included, its
+ /// controlling macro, etc.). Note that we actually hash based on the
+ /// filename, and support "deep" comparisons of file names based on current
+ /// inode numbers, so that the search can cope with non-normalized path names
+ /// and symlinks.
+ class HeaderFileInfoTrait {
+ const char *SearchPath;
+ struct stat SearchPathStatBuf;
+ llvm::Optional<int> SearchPathStatResult;
+
+ int StatSimpleCache(const char *Path, struct stat *StatBuf) {
+ if (Path == SearchPath) {
+ if (!SearchPathStatResult)
+ SearchPathStatResult = stat(Path, &SearchPathStatBuf);
+
+ *StatBuf = SearchPathStatBuf;
+ return *SearchPathStatResult;
+ }
+
+ return stat(Path, StatBuf);
+ }
+
+ public:
+ typedef const char *external_key_type;
+ typedef const char *internal_key_type;
+
+ typedef HeaderFileInfo data_type;
+
+ HeaderFileInfoTrait(const char *SearchPath = 0) : SearchPath(SearchPath) { }
+
+ static unsigned ComputeHash(const char *path) {
+ return llvm::HashString(llvm::sys::path::filename(path));
+ }
+
+ static internal_key_type GetInternalKey(const char *path) { return path; }
+
+ bool EqualKey(internal_key_type a, internal_key_type b) {
+ if (strcmp(a, b) == 0)
+ return true;
+
+ if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
+ return false;
+
+ // The file names match, but the path names don't. stat() the files to
+ // see if they are the same.
+ struct stat StatBufA, StatBufB;
+ if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB))
+ return false;
+
+ return StatBufA.st_ino == StatBufB.st_ino;
+ }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+ unsigned DataLen = (unsigned) *d++;
+ return std::make_pair(KeyLen + 1, DataLen);
+ }
+
+ static internal_key_type ReadKey(const unsigned char *d, unsigned) {
+ return (const char *)d;
+ }
+
+ static data_type ReadData(const internal_key_type, const unsigned char *d,
+ unsigned DataLen) {
+ const unsigned char *End = d + DataLen;
+ using namespace clang::io;
+ HeaderFileInfo HFI;
+ unsigned Flags = *d++;
+ HFI.isImport = (Flags >> 3) & 0x01;
+ HFI.DirInfo = (Flags >> 1) & 0x03;
+ HFI.Resolved = Flags & 0x01;
+ HFI.NumIncludes = ReadUnalignedLE16(d);
+ HFI.ControllingMacroID = ReadUnalignedLE32(d);
+ assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
+ (void)End;
+
+ // This HeaderFileInfo was externally loaded.
+ HFI.External = true;
+ return HFI;
+ }
+ };
+}
+
+/// \brief The on-disk hash table used for the global method pool.
+typedef OnDiskChainedHashTable<HeaderFileInfoTrait>
+ HeaderFileInfoLookupTable;
+
+void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
+ uint64_t Offset) {
+ // Note that this identifier has a macro definition.
+ II->setHasMacroDefinition(true);
+
+ // Adjust the offset based on our position in the chain.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Chain[I] == &F)
+ break;
+
+ Offset += Chain[I]->SizeInBits;
+ }
+
+ UnreadMacroRecordOffsets[II] = Offset;
+}
+
+void ASTReader::ReadDefinedMacros() {
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ llvm::BitstreamCursor &MacroCursor = F.MacroCursor;
+
+ // If there was no preprocessor block, skip this file.
+ if (!MacroCursor.getBitStreamReader())
+ continue;
+
+ llvm::BitstreamCursor Cursor = MacroCursor;
+ Cursor.JumpToBit(F.MacroStartOffset);
+
+ RecordData Record;
+ while (true) {
+ unsigned Code = Cursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK)
+ break;
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Cursor.ReadSubBlockID();
+ if (Cursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Cursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE:
+ DecodeIdentifierInfo(Record[0]);
+ break;
+
+ case PP_TOKEN:
+ // Ignore tokens.
+ break;
+ }
+ }
+ }
+
+ // Drain the unread macro-record offsets map.
+ while (!UnreadMacroRecordOffsets.empty())
+ LoadMacroDefinition(UnreadMacroRecordOffsets.begin());
+}
+
+void ASTReader::LoadMacroDefinition(
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) {
+ assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition");
+ PerFileData *F = 0;
+ uint64_t Offset = Pos->second;
+ UnreadMacroRecordOffsets.erase(Pos);
+
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Offset < Chain[I]->SizeInBits) {
+ F = Chain[I];
+ break;
+ }
+
+ Offset -= Chain[I]->SizeInBits;
+ }
+ if (!F) {
+ Error("Malformed macro record offset");
+ return;
+ }
+
+ ReadMacroRecord(*F, Offset);
+}
+
+void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
+ llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos
+ = UnreadMacroRecordOffsets.find(II);
+ LoadMacroDefinition(Pos);
+}
+
+MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) {
+ if (ID == 0 || ID > MacroDefinitionsLoaded.size())
+ return 0;
+
+ if (!MacroDefinitionsLoaded[ID - 1]) {
+ unsigned Index = ID - 1;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Index < F.LocalNumMacroDefinitions) {
+ SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor);
+ F.PreprocessorDetailCursor.JumpToBit(F.MacroDefinitionOffsets[Index]);
+ LoadPreprocessedEntity(F);
+ break;
+ }
+ Index -= F.LocalNumMacroDefinitions;
+ }
+ assert(MacroDefinitionsLoaded[ID - 1] && "Broken chain");
+ }
+
+ return MacroDefinitionsLoaded[ID - 1];
+}
+
+/// \brief If we are loading a relocatable PCH file, and the filename is
+/// not an absolute path, add the system root to the beginning of the file
+/// name.
+void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) {
+ // If this is not a relocatable PCH file, there's nothing to do.
+ if (!RelocatablePCH)
+ return;
+
+ if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
+ return;
+
+ if (isysroot == 0) {
+ // If no system root was given, default to '/'
+ Filename.insert(Filename.begin(), '/');
+ return;
+ }
+
+ unsigned Length = strlen(isysroot);
+ if (isysroot[Length - 1] != '/')
+ Filename.insert(Filename.begin(), '/');
+
+ Filename.insert(Filename.begin(), isysroot, isysroot + Length);
+}
+
+ASTReader::ASTReadResult
+ASTReader::ReadASTBlock(PerFileData &F) {
+ llvm::BitstreamCursor &Stream = F.Stream;
+
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ // Read all of the records and blocks for the ASt file.
+ RecordData Record;
+ bool First = true;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Error("error at end of module block in AST file");
+ return Failure;
+ }
+
+ return Success;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ switch (Stream.ReadSubBlockID()) {
+ case DECLTYPES_BLOCK_ID:
+ // We lazily load the decls block, but we want to set up the
+ // DeclsCursor cursor to point into it. Clone our current bitcode
+ // cursor to it, enter the block and read the abbrevs in that block.
+ // With the main cursor, we just skip over it.
+ F.DeclsCursor = Stream;
+ if (Stream.SkipBlock() || // Skip with the main cursor.
+ // Read the abbrevs.
+ ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ break;
+
+ case DECL_UPDATES_BLOCK_ID:
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ break;
+
+ case PREPROCESSOR_BLOCK_ID:
+ F.MacroCursor = Stream;
+ if (PP)
+ PP->setExternalSource(this);
+
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
+ break;
+
+ case PREPROCESSOR_DETAIL_BLOCK_ID:
+ F.PreprocessorDetailCursor = Stream;
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(F.PreprocessorDetailCursor,
+ PREPROCESSOR_DETAIL_BLOCK_ID)) {
+ Error("malformed preprocessor detail record in AST file");
+ return Failure;
+ }
+ F.PreprocessorDetailStartOffset
+ = F.PreprocessorDetailCursor.GetCurrentBitNo();
+ break;
+
+ case SOURCE_MANAGER_BLOCK_ID:
+ switch (ReadSourceManagerBlock(F)) {
+ case Success:
+ break;
+
+ case Failure:
+ Error("malformed source manager block in AST file");
+ return Failure;
+
+ case IgnorePCH:
+ return IgnorePCH;
+ }
+ break;
+ }
+ First = false;
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return IgnorePCH;
+ }
+
+ RelocatablePCH = Record[4];
+ if (Listener) {
+ std::string TargetTriple(BlobStart, BlobLen);
+ if (Listener->ReadTargetTriple(TargetTriple))
+ return IgnorePCH;
+ }
+ break;
+ }
+
+ case CHAINED_METADATA: {
+ if (!First) {
+ Error("CHAINED_METADATA is not first record in block");
+ return Failure;
+ }
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return IgnorePCH;
+ }
+
+ // Load the chained file, which is always a PCH file.
+ switch(ReadASTCore(llvm::StringRef(BlobStart, BlobLen), PCH)) {
+ case Failure: return Failure;
+ // If we have to ignore the dependency, we'll have to ignore this too.
+ case IgnorePCH: return IgnorePCH;
+ case Success: break;
+ }
+ break;
+ }
+
+ case TYPE_OFFSET:
+ if (F.LocalNumTypes != 0) {
+ Error("duplicate TYPE_OFFSET record in AST file");
+ return Failure;
+ }
+ F.TypeOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumTypes = Record[0];
+ break;
+
+ case DECL_OFFSET:
+ if (F.LocalNumDecls != 0) {
+ Error("duplicate DECL_OFFSET record in AST file");
+ return Failure;
+ }
+ F.DeclOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumDecls = Record[0];
+ break;
+
+ case TU_UPDATE_LEXICAL: {
+ DeclContextInfo Info = {
+ /* No visible information */ 0,
+ reinterpret_cast<const KindDeclIDPair *>(BlobStart),
+ BlobLen / sizeof(KindDeclIDPair)
+ };
+ DeclContextOffsets[Context ? Context->getTranslationUnitDecl() : 0]
+ .push_back(Info);
+ break;
+ }
+
+ case UPDATE_VISIBLE: {
+ serialization::DeclID ID = Record[0];
+ void *Table = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)BlobStart + Record[1],
+ (const unsigned char *)BlobStart,
+ ASTDeclContextNameLookupTrait(*this));
+ if (ID == 1 && Context) { // Is it the TU?
+ DeclContextInfo Info = {
+ Table, /* No lexical inforamtion */ 0, 0
+ };
+ DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
+ } else
+ PendingVisibleUpdates[ID].push_back(Table);
+ break;
+ }
+
+ case REDECLS_UPDATE_LATEST: {
+ assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
+ for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
+ DeclID First = Record[i], Latest = Record[i+1];
+ assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
+ Latest > FirstLatestDeclIDs[First]) &&
+ "The new latest is supposed to come after the previous latest");
+ FirstLatestDeclIDs[First] = Latest;
+ }
+ break;
+ }
+
+ case LANGUAGE_OPTIONS:
+ if (ParseLanguageOptions(Record) && !DisableValidation)
+ return IgnorePCH;
+ break;
+
+ case IDENTIFIER_TABLE:
+ F.IdentifierTableData = BlobStart;
+ if (Record[0]) {
+ F.IdentifierLookupTable
+ = ASTIdentifierLookupTable::Create(
+ (const unsigned char *)F.IdentifierTableData + Record[0],
+ (const unsigned char *)F.IdentifierTableData,
+ ASTIdentifierLookupTrait(*this, F));
+ if (PP)
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ }
+ break;
+
+ case IDENTIFIER_OFFSET:
+ if (F.LocalNumIdentifiers != 0) {
+ Error("duplicate IDENTIFIER_OFFSET record in AST file");
+ return Failure;
+ }
+ F.IdentifierOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumIdentifiers = Record[0];
+ break;
+
+ case EXTERNAL_DEFINITIONS:
+ // Optimization for the first block.
+ if (ExternalDefinitions.empty())
+ ExternalDefinitions.swap(Record);
+ else
+ ExternalDefinitions.insert(ExternalDefinitions.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case SPECIAL_TYPES:
+ // Optimization for the first block
+ if (SpecialTypes.empty())
+ SpecialTypes.swap(Record);
+ else
+ SpecialTypes.insert(SpecialTypes.end(), Record.begin(), Record.end());
+ break;
+
+ case STATISTICS:
+ TotalNumStatements += Record[0];
+ TotalNumMacros += Record[1];
+ TotalLexicalDeclContexts += Record[2];
+ TotalVisibleDeclContexts += Record[3];
+ break;
+
+ case TENTATIVE_DEFINITIONS:
+ // Optimization for the first block.
+ if (TentativeDefinitions.empty())
+ TentativeDefinitions.swap(Record);
+ else
+ TentativeDefinitions.insert(TentativeDefinitions.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case UNUSED_FILESCOPED_DECLS:
+ // Optimization for the first block.
+ if (UnusedFileScopedDecls.empty())
+ UnusedFileScopedDecls.swap(Record);
+ else
+ UnusedFileScopedDecls.insert(UnusedFileScopedDecls.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case WEAK_UNDECLARED_IDENTIFIERS:
+ // Later blocks overwrite earlier ones.
+ WeakUndeclaredIdentifiers.swap(Record);
+ break;
+
+ case LOCALLY_SCOPED_EXTERNAL_DECLS:
+ // Optimization for the first block.
+ if (LocallyScopedExternalDecls.empty())
+ LocallyScopedExternalDecls.swap(Record);
+ else
+ LocallyScopedExternalDecls.insert(LocallyScopedExternalDecls.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case SELECTOR_OFFSETS:
+ F.SelectorOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSelectors = Record[0];
+ break;
+
+ case METHOD_POOL:
+ F.SelectorLookupTableData = (const unsigned char *)BlobStart;
+ if (Record[0])
+ F.SelectorLookupTable
+ = ASTSelectorLookupTable::Create(
+ F.SelectorLookupTableData + Record[0],
+ F.SelectorLookupTableData,
+ ASTSelectorLookupTrait(*this));
+ TotalNumMethodPoolEntries += Record[1];
+ break;
+
+ case REFERENCED_SELECTOR_POOL:
+ F.ReferencedSelectorsData.swap(Record);
+ break;
+
+ case PP_COUNTER_VALUE:
+ if (!Record.empty() && Listener)
+ Listener->ReadCounter(Record[0]);
+ break;
+
+ case SOURCE_LOCATION_OFFSETS:
+ F.SLocOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSLocEntries = Record[0];
+ F.LocalSLocSize = Record[1];
+ break;
+
+ case SOURCE_LOCATION_PRELOADS:
+ if (PreloadSLocEntries.empty())
+ PreloadSLocEntries.swap(Record);
+ else
+ PreloadSLocEntries.insert(PreloadSLocEntries.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case STAT_CACHE: {
+ if (!DisableStatCache) {
+ ASTStatCache *MyStatCache =
+ new ASTStatCache((const unsigned char *)BlobStart + Record[0],
+ (const unsigned char *)BlobStart,
+ NumStatHits, NumStatMisses);
+ FileMgr.addStatCache(MyStatCache);
+ F.StatCache = MyStatCache;
+ }
+ break;
+ }
+
+ case EXT_VECTOR_DECLS:
+ // Optimization for the first block.
+ if (ExtVectorDecls.empty())
+ ExtVectorDecls.swap(Record);
+ else
+ ExtVectorDecls.insert(ExtVectorDecls.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case VTABLE_USES:
+ // Later tables overwrite earlier ones.
+ VTableUses.swap(Record);
+ break;
+
+ case DYNAMIC_CLASSES:
+ // Optimization for the first block.
+ if (DynamicClasses.empty())
+ DynamicClasses.swap(Record);
+ else
+ DynamicClasses.insert(DynamicClasses.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case PENDING_IMPLICIT_INSTANTIATIONS:
+ F.PendingInstantiations.swap(Record);
+ break;
+
+ case SEMA_DECL_REFS:
+ // Later tables overwrite earlier ones.
+ SemaDeclRefs.swap(Record);
+ break;
+
+ case ORIGINAL_FILE_NAME:
+ // The primary AST will be the last to get here, so it will be the one
+ // that's used.
+ ActualOriginalFileName.assign(BlobStart, BlobLen);
+ OriginalFileName = ActualOriginalFileName;
+ MaybeAddSystemRootToFilename(OriginalFileName);
+ break;
+
+ case ORIGINAL_PCH_DIR:
+ // The primary AST will be the last to get here, so it will be the one
+ // that's used.
+ OriginalDir.assign(BlobStart, BlobLen);
+ break;
+
+ case VERSION_CONTROL_BRANCH_REVISION: {
+ const std::string &CurBranch = getClangFullRepositoryVersion();
+ llvm::StringRef ASTBranch(BlobStart, BlobLen);
+ if (llvm::StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+ Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+ return IgnorePCH;
+ }
+ break;
+ }
+
+ case MACRO_DEFINITION_OFFSETS:
+ F.MacroDefinitionOffsets = (const uint32_t *)BlobStart;
+ F.NumPreallocatedPreprocessingEntities = Record[0];
+ F.LocalNumMacroDefinitions = Record[1];
+ break;
+
+ case DECL_UPDATE_OFFSETS: {
+ if (Record.size() % 2 != 0) {
+ Error("invalid DECL_UPDATE_OFFSETS block in AST file");
+ return Failure;
+ }
+ for (unsigned I = 0, N = Record.size(); I != N; I += 2)
+ DeclUpdateOffsets[static_cast<DeclID>(Record[I])]
+ .push_back(std::make_pair(&F, Record[I+1]));
+ break;
+ }
+
+ case DECL_REPLACEMENTS: {
+ if (Record.size() % 2 != 0) {
+ Error("invalid DECL_REPLACEMENTS block in AST file");
+ return Failure;
+ }
+ for (unsigned I = 0, N = Record.size(); I != N; I += 2)
+ ReplacedDecls[static_cast<DeclID>(Record[I])] =
+ std::make_pair(&F, Record[I+1]);
+ break;
+ }
+
+ case CXX_BASE_SPECIFIER_OFFSETS: {
+ if (F.LocalNumCXXBaseSpecifiers != 0) {
+ Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
+ return Failure;
+ }
+
+ F.LocalNumCXXBaseSpecifiers = Record[0];
+ F.CXXBaseSpecifiersOffsets = (const uint32_t *)BlobStart;
+ break;
+ }
+
+ case DIAG_PRAGMA_MAPPINGS:
+ if (Record.size() % 2 != 0) {
+ Error("invalid DIAG_USER_MAPPINGS block in AST file");
+ return Failure;
+ }
+ if (PragmaDiagMappings.empty())
+ PragmaDiagMappings.swap(Record);
+ else
+ PragmaDiagMappings.insert(PragmaDiagMappings.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case CUDA_SPECIAL_DECL_REFS:
+ // Later tables overwrite earlier ones.
+ CUDASpecialDeclRefs.swap(Record);
+ break;
+
+ case HEADER_SEARCH_TABLE:
+ F.HeaderFileInfoTableData = BlobStart;
+ F.LocalNumHeaderFileInfos = Record[1];
+ if (Record[0]) {
+ F.HeaderFileInfoTable
+ = HeaderFileInfoLookupTable::Create(
+ (const unsigned char *)F.HeaderFileInfoTableData + Record[0],
+ (const unsigned char *)F.HeaderFileInfoTableData);
+ if (PP)
+ PP->getHeaderSearchInfo().SetExternalSource(this);
+ }
+ break;
+
+ case FP_PRAGMA_OPTIONS:
+ // Later tables overwrite earlier ones.
+ FPPragmaOptions.swap(Record);
+ break;
+
+ case OPENCL_EXTENSIONS:
+ // Later tables overwrite earlier ones.
+ OpenCLExtensions.swap(Record);
+ break;
+ }
+ First = false;
+ }
+ Error("premature end of bitstream in AST file");
+ return Failure;
+}
+
+ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
+ ASTFileType Type) {
+ switch(ReadASTCore(FileName, Type)) {
+ case Failure: return Failure;
+ case IgnorePCH: return IgnorePCH;
+ case Success: break;
+ }
+
+ // Here comes stuff that we only do once the entire chain is loaded.
+
+ // Allocate space for loaded slocentries, identifiers, decls and types.
+ unsigned TotalNumIdentifiers = 0, TotalNumTypes = 0, TotalNumDecls = 0,
+ TotalNumPreallocatedPreprocessingEntities = 0, TotalNumMacroDefs = 0,
+ TotalNumSelectors = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ TotalNumSLocEntries += Chain[I]->LocalNumSLocEntries;
+ NextSLocOffset += Chain[I]->LocalSLocSize;
+ TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers;
+ TotalNumTypes += Chain[I]->LocalNumTypes;
+ TotalNumDecls += Chain[I]->LocalNumDecls;
+ TotalNumPreallocatedPreprocessingEntities +=
+ Chain[I]->NumPreallocatedPreprocessingEntities;
+ TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions;
+ TotalNumSelectors += Chain[I]->LocalNumSelectors;
+ }
+ SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, NextSLocOffset);
+ IdentifiersLoaded.resize(TotalNumIdentifiers);
+ TypesLoaded.resize(TotalNumTypes);
+ DeclsLoaded.resize(TotalNumDecls);
+ MacroDefinitionsLoaded.resize(TotalNumMacroDefs);
+ if (PP) {
+ if (TotalNumIdentifiers > 0)
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+ if (TotalNumPreallocatedPreprocessingEntities > 0) {
+ if (!PP->getPreprocessingRecord())
+ PP->createPreprocessingRecord();
+ PP->getPreprocessingRecord()->SetExternalSource(*this,
+ TotalNumPreallocatedPreprocessingEntities);
+ }
+ }
+ SelectorsLoaded.resize(TotalNumSelectors);
+ // Preload SLocEntries.
+ for (unsigned I = 0, N = PreloadSLocEntries.size(); I != N; ++I) {
+ ASTReadResult Result = ReadSLocEntryRecord(PreloadSLocEntries[I]);
+ if (Result != Success)
+ return Result;
+ }
+
+ // Check the predefines buffers.
+ if (!DisableValidation && CheckPredefinesBuffers())
+ return IgnorePCH;
+
+ if (PP) {
+ // Initialization of keywords and pragmas occurs before the
+ // AST file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ // We need to search the tables in all files.
+ for (unsigned J = 0, M = Chain.size(); J != M; ++J) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Chain[J]->IdentifierLookupTable;
+ // Not all AST files necessarily have identifier tables, only the useful
+ // ones.
+ if (!IdTable)
+ continue;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ IdentifierInfo *II = Identifiers[I];
+ // Look in the on-disk hash tables for an entry for this identifier
+ ASTIdentifierLookupTrait Info(*this, *Chain[J], II);
+ std::pair<const char*,unsigned> Key(II->getNameStart(),II->getLength());
+ ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
+ }
+ }
+
+ if (Context)
+ InitializeContext(*Context);
+
+ if (DeserializationListener)
+ DeserializationListener->ReaderInitialized(this);
+
+ // If this AST file is a precompiled preamble, then set the main file ID of
+ // the source manager to the file source file from which the preamble was
+ // built. This is the only valid way to use a precompiled preamble.
+ if (Type == Preamble) {
+ SourceLocation Loc
+ = SourceMgr.getLocation(FileMgr.getFile(getOriginalSourceFile()), 1, 1);
+ if (Loc.isValid()) {
+ std::pair<FileID, unsigned> Decomposed = SourceMgr.getDecomposedLoc(Loc);
+ SourceMgr.SetPreambleFileID(Decomposed.first);
+ }
+ }
+
+ return Success;
+}
+
+ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName,
+ ASTFileType Type) {
+ PerFileData *Prev = Chain.empty() ? 0 : Chain.back();
+ Chain.push_back(new PerFileData(Type));
+ PerFileData &F = *Chain.back();
+ if (Prev)
+ Prev->NextInSource = &F;
+ else
+ FirstInSource = &F;
+ F.Loaders.push_back(Prev);
+
+ // Set the AST file name.
+ F.FileName = FileName;
+
+ if (FileName != "-") {
+ CurrentDir = llvm::sys::path::parent_path(FileName);
+ if (CurrentDir.empty()) CurrentDir = ".";
+ }
+
+ // Open the AST file.
+ //
+ // FIXME: This shouldn't be here, we should just take a raw_ostream.
+ std::string ErrStr;
+ llvm::error_code ec;
+ if (FileName == "-") {
+ ec = llvm::MemoryBuffer::getSTDIN(F.Buffer);
+ if (ec)
+ ErrStr = ec.message();
+ } else
+ F.Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrStr));
+ if (!F.Buffer) {
+ Error(ErrStr.c_str());
+ return IgnorePCH;
+ }
+
+ // Initialize the stream
+ F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
+ (const unsigned char *)F.Buffer->getBufferEnd());
+ llvm::BitstreamCursor &Stream = F.Stream;
+ Stream.init(F.StreamFile);
+ F.SizeInBits = F.Buffer->getBufferSize() * 8;
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ Diag(diag::err_not_a_pch_file) << FileName;
+ return Failure;
+ }
+
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code != llvm::bitc::ENTER_SUBBLOCK) {
+ Error("invalid record at top-level of AST file");
+ return Failure;
+ }
+
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the AST subblock ID.
+ switch (BlockID) {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID:
+ if (Stream.ReadBlockInfoBlock()) {
+ Error("malformed BlockInfoBlock in AST file");
+ return Failure;
+ }
+ break;
+ case AST_BLOCK_ID:
+ switch (ReadASTBlock(F)) {
+ case Success:
+ break;
+
+ case Failure:
+ return Failure;
+
+ case IgnorePCH:
+ // FIXME: We could consider reading through to the end of this
+ // AST block, skipping subblocks, to see if there are other
+ // AST blocks elsewhere.
+
+ // Clear out any preallocated source location entries, so that
+ // the source manager does not try to resolve them later.
+ SourceMgr.ClearPreallocatedSLocEntries();
+
+ // Remove the stat cache.
+ if (F.StatCache)
+ FileMgr.removeStatCache((ASTStatCache*)F.StatCache);
+
+ return IgnorePCH;
+ }
+ break;
+ default:
+ if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ break;
+ }
+ }
+
+ return Success;
+}
+
+void ASTReader::setPreprocessor(Preprocessor &pp) {
+ PP = &pp;
+
+ unsigned TotalNum = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I)
+ TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities;
+ if (TotalNum) {
+ if (!PP->getPreprocessingRecord())
+ PP->createPreprocessingRecord();
+ PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum);
+ }
+}
+
+void ASTReader::InitializeContext(ASTContext &Ctx) {
+ Context = &Ctx;
+ assert(Context && "Passed null context!");
+
+ assert(PP && "Forgot to set Preprocessor ?");
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+ PP->setExternalSource(this);
+ PP->getHeaderSearchInfo().SetExternalSource(this);
+
+ // If we have an update block for the TU waiting, we have to add it before
+ // deserializing the decl.
+ DeclContextOffsetsMap::iterator DCU = DeclContextOffsets.find(0);
+ if (DCU != DeclContextOffsets.end()) {
+ // Insertion could invalidate map, so grab vector.
+ DeclContextInfos T;
+ T.swap(DCU->second);
+ DeclContextOffsets.erase(DCU);
+ DeclContextOffsets[Ctx.getTranslationUnitDecl()].swap(T);
+ }
+
+ // Load the translation unit declaration
+ GetTranslationUnitDecl();
+
+ // Load the special types.
+ Context->setBuiltinVaListType(
+ GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST]));
+ if (unsigned Id = SpecialTypes[SPECIAL_TYPE_OBJC_ID])
+ Context->setObjCIdType(GetType(Id));
+ if (unsigned Sel = SpecialTypes[SPECIAL_TYPE_OBJC_SELECTOR])
+ Context->setObjCSelType(GetType(Sel));
+ if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL])
+ Context->setObjCProtoType(GetType(Proto));
+ if (unsigned Class = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS])
+ Context->setObjCClassType(GetType(Class));
+
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING])
+ Context->setCFConstantStringType(GetType(String));
+ if (unsigned FastEnum
+ = SpecialTypes[SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+ Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+ if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
+ QualType FileType = GetType(File);
+ if (FileType.isNull()) {
+ Error("FILE type is NULL");
+ return;
+ }
+ if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
+ Context->setFILEDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = FileType->getAs<TagType>();
+ if (!Tag) {
+ Error("Invalid FILE type in AST file");
+ return;
+ }
+ Context->setFILEDecl(Tag->getDecl());
+ }
+ }
+ if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_jmp_buf]) {
+ QualType Jmp_bufType = GetType(Jmp_buf);
+ if (Jmp_bufType.isNull()) {
+ Error("jmp_bug type is NULL");
+ return;
+ }
+ if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
+ Context->setjmp_bufDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = Jmp_bufType->getAs<TagType>();
+ if (!Tag) {
+ Error("Invalid jmp_buf type in AST file");
+ return;
+ }
+ Context->setjmp_bufDecl(Tag->getDecl());
+ }
+ }
+ if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_sigjmp_buf]) {
+ QualType Sigjmp_bufType = GetType(Sigjmp_buf);
+ if (Sigjmp_bufType.isNull()) {
+ Error("sigjmp_buf type is NULL");
+ return;
+ }
+ if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
+ Context->setsigjmp_bufDecl(Typedef->getDecl());
+ else {
+ const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
+ assert(Tag && "Invalid sigjmp_buf type in AST file");
+ Context->setsigjmp_bufDecl(Tag->getDecl());
+ }
+ }
+ if (unsigned ObjCIdRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION])
+ Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
+ if (unsigned ObjCClassRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
+ Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_BLOCK_DESCRIPTOR])
+ Context->setBlockDescriptorType(GetType(String));
+ if (unsigned String
+ = SpecialTypes[SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
+ Context->setBlockDescriptorExtendedType(GetType(String));
+ if (unsigned ObjCSelRedef
+ = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
+ Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef);
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_NS_CONSTANT_STRING])
+ Context->setNSConstantStringType(GetType(String));
+
+ if (SpecialTypes[SPECIAL_TYPE_INT128_INSTALLED])
+ Context->setInt128Installed();
+
+ ReadPragmaDiagnosticMappings(Context->getDiagnostics());
+
+ // If there were any CUDA special declarations, deserialize them.
+ if (!CUDASpecialDeclRefs.empty()) {
+ assert(CUDASpecialDeclRefs.size() == 1 && "More decl refs than expected!");
+ Context->setcudaConfigureCallDecl(
+ cast<FunctionDecl>(GetDecl(CUDASpecialDeclRefs[0])));
+ }
+}
+
+/// \brief Retrieve the name of the original source file name
+/// directly from the AST file, without actually loading the AST
+/// file.
+std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
+ Diagnostic &Diags) {
+ // Open the AST file.
+ std::string ErrStr;
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
+ if (!Buffer) {
+ Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
+ return std::string();
+ }
+
+ // Initialize the stream
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+ StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+ (const unsigned char *)Buffer->getBufferEnd());
+ Stream.init(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
+ return std::string();
+ }
+
+ RecordData Record;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the AST subblock ID.
+ switch (BlockID) {
+ case AST_BLOCK_ID:
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+ return std::string();
+ }
+ break;
+
+ default:
+ if (Stream.SkipBlock()) {
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
+ return std::string();
+ }
+ break;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;
+ return std::string();
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
+ == ORIGINAL_FILE_NAME)
+ return std::string(BlobStart, BlobLen);
+ }
+
+ return std::string();
+}
+
+/// \brief Parse the record that corresponds to a LangOptions data
+/// structure.
+///
+/// This routine parses the language options from the AST file and then gives
+/// them to the AST listener if one is set.
+///
+/// \returns true if the listener deems the file unacceptable, false otherwise.
+bool ASTReader::ParseLanguageOptions(
+ const llvm::SmallVectorImpl<uint64_t> &Record) {
+ if (Listener) {
+ LangOptions LangOpts;
+
+ #define PARSE_LANGOPT(Option) \
+ LangOpts.Option = Record[Idx]; \
+ ++Idx
+
+ unsigned Idx = 0;
+ PARSE_LANGOPT(Trigraphs);
+ PARSE_LANGOPT(BCPLComment);
+ PARSE_LANGOPT(DollarIdents);
+ PARSE_LANGOPT(AsmPreprocessor);
+ PARSE_LANGOPT(GNUMode);
+ PARSE_LANGOPT(GNUKeywords);
+ PARSE_LANGOPT(ImplicitInt);
+ PARSE_LANGOPT(Digraphs);
+ PARSE_LANGOPT(HexFloats);
+ PARSE_LANGOPT(C99);
+ PARSE_LANGOPT(Microsoft);
+ PARSE_LANGOPT(CPlusPlus);
+ PARSE_LANGOPT(CPlusPlus0x);
+ PARSE_LANGOPT(CXXOperatorNames);
+ PARSE_LANGOPT(ObjC1);
+ PARSE_LANGOPT(ObjC2);
+ PARSE_LANGOPT(ObjCNonFragileABI);
+ PARSE_LANGOPT(ObjCNonFragileABI2);
+ PARSE_LANGOPT(AppleKext);
+ PARSE_LANGOPT(ObjCDefaultSynthProperties);
+ PARSE_LANGOPT(NoConstantCFStrings);
+ PARSE_LANGOPT(PascalStrings);
+ PARSE_LANGOPT(WritableStrings);
+ PARSE_LANGOPT(LaxVectorConversions);
+ PARSE_LANGOPT(AltiVec);
+ PARSE_LANGOPT(Exceptions);
+ PARSE_LANGOPT(SjLjExceptions);
+ PARSE_LANGOPT(ObjCExceptions);
+ PARSE_LANGOPT(MSBitfields);
+ PARSE_LANGOPT(NeXTRuntime);
+ PARSE_LANGOPT(Freestanding);
+ PARSE_LANGOPT(NoBuiltin);
+ PARSE_LANGOPT(ThreadsafeStatics);
+ PARSE_LANGOPT(POSIXThreads);
+ PARSE_LANGOPT(Blocks);
+ PARSE_LANGOPT(EmitAllDecls);
+ PARSE_LANGOPT(MathErrno);
+ LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy)
+ Record[Idx++]);
+ PARSE_LANGOPT(HeinousExtensions);
+ PARSE_LANGOPT(Optimize);
+ PARSE_LANGOPT(OptimizeSize);
+ PARSE_LANGOPT(Static);
+ PARSE_LANGOPT(PICLevel);
+ PARSE_LANGOPT(GNUInline);
+ PARSE_LANGOPT(NoInline);
+ PARSE_LANGOPT(AccessControl);
+ PARSE_LANGOPT(CharIsSigned);
+ PARSE_LANGOPT(ShortWChar);
+ PARSE_LANGOPT(ShortEnums);
+ LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]);
+ LangOpts.setVisibilityMode((Visibility)Record[Idx++]);
+ LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
+ Record[Idx++]);
+ PARSE_LANGOPT(InstantiationDepth);
+ PARSE_LANGOPT(OpenCL);
+ PARSE_LANGOPT(CUDA);
+ PARSE_LANGOPT(CatchUndefined);
+ PARSE_LANGOPT(DefaultFPContract);
+ // FIXME: Missing ElideConstructors?!
+ #undef PARSE_LANGOPT
+
+ return Listener->ReadLanguageOptions(LangOpts);
+ }
+
+ return false;
+}
+
+void ASTReader::ReadPreprocessedEntities() {
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ if (!F.PreprocessorDetailCursor.getBitStreamReader())
+ continue;
+
+ SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor);
+ F.PreprocessorDetailCursor.JumpToBit(F.PreprocessorDetailStartOffset);
+ while (LoadPreprocessedEntity(F)) { }
+ }
+}
+
+PreprocessedEntity *ASTReader::ReadPreprocessedEntityAtOffset(uint64_t Offset) {
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Offset < Chain[I]->SizeInBits) {
+ F = Chain[I];
+ break;
+ }
+
+ Offset -= Chain[I]->SizeInBits;
+ }
+
+ if (!F) {
+ Error("Malformed preprocessed entity offset");
+ return 0;
+ }
+
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this entity.
+ SavedStreamPosition SavedPosition(F->PreprocessorDetailCursor);
+ F->PreprocessorDetailCursor.JumpToBit(Offset);
+ return LoadPreprocessedEntity(*F);
+}
+
+HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
+ HeaderFileInfoTrait Trait(FE->getName());
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ HeaderFileInfoLookupTable *Table
+ = static_cast<HeaderFileInfoLookupTable *>(F.HeaderFileInfoTable);
+ if (!Table)
+ continue;
+
+ // Look in the on-disk hash table for an entry for this file name.
+ HeaderFileInfoLookupTable::iterator Pos = Table->find(FE->getName(),
+ &Trait);
+ if (Pos == Table->end())
+ continue;
+
+ HeaderFileInfo HFI = *Pos;
+ if (Listener)
+ Listener->ReadHeaderFileInfo(HFI, FE->getUID());
+
+ return HFI;
+ }
+
+ return HeaderFileInfo();
+}
+
+void ASTReader::ReadPragmaDiagnosticMappings(Diagnostic &Diag) {
+ unsigned Idx = 0;
+ while (Idx < PragmaDiagMappings.size()) {
+ SourceLocation
+ Loc = SourceLocation::getFromRawEncoding(PragmaDiagMappings[Idx++]);
+ while (1) {
+ assert(Idx < PragmaDiagMappings.size() &&
+ "Invalid data, didn't find '-1' marking end of diag/map pairs");
+ if (Idx >= PragmaDiagMappings.size())
+ break; // Something is messed up but at least avoid infinite loop in
+ // release build.
+ unsigned DiagID = PragmaDiagMappings[Idx++];
+ if (DiagID == (unsigned)-1)
+ break; // no more diag/map pairs for this location.
+ diag::Mapping Map = (diag::Mapping)PragmaDiagMappings[Idx++];
+ Diag.setDiagnosticMapping(DiagID, Map, Loc);
+ }
+ }
+}
+
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (Index < F->LocalNumTypes)
+ break;
+ Index -= F->LocalNumTypes;
+ }
+ assert(F && F->LocalNumTypes > Index && "Broken chain");
+ return RecordLocation(F, F->TypeOffsets[Index]);
+}
+
+/// \brief Read and return the type with the given index..
+///
+/// The index is the type ID, shifted and minus the number of predefs. This
+/// routine actually reads the record corresponding to the type at the given
+/// location. It is a helper routine for GetType, which deals with reading type
+/// IDs.
+QualType ASTReader::ReadTypeRecord(unsigned Index) {
+ RecordLocation Loc = TypeCursorForIndex(Index);
+ llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
+
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this type.
+ SavedStreamPosition SavedPosition(DeclsCursor);
+
+ ReadingKindTracker ReadingKind(Read_Type, *this);
+
+ // Note that we are loading a type record.
+ Deserializing AType(this);
+
+ DeclsCursor.JumpToBit(Loc.Offset);
+ RecordData Record;
+ unsigned Code = DeclsCursor.ReadCode();
+ switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
+ case TYPE_EXT_QUAL: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of extended qualifier type");
+ return QualType();
+ }
+ QualType Base = GetType(Record[0]);
+ Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
+ return Context->getQualifiedType(Base, Quals);
+ }
+
+ case TYPE_COMPLEX: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of complex type");
+ return QualType();
+ }
+ QualType ElemType = GetType(Record[0]);
+ return Context->getComplexType(ElemType);
+ }
+
+ case TYPE_POINTER: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of pointer type");
+ return QualType();
+ }
+ QualType PointeeType = GetType(Record[0]);
+ return Context->getPointerType(PointeeType);
+ }
+
+ case TYPE_BLOCK_POINTER: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of block pointer type");
+ return QualType();
+ }
+ QualType PointeeType = GetType(Record[0]);
+ return Context->getBlockPointerType(PointeeType);
+ }
+
+ case TYPE_LVALUE_REFERENCE: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of lvalue reference type");
+ return QualType();
+ }
+ QualType PointeeType = GetType(Record[0]);
+ return Context->getLValueReferenceType(PointeeType);
+ }
+
+ case TYPE_RVALUE_REFERENCE: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of rvalue reference type");
+ return QualType();
+ }
+ QualType PointeeType = GetType(Record[0]);
+ return Context->getRValueReferenceType(PointeeType);
+ }
+
+ case TYPE_MEMBER_POINTER: {
+ if (Record.size() != 2) {
+ Error("Incorrect encoding of member pointer type");
+ return QualType();
+ }
+ QualType PointeeType = GetType(Record[0]);
+ QualType ClassType = GetType(Record[1]);
+ if (PointeeType.isNull() || ClassType.isNull())
+ return QualType();
+
+ return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
+ }
+
+ case TYPE_CONSTANT_ARRAY: {
+ QualType ElementType = GetType(Record[0]);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ unsigned Idx = 3;
+ llvm::APInt Size = ReadAPInt(Record, Idx);
+ return Context->getConstantArrayType(ElementType, Size,
+ ASM, IndexTypeQuals);
+ }
+
+ case TYPE_INCOMPLETE_ARRAY: {
+ QualType ElementType = GetType(Record[0]);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
+ }
+
+ case TYPE_VARIABLE_ARRAY: {
+ QualType ElementType = GetType(Record[0]);
+ ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
+ unsigned IndexTypeQuals = Record[2];
+ SourceLocation LBLoc = ReadSourceLocation(*Loc.F, Record[3]);
+ SourceLocation RBLoc = ReadSourceLocation(*Loc.F, Record[4]);
+ return Context->getVariableArrayType(ElementType, ReadExpr(*Loc.F),
+ ASM, IndexTypeQuals,
+ SourceRange(LBLoc, RBLoc));
+ }
+
+ case TYPE_VECTOR: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of vector type in AST file");
+ return QualType();
+ }
+
+ QualType ElementType = GetType(Record[0]);
+ unsigned NumElements = Record[1];
+ unsigned VecKind = Record[2];
+ return Context->getVectorType(ElementType, NumElements,
+ (VectorType::VectorKind)VecKind);
+ }
+
+ case TYPE_EXT_VECTOR: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of extended vector type in AST file");
+ return QualType();
+ }
+
+ QualType ElementType = GetType(Record[0]);
+ unsigned NumElements = Record[1];
+ return Context->getExtVectorType(ElementType, NumElements);
+ }
+
+ case TYPE_FUNCTION_NO_PROTO: {
+ if (Record.size() != 4) {
+ Error("incorrect encoding of no-proto function type");
+ return QualType();
+ }
+ QualType ResultType = GetType(Record[0]);
+ FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]);
+ return Context->getFunctionNoProtoType(ResultType, Info);
+ }
+
+ case TYPE_FUNCTION_PROTO: {
+ QualType ResultType = GetType(Record[0]);
+
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],
+ /*regparm*/ Record[2],
+ static_cast<CallingConv>(Record[3]));
+
+ unsigned Idx = 4;
+ unsigned NumParams = Record[Idx++];
+ llvm::SmallVector<QualType, 16> ParamTypes;
+ for (unsigned I = 0; I != NumParams; ++I)
+ ParamTypes.push_back(GetType(Record[Idx++]));
+
+ EPI.Variadic = Record[Idx++];
+ EPI.TypeQuals = Record[Idx++];
+ EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
+ EPI.HasExceptionSpec = Record[Idx++];
+ EPI.HasAnyExceptionSpec = Record[Idx++];
+ EPI.NumExceptions = Record[Idx++];
+ llvm::SmallVector<QualType, 2> Exceptions;
+ for (unsigned I = 0; I != EPI.NumExceptions; ++I)
+ Exceptions.push_back(GetType(Record[Idx++]));
+ EPI.Exceptions = Exceptions.data();
+ return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
+ EPI);
+ }
+
+ case TYPE_UNRESOLVED_USING:
+ return Context->getTypeDeclType(
+ cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
+ case TYPE_TYPEDEF: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of typedef type");
+ return QualType();
+ }
+ TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0]));
+ QualType Canonical = GetType(Record[1]);
+ if (!Canonical.isNull())
+ Canonical = Context->getCanonicalType(Canonical);
+ return Context->getTypedefType(Decl, Canonical);
+ }
+
+ case TYPE_TYPEOF_EXPR:
+ return Context->getTypeOfExprType(ReadExpr(*Loc.F));
+
+ case TYPE_TYPEOF: {
+ if (Record.size() != 1) {
+ Error("incorrect encoding of typeof(type) in AST file");
+ return QualType();
+ }
+ QualType UnderlyingType = GetType(Record[0]);
+ return Context->getTypeOfType(UnderlyingType);
+ }
+
+ case TYPE_DECLTYPE:
+ return Context->getDecltypeType(ReadExpr(*Loc.F));
+
+ case TYPE_AUTO:
+ return Context->getAutoType(GetType(Record[0]));
+
+ case TYPE_RECORD: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of record type");
+ return QualType();
+ }
+ bool IsDependent = Record[0];
+ QualType T = Context->getRecordType(cast<RecordDecl>(GetDecl(Record[1])));
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+
+ case TYPE_ENUM: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of enum type");
+ return QualType();
+ }
+ bool IsDependent = Record[0];
+ QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1])));
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+
+ case TYPE_ATTRIBUTED: {
+ if (Record.size() != 3) {
+ Error("incorrect encoding of attributed type");
+ return QualType();
+ }
+ QualType modifiedType = GetType(Record[0]);
+ QualType equivalentType = GetType(Record[1]);
+ AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
+ return Context->getAttributedType(kind, modifiedType, equivalentType);
+ }
+
+ case TYPE_PAREN: {
+ if (Record.size() != 1) {
+ Error("incorrect encoding of paren type");
+ return QualType();
+ }
+ QualType InnerType = GetType(Record[0]);
+ return Context->getParenType(InnerType);
+ }
+
+ case TYPE_PACK_EXPANSION: {
+ if (Record.size() != 2) {
+ Error("incorrect encoding of pack expansion type");
+ return QualType();
+ }
+ QualType Pattern = GetType(Record[0]);
+ if (Pattern.isNull())
+ return QualType();
+ llvm::Optional<unsigned> NumExpansions;
+ if (Record[1])
+ NumExpansions = Record[1] - 1;
+ return Context->getPackExpansionType(Pattern, NumExpansions);
+ }
+
+ case TYPE_ELABORATED: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+ QualType NamedType = GetType(Record[Idx++]);
+ return Context->getElaboratedType(Keyword, NNS, NamedType);
+ }
+
+ case TYPE_OBJC_INTERFACE: {
+ unsigned Idx = 0;
+ ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
+ return Context->getObjCInterfaceType(ItfD);
+ }
+
+ case TYPE_OBJC_OBJECT: {
+ unsigned Idx = 0;
+ QualType Base = GetType(Record[Idx++]);
+ unsigned NumProtos = Record[Idx++];
+ llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
+ for (unsigned I = 0; I != NumProtos; ++I)
+ Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
+ return Context->getObjCObjectType(Base, Protos.data(), NumProtos);
+ }
+
+ case TYPE_OBJC_OBJECT_POINTER: {
+ unsigned Idx = 0;
+ QualType Pointee = GetType(Record[Idx++]);
+ return Context->getObjCObjectPointerType(Pointee);
+ }
+
+ case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+ unsigned Idx = 0;
+ QualType Parm = GetType(Record[Idx++]);
+ QualType Replacement = GetType(Record[Idx++]);
+ return
+ Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+ Replacement);
+ }
+
+ case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
+ unsigned Idx = 0;
+ QualType Parm = GetType(Record[Idx++]);
+ TemplateArgument ArgPack = ReadTemplateArgument(*Loc.F, Record, Idx);
+ return Context->getSubstTemplateTypeParmPackType(
+ cast<TemplateTypeParmType>(Parm),
+ ArgPack);
+ }
+
+ case TYPE_INJECTED_CLASS_NAME: {
+ CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0]));
+ QualType TST = GetType(Record[1]); // probably derivable
+ // FIXME: ASTContext::getInjectedClassNameType is not currently suitable
+ // for AST reading, too much interdependencies.
+ return
+ QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
+ }
+
+ case TYPE_TEMPLATE_TYPE_PARM: {
+ unsigned Idx = 0;
+ unsigned Depth = Record[Idx++];
+ unsigned Index = Record[Idx++];
+ bool Pack = Record[Idx++];
+ IdentifierInfo *Name = GetIdentifierInfo(Record, Idx);
+ return Context->getTemplateTypeParmType(Depth, Index, Pack, Name);
+ }
+
+ case TYPE_DEPENDENT_NAME: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+ const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
+ QualType Canon = GetType(Record[Idx++]);
+ if (!Canon.isNull())
+ Canon = Context->getCanonicalType(Canon);
+ return Context->getDependentNameType(Keyword, NNS, Name, Canon);
+ }
+
+ case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
+ unsigned Idx = 0;
+ ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+ const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx);
+ unsigned NumArgs = Record[Idx++];
+ llvm::SmallVector<TemplateArgument, 8> Args;
+ Args.reserve(NumArgs);
+ while (NumArgs--)
+ Args.push_back(ReadTemplateArgument(*Loc.F, Record, Idx));
+ return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name,
+ Args.size(), Args.data());
+ }
+
+ case TYPE_DEPENDENT_SIZED_ARRAY: {
+ unsigned Idx = 0;
+
+ // ArrayType
+ QualType ElementType = GetType(Record[Idx++]);
+ ArrayType::ArraySizeModifier ASM
+ = (ArrayType::ArraySizeModifier)Record[Idx++];
+ unsigned IndexTypeQuals = Record[Idx++];
+
+ // DependentSizedArrayType
+ Expr *NumElts = ReadExpr(*Loc.F);
+ SourceRange Brackets = ReadSourceRange(*Loc.F, Record, Idx);
+
+ return Context->getDependentSizedArrayType(ElementType, NumElts, ASM,
+ IndexTypeQuals, Brackets);
+ }
+
+ case TYPE_TEMPLATE_SPECIALIZATION: {
+ unsigned Idx = 0;
+ bool IsDependent = Record[Idx++];
+ TemplateName Name = ReadTemplateName(*Loc.F, Record, Idx);
+ llvm::SmallVector<TemplateArgument, 8> Args;
+ ReadTemplateArgumentList(Args, *Loc.F, Record, Idx);
+ QualType Canon = GetType(Record[Idx++]);
+ QualType T;
+ if (Canon.isNull())
+ T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(),
+ Args.size());
+ else
+ T = Context->getTemplateSpecializationType(Name, Args.data(),
+ Args.size(), Canon);
+ const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
+ return T;
+ }
+ }
+ // Suppress a GCC warning
+ return QualType();
+}
+
+class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+ ASTReader &Reader;
+ ASTReader::PerFileData &F;
+ llvm::BitstreamCursor &DeclsCursor;
+ const ASTReader::RecordData &Record;
+ unsigned &Idx;
+
+ SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
+ unsigned &I) {
+ return Reader.ReadSourceLocation(F, R, I);
+ }
+
+public:
+ TypeLocReader(ASTReader &Reader, ASTReader::PerFileData &F,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : Reader(Reader), F(F), DeclsCursor(F.DeclsCursor), Record(Record), Idx(Idx)
+ { }
+
+ // We want compile-time assurance that we've enumerated all of
+ // these, so unfortunately we have to declare them first, then
+ // define them out-of-line.
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ void VisitFunctionTypeLoc(FunctionTypeLoc);
+ void VisitArrayTypeLoc(ArrayTypeLoc);
+};
+
+void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ // nothing to do
+}
+void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ if (TL.needsExtraLocalData()) {
+ TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
+ TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
+ TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++]));
+ TL.setModeAttr(Record[Idx++]);
+ }
+}
+void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ TL.setCaretLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ TL.setAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ TL.setLBracketLoc(ReadSourceLocation(Record, Idx));
+ TL.setRBracketLoc(ReadSourceLocation(Record, Idx));
+ if (Record[Idx++])
+ TL.setSizeExpr(Reader.ReadExpr(F));
+ else
+ TL.setSizeExpr(0);
+}
+void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedArrayTypeLoc(
+ DependentSizedArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
+ DependentSizedExtVectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setTrailingReturn(Record[Idx++]);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+ TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ }
+}
+void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+}
+void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
+ if (TL.hasAttrOperand()) {
+ SourceRange range;
+ range.setBegin(ReadSourceLocation(Record, Idx));
+ range.setEnd(ReadSourceLocation(Record, Idx));
+ TL.setAttrOperandParensRange(range);
+ }
+ if (TL.hasAttrExprOperand()) {
+ if (Record[Idx++])
+ TL.setAttrExprOperand(Reader.ReadExpr(F));
+ else
+ TL.setAttrExprOperand(0);
+ } else if (TL.hasAttrEnumOperand())
+ TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ TL.setArgLocInfo(i,
+ Reader.GetTemplateArgumentLocInfo(F,
+ TL.getTypePtr()->getArg(i).getKind(),
+ Record, Idx));
+}
+void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ TL.setKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx));
+}
+void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ TL.setKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx));
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ TL.setKeywordLoc(ReadSourceLocation(Record, Idx));
+ TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx));
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ TL.setArgLocInfo(I,
+ Reader.GetTemplateArgumentLocInfo(F,
+ TL.getTypePtr()->getArg(I).getKind(),
+ Record, Idx));
+}
+void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ TL.setHasBaseTypeAsWritten(Record[Idx++]);
+ TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
+}
+void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ TL.setStarLoc(ReadSourceLocation(Record, Idx));
+}
+
+TypeSourceInfo *ASTReader::GetTypeSourceInfo(PerFileData &F,
+ const RecordData &Record,
+ unsigned &Idx) {
+ QualType InfoTy = GetType(Record[Idx++]);
+ if (InfoTy.isNull())
+ return 0;
+
+ TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy);
+ TypeLocReader TLR(*this, F, Record, Idx);
+ for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLR.Visit(TL);
+ return TInfo;
+}
+
+QualType ASTReader::GetType(TypeID ID) {
+ unsigned FastQuals = ID & Qualifiers::FastMask;
+ unsigned Index = ID >> Qualifiers::FastWidth;
+
+ if (Index < NUM_PREDEF_TYPE_IDS) {
+ QualType T;
+ switch ((PredefinedTypeIDs)Index) {
+ case PREDEF_TYPE_NULL_ID: return QualType();
+ case PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
+ case PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
+
+ case PREDEF_TYPE_CHAR_U_ID:
+ case PREDEF_TYPE_CHAR_S_ID:
+ // FIXME: Check that the signedness of CharTy is correct!
+ T = Context->CharTy;
+ break;
+
+ case PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
+ case PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
+ case PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
+ case PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
+ case PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
+ case PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
+ case PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
+ case PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
+ case PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
+ case PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
+ case PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
+ case PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
+ case PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
+ case PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
+ case PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
+ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
+ case PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
+ case PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
+ case PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
+ case PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
+ case PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
+ case PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
+ case PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
+ case PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break;
+ }
+
+ assert(!T.isNull() && "Unknown predefined type");
+ return T.withFastQualifiers(FastQuals);
+ }
+
+ Index -= NUM_PREDEF_TYPE_IDS;
+ assert(Index < TypesLoaded.size() && "Type index out-of-range");
+ if (TypesLoaded[Index].isNull()) {
+ TypesLoaded[Index] = ReadTypeRecord(Index);
+ if (TypesLoaded[Index].isNull())
+ return QualType();
+
+ TypesLoaded[Index]->setFromAST();
+ TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID);
+ if (DeserializationListener)
+ DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
+ TypesLoaded[Index]);
+ }
+
+ return TypesLoaded[Index].withFastQualifiers(FastQuals);
+}
+
+TypeID ASTReader::GetTypeID(QualType T) const {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTReader::GetTypeIdx), this));
+}
+
+TypeIdx ASTReader::GetTypeIdx(QualType T) const {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
+
+ TypeIdxMap::const_iterator I = TypeIdxs.find(T);
+ // GetTypeIdx is mostly used for computing the hash of DeclarationNames and
+ // comparing keys of ASTDeclContextNameLookupTable.
+ // If the type didn't come from the AST file use a specially marked index
+ // so that any hash/key comparison fail since no such index is stored
+ // in a AST file.
+ if (I == TypeIdxs.end())
+ return TypeIdx(-1);
+ return I->second;
+}
+
+unsigned ASTReader::getTotalNumCXXBaseSpecifiers() const {
+ unsigned Result = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I)
+ Result += Chain[I]->LocalNumCXXBaseSpecifiers;
+
+ return Result;
+}
+
+TemplateArgumentLocInfo
+ASTReader::GetTemplateArgumentLocInfo(PerFileData &F,
+ TemplateArgument::ArgKind Kind,
+ const RecordData &Record,
+ unsigned &Index) {
+ switch (Kind) {
+ case TemplateArgument::Expression:
+ return ReadExpr(F);
+ case TemplateArgument::Type:
+ return GetTypeSourceInfo(F, Record, Index);
+ case TemplateArgument::Template: {
+ SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+ SourceLocation());
+ }
+ case TemplateArgument::TemplateExpansion: {
+ SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+ EllipsisLoc);
+ }
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ return TemplateArgumentLocInfo();
+ }
+ llvm_unreachable("unexpected template argument loc");
+ return TemplateArgumentLocInfo();
+}
+
+TemplateArgumentLoc
+ASTReader::ReadTemplateArgumentLoc(PerFileData &F,
+ const RecordData &Record, unsigned &Index) {
+ TemplateArgument Arg = ReadTemplateArgument(F, Record, Index);
+
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ if (Record[Index++]) // bool InfoHasSameExpr.
+ return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
+ }
+ return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(F, Arg.getKind(),
+ Record, Index));
+}
+
+Decl *ASTReader::GetExternalDecl(uint32_t ID) {
+ return GetDecl(ID);
+}
+
+uint64_t
+ASTReader::GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID) {
+ if (ID == 0)
+ return 0;
+
+ --ID;
+ uint64_t Offset = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (ID < Chain[I]->LocalNumCXXBaseSpecifiers)
+ return Offset + Chain[I]->CXXBaseSpecifiersOffsets[ID];
+
+ ID -= Chain[I]->LocalNumCXXBaseSpecifiers;
+ Offset += Chain[I]->SizeInBits;
+ }
+
+ assert(false && "CXXBaseSpecifiers not found");
+ return 0;
+}
+
+CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
+ // Figure out which AST file contains this offset.
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (Offset < Chain[I]->SizeInBits) {
+ F = Chain[I];
+ break;
+ }
+
+ Offset -= Chain[I]->SizeInBits;
+ }
+
+ if (!F) {
+ Error("Malformed AST file: C++ base specifiers at impossible offset");
+ return 0;
+ }
+
+ llvm::BitstreamCursor &Cursor = F->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record);
+ if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
+ Error("Malformed AST file: missing C++ base specifiers");
+ return 0;
+ }
+
+ unsigned Idx = 0;
+ unsigned NumBases = Record[Idx++];
+ void *Mem = Context->Allocate(sizeof(CXXBaseSpecifier) * NumBases);
+ CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases];
+ for (unsigned I = 0; I != NumBases; ++I)
+ Bases[I] = ReadCXXBaseSpecifier(*F, Record, Idx);
+ return Bases;
+}
+
+TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() {
+ if (!DeclsLoaded[0]) {
+ ReadDeclRecord(0, 1);
+ if (DeserializationListener)
+ DeserializationListener->DeclRead(1, DeclsLoaded[0]);
+ }
+
+ return cast<TranslationUnitDecl>(DeclsLoaded[0]);
+}
+
+Decl *ASTReader::GetDecl(DeclID ID) {
+ if (ID == 0)
+ return 0;
+
+ if (ID > DeclsLoaded.size()) {
+ Error("declaration ID out-of-range for AST file");
+ return 0;
+ }
+
+ unsigned Index = ID - 1;
+ if (!DeclsLoaded[Index]) {
+ ReadDeclRecord(Index, ID);
+ if (DeserializationListener)
+ DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
+ }
+
+ return DeclsLoaded[Index];
+}
+
+/// \brief Resolve the offset of a statement into a statement.
+///
+/// This operation will read a new statement from the external
+/// source each time it is called, and is meant to be used via a
+/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
+ // Switch case IDs are per Decl.
+ ClearSwitchCaseIDs();
+
+ // Offset here is a global offset across the entire chain.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Offset < F.SizeInBits) {
+ // Since we know that this statement is part of a decl, make sure to use
+ // the decl cursor to read it.
+ F.DeclsCursor.JumpToBit(Offset);
+ return ReadStmtFromStream(F);
+ }
+ Offset -= F.SizeInBits;
+ }
+ llvm_unreachable("Broken chain");
+}
+
+bool ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ llvm::SmallVectorImpl<Decl*> &Decls) {
+ assert(DC->hasExternalLexicalStorage() &&
+ "DeclContext has no lexical decls in storage");
+
+ // There might be lexical decls in multiple parts of the chain, for the TU
+ // at least.
+ // DeclContextOffsets might reallocate as we load additional decls below,
+ // so make a copy of the vector.
+ DeclContextInfos Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
+ I != E; ++I) {
+ // IDs can be 0 if this context doesn't contain declarations.
+ if (!I->LexicalDecls)
+ continue;
+
+ // Load all of the declaration IDs
+ for (const KindDeclIDPair *ID = I->LexicalDecls,
+ *IDE = ID + I->NumLexicalDecls; ID != IDE; ++ID) {
+ if (isKindWeWant && !isKindWeWant((Decl::Kind)ID->first))
+ continue;
+
+ Decl *D = GetDecl(ID->second);
+ assert(D && "Null decl in lexical decls");
+ Decls.push_back(D);
+ }
+ }
+
+ ++NumLexicalDeclContextsRead;
+ return false;
+}
+
+DeclContext::lookup_result
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) {
+ assert(DC->hasExternalVisibleStorage() &&
+ "DeclContext has no visible decls in storage");
+ if (!Name)
+ return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
+ DeclContext::lookup_iterator(0));
+
+ llvm::SmallVector<NamedDecl *, 64> Decls;
+ // There might be visible decls in multiple parts of the chain, for the TU
+ // and namespaces. For any given name, the last available results replace
+ // all earlier ones. For this reason, we walk in reverse.
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::reverse_iterator I = Infos.rbegin(), E = Infos.rend();
+ I != E; ++I) {
+ if (!I->NameLookupTableData)
+ continue;
+
+ ASTDeclContextNameLookupTable *LookupTable =
+ (ASTDeclContextNameLookupTable*)I->NameLookupTableData;
+ ASTDeclContextNameLookupTable::iterator Pos = LookupTable->find(Name);
+ if (Pos == LookupTable->end())
+ continue;
+
+ ASTDeclContextNameLookupTrait::data_type Data = *Pos;
+ for (; Data.first != Data.second; ++Data.first)
+ Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first)));
+ break;
+ }
+
+ ++NumVisibleDeclContextsRead;
+
+ SetExternalVisibleDeclsForName(DC, Name, Decls);
+ return const_cast<DeclContext*>(DC)->lookup(Name);
+}
+
+void ASTReader::MaterializeVisibleDecls(const DeclContext *DC) {
+ assert(DC->hasExternalVisibleStorage() &&
+ "DeclContext has no visible decls in storage");
+
+ llvm::SmallVector<NamedDecl *, 64> Decls;
+ // There might be visible decls in multiple parts of the chain, for the TU
+ // and namespaces.
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
+ I != E; ++I) {
+ if (!I->NameLookupTableData)
+ continue;
+
+ ASTDeclContextNameLookupTable *LookupTable =
+ (ASTDeclContextNameLookupTable*)I->NameLookupTableData;
+ for (ASTDeclContextNameLookupTable::item_iterator
+ ItemI = LookupTable->item_begin(),
+ ItemEnd = LookupTable->item_end() ; ItemI != ItemEnd; ++ItemI) {
+ ASTDeclContextNameLookupTable::item_iterator::value_type Val
+ = *ItemI;
+ ASTDeclContextNameLookupTrait::data_type Data = Val.second;
+ Decls.clear();
+ for (; Data.first != Data.second; ++Data.first)
+ Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first)));
+ MaterializeVisibleDeclsForName(DC, Val.first, Decls);
+ }
+ }
+}
+
+void ASTReader::PassInterestingDeclsToConsumer() {
+ assert(Consumer);
+ while (!InterestingDecls.empty()) {
+ DeclGroupRef DG(InterestingDecls.front());
+ InterestingDecls.pop_front();
+ Consumer->HandleInterestingDecl(DG);
+ }
+}
+
+void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
+ this->Consumer = Consumer;
+
+ if (!Consumer)
+ return;
+
+ for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
+ // Force deserialization of this decl, which will cause it to be queued for
+ // passing to the consumer.
+ GetDecl(ExternalDefinitions[I]);
+ }
+
+ PassInterestingDeclsToConsumer();
+}
+
+void ASTReader::PrintStats() {
+ std::fprintf(stderr, "*** AST File Statistics:\n");
+
+ unsigned NumTypesLoaded
+ = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
+ QualType());
+ unsigned NumDeclsLoaded
+ = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
+ (Decl *)0);
+ unsigned NumIdentifiersLoaded
+ = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
+ IdentifiersLoaded.end(),
+ (IdentifierInfo *)0);
+ unsigned NumSelectorsLoaded
+ = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
+ SelectorsLoaded.end(),
+ Selector());
+
+ std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
+ std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
+ if (TotalNumSLocEntries)
+ std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
+ NumSLocEntriesRead, TotalNumSLocEntries,
+ ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
+ if (!TypesLoaded.empty())
+ std::fprintf(stderr, " %u/%u types read (%f%%)\n",
+ NumTypesLoaded, (unsigned)TypesLoaded.size(),
+ ((float)NumTypesLoaded/TypesLoaded.size() * 100));
+ if (!DeclsLoaded.empty())
+ std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
+ NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
+ ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
+ if (!IdentifiersLoaded.empty())
+ std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
+ NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
+ ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
+ if (!SelectorsLoaded.empty())
+ std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
+ NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
+ ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
+ if (TotalNumStatements)
+ std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
+ NumStatementsRead, TotalNumStatements,
+ ((float)NumStatementsRead/TotalNumStatements * 100));
+ if (TotalNumMacros)
+ std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
+ NumMacrosRead, TotalNumMacros,
+ ((float)NumMacrosRead/TotalNumMacros * 100));
+ if (TotalLexicalDeclContexts)
+ std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
+ NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
+ ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
+ * 100));
+ if (TotalVisibleDeclContexts)
+ std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
+ NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
+ ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
+ * 100));
+ if (TotalNumMethodPoolEntries) {
+ std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
+ NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
+ ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
+ * 100));
+ std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
+ }
+ std::fprintf(stderr, "\n");
+}
+
+void ASTReader::InitializeSema(Sema &S) {
+ SemaObj = &S;
+ S.ExternalSource = this;
+
+ // Makes sure any declarations that were deserialized "too early"
+ // still get added to the identifier's declaration chains.
+ for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
+ if (SemaObj->TUScope)
+ SemaObj->TUScope->AddDecl(PreloadedDecls[I]);
+
+ SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
+ }
+ PreloadedDecls.clear();
+
+ // If there were any tentative definitions, deserialize them and add
+ // them to Sema's list of tentative definitions.
+ for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
+ VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
+ SemaObj->TentativeDefinitions.push_back(Var);
+ }
+
+ // If there were any unused file scoped decls, deserialize them and add to
+ // Sema's list of unused file scoped decls.
+ for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
+ DeclaratorDecl *D = cast<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
+ SemaObj->UnusedFileScopedDecls.push_back(D);
+ }
+
+ // If there were any locally-scoped external declarations,
+ // deserialize them and add them to Sema's table of locally-scoped
+ // external declarations.
+ for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
+ SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
+ }
+
+ // If there were any ext_vector type declarations, deserialize them
+ // and add them to Sema's vector of such declarations.
+ for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
+ SemaObj->ExtVectorDecls.push_back(
+ cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
+
+ // FIXME: Do VTable uses and dynamic classes deserialize too much ?
+ // Can we cut them down before writing them ?
+
+ // If there were any dynamic classes declarations, deserialize them
+ // and add them to Sema's vector of such declarations.
+ for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I)
+ SemaObj->DynamicClasses.push_back(
+ cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
+
+ // Load the offsets of the declarations that Sema references.
+ // They will be lazily deserialized when needed.
+ if (!SemaDeclRefs.empty()) {
+ assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
+ SemaObj->StdNamespace = SemaDeclRefs[0];
+ SemaObj->StdBadAlloc = SemaDeclRefs[1];
+ }
+
+ for (PerFileData *F = FirstInSource; F; F = F->NextInSource) {
+
+ // If there are @selector references added them to its pool. This is for
+ // implementation of -Wselector.
+ if (!F->ReferencedSelectorsData.empty()) {
+ unsigned int DataSize = F->ReferencedSelectorsData.size()-1;
+ unsigned I = 0;
+ while (I < DataSize) {
+ Selector Sel = DecodeSelector(F->ReferencedSelectorsData[I++]);
+ SourceLocation SelLoc = ReadSourceLocation(
+ *F, F->ReferencedSelectorsData, I);
+ SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+ }
+ }
+
+ // If there were any pending implicit instantiations, deserialize them
+ // and add them to Sema's queue of such instantiations.
+ assert(F->PendingInstantiations.size() % 2 == 0 &&
+ "Expected pairs of entries");
+ for (unsigned Idx = 0, N = F->PendingInstantiations.size(); Idx < N;) {
+ ValueDecl *D=cast<ValueDecl>(GetDecl(F->PendingInstantiations[Idx++]));
+ SourceLocation Loc = ReadSourceLocation(*F, F->PendingInstantiations,Idx);
+ SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc));
+ }
+ }
+
+ // The two special data sets below always come from the most recent PCH,
+ // which is at the front of the chain.
+ PerFileData &F = *Chain.front();
+
+ // If there were any weak undeclared identifiers, deserialize them and add to
+ // Sema's list of weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty()) {
+ unsigned Idx = 0;
+ for (unsigned I = 0, N = WeakUndeclaredIdentifiers[Idx++]; I != N; ++I) {
+ IdentifierInfo *WeakId = GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
+ IdentifierInfo *AliasId= GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
+ SourceLocation Loc = ReadSourceLocation(F, WeakUndeclaredIdentifiers,Idx);
+ bool Used = WeakUndeclaredIdentifiers[Idx++];
+ Sema::WeakInfo WI(AliasId, Loc);
+ WI.setUsed(Used);
+ SemaObj->WeakUndeclaredIdentifiers.insert(std::make_pair(WeakId, WI));
+ }
+ }
+
+ // If there were any VTable uses, deserialize the information and add it
+ // to Sema's vector and map of VTable uses.
+ if (!VTableUses.empty()) {
+ unsigned Idx = 0;
+ for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) {
+ CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
+ SourceLocation Loc = ReadSourceLocation(F, VTableUses, Idx);
+ bool DefinitionRequired = VTableUses[Idx++];
+ SemaObj->VTableUses.push_back(std::make_pair(Class, Loc));
+ SemaObj->VTablesUsed[Class] = DefinitionRequired;
+ }
+ }
+
+ if (!FPPragmaOptions.empty()) {
+ assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
+ SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
+ }
+
+ if (!OpenCLExtensions.empty()) {
+ unsigned I = 0;
+#define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
+#include "clang/Basic/OpenCLExtensions.def"
+
+ assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
+ }
+}
+
+IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+ // Try to find this name within our on-disk hash tables. We start with the
+ // most recent one, since that one contains the most up-to-date info.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Chain[I]->IdentifierLookupTable;
+ if (!IdTable)
+ continue;
+ std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
+ ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of building the
+ // IdentifierInfo node and populating it with the various
+ // declarations it needs.
+ return *Pos;
+ }
+ return 0;
+}
+
+namespace clang {
+ /// \brief An identifier-lookup iterator that enumerates all of the
+ /// identifiers stored within a set of AST files.
+ class ASTIdentifierIterator : public IdentifierIterator {
+ /// \brief The AST reader whose identifiers are being enumerated.
+ const ASTReader &Reader;
+
+ /// \brief The current index into the chain of AST files stored in
+ /// the AST reader.
+ unsigned Index;
+
+ /// \brief The current position within the identifier lookup table
+ /// of the current AST file.
+ ASTIdentifierLookupTable::key_iterator Current;
+
+ /// \brief The end position within the identifier lookup table of
+ /// the current AST file.
+ ASTIdentifierLookupTable::key_iterator End;
+
+ public:
+ explicit ASTIdentifierIterator(const ASTReader &Reader);
+
+ virtual llvm::StringRef Next();
+ };
+}
+
+ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader)
+ : Reader(Reader), Index(Reader.Chain.size() - 1) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Reader.Chain[Index]->IdentifierLookupTable;
+ Current = IdTable->key_begin();
+ End = IdTable->key_end();
+}
+
+llvm::StringRef ASTIdentifierIterator::Next() {
+ while (Current == End) {
+ // If we have exhausted all of our AST files, we're done.
+ if (Index == 0)
+ return llvm::StringRef();
+
+ --Index;
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Reader.Chain[Index]->IdentifierLookupTable;
+ Current = IdTable->key_begin();
+ End = IdTable->key_end();
+ }
+
+ // We have any identifiers remaining in the current AST file; return
+ // the next one.
+ std::pair<const char*, unsigned> Key = *Current;
+ ++Current;
+ return llvm::StringRef(Key.first, Key.second);
+}
+
+IdentifierIterator *ASTReader::getIdentifiers() const {
+ return new ASTIdentifierIterator(*this);
+}
+
+std::pair<ObjCMethodList, ObjCMethodList>
+ASTReader::ReadMethodPool(Selector Sel) {
+ // Find this selector in a hash table. We want to find the most recent entry.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ if (!F.SelectorLookupTable)
+ continue;
+
+ ASTSelectorLookupTable *PoolTable
+ = (ASTSelectorLookupTable*)F.SelectorLookupTable;
+ ASTSelectorLookupTable::iterator Pos = PoolTable->find(Sel);
+ if (Pos != PoolTable->end()) {
+ ++NumSelectorsRead;
+ // FIXME: Not quite happy with the statistics here. We probably should
+ // disable this tracking when called via LoadSelector.
+ // Also, should entries without methods count as misses?
+ ++NumMethodPoolEntriesRead;
+ ASTSelectorLookupTrait::data_type Data = *Pos;
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(Data.ID, Sel);
+ return std::make_pair(Data.Instance, Data.Factory);
+ }
+ }
+
+ ++NumMethodPoolMisses;
+ return std::pair<ObjCMethodList, ObjCMethodList>();
+}
+
+void ASTReader::LoadSelector(Selector Sel) {
+ // It would be complicated to avoid reading the methods anyway. So don't.
+ ReadMethodPool(Sel);
+}
+
+void ASTReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
+ assert(ID && "Non-zero identifier ID required");
+ assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
+ IdentifiersLoaded[ID - 1] = II;
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID, II);
+}
+
+/// \brief Set the globally-visible declarations associated with the given
+/// identifier.
+///
+/// If the AST reader is currently in a state where the given declaration IDs
+/// cannot safely be resolved, they are queued until it is safe to resolve
+/// them.
+///
+/// \param II an IdentifierInfo that refers to one or more globally-visible
+/// declarations.
+///
+/// \param DeclIDs the set of declaration IDs with the name @p II that are
+/// visible at global scope.
+///
+/// \param Nonrecursive should be true to indicate that the caller knows that
+/// this call is non-recursive, and therefore the globally-visible declarations
+/// will not be placed onto the pending queue.
+void
+ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+ const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
+ bool Nonrecursive) {
+ if (NumCurrentElementsDeserializing && !Nonrecursive) {
+ PendingIdentifierInfos.push_back(PendingIdentifierInfo());
+ PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
+ PII.II = II;
+ PII.DeclIDs.append(DeclIDs.begin(), DeclIDs.end());
+ return;
+ }
+
+ for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+ if (SemaObj) {
+ if (SemaObj->TUScope) {
+ // Introduce this declaration into the translation-unit scope
+ // and add it to the declaration chain for this identifier, so
+ // that (unqualified) name lookup will find it.
+ SemaObj->TUScope->AddDecl(D);
+ }
+ SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
+ } else {
+ // Queue this declaration so that it will be added to the
+ // translation unit scope and identifier's declaration chain
+ // once a Sema object is known.
+ PreloadedDecls.push_back(D);
+ }
+ }
+}
+
+IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) {
+ if (ID == 0)
+ return 0;
+
+ if (IdentifiersLoaded.empty()) {
+ Error("no identifier table in AST file");
+ return 0;
+ }
+
+ assert(PP && "Forgot to set Preprocessor ?");
+ ID -= 1;
+ if (!IdentifiersLoaded[ID]) {
+ unsigned Index = ID;
+ const char *Str = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData *F = Chain[N - I - 1];
+ if (Index < F->LocalNumIdentifiers) {
+ uint32_t Offset = F->IdentifierOffsets[Index];
+ Str = F->IdentifierTableData + Offset;
+ break;
+ }
+ Index -= F->LocalNumIdentifiers;
+ }
+ assert(Str && "Broken Chain");
+
+ // All of the strings in the AST file are preceded by a 16-bit length.
+ // Extract that 16-bit length to avoid having to execute strlen().
+ // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
+ // unsigned integers. This is important to avoid integer overflow when
+ // we cast them to 'unsigned'.
+ const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
+ unsigned StrLen = (((unsigned) StrLenPtr[0])
+ | (((unsigned) StrLenPtr[1]) << 8)) - 1;
+ IdentifiersLoaded[ID]
+ = &PP->getIdentifierTable().get(Str, StrLen);
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
+ }
+
+ return IdentifiersLoaded[ID];
+}
+
+void ASTReader::ReadSLocEntry(unsigned ID) {
+ ReadSLocEntryRecord(ID);
+}
+
+Selector ASTReader::DecodeSelector(unsigned ID) {
+ if (ID == 0)
+ return Selector();
+
+ if (ID > SelectorsLoaded.size()) {
+ Error("selector ID out of range in AST file");
+ return Selector();
+ }
+
+ if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
+ // Load this selector from the selector table.
+ unsigned Idx = ID - 1;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Idx < F.LocalNumSelectors) {
+ ASTSelectorLookupTrait Trait(*this);
+ SelectorsLoaded[ID - 1] =
+ Trait.ReadKey(F.SelectorLookupTableData + F.SelectorOffsets[Idx], 0);
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
+ break;
+ }
+ Idx -= F.LocalNumSelectors;
+ }
+ }
+
+ return SelectorsLoaded[ID - 1];
+}
+
+Selector ASTReader::GetExternalSelector(uint32_t ID) {
+ return DecodeSelector(ID);
+}
+
+uint32_t ASTReader::GetNumExternalSelectors() {
+ // ID 0 (the null selector) is considered an external selector.
+ return getTotalNumSelectors() + 1;
+}
+
+DeclarationName
+ASTReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
+ DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
+ switch (Kind) {
+ case DeclarationName::Identifier:
+ return DeclarationName(GetIdentifierInfo(Record, Idx));
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return DeclarationName(GetSelector(Record, Idx));
+
+ case DeclarationName::CXXConstructorName:
+ return Context->DeclarationNames.getCXXConstructorName(
+ Context->getCanonicalType(GetType(Record[Idx++])));
+
+ case DeclarationName::CXXDestructorName:
+ return Context->DeclarationNames.getCXXDestructorName(
+ Context->getCanonicalType(GetType(Record[Idx++])));
+
+ case DeclarationName::CXXConversionFunctionName:
+ return Context->DeclarationNames.getCXXConversionFunctionName(
+ Context->getCanonicalType(GetType(Record[Idx++])));
+
+ case DeclarationName::CXXOperatorName:
+ return Context->DeclarationNames.getCXXOperatorName(
+ (OverloadedOperatorKind)Record[Idx++]);
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return Context->DeclarationNames.getCXXLiteralOperatorName(
+ GetIdentifierInfo(Record, Idx));
+
+ case DeclarationName::CXXUsingDirective:
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ // Required to silence GCC warning
+ return DeclarationName();
+}
+
+void ASTReader::ReadDeclarationNameLoc(PerFileData &F,
+ DeclarationNameLoc &DNLoc,
+ DeclarationName Name,
+ const RecordData &Record, unsigned &Idx) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ DNLoc.NamedType.TInfo = GetTypeSourceInfo(F, Record, Idx);
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ DNLoc.CXXOperatorName.BeginOpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ DNLoc.CXXOperatorName.EndOpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ DNLoc.CXXLiteralOperatorName.OpNameLoc
+ = ReadSourceLocation(F, Record, Idx).getRawEncoding();
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+void ASTReader::ReadDeclarationNameInfo(PerFileData &F,
+ DeclarationNameInfo &NameInfo,
+ const RecordData &Record, unsigned &Idx) {
+ NameInfo.setName(ReadDeclarationName(Record, Idx));
+ NameInfo.setLoc(ReadSourceLocation(F, Record, Idx));
+ DeclarationNameLoc DNLoc;
+ ReadDeclarationNameLoc(F, DNLoc, NameInfo.getName(), Record, Idx);
+ NameInfo.setInfo(DNLoc);
+}
+
+void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
+ const RecordData &Record, unsigned &Idx) {
+ Info.NNS = ReadNestedNameSpecifier(Record, Idx);
+ Info.NNSRange = ReadSourceRange(F, Record, Idx);
+ unsigned NumTPLists = Record[Idx++];
+ Info.NumTemplParamLists = NumTPLists;
+ if (NumTPLists) {
+ Info.TemplParamLists = new (*Context) TemplateParameterList*[NumTPLists];
+ for (unsigned i=0; i != NumTPLists; ++i)
+ Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
+ }
+}
+
+TemplateName
+ASTReader::ReadTemplateName(PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
+ switch (Kind) {
+ case TemplateName::Template:
+ return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++])));
+
+ case TemplateName::OverloadedTemplate: {
+ unsigned size = Record[Idx++];
+ UnresolvedSet<8> Decls;
+ while (size--)
+ Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++])));
+
+ return Context->getOverloadedTemplateName(Decls.begin(), Decls.end());
+ }
+
+ case TemplateName::QualifiedTemplate: {
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+ bool hasTemplKeyword = Record[Idx++];
+ TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++]));
+ return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
+ }
+
+ case TemplateName::DependentTemplate: {
+ NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
+ if (Record[Idx++]) // isIdentifier
+ return Context->getDependentTemplateName(NNS,
+ GetIdentifierInfo(Record, Idx));
+ return Context->getDependentTemplateName(NNS,
+ (OverloadedOperatorKind)Record[Idx++]);
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ TemplateTemplateParmDecl *Param
+ = cast_or_null<TemplateTemplateParmDecl>(GetDecl(Record[Idx++]));
+ if (!Param)
+ return TemplateName();
+
+ TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
+ if (ArgPack.getKind() != TemplateArgument::Pack)
+ return TemplateName();
+
+ return Context->getSubstTemplateTemplateParmPack(Param, ArgPack);
+ }
+ }
+
+ assert(0 && "Unhandled template name kind!");
+ return TemplateName();
+}
+
+TemplateArgument
+ASTReader::ReadTemplateArgument(PerFileData &F,
+ const RecordData &Record, unsigned &Idx) {
+ TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+ switch (Kind) {
+ case TemplateArgument::Null:
+ return TemplateArgument();
+ case TemplateArgument::Type:
+ return TemplateArgument(GetType(Record[Idx++]));
+ case TemplateArgument::Declaration:
+ return TemplateArgument(GetDecl(Record[Idx++]));
+ case TemplateArgument::Integral: {
+ llvm::APSInt Value = ReadAPSInt(Record, Idx);
+ QualType T = GetType(Record[Idx++]);
+ return TemplateArgument(Value, T);
+ }
+ case TemplateArgument::Template:
+ return TemplateArgument(ReadTemplateName(F, Record, Idx));
+ case TemplateArgument::TemplateExpansion: {
+ TemplateName Name = ReadTemplateName(F, Record, Idx);
+ llvm::Optional<unsigned> NumTemplateExpansions;
+ if (unsigned NumExpansions = Record[Idx++])
+ NumTemplateExpansions = NumExpansions - 1;
+ return TemplateArgument(Name, NumTemplateExpansions);
+ }
+ case TemplateArgument::Expression:
+ return TemplateArgument(ReadExpr(F));
+ case TemplateArgument::Pack: {
+ unsigned NumArgs = Record[Idx++];
+ TemplateArgument *Args = new (*Context) TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I] = ReadTemplateArgument(F, Record, Idx);
+ return TemplateArgument(Args, NumArgs);
+ }
+ }
+
+ assert(0 && "Unhandled template argument kind!");
+ return TemplateArgument();
+}
+
+TemplateParameterList *
+ASTReader::ReadTemplateParameterList(PerFileData &F,
+ const RecordData &Record, unsigned &Idx) {
+ SourceLocation TemplateLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Idx);
+
+ unsigned NumParams = Record[Idx++];
+ llvm::SmallVector<NamedDecl *, 16> Params;
+ Params.reserve(NumParams);
+ while (NumParams--)
+ Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++])));
+
+ TemplateParameterList* TemplateParams =
+ TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc,
+ Params.data(), Params.size(), RAngleLoc);
+ return TemplateParams;
+}
+
+void
+ASTReader::
+ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
+ PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ unsigned NumTemplateArgs = Record[Idx++];
+ TemplArgs.reserve(NumTemplateArgs);
+ while (NumTemplateArgs--)
+ TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
+}
+
+/// \brief Read a UnresolvedSet structure.
+void ASTReader::ReadUnresolvedSet(UnresolvedSetImpl &Set,
+ const RecordData &Record, unsigned &Idx) {
+ unsigned NumDecls = Record[Idx++];
+ while (NumDecls--) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++]));
+ AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ Set.addDecl(D, AS);
+ }
+}
+
+CXXBaseSpecifier
+ASTReader::ReadCXXBaseSpecifier(PerFileData &F,
+ const RecordData &Record, unsigned &Idx) {
+ bool isVirtual = static_cast<bool>(Record[Idx++]);
+ bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
+ AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
+ bool inheritConstructors = static_cast<bool>(Record[Idx++]);
+ TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo,
+ EllipsisLoc);
+ Result.setInheritConstructors(inheritConstructors);
+ return Result;
+}
+
+std::pair<CXXCtorInitializer **, unsigned>
+ASTReader::ReadCXXCtorInitializers(PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ CXXCtorInitializer **CtorInitializers = 0;
+ unsigned NumInitializers = Record[Idx++];
+ if (NumInitializers) {
+ ASTContext &C = *getContext();
+
+ CtorInitializers
+ = new (C) CXXCtorInitializer*[NumInitializers];
+ for (unsigned i=0; i != NumInitializers; ++i) {
+ TypeSourceInfo *BaseClassInfo = 0;
+ bool IsBaseVirtual = false;
+ FieldDecl *Member = 0;
+ IndirectFieldDecl *IndirectMember = 0;
+
+ bool IsBaseInitializer = Record[Idx++];
+ if (IsBaseInitializer) {
+ BaseClassInfo = GetTypeSourceInfo(F, Record, Idx);
+ IsBaseVirtual = Record[Idx++];
+ } else {
+ bool IsIndirectMemberInitializer = Record[Idx++];
+ if (IsIndirectMemberInitializer)
+ IndirectMember = cast<IndirectFieldDecl>(GetDecl(Record[Idx++]));
+ else
+ Member = cast<FieldDecl>(GetDecl(Record[Idx++]));
+ }
+ SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ Expr *Init = ReadExpr(F);
+ SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
+ bool IsWritten = Record[Idx++];
+ unsigned SourceOrderOrNumArrayIndices;
+ llvm::SmallVector<VarDecl *, 8> Indices;
+ if (IsWritten) {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ } else {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ Indices.reserve(SourceOrderOrNumArrayIndices);
+ for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+ Indices.push_back(cast<VarDecl>(GetDecl(Record[Idx++])));
+ }
+
+ CXXCtorInitializer *BOMInit;
+ if (IsBaseInitializer) {
+ BOMInit = new (C) CXXCtorInitializer(C, BaseClassInfo, IsBaseVirtual,
+ LParenLoc, Init, RParenLoc,
+ MemberOrEllipsisLoc);
+ } else if (IsWritten) {
+ if (Member)
+ BOMInit = new (C) CXXCtorInitializer(C, Member, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
+ else
+ BOMInit = new (C) CXXCtorInitializer(C, IndirectMember,
+ MemberOrEllipsisLoc, LParenLoc,
+ Init, RParenLoc);
+ } else {
+ BOMInit = CXXCtorInitializer::Create(C, Member, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
+ }
+
+ if (IsWritten)
+ BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
+ CtorInitializers[i] = BOMInit;
+ }
+ }
+
+ return std::make_pair(CtorInitializers, NumInitializers);
+}
+
+NestedNameSpecifier *
+ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
+ unsigned N = Record[Idx++];
+ NestedNameSpecifier *NNS = 0, *Prev = 0;
+ for (unsigned I = 0; I != N; ++I) {
+ NestedNameSpecifier::SpecifierKind Kind
+ = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier: {
+ IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
+ NNS = NestedNameSpecifier::Create(*Context, Prev, II);
+ break;
+ }
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ const Type *T = GetType(Record[Idx++]).getTypePtrOrNull();
+ if (!T)
+ return 0;
+
+ bool Template = Record[Idx++];
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T);
+ break;
+ }
+
+ case NestedNameSpecifier::Global: {
+ NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
+ // No associated value, and there can't be a prefix.
+ break;
+ }
+ }
+ Prev = NNS;
+ }
+ return NNS;
+}
+
+SourceRange
+ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ SourceLocation beg = ReadSourceLocation(F, Record, Idx);
+ SourceLocation end = ReadSourceLocation(F, Record, Idx);
+ return SourceRange(beg, end);
+}
+
+/// \brief Read an integral value
+llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+ unsigned BitWidth = Record[Idx++];
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
+ Idx += NumWords;
+ return Result;
+}
+
+/// \brief Read a signed integral value
+llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+ bool isUnsigned = Record[Idx++];
+ return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
+}
+
+/// \brief Read a floating-point value
+llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
+ return llvm::APFloat(ReadAPInt(Record, Idx));
+}
+
+// \brief Read a string
+std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
+ unsigned Len = Record[Idx++];
+ std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
+ Idx += Len;
+ return Result;
+}
+
+CXXTemporary *ASTReader::ReadCXXTemporary(const RecordData &Record,
+ unsigned &Idx) {
+ CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++]));
+ return CXXTemporary::Create(*Context, Decl);
+}
+
+DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
+ return Diag(SourceLocation(), DiagID);
+}
+
+DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+}
+
+/// \brief Retrieve the identifier table associated with the
+/// preprocessor.
+IdentifierTable &ASTReader::getIdentifierTable() {
+ assert(PP && "Forgot to set Preprocessor ?");
+ return PP->getIdentifierTable();
+}
+
+/// \brief Record that the given ID maps to the given switch-case
+/// statement.
+void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+ assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
+ SwitchCaseStmts[ID] = SC;
+}
+
+/// \brief Retrieve the switch-case statement with the given ID.
+SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
+ assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
+ return SwitchCaseStmts[ID];
+}
+
+void ASTReader::ClearSwitchCaseIDs() {
+ SwitchCaseStmts.clear();
+}
+
+void ASTReader::FinishedDeserializing() {
+ assert(NumCurrentElementsDeserializing &&
+ "FinishedDeserializing not paired with StartedDeserializing");
+ if (NumCurrentElementsDeserializing == 1) {
+ // If any identifiers with corresponding top-level declarations have
+ // been loaded, load those declarations now.
+ while (!PendingIdentifierInfos.empty()) {
+ SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
+ PendingIdentifierInfos.front().DeclIDs, true);
+ PendingIdentifierInfos.pop_front();
+ }
+
+ // Ready to load previous declarations of Decls that were delayed.
+ while (!PendingPreviousDecls.empty()) {
+ loadAndAttachPreviousDecl(PendingPreviousDecls.front().first,
+ PendingPreviousDecls.front().second);
+ PendingPreviousDecls.pop_front();
+ }
+
+ // We are not in recursive loading, so it's safe to pass the "interesting"
+ // decls to the consumer.
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
+
+ assert(PendingForwardRefs.size() == 0 &&
+ "Some forward refs did not get linked to the definition!");
+ }
+ --NumCurrentElementsDeserializing;
+}
+
+ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
+ const char *isysroot, bool DisableValidation,
+ bool DisableStatCache)
+ : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
+ SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
+ Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
+ Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
+ DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0), NextSLocOffset(0),
+ NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
+ TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
+ NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
+ NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
+ NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+ NumCurrentElementsDeserializing(0)
+{
+ RelocatablePCH = false;
+}
+
+ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags, const char *isysroot,
+ bool DisableValidation, bool DisableStatCache)
+ : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
+ Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
+ isysroot(isysroot), DisableValidation(DisableValidation),
+ DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0),
+ NextSLocOffset(0), NumStatementsRead(0), TotalNumStatements(0),
+ NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0),
+ NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
+ TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0),
+ TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0),
+ TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) {
+ RelocatablePCH = false;
+}
+
+ASTReader::~ASTReader() {
+ for (unsigned i = 0, e = Chain.size(); i != e; ++i)
+ delete Chain[e - i - 1];
+ // Delete all visible decl lookup tables
+ for (DeclContextOffsetsMap::iterator I = DeclContextOffsets.begin(),
+ E = DeclContextOffsets.end();
+ I != E; ++I) {
+ for (DeclContextInfos::iterator J = I->second.begin(), F = I->second.end();
+ J != F; ++J) {
+ if (J->NameLookupTableData)
+ delete static_cast<ASTDeclContextNameLookupTable*>(
+ J->NameLookupTableData);
+ }
+ }
+ for (DeclContextVisibleUpdatesPending::iterator
+ I = PendingVisibleUpdates.begin(),
+ E = PendingVisibleUpdates.end();
+ I != E; ++I) {
+ for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
+ F = I->second.end();
+ J != F; ++J)
+ delete static_cast<ASTDeclContextNameLookupTable*>(*J);
+ }
+}
+
+ASTReader::PerFileData::PerFileData(ASTFileType Ty)
+ : Type(Ty), SizeInBits(0), LocalNumSLocEntries(0), SLocOffsets(0), LocalSLocSize(0),
+ LocalNumIdentifiers(0), IdentifierOffsets(0), IdentifierTableData(0),
+ IdentifierLookupTable(0), LocalNumMacroDefinitions(0),
+ MacroDefinitionOffsets(0),
+ LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0),
+ HeaderFileInfoTable(0),
+ LocalNumSelectors(0), SelectorOffsets(0),
+ SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
+ DeclOffsets(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
+ LocalNumTypes(0), TypeOffsets(0), StatCache(0),
+ NumPreallocatedPreprocessingEntities(0), NextInSource(0)
+{}
+
+ASTReader::PerFileData::~PerFileData() {
+ delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
+ delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
+ delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
new file mode 100644
index 0000000..dec15dd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -0,0 +1,1693 @@
+//===--- ASTReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ASTReader::ReadDeclRecord method, which is the
+// entrypoint for loading a decl.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTCommon.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+using namespace clang;
+using namespace clang::serialization;
+
+//===----------------------------------------------------------------------===//
+// Declaration deserialization
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
+ ASTReader &Reader;
+ ASTReader::PerFileData &F;
+ llvm::BitstreamCursor &Cursor;
+ const DeclID ThisDeclID;
+ typedef ASTReader::RecordData RecordData;
+ const RecordData &Record;
+ unsigned &Idx;
+ TypeID TypeIDForTypeDecl;
+
+ uint64_t GetCurrentCursorOffset();
+ SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) {
+ return Reader.ReadSourceLocation(F, R, I);
+ }
+ SourceRange ReadSourceRange(const RecordData &R, unsigned &I) {
+ return Reader.ReadSourceRange(F, R, I);
+ }
+ TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) {
+ return Reader.GetTypeSourceInfo(F, R, I);
+ }
+ void ReadQualifierInfo(QualifierInfo &Info,
+ const RecordData &R, unsigned &I) {
+ Reader.ReadQualifierInfo(F, Info, R, I);
+ }
+ void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name,
+ const RecordData &R, unsigned &I) {
+ Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I);
+ }
+ void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo,
+ const RecordData &R, unsigned &I) {
+ Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
+ }
+
+ void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
+ const RecordData &R, unsigned &I);
+
+ void InitializeCXXDefinitionData(CXXRecordDecl *D,
+ CXXRecordDecl *DefinitionDecl,
+ const RecordData &Record, unsigned &Idx);
+ public:
+ ASTDeclReader(ASTReader &Reader, ASTReader::PerFileData &F,
+ llvm::BitstreamCursor &Cursor, DeclID thisDeclID,
+ const RecordData &Record, unsigned &Idx)
+ : Reader(Reader), F(F), Cursor(Cursor), ThisDeclID(thisDeclID),
+ Record(Record), Idx(Idx), TypeIDForTypeDecl(0) { }
+
+ static void attachPreviousDecl(Decl *D, Decl *previous);
+
+ void Visit(Decl *D);
+
+ void UpdateDecl(Decl *D, const RecordData &Record);
+
+ void VisitDecl(Decl *D);
+ void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
+ void VisitNamedDecl(NamedDecl *ND);
+ void VisitLabelDecl(LabelDecl *LD);
+ void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ void VisitTypeDecl(TypeDecl *TD);
+ void VisitTypedefDecl(TypedefDecl *TD);
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitTagDecl(TagDecl *TD);
+ void VisitEnumDecl(EnumDecl *ED);
+ void VisitRecordDecl(RecordDecl *RD);
+ void VisitCXXRecordDecl(CXXRecordDecl *D);
+ void VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D);
+ void VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ void VisitValueDecl(ValueDecl *VD);
+ void VisitEnumConstantDecl(EnumConstantDecl *ECD);
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ void VisitDeclaratorDecl(DeclaratorDecl *DD);
+ void VisitFunctionDecl(FunctionDecl *FD);
+ void VisitCXXMethodDecl(CXXMethodDecl *D);
+ void VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ void VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ void VisitCXXConversionDecl(CXXConversionDecl *D);
+ void VisitFieldDecl(FieldDecl *FD);
+ void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
+ void VisitVarDecl(VarDecl *VD);
+ void VisitImplicitParamDecl(ImplicitParamDecl *PD);
+ void VisitParmVarDecl(ParmVarDecl *PD);
+ void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ void VisitTemplateDecl(TemplateDecl *D);
+ void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
+ void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingShadowDecl(UsingShadowDecl *D);
+ void VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
+ void VisitAccessSpecDecl(AccessSpecDecl *D);
+ void VisitFriendDecl(FriendDecl *D);
+ void VisitFriendTemplateDecl(FriendTemplateDecl *D);
+ void VisitStaticAssertDecl(StaticAssertDecl *D);
+ void VisitBlockDecl(BlockDecl *BD);
+
+ std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
+
+ // FIXME: Reorder according to DeclNodes.td?
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCContainerDecl(ObjCContainerDecl *D);
+ void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ void VisitObjCIvarDecl(ObjCIvarDecl *D);
+ void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+ void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
+ void VisitObjCClassDecl(ObjCClassDecl *D);
+ void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+ void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+ void VisitObjCImplDecl(ObjCImplDecl *D);
+ void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
+ void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ };
+}
+
+uint64_t ASTDeclReader::GetCurrentCursorOffset() {
+ uint64_t Off = 0;
+ for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) {
+ ASTReader::PerFileData &F = *Reader.Chain[N - I - 1];
+ if (&Cursor == &F.DeclsCursor) {
+ Off += F.DeclsCursor.GetCurrentBitNo();
+ break;
+ }
+ Off += F.SizeInBits;
+ }
+ return Off;
+}
+
+void ASTDeclReader::Visit(Decl *D) {
+ DeclVisitor<ASTDeclReader, void>::Visit(D);
+
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+ // if we have a fully initialized TypeDecl, we can safely read its type now.
+ TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // FunctionDecl's body was written last after all other Stmts/Exprs.
+ if (Record[Idx++])
+ FD->setLazyBody(GetCurrentCursorOffset());
+ }
+}
+
+void ASTDeclReader::VisitDecl(Decl *D) {
+ D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+ D->setLexicalDeclContext(
+ cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+ D->setLocation(ReadSourceLocation(Record, Idx));
+ D->setInvalidDecl(Record[Idx++]);
+ if (Record[Idx++]) { // hasAttrs
+ AttrVec Attrs;
+ Reader.ReadAttributes(F, Attrs, Record, Idx);
+ D->setAttrs(Attrs);
+ }
+ D->setImplicit(Record[Idx++]);
+ D->setUsed(Record[Idx++]);
+ D->setAccess((AccessSpecifier)Record[Idx++]);
+ D->setPCHLevel(Record[Idx++] + (F.Type <= ASTReader::PCH));
+}
+
+void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
+ VisitDecl(TU);
+ TU->setAnonymousNamespace(
+ cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
+ VisitDecl(ND);
+ ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
+}
+
+void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
+ VisitNamedDecl(TD);
+ // Delay type reading until after we have fully initialized the decl.
+ TypeIDForTypeDecl = Record[Idx++];
+}
+
+void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+ VisitTypeDecl(TD);
+ TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+}
+
+void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
+ VisitTypeDecl(TD);
+ VisitRedeclarable(TD);
+ TD->IdentifierNamespace = Record[Idx++];
+ TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
+ TD->setDefinition(Record[Idx++]);
+ TD->setEmbeddedInDeclarator(Record[Idx++]);
+ TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
+ TD->setTagKeywordLoc(ReadSourceLocation(Record, Idx));
+ if (Record[Idx++]) { // hasExtInfo
+ TagDecl::ExtInfo *Info = new (*Reader.getContext()) TagDecl::ExtInfo();
+ ReadQualifierInfo(*Info, Record, Idx);
+ TD->TypedefDeclOrQualifier = Info;
+ } else
+ TD->setTypedefForAnonDecl(
+ cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
+ VisitTagDecl(ED);
+ if (TypeSourceInfo *TI = Reader.GetTypeSourceInfo(F, Record, Idx))
+ ED->setIntegerTypeSourceInfo(TI);
+ else
+ ED->setIntegerType(Reader.GetType(Record[Idx++]));
+ ED->setPromotionType(Reader.GetType(Record[Idx++]));
+ ED->setNumPositiveBits(Record[Idx++]);
+ ED->setNumNegativeBits(Record[Idx++]);
+ ED->IsScoped = Record[Idx++];
+ ED->IsScopedUsingClassTag = Record[Idx++];
+ ED->IsFixed = Record[Idx++];
+ ED->setInstantiationOfMemberEnum(
+ cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
+ VisitTagDecl(RD);
+ RD->setHasFlexibleArrayMember(Record[Idx++]);
+ RD->setAnonymousStructOrUnion(Record[Idx++]);
+ RD->setHasObjectMember(Record[Idx++]);
+}
+
+void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
+ VisitNamedDecl(VD);
+ VD->setType(Reader.GetType(Record[Idx++]));
+}
+
+void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
+ VisitValueDecl(ECD);
+ if (Record[Idx++])
+ ECD->setInitExpr(Reader.ReadExpr(F));
+ ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
+}
+
+void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ VisitValueDecl(DD);
+ if (Record[Idx++]) { // hasExtInfo
+ DeclaratorDecl::ExtInfo *Info
+ = new (*Reader.getContext()) DeclaratorDecl::ExtInfo();
+ ReadQualifierInfo(*Info, Record, Idx);
+ Info->TInfo = GetTypeSourceInfo(Record, Idx);
+ DD->DeclInfo = Info;
+ } else
+ DD->DeclInfo = GetTypeSourceInfo(Record, Idx);
+}
+
+void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
+ VisitDeclaratorDecl(FD);
+ VisitRedeclarable(FD);
+
+ ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
+ FD->IdentifierNamespace = Record[Idx++];
+ switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
+ default: assert(false && "Unhandled TemplatedKind!");
+ break;
+ case FunctionDecl::TK_NonTemplate:
+ break;
+ case FunctionDecl::TK_FunctionTemplate:
+ FD->setDescribedFunctionTemplate(
+ cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])));
+ break;
+ case FunctionDecl::TK_MemberSpecialization: {
+ FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
+ SourceLocation POI = ReadSourceLocation(Record, Idx);
+ FD->setInstantiationOfMemberFunction(*Reader.getContext(), InstFD, TSK);
+ FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
+ break;
+ }
+ case FunctionDecl::TK_FunctionTemplateSpecialization: {
+ FunctionTemplateDecl *Template
+ = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
+
+ // Template arguments.
+ llvm::SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+
+ // Template args as written.
+ llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
+ SourceLocation LAngleLoc, RAngleLoc;
+ if (Record[Idx++]) { // TemplateArgumentsAsWritten != 0
+ unsigned NumTemplateArgLocs = Record[Idx++];
+ TemplArgLocs.reserve(NumTemplateArgLocs);
+ for (unsigned i=0; i != NumTemplateArgLocs; ++i)
+ TemplArgLocs.push_back(
+ Reader.ReadTemplateArgumentLoc(F, Record, Idx));
+
+ LAngleLoc = ReadSourceLocation(Record, Idx);
+ RAngleLoc = ReadSourceLocation(Record, Idx);
+ }
+
+ SourceLocation POI = ReadSourceLocation(Record, Idx);
+
+ ASTContext &C = *Reader.getContext();
+ TemplateArgumentList *TemplArgList
+ = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
+ TemplateArgumentListInfo *TemplArgsInfo
+ = new (C) TemplateArgumentListInfo(LAngleLoc, RAngleLoc);
+ for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i)
+ TemplArgsInfo->addArgument(TemplArgLocs[i]);
+ FunctionTemplateSpecializationInfo *FTInfo
+ = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
+ TemplArgList,
+ TemplArgsInfo, POI);
+ FD->TemplateOrSpecialization = FTInfo;
+
+ if (FD->isCanonicalDecl()) { // if canonical add to template's set.
+ // The template that contains the specializations set. It's not safe to
+ // use getCanonicalDecl on Template since it may still be initializing.
+ FunctionTemplateDecl *CanonTemplate
+ = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+ // Get the InsertPos by FindNodeOrInsertPos() instead of calling
+ // InsertNode(FTInfo) directly to avoid the getASTContext() call in
+ // FunctionTemplateSpecializationInfo's Profile().
+ // We avoid getASTContext because a decl in the parent hierarchy may
+ // be initializing.
+ llvm::FoldingSetNodeID ID;
+ FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(),
+ TemplArgs.size(), C);
+ void *InsertPos = 0;
+ CanonTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ assert(InsertPos && "Another specialization already inserted!");
+ CanonTemplate->getSpecializations().InsertNode(FTInfo, InsertPos);
+ }
+ break;
+ }
+ case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
+ // Templates.
+ UnresolvedSet<8> TemplDecls;
+ unsigned NumTemplates = Record[Idx++];
+ while (NumTemplates--)
+ TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+
+ // Templates args.
+ TemplateArgumentListInfo TemplArgs;
+ unsigned NumArgs = Record[Idx++];
+ while (NumArgs--)
+ TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(F, Record, Idx));
+ TemplArgs.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ TemplArgs.setRAngleLoc(ReadSourceLocation(Record, Idx));
+
+ FD->setDependentTemplateSpecialization(*Reader.getContext(),
+ TemplDecls, TemplArgs);
+ break;
+ }
+ }
+
+ // FunctionDecl's body is handled last at ASTDeclReader::Visit,
+ // after everything else is read.
+
+ FD->SClass = (StorageClass)Record[Idx++];
+ FD->SClassAsWritten = (StorageClass)Record[Idx++];
+ FD->IsInline = Record[Idx++];
+ FD->IsInlineSpecified = Record[Idx++];
+ FD->IsVirtualAsWritten = Record[Idx++];
+ FD->IsPure = Record[Idx++];
+ FD->HasInheritedPrototype = Record[Idx++];
+ FD->HasWrittenPrototype = Record[Idx++];
+ FD->IsDeleted = Record[Idx++];
+ FD->IsTrivial = Record[Idx++];
+ FD->HasImplicitReturnZero = Record[Idx++];
+ FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
+
+ // Read in the parameters.
+ unsigned NumParams = Record[Idx++];
+ llvm::SmallVector<ParmVarDecl *, 16> Params;
+ Params.reserve(NumParams);
+ for (unsigned I = 0; I != NumParams; ++I)
+ Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ FD->setParams(*Reader.getContext(), Params.data(), NumParams);
+}
+
+void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+ VisitNamedDecl(MD);
+ if (Record[Idx++]) {
+ // In practice, this won't be executed (since method definitions
+ // don't occur in header files).
+ MD->setBody(Reader.ReadStmt(F));
+ MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
+ MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
+ }
+ MD->setInstanceMethod(Record[Idx++]);
+ MD->setVariadic(Record[Idx++]);
+ MD->setSynthesized(Record[Idx++]);
+ MD->setDefined(Record[Idx++]);
+ MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
+ MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
+ MD->setNumSelectorArgs(unsigned(Record[Idx++]));
+ MD->setResultType(Reader.GetType(Record[Idx++]));
+ MD->setResultTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ MD->setEndLoc(ReadSourceLocation(Record, Idx));
+ unsigned NumParams = Record[Idx++];
+ llvm::SmallVector<ParmVarDecl *, 16> Params;
+ Params.reserve(NumParams);
+ for (unsigned I = 0; I != NumParams; ++I)
+ Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams,
+ NumParams);
+}
+
+void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
+ VisitNamedDecl(CD);
+ SourceLocation A = ReadSourceLocation(Record, Idx);
+ SourceLocation B = ReadSourceLocation(Record, Idx);
+ CD->setAtEndRange(SourceRange(A, B));
+}
+
+void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
+ VisitObjCContainerDecl(ID);
+ ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtrOrNull());
+ ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
+ (Reader.GetDecl(Record[Idx++])));
+
+ // Read the directly referenced protocols and their SourceLocations.
+ unsigned NumProtocols = Record[Idx++];
+ llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
+ *Reader.getContext());
+
+ // Read the transitive closure of protocols referenced by this class.
+ NumProtocols = Record[Idx++];
+ Protocols.clear();
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+ *Reader.getContext());
+
+ // Read the ivars.
+ unsigned NumIvars = Record[Idx++];
+ llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
+ IVars.reserve(NumIvars);
+ for (unsigned I = 0; I != NumIvars; ++I)
+ IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+ ID->setCategoryList(
+ cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+ // We will rebuild this list lazily.
+ ID->setIvarList(0);
+ ID->setForwardDecl(Record[Idx++]);
+ ID->setImplicitInterfaceDecl(Record[Idx++]);
+ ID->setClassLoc(ReadSourceLocation(Record, Idx));
+ ID->setSuperClassLoc(ReadSourceLocation(Record, Idx));
+ ID->setLocEnd(ReadSourceLocation(Record, Idx));
+}
+
+void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
+ VisitFieldDecl(IVD);
+ IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
+ // This field will be built lazily.
+ IVD->setNextIvar(0);
+ bool synth = Record[Idx++];
+ IVD->setSynthesize(synth);
+}
+
+void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
+ VisitObjCContainerDecl(PD);
+ PD->setForwardDecl(Record[Idx++]);
+ PD->setLocEnd(ReadSourceLocation(Record, Idx));
+ unsigned NumProtoRefs = Record[Idx++];
+ llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+ ProtoRefs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
+}
+
+void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
+ VisitFieldDecl(FD);
+}
+
+void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
+ VisitDecl(CD);
+ unsigned NumClassRefs = Record[Idx++];
+ llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
+ ClassRefs.reserve(NumClassRefs);
+ for (unsigned I = 0; I != NumClassRefs; ++I)
+ ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::SmallVector<SourceLocation, 16> SLocs;
+ SLocs.reserve(NumClassRefs);
+ for (unsigned I = 0; I != NumClassRefs; ++I)
+ SLocs.push_back(ReadSourceLocation(Record, Idx));
+ CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
+ NumClassRefs);
+}
+
+void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
+ VisitDecl(FPD);
+ unsigned NumProtoRefs = Record[Idx++];
+ llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+ ProtoRefs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
+}
+
+void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
+ VisitObjCContainerDecl(CD);
+ CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+ unsigned NumProtoRefs = Record[Idx++];
+ llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
+ ProtoRefs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtoRefs);
+ for (unsigned I = 0; I != NumProtoRefs; ++I)
+ ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+ *Reader.getContext());
+ CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+ CD->setHasSynthBitfield(Record[Idx++]);
+ CD->setAtLoc(ReadSourceLocation(Record, Idx));
+ CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
+ VisitNamedDecl(CAD);
+ CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+ VisitNamedDecl(D);
+ D->setAtLoc(ReadSourceLocation(Record, Idx));
+ D->setType(GetTypeSourceInfo(Record, Idx));
+ // FIXME: stable encoding
+ D->setPropertyAttributes(
+ (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+ D->setPropertyAttributesAsWritten(
+ (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+ // FIXME: stable encoding
+ D->setPropertyImplementation(
+ (ObjCPropertyDecl::PropertyControl)Record[Idx++]);
+ D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
+ D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
+ D->setGetterMethodDecl(
+ cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+ D->setSetterMethodDecl(
+ cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+ D->setPropertyIvarDecl(
+ cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
+ VisitObjCContainerDecl(D);
+ D->setClassInterface(
+ cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ VisitObjCImplDecl(D);
+ D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx));
+}
+
+void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+ VisitObjCImplDecl(D);
+ D->setSuperClass(
+ cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+ llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
+ = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ D->setHasSynthBitfield(Record[Idx++]);
+}
+
+
+void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ VisitDecl(D);
+ D->setAtLoc(ReadSourceLocation(Record, Idx));
+ D->setPropertyDecl(
+ cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
+ D->PropertyIvarDecl =
+ cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]));
+ D->IvarLoc = ReadSourceLocation(Record, Idx);
+ D->setGetterCXXConstructor(Reader.ReadExpr(F));
+ D->setSetterCXXAssignment(Reader.ReadExpr(F));
+}
+
+void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
+ VisitDeclaratorDecl(FD);
+ FD->setMutable(Record[Idx++]);
+ if (Record[Idx++])
+ FD->setBitWidth(Reader.ReadExpr(F));
+ if (!FD->getDeclName()) {
+ FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
+ if (Tmpl)
+ Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
+ }
+}
+
+void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
+ VisitValueDecl(FD);
+
+ FD->ChainingSize = Record[Idx++];
+ assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2");
+ FD->Chaining = new (*Reader.getContext())NamedDecl*[FD->ChainingSize];
+
+ for (unsigned I = 0; I != FD->ChainingSize; ++I)
+ FD->Chaining[I] = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
+ VisitDeclaratorDecl(VD);
+ VisitRedeclarable(VD);
+ VD->SClass = (StorageClass)Record[Idx++];
+ VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
+ VD->setThreadSpecified(Record[Idx++]);
+ VD->setCXXDirectInitializer(Record[Idx++]);
+ VD->setExceptionVariable(Record[Idx++]);
+ VD->setNRVOVariable(Record[Idx++]);
+ if (Record[Idx++])
+ VD->setInit(Reader.ReadExpr(F));
+
+ if (Record[Idx++]) { // HasMemberSpecializationInfo.
+ VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
+ SourceLocation POI = ReadSourceLocation(Record, Idx);
+ Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
+ }
+}
+
+void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
+ VisitVarDecl(PD);
+}
+
+void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
+ VisitVarDecl(PD);
+ PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
+ PD->setHasInheritedDefaultArg(Record[Idx++]);
+ if (Record[Idx++]) // hasUninstantiatedDefaultArg.
+ PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F));
+}
+
+void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
+ VisitDecl(AD);
+ AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(F)));
+}
+
+void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
+ VisitDecl(BD);
+ BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(F)));
+ BD->setSignatureAsWritten(GetTypeSourceInfo(Record, Idx));
+ unsigned NumParams = Record[Idx++];
+ llvm::SmallVector<ParmVarDecl *, 16> Params;
+ Params.reserve(NumParams);
+ for (unsigned I = 0; I != NumParams; ++I)
+ Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ BD->setParams(Params.data(), NumParams);
+
+ bool capturesCXXThis = Record[Idx++];
+ unsigned numCaptures = Record[Idx++];
+ llvm::SmallVector<BlockDecl::Capture, 16> captures;
+ captures.reserve(numCaptures);
+ for (unsigned i = 0; i != numCaptures; ++i) {
+ VarDecl *decl = cast<VarDecl>(Reader.GetDecl(Record[Idx++]));
+ unsigned flags = Record[Idx++];
+ bool byRef = (flags & 1);
+ bool nested = (flags & 2);
+ Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : 0);
+
+ captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
+ }
+ BD->setCaptures(*Reader.getContext(), captures.begin(),
+ captures.end(), capturesCXXThis);
+}
+
+void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ VisitDecl(D);
+ D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
+ D->setHasBraces(Record[Idx++]);
+}
+
+void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
+ VisitNamedDecl(D);
+}
+
+
+void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
+ VisitNamedDecl(D);
+ D->IsInline = Record[Idx++];
+ D->LBracLoc = ReadSourceLocation(Record, Idx);
+ D->RBracLoc = ReadSourceLocation(Record, Idx);
+ D->NextNamespace = Record[Idx++];
+
+ bool IsOriginal = Record[Idx++];
+ D->OrigOrAnonNamespace.setInt(IsOriginal);
+ D->OrigOrAnonNamespace.setPointer(
+ cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ VisitNamedDecl(D);
+ D->NamespaceLoc = ReadSourceLocation(Record, Idx);
+ D->setQualifierRange(ReadSourceRange(Record, Idx));
+ D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->IdentLoc = ReadSourceLocation(Record, Idx);
+ D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
+ VisitNamedDecl(D);
+ D->setUsingLocation(ReadSourceLocation(Record, Idx));
+ D->setNestedNameRange(ReadSourceRange(Record, Idx));
+ D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
+ ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
+ D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
+ D->setTypeName(Record[Idx++]);
+ NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ if (Pattern)
+ Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern);
+}
+
+void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ VisitNamedDecl(D);
+ D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ D->UsingOrNextShadow = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ UsingShadowDecl *Pattern
+ = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
+ if (Pattern)
+ Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern);
+}
+
+void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ VisitNamedDecl(D);
+ D->UsingLoc = ReadSourceLocation(Record, Idx);
+ D->NamespaceLoc = ReadSourceLocation(Record, Idx);
+ D->QualifierRange = ReadSourceRange(Record, Idx);
+ D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ VisitValueDecl(D);
+ D->setTargetNestedNameRange(ReadSourceRange(Record, Idx));
+ D->setUsingLoc(ReadSourceLocation(Record, Idx));
+ D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
+}
+
+void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ VisitTypeDecl(D);
+ D->TargetNestedNameRange = ReadSourceRange(Record, Idx);
+ D->UsingLocation = ReadSourceLocation(Record, Idx);
+ D->TypenameLocation = ReadSourceLocation(Record, Idx);
+ D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+}
+
+void ASTDeclReader::ReadCXXDefinitionData(
+ struct CXXRecordDecl::DefinitionData &Data,
+ const RecordData &Record, unsigned &Idx) {
+ Data.UserDeclaredConstructor = Record[Idx++];
+ Data.UserDeclaredCopyConstructor = Record[Idx++];
+ Data.UserDeclaredCopyAssignment = Record[Idx++];
+ Data.UserDeclaredDestructor = Record[Idx++];
+ Data.Aggregate = Record[Idx++];
+ Data.PlainOldData = Record[Idx++];
+ Data.Empty = Record[Idx++];
+ Data.Polymorphic = Record[Idx++];
+ Data.Abstract = Record[Idx++];
+ Data.HasTrivialConstructor = Record[Idx++];
+ Data.HasTrivialCopyConstructor = Record[Idx++];
+ Data.HasTrivialCopyAssignment = Record[Idx++];
+ Data.HasTrivialDestructor = Record[Idx++];
+ Data.ComputedVisibleConversions = Record[Idx++];
+ Data.DeclaredDefaultConstructor = Record[Idx++];
+ Data.DeclaredCopyConstructor = Record[Idx++];
+ Data.DeclaredCopyAssignment = Record[Idx++];
+ Data.DeclaredDestructor = Record[Idx++];
+
+ Data.NumBases = Record[Idx++];
+ if (Data.NumBases)
+ Data.Bases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]);
+ Data.NumVBases = Record[Idx++];
+ if (Data.NumVBases)
+ Data.VBases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]);
+
+ Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx);
+ Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx);
+ assert(Data.Definition && "Data.Definition should be already set!");
+ Data.FirstFriend
+ = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
+ CXXRecordDecl *DefinitionDecl,
+ const RecordData &Record,
+ unsigned &Idx) {
+ ASTContext &C = *Reader.getContext();
+
+ if (D == DefinitionDecl) {
+ D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
+ ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
+ // We read the definition info. Check if there are pending forward
+ // references that need to point to this DefinitionData pointer.
+ ASTReader::PendingForwardRefsMap::iterator
+ FindI = Reader.PendingForwardRefs.find(D);
+ if (FindI != Reader.PendingForwardRefs.end()) {
+ ASTReader::ForwardRefs &Refs = FindI->second;
+ for (ASTReader::ForwardRefs::iterator
+ I = Refs.begin(), E = Refs.end(); I != E; ++I)
+ (*I)->DefinitionData = D->DefinitionData;
+#ifndef NDEBUG
+ // We later check whether PendingForwardRefs is empty to make sure all
+ // pending references were linked.
+ Reader.PendingForwardRefs.erase(D);
+#endif
+ }
+ } else if (DefinitionDecl) {
+ if (DefinitionDecl->DefinitionData) {
+ D->DefinitionData = DefinitionDecl->DefinitionData;
+ } else {
+ // The definition is still initializing.
+ Reader.PendingForwardRefs[DefinitionDecl].push_back(D);
+ }
+ }
+}
+
+void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ VisitRecordDecl(D);
+
+ CXXRecordDecl *DefinitionDecl
+ = cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
+ InitializeCXXDefinitionData(D, DefinitionDecl, Record, Idx);
+
+ ASTContext &C = *Reader.getContext();
+
+ enum CXXRecKind {
+ CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
+ };
+ switch ((CXXRecKind)Record[Idx++]) {
+ default:
+ assert(false && "Out of sync with ASTDeclWriter::VisitCXXRecordDecl?");
+ case CXXRecNotTemplate:
+ break;
+ case CXXRecTemplate:
+ D->TemplateOrInstantiation
+ = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+ break;
+ case CXXRecMemberSpecialization: {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
+ SourceLocation POI = ReadSourceLocation(Record, Idx);
+ MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
+ MSI->setPointOfInstantiation(POI);
+ D->TemplateOrInstantiation = MSI;
+ break;
+ }
+ }
+
+ // Load the key function to avoid deserializing every method so we can
+ // compute it.
+ if (D->IsDefinition) {
+ CXXMethodDecl *Key
+ = cast_or_null<CXXMethodDecl>(Reader.GetDecl(Record[Idx++]));
+ if (Key)
+ C.KeyFunctions[D] = Key;
+ }
+}
+
+void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ VisitFunctionDecl(D);
+ unsigned NumOverridenMethods = Record[Idx++];
+ while (NumOverridenMethods--) {
+ CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++]));
+ // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
+ // MD may be initializing.
+ Reader.getContext()->addOverriddenMethod(D, MD);
+ }
+}
+
+void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ VisitCXXMethodDecl(D);
+
+ D->IsExplicitSpecified = Record[Idx++];
+ D->ImplicitlyDefined = Record[Idx++];
+ llvm::tie(D->CtorInitializers, D->NumCtorInitializers)
+ = Reader.ReadCXXCtorInitializers(F, Record, Idx);
+}
+
+void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ VisitCXXMethodDecl(D);
+
+ D->ImplicitlyDefined = Record[Idx++];
+ D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ VisitCXXMethodDecl(D);
+ D->IsExplicitSpecified = Record[Idx++];
+}
+
+void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
+ VisitDecl(D);
+ D->setColonLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
+ VisitDecl(D);
+ if (Record[Idx++])
+ D->Friend = GetTypeSourceInfo(Record, Idx);
+ else
+ D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ D->NextFriend = Record[Idx++];
+ D->UnsupportedFriend = (Record[Idx++] != 0);
+ D->FriendLoc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+ VisitDecl(D);
+ unsigned NumParams = Record[Idx++];
+ D->NumParams = NumParams;
+ D->Params = new TemplateParameterList*[NumParams];
+ for (unsigned i = 0; i != NumParams; ++i)
+ D->Params[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
+ if (Record[Idx++]) // HasFriendDecl
+ D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ else
+ D->Friend = GetTypeSourceInfo(Record, Idx);
+ D->FriendLoc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+ VisitNamedDecl(D);
+
+ NamedDecl *TemplatedDecl
+ = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateParameterList* TemplateParams
+ = Reader.ReadTemplateParameterList(F, Record, Idx);
+ D->init(TemplatedDecl, TemplateParams);
+}
+
+void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
+ // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
+ // can be used while this is still initializing.
+
+ assert(D->CommonOrPrev.isNull() && "getCommonPtr was called earlier on this");
+ DeclID PreviousDeclID = Record[Idx++];
+ DeclID FirstDeclID = PreviousDeclID ? Record[Idx++] : 0;
+ // We delay loading of the redeclaration chain to avoid deeply nested calls.
+ // We temporarily set the first (canonical) declaration as the previous one
+ // which is the one that matters and mark the real previous DeclID to be
+ // loaded & attached later on.
+ RedeclarableTemplateDecl *FirstDecl =
+ cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID));
+ assert((FirstDecl == 0 || FirstDecl->getKind() == D->getKind()) &&
+ "FirstDecl kind mismatch");
+ if (FirstDecl) {
+ D->CommonOrPrev = FirstDecl;
+ // Mark the real previous DeclID to be loaded & attached later on.
+ if (PreviousDeclID != FirstDeclID)
+ Reader.PendingPreviousDecls.push_back(std::make_pair(D, PreviousDeclID));
+ } else {
+ D->CommonOrPrev = D->newCommon(*Reader.getContext());
+ if (RedeclarableTemplateDecl *RTD
+ = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
+ assert(RTD->getKind() == D->getKind() &&
+ "InstantiatedFromMemberTemplate kind mismatch");
+ D->setInstantiatedFromMemberTemplateImpl(RTD);
+ if (Record[Idx++])
+ D->setMemberSpecialization();
+ }
+
+ RedeclarableTemplateDecl *LatestDecl =
+ cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+
+ // This decl is a first one and the latest declaration that it points to is
+ // in the same AST file. However, if this actually needs to point to a
+ // redeclaration in another AST file, we need to update it by checking
+ // the FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
+ ASTReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ assert((LatestDecl->getLocation().isInvalid() ||
+ NewLatest->getLocation().isInvalid() ||
+ !Reader.SourceMgr.isBeforeInTranslationUnit(
+ NewLatest->getLocation(),
+ LatestDecl->getLocation())) &&
+ "The new latest is supposed to come after the previous latest");
+ LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
+ }
+
+ assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
+ D->getCommonPtr()->Latest = LatestDecl;
+ }
+
+ VisitTemplateDecl(D);
+ D->IdentifierNamespace = Record[Idx++];
+}
+
+void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
+ // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
+ // the specializations.
+ llvm::SmallVector<serialization::DeclID, 2> SpecIDs;
+ SpecIDs.push_back(0);
+
+ // Specializations.
+ unsigned Size = Record[Idx++];
+ SpecIDs[0] += Size;
+ SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+ Idx += Size;
+
+ // Partial specializations.
+ Size = Record[Idx++];
+ SpecIDs[0] += Size;
+ SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+ Idx += Size;
+
+ if (SpecIDs[0]) {
+ typedef serialization::DeclID DeclID;
+
+ ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations
+ = new (*Reader.getContext()) DeclID [SpecIDs.size()];
+ memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
+ SpecIDs.size() * sizeof(DeclID));
+ }
+
+ // InjectedClassNameType is computed.
+ }
+}
+
+void ASTDeclReader::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ VisitCXXRecordDecl(D);
+
+ ASTContext &C = *Reader.getContext();
+ if (Decl *InstD = Reader.GetDecl(Record[Idx++])) {
+ if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
+ D->SpecializedTemplate = CTD;
+ } else {
+ llvm::SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ TemplateArgumentList *ArgList
+ = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
+ TemplArgs.size());
+ ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS
+ = new (C) ClassTemplateSpecializationDecl::
+ SpecializedPartialSpecialization();
+ PS->PartialSpecialization
+ = cast<ClassTemplatePartialSpecializationDecl>(InstD);
+ PS->TemplateArgs = ArgList;
+ D->SpecializedTemplate = PS;
+ }
+ }
+
+ // Explicit info.
+ if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
+ ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
+ = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
+ ExplicitInfo->TypeAsWritten = TyInfo;
+ ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
+ ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
+ D->ExplicitInfo = ExplicitInfo;
+ }
+
+ llvm::SmallVector<TemplateArgument, 8> TemplArgs;
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
+ TemplArgs.size());
+ D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
+ D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
+
+ if (D->isCanonicalDecl()) { // It's kept in the folding set.
+ ClassTemplateDecl *CanonPattern
+ = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+ if (ClassTemplatePartialSpecializationDecl *Partial
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+ CanonPattern->getCommonPtr()->PartialSpecializations.InsertNode(Partial);
+ } else {
+ CanonPattern->getCommonPtr()->Specializations.InsertNode(D);
+ }
+ }
+}
+
+void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ VisitClassTemplateSpecializationDecl(D);
+
+ ASTContext &C = *Reader.getContext();
+ D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
+
+ unsigned NumArgs = Record[Idx++];
+ if (NumArgs) {
+ D->NumArgsAsWritten = NumArgs;
+ D->ArgsAsWritten = new (C) TemplateArgumentLoc[NumArgs];
+ for (unsigned i=0; i != NumArgs; ++i)
+ D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx);
+ }
+
+ D->SequenceNumber = Record[Idx++];
+
+ // These are read/set from/to the first declaration.
+ if (D->getPreviousDeclaration() == 0) {
+ D->InstantiatedFromMember.setPointer(
+ cast_or_null<ClassTemplatePartialSpecializationDecl>(
+ Reader.GetDecl(Record[Idx++])));
+ D->InstantiatedFromMember.setInt(Record[Idx++]);
+ }
+}
+
+void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
+ // This FunctionTemplateDecl owns a CommonPtr; read it.
+
+ // Read the function specialization declarations.
+ // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled
+ // when reading the specialized FunctionDecl.
+ unsigned NumSpecs = Record[Idx++];
+ while (NumSpecs--)
+ Reader.GetDecl(Record[Idx++]);
+ }
+}
+
+void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ VisitTypeDecl(D);
+
+ D->setDeclaredWithTypename(Record[Idx++]);
+ D->setParameterPack(Record[Idx++]);
+
+ bool Inherited = Record[Idx++];
+ TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx);
+ D->setDefaultArgument(DefArg, Inherited);
+}
+
+void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ VisitDeclaratorDecl(D);
+ // TemplateParmPosition.
+ D->setDepth(Record[Idx++]);
+ D->setPosition(Record[Idx++]);
+ if (D->isExpandedParameterPack()) {
+ void **Data = reinterpret_cast<void **>(D + 1);
+ for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+ Data[2*I] = Reader.GetType(Record[Idx++]).getAsOpaquePtr();
+ Data[2*I + 1] = GetTypeSourceInfo(Record, Idx);
+ }
+ } else {
+ // Rest of NonTypeTemplateParmDecl.
+ D->ParameterPack = Record[Idx++];
+ if (Record[Idx++]) {
+ Expr *DefArg = Reader.ReadExpr(F);
+ bool Inherited = Record[Idx++];
+ D->setDefaultArgument(DefArg, Inherited);
+ }
+ }
+}
+
+void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ VisitTemplateDecl(D);
+ // TemplateParmPosition.
+ D->setDepth(Record[Idx++]);
+ D->setPosition(Record[Idx++]);
+ // Rest of TemplateTemplateParmDecl.
+ TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(F, Record, Idx);
+ bool IsInherited = Record[Idx++];
+ D->setDefaultArgument(Arg, IsInherited);
+ D->ParameterPack = Record[Idx++];
+}
+
+void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ VisitDecl(D);
+ D->AssertExpr = Reader.ReadExpr(F);
+ D->Message = cast<StringLiteral>(Reader.ReadExpr(F));
+}
+
+std::pair<uint64_t, uint64_t>
+ASTDeclReader::VisitDeclContext(DeclContext *DC) {
+ uint64_t LexicalOffset = Record[Idx++];
+ uint64_t VisibleOffset = Record[Idx++];
+ return std::make_pair(LexicalOffset, VisibleOffset);
+}
+
+template <typename T>
+void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
+ enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ RedeclKind Kind = (RedeclKind)Record[Idx++];
+ switch (Kind) {
+ default:
+ assert(0 && "Out of sync with ASTDeclWriter::VisitRedeclarable or messed up"
+ " reading");
+ case NoRedeclaration:
+ break;
+ case PointsToPrevious: {
+ DeclID PreviousDeclID = Record[Idx++];
+ DeclID FirstDeclID = Record[Idx++];
+ // We delay loading of the redeclaration chain to avoid deeply nested calls.
+ // We temporarily set the first (canonical) declaration as the previous one
+ // which is the one that matters and mark the real previous DeclID to be
+ // loaded & attached later on.
+ D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
+ cast_or_null<T>(Reader.GetDecl(FirstDeclID)));
+ if (PreviousDeclID != FirstDeclID)
+ Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
+ PreviousDeclID));
+ break;
+ }
+ case PointsToLatest:
+ D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
+ cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+ break;
+ }
+
+ assert(!(Kind == PointsToPrevious &&
+ Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
+ Reader.FirstLatestDeclIDs.end()) &&
+ "This decl is not first, it should not be in the map");
+ if (Kind == PointsToPrevious)
+ return;
+
+ // This decl is a first one and the latest declaration that it points to is in
+ // the same AST file. However, if this actually needs to point to a
+ // redeclaration in another AST file, we need to update it by checking the
+ // FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
+ "Invalid ThisDeclID ?");
+ ASTReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ D->RedeclLink
+ = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Attribute Reading
+//===----------------------------------------------------------------------===//
+
+/// \brief Reads attributes from the current stream position.
+void ASTReader::ReadAttributes(PerFileData &F, AttrVec &Attrs,
+ const RecordData &Record, unsigned &Idx) {
+ for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) {
+ Attr *New = 0;
+ attr::Kind Kind = (attr::Kind)Record[Idx++];
+ SourceLocation Loc = ReadSourceLocation(F, Record, Idx);
+
+#include "clang/Serialization/AttrPCHRead.inc"
+
+ assert(New && "Unable to decode attribute?");
+ Attrs.push_back(New);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ASTReader Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Note that we have loaded the declaration with the given
+/// Index.
+///
+/// This routine notes that this declaration has already been loaded,
+/// so that future GetDecl calls will return this declaration rather
+/// than trying to load a new declaration.
+inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
+ assert(!DeclsLoaded[Index] && "Decl loaded twice?");
+ DeclsLoaded[Index] = D;
+}
+
+
+/// \brief Determine whether the consumer will be interested in seeing
+/// this declaration (via HandleTopLevelDecl).
+///
+/// This routine should return true for anything that might affect
+/// code generation, e.g., inline function definitions, Objective-C
+/// declarations with metadata, etc.
+static bool isConsumerInterestedIn(Decl *D) {
+ if (isa<FileScopeAsmDecl>(D))
+ return true;
+ if (VarDecl *Var = dyn_cast<VarDecl>(D))
+ return Var->isFileVarDecl() &&
+ Var->isThisDeclarationADefinition() == VarDecl::Definition;
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
+ return Func->isThisDeclarationADefinition();
+ return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D);
+}
+
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation
+ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
+ // See if there's an override.
+ DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
+ if (It != ReplacedDecls.end())
+ return RecordLocation(It->second.first, It->second.second);
+
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (Index < F->LocalNumDecls)
+ break;
+ Index -= F->LocalNumDecls;
+ }
+ assert(F && F->LocalNumDecls > Index && "Broken chain");
+ return RecordLocation(F, F->DeclOffsets[Index]);
+}
+
+void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
+ assert(D && previous);
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ TD->RedeclLink.setPointer(cast<TagDecl>(previous));
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ FD->RedeclLink.setPointer(cast<FunctionDecl>(previous));
+ } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ VD->RedeclLink.setPointer(cast<VarDecl>(previous));
+ } else {
+ RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
+ TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous);
+ }
+}
+
+void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
+ Decl *previous = GetDecl(ID);
+ ASTDeclReader::attachPreviousDecl(D, previous);
+}
+
+/// \brief Read the declaration at the given offset from the AST file.
+Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
+ RecordLocation Loc = DeclCursorForIndex(Index, ID);
+ llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this declaration.
+ SavedStreamPosition SavedPosition(DeclsCursor);
+
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+
+ // Note that we are loading a declaration record.
+ Deserializing ADecl(this);
+
+ DeclsCursor.JumpToBit(Loc.Offset);
+ RecordData Record;
+ unsigned Code = DeclsCursor.ReadCode();
+ unsigned Idx = 0;
+ ASTDeclReader Reader(*this, *Loc.F, DeclsCursor, ID, Record, Idx);
+
+ Decl *D = 0;
+ switch ((DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
+ case DECL_CONTEXT_LEXICAL:
+ case DECL_CONTEXT_VISIBLE:
+ assert(false && "Record cannot be de-serialized with ReadDeclRecord");
+ break;
+ case DECL_TRANSLATION_UNIT:
+ assert(Index == 0 && "Translation unit must be at index 0");
+ D = Context->getTranslationUnitDecl();
+ break;
+ case DECL_TYPEDEF:
+ D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+ case DECL_ENUM:
+ D = EnumDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_RECORD:
+ D = RecordDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_ENUM_CONSTANT:
+ D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
+ 0, llvm::APSInt());
+ break;
+ case DECL_FUNCTION:
+ D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
+ QualType(), 0);
+ break;
+ case DECL_LINKAGE_SPEC:
+ D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(),
+ (LinkageSpecDecl::LanguageIDs)0,
+ false);
+ break;
+ case DECL_LABEL:
+ D = LabelDecl::Create(*Context, 0, SourceLocation(), 0);
+ break;
+ case DECL_NAMESPACE:
+ D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
+ break;
+ case DECL_NAMESPACE_ALIAS:
+ D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), 0, SourceRange(), 0,
+ SourceLocation(), 0);
+ break;
+ case DECL_USING:
+ D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(),
+ 0, DeclarationNameInfo(), false);
+ break;
+ case DECL_USING_SHADOW:
+ D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+ case DECL_USING_DIRECTIVE:
+ D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), SourceRange(), 0,
+ SourceLocation(), 0, 0);
+ break;
+ case DECL_UNRESOLVED_USING_VALUE:
+ D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
+ SourceRange(), 0,
+ DeclarationNameInfo());
+ break;
+ case DECL_UNRESOLVED_USING_TYPENAME:
+ D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), SourceRange(),
+ 0, SourceLocation(),
+ DeclarationName());
+ break;
+ case DECL_CXX_RECORD:
+ D = CXXRecordDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_CXX_METHOD:
+ D = CXXMethodDecl::Create(*Context, 0, DeclarationNameInfo(),
+ QualType(), 0);
+ break;
+ case DECL_CXX_CONSTRUCTOR:
+ D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_CXX_DESTRUCTOR:
+ D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_CXX_CONVERSION:
+ D = CXXConversionDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_ACCESS_SPEC:
+ D = AccessSpecDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_FRIEND:
+ D = FriendDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_FRIEND_TEMPLATE:
+ D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_CLASS_TEMPLATE:
+ D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(),
+ DeclarationName(), 0, 0, 0);
+ break;
+ case DECL_CLASS_TEMPLATE_SPECIALIZATION:
+ D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
+ D = ClassTemplatePartialSpecializationDecl::Create(*Context,
+ Decl::EmptyShell());
+ break;
+ case DECL_FUNCTION_TEMPLATE:
+ D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(),
+ DeclarationName(), 0, 0);
+ break;
+ case DECL_TEMPLATE_TYPE_PARM:
+ D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell());
+ break;
+ case DECL_NON_TYPE_TEMPLATE_PARM:
+ D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
+ QualType(), false, 0);
+ break;
+ case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
+ D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
+ 0, QualType(), 0, 0, Record[Idx++],
+ 0);
+ break;
+ case DECL_TEMPLATE_TEMPLATE_PARM:
+ D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0, 0,
+ false, 0, 0);
+ break;
+ case DECL_STATIC_ASSERT:
+ D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+
+ case DECL_OBJC_METHOD:
+ D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
+ Selector(), QualType(), 0, 0);
+ break;
+ case DECL_OBJC_INTERFACE:
+ D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
+ break;
+ case DECL_OBJC_IVAR:
+ D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+ ObjCIvarDecl::None);
+ break;
+ case DECL_OBJC_PROTOCOL:
+ D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0);
+ break;
+ case DECL_OBJC_AT_DEFS_FIELD:
+ D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,
+ QualType(), 0);
+ break;
+ case DECL_OBJC_CLASS:
+ D = ObjCClassDecl::Create(*Context, 0, SourceLocation());
+ break;
+ case DECL_OBJC_FORWARD_PROTOCOL:
+ D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
+ break;
+ case DECL_OBJC_CATEGORY:
+ D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), SourceLocation(), 0);
+ break;
+ case DECL_OBJC_CATEGORY_IMPL:
+ D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+ case DECL_OBJC_IMPLEMENTATION:
+ D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+ case DECL_OBJC_COMPATIBLE_ALIAS:
+ D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
+ break;
+ case DECL_OBJC_PROPERTY:
+ D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
+ 0);
+ break;
+ case DECL_OBJC_PROPERTY_IMPL:
+ D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(), 0,
+ ObjCPropertyImplDecl::Dynamic, 0,
+ SourceLocation());
+ break;
+ case DECL_FIELD:
+ D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
+ false);
+ break;
+ case DECL_INDIRECTFIELD:
+ D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
+ 0, 0);
+ break;
+ case DECL_VAR:
+ D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+ SC_None, SC_None);
+ break;
+
+ case DECL_IMPLICIT_PARAM:
+ D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
+ break;
+
+ case DECL_PARM_VAR:
+ D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
+ SC_None, SC_None, 0);
+ break;
+ case DECL_FILE_SCOPE_ASM:
+ D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
+ break;
+ case DECL_BLOCK:
+ D = BlockDecl::Create(*Context, 0, SourceLocation());
+ break;
+ case DECL_CXX_BASE_SPECIFIERS:
+ Error("attempt to read a C++ base-specifier record as a declaration");
+ return 0;
+ }
+
+ assert(D && "Unknown declaration reading AST file");
+ LoadedDecl(Index, D);
+ Reader.Visit(D);
+
+ // If this declaration is also a declaration context, get the
+ // offsets for its tables of lexical and visible declarations.
+ if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
+ std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
+ if (Offsets.first || Offsets.second) {
+ DC->setHasExternalLexicalStorage(Offsets.first != 0);
+ DC->setHasExternalVisibleStorage(Offsets.second != 0);
+ DeclContextInfo Info;
+ if (ReadDeclContextStorage(DeclsCursor, Offsets, Info))
+ return 0;
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ // Reading the TU will happen after reading its lexical update blocks,
+ // so we need to make sure we insert in front. For all other contexts,
+ // the vector is empty here anyway, so there's no loss in efficiency.
+ Infos.insert(Infos.begin(), Info);
+
+ // Now add the pending visible updates for this decl context, if it has
+ // any.
+ DeclContextVisibleUpdatesPending::iterator I =
+ PendingVisibleUpdates.find(ID);
+ if (I != PendingVisibleUpdates.end()) {
+ DeclContextVisibleUpdates &U = I->second;
+ Info.LexicalDecls = 0;
+ Info.NumLexicalDecls = 0;
+ for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
+ UI != UE; ++UI) {
+ Info.NameLookupTableData = *UI;
+ Infos.push_back(Info);
+ }
+ PendingVisibleUpdates.erase(I);
+ }
+ }
+ }
+ assert(Idx == Record.size());
+
+ // The declaration may have been modified by files later in the chain.
+ // If this is the case, read the record containing the updates from each file
+ // and pass it to ASTDeclReader to make the modifications.
+ DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
+ if (UpdI != DeclUpdateOffsets.end()) {
+ FileOffsetsTy &UpdateOffsets = UpdI->second;
+ for (FileOffsetsTy::iterator
+ I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) {
+ PerFileData *F = I->first;
+ uint64_t Offset = I->second;
+ llvm::BitstreamCursor &Cursor = F->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record);
+ (void)RecCode;
+ assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
+ Reader.UpdateDecl(D, Record);
+ }
+ }
+
+ // If we have deserialized a declaration that has a definition the
+ // AST consumer might need to know about, queue it.
+ // We don't pass it to the consumer immediately because we may be in recursive
+ // loading, and some declarations may still be initializing.
+ if (isConsumerInterestedIn(D))
+ InterestingDecls.push_back(D);
+
+ return D;
+}
+
+void ASTDeclReader::UpdateDecl(Decl *D, const RecordData &Record) {
+ unsigned Idx = 0;
+ while (Idx < Record.size()) {
+ switch ((DeclUpdateKind)Record[Idx++]) {
+ case UPD_CXX_SET_DEFINITIONDATA: {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+ CXXRecordDecl *
+ DefinitionDecl = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
+ assert(!RD->DefinitionData && "DefinitionData is already set!");
+ InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx);
+ break;
+ }
+
+ case UPD_CXX_ADDED_IMPLICIT_MEMBER:
+ cast<CXXRecordDecl>(D)->addedMember(Reader.GetDecl(Record[Idx++]));
+ break;
+
+ case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
+ // It will be added to the template's specializations set when loaded.
+ Reader.GetDecl(Record[Idx++]);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
new file mode 100644
index 0000000..4e91c98
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -0,0 +1,1941 @@
+//===--- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Statement/expression deserialization. This implements the
+// ASTReader::ReadStmt method.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTReader.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+using namespace clang;
+using namespace clang::serialization;
+
+namespace clang {
+
+ class ASTStmtReader : public StmtVisitor<ASTStmtReader> {
+ ASTReader &Reader;
+ ASTReader::PerFileData &F;
+ llvm::BitstreamCursor &DeclsCursor;
+ const ASTReader::RecordData &Record;
+ unsigned &Idx;
+
+ SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
+ unsigned &I) {
+ return Reader.ReadSourceLocation(F, R, I);
+ }
+ SourceRange ReadSourceRange(const ASTReader::RecordData &R, unsigned &I) {
+ return Reader.ReadSourceRange(F, R, I);
+ }
+ TypeSourceInfo *GetTypeSourceInfo(const ASTReader::RecordData &R,
+ unsigned &I) {
+ return Reader.GetTypeSourceInfo(F, R, I);
+ }
+ void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name,
+ const ASTReader::RecordData &R, unsigned &I) {
+ Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I);
+ }
+ void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo,
+ const ASTReader::RecordData &R, unsigned &I) {
+ Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
+ }
+
+ public:
+ ASTStmtReader(ASTReader &Reader, ASTReader::PerFileData &F,
+ llvm::BitstreamCursor &Cursor,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : Reader(Reader), F(F), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
+
+ /// \brief The number of record fields required for the Stmt class
+ /// itself.
+ static const unsigned NumStmtFields = 0;
+
+ /// \brief The number of record fields required for the Expr class
+ /// itself.
+ static const unsigned NumExprFields = NumStmtFields + 6;
+
+ /// \brief Read and initialize a ExplicitTemplateArgumentList structure.
+ void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
+ unsigned NumTemplateArgs);
+
+ void VisitStmt(Stmt *S);
+ void VisitNullStmt(NullStmt *S);
+ void VisitCompoundStmt(CompoundStmt *S);
+ void VisitSwitchCase(SwitchCase *S);
+ void VisitCaseStmt(CaseStmt *S);
+ void VisitDefaultStmt(DefaultStmt *S);
+ void VisitLabelStmt(LabelStmt *S);
+ void VisitIfStmt(IfStmt *S);
+ void VisitSwitchStmt(SwitchStmt *S);
+ void VisitWhileStmt(WhileStmt *S);
+ void VisitDoStmt(DoStmt *S);
+ void VisitForStmt(ForStmt *S);
+ void VisitGotoStmt(GotoStmt *S);
+ void VisitIndirectGotoStmt(IndirectGotoStmt *S);
+ void VisitContinueStmt(ContinueStmt *S);
+ void VisitBreakStmt(BreakStmt *S);
+ void VisitReturnStmt(ReturnStmt *S);
+ void VisitDeclStmt(DeclStmt *S);
+ void VisitAsmStmt(AsmStmt *S);
+ void VisitExpr(Expr *E);
+ void VisitPredefinedExpr(PredefinedExpr *E);
+ void VisitDeclRefExpr(DeclRefExpr *E);
+ void VisitIntegerLiteral(IntegerLiteral *E);
+ void VisitFloatingLiteral(FloatingLiteral *E);
+ void VisitImaginaryLiteral(ImaginaryLiteral *E);
+ void VisitStringLiteral(StringLiteral *E);
+ void VisitCharacterLiteral(CharacterLiteral *E);
+ void VisitParenExpr(ParenExpr *E);
+ void VisitParenListExpr(ParenListExpr *E);
+ void VisitUnaryOperator(UnaryOperator *E);
+ void VisitOffsetOfExpr(OffsetOfExpr *E);
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+ void VisitCallExpr(CallExpr *E);
+ void VisitMemberExpr(MemberExpr *E);
+ void VisitCastExpr(CastExpr *E);
+ void VisitBinaryOperator(BinaryOperator *E);
+ void VisitCompoundAssignOperator(CompoundAssignOperator *E);
+ void VisitConditionalOperator(ConditionalOperator *E);
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
+ void VisitImplicitCastExpr(ImplicitCastExpr *E);
+ void VisitExplicitCastExpr(ExplicitCastExpr *E);
+ void VisitCStyleCastExpr(CStyleCastExpr *E);
+ void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
+ void VisitInitListExpr(InitListExpr *E);
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E);
+ void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+ void VisitVAArgExpr(VAArgExpr *E);
+ void VisitAddrLabelExpr(AddrLabelExpr *E);
+ void VisitStmtExpr(StmtExpr *E);
+ void VisitChooseExpr(ChooseExpr *E);
+ void VisitGNUNullExpr(GNUNullExpr *E);
+ void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+ void VisitBlockExpr(BlockExpr *E);
+ void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+ void VisitObjCStringLiteral(ObjCStringLiteral *E);
+ void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+ void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
+ void VisitObjCProtocolExpr(ObjCProtocolExpr *E);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
+ void VisitObjCMessageExpr(ObjCMessageExpr *E);
+ void VisitObjCIsaExpr(ObjCIsaExpr *E);
+
+ void VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
+ void VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
+ void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
+ void VisitObjCAtTryStmt(ObjCAtTryStmt *);
+ void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
+ void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
+
+ // C++ Statements
+ void VisitCXXCatchStmt(CXXCatchStmt *S);
+ void VisitCXXTryStmt(CXXTryStmt *S);
+
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ void VisitCXXConstructExpr(CXXConstructExpr *E);
+ void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+ void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+ void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+ void VisitCXXConstCastExpr(CXXConstCastExpr *E);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+ void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+ void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E);
+ void VisitCXXThisExpr(CXXThisExpr *E);
+ void VisitCXXThrowExpr(CXXThrowExpr *E);
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+
+ void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ void VisitCXXNewExpr(CXXNewExpr *E);
+ void VisitCXXDeleteExpr(CXXDeleteExpr *E);
+ void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+
+ void VisitExprWithCleanups(ExprWithCleanups *E);
+
+ void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
+
+ void VisitOverloadExpr(OverloadExpr *E);
+ void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
+ void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+
+ void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+ void VisitPackExpansionExpr(PackExpansionExpr *E);
+ void VisitSizeOfPackExpr(SizeOfPackExpr *E);
+ void VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
+ void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
+ // CUDA Expressions
+ void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E);
+ };
+}
+
+void ASTStmtReader::
+ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
+ unsigned NumTemplateArgs) {
+ TemplateArgumentListInfo ArgInfo;
+ ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
+ ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ ArgInfo.addArgument(
+ Reader.ReadTemplateArgumentLoc(F, Record, Idx));
+ ArgList.initializeFrom(ArgInfo);
+}
+
+void ASTStmtReader::VisitStmt(Stmt *S) {
+ assert(Idx == NumStmtFields && "Incorrect statement field count");
+}
+
+void ASTStmtReader::VisitNullStmt(NullStmt *S) {
+ VisitStmt(S);
+ S->setSemiLoc(ReadSourceLocation(Record, Idx));
+ S->LeadingEmptyMacro = Record[Idx++];
+}
+
+void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
+ VisitStmt(S);
+ llvm::SmallVector<Stmt *, 16> Stmts;
+ unsigned NumStmts = Record[Idx++];
+ while (NumStmts--)
+ Stmts.push_back(Reader.ReadSubStmt());
+ S->setStmts(*Reader.getContext(), Stmts.data(), Stmts.size());
+ S->setLBracLoc(ReadSourceLocation(Record, Idx));
+ S->setRBracLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitSwitchCase(SwitchCase *S) {
+ VisitStmt(S);
+ Reader.RecordSwitchCaseID(S, Record[Idx++]);
+}
+
+void ASTStmtReader::VisitCaseStmt(CaseStmt *S) {
+ VisitSwitchCase(S);
+ S->setLHS(Reader.ReadSubExpr());
+ S->setRHS(Reader.ReadSubExpr());
+ S->setSubStmt(Reader.ReadSubStmt());
+ S->setCaseLoc(ReadSourceLocation(Record, Idx));
+ S->setEllipsisLoc(ReadSourceLocation(Record, Idx));
+ S->setColonLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
+ VisitSwitchCase(S);
+ S->setSubStmt(Reader.ReadSubStmt());
+ S->setDefaultLoc(ReadSourceLocation(Record, Idx));
+ S->setColonLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
+ VisitStmt(S);
+ LabelDecl *LD = cast<LabelDecl>(Reader.GetDecl(Record[Idx++]));
+ LD->setStmt(S);
+ S->setDecl(LD);
+ S->setSubStmt(Reader.ReadSubStmt());
+ S->setIdentLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitIfStmt(IfStmt *S) {
+ VisitStmt(S);
+ S->setConditionVariable(*Reader.getContext(),
+ cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setCond(Reader.ReadSubExpr());
+ S->setThen(Reader.ReadSubStmt());
+ S->setElse(Reader.ReadSubStmt());
+ S->setIfLoc(ReadSourceLocation(Record, Idx));
+ S->setElseLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
+ VisitStmt(S);
+ S->setConditionVariable(*Reader.getContext(),
+ cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setCond(Reader.ReadSubExpr());
+ S->setBody(Reader.ReadSubStmt());
+ S->setSwitchLoc(ReadSourceLocation(Record, Idx));
+ if (Record[Idx++])
+ S->setAllEnumCasesCovered();
+
+ SwitchCase *PrevSC = 0;
+ for (unsigned N = Record.size(); Idx != N; ++Idx) {
+ SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
+ if (PrevSC)
+ PrevSC->setNextSwitchCase(SC);
+ else
+ S->setSwitchCaseList(SC);
+
+ PrevSC = SC;
+ }
+}
+
+void ASTStmtReader::VisitWhileStmt(WhileStmt *S) {
+ VisitStmt(S);
+ S->setConditionVariable(*Reader.getContext(),
+ cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setCond(Reader.ReadSubExpr());
+ S->setBody(Reader.ReadSubStmt());
+ S->setWhileLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitDoStmt(DoStmt *S) {
+ VisitStmt(S);
+ S->setCond(Reader.ReadSubExpr());
+ S->setBody(Reader.ReadSubStmt());
+ S->setDoLoc(ReadSourceLocation(Record, Idx));
+ S->setWhileLoc(ReadSourceLocation(Record, Idx));
+ S->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitForStmt(ForStmt *S) {
+ VisitStmt(S);
+ S->setInit(Reader.ReadSubStmt());
+ S->setCond(Reader.ReadSubExpr());
+ S->setConditionVariable(*Reader.getContext(),
+ cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setInc(Reader.ReadSubExpr());
+ S->setBody(Reader.ReadSubStmt());
+ S->setForLoc(ReadSourceLocation(Record, Idx));
+ S->setLParenLoc(ReadSourceLocation(Record, Idx));
+ S->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitGotoStmt(GotoStmt *S) {
+ VisitStmt(S);
+ S->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setGotoLoc(ReadSourceLocation(Record, Idx));
+ S->setLabelLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ VisitStmt(S);
+ S->setGotoLoc(ReadSourceLocation(Record, Idx));
+ S->setStarLoc(ReadSourceLocation(Record, Idx));
+ S->setTarget(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitContinueStmt(ContinueStmt *S) {
+ VisitStmt(S);
+ S->setContinueLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitBreakStmt(BreakStmt *S) {
+ VisitStmt(S);
+ S->setBreakLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) {
+ VisitStmt(S);
+ S->setRetValue(Reader.ReadSubExpr());
+ S->setReturnLoc(ReadSourceLocation(Record, Idx));
+ S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTStmtReader::VisitDeclStmt(DeclStmt *S) {
+ VisitStmt(S);
+ S->setStartLoc(ReadSourceLocation(Record, Idx));
+ S->setEndLoc(ReadSourceLocation(Record, Idx));
+
+ if (Idx + 1 == Record.size()) {
+ // Single declaration
+ S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++])));
+ } else {
+ llvm::SmallVector<Decl *, 16> Decls;
+ Decls.reserve(Record.size() - Idx);
+ for (unsigned N = Record.size(); Idx != N; ++Idx)
+ Decls.push_back(Reader.GetDecl(Record[Idx]));
+ S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(),
+ Decls.data(),
+ Decls.size())));
+ }
+}
+
+void ASTStmtReader::VisitAsmStmt(AsmStmt *S) {
+ VisitStmt(S);
+ unsigned NumOutputs = Record[Idx++];
+ unsigned NumInputs = Record[Idx++];
+ unsigned NumClobbers = Record[Idx++];
+ S->setAsmLoc(ReadSourceLocation(Record, Idx));
+ S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->setVolatile(Record[Idx++]);
+ S->setSimple(Record[Idx++]);
+ S->setMSAsm(Record[Idx++]);
+
+ S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
+
+ // Outputs and inputs
+ llvm::SmallVector<IdentifierInfo *, 16> Names;
+ llvm::SmallVector<StringLiteral*, 16> Constraints;
+ llvm::SmallVector<Stmt*, 16> Exprs;
+ for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
+ Names.push_back(Reader.GetIdentifierInfo(Record, Idx));
+ Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
+ Exprs.push_back(Reader.ReadSubStmt());
+ }
+
+ // Constraints
+ llvm::SmallVector<StringLiteral*, 16> Clobbers;
+ for (unsigned I = 0; I != NumClobbers; ++I)
+ Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
+
+ S->setOutputsAndInputsAndClobbers(*Reader.getContext(),
+ Names.data(), Constraints.data(),
+ Exprs.data(), NumOutputs, NumInputs,
+ Clobbers.data(), NumClobbers);
+}
+
+void ASTStmtReader::VisitExpr(Expr *E) {
+ VisitStmt(E);
+ E->setType(Reader.GetType(Record[Idx++]));
+ E->setTypeDependent(Record[Idx++]);
+ E->setValueDependent(Record[Idx++]);
+ E->ExprBits.ContainsUnexpandedParameterPack = Record[Idx++];
+ E->setValueKind(static_cast<ExprValueKind>(Record[Idx++]));
+ E->setObjectKind(static_cast<ExprObjectKind>(Record[Idx++]));
+ assert(Idx == NumExprFields && "Incorrect expression field count");
+}
+
+void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
+ VisitExpr(E);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+}
+
+void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
+ VisitExpr(E);
+
+ bool HasQualifier = Record[Idx++];
+ bool HasExplicitTemplateArgs = Record[Idx++];
+
+ E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) |
+ (HasExplicitTemplateArgs
+ ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0));
+
+ if (HasQualifier) {
+ E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx);
+ E->getNameQualifier()->Range = ReadSourceRange(Record, Idx);
+ }
+
+ if (HasExplicitTemplateArgs) {
+ unsigned NumTemplateArgs = Record[Idx++];
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
+ NumTemplateArgs);
+ }
+
+ E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record, Idx);
+}
+
+void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
+ VisitExpr(E);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setValue(*Reader.getContext(), Reader.ReadAPInt(Record, Idx));
+}
+
+void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
+ VisitExpr(E);
+ E->setValue(*Reader.getContext(), Reader.ReadAPFloat(Record, Idx));
+ E->setExact(Record[Idx++]);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ VisitExpr(E);
+ E->setSubExpr(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
+ VisitExpr(E);
+ unsigned Len = Record[Idx++];
+ assert(Record[Idx] == E->getNumConcatenated() &&
+ "Wrong number of concatenated tokens!");
+ ++Idx;
+ E->setWide(Record[Idx++]);
+
+ // Read string data
+ llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len);
+ E->setString(*Reader.getContext(), Str.str());
+ Idx += Len;
+
+ // Read source locations
+ for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
+ E->setStrTokenLoc(I, ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
+ VisitExpr(E);
+ E->setValue(Record[Idx++]);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setWide(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
+ VisitExpr(E);
+ E->setLParen(ReadSourceLocation(Record, Idx));
+ E->setRParen(ReadSourceLocation(Record, Idx));
+ E->setSubExpr(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
+ VisitExpr(E);
+ unsigned NumExprs = Record[Idx++];
+ E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs];
+ for (unsigned i = 0; i != NumExprs; ++i)
+ E->Exprs[i] = Reader.ReadSubStmt();
+ E->NumExprs = NumExprs;
+ E->LParenLoc = ReadSourceLocation(Record, Idx);
+ E->RParenLoc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
+ VisitExpr(E);
+ E->setSubExpr(Reader.ReadSubExpr());
+ E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ typedef OffsetOfExpr::OffsetOfNode Node;
+ VisitExpr(E);
+ assert(E->getNumComponents() == Record[Idx]);
+ ++Idx;
+ assert(E->getNumExpressions() == Record[Idx]);
+ ++Idx;
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
+ Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]);
+ SourceLocation Start = ReadSourceLocation(Record, Idx);
+ SourceLocation End = ReadSourceLocation(Record, Idx);
+ switch (Kind) {
+ case Node::Array:
+ E->setComponent(I, Node(Start, Record[Idx++], End));
+ break;
+
+ case Node::Field:
+ E->setComponent(I,
+ Node(Start,
+ dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])),
+ End));
+ break;
+
+ case Node::Identifier:
+ E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End));
+ break;
+
+ case Node::Base: {
+ CXXBaseSpecifier *Base = new (*Reader.getContext()) CXXBaseSpecifier();
+ *Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
+ E->setComponent(I, Node(Base));
+ break;
+ }
+ }
+ }
+
+ for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
+ E->setIndexExpr(I, Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ VisitExpr(E);
+ E->setSizeof(Record[Idx++]);
+ if (Record[Idx] == 0) {
+ E->setArgument(Reader.ReadSubExpr());
+ ++Idx;
+ } else {
+ E->setArgument(GetTypeSourceInfo(Record, Idx));
+ }
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ VisitExpr(E);
+ E->setLHS(Reader.ReadSubExpr());
+ E->setRHS(Reader.ReadSubExpr());
+ E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCallExpr(CallExpr *E) {
+ VisitExpr(E);
+ E->setNumArgs(*Reader.getContext(), Record[Idx++]);
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setCallee(Reader.ReadSubExpr());
+ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ E->setArg(I, Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitMemberExpr(MemberExpr *E) {
+ // Don't call VisitExpr, this is fully initialized at creation.
+ assert(E->getStmtClass() == Stmt::MemberExprClass &&
+ "It's a subclass, we must advance Idx!");
+}
+
+void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+ VisitExpr(E);
+ E->setBase(Reader.ReadSubExpr());
+ E->setIsaMemberLoc(ReadSourceLocation(Record, Idx));
+ E->setArrow(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitCastExpr(CastExpr *E) {
+ VisitExpr(E);
+ unsigned NumBaseSpecs = Record[Idx++];
+ assert(NumBaseSpecs == E->path_size());
+ E->setSubExpr(Reader.ReadSubExpr());
+ E->setCastKind((CastExpr::CastKind)Record[Idx++]);
+ CastExpr::path_iterator BaseI = E->path_begin();
+ while (NumBaseSpecs--) {
+ CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier;
+ *BaseSpec = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
+ *BaseI++ = BaseSpec;
+ }
+}
+
+void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
+ VisitExpr(E);
+ E->setLHS(Reader.ReadSubExpr());
+ E->setRHS(Reader.ReadSubExpr());
+ E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+ VisitBinaryOperator(E);
+ E->setComputationLHSType(Reader.GetType(Record[Idx++]));
+ E->setComputationResultType(Reader.GetType(Record[Idx++]));
+}
+
+void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
+ VisitExpr(E);
+ E->SubExprs[ConditionalOperator::COND] = Reader.ReadSubExpr();
+ E->SubExprs[ConditionalOperator::LHS] = Reader.ReadSubExpr();
+ E->SubExprs[ConditionalOperator::RHS] = Reader.ReadSubExpr();
+ E->QuestionLoc = ReadSourceLocation(Record, Idx);
+ E->ColonLoc = ReadSourceLocation(Record, Idx);
+}
+
+void
+ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ VisitExpr(E);
+ E->OpaqueValue = cast<OpaqueValueExpr>(Reader.ReadSubExpr());
+ E->SubExprs[BinaryConditionalOperator::COMMON] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::COND] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::LHS] = Reader.ReadSubExpr();
+ E->SubExprs[BinaryConditionalOperator::RHS] = Reader.ReadSubExpr();
+ E->QuestionLoc = ReadSourceLocation(Record, Idx);
+ E->ColonLoc = ReadSourceLocation(Record, Idx);
+
+ E->getOpaqueValue()->setSourceExpr(E->getCommon());
+}
+
+void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ VisitCastExpr(E);
+}
+
+void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ VisitCastExpr(E);
+ E->setTypeInfoAsWritten(GetTypeSourceInfo(Record, Idx));
+}
+
+void ASTStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ E->setLParenLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ VisitExpr(E);
+ E->setLParenLoc(ReadSourceLocation(Record, Idx));
+ E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ E->setInitializer(Reader.ReadSubExpr());
+ E->setFileScope(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+ VisitExpr(E);
+ E->setBase(Reader.ReadSubExpr());
+ E->setAccessor(Reader.GetIdentifierInfo(Record, Idx));
+ E->setAccessorLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitInitListExpr(InitListExpr *E) {
+ VisitExpr(E);
+ unsigned NumInits = Record[Idx++];
+ E->reserveInits(*Reader.getContext(), NumInits);
+ for (unsigned I = 0; I != NumInits; ++I)
+ E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr());
+ E->setSyntacticForm(cast_or_null<InitListExpr>(Reader.ReadSubStmt()));
+ E->setLBraceLoc(ReadSourceLocation(Record, Idx));
+ E->setRBraceLoc(ReadSourceLocation(Record, Idx));
+ E->setInitializedFieldInUnion(
+ cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])));
+ E->sawArrayRangeDesignator(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ typedef DesignatedInitExpr::Designator Designator;
+
+ VisitExpr(E);
+ unsigned NumSubExprs = Record[Idx++];
+ assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs");
+ for (unsigned I = 0; I != NumSubExprs; ++I)
+ E->setSubExpr(I, Reader.ReadSubExpr());
+ E->setEqualOrColonLoc(ReadSourceLocation(Record, Idx));
+ E->setGNUSyntax(Record[Idx++]);
+
+ llvm::SmallVector<Designator, 4> Designators;
+ while (Idx < Record.size()) {
+ switch ((DesignatorTypes)Record[Idx++]) {
+ case DESIG_FIELD_DECL: {
+ FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
+ SourceLocation DotLoc
+ = ReadSourceLocation(Record, Idx);
+ SourceLocation FieldLoc
+ = ReadSourceLocation(Record, Idx);
+ Designators.push_back(Designator(Field->getIdentifier(), DotLoc,
+ FieldLoc));
+ Designators.back().setField(Field);
+ break;
+ }
+
+ case DESIG_FIELD_NAME: {
+ const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx);
+ SourceLocation DotLoc
+ = ReadSourceLocation(Record, Idx);
+ SourceLocation FieldLoc
+ = ReadSourceLocation(Record, Idx);
+ Designators.push_back(Designator(Name, DotLoc, FieldLoc));
+ break;
+ }
+
+ case DESIG_ARRAY: {
+ unsigned Index = Record[Idx++];
+ SourceLocation LBracketLoc
+ = ReadSourceLocation(Record, Idx);
+ SourceLocation RBracketLoc
+ = ReadSourceLocation(Record, Idx);
+ Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc));
+ break;
+ }
+
+ case DESIG_ARRAY_RANGE: {
+ unsigned Index = Record[Idx++];
+ SourceLocation LBracketLoc
+ = ReadSourceLocation(Record, Idx);
+ SourceLocation EllipsisLoc
+ = ReadSourceLocation(Record, Idx);
+ SourceLocation RBracketLoc
+ = ReadSourceLocation(Record, Idx);
+ Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc,
+ RBracketLoc));
+ break;
+ }
+ }
+ }
+ E->setDesignators(*Reader.getContext(),
+ Designators.data(), Designators.size());
+}
+
+void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+ VisitExpr(E);
+}
+
+void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) {
+ VisitExpr(E);
+ E->setSubExpr(Reader.ReadSubExpr());
+ E->setWrittenTypeInfo(GetTypeSourceInfo(Record, Idx));
+ E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ VisitExpr(E);
+ E->setAmpAmpLoc(ReadSourceLocation(Record, Idx));
+ E->setLabelLoc(ReadSourceLocation(Record, Idx));
+ E->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTStmtReader::VisitStmtExpr(StmtExpr *E) {
+ VisitExpr(E);
+ E->setLParenLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt()));
+}
+
+void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) {
+ VisitExpr(E);
+ E->setCond(Reader.ReadSubExpr());
+ E->setLHS(Reader.ReadSubExpr());
+ E->setRHS(Reader.ReadSubExpr());
+ E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
+ VisitExpr(E);
+ E->setTokenLocation(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+ VisitExpr(E);
+ llvm::SmallVector<Expr *, 16> Exprs;
+ unsigned NumExprs = Record[Idx++];
+ while (NumExprs--)
+ Exprs.push_back(Reader.ReadSubExpr());
+ E->setExprs(*Reader.getContext(), Exprs.data(), Exprs.size());
+ E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
+ VisitExpr(E);
+ E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ VisitExpr(E);
+ E->setDecl(cast<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setByRef(Record[Idx++]);
+ E->setConstQualAdded(Record[Idx++]);
+}
+
+//===----------------------------------------------------------------------===//
+// Objective-C Expressions and Statements
+
+void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+ VisitExpr(E);
+ E->setString(cast<StringLiteral>(Reader.ReadSubStmt()));
+ E->setAtLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ VisitExpr(E);
+ E->setEncodedTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ E->setAtLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+ VisitExpr(E);
+ E->setSelector(Reader.GetSelector(Record, Idx));
+ E->setAtLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+ VisitExpr(E);
+ E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setAtLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ VisitExpr(E);
+ E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setBase(Reader.ReadSubExpr());
+ E->setIsArrow(Record[Idx++]);
+ E->setIsFreeIvar(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ VisitExpr(E);
+ bool Implicit = Record[Idx++] != 0;
+ if (Implicit) {
+ ObjCMethodDecl *Getter =
+ cast<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]));
+ ObjCMethodDecl *Setter =
+ cast<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]));
+ E->setImplicitProperty(Getter, Setter);
+ } else {
+ E->setExplicitProperty(
+ cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
+ }
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setReceiverLocation(ReadSourceLocation(Record, Idx));
+ switch (Record[Idx++]) {
+ case 0:
+ E->setBase(Reader.ReadSubExpr());
+ break;
+ case 1:
+ E->setSuperReceiver(Reader.GetType(Record[Idx++]));
+ break;
+ case 2:
+ E->setClassReceiver(
+ cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+ break;
+ }
+}
+
+void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ VisitExpr(E);
+ assert(Record[Idx] == E->getNumArgs());
+ ++Idx;
+ ObjCMessageExpr::ReceiverKind Kind
+ = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]);
+ switch (Kind) {
+ case ObjCMessageExpr::Instance:
+ E->setInstanceReceiver(Reader.ReadSubExpr());
+ break;
+
+ case ObjCMessageExpr::Class:
+ E->setClassReceiver(GetTypeSourceInfo(Record, Idx));
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ case ObjCMessageExpr::SuperInstance: {
+ QualType T = Reader.GetType(Record[Idx++]);
+ SourceLocation SuperLoc = ReadSourceLocation(Record, Idx);
+ E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance);
+ break;
+ }
+ }
+
+ assert(Kind == E->getReceiverKind());
+
+ if (Record[Idx++])
+ E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
+ else
+ E->setSelector(Reader.GetSelector(Record, Idx));
+
+ E->LBracLoc = ReadSourceLocation(Record, Idx);
+ E->RBracLoc = ReadSourceLocation(Record, Idx);
+ E->SelectorLoc = ReadSourceLocation(Record, Idx);
+
+ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ E->setArg(I, Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ VisitStmt(S);
+ S->setElement(Reader.ReadSubStmt());
+ S->setCollection(Reader.ReadSubExpr());
+ S->setBody(Reader.ReadSubStmt());
+ S->setForLoc(ReadSourceLocation(Record, Idx));
+ S->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ VisitStmt(S);
+ S->setCatchBody(Reader.ReadSubStmt());
+ S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ S->setAtCatchLoc(ReadSourceLocation(Record, Idx));
+ S->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ VisitStmt(S);
+ S->setFinallyBody(Reader.ReadSubStmt());
+ S->setAtFinallyLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ VisitStmt(S);
+ assert(Record[Idx] == S->getNumCatchStmts());
+ ++Idx;
+ bool HasFinally = Record[Idx++];
+ S->setTryBody(Reader.ReadSubStmt());
+ for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
+ S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Reader.ReadSubStmt()));
+
+ if (HasFinally)
+ S->setFinallyStmt(Reader.ReadSubStmt());
+ S->setAtTryLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+ VisitStmt(S);
+ S->setSynchExpr(Reader.ReadSubStmt());
+ S->setSynchBody(Reader.ReadSubStmt());
+ S->setAtSynchronizedLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ VisitStmt(S);
+ S->setThrowExpr(Reader.ReadSubStmt());
+ S->setThrowLoc(ReadSourceLocation(Record, Idx));
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions and Statements
+//===----------------------------------------------------------------------===//
+
+void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ VisitStmt(S);
+ S->CatchLoc = ReadSourceLocation(Record, Idx);
+ S->ExceptionDecl = cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]));
+ S->HandlerBlock = Reader.ReadSubStmt();
+}
+
+void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) {
+ VisitStmt(S);
+ assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?");
+ ++Idx;
+ S->TryLoc = ReadSourceLocation(Record, Idx);
+ S->getStmts()[0] = Reader.ReadSubStmt();
+ for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
+ S->getStmts()[i + 1] = Reader.ReadSubStmt();
+}
+
+void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ VisitCallExpr(E);
+ E->setOperator((OverloadedOperatorKind)Record[Idx++]);
+}
+
+void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ VisitExpr(E);
+ E->NumArgs = Record[Idx++];
+ if (E->NumArgs)
+ E->Args = new (*Reader.getContext()) Stmt*[E->NumArgs];
+ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ E->setArg(I, Reader.ReadSubExpr());
+ E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setElidable(Record[Idx++]);
+ E->setRequiresZeroInitialization(Record[Idx++]);
+ E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]);
+ E->ParenRange = ReadSourceRange(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+ VisitCXXConstructExpr(E);
+ E->Type = GetTypeSourceInfo(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ SourceRange R = ReadSourceRange(Record, Idx);
+ E->Loc = R.getBegin();
+ E->RParenLoc = R.getEnd();
+}
+
+void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+void ASTStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+void ASTStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
+void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ E->setTypeBeginLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+ VisitExpr(E);
+ E->setValue(Record[Idx++]);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+ VisitExpr(E);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ VisitExpr(E);
+ E->setSourceRange(ReadSourceRange(Record, Idx));
+ if (E->isTypeOperand()) { // typeid(int)
+ E->setTypeOperandSourceInfo(
+ GetTypeSourceInfo(Record, Idx));
+ return;
+ }
+
+ // typeid(42+2)
+ E->setExprOperand(Reader.ReadSubExpr());
+}
+void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
+ VisitExpr(E);
+ E->setSourceRange(ReadSourceRange(Record, Idx));
+ if (E->isTypeOperand()) { // __uuidof(ComType)
+ E->setTypeOperandSourceInfo(
+ GetTypeSourceInfo(Record, Idx));
+ return;
+ }
+
+ // __uuidof(expr)
+ E->setExprOperand(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
+ VisitExpr(E);
+ E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setImplicit(Record[Idx++]);
+}
+
+void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ VisitExpr(E);
+ E->setThrowLoc(ReadSourceLocation(Record, Idx));
+ E->setSubExpr(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ VisitExpr(E);
+
+ assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?");
+ ++Idx; // HasOtherExprStored and SubExpr was handled during creation.
+ E->Param.setPointer(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ E->Loc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ VisitExpr(E);
+ E->setTemporary(Reader.ReadCXXTemporary(Record, Idx));
+ E->setSubExpr(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ VisitExpr(E);
+ E->TypeInfo = GetTypeSourceInfo(Record, Idx);
+ E->RParenLoc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
+ VisitExpr(E);
+ E->GlobalNew = Record[Idx++];
+ E->Initializer = Record[Idx++];
+ E->UsualArrayDeleteWantsSize = Record[Idx++];
+ bool isArray = Record[Idx++];
+ unsigned NumPlacementArgs = Record[Idx++];
+ unsigned NumCtorArgs = Record[Idx++];
+ E->setOperatorNew(cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setOperatorDelete(
+ cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setConstructor(
+ cast_or_null<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
+ E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx);
+ SourceRange TypeIdParens;
+ TypeIdParens.setBegin(ReadSourceLocation(Record, Idx));
+ TypeIdParens.setEnd(ReadSourceLocation(Record, Idx));
+ E->TypeIdParens = TypeIdParens;
+ E->StartLoc = ReadSourceLocation(Record, Idx);
+ E->EndLoc = ReadSourceLocation(Record, Idx);
+ E->ConstructorLParen = ReadSourceLocation(Record, Idx);
+ E->ConstructorRParen = ReadSourceLocation(Record, Idx);
+
+ E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs,
+ NumCtorArgs);
+
+ // Install all the subexpressions.
+ for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end();
+ I != e; ++I)
+ *I = Reader.ReadSubStmt();
+}
+
+void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ VisitExpr(E);
+ E->GlobalDelete = Record[Idx++];
+ E->ArrayForm = Record[Idx++];
+ E->ArrayFormAsWritten = Record[Idx++];
+ E->UsualArrayDeleteWantsSize = Record[Idx++];
+ E->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
+ E->Argument = Reader.ReadSubExpr();
+ E->Loc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ VisitExpr(E);
+
+ E->setBase(Reader.ReadSubExpr());
+ E->setArrow(Record[Idx++]);
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+ E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ E->setQualifierRange(ReadSourceRange(Record, Idx));
+ E->setScopeTypeInfo(GetTypeSourceInfo(Record, Idx));
+ E->setColonColonLoc(ReadSourceLocation(Record, Idx));
+ E->setTildeLoc(ReadSourceLocation(Record, Idx));
+
+ IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx);
+ if (II)
+ E->setDestroyedType(II, ReadSourceLocation(Record, Idx));
+ else
+ E->setDestroyedType(GetTypeSourceInfo(Record, Idx));
+}
+
+void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
+ VisitExpr(E);
+ unsigned NumTemps = Record[Idx++];
+ if (NumTemps) {
+ E->setNumTemporaries(*Reader.getContext(), NumTemps);
+ for (unsigned i = 0; i != NumTemps; ++i)
+ E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx));
+ }
+ E->setSubExpr(Reader.ReadSubExpr());
+}
+
+void
+ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+ VisitExpr(E);
+
+ if (Record[Idx++])
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
+ Record[Idx++]);
+
+ E->setBase(Reader.ReadSubExpr());
+ E->setBaseType(Reader.GetType(Record[Idx++]));
+ E->setArrow(Record[Idx++]);
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+ E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ E->setQualifierRange(ReadSourceRange(Record, Idx));
+ E->setFirstQualifierFoundInScope(
+ cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx);
+}
+
+void
+ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ VisitExpr(E);
+
+ if (Record[Idx++])
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
+ Record[Idx++]);
+
+ ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
+ E->setQualifierRange(ReadSourceRange(Record, Idx));
+ E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+}
+
+void
+ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
+ VisitExpr(E);
+ assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?");
+ ++Idx; // NumArgs;
+ for (unsigned I = 0, N = E->arg_size(); I != N; ++I)
+ E->setArg(I, Reader.ReadSubExpr());
+ E->Type = GetTypeSourceInfo(Record, Idx);
+ E->setLParenLoc(ReadSourceLocation(Record, Idx));
+ E->setRParenLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
+ VisitExpr(E);
+
+ // Read the explicit template argument list, if available.
+ if (Record[Idx++])
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
+ Record[Idx++]);
+
+ unsigned NumDecls = Record[Idx++];
+ UnresolvedSet<8> Decls;
+ for (unsigned i = 0; i != NumDecls; ++i) {
+ NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ Decls.addDecl(D, AS);
+ }
+ E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end());
+
+ ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
+ E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ E->setQualifierRange(ReadSourceRange(Record, Idx));
+}
+
+void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ VisitOverloadExpr(E);
+ E->setArrow(Record[Idx++]);
+ E->setHasUnresolvedUsing(Record[Idx++]);
+ E->setBase(Reader.ReadSubExpr());
+ E->setBaseType(Reader.GetType(Record[Idx++]));
+ E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+}
+
+void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+ VisitOverloadExpr(E);
+ E->setRequiresADL(Record[Idx++]);
+ E->setOverloaded(Record[Idx++]);
+ E->setNamingClass(cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ E->UTT = (UnaryTypeTrait)Record[Idx++];
+ E->Value = (bool)Record[Idx++];
+ SourceRange Range = ReadSourceRange(Record, Idx);
+ E->Loc = Range.getBegin();
+ E->RParen = Range.getEnd();
+ E->QueriedType = GetTypeSourceInfo(Record, Idx);
+}
+
+void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ E->BTT = (BinaryTypeTrait)Record[Idx++];
+ E->Value = (bool)Record[Idx++];
+ SourceRange Range = ReadSourceRange(Record, Idx);
+ E->Loc = Range.getBegin();
+ E->RParen = Range.getEnd();
+ E->LhsType = GetTypeSourceInfo(Record, Idx);
+ E->RhsType = GetTypeSourceInfo(Record, Idx);
+}
+
+void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ VisitExpr(E);
+ E->Value = (bool)Record[Idx++];
+ E->Range = ReadSourceRange(Record, Idx);
+ E->Operand = Reader.ReadSubExpr();
+}
+
+void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) {
+ VisitExpr(E);
+ E->EllipsisLoc = ReadSourceLocation(Record, Idx);
+ E->NumExpansions = Record[Idx++];
+ E->Pattern = Reader.ReadSubExpr();
+}
+
+void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ VisitExpr(E);
+ E->OperatorLoc = ReadSourceLocation(Record, Idx);
+ E->PackLoc = ReadSourceLocation(Record, Idx);
+ E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->Length = Record[Idx++];
+ E->Pack = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+}
+
+void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ VisitExpr(E);
+ E->Param
+ = cast_or_null<NonTypeTemplateParmDecl>(Reader.GetDecl(Record[Idx++]));
+ TemplateArgument ArgPack = Reader.ReadTemplateArgument(F, Record, Idx);
+ if (ArgPack.getKind() != TemplateArgument::Pack)
+ return;
+
+ E->Arguments = ArgPack.pack_begin();
+ E->NumArguments = ArgPack.pack_size();
+ E->NameLoc = ReadSourceLocation(Record, Idx);
+}
+
+void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ VisitExpr(E);
+ Idx++; // skip ID
+ E->Loc = ReadSourceLocation(Record, Idx);
+}
+
+//===----------------------------------------------------------------------===//
+// CUDA Expressions and Statements
+//===----------------------------------------------------------------------===//
+
+void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
+ VisitCallExpr(E);
+ E->setConfig(cast<CallExpr>(Reader.ReadSubExpr()));
+}
+
+Stmt *ASTReader::ReadStmt(PerFileData &F) {
+ switch (ReadingKind) {
+ case Read_Decl:
+ case Read_Type:
+ return ReadStmtFromStream(F);
+ case Read_Stmt:
+ return ReadSubStmt();
+ }
+
+ llvm_unreachable("ReadingKind not set ?");
+ return 0;
+}
+
+Expr *ASTReader::ReadExpr(PerFileData &F) {
+ return cast_or_null<Expr>(ReadStmt(F));
+}
+
+Expr *ASTReader::ReadSubExpr() {
+ return cast_or_null<Expr>(ReadSubStmt());
+}
+
+// Within the bitstream, expressions are stored in Reverse Polish
+// Notation, with each of the subexpressions preceding the
+// expression they are stored in. Subexpressions are stored from last to first.
+// To evaluate expressions, we continue reading expressions and placing them on
+// the stack, with expressions having operands removing those operands from the
+// stack. Evaluation terminates when we see a STMT_STOP record, and
+// the single remaining expression on the stack is our result.
+Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
+
+ ReadingKindTracker ReadingKind(Read_Stmt, *this);
+ llvm::BitstreamCursor &Cursor = F.DeclsCursor;
+
+#ifndef NDEBUG
+ unsigned PrevNumStmts = StmtStack.size();
+#endif
+
+ RecordData Record;
+ unsigned Idx;
+ ASTStmtReader Reader(*this, F, Cursor, Record, Idx);
+ Stmt::EmptyShell Empty;
+
+ while (true) {
+ unsigned Code = Cursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Cursor.ReadBlockEnd()) {
+ Error("error at end of block in AST file");
+ return 0;
+ }
+ break;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Cursor.ReadSubBlockID();
+ if (Cursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return 0;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Cursor.ReadAbbrevRecord();
+ continue;
+ }
+
+ Stmt *S = 0;
+ Idx = 0;
+ Record.clear();
+ bool Finished = false;
+ switch ((StmtCode)Cursor.ReadRecord(Code, Record)) {
+ case STMT_STOP:
+ Finished = true;
+ break;
+
+ case STMT_NULL_PTR:
+ S = 0;
+ break;
+
+ case STMT_NULL:
+ S = new (Context) NullStmt(Empty);
+ break;
+
+ case STMT_COMPOUND:
+ S = new (Context) CompoundStmt(Empty);
+ break;
+
+ case STMT_CASE:
+ S = new (Context) CaseStmt(Empty);
+ break;
+
+ case STMT_DEFAULT:
+ S = new (Context) DefaultStmt(Empty);
+ break;
+
+ case STMT_LABEL:
+ S = new (Context) LabelStmt(Empty);
+ break;
+
+ case STMT_IF:
+ S = new (Context) IfStmt(Empty);
+ break;
+
+ case STMT_SWITCH:
+ S = new (Context) SwitchStmt(Empty);
+ break;
+
+ case STMT_WHILE:
+ S = new (Context) WhileStmt(Empty);
+ break;
+
+ case STMT_DO:
+ S = new (Context) DoStmt(Empty);
+ break;
+
+ case STMT_FOR:
+ S = new (Context) ForStmt(Empty);
+ break;
+
+ case STMT_GOTO:
+ S = new (Context) GotoStmt(Empty);
+ break;
+
+ case STMT_INDIRECT_GOTO:
+ S = new (Context) IndirectGotoStmt(Empty);
+ break;
+
+ case STMT_CONTINUE:
+ S = new (Context) ContinueStmt(Empty);
+ break;
+
+ case STMT_BREAK:
+ S = new (Context) BreakStmt(Empty);
+ break;
+
+ case STMT_RETURN:
+ S = new (Context) ReturnStmt(Empty);
+ break;
+
+ case STMT_DECL:
+ S = new (Context) DeclStmt(Empty);
+ break;
+
+ case STMT_ASM:
+ S = new (Context) AsmStmt(Empty);
+ break;
+
+ case EXPR_PREDEFINED:
+ S = new (Context) PredefinedExpr(Empty);
+ break;
+
+ case EXPR_DECL_REF:
+ S = DeclRefExpr::CreateEmpty(*Context,
+ /*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 2]
+ : 0);
+ break;
+
+ case EXPR_INTEGER_LITERAL:
+ S = IntegerLiteral::Create(*Context, Empty);
+ break;
+
+ case EXPR_FLOATING_LITERAL:
+ S = FloatingLiteral::Create(*Context, Empty);
+ break;
+
+ case EXPR_IMAGINARY_LITERAL:
+ S = new (Context) ImaginaryLiteral(Empty);
+ break;
+
+ case EXPR_STRING_LITERAL:
+ S = StringLiteral::CreateEmpty(*Context,
+ Record[ASTStmtReader::NumExprFields + 1]);
+ break;
+
+ case EXPR_CHARACTER_LITERAL:
+ S = new (Context) CharacterLiteral(Empty);
+ break;
+
+ case EXPR_PAREN:
+ S = new (Context) ParenExpr(Empty);
+ break;
+
+ case EXPR_PAREN_LIST:
+ S = new (Context) ParenListExpr(Empty);
+ break;
+
+ case EXPR_UNARY_OPERATOR:
+ S = new (Context) UnaryOperator(Empty);
+ break;
+
+ case EXPR_OFFSETOF:
+ S = OffsetOfExpr::CreateEmpty(*Context,
+ Record[ASTStmtReader::NumExprFields],
+ Record[ASTStmtReader::NumExprFields + 1]);
+ break;
+
+ case EXPR_SIZEOF_ALIGN_OF:
+ S = new (Context) SizeOfAlignOfExpr(Empty);
+ break;
+
+ case EXPR_ARRAY_SUBSCRIPT:
+ S = new (Context) ArraySubscriptExpr(Empty);
+ break;
+
+ case EXPR_CALL:
+ S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty);
+ break;
+
+ case EXPR_MEMBER: {
+ // We load everything here and fully initialize it at creation.
+ // That way we can use MemberExpr::Create and don't have to duplicate its
+ // logic with a MemberExpr::CreateEmpty.
+
+ assert(Idx == 0);
+ NestedNameSpecifier *NNS = 0;
+ SourceRange QualifierRange;
+ if (Record[Idx++]) { // HasQualifier.
+ NNS = ReadNestedNameSpecifier(Record, Idx);
+ QualifierRange = ReadSourceRange(F, Record, Idx);
+ }
+
+ TemplateArgumentListInfo ArgInfo;
+ bool HasExplicitTemplateArgs = Record[Idx++];
+ if (HasExplicitTemplateArgs) {
+ unsigned NumTemplateArgs = Record[Idx++];
+ ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx));
+ ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx));
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ ArgInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Idx));
+ }
+
+ NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++]));
+ AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
+
+ QualType T = GetType(Record[Idx++]);
+ ExprValueKind VK = static_cast<ExprValueKind>(Record[Idx++]);
+ ExprObjectKind OK = static_cast<ExprObjectKind>(Record[Idx++]);
+ Expr *Base = ReadSubExpr();
+ ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++]));
+ SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx);
+ DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
+ bool IsArrow = Record[Idx++];
+
+ S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
+ MemberD, FoundDecl, MemberNameInfo,
+ HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK);
+ ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
+ MemberD->getDeclName(), Record, Idx);
+ break;
+ }
+
+ case EXPR_BINARY_OPERATOR:
+ S = new (Context) BinaryOperator(Empty);
+ break;
+
+ case EXPR_COMPOUND_ASSIGN_OPERATOR:
+ S = new (Context) CompoundAssignOperator(Empty);
+ break;
+
+ case EXPR_CONDITIONAL_OPERATOR:
+ S = new (Context) ConditionalOperator(Empty);
+ break;
+
+ case EXPR_BINARY_CONDITIONAL_OPERATOR:
+ S = new (Context) BinaryConditionalOperator(Empty);
+ break;
+
+ case EXPR_IMPLICIT_CAST:
+ S = ImplicitCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CSTYLE_CAST:
+ S = CStyleCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_COMPOUND_LITERAL:
+ S = new (Context) CompoundLiteralExpr(Empty);
+ break;
+
+ case EXPR_EXT_VECTOR_ELEMENT:
+ S = new (Context) ExtVectorElementExpr(Empty);
+ break;
+
+ case EXPR_INIT_LIST:
+ S = new (Context) InitListExpr(*getContext(), Empty);
+ break;
+
+ case EXPR_DESIGNATED_INIT:
+ S = DesignatedInitExpr::CreateEmpty(*Context,
+ Record[ASTStmtReader::NumExprFields] - 1);
+
+ break;
+
+ case EXPR_IMPLICIT_VALUE_INIT:
+ S = new (Context) ImplicitValueInitExpr(Empty);
+ break;
+
+ case EXPR_VA_ARG:
+ S = new (Context) VAArgExpr(Empty);
+ break;
+
+ case EXPR_ADDR_LABEL:
+ S = new (Context) AddrLabelExpr(Empty);
+ break;
+
+ case EXPR_STMT:
+ S = new (Context) StmtExpr(Empty);
+ break;
+
+ case EXPR_CHOOSE:
+ S = new (Context) ChooseExpr(Empty);
+ break;
+
+ case EXPR_GNU_NULL:
+ S = new (Context) GNUNullExpr(Empty);
+ break;
+
+ case EXPR_SHUFFLE_VECTOR:
+ S = new (Context) ShuffleVectorExpr(Empty);
+ break;
+
+ case EXPR_BLOCK:
+ S = new (Context) BlockExpr(Empty);
+ break;
+
+ case EXPR_BLOCK_DECL_REF:
+ S = new (Context) BlockDeclRefExpr(Empty);
+ break;
+
+ case EXPR_OBJC_STRING_LITERAL:
+ S = new (Context) ObjCStringLiteral(Empty);
+ break;
+ case EXPR_OBJC_ENCODE:
+ S = new (Context) ObjCEncodeExpr(Empty);
+ break;
+ case EXPR_OBJC_SELECTOR_EXPR:
+ S = new (Context) ObjCSelectorExpr(Empty);
+ break;
+ case EXPR_OBJC_PROTOCOL_EXPR:
+ S = new (Context) ObjCProtocolExpr(Empty);
+ break;
+ case EXPR_OBJC_IVAR_REF_EXPR:
+ S = new (Context) ObjCIvarRefExpr(Empty);
+ break;
+ case EXPR_OBJC_PROPERTY_REF_EXPR:
+ S = new (Context) ObjCPropertyRefExpr(Empty);
+ break;
+ case EXPR_OBJC_KVC_REF_EXPR:
+ llvm_unreachable("mismatching AST file");
+ break;
+ case EXPR_OBJC_MESSAGE_EXPR:
+ S = ObjCMessageExpr::CreateEmpty(*Context,
+ Record[ASTStmtReader::NumExprFields]);
+ break;
+ case EXPR_OBJC_ISA:
+ S = new (Context) ObjCIsaExpr(Empty);
+ break;
+ case STMT_OBJC_FOR_COLLECTION:
+ S = new (Context) ObjCForCollectionStmt(Empty);
+ break;
+ case STMT_OBJC_CATCH:
+ S = new (Context) ObjCAtCatchStmt(Empty);
+ break;
+ case STMT_OBJC_FINALLY:
+ S = new (Context) ObjCAtFinallyStmt(Empty);
+ break;
+ case STMT_OBJC_AT_TRY:
+ S = ObjCAtTryStmt::CreateEmpty(*Context,
+ Record[ASTStmtReader::NumStmtFields],
+ Record[ASTStmtReader::NumStmtFields + 1]);
+ break;
+ case STMT_OBJC_AT_SYNCHRONIZED:
+ S = new (Context) ObjCAtSynchronizedStmt(Empty);
+ break;
+ case STMT_OBJC_AT_THROW:
+ S = new (Context) ObjCAtThrowStmt(Empty);
+ break;
+
+ case STMT_CXX_CATCH:
+ S = new (Context) CXXCatchStmt(Empty);
+ break;
+
+ case STMT_CXX_TRY:
+ S = CXXTryStmt::Create(*Context, Empty,
+ /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]);
+ break;
+
+ case EXPR_CXX_OPERATOR_CALL:
+ S = new (Context) CXXOperatorCallExpr(*Context, Empty);
+ break;
+
+ case EXPR_CXX_MEMBER_CALL:
+ S = new (Context) CXXMemberCallExpr(*Context, Empty);
+ break;
+
+ case EXPR_CXX_CONSTRUCT:
+ S = new (Context) CXXConstructExpr(Empty);
+ break;
+
+ case EXPR_CXX_TEMPORARY_OBJECT:
+ S = new (Context) CXXTemporaryObjectExpr(Empty);
+ break;
+
+ case EXPR_CXX_STATIC_CAST:
+ S = CXXStaticCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CXX_DYNAMIC_CAST:
+ S = CXXDynamicCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CXX_REINTERPRET_CAST:
+ S = CXXReinterpretCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CXX_CONST_CAST:
+ S = CXXConstCastExpr::CreateEmpty(*Context);
+ break;
+
+ case EXPR_CXX_FUNCTIONAL_CAST:
+ S = CXXFunctionalCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CXX_BOOL_LITERAL:
+ S = new (Context) CXXBoolLiteralExpr(Empty);
+ break;
+
+ case EXPR_CXX_NULL_PTR_LITERAL:
+ S = new (Context) CXXNullPtrLiteralExpr(Empty);
+ break;
+ case EXPR_CXX_TYPEID_EXPR:
+ S = new (Context) CXXTypeidExpr(Empty, true);
+ break;
+ case EXPR_CXX_TYPEID_TYPE:
+ S = new (Context) CXXTypeidExpr(Empty, false);
+ break;
+ case EXPR_CXX_UUIDOF_EXPR:
+ S = new (Context) CXXUuidofExpr(Empty, true);
+ break;
+ case EXPR_CXX_UUIDOF_TYPE:
+ S = new (Context) CXXUuidofExpr(Empty, false);
+ break;
+ case EXPR_CXX_THIS:
+ S = new (Context) CXXThisExpr(Empty);
+ break;
+ case EXPR_CXX_THROW:
+ S = new (Context) CXXThrowExpr(Empty);
+ break;
+ case EXPR_CXX_DEFAULT_ARG: {
+ bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields];
+ if (HasOtherExprStored) {
+ Expr *SubExpr = ReadSubExpr();
+ S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr);
+ } else
+ S = new (Context) CXXDefaultArgExpr(Empty);
+ break;
+ }
+ case EXPR_CXX_BIND_TEMPORARY:
+ S = new (Context) CXXBindTemporaryExpr(Empty);
+ break;
+
+ case EXPR_CXX_SCALAR_VALUE_INIT:
+ S = new (Context) CXXScalarValueInitExpr(Empty);
+ break;
+ case EXPR_CXX_NEW:
+ S = new (Context) CXXNewExpr(Empty);
+ break;
+ case EXPR_CXX_DELETE:
+ S = new (Context) CXXDeleteExpr(Empty);
+ break;
+ case EXPR_CXX_PSEUDO_DESTRUCTOR:
+ S = new (Context) CXXPseudoDestructorExpr(Empty);
+ break;
+
+ case EXPR_EXPR_WITH_CLEANUPS:
+ S = new (Context) ExprWithCleanups(Empty);
+ break;
+
+ case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
+ S = CXXDependentScopeMemberExpr::CreateEmpty(*Context,
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+ ? Record[ASTStmtReader::NumExprFields + 1]
+ : 0);
+ break;
+
+ case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
+ S = DependentScopeDeclRefExpr::CreateEmpty(*Context,
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+ ? Record[ASTStmtReader::NumExprFields + 1]
+ : 0);
+ break;
+
+ case EXPR_CXX_UNRESOLVED_CONSTRUCT:
+ S = CXXUnresolvedConstructExpr::CreateEmpty(*Context,
+ /*NumArgs=*/Record[ASTStmtReader::NumExprFields]);
+ break;
+
+ case EXPR_CXX_UNRESOLVED_MEMBER:
+ S = UnresolvedMemberExpr::CreateEmpty(*Context,
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+ ? Record[ASTStmtReader::NumExprFields + 1]
+ : 0);
+ break;
+
+ case EXPR_CXX_UNRESOLVED_LOOKUP:
+ S = UnresolvedLookupExpr::CreateEmpty(*Context,
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
+ ? Record[ASTStmtReader::NumExprFields + 1]
+ : 0);
+ break;
+
+ case EXPR_CXX_UNARY_TYPE_TRAIT:
+ S = new (Context) UnaryTypeTraitExpr(Empty);
+ break;
+
+ case EXPR_BINARY_TYPE_TRAIT:
+ S = new (Context) BinaryTypeTraitExpr(Empty);
+ break;
+
+ case EXPR_CXX_NOEXCEPT:
+ S = new (Context) CXXNoexceptExpr(Empty);
+ break;
+
+ case EXPR_PACK_EXPANSION:
+ S = new (Context) PackExpansionExpr(Empty);
+ break;
+
+ case EXPR_SIZEOF_PACK:
+ S = new (Context) SizeOfPackExpr(Empty);
+ break;
+
+ case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK:
+ S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
+ break;
+
+ case EXPR_OPAQUE_VALUE: {
+ unsigned key = Record[ASTStmtReader::NumExprFields];
+ OpaqueValueExpr *&expr = OpaqueValueExprs[key];
+
+ // If we already have an entry for this opaque value expression,
+ // don't bother reading it again.
+ if (expr) {
+ StmtStack.push_back(expr);
+ continue;
+ }
+
+ S = expr = new (Context) OpaqueValueExpr(Empty);
+ break;
+ }
+
+ case EXPR_CUDA_KERNEL_CALL:
+ S = new (Context) CUDAKernelCallExpr(*Context, Empty);
+ break;
+ }
+
+ // We hit a STMT_STOP, so we're done with this expression.
+ if (Finished)
+ break;
+
+ ++NumStatementsRead;
+
+ if (S)
+ Reader.Visit(S);
+
+ assert(Idx == Record.size() && "Invalid deserialization of statement");
+ StmtStack.push_back(S);
+ }
+
+#ifndef NDEBUG
+ assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!");
+ assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!");
+#endif
+
+ return StmtStack.pop_back_val();
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
new file mode 100644
index 0000000..8fcb535
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -0,0 +1,3841 @@
+//===--- ASTWriter.cpp - AST File Writer ----------------------------------===//
+//
+// 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 ASTWriter class, which writes AST files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ASTSerializationListener.h"
+#include "ASTCommon.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include <cstdio>
+#include <string.h>
+using namespace clang;
+using namespace clang::serialization;
+
+template <typename T, typename Allocator>
+T *data(std::vector<T, Allocator> &v) {
+ return v.empty() ? 0 : &v.front();
+}
+template <typename T, typename Allocator>
+const T *data(const std::vector<T, Allocator> &v) {
+ return v.empty() ? 0 : &v.front();
+}
+
+//===----------------------------------------------------------------------===//
+// Type serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class ASTTypeWriter {
+ ASTWriter &Writer;
+ ASTWriter::RecordDataImpl &Record;
+
+ public:
+ /// \brief Type code that corresponds to the record generated.
+ TypeCode Code;
+
+ ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
+ : Writer(Writer), Record(Record), Code(TYPE_EXT_QUAL) { }
+
+ void VisitArrayType(const ArrayType *T);
+ void VisitFunctionType(const FunctionType *T);
+ void VisitTagType(const TagType *T);
+
+#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ };
+}
+
+void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
+ assert(false && "Built-in types are never serialized");
+}
+
+void ASTTypeWriter::VisitComplexType(const ComplexType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Code = TYPE_COMPLEX;
+}
+
+void ASTTypeWriter::VisitPointerType(const PointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = TYPE_POINTER;
+}
+
+void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = TYPE_BLOCK_POINTER;
+}
+
+void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = TYPE_LVALUE_REFERENCE;
+}
+
+void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = TYPE_RVALUE_REFERENCE;
+}
+
+void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
+ Code = TYPE_MEMBER_POINTER;
+}
+
+void ASTTypeWriter::VisitArrayType(const ArrayType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Record.push_back(T->getSizeModifier()); // FIXME: stable values
+ Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
+}
+
+void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
+ VisitArrayType(T);
+ Writer.AddAPInt(T->getSize(), Record);
+ Code = TYPE_CONSTANT_ARRAY;
+}
+
+void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+ VisitArrayType(T);
+ Code = TYPE_INCOMPLETE_ARRAY;
+}
+
+void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
+ VisitArrayType(T);
+ Writer.AddSourceLocation(T->getLBracketLoc(), Record);
+ Writer.AddSourceLocation(T->getRBracketLoc(), Record);
+ Writer.AddStmt(T->getSizeExpr());
+ Code = TYPE_VARIABLE_ARRAY;
+}
+
+void ASTTypeWriter::VisitVectorType(const VectorType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Record.push_back(T->getNumElements());
+ Record.push_back(T->getVectorKind());
+ Code = TYPE_VECTOR;
+}
+
+void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
+ VisitVectorType(T);
+ Code = TYPE_EXT_VECTOR;
+}
+
+void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
+ Writer.AddTypeRef(T->getResultType(), Record);
+ FunctionType::ExtInfo C = T->getExtInfo();
+ Record.push_back(C.getNoReturn());
+ Record.push_back(C.getRegParm());
+ // FIXME: need to stabilize encoding of calling convention...
+ Record.push_back(C.getCC());
+}
+
+void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+ VisitFunctionType(T);
+ Code = TYPE_FUNCTION_NO_PROTO;
+}
+
+void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
+ VisitFunctionType(T);
+ Record.push_back(T->getNumArgs());
+ for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
+ Writer.AddTypeRef(T->getArgType(I), Record);
+ Record.push_back(T->isVariadic());
+ Record.push_back(T->getTypeQuals());
+ Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
+ Record.push_back(T->hasExceptionSpec());
+ Record.push_back(T->hasAnyExceptionSpec());
+ Record.push_back(T->getNumExceptions());
+ for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
+ Writer.AddTypeRef(T->getExceptionType(I), Record);
+ Code = TYPE_FUNCTION_PROTO;
+}
+
+void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = TYPE_UNRESOLVED_USING;
+}
+
+void ASTTypeWriter::VisitTypedefType(const TypedefType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ assert(!T->isCanonicalUnqualified() && "Invalid typedef ?");
+ Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record);
+ Code = TYPE_TYPEDEF;
+}
+
+void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
+ Writer.AddStmt(T->getUnderlyingExpr());
+ Code = TYPE_TYPEOF_EXPR;
+}
+
+void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) {
+ Writer.AddTypeRef(T->getUnderlyingType(), Record);
+ Code = TYPE_TYPEOF;
+}
+
+void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) {
+ Writer.AddStmt(T->getUnderlyingExpr());
+ Code = TYPE_DECLTYPE;
+}
+
+void ASTTypeWriter::VisitAutoType(const AutoType *T) {
+ Writer.AddTypeRef(T->getDeducedType(), Record);
+ Code = TYPE_AUTO;
+}
+
+void ASTTypeWriter::VisitTagType(const TagType *T) {
+ Record.push_back(T->isDependentType());
+ Writer.AddDeclRef(T->getDecl(), Record);
+ assert(!T->isBeingDefined() &&
+ "Cannot serialize in the middle of a type definition");
+}
+
+void ASTTypeWriter::VisitRecordType(const RecordType *T) {
+ VisitTagType(T);
+ Code = TYPE_RECORD;
+}
+
+void ASTTypeWriter::VisitEnumType(const EnumType *T) {
+ VisitTagType(T);
+ Code = TYPE_ENUM;
+}
+
+void ASTTypeWriter::VisitAttributedType(const AttributedType *T) {
+ Writer.AddTypeRef(T->getModifiedType(), Record);
+ Writer.AddTypeRef(T->getEquivalentType(), Record);
+ Record.push_back(T->getAttrKind());
+ Code = TYPE_ATTRIBUTED;
+}
+
+void
+ASTTypeWriter::VisitSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T) {
+ Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
+ Writer.AddTypeRef(T->getReplacementType(), Record);
+ Code = TYPE_SUBST_TEMPLATE_TYPE_PARM;
+}
+
+void
+ASTTypeWriter::VisitSubstTemplateTypeParmPackType(
+ const SubstTemplateTypeParmPackType *T) {
+ Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
+ Writer.AddTemplateArgument(T->getArgumentPack(), Record);
+ Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK;
+}
+
+void
+ASTTypeWriter::VisitTemplateSpecializationType(
+ const TemplateSpecializationType *T) {
+ Record.push_back(T->isDependentType());
+ Writer.AddTemplateName(T->getTemplateName(), Record);
+ Record.push_back(T->getNumArgs());
+ for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end();
+ ArgI != ArgE; ++ArgI)
+ Writer.AddTemplateArgument(*ArgI, Record);
+ Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
+ : T->getCanonicalTypeInternal(),
+ Record);
+ Code = TYPE_TEMPLATE_SPECIALIZATION;
+}
+
+void
+ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
+ VisitArrayType(T);
+ Writer.AddStmt(T->getSizeExpr());
+ Writer.AddSourceRange(T->getBracketsRange(), Record);
+ Code = TYPE_DEPENDENT_SIZED_ARRAY;
+}
+
+void
+ASTTypeWriter::VisitDependentSizedExtVectorType(
+ const DependentSizedExtVectorType *T) {
+ // FIXME: Serialize this type (C++ only)
+ assert(false && "Cannot serialize dependent sized extended vector types");
+}
+
+void
+ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ Record.push_back(T->getDepth());
+ Record.push_back(T->getIndex());
+ Record.push_back(T->isParameterPack());
+ Writer.AddIdentifierRef(T->getName(), Record);
+ Code = TYPE_TEMPLATE_TYPE_PARM;
+}
+
+void
+ASTTypeWriter::VisitDependentNameType(const DependentNameType *T) {
+ Record.push_back(T->getKeyword());
+ Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
+ Writer.AddIdentifierRef(T->getIdentifier(), Record);
+ Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
+ : T->getCanonicalTypeInternal(),
+ Record);
+ Code = TYPE_DEPENDENT_NAME;
+}
+
+void
+ASTTypeWriter::VisitDependentTemplateSpecializationType(
+ const DependentTemplateSpecializationType *T) {
+ Record.push_back(T->getKeyword());
+ Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
+ Writer.AddIdentifierRef(T->getIdentifier(), Record);
+ Record.push_back(T->getNumArgs());
+ for (DependentTemplateSpecializationType::iterator
+ I = T->begin(), E = T->end(); I != E; ++I)
+ Writer.AddTemplateArgument(*I, Record);
+ Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
+}
+
+void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) {
+ Writer.AddTypeRef(T->getPattern(), Record);
+ if (llvm::Optional<unsigned> NumExpansions = T->getNumExpansions())
+ Record.push_back(*NumExpansions + 1);
+ else
+ Record.push_back(0);
+ Code = TYPE_PACK_EXPANSION;
+}
+
+void ASTTypeWriter::VisitParenType(const ParenType *T) {
+ Writer.AddTypeRef(T->getInnerType(), Record);
+ Code = TYPE_PAREN;
+}
+
+void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
+ Record.push_back(T->getKeyword());
+ Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
+ Writer.AddTypeRef(T->getNamedType(), Record);
+ Code = TYPE_ELABORATED;
+}
+
+void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Writer.AddTypeRef(T->getInjectedSpecializationType(), Record);
+ Code = TYPE_INJECTED_CLASS_NAME;
+}
+
+void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = TYPE_OBJC_INTERFACE;
+}
+
+void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
+ Writer.AddTypeRef(T->getBaseType(), Record);
+ Record.push_back(T->getNumProtocols());
+ for (ObjCObjectType::qual_iterator I = T->qual_begin(),
+ E = T->qual_end(); I != E; ++I)
+ Writer.AddDeclRef(*I, Record);
+ Code = TYPE_OBJC_OBJECT;
+}
+
+void
+ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ Writer.AddTypeRef(T->getPointeeType(), Record);
+ Code = TYPE_OBJC_OBJECT_POINTER;
+}
+
+namespace {
+
+class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
+ ASTWriter &Writer;
+ ASTWriter::RecordDataImpl &Record;
+
+public:
+ TypeLocWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
+ : Writer(Writer), Record(Record) { }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
+ void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
+};
+
+}
+
+void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ // nothing to do
+}
+void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getBuiltinLoc(), Record);
+ if (TL.needsExtraLocalData()) {
+ Record.push_back(TL.getWrittenTypeSpec());
+ Record.push_back(TL.getWrittenSignSpec());
+ Record.push_back(TL.getWrittenWidthSpec());
+ Record.push_back(TL.hasModeAttr());
+ }
+}
+void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getCaretLoc(), Record);
+}
+void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getAmpLoc(), Record);
+}
+void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
+}
+void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
+ Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
+ Record.push_back(TL.getSizeExpr() ? 1 : 0);
+ if (TL.getSizeExpr())
+ Writer.AddStmt(TL.getSizeExpr());
+}
+void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
+ DependentSizedArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
+ DependentSizedExtVectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+ Record.push_back(TL.getTrailingReturn());
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ Writer.AddDeclRef(TL.getArg(i), Record);
+}
+void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+ Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
+}
+void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getAttrNameLoc(), Record);
+ if (TL.hasAttrOperand()) {
+ SourceRange range = TL.getAttrOperandParensRange();
+ Writer.AddSourceLocation(range.getBegin(), Record);
+ Writer.AddSourceLocation(range.getEnd(), Record);
+ }
+ if (TL.hasAttrExprOperand()) {
+ Expr *operand = TL.getAttrExprOperand();
+ Record.push_back(operand ? 1 : 0);
+ if (operand) Writer.AddStmt(operand);
+ } else if (TL.hasAttrEnumOperand()) {
+ Writer.AddSourceLocation(TL.getAttrEnumOperandLoc(), Record);
+ }
+}
+void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),
+ TL.getArgLoc(i).getLocInfo(), Record);
+}
+void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+}
+void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
+ Writer.AddSourceRange(TL.getQualifierRange(), Record);
+}
+void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
+ Writer.AddSourceRange(TL.getQualifierRange(), Record);
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
+ Writer.AddSourceRange(TL.getQualifierRange(), Record);
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),
+ TL.getArgLoc(I).getLocInfo(), Record);
+}
+void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getEllipsisLoc(), Record);
+}
+void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
+ Record.push_back(TL.hasBaseTypeAsWritten());
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
+}
+void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+
+//===----------------------------------------------------------------------===//
+// ASTWriter Implementation
+//===----------------------------------------------------------------------===//
+
+static void EmitBlockID(unsigned ID, const char *Name,
+ llvm::BitstreamWriter &Stream,
+ ASTWriter::RecordDataImpl &Record) {
+ Record.clear();
+ Record.push_back(ID);
+ Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
+
+ // Emit the block name if present.
+ if (Name == 0 || Name[0] == 0) return;
+ Record.clear();
+ while (*Name)
+ Record.push_back(*Name++);
+ Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
+}
+
+static void EmitRecordID(unsigned ID, const char *Name,
+ llvm::BitstreamWriter &Stream,
+ ASTWriter::RecordDataImpl &Record) {
+ Record.clear();
+ Record.push_back(ID);
+ while (*Name)
+ Record.push_back(*Name++);
+ Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
+}
+
+static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
+ ASTWriter::RecordDataImpl &Record) {
+#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
+ RECORD(STMT_STOP);
+ RECORD(STMT_NULL_PTR);
+ RECORD(STMT_NULL);
+ RECORD(STMT_COMPOUND);
+ RECORD(STMT_CASE);
+ RECORD(STMT_DEFAULT);
+ RECORD(STMT_LABEL);
+ RECORD(STMT_IF);
+ RECORD(STMT_SWITCH);
+ RECORD(STMT_WHILE);
+ RECORD(STMT_DO);
+ RECORD(STMT_FOR);
+ RECORD(STMT_GOTO);
+ RECORD(STMT_INDIRECT_GOTO);
+ RECORD(STMT_CONTINUE);
+ RECORD(STMT_BREAK);
+ RECORD(STMT_RETURN);
+ RECORD(STMT_DECL);
+ RECORD(STMT_ASM);
+ RECORD(EXPR_PREDEFINED);
+ RECORD(EXPR_DECL_REF);
+ RECORD(EXPR_INTEGER_LITERAL);
+ RECORD(EXPR_FLOATING_LITERAL);
+ RECORD(EXPR_IMAGINARY_LITERAL);
+ RECORD(EXPR_STRING_LITERAL);
+ RECORD(EXPR_CHARACTER_LITERAL);
+ RECORD(EXPR_PAREN);
+ RECORD(EXPR_UNARY_OPERATOR);
+ RECORD(EXPR_SIZEOF_ALIGN_OF);
+ RECORD(EXPR_ARRAY_SUBSCRIPT);
+ RECORD(EXPR_CALL);
+ RECORD(EXPR_MEMBER);
+ RECORD(EXPR_BINARY_OPERATOR);
+ RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);
+ RECORD(EXPR_CONDITIONAL_OPERATOR);
+ RECORD(EXPR_IMPLICIT_CAST);
+ RECORD(EXPR_CSTYLE_CAST);
+ RECORD(EXPR_COMPOUND_LITERAL);
+ RECORD(EXPR_EXT_VECTOR_ELEMENT);
+ RECORD(EXPR_INIT_LIST);
+ RECORD(EXPR_DESIGNATED_INIT);
+ RECORD(EXPR_IMPLICIT_VALUE_INIT);
+ RECORD(EXPR_VA_ARG);
+ RECORD(EXPR_ADDR_LABEL);
+ RECORD(EXPR_STMT);
+ RECORD(EXPR_CHOOSE);
+ RECORD(EXPR_GNU_NULL);
+ RECORD(EXPR_SHUFFLE_VECTOR);
+ RECORD(EXPR_BLOCK);
+ RECORD(EXPR_BLOCK_DECL_REF);
+ RECORD(EXPR_OBJC_STRING_LITERAL);
+ RECORD(EXPR_OBJC_ENCODE);
+ RECORD(EXPR_OBJC_SELECTOR_EXPR);
+ RECORD(EXPR_OBJC_PROTOCOL_EXPR);
+ RECORD(EXPR_OBJC_IVAR_REF_EXPR);
+ RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);
+ RECORD(EXPR_OBJC_KVC_REF_EXPR);
+ RECORD(EXPR_OBJC_MESSAGE_EXPR);
+ RECORD(STMT_OBJC_FOR_COLLECTION);
+ RECORD(STMT_OBJC_CATCH);
+ RECORD(STMT_OBJC_FINALLY);
+ RECORD(STMT_OBJC_AT_TRY);
+ RECORD(STMT_OBJC_AT_SYNCHRONIZED);
+ RECORD(STMT_OBJC_AT_THROW);
+ RECORD(EXPR_CXX_OPERATOR_CALL);
+ RECORD(EXPR_CXX_CONSTRUCT);
+ RECORD(EXPR_CXX_STATIC_CAST);
+ RECORD(EXPR_CXX_DYNAMIC_CAST);
+ RECORD(EXPR_CXX_REINTERPRET_CAST);
+ RECORD(EXPR_CXX_CONST_CAST);
+ RECORD(EXPR_CXX_FUNCTIONAL_CAST);
+ RECORD(EXPR_CXX_BOOL_LITERAL);
+ RECORD(EXPR_CXX_NULL_PTR_LITERAL);
+ RECORD(EXPR_CXX_TYPEID_EXPR);
+ RECORD(EXPR_CXX_TYPEID_TYPE);
+ RECORD(EXPR_CXX_UUIDOF_EXPR);
+ RECORD(EXPR_CXX_UUIDOF_TYPE);
+ RECORD(EXPR_CXX_THIS);
+ RECORD(EXPR_CXX_THROW);
+ RECORD(EXPR_CXX_DEFAULT_ARG);
+ RECORD(EXPR_CXX_BIND_TEMPORARY);
+ RECORD(EXPR_CXX_SCALAR_VALUE_INIT);
+ RECORD(EXPR_CXX_NEW);
+ RECORD(EXPR_CXX_DELETE);
+ RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR);
+ RECORD(EXPR_EXPR_WITH_CLEANUPS);
+ RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER);
+ RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF);
+ RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);
+ RECORD(EXPR_CXX_UNRESOLVED_MEMBER);
+ RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);
+ RECORD(EXPR_CXX_UNARY_TYPE_TRAIT);
+ RECORD(EXPR_CXX_NOEXCEPT);
+ RECORD(EXPR_OPAQUE_VALUE);
+ RECORD(EXPR_BINARY_TYPE_TRAIT);
+ RECORD(EXPR_PACK_EXPANSION);
+ RECORD(EXPR_SIZEOF_PACK);
+ RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
+ RECORD(EXPR_CUDA_KERNEL_CALL);
+#undef RECORD
+}
+
+void ASTWriter::WriteBlockInfoBlock() {
+ RecordData Record;
+ Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
+
+#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)
+#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
+
+ // AST Top-Level Block.
+ BLOCK(AST_BLOCK);
+ RECORD(ORIGINAL_FILE_NAME);
+ RECORD(TYPE_OFFSET);
+ RECORD(DECL_OFFSET);
+ RECORD(LANGUAGE_OPTIONS);
+ RECORD(METADATA);
+ RECORD(IDENTIFIER_OFFSET);
+ RECORD(IDENTIFIER_TABLE);
+ RECORD(EXTERNAL_DEFINITIONS);
+ RECORD(SPECIAL_TYPES);
+ RECORD(STATISTICS);
+ RECORD(TENTATIVE_DEFINITIONS);
+ RECORD(UNUSED_FILESCOPED_DECLS);
+ RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
+ RECORD(SELECTOR_OFFSETS);
+ RECORD(METHOD_POOL);
+ RECORD(PP_COUNTER_VALUE);
+ RECORD(SOURCE_LOCATION_OFFSETS);
+ RECORD(SOURCE_LOCATION_PRELOADS);
+ RECORD(STAT_CACHE);
+ RECORD(EXT_VECTOR_DECLS);
+ RECORD(VERSION_CONTROL_BRANCH_REVISION);
+ RECORD(MACRO_DEFINITION_OFFSETS);
+ RECORD(CHAINED_METADATA);
+ RECORD(REFERENCED_SELECTOR_POOL);
+ RECORD(TU_UPDATE_LEXICAL);
+ RECORD(REDECLS_UPDATE_LATEST);
+ RECORD(SEMA_DECL_REFS);
+ RECORD(WEAK_UNDECLARED_IDENTIFIERS);
+ RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
+ RECORD(DECL_REPLACEMENTS);
+ RECORD(UPDATE_VISIBLE);
+ RECORD(DECL_UPDATE_OFFSETS);
+ RECORD(DECL_UPDATES);
+ RECORD(CXX_BASE_SPECIFIER_OFFSETS);
+ RECORD(DIAG_PRAGMA_MAPPINGS);
+ RECORD(CUDA_SPECIAL_DECL_REFS);
+ RECORD(HEADER_SEARCH_TABLE);
+ RECORD(FP_PRAGMA_OPTIONS);
+ RECORD(OPENCL_EXTENSIONS);
+
+ // SourceManager Block.
+ BLOCK(SOURCE_MANAGER_BLOCK);
+ RECORD(SM_SLOC_FILE_ENTRY);
+ RECORD(SM_SLOC_BUFFER_ENTRY);
+ RECORD(SM_SLOC_BUFFER_BLOB);
+ RECORD(SM_SLOC_INSTANTIATION_ENTRY);
+ RECORD(SM_LINE_TABLE);
+
+ // Preprocessor Block.
+ BLOCK(PREPROCESSOR_BLOCK);
+ RECORD(PP_MACRO_OBJECT_LIKE);
+ RECORD(PP_MACRO_FUNCTION_LIKE);
+ RECORD(PP_TOKEN);
+
+ // Decls and Types block.
+ BLOCK(DECLTYPES_BLOCK);
+ RECORD(TYPE_EXT_QUAL);
+ RECORD(TYPE_COMPLEX);
+ RECORD(TYPE_POINTER);
+ RECORD(TYPE_BLOCK_POINTER);
+ RECORD(TYPE_LVALUE_REFERENCE);
+ RECORD(TYPE_RVALUE_REFERENCE);
+ RECORD(TYPE_MEMBER_POINTER);
+ RECORD(TYPE_CONSTANT_ARRAY);
+ RECORD(TYPE_INCOMPLETE_ARRAY);
+ RECORD(TYPE_VARIABLE_ARRAY);
+ RECORD(TYPE_VECTOR);
+ RECORD(TYPE_EXT_VECTOR);
+ RECORD(TYPE_FUNCTION_PROTO);
+ RECORD(TYPE_FUNCTION_NO_PROTO);
+ RECORD(TYPE_TYPEDEF);
+ RECORD(TYPE_TYPEOF_EXPR);
+ RECORD(TYPE_TYPEOF);
+ RECORD(TYPE_RECORD);
+ RECORD(TYPE_ENUM);
+ RECORD(TYPE_OBJC_INTERFACE);
+ RECORD(TYPE_OBJC_OBJECT);
+ RECORD(TYPE_OBJC_OBJECT_POINTER);
+ RECORD(TYPE_DECLTYPE);
+ RECORD(TYPE_ELABORATED);
+ RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM);
+ RECORD(TYPE_UNRESOLVED_USING);
+ RECORD(TYPE_INJECTED_CLASS_NAME);
+ RECORD(TYPE_OBJC_OBJECT);
+ RECORD(TYPE_TEMPLATE_TYPE_PARM);
+ RECORD(TYPE_TEMPLATE_SPECIALIZATION);
+ RECORD(TYPE_DEPENDENT_NAME);
+ RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION);
+ RECORD(TYPE_DEPENDENT_SIZED_ARRAY);
+ RECORD(TYPE_PAREN);
+ RECORD(TYPE_PACK_EXPANSION);
+ RECORD(TYPE_ATTRIBUTED);
+ RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
+ RECORD(DECL_TRANSLATION_UNIT);
+ RECORD(DECL_TYPEDEF);
+ RECORD(DECL_ENUM);
+ RECORD(DECL_RECORD);
+ RECORD(DECL_ENUM_CONSTANT);
+ RECORD(DECL_FUNCTION);
+ RECORD(DECL_OBJC_METHOD);
+ RECORD(DECL_OBJC_INTERFACE);
+ RECORD(DECL_OBJC_PROTOCOL);
+ RECORD(DECL_OBJC_IVAR);
+ RECORD(DECL_OBJC_AT_DEFS_FIELD);
+ RECORD(DECL_OBJC_CLASS);
+ RECORD(DECL_OBJC_FORWARD_PROTOCOL);
+ RECORD(DECL_OBJC_CATEGORY);
+ RECORD(DECL_OBJC_CATEGORY_IMPL);
+ RECORD(DECL_OBJC_IMPLEMENTATION);
+ RECORD(DECL_OBJC_COMPATIBLE_ALIAS);
+ RECORD(DECL_OBJC_PROPERTY);
+ RECORD(DECL_OBJC_PROPERTY_IMPL);
+ RECORD(DECL_FIELD);
+ RECORD(DECL_VAR);
+ RECORD(DECL_IMPLICIT_PARAM);
+ RECORD(DECL_PARM_VAR);
+ RECORD(DECL_FILE_SCOPE_ASM);
+ RECORD(DECL_BLOCK);
+ RECORD(DECL_CONTEXT_LEXICAL);
+ RECORD(DECL_CONTEXT_VISIBLE);
+ RECORD(DECL_NAMESPACE);
+ RECORD(DECL_NAMESPACE_ALIAS);
+ RECORD(DECL_USING);
+ RECORD(DECL_USING_SHADOW);
+ RECORD(DECL_USING_DIRECTIVE);
+ RECORD(DECL_UNRESOLVED_USING_VALUE);
+ RECORD(DECL_UNRESOLVED_USING_TYPENAME);
+ RECORD(DECL_LINKAGE_SPEC);
+ RECORD(DECL_CXX_RECORD);
+ RECORD(DECL_CXX_METHOD);
+ RECORD(DECL_CXX_CONSTRUCTOR);
+ RECORD(DECL_CXX_DESTRUCTOR);
+ RECORD(DECL_CXX_CONVERSION);
+ RECORD(DECL_ACCESS_SPEC);
+ RECORD(DECL_FRIEND);
+ RECORD(DECL_FRIEND_TEMPLATE);
+ RECORD(DECL_CLASS_TEMPLATE);
+ RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);
+ RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);
+ RECORD(DECL_FUNCTION_TEMPLATE);
+ RECORD(DECL_TEMPLATE_TYPE_PARM);
+ RECORD(DECL_NON_TYPE_TEMPLATE_PARM);
+ RECORD(DECL_TEMPLATE_TEMPLATE_PARM);
+ RECORD(DECL_STATIC_ASSERT);
+ RECORD(DECL_CXX_BASE_SPECIFIERS);
+ RECORD(DECL_INDIRECTFIELD);
+ RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);
+
+ BLOCK(PREPROCESSOR_DETAIL_BLOCK);
+ RECORD(PPD_MACRO_INSTANTIATION);
+ RECORD(PPD_MACRO_DEFINITION);
+ RECORD(PPD_INCLUSION_DIRECTIVE);
+
+ // Statements and Exprs can occur in the Decls and Types block.
+ AddStmtsExprs(Stream, Record);
+#undef RECORD
+#undef BLOCK
+ Stream.ExitBlock();
+}
+
+/// \brief Adjusts the given filename to only write out the portion of the
+/// filename that is not part of the system root directory.
+///
+/// \param Filename the file name to adjust.
+///
+/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and
+/// the returned filename will be adjusted by this system root.
+///
+/// \returns either the original filename (if it needs no adjustment) or the
+/// adjusted filename (which points into the @p Filename parameter).
+static const char *
+adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
+ assert(Filename && "No file name to adjust?");
+
+ if (!isysroot)
+ return Filename;
+
+ // Verify that the filename and the system root have the same prefix.
+ unsigned Pos = 0;
+ for (; Filename[Pos] && isysroot[Pos]; ++Pos)
+ if (Filename[Pos] != isysroot[Pos])
+ return Filename; // Prefixes don't match.
+
+ // We hit the end of the filename before we hit the end of the system root.
+ if (!Filename[Pos])
+ return Filename;
+
+ // If the file name has a '/' at the current position, skip over the '/'.
+ // We distinguish sysroot-based includes from absolute includes by the
+ // absence of '/' at the beginning of sysroot-based includes.
+ if (Filename[Pos] == '/')
+ ++Pos;
+
+ return Filename + Pos;
+}
+
+/// \brief Write the AST metadata (e.g., i686-apple-darwin9).
+void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot,
+ const std::string &OutputFile) {
+ using namespace llvm;
+
+ // Metadata
+ const TargetInfo &Target = Context.Target;
+ BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
+ MetaAbbrev->Add(BitCodeAbbrevOp(
+ Chain ? CHAINED_METADATA : METADATA));
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
+ // Target triple or chained PCH name
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
+
+ RecordData Record;
+ Record.push_back(Chain ? CHAINED_METADATA : METADATA);
+ Record.push_back(VERSION_MAJOR);
+ Record.push_back(VERSION_MINOR);
+ Record.push_back(CLANG_VERSION_MAJOR);
+ Record.push_back(CLANG_VERSION_MINOR);
+ Record.push_back(isysroot != 0);
+ // FIXME: This writes the absolute path for chained headers.
+ const std::string &BlobStr = Chain ? Chain->getFileName() : Target.getTriple().getTriple();
+ Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, BlobStr);
+
+ // Original file name
+ SourceManager &SM = Context.getSourceManager();
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+ BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
+ FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE_NAME));
+ FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+ unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
+
+ llvm::SmallString<128> MainFilePath(MainFile->getName());
+
+ llvm::sys::fs::make_absolute(MainFilePath);
+
+ const char *MainFileNameStr = MainFilePath.c_str();
+ MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
+ isysroot);
+ RecordData Record;
+ Record.push_back(ORIGINAL_FILE_NAME);
+ Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
+ }
+
+ // Original PCH directory
+ if (!OutputFile.empty() && OutputFile != "-") {
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+
+ llvm::SmallString<128> OutputPath(OutputFile);
+
+ llvm::sys::fs::make_absolute(OutputPath);
+ StringRef origDir = llvm::sys::path::parent_path(OutputPath);
+
+ RecordData Record;
+ Record.push_back(ORIGINAL_PCH_DIR);
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir);
+ }
+
+ // Repository branch/version information.
+ BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
+ RepoAbbrev->Add(BitCodeAbbrevOp(VERSION_CONTROL_BRANCH_REVISION));
+ RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
+ unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
+ Record.clear();
+ Record.push_back(VERSION_CONTROL_BRANCH_REVISION);
+ Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
+ getClangFullRepositoryVersion());
+}
+
+/// \brief Write the LangOptions structure.
+void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
+ RecordData Record;
+ Record.push_back(LangOpts.Trigraphs);
+ Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments.
+ Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers.
+ Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode.
+ Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc)
+ Record.push_back(LangOpts.GNUKeywords); // Allow GNU-extension keywords
+ Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'.
+ Record.push_back(LangOpts.Digraphs); // C94, C99 and C++
+ Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants.
+ Record.push_back(LangOpts.C99); // C99 Support
+ Record.push_back(LangOpts.Microsoft); // Microsoft extensions.
+ // LangOpts.MSCVersion is ignored because all it does it set a macro, which is
+ // already saved elsewhere.
+ Record.push_back(LangOpts.CPlusPlus); // C++ Support
+ Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support
+ Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords.
+
+ Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled.
+ Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled.
+ Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C
+ // modern abi enabled.
+ Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced
+ // modern abi enabled.
+ Record.push_back(LangOpts.AppleKext); // Apple's kernel extensions ABI
+ Record.push_back(LangOpts.ObjCDefaultSynthProperties); // Objective-C auto-synthesized
+ // properties enabled.
+ Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled..
+
+ Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings
+ Record.push_back(LangOpts.WritableStrings); // Allow writable strings
+ Record.push_back(LangOpts.LaxVectorConversions);
+ Record.push_back(LangOpts.AltiVec);
+ Record.push_back(LangOpts.Exceptions); // Support exception handling.
+ Record.push_back(LangOpts.SjLjExceptions);
+ Record.push_back(LangOpts.ObjCExceptions);
+
+ Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout
+ Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
+ Record.push_back(LangOpts.Freestanding); // Freestanding implementation
+ Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin)
+
+ // Whether static initializers are protected by locks.
+ Record.push_back(LangOpts.ThreadsafeStatics);
+ Record.push_back(LangOpts.POSIXThreads);
+ Record.push_back(LangOpts.Blocks); // block extension to C
+ Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if
+ // they are unused.
+ Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
+ // (modulo the platform support).
+
+ Record.push_back(LangOpts.getSignedOverflowBehavior());
+ Record.push_back(LangOpts.HeinousExtensions);
+
+ Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
+ Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
+ // defined.
+ Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as
+ // opposed to __DYNAMIC__).
+ Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero.
+
+ Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be
+ // used (instead of C99 semantics).
+ Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined.
+ Record.push_back(LangOpts.AccessControl); // Whether C++ access control should
+ // be enabled.
+ Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
+ // unsigned type
+ Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short
+ Record.push_back(LangOpts.ShortEnums); // Should the enum type be equivalent
+ // to the smallest integer type with
+ // enough room.
+ Record.push_back(LangOpts.getGCMode());
+ Record.push_back(LangOpts.getVisibilityMode());
+ Record.push_back(LangOpts.getStackProtectorMode());
+ Record.push_back(LangOpts.InstantiationDepth);
+ Record.push_back(LangOpts.OpenCL);
+ Record.push_back(LangOpts.CUDA);
+ Record.push_back(LangOpts.CatchUndefined);
+ Record.push_back(LangOpts.DefaultFPContract);
+ Record.push_back(LangOpts.ElideConstructors);
+ Record.push_back(LangOpts.SpellChecking);
+ Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
+}
+
+//===----------------------------------------------------------------------===//
+// stat cache Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+// Trait used for the on-disk hash table of stat cache results.
+class ASTStatCacheTrait {
+public:
+ typedef const char * key_type;
+ typedef key_type key_type_ref;
+
+ typedef struct stat data_type;
+ typedef const data_type &data_type_ref;
+
+ static unsigned ComputeHash(const char *path) {
+ return llvm::HashString(path);
+ }
+
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, const char *path,
+ data_type_ref Data) {
+ unsigned StrLen = strlen(path);
+ clang::io::Emit16(Out, StrLen);
+ unsigned DataLen = 4 + 4 + 2 + 8 + 8;
+ clang::io::Emit8(Out, DataLen);
+ return std::make_pair(StrLen + 1, DataLen);
+ }
+
+ void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) {
+ Out.write(path, KeyLen);
+ }
+
+ void EmitData(llvm::raw_ostream &Out, key_type_ref,
+ data_type_ref Data, unsigned DataLen) {
+ using namespace clang::io;
+ uint64_t Start = Out.tell(); (void)Start;
+
+ Emit32(Out, (uint32_t) Data.st_ino);
+ Emit32(Out, (uint32_t) Data.st_dev);
+ Emit16(Out, (uint16_t) Data.st_mode);
+ Emit64(Out, (uint64_t) Data.st_mtime);
+ Emit64(Out, (uint64_t) Data.st_size);
+
+ assert(Out.tell() - Start == DataLen && "Wrong data length");
+ }
+};
+} // end anonymous namespace
+
+/// \brief Write the stat() system call cache to the AST file.
+void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
+ // Build the on-disk hash table containing information about every
+ // stat() call.
+ OnDiskChainedHashTableGenerator<ASTStatCacheTrait> Generator;
+ unsigned NumStatEntries = 0;
+ for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
+ StatEnd = StatCalls.end();
+ Stat != StatEnd; ++Stat, ++NumStatEntries) {
+ const char *Filename = Stat->first();
+ Generator.insert(Filename, Stat->second);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> StatCacheData;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(StatCacheData);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out);
+ }
+
+ // Create a blob abbreviation
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(STAT_CACHE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the stat cache
+ RecordData Record;
+ Record.push_back(STAT_CACHE);
+ Record.push_back(BucketOffset);
+ Record.push_back(NumStatEntries);
+ Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str());
+}
+
+//===----------------------------------------------------------------------===//
+// Source Manager Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// file.
+static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+ // FileEntry fields.
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
+ return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer.
+static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
+ return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to a
+/// buffer's blob.
+static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_BLOB));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
+ return Stream.EmitAbbrev(Abbrev);
+}
+
+/// \brief Create an abbreviation for the SLocEntry that refers to an
+/// buffer.
+static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_INSTANTIATION_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
+ return Stream.EmitAbbrev(Abbrev);
+}
+
+namespace {
+ // Trait used for the on-disk hash table of header search information.
+ class HeaderFileInfoTrait {
+ ASTWriter &Writer;
+ HeaderSearch &HS;
+
+ public:
+ HeaderFileInfoTrait(ASTWriter &Writer, HeaderSearch &HS)
+ : Writer(Writer), HS(HS) { }
+
+ typedef const char *key_type;
+ typedef key_type key_type_ref;
+
+ typedef HeaderFileInfo data_type;
+ typedef const data_type &data_type_ref;
+
+ static unsigned ComputeHash(const char *path) {
+ // The hash is based only on the filename portion of the key, so that the
+ // reader can match based on filenames when symlinking or excess path
+ // elements ("foo/../", "../") change the form of the name. However,
+ // complete path is still the key.
+ return llvm::HashString(llvm::sys::path::filename(path));
+ }
+
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, const char *path,
+ data_type_ref Data) {
+ unsigned StrLen = strlen(path);
+ clang::io::Emit16(Out, StrLen);
+ unsigned DataLen = 1 + 2 + 4;
+ clang::io::Emit8(Out, DataLen);
+ return std::make_pair(StrLen + 1, DataLen);
+ }
+
+ void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) {
+ Out.write(path, KeyLen);
+ }
+
+ void EmitData(llvm::raw_ostream &Out, key_type_ref,
+ data_type_ref Data, unsigned DataLen) {
+ using namespace clang::io;
+ uint64_t Start = Out.tell(); (void)Start;
+
+ unsigned char Flags = (Data.isImport << 3)
+ | (Data.DirInfo << 1)
+ | Data.Resolved;
+ Emit8(Out, (uint8_t)Flags);
+ Emit16(Out, (uint16_t) Data.NumIncludes);
+
+ if (!Data.ControllingMacro)
+ Emit32(Out, (uint32_t)Data.ControllingMacroID);
+ else
+ Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro));
+ assert(Out.tell() - Start == DataLen && "Wrong data length");
+ }
+ };
+} // end anonymous namespace
+
+/// \brief Write the header search block for the list of files that
+///
+/// \param HS The header search structure to save.
+///
+/// \param Chain Whether we're creating a chained AST file.
+void ASTWriter::WriteHeaderSearch(HeaderSearch &HS, const char* isysroot) {
+ llvm::SmallVector<const FileEntry *, 16> FilesByUID;
+ HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
+
+ if (FilesByUID.size() > HS.header_file_size())
+ FilesByUID.resize(HS.header_file_size());
+
+ HeaderFileInfoTrait GeneratorTrait(*this, HS);
+ OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;
+ llvm::SmallVector<const char *, 4> SavedStrings;
+ unsigned NumHeaderSearchEntries = 0;
+ for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
+ const FileEntry *File = FilesByUID[UID];
+ if (!File)
+ continue;
+
+ const HeaderFileInfo &HFI = HS.header_file_begin()[UID];
+ if (HFI.External && Chain)
+ continue;
+
+ // Turn the file name into an absolute path, if it isn't already.
+ const char *Filename = File->getName();
+ Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+
+ // If we performed any translation on the file name at all, we need to
+ // save this string, since the generator will refer to it later.
+ if (Filename != File->getName()) {
+ Filename = strdup(Filename);
+ SavedStrings.push_back(Filename);
+ }
+
+ Generator.insert(Filename, HFI, GeneratorTrait);
+ ++NumHeaderSearchEntries;
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> TableData;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(TableData);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, GeneratorTrait);
+ }
+
+ // Create a blob abbreviation
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned TableAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the stat cache
+ RecordData Record;
+ Record.push_back(HEADER_SEARCH_TABLE);
+ Record.push_back(BucketOffset);
+ Record.push_back(NumHeaderSearchEntries);
+ Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData.str());
+
+ // Free all of the strings we had to duplicate.
+ for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)
+ free((void*)SavedStrings[I]);
+}
+
+/// \brief Writes the block containing the serialized form of the
+/// source manager.
+///
+/// TODO: We should probably use an on-disk hash table (stored in a
+/// blob), indexed based on the file name, so that we only create
+/// entries for files that we actually need. In the common case (no
+/// errors), we probably won't have to create file entries for any of
+/// the files in the AST.
+void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
+ const Preprocessor &PP,
+ const char *isysroot) {
+ RecordData Record;
+
+ // Enter the source manager block.
+ Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 3);
+
+ // Abbreviations for the various kinds of source-location entries.
+ unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
+ unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
+ unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
+ unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream);
+
+ // Write the line table.
+ if (SourceMgr.hasLineTable()) {
+ LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+ // Emit the file names
+ Record.push_back(LineTable.getNumFilenames());
+ for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
+ // Emit the file name
+ const char *Filename = LineTable.getFilename(I);
+ Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+ unsigned FilenameLen = Filename? strlen(Filename) : 0;
+ Record.push_back(FilenameLen);
+ if (FilenameLen)
+ Record.insert(Record.end(), Filename, Filename + FilenameLen);
+ }
+
+ // Emit the line entries
+ for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
+ L != LEnd; ++L) {
+ // Emit the file ID
+ Record.push_back(L->first);
+
+ // Emit the line entries
+ Record.push_back(L->second.size());
+ for (std::vector<LineEntry>::iterator LE = L->second.begin(),
+ LEEnd = L->second.end();
+ LE != LEEnd; ++LE) {
+ Record.push_back(LE->FileOffset);
+ Record.push_back(LE->LineNo);
+ Record.push_back(LE->FilenameID);
+ Record.push_back((unsigned)LE->FileKind);
+ Record.push_back(LE->IncludeOffset);
+ }
+ }
+ Stream.EmitRecord(SM_LINE_TABLE, Record);
+ }
+
+ // Write out the source location entry table. We skip the first
+ // entry, which is always the same dummy entry.
+ std::vector<uint32_t> SLocEntryOffsets;
+ RecordData PreloadSLocs;
+ unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0;
+ SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID);
+ for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size();
+ I != N; ++I) {
+ // Get this source location entry.
+ const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
+
+ // Record the offset of this source-location entry.
+ SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
+
+ // Figure out which record code to use.
+ unsigned Code;
+ if (SLoc->isFile()) {
+ if (SLoc->getFile().getContentCache()->Entry)
+ Code = SM_SLOC_FILE_ENTRY;
+ else
+ Code = SM_SLOC_BUFFER_ENTRY;
+ } else
+ Code = SM_SLOC_INSTANTIATION_ENTRY;
+ Record.clear();
+ Record.push_back(Code);
+
+ Record.push_back(SLoc->getOffset());
+ if (SLoc->isFile()) {
+ const SrcMgr::FileInfo &File = SLoc->getFile();
+ Record.push_back(File.getIncludeLoc().getRawEncoding());
+ Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
+ Record.push_back(File.hasLineDirectives());
+
+ const SrcMgr::ContentCache *Content = File.getContentCache();
+ if (Content->Entry) {
+ // The source location entry is a file. The blob associated
+ // with this entry is the file name.
+
+ // Emit size/modification time for this file.
+ Record.push_back(Content->Entry->getSize());
+ Record.push_back(Content->Entry->getModificationTime());
+
+ // Turn the file name into an absolute path, if it isn't already.
+ const char *Filename = Content->Entry->getName();
+ llvm::SmallString<128> FilePath(Filename);
+ llvm::sys::fs::make_absolute(FilePath);
+ Filename = FilePath.c_str();
+
+ Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+ Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename);
+ } else {
+ // The source location entry is a buffer. The blob associated
+ // with this entry contains the contents of the buffer.
+
+ // We add one to the size so that we capture the trailing NULL
+ // that is required by llvm::MemoryBuffer::getMemBuffer (on
+ // the reader side).
+ const llvm::MemoryBuffer *Buffer
+ = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
+ const char *Name = Buffer->getBufferIdentifier();
+ Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
+ llvm::StringRef(Name, strlen(Name) + 1));
+ Record.clear();
+ Record.push_back(SM_SLOC_BUFFER_BLOB);
+ Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
+ llvm::StringRef(Buffer->getBufferStart(),
+ Buffer->getBufferSize() + 1));
+
+ if (strcmp(Name, "<built-in>") == 0)
+ PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
+ }
+ } else {
+ // The source location entry is an instantiation.
+ const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation();
+ Record.push_back(Inst.getSpellingLoc().getRawEncoding());
+ Record.push_back(Inst.getInstantiationLocStart().getRawEncoding());
+ Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
+
+ // Compute the token length for this macro expansion.
+ unsigned NextOffset = SourceMgr.getNextOffset();
+ if (I + 1 != N)
+ NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
+ Record.push_back(NextOffset - SLoc->getOffset() - 1);
+ Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
+ }
+ }
+
+ Stream.ExitBlock();
+
+ if (SLocEntryOffsets.empty())
+ return;
+
+ // Write the source-location offsets table into the AST block. This
+ // table is used for lazily loading source-location information.
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
+ unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Record.clear();
+ Record.push_back(SOURCE_LOCATION_OFFSETS);
+ Record.push_back(SLocEntryOffsets.size());
+ unsigned BaseOffset = Chain ? Chain->getNextSLocOffset() : 0;
+ Record.push_back(SourceMgr.getNextOffset() - BaseOffset);
+ Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
+ (const char *)data(SLocEntryOffsets),
+ SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0]));
+
+ // Write the source location entry preloads array, telling the AST
+ // reader which source locations entries it should load eagerly.
+ Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs);
+}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Serialization
+//===----------------------------------------------------------------------===//
+
+static int compareMacroDefinitions(const void *XPtr, const void *YPtr) {
+ const std::pair<const IdentifierInfo *, MacroInfo *> &X =
+ *(const std::pair<const IdentifierInfo *, MacroInfo *>*)XPtr;
+ const std::pair<const IdentifierInfo *, MacroInfo *> &Y =
+ *(const std::pair<const IdentifierInfo *, MacroInfo *>*)YPtr;
+ return X.first->getName().compare(Y.first->getName());
+}
+
+/// \brief Writes the block containing the serialized form of the
+/// preprocessor.
+///
+void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
+ RecordData Record;
+
+ // If the preprocessor __COUNTER__ value has been bumped, remember it.
+ if (PP.getCounterValue() != 0) {
+ Record.push_back(PP.getCounterValue());
+ Stream.EmitRecord(PP_COUNTER_VALUE, Record);
+ Record.clear();
+ }
+
+ // Enter the preprocessor block.
+ Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);
+
+ // If the AST file contains __DATE__ or __TIME__ emit a warning about this.
+ // FIXME: use diagnostics subsystem for localization etc.
+ if (PP.SawDateOrTime())
+ fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
+
+
+ // Loop over all the macro definitions that are live at the end of the file,
+ // emitting each to the PP section.
+ PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
+
+ // Construct the list of macro definitions that need to be serialized.
+ llvm::SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2>
+ MacrosToEmit;
+ llvm::SmallPtrSet<const IdentifierInfo*, 4> MacroDefinitionsSeen;
+ for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0),
+ E = PP.macro_end(Chain == 0);
+ I != E; ++I) {
+ MacroDefinitionsSeen.insert(I->first);
+ MacrosToEmit.push_back(std::make_pair(I->first, I->second));
+ }
+
+ // Sort the set of macro definitions that need to be serialized by the
+ // name of the macro, to provide a stable ordering.
+ llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(),
+ &compareMacroDefinitions);
+
+ // Resolve any identifiers that defined macros at the time they were
+ // deserialized, adding them to the list of macros to emit (if appropriate).
+ for (unsigned I = 0, N = DeserializedMacroNames.size(); I != N; ++I) {
+ IdentifierInfo *Name
+ = const_cast<IdentifierInfo *>(DeserializedMacroNames[I]);
+ if (Name->hasMacroDefinition() && MacroDefinitionsSeen.insert(Name))
+ MacrosToEmit.push_back(std::make_pair(Name, PP.getMacroInfo(Name)));
+ }
+
+ for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) {
+ const IdentifierInfo *Name = MacrosToEmit[I].first;
+ MacroInfo *MI = MacrosToEmit[I].second;
+ if (!MI)
+ continue;
+
+ // Don't emit builtin macros like __LINE__ to the AST file unless they have
+ // been redefined by the header (in which case they are not isBuiltinMacro).
+ // Also skip macros from a AST file if we're chaining.
+
+ // FIXME: There is a (probably minor) optimization we could do here, if
+ // the macro comes from the original PCH but the identifier comes from a
+ // chained PCH, by storing the offset into the original PCH rather than
+ // writing the macro definition a second time.
+ if (MI->isBuiltinMacro() ||
+ (Chain && Name->isFromAST() && MI->isFromAST()))
+ continue;
+
+ AddIdentifierRef(Name, Record);
+ MacroOffsets[Name] = Stream.GetCurrentBitNo();
+ Record.push_back(MI->getDefinitionLoc().getRawEncoding());
+ Record.push_back(MI->isUsed());
+
+ unsigned Code;
+ if (MI->isObjectLike()) {
+ Code = PP_MACRO_OBJECT_LIKE;
+ } else {
+ Code = PP_MACRO_FUNCTION_LIKE;
+
+ Record.push_back(MI->isC99Varargs());
+ Record.push_back(MI->isGNUVarargs());
+ Record.push_back(MI->getNumArgs());
+ for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end();
+ I != E; ++I)
+ AddIdentifierRef(*I, Record);
+ }
+
+ // If we have a detailed preprocessing record, record the macro definition
+ // ID that corresponds to this macro.
+ if (PPRec)
+ Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI)));
+
+ Stream.EmitRecord(Code, Record);
+ Record.clear();
+
+ // Emit the tokens array.
+ for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
+ // Note that we know that the preprocessor does not have any annotation
+ // tokens in it because they are created by the parser, and thus can't be
+ // in a macro definition.
+ const Token &Tok = MI->getReplacementToken(TokNo);
+
+ Record.push_back(Tok.getLocation().getRawEncoding());
+ Record.push_back(Tok.getLength());
+
+ // FIXME: When reading literal tokens, reconstruct the literal pointer if
+ // it is needed.
+ AddIdentifierRef(Tok.getIdentifierInfo(), Record);
+ // FIXME: Should translate token kind to a stable encoding.
+ Record.push_back(Tok.getKind());
+ // FIXME: Should translate token flags to a stable encoding.
+ Record.push_back(Tok.getFlags());
+
+ Stream.EmitRecord(PP_TOKEN, Record);
+ Record.clear();
+ }
+ ++NumMacros;
+ }
+ Stream.ExitBlock();
+
+ if (PPRec)
+ WritePreprocessorDetail(*PPRec);
+}
+
+void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
+ if (PPRec.begin(Chain) == PPRec.end(Chain))
+ return;
+
+ // Enter the preprocessor block.
+ Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3);
+
+ // If the preprocessor has a preprocessing record, emit it.
+ unsigned NumPreprocessingRecords = 0;
+ using namespace llvm;
+
+ // Set up the abbreviation for
+ unsigned InclusionAbbrev = 0;
+ {
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ InclusionAbbrev = Stream.EmitAbbrev(Abbrev);
+ }
+
+ unsigned IndexBase = Chain ? PPRec.getNumPreallocatedEntities() : 0;
+ RecordData Record;
+ for (PreprocessingRecord::iterator E = PPRec.begin(Chain),
+ EEnd = PPRec.end(Chain);
+ E != EEnd; ++E) {
+ Record.clear();
+
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ // Record this macro definition's location.
+ MacroID ID = getMacroDefinitionID(MD);
+
+ // Don't write the macro definition if it is from another AST file.
+ if (ID < FirstMacroID)
+ continue;
+
+ // Notify the serialization listener that we're serializing this entity.
+ if (SerializationListener)
+ SerializationListener->SerializedPreprocessedEntity(*E,
+ Stream.GetCurrentBitNo());
+
+ unsigned Position = ID - FirstMacroID;
+ if (Position != MacroDefinitionOffsets.size()) {
+ if (Position > MacroDefinitionOffsets.size())
+ MacroDefinitionOffsets.resize(Position + 1);
+
+ MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo();
+ } else
+ MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
+
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ Record.push_back(ID);
+ AddSourceLocation(MD->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MD->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MD->getName(), Record);
+ AddSourceLocation(MD->getLocation(), Record);
+ Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);
+ continue;
+ }
+
+ // Notify the serialization listener that we're serializing this entity.
+ if (SerializationListener)
+ SerializationListener->SerializedPreprocessedEntity(*E,
+ Stream.GetCurrentBitNo());
+
+ if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ AddSourceLocation(MI->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MI->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MI->getName(), Record);
+ Record.push_back(getMacroDefinitionID(MI->getDefinition()));
+ Stream.EmitRecord(PPD_MACRO_INSTANTIATION, Record);
+ continue;
+ }
+
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
+ Record.push_back(PPD_INCLUSION_DIRECTIVE);
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ AddSourceLocation(ID->getSourceRange().getBegin(), Record);
+ AddSourceLocation(ID->getSourceRange().getEnd(), Record);
+ Record.push_back(ID->getFileName().size());
+ Record.push_back(ID->wasInQuotes());
+ Record.push_back(static_cast<unsigned>(ID->getKind()));
+ llvm::SmallString<64> Buffer;
+ Buffer += ID->getFileName();
+ Buffer += ID->getFile()->getName();
+ Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
+ continue;
+ }
+
+ llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
+ }
+ Stream.ExitBlock();
+
+ // Write the offsets table for the preprocessing record.
+ if (NumPreprocessingRecords > 0) {
+ // Write the offsets table for identifier IDs.
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(MACRO_DEFINITION_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Record.clear();
+ Record.push_back(MACRO_DEFINITION_OFFSETS);
+ Record.push_back(NumPreprocessingRecords);
+ Record.push_back(MacroDefinitionOffsets.size());
+ Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record,
+ (const char *)data(MacroDefinitionOffsets),
+ MacroDefinitionOffsets.size() * sizeof(uint32_t));
+ }
+}
+
+void ASTWriter::WritePragmaDiagnosticMappings(const Diagnostic &Diag) {
+ RecordData Record;
+ for (Diagnostic::DiagStatePointsTy::const_iterator
+ I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end();
+ I != E; ++I) {
+ const Diagnostic::DiagStatePoint &point = *I;
+ if (point.Loc.isInvalid())
+ continue;
+
+ Record.push_back(point.Loc.getRawEncoding());
+ for (Diagnostic::DiagState::iterator
+ I = point.State->begin(), E = point.State->end(); I != E; ++I) {
+ unsigned diag = I->first, map = I->second;
+ if (map & 0x10) { // mapping from a diagnostic pragma.
+ Record.push_back(diag);
+ Record.push_back(map & 0x7);
+ }
+ }
+ Record.push_back(-1); // mark the end of the diag/map pairs for this
+ // location.
+ }
+
+ if (!Record.empty())
+ Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
+}
+
+//===----------------------------------------------------------------------===//
+// Type Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Write the representation of a type to the AST stream.
+void ASTWriter::WriteType(QualType T) {
+ TypeIdx &Idx = TypeIdxs[T];
+ if (Idx.getIndex() == 0) // we haven't seen this type before.
+ Idx = TypeIdx(NextTypeID++);
+
+ assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST");
+
+ // Record the offset for this type.
+ unsigned Index = Idx.getIndex() - FirstTypeID;
+ if (TypeOffsets.size() == Index)
+ TypeOffsets.push_back(Stream.GetCurrentBitNo());
+ else if (TypeOffsets.size() < Index) {
+ TypeOffsets.resize(Index + 1);
+ TypeOffsets[Index] = Stream.GetCurrentBitNo();
+ }
+
+ RecordData Record;
+
+ // Emit the type's representation.
+ ASTTypeWriter W(*this, Record);
+
+ if (T.hasLocalNonFastQualifiers()) {
+ Qualifiers Qs = T.getLocalQualifiers();
+ AddTypeRef(T.getLocalUnqualifiedType(), Record);
+ Record.push_back(Qs.getAsOpaqueValue());
+ W.Code = TYPE_EXT_QUAL;
+ } else {
+ switch (T->getTypeClass()) {
+ // For all of the concrete, non-dependent types, call the
+ // appropriate visitor function.
+#define TYPE(Class, Base) \
+ case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ // Emit the serialized record.
+ Stream.EmitRecord(W.Code, Record);
+
+ // Flush any expressions that were written as part of this type.
+ FlushStmts();
+}
+
+//===----------------------------------------------------------------------===//
+// Declaration Serialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Write the block containing all of the declaration IDs
+/// lexically declared within the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
+/// bistream, or 0 if no block was written.
+uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
+ DeclContext *DC) {
+ if (DC->decls_empty())
+ return 0;
+
+ uint64_t Offset = Stream.GetCurrentBitNo();
+ RecordData Record;
+ Record.push_back(DECL_CONTEXT_LEXICAL);
+ llvm::SmallVector<KindDeclIDPair, 64> Decls;
+ for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
+ D != DEnd; ++D)
+ Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D)));
+
+ ++NumLexicalDeclContexts;
+ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
+ reinterpret_cast<char*>(Decls.data()),
+ Decls.size() * sizeof(KindDeclIDPair));
+ return Offset;
+}
+
+void ASTWriter::WriteTypeDeclOffsets() {
+ using namespace llvm;
+ RecordData Record;
+
+ // Write the type offsets array
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
+ unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+ Record.clear();
+ Record.push_back(TYPE_OFFSET);
+ Record.push_back(TypeOffsets.size());
+ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
+ (const char *)data(TypeOffsets),
+ TypeOffsets.size() * sizeof(TypeOffsets[0]));
+
+ // Write the declaration offsets array
+ Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
+ unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+ Record.clear();
+ Record.push_back(DECL_OFFSET);
+ Record.push_back(DeclOffsets.size());
+ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
+ (const char *)data(DeclOffsets),
+ DeclOffsets.size() * sizeof(DeclOffsets[0]));
+}
+
+//===----------------------------------------------------------------------===//
+// Global Method Pool and Selector Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+// Trait used for the on-disk hash table used in the method pool.
+class ASTMethodPoolTrait {
+ ASTWriter &Writer;
+
+public:
+ typedef Selector key_type;
+ typedef key_type key_type_ref;
+
+ struct data_type {
+ SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
+ typedef const data_type& data_type_ref;
+
+ explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { }
+
+ static unsigned ComputeHash(Selector Sel) {
+ return serialization::ComputeHash(Sel);
+ }
+
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel,
+ data_type_ref Methods) {
+ unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
+ clang::io::Emit16(Out, KeyLen);
+ unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ DataLen += 4;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ DataLen += 4;
+ clang::io::Emit16(Out, DataLen);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) {
+ uint64_t Start = Out.tell();
+ assert((Start >> 32) == 0 && "Selector key offset too large");
+ Writer.SetSelectorOffset(Sel, Start);
+ unsigned N = Sel.getNumArgs();
+ clang::io::Emit16(Out, N);
+ if (N == 0)
+ N = 1;
+ for (unsigned I = 0; I != N; ++I)
+ clang::io::Emit32(Out,
+ Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
+ }
+
+ void EmitData(llvm::raw_ostream& Out, key_type_ref,
+ data_type_ref Methods, unsigned DataLen) {
+ uint64_t Start = Out.tell(); (void)Start;
+ clang::io::Emit32(Out, Methods.ID);
+ unsigned NumInstanceMethods = 0;
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ ++NumInstanceMethods;
+
+ unsigned NumFactoryMethods = 0;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ ++NumFactoryMethods;
+
+ clang::io::Emit16(Out, NumInstanceMethods);
+ clang::io::Emit16(Out, NumFactoryMethods);
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
+ Method = Method->Next)
+ if (Method->Method)
+ clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+
+ assert(Out.tell() - Start == DataLen && "Data length is wrong");
+ }
+};
+} // end anonymous namespace
+
+/// \brief Write ObjC data: selectors and the method pool.
+///
+/// The method pool contains both instance and factory methods, stored
+/// in an on-disk hash table indexed by the selector. The hash table also
+/// contains an empty entry for every other selector known to Sema.
+void ASTWriter::WriteSelectors(Sema &SemaRef) {
+ using namespace llvm;
+
+ // Do we have to do anything at all?
+ if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
+ return;
+ unsigned NumTableEntries = 0;
+ // Create and write out the blob that contains selectors and the method pool.
+ {
+ OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
+ ASTMethodPoolTrait Trait(*this);
+
+ // Create the on-disk hash table representation. We walk through every
+ // selector we've seen and look it up in the method pool.
+ SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
+ for (llvm::DenseMap<Selector, SelectorID>::iterator
+ I = SelectorIDs.begin(), E = SelectorIDs.end();
+ I != E; ++I) {
+ Selector S = I->first;
+ Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
+ ASTMethodPoolTrait::data_type Data = {
+ I->second,
+ ObjCMethodList(),
+ ObjCMethodList()
+ };
+ if (F != SemaRef.MethodPool.end()) {
+ Data.Instance = F->second.first;
+ Data.Factory = F->second.second;
+ }
+ // Only write this selector if it's not in an existing AST or something
+ // changed.
+ if (Chain && I->second < FirstSelectorID) {
+ // Selector already exists. Did it change?
+ bool changed = false;
+ for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method;
+ M = M->Next) {
+ if (M->Method->getPCHLevel() == 0)
+ changed = true;
+ }
+ for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method;
+ M = M->Next) {
+ if (M->Method->getPCHLevel() == 0)
+ changed = true;
+ }
+ if (!changed)
+ continue;
+ } else if (Data.Instance.Method || Data.Factory.Method) {
+ // A new method pool entry.
+ ++NumTableEntries;
+ }
+ Generator.insert(S, Data, Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> MethodPool;
+ uint32_t BucketOffset;
+ {
+ ASTMethodPoolTrait Trait(*this);
+ llvm::raw_svector_ostream Out(MethodPool);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
+ }
+
+ // Create a blob abbreviation
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the method pool
+ RecordData Record;
+ Record.push_back(METHOD_POOL);
+ Record.push_back(BucketOffset);
+ Record.push_back(NumTableEntries);
+ Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
+
+ // Create a blob abbreviation for the selector table offsets.
+ Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the selector offsets table.
+ Record.clear();
+ Record.push_back(SELECTOR_OFFSETS);
+ Record.push_back(SelectorOffsets.size());
+ Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
+ (const char *)data(SelectorOffsets),
+ SelectorOffsets.size() * 4);
+ }
+}
+
+/// \brief Write the selectors referenced in @selector expression into AST file.
+void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
+ using namespace llvm;
+ if (SemaRef.ReferencedSelectors.empty())
+ return;
+
+ RecordData Record;
+
+ // Note: this writes out all references even for a dependent AST. But it is
+ // very tricky to fix, and given that @selector shouldn't really appear in
+ // headers, probably not worth it. It's not a correctness issue.
+ for (DenseMap<Selector, SourceLocation>::iterator S =
+ SemaRef.ReferencedSelectors.begin(),
+ E = SemaRef.ReferencedSelectors.end(); S != E; ++S) {
+ Selector Sel = (*S).first;
+ SourceLocation Loc = (*S).second;
+ AddSelectorRef(Sel, Record);
+ AddSourceLocation(Loc, Record);
+ }
+ Stream.EmitRecord(REFERENCED_SELECTOR_POOL, Record);
+}
+
+//===----------------------------------------------------------------------===//
+// Identifier Table Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ASTIdentifierTableTrait {
+ ASTWriter &Writer;
+ Preprocessor &PP;
+
+ /// \brief Determines whether this is an "interesting" identifier
+ /// that needs a full IdentifierInfo structure written into the hash
+ /// table.
+ static bool isInterestingIdentifier(const IdentifierInfo *II) {
+ return II->isPoisoned() ||
+ II->isExtensionToken() ||
+ II->hasMacroDefinition() ||
+ II->getObjCOrBuiltinID() ||
+ II->getFETokenInfo<void>();
+ }
+
+public:
+ typedef const IdentifierInfo* key_type;
+ typedef key_type key_type_ref;
+
+ typedef IdentID data_type;
+ typedef data_type data_type_ref;
+
+ ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP)
+ : Writer(Writer), PP(PP) { }
+
+ static unsigned ComputeHash(const IdentifierInfo* II) {
+ return llvm::HashString(II->getName());
+ }
+
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
+ IdentID ID) {
+ unsigned KeyLen = II->getLength() + 1;
+ unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
+ if (isInterestingIdentifier(II)) {
+ DataLen += 2; // 2 bytes for builtin ID, flags
+ if (II->hasMacroDefinition() &&
+ !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
+ DataLen += 4;
+ for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
+ DEnd = IdentifierResolver::end();
+ D != DEnd; ++D)
+ DataLen += sizeof(DeclID);
+ }
+ clang::io::Emit16(Out, DataLen);
+ // We emit the key length after the data length so that every
+ // string is preceded by a 16-bit length. This matches the PTH
+ // format for storing identifiers.
+ clang::io::Emit16(Out, KeyLen);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II,
+ unsigned KeyLen) {
+ // Record the location of the key data. This is used when generating
+ // the mapping from persistent IDs to strings.
+ Writer.SetIdentifierOffset(II, Out.tell());
+ Out.write(II->getNameStart(), KeyLen);
+ }
+
+ void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
+ IdentID ID, unsigned) {
+ if (!isInterestingIdentifier(II)) {
+ clang::io::Emit32(Out, ID << 1);
+ return;
+ }
+
+ clang::io::Emit32(Out, (ID << 1) | 0x01);
+ uint32_t Bits = 0;
+ bool hasMacroDefinition =
+ II->hasMacroDefinition() &&
+ !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
+ Bits = (uint32_t)II->getObjCOrBuiltinID();
+ Bits = (Bits << 1) | unsigned(hasMacroDefinition);
+ Bits = (Bits << 1) | unsigned(II->isExtensionToken());
+ Bits = (Bits << 1) | unsigned(II->isPoisoned());
+ Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
+ Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
+ clang::io::Emit16(Out, Bits);
+
+ if (hasMacroDefinition)
+ clang::io::Emit32(Out, Writer.getMacroOffset(II));
+
+ // Emit the declaration IDs in reverse order, because the
+ // IdentifierResolver provides the declarations as they would be
+ // visible (e.g., the function "stat" would come before the struct
+ // "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
+ // adds declarations to the end of the list (so we need to see the
+ // struct "status" before the function "status").
+ // Only emit declarations that aren't from a chained PCH, though.
+ llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
+ IdentifierResolver::end());
+ for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
+ DEnd = Decls.rend();
+ D != DEnd; ++D)
+ clang::io::Emit32(Out, Writer.getDeclID(*D));
+ }
+};
+} // end anonymous namespace
+
+/// \brief Write the identifier table into the AST file.
+///
+/// The identifier table consists of a blob containing string data
+/// (the actual identifiers themselves) and a separate "offsets" index
+/// that maps identifier IDs to locations within the blob.
+void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
+ using namespace llvm;
+
+ // Create and write out the blob that contains the identifier
+ // strings.
+ {
+ OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
+ ASTIdentifierTableTrait Trait(*this, PP);
+
+ // Look for any identifiers that were named while processing the
+ // headers, but are otherwise not needed. We add these to the hash
+ // table to enable checking of the predefines buffer in the case
+ // where the user adds new macro definitions when building the AST
+ // file.
+ for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
+ IDEnd = PP.getIdentifierTable().end();
+ ID != IDEnd; ++ID)
+ getIdentifierRef(ID->second);
+
+ // Create the on-disk hash table representation. We only store offsets
+ // for identifiers that appear here for the first time.
+ IdentifierOffsets.resize(NextIdentID - FirstIdentID);
+ for (llvm::DenseMap<const IdentifierInfo *, IdentID>::iterator
+ ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
+ ID != IDEnd; ++ID) {
+ assert(ID->first && "NULL identifier in identifier table");
+ if (!Chain || !ID->first->isFromAST())
+ Generator.insert(ID->first, ID->second, Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> IdentifierTable;
+ uint32_t BucketOffset;
+ {
+ ASTIdentifierTableTrait Trait(*this, PP);
+ llvm::raw_svector_ostream Out(IdentifierTable);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
+ }
+
+ // Create a blob abbreviation
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the identifier table
+ RecordData Record;
+ Record.push_back(IDENTIFIER_TABLE);
+ Record.push_back(BucketOffset);
+ Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
+ }
+
+ // Write the offsets table for identifier IDs.
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ RecordData Record;
+ Record.push_back(IDENTIFIER_OFFSET);
+ Record.push_back(IdentifierOffsets.size());
+ Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
+ (const char *)data(IdentifierOffsets),
+ IdentifierOffsets.size() * sizeof(uint32_t));
+}
+
+//===----------------------------------------------------------------------===//
+// DeclContext's Name Lookup Table Serialization
+//===----------------------------------------------------------------------===//
+
+namespace {
+// Trait used for the on-disk hash table used in the method pool.
+class ASTDeclContextNameLookupTrait {
+ ASTWriter &Writer;
+
+public:
+ typedef DeclarationName key_type;
+ typedef key_type key_type_ref;
+
+ typedef DeclContext::lookup_result data_type;
+ typedef const data_type& data_type_ref;
+
+ explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
+
+ unsigned ComputeHash(DeclarationName Name) {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Name.getNameKind());
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ ID.AddString(Name.getAsIdentifierInfo()->getName());
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector()));
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ ID.AddInteger(Writer.GetOrCreateTypeID(Name.getCXXNameType()));
+ break;
+ case DeclarationName::CXXOperatorName:
+ ID.AddInteger(Name.getCXXOverloadedOperator());
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(Name.getCXXLiteralIdentifier()->getName());
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return ID.ComputeHash();
+ }
+
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, DeclarationName Name,
+ data_type_ref Lookup) {
+ unsigned KeyLen = 1;
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXLiteralOperatorName:
+ KeyLen += 4;
+ break;
+ case DeclarationName::CXXOperatorName:
+ KeyLen += 1;
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+ clang::io::Emit16(Out, KeyLen);
+
+ // 2 bytes for num of decls and 4 for each DeclID.
+ unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first);
+ clang::io::Emit16(Out, DataLen);
+
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ void EmitKey(llvm::raw_ostream& Out, DeclarationName Name, unsigned) {
+ using namespace clang::io;
+
+ assert(Name.getNameKind() < 0x100 && "Invalid name kind ?");
+ Emit8(Out, Name.getNameKind());
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector()));
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Emit32(Out, Writer.getTypeID(Name.getCXXNameType()));
+ break;
+ case DeclarationName::CXXOperatorName:
+ assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?");
+ Emit8(Out, Name.getCXXOverloadedOperator());
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+ }
+
+ void EmitData(llvm::raw_ostream& Out, key_type_ref,
+ data_type Lookup, unsigned DataLen) {
+ uint64_t Start = Out.tell(); (void)Start;
+ clang::io::Emit16(Out, Lookup.second - Lookup.first);
+ for (; Lookup.first != Lookup.second; ++Lookup.first)
+ clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first));
+
+ assert(Out.tell() - Start == DataLen && "Data length is wrong");
+ }
+};
+} // end anonymous namespace
+
+/// \brief Write the block containing all of the declaration IDs
+/// visible from the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
+/// bitstream, or 0 if no block was written.
+uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
+ DeclContext *DC) {
+ if (DC->getPrimaryContext() != DC)
+ return 0;
+
+ // Since there is no name lookup into functions or methods, don't bother to
+ // build a visible-declarations table for these entities.
+ if (DC->isFunctionOrMethod())
+ return 0;
+
+ // If not in C++, we perform name lookup for the translation unit via the
+ // IdentifierInfo chains, don't bother to build a visible-declarations table.
+ // FIXME: In C++ we need the visible declarations in order to "see" the
+ // friend declarations, is there a way to do this without writing the table ?
+ if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus)
+ return 0;
+
+ // Force the DeclContext to build a its name-lookup table.
+ if (DC->hasExternalVisibleStorage())
+ DC->MaterializeVisibleDeclsFromExternalStorage();
+ else
+ DC->lookup(DeclarationName());
+
+ // Serialize the contents of the mapping used for lookup. Note that,
+ // although we have two very different code paths, the serialized
+ // representation is the same for both cases: a declaration name,
+ // followed by a size, followed by references to the visible
+ // declarations that have that name.
+ uint64_t Offset = Stream.GetCurrentBitNo();
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ if (!Map || Map->empty())
+ return 0;
+
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the on-disk hash table representation.
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ DeclarationName Name = D->first;
+ DeclContext::lookup_result Result = D->second.getLookupResult();
+ Generator.insert(Name, Result, Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> LookupTable;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
+ }
+
+ // Write the lookup table
+ RecordData Record;
+ Record.push_back(DECL_CONTEXT_VISIBLE);
+ Record.push_back(BucketOffset);
+ Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
+ LookupTable.str());
+
+ Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record);
+ ++NumVisibleDeclContexts;
+ return Offset;
+}
+
+/// \brief Write an UPDATE_VISIBLE block for the given context.
+///
+/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing
+/// DeclContext in a dependent AST file. As such, they only exist for the TU
+/// (in C++) and for namespaces.
+void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ if (!Map || Map->empty())
+ return;
+
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the hash table.
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ DeclarationName Name = D->first;
+ DeclContext::lookup_result Result = D->second.getLookupResult();
+ // For any name that appears in this table, the results are complete, i.e.
+ // they overwrite results from previous PCHs. Merging is always a mess.
+ Generator.insert(Name, Result, Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> LookupTable;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
+ }
+
+ // Write the lookup table
+ RecordData Record;
+ Record.push_back(UPDATE_VISIBLE);
+ Record.push_back(getDeclID(cast<Decl>(DC)));
+ Record.push_back(BucketOffset);
+ Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str());
+}
+
+/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
+void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
+ RecordData Record;
+ Record.push_back(Opts.fp_contract);
+ Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
+}
+
+/// \brief Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.
+void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
+ if (!SemaRef.Context.getLangOptions().OpenCL)
+ return;
+
+ const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
+ RecordData Record;
+#define OPENCLEXT(nm) Record.push_back(Opts.nm);
+#include "clang/Basic/OpenCLExtensions.def"
+ Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
+}
+
+//===----------------------------------------------------------------------===//
+// General Serialization Routines
+//===----------------------------------------------------------------------===//
+
+/// \brief Write a record containing the given attributes.
+void ASTWriter::WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record) {
+ Record.push_back(Attrs.size());
+ for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
+ const Attr * A = *i;
+ Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
+ AddSourceLocation(A->getLocation(), Record);
+
+#include "clang/Serialization/AttrPCHWrite.inc"
+
+ }
+}
+
+void ASTWriter::AddString(llvm::StringRef Str, RecordDataImpl &Record) {
+ Record.push_back(Str.size());
+ Record.insert(Record.end(), Str.begin(), Str.end());
+}
+
+/// \brief Note that the identifier II occurs at the given offset
+/// within the identifier table.
+void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
+ IdentID ID = IdentifierIDs[II];
+ // Only store offsets new to this AST file. Other identifier names are looked
+ // up earlier in the chain and thus don't need an offset.
+ if (ID >= FirstIdentID)
+ IdentifierOffsets[ID - FirstIdentID] = Offset;
+}
+
+/// \brief Note that the selector Sel occurs at the given offset
+/// within the method pool/selector table.
+void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
+ unsigned ID = SelectorIDs[Sel];
+ assert(ID && "Unknown selector");
+ // Don't record offsets for selectors that are also available in a different
+ // file.
+ if (ID < FirstSelectorID)
+ return;
+ SelectorOffsets[ID - FirstSelectorID] = Offset;
+}
+
+ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
+ : Stream(Stream), Chain(0), SerializationListener(0),
+ FirstDeclID(1), NextDeclID(FirstDeclID),
+ FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
+ FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1),
+ NextSelectorID(FirstSelectorID), FirstMacroID(1), NextMacroID(FirstMacroID),
+ CollectedStmts(&StmtsToEmit),
+ NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
+ NumVisibleDeclContexts(0), FirstCXXBaseSpecifiersID(1),
+ NextCXXBaseSpecifiersID(1)
+{
+}
+
+void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const std::string &OutputFile,
+ const char *isysroot) {
+ // Emit the file header.
+ Stream.Emit((unsigned)'C', 8);
+ Stream.Emit((unsigned)'P', 8);
+ Stream.Emit((unsigned)'C', 8);
+ Stream.Emit((unsigned)'H', 8);
+
+ WriteBlockInfoBlock();
+
+ if (Chain)
+ WriteASTChain(SemaRef, StatCalls, isysroot);
+ else
+ WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile);
+}
+
+void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const char *isysroot,
+ const std::string &OutputFile) {
+ using namespace llvm;
+
+ ASTContext &Context = SemaRef.Context;
+ Preprocessor &PP = SemaRef.PP;
+
+ // The translation unit is the first declaration we'll emit.
+ DeclIDs[Context.getTranslationUnitDecl()] = 1;
+ ++NextDeclID;
+ DeclTypesToEmit.push(Context.getTranslationUnitDecl());
+
+ // Make sure that we emit IdentifierInfos (and any attached
+ // declarations) for builtins.
+ {
+ IdentifierTable &Table = PP.getIdentifierTable();
+ llvm::SmallVector<const char *, 32> BuiltinNames;
+ Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
+ Context.getLangOptions().NoBuiltin);
+ for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
+ getIdentifierRef(&Table.get(BuiltinNames[I]));
+ }
+
+ // Build a record containing all of the tentative definitions in this file, in
+ // TentativeDefinitions order. Generally, this record will be empty for
+ // headers.
+ RecordData TentativeDefinitions;
+ for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
+ AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
+ }
+
+ // Build a record containing all of the file scoped decls in this file.
+ RecordData UnusedFileScopedDecls;
+ for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i)
+ AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
+
+ RecordData WeakUndeclaredIdentifiers;
+ if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
+ WeakUndeclaredIdentifiers.push_back(
+ SemaRef.WeakUndeclaredIdentifiers.size());
+ for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
+ I = SemaRef.WeakUndeclaredIdentifiers.begin(),
+ E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
+ AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
+ AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
+ WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
+ }
+ }
+
+ // Build a record containing all of the locally-scoped external
+ // declarations in this header file. Generally, this record will be
+ // empty.
+ RecordData LocallyScopedExternalDecls;
+ // FIXME: This is filling in the AST file in densemap order which is
+ // nondeterminstic!
+ for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
+ TD = SemaRef.LocallyScopedExternalDecls.begin(),
+ TDEnd = SemaRef.LocallyScopedExternalDecls.end();
+ TD != TDEnd; ++TD)
+ AddDeclRef(TD->second, LocallyScopedExternalDecls);
+
+ // Build a record containing all of the ext_vector declarations.
+ RecordData ExtVectorDecls;
+ for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I)
+ AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
+
+ // Build a record containing all of the VTable uses information.
+ RecordData VTableUses;
+ if (!SemaRef.VTableUses.empty()) {
+ VTableUses.push_back(SemaRef.VTableUses.size());
+ for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
+ AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
+ AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
+ VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
+ }
+ }
+
+ // Build a record containing all of dynamic classes declarations.
+ RecordData DynamicClasses;
+ for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
+ AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
+
+ // Build a record containing all of pending implicit instantiations.
+ RecordData PendingInstantiations;
+ for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+ I = SemaRef.PendingInstantiations.begin(),
+ N = SemaRef.PendingInstantiations.end(); I != N; ++I) {
+ AddDeclRef(I->first, PendingInstantiations);
+ AddSourceLocation(I->second, PendingInstantiations);
+ }
+ assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+ "There are local ones at end of translation unit!");
+
+ // Build a record containing some declaration references.
+ RecordData SemaDeclRefs;
+ if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+ AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
+ AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+ }
+
+ RecordData CUDASpecialDeclRefs;
+ if (Context.getcudaConfigureCallDecl()) {
+ AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs);
+ }
+
+ // Write the remaining AST contents.
+ RecordData Record;
+ Stream.EnterSubblock(AST_BLOCK_ID, 5);
+ WriteMetadata(Context, isysroot, OutputFile);
+ WriteLanguageOptions(Context.getLangOptions());
+ if (StatCalls && !isysroot)
+ WriteStatCache(*StatCalls);
+ WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+ // Write the record of special types.
+ Record.clear();
+
+ AddTypeRef(Context.getBuiltinVaListType(), Record);
+ AddTypeRef(Context.getObjCIdType(), Record);
+ AddTypeRef(Context.getObjCSelType(), Record);
+ AddTypeRef(Context.getObjCProtoType(), Record);
+ AddTypeRef(Context.getObjCClassType(), Record);
+ AddTypeRef(Context.getRawCFConstantStringType(), Record);
+ AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record);
+ AddTypeRef(Context.getFILEType(), Record);
+ AddTypeRef(Context.getjmp_bufType(), Record);
+ AddTypeRef(Context.getsigjmp_bufType(), Record);
+ AddTypeRef(Context.ObjCIdRedefinitionType, Record);
+ AddTypeRef(Context.ObjCClassRedefinitionType, Record);
+ AddTypeRef(Context.getRawBlockdescriptorType(), Record);
+ AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
+ AddTypeRef(Context.ObjCSelRedefinitionType, Record);
+ AddTypeRef(Context.getRawNSConstantStringType(), Record);
+ Record.push_back(Context.isInt128Installed());
+ Stream.EmitRecord(SPECIAL_TYPES, Record);
+
+ // Keep writing types and declarations until all types and
+ // declarations have been written.
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, 3);
+ WriteDeclsBlockAbbrevs();
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ Stream.ExitBlock();
+
+ WritePreprocessor(PP);
+ WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
+ WriteSelectors(SemaRef);
+ WriteReferencedSelectorsPool(SemaRef);
+ WriteIdentifierTable(PP);
+ WriteFPPragmaOptions(SemaRef.getFPOptions());
+ WriteOpenCLExtensions(SemaRef);
+
+ WriteTypeDeclOffsets();
+ WritePragmaDiagnosticMappings(Context.getDiagnostics());
+
+ // Write the C++ base-specifier set offsets.
+ if (!CXXBaseSpecifiersOffsets.empty()) {
+ // Create a blob abbreviation for the C++ base specifiers offsets.
+ using namespace llvm;
+
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ // Write the selector offsets table.
+ Record.clear();
+ Record.push_back(CXX_BASE_SPECIFIER_OFFSETS);
+ Record.push_back(CXXBaseSpecifiersOffsets.size());
+ Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record,
+ (const char *)CXXBaseSpecifiersOffsets.data(),
+ CXXBaseSpecifiersOffsets.size() * sizeof(uint32_t));
+ }
+
+ // Write the record containing external, unnamed definitions.
+ if (!ExternalDefinitions.empty())
+ Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+
+ // Write the record containing tentative definitions.
+ if (!TentativeDefinitions.empty())
+ Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);
+
+ // Write the record containing unused file scoped decls.
+ if (!UnusedFileScopedDecls.empty())
+ Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
+
+ // Write the record containing weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty())
+ Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
+ WeakUndeclaredIdentifiers);
+
+ // Write the record containing locally-scoped external definitions.
+ if (!LocallyScopedExternalDecls.empty())
+ Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS,
+ LocallyScopedExternalDecls);
+
+ // Write the record containing ext_vector type names.
+ if (!ExtVectorDecls.empty())
+ Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);
+
+ // Write the record containing VTable uses information.
+ if (!VTableUses.empty())
+ Stream.EmitRecord(VTABLE_USES, VTableUses);
+
+ // Write the record containing dynamic classes declarations.
+ if (!DynamicClasses.empty())
+ Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
+
+ // Write the record containing pending implicit instantiations.
+ if (!PendingInstantiations.empty())
+ Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
+
+ // Write the record containing declaration references of Sema.
+ if (!SemaDeclRefs.empty())
+ Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
+
+ // Write the record containing CUDA-specific declaration references.
+ if (!CUDASpecialDeclRefs.empty())
+ Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);
+
+ // Some simple statistics
+ Record.clear();
+ Record.push_back(NumStatements);
+ Record.push_back(NumMacros);
+ Record.push_back(NumLexicalDeclContexts);
+ Record.push_back(NumVisibleDeclContexts);
+ Stream.EmitRecord(STATISTICS, Record);
+ Stream.ExitBlock();
+}
+
+void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ const char *isysroot) {
+ using namespace llvm;
+
+ ASTContext &Context = SemaRef.Context;
+ Preprocessor &PP = SemaRef.PP;
+
+ RecordData Record;
+ Stream.EnterSubblock(AST_BLOCK_ID, 5);
+ WriteMetadata(Context, isysroot, "");
+ if (StatCalls && !isysroot)
+ WriteStatCache(*StatCalls);
+ // FIXME: Source manager block should only write new stuff, which could be
+ // done by tracking the largest ID in the chain
+ WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+
+ // The special types are in the chained PCH.
+
+ // We don't start with the translation unit, but with its decls that
+ // don't come from the chained PCH.
+ const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ llvm::SmallVector<KindDeclIDPair, 64> NewGlobalDecls;
+ for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
+ E = TU->noload_decls_end();
+ I != E; ++I) {
+ if ((*I)->getPCHLevel() == 0)
+ NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I)));
+ else if ((*I)->isChangedSinceDeserialization())
+ (void)GetDeclRef(*I); // Make sure it's written, but don't record it.
+ }
+ // We also need to write a lexical updates block for the TU.
+ llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv);
+ Record.clear();
+ Record.push_back(TU_UPDATE_LEXICAL);
+ Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+ reinterpret_cast<const char*>(NewGlobalDecls.data()),
+ NewGlobalDecls.size() * sizeof(KindDeclIDPair));
+ // And a visible updates block for the DeclContexts.
+ Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);
+ WriteDeclContextVisibleUpdate(TU);
+
+ // Build a record containing all of the new tentative definitions in this
+ // file, in TentativeDefinitions order.
+ RecordData TentativeDefinitions;
+ for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
+ if (SemaRef.TentativeDefinitions[i]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
+ }
+
+ // Build a record containing all of the file scoped decls in this file.
+ RecordData UnusedFileScopedDecls;
+ for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) {
+ if (SemaRef.UnusedFileScopedDecls[i]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
+ }
+
+ // We write the entire table, overwriting the tables from the chain.
+ RecordData WeakUndeclaredIdentifiers;
+ if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
+ WeakUndeclaredIdentifiers.push_back(
+ SemaRef.WeakUndeclaredIdentifiers.size());
+ for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
+ I = SemaRef.WeakUndeclaredIdentifiers.begin(),
+ E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
+ AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
+ AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
+ WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
+ }
+ }
+
+ // Build a record containing all of the locally-scoped external
+ // declarations in this header file. Generally, this record will be
+ // empty.
+ RecordData LocallyScopedExternalDecls;
+ // FIXME: This is filling in the AST file in densemap order which is
+ // nondeterminstic!
+ for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
+ TD = SemaRef.LocallyScopedExternalDecls.begin(),
+ TDEnd = SemaRef.LocallyScopedExternalDecls.end();
+ TD != TDEnd; ++TD) {
+ if (TD->second->getPCHLevel() == 0)
+ AddDeclRef(TD->second, LocallyScopedExternalDecls);
+ }
+
+ // Build a record containing all of the ext_vector declarations.
+ RecordData ExtVectorDecls;
+ for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) {
+ if (SemaRef.ExtVectorDecls[I]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
+ }
+
+ // Build a record containing all of the VTable uses information.
+ // We write everything here, because it's too hard to determine whether
+ // a use is new to this part.
+ RecordData VTableUses;
+ if (!SemaRef.VTableUses.empty()) {
+ VTableUses.push_back(SemaRef.VTableUses.size());
+ for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
+ AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
+ AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
+ VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
+ }
+ }
+
+ // Build a record containing all of dynamic classes declarations.
+ RecordData DynamicClasses;
+ for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
+ if (SemaRef.DynamicClasses[I]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
+
+ // Build a record containing all of pending implicit instantiations.
+ RecordData PendingInstantiations;
+ for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+ I = SemaRef.PendingInstantiations.begin(),
+ N = SemaRef.PendingInstantiations.end(); I != N; ++I) {
+ if (I->first->getPCHLevel() == 0) {
+ AddDeclRef(I->first, PendingInstantiations);
+ AddSourceLocation(I->second, PendingInstantiations);
+ }
+ }
+ assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+ "There are local ones at end of translation unit!");
+
+ // Build a record containing some declaration references.
+ // It's not worth the effort to avoid duplication here.
+ RecordData SemaDeclRefs;
+ if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+ AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
+ AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+ }
+
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, 3);
+ WriteDeclsBlockAbbrevs();
+ for (DeclsToRewriteTy::iterator
+ I = DeclsToRewrite.begin(), E = DeclsToRewrite.end(); I != E; ++I)
+ DeclTypesToEmit.push(const_cast<Decl*>(*I));
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ Stream.ExitBlock();
+
+ WritePreprocessor(PP);
+ WriteSelectors(SemaRef);
+ WriteReferencedSelectorsPool(SemaRef);
+ WriteIdentifierTable(PP);
+ WriteFPPragmaOptions(SemaRef.getFPOptions());
+ WriteOpenCLExtensions(SemaRef);
+
+ WriteTypeDeclOffsets();
+ // FIXME: For chained PCH only write the new mappings (we currently
+ // write all of them again).
+ WritePragmaDiagnosticMappings(Context.getDiagnostics());
+
+ /// Build a record containing first declarations from a chained PCH and the
+ /// most recent declarations in this AST that they point to.
+ RecordData FirstLatestDeclIDs;
+ for (FirstLatestDeclMap::iterator
+ I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) {
+ assert(I->first->getPCHLevel() > I->second->getPCHLevel() &&
+ "Expected first & second to be in different PCHs");
+ AddDeclRef(I->first, FirstLatestDeclIDs);
+ AddDeclRef(I->second, FirstLatestDeclIDs);
+ }
+ if (!FirstLatestDeclIDs.empty())
+ Stream.EmitRecord(REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
+
+ // Write the record containing external, unnamed definitions.
+ if (!ExternalDefinitions.empty())
+ Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+
+ // Write the record containing tentative definitions.
+ if (!TentativeDefinitions.empty())
+ Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);
+
+ // Write the record containing unused file scoped decls.
+ if (!UnusedFileScopedDecls.empty())
+ Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
+
+ // Write the record containing weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty())
+ Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
+ WeakUndeclaredIdentifiers);
+
+ // Write the record containing locally-scoped external definitions.
+ if (!LocallyScopedExternalDecls.empty())
+ Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS,
+ LocallyScopedExternalDecls);
+
+ // Write the record containing ext_vector type names.
+ if (!ExtVectorDecls.empty())
+ Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);
+
+ // Write the record containing VTable uses information.
+ if (!VTableUses.empty())
+ Stream.EmitRecord(VTABLE_USES, VTableUses);
+
+ // Write the record containing dynamic classes declarations.
+ if (!DynamicClasses.empty())
+ Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
+
+ // Write the record containing pending implicit instantiations.
+ if (!PendingInstantiations.empty())
+ Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
+
+ // Write the record containing declaration references of Sema.
+ if (!SemaDeclRefs.empty())
+ Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
+
+ // Write the updates to DeclContexts.
+ for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator
+ I = UpdatedDeclContexts.begin(),
+ E = UpdatedDeclContexts.end();
+ I != E; ++I)
+ WriteDeclContextVisibleUpdate(*I);
+
+ WriteDeclUpdatesBlocks();
+
+ Record.clear();
+ Record.push_back(NumStatements);
+ Record.push_back(NumMacros);
+ Record.push_back(NumLexicalDeclContexts);
+ Record.push_back(NumVisibleDeclContexts);
+ WriteDeclReplacementsBlock();
+ Stream.EmitRecord(STATISTICS, Record);
+ Stream.ExitBlock();
+}
+
+void ASTWriter::WriteDeclUpdatesBlocks() {
+ if (DeclUpdates.empty())
+ return;
+
+ RecordData OffsetsRecord;
+ Stream.EnterSubblock(DECL_UPDATES_BLOCK_ID, 3);
+ for (DeclUpdateMap::iterator
+ I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
+ const Decl *D = I->first;
+ UpdateRecord &URec = I->second;
+
+ if (DeclsToRewrite.count(D))
+ continue; // The decl will be written completely,no need to store updates.
+
+ uint64_t Offset = Stream.GetCurrentBitNo();
+ Stream.EmitRecord(DECL_UPDATES, URec);
+
+ OffsetsRecord.push_back(GetDeclRef(D));
+ OffsetsRecord.push_back(Offset);
+ }
+ Stream.ExitBlock();
+ Stream.EmitRecord(DECL_UPDATE_OFFSETS, OffsetsRecord);
+}
+
+void ASTWriter::WriteDeclReplacementsBlock() {
+ if (ReplacedDecls.empty())
+ return;
+
+ RecordData Record;
+ for (llvm::SmallVector<std::pair<DeclID, uint64_t>, 16>::iterator
+ I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
+ Record.push_back(I->first);
+ Record.push_back(I->second);
+ }
+ Stream.EmitRecord(DECL_REPLACEMENTS, Record);
+}
+
+void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
+ Record.push_back(Loc.getRawEncoding());
+}
+
+void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) {
+ AddSourceLocation(Range.getBegin(), Record);
+ AddSourceLocation(Range.getEnd(), Record);
+}
+
+void ASTWriter::AddAPInt(const llvm::APInt &Value, RecordDataImpl &Record) {
+ Record.push_back(Value.getBitWidth());
+ const uint64_t *Words = Value.getRawData();
+ Record.append(Words, Words + Value.getNumWords());
+}
+
+void ASTWriter::AddAPSInt(const llvm::APSInt &Value, RecordDataImpl &Record) {
+ Record.push_back(Value.isUnsigned());
+ AddAPInt(Value, Record);
+}
+
+void ASTWriter::AddAPFloat(const llvm::APFloat &Value, RecordDataImpl &Record) {
+ AddAPInt(Value.bitcastToAPInt(), Record);
+}
+
+void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {
+ Record.push_back(getIdentifierRef(II));
+}
+
+IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
+ if (II == 0)
+ return 0;
+
+ IdentID &ID = IdentifierIDs[II];
+ if (ID == 0)
+ ID = NextIdentID++;
+ return ID;
+}
+
+MacroID ASTWriter::getMacroDefinitionID(MacroDefinition *MD) {
+ if (MD == 0)
+ return 0;
+
+ MacroID &ID = MacroDefinitions[MD];
+ if (ID == 0)
+ ID = NextMacroID++;
+ return ID;
+}
+
+void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) {
+ Record.push_back(getSelectorRef(SelRef));
+}
+
+SelectorID ASTWriter::getSelectorRef(Selector Sel) {
+ if (Sel.getAsOpaquePtr() == 0) {
+ return 0;
+ }
+
+ SelectorID &SID = SelectorIDs[Sel];
+ if (SID == 0 && Chain) {
+ // This might trigger a ReadSelector callback, which will set the ID for
+ // this selector.
+ Chain->LoadSelector(Sel);
+ }
+ if (SID == 0) {
+ SID = NextSelectorID++;
+ }
+ return SID;
+}
+
+void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record) {
+ AddDeclRef(Temp->getDestructor(), Record);
+}
+
+void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd,
+ RecordDataImpl &Record) {
+ assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded");
+ CXXBaseSpecifiersToWrite.push_back(
+ QueuedCXXBaseSpecifiers(NextCXXBaseSpecifiersID,
+ Bases, BasesEnd));
+ Record.push_back(NextCXXBaseSpecifiersID++);
+}
+
+void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ const TemplateArgumentLocInfo &Arg,
+ RecordDataImpl &Record) {
+ switch (Kind) {
+ case TemplateArgument::Expression:
+ AddStmt(Arg.getAsExpr());
+ break;
+ case TemplateArgument::Type:
+ AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record);
+ break;
+ case TemplateArgument::Template:
+ AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+ AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+ break;
+ case TemplateArgument::TemplateExpansion:
+ AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+ AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+ AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
+ break;
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Pack:
+ break;
+ }
+}
+
+void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+ RecordDataImpl &Record) {
+ AddTemplateArgument(Arg.getArgument(), Record);
+
+ if (Arg.getArgument().getKind() == TemplateArgument::Expression) {
+ bool InfoHasSameExpr
+ = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr();
+ Record.push_back(InfoHasSameExpr);
+ if (InfoHasSameExpr)
+ return; // Avoid storing the same expr twice.
+ }
+ AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo(),
+ Record);
+}
+
+void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) {
+ if (TInfo == 0) {
+ AddTypeRef(QualType(), Record);
+ return;
+ }
+
+ AddTypeRef(TInfo->getType(), Record);
+ TypeLocWriter TLW(*this, Record);
+ for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLW.Visit(TL);
+}
+
+void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) {
+ Record.push_back(GetOrCreateTypeID(T));
+}
+
+TypeID ASTWriter::GetOrCreateTypeID(QualType T) {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
+}
+
+TypeID ASTWriter::getTypeID(QualType T) const {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
+}
+
+TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
+
+ TypeIdx &Idx = TypeIdxs[T];
+ if (Idx.getIndex() == 0) {
+ // We haven't seen this type before. Assign it a new ID and put it
+ // into the queue of types to emit.
+ Idx = TypeIdx(NextTypeID++);
+ DeclTypesToEmit.push(T);
+ }
+ return Idx;
+}
+
+TypeIdx ASTWriter::getTypeIdx(QualType T) const {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
+
+ TypeIdxMap::const_iterator I = TypeIdxs.find(T);
+ assert(I != TypeIdxs.end() && "Type not emitted!");
+ return I->second;
+}
+
+void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {
+ Record.push_back(GetDeclRef(D));
+}
+
+DeclID ASTWriter::GetDeclRef(const Decl *D) {
+ if (D == 0) {
+ return 0;
+ }
+ assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
+ DeclID &ID = DeclIDs[D];
+ if (ID == 0) {
+ // We haven't seen this declaration before. Give it a new ID and
+ // enqueue it in the list of declarations to emit.
+ ID = NextDeclID++;
+ DeclTypesToEmit.push(const_cast<Decl *>(D));
+ } else if (ID < FirstDeclID && D->isChangedSinceDeserialization()) {
+ // We don't add it to the replacement collection here, because we don't
+ // have the offset yet.
+ DeclTypesToEmit.push(const_cast<Decl *>(D));
+ // Reset the flag, so that we don't add this decl multiple times.
+ const_cast<Decl *>(D)->setChangedSinceDeserialization(false);
+ }
+
+ return ID;
+}
+
+DeclID ASTWriter::getDeclID(const Decl *D) {
+ if (D == 0)
+ return 0;
+
+ assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!");
+ return DeclIDs[D];
+}
+
+void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &Record) {
+ // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc.
+ Record.push_back(Name.getNameKind());
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ AddIdentifierRef(Name.getAsIdentifierInfo(), Record);
+ break;
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ AddSelectorRef(Name.getObjCSelector(), Record);
+ break;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ AddTypeRef(Name.getCXXNameType(), Record);
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ Record.push_back(Name.getCXXOverloadedOperator());
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record);
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ // No extra data to emit
+ break;
+ }
+}
+
+void ASTWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
+ DeclarationName Name, RecordDataImpl &Record) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ AddTypeSourceInfo(DNLoc.NamedType.TInfo, Record);
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ AddSourceLocation(
+ SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.BeginOpNameLoc),
+ Record);
+ AddSourceLocation(
+ SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.EndOpNameLoc),
+ Record);
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName:
+ AddSourceLocation(
+ SourceLocation::getFromRawEncoding(DNLoc.CXXLiteralOperatorName.OpNameLoc),
+ Record);
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+void ASTWriter::AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ RecordDataImpl &Record) {
+ AddDeclarationName(NameInfo.getName(), Record);
+ AddSourceLocation(NameInfo.getLoc(), Record);
+ AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName(), Record);
+}
+
+void ASTWriter::AddQualifierInfo(const QualifierInfo &Info,
+ RecordDataImpl &Record) {
+ AddNestedNameSpecifier(Info.NNS, Record);
+ AddSourceRange(Info.NNSRange, Record);
+ Record.push_back(Info.NumTemplParamLists);
+ for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i)
+ AddTemplateParameterList(Info.TemplParamLists[i], Record);
+}
+
+void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
+ RecordDataImpl &Record) {
+ // Nested name specifiers usually aren't too long. I think that 8 would
+ // typically accomodate the vast majority.
+ llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames;
+
+ // Push each of the NNS's onto a stack for serialization in reverse order.
+ while (NNS) {
+ NestedNames.push_back(NNS);
+ NNS = NNS->getPrefix();
+ }
+
+ Record.push_back(NestedNames.size());
+ while(!NestedNames.empty()) {
+ NNS = NestedNames.pop_back_val();
+ NestedNameSpecifier::SpecifierKind Kind = NNS->getKind();
+ Record.push_back(Kind);
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier:
+ AddIdentifierRef(NNS->getAsIdentifier(), Record);
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ AddDeclRef(NNS->getAsNamespace(), Record);
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ AddTypeRef(QualType(NNS->getAsType(), 0), Record);
+ Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
+ break;
+
+ case NestedNameSpecifier::Global:
+ // Don't need to write an associated value.
+ break;
+ }
+ }
+}
+
+void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
+ TemplateName::NameKind Kind = Name.getKind();
+ Record.push_back(Kind);
+ switch (Kind) {
+ case TemplateName::Template:
+ AddDeclRef(Name.getAsTemplateDecl(), Record);
+ break;
+
+ case TemplateName::OverloadedTemplate: {
+ OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate();
+ Record.push_back(OvT->size());
+ for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end();
+ I != E; ++I)
+ AddDeclRef(*I, Record);
+ break;
+ }
+
+ case TemplateName::QualifiedTemplate: {
+ QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName();
+ AddNestedNameSpecifier(QualT->getQualifier(), Record);
+ Record.push_back(QualT->hasTemplateKeyword());
+ AddDeclRef(QualT->getTemplateDecl(), Record);
+ break;
+ }
+
+ case TemplateName::DependentTemplate: {
+ DependentTemplateName *DepT = Name.getAsDependentTemplateName();
+ AddNestedNameSpecifier(DepT->getQualifier(), Record);
+ Record.push_back(DepT->isIdentifier());
+ if (DepT->isIdentifier())
+ AddIdentifierRef(DepT->getIdentifier(), Record);
+ else
+ Record.push_back(DepT->getOperator());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ SubstTemplateTemplateParmPackStorage *SubstPack
+ = Name.getAsSubstTemplateTemplateParmPack();
+ AddDeclRef(SubstPack->getParameterPack(), Record);
+ AddTemplateArgument(SubstPack->getArgumentPack(), Record);
+ break;
+ }
+ }
+}
+
+void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
+ RecordDataImpl &Record) {
+ Record.push_back(Arg.getKind());
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+ case TemplateArgument::Type:
+ AddTypeRef(Arg.getAsType(), Record);
+ break;
+ case TemplateArgument::Declaration:
+ AddDeclRef(Arg.getAsDecl(), Record);
+ break;
+ case TemplateArgument::Integral:
+ AddAPSInt(*Arg.getAsIntegral(), Record);
+ AddTypeRef(Arg.getIntegralType(), Record);
+ break;
+ case TemplateArgument::Template:
+ AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+ break;
+ case TemplateArgument::TemplateExpansion:
+ AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+ if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions())
+ Record.push_back(*NumExpansions + 1);
+ else
+ Record.push_back(0);
+ break;
+ case TemplateArgument::Expression:
+ AddStmt(Arg.getAsExpr());
+ break;
+ case TemplateArgument::Pack:
+ Record.push_back(Arg.pack_size());
+ for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end();
+ I != E; ++I)
+ AddTemplateArgument(*I, Record);
+ break;
+ }
+}
+
+void
+ASTWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
+ RecordDataImpl &Record) {
+ assert(TemplateParams && "No TemplateParams!");
+ AddSourceLocation(TemplateParams->getTemplateLoc(), Record);
+ AddSourceLocation(TemplateParams->getLAngleLoc(), Record);
+ AddSourceLocation(TemplateParams->getRAngleLoc(), Record);
+ Record.push_back(TemplateParams->size());
+ for (TemplateParameterList::const_iterator
+ P = TemplateParams->begin(), PEnd = TemplateParams->end();
+ P != PEnd; ++P)
+ AddDeclRef(*P, Record);
+}
+
+/// \brief Emit a template argument list.
+void
+ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
+ RecordDataImpl &Record) {
+ assert(TemplateArgs && "No TemplateArgs!");
+ Record.push_back(TemplateArgs->size());
+ for (int i=0, e = TemplateArgs->size(); i != e; ++i)
+ AddTemplateArgument(TemplateArgs->get(i), Record);
+}
+
+
+void
+ASTWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record) {
+ Record.push_back(Set.size());
+ for (UnresolvedSetImpl::const_iterator
+ I = Set.begin(), E = Set.end(); I != E; ++I) {
+ AddDeclRef(I.getDecl(), Record);
+ Record.push_back(I.getAccess());
+ }
+}
+
+void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
+ RecordDataImpl &Record) {
+ Record.push_back(Base.isVirtual());
+ Record.push_back(Base.isBaseOfClass());
+ Record.push_back(Base.getAccessSpecifierAsWritten());
+ Record.push_back(Base.getInheritConstructors());
+ AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
+ AddSourceRange(Base.getSourceRange(), Record);
+ AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
+}
+
+void ASTWriter::FlushCXXBaseSpecifiers() {
+ RecordData Record;
+ for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) {
+ Record.clear();
+
+ // Record the offset of this base-specifier set.
+ unsigned Index = CXXBaseSpecifiersToWrite[I].ID - FirstCXXBaseSpecifiersID;
+ if (Index == CXXBaseSpecifiersOffsets.size())
+ CXXBaseSpecifiersOffsets.push_back(Stream.GetCurrentBitNo());
+ else {
+ if (Index > CXXBaseSpecifiersOffsets.size())
+ CXXBaseSpecifiersOffsets.resize(Index + 1);
+ CXXBaseSpecifiersOffsets[Index] = Stream.GetCurrentBitNo();
+ }
+
+ const CXXBaseSpecifier *B = CXXBaseSpecifiersToWrite[I].Bases,
+ *BEnd = CXXBaseSpecifiersToWrite[I].BasesEnd;
+ Record.push_back(BEnd - B);
+ for (; B != BEnd; ++B)
+ AddCXXBaseSpecifier(*B, Record);
+ Stream.EmitRecord(serialization::DECL_CXX_BASE_SPECIFIERS, Record);
+
+ // Flush any expressions that were written as part of the base specifiers.
+ FlushStmts();
+ }
+
+ CXXBaseSpecifiersToWrite.clear();
+}
+
+void ASTWriter::AddCXXCtorInitializers(
+ const CXXCtorInitializer * const *CtorInitializers,
+ unsigned NumCtorInitializers,
+ RecordDataImpl &Record) {
+ Record.push_back(NumCtorInitializers);
+ for (unsigned i=0; i != NumCtorInitializers; ++i) {
+ const CXXCtorInitializer *Init = CtorInitializers[i];
+
+ Record.push_back(Init->isBaseInitializer());
+ if (Init->isBaseInitializer()) {
+ AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
+ Record.push_back(Init->isBaseVirtual());
+ } else {
+ Record.push_back(Init->isIndirectMemberInitializer());
+ if (Init->isIndirectMemberInitializer())
+ AddDeclRef(Init->getIndirectMember(), Record);
+ else
+ AddDeclRef(Init->getMember(), Record);
+ }
+
+ AddSourceLocation(Init->getMemberLocation(), Record);
+ AddStmt(Init->getInit());
+ AddSourceLocation(Init->getLParenLoc(), Record);
+ AddSourceLocation(Init->getRParenLoc(), Record);
+ Record.push_back(Init->isWritten());
+ if (Init->isWritten()) {
+ Record.push_back(Init->getSourceOrder());
+ } else {
+ Record.push_back(Init->getNumArrayIndices());
+ for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i)
+ AddDeclRef(Init->getArrayIndex(i), Record);
+ }
+ }
+}
+
+void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) {
+ assert(D->DefinitionData);
+ struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;
+ Record.push_back(Data.UserDeclaredConstructor);
+ Record.push_back(Data.UserDeclaredCopyConstructor);
+ Record.push_back(Data.UserDeclaredCopyAssignment);
+ Record.push_back(Data.UserDeclaredDestructor);
+ Record.push_back(Data.Aggregate);
+ Record.push_back(Data.PlainOldData);
+ Record.push_back(Data.Empty);
+ Record.push_back(Data.Polymorphic);
+ Record.push_back(Data.Abstract);
+ Record.push_back(Data.HasTrivialConstructor);
+ Record.push_back(Data.HasTrivialCopyConstructor);
+ Record.push_back(Data.HasTrivialCopyAssignment);
+ Record.push_back(Data.HasTrivialDestructor);
+ Record.push_back(Data.ComputedVisibleConversions);
+ Record.push_back(Data.DeclaredDefaultConstructor);
+ Record.push_back(Data.DeclaredCopyConstructor);
+ Record.push_back(Data.DeclaredCopyAssignment);
+ Record.push_back(Data.DeclaredDestructor);
+
+ Record.push_back(Data.NumBases);
+ if (Data.NumBases > 0)
+ AddCXXBaseSpecifiersRef(Data.getBases(), Data.getBases() + Data.NumBases,
+ Record);
+
+ // FIXME: Make VBases lazily computed when needed to avoid storing them.
+ Record.push_back(Data.NumVBases);
+ if (Data.NumVBases > 0)
+ AddCXXBaseSpecifiersRef(Data.getVBases(), Data.getVBases() + Data.NumVBases,
+ Record);
+
+ AddUnresolvedSet(Data.Conversions, Record);
+ AddUnresolvedSet(Data.VisibleConversions, Record);
+ // Data.Definition is the owning decl, no need to write it.
+ AddDeclRef(Data.FirstFriend, Record);
+}
+
+void ASTWriter::ReaderInitialized(ASTReader *Reader) {
+ assert(Reader && "Cannot remove chain");
+ assert(!Chain && "Cannot replace chain");
+ assert(FirstDeclID == NextDeclID &&
+ FirstTypeID == NextTypeID &&
+ FirstIdentID == NextIdentID &&
+ FirstSelectorID == NextSelectorID &&
+ FirstMacroID == NextMacroID &&
+ FirstCXXBaseSpecifiersID == NextCXXBaseSpecifiersID &&
+ "Setting chain after writing has started.");
+ Chain = Reader;
+
+ FirstDeclID += Chain->getTotalNumDecls();
+ FirstTypeID += Chain->getTotalNumTypes();
+ FirstIdentID += Chain->getTotalNumIdentifiers();
+ FirstSelectorID += Chain->getTotalNumSelectors();
+ FirstMacroID += Chain->getTotalNumMacroDefinitions();
+ FirstCXXBaseSpecifiersID += Chain->getTotalNumCXXBaseSpecifiers();
+ NextDeclID = FirstDeclID;
+ NextTypeID = FirstTypeID;
+ NextIdentID = FirstIdentID;
+ NextSelectorID = FirstSelectorID;
+ NextMacroID = FirstMacroID;
+ NextCXXBaseSpecifiersID = FirstCXXBaseSpecifiersID;
+}
+
+void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) {
+ IdentifierIDs[II] = ID;
+ if (II->hasMacroDefinition())
+ DeserializedMacroNames.push_back(II);
+}
+
+void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {
+ // Always take the highest-numbered type index. This copes with an interesting
+ // case for chained AST writing where we schedule writing the type and then,
+ // later, deserialize the type from another AST. In this case, we want to
+ // keep the higher-numbered entry so that we can properly write it out to
+ // the AST file.
+ TypeIdx &StoredIdx = TypeIdxs[T];
+ if (Idx.getIndex() >= StoredIdx.getIndex())
+ StoredIdx = Idx;
+}
+
+void ASTWriter::DeclRead(DeclID ID, const Decl *D) {
+ DeclIDs[D] = ID;
+}
+
+void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
+ SelectorIDs[S] = ID;
+}
+
+void ASTWriter::MacroDefinitionRead(serialization::MacroID ID,
+ MacroDefinition *MD) {
+ MacroDefinitions[MD] = ID;
+}
+
+void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
+ assert(D->isDefinition());
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ // We are interested when a PCH decl is modified.
+ if (RD->getPCHLevel() > 0) {
+ // A forward reference was mutated into a definition. Rewrite it.
+ // FIXME: This happens during template instantiation, should we
+ // have created a new definition decl instead ?
+ RewriteDecl(RD);
+ }
+
+ for (CXXRecordDecl::redecl_iterator
+ I = RD->redecls_begin(), E = RD->redecls_end(); I != E; ++I) {
+ CXXRecordDecl *Redecl = cast<CXXRecordDecl>(*I);
+ if (Redecl == RD)
+ continue;
+
+ // We are interested when a PCH decl is modified.
+ if (Redecl->getPCHLevel() > 0) {
+ UpdateRecord &Record = DeclUpdates[Redecl];
+ Record.push_back(UPD_CXX_SET_DEFINITIONDATA);
+ assert(Redecl->DefinitionData);
+ assert(Redecl->DefinitionData->Definition == D);
+ AddDeclRef(D, Record); // the DefinitionDecl
+ }
+ }
+ }
+}
+void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
+ // TU and namespaces are handled elsewhere.
+ if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
+ return;
+
+ if (!(D->getPCHLevel() == 0 && cast<Decl>(DC)->getPCHLevel() > 0))
+ return; // Not a source decl added to a DeclContext from PCH.
+
+ AddUpdatedDeclContext(DC);
+}
+
+void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
+ assert(D->isImplicit());
+ if (!(D->getPCHLevel() == 0 && RD->getPCHLevel() > 0))
+ return; // Not a source member added to a class from PCH.
+ if (!isa<CXXMethodDecl>(D))
+ return; // We are interested in lazily declared implicit methods.
+
+ // A decl coming from PCH was modified.
+ assert(RD->isDefinition());
+ UpdateRecord &Record = DeclUpdates[RD];
+ Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
+ AddDeclRef(D, Record);
+}
+
+void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) {
+ // The specializations set is kept in the canonical template.
+ TD = TD->getCanonicalDecl();
+ if (!(D->getPCHLevel() == 0 && TD->getPCHLevel() > 0))
+ return; // Not a source specialization added to a template from PCH.
+
+ UpdateRecord &Record = DeclUpdates[TD];
+ Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
+ AddDeclRef(D, Record);
+}
+
+ASTSerializationListener::~ASTSerializationListener() { }
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
new file mode 100644
index 0000000..ce07e138
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -0,0 +1,1254 @@
+//===--- ASTWriterDecl.cpp - Declaration Serialization --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements serialization for Declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Declaration serialization
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> {
+
+ ASTWriter &Writer;
+ ASTContext &Context;
+ typedef ASTWriter::RecordData RecordData;
+ RecordData &Record;
+
+ public:
+ serialization::DeclCode Code;
+ unsigned AbbrevToUse;
+
+ ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, RecordData &Record)
+ : Writer(Writer), Context(Context), Record(Record) {
+ }
+
+ void Visit(Decl *D);
+
+ void VisitDecl(Decl *D);
+ void VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ void VisitNamedDecl(NamedDecl *D);
+ void VisitLabelDecl(LabelDecl *LD);
+ void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ void VisitTypeDecl(TypeDecl *D);
+ void VisitTypedefDecl(TypedefDecl *D);
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitTagDecl(TagDecl *D);
+ void VisitEnumDecl(EnumDecl *D);
+ void VisitRecordDecl(RecordDecl *D);
+ void VisitCXXRecordDecl(CXXRecordDecl *D);
+ void VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D);
+ void VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ void VisitValueDecl(ValueDecl *D);
+ void VisitEnumConstantDecl(EnumConstantDecl *D);
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ void VisitDeclaratorDecl(DeclaratorDecl *D);
+ void VisitFunctionDecl(FunctionDecl *D);
+ void VisitCXXMethodDecl(CXXMethodDecl *D);
+ void VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ void VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ void VisitCXXConversionDecl(CXXConversionDecl *D);
+ void VisitFieldDecl(FieldDecl *D);
+ void VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ void VisitVarDecl(VarDecl *D);
+ void VisitImplicitParamDecl(ImplicitParamDecl *D);
+ void VisitParmVarDecl(ParmVarDecl *D);
+ void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ void VisitTemplateDecl(TemplateDecl *D);
+ void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
+ void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingShadowDecl(UsingShadowDecl *D);
+ void VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
+ void VisitAccessSpecDecl(AccessSpecDecl *D);
+ void VisitFriendDecl(FriendDecl *D);
+ void VisitFriendTemplateDecl(FriendTemplateDecl *D);
+ void VisitStaticAssertDecl(StaticAssertDecl *D);
+ void VisitBlockDecl(BlockDecl *D);
+
+ void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+ uint64_t VisibleOffset);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
+
+
+ // FIXME: Put in the same order is DeclNodes.td?
+ void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCContainerDecl(ObjCContainerDecl *D);
+ void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ void VisitObjCIvarDecl(ObjCIvarDecl *D);
+ void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
+ void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
+ void VisitObjCClassDecl(ObjCClassDecl *D);
+ void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+ void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
+ void VisitObjCImplDecl(ObjCImplDecl *D);
+ void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
+ void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ };
+}
+
+void ASTDeclWriter::Visit(Decl *D) {
+ DeclVisitor<ASTDeclWriter>::Visit(D);
+
+ // Handle FunctionDecl's body here and write it after all other Stmts/Exprs
+ // have been written. We want it last because we will not read it back when
+ // retrieving it from the AST, we'll just lazily set the offset.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ Record.push_back(FD->isThisDeclarationADefinition());
+ if (FD->isThisDeclarationADefinition())
+ Writer.AddStmt(FD->getBody());
+ }
+}
+
+void ASTDeclWriter::VisitDecl(Decl *D) {
+ Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
+ Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
+ Writer.AddSourceLocation(D->getLocation(), Record);
+ Record.push_back(D->isInvalidDecl());
+ Record.push_back(D->hasAttrs());
+ if (D->hasAttrs())
+ Writer.WriteAttributes(D->getAttrs(), Record);
+ Record.push_back(D->isImplicit());
+ Record.push_back(D->isUsed(false));
+ Record.push_back(D->getAccess());
+ Record.push_back(D->getPCHLevel());
+}
+
+void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ VisitDecl(D);
+ Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
+ Code = serialization::DECL_TRANSLATION_UNIT;
+}
+
+void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
+ VisitDecl(D);
+ Writer.AddDeclarationName(D->getDeclName(), Record);
+}
+
+void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+}
+
+void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+ VisitTypeDecl(D);
+ Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+ Code = serialization::DECL_TYPEDEF;
+}
+
+void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
+ VisitTypeDecl(D);
+ VisitRedeclarable(D);
+ Record.push_back(D->getIdentifierNamespace());
+ Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
+ Record.push_back(D->isDefinition());
+ Record.push_back(D->isEmbeddedInDeclarator());
+ Writer.AddSourceLocation(D->getRBraceLoc(), Record);
+ Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
+ Record.push_back(D->hasExtInfo());
+ if (D->hasExtInfo())
+ Writer.AddQualifierInfo(*D->getExtInfo(), Record);
+ else
+ Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
+}
+
+void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
+ VisitTagDecl(D);
+ Writer.AddTypeSourceInfo(D->getIntegerTypeSourceInfo(), Record);
+ if (!D->getIntegerTypeSourceInfo())
+ Writer.AddTypeRef(D->getIntegerType(), Record);
+ Writer.AddTypeRef(D->getPromotionType(), Record);
+ Record.push_back(D->getNumPositiveBits());
+ Record.push_back(D->getNumNegativeBits());
+ Record.push_back(D->isScoped());
+ Record.push_back(D->isScopedUsingClassTag());
+ Record.push_back(D->isFixed());
+ Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record);
+ Code = serialization::DECL_ENUM;
+}
+
+void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
+ VisitTagDecl(D);
+ Record.push_back(D->hasFlexibleArrayMember());
+ Record.push_back(D->isAnonymousStructOrUnion());
+ Record.push_back(D->hasObjectMember());
+ Code = serialization::DECL_RECORD;
+}
+
+void ASTDeclWriter::VisitValueDecl(ValueDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddTypeRef(D->getType(), Record);
+}
+
+void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ VisitValueDecl(D);
+ Record.push_back(D->getInitExpr()? 1 : 0);
+ if (D->getInitExpr())
+ Writer.AddStmt(D->getInitExpr());
+ Writer.AddAPSInt(D->getInitVal(), Record);
+ Code = serialization::DECL_ENUM_CONSTANT;
+}
+
+void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
+ VisitValueDecl(D);
+ Record.push_back(D->hasExtInfo());
+ if (D->hasExtInfo())
+ Writer.AddQualifierInfo(*D->getExtInfo(), Record);
+ Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+}
+
+void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
+ VisitDeclaratorDecl(D);
+ VisitRedeclarable(D);
+
+ Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
+ Record.push_back(D->getIdentifierNamespace());
+ Record.push_back(D->getTemplatedKind());
+ switch (D->getTemplatedKind()) {
+ default: assert(false && "Unhandled TemplatedKind!");
+ break;
+ case FunctionDecl::TK_NonTemplate:
+ break;
+ case FunctionDecl::TK_FunctionTemplate:
+ Writer.AddDeclRef(D->getDescribedFunctionTemplate(), Record);
+ break;
+ case FunctionDecl::TK_MemberSpecialization: {
+ MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo();
+ Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record);
+ Record.push_back(MemberInfo->getTemplateSpecializationKind());
+ Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record);
+ break;
+ }
+ case FunctionDecl::TK_FunctionTemplateSpecialization: {
+ FunctionTemplateSpecializationInfo *
+ FTSInfo = D->getTemplateSpecializationInfo();
+ Writer.AddDeclRef(FTSInfo->getTemplate(), Record);
+ Record.push_back(FTSInfo->getTemplateSpecializationKind());
+
+ // Template arguments.
+ Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record);
+
+ // Template args as written.
+ Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0);
+ if (FTSInfo->TemplateArgumentsAsWritten) {
+ Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size());
+ for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i)
+ Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i],
+ Record);
+ Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(),
+ Record);
+ Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(),
+ Record);
+ }
+
+ Writer.AddSourceLocation(FTSInfo->getPointOfInstantiation(), Record);
+
+ if (D->isCanonicalDecl()) {
+ // Write the template that contains the specializations set. We will
+ // add a FunctionTemplateSpecializationInfo to it when reading.
+ Writer.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl(), Record);
+ }
+ break;
+ }
+ case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
+ DependentFunctionTemplateSpecializationInfo *
+ DFTSInfo = D->getDependentSpecializationInfo();
+
+ // Templates.
+ Record.push_back(DFTSInfo->getNumTemplates());
+ for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i)
+ Writer.AddDeclRef(DFTSInfo->getTemplate(i), Record);
+
+ // Templates args.
+ Record.push_back(DFTSInfo->getNumTemplateArgs());
+ for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i)
+ Writer.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i), Record);
+ Writer.AddSourceLocation(DFTSInfo->getLAngleLoc(), Record);
+ Writer.AddSourceLocation(DFTSInfo->getRAngleLoc(), Record);
+ break;
+ }
+ }
+
+ // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
+ // after everything else is written.
+
+ Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+ Record.push_back(D->getStorageClassAsWritten());
+ Record.push_back(D->IsInline);
+ Record.push_back(D->isInlineSpecified());
+ Record.push_back(D->isVirtualAsWritten());
+ Record.push_back(D->isPure());
+ Record.push_back(D->hasInheritedPrototype());
+ Record.push_back(D->hasWrittenPrototype());
+ Record.push_back(D->isDeleted());
+ Record.push_back(D->isTrivial());
+ Record.push_back(D->hasImplicitReturnZero());
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
+
+ Record.push_back(D->param_size());
+ for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+ Code = serialization::DECL_FUNCTION;
+}
+
+void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ VisitNamedDecl(D);
+ // FIXME: convert to LazyStmtPtr?
+ // Unlike C/C++, method bodies will never be in header files.
+ bool HasBodyStuff = D->getBody() != 0 ||
+ D->getSelfDecl() != 0 || D->getCmdDecl() != 0;
+ Record.push_back(HasBodyStuff);
+ if (HasBodyStuff) {
+ Writer.AddStmt(D->getBody());
+ Writer.AddDeclRef(D->getSelfDecl(), Record);
+ Writer.AddDeclRef(D->getCmdDecl(), Record);
+ }
+ Record.push_back(D->isInstanceMethod());
+ Record.push_back(D->isVariadic());
+ Record.push_back(D->isSynthesized());
+ Record.push_back(D->isDefined());
+ // FIXME: stable encoding for @required/@optional
+ Record.push_back(D->getImplementationControl());
+ // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
+ Record.push_back(D->getObjCDeclQualifier());
+ Record.push_back(D->getNumSelectorArgs());
+ Writer.AddTypeRef(D->getResultType(), Record);
+ Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record);
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
+ Record.push_back(D->param_size());
+ for (ObjCMethodDecl::param_iterator P = D->param_begin(),
+ PEnd = D->param_end(); P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+ Code = serialization::DECL_OBJC_METHOD;
+}
+
+void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddSourceRange(D->getAtEndRange(), Record);
+ // Abstract class (no need to define a stable serialization::DECL code).
+}
+
+void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ VisitObjCContainerDecl(D);
+ Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+ Writer.AddDeclRef(D->getSuperClass(), Record);
+
+ // Write out the protocols that are directly referenced by the @interface.
+ Record.push_back(D->ReferencedProtocols.size());
+ for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
+ PEnd = D->protocol_end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+ for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+ PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
+
+ // Write out the protocols that are transitively referenced.
+ Record.push_back(D->AllReferencedProtocols.size());
+ for (ObjCList<ObjCProtocolDecl>::iterator
+ P = D->AllReferencedProtocols.begin(),
+ PEnd = D->AllReferencedProtocols.end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+
+ // Write out the ivars.
+ Record.push_back(D->ivar_size());
+ for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
+ IEnd = D->ivar_end(); I != IEnd; ++I)
+ Writer.AddDeclRef(*I, Record);
+ Writer.AddDeclRef(D->getCategoryList(), Record);
+ Record.push_back(D->isForwardDecl());
+ Record.push_back(D->isImplicitInterfaceDecl());
+ Writer.AddSourceLocation(D->getClassLoc(), Record);
+ Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
+ Code = serialization::DECL_OBJC_INTERFACE;
+}
+
+void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
+ VisitFieldDecl(D);
+ // FIXME: stable encoding for @public/@private/@protected/@package
+ Record.push_back(D->getAccessControl());
+ Record.push_back(D->getSynthesize());
+ Code = serialization::DECL_OBJC_IVAR;
+}
+
+void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+ VisitObjCContainerDecl(D);
+ Record.push_back(D->isForwardDecl());
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
+ Record.push_back(D->protocol_size());
+ for (ObjCProtocolDecl::protocol_iterator
+ I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+ Writer.AddDeclRef(*I, Record);
+ for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+ PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
+ Code = serialization::DECL_OBJC_PROTOCOL;
+}
+
+void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
+ VisitFieldDecl(D);
+ Code = serialization::DECL_OBJC_AT_DEFS_FIELD;
+}
+
+void ASTDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
+ VisitDecl(D);
+ Record.push_back(D->size());
+ for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+ Writer.AddDeclRef(I->getInterface(), Record);
+ for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+ Writer.AddSourceLocation(I->getLocation(), Record);
+ Code = serialization::DECL_OBJC_CLASS;
+}
+
+void ASTDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ VisitDecl(D);
+ Record.push_back(D->protocol_size());
+ for (ObjCForwardProtocolDecl::protocol_iterator
+ I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+ Writer.AddDeclRef(*I, Record);
+ for (ObjCForwardProtocolDecl::protocol_loc_iterator
+ PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
+ Code = serialization::DECL_OBJC_FORWARD_PROTOCOL;
+}
+
+void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
+ VisitObjCContainerDecl(D);
+ Writer.AddDeclRef(D->getClassInterface(), Record);
+ Record.push_back(D->protocol_size());
+ for (ObjCCategoryDecl::protocol_iterator
+ I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
+ Writer.AddDeclRef(*I, Record);
+ for (ObjCCategoryDecl::protocol_loc_iterator
+ PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+ PL != PLEnd; ++PL)
+ Writer.AddSourceLocation(*PL, Record);
+ Writer.AddDeclRef(D->getNextClassCategory(), Record);
+ Record.push_back(D->hasSynthBitfield());
+ Writer.AddSourceLocation(D->getAtLoc(), Record);
+ Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
+ Code = serialization::DECL_OBJC_CATEGORY;
+}
+
+void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddDeclRef(D->getClassInterface(), Record);
+ Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS;
+}
+
+void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddSourceLocation(D->getAtLoc(), Record);
+ Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
+ // FIXME: stable encoding
+ Record.push_back((unsigned)D->getPropertyAttributes());
+ Record.push_back((unsigned)D->getPropertyAttributesAsWritten());
+ // FIXME: stable encoding
+ Record.push_back((unsigned)D->getPropertyImplementation());
+ Writer.AddDeclarationName(D->getGetterName(), Record);
+ Writer.AddDeclarationName(D->getSetterName(), Record);
+ Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
+ Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
+ Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
+ Code = serialization::DECL_OBJC_PROPERTY;
+}
+
+void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
+ VisitObjCContainerDecl(D);
+ Writer.AddDeclRef(D->getClassInterface(), Record);
+ // Abstract class (no need to define a stable serialization::DECL code).
+}
+
+void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ VisitObjCImplDecl(D);
+ Writer.AddIdentifierRef(D->getIdentifier(), Record);
+ Code = serialization::DECL_OBJC_CATEGORY_IMPL;
+}
+
+void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+ VisitObjCImplDecl(D);
+ Writer.AddDeclRef(D->getSuperClass(), Record);
+ Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers,
+ Record);
+ Record.push_back(D->hasSynthBitfield());
+ Code = serialization::DECL_OBJC_IMPLEMENTATION;
+}
+
+void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ VisitDecl(D);
+ Writer.AddSourceLocation(D->getLocStart(), Record);
+ Writer.AddDeclRef(D->getPropertyDecl(), Record);
+ Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
+ Writer.AddSourceLocation(D->getPropertyIvarDeclLoc(), Record);
+ Writer.AddStmt(D->getGetterCXXConstructor());
+ Writer.AddStmt(D->getSetterCXXAssignment());
+ Code = serialization::DECL_OBJC_PROPERTY_IMPL;
+}
+
+void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
+ VisitDeclaratorDecl(D);
+ Record.push_back(D->isMutable());
+ Record.push_back(D->getBitWidth()? 1 : 0);
+ if (D->getBitWidth())
+ Writer.AddStmt(D->getBitWidth());
+ if (!D->getDeclName())
+ Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
+ Code = serialization::DECL_FIELD;
+}
+
+void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
+ VisitValueDecl(D);
+ Record.push_back(D->getChainingSize());
+
+ for (IndirectFieldDecl::chain_iterator
+ P = D->chain_begin(),
+ PEnd = D->chain_end(); P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+ Code = serialization::DECL_INDIRECTFIELD;
+}
+
+void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
+ VisitDeclaratorDecl(D);
+ VisitRedeclarable(D);
+ Record.push_back(D->getStorageClass()); // FIXME: stable encoding
+ Record.push_back(D->getStorageClassAsWritten());
+ Record.push_back(D->isThreadSpecified());
+ Record.push_back(D->hasCXXDirectInitializer());
+ Record.push_back(D->isExceptionVariable());
+ Record.push_back(D->isNRVOVariable());
+ Record.push_back(D->getInit() ? 1 : 0);
+ if (D->getInit())
+ Writer.AddStmt(D->getInit());
+
+ MemberSpecializationInfo *SpecInfo
+ = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0;
+ Record.push_back(SpecInfo != 0);
+ if (SpecInfo) {
+ Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record);
+ Record.push_back(SpecInfo->getTemplateSpecializationKind());
+ Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record);
+ }
+
+ Code = serialization::DECL_VAR;
+}
+
+void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
+ VisitVarDecl(D);
+ Code = serialization::DECL_IMPLICIT_PARAM;
+}
+
+void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
+ VisitVarDecl(D);
+ Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
+ Record.push_back(D->hasInheritedDefaultArg());
+ Record.push_back(D->hasUninstantiatedDefaultArg());
+ if (D->hasUninstantiatedDefaultArg())
+ Writer.AddStmt(D->getUninstantiatedDefaultArg());
+ Code = serialization::DECL_PARM_VAR;
+
+ // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
+ // we dynamically check for the properties that we optimize for, but don't
+ // know are true of all PARM_VAR_DECLs.
+ if (!D->getTypeSourceInfo() &&
+ !D->hasAttrs() &&
+ !D->isImplicit() &&
+ !D->isUsed(false) &&
+ D->getAccess() == AS_none &&
+ D->getPCHLevel() == 0 &&
+ D->getStorageClass() == 0 &&
+ !D->hasCXXDirectInitializer() && // Can params have this ever?
+ D->getObjCDeclQualifier() == 0 &&
+ !D->hasInheritedDefaultArg() &&
+ D->getInit() == 0 &&
+ !D->hasUninstantiatedDefaultArg()) // No default expr.
+ AbbrevToUse = Writer.getParmVarDeclAbbrev();
+
+ // Check things we know are true of *every* PARM_VAR_DECL, which is more than
+ // just us assuming it.
+ assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
+ assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
+ assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
+ assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
+ assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
+ assert(!D->isStaticDataMember() &&
+ "PARM_VAR_DECL can't be static data member");
+}
+
+void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
+ VisitDecl(D);
+ Writer.AddStmt(D->getAsmString());
+ Code = serialization::DECL_FILE_SCOPE_ASM;
+}
+
+void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
+ VisitDecl(D);
+ Writer.AddStmt(D->getBody());
+ Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record);
+ Record.push_back(D->param_size());
+ for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+ Record.push_back(D->capturesCXXThis());
+ Record.push_back(D->getNumCaptures());
+ for (BlockDecl::capture_iterator
+ i = D->capture_begin(), e = D->capture_end(); i != e; ++i) {
+ const BlockDecl::Capture &capture = *i;
+ Writer.AddDeclRef(capture.getVariable(), Record);
+
+ unsigned flags = 0;
+ if (capture.isByRef()) flags |= 1;
+ if (capture.isNested()) flags |= 2;
+ if (capture.hasCopyExpr()) flags |= 4;
+ Record.push_back(flags);
+
+ if (capture.hasCopyExpr()) Writer.AddStmt(capture.getCopyExpr());
+ }
+
+ Code = serialization::DECL_BLOCK;
+}
+
+void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ VisitDecl(D);
+ // FIXME: It might be nice to serialize the brace locations for this
+ // declaration, which don't seem to be readily available in the AST.
+ Record.push_back(D->getLanguage());
+ Record.push_back(D->hasBraces());
+ Code = serialization::DECL_LINKAGE_SPEC;
+}
+
+void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
+ VisitNamedDecl(D);
+ Code = serialization::DECL_LABEL;
+}
+
+
+void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
+ VisitNamedDecl(D);
+ Record.push_back(D->isInline());
+ Writer.AddSourceLocation(D->getLBracLoc(), Record);
+ Writer.AddSourceLocation(D->getRBracLoc(), Record);
+ Writer.AddDeclRef(D->getNextNamespace(), Record);
+
+ // Only write one reference--original or anonymous
+ Record.push_back(D->isOriginalNamespace());
+ if (D->isOriginalNamespace())
+ Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
+ else
+ Writer.AddDeclRef(D->getOriginalNamespace(), Record);
+ Code = serialization::DECL_NAMESPACE;
+
+ if (Writer.hasChain() && !D->isOriginalNamespace() &&
+ D->getOriginalNamespace()->getPCHLevel() > 0) {
+ NamespaceDecl *NS = D->getOriginalNamespace();
+ Writer.AddUpdatedDeclContext(NS);
+
+ // Make sure all visible decls are written. They will be recorded later.
+ NS->lookup(DeclarationName());
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(NS->getLookupPtr());
+ if (Map) {
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ DeclContext::lookup_result Result = D->second.getLookupResult();
+ while (Result.first != Result.second) {
+ Writer.GetDeclRef(*Result.first);
+ ++Result.first;
+ }
+ }
+ }
+ }
+}
+
+void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddSourceLocation(D->getNamespaceLoc(), Record);
+ Writer.AddSourceRange(D->getQualifierRange(), Record);
+ Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+ Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
+ Writer.AddDeclRef(D->getNamespace(), Record);
+ Code = serialization::DECL_NAMESPACE_ALIAS;
+}
+
+void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddSourceRange(D->getNestedNameRange(), Record);
+ Writer.AddSourceLocation(D->getUsingLocation(), Record);
+ Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
+ Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
+ Writer.AddDeclRef(D->FirstUsingShadow, Record);
+ Record.push_back(D->isTypeName());
+ Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
+ Code = serialization::DECL_USING;
+}
+
+void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddDeclRef(D->getTargetDecl(), Record);
+ Writer.AddDeclRef(D->UsingOrNextShadow, Record);
+ Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record);
+ Code = serialization::DECL_USING_SHADOW;
+}
+
+void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ VisitNamedDecl(D);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
+ Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
+ Writer.AddSourceRange(D->getQualifierRange(), Record);
+ Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+ Writer.AddDeclRef(D->getNominatedNamespace(), Record);
+ Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
+ Code = serialization::DECL_USING_DIRECTIVE;
+}
+
+void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ VisitValueDecl(D);
+ Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
+ Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
+ Code = serialization::DECL_UNRESOLVED_USING_VALUE;
+}
+
+void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ VisitTypeDecl(D);
+ Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
+ Writer.AddSourceLocation(D->getTypenameLoc(), Record);
+ Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
+}
+
+void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ VisitRecordDecl(D);
+
+ CXXRecordDecl *DefinitionDecl = 0;
+ if (D->DefinitionData)
+ DefinitionDecl = D->DefinitionData->Definition;
+ Writer.AddDeclRef(DefinitionDecl, Record);
+ if (D == DefinitionDecl)
+ Writer.AddCXXDefinitionData(D, Record);
+
+ enum {
+ CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
+ };
+ if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) {
+ Record.push_back(CXXRecTemplate);
+ Writer.AddDeclRef(TemplD, Record);
+ } else if (MemberSpecializationInfo *MSInfo
+ = D->getMemberSpecializationInfo()) {
+ Record.push_back(CXXRecMemberSpecialization);
+ Writer.AddDeclRef(MSInfo->getInstantiatedFrom(), Record);
+ Record.push_back(MSInfo->getTemplateSpecializationKind());
+ Writer.AddSourceLocation(MSInfo->getPointOfInstantiation(), Record);
+ } else {
+ Record.push_back(CXXRecNotTemplate);
+ }
+
+ // Store the key function to avoid deserializing every method so we can
+ // compute it.
+ if (D->IsDefinition)
+ Writer.AddDeclRef(Context.getKeyFunction(D), Record);
+
+ Code = serialization::DECL_CXX_RECORD;
+}
+
+void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ VisitFunctionDecl(D);
+ Record.push_back(D->size_overridden_methods());
+ for (CXXMethodDecl::method_iterator
+ I = D->begin_overridden_methods(), E = D->end_overridden_methods();
+ I != E; ++I)
+ Writer.AddDeclRef(*I, Record);
+ Code = serialization::DECL_CXX_METHOD;
+}
+
+void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ VisitCXXMethodDecl(D);
+
+ Record.push_back(D->IsExplicitSpecified);
+ Record.push_back(D->ImplicitlyDefined);
+ Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers,
+ Record);
+
+ Code = serialization::DECL_CXX_CONSTRUCTOR;
+}
+
+void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ VisitCXXMethodDecl(D);
+
+ Record.push_back(D->ImplicitlyDefined);
+ Writer.AddDeclRef(D->OperatorDelete, Record);
+
+ Code = serialization::DECL_CXX_DESTRUCTOR;
+}
+
+void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ VisitCXXMethodDecl(D);
+ Record.push_back(D->IsExplicitSpecified);
+ Code = serialization::DECL_CXX_CONVERSION;
+}
+
+void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
+ VisitDecl(D);
+ Writer.AddSourceLocation(D->getColonLoc(), Record);
+ Code = serialization::DECL_ACCESS_SPEC;
+}
+
+void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) {
+ VisitDecl(D);
+ Record.push_back(D->Friend.is<TypeSourceInfo*>());
+ if (D->Friend.is<TypeSourceInfo*>())
+ Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record);
+ else
+ Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
+ Writer.AddDeclRef(D->getNextFriend(), Record);
+ Record.push_back(D->UnsupportedFriend);
+ Writer.AddSourceLocation(D->FriendLoc, Record);
+ Code = serialization::DECL_FRIEND;
+}
+
+void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+ VisitDecl(D);
+ Record.push_back(D->getNumTemplateParameters());
+ for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i)
+ Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record);
+ Record.push_back(D->getFriendDecl() != 0);
+ if (D->getFriendDecl())
+ Writer.AddDeclRef(D->getFriendDecl(), Record);
+ else
+ Writer.AddTypeSourceInfo(D->getFriendType(), Record);
+ Writer.AddSourceLocation(D->getFriendLoc(), Record);
+ Code = serialization::DECL_FRIEND_TEMPLATE;
+}
+
+void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
+ VisitNamedDecl(D);
+
+ Writer.AddDeclRef(D->getTemplatedDecl(), Record);
+ Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
+}
+
+void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
+ // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
+ // getCommonPtr() can be used while this is still initializing.
+
+ Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ if (D->getPreviousDeclaration())
+ Writer.AddDeclRef(D->getFirstDeclaration(), Record);
+
+ if (D->getPreviousDeclaration() == 0) {
+ // This TemplateDecl owns the CommonPtr; write it.
+ assert(D->isCanonicalDecl());
+
+ Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
+ if (D->getInstantiatedFromMemberTemplate())
+ Record.push_back(D->isMemberSpecialization());
+
+ Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
+ } else {
+ RedeclarableTemplateDecl *First = D->getFirstDeclaration();
+ assert(First != D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during AST reading.
+ if (First->getMostRecentDeclaration() == D &&
+ First->getPCHLevel() > D->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = D;
+ }
+ }
+
+ VisitTemplateDecl(D);
+ Record.push_back(D->getIdentifierNamespace());
+}
+
+void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
+ typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
+ CTSDSetTy &CTSDSet = D->getSpecializations();
+ Record.push_back(CTSDSet.size());
+ for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) {
+ assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
+ Writer.AddDeclRef(&*I, Record);
+ }
+
+ typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> CTPSDSetTy;
+ CTPSDSetTy &CTPSDSet = D->getPartialSpecializations();
+ Record.push_back(CTPSDSet.size());
+ for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) {
+ assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
+ Writer.AddDeclRef(&*I, Record);
+ }
+
+ // InjectedClassNameType is computed, no need to write it.
+ }
+ Code = serialization::DECL_CLASS_TEMPLATE;
+}
+
+void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ VisitCXXRecordDecl(D);
+
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> InstFrom
+ = D->getSpecializedTemplateOrPartial();
+ Decl *InstFromD;
+ if (InstFrom.is<ClassTemplateDecl *>()) {
+ InstFromD = InstFrom.get<ClassTemplateDecl *>();
+ Writer.AddDeclRef(InstFromD, Record);
+ } else {
+ InstFromD = InstFrom.get<ClassTemplatePartialSpecializationDecl *>();
+ Writer.AddDeclRef(InstFromD, Record);
+ Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record);
+ InstFromD = cast<ClassTemplatePartialSpecializationDecl>(InstFromD)->
+ getSpecializedTemplate();
+ }
+
+ // Explicit info.
+ Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record);
+ if (D->getTypeAsWritten()) {
+ Writer.AddSourceLocation(D->getExternLoc(), Record);
+ Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record);
+ }
+
+ Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record);
+ Writer.AddSourceLocation(D->getPointOfInstantiation(), Record);
+ Record.push_back(D->getSpecializationKind());
+
+ if (D->isCanonicalDecl()) {
+ // When reading, we'll add it to the folding set of the following template.
+ Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record);
+ }
+
+ Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION;
+}
+
+void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ VisitClassTemplateSpecializationDecl(D);
+
+ Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
+
+ Record.push_back(D->getNumTemplateArgsAsWritten());
+ for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i)
+ Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record);
+
+ Record.push_back(D->getSequenceNumber());
+
+ // These are read/set from/to the first declaration.
+ if (D->getPreviousDeclaration() == 0) {
+ Writer.AddDeclRef(D->getInstantiatedFromMember(), Record);
+ Record.push_back(D->isMemberSpecialization());
+ }
+
+ Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
+}
+
+void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
+ // This FunctionTemplateDecl owns the CommonPtr; write it.
+
+ // Write the function specialization declarations.
+ Record.push_back(D->getSpecializations().size());
+ for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
+ I = D->getSpecializations().begin(),
+ E = D->getSpecializations().end() ; I != E; ++I) {
+ assert(I->Function->isCanonicalDecl() &&
+ "Expected only canonical decls in set");
+ Writer.AddDeclRef(I->Function, Record);
+ }
+ }
+ Code = serialization::DECL_FUNCTION_TEMPLATE;
+}
+
+void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ VisitTypeDecl(D);
+
+ Record.push_back(D->wasDeclaredWithTypename());
+ Record.push_back(D->isParameterPack());
+ Record.push_back(D->defaultArgumentWasInherited());
+ Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
+
+ Code = serialization::DECL_TEMPLATE_TYPE_PARM;
+}
+
+void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ // For an expanded parameter pack, record the number of expansion types here
+ // so that it's easier for
+ if (D->isExpandedParameterPack())
+ Record.push_back(D->getNumExpansionTypes());
+
+ VisitDeclaratorDecl(D);
+ // TemplateParmPosition.
+ Record.push_back(D->getDepth());
+ Record.push_back(D->getPosition());
+
+ if (D->isExpandedParameterPack()) {
+ for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
+ Writer.AddTypeRef(D->getExpansionType(I), Record);
+ Writer.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I), Record);
+ }
+
+ Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
+ } else {
+ // Rest of NonTypeTemplateParmDecl.
+ Record.push_back(D->isParameterPack());
+ Record.push_back(D->getDefaultArgument() != 0);
+ if (D->getDefaultArgument()) {
+ Writer.AddStmt(D->getDefaultArgument());
+ Record.push_back(D->defaultArgumentWasInherited());
+ }
+ Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
+ }
+}
+
+void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ VisitTemplateDecl(D);
+ // TemplateParmPosition.
+ Record.push_back(D->getDepth());
+ Record.push_back(D->getPosition());
+ // Rest of TemplateTemplateParmDecl.
+ Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
+ Record.push_back(D->defaultArgumentWasInherited());
+ Record.push_back(D->isParameterPack());
+ Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM;
+}
+
+void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ VisitDecl(D);
+ Writer.AddStmt(D->getAssertExpr());
+ Writer.AddStmt(D->getMessage());
+ Code = serialization::DECL_STATIC_ASSERT;
+}
+
+/// \brief Emit the DeclContext part of a declaration context decl.
+///
+/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations stored within this context.
+///
+/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
+/// block for this declaration context is stored. May be 0 to indicate
+/// that there are no declarations visible from this context. Note
+/// that this value will not be emitted for non-primary declaration
+/// contexts.
+void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+ uint64_t VisibleOffset) {
+ Record.push_back(LexicalOffset);
+ Record.push_back(VisibleOffset);
+}
+
+template <typename T>
+void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
+ enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ if (D->RedeclLink.getNext() == D) {
+ Record.push_back(NoRedeclaration);
+ } else {
+ if (D->RedeclLink.NextIsPrevious()) {
+ Record.push_back(PointsToPrevious);
+ Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ Writer.AddDeclRef(D->getFirstDeclaration(), Record);
+ } else {
+ Record.push_back(PointsToLatest);
+ Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
+ }
+ }
+
+ T *First = D->getFirstDeclaration();
+ T *ThisDecl = static_cast<T*>(D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during AST reading.
+ if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
+ First->getPCHLevel() > ThisDecl->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = ThisDecl;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ASTWriter Implementation
+//===----------------------------------------------------------------------===//
+
+void ASTWriter::WriteDeclsBlockAbbrevs() {
+ using namespace llvm;
+ // Abbreviation for DECL_PARM_VAR.
+ BitCodeAbbrev *Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
+
+ // Decl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
+ Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
+ Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
+ Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
+ Abv->Add(BitCodeAbbrevOp(0)); // isUsed
+ Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
+ Abv->Add(BitCodeAbbrevOp(0)); // PCH level
+
+ // NamedDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
+ // ValueDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
+ // DeclaratorDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
+ Abv->Add(BitCodeAbbrevOp(serialization::PREDEF_TYPE_NULL_ID)); // InfoType
+ // VarDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
+ Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
+ Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten
+ Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
+ Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
+ Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
+ Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable
+ Abv->Add(BitCodeAbbrevOp(0)); // HasInit
+ Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo
+ // ParmVarDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier
+ Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg
+ Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg
+
+ ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
+
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv);
+
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(Abv);
+}
+
+/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
+/// consumers of the AST.
+///
+/// Such decls will always be deserialized from the AST file, so we would like
+/// this to be as restrictive as possible. Currently the predicate is driven by
+/// code generation requirements, if other clients have a different notion of
+/// what is "required" then we may have to consider an alternate scheme where
+/// clients can iterate over the top-level decls and get information on them,
+/// without necessary deserializing them. We could explicitly require such
+/// clients to use a separate API call to "realize" the decl. This should be
+/// relatively painless since they would presumably only do it for top-level
+/// decls.
+static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
+ // File scoped assembly or obj-c implementation must be seen.
+ if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D))
+ return true;
+
+ return Context.DeclMustBeEmitted(D);
+}
+
+void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
+ // Switch case IDs are per Decl.
+ ClearSwitchCaseIDs();
+
+ RecordData Record;
+ ASTDeclWriter W(*this, Context, Record);
+
+ // If this declaration is also a DeclContext, write blocks for the
+ // declarations that lexically stored inside its context and those
+ // declarations that are visible from its context. These blocks
+ // are written before the declaration itself so that we can put
+ // their offsets into the record for the declaration.
+ uint64_t LexicalOffset = 0;
+ uint64_t VisibleOffset = 0;
+ DeclContext *DC = dyn_cast<DeclContext>(D);
+ if (DC) {
+ LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
+ VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
+ }
+
+ // Determine the ID for this declaration
+ serialization::DeclID &IDR = DeclIDs[D];
+ if (IDR == 0)
+ IDR = NextDeclID++;
+ serialization::DeclID ID = IDR;
+
+ if (ID < FirstDeclID) {
+ // We're replacing a decl in a previous file.
+ ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo()));
+ } else {
+ unsigned Index = ID - FirstDeclID;
+
+ // Record the offset for this declaration
+ if (DeclOffsets.size() == Index)
+ DeclOffsets.push_back(Stream.GetCurrentBitNo());
+ else if (DeclOffsets.size() < Index) {
+ DeclOffsets.resize(Index+1);
+ DeclOffsets[Index] = Stream.GetCurrentBitNo();
+ }
+ }
+
+ // Build and emit a record for this declaration
+ Record.clear();
+ W.Code = (serialization::DeclCode)0;
+ W.AbbrevToUse = 0;
+ W.Visit(D);
+ if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
+ if (!W.Code)
+ llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") +
+ D->getDeclKindName() + "'");
+ Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
+
+ // Flush any expressions that were written as part of this declaration.
+ FlushStmts();
+
+ // Flush C++ base specifiers, if there are any.
+ FlushCXXBaseSpecifiers();
+
+ // Note "external" declarations so that we can add them to a record in the
+ // AST file later.
+ //
+ // FIXME: This should be renamed, the predicate is much more complicated.
+ if (isRequiredDecl(D, Context))
+ ExternalDefinitions.push_back(ID);
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
new file mode 100644
index 0000000..8a5ffe9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -0,0 +1,1438 @@
+//===--- ASTWriterStmt.cpp - Statement and Expression Serialization -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements serialization for Statements and Expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Statement/expression serialization
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> {
+ ASTWriter &Writer;
+ ASTWriter::RecordData &Record;
+
+ public:
+ serialization::StmtCode Code;
+
+ ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record)
+ : Writer(Writer), Record(Record) { }
+
+ void
+ AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args);
+
+ void VisitStmt(Stmt *S);
+ void VisitNullStmt(NullStmt *S);
+ void VisitCompoundStmt(CompoundStmt *S);
+ void VisitSwitchCase(SwitchCase *S);
+ void VisitCaseStmt(CaseStmt *S);
+ void VisitDefaultStmt(DefaultStmt *S);
+ void VisitLabelStmt(LabelStmt *S);
+ void VisitIfStmt(IfStmt *S);
+ void VisitSwitchStmt(SwitchStmt *S);
+ void VisitWhileStmt(WhileStmt *S);
+ void VisitDoStmt(DoStmt *S);
+ void VisitForStmt(ForStmt *S);
+ void VisitGotoStmt(GotoStmt *S);
+ void VisitIndirectGotoStmt(IndirectGotoStmt *S);
+ void VisitContinueStmt(ContinueStmt *S);
+ void VisitBreakStmt(BreakStmt *S);
+ void VisitReturnStmt(ReturnStmt *S);
+ void VisitDeclStmt(DeclStmt *S);
+ void VisitAsmStmt(AsmStmt *S);
+ void VisitExpr(Expr *E);
+ void VisitPredefinedExpr(PredefinedExpr *E);
+ void VisitDeclRefExpr(DeclRefExpr *E);
+ void VisitIntegerLiteral(IntegerLiteral *E);
+ void VisitFloatingLiteral(FloatingLiteral *E);
+ void VisitImaginaryLiteral(ImaginaryLiteral *E);
+ void VisitStringLiteral(StringLiteral *E);
+ void VisitCharacterLiteral(CharacterLiteral *E);
+ void VisitParenExpr(ParenExpr *E);
+ void VisitParenListExpr(ParenListExpr *E);
+ void VisitUnaryOperator(UnaryOperator *E);
+ void VisitOffsetOfExpr(OffsetOfExpr *E);
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+ void VisitCallExpr(CallExpr *E);
+ void VisitMemberExpr(MemberExpr *E);
+ void VisitCastExpr(CastExpr *E);
+ void VisitBinaryOperator(BinaryOperator *E);
+ void VisitCompoundAssignOperator(CompoundAssignOperator *E);
+ void VisitConditionalOperator(ConditionalOperator *E);
+ void VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
+ void VisitImplicitCastExpr(ImplicitCastExpr *E);
+ void VisitExplicitCastExpr(ExplicitCastExpr *E);
+ void VisitCStyleCastExpr(CStyleCastExpr *E);
+ void VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ void VisitExtVectorElementExpr(ExtVectorElementExpr *E);
+ void VisitInitListExpr(InitListExpr *E);
+ void VisitDesignatedInitExpr(DesignatedInitExpr *E);
+ void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+ void VisitVAArgExpr(VAArgExpr *E);
+ void VisitAddrLabelExpr(AddrLabelExpr *E);
+ void VisitStmtExpr(StmtExpr *E);
+ void VisitChooseExpr(ChooseExpr *E);
+ void VisitGNUNullExpr(GNUNullExpr *E);
+ void VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+ void VisitBlockExpr(BlockExpr *E);
+ void VisitBlockDeclRefExpr(BlockDeclRefExpr *E);
+
+ // Objective-C Expressions
+ void VisitObjCStringLiteral(ObjCStringLiteral *E);
+ void VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+ void VisitObjCSelectorExpr(ObjCSelectorExpr *E);
+ void VisitObjCProtocolExpr(ObjCProtocolExpr *E);
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E);
+ void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E);
+ void VisitObjCMessageExpr(ObjCMessageExpr *E);
+ void VisitObjCIsaExpr(ObjCIsaExpr *E);
+
+ // Objective-C Statements
+ void VisitObjCForCollectionStmt(ObjCForCollectionStmt *);
+ void VisitObjCAtCatchStmt(ObjCAtCatchStmt *);
+ void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *);
+ void VisitObjCAtTryStmt(ObjCAtTryStmt *);
+ void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
+ void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
+
+ // C++ Statements
+ void VisitCXXCatchStmt(CXXCatchStmt *S);
+ void VisitCXXTryStmt(CXXTryStmt *S);
+
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ void VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ void VisitCXXConstructExpr(CXXConstructExpr *E);
+ void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+ void VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
+ void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
+ void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
+ void VisitCXXConstCastExpr(CXXConstCastExpr *E);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
+ void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
+ void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+ void VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ void VisitCXXUuidofExpr(CXXUuidofExpr *E);
+ void VisitCXXThisExpr(CXXThisExpr *E);
+ void VisitCXXThrowExpr(CXXThrowExpr *E);
+ void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+
+ void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ void VisitCXXNewExpr(CXXNewExpr *E);
+ void VisitCXXDeleteExpr(CXXDeleteExpr *E);
+ void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+
+ void VisitExprWithCleanups(ExprWithCleanups *E);
+ void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
+
+ void VisitOverloadExpr(OverloadExpr *E);
+ void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
+ void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+
+ void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+ void VisitPackExpansionExpr(PackExpansionExpr *E);
+ void VisitSizeOfPackExpr(SizeOfPackExpr *E);
+ void VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E);
+ void VisitOpaqueValueExpr(OpaqueValueExpr *E);
+
+ // CUDA Expressions
+ void VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E);
+ };
+}
+
+void ASTStmtWriter::
+AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) {
+ Writer.AddSourceLocation(Args.LAngleLoc, Record);
+ Writer.AddSourceLocation(Args.RAngleLoc, Record);
+ for (unsigned i=0; i != Args.NumTemplateArgs; ++i)
+ Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record);
+}
+
+void ASTStmtWriter::VisitStmt(Stmt *S) {
+}
+
+void ASTStmtWriter::VisitNullStmt(NullStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getSemiLoc(), Record);
+ Record.push_back(S->LeadingEmptyMacro);
+ Code = serialization::STMT_NULL;
+}
+
+void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
+ VisitStmt(S);
+ Record.push_back(S->size());
+ for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
+ CS != CSEnd; ++CS)
+ Writer.AddStmt(*CS);
+ Writer.AddSourceLocation(S->getLBracLoc(), Record);
+ Writer.AddSourceLocation(S->getRBracLoc(), Record);
+ Code = serialization::STMT_COMPOUND;
+}
+
+void ASTStmtWriter::VisitSwitchCase(SwitchCase *S) {
+ VisitStmt(S);
+ Record.push_back(Writer.getSwitchCaseID(S));
+}
+
+void ASTStmtWriter::VisitCaseStmt(CaseStmt *S) {
+ VisitSwitchCase(S);
+ Writer.AddStmt(S->getLHS());
+ Writer.AddStmt(S->getRHS());
+ Writer.AddStmt(S->getSubStmt());
+ Writer.AddSourceLocation(S->getCaseLoc(), Record);
+ Writer.AddSourceLocation(S->getEllipsisLoc(), Record);
+ Writer.AddSourceLocation(S->getColonLoc(), Record);
+ Code = serialization::STMT_CASE;
+}
+
+void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
+ VisitSwitchCase(S);
+ Writer.AddStmt(S->getSubStmt());
+ Writer.AddSourceLocation(S->getDefaultLoc(), Record);
+ Writer.AddSourceLocation(S->getColonLoc(), Record);
+ Code = serialization::STMT_DEFAULT;
+}
+
+void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
+ VisitStmt(S);
+ Writer.AddDeclRef(S->getDecl(), Record);
+ Writer.AddStmt(S->getSubStmt());
+ Writer.AddSourceLocation(S->getIdentLoc(), Record);
+ Code = serialization::STMT_LABEL;
+}
+
+void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
+ VisitStmt(S);
+ Writer.AddDeclRef(S->getConditionVariable(), Record);
+ Writer.AddStmt(S->getCond());
+ Writer.AddStmt(S->getThen());
+ Writer.AddStmt(S->getElse());
+ Writer.AddSourceLocation(S->getIfLoc(), Record);
+ Writer.AddSourceLocation(S->getElseLoc(), Record);
+ Code = serialization::STMT_IF;
+}
+
+void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
+ VisitStmt(S);
+ Writer.AddDeclRef(S->getConditionVariable(), Record);
+ Writer.AddStmt(S->getCond());
+ Writer.AddStmt(S->getBody());
+ Writer.AddSourceLocation(S->getSwitchLoc(), Record);
+ Record.push_back(S->isAllEnumCasesCovered());
+ for (SwitchCase *SC = S->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase())
+ Record.push_back(Writer.RecordSwitchCaseID(SC));
+ Code = serialization::STMT_SWITCH;
+}
+
+void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) {
+ VisitStmt(S);
+ Writer.AddDeclRef(S->getConditionVariable(), Record);
+ Writer.AddStmt(S->getCond());
+ Writer.AddStmt(S->getBody());
+ Writer.AddSourceLocation(S->getWhileLoc(), Record);
+ Code = serialization::STMT_WHILE;
+}
+
+void ASTStmtWriter::VisitDoStmt(DoStmt *S) {
+ VisitStmt(S);
+ Writer.AddStmt(S->getCond());
+ Writer.AddStmt(S->getBody());
+ Writer.AddSourceLocation(S->getDoLoc(), Record);
+ Writer.AddSourceLocation(S->getWhileLoc(), Record);
+ Writer.AddSourceLocation(S->getRParenLoc(), Record);
+ Code = serialization::STMT_DO;
+}
+
+void ASTStmtWriter::VisitForStmt(ForStmt *S) {
+ VisitStmt(S);
+ Writer.AddStmt(S->getInit());
+ Writer.AddStmt(S->getCond());
+ Writer.AddDeclRef(S->getConditionVariable(), Record);
+ Writer.AddStmt(S->getInc());
+ Writer.AddStmt(S->getBody());
+ Writer.AddSourceLocation(S->getForLoc(), Record);
+ Writer.AddSourceLocation(S->getLParenLoc(), Record);
+ Writer.AddSourceLocation(S->getRParenLoc(), Record);
+ Code = serialization::STMT_FOR;
+}
+
+void ASTStmtWriter::VisitGotoStmt(GotoStmt *S) {
+ VisitStmt(S);
+ Writer.AddDeclRef(S->getLabel(), Record);
+ Writer.AddSourceLocation(S->getGotoLoc(), Record);
+ Writer.AddSourceLocation(S->getLabelLoc(), Record);
+ Code = serialization::STMT_GOTO;
+}
+
+void ASTStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getGotoLoc(), Record);
+ Writer.AddSourceLocation(S->getStarLoc(), Record);
+ Writer.AddStmt(S->getTarget());
+ Code = serialization::STMT_INDIRECT_GOTO;
+}
+
+void ASTStmtWriter::VisitContinueStmt(ContinueStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getContinueLoc(), Record);
+ Code = serialization::STMT_CONTINUE;
+}
+
+void ASTStmtWriter::VisitBreakStmt(BreakStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getBreakLoc(), Record);
+ Code = serialization::STMT_BREAK;
+}
+
+void ASTStmtWriter::VisitReturnStmt(ReturnStmt *S) {
+ VisitStmt(S);
+ Writer.AddStmt(S->getRetValue());
+ Writer.AddSourceLocation(S->getReturnLoc(), Record);
+ Writer.AddDeclRef(S->getNRVOCandidate(), Record);
+ Code = serialization::STMT_RETURN;
+}
+
+void ASTStmtWriter::VisitDeclStmt(DeclStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getStartLoc(), Record);
+ Writer.AddSourceLocation(S->getEndLoc(), Record);
+ DeclGroupRef DG = S->getDeclGroup();
+ for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
+ Writer.AddDeclRef(*D, Record);
+ Code = serialization::STMT_DECL;
+}
+
+void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) {
+ VisitStmt(S);
+ Record.push_back(S->getNumOutputs());
+ Record.push_back(S->getNumInputs());
+ Record.push_back(S->getNumClobbers());
+ Writer.AddSourceLocation(S->getAsmLoc(), Record);
+ Writer.AddSourceLocation(S->getRParenLoc(), Record);
+ Record.push_back(S->isVolatile());
+ Record.push_back(S->isSimple());
+ Record.push_back(S->isMSAsm());
+ Writer.AddStmt(S->getAsmString());
+
+ // Outputs
+ for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
+ Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record);
+ Writer.AddStmt(S->getOutputConstraintLiteral(I));
+ Writer.AddStmt(S->getOutputExpr(I));
+ }
+
+ // Inputs
+ for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
+ Writer.AddIdentifierRef(S->getInputIdentifier(I), Record);
+ Writer.AddStmt(S->getInputConstraintLiteral(I));
+ Writer.AddStmt(S->getInputExpr(I));
+ }
+
+ // Clobbers
+ for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
+ Writer.AddStmt(S->getClobber(I));
+
+ Code = serialization::STMT_ASM;
+}
+
+void ASTStmtWriter::VisitExpr(Expr *E) {
+ VisitStmt(E);
+ Writer.AddTypeRef(E->getType(), Record);
+ Record.push_back(E->isTypeDependent());
+ Record.push_back(E->isValueDependent());
+ Record.push_back(E->containsUnexpandedParameterPack());
+ Record.push_back(E->getValueKind());
+ Record.push_back(E->getObjectKind());
+}
+
+void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Record.push_back(E->getIdentType()); // FIXME: stable encoding
+ Code = serialization::EXPR_PREDEFINED;
+}
+
+void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
+ VisitExpr(E);
+
+ Record.push_back(E->hasQualifier());
+ Record.push_back(E->hasExplicitTemplateArgs());
+
+ if (E->hasQualifier()) {
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+ }
+
+ if (E->hasExplicitTemplateArgs()) {
+ unsigned NumTemplateArgs = E->getNumTemplateArgs();
+ Record.push_back(NumTemplateArgs);
+ AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs());
+ }
+
+ Writer.AddDeclRef(E->getDecl(), Record);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Writer.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record);
+ Code = serialization::EXPR_DECL_REF;
+}
+
+void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Writer.AddAPInt(E->getValue(), Record);
+ Code = serialization::EXPR_INTEGER_LITERAL;
+}
+
+void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
+ VisitExpr(E);
+ Writer.AddAPFloat(E->getValue(), Record);
+ Record.push_back(E->isExact());
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Code = serialization::EXPR_FLOATING_LITERAL;
+}
+
+void ASTStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_IMAGINARY_LITERAL;
+}
+
+void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) {
+ VisitExpr(E);
+ Record.push_back(E->getByteLength());
+ Record.push_back(E->getNumConcatenated());
+ Record.push_back(E->isWide());
+ // FIXME: String data should be stored as a blob at the end of the
+ // StringLiteral. However, we can't do so now because we have no
+ // provision for coping with abbreviations when we're jumping around
+ // the AST file during deserialization.
+ Record.append(E->getString().begin(), E->getString().end());
+ for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
+ Writer.AddSourceLocation(E->getStrTokenLoc(I), Record);
+ Code = serialization::EXPR_STRING_LITERAL;
+}
+
+void ASTStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
+ VisitExpr(E);
+ Record.push_back(E->getValue());
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Record.push_back(E->isWide());
+ Code = serialization::EXPR_CHARACTER_LITERAL;
+}
+
+void ASTStmtWriter::VisitParenExpr(ParenExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLParen(), Record);
+ Writer.AddSourceLocation(E->getRParen(), Record);
+ Writer.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_PAREN;
+}
+
+void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->NumExprs);
+ for (unsigned i=0; i != E->NumExprs; ++i)
+ Writer.AddStmt(E->Exprs[i]);
+ Writer.AddSourceLocation(E->LParenLoc, Record);
+ Writer.AddSourceLocation(E->RParenLoc, Record);
+ Code = serialization::EXPR_PAREN_LIST;
+}
+
+void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getSubExpr());
+ Record.push_back(E->getOpcode()); // FIXME: stable encoding
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Code = serialization::EXPR_UNARY_OPERATOR;
+}
+
+void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumComponents());
+ Record.push_back(E->getNumExpressions());
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+ for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
+ const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I);
+ Record.push_back(ON.getKind()); // FIXME: Stable encoding
+ Writer.AddSourceLocation(ON.getRange().getBegin(), Record);
+ Writer.AddSourceLocation(ON.getRange().getEnd(), Record);
+ switch (ON.getKind()) {
+ case OffsetOfExpr::OffsetOfNode::Array:
+ Record.push_back(ON.getArrayExprIndex());
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Field:
+ Writer.AddDeclRef(ON.getField(), Record);
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Identifier:
+ Writer.AddIdentifierRef(ON.getFieldName(), Record);
+ break;
+
+ case OffsetOfExpr::OffsetOfNode::Base:
+ Writer.AddCXXBaseSpecifier(*ON.getBase(), Record);
+ break;
+ }
+ }
+ for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
+ Writer.AddStmt(E->getIndexExpr(I));
+ Code = serialization::EXPR_OFFSETOF;
+}
+
+void ASTStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->isSizeOf());
+ if (E->isArgumentType())
+ Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record);
+ else {
+ Record.push_back(0);
+ Writer.AddStmt(E->getArgumentExpr());
+ }
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_SIZEOF_ALIGN_OF;
+}
+
+void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getLHS());
+ Writer.AddStmt(E->getRHS());
+ Writer.AddSourceLocation(E->getRBracketLoc(), Record);
+ Code = serialization::EXPR_ARRAY_SUBSCRIPT;
+}
+
+void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumArgs());
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Writer.AddStmt(E->getCallee());
+ for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg)
+ Writer.AddStmt(*Arg);
+ Code = serialization::EXPR_CALL;
+}
+
+void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
+ // Don't call VisitExpr, we'll write everything here.
+
+ Record.push_back(E->hasQualifier());
+ if (E->hasQualifier()) {
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+ }
+
+ Record.push_back(E->hasExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs()) {
+ unsigned NumTemplateArgs = E->getNumTemplateArgs();
+ Record.push_back(NumTemplateArgs);
+ Writer.AddSourceLocation(E->getLAngleLoc(), Record);
+ Writer.AddSourceLocation(E->getRAngleLoc(), Record);
+ for (unsigned i=0; i != NumTemplateArgs; ++i)
+ Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record);
+ }
+
+ DeclAccessPair FoundDecl = E->getFoundDecl();
+ Writer.AddDeclRef(FoundDecl.getDecl(), Record);
+ Record.push_back(FoundDecl.getAccess());
+
+ Writer.AddTypeRef(E->getType(), Record);
+ Record.push_back(E->getValueKind());
+ Record.push_back(E->getObjectKind());
+ Writer.AddStmt(E->getBase());
+ Writer.AddDeclRef(E->getMemberDecl(), Record);
+ Writer.AddSourceLocation(E->getMemberLoc(), Record);
+ Record.push_back(E->isArrow());
+ Writer.AddDeclarationNameLoc(E->MemberDNLoc,
+ E->getMemberDecl()->getDeclName(), Record);
+ Code = serialization::EXPR_MEMBER;
+}
+
+void ASTStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getBase());
+ Writer.AddSourceLocation(E->getIsaMemberLoc(), Record);
+ Record.push_back(E->isArrow());
+ Code = serialization::EXPR_OBJC_ISA;
+}
+
+void ASTStmtWriter::VisitCastExpr(CastExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->path_size());
+ Writer.AddStmt(E->getSubExpr());
+ Record.push_back(E->getCastKind()); // FIXME: stable encoding
+
+ for (CastExpr::path_iterator
+ PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI)
+ Writer.AddCXXBaseSpecifier(**PI, Record);
+}
+
+void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getLHS());
+ Writer.AddStmt(E->getRHS());
+ Record.push_back(E->getOpcode()); // FIXME: stable encoding
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Code = serialization::EXPR_BINARY_OPERATOR;
+}
+
+void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+ VisitBinaryOperator(E);
+ Writer.AddTypeRef(E->getComputationLHSType(), Record);
+ Writer.AddTypeRef(E->getComputationResultType(), Record);
+ Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR;
+}
+
+void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getCond());
+ Writer.AddStmt(E->getLHS());
+ Writer.AddStmt(E->getRHS());
+ Writer.AddSourceLocation(E->getQuestionLoc(), Record);
+ Writer.AddSourceLocation(E->getColonLoc(), Record);
+ Code = serialization::EXPR_CONDITIONAL_OPERATOR;
+}
+
+void
+ASTStmtWriter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getOpaqueValue());
+ Writer.AddStmt(E->getCommon());
+ Writer.AddStmt(E->getCond());
+ Writer.AddStmt(E->getTrueExpr());
+ Writer.AddStmt(E->getFalseExpr());
+ Writer.AddSourceLocation(E->getQuestionLoc(), Record);
+ Writer.AddSourceLocation(E->getColonLoc(), Record);
+ Code = serialization::EXPR_BINARY_CONDITIONAL_OPERATOR;
+}
+
+void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+ VisitCastExpr(E);
+ Code = serialization::EXPR_IMPLICIT_CAST;
+}
+
+void ASTStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ VisitCastExpr(E);
+ Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
+}
+
+void ASTStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ Writer.AddSourceLocation(E->getLParenLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_CSTYLE_CAST;
+}
+
+void ASTStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLParenLoc(), Record);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+ Writer.AddStmt(E->getInitializer());
+ Record.push_back(E->isFileScope());
+ Code = serialization::EXPR_COMPOUND_LITERAL;
+}
+
+void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getBase());
+ Writer.AddIdentifierRef(&E->getAccessor(), Record);
+ Writer.AddSourceLocation(E->getAccessorLoc(), Record);
+ Code = serialization::EXPR_EXT_VECTOR_ELEMENT;
+}
+
+void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumInits());
+ for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
+ Writer.AddStmt(E->getInit(I));
+ Writer.AddStmt(E->getSyntacticForm());
+ Writer.AddSourceLocation(E->getLBraceLoc(), Record);
+ Writer.AddSourceLocation(E->getRBraceLoc(), Record);
+ Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
+ Record.push_back(E->hadArrayRangeDesignator());
+ Code = serialization::EXPR_INIT_LIST;
+}
+
+void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumSubExprs());
+ for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
+ Writer.AddStmt(E->getSubExpr(I));
+ Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record);
+ Record.push_back(E->usesGNUSyntax());
+ for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+ DEnd = E->designators_end();
+ D != DEnd; ++D) {
+ if (D->isFieldDesignator()) {
+ if (FieldDecl *Field = D->getField()) {
+ Record.push_back(serialization::DESIG_FIELD_DECL);
+ Writer.AddDeclRef(Field, Record);
+ } else {
+ Record.push_back(serialization::DESIG_FIELD_NAME);
+ Writer.AddIdentifierRef(D->getFieldName(), Record);
+ }
+ Writer.AddSourceLocation(D->getDotLoc(), Record);
+ Writer.AddSourceLocation(D->getFieldLoc(), Record);
+ } else if (D->isArrayDesignator()) {
+ Record.push_back(serialization::DESIG_ARRAY);
+ Record.push_back(D->getFirstExprIndex());
+ Writer.AddSourceLocation(D->getLBracketLoc(), Record);
+ Writer.AddSourceLocation(D->getRBracketLoc(), Record);
+ } else {
+ assert(D->isArrayRangeDesignator() && "Unknown designator");
+ Record.push_back(serialization::DESIG_ARRAY_RANGE);
+ Record.push_back(D->getFirstExprIndex());
+ Writer.AddSourceLocation(D->getLBracketLoc(), Record);
+ Writer.AddSourceLocation(D->getEllipsisLoc(), Record);
+ Writer.AddSourceLocation(D->getRBracketLoc(), Record);
+ }
+ }
+ Code = serialization::EXPR_DESIGNATED_INIT;
+}
+
+void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+ VisitExpr(E);
+ Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
+}
+
+void ASTStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getSubExpr());
+ Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record);
+ Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_VA_ARG;
+}
+
+void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
+ Writer.AddSourceLocation(E->getLabelLoc(), Record);
+ Writer.AddDeclRef(E->getLabel(), Record);
+ Code = serialization::EXPR_ADDR_LABEL;
+}
+
+void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getSubStmt());
+ Writer.AddSourceLocation(E->getLParenLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_STMT;
+}
+
+void ASTStmtWriter::VisitChooseExpr(ChooseExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getCond());
+ Writer.AddStmt(E->getLHS());
+ Writer.AddStmt(E->getRHS());
+ Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_CHOOSE;
+}
+
+void ASTStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getTokenLocation(), Record);
+ Code = serialization::EXPR_GNU_NULL;
+}
+
+void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumSubExprs());
+ for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
+ Writer.AddStmt(E->getExpr(I));
+ Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_SHUFFLE_VECTOR;
+}
+
+void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->getBlockDecl(), Record);
+ Code = serialization::EXPR_BLOCK;
+}
+
+void ASTStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->getDecl(), Record);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Record.push_back(E->isByRef());
+ Record.push_back(E->isConstQualAdded());
+ Code = serialization::EXPR_BLOCK_DECL_REF;
+}
+
+//===----------------------------------------------------------------------===//
+// Objective-C Expressions and Statements.
+//===----------------------------------------------------------------------===//
+
+void ASTStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getString());
+ Writer.AddSourceLocation(E->getAtLoc(), Record);
+ Code = serialization::EXPR_OBJC_STRING_LITERAL;
+}
+
+void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ VisitExpr(E);
+ Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record);
+ Writer.AddSourceLocation(E->getAtLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_OBJC_ENCODE;
+}
+
+void ASTStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+ VisitExpr(E);
+ Writer.AddSelectorRef(E->getSelector(), Record);
+ Writer.AddSourceLocation(E->getAtLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_OBJC_SELECTOR_EXPR;
+}
+
+void ASTStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->getProtocol(), Record);
+ Writer.AddSourceLocation(E->getAtLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_OBJC_PROTOCOL_EXPR;
+}
+
+void ASTStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->getDecl(), Record);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Writer.AddStmt(E->getBase());
+ Record.push_back(E->isArrow());
+ Record.push_back(E->isFreeIvar());
+ Code = serialization::EXPR_OBJC_IVAR_REF_EXPR;
+}
+
+void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->isImplicitProperty());
+ if (E->isImplicitProperty()) {
+ Writer.AddDeclRef(E->getImplicitPropertyGetter(), Record);
+ Writer.AddDeclRef(E->getImplicitPropertySetter(), Record);
+ } else {
+ Writer.AddDeclRef(E->getExplicitProperty(), Record);
+ }
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Writer.AddSourceLocation(E->getReceiverLocation(), Record);
+ if (E->isObjectReceiver()) {
+ Record.push_back(0);
+ Writer.AddStmt(E->getBase());
+ } else if (E->isSuperReceiver()) {
+ Record.push_back(1);
+ Writer.AddTypeRef(E->getSuperReceiverType(), Record);
+ } else {
+ Record.push_back(2);
+ Writer.AddDeclRef(E->getClassReceiver(), Record);
+ }
+
+ Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR;
+}
+
+void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumArgs());
+ Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding
+ switch (E->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ Writer.AddStmt(E->getInstanceReceiver());
+ break;
+
+ case ObjCMessageExpr::Class:
+ Writer.AddTypeSourceInfo(E->getClassReceiverTypeInfo(), Record);
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ case ObjCMessageExpr::SuperInstance:
+ Writer.AddTypeRef(E->getSuperType(), Record);
+ Writer.AddSourceLocation(E->getSuperLoc(), Record);
+ break;
+ }
+
+ if (E->getMethodDecl()) {
+ Record.push_back(1);
+ Writer.AddDeclRef(E->getMethodDecl(), Record);
+ } else {
+ Record.push_back(0);
+ Writer.AddSelectorRef(E->getSelector(), Record);
+ }
+
+ Writer.AddSourceLocation(E->getLeftLoc(), Record);
+ Writer.AddSourceLocation(E->getRightLoc(), Record);
+ Writer.AddSourceLocation(E->getSelectorLoc(), Record);
+
+ for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg)
+ Writer.AddStmt(*Arg);
+ Code = serialization::EXPR_OBJC_MESSAGE_EXPR;
+}
+
+void ASTStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+ VisitStmt(S);
+ Writer.AddStmt(S->getElement());
+ Writer.AddStmt(S->getCollection());
+ Writer.AddStmt(S->getBody());
+ Writer.AddSourceLocation(S->getForLoc(), Record);
+ Writer.AddSourceLocation(S->getRParenLoc(), Record);
+ Code = serialization::STMT_OBJC_FOR_COLLECTION;
+}
+
+void ASTStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+ Writer.AddStmt(S->getCatchBody());
+ Writer.AddDeclRef(S->getCatchParamDecl(), Record);
+ Writer.AddSourceLocation(S->getAtCatchLoc(), Record);
+ Writer.AddSourceLocation(S->getRParenLoc(), Record);
+ Code = serialization::STMT_OBJC_CATCH;
+}
+
+void ASTStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+ Writer.AddStmt(S->getFinallyBody());
+ Writer.AddSourceLocation(S->getAtFinallyLoc(), Record);
+ Code = serialization::STMT_OBJC_FINALLY;
+}
+
+void ASTStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+ Record.push_back(S->getNumCatchStmts());
+ Record.push_back(S->getFinallyStmt() != 0);
+ Writer.AddStmt(S->getTryBody());
+ for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
+ Writer.AddStmt(S->getCatchStmt(I));
+ if (S->getFinallyStmt())
+ Writer.AddStmt(S->getFinallyStmt());
+ Writer.AddSourceLocation(S->getAtTryLoc(), Record);
+ Code = serialization::STMT_OBJC_AT_TRY;
+}
+
+void ASTStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+ Writer.AddStmt(S->getSynchExpr());
+ Writer.AddStmt(S->getSynchBody());
+ Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record);
+ Code = serialization::STMT_OBJC_AT_SYNCHRONIZED;
+}
+
+void ASTStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+ Writer.AddStmt(S->getThrowExpr());
+ Writer.AddSourceLocation(S->getThrowLoc(), Record);
+ Code = serialization::STMT_OBJC_AT_THROW;
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions and Statements.
+//===----------------------------------------------------------------------===//
+
+void ASTStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getCatchLoc(), Record);
+ Writer.AddDeclRef(S->getExceptionDecl(), Record);
+ Writer.AddStmt(S->getHandlerBlock());
+ Code = serialization::STMT_CXX_CATCH;
+}
+
+void ASTStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) {
+ VisitStmt(S);
+ Record.push_back(S->getNumHandlers());
+ Writer.AddSourceLocation(S->getTryLoc(), Record);
+ Writer.AddStmt(S->getTryBlock());
+ for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
+ Writer.AddStmt(S->getHandler(i));
+ Code = serialization::STMT_CXX_TRY;
+}
+
+void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ VisitCallExpr(E);
+ Record.push_back(E->getOperator());
+ Code = serialization::EXPR_CXX_OPERATOR_CALL;
+}
+
+void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+ VisitCallExpr(E);
+ Code = serialization::EXPR_CXX_MEMBER_CALL;
+}
+
+void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumArgs());
+ for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ Writer.AddStmt(E->getArg(I));
+ Writer.AddDeclRef(E->getConstructor(), Record);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Record.push_back(E->isElidable());
+ Record.push_back(E->requiresZeroInitialization());
+ Record.push_back(E->getConstructionKind()); // FIXME: stable encoding
+ Writer.AddSourceRange(E->getParenRange(), Record);
+ Code = serialization::EXPR_CXX_CONSTRUCT;
+}
+
+void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+ VisitCXXConstructExpr(E);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+ Code = serialization::EXPR_CXX_TEMPORARY_OBJECT;
+}
+
+void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()),
+ Record);
+}
+
+void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = serialization::EXPR_CXX_STATIC_CAST;
+}
+
+void ASTStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = serialization::EXPR_CXX_DYNAMIC_CAST;
+}
+
+void ASTStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = serialization::EXPR_CXX_REINTERPRET_CAST;
+}
+
+void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+ VisitCXXNamedCastExpr(E);
+ Code = serialization::EXPR_CXX_CONST_CAST;
+}
+
+void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+ VisitExplicitCastExpr(E);
+ Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_CXX_FUNCTIONAL_CAST;
+}
+
+void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getValue());
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Code = serialization::EXPR_CXX_BOOL_LITERAL;
+}
+
+void ASTStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Code = serialization::EXPR_CXX_NULL_PTR_LITERAL;
+}
+
+void ASTStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ if (E->isTypeOperand()) {
+ Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record);
+ Code = serialization::EXPR_CXX_TYPEID_TYPE;
+ } else {
+ Writer.AddStmt(E->getExprOperand());
+ Code = serialization::EXPR_CXX_TYPEID_EXPR;
+ }
+}
+
+void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ if (E->isTypeOperand()) {
+ Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record);
+ Code = serialization::EXPR_CXX_UUIDOF_TYPE;
+ } else {
+ Writer.AddStmt(E->getExprOperand());
+ Code = serialization::EXPR_CXX_UUIDOF_EXPR;
+ }
+}
+
+void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Record.push_back(E->isImplicit());
+ Code = serialization::EXPR_CXX_THIS;
+}
+
+void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getThrowLoc(), Record);
+ Writer.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_CXX_THROW;
+}
+
+void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ VisitExpr(E);
+
+ bool HasOtherExprStored = E->Param.getInt();
+ // Store these first, the reader reads them before creation.
+ Record.push_back(HasOtherExprStored);
+ if (HasOtherExprStored)
+ Writer.AddStmt(E->getExpr());
+ Writer.AddDeclRef(E->getParam(), Record);
+ Writer.AddSourceLocation(E->getUsedLocation(), Record);
+
+ Code = serialization::EXPR_CXX_DEFAULT_ARG;
+}
+
+void ASTStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ VisitExpr(E);
+ Writer.AddCXXTemporary(E->getTemporary(), Record);
+ Writer.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_CXX_BIND_TEMPORARY;
+}
+
+void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ VisitExpr(E);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_CXX_SCALAR_VALUE_INIT;
+}
+
+void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->isGlobalNew());
+ Record.push_back(E->hasInitializer());
+ Record.push_back(E->doesUsualArrayDeleteWantSize());
+ Record.push_back(E->isArray());
+ Record.push_back(E->getNumPlacementArgs());
+ Record.push_back(E->getNumConstructorArgs());
+ Writer.AddDeclRef(E->getOperatorNew(), Record);
+ Writer.AddDeclRef(E->getOperatorDelete(), Record);
+ Writer.AddDeclRef(E->getConstructor(), Record);
+ Writer.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo(), Record);
+ Writer.AddSourceRange(E->getTypeIdParens(), Record);
+ Writer.AddSourceLocation(E->getStartLoc(), Record);
+ Writer.AddSourceLocation(E->getEndLoc(), Record);
+ Writer.AddSourceLocation(E->getConstructorLParen(), Record);
+ Writer.AddSourceLocation(E->getConstructorRParen(), Record);
+ for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end();
+ I != e; ++I)
+ Writer.AddStmt(*I);
+
+ Code = serialization::EXPR_CXX_NEW;
+}
+
+void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->isGlobalDelete());
+ Record.push_back(E->isArrayForm());
+ Record.push_back(E->isArrayFormAsWritten());
+ Record.push_back(E->doesUsualArrayDeleteWantSize());
+ Writer.AddDeclRef(E->getOperatorDelete(), Record);
+ Writer.AddStmt(E->getArgument());
+ Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record);
+
+ Code = serialization::EXPR_CXX_DELETE;
+}
+
+void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ VisitExpr(E);
+
+ Writer.AddStmt(E->getBase());
+ Record.push_back(E->isArrow());
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+ Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record);
+ Writer.AddSourceLocation(E->getColonColonLoc(), Record);
+ Writer.AddSourceLocation(E->getTildeLoc(), Record);
+
+ // PseudoDestructorTypeStorage.
+ Writer.AddIdentifierRef(E->getDestroyedTypeIdentifier(), Record);
+ if (E->getDestroyedTypeIdentifier())
+ Writer.AddSourceLocation(E->getDestroyedTypeLoc(), Record);
+ else
+ Writer.AddTypeSourceInfo(E->getDestroyedTypeInfo(), Record);
+
+ Code = serialization::EXPR_CXX_PSEUDO_DESTRUCTOR;
+}
+
+void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) {
+ VisitExpr(E);
+ Record.push_back(E->getNumTemporaries());
+ for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i)
+ Writer.AddCXXTemporary(E->getTemporary(i), Record);
+
+ Writer.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_EXPR_WITH_CLEANUPS;
+}
+
+void
+ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+ VisitExpr(E);
+
+ // Don't emit anything here, hasExplicitTemplateArgs() must be
+ // emitted first.
+
+ Record.push_back(E->hasExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs()) {
+ const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
+ Record.push_back(Args.NumTemplateArgs);
+ AddExplicitTemplateArgumentList(Args);
+ }
+
+ if (!E->isImplicitAccess())
+ Writer.AddStmt(E->getBase());
+ else
+ Writer.AddStmt(0);
+ Writer.AddTypeRef(E->getBaseType(), Record);
+ Record.push_back(E->isArrow());
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+ Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record);
+ Writer.AddDeclarationNameInfo(E->MemberNameInfo, Record);
+ Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
+}
+
+void
+ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ VisitExpr(E);
+
+ // Don't emit anything here, hasExplicitTemplateArgs() must be
+ // emitted first.
+ Record.push_back(E->hasExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs()) {
+ const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
+ Record.push_back(Args.NumTemplateArgs);
+ AddExplicitTemplateArgumentList(Args);
+ }
+
+ Writer.AddDeclarationNameInfo(E->NameInfo, Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
+}
+
+void
+ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->arg_size());
+ for (CXXUnresolvedConstructExpr::arg_iterator
+ ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI)
+ Writer.AddStmt(*ArgI);
+ Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
+ Writer.AddSourceLocation(E->getLParenLoc(), Record);
+ Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT;
+}
+
+void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
+ VisitExpr(E);
+
+ // Don't emit anything here, hasExplicitTemplateArgs() must be emitted first.
+ Record.push_back(E->hasExplicitTemplateArgs());
+ if (E->hasExplicitTemplateArgs()) {
+ const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
+ Record.push_back(Args.NumTemplateArgs);
+ AddExplicitTemplateArgumentList(Args);
+ }
+
+ Record.push_back(E->getNumDecls());
+ for (OverloadExpr::decls_iterator
+ OvI = E->decls_begin(), OvE = E->decls_end(); OvI != OvE; ++OvI) {
+ Writer.AddDeclRef(OvI.getDecl(), Record);
+ Record.push_back(OvI.getAccess());
+ }
+
+ Writer.AddDeclarationNameInfo(E->NameInfo, Record);
+ Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
+ Writer.AddSourceRange(E->getQualifierRange(), Record);
+}
+
+void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ VisitOverloadExpr(E);
+ Record.push_back(E->isArrow());
+ Record.push_back(E->hasUnresolvedUsing());
+ Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0);
+ Writer.AddTypeRef(E->getBaseType(), Record);
+ Writer.AddSourceLocation(E->getOperatorLoc(), Record);
+ Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER;
+}
+
+void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+ VisitOverloadExpr(E);
+ Record.push_back(E->requiresADL());
+ Record.push_back(E->isOverloaded());
+ Writer.AddDeclRef(E->getNamingClass(), Record);
+ Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
+}
+
+void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getTrait());
+ Record.push_back(E->getValue());
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(), Record);
+ Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
+}
+
+void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getTrait());
+ Record.push_back(E->getValue());
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ Writer.AddTypeSourceInfo(E->getLhsTypeSourceInfo(), Record);
+ Writer.AddTypeSourceInfo(E->getRhsTypeSourceInfo(), Record);
+ Code = serialization::EXPR_BINARY_TYPE_TRAIT;
+}
+
+void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getValue());
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ Writer.AddStmt(E->getOperand());
+ Code = serialization::EXPR_CXX_NOEXCEPT;
+}
+
+void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->getEllipsisLoc(), Record);
+ Record.push_back(E->NumExpansions);
+ Writer.AddStmt(E->getPattern());
+ Code = serialization::EXPR_PACK_EXPANSION;
+}
+
+void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->OperatorLoc, Record);
+ Writer.AddSourceLocation(E->PackLoc, Record);
+ Writer.AddSourceLocation(E->RParenLoc, Record);
+ Record.push_back(E->Length);
+ Writer.AddDeclRef(E->Pack, Record);
+ Code = serialization::EXPR_SIZEOF_PACK;
+}
+
+void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
+ SubstNonTypeTemplateParmPackExpr *E) {
+ VisitExpr(E);
+ Writer.AddDeclRef(E->Param, Record);
+ Writer.AddTemplateArgument(E->getArgumentPack(), Record);
+ Writer.AddSourceLocation(E->NameLoc, Record);
+ Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
+}
+
+void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ VisitExpr(E);
+ Record.push_back(Writer.getOpaqueValueID(E));
+ Writer.AddSourceLocation(E->getLocation(), Record);
+ Code = serialization::EXPR_OPAQUE_VALUE;
+}
+
+//===----------------------------------------------------------------------===//
+// CUDA Expressions and Statements.
+//===----------------------------------------------------------------------===//
+
+void ASTStmtWriter::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
+ VisitCallExpr(E);
+ Writer.AddStmt(E->getConfig());
+ Code = serialization::EXPR_CUDA_KERNEL_CALL;
+}
+
+//===----------------------------------------------------------------------===//
+// ASTWriter Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) {
+ assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
+ "SwitchCase recorded twice");
+ unsigned NextID = SwitchCaseIDs.size();
+ SwitchCaseIDs[S] = NextID;
+ return NextID;
+}
+
+unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) {
+ assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
+ "SwitchCase hasn't been seen yet");
+ return SwitchCaseIDs[S];
+}
+
+void ASTWriter::ClearSwitchCaseIDs() {
+ SwitchCaseIDs.clear();
+}
+
+unsigned ASTWriter::getOpaqueValueID(OpaqueValueExpr *e) {
+ unsigned &entry = OpaqueValues[e];
+ if (!entry) entry = OpaqueValues.size();
+ return entry;
+}
+
+/// \brief Write the given substatement or subexpression to the
+/// bitstream.
+void ASTWriter::WriteSubStmt(Stmt *S) {
+ RecordData Record;
+ ASTStmtWriter Writer(*this, Record);
+ ++NumStatements;
+
+ if (!S) {
+ Stream.EmitRecord(serialization::STMT_NULL_PTR, Record);
+ return;
+ }
+
+ // Redirect ASTWriter::AddStmt to collect sub stmts.
+ llvm::SmallVector<Stmt *, 16> SubStmts;
+ CollectedStmts = &SubStmts;
+
+ Writer.Code = serialization::STMT_NULL_PTR;
+ Writer.Visit(S);
+
+#ifndef NDEBUG
+ if (Writer.Code == serialization::STMT_NULL_PTR) {
+ SourceManager &SrcMgr
+ = DeclIDs.begin()->first->getASTContext().getSourceManager();
+ S->dump(SrcMgr);
+ assert(0 && "Unhandled sub statement writing AST file");
+ }
+#endif
+
+ // Revert ASTWriter::AddStmt.
+ CollectedStmts = &StmtsToEmit;
+
+ // Write the sub stmts in reverse order, last to first. When reading them back
+ // we will read them in correct order by "pop"ing them from the Stmts stack.
+ // This simplifies reading and allows to store a variable number of sub stmts
+ // without knowing it in advance.
+ while (!SubStmts.empty())
+ WriteSubStmt(SubStmts.pop_back_val());
+
+ Stream.EmitRecord(Writer.Code, Record);
+}
+
+/// \brief Flush all of the statements that have been added to the
+/// queue via AddStmt().
+void ASTWriter::FlushStmts() {
+ RecordData Record;
+
+ for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
+ WriteSubStmt(StmtsToEmit[I]);
+
+ assert(N == StmtsToEmit.size() &&
+ "Substatement writen via AddStmt rather than WriteSubStmt!");
+
+ // Note that we are at the end of a full expression. Any
+ // expression records that follow this one are part of a different
+ // expression.
+ Stream.EmitRecord(serialization::STMT_STOP, Record);
+ }
+
+ StmtsToEmit.clear();
+}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
new file mode 100644
index 0000000..b8833ce
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
@@ -0,0 +1,78 @@
+//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- 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 CreatePCHGenerate function, which creates an
+// ASTConsumer that generates a PCH file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Serialization/ASTWriter.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+using namespace clang;
+
+PCHGenerator::PCHGenerator(const Preprocessor &PP,
+ const std::string &OutputFile,
+ bool Chaining,
+ const char *isysroot,
+ llvm::raw_ostream *OS)
+ : PP(PP), OutputFile(OutputFile), isysroot(isysroot), Out(OS), SemaPtr(0),
+ StatCalls(0), Stream(Buffer), Writer(Stream), Chaining(Chaining) {
+ // Install a stat() listener to keep track of all of the stat()
+ // calls.
+ StatCalls = new MemorizeStatCalls();
+ // If we have a chain, we want new stat calls only, so install the memorizer
+ // *after* the already installed ASTReader's stat cache.
+ PP.getFileManager().addStatCache(StatCalls,
+ /*AtBeginning=*/!Chaining);
+}
+
+void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+ if (PP.getDiagnostics().hasErrorOccurred())
+ return;
+
+ // Set up the serialization listener.
+ Writer.SetSerializationListener(GetASTSerializationListener());
+
+ // Emit the PCH file
+ assert(SemaPtr && "No Sema?");
+ Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, isysroot);
+
+ // Write the generated bitstream to "Out".
+ Out->write((char *)&Buffer.front(), Buffer.size());
+
+ // Make sure it hits disk now.
+ Out->flush();
+
+ // Free up some memory, in case the process is kept alive.
+ Buffer.clear();
+}
+
+ASTMutationListener *PCHGenerator::GetASTMutationListener() {
+ if (Chaining)
+ return &Writer;
+ return 0;
+}
+
+ASTSerializationListener *PCHGenerator::GetASTSerializationListener() {
+ return 0;
+}
+
+ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
+ return &Writer;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/CMakeLists.txt b/contrib/llvm/tools/clang/lib/StaticAnalyzer/CMakeLists.txt
new file mode 100644
index 0000000..3d15092
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_subdirectory(Core)
+add_subdirectory(Checkers)
+add_subdirectory(Frontend)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
new file mode 100644
index 0000000..8832b05
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
@@ -0,0 +1,96 @@
+//== AdjustedReturnValueChecker.cpp -----------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines AdjustedReturnValueChecker, a simple check to see if the
+// return value of a function call is different than the one the caller thinks
+// it is.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class AdjustedReturnValueChecker :
+ public CheckerVisitor<AdjustedReturnValueChecker> {
+public:
+ AdjustedReturnValueChecker() {}
+
+ void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+
+ static void *getTag() {
+ static int x = 0; return &x;
+ }
+};
+}
+
+void ento::RegisterAdjustedReturnValueChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new AdjustedReturnValueChecker());
+}
+
+void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+
+ // Get the result type of the call.
+ QualType expectedResultTy = CE->getType();
+
+ // Fetch the signature of the called function.
+ const GRState *state = C.getState();
+
+ SVal V = state->getSVal(CE);
+
+ if (V.isUnknown())
+ return;
+
+ // Casting to void? Discard the value.
+ if (expectedResultTy->isVoidType()) {
+ C.generateNode(state->BindExpr(CE, UnknownVal()));
+ return;
+ }
+
+ const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
+ if (!callee)
+ return;
+
+ QualType actualResultTy;
+
+ if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
+ const FunctionDecl *FD = FT->getDecl();
+ actualResultTy = FD->getResultType();
+ }
+ else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
+ const BlockTextRegion *BR = BD->getCodeRegion();
+ const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
+ const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+ actualResultTy = FT->getResultType();
+ }
+
+ // Can this happen?
+ if (actualResultTy.isNull())
+ return;
+
+ // For now, ignore references.
+ if (actualResultTy->getAs<ReferenceType>())
+ return;
+
+
+ // Are they the same?
+ if (expectedResultTy != actualResultTy) {
+ // FIXME: Do more checking and actual emit an error. At least performing
+ // the cast avoids some assertion failures elsewhere.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
+ C.generateNode(state->BindExpr(CE, V));
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
new file mode 100644
index 0000000..7b68887
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -0,0 +1,123 @@
+//==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file reports various statistics about analyzer visitation.
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+
+// FIXME: Restructure checker registration.
+#include "ExperimentalChecks.h"
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class AnalyzerStatsChecker : public CheckerVisitor<AnalyzerStatsChecker> {
+public:
+ static void *getTag();
+ void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng);
+
+private:
+ llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
+};
+}
+
+void *AnalyzerStatsChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void ento::RegisterAnalyzerStatsChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new AnalyzerStatsChecker());
+}
+
+void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ ExprEngine &Eng) {
+ const CFG *C = 0;
+ const Decl *D = 0;
+ const LocationContext *LC = 0;
+ const SourceManager &SM = B.getSourceManager();
+
+ // Iterate over explodedgraph
+ for (ExplodedGraph::node_iterator I = G.nodes_begin();
+ I != G.nodes_end(); ++I) {
+ const ProgramPoint &P = I->getLocation();
+ // Save the LocationContext if we don't have it already
+ if (!LC)
+ LC = P.getLocationContext();
+
+ if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+ const CFGBlock *CB = BE->getBlock();
+ reachable.insert(CB);
+ }
+ }
+
+ // Get the CFG and the Decl of this block
+ C = LC->getCFG();
+ D = LC->getAnalysisContext()->getDecl();
+
+ unsigned total = 0, unreachable = 0;
+
+ // Find CFGBlocks that were not covered by any node
+ for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+ const CFGBlock *CB = *I;
+ ++total;
+ // Check if the block is unreachable
+ if (!reachable.count(CB)) {
+ ++unreachable;
+ }
+ }
+
+ // We never 'reach' the entry block, so correct the unreachable count
+ unreachable--;
+
+ // Generate the warning string
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream output(buf);
+ PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+ if (Loc.isValid()) {
+ output << Loc.getFilename() << " : ";
+
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ const NamedDecl *ND = cast<NamedDecl>(D);
+ output << ND;
+ }
+ else if (isa<BlockDecl>(D)) {
+ output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
+ }
+ }
+
+ output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
+ << unreachable << " | Aborted Block: "
+ << (Eng.wasBlockAborted() ? "yes" : "no")
+ << " | Empty WorkList: "
+ << (Eng.hasEmptyWorkList() ? "yes" : "no");
+
+ B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(),
+ D->getLocation());
+
+ // Emit warning for each block we bailed out on
+ typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
+ const CoreEngine &CE = Eng.getCoreEngine();
+ for (AbortedIterator I = CE.blocks_aborted_begin(),
+ E = CE.blocks_aborted_end(); I != E; ++I) {
+ const BlockEdge &BE = I->first;
+ const CFGBlock *Exit = BE.getDst();
+ const CFGElement &CE = Exit->front();
+ if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE))
+ B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer "
+ "stopped analyzing at this point", CS->getStmt()->getLocStart());
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
new file mode 100644
index 0000000..9194791
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -0,0 +1,92 @@
+//== ArrayBoundChecker.cpp ------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ArrayBoundChecker, which is a path-sensitive check
+// which looks for an out-of-bound array element access.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ArrayBoundChecker :
+ public CheckerVisitor<ArrayBoundChecker> {
+ BuiltinBug *BT;
+public:
+ ArrayBoundChecker() : BT(0) {}
+ static void *getTag() { static int x = 0; return &x; }
+ void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
+};
+}
+
+void ento::RegisterArrayBoundChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new ArrayBoundChecker());
+}
+
+void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
+ bool isLoad) {
+ // Check for out of bound array element access.
+ const MemRegion *R = l.getAsRegion();
+ if (!R)
+ return;
+
+ const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+ if (!ER)
+ return;
+
+ // Get the index of the accessed element.
+ DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+ // Zero index is always in bound, this also passes ElementRegions created for
+ // pointer casts.
+ if (Idx.isZeroConstant())
+ return;
+
+ const GRState *state = C.getState();
+
+ // Get the size of the array.
+ DefinedOrUnknownSVal NumElements
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+ ER->getValueType());
+
+ const GRState *StInBound = state->assumeInBound(Idx, NumElements, true);
+ const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false);
+ if (StOutBound && !StInBound) {
+ ExplodedNode *N = C.generateSink(StOutBound);
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Out-of-bound array access",
+ "Access out-of-bound array element (buffer overflow)");
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+
+ // Generate a report for this bug.
+ RangedBugReport *report =
+ new RangedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(S->getSourceRange());
+ C.EmitReport(report);
+ return;
+ }
+
+ // Array bound check succeeded. From this point forward the array bound
+ // should always succeed.
+ assert(StInBound);
+ C.addTransition(StInBound);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
new file mode 100644
index 0000000..f803d27
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -0,0 +1,277 @@
+//== ArrayBoundCheckerV2.cpp ------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ArrayBoundCheckerV2, which is a path-sensitive check
+// which looks for an out-of-bound array element access.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/CharUnits.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ArrayBoundCheckerV2 :
+ public CheckerVisitor<ArrayBoundCheckerV2> {
+ BuiltinBug *BT;
+
+ enum OOB_Kind { OOB_Precedes, OOB_Excedes };
+
+ void reportOOB(CheckerContext &C, const GRState *errorState,
+ OOB_Kind kind);
+
+public:
+ ArrayBoundCheckerV2() : BT(0) {}
+ static void *getTag() { static int x = 0; return &x; }
+ void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
+};
+
+// FIXME: Eventually replace RegionRawOffset with this class.
+class RegionRawOffsetV2 {
+private:
+ const SubRegion *baseRegion;
+ SVal byteOffset;
+
+ RegionRawOffsetV2()
+ : baseRegion(0), byteOffset(UnknownVal()) {}
+
+public:
+ RegionRawOffsetV2(const SubRegion* base, SVal offset)
+ : baseRegion(base), byteOffset(offset) {}
+
+ NonLoc getByteOffset() const { return cast<NonLoc>(byteOffset); }
+ const SubRegion *getRegion() const { return baseRegion; }
+
+ static RegionRawOffsetV2 computeOffset(const GRState *state,
+ SValBuilder &svalBuilder,
+ SVal location);
+
+ void dump() const;
+ void dumpToStream(llvm::raw_ostream& os) const;
+};
+}
+
+void ento::RegisterArrayBoundCheckerV2(ExprEngine &Eng) {
+ Eng.registerCheck(new ArrayBoundCheckerV2());
+}
+
+void ArrayBoundCheckerV2::visitLocation(CheckerContext &checkerContext,
+ const Stmt *S,
+ SVal location, bool isLoad) {
+
+ // NOTE: Instead of using GRState::assumeInBound(), we are prototyping
+ // some new logic here that reasons directly about memory region extents.
+ // Once that logic is more mature, we can bring it back to assumeInBound()
+ // for all clients to use.
+ //
+ // The algorithm we are using here for bounds checking is to see if the
+ // memory access is within the extent of the base region. Since we
+ // have some flexibility in defining the base region, we can achieve
+ // various levels of conservatism in our buffer overflow checking.
+ const GRState *state = checkerContext.getState();
+ const GRState *originalState = state;
+
+ SValBuilder &svalBuilder = checkerContext.getSValBuilder();
+ const RegionRawOffsetV2 &rawOffset =
+ RegionRawOffsetV2::computeOffset(state, svalBuilder, location);
+
+ if (!rawOffset.getRegion())
+ return;
+
+ // CHECK LOWER BOUND: Is byteOffset < 0? If so, we are doing a load/store
+ // before the first valid offset in the memory region.
+
+ SVal lowerBound
+ = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(),
+ svalBuilder.makeZeroArrayIndex(),
+ svalBuilder.getConditionType());
+
+ NonLoc *lowerBoundToCheck = dyn_cast<NonLoc>(&lowerBound);
+ if (!lowerBoundToCheck)
+ return;
+
+ const GRState *state_precedesLowerBound, *state_withinLowerBound;
+ llvm::tie(state_precedesLowerBound, state_withinLowerBound) =
+ state->assume(*lowerBoundToCheck);
+
+ // Are we constrained enough to definitely precede the lower bound?
+ if (state_precedesLowerBound && !state_withinLowerBound) {
+ reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes);
+ return;
+ }
+
+ // Otherwise, assume the constraint of the lower bound.
+ assert(state_withinLowerBound);
+ state = state_withinLowerBound;
+
+ do {
+ // CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)? If so,
+ // we are doing a load/store after the last valid offset.
+ DefinedOrUnknownSVal extentVal =
+ rawOffset.getRegion()->getExtent(svalBuilder);
+ if (!isa<NonLoc>(extentVal))
+ break;
+
+ SVal upperbound
+ = svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(),
+ cast<NonLoc>(extentVal),
+ svalBuilder.getConditionType());
+
+ NonLoc *upperboundToCheck = dyn_cast<NonLoc>(&upperbound);
+ if (!upperboundToCheck)
+ break;
+
+ const GRState *state_exceedsUpperBound, *state_withinUpperBound;
+ llvm::tie(state_exceedsUpperBound, state_withinUpperBound) =
+ state->assume(*upperboundToCheck);
+
+ // Are we constrained enough to definitely exceed the upper bound?
+ if (state_exceedsUpperBound && !state_withinUpperBound) {
+ reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
+ return;
+ }
+
+ assert(state_withinUpperBound);
+ state = state_withinUpperBound;
+ }
+ while (false);
+
+ if (state != originalState)
+ checkerContext.generateNode(state);
+}
+
+void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
+ const GRState *errorState,
+ OOB_Kind kind) {
+
+ ExplodedNode *errorNode = checkerContext.generateSink(errorState);
+ if (!errorNode)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Out-of-bound access");
+
+ // FIXME: This diagnostics are preliminary. We should get far better
+ // diagnostics for explaining buffer overruns.
+
+ llvm::SmallString<256> buf;
+ llvm::raw_svector_ostream os(buf);
+ os << "Out of bound memory access "
+ << (kind == OOB_Precedes ? "(accessed memory precedes memory block)"
+ : "(access exceeds upper limit of memory block)");
+
+ checkerContext.EmitReport(new RangedBugReport(*BT, os.str(), errorNode));
+}
+
+void RegionRawOffsetV2::dump() const {
+ dumpToStream(llvm::errs());
+}
+
+void RegionRawOffsetV2::dumpToStream(llvm::raw_ostream& os) const {
+ os << "raw_offset_v2{" << getRegion() << ',' << getByteOffset() << '}';
+}
+
+// FIXME: Merge with the implementation of the same method in Store.cpp
+static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *D = RT->getDecl();
+ if (!D->getDefinition())
+ return false;
+ }
+
+ return true;
+}
+
+
+// Lazily computes a value to be used by 'computeOffset'. If 'val'
+// is unknown or undefined, we lazily substitute '0'. Otherwise,
+// return 'val'.
+static inline SVal getValue(SVal val, SValBuilder &svalBuilder) {
+ return isa<UndefinedVal>(val) ? svalBuilder.makeArrayIndex(0) : val;
+}
+
+// Scale a base value by a scaling factor, and return the scaled
+// value as an SVal. Used by 'computeOffset'.
+static inline SVal scaleValue(const GRState *state,
+ NonLoc baseVal, CharUnits scaling,
+ SValBuilder &sb) {
+ return sb.evalBinOpNN(state, BO_Mul, baseVal,
+ sb.makeArrayIndex(scaling.getQuantity()),
+ sb.getArrayIndexType());
+}
+
+// Add an SVal to another, treating unknown and undefined values as
+// summing to UnknownVal. Used by 'computeOffset'.
+static SVal addValue(const GRState *state, SVal x, SVal y,
+ SValBuilder &svalBuilder) {
+ // We treat UnknownVals and UndefinedVals the same here because we
+ // only care about computing offsets.
+ if (x.isUnknownOrUndef() || y.isUnknownOrUndef())
+ return UnknownVal();
+
+ return svalBuilder.evalBinOpNN(state, BO_Add,
+ cast<NonLoc>(x), cast<NonLoc>(y),
+ svalBuilder.getArrayIndexType());
+}
+
+/// Compute a raw byte offset from a base region. Used for array bounds
+/// checking.
+RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state,
+ SValBuilder &svalBuilder,
+ SVal location)
+{
+ const MemRegion *region = location.getAsRegion();
+ SVal offset = UndefinedVal();
+
+ while (region) {
+ switch (region->getKind()) {
+ default: {
+ if (const SubRegion *subReg = dyn_cast<SubRegion>(region))
+ if (!offset.isUnknownOrUndef())
+ return RegionRawOffsetV2(subReg, offset);
+ return RegionRawOffsetV2();
+ }
+ case MemRegion::ElementRegionKind: {
+ const ElementRegion *elemReg = cast<ElementRegion>(region);
+ SVal index = elemReg->getIndex();
+ if (!isa<NonLoc>(index))
+ return RegionRawOffsetV2();
+ QualType elemType = elemReg->getElementType();
+ // If the element is an incomplete type, go no further.
+ ASTContext &astContext = svalBuilder.getContext();
+ if (!IsCompleteType(astContext, elemType))
+ return RegionRawOffsetV2();
+
+ // Update the offset.
+ offset = addValue(state,
+ getValue(offset, svalBuilder),
+ scaleValue(state,
+ cast<NonLoc>(index),
+ astContext.getTypeSizeInChars(elemType),
+ svalBuilder),
+ svalBuilder);
+
+ if (offset.isUnknownOrUndef())
+ return RegionRawOffsetV2();
+
+ region = elemReg->getSuperRegion();
+ continue;
+ }
+ }
+ }
+ return RegionRawOffsetV2();
+}
+
+
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
new file mode 100644
index 0000000..e4865b1
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
@@ -0,0 +1,136 @@
+//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines AttrNonNullChecker, a builtin check in ExprEngine that
+// performs checks for arguments declared to have nonnull attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class AttrNonNullChecker
+ : public CheckerVisitor<AttrNonNullChecker> {
+ BugType *BT;
+public:
+ AttrNonNullChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} // end anonymous namespace
+
+void ento::RegisterAttrNonNullChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new AttrNonNullChecker());
+}
+
+void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+
+ // Check if the callee has a 'nonnull' attribute.
+ SVal X = state->getSVal(CE->getCallee());
+
+ const FunctionDecl* FD = X.getAsFunctionDecl();
+ if (!FD)
+ return;
+
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+ if (!Att)
+ return;
+
+ // Iterate through the arguments of CE and check them for null.
+ unsigned idx = 0;
+
+ for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+ ++I, ++idx) {
+
+ if (!Att->isNonNull(idx))
+ continue;
+
+ SVal V = state->getSVal(*I);
+ DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
+
+ // If the value is unknown or undefined, we can't perform this check.
+ if (!DV)
+ continue;
+
+ if (!isa<Loc>(*DV)) {
+ // If the argument is a union type, we want to handle a potential
+ // transparent_unoin GCC extension.
+ QualType T = (*I)->getType();
+ const RecordType *UT = T->getAsUnionType();
+ if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ continue;
+ if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) {
+ nonloc::CompoundVal::iterator CSV_I = CSV->begin();
+ assert(CSV_I != CSV->end());
+ V = *CSV_I;
+ DV = dyn_cast<DefinedSVal>(&V);
+ assert(++CSV_I == CSV->end());
+ if (!DV)
+ continue;
+ }
+ else {
+ // FIXME: Handle LazyCompoundVals?
+ continue;
+ }
+ }
+
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
+
+ if (stateNull && !stateNotNull) {
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
+
+ // Lazily allocate the BugType object if it hasn't already been
+ // created. Ownership is transferred to the BugReporter object once
+ // the BugReport is passed to 'EmitWarning'.
+ if (!BT)
+ BT = new BugType("Argument with 'nonnull' attribute passed null",
+ "API");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT,
+ "Null pointer passed as an argument to a "
+ "'nonnull' parameter", errorNode);
+
+ // Highlight the range of the argument that was null.
+ const Expr *arg = *I;
+ R->addRange(arg->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
+
+ // Emit the bug report.
+ C.EmitReport(R);
+ }
+
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+
+ // If a pointer value passed the check we should assume that it is
+ // indeed not null from this point forward.
+ assert(stateNotNull);
+ state = stateNotNull;
+ }
+
+ // If we reach here all of the arguments passed the nonnull check.
+ // If 'state' has been updated generated a new node.
+ C.addTransition(state);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
new file mode 100644
index 0000000..1b6c528
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -0,0 +1,521 @@
+//== BasicObjCFoundationChecks.cpp - Simple Apple-Foundation checks -*- C++ -*--
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BasicObjCFoundationChecks, a class that encapsulates
+// a set of simple checks to run on Objective-C code using Apple's Foundation
+// classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BasicObjCFoundationChecks.h"
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class APIMisuse : public BugType {
+public:
+ APIMisuse(const char* name) : BugType(name, "API Misuse (Apple)") {}
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static const ObjCInterfaceType* GetReceiverType(const ObjCMessage &msg) {
+ if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
+ return ID->getTypeForDecl()->getAs<ObjCInterfaceType>();
+ return NULL;
+}
+
+static const char* GetReceiverNameType(const ObjCMessage &msg) {
+ if (const ObjCInterfaceType *ReceiverType = GetReceiverType(msg))
+ return ReceiverType->getDecl()->getIdentifier()->getNameStart();
+ return NULL;
+}
+
+static bool isNSString(llvm::StringRef ClassName) {
+ return ClassName == "NSString" || ClassName == "NSMutableString";
+}
+
+static inline bool isNil(SVal X) {
+ return isa<loc::ConcreteInt>(X);
+}
+
+//===----------------------------------------------------------------------===//
+// NilArgChecker - Check for prohibited nil arguments to ObjC method calls.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class NilArgChecker : public CheckerVisitor<NilArgChecker> {
+ APIMisuse *BT;
+ void WarnNilArg(CheckerContext &C, const ObjCMessage &msg, unsigned Arg);
+ public:
+ NilArgChecker() : BT(0) {}
+ static void *getTag() { static int x = 0; return &x; }
+ void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ };
+}
+
+void NilArgChecker::WarnNilArg(CheckerContext &C,
+ const ObjCMessage &msg,
+ unsigned int Arg)
+{
+ if (!BT)
+ BT = new APIMisuse("nil argument");
+
+ if (ExplodedNode *N = C.generateSink()) {
+ llvm::SmallString<128> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+ os << "Argument to '" << GetReceiverNameType(msg) << "' method '"
+ << msg.getSelector().getAsString() << "' cannot be nil";
+
+ RangedBugReport *R = new RangedBugReport(*BT, os.str(), N);
+ R->addRange(msg.getArgSourceRange(Arg));
+ C.EmitReport(R);
+ }
+}
+
+void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
+ ObjCMessage msg)
+{
+ const ObjCInterfaceType *ReceiverType = GetReceiverType(msg);
+ if (!ReceiverType)
+ return;
+
+ if (isNSString(ReceiverType->getDecl()->getIdentifier()->getName())) {
+ Selector S = msg.getSelector();
+
+ if (S.isUnarySelector())
+ return;
+
+ // FIXME: This is going to be really slow doing these checks with
+ // lexical comparisons.
+
+ std::string NameStr = S.getAsString();
+ llvm::StringRef Name(NameStr);
+ assert(!Name.empty());
+
+ // FIXME: Checking for initWithFormat: will not work in most cases
+ // yet because [NSString alloc] returns id, not NSString*. We will
+ // need support for tracking expected-type information in the analyzer
+ // to find these errors.
+ if (Name == "caseInsensitiveCompare:" ||
+ Name == "compare:" ||
+ Name == "compare:options:" ||
+ Name == "compare:options:range:" ||
+ Name == "compare:options:range:locale:" ||
+ Name == "componentsSeparatedByCharactersInSet:" ||
+ Name == "initWithFormat:") {
+ if (isNil(msg.getArgSVal(0, C.getState())))
+ WarnNilArg(C, msg, 0);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFNumberCreateChecker : public CheckerVisitor<CFNumberCreateChecker> {
+ APIMisuse* BT;
+ IdentifierInfo* II;
+public:
+ CFNumberCreateChecker() : BT(0), II(0) {}
+ ~CFNumberCreateChecker() {}
+ static void *getTag() { static int x = 0; return &x; }
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+private:
+ void EmitError(const TypedRegion* R, const Expr* Ex,
+ uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
+};
+} // end anonymous namespace
+
+enum CFNumberType {
+ kCFNumberSInt8Type = 1,
+ kCFNumberSInt16Type = 2,
+ kCFNumberSInt32Type = 3,
+ kCFNumberSInt64Type = 4,
+ kCFNumberFloat32Type = 5,
+ kCFNumberFloat64Type = 6,
+ kCFNumberCharType = 7,
+ kCFNumberShortType = 8,
+ kCFNumberIntType = 9,
+ kCFNumberLongType = 10,
+ kCFNumberLongLongType = 11,
+ kCFNumberFloatType = 12,
+ kCFNumberDoubleType = 13,
+ kCFNumberCFIndexType = 14,
+ kCFNumberNSIntegerType = 15,
+ kCFNumberCGFloatType = 16
+};
+
+namespace {
+ template<typename T>
+ class Optional {
+ bool IsKnown;
+ T Val;
+ public:
+ Optional() : IsKnown(false), Val(0) {}
+ Optional(const T& val) : IsKnown(true), Val(val) {}
+
+ bool isKnown() const { return IsKnown; }
+
+ const T& getValue() const {
+ assert (isKnown());
+ return Val;
+ }
+
+ operator const T&() const {
+ return getValue();
+ }
+ };
+}
+
+static Optional<uint64_t> GetCFNumberSize(ASTContext& Ctx, uint64_t i) {
+ static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
+
+ if (i < kCFNumberCharType)
+ return FixedSize[i-1];
+
+ QualType T;
+
+ switch (i) {
+ case kCFNumberCharType: T = Ctx.CharTy; break;
+ case kCFNumberShortType: T = Ctx.ShortTy; break;
+ case kCFNumberIntType: T = Ctx.IntTy; break;
+ case kCFNumberLongType: T = Ctx.LongTy; break;
+ case kCFNumberLongLongType: T = Ctx.LongLongTy; break;
+ case kCFNumberFloatType: T = Ctx.FloatTy; break;
+ case kCFNumberDoubleType: T = Ctx.DoubleTy; break;
+ case kCFNumberCFIndexType:
+ case kCFNumberNSIntegerType:
+ case kCFNumberCGFloatType:
+ // FIXME: We need a way to map from names to Type*.
+ default:
+ return Optional<uint64_t>();
+ }
+
+ return Ctx.getTypeSize(T);
+}
+
+#if 0
+static const char* GetCFNumberTypeStr(uint64_t i) {
+ static const char* Names[] = {
+ "kCFNumberSInt8Type",
+ "kCFNumberSInt16Type",
+ "kCFNumberSInt32Type",
+ "kCFNumberSInt64Type",
+ "kCFNumberFloat32Type",
+ "kCFNumberFloat64Type",
+ "kCFNumberCharType",
+ "kCFNumberShortType",
+ "kCFNumberIntType",
+ "kCFNumberLongType",
+ "kCFNumberLongLongType",
+ "kCFNumberFloatType",
+ "kCFNumberDoubleType",
+ "kCFNumberCFIndexType",
+ "kCFNumberNSIntegerType",
+ "kCFNumberCGFloatType"
+ };
+
+ return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
+}
+#endif
+
+void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE)
+{
+ const Expr* Callee = CE->getCallee();
+ const GRState *state = C.getState();
+ SVal CallV = state->getSVal(Callee);
+ const FunctionDecl* FD = CallV.getAsFunctionDecl();
+
+ if (!FD)
+ return;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II)
+ II = &Ctx.Idents.get("CFNumberCreate");
+
+ if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
+ return;
+
+ // Get the value of the "theType" argument.
+ SVal TheTypeVal = state->getSVal(CE->getArg(1));
+
+ // FIXME: We really should allow ranges of valid theType values, and
+ // bifurcate the state appropriately.
+ nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
+ if (!V)
+ return;
+
+ uint64_t NumberKind = V->getValue().getLimitedValue();
+ Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);
+
+ // FIXME: In some cases we can emit an error.
+ if (!TargetSize.isKnown())
+ return;
+
+ // Look at the value of the integer being passed by reference. Essentially
+ // we want to catch cases where the value passed in is not equal to the
+ // size of the type being created.
+ SVal TheValueExpr = state->getSVal(CE->getArg(2));
+
+ // FIXME: Eventually we should handle arbitrary locations. We can do this
+ // by having an enhanced memory model that does low-level typing.
+ loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
+ if (!LV)
+ return;
+
+ const TypedRegion* R = dyn_cast<TypedRegion>(LV->stripCasts());
+ if (!R)
+ return;
+
+ QualType T = Ctx.getCanonicalType(R->getValueType());
+
+ // FIXME: If the pointee isn't an integer type, should we flag a warning?
+ // People can do weird stuff with pointers.
+
+ if (!T->isIntegerType())
+ return;
+
+ uint64_t SourceSize = Ctx.getTypeSize(T);
+
+ // CHECK: is SourceSize == TargetSize
+ if (SourceSize == TargetSize)
+ return;
+
+ // Generate an error. Only generate a sink if 'SourceSize < TargetSize';
+ // otherwise generate a regular node.
+ //
+ // FIXME: We can actually create an abstract "CFNumber" object that has
+ // the bits initialized to the provided values.
+ //
+ if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
+ : C.generateNode()) {
+ llvm::SmallString<128> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+
+ os << (SourceSize == 8 ? "An " : "A ")
+ << SourceSize << " bit integer is used to initialize a CFNumber "
+ "object that represents "
+ << (TargetSize == 8 ? "an " : "a ")
+ << TargetSize << " bit integer. ";
+
+ if (SourceSize < TargetSize)
+ os << (TargetSize - SourceSize)
+ << " bits of the CFNumber value will be garbage." ;
+ else
+ os << (SourceSize - TargetSize)
+ << " bits of the input integer will be lost.";
+
+ if (!BT)
+ BT = new APIMisuse("Bad use of CFNumberCreate");
+
+ RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
+ report->addRange(CE->getArg(2)->getSourceRange());
+ C.EmitReport(report);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// CFRetain/CFRelease checking for null arguments.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFRetainReleaseChecker : public CheckerVisitor<CFRetainReleaseChecker> {
+ APIMisuse *BT;
+ IdentifierInfo *Retain, *Release;
+public:
+ CFRetainReleaseChecker(): BT(0), Retain(0), Release(0) {}
+ static void *getTag() { static int x = 0; return &x; }
+ void PreVisitCallExpr(CheckerContext& C, const CallExpr* CE);
+};
+} // end anonymous namespace
+
+
+void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
+ const CallExpr* CE) {
+ // If the CallExpr doesn't have exactly 1 argument just give up checking.
+ if (CE->getNumArgs() != 1)
+ return;
+
+ // Get the function declaration of the callee.
+ const GRState* state = C.getState();
+ SVal X = state->getSVal(CE->getCallee());
+ const FunctionDecl* FD = X.getAsFunctionDecl();
+
+ if (!FD)
+ return;
+
+ if (!BT) {
+ ASTContext &Ctx = C.getASTContext();
+ Retain = &Ctx.Idents.get("CFRetain");
+ Release = &Ctx.Idents.get("CFRelease");
+ BT = new APIMisuse("null passed to CFRetain/CFRelease");
+ }
+
+ // Check if we called CFRetain/CFRelease.
+ const IdentifierInfo *FuncII = FD->getIdentifier();
+ if (!(FuncII == Retain || FuncII == Release))
+ return;
+
+ // FIXME: The rest of this just checks that the argument is non-null.
+ // It should probably be refactored and combined with AttrNonNullChecker.
+
+ // Get the argument's value.
+ const Expr *Arg = CE->getArg(0);
+ SVal ArgVal = state->getSVal(Arg);
+ DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
+ if (!DefArgVal)
+ return;
+
+ // Get a NULL value.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ DefinedSVal zero = cast<DefinedSVal>(svalBuilder.makeZeroVal(Arg->getType()));
+
+ // Make an expression asserting that they're equal.
+ DefinedOrUnknownSVal ArgIsNull = svalBuilder.evalEQ(state, zero, *DefArgVal);
+
+ // Are they equal?
+ const GRState *stateTrue, *stateFalse;
+ llvm::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
+
+ if (stateTrue && !stateFalse) {
+ ExplodedNode *N = C.generateSink(stateTrue);
+ if (!N)
+ return;
+
+ const char *description = (FuncII == Retain)
+ ? "Null pointer argument in call to CFRetain"
+ : "Null pointer argument in call to CFRelease";
+
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, description, N);
+ report->addRange(Arg->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Arg);
+ C.EmitReport(report);
+ return;
+ }
+
+ // From here on, we know the argument is non-null.
+ C.addTransition(stateFalse);
+}
+
+//===----------------------------------------------------------------------===//
+// Check for sending 'retain', 'release', or 'autorelease' directly to a Class.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ClassReleaseChecker : public CheckerVisitor<ClassReleaseChecker> {
+ Selector releaseS;
+ Selector retainS;
+ Selector autoreleaseS;
+ Selector drainS;
+ BugType *BT;
+public:
+ ClassReleaseChecker()
+ : BT(0) {}
+
+ static void *getTag() { static int x = 0; return &x; }
+
+ void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+};
+}
+
+void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
+ ObjCMessage msg) {
+
+ if (!BT) {
+ BT = new APIMisuse("message incorrectly sent to class instead of class "
+ "instance");
+
+ ASTContext &Ctx = C.getASTContext();
+ releaseS = GetNullarySelector("release", Ctx);
+ retainS = GetNullarySelector("retain", Ctx);
+ autoreleaseS = GetNullarySelector("autorelease", Ctx);
+ drainS = GetNullarySelector("drain", Ctx);
+ }
+
+ if (msg.isInstanceMessage())
+ return;
+ const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
+ assert(Class);
+
+ Selector S = msg.getSelector();
+ if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
+ return;
+
+ if (ExplodedNode *N = C.generateNode()) {
+ llvm::SmallString<200> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "The '" << S.getAsString() << "' message should be sent to instances "
+ "of class '" << Class->getName()
+ << "' and not the class directly";
+
+ RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
+ report->addRange(msg.getSourceRange());
+ C.EmitReport(report);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Check registration.
+//===----------------------------------------------------------------------===//
+
+static void RegisterNilArgChecker(ExprEngine& Eng) {
+ Eng.registerCheck(new NilArgChecker());
+}
+
+void ento::registerNilArgChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterNilArgChecker);
+}
+
+static void RegisterCFNumberCreateChecker(ExprEngine& Eng) {
+ Eng.registerCheck(new CFNumberCreateChecker());
+}
+
+void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterCFNumberCreateChecker);
+}
+
+static void RegisterCFRetainReleaseChecker(ExprEngine& Eng) {
+ Eng.registerCheck(new CFRetainReleaseChecker());
+}
+
+void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterCFRetainReleaseChecker);
+}
+
+static void RegisterClassReleaseChecker(ExprEngine& Eng) {
+ Eng.registerCheck(new ClassReleaseChecker());
+}
+
+void ento::registerClassReleaseChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterClassReleaseChecker);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h
new file mode 100644
index 0000000..92cfb1a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h
@@ -0,0 +1,35 @@
+//== BasicObjCFoundationChecks.h - Simple Apple-Foundation checks -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BasicObjCFoundationChecks, a class that encapsulates
+// a set of simple checks to run on Objective-C code using Apple's Foundation
+// classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_BASICOBJCFOUNDATIONCHECKS
+#define LLVM_CLANG_GR_BASICOBJCFOUNDATIONCHECKS
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+
+namespace ento {
+
+class BugReporter;
+class ExprEngine;
+
+void RegisterNSErrorChecks(BugReporter& BR, ExprEngine &Eng, const Decl &D);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
new file mode 100644
index 0000000..417b015
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -0,0 +1,83 @@
+//=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker evaluates clang builtin functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+#include "clang/Basic/Builtins.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BuiltinFunctionChecker : public Checker {
+public:
+ static void *getTag() { static int tag = 0; return &tag; }
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+
+void ento::RegisterBuiltinFunctionChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new BuiltinFunctionChecker());
+}
+
+bool BuiltinFunctionChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE){
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+
+ if (!FD)
+ return false;
+
+ unsigned id = FD->getBuiltinID();
+
+ if (!id)
+ return false;
+
+ switch (id) {
+ case Builtin::BI__builtin_expect: {
+ // For __builtin_expect, just return the value of the subexpression.
+ assert (CE->arg_begin() != CE->arg_end());
+ SVal X = state->getSVal(*(CE->arg_begin()));
+ C.generateNode(state->BindExpr(CE, X));
+ return true;
+ }
+
+ case Builtin::BI__builtin_alloca: {
+ // FIXME: Refactor into StoreManager itself?
+ MemRegionManager& RM = C.getStoreManager().getRegionManager();
+ const AllocaRegion* R =
+ RM.getAllocaRegion(CE, C.getNodeBuilder().getCurrentBlockCount(),
+ C.getPredecessor()->getLocationContext());
+
+ // Set the extent of the region in bytes. This enables us to use the
+ // SVal of the argument directly. If we save the extent in bits, we
+ // cannot represent values like symbol*8.
+ DefinedOrUnknownSVal Size =
+ cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin())));
+
+ SValBuilder& svalBuilder = C.getSValBuilder();
+ DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
+ DefinedOrUnknownSVal extentMatchesSizeArg =
+ svalBuilder.evalEQ(state, Extent, Size);
+ state = state->assume(extentMatchesSizeArg, true);
+
+ C.generateNode(state->BindExpr(CE, loc::MemRegionVal(R)));
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
new file mode 100644
index 0000000..e172a52
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -0,0 +1,70 @@
+set(LLVM_TARGET_DEFINITIONS Checkers.td)
+tablegen(Checkers.inc
+ -gen-clang-sa-checkers
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
+add_custom_target(ClangSACheckers
+ DEPENDS Checkers.inc)
+
+set(LLVM_USED_LIBS clangBasic clangAST)
+
+add_clang_library(clangStaticAnalyzerCheckers
+ AdjustedReturnValueChecker.cpp
+ AnalyzerStatsChecker.cpp
+ ArrayBoundChecker.cpp
+ ArrayBoundCheckerV2.cpp
+ AttrNonNullChecker.cpp
+ BasicObjCFoundationChecks.cpp
+ BuiltinFunctionChecker.cpp
+ CStringChecker.cpp
+ CallAndMessageChecker.cpp
+ CastSizeChecker.cpp
+ CastToStructChecker.cpp
+ CheckObjCDealloc.cpp
+ CheckObjCInstMethSignature.cpp
+ CheckSecuritySyntaxOnly.cpp
+ CheckSizeofPointer.cpp
+ ChrootChecker.cpp
+ ClangSACheckerProvider.cpp
+ DeadStoresChecker.cpp
+ DebugCheckers.cpp
+ DereferenceChecker.cpp
+ DivZeroChecker.cpp
+ ExprEngine.cpp
+ ExperimentalChecks.cpp
+ FixedAddressChecker.cpp
+ IdempotentOperationChecker.cpp
+ LLVMConventionsChecker.cpp
+ MacOSXAPIChecker.cpp
+ MallocChecker.cpp
+ NSAutoreleasePoolChecker.cpp
+ NSErrorChecker.cpp
+ NoReturnFunctionChecker.cpp
+ OSAtomicChecker.cpp
+ ObjCAtSyncChecker.cpp
+ ObjCSelfInitChecker.cpp
+ ObjCUnusedIVarsChecker.cpp
+ PointerArithChecker.cpp
+ PointerSubChecker.cpp
+ PthreadLockChecker.cpp
+ ReturnPointerRangeChecker.cpp
+ ReturnUndefChecker.cpp
+ StackAddrLeakChecker.cpp
+ StreamChecker.cpp
+ UndefBranchChecker.cpp
+ UndefCapturedBlockVarChecker.cpp
+ UndefResultChecker.cpp
+ UndefinedArraySubscriptChecker.cpp
+ UndefinedAssignmentChecker.cpp
+ UnixAPIChecker.cpp
+ UnreachableCodeChecker.cpp
+ VLASizeChecker.cpp
+ )
+
+add_dependencies(clangStaticAnalyzerCheckers
+ clangStaticAnalyzerCore
+ ClangAttrClasses
+ ClangAttrList
+ ClangDeclNodes
+ ClangStmtNodes
+ ClangSACheckers
+ )
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
new file mode 100644
index 0000000..03f9047
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -0,0 +1,1053 @@
+//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines CStringChecker, which is an assortment of checks on calls
+// to functions in <string.h>.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CStringChecker : public CheckerVisitor<CStringChecker> {
+ BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString;
+public:
+ CStringChecker()
+ : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0)
+ {}
+ static void *getTag() { static int tag; return &tag; }
+
+ bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+ void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
+ void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
+ void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
+ bool wantsRegionChangeUpdate(const GRState *state);
+
+ const GRState *EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool*);
+
+ typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
+
+ void evalMemcpy(CheckerContext &C, const CallExpr *CE);
+ void evalMemmove(CheckerContext &C, const CallExpr *CE);
+ void evalBcopy(CheckerContext &C, const CallExpr *CE);
+ void evalCopyCommon(CheckerContext &C, const GRState *state,
+ const Expr *Size, const Expr *Source, const Expr *Dest,
+ bool Restricted = false);
+
+ void evalMemcmp(CheckerContext &C, const CallExpr *CE);
+
+ void evalstrLength(CheckerContext &C, const CallExpr *CE);
+
+ void evalStrcpy(CheckerContext &C, const CallExpr *CE);
+ void evalStpcpy(CheckerContext &C, const CallExpr *CE);
+ void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd);
+
+ // Utility methods
+ std::pair<const GRState*, const GRState*>
+ assumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
+
+ const GRState *setCStringLength(const GRState *state, const MemRegion *MR,
+ SVal strLength);
+ SVal getCStringLengthForRegion(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, const MemRegion *MR);
+ SVal getCStringLength(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, SVal Buf);
+
+ const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state,
+ const Expr *Ex, SVal V);
+
+ bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR);
+
+ // Re-usable checks
+ const GRState *checkNonNull(CheckerContext &C, const GRState *state,
+ const Expr *S, SVal l);
+ const GRState *CheckLocation(CheckerContext &C, const GRState *state,
+ const Expr *S, SVal l,
+ bool IsDestination = false);
+ const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
+ const Expr *Size,
+ const Expr *FirstBuf,
+ const Expr *SecondBuf = NULL,
+ bool FirstIsDestination = false);
+ const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
+ const Expr *Size, const Expr *First,
+ const Expr *Second);
+ void emitOverlapBug(CheckerContext &C, const GRState *state,
+ const Stmt *First, const Stmt *Second);
+};
+
+class CStringLength {
+public:
+ typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
+};
+} //end anonymous namespace
+
+namespace clang {
+namespace ento {
+ template <>
+ struct GRStateTrait<CStringLength>
+ : public GRStatePartialTrait<CStringLength::EntryMap> {
+ static void *GDMIndex() { return CStringChecker::getTag(); }
+ };
+}
+}
+
+static void RegisterCStringChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new CStringChecker());
+}
+
+void ento::registerCStringChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterCStringChecker);
+}
+
+//===----------------------------------------------------------------------===//
+// Individual checks and utility methods.
+//===----------------------------------------------------------------------===//
+
+std::pair<const GRState*, const GRState*>
+CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V,
+ QualType Ty) {
+ DefinedSVal *val = dyn_cast<DefinedSVal>(&V);
+ if (!val)
+ return std::pair<const GRState*, const GRState *>(state, state);
+
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
+ return state->assume(svalBuilder.evalEQ(state, *val, zero));
+}
+
+const GRState *CStringChecker::checkNonNull(CheckerContext &C,
+ const GRState *state,
+ const Expr *S, SVal l) {
+ // If a previous check has failed, propagate the failure.
+ if (!state)
+ return NULL;
+
+ const GRState *stateNull, *stateNonNull;
+ llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
+
+ if (stateNull && !stateNonNull) {
+ ExplodedNode *N = C.generateSink(stateNull);
+ if (!N)
+ return NULL;
+
+ if (!BT_Null)
+ BT_Null = new BuiltinBug("API",
+ "Null pointer argument in call to byte string function");
+
+ // Generate a report for this bug.
+ BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
+ EnhancedBugReport *report = new EnhancedBugReport(*BT,
+ BT->getDescription(), N);
+
+ report->addRange(S->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
+ C.EmitReport(report);
+ return NULL;
+ }
+
+ // From here on, assume that the value is non-null.
+ assert(stateNonNull);
+ return stateNonNull;
+}
+
+// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
+const GRState *CStringChecker::CheckLocation(CheckerContext &C,
+ const GRState *state,
+ const Expr *S, SVal l,
+ bool IsDestination) {
+ // If a previous check has failed, propagate the failure.
+ if (!state)
+ return NULL;
+
+ // Check for out of bound array element access.
+ const MemRegion *R = l.getAsRegion();
+ if (!R)
+ return state;
+
+ const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+ if (!ER)
+ return state;
+
+ assert(ER->getValueType() == C.getASTContext().CharTy &&
+ "CheckLocation should only be called with char* ElementRegions");
+
+ // Get the size of the array.
+ const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
+ DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
+
+ // Get the index of the accessed element.
+ DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+ const GRState *StInBound = state->assumeInBound(Idx, Size, true);
+ const GRState *StOutBound = state->assumeInBound(Idx, Size, false);
+ if (StOutBound && !StInBound) {
+ ExplodedNode *N = C.generateSink(StOutBound);
+ if (!N)
+ return NULL;
+
+ BuiltinBug *BT;
+ if (IsDestination) {
+ if (!BT_BoundsWrite) {
+ BT_BoundsWrite = new BuiltinBug("Out-of-bound array access",
+ "Byte string function overflows destination buffer");
+ }
+ BT = static_cast<BuiltinBug*>(BT_BoundsWrite);
+ } else {
+ if (!BT_Bounds) {
+ BT_Bounds = new BuiltinBug("Out-of-bound array access",
+ "Byte string function accesses out-of-bound array element");
+ }
+ BT = static_cast<BuiltinBug*>(BT_Bounds);
+ }
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+
+ // Generate a report for this bug.
+ RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(S->getSourceRange());
+ C.EmitReport(report);
+ return NULL;
+ }
+
+ // Array bound check succeeded. From this point forward the array bound
+ // should always succeed.
+ return StInBound;
+}
+
+const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
+ const GRState *state,
+ const Expr *Size,
+ const Expr *FirstBuf,
+ const Expr *SecondBuf,
+ bool FirstIsDestination) {
+ // If a previous check has failed, propagate the failure.
+ if (!state)
+ return NULL;
+
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ ASTContext &Ctx = C.getASTContext();
+
+ QualType sizeTy = Size->getType();
+ QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
+
+ // Check that the first buffer is non-null.
+ SVal BufVal = state->getSVal(FirstBuf);
+ state = checkNonNull(C, state, FirstBuf, BufVal);
+ if (!state)
+ return NULL;
+
+ // Get the access length and make sure it is known.
+ SVal LengthVal = state->getSVal(Size);
+ NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
+ if (!Length)
+ return state;
+
+ // Compute the offset of the last element to be accessed: size-1.
+ NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
+ NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub,
+ *Length, One, sizeTy));
+
+ // Check that the first buffer is sufficently long.
+ SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
+ if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+ SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
+ LastOffset, PtrTy);
+ state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination);
+
+ // If the buffer isn't large enough, abort.
+ if (!state)
+ return NULL;
+ }
+
+ // If there's a second buffer, check it as well.
+ if (SecondBuf) {
+ BufVal = state->getSVal(SecondBuf);
+ state = checkNonNull(C, state, SecondBuf, BufVal);
+ if (!state)
+ return NULL;
+
+ BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());
+ if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+ SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
+ LastOffset, PtrTy);
+ state = CheckLocation(C, state, SecondBuf, BufEnd);
+ }
+ }
+
+ // Large enough or not, return this state!
+ return state;
+}
+
+const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
+ const GRState *state,
+ const Expr *Size,
+ const Expr *First,
+ const Expr *Second) {
+ // Do a simple check for overlap: if the two arguments are from the same
+ // buffer, see if the end of the first is greater than the start of the second
+ // or vice versa.
+
+ // If a previous check has failed, propagate the failure.
+ if (!state)
+ return NULL;
+
+ const GRState *stateTrue, *stateFalse;
+
+ // Get the buffer values and make sure they're known locations.
+ SVal firstVal = state->getSVal(First);
+ SVal secondVal = state->getSVal(Second);
+
+ Loc *firstLoc = dyn_cast<Loc>(&firstVal);
+ if (!firstLoc)
+ return state;
+
+ Loc *secondLoc = dyn_cast<Loc>(&secondVal);
+ if (!secondLoc)
+ return state;
+
+ // Are the two values the same?
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
+
+ if (stateTrue && !stateFalse) {
+ // If the values are known to be equal, that's automatically an overlap.
+ emitOverlapBug(C, stateTrue, First, Second);
+ return NULL;
+ }
+
+ // assume the two expressions are not equal.
+ assert(stateFalse);
+ state = stateFalse;
+
+ // Which value comes first?
+ ASTContext &Ctx = svalBuilder.getContext();
+ QualType cmpTy = Ctx.IntTy;
+ SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
+ *firstLoc, *secondLoc, cmpTy);
+ DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse);
+ if (!reverseTest)
+ return state;
+
+ llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
+ if (stateTrue) {
+ if (stateFalse) {
+ // If we don't know which one comes first, we can't perform this test.
+ return state;
+ } else {
+ // Switch the values so that firstVal is before secondVal.
+ Loc *tmpLoc = firstLoc;
+ firstLoc = secondLoc;
+ secondLoc = tmpLoc;
+
+ // Switch the Exprs as well, so that they still correspond.
+ const Expr *tmpExpr = First;
+ First = Second;
+ Second = tmpExpr;
+ }
+ }
+
+ // Get the length, and make sure it too is known.
+ SVal LengthVal = state->getSVal(Size);
+ NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
+ if (!Length)
+ return state;
+
+ // Convert the first buffer's start address to char*.
+ // Bail out if the cast fails.
+ QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
+ SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, First->getType());
+ Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
+ if (!FirstStartLoc)
+ return state;
+
+ // Compute the end of the first buffer. Bail out if THAT fails.
+ SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
+ *FirstStartLoc, *Length, CharPtrTy);
+ Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
+ if (!FirstEndLoc)
+ return state;
+
+ // Is the end of the first buffer past the start of the second buffer?
+ SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
+ *FirstEndLoc, *secondLoc, cmpTy);
+ DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
+ if (!OverlapTest)
+ return state;
+
+ llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
+
+ if (stateTrue && !stateFalse) {
+ // Overlap!
+ emitOverlapBug(C, stateTrue, First, Second);
+ return NULL;
+ }
+
+ // assume the two expressions don't overlap.
+ assert(stateFalse);
+ return stateFalse;
+}
+
+void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
+ const Stmt *First, const Stmt *Second) {
+ ExplodedNode *N = C.generateSink(state);
+ if (!N)
+ return;
+
+ if (!BT_Overlap)
+ BT_Overlap = new BugType("Unix API", "Improper arguments");
+
+ // Generate a report for this bug.
+ RangedBugReport *report =
+ new RangedBugReport(*BT_Overlap,
+ "Arguments must not be overlapping buffers", N);
+ report->addRange(First->getSourceRange());
+ report->addRange(Second->getSourceRange());
+
+ C.EmitReport(report);
+}
+
+const GRState *CStringChecker::setCStringLength(const GRState *state,
+ const MemRegion *MR,
+ SVal strLength) {
+ assert(!strLength.isUndef() && "Attempt to set an undefined string length");
+ if (strLength.isUnknown())
+ return state;
+
+ MR = MR->StripCasts();
+
+ switch (MR->getKind()) {
+ case MemRegion::StringRegionKind:
+ // FIXME: This can happen if we strcpy() into a string region. This is
+ // undefined [C99 6.4.5p6], but we should still warn about it.
+ return state;
+
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ return state->set<CStringLength>(MR, strLength);
+
+ case MemRegion::ElementRegionKind:
+ // FIXME: Handle element regions by upper-bounding the parent region's
+ // string length.
+ return state;
+
+ default:
+ // Other regions (mostly non-data) can't have a reliable C string length.
+ // For now, just ignore the change.
+ // FIXME: These are rare but not impossible. We should output some kind of
+ // warning for things like strcpy((char[]){'a', 0}, "b");
+ return state;
+ }
+}
+
+SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
+ const GRState *&state,
+ const Expr *Ex,
+ const MemRegion *MR) {
+ // If there's a recorded length, go ahead and return it.
+ const SVal *Recorded = state->get<CStringLength>(MR);
+ if (Recorded)
+ return *Recorded;
+
+ // Otherwise, get a new symbol and update the state.
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ QualType sizeTy = svalBuilder.getContext().getSizeType();
+ SVal strLength = svalBuilder.getMetadataSymbolVal(getTag(), MR, Ex, sizeTy, Count);
+ state = state->set<CStringLength>(MR, strLength);
+ return strLength;
+}
+
+SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, SVal Buf) {
+ const MemRegion *MR = Buf.getAsRegion();
+ if (!MR) {
+ // If we can't get a region, see if it's something we /know/ isn't a
+ // C string. In the context of locations, the only time we can issue such
+ // a warning is for labels.
+ if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
+ if (ExplodedNode *N = C.generateNode(state)) {
+ if (!BT_NotCString)
+ BT_NotCString = new BuiltinBug("API",
+ "Argument is not a null-terminated string.");
+
+ llvm::SmallString<120> buf;
+ llvm::raw_svector_ostream os(buf);
+ os << "Argument to byte string function is the address of the label '"
+ << Label->getLabel()->getName()
+ << "', which is not a null-terminated string";
+
+ // Generate a report for this bug.
+ EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+ os.str(), N);
+
+ report->addRange(Ex->getSourceRange());
+ C.EmitReport(report);
+ }
+
+ return UndefinedVal();
+ }
+
+ // If it's not a region and not a label, give up.
+ return UnknownVal();
+ }
+
+ // If we have a region, strip casts from it and see if we can figure out
+ // its length. For anything we can't figure out, just return UnknownVal.
+ MR = MR->StripCasts();
+
+ switch (MR->getKind()) {
+ case MemRegion::StringRegionKind: {
+ // Modifying the contents of string regions is undefined [C99 6.4.5p6],
+ // so we can assume that the byte length is the correct C string length.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ QualType sizeTy = svalBuilder.getContext().getSizeType();
+ const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
+ return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy);
+ }
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ return getCStringLengthForRegion(C, state, Ex, MR);
+ case MemRegion::CompoundLiteralRegionKind:
+ // FIXME: Can we track this? Is it necessary?
+ return UnknownVal();
+ case MemRegion::ElementRegionKind:
+ // FIXME: How can we handle this? It's not good enough to subtract the
+ // offset from the base string length; consider "123\x00567" and &a[5].
+ return UnknownVal();
+ default:
+ // Other regions (mostly non-data) can't have a reliable C string length.
+ // In this case, an error is emitted and UndefinedVal is returned.
+ // The caller should always be prepared to handle this case.
+ if (ExplodedNode *N = C.generateNode(state)) {
+ if (!BT_NotCString)
+ BT_NotCString = new BuiltinBug("API",
+ "Argument is not a null-terminated string.");
+
+ llvm::SmallString<120> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "Argument to byte string function is ";
+
+ if (SummarizeRegion(os, C.getASTContext(), MR))
+ os << ", which is not a null-terminated string";
+ else
+ os << "not a null-terminated string";
+
+ // Generate a report for this bug.
+ EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+ os.str(), N);
+
+ report->addRange(Ex->getSourceRange());
+ C.EmitReport(report);
+ }
+
+ return UndefinedVal();
+ }
+}
+
+const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C,
+ const GRState *state,
+ const Expr *E, SVal V) {
+ Loc *L = dyn_cast<Loc>(&V);
+ if (!L)
+ return state;
+
+ // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
+ // some assumptions about the value that CFRefCount can't. Even so, it should
+ // probably be refactored.
+ if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) {
+ const MemRegion *R = MR->getRegion()->StripCasts();
+
+ // Are we dealing with an ElementRegion? If so, we should be invalidating
+ // the super-region.
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ R = ER->getSuperRegion();
+ // FIXME: What about layers of ElementRegions?
+ }
+
+ // Invalidate this region.
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ return state->invalidateRegion(R, E, Count, NULL);
+ }
+
+ // If we have a non-region value by chance, just remove the binding.
+ // FIXME: is this necessary or correct? This handles the non-Region
+ // cases. Is it ever valid to store to these?
+ return state->unbindLoc(*L);
+}
+
+bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR) {
+ const TypedRegion *TR = dyn_cast<TypedRegion>(MR);
+ if (!TR)
+ return false;
+
+ switch (TR->getKind()) {
+ case MemRegion::FunctionTextRegionKind: {
+ const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl();
+ if (FD)
+ os << "the address of the function '" << FD << "'";
+ else
+ os << "the address of a function";
+ return true;
+ }
+ case MemRegion::BlockTextRegionKind:
+ os << "block text";
+ return true;
+ case MemRegion::BlockDataRegionKind:
+ os << "a block";
+ return true;
+ case MemRegion::CXXThisRegionKind:
+ case MemRegion::CXXTempObjectRegionKind:
+ os << "a C++ temp object of type " << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::VarRegionKind:
+ os << "a variable of type" << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::FieldRegionKind:
+ os << "a field of type " << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::ObjCIvarRegionKind:
+ os << "an instance variable of type " << TR->getValueType().getAsString();
+ return true;
+ default:
+ return false;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// evaluation of individual function calls.
+//===----------------------------------------------------------------------===//
+
+void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
+ const Expr *Size, const Expr *Dest,
+ const Expr *Source, bool Restricted) {
+ // See if the size argument is zero.
+ SVal sizeVal = state->getSVal(Size);
+ QualType sizeTy = Size->getType();
+
+ const GRState *stateZeroSize, *stateNonZeroSize;
+ llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy);
+
+ // If the size is zero, there won't be any actual memory access.
+ if (stateZeroSize)
+ C.addTransition(stateZeroSize);
+
+ // If the size can be nonzero, we have to check the other arguments.
+ if (stateNonZeroSize) {
+ state = stateNonZeroSize;
+ state = CheckBufferAccess(C, state, Size, Dest, Source,
+ /* FirstIsDst = */ true);
+ if (Restricted)
+ state = CheckOverlap(C, state, Size, Dest, Source);
+
+ if (state) {
+ // Invalidate the destination.
+ // FIXME: Even if we can't perfectly model the copy, we should see if we
+ // can use LazyCompoundVals to copy the source values into the destination.
+ // This would probably remove any existing bindings past the end of the
+ // copied region, but that's still an improvement over blank invalidation.
+ state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest));
+ C.addTransition(state);
+ }
+ }
+}
+
+
+void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
+ // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
+ // The return value is the address of the destination buffer.
+ const Expr *Dest = CE->getArg(0);
+ const GRState *state = C.getState();
+ state = state->BindExpr(CE, state->getSVal(Dest));
+ evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
+}
+
+void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
+ // void *memmove(void *dst, const void *src, size_t n);
+ // The return value is the address of the destination buffer.
+ const Expr *Dest = CE->getArg(0);
+ const GRState *state = C.getState();
+ state = state->BindExpr(CE, state->getSVal(Dest));
+ evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
+}
+
+void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) {
+ // void bcopy(const void *src, void *dst, size_t n);
+ evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
+}
+
+void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
+ // int memcmp(const void *s1, const void *s2, size_t n);
+ const Expr *Left = CE->getArg(0);
+ const Expr *Right = CE->getArg(1);
+ const Expr *Size = CE->getArg(2);
+
+ const GRState *state = C.getState();
+ SValBuilder &svalBuilder = C.getSValBuilder();
+
+ // See if the size argument is zero.
+ SVal sizeVal = state->getSVal(Size);
+ QualType sizeTy = Size->getType();
+
+ const GRState *stateZeroSize, *stateNonZeroSize;
+ llvm::tie(stateZeroSize, stateNonZeroSize) =
+ assumeZero(C, state, sizeVal, sizeTy);
+
+ // If the size can be zero, the result will be 0 in that case, and we don't
+ // have to check either of the buffers.
+ if (stateZeroSize) {
+ state = stateZeroSize;
+ state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+ C.addTransition(state);
+ }
+
+ // If the size can be nonzero, we have to check the other arguments.
+ if (stateNonZeroSize) {
+ state = stateNonZeroSize;
+ // If we know the two buffers are the same, we know the result is 0.
+ // First, get the two buffers' addresses. Another checker will have already
+ // made sure they're not undefined.
+ DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
+ DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
+
+ // See if they are the same.
+ DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
+ const GRState *StSameBuf, *StNotSameBuf;
+ llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
+
+ // If the two arguments might be the same buffer, we know the result is zero,
+ // and we only need to check one size.
+ if (StSameBuf) {
+ state = StSameBuf;
+ state = CheckBufferAccess(C, state, Size, Left);
+ if (state) {
+ state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+ C.addTransition(state);
+ }
+ }
+
+ // If the two arguments might be different buffers, we have to check the
+ // size of both of them.
+ if (StNotSameBuf) {
+ state = StNotSameBuf;
+ state = CheckBufferAccess(C, state, Size, Left, Right);
+ if (state) {
+ // The return value is the comparison result, which we don't know.
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
+ state = state->BindExpr(CE, CmpV);
+ C.addTransition(state);
+ }
+ }
+ }
+}
+
+void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
+ // size_t strlen(const char *s);
+ const GRState *state = C.getState();
+ const Expr *Arg = CE->getArg(0);
+ SVal ArgVal = state->getSVal(Arg);
+
+ // Check that the argument is non-null.
+ state = checkNonNull(C, state, Arg, ArgVal);
+
+ if (state) {
+ SVal strLength = getCStringLength(C, state, Arg, ArgVal);
+
+ // If the argument isn't a valid C string, there's no valid state to
+ // transition to.
+ if (strLength.isUndef())
+ return;
+
+ // If getCStringLength couldn't figure out the length, conjure a return
+ // value, so it can be used in constraints, at least.
+ if (strLength.isUnknown()) {
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ strLength = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count);
+ }
+
+ // Bind the return value.
+ state = state->BindExpr(CE, strLength);
+ C.addTransition(state);
+ }
+}
+
+void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) {
+ // char *strcpy(char *restrict dst, const char *restrict src);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false);
+}
+
+void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) {
+ // char *stpcpy(char *restrict dst, const char *restrict src);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ true);
+}
+
+void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
+ bool returnEnd) {
+ const GRState *state = C.getState();
+
+ // Check that the destination is non-null
+ const Expr *Dst = CE->getArg(0);
+ SVal DstVal = state->getSVal(Dst);
+
+ state = checkNonNull(C, state, Dst, DstVal);
+ if (!state)
+ return;
+
+ // Check that the source is non-null.
+ const Expr *srcExpr = CE->getArg(1);
+ SVal srcVal = state->getSVal(srcExpr);
+ state = checkNonNull(C, state, srcExpr, srcVal);
+ if (!state)
+ return;
+
+ // Get the string length of the source.
+ SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
+
+ // If the source isn't a valid C string, give up.
+ if (strLength.isUndef())
+ return;
+
+ SVal Result = (returnEnd ? UnknownVal() : DstVal);
+
+ // If the destination is a MemRegion, try to check for a buffer overflow and
+ // record the new string length.
+ if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) {
+ // If the length is known, we can check for an overflow.
+ if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&strLength)) {
+ SVal lastElement =
+ C.getSValBuilder().evalBinOpLN(state, BO_Add, *dstRegVal,
+ *knownStrLength, Dst->getType());
+
+ state = CheckLocation(C, state, Dst, lastElement, /* IsDst = */ true);
+ if (!state)
+ return;
+
+ // If this is a stpcpy-style copy, the last element is the return value.
+ if (returnEnd)
+ Result = lastElement;
+ }
+
+ // Invalidate the destination. This must happen before we set the C string
+ // length because invalidation will clear the length.
+ // FIXME: Even if we can't perfectly model the copy, we should see if we
+ // can use LazyCompoundVals to copy the source values into the destination.
+ // This would probably remove any existing bindings past the end of the
+ // string, but that's still an improvement over blank invalidation.
+ state = InvalidateBuffer(C, state, Dst, *dstRegVal);
+
+ // Set the C string length of the destination.
+ state = setCStringLength(state, dstRegVal->getRegion(), strLength);
+ }
+
+ // If this is a stpcpy-style copy, but we were unable to check for a buffer
+ // overflow, we still need a result. Conjure a return value.
+ if (returnEnd && Result.isUnknown()) {
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ strLength = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
+ }
+
+ // Set the return value.
+ state = state->BindExpr(CE, Result);
+ C.addTransition(state);
+}
+
+//===----------------------------------------------------------------------===//
+// The driver method, and other Checker callbacks.
+//===----------------------------------------------------------------------===//
+
+bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ // Get the callee. All the functions we care about are C functions
+ // with simple identifiers.
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
+
+ if (!FD)
+ return false;
+
+ // Get the name of the callee. If it's a builtin, strip off the prefix.
+ IdentifierInfo *II = FD->getIdentifier();
+ if (!II) // if no identifier, not a simple C function
+ return false;
+ llvm::StringRef Name = II->getName();
+ if (Name.startswith("__builtin_"))
+ Name = Name.substr(10);
+
+ FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
+ .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy)
+ .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp)
+ .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove)
+ .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy)
+ .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy)
+ .Case("strlen", &CStringChecker::evalstrLength)
+ .Case("bcopy", &CStringChecker::evalBcopy)
+ .Default(NULL);
+
+ // If the callee isn't a string function, let another checker handle it.
+ if (!evalFunction)
+ return false;
+
+ // Check and evaluate the call.
+ (this->*evalFunction)(C, CE);
+ return true;
+}
+
+void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+ // Record string length for char a[] = "abc";
+ const GRState *state = C.getState();
+
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+ I != E; ++I) {
+ const VarDecl *D = dyn_cast<VarDecl>(*I);
+ if (!D)
+ continue;
+
+ // FIXME: Handle array fields of structs.
+ if (!D->getType()->isArrayType())
+ continue;
+
+ const Expr *Init = D->getInit();
+ if (!Init)
+ continue;
+ if (!isa<StringLiteral>(Init))
+ continue;
+
+ Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext());
+ const MemRegion *MR = VarLoc.getAsRegion();
+ if (!MR)
+ continue;
+
+ SVal StrVal = state->getSVal(Init);
+ assert(StrVal.isValid() && "Initializer string is unknown or undefined");
+ DefinedOrUnknownSVal strLength
+ = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal));
+
+ state = state->set<CStringLength>(MR, strLength);
+ }
+
+ C.addTransition(state);
+}
+
+bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) {
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ return !Entries.isEmpty();
+}
+
+const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool *) {
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ if (Entries.isEmpty())
+ return state;
+
+ llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
+ llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
+
+ // First build sets for the changed regions and their super-regions.
+ for ( ; Begin != End; ++Begin) {
+ const MemRegion *MR = *Begin;
+ Invalidated.insert(MR);
+
+ SuperRegions.insert(MR);
+ while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
+ MR = SR->getSuperRegion();
+ SuperRegions.insert(MR);
+ }
+ }
+
+ CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+
+ // Then loop over the entries in the current state.
+ for (CStringLength::EntryMap::iterator I = Entries.begin(),
+ E = Entries.end(); I != E; ++I) {
+ const MemRegion *MR = I.getKey();
+
+ // Is this entry for a super-region of a changed region?
+ if (SuperRegions.count(MR)) {
+ Entries = F.remove(Entries, MR);
+ continue;
+ }
+
+ // Is this entry for a sub-region of a changed region?
+ const MemRegion *Super = MR;
+ while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
+ Super = SR->getSuperRegion();
+ if (Invalidated.count(Super)) {
+ Entries = F.remove(Entries, MR);
+ break;
+ }
+ }
+ }
+
+ return state->set<CStringLength>(Entries);
+}
+
+void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
+ // Mark all symbols in our string length map as valid.
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+
+ for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ SVal Len = I.getData();
+ if (SymbolRef Sym = Len.getAsSymbol())
+ SR.markInUse(Sym);
+ }
+}
+
+void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
+ if (!SR.hasDeadSymbols())
+ return;
+
+ const GRState *state = C.getState();
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ if (Entries.isEmpty())
+ return;
+
+ CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+ for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ SVal Len = I.getData();
+ if (SymbolRef Sym = Len.getAsSymbol()) {
+ if (SR.isDead(Sym))
+ Entries = F.remove(Entries, I.getKey());
+ }
+ }
+
+ state = state->set<CStringLength>(Entries);
+ C.generateNode(state);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
new file mode 100644
index 0000000..415900e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -0,0 +1,358 @@
+//===--- CallAndMessageChecker.cpp ------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines CallAndMessageChecker, a builtin checker that checks for various
+// errors of call and objc message expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CallAndMessageChecker
+ : public CheckerVisitor<CallAndMessageChecker> {
+ BugType *BT_call_null;
+ BugType *BT_call_undef;
+ BugType *BT_call_arg;
+ BugType *BT_msg_undef;
+ BugType *BT_msg_arg;
+ BugType *BT_msg_ret;
+public:
+ CallAndMessageChecker() :
+ BT_call_null(0), BT_call_undef(0), BT_call_arg(0),
+ BT_msg_undef(0), BT_msg_arg(0), BT_msg_ret(0) {}
+
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ bool evalNilReceiver(CheckerContext &C, ObjCMessage msg);
+
+private:
+ void PreVisitProcessArgs(CheckerContext &C, CallOrObjCMessage callOrMsg,
+ const char *BT_desc, BugType *&BT);
+ bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange argRange,
+ const Expr *argEx, const char *BT_desc, BugType *&BT);
+
+ void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
+ void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
+ ExplodedNode *N);
+
+ void HandleNilReceiver(CheckerContext &C, const GRState *state,
+ ObjCMessage msg);
+
+ void LazyInit_BT(const char *desc, BugType *&BT) {
+ if (!BT)
+ BT = new BuiltinBug(desc);
+ }
+};
+} // end anonymous namespace
+
+void ento::RegisterCallAndMessageChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new CallAndMessageChecker());
+}
+
+void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C,
+ const CallExpr *CE) {
+ ExplodedNode *N = C.generateSink();
+ if (!N)
+ return;
+
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetCalleeExpr(N));
+ C.EmitReport(R);
+}
+
+void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
+ CallOrObjCMessage callOrMsg,
+ const char *BT_desc,
+ BugType *&BT) {
+ for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
+ if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
+ callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
+ BT_desc, BT))
+ return;
+}
+
+bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
+ SVal V, SourceRange argRange,
+ const Expr *argEx,
+ const char *BT_desc,
+ BugType *&BT) {
+
+ if (V.isUndef()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ LazyInit_BT(BT_desc, BT);
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+ R->addRange(argRange);
+ if (argEx)
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx);
+ C.EmitReport(R);
+ }
+ return true;
+ }
+
+ if (const nonloc::LazyCompoundVal *LV =
+ dyn_cast<nonloc::LazyCompoundVal>(&V)) {
+
+ class FindUninitializedField {
+ public:
+ llvm::SmallVector<const FieldDecl *, 10> FieldChain;
+ private:
+ ASTContext &C;
+ StoreManager &StoreMgr;
+ MemRegionManager &MrMgr;
+ Store store;
+ public:
+ FindUninitializedField(ASTContext &c, StoreManager &storeMgr,
+ MemRegionManager &mrMgr, Store s)
+ : C(c), StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
+
+ bool Find(const TypedRegion *R) {
+ QualType T = R->getValueType();
+ if (const RecordType *RT = T->getAsStructureType()) {
+ const RecordDecl *RD = RT->getDecl()->getDefinition();
+ assert(RD && "Referred record has no definition");
+ for (RecordDecl::field_iterator I =
+ RD->field_begin(), E = RD->field_end(); I!=E; ++I) {
+ const FieldRegion *FR = MrMgr.getFieldRegion(*I, R);
+ FieldChain.push_back(*I);
+ T = (*I)->getType();
+ if (T->getAsStructureType()) {
+ if (Find(FR))
+ return true;
+ }
+ else {
+ const SVal &V = StoreMgr.Retrieve(store, loc::MemRegionVal(FR));
+ if (V.isUndef())
+ return true;
+ }
+ FieldChain.pop_back();
+ }
+ }
+
+ return false;
+ }
+ };
+
+ const LazyCompoundValData *D = LV->getCVData();
+ FindUninitializedField F(C.getASTContext(),
+ C.getState()->getStateManager().getStoreManager(),
+ C.getSValBuilder().getRegionManager(),
+ D->getStore());
+
+ if (F.Find(D->getRegion())) {
+ if (ExplodedNode *N = C.generateSink()) {
+ LazyInit_BT(BT_desc, BT);
+ llvm::SmallString<512> Str;
+ llvm::raw_svector_ostream os(Str);
+ os << "Passed-by-value struct argument contains uninitialized data";
+
+ if (F.FieldChain.size() == 1)
+ os << " (e.g., field: '" << F.FieldChain[0] << "')";
+ else {
+ os << " (e.g., via the field chain: '";
+ bool first = true;
+ for (llvm::SmallVectorImpl<const FieldDecl *>::iterator
+ DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
+ if (first)
+ first = false;
+ else
+ os << '.';
+ os << *DI;
+ }
+ os << "')";
+ }
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, os.str(), N);
+ R->addRange(argRange);
+
+ // FIXME: enhance track back for uninitialized value for arbitrary
+ // memregions
+ C.EmitReport(R);
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CallAndMessageChecker::PreVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE){
+
+ const Expr *Callee = CE->getCallee()->IgnoreParens();
+ SVal L = C.getState()->getSVal(Callee);
+
+ if (L.isUndef()) {
+ if (!BT_call_undef)
+ BT_call_undef =
+ new BuiltinBug("Called function pointer is an uninitalized pointer value");
+ EmitBadCall(BT_call_undef, C, CE);
+ return;
+ }
+
+ if (isa<loc::ConcreteInt>(L)) {
+ if (!BT_call_null)
+ BT_call_null =
+ new BuiltinBug("Called function pointer is null (null dereference)");
+ EmitBadCall(BT_call_null, C, CE);
+ }
+
+ PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()),
+ "Function call argument is an uninitialized value",
+ BT_call_arg);
+}
+
+void CallAndMessageChecker::preVisitObjCMessage(CheckerContext &C,
+ ObjCMessage msg) {
+
+ const GRState *state = C.getState();
+
+ // FIXME: Handle 'super'?
+ if (const Expr *receiver = msg.getInstanceReceiver())
+ if (state->getSVal(receiver).isUndef()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_msg_undef)
+ BT_msg_undef =
+ new BuiltinBug("Receiver in message expression is an uninitialized value");
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
+ R->addRange(receiver->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ receiver);
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ const char *bugDesc = msg.isPropertySetter() ?
+ "Argument for property setter is an uninitialized value"
+ : "Argument in message expression is an uninitialized value";
+ // Check for any arguments that are uninitialized/undefined.
+ PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg);
+}
+
+bool CallAndMessageChecker::evalNilReceiver(CheckerContext &C,
+ ObjCMessage msg) {
+ HandleNilReceiver(C, C.getState(), msg);
+ return true; // Nil receiver is not handled elsewhere.
+}
+
+void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
+ const ObjCMessage &msg,
+ ExplodedNode *N) {
+
+ if (!BT_msg_ret)
+ BT_msg_ret =
+ new BuiltinBug("Receiver in message expression is "
+ "'nil' and returns a garbage value");
+
+ llvm::SmallString<200> buf;
+ llvm::raw_svector_ostream os(buf);
+ os << "The receiver of message '" << msg.getSelector().getAsString()
+ << "' is nil and returns a value of type '"
+ << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";
+
+ EnhancedBugReport *report = new EnhancedBugReport(*BT_msg_ret, os.str(), N);
+ if (const Expr *receiver = msg.getInstanceReceiver()) {
+ report->addRange(receiver->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ receiver);
+ }
+ C.EmitReport(report);
+}
+
+static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
+ return triple.getVendor() == llvm::Triple::Apple &&
+ (triple.getDarwinMajorNumber() >= 9 ||
+ triple.getArch() == llvm::Triple::arm ||
+ triple.getArch() == llvm::Triple::thumb);
+}
+
+void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
+ const GRState *state,
+ ObjCMessage msg) {
+ ASTContext &Ctx = C.getASTContext();
+
+ // Check the return type of the message expression. A message to nil will
+ // return different values depending on the return type and the architecture.
+ QualType RetTy = msg.getType(Ctx);
+
+ CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
+
+ if (CanRetTy->isStructureOrClassType()) {
+ // FIXME: At some point we shouldn't rely on isConsumedExpr(), but instead
+ // have the "use of undefined value" be smarter about where the
+ // undefined value came from.
+ if (C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())){
+ if (ExplodedNode* N = C.generateSink(state))
+ emitNilReceiverBug(C, msg, N);
+ return;
+ }
+
+ // The result is not consumed by a surrounding expression. Just propagate
+ // the current state.
+ C.addTransition(state);
+ return;
+ }
+
+ // Other cases: check if the return type is smaller than void*.
+ if (CanRetTy != Ctx.VoidTy &&
+ C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())) {
+ // Compute: sizeof(void *) and sizeof(return type)
+ const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
+ const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
+
+ if (voidPtrSize < returnTypeSize &&
+ !(supportsNilWithFloatRet(Ctx.Target.getTriple()) &&
+ (Ctx.FloatTy == CanRetTy ||
+ Ctx.DoubleTy == CanRetTy ||
+ Ctx.LongDoubleTy == CanRetTy ||
+ Ctx.LongLongTy == CanRetTy ||
+ Ctx.UnsignedLongLongTy == CanRetTy))) {
+ if (ExplodedNode* N = C.generateSink(state))
+ emitNilReceiverBug(C, msg, N);
+ return;
+ }
+
+ // Handle the safe cases where the return value is 0 if the
+ // receiver is nil.
+ //
+ // FIXME: For now take the conservative approach that we only
+ // return null values if we *know* that the receiver is nil.
+ // This is because we can have surprises like:
+ //
+ // ... = [[NSScreens screens] objectAtIndex:0];
+ //
+ // What can happen is that [... screens] could return nil, but
+ // it most likely isn't nil. We should assume the semantics
+ // of this case unless we have *a lot* more knowledge.
+ //
+ SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
+ C.generateNode(state->BindExpr(msg.getOriginExpr(), V));
+ return;
+ }
+
+ C.addTransition(state);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
new file mode 100644
index 0000000..518cf96
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -0,0 +1,91 @@
+//=== CastSizeChecker.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CastSizeChecker checks when casting a malloc'ed symbolic region to type T,
+// whether the size of the symbolic region is a multiple of the size of T.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/CharUnits.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "InternalChecks.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
+ BuiltinBug *BT;
+public:
+ CastSizeChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+};
+}
+
+void *CastSizeChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+ ASTContext &Ctx = C.getASTContext();
+ QualType ToTy = Ctx.getCanonicalType(CE->getType());
+ const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+ if (!ToPTy)
+ return;
+
+ QualType ToPointeeTy = ToPTy->getPointeeType();
+
+ // Only perform the check if 'ToPointeeTy' is a complete type.
+ if (ToPointeeTy->isIncompleteType())
+ return;
+
+ const GRState *state = C.getState();
+ const MemRegion *R = state->getSVal(E).getAsRegion();
+ if (R == 0)
+ return;
+
+ const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+ if (SR == 0)
+ return;
+
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ SVal extent = SR->getExtent(svalBuilder);
+ const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
+ if (!extentInt)
+ return;
+
+ CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
+ CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
+
+ // Ignore void, and a few other un-sizeable types.
+ if (typeSize.isZero())
+ return;
+
+ if (regionSize % typeSize != 0) {
+ if (ExplodedNode *errorNode = C.generateSink()) {
+ if (!BT)
+ BT = new BuiltinBug("Cast region with wrong size.",
+ "Cast a region whose size is not a multiple of the"
+ " destination type size.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
+ errorNode);
+ R->addRange(CE->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+
+void ento::RegisterCastSizeChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new CastSizeChecker());
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
new file mode 100644
index 0000000..8ec226a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -0,0 +1,84 @@
+//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines CastToStructChecker, a builtin checker that checks for
+// cast from non-struct pointer to struct pointer.
+// This check corresponds to CWE-588.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CastToStructChecker
+ : public CheckerVisitor<CastToStructChecker> {
+ BuiltinBug *BT;
+public:
+ CastToStructChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+};
+}
+
+void *CastToStructChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
+ const CastExpr *CE) {
+ const Expr *E = CE->getSubExpr();
+ ASTContext &Ctx = C.getASTContext();
+ QualType OrigTy = Ctx.getCanonicalType(E->getType());
+ QualType ToTy = Ctx.getCanonicalType(CE->getType());
+
+ const PointerType *OrigPTy = dyn_cast<PointerType>(OrigTy.getTypePtr());
+ const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
+
+ if (!ToPTy || !OrigPTy)
+ return;
+
+ QualType OrigPointeeTy = OrigPTy->getPointeeType();
+ QualType ToPointeeTy = ToPTy->getPointeeType();
+
+ if (!ToPointeeTy->isStructureOrClassType())
+ return;
+
+ // We allow cast from void*.
+ if (OrigPointeeTy->isVoidType())
+ return;
+
+ // Now the cast-to-type is struct pointer, the original type is not void*.
+ if (!OrigPointeeTy->isRecordType()) {
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT)
+ BT = new BuiltinBug("Cast from non-struct type to struct type",
+ "Casting a non-structure type to a structure type "
+ "and accessing a field can lead to memory access "
+ "errors or data corruption.");
+ RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
+ R->addRange(CE->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+static void RegisterCastToStructChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new CastToStructChecker());
+}
+
+void ento::registerCastToStructChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterCastToStructChecker);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
new file mode 100644
index 0000000..ad3bab6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -0,0 +1,284 @@
+//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a CheckObjCDealloc, a checker that
+// analyzes an Objective-C class's implementation to determine if it
+// correctly implements -dealloc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool scan_dealloc(Stmt* S, Selector Dealloc) {
+
+ if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
+ if (ME->getSelector() == Dealloc) {
+ switch (ME->getReceiverKind()) {
+ case ObjCMessageExpr::Instance: return false;
+ case ObjCMessageExpr::SuperInstance: return true;
+ case ObjCMessageExpr::Class: break;
+ case ObjCMessageExpr::SuperClass: break;
+ }
+ }
+
+ // Recurse to children.
+
+ for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
+ if (*I && scan_dealloc(*I, Dealloc))
+ return true;
+
+ return false;
+}
+
+static bool scan_ivar_release(Stmt* S, ObjCIvarDecl* ID,
+ const ObjCPropertyDecl* PD,
+ Selector Release,
+ IdentifierInfo* SelfII,
+ ASTContext& Ctx) {
+
+ // [mMyIvar release]
+ if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
+ if (ME->getSelector() == Release)
+ if (ME->getInstanceReceiver())
+ if (Expr* Receiver = ME->getInstanceReceiver()->IgnoreParenCasts())
+ if (ObjCIvarRefExpr* E = dyn_cast<ObjCIvarRefExpr>(Receiver))
+ if (E->getDecl() == ID)
+ return true;
+
+ // [self setMyIvar:nil];
+ if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
+ if (ME->getInstanceReceiver())
+ if (Expr* Receiver = ME->getInstanceReceiver()->IgnoreParenCasts())
+ if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(Receiver))
+ if (E->getDecl()->getIdentifier() == SelfII)
+ if (ME->getMethodDecl() == PD->getSetterMethodDecl() &&
+ ME->getNumArgs() == 1 &&
+ ME->getArg(0)->isNullPointerConstant(Ctx,
+ Expr::NPC_ValueDependentIsNull))
+ return true;
+
+ // self.myIvar = nil;
+ if (BinaryOperator* BO = dyn_cast<BinaryOperator>(S))
+ if (BO->isAssignmentOp())
+ if (ObjCPropertyRefExpr* PRE =
+ dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParenCasts()))
+ if (PRE->isExplicitProperty() && PRE->getExplicitProperty() == PD)
+ if (BO->getRHS()->isNullPointerConstant(Ctx,
+ Expr::NPC_ValueDependentIsNull)) {
+ // This is only a 'release' if the property kind is not
+ // 'assign'.
+ return PD->getSetterKind() != ObjCPropertyDecl::Assign;;
+ }
+
+ // Recurse to children.
+ for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
+ if (*I && scan_ivar_release(*I, ID, PD, Release, SelfII, Ctx))
+ return true;
+
+ return false;
+}
+
+static void checkObjCDealloc(const ObjCImplementationDecl* D,
+ const LangOptions& LOpts, BugReporter& BR) {
+
+ assert (LOpts.getGCMode() != LangOptions::GCOnly);
+
+ ASTContext& Ctx = BR.getContext();
+ const ObjCInterfaceDecl* ID = D->getClassInterface();
+
+ // Does the class contain any ivars that are pointers (or id<...>)?
+ // If not, skip the check entirely.
+ // NOTE: This is motivated by PR 2517:
+ // http://llvm.org/bugs/show_bug.cgi?id=2517
+
+ bool containsPointerIvar = false;
+
+ for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
+ I!=E; ++I) {
+
+ ObjCIvarDecl* ID = *I;
+ QualType T = ID->getType();
+
+ if (!T->isObjCObjectPointerType() ||
+ ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
+ ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections.
+ continue;
+
+ containsPointerIvar = true;
+ break;
+ }
+
+ if (!containsPointerIvar)
+ return;
+
+ // Determine if the class subclasses NSObject.
+ IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+ IdentifierInfo* SenTestCaseII = &Ctx.Idents.get("SenTestCase");
+
+
+ for ( ; ID ; ID = ID->getSuperClass()) {
+ IdentifierInfo *II = ID->getIdentifier();
+
+ if (II == NSObjectII)
+ break;
+
+ // FIXME: For now, ignore classes that subclass SenTestCase, as these don't
+ // need to implement -dealloc. They implement tear down in another way,
+ // which we should try and catch later.
+ // http://llvm.org/bugs/show_bug.cgi?id=3187
+ if (II == SenTestCaseII)
+ return;
+ }
+
+ if (!ID)
+ return;
+
+ // Get the "dealloc" selector.
+ IdentifierInfo* II = &Ctx.Idents.get("dealloc");
+ Selector S = Ctx.Selectors.getSelector(0, &II);
+ ObjCMethodDecl* MD = 0;
+
+ // Scan the instance methods for "dealloc".
+ for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
+ E = D->instmeth_end(); I!=E; ++I) {
+
+ if ((*I)->getSelector() == S) {
+ MD = *I;
+ break;
+ }
+ }
+
+ if (!MD) { // No dealloc found.
+
+ const char* name = LOpts.getGCMode() == LangOptions::NonGC
+ ? "missing -dealloc"
+ : "missing -dealloc (Hybrid MM, non-GC)";
+
+ std::string buf;
+ llvm::raw_string_ostream os(buf);
+ os << "Objective-C class '" << D << "' lacks a 'dealloc' instance method";
+
+ BR.EmitBasicReport(name, os.str(), D->getLocStart());
+ return;
+ }
+
+ // dealloc found. Scan for missing [super dealloc].
+ if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {
+
+ const char* name = LOpts.getGCMode() == LangOptions::NonGC
+ ? "missing [super dealloc]"
+ : "missing [super dealloc] (Hybrid MM, non-GC)";
+
+ std::string buf;
+ llvm::raw_string_ostream os(buf);
+ os << "The 'dealloc' instance method in Objective-C class '" << D
+ << "' does not send a 'dealloc' message to its super class"
+ " (missing [super dealloc])";
+
+ BR.EmitBasicReport(name, os.str(), D->getLocStart());
+ return;
+ }
+
+ // Get the "release" selector.
+ IdentifierInfo* RII = &Ctx.Idents.get("release");
+ Selector RS = Ctx.Selectors.getSelector(0, &RII);
+
+ // Get the "self" identifier
+ IdentifierInfo* SelfII = &Ctx.Idents.get("self");
+
+ // Scan for missing and extra releases of ivars used by implementations
+ // of synthesized properties
+ for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
+ E = D->propimpl_end(); I!=E; ++I) {
+
+ // We can only check the synthesized properties
+ if ((*I)->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
+ continue;
+
+ ObjCIvarDecl* ID = (*I)->getPropertyIvarDecl();
+ if (!ID)
+ continue;
+
+ QualType T = ID->getType();
+ if (!T->isObjCObjectPointerType()) // Skip non-pointer ivars
+ continue;
+
+ const ObjCPropertyDecl* PD = (*I)->getPropertyDecl();
+ if (!PD)
+ continue;
+
+ // ivars cannot be set via read-only properties, so we'll skip them
+ if (PD->isReadOnly())
+ continue;
+
+ // ivar must be released if and only if the kind of setter was not 'assign'
+ bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign;
+ if (scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx)
+ != requiresRelease) {
+ const char *name;
+ const char* category = "Memory (Core Foundation/Objective-C)";
+
+ std::string buf;
+ llvm::raw_string_ostream os(buf);
+
+ if (requiresRelease) {
+ name = LOpts.getGCMode() == LangOptions::NonGC
+ ? "missing ivar release (leak)"
+ : "missing ivar release (Hybrid MM, non-GC)";
+
+ os << "The '" << ID
+ << "' instance variable was retained by a synthesized property but "
+ "wasn't released in 'dealloc'";
+ } else {
+ name = LOpts.getGCMode() == LangOptions::NonGC
+ ? "extra ivar release (use-after-release)"
+ : "extra ivar release (Hybrid MM, non-GC)";
+
+ os << "The '" << ID
+ << "' instance variable was not retained by a synthesized property "
+ "but was released in 'dealloc'";
+ }
+
+ BR.EmitBasicReport(name, category, os.str(), (*I)->getLocation());
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCDeallocChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCDeallocChecker : public CheckerV2<
+ check::ASTDecl<ObjCImplementationDecl> > {
+public:
+ void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
+ return;
+ checkObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
+ }
+};
+}
+
+void ento::registerObjCDeallocChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCDeallocChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
new file mode 100644
index 0000000..369ba0b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp
@@ -0,0 +1,140 @@
+//=- CheckObjCInstMethodRetTy.cpp - Check ObjC method signatures -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a CheckObjCInstMethSignature, a flow-insenstive check
+// that determines if an Objective-C class interface incorrectly redefines
+// the method signature in a subclass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/ASTContext.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool AreTypesCompatible(QualType Derived, QualType Ancestor,
+ ASTContext& C) {
+
+ // Right now don't compare the compatibility of pointers. That involves
+ // looking at subtyping relationships. FIXME: Future patch.
+ if (Derived->isAnyPointerType() && Ancestor->isAnyPointerType())
+ return true;
+
+ return C.typesAreCompatible(Derived, Ancestor);
+}
+
+static void CompareReturnTypes(const ObjCMethodDecl *MethDerived,
+ const ObjCMethodDecl *MethAncestor,
+ BugReporter &BR, ASTContext &Ctx,
+ const ObjCImplementationDecl *ID) {
+
+ QualType ResDerived = MethDerived->getResultType();
+ QualType ResAncestor = MethAncestor->getResultType();
+
+ if (!AreTypesCompatible(ResDerived, ResAncestor, Ctx)) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "The Objective-C class '"
+ << MethDerived->getClassInterface()
+ << "', which is derived from class '"
+ << MethAncestor->getClassInterface()
+ << "', defines the instance method '"
+ << MethDerived->getSelector().getAsString()
+ << "' whose return type is '"
+ << ResDerived.getAsString()
+ << "'. A method with the same name (same selector) is also defined in "
+ "class '"
+ << MethAncestor->getClassInterface()
+ << "' and has a return type of '"
+ << ResAncestor.getAsString()
+ << "'. These two types are incompatible, and may result in undefined "
+ "behavior for clients of these classes.";
+
+ BR.EmitBasicReport("Incompatible instance method return type",
+ os.str(), MethDerived->getLocStart());
+ }
+}
+
+static void CheckObjCInstMethSignature(const ObjCImplementationDecl* ID,
+ BugReporter& BR) {
+
+ const ObjCInterfaceDecl* D = ID->getClassInterface();
+ const ObjCInterfaceDecl* C = D->getSuperClass();
+
+ if (!C)
+ return;
+
+ ASTContext& Ctx = BR.getContext();
+
+ // Build a DenseMap of the methods for quick querying.
+ typedef llvm::DenseMap<Selector,ObjCMethodDecl*> MapTy;
+ MapTy IMeths;
+ unsigned NumMethods = 0;
+
+ for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(),
+ E=ID->instmeth_end(); I!=E; ++I) {
+
+ ObjCMethodDecl* M = *I;
+ IMeths[M->getSelector()] = M;
+ ++NumMethods;
+ }
+
+ // Now recurse the class hierarchy chain looking for methods with the
+ // same signatures.
+ while (C && NumMethods) {
+ for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(),
+ E=C->instmeth_end(); I!=E; ++I) {
+
+ ObjCMethodDecl* M = *I;
+ Selector S = M->getSelector();
+
+ MapTy::iterator MI = IMeths.find(S);
+
+ if (MI == IMeths.end() || MI->second == 0)
+ continue;
+
+ --NumMethods;
+ ObjCMethodDecl* MethDerived = MI->second;
+ MI->second = 0;
+
+ CompareReturnTypes(MethDerived, M, BR, Ctx, ID);
+ }
+
+ C = C->getSuperClass();
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCMethSigsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCMethSigsChecker : public CheckerV2<
+ check::ASTDecl<ObjCImplementationDecl> > {
+public:
+ void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ CheckObjCInstMethSignature(D, BR);
+ }
+};
+}
+
+void ento::registerObjCMethSigsChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCMethSigsChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
new file mode 100644
index 0000000..185520c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -0,0 +1,517 @@
+//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of flow-insensitive security checks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool isArc4RandomAvailable(const ASTContext &Ctx) {
+ const llvm::Triple &T = Ctx.Target.getTriple();
+ return T.getVendor() == llvm::Triple::Apple ||
+ T.getOS() == llvm::Triple::FreeBSD ||
+ T.getOS() == llvm::Triple::NetBSD ||
+ T.getOS() == llvm::Triple::OpenBSD ||
+ T.getOS() == llvm::Triple::DragonFly;
+}
+
+namespace {
+class WalkAST : public StmtVisitor<WalkAST> {
+ BugReporter &BR;
+ IdentifierInfo *II_gets;
+ IdentifierInfo *II_getpw;
+ IdentifierInfo *II_mktemp;
+ enum { num_rands = 9 };
+ IdentifierInfo *II_rand[num_rands];
+ IdentifierInfo *II_random;
+ enum { num_setids = 6 };
+ IdentifierInfo *II_setid[num_setids];
+
+ const bool CheckRand;
+
+public:
+ WalkAST(BugReporter &br) : BR(br),
+ II_gets(0), II_getpw(0), II_mktemp(0),
+ II_rand(), II_random(0), II_setid(),
+ CheckRand(isArc4RandomAvailable(BR.getContext())) {}
+
+ // Statement visitor methods.
+ void VisitCallExpr(CallExpr *CE);
+ void VisitForStmt(ForStmt *S);
+ void VisitCompoundStmt (CompoundStmt *S);
+ void VisitStmt(Stmt *S) { VisitChildren(S); }
+
+ void VisitChildren(Stmt *S);
+
+ // Helpers.
+ IdentifierInfo *GetIdentifier(IdentifierInfo *& II, const char *str);
+
+ // Checker-specific methods.
+ void CheckLoopConditionForFloat(const ForStmt *FS);
+ void CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckCall_random(const CallExpr *CE, const FunctionDecl *FD);
+ void CheckUncheckedReturnValue(CallExpr *CE);
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Helper methods.
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo *WalkAST::GetIdentifier(IdentifierInfo *& II, const char *str) {
+ if (!II)
+ II = &BR.getContext().Idents.get(str);
+
+ return II;
+}
+
+//===----------------------------------------------------------------------===//
+// AST walking.
+//===----------------------------------------------------------------------===//
+
+void WalkAST::VisitChildren(Stmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+ if (Stmt *child = *I)
+ Visit(child);
+}
+
+void WalkAST::VisitCallExpr(CallExpr *CE) {
+ if (const FunctionDecl *FD = CE->getDirectCallee()) {
+ CheckCall_gets(CE, FD);
+ CheckCall_getpw(CE, FD);
+ CheckCall_mktemp(CE, FD);
+ if (CheckRand) {
+ CheckCall_rand(CE, FD);
+ CheckCall_random(CE, FD);
+ }
+ }
+
+ // Recurse and check children.
+ VisitChildren(CE);
+}
+
+void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+ if (Stmt *child = *I) {
+ if (CallExpr *CE = dyn_cast<CallExpr>(child))
+ CheckUncheckedReturnValue(CE);
+ Visit(child);
+ }
+}
+
+void WalkAST::VisitForStmt(ForStmt *FS) {
+ CheckLoopConditionForFloat(FS);
+
+ // Recurse and check children.
+ VisitChildren(FS);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: floating poing variable used as loop counter.
+// Originally: <rdar://problem/6336718>
+// Implements: CERT security coding advisory FLP-30.
+//===----------------------------------------------------------------------===//
+
+static const DeclRefExpr*
+GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
+ expr = expr->IgnoreParenCasts();
+
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
+ if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
+ B->getOpcode() == BO_Comma))
+ return NULL;
+
+ if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y))
+ return lhs;
+
+ if (const DeclRefExpr *rhs = GetIncrementedVar(B->getRHS(), x, y))
+ return rhs;
+
+ return NULL;
+ }
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
+ const NamedDecl *ND = DR->getDecl();
+ return ND == x || ND == y ? DR : NULL;
+ }
+
+ if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
+ return U->isIncrementDecrementOp()
+ ? GetIncrementedVar(U->getSubExpr(), x, y) : NULL;
+
+ return NULL;
+}
+
+/// CheckLoopConditionForFloat - This check looks for 'for' statements that
+/// use a floating point variable as a loop counter.
+/// CERT: FLP30-C, FLP30-CPP.
+///
+void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
+ // Does the loop have a condition?
+ const Expr *condition = FS->getCond();
+
+ if (!condition)
+ return;
+
+ // Does the loop have an increment?
+ const Expr *increment = FS->getInc();
+
+ if (!increment)
+ return;
+
+ // Strip away '()' and casts.
+ condition = condition->IgnoreParenCasts();
+ increment = increment->IgnoreParenCasts();
+
+ // Is the loop condition a comparison?
+ const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
+
+ if (!B)
+ return;
+
+ // Is this a comparison?
+ if (!(B->isRelationalOp() || B->isEqualityOp()))
+ return;
+
+ // Are we comparing variables?
+ const DeclRefExpr *drLHS =
+ dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
+ const DeclRefExpr *drRHS =
+ dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
+
+ // Does at least one of the variables have a floating point type?
+ drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : NULL;
+ drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : NULL;
+
+ if (!drLHS && !drRHS)
+ return;
+
+ const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
+ const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;
+
+ if (!vdLHS && !vdRHS)
+ return;
+
+ // Does either variable appear in increment?
+ const DeclRefExpr *drInc = GetIncrementedVar(increment, vdLHS, vdRHS);
+
+ if (!drInc)
+ return;
+
+ // Emit the error. First figure out which DeclRefExpr in the condition
+ // referenced the compared variable.
+ const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
+
+ llvm::SmallVector<SourceRange, 2> ranges;
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+
+ os << "Variable '" << drCond->getDecl()->getName()
+ << "' with floating point type '" << drCond->getType().getAsString()
+ << "' should not be used as a loop counter";
+
+ ranges.push_back(drCond->getSourceRange());
+ ranges.push_back(drInc->getSourceRange());
+
+ const char *bugType = "Floating point variable used as loop counter";
+ BR.EmitBasicReport(bugType, "Security", os.str(),
+ FS->getLocStart(), ranges.data(), ranges.size());
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'gets' is insecure.
+// Originally: <rdar://problem/6335715>
+// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
+// CWE-242: Use of Inherently Dangerous Function
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
+ if (FD->getIdentifier() != GetIdentifier(II_gets, "gets"))
+ return;
+
+ const FunctionProtoType *FPT
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if (!FPT)
+ return;
+
+ // Verify that the function takes a single argument.
+ if (FPT->getNumArgs() != 1)
+ return;
+
+ // Is the argument a 'char*'?
+ const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+ return;
+
+ // Issue a warning.
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport("Potential buffer overflow in call to 'gets'",
+ "Security",
+ "Call to function 'gets' is extremely insecure as it can "
+ "always result in a buffer overflow",
+ CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'getpwd' is insecure.
+// CWE-477: Use of Obsolete Functions
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
+ if (FD->getIdentifier() != GetIdentifier(II_getpw, "getpw"))
+ return;
+
+ const FunctionProtoType *FPT
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if (!FPT)
+ return;
+
+ // Verify that the function takes two arguments.
+ if (FPT->getNumArgs() != 2)
+ return;
+
+ // Verify the first argument type is integer.
+ if (!FPT->getArgType(0)->isIntegerType())
+ return;
+
+ // Verify the second argument type is char*.
+ const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(1));
+ if (!PT)
+ return;
+
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+ return;
+
+ // Issue a warning.
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport("Potential buffer overflow in call to 'getpw'",
+ "Security",
+ "The getpw() function is dangerous as it may overflow the "
+ "provided buffer. It is obsoleted by getpwuid().",
+ CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Any use of 'mktemp' is insecure.It is obsoleted by mkstemp().
+// CWE-377: Insecure Temporary File
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
+ if (FD->getIdentifier() != GetIdentifier(II_mktemp, "mktemp"))
+ return;
+
+ const FunctionProtoType *FPT
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if(!FPT)
+ return;
+
+ // Verify that the funcion takes a single argument.
+ if (FPT->getNumArgs() != 1)
+ return;
+
+ // Verify that the argument is Pointer Type.
+ const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
+ if (!PT)
+ return;
+
+ // Verify that the argument is a 'char*'.
+ if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
+ return;
+
+ // Issue a waring.
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
+ "Security",
+ "Call to function 'mktemp' is insecure as it always "
+ "creates or uses insecure temporary file. Use 'mkstemp' instead",
+ CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Linear congruent random number generators should not be used
+// Originally: <rdar://problem/63371000>
+// CWE-338: Use of cryptographically weak prng
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
+ if (II_rand[0] == NULL) {
+ // This check applies to these functions
+ static const char * const identifiers[num_rands] = {
+ "drand48", "erand48", "jrand48", "lrand48", "mrand48", "nrand48",
+ "lcong48",
+ "rand", "rand_r"
+ };
+
+ for (size_t i = 0; i < num_rands; i++)
+ II_rand[i] = &BR.getContext().Idents.get(identifiers[i]);
+ }
+
+ const IdentifierInfo *id = FD->getIdentifier();
+ size_t identifierid;
+
+ for (identifierid = 0; identifierid < num_rands; identifierid++)
+ if (id == II_rand[identifierid])
+ break;
+
+ if (identifierid >= num_rands)
+ return;
+
+ const FunctionProtoType *FTP
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if (!FTP)
+ return;
+
+ if (FTP->getNumArgs() == 1) {
+ // Is the argument an 'unsigned short *'?
+ // (Actually any integer type is allowed.)
+ const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
+ if (!PT)
+ return;
+
+ if (! PT->getPointeeType()->isIntegerType())
+ return;
+ }
+ else if (FTP->getNumArgs() != 0)
+ return;
+
+ // Issue a warning.
+ llvm::SmallString<256> buf1;
+ llvm::raw_svector_ostream os1(buf1);
+ os1 << '\'' << FD << "' is a poor random number generator";
+
+ llvm::SmallString<256> buf2;
+ llvm::raw_svector_ostream os2(buf2);
+ os2 << "Function '" << FD
+ << "' is obsolete because it implements a poor random number generator."
+ << " Use 'arc4random' instead";
+
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: 'random' should not be used
+// Originally: <rdar://problem/63371000>
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckCall_random(const CallExpr *CE, const FunctionDecl *FD) {
+ if (FD->getIdentifier() != GetIdentifier(II_random, "random"))
+ return;
+
+ const FunctionProtoType *FTP
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if (!FTP)
+ return;
+
+ // Verify that the function takes no argument.
+ if (FTP->getNumArgs() != 0)
+ return;
+
+ // Issue a warning.
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport("'random' is not a secure random number generator",
+ "Security",
+ "The 'random' function produces a sequence of values that "
+ "an adversary may be able to predict. Use 'arc4random' "
+ "instead", CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// Check: Should check whether privileges are dropped successfully.
+// Originally: <rdar://problem/6337132>
+//===----------------------------------------------------------------------===//
+
+void WalkAST::CheckUncheckedReturnValue(CallExpr *CE) {
+ const FunctionDecl *FD = CE->getDirectCallee();
+ if (!FD)
+ return;
+
+ if (II_setid[0] == NULL) {
+ static const char * const identifiers[num_setids] = {
+ "setuid", "setgid", "seteuid", "setegid",
+ "setreuid", "setregid"
+ };
+
+ for (size_t i = 0; i < num_setids; i++)
+ II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
+ }
+
+ const IdentifierInfo *id = FD->getIdentifier();
+ size_t identifierid;
+
+ for (identifierid = 0; identifierid < num_setids; identifierid++)
+ if (id == II_setid[identifierid])
+ break;
+
+ if (identifierid >= num_setids)
+ return;
+
+ const FunctionProtoType *FTP
+ = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
+ if (!FTP)
+ return;
+
+ // Verify that the function takes one or two arguments (depending on
+ // the function).
+ if (FTP->getNumArgs() != (identifierid < 4 ? 1 : 2))
+ return;
+
+ // The arguments must be integers.
+ for (unsigned i = 0; i < FTP->getNumArgs(); i++)
+ if (! FTP->getArgType(i)->isIntegerType())
+ return;
+
+ // Issue a warning.
+ llvm::SmallString<256> buf1;
+ llvm::raw_svector_ostream os1(buf1);
+ os1 << "Return value is not checked in call to '" << FD << '\'';
+
+ llvm::SmallString<256> buf2;
+ llvm::raw_svector_ostream os2(buf2);
+ os2 << "The return value from the call to '" << FD
+ << "' is not checked. If an error occurs in '" << FD
+ << "', the following code may execute with unexpected privileges";
+
+ SourceRange R = CE->getCallee()->getSourceRange();
+ BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1);
+}
+
+//===----------------------------------------------------------------------===//
+// SecuritySyntaxChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SecuritySyntaxChecker : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ WalkAST walker(BR);
+ walker.Visit(D->getBody());
+ }
+};
+}
+
+void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
+ mgr.registerChecker<SecuritySyntaxChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
new file mode 100644
index 0000000..d46ac81
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -0,0 +1,87 @@
+//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a check for unintended use of sizeof() on pointer
+// expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/StmtVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class WalkAST : public StmtVisitor<WalkAST> {
+ BugReporter &BR;
+
+public:
+ WalkAST(BugReporter &br) : BR(br) {}
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ void VisitStmt(Stmt *S) { VisitChildren(S); }
+ void VisitChildren(Stmt *S);
+};
+}
+
+void WalkAST::VisitChildren(Stmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
+ if (Stmt *child = *I)
+ Visit(child);
+}
+
+// CWE-467: Use of sizeof() on a Pointer Type
+void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ if (!E->isSizeOf())
+ return;
+
+ // If an explicit type is used in the code, usually the coder knows what he is
+ // doing.
+ if (E->isArgumentType())
+ return;
+
+ QualType T = E->getTypeOfArgument();
+ if (T->isPointerType()) {
+
+ // Many false positives have the form 'sizeof *p'. This is reasonable
+ // because people know what they are doing when they intentionally
+ // dereference the pointer.
+ Expr *ArgEx = E->getArgumentExpr();
+ if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
+ return;
+
+ SourceRange R = ArgEx->getSourceRange();
+ BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
+ "Logic",
+ "The code calls sizeof() on a pointer type. "
+ "This can produce an unexpected result.",
+ E->getLocStart(), &R, 1);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// SizeofPointerChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SizeofPointerChecker : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ WalkAST walker(BR);
+ walker.Visit(D->getBody());
+ }
+};
+}
+
+void ento::registerSizeofPointerChecker(CheckerManager &mgr) {
+ mgr.registerChecker<SizeofPointerChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
new file mode 100644
index 0000000..1dc7486
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -0,0 +1,197 @@
+//===--- Checkers.td - Static Analyzer Checkers -===-----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+include "clang/StaticAnalyzer/Checkers/CheckerBase.td"
+
+//===----------------------------------------------------------------------===//
+// Packages.
+//===----------------------------------------------------------------------===//
+
+def Core : Package<"core">;
+def Cocoa : Package<"cocoa">;
+def Unix : Package<"unix">;
+def MacOSX : Package<"macosx">;
+
+def CoreExperimental : Package<"experimental">,
+ InPackage<Core>, Hidden;
+
+def CocoaExperimental : Package<"experimental">,
+ InPackage<Cocoa>, Hidden;
+
+def UnixExperimental : Package<"experimental">,
+ InPackage<Unix>, Hidden;
+
+def LLVM : Package<"llvm">;
+def Debug : Package<"debug">;
+
+//===----------------------------------------------------------------------===//
+// Groups.
+//===----------------------------------------------------------------------===//
+
+def AllExperimental : CheckerGroup<"all-experimental">,
+ Hidden;
+
+//===----------------------------------------------------------------------===//
+// Checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Cocoa in {
+
+def ObjCSelfInitChecker : Checker<"SelfInit">,
+ HelpText<"Check that 'self' is propely initialized inside an initializer method">,
+ DescFile<"ObjCSelfInitChecker.cpp">;
+
+def ObjCAtSyncChecker : Checker<"AtSync">,
+ HelpText<"Check for null pointers used as mutexes for @synchronized">,
+ DescFile<"ObjCAtSyncChecker.cpp">;
+
+def NilArgChecker : Checker<"NilArg">,
+ HelpText<"Check for prohibited nil arguments to ObjC method calls">,
+ DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def ClassReleaseChecker : Checker<"ClassRelease">,
+ HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly to a Class">,
+ DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">,
+ HelpText<"Warn for subpar uses of NSAutoreleasePool">,
+ DescFile<"NSAutoreleasePoolChecker.cpp">;
+
+def ObjCMethSigsChecker : Checker<"MethodSigs">,
+ HelpText<"Warn about Objective-C method signatures with type incompatibilities">,
+ DescFile<"CheckObjCInstMethSignature.cpp">;
+
+def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
+ HelpText<"Warn about private ivars that are never used">,
+ DescFile<"ObjCUnusedIVarsChecker.cpp">;
+
+}
+
+def StackAddrLeakChecker : Checker<"StackAddrLeak">,
+ InPackage<Core>,
+ HelpText<"Check that addresses to stack memory are not leaked outside the function">,
+ DescFile<"StackAddrLeakChecker.cpp">;
+
+def DeadStoresChecker : Checker<"DeadStores">,
+ InPackage<Core>,
+ HelpText<"Check for stores to dead variables">,
+ DescFile<"DeadStoresChecker.cpp">;
+
+def UnixAPIChecker : Checker<"API">,
+ InPackage<Unix>,
+ HelpText<"Check calls to various UNIX/Posix functions">,
+ DescFile<"UnixAPIChecker.cpp">;
+
+def MacOSXAPIChecker : Checker<"API">,
+ InPackage<MacOSX>,
+ HelpText<"Check calls to various MacOSXAPIChecker">,
+ DescFile<"MacOSXAPIChecker.cpp">;
+
+def CFNumberCreateChecker : Checker<"CFNumber">,
+ InPackage<MacOSX>,
+ HelpText<"Check for CFNumberCreate">,
+ DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
+ InPackage<MacOSX>,
+ HelpText<"Check for null arguments to CFRetain/CFRelease">,
+ DescFile<"BasicObjCFoundationChecks.cpp">;
+
+def LLVMConventionsChecker : Checker<"Conventions">,
+ InPackage<LLVM>,
+ HelpText<"Check code for LLVM codebase conventions">,
+ DescFile<"LLVMConventionsChecker.cpp">;
+
+def LiveVariablesDumper : Checker<"DumpLiveVars">,
+ InPackage<Debug>,
+ HelpText<"Print results of live variable analysis">,
+ DescFile<"DebugCheckers.cpp">;
+
+def CFGViewer : Checker<"ViewCFG">,
+ InPackage<Debug>,
+ HelpText<"View Control-Flow Graphs using GraphViz">,
+ DescFile<"DebugCheckers.cpp">;
+
+def CFGDumper : Checker<"DumpCFG">,
+ InPackage<Debug>,
+ HelpText<"Display Control-Flow Graphs">,
+ DescFile<"DebugCheckers.cpp">;
+
+//===----------------------------------------------------------------------===//
+// Hidden experimental checkers.
+//===----------------------------------------------------------------------===//
+
+let Group = AllExperimental in {
+
+def CStringChecker : Checker<"CString">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check calls to functions in <string.h>">,
+ DescFile<"CStringChecker.cpp">;
+
+def UnreachableCodeChecker : Checker<"UnreachableCode">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check unreachable code">,
+ DescFile<"UnreachableCodeChecker.cpp">;
+
+def IdempotentOperationChecker : Checker<"IdempotentOps">,
+ InPackage<CoreExperimental>,
+ HelpText<"Warn about idempotent operations">,
+ DescFile<"IdempotentOperationChecker.cpp">;
+
+def CastToStructChecker : Checker<"CastToStruct">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for cast from non-struct pointer to struct pointer">,
+ DescFile<"CastToStructChecker.cpp">;
+
+def FixedAddressChecker : Checker<"FixedAddr">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for assignment of a fixed address to a pointer">,
+ DescFile<"FixedAddressChecker.cpp">;
+
+def PointerArithChecker : Checker<"PointerArithm">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for pointer arithmetic on locations other than array elements">,
+ DescFile<"PointerArithChecker">;
+
+def PointerSubChecker : Checker<"PointerSub">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">,
+ DescFile<"PointerSubChecker">;
+
+def SizeofPointerChecker : Checker<"SizeofPtr">,
+ InPackage<CoreExperimental>,
+ HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
+ DescFile<"CheckSizeofPointer.cpp">;
+
+def SecuritySyntaxChecker : Checker<"SecuritySyntactic">,
+ InPackage<CoreExperimental>,
+ HelpText<"Perform quick security checks that require no data flow">,
+ DescFile<"CheckSecuritySyntaxOnly.cpp">;
+
+def ObjCDeallocChecker : Checker<"Dealloc">,
+ InPackage<CocoaExperimental>,
+ HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
+ DescFile<"CheckObjCDealloc.cpp">;
+
+def ChrootChecker : Checker<"Chroot">,
+ InPackage<UnixExperimental>,
+ HelpText<"Check improper use of chroot">,
+ DescFile<"ChrootChecker.cpp">;
+
+def PthreadLockChecker : Checker<"PthreadLock">,
+ InPackage<UnixExperimental>,
+ HelpText<"Simple lock -> unlock checker">,
+ DescFile<"PthreadLockChecker.cpp">;
+
+def StreamChecker : Checker<"Stream">,
+ InPackage<UnixExperimental>,
+ HelpText<"Check stream handling functions">,
+ DescFile<"StreamChecker.cpp">;
+
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
new file mode 100644
index 0000000..36e76d0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -0,0 +1,167 @@
+//===- Chrootchecker.cpp -------- Basic security checks ----------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines chroot checker, which checks improper use of chroot.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+// enum value that represent the jail state
+enum Kind { NO_CHROOT, ROOT_CHANGED, JAIL_ENTERED };
+
+bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
+//bool isJailEntered(intptr_t k) { return k == JAIL_ENTERED; }
+
+// This checker checks improper use of chroot.
+// The state transition:
+// NO_CHROOT ---chroot(path)--> ROOT_CHANGED ---chdir(/) --> JAIL_ENTERED
+// | |
+// ROOT_CHANGED<--chdir(..)-- JAIL_ENTERED<--chdir(..)--
+// | |
+// bug<--foo()-- JAIL_ENTERED<--foo()--
+class ChrootChecker : public CheckerVisitor<ChrootChecker> {
+ IdentifierInfo *II_chroot, *II_chdir;
+ // This bug refers to possibly break out of a chroot() jail.
+ BuiltinBug *BT_BreakJail;
+
+public:
+ ChrootChecker() : II_chroot(0), II_chdir(0), BT_BreakJail(0) {}
+
+ static void *getTag() {
+ static int x;
+ return &x;
+ }
+
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+ virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+
+private:
+ void Chroot(CheckerContext &C, const CallExpr *CE);
+ void Chdir(CheckerContext &C, const CallExpr *CE);
+};
+
+} // end anonymous namespace
+
+static void RegisterChrootChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new ChrootChecker());
+}
+
+void ento::registerChrootChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterChrootChecker);
+}
+
+bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II_chroot)
+ II_chroot = &Ctx.Idents.get("chroot");
+ if (!II_chdir)
+ II_chdir = &Ctx.Idents.get("chdir");
+
+ if (FD->getIdentifier() == II_chroot) {
+ Chroot(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_chdir) {
+ Chdir(C, CE);
+ return true;
+ }
+
+ return false;
+}
+
+void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ GRStateManager &Mgr = state->getStateManager();
+
+ // Once encouter a chroot(), set the enum value ROOT_CHANGED directly in
+ // the GDM.
+ state = Mgr.addGDM(state, ChrootChecker::getTag(), (void*) ROOT_CHANGED);
+ C.addTransition(state);
+}
+
+void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ GRStateManager &Mgr = state->getStateManager();
+
+ // If there are no jail state in the GDM, just return.
+ const void* k = state->FindGDM(ChrootChecker::getTag());
+ if (!k)
+ return;
+
+ // After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
+ const Expr *ArgExpr = CE->getArg(0);
+ SVal ArgVal = state->getSVal(ArgExpr);
+
+ if (const MemRegion *R = ArgVal.getAsRegion()) {
+ R = R->StripCasts();
+ if (const StringRegion* StrRegion= dyn_cast<StringRegion>(R)) {
+ const StringLiteral* Str = StrRegion->getStringLiteral();
+ if (Str->getString() == "/")
+ state = Mgr.addGDM(state, ChrootChecker::getTag(),
+ (void*) JAIL_ENTERED);
+ }
+ }
+
+ C.addTransition(state);
+}
+
+// Check the jail state before any function call except chroot and chdir().
+void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II_chroot)
+ II_chroot = &Ctx.Idents.get("chroot");
+ if (!II_chdir)
+ II_chdir = &Ctx.Idents.get("chdir");
+
+ // Ingnore chroot and chdir.
+ if (FD->getIdentifier() == II_chroot || FD->getIdentifier() == II_chdir)
+ return;
+
+ // If jail state is ROOT_CHANGED, generate BugReport.
+ void* const* k = state->FindGDM(ChrootChecker::getTag());
+ if (k)
+ if (isRootChanged((intptr_t) *k))
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT_BreakJail)
+ BT_BreakJail = new BuiltinBug("Break out of jail",
+ "No call of chdir(\"/\") immediately "
+ "after chroot");
+ BugReport *R = new BugReport(*BT_BreakJail,
+ BT_BreakJail->getDescription(), N);
+ C.EmitReport(R);
+ }
+
+ return;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
new file mode 100644
index 0000000..94f200f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
@@ -0,0 +1,137 @@
+//===--- ClangSACheckerProvider.cpp - Clang SA Checkers Provider ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the CheckerProvider for the checkers defined in
+// libclangStaticAnalyzerCheckers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckerProvider.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+/// \brief Provider for all the checkers in libclangStaticAnalyzerCheckers.
+class ClangSACheckerProvider : public CheckerProvider {
+public:
+ virtual void registerCheckers(CheckerManager &checkerMgr,
+ CheckerOptInfo *checkOpts, unsigned numCheckOpts);
+};
+
+}
+
+CheckerProvider *ento::createClangSACheckerProvider() {
+ return new ClangSACheckerProvider();
+}
+
+namespace {
+
+struct StaticCheckerInfoRec {
+ const char *FullName;
+ void (*RegFunc)(CheckerManager &mgr);
+ bool Hidden;
+};
+
+} // end anonymous namespace.
+
+static const StaticCheckerInfoRec StaticCheckerInfo[] = {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \
+ { FULLNAME, register##CLASS, HIDDEN },
+#include "Checkers.inc"
+ { 0, 0, 0}
+#undef CHECKER
+#undef GET_CHECKERS
+};
+
+namespace {
+
+struct CheckNameOption {
+ const char *Name;
+ const short *Members;
+ const short *SubGroups;
+ bool Hidden;
+};
+
+} // end anonymous namespace.
+
+#define GET_MEMBER_ARRAYS
+#include "Checkers.inc"
+#undef GET_MEMBER_ARRAYS
+
+// The table of check name options, sorted by name for fast binary lookup.
+static const CheckNameOption CheckNameTable[] = {
+#define GET_CHECKNAME_TABLE
+#include "Checkers.inc"
+#undef GET_CHECKNAME_TABLE
+};
+static const size_t
+ CheckNameTableSize = sizeof(CheckNameTable) / sizeof(CheckNameTable[0]);
+
+static bool CheckNameOptionCompare(const CheckNameOption &LHS,
+ const CheckNameOption &RHS) {
+ return strcmp(LHS.Name, RHS.Name) < 0;
+}
+
+static void collectCheckers(const CheckNameOption *checkName,
+ bool enable,
+ llvm::DenseSet<const StaticCheckerInfoRec *> &checkers,
+ bool collectHidden) {
+ if (checkName->Hidden && !collectHidden)
+ return;
+
+ if (const short *member = checkName->Members) {
+ if (enable) {
+ if (collectHidden || !StaticCheckerInfo[*member].Hidden)
+ checkers.insert(&StaticCheckerInfo[*member]);
+ } else {
+ for (; *member != -1; ++member)
+ checkers.erase(&StaticCheckerInfo[*member]);
+ }
+ }
+
+ // Enable/disable all subgroups along with this one.
+ if (const short *subGroups = checkName->SubGroups) {
+ for (; *subGroups != -1; ++subGroups)
+ collectCheckers(&CheckNameTable[*subGroups], enable, checkers,
+ collectHidden && checkName->Hidden);
+ }
+}
+
+static void collectCheckers(CheckerOptInfo &opt,
+ llvm::DenseSet<const StaticCheckerInfoRec *> &checkers) {
+ const char *optName = opt.getName();
+ CheckNameOption key = { optName, 0, 0, false };
+ const CheckNameOption *found =
+ std::lower_bound(CheckNameTable, CheckNameTable + CheckNameTableSize, key,
+ CheckNameOptionCompare);
+ if (found == CheckNameTable + CheckNameTableSize ||
+ strcmp(found->Name, optName) != 0)
+ return; // Check name not found.
+
+ opt.claim();
+ collectCheckers(found, opt.isEnabled(), checkers, /*collectHidden=*/true);
+}
+
+void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
+ CheckerOptInfo *checkOpts, unsigned numCheckOpts) {
+ llvm::DenseSet<const StaticCheckerInfoRec *> enabledCheckers;
+ for (unsigned i = 0; i != numCheckOpts; ++i)
+ collectCheckers(checkOpts[i], enabledCheckers);
+ for (llvm::DenseSet<const StaticCheckerInfoRec *>::iterator
+ I = enabledCheckers.begin(), E = enabledCheckers.end(); I != E; ++I) {
+ (*I)->RegFunc(checkerMgr);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h
new file mode 100644
index 0000000..f6c8011
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h
@@ -0,0 +1,29 @@
+//===--- ClangSACheckerProvider.h - Clang SA Checkers Provider --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the entry point for creating the provider for the checkers defined
+// in libclangStaticAnalyzerCheckers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CHECKERS_CLANGSACHECKERPROVIDER_H
+#define LLVM_CLANG_SA_CHECKERS_CLANGSACHECKERPROVIDER_H
+
+namespace clang {
+
+namespace ento {
+ class CheckerProvider;
+
+CheckerProvider *createClangSACheckerProvider();
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
new file mode 100644
index 0000000..73239f5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
@@ -0,0 +1,34 @@
+//===--- ClangSACheckers.h - Registration functions for Checkers *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares the registation functions for the checkers defined in
+// libclangStaticAnalyzerCheckers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_LIB_CHECKERS_CLANGSACHECKERS_H
+#define LLVM_CLANG_SA_LIB_CHECKERS_CLANGSACHECKERS_H
+
+namespace clang {
+
+namespace ento {
+class CheckerManager;
+
+#define GET_CHECKERS
+#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,HIDDEN) \
+ void register##CLASS(CheckerManager &mgr);
+#include "Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
new file mode 100644
index 0000000..3b39372
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -0,0 +1,363 @@
+//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a DeadStores, a flow-sensitive checker that looks for
+// stores to variables that are no longer live.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ParentMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+// FIXME: Eventually migrate into its own file, and have it managed by
+// AnalysisManager.
+class ReachableCode {
+ const CFG &cfg;
+ llvm::BitVector reachable;
+public:
+ ReachableCode(const CFG &cfg)
+ : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
+
+ void computeReachableBlocks();
+
+ bool isReachable(const CFGBlock *block) const {
+ return reachable[block->getBlockID()];
+ }
+};
+}
+
+void ReachableCode::computeReachableBlocks() {
+ if (!cfg.getNumBlockIDs())
+ return;
+
+ llvm::SmallVector<const CFGBlock*, 10> worklist;
+ worklist.push_back(&cfg.getEntry());
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+ llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
+ if (isReachable)
+ continue;
+ isReachable = true;
+ for (CFGBlock::const_succ_iterator i = block->succ_begin(),
+ e = block->succ_end(); i != e; ++i)
+ if (const CFGBlock *succ = *i)
+ worklist.push_back(succ);
+ }
+}
+
+namespace {
+class DeadStoreObs : public LiveVariables::ObserverTy {
+ const CFG &cfg;
+ ASTContext &Ctx;
+ BugReporter& BR;
+ ParentMap& Parents;
+ llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+ llvm::OwningPtr<ReachableCode> reachableCode;
+ const CFGBlock *currentBlock;
+
+ enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
+
+public:
+ DeadStoreObs(const CFG &cfg, ASTContext &ctx,
+ BugReporter& br, ParentMap& parents,
+ llvm::SmallPtrSet<VarDecl*, 20> &escaped)
+ : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
+ Escaped(escaped), currentBlock(0) {}
+
+ virtual ~DeadStoreObs() {}
+
+ void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
+ if (Escaped.count(V))
+ return;
+
+ // Compute reachable blocks within the CFG for trivial cases
+ // where a bogus dead store can be reported because itself is unreachable.
+ if (!reachableCode.get()) {
+ reachableCode.reset(new ReachableCode(cfg));
+ reachableCode->computeReachableBlocks();
+ }
+
+ if (!reachableCode->isReachable(currentBlock))
+ return;
+
+ const std::string &name = V->getNameAsString();
+
+ const char* BugType = 0;
+ std::string msg;
+
+ switch (dsk) {
+ default:
+ assert(false && "Impossible dead store type.");
+
+ case DeadInit:
+ BugType = "Dead initialization";
+ msg = "Value stored to '" + name +
+ "' during its initialization is never read";
+ break;
+
+ case DeadIncrement:
+ BugType = "Dead increment";
+ case Standard:
+ if (!BugType) BugType = "Dead assignment";
+ msg = "Value stored to '" + name + "' is never read";
+ break;
+
+ case Enclosing:
+ // Don't report issues in this case, e.g.: "if (x = foo())",
+ // where 'x' is unused later. We have yet to see a case where
+ // this is a real bug.
+ return;
+ }
+
+ BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
+ }
+
+ void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
+ DeadStoreKind dsk,
+ const LiveVariables::AnalysisDataTy& AD,
+ const LiveVariables::ValTy& Live) {
+
+ if (!VD->hasLocalStorage())
+ return;
+ // Reference types confuse the dead stores checker. Skip them
+ // for now.
+ if (VD->getType()->getAs<ReferenceType>())
+ return;
+
+ if (!Live(VD, AD) &&
+ !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
+ Report(VD, dsk, Ex->getSourceRange().getBegin(),
+ Val->getSourceRange());
+ }
+
+ void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
+ const LiveVariables::AnalysisDataTy& AD,
+ const LiveVariables::ValTy& Live) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+ CheckVarDecl(VD, DR, Val, dsk, AD, Live);
+ }
+
+ bool isIncrement(VarDecl* VD, BinaryOperator* B) {
+ if (B->isCompoundAssignmentOp())
+ return true;
+
+ Expr* RHS = B->getRHS()->IgnoreParenCasts();
+ BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
+
+ if (!BRHS)
+ return false;
+
+ DeclRefExpr *DR;
+
+ if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
+ if (DR->getDecl() == VD)
+ return true;
+
+ if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
+ if (DR->getDecl() == VD)
+ return true;
+
+ return false;
+ }
+
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *block,
+ const LiveVariables::AnalysisDataTy& AD,
+ const LiveVariables::ValTy& Live) {
+
+ currentBlock = block;
+
+ // Skip statements in macros.
+ if (S->getLocStart().isMacroID())
+ return;
+
+ // Only cover dead stores from regular assignments. ++/-- dead stores
+ // have never flagged a real bug.
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (!B->isAssignmentOp()) return; // Skip non-assignments.
+
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
+ if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Special case: check for assigning null to a pointer.
+ // This is a common form of defensive programming.
+ QualType T = VD->getType();
+ if (T->isPointerType() || T->isObjCObjectPointerType()) {
+ if (B->getRHS()->isNullPointerConstant(Ctx,
+ Expr::NPC_ValueDependentIsNull))
+ return;
+ }
+
+ Expr* RHS = B->getRHS()->IgnoreParenCasts();
+ // Special case: self-assignments. These are often used to shut up
+ // "unused variable" compiler warnings.
+ if (DeclRefExpr* RhsDR = dyn_cast<DeclRefExpr>(RHS))
+ if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
+ return;
+
+ // Otherwise, issue a warning.
+ DeadStoreKind dsk = Parents.isConsumedExpr(B)
+ ? Enclosing
+ : (isIncrement(VD,B) ? DeadIncrement : Standard);
+
+ CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
+ }
+ }
+ else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
+ if (!U->isIncrementOp() || U->isPrefix())
+ return;
+
+ Stmt *parent = Parents.getParentIgnoreParenCasts(U);
+ if (!parent || !isa<ReturnStmt>(parent))
+ return;
+
+ Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
+
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
+ CheckDeclRef(DR, U, DeadIncrement, AD, Live);
+ }
+ else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ // Iterate through the decls. Warn if any initializers are complex
+ // expressions that are not live (never used).
+ for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+ DI != DE; ++DI) {
+
+ VarDecl* V = dyn_cast<VarDecl>(*DI);
+
+ if (!V)
+ continue;
+
+ if (V->hasLocalStorage()) {
+ // Reference types confuse the dead stores checker. Skip them
+ // for now.
+ if (V->getType()->getAs<ReferenceType>())
+ return;
+
+ if (Expr* E = V->getInit()) {
+ // Don't warn on C++ objects (yet) until we can show that their
+ // constructors/destructors don't have side effects.
+ if (isa<CXXConstructExpr>(E))
+ return;
+
+ if (isa<ExprWithCleanups>(E))
+ return;
+
+ // A dead initialization is a variable that is dead after it
+ // is initialized. We don't flag warnings for those variables
+ // marked 'unused'.
+ if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
+ // Special case: check for initializations with constants.
+ //
+ // e.g. : int x = 0;
+ //
+ // If x is EVER assigned a new value later, don't issue
+ // a warning. This is because such initialization can be
+ // due to defensive programming.
+ if (E->isConstantInitializer(Ctx, false))
+ return;
+
+ if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ // Special case: check for initialization from constant
+ // variables.
+ //
+ // e.g. extern const int MyConstant;
+ // int x = MyConstant;
+ //
+ if (VD->hasGlobalStorage() &&
+ VD->getType().isConstQualified())
+ return;
+ // Special case: check for initialization from scalar
+ // parameters. This is often a form of defensive
+ // programming. Non-scalars are still an error since
+ // because it more likely represents an actual algorithmic
+ // bug.
+ if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
+ return;
+ }
+
+ Report(V, DeadInit, V->getLocation(), E->getSourceRange());
+ }
+ }
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Driver function to invoke the Dead-Stores checker on a CFG.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
+ CFG *cfg;
+public:
+ FindEscaped(CFG *c) : cfg(c) {}
+
+ CFG& getCFG() { return *cfg; }
+
+ llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+
+ void VisitUnaryOperator(UnaryOperator* U) {
+ // Check for '&'. Any VarDecl whose value has its address-taken we
+ // treat as escaped.
+ Expr* E = U->getSubExpr()->IgnoreParenCasts();
+ if (U->getOpcode() == UO_AddrOf)
+ if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+ if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ Escaped.insert(VD);
+ return;
+ }
+ Visit(E);
+ }
+};
+} // end anonymous namespace
+
+
+//===----------------------------------------------------------------------===//
+// DeadStoresChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DeadStoresChecker : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (LiveVariables *L = mgr.getLiveVariables(D)) {
+ CFG &cfg = *mgr.getCFG(D);
+ ParentMap &pmap = mgr.getParentMap(D);
+ FindEscaped FS(&cfg);
+ FS.getCFG().VisitBlockStmts(FS);
+ DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
+ L->runOnAllBlocks(cfg, &A);
+ }
+ }
+};
+}
+
+void ento::registerDeadStoresChecker(CheckerManager &mgr) {
+ mgr.registerChecker<DeadStoresChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
new file mode 100644
index 0000000..091d99b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -0,0 +1,80 @@
+//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a checkers that display debugging information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// LiveVariablesDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class LiveVariablesDumper : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (LiveVariables* L = mgr.getLiveVariables(D)) {
+ L->dumpBlockLiveness(mgr.getSourceManager());
+ }
+ }
+};
+}
+
+void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
+ mgr.registerChecker<LiveVariablesDumper>();
+}
+
+//===----------------------------------------------------------------------===//
+// CFGViewer
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFGViewer : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ cfg->viewCFG(mgr.getLangOptions());
+ }
+ }
+};
+}
+
+void ento::registerCFGViewer(CheckerManager &mgr) {
+ mgr.registerChecker<CFGViewer>();
+}
+
+//===----------------------------------------------------------------------===//
+// CFGDumper
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CFGDumper : public CheckerV2<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ cfg->dump(mgr.getLangOptions());
+ }
+ }
+};
+}
+
+void ento::registerCFGDumper(CheckerManager &mgr) {
+ mgr.registerChecker<CFGDumper>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
new file mode 100644
index 0000000..606ac4a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -0,0 +1,205 @@
+//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NullDerefChecker, a builtin check in ExprEngine that performs
+// checks for null pointers at loads and stores.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DereferenceChecker : public Checker {
+ BuiltinBug *BT_null;
+ BuiltinBug *BT_undef;
+ llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes;
+public:
+ DereferenceChecker() : BT_null(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
+ bool isLoad);
+
+ std::pair<ExplodedNode * const*, ExplodedNode * const*>
+ getImplicitNodes() const {
+ return std::make_pair(ImplicitNullDerefNodes.data(),
+ ImplicitNullDerefNodes.data() +
+ ImplicitNullDerefNodes.size());
+ }
+ void AddDerefSource(llvm::raw_ostream &os,
+ llvm::SmallVectorImpl<SourceRange> &Ranges,
+ const Expr *Ex, bool loadedFrom = false);
+};
+} // end anonymous namespace
+
+void ento::RegisterDereferenceChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new DereferenceChecker());
+}
+
+std::pair<ExplodedNode * const *, ExplodedNode * const *>
+ento::GetImplicitNullDereferences(ExprEngine &Eng) {
+ DereferenceChecker *checker = Eng.getChecker<DereferenceChecker>();
+ if (!checker)
+ return std::make_pair((ExplodedNode * const *) 0,
+ (ExplodedNode * const *) 0);
+ return checker->getImplicitNodes();
+}
+
+void DereferenceChecker::AddDerefSource(llvm::raw_ostream &os,
+ llvm::SmallVectorImpl<SourceRange> &Ranges,
+ const Expr *Ex,
+ bool loadedFrom) {
+ Ex = Ex->IgnoreParenLValueCasts();
+ switch (Ex->getStmtClass()) {
+ default:
+ return;
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(Ex);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ os << " (" << (loadedFrom ? "loaded from" : "from")
+ << " variable '" << VD->getName() << "')";
+ Ranges.push_back(DR->getSourceRange());
+ }
+ return;
+ }
+ case Stmt::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(Ex);
+ os << " (" << (loadedFrom ? "loaded from" : "via")
+ << " field '" << ME->getMemberNameInfo() << "')";
+ SourceLocation L = ME->getMemberLoc();
+ Ranges.push_back(SourceRange(L, L));
+ break;
+ }
+ }
+}
+
+void DereferenceChecker::visitLocation(CheckerContext &C, const Stmt *S,
+ SVal l, bool isLoad) {
+ // Check for dereference of an undefined value.
+ if (l.isUndef()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Dereference of undefined pointer value");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+ C.EmitReport(report);
+ }
+ return;
+ }
+
+ DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(location))
+ return;
+
+ const GRState *state = C.getState();
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->assume(location);
+
+ // The explicit NULL case.
+ if (nullState) {
+ if (!notNullState) {
+ // Generate an error node.
+ ExplodedNode *N = C.generateSink(nullState);
+ if (!N)
+ return;
+
+ // We know that 'location' cannot be non-null. This is what
+ // we call an "explicit" null dereference.
+ if (!BT_null)
+ BT_null = new BuiltinBug("Dereference of null pointer");
+
+ llvm::SmallString<100> buf;
+ llvm::SmallVector<SourceRange, 2> Ranges;
+
+ // Walk through lvalue casts to get the original expression
+ // that syntactically caused the load.
+ if (const Expr *expr = dyn_cast<Expr>(S))
+ S = expr->IgnoreParenLValueCasts();
+
+ switch (S->getStmtClass()) {
+ case Stmt::ArraySubscriptExprClass: {
+ llvm::raw_svector_ostream os(buf);
+ os << "Array access";
+ const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S);
+ AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts());
+ os << " results in a null pointer dereference";
+ break;
+ }
+ case Stmt::UnaryOperatorClass: {
+ llvm::raw_svector_ostream os(buf);
+ os << "Dereference of null pointer";
+ const UnaryOperator *U = cast<UnaryOperator>(S);
+ AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(), true);
+ break;
+ }
+ case Stmt::MemberExprClass: {
+ const MemberExpr *M = cast<MemberExpr>(S);
+ if (M->isArrow()) {
+ llvm::raw_svector_ostream os(buf);
+ os << "Access to field '" << M->getMemberNameInfo()
+ << "' results in a dereference of a null pointer";
+ AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(), true);
+ }
+ break;
+ }
+ case Stmt::ObjCIvarRefExprClass: {
+ const ObjCIvarRefExpr *IV = cast<ObjCIvarRefExpr>(S);
+ if (const DeclRefExpr *DR =
+ dyn_cast<DeclRefExpr>(IV->getBase()->IgnoreParenCasts())) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ llvm::raw_svector_ostream os(buf);
+ os << "Instance variable access (via '" << VD->getName()
+ << "') results in a null pointer dereference";
+ }
+ }
+ Ranges.push_back(IV->getSourceRange());
+ break;
+ }
+ default:
+ break;
+ }
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_null,
+ buf.empty() ? BT_null->getDescription():buf.str(),
+ N);
+
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDerefExpr(N));
+
+ for (llvm::SmallVectorImpl<SourceRange>::iterator
+ I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
+ report->addRange(*I);
+
+ C.EmitReport(report);
+ return;
+ }
+ else {
+ // Otherwise, we have the case where the location could either be
+ // null or not-null. Record the error node as an "implicit" null
+ // dereference.
+ if (ExplodedNode *N = C.generateSink(nullState))
+ ImplicitNullDerefNodes.push_back(N);
+ }
+ }
+
+ // From this point forward, we know that the location is not null.
+ C.addTransition(notNullState);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
new file mode 100644
index 0000000..20cc904
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -0,0 +1,86 @@
+//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines DivZeroChecker, a builtin check in ExprEngine that performs
+// checks for division by zeros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
+ BuiltinBug *BT;
+public:
+ DivZeroChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+} // end anonymous namespace
+
+void ento::RegisterDivZeroChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new DivZeroChecker());
+}
+
+void *DivZeroChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ BinaryOperator::Opcode Op = B->getOpcode();
+ if (Op != BO_Div &&
+ Op != BO_Rem &&
+ Op != BO_DivAssign &&
+ Op != BO_RemAssign)
+ return;
+
+ if (!B->getRHS()->getType()->isIntegerType() ||
+ !B->getRHS()->getType()->isScalarType())
+ return;
+
+ SVal Denom = C.getState()->getSVal(B->getRHS());
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
+
+ // Divide-by-undefined handled in the generic checking for uses of
+ // undefined values.
+ if (!DV)
+ return;
+
+ // Check for divide by zero.
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotZero, *stateZero;
+ llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
+
+ if (stateZero && !stateNotZero) {
+ if (ExplodedNode *N = C.generateSink(stateZero)) {
+ if (!BT)
+ BT = new BuiltinBug("Division by zero");
+
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT, BT->getDescription(), N);
+
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetDenomExpr(N));
+
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ // If we get here, then the denom should not be zero. We abandon the implicit
+ // zero denom case for now.
+ C.addTransition(stateNotZero);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
new file mode 100644
index 0000000..d9bb480
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
@@ -0,0 +1,37 @@
+//=-- ExperimentalChecks.h ----------------------------------------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions to instantiate and register experimental
+// checks in ExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "ExperimentalChecks.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+
+using namespace clang;
+using namespace ento;
+
+void ento::RegisterExperimentalChecks(ExprEngine &Eng) {
+ // These are checks that never belong as internal checks
+ // within ExprEngine.
+ RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this.
+}
+
+void ento::RegisterExperimentalInternalChecks(ExprEngine &Eng) {
+ // These are internal checks that should eventually migrate to
+ // RegisterInternalChecks() once they have been further tested.
+
+ // Note that this must be registered after ReturnStackAddresEngsChecker.
+ RegisterReturnPointerRangeChecker(Eng);
+
+ RegisterArrayBoundChecker(Eng);
+ RegisterCastSizeChecker(Eng);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h
new file mode 100644
index 0000000..1f38ad7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.h
@@ -0,0 +1,31 @@
+//=-- ExperimentalChecks.h ----------------------------------------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions to instantiate and register experimental
+// checks in ExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_ExprEngine_EXPERIMENTAL_CHECKS
+#define LLVM_CLANG_GR_ExprEngine_EXPERIMENTAL_CHECKS
+
+namespace clang {
+
+namespace ento {
+
+class ExprEngine;
+
+void RegisterAnalyzerStatsChecker(ExprEngine &Eng);
+void RegisterMallocChecker(ExprEngine &Eng);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
new file mode 100644
index 0000000..ab8d564
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -0,0 +1,3655 @@
+//=-- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a meta-engine for path-sensitive dataflow analysis that
+// is built on GREngine, but provides the boilerplate to execute transfer
+// functions and build the ExplodedGraph at the expression level.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: Restructure checker registration.
+#include "InternalChecks.h"
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/ImmutableList.h"
+
+#ifndef NDEBUG
+#include "llvm/Support/GraphWriter.h"
+#endif
+
+using namespace clang;
+using namespace ento;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+using llvm::cast;
+using llvm::APSInt;
+
+namespace {
+ // Trait class for recording returned expression in the state.
+ struct ReturnExpr {
+ static int TagInt;
+ typedef const Stmt *data_type;
+ };
+ int ReturnExpr::TagInt;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
+ IdentifierInfo* II = &Ctx.Idents.get(name);
+ return Ctx.Selectors.getSelector(0, &II);
+}
+
+//===----------------------------------------------------------------------===//
+// Checker worklist routines.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, CallbackKind Kind) {
+
+ // Determine if we already have a cached 'CheckersOrdered' vector
+ // specifically tailored for the provided <CallbackKind, Stmt kind>. This
+ // can reduce the number of checkers actually called.
+ CheckersOrdered *CO = &Checkers;
+ llvm::OwningPtr<CheckersOrdered> NewCO;
+
+ // The cache key is made up of the and the callback kind (pre- or post-visit)
+ // and the statement kind.
+ CallbackTag K = GetCallbackTag(Kind, S->getStmtClass());
+
+ CheckersOrdered *& CO_Ref = COCache[K];
+
+ if (!CO_Ref) {
+ // If we have no previously cached CheckersOrdered vector for this
+ // statement kind, then create one.
+ NewCO.reset(new CheckersOrdered);
+ }
+ else {
+ // Use the already cached set.
+ CO = CO_Ref;
+ }
+
+ if (CO->empty()) {
+ // If there are no checkers, return early without doing any
+ // more work.
+ Dst.insert(Src);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ ExplodedNodeSet *PrevSet = &Src;
+ unsigned checkersEvaluated = 0;
+
+ for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) {
+ // If all nodes are sunk, bail out early.
+ if (PrevSet->empty())
+ break;
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
+ void *tag = I->first;
+ Checker *checker = I->second;
+ bool respondsToCallback = true;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI) {
+
+ checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag,
+ Kind == PreVisitStmtCallback, respondsToCallback);
+
+ }
+
+ PrevSet = CurrSet;
+
+ if (NewCO.get()) {
+ ++checkersEvaluated;
+ if (respondsToCallback)
+ NewCO->push_back(*I);
+ }
+ }
+
+ // If we built NewCO, check if we called all the checkers. This is important
+ // so that we know that we accurately determined the entire set of checkers
+ // that responds to this callback. Note that 'checkersEvaluated' might
+ // not be the same as Checkers.size() if one of the Checkers generates
+ // a sink node.
+ if (NewCO.get() && checkersEvaluated == Checkers.size())
+ CO_Ref = NewCO.take();
+
+ // Don't autotransition. The CheckerContext objects should do this
+ // automatically.
+}
+
+void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
+ ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src,
+ bool isPrevisit) {
+
+ if (Checkers.empty()) {
+ Dst.insert(Src);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
+
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checker->GR_visitObjCMessage(*CurrSet, *Builder, *this, msg,
+ *NI, tag, isPrevisit);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+
+ // Don't autotransition. The CheckerContext objects should do this
+ // automatically.
+}
+
+void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg,
+ ExplodedNodeSet &Dst,
+ const GRState *state,
+ ExplodedNode *Pred) {
+ bool evaluated = false;
+ ExplodedNodeSet DstTmp;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, msg, Pred, state,
+ tag)) {
+ evaluated = true;
+ break;
+ } else
+ // The checker didn't evaluate the expr. Restore the Dst.
+ DstTmp.clear();
+ }
+
+ if (evaluated)
+ Dst.insert(DstTmp);
+ else
+ Dst.insert(Pred);
+}
+
+// CheckerEvalCall returns true if one of the checkers processed the node.
+// This may return void when all call evaluation logic goes to some checker
+// in the future.
+bool ExprEngine::CheckerEvalCall(const CallExpr *CE,
+ ExplodedNodeSet &Dst,
+ ExplodedNode *Pred) {
+ bool evaluated = false;
+ ExplodedNodeSet DstTmp;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ if (checker->GR_evalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
+ evaluated = true;
+ break;
+ } else
+ // The checker didn't evaluate the expr. Restore the DstTmp set.
+ DstTmp.clear();
+ }
+
+ if (evaluated)
+ Dst.insert(DstTmp);
+ else
+ Dst.insert(Pred);
+
+ return evaluated;
+}
+
+// FIXME: This is largely copy-paste from CheckerVisit(). Need to
+// unify.
+void ExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location,
+ SVal val, bool isPrevisit) {
+
+ if (Checkers.empty()) {
+ Dst.insert(Src);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
+
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
+ *NI, tag, location, val, isPrevisit);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+
+ // Don't autotransition. The CheckerContext objects should do this
+ // automatically.
+}
+//===----------------------------------------------------------------------===//
+// Engine construction and deletion.
+//===----------------------------------------------------------------------===//
+
+static void RegisterInternalChecks(ExprEngine &Eng) {
+ // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
+ // are different than what probably many checks will do since they don't
+ // create BugReports on-the-fly but instead wait until ExprEngine finishes
+ // analyzing a function. Generation of BugReport objects is done via a call
+ // to 'FlushReports' from BugReporter.
+ // The following checks do not need to have their associated BugTypes
+ // explicitly registered with the BugReporter. If they issue any BugReports,
+ // their associated BugType will get registered with the BugReporter
+ // automatically. Note that the check itself is owned by the ExprEngine
+ // object.
+ RegisterAdjustedReturnValueChecker(Eng);
+ // CallAndMessageChecker should be registered before AttrNonNullChecker,
+ // where we assume arguments are not undefined.
+ RegisterCallAndMessageChecker(Eng);
+ RegisterAttrNonNullChecker(Eng);
+ RegisterDereferenceChecker(Eng);
+ RegisterVLASizeChecker(Eng);
+ RegisterDivZeroChecker(Eng);
+ RegisterReturnUndefChecker(Eng);
+ RegisterUndefinedArraySubscriptChecker(Eng);
+ RegisterUndefinedAssignmentChecker(Eng);
+ RegisterUndefBranchChecker(Eng);
+ RegisterUndefCapturedBlockVarChecker(Eng);
+ RegisterUndefResultChecker(Eng);
+
+ // This is not a checker yet.
+ RegisterNoReturnFunctionChecker(Eng);
+ RegisterBuiltinFunctionChecker(Eng);
+ RegisterOSAtomicChecker(Eng);
+}
+
+ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)
+ : AMgr(mgr),
+ Engine(*this),
+ G(Engine.getGraph()),
+ Builder(NULL),
+ StateMgr(getContext(), mgr.getStoreManagerCreator(),
+ mgr.getConstraintManagerCreator(), G.getAllocator(),
+ *this),
+ SymMgr(StateMgr.getSymbolManager()),
+ svalBuilder(StateMgr.getSValBuilder()),
+ EntryNode(NULL), currentStmt(NULL),
+ NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
+ RaiseSel(GetNullarySelector("raise", getContext())),
+ BR(mgr, *this), TF(tf) {
+ // Register internal checks.
+ RegisterInternalChecks(*this);
+
+ // FIXME: Eventually remove the TF object entirely.
+ TF->RegisterChecks(*this);
+ TF->RegisterPrinters(getStateManager().Printers);
+
+ mgr.getCheckerManager()->registerCheckersToEngine(*this);
+
+ if (mgr.shouldEagerlyTrimExplodedGraph()) {
+ // Enable eager node reclaimation when constructing the ExplodedGraph.
+ G.enableNodeReclamation();
+ }
+}
+
+ExprEngine::~ExprEngine() {
+ BR.FlushReports();
+ delete [] NSExceptionInstanceRaiseSelectors;
+
+ // Delete the set of checkers.
+ for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
+ delete I->second;
+
+ for (CheckersOrderedCache::iterator I=COCache.begin(), E=COCache.end();
+ I!=E;++I)
+ delete I->second;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+const GRState* ExprEngine::getInitialState(const LocationContext *InitLoc) {
+ const GRState *state = StateMgr.getInitialState(InitLoc);
+
+ // Preconditions.
+
+ // FIXME: It would be nice if we had a more general mechanism to add
+ // such preconditions. Some day.
+ do {
+ const Decl *D = InitLoc->getDecl();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Precondition: the first argument of 'main' is an integer guaranteed
+ // to be > 0.
+ const IdentifierInfo *II = FD->getIdentifier();
+ if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
+ break;
+
+ const ParmVarDecl *PD = FD->getParamDecl(0);
+ QualType T = PD->getType();
+ if (!T->isIntegerType())
+ break;
+
+ const MemRegion *R = state->getRegion(PD, InitLoc);
+ if (!R)
+ break;
+
+ SVal V = state->getSVal(loc::MemRegionVal(R));
+ SVal Constraint_untested = evalBinOp(state, BO_GT, V,
+ svalBuilder.makeZeroVal(T),
+ getContext().IntTy);
+
+ DefinedOrUnknownSVal *Constraint =
+ dyn_cast<DefinedOrUnknownSVal>(&Constraint_untested);
+
+ if (!Constraint)
+ break;
+
+ if (const GRState *newState = state->assume(*Constraint, true))
+ state = newState;
+
+ break;
+ }
+
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ // Precondition: 'self' is always non-null upon entry to an Objective-C
+ // method.
+ const ImplicitParamDecl *SelfD = MD->getSelfDecl();
+ const MemRegion *R = state->getRegion(SelfD, InitLoc);
+ SVal V = state->getSVal(loc::MemRegionVal(R));
+
+ if (const Loc *LV = dyn_cast<Loc>(&V)) {
+ // Assume that the pointer value in 'self' is non-null.
+ state = state->assume(*LV, true);
+ assert(state && "'self' cannot be null");
+ }
+ }
+ } while (0);
+
+ return state;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-level transfer function logic (Dispatcher).
+//===----------------------------------------------------------------------===//
+
+/// evalAssume - Called by ConstraintManager. Used to call checker-specific
+/// logic for handling assumptions on symbolic values.
+const GRState *ExprEngine::processAssume(const GRState *state, SVal cond,
+ bool assumption) {
+ // Determine if we already have a cached 'CheckersOrdered' vector
+ // specifically tailored for processing assumptions. This
+ // can reduce the number of checkers actually called.
+ CheckersOrdered *CO = &Checkers;
+ llvm::OwningPtr<CheckersOrdered> NewCO;
+
+ CallbackTag K = GetCallbackTag(processAssumeCallback);
+ CheckersOrdered *& CO_Ref = COCache[K];
+
+ if (!CO_Ref) {
+ // If we have no previously cached CheckersOrdered vector for this
+ // statement kind, then create one.
+ NewCO.reset(new CheckersOrdered);
+ }
+ else {
+ // Use the already cached set.
+ CO = CO_Ref;
+ }
+
+ if (!CO->empty()) {
+ // Let the checkers have a crack at the assume before the transfer functions
+ // get their turn.
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) {
+
+ // If any checker declares the state infeasible (or if it starts that
+ // way), bail out.
+ if (!state)
+ return NULL;
+
+ Checker *C = I->second;
+ bool respondsToCallback = true;
+
+ state = C->evalAssume(state, cond, assumption, &respondsToCallback);
+
+ // Check if we're building the cache of checkers that care about
+ // assumptions.
+ if (NewCO.get() && respondsToCallback)
+ NewCO->push_back(*I);
+ }
+
+ // If we got through all the checkers, and we built a list of those that
+ // care about assumptions, save it.
+ if (NewCO.get())
+ CO_Ref = NewCO.take();
+ }
+
+ // If the state is infeasible at this point, bail out.
+ if (!state)
+ return NULL;
+
+ return TF->evalAssume(state, cond, assumption);
+}
+
+bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
+ CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+ CheckersOrdered *CO = COCache[K];
+
+ if (!CO)
+ CO = &Checkers;
+
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+ Checker *C = I->second;
+ if (C->wantsRegionChangeUpdate(state))
+ return true;
+ }
+
+ return false;
+}
+
+const GRState *
+ExprEngine::processRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ // FIXME: Most of this method is copy-pasted from processAssume.
+
+ // Determine if we already have a cached 'CheckersOrdered' vector
+ // specifically tailored for processing region changes. This
+ // can reduce the number of checkers actually called.
+ CheckersOrdered *CO = &Checkers;
+ llvm::OwningPtr<CheckersOrdered> NewCO;
+
+ CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+ CheckersOrdered *& CO_Ref = COCache[K];
+
+ if (!CO_Ref) {
+ // If we have no previously cached CheckersOrdered vector for this
+ // callback, then create one.
+ NewCO.reset(new CheckersOrdered);
+ }
+ else {
+ // Use the already cached set.
+ CO = CO_Ref;
+ }
+
+ // If there are no checkers, just return the state as is.
+ if (CO->empty())
+ return state;
+
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+ // If any checker declares the state infeasible (or if it starts that way),
+ // bail out.
+ if (!state)
+ return NULL;
+
+ Checker *C = I->second;
+ bool respondsToCallback = true;
+
+ state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback);
+
+ // See if we're building a cache of checkers that care about region changes.
+ if (NewCO.get() && respondsToCallback)
+ NewCO->push_back(*I);
+ }
+
+ // If we got through all the checkers, and we built a list of those that
+ // care about region changes, save it.
+ if (NewCO.get())
+ CO_Ref = NewCO.take();
+
+ return state;
+}
+
+void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+ I->second->VisitEndAnalysis(G, BR, *this);
+ }
+}
+
+void ExprEngine::processCFGElement(const CFGElement E,
+ StmtNodeBuilder& builder) {
+ switch (E.getKind()) {
+ case CFGElement::Statement:
+ ProcessStmt(E.getAs<CFGStmt>(), builder);
+ break;
+ case CFGElement::Initializer:
+ ProcessInitializer(E.getAs<CFGInitializer>(), builder);
+ break;
+ case CFGElement::ImplicitDtor:
+ ProcessImplicitDtor(E.getAs<CFGImplicitDtor>(), builder);
+ break;
+ default:
+ // Suppress compiler warning.
+ llvm_unreachable("Unexpected CFGElement kind.");
+ }
+}
+
+void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
+ // Reclaim any unnecessary nodes in the ExplodedGraph.
+ G.reclaimRecentlyAllocatedNodes();
+ // Recycle any unused states in the GRStateManager.
+ StateMgr.recycleUnusedStates();
+
+ currentStmt = S.getStmt();
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ currentStmt->getLocStart(),
+ "Error evaluating statement");
+
+ Builder = &builder;
+ EntryNode = builder.getPredecessor();
+
+ // Create the cleaned state.
+ const LocationContext *LC = EntryNode->getLocationContext();
+ SymbolReaper SymReaper(LC, currentStmt, SymMgr);
+
+ if (AMgr.shouldPurgeDead()) {
+ const GRState *St = EntryNode->getState();
+
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+ Checker *checker = I->second;
+ checker->MarkLiveSymbols(St, SymReaper);
+ }
+
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ CleanedState = StateMgr.removeDeadBindings(St, SFC, SymReaper);
+ } else {
+ CleanedState = EntryNode->getState();
+ }
+
+ // Process any special transfer function for dead symbols.
+ ExplodedNodeSet Tmp;
+
+ if (!SymReaper.hasDeadSymbols())
+ Tmp.Add(EntryNode);
+ else {
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ SaveOr OldHasGen(Builder->hasGeneratedNode);
+
+ SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);
+ Builder->PurgingDeadSymbols = true;
+
+ // FIXME: This should soon be removed.
+ ExplodedNodeSet Tmp2;
+ getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
+ CleanedState, SymReaper);
+
+ if (Checkers.empty())
+ Tmp.insert(Tmp2);
+ else {
+ ExplodedNodeSet Tmp3;
+ ExplodedNodeSet *SrcSet = &Tmp2;
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+ ExplodedNodeSet *DstSet = 0;
+ if (I+1 == E)
+ DstSet = &Tmp;
+ else {
+ DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
+ DstSet->clear();
+ }
+
+ void *tag = I->first;
+ Checker *checker = I->second;
+ for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
+ NI != NE; ++NI)
+ checker->GR_evalDeadSymbols(*DstSet, *Builder, *this, currentStmt,
+ *NI, SymReaper, tag);
+ SrcSet = DstSet;
+ }
+ }
+
+ if (!Builder->BuildSinks && !Builder->hasGeneratedNode)
+ Tmp.Add(EntryNode);
+ }
+
+ bool HasAutoGenerated = false;
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ ExplodedNodeSet Dst;
+
+ // Set the cleaned state.
+ Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));
+
+ // Visit the statement.
+ Visit(currentStmt, *I, Dst);
+
+ // Do we need to auto-generate a node? We only need to do this to generate
+ // a node with a "cleaned" state; CoreEngine will actually handle
+ // auto-transitions for other cases.
+ if (Dst.size() == 1 && *Dst.begin() == EntryNode
+ && !Builder->hasGeneratedNode && !HasAutoGenerated) {
+ HasAutoGenerated = true;
+ builder.generateNode(currentStmt, GetState(EntryNode), *I);
+ }
+ }
+
+ // NULL out these variables to cleanup.
+ CleanedState = NULL;
+ EntryNode = NULL;
+
+ currentStmt = 0;
+
+ Builder = NULL;
+}
+
+void ExprEngine::ProcessInitializer(const CFGInitializer Init,
+ StmtNodeBuilder &builder) {
+ // We don't set EntryNode and currentStmt. And we don't clean up state.
+ const CXXCtorInitializer *BMI = Init.getInitializer();
+
+ ExplodedNode *pred = builder.getPredecessor();
+
+ const StackFrameContext *stackFrame = cast<StackFrameContext>(pred->getLocationContext());
+ const CXXConstructorDecl *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
+ const CXXThisRegion *thisReg = getCXXThisRegion(decl, stackFrame);
+
+ SVal thisVal = pred->getState()->getSVal(thisReg);
+
+ if (BMI->isAnyMemberInitializer()) {
+ ExplodedNodeSet Dst;
+
+ // Evaluate the initializer.
+ Visit(BMI->getInit(), pred, Dst);
+
+ for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
+ ExplodedNode *Pred = *I;
+ const GRState *state = Pred->getState();
+
+ const FieldDecl *FD = BMI->getAnyMember();
+
+ SVal FieldLoc = state->getLValue(FD, thisVal);
+ SVal InitVal = state->getSVal(BMI->getInit());
+ state = state->bindLoc(FieldLoc, InitVal);
+
+ // Use a custom node building process.
+ PostInitializer PP(BMI, stackFrame);
+ // Builder automatically add the generated node to the deferred set,
+ // which are processed in the builder's dtor.
+ builder.generateNode(PP, state, Pred);
+ }
+ return;
+ }
+
+ assert(BMI->isBaseInitializer());
+
+ // Get the base class declaration.
+ const CXXConstructExpr *ctorExpr = cast<CXXConstructExpr>(BMI->getInit());
+
+ // Create the base object region.
+ SVal baseVal =
+ getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
+ const MemRegion *baseReg = baseVal.getAsRegion();
+ assert(baseReg);
+ Builder = &builder;
+ ExplodedNodeSet dst;
+ VisitCXXConstructExpr(ctorExpr, baseReg, pred, dst);
+}
+
+void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
+ StmtNodeBuilder &builder) {
+ Builder = &builder;
+
+ switch (D.getDtorKind()) {
+ case CFGElement::AutomaticObjectDtor:
+ ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder);
+ break;
+ case CFGElement::BaseDtor:
+ ProcessBaseDtor(cast<CFGBaseDtor>(D), builder);
+ break;
+ case CFGElement::MemberDtor:
+ ProcessMemberDtor(cast<CFGMemberDtor>(D), builder);
+ break;
+ case CFGElement::TemporaryDtor:
+ ProcessTemporaryDtor(cast<CFGTemporaryDtor>(D), builder);
+ break;
+ default:
+ llvm_unreachable("Unexpected dtor kind.");
+ }
+}
+
+void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
+ StmtNodeBuilder &builder) {
+ ExplodedNode *pred = builder.getPredecessor();
+ const GRState *state = pred->getState();
+ const VarDecl *varDecl = dtor.getVarDecl();
+
+ QualType varType = varDecl->getType();
+
+ if (const ReferenceType *refType = varType->getAs<ReferenceType>())
+ varType = refType->getPointeeType();
+
+ const CXXRecordDecl *recordDecl = varType->getAsCXXRecordDecl();
+ assert(recordDecl && "get CXXRecordDecl fail");
+ const CXXDestructorDecl *dtorDecl = recordDecl->getDestructor();
+
+ Loc dest = state->getLValue(varDecl, pred->getLocationContext());
+
+ ExplodedNodeSet dstSet;
+ VisitCXXDestructor(dtorDecl, cast<loc::MemRegionVal>(dest).getRegion(),
+ dtor.getTriggerStmt(), pred, dstSet);
+}
+
+void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
+ StmtNodeBuilder &builder) {
+}
+
+void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
+ StmtNodeBuilder &builder) {
+}
+
+void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
+ StmtNodeBuilder &builder) {
+}
+
+void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ S->getLocStart(),
+ "Error evaluating statement");
+
+ // Expressions to ignore.
+ if (const Expr *Ex = dyn_cast<Expr>(S))
+ S = Ex->IgnoreParens();
+
+ // FIXME: add metadata to the CFG so that we can disable
+ // this check when we KNOW that there is no block-level subexpression.
+ // The motivation is that this check requires a hashtable lookup.
+
+ if (S != currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(S)) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ switch (S->getStmtClass()) {
+ // C++ stuff we don't support yet.
+ case Stmt::CXXBindTemporaryExprClass:
+ case Stmt::CXXCatchStmtClass:
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::ExprWithCleanupsClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::CXXTemporaryObjectExprClass:
+ case Stmt::CXXThrowExprClass:
+ case Stmt::CXXTryStmtClass:
+ case Stmt::CXXTypeidExprClass:
+ case Stmt::CXXUuidofExprClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::CXXScalarValueInitExprClass:
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::UnaryTypeTraitExprClass:
+ case Stmt::BinaryTypeTraitExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ case Stmt::CXXNoexceptExprClass:
+ case Stmt::PackExpansionExprClass:
+ case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ {
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ Builder->BuildSinks = true;
+ MakeNode(Dst, S, Pred, GetState(Pred));
+ break;
+ }
+
+ case Stmt::ParenExprClass:
+ llvm_unreachable("ParenExprs already handled.");
+ // Cases that should never be evaluated simply because they shouldn't
+ // appear in the CFG.
+ case Stmt::BreakStmtClass:
+ case Stmt::CaseStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::NoStmtClass:
+ case Stmt::NullStmtClass:
+ llvm_unreachable("Stmt should not be in analyzer evaluation loop");
+ break;
+
+ case Stmt::GNUNullExprClass: {
+ MakeNode(Dst, S, Pred, GetState(Pred)->BindExpr(S, svalBuilder.makeNull()));
+ break;
+ }
+
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::ObjCPropertyRefExprClass:
+ VisitObjCPropertyRefExpr(cast<ObjCPropertyRefExpr>(S), Pred, Dst);
+ break;
+
+ // Cases not handled yet; but will handle some day.
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::ImplicitValueInitExprClass:
+ case Stmt::ObjCAtCatchStmtClass:
+ case Stmt::ObjCAtFinallyStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ case Stmt::ObjCEncodeExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ObjCProtocolExprClass:
+ case Stmt::ObjCSelectorExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::CUDAKernelCallExprClass:
+ case Stmt::OpaqueValueExprClass:
+ // Fall through.
+
+ // Cases we intentionally don't evaluate, since they don't need
+ // to be explicitly evaluated.
+ case Stmt::AddrLabelExprClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::SizeOfPackExprClass:
+ Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
+ break;
+
+ case Stmt::ArraySubscriptExprClass:
+ VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::AsmStmtClass:
+ VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::BlockDeclRefExprClass: {
+ const BlockDeclRefExpr *BE = cast<BlockDeclRefExpr>(S);
+ VisitCommonDeclRefExpr(BE, BE->getDecl(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::BlockExprClass:
+ VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator* B = cast<BinaryOperator>(S);
+ if (B->isLogicalOp()) {
+ VisitLogicalExpr(B, Pred, Dst);
+ break;
+ }
+ else if (B->getOpcode() == BO_Comma) {
+ const GRState* state = GetState(Pred);
+ MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
+ break;
+ }
+
+ if (AMgr.shouldEagerlyAssume() &&
+ (B->isRelationalOp() || B->isEqualityOp())) {
+ ExplodedNodeSet Tmp;
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
+ evalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
+ }
+ else
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+
+ break;
+ }
+
+ case Stmt::CallExprClass: {
+ const CallExpr* C = cast<CallExpr>(S);
+ VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+ break;
+ }
+
+ case Stmt::CXXConstructExprClass: {
+ const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
+ // For block-level CXXConstructExpr, we don't have a destination region.
+ // Let VisitCXXConstructExpr() create one.
+ VisitCXXConstructExpr(C, 0, Pred, Dst);
+ break;
+ }
+
+ case Stmt::CXXMemberCallExprClass: {
+ const CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
+ VisitCXXMemberCallExpr(MCE, Pred, Dst);
+ break;
+ }
+
+ case Stmt::CXXOperatorCallExprClass: {
+ const CXXOperatorCallExpr *C = cast<CXXOperatorCallExpr>(S);
+ VisitCXXOperatorCallExpr(C, Pred, Dst);
+ break;
+ }
+
+ case Stmt::CXXNewExprClass: {
+ const CXXNewExpr *NE = cast<CXXNewExpr>(S);
+ VisitCXXNewExpr(NE, Pred, Dst);
+ break;
+ }
+
+ case Stmt::CXXDeleteExprClass: {
+ const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
+ VisitCXXDeleteExpr(CDE, Pred, Dst);
+ break;
+ }
+ // FIXME: ChooseExpr is really a constant. We need to fix
+ // the CFG do not model them as explicit control-flow.
+
+ case Stmt::ChooseExprClass: { // __builtin_choose_expr
+ const ChooseExpr* C = cast<ChooseExpr>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CompoundAssignOperatorClass:
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ break;
+
+ case Stmt::CompoundLiteralExprClass:
+ VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: { // '?' operator
+ const AbstractConditionalOperator *C
+ = cast<AbstractConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CXXThisExprClass:
+ VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DE = cast<DeclRefExpr>(S);
+ VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::DeclStmtClass:
+ VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::ForStmtClass:
+ // This case isn't for branch processing, but for handling the
+ // initialization of a condition variable.
+ VisitCondInit(cast<ForStmt>(S)->getConditionVariable(), S, Pred, Dst);
+ break;
+
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass: {
+ const CastExpr* C = cast<CastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::IfStmtClass:
+ // This case isn't for branch processing, but for handling the
+ // initialization of a condition variable.
+ VisitCondInit(cast<IfStmt>(S)->getConditionVariable(), S, Pred, Dst);
+ break;
+
+ case Stmt::InitListExprClass:
+ VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::MemberExprClass:
+ VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
+ break;
+ case Stmt::ObjCIvarRefExprClass:
+ VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::ObjCForCollectionStmtClass:
+ VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::ObjCMessageExprClass:
+ VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::ObjCAtThrowStmtClass: {
+ // FIXME: This is not complete. We basically treat @throw as
+ // an abort.
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ Builder->BuildSinks = true;
+ MakeNode(Dst, S, Pred, GetState(Pred));
+ break;
+ }
+
+ case Stmt::ReturnStmtClass:
+ VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::OffsetOfExprClass:
+ VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::SizeOfAlignOfExprClass:
+ VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::StmtExprClass: {
+ const StmtExpr* SE = cast<StmtExpr>(S);
+
+ if (SE->getSubStmt()->body_empty()) {
+ // Empty statement expression.
+ assert(SE->getType() == getContext().VoidTy
+ && "Empty statement expression must have void type.");
+ Dst.Add(Pred);
+ break;
+ }
+
+ if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
+ const GRState* state = GetState(Pred);
+ MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));
+ }
+ else
+ Dst.Add(Pred);
+
+ break;
+ }
+
+ case Stmt::StringLiteralClass: {
+ const GRState* state = GetState(Pred);
+ SVal V = state->getLValue(cast<StringLiteral>(S));
+ MakeNode(Dst, S, Pred, state->BindExpr(S, V));
+ return;
+ }
+
+ case Stmt::SwitchStmtClass:
+ // This case isn't for branch processing, but for handling the
+ // initialization of a condition variable.
+ VisitCondInit(cast<SwitchStmt>(S)->getConditionVariable(), S, Pred, Dst);
+ break;
+
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *U = cast<UnaryOperator>(S);
+ if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
+ ExplodedNodeSet Tmp;
+ VisitUnaryOperator(U, Pred, Tmp);
+ evalEagerlyAssume(Dst, Tmp, U);
+ }
+ else
+ VisitUnaryOperator(U, Pred, Dst);
+ break;
+ }
+
+ case Stmt::WhileStmtClass:
+ // This case isn't for branch processing, but for handling the
+ // initialization of a condition variable.
+ VisitCondInit(cast<WhileStmt>(S)->getConditionVariable(), S, Pred, Dst);
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Block entrance. (Update counters).
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+ GenericNodeBuilder<BlockEntrance> &nodeBuilder){
+
+ // FIXME: Refactor this into a checker.
+ const CFGBlock *block = nodeBuilder.getProgramPoint().getBlock();
+ ExplodedNode *pred = nodeBuilder.getPredecessor();
+
+ if (nodeBuilder.getBlockCounter().getNumVisited(
+ pred->getLocationContext()->getCurrentStackFrame(),
+ block->getBlockID()) >= AMgr.getMaxVisit()) {
+
+ static int tag = 0;
+ nodeBuilder.generateNode(pred->getState(), pred, &tag, true);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Generic node creation.
+//===----------------------------------------------------------------------===//
+
+ExplodedNode* ExprEngine::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St,
+ ProgramPoint::Kind K, const void *tag) {
+ assert (Builder && "StmtNodeBuilder not present.");
+ SaveAndRestore<const void*> OldTag(Builder->Tag);
+ Builder->Tag = tag;
+ return Builder->MakeNode(Dst, S, Pred, St, K);
+}
+
+//===----------------------------------------------------------------------===//
+// Branch processing.
+//===----------------------------------------------------------------------===//
+
+const GRState* ExprEngine::MarkBranch(const GRState* state,
+ const Stmt* Terminator,
+ bool branchTaken) {
+
+ switch (Terminator->getStmtClass()) {
+ default:
+ return state;
+
+ case Stmt::BinaryOperatorClass: { // '&&' and '||'
+
+ const BinaryOperator* B = cast<BinaryOperator>(Terminator);
+ BinaryOperator::Opcode Op = B->getOpcode();
+
+ assert (Op == BO_LAnd || Op == BO_LOr);
+
+ // For &&, if we take the true branch, then the value of the whole
+ // expression is that of the RHS expression.
+ //
+ // For ||, if we take the false branch, then the value of the whole
+ // expression is that of the RHS expression.
+
+ const Expr* Ex = (Op == BO_LAnd && branchTaken) ||
+ (Op == BO_LOr && !branchTaken)
+ ? B->getRHS() : B->getLHS();
+
+ return state->BindExpr(B, UndefinedVal(Ex));
+ }
+
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: { // ?:
+ const AbstractConditionalOperator* C
+ = cast<AbstractConditionalOperator>(Terminator);
+
+ // For ?, if branchTaken == true then the value is either the LHS or
+ // the condition itself. (GNU extension).
+
+ const Expr* Ex;
+
+ if (branchTaken)
+ Ex = C->getTrueExpr();
+ else
+ Ex = C->getFalseExpr();
+
+ return state->BindExpr(C, UndefinedVal(Ex));
+ }
+
+ case Stmt::ChooseExprClass: { // ?:
+
+ const ChooseExpr* C = cast<ChooseExpr>(Terminator);
+
+ const Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
+ return state->BindExpr(C, UndefinedVal(Ex));
+ }
+ }
+}
+
+/// RecoverCastedSymbol - A helper function for ProcessBranch that is used
+/// to try to recover some path-sensitivity for casts of symbolic
+/// integers that promote their values (which are currently not tracked well).
+/// This function returns the SVal bound to Condition->IgnoreCasts if all the
+// cast(s) did was sign-extend the original value.
+static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
+ const Stmt* Condition, ASTContext& Ctx) {
+
+ const Expr *Ex = dyn_cast<Expr>(Condition);
+ if (!Ex)
+ return UnknownVal();
+
+ uint64_t bits = 0;
+ bool bitsInit = false;
+
+ while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ QualType T = CE->getType();
+
+ if (!T->isIntegerType())
+ return UnknownVal();
+
+ uint64_t newBits = Ctx.getTypeSize(T);
+ if (!bitsInit || newBits < bits) {
+ bitsInit = true;
+ bits = newBits;
+ }
+
+ Ex = CE->getSubExpr();
+ }
+
+ // We reached a non-cast. Is it a symbolic value?
+ QualType T = Ex->getType();
+
+ if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
+ return UnknownVal();
+
+ return state->getSVal(Ex);
+}
+
+void ExprEngine::processBranch(const Stmt* Condition, const Stmt* Term,
+ BranchNodeBuilder& builder) {
+
+ // Check for NULL conditions; e.g. "for(;;)"
+ if (!Condition) {
+ builder.markInfeasible(false);
+ return;
+ }
+
+ PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+ Condition->getLocStart(),
+ "Error evaluating branch");
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
+ void *tag = I->first;
+ Checker *checker = I->second;
+ checker->VisitBranchCondition(builder, *this, Condition, tag);
+ }
+
+ // If the branch condition is undefined, return;
+ if (!builder.isFeasible(true) && !builder.isFeasible(false))
+ return;
+
+ const GRState* PrevState = builder.getState();
+ SVal X = PrevState->getSVal(Condition);
+
+ if (X.isUnknown()) {
+ // Give it a chance to recover from unknown.
+ if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+ if (Ex->getType()->isIntegerType()) {
+ // Try to recover some path-sensitivity. Right now casts of symbolic
+ // integers that promote their values are currently not tracked well.
+ // If 'Condition' is such an expression, try and recover the
+ // underlying value and use that instead.
+ SVal recovered = RecoverCastedSymbol(getStateManager(),
+ builder.getState(), Condition,
+ getContext());
+
+ if (!recovered.isUnknown()) {
+ X = recovered;
+ }
+ }
+ }
+ // If the condition is still unknown, give up.
+ if (X.isUnknown()) {
+ builder.generateNode(MarkBranch(PrevState, Term, true), true);
+ builder.generateNode(MarkBranch(PrevState, Term, false), false);
+ return;
+ }
+ }
+
+ DefinedSVal V = cast<DefinedSVal>(X);
+
+ // Process the true branch.
+ if (builder.isFeasible(true)) {
+ if (const GRState *state = PrevState->assume(V, true))
+ builder.generateNode(MarkBranch(state, Term, true), true);
+ else
+ builder.markInfeasible(true);
+ }
+
+ // Process the false branch.
+ if (builder.isFeasible(false)) {
+ if (const GRState *state = PrevState->assume(V, false))
+ builder.generateNode(MarkBranch(state, Term, false), false);
+ else
+ builder.markInfeasible(false);
+ }
+}
+
+/// processIndirectGoto - Called by CoreEngine. Used to generate successor
+/// nodes by processing the 'effects' of a computed goto jump.
+void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
+
+ const GRState *state = builder.getState();
+ SVal V = state->getSVal(builder.getTarget());
+
+ // Three possibilities:
+ //
+ // (1) We know the computed label.
+ // (2) The label is NULL (or some other constant), or Undefined.
+ // (3) We have no clue about the label. Dispatch to all targets.
+ //
+
+ typedef IndirectGotoNodeBuilder::iterator iterator;
+
+ if (isa<loc::GotoLabel>(V)) {
+ const LabelDecl *L = cast<loc::GotoLabel>(V).getLabel();
+
+ for (iterator I = builder.begin(), E = builder.end(); I != E; ++I) {
+ if (I.getLabel() == L) {
+ builder.generateNode(I, state);
+ return;
+ }
+ }
+
+ assert(false && "No block with label.");
+ return;
+ }
+
+ if (isa<loc::ConcreteInt>(V) || isa<UndefinedVal>(V)) {
+ // Dispatch to the first target and mark it as a sink.
+ //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
+ // FIXME: add checker visit.
+ // UndefBranches.insert(N);
+ return;
+ }
+
+ // This is really a catch-all. We don't support symbolics yet.
+ // FIXME: Implement dispatch for symbolic pointers.
+
+ for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
+ builder.generateNode(I, state);
+}
+
+
+void ExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L,
+ const Expr* R,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+
+ assert(Ex == currentStmt &&
+ Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
+
+ const GRState* state = GetState(Pred);
+ SVal X = state->getSVal(Ex);
+
+ assert (X.isUndef());
+
+ const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+ assert(SE);
+ X = state->getSVal(SE);
+
+ // Make sure that we invalidate the previous binding.
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));
+}
+
+/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
+/// nodes when the control reaches the end of a function.
+void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
+ getTF().evalEndPath(*this, builder);
+ StateMgr.EndPath(builder.getState());
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
+ void *tag = I->first;
+ Checker *checker = I->second;
+ checker->evalEndPath(builder, tag, *this);
+ }
+}
+
+/// ProcessSwitch - Called by CoreEngine. Used to generate successor
+/// nodes by processing the 'effects' of a switch statement.
+void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
+ typedef SwitchNodeBuilder::iterator iterator;
+ const GRState* state = builder.getState();
+ const Expr* CondE = builder.getCondition();
+ SVal CondV_untested = state->getSVal(CondE);
+
+ if (CondV_untested.isUndef()) {
+ //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
+ // FIXME: add checker
+ //UndefBranches.insert(N);
+
+ return;
+ }
+ DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
+
+ const GRState *DefaultSt = state;
+
+ iterator I = builder.begin(), EI = builder.end();
+ bool defaultIsFeasible = I == EI;
+
+ for ( ; I != EI; ++I) {
+ const CaseStmt* Case = I.getCase();
+
+ // Evaluate the LHS of the case value.
+ Expr::EvalResult V1;
+ bool b = Case->getLHS()->Evaluate(V1, getContext());
+
+ // Sanity checks. These go away in Release builds.
+ assert(b && V1.Val.isInt() && !V1.HasSideEffects
+ && "Case condition must evaluate to an integer constant.");
+ (void)b; // silence unused variable warning
+ assert(V1.Val.getInt().getBitWidth() ==
+ getContext().getTypeSize(CondE->getType()));
+
+ // Get the RHS of the case, if it exists.
+ Expr::EvalResult V2;
+
+ if (const Expr* E = Case->getRHS()) {
+ b = E->Evaluate(V2, getContext());
+ assert(b && V2.Val.isInt() && !V2.HasSideEffects
+ && "Case condition must evaluate to an integer constant.");
+ (void)b; // silence unused variable warning
+ }
+ else
+ V2 = V1;
+
+ // FIXME: Eventually we should replace the logic below with a range
+ // comparison, rather than concretize the values within the range.
+ // This should be easy once we have "ranges" for NonLVals.
+
+ do {
+ nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
+ DefinedOrUnknownSVal Res = svalBuilder.evalEQ(DefaultSt ? DefaultSt : state,
+ CondV, CaseVal);
+
+ // Now "assume" that the case matches.
+ if (const GRState* stateNew = state->assume(Res, true)) {
+ builder.generateCaseStmtNode(I, stateNew);
+
+ // If CondV evaluates to a constant, then we know that this
+ // is the *only* case that we can take, so stop evaluating the
+ // others.
+ if (isa<nonloc::ConcreteInt>(CondV))
+ return;
+ }
+
+ // Now "assume" that the case doesn't match. Add this state
+ // to the default state (if it is feasible).
+ if (DefaultSt) {
+ if (const GRState *stateNew = DefaultSt->assume(Res, false)) {
+ defaultIsFeasible = true;
+ DefaultSt = stateNew;
+ }
+ else {
+ defaultIsFeasible = false;
+ DefaultSt = NULL;
+ }
+ }
+
+ // Concretize the next value in the range.
+ if (V1.Val.getInt() == V2.Val.getInt())
+ break;
+
+ ++V1.Val.getInt();
+ assert (V1.Val.getInt() <= V2.Val.getInt());
+
+ } while (true);
+ }
+
+ if (!defaultIsFeasible)
+ return;
+
+ // If we have switch(enum value), the default branch is not
+ // feasible if all of the enum constants not covered by 'case:' statements
+ // are not feasible values for the switch condition.
+ //
+ // Note that this isn't as accurate as it could be. Even if there isn't
+ // a case for a particular enum value as long as that enum value isn't
+ // feasible then it shouldn't be considered for making 'default:' reachable.
+ const SwitchStmt *SS = builder.getSwitch();
+ const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();
+ if (CondExpr->getType()->getAs<EnumType>()) {
+ if (SS->isAllEnumCasesCovered())
+ return;
+ }
+
+ builder.generateDefaultCaseNode(DefaultSt);
+}
+
+void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
+ const GRState *state = B.getState()->enterStackFrame(B.getCalleeContext());
+ B.generateNode(state);
+}
+
+void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
+ const GRState *state = B.getState();
+ const ExplodedNode *Pred = B.getPredecessor();
+ const StackFrameContext *calleeCtx =
+ cast<StackFrameContext>(Pred->getLocationContext());
+ const Stmt *CE = calleeCtx->getCallSite();
+
+ // If the callee returns an expression, bind its value to CallExpr.
+ const Stmt *ReturnedExpr = state->get<ReturnExpr>();
+ if (ReturnedExpr) {
+ SVal RetVal = state->getSVal(ReturnedExpr);
+ state = state->BindExpr(CE, RetVal);
+ // Clear the return expr GDM.
+ state = state->remove<ReturnExpr>();
+ }
+
+ // Bind the constructed object value to CXXConstructExpr.
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
+ const CXXThisRegion *ThisR =
+ getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
+
+ SVal ThisV = state->getSVal(ThisR);
+ // Always bind the region to the CXXConstructExpr.
+ state = state->BindExpr(CCE, ThisV);
+ }
+
+ B.generateNode(state);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions: logical operations ('&&', '||').
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+
+ assert(B->getOpcode() == BO_LAnd ||
+ B->getOpcode() == BO_LOr);
+
+ assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
+
+ const GRState* state = GetState(Pred);
+ SVal X = state->getSVal(B);
+ assert(X.isUndef());
+
+ const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
+ assert(Ex);
+
+ if (Ex == B->getRHS()) {
+ X = state->getSVal(Ex);
+
+ // Handle undefined values.
+ if (X.isUndef()) {
+ MakeNode(Dst, B, Pred, state->BindExpr(B, X));
+ return;
+ }
+
+ DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);
+
+ // We took the RHS. Because the value of the '&&' or '||' expression must
+ // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0
+ // or 1. Alternatively, we could take a lazy approach, and calculate this
+ // value later when necessary. We don't have the machinery in place for
+ // this right now, and since most logical expressions are used for branches,
+ // the payoff is not likely to be large. Instead, we do eager evaluation.
+ if (const GRState *newState = state->assume(XD, true))
+ MakeNode(Dst, B, Pred,
+ newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
+
+ if (const GRState *newState = state->assume(XD, false))
+ MakeNode(Dst, B, Pred,
+ newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
+ }
+ else {
+ // We took the LHS expression. Depending on whether we are '&&' or
+ // '||' we know what the value of the expression is via properties of
+ // the short-circuiting.
+ X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
+ B->getType());
+ MakeNode(Dst, B, Pred, state->BindExpr(B, X));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions: Loads and stores.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+
+ ExplodedNodeSet Tmp;
+
+ CanQualType T = getContext().getCanonicalType(BE->getType());
+ SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
+ Pred->getLocationContext());
+
+ MakeNode(Tmp, BE, Pred, GetState(Pred)->BindExpr(BE, V),
+ ProgramPoint::PostLValueKind);
+
+ // Post-visit the BlockExpr.
+ CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);
+}
+
+void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ const GRState *state = GetState(Pred);
+
+ if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
+ assert(Ex->isLValue());
+ SVal V = state->getLValue(VD, Pred->getLocationContext());
+
+ // For references, the 'lvalue' is the pointer address stored in the
+ // reference region.
+ if (VD->getType()->isReferenceType()) {
+ if (const MemRegion *R = V.getAsRegion())
+ V = state->getSVal(R);
+ else
+ V = UnknownVal();
+ }
+
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
+ ProgramPoint::PostLValueKind);
+ return;
+ }
+ if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
+ assert(!Ex->isLValue());
+ SVal V = svalBuilder.makeIntVal(ED->getInitVal());
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
+ return;
+ }
+ if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
+ SVal V = svalBuilder.getFunctionPointer(FD);
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
+ ProgramPoint::PostLValueKind);
+ return;
+ }
+ assert (false &&
+ "ValueDecl support for this ValueDecl not implemented.");
+}
+
+/// VisitArraySubscriptExpr - Transfer function for array accesses
+void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* A,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst){
+
+ const Expr* Base = A->getBase()->IgnoreParens();
+ const Expr* Idx = A->getIdx()->IgnoreParens();
+
+ // Evaluate the base.
+ ExplodedNodeSet Tmp;
+ Visit(Base, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
+ ExplodedNodeSet Tmp2;
+ Visit(Idx, *I1, Tmp2); // Evaluate the index.
+ ExplodedNodeSet Tmp3;
+ CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);
+
+ for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
+ const GRState* state = GetState(*I2);
+ SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
+ state->getSVal(Base));
+ assert(A->isLValue());
+ MakeNode(Dst, A, *I2, state->BindExpr(A, V), ProgramPoint::PostLValueKind);
+ }
+ }
+}
+
+/// VisitMemberExpr - Transfer function for member expressions.
+void ExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+
+ Expr *baseExpr = M->getBase()->IgnoreParens();
+ ExplodedNodeSet dstBase;
+ Visit(baseExpr, Pred, dstBase);
+
+ FieldDecl *field = dyn_cast<FieldDecl>(M->getMemberDecl());
+ if (!field) // FIXME: skipping member expressions for non-fields
+ return;
+
+ for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();
+ I != E; ++I) {
+ const GRState* state = GetState(*I);
+ SVal baseExprVal = state->getSVal(baseExpr);
+ if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
+ isa<nonloc::CompoundVal>(baseExprVal) ||
+ // FIXME: This can originate by conjuring a symbol for an unknown
+ // temporary struct object, see test/Analysis/fields.c:
+ // (p = getit()).x
+ isa<nonloc::SymbolVal>(baseExprVal)) {
+ MakeNode(Dst, M, *I, state->BindExpr(M, UnknownVal()));
+ continue;
+ }
+
+ // FIXME: Should we insert some assumption logic in here to determine
+ // if "Base" is a valid piece of memory? Before we put this assumption
+ // later when using FieldOffset lvals (which we no longer have).
+
+ // For all other cases, compute an lvalue.
+ SVal L = state->getLValue(field, baseExprVal);
+ if (M->isLValue())
+ MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
+ else
+ evalLoad(Dst, M, *I, state, L);
+ }
+}
+
+/// evalBind - Handle the semantics of binding a value to a specific location.
+/// This method is used by evalStore and (soon) VisitDeclStmt, and others.
+void ExprEngine::evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
+ ExplodedNode* Pred, const GRState* state,
+ SVal location, SVal Val, bool atDeclInit) {
+
+
+ // Do a previsit of the bind.
+ ExplodedNodeSet CheckedSet, Src;
+ Src.Add(Pred);
+ CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I!=E; ++I) {
+
+ if (Pred != *I)
+ state = GetState(*I);
+
+ const GRState* newState = 0;
+
+ if (atDeclInit) {
+ const VarRegion *VR =
+ cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
+
+ newState = state->bindDecl(VR, Val);
+ }
+ else {
+ if (location.isUnknown()) {
+ // We know that the new state will be the same as the old state since
+ // the location of the binding is "unknown". Consequently, there
+ // is no reason to just create a new node.
+ newState = state;
+ }
+ else {
+ // We are binding to a value other than 'unknown'. Perform the binding
+ // using the StoreManager.
+ newState = state->bindLoc(cast<Loc>(location), Val);
+ }
+ }
+
+ // The next thing to do is check if the TransferFuncs object wants to
+ // update the state based on the new binding. If the GRTransferFunc object
+ // doesn't do anything, just auto-propagate the current state.
+
+ // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
+ // is non-NULL. Checkers typically care about
+
+ StmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
+ true);
+
+ getTF().evalBind(BuilderRef, location, Val);
+ }
+}
+
+/// evalStore - Handle the semantics of a store via an assignment.
+/// @param Dst The node set to store generated state nodes
+/// @param AssignE The assignment expression if the store happens in an
+/// assignment.
+/// @param LocatioinE The location expression that is stored to.
+/// @param state The current simulation state
+/// @param location The location to store the value
+/// @param Val The value to be stored
+void ExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
+ const Expr* LocationE,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location, SVal Val,
+ const void *tag) {
+
+ assert(Builder && "StmtNodeBuilder must be defined.");
+
+ // Proceed with the store. We use AssignE as the anchor for the PostStore
+ // ProgramPoint if it is non-NULL, and LocationE otherwise.
+ const Expr *StoreE = AssignE ? AssignE : LocationE;
+
+ if (isa<loc::ObjCPropRef>(location)) {
+ loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location);
+ ExplodedNodeSet src = Pred;
+ return VisitObjCMessage(ObjCPropertySetter(prop.getPropRefExpr(),
+ StoreE, Val), src, Dst);
+ }
+
+ // Evaluate the location (checks for bad dereferences).
+ ExplodedNodeSet Tmp;
+ evalLocation(Tmp, LocationE, Pred, state, location, tag, false);
+
+ if (Tmp.empty())
+ return;
+
+ assert(!location.isUndef());
+
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,
+ ProgramPoint::PostStoreKind);
+
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
+ evalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
+}
+
+void ExprEngine::evalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location,
+ const void *tag, QualType LoadTy) {
+ assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
+
+ if (isa<loc::ObjCPropRef>(location)) {
+ loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location);
+ ExplodedNodeSet src = Pred;
+ return VisitObjCMessage(ObjCPropertyGetter(prop.getPropRefExpr(), Ex),
+ src, Dst);
+ }
+
+ // Are we loading from a region? This actually results in two loads; one
+ // to fetch the address of the referenced value and one to fetch the
+ // referenced value.
+ if (const TypedRegion *TR =
+ dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
+
+ QualType ValTy = TR->getValueType();
+ if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
+ static int loadReferenceTag = 0;
+ ExplodedNodeSet Tmp;
+ evalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,
+ getContext().getPointerType(RT->getPointeeType()));
+
+ // Perform the load from the referenced value.
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
+ state = GetState(*I);
+ location = state->getSVal(Ex);
+ evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
+ }
+ return;
+ }
+ }
+
+ evalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
+}
+
+void ExprEngine::evalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location,
+ const void *tag, QualType LoadTy) {
+
+ // Evaluate the location (checks for bad dereferences).
+ ExplodedNodeSet Tmp;
+ evalLocation(Tmp, Ex, Pred, state, location, tag, true);
+
+ if (Tmp.empty())
+ return;
+
+ assert(!location.isUndef());
+
+ SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
+
+ // Proceed with the load.
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ state = GetState(*NI);
+
+ if (location.isUnknown()) {
+ // This is important. We must nuke the old binding.
+ MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+ ProgramPoint::PostLoadKind, tag);
+ }
+ else {
+ if (LoadTy.isNull())
+ LoadTy = Ex->getType();
+ SVal V = state->getSVal(cast<Loc>(location), LoadTy);
+ MakeNode(Dst, Ex, *NI, state->bindExprAndLocation(Ex, location, V),
+ ProgramPoint::PostLoadKind, tag);
+ }
+ }
+}
+
+void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
+ ExplodedNode* Pred,
+ const GRState* state, SVal location,
+ const void *tag, bool isLoad) {
+ // Early checks for performance reason.
+ if (location.isUnknown() || Checkers.empty()) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ ExplodedNodeSet Src, Tmp;
+ Src.Add(Pred);
+ ExplodedNodeSet *PrevSet = &Src;
+
+ for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+ {
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+ CurrSet->clear();
+ }
+
+ void *tag = I->first;
+ Checker *checker = I->second;
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI) {
+ // Use the 'state' argument only when the predecessor node is the
+ // same as Pred. This allows us to catch updates to the state.
+ checker->GR_visitLocation(*CurrSet, *Builder, *this, S, *NI,
+ *NI == Pred ? state : GetState(*NI),
+ location, tag, isLoad);
+ }
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+}
+
+bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
+ ExplodedNode *Pred) {
+ const GRState *state = GetState(Pred);
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ // Check if the function definition is in the same translation unit.
+ if (FD->hasBody(FD)) {
+ const StackFrameContext *stackFrame =
+ AMgr.getStackFrame(AMgr.getAnalysisContext(FD),
+ Pred->getLocationContext(),
+ CE, Builder->getBlock(), Builder->getIndex());
+ // Now we have the definition of the callee, create a CallEnter node.
+ CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
+
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ Dst.Add(N);
+ return true;
+ }
+
+ // Check if we can find the function definition in other translation units.
+ if (AMgr.hasIndexer()) {
+ AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
+ if (C == 0)
+ return false;
+ const StackFrameContext *stackFrame =
+ AMgr.getStackFrame(C, Pred->getLocationContext(),
+ CE, Builder->getBlock(), Builder->getIndex());
+ CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ Dst.Add(N);
+ return true;
+ }
+
+ return false;
+}
+
+void ExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+ CallExpr::const_arg_iterator AI,
+ CallExpr::const_arg_iterator AE,
+ ExplodedNodeSet& Dst) {
+
+ // Determine the type of function we're calling (if available).
+ const FunctionProtoType *Proto = NULL;
+ QualType FnType = CE->getCallee()->IgnoreParens()->getType();
+ if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
+ Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
+
+ // Evaluate the arguments.
+ ExplodedNodeSet ArgsEvaluated;
+ evalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, ArgsEvaluated);
+
+ // Now process the call itself.
+ ExplodedNodeSet DstTmp;
+ const Expr* Callee = CE->getCallee()->IgnoreParens();
+
+ for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(),
+ NE=ArgsEvaluated.end(); NI != NE; ++NI) {
+ // Evaluate the callee.
+ ExplodedNodeSet DstTmp2;
+ Visit(Callee, *NI, DstTmp2);
+ // Perform the previsit of the CallExpr, storing the results in DstTmp.
+ CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback);
+ }
+
+ // Finally, evaluate the function call. We try each of the checkers
+ // to see if the can evaluate the function call.
+ ExplodedNodeSet DstTmp3;
+
+ for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
+ DI != DE; ++DI) {
+
+ const GRState* state = GetState(*DI);
+ SVal L = state->getSVal(Callee);
+
+ // FIXME: Add support for symbolic function calls (calls involving
+ // function pointer values that are symbolic).
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ ExplodedNodeSet DstChecker;
+
+ // If the callee is processed by a checker, skip the rest logic.
+ if (CheckerEvalCall(CE, DstChecker, *DI))
+ DstTmp3.insert(DstChecker);
+ else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {
+ // Callee is inlined. We shouldn't do post call checking.
+ return;
+ }
+ else {
+ for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
+ DE_Checker = DstChecker.end();
+ DI_Checker != DE_Checker; ++DI_Checker) {
+
+ // Dispatch to the plug-in transfer function.
+ unsigned oldSize = DstTmp3.size();
+ SaveOr OldHasGen(Builder->hasGeneratedNode);
+ Pred = *DI_Checker;
+
+ // Dispatch to transfer function logic to handle the call itself.
+ // FIXME: Allow us to chain together transfer functions.
+ assert(Builder && "StmtNodeBuilder must be defined.");
+ getTF().evalCall(DstTmp3, *this, *Builder, CE, L, Pred);
+
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+ if (!Builder->BuildSinks && DstTmp3.size() == oldSize &&
+ !Builder->hasGeneratedNode)
+ MakeNode(DstTmp3, CE, Pred, state);
+ }
+ }
+ }
+
+ // Finally, perform the post-condition check of the CallExpr and store
+ // the created nodes in 'Dst'.
+ CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C dot-syntax to access a property.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Ex,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ExplodedNodeSet dstBase;
+
+ // Visit the receiver (if any).
+ if (Ex->isObjectReceiver())
+ Visit(Ex->getBase(), Pred, dstBase);
+ else
+ dstBase = Pred;
+
+ ExplodedNodeSet dstPropRef;
+
+ // Using the base, compute the lvalue of the instance variable.
+ for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();
+ I!=E; ++I) {
+ ExplodedNode *nodeBase = *I;
+ const GRState *state = GetState(nodeBase);
+ MakeNode(dstPropRef, Ex, *I, state->BindExpr(Ex, loc::ObjCPropRef(Ex)));
+ }
+
+ Dst.insert(dstPropRef);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C ivar references.
+//===----------------------------------------------------------------------===//
+
+static std::pair<const void*,const void*> EagerlyAssumeTag
+ = std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
+
+void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ const Expr *Ex) {
+ for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
+ ExplodedNode *Pred = *I;
+
+ // Test if the previous node was as the same expression. This can happen
+ // when the expression fails to evaluate to anything meaningful and
+ // (as an optimization) we don't generate a node.
+ ProgramPoint P = Pred->getLocation();
+ if (!isa<PostStmt>(P) || cast<PostStmt>(P).getStmt() != Ex) {
+ Dst.Add(Pred);
+ continue;
+ }
+
+ const GRState* state = GetState(Pred);
+ SVal V = state->getSVal(Ex);
+ if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {
+ // First assume that the condition is true.
+ if (const GRState *stateTrue = state->assume(*SEV, true)) {
+ stateTrue = stateTrue->BindExpr(Ex,
+ svalBuilder.makeIntVal(1U, Ex->getType()));
+ Dst.Add(Builder->generateNode(PostStmtCustom(Ex,
+ &EagerlyAssumeTag, Pred->getLocationContext()),
+ stateTrue, Pred));
+ }
+
+ // Next, assume that the condition is false.
+ if (const GRState *stateFalse = state->assume(*SEV, false)) {
+ stateFalse = stateFalse->BindExpr(Ex,
+ svalBuilder.makeIntVal(0U, Ex->getType()));
+ Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,
+ Pred->getLocationContext()),
+ stateFalse, Pred));
+ }
+ }
+ else
+ Dst.Add(Pred);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C @synchronized.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+
+ // The mutex expression is a CFGElement, so we don't need to explicitly
+ // visit it since it will already be processed.
+
+ // Pre-visit the ObjCAtSynchronizedStmt.
+ ExplodedNodeSet Tmp;
+ Tmp.Add(Pred);
+ CheckerVisit(S, Dst, Tmp, PreVisitStmtCallback);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C ivar references.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* Ex,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+
+ // Visit the base expression, which is needed for computing the lvalue
+ // of the ivar.
+ ExplodedNodeSet dstBase;
+ const Expr *baseExpr = Ex->getBase();
+ Visit(baseExpr, Pred, dstBase);
+
+ ExplodedNodeSet dstIvar;
+
+ // Using the base, compute the lvalue of the instance variable.
+ for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();
+ I!=E; ++I) {
+ ExplodedNode *nodeBase = *I;
+ const GRState *state = GetState(nodeBase);
+ SVal baseVal = state->getSVal(baseExpr);
+ SVal location = state->getLValue(Ex->getDecl(), baseVal);
+ MakeNode(dstIvar, Ex, *I, state->BindExpr(Ex, location));
+ }
+
+ // Perform the post-condition check of the ObjCIvarRefExpr and store
+ // the created nodes in 'Dst'.
+ CheckerVisit(Ex, Dst, dstIvar, PostVisitStmtCallback);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C fast enumeration 'for' statements.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+
+ // ObjCForCollectionStmts are processed in two places. This method
+ // handles the case where an ObjCForCollectionStmt* occurs as one of the
+ // statements within a basic block. This transfer function does two things:
+ //
+ // (1) binds the next container value to 'element'. This creates a new
+ // node in the ExplodedGraph.
+ //
+ // (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
+ // whether or not the container has any more elements. This value
+ // will be tested in ProcessBranch. We need to explicitly bind
+ // this value because a container can contain nil elements.
+ //
+ // FIXME: Eventually this logic should actually do dispatches to
+ // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
+ // This will require simulating a temporary NSFastEnumerationState, either
+ // through an SVal or through the use of MemRegions. This value can
+ // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
+ // terminates we reclaim the temporary (it goes out of scope) and we
+ // we can test if the SVal is 0 or if the MemRegion is null (depending
+ // on what approach we take).
+ //
+ // For now: simulate (1) by assigning either a symbol or nil if the
+ // container is empty. Thus this transfer function will by default
+ // result in state splitting.
+
+ const Stmt* elem = S->getElement();
+ SVal ElementV;
+
+ if (const DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
+ const VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
+ assert (ElemD->getInit() == 0);
+ ElementV = GetState(Pred)->getLValue(ElemD, Pred->getLocationContext());
+ VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ Visit(cast<Expr>(elem), Pred, Tmp);
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
+ const GRState* state = GetState(*I);
+ VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));
+ }
+}
+
+void ExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ SVal ElementV) {
+
+ // Check if the location we are writing back to is a null pointer.
+ const Stmt* elem = S->getElement();
+ ExplodedNodeSet Tmp;
+ evalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
+
+ if (Tmp.empty())
+ return;
+
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
+ Pred = *NI;
+ const GRState *state = GetState(Pred);
+
+ // Handle the case where the container still has elements.
+ SVal TrueV = svalBuilder.makeTruthVal(1);
+ const GRState *hasElems = state->BindExpr(S, TrueV);
+
+ // Handle the case where the container has no elements.
+ SVal FalseV = svalBuilder.makeTruthVal(0);
+ const GRState *noElems = state->BindExpr(S, FalseV);
+
+ if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
+ if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
+ // FIXME: The proper thing to do is to really iterate over the
+ // container. We will do this with dispatch logic to the store.
+ // For now, just 'conjure' up a symbolic value.
+ QualType T = R->getValueType();
+ assert(Loc::isLocType(T));
+ unsigned Count = Builder->getCurrentBlockCount();
+ SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
+ SVal V = svalBuilder.makeLoc(Sym);
+ hasElems = hasElems->bindLoc(ElementV, V);
+
+ // Bind the location to 'nil' on the false branch.
+ SVal nilV = svalBuilder.makeIntVal(0, T);
+ noElems = noElems->bindLoc(ElementV, nilV);
+ }
+
+ // Create the new nodes.
+ MakeNode(Dst, S, Pred, hasElems);
+ MakeNode(Dst, S, Pred, noElems);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C message expressions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCMsgWLItem {
+public:
+ ObjCMessageExpr::const_arg_iterator I;
+ ExplodedNode *N;
+
+ ObjCMsgWLItem(const ObjCMessageExpr::const_arg_iterator &i, ExplodedNode *n)
+ : I(i), N(n) {}
+};
+} // end anonymous namespace
+
+void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst){
+
+ // Create a worklist to process both the arguments.
+ llvm::SmallVector<ObjCMsgWLItem, 20> WL;
+
+ // But first evaluate the receiver (if any).
+ ObjCMessageExpr::const_arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
+ if (const Expr *Receiver = ME->getInstanceReceiver()) {
+ ExplodedNodeSet Tmp;
+ Visit(Receiver, Pred, Tmp);
+
+ if (Tmp.empty())
+ return;
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I)
+ WL.push_back(ObjCMsgWLItem(AI, *I));
+ }
+ else
+ WL.push_back(ObjCMsgWLItem(AI, Pred));
+
+ // Evaluate the arguments.
+ ExplodedNodeSet ArgsEvaluated;
+ while (!WL.empty()) {
+ ObjCMsgWLItem Item = WL.back();
+ WL.pop_back();
+
+ if (Item.I == AE) {
+ ArgsEvaluated.insert(Item.N);
+ continue;
+ }
+
+ // Evaluate the subexpression.
+ ExplodedNodeSet Tmp;
+
+ // FIXME: [Objective-C++] handle arguments that are references
+ Visit(*Item.I, Item.N, Tmp);
+
+ // Enqueue evaluating the next argument on the worklist.
+ ++(Item.I);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
+ WL.push_back(ObjCMsgWLItem(Item.I, *NI));
+ }
+
+ // Now that the arguments are processed, handle the ObjC message.
+ VisitObjCMessage(ME, ArgsEvaluated, Dst);
+}
+
+void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
+ ExplodedNodeSet &Src, ExplodedNodeSet& Dst) {
+
+ // Handle the previsits checks.
+ ExplodedNodeSet DstPrevisit;
+ CheckerVisitObjCMessage(msg, DstPrevisit, Src, /*isPreVisit=*/true);
+
+ // Proceed with evaluate the message expression.
+ ExplodedNodeSet dstEval;
+
+ for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(),
+ DE = DstPrevisit.end(); DI != DE; ++DI) {
+
+ ExplodedNode *Pred = *DI;
+ bool RaisesException = false;
+ unsigned oldSize = dstEval.size();
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ SaveOr OldHasGen(Builder->hasGeneratedNode);
+
+ if (const Expr *Receiver = msg.getInstanceReceiver()) {
+ const GRState *state = GetState(Pred);
+
+ // Bifurcate the state into nil and non-nil ones.
+ DefinedOrUnknownSVal receiverVal =
+ cast<DefinedOrUnknownSVal>(state->getSVal(Receiver));
+
+ const GRState *notNilState, *nilState;
+ llvm::tie(notNilState, nilState) = state->assume(receiverVal);
+
+ // There are three cases: can be nil or non-nil, must be nil, must be
+ // non-nil. We handle must be nil, and merge the rest two into non-nil.
+ if (nilState && !notNilState) {
+ CheckerEvalNilReceiver(msg, dstEval, nilState, Pred);
+ continue;
+ }
+
+ // Check if the "raise" message was sent.
+ assert(notNilState);
+ if (msg.getSelector() == RaiseSel)
+ RaisesException = true;
+
+ // Check if we raise an exception. For now treat these as sinks.
+ // Eventually we will want to handle exceptions properly.
+ if (RaisesException)
+ Builder->BuildSinks = true;
+
+ // Dispatch to plug-in transfer function.
+ evalObjCMessage(dstEval, msg, Pred, notNilState);
+ }
+ else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
+ IdentifierInfo* ClsName = Iface->getIdentifier();
+ Selector S = msg.getSelector();
+
+ // Check for special instance methods.
+ if (!NSExceptionII) {
+ ASTContext& Ctx = getContext();
+ NSExceptionII = &Ctx.Idents.get("NSException");
+ }
+
+ if (ClsName == NSExceptionII) {
+ enum { NUM_RAISE_SELECTORS = 2 };
+
+ // Lazily create a cache of the selectors.
+ if (!NSExceptionInstanceRaiseSelectors) {
+ ASTContext& Ctx = getContext();
+ NSExceptionInstanceRaiseSelectors =
+ new Selector[NUM_RAISE_SELECTORS];
+ llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
+ unsigned idx = 0;
+
+ // raise:format:
+ II.push_back(&Ctx.Idents.get("raise"));
+ II.push_back(&Ctx.Idents.get("format"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
+
+ // raise:format::arguments:
+ II.push_back(&Ctx.Idents.get("arguments"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
+ }
+
+ for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
+ if (S == NSExceptionInstanceRaiseSelectors[i]) {
+ RaisesException = true;
+ break;
+ }
+ }
+
+ // Check if we raise an exception. For now treat these as sinks.
+ // Eventually we will want to handle exceptions properly.
+ if (RaisesException)
+ Builder->BuildSinks = true;
+
+ // Dispatch to plug-in transfer function.
+ evalObjCMessage(dstEval, msg, Pred, Builder->GetState(Pred));
+ }
+
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+ if (!Builder->BuildSinks && dstEval.size() == oldSize &&
+ !Builder->hasGeneratedNode)
+ MakeNode(dstEval, msg.getOriginExpr(), Pred, GetState(Pred));
+ }
+
+ // Finally, perform the post-condition check of the ObjCMessageExpr and store
+ // the created nodes in 'Dst'.
+ CheckerVisitObjCMessage(msg, Dst, dstEval, /*isPreVisit=*/false);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions: Miscellaneous statements.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+
+ ExplodedNodeSet S1;
+ Visit(Ex, Pred, S1);
+ ExplodedNodeSet S2;
+ CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
+
+ if (CastE->getCastKind() == CK_LValueToRValue ||
+ CastE->getCastKind() == CK_GetObjCProperty) {
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I!=E; ++I) {
+ ExplodedNode *subExprNode = *I;
+ const GRState *state = GetState(subExprNode);
+ evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
+ }
+ return;
+ }
+
+ // All other casts.
+ QualType T = CastE->getType();
+ QualType ExTy = Ex->getType();
+
+ if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
+ T = ExCast->getTypeAsWritten();
+
+#if 0
+ // If we are evaluating the cast in an lvalue context, we implicitly want
+ // the cast to evaluate to a location.
+ if (asLValue) {
+ ASTContext &Ctx = getContext();
+ T = Ctx.getPointerType(Ctx.getCanonicalType(T));
+ ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
+ }
+#endif
+
+ switch (CastE->getCastKind()) {
+ case CK_ToVoid:
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
+ Dst.Add(*I);
+ return;
+
+ case CK_LValueToRValue:
+ case CK_NoOp:
+ case CK_FunctionToPointerDecay:
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ // Copy the SVal of Ex to CastE.
+ ExplodedNode *N = *I;
+ const GRState *state = GetState(N);
+ SVal V = state->getSVal(Ex);
+ state = state->BindExpr(CastE, V);
+ MakeNode(Dst, CastE, N, state);
+ }
+ return;
+
+ case CK_GetObjCProperty:
+ case CK_Dependent:
+ case CK_ArrayToPointerDecay:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_IntegralCast:
+ case CK_NullToPointer:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
+ case CK_FloatingCast:
+ case CK_FloatingRealToComplex:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralRealToComplex:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexToBoolean:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex:
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+
+ case CK_ObjCObjectLValueCast: {
+ // Delegate to SValBuilder to process.
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ExplodedNode* N = *I;
+ const GRState* state = GetState(N);
+ SVal V = state->getSVal(Ex);
+ V = svalBuilder.evalCast(V, T, ExTy);
+ state = state->BindExpr(CastE, V);
+ MakeNode(Dst, CastE, N, state);
+ }
+ return;
+ }
+
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ // For DerivedToBase cast, delegate to the store manager.
+ for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ExplodedNode *node = *I;
+ const GRState *state = GetState(node);
+ SVal val = state->getSVal(Ex);
+ val = getStoreManager().evalDerivedToBase(val, T);
+ state = state->BindExpr(CastE, val);
+ MakeNode(Dst, CastE, node, state);
+ }
+ return;
+
+ // Various C++ casts that are not handled yet.
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_BaseToDerived:
+ case CK_NullToMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_UserDefinedConversion:
+ case CK_ConstructorConversion:
+ case CK_VectorSplat:
+ case CK_MemberPointerToBoolean: {
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ Builder->BuildSinks = true;
+ MakeNode(Dst, CastE, Pred, GetState(Pred));
+ return;
+ }
+ }
+}
+
+void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ const InitListExpr* ILE
+ = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+ ExplodedNodeSet Tmp;
+ Visit(ILE, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
+ const GRState* state = GetState(*I);
+ SVal ILV = state->getSVal(ILE);
+ const LocationContext *LC = (*I)->getLocationContext();
+ state = state->bindCompoundLiteral(CL, LC, ILV);
+
+ if (CL->isLValue()) {
+ MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC)));
+ }
+ else
+ MakeNode(Dst, CL, *I, state->BindExpr(CL, ILV));
+ }
+}
+
+void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
+ ExplodedNodeSet& Dst) {
+
+ // The CFG has one DeclStmt per Decl.
+ const Decl* D = *DS->decl_begin();
+
+ if (!D || !isa<VarDecl>(D))
+ return;
+
+ const VarDecl* VD = dyn_cast<VarDecl>(D);
+ const Expr* InitEx = VD->getInit();
+
+ // FIXME: static variables may have an initializer, but the second
+ // time a function is called those values may not be current.
+ ExplodedNodeSet Tmp;
+
+ if (InitEx) {
+ if (VD->getType()->isReferenceType() && !InitEx->isLValue()) {
+ // If the initializer is C++ record type, it should already has a
+ // temp object.
+ if (!InitEx->getType()->isRecordType())
+ CreateCXXTemporaryObject(InitEx, Pred, Tmp);
+ else
+ Tmp.Add(Pred);
+ } else
+ Visit(InitEx, Pred, Tmp);
+ } else
+ Tmp.Add(Pred);
+
+ ExplodedNodeSet Tmp2;
+ CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback);
+
+ for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
+ ExplodedNode *N = *I;
+ const GRState *state = GetState(N);
+
+ // Decls without InitExpr are not initialized explicitly.
+ const LocationContext *LC = N->getLocationContext();
+
+ if (InitEx) {
+ SVal InitVal = state->getSVal(InitEx);
+
+ // We bound the temp obj region to the CXXConstructExpr. Now recover
+ // the lazy compound value when the variable is not a reference.
+ if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() &&
+ !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
+ InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
+ assert(isa<nonloc::LazyCompoundVal>(InitVal));
+ }
+
+ // Recover some path-sensitivity if a scalar value evaluated to
+ // UnknownVal.
+ if ((InitVal.isUnknown() ||
+ !getConstraintManager().canReasonAbout(InitVal)) &&
+ !VD->getType()->isReferenceType()) {
+ InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
+ Builder->getCurrentBlockCount());
+ }
+
+ evalBind(Dst, DS, *I, state,
+ loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
+ }
+ else {
+ state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
+ MakeNode(Dst, DS, *I, state);
+ }
+ }
+}
+
+void ExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
+ ExplodedNode *Pred, ExplodedNodeSet& Dst) {
+
+ const Expr* InitEx = VD->getInit();
+ ExplodedNodeSet Tmp;
+ Visit(InitEx, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ ExplodedNode *N = *I;
+ const GRState *state = GetState(N);
+
+ const LocationContext *LC = N->getLocationContext();
+ SVal InitVal = state->getSVal(InitEx);
+
+ // Recover some path-sensitivity if a scalar value evaluated to
+ // UnknownVal.
+ if (InitVal.isUnknown() ||
+ !getConstraintManager().canReasonAbout(InitVal)) {
+ InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
+ Builder->getCurrentBlockCount());
+ }
+
+ evalBind(Dst, S, N, state,
+ loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
+ }
+}
+
+namespace {
+ // This class is used by VisitInitListExpr as an item in a worklist
+ // for processing the values contained in an InitListExpr.
+class InitListWLItem {
+public:
+ llvm::ImmutableList<SVal> Vals;
+ ExplodedNode* N;
+ InitListExpr::const_reverse_iterator Itr;
+
+ InitListWLItem(ExplodedNode* n, llvm::ImmutableList<SVal> vals,
+ InitListExpr::const_reverse_iterator itr)
+ : Vals(vals), N(n), Itr(itr) {}
+};
+}
+
+
+void ExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+
+ const GRState* state = GetState(Pred);
+ QualType T = getContext().getCanonicalType(E->getType());
+ unsigned NumInitElements = E->getNumInits();
+
+ if (T->isArrayType() || T->isRecordType() || T->isVectorType()) {
+ llvm::ImmutableList<SVal> StartVals = getBasicVals().getEmptySValList();
+
+ // Handle base case where the initializer has no elements.
+ // e.g: static int* myArray[] = {};
+ if (NumInitElements == 0) {
+ SVal V = svalBuilder.makeCompoundVal(T, StartVals);
+ MakeNode(Dst, E, Pred, state->BindExpr(E, V));
+ return;
+ }
+
+ // Create a worklist to process the initializers.
+ llvm::SmallVector<InitListWLItem, 10> WorkList;
+ WorkList.reserve(NumInitElements);
+ WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));
+ InitListExpr::const_reverse_iterator ItrEnd = E->rend();
+ assert(!(E->rbegin() == E->rend()));
+
+ // Process the worklist until it is empty.
+ while (!WorkList.empty()) {
+ InitListWLItem X = WorkList.back();
+ WorkList.pop_back();
+
+ ExplodedNodeSet Tmp;
+ Visit(*X.Itr, X.N, Tmp);
+
+ InitListExpr::const_reverse_iterator NewItr = X.Itr + 1;
+
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) {
+ // Get the last initializer value.
+ state = GetState(*NI);
+ SVal InitV = state->getSVal(cast<Expr>(*X.Itr));
+
+ // Construct the new list of values by prepending the new value to
+ // the already constructed list.
+ llvm::ImmutableList<SVal> NewVals =
+ getBasicVals().consVals(InitV, X.Vals);
+
+ if (NewItr == ItrEnd) {
+ // Now we have a list holding all init values. Make CompoundValData.
+ SVal V = svalBuilder.makeCompoundVal(T, NewVals);
+
+ // Make final state and node.
+ MakeNode(Dst, E, *NI, state->BindExpr(E, V));
+ }
+ else {
+ // Still some initializer values to go. Push them onto the worklist.
+ WorkList.push_back(InitListWLItem(*NI, NewVals, NewItr));
+ }
+ }
+ }
+
+ return;
+ }
+
+ if (Loc::isLocType(T) || T->isIntegerType()) {
+ assert (E->getNumInits() == 1);
+ ExplodedNodeSet Tmp;
+ const Expr* Init = E->getInit(0);
+ Visit(Init, Pred, Tmp);
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) {
+ state = GetState(*I);
+ MakeNode(Dst, E, *I, state->BindExpr(E, state->getSVal(Init)));
+ }
+ return;
+ }
+
+ assert(0 && "unprocessed InitListExpr type");
+}
+
+/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
+void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ QualType T = Ex->getTypeOfArgument();
+ CharUnits amt;
+
+ if (Ex->isSizeOf()) {
+ if (T == getContext().VoidTy) {
+ // sizeof(void) == 1 byte.
+ amt = CharUnits::One();
+ }
+ else if (!T->isConstantSizeType()) {
+ assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
+
+ // FIXME: Add support for VLA type arguments, not just VLA expressions.
+ // When that happens, we should probably refactor VLASizeChecker's code.
+ if (Ex->isArgumentType()) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ // Get the size by getting the extent of the sub-expression.
+ // First, visit the sub-expression to find its region.
+ const Expr *Arg = Ex->getArgumentExpr();
+ ExplodedNodeSet Tmp;
+ Visit(Arg, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ const GRState* state = GetState(*I);
+ const MemRegion *MR = state->getSVal(Arg).getAsRegion();
+
+ // If the subexpression can't be resolved to a region, we don't know
+ // anything about its size. Just leave the state as is and continue.
+ if (!MR) {
+ Dst.Add(*I);
+ continue;
+ }
+
+ // The result is the extent of the VLA.
+ SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);
+ MakeNode(Dst, Ex, *I, state->BindExpr(Ex, Extent));
+ }
+
+ return;
+ }
+ else if (T->getAs<ObjCObjectType>()) {
+ // Some code tries to take the sizeof an ObjCObjectType, relying that
+ // the compiler has laid out its representation. Just report Unknown
+ // for these.
+ Dst.Add(Pred);
+ return;
+ }
+ else {
+ // All other cases.
+ amt = getContext().getTypeSizeInChars(T);
+ }
+ }
+ else // Get alignment of the type.
+ amt = getContext().getTypeAlignInChars(T);
+
+ MakeNode(Dst, Ex, Pred,
+ GetState(Pred)->BindExpr(Ex,
+ svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())));
+}
+
+void ExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+ Expr::EvalResult Res;
+ if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
+ const APSInt &IV = Res.Val.getInt();
+ assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
+ assert(OOE->getType()->isIntegerType());
+ assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
+ SVal X = svalBuilder.makeIntVal(IV);
+ MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X));
+ return;
+ }
+ // FIXME: Handle the case where __builtin_offsetof is not a constant.
+ Dst.Add(Pred);
+}
+
+void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+
+ switch (U->getOpcode()) {
+
+ default:
+ break;
+
+ case UO_Real: {
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+
+ // FIXME: We don't have complex SValues yet.
+ if (Ex->getType()->isAnyComplexType()) {
+ // Just report "Unknown."
+ Dst.Add(*I);
+ continue;
+ }
+
+ // For all other types, UO_Real is an identity operation.
+ assert (U->getType() == Ex->getType());
+ const GRState* state = GetState(*I);
+ MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+ }
+
+ return;
+ }
+
+ case UO_Imag: {
+
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ // FIXME: We don't have complex SValues yet.
+ if (Ex->getType()->isAnyComplexType()) {
+ // Just report "Unknown."
+ Dst.Add(*I);
+ continue;
+ }
+
+ // For all other types, UO_Imag returns 0.
+ const GRState* state = GetState(*I);
+ SVal X = svalBuilder.makeZeroVal(Ex->getType());
+ MakeNode(Dst, U, *I, state->BindExpr(U, X));
+ }
+
+ return;
+ }
+
+ case UO_Plus:
+ assert(!U->isLValue());
+ // FALL-THROUGH.
+ case UO_Deref:
+ case UO_AddrOf:
+ case UO_Extension: {
+
+ // Unary "+" is a no-op, similar to a parentheses. We still have places
+ // where it may be a block-level expression, so we need to
+ // generate an extra node that just propagates the value of the
+ // subexpression.
+
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ const GRState* state = GetState(*I);
+ MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+ }
+
+ return;
+ }
+
+ case UO_LNot:
+ case UO_Minus:
+ case UO_Not: {
+ assert (!U->isLValue());
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ const GRState* state = GetState(*I);
+
+ // Get the value of the subexpression.
+ SVal V = state->getSVal(Ex);
+
+ if (V.isUnknownOrUndef()) {
+ MakeNode(Dst, U, *I, state->BindExpr(U, V));
+ continue;
+ }
+
+// QualType DstT = getContext().getCanonicalType(U->getType());
+// QualType SrcT = getContext().getCanonicalType(Ex->getType());
+//
+// if (DstT != SrcT) // Perform promotions.
+// V = evalCast(V, DstT);
+//
+// if (V.isUnknownOrUndef()) {
+// MakeNode(Dst, U, *I, BindExpr(St, U, V));
+// continue;
+// }
+
+ switch (U->getOpcode()) {
+ default:
+ assert(false && "Invalid Opcode.");
+ break;
+
+ case UO_Not:
+ // FIXME: Do we need to handle promotions?
+ state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
+ break;
+
+ case UO_Minus:
+ // FIXME: Do we need to handle promotions?
+ state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
+ break;
+
+ case UO_LNot:
+
+ // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
+ //
+ // Note: technically we do "E == 0", but this is the same in the
+ // transfer functions as "0 == E".
+ SVal Result;
+
+ if (isa<Loc>(V)) {
+ Loc X = svalBuilder.makeNull();
+ Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,
+ U->getType());
+ }
+ else {
+ nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
+ Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
+ U->getType());
+ }
+
+ state = state->BindExpr(U, Result);
+
+ break;
+ }
+
+ MakeNode(Dst, U, *I, state);
+ }
+
+ return;
+ }
+ }
+
+ // Handle ++ and -- (both pre- and post-increment).
+ assert (U->isIncrementDecrementOp());
+ ExplodedNodeSet Tmp;
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
+ Visit(Ex, Pred, Tmp);
+
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
+
+ const GRState* state = GetState(*I);
+ SVal loc = state->getSVal(Ex);
+
+ // Perform a load.
+ ExplodedNodeSet Tmp2;
+ evalLoad(Tmp2, Ex, *I, state, loc);
+
+ for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
+
+ state = GetState(*I2);
+ SVal V2_untested = state->getSVal(Ex);
+
+ // Propagate unknown and undefined values.
+ if (V2_untested.isUnknownOrUndef()) {
+ MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));
+ continue;
+ }
+ DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
+
+ // Handle all other values.
+ BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add
+ : BO_Sub;
+
+ // If the UnaryOperator has non-location type, use its type to create the
+ // constant value. If the UnaryOperator has location type, create the
+ // constant with int type and pointer width.
+ SVal RHS;
+
+ if (U->getType()->isAnyPointerType())
+ RHS = svalBuilder.makeArrayIndex(1);
+ else
+ RHS = svalBuilder.makeIntVal(1, U->getType());
+
+ SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
+
+ // Conjure a new symbol if necessary to recover precision.
+ if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
+ DefinedOrUnknownSVal SymVal =
+ svalBuilder.getConjuredSymbolVal(NULL, Ex,
+ Builder->getCurrentBlockCount());
+ Result = SymVal;
+
+ // If the value is a location, ++/-- should always preserve
+ // non-nullness. Check if the original value was non-null, and if so
+ // propagate that constraint.
+ if (Loc::isLocType(U->getType())) {
+ DefinedOrUnknownSVal Constraint =
+ svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
+
+ if (!state->assume(Constraint, true)) {
+ // It isn't feasible for the original value to be null.
+ // Propagate this constraint.
+ Constraint = svalBuilder.evalEQ(state, SymVal,
+ svalBuilder.makeZeroVal(U->getType()));
+
+
+ state = state->assume(Constraint, false);
+ assert(state);
+ }
+ }
+ }
+
+ // Since the lvalue-to-rvalue conversion is explicit in the AST,
+ // we bind an l-value if the operator is prefix and an lvalue (in C++).
+ if (U->isLValue())
+ state = state->BindExpr(U, loc);
+ else
+ state = state->BindExpr(U, V2);
+
+ // Perform the store.
+ evalStore(Dst, NULL, U, *I2, state, loc, Result);
+ }
+ }
+}
+
+void ExprEngine::VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
+}
+
+void ExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt* A,
+ AsmStmt::const_outputs_iterator I,
+ AsmStmt::const_outputs_iterator E,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+ if (I == E) {
+ VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ Visit(*I, Pred, Tmp);
+ ++I;
+
+ for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)
+ VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
+}
+
+void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt* A,
+ AsmStmt::const_inputs_iterator I,
+ AsmStmt::const_inputs_iterator E,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ if (I == E) {
+
+ // We have processed both the inputs and the outputs. All of the outputs
+ // should evaluate to Locs. Nuke all of their values.
+
+ // FIXME: Some day in the future it would be nice to allow a "plug-in"
+ // which interprets the inline asm and stores proper results in the
+ // outputs.
+
+ const GRState* state = GetState(Pred);
+
+ for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
+ OE = A->end_outputs(); OI != OE; ++OI) {
+
+ SVal X = state->getSVal(*OI);
+ assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
+
+ if (isa<Loc>(X))
+ state = state->bindLoc(cast<Loc>(X), UnknownVal());
+ }
+
+ MakeNode(Dst, A, Pred, state);
+ return;
+ }
+
+ ExplodedNodeSet Tmp;
+ Visit(*I, Pred, Tmp);
+
+ ++I;
+
+ for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI!=NE; ++NI)
+ VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
+}
+
+void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ExplodedNodeSet Src;
+ if (const Expr *RetE = RS->getRetValue()) {
+ // Record the returned expression in the state. It will be used in
+ // processCallExit to bind the return value to the call expr.
+ {
+ static int tag = 0;
+ const GRState *state = GetState(Pred);
+ state = state->set<ReturnExpr>(RetE);
+ Pred = Builder->generateNode(RetE, state, Pred, &tag);
+ }
+ // We may get a NULL Pred because we generated a cached node.
+ if (Pred)
+ Visit(RetE, Pred, Src);
+ }
+ else {
+ Src.Add(Pred);
+ }
+
+ ExplodedNodeSet CheckedSet;
+ CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
+
+ assert(Builder && "StmtNodeBuilder must be defined.");
+
+ Pred = *I;
+ unsigned size = Dst.size();
+
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ SaveOr OldHasGen(Builder->hasGeneratedNode);
+
+ getTF().evalReturn(Dst, *this, *Builder, RS, Pred);
+
+ // Handle the case where no nodes where generated.
+ if (!Builder->BuildSinks && Dst.size() == size &&
+ !Builder->hasGeneratedNode)
+ MakeNode(Dst, RS, Pred, GetState(Pred));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions: Binary operators.
+//===----------------------------------------------------------------------===//
+
+void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
+ ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
+ ExplodedNodeSet Tmp1;
+ Expr* LHS = B->getLHS()->IgnoreParens();
+ Expr* RHS = B->getRHS()->IgnoreParens();
+
+ Visit(LHS, Pred, Tmp1);
+ ExplodedNodeSet Tmp3;
+
+ for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
+ SVal LeftV = GetState(*I1)->getSVal(LHS);
+ ExplodedNodeSet Tmp2;
+ Visit(RHS, *I1, Tmp2);
+
+ ExplodedNodeSet CheckedSet;
+ CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback);
+
+ // With both the LHS and RHS evaluated, process the operation itself.
+
+ for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
+ I2 != E2; ++I2) {
+
+ const GRState *state = GetState(*I2);
+ SVal RightV = state->getSVal(RHS);
+
+ BinaryOperator::Opcode Op = B->getOpcode();
+
+ if (Op == BO_Assign) {
+ // EXPERIMENTAL: "Conjured" symbols.
+ // FIXME: Handle structs.
+ if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
+ {
+ unsigned Count = Builder->getCurrentBlockCount();
+ RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);
+ }
+
+ SVal ExprVal = B->isLValue() ? LeftV : RightV;
+
+ // Simulate the effects of a "store": bind the value of the RHS
+ // to the L-Value represented by the LHS.
+ evalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
+ continue;
+ }
+
+ if (!B->isAssignmentOp()) {
+ // Process non-assignments except commas or short-circuited
+ // logical expressions (LAnd and LOr).
+ SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
+
+ if (Result.isUnknown()) {
+ MakeNode(Tmp3, B, *I2, state);
+ continue;
+ }
+
+ state = state->BindExpr(B, Result);
+
+ MakeNode(Tmp3, B, *I2, state);
+ continue;
+ }
+
+ assert (B->isCompoundAssignmentOp());
+
+ switch (Op) {
+ default:
+ assert(0 && "Invalid opcode for compound assignment.");
+ case BO_MulAssign: Op = BO_Mul; break;
+ case BO_DivAssign: Op = BO_Div; break;
+ case BO_RemAssign: Op = BO_Rem; break;
+ case BO_AddAssign: Op = BO_Add; break;
+ case BO_SubAssign: Op = BO_Sub; break;
+ case BO_ShlAssign: Op = BO_Shl; break;
+ case BO_ShrAssign: Op = BO_Shr; break;
+ case BO_AndAssign: Op = BO_And; break;
+ case BO_XorAssign: Op = BO_Xor; break;
+ case BO_OrAssign: Op = BO_Or; break;
+ }
+
+ // Perform a load (the LHS). This performs the checks for
+ // null dereferences, and so on.
+ ExplodedNodeSet Tmp4;
+ SVal location = state->getSVal(LHS);
+ evalLoad(Tmp4, LHS, *I2, state, location);
+
+ for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
+ ++I4) {
+ state = GetState(*I4);
+ SVal V = state->getSVal(LHS);
+
+ // Get the computation type.
+ QualType CTy =
+ cast<CompoundAssignOperator>(B)->getComputationResultType();
+ CTy = getContext().getCanonicalType(CTy);
+
+ QualType CLHSTy =
+ cast<CompoundAssignOperator>(B)->getComputationLHSType();
+ CLHSTy = getContext().getCanonicalType(CLHSTy);
+
+ QualType LTy = getContext().getCanonicalType(LHS->getType());
+
+ // Promote LHS.
+ V = svalBuilder.evalCast(V, CLHSTy, LTy);
+
+ // Compute the result of the operation.
+ SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
+ B->getType(), CTy);
+
+ // EXPERIMENTAL: "Conjured" symbols.
+ // FIXME: Handle structs.
+
+ SVal LHSVal;
+
+ if (Result.isUnknown() ||
+ !getConstraintManager().canReasonAbout(Result)) {
+
+ unsigned Count = Builder->getCurrentBlockCount();
+
+ // The symbolic value is actually for the type of the left-hand side
+ // expression, not the computation type, as this is the value the
+ // LValue on the LHS will bind to.
+ LHSVal = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
+
+ // However, we need to convert the symbol to the computation type.
+ Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
+ }
+ else {
+ // The left-hand side may bind to a different value then the
+ // computation type.
+ LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
+ }
+
+ // In C++, assignment and compound assignment operators return an
+ // lvalue.
+ if (B->isLValue())
+ state = state->BindExpr(B, location);
+ else
+ state = state->BindExpr(B, Result);
+
+ evalStore(Tmp3, B, LHS, *I4, state, location, LHSVal);
+ }
+ }
+ }
+
+ CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback);
+}
+
+//===----------------------------------------------------------------------===//
+// Checker registration/lookup.
+//===----------------------------------------------------------------------===//
+
+Checker *ExprEngine::lookupChecker(void *tag) const {
+ CheckerMap::const_iterator I = CheckerM.find(tag);
+ return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
+}
+
+//===----------------------------------------------------------------------===//
+// Visualization.
+//===----------------------------------------------------------------------===//
+
+#ifndef NDEBUG
+static ExprEngine* GraphPrintCheckerState;
+static SourceManager* GraphPrintSourceManager;
+
+namespace llvm {
+template<>
+struct DOTGraphTraits<ExplodedNode*> :
+ public DefaultDOTGraphTraits {
+
+ DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
+
+ // FIXME: Since we do not cache error nodes in ExprEngine now, this does not
+ // work.
+ static std::string getNodeAttributes(const ExplodedNode* N, void*) {
+
+#if 0
+ // FIXME: Replace with a general scheme to tell if the node is
+ // an error node.
+ if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
+ GraphPrintCheckerState->isExplicitNullDeref(N) ||
+ GraphPrintCheckerState->isUndefDeref(N) ||
+ GraphPrintCheckerState->isUndefStore(N) ||
+ GraphPrintCheckerState->isUndefControlFlow(N) ||
+ GraphPrintCheckerState->isUndefResult(N) ||
+ GraphPrintCheckerState->isBadCall(N) ||
+ GraphPrintCheckerState->isUndefArg(N))
+ return "color=\"red\",style=\"filled\"";
+
+ if (GraphPrintCheckerState->isNoReturnCall(N))
+ return "color=\"blue\",style=\"filled\"";
+#endif
+ return "";
+ }
+
+ static std::string getNodeLabel(const ExplodedNode* N, void*){
+
+ std::string sbuf;
+ llvm::raw_string_ostream Out(sbuf);
+
+ // Program Location.
+ ProgramPoint Loc = N->getLocation();
+
+ switch (Loc.getKind()) {
+ case ProgramPoint::BlockEntranceKind:
+ Out << "Block Entrance: B"
+ << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
+ break;
+
+ case ProgramPoint::BlockExitKind:
+ assert (false);
+ break;
+
+ case ProgramPoint::CallEnterKind:
+ Out << "CallEnter";
+ break;
+
+ case ProgramPoint::CallExitKind:
+ Out << "CallExit";
+ break;
+
+ default: {
+ if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) {
+ const Stmt* S = L->getStmt();
+ SourceLocation SLoc = S->getLocStart();
+
+ Out << S->getStmtClassName() << ' ' << (void*) S << ' ';
+ LangOptions LO; // FIXME.
+ S->printPretty(Out, 0, PrintingPolicy(LO));
+
+ if (SLoc.isFileID()) {
+ Out << "\\lline="
+ << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)
+ << " col="
+ << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc)
+ << "\\l";
+ }
+
+ if (isa<PreStmt>(Loc))
+ Out << "\\lPreStmt\\l;";
+ else if (isa<PostLoad>(Loc))
+ Out << "\\lPostLoad\\l;";
+ else if (isa<PostStore>(Loc))
+ Out << "\\lPostStore\\l";
+ else if (isa<PostLValue>(Loc))
+ Out << "\\lPostLValue\\l";
+
+#if 0
+ // FIXME: Replace with a general scheme to determine
+ // the name of the check.
+ if (GraphPrintCheckerState->isImplicitNullDeref(N))
+ Out << "\\|Implicit-Null Dereference.\\l";
+ else if (GraphPrintCheckerState->isExplicitNullDeref(N))
+ Out << "\\|Explicit-Null Dereference.\\l";
+ else if (GraphPrintCheckerState->isUndefDeref(N))
+ Out << "\\|Dereference of undefialied value.\\l";
+ else if (GraphPrintCheckerState->isUndefStore(N))
+ Out << "\\|Store to Undefined Loc.";
+ else if (GraphPrintCheckerState->isUndefResult(N))
+ Out << "\\|Result of operation is undefined.";
+ else if (GraphPrintCheckerState->isNoReturnCall(N))
+ Out << "\\|Call to function marked \"noreturn\".";
+ else if (GraphPrintCheckerState->isBadCall(N))
+ Out << "\\|Call to NULL/Undefined.";
+ else if (GraphPrintCheckerState->isUndefArg(N))
+ Out << "\\|Argument in call is undefined";
+#endif
+
+ break;
+ }
+
+ const BlockEdge& E = cast<BlockEdge>(Loc);
+ Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
+ << E.getDst()->getBlockID() << ')';
+
+ if (const Stmt* T = E.getSrc()->getTerminator()) {
+
+ SourceLocation SLoc = T->getLocStart();
+
+ Out << "\\|Terminator: ";
+ LangOptions LO; // FIXME.
+ E.getSrc()->printTerminator(Out, LO);
+
+ if (SLoc.isFileID()) {
+ Out << "\\lline="
+ << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)
+ << " col="
+ << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc);
+ }
+
+ if (isa<SwitchStmt>(T)) {
+ const Stmt* Label = E.getDst()->getLabel();
+
+ if (Label) {
+ if (const CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
+ Out << "\\lcase ";
+ LangOptions LO; // FIXME.
+ C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
+
+ if (const Stmt* RHS = C->getRHS()) {
+ Out << " .. ";
+ RHS->printPretty(Out, 0, PrintingPolicy(LO));
+ }
+
+ Out << ":";
+ }
+ else {
+ assert (isa<DefaultStmt>(Label));
+ Out << "\\ldefault:";
+ }
+ }
+ else
+ Out << "\\l(implicit) default:";
+ }
+ else if (isa<IndirectGotoStmt>(T)) {
+ // FIXME
+ }
+ else {
+ Out << "\\lCondition: ";
+ if (*E.getSrc()->succ_begin() == E.getDst())
+ Out << "true";
+ else
+ Out << "false";
+ }
+
+ Out << "\\l";
+ }
+
+#if 0
+ // FIXME: Replace with a general scheme to determine
+ // the name of the check.
+ if (GraphPrintCheckerState->isUndefControlFlow(N)) {
+ Out << "\\|Control-flow based on\\lUndefined value.\\l";
+ }
+#endif
+ }
+ }
+
+ const GRState *state = N->getState();
+ Out << "\\|StateID: " << (void*) state
+ << " NodeID: " << (void*) N << "\\|";
+ state->printDOT(Out, *N->getLocationContext()->getCFG());
+ Out << "\\l";
+ return Out.str();
+ }
+};
+} // end llvm namespace
+#endif
+
+#ifndef NDEBUG
+template <typename ITERATOR>
+ExplodedNode* GetGraphNode(ITERATOR I) { return *I; }
+
+template <> ExplodedNode*
+GetGraphNode<llvm::DenseMap<ExplodedNode*, Expr*>::iterator>
+ (llvm::DenseMap<ExplodedNode*, Expr*>::iterator I) {
+ return I->first;
+}
+#endif
+
+void ExprEngine::ViewGraph(bool trim) {
+#ifndef NDEBUG
+ if (trim) {
+ std::vector<ExplodedNode*> Src;
+
+ // Flush any outstanding reports to make sure we cover all the nodes.
+ // This does not cause them to get displayed.
+ for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I)
+ const_cast<BugType*>(*I)->FlushReports(BR);
+
+ // Iterate through the reports and get their nodes.
+ for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) {
+ for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end();
+ I2!=E2; ++I2) {
+ const BugReportEquivClass& EQ = *I2;
+ const BugReport &R = **EQ.begin();
+ ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
+ if (N) Src.push_back(N);
+ }
+ }
+
+ ViewGraph(&Src[0], &Src[0]+Src.size());
+ }
+ else {
+ GraphPrintCheckerState = this;
+ GraphPrintSourceManager = &getContext().getSourceManager();
+
+ llvm::ViewGraph(*G.roots_begin(), "ExprEngine");
+
+ GraphPrintCheckerState = NULL;
+ GraphPrintSourceManager = NULL;
+ }
+#endif
+}
+
+void ExprEngine::ViewGraph(ExplodedNode** Beg, ExplodedNode** End) {
+#ifndef NDEBUG
+ GraphPrintCheckerState = this;
+ GraphPrintSourceManager = &getContext().getSourceManager();
+
+ std::auto_ptr<ExplodedGraph> TrimmedG(G.Trim(Beg, End).first);
+
+ if (!TrimmedG.get())
+ llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
+ else
+ llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");
+
+ GraphPrintCheckerState = NULL;
+ GraphPrintSourceManager = NULL;
+#endif
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
new file mode 100644
index 0000000..fe628a2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -0,0 +1,77 @@
+//=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines FixedAddressChecker, a builtin checker that checks for
+// assignment of a fixed address to a pointer.
+// This check corresponds to CWE-587.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class FixedAddressChecker
+ : public CheckerVisitor<FixedAddressChecker> {
+ BuiltinBug *BT;
+public:
+ FixedAddressChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *FixedAddressChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ // Using a fixed address is not portable because that address will probably
+ // not be valid in all environments or platforms.
+
+ if (B->getOpcode() != BO_Assign)
+ return;
+
+ QualType T = B->getType();
+ if (!T->isPointerType())
+ return;
+
+ const GRState *state = C.getState();
+
+ SVal RV = state->getSVal(B->getRHS());
+
+ if (!RV.isConstant() || RV.isZeroConstant())
+ return;
+
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT)
+ BT = new BuiltinBug("Use fixed address",
+ "Using a fixed address is not portable because that "
+ "address will probably not be valid in all "
+ "environments or platforms.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getRHS()->getSourceRange());
+ C.EmitReport(R);
+ }
+}
+
+static void RegisterFixedAddressChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new FixedAddressChecker());
+}
+
+void ento::registerFixedAddressChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterFixedAddressChecker);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
new file mode 100644
index 0000000..f49b125
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -0,0 +1,822 @@
+//==- IdempotentOperationChecker.cpp - Idempotent Operations ----*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of path-sensitive checks for idempotent and/or
+// tautological operations. Each potential operation is checked along all paths
+// to see if every path results in a pointless operation.
+// +-------------------------------------------+
+// |Table of idempotent/tautological operations|
+// +-------------------------------------------+
+//+--------------------------------------------------------------------------+
+//|Operator | x op x | x op 1 | 1 op x | x op 0 | 0 op x | x op ~0 | ~0 op x |
+//+--------------------------------------------------------------------------+
+// +, += | | | | x | x | |
+// -, -= | | | | x | -x | |
+// *, *= | | x | x | 0 | 0 | |
+// /, /= | 1 | x | | N/A | 0 | |
+// &, &= | x | | | 0 | 0 | x | x
+// |, |= | x | | | x | x | ~0 | ~0
+// ^, ^= | 0 | | | x | x | |
+// <<, <<= | | | | x | 0 | |
+// >>, >>= | | | | x | 0 | |
+// || | 1 | 1 | 1 | x | x | 1 | 1
+// && | 1 | x | x | 0 | 0 | x | x
+// = | x | | | | | |
+// == | 1 | | | | | |
+// >= | 1 | | | | | |
+// <= | 1 | | | | | |
+// > | 0 | | | | | |
+// < | 0 | | | | | |
+// != | 0 | | | | | |
+//===----------------------------------------------------------------------===//
+//
+// Things TODO:
+// - Improved error messages
+// - Handle mixed assumptions (which assumptions can belong together?)
+// - Finer grained false positive control (levels)
+// - Handling ~0 values
+
+#include "ClangSACheckers.h"
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <deque>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class IdempotentOperationChecker
+ : public CheckerVisitor<IdempotentOperationChecker> {
+public:
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng);
+
+private:
+ // Our assumption about a particular operation.
+ enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
+ RHSis0 };
+
+ void UpdateAssumption(Assumption &A, const Assumption &New);
+
+ // False positive reduction methods
+ static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
+ static bool isUnused(const Expr *E, AnalysisContext *AC);
+ static bool isTruncationExtensionAssignment(const Expr *LHS,
+ const Expr *RHS);
+ bool pathWasCompletelyAnalyzed(const CFG *cfg,
+ const CFGBlock *CB,
+ const CFGStmtMap *CBM,
+ const CoreEngine &CE);
+ static bool CanVary(const Expr *Ex,
+ AnalysisContext *AC);
+ static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
+ AnalysisContext *AC);
+ static bool containsNonLocalVarDecl(const Stmt *S);
+
+ // Hash table and related data structures
+ struct BinaryOperatorData {
+ BinaryOperatorData() : assumption(Possible), analysisContext(0) {}
+
+ Assumption assumption;
+ AnalysisContext *analysisContext;
+ ExplodedNodeSet explodedNodes; // Set of ExplodedNodes that refer to a
+ // BinaryOperator
+ };
+ typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
+ AssumptionMap;
+ AssumptionMap hash;
+
+ // A class that performs reachability queries for CFGBlocks. Several internal
+ // checks in this checker require reachability information. The requests all
+ // tend to have a common destination, so we lazily do a predecessor search
+ // from the destination node and cache the results to prevent work
+ // duplication.
+ class CFGReachabilityAnalysis {
+ typedef llvm::BitVector ReachableSet;
+ typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ ReachableSet analyzed;
+ ReachableMap reachable;
+ public:
+ CFGReachabilityAnalysis(const CFG &cfg)
+ : analyzed(cfg.getNumBlockIDs(), false) {}
+
+ inline bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
+ private:
+ void MapReachability(const CFGBlock *Dst);
+ };
+ llvm::OwningPtr<CFGReachabilityAnalysis> CRA;
+};
+}
+
+void *IdempotentOperationChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+static void RegisterIdempotentOperationChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new IdempotentOperationChecker());
+}
+
+void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterIdempotentOperationChecker);
+}
+
+void IdempotentOperationChecker::PreVisitBinaryOperator(
+ CheckerContext &C,
+ const BinaryOperator *B) {
+ // Find or create an entry in the hash for this BinaryOperator instance.
+ // If we haven't done a lookup before, it will get default initialized to
+ // 'Possible'. At this stage we do not store the ExplodedNode, as it has not
+ // been created yet.
+ BinaryOperatorData &Data = hash[B];
+ Assumption &A = Data.assumption;
+ AnalysisContext *AC = C.getCurrentAnalysisContext();
+ Data.analysisContext = AC;
+
+ // If we already have visited this node on a path that does not contain an
+ // idempotent operation, return immediately.
+ if (A == Impossible)
+ return;
+
+ // Retrieve both sides of the operator and determine if they can vary (which
+ // may mean this is a false positive.
+ const Expr *LHS = B->getLHS();
+ const Expr *RHS = B->getRHS();
+
+ // At this stage we can calculate whether each side contains a false positive
+ // that applies to all operators. We only need to calculate this the first
+ // time.
+ bool LHSContainsFalsePositive = false, RHSContainsFalsePositive = false;
+ if (A == Possible) {
+ // An expression contains a false positive if it can't vary, or if it
+ // contains a known false positive VarDecl.
+ LHSContainsFalsePositive = !CanVary(LHS, AC)
+ || containsNonLocalVarDecl(LHS);
+ RHSContainsFalsePositive = !CanVary(RHS, AC)
+ || containsNonLocalVarDecl(RHS);
+ }
+
+ const GRState *state = C.getState();
+
+ SVal LHSVal = state->getSVal(LHS);
+ SVal RHSVal = state->getSVal(RHS);
+
+ // If either value is unknown, we can't be 100% sure of all paths.
+ if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {
+ A = Impossible;
+ return;
+ }
+ BinaryOperator::Opcode Op = B->getOpcode();
+
+ // Dereference the LHS SVal if this is an assign operation
+ switch (Op) {
+ default:
+ break;
+
+ // Fall through intentional
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Assign:
+ // Assign statements have one extra level of indirection
+ if (!isa<Loc>(LHSVal)) {
+ A = Impossible;
+ return;
+ }
+ LHSVal = state->getSVal(cast<Loc>(LHSVal), LHS->getType());
+ }
+
+
+ // We now check for various cases which result in an idempotent operation.
+
+ // x op x
+ switch (Op) {
+ default:
+ break; // We don't care about any other operators.
+
+ // Fall through intentional
+ case BO_Assign:
+ // x Assign x can be used to silence unused variable warnings intentionally.
+ // If this is a self assignment and the variable is referenced elsewhere,
+ // and the assignment is not a truncation or extension, then it is a false
+ // positive.
+ if (isSelfAssign(LHS, RHS)) {
+ if (!isUnused(LHS, AC) && !isTruncationExtensionAssignment(LHS, RHS)) {
+ UpdateAssumption(A, Equal);
+ return;
+ }
+ else {
+ A = Impossible;
+ return;
+ }
+ }
+
+ case BO_SubAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_Sub:
+ case BO_Div:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_LOr:
+ case BO_LAnd:
+ case BO_EQ:
+ case BO_NE:
+ if (LHSVal != RHSVal || LHSContainsFalsePositive
+ || RHSContainsFalsePositive)
+ break;
+ UpdateAssumption(A, Equal);
+ return;
+ }
+
+ // x op 1
+ switch (Op) {
+ default:
+ break; // We don't care about any other operators.
+
+ // Fall through intentional
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_Mul:
+ case BO_Div:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!RHSVal.isConstant(1) || RHSContainsFalsePositive)
+ break;
+ UpdateAssumption(A, RHSis1);
+ return;
+ }
+
+ // 1 op x
+ switch (Op) {
+ default:
+ break; // We don't care about any other operators.
+
+ // Fall through intentional
+ case BO_MulAssign:
+ case BO_Mul:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!LHSVal.isConstant(1) || LHSContainsFalsePositive)
+ break;
+ UpdateAssumption(A, LHSis1);
+ return;
+ }
+
+ // x op 0
+ switch (Op) {
+ default:
+ break; // We don't care about any other operators.
+
+ // Fall through intentional
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Mul:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!RHSVal.isConstant(0) || RHSContainsFalsePositive)
+ break;
+ UpdateAssumption(A, RHSis0);
+ return;
+ }
+
+ // 0 op x
+ switch (Op) {
+ default:
+ break; // We don't care about any other operators.
+
+ // Fall through intentional
+ //case BO_AddAssign: // Common false positive
+ case BO_SubAssign: // Check only if unsigned
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ //case BO_OrAssign: // Common false positive
+ //case BO_XorAssign: // Common false positive
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Mul:
+ case BO_Div:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!LHSVal.isConstant(0) || LHSContainsFalsePositive)
+ break;
+ UpdateAssumption(A, LHSis0);
+ return;
+ }
+
+ // If we get to this point, there has been a valid use of this operation.
+ A = Impossible;
+}
+
+// At the post visit stage, the predecessor ExplodedNode will be the
+// BinaryOperator that was just created. We use this hook to collect the
+// ExplodedNode.
+void IdempotentOperationChecker::PostVisitBinaryOperator(
+ CheckerContext &C,
+ const BinaryOperator *B) {
+ // Add the ExplodedNode we just visited
+ BinaryOperatorData &Data = hash[B];
+
+ const Stmt *predStmt
+ = cast<StmtPoint>(C.getPredecessor()->getLocation()).getStmt();
+
+ // Ignore implicit calls to setters.
+ if (isa<ObjCPropertyRefExpr>(predStmt))
+ return;
+
+ assert(isa<BinaryOperator>(predStmt));
+ Data.explodedNodes.Add(C.getPredecessor());
+}
+
+void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &BR,
+ ExprEngine &Eng) {
+ BugType *BT = new BugType("Idempotent operation", "Dead code");
+ // Iterate over the hash to see if we have any paths with definite
+ // idempotent operations.
+ for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
+ // Unpack the hash contents
+ const BinaryOperatorData &Data = i->second;
+ const Assumption &A = Data.assumption;
+ AnalysisContext *AC = Data.analysisContext;
+ const ExplodedNodeSet &ES = Data.explodedNodes;
+
+ const BinaryOperator *B = i->first;
+
+ if (A == Impossible)
+ continue;
+
+ // If the analyzer did not finish, check to see if we can still emit this
+ // warning
+ if (Eng.hasWorkRemaining()) {
+ const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
+ &AC->getParentMap());
+
+ // If we can trace back
+ if (!pathWasCompletelyAnalyzed(AC->getCFG(),
+ CBM->getBlock(B), CBM,
+ Eng.getCoreEngine()))
+ continue;
+
+ delete CBM;
+ }
+
+ // Select the error message and SourceRanges to report.
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+ bool LHSRelevant = false, RHSRelevant = false;
+ switch (A) {
+ case Equal:
+ LHSRelevant = true;
+ RHSRelevant = true;
+ if (B->getOpcode() == BO_Assign)
+ os << "Assigned value is always the same as the existing value";
+ else
+ os << "Both operands to '" << B->getOpcodeStr()
+ << "' always have the same value";
+ break;
+ case LHSis1:
+ LHSRelevant = true;
+ os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
+ break;
+ case RHSis1:
+ RHSRelevant = true;
+ os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
+ break;
+ case LHSis0:
+ LHSRelevant = true;
+ os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
+ break;
+ case RHSis0:
+ RHSRelevant = true;
+ os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
+ break;
+ case Possible:
+ llvm_unreachable("Operation was never marked with an assumption");
+ case Impossible:
+ llvm_unreachable(0);
+ }
+
+ // Add a report for each ExplodedNode
+ for (ExplodedNodeSet::iterator I = ES.begin(), E = ES.end(); I != E; ++I) {
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), *I);
+
+ // Add source ranges and visitor hooks
+ if (LHSRelevant) {
+ const Expr *LHS = i->first->getLHS();
+ report->addRange(LHS->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS);
+ }
+ if (RHSRelevant) {
+ const Expr *RHS = i->first->getRHS();
+ report->addRange(i->first->getRHS()->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS);
+ }
+
+ BR.EmitReport(report);
+ }
+ }
+}
+
+// Updates the current assumption given the new assumption
+inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
+ const Assumption &New) {
+// If the assumption is the same, there is nothing to do
+ if (A == New)
+ return;
+
+ switch (A) {
+ // If we don't currently have an assumption, set it
+ case Possible:
+ A = New;
+ return;
+
+ // If we have determined that a valid state happened, ignore the new
+ // assumption.
+ case Impossible:
+ return;
+
+ // Any other case means that we had a different assumption last time. We don't
+ // currently support mixing assumptions for diagnostic reasons, so we set
+ // our assumption to be impossible.
+ default:
+ A = Impossible;
+ return;
+ }
+}
+
+// Check for a statement where a variable is self assigned to possibly avoid an
+// unused variable warning.
+bool IdempotentOperationChecker::isSelfAssign(const Expr *LHS, const Expr *RHS) {
+ LHS = LHS->IgnoreParenCasts();
+ RHS = RHS->IgnoreParenCasts();
+
+ const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
+ if (!LHS_DR)
+ return false;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+ if (!VD)
+ return false;
+
+ const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
+ if (!RHS_DR)
+ return false;
+
+ if (VD != RHS_DR->getDecl())
+ return false;
+
+ return true;
+}
+
+// Returns true if the Expr points to a VarDecl that is not read anywhere
+// outside of self-assignments.
+bool IdempotentOperationChecker::isUnused(const Expr *E,
+ AnalysisContext *AC) {
+ if (!E)
+ return false;
+
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+ if (!DR)
+ return false;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return false;
+
+ if (AC->getPseudoConstantAnalysis()->wasReferenced(VD))
+ return false;
+
+ return true;
+}
+
+// Check for self casts truncating/extending a variable
+bool IdempotentOperationChecker::isTruncationExtensionAssignment(
+ const Expr *LHS,
+ const Expr *RHS) {
+
+ const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
+ if (!LHS_DR)
+ return false;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+ if (!VD)
+ return false;
+
+ const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
+ if (!RHS_DR)
+ return false;
+
+ if (VD != RHS_DR->getDecl())
+ return false;
+
+ return dyn_cast<DeclRefExpr>(RHS->IgnoreParenLValueCasts()) == NULL;
+}
+
+// Returns false if a path to this block was not completely analyzed, or true
+// otherwise.
+bool
+IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg,
+ const CFGBlock *CB,
+ const CFGStmtMap *CBM,
+ const CoreEngine &CE) {
+
+ if (!CRA.get())
+ CRA.reset(new CFGReachabilityAnalysis(*cfg));
+
+ // Test for reachability from any aborted blocks to this block
+ typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
+ for (AbortedIterator I = CE.blocks_aborted_begin(),
+ E = CE.blocks_aborted_end(); I != E; ++I) {
+ const BlockEdge &BE = I->first;
+
+ // The destination block on the BlockEdge is the first block that was not
+ // analyzed. If we can reach this block from the aborted block, then this
+ // block was not completely analyzed.
+ //
+ // Also explicitly check if the current block is the destination block.
+ // While technically reachable, it means we aborted the analysis on
+ // a path that included that block.
+ const CFGBlock *destBlock = BE.getDst();
+ if (destBlock == CB || CRA->isReachable(destBlock, CB))
+ return false;
+ }
+
+ // For the items still on the worklist, see if they are in blocks that
+ // can eventually reach 'CB'.
+ class VisitWL : public WorkList::Visitor {
+ const CFGStmtMap *CBM;
+ const CFGBlock *TargetBlock;
+ CFGReachabilityAnalysis &CRA;
+ public:
+ VisitWL(const CFGStmtMap *cbm, const CFGBlock *targetBlock,
+ CFGReachabilityAnalysis &cra)
+ : CBM(cbm), TargetBlock(targetBlock), CRA(cra) {}
+ virtual bool visit(const WorkListUnit &U) {
+ ProgramPoint P = U.getNode()->getLocation();
+ const CFGBlock *B = 0;
+ if (StmtPoint *SP = dyn_cast<StmtPoint>(&P)) {
+ B = CBM->getBlock(SP->getStmt());
+ }
+ else if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ B = BE->getDst();
+ }
+ else if (BlockEntrance *BEnt = dyn_cast<BlockEntrance>(&P)) {
+ B = BEnt->getBlock();
+ }
+ else if (BlockExit *BExit = dyn_cast<BlockExit>(&P)) {
+ B = BExit->getBlock();
+ }
+ if (!B)
+ return true;
+
+ return CRA.isReachable(B, TargetBlock);
+ }
+ };
+ VisitWL visitWL(CBM, CB, *CRA.get());
+ // Were there any items in the worklist that could potentially reach
+ // this block?
+ if (CE.getWorkList()->visitItemsInWorkList(visitWL))
+ return false;
+
+ // Verify that this block is reachable from the entry block
+ if (!CRA->isReachable(&cfg->getEntry(), CB))
+ return false;
+
+ // If we get to this point, there is no connection to the entry block or an
+ // aborted block. This path is unreachable and we can report the error.
+ return true;
+}
+
+// Recursive function that determines whether an expression contains any element
+// that varies. This could be due to a compile-time constant like sizeof. An
+// expression may also involve a variable that behaves like a constant. The
+// function returns true if the expression varies, and false otherwise.
+bool IdempotentOperationChecker::CanVary(const Expr *Ex,
+ AnalysisContext *AC) {
+ // Parentheses and casts are irrelevant here
+ Ex = Ex->IgnoreParenCasts();
+
+ if (Ex->getLocStart().isMacroID())
+ return false;
+
+ switch (Ex->getStmtClass()) {
+ // Trivially true cases
+ case Stmt::ArraySubscriptExprClass:
+ case Stmt::MemberExprClass:
+ case Stmt::StmtExprClass:
+ case Stmt::CallExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ return true;
+ default:
+ return true;
+
+ // Trivially false cases
+ case Stmt::IntegerLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::OffsetOfExprClass:
+ case Stmt::CompoundLiteralExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::BinaryTypeTraitExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::InitListExprClass:
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::BlockExprClass:
+ case Stmt::BlockDeclRefExprClass:
+ return false;
+
+ // Cases requiring custom logic
+ case Stmt::SizeOfAlignOfExprClass: {
+ const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
+ if (!SE->isSizeOf())
+ return false;
+ return SE->getTypeOfArgument()->isVariableArrayType();
+ }
+ case Stmt::DeclRefExprClass:
+ // Check for constants/pseudoconstants
+ return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC);
+
+ // The next cases require recursion for subexpressions
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *B = cast<const BinaryOperator>(Ex);
+
+ // Exclude cases involving pointer arithmetic. These are usually
+ // false positives.
+ if (B->getOpcode() == BO_Sub || B->getOpcode() == BO_Add)
+ if (B->getLHS()->getType()->getAs<PointerType>())
+ return false;
+
+ return CanVary(B->getRHS(), AC)
+ || CanVary(B->getLHS(), AC);
+ }
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *U = cast<const UnaryOperator>(Ex);
+ // Handle trivial case first
+ switch (U->getOpcode()) {
+ case UO_Extension:
+ return false;
+ default:
+ return CanVary(U->getSubExpr(), AC);
+ }
+ }
+ case Stmt::ChooseExprClass:
+ return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
+ AC->getASTContext()), AC);
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::BinaryConditionalOperatorClass:
+ return CanVary(cast<AbstractConditionalOperator>(Ex)->getCond(), AC);
+ }
+}
+
+// Returns true if a DeclRefExpr is or behaves like a constant.
+bool IdempotentOperationChecker::isConstantOrPseudoConstant(
+ const DeclRefExpr *DR,
+ AnalysisContext *AC) {
+ // Check if the type of the Decl is const-qualified
+ if (DR->getType().isConstQualified())
+ return true;
+
+ // Check for an enum
+ if (isa<EnumConstantDecl>(DR->getDecl()))
+ return true;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return true;
+
+ // Check if the Decl behaves like a constant. This check also takes care of
+ // static variables, which can only change between function calls if they are
+ // modified in the AST.
+ PseudoConstantAnalysis *PCA = AC->getPseudoConstantAnalysis();
+ if (PCA->isPseudoConstant(VD))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing VarDecl's with storage other
+// than local
+bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+ if (DR)
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (!VD->hasLocalStorage())
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsNonLocalVarDecl(child))
+ return true;
+
+ return false;
+}
+
+bool IdempotentOperationChecker::CFGReachabilityAnalysis::isReachable(
+ const CFGBlock *Src,
+ const CFGBlock *Dst) {
+ const unsigned DstBlockID = Dst->getBlockID();
+
+ // If we haven't analyzed the destination node, run the analysis now
+ if (!analyzed[DstBlockID]) {
+ MapReachability(Dst);
+ analyzed[DstBlockID] = true;
+ }
+
+ // Return the cached result
+ return reachable[DstBlockID][Src->getBlockID()];
+}
+
+// Maps reachability to a common node by walking the predecessors of the
+// destination node.
+void IdempotentOperationChecker::CFGReachabilityAnalysis::MapReachability(
+ const CFGBlock *Dst) {
+
+ llvm::SmallVector<const CFGBlock *, 11> worklist;
+ llvm::BitVector visited(analyzed.size());
+
+ ReachableSet &DstReachability = reachable[Dst->getBlockID()];
+ DstReachability.resize(analyzed.size(), false);
+
+ // Start searching from the destination node, since we commonly will perform
+ // multiple queries relating to a destination node.
+ worklist.push_back(Dst);
+ bool firstRun = true;
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+
+ if (visited[block->getBlockID()])
+ continue;
+ visited[block->getBlockID()] = true;
+
+ // Update reachability information for this node -> Dst
+ if (!firstRun) {
+ // Don't insert Dst -> Dst unless it was a predecessor of itself
+ DstReachability[block->getBlockID()] = true;
+ }
+ else
+ firstRun = false;
+
+ // Add the predecessors to the worklist.
+ for (CFGBlock::const_pred_iterator i = block->pred_begin(),
+ e = block->pred_end(); i != e; ++i) {
+ worklist.push_back(*i);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
new file mode 100644
index 0000000..e855386
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
@@ -0,0 +1,51 @@
+//=-- InternalChecks.h- Builtin ExprEngine Checks -------------------*- C++ -*-=
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions to instantiate and register the "built-in"
+// checks in ExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_ExprEngine_INTERNAL_CHECKS
+#define LLVM_CLANG_GR_ExprEngine_INTERNAL_CHECKS
+
+namespace clang {
+
+namespace ento {
+
+class ExprEngine;
+
+// Foundational checks that handle basic semantics.
+void RegisterAdjustedReturnValueChecker(ExprEngine &Eng);
+void RegisterArrayBoundChecker(ExprEngine &Eng);
+void RegisterArrayBoundCheckerV2(ExprEngine &Eng);
+void RegisterAttrNonNullChecker(ExprEngine &Eng);
+void RegisterBuiltinFunctionChecker(ExprEngine &Eng);
+void RegisterCallAndMessageChecker(ExprEngine &Eng);
+void RegisterCastSizeChecker(ExprEngine &Eng);
+void RegisterDereferenceChecker(ExprEngine &Eng);
+void RegisterDivZeroChecker(ExprEngine &Eng);
+void RegisterNoReturnFunctionChecker(ExprEngine &Eng);
+void RegisterReturnPointerRangeChecker(ExprEngine &Eng);
+void RegisterReturnUndefChecker(ExprEngine &Eng);
+void RegisterUndefBranchChecker(ExprEngine &Eng);
+void RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng);
+void RegisterUndefResultChecker(ExprEngine &Eng);
+void RegisterUndefinedArraySubscriptChecker(ExprEngine &Eng);
+void RegisterUndefinedAssignmentChecker(ExprEngine &Eng);
+void RegisterVLASizeChecker(ExprEngine &Eng);
+
+// API checks.
+void RegisterOSAtomicChecker(ExprEngine &Eng);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
new file mode 100644
index 0000000..9e3adc8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -0,0 +1,311 @@
+//=== LLVMConventionsChecker.cpp - Check LLVM codebase conventions ---*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines LLVMConventionsChecker, a bunch of small little checks
+// for checking specific coding conventions in the LLVM/Clang codebase.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/StmtVisitor.h"
+#include <string>
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Generic type checking routines.
+//===----------------------------------------------------------------------===//
+
+static bool IsLLVMStringRef(QualType T) {
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ return llvm::StringRef(QualType(RT, 0).getAsString()) ==
+ "class llvm::StringRef";
+}
+
+/// Check whether the declaration is semantically inside the top-level
+/// namespace named by ns.
+static bool InNamespace(const Decl *D, llvm::StringRef NS) {
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext());
+ if (!ND)
+ return false;
+ const IdentifierInfo *II = ND->getIdentifier();
+ if (!II || !II->getName().equals(NS))
+ return false;
+ return isa<TranslationUnitDecl>(ND->getDeclContext());
+}
+
+static bool IsStdString(QualType T) {
+ if (const ElaboratedType *QT = T->getAs<ElaboratedType>())
+ T = QT->getNamedType();
+
+ const TypedefType *TT = T->getAs<TypedefType>();
+ if (!TT)
+ return false;
+
+ const TypedefDecl *TD = TT->getDecl();
+
+ if (!InNamespace(TD, "std"))
+ return false;
+
+ return TD->getName() == "string";
+}
+
+static bool IsClangType(const RecordDecl *RD) {
+ return RD->getName() == "Type" && InNamespace(RD, "clang");
+}
+
+static bool IsClangDecl(const RecordDecl *RD) {
+ return RD->getName() == "Decl" && InNamespace(RD, "clang");
+}
+
+static bool IsClangStmt(const RecordDecl *RD) {
+ return RD->getName() == "Stmt" && InNamespace(RD, "clang");
+}
+
+static bool IsClangAttr(const RecordDecl *RD) {
+ return RD->getName() == "Attr" && InNamespace(RD, "clang");
+}
+
+static bool IsStdVector(QualType T) {
+ const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
+ if (!TS)
+ return false;
+
+ TemplateName TM = TS->getTemplateName();
+ TemplateDecl *TD = TM.getAsTemplateDecl();
+
+ if (!TD || !InNamespace(TD, "std"))
+ return false;
+
+ return TD->getName() == "vector";
+}
+
+static bool IsSmallVector(QualType T) {
+ const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
+ if (!TS)
+ return false;
+
+ TemplateName TM = TS->getTemplateName();
+ TemplateDecl *TD = TM.getAsTemplateDecl();
+
+ if (!TD || !InNamespace(TD, "llvm"))
+ return false;
+
+ return TD->getName() == "SmallVector";
+}
+
+//===----------------------------------------------------------------------===//
+// CHECK: a llvm::StringRef should not be bound to a temporary std::string whose
+// lifetime is shorter than the StringRef's.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class StringRefCheckerVisitor : public StmtVisitor<StringRefCheckerVisitor> {
+ BugReporter &BR;
+public:
+ StringRefCheckerVisitor(BugReporter &br) : BR(br) {}
+ void VisitChildren(Stmt *S) {
+ for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
+ I != E; ++I)
+ if (Stmt *child = *I)
+ Visit(child);
+ }
+ void VisitStmt(Stmt *S) { VisitChildren(S); }
+ void VisitDeclStmt(DeclStmt *DS);
+private:
+ void VisitVarDecl(VarDecl *VD);
+};
+} // end anonymous namespace
+
+static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR) {
+ StringRefCheckerVisitor walker(BR);
+ walker.Visit(D->getBody());
+}
+
+void StringRefCheckerVisitor::VisitDeclStmt(DeclStmt *S) {
+ VisitChildren(S);
+
+ for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();I!=E; ++I)
+ if (VarDecl *VD = dyn_cast<VarDecl>(*I))
+ VisitVarDecl(VD);
+}
+
+void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) {
+ Expr *Init = VD->getInit();
+ if (!Init)
+ return;
+
+ // Pattern match for:
+ // llvm::StringRef x = call() (where call returns std::string)
+ if (!IsLLVMStringRef(VD->getType()))
+ return;
+ ExprWithCleanups *Ex1 = dyn_cast<ExprWithCleanups>(Init);
+ if (!Ex1)
+ return;
+ CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->getSubExpr());
+ if (!Ex2 || Ex2->getNumArgs() != 1)
+ return;
+ ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->getArg(0));
+ if (!Ex3)
+ return;
+ CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->getSubExpr());
+ if (!Ex4 || Ex4->getNumArgs() != 1)
+ return;
+ ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->getArg(0));
+ if (!Ex5)
+ return;
+ CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->getSubExpr());
+ if (!Ex6 || !IsStdString(Ex6->getType()))
+ return;
+
+ // Okay, badness! Report an error.
+ const char *desc = "StringRef should not be bound to temporary "
+ "std::string that it outlives";
+
+ BR.EmitBasicReport(desc, "LLVM Conventions", desc,
+ VD->getLocStart(), Init->getSourceRange());
+}
+
+//===----------------------------------------------------------------------===//
+// CHECK: Clang AST nodes should not have fields that can allocate
+// memory.
+//===----------------------------------------------------------------------===//
+
+static bool AllocatesMemory(QualType T) {
+ return IsStdVector(T) || IsStdString(T) || IsSmallVector(T);
+}
+
+// This type checking could be sped up via dynamic programming.
+static bool IsPartOfAST(const CXXRecordDecl *R) {
+ if (IsClangStmt(R) || IsClangType(R) || IsClangDecl(R) || IsClangAttr(R))
+ return true;
+
+ for (CXXRecordDecl::base_class_const_iterator I = R->bases_begin(),
+ E = R->bases_end(); I!=E; ++I) {
+ CXXBaseSpecifier BS = *I;
+ QualType T = BS.getType();
+ if (const RecordType *baseT = T->getAs<RecordType>()) {
+ CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getDecl());
+ if (IsPartOfAST(baseD))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+namespace {
+class ASTFieldVisitor {
+ llvm::SmallVector<FieldDecl*, 10> FieldChain;
+ const CXXRecordDecl *Root;
+ BugReporter &BR;
+public:
+ ASTFieldVisitor(const CXXRecordDecl *root, BugReporter &br)
+ : Root(root), BR(br) {}
+
+ void Visit(FieldDecl *D);
+ void ReportError(QualType T);
+};
+} // end anonymous namespace
+
+static void CheckASTMemory(const CXXRecordDecl *R, BugReporter &BR) {
+ if (!IsPartOfAST(R))
+ return;
+
+ for (RecordDecl::field_iterator I = R->field_begin(), E = R->field_end();
+ I != E; ++I) {
+ ASTFieldVisitor walker(R, BR);
+ walker.Visit(*I);
+ }
+}
+
+void ASTFieldVisitor::Visit(FieldDecl *D) {
+ FieldChain.push_back(D);
+
+ QualType T = D->getType();
+
+ if (AllocatesMemory(T))
+ ReportError(T);
+
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl()->getDefinition();
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I)
+ Visit(*I);
+ }
+
+ FieldChain.pop_back();
+}
+
+void ASTFieldVisitor::ReportError(QualType T) {
+ llvm::SmallString<1024> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "AST class '" << Root->getName() << "' has a field '"
+ << FieldChain.front()->getName() << "' that allocates heap memory";
+ if (FieldChain.size() > 1) {
+ os << " via the following chain: ";
+ bool isFirst = true;
+ for (llvm::SmallVectorImpl<FieldDecl*>::iterator I=FieldChain.begin(),
+ E=FieldChain.end(); I!=E; ++I) {
+ if (!isFirst)
+ os << '.';
+ else
+ isFirst = false;
+ os << (*I)->getName();
+ }
+ }
+ os << " (type " << FieldChain.back()->getType().getAsString() << ")";
+ os.flush();
+
+ // Note that this will fire for every translation unit that uses this
+ // class. This is suboptimal, but at least scan-build will merge
+ // duplicate HTML reports. In the future we need a unified way of merging
+ // duplicate reports across translation units. For C++ classes we cannot
+ // just report warnings when we see an out-of-line method definition for a
+ // class, as that heuristic doesn't always work (the complete definition of
+ // the class may be in the header file, for example).
+ BR.EmitBasicReport("AST node allocates heap memory", "LLVM Conventions",
+ os.str(), FieldChain.front()->getLocStart());
+}
+
+//===----------------------------------------------------------------------===//
+// LLVMConventionsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class LLVMConventionsChecker : public CheckerV2<
+ check::ASTDecl<CXXRecordDecl>,
+ check::ASTCodeBody > {
+public:
+ void checkASTDecl(const CXXRecordDecl *R, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ if (R->isDefinition())
+ CheckASTMemory(R, BR);
+ }
+
+ void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ CheckStringRefAssignedTemporary(D, BR);
+ }
+};
+}
+
+void ento::registerLLVMConventionsChecker(CheckerManager &mgr) {
+ mgr.registerChecker<LLVMConventionsChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
new file mode 100644
index 0000000..358be12
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -0,0 +1,146 @@
+// MacOSXAPIChecker.h - Checks proper use of various MacOS X APIs --*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines MacOSXAPIChecker, which is an assortment of checks on calls
+// to various, widely used Mac OS X functions.
+//
+// FIXME: What's currently in BasicObjCFoundationChecks.cpp should be migrated
+// to here, using the new Checker interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class MacOSXAPIChecker : public CheckerVisitor<MacOSXAPIChecker> {
+ enum SubChecks {
+ DispatchOnce = 0,
+ DispatchOnceF,
+ NumChecks
+ };
+
+ BugType *BTypes[NumChecks];
+
+public:
+ MacOSXAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
+ static void *getTag() { static unsigned tag = 0; return &tag; }
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} //end anonymous namespace
+
+static void RegisterMacOSXAPIChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new MacOSXAPIChecker());
+}
+
+void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterMacOSXAPIChecker);
+}
+
+//===----------------------------------------------------------------------===//
+// dispatch_once and dispatch_once_f
+//===----------------------------------------------------------------------===//
+
+static void CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
+ BugType *&BT, const IdentifierInfo *FI) {
+
+ if (!BT) {
+ llvm::SmallString<128> S;
+ llvm::raw_svector_ostream os(S);
+ os << "Improper use of '" << FI->getName() << '\'';
+ BT = new BugType(os.str(), "Mac OS X API");
+ }
+
+ if (CE->getNumArgs() < 1)
+ return;
+
+ // Check if the first argument is stack allocated. If so, issue a warning
+ // because that's likely to be bad news.
+ const GRState *state = C.getState();
+ const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+ if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
+ return;
+
+ ExplodedNode *N = C.generateSink(state);
+ if (!N)
+ return;
+
+ llvm::SmallString<256> S;
+ llvm::raw_svector_ostream os(S);
+ os << "Call to '" << FI->getName() << "' uses";
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R))
+ os << " the local variable '" << VR->getDecl()->getName() << '\'';
+ else
+ os << " stack allocated memory";
+ os << " for the predicate value. Using such transient memory for "
+ "the predicate is potentially dangerous.";
+ if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+ os << " Perhaps you intended to declare the variable as 'static'?";
+
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), N);
+ report->addRange(CE->getArg(0)->getSourceRange());
+ C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// Central dispatch function.
+//===----------------------------------------------------------------------===//
+
+typedef void (*SubChecker)(CheckerContext &C, const CallExpr *CE, BugType *&BT,
+ const IdentifierInfo *FI);
+namespace {
+ class SubCheck {
+ SubChecker SC;
+ BugType **BT;
+ public:
+ SubCheck(SubChecker sc, BugType *& bt) : SC(sc), BT(&bt) {}
+ SubCheck() : SC(NULL), BT(NULL) {}
+
+ void run(CheckerContext &C, const CallExpr *CE,
+ const IdentifierInfo *FI) const {
+ if (SC)
+ SC(C, CE, *BT, FI);
+ }
+ };
+} // end anonymous namespace
+
+void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ // FIXME: Mostly copy and paste from UnixAPIChecker. Should refactor.
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ const FunctionTextRegion *Fn =
+ dyn_cast_or_null<FunctionTextRegion>(state->getSVal(Callee).getAsRegion());
+
+ if (!Fn)
+ return;
+
+ const IdentifierInfo *FI = Fn->getDecl()->getIdentifier();
+ if (!FI)
+ return;
+
+ const SubCheck &SC =
+ llvm::StringSwitch<SubCheck>(FI->getName())
+ .Case("dispatch_once", SubCheck(CheckDispatchOnce, BTypes[DispatchOnce]))
+ .Case("dispatch_once_f", SubCheck(CheckDispatchOnce,
+ BTypes[DispatchOnceF]))
+ .Default(SubCheck());
+
+ SC.run(C, CE, FI);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Makefile b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Makefile
new file mode 100644
index 0000000..97f4642
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Makefile
@@ -0,0 +1,24 @@
+##===- clang/lib/Checker/Makefile --------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This implements analyses built on top of source-level CFGs.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../..
+LIBRARYNAME := clangStaticAnalyzerCheckers
+
+BUILT_SOURCES = Checkers.inc
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/Checkers.inc.tmp : Checkers.td $(PROJ_SRC_DIR)/$(CLANG_LEVEL)/include/clang/StaticAnalyzer/Checkers/CheckerBase.td $(TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Clang SA Checkers tables with tblgen"
+ $(Verb) $(TableGen) -gen-clang-sa-checkers -I $(PROJ_SRC_DIR)/$(CLANG_LEVEL)/include -o $(call SYSPATH, $@) $<
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
new file mode 100644
index 0000000..9d3a887
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -0,0 +1,731 @@
+//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines malloc/free checker, which checks for potential memory
+// leaks, double free, and use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExperimentalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class RefState {
+ enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
+ Relinquished } K;
+ const Stmt *S;
+
+public:
+ RefState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+ bool isAllocated() const { return K == AllocateUnchecked; }
+ //bool isFailed() const { return K == AllocateFailed; }
+ bool isReleased() const { return K == Released; }
+ //bool isEscaped() const { return K == Escaped; }
+ //bool isRelinquished() const { return K == Relinquished; }
+
+ bool operator==(const RefState &X) const {
+ return K == X.K && S == X.S;
+ }
+
+ static RefState getAllocateUnchecked(const Stmt *s) {
+ return RefState(AllocateUnchecked, s);
+ }
+ static RefState getAllocateFailed() {
+ return RefState(AllocateFailed, 0);
+ }
+ static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
+ static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
+ static RefState getRelinquished(const Stmt *s) {
+ return RefState(Relinquished, s);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(K);
+ ID.AddPointer(S);
+ }
+};
+
+class RegionState {};
+
+class MallocChecker : public CheckerVisitor<MallocChecker> {
+ BuiltinBug *BT_DoubleFree;
+ BuiltinBug *BT_Leak;
+ BuiltinBug *BT_UseFree;
+ BuiltinBug *BT_UseRelinquished;
+ BuiltinBug *BT_BadFree;
+ IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
+
+public:
+ MallocChecker()
+ : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0),
+ BT_BadFree(0),
+ II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
+ static void *getTag();
+ bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+ void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
+ void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+ const GRState *evalAssume(const GRState *state, SVal Cond, bool Assumption,
+ bool *respondsToCallback);
+ void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
+
+private:
+ void MallocMem(CheckerContext &C, const CallExpr *CE);
+ void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att);
+ const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
+ const Expr *SizeEx, SVal Init,
+ const GRState *state) {
+ return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
+ }
+ const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
+ SVal SizeEx, SVal Init,
+ const GRState *state);
+
+ void FreeMem(CheckerContext &C, const CallExpr *CE);
+ void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att);
+ const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
+ const GRState *state, unsigned Num, bool Hold);
+
+ void ReallocMem(CheckerContext &C, const CallExpr *CE);
+ void CallocMem(CheckerContext &C, const CallExpr *CE);
+
+ bool SummarizeValue(llvm::raw_ostream& os, SVal V);
+ bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR);
+ void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range);
+};
+} // end anonymous namespace
+
+typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
+
+namespace clang {
+namespace ento {
+ template <>
+ struct GRStateTrait<RegionState>
+ : public GRStatePartialTrait<RegionStateTy> {
+ static void *GDMIndex() { return MallocChecker::getTag(); }
+ };
+}
+}
+
+void ento::RegisterMallocChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new MallocChecker());
+}
+
+void *MallocChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+bool MallocChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II_malloc)
+ II_malloc = &Ctx.Idents.get("malloc");
+ if (!II_free)
+ II_free = &Ctx.Idents.get("free");
+ if (!II_realloc)
+ II_realloc = &Ctx.Idents.get("realloc");
+ if (!II_calloc)
+ II_calloc = &Ctx.Idents.get("calloc");
+
+ if (FD->getIdentifier() == II_malloc) {
+ MallocMem(C, CE);
+ return true;
+ }
+
+ if (FD->getIdentifier() == II_free) {
+ FreeMem(C, CE);
+ return true;
+ }
+
+ if (FD->getIdentifier() == II_realloc) {
+ ReallocMem(C, CE);
+ return true;
+ }
+
+ if (FD->getIdentifier() == II_calloc) {
+ CallocMem(C, CE);
+ return true;
+ }
+
+ // Check all the attributes, if there are any.
+ // There can be multiple of these attributes.
+ bool rv = false;
+ if (FD->hasAttrs()) {
+ for (specific_attr_iterator<OwnershipAttr>
+ i = FD->specific_attr_begin<OwnershipAttr>(),
+ e = FD->specific_attr_end<OwnershipAttr>();
+ i != e; ++i) {
+ switch ((*i)->getOwnKind()) {
+ case OwnershipAttr::Returns: {
+ MallocMemReturnsAttr(C, CE, *i);
+ rv = true;
+ break;
+ }
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds: {
+ FreeMemAttr(C, CE, *i);
+ rv = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return rv;
+}
+
+void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(),
+ C.getState());
+ C.addTransition(state);
+}
+
+void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att) {
+ if (Att->getModule() != "malloc")
+ return;
+
+ OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+ if (I != E) {
+ const GRState *state =
+ MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+ C.addTransition(state);
+ return;
+ }
+ const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
+ C.getState());
+ C.addTransition(state);
+}
+
+const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
+ const CallExpr *CE,
+ SVal Size, SVal Init,
+ const GRState *state) {
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ SValBuilder &svalBuilder = C.getSValBuilder();
+
+ // Set the return value.
+ SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
+ state = state->BindExpr(CE, retVal);
+
+ // Fill the region with the initialization value.
+ state = state->bindDefault(retVal, Init);
+
+ // Set the region's extent equal to the Size parameter.
+ const SymbolicRegion *R = cast<SymbolicRegion>(retVal.getAsRegion());
+ DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
+ DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size);
+ DefinedOrUnknownSVal extentMatchesSize =
+ svalBuilder.evalEQ(state, Extent, DefinedSize);
+
+ state = state->assume(extentMatchesSize, true);
+ assert(state);
+
+ SymbolRef Sym = retVal.getAsLocSymbol();
+ assert(Sym);
+
+ // Set the symbol's state to Allocated.
+ return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE));
+}
+
+void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
+
+ if (state)
+ C.addTransition(state);
+}
+
+void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att) {
+ if (Att->getModule() != "malloc")
+ return;
+
+ for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+ I != E; ++I) {
+ const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
+ Att->getOwnKind() == OwnershipAttr::Holds);
+ if (state)
+ C.addTransition(state);
+ }
+}
+
+const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
+ const GRState *state, unsigned Num,
+ bool Hold) {
+ const Expr *ArgExpr = CE->getArg(Num);
+ SVal ArgVal = state->getSVal(ArgExpr);
+
+ DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(location))
+ return state;
+
+ // FIXME: Technically using 'Assume' here can result in a path
+ // bifurcation. In such cases we need to return two states, not just one.
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->assume(location);
+
+ // The explicit NULL case, no operation is performed.
+ if (nullState && !notNullState)
+ return nullState;
+
+ assert(notNullState);
+
+ // Unknown values could easily be okay
+ // Undefined values are handled elsewhere
+ if (ArgVal.isUnknownOrUndef())
+ return notNullState;
+
+ const MemRegion *R = ArgVal.getAsRegion();
+
+ // Nonlocs can't be freed, of course.
+ // Non-region locations (labels and fixed addresses) also shouldn't be freed.
+ if (!R) {
+ ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+ return NULL;
+ }
+
+ R = R->StripCasts();
+
+ // Blocks might show up as heap data, but should not be free()d
+ if (isa<BlockDataRegion>(R)) {
+ ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+ return NULL;
+ }
+
+ const MemSpaceRegion *MS = R->getMemorySpace();
+
+ // Parameters, locals, statics, and globals shouldn't be freed.
+ if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
+ // FIXME: at the time this code was written, malloc() regions were
+ // represented by conjured symbols, which are all in UnknownSpaceRegion.
+ // This means that there isn't actually anything from HeapSpaceRegion
+ // that should be freed, even though we allow it here.
+ // Of course, free() can work on memory allocated outside the current
+ // function, so UnknownSpaceRegion is always a possibility.
+ // False negatives are better than false positives.
+
+ ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
+ return NULL;
+ }
+
+ const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
+ // Various cases could lead to non-symbol values here.
+ // For now, ignore them.
+ if (!SR)
+ return notNullState;
+
+ SymbolRef Sym = SR->getSymbol();
+ const RefState *RS = state->get<RegionState>(Sym);
+
+ // If the symbol has not been tracked, return. This is possible when free() is
+ // called on a pointer that does not get its pointee directly from malloc().
+ // Full support of this requires inter-procedural analysis.
+ if (!RS)
+ return notNullState;
+
+ // Check double free.
+ if (RS->isReleased()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_DoubleFree)
+ BT_DoubleFree
+ = new BuiltinBug("Double free",
+ "Try to free a memory block that has been released");
+ // FIXME: should find where it's freed last time.
+ BugReport *R = new BugReport(*BT_DoubleFree,
+ BT_DoubleFree->getDescription(), N);
+ C.EmitReport(R);
+ }
+ return NULL;
+ }
+
+ // Normal free.
+ if (Hold)
+ return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE));
+ return notNullState->set<RegionState>(Sym, RefState::getReleased(CE));
+}
+
+bool MallocChecker::SummarizeValue(llvm::raw_ostream& os, SVal V) {
+ if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V))
+ os << "an integer (" << IntVal->getValue() << ")";
+ else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V))
+ os << "a constant address (" << ConstAddr->getValue() << ")";
+ else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V))
+ os << "the address of the label '" << Label->getLabel()->getName() << "'";
+ else
+ return false;
+
+ return true;
+}
+
+bool MallocChecker::SummarizeRegion(llvm::raw_ostream& os,
+ const MemRegion *MR) {
+ switch (MR->getKind()) {
+ case MemRegion::FunctionTextRegionKind: {
+ const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+ if (FD)
+ os << "the address of the function '" << FD << "'";
+ else
+ os << "the address of a function";
+ return true;
+ }
+ case MemRegion::BlockTextRegionKind:
+ os << "block text";
+ return true;
+ case MemRegion::BlockDataRegionKind:
+ // FIXME: where the block came from?
+ os << "a block";
+ return true;
+ default: {
+ const MemSpaceRegion *MS = MR->getMemorySpace();
+
+ switch (MS->getKind()) {
+ case MemRegion::StackLocalsSpaceRegionKind: {
+ const VarRegion *VR = dyn_cast<VarRegion>(MR);
+ const VarDecl *VD;
+ if (VR)
+ VD = VR->getDecl();
+ else
+ VD = NULL;
+
+ if (VD)
+ os << "the address of the local variable '" << VD->getName() << "'";
+ else
+ os << "the address of a local stack variable";
+ return true;
+ }
+ case MemRegion::StackArgumentsSpaceRegionKind: {
+ const VarRegion *VR = dyn_cast<VarRegion>(MR);
+ const VarDecl *VD;
+ if (VR)
+ VD = VR->getDecl();
+ else
+ VD = NULL;
+
+ if (VD)
+ os << "the address of the parameter '" << VD->getName() << "'";
+ else
+ os << "the address of a parameter";
+ return true;
+ }
+ case MemRegion::NonStaticGlobalSpaceRegionKind:
+ case MemRegion::StaticGlobalSpaceRegionKind: {
+ const VarRegion *VR = dyn_cast<VarRegion>(MR);
+ const VarDecl *VD;
+ if (VR)
+ VD = VR->getDecl();
+ else
+ VD = NULL;
+
+ if (VD) {
+ if (VD->isStaticLocal())
+ os << "the address of the static variable '" << VD->getName() << "'";
+ else
+ os << "the address of the global variable '" << VD->getName() << "'";
+ } else
+ os << "the address of a global variable";
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+ }
+}
+
+void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
+ SourceRange range) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_BadFree)
+ BT_BadFree = new BuiltinBug("Bad free");
+
+ llvm::SmallString<100> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ const MemRegion *MR = ArgVal.getAsRegion();
+ if (MR) {
+ while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR))
+ MR = ER->getSuperRegion();
+
+ // Special case for alloca()
+ if (isa<AllocaRegion>(MR))
+ os << "Argument to free() was allocated by alloca(), not malloc()";
+ else {
+ os << "Argument to free() is ";
+ if (SummarizeRegion(os, MR))
+ os << ", which is not memory allocated by malloc()";
+ else
+ os << "not memory allocated by malloc()";
+ }
+ } else {
+ os << "Argument to free() is ";
+ if (SummarizeValue(os, ArgVal))
+ os << ", which is not memory allocated by malloc()";
+ else
+ os << "not memory allocated by malloc()";
+ }
+
+ EnhancedBugReport *R = new EnhancedBugReport(*BT_BadFree, os.str(), N);
+ R->addRange(range);
+ C.EmitReport(R);
+ }
+}
+
+void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *arg0Expr = CE->getArg(0);
+ DefinedOrUnknownSVal arg0Val
+ = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr));
+
+ SValBuilder &svalBuilder = C.getSValBuilder();
+
+ DefinedOrUnknownSVal PtrEQ =
+ svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
+
+ // If the ptr is NULL, the call is equivalent to malloc(size).
+ if (const GRState *stateEqual = state->assume(PtrEQ, true)) {
+ // Hack: set the NULL symbolic region to released to suppress false warning.
+ // In the future we should add more states for allocated regions, e.g.,
+ // CheckedNull, CheckedNonNull.
+
+ SymbolRef Sym = arg0Val.getAsLocSymbol();
+ if (Sym)
+ stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
+
+ const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
+ UndefinedVal(), stateEqual);
+ C.addTransition(stateMalloc);
+ }
+
+ if (const GRState *stateNotEqual = state->assume(PtrEQ, false)) {
+ const Expr *Arg1 = CE->getArg(1);
+ DefinedOrUnknownSVal Arg1Val =
+ cast<DefinedOrUnknownSVal>(stateNotEqual->getSVal(Arg1));
+ DefinedOrUnknownSVal SizeZero =
+ svalBuilder.evalEQ(stateNotEqual, Arg1Val,
+ svalBuilder.makeIntValWithPtrWidth(0, false));
+
+ if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
+ if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false))
+ C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
+
+ if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
+ if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
+ 0, false)) {
+ // FIXME: We should copy the content of the original buffer.
+ const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
+ UnknownVal(), stateFree);
+ C.addTransition(stateRealloc);
+ }
+ }
+}
+
+void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ SValBuilder &svalBuilder = C.getSValBuilder();
+
+ SVal count = state->getSVal(CE->getArg(0));
+ SVal elementSize = state->getSVal(CE->getArg(1));
+ SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
+ svalBuilder.getContext().getSizeType());
+ SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
+
+ C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state));
+}
+
+void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper)
+{
+ if (!SymReaper.hasDeadSymbols())
+ return;
+
+ const GRState *state = C.getState();
+ RegionStateTy RS = state->get<RegionState>();
+ RegionStateTy::Factory &F = state->get_context<RegionState>();
+
+ for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+ if (SymReaper.isDead(I->first)) {
+ if (I->second.isAllocated()) {
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT_Leak)
+ BT_Leak = new BuiltinBug("Memory leak",
+ "Allocated memory never released. Potential memory leak.");
+ // FIXME: where it is allocated.
+ BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+ C.EmitReport(R);
+ }
+ }
+
+ // Remove the dead symbol from the map.
+ RS = F.remove(RS, I->first);
+ }
+ }
+ C.generateNode(state->set<RegionState>(RS));
+}
+
+void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
+ ExprEngine &Eng) {
+ const GRState *state = B.getState();
+ RegionStateTy M = state->get<RegionState>();
+
+ for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ RefState RS = I->second;
+ if (RS.isAllocated()) {
+ ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ if (N) {
+ if (!BT_Leak)
+ BT_Leak = new BuiltinBug("Memory leak",
+ "Allocated memory never released. Potential memory leak.");
+ BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+ Eng.getBugReporter().EmitReport(R);
+ }
+ }
+ }
+}
+
+void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+ const Expr *retExpr = S->getRetValue();
+ if (!retExpr)
+ return;
+
+ const GRState *state = C.getState();
+
+ SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
+ if (!Sym)
+ return;
+
+ const RefState *RS = state->get<RegionState>(Sym);
+ if (!RS)
+ return;
+
+ // FIXME: check other cases.
+ if (RS->isAllocated())
+ state = state->set<RegionState>(Sym, RefState::getEscaped(S));
+
+ C.addTransition(state);
+}
+
+const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond,
+ bool Assumption,
+ bool * /* respondsToCallback */) {
+ // If a symblic region is assumed to NULL, set its state to AllocateFailed.
+ // FIXME: should also check symbols assumed to non-null.
+
+ RegionStateTy RS = state->get<RegionState>();
+
+ for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+ if (state->getSymVal(I.getKey()))
+ state = state->set<RegionState>(I.getKey(),RefState::getAllocateFailed());
+ }
+
+ return state;
+}
+
+// Check if the location is a freed symbolic region.
+void MallocChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
+ bool isLoad) {
+ SymbolRef Sym = l.getLocSymbolInBase();
+ if (Sym) {
+ const RefState *RS = C.getState()->get<RegionState>(Sym);
+ if (RS && RS->isReleased()) {
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT_UseFree)
+ BT_UseFree = new BuiltinBug("Use dynamically allocated memory after"
+ " it is freed.");
+
+ BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),
+ N);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
+
+void MallocChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *StoreE,
+ SVal location,
+ SVal val) {
+ // The PreVisitBind implements the same algorithm as already used by the
+ // Objective C ownership checker: if the pointer escaped from this scope by
+ // assignment, let it go. However, assigning to fields of a stack-storage
+ // structure does not transfer ownership.
+
+ const GRState *state = C.getState();
+ DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(l))
+ return;
+
+ // Before checking if the state is null, check if 'val' has a RefState.
+ // Only then should we check for null and bifurcate the state.
+ SymbolRef Sym = val.getLocSymbolInBase();
+ if (Sym) {
+ if (const RefState *RS = state->get<RegionState>(Sym)) {
+ // If ptr is NULL, no operation is performed.
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->assume(l);
+
+ // Generate a transition for 'nullState' to record the assumption
+ // that the state was null.
+ if (nullState)
+ C.addTransition(nullState);
+
+ if (!notNullState)
+ return;
+
+ if (RS->isAllocated()) {
+ // Something we presently own is being assigned somewhere.
+ const MemRegion *AR = location.getAsRegion();
+ if (!AR)
+ return;
+ AR = AR->StripCasts()->getBaseRegion();
+ do {
+ // If it is on the stack, we still own it.
+ if (AR->hasStackNonParametersStorage())
+ break;
+
+ // If the state can't represent this binding, we still own it.
+ if (notNullState == (notNullState->bindLoc(cast<Loc>(location),
+ UnknownVal())))
+ break;
+
+ // We no longer own this pointer.
+ notNullState =
+ notNullState->set<RegionState>(Sym,
+ RefState::getRelinquished(StoreE));
+ }
+ while (false);
+ }
+ C.addTransition(notNullState);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
new file mode 100644
index 0000000..9fb89d7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -0,0 +1,92 @@
+//=- NSAutoreleasePoolChecker.cpp --------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a NSAutoreleasePoolChecker, a small checker that warns
+// about subpar uses of NSAutoreleasePool. Note that while the check itself
+// (in it's current form) could be written as a flow-insensitive check, in
+// can be potentially enhanced in the future with flow-sensitive information.
+// It is also a good example of the CheckerVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class NSAutoreleasePoolChecker
+ : public CheckerVisitor<NSAutoreleasePoolChecker> {
+
+ Selector releaseS;
+
+public:
+ NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
+
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+
+ void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+};
+
+} // end anonymous namespace
+
+
+static void RegisterNSAutoreleasePoolChecker(ExprEngine &Eng) {
+ ASTContext &Ctx = Eng.getContext();
+ if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
+ Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
+ Ctx)));
+ }
+}
+
+void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterNSAutoreleasePoolChecker);
+}
+
+void
+NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
+ ObjCMessage msg) {
+
+ const Expr *receiver = msg.getInstanceReceiver();
+ if (!receiver)
+ return;
+
+ // FIXME: Enhance with value-tracking information instead of consulting
+ // the type of the expression.
+ const ObjCObjectPointerType* PT =
+ receiver->getType()->getAs<ObjCObjectPointerType>();
+
+ if (!PT)
+ return;
+ const ObjCInterfaceDecl* OD = PT->getInterfaceDecl();
+ if (!OD)
+ return;
+ if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+ return;
+
+ // Sending 'release' message?
+ if (msg.getSelector() != releaseS)
+ return;
+
+ SourceRange R = msg.getSourceRange();
+
+ C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
+ "API Upgrade (Apple)",
+ "Use -drain instead of -release when using NSAutoreleasePool "
+ "and garbage collection", R.getBegin(), &R, 1);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
new file mode 100644
index 0000000..7a1b978
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -0,0 +1,238 @@
+//=- NSErrorCheckerer.cpp - Coding conventions for uses of NSError -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a CheckNSError, a flow-insenstive check
+// that determines if an Objective-C class interface correctly returns
+// a non-void return type.
+//
+// File under feature request PR 2600.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
+#include "BasicObjCFoundationChecks.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class NSErrorChecker : public BugType {
+ const Decl &CodeDecl;
+ const bool isNSErrorWarning;
+ IdentifierInfo * const II;
+ ExprEngine &Eng;
+
+ void CheckSignature(const ObjCMethodDecl& MD, QualType& ResultTy,
+ llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
+
+ void CheckSignature(const FunctionDecl& MD, QualType& ResultTy,
+ llvm::SmallVectorImpl<VarDecl*>& ErrorParams);
+
+ bool CheckNSErrorArgument(QualType ArgTy);
+ bool CheckCFErrorArgument(QualType ArgTy);
+
+ void CheckParamDeref(const VarDecl *V, const LocationContext *LC,
+ const GRState *state, BugReporter& BR);
+
+ void EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl);
+
+public:
+ NSErrorChecker(const Decl &D, bool isNSError, ExprEngine& eng)
+ : BugType(isNSError ? "NSError** null dereference"
+ : "CFErrorRef* null dereference",
+ "Coding conventions (Apple)"),
+ CodeDecl(D),
+ isNSErrorWarning(isNSError),
+ II(&eng.getContext().Idents.get(isNSErrorWarning ? "NSError":"CFErrorRef")),
+ Eng(eng) {}
+
+ void FlushReports(BugReporter& BR);
+};
+
+} // end anonymous namespace
+
+void ento::RegisterNSErrorChecks(BugReporter& BR, ExprEngine &Eng,
+ const Decl &D) {
+ BR.Register(new NSErrorChecker(D, true, Eng));
+ BR.Register(new NSErrorChecker(D, false, Eng));
+}
+
+void NSErrorChecker::FlushReports(BugReporter& BR) {
+ // Get the analysis engine and the exploded analysis graph.
+ ExplodedGraph& G = Eng.getGraph();
+
+ // Get the ASTContext, which is useful for querying type information.
+ ASTContext &Ctx = BR.getContext();
+
+ QualType ResultTy;
+ llvm::SmallVector<VarDecl*, 5> ErrorParams;
+
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CodeDecl))
+ CheckSignature(*MD, ResultTy, ErrorParams);
+ else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(&CodeDecl))
+ CheckSignature(*FD, ResultTy, ErrorParams);
+ else
+ return;
+
+ if (ErrorParams.empty())
+ return;
+
+ if (ResultTy == Ctx.VoidTy) EmitRetTyWarning(BR, CodeDecl);
+
+ for (ExplodedGraph::roots_iterator RI=G.roots_begin(), RE=G.roots_end();
+ RI!=RE; ++RI) {
+ // Scan the parameters for an implicit null dereference.
+ for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
+ E=ErrorParams.end(); I!=E; ++I)
+ CheckParamDeref(*I, (*RI)->getLocationContext(), (*RI)->getState(), BR);
+ }
+}
+
+void NSErrorChecker::EmitRetTyWarning(BugReporter& BR, const Decl& CodeDecl) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ if (isa<ObjCMethodDecl>(CodeDecl))
+ os << "Method";
+ else
+ os << "Function";
+
+ os << " accepting ";
+ os << (isNSErrorWarning ? "NSError**" : "CFErrorRef*");
+ os << " should have a non-void return value to indicate whether or not an "
+ "error occurred";
+
+ BR.EmitBasicReport(isNSErrorWarning
+ ? "Bad return type when passing NSError**"
+ : "Bad return type when passing CFError*",
+ getCategory(), os.str(),
+ CodeDecl.getLocation());
+}
+
+void
+NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy,
+ llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
+
+ ResultTy = M.getResultType();
+
+ for (ObjCMethodDecl::param_iterator I=M.param_begin(),
+ E=M.param_end(); I!=E; ++I) {
+
+ QualType T = (*I)->getType();
+
+ if (isNSErrorWarning) {
+ if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
+ }
+ else if (CheckCFErrorArgument(T))
+ ErrorParams.push_back(*I);
+ }
+}
+
+void
+NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy,
+ llvm::SmallVectorImpl<VarDecl*>& ErrorParams) {
+
+ ResultTy = F.getResultType();
+
+ for (FunctionDecl::param_const_iterator I = F.param_begin(),
+ E = F.param_end(); I != E; ++I) {
+
+ QualType T = (*I)->getType();
+
+ if (isNSErrorWarning) {
+ if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I);
+ }
+ else if (CheckCFErrorArgument(T))
+ ErrorParams.push_back(*I);
+ }
+}
+
+
+bool NSErrorChecker::CheckNSErrorArgument(QualType ArgTy) {
+
+ const PointerType* PPT = ArgTy->getAs<PointerType>();
+ if (!PPT)
+ return false;
+
+ const ObjCObjectPointerType* PT =
+ PPT->getPointeeType()->getAs<ObjCObjectPointerType>();
+
+ if (!PT)
+ return false;
+
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+
+ // FIXME: Can ID ever be NULL?
+ if (ID)
+ return II == ID->getIdentifier();
+
+ return false;
+}
+
+bool NSErrorChecker::CheckCFErrorArgument(QualType ArgTy) {
+
+ const PointerType* PPT = ArgTy->getAs<PointerType>();
+ if (!PPT) return false;
+
+ const TypedefType* TT = PPT->getPointeeType()->getAs<TypedefType>();
+ if (!TT) return false;
+
+ return TT->getDecl()->getIdentifier() == II;
+}
+
+void NSErrorChecker::CheckParamDeref(const VarDecl *Param,
+ const LocationContext *LC,
+ const GRState *rootState,
+ BugReporter& BR) {
+
+ SVal ParamL = rootState->getLValue(Param, LC);
+ const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
+ assert (ParamR && "Parameters always have VarRegions.");
+ SVal ParamSVal = rootState->getSVal(ParamR);
+
+ // FIXME: For now assume that ParamSVal is symbolic. We need to generalize
+ // this later.
+ SymbolRef ParamSym = ParamSVal.getAsLocSymbol();
+ if (!ParamSym)
+ return;
+
+ // Iterate over the implicit-null dereferences.
+ ExplodedNode *const* I, *const* E;
+ llvm::tie(I, E) = GetImplicitNullDereferences(Eng);
+ for ( ; I != E; ++I) {
+ const GRState *state = (*I)->getState();
+ SVal location = state->getSVal((*I)->getLocationAs<StmtPoint>()->getStmt());
+ if (location.getAsSymbol() != ParamSym)
+ continue;
+
+ // Emit an error.
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Potential null dereference. According to coding standards ";
+
+ if (isNSErrorWarning)
+ os << "in 'Creating and Returning NSError Objects' the parameter '";
+ else
+ os << "documented in CoreFoundation/CFError.h the parameter '";
+
+ os << Param << "' may be null.";
+
+ BugReport *report = new BugReport(*this, os.str(), *I);
+ // FIXME: Notable symbols are now part of the report. We should
+ // add support for notable symbols in BugReport.
+ // BR.addNotableSymbol(SV->getSymbol());
+ BR.EmitReport(report);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
new file mode 100644
index 0000000..40040ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -0,0 +1,80 @@
+//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NoReturnFunctionChecker, which evaluates functions that do not
+// return to the caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class NoReturnFunctionChecker : public CheckerVisitor<NoReturnFunctionChecker> {
+public:
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+
+void ento::RegisterNoReturnFunctionChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new NoReturnFunctionChecker());
+}
+
+void NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+
+ bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
+
+ if (!BuildSinks) {
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return;
+
+ if (FD->getAttr<AnalyzerNoReturnAttr>())
+ BuildSinks = true;
+ else if (const IdentifierInfo *II = FD->getIdentifier()) {
+ // HACK: Some functions are not marked noreturn, and don't return.
+ // Here are a few hardwired ones. If this takes too long, we can
+ // potentially cache these results.
+ BuildSinks
+ = llvm::StringSwitch<bool>(llvm::StringRef(II->getName()))
+ .Case("exit", true)
+ .Case("panic", true)
+ .Case("error", true)
+ .Case("Assert", true)
+ // FIXME: This is just a wrapper around throwing an exception.
+ // Eventually inter-procedural analysis should handle this easily.
+ .Case("ziperr", true)
+ .Case("assfail", true)
+ .Case("db_error", true)
+ .Case("__assert", true)
+ .Case("__assert_rtn", true)
+ .Case("__assert_fail", true)
+ .Case("dtrace_assfail", true)
+ .Case("yy_fatal_error", true)
+ .Case("_XCAssertionFailureHandler", true)
+ .Case("_DTAssertionFailureHandler", true)
+ .Case("_TSAssertionFailureHandler", true)
+ .Default(false);
+ }
+ }
+
+ if (BuildSinks)
+ C.generateSink(CE);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
new file mode 100644
index 0000000..e1126b6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
@@ -0,0 +1,203 @@
+//=== OSAtomicChecker.cpp - OSAtomic functions evaluator --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker evaluates OSAtomic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+#include "clang/Basic/Builtins.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class OSAtomicChecker : public Checker {
+public:
+ static void *getTag() { static int tag = 0; return &tag; }
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+
+private:
+ bool evalOSAtomicCompareAndSwap(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+
+void ento::RegisterOSAtomicChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new OSAtomicChecker());
+}
+
+bool OSAtomicChecker::evalCallExpr(CheckerContext &C,const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+
+ const FunctionDecl* FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ const IdentifierInfo *II = FD->getIdentifier();
+ if (!II)
+ return false;
+
+ llvm::StringRef FName(II->getName());
+
+ // Check for compare and swap.
+ if (FName.startswith("OSAtomicCompareAndSwap") ||
+ FName.startswith("objc_atomicCompareAndSwap"))
+ return evalOSAtomicCompareAndSwap(C, CE);
+
+ // FIXME: Other atomics.
+ return false;
+}
+
+bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C,
+ const CallExpr *CE) {
+ // Not enough arguments to match OSAtomicCompareAndSwap?
+ if (CE->getNumArgs() != 3)
+ return false;
+
+ ASTContext &Ctx = C.getASTContext();
+ const Expr *oldValueExpr = CE->getArg(0);
+ QualType oldValueType = Ctx.getCanonicalType(oldValueExpr->getType());
+
+ const Expr *newValueExpr = CE->getArg(1);
+ QualType newValueType = Ctx.getCanonicalType(newValueExpr->getType());
+
+ // Do the types of 'oldValue' and 'newValue' match?
+ if (oldValueType != newValueType)
+ return false;
+
+ const Expr *theValueExpr = CE->getArg(2);
+ const PointerType *theValueType=theValueExpr->getType()->getAs<PointerType>();
+
+ // theValueType not a pointer?
+ if (!theValueType)
+ return false;
+
+ QualType theValueTypePointee =
+ Ctx.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType();
+
+ // The pointee must match newValueType and oldValueType.
+ if (theValueTypePointee != newValueType)
+ return false;
+
+ static unsigned magic_load = 0;
+ static unsigned magic_store = 0;
+
+ const void *OSAtomicLoadTag = &magic_load;
+ const void *OSAtomicStoreTag = &magic_store;
+
+ // Load 'theValue'.
+ ExprEngine &Engine = C.getEngine();
+ const GRState *state = C.getState();
+ ExplodedNodeSet Tmp;
+ SVal location = state->getSVal(theValueExpr);
+ // Here we should use the value type of the region as the load type, because
+ // we are simulating the semantics of the function, not the semantics of
+ // passing argument. So the type of theValue expr is not we are loading.
+ // But usually the type of the varregion is not the type we want either,
+ // we still need to do a CastRetrievedVal in store manager. So actually this
+ // LoadTy specifying can be omitted. But we put it here to emphasize the
+ // semantics.
+ QualType LoadTy;
+ if (const TypedRegion *TR =
+ dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
+ LoadTy = TR->getValueType();
+ }
+ Engine.evalLoad(Tmp, theValueExpr, C.getPredecessor(),
+ state, location, OSAtomicLoadTag, LoadTy);
+
+ if (Tmp.empty()) {
+ // If no nodes were generated, other checkers must generated sinks. But
+ // since the builder state was restored, we set it manually to prevent
+ // auto transition.
+ // FIXME: there should be a better approach.
+ C.getNodeBuilder().BuildSinks = true;
+ return true;
+ }
+
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end();
+ I != E; ++I) {
+
+ ExplodedNode *N = *I;
+ const GRState *stateLoad = N->getState();
+ SVal theValueVal_untested = stateLoad->getSVal(theValueExpr);
+ SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr);
+
+ // FIXME: Issue an error.
+ if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
+ return false;
+ }
+
+ DefinedOrUnknownSVal theValueVal =
+ cast<DefinedOrUnknownSVal>(theValueVal_untested);
+ DefinedOrUnknownSVal oldValueVal =
+ cast<DefinedOrUnknownSVal>(oldValueVal_untested);
+
+ SValBuilder &svalBuilder = Engine.getSValBuilder();
+
+ // Perform the comparison.
+ DefinedOrUnknownSVal Cmp = svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);
+
+ const GRState *stateEqual = stateLoad->assume(Cmp, true);
+
+ // Were they equal?
+ if (stateEqual) {
+ // Perform the store.
+ ExplodedNodeSet TmpStore;
+ SVal val = stateEqual->getSVal(newValueExpr);
+
+ // Handle implicit value casts.
+ if (const TypedRegion *R =
+ dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
+ val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType());
+ }
+
+ Engine.evalStore(TmpStore, NULL, theValueExpr, N,
+ stateEqual, location, val, OSAtomicStoreTag);
+
+ if (TmpStore.empty()) {
+ // If no nodes were generated, other checkers must generated sinks. But
+ // since the builder state was restored, we set it manually to prevent
+ // auto transition.
+ // FIXME: there should be a better approach.
+ C.getNodeBuilder().BuildSinks = true;
+ return true;
+ }
+
+ // Now bind the result of the comparison.
+ for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
+ E2 = TmpStore.end(); I2 != E2; ++I2) {
+ ExplodedNode *predNew = *I2;
+ const GRState *stateNew = predNew->getState();
+ // Check for 'void' return type if we have a bogus function prototype.
+ SVal Res = UnknownVal();
+ QualType T = CE->getType();
+ if (!T->isVoidType())
+ Res = Engine.getSValBuilder().makeTruthVal(true, T);
+ C.generateNode(stateNew->BindExpr(CE, Res), predNew);
+ }
+ }
+
+ // Were they not equal?
+ if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) {
+ // Check for 'void' return type if we have a bogus function prototype.
+ SVal Res = UnknownVal();
+ QualType T = CE->getType();
+ if (!T->isVoidType())
+ Res = Engine.getSValBuilder().makeTruthVal(false, CE->getType());
+ C.generateNode(stateNotEqual->BindExpr(CE, Res), N);
+ }
+ }
+
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
new file mode 100644
index 0000000..7d440ab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -0,0 +1,100 @@
+//== ObjCAtSyncChecker.cpp - nil mutex checker for @synchronized -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ObjCAtSyncChecker, a builtin check that checks for null pointers
+// used as mutexes for @synchronized.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ObjCAtSyncChecker : public CheckerVisitor<ObjCAtSyncChecker> {
+ BuiltinBug *BT_null;
+ BuiltinBug *BT_undef;
+public:
+ ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
+ const ObjCAtSynchronizedStmt *S);
+};
+} // end anonymous namespace
+
+static void RegisterObjCAtSyncChecker(ExprEngine &Eng) {
+ // @synchronized is an Objective-C 2 feature.
+ if (Eng.getContext().getLangOptions().ObjC2)
+ Eng.registerCheck(new ObjCAtSyncChecker());
+}
+
+void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterObjCAtSyncChecker);
+}
+
+void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
+ const ObjCAtSynchronizedStmt *S) {
+
+ const Expr *Ex = S->getSynchExpr();
+ const GRState *state = C.getState();
+ SVal V = state->getSVal(Ex);
+
+ // Uninitialized value used for the mutex?
+ if (isa<UndefinedVal>(V)) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Uninitialized value used as mutex "
+ "for @synchronized");
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ C.EmitReport(report);
+ }
+ return;
+ }
+
+ if (V.isUnknown())
+ return;
+
+ // Check for null mutexes.
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
+
+ if (nullState) {
+ if (!notNullState) {
+ // Generate an error node. This isn't a sink since
+ // a null mutex just means no synchronization occurs.
+ if (ExplodedNode *N = C.generateNode(nullState)) {
+ if (!BT_null)
+ BT_null = new BuiltinBug("Nil value used as mutex for @synchronized() "
+ "(no synchronization will occur)");
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_null, BT_null->getDescription(), N);
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ Ex);
+
+ C.EmitReport(report);
+ return;
+ }
+ }
+ // Don't add a transition for 'nullState'. If the value is
+ // under-constrained to be null or non-null, assume it is non-null
+ // afterwards.
+ }
+
+ if (notNullState)
+ C.addTransition(notNullState);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
new file mode 100644
index 0000000..4f247ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -0,0 +1,356 @@
+//== ObjCSelfInitChecker.cpp - Checker for 'self' initialization -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines ObjCSelfInitChecker, a builtin check that checks for uses of
+// 'self' before proper initialization.
+//
+//===----------------------------------------------------------------------===//
+
+// This checks initialization methods to verify that they assign 'self' to the
+// result of an initialization call (e.g. [super init], or [self initWith..])
+// before using 'self' or any instance variable.
+//
+// To perform the required checking, values are tagged wih flags that indicate
+// 1) if the object is the one pointed to by 'self', and 2) if the object
+// is the result of an initializer (e.g. [super init]).
+//
+// Uses of an object that is true for 1) but not 2) trigger a diagnostic.
+// The uses that are currently checked are:
+// - Using instance variables.
+// - Returning the object.
+//
+// Note that we don't check for an invalid 'self' that is the receiver of an
+// obj-c message expression to cut down false positives where logging functions
+// get information from self (like its class) or doing "invalidation" on self
+// when the initialization fails.
+//
+// Because the object that 'self' points to gets invalidated when a call
+// receives a reference to 'self', the checker keeps track and passes the flags
+// for 1) and 2) to the new object that 'self' points to after the call.
+//
+// FIXME (rdar://7937506): In the case of:
+// [super init];
+// return self;
+// Have an extra PathDiagnosticPiece in the path that says "called [super init],
+// but didn't assign the result to self."
+
+//===----------------------------------------------------------------------===//
+
+// FIXME: Somehow stick the link to Apple's documentation about initializing
+// objects in the diagnostics.
+// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/AST/ParentMap.h"
+
+using namespace clang;
+using namespace ento;
+
+static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND);
+static bool isInitializationMethod(const ObjCMethodDecl *MD);
+static bool isInitMessage(const ObjCMessage &msg);
+static bool isSelfVar(SVal location, CheckerContext &C);
+
+namespace {
+enum SelfFlagEnum {
+ /// \brief No flag set.
+ SelfFlag_None = 0x0,
+ /// \brief Value came from 'self'.
+ SelfFlag_Self = 0x1,
+ /// \brief Value came from the result of an initializer (e.g. [super init]).
+ SelfFlag_InitRes = 0x2
+};
+}
+
+namespace {
+class ObjCSelfInitChecker : public CheckerVisitor<ObjCSelfInitChecker> {
+ /// \brief A call receiving a reference to 'self' invalidates the object that
+ /// 'self' contains. This field keeps the "self flags" assigned to the 'self'
+ /// object before the call and assign them to the new object that 'self'
+ /// points to after the call.
+ SelfFlagEnum preCallSelfFlags;
+
+public:
+ static void *getTag() { static int tag = 0; return &tag; }
+ void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E);
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+ void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE);
+ void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE);
+ virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
+ bool isLoad);
+};
+} // end anonymous namespace
+
+static void RegisterObjCSelfInitChecker(ExprEngine &Eng) {
+ if (Eng.getContext().getLangOptions().ObjC1)
+ Eng.registerCheck(new ObjCSelfInitChecker());
+}
+
+void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterObjCSelfInitChecker);
+}
+
+namespace {
+
+class InitSelfBug : public BugType {
+ const std::string desc;
+public:
+ InitSelfBug() : BugType("missing \"self = [(super or self) init...]\"",
+ "missing \"self = [(super or self) init...]\"") {}
+};
+
+} // end anonymous namespace
+
+typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag;
+namespace { struct CalledInit {}; }
+
+namespace clang {
+namespace ento {
+ template<>
+ struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> {
+ static void* GDMIndex() {
+ static int index = 0;
+ return &index;
+ }
+ };
+ template <>
+ struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+ };
+}
+}
+
+static SelfFlagEnum getSelfFlags(SVal val, const GRState *state) {
+ if (SymbolRef sym = val.getAsSymbol())
+ if (const unsigned *attachedFlags = state->get<SelfFlag>(sym))
+ return (SelfFlagEnum)*attachedFlags;
+ return SelfFlag_None;
+}
+
+static SelfFlagEnum getSelfFlags(SVal val, CheckerContext &C) {
+ return getSelfFlags(val, C.getState());
+}
+
+static void addSelfFlag(const GRState *state, SVal val,
+ SelfFlagEnum flag, CheckerContext &C) {
+ // We tag the symbol that the SVal wraps.
+ if (SymbolRef sym = val.getAsSymbol())
+ C.addTransition(state->set<SelfFlag>(sym, getSelfFlags(val, C) | flag));
+}
+
+static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) {
+ return getSelfFlags(val, C) & flag;
+}
+
+/// \brief Returns true of the value of the expression is the object that 'self'
+/// points to and is an object that did not come from the result of calling
+/// an initializer.
+static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
+ SVal exprVal = C.getState()->getSVal(E);
+ if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
+ return false; // value did not come from 'self'.
+ if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
+ return false; // 'self' is properly initialized.
+
+ return true;
+}
+
+static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
+ const char *errorStr) {
+ if (!E)
+ return;
+
+ if (!C.getState()->get<CalledInit>())
+ return;
+
+ if (!isInvalidSelf(E, C))
+ return;
+
+ // Generate an error node.
+ ExplodedNode *N = C.generateSink();
+ if (!N)
+ return;
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*new InitSelfBug(), errorStr, N);
+ C.EmitReport(report);
+}
+
+void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
+ ObjCMessage msg) {
+ // When encountering a message that does initialization (init rule),
+ // tag the return value so that we know later on that if self has this value
+ // then it is properly initialized.
+
+ // FIXME: A callback should disable checkers at the start of functions.
+ if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+ C.getCurrentAnalysisContext()->getDecl())))
+ return;
+
+ if (isInitMessage(msg)) {
+ // Tag the return value as the result of an initializer.
+ const GRState *state = C.getState();
+
+ // FIXME this really should be context sensitive, where we record
+ // the current stack frame (for IPA). Also, we need to clean this
+ // value out when we return from this method.
+ state = state->set<CalledInit>(true);
+
+ SVal V = state->getSVal(msg.getOriginExpr());
+ addSelfFlag(state, V, SelfFlag_InitRes, C);
+ return;
+ }
+
+ // We don't check for an invalid 'self' in an obj-c message expression to cut
+ // down false positives where logging functions get information from self
+ // (like its class) or doing "invalidation" on self when the initialization
+ // fails.
+}
+
+void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
+ const ObjCIvarRefExpr *E) {
+ // FIXME: A callback should disable checkers at the start of functions.
+ if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+ C.getCurrentAnalysisContext()->getDecl())))
+ return;
+
+ checkForInvalidSelf(E->getBase(), C,
+ "Instance variable used while 'self' is not set to the result of "
+ "'[(super or self) init...]'");
+}
+
+void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *S) {
+ // FIXME: A callback should disable checkers at the start of functions.
+ if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
+ C.getCurrentAnalysisContext()->getDecl())))
+ return;
+
+ checkForInvalidSelf(S->getRetValue(), C,
+ "Returning 'self' while it is not set to the result of "
+ "'[(super or self) init...]'");
+}
+
+// When a call receives a reference to 'self', [Pre/Post]VisitGenericCall pass
+// the SelfFlags from the object 'self' point to before the call, to the new
+// object after the call. This is to avoid invalidation of 'self' by logging
+// functions.
+// Another common pattern in classes with multiple initializers is to put the
+// subclass's common initialization bits into a static function that receives
+// the value of 'self', e.g:
+// @code
+// if (!(self = [super init]))
+// return nil;
+// if (!(self = _commonInit(self)))
+// return nil;
+// @endcode
+// Until we can use inter-procedural analysis, in such a call, transfer the
+// SelfFlags to the result of the call.
+
+void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ for (CallExpr::const_arg_iterator
+ I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
+ SVal argV = state->getSVal(*I);
+ if (isSelfVar(argV, C)) {
+ preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ return;
+ } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
+ preCallSelfFlags = getSelfFlags(argV, C);
+ return;
+ }
+ }
+}
+
+void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ for (CallExpr::const_arg_iterator
+ I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
+ SVal argV = state->getSVal(*I);
+ if (isSelfVar(argV, C)) {
+ addSelfFlag(state, state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C);
+ return;
+ } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
+ addSelfFlag(state, state->getSVal(CE), preCallSelfFlags, C);
+ return;
+ }
+ }
+}
+
+void ObjCSelfInitChecker::visitLocation(CheckerContext &C, const Stmt *S,
+ SVal location, bool isLoad) {
+ // Tag the result of a load from 'self' so that we can easily know that the
+ // value is the object that 'self' points to.
+ const GRState *state = C.getState();
+ if (isSelfVar(location, C))
+ addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C);
+}
+
+// FIXME: A callback should disable checkers at the start of functions.
+static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) {
+ if (!ND)
+ return false;
+
+ const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND);
+ if (!MD)
+ return false;
+ if (!isInitializationMethod(MD))
+ return false;
+
+ // self = [super init] applies only to NSObject subclasses.
+ // For instance, NSProxy doesn't implement -init.
+ ASTContext& Ctx = MD->getASTContext();
+ IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
+ ObjCInterfaceDecl* ID = MD->getClassInterface()->getSuperClass();
+ for ( ; ID ; ID = ID->getSuperClass()) {
+ IdentifierInfo *II = ID->getIdentifier();
+
+ if (II == NSObjectII)
+ break;
+ }
+ if (!ID)
+ return false;
+
+ return true;
+}
+
+/// \brief Returns true if the location is 'self'.
+static bool isSelfVar(SVal location, CheckerContext &C) {
+ AnalysisContext *analCtx = C.getCurrentAnalysisContext();
+ if (!analCtx->getSelfDecl())
+ return false;
+ if (!isa<loc::MemRegionVal>(location))
+ return false;
+
+ loc::MemRegionVal MRV = cast<loc::MemRegionVal>(location);
+ if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.getRegion()))
+ return (DR->getDecl() == analCtx->getSelfDecl());
+
+ return false;
+}
+
+static bool isInitializationMethod(const ObjCMethodDecl *MD) {
+ // Init methods with prefix like '-(id)_init' are private and the requirements
+ // are less strict so we don't check those.
+ return MD->isInstanceMethod() &&
+ cocoa::deriveNamingConvention(MD->getSelector(),
+ /*ignorePrefix=*/false) == cocoa::InitRule;
+}
+
+static bool isInitMessage(const ObjCMessage &msg) {
+ return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
new file mode 100644
index 0000000..6e92498
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
@@ -0,0 +1,184 @@
+//==- ObjCUnusedIVarsChecker.cpp - Check for unused ivars --------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a CheckObjCUnusedIvars, a checker that
+// analyzes an Objective-C class's interface/implementation to determine if it
+// has any ivars that are never accessed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+using namespace ento;
+
+enum IVarState { Unused, Used };
+typedef llvm::DenseMap<const ObjCIvarDecl*,IVarState> IvarUsageMap;
+
+static void Scan(IvarUsageMap& M, const Stmt* S) {
+ if (!S)
+ return;
+
+ if (const ObjCIvarRefExpr *Ex = dyn_cast<ObjCIvarRefExpr>(S)) {
+ const ObjCIvarDecl *D = Ex->getDecl();
+ IvarUsageMap::iterator I = M.find(D);
+ if (I != M.end())
+ I->second = Used;
+ return;
+ }
+
+ // Blocks can reference an instance variable of a class.
+ if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+ Scan(M, BE->getBody());
+ return;
+ }
+
+ for (Stmt::const_child_iterator I=S->child_begin(),E=S->child_end(); I!=E;++I)
+ Scan(M, *I);
+}
+
+static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) {
+ if (!D)
+ return;
+
+ const ObjCIvarDecl* ID = D->getPropertyIvarDecl();
+
+ if (!ID)
+ return;
+
+ IvarUsageMap::iterator I = M.find(ID);
+ if (I != M.end())
+ I->second = Used;
+}
+
+static void Scan(IvarUsageMap& M, const ObjCContainerDecl* D) {
+ // Scan the methods for accesses.
+ for (ObjCContainerDecl::instmeth_iterator I = D->instmeth_begin(),
+ E = D->instmeth_end(); I!=E; ++I)
+ Scan(M, (*I)->getBody());
+
+ if (const ObjCImplementationDecl *ID = dyn_cast<ObjCImplementationDecl>(D)) {
+ // Scan for @synthesized property methods that act as setters/getters
+ // to an ivar.
+ for (ObjCImplementationDecl::propimpl_iterator I = ID->propimpl_begin(),
+ E = ID->propimpl_end(); I!=E; ++I)
+ Scan(M, *I);
+
+ // Scan the associated categories as well.
+ for (const ObjCCategoryDecl *CD =
+ ID->getClassInterface()->getCategoryList(); CD ;
+ CD = CD->getNextClassCategory()) {
+ if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
+ Scan(M, CID);
+ }
+ }
+}
+
+static void Scan(IvarUsageMap &M, const DeclContext *C, const FileID FID,
+ SourceManager &SM) {
+ for (DeclContext::decl_iterator I=C->decls_begin(), E=C->decls_end();
+ I!=E; ++I)
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ SourceLocation L = FD->getLocStart();
+ if (SM.getFileID(L) == FID)
+ Scan(M, FD->getBody());
+ }
+}
+
+static void checkObjCUnusedIvar(const ObjCImplementationDecl *D,
+ BugReporter &BR) {
+
+ const ObjCInterfaceDecl* ID = D->getClassInterface();
+ IvarUsageMap M;
+
+ // Iterate over the ivars.
+ for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(),
+ E=ID->ivar_end(); I!=E; ++I) {
+
+ const ObjCIvarDecl* ID = *I;
+
+ // Ignore ivars that...
+ // (a) aren't private
+ // (b) explicitly marked unused
+ // (c) are iboutlets
+ // (d) are unnamed bitfields
+ if (ID->getAccessControl() != ObjCIvarDecl::Private ||
+ ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>() ||
+ ID->getAttr<IBOutletCollectionAttr>() ||
+ ID->isUnnamedBitfield())
+ continue;
+
+ M[ID] = Unused;
+ }
+
+ if (M.empty())
+ return;
+
+ // Now scan the implementation declaration.
+ Scan(M, D);
+
+ // Any potentially unused ivars?
+ bool hasUnused = false;
+ for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
+ if (I->second == Unused) {
+ hasUnused = true;
+ break;
+ }
+
+ if (!hasUnused)
+ return;
+
+ // We found some potentially unused ivars. Scan the entire translation unit
+ // for functions inside the @implementation that reference these ivars.
+ // FIXME: In the future hopefully we can just use the lexical DeclContext
+ // to go from the ObjCImplementationDecl to the lexically "nested"
+ // C functions.
+ SourceManager &SM = BR.getSourceManager();
+ Scan(M, D->getDeclContext(), SM.getFileID(D->getLocation()), SM);
+
+ // Find ivars that are unused.
+ for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
+ if (I->second == Unused) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Instance variable '" << I->first << "' in class '" << ID
+ << "' is never used by the methods in its @implementation "
+ "(although it may be used by category methods).";
+
+ BR.EmitBasicReport("Unused instance variable", "Optimization",
+ os.str(), I->first->getLocation());
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// ObjCUnusedIvarsChecker
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCUnusedIvarsChecker : public CheckerV2<
+ check::ASTDecl<ObjCImplementationDecl> > {
+public:
+ void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& mgr,
+ BugReporter &BR) const {
+ checkObjCUnusedIvar(D, BR);
+ }
+};
+}
+
+void ento::registerObjCUnusedIvarsChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCUnusedIvarsChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
new file mode 100644
index 0000000..741e48b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -0,0 +1,77 @@
+//=== PointerArithChecker.cpp - Pointer arithmetic checker -----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerArithChecker, a builtin checker that checks for
+// pointer arithmetic on locations other than array elements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PointerArithChecker
+ : public CheckerVisitor<PointerArithChecker> {
+ BuiltinBug *BT;
+public:
+ PointerArithChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *PointerArithChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
+ return;
+
+ const GRState *state = C.getState();
+ SVal LV = state->getSVal(B->getLHS());
+ SVal RV = state->getSVal(B->getRHS());
+
+ const MemRegion *LR = LV.getAsRegion();
+
+ if (!LR || !RV.isConstant())
+ return;
+
+ // If pointer arithmetic is done on variables of non-array type, this often
+ // means behavior rely on memory organization, which is dangerous.
+ if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
+ isa<CompoundLiteralRegion>(LR)) {
+
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT)
+ BT = new BuiltinBug("Dangerous pointer arithmetic",
+ "Pointer arithmetic done on non-array variables "
+ "means reliance on memory layout, which is "
+ "dangerous.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getSourceRange());
+ C.EmitReport(R);
+ }
+ }
+}
+
+static void RegisterPointerArithChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new PointerArithChecker());
+}
+
+void ento::registerPointerArithChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterPointerArithChecker);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
new file mode 100644
index 0000000..f28fe9a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -0,0 +1,84 @@
+//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerSubChecker, a builtin checker that checks for
+// pointer subtractions on two pointers pointing to different memory chunks.
+// This check corresponds to CWE-469.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PointerSubChecker
+ : public CheckerVisitor<PointerSubChecker> {
+ BuiltinBug *BT;
+public:
+ PointerSubChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *PointerSubChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ // When doing pointer subtraction, if the two pointers do not point to the
+ // same memory chunk, emit a warning.
+ if (B->getOpcode() != BO_Sub)
+ return;
+
+ const GRState *state = C.getState();
+ SVal LV = state->getSVal(B->getLHS());
+ SVal RV = state->getSVal(B->getRHS());
+
+ const MemRegion *LR = LV.getAsRegion();
+ const MemRegion *RR = RV.getAsRegion();
+
+ if (!(LR && RR))
+ return;
+
+ const MemRegion *BaseLR = LR->getBaseRegion();
+ const MemRegion *BaseRR = RR->getBaseRegion();
+
+ if (BaseLR == BaseRR)
+ return;
+
+ // Allow arithmetic on different symbolic regions.
+ if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
+ return;
+
+ if (ExplodedNode *N = C.generateNode()) {
+ if (!BT)
+ BT = new BuiltinBug("Pointer subtraction",
+ "Subtraction of two pointers that do not point to "
+ "the same memory chunk may cause incorrect result.");
+ RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
+ R->addRange(B->getSourceRange());
+ C.EmitReport(R);
+ }
+}
+
+static void RegisterPointerSubChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new PointerSubChecker());
+}
+
+void ento::registerPointerSubChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterPointerSubChecker);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
new file mode 100644
index 0000000..34c095f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -0,0 +1,152 @@
+//===--- PthreadLockChecker.h - Undefined arguments checker ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines PthreadLockChecker, a simple lock -> unlock checker. Eventually
+// this shouldn't be registered with ExprEngineInternalChecks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "llvm/ADT/ImmutableSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PthreadLockChecker
+ : public CheckerVisitor<PthreadLockChecker> {
+ BugType *BT;
+public:
+ PthreadLockChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+
+ void AcquireLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock, bool isTryLock);
+
+ void ReleaseLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock);
+
+};
+} // end anonymous namespace
+
+// GDM Entry for tracking lock state.
+namespace { class LockSet {}; }
+namespace clang {
+namespace ento {
+template <> struct GRStateTrait<LockSet> :
+ public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
+ static void* GDMIndex() { return PthreadLockChecker::getTag(); }
+};
+} // end GR namespace
+} // end clang namespace
+
+static void RegisterPthreadLockChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new PthreadLockChecker());
+}
+
+void ento::registerPthreadLockChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterPthreadLockChecker);
+}
+
+
+void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
+ const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ const FunctionTextRegion *R =
+ dyn_cast_or_null<FunctionTextRegion>(state->getSVal(Callee).getAsRegion());
+
+ if (!R)
+ return;
+
+ IdentifierInfo *II = R->getDecl()->getIdentifier();
+ if (!II) // if no identifier, not a simple C function
+ return;
+ llvm::StringRef FName = II->getName();
+
+ if (FName == "pthread_mutex_lock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false);
+ }
+ else if (FName == "pthread_mutex_trylock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true);
+ }
+ else if (FName == "pthread_mutex_unlock") {
+ if (CE->getNumArgs() != 1)
+ return;
+ ReleaseLock(C, CE, state->getSVal(CE->getArg(0)));
+ }
+}
+
+void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock, bool isTryLock) {
+
+ const MemRegion *lockR = lock.getAsRegion();
+ if (!lockR)
+ return;
+
+ const GRState *state = C.getState();
+
+ SVal X = state->getSVal(CE);
+ if (X.isUnknownOrUndef())
+ return;
+
+ DefinedSVal retVal = cast<DefinedSVal>(X);
+ const GRState *lockSucc = state;
+
+ if (isTryLock) {
+ // Bifurcate the state, and allow a mode where the lock acquisition fails.
+ const GRState *lockFail;
+ llvm::tie(lockFail, lockSucc) = state->assume(retVal);
+ assert(lockFail && lockSucc);
+ C.addTransition(C.generateNode(CE, lockFail));
+ }
+ else {
+ // Assume that the return value was 0.
+ lockSucc = state->assume(retVal, false);
+ assert(lockSucc);
+ }
+
+ // Record that the lock was acquired.
+ lockSucc = lockSucc->add<LockSet>(lockR);
+
+ C.addTransition(lockSucc != state ? C.generateNode(CE, lockSucc) :
+ C.getPredecessor());
+}
+
+void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
+ SVal lock) {
+
+ const MemRegion *lockR = lock.getAsRegion();
+ if (!lockR)
+ return;
+
+ const GRState *state = C.getState();
+
+ // Record that the lock was released.
+ // FIXME: Handle unlocking locks that were never acquired. This may
+ // require IPA for wrappers.
+ const GRState *unlockState = state->remove<LockSet>(lockR);
+
+ if (state == unlockState)
+ return;
+
+ C.addTransition(C.generateNode(CE, unlockState));
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
new file mode 100644
index 0000000..838a00f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -0,0 +1,95 @@
+//== ReturnPointerRangeChecker.cpp ------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ReturnPointerRangeChecker, which is a path-sensitive check
+// which looks for an out-of-bound pointer being returned to callers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ReturnPointerRangeChecker :
+ public CheckerVisitor<ReturnPointerRangeChecker> {
+ BuiltinBug *BT;
+public:
+ ReturnPointerRangeChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void ento::RegisterReturnPointerRangeChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new ReturnPointerRangeChecker());
+}
+
+void *ReturnPointerRangeChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+ const GRState *state = C.getState();
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ SVal V = state->getSVal(RetE);
+ const MemRegion *R = V.getAsRegion();
+
+ const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
+ if (!ER)
+ return;
+
+ DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+ // Zero index is always in bound, this also passes ElementRegions created for
+ // pointer casts.
+ if (Idx.isZeroConstant())
+ return;
+ // FIXME: All of this out-of-bounds checking should eventually be refactored
+ // into a common place.
+
+ DefinedOrUnknownSVal NumElements
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+ ER->getValueType());
+
+ const GRState *StInBound = state->assumeInBound(Idx, NumElements, true);
+ const GRState *StOutBound = state->assumeInBound(Idx, NumElements, false);
+ if (StOutBound && !StInBound) {
+ ExplodedNode *N = C.generateSink(StOutBound);
+
+ if (!N)
+ return;
+
+ // FIXME: This bug correspond to CWE-466. Eventually we should have bug
+ // types explicitly reference such exploit categories (when applicable).
+ if (!BT)
+ BT = new BuiltinBug("Return of pointer value outside of expected range",
+ "Returned pointer value points outside the original object "
+ "(potential buffer overflow)");
+
+ // FIXME: It would be nice to eventually make this diagnostic more clear,
+ // e.g., by referencing the original declaration or by saying *why* this
+ // reference is outside the range.
+
+ // Generate a report for this bug.
+ RangedBugReport *report =
+ new RangedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(RetE->getSourceRange());
+ C.EmitReport(report);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
new file mode 100644
index 0000000..555eaf4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -0,0 +1,69 @@
+//== ReturnUndefChecker.cpp -------------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ReturnUndefChecker, which is a path-sensitive
+// check which looks for undefined or garbage values being returned to the
+// caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ReturnUndefChecker :
+ public CheckerVisitor<ReturnUndefChecker> {
+ BuiltinBug *BT;
+public:
+ ReturnUndefChecker() : BT(0) {}
+ static void *getTag();
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void ento::RegisterReturnUndefChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new ReturnUndefChecker());
+}
+
+void *ReturnUndefChecker::getTag() {
+ static int x = 0; return &x;
+}
+
+void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ if (!C.getState()->getSVal(RetE).isUndef())
+ return;
+
+ ExplodedNode *N = C.generateSink();
+
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Garbage return value",
+ "Undefined or garbage value returned to caller");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT, BT->getDescription(), N);
+
+ report->addRange(RetE->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
+
+ C.EmitReport(report);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
new file mode 100644
index 0000000..363f404
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
@@ -0,0 +1,210 @@
+//=== StackAddrLeakChecker.cpp ------------------------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines stack address leak checker, which checks if an invalid
+// stack address is stored into a global or heap location. See CERT DCL30-C.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
+using namespace clang;
+using namespace ento;
+
+namespace {
+class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> {
+ BuiltinBug *BT_stackleak;
+ BuiltinBug *BT_returnstack;
+
+public:
+ StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {}
+ static void *getTag() {
+ static int x;
+ return &x;
+ }
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+ void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
+private:
+ void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
+ SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
+ SourceManager &SM);
+};
+}
+
+static void RegisterStackAddrLeakChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new StackAddrLeakChecker());
+}
+
+void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterStackAddrLeakChecker);
+}
+
+SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
+ const MemRegion *R,
+ SourceManager &SM) {
+ // Get the base region, stripping away fields and elements.
+ R = R->getBaseRegion();
+ SourceRange range;
+ os << "Address of ";
+
+ // Check if the region is a compound literal.
+ if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
+ const CompoundLiteralExpr* CL = CR->getLiteralExpr();
+ os << "stack memory associated with a compound literal "
+ "declared on line "
+ << SM.getInstantiationLineNumber(CL->getLocStart())
+ << " returned to caller";
+ range = CL->getSourceRange();
+ }
+ else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
+ const Expr* ARE = AR->getExpr();
+ SourceLocation L = ARE->getLocStart();
+ range = ARE->getSourceRange();
+ os << "stack memory allocated by call to alloca() on line "
+ << SM.getInstantiationLineNumber(L);
+ }
+ else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
+ const BlockDecl *BD = BR->getCodeRegion()->getDecl();
+ SourceLocation L = BD->getLocStart();
+ range = BD->getSourceRange();
+ os << "stack-allocated block declared on line "
+ << SM.getInstantiationLineNumber(L);
+ }
+ else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << "stack memory associated with local variable '"
+ << VR->getString() << '\'';
+ range = VR->getDecl()->getSourceRange();
+ }
+ else {
+ assert(false && "Invalid region in ReturnStackAddressChecker.");
+ }
+
+ return range;
+}
+
+void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) {
+ ExplodedNode *N = C.generateSink();
+
+ if (!N)
+ return;
+
+ if (!BT_returnstack)
+ BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory");
+
+ // Generate a report for this bug.
+ llvm::SmallString<512> buf;
+ llvm::raw_svector_ostream os(buf);
+ SourceRange range = GenName(os, R, C.getSourceManager());
+ os << " returned to caller";
+ RangedBugReport *report = new RangedBugReport(*BT_returnstack, os.str(), N);
+ report->addRange(RetE->getSourceRange());
+ if (range.isValid())
+ report->addRange(range);
+
+ C.EmitReport(report);
+}
+
+void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
+ const ReturnStmt *RS) {
+
+ const Expr *RetE = RS->getRetValue();
+ if (!RetE)
+ return;
+
+ SVal V = C.getState()->getSVal(RetE);
+ const MemRegion *R = V.getAsRegion();
+
+ if (!R || !R->hasStackStorage())
+ return;
+
+ if (R->hasStackStorage()) {
+ EmitStackError(C, R, RetE);
+ return;
+ }
+}
+
+void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
+ ExprEngine &Eng) {
+
+ const GRState *state = B.getState();
+
+ // Iterate over all bindings to global variables and see if it contains
+ // a memory region in the stack space.
+ class CallBack : public StoreManager::BindingsHandler {
+ private:
+ const StackFrameContext *CurSFC;
+ public:
+ llvm::SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V;
+
+ CallBack(const LocationContext *LCtx)
+ : CurSFC(LCtx->getCurrentStackFrame()) {}
+
+ bool HandleBinding(StoreManager &SMgr, Store store,
+ const MemRegion *region, SVal val) {
+
+ if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
+ return true;
+
+ const MemRegion *vR = val.getAsRegion();
+ if (!vR)
+ return true;
+
+ if (const StackSpaceRegion *SSR =
+ dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
+ // If the global variable holds a location in the current stack frame,
+ // record the binding to emit a warning.
+ if (SSR->getStackFrame() == CurSFC)
+ V.push_back(std::make_pair(region, vR));
+ }
+
+ return true;
+ }
+ };
+
+ CallBack cb(B.getPredecessor()->getLocationContext());
+ state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
+
+ if (cb.V.empty())
+ return;
+
+ // Generate an error node.
+ ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ if (!N)
+ return;
+
+ if (!BT_stackleak)
+ BT_stackleak =
+ new BuiltinBug("Stack address stored into global variable",
+ "Stack address was saved into a global variable. "
+ "This is dangerous because the address will become "
+ "invalid after returning from the function");
+
+ for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
+ // Generate a report for this bug.
+ llvm::SmallString<512> buf;
+ llvm::raw_svector_ostream os(buf);
+ SourceRange range = GenName(os, cb.V[i].second,
+ Eng.getContext().getSourceManager());
+ os << " is still referred to by the global variable '";
+ const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion());
+ os << VR->getDecl()->getNameAsString()
+ << "' upon returning to the caller. This will be a dangling reference";
+ RangedBugReport *report = new RangedBugReport(*BT_stackleak, os.str(), N);
+ if (range.isValid())
+ report->addRange(range);
+
+ Eng.getBugReporter().EmitReport(report);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
new file mode 100644
index 0000000..2655be2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -0,0 +1,470 @@
+//===-- StreamChecker.cpp -----------------------------------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines checkers that model and check stream handling functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+struct StreamState {
+ enum Kind { Opened, Closed, OpenFailed, Escaped } K;
+ const Stmt *S;
+
+ StreamState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+ bool isOpened() const { return K == Opened; }
+ bool isClosed() const { return K == Closed; }
+ //bool isOpenFailed() const { return K == OpenFailed; }
+ //bool isEscaped() const { return K == Escaped; }
+
+ bool operator==(const StreamState &X) const {
+ return K == X.K && S == X.S;
+ }
+
+ static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
+ static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
+ static StreamState getOpenFailed(const Stmt *s) {
+ return StreamState(OpenFailed, s);
+ }
+ static StreamState getEscaped(const Stmt *s) {
+ return StreamState(Escaped, s);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(K);
+ ID.AddPointer(S);
+ }
+};
+
+class StreamChecker : public CheckerVisitor<StreamChecker> {
+ IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite,
+ *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
+ *II_clearerr, *II_feof, *II_ferror, *II_fileno;
+ BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;
+
+public:
+ StreamChecker()
+ : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0),
+ II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0),
+ II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0),
+ BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0),
+ BT_ResourceLeak(0) {}
+
+ static void *getTag() {
+ static int x;
+ return &x;
+ }
+
+ virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
+ void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
+ void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+
+private:
+ void Fopen(CheckerContext &C, const CallExpr *CE);
+ void Tmpfile(CheckerContext &C, const CallExpr *CE);
+ void Fclose(CheckerContext &C, const CallExpr *CE);
+ void Fread(CheckerContext &C, const CallExpr *CE);
+ void Fwrite(CheckerContext &C, const CallExpr *CE);
+ void Fseek(CheckerContext &C, const CallExpr *CE);
+ void Ftell(CheckerContext &C, const CallExpr *CE);
+ void Rewind(CheckerContext &C, const CallExpr *CE);
+ void Fgetpos(CheckerContext &C, const CallExpr *CE);
+ void Fsetpos(CheckerContext &C, const CallExpr *CE);
+ void Clearerr(CheckerContext &C, const CallExpr *CE);
+ void Feof(CheckerContext &C, const CallExpr *CE);
+ void Ferror(CheckerContext &C, const CallExpr *CE);
+ void Fileno(CheckerContext &C, const CallExpr *CE);
+
+ void OpenFileAux(CheckerContext &C, const CallExpr *CE);
+
+ const GRState *CheckNullStream(SVal SV, const GRState *state,
+ CheckerContext &C);
+ const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state,
+ CheckerContext &C);
+};
+
+} // end anonymous namespace
+
+namespace clang {
+namespace ento {
+ template <>
+ struct GRStateTrait<StreamState>
+ : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
+ static void *GDMIndex() { return StreamChecker::getTag(); }
+ };
+}
+}
+
+static void RegisterStreamChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new StreamChecker());
+}
+
+void ento::registerStreamChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterStreamChecker);
+}
+
+bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ ASTContext &Ctx = C.getASTContext();
+ if (!II_fopen)
+ II_fopen = &Ctx.Idents.get("fopen");
+ if (!II_tmpfile)
+ II_tmpfile = &Ctx.Idents.get("tmpfile");
+ if (!II_fclose)
+ II_fclose = &Ctx.Idents.get("fclose");
+ if (!II_fread)
+ II_fread = &Ctx.Idents.get("fread");
+ if (!II_fwrite)
+ II_fwrite = &Ctx.Idents.get("fwrite");
+ if (!II_fseek)
+ II_fseek = &Ctx.Idents.get("fseek");
+ if (!II_ftell)
+ II_ftell = &Ctx.Idents.get("ftell");
+ if (!II_rewind)
+ II_rewind = &Ctx.Idents.get("rewind");
+ if (!II_fgetpos)
+ II_fgetpos = &Ctx.Idents.get("fgetpos");
+ if (!II_fsetpos)
+ II_fsetpos = &Ctx.Idents.get("fsetpos");
+ if (!II_clearerr)
+ II_clearerr = &Ctx.Idents.get("clearerr");
+ if (!II_feof)
+ II_feof = &Ctx.Idents.get("feof");
+ if (!II_ferror)
+ II_ferror = &Ctx.Idents.get("ferror");
+ if (!II_fileno)
+ II_fileno = &Ctx.Idents.get("fileno");
+
+ if (FD->getIdentifier() == II_fopen) {
+ Fopen(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_tmpfile) {
+ Tmpfile(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fclose) {
+ Fclose(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fread) {
+ Fread(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fwrite) {
+ Fwrite(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fseek) {
+ Fseek(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_ftell) {
+ Ftell(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_rewind) {
+ Rewind(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fgetpos) {
+ Fgetpos(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fsetpos) {
+ Fsetpos(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_clearerr) {
+ Clearerr(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_feof) {
+ Feof(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_ferror) {
+ Ferror(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fileno) {
+ Fileno(C, CE);
+ return true;
+ }
+
+ return false;
+}
+
+void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
+ OpenFileAux(C, CE);
+}
+
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
+ OpenFileAux(C, CE);
+}
+
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ DefinedSVal RetVal =
+ cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, Count));
+ state = state->BindExpr(CE, RetVal);
+
+ ConstraintManager &CM = C.getConstraintManager();
+ // Bifurcate the state into two: one with a valid FILE* pointer, the other
+ // with a NULL.
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal);
+
+ if (SymbolRef Sym = RetVal.getAsSymbol()) {
+ // if RetVal is not NULL, set the symbol's state to Opened.
+ stateNotNull =
+ stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE));
+ stateNull =
+ stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE));
+
+ C.addTransition(stateNotNull);
+ C.addTransition(stateNull);
+ }
+}
+
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = CheckDoubleClose(CE, C.getState(), C);
+ if (state)
+ C.addTransition(state);
+}
+
+void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+ return;
+}
+
+void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+ return;
+}
+
+void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
+ return;
+ // Check the legality of the 'whence' argument of 'fseek'.
+ SVal Whence = state->getSVal(CE->getArg(2));
+ const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
+
+ if (!CI)
+ return;
+
+ int64_t x = CI->getValue().getSExtValue();
+ if (x >= 0 && x <= 2)
+ return;
+
+ if (ExplodedNode *N = C.generateNode(state)) {
+ if (!BT_illegalwhence)
+ BT_illegalwhence = new BuiltinBug("Illegal whence argument",
+ "The whence argument to fseek() should be "
+ "SEEK_SET, SEEK_END, or SEEK_CUR.");
+ BugReport *R = new BugReport(*BT_illegalwhence,
+ BT_illegalwhence->getDescription(), N);
+ C.EmitReport(R);
+ }
+}
+
+void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
+ CheckerContext &C) {
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
+ if (!DV)
+ return 0;
+
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
+
+ if (!stateNotNull && stateNull) {
+ if (ExplodedNode *N = C.generateSink(stateNull)) {
+ if (!BT_nullfp)
+ BT_nullfp = new BuiltinBug("NULL stream pointer",
+ "Stream pointer might be NULL.");
+ BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
+ C.EmitReport(R);
+ }
+ return 0;
+ }
+ return stateNotNull;
+}
+
+const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
+ const GRState *state,
+ CheckerContext &C) {
+ SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
+ if (!Sym)
+ return state;
+
+ const StreamState *SS = state->get<StreamState>(Sym);
+
+ // If the file stream is not tracked, return.
+ if (!SS)
+ return state;
+
+ // Check: Double close a File Descriptor could cause undefined behaviour.
+ // Conforming to man-pages
+ if (SS->isClosed()) {
+ ExplodedNode *N = C.generateSink();
+ if (N) {
+ if (!BT_doubleclose)
+ BT_doubleclose = new BuiltinBug("Double fclose",
+ "Try to close a file Descriptor already"
+ " closed. Cause undefined behaviour.");
+ BugReport *R = new BugReport(*BT_doubleclose,
+ BT_doubleclose->getDescription(), N);
+ C.EmitReport(R);
+ }
+ return NULL;
+ }
+
+ // Close the File Descriptor.
+ return state->set<StreamState>(Sym, StreamState::getClosed(CE));
+}
+
+void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I != E; ++I) {
+ SymbolRef Sym = *I;
+ const GRState *state = C.getState();
+ const StreamState *SS = state->get<StreamState>(Sym);
+ if (!SS)
+ return;
+
+ if (SS->isOpened()) {
+ ExplodedNode *N = C.generateSink();
+ if (N) {
+ if (!BT_ResourceLeak)
+ BT_ResourceLeak = new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak.");
+ BugReport *R = new BugReport(*BT_ResourceLeak,
+ BT_ResourceLeak->getDescription(), N);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
+
+void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
+ ExprEngine &Eng) {
+ const GRState *state = B.getState();
+ typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
+ SymMap M = state->get<StreamState>();
+
+ for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ StreamState SS = I->second;
+ if (SS.isOpened()) {
+ ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ if (N) {
+ if (!BT_ResourceLeak)
+ BT_ResourceLeak = new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak.");
+ BugReport *R = new BugReport(*BT_ResourceLeak,
+ BT_ResourceLeak->getDescription(), N);
+ Eng.getBugReporter().EmitReport(R);
+ }
+ }
+ }
+}
+
+void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+ const Expr *RetE = S->getRetValue();
+ if (!RetE)
+ return;
+
+ const GRState *state = C.getState();
+ SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
+
+ if (!Sym)
+ return;
+
+ const StreamState *SS = state->get<StreamState>(Sym);
+ if(!SS)
+ return;
+
+ if (SS->isOpened())
+ state = state->set<StreamState>(Sym, StreamState::getEscaped(S));
+
+ C.addTransition(state);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
new file mode 100644
index 0000000..14ae9ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -0,0 +1,120 @@
+//=== UndefBranchChecker.cpp -----------------------------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines UndefBranchChecker, which checks for undefined branch
+// condition.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class UndefBranchChecker : public Checker {
+ BuiltinBug *BT;
+
+ struct FindUndefExpr {
+ GRStateManager& VM;
+ const GRState* St;
+
+ FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
+
+ const Expr* FindExpr(const Expr* Ex) {
+ if (!MatchesCriteria(Ex))
+ return 0;
+
+ for (Stmt::const_child_iterator I = Ex->child_begin(),
+ E = Ex->child_end();I!=E;++I)
+ if (const Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
+ const Expr* E2 = FindExpr(ExI);
+ if (E2) return E2;
+ }
+
+ return Ex;
+ }
+
+ bool MatchesCriteria(const Expr* Ex) { return St->getSVal(Ex).isUndef(); }
+ };
+
+public:
+ UndefBranchChecker() : BT(0) {}
+ static void *getTag();
+ void VisitBranchCondition(BranchNodeBuilder &Builder, ExprEngine &Eng,
+ const Stmt *Condition, void *tag);
+};
+
+}
+
+void ento::RegisterUndefBranchChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UndefBranchChecker());
+}
+
+void *UndefBranchChecker::getTag() {
+ static int x;
+ return &x;
+}
+
+void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder,
+ ExprEngine &Eng,
+ const Stmt *Condition, void *tag){
+ const GRState *state = Builder.getState();
+ SVal X = state->getSVal(Condition);
+ if (X.isUndef()) {
+ ExplodedNode *N = Builder.generateNode(state, true);
+ if (N) {
+ N->markAsSink();
+ if (!BT)
+ BT = new BuiltinBug("Branch condition evaluates to a garbage value");
+
+ // What's going on here: we want to highlight the subexpression of the
+ // condition that is the most likely source of the "uninitialized
+ // branch condition." We do a recursive walk of the condition's
+ // subexpressions and roughly look for the most nested subexpression
+ // that binds to Undefined. We then highlight that expression's range.
+ BlockEdge B = cast<BlockEdge>(N->getLocation());
+ const Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
+ assert (Ex && "Block must have a terminator.");
+
+ // Get the predecessor node and check if is a PostStmt with the Stmt
+ // being the terminator condition. We want to inspect the state
+ // of that node instead because it will contain main information about
+ // the subexpressions.
+ assert (!N->pred_empty());
+
+ // Note: any predecessor will do. They should have identical state,
+ // since all the BlockEdge did was act as an error sink since the value
+ // had to already be undefined.
+ ExplodedNode *PrevN = *N->pred_begin();
+ ProgramPoint P = PrevN->getLocation();
+ const GRState* St = N->getState();
+
+ if (PostStmt* PS = dyn_cast<PostStmt>(&P))
+ if (PS->getStmt() == Ex)
+ St = PrevN->getState();
+
+ FindUndefExpr FindIt(Eng.getStateManager(), St);
+ Ex = FindIt.FindExpr(Ex);
+
+ // Emit the bug report.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N);
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ R->addRange(Ex->getSourceRange());
+
+ Eng.getBugReporter().EmitReport(R);
+ }
+
+ Builder.markInfeasible(true);
+ Builder.markInfeasible(false);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
new file mode 100644
index 0000000..6d3c966
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -0,0 +1,102 @@
+// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker detects blocks that capture uninitialized values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefCapturedBlockVarChecker
+ : public CheckerVisitor<UndefCapturedBlockVarChecker> {
+ BugType *BT;
+
+public:
+ UndefCapturedBlockVarChecker() : BT(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE);
+};
+} // end anonymous namespace
+
+void ento::RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UndefCapturedBlockVarChecker());
+}
+
+static const BlockDeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
+ const VarDecl *VD){
+ if (const BlockDeclRefExpr *BR = dyn_cast<BlockDeclRefExpr>(S))
+ if (BR->getDecl() == VD)
+ return BR;
+
+ for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
+ I!=E; ++I)
+ if (const Stmt *child = *I) {
+ const BlockDeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
+ if (BR)
+ return BR;
+ }
+
+ return NULL;
+}
+
+void
+UndefCapturedBlockVarChecker::PostVisitBlockExpr(CheckerContext &C,
+ const BlockExpr *BE) {
+ if (!BE->getBlockDecl()->hasCaptures())
+ return;
+
+ const GRState *state = C.getState();
+ const BlockDataRegion *R =
+ cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+
+ BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+ E = R->referenced_vars_end();
+
+ for (; I != E; ++I) {
+ // This VarRegion is the region associated with the block; we need
+ // the one associated with the encompassing context.
+ const VarRegion *VR = *I;
+ const VarDecl *VD = VR->getDecl();
+
+ if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
+ continue;
+
+ // Get the VarRegion associated with VD in the local stack frame.
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
+ VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
+
+ if (state->getSVal(VR).isUndef())
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT)
+ BT = new BuiltinBug("uninitialized variable captured by block");
+
+ // Generate a bug report.
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "Variable '" << VD->getName()
+ << "' is uninitialized when captured by block";
+
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, os.str(), N);
+ if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
+ R->addRange(Ex->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerFindLastStore, VR);
+ // need location of block
+ C.EmitReport(R);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
new file mode 100644
index 0000000..64a3567
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -0,0 +1,87 @@
+//=== UndefResultChecker.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefResultChecker, a builtin check in ExprEngine that
+// performs checks for undefined results of non-assignment binary operators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefResultChecker
+ : public CheckerVisitor<UndefResultChecker> {
+
+ BugType *BT;
+
+public:
+ UndefResultChecker() : BT(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+} // end anonymous namespace
+
+void ento::RegisterUndefResultChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UndefResultChecker());
+}
+
+void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
+ const GRState *state = C.getState();
+ if (state->getSVal(B).isUndef()) {
+ // Generate an error node.
+ ExplodedNode *N = C.generateSink();
+ if (!N)
+ return;
+
+ if (!BT)
+ BT = new BuiltinBug("Result of operation is garbage or undefined");
+
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream OS(sbuf);
+ const Expr *Ex = NULL;
+ bool isLeft = true;
+
+ if (state->getSVal(B->getLHS()).isUndef()) {
+ Ex = B->getLHS()->IgnoreParenCasts();
+ isLeft = true;
+ }
+ else if (state->getSVal(B->getRHS()).isUndef()) {
+ Ex = B->getRHS()->IgnoreParenCasts();
+ isLeft = false;
+ }
+
+ if (Ex) {
+ OS << "The " << (isLeft ? "left" : "right")
+ << " operand of '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' is a garbage value";
+ }
+ else {
+ // Neither operand was undefined, but the result is undefined.
+ OS << "The result of the '"
+ << BinaryOperator::getOpcodeStr(B->getOpcode())
+ << "' expression is undefined";
+ }
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N);
+ if (Ex) {
+ report->addRange(Ex->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+ }
+ else
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
+ C.EmitReport(report);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
new file mode 100644
index 0000000..ff03448
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -0,0 +1,57 @@
+//===--- UndefinedArraySubscriptChecker.h ----------------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedArraySubscriptChecker, a builtin check in ExprEngine
+// that performs checks for undefined array subscripts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefinedArraySubscriptChecker
+ : public CheckerVisitor<UndefinedArraySubscriptChecker> {
+ BugType *BT;
+public:
+ UndefinedArraySubscriptChecker() : BT(0) {}
+ static void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+ void PreVisitArraySubscriptExpr(CheckerContext &C,
+ const ArraySubscriptExpr *A);
+};
+} // end anonymous namespace
+
+void ento::RegisterUndefinedArraySubscriptChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UndefinedArraySubscriptChecker());
+}
+
+void
+UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C,
+ const ArraySubscriptExpr *A) {
+ if (C.getState()->getSVal(A->getIdx()).isUndef()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ if (!BT)
+ BT = new BuiltinBug("Array subscript is undefined");
+
+ // Generate a report for this bug.
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+ R->addRange(A->getIdx()->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ A->getIdx());
+ C.EmitReport(R);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
new file mode 100644
index 0000000..e53cbba
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -0,0 +1,94 @@
+//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UndefinedAssginmentChecker, a builtin check in ExprEngine that
+// checks for assigning undefined values.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UndefinedAssignmentChecker
+ : public CheckerVisitor<UndefinedAssignmentChecker> {
+ BugType *BT;
+public:
+ UndefinedAssignmentChecker() : BT(0) {}
+ static void *getTag();
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
+};
+}
+
+void ento::RegisterUndefinedAssignmentChecker(ExprEngine &Eng){
+ Eng.registerCheck(new UndefinedAssignmentChecker());
+}
+
+void *UndefinedAssignmentChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *StoreE,
+ SVal location,
+ SVal val) {
+ if (!val.isUndef())
+ return;
+
+ ExplodedNode *N = C.generateSink();
+
+ if (!N)
+ return;
+
+ const char *str = "Assigned value is garbage or undefined";
+
+ if (!BT)
+ BT = new BuiltinBug(str);
+
+ // Generate a report for this bug.
+ const Expr *ex = 0;
+
+ while (StoreE) {
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
+ if (B->isCompoundAssignmentOp()) {
+ const GRState *state = C.getState();
+ if (state->getSVal(B->getLHS()).isUndef()) {
+ str = "The left expression of the compound assignment is an "
+ "uninitialized value. The computed value will also be garbage";
+ ex = B->getLHS();
+ break;
+ }
+ }
+
+ ex = B->getRHS();
+ break;
+ }
+
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
+ const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ ex = VD->getInit();
+ }
+
+ break;
+ }
+
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, str, N);
+ if (ex) {
+ R->addRange(ex->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
+ }
+ C.EmitReport(R);
+}
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
new file mode 100644
index 0000000..a53ebb5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -0,0 +1,282 @@
+//= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines UnixAPIChecker, which is an assortment of checks on calls
+// to various, widely used UNIX/Posix functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <fcntl.h>
+
+using namespace clang;
+using namespace ento;
+using llvm::Optional;
+
+namespace {
+class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
+ enum SubChecks {
+ OpenFn = 0,
+ PthreadOnceFn = 1,
+ MallocZero = 2,
+ NumChecks
+ };
+
+ BugType *BTypes[NumChecks];
+
+public:
+ Optional<uint64_t> Val_O_CREAT;
+
+public:
+ UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
+ static void *getTag() { static unsigned tag = 0; return &tag; }
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+} //end anonymous namespace
+
+static void RegisterUnixAPIChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UnixAPIChecker());
+}
+
+void ento::registerUnixAPIChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterUnixAPIChecker);
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+static inline void LazyInitialize(BugType *&BT, const char *name) {
+ if (BT)
+ return;
+ BT = new BugType(name, "Unix API");
+}
+
+//===----------------------------------------------------------------------===//
+// "open" (man 2 open)
+//===----------------------------------------------------------------------===//
+
+static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
+ const CallExpr *CE, BugType *&BT) {
+ // The definition of O_CREAT is platform specific. We need a better way
+ // of querying this information from the checking environment.
+ if (!UC.Val_O_CREAT.hasValue()) {
+ if (C.getASTContext().Target.getTriple().getVendor() == llvm::Triple::Apple)
+ UC.Val_O_CREAT = 0x0200;
+ else {
+ // FIXME: We need a more general way of getting the O_CREAT value.
+ // We could possibly grovel through the preprocessor state, but
+ // that would require passing the Preprocessor object to the ExprEngine.
+ return;
+ }
+ }
+
+ LazyInitialize(BT, "Improper use of 'open'");
+
+ // Look at the 'oflags' argument for the O_CREAT flag.
+ const GRState *state = C.getState();
+
+ if (CE->getNumArgs() < 2) {
+ // The frontend should issue a warning for this case, so this is a sanity
+ // check.
+ return;
+ }
+
+ // Now check if oflags has O_CREAT set.
+ const Expr *oflagsEx = CE->getArg(1);
+ const SVal V = state->getSVal(oflagsEx);
+ if (!isa<NonLoc>(V)) {
+ // The case where 'V' can be a location can only be due to a bad header,
+ // so in this case bail out.
+ return;
+ }
+ NonLoc oflags = cast<NonLoc>(V);
+ NonLoc ocreateFlag =
+ cast<NonLoc>(C.getSValBuilder().makeIntVal(UC.Val_O_CREAT.getValue(),
+ oflagsEx->getType()));
+ SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
+ oflags, ocreateFlag,
+ oflagsEx->getType());
+ if (maskedFlagsUC.isUnknownOrUndef())
+ return;
+ DefinedSVal maskedFlags = cast<DefinedSVal>(maskedFlagsUC);
+
+ // Check if maskedFlags is non-zero.
+ const GRState *trueState, *falseState;
+ llvm::tie(trueState, falseState) = state->assume(maskedFlags);
+
+ // Only emit an error if the value of 'maskedFlags' is properly
+ // constrained;
+ if (!(trueState && !falseState))
+ return;
+
+ if (CE->getNumArgs() < 3) {
+ ExplodedNode *N = C.generateSink(trueState);
+ if (!N)
+ return;
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT,
+ "Call to 'open' requires a third argument when "
+ "the 'O_CREAT' flag is set", N);
+ report->addRange(oflagsEx->getSourceRange());
+ C.EmitReport(report);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// pthread_once
+//===----------------------------------------------------------------------===//
+
+static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
+ const CallExpr *CE, BugType *&BT) {
+
+ // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
+ // They can possibly be refactored.
+
+ LazyInitialize(BT, "Improper use of 'pthread_once'");
+
+ if (CE->getNumArgs() < 1)
+ return;
+
+ // Check if the first argument is stack allocated. If so, issue a warning
+ // because that's likely to be bad news.
+ const GRState *state = C.getState();
+ const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+ if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
+ return;
+
+ ExplodedNode *N = C.generateSink(state);
+ if (!N)
+ return;
+
+ llvm::SmallString<256> S;
+ llvm::raw_svector_ostream os(S);
+ os << "Call to 'pthread_once' uses";
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R))
+ os << " the local variable '" << VR->getDecl()->getName() << '\'';
+ else
+ os << " stack allocated memory";
+ os << " for the \"control\" value. Using such transient memory for "
+ "the control value is potentially dangerous.";
+ if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+ os << " Perhaps you intended to declare the variable as 'static'?";
+
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), N);
+ report->addRange(CE->getArg(0)->getSourceRange());
+ C.EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// "malloc" with allocation size 0
+//===----------------------------------------------------------------------===//
+
+// FIXME: Eventually this should be rolled into the MallocChecker, but this
+// check is more basic and is valuable for widespread use.
+static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC,
+ const CallExpr *CE, BugType *&BT) {
+
+ // Sanity check that malloc takes one argument.
+ if (CE->getNumArgs() != 1)
+ return;
+
+ // Check if the allocation size is 0.
+ const GRState *state = C.getState();
+ SVal argVal = state->getSVal(CE->getArg(0));
+
+ if (argVal.isUnknownOrUndef())
+ return;
+
+ const GRState *trueState, *falseState;
+ llvm::tie(trueState, falseState) = state->assume(cast<DefinedSVal>(argVal));
+
+ // Is the value perfectly constrained to zero?
+ if (falseState && !trueState) {
+ ExplodedNode *N = C.generateSink(falseState);
+ if (!N)
+ return;
+
+ // FIXME: Add reference to CERT advisory, and/or C99 standard in bug
+ // output.
+
+ LazyInitialize(BT, "Undefined allocation of 0 bytes");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT, "Call to 'malloc' has an allocation size"
+ " of 0 bytes", N);
+ report->addRange(CE->getArg(0)->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ CE->getArg(0));
+ C.EmitReport(report);
+ return;
+ }
+ // Assume the the value is non-zero going forward.
+ assert(trueState);
+ if (trueState != state) {
+ C.addTransition(trueState);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Central dispatch function.
+//===----------------------------------------------------------------------===//
+
+typedef void (*SubChecker)(CheckerContext &C, UnixAPIChecker &UC,
+ const CallExpr *CE, BugType *&BT);
+namespace {
+ class SubCheck {
+ SubChecker SC;
+ UnixAPIChecker *UC;
+ BugType **BT;
+ public:
+ SubCheck(SubChecker sc, UnixAPIChecker *uc, BugType *& bt) : SC(sc), UC(uc),
+ BT(&bt) {}
+ SubCheck() : SC(NULL), UC(NULL), BT(NULL) {}
+
+ void run(CheckerContext &C, const CallExpr *CE) const {
+ if (SC)
+ SC(C, *UC, CE, *BT);
+ }
+ };
+} // end anonymous namespace
+
+void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ // Get the callee. All the functions we care about are C functions
+ // with simple identifiers.
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ const FunctionTextRegion *Fn =
+ dyn_cast_or_null<FunctionTextRegion>(state->getSVal(Callee).getAsRegion());
+
+ if (!Fn)
+ return;
+
+ const IdentifierInfo *FI = Fn->getDecl()->getIdentifier();
+ if (!FI)
+ return;
+
+ const SubCheck &SC =
+ llvm::StringSwitch<SubCheck>(FI->getName())
+ .Case("open",
+ SubCheck(CheckOpen, this, BTypes[OpenFn]))
+ .Case("pthread_once",
+ SubCheck(CheckPthreadOnce, this, BTypes[PthreadOnceFn]))
+ .Case("malloc",
+ SubCheck(CheckMallocZero, this, BTypes[MallocZero]))
+ .Default(SubCheck());
+
+ SC.run(C, CE);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
new file mode 100644
index 0000000..3038e29
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -0,0 +1,228 @@
+//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file implements a generalized unreachable code checker using a
+// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
+// post-analysis to determine what was never visited.
+//
+// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+// The number of CFGBlock pointers we want to reserve memory for. This is used
+// once for each function we analyze.
+#define DEFAULT_CFGBLOCKS 256
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class UnreachableCodeChecker : public Checker {
+public:
+ static void *getTag();
+ void VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ ExprEngine &Eng);
+private:
+ static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
+ void FindUnreachableEntryPoints(const CFGBlock *CB);
+ static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
+ static inline bool isEmptyCFGBlock(const CFGBlock *CB);
+
+ llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
+ llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
+};
+}
+
+void *UnreachableCodeChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+static void RegisterUnreachableCodeChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new UnreachableCodeChecker());
+}
+
+void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
+ mgr.addCheckerRegisterFunction(RegisterUnreachableCodeChecker);
+}
+
+void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ ExprEngine &Eng) {
+ // Bail out if we didn't cover all paths
+ if (Eng.hasWorkRemaining())
+ return;
+
+ CFG *C = 0;
+ ParentMap *PM = 0;
+ // Iterate over ExplodedGraph
+ for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
+ I != E; ++I) {
+ const ProgramPoint &P = I->getLocation();
+ const LocationContext *LC = P.getLocationContext();
+
+ // Save the CFG if we don't have it already
+ if (!C)
+ C = LC->getAnalysisContext()->getUnoptimizedCFG();
+ if (!PM)
+ PM = &LC->getParentMap();
+
+ if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+ const CFGBlock *CB = BE->getBlock();
+ reachable.insert(CB->getBlockID());
+ }
+ }
+
+ // Bail out if we didn't get the CFG or the ParentMap.
+ if (!C || !PM)
+ return;
+
+ ASTContext &Ctx = B.getContext();
+
+ // Find CFGBlocks that were not covered by any node
+ for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
+ const CFGBlock *CB = *I;
+ // Check if the block is unreachable
+ if (reachable.count(CB->getBlockID()))
+ continue;
+
+ // Check if the block is empty (an artificial block)
+ if (isEmptyCFGBlock(CB))
+ continue;
+
+ // Find the entry points for this block
+ if (!visited.count(CB->getBlockID()))
+ FindUnreachableEntryPoints(CB);
+
+ // This block may have been pruned; check if we still want to report it
+ if (reachable.count(CB->getBlockID()))
+ continue;
+
+ // Check for false positives
+ if (CB->size() > 0 && isInvalidPath(CB, *PM))
+ continue;
+
+ // Special case for __builtin_unreachable.
+ // FIXME: This should be extended to include other unreachable markers,
+ // such as llvm_unreachable.
+ if (!CB->empty()) {
+ CFGElement First = CB->front();
+ if (CFGStmt S = First.getAs<CFGStmt>()) {
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S.getStmt())) {
+ if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
+ continue;
+ }
+ }
+ }
+
+ // We found a block that wasn't covered - find the statement to report
+ SourceRange SR;
+ SourceLocation SL;
+ if (const Stmt *S = getUnreachableStmt(CB)) {
+ SR = S->getSourceRange();
+ SL = S->getLocStart();
+ if (SR.isInvalid() || SL.isInvalid())
+ continue;
+ }
+ else
+ continue;
+
+ // Check if the SourceLocation is in a system header
+ const SourceManager &SM = B.getSourceManager();
+ if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
+ continue;
+
+ B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
+ " executed", SL, SR);
+ }
+}
+
+// Recursively finds the entry point(s) for this dead CFGBlock.
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+ visited.insert(CB->getBlockID());
+
+ for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end();
+ I != E; ++I) {
+ if (!reachable.count((*I)->getBlockID())) {
+ // If we find an unreachable predecessor, mark this block as reachable so
+ // we don't report this block
+ reachable.insert(CB->getBlockID());
+ if (!visited.count((*I)->getBlockID()))
+ // If we haven't previously visited the unreachable predecessor, recurse
+ FindUnreachableEntryPoints(*I);
+ }
+ }
+}
+
+// Find the Stmt* in a CFGBlock for reporting a warning
+const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
+ for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
+ if (CFGStmt S = I->getAs<CFGStmt>())
+ return S;
+ }
+ if (const Stmt *S = CB->getTerminator())
+ return S;
+ else
+ return 0;
+}
+
+// Determines if the path to this CFGBlock contained an element that infers this
+// block is a false positive. We assume that FindUnreachableEntryPoints has
+// already marked only the entry points to any dead code, so we need only to
+// find the condition that led to this block (the predecessor of this block.)
+// There will never be more than one predecessor.
+bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
+ const ParentMap &PM) {
+ // We only expect a predecessor size of 0 or 1. If it is >1, then an external
+ // condition has broken our assumption (for example, a sink being placed by
+ // another check). In these cases, we choose not to report.
+ if (CB->pred_size() > 1)
+ return true;
+
+ // If there are no predecessors, then this block is trivially unreachable
+ if (CB->pred_size() == 0)
+ return false;
+
+ const CFGBlock *pred = *CB->pred_begin();
+
+ // Get the predecessor block's terminator conditon
+ const Stmt *cond = pred->getTerminatorCondition();
+
+ //assert(cond && "CFGBlock's predecessor has a terminator condition");
+ // The previous assertion is invalid in some cases (eg do/while). Leaving
+ // reporting of these situations on at the moment to help triage these cases.
+ if (!cond)
+ return false;
+
+ // Run each of the checks on the conditions
+ if (containsMacro(cond) || containsEnum(cond)
+ || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
+ || containsStmt<SizeOfAlignOfExpr>(cond))
+ return true;
+
+ return false;
+}
+
+// Returns true if the given CFGBlock is empty
+bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
+ return CB->getLabel() == 0 // No labels
+ && CB->size() == 0 // No statements
+ && CB->getTerminator() == 0; // No terminator
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
new file mode 100644
index 0000000..ba46e17
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -0,0 +1,138 @@
+//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines VLASizeChecker, a builtin check in ExprEngine that
+// performs checks for declaration of VLA of undefined or zero size.
+// In addition, VLASizeChecker is responsible for defining the extent
+// of the MemRegion that represents a VLA.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InternalChecks.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
+ BugType *BT_zero;
+ BugType *BT_undef;
+
+public:
+ VLASizeChecker() : BT_zero(0), BT_undef(0) {}
+ static void *getTag() { static int tag = 0; return &tag; }
+ void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
+};
+} // end anonymous namespace
+
+void ento::RegisterVLASizeChecker(ExprEngine &Eng) {
+ Eng.registerCheck(new VLASizeChecker());
+}
+
+void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+ if (!DS->isSingleDecl())
+ return;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!VD)
+ return;
+
+ ASTContext &Ctx = C.getASTContext();
+ const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
+ if (!VLA)
+ return;
+
+ // FIXME: Handle multi-dimensional VLAs.
+ const Expr* SE = VLA->getSizeExpr();
+ const GRState *state = C.getState();
+ SVal sizeV = state->getSVal(SE);
+
+ if (sizeV.isUndef()) {
+ // Generate an error node.
+ ExplodedNode *N = C.generateSink();
+ if (!N)
+ return;
+
+ if (!BT_undef)
+ BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
+ "garbage value as its size");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
+ report->addRange(SE->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ C.EmitReport(report);
+ return;
+ }
+
+ // See if the size value is known. It can't be undefined because we would have
+ // warned about that already.
+ if (sizeV.isUnknown())
+ return;
+
+ // Check if the size is zero.
+ DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
+
+ const GRState *stateNotZero, *stateZero;
+ llvm::tie(stateNotZero, stateZero) = state->assume(sizeD);
+
+ if (stateZero && !stateNotZero) {
+ ExplodedNode* N = C.generateSink(stateZero);
+ if (!BT_zero)
+ BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
+ "size");
+
+ EnhancedBugReport *report =
+ new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
+ report->addRange(SE->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
+ C.EmitReport(report);
+ return;
+ }
+
+ // From this point on, assume that the size is not zero.
+ state = stateNotZero;
+
+ // VLASizeChecker is responsible for defining the extent of the array being
+ // declared. We do this by multiplying the array length by the element size,
+ // then matching that with the array region's extent symbol.
+
+ // Convert the array length to size_t.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ QualType SizeTy = Ctx.getSizeType();
+ NonLoc ArrayLength = cast<NonLoc>(svalBuilder.evalCast(sizeD, SizeTy,
+ SE->getType()));
+
+ // Get the element size.
+ CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
+ SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.getQuantity(), SizeTy);
+
+ // Multiply the array length by the element size.
+ SVal ArraySizeVal = svalBuilder.evalBinOpNN(state, BO_Mul, ArrayLength,
+ cast<NonLoc>(EleSizeVal), SizeTy);
+
+ // Finally, assume that the array's extent matches the given size.
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
+ DefinedOrUnknownSVal Extent =
+ state->getRegion(VD, LC)->getExtent(svalBuilder);
+ DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
+ DefinedOrUnknownSVal sizeIsKnown =
+ svalBuilder.evalEQ(state, Extent, ArraySize);
+ state = state->assume(sizeIsKnown, true);
+
+ // Assume should not fail at this point.
+ assert(state);
+
+ // Remember our assumptions!
+ C.addTransition(state);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp
new file mode 100644
index 0000000..e80cf9b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AggExprVisitor.cpp
@@ -0,0 +1,69 @@
+//=-- AggExprVisitor.cpp - evaluating expressions of C++ class type -*- 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 AggExprVisitor class, which contains lots of boiler
+// plate code for evaluating expressions of C++ class type.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/StmtVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+/// AggExprVisitor is designed after AggExprEmitter of the CodeGen module. It
+/// is used for evaluating exprs of C++ object type. Evaluating such exprs
+/// requires a destination pointer pointing to the object being evaluated
+/// into. Passing such a pointer around would pollute the Visit* interface of
+/// ExprEngine. AggExprVisitor encapsulates code that goes through various
+/// cast and construct exprs (and others), and at the final point, dispatches
+/// back to the ExprEngine to let the real evaluation logic happen.
+class AggExprVisitor : public StmtVisitor<AggExprVisitor> {
+ const MemRegion *Dest;
+ ExplodedNode *Pred;
+ ExplodedNodeSet &DstSet;
+ ExprEngine &Eng;
+
+public:
+ AggExprVisitor(const MemRegion *dest, ExplodedNode *N, ExplodedNodeSet &dst,
+ ExprEngine &eng)
+ : Dest(dest), Pred(N), DstSet(dst), Eng(eng) {}
+
+ void VisitCastExpr(CastExpr *E);
+ void VisitCXXConstructExpr(CXXConstructExpr *E);
+ void VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+};
+}
+
+void AggExprVisitor::VisitCastExpr(CastExpr *E) {
+ switch (E->getCastKind()) {
+ default:
+ assert(0 && "Unhandled cast kind");
+ case CK_NoOp:
+ case CK_ConstructorConversion:
+ case CK_UserDefinedConversion:
+ Visit(E->getSubExpr());
+ break;
+ }
+}
+
+void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet);
+}
+
+void AggExprVisitor::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+ Eng.VisitCXXMemberCallExpr(E, Pred, DstSet);
+}
+
+void ExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+ AggExprVisitor(Dest, Pred, Dst, *this).Visit(const_cast<Expr *>(E));
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
new file mode 100644
index 0000000..5f4f83c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -0,0 +1,32 @@
+//===-- AnalysisManager.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Indexer.h"
+
+using namespace clang;
+using namespace ento;
+
+AnalysisContext *
+AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) {
+ idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D),
+ Idxer->getProgram());
+ FunctionDecl *FuncDef;
+ idx::TranslationUnit *TU;
+ llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
+
+ if (FuncDef == 0)
+ return 0;
+
+ // This AnalysisContext wraps function definition in another translation unit.
+ // But it is still owned by the AnalysisManager associated with the current
+ // translation unit.
+ return AnaCtxMgr.getContext(FuncDef, TU);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicConstraintManager.cpp
new file mode 100644
index 0000000..3050ca3
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicConstraintManager.cpp
@@ -0,0 +1,338 @@
+//== BasicConstraintManager.cpp - Manage basic constraints.------*- 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 BasicConstraintManager, a class that tracks simple
+// equality and inequality constraints on symbolic values of GRState.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SimpleConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+
+namespace { class ConstNotEq {}; }
+namespace { class ConstEq {}; }
+
+typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
+typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
+
+static int ConstEqIndex = 0;
+static int ConstNotEqIndex = 0;
+
+namespace clang {
+namespace ento {
+template<>
+struct GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> {
+ static inline void* GDMIndex() { return &ConstNotEqIndex; }
+};
+
+template<>
+struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
+ static inline void* GDMIndex() { return &ConstEqIndex; }
+};
+}
+}
+
+namespace {
+// BasicConstraintManager only tracks equality and inequality constraints of
+// constants and integer variables.
+class BasicConstraintManager
+ : public SimpleConstraintManager {
+ GRState::IntSetTy::Factory ISetFactory;
+public:
+ BasicConstraintManager(GRStateManager &statemgr, SubEngine &subengine)
+ : SimpleConstraintManager(subengine),
+ ISetFactory(statemgr.getAllocator()) {}
+
+ const GRState *assumeSymNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymLT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymGT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymGE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment);
+
+ const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
+
+ const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
+
+ const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
+ bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
+ const;
+ bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
+ const;
+
+ const GRState* removeDeadBindings(const GRState* state, SymbolReaper& SymReaper);
+
+ void print(const GRState* state, llvm::raw_ostream& Out,
+ const char* nl, const char *sep);
+};
+
+} // end anonymous namespace
+
+ConstraintManager* ento::CreateBasicConstraintManager(GRStateManager& statemgr,
+ SubEngine &subengine) {
+ return new BasicConstraintManager(statemgr, subengine);
+}
+
+
+const GRState*
+BasicConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // First, determine if sym == X, where X+Adjustment != V.
+ llvm::APSInt Adjusted = V-Adjustment;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = (*X != Adjusted);
+ return isFeasible ? state : NULL;
+ }
+
+ // Second, determine if sym+Adjustment != V.
+ if (isNotEqual(state, sym, Adjusted))
+ return state;
+
+ // If we reach here, sym is not a constant and we don't know if it is != V.
+ // Make that assumption.
+ return AddNE(state, sym, Adjusted);
+}
+
+const GRState*
+BasicConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // First, determine if sym == X, where X+Adjustment != V.
+ llvm::APSInt Adjusted = V-Adjustment;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = (*X == Adjusted);
+ return isFeasible ? state : NULL;
+ }
+
+ // Second, determine if sym+Adjustment != V.
+ if (isNotEqual(state, sym, Adjusted))
+ return NULL;
+
+ // If we reach here, sym is not a constant and we don't know if it is == V.
+ // Make that assumption.
+ return AddEQ(state, sym, Adjusted);
+}
+
+// The logic for these will be handled in another ConstraintManager.
+const GRState*
+BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // Is 'V' the smallest possible value?
+ if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
+ // sym cannot be any value less than 'V'. This path is infeasible.
+ return NULL;
+ }
+
+ // FIXME: For now have assuming x < y be the same as assuming sym != V;
+ return assumeSymNE(state, sym, V, Adjustment);
+}
+
+const GRState*
+BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // Is 'V' the largest possible value?
+ if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
+ // sym cannot be any value greater than 'V'. This path is infeasible.
+ return NULL;
+ }
+
+ // FIXME: For now have assuming x > y be the same as assuming sym != V;
+ return assumeSymNE(state, sym, V, Adjustment);
+}
+
+const GRState*
+BasicConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // Reject a path if the value of sym is a constant X and !(X+Adj >= V).
+ if (const llvm::APSInt *X = getSymVal(state, sym)) {
+ bool isFeasible = (*X >= V-Adjustment);
+ return isFeasible ? state : NULL;
+ }
+
+ // Sym is not a constant, but it is worth looking to see if V is the
+ // maximum integer value.
+ if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
+ llvm::APSInt Adjusted = V-Adjustment;
+
+ // If we know that sym != V (after adjustment), then this condition
+ // is infeasible since there is no other value greater than V.
+ bool isFeasible = !isNotEqual(state, sym, Adjusted);
+
+ // If the path is still feasible then as a consequence we know that
+ // 'sym+Adjustment == V' because there are no larger values.
+ // Add this constraint.
+ return isFeasible ? AddEQ(state, sym, Adjusted) : NULL;
+ }
+
+ return state;
+}
+
+const GRState*
+BasicConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) {
+ // Reject a path if the value of sym is a constant X and !(X+Adj <= V).
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = (*X <= V-Adjustment);
+ return isFeasible ? state : NULL;
+ }
+
+ // Sym is not a constant, but it is worth looking to see if V is the
+ // minimum integer value.
+ if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
+ llvm::APSInt Adjusted = V-Adjustment;
+
+ // If we know that sym != V (after adjustment), then this condition
+ // is infeasible since there is no other value less than V.
+ bool isFeasible = !isNotEqual(state, sym, Adjusted);
+
+ // If the path is still feasible then as a consequence we know that
+ // 'sym+Adjustment == V' because there are no smaller values.
+ // Add this constraint.
+ return isFeasible ? AddEQ(state, sym, Adjusted) : NULL;
+ }
+
+ return state;
+}
+
+const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) {
+ // Create a new state with the old binding replaced.
+ return state->set<ConstEq>(sym, &state->getBasicVals().getValue(V));
+}
+
+const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) {
+
+ // First, retrieve the NE-set associated with the given symbol.
+ ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
+ GRState::IntSetTy S = T ? *T : ISetFactory.getEmptySet();
+
+ // Now add V to the NE set.
+ S = ISetFactory.add(S, &state->getBasicVals().getValue(V));
+
+ // Create a new state with the old binding replaced.
+ return state->set<ConstNotEq>(sym, S);
+}
+
+const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
+ SymbolRef sym) const {
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
+ return T ? *T : NULL;
+}
+
+bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) const {
+
+ // Retrieve the NE-set associated with the given symbol.
+ const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
+
+ // See if V is present in the NE-set.
+ return T ? T->contains(&state->getBasicVals().getValue(V)) : false;
+}
+
+bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) const {
+ // Retrieve the EQ-set associated with the given symbol.
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
+ // See if V is present in the EQ-set.
+ return T ? **T == V : false;
+}
+
+/// Scan all symbols referenced by the constraints. If the symbol is not alive
+/// as marked in LSymbols, mark it as dead in DSymbols.
+const GRState*
+BasicConstraintManager::removeDeadBindings(const GRState* state,
+ SymbolReaper& SymReaper) {
+
+ ConstEqTy CE = state->get<ConstEq>();
+ ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
+
+ for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
+ SymbolRef sym = I.getKey();
+ if (SymReaper.maybeDead(sym))
+ CE = CEFactory.remove(CE, sym);
+ }
+ state = state->set<ConstEq>(CE);
+
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
+ ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
+
+ for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
+ SymbolRef sym = I.getKey();
+ if (SymReaper.maybeDead(sym))
+ CNE = CNEFactory.remove(CNE, sym);
+ }
+
+ return state->set<ConstNotEq>(CNE);
+}
+
+void BasicConstraintManager::print(const GRState* state, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) {
+ // Print equality constraints.
+
+ ConstEqTy CE = state->get<ConstEq>();
+
+ if (!CE.isEmpty()) {
+ Out << nl << sep << "'==' constraints:";
+ for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I)
+ Out << nl << " $" << I.getKey() << " : " << *I.getData();
+ }
+
+ // Print != constraints.
+
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
+
+ if (!CNE.isEmpty()) {
+ Out << nl << sep << "'!=' constraints:";
+
+ for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
+ Out << nl << " $" << I.getKey() << " : ";
+ bool isFirst = true;
+
+ GRState::IntSetTy::iterator J = I.getData().begin(),
+ EJ = I.getData().end();
+
+ for ( ; J != EJ; ++J) {
+ if (isFirst) isFirst = false;
+ else Out << ", ";
+
+ Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp
new file mode 100644
index 0000000..98365e7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp
@@ -0,0 +1,604 @@
+//== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the BasicStore and BasicStoreManager classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+using namespace ento;
+
+typedef llvm::ImmutableMap<const MemRegion*,SVal> BindingsTy;
+
+namespace {
+
+class BasicStoreSubRegionMap : public SubRegionMap {
+public:
+ BasicStoreSubRegionMap() {}
+
+ bool iterSubRegions(const MemRegion* R, Visitor& V) const {
+ return true; // Do nothing. No subregions.
+ }
+};
+
+class BasicStoreManager : public StoreManager {
+ BindingsTy::Factory VBFactory;
+public:
+ BasicStoreManager(GRStateManager& mgr)
+ : StoreManager(mgr), VBFactory(mgr.getAllocator()) {}
+
+ ~BasicStoreManager() {}
+
+ SubRegionMap *getSubRegionMap(Store store) {
+ return new BasicStoreSubRegionMap();
+ }
+
+ SVal Retrieve(Store store, Loc loc, QualType T = QualType());
+
+ StoreRef invalidateRegion(Store store, const MemRegion *R, const Expr *E,
+ unsigned Count, InvalidatedSymbols *IS);
+
+ StoreRef invalidateRegions(Store store, const MemRegion * const *Begin,
+ const MemRegion * const *End, const Expr *E,
+ unsigned Count, InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions);
+
+ StoreRef scanForIvars(Stmt *B, const Decl* SelfDecl,
+ const MemRegion *SelfRegion, Store St);
+
+ StoreRef Bind(Store St, Loc loc, SVal V);
+ StoreRef Remove(Store St, Loc loc);
+ StoreRef getInitialStore(const LocationContext *InitLoc);
+
+ StoreRef BindCompoundLiteral(Store store, const CompoundLiteralExpr*,
+ const LocationContext*, SVal val) {
+ return StoreRef(store, *this);
+ }
+
+ /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
+ /// conversions between arrays and pointers.
+ SVal ArrayToPointer(Loc Array) { return Array; }
+
+ /// removeDeadBindings - Scans a BasicStore of 'state' for dead values.
+ /// It updatees the GRState object in place with the values removed.
+ StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
+
+ void iterBindings(Store store, BindingsHandler& f);
+
+ StoreRef BindDecl(Store store, const VarRegion *VR, SVal InitVal) {
+ return BindDeclInternal(store, VR, &InitVal);
+ }
+
+ StoreRef BindDeclWithNoInit(Store store, const VarRegion *VR) {
+ return BindDeclInternal(store, VR, 0);
+ }
+
+ StoreRef BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal);
+
+ static inline BindingsTy GetBindings(Store store) {
+ return BindingsTy(static_cast<const BindingsTy::TreeTy*>(store));
+ }
+
+ void print(Store store, llvm::raw_ostream& Out, const char* nl,
+ const char *sep);
+
+private:
+ SVal LazyRetrieve(Store store, const TypedRegion *R);
+};
+
+} // end anonymous namespace
+
+
+StoreManager* ento::CreateBasicStoreManager(GRStateManager& StMgr) {
+ return new BasicStoreManager(StMgr);
+}
+
+static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
+ bool foundPointer = false;
+ while (1) {
+ const PointerType *PT = T->getAs<PointerType>();
+ if (!PT) {
+ if (!foundPointer)
+ return false;
+
+ // intptr_t* or intptr_t**, etc?
+ if (T->isIntegerType() && C.getTypeSize(T) == C.getTypeSize(C.VoidPtrTy))
+ return true;
+
+ QualType X = C.getCanonicalType(T).getUnqualifiedType();
+ return X == C.VoidTy;
+ }
+
+ foundPointer = true;
+ T = PT->getPointeeType();
+ }
+}
+
+SVal BasicStoreManager::LazyRetrieve(Store store, const TypedRegion *R) {
+ const VarRegion *VR = dyn_cast<VarRegion>(R);
+ if (!VR)
+ return UnknownVal();
+
+ const VarDecl *VD = VR->getDecl();
+ QualType T = VD->getType();
+
+ // Only handle simple types that we can symbolicate.
+ if (!SymbolManager::canSymbolicate(T) || !T->isScalarType())
+ return UnknownVal();
+
+ // Globals and parameters start with symbolic values.
+ // Local variables initially are undefined.
+
+ // Non-static globals may have had their values reset by invalidateRegions.
+ const MemSpaceRegion *MS = VR->getMemorySpace();
+ if (isa<NonStaticGlobalSpaceRegion>(MS)) {
+ BindingsTy B = GetBindings(store);
+ // FIXME: Copy-and-pasted from RegionStore.cpp.
+ if (BindingsTy::data_type *Val = B.lookup(MS)) {
+ if (SymbolRef parentSym = Val->getAsSymbol())
+ return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
+
+ if (Val->isZeroConstant())
+ return svalBuilder.makeZeroVal(T);
+
+ if (Val->isUnknownOrUndef())
+ return *Val;
+
+ assert(0 && "Unknown default value.");
+ }
+ }
+
+ if (VR->hasGlobalsOrParametersStorage() ||
+ isa<UnknownSpaceRegion>(VR->getMemorySpace()))
+ return svalBuilder.getRegionValueSymbolVal(R);
+
+ return UndefinedVal();
+}
+
+SVal BasicStoreManager::Retrieve(Store store, Loc loc, QualType T) {
+ if (isa<UnknownVal>(loc))
+ return UnknownVal();
+
+ assert(!isa<UndefinedVal>(loc));
+
+ switch (loc.getSubKind()) {
+
+ case loc::MemRegionKind: {
+ const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
+
+ if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R) ||
+ isa<CXXThisRegion>(R)))
+ return UnknownVal();
+
+ BindingsTy B = GetBindings(store);
+ BindingsTy::data_type *Val = B.lookup(R);
+ const TypedRegion *TR = cast<TypedRegion>(R);
+
+ if (Val)
+ return CastRetrievedVal(*Val, TR, T);
+
+ SVal V = LazyRetrieve(store, TR);
+ return V.isUnknownOrUndef() ? V : CastRetrievedVal(V, TR, T);
+ }
+
+ case loc::ObjCPropRefKind:
+ case loc::ConcreteIntKind:
+ // Support direct accesses to memory. It's up to individual checkers
+ // to flag an error.
+ return UnknownVal();
+
+ default:
+ assert (false && "Invalid Loc.");
+ break;
+ }
+
+ return UnknownVal();
+}
+
+StoreRef BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
+ if (isa<loc::ConcreteInt>(loc))
+ return StoreRef(store, *this);
+
+ const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
+
+ // Special case: a default symbol assigned to the NonStaticGlobalsSpaceRegion
+ // that is used to derive other symbols.
+ if (isa<NonStaticGlobalSpaceRegion>(R)) {
+ BindingsTy B = GetBindings(store);
+ return StoreRef(VBFactory.add(B, R, V).getRoot(), *this);
+ }
+
+ // Special case: handle store of pointer values (Loc) to pointers via
+ // a cast to intXX_t*, void*, etc. This is needed to handle
+ // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
+ if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ // FIXME: Should check for index 0.
+ QualType T = ER->getLocationType();
+
+ if (isHigherOrderRawPtr(T, Ctx))
+ R = ER->getSuperRegion();
+ }
+
+ if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R) || isa<CXXThisRegion>(R)))
+ return StoreRef(store, *this);
+
+ const TypedRegion *TyR = cast<TypedRegion>(R);
+
+ // Do not bind to arrays. We need to explicitly check for this so that
+ // we do not encounter any weirdness of trying to load/store from arrays.
+ if (TyR->isBoundable() && TyR->getValueType()->isArrayType())
+ return StoreRef(store, *this);
+
+ if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
+ // Only convert 'V' to a location iff the underlying region type
+ // is a location as well.
+ // FIXME: We are allowing a store of an arbitrary location to
+ // a pointer. We may wish to flag a type error here if the types
+ // are incompatible. This may also cause lots of breakage
+ // elsewhere. Food for thought.
+ if (TyR->isBoundable() && Loc::isLocType(TyR->getValueType()))
+ V = X->getLoc();
+ }
+
+ BindingsTy B = GetBindings(store);
+ return StoreRef(V.isUnknown()
+ ? VBFactory.remove(B, R).getRoot()
+ : VBFactory.add(B, R, V).getRoot(), *this);
+}
+
+StoreRef BasicStoreManager::Remove(Store store, Loc loc) {
+ switch (loc.getSubKind()) {
+ case loc::MemRegionKind: {
+ const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
+
+ if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R) ||
+ isa<CXXThisRegion>(R)))
+ return StoreRef(store, *this);
+
+ return StoreRef(VBFactory.remove(GetBindings(store), R).getRoot(), *this);
+ }
+ default:
+ assert ("Remove for given Loc type not yet implemented.");
+ return StoreRef(store, *this);
+ }
+}
+
+StoreRef BasicStoreManager::removeDeadBindings(Store store,
+ const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
+{
+ BindingsTy B = GetBindings(store);
+ typedef SVal::symbol_iterator symbol_iterator;
+
+ // Iterate over the variable bindings.
+ for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
+ if (const VarRegion *VR = dyn_cast<VarRegion>(I.getKey())) {
+ if (SymReaper.isLive(VR))
+ RegionRoots.push_back(VR);
+ else
+ continue;
+ }
+ else if (isa<ObjCIvarRegion>(I.getKey()) ||
+ isa<NonStaticGlobalSpaceRegion>(I.getKey()) ||
+ isa<CXXThisRegion>(I.getKey()))
+ RegionRoots.push_back(I.getKey());
+ else
+ continue;
+
+ // Mark the bindings in the data as live.
+ SVal X = I.getData();
+ for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
+ SymReaper.markLive(*SI);
+ }
+
+ // Scan for live variables and live symbols.
+ llvm::SmallPtrSet<const MemRegion*, 10> Marked;
+
+ while (!RegionRoots.empty()) {
+ const MemRegion* MR = RegionRoots.back();
+ RegionRoots.pop_back();
+
+ while (MR) {
+ if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(MR)) {
+ SymReaper.markLive(SymR->getSymbol());
+ break;
+ }
+ else if (isa<VarRegion>(MR) || isa<ObjCIvarRegion>(MR) ||
+ isa<NonStaticGlobalSpaceRegion>(MR) || isa<CXXThisRegion>(MR)) {
+ if (Marked.count(MR))
+ break;
+
+ Marked.insert(MR);
+ SVal X = Retrieve(store, loc::MemRegionVal(MR));
+
+ // FIXME: We need to handle symbols nested in region definitions.
+ for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI)
+ SymReaper.markLive(*SI);
+
+ if (!isa<loc::MemRegionVal>(X))
+ break;
+
+ const loc::MemRegionVal& LVD = cast<loc::MemRegionVal>(X);
+ RegionRoots.push_back(LVD.getRegion());
+ break;
+ }
+ else if (const SubRegion* R = dyn_cast<SubRegion>(MR))
+ MR = R->getSuperRegion();
+ else
+ break;
+ }
+ }
+
+ // Remove dead variable bindings.
+ StoreRef newStore(store, *this);
+ for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
+ const MemRegion* R = I.getKey();
+
+ if (!Marked.count(R)) {
+ newStore = Remove(newStore.getStore(), svalBuilder.makeLoc(R));
+ SVal X = I.getData();
+
+ for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
+ SymReaper.maybeDead(*SI);
+ }
+ }
+
+ return newStore;
+}
+
+StoreRef BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl,
+ const MemRegion *SelfRegion,
+ Store St) {
+
+ StoreRef newStore(St, *this);
+
+ for (Stmt::child_iterator CI=B->child_begin(), CE=B->child_end();
+ CI != CE; ++CI) {
+
+ if (!*CI)
+ continue;
+
+ // Check if the statement is an ivar reference. We only
+ // care about self.ivar.
+ if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(*CI)) {
+ const Expr *Base = IV->getBase()->IgnoreParenCasts();
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Base)) {
+ if (DR->getDecl() == SelfDecl) {
+ const ObjCIvarRegion *IVR = MRMgr.getObjCIvarRegion(IV->getDecl(),
+ SelfRegion);
+ SVal X = svalBuilder.getRegionValueSymbolVal(IVR);
+ newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(IVR), X);
+ }
+ }
+ }
+ else
+ newStore = scanForIvars(*CI, SelfDecl, SelfRegion, newStore.getStore());
+ }
+
+ return newStore;
+}
+
+StoreRef BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
+ // The LiveVariables information already has a compilation of all VarDecls
+ // used in the function. Iterate through this set, and "symbolicate"
+ // any VarDecl whose value originally comes from outside the function.
+ typedef LiveVariables::AnalysisDataTy LVDataTy;
+ LVDataTy& D = InitLoc->getLiveVariables()->getAnalysisData();
+ StoreRef St(VBFactory.getEmptyMap().getRoot(), *this);
+
+ for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
+ const NamedDecl* ND = I->first;
+
+ // Handle implicit parameters.
+ if (const ImplicitParamDecl* PD = dyn_cast<ImplicitParamDecl>(ND)) {
+ const Decl& CD = *InitLoc->getDecl();
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CD)) {
+ if (MD->getSelfDecl() == PD) {
+ // FIXME: Add type constraints (when they become available) to
+ // SelfRegion? (i.e., it implements MD->getClassInterface()).
+ const VarRegion *VR = MRMgr.getVarRegion(PD, InitLoc);
+ const MemRegion *SelfRegion =
+ svalBuilder.getRegionValueSymbolVal(VR).getAsRegion();
+ assert(SelfRegion);
+ St = Bind(St.getStore(), svalBuilder.makeLoc(VR),
+ loc::MemRegionVal(SelfRegion));
+ // Scan the method for ivar references. While this requires an
+ // entire AST scan, the cost should not be high in practice.
+ St = scanForIvars(MD->getBody(), PD, SelfRegion, St.getStore());
+ }
+ }
+ }
+ }
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(InitLoc->getDecl())) {
+ // For C++ methods add symbolic region for 'this' in initial stack frame.
+ QualType ThisT = MD->getThisType(StateMgr.getContext());
+ MemRegionManager &RegMgr = svalBuilder.getRegionManager();
+ const CXXThisRegion *ThisR = RegMgr.getCXXThisRegion(ThisT, InitLoc);
+ SVal ThisV = svalBuilder.getRegionValueSymbolVal(ThisR);
+ St = Bind(St.getStore(), svalBuilder.makeLoc(ThisR), ThisV);
+ }
+
+ return St;
+}
+
+StoreRef BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
+ SVal* InitVal) {
+
+ BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+ const VarDecl *VD = VR->getDecl();
+ StoreRef newStore(store, *this);
+
+ // BasicStore does not model arrays and structs.
+ if (VD->getType()->isArrayType() || VD->getType()->isStructureOrClassType())
+ return newStore;
+
+ if (VD->hasGlobalStorage()) {
+ // Handle variables with global storage: extern, static, PrivateExtern.
+
+ // FIXME:: static variables may have an initializer, but the second time a
+ // function is called those values may not be current. Currently, a function
+ // will not be called more than once.
+
+ // Static global variables should not be visited here.
+ assert(!(VD->getStorageClass() == SC_Static &&
+ VD->isFileVarDecl()));
+
+ // Process static variables.
+ if (VD->getStorageClass() == SC_Static) {
+ // C99: 6.7.8 Initialization
+ // If an object that has static storage duration is not initialized
+ // explicitly, then:
+ // -if it has pointer type, it is initialized to a null pointer;
+ // -if it has arithmetic type, it is initialized to (positive or
+ // unsigned) zero;
+ if (!InitVal) {
+ QualType T = VD->getType();
+ if (Loc::isLocType(T))
+ newStore = Bind(store, loc::MemRegionVal(VR),
+ loc::ConcreteInt(BasicVals.getValue(0, T)));
+ else if (T->isIntegerType() && T->isScalarType())
+ newStore = Bind(store, loc::MemRegionVal(VR),
+ nonloc::ConcreteInt(BasicVals.getValue(0, T)));
+ } else {
+ newStore = Bind(store, loc::MemRegionVal(VR), *InitVal);
+ }
+ }
+ } else {
+ // Process local scalar variables.
+ QualType T = VD->getType();
+ // BasicStore only supports scalars.
+ if ((T->isScalarType() || T->isReferenceType()) &&
+ svalBuilder.getSymbolManager().canSymbolicate(T)) {
+ SVal V = InitVal ? *InitVal : UndefinedVal();
+ newStore = Bind(store, loc::MemRegionVal(VR), V);
+ }
+ }
+
+ return newStore;
+}
+
+void BasicStoreManager::print(Store store, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) {
+
+ BindingsTy B = GetBindings(store);
+ Out << "Variables:" << nl;
+
+ bool isFirst = true;
+
+ for (BindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
+ if (isFirst)
+ isFirst = false;
+ else
+ Out << nl;
+
+ Out << ' ' << I.getKey() << " : " << I.getData();
+ }
+}
+
+
+void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) {
+ BindingsTy B = GetBindings(store);
+
+ for (BindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I)
+ if (!f.HandleBinding(*this, store, I.getKey(), I.getData()))
+ return;
+
+}
+
+StoreManager::BindingsHandler::~BindingsHandler() {}
+
+//===----------------------------------------------------------------------===//
+// Binding invalidation.
+//===----------------------------------------------------------------------===//
+
+
+StoreRef BasicStoreManager::invalidateRegions(Store store,
+ const MemRegion * const *I,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
+ StoreRef newStore(store, *this);
+
+ if (invalidateGlobals) {
+ BindingsTy B = GetBindings(store);
+ for (BindingsTy::iterator I=B.begin(), End=B.end(); I != End; ++I) {
+ const MemRegion *R = I.getKey();
+ if (isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace()))
+ newStore = invalidateRegion(newStore.getStore(), R, E, Count, IS);
+ }
+ }
+
+ for ( ; I != End ; ++I) {
+ const MemRegion *R = *I;
+ // Don't invalidate globals twice.
+ if (invalidateGlobals) {
+ if (isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace()))
+ continue;
+ }
+ newStore = invalidateRegion(newStore.getStore(), *I, E, Count, IS);
+ if (Regions)
+ Regions->push_back(R);
+ }
+
+ // FIXME: This is copy-and-paste from RegionStore.cpp.
+ if (invalidateGlobals) {
+ // Bind the non-static globals memory space to a new symbol that we will
+ // use to derive the bindings for all non-static globals.
+ const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion();
+ SVal V =
+ svalBuilder.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS, E,
+ /* symbol type, doesn't matter */ Ctx.IntTy,
+ Count);
+
+ newStore = Bind(newStore.getStore(), loc::MemRegionVal(GS), V);
+ if (Regions)
+ Regions->push_back(GS);
+ }
+
+ return newStore;
+}
+
+
+StoreRef BasicStoreManager::invalidateRegion(Store store,
+ const MemRegion *R,
+ const Expr *E,
+ unsigned Count,
+ InvalidatedSymbols *IS) {
+ R = R->StripCasts();
+
+ if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
+ return StoreRef(store, *this);
+
+ if (IS) {
+ BindingsTy B = GetBindings(store);
+ if (BindingsTy::data_type *Val = B.lookup(R)) {
+ if (SymbolRef Sym = Val->getAsSymbol())
+ IS->insert(Sym);
+ }
+ }
+
+ QualType T = cast<TypedRegion>(R)->getValueType();
+ SVal V = svalBuilder.getConjuredSymbolVal(R, E, T, Count);
+ return Bind(store, loc::MemRegionVal(R), V);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
new file mode 100644
index 0000000..6315d83
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -0,0 +1,288 @@
+//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- 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 BasicValueFactory, a class that manages the lifetime
+// of APSInt objects and symbolic constraints used by ExprEngine
+// and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+
+using namespace clang;
+using namespace ento;
+
+void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
+ llvm::ImmutableList<SVal> L) {
+ T.Profile(ID);
+ ID.AddPointer(L.getInternalPointer());
+}
+
+void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
+ const void *store,const TypedRegion *region) {
+ ID.AddPointer(store);
+ ID.AddPointer(region);
+}
+
+typedef std::pair<SVal, uintptr_t> SValData;
+typedef std::pair<SVal, SVal> SValPair;
+
+namespace llvm {
+template<> struct FoldingSetTrait<SValData> {
+ static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
+ X.first.Profile(ID);
+ ID.AddPointer( (void*) X.second);
+ }
+};
+
+template<> struct FoldingSetTrait<SValPair> {
+ static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
+ X.first.Profile(ID);
+ X.second.Profile(ID);
+ }
+};
+}
+
+typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
+ PersistentSValsTy;
+
+typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
+ PersistentSValPairsTy;
+
+BasicValueFactory::~BasicValueFactory() {
+ // Note that the dstor for the contents of APSIntSet will never be called,
+ // so we iterate over the set and invoke the dstor for each APSInt. This
+ // frees an aux. memory allocated to represent very large constants.
+ for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
+ I->getValue().~APSInt();
+
+ delete (PersistentSValsTy*) PersistentSVals;
+ delete (PersistentSValPairsTy*) PersistentSValPairs;
+}
+
+const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
+
+ X.Profile(ID);
+ FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!P) {
+ P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+ new (P) FoldNodeTy(X);
+ APSIntSet.InsertNode(P, InsertPos);
+ }
+
+ return *P;
+}
+
+const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
+ bool isUnsigned) {
+ llvm::APSInt V(X, isUnsigned);
+ return getValue(V);
+}
+
+const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
+ bool isUnsigned) {
+ llvm::APSInt V(BitWidth, isUnsigned);
+ V = X;
+ return getValue(V);
+}
+
+const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
+
+ unsigned bits = Ctx.getTypeSize(T);
+ llvm::APSInt V(bits, T->isUnsignedIntegerType() || Loc::isLocType(T));
+ V = X;
+ return getValue(V);
+}
+
+const CompoundValData*
+BasicValueFactory::getCompoundValData(QualType T,
+ llvm::ImmutableList<SVal> Vals) {
+
+ llvm::FoldingSetNodeID ID;
+ CompoundValData::Profile(ID, T, Vals);
+ void* InsertPos;
+
+ CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!D) {
+ D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
+ new (D) CompoundValData(T, Vals);
+ CompoundValDataSet.InsertNode(D, InsertPos);
+ }
+
+ return D;
+}
+
+const LazyCompoundValData*
+BasicValueFactory::getLazyCompoundValData(const void *store,
+ const TypedRegion *region) {
+ llvm::FoldingSetNodeID ID;
+ LazyCompoundValData::Profile(ID, store, region);
+ void* InsertPos;
+
+ LazyCompoundValData *D =
+ LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!D) {
+ D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
+ new (D) LazyCompoundValData(store, region);
+ LazyCompoundValDataSet.InsertNode(D, InsertPos);
+ }
+
+ return D;
+}
+
+const llvm::APSInt*
+BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt& V1, const llvm::APSInt& V2) {
+
+ switch (Op) {
+ default:
+ assert (false && "Invalid Opcode.");
+
+ case BO_Mul:
+ return &getValue( V1 * V2 );
+
+ case BO_Div:
+ return &getValue( V1 / V2 );
+
+ case BO_Rem:
+ return &getValue( V1 % V2 );
+
+ case BO_Add:
+ return &getValue( V1 + V2 );
+
+ case BO_Sub:
+ return &getValue( V1 - V2 );
+
+ case BO_Shl: {
+
+ // FIXME: This logic should probably go higher up, where we can
+ // test these conditions symbolically.
+
+ // FIXME: Expand these checks to include all undefined behavior.
+
+ if (V2.isSigned() && V2.isNegative())
+ return NULL;
+
+ uint64_t Amt = V2.getZExtValue();
+
+ if (Amt > V1.getBitWidth())
+ return NULL;
+
+ return &getValue( V1.operator<<( (unsigned) Amt ));
+ }
+
+ case BO_Shr: {
+
+ // FIXME: This logic should probably go higher up, where we can
+ // test these conditions symbolically.
+
+ // FIXME: Expand these checks to include all undefined behavior.
+
+ if (V2.isSigned() && V2.isNegative())
+ return NULL;
+
+ uint64_t Amt = V2.getZExtValue();
+
+ if (Amt > V1.getBitWidth())
+ return NULL;
+
+ return &getValue( V1.operator>>( (unsigned) Amt ));
+ }
+
+ case BO_LT:
+ return &getTruthValue( V1 < V2 );
+
+ case BO_GT:
+ return &getTruthValue( V1 > V2 );
+
+ case BO_LE:
+ return &getTruthValue( V1 <= V2 );
+
+ case BO_GE:
+ return &getTruthValue( V1 >= V2 );
+
+ case BO_EQ:
+ return &getTruthValue( V1 == V2 );
+
+ case BO_NE:
+ return &getTruthValue( V1 != V2 );
+
+ // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
+
+ case BO_And:
+ return &getValue( V1 & V2 );
+
+ case BO_Or:
+ return &getValue( V1 | V2 );
+
+ case BO_Xor:
+ return &getValue( V1 ^ V2 );
+ }
+}
+
+
+const std::pair<SVal, uintptr_t>&
+BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
+
+ // Lazily create the folding set.
+ if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
+
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ V.Profile(ID);
+ ID.AddPointer((void*) Data);
+
+ PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
+
+ typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
+ FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!P) {
+ P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+ new (P) FoldNodeTy(std::make_pair(V, Data));
+ Map.InsertNode(P, InsertPos);
+ }
+
+ return P->getValue();
+}
+
+const std::pair<SVal, SVal>&
+BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
+
+ // Lazily create the folding set.
+ if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
+
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ V1.Profile(ID);
+ V2.Profile(ID);
+
+ PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
+
+ typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
+ FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!P) {
+ P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+ new (P) FoldNodeTy(std::make_pair(V1, V2));
+ Map.InsertNode(P, InsertPos);
+ }
+
+ return P->getValue();
+}
+
+const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
+ return &getPersistentSValWithData(X, 0).first;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp
new file mode 100644
index 0000000..ed52b6b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp
@@ -0,0 +1,86 @@
+//==- BlockCounter.h - ADT for counting block visits -------------*- 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 BlockCounter, an abstract data type used to count
+// the number of times a given block has been visited along a path
+// analyzed by CoreEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class CountKey {
+ const StackFrameContext *CallSite;
+ unsigned BlockID;
+
+public:
+ CountKey(const StackFrameContext *CS, unsigned ID)
+ : CallSite(CS), BlockID(ID) {}
+
+ bool operator==(const CountKey &RHS) const {
+ return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID);
+ }
+
+ bool operator<(const CountKey &RHS) const {
+ return (CallSite == RHS.CallSite) ? (BlockID < RHS.BlockID)
+ : (CallSite < RHS.CallSite);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(CallSite);
+ ID.AddInteger(BlockID);
+ }
+};
+
+}
+
+typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
+
+static inline CountMap GetMap(void* D) {
+ return CountMap(static_cast<CountMap::TreeTy*>(D));
+}
+
+static inline CountMap::Factory& GetFactory(void* F) {
+ return *static_cast<CountMap::Factory*>(F);
+}
+
+unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
+ unsigned BlockID) const {
+ CountMap M = GetMap(Data);
+ CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
+ return T ? *T : 0;
+}
+
+BlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
+ F = new CountMap::Factory(Alloc);
+}
+
+BlockCounter::Factory::~Factory() {
+ delete static_cast<CountMap::Factory*>(F);
+}
+
+BlockCounter
+BlockCounter::Factory::IncrementCount(BlockCounter BC,
+ const StackFrameContext *CallSite,
+ unsigned BlockID) {
+ return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
+ CountKey(CallSite, BlockID),
+ BC.getNumVisited(CallSite, BlockID)+1).getRoot());
+}
+
+BlockCounter
+BlockCounter::Factory::GetEmptyCounter() {
+ return BlockCounter(GetFactory(F).getEmptyMap().getRoot());
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
new file mode 100644
index 0000000..9a84045
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -0,0 +1,1896 @@
+// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- 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 BugReporter, a utility class for generating
+// PathDiagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <queue>
+
+using namespace clang;
+using namespace ento;
+
+BugReporterVisitor::~BugReporterVisitor() {}
+BugReporterContext::~BugReporterContext() {
+ for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I)
+ if ((*I)->isOwnedByReporterContext()) delete *I;
+}
+
+void BugReporterContext::addVisitor(BugReporterVisitor* visitor) {
+ if (!visitor)
+ return;
+
+ llvm::FoldingSetNodeID ID;
+ visitor->Profile(ID);
+ void *InsertPos;
+
+ if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
+ delete visitor;
+ return;
+ }
+
+ CallbacksSet.InsertNode(visitor, InsertPos);
+ Callbacks = F.add(visitor, Callbacks);
+}
+
+//===----------------------------------------------------------------------===//
+// Helper routines for walking the ExplodedGraph and fetching statements.
+//===----------------------------------------------------------------------===//
+
+static inline const Stmt* GetStmt(const ProgramPoint &P) {
+ if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P))
+ return SP->getStmt();
+ else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P))
+ return BE->getSrc()->getTerminator();
+
+ return 0;
+}
+
+static inline const ExplodedNode*
+GetPredecessorNode(const ExplodedNode* N) {
+ return N->pred_empty() ? NULL : *(N->pred_begin());
+}
+
+static inline const ExplodedNode*
+GetSuccessorNode(const ExplodedNode* N) {
+ return N->succ_empty() ? NULL : *(N->succ_begin());
+}
+
+static const Stmt* GetPreviousStmt(const ExplodedNode* N) {
+ for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N))
+ if (const Stmt *S = GetStmt(N->getLocation()))
+ return S;
+
+ return 0;
+}
+
+static const Stmt* GetNextStmt(const ExplodedNode* N) {
+ for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N))
+ if (const Stmt *S = GetStmt(N->getLocation())) {
+ // Check if the statement is '?' or '&&'/'||'. These are "merges",
+ // not actual statement points.
+ switch (S->getStmtClass()) {
+ case Stmt::ChooseExprClass:
+ case Stmt::BinaryConditionalOperatorClass: continue;
+ case Stmt::ConditionalOperatorClass: continue;
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
+ if (Op == BO_LAnd || Op == BO_LOr)
+ continue;
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Some expressions don't have locations.
+ if (S->getLocStart().isInvalid())
+ continue;
+
+ return S;
+ }
+
+ return 0;
+}
+
+static inline const Stmt*
+GetCurrentOrPreviousStmt(const ExplodedNode* N) {
+ if (const Stmt *S = GetStmt(N->getLocation()))
+ return S;
+
+ return GetPreviousStmt(N);
+}
+
+static inline const Stmt*
+GetCurrentOrNextStmt(const ExplodedNode* N) {
+ if (const Stmt *S = GetStmt(N->getLocation()))
+ return S;
+
+ return GetNextStmt(N);
+}
+
+//===----------------------------------------------------------------------===//
+// PathDiagnosticBuilder and its associated routines and helper objects.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::DenseMap<const ExplodedNode*,
+const ExplodedNode*> NodeBackMap;
+
+namespace {
+class NodeMapClosure : public BugReport::NodeResolver {
+ NodeBackMap& M;
+public:
+ NodeMapClosure(NodeBackMap *m) : M(*m) {}
+ ~NodeMapClosure() {}
+
+ const ExplodedNode* getOriginalNode(const ExplodedNode* N) {
+ NodeBackMap::iterator I = M.find(N);
+ return I == M.end() ? 0 : I->second;
+ }
+};
+
+class PathDiagnosticBuilder : public BugReporterContext {
+ BugReport *R;
+ PathDiagnosticClient *PDC;
+ llvm::OwningPtr<ParentMap> PM;
+ NodeMapClosure NMC;
+public:
+ PathDiagnosticBuilder(GRBugReporter &br,
+ BugReport *r, NodeBackMap *Backmap,
+ PathDiagnosticClient *pdc)
+ : BugReporterContext(br),
+ R(r), PDC(pdc), NMC(Backmap) {
+ addVisitor(R);
+ }
+
+ PathDiagnosticLocation ExecutionContinues(const ExplodedNode* N);
+
+ PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os,
+ const ExplodedNode* N);
+
+ Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
+
+ ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); }
+
+ const Stmt *getParent(const Stmt *S) {
+ return getParentMap().getParent(S);
+ }
+
+ virtual NodeMapClosure& getNodeResolver() { return NMC; }
+
+ PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
+
+ PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
+ return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
+ }
+
+ bool supportsLogicalOpControlFlow() const {
+ return PDC ? PDC->supportsLogicalOpControlFlow() : true;
+ }
+};
+} // end anonymous namespace
+
+PathDiagnosticLocation
+PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode* N) {
+ if (const Stmt *S = GetNextStmt(N))
+ return PathDiagnosticLocation(S, getSourceManager());
+
+ return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(),
+ getSourceManager());
+}
+
+PathDiagnosticLocation
+PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os,
+ const ExplodedNode* N) {
+
+ // Slow, but probably doesn't matter.
+ if (os.str().empty())
+ os << ' ';
+
+ const PathDiagnosticLocation &Loc = ExecutionContinues(N);
+
+ if (Loc.asStmt())
+ os << "Execution continues on line "
+ << getSourceManager().getInstantiationLineNumber(Loc.asLocation())
+ << '.';
+ else {
+ os << "Execution jumps to the end of the ";
+ const Decl *D = N->getLocationContext()->getDecl();
+ if (isa<ObjCMethodDecl>(D))
+ os << "method";
+ else if (isa<FunctionDecl>(D))
+ os << "function";
+ else {
+ assert(isa<BlockDecl>(D));
+ os << "anonymous block";
+ }
+ os << '.';
+ }
+
+ return Loc;
+}
+
+static bool IsNested(const Stmt *S, ParentMap &PM) {
+ if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
+ return true;
+
+ const Stmt *Parent = PM.getParentIgnoreParens(S);
+
+ if (Parent)
+ switch (Parent->getStmtClass()) {
+ case Stmt::ForStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::WhileStmtClass:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+PathDiagnosticLocation
+PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
+ assert(S && "Null Stmt* passed to getEnclosingStmtLocation");
+ ParentMap &P = getParentMap();
+ SourceManager &SMgr = getSourceManager();
+
+ while (IsNested(S, P)) {
+ const Stmt *Parent = P.getParentIgnoreParens(S);
+
+ if (!Parent)
+ break;
+
+ switch (Parent->getStmtClass()) {
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *B = cast<BinaryOperator>(Parent);
+ if (B->isLogicalOp())
+ return PathDiagnosticLocation(S, SMgr);
+ break;
+ }
+ case Stmt::CompoundStmtClass:
+ case Stmt::StmtExprClass:
+ return PathDiagnosticLocation(S, SMgr);
+ case Stmt::ChooseExprClass:
+ // Similar to '?' if we are referring to condition, just have the edge
+ // point to the entire choose expression.
+ if (cast<ChooseExpr>(Parent)->getCond() == S)
+ return PathDiagnosticLocation(Parent, SMgr);
+ else
+ return PathDiagnosticLocation(S, SMgr);
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ // For '?', if we are referring to condition, just have the edge point
+ // to the entire '?' expression.
+ if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
+ return PathDiagnosticLocation(Parent, SMgr);
+ else
+ return PathDiagnosticLocation(S, SMgr);
+ case Stmt::DoStmtClass:
+ return PathDiagnosticLocation(S, SMgr);
+ case Stmt::ForStmtClass:
+ if (cast<ForStmt>(Parent)->getBody() == S)
+ return PathDiagnosticLocation(S, SMgr);
+ break;
+ case Stmt::IfStmtClass:
+ if (cast<IfStmt>(Parent)->getCond() != S)
+ return PathDiagnosticLocation(S, SMgr);
+ break;
+ case Stmt::ObjCForCollectionStmtClass:
+ if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
+ return PathDiagnosticLocation(S, SMgr);
+ break;
+ case Stmt::WhileStmtClass:
+ if (cast<WhileStmt>(Parent)->getCond() != S)
+ return PathDiagnosticLocation(S, SMgr);
+ break;
+ default:
+ break;
+ }
+
+ S = Parent;
+ }
+
+ assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
+
+ // Special case: DeclStmts can appear in for statement declarations, in which
+ // case the ForStmt is the context.
+ if (isa<DeclStmt>(S)) {
+ if (const Stmt *Parent = P.getParent(S)) {
+ switch (Parent->getStmtClass()) {
+ case Stmt::ForStmtClass:
+ case Stmt::ObjCForCollectionStmtClass:
+ return PathDiagnosticLocation(Parent, SMgr);
+ default:
+ break;
+ }
+ }
+ }
+ else if (isa<BinaryOperator>(S)) {
+ // Special case: the binary operator represents the initialization
+ // code in a for statement (this can happen when the variable being
+ // initialized is an old variable.
+ if (const ForStmt *FS =
+ dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) {
+ if (FS->getInit() == S)
+ return PathDiagnosticLocation(FS, SMgr);
+ }
+ }
+
+ return PathDiagnosticLocation(S, SMgr);
+}
+
+//===----------------------------------------------------------------------===//
+// ScanNotableSymbols: closure-like callback for scanning Store bindings.
+//===----------------------------------------------------------------------===//
+
+static const VarDecl*
+GetMostRecentVarDeclBinding(const ExplodedNode* N,
+ GRStateManager& VMgr, SVal X) {
+
+ for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
+
+ ProgramPoint P = N->getLocation();
+
+ if (!isa<PostStmt>(P))
+ continue;
+
+ const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
+
+ if (!DR)
+ continue;
+
+ SVal Y = N->getState()->getSVal(DR);
+
+ if (X != Y)
+ continue;
+
+ const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
+
+ if (!VD)
+ continue;
+
+ return VD;
+ }
+
+ return 0;
+}
+
+namespace {
+class NotableSymbolHandler
+: public StoreManager::BindingsHandler {
+
+ SymbolRef Sym;
+ const GRState* PrevSt;
+ const Stmt* S;
+ GRStateManager& VMgr;
+ const ExplodedNode* Pred;
+ PathDiagnostic& PD;
+ BugReporter& BR;
+
+public:
+
+ NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s,
+ GRStateManager& vmgr, const ExplodedNode* pred,
+ PathDiagnostic& pd, BugReporter& br)
+ : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
+
+ bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
+ SVal V) {
+
+ SymbolRef ScanSym = V.getAsSymbol();
+
+ if (ScanSym != Sym)
+ return true;
+
+ // Check if the previous state has this binding.
+ SVal X = PrevSt->getSVal(loc::MemRegionVal(R));
+
+ if (X == V) // Same binding?
+ return true;
+
+ // Different binding. Only handle assignments for now. We don't pull
+ // this check out of the loop because we will eventually handle other
+ // cases.
+
+ VarDecl *VD = 0;
+
+ if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (!B->isAssignmentOp())
+ return true;
+
+ // What variable did we assign to?
+ DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
+
+ if (!DR)
+ return true;
+
+ VD = dyn_cast<VarDecl>(DR->getDecl());
+ }
+ else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+ // FIXME: Eventually CFGs won't have DeclStmts. Right now we
+ // assume that each DeclStmt has a single Decl. This invariant
+ // holds by contruction in the CFG.
+ VD = dyn_cast<VarDecl>(*DS->decl_begin());
+ }
+
+ if (!VD)
+ return true;
+
+ // What is the most recently referenced variable with this binding?
+ const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
+
+ if (!MostRecent)
+ return true;
+
+ // Create the diagnostic.
+ FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
+
+ if (Loc::isLocType(VD->getType())) {
+ std::string msg = "'" + std::string(VD->getNameAsString()) +
+ "' now aliases '" + MostRecent->getNameAsString() + "'";
+
+ PD.push_front(new PathDiagnosticEventPiece(L, msg));
+ }
+
+ return true;
+ }
+};
+}
+
+static void HandleNotableSymbol(const ExplodedNode* N,
+ const Stmt* S,
+ SymbolRef Sym, BugReporter& BR,
+ PathDiagnostic& PD) {
+
+ const ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin();
+ const GRState* PrevSt = Pred ? Pred->getState() : 0;
+
+ if (!PrevSt)
+ return;
+
+ // Look at the region bindings of the current state that map to the
+ // specified symbol. Are any of them not in the previous state?
+ GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
+ NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
+ cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
+}
+
+namespace {
+class ScanNotableSymbols
+: public StoreManager::BindingsHandler {
+
+ llvm::SmallSet<SymbolRef, 10> AlreadyProcessed;
+ const ExplodedNode* N;
+ const Stmt* S;
+ GRBugReporter& BR;
+ PathDiagnostic& PD;
+
+public:
+ ScanNotableSymbols(const ExplodedNode* n, const Stmt* s,
+ GRBugReporter& br, PathDiagnostic& pd)
+ : N(n), S(s), BR(br), PD(pd) {}
+
+ bool HandleBinding(StoreManager& SMgr, Store store,
+ const MemRegion* R, SVal V) {
+
+ SymbolRef ScanSym = V.getAsSymbol();
+
+ if (!ScanSym)
+ return true;
+
+ if (!BR.isNotable(ScanSym))
+ return true;
+
+ if (AlreadyProcessed.count(ScanSym))
+ return true;
+
+ AlreadyProcessed.insert(ScanSym);
+
+ HandleNotableSymbol(N, S, ScanSym, BR, PD);
+ return true;
+ }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// "Minimal" path diagnostic generation algorithm.
+//===----------------------------------------------------------------------===//
+
+static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM);
+
+static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
+ PathDiagnosticBuilder &PDB,
+ const ExplodedNode *N) {
+
+ SourceManager& SMgr = PDB.getSourceManager();
+ const ExplodedNode* NextNode = N->pred_empty()
+ ? NULL : *(N->pred_begin());
+ while (NextNode) {
+ N = NextNode;
+ NextNode = GetPredecessorNode(N);
+
+ ProgramPoint P = N->getLocation();
+
+ if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock* Src = BE->getSrc();
+ const CFGBlock* Dst = BE->getDst();
+ const Stmt* T = Src->getTerminator();
+
+ if (!T)
+ continue;
+
+ FullSourceLoc Start(T->getLocStart(), SMgr);
+
+ switch (T->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass: {
+ const Stmt* S = GetNextStmt(N);
+
+ if (!S)
+ continue;
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
+
+ os << "Control jumps to line "
+ << End.asLocation().getInstantiationLineNumber();
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ break;
+ }
+
+ case Stmt::SwitchStmtClass: {
+ // Figure out what case arm we took.
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ if (const Stmt* S = Dst->getLabel()) {
+ PathDiagnosticLocation End(S, SMgr);
+
+ switch (S->getStmtClass()) {
+ default:
+ os << "No cases match in the switch statement. "
+ "Control jumps to line "
+ << End.asLocation().getInstantiationLineNumber();
+ break;
+ case Stmt::DefaultStmtClass:
+ os << "Control jumps to the 'default' case at line "
+ << End.asLocation().getInstantiationLineNumber();
+ break;
+
+ case Stmt::CaseStmtClass: {
+ os << "Control jumps to 'case ";
+ const CaseStmt* Case = cast<CaseStmt>(S);
+ const Expr* LHS = Case->getLHS()->IgnoreParenCasts();
+
+ // Determine if it is an enum.
+ bool GetRawInt = true;
+
+ if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
+ // FIXME: Maybe this should be an assertion. Are there cases
+ // were it is not an EnumConstantDecl?
+ const EnumConstantDecl* D =
+ dyn_cast<EnumConstantDecl>(DR->getDecl());
+
+ if (D) {
+ GetRawInt = false;
+ os << D;
+ }
+ }
+
+ if (GetRawInt)
+ os << LHS->EvaluateAsInt(PDB.getASTContext());
+
+ os << ":' at line "
+ << End.asLocation().getInstantiationLineNumber();
+ break;
+ }
+ }
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ os << "'Default' branch taken. ";
+ const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+
+ break;
+ }
+
+ case Stmt::BreakStmtClass:
+ case Stmt::ContinueStmtClass: {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ break;
+ }
+
+ // Determine control-flow for ternary '?'.
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass: {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "'?' condition is ";
+
+ if (*(Src->succ_begin()+1) == Dst)
+ os << "false";
+ else
+ os << "true";
+
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ break;
+ }
+
+ // Determine control-flow for short-circuited '&&' and '||'.
+ case Stmt::BinaryOperatorClass: {
+ if (!PDB.supportsLogicalOpControlFlow())
+ break;
+
+ const BinaryOperator *B = cast<BinaryOperator>(T);
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Left side of '";
+
+ if (B->getOpcode() == BO_LAnd) {
+ os << "&&" << "' is ";
+
+ if (*(Src->succ_begin()+1) == Dst) {
+ os << "false";
+ PathDiagnosticLocation End(B->getLHS(), SMgr);
+ PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ os << "true";
+ PathDiagnosticLocation Start(B->getLHS(), SMgr);
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ }
+ else {
+ assert(B->getOpcode() == BO_LOr);
+ os << "||" << "' is ";
+
+ if (*(Src->succ_begin()+1) == Dst) {
+ os << "false";
+ PathDiagnosticLocation Start(B->getLHS(), SMgr);
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ os << "true";
+ PathDiagnosticLocation End(B->getLHS(), SMgr);
+ PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ }
+
+ break;
+ }
+
+ case Stmt::DoStmtClass: {
+ if (*(Src->succ_begin()) == Dst) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "Loop condition is true. ";
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
+
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Loop condition is false. Exiting loop"));
+ }
+
+ break;
+ }
+
+ case Stmt::WhileStmtClass:
+ case Stmt::ForStmtClass: {
+ if (*(Src->succ_begin()+1) == Dst) {
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "Loop condition is false. ";
+ PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ os.str()));
+ }
+ else {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Loop condition is true. Entering loop body"));
+ }
+
+ break;
+ }
+
+ case Stmt::IfStmtClass: {
+ PathDiagnosticLocation End = PDB.ExecutionContinues(N);
+
+ if (const Stmt *S = End.asStmt())
+ End = PDB.getEnclosingStmtLocation(S);
+
+ if (*(Src->succ_begin()+1) == Dst)
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Taking false branch"));
+ else
+ PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
+ "Taking true branch"));
+
+ break;
+ }
+ }
+ }
+
+ if (NextNode) {
+ for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
+ E = PDB.visitor_end(); I!=E; ++I) {
+ if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB))
+ PD.push_front(p);
+ }
+ }
+
+ if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
+ // Scan the region bindings, and see if a "notable" symbol has a new
+ // lval binding.
+ ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
+ PDB.getStateManager().iterBindings(N->getState(), SNS);
+ }
+ }
+
+ // After constructing the full PathDiagnostic, do a pass over it to compact
+ // PathDiagnosticPieces that occur within a macro.
+ CompactPathDiagnostic(PD, PDB.getSourceManager());
+}
+
+//===----------------------------------------------------------------------===//
+// "Extensive" PathDiagnostic generation.
+//===----------------------------------------------------------------------===//
+
+static bool IsControlFlowExpr(const Stmt *S) {
+ const Expr *E = dyn_cast<Expr>(S);
+
+ if (!E)
+ return false;
+
+ E = E->IgnoreParenCasts();
+
+ if (isa<AbstractConditionalOperator>(E))
+ return true;
+
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E))
+ if (B->isLogicalOp())
+ return true;
+
+ return false;
+}
+
+namespace {
+class ContextLocation : public PathDiagnosticLocation {
+ bool IsDead;
+public:
+ ContextLocation(const PathDiagnosticLocation &L, bool isdead = false)
+ : PathDiagnosticLocation(L), IsDead(isdead) {}
+
+ void markDead() { IsDead = true; }
+ bool isDead() const { return IsDead; }
+};
+
+class EdgeBuilder {
+ std::vector<ContextLocation> CLocs;
+ typedef std::vector<ContextLocation>::iterator iterator;
+ PathDiagnostic &PD;
+ PathDiagnosticBuilder &PDB;
+ PathDiagnosticLocation PrevLoc;
+
+ bool IsConsumedExpr(const PathDiagnosticLocation &L);
+
+ bool containsLocation(const PathDiagnosticLocation &Container,
+ const PathDiagnosticLocation &Containee);
+
+ PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
+
+ PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
+ bool firstCharOnly = false) {
+ if (const Stmt *S = L.asStmt()) {
+ const Stmt *Original = S;
+ while (1) {
+ // Adjust the location for some expressions that are best referenced
+ // by one of their subexpressions.
+ switch (S->getStmtClass()) {
+ default:
+ break;
+ case Stmt::ParenExprClass:
+ S = cast<ParenExpr>(S)->IgnoreParens();
+ firstCharOnly = true;
+ continue;
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ S = cast<AbstractConditionalOperator>(S)->getCond();
+ firstCharOnly = true;
+ continue;
+ case Stmt::ChooseExprClass:
+ S = cast<ChooseExpr>(S)->getCond();
+ firstCharOnly = true;
+ continue;
+ case Stmt::BinaryOperatorClass:
+ S = cast<BinaryOperator>(S)->getLHS();
+ firstCharOnly = true;
+ continue;
+ }
+
+ break;
+ }
+
+ if (S != Original)
+ L = PathDiagnosticLocation(S, L.getManager());
+ }
+
+ if (firstCharOnly)
+ L = PathDiagnosticLocation(L.asLocation());
+
+ return L;
+ }
+
+ void popLocation() {
+ if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) {
+ // For contexts, we only one the first character as the range.
+ rawAddEdge(cleanUpLocation(CLocs.back(), true));
+ }
+ CLocs.pop_back();
+ }
+
+public:
+ EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
+ : PD(pd), PDB(pdb) {
+
+ // If the PathDiagnostic already has pieces, add the enclosing statement
+ // of the first piece as a context as well.
+ if (!PD.empty()) {
+ PrevLoc = PD.begin()->getLocation();
+
+ if (const Stmt *S = PrevLoc.asStmt())
+ addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
+ }
+ }
+
+ ~EdgeBuilder() {
+ while (!CLocs.empty()) popLocation();
+
+ // Finally, add an initial edge from the start location of the first
+ // statement (if it doesn't already exist).
+ // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
+ if (const CompoundStmt *CS =
+ dyn_cast_or_null<CompoundStmt>(PDB.getCodeDecl().getBody()))
+ if (!CS->body_empty()) {
+ SourceLocation Loc = (*CS->body_begin())->getLocStart();
+ rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
+ }
+
+ }
+
+ void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
+
+ void rawAddEdge(PathDiagnosticLocation NewLoc);
+
+ void addContext(const Stmt *S);
+ void addExtendedContext(const Stmt *S);
+};
+} // end anonymous namespace
+
+
+PathDiagnosticLocation
+EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
+ if (const Stmt *S = L.asStmt()) {
+ if (IsControlFlowExpr(S))
+ return L;
+
+ return PDB.getEnclosingStmtLocation(S);
+ }
+
+ return L;
+}
+
+bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
+ const PathDiagnosticLocation &Containee) {
+
+ if (Container == Containee)
+ return true;
+
+ if (Container.asDecl())
+ return true;
+
+ if (const Stmt *S = Containee.asStmt())
+ if (const Stmt *ContainerS = Container.asStmt()) {
+ while (S) {
+ if (S == ContainerS)
+ return true;
+ S = PDB.getParent(S);
+ }
+ return false;
+ }
+
+ // Less accurate: compare using source ranges.
+ SourceRange ContainerR = Container.asRange();
+ SourceRange ContaineeR = Containee.asRange();
+
+ SourceManager &SM = PDB.getSourceManager();
+ SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin());
+ SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd());
+ SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin());
+ SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd());
+
+ unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg);
+ unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd);
+ unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg);
+ unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd);
+
+ assert(ContainerBegLine <= ContainerEndLine);
+ assert(ContaineeBegLine <= ContaineeEndLine);
+
+ return (ContainerBegLine <= ContaineeBegLine &&
+ ContainerEndLine >= ContaineeEndLine &&
+ (ContainerBegLine != ContaineeBegLine ||
+ SM.getInstantiationColumnNumber(ContainerRBeg) <=
+ SM.getInstantiationColumnNumber(ContaineeRBeg)) &&
+ (ContainerEndLine != ContaineeEndLine ||
+ SM.getInstantiationColumnNumber(ContainerREnd) >=
+ SM.getInstantiationColumnNumber(ContainerREnd)));
+}
+
+void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
+ if (!PrevLoc.isValid()) {
+ PrevLoc = NewLoc;
+ return;
+ }
+
+ const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc);
+ const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc);
+
+ if (NewLocClean.asLocation() == PrevLocClean.asLocation())
+ return;
+
+ // FIXME: Ignore intra-macro edges for now.
+ if (NewLocClean.asLocation().getInstantiationLoc() ==
+ PrevLocClean.asLocation().getInstantiationLoc())
+ return;
+
+ PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
+ PrevLoc = NewLoc;
+}
+
+void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
+
+ if (!alwaysAdd && NewLoc.asLocation().isMacroID())
+ return;
+
+ const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
+
+ while (!CLocs.empty()) {
+ ContextLocation &TopContextLoc = CLocs.back();
+
+ // Is the top location context the same as the one for the new location?
+ if (TopContextLoc == CLoc) {
+ if (alwaysAdd) {
+ if (IsConsumedExpr(TopContextLoc) &&
+ !IsControlFlowExpr(TopContextLoc.asStmt()))
+ TopContextLoc.markDead();
+
+ rawAddEdge(NewLoc);
+ }
+
+ return;
+ }
+
+ if (containsLocation(TopContextLoc, CLoc)) {
+ if (alwaysAdd) {
+ rawAddEdge(NewLoc);
+
+ if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) {
+ CLocs.push_back(ContextLocation(CLoc, true));
+ return;
+ }
+ }
+
+ CLocs.push_back(CLoc);
+ return;
+ }
+
+ // Context does not contain the location. Flush it.
+ popLocation();
+ }
+
+ // If we reach here, there is no enclosing context. Just add the edge.
+ rawAddEdge(NewLoc);
+}
+
+bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) {
+ if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt()))
+ return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X);
+
+ return false;
+}
+
+void EdgeBuilder::addExtendedContext(const Stmt *S) {
+ if (!S)
+ return;
+
+ const Stmt *Parent = PDB.getParent(S);
+ while (Parent) {
+ if (isa<CompoundStmt>(Parent))
+ Parent = PDB.getParent(Parent);
+ else
+ break;
+ }
+
+ if (Parent) {
+ switch (Parent->getStmtClass()) {
+ case Stmt::DoStmtClass:
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ addContext(Parent);
+ default:
+ break;
+ }
+ }
+
+ addContext(S);
+}
+
+void EdgeBuilder::addContext(const Stmt *S) {
+ if (!S)
+ return;
+
+ PathDiagnosticLocation L(S, PDB.getSourceManager());
+
+ while (!CLocs.empty()) {
+ const PathDiagnosticLocation &TopContextLoc = CLocs.back();
+
+ // Is the top location context the same as the one for the new location?
+ if (TopContextLoc == L)
+ return;
+
+ if (containsLocation(TopContextLoc, L)) {
+ CLocs.push_back(L);
+ return;
+ }
+
+ // Context does not contain the location. Flush it.
+ popLocation();
+ }
+
+ CLocs.push_back(L);
+}
+
+static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
+ PathDiagnosticBuilder &PDB,
+ const ExplodedNode *N) {
+ EdgeBuilder EB(PD, PDB);
+
+ const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
+ while (NextNode) {
+ N = NextNode;
+ NextNode = GetPredecessorNode(N);
+ ProgramPoint P = N->getLocation();
+
+ do {
+ // Block edges.
+ if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock &Blk = *BE->getSrc();
+ const Stmt *Term = Blk.getTerminator();
+
+ // Are we jumping to the head of a loop? Add a special diagnostic.
+ if (const Stmt *Loop = BE->getDst()->getLoopTarget()) {
+ PathDiagnosticLocation L(Loop, PDB.getSourceManager());
+ const CompoundStmt *CS = NULL;
+
+ if (!Term) {
+ if (const ForStmt *FS = dyn_cast<ForStmt>(Loop))
+ CS = dyn_cast<CompoundStmt>(FS->getBody());
+ else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop))
+ CS = dyn_cast<CompoundStmt>(WS->getBody());
+ }
+
+ PathDiagnosticEventPiece *p =
+ new PathDiagnosticEventPiece(L,
+ "Looping back to the head of the loop");
+
+ EB.addEdge(p->getLocation(), true);
+ PD.push_front(p);
+
+ if (CS) {
+ PathDiagnosticLocation BL(CS->getRBracLoc(),
+ PDB.getSourceManager());
+ BL = PathDiagnosticLocation(BL.asLocation());
+ EB.addEdge(BL);
+ }
+ }
+
+ if (Term)
+ EB.addContext(Term);
+
+ break;
+ }
+
+ if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+ if (CFGStmt S = BE->getFirstElement().getAs<CFGStmt>()) {
+ if (IsControlFlowExpr(S)) {
+ // Add the proper context for '&&', '||', and '?'.
+ EB.addContext(S);
+ }
+ else
+ EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
+ }
+
+ break;
+ }
+ } while (0);
+
+ if (!NextNode)
+ continue;
+
+ for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
+ E = PDB.visitor_end(); I!=E; ++I) {
+ if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB)) {
+ const PathDiagnosticLocation &Loc = p->getLocation();
+ EB.addEdge(Loc, true);
+ PD.push_front(p);
+ if (const Stmt *S = Loc.asStmt())
+ EB.addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt());
+ }
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for BugType and subclasses.
+//===----------------------------------------------------------------------===//
+BugType::~BugType() {
+ // Free up the equivalence class objects. Observe that we get a pointer to
+ // the object first before incrementing the iterator, as destroying the
+ // node before doing so means we will read from freed memory.
+ for (iterator I = begin(), E = end(); I !=E; ) {
+ BugReportEquivClass *EQ = &*I;
+ ++I;
+ delete EQ;
+ }
+}
+void BugType::FlushReports(BugReporter &BR) {}
+
+//===----------------------------------------------------------------------===//
+// Methods for BugReport and subclasses.
+//===----------------------------------------------------------------------===//
+BugReport::~BugReport() {}
+RangedBugReport::~RangedBugReport() {}
+
+const Stmt* BugReport::getStmt() const {
+ ProgramPoint ProgP = ErrorNode->getLocation();
+ const Stmt *S = NULL;
+
+ if (BlockEntrance* BE = dyn_cast<BlockEntrance>(&ProgP)) {
+ CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
+ if (BE->getBlock() == &Exit)
+ S = GetPreviousStmt(ErrorNode);
+ }
+ if (!S)
+ S = GetStmt(ProgP);
+
+ return S;
+}
+
+PathDiagnosticPiece*
+BugReport::getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* EndPathNode) {
+
+ const Stmt* S = getStmt();
+
+ if (!S)
+ return NULL;
+
+ BugReport::ranges_iterator Beg, End;
+ llvm::tie(Beg, End) = getRanges();
+ PathDiagnosticLocation L(S, BRC.getSourceManager());
+
+ // Only add the statement itself as a range if we didn't specify any
+ // special ranges for this report.
+ PathDiagnosticPiece* P = new PathDiagnosticEventPiece(L, getDescription(),
+ Beg == End);
+
+ for (; Beg != End; ++Beg)
+ P->addRange(*Beg);
+
+ return P;
+}
+
+std::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
+BugReport::getRanges() const {
+ if (const Expr* E = dyn_cast_or_null<Expr>(getStmt())) {
+ R = E->getSourceRange();
+ assert(R.isValid());
+ return std::make_pair(&R, &R+1);
+ }
+ else
+ return std::make_pair(ranges_iterator(), ranges_iterator());
+}
+
+SourceLocation BugReport::getLocation() const {
+ if (ErrorNode)
+ if (const Stmt* S = GetCurrentOrPreviousStmt(ErrorNode)) {
+ // For member expressions, return the location of the '.' or '->'.
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
+ return ME->getMemberLoc();
+ // For binary operators, return the location of the operator.
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ return B->getOperatorLoc();
+
+ return S->getLocStart();
+ }
+
+ return FullSourceLoc();
+}
+
+PathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode* N,
+ const ExplodedNode* PrevN,
+ BugReporterContext &BRC) {
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods for BugReporter and subclasses.
+//===----------------------------------------------------------------------===//
+
+BugReportEquivClass::~BugReportEquivClass() {
+ for (iterator I=begin(), E=end(); I!=E; ++I) delete *I;
+}
+
+GRBugReporter::~GRBugReporter() { }
+BugReporterData::~BugReporterData() {}
+
+ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
+
+GRStateManager&
+GRBugReporter::getStateManager() { return Eng.getStateManager(); }
+
+BugReporter::~BugReporter() { FlushReports(); }
+
+void BugReporter::FlushReports() {
+ if (BugTypes.isEmpty())
+ return;
+
+ // First flush the warnings for each BugType. This may end up creating new
+ // warnings and new BugTypes. Because ImmutableSet is a functional data
+ // structure, we do not need to worry about the iterators being invalidated.
+ for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
+ const_cast<BugType*>(*I)->FlushReports(*this);
+
+ // Iterate through BugTypes a second time. BugTypes may have been updated
+ // with new BugType objects and new warnings.
+ for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) {
+ BugType *BT = const_cast<BugType*>(*I);
+
+ typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
+ SetTy& EQClasses = BT->EQClasses;
+
+ for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
+ BugReportEquivClass& EQ = *EI;
+ FlushReport(EQ);
+ }
+
+ // Delete the BugType object.
+ delete BT;
+ }
+
+ // Remove all references to the BugType objects.
+ BugTypes = F.getEmptySet();
+}
+
+//===----------------------------------------------------------------------===//
+// PathDiagnostics generation.
+//===----------------------------------------------------------------------===//
+
+static std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
+ std::pair<ExplodedNode*, unsigned> >
+MakeReportGraph(const ExplodedGraph* G,
+ llvm::SmallVectorImpl<const ExplodedNode*> &nodes) {
+
+ // Create the trimmed graph. It will contain the shortest paths from the
+ // error nodes to the root. In the new graph we should only have one
+ // error node unless there are two or more error nodes with the same minimum
+ // path length.
+ ExplodedGraph* GTrim;
+ InterExplodedGraphMap* NMap;
+
+ llvm::DenseMap<const void*, const void*> InverseMap;
+ llvm::tie(GTrim, NMap) = G->Trim(nodes.data(), nodes.data() + nodes.size(),
+ &InverseMap);
+
+ // Create owning pointers for GTrim and NMap just to ensure that they are
+ // released when this function exists.
+ llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim);
+ llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap);
+
+ // Find the (first) error node in the trimmed graph. We just need to consult
+ // the node map (NMap) which maps from nodes in the original graph to nodes
+ // in the new graph.
+
+ std::queue<const ExplodedNode*> WS;
+ typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy;
+ IndexMapTy IndexMap;
+
+ for (unsigned nodeIndex = 0 ; nodeIndex < nodes.size(); ++nodeIndex) {
+ const ExplodedNode *originalNode = nodes[nodeIndex];
+ if (const ExplodedNode *N = NMap->getMappedNode(originalNode)) {
+ WS.push(N);
+ IndexMap[originalNode] = nodeIndex;
+ }
+ }
+
+ assert(!WS.empty() && "No error node found in the trimmed graph.");
+
+ // Create a new (third!) graph with a single path. This is the graph
+ // that will be returned to the caller.
+ ExplodedGraph *GNew = new ExplodedGraph();
+
+ // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS
+ // to the root node, and then construct a new graph that contains only
+ // a single path.
+ llvm::DenseMap<const void*,unsigned> Visited;
+
+ unsigned cnt = 0;
+ const ExplodedNode* Root = 0;
+
+ while (!WS.empty()) {
+ const ExplodedNode* Node = WS.front();
+ WS.pop();
+
+ if (Visited.find(Node) != Visited.end())
+ continue;
+
+ Visited[Node] = cnt++;
+
+ if (Node->pred_empty()) {
+ Root = Node;
+ break;
+ }
+
+ for (ExplodedNode::const_pred_iterator I=Node->pred_begin(),
+ E=Node->pred_end(); I!=E; ++I)
+ WS.push(*I);
+ }
+
+ assert(Root);
+
+ // Now walk from the root down the BFS path, always taking the successor
+ // with the lowest number.
+ ExplodedNode *Last = 0, *First = 0;
+ NodeBackMap *BM = new NodeBackMap();
+ unsigned NodeIndex = 0;
+
+ for ( const ExplodedNode *N = Root ;;) {
+ // Lookup the number associated with the current node.
+ llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
+ assert(I != Visited.end());
+
+ // Create the equivalent node in the new graph with the same state
+ // and location.
+ ExplodedNode* NewN = GNew->getNode(N->getLocation(), N->getState());
+
+ // Store the mapping to the original node.
+ llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
+ assert(IMitr != InverseMap.end() && "No mapping to original node.");
+ (*BM)[NewN] = (const ExplodedNode*) IMitr->second;
+
+ // Link up the new node with the previous node.
+ if (Last)
+ NewN->addPredecessor(Last, *GNew);
+
+ Last = NewN;
+
+ // Are we at the final node?
+ IndexMapTy::iterator IMI =
+ IndexMap.find((const ExplodedNode*)(IMitr->second));
+ if (IMI != IndexMap.end()) {
+ First = NewN;
+ NodeIndex = IMI->second;
+ break;
+ }
+
+ // Find the next successor node. We choose the node that is marked
+ // with the lowest DFS number.
+ ExplodedNode::const_succ_iterator SI = N->succ_begin();
+ ExplodedNode::const_succ_iterator SE = N->succ_end();
+ N = 0;
+
+ for (unsigned MinVal = 0; SI != SE; ++SI) {
+
+ I = Visited.find(*SI);
+
+ if (I == Visited.end())
+ continue;
+
+ if (!N || I->second < MinVal) {
+ N = *SI;
+ MinVal = I->second;
+ }
+ }
+
+ assert(N);
+ }
+
+ assert(First);
+
+ return std::make_pair(std::make_pair(GNew, BM),
+ std::make_pair(First, NodeIndex));
+}
+
+/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
+/// and collapses PathDiagosticPieces that are expanded by macros.
+static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
+ typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> >
+ MacroStackTy;
+
+ typedef std::vector<PathDiagnosticPiece*>
+ PiecesTy;
+
+ MacroStackTy MacroStack;
+ PiecesTy Pieces;
+
+ for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) {
+ // Get the location of the PathDiagnosticPiece.
+ const FullSourceLoc Loc = I->getLocation().asLocation();
+
+ // Determine the instantiation location, which is the location we group
+ // related PathDiagnosticPieces.
+ SourceLocation InstantiationLoc = Loc.isMacroID() ?
+ SM.getInstantiationLoc(Loc) :
+ SourceLocation();
+
+ if (Loc.isFileID()) {
+ MacroStack.clear();
+ Pieces.push_back(&*I);
+ continue;
+ }
+
+ assert(Loc.isMacroID());
+
+ // Is the PathDiagnosticPiece within the same macro group?
+ if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
+ MacroStack.back().first->push_back(&*I);
+ continue;
+ }
+
+ // We aren't in the same group. Are we descending into a new macro
+ // or are part of an old one?
+ PathDiagnosticMacroPiece *MacroGroup = 0;
+
+ SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
+ SM.getInstantiationLoc(Loc) :
+ SourceLocation();
+
+ // Walk the entire macro stack.
+ while (!MacroStack.empty()) {
+ if (InstantiationLoc == MacroStack.back().second) {
+ MacroGroup = MacroStack.back().first;
+ break;
+ }
+
+ if (ParentInstantiationLoc == MacroStack.back().second) {
+ MacroGroup = MacroStack.back().first;
+ break;
+ }
+
+ MacroStack.pop_back();
+ }
+
+ if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
+ // Create a new macro group and add it to the stack.
+ PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc);
+
+ if (MacroGroup)
+ MacroGroup->push_back(NewGroup);
+ else {
+ assert(InstantiationLoc.isFileID());
+ Pieces.push_back(NewGroup);
+ }
+
+ MacroGroup = NewGroup;
+ MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
+ }
+
+ // Finally, add the PathDiagnosticPiece to the group.
+ MacroGroup->push_back(&*I);
+ }
+
+ // Now take the pieces and construct a new PathDiagnostic.
+ PD.resetPath(false);
+
+ for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
+ if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I))
+ if (!MP->containsEvent()) {
+ delete MP;
+ continue;
+ }
+
+ PD.push_back(*I);
+ }
+}
+
+void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
+ llvm::SmallVectorImpl<BugReport *> &bugReports) {
+
+ assert(!bugReports.empty());
+ llvm::SmallVector<const ExplodedNode *, 10> errorNodes;
+ for (llvm::SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
+ E = bugReports.end(); I != E; ++I) {
+ errorNodes.push_back((*I)->getErrorNode());
+ }
+
+ // Construct a new graph that contains only a single path from the error
+ // node to a root.
+ const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
+ std::pair<ExplodedNode*, unsigned> >&
+ GPair = MakeReportGraph(&getGraph(), errorNodes);
+
+ // Find the BugReport with the original location.
+ assert(GPair.second.second < bugReports.size());
+ BugReport *R = bugReports[GPair.second.second];
+ assert(R && "No original report found for sliced graph.");
+
+ llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first);
+ llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
+ const ExplodedNode *N = GPair.second.first;
+
+ // Start building the path diagnostic...
+ PathDiagnosticBuilder PDB(*this, R, BackMap.get(), getPathDiagnosticClient());
+
+ if (PathDiagnosticPiece* Piece = R->getEndPath(PDB, N))
+ PD.push_back(Piece);
+ else
+ return;
+
+ // Register node visitors.
+ R->registerInitialVisitors(PDB, N);
+ bugreporter::registerNilReceiverVisitor(PDB);
+
+ switch (PDB.getGenerationScheme()) {
+ case PathDiagnosticClient::Extensive:
+ GenerateExtensivePathDiagnostic(PD, PDB, N);
+ break;
+ case PathDiagnosticClient::Minimal:
+ GenerateMinimalPathDiagnostic(PD, PDB, N);
+ break;
+ }
+}
+
+void BugReporter::Register(BugType *BT) {
+ BugTypes = F.add(BugTypes, BT);
+}
+
+void BugReporter::EmitReport(BugReport* R) {
+ // Compute the bug report's hash to determine its equivalence class.
+ llvm::FoldingSetNodeID ID;
+ R->Profile(ID);
+
+ // Lookup the equivance class. If there isn't one, create it.
+ BugType& BT = R->getBugType();
+ Register(&BT);
+ void *InsertPos;
+ BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!EQ) {
+ EQ = new BugReportEquivClass(R);
+ BT.EQClasses.InsertNode(EQ, InsertPos);
+ }
+ else
+ EQ->AddReport(R);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Emitting reports in equivalence classes.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct FRIEC_WLItem {
+ const ExplodedNode *N;
+ ExplodedNode::const_succ_iterator I, E;
+
+ FRIEC_WLItem(const ExplodedNode *n)
+ : N(n), I(N->succ_begin()), E(N->succ_end()) {}
+};
+}
+
+static BugReport *
+FindReportInEquivalenceClass(BugReportEquivClass& EQ,
+ llvm::SmallVectorImpl<BugReport*> &bugReports) {
+
+ BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
+ assert(I != E);
+ BugReport *R = *I;
+ BugType& BT = R->getBugType();
+
+ // If we don't need to suppress any of the nodes because they are
+ // post-dominated by a sink, simply add all the nodes in the equivalence class
+ // to 'Nodes'. Any of the reports will serve as a "representative" report.
+ if (!BT.isSuppressOnSink()) {
+ for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
+ const ExplodedNode* N = I->getErrorNode();
+ if (N) {
+ R = *I;
+ bugReports.push_back(R);
+ }
+ }
+ return R;
+ }
+
+ // For bug reports that should be suppressed when all paths are post-dominated
+ // by a sink node, iterate through the reports in the equivalence class
+ // until we find one that isn't post-dominated (if one exists). We use a
+ // DFS traversal of the ExplodedGraph to find a non-sink node. We could write
+ // this as a recursive function, but we don't want to risk blowing out the
+ // stack for very long paths.
+ BugReport *exampleReport = 0;
+
+ for (; I != E; ++I) {
+ R = *I;
+ const ExplodedNode *errorNode = R->getErrorNode();
+
+ if (!errorNode)
+ continue;
+ if (errorNode->isSink()) {
+ assert(false &&
+ "BugType::isSuppressSink() should not be 'true' for sink end nodes");
+ return 0;
+ }
+ // No successors? By definition this nodes isn't post-dominated by a sink.
+ if (errorNode->succ_empty()) {
+ bugReports.push_back(R);
+ if (!exampleReport)
+ exampleReport = R;
+ continue;
+ }
+
+ // At this point we know that 'N' is not a sink and it has at least one
+ // successor. Use a DFS worklist to find a non-sink end-of-path node.
+ typedef FRIEC_WLItem WLItem;
+ typedef llvm::SmallVector<WLItem, 10> DFSWorkList;
+ llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
+
+ DFSWorkList WL;
+ WL.push_back(errorNode);
+ Visited[errorNode] = 1;
+
+ while (!WL.empty()) {
+ WLItem &WI = WL.back();
+ assert(!WI.N->succ_empty());
+
+ for (; WI.I != WI.E; ++WI.I) {
+ const ExplodedNode *Succ = *WI.I;
+ // End-of-path node?
+ if (Succ->succ_empty()) {
+ // If we found an end-of-path node that is not a sink.
+ if (!Succ->isSink()) {
+ bugReports.push_back(R);
+ if (!exampleReport)
+ exampleReport = R;
+ WL.clear();
+ break;
+ }
+ // Found a sink? Continue on to the next successor.
+ continue;
+ }
+ // Mark the successor as visited. If it hasn't been explored,
+ // enqueue it to the DFS worklist.
+ unsigned &mark = Visited[Succ];
+ if (!mark) {
+ mark = 1;
+ WL.push_back(Succ);
+ break;
+ }
+ }
+
+ // The worklist may have been cleared at this point. First
+ // check if it is empty before checking the last item.
+ if (!WL.empty() && &WL.back() == &WI)
+ WL.pop_back();
+ }
+ }
+
+ // ExampleReport will be NULL if all the nodes in the equivalence class
+ // were post-dominated by sinks.
+ return exampleReport;
+}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticCache. This is a hack to cache analyzer diagnostics. It
+// uses global state, which eventually should go elsewhere.
+//===----------------------------------------------------------------------===//
+namespace {
+class DiagCacheItem : public llvm::FoldingSetNode {
+ llvm::FoldingSetNodeID ID;
+public:
+ DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
+ ID.AddString(R->getBugType().getName());
+ ID.AddString(R->getBugType().getCategory());
+ ID.AddString(R->getDescription());
+ ID.AddInteger(R->getLocation().getRawEncoding());
+ PD->Profile(ID);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &id) {
+ id = ID;
+ }
+
+ llvm::FoldingSetNodeID &getID() { return ID; }
+};
+}
+
+static bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
+ // FIXME: Eventually this diagnostic cache should reside in something
+ // like AnalysisManager instead of being a static variable. This is
+ // really unsafe in the long term.
+ typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache;
+ static DiagnosticCache DC;
+
+ void *InsertPos;
+ DiagCacheItem *Item = new DiagCacheItem(R, PD);
+
+ if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) {
+ delete Item;
+ return true;
+ }
+
+ DC.InsertNode(Item, InsertPos);
+ return false;
+}
+
+void BugReporter::FlushReport(BugReportEquivClass& EQ) {
+ llvm::SmallVector<BugReport*, 10> bugReports;
+ BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
+ if (!exampleReport)
+ return;
+
+ PathDiagnosticClient* PD = getPathDiagnosticClient();
+
+ // FIXME: Make sure we use the 'R' for the path that was actually used.
+ // Probably doesn't make a difference in practice.
+ BugType& BT = exampleReport->getBugType();
+
+ llvm::OwningPtr<PathDiagnostic>
+ D(new PathDiagnostic(exampleReport->getBugType().getName(),
+ !PD || PD->useVerboseDescription()
+ ? exampleReport->getDescription()
+ : exampleReport->getShortDescription(),
+ BT.getCategory()));
+
+ if (!bugReports.empty())
+ GeneratePathDiagnostic(*D.get(), bugReports);
+
+ if (IsCachedDiagnostic(exampleReport, D.get()))
+ return;
+
+ // Get the meta data.
+ std::pair<const char**, const char**> Meta =
+ exampleReport->getExtraDescriptiveText();
+ for (const char** s = Meta.first; s != Meta.second; ++s)
+ D->addMeta(*s);
+
+ // Emit a summary diagnostic to the regular Diagnostics engine.
+ BugReport::ranges_iterator Beg, End;
+ llvm::tie(Beg, End) = exampleReport->getRanges();
+ Diagnostic &Diag = getDiagnostic();
+ FullSourceLoc L(exampleReport->getLocation(), getSourceManager());
+
+ // Search the description for '%', as that will be interpretted as a
+ // format character by FormatDiagnostics.
+ llvm::StringRef desc = exampleReport->getShortDescription();
+ unsigned ErrorDiag;
+ {
+ llvm::SmallString<512> TmpStr;
+ llvm::raw_svector_ostream Out(TmpStr);
+ for (llvm::StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
+ if (*I == '%')
+ Out << "%%";
+ else
+ Out << *I;
+
+ Out.flush();
+ ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr);
+ }
+
+ {
+ DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
+ for (BugReport::ranges_iterator I = Beg; I != End; ++I)
+ diagBuilder << *I;
+ }
+
+ // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
+ if (!PD)
+ return;
+
+ if (D->empty()) {
+ PathDiagnosticPiece* piece =
+ new PathDiagnosticEventPiece(L, exampleReport->getDescription());
+
+ for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
+ D->push_back(piece);
+ }
+
+ PD->HandlePathDiagnostic(D.take());
+}
+
+void BugReporter::EmitBasicReport(llvm::StringRef name, llvm::StringRef str,
+ SourceLocation Loc,
+ SourceRange* RBeg, unsigned NumRanges) {
+ EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
+}
+
+void BugReporter::EmitBasicReport(llvm::StringRef name,
+ llvm::StringRef category,
+ llvm::StringRef str, SourceLocation Loc,
+ SourceRange* RBeg, unsigned NumRanges) {
+
+ // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'.
+ BugType *BT = new BugType(name, category);
+ FullSourceLoc L = getContext().getFullLoc(Loc);
+ RangedBugReport *R = new DiagBugReport(*BT, str, L);
+ for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
+ EmitReport(R);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
new file mode 100644
index 0000000..8e31ade
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -0,0 +1,457 @@
+// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of BugReporter "visitors" which can be used to
+// enhance the diagnostics reported for a bug.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
+ // Pattern match for a few useful cases (do something smarter later):
+ // a[0], p->f, *p
+ const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
+
+ if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
+ if (U->getOpcode() == UO_Deref)
+ return U->getSubExpr()->IgnoreParenCasts();
+ }
+ else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
+ return ME->getBase()->IgnoreParenCasts();
+ }
+ else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
+ // Retrieve the base for arrays since BasicStoreManager doesn't know how
+ // to reason about them.
+ return AE->getBase();
+ }
+
+ return NULL;
+}
+
+const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) {
+ const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
+ if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S))
+ return BE->getRHS();
+ return NULL;
+}
+
+const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) {
+ // Callee is checked as a PreVisit to the CallExpr.
+ const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S))
+ return CE->getCallee();
+ return NULL;
+}
+
+const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) {
+ const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
+ if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S))
+ return RS->getRetValue();
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Definitions for bug reporter visitors.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FindLastStoreBRVisitor : public BugReporterVisitor {
+ const MemRegion *R;
+ SVal V;
+ bool satisfied;
+ const ExplodedNode *StoreSite;
+public:
+ FindLastStoreBRVisitor(SVal v, const MemRegion *r)
+ : R(r), V(v), satisfied(false), StoreSite(0) {}
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int tag = 0;
+ ID.AddPointer(&tag);
+ ID.AddPointer(R);
+ ID.Add(V);
+ }
+
+ PathDiagnosticPiece* VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext& BRC) {
+
+ if (satisfied)
+ return NULL;
+
+ if (!StoreSite) {
+ const ExplodedNode *Node = N, *Last = NULL;
+
+ for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ if (const PostStmt *P = Node->getLocationAs<PostStmt>())
+ if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
+ if (DS->getSingleDecl() == VR->getDecl()) {
+ Last = Node;
+ break;
+ }
+ }
+
+ if (Node->getState()->getSVal(R) != V)
+ break;
+ }
+
+ if (!Node || !Last) {
+ satisfied = true;
+ return NULL;
+ }
+
+ StoreSite = Last;
+ }
+
+ if (StoreSite != N)
+ return NULL;
+
+ satisfied = true;
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
+
+ if (const PostStmt *PS = N->getLocationAs<PostStmt>()) {
+ if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) {
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << "Variable '" << VR->getDecl() << "' ";
+ }
+ else
+ return NULL;
+
+ if (isa<loc::ConcreteInt>(V)) {
+ bool b = false;
+ if (R->isBoundable()) {
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
+ os << "initialized to nil";
+ b = true;
+ }
+ }
+ }
+
+ if (!b)
+ os << "initialized to a null pointer value";
+ }
+ else if (isa<nonloc::ConcreteInt>(V)) {
+ os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue();
+ }
+ else if (V.isUndef()) {
+ if (isa<VarRegion>(R)) {
+ const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
+ if (VD->getInit())
+ os << "initialized to a garbage value";
+ else
+ os << "declared without an initial value";
+ }
+ }
+ }
+ }
+
+ if (os.str().empty()) {
+ if (isa<loc::ConcreteInt>(V)) {
+ bool b = false;
+ if (R->isBoundable()) {
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
+ os << "nil object reference stored to ";
+ b = true;
+ }
+ }
+ }
+
+ if (!b)
+ os << "Null pointer value stored to ";
+ }
+ else if (V.isUndef()) {
+ os << "Uninitialized value stored to ";
+ }
+ else if (isa<nonloc::ConcreteInt>(V)) {
+ os << "The value " << cast<nonloc::ConcreteInt>(V).getValue()
+ << " is assigned to ";
+ }
+ else
+ return NULL;
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ os << '\'' << VR->getDecl() << '\'';
+ }
+ else
+ return NULL;
+ }
+
+ // FIXME: Refactor this into BugReporterContext.
+ const Stmt *S = 0;
+ ProgramPoint P = N->getLocation();
+
+ if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock *BSrc = BE->getSrc();
+ S = BSrc->getTerminatorCondition();
+ }
+ else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ S = PS->getStmt();
+ }
+
+ if (!S)
+ return NULL;
+
+ // Construct a new PathDiagnosticPiece.
+ PathDiagnosticLocation L(S, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, os.str());
+ }
+};
+
+
+static void registerFindLastStore(BugReporterContext& BRC, const MemRegion *R,
+ SVal V) {
+ BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
+}
+
+class TrackConstraintBRVisitor : public BugReporterVisitor {
+ DefinedSVal Constraint;
+ const bool Assumption;
+ bool isSatisfied;
+public:
+ TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
+ : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int tag = 0;
+ ID.AddPointer(&tag);
+ ID.AddBoolean(Assumption);
+ ID.Add(Constraint);
+ }
+
+ PathDiagnosticPiece* VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext& BRC) {
+ if (isSatisfied)
+ return NULL;
+
+ // Check if in the previous state it was feasible for this constraint
+ // to *not* be true.
+ if (PrevN->getState()->assume(Constraint, !Assumption)) {
+
+ isSatisfied = true;
+
+ // As a sanity check, make sure that the negation of the constraint
+ // was infeasible in the current state. If it is feasible, we somehow
+ // missed the transition point.
+ if (N->getState()->assume(Constraint, !Assumption))
+ return NULL;
+
+ // We found the transition point for the constraint. We now need to
+ // pretty-print the constraint. (work-in-progress)
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ if (isa<Loc>(Constraint)) {
+ os << "Assuming pointer value is ";
+ os << (Assumption ? "non-null" : "null");
+ }
+
+ if (os.str().empty())
+ return NULL;
+
+ // FIXME: Refactor this into BugReporterContext.
+ const Stmt *S = 0;
+ ProgramPoint P = N->getLocation();
+
+ if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock *BSrc = BE->getSrc();
+ S = BSrc->getTerminatorCondition();
+ }
+ else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ S = PS->getStmt();
+ }
+
+ if (!S)
+ return NULL;
+
+ // Construct a new PathDiagnosticPiece.
+ PathDiagnosticLocation L(S, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, os.str());
+ }
+
+ return NULL;
+ }
+};
+} // end anonymous namespace
+
+static void registerTrackConstraint(BugReporterContext& BRC,
+ DefinedSVal Constraint,
+ bool Assumption) {
+ BRC.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption));
+}
+
+void bugreporter::registerTrackNullOrUndefValue(BugReporterContext& BRC,
+ const void *data,
+ const ExplodedNode* N) {
+
+ const Stmt *S = static_cast<const Stmt*>(data);
+
+ if (!S)
+ return;
+
+ GRStateManager &StateMgr = BRC.getStateManager();
+ const GRState *state = N->getState();
+
+ // Walk through lvalue-to-rvalue conversions.
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ const VarRegion *R =
+ StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
+
+ // What did we load?
+ SVal V = state->getSVal(loc::MemRegionVal(R));
+
+ if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
+ || V.isUndef()) {
+ ::registerFindLastStore(BRC, R, V);
+ }
+ }
+ }
+
+ SVal V = state->getSValAsScalarOrLoc(S);
+
+ // Uncomment this to find cases where we aren't properly getting the
+ // base value that was dereferenced.
+ // assert(!V.isUnknownOrUndef());
+
+ // Is it a symbolic value?
+ if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
+ const SubRegion *R = cast<SubRegion>(L->getRegion());
+ while (R && !isa<SymbolicRegion>(R)) {
+ R = dyn_cast<SubRegion>(R->getSuperRegion());
+ }
+
+ if (R) {
+ assert(isa<SymbolicRegion>(R));
+ registerTrackConstraint(BRC, loc::MemRegionVal(R), false);
+ }
+ }
+}
+
+void bugreporter::registerFindLastStore(BugReporterContext& BRC,
+ const void *data,
+ const ExplodedNode* N) {
+
+ const MemRegion *R = static_cast<const MemRegion*>(data);
+
+ if (!R)
+ return;
+
+ const GRState *state = N->getState();
+ SVal V = state->getSVal(R);
+
+ if (V.isUnknown())
+ return;
+
+ BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
+}
+
+
+namespace {
+class NilReceiverVisitor : public BugReporterVisitor {
+public:
+ NilReceiverVisitor() {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ PathDiagnosticPiece* VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext& BRC) {
+
+ const PostStmt *P = N->getLocationAs<PostStmt>();
+ if (!P)
+ return 0;
+ const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
+ if (!ME)
+ return 0;
+ const Expr *Receiver = ME->getInstanceReceiver();
+ if (!Receiver)
+ return 0;
+ const GRState *state = N->getState();
+ const SVal &V = state->getSVal(Receiver);
+ const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
+ if (!DV)
+ return 0;
+ state = state->assume(*DV, true);
+ if (state)
+ return 0;
+
+ // The receiver was nil, and hence the method was skipped.
+ // Register a BugReporterVisitor to issue a message telling us how
+ // the receiver was null.
+ bugreporter::registerTrackNullOrUndefValue(BRC, Receiver, N);
+ // Issue a message saying that the method was skipped.
+ PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, "No method actually called "
+ "because the receiver is nil");
+ }
+};
+} // end anonymous namespace
+
+void bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) {
+ BRC.addVisitor(new NilReceiverVisitor());
+}
+
+// Registers every VarDecl inside a Stmt with a last store vistor.
+void bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
+ const void *stmt,
+ const ExplodedNode *N) {
+ const Stmt *S = static_cast<const Stmt *>(stmt);
+
+ std::deque<const Stmt *> WorkList;
+
+ WorkList.push_back(S);
+
+ while (!WorkList.empty()) {
+ const Stmt *Head = WorkList.front();
+ WorkList.pop_front();
+
+ GRStateManager &StateMgr = BRC.getStateManager();
+ const GRState *state = N->getState();
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ const VarRegion *R =
+ StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
+
+ // What did we load?
+ SVal V = state->getSVal(S);
+
+ if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
+ ::registerFindLastStore(BRC, R, V);
+ }
+ }
+ }
+
+ for (Stmt::const_child_iterator I = Head->child_begin();
+ I != Head->child_end(); ++I)
+ WorkList.push_back(*I);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp
new file mode 100644
index 0000000..b3721d7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CFRefCount.cpp
@@ -0,0 +1,3519 @@
+// CFRefCount.cpp - Transfer functions for tracking simple values -*- 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 methods for CFRefCount, which implements
+// a reference count checker for Core Foundation (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include <stdarg.h>
+
+using namespace clang;
+using namespace ento;
+using llvm::StringRef;
+using llvm::StrInStrNoCase;
+
+namespace {
+class InstanceReceiver {
+ ObjCMessage Msg;
+ const LocationContext *LC;
+public:
+ InstanceReceiver() : LC(0) { }
+ InstanceReceiver(const ObjCMessage &msg,
+ const LocationContext *lc = 0) : Msg(msg), LC(lc) {}
+
+ bool isValid() const {
+ return Msg.isValid() && Msg.isInstanceMessage();
+ }
+ operator bool() const {
+ return isValid();
+ }
+
+ SVal getSValAsScalarOrLoc(const GRState *state) {
+ assert(isValid());
+ // We have an expression for the receiver? Fetch the value
+ // of that expression.
+ if (const Expr *Ex = Msg.getInstanceReceiver())
+ return state->getSValAsScalarOrLoc(Ex);
+
+ // Otherwise we are sending a message to super. In this case the
+ // object reference is the same as 'self'.
+ if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl())
+ return state->getSVal(state->getRegion(SelfDecl, LC));
+
+ return UnknownVal();
+ }
+
+ SourceRange getSourceRange() const {
+ assert(isValid());
+ if (const Expr *Ex = Msg.getInstanceReceiver())
+ return Ex->getSourceRange();
+
+ // Otherwise we are sending a message to super.
+ SourceLocation L = Msg.getSuperLoc();
+ assert(L.isValid());
+ return SourceRange(L, L);
+ }
+};
+}
+
+static const ObjCMethodDecl*
+ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
+ const ObjCInterfaceDecl *ID = MD->getClassInterface();
+
+ return MD->isInstanceMethod()
+ ? ID->lookupInstanceMethod(MD->getSelector())
+ : ID->lookupClassMethod(MD->getSelector());
+}
+
+namespace {
+class GenericNodeBuilderRefCount {
+ StmtNodeBuilder *SNB;
+ const Stmt *S;
+ const void *tag;
+ EndOfFunctionNodeBuilder *ENB;
+public:
+ GenericNodeBuilderRefCount(StmtNodeBuilder &snb, const Stmt *s,
+ const void *t)
+ : SNB(&snb), S(s), tag(t), ENB(0) {}
+
+ GenericNodeBuilderRefCount(EndOfFunctionNodeBuilder &enb)
+ : SNB(0), S(0), tag(0), ENB(&enb) {}
+
+ ExplodedNode *MakeNode(const GRState *state, ExplodedNode *Pred) {
+ if (SNB)
+ return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
+ state, Pred);
+
+ assert(ENB);
+ return ENB->generateNode(state, Pred);
+ }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Primitives used for constructing summaries for function/method calls.
+//===----------------------------------------------------------------------===//
+
+/// ArgEffect is used to summarize a function/method call's effect on a
+/// particular argument.
+enum ArgEffect { Autorelease, Dealloc, DecRef, DecRefMsg, DoNothing,
+ DoNothingByRef, IncRefMsg, IncRef, MakeCollectable, MayEscape,
+ NewAutoreleasePool, SelfOwn, StopTracking };
+
+namespace llvm {
+template <> struct FoldingSetTrait<ArgEffect> {
+static inline void Profile(const ArgEffect X, FoldingSetNodeID& ID) {
+ ID.AddInteger((unsigned) X);
+}
+};
+} // end llvm namespace
+
+/// ArgEffects summarizes the effects of a function/method call on all of
+/// its arguments.
+typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
+
+namespace {
+
+/// RetEffect is used to summarize a function/method call's behavior with
+/// respect to its return value.
+class RetEffect {
+public:
+ enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
+ NotOwnedSymbol, GCNotOwnedSymbol, ReceiverAlias,
+ OwnedWhenTrackedReceiver };
+
+ enum ObjKind { CF, ObjC, AnyObj };
+
+private:
+ Kind K;
+ ObjKind O;
+ unsigned index;
+
+ RetEffect(Kind k, unsigned idx = 0) : K(k), O(AnyObj), index(idx) {}
+ RetEffect(Kind k, ObjKind o) : K(k), O(o), index(0) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ unsigned getIndex() const {
+ assert(getKind() == Alias);
+ return index;
+ }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+ K == OwnedWhenTrackedReceiver;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+ }
+
+ static RetEffect MakeAlias(unsigned Idx) {
+ return RetEffect(Alias, Idx);
+ }
+ static RetEffect MakeReceiverAlias() {
+ return RetEffect(ReceiverAlias);
+ }
+ static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
+ return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeGCNotOwned() {
+ return RetEffect(GCNotOwnedSymbol, ObjC);
+ }
+
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Reference-counting logic (typestate + counts).
+//===----------------------------------------------------------------------===//
+
+class RefVal {
+public:
+ enum Kind {
+ Owned = 0, // Owning reference.
+ NotOwned, // Reference is not owned by still valid (not freed).
+ Released, // Object has been released.
+ ReturnedOwned, // Returned object passes ownership to caller.
+ ReturnedNotOwned, // Return object does not pass ownership to caller.
+ ERROR_START,
+ ErrorDeallocNotOwned, // -dealloc called on non-owned object.
+ ErrorDeallocGC, // Calling -dealloc with GC enabled.
+ ErrorUseAfterRelease, // Object used after released.
+ ErrorReleaseNotOwned, // Release of an object that was not owned.
+ ERROR_LEAK_START,
+ ErrorLeak, // A memory leak due to excessive reference counts.
+ ErrorLeakReturned, // A memory leak due to the returning method not having
+ // the correct naming conventions.
+ ErrorGCLeakReturned,
+ ErrorOverAutorelease,
+ ErrorReturnedNotOwned
+ };
+
+private:
+ Kind kind;
+ RetEffect::ObjKind okind;
+ unsigned Cnt;
+ unsigned ACnt;
+ QualType T;
+
+ RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t)
+ : kind(k), okind(o), Cnt(cnt), ACnt(acnt), T(t) {}
+
+public:
+ Kind getKind() const { return kind; }
+
+ RetEffect::ObjKind getObjKind() const { return okind; }
+
+ unsigned getCount() const { return Cnt; }
+ unsigned getAutoreleaseCount() const { return ACnt; }
+ unsigned getCombinedCounts() const { return Cnt + ACnt; }
+ void clearCounts() { Cnt = 0; ACnt = 0; }
+ void setCount(unsigned i) { Cnt = i; }
+ void setAutoreleaseCount(unsigned i) { ACnt = i; }
+
+ QualType getType() const { return T; }
+
+ bool isOwned() const {
+ return getKind() == Owned;
+ }
+
+ bool isNotOwned() const {
+ return getKind() == NotOwned;
+ }
+
+ bool isReturnedOwned() const {
+ return getKind() == ReturnedOwned;
+ }
+
+ bool isReturnedNotOwned() const {
+ return getKind() == ReturnedNotOwned;
+ }
+
+ static RefVal makeOwned(RetEffect::ObjKind o, QualType t,
+ unsigned Count = 1) {
+ return RefVal(Owned, o, Count, 0, t);
+ }
+
+ static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t,
+ unsigned Count = 0) {
+ return RefVal(NotOwned, o, Count, 0, t);
+ }
+
+ // Comparison, profiling, and pretty-printing.
+
+ bool operator==(const RefVal& X) const {
+ return kind == X.kind && Cnt == X.Cnt && T == X.T && ACnt == X.ACnt;
+ }
+
+ RefVal operator-(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() - i,
+ getAutoreleaseCount(), getType());
+ }
+
+ RefVal operator+(size_t i) const {
+ return RefVal(getKind(), getObjKind(), getCount() + i,
+ getAutoreleaseCount(), getType());
+ }
+
+ RefVal operator^(Kind k) const {
+ return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
+ getType());
+ }
+
+ RefVal autorelease() const {
+ return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
+ getType());
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) kind);
+ ID.AddInteger(Cnt);
+ ID.AddInteger(ACnt);
+ ID.Add(T);
+ }
+
+ void print(llvm::raw_ostream& Out) const;
+};
+
+void RefVal::print(llvm::raw_ostream& Out) const {
+ if (!T.isNull())
+ Out << "Tracked Type:" << T.getAsString() << '\n';
+
+ switch (getKind()) {
+ default: assert(false);
+ case Owned: {
+ Out << "Owned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case NotOwned: {
+ Out << "NotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedOwned: {
+ Out << "ReturnedOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case ReturnedNotOwned: {
+ Out << "ReturnedNotOwned";
+ unsigned cnt = getCount();
+ if (cnt) Out << " (+ " << cnt << ")";
+ break;
+ }
+
+ case Released:
+ Out << "Released";
+ break;
+
+ case ErrorDeallocGC:
+ Out << "-dealloc (GC)";
+ break;
+
+ case ErrorDeallocNotOwned:
+ Out << "-dealloc (not-owned)";
+ break;
+
+ case ErrorLeak:
+ Out << "Leaked";
+ break;
+
+ case ErrorLeakReturned:
+ Out << "Leaked (Bad naming)";
+ break;
+
+ case ErrorGCLeakReturned:
+ Out << "Leaked (GC-ed at return)";
+ break;
+
+ case ErrorUseAfterRelease:
+ Out << "Use-After-Release [ERROR]";
+ break;
+
+ case ErrorReleaseNotOwned:
+ Out << "Release of Not-Owned [ERROR]";
+ break;
+
+ case RefVal::ErrorOverAutorelease:
+ Out << "Over autoreleased";
+ break;
+
+ case RefVal::ErrorReturnedNotOwned:
+ Out << "Non-owned object returned instead of owned";
+ break;
+ }
+
+ if (ACnt) {
+ Out << " [ARC +" << ACnt << ']';
+ }
+}
+} //end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RefBindings - State used to track object reference counts.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolRef, RefVal> RefBindings;
+
+namespace clang {
+namespace ento {
+ template<>
+ struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
+ static void* GDMIndex() {
+ static int RefBIndex = 0;
+ return &RefBIndex;
+ }
+ };
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Summaries
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainSummary {
+ /// Args - an ordered vector of (index, ArgEffect) pairs, where index
+ /// specifies the argument (starting from 0). This can be sparsely
+ /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
+ ArgEffects Args;
+
+ /// DefaultArgEffect - The default ArgEffect to apply to arguments that
+ /// do not have an entry in Args.
+ ArgEffect DefaultArgEffect;
+
+ /// Receiver - If this summary applies to an Objective-C message expression,
+ /// this is the effect applied to the state of the receiver.
+ ArgEffect Receiver;
+
+ /// Ret - The effect on the return value. Used to indicate if the
+ /// function/method call returns a new tracked symbol, returns an
+ /// alias of one of the arguments in the call, and so on.
+ RetEffect Ret;
+
+ /// EndPath - Indicates that execution of this method/function should
+ /// terminate the simulation of a path.
+ bool EndPath;
+
+public:
+ RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
+ ArgEffect ReceiverEff, bool endpath = false)
+ : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
+ EndPath(endpath) {}
+
+ /// getArg - Return the argument effect on the argument specified by
+ /// idx (starting from 0).
+ ArgEffect getArg(unsigned idx) const {
+ if (const ArgEffect *AE = Args.lookup(idx))
+ return *AE;
+
+ return DefaultArgEffect;
+ }
+
+ void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
+ Args = af.add(Args, idx, e);
+ }
+
+ /// setDefaultArgEffect - Set the default argument effect.
+ void setDefaultArgEffect(ArgEffect E) {
+ DefaultArgEffect = E;
+ }
+
+ /// getRetEffect - Returns the effect on the return value of the call.
+ RetEffect getRetEffect() const { return Ret; }
+
+ /// setRetEffect - Set the effect of the return value of the call.
+ void setRetEffect(RetEffect E) { Ret = E; }
+
+ /// isEndPath - Returns true if executing the given method/function should
+ /// terminate the path.
+ bool isEndPath() const { return EndPath; }
+
+
+ /// Sets the effect on the receiver of the message.
+ void setReceiverEffect(ArgEffect e) { Receiver = e; }
+
+ /// getReceiverEffect - Returns the effect on the receiver of the call.
+ /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
+ ArgEffect getReceiverEffect() const { return Receiver; }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Data structures for constructing summaries.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ObjCSummaryKey {
+ IdentifierInfo* II;
+ Selector S;
+public:
+ ObjCSummaryKey(IdentifierInfo* ii, Selector s)
+ : II(ii), S(s) {}
+
+ ObjCSummaryKey(const ObjCInterfaceDecl* d, Selector s)
+ : II(d ? d->getIdentifier() : 0), S(s) {}
+
+ ObjCSummaryKey(const ObjCInterfaceDecl* d, IdentifierInfo *ii, Selector s)
+ : II(d ? d->getIdentifier() : ii), S(s) {}
+
+ ObjCSummaryKey(Selector s)
+ : II(0), S(s) {}
+
+ IdentifierInfo* getIdentifier() const { return II; }
+ Selector getSelector() const { return S; }
+};
+}
+
+namespace llvm {
+template <> struct DenseMapInfo<ObjCSummaryKey> {
+ static inline ObjCSummaryKey getEmptyKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
+ DenseMapInfo<Selector>::getEmptyKey());
+ }
+
+ static inline ObjCSummaryKey getTombstoneKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
+ DenseMapInfo<Selector>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const ObjCSummaryKey &V) {
+ return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
+ & 0x88888888)
+ | (DenseMapInfo<Selector>::getHashValue(V.getSelector())
+ & 0x55555555);
+ }
+
+ static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
+ return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
+ RHS.getIdentifier()) &&
+ DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
+ RHS.getSelector());
+ }
+
+};
+template <>
+struct isPodLike<ObjCSummaryKey> { static const bool value = true; };
+} // end llvm namespace
+
+namespace {
+class ObjCSummaryCache {
+ typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
+ MapTy M;
+public:
+ ObjCSummaryCache() {}
+
+ RetainSummary* find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
+ Selector S) {
+ // Lookup the method using the decl for the class @interface. If we
+ // have no decl, lookup using the class name.
+ return D ? find(D, S) : find(ClsName, S);
+ }
+
+ RetainSummary* find(const ObjCInterfaceDecl* D, Selector S) {
+ // Do a lookup with the (D,S) pair. If we find a match return
+ // the iterator.
+ ObjCSummaryKey K(D, S);
+ MapTy::iterator I = M.find(K);
+
+ if (I != M.end() || !D)
+ return I->second;
+
+ // Walk the super chain. If we find a hit with a parent, we'll end
+ // up returning that summary. We actually allow that key (null,S), as
+ // we cache summaries for the null ObjCInterfaceDecl* to allow us to
+ // generate initial summaries without having to worry about NSObject
+ // being declared.
+ // FIXME: We may change this at some point.
+ for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
+ if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
+ break;
+
+ if (!C)
+ return NULL;
+ }
+
+ // Cache the summary with original key to make the next lookup faster
+ // and return the iterator.
+ RetainSummary *Summ = I->second;
+ M[K] = Summ;
+ return Summ;
+ }
+
+ RetainSummary* find(IdentifierInfo* II, Selector S) {
+ // FIXME: Class method lookup. Right now we dont' have a good way
+ // of going between IdentifierInfo* and the class hierarchy.
+ MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
+
+ if (I == M.end())
+ I = M.find(ObjCSummaryKey(S));
+
+ return I == M.end() ? NULL : I->second;
+ }
+
+ RetainSummary*& operator[](ObjCSummaryKey K) {
+ return M[K];
+ }
+
+ RetainSummary*& operator[](Selector S) {
+ return M[ ObjCSummaryKey(S) ];
+ }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Data structures for managing collections of summaries.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainSummaryManager {
+
+ //==-----------------------------------------------------------------==//
+ // Typedefs.
+ //==-----------------------------------------------------------------==//
+
+ typedef llvm::DenseMap<const FunctionDecl*, RetainSummary*>
+ FuncSummariesTy;
+
+ typedef ObjCSummaryCache ObjCMethodSummariesTy;
+
+ //==-----------------------------------------------------------------==//
+ // Data.
+ //==-----------------------------------------------------------------==//
+
+ /// Ctx - The ASTContext object for the analyzed ASTs.
+ ASTContext& Ctx;
+
+ /// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
+ /// "CFDictionaryCreate".
+ IdentifierInfo* CFDictionaryCreateII;
+
+ /// GCEnabled - Records whether or not the analyzed code runs in GC mode.
+ const bool GCEnabled;
+
+ /// FuncSummaries - A map from FunctionDecls to summaries.
+ FuncSummariesTy FuncSummaries;
+
+ /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
+ /// to summaries.
+ ObjCMethodSummariesTy ObjCClassMethodSummaries;
+
+ /// ObjCMethodSummaries - A map from selectors to summaries.
+ ObjCMethodSummariesTy ObjCMethodSummaries;
+
+ /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
+ /// and all other data used by the checker.
+ llvm::BumpPtrAllocator BPAlloc;
+
+ /// AF - A factory for ArgEffects objects.
+ ArgEffects::Factory AF;
+
+ /// ScratchArgs - A holding buffer for construct ArgEffects.
+ ArgEffects ScratchArgs;
+
+ /// ObjCAllocRetE - Default return effect for methods returning Objective-C
+ /// objects.
+ RetEffect ObjCAllocRetE;
+
+ /// ObjCInitRetE - Default return effect for init methods returning
+ /// Objective-C objects.
+ RetEffect ObjCInitRetE;
+
+ RetainSummary DefaultSummary;
+ RetainSummary* StopSummary;
+
+ //==-----------------------------------------------------------------==//
+ // Methods.
+ //==-----------------------------------------------------------------==//
+
+ /// getArgEffects - Returns a persistent ArgEffects object based on the
+ /// data in ScratchArgs.
+ ArgEffects getArgEffects();
+
+ enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
+
+public:
+ RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+ RetainSummary *getDefaultSummary() {
+ RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
+ return new (Summ) RetainSummary(DefaultSummary);
+ }
+
+ RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
+
+ RetainSummary* getCFSummaryCreateRule(const FunctionDecl* FD);
+ RetainSummary* getCFSummaryGetRule(const FunctionDecl* FD);
+ RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl* FD,
+ StringRef FName);
+
+ RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
+ ArgEffect ReceiverEff = DoNothing,
+ ArgEffect DefaultEff = MayEscape,
+ bool isEndPath = false);
+
+ RetainSummary* getPersistentSummary(RetEffect RE,
+ ArgEffect ReceiverEff = DoNothing,
+ ArgEffect DefaultEff = MayEscape) {
+ return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
+ }
+
+ RetainSummary *getPersistentStopSummary() {
+ if (StopSummary)
+ return StopSummary;
+
+ StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
+ StopTracking, StopTracking);
+
+ return StopSummary;
+ }
+
+ RetainSummary *getInitMethodSummary(QualType RetTy);
+
+ void InitializeClassMethodSummaries();
+ void InitializeMethodSummaries();
+private:
+ void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
+ ObjCClassMethodSummaries[S] = Summ;
+ }
+
+ void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
+ ObjCMethodSummaries[S] = Summ;
+ }
+
+ void addClassMethSummary(const char* Cls, const char* nullaryName,
+ RetainSummary *Summ) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = GetNullarySelector(nullaryName, Ctx);
+ ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ void addInstMethSummary(const char* Cls, const char* nullaryName,
+ RetainSummary *Summ) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = GetNullarySelector(nullaryName, Ctx);
+ ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ Selector generateSelector(va_list argp) {
+ llvm::SmallVector<IdentifierInfo*, 10> II;
+
+ while (const char* s = va_arg(argp, const char*))
+ II.push_back(&Ctx.Idents.get(s));
+
+ return Ctx.Selectors.getSelector(II.size(), &II[0]);
+ }
+
+ void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
+ RetainSummary* Summ, va_list argp) {
+ Selector S = generateSelector(argp);
+ Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
+ va_list argp;
+ va_start(argp, Summ);
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
+ va_end(argp);
+ }
+
+ void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) {
+ va_list argp;
+ va_start(argp, Summ);
+ addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
+ va_end(argp);
+ }
+
+ void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) {
+ va_list argp;
+ va_start(argp, Summ);
+ addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
+ va_end(argp);
+ }
+
+ void addPanicSummary(const char* Cls, ...) {
+ RetainSummary* Summ = getPersistentSummary(AF.getEmptyMap(),
+ RetEffect::MakeNoRet(),
+ DoNothing, DoNothing, true);
+ va_list argp;
+ va_start (argp, Cls);
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
+ va_end(argp);
+ }
+
+public:
+
+ RetainSummaryManager(ASTContext& ctx, bool gcenabled)
+ : Ctx(ctx),
+ CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
+ GCEnabled(gcenabled), AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
+ ObjCAllocRetE(gcenabled ? RetEffect::MakeGCNotOwned()
+ : RetEffect::MakeOwned(RetEffect::ObjC, true)),
+ ObjCInitRetE(gcenabled ? RetEffect::MakeGCNotOwned()
+ : RetEffect::MakeOwnedWhenTrackedReceiver()),
+ DefaultSummary(AF.getEmptyMap() /* per-argument effects (none) */,
+ RetEffect::MakeNoRet() /* return effect */,
+ MayEscape, /* default argument effect */
+ DoNothing /* receiver effect */),
+ StopSummary(0) {
+
+ InitializeClassMethodSummaries();
+ InitializeMethodSummaries();
+ }
+
+ ~RetainSummaryManager();
+
+ RetainSummary* getSummary(const FunctionDecl* FD);
+
+ RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
+ const GRState *state,
+ const LocationContext *LC);
+
+ RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg,
+ const ObjCInterfaceDecl* ID) {
+ return getInstanceMethodSummary(msg.getSelector(), 0,
+ ID, msg.getMethodDecl(), msg.getType(Ctx));
+ }
+
+ RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
+ const ObjCInterfaceDecl* ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy);
+
+ RetainSummary *getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
+ const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy);
+
+ RetainSummary *getClassMethodSummary(const ObjCMessage &msg) {
+ const ObjCInterfaceDecl *Class = 0;
+ if (!msg.isInstanceMessage())
+ Class = msg.getReceiverInterface();
+
+ return getClassMethodSummary(msg.getSelector(),
+ Class? Class->getIdentifier() : 0,
+ Class,
+ msg.getMethodDecl(), msg.getType(Ctx));
+ }
+
+ /// getMethodSummary - This version of getMethodSummary is used to query
+ /// the summary for the current method being analyzed.
+ RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
+ // FIXME: Eventually this should be unneeded.
+ const ObjCInterfaceDecl *ID = MD->getClassInterface();
+ Selector S = MD->getSelector();
+ IdentifierInfo *ClsName = ID->getIdentifier();
+ QualType ResultTy = MD->getResultType();
+
+ // Resolve the method decl last.
+ if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD))
+ MD = InterfaceMD;
+
+ if (MD->isInstanceMethod())
+ return getInstanceMethodSummary(S, ClsName, ID, MD, ResultTy);
+ else
+ return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
+ }
+
+ RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
+ Selector S, QualType RetTy);
+
+ void updateSummaryFromAnnotations(RetainSummary &Summ,
+ const ObjCMethodDecl *MD);
+
+ void updateSummaryFromAnnotations(RetainSummary &Summ,
+ const FunctionDecl *FD);
+
+ bool isGCEnabled() const { return GCEnabled; }
+
+ RetainSummary *copySummary(RetainSummary *OldSumm) {
+ RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
+ new (Summ) RetainSummary(*OldSumm);
+ return Summ;
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Implementation of checker data structures.
+//===----------------------------------------------------------------------===//
+
+RetainSummaryManager::~RetainSummaryManager() {}
+
+ArgEffects RetainSummaryManager::getArgEffects() {
+ ArgEffects AE = ScratchArgs;
+ ScratchArgs = AF.getEmptyMap();
+ return AE;
+}
+
+RetainSummary*
+RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
+ ArgEffect ReceiverEff,
+ ArgEffect DefaultEff,
+ bool isEndPath) {
+ // Create the summary and return it.
+ RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
+ new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
+ return Summ;
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for functions (largely uses of Core Foundation).
+//===----------------------------------------------------------------------===//
+
+static bool isRetain(const FunctionDecl* FD, StringRef FName) {
+ return FName.endswith("Retain");
+}
+
+static bool isRelease(const FunctionDecl* FD, StringRef FName) {
+ return FName.endswith("Release");
+}
+
+RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl* FD) {
+ // Look up a summary in our cache of FunctionDecls -> Summaries.
+ FuncSummariesTy::iterator I = FuncSummaries.find(FD);
+ if (I != FuncSummaries.end())
+ return I->second;
+
+ // No summary? Generate one.
+ RetainSummary *S = 0;
+
+ do {
+ // We generate "stop" summaries for implicitly defined functions.
+ if (FD->isImplicit()) {
+ S = getPersistentStopSummary();
+ break;
+ }
+
+ // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
+ // function's type.
+ const FunctionType* FT = FD->getType()->getAs<FunctionType>();
+ const IdentifierInfo *II = FD->getIdentifier();
+ if (!II)
+ break;
+
+ StringRef FName = II->getName();
+
+ // Strip away preceding '_'. Doing this here will effect all the checks
+ // down below.
+ FName = FName.substr(FName.find_first_not_of('_'));
+
+ // Inspect the result type.
+ QualType RetTy = FT->getResultType();
+
+ // FIXME: This should all be refactored into a chain of "summary lookup"
+ // filters.
+ assert(ScratchArgs.isEmpty());
+
+ if (FName == "pthread_create") {
+ // Part of: <rdar://problem/7299394>. This will be addressed
+ // better with IPA.
+ S = getPersistentStopSummary();
+ } else if (FName == "NSMakeCollectable") {
+ // Handle: id NSMakeCollectable(CFTypeRef)
+ S = (RetTy->isObjCIdType())
+ ? getUnarySummary(FT, cfmakecollectable)
+ : getPersistentStopSummary();
+ } else if (FName == "IOBSDNameMatching" ||
+ FName == "IOServiceMatching" ||
+ FName == "IOServiceNameMatching" ||
+ FName == "IORegistryEntryIDMatching" ||
+ FName == "IOOpenFirmwarePathMatching") {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ } else if (FName == "IOServiceGetMatchingService" ||
+ FName == "IOServiceGetMatchingServices") {
+ // FIXES: <rdar://problem/6326900>
+ // This should be addressed using a API table. This strcmp is also
+ // a little gross, but there is no need to super optimize here.
+ ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ } else if (FName == "IOServiceAddNotification" ||
+ FName == "IOServiceAddMatchingNotification") {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ } else if (FName == "CVPixelBufferCreateWithBytes") {
+ // FIXES: <rdar://problem/7283567>
+ // Eventually this can be improved by recognizing that the pixel
+ // buffer passed to CVPixelBufferCreateWithBytes is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ // FIXME: This function has an out parameter that returns an
+ // allocated object.
+ ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ } else if (FName == "CGBitmapContextCreateWithData") {
+ // FIXES: <rdar://problem/7358899>
+ // Eventually this can be improved by recognizing that 'releaseInfo'
+ // passed to CGBitmapContextCreateWithData is released via
+ // a callback and doing full IPA to make sure this is done correctly.
+ ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
+ // FIXES: <rdar://problem/7283567>
+ // Eventually this can be improved by recognizing that the pixel
+ // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
+ // via a callback and doing full IPA to make sure this is done
+ // correctly.
+ ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ }
+
+ // Did we get a summary?
+ if (S)
+ break;
+
+ // Enable this code once the semantics of NSDeallocateObject are resolved
+ // for GC. <rdar://problem/6619988>
+#if 0
+ // Handle: NSDeallocateObject(id anObject);
+ // This method does allow 'nil' (although we don't check it now).
+ if (strcmp(FName, "NSDeallocateObject") == 0) {
+ return RetTy == Ctx.VoidTy
+ ? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Dealloc)
+ : getPersistentStopSummary();
+ }
+#endif
+
+ if (RetTy->isPointerType()) {
+ // For CoreFoundation ('CF') types.
+ if (cocoa::isRefType(RetTy, "CF", FName)) {
+ if (isRetain(FD, FName))
+ S = getUnarySummary(FT, cfretain);
+ else if (FName.find("MakeCollectable") != StringRef::npos)
+ S = getUnarySummary(FT, cfmakecollectable);
+ else
+ S = getCFCreateGetRuleSummary(FD, FName);
+
+ break;
+ }
+
+ // For CoreGraphics ('CG') types.
+ if (cocoa::isRefType(RetTy, "CG", FName)) {
+ if (isRetain(FD, FName))
+ S = getUnarySummary(FT, cfretain);
+ else
+ S = getCFCreateGetRuleSummary(FD, FName);
+
+ break;
+ }
+
+ // For the Disk Arbitration API (DiskArbitration/DADisk.h)
+ if (cocoa::isRefType(RetTy, "DADisk") ||
+ cocoa::isRefType(RetTy, "DADissenter") ||
+ cocoa::isRefType(RetTy, "DASessionRef")) {
+ S = getCFCreateGetRuleSummary(FD, FName);
+ break;
+ }
+
+ break;
+ }
+
+ // Check for release functions, the only kind of functions that we care
+ // about that don't return a pointer type.
+ if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
+ // Test for 'CGCF'.
+ FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
+
+ if (isRelease(FD, FName))
+ S = getUnarySummary(FT, cfrelease);
+ else {
+ assert (ScratchArgs.isEmpty());
+ // Remaining CoreFoundation and CoreGraphics functions.
+ // We use to assume that they all strictly followed the ownership idiom
+ // and that ownership cannot be transferred. While this is technically
+ // correct, many methods allow a tracked object to escape. For example:
+ //
+ // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
+ // CFDictionaryAddValue(y, key, x);
+ // CFRelease(x);
+ // ... it is okay to use 'x' since 'y' has a reference to it
+ //
+ // We handle this and similar cases with the follow heuristic. If the
+ // function name contains "InsertValue", "SetValue", "AddValue",
+ // "AppendValue", or "SetAttribute", then we assume that arguments may
+ // "escape." This means that something else holds on to the object,
+ // allowing it be used even after its local retain count drops to 0.
+ ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
+ ? MayEscape : DoNothing;
+
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
+ }
+ }
+ }
+ while (0);
+
+ if (!S)
+ S = getDefaultSummary();
+
+ // Annotations override defaults.
+ assert(S);
+ updateSummaryFromAnnotations(*S, FD);
+
+ FuncSummaries[FD] = S;
+ return S;
+}
+
+RetainSummary*
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl* FD,
+ StringRef FName) {
+
+ if (FName.find("Create") != StringRef::npos ||
+ FName.find("Copy") != StringRef::npos)
+ return getCFSummaryCreateRule(FD);
+
+ if (FName.find("Get") != StringRef::npos)
+ return getCFSummaryGetRule(FD);
+
+ return getDefaultSummary();
+}
+
+RetainSummary*
+RetainSummaryManager::getUnarySummary(const FunctionType* FT,
+ UnaryFuncKind func) {
+
+ // Sanity check that this is *really* a unary function. This can
+ // happen if people do weird things.
+ const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
+ if (!FTP || FTP->getNumArgs() != 1)
+ return getPersistentStopSummary();
+
+ assert (ScratchArgs.isEmpty());
+
+ switch (func) {
+ case cfretain: {
+ ScratchArgs = AF.add(ScratchArgs, 0, IncRef);
+ return getPersistentSummary(RetEffect::MakeAlias(0),
+ DoNothing, DoNothing);
+ }
+
+ case cfrelease: {
+ ScratchArgs = AF.add(ScratchArgs, 0, DecRef);
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ DoNothing, DoNothing);
+ }
+
+ case cfmakecollectable: {
+ ScratchArgs = AF.add(ScratchArgs, 0, MakeCollectable);
+ return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing, DoNothing);
+ }
+
+ default:
+ assert (false && "Not a supported unary function.");
+ return getDefaultSummary();
+ }
+}
+
+RetainSummary*
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl* FD) {
+ assert (ScratchArgs.isEmpty());
+
+ if (FD->getIdentifier() == CFDictionaryCreateII) {
+ ScratchArgs = AF.add(ScratchArgs, 1, DoNothingByRef);
+ ScratchArgs = AF.add(ScratchArgs, 2, DoNothingByRef);
+ }
+
+ return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+}
+
+RetainSummary*
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl* FD) {
+ assert (ScratchArgs.isEmpty());
+ return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
+ DoNothing, DoNothing);
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for Selectors.
+//===----------------------------------------------------------------------===//
+
+RetainSummary*
+RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
+ assert(ScratchArgs.isEmpty());
+ // 'init' methods conceptually return a newly allocated object and claim
+ // the receiver.
+ if (cocoa::isCocoaObjectRef(RetTy) || cocoa::isCFObjectRef(RetTy))
+ return getPersistentSummary(ObjCInitRetE, DecRefMsg);
+
+ return getDefaultSummary();
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
+ const FunctionDecl *FD) {
+ if (!FD)
+ return;
+
+ // Effects on the parameters.
+ unsigned parm_idx = 0;
+ for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
+ pe = FD->param_end(); pi != pe; ++pi) {
+ const ParmVarDecl *pd = *pi;
+ if (pd->getAttr<NSConsumedAttr>()) {
+ if (!GCEnabled)
+ Summ.addArg(AF, parm_idx, DecRef);
+ }
+ else if(pd->getAttr<CFConsumedAttr>()) {
+ Summ.addArg(AF, parm_idx, DecRef);
+ }
+ }
+
+ QualType RetTy = FD->getResultType();
+
+ // Determine if there is a special return effect for this method.
+ if (cocoa::isCocoaObjectRef(RetTy)) {
+ if (FD->getAttr<NSReturnsRetainedAttr>()) {
+ Summ.setRetEffect(ObjCAllocRetE);
+ }
+ else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+ }
+ else if (FD->getAttr<NSReturnsNotRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+ }
+ else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+ }
+ }
+ else if (RetTy->getAs<PointerType>()) {
+ if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+ }
+ }
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
+ const ObjCMethodDecl *MD) {
+ if (!MD)
+ return;
+
+ bool isTrackedLoc = false;
+
+ // Effects on the receiver.
+ if (MD->getAttr<NSConsumesSelfAttr>()) {
+ if (!GCEnabled)
+ Summ.setReceiverEffect(DecRefMsg);
+ }
+
+ // Effects on the parameters.
+ unsigned parm_idx = 0;
+ for (ObjCMethodDecl::param_iterator pi=MD->param_begin(), pe=MD->param_end();
+ pi != pe; ++pi, ++parm_idx) {
+ const ParmVarDecl *pd = *pi;
+ if (pd->getAttr<NSConsumedAttr>()) {
+ if (!GCEnabled)
+ Summ.addArg(AF, parm_idx, DecRef);
+ }
+ else if(pd->getAttr<CFConsumedAttr>()) {
+ Summ.addArg(AF, parm_idx, DecRef);
+ }
+ }
+
+ // Determine if there is a special return effect for this method.
+ if (cocoa::isCocoaObjectRef(MD->getResultType())) {
+ if (MD->getAttr<NSReturnsRetainedAttr>()) {
+ Summ.setRetEffect(ObjCAllocRetE);
+ return;
+ }
+ if (MD->getAttr<NSReturnsNotRetainedAttr>()) {
+ Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+ return;
+ }
+
+ isTrackedLoc = true;
+ }
+
+ if (!isTrackedLoc)
+ isTrackedLoc = MD->getResultType()->getAs<PointerType>() != NULL;
+
+ if (isTrackedLoc) {
+ if (MD->getAttr<CFReturnsRetainedAttr>())
+ Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+ else if (MD->getAttr<CFReturnsNotRetainedAttr>())
+ Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+ }
+}
+
+RetainSummary*
+RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
+ Selector S, QualType RetTy) {
+
+ if (MD) {
+ // Scan the method decl for 'void*' arguments. These should be treated
+ // as 'StopTracking' because they are often used with delegates.
+ // Delegates are a frequent form of false positives with the retain
+ // count checker.
+ unsigned i = 0;
+ for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
+ E = MD->param_end(); I != E; ++I, ++i)
+ if (ParmVarDecl *PD = *I) {
+ QualType Ty = Ctx.getCanonicalType(PD->getType());
+ if (Ty.getLocalUnqualifiedType() == Ctx.VoidPtrTy)
+ ScratchArgs = AF.add(ScratchArgs, i, StopTracking);
+ }
+ }
+
+ // Any special effect for the receiver?
+ ArgEffect ReceiverEff = DoNothing;
+
+ // If one of the arguments in the selector has the keyword 'delegate' we
+ // should stop tracking the reference count for the receiver. This is
+ // because the reference count is quite possibly handled by a delegate
+ // method.
+ if (S.isKeywordSelector()) {
+ const std::string &str = S.getAsString();
+ assert(!str.empty());
+ if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
+ ReceiverEff = StopTracking;
+ }
+
+ // Look for methods that return an owned object.
+ if (cocoa::isCocoaObjectRef(RetTy)) {
+ // EXPERIMENTAL: assume the Cocoa conventions for all objects returned
+ // by instance methods.
+ RetEffect E = cocoa::followsFundamentalRule(S)
+ ? ObjCAllocRetE : RetEffect::MakeNotOwned(RetEffect::ObjC);
+
+ return getPersistentSummary(E, ReceiverEff, MayEscape);
+ }
+
+ // Look for methods that return an owned core foundation object.
+ if (cocoa::isCFObjectRef(RetTy)) {
+ RetEffect E = cocoa::followsFundamentalRule(S)
+ ? RetEffect::MakeOwned(RetEffect::CF, true)
+ : RetEffect::MakeNotOwned(RetEffect::CF);
+
+ return getPersistentSummary(E, ReceiverEff, MayEscape);
+ }
+
+ if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing)
+ return getDefaultSummary();
+
+ return getPersistentSummary(RetEffect::MakeNoRet(), ReceiverEff, MayEscape);
+}
+
+RetainSummary*
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
+ const GRState *state,
+ const LocationContext *LC) {
+
+ // We need the type-information of the tracked receiver object
+ // Retrieve it from the state.
+ const Expr *Receiver = msg.getInstanceReceiver();
+ const ObjCInterfaceDecl* ID = 0;
+
+ // FIXME: Is this really working as expected? There are cases where
+ // we just use the 'ID' from the message expression.
+ SVal receiverV;
+
+ if (Receiver) {
+ receiverV = state->getSValAsScalarOrLoc(Receiver);
+
+ // FIXME: Eventually replace the use of state->get<RefBindings> with
+ // a generic API for reasoning about the Objective-C types of symbolic
+ // objects.
+ if (SymbolRef Sym = receiverV.getAsLocSymbol())
+ if (const RefVal *T = state->get<RefBindings>(Sym))
+ if (const ObjCObjectPointerType* PT =
+ T->getType()->getAs<ObjCObjectPointerType>())
+ ID = PT->getInterfaceDecl();
+
+ // FIXME: this is a hack. This may or may not be the actual method
+ // that is called.
+ if (!ID) {
+ if (const ObjCObjectPointerType *PT =
+ Receiver->getType()->getAs<ObjCObjectPointerType>())
+ ID = PT->getInterfaceDecl();
+ }
+ } else {
+ // FIXME: Hack for 'super'.
+ ID = msg.getReceiverInterface();
+ }
+
+ // FIXME: The receiver could be a reference to a class, meaning that
+ // we should use the class method.
+ RetainSummary *Summ = getInstanceMethodSummary(msg, ID);
+ return Summ ? Summ : getDefaultSummary();
+}
+
+RetainSummary*
+RetainSummaryManager::getInstanceMethodSummary(Selector S,
+ IdentifierInfo *ClsName,
+ const ObjCInterfaceDecl* ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy) {
+
+ // Look up a summary in our summary cache.
+ RetainSummary *Summ = ObjCMethodSummaries.find(ID, ClsName, S);
+
+ if (!Summ) {
+ assert(ScratchArgs.isEmpty());
+
+ // "initXXX": pass-through for receiver.
+ if (cocoa::deriveNamingConvention(S) == cocoa::InitRule)
+ Summ = getInitMethodSummary(RetTy);
+ else
+ Summ = getCommonMethodSummary(MD, S, RetTy);
+
+ // Annotations override defaults.
+ updateSummaryFromAnnotations(*Summ, MD);
+
+ // Memoize the summary.
+ ObjCMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
+ }
+
+ return Summ;
+}
+
+RetainSummary*
+RetainSummaryManager::getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
+ const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy) {
+
+ assert(ClsName && "Class name must be specified.");
+ RetainSummary *Summ = ObjCClassMethodSummaries.find(ID, ClsName, S);
+
+ if (!Summ) {
+ Summ = getCommonMethodSummary(MD, S, RetTy);
+ // Annotations override defaults.
+ updateSummaryFromAnnotations(*Summ, MD);
+ // Memoize the summary.
+ ObjCClassMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
+ }
+
+ return Summ;
+}
+
+void RetainSummaryManager::InitializeClassMethodSummaries() {
+ assert(ScratchArgs.isEmpty());
+ RetainSummary* Summ = getPersistentSummary(ObjCAllocRetE);
+
+ // Create the [NSAssertionHandler currentHander] summary.
+ addClassMethSummary("NSAssertionHandler", "currentHandler",
+ getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
+
+ // Create the [NSAutoreleasePool addObject:] summary.
+ ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
+ addClassMethSummary("NSAutoreleasePool", "addObject",
+ getPersistentSummary(RetEffect::MakeNoRet(),
+ DoNothing, Autorelease));
+
+ // Create the summaries for [NSObject performSelector...]. We treat
+ // these as 'stop tracking' for the arguments because they are often
+ // used for delegates that can release the object. When we have better
+ // inter-procedural analysis we can potentially do something better. This
+ // workaround is to remove false positives.
+ Summ = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking);
+ IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject");
+ addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+ "afterDelay", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+ "afterDelay", "inModes", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+ "withObject", "waitUntilDone", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+ "withObject", "waitUntilDone", "modes", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+ "withObject", "waitUntilDone", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+ "withObject", "waitUntilDone", "modes", NULL);
+ addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground",
+ "withObject", NULL);
+}
+
+void RetainSummaryManager::InitializeMethodSummaries() {
+
+ assert (ScratchArgs.isEmpty());
+
+ // Create the "init" selector. It just acts as a pass-through for the
+ // receiver.
+ RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
+ addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
+
+ // awakeAfterUsingCoder: behaves basically like an 'init' method. It
+ // claims the receiver and returns a retained object.
+ addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
+ InitSumm);
+
+ // The next methods are allocators.
+ RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
+ RetainSummary *CFAllocSumm =
+ getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+
+ // Create the "retain" selector.
+ RetEffect E = RetEffect::MakeReceiverAlias();
+ RetainSummary *Summ = getPersistentSummary(E, IncRefMsg);
+ addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
+
+ // Create the "release" selector.
+ Summ = getPersistentSummary(E, DecRefMsg);
+ addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
+
+ // Create the "drain" selector.
+ Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
+ addNSObjectMethSummary(GetNullarySelector("drain", Ctx), Summ);
+
+ // Create the -dealloc summary.
+ Summ = getPersistentSummary(RetEffect::MakeNoRet(), Dealloc);
+ addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
+
+ // Create the "autorelease" selector.
+ Summ = getPersistentSummary(E, Autorelease);
+ addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
+
+ // Specially handle NSAutoreleasePool.
+ addInstMethSummary("NSAutoreleasePool", "init",
+ getPersistentSummary(RetEffect::MakeReceiverAlias(),
+ NewAutoreleasePool));
+
+ // For NSWindow, allocated objects are (initially) self-owned.
+ // FIXME: For now we opt for false negatives with NSWindow, as these objects
+ // self-own themselves. However, they only do this once they are displayed.
+ // Thus, we need to track an NSWindow's display status.
+ // This is tracked in <rdar://problem/6062711>.
+ // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
+ RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
+ StopTracking,
+ StopTracking);
+
+ addClassMethSummary("NSWindow", "alloc", NoTrackYet);
+
+#if 0
+ addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
+ "styleMask", "backing", "defer", NULL);
+
+ addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
+ "styleMask", "backing", "defer", "screen", NULL);
+#endif
+
+ // For NSPanel (which subclasses NSWindow), allocated objects are not
+ // self-owned.
+ // FIXME: For now we don't track NSPanels. object for the same reason
+ // as for NSWindow objects.
+ addClassMethSummary("NSPanel", "alloc", NoTrackYet);
+
+#if 0
+ addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
+ "styleMask", "backing", "defer", NULL);
+
+ addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
+ "styleMask", "backing", "defer", "screen", NULL);
+#endif
+
+ // Don't track allocated autorelease pools yet, as it is okay to prematurely
+ // exit a method.
+ addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
+
+ // Create NSAssertionHandler summaries.
+ addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
+ "lineNumber", "description", NULL);
+
+ addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
+ "file", "lineNumber", "description", NULL);
+
+ // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
+ addInstMethSummary("QCRenderer", AllocSumm,
+ "createSnapshotImageOfType", NULL);
+ addInstMethSummary("QCView", AllocSumm,
+ "createSnapshotImageOfType", NULL);
+
+ // Create summaries for CIContext, 'createCGImage' and
+ // 'createCGLayerWithSize'. These objects are CF objects, and are not
+ // automatically garbage collected.
+ addInstMethSummary("CIContext", CFAllocSumm,
+ "createCGImage", "fromRect", NULL);
+ addInstMethSummary("CIContext", CFAllocSumm,
+ "createCGImage", "fromRect", "format", "colorSpace", NULL);
+ addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize",
+ "info", NULL);
+}
+
+//===----------------------------------------------------------------------===//
+// AutoreleaseBindings - State used to track objects in autorelease pools.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolRef, unsigned> ARCounts;
+typedef llvm::ImmutableMap<SymbolRef, ARCounts> ARPoolContents;
+typedef llvm::ImmutableList<SymbolRef> ARStack;
+
+static int AutoRCIndex = 0;
+static int AutoRBIndex = 0;
+
+namespace { class AutoreleasePoolContents {}; }
+namespace { class AutoreleaseStack {}; }
+
+namespace clang {
+namespace ento {
+template<> struct GRStateTrait<AutoreleaseStack>
+ : public GRStatePartialTrait<ARStack> {
+ static inline void* GDMIndex() { return &AutoRBIndex; }
+};
+
+template<> struct GRStateTrait<AutoreleasePoolContents>
+ : public GRStatePartialTrait<ARPoolContents> {
+ static inline void* GDMIndex() { return &AutoRCIndex; }
+};
+} // end GR namespace
+} // end clang namespace
+
+static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
+ ARStack stack = state->get<AutoreleaseStack>();
+ return stack.isEmpty() ? SymbolRef() : stack.getHead();
+}
+
+static const GRState * SendAutorelease(const GRState *state,
+ ARCounts::Factory &F, SymbolRef sym) {
+
+ SymbolRef pool = GetCurrentAutoreleasePool(state);
+ const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
+ ARCounts newCnts(0);
+
+ if (cnts) {
+ const unsigned *cnt = (*cnts).lookup(sym);
+ newCnts = F.add(*cnts, sym, cnt ? *cnt + 1 : 1);
+ }
+ else
+ newCnts = F.add(F.getEmptyMap(), sym, 1);
+
+ return state->set<AutoreleasePoolContents>(pool, newCnts);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer functions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class CFRefCount : public TransferFuncs {
+public:
+ class BindingsPrinter : public GRState::Printer {
+ public:
+ virtual void Print(llvm::raw_ostream& Out, const GRState* state,
+ const char* nl, const char* sep);
+ };
+
+private:
+ typedef llvm::DenseMap<const ExplodedNode*, const RetainSummary*>
+ SummaryLogTy;
+
+ RetainSummaryManager Summaries;
+ SummaryLogTy SummaryLog;
+ const LangOptions& LOpts;
+ ARCounts::Factory ARCountFactory;
+
+ BugType *useAfterRelease, *releaseNotOwned;
+ BugType *deallocGC, *deallocNotOwned;
+ BugType *leakWithinFunction, *leakAtReturn;
+ BugType *overAutorelease;
+ BugType *returnNotOwnedForOwned;
+ BugReporter *BR;
+
+ const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
+ RefVal::Kind& hasErr);
+
+ void ProcessNonLeakError(ExplodedNodeSet& Dst,
+ StmtNodeBuilder& Builder,
+ const Expr* NodeExpr, SourceRange ErrorRange,
+ ExplodedNode* Pred,
+ const GRState* St,
+ RefVal::Kind hasErr, SymbolRef Sym);
+
+ const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
+ llvm::SmallVectorImpl<SymbolRef> &Leaked);
+
+ ExplodedNode* ProcessLeaks(const GRState * state,
+ llvm::SmallVectorImpl<SymbolRef> &Leaked,
+ GenericNodeBuilderRefCount &Builder,
+ ExprEngine &Eng,
+ ExplodedNode *Pred = 0);
+
+public:
+ CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
+ : Summaries(Ctx, gcenabled),
+ LOpts(lopts), useAfterRelease(0), releaseNotOwned(0),
+ deallocGC(0), deallocNotOwned(0),
+ leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
+ returnNotOwnedForOwned(0), BR(0) {}
+
+ virtual ~CFRefCount() {}
+
+ void RegisterChecks(ExprEngine &Eng);
+
+ virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
+ Printers.push_back(new BindingsPrinter());
+ }
+
+ bool isGCEnabled() const { return Summaries.isGCEnabled(); }
+ const LangOptions& getLangOptions() const { return LOpts; }
+
+ const RetainSummary *getSummaryOfNode(const ExplodedNode *N) const {
+ SummaryLogTy::const_iterator I = SummaryLog.find(N);
+ return I == SummaryLog.end() ? 0 : I->second;
+ }
+
+ // Calls.
+
+ void evalSummary(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ const Expr* Ex,
+ const CallOrObjCMessage &callOrMsg,
+ InstanceReceiver Receiver,
+ const RetainSummary& Summ,
+ const MemRegion *Callee,
+ ExplodedNode* Pred, const GRState *state);
+
+ virtual void evalCall(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ const CallExpr* CE, SVal L,
+ ExplodedNode* Pred);
+
+
+ virtual void evalObjCMessage(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ObjCMessage msg,
+ ExplodedNode* Pred,
+ const GRState *state);
+ // Stores.
+ virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val);
+
+ // End-of-path.
+
+ virtual void evalEndPath(ExprEngine& Engine,
+ EndOfFunctionNodeBuilder& Builder);
+
+ virtual void evalDeadSymbols(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ ExplodedNode* Pred,
+ const GRState* state,
+ SymbolReaper& SymReaper);
+
+ std::pair<ExplodedNode*, const GRState *>
+ HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilderRefCount Bd,
+ ExplodedNode* Pred, ExprEngine &Eng,
+ SymbolRef Sym, RefVal V, bool &stop);
+ // Return statements.
+
+ virtual void evalReturn(ExplodedNodeSet& Dst,
+ ExprEngine& Engine,
+ StmtNodeBuilder& Builder,
+ const ReturnStmt* S,
+ ExplodedNode* Pred);
+
+ // Assumptions.
+
+ virtual const GRState *evalAssume(const GRState* state, SVal condition,
+ bool assumption);
+};
+
+} // end anonymous namespace
+
+static void PrintPool(llvm::raw_ostream &Out, SymbolRef Sym,
+ const GRState *state) {
+ Out << ' ';
+ if (Sym)
+ Out << Sym->getSymbolID();
+ else
+ Out << "<pool>";
+ Out << ":{";
+
+ // Get the contents of the pool.
+ if (const ARCounts *cnts = state->get<AutoreleasePoolContents>(Sym))
+ for (ARCounts::iterator J=cnts->begin(), EJ=cnts->end(); J != EJ; ++J)
+ Out << '(' << J.getKey() << ',' << J.getData() << ')';
+
+ Out << '}';
+}
+
+void CFRefCount::BindingsPrinter::Print(llvm::raw_ostream& Out,
+ const GRState* state,
+ const char* nl, const char* sep) {
+
+ RefBindings B = state->get<RefBindings>();
+
+ if (!B.isEmpty())
+ Out << sep << nl;
+
+ for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
+ Out << (*I).first << " : ";
+ (*I).second.print(Out);
+ Out << nl;
+ }
+
+ // Print the autorelease stack.
+ Out << sep << nl << "AR pool stack:";
+ ARStack stack = state->get<AutoreleaseStack>();
+
+ PrintPool(Out, SymbolRef(), state); // Print the caller's pool.
+ for (ARStack::iterator I=stack.begin(), E=stack.end(); I!=E; ++I)
+ PrintPool(Out, *I, state);
+
+ Out << nl;
+}
+
+//===----------------------------------------------------------------------===//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+ //===-------------===//
+ // Bug Descriptions. //
+ //===-------------===//
+
+ class CFRefBug : public BugType {
+ protected:
+ CFRefCount& TF;
+
+ CFRefBug(CFRefCount* tf, llvm::StringRef name)
+ : BugType(name, "Memory (Core Foundation/Objective-C)"), TF(*tf) {}
+ public:
+
+ CFRefCount& getTF() { return TF; }
+
+ // FIXME: Eventually remove.
+ virtual const char* getDescription() const = 0;
+
+ virtual bool isLeak() const { return false; }
+ };
+
+ class UseAfterRelease : public CFRefBug {
+ public:
+ UseAfterRelease(CFRefCount* tf)
+ : CFRefBug(tf, "Use-after-release") {}
+
+ const char* getDescription() const {
+ return "Reference-counted object is used after it is released";
+ }
+ };
+
+ class BadRelease : public CFRefBug {
+ public:
+ BadRelease(CFRefCount* tf) : CFRefBug(tf, "Bad release") {}
+
+ const char* getDescription() const {
+ return "Incorrect decrement of the reference count of an object that is "
+ "not owned at this point by the caller";
+ }
+ };
+
+ class DeallocGC : public CFRefBug {
+ public:
+ DeallocGC(CFRefCount *tf)
+ : CFRefBug(tf, "-dealloc called while using garbage collection") {}
+
+ const char *getDescription() const {
+ return "-dealloc called while using garbage collection";
+ }
+ };
+
+ class DeallocNotOwned : public CFRefBug {
+ public:
+ DeallocNotOwned(CFRefCount *tf)
+ : CFRefBug(tf, "-dealloc sent to non-exclusively owned object") {}
+
+ const char *getDescription() const {
+ return "-dealloc sent to object that may be referenced elsewhere";
+ }
+ };
+
+ class OverAutorelease : public CFRefBug {
+ public:
+ OverAutorelease(CFRefCount *tf) :
+ CFRefBug(tf, "Object sent -autorelease too many times") {}
+
+ const char *getDescription() const {
+ return "Object sent -autorelease too many times";
+ }
+ };
+
+ class ReturnedNotOwnedForOwned : public CFRefBug {
+ public:
+ ReturnedNotOwnedForOwned(CFRefCount *tf) :
+ CFRefBug(tf, "Method should return an owned object") {}
+
+ const char *getDescription() const {
+ return "Object with +0 retain counts returned to caller where a +1 "
+ "(owning) retain count is expected";
+ }
+ };
+
+ class Leak : public CFRefBug {
+ const bool isReturn;
+ protected:
+ Leak(CFRefCount* tf, llvm::StringRef name, bool isRet)
+ : CFRefBug(tf, name), isReturn(isRet) {}
+ public:
+
+ const char* getDescription() const { return ""; }
+
+ bool isLeak() const { return true; }
+ };
+
+ class LeakAtReturn : public Leak {
+ public:
+ LeakAtReturn(CFRefCount* tf, llvm::StringRef name)
+ : Leak(tf, name, true) {}
+ };
+
+ class LeakWithinFunction : public Leak {
+ public:
+ LeakWithinFunction(CFRefCount* tf, llvm::StringRef name)
+ : Leak(tf, name, false) {}
+ };
+
+ //===---------===//
+ // Bug Reports. //
+ //===---------===//
+
+ class CFRefReport : public RangedBugReport {
+ protected:
+ SymbolRef Sym;
+ const CFRefCount &TF;
+ public:
+ CFRefReport(CFRefBug& D, const CFRefCount &tf,
+ ExplodedNode *n, SymbolRef sym)
+ : RangedBugReport(D, D.getDescription(), n), Sym(sym), TF(tf) {}
+
+ CFRefReport(CFRefBug& D, const CFRefCount &tf,
+ ExplodedNode *n, SymbolRef sym, llvm::StringRef endText)
+ : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
+
+ virtual ~CFRefReport() {}
+
+ CFRefBug& getBugType() const {
+ return (CFRefBug&) RangedBugReport::getBugType();
+ }
+
+ virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const {
+ if (!getBugType().isLeak())
+ return RangedBugReport::getRanges();
+ else
+ return std::make_pair(ranges_iterator(), ranges_iterator());
+ }
+
+ SymbolRef getSymbol() const { return Sym; }
+
+ PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* N);
+
+ std::pair<const char**,const char**> getExtraDescriptiveText();
+
+ PathDiagnosticPiece* VisitNode(const ExplodedNode* N,
+ const ExplodedNode* PrevN,
+ BugReporterContext& BRC);
+ };
+
+ class CFRefLeakReport : public CFRefReport {
+ SourceLocation AllocSite;
+ const MemRegion* AllocBinding;
+ public:
+ CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
+ ExplodedNode *n, SymbolRef sym,
+ ExprEngine& Eng);
+
+ PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* N);
+
+ SourceLocation getLocation() const { return AllocSite; }
+ };
+} // end anonymous namespace
+
+
+
+static const char* Msgs[] = {
+ // GC only
+ "Code is compiled to only use garbage collection",
+ // No GC.
+ "Code is compiled to use reference counts",
+ // Hybrid, with GC.
+ "Code is compiled to use either garbage collection (GC) or reference counts"
+ " (non-GC). The bug occurs with GC enabled",
+ // Hybrid, without GC
+ "Code is compiled to use either garbage collection (GC) or reference counts"
+ " (non-GC). The bug occurs in non-GC mode"
+};
+
+std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() {
+ CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF();
+
+ switch (TF.getLangOptions().getGCMode()) {
+ default:
+ assert(false);
+
+ case LangOptions::GCOnly:
+ assert (TF.isGCEnabled());
+ return std::make_pair(&Msgs[0], &Msgs[0]+1);
+
+ case LangOptions::NonGC:
+ assert (!TF.isGCEnabled());
+ return std::make_pair(&Msgs[1], &Msgs[1]+1);
+
+ case LangOptions::HybridGC:
+ if (TF.isGCEnabled())
+ return std::make_pair(&Msgs[2], &Msgs[2]+1);
+ else
+ return std::make_pair(&Msgs[3], &Msgs[3]+1);
+ }
+}
+
+static inline bool contains(const llvm::SmallVectorImpl<ArgEffect>& V,
+ ArgEffect X) {
+ for (llvm::SmallVectorImpl<ArgEffect>::const_iterator I=V.begin(), E=V.end();
+ I!=E; ++I)
+ if (*I == X) return true;
+
+ return false;
+}
+
+PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N,
+ const ExplodedNode* PrevN,
+ BugReporterContext& BRC) {
+
+ if (!isa<PostStmt>(N->getLocation()))
+ return NULL;
+
+ // Check if the type state has changed.
+ const GRState *PrevSt = PrevN->getState();
+ const GRState *CurrSt = N->getState();
+
+ const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
+ if (!CurrT) return NULL;
+
+ const RefVal &CurrV = *CurrT;
+ const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
+
+ // Create a string buffer to constain all the useful things we want
+ // to tell the user.
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ // This is the allocation site since the previous node had no bindings
+ // for this symbol.
+ if (!PrevT) {
+ const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ // Get the name of the callee (if it is available).
+ SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
+ if (const FunctionDecl* FD = X.getAsFunctionDecl())
+ os << "Call to function '" << FD << '\'';
+ else
+ os << "function call";
+ }
+ else if (isa<ObjCMessageExpr>(S)) {
+ os << "Method";
+ } else {
+ os << "Property";
+ }
+
+ if (CurrV.getObjKind() == RetEffect::CF) {
+ os << " returns a Core Foundation object with a ";
+ }
+ else {
+ assert (CurrV.getObjKind() == RetEffect::ObjC);
+ os << " returns an Objective-C object with a ";
+ }
+
+ if (CurrV.isOwned()) {
+ os << "+1 retain count (owning reference).";
+
+ if (static_cast<CFRefBug&>(getBugType()).getTF().isGCEnabled()) {
+ assert(CurrV.getObjKind() == RetEffect::CF);
+ os << " "
+ "Core Foundation objects are not automatically garbage collected.";
+ }
+ }
+ else {
+ assert (CurrV.isNotOwned());
+ os << "+0 retain count (non-owning reference).";
+ }
+
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(Pos, os.str());
+ }
+
+ // Gather up the effects that were performed on the object at this
+ // program point
+ llvm::SmallVector<ArgEffect, 2> AEffects;
+
+ if (const RetainSummary *Summ =
+ TF.getSummaryOfNode(BRC.getNodeResolver().getOriginalNode(N))) {
+ // We only have summaries attached to nodes after evaluating CallExpr and
+ // ObjCMessageExprs.
+ const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
+
+ if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ // Iterate through the parameter expressions and see if the symbol
+ // was ever passed as an argument.
+ unsigned i = 0;
+
+ for (CallExpr::const_arg_iterator AI=CE->arg_begin(), AE=CE->arg_end();
+ AI!=AE; ++AI, ++i) {
+
+ // Retrieve the value of the argument. Is it the symbol
+ // we are interested in?
+ if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
+ continue;
+
+ // We have an argument. Get the effect!
+ AEffects.push_back(Summ->getArg(i));
+ }
+ }
+ else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
+ if (const Expr *receiver = ME->getInstanceReceiver())
+ if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
+ // The symbol we are tracking is the receiver.
+ AEffects.push_back(Summ->getReceiverEffect());
+ }
+ }
+ }
+
+ do {
+ // Get the previous type state.
+ RefVal PrevV = *PrevT;
+
+ // Specially handle -dealloc.
+ if (!TF.isGCEnabled() && contains(AEffects, Dealloc)) {
+ // Determine if the object's reference count was pushed to zero.
+ assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
+ // We may not have transitioned to 'release' if we hit an error.
+ // This case is handled elsewhere.
+ if (CurrV.getKind() == RefVal::Released) {
+ assert(CurrV.getCombinedCounts() == 0);
+ os << "Object released by directly sending the '-dealloc' message";
+ break;
+ }
+ }
+
+ // Specially handle CFMakeCollectable and friends.
+ if (contains(AEffects, MakeCollectable)) {
+ // Get the name of the function.
+ const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
+ SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+ const FunctionDecl* FD = X.getAsFunctionDecl();
+ const std::string& FName = FD->getNameAsString();
+
+ if (TF.isGCEnabled()) {
+ // Determine if the object's reference count was pushed to zero.
+ assert(!(PrevV == CurrV) && "The typestate *must* have changed.");
+
+ os << "In GC mode a call to '" << FName
+ << "' decrements an object's retain count and registers the "
+ "object with the garbage collector. ";
+
+ if (CurrV.getKind() == RefVal::Released) {
+ assert(CurrV.getCount() == 0);
+ os << "Since it now has a 0 retain count the object can be "
+ "automatically collected by the garbage collector.";
+ }
+ else
+ os << "An object must have a 0 retain count to be garbage collected. "
+ "After this call its retain count is +" << CurrV.getCount()
+ << '.';
+ }
+ else
+ os << "When GC is not enabled a call to '" << FName
+ << "' has no effect on its argument.";
+
+ // Nothing more to say.
+ break;
+ }
+
+ // Determine if the typestate has changed.
+ if (!(PrevV == CurrV))
+ switch (CurrV.getKind()) {
+ case RefVal::Owned:
+ case RefVal::NotOwned:
+
+ if (PrevV.getCount() == CurrV.getCount()) {
+ // Did an autorelease message get sent?
+ if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
+ return 0;
+
+ assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
+ os << "Object sent -autorelease message";
+ break;
+ }
+
+ if (PrevV.getCount() > CurrV.getCount())
+ os << "Reference count decremented.";
+ else
+ os << "Reference count incremented.";
+
+ if (unsigned Count = CurrV.getCount())
+ os << " The object now has a +" << Count << " retain count.";
+
+ if (PrevV.getKind() == RefVal::Released) {
+ assert(TF.isGCEnabled() && CurrV.getCount() > 0);
+ os << " The object is not eligible for garbage collection until the "
+ "retain count reaches 0 again.";
+ }
+
+ break;
+
+ case RefVal::Released:
+ os << "Object released.";
+ break;
+
+ case RefVal::ReturnedOwned:
+ os << "Object returned to caller as an owning reference (single retain "
+ "count transferred to caller).";
+ break;
+
+ case RefVal::ReturnedNotOwned:
+ os << "Object returned to caller with a +0 (non-owning) retain count.";
+ break;
+
+ default:
+ return NULL;
+ }
+
+ // Emit any remaining diagnostics for the argument effects (if any).
+ for (llvm::SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
+ E=AEffects.end(); I != E; ++I) {
+
+ // A bunch of things have alternate behavior under GC.
+ if (TF.isGCEnabled())
+ switch (*I) {
+ default: break;
+ case Autorelease:
+ os << "In GC mode an 'autorelease' has no effect.";
+ continue;
+ case IncRefMsg:
+ os << "In GC mode the 'retain' message has no effect.";
+ continue;
+ case DecRefMsg:
+ os << "In GC mode the 'release' message has no effect.";
+ continue;
+ }
+ }
+ } while (0);
+
+ if (os.str().empty())
+ return 0; // We have nothing to say!
+
+ const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager());
+ PathDiagnosticPiece* P = new PathDiagnosticEventPiece(Pos, os.str());
+
+ // Add the range by scanning the children of the statement for any bindings
+ // to Sym.
+ for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
+ I!=E; ++I)
+ if (const Expr* Exp = dyn_cast_or_null<Expr>(*I))
+ if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
+ P->addRange(Exp->getSourceRange());
+ break;
+ }
+
+ return P;
+}
+
+namespace {
+ class FindUniqueBinding :
+ public StoreManager::BindingsHandler {
+ SymbolRef Sym;
+ const MemRegion* Binding;
+ bool First;
+
+ public:
+ FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {}
+
+ bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
+ SVal val) {
+
+ SymbolRef SymV = val.getAsSymbol();
+ if (!SymV || SymV != Sym)
+ return true;
+
+ if (Binding) {
+ First = false;
+ return false;
+ }
+ else
+ Binding = R;
+
+ return true;
+ }
+
+ operator bool() { return First && Binding; }
+ const MemRegion* getRegion() { return Binding; }
+ };
+}
+
+static std::pair<const ExplodedNode*,const MemRegion*>
+GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode* N,
+ SymbolRef Sym) {
+
+ // Find both first node that referred to the tracked symbol and the
+ // memory location that value was store to.
+ const ExplodedNode* Last = N;
+ const MemRegion* FirstBinding = 0;
+
+ while (N) {
+ const GRState* St = N->getState();
+ RefBindings B = St->get<RefBindings>();
+
+ if (!B.lookup(Sym))
+ break;
+
+ FindUniqueBinding FB(Sym);
+ StateMgr.iterBindings(St, FB);
+ if (FB) FirstBinding = FB.getRegion();
+
+ Last = N;
+ N = N->pred_empty() ? NULL : *(N->pred_begin());
+ }
+
+ return std::make_pair(Last, FirstBinding);
+}
+
+PathDiagnosticPiece*
+CFRefReport::getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* EndN) {
+ // Tell the BugReporterContext to report cases when the tracked symbol is
+ // assigned to different variables, etc.
+ BRC.addNotableSymbol(Sym);
+ return RangedBugReport::getEndPath(BRC, EndN);
+}
+
+PathDiagnosticPiece*
+CFRefLeakReport::getEndPath(BugReporterContext& BRC,
+ const ExplodedNode* EndN){
+
+ // Tell the BugReporterContext to report cases when the tracked symbol is
+ // assigned to different variables, etc.
+ BRC.addNotableSymbol(Sym);
+
+ // We are reporting a leak. Walk up the graph to get to the first node where
+ // the symbol appeared, and also get the first VarDecl that tracked object
+ // is stored to.
+ const ExplodedNode* AllocNode = 0;
+ const MemRegion* FirstBinding = 0;
+
+ llvm::tie(AllocNode, FirstBinding) =
+ GetAllocationSite(BRC.getStateManager(), EndN, Sym);
+
+ // Get the allocate site.
+ assert(AllocNode);
+ const Stmt* FirstStmt = cast<PostStmt>(AllocNode->getLocation()).getStmt();
+
+ SourceManager& SMgr = BRC.getSourceManager();
+ unsigned AllocLine =SMgr.getInstantiationLineNumber(FirstStmt->getLocStart());
+
+ // Compute an actual location for the leak. Sometimes a leak doesn't
+ // occur at an actual statement (e.g., transition between blocks; end
+ // of function) so we need to walk the graph and compute a real location.
+ const ExplodedNode* LeakN = EndN;
+ PathDiagnosticLocation L;
+
+ while (LeakN) {
+ ProgramPoint P = LeakN->getLocation();
+
+ if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
+ L = PathDiagnosticLocation(PS->getStmt()->getLocStart(), SMgr);
+ break;
+ }
+ else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ if (const Stmt* Term = BE->getSrc()->getTerminator()) {
+ L = PathDiagnosticLocation(Term->getLocStart(), SMgr);
+ break;
+ }
+ }
+
+ LeakN = LeakN->succ_empty() ? 0 : *(LeakN->succ_begin());
+ }
+
+ if (!L.isValid()) {
+ const Decl &D = EndN->getCodeDecl();
+ L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr);
+ }
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "Object allocated on line " << AllocLine;
+
+ if (FirstBinding)
+ os << " and stored into '" << FirstBinding->getString() << '\'';
+
+ // Get the retain count.
+ const RefVal* RV = EndN->getState()->get<RefBindings>(Sym);
+
+ if (RV->getKind() == RefVal::ErrorLeakReturned) {
+ // FIXME: Per comments in rdar://6320065, "create" only applies to CF
+ // ojbects. Only "copy", "alloc", "retain" and "new" transfer ownership
+ // to the caller for NS objects.
+ ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
+ os << " is returned from a method whose name ('"
+ << MD.getSelector().getAsString()
+ << "') does not contain 'copy' or otherwise starts with"
+ " 'new' or 'alloc'. This violates the naming convention rules given"
+ " in the Memory Management Guide for Cocoa (object leaked)";
+ }
+ else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
+ ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
+ os << " and returned from method '" << MD.getSelector().getAsString()
+ << "' is potentially leaked when using garbage collection. Callers "
+ "of this method do not expect a returned object with a +1 retain "
+ "count since they expect the object to be managed by the garbage "
+ "collector";
+ }
+ else
+ os << " is not referenced later in this execution path and has a retain "
+ "count of +" << RV->getCount() << " (object leaked)";
+
+ return new PathDiagnosticEventPiece(L, os.str());
+}
+
+CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf,
+ ExplodedNode *n,
+ SymbolRef sym, ExprEngine& Eng)
+: CFRefReport(D, tf, n, sym) {
+
+ // Most bug reports are cached at the location where they occured.
+ // With leaks, we want to unique them by the location where they were
+ // allocated, and only report a single path. To do this, we need to find
+ // the allocation site of a piece of tracked memory, which we do via a
+ // call to GetAllocationSite. This will walk the ExplodedGraph backwards.
+ // Note that this is *not* the trimmed graph; we are guaranteed, however,
+ // that all ancestor nodes that represent the allocation site have the
+ // same SourceLocation.
+ const ExplodedNode* AllocNode = 0;
+
+ llvm::tie(AllocNode, AllocBinding) = // Set AllocBinding.
+ GetAllocationSite(Eng.getStateManager(), getErrorNode(), getSymbol());
+
+ // Get the SourceLocation for the allocation site.
+ ProgramPoint P = AllocNode->getLocation();
+ AllocSite = cast<PostStmt>(P).getStmt()->getLocStart();
+
+ // Fill in the description of the bug.
+ Description.clear();
+ llvm::raw_string_ostream os(Description);
+ SourceManager& SMgr = Eng.getContext().getSourceManager();
+ unsigned AllocLine = SMgr.getInstantiationLineNumber(AllocSite);
+ os << "Potential leak ";
+ if (tf.isGCEnabled()) {
+ os << "(when using garbage collection) ";
+ }
+ os << "of an object allocated on line " << AllocLine;
+
+ // FIXME: AllocBinding doesn't get populated for RegionStore yet.
+ if (AllocBinding)
+ os << " and stored into '" << AllocBinding->getString() << '\'';
+}
+
+//===----------------------------------------------------------------------===//
+// Main checker logic.
+//===----------------------------------------------------------------------===//
+
+/// GetReturnType - Used to get the return type of a message expression or
+/// function call with the intention of affixing that type to a tracked symbol.
+/// While the the return type can be queried directly from RetEx, when
+/// invoking class methods we augment to the return type to be that of
+/// a pointer to the class (as opposed it just being id).
+static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
+ QualType RetTy = RetE->getType();
+ // If RetE is not a message expression just return its type.
+ // If RetE is a message expression, return its types if it is something
+ /// more specific than id.
+ if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE))
+ if (const ObjCObjectPointerType *PT = RetTy->getAs<ObjCObjectPointerType>())
+ if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
+ PT->isObjCClassType()) {
+ // At this point we know the return type of the message expression is
+ // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
+ // is a call to a class method whose type we can resolve. In such
+ // cases, promote the return type to XXX* (where XXX is the class).
+ const ObjCInterfaceDecl *D = ME->getReceiverInterface();
+ return !D ? RetTy :
+ Ctx.getObjCObjectPointerType(Ctx.getObjCInterfaceType(D));
+ }
+
+ return RetTy;
+}
+
+void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ const Expr* Ex,
+ const CallOrObjCMessage &callOrMsg,
+ InstanceReceiver Receiver,
+ const RetainSummary& Summ,
+ const MemRegion *Callee,
+ ExplodedNode* Pred, const GRState *state) {
+
+ // Evaluate the effect of the arguments.
+ RefVal::Kind hasErr = (RefVal::Kind) 0;
+ SourceRange ErrorRange;
+ SymbolRef ErrorSym = 0;
+
+ llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
+
+ // HACK: Symbols that have ref-count state that are referenced directly
+ // (not as structure or array elements, or via bindings) by an argument
+ // should not have their ref-count state stripped after we have
+ // done an invalidation pass.
+ llvm::DenseSet<SymbolRef> WhitelistedSymbols;
+
+ // Invalidate all instance variables of the receiver of a message.
+ // FIXME: We should be able to do better with inter-procedural analysis.
+ if (Receiver) {
+ SVal V = Receiver.getSValAsScalarOrLoc(state);
+ if (SymbolRef Sym = V.getAsLocSymbol()) {
+ if (state->get<RefBindings>(Sym))
+ WhitelistedSymbols.insert(Sym);
+ }
+ if (const MemRegion *region = V.getAsRegion())
+ RegionsToInvalidate.push_back(region);
+ }
+
+ for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) {
+ SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
+ SymbolRef Sym = V.getAsLocSymbol();
+
+ if (Sym)
+ if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
+ WhitelistedSymbols.insert(Sym);
+ state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
+ if (hasErr) {
+ ErrorRange = callOrMsg.getArgSourceRange(idx);
+ ErrorSym = Sym;
+ break;
+ }
+ }
+
+ tryAgain:
+ if (isa<Loc>(V)) {
+ if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(&V)) {
+ if (Summ.getArg(idx) == DoNothingByRef)
+ continue;
+
+ // Invalidate the value of the variable passed by reference.
+ const MemRegion *R = MR->getRegion();
+
+ // Are we dealing with an ElementRegion? If the element type is
+ // a basic integer type (e.g., char, int) and the underying region
+ // is a variable region then strip off the ElementRegion.
+ // FIXME: We really need to think about this for the general case
+ // as sometimes we are reasoning about arrays and other times
+ // about (char*), etc., is just a form of passing raw bytes.
+ // e.g., void *p = alloca(); foo((char*)p);
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ // Checking for 'integral type' is probably too promiscuous, but
+ // we'll leave it in for now until we have a systematic way of
+ // handling all of these cases. Eventually we need to come up
+ // with an interface to StoreManager so that this logic can be
+ // approriately delegated to the respective StoreManagers while
+ // still allowing us to do checker-specific logic (e.g.,
+ // invalidating reference counts), probably via callbacks.
+ if (ER->getElementType()->isIntegralOrEnumerationType()) {
+ const MemRegion *superReg = ER->getSuperRegion();
+ if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
+ isa<ObjCIvarRegion>(superReg))
+ R = cast<TypedRegion>(superReg);
+ }
+ // FIXME: What about layers of ElementRegions?
+ }
+
+ // Mark this region for invalidation. We batch invalidate regions
+ // below for efficiency.
+ RegionsToInvalidate.push_back(R);
+ continue;
+ }
+ else {
+ // Nuke all other arguments passed by reference.
+ // FIXME: is this necessary or correct? This handles the non-Region
+ // cases. Is it ever valid to store to these?
+ state = state->unbindLoc(cast<Loc>(V));
+ }
+ }
+ else if (isa<nonloc::LocAsInteger>(V)) {
+ // If we are passing a location wrapped as an integer, unwrap it and
+ // invalidate the values referred by the location.
+ V = cast<nonloc::LocAsInteger>(V).getLoc();
+ goto tryAgain;
+ }
+ }
+
+ // Block calls result in all captured values passed-via-reference to be
+ // invalidated.
+ if (const BlockDataRegion *BR = dyn_cast_or_null<BlockDataRegion>(Callee)) {
+ RegionsToInvalidate.push_back(BR);
+ }
+
+ // Invalidate regions we designed for invalidation use the batch invalidation
+ // API.
+
+ // FIXME: We can have collisions on the conjured symbol if the
+ // expression *I also creates conjured symbols. We probably want
+ // to identify conjured symbols by an expression pair: the enclosing
+ // expression (the context) and the expression itself. This should
+ // disambiguate conjured symbols.
+ unsigned Count = Builder.getCurrentBlockCount();
+ StoreManager::InvalidatedSymbols IS;
+
+ // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
+ // global variables.
+ state = state->invalidateRegions(RegionsToInvalidate.data(),
+ RegionsToInvalidate.data() +
+ RegionsToInvalidate.size(),
+ Ex, Count, &IS,
+ /* invalidateGlobals = */ true);
+
+ for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
+ E = IS.end(); I!=E; ++I) {
+ SymbolRef sym = *I;
+ if (WhitelistedSymbols.count(sym))
+ continue;
+ // Remove any existing reference-count binding.
+ state = state->remove<RefBindings>(*I);
+ }
+
+ // Evaluate the effect on the message receiver.
+ if (!ErrorRange.isValid() && Receiver) {
+ SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol();
+ if (Sym) {
+ if (const RefVal* T = state->get<RefBindings>(Sym)) {
+ state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
+ if (hasErr) {
+ ErrorRange = Receiver.getSourceRange();
+ ErrorSym = Sym;
+ }
+ }
+ }
+ }
+
+ // Process any errors.
+ if (hasErr) {
+ ProcessNonLeakError(Dst, Builder, Ex, ErrorRange, Pred, state,
+ hasErr, ErrorSym);
+ return;
+ }
+
+ // Consult the summary for the return value.
+ RetEffect RE = Summ.getRetEffect();
+
+ if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
+ bool found = false;
+ if (Receiver) {
+ SVal V = Receiver.getSValAsScalarOrLoc(state);
+ if (SymbolRef Sym = V.getAsLocSymbol())
+ if (state->get<RefBindings>(Sym)) {
+ found = true;
+ RE = Summaries.getObjAllocRetEffect();
+ }
+ } // FIXME: Otherwise, this is a send-to-super instance message.
+ if (!found)
+ RE = RetEffect::MakeNoRet();
+ }
+
+ switch (RE.getKind()) {
+ default:
+ assert (false && "Unhandled RetEffect."); break;
+
+ case RetEffect::NoRet: {
+ // Make up a symbol for the return value (not reference counted).
+ // FIXME: Most of this logic is not specific to the retain/release
+ // checker.
+
+ // FIXME: We eventually should handle structs and other compound types
+ // that are returned by value.
+
+ QualType T = callOrMsg.getResultType(Eng.getContext());
+ if (Loc::isLocType(T) || (T->isIntegerType() && T->isScalarType())) {
+ unsigned Count = Builder.getCurrentBlockCount();
+ SValBuilder &svalBuilder = Eng.getSValBuilder();
+ SVal X = svalBuilder.getConjuredSymbolVal(NULL, Ex, T, Count);
+ state = state->BindExpr(Ex, X, false);
+ }
+
+ break;
+ }
+
+ case RetEffect::Alias: {
+ unsigned idx = RE.getIndex();
+ assert (idx < callOrMsg.getNumArgs());
+ SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
+ state = state->BindExpr(Ex, V, false);
+ break;
+ }
+
+ case RetEffect::ReceiverAlias: {
+ assert(Receiver);
+ SVal V = Receiver.getSValAsScalarOrLoc(state);
+ state = state->BindExpr(Ex, V, false);
+ break;
+ }
+
+ case RetEffect::OwnedAllocatedSymbol:
+ case RetEffect::OwnedSymbol: {
+ unsigned Count = Builder.getCurrentBlockCount();
+ SValBuilder &svalBuilder = Eng.getSValBuilder();
+ SymbolRef Sym = svalBuilder.getConjuredSymbol(Ex, Count);
+ QualType RetT = GetReturnType(Ex, svalBuilder.getContext());
+ state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
+ RetT));
+ state = state->BindExpr(Ex, svalBuilder.makeLoc(Sym), false);
+
+ // FIXME: Add a flag to the checker where allocations are assumed to
+ // *not fail.
+#if 0
+ if (RE.getKind() == RetEffect::OwnedAllocatedSymbol) {
+ bool isFeasible;
+ state = state.assume(loc::SymbolVal(Sym), true, isFeasible);
+ assert(isFeasible && "Cannot assume fresh symbol is non-null.");
+ }
+#endif
+
+ break;
+ }
+
+ case RetEffect::GCNotOwnedSymbol:
+ case RetEffect::NotOwnedSymbol: {
+ unsigned Count = Builder.getCurrentBlockCount();
+ SValBuilder &svalBuilder = Eng.getSValBuilder();
+ SymbolRef Sym = svalBuilder.getConjuredSymbol(Ex, Count);
+ QualType RetT = GetReturnType(Ex, svalBuilder.getContext());
+ state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
+ RetT));
+ state = state->BindExpr(Ex, svalBuilder.makeLoc(Sym), false);
+ break;
+ }
+ }
+
+ // Generate a sink node if we are at the end of a path.
+ ExplodedNode *NewNode =
+ Summ.isEndPath() ? Builder.MakeSinkNode(Dst, Ex, Pred, state)
+ : Builder.MakeNode(Dst, Ex, Pred, state);
+
+ // Annotate the edge with summary we used.
+ if (NewNode) SummaryLog[NewNode] = &Summ;
+}
+
+
+void CFRefCount::evalCall(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ const CallExpr* CE, SVal L,
+ ExplodedNode* Pred) {
+
+ RetainSummary *Summ = 0;
+
+ // FIXME: Better support for blocks. For now we stop tracking anything
+ // that is passed to blocks.
+ // FIXME: Need to handle variables that are "captured" by the block.
+ if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
+ Summ = Summaries.getPersistentStopSummary();
+ }
+ else {
+ const FunctionDecl* FD = L.getAsFunctionDecl();
+ Summ = !FD ? Summaries.getDefaultSummary() :
+ Summaries.getSummary(FD);
+ }
+
+ assert(Summ);
+ evalSummary(Dst, Eng, Builder, CE,
+ CallOrObjCMessage(CE, Builder.GetState(Pred)),
+ InstanceReceiver(), *Summ,L.getAsRegion(),
+ Pred, Builder.GetState(Pred));
+}
+
+void CFRefCount::evalObjCMessage(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ ObjCMessage msg,
+ ExplodedNode* Pred,
+ const GRState *state) {
+ RetainSummary *Summ =
+ msg.isInstanceMessage()
+ ? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext())
+ : Summaries.getClassMethodSummary(msg);
+
+ assert(Summ && "RetainSummary is null");
+ evalSummary(Dst, Eng, Builder, msg.getOriginExpr(),
+ CallOrObjCMessage(msg, Builder.GetState(Pred)),
+ InstanceReceiver(msg, Pred->getLocationContext()), *Summ, NULL,
+ Pred, state);
+}
+
+namespace {
+class StopTrackingCallback : public SymbolVisitor {
+ const GRState *state;
+public:
+ StopTrackingCallback(const GRState *st) : state(st) {}
+ const GRState *getState() const { return state; }
+
+ bool VisitSymbol(SymbolRef sym) {
+ state = state->remove<RefBindings>(sym);
+ return true;
+ }
+};
+} // end anonymous namespace
+
+
+void CFRefCount::evalBind(StmtNodeBuilderRef& B, SVal location, SVal val) {
+ // Are we storing to something that causes the value to "escape"?
+ bool escapes = false;
+
+ // A value escapes in three possible cases (this may change):
+ //
+ // (1) we are binding to something that is not a memory region.
+ // (2) we are binding to a memregion that does not have stack storage
+ // (3) we are binding to a memregion with stack storage that the store
+ // does not understand.
+ const GRState *state = B.getState();
+
+ if (!isa<loc::MemRegionVal>(location))
+ escapes = true;
+ else {
+ const MemRegion* R = cast<loc::MemRegionVal>(location).getRegion();
+ escapes = !R->hasStackStorage();
+
+ if (!escapes) {
+ // To test (3), generate a new state with the binding removed. If it is
+ // the same state, then it escapes (since the store cannot represent
+ // the binding).
+ escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
+ }
+ }
+
+ // If our store can represent the binding and we aren't storing to something
+ // that doesn't have local storage then just return and have the simulation
+ // state continue as is.
+ if (!escapes)
+ return;
+
+ // Otherwise, find all symbols referenced by 'val' that we are tracking
+ // and stop tracking them.
+ B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
+}
+
+ // Return statements.
+
+void CFRefCount::evalReturn(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ const ReturnStmt* S,
+ ExplodedNode* Pred) {
+
+ const Expr* RetE = S->getRetValue();
+ if (!RetE)
+ return;
+
+ const GRState *state = Builder.GetState(Pred);
+ SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
+
+ if (!Sym)
+ return;
+
+ // Get the reference count binding (if any).
+ const RefVal* T = state->get<RefBindings>(Sym);
+
+ if (!T)
+ return;
+
+ // Change the reference count.
+ RefVal X = *T;
+
+ switch (X.getKind()) {
+ case RefVal::Owned: {
+ unsigned cnt = X.getCount();
+ assert (cnt > 0);
+ X.setCount(cnt - 1);
+ X = X ^ RefVal::ReturnedOwned;
+ break;
+ }
+
+ case RefVal::NotOwned: {
+ unsigned cnt = X.getCount();
+ if (cnt) {
+ X.setCount(cnt - 1);
+ X = X ^ RefVal::ReturnedOwned;
+ }
+ else {
+ X = X ^ RefVal::ReturnedNotOwned;
+ }
+ break;
+ }
+
+ default:
+ return;
+ }
+
+ // Update the binding.
+ state = state->set<RefBindings>(Sym, X);
+ Pred = Builder.MakeNode(Dst, S, Pred, state);
+
+ // Did we cache out?
+ if (!Pred)
+ return;
+
+ // Update the autorelease counts.
+ static unsigned autoreleasetag = 0;
+ GenericNodeBuilderRefCount Bd(Builder, S, &autoreleasetag);
+ bool stop = false;
+ llvm::tie(Pred, state) = HandleAutoreleaseCounts(state , Bd, Pred, Eng, Sym,
+ X, stop);
+
+ // Did we cache out?
+ if (!Pred || stop)
+ return;
+
+ // Get the updated binding.
+ T = state->get<RefBindings>(Sym);
+ assert(T);
+ X = *T;
+
+ // Any leaks or other errors?
+ if (X.isReturnedOwned() && X.getCount() == 0) {
+ Decl const *CD = &Pred->getCodeDecl();
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
+ const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
+ RetEffect RE = Summ.getRetEffect();
+ bool hasError = false;
+
+ if (RE.getKind() != RetEffect::NoRet) {
+ if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
+ // Things are more complicated with garbage collection. If the
+ // returned object is suppose to be an Objective-C object, we have
+ // a leak (as the caller expects a GC'ed object) because no
+ // method should return ownership unless it returns a CF object.
+ hasError = true;
+ X = X ^ RefVal::ErrorGCLeakReturned;
+ }
+ else if (!RE.isOwned()) {
+ // Either we are using GC and the returned object is a CF type
+ // or we aren't using GC. In either case, we expect that the
+ // enclosing method is expected to return ownership.
+ hasError = true;
+ X = X ^ RefVal::ErrorLeakReturned;
+ }
+ }
+
+ if (hasError) {
+ // Generate an error node.
+ static int ReturnOwnLeakTag = 0;
+ state = state->set<RefBindings>(Sym, X);
+ ExplodedNode *N =
+ Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
+ &ReturnOwnLeakTag), state, Pred);
+ if (N) {
+ CFRefReport *report =
+ new CFRefLeakReport(*static_cast<CFRefBug*>(leakAtReturn), *this,
+ N, Sym, Eng);
+ BR->EmitReport(report);
+ }
+ }
+ }
+ }
+ else if (X.isReturnedNotOwned()) {
+ Decl const *CD = &Pred->getCodeDecl();
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
+ const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
+ if (Summ.getRetEffect().isOwned()) {
+ // Trying to return a not owned object to a caller expecting an
+ // owned object.
+
+ static int ReturnNotOwnedForOwnedTag = 0;
+ state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
+ if (ExplodedNode *N =
+ Builder.generateNode(PostStmt(S, Pred->getLocationContext(),
+ &ReturnNotOwnedForOwnedTag),
+ state, Pred)) {
+ CFRefReport *report =
+ new CFRefReport(*static_cast<CFRefBug*>(returnNotOwnedForOwned),
+ *this, N, Sym);
+ BR->EmitReport(report);
+ }
+ }
+ }
+ }
+}
+
+// Assumptions.
+
+const GRState* CFRefCount::evalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
+
+ // FIXME: We may add to the interface of evalAssume the list of symbols
+ // whose assumptions have changed. For now we just iterate through the
+ // bindings and check if any of the tracked symbols are NULL. This isn't
+ // too bad since the number of symbols we will track in practice are
+ // probably small and evalAssume is only called at branches and a few
+ // other places.
+ RefBindings B = state->get<RefBindings>();
+
+ if (B.isEmpty())
+ return state;
+
+ bool changed = false;
+ RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
+
+ for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
+ // Check if the symbol is null (or equal to any constant).
+ // If this is the case, stop tracking the symbol.
+ if (state->getSymVal(I.getKey())) {
+ changed = true;
+ B = RefBFactory.remove(B, I.getKey());
+ }
+ }
+
+ if (changed)
+ state = state->set<RefBindings>(B);
+
+ return state;
+}
+
+const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
+ RefVal V, ArgEffect E,
+ RefVal::Kind& hasErr) {
+
+ // In GC mode [... release] and [... retain] do nothing.
+ switch (E) {
+ default: break;
+ case IncRefMsg: E = isGCEnabled() ? DoNothing : IncRef; break;
+ case DecRefMsg: E = isGCEnabled() ? DoNothing : DecRef; break;
+ case MakeCollectable: E = isGCEnabled() ? DecRef : DoNothing; break;
+ case NewAutoreleasePool: E = isGCEnabled() ? DoNothing :
+ NewAutoreleasePool; break;
+ }
+
+ // Handle all use-after-releases.
+ if (!isGCEnabled() && V.getKind() == RefVal::Released) {
+ V = V ^ RefVal::ErrorUseAfterRelease;
+ hasErr = V.getKind();
+ return state->set<RefBindings>(sym, V);
+ }
+
+ switch (E) {
+ default:
+ assert (false && "Unhandled CFRef transition.");
+
+ case Dealloc:
+ // Any use of -dealloc in GC is *bad*.
+ if (isGCEnabled()) {
+ V = V ^ RefVal::ErrorDeallocGC;
+ hasErr = V.getKind();
+ break;
+ }
+
+ switch (V.getKind()) {
+ default:
+ assert(false && "Invalid case.");
+ case RefVal::Owned:
+ // The object immediately transitions to the released state.
+ V = V ^ RefVal::Released;
+ V.clearCounts();
+ return state->set<RefBindings>(sym, V);
+ case RefVal::NotOwned:
+ V = V ^ RefVal::ErrorDeallocNotOwned;
+ hasErr = V.getKind();
+ break;
+ }
+ break;
+
+ case NewAutoreleasePool:
+ assert(!isGCEnabled());
+ return state->add<AutoreleaseStack>(sym);
+
+ case MayEscape:
+ if (V.getKind() == RefVal::Owned) {
+ V = V ^ RefVal::NotOwned;
+ break;
+ }
+
+ // Fall-through.
+
+ case DoNothingByRef:
+ case DoNothing:
+ return state;
+
+ case Autorelease:
+ if (isGCEnabled())
+ return state;
+
+ // Update the autorelease counts.
+ state = SendAutorelease(state, ARCountFactory, sym);
+ V = V.autorelease();
+ break;
+
+ case StopTracking:
+ return state->remove<RefBindings>(sym);
+
+ case IncRef:
+ switch (V.getKind()) {
+ default:
+ assert(false);
+
+ case RefVal::Owned:
+ case RefVal::NotOwned:
+ V = V + 1;
+ break;
+ case RefVal::Released:
+ // Non-GC cases are handled above.
+ assert(isGCEnabled());
+ V = (V ^ RefVal::Owned) + 1;
+ break;
+ }
+ break;
+
+ case SelfOwn:
+ V = V ^ RefVal::NotOwned;
+ // Fall-through.
+ case DecRef:
+ switch (V.getKind()) {
+ default:
+ // case 'RefVal::Released' handled above.
+ assert (false);
+
+ case RefVal::Owned:
+ assert(V.getCount() > 0);
+ if (V.getCount() == 1) V = V ^ RefVal::Released;
+ V = V - 1;
+ break;
+
+ case RefVal::NotOwned:
+ if (V.getCount() > 0)
+ V = V - 1;
+ else {
+ V = V ^ RefVal::ErrorReleaseNotOwned;
+ hasErr = V.getKind();
+ }
+ break;
+
+ case RefVal::Released:
+ // Non-GC cases are handled above.
+ assert(isGCEnabled());
+ V = V ^ RefVal::ErrorUseAfterRelease;
+ hasErr = V.getKind();
+ break;
+ }
+ break;
+ }
+ return state->set<RefBindings>(sym, V);
+}
+
+//===----------------------------------------------------------------------===//
+// Handle dead symbols and end-of-path.
+//===----------------------------------------------------------------------===//
+
+std::pair<ExplodedNode*, const GRState *>
+CFRefCount::HandleAutoreleaseCounts(const GRState * state,
+ GenericNodeBuilderRefCount Bd,
+ ExplodedNode* Pred,
+ ExprEngine &Eng,
+ SymbolRef Sym, RefVal V, bool &stop) {
+
+ unsigned ACnt = V.getAutoreleaseCount();
+ stop = false;
+
+ // No autorelease counts? Nothing to be done.
+ if (!ACnt)
+ return std::make_pair(Pred, state);
+
+ assert(!isGCEnabled() && "Autorelease counts in GC mode?");
+ unsigned Cnt = V.getCount();
+
+ // FIXME: Handle sending 'autorelease' to already released object.
+
+ if (V.getKind() == RefVal::ReturnedOwned)
+ ++Cnt;
+
+ if (ACnt <= Cnt) {
+ if (ACnt == Cnt) {
+ V.clearCounts();
+ if (V.getKind() == RefVal::ReturnedOwned)
+ V = V ^ RefVal::ReturnedNotOwned;
+ else
+ V = V ^ RefVal::NotOwned;
+ }
+ else {
+ V.setCount(Cnt - ACnt);
+ V.setAutoreleaseCount(0);
+ }
+ state = state->set<RefBindings>(Sym, V);
+ ExplodedNode *N = Bd.MakeNode(state, Pred);
+ stop = (N == 0);
+ return std::make_pair(N, state);
+ }
+
+ // Woah! More autorelease counts then retain counts left.
+ // Emit hard error.
+ stop = true;
+ V = V ^ RefVal::ErrorOverAutorelease;
+ state = state->set<RefBindings>(Sym, V);
+
+ if (ExplodedNode *N = Bd.MakeNode(state, Pred)) {
+ N->markAsSink();
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+ os << "Object over-autoreleased: object was sent -autorelease";
+ if (V.getAutoreleaseCount() > 1)
+ os << V.getAutoreleaseCount() << " times";
+ os << " but the object has ";
+ if (V.getCount() == 0)
+ os << "zero (locally visible)";
+ else
+ os << "+" << V.getCount();
+ os << " retain counts";
+
+ CFRefReport *report =
+ new CFRefReport(*static_cast<CFRefBug*>(overAutorelease),
+ *this, N, Sym, os.str());
+ BR->EmitReport(report);
+ }
+
+ return std::make_pair((ExplodedNode*)0, state);
+}
+
+const GRState *
+CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
+ llvm::SmallVectorImpl<SymbolRef> &Leaked) {
+
+ bool hasLeak = V.isOwned() ||
+ ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
+
+ if (!hasLeak)
+ return state->remove<RefBindings>(sid);
+
+ Leaked.push_back(sid);
+ return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
+}
+
+ExplodedNode*
+CFRefCount::ProcessLeaks(const GRState * state,
+ llvm::SmallVectorImpl<SymbolRef> &Leaked,
+ GenericNodeBuilderRefCount &Builder,
+ ExprEngine& Eng,
+ ExplodedNode *Pred) {
+
+ if (Leaked.empty())
+ return Pred;
+
+ // Generate an intermediate node representing the leak point.
+ ExplodedNode *N = Builder.MakeNode(state, Pred);
+
+ if (N) {
+ for (llvm::SmallVectorImpl<SymbolRef>::iterator
+ I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
+
+ CFRefBug *BT = static_cast<CFRefBug*>(Pred ? leakWithinFunction
+ : leakAtReturn);
+ assert(BT && "BugType not initialized.");
+ CFRefLeakReport* report = new CFRefLeakReport(*BT, *this, N, *I, Eng);
+ BR->EmitReport(report);
+ }
+ }
+
+ return N;
+}
+
+void CFRefCount::evalEndPath(ExprEngine& Eng,
+ EndOfFunctionNodeBuilder& Builder) {
+
+ const GRState *state = Builder.getState();
+ GenericNodeBuilderRefCount Bd(Builder);
+ RefBindings B = state->get<RefBindings>();
+ ExplodedNode *Pred = 0;
+
+ for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ bool stop = false;
+ llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
+ (*I).first,
+ (*I).second, stop);
+
+ if (stop)
+ return;
+ }
+
+ B = state->get<RefBindings>();
+ llvm::SmallVector<SymbolRef, 10> Leaked;
+
+ for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
+ state = HandleSymbolDeath(state, (*I).first, (*I).second, Leaked);
+
+ ProcessLeaks(state, Leaked, Bd, Eng, Pred);
+}
+
+void CFRefCount::evalDeadSymbols(ExplodedNodeSet& Dst,
+ ExprEngine& Eng,
+ StmtNodeBuilder& Builder,
+ ExplodedNode* Pred,
+ const GRState* state,
+ SymbolReaper& SymReaper) {
+ const Stmt *S = Builder.getStmt();
+ RefBindings B = state->get<RefBindings>();
+
+ // Update counts from autorelease pools
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I != E; ++I) {
+ SymbolRef Sym = *I;
+ if (const RefVal* T = B.lookup(Sym)){
+ // Use the symbol as the tag.
+ // FIXME: This might not be as unique as we would like.
+ GenericNodeBuilderRefCount Bd(Builder, S, Sym);
+ bool stop = false;
+ llvm::tie(Pred, state) = HandleAutoreleaseCounts(state, Bd, Pred, Eng,
+ Sym, *T, stop);
+ if (stop)
+ return;
+ }
+ }
+
+ B = state->get<RefBindings>();
+ llvm::SmallVector<SymbolRef, 10> Leaked;
+
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I != E; ++I) {
+ if (const RefVal* T = B.lookup(*I))
+ state = HandleSymbolDeath(state, *I, *T, Leaked);
+ }
+
+ static unsigned LeakPPTag = 0;
+ {
+ GenericNodeBuilderRefCount Bd(Builder, S, &LeakPPTag);
+ Pred = ProcessLeaks(state, Leaked, Bd, Eng, Pred);
+ }
+
+ // Did we cache out?
+ if (!Pred)
+ return;
+
+ // Now generate a new node that nukes the old bindings.
+ RefBindings::Factory& F = state->get_context<RefBindings>();
+
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I!=E; ++I) B = F.remove(B, *I);
+
+ state = state->set<RefBindings>(B);
+ Builder.MakeNode(Dst, S, Pred, state);
+}
+
+void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
+ StmtNodeBuilder& Builder,
+ const Expr* NodeExpr,
+ SourceRange ErrorRange,
+ ExplodedNode* Pred,
+ const GRState* St,
+ RefVal::Kind hasErr, SymbolRef Sym) {
+ Builder.BuildSinks = true;
+ ExplodedNode *N = Builder.MakeNode(Dst, NodeExpr, Pred, St);
+
+ if (!N)
+ return;
+
+ CFRefBug *BT = 0;
+
+ switch (hasErr) {
+ default:
+ assert(false && "Unhandled error.");
+ return;
+ case RefVal::ErrorUseAfterRelease:
+ BT = static_cast<CFRefBug*>(useAfterRelease);
+ break;
+ case RefVal::ErrorReleaseNotOwned:
+ BT = static_cast<CFRefBug*>(releaseNotOwned);
+ break;
+ case RefVal::ErrorDeallocGC:
+ BT = static_cast<CFRefBug*>(deallocGC);
+ break;
+ case RefVal::ErrorDeallocNotOwned:
+ BT = static_cast<CFRefBug*>(deallocNotOwned);
+ break;
+ }
+
+ CFRefReport *report = new CFRefReport(*BT, *this, N, Sym);
+ report->addRange(ErrorRange);
+ BR->EmitReport(report);
+}
+
+//===----------------------------------------------------------------------===//
+// Pieces of the retain/release checker implemented using a CheckerVisitor.
+// More pieces of the retain/release checker will be migrated to this interface
+// (ideally, all of it some day).
+//===----------------------------------------------------------------------===//
+
+namespace {
+class RetainReleaseChecker
+ : public CheckerVisitor<RetainReleaseChecker> {
+ CFRefCount *TF;
+public:
+ RetainReleaseChecker(CFRefCount *tf) : TF(tf) {}
+ static void* getTag() { static int x = 0; return &x; }
+
+ void PostVisitBlockExpr(CheckerContext &C, const BlockExpr *BE);
+};
+} // end anonymous namespace
+
+
+void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C,
+ const BlockExpr *BE) {
+
+ // Scan the BlockDecRefExprs for any object the retain/release checker
+ // may be tracking.
+ if (!BE->getBlockDecl()->hasCaptures())
+ return;
+
+ const GRState *state = C.getState();
+ const BlockDataRegion *R =
+ cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+
+ BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
+ E = R->referenced_vars_end();
+
+ if (I == E)
+ return;
+
+ // FIXME: For now we invalidate the tracking of all symbols passed to blocks
+ // via captured variables, even though captured variables result in a copy
+ // and in implicit increment/decrement of a retain count.
+ llvm::SmallVector<const MemRegion*, 10> Regions;
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
+ MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
+
+ for ( ; I != E; ++I) {
+ const VarRegion *VR = *I;
+ if (VR->getSuperRegion() == R) {
+ VR = MemMgr.getVarRegion(VR->getDecl(), LC);
+ }
+ Regions.push_back(VR);
+ }
+
+ state =
+ state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
+ Regions.data() + Regions.size()).getState();
+ C.addTransition(state);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function creation for external clients.
+//===----------------------------------------------------------------------===//
+
+void CFRefCount::RegisterChecks(ExprEngine& Eng) {
+ BugReporter &BR = Eng.getBugReporter();
+
+ useAfterRelease = new UseAfterRelease(this);
+ BR.Register(useAfterRelease);
+
+ releaseNotOwned = new BadRelease(this);
+ BR.Register(releaseNotOwned);
+
+ deallocGC = new DeallocGC(this);
+ BR.Register(deallocGC);
+
+ deallocNotOwned = new DeallocNotOwned(this);
+ BR.Register(deallocNotOwned);
+
+ overAutorelease = new OverAutorelease(this);
+ BR.Register(overAutorelease);
+
+ returnNotOwnedForOwned = new ReturnedNotOwnedForOwned(this);
+ BR.Register(returnNotOwnedForOwned);
+
+ // First register "return" leaks.
+ const char* name = 0;
+
+ if (isGCEnabled())
+ name = "Leak of returned object when using garbage collection";
+ else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
+ name = "Leak of returned object when not using garbage collection (GC) in "
+ "dual GC/non-GC code";
+ else {
+ assert(getLangOptions().getGCMode() == LangOptions::NonGC);
+ name = "Leak of returned object";
+ }
+
+ // Leaks should not be reported if they are post-dominated by a sink.
+ leakAtReturn = new LeakAtReturn(this, name);
+ leakAtReturn->setSuppressOnSink(true);
+ BR.Register(leakAtReturn);
+
+ // Second, register leaks within a function/method.
+ if (isGCEnabled())
+ name = "Leak of object when using garbage collection";
+ else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
+ name = "Leak of object when not using garbage collection (GC) in "
+ "dual GC/non-GC code";
+ else {
+ assert(getLangOptions().getGCMode() == LangOptions::NonGC);
+ name = "Leak";
+ }
+
+ // Leaks should not be reported if they are post-dominated by sinks.
+ leakWithinFunction = new LeakWithinFunction(this, name);
+ leakWithinFunction->setSuppressOnSink(true);
+ BR.Register(leakWithinFunction);
+
+ // Save the reference to the BugReporter.
+ this->BR = &BR;
+
+ // Register the RetainReleaseChecker with the ExprEngine object.
+ // Functionality in CFRefCount will be migrated to RetainReleaseChecker
+ // over time.
+ Eng.registerCheck(new RetainReleaseChecker(this));
+}
+
+TransferFuncs* ento::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts) {
+ return new CFRefCount(Ctx, GCEnabled, lopts);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
new file mode 100644
index 0000000..14c636c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -0,0 +1,41 @@
+set(LLVM_LINK_COMPONENTS support)
+
+set(LLVM_USED_LIBS clangBasic clangLex clangAST clangFrontend clangRewrite)
+
+add_clang_library(clangStaticAnalyzerCore
+ AggExprVisitor.cpp
+ AnalysisManager.cpp
+ BasicConstraintManager.cpp
+ BasicStore.cpp
+ BasicValueFactory.cpp
+ BugReporter.cpp
+ BugReporterVisitors.cpp
+ CFRefCount.cpp
+ Checker.cpp
+ CheckerHelpers.cpp
+ CheckerManager.cpp
+ Environment.cpp
+ ExplodedGraph.cpp
+ FlatStore.cpp
+ BlockCounter.cpp
+ CXXExprEngine.cpp
+ CoreEngine.cpp
+ GRState.cpp
+ HTMLDiagnostics.cpp
+ MemRegion.cpp
+ ObjCMessage.cpp
+ PathDiagnostic.cpp
+ PlistDiagnostics.cpp
+ RangeConstraintManager.cpp
+ RegionStore.cpp
+ SimpleConstraintManager.cpp
+ SimpleSValBuilder.cpp
+ Store.cpp
+ SValBuilder.cpp
+ SVals.cpp
+ SymbolManager.cpp
+ TextPathDiagnostics.cpp
+ )
+
+add_dependencies(clangStaticAnalyzerCore ClangAttrClasses ClangAttrList ClangDeclNodes
+ ClangStmtNodes)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
new file mode 100644
index 0000000..56dfe8c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
@@ -0,0 +1,322 @@
+//===- GRCXXExprEngine.cpp - C++ expr evaluation engine ---------*- 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 C++ expression evaluation engine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CallExprWLItem {
+public:
+ CallExpr::const_arg_iterator I;
+ ExplodedNode *N;
+
+ CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
+ : I(i), N(n) {}
+};
+}
+
+void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
+ const FunctionProtoType *FnType,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ bool FstArgAsLValue) {
+
+
+ llvm::SmallVector<CallExprWLItem, 20> WorkList;
+ WorkList.reserve(AE - AI);
+ WorkList.push_back(CallExprWLItem(AI, Pred));
+
+ while (!WorkList.empty()) {
+ CallExprWLItem Item = WorkList.back();
+ WorkList.pop_back();
+
+ if (Item.I == AE) {
+ Dst.insert(Item.N);
+ continue;
+ }
+
+ // Evaluate the argument.
+ ExplodedNodeSet Tmp;
+ if (FstArgAsLValue) {
+ FstArgAsLValue = false;
+ }
+
+ Visit(*Item.I, Item.N, Tmp);
+ ++(Item.I);
+ for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
+ WorkList.push_back(CallExprWLItem(Item.I, *NI));
+ }
+}
+
+const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
+ const StackFrameContext *SFC) {
+ const Type *T = D->getTypeForDecl();
+ QualType PT = getContext().getPointerType(QualType(T, 0));
+ return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
+}
+
+const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
+ const StackFrameContext *frameCtx) {
+ return svalBuilder.getRegionManager().
+ getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
+}
+
+void ExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
+ const GRState *state = GetState(*I);
+
+ // Bind the temporary object to the value of the expression. Then bind
+ // the expression to the location of the object.
+ SVal V = state->getSVal(Ex);
+
+ const MemRegion *R =
+ svalBuilder.getRegionManager().getCXXTempObjectRegion(Ex,
+ Pred->getLocationContext());
+
+ state = state->bindLoc(loc::MemRegionVal(R), V);
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
+ }
+}
+
+void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
+ const MemRegion *Dest,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ if (!Dest)
+ Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
+ Pred->getLocationContext());
+
+ if (E->isElidable()) {
+ VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
+ return;
+ }
+
+ const CXXConstructorDecl *CD = E->getConstructor();
+ assert(CD);
+
+ if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
+ // FIXME: invalidate the object.
+ return;
+
+
+ // Evaluate other arguments.
+ ExplodedNodeSet argsEvaluated;
+ const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
+ evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
+ // The callee stack frame context used to create the 'this' parameter region.
+ const StackFrameContext *SFC = AMgr.getStackFrame(CD,
+ Pred->getLocationContext(),
+ E, Builder->getBlock(),
+ Builder->getIndex());
+
+ const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
+ SFC);
+
+ CallEnter Loc(E, SFC, Pred->getLocationContext());
+ for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
+ NE = argsEvaluated.end(); NI != NE; ++NI) {
+ const GRState *state = GetState(*NI);
+ // Setup 'this' region, so that the ctor is evaluated on the object pointed
+ // by 'Dest'.
+ state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ if (N)
+ Dst.Add(N);
+ }
+}
+
+void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
+ const MemRegion *Dest,
+ const Stmt *S,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ if (!(DD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
+ return;
+ // Create the context for 'this' region.
+ const StackFrameContext *SFC = AMgr.getStackFrame(DD,
+ Pred->getLocationContext(),
+ S, Builder->getBlock(),
+ Builder->getIndex());
+
+ const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
+
+ CallEnter PP(S, SFC, Pred->getLocationContext());
+
+ const GRState *state = Pred->getState();
+ state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
+ ExplodedNode *N = Builder->generateNode(PP, state, Pred);
+ if (N)
+ Dst.Add(N);
+}
+
+void ExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ // Get the method type.
+ const FunctionProtoType *FnType =
+ MCE->getCallee()->getType()->getAs<FunctionProtoType>();
+ assert(FnType && "Method type not available");
+
+ // Evaluate explicit arguments with a worklist.
+ ExplodedNodeSet argsEvaluated;
+ evalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, argsEvaluated);
+
+ // Evaluate the implicit object argument.
+ ExplodedNodeSet AllargsEvaluated;
+ const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
+ if (!ME)
+ return;
+ Expr *ObjArgExpr = ME->getBase();
+ for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
+ E = argsEvaluated.end(); I != E; ++I) {
+ Visit(ObjArgExpr, *I, AllargsEvaluated);
+ }
+
+ // Now evaluate the call itself.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
+ assert(MD && "not a CXXMethodDecl?");
+ evalMethodCall(MCE, MD, ObjArgExpr, Pred, AllargsEvaluated, Dst);
+}
+
+void ExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
+ if (!MD) {
+ // If the operator doesn't represent a method call treat as regural call.
+ VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+ return;
+ }
+
+ // Determine the type of function we're calling (if available).
+ const FunctionProtoType *Proto = NULL;
+ QualType FnType = C->getCallee()->IgnoreParens()->getType();
+ if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
+ Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
+
+ // Evaluate arguments treating the first one (object method is called on)
+ // as alvalue.
+ ExplodedNodeSet argsEvaluated;
+ evalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, argsEvaluated, true);
+
+ // Now evaluate the call itself.
+ evalMethodCall(C, MD, C->getArg(0), Pred, argsEvaluated, Dst);
+}
+
+void ExprEngine::evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
+ const Expr *ThisExpr, ExplodedNode *Pred,
+ ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
+ // Allow checkers to pre-visit the member call.
+ ExplodedNodeSet PreVisitChecks;
+ CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
+
+ if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
+ // FIXME: conservative method call evaluation.
+ CheckerVisit(MCE, Dst, PreVisitChecks, PostVisitStmtCallback);
+ return;
+ }
+
+ const StackFrameContext *SFC = AMgr.getStackFrame(MD,
+ Pred->getLocationContext(),
+ MCE,
+ Builder->getBlock(),
+ Builder->getIndex());
+ const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
+ CallEnter Loc(MCE, SFC, Pred->getLocationContext());
+ for (ExplodedNodeSet::iterator I = PreVisitChecks.begin(),
+ E = PreVisitChecks.end(); I != E; ++I) {
+ // Set up 'this' region.
+ const GRState *state = GetState(*I);
+ state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
+ Dst.Add(Builder->generateNode(Loc, state, *I));
+ }
+}
+
+void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ if (CNE->isArray()) {
+ // FIXME: allocating an array has not been handled.
+ return;
+ }
+
+ unsigned Count = Builder->getCurrentBlockCount();
+ DefinedOrUnknownSVal symVal =
+ svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count);
+ const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
+
+ QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
+
+ const ElementRegion *EleReg =
+ getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
+
+ // Evaluate constructor arguments.
+ const FunctionProtoType *FnType = NULL;
+ const CXXConstructorDecl *CD = CNE->getConstructor();
+ if (CD)
+ FnType = CD->getType()->getAs<FunctionProtoType>();
+ ExplodedNodeSet argsEvaluated;
+ evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
+ FnType, Pred, argsEvaluated);
+
+ // Initialize the object region and bind the 'new' expression.
+ for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
+ E = argsEvaluated.end(); I != E; ++I) {
+ const GRState *state = GetState(*I);
+
+ if (ObjTy->isRecordType()) {
+ state = state->invalidateRegion(EleReg, CNE, Count);
+ } else {
+ if (CNE->hasInitializer()) {
+ SVal V = state->getSVal(*CNE->constructor_arg_begin());
+ state = state->bindLoc(loc::MemRegionVal(EleReg), V);
+ } else {
+ // Explicitly set to undefined, because currently we retrieve symbolic
+ // value from symbolic region.
+ state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
+ }
+ }
+ state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
+ MakeNode(Dst, CNE, *I, state);
+ }
+}
+
+void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
+ ExplodedNode *Pred,ExplodedNodeSet &Dst) {
+ // Should do more checking.
+ ExplodedNodeSet Argevaluated;
+ Visit(CDE->getArgument(), Pred, Argevaluated);
+ for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
+ E = Argevaluated.end(); I != E; ++I) {
+ const GRState *state = GetState(*I);
+ MakeNode(Dst, CDE, *I, state);
+ }
+}
+
+void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ // Get the this object region from StoreManager.
+ const MemRegion *R =
+ svalBuilder.getRegionManager().getCXXThisRegion(
+ getContext().getCanonicalType(TE->getType()),
+ Pred->getLocationContext());
+
+ const GRState *state = GetState(Pred);
+ SVal V = state->getSVal(loc::MemRegionVal(R));
+ MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
new file mode 100644
index 0000000..a014eec
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
@@ -0,0 +1,35 @@
+//== Checker.h - Abstract interface for checkers -----------------*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines Checker and CheckerVisitor, classes used for creating
+// domain-specific checks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+using namespace clang;
+using namespace ento;
+
+Checker::~Checker() {}
+
+CheckerContext::~CheckerContext() {
+ // Do we need to autotransition? 'Dst' can get populated in a variety of
+ // ways, including 'addTransition()' adding the predecessor node to Dst
+ // without actually generated a new node. We also shouldn't autotransition
+ // if we are building sinks or we generated a node and decided to not
+ // add it as a transition.
+ if (Dst.size() == size && !B.BuildSinks && !B.hasGeneratedNode) {
+ if (ST && ST != B.GetState(Pred)) {
+ static int autoTransitionTag = 0;
+ addTransition(ST, &autoTransitionTag);
+ }
+ else
+ Dst.Add(Pred);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
new file mode 100644
index 0000000..28df695
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -0,0 +1,80 @@
+//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several static functions for use in checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/AST/Expr.h"
+
+// Recursively find any substatements containing macros
+bool clang::ento::containsMacro(const Stmt *S) {
+ if (S->getLocStart().isMacroID())
+ return true;
+
+ if (S->getLocEnd().isMacroID())
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsMacro(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing enum constants
+bool clang::ento::containsEnum(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+ if (DR && isa<EnumConstantDecl>(DR->getDecl()))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsEnum(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing static vars
+bool clang::ento::containsStaticLocal(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+ if (DR)
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VD->isStaticLocal())
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsStaticLocal(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing __builtin_offsetof
+bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
+ if (isa<OffsetOfExpr>(S))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsBuiltinOffsetOf(child))
+ return true;
+
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
new file mode 100644
index 0000000..1989b82
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -0,0 +1,85 @@
+//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Manager.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "clang/AST/DeclBase.h"
+
+using namespace clang;
+using namespace ento;
+
+void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ assert(D);
+
+ unsigned DeclKind = D->getKind();
+ CachedDeclCheckers *checkers = 0;
+ CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
+ if (CCI != CachedDeclCheckersMap.end()) {
+ checkers = &(CCI->second);
+ } else {
+ // Find the checkers that should run for this Decl and cache them.
+ checkers = &CachedDeclCheckersMap[DeclKind];
+ for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
+ DeclCheckerInfo &info = DeclCheckers[i];
+ if (info.IsForDeclFn(D))
+ checkers->push_back(std::make_pair(info.Checker, info.CheckFn));
+ }
+ }
+
+ assert(checkers);
+ for (CachedDeclCheckers::iterator
+ I = checkers->begin(), E = checkers->end(); I != E; ++I) {
+ CheckerRef checker = I->first;
+ CheckDeclFunc fn = I->second;
+ fn(checker, D, mgr, BR);
+ }
+}
+
+void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ assert(D && D->hasBody());
+
+ for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) {
+ CheckerRef checker = BodyCheckers[i].first;
+ CheckDeclFunc fn = BodyCheckers[i].second;
+ fn(checker, D, mgr, BR);
+ }
+}
+
+void CheckerManager::_registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
+ HandlesDeclFunc isForDeclFn) {
+ DeclCheckerInfo info = { checker, checkfn, isForDeclFn };
+ DeclCheckers.push_back(info);
+}
+
+void CheckerManager::_registerForBody(CheckerRef checker,
+ CheckDeclFunc checkfn) {
+ BodyCheckers.push_back(std::make_pair(checker, checkfn));
+}
+
+void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
+ for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
+ Funcs[i](eng);
+}
+
+CheckerManager::~CheckerManager() {
+ for (unsigned i = 0, e = Checkers.size(); i != e; ++i) {
+ CheckerRef checker = Checkers[i].first;
+ Dtor dtor = Checkers[i].second;
+ dtor(checker);
+ }
+}
+
+// Anchor for the vtable.
+CheckerProvider::~CheckerProvider() { }
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
new file mode 100644
index 0000000..070042a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -0,0 +1,848 @@
+//==- CoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic engine for intraprocedural, path-sensitive,
+// dataflow analysis via graph reachability engine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Index/TranslationUnit.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+#include <queue>
+
+using llvm::cast;
+using llvm::isa;
+using namespace clang;
+using namespace ento;
+
+// This should be removed in the future.
+namespace clang {
+namespace ento {
+TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts);
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Worklist classes for exploration of reachable states.
+//===----------------------------------------------------------------------===//
+
+WorkList::Visitor::~Visitor() {}
+
+namespace {
+class DFS : public WorkList {
+ llvm::SmallVector<WorkListUnit,20> Stack;
+public:
+ virtual bool hasWork() const {
+ return !Stack.empty();
+ }
+
+ virtual void enqueue(const WorkListUnit& U) {
+ Stack.push_back(U);
+ }
+
+ virtual WorkListUnit dequeue() {
+ assert (!Stack.empty());
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+
+ virtual bool visitItemsInWorkList(Visitor &V) {
+ for (llvm::SmallVectorImpl<WorkListUnit>::iterator
+ I = Stack.begin(), E = Stack.end(); I != E; ++I) {
+ if (V.visit(*I))
+ return true;
+ }
+ return false;
+ }
+};
+
+class BFS : public WorkList {
+ std::deque<WorkListUnit> Queue;
+public:
+ virtual bool hasWork() const {
+ return !Queue.empty();
+ }
+
+ virtual void enqueue(const WorkListUnit& U) {
+ Queue.push_front(U);
+ }
+
+ virtual WorkListUnit dequeue() {
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+
+ virtual bool visitItemsInWorkList(Visitor &V) {
+ for (std::deque<WorkListUnit>::iterator
+ I = Queue.begin(), E = Queue.end(); I != E; ++I) {
+ if (V.visit(*I))
+ return true;
+ }
+ return false;
+ }
+};
+
+} // end anonymous namespace
+
+// Place the dstor for WorkList here because it contains virtual member
+// functions, and we the code for the dstor generated in one compilation unit.
+WorkList::~WorkList() {}
+
+WorkList *WorkList::makeDFS() { return new DFS(); }
+WorkList *WorkList::makeBFS() { return new BFS(); }
+
+namespace {
+ class BFSBlockDFSContents : public WorkList {
+ std::deque<WorkListUnit> Queue;
+ llvm::SmallVector<WorkListUnit,20> Stack;
+ public:
+ virtual bool hasWork() const {
+ return !Queue.empty() || !Stack.empty();
+ }
+
+ virtual void enqueue(const WorkListUnit& U) {
+ if (isa<BlockEntrance>(U.getNode()->getLocation()))
+ Queue.push_front(U);
+ else
+ Stack.push_back(U);
+ }
+
+ virtual WorkListUnit dequeue() {
+ // Process all basic blocks to completion.
+ if (!Stack.empty()) {
+ const WorkListUnit& U = Stack.back();
+ Stack.pop_back(); // This technically "invalidates" U, but we are fine.
+ return U;
+ }
+
+ assert(!Queue.empty());
+ // Don't use const reference. The subsequent pop_back() might make it
+ // unsafe.
+ WorkListUnit U = Queue.front();
+ Queue.pop_front();
+ return U;
+ }
+ virtual bool visitItemsInWorkList(Visitor &V) {
+ for (llvm::SmallVectorImpl<WorkListUnit>::iterator
+ I = Stack.begin(), E = Stack.end(); I != E; ++I) {
+ if (V.visit(*I))
+ return true;
+ }
+ for (std::deque<WorkListUnit>::iterator
+ I = Queue.begin(), E = Queue.end(); I != E; ++I) {
+ if (V.visit(*I))
+ return true;
+ }
+ return false;
+ }
+
+ };
+} // end anonymous namespace
+
+WorkList* WorkList::makeBFSBlockDFSContents() {
+ return new BFSBlockDFSContents();
+}
+
+//===----------------------------------------------------------------------===//
+// Core analysis engine.
+//===----------------------------------------------------------------------===//
+
+/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
+bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
+ const GRState *InitState) {
+
+ if (G->num_roots() == 0) { // Initialize the analysis by constructing
+ // the root if none exists.
+
+ const CFGBlock* Entry = &(L->getCFG()->getEntry());
+
+ assert (Entry->empty() &&
+ "Entry block must be empty.");
+
+ assert (Entry->succ_size() == 1 &&
+ "Entry block must have 1 successor.");
+
+ // Get the solitary successor.
+ const CFGBlock* Succ = *(Entry->succ_begin());
+
+ // Construct an edge representing the
+ // starting location in the function.
+ BlockEdge StartLoc(Entry, Succ, L);
+
+ // Set the current block counter to being empty.
+ WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
+
+ if (!InitState)
+ // Generate the root.
+ generateNode(StartLoc, SubEng.getInitialState(L), 0);
+ else
+ generateNode(StartLoc, InitState, 0);
+ }
+
+ // Check if we have a steps limit
+ bool UnlimitedSteps = Steps == 0;
+
+ while (WList->hasWork()) {
+ if (!UnlimitedSteps) {
+ if (Steps == 0)
+ break;
+ --Steps;
+ }
+
+ const WorkListUnit& WU = WList->dequeue();
+
+ // Set the current block counter.
+ WList->setBlockCounter(WU.getBlockCounter());
+
+ // Retrieve the node.
+ ExplodedNode* Node = WU.getNode();
+
+ // Dispatch on the location type.
+ switch (Node->getLocation().getKind()) {
+ case ProgramPoint::BlockEdgeKind:
+ HandleBlockEdge(cast<BlockEdge>(Node->getLocation()), Node);
+ break;
+
+ case ProgramPoint::BlockEntranceKind:
+ HandleBlockEntrance(cast<BlockEntrance>(Node->getLocation()), Node);
+ break;
+
+ case ProgramPoint::BlockExitKind:
+ assert (false && "BlockExit location never occur in forward analysis.");
+ break;
+
+ case ProgramPoint::CallEnterKind:
+ HandleCallEnter(cast<CallEnter>(Node->getLocation()), WU.getBlock(),
+ WU.getIndex(), Node);
+ break;
+
+ case ProgramPoint::CallExitKind:
+ HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
+ break;
+
+ default:
+ assert(isa<PostStmt>(Node->getLocation()) ||
+ isa<PostInitializer>(Node->getLocation()));
+ HandlePostStmt(WU.getBlock(), WU.getIndex(), Node);
+ break;
+ }
+ }
+
+ SubEng.processEndWorklist(hasWorkRemaining());
+ return WList->hasWork();
+}
+
+void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
+ unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst) {
+ ExecuteWorkList(L, Steps, InitState);
+ for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
+ E = G->EndNodes.end(); I != E; ++I) {
+ Dst.Add(*I);
+ }
+}
+
+void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
+ unsigned Index, ExplodedNode *Pred) {
+ CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
+ L.getCalleeContext(), Block, Index);
+ SubEng.processCallEnter(Builder);
+}
+
+void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
+ CallExitNodeBuilder Builder(*this, Pred);
+ SubEng.processCallExit(Builder);
+}
+
+void CoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
+
+ const CFGBlock* Blk = L.getDst();
+
+ // Check if we are entering the EXIT block.
+ if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
+
+ assert (L.getLocationContext()->getCFG()->getExit().size() == 0
+ && "EXIT block cannot contain Stmts.");
+
+ // Process the final state transition.
+ EndOfFunctionNodeBuilder Builder(Blk, Pred, this);
+ SubEng.processEndOfFunction(Builder);
+
+ // This path is done. Don't enqueue any more nodes.
+ return;
+ }
+
+ // Call into the subengine to process entering the CFGBlock.
+ ExplodedNodeSet dstNodes;
+ BlockEntrance BE(Blk, Pred->getLocationContext());
+ GenericNodeBuilder<BlockEntrance> nodeBuilder(*this, Pred, BE);
+ SubEng.processCFGBlockEntrance(dstNodes, nodeBuilder);
+
+ if (dstNodes.empty()) {
+ if (!nodeBuilder.hasGeneratedNode) {
+ // Auto-generate a node and enqueue it to the worklist.
+ generateNode(BE, Pred->State, Pred);
+ }
+ }
+ else {
+ for (ExplodedNodeSet::iterator I = dstNodes.begin(), E = dstNodes.end();
+ I != E; ++I) {
+ WList->enqueue(*I);
+ }
+ }
+
+ for (llvm::SmallVectorImpl<ExplodedNode*>::const_iterator
+ I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end();
+ I != E; ++I) {
+ blocksAborted.push_back(std::make_pair(L, *I));
+ }
+}
+
+void CoreEngine::HandleBlockEntrance(const BlockEntrance& L,
+ ExplodedNode* Pred) {
+
+ // Increment the block counter.
+ BlockCounter Counter = WList->getBlockCounter();
+ Counter = BCounterFactory.IncrementCount(Counter,
+ Pred->getLocationContext()->getCurrentStackFrame(),
+ L.getBlock()->getBlockID());
+ WList->setBlockCounter(Counter);
+
+ // Process the entrance of the block.
+ if (CFGElement E = L.getFirstElement()) {
+ StmtNodeBuilder Builder(L.getBlock(), 0, Pred, this,
+ SubEng.getStateManager());
+ SubEng.processCFGElement(E, Builder);
+ }
+ else
+ HandleBlockExit(L.getBlock(), Pred);
+}
+
+void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
+
+ if (const Stmt* Term = B->getTerminator()) {
+ switch (Term->getStmtClass()) {
+ default:
+ assert(false && "Analysis for this terminator not implemented.");
+ break;
+
+ case Stmt::BinaryOperatorClass: // '&&' and '||'
+ HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
+ return;
+
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
+ Term, B, Pred);
+ return;
+
+ // FIXME: Use constant-folding in CFG construction to simplify this
+ // case.
+
+ case Stmt::ChooseExprClass:
+ HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
+ return;
+
+ case Stmt::DoStmtClass:
+ HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
+ return;
+
+ case Stmt::ForStmtClass:
+ HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
+ return;
+
+ case Stmt::ContinueStmtClass:
+ case Stmt::BreakStmtClass:
+ case Stmt::GotoStmtClass:
+ break;
+
+ case Stmt::IfStmtClass:
+ HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
+ return;
+
+ case Stmt::IndirectGotoStmtClass: {
+ // Only 1 successor: the indirect goto dispatch block.
+ assert (B->succ_size() == 1);
+
+ IndirectGotoNodeBuilder
+ builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
+ *(B->succ_begin()), this);
+
+ SubEng.processIndirectGoto(builder);
+ return;
+ }
+
+ case Stmt::ObjCForCollectionStmtClass: {
+ // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
+ //
+ // (1) inside a basic block, which represents the binding of the
+ // 'element' variable to a value.
+ // (2) in a terminator, which represents the branch.
+ //
+ // For (1), subengines will bind a value (i.e., 0 or 1) indicating
+ // whether or not collection contains any more elements. We cannot
+ // just test to see if the element is nil because a container can
+ // contain nil elements.
+ HandleBranch(Term, Term, B, Pred);
+ return;
+ }
+
+ case Stmt::SwitchStmtClass: {
+ SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
+ this);
+
+ SubEng.processSwitch(builder);
+ return;
+ }
+
+ case Stmt::WhileStmtClass:
+ HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
+ return;
+ }
+ }
+
+ assert (B->succ_size() == 1 &&
+ "Blocks with no terminator should have at most 1 successor.");
+
+ generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
+ Pred->State, Pred);
+}
+
+void CoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
+ const CFGBlock * B, ExplodedNode* Pred) {
+ assert(B->succ_size() == 2);
+ BranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
+ Pred, this);
+ SubEng.processBranch(Cond, Term, Builder);
+}
+
+void CoreEngine::HandlePostStmt(const CFGBlock* B, unsigned StmtIdx,
+ ExplodedNode* Pred) {
+ assert (!B->empty());
+
+ if (StmtIdx == B->size())
+ HandleBlockExit(B, Pred);
+ else {
+ StmtNodeBuilder Builder(B, StmtIdx, Pred, this,
+ SubEng.getStateManager());
+ SubEng.processCFGElement((*B)[StmtIdx], Builder);
+ }
+}
+
+/// generateNode - Utility method to generate nodes, hook up successors,
+/// and add nodes to the worklist.
+void CoreEngine::generateNode(const ProgramPoint& Loc,
+ const GRState* State, ExplodedNode* Pred) {
+
+ bool IsNew;
+ ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
+
+ if (Pred)
+ Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor.
+ else {
+ assert (IsNew);
+ G->addRoot(Node); // 'Node' has no predecessor. Make it a root.
+ }
+
+ // Only add 'Node' to the worklist if it was freshly generated.
+ if (IsNew) WList->enqueue(Node);
+}
+
+ExplodedNode *
+GenericNodeBuilderImpl::generateNodeImpl(const GRState *state,
+ ExplodedNode *pred,
+ ProgramPoint programPoint,
+ bool asSink) {
+
+ hasGeneratedNode = true;
+ bool isNew;
+ ExplodedNode *node = engine.getGraph().getNode(programPoint, state, &isNew);
+ if (pred)
+ node->addPredecessor(pred, engine.getGraph());
+ if (isNew) {
+ if (asSink) {
+ node->markAsSink();
+ sinksGenerated.push_back(node);
+ }
+ return node;
+ }
+ return 0;
+}
+
+StmtNodeBuilder::StmtNodeBuilder(const CFGBlock* b, unsigned idx,
+ ExplodedNode* N, CoreEngine* e,
+ GRStateManager &mgr)
+ : Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr),
+ PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
+ PointKind(ProgramPoint::PostStmtKind), Tag(0) {
+ Deferred.insert(N);
+ CleanedState = Pred->getState();
+}
+
+StmtNodeBuilder::~StmtNodeBuilder() {
+ for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
+ if (!(*I)->isSink())
+ GenerateAutoTransition(*I);
+}
+
+void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
+ assert (!N->isSink());
+
+ // Check if this node entered a callee.
+ if (isa<CallEnter>(N->getLocation())) {
+ // Still use the index of the CallExpr. It's needed to create the callee
+ // StackFrameContext.
+ Eng.WList->enqueue(N, &B, Idx);
+ return;
+ }
+
+ // Do not create extra nodes. Move to the next CFG element.
+ if (isa<PostInitializer>(N->getLocation())) {
+ Eng.WList->enqueue(N, &B, Idx+1);
+ return;
+ }
+
+ PostStmt Loc(getStmt(), N->getLocationContext());
+
+ if (Loc == N->getLocation()) {
+ // Note: 'N' should be a fresh node because otherwise it shouldn't be
+ // a member of Deferred.
+ Eng.WList->enqueue(N, &B, Idx+1);
+ return;
+ }
+
+ bool IsNew;
+ ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
+ Succ->addPredecessor(N, *Eng.G);
+
+ if (IsNew)
+ Eng.WList->enqueue(Succ, &B, Idx+1);
+}
+
+ExplodedNode* StmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St,
+ ProgramPoint::Kind K) {
+
+ ExplodedNode* N = generateNode(S, St, Pred, K);
+
+ if (N) {
+ if (BuildSinks)
+ N->markAsSink();
+ else
+ Dst.Add(N);
+ }
+
+ return N;
+}
+
+static ProgramPoint GetProgramPoint(const Stmt *S, ProgramPoint::Kind K,
+ const LocationContext *LC, const void *tag){
+ switch (K) {
+ default:
+ assert(false && "Unhandled ProgramPoint kind");
+ case ProgramPoint::PreStmtKind:
+ return PreStmt(S, LC, tag);
+ case ProgramPoint::PostStmtKind:
+ return PostStmt(S, LC, tag);
+ case ProgramPoint::PreLoadKind:
+ return PreLoad(S, LC, tag);
+ case ProgramPoint::PostLoadKind:
+ return PostLoad(S, LC, tag);
+ case ProgramPoint::PreStoreKind:
+ return PreStore(S, LC, tag);
+ case ProgramPoint::PostStoreKind:
+ return PostStore(S, LC, tag);
+ case ProgramPoint::PostLValueKind:
+ return PostLValue(S, LC, tag);
+ case ProgramPoint::PostPurgeDeadSymbolsKind:
+ return PostPurgeDeadSymbols(S, LC, tag);
+ }
+}
+
+ExplodedNode*
+StmtNodeBuilder::generateNodeInternal(const Stmt* S, const GRState* state,
+ ExplodedNode* Pred,
+ ProgramPoint::Kind K,
+ const void *tag) {
+
+ const ProgramPoint &L = GetProgramPoint(S, K, Pred->getLocationContext(),tag);
+ return generateNodeInternal(L, state, Pred);
+}
+
+ExplodedNode*
+StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
+ const GRState* State,
+ ExplodedNode* Pred) {
+ bool IsNew;
+ ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
+ N->addPredecessor(Pred, *Eng.G);
+ Deferred.erase(Pred);
+
+ if (IsNew) {
+ Deferred.insert(N);
+ return N;
+ }
+
+ return NULL;
+}
+
+ExplodedNode* BranchNodeBuilder::generateNode(const GRState* State,
+ bool branch) {
+
+ // If the branch has been marked infeasible we should not generate a node.
+ if (!isFeasible(branch))
+ return NULL;
+
+ bool IsNew;
+
+ ExplodedNode* Succ =
+ Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
+ State, &IsNew);
+
+ Succ->addPredecessor(Pred, *Eng.G);
+
+ if (branch)
+ GeneratedTrue = true;
+ else
+ GeneratedFalse = true;
+
+ if (IsNew) {
+ Deferred.push_back(Succ);
+ return Succ;
+ }
+
+ return NULL;
+}
+
+BranchNodeBuilder::~BranchNodeBuilder() {
+ if (!GeneratedTrue) generateNode(Pred->State, true);
+ if (!GeneratedFalse) generateNode(Pred->State, false);
+
+ for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
+ if (!(*I)->isSink()) Eng.WList->enqueue(*I);
+}
+
+
+ExplodedNode*
+IndirectGotoNodeBuilder::generateNode(const iterator& I, const GRState* St,
+ bool isSink) {
+ bool IsNew;
+
+ ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
+ Pred->getLocationContext()), St, &IsNew);
+
+ Succ->addPredecessor(Pred, *Eng.G);
+
+ if (IsNew) {
+
+ if (isSink)
+ Succ->markAsSink();
+ else
+ Eng.WList->enqueue(Succ);
+
+ return Succ;
+ }
+
+ return NULL;
+}
+
+
+ExplodedNode*
+SwitchNodeBuilder::generateCaseStmtNode(const iterator& I, const GRState* St){
+
+ bool IsNew;
+
+ ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(),
+ Pred->getLocationContext()), St, &IsNew);
+ Succ->addPredecessor(Pred, *Eng.G);
+
+ if (IsNew) {
+ Eng.WList->enqueue(Succ);
+ return Succ;
+ }
+
+ return NULL;
+}
+
+
+ExplodedNode*
+SwitchNodeBuilder::generateDefaultCaseNode(const GRState* St, bool isSink) {
+
+ // Get the block for the default case.
+ assert (Src->succ_rbegin() != Src->succ_rend());
+ CFGBlock* DefaultBlock = *Src->succ_rbegin();
+
+ bool IsNew;
+
+ ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
+ Pred->getLocationContext()), St, &IsNew);
+ Succ->addPredecessor(Pred, *Eng.G);
+
+ if (IsNew) {
+ if (isSink)
+ Succ->markAsSink();
+ else
+ Eng.WList->enqueue(Succ);
+
+ return Succ;
+ }
+
+ return NULL;
+}
+
+EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
+ // Auto-generate an EOP node if one has not been generated.
+ if (!hasGeneratedNode) {
+ // If we are in an inlined call, generate CallExit node.
+ if (Pred->getLocationContext()->getParent())
+ GenerateCallExitNode(Pred->State);
+ else
+ generateNode(Pred->State);
+ }
+}
+
+ExplodedNode*
+EndOfFunctionNodeBuilder::generateNode(const GRState* State, const void *tag,
+ ExplodedNode* P) {
+ hasGeneratedNode = true;
+ bool IsNew;
+
+ ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
+ Pred->getLocationContext(), tag), State, &IsNew);
+
+ Node->addPredecessor(P ? P : Pred, *Eng.G);
+
+ if (IsNew) {
+ Eng.G->addEndOfPath(Node);
+ return Node;
+ }
+
+ return NULL;
+}
+
+void EndOfFunctionNodeBuilder::GenerateCallExitNode(const GRState *state) {
+ hasGeneratedNode = true;
+ // Create a CallExit node and enqueue it.
+ const StackFrameContext *LocCtx
+ = cast<StackFrameContext>(Pred->getLocationContext());
+ const Stmt *CE = LocCtx->getCallSite();
+
+ // Use the the callee location context.
+ CallExit Loc(CE, LocCtx);
+
+ bool isNew;
+ ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
+ Node->addPredecessor(Pred, *Eng.G);
+
+ if (isNew)
+ Eng.WList->enqueue(Node);
+}
+
+
+void CallEnterNodeBuilder::generateNode(const GRState *state) {
+ // Check if the callee is in the same translation unit.
+ if (CalleeCtx->getTranslationUnit() !=
+ Pred->getLocationContext()->getTranslationUnit()) {
+ // Create a new engine. We must be careful that the new engine should not
+ // reference data structures owned by the old engine.
+
+ AnalysisManager &OldMgr = Eng.SubEng.getAnalysisManager();
+
+ // Get the callee's translation unit.
+ idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
+
+ // Create a new AnalysisManager with components of the callee's
+ // TranslationUnit.
+ // The Diagnostic is actually shared when we create ASTUnits from AST files.
+ AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(),
+ OldMgr.getLangOptions(),
+ OldMgr.getPathDiagnosticClient(),
+ OldMgr.getStoreManagerCreator(),
+ OldMgr.getConstraintManagerCreator(),
+ OldMgr.getCheckerManager(),
+ OldMgr.getIndexer(),
+ OldMgr.getMaxNodes(), OldMgr.getMaxVisit(),
+ OldMgr.shouldVisualizeGraphviz(),
+ OldMgr.shouldVisualizeUbigraph(),
+ OldMgr.shouldPurgeDead(),
+ OldMgr.shouldEagerlyAssume(),
+ OldMgr.shouldTrimGraph(),
+ OldMgr.shouldInlineCall(),
+ OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(),
+ OldMgr.getAnalysisContextManager().getAddImplicitDtors(),
+ OldMgr.getAnalysisContextManager().getAddInitializers(),
+ OldMgr.shouldEagerlyTrimExplodedGraph());
+ llvm::OwningPtr<TransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
+ /* GCEnabled */ false,
+ AMgr.getLangOptions()));
+ // Create the new engine.
+ ExprEngine NewEng(AMgr, TF.take());
+
+ // Create the new LocationContext.
+ AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
+ CalleeCtx->getTranslationUnit());
+ const StackFrameContext *OldLocCtx = CalleeCtx;
+ const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
+ OldLocCtx->getParent(),
+ OldLocCtx->getCallSite(),
+ OldLocCtx->getCallSiteBlock(),
+ OldLocCtx->getIndex());
+
+ // Now create an initial state for the new engine.
+ const GRState *NewState = NewEng.getStateManager().MarshalState(state,
+ NewLocCtx);
+ ExplodedNodeSet ReturnNodes;
+ NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
+ NewState, ReturnNodes);
+ return;
+ }
+
+ // Get the callee entry block.
+ const CFGBlock *Entry = &(CalleeCtx->getCFG()->getEntry());
+ assert(Entry->empty());
+ assert(Entry->succ_size() == 1);
+
+ // Get the solitary successor.
+ const CFGBlock *SuccB = *(Entry->succ_begin());
+
+ // Construct an edge representing the starting location in the callee.
+ BlockEdge Loc(Entry, SuccB, CalleeCtx);
+
+ bool isNew;
+ ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
+ Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
+
+ if (isNew)
+ Eng.WList->enqueue(Node);
+}
+
+void CallExitNodeBuilder::generateNode(const GRState *state) {
+ // Get the callee's location context.
+ const StackFrameContext *LocCtx
+ = cast<StackFrameContext>(Pred->getLocationContext());
+ // When exiting an implicit automatic obj dtor call, the callsite is the Stmt
+ // that triggers the dtor.
+ PostStmt Loc(LocCtx->getCallSite(), LocCtx->getParent());
+ bool isNew;
+ ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
+ Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
+ if (isNew)
+ Eng.WList->enqueue(Node, LocCtx->getCallSiteBlock(),
+ LocCtx->getIndex() + 1);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
new file mode 100644
index 0000000..ecaff29
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -0,0 +1,234 @@
+//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the Environment and EnvironmentManager classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+
+using namespace clang;
+using namespace ento;
+
+SVal Environment::lookupExpr(const Stmt* E) const {
+ const SVal* X = ExprBindings.lookup(E);
+ if (X) {
+ SVal V = *X;
+ return V;
+ }
+ return UnknownVal();
+}
+
+SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const {
+ for (;;) {
+ switch (E->getStmtClass()) {
+ case Stmt::AddrLabelExprClass:
+ return svalBuilder.makeLoc(cast<AddrLabelExpr>(E));
+ case Stmt::ParenExprClass:
+ // ParenExprs are no-ops.
+ E = cast<ParenExpr>(E)->getSubExpr();
+ continue;
+ case Stmt::CharacterLiteralClass: {
+ const CharacterLiteral* C = cast<CharacterLiteral>(E);
+ return svalBuilder.makeIntVal(C->getValue(), C->getType());
+ }
+ case Stmt::CXXBoolLiteralExprClass: {
+ const SVal *X = ExprBindings.lookup(E);
+ if (X)
+ return *X;
+ else
+ return svalBuilder.makeBoolVal(cast<CXXBoolLiteralExpr>(E));
+ }
+ case Stmt::IntegerLiteralClass: {
+ // In C++, this expression may have been bound to a temporary object.
+ SVal const *X = ExprBindings.lookup(E);
+ if (X)
+ return *X;
+ else
+ return svalBuilder.makeIntVal(cast<IntegerLiteral>(E));
+ }
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::CStyleCastExprClass: {
+ // We blast through no-op casts to get the descendant
+ // subexpression that has a value.
+ const CastExpr* C = cast<CastExpr>(E);
+ QualType CT = C->getType();
+ if (CT->isVoidType())
+ return UnknownVal();
+ if (C->getCastKind() == CK_NoOp) {
+ E = C->getSubExpr();
+ continue;
+ }
+ break;
+ }
+ case Stmt::ExprWithCleanupsClass:
+ E = cast<ExprWithCleanups>(E)->getSubExpr();
+ continue;
+ case Stmt::CXXBindTemporaryExprClass:
+ E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
+ continue;
+ // Handle all other Stmt* using a lookup.
+ default:
+ break;
+ };
+ break;
+ }
+ return lookupExpr(E);
+}
+
+Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S,
+ SVal V, bool Invalidate) {
+ assert(S);
+
+ if (V.isUnknown()) {
+ if (Invalidate)
+ return Environment(F.remove(Env.ExprBindings, S));
+ else
+ return Env;
+ }
+
+ return Environment(F.add(Env.ExprBindings, S, V));
+}
+
+static inline const Stmt *MakeLocation(const Stmt *S) {
+ return (const Stmt*) (((uintptr_t) S) | 0x1);
+}
+
+Environment EnvironmentManager::bindExprAndLocation(Environment Env,
+ const Stmt *S,
+ SVal location, SVal V) {
+ return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location),
+ S, V));
+}
+
+namespace {
+class MarkLiveCallback : public SymbolVisitor {
+ SymbolReaper &SymReaper;
+public:
+ MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
+ bool VisitSymbol(SymbolRef sym) { SymReaper.markLive(sym); return true; }
+};
+} // end anonymous namespace
+
+static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) {
+ const LocationContext *ParentLC = LC->getParent();
+ while (ParentLC) {
+ CFG &C = *ParentLC->getCFG();
+ if (C.isBlkExpr(E))
+ return true;
+ ParentLC = ParentLC->getParent();
+ }
+
+ return false;
+}
+
+// In addition to mapping from Stmt * - > SVals in the Environment, we also
+// maintain a mapping from Stmt * -> SVals (locations) that were used during
+// a load and store.
+static inline bool IsLocation(const Stmt *S) {
+ return (bool) (((uintptr_t) S) & 0x1);
+}
+
+// removeDeadBindings:
+// - Remove subexpression bindings.
+// - Remove dead block expression bindings.
+// - Keep live block expression bindings:
+// - Mark their reachable symbols live in SymbolReaper,
+// see ScanReachableSymbols.
+// - Mark the region in DRoots if the binding is a loc::MemRegionVal.
+Environment
+EnvironmentManager::removeDeadBindings(Environment Env,
+ SymbolReaper &SymReaper,
+ const GRState *ST,
+ llvm::SmallVectorImpl<const MemRegion*> &DRoots) {
+
+ CFG &C = *SymReaper.getLocationContext()->getCFG();
+
+ // We construct a new Environment object entirely, as this is cheaper than
+ // individually removing all the subexpression bindings (which will greatly
+ // outnumber block-level expression bindings).
+ Environment NewEnv = getInitialEnvironment();
+
+ llvm::SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations;
+
+ // Iterate over the block-expr bindings.
+ for (Environment::iterator I = Env.begin(), E = Env.end();
+ I != E; ++I) {
+
+ const Stmt *BlkExpr = I.getKey();
+
+ // For recorded locations (used when evaluating loads and stores), we
+ // consider them live only when their associated normal expression is
+ // also live.
+ // NOTE: This assumes that loads/stores that evaluated to UnknownVal
+ // still have an entry in the map.
+ if (IsLocation(BlkExpr)) {
+ deferredLocations.push_back(std::make_pair(BlkExpr, I.getData()));
+ continue;
+ }
+
+ const SVal &X = I.getData();
+
+ // Block-level expressions in callers are assumed always live.
+ if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) {
+ NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X);
+
+ if (isa<loc::MemRegionVal>(X)) {
+ const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
+ DRoots.push_back(R);
+ }
+
+ // Mark all symbols in the block expr's value live.
+ MarkLiveCallback cb(SymReaper);
+ ST->scanReachableSymbols(X, cb);
+ continue;
+ }
+
+ // Not a block-level expression?
+ if (!C.isBlkExpr(BlkExpr))
+ continue;
+
+ if (SymReaper.isLive(BlkExpr)) {
+ // Copy the binding to the new map.
+ NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X);
+
+ // If the block expr's value is a memory region, then mark that region.
+ if (isa<loc::MemRegionVal>(X)) {
+ const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
+ DRoots.push_back(R);
+ }
+
+ // Mark all symbols in the block expr's value live.
+ MarkLiveCallback cb(SymReaper);
+ ST->scanReachableSymbols(X, cb);
+ continue;
+ }
+
+ // Otherwise the expression is dead with a couple exceptions.
+ // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the
+ // beginning of itself, but we need its UndefinedVal to determine its
+ // SVal.
+ if (X.isUndef() && cast<UndefinedVal>(X).getData())
+ NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X);
+ }
+
+ // Go through he deferred locations and add them to the new environment if
+ // the correspond Stmt* is in the map as well.
+ for (llvm::SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator
+ I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
+ const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1);
+ if (NewEnv.ExprBindings.lookup(S))
+ NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, I->first, I->second);
+ }
+
+ return NewEnv;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
new file mode 100644
index 0000000..2a8364d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -0,0 +1,392 @@
+//=-- ExplodedGraph.cpp - Local, Path-Sens. "Exploded Graph" -*- 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 template classes ExplodedNode and ExplodedGraph,
+// which represent a path-sensitive, intra-procedural "exploded graph."
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Node auditing.
+//===----------------------------------------------------------------------===//
+
+// An out of line virtual method to provide a home for the class vtable.
+ExplodedNode::Auditor::~Auditor() {}
+
+#ifndef NDEBUG
+static ExplodedNode::Auditor* NodeAuditor = 0;
+#endif
+
+void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
+#ifndef NDEBUG
+ NodeAuditor = A;
+#endif
+}
+
+//===----------------------------------------------------------------------===//
+// Cleanup.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<ExplodedNode*> NodeList;
+static inline NodeList*& getNodeList(void *&p) { return (NodeList*&) p; }
+
+ExplodedGraph::~ExplodedGraph() {
+ if (reclaimNodes) {
+ delete getNodeList(recentlyAllocatedNodes);
+ delete getNodeList(freeNodes);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Node reclamation.
+//===----------------------------------------------------------------------===//
+
+void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
+ if (!recentlyAllocatedNodes)
+ return;
+ NodeList &nl = *getNodeList(recentlyAllocatedNodes);
+
+ // Reclaimn all nodes that match *all* the following criteria:
+ //
+ // (1) 1 predecessor (that has one successor)
+ // (2) 1 successor (that has one predecessor)
+ // (3) The ProgramPoint is for a PostStmt.
+ // (4) There is no 'tag' for the ProgramPoint.
+ // (5) The 'store' is the same as the predecessor.
+ // (6) The 'GDM' is the same as the predecessor.
+ // (7) The LocationContext is the same as the predecessor.
+ // (8) The PostStmt is for a non-CFGElement expression.
+
+ for (NodeList::iterator i = nl.begin(), e = nl.end() ; i != e; ++i) {
+ ExplodedNode *node = *i;
+
+ // Conditions 1 and 2.
+ if (node->pred_size() != 1 || node->succ_size() != 1)
+ continue;
+
+ ExplodedNode *pred = *(node->pred_begin());
+ if (pred->succ_size() != 1)
+ continue;
+
+ ExplodedNode *succ = *(node->succ_begin());
+ if (succ->pred_size() != 1)
+ continue;
+
+ // Condition 3.
+ ProgramPoint progPoint = node->getLocation();
+ if (!isa<PostStmt>(progPoint))
+ continue;
+
+ // Condition 4.
+ PostStmt ps = cast<PostStmt>(progPoint);
+ if (ps.getTag() || isa<PostStmtCustom>(ps))
+ continue;
+
+ if (isa<BinaryOperator>(ps.getStmt()))
+ continue;
+
+ // Conditions 5, 6, and 7.
+ const GRState *state = node->getState();
+ const GRState *pred_state = pred->getState();
+ if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
+ progPoint.getLocationContext() != pred->getLocationContext())
+ continue;
+
+ // Condition 8.
+ if (node->getCFG().isBlkExpr(ps.getStmt()))
+ continue;
+
+ // If we reach here, we can remove the node. This means:
+ // (a) changing the predecessors successor to the successor of this node
+ // (b) changing the successors predecessor to the predecessor of this node
+ // (c) Putting 'node' onto freeNodes.
+ pred->replaceSuccessor(succ);
+ succ->replacePredecessor(pred);
+ if (!freeNodes)
+ freeNodes = new NodeList();
+ getNodeList(freeNodes)->push_back(node);
+ Nodes.RemoveNode(node);
+ --NumNodes;
+ node->~ExplodedNode();
+ }
+
+ nl.clear();
+}
+
+//===----------------------------------------------------------------------===//
+// ExplodedNode.
+//===----------------------------------------------------------------------===//
+
+static inline BumpVector<ExplodedNode*>& getVector(void* P) {
+ return *reinterpret_cast<BumpVector<ExplodedNode*>*>(P);
+}
+
+void ExplodedNode::addPredecessor(ExplodedNode* V, ExplodedGraph &G) {
+ assert (!V->isSink());
+ Preds.addNode(V, G);
+ V->Succs.addNode(this, G);
+#ifndef NDEBUG
+ if (NodeAuditor) NodeAuditor->AddEdge(V, this);
+#endif
+}
+
+void ExplodedNode::NodeGroup::replaceNode(ExplodedNode *node) {
+ assert(getKind() == Size1);
+ P = reinterpret_cast<uintptr_t>(node);
+ assert(getKind() == Size1);
+}
+
+void ExplodedNode::NodeGroup::addNode(ExplodedNode* N, ExplodedGraph &G) {
+ assert((reinterpret_cast<uintptr_t>(N) & Mask) == 0x0);
+ assert(!getFlag());
+
+ if (getKind() == Size1) {
+ if (ExplodedNode* NOld = getNode()) {
+ BumpVectorContext &Ctx = G.getNodeAllocator();
+ BumpVector<ExplodedNode*> *V =
+ G.getAllocator().Allocate<BumpVector<ExplodedNode*> >();
+ new (V) BumpVector<ExplodedNode*>(Ctx, 4);
+
+ assert((reinterpret_cast<uintptr_t>(V) & Mask) == 0x0);
+ V->push_back(NOld, Ctx);
+ V->push_back(N, Ctx);
+ P = reinterpret_cast<uintptr_t>(V) | SizeOther;
+ assert(getPtr() == (void*) V);
+ assert(getKind() == SizeOther);
+ }
+ else {
+ P = reinterpret_cast<uintptr_t>(N);
+ assert(getKind() == Size1);
+ }
+ }
+ else {
+ assert(getKind() == SizeOther);
+ getVector(getPtr()).push_back(N, G.getNodeAllocator());
+ }
+}
+
+unsigned ExplodedNode::NodeGroup::size() const {
+ if (getFlag())
+ return 0;
+
+ if (getKind() == Size1)
+ return getNode() ? 1 : 0;
+ else
+ return getVector(getPtr()).size();
+}
+
+ExplodedNode **ExplodedNode::NodeGroup::begin() const {
+ if (getFlag())
+ return NULL;
+
+ if (getKind() == Size1)
+ return (ExplodedNode**) (getPtr() ? &P : NULL);
+ else
+ return const_cast<ExplodedNode**>(&*(getVector(getPtr()).begin()));
+}
+
+ExplodedNode** ExplodedNode::NodeGroup::end() const {
+ if (getFlag())
+ return NULL;
+
+ if (getKind() == Size1)
+ return (ExplodedNode**) (getPtr() ? &P+1 : NULL);
+ else {
+ // Dereferencing end() is undefined behaviour. The vector is not empty, so
+ // we can dereference the last elem and then add 1 to the result.
+ return const_cast<ExplodedNode**>(getVector(getPtr()).end());
+ }
+}
+
+ExplodedNode *ExplodedGraph::getNode(const ProgramPoint& L,
+ const GRState* State, bool* IsNew) {
+ // Profile 'State' to determine if we already have an existing node.
+ llvm::FoldingSetNodeID profile;
+ void* InsertPos = 0;
+
+ NodeTy::Profile(profile, L, State);
+ NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
+
+ if (!V) {
+ if (freeNodes && !getNodeList(freeNodes)->empty()) {
+ NodeList *nl = getNodeList(freeNodes);
+ V = nl->back();
+ nl->pop_back();
+ }
+ else {
+ // Allocate a new node.
+ V = (NodeTy*) getAllocator().Allocate<NodeTy>();
+ }
+
+ new (V) NodeTy(L, State);
+
+ if (reclaimNodes) {
+ if (!recentlyAllocatedNodes)
+ recentlyAllocatedNodes = new NodeList();
+ getNodeList(recentlyAllocatedNodes)->push_back(V);
+ }
+
+ // Insert the node into the node set and return it.
+ Nodes.InsertNode(V, InsertPos);
+
+ ++NumNodes;
+
+ if (IsNew) *IsNew = true;
+ }
+ else
+ if (IsNew) *IsNew = false;
+
+ return V;
+}
+
+std::pair<ExplodedGraph*, InterExplodedGraphMap*>
+ExplodedGraph::Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
+ llvm::DenseMap<const void*, const void*> *InverseMap) const {
+
+ if (NBeg == NEnd)
+ return std::make_pair((ExplodedGraph*) 0,
+ (InterExplodedGraphMap*) 0);
+
+ assert (NBeg < NEnd);
+
+ llvm::OwningPtr<InterExplodedGraphMap> M(new InterExplodedGraphMap());
+
+ ExplodedGraph* G = TrimInternal(NBeg, NEnd, M.get(), InverseMap);
+
+ return std::make_pair(static_cast<ExplodedGraph*>(G), M.take());
+}
+
+ExplodedGraph*
+ExplodedGraph::TrimInternal(const ExplodedNode* const* BeginSources,
+ const ExplodedNode* const* EndSources,
+ InterExplodedGraphMap* M,
+ llvm::DenseMap<const void*, const void*> *InverseMap) const {
+
+ typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
+ Pass1Ty Pass1;
+
+ typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> Pass2Ty;
+ Pass2Ty& Pass2 = M->M;
+
+ llvm::SmallVector<const ExplodedNode*, 10> WL1, WL2;
+
+ // ===- Pass 1 (reverse DFS) -===
+ for (const ExplodedNode* const* I = BeginSources; I != EndSources; ++I) {
+ assert(*I);
+ WL1.push_back(*I);
+ }
+
+ // Process the first worklist until it is empty. Because it is a std::list
+ // it acts like a FIFO queue.
+ while (!WL1.empty()) {
+ const ExplodedNode *N = WL1.back();
+ WL1.pop_back();
+
+ // Have we already visited this node? If so, continue to the next one.
+ if (Pass1.count(N))
+ continue;
+
+ // Otherwise, mark this node as visited.
+ Pass1.insert(N);
+
+ // If this is a root enqueue it to the second worklist.
+ if (N->Preds.empty()) {
+ WL2.push_back(N);
+ continue;
+ }
+
+ // Visit our predecessors and enqueue them.
+ for (ExplodedNode** I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I)
+ WL1.push_back(*I);
+ }
+
+ // We didn't hit a root? Return with a null pointer for the new graph.
+ if (WL2.empty())
+ return 0;
+
+ // Create an empty graph.
+ ExplodedGraph* G = MakeEmptyGraph();
+
+ // ===- Pass 2 (forward DFS to construct the new graph) -===
+ while (!WL2.empty()) {
+ const ExplodedNode* N = WL2.back();
+ WL2.pop_back();
+
+ // Skip this node if we have already processed it.
+ if (Pass2.find(N) != Pass2.end())
+ continue;
+
+ // Create the corresponding node in the new graph and record the mapping
+ // from the old node to the new node.
+ ExplodedNode* NewN = G->getNode(N->getLocation(), N->State, NULL);
+ Pass2[N] = NewN;
+
+ // Also record the reverse mapping from the new node to the old node.
+ if (InverseMap) (*InverseMap)[NewN] = N;
+
+ // If this node is a root, designate it as such in the graph.
+ if (N->Preds.empty())
+ G->addRoot(NewN);
+
+ // In the case that some of the intended predecessors of NewN have already
+ // been created, we should hook them up as predecessors.
+
+ // Walk through the predecessors of 'N' and hook up their corresponding
+ // nodes in the new graph (if any) to the freshly created node.
+ for (ExplodedNode **I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I) {
+ Pass2Ty::iterator PI = Pass2.find(*I);
+ if (PI == Pass2.end())
+ continue;
+
+ NewN->addPredecessor(PI->second, *G);
+ }
+
+ // In the case that some of the intended successors of NewN have already
+ // been created, we should hook them up as successors. Otherwise, enqueue
+ // the new nodes from the original graph that should have nodes created
+ // in the new graph.
+ for (ExplodedNode **I=N->Succs.begin(), **E=N->Succs.end(); I!=E; ++I) {
+ Pass2Ty::iterator PI = Pass2.find(*I);
+ if (PI != Pass2.end()) {
+ PI->second->addPredecessor(NewN, *G);
+ continue;
+ }
+
+ // Enqueue nodes to the worklist that were marked during pass 1.
+ if (Pass1.count(*I))
+ WL2.push_back(*I);
+ }
+
+ // Finally, explictly mark all nodes without any successors as sinks.
+ if (N->isSink())
+ NewN->markAsSink();
+ }
+
+ return G;
+}
+
+ExplodedNode*
+InterExplodedGraphMap::getMappedNode(const ExplodedNode* N) const {
+ llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::const_iterator I =
+ M.find(N);
+
+ return I == M.end() ? 0 : I->second;
+}
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp
new file mode 100644
index 0000000..99a5ead
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp
@@ -0,0 +1,204 @@
+//=== FlatStore.cpp - Flat region-based store model -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "llvm/ADT/ImmutableIntervalMap.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::Interval;
+
+// The actual store type.
+typedef llvm::ImmutableIntervalMap<SVal> BindingVal;
+typedef llvm::ImmutableMap<const MemRegion *, BindingVal> RegionBindings;
+
+namespace {
+class FlatStoreManager : public StoreManager {
+ RegionBindings::Factory RBFactory;
+ BindingVal::Factory BVFactory;
+
+public:
+ FlatStoreManager(GRStateManager &mgr)
+ : StoreManager(mgr),
+ RBFactory(mgr.getAllocator()),
+ BVFactory(mgr.getAllocator()) {}
+
+ SVal Retrieve(Store store, Loc L, QualType T);
+ StoreRef Bind(Store store, Loc L, SVal val);
+ StoreRef Remove(Store St, Loc L);
+ StoreRef BindCompoundLiteral(Store store, const CompoundLiteralExpr* cl,
+ const LocationContext *LC, SVal v);
+
+ StoreRef getInitialStore(const LocationContext *InitLoc) {
+ return StoreRef(RBFactory.getEmptyMap().getRoot(), *this);
+ }
+
+ SubRegionMap *getSubRegionMap(Store store) {
+ return 0;
+ }
+
+ SVal ArrayToPointer(Loc Array);
+ StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots){
+ return StoreRef(store, *this);
+ }
+
+ StoreRef BindDecl(Store store, const VarRegion *VR, SVal initVal);
+
+ StoreRef BindDeclWithNoInit(Store store, const VarRegion *VR);
+
+ typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+
+ StoreRef invalidateRegions(Store store, const MemRegion * const *I,
+ const MemRegion * const *E, const Expr *Ex,
+ unsigned Count, InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions);
+
+ void print(Store store, llvm::raw_ostream& Out, const char* nl,
+ const char *sep);
+ void iterBindings(Store store, BindingsHandler& f);
+
+private:
+ static RegionBindings getRegionBindings(Store store) {
+ return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
+ }
+
+ class RegionInterval {
+ public:
+ const MemRegion *R;
+ Interval I;
+ RegionInterval(const MemRegion *r, int64_t s, int64_t e) : R(r), I(s, e){}
+ };
+
+ RegionInterval RegionToInterval(const MemRegion *R);
+
+ SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
+};
+} // end anonymous namespace
+
+StoreManager *ento::CreateFlatStoreManager(GRStateManager &StMgr) {
+ return new FlatStoreManager(StMgr);
+}
+
+SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
+ const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
+ RegionInterval RI = RegionToInterval(R);
+ // FIXME: FlatStore should handle regions with unknown intervals.
+ if (!RI.R)
+ return UnknownVal();
+
+ RegionBindings B = getRegionBindings(store);
+ const BindingVal *BV = B.lookup(RI.R);
+ if (BV) {
+ const SVal *V = BVFactory.lookup(*BV, RI.I);
+ if (V)
+ return *V;
+ else
+ return RetrieveRegionWithNoBinding(R, T);
+ }
+ return RetrieveRegionWithNoBinding(R, T);
+}
+
+SVal FlatStoreManager::RetrieveRegionWithNoBinding(const MemRegion *R,
+ QualType T) {
+ if (R->hasStackNonParametersStorage())
+ return UndefinedVal();
+ else
+ return svalBuilder.getRegionValueSymbolVal(cast<TypedRegion>(R));
+}
+
+StoreRef FlatStoreManager::Bind(Store store, Loc L, SVal val) {
+ const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
+ RegionBindings B = getRegionBindings(store);
+ const BindingVal *V = B.lookup(R);
+
+ BindingVal BV = BVFactory.getEmptyMap();
+ if (V)
+ BV = *V;
+
+ RegionInterval RI = RegionToInterval(R);
+ // FIXME: FlatStore should handle regions with unknown intervals.
+ if (!RI.R)
+ return StoreRef(B.getRoot(), *this);
+ BV = BVFactory.add(BV, RI.I, val);
+ B = RBFactory.add(B, RI.R, BV);
+ return StoreRef(B.getRoot(), *this);
+}
+
+StoreRef FlatStoreManager::Remove(Store store, Loc L) {
+ return StoreRef(store, *this);
+}
+
+StoreRef FlatStoreManager::BindCompoundLiteral(Store store,
+ const CompoundLiteralExpr* cl,
+ const LocationContext *LC,
+ SVal v) {
+ return StoreRef(store, *this);
+}
+
+SVal FlatStoreManager::ArrayToPointer(Loc Array) {
+ return Array;
+}
+
+StoreRef FlatStoreManager::BindDecl(Store store, const VarRegion *VR,
+ SVal initVal) {
+ return Bind(store, svalBuilder.makeLoc(VR), initVal);
+}
+
+StoreRef FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR){
+ return StoreRef(store, *this);
+}
+
+StoreRef FlatStoreManager::invalidateRegions(Store store,
+ const MemRegion * const *I,
+ const MemRegion * const *E,
+ const Expr *Ex, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
+ assert(false && "Not implemented");
+ return StoreRef(store, *this);
+}
+
+void FlatStoreManager::print(Store store, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) {
+}
+
+void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
+}
+
+FlatStoreManager::RegionInterval
+FlatStoreManager::RegionToInterval(const MemRegion *R) {
+ switch (R->getKind()) {
+ case MemRegion::VarRegionKind: {
+ QualType T = cast<VarRegion>(R)->getValueType();
+ int64_t Size = Ctx.getTypeSize(T);
+ return RegionInterval(R, 0, Size-1);
+ }
+
+ case MemRegion::ElementRegionKind:
+ case MemRegion::FieldRegionKind: {
+ RegionOffset Offset = R->getAsOffset();
+ // We cannot compute offset for all regions, for example, elements
+ // with symbolic offsets.
+ if (!Offset.getRegion())
+ return RegionInterval(0, 0, 0);
+ int64_t Start = Offset.getOffset();
+ int64_t Size = Ctx.getTypeSize(cast<TypedRegion>(R)->getValueType());
+ return RegionInterval(Offset.getRegion(), Start, Start+Size);
+ }
+
+ default:
+ llvm_unreachable("Region kind unhandled.");
+ return RegionInterval(0, 0, 0);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/GRState.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/GRState.cpp
new file mode 100644
index 0000000..7b21677
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/GRState.cpp
@@ -0,0 +1,606 @@
+//= GRState.cpp - Path-Sensitive "State" for tracking values -----*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements GRState and GRStateManager.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+// Give the vtable for ConstraintManager somewhere to live.
+// FIXME: Move this elsewhere.
+ConstraintManager::~ConstraintManager() {}
+
+GRState::GRState(GRStateManager *mgr, const Environment& env,
+ StoreRef st, GenericDataMap gdm)
+ : stateMgr(mgr),
+ Env(env),
+ store(st.getStore()),
+ GDM(gdm),
+ refCount(0) {
+ stateMgr->getStoreManager().incrementReferenceCount(store);
+}
+
+GRState::GRState(const GRState& RHS)
+ : llvm::FoldingSetNode(),
+ stateMgr(RHS.stateMgr),
+ Env(RHS.Env),
+ store(RHS.store),
+ GDM(RHS.GDM),
+ refCount(0) {
+ stateMgr->getStoreManager().incrementReferenceCount(store);
+}
+
+GRState::~GRState() {
+ if (store)
+ stateMgr->getStoreManager().decrementReferenceCount(store);
+}
+
+GRStateManager::~GRStateManager() {
+ for (std::vector<GRState::Printer*>::iterator I=Printers.begin(),
+ E=Printers.end(); I!=E; ++I)
+ delete *I;
+
+ for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
+ I!=E; ++I)
+ I->second.second(I->second.first);
+}
+
+const GRState*
+GRStateManager::removeDeadBindings(const GRState* state,
+ const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper) {
+
+ // This code essentially performs a "mark-and-sweep" of the VariableBindings.
+ // The roots are any Block-level exprs and Decls that our liveness algorithm
+ // tells us are live. We then see what Decls they may reference, and keep
+ // those around. This code more than likely can be made faster, and the
+ // frequency of which this method is called should be experimented with
+ // for optimum performance.
+ llvm::SmallVector<const MemRegion*, 10> RegionRoots;
+ GRState NewState = *state;
+
+ NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper,
+ state, RegionRoots);
+
+ // Clean up the store.
+ NewState.setStore(StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
+ SymReaper, RegionRoots));
+ state = getPersistentState(NewState);
+ return ConstraintMgr->removeDeadBindings(state, SymReaper);
+}
+
+const GRState *GRStateManager::MarshalState(const GRState *state,
+ const StackFrameContext *InitLoc) {
+ // make up an empty state for now.
+ GRState State(this,
+ EnvMgr.getInitialEnvironment(),
+ StoreMgr->getInitialStore(InitLoc),
+ GDMFactory.getEmptyMap());
+
+ return getPersistentState(State);
+}
+
+const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
+ const LocationContext *LC,
+ SVal V) const {
+ const StoreRef &newStore =
+ getStateManager().StoreMgr->BindCompoundLiteral(getStore(), CL, LC, V);
+ return makeWithStore(newStore);
+}
+
+const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
+ const StoreRef &newStore =
+ getStateManager().StoreMgr->BindDecl(getStore(), VR, IVal);
+ return makeWithStore(newStore);
+}
+
+const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
+ const StoreRef &newStore =
+ getStateManager().StoreMgr->BindDeclWithNoInit(getStore(), VR);
+ return makeWithStore(newStore);
+}
+
+const GRState *GRState::bindLoc(Loc LV, SVal V) const {
+ GRStateManager &Mgr = getStateManager();
+ const GRState *newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
+ LV, V));
+ const MemRegion *MR = LV.getAsRegion();
+ if (MR && Mgr.getOwningEngine())
+ return Mgr.getOwningEngine()->processRegionChange(newState, MR);
+
+ return newState;
+}
+
+const GRState *GRState::bindDefault(SVal loc, SVal V) const {
+ GRStateManager &Mgr = getStateManager();
+ const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
+ const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V);
+ const GRState *new_state = makeWithStore(newStore);
+ return Mgr.getOwningEngine() ?
+ Mgr.getOwningEngine()->processRegionChange(new_state, R) :
+ new_state;
+}
+
+const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const {
+ GRStateManager &Mgr = getStateManager();
+ SubEngine* Eng = Mgr.getOwningEngine();
+
+ if (Eng && Eng->wantsRegionChangeUpdate(this)) {
+ StoreManager::InvalidatedRegions Regions;
+ const StoreRef &newStore
+ = Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
+ invalidateGlobals, &Regions);
+ const GRState *newState = makeWithStore(newStore);
+ return Eng->processRegionChanges(newState,
+ &Regions.front(),
+ &Regions.back()+1);
+ }
+
+ const StoreRef &newStore =
+ Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
+ invalidateGlobals, NULL);
+ return makeWithStore(newStore);
+}
+
+const GRState *GRState::unbindLoc(Loc LV) const {
+ assert(!isa<loc::MemRegionVal>(LV) && "Use invalidateRegion instead.");
+
+ Store OldStore = getStore();
+ const StoreRef &newStore = getStateManager().StoreMgr->Remove(OldStore, LV);
+
+ if (newStore.getStore() == OldStore)
+ return this;
+
+ return makeWithStore(newStore);
+}
+
+const GRState *GRState::enterStackFrame(const StackFrameContext *frame) const {
+ const StoreRef &new_store =
+ getStateManager().StoreMgr->enterStackFrame(this, frame);
+ return makeWithStore(new_store);
+}
+
+SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
+ // We only want to do fetches from regions that we can actually bind
+ // values. For example, SymbolicRegions of type 'id<...>' cannot
+ // have direct bindings (but their can be bindings on their subregions).
+ if (!R->isBoundable())
+ return UnknownVal();
+
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ QualType T = TR->getValueType();
+ if (Loc::isLocType(T) || T->isIntegerType())
+ return getSVal(R);
+ }
+
+ return UnknownVal();
+}
+
+SVal GRState::getSVal(Loc location, QualType T) const {
+ SVal V = getRawSVal(cast<Loc>(location), T);
+
+ // If 'V' is a symbolic value that is *perfectly* constrained to
+ // be a constant value, use that value instead to lessen the burden
+ // on later analysis stages (so we have less symbolic values to reason
+ // about).
+ if (!T.isNull()) {
+ if (SymbolRef sym = V.getAsSymbol()) {
+ if (const llvm::APSInt *Int = getSymVal(sym)) {
+ // FIXME: Because we don't correctly model (yet) sign-extension
+ // and truncation of symbolic values, we need to convert
+ // the integer value to the correct signedness and bitwidth.
+ //
+ // This shows up in the following:
+ //
+ // char foo();
+ // unsigned x = foo();
+ // if (x == 54)
+ // ...
+ //
+ // The symbolic value stored to 'x' is actually the conjured
+ // symbol for the call to foo(); the type of that symbol is 'char',
+ // not unsigned.
+ const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
+
+ if (isa<Loc>(V))
+ return loc::ConcreteInt(NewV);
+ else
+ return nonloc::ConcreteInt(NewV);
+ }
+ }
+ }
+
+ return V;
+}
+
+const GRState *GRState::BindExpr(const Stmt* S, SVal V, bool Invalidate) const{
+ Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V,
+ Invalidate);
+ if (NewEnv == Env)
+ return this;
+
+ GRState NewSt = *this;
+ NewSt.Env = NewEnv;
+ return getStateManager().getPersistentState(NewSt);
+}
+
+const GRState *GRState::bindExprAndLocation(const Stmt *S, SVal location,
+ SVal V) const {
+ Environment NewEnv =
+ getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V);
+
+ if (NewEnv == Env)
+ return this;
+
+ GRState NewSt = *this;
+ NewSt.Env = NewEnv;
+ return getStateManager().getPersistentState(NewSt);
+}
+
+const GRState *GRState::assumeInBound(DefinedOrUnknownSVal Idx,
+ DefinedOrUnknownSVal UpperBound,
+ bool Assumption) const {
+ if (Idx.isUnknown() || UpperBound.isUnknown())
+ return this;
+
+ // Build an expression for 0 <= Idx < UpperBound.
+ // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
+ // FIXME: This should probably be part of SValBuilder.
+ GRStateManager &SM = getStateManager();
+ SValBuilder &svalBuilder = SM.getSValBuilder();
+ ASTContext &Ctx = svalBuilder.getContext();
+
+ // Get the offset: the minimum value of the array index type.
+ BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
+ // FIXME: This should be using ValueManager::ArrayindexTy...somehow.
+ QualType indexTy = Ctx.IntTy;
+ nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
+
+ // Adjust the index.
+ SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
+ cast<NonLoc>(Idx), Min, indexTy);
+ if (newIdx.isUnknownOrUndef())
+ return this;
+
+ // Adjust the upper bound.
+ SVal newBound =
+ svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound),
+ Min, indexTy);
+
+ if (newBound.isUnknownOrUndef())
+ return this;
+
+ // Build the actual comparison.
+ SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT,
+ cast<NonLoc>(newIdx), cast<NonLoc>(newBound),
+ Ctx.IntTy);
+ if (inBound.isUnknownOrUndef())
+ return this;
+
+ // Finally, let the constraint manager take care of it.
+ ConstraintManager &CM = SM.getConstraintManager();
+ return CM.assume(this, cast<DefinedSVal>(inBound), Assumption);
+}
+
+const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
+ GRState State(this,
+ EnvMgr.getInitialEnvironment(),
+ StoreMgr->getInitialStore(InitLoc),
+ GDMFactory.getEmptyMap());
+
+ return getPersistentState(State);
+}
+
+void GRStateManager::recycleUnusedStates() {
+ for (std::vector<GRState*>::iterator i = recentlyAllocatedStates.begin(),
+ e = recentlyAllocatedStates.end(); i != e; ++i) {
+ GRState *state = *i;
+ if (state->referencedByExplodedNode())
+ continue;
+ StateSet.RemoveNode(state);
+ freeStates.push_back(state);
+ state->~GRState();
+ }
+ recentlyAllocatedStates.clear();
+}
+
+const GRState* GRStateManager::getPersistentState(GRState& State) {
+
+ llvm::FoldingSetNodeID ID;
+ State.Profile(ID);
+ void* InsertPos;
+
+ if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
+ return I;
+
+ GRState *newState = 0;
+ if (!freeStates.empty()) {
+ newState = freeStates.back();
+ freeStates.pop_back();
+ }
+ else {
+ newState = (GRState*) Alloc.Allocate<GRState>();
+ }
+ new (newState) GRState(State);
+ StateSet.InsertNode(newState, InsertPos);
+ recentlyAllocatedStates.push_back(newState);
+ return newState;
+}
+
+const GRState* GRState::makeWithStore(const StoreRef &store) const {
+ GRState NewSt = *this;
+ NewSt.setStore(store);
+ return getStateManager().getPersistentState(NewSt);
+}
+
+void GRState::setStore(const StoreRef &newStore) {
+ Store newStoreStore = newStore.getStore();
+ if (newStoreStore)
+ stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
+ if (store)
+ stateMgr->getStoreManager().decrementReferenceCount(store);
+ store = newStoreStore;
+}
+
+//===----------------------------------------------------------------------===//
+// State pretty-printing.
+//===----------------------------------------------------------------------===//
+
+static bool IsEnvLoc(const Stmt *S) {
+ // FIXME: This is a layering violation. Should be in environment.
+ return (bool) (((uintptr_t) S) & 0x1);
+}
+
+void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
+ const char* sep) const {
+ // Print the store.
+ GRStateManager &Mgr = getStateManager();
+ Mgr.getStoreManager().print(getStore(), Out, nl, sep);
+
+ // Print Subexpression bindings.
+ bool isFirst = true;
+
+ // FIXME: All environment printing should be moved inside Environment.
+ for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
+ if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey()))
+ continue;
+
+ if (isFirst) {
+ Out << nl << nl << "Sub-Expressions:" << nl;
+ isFirst = false;
+ }
+ else { Out << nl; }
+
+ Out << " (" << (void*) I.getKey() << ") ";
+ LangOptions LO; // FIXME.
+ I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
+ Out << " : " << I.getData();
+ }
+
+ // Print block-expression bindings.
+ isFirst = true;
+
+ for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
+ if (!C.isBlkExpr(I.getKey()))
+ continue;
+
+ if (isFirst) {
+ Out << nl << nl << "Block-level Expressions:" << nl;
+ isFirst = false;
+ }
+ else { Out << nl; }
+
+ Out << " (" << (void*) I.getKey() << ") ";
+ LangOptions LO; // FIXME.
+ I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
+ Out << " : " << I.getData();
+ }
+
+ // Print locations.
+ isFirst = true;
+
+ for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
+ if (!IsEnvLoc(I.getKey()))
+ continue;
+
+ if (isFirst) {
+ Out << nl << nl << "Load/store locations:" << nl;
+ isFirst = false;
+ }
+ else { Out << nl; }
+
+ const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
+
+ Out << " (" << (void*) S << ") ";
+ LangOptions LO; // FIXME.
+ S->printPretty(Out, 0, PrintingPolicy(LO));
+ Out << " : " << I.getData();
+ }
+
+ Mgr.getConstraintManager().print(this, Out, nl, sep);
+
+ // Print checker-specific data.
+ for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
+ E = Mgr.Printers.end(); I != E; ++I) {
+ (*I)->Print(Out, this, nl, sep);
+ }
+}
+
+void GRState::printDOT(llvm::raw_ostream& Out, CFG &C) const {
+ print(Out, C, "\\l", "\\|");
+}
+
+void GRState::printStdErr(CFG &C) const {
+ print(llvm::errs(), C);
+}
+
+//===----------------------------------------------------------------------===//
+// Generic Data Map.
+//===----------------------------------------------------------------------===//
+
+void* const* GRState::FindGDM(void* K) const {
+ return GDM.lookup(K);
+}
+
+void*
+GRStateManager::FindGDMContext(void* K,
+ void* (*CreateContext)(llvm::BumpPtrAllocator&),
+ void (*DeleteContext)(void*)) {
+
+ std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
+ if (!p.first) {
+ p.first = CreateContext(Alloc);
+ p.second = DeleteContext;
+ }
+
+ return p.first;
+}
+
+const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
+ GRState::GenericDataMap M1 = St->getGDM();
+ GRState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
+
+ if (M1 == M2)
+ return St;
+
+ GRState NewSt = *St;
+ NewSt.GDM = M2;
+ return getPersistentState(NewSt);
+}
+
+const GRState *GRStateManager::removeGDM(const GRState *state, void *Key) {
+ GRState::GenericDataMap OldM = state->getGDM();
+ GRState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
+
+ if (NewM == OldM)
+ return state;
+
+ GRState NewState = *state;
+ NewState.GDM = NewM;
+ return getPersistentState(NewState);
+}
+
+//===----------------------------------------------------------------------===//
+// Utility.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class ScanReachableSymbols : public SubRegionMap::Visitor {
+ typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
+
+ VisitedRegionsTy visited;
+ const GRState *state;
+ SymbolVisitor &visitor;
+ llvm::OwningPtr<SubRegionMap> SRM;
+public:
+
+ ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
+ : state(st), visitor(v) {}
+
+ bool scan(nonloc::CompoundVal val);
+ bool scan(SVal val);
+ bool scan(const MemRegion *R);
+
+ // From SubRegionMap::Visitor.
+ bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) {
+ return scan(SubRegion);
+ }
+};
+}
+
+bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
+ for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
+ if (!scan(*I))
+ return false;
+
+ return true;
+}
+
+bool ScanReachableSymbols::scan(SVal val) {
+ if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
+ return scan(X->getRegion());
+
+ if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val))
+ return scan(X->getLoc());
+
+ if (SymbolRef Sym = val.getAsSymbol())
+ return visitor.VisitSymbol(Sym);
+
+ if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
+ return scan(*X);
+
+ return true;
+}
+
+bool ScanReachableSymbols::scan(const MemRegion *R) {
+ if (isa<MemSpaceRegion>(R) || visited.count(R))
+ return true;
+
+ visited.insert(R);
+
+ // If this is a symbolic region, visit the symbol for the region.
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ if (!visitor.VisitSymbol(SR->getSymbol()))
+ return false;
+
+ // If this is a subregion, also visit the parent regions.
+ if (const SubRegion *SR = dyn_cast<SubRegion>(R))
+ if (!scan(SR->getSuperRegion()))
+ return false;
+
+ // Now look at the binding to this region (if any).
+ if (!scan(state->getSValAsScalarOrLoc(R)))
+ return false;
+
+ // Now look at the subregions.
+ if (!SRM.get())
+ SRM.reset(state->getStateManager().getStoreManager().
+ getSubRegionMap(state->getStore()));
+
+ return SRM->iterSubRegions(R, *this);
+}
+
+bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
+ ScanReachableSymbols S(this, visitor);
+ return S.scan(val);
+}
+
+bool GRState::scanReachableSymbols(const SVal *I, const SVal *E,
+ SymbolVisitor &visitor) const {
+ ScanReachableSymbols S(this, visitor);
+ for ( ; I != E; ++I) {
+ if (!S.scan(*I))
+ return false;
+ }
+ return true;
+}
+
+bool GRState::scanReachableSymbols(const MemRegion * const *I,
+ const MemRegion * const *E,
+ SymbolVisitor &visitor) const {
+ ScanReachableSymbols S(this, visitor);
+ for ( ; I != E; ++I) {
+ if (!S.scan(*I))
+ return false;
+ }
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
new file mode 100644
index 0000000..1ebc28c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -0,0 +1,581 @@
+//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- 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 HTMLDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Rewrite/HTMLRewrite.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Boilerplate.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class HTMLDiagnostics : public PathDiagnosticClient {
+ llvm::sys::Path Directory, FilePrefix;
+ bool createdDir, noDir;
+ const Preprocessor &PP;
+ std::vector<const PathDiagnostic*> BatchedDiags;
+public:
+ HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
+
+ virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
+
+ virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+
+ virtual void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "HTMLDiagnostics";
+ }
+
+ unsigned ProcessMacroPiece(llvm::raw_ostream& os,
+ const PathDiagnosticMacroPiece& P,
+ unsigned num);
+
+ void HandlePiece(Rewriter& R, FileID BugFileID,
+ const PathDiagnosticPiece& P, unsigned num, unsigned max);
+
+ void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
+ const char *HighlightStart = "<span class=\"mrange\">",
+ const char *HighlightEnd = "</span>");
+
+ void ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade);
+};
+
+} // end anonymous namespace
+
+HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
+ const Preprocessor &pp)
+ : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
+ PP(pp) {
+ // All html files begin with "report"
+ FilePrefix.appendComponent("report");
+}
+
+PathDiagnosticClient*
+ento::createHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
+ return new HTMLDiagnostics(prefix, PP);
+}
+
+//===----------------------------------------------------------------------===//
+// Report processing.
+//===----------------------------------------------------------------------===//
+
+void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+ if (!D)
+ return;
+
+ if (D->empty()) {
+ delete D;
+ return;
+ }
+
+ const_cast<PathDiagnostic*>(D)->flattenLocations();
+ BatchedDiags.push_back(D);
+}
+
+void
+HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
+{
+ while (!BatchedDiags.empty()) {
+ const PathDiagnostic* D = BatchedDiags.back();
+ BatchedDiags.pop_back();
+ ReportDiag(*D, FilesMade);
+ delete D;
+ }
+
+ BatchedDiags.clear();
+}
+
+void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
+ llvm::SmallVectorImpl<std::string> *FilesMade){
+ // Create the HTML directory if it is missing.
+ if (!createdDir) {
+ createdDir = true;
+ std::string ErrorMsg;
+ Directory.createDirectoryOnDisk(true, &ErrorMsg);
+
+ bool IsDirectory;
+ if (llvm::sys::fs::is_directory(Directory.str(), IsDirectory) ||
+ !IsDirectory) {
+ llvm::errs() << "warning: could not create directory '"
+ << Directory.str() << "'\n"
+ << "reason: " << ErrorMsg << '\n';
+
+ noDir = true;
+
+ return;
+ }
+ }
+
+ if (noDir)
+ return;
+
+ const SourceManager &SMgr = D.begin()->getLocation().getManager();
+ FileID FID;
+
+ // Verify that the entire path is from the same FileID.
+ for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) {
+ FullSourceLoc L = I->getLocation().asLocation().getInstantiationLoc();
+
+ if (FID.isInvalid()) {
+ FID = SMgr.getFileID(L);
+ } else if (SMgr.getFileID(L) != FID)
+ return; // FIXME: Emit a warning?
+
+ // Check the source ranges.
+ for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
+ RE=I->ranges_end(); RI!=RE; ++RI) {
+
+ SourceLocation L = SMgr.getInstantiationLoc(RI->getBegin());
+
+ if (!L.isFileID() || SMgr.getFileID(L) != FID)
+ return; // FIXME: Emit a warning?
+
+ L = SMgr.getInstantiationLoc(RI->getEnd());
+
+ if (!L.isFileID() || SMgr.getFileID(L) != FID)
+ return; // FIXME: Emit a warning?
+ }
+ }
+
+ if (FID.isInvalid())
+ return; // FIXME: Emit a warning?
+
+ // Create a new rewriter to generate HTML.
+ Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
+
+ // Process the path.
+ unsigned n = D.size();
+ unsigned max = n;
+
+ for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
+ I!=E; ++I, --n)
+ HandlePiece(R, FID, *I, n, max);
+
+ // Add line numbers, header, footer, etc.
+
+ // unsigned FID = R.getSourceMgr().getMainFileID();
+ html::EscapeText(R, FID);
+ html::AddLineNumbers(R, FID);
+
+ // If we have a preprocessor, relex the file and syntax highlight.
+ // We might not have a preprocessor if we come from a deserialized AST file,
+ // for example.
+
+ html::SyntaxHighlight(R, FID, PP);
+ html::HighlightMacros(R, FID, PP);
+
+ // Get the full directory name of the analyzed file.
+
+ const FileEntry* Entry = SMgr.getFileEntryForID(FID);
+
+ // This is a cludge; basically we want to append either the full
+ // working directory if we have no directory information. This is
+ // a work in progress.
+
+ std::string DirName = "";
+
+ if (llvm::sys::path::is_relative(Entry->getName())) {
+ llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
+ DirName = P.str() + "/";
+ }
+
+ // Add the name of the file as an <h1> tag.
+
+ {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+
+ os << "<!-- REPORTHEADER -->\n"
+ << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
+ "<tr><td class=\"rowname\">File:</td><td>"
+ << html::EscapeText(DirName)
+ << html::EscapeText(Entry->getName())
+ << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
+ "<a href=\"#EndPath\">line "
+ << (*D.rbegin()).getLocation().asLocation().getInstantiationLineNumber()
+ << ", column "
+ << (*D.rbegin()).getLocation().asLocation().getInstantiationColumnNumber()
+ << "</a></td></tr>\n"
+ "<tr><td class=\"rowname\">Description:</td><td>"
+ << D.getDescription() << "</td></tr>\n";
+
+ // Output any other meta data.
+
+ for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
+ I!=E; ++I) {
+ os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
+ }
+
+ os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
+ "<h3>Annotated Source Code</h3>\n";
+
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
+ }
+
+ // Embed meta-data tags.
+ {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+
+ const std::string& BugDesc = D.getDescription();
+ if (!BugDesc.empty())
+ os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
+
+ const std::string& BugType = D.getBugType();
+ if (!BugType.empty())
+ os << "\n<!-- BUGTYPE " << BugType << " -->\n";
+
+ const std::string& BugCategory = D.getCategory();
+ if (!BugCategory.empty())
+ os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
+
+ os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
+
+ os << "\n<!-- BUGLINE "
+ << D.back()->getLocation().asLocation().getInstantiationLineNumber()
+ << " -->\n";
+
+ os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
+
+ // Mark the end of the tags.
+ os << "\n<!-- BUGMETAEND -->\n";
+
+ // Insert the text.
+ R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
+ }
+
+ // Add CSS, header, and footer.
+
+ html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
+
+ // Get the rewrite buffer.
+ const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
+
+ if (!Buf) {
+ llvm::errs() << "warning: no diagnostics generated for main file.\n";
+ return;
+ }
+
+ // Create a path for the target HTML file.
+ llvm::sys::Path F(FilePrefix);
+ F.makeUnique(false, NULL);
+
+ // Rename the file with an HTML extension.
+ llvm::sys::Path H(F);
+ H.appendSuffix("html");
+ F.renamePathOnDisk(H, NULL);
+
+ std::string ErrorMsg;
+ llvm::raw_fd_ostream os(H.c_str(), ErrorMsg);
+
+ if (!ErrorMsg.empty()) {
+ llvm::errs() << "warning: could not create file '" << F.str()
+ << "'\n";
+ return;
+ }
+
+ if (FilesMade)
+ FilesMade->push_back(llvm::sys::path::filename(H.str()));
+
+ // Emit the HTML to disk.
+ for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
+ os << *I;
+}
+
+void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
+ const PathDiagnosticPiece& P,
+ unsigned num, unsigned max) {
+
+ // For now, just draw a box above the line in question, and emit the
+ // warning.
+ FullSourceLoc Pos = P.getLocation().asLocation();
+
+ if (!Pos.isValid())
+ return;
+
+ SourceManager &SM = R.getSourceMgr();
+ assert(&Pos.getManager() == &SM && "SourceManagers are different!");
+ std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedInstantiationLoc(Pos);
+
+ if (LPosInfo.first != BugFileID)
+ return;
+
+ const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
+ const char* FileStart = Buf->getBufferStart();
+
+ // Compute the column number. Rewind from the current position to the start
+ // of the line.
+ unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
+ const char *TokInstantiationPtr =Pos.getInstantiationLoc().getCharacterData();
+ const char *LineStart = TokInstantiationPtr-ColNo;
+
+ // Compute LineEnd.
+ const char *LineEnd = TokInstantiationPtr;
+ const char* FileEnd = Buf->getBufferEnd();
+ while (*LineEnd != '\n' && LineEnd != FileEnd)
+ ++LineEnd;
+
+ // Compute the margin offset by counting tabs and non-tabs.
+ unsigned PosNo = 0;
+ for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
+ PosNo += *c == '\t' ? 8 : 1;
+
+ // Create the html for the message.
+
+ const char *Kind = 0;
+ switch (P.getKind()) {
+ case PathDiagnosticPiece::Event: Kind = "Event"; break;
+ case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
+ // Setting Kind to "Control" is intentional.
+ case PathDiagnosticPiece::Macro: Kind = "Control"; break;
+ }
+
+ std::string sbuf;
+ llvm::raw_string_ostream os(sbuf);
+
+ os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
+
+ if (num == max)
+ os << "EndPath";
+ else
+ os << "Path" << num;
+
+ os << "\" class=\"msg";
+ if (Kind)
+ os << " msg" << Kind;
+ os << "\" style=\"margin-left:" << PosNo << "ex";
+
+ // Output a maximum size.
+ if (!isa<PathDiagnosticMacroPiece>(P)) {
+ // Get the string and determining its maximum substring.
+ const std::string& Msg = P.getString();
+ unsigned max_token = 0;
+ unsigned cnt = 0;
+ unsigned len = Msg.size();
+
+ for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
+ switch (*I) {
+ default:
+ ++cnt;
+ continue;
+ case ' ':
+ case '\t':
+ case '\n':
+ if (cnt > max_token) max_token = cnt;
+ cnt = 0;
+ }
+
+ if (cnt > max_token)
+ max_token = cnt;
+
+ // Determine the approximate size of the message bubble in em.
+ unsigned em;
+ const unsigned max_line = 120;
+
+ if (max_token >= max_line)
+ em = max_token / 2;
+ else {
+ unsigned characters = max_line;
+ unsigned lines = len / max_line;
+
+ if (lines > 0) {
+ for (; characters > max_token; --characters)
+ if (len / characters > lines) {
+ ++characters;
+ break;
+ }
+ }
+
+ em = characters / 2;
+ }
+
+ if (em < max_line/2)
+ os << "; max-width:" << em << "em";
+ }
+ else
+ os << "; max-width:100em";
+
+ os << "\">";
+
+ if (max > 1) {
+ os << "<table class=\"msgT\"><tr><td valign=\"top\">";
+ os << "<div class=\"PathIndex";
+ if (Kind) os << " PathIndex" << Kind;
+ os << "\">" << num << "</div>";
+ os << "</td><td>";
+ }
+
+ if (const PathDiagnosticMacroPiece *MP =
+ dyn_cast<PathDiagnosticMacroPiece>(&P)) {
+
+ os << "Within the expansion of the macro '";
+
+ // Get the name of the macro by relexing it.
+ {
+ FullSourceLoc L = MP->getLocation().asLocation().getInstantiationLoc();
+ assert(L.isFileID());
+ llvm::StringRef BufferInfo = L.getBufferData();
+ const char* MacroName = L.getDecomposedLoc().second + BufferInfo.data();
+ Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.begin(),
+ MacroName, BufferInfo.end());
+
+ Token TheTok;
+ rawLexer.LexFromRawLexer(TheTok);
+ for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
+ os << MacroName[i];
+ }
+
+ os << "':\n";
+
+ if (max > 1)
+ os << "</td></tr></table>";
+
+ // Within a macro piece. Write out each event.
+ ProcessMacroPiece(os, *MP, 0);
+ }
+ else {
+ os << html::EscapeText(P.getString());
+
+ if (max > 1)
+ os << "</td></tr></table>";
+ }
+
+ os << "</div></td></tr>";
+
+ // Insert the new html.
+ unsigned DisplayPos = LineEnd - FileStart;
+ SourceLocation Loc =
+ SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos);
+
+ R.InsertTextBefore(Loc, os.str());
+
+ // Now highlight the ranges.
+ for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
+ I != E; ++I)
+ HighlightRange(R, LPosInfo.first, *I);
+
+#if 0
+ // If there is a code insertion hint, insert that code.
+ // FIXME: This code is disabled because it seems to mangle the HTML
+ // output. I'm leaving it here because it's generally the right idea,
+ // but needs some help from someone more familiar with the rewriter.
+ for (const FixItHint *Hint = P.fixit_begin(), *HintEnd = P.fixit_end();
+ Hint != HintEnd; ++Hint) {
+ if (Hint->RemoveRange.isValid()) {
+ HighlightRange(R, LPosInfo.first, Hint->RemoveRange,
+ "<span class=\"CodeRemovalHint\">", "</span>");
+ }
+ if (Hint->InsertionLoc.isValid()) {
+ std::string EscapedCode = html::EscapeText(Hint->CodeToInsert, true);
+ EscapedCode = "<span class=\"CodeInsertionHint\">" + EscapedCode
+ + "</span>";
+ R.InsertTextBefore(Hint->InsertionLoc, EscapedCode);
+ }
+ }
+#endif
+}
+
+static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) {
+ unsigned x = n % ('z' - 'a');
+ n /= 'z' - 'a';
+
+ if (n > 0)
+ EmitAlphaCounter(os, n);
+
+ os << char('a' + x);
+}
+
+unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os,
+ const PathDiagnosticMacroPiece& P,
+ unsigned num) {
+
+ for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
+ I!=E; ++I) {
+
+ if (const PathDiagnosticMacroPiece *MP =
+ dyn_cast<PathDiagnosticMacroPiece>(*I)) {
+ num = ProcessMacroPiece(os, *MP, num);
+ continue;
+ }
+
+ if (PathDiagnosticEventPiece *EP = dyn_cast<PathDiagnosticEventPiece>(*I)) {
+ os << "<div class=\"msg msgEvent\" style=\"width:94%; "
+ "margin-left:5px\">"
+ "<table class=\"msgT\"><tr>"
+ "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">";
+ EmitAlphaCounter(os, num++);
+ os << "</div></td><td valign=\"top\">"
+ << html::EscapeText(EP->getString())
+ << "</td></tr></table></div>\n";
+ }
+ }
+
+ return num;
+}
+
+void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
+ SourceRange Range,
+ const char *HighlightStart,
+ const char *HighlightEnd) {
+ SourceManager &SM = R.getSourceMgr();
+ const LangOptions &LangOpts = R.getLangOpts();
+
+ SourceLocation InstantiationStart = SM.getInstantiationLoc(Range.getBegin());
+ unsigned StartLineNo = SM.getInstantiationLineNumber(InstantiationStart);
+
+ SourceLocation InstantiationEnd = SM.getInstantiationLoc(Range.getEnd());
+ unsigned EndLineNo = SM.getInstantiationLineNumber(InstantiationEnd);
+
+ if (EndLineNo < StartLineNo)
+ return;
+
+ if (SM.getFileID(InstantiationStart) != BugFileID ||
+ SM.getFileID(InstantiationEnd) != BugFileID)
+ return;
+
+ // Compute the column number of the end.
+ unsigned EndColNo = SM.getInstantiationColumnNumber(InstantiationEnd);
+ unsigned OldEndColNo = EndColNo;
+
+ if (EndColNo) {
+ // Add in the length of the token, so that we cover multi-char tokens.
+ EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
+ }
+
+ // Highlight the range. Make the span tag the outermost tag for the
+ // selected range.
+
+ SourceLocation E =
+ InstantiationEnd.getFileLocWithOffset(EndColNo - OldEndColNo);
+
+ html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Makefile b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Makefile
new file mode 100644
index 0000000..4aebc16
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Makefile
@@ -0,0 +1,17 @@
+##===- clang/lib/StaticAnalyzer/Core/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This implements analyses built on top of source-level CFGs.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../..
+LIBRARYNAME := clangStaticAnalyzerCore
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
new file mode 100644
index 0000000..d9e884a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -0,0 +1,988 @@
+//== MemRegion.cpp - Abstract memory regions for static analysis --*- 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 MemRegion and its subclasses. MemRegion defines a
+// partially-typed abstraction of memory useful for path-sensitive dataflow
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/RecordLayout.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// MemRegion Construction.
+//===----------------------------------------------------------------------===//
+
+template<typename RegionTy> struct MemRegionManagerTrait;
+
+template <typename RegionTy, typename A1>
+RegionTy* MemRegionManager::getRegion(const A1 a1) {
+
+ const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
+ MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1>
+RegionTy* MemRegionManager::getSubRegion(const A1 a1,
+ const MemRegion *superRegion) {
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1, typename A2>
+RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
+
+ const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
+ MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, a2, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, a2, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1, typename A2>
+RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
+ const MemRegion *superRegion) {
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, a2, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, a2, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1, typename A2, typename A3>
+RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3,
+ const MemRegion *superRegion) {
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, a2, a3, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+//===----------------------------------------------------------------------===//
+// Object destruction.
+//===----------------------------------------------------------------------===//
+
+MemRegion::~MemRegion() {}
+
+MemRegionManager::~MemRegionManager() {
+ // All regions and their data are BumpPtrAllocated. No need to call
+ // their destructors.
+}
+
+//===----------------------------------------------------------------------===//
+// Basic methods.
+//===----------------------------------------------------------------------===//
+
+bool SubRegion::isSubRegionOf(const MemRegion* R) const {
+ const MemRegion* r = getSuperRegion();
+ while (r != 0) {
+ if (r == R)
+ return true;
+ if (const SubRegion* sr = dyn_cast<SubRegion>(r))
+ r = sr->getSuperRegion();
+ else
+ break;
+ }
+ return false;
+}
+
+MemRegionManager* SubRegion::getMemRegionManager() const {
+ const SubRegion* r = this;
+ do {
+ const MemRegion *superRegion = r->getSuperRegion();
+ if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
+ r = sr;
+ continue;
+ }
+ return superRegion->getMemRegionManager();
+ } while (1);
+}
+
+const StackFrameContext *VarRegion::getStackFrame() const {
+ const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
+ return SSR ? SSR->getStackFrame() : NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Region extents.
+//===----------------------------------------------------------------------===//
+
+DefinedOrUnknownSVal DeclRegion::getExtent(SValBuilder &svalBuilder) const {
+ ASTContext& Ctx = svalBuilder.getContext();
+ QualType T = getDesugaredValueType(Ctx);
+
+ if (isa<VariableArrayType>(T))
+ return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
+ if (isa<IncompleteArrayType>(T))
+ return UnknownVal();
+
+ CharUnits size = Ctx.getTypeSizeInChars(T);
+ QualType sizeTy = svalBuilder.getArrayIndexType();
+ return svalBuilder.makeIntVal(size.getQuantity(), sizeTy);
+}
+
+DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const {
+ DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder);
+
+ // A zero-length array at the end of a struct often stands for dynamically-
+ // allocated extra memory.
+ if (Extent.isZeroConstant()) {
+ QualType T = getDesugaredValueType(svalBuilder.getContext());
+
+ if (isa<ConstantArrayType>(T))
+ return UnknownVal();
+ }
+
+ return Extent;
+}
+
+DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const {
+ return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
+}
+
+DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const {
+ return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
+}
+
+DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const {
+ return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1,
+ svalBuilder.getArrayIndexType());
+}
+
+QualType CXXBaseObjectRegion::getValueType() const {
+ return QualType(decl->getTypeForDecl(), 0);
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSet profiling.
+//===----------------------------------------------------------------------===//
+
+void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned)getKind());
+}
+
+void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger((unsigned)getKind());
+ ID.AddPointer(getStackFrame());
+}
+
+void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger((unsigned)getKind());
+ ID.AddPointer(getCodeRegion());
+}
+
+void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const StringLiteral* Str,
+ const MemRegion* superRegion) {
+ ID.AddInteger((unsigned) StringRegionKind);
+ ID.AddPointer(Str);
+ ID.AddPointer(superRegion);
+}
+
+void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const Expr* Ex, unsigned cnt,
+ const MemRegion *) {
+ ID.AddInteger((unsigned) AllocaRegionKind);
+ ID.AddPointer(Ex);
+ ID.AddInteger(cnt);
+}
+
+void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ ProfileRegion(ID, Ex, Cnt, superRegion);
+}
+
+void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
+}
+
+void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const CompoundLiteralExpr* CL,
+ const MemRegion* superRegion) {
+ ID.AddInteger((unsigned) CompoundLiteralRegionKind);
+ ID.AddPointer(CL);
+ ID.AddPointer(superRegion);
+}
+
+void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sRegion) {
+ ID.AddInteger((unsigned) CXXThisRegionKind);
+ ID.AddPointer(PT);
+ ID.AddPointer(sRegion);
+}
+
+void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
+}
+
+void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
+ const MemRegion* superRegion, Kind k) {
+ ID.AddInteger((unsigned) k);
+ ID.AddPointer(D);
+ ID.AddPointer(superRegion);
+}
+
+void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
+}
+
+void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ VarRegion::ProfileRegion(ID, getDecl(), superRegion);
+}
+
+void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
+ const MemRegion *sreg) {
+ ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
+ ID.Add(sym);
+ ID.AddPointer(sreg);
+}
+
+void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
+}
+
+void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ QualType ElementType, SVal Idx,
+ const MemRegion* superRegion) {
+ ID.AddInteger(MemRegion::ElementRegionKind);
+ ID.Add(ElementType);
+ ID.AddPointer(superRegion);
+ Idx.Profile(ID);
+}
+
+void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
+}
+
+void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const FunctionDecl *FD,
+ const MemRegion*) {
+ ID.AddInteger(MemRegion::FunctionTextRegionKind);
+ ID.AddPointer(FD);
+}
+
+void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ FunctionTextRegion::ProfileRegion(ID, FD, superRegion);
+}
+
+void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const BlockDecl *BD, CanQualType,
+ const AnalysisContext *AC,
+ const MemRegion*) {
+ ID.AddInteger(MemRegion::BlockTextRegionKind);
+ ID.AddPointer(BD);
+}
+
+void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
+}
+
+void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const BlockTextRegion *BC,
+ const LocationContext *LC,
+ const MemRegion *sReg) {
+ ID.AddInteger(MemRegion::BlockDataRegionKind);
+ ID.AddPointer(BC);
+ ID.AddPointer(LC);
+ ID.AddPointer(sReg);
+}
+
+void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion());
+}
+
+void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ Expr const *Ex,
+ const MemRegion *sReg) {
+ ID.AddPointer(Ex);
+ ID.AddPointer(sReg);
+}
+
+void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ ProfileRegion(ID, Ex, getSuperRegion());
+}
+
+void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const CXXRecordDecl *decl,
+ const MemRegion *sReg) {
+ ID.AddPointer(decl);
+ ID.AddPointer(sReg);
+}
+
+void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+ ProfileRegion(ID, decl, superRegion);
+}
+
+//===----------------------------------------------------------------------===//
+// Region pretty-printing.
+//===----------------------------------------------------------------------===//
+
+void MemRegion::dump() const {
+ dumpToStream(llvm::errs());
+}
+
+std::string MemRegion::getString() const {
+ std::string s;
+ llvm::raw_string_ostream os(s);
+ dumpToStream(os);
+ return os.str();
+}
+
+void MemRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "<Unknown Region>";
+}
+
+void AllocaRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
+}
+
+void FunctionTextRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "code{" << getDecl()->getDeclName().getAsString() << '}';
+}
+
+void BlockTextRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "block_code{" << (void*) this << '}';
+}
+
+void BlockDataRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "block_data{" << BC << '}';
+}
+
+void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const {
+ // FIXME: More elaborate pretty-printing.
+ os << "{ " << (void*) CL << " }";
+}
+
+void CXXTempObjectRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "temp_object";
+}
+
+void CXXBaseObjectRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "base " << decl->getName();
+}
+
+void CXXThisRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "this";
+}
+
+void ElementRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "element{" << superRegion << ','
+ << Index << ',' << getElementType().getAsString() << '}';
+}
+
+void FieldRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << superRegion << "->" << getDecl();
+}
+
+void NonStaticGlobalSpaceRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "NonStaticGlobalSpaceRegion";
+}
+
+void ObjCIvarRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "ivar{" << superRegion << ',' << getDecl() << '}';
+}
+
+void StringRegion::dumpToStream(llvm::raw_ostream& os) const {
+ Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions()));
+}
+
+void SymbolicRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "SymRegion{" << sym << '}';
+}
+
+void VarRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << cast<VarDecl>(D);
+}
+
+void RegionRawOffset::dump() const {
+ dumpToStream(llvm::errs());
+}
+
+void RegionRawOffset::dumpToStream(llvm::raw_ostream& os) const {
+ os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
+}
+
+void StaticGlobalSpaceRegion::dumpToStream(llvm::raw_ostream &os) const {
+ os << "StaticGlobalsMemSpace{" << CR << '}';
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager methods.
+//===----------------------------------------------------------------------===//
+
+template <typename REG>
+const REG *MemRegionManager::LazyAllocate(REG*& region) {
+ if (!region) {
+ region = (REG*) A.Allocate<REG>();
+ new (region) REG(this);
+ }
+
+ return region;
+}
+
+template <typename REG, typename ARG>
+const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
+ if (!region) {
+ region = (REG*) A.Allocate<REG>();
+ new (region) REG(this, a);
+ }
+
+ return region;
+}
+
+const StackLocalsSpaceRegion*
+MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
+ assert(STC);
+ StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
+
+ if (R)
+ return R;
+
+ R = A.Allocate<StackLocalsSpaceRegion>();
+ new (R) StackLocalsSpaceRegion(this, STC);
+ return R;
+}
+
+const StackArgumentsSpaceRegion *
+MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
+ assert(STC);
+ StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
+
+ if (R)
+ return R;
+
+ R = A.Allocate<StackArgumentsSpaceRegion>();
+ new (R) StackArgumentsSpaceRegion(this, STC);
+ return R;
+}
+
+const GlobalsSpaceRegion
+*MemRegionManager::getGlobalsRegion(const CodeTextRegion *CR) {
+ if (!CR)
+ return LazyAllocate(globals);
+
+ StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
+ if (R)
+ return R;
+
+ R = A.Allocate<StaticGlobalSpaceRegion>();
+ new (R) StaticGlobalSpaceRegion(this, CR);
+ return R;
+}
+
+const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
+ return LazyAllocate(heap);
+}
+
+const MemSpaceRegion *MemRegionManager::getUnknownRegion() {
+ return LazyAllocate(unknown);
+}
+
+const MemSpaceRegion *MemRegionManager::getCodeRegion() {
+ return LazyAllocate(code);
+}
+
+//===----------------------------------------------------------------------===//
+// Constructing regions.
+//===----------------------------------------------------------------------===//
+
+const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){
+ return getSubRegion<StringRegion>(Str, getGlobalsRegion());
+}
+
+const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
+ const LocationContext *LC) {
+ const MemRegion *sReg = 0;
+
+ if (D->hasGlobalStorage() && !D->isStaticLocal())
+ sReg = getGlobalsRegion();
+ else {
+ // FIXME: Once we implement scope handling, we will need to properly lookup
+ // 'D' to the proper LocationContext.
+ const DeclContext *DC = D->getDeclContext();
+ const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
+
+ if (!STC)
+ sReg = getUnknownRegion();
+ else {
+ if (D->hasLocalStorage()) {
+ sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
+ ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
+ : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
+ }
+ else {
+ assert(D->isStaticLocal());
+ const Decl *D = STC->getDecl();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ sReg = getGlobalsRegion(getFunctionTextRegion(FD));
+ else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ const BlockTextRegion *BTR =
+ getBlockTextRegion(BD,
+ C.getCanonicalType(BD->getSignatureAsWritten()->getType()),
+ STC->getAnalysisContext());
+ sReg = getGlobalsRegion(BTR);
+ }
+ else {
+ // FIXME: For ObjC-methods, we need a new CodeTextRegion. For now
+ // just use the main global memspace.
+ sReg = getGlobalsRegion();
+ }
+ }
+ }
+ }
+
+ return getSubRegion<VarRegion>(D, sReg);
+}
+
+const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
+ const MemRegion *superR) {
+ return getSubRegion<VarRegion>(D, superR);
+}
+
+const BlockDataRegion *
+MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
+ const LocationContext *LC) {
+ const MemRegion *sReg = 0;
+
+ if (LC) {
+ // FIXME: Once we implement scope handling, we want the parent region
+ // to be the scope.
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ sReg = getStackLocalsRegion(STC);
+ }
+ else {
+ // We allow 'LC' to be NULL for cases where want BlockDataRegions
+ // without context-sensitivity.
+ sReg = getUnknownRegion();
+ }
+
+ return getSubRegion<BlockDataRegion>(BC, LC, sReg);
+}
+
+const CompoundLiteralRegion*
+MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
+ const LocationContext *LC) {
+
+ const MemRegion *sReg = 0;
+
+ if (CL->isFileScope())
+ sReg = getGlobalsRegion();
+ else {
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ sReg = getStackLocalsRegion(STC);
+ }
+
+ return getSubRegion<CompoundLiteralRegion>(CL, sReg);
+}
+
+const ElementRegion*
+MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
+ const MemRegion* superRegion,
+ ASTContext& Ctx){
+
+ QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
+
+ llvm::FoldingSetNodeID ID;
+ ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
+
+ void* InsertPos;
+ MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+ ElementRegion* R = cast_or_null<ElementRegion>(data);
+
+ if (!R) {
+ R = (ElementRegion*) A.Allocate<ElementRegion>();
+ new (R) ElementRegion(T, Idx, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+const FunctionTextRegion *
+MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
+ return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
+}
+
+const BlockTextRegion *
+MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy,
+ AnalysisContext *AC) {
+ return getSubRegion<BlockTextRegion>(BD, locTy, AC, getCodeRegion());
+}
+
+
+/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
+ return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
+}
+
+const FieldRegion*
+MemRegionManager::getFieldRegion(const FieldDecl* d,
+ const MemRegion* superRegion){
+ return getSubRegion<FieldRegion>(d, superRegion);
+}
+
+const ObjCIvarRegion*
+MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
+ const MemRegion* superRegion) {
+ return getSubRegion<ObjCIvarRegion>(d, superRegion);
+}
+
+const CXXTempObjectRegion*
+MemRegionManager::getCXXTempObjectRegion(Expr const *E,
+ LocationContext const *LC) {
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ assert(SFC);
+ return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
+}
+
+const CXXBaseObjectRegion *
+MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl,
+ const MemRegion *superRegion) {
+ return getSubRegion<CXXBaseObjectRegion>(decl, superRegion);
+}
+
+const CXXThisRegion*
+MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC) {
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ const PointerType *PT = thisPointerTy->getAs<PointerType>();
+ assert(PT);
+ return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
+}
+
+const AllocaRegion*
+MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt,
+ const LocationContext *LC) {
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
+}
+
+const MemSpaceRegion *MemRegion::getMemorySpace() const {
+ const MemRegion *R = this;
+ const SubRegion* SR = dyn_cast<SubRegion>(this);
+
+ while (SR) {
+ R = SR->getSuperRegion();
+ SR = dyn_cast<SubRegion>(R);
+ }
+
+ return dyn_cast<MemSpaceRegion>(R);
+}
+
+bool MemRegion::hasStackStorage() const {
+ return isa<StackSpaceRegion>(getMemorySpace());
+}
+
+bool MemRegion::hasStackNonParametersStorage() const {
+ return isa<StackLocalsSpaceRegion>(getMemorySpace());
+}
+
+bool MemRegion::hasStackParametersStorage() const {
+ return isa<StackArgumentsSpaceRegion>(getMemorySpace());
+}
+
+bool MemRegion::hasGlobalsOrParametersStorage() const {
+ const MemSpaceRegion *MS = getMemorySpace();
+ return isa<StackArgumentsSpaceRegion>(MS) ||
+ isa<GlobalsSpaceRegion>(MS);
+}
+
+// getBaseRegion strips away all elements and fields, and get the base region
+// of them.
+const MemRegion *MemRegion::getBaseRegion() const {
+ const MemRegion *R = this;
+ while (true) {
+ switch (R->getKind()) {
+ case MemRegion::ElementRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ case MemRegion::CXXBaseObjectRegionKind:
+ R = cast<SubRegion>(R)->getSuperRegion();
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ return R;
+}
+
+//===----------------------------------------------------------------------===//
+// View handling.
+//===----------------------------------------------------------------------===//
+
+const MemRegion *MemRegion::StripCasts() const {
+ const MemRegion *R = this;
+ while (true) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ // FIXME: generalize. Essentially we want to strip away ElementRegions
+ // that were layered on a symbolic region because of casts. We only
+ // want to strip away ElementRegions, however, where the index is 0.
+ SVal index = ER->getIndex();
+ if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
+ if (CI->getValue().getSExtValue() == 0) {
+ R = ER->getSuperRegion();
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ return R;
+}
+
+// FIXME: Merge with the implementation of the same method in Store.cpp
+static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *D = RT->getDecl();
+ if (!D->getDefinition())
+ return false;
+ }
+
+ return true;
+}
+
+RegionRawOffset ElementRegion::getAsArrayOffset() const {
+ CharUnits offset = CharUnits::Zero();
+ const ElementRegion *ER = this;
+ const MemRegion *superR = NULL;
+ ASTContext &C = getContext();
+
+ // FIXME: Handle multi-dimensional arrays.
+
+ while (ER) {
+ superR = ER->getSuperRegion();
+
+ // FIXME: generalize to symbolic offsets.
+ SVal index = ER->getIndex();
+ if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
+ // Update the offset.
+ int64_t i = CI->getValue().getSExtValue();
+
+ if (i != 0) {
+ QualType elemType = ER->getElementType();
+
+ // If we are pointing to an incomplete type, go no further.
+ if (!IsCompleteType(C, elemType)) {
+ superR = ER;
+ break;
+ }
+
+ CharUnits size = C.getTypeSizeInChars(elemType);
+ offset += (i * size);
+ }
+
+ // Go to the next ElementRegion (if any).
+ ER = dyn_cast<ElementRegion>(superR);
+ continue;
+ }
+
+ return NULL;
+ }
+
+ assert(superR && "super region cannot be NULL");
+ return RegionRawOffset(superR, offset);
+}
+
+RegionOffset MemRegion::getAsOffset() const {
+ const MemRegion *R = this;
+ int64_t Offset = 0;
+
+ while (1) {
+ switch (R->getKind()) {
+ default:
+ return RegionOffset(0);
+ case SymbolicRegionKind:
+ case AllocaRegionKind:
+ case CompoundLiteralRegionKind:
+ case CXXThisRegionKind:
+ case StringRegionKind:
+ case VarRegionKind:
+ case CXXTempObjectRegionKind:
+ goto Finish;
+ case ElementRegionKind: {
+ const ElementRegion *ER = cast<ElementRegion>(R);
+ QualType EleTy = ER->getValueType();
+
+ if (!IsCompleteType(getContext(), EleTy))
+ return RegionOffset(0);
+
+ SVal Index = ER->getIndex();
+ if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
+ int64_t i = CI->getValue().getSExtValue();
+ CharUnits Size = getContext().getTypeSizeInChars(EleTy);
+ Offset += i * Size.getQuantity() * 8;
+ } else {
+ // We cannot compute offset for non-concrete index.
+ return RegionOffset(0);
+ }
+ R = ER->getSuperRegion();
+ break;
+ }
+ case FieldRegionKind: {
+ const FieldRegion *FR = cast<FieldRegion>(R);
+ const RecordDecl *RD = FR->getDecl()->getParent();
+ if (!RD->isDefinition())
+ // We cannot compute offset for incomplete type.
+ return RegionOffset(0);
+ // Get the field number.
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator FI = RD->field_begin(),
+ FE = RD->field_end(); FI != FE; ++FI, ++idx)
+ if (FR->getDecl() == *FI)
+ break;
+
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ // This is offset in bits.
+ Offset += Layout.getFieldOffset(idx);
+ R = FR->getSuperRegion();
+ break;
+ }
+ }
+ }
+
+ Finish:
+ return RegionOffset(R, Offset);
+}
+
+//===----------------------------------------------------------------------===//
+// BlockDataRegion
+//===----------------------------------------------------------------------===//
+
+void BlockDataRegion::LazyInitializeReferencedVars() {
+ if (ReferencedVars)
+ return;
+
+ AnalysisContext *AC = getCodeRegion()->getAnalysisContext();
+ AnalysisContext::referenced_decls_iterator I, E;
+ llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
+
+ if (I == E) {
+ ReferencedVars = (void*) 0x1;
+ return;
+ }
+
+ MemRegionManager &MemMgr = *getMemRegionManager();
+ llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
+ BumpVectorContext BC(A);
+
+ typedef BumpVector<const MemRegion*> VarVec;
+ VarVec *BV = (VarVec*) A.Allocate<VarVec>();
+ new (BV) VarVec(BC, E - I);
+
+ for ( ; I != E; ++I) {
+ const VarDecl *VD = *I;
+ const VarRegion *VR = 0;
+
+ if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage())
+ VR = MemMgr.getVarRegion(VD, this);
+ else {
+ if (LC)
+ VR = MemMgr.getVarRegion(VD, LC);
+ else {
+ VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
+ }
+ }
+
+ assert(VR);
+ BV->push_back(VR, BC);
+ }
+
+ ReferencedVars = BV;
+}
+
+BlockDataRegion::referenced_vars_iterator
+BlockDataRegion::referenced_vars_begin() const {
+ const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
+
+ BumpVector<const MemRegion*> *Vec =
+ static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
+
+ return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
+ NULL : Vec->begin());
+}
+
+BlockDataRegion::referenced_vars_iterator
+BlockDataRegion::referenced_vars_end() const {
+ const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
+
+ BumpVector<const MemRegion*> *Vec =
+ static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
+
+ return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
+ NULL : Vec->end());
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
new file mode 100644
index 0000000..2e370d6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
@@ -0,0 +1,99 @@
+//===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- 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 ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+
+using namespace clang;
+using namespace ento;
+
+QualType ObjCMessage::getType(ASTContext &ctx) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getType();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (isPropertySetter())
+ return ctx.VoidTy;
+ return propE->getType();
+}
+
+Selector ObjCMessage::getSelector() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getSelector();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (isPropertySetter())
+ return propE->getSetterSelector();
+ return propE->getGetterSelector();
+}
+
+const ObjCMethodDecl *ObjCMessage::getMethodDecl() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getMethodDecl();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (propE->isImplicitProperty())
+ return isPropertySetter() ? propE->getImplicitPropertySetter()
+ : propE->getImplicitPropertyGetter();
+ return 0;
+}
+
+const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getReceiverInterface();
+ const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+ if (propE->isClassReceiver())
+ return propE->getClassReceiver();
+ QualType recT;
+ if (const Expr *recE = getInstanceReceiver())
+ recT = recE->getType();
+ else {
+ assert(propE->isSuperReceiver());
+ recT = propE->getSuperReceiverType();
+ }
+ if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+ return 0;
+}
+
+const Expr *ObjCMessage::getArgExpr(unsigned i) const {
+ assert(isValid() && "This ObjCMessage is uninitialized!");
+ assert(i < getNumArgs() && "Invalid index for argument");
+ if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+ return msgE->getArg(i);
+ assert(isPropertySetter());
+ if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE))
+ if (bop->isAssignmentOp())
+ return bop->getRHS();
+ return 0;
+}
+
+QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
+ if (CallE) {
+ const Expr *Callee = CallE->getCallee();
+ if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
+ return FD->getResultType();
+ return CallE->getType();
+ }
+ return Msg.getResultType(ctx);
+}
+
+SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const {
+ assert(i < getNumArgs());
+ if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i));
+ QualType argT = Msg.getArgType(i);
+ if (Loc::isLocType(argT) || argT->isIntegerType())
+ return Msg.getArgSVal(i, State);
+ return UnknownVal();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
new file mode 100644
index 0000000..872bbfe
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -0,0 +1,280 @@
+//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- 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 PathDiagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Casting.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::dyn_cast;
+using llvm::isa;
+
+bool PathDiagnosticMacroPiece::containsEvent() const {
+ for (const_iterator I = begin(), E = end(); I!=E; ++I) {
+ if (isa<PathDiagnosticEventPiece>(*I))
+ return true;
+
+ if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
+ if (MP->containsEvent())
+ return true;
+ }
+
+ return false;
+}
+
+static llvm::StringRef StripTrailingDots(llvm::StringRef s) {
+ for (llvm::StringRef::size_type i = s.size(); i != 0; --i)
+ if (s[i - 1] != '.')
+ return s.substr(0, i);
+ return "";
+}
+
+PathDiagnosticPiece::PathDiagnosticPiece(llvm::StringRef s,
+ Kind k, DisplayHint hint)
+ : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
+
+PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
+ : kind(k), Hint(hint) {}
+
+PathDiagnosticPiece::~PathDiagnosticPiece() {}
+PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
+PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
+
+PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {
+ for (iterator I = begin(), E = end(); I != E; ++I) delete *I;
+}
+
+PathDiagnostic::PathDiagnostic() : Size(0) {}
+
+PathDiagnostic::~PathDiagnostic() {
+ for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
+}
+
+void PathDiagnostic::resetPath(bool deletePieces) {
+ Size = 0;
+
+ if (deletePieces)
+ for (iterator I=begin(), E=end(); I!=E; ++I)
+ delete &*I;
+
+ path.clear();
+}
+
+
+PathDiagnostic::PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc,
+ llvm::StringRef category)
+ : Size(0),
+ BugType(StripTrailingDots(bugtype)),
+ Desc(StripTrailingDots(desc)),
+ Category(StripTrailingDots(category)) {}
+
+void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Default implementation (Warnings/errors count).
+ DiagnosticClient::HandleDiagnostic(DiagLevel, Info);
+
+ // Create a PathDiagnostic with a single piece.
+
+ PathDiagnostic* D = new PathDiagnostic();
+
+ const char *LevelStr;
+ switch (DiagLevel) {
+ default:
+ case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
+ case Diagnostic::Note: LevelStr = "note: "; break;
+ case Diagnostic::Warning: LevelStr = "warning: "; break;
+ case Diagnostic::Error: LevelStr = "error: "; break;
+ case Diagnostic::Fatal: LevelStr = "fatal error: "; break;
+ }
+
+ llvm::SmallString<100> StrC;
+ StrC += LevelStr;
+ Info.FormatDiagnostic(StrC);
+
+ PathDiagnosticPiece *P =
+ new PathDiagnosticEventPiece(FullSourceLoc(Info.getLocation(),
+ Info.getSourceManager()),
+ StrC.str());
+
+ for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
+ P->addRange(Info.getRange(i).getAsRange());
+ for (unsigned i = 0, e = Info.getNumFixItHints(); i != e; ++i)
+ P->addFixItHint(Info.getFixItHint(i));
+ D->push_front(P);
+
+ HandlePathDiagnostic(D);
+}
+
+//===----------------------------------------------------------------------===//
+// PathDiagnosticLocation methods.
+//===----------------------------------------------------------------------===//
+
+FullSourceLoc PathDiagnosticLocation::asLocation() const {
+ assert(isValid());
+ // Note that we want a 'switch' here so that the compiler can warn us in
+ // case we add more cases.
+ switch (K) {
+ case SingleLocK:
+ case RangeK:
+ break;
+ case StmtK:
+ return FullSourceLoc(S->getLocStart(), const_cast<SourceManager&>(*SM));
+ case DeclK:
+ return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
+ }
+
+ return FullSourceLoc(R.getBegin(), const_cast<SourceManager&>(*SM));
+}
+
+PathDiagnosticRange PathDiagnosticLocation::asRange() const {
+ assert(isValid());
+ // Note that we want a 'switch' here so that the compiler can warn us in
+ // case we add more cases.
+ switch (K) {
+ case SingleLocK:
+ return PathDiagnosticRange(R, true);
+ case RangeK:
+ break;
+ case StmtK: {
+ const Stmt *S = asStmt();
+ switch (S->getStmtClass()) {
+ default:
+ break;
+ case Stmt::DeclStmtClass: {
+ const DeclStmt *DS = cast<DeclStmt>(S);
+ if (DS->isSingleDecl()) {
+ // Should always be the case, but we'll be defensive.
+ return SourceRange(DS->getLocStart(),
+ DS->getSingleDecl()->getLocation());
+ }
+ break;
+ }
+ // FIXME: Provide better range information for different
+ // terminators.
+ case Stmt::IfStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::ChooseExprClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::SwitchStmtClass:
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::ObjCForCollectionStmtClass: {
+ SourceLocation L = S->getLocStart();
+ return SourceRange(L, L);
+ }
+ }
+
+ return S->getSourceRange();
+ }
+ case DeclK:
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
+ return MD->getSourceRange();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (Stmt *Body = FD->getBody())
+ return Body->getSourceRange();
+ }
+ else {
+ SourceLocation L = D->getLocation();
+ return PathDiagnosticRange(SourceRange(L, L), true);
+ }
+ }
+
+ return R;
+}
+
+void PathDiagnosticLocation::flatten() {
+ if (K == StmtK) {
+ R = asRange();
+ K = RangeK;
+ S = 0;
+ D = 0;
+ }
+ else if (K == DeclK) {
+ SourceLocation L = D->getLocation();
+ R = SourceRange(L, L);
+ K = SingleLocK;
+ S = 0;
+ D = 0;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// FoldingSet profiling methods.
+//===----------------------------------------------------------------------===//
+
+void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger((unsigned) K);
+ switch (K) {
+ case RangeK:
+ ID.AddInteger(R.getBegin().getRawEncoding());
+ ID.AddInteger(R.getEnd().getRawEncoding());
+ break;
+ case SingleLocK:
+ ID.AddInteger(R.getBegin().getRawEncoding());
+ break;
+ case StmtK:
+ ID.Add(S);
+ break;
+ case DeclK:
+ ID.Add(D);
+ break;
+ }
+ return;
+}
+
+void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger((unsigned) getKind());
+ ID.AddString(str);
+ // FIXME: Add profiling support for code hints.
+ ID.AddInteger((unsigned) getDisplayHint());
+ for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) {
+ ID.AddInteger(I->getBegin().getRawEncoding());
+ ID.AddInteger(I->getEnd().getRawEncoding());
+ }
+}
+
+void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
+ PathDiagnosticPiece::Profile(ID);
+ ID.Add(Pos);
+}
+
+void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
+ PathDiagnosticPiece::Profile(ID);
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ ID.Add(*I);
+}
+
+void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
+ PathDiagnosticSpotPiece::Profile(ID);
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ ID.Add(**I);
+}
+
+void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Size);
+ ID.AddString(BugType);
+ ID.AddString(Desc);
+ ID.AddString(Category);
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ ID.Add(*I);
+
+ for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
+ ID.AddString(*I);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
new file mode 100644
index 0000000..fbbbd46
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -0,0 +1,472 @@
+//===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- 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 PlistDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+using namespace ento;
+using llvm::cast;
+
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+namespace clang {
+ class Preprocessor;
+}
+
+namespace {
+struct CompareDiagnostics {
+ // Compare if 'X' is "<" than 'Y'.
+ bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
+ // First compare by location
+ const FullSourceLoc &XLoc = X->getLocation().asLocation();
+ const FullSourceLoc &YLoc = Y->getLocation().asLocation();
+ if (XLoc < YLoc)
+ return true;
+ if (XLoc != YLoc)
+ return false;
+
+ // Next, compare by bug type.
+ llvm::StringRef XBugType = X->getBugType();
+ llvm::StringRef YBugType = Y->getBugType();
+ if (XBugType < YBugType)
+ return true;
+ if (XBugType != YBugType)
+ return false;
+
+ // Next, compare by bug description.
+ llvm::StringRef XDesc = X->getDescription();
+ llvm::StringRef YDesc = Y->getDescription();
+ if (XDesc < YDesc)
+ return true;
+ if (XDesc != YDesc)
+ return false;
+
+ // FIXME: Further refine by comparing PathDiagnosticPieces?
+ return false;
+ }
+};
+}
+
+namespace {
+ class PlistDiagnostics : public PathDiagnosticClient {
+ std::vector<const PathDiagnostic*> BatchedDiags;
+ const std::string OutputFile;
+ const LangOptions &LangOpts;
+ llvm::OwningPtr<PathDiagnosticClient> SubPD;
+ bool flushed;
+ public:
+ PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
+ PathDiagnosticClient *subPD);
+
+ ~PlistDiagnostics() { FlushDiagnostics(NULL); }
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
+
+ void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ virtual llvm::StringRef getName() const {
+ return "PlistDiagnostics";
+ }
+
+ PathGenerationScheme getGenerationScheme() const;
+ bool supportsLogicalOpControlFlow() const { return true; }
+ bool supportsAllBlockEdges() const { return true; }
+ virtual bool useVerboseDescription() const { return false; }
+ };
+} // end anonymous namespace
+
+PlistDiagnostics::PlistDiagnostics(const std::string& output,
+ const LangOptions &LO,
+ PathDiagnosticClient *subPD)
+ : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
+
+PathDiagnosticClient*
+ento::createPlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
+ PathDiagnosticClient *subPD) {
+ return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
+}
+
+PathDiagnosticClient::PathGenerationScheme
+PlistDiagnostics::getGenerationScheme() const {
+ if (const PathDiagnosticClient *PD = SubPD.get())
+ return PD->getGenerationScheme();
+
+ return Extensive;
+}
+
+static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
+ const SourceManager* SM, SourceLocation L) {
+
+ FileID FID = SM->getFileID(SM->getInstantiationLoc(L));
+ FIDMap::iterator I = FIDs.find(FID);
+ if (I != FIDs.end()) return;
+ FIDs[FID] = V.size();
+ V.push_back(FID);
+}
+
+static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
+ SourceLocation L) {
+ FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
+ FIDMap::const_iterator I = FIDs.find(FID);
+ assert(I != FIDs.end());
+ return I->second;
+}
+
+static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i) o << ' ';
+ return o;
+}
+
+static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation L, const FIDMap &FM,
+ unsigned indent, bool extend = false) {
+
+ FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));
+
+ // Add in the length of the token, so that we cover multi-char tokens.
+ unsigned offset =
+ extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
+
+ Indent(o, indent) << "<dict>\n";
+ Indent(o, indent) << " <key>line</key><integer>"
+ << Loc.getInstantiationLineNumber() << "</integer>\n";
+ Indent(o, indent) << " <key>col</key><integer>"
+ << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
+ Indent(o, indent) << " <key>file</key><integer>"
+ << GetFID(FM, SM, Loc) << "</integer>\n";
+ Indent(o, indent) << "</dict>\n";
+}
+
+static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const PathDiagnosticLocation &L, const FIDMap& FM,
+ unsigned indent, bool extend = false) {
+ EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
+}
+
+static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ PathDiagnosticRange R, const FIDMap &FM,
+ unsigned indent) {
+ Indent(o, indent) << "<array>\n";
+ EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
+ EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
+ Indent(o, indent) << "</array>\n";
+}
+
+static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
+ const std::string& s) {
+ o << "<string>";
+ for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
+ char c = *I;
+ switch (c) {
+ default: o << c; break;
+ case '&': o << "&amp;"; break;
+ case '<': o << "&lt;"; break;
+ case '>': o << "&gt;"; break;
+ case '\'': o << "&apos;"; break;
+ case '\"': o << "&quot;"; break;
+ }
+ }
+ o << "</string>";
+ return o;
+}
+
+static void ReportControlFlow(llvm::raw_ostream& o,
+ const PathDiagnosticControlFlowPiece& P,
+ const FIDMap& FM,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ unsigned indent) {
+
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+
+ Indent(o, indent) << "<key>kind</key><string>control</string>\n";
+
+ // Emit edges.
+ Indent(o, indent) << "<key>edges</key>\n";
+ ++indent;
+ Indent(o, indent) << "<array>\n";
+ ++indent;
+ for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
+ I!=E; ++I) {
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+ Indent(o, indent) << "<key>start</key>\n";
+ EmitRange(o, SM, LangOpts, I->getStart().asRange(), FM, indent+1);
+ Indent(o, indent) << "<key>end</key>\n";
+ EmitRange(o, SM, LangOpts, I->getEnd().asRange(), FM, indent+1);
+ --indent;
+ Indent(o, indent) << "</dict>\n";
+ }
+ --indent;
+ Indent(o, indent) << "</array>\n";
+ --indent;
+
+ // Output any helper text.
+ const std::string& s = P.getString();
+ if (!s.empty()) {
+ Indent(o, indent) << "<key>alternate</key>";
+ EmitString(o, s) << '\n';
+ }
+
+ --indent;
+ Indent(o, indent) << "</dict>\n";
+}
+
+static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+ const FIDMap& FM,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ unsigned indent) {
+
+ Indent(o, indent) << "<dict>\n";
+ ++indent;
+
+ Indent(o, indent) << "<key>kind</key><string>event</string>\n";
+
+ // Output the location.
+ FullSourceLoc L = P.getLocation().asLocation();
+
+ Indent(o, indent) << "<key>location</key>\n";
+ EmitLocation(o, SM, LangOpts, L, FM, indent);
+
+ // Output the ranges (if any).
+ PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
+ RE = P.ranges_end();
+
+ if (RI != RE) {
+ Indent(o, indent) << "<key>ranges</key>\n";
+ Indent(o, indent) << "<array>\n";
+ ++indent;
+ for (; RI != RE; ++RI)
+ EmitRange(o, SM, LangOpts, *RI, FM, indent+1);
+ --indent;
+ Indent(o, indent) << "</array>\n";
+ }
+
+ // Output the text.
+ assert(!P.getString().empty());
+ Indent(o, indent) << "<key>extended_message</key>\n";
+ Indent(o, indent);
+ EmitString(o, P.getString()) << '\n';
+
+ // Output the short text.
+ // FIXME: Really use a short string.
+ Indent(o, indent) << "<key>message</key>\n";
+ EmitString(o, P.getString()) << '\n';
+
+ // Finish up.
+ --indent;
+ Indent(o, indent); o << "</dict>\n";
+}
+
+static void ReportMacro(llvm::raw_ostream& o,
+ const PathDiagnosticMacroPiece& P,
+ const FIDMap& FM, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ unsigned indent) {
+
+ for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
+ I!=E; ++I) {
+
+ switch ((*I)->getKind()) {
+ default:
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
+ indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
+ indent);
+ break;
+ }
+ }
+}
+
+static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
+ const FIDMap& FM, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+
+ unsigned indent = 4;
+
+ switch (P.getKind()) {
+ case PathDiagnosticPiece::ControlFlow:
+ ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
+ LangOpts, indent);
+ break;
+ case PathDiagnosticPiece::Event:
+ ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
+ indent);
+ break;
+ case PathDiagnosticPiece::Macro:
+ ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
+ indent);
+ break;
+ }
+}
+
+void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+ if (!D)
+ return;
+
+ if (D->empty()) {
+ delete D;
+ return;
+ }
+
+ // We need to flatten the locations (convert Stmt* to locations) because
+ // the referenced statements may be freed by the time the diagnostics
+ // are emitted.
+ const_cast<PathDiagnostic*>(D)->flattenLocations();
+ BatchedDiags.push_back(D);
+}
+
+void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
+ *FilesMade) {
+
+ if (flushed)
+ return;
+
+ flushed = true;
+
+ // Sort the diagnostics so that they are always emitted in a deterministic
+ // order.
+ if (!BatchedDiags.empty())
+ std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics());
+
+ // Build up a set of FIDs that we use by scanning the locations and
+ // ranges of the diagnostics.
+ FIDMap FM;
+ llvm::SmallVector<FileID, 10> Fids;
+ const SourceManager* SM = 0;
+
+ if (!BatchedDiags.empty())
+ SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager();
+
+ for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(),
+ DE = BatchedDiags.end(); DI != DE; ++DI) {
+
+ const PathDiagnostic *D = *DI;
+
+ for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) {
+ AddFID(FM, Fids, SM, I->getLocation().asLocation());
+
+ for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
+ RE=I->ranges_end(); RI!=RE; ++RI) {
+ AddFID(FM, Fids, SM, RI->getBegin());
+ AddFID(FM, Fids, SM, RI->getEnd());
+ }
+ }
+ }
+
+ // Open the file.
+ std::string ErrMsg;
+ llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
+ if (!ErrMsg.empty()) {
+ llvm::errs() << "warning: could not creat file: " << OutputFile << '\n';
+ return;
+ }
+
+ // Write the plist header.
+ o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ "<plist version=\"1.0\">\n";
+
+ // Write the root object: a <dict> containing...
+ // - "files", an <array> mapping from FIDs to file names
+ // - "diagnostics", an <array> containing the path diagnostics
+ o << "<dict>\n"
+ " <key>files</key>\n"
+ " <array>\n";
+
+ for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
+ I!=E; ++I) {
+ o << " ";
+ EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
+ }
+
+ o << " </array>\n"
+ " <key>diagnostics</key>\n"
+ " <array>\n";
+
+ for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(),
+ DE = BatchedDiags.end(); DI!=DE; ++DI) {
+
+ o << " <dict>\n"
+ " <key>path</key>\n";
+
+ const PathDiagnostic *D = *DI;
+ // Create an owning smart pointer for 'D' just so that we auto-free it
+ // when we exit this method.
+ llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));
+
+ o << " <array>\n";
+
+ for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
+ ReportDiag(o, *I, FM, *SM, LangOpts);
+
+ o << " </array>\n";
+
+ // Output the bug type and bug category.
+ o << " <key>description</key>";
+ EmitString(o, D->getDescription()) << '\n';
+ o << " <key>category</key>";
+ EmitString(o, D->getCategory()) << '\n';
+ o << " <key>type</key>";
+ EmitString(o, D->getBugType()) << '\n';
+
+ // Output the location of the bug.
+ o << " <key>location</key>\n";
+ EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
+
+ // Output the diagnostic to the sub-diagnostic client, if any.
+ if (SubPD) {
+ SubPD->HandlePathDiagnostic(OwnedD.take());
+ llvm::SmallVector<std::string, 1> SubFilesMade;
+ SubPD->FlushDiagnostics(SubFilesMade);
+
+ if (!SubFilesMade.empty()) {
+ o << " <key>" << SubPD->getName() << "_files</key>\n";
+ o << " <array>\n";
+ for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
+ o << " <string>" << SubFilesMade[i] << "</string>\n";
+ o << " </array>\n";
+ }
+ }
+
+ // Close up the entry.
+ o << " </dict>\n";
+ }
+
+ o << " </array>\n";
+
+ // Finish.
+ o << "</dict>\n</plist>";
+
+ if (FilesMade)
+ FilesMade->push_back(OutputFile);
+
+ BatchedDiags.clear();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
new file mode 100644
index 0000000..389fff5
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -0,0 +1,441 @@
+//== RangeConstraintManager.cpp - Manage range constraints.------*- 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 RangeConstraintManager, a class that tracks simple
+// equality and inequality constraints on symbolic values of GRState.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SimpleConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace { class ConstraintRange {}; }
+static int ConstraintRangeIndex = 0;
+
+/// A Range represents the closed range [from, to]. The caller must
+/// guarantee that from <= to. Note that Range is immutable, so as not
+/// to subvert RangeSet's immutability.
+namespace {
+class Range : public std::pair<const llvm::APSInt*,
+ const llvm::APSInt*> {
+public:
+ Range(const llvm::APSInt &from, const llvm::APSInt &to)
+ : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) {
+ assert(from <= to);
+ }
+ bool Includes(const llvm::APSInt &v) const {
+ return *first <= v && v <= *second;
+ }
+ const llvm::APSInt &From() const {
+ return *first;
+ }
+ const llvm::APSInt &To() const {
+ return *second;
+ }
+ const llvm::APSInt *getConcreteValue() const {
+ return &From() == &To() ? &From() : NULL;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(&From());
+ ID.AddPointer(&To());
+ }
+};
+
+
+class RangeTrait : public llvm::ImutContainerInfo<Range> {
+public:
+ // When comparing if one Range is less than another, we should compare
+ // the actual APSInt values instead of their pointers. This keeps the order
+ // consistent (instead of comparing by pointer values) and can potentially
+ // be used to speed up some of the operations in RangeSet.
+ static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
+ return *lhs.first < *rhs.first || (!(*rhs.first < *lhs.first) &&
+ *lhs.second < *rhs.second);
+ }
+};
+
+/// RangeSet contains a set of ranges. If the set is empty, then
+/// there the value of a symbol is overly constrained and there are no
+/// possible values for that symbol.
+class RangeSet {
+ typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet;
+ PrimRangeSet ranges; // no need to make const, since it is an
+ // ImmutableSet - this allows default operator=
+ // to work.
+public:
+ typedef PrimRangeSet::Factory Factory;
+ typedef PrimRangeSet::iterator iterator;
+
+ RangeSet(PrimRangeSet RS) : ranges(RS) {}
+
+ iterator begin() const { return ranges.begin(); }
+ iterator end() const { return ranges.end(); }
+
+ bool isEmpty() const { return ranges.isEmpty(); }
+
+ /// Construct a new RangeSet representing '{ [from, to] }'.
+ RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to)
+ : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
+
+ /// Profile - Generates a hash profile of this RangeSet for use
+ /// by FoldingSet.
+ void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); }
+
+ /// getConcreteValue - If a symbol is contrained to equal a specific integer
+ /// constant then this method returns that value. Otherwise, it returns
+ /// NULL.
+ const llvm::APSInt* getConcreteValue() const {
+ return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : 0;
+ }
+
+private:
+ void IntersectInRange(BasicValueFactory &BV, Factory &F,
+ const llvm::APSInt &Lower,
+ const llvm::APSInt &Upper,
+ PrimRangeSet &newRanges,
+ PrimRangeSet::iterator &i,
+ PrimRangeSet::iterator &e) const {
+ // There are six cases for each range R in the set:
+ // 1. R is entirely before the intersection range.
+ // 2. R is entirely after the intersection range.
+ // 3. R contains the entire intersection range.
+ // 4. R starts before the intersection range and ends in the middle.
+ // 5. R starts in the middle of the intersection range and ends after it.
+ // 6. R is entirely contained in the intersection range.
+ // These correspond to each of the conditions below.
+ for (/* i = begin(), e = end() */; i != e; ++i) {
+ if (i->To() < Lower) {
+ continue;
+ }
+ if (i->From() > Upper) {
+ break;
+ }
+
+ if (i->Includes(Lower)) {
+ if (i->Includes(Upper)) {
+ newRanges = F.add(newRanges, Range(BV.getValue(Lower),
+ BV.getValue(Upper)));
+ break;
+ } else
+ newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
+ } else {
+ if (i->Includes(Upper)) {
+ newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
+ break;
+ } else
+ newRanges = F.add(newRanges, *i);
+ }
+ }
+ }
+
+public:
+ // Returns a set containing the values in the receiving set, intersected with
+ // the closed range [Lower, Upper]. Unlike the Range type, this range uses
+ // modular arithmetic, corresponding to the common treatment of C integer
+ // overflow. Thus, if the Lower bound is greater than the Upper bound, the
+ // range is taken to wrap around. This is equivalent to taking the
+ // intersection with the two ranges [Min, Upper] and [Lower, Max],
+ // or, alternatively, /removing/ all integers between Upper and Lower.
+ RangeSet Intersect(BasicValueFactory &BV, Factory &F,
+ const llvm::APSInt &Lower,
+ const llvm::APSInt &Upper) const {
+ PrimRangeSet newRanges = F.getEmptySet();
+
+ PrimRangeSet::iterator i = begin(), e = end();
+ if (Lower <= Upper)
+ IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
+ else {
+ // The order of the next two statements is important!
+ // IntersectInRange() does not reset the iteration state for i and e.
+ // Therefore, the lower range most be handled first.
+ IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e);
+ IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e);
+ }
+ return newRanges;
+ }
+
+ void print(llvm::raw_ostream &os) const {
+ bool isFirst = true;
+ os << "{ ";
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ if (isFirst)
+ isFirst = false;
+ else
+ os << ", ";
+
+ os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
+ << ']';
+ }
+ os << " }";
+ }
+
+ bool operator==(const RangeSet &other) const {
+ return ranges == other.ranges;
+ }
+};
+} // end anonymous namespace
+
+typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstraintRangeTy;
+
+namespace clang {
+namespace ento {
+template<>
+struct GRStateTrait<ConstraintRange>
+ : public GRStatePartialTrait<ConstraintRangeTy> {
+ static inline void* GDMIndex() { return &ConstraintRangeIndex; }
+};
+}
+}
+
+namespace {
+class RangeConstraintManager : public SimpleConstraintManager{
+ RangeSet GetRange(const GRState *state, SymbolRef sym);
+public:
+ RangeConstraintManager(SubEngine &subengine)
+ : SimpleConstraintManager(subengine) {}
+
+ const GRState *assumeSymNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymLT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymGT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymGE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const GRState *assumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment);
+
+ const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
+
+ // FIXME: Refactor into SimpleConstraintManager?
+ bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const {
+ const llvm::APSInt *i = getSymVal(St, sym);
+ return i ? *i == V : false;
+ }
+
+ const GRState* removeDeadBindings(const GRState* St, SymbolReaper& SymReaper);
+
+ void print(const GRState* St, llvm::raw_ostream& Out,
+ const char* nl, const char *sep);
+
+private:
+ RangeSet::Factory F;
+};
+
+} // end anonymous namespace
+
+ConstraintManager* ento::CreateRangeConstraintManager(GRStateManager&,
+ SubEngine &subeng) {
+ return new RangeConstraintManager(subeng);
+}
+
+const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
+ SymbolRef sym) const {
+ const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
+ return T ? T->getConcreteValue() : NULL;
+}
+
+/// Scan all symbols referenced by the constraints. If the symbol is not alive
+/// as marked in LSymbols, mark it as dead in DSymbols.
+const GRState*
+RangeConstraintManager::removeDeadBindings(const GRState* state,
+ SymbolReaper& SymReaper) {
+
+ ConstraintRangeTy CR = state->get<ConstraintRange>();
+ ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
+
+ for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
+ SymbolRef sym = I.getKey();
+ if (SymReaper.maybeDead(sym))
+ CR = CRFactory.remove(CR, sym);
+ }
+
+ return state->set<ConstraintRange>(CR);
+}
+
+RangeSet
+RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
+ if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
+ return *V;
+
+ // Lazily generate a new RangeSet representing all possible values for the
+ // given symbol type.
+ QualType T = state->getSymbolManager().getType(sym);
+ BasicValueFactory& BV = state->getBasicVals();
+ return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
+}
+
+//===------------------------------------------------------------------------===
+// assumeSymX methods: public interface for RangeConstraintManager.
+//===------------------------------------------------------------------------===/
+
+// The syntax for ranges below is mathematical, using [x, y] for closed ranges
+// and (x, y) for open ranges. These ranges are modular, corresponding with
+// a common treatment of C integer overflow. This means that these methods
+// do not have to worry about overflow; RangeSet::Intersect can handle such a
+// "wraparound" range.
+// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
+// UINT_MAX, 0, 1, and 2.
+
+const GRState*
+RangeConstraintManager::assumeSymNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ BasicValueFactory &BV = state->getBasicVals();
+
+ llvm::APSInt Lower = Int-Adjustment;
+ llvm::APSInt Upper = Lower;
+ --Lower;
+ ++Upper;
+
+ // [Int-Adjustment+1, Int-Adjustment-1]
+ // Notice that the lower bound is greater than the upper bound.
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, Upper, Lower);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+const GRState*
+RangeConstraintManager::assumeSymEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ // [Int-Adjustment, Int-Adjustment]
+ BasicValueFactory &BV = state->getBasicVals();
+ llvm::APSInt AdjInt = Int-Adjustment;
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, AdjInt, AdjInt);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+const GRState*
+RangeConstraintManager::assumeSymLT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ BasicValueFactory &BV = state->getBasicVals();
+
+ QualType T = state->getSymbolManager().getType(sym);
+ const llvm::APSInt &Min = BV.getMinValue(T);
+
+ // Special case for Int == Min. This is always false.
+ if (Int == Min)
+ return NULL;
+
+ llvm::APSInt Lower = Min-Adjustment;
+ llvm::APSInt Upper = Int-Adjustment;
+ --Upper;
+
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+const GRState*
+RangeConstraintManager::assumeSymGT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ BasicValueFactory &BV = state->getBasicVals();
+
+ QualType T = state->getSymbolManager().getType(sym);
+ const llvm::APSInt &Max = BV.getMaxValue(T);
+
+ // Special case for Int == Max. This is always false.
+ if (Int == Max)
+ return NULL;
+
+ llvm::APSInt Lower = Int-Adjustment;
+ llvm::APSInt Upper = Max-Adjustment;
+ ++Lower;
+
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+const GRState*
+RangeConstraintManager::assumeSymGE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ BasicValueFactory &BV = state->getBasicVals();
+
+ QualType T = state->getSymbolManager().getType(sym);
+ const llvm::APSInt &Min = BV.getMinValue(T);
+
+ // Special case for Int == Min. This is always feasible.
+ if (Int == Min)
+ return state;
+
+ const llvm::APSInt &Max = BV.getMaxValue(T);
+
+ llvm::APSInt Lower = Int-Adjustment;
+ llvm::APSInt Upper = Max-Adjustment;
+
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+const GRState*
+RangeConstraintManager::assumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& Int,
+ const llvm::APSInt& Adjustment) {
+ BasicValueFactory &BV = state->getBasicVals();
+
+ QualType T = state->getSymbolManager().getType(sym);
+ const llvm::APSInt &Max = BV.getMaxValue(T);
+
+ // Special case for Int == Max. This is always feasible.
+ if (Int == Max)
+ return state;
+
+ const llvm::APSInt &Min = BV.getMinValue(T);
+
+ llvm::APSInt Lower = Min-Adjustment;
+ llvm::APSInt Upper = Int-Adjustment;
+
+ RangeSet New = GetRange(state, sym).Intersect(BV, F, Lower, Upper);
+ return New.isEmpty() ? NULL : state->set<ConstraintRange>(sym, New);
+}
+
+//===------------------------------------------------------------------------===
+// Pretty-printing.
+//===------------------------------------------------------------------------===/
+
+void RangeConstraintManager::print(const GRState* St, llvm::raw_ostream& Out,
+ const char* nl, const char *sep) {
+
+ ConstraintRangeTy Ranges = St->get<ConstraintRange>();
+
+ if (Ranges.isEmpty())
+ return;
+
+ Out << nl << sep << "ranges of symbol values:";
+
+ for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){
+ Out << nl << ' ' << I.getKey() << " : ";
+ I.getData().print(Out);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
new file mode 100644
index 0000000..19e0e12
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -0,0 +1,1813 @@
+//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a basic region store model. In this model, we do have field
+// sensitivity. But we assume nothing about the heap shape. So recursive data
+// structures are largely ignored. Basically we do 1-limiting analysis.
+// Parameter pointers are assumed with no aliasing. Pointee objects of
+// parameters are created lazily.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::Optional;
+
+//===----------------------------------------------------------------------===//
+// Representation of binding keys.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class BindingKey {
+public:
+ enum Kind { Direct = 0x0, Default = 0x1 };
+private:
+ llvm ::PointerIntPair<const MemRegion*, 1> P;
+ uint64_t Offset;
+
+ explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
+ : P(r, (unsigned) k), Offset(offset) {}
+public:
+
+ bool isDirect() const { return P.getInt() == Direct; }
+
+ const MemRegion *getRegion() const { return P.getPointer(); }
+ uint64_t getOffset() const { return Offset; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddPointer(P.getOpaqueValue());
+ ID.AddInteger(Offset);
+ }
+
+ static BindingKey Make(const MemRegion *R, Kind k);
+
+ bool operator<(const BindingKey &X) const {
+ if (P.getOpaqueValue() < X.P.getOpaqueValue())
+ return true;
+ if (P.getOpaqueValue() > X.P.getOpaqueValue())
+ return false;
+ return Offset < X.Offset;
+ }
+
+ bool operator==(const BindingKey &X) const {
+ return P.getOpaqueValue() == X.P.getOpaqueValue() &&
+ Offset == X.Offset;
+ }
+
+ bool isValid() const {
+ return getRegion() != NULL;
+ }
+};
+} // end anonymous namespace
+
+BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ const RegionRawOffset &O = ER->getAsArrayOffset();
+
+ // FIXME: There are some ElementRegions for which we cannot compute
+ // raw offsets yet, including regions with symbolic offsets. These will be
+ // ignored by the store.
+ return BindingKey(O.getRegion(), O.getOffset().getQuantity(), k);
+ }
+
+ return BindingKey(R, 0, k);
+}
+
+namespace llvm {
+ static inline
+ llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
+ os << '(' << K.getRegion() << ',' << K.getOffset()
+ << ',' << (K.isDirect() ? "direct" : "default")
+ << ')';
+ return os;
+ }
+} // end llvm namespace
+
+//===----------------------------------------------------------------------===//
+// Actual Store type.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<BindingKey, SVal> RegionBindings;
+
+//===----------------------------------------------------------------------===//
+// Fine-grained control of RegionStoreManager.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct minimal_features_tag {};
+struct maximal_features_tag {};
+
+class RegionStoreFeatures {
+ bool SupportsFields;
+public:
+ RegionStoreFeatures(minimal_features_tag) :
+ SupportsFields(false) {}
+
+ RegionStoreFeatures(maximal_features_tag) :
+ SupportsFields(true) {}
+
+ void enableFields(bool t) { SupportsFields = t; }
+
+ bool supportsFields() const { return SupportsFields; }
+};
+}
+
+//===----------------------------------------------------------------------===//
+// Main RegionStore logic.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class RegionStoreSubRegionMap : public SubRegionMap {
+public:
+ typedef llvm::ImmutableSet<const MemRegion*> Set;
+ typedef llvm::DenseMap<const MemRegion*, Set> Map;
+private:
+ Set::Factory F;
+ Map M;
+public:
+ bool add(const MemRegion* Parent, const MemRegion* SubRegion) {
+ Map::iterator I = M.find(Parent);
+
+ if (I == M.end()) {
+ M.insert(std::make_pair(Parent, F.add(F.getEmptySet(), SubRegion)));
+ return true;
+ }
+
+ I->second = F.add(I->second, SubRegion);
+ return false;
+ }
+
+ void process(llvm::SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R);
+
+ ~RegionStoreSubRegionMap() {}
+
+ const Set *getSubRegions(const MemRegion *Parent) const {
+ Map::const_iterator I = M.find(Parent);
+ return I == M.end() ? NULL : &I->second;
+ }
+
+ bool iterSubRegions(const MemRegion* Parent, Visitor& V) const {
+ Map::const_iterator I = M.find(Parent);
+
+ if (I == M.end())
+ return true;
+
+ Set S = I->second;
+ for (Set::iterator SI=S.begin(),SE=S.end(); SI != SE; ++SI) {
+ if (!V.Visit(Parent, *SI))
+ return false;
+ }
+
+ return true;
+ }
+};
+
+void
+RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
+ const SubRegion *R) {
+ const MemRegion *superR = R->getSuperRegion();
+ if (add(superR, R))
+ if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
+ WL.push_back(sr);
+}
+
+class RegionStoreManager : public StoreManager {
+ const RegionStoreFeatures Features;
+ RegionBindings::Factory RBFactory;
+
+public:
+ RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
+ : StoreManager(mgr),
+ Features(f),
+ RBFactory(mgr.getAllocator()) {}
+
+ SubRegionMap *getSubRegionMap(Store store) {
+ return getRegionStoreSubRegionMap(store);
+ }
+
+ RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
+
+ Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
+ /// getDefaultBinding - Returns an SVal* representing an optional default
+ /// binding associated with a region and its subregions.
+ Optional<SVal> getDefaultBinding(RegionBindings B, const MemRegion *R);
+
+ /// setImplicitDefaultValue - Set the default binding for the provided
+ /// MemRegion to the value implicitly defined for compound literals when
+ /// the value is not specified.
+ StoreRef setImplicitDefaultValue(Store store, const MemRegion *R, QualType T);
+
+ /// ArrayToPointer - Emulates the "decay" of an array to a pointer
+ /// type. 'Array' represents the lvalue of the array being decayed
+ /// to a pointer, and the returned SVal represents the decayed
+ /// version of that lvalue (i.e., a pointer to the first element of
+ /// the array). This is called by ExprEngine when evaluating
+ /// casts from arrays to pointers.
+ SVal ArrayToPointer(Loc Array);
+
+ /// For DerivedToBase casts, create a CXXBaseObjectRegion and return it.
+ virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType);
+
+ StoreRef getInitialStore(const LocationContext *InitLoc) {
+ return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this);
+ }
+
+ //===-------------------------------------------------------------------===//
+ // Binding values to regions.
+ //===-------------------------------------------------------------------===//
+
+ StoreRef invalidateRegions(Store store,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions);
+
+public: // Made public for helper classes.
+
+ void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
+ RegionStoreSubRegionMap &M);
+
+ RegionBindings addBinding(RegionBindings B, BindingKey K, SVal V);
+
+ RegionBindings addBinding(RegionBindings B, const MemRegion *R,
+ BindingKey::Kind k, SVal V);
+
+ const SVal *lookup(RegionBindings B, BindingKey K);
+ const SVal *lookup(RegionBindings B, const MemRegion *R, BindingKey::Kind k);
+
+ RegionBindings removeBinding(RegionBindings B, BindingKey K);
+ RegionBindings removeBinding(RegionBindings B, const MemRegion *R,
+ BindingKey::Kind k);
+
+ RegionBindings removeBinding(RegionBindings B, const MemRegion *R) {
+ return removeBinding(removeBinding(B, R, BindingKey::Direct), R,
+ BindingKey::Default);
+ }
+
+public: // Part of public interface to class.
+
+ StoreRef Bind(Store store, Loc LV, SVal V);
+
+ // BindDefault is only used to initialize a region with a default value.
+ StoreRef BindDefault(Store store, const MemRegion *R, SVal V) {
+ RegionBindings B = GetRegionBindings(store);
+ assert(!lookup(B, R, BindingKey::Default));
+ assert(!lookup(B, R, BindingKey::Direct));
+ return StoreRef(addBinding(B, R, BindingKey::Default, V).getRootWithoutRetain(), *this);
+ }
+
+ StoreRef BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL,
+ const LocationContext *LC, SVal V);
+
+ StoreRef BindDecl(Store store, const VarRegion *VR, SVal InitVal);
+
+ StoreRef BindDeclWithNoInit(Store store, const VarRegion *) {
+ return StoreRef(store, *this);
+ }
+
+ /// BindStruct - Bind a compound value to a structure.
+ StoreRef BindStruct(Store store, const TypedRegion* R, SVal V);
+
+ StoreRef BindArray(Store store, const TypedRegion* R, SVal V);
+
+ /// KillStruct - Set the entire struct to unknown.
+ StoreRef KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
+
+ StoreRef Remove(Store store, Loc LV);
+
+ void incrementReferenceCount(Store store) {
+ GetRegionBindings(store).manualRetain();
+ }
+
+ /// If the StoreManager supports it, decrement the reference count of
+ /// the specified Store object. If the reference count hits 0, the memory
+ /// associated with the object is recycled.
+ void decrementReferenceCount(Store store) {
+ GetRegionBindings(store).manualRelease();
+ }
+
+ //===------------------------------------------------------------------===//
+ // Loading values from regions.
+ //===------------------------------------------------------------------===//
+
+ /// The high level logic for this method is this:
+ /// Retrieve (L)
+ /// if L has binding
+ /// return L's binding
+ /// else if L is in killset
+ /// return unknown
+ /// else
+ /// if L is on stack or heap
+ /// return undefined
+ /// else
+ /// return symbolic
+ SVal Retrieve(Store store, Loc L, QualType T = QualType());
+
+ SVal RetrieveElement(Store store, const ElementRegion *R);
+
+ SVal RetrieveField(Store store, const FieldRegion *R);
+
+ SVal RetrieveObjCIvar(Store store, const ObjCIvarRegion *R);
+
+ SVal RetrieveVar(Store store, const VarRegion *R);
+
+ SVal RetrieveLazySymbol(const TypedRegion *R);
+
+ SVal RetrieveFieldOrElementCommon(Store store, const TypedRegion *R,
+ QualType Ty, const MemRegion *superR);
+
+ /// Retrieve the values in a struct and return a CompoundVal, used when doing
+ /// struct copy:
+ /// struct s x, y;
+ /// x = y;
+ /// y's value is retrieved by this method.
+ SVal RetrieveStruct(Store store, const TypedRegion* R);
+
+ SVal RetrieveArray(Store store, const TypedRegion* R);
+
+ /// Used to lazily generate derived symbols for bindings that are defined
+ /// implicitly by default bindings in a super region.
+ Optional<SVal> RetrieveDerivedDefaultValue(RegionBindings B,
+ const MemRegion *superR,
+ const TypedRegion *R, QualType Ty);
+
+ /// Get the state and region whose binding this region R corresponds to.
+ std::pair<Store, const MemRegion*>
+ GetLazyBinding(RegionBindings B, const MemRegion *R);
+
+ StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store,
+ const TypedRegion *R);
+
+ //===------------------------------------------------------------------===//
+ // State pruning.
+ //===------------------------------------------------------------------===//
+
+ /// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
+ /// It returns a new Store with these values removed.
+ StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
+
+ StoreRef enterStackFrame(const GRState *state, const StackFrameContext *frame);
+
+ //===------------------------------------------------------------------===//
+ // Region "extents".
+ //===------------------------------------------------------------------===//
+
+ // FIXME: This method will soon be eliminated; see the note in Store.h.
+ DefinedOrUnknownSVal getSizeInElements(const GRState *state,
+ const MemRegion* R, QualType EleTy);
+
+ //===------------------------------------------------------------------===//
+ // Utility methods.
+ //===------------------------------------------------------------------===//
+
+ static inline RegionBindings GetRegionBindings(Store store) {
+ return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
+ }
+
+ void print(Store store, llvm::raw_ostream& Out, const char* nl,
+ const char *sep);
+
+ void iterBindings(Store store, BindingsHandler& f) {
+ RegionBindings B = GetRegionBindings(store);
+ for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
+ const BindingKey &K = I.getKey();
+ if (!K.isDirect())
+ continue;
+ if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey().getRegion())) {
+ // FIXME: Possibly incorporate the offset?
+ if (!f.HandleBinding(*this, store, R, I.getData()))
+ return;
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RegionStore creation.
+//===----------------------------------------------------------------------===//
+
+StoreManager *ento::CreateRegionStoreManager(GRStateManager& StMgr) {
+ RegionStoreFeatures F = maximal_features_tag();
+ return new RegionStoreManager(StMgr, F);
+}
+
+StoreManager *ento::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
+ RegionStoreFeatures F = minimal_features_tag();
+ F.enableFields(true);
+ return new RegionStoreManager(StMgr, F);
+}
+
+
+RegionStoreSubRegionMap*
+RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
+ RegionBindings B = GetRegionBindings(store);
+ RegionStoreSubRegionMap *M = new RegionStoreSubRegionMap();
+
+ llvm::SmallVector<const SubRegion*, 10> WL;
+
+ for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I)
+ if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey().getRegion()))
+ M->process(WL, R);
+
+ // We also need to record in the subregion map "intermediate" regions that
+ // don't have direct bindings but are super regions of those that do.
+ while (!WL.empty()) {
+ const SubRegion *R = WL.back();
+ WL.pop_back();
+ M->process(WL, R);
+ }
+
+ return M;
+}
+
+//===----------------------------------------------------------------------===//
+// Region Cluster analysis.
+//===----------------------------------------------------------------------===//
+
+namespace {
+template <typename DERIVED>
+class ClusterAnalysis {
+protected:
+ typedef BumpVector<BindingKey> RegionCluster;
+ typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
+ llvm::DenseMap<const RegionCluster*, unsigned> Visited;
+ typedef llvm::SmallVector<std::pair<const MemRegion *, RegionCluster*>, 10>
+ WorkList;
+
+ BumpVectorContext BVC;
+ ClusterMap ClusterM;
+ WorkList WL;
+
+ RegionStoreManager &RM;
+ ASTContext &Ctx;
+ SValBuilder &svalBuilder;
+
+ RegionBindings B;
+
+ const bool includeGlobals;
+
+public:
+ ClusterAnalysis(RegionStoreManager &rm, GRStateManager &StateMgr,
+ RegionBindings b, const bool includeGlobals)
+ : RM(rm), Ctx(StateMgr.getContext()),
+ svalBuilder(StateMgr.getSValBuilder()),
+ B(b), includeGlobals(includeGlobals) {}
+
+ RegionBindings getRegionBindings() const { return B; }
+
+ RegionCluster &AddToCluster(BindingKey K) {
+ const MemRegion *R = K.getRegion();
+ const MemRegion *baseR = R->getBaseRegion();
+ RegionCluster &C = getCluster(baseR);
+ C.push_back(K, BVC);
+ static_cast<DERIVED*>(this)->VisitAddedToCluster(baseR, C);
+ return C;
+ }
+
+ bool isVisited(const MemRegion *R) {
+ return (bool) Visited[&getCluster(R->getBaseRegion())];
+ }
+
+ RegionCluster& getCluster(const MemRegion *R) {
+ RegionCluster *&CRef = ClusterM[R];
+ if (!CRef) {
+ void *Mem = BVC.getAllocator().template Allocate<RegionCluster>();
+ CRef = new (Mem) RegionCluster(BVC, 10);
+ }
+ return *CRef;
+ }
+
+ void GenerateClusters() {
+ // Scan the entire set of bindings and make the region clusters.
+ for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
+ RegionCluster &C = AddToCluster(RI.getKey());
+ if (const MemRegion *R = RI.getData().getAsRegion()) {
+ // Generate a cluster, but don't add the region to the cluster
+ // if there aren't any bindings.
+ getCluster(R->getBaseRegion());
+ }
+ if (includeGlobals) {
+ const MemRegion *R = RI.getKey().getRegion();
+ if (isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace()))
+ AddToWorkList(R, C);
+ }
+ }
+ }
+
+ bool AddToWorkList(const MemRegion *R, RegionCluster &C) {
+ if (unsigned &visited = Visited[&C])
+ return false;
+ else
+ visited = 1;
+
+ WL.push_back(std::make_pair(R, &C));
+ return true;
+ }
+
+ bool AddToWorkList(BindingKey K) {
+ return AddToWorkList(K.getRegion());
+ }
+
+ bool AddToWorkList(const MemRegion *R) {
+ const MemRegion *baseR = R->getBaseRegion();
+ return AddToWorkList(baseR, getCluster(baseR));
+ }
+
+ void RunWorkList() {
+ while (!WL.empty()) {
+ const MemRegion *baseR;
+ RegionCluster *C;
+ llvm::tie(baseR, C) = WL.back();
+ WL.pop_back();
+
+ // First visit the cluster.
+ static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end());
+
+ // Next, visit the base region.
+ static_cast<DERIVED*>(this)->VisitBaseRegion(baseR);
+ }
+ }
+
+public:
+ void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {}
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {}
+ void VisitBaseRegion(const MemRegion *baseR) {}
+};
+}
+
+//===----------------------------------------------------------------------===//
+// Binding invalidation.
+//===----------------------------------------------------------------------===//
+
+void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
+ const MemRegion *R,
+ RegionStoreSubRegionMap &M) {
+
+ if (const RegionStoreSubRegionMap::Set *S = M.getSubRegions(R))
+ for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
+ I != E; ++I)
+ RemoveSubRegionBindings(B, *I, M);
+
+ B = removeBinding(B, R);
+}
+
+namespace {
+class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
+{
+ const Expr *Ex;
+ unsigned Count;
+ StoreManager::InvalidatedSymbols *IS;
+ StoreManager::InvalidatedRegions *Regions;
+public:
+ invalidateRegionsWorker(RegionStoreManager &rm,
+ GRStateManager &stateMgr,
+ RegionBindings b,
+ const Expr *ex, unsigned count,
+ StoreManager::InvalidatedSymbols *is,
+ StoreManager::InvalidatedRegions *r,
+ bool includeGlobals)
+ : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals),
+ Ex(ex), Count(count), IS(is), Regions(r) {}
+
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
+ void VisitBaseRegion(const MemRegion *baseR);
+
+private:
+ void VisitBinding(SVal V);
+};
+}
+
+void invalidateRegionsWorker::VisitBinding(SVal V) {
+ // A symbol? Mark it touched by the invalidation.
+ if (IS)
+ if (SymbolRef Sym = V.getAsSymbol())
+ IS->insert(Sym);
+
+ if (const MemRegion *R = V.getAsRegion()) {
+ AddToWorkList(R);
+ return;
+ }
+
+ // Is it a LazyCompoundVal? All references get invalidated as well.
+ if (const nonloc::LazyCompoundVal *LCS =
+ dyn_cast<nonloc::LazyCompoundVal>(&V)) {
+
+ const MemRegion *LazyR = LCS->getRegion();
+ RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore());
+
+ for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
+ const SubRegion *baseR = dyn_cast<SubRegion>(RI.getKey().getRegion());
+ if (baseR && baseR->isSubRegionOf(LazyR))
+ VisitBinding(RI.getData());
+ }
+
+ return;
+ }
+}
+
+void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
+ BindingKey *I, BindingKey *E) {
+ for ( ; I != E; ++I) {
+ // Get the old binding. Is it a region? If so, add it to the worklist.
+ const BindingKey &K = *I;
+ if (const SVal *V = RM.lookup(B, K))
+ VisitBinding(*V);
+
+ B = RM.removeBinding(B, K);
+ }
+}
+
+void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
+ if (IS) {
+ // Symbolic region? Mark that symbol touched by the invalidation.
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
+ IS->insert(SR->getSymbol());
+ }
+
+ // BlockDataRegion? If so, invalidate captured variables that are passed
+ // by reference.
+ if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
+ for (BlockDataRegion::referenced_vars_iterator
+ BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
+ BI != BE; ++BI) {
+ const VarRegion *VR = *BI;
+ const VarDecl *VD = VR->getDecl();
+ if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
+ AddToWorkList(VR);
+ }
+ return;
+ }
+
+ // Otherwise, we have a normal data region. Record that we touched the region.
+ if (Regions)
+ Regions->push_back(baseR);
+
+ if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
+ // Invalidate the region by setting its default value to
+ // conjured symbol. The type of the symbol is irrelavant.
+ DefinedOrUnknownSVal V =
+ svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy, Count);
+ B = RM.addBinding(B, baseR, BindingKey::Default, V);
+ return;
+ }
+
+ if (!baseR->isBoundable())
+ return;
+
+ const TypedRegion *TR = cast<TypedRegion>(baseR);
+ QualType T = TR->getValueType();
+
+ // Invalidate the binding.
+ if (T->isStructureType()) {
+ // Invalidate the region by setting its default value to
+ // conjured symbol. The type of the symbol is irrelavant.
+ DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
+ Count);
+ B = RM.addBinding(B, baseR, BindingKey::Default, V);
+ return;
+ }
+
+ if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+ // Set the default value of the array to conjured symbol.
+ DefinedOrUnknownSVal V =
+ svalBuilder.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count);
+ B = RM.addBinding(B, baseR, BindingKey::Default, V);
+ return;
+ }
+
+ if (includeGlobals &&
+ isa<NonStaticGlobalSpaceRegion>(baseR->getMemorySpace())) {
+ // If the region is a global and we are invalidating all globals,
+ // just erase the entry. This causes all globals to be lazily
+ // symbolicated from the same base symbol.
+ B = RM.removeBinding(B, baseR);
+ return;
+ }
+
+
+ DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, T, Count);
+ assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
+ B = RM.addBinding(B, baseR, BindingKey::Direct, V);
+}
+
+StoreRef RegionStoreManager::invalidateRegions(Store store,
+ const MemRegion * const *I,
+ const MemRegion * const *E,
+ const Expr *Ex, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
+ invalidateRegionsWorker W(*this, StateMgr,
+ RegionStoreManager::GetRegionBindings(store),
+ Ex, Count, IS, Regions, invalidateGlobals);
+
+ // Scan the bindings and generate the clusters.
+ W.GenerateClusters();
+
+ // Add I .. E to the worklist.
+ for ( ; I != E; ++I)
+ W.AddToWorkList(*I);
+
+ W.RunWorkList();
+
+ // Return the new bindings.
+ RegionBindings B = W.getRegionBindings();
+
+ if (invalidateGlobals) {
+ // Bind the non-static globals memory space to a new symbol that we will
+ // use to derive the bindings for all non-static globals.
+ const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion();
+ SVal V =
+ svalBuilder.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS, Ex,
+ /* symbol type, doesn't matter */ Ctx.IntTy,
+ Count);
+ B = addBinding(B, BindingKey::Make(GS, BindingKey::Default), V);
+
+ // Even if there are no bindings in the global scope, we still need to
+ // record that we touched it.
+ if (Regions)
+ Regions->push_back(GS);
+ }
+
+ return StoreRef(B.getRootWithoutRetain(), *this);
+}
+
+//===----------------------------------------------------------------------===//
+// Extents for regions.
+//===----------------------------------------------------------------------===//
+
+DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
+ const MemRegion *R,
+ QualType EleTy) {
+ SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
+ const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
+ if (!SizeInt)
+ return UnknownVal();
+
+ CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
+
+ if (Ctx.getAsVariableArrayType(EleTy)) {
+ // FIXME: We need to track extra state to properly record the size
+ // of VLAs. Returning UnknownVal here, however, is a stop-gap so that
+ // we don't have a divide-by-zero below.
+ return UnknownVal();
+ }
+
+ CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
+
+ // If a variable is reinterpreted as a type that doesn't fit into a larger
+ // type evenly, round it down.
+ // This is a signed value, since it's used in arithmetic with signed indices.
+ return svalBuilder.makeIntVal(RegionSize / EleSize, false);
+}
+
+//===----------------------------------------------------------------------===//
+// Location and region casting.
+//===----------------------------------------------------------------------===//
+
+/// ArrayToPointer - Emulates the "decay" of an array to a pointer
+/// type. 'Array' represents the lvalue of the array being decayed
+/// to a pointer, and the returned SVal represents the decayed
+/// version of that lvalue (i.e., a pointer to the first element of
+/// the array). This is called by ExprEngine when evaluating casts
+/// from arrays to pointers.
+SVal RegionStoreManager::ArrayToPointer(Loc Array) {
+ if (!isa<loc::MemRegionVal>(Array))
+ return UnknownVal();
+
+ const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
+ const TypedRegion* ArrayR = dyn_cast<TypedRegion>(R);
+
+ if (!ArrayR)
+ return UnknownVal();
+
+ // Strip off typedefs from the ArrayRegion's ValueType.
+ QualType T = ArrayR->getValueType().getDesugaredType(Ctx);
+ const ArrayType *AT = cast<ArrayType>(T);
+ T = AT->getElementType();
+
+ NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
+ return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
+}
+
+SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
+ const CXXRecordDecl *baseDecl;
+ if (baseType->isPointerType())
+ baseDecl = baseType->getCXXRecordDeclForPointerType();
+ else
+ baseDecl = baseType->getAsCXXRecordDecl();
+
+ assert(baseDecl && "not a CXXRecordDecl?");
+
+ loc::MemRegionVal *derivedRegVal = dyn_cast<loc::MemRegionVal>(&derived);
+ if (!derivedRegVal)
+ return derived;
+
+ const MemRegion *baseReg =
+ MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion());
+
+ return loc::MemRegionVal(baseReg);
+}
+
+//===----------------------------------------------------------------------===//
+// Loading values from regions.
+//===----------------------------------------------------------------------===//
+
+Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B,
+ const MemRegion *R) {
+
+ if (const SVal *V = lookup(B, R, BindingKey::Direct))
+ return *V;
+
+ return Optional<SVal>();
+}
+
+Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
+ const MemRegion *R) {
+ if (R->isBoundable())
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
+ if (TR->getValueType()->isUnionType())
+ return UnknownVal();
+
+ if (const SVal *V = lookup(B, R, BindingKey::Default))
+ return *V;
+
+ return Optional<SVal>();
+}
+
+SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
+ assert(!isa<UnknownVal>(L) && "location unknown");
+ assert(!isa<UndefinedVal>(L) && "location undefined");
+
+ // For access to concrete addresses, return UnknownVal. Checks
+ // for null dereferences (and similar errors) are done by checkers, not
+ // the Store.
+ // FIXME: We can consider lazily symbolicating such memory, but we really
+ // should defer this when we can reason easily about symbolicating arrays
+ // of bytes.
+ if (isa<loc::ConcreteInt>(L)) {
+ return UnknownVal();
+ }
+ if (!isa<loc::MemRegionVal>(L)) {
+ return UnknownVal();
+ }
+
+ const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
+
+ if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) {
+ if (T.isNull()) {
+ const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
+ T = SR->getSymbol()->getType(Ctx);
+ }
+ MR = GetElementZeroRegion(MR, T);
+ }
+
+ if (isa<CodeTextRegion>(MR)) {
+ assert(0 && "Why load from a code text region?");
+ return UnknownVal();
+ }
+
+ // FIXME: Perhaps this method should just take a 'const MemRegion*' argument
+ // instead of 'Loc', and have the other Loc cases handled at a higher level.
+ const TypedRegion *R = cast<TypedRegion>(MR);
+ QualType RTy = R->getValueType();
+
+ // FIXME: We should eventually handle funny addressing. e.g.:
+ //
+ // int x = ...;
+ // int *p = &x;
+ // char *q = (char*) p;
+ // char c = *q; // returns the first byte of 'x'.
+ //
+ // Such funny addressing will occur due to layering of regions.
+
+ if (RTy->isStructureOrClassType())
+ return RetrieveStruct(store, R);
+
+ // FIXME: Handle unions.
+ if (RTy->isUnionType())
+ return UnknownVal();
+
+ if (RTy->isArrayType())
+ return RetrieveArray(store, R);
+
+ // FIXME: handle Vector types.
+ if (RTy->isVectorType())
+ return UnknownVal();
+
+ if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
+ return CastRetrievedVal(RetrieveField(store, FR), FR, T, false);
+
+ if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the element type. Eventually we want to compose these values
+ // more intelligently. For example, an 'element' can encompass multiple
+ // bound regions (e.g., several bound bytes), or could be a subset of
+ // a larger value.
+ return CastRetrievedVal(RetrieveElement(store, ER), ER, T, false);
+ }
+
+ if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the ivar type. What we should model is stores to ivars
+ // that blow past the extent of the ivar. If the address of the ivar is
+ // reinterpretted, it is possible we stored a different value that could
+ // fit within the ivar. Either we need to cast these when storing them
+ // or reinterpret them lazily (as we do here).
+ return CastRetrievedVal(RetrieveObjCIvar(store, IVR), IVR, T, false);
+ }
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
+ // FIXME: Here we actually perform an implicit conversion from the loaded
+ // value to the variable type. What we should model is stores to variables
+ // that blow past the extent of the variable. If the address of the
+ // variable is reinterpretted, it is possible we stored a different value
+ // that could fit within the variable. Either we need to cast these when
+ // storing them or reinterpret them lazily (as we do here).
+ return CastRetrievedVal(RetrieveVar(store, VR), VR, T, false);
+ }
+
+ RegionBindings B = GetRegionBindings(store);
+ const SVal *V = lookup(B, R, BindingKey::Direct);
+
+ // Check if the region has a binding.
+ if (V)
+ return *V;
+
+ // The location does not have a bound value. This means that it has
+ // the value it had upon its creation and/or entry to the analyzed
+ // function/method. These are either symbolic values or 'undefined'.
+ if (R->hasStackNonParametersStorage()) {
+ // All stack variables are considered to have undefined values
+ // upon creation. All heap allocated blocks are considered to
+ // have undefined values as well unless they are explicitly bound
+ // to specific values.
+ return UndefinedVal();
+ }
+
+ // All other values are symbolic.
+ return svalBuilder.getRegionValueSymbolVal(R);
+}
+
+std::pair<Store, const MemRegion *>
+RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) {
+ if (Optional<SVal> OV = getDirectBinding(B, R))
+ if (const nonloc::LazyCompoundVal *V =
+ dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
+ return std::make_pair(V->getStore(), V->getRegion());
+
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ const std::pair<Store, const MemRegion *> &X =
+ GetLazyBinding(B, ER->getSuperRegion());
+
+ if (X.second)
+ return std::make_pair(X.first,
+ MRMgr.getElementRegionWithSuper(ER, X.second));
+ }
+ else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
+ const std::pair<Store, const MemRegion *> &X =
+ GetLazyBinding(B, FR->getSuperRegion());
+
+ if (X.second)
+ return std::make_pair(X.first,
+ MRMgr.getFieldRegionWithSuper(FR, X.second));
+ }
+ // C++ base object region is another kind of region that we should blast
+ // through to look for lazy compound value. It is like a field region.
+ else if (const CXXBaseObjectRegion *baseReg =
+ dyn_cast<CXXBaseObjectRegion>(R)) {
+ const std::pair<Store, const MemRegion *> &X =
+ GetLazyBinding(B, baseReg->getSuperRegion());
+
+ if (X.second)
+ return std::make_pair(X.first,
+ MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second));
+ }
+ // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
+ // possible for a valid lazy binding.
+ return std::make_pair((Store) 0, (const MemRegion *) 0);
+}
+
+SVal RegionStoreManager::RetrieveElement(Store store,
+ const ElementRegion* R) {
+ // Check if the region has a binding.
+ RegionBindings B = GetRegionBindings(store);
+ if (const Optional<SVal> &V = getDirectBinding(B, R))
+ return *V;
+
+ const MemRegion* superR = R->getSuperRegion();
+
+ // Check if the region is an element region of a string literal.
+ if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
+ // FIXME: Handle loads from strings where the literal is treated as
+ // an integer, e.g., *((unsigned int*)"hello")
+ QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
+ if (T != Ctx.getCanonicalType(R->getElementType()))
+ return UnknownVal();
+
+ const StringLiteral *Str = StrR->getStringLiteral();
+ SVal Idx = R->getIndex();
+ if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
+ int64_t i = CI->getValue().getSExtValue();
+ int64_t byteLength = Str->getByteLength();
+ // Technically, only i == byteLength is guaranteed to be null.
+ // However, such overflows should be caught before reaching this point;
+ // the only time such an access would be made is if a string literal was
+ // used to initialize a larger array.
+ char c = (i >= byteLength) ? '\0' : Str->getString()[i];
+ return svalBuilder.makeIntVal(c, T);
+ }
+ }
+
+ // Check for loads from a code text region. For such loads, just give up.
+ if (isa<CodeTextRegion>(superR))
+ return UnknownVal();
+
+ // Handle the case where we are indexing into a larger scalar object.
+ // For example, this handles:
+ // int x = ...
+ // char *y = &x;
+ // return *y;
+ // FIXME: This is a hack, and doesn't do anything really intelligent yet.
+ const RegionRawOffset &O = R->getAsArrayOffset();
+ if (const TypedRegion *baseR = dyn_cast_or_null<TypedRegion>(O.getRegion())) {
+ QualType baseT = baseR->getValueType();
+ if (baseT->isScalarType()) {
+ QualType elemT = R->getElementType();
+ if (elemT->isScalarType()) {
+ if (Ctx.getTypeSizeInChars(baseT) >= Ctx.getTypeSizeInChars(elemT)) {
+ if (const Optional<SVal> &V = getDirectBinding(B, superR)) {
+ if (SymbolRef parentSym = V->getAsSymbol())
+ return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
+
+ if (V->isUnknownOrUndef())
+ return *V;
+ // Other cases: give up. We are indexing into a larger object
+ // that has some value, but we don't know how to handle that yet.
+ return UnknownVal();
+ }
+ }
+ }
+ }
+ }
+ return RetrieveFieldOrElementCommon(store, R, R->getElementType(), superR);
+}
+
+SVal RegionStoreManager::RetrieveField(Store store,
+ const FieldRegion* R) {
+
+ // Check if the region has a binding.
+ RegionBindings B = GetRegionBindings(store);
+ if (const Optional<SVal> &V = getDirectBinding(B, R))
+ return *V;
+
+ QualType Ty = R->getValueType();
+ return RetrieveFieldOrElementCommon(store, R, Ty, R->getSuperRegion());
+}
+
+Optional<SVal>
+RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B,
+ const MemRegion *superR,
+ const TypedRegion *R,
+ QualType Ty) {
+
+ if (const Optional<SVal> &D = getDefaultBinding(B, superR)) {
+ if (SymbolRef parentSym = D->getAsSymbol())
+ return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
+
+ if (D->isZeroConstant())
+ return svalBuilder.makeZeroVal(Ty);
+
+ if (D->isUnknownOrUndef())
+ return *D;
+
+ assert(0 && "Unknown default value");
+ }
+
+ return Optional<SVal>();
+}
+
+SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store,
+ const TypedRegion *R,
+ QualType Ty,
+ const MemRegion *superR) {
+
+ // At this point we have already checked in either RetrieveElement or
+ // RetrieveField if 'R' has a direct binding.
+
+ RegionBindings B = GetRegionBindings(store);
+
+ while (superR) {
+ if (const Optional<SVal> &D =
+ RetrieveDerivedDefaultValue(B, superR, R, Ty))
+ return *D;
+
+ // If our super region is a field or element itself, walk up the region
+ // hierarchy to see if there is a default value installed in an ancestor.
+ if (const SubRegion *SR = dyn_cast<SubRegion>(superR)) {
+ superR = SR->getSuperRegion();
+ continue;
+ }
+ break;
+ }
+
+ // Lazy binding?
+ Store lazyBindingStore = NULL;
+ const MemRegion *lazyBindingRegion = NULL;
+ llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R);
+
+ if (lazyBindingRegion) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(lazyBindingRegion))
+ return RetrieveElement(lazyBindingStore, ER);
+ return RetrieveField(lazyBindingStore,
+ cast<FieldRegion>(lazyBindingRegion));
+ }
+
+ if (R->hasStackNonParametersStorage()) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ // Currently we don't reason specially about Clang-style vectors. Check
+ // if superR is a vector and if so return Unknown.
+ if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
+ if (typedSuperR->getValueType()->isVectorType())
+ return UnknownVal();
+ }
+
+ // FIXME: We also need to take ElementRegions with symbolic indexes into
+ // account.
+ if (!ER->getIndex().isConstant())
+ return UnknownVal();
+ }
+
+ return UndefinedVal();
+ }
+
+ // All other values are symbolic.
+ return svalBuilder.getRegionValueSymbolVal(R);
+}
+
+SVal RegionStoreManager::RetrieveObjCIvar(Store store, const ObjCIvarRegion* R){
+
+ // Check if the region has a binding.
+ RegionBindings B = GetRegionBindings(store);
+
+ if (const Optional<SVal> &V = getDirectBinding(B, R))
+ return *V;
+
+ const MemRegion *superR = R->getSuperRegion();
+
+ // Check if the super region has a default binding.
+ if (const Optional<SVal> &V = getDefaultBinding(B, superR)) {
+ if (SymbolRef parentSym = V->getAsSymbol())
+ return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
+
+ // Other cases: give up.
+ return UnknownVal();
+ }
+
+ return RetrieveLazySymbol(R);
+}
+
+SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
+
+ // Check if the region has a binding.
+ RegionBindings B = GetRegionBindings(store);
+
+ if (const Optional<SVal> &V = getDirectBinding(B, R))
+ return *V;
+
+ // Lazily derive a value for the VarRegion.
+ const VarDecl *VD = R->getDecl();
+ QualType T = VD->getType();
+ const MemSpaceRegion *MS = R->getMemorySpace();
+
+ if (isa<UnknownSpaceRegion>(MS) ||
+ isa<StackArgumentsSpaceRegion>(MS))
+ return svalBuilder.getRegionValueSymbolVal(R);
+
+ if (isa<GlobalsSpaceRegion>(MS)) {
+ if (isa<NonStaticGlobalSpaceRegion>(MS)) {
+ // Is 'VD' declared constant? If so, retrieve the constant value.
+ QualType CT = Ctx.getCanonicalType(T);
+ if (CT.isConstQualified()) {
+ const Expr *Init = VD->getInit();
+ // Do the null check first, as we want to call 'IgnoreParenCasts'.
+ if (Init)
+ if (const IntegerLiteral *IL =
+ dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
+ const nonloc::ConcreteInt &V = svalBuilder.makeIntVal(IL);
+ return svalBuilder.evalCast(V, Init->getType(), IL->getType());
+ }
+ }
+
+ if (const Optional<SVal> &V = RetrieveDerivedDefaultValue(B, MS, R, CT))
+ return V.getValue();
+
+ return svalBuilder.getRegionValueSymbolVal(R);
+ }
+
+ if (T->isIntegerType())
+ return svalBuilder.makeIntVal(0, T);
+ if (T->isPointerType())
+ return svalBuilder.makeNull();
+
+ return UnknownVal();
+ }
+
+ return UndefinedVal();
+}
+
+SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
+ // All other values are symbolic.
+ return svalBuilder.getRegionValueSymbolVal(R);
+}
+
+SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
+ QualType T = R->getValueType();
+ assert(T->isStructureOrClassType());
+ return svalBuilder.makeLazyCompoundVal(store, R);
+}
+
+SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
+ assert(Ctx.getAsConstantArrayType(R->getValueType()));
+ return svalBuilder.makeLazyCompoundVal(store, R);
+}
+
+//===----------------------------------------------------------------------===//
+// Binding values to regions.
+//===----------------------------------------------------------------------===//
+
+StoreRef RegionStoreManager::Remove(Store store, Loc L) {
+ if (isa<loc::MemRegionVal>(L))
+ if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion())
+ return StoreRef(removeBinding(GetRegionBindings(store),
+ R).getRootWithoutRetain(),
+ *this);
+
+ return StoreRef(store, *this);
+}
+
+StoreRef RegionStoreManager::Bind(Store store, Loc L, SVal V) {
+ if (isa<loc::ConcreteInt>(L))
+ return StoreRef(store, *this);
+
+ // If we get here, the location should be a region.
+ const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
+
+ // Check if the region is a struct region.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
+ if (TR->getValueType()->isStructureOrClassType())
+ return BindStruct(store, TR, V);
+
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ if (ER->getIndex().isZeroConstant()) {
+ if (const TypedRegion *superR =
+ dyn_cast<TypedRegion>(ER->getSuperRegion())) {
+ QualType superTy = superR->getValueType();
+ // For now, just invalidate the fields of the struct/union/class.
+ // This is for test rdar_test_7185607 in misc-ps-region-store.m.
+ // FIXME: Precisely handle the fields of the record.
+ if (superTy->isStructureOrClassType())
+ return KillStruct(store, superR, UnknownVal());
+ }
+ }
+ }
+ else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ // Binding directly to a symbolic region should be treated as binding
+ // to element 0.
+ QualType T = SR->getSymbol()->getType(Ctx);
+
+ // FIXME: Is this the right way to handle symbols that are references?
+ if (const PointerType *PT = T->getAs<PointerType>())
+ T = PT->getPointeeType();
+ else
+ T = T->getAs<ReferenceType>()->getPointeeType();
+
+ R = GetElementZeroRegion(SR, T);
+ }
+
+ // Perform the binding.
+ RegionBindings B = GetRegionBindings(store);
+ return StoreRef(addBinding(B, R, BindingKey::Direct,
+ V).getRootWithoutRetain(), *this);
+}
+
+StoreRef RegionStoreManager::BindDecl(Store store, const VarRegion *VR,
+ SVal InitVal) {
+
+ QualType T = VR->getDecl()->getType();
+
+ if (T->isArrayType())
+ return BindArray(store, VR, InitVal);
+ if (T->isStructureOrClassType())
+ return BindStruct(store, VR, InitVal);
+
+ return Bind(store, svalBuilder.makeLoc(VR), InitVal);
+}
+
+// FIXME: this method should be merged into Bind().
+StoreRef RegionStoreManager::BindCompoundLiteral(Store store,
+ const CompoundLiteralExpr *CL,
+ const LocationContext *LC,
+ SVal V) {
+ return Bind(store, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)),
+ V);
+}
+
+StoreRef RegionStoreManager::setImplicitDefaultValue(Store store,
+ const MemRegion *R,
+ QualType T) {
+ RegionBindings B = GetRegionBindings(store);
+ SVal V;
+
+ if (Loc::isLocType(T))
+ V = svalBuilder.makeNull();
+ else if (T->isIntegerType())
+ V = svalBuilder.makeZeroVal(T);
+ else if (T->isStructureOrClassType() || T->isArrayType()) {
+ // Set the default value to a zero constant when it is a structure
+ // or array. The type doesn't really matter.
+ V = svalBuilder.makeZeroVal(Ctx.IntTy);
+ }
+ else {
+ return StoreRef(store, *this);
+ }
+
+ return StoreRef(addBinding(B, R, BindingKey::Default,
+ V).getRootWithoutRetain(), *this);
+}
+
+StoreRef RegionStoreManager::BindArray(Store store, const TypedRegion* R,
+ SVal Init) {
+
+ const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
+ QualType ElementTy = AT->getElementType();
+ Optional<uint64_t> Size;
+
+ if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
+ Size = CAT->getSize().getZExtValue();
+
+ // Check if the init expr is a string literal.
+ if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
+ const StringRegion *S = cast<StringRegion>(MRV->getRegion());
+
+ // Treat the string as a lazy compound value.
+ nonloc::LazyCompoundVal LCV =
+ cast<nonloc::LazyCompoundVal>(svalBuilder.makeLazyCompoundVal(store, S));
+ return CopyLazyBindings(LCV, store, R);
+ }
+
+ // Handle lazy compound values.
+ if (nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&Init))
+ return CopyLazyBindings(*LCV, store, R);
+
+ // Remaining case: explicit compound values.
+
+ if (Init.isUnknown())
+ return setImplicitDefaultValue(store, R, ElementTy);
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+ uint64_t i = 0;
+
+ StoreRef newStore(store, *this);
+ for (; Size.hasValue() ? i < Size.getValue() : true ; ++i, ++VI) {
+ // The init list might be shorter than the array length.
+ if (VI == VE)
+ break;
+
+ const NonLoc &Idx = svalBuilder.makeArrayIndex(i);
+ const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
+
+ if (ElementTy->isStructureOrClassType())
+ newStore = BindStruct(newStore.getStore(), ER, *VI);
+ else if (ElementTy->isArrayType())
+ newStore = BindArray(newStore.getStore(), ER, *VI);
+ else
+ newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(ER), *VI);
+ }
+
+ // If the init list is shorter than the array length, set the
+ // array default value.
+ if (Size.hasValue() && i < Size.getValue())
+ newStore = setImplicitDefaultValue(newStore.getStore(), R, ElementTy);
+
+ return newStore;
+}
+
+StoreRef RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
+ SVal V) {
+
+ if (!Features.supportsFields())
+ return StoreRef(store, *this);
+
+ QualType T = R->getValueType();
+ assert(T->isStructureOrClassType());
+
+ const RecordType* RT = T->getAs<RecordType>();
+ RecordDecl* RD = RT->getDecl();
+
+ if (!RD->isDefinition())
+ return StoreRef(store, *this);
+
+ // Handle lazy compound values.
+ if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
+ return CopyLazyBindings(*LCV, store, R);
+
+ // We may get non-CompoundVal accidentally due to imprecise cast logic or
+ // that we are binding symbolic struct value. Kill the field values, and if
+ // the value is symbolic go and bind it as a "default" binding.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
+ SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
+ return KillStruct(store, R, SV);
+ }
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+
+ RecordDecl::field_iterator FI, FE;
+ StoreRef newStore(store, *this);
+
+ for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) {
+
+ if (VI == VE)
+ break;
+
+ QualType FTy = (*FI)->getType();
+ const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
+
+ if (FTy->isArrayType())
+ newStore = BindArray(newStore.getStore(), FR, *VI);
+ else if (FTy->isStructureOrClassType())
+ newStore = BindStruct(newStore.getStore(), FR, *VI);
+ else
+ newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(FR), *VI);
+ }
+
+ // There may be fewer values in the initialize list than the fields of struct.
+ if (FI != FE) {
+ RegionBindings B = GetRegionBindings(newStore.getStore());
+ B = addBinding(B, R, BindingKey::Default, svalBuilder.makeIntVal(0, false));
+ newStore = StoreRef(B.getRootWithoutRetain(), *this);
+ }
+
+ return newStore;
+}
+
+StoreRef RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
+ SVal DefaultVal) {
+ BindingKey key = BindingKey::Make(R, BindingKey::Default);
+
+ // The BindingKey may be "invalid" if we cannot handle the region binding
+ // explicitly. One example is something like array[index], where index
+ // is a symbolic value. In such cases, we want to invalidate the entire
+ // array, as the index assignment could have been to any element. In
+ // the case of nested symbolic indices, we need to march up the region
+ // hierarchy untile we reach a region whose binding we can reason about.
+ const SubRegion *subReg = R;
+
+ while (!key.isValid()) {
+ if (const SubRegion *tmp = dyn_cast<SubRegion>(subReg->getSuperRegion())) {
+ subReg = tmp;
+ key = BindingKey::Make(tmp, BindingKey::Default);
+ }
+ else
+ break;
+ }
+
+ // Remove the old bindings, using 'subReg' as the root of all regions
+ // we will invalidate.
+ RegionBindings B = GetRegionBindings(store);
+ llvm::OwningPtr<RegionStoreSubRegionMap>
+ SubRegions(getRegionStoreSubRegionMap(store));
+ RemoveSubRegionBindings(B, subReg, *SubRegions);
+
+ // Set the default value of the struct region to "unknown".
+ if (!key.isValid())
+ return StoreRef(B.getRootWithoutRetain(), *this);
+
+ return StoreRef(addBinding(B, key, DefaultVal).getRootWithoutRetain(), *this);
+}
+
+StoreRef RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
+ Store store,
+ const TypedRegion *R) {
+
+ // Nuke the old bindings stemming from R.
+ RegionBindings B = GetRegionBindings(store);
+
+ llvm::OwningPtr<RegionStoreSubRegionMap>
+ SubRegions(getRegionStoreSubRegionMap(store));
+
+ // B and DVM are updated after the call to RemoveSubRegionBindings.
+ RemoveSubRegionBindings(B, R, *SubRegions.get());
+
+ // Now copy the bindings. This amounts to just binding 'V' to 'R'. This
+ // results in a zero-copy algorithm.
+ return StoreRef(addBinding(B, R, BindingKey::Direct,
+ V).getRootWithoutRetain(), *this);
+}
+
+//===----------------------------------------------------------------------===//
+// "Raw" retrievals and bindings.
+//===----------------------------------------------------------------------===//
+
+
+RegionBindings RegionStoreManager::addBinding(RegionBindings B, BindingKey K,
+ SVal V) {
+ if (!K.isValid())
+ return B;
+ return RBFactory.add(B, K, V);
+}
+
+RegionBindings RegionStoreManager::addBinding(RegionBindings B,
+ const MemRegion *R,
+ BindingKey::Kind k, SVal V) {
+ return addBinding(B, BindingKey::Make(R, k), V);
+}
+
+const SVal *RegionStoreManager::lookup(RegionBindings B, BindingKey K) {
+ if (!K.isValid())
+ return NULL;
+ return B.lookup(K);
+}
+
+const SVal *RegionStoreManager::lookup(RegionBindings B,
+ const MemRegion *R,
+ BindingKey::Kind k) {
+ return lookup(B, BindingKey::Make(R, k));
+}
+
+RegionBindings RegionStoreManager::removeBinding(RegionBindings B,
+ BindingKey K) {
+ if (!K.isValid())
+ return B;
+ return RBFactory.remove(B, K);
+}
+
+RegionBindings RegionStoreManager::removeBinding(RegionBindings B,
+ const MemRegion *R,
+ BindingKey::Kind k){
+ return removeBinding(B, BindingKey::Make(R, k));
+}
+
+//===----------------------------------------------------------------------===//
+// State pruning.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class removeDeadBindingsWorker :
+ public ClusterAnalysis<removeDeadBindingsWorker> {
+ llvm::SmallVector<const SymbolicRegion*, 12> Postponed;
+ SymbolReaper &SymReaper;
+ const StackFrameContext *CurrentLCtx;
+
+public:
+ removeDeadBindingsWorker(RegionStoreManager &rm, GRStateManager &stateMgr,
+ RegionBindings b, SymbolReaper &symReaper,
+ const StackFrameContext *LCtx)
+ : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b,
+ /* includeGlobals = */ false),
+ SymReaper(symReaper), CurrentLCtx(LCtx) {}
+
+ // Called by ClusterAnalysis.
+ void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C);
+ void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
+
+ void VisitBindingKey(BindingKey K);
+ bool UpdatePostponed();
+ void VisitBinding(SVal V);
+};
+}
+
+void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
+ RegionCluster &C) {
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
+ if (SymReaper.isLive(VR))
+ AddToWorkList(baseR, C);
+
+ return;
+ }
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
+ if (SymReaper.isLive(SR->getSymbol()))
+ AddToWorkList(SR, C);
+ else
+ Postponed.push_back(SR);
+
+ return;
+ }
+
+ if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
+ AddToWorkList(baseR, C);
+ return;
+ }
+
+ // CXXThisRegion in the current or parent location context is live.
+ if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
+ const StackArgumentsSpaceRegion *StackReg =
+ cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
+ const StackFrameContext *RegCtx = StackReg->getStackFrame();
+ if (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx))
+ AddToWorkList(TR, C);
+ }
+}
+
+void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
+ BindingKey *I, BindingKey *E) {
+ for ( ; I != E; ++I)
+ VisitBindingKey(*I);
+}
+
+void removeDeadBindingsWorker::VisitBinding(SVal V) {
+ // Is it a LazyCompoundVal? All referenced regions are live as well.
+ if (const nonloc::LazyCompoundVal *LCS =
+ dyn_cast<nonloc::LazyCompoundVal>(&V)) {
+
+ const MemRegion *LazyR = LCS->getRegion();
+ RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore());
+ for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
+ const SubRegion *baseR = dyn_cast<SubRegion>(RI.getKey().getRegion());
+ if (baseR && baseR->isSubRegionOf(LazyR))
+ VisitBinding(RI.getData());
+ }
+ return;
+ }
+
+ // If V is a region, then add it to the worklist.
+ if (const MemRegion *R = V.getAsRegion())
+ AddToWorkList(R);
+
+ // Update the set of live symbols.
+ for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end();
+ SI!=SE;++SI)
+ SymReaper.markLive(*SI);
+}
+
+void removeDeadBindingsWorker::VisitBindingKey(BindingKey K) {
+ const MemRegion *R = K.getRegion();
+
+ // Mark this region "live" by adding it to the worklist. This will cause
+ // use to visit all regions in the cluster (if we haven't visited them
+ // already).
+ if (AddToWorkList(R)) {
+ // Mark the symbol for any live SymbolicRegion as "live". This means we
+ // should continue to track that symbol.
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
+ SymReaper.markLive(SymR->getSymbol());
+
+ // For BlockDataRegions, enqueue the VarRegions for variables marked
+ // with __block (passed-by-reference).
+ // via BlockDeclRefExprs.
+ if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
+ for (BlockDataRegion::referenced_vars_iterator
+ RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
+ RI != RE; ++RI) {
+ if ((*RI)->getDecl()->getAttr<BlocksAttr>())
+ AddToWorkList(*RI);
+ }
+
+ // No possible data bindings on a BlockDataRegion.
+ return;
+ }
+ }
+
+ // Visit the data binding for K.
+ if (const SVal *V = RM.lookup(B, K))
+ VisitBinding(*V);
+}
+
+bool removeDeadBindingsWorker::UpdatePostponed() {
+ // See if any postponed SymbolicRegions are actually live now, after
+ // having done a scan.
+ bool changed = false;
+
+ for (llvm::SmallVectorImpl<const SymbolicRegion*>::iterator
+ I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) {
+ if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(*I)) {
+ if (SymReaper.isLive(SR->getSymbol())) {
+ changed |= AddToWorkList(SR);
+ *I = NULL;
+ }
+ }
+ }
+
+ return changed;
+}
+
+StoreRef RegionStoreManager::removeDeadBindings(Store store,
+ const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
+{
+ RegionBindings B = GetRegionBindings(store);
+ removeDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
+ W.GenerateClusters();
+
+ // Enqueue the region roots onto the worklist.
+ for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
+ E=RegionRoots.end(); I!=E; ++I)
+ W.AddToWorkList(*I);
+
+ do W.RunWorkList(); while (W.UpdatePostponed());
+
+ // We have now scanned the store, marking reachable regions and symbols
+ // as live. We now remove all the regions that are dead from the store
+ // as well as update DSymbols with the set symbols that are now dead.
+ for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ const BindingKey &K = I.getKey();
+
+ // If the cluster has been visited, we know the region has been marked.
+ if (W.isVisited(K.getRegion()))
+ continue;
+
+ // Remove the dead entry.
+ B = removeBinding(B, K);
+
+ // Mark all non-live symbols that this binding references as dead.
+ if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(K.getRegion()))
+ SymReaper.maybeDead(SymR->getSymbol());
+
+ SVal X = I.getData();
+ SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
+ for (; SI != SE; ++SI)
+ SymReaper.maybeDead(*SI);
+ }
+
+ return StoreRef(B.getRootWithoutRetain(), *this);
+}
+
+
+StoreRef RegionStoreManager::enterStackFrame(const GRState *state,
+ const StackFrameContext *frame) {
+ FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
+ FunctionDecl::param_const_iterator PI = FD->param_begin(),
+ PE = FD->param_end();
+ StoreRef store = StoreRef(state->getStore(), *this);
+
+ if (CallExpr const *CE = dyn_cast<CallExpr>(frame->getCallSite())) {
+ CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
+
+ // Copy the arg expression value to the arg variables. We check that
+ // PI != PE because the actual number of arguments may be different than
+ // the function declaration.
+ for (; AI != AE && PI != PE; ++AI, ++PI) {
+ SVal ArgVal = state->getSVal(*AI);
+ store = Bind(store.getStore(),
+ svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal);
+ }
+ } else if (const CXXConstructExpr *CE =
+ dyn_cast<CXXConstructExpr>(frame->getCallSite())) {
+ CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(),
+ AE = CE->arg_end();
+
+ // Copy the arg expression value to the arg variables.
+ for (; AI != AE; ++AI, ++PI) {
+ SVal ArgVal = state->getSVal(*AI);
+ store = Bind(store.getStore(),
+ svalBuilder.makeLoc(MRMgr.getVarRegion(*PI,frame)), ArgVal);
+ }
+ } else
+ assert(isa<CXXDestructorDecl>(frame->getDecl()));
+
+ return store;
+}
+
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,
+ const char* nl, const char *sep) {
+ RegionBindings B = GetRegionBindings(store);
+ OS << "Store (direct and default bindings):" << nl;
+
+ for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
+ OS << ' ' << I.getKey() << " : " << I.getData() << nl;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
new file mode 100644
index 0000000..b0fd497
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -0,0 +1,310 @@
+// SValBuilder.cpp - Basic class for all SValBuilder implementations -*- 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 SValBuilder, the base class for all (complete) SValBuilder
+// implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Basic SVal creation.
+//===----------------------------------------------------------------------===//
+
+DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType T) {
+ if (Loc::isLocType(T))
+ return makeNull();
+
+ if (T->isIntegerType())
+ return makeIntVal(0, T);
+
+ // FIXME: Handle floats.
+ // FIXME: Handle structs.
+ return UnknownVal();
+}
+
+
+NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& v, QualType T) {
+ // The Environment ensures we always get a persistent APSInt in
+ // BasicValueFactory, so we don't need to get the APSInt from
+ // BasicValueFactory again.
+ assert(!Loc::isLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
+}
+
+NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType T) {
+ assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
+ assert(!Loc::isLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
+}
+
+
+SVal SValBuilder::convertToArrayIndex(SVal V) {
+ if (V.isUnknownOrUndef())
+ return V;
+
+ // Common case: we have an appropriately sized integer.
+ if (nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&V)) {
+ const llvm::APSInt& I = CI->getValue();
+ if (I.getBitWidth() == ArrayIndexWidth && I.isSigned())
+ return V;
+ }
+
+ return evalCastNL(cast<NonLoc>(V), ArrayIndexTy);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getRegionValueSymbolVal(const TypedRegion* R) {
+ QualType T = R->getValueType();
+
+ if (!SymbolManager::canSymbolicate(T))
+ return UnknownVal();
+
+ SymbolRef sym = SymMgr.getRegionValueSymbol(R);
+
+ if (Loc::isLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
+
+DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *SymbolTag,
+ const Expr *E,
+ unsigned Count) {
+ QualType T = E->getType();
+
+ if (!SymbolManager::canSymbolicate(T))
+ return UnknownVal();
+
+ SymbolRef sym = SymMgr.getConjuredSymbol(E, Count, SymbolTag);
+
+ if (Loc::isLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
+
+DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *SymbolTag,
+ const Expr *E,
+ QualType T,
+ unsigned Count) {
+
+ if (!SymbolManager::canSymbolicate(T))
+ return UnknownVal();
+
+ SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count, SymbolTag);
+
+ if (Loc::isLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
+
+DefinedSVal SValBuilder::getMetadataSymbolVal(const void *SymbolTag,
+ const MemRegion *MR,
+ const Expr *E, QualType T,
+ unsigned Count) {
+ assert(SymbolManager::canSymbolicate(T) && "Invalid metadata symbol type");
+
+ SymbolRef sym = SymMgr.getMetadataSymbol(MR, E, T, Count, SymbolTag);
+
+ if (Loc::isLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
+
+DefinedOrUnknownSVal
+SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
+ const TypedRegion *R) {
+ QualType T = R->getValueType();
+
+ if (!SymbolManager::canSymbolicate(T))
+ return UnknownVal();
+
+ SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, R);
+
+ if (Loc::isLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
+
+DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl* FD) {
+ return loc::MemRegionVal(MemMgr.getFunctionTextRegion(FD));
+}
+
+DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *D,
+ CanQualType locTy,
+ const LocationContext *LC) {
+ const BlockTextRegion *BC =
+ MemMgr.getBlockTextRegion(D, locTy, LC->getAnalysisContext());
+ const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, LC);
+ return loc::MemRegionVal(BD);
+}
+
+//===----------------------------------------------------------------------===//
+
+SVal SValBuilder::evalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
+ SVal L, SVal R, QualType T) {
+
+ if (L.isUndef() || R.isUndef())
+ return UndefinedVal();
+
+ if (L.isUnknown() || R.isUnknown())
+ return UnknownVal();
+
+ if (isa<Loc>(L)) {
+ if (isa<Loc>(R))
+ return evalBinOpLL(ST, Op, cast<Loc>(L), cast<Loc>(R), T);
+
+ return evalBinOpLN(ST, Op, cast<Loc>(L), cast<NonLoc>(R), T);
+ }
+
+ if (isa<Loc>(R)) {
+ // Support pointer arithmetic where the addend is on the left
+ // and the pointer on the right.
+ assert(Op == BO_Add);
+
+ // Commute the operands.
+ return evalBinOpLN(ST, Op, cast<Loc>(R), cast<NonLoc>(L), T);
+ }
+
+ return evalBinOpNN(ST, Op, cast<NonLoc>(L), cast<NonLoc>(R), T);
+}
+
+DefinedOrUnknownSVal SValBuilder::evalEQ(const GRState *ST,
+ DefinedOrUnknownSVal L,
+ DefinedOrUnknownSVal R) {
+ return cast<DefinedOrUnknownSVal>(evalBinOp(ST, BO_EQ, L, R,
+ Context.IntTy));
+}
+
+// FIXME: should rewrite according to the cast kind.
+SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
+ if (val.isUnknownOrUndef() || castTy == originalTy)
+ return val;
+
+ // For const casts, just propagate the value.
+ if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
+ if (Context.hasSameUnqualifiedType(castTy, originalTy))
+ return val;
+
+ // Check for casts to real or complex numbers. We don't handle these at all
+ // right now.
+ if (castTy->isFloatingType() || castTy->isAnyComplexType())
+ return UnknownVal();
+
+ // Check for casts from integers to integers.
+ if (castTy->isIntegerType() && originalTy->isIntegerType())
+ return evalCastNL(cast<NonLoc>(val), castTy);
+
+ // Check for casts from pointers to integers.
+ if (castTy->isIntegerType() && Loc::isLocType(originalTy))
+ return evalCastL(cast<Loc>(val), castTy);
+
+ // Check for casts from integers to pointers.
+ if (Loc::isLocType(castTy) && originalTy->isIntegerType()) {
+ if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
+ if (const MemRegion *R = LV->getLoc().getAsRegion()) {
+ StoreManager &storeMgr = StateMgr.getStoreManager();
+ R = storeMgr.castRegion(R, castTy);
+ return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
+ }
+ return LV->getLoc();
+ }
+ goto DispatchCast;
+ }
+
+ // Just pass through function and block pointers.
+ if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
+ assert(Loc::isLocType(castTy));
+ return val;
+ }
+
+ // Check for casts from array type to another type.
+ if (originalTy->isArrayType()) {
+ // We will always decay to a pointer.
+ val = StateMgr.ArrayToPointer(cast<Loc>(val));
+
+ // Are we casting from an array to a pointer? If so just pass on
+ // the decayed value.
+ if (castTy->isPointerType())
+ return val;
+
+ // Are we casting from an array to an integer? If so, cast the decayed
+ // pointer value to an integer.
+ assert(castTy->isIntegerType());
+
+ // FIXME: Keep these here for now in case we decide soon that we
+ // need the original decayed type.
+ // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
+ // QualType pointerTy = C.getPointerType(elemTy);
+ return evalCastL(cast<Loc>(val), castTy);
+ }
+
+ // Check for casts from a region to a specific type.
+ if (const MemRegion *R = val.getAsRegion()) {
+ // FIXME: We should handle the case where we strip off view layers to get
+ // to a desugared type.
+
+ if (!Loc::isLocType(castTy)) {
+ // FIXME: There can be gross cases where one casts the result of a function
+ // (that returns a pointer) to some other value that happens to fit
+ // within that pointer value. We currently have no good way to
+ // model such operations. When this happens, the underlying operation
+ // is that the caller is reasoning about bits. Conceptually we are
+ // layering a "view" of a location on top of those bits. Perhaps
+ // we need to be more lazy about mutual possible views, even on an
+ // SVal? This may be necessary for bit-level reasoning as well.
+ return UnknownVal();
+ }
+
+ // We get a symbolic function pointer for a dereference of a function
+ // pointer, but it is of function type. Example:
+
+ // struct FPRec {
+ // void (*my_func)(int * x);
+ // };
+ //
+ // int bar(int x);
+ //
+ // int f1_a(struct FPRec* foo) {
+ // int x;
+ // (*foo->my_func)(&x);
+ // return bar(x)+1; // no-warning
+ // }
+
+ assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
+ originalTy->isBlockPointerType() || castTy->isReferenceType());
+
+ StoreManager &storeMgr = StateMgr.getStoreManager();
+
+ // Delegate to store manager to get the result of casting a region to a
+ // different type. If the MemRegion* returned is NULL, this expression
+ // Evaluates to UnknownVal.
+ R = storeMgr.castRegion(R, castTy);
+ return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
+ }
+
+DispatchCast:
+ // All other cases.
+ return isa<Loc>(val) ? evalCastL(cast<Loc>(val), castTy)
+ : evalCastNL(cast<NonLoc>(val), castTy);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
new file mode 100644
index 0000000..4614e34
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -0,0 +1,378 @@
+//= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- 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 SVal, Loc, and NonLoc, classes that represent
+// abstract r-values for use with path-sensitive value tracking.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/IdentifierTable.h"
+
+using namespace clang;
+using namespace ento;
+using llvm::dyn_cast;
+using llvm::cast;
+using llvm::APSInt;
+
+//===----------------------------------------------------------------------===//
+// Symbol iteration within an SVal.
+//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+bool SVal::hasConjuredSymbol() const {
+ if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
+ SymbolRef sym = SV->getSymbol();
+ if (isa<SymbolConjured>(sym))
+ return true;
+ }
+
+ if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
+ const MemRegion *R = RV->getRegion();
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+ SymbolRef sym = SR->getSymbol();
+ if (isa<SymbolConjured>(sym))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+const FunctionDecl *SVal::getAsFunctionDecl() const {
+ if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
+ const MemRegion* R = X->getRegion();
+ if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
+ return CTR->getDecl();
+ }
+
+ return NULL;
+}
+
+/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
+/// wraps a symbol, return that SymbolRef. Otherwise return 0.
+// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
+SymbolRef SVal::getAsLocSymbol() const {
+ if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this))
+ return X->getLoc().getAsLocSymbol();
+
+ if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
+ const MemRegion *R = X->stripCasts();
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
+ return SymR->getSymbol();
+ }
+ return NULL;
+}
+
+/// Get the symbol in the SVal or its base region.
+SymbolRef SVal::getLocSymbolInBase() const {
+ const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this);
+
+ if (!X)
+ return 0;
+
+ const MemRegion *R = X->getRegion();
+
+ while (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR))
+ return SymR->getSymbol();
+ else
+ R = SR->getSuperRegion();
+ }
+
+ return 0;
+}
+
+/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
+/// Otherwise return 0.
+// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
+SymbolRef SVal::getAsSymbol() const {
+ if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
+ return X->getSymbol();
+
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
+ return Y;
+
+ return getAsLocSymbol();
+}
+
+/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+/// return that expression. Otherwise return NULL.
+const SymExpr *SVal::getAsSymbolicExpression() const {
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ return X->getSymbolicExpression();
+
+ return getAsSymbol();
+}
+
+const MemRegion *SVal::getAsRegion() const {
+ if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
+ return X->getRegion();
+
+ if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this)) {
+ return X->getLoc().getAsRegion();
+ }
+
+ return 0;
+}
+
+const MemRegion *loc::MemRegionVal::stripCasts() const {
+ const MemRegion *R = getRegion();
+ return R ? R->StripCasts() : NULL;
+}
+
+bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
+ return itr == X.itr;
+}
+
+bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
+ return itr != X.itr;
+}
+
+SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
+ itr.push_back(SE);
+ while (!isa<SymbolData>(itr.back())) expand();
+}
+
+SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
+ assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
+ assert(isa<SymbolData>(itr.back()));
+ itr.pop_back();
+ if (!itr.empty())
+ while (!isa<SymbolData>(itr.back())) expand();
+ return *this;
+}
+
+SymbolRef SVal::symbol_iterator::operator*() {
+ assert(!itr.empty() && "attempting to dereference an 'end' iterator");
+ return cast<SymbolData>(itr.back());
+}
+
+void SVal::symbol_iterator::expand() {
+ const SymExpr *SE = itr.back();
+ itr.pop_back();
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+ itr.push_back(SIE->getLHS());
+ return;
+ }
+ else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
+ itr.push_back(SSE->getLHS());
+ itr.push_back(SSE->getRHS());
+ return;
+ }
+
+ assert(false && "unhandled expansion case");
+}
+
+const void *nonloc::LazyCompoundVal::getStore() const {
+ return static_cast<const LazyCompoundValData*>(Data)->getStore();
+}
+
+const TypedRegion *nonloc::LazyCompoundVal::getRegion() const {
+ return static_cast<const LazyCompoundValData*>(Data)->getRegion();
+}
+
+//===----------------------------------------------------------------------===//
+// Other Iterators.
+//===----------------------------------------------------------------------===//
+
+nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
+ return getValue()->begin();
+}
+
+nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
+ return getValue()->end();
+}
+
+//===----------------------------------------------------------------------===//
+// Useful predicates.
+//===----------------------------------------------------------------------===//
+
+bool SVal::isConstant() const {
+ return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
+}
+
+bool SVal::isConstant(int I) const {
+ if (isa<loc::ConcreteInt>(*this))
+ return cast<loc::ConcreteInt>(*this).getValue() == I;
+ else if (isa<nonloc::ConcreteInt>(*this))
+ return cast<nonloc::ConcreteInt>(*this).getValue() == I;
+ else
+ return false;
+}
+
+bool SVal::isZeroConstant() const {
+ return isConstant(0);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Transfer function dispatch for Non-Locs.
+//===----------------------------------------------------------------------===//
+
+SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
+ BinaryOperator::Opcode Op,
+ const nonloc::ConcreteInt& R) const {
+ const llvm::APSInt* X =
+ svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
+
+ if (X)
+ return nonloc::ConcreteInt(*X);
+ else
+ return UndefinedVal();
+}
+
+nonloc::ConcreteInt
+nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
+ return svalBuilder.makeIntVal(~getValue());
+}
+
+nonloc::ConcreteInt
+nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
+ return svalBuilder.makeIntVal(-getValue());
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function dispatch for Locs.
+//===----------------------------------------------------------------------===//
+
+SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
+ BinaryOperator::Opcode Op,
+ const loc::ConcreteInt& R) const {
+
+ assert (Op == BO_Add || Op == BO_Sub ||
+ (Op >= BO_LT && Op <= BO_NE));
+
+ const llvm::APSInt* X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
+
+ if (X)
+ return loc::ConcreteInt(*X);
+ else
+ return UndefinedVal();
+}
+
+//===----------------------------------------------------------------------===//
+// Pretty-Printing.
+//===----------------------------------------------------------------------===//
+
+void SVal::dump() const { dumpToStream(llvm::errs()); }
+
+void SVal::dumpToStream(llvm::raw_ostream& os) const {
+ switch (getBaseKind()) {
+ case UnknownKind:
+ os << "Unknown";
+ break;
+ case NonLocKind:
+ cast<NonLoc>(this)->dumpToStream(os);
+ break;
+ case LocKind:
+ cast<Loc>(this)->dumpToStream(os);
+ break;
+ case UndefinedKind:
+ os << "Undefined";
+ break;
+ default:
+ assert (false && "Invalid SVal.");
+ }
+}
+
+void NonLoc::dumpToStream(llvm::raw_ostream& os) const {
+ switch (getSubKind()) {
+ case nonloc::ConcreteIntKind: {
+ const nonloc::ConcreteInt& C = *cast<nonloc::ConcreteInt>(this);
+ if (C.getValue().isUnsigned())
+ os << C.getValue().getZExtValue();
+ else
+ os << C.getValue().getSExtValue();
+ os << ' ' << (C.getValue().isUnsigned() ? 'U' : 'S')
+ << C.getValue().getBitWidth() << 'b';
+ break;
+ }
+ case nonloc::SymbolValKind:
+ os << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
+ break;
+ case nonloc::SymExprValKind: {
+ const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
+ const SymExpr *SE = C.getSymbolicExpression();
+ os << SE;
+ break;
+ }
+ case nonloc::LocAsIntegerKind: {
+ const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
+ os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
+ break;
+ }
+ case nonloc::CompoundValKind: {
+ const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
+ os << "compoundVal{";
+ bool first = true;
+ for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
+ if (first) {
+ os << ' '; first = false;
+ }
+ else
+ os << ", ";
+
+ (*I).dumpToStream(os);
+ }
+ os << "}";
+ break;
+ }
+ case nonloc::LazyCompoundValKind: {
+ const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
+ os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
+ << ',' << C.getRegion()
+ << '}';
+ break;
+ }
+ default:
+ assert (false && "Pretty-printed not implemented for this NonLoc.");
+ break;
+ }
+}
+
+void Loc::dumpToStream(llvm::raw_ostream& os) const {
+ switch (getSubKind()) {
+ case loc::ConcreteIntKind:
+ os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
+ break;
+ case loc::GotoLabelKind:
+ os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getName();
+ break;
+ case loc::MemRegionKind:
+ os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
+ break;
+ case loc::ObjCPropRefKind: {
+ const ObjCPropertyRefExpr *E = cast<loc::ObjCPropRef>(this)->getPropRefExpr();
+ os << "objc-prop{";
+ if (E->isSuperReceiver())
+ os << "super.";
+ else if (E->getBase())
+ os << "<base>.";
+
+ if (E->isImplicitProperty())
+ os << E->getImplicitPropertyGetter()->getSelector().getAsString();
+ else
+ os << E->getExplicitProperty()->getName();
+
+ os << "}";
+ break;
+ }
+ default:
+ assert(false && "Pretty-printing not implemented for this Loc.");
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
new file mode 100644
index 0000000..e0b61ab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -0,0 +1,303 @@
+//== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines SimpleConstraintManager, a class that holds code shared
+// between BasicConstraintManager and RangeConstraintManager.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SimpleConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
+
+namespace clang {
+
+namespace ento {
+
+SimpleConstraintManager::~SimpleConstraintManager() {}
+
+bool SimpleConstraintManager::canReasonAbout(SVal X) const {
+ if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) {
+ const SymExpr *SE = SymVal->getSymbolicExpression();
+
+ if (isa<SymbolData>(SE))
+ return true;
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+ switch (SIE->getOpcode()) {
+ // We don't reason yet about bitwise-constraints on symbolic values.
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ return false;
+ // We don't reason yet about these arithmetic constraints on
+ // symbolic values.
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Shl:
+ case BO_Shr:
+ return false;
+ // All other cases.
+ default:
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+const GRState *SimpleConstraintManager::assume(const GRState *state,
+ DefinedSVal Cond,
+ bool Assumption) {
+ if (isa<NonLoc>(Cond))
+ return assume(state, cast<NonLoc>(Cond), Assumption);
+ else
+ return assume(state, cast<Loc>(Cond), Assumption);
+}
+
+const GRState *SimpleConstraintManager::assume(const GRState *state, Loc cond,
+ bool assumption) {
+ state = assumeAux(state, cond, assumption);
+ return SU.processAssume(state, cond, assumption);
+}
+
+const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
+ Loc Cond, bool Assumption) {
+
+ BasicValueFactory &BasicVals = state->getBasicVals();
+
+ switch (Cond.getSubKind()) {
+ default:
+ assert (false && "'Assume' not implemented for this Loc.");
+ return state;
+
+ case loc::MemRegionKind: {
+ // FIXME: Should this go into the storemanager?
+
+ const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
+ const SubRegion *SubR = dyn_cast<SubRegion>(R);
+
+ while (SubR) {
+ // FIXME: now we only find the first symbolic region.
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
+ const llvm::APSInt &zero = BasicVals.getZeroWithPtrWidth();
+ if (Assumption)
+ return assumeSymNE(state, SymR->getSymbol(), zero, zero);
+ else
+ return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
+ }
+ SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
+ }
+
+ // FALL-THROUGH.
+ }
+
+ case loc::GotoLabelKind:
+ return Assumption ? state : NULL;
+
+ case loc::ConcreteIntKind: {
+ bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
+ }
+ } // end switch
+}
+
+const GRState *SimpleConstraintManager::assume(const GRState *state,
+ NonLoc cond,
+ bool assumption) {
+ state = assumeAux(state, cond, assumption);
+ return SU.processAssume(state, cond, assumption);
+}
+
+static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
+ // FIXME: This should probably be part of BinaryOperator, since this isn't
+ // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.)
+ switch (op) {
+ default:
+ assert(false && "Invalid opcode.");
+ case BO_LT: return BO_GE;
+ case BO_GT: return BO_LE;
+ case BO_LE: return BO_GT;
+ case BO_GE: return BO_LT;
+ case BO_EQ: return BO_NE;
+ case BO_NE: return BO_EQ;
+ }
+}
+
+const GRState *SimpleConstraintManager::assumeAux(const GRState *state,
+ NonLoc Cond,
+ bool Assumption) {
+
+ // We cannot reason about SymSymExprs,
+ // and can only reason about some SymIntExprs.
+ if (!canReasonAbout(Cond)) {
+ // Just return the current state indicating that the path is feasible.
+ // This may be an over-approximation of what is possible.
+ return state;
+ }
+
+ BasicValueFactory &BasicVals = state->getBasicVals();
+ SymbolManager &SymMgr = state->getSymbolManager();
+
+ switch (Cond.getSubKind()) {
+ default:
+ assert(false && "'Assume' not implemented for this NonLoc");
+
+ case nonloc::SymbolValKind: {
+ nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
+ SymbolRef sym = SV.getSymbol();
+ QualType T = SymMgr.getType(sym);
+ const llvm::APSInt &zero = BasicVals.getValue(0, T);
+ if (Assumption)
+ return assumeSymNE(state, sym, zero, zero);
+ else
+ return assumeSymEQ(state, sym, zero, zero);
+ }
+
+ case nonloc::SymExprValKind: {
+ nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
+
+ // For now, we only handle expressions whose RHS is an integer.
+ // All other expressions are assumed to be feasible.
+ const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression());
+ if (!SE)
+ return state;
+
+ BinaryOperator::Opcode op = SE->getOpcode();
+ // Implicitly compare non-comparison expressions to 0.
+ if (!BinaryOperator::isComparisonOp(op)) {
+ QualType T = SymMgr.getType(SE);
+ const llvm::APSInt &zero = BasicVals.getValue(0, T);
+ op = (Assumption ? BO_NE : BO_EQ);
+ return assumeSymRel(state, SE, op, zero);
+ }
+
+ // From here on out, op is the real comparison we'll be testing.
+ if (!Assumption)
+ op = NegateComparison(op);
+
+ return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
+ }
+
+ case nonloc::ConcreteIntKind: {
+ bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
+ }
+
+ case nonloc::LocAsIntegerKind:
+ return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
+ Assumption);
+ } // end switch
+}
+
+const GRState *SimpleConstraintManager::assumeSymRel(const GRState *state,
+ const SymExpr *LHS,
+ BinaryOperator::Opcode op,
+ const llvm::APSInt& Int) {
+ assert(BinaryOperator::isComparisonOp(op) &&
+ "Non-comparison ops should be rewritten as comparisons to zero.");
+
+ // We only handle simple comparisons of the form "$sym == constant"
+ // or "($sym+constant1) == constant2".
+ // The adjustment is "constant1" in the above expression. It's used to
+ // "slide" the solution range around for modular arithmetic. For example,
+ // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
+ // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
+ // the subclasses of SimpleConstraintManager to handle the adjustment.
+ llvm::APSInt Adjustment;
+
+ // First check if the LHS is a simple symbol reference.
+ SymbolRef Sym = dyn_cast<SymbolData>(LHS);
+ if (Sym) {
+ Adjustment = 0;
+ } else {
+ // Next, see if it's a "($sym+constant1)" expression.
+ const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS);
+
+ // We don't handle "($sym1+$sym2)".
+ // Give up and assume the constraint is feasible.
+ if (!SE)
+ return state;
+
+ // We don't handle "(<expr>+constant1)".
+ // Give up and assume the constraint is feasible.
+ Sym = dyn_cast<SymbolData>(SE->getLHS());
+ if (!Sym)
+ return state;
+
+ // Get the constant out of the expression "($sym+constant1)".
+ switch (SE->getOpcode()) {
+ case BO_Add:
+ Adjustment = SE->getRHS();
+ break;
+ case BO_Sub:
+ Adjustment = -SE->getRHS();
+ break;
+ default:
+ // We don't handle non-additive operators.
+ // Give up and assume the constraint is feasible.
+ return state;
+ }
+ }
+
+ // FIXME: This next section is a hack. It silently converts the integers to
+ // be of the same type as the symbol, which is not always correct. Really the
+ // comparisons should be performed using the Int's type, then mapped back to
+ // the symbol's range of values.
+ GRStateManager &StateMgr = state->getStateManager();
+ ASTContext &Ctx = StateMgr.getContext();
+
+ QualType T = Sym->getType(Ctx);
+ assert(T->isIntegerType() || Loc::isLocType(T));
+ unsigned bitwidth = Ctx.getTypeSize(T);
+ bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
+
+ // Convert the adjustment.
+ Adjustment.setIsUnsigned(isSymUnsigned);
+ Adjustment = Adjustment.extOrTrunc(bitwidth);
+
+ // Convert the right-hand side integer.
+ llvm::APSInt ConvertedInt(Int, isSymUnsigned);
+ ConvertedInt = ConvertedInt.extOrTrunc(bitwidth);
+
+ switch (op) {
+ default:
+ // No logic yet for other operators. assume the constraint is feasible.
+ return state;
+
+ case BO_EQ:
+ return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
+
+ case BO_NE:
+ return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
+
+ case BO_GT:
+ return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
+
+ case BO_GE:
+ return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
+
+ case BO_LT:
+ return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
+
+ case BO_LE:
+ return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
+ } // end switch
+}
+
+} // end of namespace ento
+
+} // end of namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
new file mode 100644
index 0000000..a2952af
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -0,0 +1,93 @@
+//== SimpleConstraintManager.h ----------------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Code shared between BasicConstraintManager and RangeConstraintManager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H
+#define LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+
+namespace clang {
+
+namespace ento {
+
+class SimpleConstraintManager : public ConstraintManager {
+ SubEngine &SU;
+public:
+ SimpleConstraintManager(SubEngine &subengine) : SU(subengine) {}
+ virtual ~SimpleConstraintManager();
+
+ //===------------------------------------------------------------------===//
+ // Common implementation for the interface provided by ConstraintManager.
+ //===------------------------------------------------------------------===//
+
+ bool canReasonAbout(SVal X) const;
+
+ const GRState *assume(const GRState *state, DefinedSVal Cond,
+ bool Assumption);
+
+ const GRState *assume(const GRState *state, Loc Cond, bool Assumption);
+
+ const GRState *assume(const GRState *state, NonLoc Cond, bool Assumption);
+
+ const GRState *assumeSymRel(const GRState *state,
+ const SymExpr *LHS,
+ BinaryOperator::Opcode op,
+ const llvm::APSInt& Int);
+
+protected:
+
+ //===------------------------------------------------------------------===//
+ // Interface that subclasses must implement.
+ //===------------------------------------------------------------------===//
+
+ // Each of these is of the form "$sym+Adj <> V", where "<>" is the comparison
+ // operation for the method being invoked.
+ virtual const GRState *assumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ virtual const GRState *assumeSymEQ(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ virtual const GRState *assumeSymLT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ virtual const GRState *assumeSymGT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ virtual const GRState *assumeSymLE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ virtual const GRState *assumeSymGE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V,
+ const llvm::APSInt& Adjustment) = 0;
+
+ //===------------------------------------------------------------------===//
+ // Internal implementation.
+ //===------------------------------------------------------------------===//
+
+ const GRState *assumeAux(const GRState *state, Loc Cond,bool Assumption);
+
+ const GRState *assumeAux(const GRState *state, NonLoc Cond, bool Assumption);
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
new file mode 100644
index 0000000..9a46bd6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -0,0 +1,917 @@
+// SimpleSValBuilder.cpp - A basic SValBuilder -----------------------*- 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 SimpleSValBuilder, a basic implementation of SValBuilder.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class SimpleSValBuilder : public SValBuilder {
+protected:
+ virtual SVal evalCastNL(NonLoc val, QualType castTy);
+ virtual SVal evalCastL(Loc val, QualType castTy);
+
+public:
+ SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
+ GRStateManager &stateMgr)
+ : SValBuilder(alloc, context, stateMgr) {}
+ virtual ~SimpleSValBuilder() {}
+
+ virtual SVal evalMinus(NonLoc val);
+ virtual SVal evalComplement(NonLoc val);
+ virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy);
+ virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op,
+ Loc lhs, Loc rhs, QualType resultTy);
+ virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op,
+ Loc lhs, NonLoc rhs, QualType resultTy);
+
+ /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
+ /// (integer) value, that value is returned. Otherwise, returns NULL.
+ virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V);
+
+ SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
+ const llvm::APSInt &RHS, QualType resultTy);
+};
+} // end anonymous namespace
+
+SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
+ ASTContext &context,
+ GRStateManager &stateMgr) {
+ return new SimpleSValBuilder(alloc, context, stateMgr);
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function for Casts.
+//===----------------------------------------------------------------------===//
+
+SVal SimpleSValBuilder::evalCastNL(NonLoc val, QualType castTy) {
+
+ bool isLocType = Loc::isLocType(castTy);
+
+ if (nonloc::LocAsInteger *LI = dyn_cast<nonloc::LocAsInteger>(&val)) {
+ if (isLocType)
+ return LI->getLoc();
+
+ // FIXME: Correctly support promotions/truncations.
+ unsigned castSize = Context.getTypeSize(castTy);
+ if (castSize == LI->getNumBits())
+ return val;
+ return makeLocAsInteger(LI->getLoc(), castSize);
+ }
+
+ if (const SymExpr *se = val.getAsSymbolicExpression()) {
+ QualType T = Context.getCanonicalType(se->getType(Context));
+ if (T == Context.getCanonicalType(castTy))
+ return val;
+
+ // FIXME: Remove this hack when we support symbolic truncation/extension.
+ // HACK: If both castTy and T are integers, ignore the cast. This is
+ // not a permanent solution. Eventually we want to precisely handle
+ // extension/truncation of symbolic integers. This prevents us from losing
+ // precision when we assign 'x = y' and 'y' is symbolic and x and y are
+ // different integer types.
+ if (T->isIntegerType() && castTy->isIntegerType())
+ return val;
+
+ return UnknownVal();
+ }
+
+ if (!isa<nonloc::ConcreteInt>(val))
+ return UnknownVal();
+
+ // Only handle casts from integers to integers.
+ if (!isLocType && !castTy->isIntegerType())
+ return UnknownVal();
+
+ llvm::APSInt i = cast<nonloc::ConcreteInt>(val).getValue();
+ i.setIsUnsigned(castTy->isUnsignedIntegerType() || Loc::isLocType(castTy));
+ i = i.extOrTrunc(Context.getTypeSize(castTy));
+
+ if (isLocType)
+ return makeIntLocVal(i);
+ else
+ return makeIntVal(i);
+}
+
+SVal SimpleSValBuilder::evalCastL(Loc val, QualType castTy) {
+
+ // Casts from pointers -> pointers, just return the lval.
+ //
+ // Casts from pointers -> references, just return the lval. These
+ // can be introduced by the frontend for corner cases, e.g
+ // casting from va_list* to __builtin_va_list&.
+ //
+ if (Loc::isLocType(castTy) || castTy->isReferenceType())
+ return val;
+
+ // FIXME: Handle transparent unions where a value can be "transparently"
+ // lifted into a union type.
+ if (castTy->isUnionType())
+ return UnknownVal();
+
+ if (castTy->isIntegerType()) {
+ unsigned BitWidth = Context.getTypeSize(castTy);
+
+ if (!isa<loc::ConcreteInt>(val))
+ return makeLocAsInteger(val, BitWidth);
+
+ llvm::APSInt i = cast<loc::ConcreteInt>(val).getValue();
+ i.setIsUnsigned(castTy->isUnsignedIntegerType() || Loc::isLocType(castTy));
+ i = i.extOrTrunc(BitWidth);
+ return makeIntVal(i);
+ }
+
+ // All other cases: return 'UnknownVal'. This includes casting pointers
+ // to floats, which is probably badness it itself, but this is a good
+ // intermediate solution until we do something better.
+ return UnknownVal();
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function for unary operators.
+//===----------------------------------------------------------------------===//
+
+SVal SimpleSValBuilder::evalMinus(NonLoc val) {
+ switch (val.getSubKind()) {
+ case nonloc::ConcreteIntKind:
+ return cast<nonloc::ConcreteInt>(val).evalMinus(*this);
+ default:
+ return UnknownVal();
+ }
+}
+
+SVal SimpleSValBuilder::evalComplement(NonLoc X) {
+ switch (X.getSubKind()) {
+ case nonloc::ConcreteIntKind:
+ return cast<nonloc::ConcreteInt>(X).evalComplement(*this);
+ default:
+ return UnknownVal();
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function for binary operators.
+//===----------------------------------------------------------------------===//
+
+static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
+ switch (op) {
+ default:
+ assert(false && "Invalid opcode.");
+ case BO_LT: return BO_GE;
+ case BO_GT: return BO_LE;
+ case BO_LE: return BO_GT;
+ case BO_GE: return BO_LT;
+ case BO_EQ: return BO_NE;
+ case BO_NE: return BO_EQ;
+ }
+}
+
+static BinaryOperator::Opcode ReverseComparison(BinaryOperator::Opcode op) {
+ switch (op) {
+ default:
+ assert(false && "Invalid opcode.");
+ case BO_LT: return BO_GT;
+ case BO_GT: return BO_LT;
+ case BO_LE: return BO_GE;
+ case BO_GE: return BO_LE;
+ case BO_EQ:
+ case BO_NE:
+ return op;
+ }
+}
+
+SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
+ BinaryOperator::Opcode op,
+ const llvm::APSInt &RHS,
+ QualType resultTy) {
+ bool isIdempotent = false;
+
+ // Check for a few special cases with known reductions first.
+ switch (op) {
+ default:
+ // We can't reduce this case; just treat it normally.
+ break;
+ case BO_Mul:
+ // a*0 and a*1
+ if (RHS == 0)
+ return makeIntVal(0, resultTy);
+ else if (RHS == 1)
+ isIdempotent = true;
+ break;
+ case BO_Div:
+ // a/0 and a/1
+ if (RHS == 0)
+ // This is also handled elsewhere.
+ return UndefinedVal();
+ else if (RHS == 1)
+ isIdempotent = true;
+ break;
+ case BO_Rem:
+ // a%0 and a%1
+ if (RHS == 0)
+ // This is also handled elsewhere.
+ return UndefinedVal();
+ else if (RHS == 1)
+ return makeIntVal(0, resultTy);
+ break;
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_Xor:
+ // a+0, a-0, a<<0, a>>0, a^0
+ if (RHS == 0)
+ isIdempotent = true;
+ break;
+ case BO_And:
+ // a&0 and a&(~0)
+ if (RHS == 0)
+ return makeIntVal(0, resultTy);
+ else if (RHS.isAllOnesValue())
+ isIdempotent = true;
+ break;
+ case BO_Or:
+ // a|0 and a|(~0)
+ if (RHS == 0)
+ isIdempotent = true;
+ else if (RHS.isAllOnesValue()) {
+ const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS);
+ return nonloc::ConcreteInt(Result);
+ }
+ break;
+ }
+
+ // Idempotent ops (like a*1) can still change the type of an expression.
+ // Wrap the LHS up in a NonLoc again and let evalCastNL do the dirty work.
+ if (isIdempotent) {
+ if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS))
+ return evalCastNL(nonloc::SymbolVal(LHSSym), resultTy);
+ return evalCastNL(nonloc::SymExprVal(LHS), resultTy);
+ }
+
+ // If we reach this point, the expression cannot be simplified.
+ // Make a SymExprVal for the entire thing.
+ return makeNonLoc(LHS, op, RHS, resultTy);
+}
+
+SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
+ BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs,
+ QualType resultTy) {
+ // Handle trivial case where left-side and right-side are the same.
+ if (lhs == rhs)
+ switch (op) {
+ default:
+ break;
+ case BO_EQ:
+ case BO_LE:
+ case BO_GE:
+ return makeTruthVal(true, resultTy);
+ case BO_LT:
+ case BO_GT:
+ case BO_NE:
+ return makeTruthVal(false, resultTy);
+ case BO_Xor:
+ case BO_Sub:
+ return makeIntVal(0, resultTy);
+ case BO_Or:
+ case BO_And:
+ return evalCastNL(lhs, resultTy);
+ }
+
+ while (1) {
+ switch (lhs.getSubKind()) {
+ default:
+ return UnknownVal();
+ case nonloc::LocAsIntegerKind: {
+ Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
+ switch (rhs.getSubKind()) {
+ case nonloc::LocAsIntegerKind:
+ return evalBinOpLL(state, op, lhsL,
+ cast<nonloc::LocAsInteger>(rhs).getLoc(),
+ resultTy);
+ case nonloc::ConcreteIntKind: {
+ // Transform the integer into a location and compare.
+ llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue();
+ i.setIsUnsigned(true);
+ i = i.extOrTrunc(Context.getTypeSize(Context.VoidPtrTy));
+ return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
+ }
+ default:
+ switch (op) {
+ case BO_EQ:
+ return makeTruthVal(false, resultTy);
+ case BO_NE:
+ return makeTruthVal(true, resultTy);
+ default:
+ // This case also handles pointer arithmetic.
+ return UnknownVal();
+ }
+ }
+ }
+ case nonloc::SymExprValKind: {
+ nonloc::SymExprVal *selhs = cast<nonloc::SymExprVal>(&lhs);
+
+ // Only handle LHS of the form "$sym op constant", at least for now.
+ const SymIntExpr *symIntExpr =
+ dyn_cast<SymIntExpr>(selhs->getSymbolicExpression());
+
+ if (!symIntExpr)
+ return UnknownVal();
+
+ // Is this a logical not? (!x is represented as x == 0.)
+ if (op == BO_EQ && rhs.isZeroConstant()) {
+ // We know how to negate certain expressions. Simplify them here.
+
+ BinaryOperator::Opcode opc = symIntExpr->getOpcode();
+ switch (opc) {
+ default:
+ // We don't know how to negate this operation.
+ // Just handle it as if it were a normal comparison to 0.
+ break;
+ case BO_LAnd:
+ case BO_LOr:
+ assert(false && "Logical operators handled by branching logic.");
+ return UnknownVal();
+ case BO_Assign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ case BO_Comma:
+ assert(false && "'=' and ',' operators handled by ExprEngine.");
+ return UnknownVal();
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ assert(false && "Pointer arithmetic not handled here.");
+ return UnknownVal();
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ // Negate the comparison and make a value.
+ opc = NegateComparison(opc);
+ assert(symIntExpr->getType(Context) == resultTy);
+ return makeNonLoc(symIntExpr->getLHS(), opc,
+ symIntExpr->getRHS(), resultTy);
+ }
+ }
+
+ // For now, only handle expressions whose RHS is a constant.
+ const nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs);
+ if (!rhsInt)
+ return UnknownVal();
+
+ // If both the LHS and the current expression are additive,
+ // fold their constants.
+ if (BinaryOperator::isAdditiveOp(op)) {
+ BinaryOperator::Opcode lop = symIntExpr->getOpcode();
+ if (BinaryOperator::isAdditiveOp(lop)) {
+ // resultTy may not be the best type to convert to, but it's
+ // probably the best choice in expressions with mixed type
+ // (such as x+1U+2LL). The rules for implicit conversions should
+ // choose a reasonable type to preserve the expression, and will
+ // at least match how the value is going to be used.
+ const llvm::APSInt &first =
+ BasicVals.Convert(resultTy, symIntExpr->getRHS());
+ const llvm::APSInt &second =
+ BasicVals.Convert(resultTy, rhsInt->getValue());
+ const llvm::APSInt *newRHS;
+ if (lop == op)
+ newRHS = BasicVals.evalAPSInt(BO_Add, first, second);
+ else
+ newRHS = BasicVals.evalAPSInt(BO_Sub, first, second);
+ return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
+ }
+ }
+
+ // Otherwise, make a SymExprVal out of the expression.
+ return MakeSymIntVal(symIntExpr, op, rhsInt->getValue(), resultTy);
+ }
+ case nonloc::ConcreteIntKind: {
+ const nonloc::ConcreteInt& lhsInt = cast<nonloc::ConcreteInt>(lhs);
+
+ if (isa<nonloc::ConcreteInt>(rhs)) {
+ return lhsInt.evalBinOp(*this, op, cast<nonloc::ConcreteInt>(rhs));
+ } else {
+ const llvm::APSInt& lhsValue = lhsInt.getValue();
+
+ // Swap the left and right sides and flip the operator if doing so
+ // allows us to better reason about the expression (this is a form
+ // of expression canonicalization).
+ // While we're at it, catch some special cases for non-commutative ops.
+ NonLoc tmp = rhs;
+ rhs = lhs;
+ lhs = tmp;
+
+ switch (op) {
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ op = ReverseComparison(op);
+ continue;
+ case BO_EQ:
+ case BO_NE:
+ case BO_Add:
+ case BO_Mul:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ continue;
+ case BO_Shr:
+ if (lhsValue.isAllOnesValue() && lhsValue.isSigned())
+ // At this point lhs and rhs have been swapped.
+ return rhs;
+ // FALL-THROUGH
+ case BO_Shl:
+ if (lhsValue == 0)
+ // At this point lhs and rhs have been swapped.
+ return rhs;
+ return UnknownVal();
+ default:
+ return UnknownVal();
+ }
+ }
+ }
+ case nonloc::SymbolValKind: {
+ nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
+ SymbolRef Sym = slhs->getSymbol();
+ // Does the symbol simplify to a constant? If so, "fold" the constant
+ // by setting 'lhs' to a ConcreteInt and try again.
+ if (Sym->getType(Context)->isIntegerType())
+ if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
+ // The symbol evaluates to a constant. If necessary, promote the
+ // folded constant (LHS) to the result type.
+ const llvm::APSInt &lhs_I = BasicVals.Convert(resultTy, *Constant);
+ lhs = nonloc::ConcreteInt(lhs_I);
+
+ // Also promote the RHS (if necessary).
+
+ // For shifts, it is not necessary to promote the RHS.
+ if (BinaryOperator::isShiftOp(op))
+ continue;
+
+ // Other operators: do an implicit conversion. This shouldn't be
+ // necessary once we support truncation/extension of symbolic values.
+ if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
+ rhs = nonloc::ConcreteInt(BasicVals.Convert(resultTy,
+ rhs_I->getValue()));
+ }
+
+ continue;
+ }
+
+ // Is the RHS a symbol we can simplify?
+ if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
+ SymbolRef RSym = srhs->getSymbol();
+ if (RSym->getType(Context)->isIntegerType()) {
+ if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
+ // The symbol evaluates to a constant.
+ const llvm::APSInt &rhs_I = BasicVals.Convert(resultTy, *Constant);
+ rhs = nonloc::ConcreteInt(rhs_I);
+ }
+ }
+ }
+
+ if (isa<nonloc::ConcreteInt>(rhs)) {
+ return MakeSymIntVal(slhs->getSymbol(), op,
+ cast<nonloc::ConcreteInt>(rhs).getValue(),
+ resultTy);
+ }
+
+ return UnknownVal();
+ }
+ }
+ }
+}
+
+// FIXME: all this logic will change if/when we have MemRegion::getLocation().
+SVal SimpleSValBuilder::evalBinOpLL(const GRState *state,
+ BinaryOperator::Opcode op,
+ Loc lhs, Loc rhs,
+ QualType resultTy) {
+ // Only comparisons and subtractions are valid operations on two pointers.
+ // See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15].
+ // However, if a pointer is casted to an integer, evalBinOpNN may end up
+ // calling this function with another operation (PR7527). We don't attempt to
+ // model this for now, but it could be useful, particularly when the
+ // "location" is actually an integer value that's been passed through a void*.
+ if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub))
+ return UnknownVal();
+
+ // Special cases for when both sides are identical.
+ if (lhs == rhs) {
+ switch (op) {
+ default:
+ assert(false && "Unimplemented operation for two identical values");
+ return UnknownVal();
+ case BO_Sub:
+ return makeZeroVal(resultTy);
+ case BO_EQ:
+ case BO_LE:
+ case BO_GE:
+ return makeTruthVal(true, resultTy);
+ case BO_NE:
+ case BO_LT:
+ case BO_GT:
+ return makeTruthVal(false, resultTy);
+ }
+ }
+
+ switch (lhs.getSubKind()) {
+ default:
+ assert(false && "Ordering not implemented for this Loc.");
+ return UnknownVal();
+
+ case loc::GotoLabelKind:
+ // The only thing we know about labels is that they're non-null.
+ if (rhs.isZeroConstant()) {
+ switch (op) {
+ default:
+ break;
+ case BO_Sub:
+ return evalCastL(lhs, resultTy);
+ case BO_EQ:
+ case BO_LE:
+ case BO_LT:
+ return makeTruthVal(false, resultTy);
+ case BO_NE:
+ case BO_GT:
+ case BO_GE:
+ return makeTruthVal(true, resultTy);
+ }
+ }
+ // There may be two labels for the same location, and a function region may
+ // have the same address as a label at the start of the function (depending
+ // on the ABI).
+ // FIXME: we can probably do a comparison against other MemRegions, though.
+ // FIXME: is there a way to tell if two labels refer to the same location?
+ return UnknownVal();
+
+ case loc::ConcreteIntKind: {
+ // If one of the operands is a symbol and the other is a constant,
+ // build an expression for use by the constraint manager.
+ if (SymbolRef rSym = rhs.getAsLocSymbol()) {
+ // We can only build expressions with symbols on the left,
+ // so we need a reversible operator.
+ if (!BinaryOperator::isComparisonOp(op))
+ return UnknownVal();
+
+ const llvm::APSInt &lVal = cast<loc::ConcreteInt>(lhs).getValue();
+ return makeNonLoc(rSym, ReverseComparison(op), lVal, resultTy);
+ }
+
+ // If both operands are constants, just perform the operation.
+ if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
+ SVal ResultVal = cast<loc::ConcreteInt>(lhs).evalBinOp(BasicVals, op,
+ *rInt);
+ if (Loc *Result = dyn_cast<Loc>(&ResultVal))
+ return evalCastL(*Result, resultTy);
+ else
+ return UnknownVal();
+ }
+
+ // Special case comparisons against NULL.
+ // This must come after the test if the RHS is a symbol, which is used to
+ // build constraints. The address of any non-symbolic region is guaranteed
+ // to be non-NULL, as is any label.
+ assert(isa<loc::MemRegionVal>(rhs) || isa<loc::GotoLabel>(rhs));
+ if (lhs.isZeroConstant()) {
+ switch (op) {
+ default:
+ break;
+ case BO_EQ:
+ case BO_GT:
+ case BO_GE:
+ return makeTruthVal(false, resultTy);
+ case BO_NE:
+ case BO_LT:
+ case BO_LE:
+ return makeTruthVal(true, resultTy);
+ }
+ }
+
+ // Comparing an arbitrary integer to a region or label address is
+ // completely unknowable.
+ return UnknownVal();
+ }
+ case loc::MemRegionKind: {
+ if (loc::ConcreteInt *rInt = dyn_cast<loc::ConcreteInt>(&rhs)) {
+ // If one of the operands is a symbol and the other is a constant,
+ // build an expression for use by the constraint manager.
+ if (SymbolRef lSym = lhs.getAsLocSymbol())
+ return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
+
+ // Special case comparisons to NULL.
+ // This must come after the test if the LHS is a symbol, which is used to
+ // build constraints. The address of any non-symbolic region is guaranteed
+ // to be non-NULL.
+ if (rInt->isZeroConstant()) {
+ switch (op) {
+ default:
+ break;
+ case BO_Sub:
+ return evalCastL(lhs, resultTy);
+ case BO_EQ:
+ case BO_LT:
+ case BO_LE:
+ return makeTruthVal(false, resultTy);
+ case BO_NE:
+ case BO_GT:
+ case BO_GE:
+ return makeTruthVal(true, resultTy);
+ }
+ }
+
+ // Comparing a region to an arbitrary integer is completely unknowable.
+ return UnknownVal();
+ }
+
+ // Get both values as regions, if possible.
+ const MemRegion *LeftMR = lhs.getAsRegion();
+ assert(LeftMR && "MemRegionKind SVal doesn't have a region!");
+
+ const MemRegion *RightMR = rhs.getAsRegion();
+ if (!RightMR)
+ // The RHS is probably a label, which in theory could address a region.
+ // FIXME: we can probably make a more useful statement about non-code
+ // regions, though.
+ return UnknownVal();
+
+ // If both values wrap regions, see if they're from different base regions.
+ const MemRegion *LeftBase = LeftMR->getBaseRegion();
+ const MemRegion *RightBase = RightMR->getBaseRegion();
+ if (LeftBase != RightBase &&
+ !isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) {
+ switch (op) {
+ default:
+ return UnknownVal();
+ case BO_EQ:
+ return makeTruthVal(false, resultTy);
+ case BO_NE:
+ return makeTruthVal(true, resultTy);
+ }
+ }
+
+ // The two regions are from the same base region. See if they're both a
+ // type of region we know how to compare.
+
+ // FIXME: If/when there is a getAsRawOffset() for FieldRegions, this
+ // ElementRegion path and the FieldRegion path below should be unified.
+ if (const ElementRegion *LeftER = dyn_cast<ElementRegion>(LeftMR)) {
+ // First see if the right region is also an ElementRegion.
+ const ElementRegion *RightER = dyn_cast<ElementRegion>(RightMR);
+ if (!RightER)
+ return UnknownVal();
+
+ // Next, see if the two ERs have the same super-region and matching types.
+ // FIXME: This should do something useful even if the types don't match,
+ // though if both indexes are constant the RegionRawOffset path will
+ // give the correct answer.
+ if (LeftER->getSuperRegion() == RightER->getSuperRegion() &&
+ LeftER->getElementType() == RightER->getElementType()) {
+ // Get the left index and cast it to the correct type.
+ // If the index is unknown or undefined, bail out here.
+ SVal LeftIndexVal = LeftER->getIndex();
+ NonLoc *LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
+ if (!LeftIndex)
+ return UnknownVal();
+ LeftIndexVal = evalCastNL(*LeftIndex, resultTy);
+ LeftIndex = dyn_cast<NonLoc>(&LeftIndexVal);
+ if (!LeftIndex)
+ return UnknownVal();
+
+ // Do the same for the right index.
+ SVal RightIndexVal = RightER->getIndex();
+ NonLoc *RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
+ if (!RightIndex)
+ return UnknownVal();
+ RightIndexVal = evalCastNL(*RightIndex, resultTy);
+ RightIndex = dyn_cast<NonLoc>(&RightIndexVal);
+ if (!RightIndex)
+ return UnknownVal();
+
+ // Actually perform the operation.
+ // evalBinOpNN expects the two indexes to already be the right type.
+ return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
+ }
+
+ // If the element indexes aren't comparable, see if the raw offsets are.
+ RegionRawOffset LeftOffset = LeftER->getAsArrayOffset();
+ RegionRawOffset RightOffset = RightER->getAsArrayOffset();
+
+ if (LeftOffset.getRegion() != NULL &&
+ LeftOffset.getRegion() == RightOffset.getRegion()) {
+ CharUnits left = LeftOffset.getOffset();
+ CharUnits right = RightOffset.getOffset();
+
+ switch (op) {
+ default:
+ return UnknownVal();
+ case BO_LT:
+ return makeTruthVal(left < right, resultTy);
+ case BO_GT:
+ return makeTruthVal(left > right, resultTy);
+ case BO_LE:
+ return makeTruthVal(left <= right, resultTy);
+ case BO_GE:
+ return makeTruthVal(left >= right, resultTy);
+ case BO_EQ:
+ return makeTruthVal(left == right, resultTy);
+ case BO_NE:
+ return makeTruthVal(left != right, resultTy);
+ }
+ }
+
+ // If we get here, we have no way of comparing the ElementRegions.
+ return UnknownVal();
+ }
+
+ // See if both regions are fields of the same structure.
+ // FIXME: This doesn't handle nesting, inheritance, or Objective-C ivars.
+ if (const FieldRegion *LeftFR = dyn_cast<FieldRegion>(LeftMR)) {
+ // Only comparisons are meaningful here!
+ if (!BinaryOperator::isComparisonOp(op))
+ return UnknownVal();
+
+ // First see if the right region is also a FieldRegion.
+ const FieldRegion *RightFR = dyn_cast<FieldRegion>(RightMR);
+ if (!RightFR)
+ return UnknownVal();
+
+ // Next, see if the two FRs have the same super-region.
+ // FIXME: This doesn't handle casts yet, and simply stripping the casts
+ // doesn't help.
+ if (LeftFR->getSuperRegion() != RightFR->getSuperRegion())
+ return UnknownVal();
+
+ const FieldDecl *LeftFD = LeftFR->getDecl();
+ const FieldDecl *RightFD = RightFR->getDecl();
+ const RecordDecl *RD = LeftFD->getParent();
+
+ // Make sure the two FRs are from the same kind of record. Just in case!
+ // FIXME: This is probably where inheritance would be a problem.
+ if (RD != RightFD->getParent())
+ return UnknownVal();
+
+ // We know for sure that the two fields are not the same, since that
+ // would have given us the same SVal.
+ if (op == BO_EQ)
+ return makeTruthVal(false, resultTy);
+ if (op == BO_NE)
+ return makeTruthVal(true, resultTy);
+
+ // Iterate through the fields and see which one comes first.
+ // [C99 6.7.2.1.13] "Within a structure object, the non-bit-field
+ // members and the units in which bit-fields reside have addresses that
+ // increase in the order in which they are declared."
+ bool leftFirst = (op == BO_LT || op == BO_LE);
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I!=E; ++I) {
+ if (*I == LeftFD)
+ return makeTruthVal(leftFirst, resultTy);
+ if (*I == RightFD)
+ return makeTruthVal(!leftFirst, resultTy);
+ }
+
+ assert(false && "Fields not found in parent record's definition");
+ }
+
+ // If we get here, we have no way of comparing the regions.
+ return UnknownVal();
+ }
+ }
+}
+
+SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
+ BinaryOperator::Opcode op,
+ Loc lhs, NonLoc rhs, QualType resultTy) {
+
+ // Special case: rhs is a zero constant.
+ if (rhs.isZeroConstant())
+ return lhs;
+
+ // Special case: 'rhs' is an integer that has the same width as a pointer and
+ // we are using the integer location in a comparison. Normally this cannot be
+ // triggered, but transfer functions like those for OSCommpareAndSwapBarrier32
+ // can generate comparisons that trigger this code.
+ // FIXME: Are all locations guaranteed to have pointer width?
+ if (BinaryOperator::isComparisonOp(op)) {
+ if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
+ const llvm::APSInt *x = &rhsInt->getValue();
+ ASTContext &ctx = Context;
+ if (ctx.getTypeSize(ctx.VoidPtrTy) == x->getBitWidth()) {
+ // Convert the signedness of the integer (if necessary).
+ if (x->isSigned())
+ x = &getBasicValueFactory().getValue(*x, true);
+
+ return evalBinOpLL(state, op, lhs, loc::ConcreteInt(*x), resultTy);
+ }
+ }
+ }
+
+ // We are dealing with pointer arithmetic.
+
+ // Handle pointer arithmetic on constant values.
+ if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
+ if (loc::ConcreteInt *lhsInt = dyn_cast<loc::ConcreteInt>(&lhs)) {
+ const llvm::APSInt &leftI = lhsInt->getValue();
+ assert(leftI.isUnsigned());
+ llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true);
+
+ // Convert the bitwidth of rightI. This should deal with overflow
+ // since we are dealing with concrete values.
+ rightI = rightI.extOrTrunc(leftI.getBitWidth());
+
+ // Offset the increment by the pointer size.
+ llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
+ rightI *= Multiplicand;
+
+ // Compute the adjusted pointer.
+ switch (op) {
+ case BO_Add:
+ rightI = leftI + rightI;
+ break;
+ case BO_Sub:
+ rightI = leftI - rightI;
+ break;
+ default:
+ llvm_unreachable("Invalid pointer arithmetic operation");
+ }
+ return loc::ConcreteInt(getBasicValueFactory().getValue(rightI));
+ }
+ }
+
+ // Handle cases where 'lhs' is a region.
+ if (const MemRegion *region = lhs.getAsRegion()) {
+ rhs = cast<NonLoc>(convertToArrayIndex(rhs));
+ SVal index = UnknownVal();
+ const MemRegion *superR = 0;
+ QualType elementType;
+
+ if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
+ index = evalBinOpNN(state, BO_Add, elemReg->getIndex(), rhs,
+ getArrayIndexType());
+ superR = elemReg->getSuperRegion();
+ elementType = elemReg->getElementType();
+ }
+ else if (isa<SubRegion>(region)) {
+ superR = region;
+ index = rhs;
+ if (const PointerType *PT = resultTy->getAs<PointerType>()) {
+ elementType = PT->getPointeeType();
+ }
+ else {
+ const ObjCObjectPointerType *OT =
+ resultTy->getAs<ObjCObjectPointerType>();
+ elementType = OT->getPointeeType();
+ }
+ }
+
+ if (NonLoc *indexV = dyn_cast<NonLoc>(&index)) {
+ return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV,
+ superR, getContext()));
+ }
+ }
+ return UnknownVal();
+}
+
+const llvm::APSInt *SimpleSValBuilder::getKnownValue(const GRState *state,
+ SVal V) {
+ if (V.isUnknownOrUndef())
+ return NULL;
+
+ if (loc::ConcreteInt* X = dyn_cast<loc::ConcreteInt>(&V))
+ return &X->getValue();
+
+ if (nonloc::ConcreteInt* X = dyn_cast<nonloc::ConcreteInt>(&V))
+ return &X->getValue();
+
+ if (SymbolRef Sym = V.getAsSymbol())
+ return state->getSymVal(Sym);
+
+ // FIXME: Add support for SymExprs.
+ return NULL;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
new file mode 100644
index 0000000..7225170
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -0,0 +1,338 @@
+//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the types Store and StoreManager.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
+#include "clang/AST/CharUnits.h"
+
+using namespace clang;
+using namespace ento;
+
+StoreManager::StoreManager(GRStateManager &stateMgr)
+ : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
+ MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
+
+StoreRef StoreManager::enterStackFrame(const GRState *state,
+ const StackFrameContext *frame) {
+ return StoreRef(state->getStore(), *this);
+}
+
+const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
+ QualType EleTy, uint64_t index) {
+ NonLoc idx = svalBuilder.makeArrayIndex(index);
+ return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext());
+}
+
+// FIXME: Merge with the implementation of the same method in MemRegion.cpp
+static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *D = RT->getDecl();
+ if (!D->getDefinition())
+ return false;
+ }
+
+ return true;
+}
+
+StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) {
+ return StoreRef(store, *this);
+}
+
+const ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R,
+ QualType T) {
+ NonLoc idx = svalBuilder.makeZeroArrayIndex();
+ assert(!T.isNull());
+ return MRMgr.getElementRegion(T, idx, R, Ctx);
+}
+
+const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) {
+
+ ASTContext& Ctx = StateMgr.getContext();
+
+ // Handle casts to Objective-C objects.
+ if (CastToTy->isObjCObjectPointerType())
+ return R->StripCasts();
+
+ if (CastToTy->isBlockPointerType()) {
+ // FIXME: We may need different solutions, depending on the symbol
+ // involved. Blocks can be casted to/from 'id', as they can be treated
+ // as Objective-C objects. This could possibly be handled by enhancing
+ // our reasoning of downcasts of symbolic objects.
+ if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R))
+ return R;
+
+ // We don't know what to make of it. Return a NULL region, which
+ // will be interpretted as UnknownVal.
+ return NULL;
+ }
+
+ // Now assume we are casting from pointer to pointer. Other cases should
+ // already be handled.
+ QualType PointeeTy = CastToTy->getPointeeType();
+ QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
+
+ // Handle casts to void*. We just pass the region through.
+ if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy)
+ return R;
+
+ // Handle casts from compatible types.
+ if (R->isBoundable())
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
+ if (CanonPointeeTy == ObjTy)
+ return R;
+ }
+
+ // Process region cast according to the kind of the region being cast.
+ switch (R->getKind()) {
+ case MemRegion::CXXThisRegionKind:
+ case MemRegion::GenericMemSpaceRegionKind:
+ case MemRegion::StackLocalsSpaceRegionKind:
+ case MemRegion::StackArgumentsSpaceRegionKind:
+ case MemRegion::HeapSpaceRegionKind:
+ case MemRegion::UnknownSpaceRegionKind:
+ case MemRegion::NonStaticGlobalSpaceRegionKind:
+ case MemRegion::StaticGlobalSpaceRegionKind: {
+ assert(0 && "Invalid region cast");
+ break;
+ }
+
+ case MemRegion::FunctionTextRegionKind:
+ case MemRegion::BlockTextRegionKind:
+ case MemRegion::BlockDataRegionKind:
+ case MemRegion::StringRegionKind:
+ // FIXME: Need to handle arbitrary downcasts.
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::CompoundLiteralRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::CXXTempObjectRegionKind:
+ case MemRegion::CXXBaseObjectRegionKind:
+ return MakeElementRegion(R, PointeeTy);
+
+ case MemRegion::ElementRegionKind: {
+ // If we are casting from an ElementRegion to another type, the
+ // algorithm is as follows:
+ //
+ // (1) Compute the "raw offset" of the ElementRegion from the
+ // base region. This is done by calling 'getAsRawOffset()'.
+ //
+ // (2a) If we get a 'RegionRawOffset' after calling
+ // 'getAsRawOffset()', determine if the absolute offset
+ // can be exactly divided into chunks of the size of the
+ // casted-pointee type. If so, create a new ElementRegion with
+ // the pointee-cast type as the new ElementType and the index
+ // being the offset divded by the chunk size. If not, create
+ // a new ElementRegion at offset 0 off the raw offset region.
+ //
+ // (2b) If we don't a get a 'RegionRawOffset' after calling
+ // 'getAsRawOffset()', it means that we are at offset 0.
+ //
+ // FIXME: Handle symbolic raw offsets.
+
+ const ElementRegion *elementR = cast<ElementRegion>(R);
+ const RegionRawOffset &rawOff = elementR->getAsArrayOffset();
+ const MemRegion *baseR = rawOff.getRegion();
+
+ // If we cannot compute a raw offset, throw up our hands and return
+ // a NULL MemRegion*.
+ if (!baseR)
+ return NULL;
+
+ CharUnits off = rawOff.getOffset();
+
+ if (off.isZero()) {
+ // Edge case: we are at 0 bytes off the beginning of baseR. We
+ // check to see if type we are casting to is the same as the base
+ // region. If so, just return the base region.
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(baseR)) {
+ QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
+ QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
+ if (CanonPointeeTy == ObjTy)
+ return baseR;
+ }
+
+ // Otherwise, create a new ElementRegion at offset 0.
+ return MakeElementRegion(baseR, PointeeTy);
+ }
+
+ // We have a non-zero offset from the base region. We want to determine
+ // if the offset can be evenly divided by sizeof(PointeeTy). If so,
+ // we create an ElementRegion whose index is that value. Otherwise, we
+ // create two ElementRegions, one that reflects a raw offset and the other
+ // that reflects the cast.
+
+ // Compute the index for the new ElementRegion.
+ int64_t newIndex = 0;
+ const MemRegion *newSuperR = 0;
+
+ // We can only compute sizeof(PointeeTy) if it is a complete type.
+ if (IsCompleteType(Ctx, PointeeTy)) {
+ // Compute the size in **bytes**.
+ CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy);
+ if (!pointeeTySize.isZero()) {
+ // Is the offset a multiple of the size? If so, we can layer the
+ // ElementRegion (with elementType == PointeeTy) directly on top of
+ // the base region.
+ if (off % pointeeTySize == 0) {
+ newIndex = off / pointeeTySize;
+ newSuperR = baseR;
+ }
+ }
+ }
+
+ if (!newSuperR) {
+ // Create an intermediate ElementRegion to represent the raw byte.
+ // This will be the super region of the final ElementRegion.
+ newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off.getQuantity());
+ }
+
+ return MakeElementRegion(newSuperR, PointeeTy, newIndex);
+ }
+ }
+
+ assert(0 && "unreachable");
+ return 0;
+}
+
+
+/// CastRetrievedVal - Used by subclasses of StoreManager to implement
+/// implicit casts that arise from loads from regions that are reinterpreted
+/// as another region.
+SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
+ QualType castTy, bool performTestOnly) {
+
+ if (castTy.isNull())
+ return V;
+
+ ASTContext &Ctx = svalBuilder.getContext();
+
+ if (performTestOnly) {
+ // Automatically translate references to pointers.
+ QualType T = R->getValueType();
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ T = Ctx.getPointerType(RT->getPointeeType());
+
+ assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T));
+ return V;
+ }
+
+ if (const Loc *L = dyn_cast<Loc>(&V))
+ return svalBuilder.evalCastL(*L, castTy);
+ else if (const NonLoc *NL = dyn_cast<NonLoc>(&V))
+ return svalBuilder.evalCastNL(*NL, castTy);
+
+ return V;
+}
+
+SVal StoreManager::getLValueFieldOrIvar(const Decl* D, SVal Base) {
+ if (Base.isUnknownOrUndef())
+ return Base;
+
+ Loc BaseL = cast<Loc>(Base);
+ const MemRegion* BaseR = 0;
+
+ switch (BaseL.getSubKind()) {
+ case loc::MemRegionKind:
+ BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
+ break;
+
+ case loc::GotoLabelKind:
+ // These are anormal cases. Flag an undefined value.
+ return UndefinedVal();
+
+ case loc::ConcreteIntKind:
+ // While these seem funny, this can happen through casts.
+ // FIXME: What we should return is the field offset. For example,
+ // add the field offset to the integer value. That way funny things
+ // like this work properly: &(((struct foo *) 0xa)->f)
+ return Base;
+
+ default:
+ assert(0 && "Unhandled Base.");
+ return Base;
+ }
+
+ // NOTE: We must have this check first because ObjCIvarDecl is a subclass
+ // of FieldDecl.
+ if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D))
+ return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR));
+
+ return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
+}
+
+SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
+ SVal Base) {
+
+ // If the base is an unknown or undefined value, just return it back.
+ // FIXME: For absolute pointer addresses, we just return that value back as
+ // well, although in reality we should return the offset added to that
+ // value.
+ if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
+ return Base;
+
+ const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
+
+ // Pointer of any type can be cast and used as array base.
+ const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
+
+ // Convert the offset to the appropriate size and signedness.
+ Offset = cast<NonLoc>(svalBuilder.convertToArrayIndex(Offset));
+
+ if (!ElemR) {
+ //
+ // If the base region is not an ElementRegion, create one.
+ // This can happen in the following example:
+ //
+ // char *p = __builtin_alloc(10);
+ // p[1] = 8;
+ //
+ // Observe that 'p' binds to an AllocaRegion.
+ //
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
+ BaseRegion, Ctx));
+ }
+
+ SVal BaseIdx = ElemR->getIndex();
+
+ if (!isa<nonloc::ConcreteInt>(BaseIdx))
+ return UnknownVal();
+
+ const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
+
+ // Only allow non-integer offsets if the base region has no offset itself.
+ // FIXME: This is a somewhat arbitrary restriction. We should be using
+ // SValBuilder here to add the two offsets without checking their types.
+ if (!isa<nonloc::ConcreteInt>(Offset)) {
+ if (isa<ElementRegion>(BaseRegion->StripCasts()))
+ return UnknownVal();
+
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
+ ElemR->getSuperRegion(),
+ Ctx));
+ }
+
+ const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
+ assert(BaseIdxI.isSigned());
+
+ // Compute the new index.
+ nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI +
+ OffI));
+
+ // Construct the new ElementRegion.
+ const MemRegion *ArrayR = ElemR->getSuperRegion();
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
+ Ctx));
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
new file mode 100644
index 0000000..c1ca1cf
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -0,0 +1,345 @@
+//== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
+// created for use by ExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+void SymExpr::dump() const {
+ dumpToStream(llvm::errs());
+}
+
+static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) {
+ switch (Op) {
+ default:
+ assert(false && "operator printing not implemented");
+ break;
+ case BO_Mul: os << '*' ; break;
+ case BO_Div: os << '/' ; break;
+ case BO_Rem: os << '%' ; break;
+ case BO_Add: os << '+' ; break;
+ case BO_Sub: os << '-' ; break;
+ case BO_Shl: os << "<<" ; break;
+ case BO_Shr: os << ">>" ; break;
+ case BO_LT: os << "<" ; break;
+ case BO_GT: os << '>' ; break;
+ case BO_LE: os << "<=" ; break;
+ case BO_GE: os << ">=" ; break;
+ case BO_EQ: os << "==" ; break;
+ case BO_NE: os << "!=" ; break;
+ case BO_And: os << '&' ; break;
+ case BO_Xor: os << '^' ; break;
+ case BO_Or: os << '|' ; break;
+ }
+}
+
+void SymIntExpr::dumpToStream(llvm::raw_ostream& os) const {
+ os << '(';
+ getLHS()->dumpToStream(os);
+ os << ") ";
+ print(os, getOpcode());
+ os << ' ' << getRHS().getZExtValue();
+ if (getRHS().isUnsigned()) os << 'U';
+}
+
+void SymSymExpr::dumpToStream(llvm::raw_ostream& os) const {
+ os << '(';
+ getLHS()->dumpToStream(os);
+ os << ") ";
+ os << '(';
+ getRHS()->dumpToStream(os);
+ os << ')';
+}
+
+void SymbolConjured::dumpToStream(llvm::raw_ostream& os) const {
+ os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
+}
+
+void SymbolDerived::dumpToStream(llvm::raw_ostream& os) const {
+ os << "derived_$" << getSymbolID() << '{'
+ << getParentSymbol() << ',' << getRegion() << '}';
+}
+
+void SymbolExtent::dumpToStream(llvm::raw_ostream& os) const {
+ os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
+}
+
+void SymbolMetadata::dumpToStream(llvm::raw_ostream& os) const {
+ os << "meta_$" << getSymbolID() << '{'
+ << getRegion() << ',' << T.getAsString() << '}';
+}
+
+void SymbolRegionValue::dumpToStream(llvm::raw_ostream& os) const {
+ os << "reg_$" << getSymbolID() << "<" << R << ">";
+}
+
+const SymbolRegionValue*
+SymbolManager::getRegionValueSymbol(const TypedRegion* R) {
+ llvm::FoldingSetNodeID profile;
+ SymbolRegionValue::Profile(profile, R);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
+ new (SD) SymbolRegionValue(SymbolCounter, R);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolRegionValue>(SD);
+}
+
+const SymbolConjured*
+SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, unsigned Count,
+ const void* SymbolTag) {
+
+ llvm::FoldingSetNodeID profile;
+ SymbolConjured::Profile(profile, E, T, Count, SymbolTag);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
+ new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolConjured>(SD);
+}
+
+const SymbolDerived*
+SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
+ const TypedRegion *R) {
+
+ llvm::FoldingSetNodeID profile;
+ SymbolDerived::Profile(profile, parentSymbol, R);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
+ new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolDerived>(SD);
+}
+
+const SymbolExtent*
+SymbolManager::getExtentSymbol(const SubRegion *R) {
+ llvm::FoldingSetNodeID profile;
+ SymbolExtent::Profile(profile, R);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
+ new (SD) SymbolExtent(SymbolCounter, R);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolExtent>(SD);
+}
+
+const SymbolMetadata*
+SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt* S, QualType T,
+ unsigned Count, const void* SymbolTag) {
+
+ llvm::FoldingSetNodeID profile;
+ SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
+ new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolMetadata>(SD);
+}
+
+const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
+ BinaryOperator::Opcode op,
+ const llvm::APSInt& v,
+ QualType t) {
+ llvm::FoldingSetNodeID ID;
+ SymIntExpr::Profile(ID, lhs, op, v, t);
+ void *InsertPos;
+ SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!data) {
+ data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
+ new (data) SymIntExpr(lhs, op, v, t);
+ DataSet.InsertNode(data, InsertPos);
+ }
+
+ return cast<SymIntExpr>(data);
+}
+
+const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
+ BinaryOperator::Opcode op,
+ const SymExpr *rhs,
+ QualType t) {
+ llvm::FoldingSetNodeID ID;
+ SymSymExpr::Profile(ID, lhs, op, rhs, t);
+ void *InsertPos;
+ SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!data) {
+ data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
+ new (data) SymSymExpr(lhs, op, rhs, t);
+ DataSet.InsertNode(data, InsertPos);
+ }
+
+ return cast<SymSymExpr>(data);
+}
+
+QualType SymbolConjured::getType(ASTContext&) const {
+ return T;
+}
+
+QualType SymbolDerived::getType(ASTContext& Ctx) const {
+ return R->getValueType();
+}
+
+QualType SymbolExtent::getType(ASTContext& Ctx) const {
+ return Ctx.getSizeType();
+}
+
+QualType SymbolMetadata::getType(ASTContext&) const {
+ return T;
+}
+
+QualType SymbolRegionValue::getType(ASTContext& C) const {
+ return R->getValueType();
+}
+
+SymbolManager::~SymbolManager() {}
+
+bool SymbolManager::canSymbolicate(QualType T) {
+ T = T.getCanonicalType();
+
+ if (Loc::isLocType(T))
+ return true;
+
+ if (T->isIntegerType())
+ return T->isScalarType();
+
+ if (T->isRecordType() && !T->isUnionType())
+ return true;
+
+ return false;
+}
+
+void SymbolReaper::markLive(SymbolRef sym) {
+ TheLiving.insert(sym);
+ TheDead.erase(sym);
+}
+
+void SymbolReaper::markInUse(SymbolRef sym) {
+ if (isa<SymbolMetadata>(sym))
+ MetadataInUse.insert(sym);
+}
+
+bool SymbolReaper::maybeDead(SymbolRef sym) {
+ if (isLive(sym))
+ return false;
+
+ TheDead.insert(sym);
+ return true;
+}
+
+static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
+ MR = MR->getBaseRegion();
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ return Reaper.isLive(SR->getSymbol());
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+ return Reaper.isLive(VR);
+
+ // FIXME: This is a gross over-approximation. What we really need is a way to
+ // tell if anything still refers to this region. Unlike SymbolicRegions,
+ // AllocaRegions don't have associated symbols, though, so we don't actually
+ // have a way to track their liveness.
+ if (isa<AllocaRegion>(MR))
+ return true;
+
+ if (isa<CXXThisRegion>(MR))
+ return true;
+
+ if (isa<MemSpaceRegion>(MR))
+ return true;
+
+ return false;
+}
+
+bool SymbolReaper::isLive(SymbolRef sym) {
+ if (TheLiving.count(sym))
+ return true;
+
+ if (const SymbolDerived *derived = dyn_cast<SymbolDerived>(sym)) {
+ if (isLive(derived->getParentSymbol())) {
+ markLive(sym);
+ return true;
+ }
+ return false;
+ }
+
+ if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) {
+ if (IsLiveRegion(*this, extent->getRegion())) {
+ markLive(sym);
+ return true;
+ }
+ return false;
+ }
+
+ if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) {
+ if (MetadataInUse.count(sym)) {
+ if (IsLiveRegion(*this, metadata->getRegion())) {
+ markLive(sym);
+ MetadataInUse.erase(sym);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Interogate the symbol. It may derive from an input value to
+ // the analyzed function/method.
+ return isa<SymbolRegionValue>(sym);
+}
+
+bool SymbolReaper::isLive(const Stmt* ExprVal) const {
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, ExprVal);
+}
+
+bool SymbolReaper::isLive(const VarRegion *VR) const {
+ const StackFrameContext *VarContext = VR->getStackFrame();
+ const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
+
+ if (VarContext == CurrentContext)
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, VR->getDecl());
+
+ return VarContext->isParentOf(CurrentContext);
+}
+
+SymbolVisitor::~SymbolVisitor() {}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
new file mode 100644
index 0000000..230b6a10
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
@@ -0,0 +1,70 @@
+//===--- TextPathDiagnostics.cpp - Text Diagnostics for Paths ---*- 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 TextPathDiagnostics object.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+using namespace ento;
+using namespace llvm;
+
+namespace {
+
+/// \brief Simple path diagnostic client used for outputting as diagnostic notes
+/// the sequence of events.
+class TextPathDiagnostics : public PathDiagnosticClient {
+ const std::string OutputFile;
+ Diagnostic &Diag;
+
+public:
+ TextPathDiagnostics(const std::string& output, Diagnostic &diag)
+ : OutputFile(output), Diag(diag) {}
+
+ void HandlePathDiagnostic(const PathDiagnostic* D);
+
+ void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade) { }
+
+ virtual llvm::StringRef getName() const {
+ return "TextPathDiagnostics";
+ }
+
+ PathGenerationScheme getGenerationScheme() const { return Minimal; }
+ bool supportsLogicalOpControlFlow() const { return true; }
+ bool supportsAllBlockEdges() const { return true; }
+ virtual bool useVerboseDescription() const { return true; }
+};
+
+} // end anonymous namespace
+
+PathDiagnosticClient*
+ento::createTextPathDiagnosticClient(const std::string& out,
+ const Preprocessor &PP) {
+ return new TextPathDiagnostics(out, PP.getDiagnostics());
+}
+
+void TextPathDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
+ if (!D)
+ return;
+
+ if (D->empty()) {
+ delete D;
+ return;
+ }
+
+ for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I) {
+ unsigned diagID = Diag.getDiagnosticIDs()->getCustomDiagID(
+ DiagnosticIDs::Note, I->getString());
+ Diag.Report(I->getLocation().asLocation(), diagID);
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
new file mode 100644
index 0000000..dbfebcc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -0,0 +1,544 @@
+//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// "Meta" ASTConsumer for running different source analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AnalysisConsumer.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Analyses/UninitializedValues.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
+
+// FIXME: Restructure checker registration.
+#include "../Checkers/ClangSACheckers.h"
+#include "../Checkers/ExperimentalChecks.h"
+#include "../Checkers/InternalChecks.h"
+#include "../Checkers/BasicObjCFoundationChecks.h"
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/AnalyzerOptions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/ADT/OwningPtr.h"
+
+using namespace clang;
+using namespace ento;
+
+static ExplodedNode::Auditor* CreateUbiViz();
+
+//===----------------------------------------------------------------------===//
+// Special PathDiagnosticClients.
+//===----------------------------------------------------------------------===//
+
+static PathDiagnosticClient*
+createPlistHTMLDiagnosticClient(const std::string& prefix,
+ const Preprocessor &PP) {
+ PathDiagnosticClient *PD =
+ createHTMLDiagnosticClient(llvm::sys::path::parent_path(prefix), PP);
+ return createPlistDiagnosticClient(prefix, PP, PD);
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer declaration.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class AnalysisConsumer : public ASTConsumer {
+public:
+ typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
+ typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,
+ TranslationUnitDecl &TU);
+
+private:
+ typedef std::vector<CodeAction> Actions;
+ typedef std::vector<TUAction> TUActions;
+
+ Actions FunctionActions;
+ Actions ObjCMethodActions;
+ Actions ObjCImplementationActions;
+ Actions CXXMethodActions;
+
+public:
+ ASTContext* Ctx;
+ const Preprocessor &PP;
+ const std::string OutDir;
+ AnalyzerOptions Opts;
+
+ // PD is owned by AnalysisManager.
+ PathDiagnosticClient *PD;
+
+ StoreManagerCreator CreateStoreMgr;
+ ConstraintManagerCreator CreateConstraintMgr;
+
+ llvm::OwningPtr<CheckerManager> checkerMgr;
+ llvm::OwningPtr<AnalysisManager> Mgr;
+
+ AnalysisConsumer(const Preprocessor& pp,
+ const std::string& outdir,
+ const AnalyzerOptions& opts)
+ : Ctx(0), PP(pp), OutDir(outdir),
+ Opts(opts), PD(0) {
+ DigestAnalyzerOptions();
+ }
+
+ void DigestAnalyzerOptions() {
+ // Create the PathDiagnosticClient.
+ if (!OutDir.empty()) {
+ switch (Opts.AnalysisDiagOpt) {
+ default:
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
+ case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
+#include "clang/Frontend/Analyses.def"
+ }
+ } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
+ // Create the text client even without a specified output file since
+ // it just uses diagnostic notes.
+ PD = createTextPathDiagnosticClient("", PP);
+ }
+
+ // Create the analyzer component creators.
+ switch (Opts.AnalysisStoreOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
+ case NAME##Model: CreateStoreMgr = CREATEFN; break;
+#include "clang/Frontend/Analyses.def"
+ }
+
+ switch (Opts.AnalysisConstraintsOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
+ case NAME##Model: CreateConstraintMgr = CREATEFN; break;
+#include "clang/Frontend/Analyses.def"
+ }
+ }
+
+ void DisplayFunction(const Decl *D) {
+ if (!Opts.AnalyzerDisplayProgress)
+ return;
+
+ SourceManager &SM = Mgr->getASTContext().getSourceManager();
+ PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+ if (Loc.isValid()) {
+ llvm::errs() << "ANALYZE: " << Loc.getFilename();
+
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ const NamedDecl *ND = cast<NamedDecl>(D);
+ llvm::errs() << ' ' << ND << '\n';
+ }
+ else if (isa<BlockDecl>(D)) {
+ llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
+ << Loc.getColumn() << '\n';
+ }
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ Selector S = MD->getSelector();
+ llvm::errs() << ' ' << S.getAsString();
+ }
+ }
+ }
+
+ void addCodeAction(CodeAction action) {
+ FunctionActions.push_back(action);
+ ObjCMethodActions.push_back(action);
+ CXXMethodActions.push_back(action);
+ }
+
+ void addObjCImplementationAction(CodeAction action) {
+ ObjCImplementationActions.push_back(action);
+ }
+
+ virtual void Initialize(ASTContext &Context) {
+ Ctx = &Context;
+ checkerMgr.reset(registerCheckers(Opts, PP.getDiagnostics()));
+ Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+ PP.getLangOptions(), PD,
+ CreateStoreMgr, CreateConstraintMgr,
+ checkerMgr.get(),
+ /* Indexer */ 0,
+ Opts.MaxNodes, Opts.MaxLoop,
+ Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
+ Opts.PurgeDead, Opts.EagerlyAssume,
+ Opts.TrimGraph, Opts.InlineCall,
+ Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
+ Opts.CFGAddInitializers,
+ Opts.EagerlyTrimEGraph));
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &C);
+ void HandleDeclContext(ASTContext &C, DeclContext *dc);
+
+ void HandleCode(Decl *D, Actions& actions);
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer implementation.
+//===----------------------------------------------------------------------===//
+
+void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
+ BugReporter BR(*Mgr);
+ for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
+ I != E; ++I) {
+ Decl *D = *I;
+ checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
+
+ switch (D->getKind()) {
+ case Decl::Namespace: {
+ HandleDeclContext(C, cast<NamespaceDecl>(D));
+ break;
+ }
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::CXXMethod:
+ case Decl::Function: {
+ FunctionDecl* FD = cast<FunctionDecl>(D);
+ // We skip function template definitions, as their semantics is
+ // only determined when they are instantiated.
+ if (FD->isThisDeclarationADefinition() &&
+ !FD->isDependentContext()) {
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
+ FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
+ break;
+ DisplayFunction(FD);
+ HandleCode(FD, FunctionActions);
+ }
+ break;
+ }
+
+ case Decl::ObjCImplementation: {
+ ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I);
+ HandleCode(ID, ObjCImplementationActions);
+
+ for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(),
+ ME = ID->meth_end(); MI != ME; ++MI) {
+ if ((*MI)->isThisDeclarationADefinition()) {
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
+ Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())
+ break;
+ DisplayFunction(*MI);
+ HandleCode(*MI, ObjCMethodActions);
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+
+void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
+ BugReporter BR(*Mgr);
+ TranslationUnitDecl *TU = C.getTranslationUnitDecl();
+ checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
+ HandleDeclContext(C, TU);
+
+ // Explicitly destroy the PathDiagnosticClient. This will flush its output.
+ // FIXME: This should be replaced with something that doesn't rely on
+ // side-effects in PathDiagnosticClient's destructor. This is required when
+ // used with option -disable-free.
+ Mgr.reset(NULL);
+}
+
+static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
+ if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ WL.push_back(BD);
+
+ for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
+ I!=E; ++I)
+ if (DeclContext *DC = dyn_cast<DeclContext>(*I))
+ FindBlocks(DC, WL);
+}
+
+void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) {
+
+ // Don't run the actions if an error has occured with parsing the file.
+ Diagnostic &Diags = PP.getDiagnostics();
+ if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
+ return;
+
+ // Don't run the actions on declarations in header files unless
+ // otherwise specified.
+ SourceManager &SM = Ctx->getSourceManager();
+ SourceLocation SL = SM.getInstantiationLoc(D->getLocation());
+ if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
+ return;
+
+ // Clear the AnalysisManager of old AnalysisContexts.
+ Mgr->ClearContexts();
+
+ // Dispatch on the actions.
+ llvm::SmallVector<Decl*, 10> WL;
+ WL.push_back(D);
+
+ if (D->hasBody() && Opts.AnalyzeNestedBlocks)
+ FindBlocks(cast<DeclContext>(D), WL);
+
+ BugReporter BR(*Mgr);
+ for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
+ WI != WE; ++WI)
+ if ((*WI)->hasBody())
+ checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
+
+ for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
+ for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
+ WI != WE; ++WI)
+ (*I)(*this, *Mgr, *WI);
+}
+
+//===----------------------------------------------------------------------===//
+// Analyses
+//===----------------------------------------------------------------------===//
+
+static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ if (CFG* c = mgr.getCFG(D)) {
+ CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
+ }
+}
+
+
+static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D,
+ TransferFuncs* tf) {
+
+ llvm::OwningPtr<TransferFuncs> TF(tf);
+
+ // Construct the analysis engine. We first query for the LiveVariables
+ // information to see if the CFG is valid.
+ // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
+ if (!mgr.getLiveVariables(D))
+ return;
+ ExprEngine Eng(mgr, TF.take());
+
+ if (C.Opts.EnableExperimentalInternalChecks)
+ RegisterExperimentalInternalChecks(Eng);
+
+ RegisterNSErrorChecks(Eng.getBugReporter(), Eng, *D);
+
+ if (C.Opts.EnableExperimentalChecks)
+ RegisterExperimentalChecks(Eng);
+
+ if (C.Opts.BufferOverflows)
+ RegisterArrayBoundCheckerV2(Eng);
+
+ // Enable AnalyzerStatsChecker if it was given as an argument
+ if (C.Opts.AnalyzerStats)
+ RegisterAnalyzerStatsChecker(Eng);
+
+ // Set the graph auditor.
+ llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
+ if (mgr.shouldVisualizeUbigraph()) {
+ Auditor.reset(CreateUbiViz());
+ ExplodedNode::SetAuditor(Auditor.get());
+ }
+
+ // Execute the worklist algorithm.
+ Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
+
+ // Release the auditor (if any) so that it doesn't monitor the graph
+ // created BugReporter.
+ ExplodedNode::SetAuditor(0);
+
+ // Visualize the exploded graph.
+ if (mgr.shouldVisualizeGraphviz())
+ Eng.ViewGraph(mgr.shouldTrimGraph());
+
+ // Display warnings.
+ Eng.getBugReporter().FlushReports();
+}
+
+static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D, bool GCEnabled) {
+
+ TransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
+ GCEnabled,
+ mgr.getLangOptions());
+
+ ActionExprEngine(C, mgr, D, TF);
+}
+
+static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+
+ switch (mgr.getLangOptions().getGCMode()) {
+ default:
+ assert (false && "Invalid GC mode.");
+ case LangOptions::NonGC:
+ ActionObjCMemCheckerAux(C, mgr, D, false);
+ break;
+
+ case LangOptions::GCOnly:
+ ActionObjCMemCheckerAux(C, mgr, D, true);
+ break;
+
+ case LangOptions::HybridGC:
+ ActionObjCMemCheckerAux(C, mgr, D, false);
+ ActionObjCMemCheckerAux(C, mgr, D, true);
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// AnalysisConsumer creation.
+//===----------------------------------------------------------------------===//
+
+ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
+ const std::string& OutDir,
+ const AnalyzerOptions& Opts) {
+ llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
+
+ for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
+ switch (Opts.AnalysisList[i]) {
+#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
+ case NAME:\
+ C->add ## SCOPE ## Action(&Action ## NAME);\
+ break;
+#include "clang/Frontend/Analyses.def"
+ default: break;
+ }
+
+ // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
+ pp.getDiagnostics().setWarningsAsErrors(false);
+
+ return C.take();
+}
+
+//===----------------------------------------------------------------------===//
+// Ubigraph Visualization. FIXME: Move to separate file.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class UbigraphViz : public ExplodedNode::Auditor {
+ llvm::OwningPtr<llvm::raw_ostream> Out;
+ llvm::sys::Path Dir, Filename;
+ unsigned Cntr;
+
+ typedef llvm::DenseMap<void*,unsigned> VMap;
+ VMap M;
+
+public:
+ UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
+ llvm::sys::Path& filename);
+
+ ~UbigraphViz();
+
+ virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);
+};
+
+} // end anonymous namespace
+
+static ExplodedNode::Auditor* CreateUbiViz() {
+ std::string ErrMsg;
+
+ llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
+ if (!ErrMsg.empty())
+ return 0;
+
+ llvm::sys::Path Filename = Dir;
+ Filename.appendComponent("llvm_ubi");
+ Filename.makeUnique(true,&ErrMsg);
+
+ if (!ErrMsg.empty())
+ return 0;
+
+ llvm::errs() << "Writing '" << Filename.str() << "'.\n";
+
+ llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
+ Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
+
+ if (!ErrMsg.empty())
+ return 0;
+
+ return new UbigraphViz(Stream.take(), Dir, Filename);
+}
+
+void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {
+
+ assert (Src != Dst && "Self-edges are not allowed.");
+
+ // Lookup the Src. If it is a new node, it's a root.
+ VMap::iterator SrcI= M.find(Src);
+ unsigned SrcID;
+
+ if (SrcI == M.end()) {
+ M[Src] = SrcID = Cntr++;
+ *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
+ }
+ else
+ SrcID = SrcI->second;
+
+ // Lookup the Dst.
+ VMap::iterator DstI= M.find(Dst);
+ unsigned DstID;
+
+ if (DstI == M.end()) {
+ M[Dst] = DstID = Cntr++;
+ *Out << "('vertex', " << DstID << ")\n";
+ }
+ else {
+ // We have hit DstID before. Change its style to reflect a cache hit.
+ DstID = DstI->second;
+ *Out << "('change_vertex_style', " << DstID << ", 1)\n";
+ }
+
+ // Add the edge.
+ *Out << "('edge', " << SrcID << ", " << DstID
+ << ", ('arrow','true'), ('oriented', 'true'))\n";
+}
+
+UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
+ llvm::sys::Path& filename)
+ : Out(out), Dir(dir), Filename(filename), Cntr(0) {
+
+ *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
+ *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
+ " ('size', '1.5'))\n";
+}
+
+UbigraphViz::~UbigraphViz() {
+ Out.reset(0);
+ llvm::errs() << "Running 'ubiviz' program... ";
+ std::string ErrMsg;
+ llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
+ std::vector<const char*> args;
+ args.push_back(Ubiviz.c_str());
+ args.push_back(Filename.c_str());
+ args.push_back(0);
+
+ if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
+ llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
+ }
+
+ // Delete the directory.
+ Dir.eraseFromDisk(true);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h
new file mode 100644
index 0000000..646fe97
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -0,0 +1,41 @@
+//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains the functions necessary for a front-end to run various
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_ANALYSISCONSUMER_H
+#define LLVM_CLANG_GR_ANALYSISCONSUMER_H
+
+#include <string>
+
+namespace clang {
+
+class AnalyzerOptions;
+class ASTConsumer;
+class Preprocessor;
+class Diagnostic;
+
+namespace ento {
+class CheckerManager;
+
+/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
+/// analysis passes. (The set of analyses run is controlled by command-line
+/// options.)
+ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
+ const std::string &output,
+ const AnalyzerOptions& Opts);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
new file mode 100644
index 0000000..cd9ac1b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LLVM_NO_RTTI 1)
+
+set(LLVM_USED_LIBS clangBasic clangLex clangAST clangFrontend clangRewrite)
+
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../Checkers )
+
+add_clang_library(clangStaticAnalyzerFrontend
+ AnalysisConsumer.cpp
+ CheckerRegistration.cpp
+ FrontendActions.cpp
+ )
+
+add_dependencies(clangStaticAnalyzerFrontend
+ clangStaticAnalyzerCheckers
+ clangStaticAnalyzerCore
+ ClangAttrClasses
+ ClangAttrList
+ ClangDeclNodes
+ ClangStmtNode
+ )
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
new file mode 100644
index 0000000..6625729
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -0,0 +1,50 @@
+//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the registration function for the analyzer checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "../Checkers/ClangSACheckerProvider.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "clang/Frontend/AnalyzerOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang;
+using namespace ento;
+
+CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
+ Diagnostic &diags) {
+ llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager());
+
+ llvm::SmallVector<CheckerOptInfo, 8> checkerOpts;
+ for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
+ const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
+ checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
+ }
+
+ llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
+ provider->registerCheckers(*checkerMgr,
+ checkerOpts.data(), checkerOpts.size());
+
+ // FIXME: Load CheckerProviders from plugins.
+
+ for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
+ if (checkerOpts[i].isUnclaimed())
+ diags.Report(diag::warn_unkwown_analyzer_checker)
+ << checkerOpts[i].getName();
+ }
+
+ return checkerMgr.take();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/FrontendActions.cpp
new file mode 100644
index 0000000..a59cc68
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/FrontendActions.cpp
@@ -0,0 +1,22 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "AnalysisConsumer.h"
+using namespace clang;
+using namespace ento;
+
+ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateAnalysisConsumer(CI.getPreprocessor(),
+ CI.getFrontendOpts().OutputFile,
+ CI.getAnalyzerOpts());
+}
+
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/Makefile b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/Makefile
new file mode 100644
index 0000000..2698120
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/Makefile
@@ -0,0 +1,19 @@
+##===- clang/lib/StaticAnalyzer/Frontend/Makefile ----------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# Starting point into the static analyzer land for the driver.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../..
+LIBRARYNAME := clangStaticAnalyzerFrontend
+
+CPP.Flags += -I${PROJ_OBJ_DIR}/../Checkers
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Makefile b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Makefile
new file mode 100644
index 0000000..c166f06
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Makefile
@@ -0,0 +1,18 @@
+##===- clang/lib/StaticAnalyzer/Makefile -------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This implements analyses built on top of source-level CFGs.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+DIRS := Checkers Frontend
+PARALLEL_DIRS := Core
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/README.txt b/contrib/llvm/tools/clang/lib/StaticAnalyzer/README.txt
new file mode 100644
index 0000000..1406eca
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/README.txt
@@ -0,0 +1,139 @@
+//===----------------------------------------------------------------------===//
+// Clang Static Analyzer
+//===----------------------------------------------------------------------===//
+
+= Library Structure =
+
+The analyzer library has two layers: a (low-level) static analysis
+engine (GRExprEngine.cpp and friends), and some static checkers
+(*Checker.cpp). The latter are built on top of the former via the
+Checker and CheckerVisitor interfaces (Checker.h and
+CheckerVisitor.h). The Checker interface is designed to be minimal
+and simple for checker writers, and attempts to isolate them from much
+of the gore of the internal analysis engine.
+
+= How It Works =
+
+The analyzer is inspired by several foundational research papers ([1],
+[2]). (FIXME: kremenek to add more links)
+
+In a nutshell, the analyzer is basically a source code simulator that
+traces out possible paths of execution. The state of the program
+(values of variables and expressions) is encapsulated by the state
+(GRState). A location in the program is called a program point
+(ProgramPoint), and the combination of state and program point is a
+node in an exploded graph (ExplodedGraph). The term "exploded" comes
+from exploding the control-flow edges in the control-flow graph (CFG).
+
+Conceptually the analyzer does a reachability analysis through the
+ExplodedGraph. We start at a root node, which has the entry program
+point and initial state, and then simulate transitions by analyzing
+individual expressions. The analysis of an expression can cause the
+state to change, resulting in a new node in the ExplodedGraph with an
+updated program point and an updated state. A bug is found by hitting
+a node that satisfies some "bug condition" (basically a violation of a
+checking invariant).
+
+The analyzer traces out multiple paths by reasoning about branches and
+then bifurcating the state: on the true branch the conditions of the
+branch are assumed to be true and on the false branch the conditions
+of the branch are assumed to be false. Such "assumptions" create
+constraints on the values of the program, and those constraints are
+recorded in the GRState object (and are manipulated by the
+ConstraintManager). If assuming the conditions of a branch would
+cause the constraints to be unsatisfiable, the branch is considered
+infeasible and that path is not taken. This is how we get
+path-sensitivity. We reduce exponential blow-up by caching nodes. If
+a new node with the same state and program point as an existing node
+would get generated, the path "caches out" and we simply reuse the
+existing node. Thus the ExplodedGraph is not a DAG; it can contain
+cycles as paths loop back onto each other and cache out.
+
+GRState and ExplodedNodes are basically immutable once created. Once
+one creates a GRState, you need to create a new one to get a new
+GRState. This immutability is key since the ExplodedGraph represents
+the behavior of the analyzed program from the entry point. To
+represent these efficiently, we use functional data structures (e.g.,
+ImmutableMaps) which share data between instances.
+
+Finally, individual Checkers work by also manipulating the analysis
+state. The analyzer engine talks to them via a visitor interface.
+For example, the PreVisitCallExpr() method is called by GRExprEngine
+to tell the Checker that we are about to analyze a CallExpr, and the
+checker is asked to check for any preconditions that might not be
+satisfied. The checker can do nothing, or it can generate a new
+GRState and ExplodedNode which contains updated checker state. If it
+finds a bug, it can tell the BugReporter object about the bug,
+providing it an ExplodedNode which is the last node in the path that
+triggered the problem.
+
+= Notes about C++ =
+
+Since now constructors are seen before the variable that is constructed
+in the CFG, we create a temporary object as the destination region that
+is constructed into. See ExprEngine::VisitCXXConstructExpr().
+
+In ExprEngine::processCallExit(), we always bind the object region to the
+evaluated CXXConstructExpr. Then in VisitDeclStmt(), we compute the
+corresponding lazy compound value if the variable is not a reference, and
+bind the variable region to the lazy compound value. If the variable
+is a reference, just use the object region as the initilizer value.
+
+Before entering a C++ method (or ctor/dtor), the 'this' region is bound
+to the object region. In ctors, we synthesize 'this' region with
+CXXRecordDecl*, which means we do not use type qualifiers. In methods, we
+synthesize 'this' region with CXXMethodDecl*, which has getThisType()
+taking type qualifiers into account. It does not matter we use qualified
+'this' region in one method and unqualified 'this' region in another
+method, because we only need to ensure the 'this' region is consistent
+when we synthesize it and create it directly from CXXThisExpr in a single
+method call.
+
+= Working on the Analyzer =
+
+If you are interested in bringing up support for C++ expressions, the
+best place to look is the visitation logic in GRExprEngine, which
+handles the simulation of individual expressions. There are plenty of
+examples there of how other expressions are handled.
+
+If you are interested in writing checkers, look at the Checker and
+CheckerVisitor interfaces (Checker.h and CheckerVisitor.h). Also look
+at the files named *Checker.cpp for examples on how you can implement
+these interfaces.
+
+= Debugging the Analyzer =
+
+There are some useful command-line options for debugging. For example:
+
+$ clang -cc1 -help | grep analyze
+ -analyze-function <value>
+ -analyzer-display-progress
+ -analyzer-viz-egraph-graphviz
+ ...
+
+The first allows you to specify only analyzing a specific function.
+The second prints to the console what function is being analyzed. The
+third generates a graphviz dot file of the ExplodedGraph. This is
+extremely useful when debugging the analyzer and viewing the
+simulation results.
+
+Of course, viewing the CFG (Control-Flow Graph) is also useful:
+
+$ clang -cc1 -help | grep cfg
+ -cfg-add-implicit-dtors Add C++ implicit destructors to CFGs for all analyses
+ -cfg-add-initializers Add C++ initializers to CFGs for all analyses
+ -cfg-dump Display Control-Flow Graphs
+ -cfg-view View Control-Flow Graphs using GraphViz
+ -unoptimized-cfg Generate unoptimized CFGs for all analyses
+
+-cfg-dump dumps a textual representation of the CFG to the console,
+and -cfg-view creates a GraphViz representation.
+
+= References =
+
+[1] Precise interprocedural dataflow analysis via graph reachability,
+ T Reps, S Horwitz, and M Sagiv, POPL '95,
+ http://portal.acm.org/citation.cfm?id=199462
+
+[2] A memory model for static analysis of C programs, Z Xu, T
+ Kremenek, and J Zhang, http://lcs.ios.ac.cn/~xzx/memmodel.pdf
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp
new file mode 100644
index 0000000..7fb394f
--- /dev/null
+++ b/contrib/llvm/tools/clang/tools/driver/cc1_main.cpp
@@ -0,0 +1,182 @@
+//===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1 functionality, which implements the
+// core compiler functionality along with a number of additional tools for
+// demonstration and testing purposes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/FrontendTool/Utils.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetSelect.h"
+#include <cstdio>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Main driver
+//===----------------------------------------------------------------------===//
+
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+ Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // We cannot recover from llvm errors.
+ exit(1);
+}
+
+// FIXME: Define the need for this testing away.
+static int cc1_test(Diagnostic &Diags,
+ const char **ArgBegin, const char **ArgEnd) {
+ using namespace clang::driver;
+
+ llvm::errs() << "cc1 argv:";
+ for (const char **i = ArgBegin; i != ArgEnd; ++i)
+ llvm::errs() << " \"" << *i << '"';
+ llvm::errs() << "\n";
+
+ // Parse the arguments.
+ OptTable *Opts = createCC1OptTable();
+ unsigned MissingArgIndex, MissingArgCount;
+ InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd,
+ MissingArgIndex, MissingArgCount);
+
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diags.Report(clang::diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+ // Dump the parsed arguments.
+ llvm::errs() << "cc1 parsed options:\n";
+ for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
+ it != ie; ++it)
+ (*it)->dump();
+
+ // Create a compiler invocation.
+ llvm::errs() << "cc1 creating invocation.\n";
+ CompilerInvocation Invocation;
+ CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags);
+
+ // Convert the invocation back to argument strings.
+ std::vector<std::string> InvocationArgs;
+ Invocation.toArgs(InvocationArgs);
+
+ // Dump the converted arguments.
+ llvm::SmallVector<const char*, 32> Invocation2Args;
+ llvm::errs() << "invocation argv :";
+ for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
+ Invocation2Args.push_back(InvocationArgs[i].c_str());
+ llvm::errs() << " \"" << InvocationArgs[i] << '"';
+ }
+ llvm::errs() << "\n";
+
+ // Convert those arguments to another invocation, and check that we got the
+ // same thing.
+ CompilerInvocation Invocation2;
+ CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
+ Invocation2Args.end(), Diags);
+
+ // FIXME: Implement CompilerInvocation comparison.
+ if (true) {
+ //llvm::errs() << "warning: Invocations differ!\n";
+
+ std::vector<std::string> Invocation2Args;
+ Invocation2.toArgs(Invocation2Args);
+ llvm::errs() << "invocation2 argv:";
+ for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i)
+ llvm::errs() << " \"" << Invocation2Args[i] << '"';
+ llvm::errs() << "\n";
+ }
+
+ return 0;
+}
+
+int cc1_main(const char **ArgBegin, const char **ArgEnd,
+ const char *Argv0, void *MainAddr) {
+ llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+
+ // Run clang -cc1 test.
+ if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
+ Diagnostic Diags(DiagID, new TextDiagnosticPrinter(llvm::errs(),
+ DiagnosticOptions()));
+ return cc1_test(Diags, ArgBegin + 1, ArgEnd);
+ }
+
+ // Initialize targets first, so that --version shows registered targets.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+
+ // Buffer diagnostics from argument parsing so that we can output them using a
+ // well formed diagnostic object.
+ TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
+ Diagnostic Diags(DiagID, DiagsBuffer);
+ CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd,
+ Diags);
+
+ // Infer the builtin include path if unspecified.
+ if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
+ Clang->getHeaderSearchOpts().ResourceDir.empty())
+ Clang->getHeaderSearchOpts().ResourceDir =
+ CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
+
+ // Create the actual diagnostics engine.
+ Clang->createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
+ if (!Clang->hasDiagnostics())
+ return 1;
+
+ // Set an error handler, so that any LLVM backend diagnostics go through our
+ // error handler.
+ llvm::install_fatal_error_handler(LLVMErrorHandler,
+ static_cast<void*>(&Clang->getDiagnostics()));
+
+ DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
+
+ // Execute the frontend actions.
+ bool Success = ExecuteCompilerInvocation(Clang.get());
+
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now. This happens in -disable-free mode.
+ llvm::TimerGroup::printAll(llvm::errs());
+
+ // Our error handler depends on the Diagnostics object, which we're
+ // potentially about to delete. Uninstall the handler now so that any
+ // later errors use the default handling behavior instead.
+ llvm::remove_fatal_error_handler();
+
+ // When running with -disable-free, don't do any destruction or shutdown.
+ if (Clang->getFrontendOpts().DisableFree) {
+ if (Clang->getFrontendOpts().ShowStats)
+ llvm::PrintStatistics();
+ Clang.take();
+ return !Success;
+ }
+
+ // Managed static deconstruction. Useful for making things like
+ // -time-passes usable.
+ llvm::llvm_shutdown();
+
+ return !Success;
+}
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
new file mode 100644
index 0000000..1d544f3
--- /dev/null
+++ b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
@@ -0,0 +1,400 @@
+//===-- cc1as_main.cpp - Clang Assembler ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1as functionality, which implements
+// the direct interface to the LLVM MC based assembler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/CC1AsOptions.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Target/TargetAsmBackend.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetAsmParser.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
+using namespace clang;
+using namespace clang::driver;
+using namespace llvm;
+
+namespace {
+
+/// \brief Helper class for representing a single invocation of the assembler.
+struct AssemblerInvocation {
+ /// @name Target Options
+ /// @{
+
+ std::string Triple;
+
+ /// @}
+ /// @name Language Options
+ /// @{
+
+ std::vector<std::string> IncludePaths;
+ unsigned NoInitialTextSection : 1;
+
+ /// @}
+ /// @name Frontend Options
+ /// @{
+
+ std::string InputFile;
+ std::vector<std::string> LLVMArgs;
+ std::string OutputPath;
+ enum FileType {
+ FT_Asm, ///< Assembly (.s) output, transliterate mode.
+ FT_Null, ///< No output, for timing purposes.
+ FT_Obj ///< Object file output.
+ };
+ FileType OutputType;
+ unsigned ShowHelp : 1;
+ unsigned ShowVersion : 1;
+
+ /// @}
+ /// @name Transliterate Options
+ /// @{
+
+ unsigned OutputAsmVariant;
+ unsigned ShowEncoding : 1;
+ unsigned ShowInst : 1;
+
+ /// @}
+ /// @name Assembler Options
+ /// @{
+
+ unsigned RelaxAll : 1;
+ unsigned NoExecStack : 1;
+
+ /// @}
+
+public:
+ AssemblerInvocation() {
+ Triple = "";
+ NoInitialTextSection = 0;
+ InputFile = "-";
+ OutputPath = "-";
+ OutputType = FT_Asm;
+ OutputAsmVariant = 0;
+ ShowInst = 0;
+ ShowEncoding = 0;
+ RelaxAll = 0;
+ NoExecStack = 0;
+ }
+
+ static void CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
+ const char **ArgEnd, Diagnostic &Diags);
+};
+
+}
+
+void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
+ const char **ArgBegin,
+ const char **ArgEnd,
+ Diagnostic &Diags) {
+ using namespace clang::driver::cc1asoptions;
+ // Parse the arguments.
+ OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
+ unsigned MissingArgIndex, MissingArgCount;
+ OwningPtr<InputArgList> Args(
+ OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
+
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diags.Report(diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+ // Issue errors on unknown arguments.
+ for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
+ ie = Args->filtered_end(); it != ie; ++it)
+ Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
+
+ // Construct the invocation.
+
+ // Target Options
+ Opts.Triple = Triple::normalize(Args->getLastArgValue(OPT_triple));
+ if (Opts.Triple.empty()) // Use the host triple if unspecified.
+ Opts.Triple = sys::getHostTriple();
+
+ // Language Options
+ Opts.IncludePaths = Args->getAllArgValues(OPT_I);
+ Opts.NoInitialTextSection = Args->hasArg(OPT_n);
+
+ // Frontend Options
+ if (Args->hasArg(OPT_INPUT)) {
+ bool First = true;
+ for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
+ ie = Args->filtered_end(); it != ie; ++it, First=false) {
+ const Arg *A = it;
+ if (First)
+ Opts.InputFile = A->getValue(*Args);
+ else
+ Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
+ }
+ }
+ Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
+ Opts.OutputPath = Args->getLastArgValue(OPT_o);
+ if (Arg *A = Args->getLastArg(OPT_filetype)) {
+ StringRef Name = A->getValue(*Args);
+ unsigned OutputType = StringSwitch<unsigned>(Name)
+ .Case("asm", FT_Asm)
+ .Case("null", FT_Null)
+ .Case("obj", FT_Obj)
+ .Default(~0U);
+ if (OutputType == ~0U)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(*Args) << Name;
+ else
+ Opts.OutputType = FileType(OutputType);
+ }
+ Opts.ShowHelp = Args->hasArg(OPT_help);
+ Opts.ShowVersion = Args->hasArg(OPT_version);
+
+ // Transliterate Options
+ Opts.OutputAsmVariant = Args->getLastArgIntValue(OPT_output_asm_variant,
+ 0, Diags);
+ Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
+ Opts.ShowInst = Args->hasArg(OPT_show_inst);
+
+ // Assemble Options
+ Opts.RelaxAll = Args->hasArg(OPT_relax_all);
+ Opts.NoExecStack = Args->hasArg(OPT_no_exec_stack);
+}
+
+static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
+ Diagnostic &Diags,
+ bool Binary) {
+ if (Opts.OutputPath.empty())
+ Opts.OutputPath = "-";
+
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT.
+ if (Opts.OutputPath != "-")
+ sys::RemoveFileOnSignal(sys::Path(Opts.OutputPath));
+
+ std::string Error;
+ raw_fd_ostream *Out =
+ new raw_fd_ostream(Opts.OutputPath.c_str(), Error,
+ (Binary ? raw_fd_ostream::F_Binary : 0));
+ if (!Error.empty()) {
+ Diags.Report(diag::err_fe_unable_to_open_output)
+ << Opts.OutputPath << Error;
+ return 0;
+ }
+
+ return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
+}
+
+static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
+ // Get the target specific parser.
+ std::string Error;
+ const Target *TheTarget(TargetRegistry::lookupTarget(Opts.Triple, Error));
+ if (!TheTarget) {
+ Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+ return false;
+ }
+
+ OwningPtr<MemoryBuffer> BufferPtr;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(Opts.InputFile, BufferPtr)) {
+ Error = ec.message();
+ Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
+ return false;
+ }
+ MemoryBuffer *Buffer = BufferPtr.take();
+
+ SourceMgr SrcMgr;
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
+
+ // Record the location of the include directories so that the lexer can find
+ // it later.
+ SrcMgr.setIncludeDirs(Opts.IncludePaths);
+
+ OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(Opts.Triple));
+ assert(MAI && "Unable to create target asm info!");
+
+ bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
+ formatted_raw_ostream *Out = GetOutputStream(Opts, Diags, IsBinary);
+ if (!Out)
+ return false;
+
+ // FIXME: We shouldn't need to do this (and link in codegen).
+ OwningPtr<TargetMachine> TM(TheTarget->createTargetMachine(Opts.Triple, ""));
+ if (!TM) {
+ Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+ return false;
+ }
+
+ const TargetAsmInfo *tai = new TargetAsmInfo(*TM);
+ MCContext Ctx(*MAI, tai);
+
+ OwningPtr<MCStreamer> Str;
+
+ const TargetLoweringObjectFile &TLOF =
+ TM->getTargetLowering()->getObjFileLowering();
+ const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(Ctx, *TM);
+
+ // FIXME: There is a bit of code duplication with addPassesToEmitFile.
+ if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
+ MCInstPrinter *IP =
+ TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI);
+ MCCodeEmitter *CE = 0;
+ TargetAsmBackend *TAB = 0;
+ if (Opts.ShowEncoding) {
+ CE = TheTarget->createCodeEmitter(*TM, Ctx);
+ TAB = TheTarget->createAsmBackend(Opts.Triple);
+ }
+ Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
+ /*useLoc*/ true, IP, CE, TAB,
+ Opts.ShowInst));
+ } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
+ Str.reset(createNullStreamer(Ctx));
+ } else {
+ assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
+ "Invalid file type!");
+ MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx);
+ TargetAsmBackend *TAB = TheTarget->createAsmBackend(Opts.Triple);
+ Str.reset(TheTarget->createObjectStreamer(Opts.Triple, Ctx, *TAB, *Out,
+ CE, Opts.RelaxAll,
+ Opts.NoExecStack));
+ Str.get()->InitSections();
+ }
+
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
+ *Str.get(), *MAI));
+ OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM));
+ if (!TAP) {
+ Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+ return false;
+ }
+
+ Parser->setTargetParser(*TAP.get());
+
+ bool Success = !Parser->Run(Opts.NoInitialTextSection);
+
+ // Close the output.
+ delete Out;
+
+ // Delete output on errors.
+ if (!Success && Opts.OutputPath != "-")
+ sys::Path(Opts.OutputPath).eraseFromDisk();
+
+ return Success;
+}
+
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+ Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // We cannot recover from llvm errors.
+ exit(1);
+}
+
+int cc1as_main(const char **ArgBegin, const char **ArgEnd,
+ const char *Argv0, void *MainAddr) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(ArgEnd - ArgBegin, ArgBegin);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ // Initialize targets and assembly printers/parsers.
+ InitializeAllTargetInfos();
+ // FIXME: We shouldn't need to initialize the Target(Machine)s.
+ InitializeAllTargets();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ // Construct our diagnostic client.
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(errs(), DiagnosticOptions());
+ DiagClient->setPrefix("clang -cc1as");
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ Diagnostic Diags(DiagID, DiagClient);
+
+ // Set an error handler, so that any LLVM backend diagnostics go through our
+ // error handler.
+ ScopedFatalErrorHandler FatalErrorHandler
+ (LLVMErrorHandler, static_cast<void*>(&Diags));
+
+ // Parse the arguments.
+ AssemblerInvocation Asm;
+ AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags);
+
+ // Honor -help.
+ if (Asm.ShowHelp) {
+ llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1AsOptTable());
+ Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler");
+ return 0;
+ }
+
+ // Honor -version.
+ //
+ // FIXME: Use a better -version message?
+ if (Asm.ShowVersion) {
+ llvm::cl::PrintVersionMessage();
+ return 0;
+ }
+
+ // Honor -mllvm.
+ //
+ // FIXME: Remove this, one day.
+ if (!Asm.LLVMArgs.empty()) {
+ unsigned NumArgs = Asm.LLVMArgs.size();
+ const char **Args = new const char*[NumArgs + 2];
+ Args[0] = "clang (LLVM option parsing)";
+ for (unsigned i = 0; i != NumArgs; ++i)
+ Args[i + 1] = Asm.LLVMArgs[i].c_str();
+ Args[NumArgs + 1] = 0;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
+ }
+
+ // Execute the invocation, unless there were parsing errors.
+ bool Success = false;
+ if (!Diags.hasErrorOccurred())
+ Success = ExecuteAssembler(Asm, Diags);
+
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now.
+ TimerGroup::printAll(errs());
+
+ return !Success;
+}
diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp
new file mode 100644
index 0000000..0b5d2c9
--- /dev/null
+++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp
@@ -0,0 +1,394 @@
+//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang driver; it is a thin wrapper
+// for functionality in the Driver clang library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Option.h"
+#include "clang/Frontend/DiagnosticOptions.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+#include <cctype>
+using namespace clang;
+using namespace clang::driver;
+
+llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
+ if (!CanonicalPrefixes)
+ return llvm::sys::Path(Argv0);
+
+ // This just needs to be some symbol in the binary; C++ doesn't
+ // allow taking the address of ::main however.
+ void *P = (void*) (intptr_t) GetExecutablePath;
+ return llvm::sys::Path::GetMainExecutable(Argv0, P);
+}
+
+static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
+ llvm::StringRef S) {
+ return SavedStrings.insert(S).first->c_str();
+}
+
+/// ApplyQAOverride - Apply a list of edits to the input argument lists.
+///
+/// The input string is a space separate list of edits to perform,
+/// they are applied in order to the input argument lists. Edits
+/// should be one of the following forms:
+///
+/// '#': Silence information about the changes to the command line arguments.
+///
+/// '^': Add FOO as a new argument at the beginning of the command line.
+///
+/// '+': Add FOO as a new argument at the end of the command line.
+///
+/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
+/// line.
+///
+/// 'xOPTION': Removes all instances of the literal argument OPTION.
+///
+/// 'XOPTION': Removes all instances of the literal argument OPTION,
+/// and the following argument.
+///
+/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
+/// at the end of the command line.
+///
+/// \param OS - The stream to write edit information to.
+/// \param Args - The vector of command line arguments.
+/// \param Edit - The override command to perform.
+/// \param SavedStrings - Set to use for storing string representations.
+static void ApplyOneQAOverride(llvm::raw_ostream &OS,
+ llvm::SmallVectorImpl<const char*> &Args,
+ llvm::StringRef Edit,
+ std::set<std::string> &SavedStrings) {
+ // This does not need to be efficient.
+
+ if (Edit[0] == '^') {
+ const char *Str =
+ SaveStringInSet(SavedStrings, Edit.substr(1));
+ OS << "### Adding argument " << Str << " at beginning\n";
+ Args.insert(Args.begin() + 1, Str);
+ } else if (Edit[0] == '+') {
+ const char *Str =
+ SaveStringInSet(SavedStrings, Edit.substr(1));
+ OS << "### Adding argument " << Str << " at end\n";
+ Args.push_back(Str);
+ } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
+ Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) {
+ llvm::StringRef MatchPattern = Edit.substr(2).split('/').first;
+ llvm::StringRef ReplPattern = Edit.substr(2).split('/').second;
+ ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
+
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
+
+ if (Repl != Args[i]) {
+ OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
+ Args[i] = SaveStringInSet(SavedStrings, Repl);
+ }
+ }
+ } else if (Edit[0] == 'x' || Edit[0] == 'X') {
+ std::string Option = Edit.substr(1, std::string::npos);
+ for (unsigned i = 1; i < Args.size();) {
+ if (Option == Args[i]) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ if (Edit[0] == 'X') {
+ if (i < Args.size()) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ } else
+ OS << "### Invalid X edit, end of command line!\n";
+ }
+ } else
+ ++i;
+ }
+ } else if (Edit[0] == 'O') {
+ for (unsigned i = 1; i < Args.size();) {
+ const char *A = Args[i];
+ if (A[0] == '-' && A[1] == 'O' &&
+ (A[2] == '\0' ||
+ (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
+ ('0' <= A[2] && A[2] <= '9'))))) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ } else
+ ++i;
+ }
+ OS << "### Adding argument " << Edit << " at end\n";
+ Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str()));
+ } else {
+ OS << "### Unrecognized edit: " << Edit << "\n";
+ }
+}
+
+/// ApplyQAOverride - Apply a comma separate list of edits to the
+/// input argument lists. See ApplyOneQAOverride.
+static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args,
+ const char *OverrideStr,
+ std::set<std::string> &SavedStrings) {
+ llvm::raw_ostream *OS = &llvm::errs();
+
+ if (OverrideStr[0] == '#') {
+ ++OverrideStr;
+ OS = &llvm::nulls();
+ }
+
+ *OS << "### QA_OVERRIDE_GCC3_OPTIONS: " << OverrideStr << "\n";
+
+ // This does not need to be efficient.
+
+ const char *S = OverrideStr;
+ while (*S) {
+ const char *End = ::strchr(S, ' ');
+ if (!End)
+ End = S + strlen(S);
+ if (End != S)
+ ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
+ S = End;
+ if (*S != '\0')
+ ++S;
+ }
+}
+
+extern int cc1_main(const char **ArgBegin, const char **ArgEnd,
+ const char *Argv0, void *MainAddr);
+extern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
+ const char *Argv0, void *MainAddr);
+
+static void ExpandArgsFromBuf(const char *Arg,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ const char *FName = Arg + 1;
+ llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
+ if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
+ return;
+ }
+
+ const char *Buf = MemBuf->getBufferStart();
+ char InQuote = ' ';
+ std::string CurArg;
+
+ for (const char *P = Buf; ; ++P) {
+ if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
+ if (!CurArg.empty()) {
+
+ if (CurArg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
+ } else {
+ ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
+ }
+
+ CurArg = "";
+ }
+ if (*P == '\0')
+ break;
+ else
+ continue;
+ }
+
+ if (isspace(*P)) {
+ if (InQuote != ' ')
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '"' || *P == '\'') {
+ if (InQuote == *P)
+ InQuote = ' ';
+ else if (InQuote == ' ')
+ InQuote = *P;
+ else
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '\\') {
+ ++P;
+ if (*P != '\0')
+ CurArg.push_back(*P);
+ continue;
+ }
+ CurArg.push_back(*P);
+ }
+}
+
+static void ExpandArgv(int argc, const char **argv,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ for (int i = 0; i < argc; ++i) {
+ const char *Arg = argv[i];
+ if (Arg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
+ continue;
+ }
+
+ ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
+ }
+}
+
+int main(int argc_, const char **argv_) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::PrettyStackTraceProgram X(argc_, argv_);
+
+ std::set<std::string> SavedStrings;
+ llvm::SmallVector<const char*, 256> argv;
+
+ ExpandArgv(argc_, argv_, argv, SavedStrings);
+
+ // Handle -cc1 integrated tools.
+ if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
+ llvm::StringRef Tool = argv[1] + 4;
+
+ if (Tool == "")
+ return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
+ (void*) (intptr_t) GetExecutablePath);
+ if (Tool == "as")
+ return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
+ (void*) (intptr_t) GetExecutablePath);
+
+ // Reject unknown tools.
+ llvm::errs() << "error: unknown integrated tool '" << Tool << "'\n";
+ return 1;
+ }
+
+ bool CanonicalPrefixes = true;
+ for (int i = 1, size = argv.size(); i < size; ++i) {
+ if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") {
+ CanonicalPrefixes = false;
+ break;
+ }
+ }
+
+ llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
+
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
+ DiagClient->setPrefix(llvm::sys::path::stem(Path.str()));
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ Diagnostic Diags(DiagID, DiagClient);
+
+#ifdef CLANG_IS_PRODUCTION
+ const bool IsProduction = true;
+# ifdef CLANGXX_IS_PRODUCTION
+ const bool CXXIsProduction = true;
+# else
+ const bool CXXIsProduction = false;
+# endif
+#else
+ const bool IsProduction = false;
+ const bool CXXIsProduction = false;
+#endif
+ Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
+ "a.out", IsProduction, CXXIsProduction,
+ Diags);
+
+ // Attempt to find the original path used to invoke the driver, to determine
+ // the installed path. We do this manually, because we want to support that
+ // path being a symlink.
+ {
+ llvm::SmallString<128> InstalledPath(argv[0]);
+
+ // Do a PATH lookup, if there are no directory components.
+ if (llvm::sys::path::filename(InstalledPath) == InstalledPath) {
+ llvm::sys::Path Tmp = llvm::sys::Program::FindProgramByName(
+ llvm::sys::path::filename(InstalledPath.str()));
+ if (!Tmp.empty())
+ InstalledPath = Tmp.str();
+ }
+ llvm::sys::fs::make_absolute(InstalledPath);
+ InstalledPath = llvm::sys::path::parent_path(InstalledPath);
+ bool exists;
+ if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists)
+ TheDriver.setInstalledDir(InstalledPath);
+ }
+
+ // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
+ // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
+ //
+ // Note that we intentionally want to use argv[0] here, to support "clang++"
+ // being a symlink.
+ //
+ // We use *argv instead of argv[0] to work around a bogus g++ warning.
+ const char *progname = argv_[0];
+ std::string ProgName(llvm::sys::path::stem(progname));
+ if (llvm::StringRef(ProgName).endswith("++") ||
+ llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
+ TheDriver.CCCIsCXX = true;
+ }
+
+ // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
+ TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
+ if (TheDriver.CCPrintOptions)
+ TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
+
+ // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
+ TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
+ if (TheDriver.CCPrintHeaders)
+ TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
+
+ // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
+ // command line behind the scenes.
+ if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
+ // FIXME: Driver shouldn't take extra initial argument.
+ ApplyQAOverride(argv, OverrideStr, SavedStrings);
+ } else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
+ // FIXME: Driver shouldn't take extra initial argument.
+ std::vector<const char*> ExtraArgs;
+
+ for (;;) {
+ const char *Next = strchr(Cur, ',');
+
+ if (Next) {
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings,
+ std::string(Cur, Next)));
+ Cur = Next + 1;
+ } else {
+ if (*Cur != '\0')
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
+ break;
+ }
+ }
+
+ argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
+ }
+
+ llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(),
+ &argv[0]));
+ int Res = 0;
+ if (C.get())
+ Res = TheDriver.ExecuteCompilation(*C);
+
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now. This happens in -disable-free mode.
+ llvm::TimerGroup::printAll(llvm::errs());
+
+ llvm::llvm_shutdown();
+
+ return Res;
+}
OpenPOWER on IntegriCloud